summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--psprint/inc/psprint/fontmanager.hxx513
-rw-r--r--psprint/inc/psprint/helper.hxx88
-rw-r--r--psprint/inc/psprint/jobdata.hxx116
-rw-r--r--psprint/inc/psprint/ppdparser.hxx336
-rw-r--r--psprint/inc/psprint/printergfx.hxx408
-rw-r--r--psprint/inc/psprint/printerinfomanager.hxx211
-rw-r--r--psprint/inc/psprint/printerjob.hxx161
-rw-r--r--psprint/inc/psprint/strhelper.hxx101
-rw-r--r--psprint/prj/build.lst8
-rw-r--r--psprint/prj/d.lst12
-rw-r--r--psprint/source/fontmanager/adobeenc.tab658
-rw-r--r--psprint/source/fontmanager/fontmanager.cxx2435
-rw-r--r--psprint/source/fontmanager/makefile.mk92
-rw-r--r--psprint/source/fontmanager/parseAFM.cxx1464
-rw-r--r--psprint/source/fontmanager/parseAFM.hxx343
-rw-r--r--psprint/source/fontsubset/crc32.c120
-rw-r--r--psprint/source/fontsubset/crc32.h79
-rw-r--r--psprint/source/fontsubset/gsub.cxx319
-rw-r--r--psprint/source/fontsubset/gsub.h70
-rw-r--r--psprint/source/fontsubset/list.c623
-rw-r--r--psprint/source/fontsubset/list.h135
-rw-r--r--psprint/source/fontsubset/makefile.mk93
-rw-r--r--psprint/source/fontsubset/sft.c3074
-rw-r--r--psprint/source/fontsubset/sft.h649
-rw-r--r--psprint/source/fontsubset/ttcr.c1666
-rw-r--r--psprint/source/fontsubset/ttcr.h311
-rw-r--r--psprint/source/fontsubset/u2big5.inc1788
-rw-r--r--psprint/source/fontsubset/u2johab.inc2206
-rw-r--r--psprint/source/fontsubset/u2prc.inc3068
-rw-r--r--psprint/source/fontsubset/u2shiftjis.inc999
-rw-r--r--psprint/source/fontsubset/u2wansung.inc1103
-rw-r--r--psprint/source/fontsubset/xlat.c218
-rw-r--r--psprint/source/fontsubset/xlat.h99
-rw-r--r--psprint/source/helper/helper.cxx182
-rw-r--r--psprint/source/helper/makefile.mk91
-rw-r--r--psprint/source/helper/ppdparser.cxx1513
-rw-r--r--psprint/source/helper/strhelper.cxx735
-rw-r--r--psprint/source/printer/jobdata.cxx220
-rw-r--r--psprint/source/printer/makefile.mk90
-rw-r--r--psprint/source/printer/printerinfomanager.cxx930
-rw-r--r--psprint/source/printergfx/bitmap_gfx.cxx759
-rw-r--r--psprint/source/printergfx/common_gfx.cxx937
-rw-r--r--psprint/source/printergfx/glyphset.cxx398
-rw-r--r--psprint/source/printergfx/glyphset.hxx137
-rw-r--r--psprint/source/printergfx/makefile.mk96
-rw-r--r--psprint/source/printergfx/printerjob.cxx858
-rw-r--r--psprint/source/printergfx/psputil.cxx300
-rw-r--r--psprint/source/printergfx/psputil.hxx122
-rw-r--r--psprint/source/printergfx/text_gfx.cxx525
-rw-r--r--psprint/util/makefile.mk113
50 files changed, 31572 insertions, 0 deletions
diff --git a/psprint/inc/psprint/fontmanager.hxx b/psprint/inc/psprint/fontmanager.hxx
new file mode 100644
index 000000000000..e454849863fb
--- /dev/null
+++ b/psprint/inc/psprint/fontmanager.hxx
@@ -0,0 +1,513 @@
+/*************************************************************************
+ *
+ * $RCSfile: fontmanager.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:33 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _PSPRINT_FONTMANAGER_HXX_
+#define _PSPRINT_FONTMANAGER_HXX_
+
+#ifndef __SGI_STL_HASH_MAP
+#include <hash_map>
+#endif
+#ifndef __SGI_STL_LIST
+#include <list>
+#endif
+#ifndef _PSPRINT_HELPER_HXX_
+#include <psprint/helper.hxx>
+#endif
+
+#define ATOM_FAMILYNAME 2
+#define ATOM_PSNAME 3
+
+/*
+ * some words on metrics: every length returned by PrintFontManager and
+ * friends are PostScript afm style, that is they are 1/1000 font height
+ */
+
+// forward declarations
+
+namespace utl { class MultiAtomProvider; } // see unotools/atom.hxx
+
+namespace psp {
+class PPDParser; // see ppdparser.hxx
+
+namespace italic
+{
+enum type {
+ Upright = 0,
+ Oblique = 1,
+ Italic = 2,
+ Unknown = 3
+};
+}
+
+namespace width
+{
+enum type {
+ Unknown = 0,
+ UltraCondensed = 1,
+ ExtraCondensed = 2,
+ Condensed = 3,
+ SemiCondensed = 4,
+ Normal = 5,
+ SemiExpanded = 6,
+ Expanded = 7,
+ ExtraExpanded = 8,
+ UltraExpanded = 9
+};
+}
+
+namespace pitch
+{
+enum type {
+ Unknown = 0,
+ Fixed = 1,
+ Variable = 2
+};
+}
+
+namespace weight
+{
+enum type {
+ Unknown = 0,
+ Thin = 1,
+ UltraLight = 2,
+ Light = 3,
+ SemiLight = 4,
+ Normal = 5,
+ Medium = 6,
+ SemiBold = 7,
+ Bold = 8,
+ UltraBold = 9,
+ Black = 10
+};
+}
+
+namespace family
+{
+enum type {
+ Unknown = 0,
+ Decorative = 1,
+ Modern = 2,
+ Roman = 3,
+ Script = 4,
+ Swiss = 5,
+ System = 6
+};
+}
+
+namespace fonttype
+{
+enum type {
+ Unknown = 0,
+ Type1 = 1,
+ TrueType = 2,
+ Builtin = 3
+};
+}
+
+/*
+ * the difference between FastPrintFontInfo and PrintFontInfo
+ * is that the information in FastPrintFontInfo can usually
+ * be gathered without openening either the font file or
+ * an afm metric file. they are gathered from fonts.dir alone.
+ * if only FastPrintFontInfo is gathered and PrintFontInfo
+ * on demand and for less fonts, then performance in startup
+ * increases considerably
+ */
+
+struct FastPrintFontInfo
+{
+ fontID m_nID; // FontID
+ fonttype::type m_eType;
+
+ // font attributes
+ ::rtl::OUString m_aFamilyName;
+ family::type m_eFamilyStyle;
+ italic::type m_eItalic;
+ width::type m_eWidth;
+ weight::type m_eWeight;
+ pitch::type m_ePitch;
+ rtl_TextEncoding m_aEncoding;
+};
+
+struct PrintFontInfo : public FastPrintFontInfo
+{
+ int m_nAscend;
+ int m_nDescend;
+ int m_nLeading;
+ int m_nWidth;
+};
+
+// the values are per thousand of the font size
+// note: width, height contain advances, not bounding box
+struct CharacterMetric
+{
+ short int width, height;
+
+ CharacterMetric() : width( 0 ), height( 0 ) {}
+};
+
+struct KernPair
+{
+ sal_Unicode first, second;
+ short int kern_x, kern_y;
+
+ KernPair() : first( 0 ), second( 0 ), kern_x( 0 ), kern_y( 0 ) {}
+};
+
+// a class to manage printable fonts
+// aims are type1 and truetype fonts
+
+class PrintFontManager
+{
+ struct PrintFont;
+ struct TrueTypeFontFile;
+ struct Type1FontFile;
+ struct BuiltinFont;
+ friend class PrintFont;
+ friend class TrueTypeFontFile;
+ friend class Type1FontFile;
+ friend class BuiltinFont;
+
+ struct PrintFontMetrics
+ {
+ // character metrics are stored by the following keys:
+ // lower two bytes contain a sal_Unicode (a UCS2 character)
+ // upper byte contains: 0 for horizontal metric
+ // 1 for vertical metric
+ // highest byte: 0 for now
+ ::std::hash_map< int, CharacterMetric > m_aMetrics;
+ // contains the unicode blocks for which metrics were queried
+ // this implies that metrics should be queried in terms of
+ // unicode blocks. here a unicode block is identified
+ // by the upper byte of the UCS2 encoding.
+ // note that the corresponding bit should be set even
+ // if the font does not support a single character of that page
+ // this map shows, which pages were queried already
+ // if (like in AFM metrics) all metrics are queried in
+ // a single pass, then all bits should be set
+ char m_aPages[32];
+
+ bool m_bKernPairsQueried;
+ ::std::list< KernPair > m_aXKernPairs;
+ ::std::list< KernPair > m_aYKernPairs;
+
+ PrintFontMetrics() : m_bKernPairsQueried( false ) {}
+ };
+
+ struct PrintFont
+ {
+ fonttype::type m_eType;
+
+ // font attributes
+ int m_nFamilyName; // atom
+ int m_nPSName; // atom
+ italic::type m_eItalic;
+ width::type m_eWidth;
+ weight::type m_eWeight;
+ pitch::type m_ePitch;
+ rtl_TextEncoding m_aEncoding;
+ CharacterMetric m_aGlobalMetricX;
+ CharacterMetric m_aGlobalMetricY;
+ PrintFontMetrics* m_pMetrics;
+ int m_nAscend;
+ int m_nDescend;
+ int m_nLeading;
+
+ PrintFont( fonttype::type eType );
+ virtual ~PrintFont();
+ virtual bool queryMetricPage( int nPage, ::utl::MultiAtomProvider* pProvider ) = 0;
+
+ bool readAfmMetrics( const ::rtl::OString& rFileName, ::utl::MultiAtomProvider* pProvider );
+ };
+
+ struct Type1FontFile : public PrintFont
+ {
+ int m_nDirectory; // atom containing system dependent path
+ ::rtl::OString m_aFontFile; // relative to directory
+ ::rtl::OString m_aMetricFile; // dito
+ ::rtl::OString m_aXLFD; // mainly for administration, contains the XLFD from fonts.dir
+
+ /* note: m_aFontFile and Metric file are not atoms
+ because they should be fairly unique */
+
+ Type1FontFile() : PrintFont( fonttype::Type1 ) {}
+ virtual ~Type1FontFile();
+ virtual bool queryMetricPage( int nPage, ::utl::MultiAtomProvider* pProvider );
+ };
+
+ struct TrueTypeFontFile : public PrintFont
+ {
+ int m_nDirectory; // atom containing system dependent path
+ ::rtl::OString m_aFontFile; // relative to directory
+ ::rtl::OString m_aXLFD; // mainly for administration, contains the XLFD from fonts.dir
+ int m_nCollectionEntry; // -1 for regular fonts, 0 to ... for fonts stemming from collections
+
+ TrueTypeFontFile() : PrintFont( fonttype::TrueType ) {}
+ virtual ~TrueTypeFontFile();
+ virtual bool queryMetricPage( int nPage, ::utl::MultiAtomProvider* pProvider );
+ };
+
+ struct BuiltinFont : public PrintFont
+ {
+ int m_nDirectory; // atom containing system dependent path
+ ::rtl::OString m_aMetricFile;
+
+ BuiltinFont() : PrintFont( fonttype::Builtin ) {}
+ virtual ~BuiltinFont();
+ virtual bool queryMetricPage( int nPage, ::utl::MultiAtomProvider* pProvider );
+ };
+
+ fontID m_nNextFontID;
+ ::std::hash_map< fontID, PrintFont* > m_aFonts;
+ ::std::hash_map< int, family::type > m_aFamilyTypes;
+ ::std::list< ::rtl::OUString > m_aPrinterDrivers;
+ ::std::list< ::rtl::OString > m_aFontDirectories;
+ ::utl::MultiAtomProvider* m_pAtoms;
+
+ ::std::hash_map< ::rtl::OString, int, ::rtl::OStringHash >
+ m_aDirToAtom;
+ ::std::hash_map< int, ::rtl::OString > m_aAtomToDir;
+ int m_nNextDirAtom;
+
+
+ ::rtl::OString getAfmFile( PrintFont* pFont ) const;
+ ::rtl::OString getFontFile( PrintFont* pFont ) const;
+
+ void getFontAttributesFromXLFD( PrintFont* pFont, const ByteString& rXLFD ) const;
+
+ bool analyzeFontFile( int nDirID, const ::rtl::OString& rFileName, bool bReadFile, const ::rtl::OString& rXLFD, ::std::list< PrintFont* >& rNewFonts ) const;
+ bool analyzeTrueTypeFile( PrintFont* pFont ) const;
+ // finds the FIRST id for this font file; there may be more
+ // for TrueType collections
+ fontID findFontFileID( int nDirID, const ::rtl::OString& rFile ) const;
+ fontID findFontBuiltinID( int nPSNameAtom ) const;
+
+ family::type matchFamilyName( const ::rtl::OUString& rFamily ) const;
+
+ PrintFont* getFont( fontID nID ) const
+ {
+ ::std::hash_map< int, PrintFont* >::const_iterator it;
+ it = m_aFonts.find( nID );
+ return it == m_aFonts.end() ? NULL : it->second;
+ }
+ ByteString getXLFD( PrintFont* pFont ) const;
+ void fillPrintFontInfo( PrintFont* pFont, FastPrintFontInfo& rInfo ) const;
+ void fillPrintFontInfo( PrintFont* pFont, PrintFontInfo& rInfo ) const;
+
+ const ::rtl::OString& getDirectory( int nAtom ) const;
+ int getDirectoryAtom( const ::rtl::OString& rDirectory, bool bCreate = false );
+
+ PrintFontManager();
+ ~PrintFontManager();
+public:
+ static PrintFontManager& get(); // one instance only
+
+ int addFontFile( const ::rtl::OString& rFileName, int nFaceNum );
+
+ // initialize takes an X Display*
+ // if NULL then an XOpendDisplay( NULL ) is performed
+ // the Display connection is used to get the font path
+ void initialize( void* pDisplay = NULL );
+
+ // returns the number of managed fonts
+ int getFontCount() const { return m_aFonts.size(); }
+ // returns the ids of all managed fonts. on pParser != NULL
+ // all fonttype::Builtin type fonts are not listed
+ // which do not occur in the PPD of pParser
+ void getFontList( ::std::list< fontID >& rFontIDs, const PPDParser* pParser = NULL ) const;
+ // get the font list and detailed font info. see getFontList for pParser
+ void getFontListWithInfo( ::std::list< PrintFontInfo >& rFonts, const PPDParser* pParser = NULL ) const;
+ // get the font list and fast font info. see getFontList for pParser
+ void getFontListWithFastInfo( ::std::list< FastPrintFontInfo >& rFonts, const PPDParser* pParser = NULL ) const;
+
+ // get font info for a specific font
+ bool getFontInfo( fontID nFontID, PrintFontInfo& rInfo ) const;
+ // get fast font info for a specific font
+ bool getFontFastInfo( fontID nFontID, FastPrintFontInfo& rInfo ) const;
+
+ // routines to get font info in small pieces
+
+ // get a specific fonts family name
+ const ::rtl::OUString& getFontFamily( fontID nFontID ) const;
+ // get a specific fonts PSName name
+ const ::rtl::OUString& getPSName( fontID nFontID ) const;
+
+ // get a specific fonts style family
+ family::type PrintFontManager::getFontFamilyType( fontID nFontID ) const;
+
+ // get a specific fonts type
+ fonttype::type getFontType( fontID nFontID ) const
+ {
+ PrintFont* pFont = getFont( nFontID );
+ return pFont ? pFont->m_eType : fonttype::Unknown;
+ }
+
+ // get a specific fonts italic type
+ italic::type getFontItalic( fontID nFontID ) const
+ {
+ PrintFont* pFont = getFont( nFontID );
+ return pFont ? pFont->m_eItalic : italic::Unknown;
+ }
+
+ // get a specific fonts width type
+ width::type getFontWidth( fontID nFontID ) const
+ {
+ PrintFont* pFont = getFont( nFontID );
+ return pFont ? pFont->m_eWidth : width::Unknown;
+ }
+
+ // get a specific fonts weight type
+ weight::type getFontWeight( fontID nFontID ) const
+ {
+ PrintFont* pFont = getFont( nFontID );
+ return pFont ? pFont->m_eWeight : weight::Unknown;
+ }
+
+ // get a specific fonts pitch type
+ pitch::type getFontPitch( fontID nFontID ) const
+ {
+ PrintFont* pFont = getFont( nFontID );
+ return pFont ? pFont->m_ePitch : pitch::Unknown;
+ }
+
+ // get a specific fonts encoding
+ rtl_TextEncoding getFontEncoding( fontID nFontID ) const
+ {
+ PrintFont* pFont = getFont( nFontID );
+ return pFont ? pFont->m_aEncoding : RTL_TEXTENCODING_DONTKNOW;
+ }
+
+ // get a specific fonts system dependent filename
+ ::rtl::OString getFontFileSysPath( fontID nFontID ) const
+ {
+ return getFontFile( getFont( nFontID ) );
+ }
+
+ // get the ttc face number
+ int getFontFaceNumber( fontID nFontID ) const
+ {
+ int nRet = -1;
+ PrintFont* pFont = getFont( nFontID );
+ if( pFont->m_eType == fonttype::TrueType )
+ nRet = static_cast< TrueTypeFontFile* >(pFont)->m_nCollectionEntry;
+ return nRet;
+ }
+
+ // get a specific fonts global metrics
+ const CharacterMetric& getGlobalFontMetric( fontID nFontID, bool bHorizontal ) const;
+
+ // get a specific fonts ascend
+ int getFontAscend( fontID nFontID ) const;
+
+ // get a specific fonts descent
+ int getFontDescend( fontID nFontID ) const;
+
+ // get a specific fonts leading
+ int getFontLeading( fontID nFontID ) const;
+
+ // get the XLFD for a font that originated from the X fontpath
+ // note: this may not be the original line that was in the fonts.dir
+ // returns a string for every font, but only TrueType and Type1
+ // fonts originated from the X font path, so check for the font type
+ ::rtl::OUString getFontXLFD( fontID nFontID ) const;
+
+ // get a specific fonts metrics
+
+ // get metrics for a sal_Unicode range
+ // the user is responsible to allocate pArray large enough
+ bool getMetrics( fontID nFontID, sal_Unicode minCharacter, sal_Unicode maxCharacter, CharacterMetric* pArray, bool bVertical = false ) const;
+ // get metrics for an array of sal_Unicode characters
+ // the user is responsible to allocate pArray large enough
+ bool getMetrics( fontID nFontID, const sal_Unicode* pString, int nLen, CharacterMetric* pArray, bool bVertical = false ) const;
+
+ // to get font substitution transparently use the
+ // getKernPairs method of PrinterGfx
+ const ::std::list< KernPair >& getKernPairs( fontID nFontID, bool bVertical = false ) const;
+
+ // font administration functions
+
+ // for importFonts to provide the user feedback
+ class ImportFontCallback
+ {
+ public:
+ enum FailCondition { NoWritableDirectory, NoAfmMetric, AfmCopyFailed, FontCopyFailed };
+ virtual void importFontsFailed( FailCondition eReason ) = 0;
+ virtual void progress( const ::rtl::OUString& rFile ) = 0;
+ virtual bool queryOverwriteFile( const ::rtl::OUString& rFile ) = 0;
+ virtual void importFontFailed( const ::rtl::OUString& rFile, FailCondition ) = 0;
+ virtual bool isCanceled() = 0;
+ };
+
+ // checks wether font import would fail due to no writeable directory
+ bool checkImportPossible() const;
+ // expects system paths not UNC paths
+ // returns the number of fonts successfully imported
+ int importFonts( const ::std::list< ::rtl::OUString >& rFiles, ImportFontCallback* pCallback = NULL );
+
+ // check wether changeFontProperties would fail due to not writable fonts.dir
+ bool checkChangeFontPropertiesPossible( fontID nFont ) const;
+ // change fonts.dir entry for font
+ bool changeFontProperties( fontID nFont, const ::rtl::OUString& rXLFD );
+};
+
+} // namespace
+
+#endif // _PSPRINT_FONTMANAGER_HXX_
diff --git a/psprint/inc/psprint/helper.hxx b/psprint/inc/psprint/helper.hxx
new file mode 100644
index 000000000000..99b4cd9e58fa
--- /dev/null
+++ b/psprint/inc/psprint/helper.hxx
@@ -0,0 +1,88 @@
+/*************************************************************************
+ *
+ * $RCSfile: helper.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:33 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _PSPRINT_HELPER_HXX_
+#define _PSPRINT_HELPER_HXX_
+
+#ifndef __SGI_STL_HASH_MAP
+#include <hash_map>
+#endif
+#ifndef _RTL_USTRING_
+#include <rtl/ustring>
+#endif
+
+
+// forwards
+namespace osl { class File; }
+
+#ifndef _RTL_USTRING_
+#include <rtl/ustring>
+#endif
+
+namespace psp {
+typedef int fontID;
+
+const ::rtl::OUString& getPrinterPath();
+
+bool convertPfbToPfa( ::osl::File& rInFile, ::osl::File& rOutFile );
+} // namespace
+
+#endif // _PSPRINT_HELPER_HXX_
diff --git a/psprint/inc/psprint/jobdata.hxx b/psprint/inc/psprint/jobdata.hxx
new file mode 100644
index 000000000000..8e6b6597e118
--- /dev/null
+++ b/psprint/inc/psprint/jobdata.hxx
@@ -0,0 +1,116 @@
+/*************************************************************************
+ *
+ * $RCSfile: jobdata.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:33 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _PSPRINT_JOBDATA_HXX_
+#define _PSPRINT_JOBDATA_HXX_
+
+#ifndef _PSPRINT_PPDPARSER_HXX_
+#include <psprint/ppdparser.hxx>
+#endif
+
+namespace psp {
+
+namespace orientation {
+enum type {
+ Portrait,
+ Landscape
+};
+}
+
+struct JobData
+{
+ int m_nCopies;
+ int m_nScale; // in percent
+ int m_nLeftMarginAdjust;
+ int m_nRightMarginAdjust;
+ int m_nTopMarginAdjust;
+ int m_nBottomMarginAdjust;
+ // user overrides for PPD
+ int m_nColorDepth;
+ int m_nPSLevel; // 0: no override, else languaglevel to use
+ int m_nColorDevice; // 0: no override, -1 grey scale, +1 color
+ orientation::type m_eOrientation;
+ ::rtl::OUString m_aPrinterName;
+ const PPDParser* m_pParser;
+ PPDContext m_aContext;
+
+ JobData() :
+ m_nCopies( 1 ),
+ m_nScale( 100 ),
+ m_nLeftMarginAdjust( 0 ),
+ m_nRightMarginAdjust( 0 ),
+ m_nTopMarginAdjust( 0 ),
+ m_nBottomMarginAdjust( 0 ),
+ m_nColorDepth( 24 ),
+ m_nPSLevel( 0 ),
+ m_nColorDevice( 0 ),
+ m_eOrientation( orientation::Portrait ),
+ m_pParser( NULL ) {}
+
+ // creates a new buffer using new
+ // it is up to the user to delete it again
+ bool getStreamBuffer( void*& pData, int& bytes );
+ static bool constructFromStreamBuffer( void* pData, int bytes, JobData& rJobData );
+};
+
+} // namespace
+
+#endif // PSPRINT_JOBDATA_HXX
diff --git a/psprint/inc/psprint/ppdparser.hxx b/psprint/inc/psprint/ppdparser.hxx
new file mode 100644
index 000000000000..bdee073180d5
--- /dev/null
+++ b/psprint/inc/psprint/ppdparser.hxx
@@ -0,0 +1,336 @@
+/*************************************************************************
+ *
+ * $RCSfile: ppdparser.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:33 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#ifndef _PSPRINT_PPDPARSER_HXX_
+#define _PSPRINT_PPDPARSER_HXX_
+
+#ifndef __SGI_STL_LIST
+#include <list>
+#endif
+#ifndef _PSPRINT_HELPER_HXX_
+#include <psprint/helper.hxx> // hash_map and OUString hash
+#endif
+#ifndef _STRING_HXX
+#include <tools/string.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+
+namespace psp {
+
+class PPDParser;
+
+enum PPDValueType { eInvocation, eQuoted, eSymbol, eString, eNo };
+
+struct PPDValue
+{
+ PPDValueType m_eType;
+ String m_aOption;
+ String m_aOptionTranslation;
+ String m_aValue;
+ String m_aValueTranslation;
+};
+
+// ----------------------------------------------------------------------
+
+/*
+ * PPDKey - a container for the available options (=values) of a PPD keyword
+ */
+
+class PPDKey
+{
+ friend class PPDParser;
+
+ String m_aKey;
+ ::std::hash_map< ::rtl::OUString, PPDValue, ::rtl::OUStringHash >
+ m_aValues;
+ const PPDValue* m_pDefaultValue;
+ bool m_bQueryValue;
+ PPDValue m_aQueryValue;
+
+public:
+ enum UIType { PickOne, PickMany, Boolean };
+ enum SetupType { ExitServer, Prolog, DocumentSetup, PageSetup, JCLSetup, AnySetup };
+private:
+
+ bool m_bUIOption;
+ String m_aUITranslation;
+ UIType m_eUIType;
+ int m_nOrderDependency;
+ SetupType m_eSetupType;
+public:
+ PPDKey( const String& rKey );
+ ~PPDKey();
+
+ PPDValue* insertValue( const String& rOption );
+ int countValues() const
+ { return m_aValues.size(); }
+ // neither getValue will return the query option
+ const PPDValue* getValue( int n ) const;
+ const PPDValue* getValue( const String& rOption ) const;
+ const PPDValue* getDefaultValue() const { return m_pDefaultValue; }
+ const PPDValue* getQueryValue() const { return m_bQueryValue ? &m_aQueryValue : NULL; }
+
+ const String& getKey() const { return m_aKey; }
+ bool isUIKey() const { return m_bUIOption; }
+ const String& getUITranslation() const { return m_aUITranslation; }
+ UIType getUIType() const { return m_eUIType; }
+ SetupType getSetupType() const { return m_eSetupType; }
+ int getOrderDependency() const { return m_nOrderDependency; }
+};
+
+// ----------------------------------------------------------------------
+
+/*
+ * PPDParser - parses a PPD file and contains all available keys from it
+ */
+
+class PPDContext;
+
+class PPDParser
+{
+ friend class PPDContext;
+public:
+ struct PPDConstraint
+ {
+ const PPDKey* m_pKey1;
+ const PPDValue* m_pOption1;
+ const PPDKey* m_pKey2;
+ const PPDValue* m_pOption2;
+
+ PPDConstraint() : m_pKey1( NULL ), m_pOption1( NULL ), m_pKey2( NULL ), m_pOption2( NULL ) {}
+ };
+
+ static ::std::list< PPDParser* > aAllParsers;
+
+ ::std::hash_map< ::rtl::OUString, PPDKey*, ::rtl::OUStringHash >
+ m_aKeys;
+ ::std::list< PPDConstraint > m_aConstraints;
+
+ // some identifying fields
+ String m_aPrinterName;
+ String m_aNickName;
+ // the full path of the PPD file
+ String m_aFile;
+ // some basic attributes
+ bool m_bColorDevice;
+ bool m_bType42Capable;
+ ULONG m_nLanguageLevel;
+
+
+ // shortcuts to important keys and their default values
+ // imageable area
+ const PPDValue* m_pDefaultImageableArea;
+ const PPDKey* m_pImageableAreas;
+ // paper dimensions
+ const PPDValue* m_pDefaultPaperDimension;
+ const PPDKey* m_pPaperDimensions;
+ // paper trays
+ const PPDValue* m_pDefaultInputSlot;
+ const PPDKey* m_pInputSlots;
+ // resolutions
+ const PPDValue* m_pDefaultResolution;
+ const PPDKey* m_pResolutions;
+ // duplex commands
+ const PPDValue* m_pDefaultDuplexType;
+ const PPDKey* m_pDuplexTypes;
+
+ // fonts
+ const PPDKey* m_pFontList;
+
+ PPDParser( const String& rFile );
+ ~PPDParser();
+
+ void parseOrderDependency( const String& rLine );
+ void parseOpenUI( const String& rLine );
+ void parseConstraint( const String& rLine );
+ void parse( ::std::list< String >& rLines );
+public:
+ static const PPDParser* getParser( String aFile );
+ static String getPPDPrinterName( const String& rFile );
+ static void freeAll();
+
+ const String& getFilename() const { return m_aFile; }
+
+ const PPDKey* getKey( int n ) const;
+ const PPDKey* getKey( const String& rKey ) const;
+ int getKeys() const { return m_aKeys.size(); }
+ bool hasKey( const PPDKey* ) const;
+
+ const ::std::list< PPDConstraint >& getConstraints() const { return m_aConstraints; }
+
+ const String& getPrinterName() const
+ { return m_aPrinterName.Len() ? m_aPrinterName : m_aNickName; }
+ const String& getNickName() const
+ { return m_aNickName.Len() ? m_aNickName : m_aPrinterName; }
+
+ bool isColorDevice() const { return m_bColorDevice; }
+ bool isType42Capable() const { return m_bType42Capable; }
+ ULONG getLanguageLevel() const { return m_nLanguageLevel; }
+
+ const String& getDefaultPaperDimension() const;
+ const void getDefaultPaperDimension( int& rWidth, int& rHeight ) const
+ { getPaperDimension( getDefaultPaperDimension(), rWidth, rHeight ); }
+ bool getPaperDimension( const String& rPaperName,
+ int& rWidth, int& rHeight ) const;
+ // width and height in pt
+ // returns false if paper not found
+ int getPaperDimensions() const
+ { return m_pPaperDimensions ? m_pPaperDimensions->countValues() : 0; }
+ const String& getPaperDimension( int ) const;
+ const String& getPaperDimensionCommand( int ) const;
+ const String& getPaperDimensionCommand( const String & ) const;
+
+ // match the best paper for width and height
+ const String& matchPaper( int nWidth, int nHeight ) const;
+
+ bool getMargins( const String& rPaperName,
+ int &rLeft, int& rRight,
+ int &rUpper, int& rLower ) const;
+ // values in pt
+ // returns true if paper found
+
+ // values int pt
+
+ const String& getDefaultInputSlot() const;
+ int getInputSlots() const
+ { return m_pInputSlots ? m_pInputSlots->countValues() : 0; }
+ const String& getSlot( int ) const;
+ const String& getSlotCommand( int ) const;
+ const String& getSlotCommand( const String& ) const;
+
+ void getDefaultResolution( int& rXRes, int& rYRes ) const;
+ int getResolutions() const;
+ void getResolution( int, int& rXRes, int& rYRes ) const;
+ const String& getResolutionCommand( int nXRes, int nYRes ) const;
+ // values in dpi
+ void getResolutionFromString( const String&, int&, int& ) const;
+ // helper function
+
+ const String& getDefaultDuplexType() const;
+ int getDuplexTypes() const
+ { return m_pDuplexTypes ? m_pDuplexTypes->countValues() : 0; }
+ const String& getDuplex( int ) const;
+ const String& getDuplexCommand( int ) const;
+ const String& getDuplexCommand( const String& ) const;
+
+ int getFonts() const
+ { return m_pFontList ? m_pFontList->countValues() : 0; }
+ void getFontAttributes( int,
+ String& rEncoding,
+ String& rCharset ) const;
+ void getFontAttributes( const String&,
+ String& rEncoding,
+ String& rCharset ) const;
+ const String& getFont( int ) const;
+};
+
+// ----------------------------------------------------------------------
+
+/*
+ * PPDContext - a class to manage user definable states based on the
+ * contents of a PPDParser.
+ */
+
+class PPDContext
+{
+ ::std::hash_map< const PPDKey*, const PPDValue* > m_aCurrentValues;
+ const PPDParser* m_pParser;
+
+ // returns false: check failed, new value is constrained
+ // true: check succeded, new value can be set
+ bool checkConstraints( const PPDKey*, const PPDValue*, bool bDoReset );
+ bool resetValue( const PPDKey*, bool bDefaultable = false );
+public:
+ PPDContext( const PPDParser* pParser = NULL );
+ PPDContext( const PPDContext& rContext ) { operator=( rContext ); }
+ PPDContext& operator=( const PPDContext& rContext );
+ ~PPDContext();
+
+ void setParser( const PPDParser* );
+ const PPDParser* getParser() const { return m_pParser; }
+
+ const PPDValue* getValue( const PPDKey* ) const;
+ const PPDValue* setValue( const PPDKey*, const PPDValue*, bool bDontCareForConstraints = false );
+
+ int countValuesModified() const { return m_aCurrentValues.size(); }
+ const PPDKey* getModifiedKey( int n ) const;
+
+ // public wrapper for the private method
+ bool checkConstraints( const PPDKey*, const PPDValue* );
+
+ void getUnconstrainedValues( const PPDKey*, ::std::list< const PPDValue* >& rValues );
+
+ // for printer setup
+ void* getStreamableBuffer( ULONG& rBytes ) const;
+ void rebuildFromStreamBuffer( void* pBuffer, ULONG nBytes );
+
+ // convenience
+ void getResolution( int& rDPIx, int& rDPIy ) const;
+
+ // width, height in points, paper will contain the name of the selected
+ // paper after the call
+ void getPageSize( String& rPaper, int& rWidth, int& rHeight ) const;
+};
+
+} // namespace
+
+#endif // _PSPRINT_PPDPARSER_HXX_
diff --git a/psprint/inc/psprint/printergfx.hxx b/psprint/inc/psprint/printergfx.hxx
new file mode 100644
index 000000000000..286e95be492f
--- /dev/null
+++ b/psprint/inc/psprint/printergfx.hxx
@@ -0,0 +1,408 @@
+/*************************************************************************
+ *
+ * $RCSfile: printergfx.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:33 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _PSPRINT_PRINTERGFX_HXX_
+#define _PSPRINT_PRINTERGFX_HXX_
+
+#ifndef _PSPRINT_HELPER_HXX_
+#include <psprint/helper.hxx>
+#endif
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+#ifndef _SV_GEN_HXX
+#include <tools/gen.hxx>
+#endif
+#ifndef __SGI_STL_LIST
+#include <list>
+#endif
+#ifndef __SGI_STL_HASH_MAP
+#include <hash_map>
+#endif
+
+namespace psp {
+
+// forwards
+class JobData;
+
+/*
+ * lightweight container to handle RGB values
+ */
+
+class PrinterColor
+{
+public:
+
+ typedef enum ColorSpace { eInvalid, eRGB };
+
+private:
+
+ sal_uInt8 mnRed;
+ sal_uInt8 mnGreen;
+ sal_uInt8 mnBlue;
+ ColorSpace meColorspace;
+
+public:
+
+ PrinterColor () :
+ meColorspace(eInvalid)
+ {}
+ PrinterColor (sal_uInt16 nRed, sal_uInt16 nGreen,
+ sal_uInt16 nBlue) :
+ mnRed (nRed),
+ mnGreen (nGreen),
+ mnBlue (nBlue),
+ meColorspace (eRGB)
+ {}
+ PrinterColor (sal_uInt32 nRGB) :
+ meColorspace (eRGB),
+ mnBlue ((nRGB & 0x000000ff) ),
+ mnGreen ((nRGB & 0x0000ff00) >> 8),
+ mnRed ((nRGB & 0x00ff0000) >> 16)
+ {}
+ ~PrinterColor ()
+ {}
+
+ sal_Bool Is () const
+ { return meColorspace != eInvalid; }
+
+ ColorSpace GetColorSpace () const
+ { return meColorspace; }
+ sal_uInt16 GetRed () const
+ { return mnRed; }
+ sal_uInt16 GetGreen () const
+ { return mnGreen; }
+ sal_uInt16 GetBlue () const
+ { return mnBlue; }
+ sal_Bool operator== (const PrinterColor& aColor) const
+ {
+ return aColor.Is() && this->Is()
+ && mnRed == aColor.mnRed
+ && mnGreen == aColor.mnGreen
+ && mnBlue == aColor.mnBlue;
+ }
+ PrinterColor& operator= (const PrinterColor& aColor)
+ {
+ meColorspace = aColor.meColorspace;
+ mnRed = aColor.mnRed;
+ mnGreen = aColor.mnGreen;
+ mnBlue = aColor.mnBlue;
+
+ return *this;
+ }
+
+ PrinterColor& operator= (sal_uInt32 nRGB)
+ {
+ meColorspace = eRGB;
+ mnBlue = (nRGB & 0x000000ff);
+ mnGreen = (nRGB & 0x0000ff00) >> 8;
+ mnRed = (nRGB & 0x00ff0000) >> 16;
+
+ return *this;
+ }
+};
+
+/*
+ * forward declarations
+ */
+
+class GlyphSet;
+class PrinterJob;
+class PrintFontManager;
+class KernPair;
+struct CharacterMetric;
+
+/*
+ * Bitmap Interface, this has to be filled with your actual bitmap implementation
+ * sample implementations can be found in:
+ * psprint/workben/cui/pspdem.cxx
+ * vcl/unx/source/gdi/salgdi2.cxx
+ */
+
+class PrinterBmp
+{
+public:
+
+ virtual ~PrinterBmp () = 0;
+ virtual sal_uInt32 GetPaletteColor (sal_uInt32 nIdx) const = 0;
+ virtual sal_uInt32 GetPaletteEntryCount () const = 0;
+ virtual sal_uInt32 GetPixelRGB (sal_uInt32 nRow, sal_uInt32 nColumn) const = 0;
+ virtual sal_uInt8 GetPixelGray (sal_uInt32 nRow, sal_uInt32 nColumn) const = 0;
+ virtual sal_uInt8 GetPixelIdx (sal_uInt32 nRow, sal_uInt32 nColumn) const = 0;
+ virtual sal_uInt32 GetWidth () const = 0;
+ virtual sal_uInt32 GetHeight () const = 0;
+ virtual sal_uInt32 GetDepth () const = 0;
+};
+
+/*
+ * printer raster operations
+ */
+
+class PrinterGfx
+{
+private:
+
+ /* common settings */
+
+ double mfScaleX;
+ double mfScaleY;
+
+ sal_uInt32 mnDpiX;
+ sal_uInt32 mnDpiY;
+ sal_uInt16 mnDepth;
+
+ sal_uInt16 mnPSLevel;
+ sal_Bool mbColor;
+ sal_Bool mbUploadPS42Fonts;
+
+ osl::File* mpPageHeader;
+ osl::File* mpPageBody;
+
+ void TranslateCoordinates (sal_Int32 &rXOut, sal_Int32 &rYOut,
+ sal_Int32 nXIn, sal_Int32 nYIn )
+ { rXOut = nXIn; rYOut = nYIn; }
+ void TranslateCoordinates (Point& rOut, const Point& rIn)
+ { rOut = rIn; }
+
+ /* text/font related data, for a type1 font it has to be checked
+ whether this font has already been downloaded. A TrueType font
+ will be converted into one or more Type3 fonts, containing glyphs
+ in no particular order. In addition to the existence of the
+ glyph in one of the subfonts, the mapping from unicode to the
+ glyph has to be remembered */
+
+ std::list< sal_Int32 > maPS1Font;
+ std::list< GlyphSet > maPS3Font;
+
+ sal_Int32 mnFontID;
+ sal_Int32 mnFallbackID;
+ sal_Int32 mnTextHeight;
+ sal_Int32 mnTextWidth;
+ sal_Int32 mnTextAngle;
+ bool mbTextVertical;
+ rtl::OString maCurrentFont;
+ PrintFontManager& mrFontMgr;
+
+ /* bitmap drawing implementation */
+
+ sal_Bool mbCompressBmp;
+
+ void DrawPS1GrayImage (const PrinterBmp& rBitmap, const Rectangle& rArea);
+ void DrawPS2GrayImage (const PrinterBmp& rBitmap, const Rectangle& rArea);
+ void DrawPS2PaletteImage (const PrinterBmp& rBitmap, const Rectangle& rArea);
+ void DrawPS2TrueColorImage (const PrinterBmp& rBitmap, const Rectangle& rArea);
+
+ /* clip region */
+
+ std::list< Rectangle > maClipRegion;
+ sal_Bool JoinVerticalClipRectangles( std::list< Rectangle >::iterator& it,
+ Point& aOldPoint, sal_Int32& nColumn );
+
+ /* color settings */
+
+ sal_Bool mbCurrentColorValid;
+ PrinterColor maCurrentColor;
+
+ sal_Bool mbCurrentLineWidthValid;
+ double mfLineWidth;
+
+ PrinterColor maFillColor;
+ PrinterColor maTextColor;
+ PrinterColor maLineColor;
+
+ /* font / font substitution */
+ const ::std::hash_map< fontID, fontID >* mpFontSubstitutes;
+ int getCharWidth (sal_Bool b_vert, sal_Unicode n_char,
+ CharacterMetric *p_bbox);
+ fontID getCharMetric (fontID p_font[3], sal_Unicode n_char,
+ CharacterMetric *p_bbox);
+ fontID getFontSubstitute ();
+
+public:
+
+ enum pspath_t { moveto = 0, lineto = 1 };
+ void PSBinLineTo (const Point& rCurrent, Point& rOld,
+ sal_Int32& nColumn);
+ void PSBinMoveTo (const Point& rCurrent, Point& rOld,
+ sal_Int32& nColumn);
+ void PSBinStartPath ();
+ void PSBinEndPath ();
+ void PSBinCurrentPath (sal_uInt32 nPoints, const Point* pPath);
+ void PSBinPath (const Point& rCurrent, Point& rOld,
+ pspath_t eType, sal_Int32& nColumn);
+
+ void PSSetColor (const PrinterColor& rColor);
+ void PSSetLineWidth ();
+
+ void PSUploadPS1Font (sal_Int32 nFontID);
+ void PSSetFont (rtl::OString& rName,
+ rtl_TextEncoding nEncoding = RTL_TEXTENCODING_DONTKNOW);
+ void PSRotate (sal_Int32 nAngle);
+ void PSTranslate (const Point& rPoint);
+ void PSMoveTo (const Point& rPoint);
+ void PSRMoveTo (sal_Int32 nDx, sal_Int32 nDy = 0);
+ void PSScale (double fScaleX, double fScaleY);
+ void PSLineTo(const Point& rPoint );
+ void PSPointOp (const Point& rPoint, const sal_Char* pOperator);
+ void PSHexString (const sal_uChar* pString, sal_Int16 nLen);
+ void PSDeltaArray (const sal_Int32 *pArray, sal_Int16 nEntries);
+ void PSShowText (const sal_uChar* pString,
+ sal_Int16 nGlyphs, sal_Int16 nBytes,
+ const sal_Int32* pDeltaArray = NULL);
+ void PSGSave ();
+ void PSGRestore ();
+
+ void OnEndPage ();
+ PrintFontManager& GetFontMgr ();
+
+ void drawVerticalizedText (const Point& rPoint,
+ const sal_Unicode* pStr,
+ sal_Int16 nLen,
+ const sal_Int32* pDeltaArray );
+ void drawText (const Point& rPoint,
+ const sal_Unicode* pStr, sal_Int16 nLen,
+ const sal_Int32* pDeltaArray = NULL);
+public:
+ PrinterGfx();
+ ~PrinterGfx();
+ sal_Bool Init (PrinterJob &rPrinterSpec);
+ sal_Bool Init (const JobData& rData);
+ void Clear();
+
+ // query depth and size
+ void GetResolution (sal_Int32 &rDpiX, sal_Int32 &rDpiY) const;
+ void GetScreenFontResolution (sal_Int32 &rDpiX, sal_Int32 &rDpiY) const;
+ sal_uInt16 GetBitCount ();
+
+ // clip region
+ void ResetClipRegion ();
+ void BeginSetClipRegion (sal_uInt32);
+ sal_Bool UnionClipRegion (sal_Int32 nX, sal_Int32 nY,
+ sal_Int32 nDX, sal_Int32 nDY);
+ void EndSetClipRegion ();
+
+ // set xy color
+ void SetLineColor (const PrinterColor& rLineColor = PrinterColor())
+ { maLineColor = rLineColor; }
+ void SetFillColor (const PrinterColor& rFillColor = PrinterColor())
+ { maFillColor = rFillColor; }
+
+ // drawing primitives
+ void DrawPixel (const Point& rPoint, const PrinterColor& rPixelColor);
+ void DrawPixel (const Point& rPoint)
+ { DrawPixel (rPoint, maLineColor); }
+ void DrawLine (const Point& rFrom, const Point& rTo);
+ void DrawRect (const Rectangle& rRectangle);
+ void DrawPolyLine (sal_uInt32 nPoints, const Point* pPath );
+ void DrawPolygon (sal_uInt32 nPoints, const Point* pPath);
+ void DrawPolyPolygon (sal_uInt32 nPoly,
+ const sal_uInt32 *pPolygonSize,
+ const Point** pPolygonList);
+
+ // eps
+ sal_Bool DrawEPS ( const Rectangle& rBoundingBox, void* pPtr, sal_uInt32 nSize);
+
+ // image drawing
+ void DrawBitmap (const Rectangle& rDest, const Rectangle& rSrc,
+ const PrinterBmp& rBitmap);
+ void DrawBitmap (const Rectangle& rDest, const Rectangle& rSrc,
+ const PrinterBmp& rBitmap,
+ const PrinterBmp& rTransBitmap);
+ void DrawMask (const Rectangle& rDest, const Rectangle& rSrc,
+ const PrinterBmp &rBitmap, PrinterColor& rMaskColor);
+
+ // font and text handling
+ sal_uInt16 SetFont (
+ sal_Int32 nFontID,
+ sal_Int32 nPointHeight,
+ sal_Int32 nPointWidth,
+ sal_Int32 nAngle,
+ bool bVertical
+ );
+ sal_uInt16 SetFallbackFont ( sal_Int32 nFontID );
+ sal_Int32 GetFontAngle () const
+ { return mnTextAngle; }
+ sal_Int32 GetFontID () const
+ { return mnFontID; }
+ sal_Int32 GetFontHeight () const
+ { return mnTextHeight; }
+ sal_Int32 GetFontWidth () const
+ { return mnTextWidth; }
+ void DrawText (const Point& rPoint,
+ const sal_Unicode* pStr, sal_Int16 nLen,
+ const sal_Int32* pDeltaArray = NULL);
+ void SetTextColor (PrinterColor& rTextColor)
+ { maTextColor = rTextColor; }
+ sal_Int32 GetCharWidth (sal_uInt16 nFrom, sal_uInt16 nTo,
+ long *pWidthArray);
+ const ::std::list< KernPair >& getKernPairs( bool bVertical = false ) const;
+ // advanced font handling
+ sal_Bool GetGlyphBoundRect (sal_Unicode c, Rectangle& rOutRect);
+ sal_uInt32 GetGlyphOutline (sal_Unicode c,
+ sal_uInt16 **ppPolySizes, Point **ppPoints,
+ sal_uInt8 **ppFlags);
+};
+
+} /* namespace psp */
+
+
+#endif /* _PSPRINT_PRINTERGFX_HXX_ */
+
diff --git a/psprint/inc/psprint/printerinfomanager.hxx b/psprint/inc/psprint/printerinfomanager.hxx
new file mode 100644
index 000000000000..2e8d473a3218
--- /dev/null
+++ b/psprint/inc/psprint/printerinfomanager.hxx
@@ -0,0 +1,211 @@
+/*************************************************************************
+ *
+ * $RCSfile: printerinfomanager.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:32 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _PSPRINT_PRINTERINFOMANAGER_HXX_
+#define _PSPRINT_PRINTERINFOMANAGER_HXX_
+
+#ifndef __SGI_STL_HASH_MAP
+#include <hash_map>
+#endif
+#ifndef __SGI_STL_LIST
+#include <list>
+#endif
+#ifndef _PSPRINT_HELPER_HXX_
+#include <psprint/helper.hxx>
+#endif
+#ifndef _PSPRINT_JOBDATA_HXX_
+#include <psprint/jobdata.hxx>
+#endif
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+#ifndef _PSPRINT_HELPER_HXX_
+#include <psprint/helper.hxx>
+#endif
+
+namespace psp
+{
+struct PrinterInfo : JobData
+{
+ // basename of PPD
+ ::rtl::OUString m_aDriverName;
+ // can be the queue
+ ::rtl::OUString m_aLocation;
+ // a user defined comment
+ ::rtl::OUString m_aComment;
+ // a command line to pipe a PS-file to
+ ::rtl::OUString m_aCommand;
+ // a list of special features separated by ',' not used by psprint
+ // but assigned from the outside (currently only for "fax")
+ ::rtl::OUString m_aFeatures;
+ // a mapping of fonts to other fonts.
+ // this provides a method for the user
+ // to replace arbitrary fonts by printer builtin fonts
+ // currently this is only a mapping between font names
+ // assuming that only adbobe standard encoding fonts are
+ // built into the printer. in future it may be necessary
+ // to map to a font name and UCS2 vector which should be mapped
+ // this vector is currently implicitly given by the adobe
+ // standard encoding
+ bool m_bPerformFontSubstitution;
+ ::std::hash_map< ::rtl::OUString, ::rtl::OUString, ::rtl::OUStringHash >
+ m_aFontSubstitutes;
+ ::std::hash_map< fontID, fontID >
+ m_aFontSubstitutions;
+};
+
+class PrinterInfoManager
+{
+ // needed for checkPrintersChanged: files (not necessarily existant)
+ // and their last known modification time
+ struct WatchFile
+ {
+ // the file in question
+ ::rtl::OUString m_aFilePath;
+ // the last know modification time or 0, if file did not exist
+ TimeValue m_aModified;
+ };
+
+ // internal data to describe a printer
+ struct Printer
+ {
+ // configuration file containing this printer
+ // empty means a freshly added printer that has to be saved yet
+ ::rtl::OUString m_aFile;
+ // group in m_aFile containing the printer
+ // this must be unique over all configuration files
+ // it usually should be the printer name
+ ::rtl::OString m_aGroup;
+ // wether changes need to be saved
+ bool m_bModified;
+ // the corresponding info and job data
+ PrinterInfo m_aInfo;
+ };
+
+ ::std::hash_map< ::rtl::OUString, Printer, ::rtl::OUStringHash > m_aPrinters;
+ PrinterInfo m_aGlobalDefaults;
+ ::std::list< WatchFile > m_aWatchFiles;
+ ::rtl::OUString m_aDefaultPrinter;
+ ::rtl::OUString m_aSystemPrintCommand;
+ ::std::list< ::rtl::OUString > m_aSystemPrintQueues;
+
+ PrinterInfoManager();
+ ~PrinterInfoManager();
+
+ void initialize();
+
+ // fill in font substitutions
+ // the resulting hash_map maps from source to target font ids
+ void fillFontSubstitutions( PrinterInfo& rInfo ) const;
+public:
+
+ // there can only be one
+ static PrinterInfoManager& get();
+
+ // lists the names of all known printers
+ void listPrinters( ::std::list< ::rtl::OUString >& rList ) const;
+
+ // gets the number of known printers
+ int countPrinters() const { return m_aPrinters.size(); }
+
+ // gets info about a named printer
+ const PrinterInfo& getPrinterInfo( const ::rtl::OUString& rPrinter ) const;
+
+ // gets the name of the default printer
+ const ::rtl::OUString& getDefaultPrinter() const { return m_aDefaultPrinter; }
+
+ // changes the info about a named printer
+ void changePrinterInfo( const ::rtl::OUString& rPrinter, const PrinterInfo& rNewInfo );
+
+ // check if the printer configuration has changed
+ bool checkPrintersChanged();
+
+ // members for administration (->padmin)
+
+ // add a named printer
+ // addPrinter fails if a printer with the same name already exists
+ // or the driver does not exist
+ bool addPrinter( const ::rtl::OUString& rPrinterName, const ::rtl::OUString& rDriverName );
+
+ // remove a namend printer
+ // this fails if the config file belonging to this printer
+ // is not writeable
+ bool removePrinter( const ::rtl::OUString& rPrinterName );
+
+ // save the changes to all printers. this fails if there
+ // is no writable config file at all
+ bool writePrinterConfig();
+
+ // set a new default printer
+ // fails if the specified printer does not exist
+ bool setDefaultPrinter( const ::rtl::OUString& rPrinterName );
+
+ // primarily used internally but also by padmin
+ // returns the printer queue names
+ const ::std::list< ::rtl::OUString >& getSystemPrintQueues();
+
+ // similar but returnse whole commandlines
+ void getSystemPrintCommands( ::std::list< ::rtl::OUString >& rCommands );
+};
+
+} // namespace
+
+#endif // _PSPRINT_PRINTERINFOMANAGER_HXX_
diff --git a/psprint/inc/psprint/printerjob.hxx b/psprint/inc/psprint/printerjob.hxx
new file mode 100644
index 000000000000..9191b5be7dd0
--- /dev/null
+++ b/psprint/inc/psprint/printerjob.hxx
@@ -0,0 +1,161 @@
+/*************************************************************************
+ *
+ * $RCSfile: printerjob.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:33 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _PSPRINT_PRINTERJOB_HXX_
+#define _PSPRINT_PRINTERJOB_HXX_
+
+#ifndef __SGI_STL_LIST
+#include <list>
+#endif
+#ifndef _PSPRINT_JOBDATA_HXX_
+#include <psprint/jobdata.hxx>
+#endif
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+#ifndef _RTL_STRING_HXX_
+#include <rtl/string.hxx>
+#endif
+
+// forward declarations
+class SalGraphics;
+
+namespace psp {
+
+
+class PrinterJob
+{
+private: // private data
+
+ rtl::OUString maSpoolDirName;
+ rtl::OUString maFileName; // empty: spool to command, else spool to named file
+
+ osl::File* mpJobHeader;
+ osl::File* mpJobTrailer;
+
+ std::list< osl::File* > maPageList;
+ std::list< osl::File* > maHeaderList;
+
+ JobData m_aLastJobData;
+
+ sal_uInt32 mnResX;
+ sal_uInt32 mnResY;
+
+ sal_uInt32 mnWidthPt;
+ sal_uInt32 mnHeightPt;
+
+ sal_uInt32 mnLMarginPt;
+ sal_uInt32 mnRMarginPt;
+ sal_uInt32 mnTMarginPt;
+ sal_uInt32 mnBMarginPt;
+
+ double mfXScale;
+ double mfYScale;
+
+ sal_Int32 mnErrorCode;
+
+private: // private methods
+
+ osl::File* CreateSpoolFile (const rtl::OUString& rName,
+ const rtl::OUString& rExtension);
+ void InitPaperSize (const JobData& rJobSetup);
+
+ bool writeSetup( osl::File* pFile, const JobData& );
+ bool writePageSetup( osl::File* pFile, const JobData& );
+ bool writeProlog (osl::File* pFile);
+
+public: // for usage in PrinterGfx
+
+ void GetResolution (sal_uInt32 &rDpiX, sal_uInt32 &rDpiY) const;
+ void GetScale (double &rXScale, double &rYScale) const;
+ sal_uInt16 GetDepth () const;
+ sal_uInt16 GetPostscriptLevel (const JobData *pJobData = NULL) const;
+ sal_Bool IsColorPrinter () const;
+
+ osl::File* GetDocumentHeader ();
+ osl::File* GetDocumentTrailer ();
+ osl::File* GetCurrentPageHeader ();
+ osl::File* GetCurrentPageBody ();
+
+ const ::rtl::OUString& GetPrinterName() const { return m_aLastJobData.m_aPrinterName; }
+
+public:
+ PrinterJob ();
+ ~PrinterJob ();
+
+ sal_Bool StartJob (const rtl::OUString& rFileName,
+ const rtl::OUString& rJobName,
+ const rtl::OUString& rAppName,
+ const JobData& rSetupData);
+ sal_Bool EndJob ();
+
+ sal_Bool AbortJob ();
+
+ SalGraphics* StartPage (const JobData& rJobSetup, sal_Bool bNewJobData);
+ sal_Bool EndPage ();
+
+ sal_uInt32 GetErrorCode ();
+};
+
+} /* namespace psp */
+
+#endif /* _PSPRINT_PRINTERJOB_HXX_ */
+
diff --git a/psprint/inc/psprint/strhelper.hxx b/psprint/inc/psprint/strhelper.hxx
new file mode 100644
index 000000000000..b4f9a4523677
--- /dev/null
+++ b/psprint/inc/psprint/strhelper.hxx
@@ -0,0 +1,101 @@
+/*************************************************************************
+ *
+ * $RCSfile: strhelper.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:33 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+#ifndef _PSPRINT_STRHELPER_HXX_
+#define _PSPRINT_STRHELPER_HXX_
+
+#ifndef _STRING_HXX
+#include <tools/string.hxx>
+#endif
+
+namespace psp {
+
+String GetCommandLineToken( int, const String& );
+ByteString GetCommandLineToken( int, const ByteString& );
+// gets one token of a unix command line style string
+// doublequote, singlequote and singleleftquote protect their respective
+// contents
+
+int GetCommandLineTokenCount( const String& );
+int GetCommandLineTokenCount( const ByteString& );
+// returns number of tokens (zero if empty or whitespace only)
+
+String WhitespaceToSpace( const String&, BOOL bProtect = TRUE );
+ByteString WhitespaceToSpace( const ByteString&, BOOL bProtect = TRUE );
+// returns a string with multiple adjacent occurences of whitespace
+// converted to a single space. if bProtect is TRUE (nonzero), then
+// doublequote, singlequote and singleleftquote protect their respective
+// contents
+
+double StringToDouble( const String& rStr );
+double StringToDouble( const ByteString& rStr );
+// parses the first double in the string; decimal is '.' only
+
+// fills a character buffer with the string representation of a double
+// the buffer has to be long enough (e.g. 128 bytes)
+// returns the string len
+int getValueOfDouble( char* pBuffer, double f, int nPrecision = 0 );
+// corresponding convenience functions
+ByteString DoubleToByteString( double f, int nPrecision = 0 );
+String DoubleToString( double f, int nPrecision = 0 );
+
+} // namespace
+
+#endif // _PSPRINT_STRHELPER_HXX_
diff --git a/psprint/prj/build.lst b/psprint/prj/build.lst
new file mode 100644
index 000000000000..f95e2a2600c5
--- /dev/null
+++ b/psprint/prj/build.lst
@@ -0,0 +1,8 @@
+pp psprint : tools unotools NULL
+pp psprint usr1 - all pp_mkout NULL
+pp psprint\source\fontsubset nmake - u pp_fontsset NULL
+pp psprint\source\printer nmake - u pp_printer NULL
+pp psprint\source\fontmanager nmake - u pp_fontmgr NULL
+pp psprint\source\helper nmake - u pp_helper NULL
+pp psprint\source\printergfx nmake - u pp_printergfx NULL
+pp psprint\util nmake - u pp_util pp_fontmgr pp_fontsset pp_helper pp_printer pp_printergfx NULL
diff --git a/psprint/prj/d.lst b/psprint/prj/d.lst
new file mode 100644
index 000000000000..cfe51cb4419b
--- /dev/null
+++ b/psprint/prj/d.lst
@@ -0,0 +1,12 @@
+mkdir: %_DEST%\inc%_EXT%\psprint
+
+..\%__SRC%\lib\*.so %_DEST%\lib%_EXT%\*.so
+
+..\inc\psprint\*.hxx %_DEST%\inc%_EXT%\psprint\*.hxx
+
+..\%__SRC%\lib\lib*static*.dylib %_DEST%\lib%_EXT%\lib*static*.dylib
+..\%__SRC%\misc\*staticdatamembers.cxx %_DEST%\inc%_EXT%\*staticdatamembers.cxx
+..\%__SRC%\misc\*staticdatamembers.h* %_DEST%\inc%_EXT%\*staticdatamembers.h*
+
+dos: sh -c "if test %OS% = MACOSX; then create-bundle %_DEST%\lib%_EXT%\*.dylib; fi"
+dos: sh -c "if test %OS% = MACOSX; then create-libstatic-link %_DEST%\lib%_EXT%; fi"
diff --git a/psprint/source/fontmanager/adobeenc.tab b/psprint/source/fontmanager/adobeenc.tab
new file mode 100644
index 000000000000..d03f92573a45
--- /dev/null
+++ b/psprint/source/fontmanager/adobeenc.tab
@@ -0,0 +1,658 @@
+/*************************************************************************
+ *
+ * $RCSfile: adobeenc.tab,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:34 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+struct AdobeConvEntry
+{
+ sal_Unicode aUnicode;
+ sal_uInt8 aAdobecode;
+ const char* pAdobename;
+};
+
+static AdobeConvEntry aAdobeStandardNoneCodes[] =
+{
+ { 0x00A6, 0, "brokenbar" },
+ { 0x00A9, 0, "copyright" },
+ { 0x00AC, 0, "logicalnot" },
+ { 0x00AE, 0, "registered" },
+ { 0x00B1, 0, "plusminus" },
+ { 0x00B2, 0, "twosuperior" },
+ { 0x00B3, 0, "threesuperior" },
+ { 0x00B5, 0, "mu" },
+ { 0x00B9, 0, "onesuperior" },
+ { 0x00BC, 0, "onequarter" },
+ { 0x00BD, 0, "onehalf" },
+ { 0x00BE, 0, "threequarters" },
+ { 0x00C0, 0, "Agrave" },
+ { 0x00C1, 0, "Aacute" },
+ { 0x00C2, 0, "Acircumflex" },
+ { 0x00C3, 0, "Atilde" },
+ { 0x00C4, 0, "Adieresis" },
+ { 0x00C5, 0, "Aring" },
+ { 0x00C7, 0, "Ccedilla" },
+ { 0x00C8, 0, "Egrave" },
+ { 0x00C9, 0, "Eacute" },
+ { 0x00CA, 0, "Ecircumflex" },
+ { 0x00CB, 0, "Edieresis" },
+ { 0x00CC, 0, "Igrave" },
+ { 0x00CD, 0, "Iacute" },
+ { 0x00CE, 0, "Icircumflex" },
+ { 0x00CF, 0, "Idieresis" },
+ { 0x00D0, 0, "Eth" },
+ { 0x00D1, 0, "Ntilde" },
+ { 0x00D2, 0, "Ograve" },
+ { 0x00D3, 0, "Oacute" },
+ { 0x00D4, 0, "Ocircumflex" },
+ { 0x00D5, 0, "Otilde" },
+ { 0x00D6, 0, "Odieresis" },
+ { 0x00D7, 0, "multiply" },
+ { 0x00D9, 0, "Ugrave" },
+ { 0x00DA, 0, "Uacute" },
+ { 0x00DB, 0, "Ucircumflex" },
+ { 0x00DC, 0, "Udieresis" },
+ { 0x00DD, 0, "Yacute" },
+ { 0x00DE, 0, "Thorn" },
+ { 0x00E0, 0, "agrave" },
+ { 0x00E1, 0, "aacute" },
+ { 0x00E2, 0, "acircumflex" },
+ { 0x00E3, 0, "atilde" },
+ { 0x00E4, 0, "adieresis" },
+ { 0x00E5, 0, "aring" },
+ { 0x00E7, 0, "ccedilla" },
+ { 0x00E8, 0, "egrave" },
+ { 0x00E9, 0, "eacute" },
+ { 0x00EA, 0, "ecircumflex" },
+ { 0x00EB, 0, "edieresis" },
+ { 0x00EC, 0, "igrave" },
+ { 0x00ED, 0, "iacute" },
+ { 0x00EE, 0, "icircumflex" },
+ { 0x00EF, 0, "idieresis" },
+ { 0x00F0, 0, "eth" },
+ { 0x00F1, 0, "ntilde" },
+ { 0x00F2, 0, "ograve" },
+ { 0x00F3, 0, "oacute" },
+ { 0x00F4, 0, "ocircumflex" },
+ { 0x00F5, 0, "otilde" },
+ { 0x00F6, 0, "odieresis" },
+ { 0x00F7, 0, "divide" },
+ { 0x00F9, 0, "ugrave" },
+ { 0x00FA, 0, "uacute" },
+ { 0x00FB, 0, "ucircumflex" },
+ { 0x00FC, 0, "udieresis" },
+ { 0x00FD, 0, "yacute" },
+ { 0x00FE, 0, "thorn" },
+ { 0x00FF, 0, "ydieresis" }
+};
+
+
+static const AdobeConvEntry aAdobeStandardConvTable[] =
+{
+ { 0x0020, 0x20, "space" },
+ { 0x0021, 0x21, "exclam" },
+ { 0x0022, 0x22, "quotedbl" },
+ { 0x0023, 0x23, "numbersign" },
+ { 0x0024, 0x24, "dollar" },
+ { 0x0025, 0x25, "percent" },
+ { 0x0026, 0x26, "ampersand" },
+ { 0x0027, 0xA9, "quotesingle" },
+ { 0x0028, 0x28, "parenleft" },
+ { 0x0029, 0x29, "parenright" },
+ { 0x002A, 0x2A, "asterisk" },
+ { 0x002B, 0x2B, "plus" },
+ { 0x002C, 0x2C, "comma" },
+ { 0x002D, 0x2D, "hyphen" },
+ { 0x002E, 0x2E, "period" },
+ { 0x002F, 0x2F, "slash" },
+ { 0x0030, 0x30, "zero" },
+ { 0x0031, 0x31, "one" },
+ { 0x0032, 0x32, "two" },
+ { 0x0033, 0x33, "three" },
+ { 0x0034, 0x34, "four" },
+ { 0x0035, 0x35, "five" },
+ { 0x0036, 0x36, "six" },
+ { 0x0037, 0x37, "seven" },
+ { 0x0038, 0x38, "eight" },
+ { 0x0039, 0x39, "nine" },
+ { 0x003A, 0x3A, "colon" },
+ { 0x003B, 0x3B, "semicolon" },
+ { 0x003C, 0x3C, "less" },
+ { 0x003D, 0x3D, "equal" },
+ { 0x003E, 0x3E, "greater" },
+ { 0x003F, 0x3F, "question" },
+ { 0x0040, 0x40, "at" },
+ { 0x0041, 0x41, "A" },
+ { 0x0042, 0x42, "B" },
+ { 0x0043, 0x43, "C" },
+ { 0x0044, 0x44, "D" },
+ { 0x0045, 0x45, "E" },
+ { 0x0046, 0x46, "F" },
+ { 0x0047, 0x47, "G" },
+ { 0x0048, 0x48, "H" },
+ { 0x0049, 0x49, "I" },
+ { 0x004A, 0x4A, "J" },
+ { 0x004B, 0x4B, "K" },
+ { 0x004C, 0x4C, "L" },
+ { 0x004D, 0x4D, "M" },
+ { 0x004E, 0x4E, "N" },
+ { 0x004F, 0x4F, "O" },
+ { 0x0050, 0x50, "P" },
+ { 0x0051, 0x51, "Q" },
+ { 0x0052, 0x52, "R" },
+ { 0x0053, 0x53, "S" },
+ { 0x0054, 0x54, "T" },
+ { 0x0055, 0x55, "U" },
+ { 0x0056, 0x56, "V" },
+ { 0x0057, 0x57, "W" },
+ { 0x0058, 0x58, "X" },
+ { 0x0059, 0x59, "Y" },
+ { 0x005A, 0x5A, "Z" },
+ { 0x005B, 0x5B, "bracketleft" },
+ { 0x005C, 0x5C, "backslash" },
+ { 0x005D, 0x5D, "bracketright" },
+ { 0x005E, 0x5E, "asciicircum" },
+ { 0x005F, 0x5F, "underscore" },
+ { 0x0060, 0xC1, "grave" },
+ { 0x0061, 0x61, "a" },
+ { 0x0062, 0x62, "b" },
+ { 0x0063, 0x63, "c" },
+ { 0x0064, 0x64, "d" },
+ { 0x0065, 0x65, "e" },
+ { 0x0066, 0x66, "f" },
+ { 0x0067, 0x67, "g" },
+ { 0x0068, 0x68, "h" },
+ { 0x0069, 0x69, "i" },
+ { 0x006A, 0x6A, "j" },
+ { 0x006B, 0x6B, "k" },
+ { 0x006C, 0x6C, "l" },
+ { 0x006D, 0x6D, "m" },
+ { 0x006E, 0x6E, "n" },
+ { 0x006F, 0x6F, "o" },
+ { 0x0070, 0x70, "p" },
+ { 0x0071, 0x71, "q" },
+ { 0x0072, 0x72, "r" },
+ { 0x0073, 0x73, "s" },
+ { 0x0074, 0x74, "t" },
+ { 0x0075, 0x75, "u" },
+ { 0x0076, 0x76, "v" },
+ { 0x0077, 0x77, "w" },
+ { 0x0078, 0x78, "x" },
+ { 0x0079, 0x79, "y" },
+ { 0x007A, 0x7A, "z" },
+ { 0x007B, 0x7B, "braceleft" },
+ { 0x007C, 0x7C, "bar" },
+ { 0x007D, 0x7D, "braceright" },
+ { 0x007E, 0x7E, "asciitilde" },
+ { 0x00A1, 0xA1, "exclamdown" },
+ { 0x00A2, 0xA2, "cent" },
+ { 0x00A3, 0xA3, "sterling" },
+ { 0x00A4, 0xA8, "currency" },
+ { 0x00A5, 0xA5, "yen" },
+ { 0x00A7, 0xA7, "section" },
+ { 0x00A8, 0xC8, "dieresis" },
+ { 0x00AA, 0xE3, "ordfeminine" },
+ { 0x00AB, 0xAB, "guillemotleft" },
+ { 0x00AF, 0xC5, "macron" },
+ { 0x00B4, 0xC2, "acute" },
+ { 0x00B6, 0xB6, "paragraph" },
+ { 0x00B7, 0xB4, "periodcentered" },
+ { 0x00B8, 0xCB, "cedilla" },
+ { 0x00BA, 0xEB, "ordmasculine" },
+ { 0x00BB, 0xBB, "guillemotright" },
+ { 0x00BF, 0xBF, "questiondown" },
+ { 0x00C6, 0xE1, "AE" },
+ { 0x00D8, 0xE9, "Oslash" },
+ { 0x00DF, 0xFB, "germandbls" },
+ { 0x00E6, 0xF1, "ae" },
+ { 0x00F8, 0xF9, "oslash" },
+ { 0x0131, 0xF5, "dotlessi" },
+ { 0x0141, 0xE8, "Lslash" },
+ { 0x0142, 0xF8, "lslash" },
+ { 0x0152, 0xEA, "OE" },
+ { 0x0153, 0xFA, "oe" },
+ { 0x0192, 0xA6, "florin" },
+ { 0x02C6, 0xC3, "circumflex" },
+ { 0x02C7, 0xCF, "caron" },
+ { 0x02D8, 0xC6, "breve" },
+ { 0x02D9, 0xC7, "dotaccent" },
+ { 0x02DA, 0xCA, "ring" },
+ { 0x02DB, 0xCE, "ogonek" },
+ { 0x02DC, 0xC4, "tilde" },
+ { 0x02DD, 0xCD, "hungarumlaut" },
+ { 0x2013, 0xB1, "endash" },
+ { 0x2014, 0xD0, "emdash" },
+ { 0x2018, 0x60, "quoteleft" },
+ { 0x2019, 0x27, "quoteright" },
+ { 0x201A, 0xB8, "quotesinglbase" },
+ { 0x201C, 0xAA, "quotedblleft" },
+ { 0x201D, 0xBA, "quotedblright" },
+ { 0x201E, 0xB9, "quotedblbase" },
+ { 0x2020, 0xB2, "dagger" },
+ { 0x2021, 0xB3, "daggerdbl" },
+ { 0x2022, 0xB7, "bullet" },
+ { 0x2026, 0xBC, "ellipsis" },
+ { 0x2030, 0xBD, "perthousand" },
+ { 0x2039, 0xAC, "guilsinglleft" },
+ { 0x203A, 0xAD, "guilsinglright" },
+ { 0x2044, 0xA4, "fraction" },
+ { 0xFB01, 0xAE, "fi" },
+ { 0xFB02, 0xAF, "fl" },
+};
+
+static const AdobeConvEntry aAdobeSymbolConvTable[] =
+{
+ { 0x0020, 0x20, "space" },
+ { 0x0021, 0x21, "exclam" },
+ { 0x0023, 0x23, "numbersign" },
+ { 0x0025, 0x25, "percent" },
+ { 0x0026, 0x26, "ampersand" },
+ { 0x0028, 0x28, "parenleft" },
+ { 0x0029, 0x29, "parenright" },
+ { 0x002B, 0x2B, "plus" },
+ { 0x002C, 0x2C, "comma" },
+ { 0x002E, 0x2E, "period" },
+ { 0x002F, 0x2F, "slash" },
+ { 0x0030, 0x30, "zero" },
+ { 0x0031, 0x31, "one" },
+ { 0x0032, 0x32, "two" },
+ { 0x0033, 0x33, "three" },
+ { 0x0034, 0x34, "four" },
+ { 0x0035, 0x35, "five" },
+ { 0x0036, 0x36, "six" },
+ { 0x0037, 0x37, "seven" },
+ { 0x0038, 0x38, "eight" },
+ { 0x0039, 0x39, "nine" },
+ { 0x003A, 0x3A, "colon" },
+ { 0x003B, 0x3B, "semicolon" },
+ { 0x003C, 0x3C, "less" },
+ { 0x003D, 0x3D, "equal" },
+ { 0x003E, 0x3E, "greater" },
+ { 0x003F, 0x3F, "question" },
+ { 0x005B, 0x5B, "bracketleft" },
+ { 0x005D, 0x5D, "bracketright" },
+ { 0x005F, 0x5F, "underscore" },
+ { 0x007B, 0x7B, "braceleft" },
+ { 0x007C, 0x7C, "bar" },
+ { 0x007D, 0x7D, "braceright" },
+ { 0x00A9, 0xD3, "copyrightserif" },
+ { 0x00A9, 0xE3, "copyrightsans" },
+ { 0x00AC, 0xD8, "logicalnot" },
+ { 0x00AE, 0xD2, "registeredserif" },
+ { 0x00AE, 0xE2, "registeredsans" },
+ { 0x00B0, 0xB0, "degree" },
+ { 0x00B1, 0xB1, "plusminus" },
+ { 0x00D7, 0xB4, "multiply" },
+ { 0x00F7, 0xB8, "divide" },
+ { 0x0192, 0xA6, "florin" },
+ { 0x0391, 0x41, "Alpha" },
+ { 0x0392, 0x42, "Beta" },
+ { 0x0393, 0x47, "Gamma" },
+ { 0x0394, 0x44, "Delta" },
+ { 0x0395, 0x45, "Epsilon" },
+ { 0x0396, 0x5A, "Zeta" },
+ { 0x0397, 0x48, "Eta" },
+ { 0x0398, 0x51, "Theta" },
+ { 0x0399, 0x49, "Iota" },
+ { 0x039A, 0x4B, "Kappa" },
+ { 0x039B, 0x4C, "Lambda" },
+ { 0x039C, 0x4D, "Mu" },
+ { 0x039D, 0x4E, "Nu" },
+ { 0x039E, 0x58, "Xi" },
+ { 0x039F, 0x4F, "Omicron" },
+ { 0x03A0, 0x50, "Pi" },
+ { 0x03A1, 0x52, "Rho" },
+ { 0x03A3, 0x53, "Sigma" },
+ { 0x03A4, 0x54, "Tau" },
+ { 0x03A5, 0x55, "Upsilon" },
+ { 0x03A6, 0x46, "Phi" },
+ { 0x03A7, 0x43, "Chi" },
+ { 0x03A8, 0x59, "Psi" },
+ { 0x03A9, 0x57, "Omega" },
+ { 0x03B1, 0x61, "alpha" },
+ { 0x03B2, 0x62, "beta" },
+ { 0x03B3, 0x67, "gamma" },
+ { 0x03B4, 0x64, "delta" },
+ { 0x03B5, 0x65, "epsilon" },
+ { 0x03B6, 0x7A, "zeta" },
+ { 0x03B7, 0x68, "eta" },
+ { 0x03B8, 0x71, "theta" },
+ { 0x03B9, 0x69, "iota" },
+ { 0x03BA, 0x6B, "kappa" },
+ { 0x03BB, 0x6C, "lambda" },
+ { 0x03BC, 0x6D, "mu" },
+ { 0x03BD, 0x6E, "nu" },
+ { 0x03BE, 0x78, "xi" },
+ { 0x03BF, 0x6F, "omicron" },
+ { 0x03C0, 0x70, "pi" },
+ { 0x03C1, 0x72, "rho" },
+ { 0x03C2, 0x56, "sigma1" },
+ { 0x03C3, 0x73, "sigma" },
+ { 0x03C4, 0x74, "tau" },
+ { 0x03C5, 0x75, "upsilon" },
+ { 0x03C6, 0x66, "phi" },
+ { 0x03C7, 0x63, "chi" },
+ { 0x03C8, 0x79, "psi" },
+ { 0x03C9, 0x77, "omega" },
+ { 0x03D1, 0x4A, "theta1" },
+ { 0x03D2, 0xA1, "Upsilon1" },
+ { 0x03D5, 0x6A, "phi1" },
+ { 0x03D6, 0x76, "omega1" },
+ { 0x2022, 0xB7, "bullet" },
+ { 0x2026, 0xBC, "ellipsis" },
+ { 0x2032, 0xA2, "minute" },
+ { 0x2033, 0xB2, "second" },
+ { 0x203E, 0x60, "radicalex" },
+ { 0x2044, 0xA4, "fraction" },
+ { 0x2111, 0xC1, "Ifraktur" },
+ { 0x2118, 0xC3, "weierstrass" },
+ { 0x211C, 0xC2, "Rfraktur" },
+ { 0x2122, 0xD4, "trademarkserif" },
+ { 0x2122, 0xE4, "trademarksans" },
+ { 0x2126, 0x57, "Omega" },
+ { 0x2135, 0xC0, "aleph" },
+ { 0x2190, 0xAC, "arrowleft" },
+ { 0x2191, 0xAD, "arrowup" },
+ { 0x2192, 0xAE, "arrowright" },
+ { 0x2193, 0xAF, "arrowdown" },
+ { 0x2194, 0xAB, "arrowboth" },
+ { 0x21B5, 0xBF, "carriagereturn" },
+ { 0x21D0, 0xDC, "arrowdblleft" },
+ { 0x21D1, 0xDD, "arrowdblup" },
+ { 0x21D2, 0xDE, "arrowdblright" },
+ { 0x21D3, 0xDF, "arrowdbldown" },
+ { 0x21D4, 0xDB, "arrowdblboth" },
+ { 0x2200, 0x22, "universal" },
+ { 0x2202, 0xB6, "partialdiff" },
+ { 0x2203, 0x24, "existential" },
+ { 0x2205, 0xC6, "emptyset" },
+ { 0x2206, 0x44, "Delta" },
+ { 0x2207, 0xD1, "gradient" },
+ { 0x2208, 0xCE, "element" },
+ { 0x2209, 0xCF, "notelement" },
+ { 0x220B, 0x27, "suchthat" },
+ { 0x220F, 0xD5, "product" },
+ { 0x2211, 0xE5, "summation" },
+ { 0x2212, 0x2D, "minus" },
+ { 0x2215, 0xA4, "fraction" },
+ { 0x2217, 0x2A, "asteriskmath" },
+ { 0x221A, 0xD6, "radical" },
+ { 0x221D, 0xB5, "proportional" },
+ { 0x221E, 0xA5, "infinity" },
+ { 0x2220, 0xD0, "angle" },
+ { 0x2227, 0xD9, "logicaland" },
+ { 0x2228, 0xDA, "logicalor" },
+ { 0x2229, 0xC7, "intersection" },
+ { 0x222A, 0xC8, "union" },
+ { 0x222B, 0xF2, "integral" },
+ { 0x2234, 0x5C, "therefore" },
+ { 0x223C, 0x7E, "similar" },
+ { 0x2245, 0x40, "congruent" },
+ { 0x2248, 0xBB, "approxequal" },
+ { 0x2260, 0xB9, "notequal" },
+ { 0x2261, 0xBA, "equivalence" },
+ { 0x2264, 0xA3, "lessequal" },
+ { 0x2265, 0xB3, "greaterequal" },
+ { 0x2282, 0xCC, "propersubset" },
+ { 0x2283, 0xC9, "propersuperset" },
+ { 0x2284, 0xCB, "notsubset" },
+ { 0x2286, 0xCD, "reflexsubset" },
+ { 0x2287, 0xCA, "reflexsuperset" },
+ { 0x2295, 0xC5, "circleplus" },
+ { 0x2297, 0xC4, "circlemultiply" },
+ { 0x22A5, 0x5E, "perpendicular" },
+ { 0x22C5, 0xD7, "dotmath" },
+ { 0x2320, 0xF3, "integraltp" },
+ { 0x2321, 0xF5, "integralbt" },
+ { 0x2329, 0xE1, "angleleft" },
+ { 0x232A, 0xF1, "angleright" },
+ { 0x25CA, 0xE0, "lozenge" },
+ { 0x2660, 0xAA, "spade" },
+ { 0x2663, 0xA7, "club" },
+ { 0x2665, 0xA9, "heart" },
+ { 0x2666, 0xA8, "diamond" },
+};
+
+static const AdobeConvEntry aAdobeDingBatsTable[] =
+{
+ { 0x2192, 0xD5, "a161" },
+ { 0x2194, 0xD6, "a163" },
+ { 0x2195, 0xD7, "a164" },
+ { 0x2460, 0xAC, "a120" },
+ { 0x2461, 0xAD, "a121" },
+ { 0x2462, 0xAE, "a122" },
+ { 0x2463, 0xAF, "a123" },
+ { 0x2464, 0xB0, "a124" },
+ { 0x2465, 0xB1, "a125" },
+ { 0x2466, 0xB2, "a126" },
+ { 0x2467, 0xB3, "a127" },
+ { 0x2468, 0xB4, "a128" },
+ { 0x2469, 0xB5, "a129" },
+ { 0x25A0, 0x6E, "a73" },
+ { 0x25B2, 0x73, "a76" },
+ { 0x25BC, 0x74, "a77" },
+ { 0x25C6, 0x75, "a78" },
+ { 0x2605, 0x48, "a35" },
+ { 0x260E, 0x25, "a4" },
+ { 0x261B, 0x2A, "a11" },
+ { 0x261E, 0x2B, "a12" },
+ { 0x2660, 0xAB, "a109" },
+ { 0x2663, 0xA8, "a112" },
+ { 0x2665, 0xAA, "a110" },
+ { 0x2666, 0xA9, "a111" },
+ { 0x2701, 0x21, "a1" },
+ { 0x2702, 0x22, "a2" },
+ { 0x2703, 0x23, "a202" },
+ { 0x2704, 0x24, "a3" },
+ { 0x2706, 0x26, "a5" },
+ { 0x2707, 0x27, "a119" },
+ { 0x2708, 0x28, "a118" },
+ { 0x2709, 0x29, "a117" },
+ { 0x270C, 0x2C, "a13" },
+ { 0x270D, 0x2D, "a14" },
+ { 0x270E, 0x2E, "a15" },
+ { 0x270F, 0x2F, "a16" },
+ { 0x2710, 0x30, "a105" },
+ { 0x2711, 0x31, "a17" },
+ { 0x2712, 0x32, "a18" },
+ { 0x2713, 0x33, "a19" },
+ { 0x2714, 0x34, "a20" },
+ { 0x2715, 0x35, "a21" },
+ { 0x2716, 0x36, "a22" },
+ { 0x2717, 0x37, "a23" },
+ { 0x2718, 0x38, "a24" },
+ { 0x2719, 0x39, "a25" },
+ { 0x271A, 0x3A, "a26" },
+ { 0x271B, 0x3B, "a27" },
+ { 0x271C, 0x3C, "a28" },
+ { 0x271D, 0x3D, "a6" },
+ { 0x271E, 0x3E, "a7" },
+ { 0x271F, 0x3F, "a8" },
+ { 0x2720, 0x40, "a9" },
+ { 0x2721, 0x41, "a10" },
+ { 0x2722, 0x42, "a29" },
+ { 0x2723, 0x43, "a30" },
+ { 0x2724, 0x44, "a31" },
+ { 0x2725, 0x45, "a32" },
+ { 0x2726, 0x46, "a33" },
+ { 0x2727, 0x47, "a34" },
+ { 0x2729, 0x49, "a36" },
+ { 0x272A, 0x4A, "a37" },
+ { 0x272B, 0x4B, "a38" },
+ { 0x272C, 0x4C, "a39" },
+ { 0x272D, 0x4D, "a40" },
+ { 0x272E, 0x4E, "a41" },
+ { 0x272F, 0x4F, "a42" },
+ { 0x2730, 0x50, "a43" },
+ { 0x2731, 0x51, "a44" },
+ { 0x2732, 0x52, "a45" },
+ { 0x2733, 0x53, "a46" },
+ { 0x2734, 0x54, "a47" },
+ { 0x2735, 0x55, "a48" },
+ { 0x2736, 0x56, "a49" },
+ { 0x2737, 0x57, "a50" },
+ { 0x2738, 0x58, "a51" },
+ { 0x2739, 0x59, "a52" },
+ { 0x273A, 0x5A, "a53" },
+ { 0x273B, 0x5B, "a54" },
+ { 0x273C, 0x5C, "a55" },
+ { 0x273D, 0x5D, "a56" },
+ { 0x273E, 0x5E, "a57" },
+ { 0x273F, 0x5F, "a58" },
+ { 0x2740, 0x60, "a59" },
+ { 0x2741, 0x61, "a60" },
+ { 0x2742, 0x62, "a61" },
+ { 0x2743, 0x63, "a62" },
+ { 0x2744, 0x64, "a63" },
+ { 0x2745, 0x65, "a64" },
+ { 0x2746, 0x66, "a65" },
+ { 0x2747, 0x67, "a66" },
+ { 0x2748, 0x68, "a67" },
+ { 0x2749, 0x69, "a68" },
+ { 0x274A, 0x6A, "a69" },
+ { 0x274B, 0x6B, "a70" },
+ { 0x274D, 0x6D, "a72" },
+ { 0x274F, 0x6F, "a74" },
+ { 0x2750, 0x70, "a203" },
+ { 0x2751, 0x71, "a75" },
+ { 0x2752, 0x72, "a204" },
+ { 0x2756, 0x76, "a79" },
+ { 0x2758, 0x78, "a82" },
+ { 0x2759, 0x79, "a83" },
+ { 0x275A, 0x7A, "a84" },
+ { 0x275B, 0x7B, "a97" },
+ { 0x275C, 0x7C, "a98" },
+ { 0x275D, 0x7D, "a99" },
+ { 0x275E, 0x7E, "a100" },
+ { 0x2761, 0xA1, "a101" },
+ { 0x2762, 0xA2, "a102" },
+ { 0x2763, 0xA3, "a103" },
+ { 0x2764, 0xA4, "a104" },
+ { 0x2765, 0xA5, "a105" },
+ { 0x2766, 0xA6, "a106" },
+ { 0x2767, 0xA7, "a107" },
+ { 0x2776, 0xB6, "a130" },
+ { 0x2777, 0xB7, "a131" },
+ { 0x2778, 0xB8, "a132" },
+ { 0x2779, 0xB9, "a133" },
+ { 0x277A, 0xBA, "a134" },
+ { 0x277B, 0xBB, "a135" },
+ { 0x277C, 0xBC, "a136" },
+ { 0x277D, 0xBD, "a137" },
+ { 0x277E, 0xBE, "a138" },
+ { 0x277F, 0xBF, "a139" },
+ { 0x2780, 0xC0, "a140" },
+ { 0x2781, 0xC1, "a141" },
+ { 0x2782, 0xC2, "a142" },
+ { 0x2783, 0xC3, "a143" },
+ { 0x2784, 0xC4, "a144" },
+ { 0x2785, 0xC5, "a145" },
+ { 0x2786, 0xC6, "a146" },
+ { 0x2787, 0xC7, "a147" },
+ { 0x2788, 0xC8, "a148" },
+ { 0x2789, 0xC9, "a149" },
+ { 0x278A, 0xCA, "a150" },
+ { 0x278B, 0xCB, "a151" },
+ { 0x278C, 0xCC, "a152" },
+ { 0x278D, 0xCD, "a153" },
+ { 0x278E, 0xCE, "a154" },
+ { 0x278F, 0xCF, "a155" },
+ { 0x2790, 0xD0, "a156" },
+ { 0x2791, 0xD1, "a157" },
+ { 0x2792, 0xD2, "a158" },
+ { 0x2793, 0xD3, "a159" },
+ { 0x2794, 0xD4, "a160" },
+ { 0x2798, 0xD8, "a196" },
+ { 0x2799, 0xD9, "a165" },
+ { 0x279A, 0xDA, "a192" },
+ { 0x279B, 0xDB, "a166" },
+ { 0x279C, 0xDC, "a167" },
+ { 0x279D, 0xDD, "a168" },
+ { 0x279E, 0xDE, "a169" },
+ { 0x279F, 0xDF, "a170" },
+ { 0x27A0, 0xE0, "a171" },
+ { 0x27A1, 0xE1, "a172" },
+ { 0x27A2, 0xE2, "a173" },
+ { 0x27A3, 0xE3, "a162" },
+ { 0x27A4, 0xE4, "a174" },
+ { 0x27A5, 0xE5, "a175" },
+ { 0x27A6, 0xE6, "a176" },
+ { 0x27A7, 0xE7, "a177" },
+ { 0x27A8, 0xE8, "a178" },
+ { 0x27A9, 0xE9, "a179" },
+ { 0x27AA, 0xEA, "a193" },
+ { 0x27AB, 0xEB, "a180" },
+ { 0x27AC, 0xEC, "a199" },
+ { 0x27AD, 0xED, "a181" },
+ { 0x27AE, 0xEE, "a200" },
+ { 0x27AF, 0xEF, "a182" },
+ { 0x27B1, 0xF1, "a201" },
+ { 0x27B2, 0xF2, "a183" },
+ { 0x27B3, 0xF3, "a184" },
+ { 0x27B4, 0xF4, "a197" },
+ { 0x27B5, 0xF5, "a185" },
+ { 0x27B6, 0xF6, "a194" },
+ { 0x27B7, 0xF7, "a198" },
+ { 0x27B8, 0xF8, "a186" },
+ { 0x27B9, 0xF9, "a195" },
+ { 0x27BA, 0xFA, "a187" },
+ { 0x27BB, 0xFB, "a188" },
+ { 0x27BC, 0xFC, "a189" },
+ { 0x27BD, 0xFD, "a190" },
+ { 0x27BE, 0xFE, "a191" },
+};
diff --git a/psprint/source/fontmanager/fontmanager.cxx b/psprint/source/fontmanager/fontmanager.cxx
new file mode 100644
index 000000000000..a23f70901fd4
--- /dev/null
+++ b/psprint/source/fontmanager/fontmanager.cxx
@@ -0,0 +1,2435 @@
+/*************************************************************************
+ *
+ * $RCSfile: fontmanager.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:35 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#define Window XLIB_Window
+#include <X11/Xlib.h>
+#undef Window
+#include <unistd.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#ifndef _OSL_THREAD_H_
+#include <osl/thread.h>
+#endif
+#ifndef _UTL_ATOM_HXX_
+#include <unotools/atom.hxx>
+#endif
+#ifndef _PSPRINT_FONTMANAGER_HXX_
+#include <psprint/fontmanager.hxx>
+#endif
+#ifndef _URLOBJ_HXX
+#include <tools/urlobj.hxx>
+#endif
+#ifndef _STREAM_HXX
+#include <tools/stream.hxx>
+#endif
+#ifndef _PSPRINT_HELPER_HXX_
+#include <psprint/helper.hxx>
+#endif
+#ifndef _OSL_FILE_HXX_
+#include <osl/file.hxx>
+#endif
+#ifndef _PSPRINT_STRHELPER_HXX_
+#include <psprint/strhelper.hxx>
+#endif
+#ifndef _PSPRINT_PPDPARSER_HXX_
+#include <psprint/ppdparser.hxx>
+#endif
+#ifndef _RTL_TENCINFO_H
+#include <rtl/tencinfo.h>
+#endif
+#ifndef _TOOLS_DEBUG_HXX
+#include <tools/debug.hxx>
+#endif
+#ifndef _CONFIG_HXX
+#include <tools/config.hxx>
+#endif
+
+#include <parseAFM.hxx>
+#include <sft.h>
+
+#ifdef DEBUG
+#include <sys/times.h>
+#include <stdio.h>
+#endif
+
+#ifdef SOLARIS
+#include <alloca.h>
+#endif
+
+#include <adobeenc.tab> // get encoding table for AFM metrics
+
+#define PRINTER_METRICDIR "fontmetric"
+
+using namespace utl;
+using namespace psp;
+using namespace osl;
+using namespace rtl;
+
+/*
+ * static helpers
+ */
+
+inline sal_uInt16 getUInt16BE( const byte*& pBuffer )
+{
+ sal_uInt16 nRet = (sal_uInt16)pBuffer[1] |
+ (((sal_uInt16)pBuffer[0]) << 8);
+ pBuffer+=2;
+ return nRet;
+}
+
+static italic::type parseItalic( const ByteString& rItalic )
+{
+ italic::type eItalic = italic::Unknown;
+ if( rItalic.EqualsIgnoreCaseAscii( "i" ) )
+ eItalic = italic::Italic;
+ else if( rItalic.EqualsIgnoreCaseAscii( "o" ) )
+ eItalic = italic::Oblique;
+ else
+ eItalic = italic::Upright;
+ return eItalic;
+}
+
+// -------------------------------------------------------------------------
+
+static weight::type parseWeight( const ByteString& rWeight )
+{
+ weight::type eWeight = weight::Unknown;
+ if( rWeight.Search( "bold" ) != STRING_NOTFOUND )
+ {
+ if( rWeight.Search( "emi" ) != STRING_NOTFOUND ) // semi, demi
+ eWeight = weight::SemiBold;
+ else if( rWeight.Search( "ultra" ) != STRING_NOTFOUND )
+ eWeight = weight::UltraBold;
+ else
+ eWeight = weight::Bold;
+ }
+ else if( rWeight.Search( "light" ) != STRING_NOTFOUND )
+ {
+ if( rWeight.Search( "emi" ) != STRING_NOTFOUND ) // semi, demi
+ eWeight = weight::SemiLight;
+ else if( rWeight.Search( "ultra" ) != STRING_NOTFOUND )
+ eWeight = weight::UltraLight;
+ else
+ eWeight = weight::Light;
+ }
+ else if( rWeight.Search( "black" ) != STRING_NOTFOUND )
+ eWeight = weight::Black;
+ else if( rWeight.Equals( "demi" ) )
+ eWeight = weight::SemiBold;
+ else if( rWeight.Equals( "book" ) ||
+ rWeight.Equals( "semicondensed" ) )
+ eWeight = weight::Light;
+ else if( rWeight.Equals( "medium" ) || rWeight.Equals( "roman" ) )
+ eWeight = weight::Medium;
+ else
+ eWeight = weight::Normal;
+ return eWeight;
+}
+
+// -------------------------------------------------------------------------
+
+static width::type parseWidth( const ByteString& rWidth )
+{
+ width::type eWidth = width::Unknown;
+ if( rWidth.Equals( "bold" ) ||
+ rWidth.Equals( "semiexpanded" ) )
+ eWidth = width::SemiExpanded;
+ else if( rWidth.Equals( "condensed" ) ||
+ rWidth.Equals( "narrow" ) )
+ eWidth = width::Condensed;
+ else if( rWidth.Equals( "double wide" ) ||
+ rWidth.Equals( "extraexpanded" ) ||
+ rWidth.Equals( "ultraexpanded" ) )
+ eWidth = width::UltraExpanded;
+ else if( rWidth.Equals( "expanded" ) ||
+ rWidth.Equals( "wide" ) )
+ eWidth = width::Expanded;
+ else if( rWidth.Equals( "extracondensed" ) )
+ eWidth = width::ExtraCondensed;
+ else if( rWidth.Equals( "semicondensed" ) )
+ eWidth = width::SemiCondensed;
+ else if( rWidth.Equals( "ultracondensed" ) )
+ eWidth = width::UltraCondensed;
+ else
+ eWidth = width::Normal;
+
+ return eWidth;
+}
+
+// -------------------------------------------------------------------------
+
+/*
+ * PrintFont implementations
+ */
+PrintFontManager::PrintFont::PrintFont( fonttype::type eType ) :
+ m_eType( eType ),
+ m_nFamilyName( 0 ),
+ m_nPSName( 0 ),
+ m_eItalic( italic::Unknown ),
+ m_eWidth( width::Unknown ),
+ m_eWeight( weight::Unknown ),
+ m_ePitch( pitch::Unknown ),
+ m_aEncoding( RTL_TEXTENCODING_DONTKNOW ),
+ m_pMetrics( NULL ),
+ m_nAscend( 0 ),
+ m_nDescend( 0 ),
+ m_nLeading( 0 )
+{
+}
+
+// -------------------------------------------------------------------------
+
+PrintFontManager::PrintFont::~PrintFont()
+{
+ if( m_pMetrics )
+ delete m_pMetrics;
+}
+
+// -------------------------------------------------------------------------
+
+PrintFontManager::Type1FontFile::~Type1FontFile()
+{
+}
+
+// -------------------------------------------------------------------------
+
+PrintFontManager::TrueTypeFontFile::~TrueTypeFontFile()
+{
+}
+
+// -------------------------------------------------------------------------
+
+PrintFontManager::BuiltinFont::~BuiltinFont()
+{
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::Type1FontFile::queryMetricPage( int nPage, MultiAtomProvider* pProvider )
+{
+ return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider );
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::BuiltinFont::queryMetricPage( int nPage, MultiAtomProvider* pProvider )
+{
+ return readAfmMetrics( PrintFontManager::get().getAfmFile( this ), pProvider );
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::TrueTypeFontFile::queryMetricPage( int nPage, MultiAtomProvider* pProvider )
+{
+ bool bSuccess = false;
+
+ ByteString aFile( PrintFontManager::get().getFontFile( this ) );
+
+ TrueTypeFont* pTTFont = NULL;
+
+ if( OpenTTFont( aFile.GetBuffer(), m_nCollectionEntry < 0 ? 0 : m_nCollectionEntry, &pTTFont ) == SF_OK )
+ {
+ if( ! m_pMetrics )
+ {
+ m_pMetrics = new PrintFontMetrics;
+ memset (m_pMetrics->m_aPages, 0, sizeof(m_pMetrics->m_aPages));
+ }
+ m_pMetrics->m_aPages[ nPage/8 ] |= (1 << ( nPage & 7 ));
+ int i;
+ uint16 table[256];
+
+ for( i = 0; i < 256; i++ )
+ table[ i ] = 256*nPage + i;
+
+ int nCharacters = nPage < 255 ? 256 : 254;
+ MapString( pTTFont, table, nCharacters, NULL, 0 );
+ TTSimpleGlyphMetrics* pMetrics = GetTTSimpleCharMetrics( pTTFont, nPage*256, nCharacters, 0 );
+ if( pMetrics )
+ {
+ for( i = 0; i < nCharacters; i++ )
+ {
+ if( table[i] )
+ {
+ CharacterMetric& rChar = m_pMetrics->m_aMetrics[ nPage*256 + i ];
+ rChar.width = pMetrics[ i ].adv;
+ rChar.height = m_aGlobalMetricX.height;
+ }
+ }
+
+ free( pMetrics );
+ }
+
+ for( i = 0; i < 256; i++ )
+ table[ i ] = 256*nPage + i;
+ MapString( pTTFont, table, nCharacters, NULL, 1 );
+ pMetrics = GetTTSimpleCharMetrics( pTTFont, nPage*256, nCharacters, 1 );
+ if( pMetrics )
+ {
+ for( i = 0; i < nCharacters; i++ )
+ {
+ if( table[i] )
+ {
+ CharacterMetric& rChar = m_pMetrics->m_aMetrics[ nPage*256 + i + ( 1 << 16 ) ];
+ rChar.width = m_aGlobalMetricY.width;
+ rChar.height = pMetrics[ i ].adv;
+ }
+ }
+ free( pMetrics );
+ }
+
+ if( ! m_pMetrics->m_bKernPairsQueried )
+ {
+ m_pMetrics->m_bKernPairsQueried = true;
+ // this is really a hack
+ // in future MapString/KernGlyphs should be used
+ // but vcl is not in a state where that could be used
+ // so currently we get kernpairs by accessing the raw data
+ struct _TrueTypeFont* pImplTTFont = (struct _TrueTypeFont*)pTTFont;
+
+ if( pImplTTFont->nkern && pImplTTFont->kerntype == KT_MICROSOFT )
+ {
+ // create a glyph -> character mapping
+ ::std::hash_map< sal_uInt16, sal_Unicode > aGlyphMap;
+ ::std::hash_map< sal_uInt16, sal_Unicode >::iterator left, right;
+ for( i = 21; i < 0xfffd; i++ )
+ {
+ sal_uInt16 nGlyph = MapChar( pTTFont, (sal_Unicode)i, 0 ); // kerning for horz only
+ if( nGlyph != 0 )
+ aGlyphMap[ nGlyph ] = (sal_Unicode)i;
+ }
+
+
+ KernPair aPair;
+ for( i = 0; i < pImplTTFont->nkern; i++ )
+ {
+ const byte* pTable = pImplTTFont->kerntables[i];
+
+ sal_uInt16 nVersion = getUInt16BE( pTable );
+ sal_uInt16 nLength = getUInt16BE( pTable );
+ sal_uInt16 nCoverage = getUInt16BE( pTable );
+
+ aPair.kern_x = 0;
+ aPair.kern_y = 0;
+ switch( nCoverage >> 8 )
+ {
+ case 0:
+ {
+ sal_uInt16 nPairs = getUInt16BE( pTable );
+ pTable += 6;
+ for( int n = 0; n < nPairs; n++ )
+ {
+ sal_uInt16 nLeftGlyph = getUInt16BE( pTable );
+ sal_uInt16 nRightGlyph = getUInt16BE( pTable );
+ sal_Int16 nKern = (sal_Int16)getUInt16BE( pTable );
+
+ left = aGlyphMap.find( nLeftGlyph );
+ right = aGlyphMap.find( nRightGlyph );
+ if( left != aGlyphMap.end() && right != aGlyphMap.end() )
+ {
+ aPair.first = left->second;
+ aPair.second = right->second;
+ switch( nCoverage & 1 )
+ {
+ case 1:
+ aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
+ m_pMetrics->m_aXKernPairs.push_back( aPair );
+ break;
+ case 0:
+ aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
+ m_pMetrics->m_aYKernPairs.push_back( aPair );
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case 2:
+
+ {
+ const byte* pSubTable = pTable;
+ sal_uInt16 nRowWidth = getUInt16BE( pTable );
+ sal_uInt16 nOfLeft = getUInt16BE( pTable );
+ sal_uInt16 nOfRight = getUInt16BE( pTable );
+ sal_uInt16 nOfArray = getUInt16BE( pTable );
+ const byte* pTmp = pSubTable + nOfLeft;
+ sal_uInt16 nFirstLeft = getUInt16BE( pTmp );
+ sal_uInt16 nLastLeft = getUInt16BE( pTmp ) + nFirstLeft - 1;
+ pTmp = pSubTable + nOfRight;
+ sal_uInt16 nFirstRight = getUInt16BE( pTmp );
+ sal_uInt16 nLastRight = getUInt16BE( pTmp ) + nFirstRight -1;
+
+ int nPairs = (int)(nLastLeft-nFirstLeft+1)*(int)(nLastRight-nFirstRight+1);
+ for( aPair.first = nFirstLeft; aPair.first < nLastLeft; aPair.first++ )
+ {
+ for( aPair.second = 0; aPair.second < nLastRight; aPair.second++ )
+ {
+ sal_Int16 nKern = (sal_Int16)getUInt16BE( pTmp );
+ switch( nCoverage & 1 )
+ {
+ case 1:
+ aPair.kern_x = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
+ m_pMetrics->m_aXKernPairs.push_back( aPair );
+ break;
+ case 0:
+ aPair.kern_y = (int)nKern * 1000 / pImplTTFont->unitsPerEm;
+ m_pMetrics->m_aYKernPairs.push_back( aPair );
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+#ifdef DEBUG
+ fprintf( stderr, "found %d/%d kern pairs for %s\n",
+ m_pMetrics->m_aXKernPairs.size(),
+ m_pMetrics->m_aYKernPairs.size(),
+ OUStringToOString( pProvider->getString( ATOM_FAMILYNAME, m_nFamilyName ), RTL_TEXTENCODING_MS_1252 ).getStr() );
+#endif
+ }
+
+ CloseTTFont( pTTFont );
+ bSuccess = true;
+ }
+ return bSuccess;
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::PrintFont::readAfmMetrics( const OString& rFileName, MultiAtomProvider* pProvider )
+{
+ int i;
+ FILE* fp = fopen( rFileName.getStr(), "r" );
+ if( ! fp )
+ return false;
+ FontInfo* pInfo = NULL;
+ int nResult = parseFile( fp, &pInfo, P_ALL );
+ fclose( fp );
+ if( nResult != ok )
+ {
+ if( pInfo )
+ freeFontInfo( pInfo );
+ return false;
+ }
+
+ // fill in global info
+
+ // family name (if not already set)
+ if( ! m_nFamilyName )
+ {
+ OUString aFamily( OStringToOUString( pInfo->gfi->familyName, RTL_TEXTENCODING_ISO_8859_1 ) );
+ if( ! aFamily.getLength() )
+ aFamily = OStringToOUString( pInfo->gfi->fontName, RTL_TEXTENCODING_ISO_8859_1 );
+ m_nFamilyName = pProvider->getAtom( ATOM_FAMILYNAME, aFamily, sal_True );
+ }
+
+ // PSName
+ OUString aPSName( OStringToOUString( pInfo->gfi->fontName, RTL_TEXTENCODING_ISO_8859_1 ) );
+ m_nPSName = pProvider->getAtom( ATOM_PSNAME, aPSName, sal_True );
+
+ // italic
+ if( pInfo->gfi->italicAngle > 0 )
+ m_eItalic = italic::Oblique;
+ else if( pInfo->gfi->italicAngle < 0 )
+ m_eItalic = italic::Italic;
+ else
+ m_eItalic = italic::Upright;
+
+ // weight
+ m_eWeight = parseWeight( ByteString( pInfo->gfi->weight ).ToLowerAscii() );
+
+ // pitch
+ m_ePitch = pInfo->gfi->isFixedPitch ? pitch::Fixed : pitch::Variable;
+
+ // encoding - only set if unknown
+ // try to parse the font name and decide wether it might be a
+ // japanese font. Who invented this PITA ?
+ int nTokens = aPSName.getTokenCount( '-' );
+ if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW && nTokens > 2 &&
+ ( ! aPSName.getToken( nTokens-1, '-' ).compareToAscii( "H" ) ||
+ ! aPSName.getToken( nTokens-1, '-' ).compareToAscii( "V" ) )
+ )
+ {
+ static const char* pEncs[] =
+ {
+ "EUC",
+ "RKSJ",
+ "SJ"
+ };
+ static const rtl_TextEncoding aEncs[] =
+ {
+ RTL_TEXTENCODING_EUC_JP,
+ RTL_TEXTENCODING_SHIFT_JIS,
+ RTL_TEXTENCODING_JIS_X_0208
+ };
+
+ for( int enc = 0; enc < sizeof( aEncs )/sizeof(aEncs[0]) && m_aEncoding == RTL_TEXTENCODING_DONTKNOW; enc++ )
+ for( int i = 1; i < nTokens-1 && m_aEncoding == RTL_TEXTENCODING_DONTKNOW; i++ )
+ {
+ OUString aEncoding( aPSName.getToken( i, '-' ) );
+ if( ! aEncoding.compareToAscii( pEncs[enc] ) )
+ m_aEncoding = aEncs[ enc ];
+ }
+
+ // default is jis
+ if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
+ m_aEncoding = RTL_TEXTENCODING_JIS_X_0208;
+#ifdef DEBUG
+ fprintf( stderr, "Encoding %d for %s\n", m_aEncoding, pInfo->gfi->fontName );
+#endif
+ }
+ int nAdobeEncoding = 0;
+ if( pInfo->gfi->encodingScheme )
+ {
+ if( !strcmp( pInfo->gfi->encodingScheme, "AdobeStandardEncoding" ) )
+ nAdobeEncoding = 1;
+ else if( !strcmp( pInfo->gfi->encodingScheme, "Symbol") )
+ nAdobeEncoding = 2;
+ else if( !strcmp( pInfo->gfi->encodingScheme, "FontSpecific") )
+ nAdobeEncoding = 3;
+
+ if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
+ m_aEncoding = nAdobeEncoding == 1 ?
+ RTL_TEXTENCODING_MS_1252 : RTL_TEXTENCODING_SYMBOL;
+ }
+ else if( m_aEncoding == RTL_TEXTENCODING_DONTKNOW )
+ m_aEncoding = RTL_TEXTENCODING_MS_1252;
+
+ // ascend
+ m_nAscend = pInfo->gfi->fontBBox.ury;
+
+ // descend
+ // descends have opposite sign of our definition
+ m_nDescend = -pInfo->gfi->fontBBox.lly;
+
+ // fallback to ascender, descender
+ // interestigly the BBox seems to describe Ascender and Descender better
+ // as we understand it
+ if( m_nAscend == 0 )
+ m_nAscend = pInfo->gfi->ascender;
+ if( m_nDescend == 0)
+ m_nDescend = -pInfo->gfi->descender;
+
+ m_nLeading = m_nAscend + m_nDescend - 1000;
+
+ if( m_pMetrics )
+ delete m_pMetrics;
+ m_pMetrics = new PrintFontMetrics;
+ // mark all pages as queried
+ memset( m_pMetrics->m_aPages, 0xff, sizeof( m_pMetrics->m_aPages ) );
+
+ m_aGlobalMetricX.width = m_aGlobalMetricY.width =
+ pInfo->gfi->charwidth ? pInfo->gfi->charwidth : pInfo->gfi->fontBBox.urx;
+ m_aGlobalMetricX.height = m_aGlobalMetricY.height =
+ pInfo->gfi->capHeight ? pInfo->gfi->capHeight : pInfo->gfi->fontBBox.ury;
+
+ // fill in character metrics
+
+ // first transform the character codes to unicode
+ // note: this only works with single byte encodings
+ sal_Unicode* pUnicodes = (sal_Unicode*)alloca( pInfo->numOfChars * sizeof(sal_Unicode));
+ CharMetricInfo* pChar = pInfo->cmi;
+
+ for( i = 0; i < pInfo->numOfChars; i++, pChar++ )
+ {
+ if( pChar->code != -1 )
+ {
+ ByteString aTranslate;
+ if( pChar->code & 0xff000000 )
+ aTranslate += (char)(pChar->code >> 24 );
+ if( pChar->code & 0xffff0000 )
+ aTranslate += (char)((pChar->code & 0x00ff0000) >> 16 );
+ if( pChar->code & 0xffffff00 )
+ aTranslate += (char)((pChar->code & 0x0000ff00) >> 8 );
+ aTranslate += (char)(pChar->code & 0xff);
+ String aUni( aTranslate, m_aEncoding );
+ pUnicodes[i] = *aUni.GetBuffer();
+ }
+ else
+ pUnicodes[i] = 0;
+ }
+
+ // now fill in the character metrics
+ // parseAFM.cxx effectively only supports direction 0 (horizontal)
+ pChar = pInfo->cmi;
+ CharacterMetric aMetric;
+ for( i = 0; i < pInfo->numOfChars; i++, pChar++ )
+ {
+ if( pChar->code == -1 && ! pChar->name )
+ continue;
+
+ aMetric.width = pChar->wx ? pChar->wx : pChar->charBBox.urx;
+ aMetric.height = pChar->wy ? pChar->wy : pChar->charBBox.ury - pChar->charBBox.lly;
+ if( aMetric.width == 0 && aMetric.height == 0 )
+ // guess something for e.g. space
+ aMetric.width = m_aGlobalMetricX.width/4;
+
+ if( ( nAdobeEncoding == 0 ) ||
+ ( ( nAdobeEncoding == 3 ) && ( m_aEncoding != RTL_TEXTENCODING_SYMBOL ) ) )
+ {
+ if( pChar->code != -1 )
+ {
+ m_pMetrics->m_aMetrics[ pUnicodes[i] ] = aMetric;
+ }
+ else if( pChar->name )
+ {
+ for( int n = 0; n < sizeof(aAdobeStandardNoneCodes)/sizeof(aAdobeStandardNoneCodes[0]); n++ )
+ {
+ if( ! strcmp( pChar->name, aAdobeStandardNoneCodes[n].pAdobename ) )
+ {
+ m_pMetrics->m_aMetrics[ aAdobeStandardNoneCodes[n].aUnicode ] = aMetric;
+ }
+ }
+ }
+ }
+ else if( nAdobeEncoding == 1 )
+ {
+ if( pChar->code == -1 )
+ {
+ if( pChar->name )
+ {
+
+ for( int n = 0; n < sizeof(aAdobeStandardNoneCodes)/sizeof(aAdobeStandardNoneCodes[0]); n++ )
+ {
+ if( ! strcmp( pChar->name, aAdobeStandardNoneCodes[n].pAdobename ) )
+ {
+ m_pMetrics->m_aMetrics[ aAdobeStandardNoneCodes[n].aUnicode ] = aMetric;
+ }
+ }
+ }
+ }
+ else
+ {
+ for( int n = 0; n < sizeof(aAdobeStandardConvTable)/sizeof(aAdobeStandardConvTable[0]); n++ )
+ {
+ if( pChar->code == aAdobeStandardConvTable[n].aAdobecode )
+ {
+ m_pMetrics->m_aMetrics[ aAdobeStandardConvTable[n].aUnicode ] = aMetric;
+ break;
+ }
+ }
+ }
+ }
+ else if( nAdobeEncoding == 2 )
+ {
+ if( pChar->code == -1 )
+ {
+ if( pChar->name )
+ {
+ for( int n = 0; n < sizeof(aAdobeSymbolConvTable)/sizeof(aAdobeSymbolConvTable[0]); n++ )
+ {
+ if( ! strcmp( pChar->name, aAdobeStandardNoneCodes[n].pAdobename ) )
+ {
+ m_pMetrics->m_aMetrics[ aAdobeStandardNoneCodes[n].aUnicode ] = aMetric;
+ }
+ }
+ }
+ }
+ else
+ {
+ for( int n = 0; n < sizeof(aAdobeSymbolConvTable)/sizeof(aAdobeSymbolConvTable[0]); n++ )
+ {
+ if( pChar->code == aAdobeSymbolConvTable[n].aAdobecode )
+ {
+ m_pMetrics->m_aMetrics[ aAdobeSymbolConvTable[n].aUnicode ] = aMetric;
+ break;
+ }
+ }
+ }
+ }
+ else if( nAdobeEncoding == 3 )
+ {
+ if( pChar->code != -1 )
+ {
+ sal_Unicode code = 0xf000 + pChar->code;
+ m_pMetrics->m_aMetrics[ code ] = aMetric;
+ // maybe should try to find the name in the convtabs ?
+ }
+ }
+ }
+
+ m_pMetrics->m_aXKernPairs.clear();
+ m_pMetrics->m_aYKernPairs.clear();
+
+ // now fill in the kern pairs
+ // parseAFM.cxx effectively only supports direction 0 (horizontal)
+ PairKernData* pKern = pInfo->pkd;
+ KernPair aPair;
+ for( i = 0; i < pInfo->numOfPairs; i++, pKern++ )
+ {
+ aPair.first = 0;
+ aPair.second = 0;
+ // currently we have to find the adobe character names
+ // in the already parsed character metrics to find
+ // the corresponding UCS2 code which is a bit dangerous
+ // since the character names are not required
+ // in the metric descriptions
+ pChar = pInfo->cmi;
+ for( int j = 0;
+ j < pInfo->numOfChars && ( aPair.first == 0 || aPair.second == 0 );
+ j++, pChar++ )
+ {
+ if( pChar->code != -1 )
+ {
+ if( ! strcmp( pKern->name1, pChar->name ? pChar->name : "" ) )
+ aPair.first = pUnicodes[ j ];
+ if( ! strcmp( pKern->name2, pChar->name ? pChar->name : "" ) )
+ aPair.second = pUnicodes[ j ];
+ }
+ }
+ if( aPair.first && aPair.second )
+ {
+ aPair.kern_x = pKern->xamt;
+ aPair.kern_y = pKern->yamt;
+ m_pMetrics->m_aXKernPairs.push_back( aPair );
+ }
+ }
+ m_pMetrics->m_bKernPairsQueried = true;
+
+ freeFontInfo( pInfo );
+ return true;
+}
+
+// -------------------------------------------------------------------------
+
+/*
+ * one instance only
+ */
+PrintFontManager& PrintFontManager::get()
+{
+ static PrintFontManager* theManager = NULL;
+ if( ! theManager )
+ {
+ theManager = new PrintFontManager();
+ theManager->initialize();
+ }
+ return *theManager;
+}
+
+// -------------------------------------------------------------------------
+
+/*
+ * the PrintFontManager
+ */
+
+PrintFontManager::PrintFontManager() :
+ m_pAtoms( new MultiAtomProvider() ),
+ m_nNextFontID( 1 ),
+ m_nNextDirAtom( 1 )
+{
+}
+
+// -------------------------------------------------------------------------
+
+PrintFontManager::~PrintFontManager()
+{
+ for( ::std::hash_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
+ delete (*it).second;
+ delete m_pAtoms;
+}
+
+// -------------------------------------------------------------------------
+
+const OString& PrintFontManager::getDirectory( int nAtom ) const
+{
+ static OString aEmpty;
+ ::std::hash_map< int, OString >::const_iterator it( m_aAtomToDir.find( nAtom ) );
+ return it != m_aAtomToDir.end() ? it->second : aEmpty;
+}
+
+// -------------------------------------------------------------------------
+
+int PrintFontManager::getDirectoryAtom( const OString& rDirectory, bool bCreate )
+{
+ int nAtom = 0;
+ ::std::hash_map< OString, int, OStringHash >::const_iterator it
+ ( m_aDirToAtom.find( rDirectory ) );
+ if( it != m_aDirToAtom.end() )
+ nAtom = it->second;
+ else if( bCreate )
+ {
+ nAtom = m_nNextDirAtom++;
+ m_aDirToAtom[ rDirectory ] = nAtom;
+ m_aAtomToDir[ nAtom ] = rDirectory;
+ }
+ return nAtom;
+}
+
+// -------------------------------------------------------------------------
+
+int PrintFontManager::addFontFile( const ::rtl::OString& rFileName, int nFaceNum )
+{
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ INetURLObject aPath( OStringToOUString( rFileName, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL );
+ OString aName( OUStringToOString( aPath.GetName(), aEncoding ) );
+ OString aDir( OUStringToOString( aPath.GetPath(), aEncoding ) );
+
+ int nDirID = getDirectoryAtom( aDir, true );
+ fontID nFontId = findFontFileID( nDirID, aName );
+ if( !nFontId )
+ {
+ ::std::list< PrintFont* > aNewFonts;
+ if( analyzeFontFile( nDirID, aName, false, OString(), aNewFonts ) )
+ {
+ for( ::std::list< PrintFont* >::iterator it = aNewFonts.begin();
+ it != aNewFonts.end(); ++it )
+ m_aFonts[ nFontId = m_nNextFontID++ ] = *it;
+ }
+ }
+ return nFontId;
+}
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::analyzeFontFile( int nDirID, const OString& rFontFile, bool bReadFile, const OString& rXLFD, ::std::list< PrintFontManager::PrintFont* >& rNewFonts ) const
+{
+ rNewFonts.clear();
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+
+ OString aDir( getDirectory( nDirID ) );
+
+ ByteString aExt( rFontFile.getToken( rFontFile.getTokenCount( '.' )-1, '.' ) );
+ if( aExt.EqualsIgnoreCaseAscii( "pfb" ) || aExt.EqualsIgnoreCaseAscii( "pfa" ) )
+ {
+ // check for corresponding afm metric
+ // first look for an adjacent file
+
+ ByteString aName( rFontFile );
+ aName.Erase( aName.Len()-4 );
+ aName.Append( ".afm" );
+
+ ByteString aFilePath( aDir );
+ aFilePath.Append( '/' );
+ aFilePath.Append( aName );
+
+ ByteString aAfmFile;
+ if( access( aFilePath.GetBuffer(), F_OK ) )
+ {
+ // try in subdirectory afm instead
+ aFilePath = aDir;
+ aFilePath.Append( "/afm/" );
+ aFilePath.Append( aName );
+
+ if( ! access( aFilePath.GetBuffer(), F_OK ) )
+ {
+ aAfmFile = "afm/";
+ aAfmFile += aName;
+ }
+ }
+ else
+ aAfmFile = aName;
+
+ if( aAfmFile.Len() )
+ {
+ Type1FontFile* pFont = new Type1FontFile();
+ pFont->m_nDirectory = nDirID;
+
+ pFont->m_aFontFile = rFontFile;
+ pFont->m_aMetricFile = aAfmFile;
+
+ if( bReadFile )
+ {
+ if( ! pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms ) )
+ {
+ delete pFont;
+ pFont = NULL;
+ }
+ }
+ else
+ getFontAttributesFromXLFD( pFont, rXLFD );
+ if( pFont )
+ rNewFonts.push_back( pFont );
+ }
+ }
+ else if( aExt.EqualsIgnoreCaseAscii( "ttf" ) )
+ {
+ TrueTypeFontFile* pFont = new TrueTypeFontFile();
+ pFont->m_nDirectory = nDirID;
+ pFont->m_aFontFile = rFontFile;
+ pFont->m_nCollectionEntry = -1;
+
+ if( bReadFile )
+ {
+ if( ! analyzeTrueTypeFile( pFont ) )
+ {
+ delete pFont;
+ pFont = NULL;
+ }
+ }
+ else
+ getFontAttributesFromXLFD( pFont, rXLFD );
+ if( pFont )
+ rNewFonts.push_back( pFont );
+ }
+ else if( aExt.EqualsIgnoreCaseAscii( "ttc" ) )
+ {
+ OString aFullPath( aDir );
+ aFullPath += "/";
+ aFullPath += rFontFile;
+
+ // get number of ttc entries
+ int nLength = CountTTCFonts( aFullPath.getStr() );
+ if( nLength )
+ {
+#ifdef DEBUG
+ fprintf( stderr, "%s contains %d fonts\n XLFD=\"%s\"\n", aFullPath.getStr(), nLength, rXLFD.getStr() );
+#endif
+ for( int i = 0; i < nLength; i++ )
+ {
+ TrueTypeFontFile* pFont = new TrueTypeFontFile();
+ pFont->m_nDirectory = nDirID;
+ pFont->m_aFontFile = rFontFile;
+ pFont->m_nCollectionEntry = i;
+ getFontAttributesFromXLFD( pFont, rXLFD );
+ if( ! analyzeTrueTypeFile( pFont ) )
+ {
+ delete pFont;
+ pFont = NULL;
+ }
+ else
+ rNewFonts.push_back( pFont );
+ }
+ }
+#ifdef DEBUG
+ else
+ fprintf( stderr, "CountTTCFonts( \"%s/%s\" ) failed\n", getDirectory(nDirID).getStr(), rFontFile.getStr() );
+#endif
+ }
+ return ! rNewFonts.empty();
+}
+
+// -------------------------------------------------------------------------
+
+fontID PrintFontManager::findFontBuiltinID( int nPSNameAtom ) const
+{
+ fontID nID = 0;
+ ::std::hash_map< int, PrintFont* >::const_iterator it;
+ for( it = m_aFonts.begin(); nID == 0 && it != m_aFonts.end(); ++it )
+ {
+ if( it->second->m_eType == fonttype::Builtin &&
+ it->second->m_nPSName == nPSNameAtom )
+ nID = it->first;
+ }
+ return nID;
+}
+
+// -------------------------------------------------------------------------
+
+fontID PrintFontManager::findFontFileID( int nDirID, const OString& rFontFile ) const
+{
+ fontID nID = 0;
+ ::std::hash_map< int, PrintFont* >::const_iterator it;
+ for( it = m_aFonts.begin(); nID == 0 && it != m_aFonts.end(); ++it )
+ {
+ switch( it->second->m_eType )
+ {
+ case fonttype::Type1:
+ {
+ Type1FontFile* const pFont = static_cast< Type1FontFile* const >((*it).second);
+ if( pFont->m_nDirectory == nDirID &&
+ pFont->m_aFontFile == rFontFile )
+ nID = it->first;
+ }
+ break;
+ case fonttype::TrueType:
+ {
+ TrueTypeFontFile* const pFont = static_cast< TrueTypeFontFile* const >((*it).second);
+ if( pFont->m_nDirectory == nDirID &&
+ pFont->m_aFontFile == rFontFile )
+ nID = it->first;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ return nID;
+}
+
+// -------------------------------------------------------------------------
+
+void PrintFontManager::getFontAttributesFromXLFD( PrintFont* pFont, const ByteString& rXLFD ) const
+{
+ if( rXLFD.GetTokenCount( '-' ) != 15 )
+ return;
+
+ ByteString aFamilyXLFD( WhitespaceToSpace( rXLFD.GetToken( 2, '-' ) ) );
+ int nTokens = aFamilyXLFD.GetTokenCount( ' ' );
+ ByteString aFamilyName;
+ for( int nToken = 0; nToken < nTokens; nToken++ )
+ {
+ ByteString aToken( aFamilyXLFD.GetToken( nToken, ' ' ) );
+ ByteString aNewToken( aToken.GetChar( 0 ) );
+ aNewToken.ToUpperAscii();
+ aNewToken += aToken.Copy( 1 );
+ if( nToken > 0 )
+ aFamilyName.Append( ' ' );
+ aFamilyName += aNewToken;
+ }
+
+ pFont->m_nFamilyName =
+ m_pAtoms->getAtom( ATOM_FAMILYNAME,
+ String( aFamilyName, RTL_TEXTENCODING_ISO_8859_1 ),
+ sal_True );
+ ByteString aToken;
+
+ // evaluate weight
+ aToken = rXLFD.GetToken( 3, '-' ).ToLowerAscii();
+ pFont->m_eWeight = parseWeight( aToken );
+
+ // evaluate slant
+ aToken = rXLFD.GetToken( 4, '-' );
+ pFont->m_eItalic = parseItalic( aToken );
+
+ // evaluate width
+ aToken = rXLFD.GetToken( 5, '-' ).ToLowerAscii();
+ pFont->m_eWidth = parseWidth( aToken );
+
+ // evaluate pitch
+ aToken = rXLFD.GetToken( 11, '-' ).ToLowerAscii();
+ if( aToken.Equals( "c" ) || aToken.Equals( "m" ) )
+ pFont->m_ePitch = pitch::Fixed;
+ else
+ pFont->m_ePitch = pitch::Variable;
+
+ // get encoding
+ aToken = rXLFD.GetToken( 6, '-' ).ToLowerAscii();
+ if( aToken.Search( "symbol" ) != STRING_NOTFOUND )
+ pFont->m_aEncoding = RTL_TEXTENCODING_SYMBOL;
+ else
+ {
+ aToken =WhitespaceToSpace( rXLFD.GetToken( 14 ) );
+ if( aToken.EqualsIgnoreCaseAscii( "symbol" ) )
+ pFont->m_aEncoding = RTL_TEXTENCODING_SYMBOL;
+ else
+ {
+ aToken = rXLFD.GetToken( 13, '-' );
+ aToken += '-';
+ aToken += WhitespaceToSpace( rXLFD.GetToken( 14, '-' ) );
+ pFont->m_aEncoding = rtl_getTextEncodingFromUnixCharset( aToken.GetBuffer() );
+ }
+ }
+
+ // handle iso8859-1 as ms1252 to fill the "gap" starting at 0x80
+ if( pFont->m_aEncoding == RTL_TEXTENCODING_ISO_8859_1 )
+ pFont->m_aEncoding = RTL_TEXTENCODING_MS_1252;
+
+ switch( pFont->m_eType )
+ {
+ case fonttype::Type1:
+ static_cast<Type1FontFile*>(pFont)->m_aXLFD = rXLFD;
+ break;
+ case fonttype::TrueType:
+ static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD = rXLFD;
+ break;
+ }
+}
+
+// -------------------------------------------------------------------------
+
+ByteString PrintFontManager::getXLFD( PrintFont* pFont ) const
+{
+ if( pFont->m_eType == fonttype::Type1 )
+ {
+ if( static_cast<Type1FontFile*>(pFont)->m_aXLFD.getLength() )
+ return static_cast<Type1FontFile*>(pFont)->m_aXLFD;
+ }
+ if( pFont->m_eType == fonttype::TrueType )
+ {
+ if( static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD.getLength() )
+ return static_cast<TrueTypeFontFile*>(pFont)->m_aXLFD;
+ }
+
+ ByteString aXLFD( "-misc-" );
+ aXLFD += ByteString( String( m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ) ), RTL_TEXTENCODING_ISO_8859_1 );
+ aXLFD += '-';
+ switch( pFont->m_eWeight )
+ {
+ case weight::Thin: aXLFD += "thin";break;
+ case weight::UltraLight: aXLFD += "ultralight";break;
+ case weight::Light: aXLFD += "light";break;
+ case weight::SemiLight: aXLFD += "semilight";break;
+ case weight::Normal: aXLFD += "normal";break;
+ case weight::Medium: aXLFD += "medium";break;
+ case weight::SemiBold: aXLFD += "semibold";break;
+ case weight::Bold: aXLFD += "bold";break;
+ case weight::UltraBold: aXLFD += "ultrabold";break;
+ case weight::Black: aXLFD += "black";break;
+ }
+ aXLFD += '-';
+ switch( pFont->m_eItalic )
+ {
+ case italic::Upright: aXLFD += 'r';break;
+ case italic::Oblique: aXLFD += 'o';break;
+ case italic::Italic: aXLFD += 'i';break;
+ }
+ aXLFD += '-';
+ switch( pFont->m_eWidth )
+ {
+ case width::UltraCondensed: aXLFD += "ultracondensed";break;
+ case width::ExtraCondensed: aXLFD += "extracondensed";break;
+ case width::Condensed: aXLFD += "condensed";break;
+ case width::SemiCondensed: aXLFD += "semicondensed";break;
+ case width::Normal: aXLFD += "normal";break;
+ case width::SemiExpanded: aXLFD += "semiexpanded";break;
+ case width::Expanded: aXLFD += "expanded";break;
+ case width::ExtraExpanded: aXLFD += "extraexpanded";break;
+ case width::UltraExpanded: aXLFD += "ultraexpanded";break;
+ }
+ aXLFD += "--0-0-0-0-";
+ aXLFD += pFont->m_ePitch == pitch::Fixed ? "m" : "p";
+ aXLFD += "-0-";
+ aXLFD += rtl_getBestUnixCharsetFromTextEncoding( pFont->m_aEncoding );
+
+ return aXLFD;
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::analyzeTrueTypeFile( PrintFont* pFont ) const
+{
+ bool bSuccess = false;
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ ByteString aFile = getFontFile( pFont );
+ TrueTypeFont* pTTFont = NULL;
+
+ TrueTypeFontFile* pTTFontFile = static_cast< TrueTypeFontFile* >(pFont);
+ int nFace = pTTFontFile->m_nCollectionEntry;
+ if( OpenTTFont( aFile.GetBuffer(), nFace < 0 ? 0 : nFace, &pTTFont ) == SF_OK )
+ {
+ TTGlobalFontInfo aInfo;
+ GetTTGlobalFontInfo( pTTFont, & aInfo );
+
+ // set family name from XLFD if possible
+ if( ! pFont->m_nFamilyName )
+ {
+ if( ! aInfo.family || ! *aInfo.family )
+ // poor font does not have a family name
+ // name it to file name minus ".tt{f|c}"
+ pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, OStringToOUString( pTTFontFile->m_aFontFile.copy( 0, pTTFontFile->m_aFontFile.getLength()-4 ), aEncoding ) );
+ else
+ pFont->m_nFamilyName = m_pAtoms->getAtom( ATOM_FAMILYNAME, String( ByteString( aInfo.family ), aEncoding ), sal_True );
+ }
+
+
+ pFont->m_nPSName = m_pAtoms->getAtom( ATOM_PSNAME, String( ByteString( aInfo.psname ), aEncoding ), sal_True );
+ switch( aInfo.weight )
+ {
+ case FW_THIN: pFont->m_eWeight = weight::Thin; break;
+ case FW_EXTRALIGHT: pFont->m_eWeight = weight::UltraLight; break;
+ case FW_LIGHT: pFont->m_eWeight = weight::Light; break;
+ case FW_MEDIUM: pFont->m_eWeight = weight::Medium; break;
+ case FW_SEMIBOLD: pFont->m_eWeight = weight::SemiBold; break;
+ case FW_BOLD: pFont->m_eWeight = weight::Bold; break;
+ case FW_EXTRABOLD: pFont->m_eWeight = weight::UltraBold; break;
+ case FW_BLACK: pFont->m_eWeight = weight::Black; break;
+
+ case FW_NORMAL:
+ default: pFont->m_eWeight = weight::Normal; break;
+ }
+
+ switch( aInfo.width )
+ {
+ case FWIDTH_ULTRA_CONDENSED: pFont->m_eWidth = width::UltraCondensed; break;
+ case FWIDTH_EXTRA_CONDENSED: pFont->m_eWidth = width::ExtraCondensed; break;
+ case FWIDTH_CONDENSED: pFont->m_eWidth = width::Condensed; break;
+ case FWIDTH_SEMI_CONDENSED: pFont->m_eWidth = width::SemiCondensed; break;
+ case FWIDTH_SEMI_EXPANDED: pFont->m_eWidth = width::SemiExpanded; break;
+ case FWIDTH_EXPANDED: pFont->m_eWidth = width::Expanded; break;
+ case FWIDTH_EXTRA_EXPANDED: pFont->m_eWidth = width::ExtraExpanded; break;
+ case FWIDTH_ULTRA_EXPANDED: pFont->m_eWidth = width::UltraExpanded; break;
+
+ case FWIDTH_NORMAL:
+ default: pFont->m_eWidth = width::Normal; break;
+ }
+
+ pFont->m_ePitch = aInfo.pitch ? pitch::Fixed : pitch::Variable;
+ pFont->m_eItalic = aInfo.italicAngle == 0 ? italic::Upright : ( aInfo.italicAngle < 0 ? italic::Italic : italic::Oblique );
+
+ pFont->m_aEncoding = aInfo.symbolEncoded ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UCS2;
+
+ pFont->m_aGlobalMetricY.width = pFont->m_aGlobalMetricX.width = aInfo.xMax - aInfo.xMin;
+ pFont->m_aGlobalMetricY.height = pFont->m_aGlobalMetricX.height = aInfo.yMax - aInfo.yMin;
+
+ if( aInfo.winAscent && aInfo.winDescent )
+ {
+ pFont->m_nAscend = aInfo.winAscent;
+ pFont->m_nDescend = aInfo.winDescent;
+ pFont->m_nLeading = pFont->m_nAscend + pFont->m_nDescend - 1000;
+ }
+ else if( aInfo.typoAscender && aInfo.typoDescender )
+ {
+ pFont->m_nLeading = aInfo.typoLineGap;
+ pFont->m_nAscend = aInfo.typoAscender;
+ pFont->m_nDescend = -aInfo.typoDescender;
+ }
+ else
+ {
+ pFont->m_nLeading = aInfo.linegap;
+ pFont->m_nAscend = aInfo.ascender;
+ pFont->m_nDescend = -aInfo.descender;
+ }
+
+ // last try: font bounding box
+ if( pFont->m_nAscend == 0 )
+ pFont->m_nAscend = aInfo.yMax;
+ if( pFont->m_nDescend == 0 )
+ pFont->m_nDescend = -aInfo.yMin;
+ if( pFont->m_nLeading == 0 )
+ pFont->m_nLeading = 15 * (pFont->m_nAscend+pFont->m_nDescend) / 100;
+
+ if( pFont->m_nAscend && pFont->m_nDescend )
+ pFont->m_aGlobalMetricX.height = pFont->m_aGlobalMetricY.height = pFont->m_nAscend + pFont->m_nDescend;
+
+ CloseTTFont( pTTFont );
+ bSuccess = true;
+ }
+#ifdef DEBUG
+ else
+ fprintf( stderr, "could not OpenTTFont \"%s\"\n", aFile.GetBuffer() );
+#endif
+
+ return bSuccess;
+}
+
+// -------------------------------------------------------------------------
+
+static void normPath( ByteString& rPath )
+{
+ while( rPath.SearchAndReplace( "//", "/" ) != STRING_NOTFOUND )
+ ;
+ if( rPath.Len() > 0 && rPath.GetChar( rPath.Len()-1 ) == '/' )
+ rPath.Erase( rPath.Len()-1 );
+}
+
+
+void PrintFontManager::initialize( void* pInitDisplay )
+{
+ long aDirEntBuffer[ (sizeof(struct dirent)+_PC_NAME_MAX)+1 ];
+
+ // initialize may be called twice in the future
+ {
+ for( ::std::hash_map< fontID, PrintFont* >::const_iterator it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
+ delete (*it).second;
+ m_nNextFontID = 1;
+ m_aFonts.clear();
+ m_aFontDirectories.clear();
+ }
+
+#ifdef DEBUG
+ clock_t aStart;
+ clock_t aStep1;
+ clock_t aStep2;
+ clock_t aStep3;
+ int nBuiltinFonts = 0;
+
+ struct tms tms;
+
+ aStart = times( &tms );
+#endif
+
+ // part one - look for downloadable fonts
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ static const char* pSalPrivatePath = getenv( "SAL_FONTPATH_PRIVATE" );
+
+ // search for the fonts in SAL_PRIVATE_FONTPATH first; those are
+ // the TrueType fonts installed with the office
+ if( pSalPrivatePath )
+ {
+ ByteString aPath( pSalPrivatePath );
+ int nTokens = aPath.GetTokenCount( ';' );
+ for( int i = 0; i < nTokens; i++ )
+ {
+ ByteString aToken( aPath.GetToken( i, ';' ) );
+ normPath( aToken );
+ m_aFontDirectories.push_back( aToken );
+ }
+ }
+
+ Display *pDisplay = (Display*)pInitDisplay;
+
+ if( ! pDisplay )
+ pDisplay = XOpenDisplay( NULL );
+
+
+ // get font paths to look for fonts
+ int nPaths = 0, i;
+ char** pPaths = XGetFontPath( pDisplay, &nPaths );
+
+ for( i = 0; i < nPaths; i++ )
+ {
+ ByteString aPath( pPaths[i] );
+ normPath( aPath );
+ m_aFontDirectories.push_back( aPath );
+ }
+
+ if( nPaths )
+ XFreeFontPath( pPaths );
+
+ if( ! pInitDisplay )
+ XCloseDisplay( pDisplay );
+
+ // insert some standard directories
+ m_aFontDirectories.push_back( "/usr/openwin/lib/X11/fonts/Type1" );
+ m_aFontDirectories.push_back( "/usr/openwin/lib/X11/fonts/Type1/sun" );
+ m_aFontDirectories.push_back( "/usr/X11R6/lib/X11/fonts/Type1" );
+#ifdef SOLARIS
+
+ /* cde specials, from /usr/dt/bin/Xsession: here are the good fonts,
+ the OWfontpath file may contain as well multiple lines as a comma
+ separated list of fonts in each line. to make it even more weird
+ environment variables are allowed as well */
+
+ const char* lang = getenv("LANG");
+ if ( lang != NULL )
+ {
+ String aOpenWinDir( String::CreateFromAscii( "/usr/openwin/lib/locale/" ) );
+ aOpenWinDir.AppendAscii( lang );
+ aOpenWinDir.AppendAscii( "/OWfontpath" );
+
+ SvFileStream aStream( aOpenWinDir, STREAM_READ );
+
+ // TODO: replace environment variables
+ while( aStream.IsOpen() && ! aStream.IsEof() )
+ {
+ ByteString aLine;
+ aStream.ReadLine( aLine );
+ normPath( aLine );
+ m_aFontDirectories.push_back( aLine );
+ }
+ }
+
+#endif /* SOLARIS */
+
+ // search for font files in each path
+ ::std::list< OString >::iterator dir_it;
+ for( dir_it = m_aFontDirectories.begin(); dir_it != m_aFontDirectories.end(); ++dir_it )
+ {
+ OString aPath( *dir_it );
+ // there may be ":unscaled" directories (see XFree86)
+ // it should be safe to ignore them since they should not
+ // contain any of our recognbizeable fonts
+ OUString aUniPath;
+ FileBase::normalizePath( OStringToOUString( aPath, aEncoding ), aUniPath );
+
+ // read fonts.dir if possible
+ ::std::hash_map< OString, ByteString, OStringHash > aFontsDir;
+ ByteString aGccDummy( aPath );
+ String aFontsDirPath( aGccDummy, aEncoding );
+ aFontsDirPath.AppendAscii( "/fonts.dir" );
+ int nDirID = getDirectoryAtom( aPath, true );
+ SvFileStream aStream( aFontsDirPath, STREAM_READ );
+ if( aStream.IsOpen() )
+ {
+ ByteString aLine;
+ while( ! aStream.IsEof() )
+ {
+ aStream.ReadLine( aLine );
+ ByteString aFileName( GetCommandLineToken( 0, aLine ) );
+ ByteString aXLFD( aLine.Copy( aFileName.Len() ) );
+ if( aFileName.Len() && aXLFD.Len() )
+ aFontsDir[ aFileName ] = aXLFD;
+ }
+ }
+
+ DIR* pDIR = opendir( aPath.getStr() );
+ struct dirent* pEntry = (struct dirent*)aDirEntBuffer;
+ if( pDIR )
+ {
+ while( ! readdir_r( pDIR, (struct dirent*)aDirEntBuffer, &pEntry ) && pEntry )
+ {
+ OString aFileName( pEntry->d_name );
+ struct stat aStat;
+ ByteString aFilePath( aPath );
+ aFilePath.Append( '/' );
+ aFilePath.Append( ByteString( aFileName ) );
+ if( ! stat( aFilePath.GetBuffer(), &aStat ) &&
+ S_ISREG( aStat.st_mode ) )
+ {
+ if( findFontFileID( nDirID, aFileName ) == 0 )
+ {
+ ByteString aXLFD;
+ ::std::hash_map< OString, ByteString, OStringHash >::const_iterator it =
+ aFontsDir.find( aFileName );
+ if( it != aFontsDir.end() )
+ aXLFD = (*it).second;
+
+ // fill in font attributes from XLFD rather
+ // than reading every file
+ ::std::list< PrintFont* > aNewFonts;
+ if( analyzeFontFile( nDirID, aFileName, aXLFD.Len() ? false : true, aXLFD, aNewFonts ) )
+ {
+ for( ::std::list< PrintFont* >::iterator it = aNewFonts.begin(); it != aNewFonts.end(); ++it )
+ {
+ m_aFonts[ m_nNextFontID++ ] = *it;
+#ifdef DEBUG
+ fprintf( stderr, "adding font \"%s\" from file \"%s/%s\"\n", OUStringToOString( m_pAtoms->getString( ATOM_FAMILYNAME, (*it)->m_nFamilyName ), RTL_TEXTENCODING_MS_1252 ).getStr(), aPath.getStr(), aFileName.getStr() );
+#endif
+ }
+ }
+ }
+ }
+ }
+ closedir( pDIR );
+ }
+ }
+
+#ifdef DEBUG
+ aStep1 = times( &tms );
+#endif
+
+ // part two - look for metrics for builtin printer fonts
+ OUString aPath( getPrinterPath() );
+ nPaths = aPath.getTokenCount( ':' );
+ for( i = 0; i < nPaths; i++ )
+ {
+ OString aDir( OUStringToOString( aPath.getToken( i, ':' ), aEncoding ) );
+ aDir += "/"PRINTER_METRICDIR;
+ DIR* pDIR = opendir( aDir.getStr() );
+ if( pDIR )
+ {
+ struct dirent* pDirEntry = (struct dirent*)aDirEntBuffer;
+ OString aSysDir( aDir );
+ int nDirAtom = getDirectoryAtom( aDir, true );
+
+ // get cache information
+ aSysDir += "/builtincache";
+ struct stat aStat;
+ time_t nCacheDate = 0;
+ if( ! stat( aSysDir.getStr(), &aStat ) )
+ nCacheDate = aStat.st_mtime;
+ Config aCache( OStringToOUString( aSysDir, aEncoding ) );
+
+ while( ! readdir_r( pDIR, (struct dirent*)aDirEntBuffer, &pDirEntry ) && pDirEntry )
+ {
+ ByteString aFile( aDir );
+ aFile += '/';
+ aFile += pDirEntry->d_name;
+ if( ! stat( aFile.GetBuffer(), &aStat )
+ && S_ISREG( aStat.st_mode )
+ )
+ {
+ OString aFileName( pDirEntry->d_name, strlen( pDirEntry->d_name ) );
+ OString aExt( aFileName.getToken( aFileName.getTokenCount( '.' )-1, '.' ) );
+ if( aExt.equalsIgnoreCase( "afm" ) )
+ {
+ BuiltinFont* pFont = new BuiltinFont;
+ pFont->m_nDirectory = nDirAtom;
+ pFont->m_aMetricFile = aFileName;
+
+ // first try the cache
+ bool bWasCached = false;
+ if( aCache.HasGroup( aFileName ) )
+ {
+ aCache.SetGroup( aFileName );
+ if( aStat.st_mtime <= nCacheDate )
+ {
+ bWasCached = true;
+ pFont->m_nFamilyName= m_pAtoms->getAtom( ATOM_FAMILYNAME, String( aCache.ReadKey( "FamilyName" ), RTL_TEXTENCODING_UTF8 ), sal_True );
+ pFont->m_nPSName = m_pAtoms->getAtom( ATOM_PSNAME, String( aCache.ReadKey( "PSName" ), RTL_TEXTENCODING_UTF8 ), sal_True );
+ pFont->m_eItalic = (italic::type)aCache.ReadKey( "Italic" ).ToInt32();
+ pFont->m_eWidth = (width::type)aCache.ReadKey( "Width" ).ToInt32();
+ pFont->m_ePitch = (pitch::type)aCache.ReadKey( "Pitch" ).ToInt32();
+ pFont->m_eWeight = (weight::type)aCache.ReadKey( "Weight" ).ToInt32();
+ pFont->m_aEncoding = (rtl_TextEncoding)aCache.ReadKey( "Encoding" ).ToInt32();
+ pFont->m_nAscend = aCache.ReadKey( "Ascend" ).ToInt32();
+ pFont->m_nDescend = aCache.ReadKey( "Descend" ).ToInt32();
+ pFont->m_nLeading = aCache.ReadKey( "Leading" ).ToInt32();
+ ByteString aValue = aCache.ReadKey( "GlobalMetrics" );
+ pFont->m_aGlobalMetricX.width = aValue.GetToken( 0, ',' ).ToInt32();
+ pFont->m_aGlobalMetricX.height = aValue.GetToken( 1, ',' ).ToInt32();
+ pFont->m_aGlobalMetricY.width = aValue.GetToken( 2, ',' ).ToInt32();
+ pFont->m_aGlobalMetricY.height = aValue.GetToken( 3, ',' ).ToInt32();
+ m_aFonts[ m_nNextFontID++ ] = pFont;
+#ifdef DEBUG
+ nBuiltinFonts++;
+#endif
+ }
+ }
+
+ if( ! bWasCached )
+ {
+ if( pFont->readAfmMetrics( aFile, m_pAtoms ) &&
+ findFontBuiltinID( pFont->m_nPSName ) == 0
+ )
+ {
+ m_aFonts[ m_nNextFontID++ ] = pFont;
+#ifdef DEBUG
+ nBuiltinFonts++;
+#endif
+
+ // update the cache
+ aCache.SetGroup( aFileName );
+ aCache.WriteKey( "FamilyName", ByteString( String( m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ) ), RTL_TEXTENCODING_UTF8 ) );
+ aCache.WriteKey( "PSName", ByteString( String( m_pAtoms->getString( ATOM_PSNAME, pFont->m_nPSName ) ), RTL_TEXTENCODING_UTF8 ) );
+ aCache.WriteKey( "Italic", ByteString::CreateFromInt32( (int)pFont->m_eItalic ) );
+ aCache.WriteKey( "Width", ByteString::CreateFromInt32( (int)pFont->m_eWidth ) );
+ aCache.WriteKey( "Weight", ByteString::CreateFromInt32( (int)pFont->m_eWeight ) );
+ aCache.WriteKey( "Pitch", ByteString::CreateFromInt32( (int)pFont->m_ePitch ) );
+ aCache.WriteKey( "Encoding", ByteString::CreateFromInt32( (int)pFont->m_aEncoding ) );
+ aCache.WriteKey( "Ascend", ByteString::CreateFromInt32( pFont->m_nAscend ) );
+ aCache.WriteKey( "Descend", ByteString::CreateFromInt32( pFont->m_nDescend ) );
+ aCache.WriteKey( "Leading", ByteString::CreateFromInt32( pFont->m_nLeading ) );
+ ByteString aValue( ByteString::CreateFromInt32( pFont->m_aGlobalMetricX.width ) );
+ aValue += ',';
+ aValue += ByteString::CreateFromInt32( pFont->m_aGlobalMetricX.height );
+ aValue += ',';
+ aValue += ByteString::CreateFromInt32( pFont->m_aGlobalMetricY.width );
+ aValue += ',';
+ aValue += ByteString::CreateFromInt32( pFont->m_aGlobalMetricY.height );
+ aCache.WriteKey( "GlobalMetrics", aValue );
+ }
+ else
+ delete pFont;
+ }
+ }
+ }
+ }
+ closedir( pDIR );
+ }
+ }
+
+#ifdef DEBUG
+ aStep2 = times( &tms );
+#endif
+
+ // part three - fill in family styles
+ ::std::hash_map< fontID, PrintFont* >::iterator font_it;
+ for (font_it = m_aFonts.begin(); font_it != m_aFonts.end(); ++font_it)
+ {
+ ::std::hash_map< int, family::type >::const_iterator it =
+ m_aFamilyTypes.find( font_it->second->m_nFamilyName );
+ if (it != m_aFamilyTypes.end())
+ continue;
+ const ::rtl::OUString& rFamily =
+ m_pAtoms->getString( ATOM_FAMILYNAME, font_it->second->m_nFamilyName);
+ family::type eType = matchFamilyName( rFamily );
+ m_aFamilyTypes[ font_it->second->m_nFamilyName ] = eType;
+ }
+
+#ifdef DEBUG
+ aStep3 = times( &tms );
+ fprintf( stderr, "PrintFontManager::initialize: collected %d fonts (%d builtin)\n", m_aFonts.size(), nBuiltinFonts );
+ fprintf( stderr, "Step 1 took %lf seconds\n", (double)(aStep1 - aStart)/(double)CLK_TCK );
+ fprintf( stderr, "Step 2 took %lf seconds\n", (double)(aStep2 - aStep1)/(double)CLK_TCK );
+ fprintf( stderr, "Step 3 took %lf seconds\n", (double)(aStep3 - aStep2)/(double)CLK_TCK );
+#endif
+}
+
+// -------------------------------------------------------------------------
+inline bool
+equalPitch (psp::pitch::type from, psp::pitch::type to)
+{
+ return from == to;
+}
+
+inline bool
+equalWeight (psp::weight::type from, psp::weight::type to)
+{
+ return from > to ? (from - to) <= 3 : (to - from) <= 3;
+}
+
+inline bool
+equalItalic (psp::italic::type from, psp::italic::type to)
+{
+ if ( (from == psp::italic::Italic) || (from == psp::italic::Oblique) )
+ return (to == psp::italic::Italic) || (to == psp::italic::Oblique);
+ return to == from;
+}
+inline bool
+equalEncoding (rtl_TextEncoding from, rtl_TextEncoding to)
+{
+ if ((from == RTL_TEXTENCODING_ISO_8859_1) || (from == RTL_TEXTENCODING_MS_1252))
+ return (to == RTL_TEXTENCODING_ISO_8859_1) || (to == RTL_TEXTENCODING_MS_1252);
+ return from == to;
+}
+
+void PrintFontManager::getFontList( ::std::list< fontID >& rFontIDs, const PPDParser* pParser ) const
+{
+ rFontIDs.clear();
+ ::std::hash_map< fontID, PrintFont* >::const_iterator it;
+ ::std::list< PrintFont* > aBuiltinFonts;
+
+ for( it = m_aFonts.begin(); it != m_aFonts.end(); ++it )
+ {
+ if( pParser && it->second->m_eType == fonttype::Builtin )
+ {
+ int nFonts = pParser->getFonts();
+ String aPSName = m_pAtoms->getString( ATOM_PSNAME, it->second->m_nPSName );
+ for( int j = 0; j < nFonts; j++ )
+ {
+ if( aPSName.Equals( pParser->getFont( j ) ) )
+ {
+ rFontIDs.push_back( it->first );
+ aBuiltinFonts.push_back( it->second );
+ break;
+ }
+ }
+ }
+ else
+ rFontIDs.push_back( it->first );
+ }
+
+ if( pParser )
+ {
+ // remove doubles for builtins
+ ::std::list< fontID >::iterator font_it;
+ ::std::list< fontID >::iterator temp_it;
+ font_it = rFontIDs.begin();
+ while( font_it != rFontIDs.end() )
+ {
+ temp_it = font_it;
+ ++temp_it;
+ PrintFont* pFont = getFont( *font_it );
+ if( pFont->m_eType != fonttype::Builtin )
+ {
+ const OUString& rFontFamily( m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName ) );
+
+ for( ::std::list< PrintFont* >::const_iterator bit = aBuiltinFonts.begin();
+ bit != aBuiltinFonts.end(); ++bit )
+ {
+ if( ! equalItalic (pFont->m_eItalic, (*bit)->m_eItalic) )
+ continue;
+ if( ! equalWeight (pFont->m_eWeight, (*bit)->m_eWeight) )
+ continue;
+ if( ! equalPitch (pFont->m_ePitch, (*bit)->m_ePitch) )
+ continue;
+ if( ! equalEncoding(pFont->m_aEncoding, (*bit)->m_aEncoding) )
+ continue;
+ const OUString& rBuiltinFamily( m_pAtoms->getString( ATOM_FAMILYNAME, (*bit)->m_nFamilyName ) );
+ if( rFontFamily.equalsIgnoreCase( rBuiltinFamily ) )
+ {
+ // remove double
+ rFontIDs.erase( font_it );
+ break;
+ }
+ }
+ }
+ font_it = temp_it;
+ }
+ }
+}
+
+// -------------------------------------------------------------------------
+
+void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, FastPrintFontInfo& rInfo ) const
+{
+ ::std::hash_map< int, family::type >::const_iterator style_it =
+ m_aFamilyTypes.find( pFont->m_nFamilyName );
+ rInfo.m_eType = pFont->m_eType;
+ rInfo.m_aFamilyName = m_pAtoms->getString( ATOM_FAMILYNAME, pFont->m_nFamilyName );
+ rInfo.m_eFamilyStyle = style_it != m_aFamilyTypes.end() ? style_it->second : family::Unknown;
+ rInfo.m_eItalic = pFont->m_eItalic;
+ rInfo.m_eWidth = pFont->m_eWidth;
+ rInfo.m_eWeight = pFont->m_eWeight;
+ rInfo.m_ePitch = pFont->m_ePitch;
+ rInfo.m_aEncoding = pFont->m_aEncoding;
+}
+
+// -------------------------------------------------------------------------
+
+void PrintFontManager::fillPrintFontInfo( PrintFont* pFont, PrintFontInfo& rInfo ) const
+{
+ if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
+ {
+ // might be a truetype font not analyzed or type1 without metrics read
+ if( pFont->m_eType == fonttype::Type1 )
+ pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms );
+ else if( pFont->m_eType == fonttype::TrueType )
+ analyzeTrueTypeFile( pFont );
+ }
+
+ fillPrintFontInfo( pFont, static_cast< FastPrintFontInfo& >( rInfo ) );
+
+ rInfo.m_nAscend = pFont->m_nAscend;
+ rInfo.m_nDescend = pFont->m_nDescend;
+ rInfo.m_nLeading = pFont->m_nLeading;
+ rInfo.m_nWidth = pFont->m_aGlobalMetricX.width < pFont->m_aGlobalMetricY.width ? pFont->m_aGlobalMetricY.width : pFont->m_aGlobalMetricX.width;
+}
+
+// -------------------------------------------------------------------------
+
+void PrintFontManager::getFontListWithInfo( ::std::list< PrintFontInfo >& rFonts, const PPDParser* pParser ) const
+{
+ rFonts.clear();
+ ::std::list< fontID > aFontList;
+ getFontList( aFontList, pParser );
+
+ ::std::list< fontID >::iterator it;
+ for( it = aFontList.begin(); it != aFontList.end(); ++it )
+ {
+ PrintFontInfo aInfo;
+ aInfo.m_nID = *it;
+ fillPrintFontInfo( getFont( *it ), aInfo );
+ rFonts.push_back( aInfo );
+ }
+}
+
+// -------------------------------------------------------------------------
+
+void PrintFontManager::getFontListWithFastInfo( ::std::list< FastPrintFontInfo >& rFonts, const PPDParser* pParser ) const
+{
+ rFonts.clear();
+ ::std::list< fontID > aFontList;
+ getFontList( aFontList, pParser );
+
+ ::std::list< fontID >::iterator it;
+ for( it = aFontList.begin(); it != aFontList.end(); ++it )
+ {
+ FastPrintFontInfo aInfo;
+ aInfo.m_nID = *it;
+ fillPrintFontInfo( getFont( *it ), aInfo );
+ rFonts.push_back( aInfo );
+ }
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::getFontInfo( fontID nFontID, PrintFontInfo& rInfo ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ if( pFont )
+ {
+ rInfo.m_nID = nFontID;
+ fillPrintFontInfo( pFont, rInfo );
+ }
+ return pFont ? true : false;
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::getFontFastInfo( fontID nFontID, FastPrintFontInfo& rInfo ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ if( pFont )
+ {
+ rInfo.m_nID = nFontID;
+ fillPrintFontInfo( pFont, rInfo );
+ }
+ return pFont ? true : false;
+}
+
+// -------------------------------------------------------------------------
+
+family::type PrintFontManager::matchFamilyName( const ::rtl::OUString& rFamily ) const
+{
+ typedef struct {
+ const char* mpName;
+ sal_uInt16 mnLength;
+ family::type meType;
+ } family_t;
+
+#define InitializeClass( p, a ) p, sizeof(p) - 1, a
+ const family_t pFamilyMatch[] = {
+ { InitializeClass( "arial", family::Swiss ) },
+ { InitializeClass( "arioso", family::Script ) },
+ { InitializeClass( "avant garde", family::Swiss ) },
+ { InitializeClass( "avantgarde", family::Swiss ) },
+ { InitializeClass( "bembo", family::Roman ) },
+ { InitializeClass( "bookman", family::Roman ) },
+ { InitializeClass( "conga", family::Roman ) },
+ { InitializeClass( "courier", family::Modern ) },
+ { InitializeClass( "curl", family::Script ) },
+ { InitializeClass( "fixed", family::Modern ) },
+ { InitializeClass( "gill", family::Swiss ) },
+ { InitializeClass( "helmet", family::Modern ) },
+ { InitializeClass( "helvetica", family::Swiss ) },
+ { InitializeClass( "international", family::Modern ) },
+ { InitializeClass( "lucida", family::Swiss ) },
+ { InitializeClass( "new century schoolbook", family::Roman ) },
+ { InitializeClass( "palatino", family::Roman ) },
+ { InitializeClass( "roman", family::Roman ) },
+ { InitializeClass( "sans serif", family::Swiss ) },
+ { InitializeClass( "sansserif", family::Swiss ) },
+ { InitializeClass( "serf", family::Roman ) },
+ { InitializeClass( "serif", family::Roman ) },
+ { InitializeClass( "times", family::Roman ) },
+ { InitializeClass( "utopia", family::Roman ) },
+ { InitializeClass( "zapf chancery", family::Script ) },
+ { InitializeClass( "zapfchancery", family::Script ) }
+ };
+
+ rtl::OString aFamily = rtl::OUStringToOString( rFamily, RTL_TEXTENCODING_ISO_8859_1 );
+ sal_uInt32 nLower = 0;
+ sal_uInt32 nUpper = sizeof(pFamilyMatch) / sizeof(pFamilyMatch[0]);
+
+ while( nLower < nUpper )
+ {
+ sal_uInt32 nCurrent = (nLower + nUpper) / 2;
+ const family_t* pHaystack = pFamilyMatch + nCurrent;
+ sal_Int32 nComparison = rtl_str_compareIgnoreCase_WithLength(
+ aFamily.getStr(), pHaystack->mpName, pHaystack->mnLength );
+
+ if( nComparison < 0 )
+ nUpper = nCurrent;
+ else
+ if( nComparison > 0 )
+ nLower = nCurrent + 1;
+ else
+ return pHaystack->meType;
+ }
+
+ return family::Unknown;
+}
+
+// -------------------------------------------------------------------------
+
+family::type PrintFontManager::getFontFamilyType( fontID nFontID ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ if( !pFont )
+ return family::Unknown;
+
+ ::std::hash_map< int, family::type >::const_iterator it =
+ m_aFamilyTypes.find( pFont->m_nFamilyName );
+ return (it != m_aFamilyTypes.end()) ? it->second : family::Unknown;
+}
+
+
+// -------------------------------------------------------------------------
+
+const ::rtl::OUString& PrintFontManager::getFontFamily( fontID nFontID ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ return m_pAtoms->getString( ATOM_FAMILYNAME, pFont ? pFont->m_nFamilyName : INVALID_ATOM );
+}
+
+// -------------------------------------------------------------------------
+
+OString PrintFontManager::getAfmFile( PrintFont* pFont ) const
+{
+ OString aMetricPath;
+ if( pFont && pFont->m_eType == fonttype::Type1 )
+ {
+ Type1FontFile* pPSFont = static_cast< Type1FontFile* >(pFont);
+ ::std::hash_map< int, OString >::const_iterator it = m_aAtomToDir.find( pPSFont->m_nDirectory );
+ aMetricPath = it->second;
+ aMetricPath += "/";
+ aMetricPath += pPSFont->m_aMetricFile;
+ }
+ return aMetricPath;
+}
+
+// -------------------------------------------------------------------------
+
+OString PrintFontManager::getFontFile( PrintFont* pFont ) const
+{
+ OString aPath;
+
+ if( pFont && pFont->m_eType == fonttype::Type1 )
+ {
+ Type1FontFile* pPSFont = static_cast< Type1FontFile* >(pFont);
+ ::std::hash_map< int, OString >::const_iterator it = m_aAtomToDir.find( pPSFont->m_nDirectory );
+ aPath = it->second;
+ aPath += "/";
+ aPath += pPSFont->m_aFontFile;
+ }
+ else if( pFont && pFont->m_eType == fonttype::TrueType )
+ {
+ TrueTypeFontFile* pTTFont = static_cast< TrueTypeFontFile* >(pFont);
+ ::std::hash_map< int, OString >::const_iterator it = m_aAtomToDir.find( pTTFont->m_nDirectory );
+ aPath = it->second;
+ aPath += "/";
+ aPath += pTTFont->m_aFontFile;
+ }
+ return aPath;
+}
+
+// -------------------------------------------------------------------------
+
+const ::rtl::OUString& PrintFontManager::getPSName( fontID nFontID ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ if( pFont && pFont->m_nPSName == 0 )
+ {
+ if( pFont->m_eType == fonttype::TrueType )
+ analyzeTrueTypeFile( pFont );
+ }
+
+ return m_pAtoms->getString( ATOM_PSNAME, pFont ? pFont->m_nPSName : INVALID_ATOM );
+}
+
+// -------------------------------------------------------------------------
+
+const CharacterMetric& PrintFontManager::getGlobalFontMetric( fontID nFontID, bool bHorizontal ) const
+{
+ static CharacterMetric aMetric;
+ PrintFont* pFont = getFont( nFontID );
+ return pFont ? ( bHorizontal ? pFont->m_aGlobalMetricX : pFont->m_aGlobalMetricY ) : aMetric;
+}
+
+// -------------------------------------------------------------------------
+
+int PrintFontManager::getFontAscend( fontID nFontID ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
+ {
+ // might be a truetype font not yet analyzed
+ if( pFont->m_eType == fonttype::TrueType )
+ analyzeTrueTypeFile( pFont );
+ }
+ return pFont->m_nAscend;
+}
+
+// -------------------------------------------------------------------------
+
+int PrintFontManager::getFontDescend( fontID nFontID ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
+ {
+ // might be a truetype font not yet analyzed
+ if( pFont->m_eType == fonttype::TrueType )
+ analyzeTrueTypeFile( pFont );
+ }
+ return pFont->m_nDescend;
+}
+
+// -------------------------------------------------------------------------
+
+int PrintFontManager::getFontLeading( fontID nFontID ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
+ {
+ // might be a truetype font not yet analyzed
+ if( pFont->m_eType == fonttype::TrueType )
+ analyzeTrueTypeFile( pFont );
+ }
+ return pFont->m_nLeading;
+}
+
+// -------------------------------------------------------------------------
+
+OUString PrintFontManager::getFontXLFD( fontID nFontID ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ return pFont ? OStringToOUString( getXLFD( pFont ), RTL_TEXTENCODING_ISO_8859_1 ) : OUString();
+}
+
+// -------------------------------------------------------------------------
+
+const ::std::list< KernPair >& PrintFontManager::getKernPairs( fontID nFontID, bool bVertical ) const
+{
+ static ::std::list< KernPair > aEmpty;
+
+ PrintFont* pFont = getFont( nFontID );
+ if( ! pFont )
+ return aEmpty;
+
+ if( ! pFont->m_pMetrics || ! pFont->m_pMetrics->m_bKernPairsQueried )
+ pFont->queryMetricPage( 0, m_pAtoms );
+ if( ! pFont->m_pMetrics || ! pFont->m_pMetrics->m_bKernPairsQueried )
+ return aEmpty;
+ return bVertical ? pFont->m_pMetrics->m_aYKernPairs : pFont->m_pMetrics->m_aXKernPairs;
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::getMetrics( fontID nFontID, const sal_Unicode* pString, int nLen, CharacterMetric* pArray, bool bVertical ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ if( ! pFont )
+ return false;
+
+ if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
+ {
+ // might be a font not yet analyzed
+ if( pFont->m_eType == fonttype::Type1 )
+ pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms );
+ else if( pFont->m_eType == fonttype::TrueType )
+ analyzeTrueTypeFile( pFont );
+ }
+
+ for( int i = 0; i < nLen; i++ )
+ {
+ if( ! pFont->m_pMetrics ||
+ ! ( pFont->m_pMetrics->m_aPages[ pString[i] >> 11 ] & ( 1 << ( ( pString[i] >> 8 ) & 7 ) ) ) )
+ pFont->queryMetricPage( pString[i] >> 8, m_pAtoms );
+ pArray[i].width = pArray[i].height = -1;
+ if( pFont->m_pMetrics )
+ {
+ int effectiveCode = pString[i];
+ effectiveCode |= bVertical ? 1 << 16 : 0;
+ ::std::hash_map< int, CharacterMetric >::const_iterator it =
+ pFont->m_pMetrics->m_aMetrics.find( effectiveCode );
+ if( it != pFont->m_pMetrics->m_aMetrics.end() )
+ pArray[ i ] = it->second;
+ }
+ }
+
+ return true;
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::getMetrics( fontID nFontID, sal_Unicode minCharacter, sal_Unicode maxCharacter, CharacterMetric* pArray, bool bVertical ) const
+{
+ PrintFont* pFont = getFont( nFontID );
+ if( ! pFont )
+ return false;
+
+ if( pFont->m_nAscend == 0 && pFont->m_nDescend == 0 )
+ {
+ // might be a font not yet analyzed
+ if( pFont->m_eType == fonttype::Type1 )
+ pFont->readAfmMetrics( getAfmFile( pFont ), m_pAtoms );
+ else if( pFont->m_eType == fonttype::TrueType )
+ analyzeTrueTypeFile( pFont );
+ }
+
+ for( sal_Unicode code = minCharacter; code <= maxCharacter; code++ )
+ {
+ if( ! pFont->m_pMetrics ||
+ ! ( pFont->m_pMetrics->m_aPages[ code >> 11 ] & ( 1 << ( ( code >> 8 ) & 7 ) ) ) )
+ pFont->queryMetricPage( code >> 8, m_pAtoms );
+ pArray[ code - minCharacter ].width = -1;
+ pArray[ code - minCharacter ].height = -1;
+ if( pFont->m_pMetrics )
+ {
+ int effectiveCode = code;
+ effectiveCode |= bVertical ? 1 << 16 : 0;
+ ::std::hash_map< int, CharacterMetric >::const_iterator it =
+ pFont->m_pMetrics->m_aMetrics.find( effectiveCode );
+ if( it != pFont->m_pMetrics->m_aMetrics.end() )
+ pArray[ code - minCharacter ] = it->second;
+ }
+ }
+ return true;
+}
+
+// -------------------------------------------------------------------------
+
+static bool createPath( const ByteString& rPath )
+{
+ bool bSuccess = false;
+#ifdef DEBUG
+ fprintf( stderr, "createPath( %s )\n", rPath.GetBuffer() );
+#endif
+
+ if( access( rPath.GetBuffer(), F_OK ) )
+ {
+ int nPos = rPath.SearchBackward( '/' );
+ if( nPos != STRING_NOTFOUND )
+ while( nPos > 0 && rPath.GetChar( nPos ) == '/' )
+ nPos--;
+
+ if( nPos != STRING_NOTFOUND && nPos != 0 && createPath( rPath.Copy( 0, nPos+1 ) ) )
+ {
+#ifdef DEBUG
+ fprintf( stderr, "mkdir ", rPath.GetBuffer() );
+#endif
+ bSuccess = mkdir( rPath.GetBuffer(), 0777 ) ? false : true;
+#ifdef DEBUG
+ fprintf( stderr, "%s\n", bSuccess ? "succeeded" : "failed" );
+#endif
+ }
+ }
+ else
+ bSuccess = true;
+
+ return bSuccess;
+}
+
+
+// -------------------------------------------------------------------------
+
+int PrintFontManager::importFonts( const ::std::list< OUString >& rFiles, ImportFontCallback* pCallback )
+{
+ int nSuccess = 0;
+
+ // find a directory with write access
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ SvFileStream aFontsDir;
+ int nDirID;
+ INetURLObject aDir;
+ for( ::std::list< OString >::const_iterator dir_it = m_aFontDirectories.begin();
+ ! ( aFontsDir.IsOpen() && aFontsDir.IsWritable() ) && dir_it != m_aFontDirectories.end(); ++dir_it )
+ {
+ // there must be a writable fonts.dir in that directory
+ aDir = INetURLObject( OStringToOUString( *dir_it, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL );
+ nDirID = getDirectoryAtom( *dir_it, false );
+ INetURLObject aFDir( aDir );
+ ByteString aDirPath( aFDir.PathToFileName(), aEncoding );
+ if( createPath( aDirPath ) )
+ {
+ aFDir.Append( String( RTL_CONSTASCII_USTRINGPARAM( "fonts.dir" ) ) );
+ aFontsDir.Open( aFDir.PathToFileName(), STREAM_READ | STREAM_WRITE );
+ }
+ }
+ if( aFontsDir.IsOpen() )
+ {
+ aFontsDir.SetLineDelimiter( LINEEND_LF );
+ // we have a suitable path
+ // read the fonts.dir
+ ::std::list< ByteString > aLines;
+ ::std::list< ByteString >::iterator line_it;
+ ByteString aLine;
+ while( ! aFontsDir.IsEof() )
+ {
+ aFontsDir.ReadLine( aLine );
+ if( aLine.Len() )
+ aLines.push_back( aLine );
+ }
+ if( aLines.begin() != aLines.end() )
+ aLines.pop_front(); // not interested in the number of lines
+
+ // copy the font files and add them to fonts.dir
+ // do not overwrite existing files unless user wants it that way
+ for( ::std::list< OUString >::const_iterator font_it = rFiles.begin();
+ font_it != rFiles.end(); ++font_it )
+ {
+ INetURLObject aFrom( *font_it, INET_PROT_FILE, INetURLObject::ENCODE_ALL );
+ INetURLObject aTo( aDir );
+ aTo.Append( aFrom.GetName() );
+
+ if( pCallback )
+ pCallback->progress( aTo.PathToFileName() );
+
+ if( pCallback && pCallback->isCanceled() )
+ break;
+
+ if( ! access( ByteString( aTo.PathToFileName(), aEncoding ).GetBuffer(), F_OK ) )
+ {
+ if( ! ( pCallback ? pCallback->queryOverwriteFile( aTo.PathToFileName() ) : false ) )
+ continue;
+ }
+ // look for afm if necessary
+ OUString aAfmCopied;
+ if( aFrom.getExtension().EqualsIgnoreCaseAscii( "pfa" ) ||
+ aFrom.getExtension().EqualsIgnoreCaseAscii( "pfb" ) )
+ {
+ INetURLObject aFromAfm( aFrom );
+ aFromAfm.setExtension( String( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
+ if( access( ByteString( aFromAfm.PathToFileName(), aEncoding ).GetBuffer(), F_OK ) )
+ {
+ aFromAfm.setExtension( String( RTL_CONSTASCII_USTRINGPARAM( "AFM" ) ) );
+ if( access( ByteString( aFromAfm.PathToFileName(), aEncoding ).GetBuffer(), F_OK ) )
+ {
+ aFromAfm.removeSegment();
+ aFromAfm.Append( String( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
+ aFromAfm.Append( aTo.GetName() );
+ aFromAfm.setExtension( String( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
+ if( access( ByteString( aFromAfm.PathToFileName(), aEncoding ).GetBuffer(), F_OK ) )
+ {
+ aFromAfm.setExtension( String( RTL_CONSTASCII_USTRINGPARAM( "AFM" ) ) );
+ if( access( ByteString( aFromAfm.PathToFileName(), aEncoding ).GetBuffer(), F_OK ) )
+ {
+ // give up
+ if( pCallback )
+ pCallback->importFontFailed( aTo.PathToFileName(), ImportFontCallback::NoAfmMetric );
+ continue;
+ }
+ }
+ }
+ }
+ INetURLObject aToAfm( aTo );
+ aToAfm.setExtension( String( RTL_CONSTASCII_USTRINGPARAM( "afm" ) ) );
+ OUString aFromPath, aToPath;
+ FileBase::normalizePath( aFromAfm.PathToFileName(), aFromPath );
+ FileBase::normalizePath( aToAfm.PathToFileName(), aToPath );
+
+ FileBase::RC nError = File::copy( aFromPath, aToPath );
+ if( nError )
+ {
+ if( pCallback )
+ pCallback->importFontFailed( aTo.PathToFileName(), ImportFontCallback::AfmCopyFailed );
+ continue;
+ }
+ aAfmCopied = aToPath;
+ }
+ // copy font file
+ OUString aFontFrom, aFontTo;
+ FileBase::normalizePath( aFrom.PathToFileName(), aFontFrom );
+ FileBase::normalizePath( aTo.PathToFileName(), aFontTo );
+ if( File::copy( aFontFrom, aFontTo ) )
+ {
+ if( aAfmCopied.getLength() )
+ File::remove( aAfmCopied );
+ if( pCallback )
+ pCallback->importFontFailed( aTo.PathToFileName(), ImportFontCallback::FontCopyFailed );
+ continue;
+ }
+
+ ::std::list< PrintFont* > aNewFonts;
+ ::std::list< PrintFont* >::iterator it;
+ if( analyzeFontFile( nDirID, OUStringToOString( aTo.GetName(), aEncoding ), true, OString(), aNewFonts ) )
+ {
+ // remove all fonts for the same file
+ // discarding their font ids
+ ::std::hash_map< fontID, PrintFont* >::iterator current, next;
+ current = m_aFonts.begin();
+ OString aFileName( OUStringToOString( aTo.GetName(), aEncoding ) );
+ while( current != m_aFonts.end() )
+ {
+ bool bRemove = false;
+ switch( current->second->m_eType )
+ {
+ case fonttype::Type1:
+ if( static_cast<Type1FontFile*>(current->second)->m_aFontFile == aFileName )
+ bRemove = true;
+ break;
+ case fonttype::TrueType:
+ if( static_cast<TrueTypeFontFile*>(current->second)->m_aFontFile == aFileName )
+ bRemove = true;
+ break;
+ }
+ if( bRemove )
+ {
+ next = current;
+ ++next;
+ delete current->second;
+ m_aFonts.erase( current );
+ current = next;
+ }
+ else
+ ++current;
+ }
+
+ DBG_ASSERT( !findFontFileID( nDirID, aFileName ), "not all fonts removed for file" );
+
+ nSuccess++;
+ for( it = aNewFonts.begin(); it != aNewFonts.end(); ++it )
+ {
+ m_aFonts[ m_nNextFontID++ ] = *it;
+ aLine = ByteString( aTo.GetName(), aEncoding );
+ aLine += ' ';
+ aLine += getXLFD( *it );
+
+ ByteString aFile( aTo.GetName(), aEncoding );
+ for( line_it = aLines.begin(); line_it != aLines.end(); ++line_it )
+ {
+ if( line_it->GetToken( 0, ' ' ).Equals( aFile ) )
+ {
+ *line_it = aLine;
+ break;
+ }
+ }
+ if( line_it == aLines.end() )
+ aLines.push_back( aLine );
+ }
+ }
+ }
+ aFontsDir.Seek( STREAM_SEEK_TO_BEGIN );
+ aFontsDir.SetStreamSize( 0 );
+ aFontsDir.WriteLine( ByteString::CreateFromInt32( aLines.size() ) );
+ for( line_it = aLines.begin(); line_it != aLines.end(); ++line_it )
+ aFontsDir.WriteLine( *line_it );
+
+ // rehash X font path
+ Display* pDisplay = XOpenDisplay( NULL );
+ if( pDisplay )
+ {
+ int nPaths = 0;
+ char** pFontPaths = XGetFontPath( pDisplay, &nPaths );
+ XSetFontPath( pDisplay, pFontPaths, nPaths );
+ if( pFontPaths && nPaths )
+ XFreeFontPath( pFontPaths );
+ XCloseDisplay( pDisplay );
+ }
+ }
+ else if( pCallback )
+ pCallback->importFontsFailed( ImportFontCallback::NoWritableDirectory );
+
+ return nSuccess;
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::checkImportPossible() const
+{
+ bool bSuccess = false;
+
+ // find a directory with write access
+ SvFileStream aFontsDir;
+ INetURLObject aDir;
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ for( ::std::list< OString >::const_iterator dir_it = m_aFontDirectories.begin();
+ ! ( aFontsDir.IsOpen() && aFontsDir.IsWritable() ) && dir_it != m_aFontDirectories.end(); ++dir_it )
+ {
+ // there must be a writable fonts.dir in that directory
+ aDir = INetURLObject( OStringToOUString( *dir_it, aEncoding ), INET_PROT_FILE, INetURLObject::ENCODE_ALL );
+ INetURLObject aFDir( aDir );
+ ByteString aDirPath( aFDir.PathToFileName(), aEncoding );
+ if( createPath( aDirPath ) )
+ {
+ aFDir.Append( String( RTL_CONSTASCII_USTRINGPARAM( "fonts.dir" ) ) );
+ aFontsDir.Open( aFDir.PathToFileName(), STREAM_READ | STREAM_WRITE );
+ }
+ }
+ if( aFontsDir.IsOpen() && aFontsDir.IsWritable() )
+ {
+#ifdef DEBUG
+ fprintf( stderr, "found writable %s\n", ByteString( aFontsDir.GetFileName(), osl_getThreadTextEncoding() ).GetBuffer() );
+#endif
+ bSuccess = true;
+ }
+
+ return bSuccess;
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::checkChangeFontPropertiesPossible( fontID nFontID ) const
+{
+ bool bSuccess = false;
+ PrintFont* pFont = getFont( nFontID );
+ if( pFont )
+ {
+ OString aFontsDirPath;
+ switch( pFont->m_eType )
+ {
+ case fonttype::Type1:
+ aFontsDirPath = getDirectory( static_cast< Type1FontFile* >(pFont)->m_nDirectory );
+ break;
+ case fonttype::TrueType:
+ aFontsDirPath = getDirectory( static_cast< TrueTypeFontFile* >(pFont)->m_nDirectory );
+ break;
+ }
+ if( aFontsDirPath.getLength() )
+ {
+ OUString aUniPath, aFDPath;
+ FileBase::normalizePath( OStringToOUString( aFontsDirPath, osl_getThreadTextEncoding() ), aUniPath );
+ aUniPath += OUString::createFromAscii( "/fonts.dir" );
+ FileBase::getSystemPathFromNormalizedPath( aUniPath, aFDPath );
+ SvFileStream aFontsDir( aFDPath, STREAM_READ | STREAM_WRITE );
+ if( aFontsDir.IsOpen() && aFontsDir.IsWritable() )
+ bSuccess = true;
+ }
+ }
+ return bSuccess;
+}
+
+// -------------------------------------------------------------------------
+
+bool PrintFontManager::changeFontProperties( fontID nFontID, const ::rtl::OUString& rXLFD )
+{
+ bool bSuccess = false;
+ if( ! checkChangeFontPropertiesPossible( nFontID ) )
+ return bSuccess;
+
+ rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
+ PrintFont* pFont = getFont( nFontID );
+ OString aFontsDirPath;
+ ByteString aFontFile;
+
+ switch( pFont->m_eType )
+ {
+ case fonttype::Type1:
+ aFontsDirPath = getDirectory( static_cast< Type1FontFile* >(pFont)->m_nDirectory );
+ aFontFile = static_cast< Type1FontFile* >(pFont)->m_aFontFile;
+ break;
+ case fonttype::TrueType:
+ aFontsDirPath = getDirectory( static_cast< TrueTypeFontFile* >(pFont)->m_nDirectory );
+ aFontFile = static_cast< TrueTypeFontFile* >(pFont)->m_aFontFile;
+ break;
+ }
+ OUString aUniPath, aFDPath;
+ FileBase::normalizePath( OStringToOUString( aFontsDirPath, aEncoding ), aUniPath );
+ aUniPath += OUString::createFromAscii( "/fonts.dir" );
+ FileBase::getSystemPathFromNormalizedPath( aUniPath, aFDPath );
+
+ SvFileStream aFontsDir( aFDPath, STREAM_READ | STREAM_WRITE );
+ aFontsDir.SetLineDelimiter( LINEEND_LF );
+ if( aFontsDir.IsOpen() && aFontsDir.IsWritable() )
+ {
+ ByteString aXLFD( OUStringToOString( rXLFD, RTL_TEXTENCODING_ISO_8859_1 ) );
+ ::std::list< ByteString > aLines;
+ ByteString aLine;
+ aFontsDir.ReadLine( aLine ); // pop line count
+ while( ! aFontsDir.IsEof() )
+ {
+ aFontsDir.ReadLine( aLine );
+ if( GetCommandLineToken( 0, aLine ) == aFontFile )
+ {
+ bSuccess = true;
+ aLine = aFontFile;
+ aLine += ' ';
+ aLine += aXLFD;
+ }
+ if( aLine.Len() )
+ aLines.push_back( aLine );
+ }
+ if( ! bSuccess ) // ??? this should not happen
+ {
+ bSuccess = true;
+ aLine = aFontFile;
+ aLine += ' ';
+ aLine += aXLFD;
+ aLines.push_back( aLine );
+ }
+ // write the file
+ aFontsDir.Seek( STREAM_SEEK_TO_BEGIN );
+ aFontsDir.SetStreamSize( 0 );
+ // write number of fonts
+ aFontsDir.WriteLine( ByteString::CreateFromInt32( aLines.size() ) );
+ while( aLines.begin() != aLines.end() )
+ {
+ aFontsDir.WriteLine( aLines.front() );
+ aLines.pop_front();
+ }
+ getFontAttributesFromXLFD( pFont, aXLFD );
+ }
+ return bSuccess;
+}
diff --git a/psprint/source/fontmanager/makefile.mk b/psprint/source/fontmanager/makefile.mk
new file mode 100644
index 000000000000..1f98f93fa4a0
--- /dev/null
+++ b/psprint/source/fontmanager/makefile.mk
@@ -0,0 +1,92 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: pl $ $Date: 2001-05-08 11:45:34 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+ENABLE_EXCEPTIONS=TRUE
+PRJNAME=psprint
+TARGET=fontman
+
+ENVCFLAGS+= -I..$/fontsubset
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+
+.IF "$(OS)"=="MACOSX"
+
+dummy:
+ @echo "Nothing to build for Mac OS X"
+
+.ELSE # "$(OS)"=="MACOSX"
+
+SLOFILES=\
+ $(SLO)$/fontmanager.obj \
+ $(SLO)$/parseAFM.obj
+
+.ENDIF # "$(OS)"=="MACOSX"
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/psprint/source/fontmanager/parseAFM.cxx b/psprint/source/fontmanager/parseAFM.cxx
new file mode 100644
index 000000000000..77398980652d
--- /dev/null
+++ b/psprint/source/fontmanager/parseAFM.cxx
@@ -0,0 +1,1464 @@
+/*
+ * (C) 1988, 1989, 1990 by Adobe Systems Incorporated. All rights reserved.
+ *
+ * This file may be freely copied and redistributed as long as:
+ * 1) This entire notice continues to be included in the file,
+ * 2) If the file has been modified in any way, a notice of such
+ * modification is conspicuously indicated.
+ *
+ * PostScript, Display PostScript, and Adobe are registered trademarks of
+ * Adobe Systems Incorporated.
+ *
+ * ************************************************************************
+ * THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO CHANGE WITHOUT
+ * NOTICE, AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ADOBE SYSTEMS
+ * INCORPORATED. ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY OR
+ * LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO WARRANTY OF ANY
+ * KIND (EXPRESS, IMPLIED OR STATUTORY) WITH RESPECT TO THIS INFORMATION,
+ * AND EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ * ************************************************************************
+ */
+
+/*
+ * Changes made for OpenOffice.org
+ *
+ * 10/24/2000 pl - changed code to compile with c++-compilers
+ * - added namespace to avoid symbol clashes
+ * - replaced BOOL by bool
+ * - added function to free space allocated by parseFile
+ * 10/26/2000 pl - added additional keys
+ * - added ability to parse slightly broken files
+ * - added charwidth member to GlobalFontInfo
+ * 04/26/2001 pl - added OpenOffice header
+ */
+
+/*************************************************************************
+ *
+ * $RCSfile: parseAFM.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:36 $
+ *
+ ************************************************************************/
+
+/* parseAFM.c
+ *
+ * This file is used in conjuction with the parseAFM.h header file.
+ * This file contains several procedures that are used to parse AFM
+ * files. It is intended to work with an application program that needs
+ * font metric information. The program can be used as is by making a
+ * procedure call to "parseFile" (passing in the expected parameters)
+ * and having it fill in a data structure with the data from the
+ * AFM file, or an application developer may wish to customize this
+ * code.
+ *
+ * There is also a file, parseAFMclient.c, that is a sample application
+ * showing how to call the "parseFile" procedure and how to use the data
+ * after "parseFile" has returned.
+ *
+ * Please read the comments in parseAFM.h and parseAFMclient.c.
+ *
+ * History:
+ * original: DSM Thu Oct 20 17:39:59 PDT 1988
+ * modified: DSM Mon Jul 3 14:17:50 PDT 1989
+ * - added 'storageProblem' return code
+ * - fixed bug of not allocating extra byte for string duplication
+ * - fixed typos
+ * modified: DSM Tue Apr 3 11:18:34 PDT 1990
+ * - added free(ident) at end of parseFile routine
+ * modified: DSM Tue Jun 19 10:16:29 PDT 1990
+ * - changed (width == 250) to (width = 250) in initializeArray
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/file.h>
+#include <math.h>
+#include <parseAFM.hxx>
+#include <psprint/strhelper.hxx>
+
+#define lineterm EOL /* line terminating character */
+#define normalEOF 1 /* return code from parsing routines used only */
+/* in this module */
+#define Space "space" /* used in string comparison to look for the width */
+/* of the space character to init the widths array */
+#define False "false" /* used in string comparison to check the value of */
+/* boolean keys (e.g. IsFixedPitch) */
+
+#define MATCH(A,B) (strncmp((A),(B), MAX_NAME) == 0)
+
+namespace psp {
+
+/*************************** GLOBALS ***********************/
+
+static char *ident = NULL; /* storage buffer for keywords */
+
+
+/* "shorts" for fast case statement
+ * The values of each of these enumerated items correspond to an entry in the
+ * table of strings defined below. Therefore, if you add a new string as
+ * new keyword into the keyStrings table, you must also add a corresponding
+ * parseKey AND it MUST be in the same position!
+ *
+ * IMPORTANT: since the sorting algorithm is a binary search, the strings of
+ * keywords must be placed in lexicographical order, below. [Therefore, the
+ * enumerated items are not necessarily in lexicographical order, depending
+ * on the name chosen. BUT, they must be placed in the same position as the
+ * corresponding key string.] The NOPE shall remain in the last position,
+ * since it does not correspond to any key string, and it is used in the
+ * "recognize" procedure to calculate how many possible keys there are.
+ */
+
+// some metrics have Ascent, Descent instead Ascender, Descender or Em
+// which is not allowed per afm spcification, but let us handle
+// this gently
+enum parseKey {
+ ASCENDER, ASCENT, CHARBBOX, CODE, COMPCHAR, CODEHEX, CAPHEIGHT, CHARWIDTH, CHARACTERS, COMMENT,
+ DESCENDER, DESCENT, EM, ENCODINGSCHEME, ENDCHARMETRICS, ENDCOMPOSITES, ENDDIRECTION,
+ ENDFONTMETRICS, ENDKERNDATA, ENDKERNPAIRS, ENDTRACKKERN,
+ FAMILYNAME, FONTBBOX, FONTNAME, FULLNAME, ISBASEFONT, ISFIXEDPITCH,
+ ITALICANGLE, KERNPAIR, KERNPAIRXAMT, LIGATURE, MAPPINGSCHEME, METRICSSETS, CHARNAME,
+ NOTICE, COMPCHARPIECE, STARTCHARMETRICS, STARTCOMPOSITES, STARTDIRECTION,
+ STARTFONTMETRICS, STARTKERNDATA, STARTKERNPAIRS,
+ STARTTRACKKERN, TRACKKERN, UNDERLINEPOSITION,
+ UNDERLINETHICKNESS, VVECTOR, VERSION, XYWIDTH, X0WIDTH, XWIDTH, WEIGHT, XHEIGHT,
+ NOPE
+};
+
+/* keywords for the system:
+ * This a table of all of the current strings that are vaild AFM keys.
+ * Each entry can be referenced by the appropriate parseKey value (an
+ * enumerated data type defined above). If you add a new keyword here,
+ * a corresponding parseKey MUST be added to the enumerated data type
+ * defined above, AND it MUST be added in the same position as the
+ * string is in this table.
+ *
+ * IMPORTANT: since the sorting algorithm is a binary search, the keywords
+ * must be placed in lexicographical order. And, NULL should remain at the
+ * end.
+ */
+
+static char *keyStrings[] = {
+ "Ascender", "Ascent", "B", "C", "CC", "CH", "CapHeight", "CharWidth", "Characters", "Comment",
+ "Descender", "Descent", "Em", "EncodingScheme", "EndCharMetrics", "EndComposites", "EndDirection",
+ "EndFontMetrics", "EndKernData", "EndKernPairs", "EndTrackKern",
+ "FamilyName", "FontBBox", "FontName", "FullName", "IsBaseFont", "IsFixedPitch",
+ "ItalicAngle", "KP", "KPX", "L", "MappingScheme", "MetricsSets", "N",
+ "Notice", "PCC", "StartCharMetrics", "StartComposites", "StartDirection",
+ "StartFontMetrics", "StartKernData", "StartKernPairs",
+ "StartTrackKern", "TrackKern", "UnderlinePosition",
+ "UnderlineThickness", "V", "Version", "W", "W0X", "WX", "Weight", "XHeight",
+ NULL};
+
+/*************************** PARSING ROUTINES **************/
+
+/*************************** token *************************/
+
+/* A "AFM File Conventions" tokenizer. That means that it will
+ * return the next token delimited by white space. See also
+ * the `linetoken' routine, which does a similar thing but
+ * reads all tokens until the next end-of-line.
+ */
+
+static char *token( FILE* stream )
+{
+ int ch, idx;
+
+ /* skip over white space */
+ while ((ch = fgetc(stream)) == ' ' || ch == lineterm || ch == '\r' ||
+ ch == ',' || ch == '\t' || ch == ';');
+
+ idx = 0;
+ while (ch != EOF && ch != ' ' && ch != lineterm && ch != '\r'
+ && ch != '\t' && ch != ':' && ch != ';')
+ {
+ ident[idx++] = ch;
+ ch = fgetc(stream);
+ } /* while */
+
+ if (ch == EOF && idx < 1) return ((char *)NULL);
+ if (idx >= 1 && ch != ':' ) ungetc(ch, stream);
+ if (idx < 1 ) ident[idx++] = ch; /* single-character token */
+ ident[idx] = 0;
+
+ return(ident); /* returns pointer to the token */
+
+} /* token */
+
+
+/*************************** linetoken *************************/
+
+/* "linetoken" will get read all tokens until the EOL character from
+ * the given stream. This is used to get any arguments that can be
+ * more than one word (like Comment lines and FullName).
+ */
+
+static char *linetoken( FILE* stream )
+{
+ int ch, idx;
+
+ while ((ch = fgetc(stream)) == ' ' || ch == '\t' );
+
+ idx = 0;
+ while (ch != EOF && ch != lineterm && ch != '\r')
+ {
+ ident[idx++] = ch;
+ ch = fgetc(stream);
+ } /* while */
+
+ ungetc(ch, stream);
+ ident[idx] = 0;
+
+ return(ident); /* returns pointer to the token */
+
+} /* linetoken */
+
+
+/*************************** recognize *************************/
+
+/* This function tries to match a string to a known list of
+ * valid AFM entries (check the keyStrings array above).
+ * "ident" contains everything from white space through the
+ * next space, tab, or ":" character.
+ *
+ * The algorithm is a standard Knuth binary search.
+ */
+
+static enum parseKey recognize( register char* ident)
+{
+ int lower = 0, upper = (int) NOPE, midpoint, cmpvalue;
+ bool found = false;
+
+ while ((upper >= lower) && !found)
+ {
+ midpoint = (lower + upper)/2;
+ if (keyStrings[midpoint] == NULL) break;
+ cmpvalue = strncmp(ident, keyStrings[midpoint], MAX_NAME);
+ if (cmpvalue == 0) found = true;
+ else if (cmpvalue < 0) upper = midpoint - 1;
+ else lower = midpoint + 1;
+ } /* while */
+
+ if (found) return (enum parseKey) midpoint;
+ else return NOPE;
+
+} /* recognize */
+
+
+/************************* parseGlobals *****************************/
+
+/* This function is called by "parseFile". It will parse the AFM File
+ * up to the "StartCharMetrics" keyword, which essentially marks the
+ * end of the Global Font Information and the beginning of the character
+ * metrics information.
+ *
+ * If the caller of "parseFile" specified that it wanted the Global
+ * Font Information (as defined by the "AFM File Specification"
+ * document), then that information will be stored in the returned
+ * data structure.
+ *
+ * Any Global Font Information entries that are not found in a
+ * given file, will have the usual default initialization value
+ * for its type (i.e. entries of type int will be 0, etc).
+ *
+ * This function returns an error code specifying whether there was
+ * a premature EOF or a parsing error. This return value is used by
+ * parseFile to determine if there is more file to parse.
+ */
+
+static bool parseGlobals( FILE* fp, register GlobalFontInfo* gfi )
+{
+ bool cont = true, save = (gfi != NULL);
+ int error = ok;
+ register char *keyword;
+ int direction = -1;
+
+ while (cont)
+ {
+ keyword = token(fp);
+
+ if (keyword == NULL)
+ /* Have reached an early and unexpected EOF. */
+ /* Set flag and stop parsing */
+ {
+ error = earlyEOF;
+ break; /* get out of loop */
+ }
+ if (!save)
+ /* get tokens until the end of the Global Font info section */
+ /* without saving any of the data */
+ switch (recognize(keyword))
+ {
+ case STARTCHARMETRICS:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ default:
+ break;
+ } /* switch */
+ else
+ /* otherwise parse entire global font info section, */
+ /* saving the data */
+ switch(recognize(keyword))
+ {
+ case STARTFONTMETRICS:
+ keyword = token(fp);
+ gfi->afmVersion = strdup( keyword );
+ break;
+ case COMMENT:
+ keyword = linetoken(fp);
+ break;
+ case FONTNAME:
+ keyword = token(fp);
+ gfi->fontName = strdup( keyword );
+ break;
+ case ENCODINGSCHEME:
+ keyword = token(fp);
+ gfi->encodingScheme = strdup( keyword );
+ break;
+ case FULLNAME:
+ keyword = linetoken(fp);
+ gfi->fullName = strdup( keyword );
+ break;
+ case FAMILYNAME:
+ keyword = linetoken(fp);
+ gfi->familyName = strdup( keyword );
+ break;
+ case WEIGHT:
+ keyword = token(fp);
+ gfi->weight = strdup( keyword );
+ break;
+ case ITALICANGLE:
+ keyword = token(fp);
+ gfi->italicAngle = StringToDouble( keyword );
+ break;
+ case ISFIXEDPITCH:
+ keyword = token(fp);
+ if (MATCH(keyword, False))
+ gfi->isFixedPitch = 0;
+ else
+ gfi->isFixedPitch = 1;
+ break;
+ case UNDERLINEPOSITION:
+ keyword = token(fp);
+ gfi->underlinePosition = atoi(keyword);
+ break;
+ case UNDERLINETHICKNESS:
+ keyword = token(fp);
+ gfi->underlineThickness = atoi(keyword);
+ break;
+ case VERSION:
+ keyword = token(fp);
+ gfi->version = strdup( keyword );
+ break;
+ case NOTICE:
+ keyword = linetoken(fp);
+ gfi->notice = strdup( keyword );
+ break;
+ case FONTBBOX:
+ keyword = token(fp);
+ gfi->fontBBox.llx = atoi(keyword);
+ keyword = token(fp);
+ gfi->fontBBox.lly = atoi(keyword);
+ keyword = token(fp);
+ gfi->fontBBox.urx = atoi(keyword);
+ keyword = token(fp);
+ gfi->fontBBox.ury = atoi(keyword);
+ break;
+ case CAPHEIGHT:
+ keyword = token(fp);
+ gfi->capHeight = atoi(keyword);
+ break;
+ case XHEIGHT:
+ keyword = token(fp);
+ gfi->xHeight = atoi(keyword);
+ break;
+ case DESCENT:
+ keyword = token(fp);
+ gfi->descender = -atoi(keyword);
+ break;
+ case DESCENDER:
+ keyword = token(fp);
+ gfi->descender = atoi(keyword);
+ break;
+ case ASCENT:
+ case ASCENDER:
+ keyword = token(fp);
+ gfi->ascender = atoi(keyword);
+ break;
+ case STARTCHARMETRICS:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ case EM:
+ // skip one token
+ keyword = token(fp);
+ break;
+ case STARTDIRECTION:
+ keyword = token(fp);
+ direction = atoi(keyword);
+ break; /* ignore this for now */
+ case ENDDIRECTION:
+ break; /* ignore this for now */
+ case MAPPINGSCHEME:
+ keyword = token(fp);
+ break; /* ignore this for now */
+ case CHARACTERS:
+ keyword = token(fp);
+ break; /* ignore this for now */
+ case ISBASEFONT:
+ keyword = token(fp);
+ break; /* ignore this for now */
+ case CHARWIDTH:
+ keyword = token(fp);
+ if (direction == 0)
+ gfi->charwidth = atoi(keyword);
+ keyword = token(fp);
+ /* ignore y-width for now */
+ break;
+ case METRICSSETS:
+ keyword = token(fp);
+ break; /* ignore this for now */
+ case NOPE:
+ default:
+ error = parseError;
+ break;
+ } /* switch */
+ } /* while */
+
+ return(error);
+
+} /* parseGlobals */
+
+
+
+/************************* initializeArray ************************/
+
+/* Unmapped character codes are (at Adobe Systems) assigned the
+ * width of the space character (if one exists) else they get the
+ * value of 250 ems. This function initializes all entries in the
+ * char widths array to have this value. Then any mapped character
+ * codes will be replaced with the width of the appropriate character
+ * when parsing the character metric section.
+
+ * This function parses the Character Metrics Section looking
+ * for a space character (by comparing character names). If found,
+ * the width of the space character will be used to initialize the
+ * values in the array of character widths.
+ *
+ * Before returning, the position of the read/write pointer of the
+ * file is reset to be where it was upon entering this function.
+ */
+
+static int initializeArray( FILE* fp, register int* cwi)
+{
+ bool cont = true, found = false;
+ long opos = ftell(fp);
+ int code = 0, width = 0, i = 0, error = 0;
+ register char *keyword;
+
+ while (cont)
+ {
+ keyword = token(fp);
+ if (keyword == NULL)
+ {
+ error = earlyEOF;
+ break; /* get out of loop */
+ }
+ switch(recognize(keyword))
+ {
+ case COMMENT:
+ keyword = linetoken(fp);
+ break;
+ case CODE:
+ code = atoi(token(fp));
+ break;
+ case CODEHEX:
+ sscanf(token(fp),"<%x>", &code);
+ break;
+ case XWIDTH:
+ width = atoi(token(fp));
+ break;
+ case X0WIDTH:
+ (void) token(fp);
+ break;
+ case CHARNAME:
+ keyword = token(fp);
+ if (MATCH(keyword, Space))
+ {
+ cont = false;
+ found = true;
+ }
+ break;
+ case ENDCHARMETRICS:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ case NOPE:
+ default:
+ error = parseError;
+ break;
+ } /* switch */
+ } /* while */
+
+ if (!found)
+ width = 250;
+
+ for (i = 0; i < 256; ++i)
+ cwi[i] = width;
+
+ fseek(fp, opos, 0);
+
+ return(error);
+
+} /* initializeArray */
+
+
+/************************* parseCharWidths **************************/
+
+/* This function is called by "parseFile". It will parse the AFM File
+ * up to the "EndCharMetrics" keyword. It will save the character
+ * width info (as opposed to all of the character metric information)
+ * if requested by the caller of parseFile. Otherwise, it will just
+ * parse through the section without saving any information.
+ *
+ * If data is to be saved, parseCharWidths is passed in a pointer
+ * to an array of widths that has already been initialized by the
+ * standard value for unmapped character codes. This function parses
+ * the Character Metrics section only storing the width information
+ * for the encoded characters into the array using the character code
+ * as the index into that array.
+ *
+ * This function returns an error code specifying whether there was
+ * a premature EOF or a parsing error. This return value is used by
+ * parseFile to determine if there is more file to parse.
+ */
+
+static parseCharWidths( FILE* fp, register int* cwi)
+{
+ bool cont = true, save = (cwi != NULL);
+ int pos = 0, error = ok;
+ register char *keyword;
+
+ while (cont)
+ {
+ keyword = token(fp);
+ /* Have reached an early and unexpected EOF. */
+ /* Set flag and stop parsing */
+ if (keyword == NULL)
+ {
+ error = earlyEOF;
+ break; /* get out of loop */
+ }
+ if (!save)
+ /* get tokens until the end of the Char Metrics section without */
+ /* saving any of the data*/
+ switch (recognize(keyword))
+ {
+ case ENDCHARMETRICS:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ default:
+ break;
+ } /* switch */
+ else
+ /* otherwise parse entire char metrics section, saving */
+ /* only the char x-width info */
+ switch(recognize(keyword))
+ {
+ case COMMENT:
+ keyword = linetoken(fp);
+ break;
+ case CODE:
+ keyword = token(fp);
+ pos = atoi(keyword);
+ break;
+ case XYWIDTH:
+ /* PROBLEM: Should be no Y-WIDTH when doing "quick & dirty" */
+ keyword = token(fp); keyword = token(fp); /* eat values */
+ error = parseError;
+ break;
+ case CODEHEX:
+ keyword = token(fp);
+ sscanf(keyword, "<%x>", &pos);
+ break;
+ case X0WIDTH:
+ (void) token(fp);
+ break;
+ case XWIDTH:
+ keyword = token(fp);
+ if (pos >= 0) /* ignore unmapped chars */
+ cwi[pos] = atoi(keyword);
+ break;
+ case ENDCHARMETRICS:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ case CHARNAME: /* eat values (so doesn't cause parseError) */
+ keyword = token(fp);
+ break;
+ case CHARBBOX:
+ keyword = token(fp); keyword = token(fp);
+ keyword = token(fp); keyword = token(fp);
+ break;
+ case LIGATURE:
+ keyword = token(fp); keyword = token(fp);
+ break;
+ case VVECTOR:
+ keyword = token(fp);
+ keyword = token(fp);
+ break;
+ case NOPE:
+ default:
+ error = parseError;
+ break;
+ } /* switch */
+ } /* while */
+
+ return(error);
+
+} /* parseCharWidths */
+
+
+/*
+ * number of char metrics is almost allways inaccurate, so be gentle and try to
+ * adapt our internal storage by adjusting the allocated list
+ */
+
+static int
+reallocFontMetrics( void **pp_fontmetrics, int *p_oldcount, unsigned int n_newcount,
+ unsigned int n_size )
+{
+ char *p_tmpmetrics = NULL;
+
+ if ((pp_fontmetrics == NULL) || (*pp_fontmetrics == NULL))
+ return storageProblem;
+
+ if (*p_oldcount == n_newcount)
+ return ok;
+
+ p_tmpmetrics = (char*)realloc(*pp_fontmetrics, n_newcount * n_size);
+ if (p_tmpmetrics == NULL)
+ return storageProblem;
+
+ if ( n_newcount > *p_oldcount )
+ {
+ char *p_inimetrics = p_tmpmetrics + n_size * *p_oldcount;
+ int n_inimetrics = n_size * (n_newcount - *p_oldcount);
+ memset( p_inimetrics, 0, n_inimetrics );
+ }
+
+ *pp_fontmetrics = p_tmpmetrics;
+ *p_oldcount = n_newcount;
+
+ return ok;
+}
+
+static unsigned int
+enlargeCount( unsigned int n_oldcount )
+{
+ unsigned int n_newcount = n_oldcount + n_oldcount / 5;
+ if (n_oldcount == n_newcount )
+ n_newcount = n_oldcount + 5;
+
+ return n_newcount;
+}
+
+/************************* parseCharMetrics ************************/
+
+/* This function is called by parseFile if the caller of parseFile
+ * requested that all character metric information be saved
+ * (as opposed to only the character width information).
+ *
+ * parseCharMetrics is passed in a pointer to an array of records
+ * to hold information on a per character basis. This function
+ * parses the Character Metrics section storing all character
+ * metric information for the ALL characters (mapped and unmapped)
+ * into the array.
+ *
+ * This function returns an error code specifying whether there was
+ * a premature EOF or a parsing error. This return value is used by
+ * parseFile to determine if there is more file to parse.
+ */
+
+static parseCharMetrics( FILE* fp, register FontInfo* fi)
+{
+ bool cont = true, firstTime = true;
+ int error = ok, count = 0;
+ register CharMetricInfo *temp = fi->cmi;
+ register char *keyword;
+
+ while (cont)
+ {
+ keyword = token(fp);
+ if (keyword == NULL)
+ {
+ error = earlyEOF;
+ break; /* get out of loop */
+ }
+ switch(recognize(keyword))
+ {
+ case COMMENT:
+ keyword = linetoken(fp);
+ break;
+ case CODE:
+ if (!(count < fi->numOfChars))
+ {
+ reallocFontMetrics( (void**)&(fi->cmi),
+ &(fi->numOfChars), enlargeCount(fi->numOfChars),
+ sizeof(CharMetricInfo) );
+ temp = &(fi->cmi[ count - 1 ]);
+ }
+ if (count < fi->numOfChars)
+ {
+ if (firstTime) firstTime = false;
+ else temp++;
+ temp->code = atoi(token(fp));
+ if (fi->gfi && fi->gfi->charwidth)
+ temp->wx = fi->gfi->charwidth;
+ count++;
+ }
+ else
+ {
+ error = parseError;
+ cont = false;
+ }
+ break;
+ case CODEHEX:
+ if (!(count < fi->numOfChars ))
+ {
+ reallocFontMetrics( (void**)&(fi->cmi),
+ &(fi->numOfChars), enlargeCount(fi->numOfChars),
+ sizeof(CharMetricInfo) );
+ temp = &(fi->cmi[ count - 1 ]);
+ }
+ if (count < fi->numOfChars) {
+ if (firstTime)
+ firstTime = FALSE;
+ else
+ temp++;
+ sscanf(token(fp),"<%x>", &temp->code);
+ if (fi->gfi && fi->gfi->charwidth)
+ temp->wx = fi->gfi->charwidth;
+ count++;
+ }
+ else {
+ error = parseError;
+ cont = FALSE;
+ }
+ break;
+ case XYWIDTH:
+ temp->wx = atoi(token(fp));
+ temp->wy = atoi(token(fp));
+ break;
+ case X0WIDTH:
+ temp->wx = atoi(token(fp));
+ break;
+ case XWIDTH:
+ temp->wx = atoi(token(fp));
+ break;
+ case CHARNAME:
+ keyword = token(fp);
+ temp->name = (char *) malloc(strlen(keyword) + 1);
+ strcpy(temp->name, keyword);
+ break;
+ case CHARBBOX:
+ temp->charBBox.llx = atoi(token(fp));
+ temp->charBBox.lly = atoi(token(fp));
+ temp->charBBox.urx = atoi(token(fp));
+ temp->charBBox.ury = atoi(token(fp));
+ break;
+ case LIGATURE: {
+ Ligature **tail = &(temp->ligs);
+ Ligature *node = *tail;
+
+ if (*tail != NULL)
+ {
+ while (node->next != NULL)
+ node = node->next;
+ tail = &(node->next);
+ }
+
+ *tail = (Ligature *) calloc(1, sizeof(Ligature));
+ keyword = token(fp);
+ (*tail)->succ = (char *) malloc(strlen(keyword) + 1);
+ strcpy((*tail)->succ, keyword);
+ keyword = token(fp);
+ (*tail)->lig = (char *) malloc(strlen(keyword) + 1);
+ strcpy((*tail)->lig, keyword);
+ break; }
+ case ENDCHARMETRICS:
+ cont = false;;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ case VVECTOR:
+ keyword = token(fp);
+ keyword = token(fp);
+ break;
+ case NOPE:
+ default:
+ error = parseError;
+ break;
+ } /* switch */
+ } /* while */
+
+ if ((error == ok) && (count != fi->numOfChars))
+ error = reallocFontMetrics( (void**)&(fi->cmi), &(fi->numOfChars),
+ count, sizeof(CharMetricInfo) );
+
+ if ((error == ok) && (count != fi->numOfChars))
+ error = parseError;
+
+ return(error);
+
+} /* parseCharMetrics */
+
+
+
+/************************* parseTrackKernData ***********************/
+
+/* This function is called by "parseFile". It will parse the AFM File
+ * up to the "EndTrackKern" or "EndKernData" keywords. It will save the
+ * track kerning data if requested by the caller of parseFile.
+ *
+ * parseTrackKernData is passed in a pointer to the FontInfo record.
+ * If data is to be saved, the FontInfo record will already contain
+ * a valid pointer to storage for the track kerning data.
+ *
+ * This function returns an error code specifying whether there was
+ * a premature EOF or a parsing error. This return value is used by
+ * parseFile to determine if there is more file to parse.
+ */
+
+static parseTrackKernData( FILE* fp, register FontInfo* fi)
+{
+ bool cont = true, save = (fi->tkd != NULL);
+ int pos = 0, error = ok, tcount = 0;
+ register char *keyword;
+
+ while (cont)
+ {
+ keyword = token(fp);
+
+ if (keyword == NULL)
+ {
+ error = earlyEOF;
+ break; /* get out of loop */
+ }
+ if (!save)
+ /* get tokens until the end of the Track Kerning Data */
+ /* section without saving any of the data */
+ switch(recognize(keyword))
+ {
+ case ENDTRACKKERN:
+ case ENDKERNDATA:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ default:
+ break;
+ } /* switch */
+ else
+ /* otherwise parse entire Track Kerning Data section, */
+ /* saving the data */
+ switch(recognize(keyword))
+ {
+ case COMMENT:
+ keyword = linetoken(fp);
+ break;
+ case TRACKKERN:
+ if (!(tcount < fi->numOfTracks))
+ {
+ reallocFontMetrics( (void**)&(fi->tkd), &(fi->numOfTracks),
+ enlargeCount(fi->numOfTracks), sizeof(TrackKernData) );
+ }
+
+ if (tcount < fi->numOfTracks)
+ {
+ keyword = token(fp);
+ fi->tkd[pos].degree = atoi(keyword);
+ keyword = token(fp);
+ fi->tkd[pos].minPtSize = StringToDouble(keyword);
+ keyword = token(fp);
+ fi->tkd[pos].minKernAmt = StringToDouble(keyword);
+ keyword = token(fp);
+ fi->tkd[pos].maxPtSize = StringToDouble(keyword);
+ keyword = token(fp);
+ fi->tkd[pos++].maxKernAmt = StringToDouble(keyword);
+ tcount++;
+ }
+ else
+ {
+ error = parseError;
+ cont = false;
+ }
+ break;
+ case ENDTRACKKERN:
+ case ENDKERNDATA:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ case NOPE:
+ default:
+ error = parseError;
+ break;
+ } /* switch */
+ } /* while */
+
+ if (error == ok && tcount != fi->numOfTracks)
+ error = reallocFontMetrics( (void**)&(fi->tkd), &(fi->numOfTracks),
+ tcount, sizeof(TrackKernData) );
+
+ if (error == ok && tcount != fi->numOfTracks)
+ error = parseError;
+
+ return(error);
+
+} /* parseTrackKernData */
+
+
+/************************* parsePairKernData ************************/
+
+/* This function is called by "parseFile". It will parse the AFM File
+ * up to the "EndKernPairs" or "EndKernData" keywords. It will save
+ * the pair kerning data if requested by the caller of parseFile.
+ *
+ * parsePairKernData is passed in a pointer to the FontInfo record.
+ * If data is to be saved, the FontInfo record will already contain
+ * a valid pointer to storage for the pair kerning data.
+ *
+ * This function returns an error code specifying whether there was
+ * a premature EOF or a parsing error. This return value is used by
+ * parseFile to determine if there is more file to parse.
+ */
+
+static parsePairKernData( FILE* fp, register FontInfo* fi)
+{
+ bool cont = true, save = (fi->pkd != NULL);
+ int pos = 0, error = ok, pcount = 0;
+ register char *keyword;
+
+ while (cont)
+ {
+ keyword = token(fp);
+
+ if (keyword == NULL)
+ {
+ error = earlyEOF;
+ break; /* get out of loop */
+ }
+ if (!save)
+ /* get tokens until the end of the Pair Kerning Data */
+ /* section without saving any of the data */
+ switch(recognize(keyword))
+ {
+ case ENDKERNPAIRS:
+ case ENDKERNDATA:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ default:
+ break;
+ } /* switch */
+ else
+ /* otherwise parse entire Pair Kerning Data section, */
+ /* saving the data */
+ switch(recognize(keyword))
+ {
+ case COMMENT:
+ keyword = linetoken(fp);
+ break;
+ case KERNPAIR:
+ if (!(pcount < fi->numOfPairs))
+ {
+ reallocFontMetrics( (void**)&(fi->pkd), &(fi->numOfPairs),
+ enlargeCount(fi->numOfPairs), sizeof(PairKernData) );
+ }
+ if (pcount < fi->numOfPairs)
+ {
+ keyword = token(fp);
+ fi->pkd[pos].name1 = strdup( keyword );
+ keyword = token(fp);
+ fi->pkd[pos].name2 = strdup( keyword );
+ keyword = token(fp);
+ fi->pkd[pos].xamt = atoi(keyword);
+ keyword = token(fp);
+ fi->pkd[pos++].yamt = atoi(keyword);
+ pcount++;
+ }
+ else
+ {
+ error = parseError;
+ cont = false;
+ }
+ break;
+ case KERNPAIRXAMT:
+ if (!(pcount < fi->numOfPairs))
+ {
+ reallocFontMetrics( (void**)&(fi->pkd), &(fi->numOfPairs),
+ enlargeCount(fi->numOfPairs), sizeof(PairKernData) );
+ }
+ if (pcount < fi->numOfPairs)
+ {
+ keyword = token(fp);
+ fi->pkd[pos].name1 = strdup( keyword );
+ keyword = token(fp);
+ fi->pkd[pos].name2 = strdup( keyword );
+ keyword = token(fp);
+ fi->pkd[pos++].xamt = atoi(keyword);
+ pcount++;
+ }
+ else
+ {
+ error = parseError;
+ cont = false;
+ }
+ break;
+ case ENDKERNPAIRS:
+ case ENDKERNDATA:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ case NOPE:
+ default:
+ error = parseError;
+ break;
+ } /* switch */
+ } /* while */
+
+ if ((error == ok) && (pcount != fi->numOfPairs))
+ error = reallocFontMetrics( (void**)&(fi->pkd), &(fi->numOfPairs),
+ pcount, sizeof(PairKernData) );
+
+ if (error == ok && pcount != fi->numOfPairs)
+ error = parseError;
+
+ return(error);
+
+} /* parsePairKernData */
+
+
+/************************* parseCompCharData **************************/
+
+/* This function is called by "parseFile". It will parse the AFM File
+ * up to the "EndComposites" keyword. It will save the composite
+ * character data if requested by the caller of parseFile.
+ *
+ * parseCompCharData is passed in a pointer to the FontInfo record, and
+ * a boolean representing if the data should be saved.
+ *
+ * This function will create the appropriate amount of storage for
+ * the composite character data and store a pointer to the storage
+ * in the FontInfo record.
+ *
+ * This function returns an error code specifying whether there was
+ * a premature EOF or a parsing error. This return value is used by
+ * parseFile to determine if there is more file to parse.
+ */
+
+static parseCompCharData( FILE* fp, register FontInfo* fi)
+{
+ bool cont = true, firstTime = true, save = (fi->ccd != NULL);
+ int pos = 0, j = 0, error = ok, ccount = 0, pcount = 0;
+ register char *keyword;
+
+ while (cont)
+ {
+ keyword = token(fp);
+ if (keyword == NULL)
+ /* Have reached an early and unexpected EOF. */
+ /* Set flag and stop parsing */
+ {
+ error = earlyEOF;
+ break; /* get out of loop */
+ }
+ if (ccount > fi->numOfComps)
+ {
+ reallocFontMetrics( (void**)&(fi->ccd), &(fi->numOfComps),
+ enlargeCount(fi->numOfComps), sizeof(CompCharData) );
+ }
+ if (ccount > fi->numOfComps)
+ {
+ error = parseError;
+ break; /* get out of loop */
+ }
+ if (!save)
+ /* get tokens until the end of the Composite Character info */
+ /* section without saving any of the data */
+ switch(recognize(keyword))
+ {
+ case ENDCOMPOSITES:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ case COMMENT:
+ case COMPCHAR:
+ keyword = linetoken(fp);
+ break;
+ default:
+ break;
+ } /* switch */
+ else
+ /* otherwise parse entire Composite Character info section, */
+ /* saving the data */
+ switch(recognize(keyword))
+ {
+ case COMMENT:
+ keyword = linetoken(fp);
+ break;
+ case COMPCHAR:
+ if (!(ccount < fi->numOfComps))
+ {
+ reallocFontMetrics( (void**)&(fi->ccd), &(fi->numOfComps),
+ enlargeCount(fi->numOfComps), sizeof(CompCharData) );
+ }
+ if (ccount < fi->numOfComps)
+ {
+ keyword = token(fp);
+ if (pcount != fi->ccd[pos].numOfPieces)
+ error = parseError;
+ pcount = 0;
+ if (firstTime) firstTime = false;
+ else pos++;
+ fi->ccd[pos].ccName = strdup( keyword );
+ keyword = token(fp);
+ fi->ccd[pos].numOfPieces = atoi(keyword);
+ fi->ccd[pos].pieces = (Pcc *)
+ calloc(fi->ccd[pos].numOfPieces, sizeof(Pcc));
+ j = 0;
+ ccount++;
+ }
+ else
+ {
+ error = parseError;
+ cont = false;
+ }
+ break;
+ case COMPCHARPIECE:
+ if (pcount < fi->ccd[pos].numOfPieces)
+ {
+ keyword = token(fp);
+ fi->ccd[pos].pieces[j].pccName = strdup( keyword );
+ keyword = token(fp);
+ fi->ccd[pos].pieces[j].deltax = atoi(keyword);
+ keyword = token(fp);
+ fi->ccd[pos].pieces[j++].deltay = atoi(keyword);
+ pcount++;
+ }
+ else
+ error = parseError;
+ break;
+ case ENDCOMPOSITES:
+ cont = false;
+ break;
+ case ENDFONTMETRICS:
+ cont = false;
+ error = normalEOF;
+ break;
+ case NOPE:
+ default:
+ error = parseError;
+ break;
+ } /* switch */
+ } /* while */
+
+ if (error == ok && ccount != fi->numOfComps)
+ reallocFontMetrics( (void**)&(fi->ccd), &(fi->numOfComps),
+ ccount, sizeof(CompCharData) );
+
+ if (error == ok && ccount != fi->numOfComps)
+ error = parseError;
+
+ return(error);
+
+} /* parseCompCharData */
+
+
+
+
+/*************************** 'PUBLIC' FUNCTION ********************/
+
+
+/*************************** parseFile *****************************/
+
+/* parseFile is the only 'public' procedure available. It is called
+ * from an application wishing to get information from an AFM file.
+ * The caller of this function is responsible for locating and opening
+ * an AFM file and handling all errors associated with that task.
+ *
+ * parseFile expects 3 parameters: a vaild file pointer, a pointer
+ * to a (FontInfo *) variable (for which storage will be allocated and
+ * the data requested filled in), and a mask specifying which
+ * data from the AFM File should be saved in the FontInfo structure.
+ *
+ * The file will be parsed and the requested data will be stored in
+ * a record of type FontInfo (refer to ParseAFM.h).
+ *
+ * parseFile returns an error code as defined in parseAFM.h.
+ *
+ * The position of the read/write pointer associated with the file
+ * pointer upon return of this function is undefined.
+ */
+
+int parseFile ( FILE* fp, FontInfo** fi, FLAGS flags)
+{
+
+ int code = ok; /* return code from each of the parsing routines */
+ int error = ok; /* used as the return code from this function */
+
+ register char *keyword; /* used to store a token */
+
+
+ /* storage data for the global variable ident */
+ ident = (char *) calloc(MAX_NAME, sizeof(char));
+ if (ident == NULL) {error = storageProblem; return(error);}
+
+ (*fi) = (FontInfo *) calloc(1, sizeof(FontInfo));
+ if ((*fi) == NULL) {error = storageProblem; return(error);}
+
+ if (flags & P_G)
+ {
+ (*fi)->gfi = (GlobalFontInfo *) calloc(1, sizeof(GlobalFontInfo));
+ if ((*fi)->gfi == NULL) {error = storageProblem; return(error);}
+ }
+
+ /* The AFM File begins with Global Font Information. This section */
+ /* will be parsed whether or not information should be saved. */
+ code = parseGlobals(fp, (*fi)->gfi);
+
+ if (code < 0) error = code;
+
+ /* The Global Font Information is followed by the Character Metrics */
+ /* section. Which procedure is used to parse this section depends on */
+ /* how much information should be saved. If all of the metrics info */
+ /* is wanted, parseCharMetrics is called. If only the character widths */
+ /* is wanted, parseCharWidths is called. parseCharWidths will also */
+ /* be called in the case that no character data is to be saved, just */
+ /* to parse through the section. */
+
+ if ((code != normalEOF) && (code != earlyEOF))
+ {
+ (*fi)->numOfChars = atoi(token(fp));
+ if (flags & (P_M ^ P_W))
+ {
+ (*fi)->cmi = (CharMetricInfo *)
+ calloc((*fi)->numOfChars, sizeof(CharMetricInfo));
+ if ((*fi)->cmi == NULL) {error = storageProblem; return(error);}
+ code = parseCharMetrics(fp, *fi);
+ }
+ else
+ {
+ if (flags & P_W)
+ {
+ (*fi)->cwi = (int *) calloc(256, sizeof(int));
+ if ((*fi)->cwi == NULL)
+ {
+ error = storageProblem;
+ return(error);
+ }
+ }
+ /* parse section regardless */
+ code = parseCharWidths(fp, (*fi)->cwi);
+ } /* else */
+ } /* if */
+
+ if ((error != earlyEOF) && (code < 0)) error = code;
+
+ /* The remaining sections of the AFM are optional. This code will */
+ /* look at the next keyword in the file to determine what section */
+ /* is next, and then allocate the appropriate amount of storage */
+ /* for the data (if the data is to be saved) and call the */
+ /* appropriate parsing routine to parse the section. */
+
+ while ((code != normalEOF) && (code != earlyEOF))
+ {
+ keyword = token(fp);
+ if (keyword == NULL)
+ /* Have reached an early and unexpected EOF. */
+ /* Set flag and stop parsing */
+ {
+ code = earlyEOF;
+ break; /* get out of loop */
+ }
+ switch(recognize(keyword))
+ {
+ case STARTKERNDATA:
+ break;
+ case ENDKERNDATA:
+ break;
+ case STARTTRACKKERN:
+ keyword = token(fp);
+ if (flags & P_T)
+ {
+ (*fi)->numOfTracks = atoi(keyword);
+ (*fi)->tkd = (TrackKernData *)
+ calloc((*fi)->numOfTracks, sizeof(TrackKernData));
+ if ((*fi)->tkd == NULL)
+ {
+ error = storageProblem;
+ return(error);
+ }
+ } /* if */
+ code = parseTrackKernData(fp, *fi);
+ break;
+ case STARTKERNPAIRS:
+ keyword = token(fp);
+ if (flags & P_P)
+ {
+ (*fi)->numOfPairs = atoi(keyword);
+ (*fi)->pkd = (PairKernData *)
+ calloc((*fi)->numOfPairs, sizeof(PairKernData));
+ if ((*fi)->pkd == NULL)
+ {
+ error = storageProblem;
+ return(error);
+ }
+ } /* if */
+ code = parsePairKernData(fp, *fi);
+ break;
+ case STARTCOMPOSITES:
+ keyword = token(fp);
+ if (flags & P_C)
+ {
+ (*fi)->numOfComps = atoi(keyword);
+ (*fi)->ccd = (CompCharData *)
+ calloc((*fi)->numOfComps, sizeof(CompCharData));
+ if ((*fi)->ccd == NULL)
+ {
+ error = storageProblem;
+ return(error);
+ }
+ } /* if */
+ code = parseCompCharData(fp, *fi);
+ break;
+ case ENDFONTMETRICS:
+ code = normalEOF;
+ break;
+ case COMMENT:
+ linetoken(fp);
+ break;
+ case NOPE:
+ default:
+ code = parseError;
+ break;
+ } /* switch */
+
+ if ((error != earlyEOF) && (code < 0)) error = code;
+
+ } /* while */
+
+ if ((error != earlyEOF) && (code < 0)) error = code;
+
+ if (ident != NULL) { free(ident); ident = NULL; }
+
+ return(error);
+
+} /* parseFile */
+
+void
+freeFontInfo (FontInfo *fi)
+{
+ int i, j;
+
+ if (fi->gfi)
+ {
+ free (fi->gfi->afmVersion);
+ free (fi->gfi->fontName);
+ free (fi->gfi->fullName);
+ free (fi->gfi->familyName);
+ free (fi->gfi->weight);
+ free (fi->gfi->version);
+ free (fi->gfi->notice);
+ free (fi->gfi->encodingScheme);
+ free (fi->gfi);
+ }
+
+ free (fi->cwi);
+
+ if (fi->cmi)
+ {
+ for (i = 0; i < fi->numOfChars; i++)
+ {
+ Ligature *ligs;
+ free (fi->cmi[i].name);
+ ligs = fi->cmi[i].ligs;
+ while (ligs)
+ {
+ Ligature *tmp;
+ tmp = ligs;
+ ligs = ligs->next;
+ free (tmp->succ);
+ free (tmp->lig);
+ free (tmp);
+ }
+ }
+ free (fi->cmi);
+ }
+
+ free (fi->tkd);
+
+ if (fi->pkd)
+ {
+ for (int i = 0; i < fi->numOfPairs; i++)
+ {
+ free (fi->pkd[i].name1);
+ free (fi->pkd[i].name2);
+ }
+ free (fi->pkd);
+ }
+
+ if (fi->ccd)
+ {
+ for (i = 0; i < fi->numOfComps; i++)
+ {
+ free (fi->ccd[i].ccName);
+ for (j = 0; j < fi->ccd[i].numOfPieces; j++)
+ free (fi->ccd[i].pieces[j].pccName);
+
+ free (fi->ccd[i].pieces);
+ }
+ free (fi->ccd);
+ }
+
+ free (fi);
+}
+
+} // namspace
diff --git a/psprint/source/fontmanager/parseAFM.hxx b/psprint/source/fontmanager/parseAFM.hxx
new file mode 100644
index 000000000000..ab0d1d961448
--- /dev/null
+++ b/psprint/source/fontmanager/parseAFM.hxx
@@ -0,0 +1,343 @@
+/*
+ * (C) 1988, 1989 by Adobe Systems Incorporated. All rights reserved.
+ *
+ * This file may be freely copied and redistributed as long as:
+ * 1) This entire notice continues to be included in the file,
+ * 2) If the file has been modified in any way, a notice of such
+ * modification is conspicuously indicated.
+ *
+ * PostScript, Display PostScript, and Adobe are registered trademarks of
+ * Adobe Systems Incorporated.
+ *
+ * ************************************************************************
+ * THE INFORMATION BELOW IS FURNISHED AS IS, IS SUBJECT TO CHANGE WITHOUT
+ * NOTICE, AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY ADOBE SYSTEMS
+ * INCORPORATED. ADOBE SYSTEMS INCORPORATED ASSUMES NO RESPONSIBILITY OR
+ * LIABILITY FOR ANY ERRORS OR INACCURACIES, MAKES NO WARRANTY OF ANY
+ * KIND (EXPRESS, IMPLIED OR STATUTORY) WITH RESPECT TO THIS INFORMATION,
+ * AND EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR PARTICULAR PURPOSES AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+ * ************************************************************************
+ */
+
+/*
+ * Changes made for OpenOffice.org
+ *
+ * 10/24/2000 pl - changed code to compile with c++-compilers
+ * - added namespace to avoid symbol clashes
+ * - replaced BOOL by bool
+ * - added function to free space allocated by parseFile
+ * 10/26/2000 pl - added additional keys
+ * - added ability to parse slightly broken files
+ * - added charwidth member to GlobalFontInfo
+ * 04/26/2001 pl - added OpenOffice header
+ */
+
+/*************************************************************************
+ *
+ * $RCSfile: parseAFM.hxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:36 $
+ *
+ ************************************************************************/
+
+/* ParseAFM.h
+ *
+ * This header file is used in conjuction with the parseAFM.c file.
+ * Together these files provide the functionality to parse Adobe Font
+ * Metrics files and store the information in predefined data structures.
+ * It is intended to work with an application program that needs font metric
+ * information. The program can be used as is by making a procedure call to
+ * parse an AFM file and have the data stored, or an application developer
+ * may wish to customize the code.
+ *
+ * This header file defines the data structures used as well as the key
+ * strings that are currently recognized by this version of the AFM parser.
+ * This program is based on the document "Adobe Font Metrics Files,
+ * Specification Version 2.0".
+ *
+ * AFM files are separated into distinct sections of different data. Because
+ * of this, the parseAFM program can parse a specified file to only save
+ * certain sections of information based on the application's needs. A record
+ * containing the requested information will be returned to the application.
+ *
+ * AFM files are divided into five sections of data:
+ * 1) The Global Font Information
+ * 2) The Character Metrics Information
+ * 3) The Track Kerning Data
+ * 4) The Pair-Wise Kerning Data
+ * 5) The Composite Character Data
+ *
+ * Basically, the application can request any of these sections independent
+ * of what other sections are requested. In addition, in recognizing that
+ * many applications will want ONLY the x-width of characters and not all
+ * of the other character metrics information, there is a way to receive
+ * only the width information so as not to pay the storage cost for the
+ * unwanted data. An application should never request both the
+ * "quick and dirty" char metrics (widths only) and the Character Metrics
+ * Information since the Character Metrics Information will contain all
+ * of the character widths as well.
+ *
+ * There is a procedure in parseAFM.c, called parseFile, that can be
+ * called from any application wishing to get information from the AFM File.
+ * This procedure expects 3 parameters: a vaild file descriptor, a pointer
+ * to a (FontInfo *) variable (for which space will be allocated and then
+ * will be filled in with the data requested), and a mask specifying
+ * which data from the AFM File should be saved in the FontInfo structure.
+ *
+ * The flags that can be used to set the appropriate mask are defined below.
+ * In addition, several commonly used masks have already been defined.
+ *
+ * History:
+ * original: DSM Thu Oct 20 17:39:59 PDT 1988
+ * modified: DSM Mon Jul 3 14:17:50 PDT 1989
+ * - added 'storageProblem' return code
+ * - fixed typos
+ */
+
+#include <stdio.h>
+
+namespace psp {
+
+/* your basic constants */
+#define EOL '\n' /* end-of-line indicator */
+#define MAX_NAME 4096 /* max length for identifiers */
+#define FLAGS int
+
+
+
+/* Flags that can be AND'ed together to specify exactly what
+ * information from the AFM file should be saved.
+ */
+#define P_G 0x01 /* 0000 0001 */ /* Global Font Info */
+#define P_W 0x02 /* 0000 0010 */ /* Character Widths ONLY */
+#define P_M 0x06 /* 0000 0110 */ /* All Char Metric Info */
+#define P_P 0x08 /* 0000 1000 */ /* Pair Kerning Info */
+#define P_T 0x10 /* 0001 0000 */ /* Track Kerning Info */
+#define P_C 0x20 /* 0010 0000 */ /* Composite Char Info */
+
+
+/* Commonly used flags
+ */
+#define P_GW (P_G | P_W)
+#define P_GM (P_G | P_M)
+#define P_GMP (P_G | P_M | P_P)
+#define P_GMK (P_G | P_M | P_P | P_T)
+#define P_ALL (P_G | P_M | P_P | P_T | P_C)
+
+
+
+/* Possible return codes from the parseFile procedure.
+ *
+ * ok means there were no problems parsing the file.
+ *
+ * parseError means that there was some kind of parsing error, but the
+ * parser went on. This could include problems like the count for any given
+ * section does not add up to how many entries there actually were, or
+ * there was a key that was not recognized. The return record may contain
+ * vaild data or it may not.
+ *
+ * earlyEOF means that an End of File was encountered before expected. This
+ * may mean that the AFM file had been truncated, or improperly formed.
+ *
+ * storageProblem means that there were problems allocating storage for
+ * the data structures that would have contained the AFM data.
+ */
+
+enum afmError { ok = 0, parseError = -1, earlyEOF = -2, storageProblem = -3 };
+
+
+/************************* TYPES *********************************/
+/* Below are all of the data structure definitions. These structures
+ * try to map as closely as possible to grouping and naming of data
+ * in the AFM Files.
+ */
+
+
+/* Bounding box definition. Used for the Font BBox as well as the
+ * Character BBox.
+ */
+typedef struct
+{
+ int llx; /* lower left x-position */
+ int lly; /* lower left y-position */
+ int urx; /* upper right x-position */
+ int ury; /* upper right y-position */
+} BBox;
+
+
+/* Global Font information.
+ * The key that each field is associated with is in comments. For an
+ * explanation about each key and its value please refer to the AFM
+ * documentation (full title & version given above).
+ */
+typedef struct
+{
+ char *afmVersion; /* key: StartFontMetrics */
+ char *fontName; /* key: FontName */
+ char *fullName; /* key: FullName */
+ char *familyName; /* key: FamilyName */
+ char *weight; /* key: Weight */
+ float italicAngle; /* key: ItalicAngle */
+ bool isFixedPitch; /* key: IsFixedPitch */
+ BBox fontBBox; /* key: FontBBox */
+ int underlinePosition; /* key: UnderlinePosition */
+ int underlineThickness; /* key: UnderlineThickness */
+ char *version; /* key: Version */
+ char *notice; /* key: Notice */
+ char *encodingScheme; /* key: EncodingScheme */
+ int capHeight; /* key: CapHeight */
+ int xHeight; /* key: XHeight */
+ int ascender; /* key: Ascender */
+ int descender; /* key: Descender */
+ int charwidth; /* key: CharWidth */
+} GlobalFontInfo;
+
+
+/* Ligature definition is a linked list since any character can have
+ * any number of ligatures.
+ */
+typedef struct _t_ligature
+{
+ char *succ, *lig;
+ struct _t_ligature *next;
+} Ligature;
+
+
+/* Character Metric Information. This structure is used only if ALL
+ * character metric information is requested. If only the character
+ * widths is requested, then only an array of the character x-widths
+ * is returned.
+ *
+ * The key that each field is associated with is in comments. For an
+ * explanation about each key and its value please refer to the
+ * Character Metrics section of the AFM documentation (full title
+ * & version given above).
+ */
+typedef struct
+{
+ int code, /* key: C */
+ wx, /* key: WX */
+ w0x, /* key: W0X */
+ wy; /* together wx and wy are associated with key: W */
+ char *name; /* key: N */
+ BBox charBBox; /* key: B */
+ Ligature *ligs; /* key: L (linked list; not a fixed number of Ls */
+} CharMetricInfo;
+
+
+/* Track kerning data structure.
+ * The fields of this record are the five values associated with every
+ * TrackKern entry.
+ *
+ * For an explanation about each value please refer to the
+ * Track Kerning section of the AFM documentation (full title
+ * & version given above).
+ */
+typedef struct
+{
+ int degree;
+ float minPtSize,
+ minKernAmt,
+ maxPtSize,
+ maxKernAmt;
+} TrackKernData;
+
+
+/* Pair Kerning data structure.
+ * The fields of this record are the four values associated with every
+ * KP entry. For KPX entries, the yamt will be zero.
+ *
+ * For an explanation about each value please refer to the
+ * Pair Kerning section of the AFM documentation (full title
+ * & version given above).
+ */
+typedef struct
+{
+ char *name1;
+ char *name2;
+ int xamt,
+ yamt;
+} PairKernData;
+
+
+/* PCC is a piece of a composite character. This is a sub structure of a
+ * compCharData described below.
+ * These fields will be filled in with the values from the key PCC.
+ *
+ * For an explanation about each key and its value please refer to the
+ * Composite Character section of the AFM documentation (full title
+ * & version given above).
+ */
+typedef struct
+{
+ char *pccName;
+ int deltax,
+ deltay;
+} Pcc;
+
+
+/* Composite Character Information data structure.
+ * The fields ccName and numOfPieces are filled with the values associated
+ * with the key CC. The field pieces points to an array (size = numOfPieces)
+ * of information about each of the parts of the composite character. That
+ * array is filled in with the values from the key PCC.
+ *
+ * For an explanation about each key and its value please refer to the
+ * Composite Character section of the AFM documentation (full title
+ * & version given above).
+ */
+typedef struct
+{
+ char *ccName;
+ int numOfPieces;
+ Pcc *pieces;
+} CompCharData;
+
+
+/* FontInfo
+ * Record type containing pointers to all of the other data
+ * structures containing information about a font.
+ * A a record of this type is filled with data by the
+ * parseFile function.
+ */
+typedef struct
+{
+ GlobalFontInfo *gfi; /* ptr to a GlobalFontInfo record */
+ int *cwi; /* ptr to 256 element array of just char widths */
+ int numOfChars; /* number of entries in char metrics array */
+ CharMetricInfo *cmi; /* ptr to char metrics array */
+ int numOfTracks; /* number to entries in track kerning array */
+ TrackKernData *tkd; /* ptr to track kerning array */
+ int numOfPairs; /* number to entries in pair kerning array */
+ PairKernData *pkd; /* ptr to pair kerning array */
+ int numOfComps; /* number to entries in comp char array */
+ CompCharData *ccd; /* ptr to comp char array */
+} FontInfo;
+
+
+
+/************************* PROCEDURES ****************************/
+
+/* Call this procedure to do the grunt work of parsing an AFM file.
+ *
+ * "fp" should be a valid file pointer to an AFM file.
+ *
+ * "fi" is a pointer to a pointer to a FontInfo record sturcture
+ * (defined above). Storage for the FontInfo structure will be
+ * allocated in parseFile and the structure will be filled in
+ * with the requested data from the AFM File.
+ *
+ * "flags" is a mask with bits set representing what data should
+ * be saved. Defined above are valid flags that can be used to set
+ * the mask, as well as a few commonly used masks.
+ *
+ * The possible return codes from parseFile are defined above.
+ */
+
+int parseFile( FILE *fp, FontInfo **fi, FLAGS flags );
+void freeFontInfo(FontInfo *fi);
+
+} // namespace
diff --git a/psprint/source/fontsubset/crc32.c b/psprint/source/fontsubset/crc32.c
new file mode 100644
index 000000000000..f614696fa5e6
--- /dev/null
+++ b/psprint/source/fontsubset/crc32.c
@@ -0,0 +1,120 @@
+/*************************************************************************
+ *
+ * $RCSfile: crc32.c,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Alexander Gelfenbain
+ *
+ *
+ ************************************************************************/
+
+/* $Id: crc32.c,v 1.1.1.1 2001-05-08 11:45:36 pl Exp $ */
+
+/**
+ *
+ * @file crc32.c
+ * @brief CRC-32 calculation function
+ * @author Alexander Gelfenbain
+ */
+
+#include "sft.h"
+#include "crc32.h"
+
+static uint32 crcTable[256] = {
+ 0x00000000UL, 0x77073096UL, 0xEE0E612CUL, 0x990951BAUL, 0x076DC419UL, 0x706AF48FUL, 0xE963A535UL, 0x9E6495A3UL,
+ 0x0EDB8832UL, 0x79DCB8A4UL, 0xE0D5E91EUL, 0x97D2D988UL, 0x09B64C2BUL, 0x7EB17CBDUL, 0xE7B82D07UL, 0x90BF1D91UL,
+ 0x1DB71064UL, 0x6AB020F2UL, 0xF3B97148UL, 0x84BE41DEUL, 0x1ADAD47DUL, 0x6DDDE4EBUL, 0xF4D4B551UL, 0x83D385C7UL,
+ 0x136C9856UL, 0x646BA8C0UL, 0xFD62F97AUL, 0x8A65C9ECUL, 0x14015C4FUL, 0x63066CD9UL, 0xFA0F3D63UL, 0x8D080DF5UL,
+ 0x3B6E20C8UL, 0x4C69105EUL, 0xD56041E4UL, 0xA2677172UL, 0x3C03E4D1UL, 0x4B04D447UL, 0xD20D85FDUL, 0xA50AB56BUL,
+ 0x35B5A8FAUL, 0x42B2986CUL, 0xDBBBC9D6UL, 0xACBCF940UL, 0x32D86CE3UL, 0x45DF5C75UL, 0xDCD60DCFUL, 0xABD13D59UL,
+ 0x26D930ACUL, 0x51DE003AUL, 0xC8D75180UL, 0xBFD06116UL, 0x21B4F4B5UL, 0x56B3C423UL, 0xCFBA9599UL, 0xB8BDA50FUL,
+ 0x2802B89EUL, 0x5F058808UL, 0xC60CD9B2UL, 0xB10BE924UL, 0x2F6F7C87UL, 0x58684C11UL, 0xC1611DABUL, 0xB6662D3DUL,
+ 0x76DC4190UL, 0x01DB7106UL, 0x98D220BCUL, 0xEFD5102AUL, 0x71B18589UL, 0x06B6B51FUL, 0x9FBFE4A5UL, 0xE8B8D433UL,
+ 0x7807C9A2UL, 0x0F00F934UL, 0x9609A88EUL, 0xE10E9818UL, 0x7F6A0DBBUL, 0x086D3D2DUL, 0x91646C97UL, 0xE6635C01UL,
+ 0x6B6B51F4UL, 0x1C6C6162UL, 0x856530D8UL, 0xF262004EUL, 0x6C0695EDUL, 0x1B01A57BUL, 0x8208F4C1UL, 0xF50FC457UL,
+ 0x65B0D9C6UL, 0x12B7E950UL, 0x8BBEB8EAUL, 0xFCB9887CUL, 0x62DD1DDFUL, 0x15DA2D49UL, 0x8CD37CF3UL, 0xFBD44C65UL,
+ 0x4DB26158UL, 0x3AB551CEUL, 0xA3BC0074UL, 0xD4BB30E2UL, 0x4ADFA541UL, 0x3DD895D7UL, 0xA4D1C46DUL, 0xD3D6F4FBUL,
+ 0x4369E96AUL, 0x346ED9FCUL, 0xAD678846UL, 0xDA60B8D0UL, 0x44042D73UL, 0x33031DE5UL, 0xAA0A4C5FUL, 0xDD0D7CC9UL,
+ 0x5005713CUL, 0x270241AAUL, 0xBE0B1010UL, 0xC90C2086UL, 0x5768B525UL, 0x206F85B3UL, 0xB966D409UL, 0xCE61E49FUL,
+ 0x5EDEF90EUL, 0x29D9C998UL, 0xB0D09822UL, 0xC7D7A8B4UL, 0x59B33D17UL, 0x2EB40D81UL, 0xB7BD5C3BUL, 0xC0BA6CADUL,
+ 0xEDB88320UL, 0x9ABFB3B6UL, 0x03B6E20CUL, 0x74B1D29AUL, 0xEAD54739UL, 0x9DD277AFUL, 0x04DB2615UL, 0x73DC1683UL,
+ 0xE3630B12UL, 0x94643B84UL, 0x0D6D6A3EUL, 0x7A6A5AA8UL, 0xE40ECF0BUL, 0x9309FF9DUL, 0x0A00AE27UL, 0x7D079EB1UL,
+ 0xF00F9344UL, 0x8708A3D2UL, 0x1E01F268UL, 0x6906C2FEUL, 0xF762575DUL, 0x806567CBUL, 0x196C3671UL, 0x6E6B06E7UL,
+ 0xFED41B76UL, 0x89D32BE0UL, 0x10DA7A5AUL, 0x67DD4ACCUL, 0xF9B9DF6FUL, 0x8EBEEFF9UL, 0x17B7BE43UL, 0x60B08ED5UL,
+ 0xD6D6A3E8UL, 0xA1D1937EUL, 0x38D8C2C4UL, 0x4FDFF252UL, 0xD1BB67F1UL, 0xA6BC5767UL, 0x3FB506DDUL, 0x48B2364BUL,
+ 0xD80D2BDAUL, 0xAF0A1B4CUL, 0x36034AF6UL, 0x41047A60UL, 0xDF60EFC3UL, 0xA867DF55UL, 0x316E8EEFUL, 0x4669BE79UL,
+ 0xCB61B38CUL, 0xBC66831AUL, 0x256FD2A0UL, 0x5268E236UL, 0xCC0C7795UL, 0xBB0B4703UL, 0x220216B9UL, 0x5505262FUL,
+ 0xC5BA3BBEUL, 0xB2BD0B28UL, 0x2BB45A92UL, 0x5CB36A04UL, 0xC2D7FFA7UL, 0xB5D0CF31UL, 0x2CD99E8BUL, 0x5BDEAE1DUL,
+ 0x9B64C2B0UL, 0xEC63F226UL, 0x756AA39CUL, 0x026D930AUL, 0x9C0906A9UL, 0xEB0E363FUL, 0x72076785UL, 0x05005713UL,
+ 0x95BF4A82UL, 0xE2B87A14UL, 0x7BB12BAEUL, 0x0CB61B38UL, 0x92D28E9BUL, 0xE5D5BE0DUL, 0x7CDCEFB7UL, 0x0BDBDF21UL,
+ 0x86D3D2D4UL, 0xF1D4E242UL, 0x68DDB3F8UL, 0x1FDA836EUL, 0x81BE16CDUL, 0xF6B9265BUL, 0x6FB077E1UL, 0x18B74777UL,
+ 0x88085AE6UL, 0xFF0F6A70UL, 0x66063BCAUL, 0x11010B5CUL, 0x8F659EFFUL, 0xF862AE69UL, 0x616BFFD3UL, 0x166CCF45UL,
+ 0xA00AE278UL, 0xD70DD2EEUL, 0x4E048354UL, 0x3903B3C2UL, 0xA7672661UL, 0xD06016F7UL, 0x4969474DUL, 0x3E6E77DBUL,
+ 0xAED16A4AUL, 0xD9D65ADCUL, 0x40DF0B66UL, 0x37D83BF0UL, 0xA9BCAE53UL, 0xDEBB9EC5UL, 0x47B2CF7FUL, 0x30B5FFE9UL,
+ 0xBDBDF21CUL, 0xCABAC28AUL, 0x53B39330UL, 0x24B4A3A6UL, 0xBAD03605UL, 0xCDD70693UL, 0x54DE5729UL, 0x23D967BFUL,
+ 0xB3667A2EUL, 0xC4614AB8UL, 0x5D681B02UL, 0x2A6F2B94UL, 0xB40BBE37UL, 0xC30C8EA1UL, 0x5A05DF1BUL, 0x2D02EF8DUL
+};
+
+uint32 crc32(const void *ptr, size_t len)
+{
+ uint32 crc = 0xFFFFFFFF;
+ const byte *bp = (const byte *) ptr;
+ size_t i;
+
+ for (i=0; i<len; i++) {
+ crc = crcTable[(crc ^ bp[i]) & 0xFF] ^ (crc >> 8);
+ }
+
+ return crc ^ 0xFFFFFFFF;
+}
diff --git a/psprint/source/fontsubset/crc32.h b/psprint/source/fontsubset/crc32.h
new file mode 100644
index 000000000000..8fe50e1076dd
--- /dev/null
+++ b/psprint/source/fontsubset/crc32.h
@@ -0,0 +1,79 @@
+/*************************************************************************
+ *
+ * $RCSfile: crc32.h,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Alexander Gelfenbain
+ *
+ *
+ ************************************************************************/
+
+/* $Id: crc32.h,v 1.1.1.1 2001-05-08 11:45:36 pl Exp $ */
+
+/**
+ *
+ * @file crc32.h
+ * @brief CRC-32 calculation function
+ * @author Alexander Gelfenbain
+ */
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+ uint32 crc32(const void *ptr, size_t len);
+#ifdef __cplusplus
+}
+#endif
diff --git a/psprint/source/fontsubset/gsub.cxx b/psprint/source/fontsubset/gsub.cxx
new file mode 100644
index 000000000000..95a4209268ae
--- /dev/null
+++ b/psprint/source/fontsubset/gsub.cxx
@@ -0,0 +1,319 @@
+/*************************************************************************
+ *
+ * $RCSfile: gsub.cxx,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+extern "C"
+{
+#include "sft.h"
+#undef true
+#undef false
+
+#include "gsub.h"
+}
+
+#include <vector>
+#include <map>
+#include <algorithm>
+
+typedef uint32 ULONG;
+typedef uint16 USHORT;
+typedef uint8 FT_Byte;
+
+typedef std::map<USHORT,USHORT> GlyphSubstitution;
+
+
+inline long NEXT_Long( const unsigned char* &p )
+{
+ long nVal = (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3];
+ p += 4;
+ return nVal;
+}
+
+inline long NEXT_UShort( const unsigned char* &p )
+{
+ long nVal = (p[0]<<8) + p[1];
+ p += 2;
+ return nVal;
+}
+
+#define MKTAG(s) ((((((s[0]<<8)+s[1])<<8)+s[2])<<8)+s[3])
+
+int ReadGSUB( struct _TrueTypeFont* pTTFile, unsigned char* pGsubBase,
+ int nRequestedScript, int nRequestedLangsys )
+{
+ if( !pGsubBase )
+ return -1;
+
+ typedef std::vector<ULONG> ReqFeatureTagList;
+ ReqFeatureTagList aReqFeatureTagList;
+
+ aReqFeatureTagList.push_back( MKTAG("vert") );
+
+ // parse GSUB header
+ const FT_Byte* pGsubHeader = pGsubBase;
+ const ULONG nVersion = NEXT_Long( pGsubHeader );
+ const USHORT nOfsScriptList = NEXT_UShort( pGsubHeader );
+ const USHORT nOfsFeatureTable = NEXT_UShort( pGsubHeader );
+ const USHORT nOfsLookupList = NEXT_UShort( pGsubHeader );
+
+ typedef std::vector<USHORT> UshortList;
+ UshortList aFeatureIndexList;
+ UshortList aFeatureOffsetList;
+
+ // parse Script Table
+ const FT_Byte* pScriptHeader = pGsubBase + nOfsScriptList;
+ const USHORT nCntScript = NEXT_UShort( pScriptHeader );
+ for( USHORT nScriptIndex = 0; nScriptIndex < nCntScript; ++nScriptIndex )
+ {
+ const ULONG nTag = NEXT_Long( pScriptHeader ); // e.g. hani/arab/kana/hang
+ const USHORT nOfsScriptTable= NEXT_UShort( pScriptHeader );
+ if( (nTag != nRequestedScript) && (nRequestedScript != 0) )
+ continue;
+
+ const FT_Byte* pScriptTable = pGsubBase + nOfsScriptList + nOfsScriptTable;
+ const USHORT nDefaultLangsysOfs = NEXT_UShort( pScriptTable );
+ const USHORT nCntLangSystem = NEXT_UShort( pScriptTable );
+ USHORT nLangsysOffset = 0;
+ for( USHORT nLangsysIndex = 0; nLangsysIndex < nCntLangSystem; ++nLangsysIndex )
+ {
+ const ULONG nTag = NEXT_Long( pScriptTable ); // e.g. KOR/ZHS/ZHT/JAN
+ const USHORT nOffset= NEXT_UShort( pScriptTable );
+ if( (nTag != nRequestedLangsys) && (nRequestedLangsys != 0) )
+ continue;
+ nLangsysOffset = nOffset;
+ break;
+ }
+
+ if( (nDefaultLangsysOfs != 0) && (nDefaultLangsysOfs != nLangsysOffset) )
+ {
+ const FT_Byte* pLangSys = pGsubBase + nOfsScriptList + nOfsScriptTable + nDefaultLangsysOfs;
+ const USHORT nLookupOrder = NEXT_UShort( pLangSys );
+ const USHORT nReqFeatureIdx = NEXT_UShort( pLangSys );
+ const USHORT nCntFeature = NEXT_UShort( pLangSys );
+ aFeatureIndexList.push_back( nReqFeatureIdx );
+ for( USHORT i = 0; i < nCntFeature; ++i )
+ {
+ const USHORT nFeatureIndex = NEXT_UShort( pLangSys );
+ aFeatureIndexList.push_back( nFeatureIndex );
+ }
+ }
+
+ if( nLangsysOffset != 0 )
+ {
+ const FT_Byte* pLangSys = pGsubBase + nOfsScriptList + nOfsScriptTable + nLangsysOffset;
+ const USHORT nLookupOrder = NEXT_UShort( pLangSys );
+ const USHORT nReqFeatureIdx = NEXT_UShort( pLangSys );
+ const USHORT nCntFeature = NEXT_UShort( pLangSys );
+ aFeatureIndexList.push_back( nReqFeatureIdx );
+ for( USHORT i = 0; i < nCntFeature; ++i )
+ {
+ const USHORT nFeatureIndex = NEXT_UShort( pLangSys );
+ aFeatureIndexList.push_back( nFeatureIndex );
+ }
+ }
+ }
+
+ if( !aFeatureIndexList.size() )
+ return true;
+
+ UshortList aLookupIndexList;
+ UshortList aLookupOffsetList;
+
+ // parse Feature Table
+ const FT_Byte* pFeatureHeader = pGsubBase + nOfsFeatureTable;
+ const USHORT nCntFeature = NEXT_UShort( pFeatureHeader );
+ for( USHORT nFeatureIndex = 0; nFeatureIndex < nCntFeature; ++nFeatureIndex )
+ {
+ const ULONG nTag = NEXT_Long( pFeatureHeader ); // e.g. locl/vert/trad/smpl/liga/fina/...
+ const USHORT nOffset= NEXT_UShort( pFeatureHeader );
+
+ // feature (required && (requested || available))?
+ if( (aFeatureIndexList[0] != nFeatureIndex)
+ && (!std::count( aReqFeatureTagList.begin(), aReqFeatureTagList.end(), nTag))
+ || (!std::count( aFeatureIndexList.begin(), aFeatureIndexList.end(), nFeatureIndex) ) )
+ continue;
+
+ const FT_Byte* pFeatureTable = pGsubBase + nOfsFeatureTable + nOffset;
+ const USHORT nCntLookups = NEXT_UShort( pFeatureTable );
+ for( USHORT i = 0; i < nCntLookups; ++i )
+ {
+ const USHORT nLookupIndex = NEXT_UShort( pFeatureTable );
+ aLookupIndexList.push_back( nLookupIndex );
+ }
+ if( nCntLookups == 0 ) //### hack needed by Mincho/Gothic/Mingliu/Simsun/...
+ aLookupIndexList.push_back( 0 );
+ }
+
+ // parse Lookup List
+ const FT_Byte* pLookupHeader = pGsubBase + nOfsLookupList;
+ const USHORT nCntLookupTable = NEXT_UShort( pLookupHeader );
+ for( USHORT nLookupIdx = 0; nLookupIdx < nCntLookupTable; ++nLookupIdx )
+ {
+ const USHORT nOffset = NEXT_UShort( pLookupHeader );
+ if( std::count( aLookupIndexList.begin(), aLookupIndexList.end(), nLookupIdx ) )
+ aLookupOffsetList.push_back( nOffset );
+ }
+
+ UshortList::const_iterator it = aLookupOffsetList.begin();
+ for(; it != aLookupOffsetList.end(); ++it )
+ {
+ const USHORT nOfsLookupTable = *it;
+ const FT_Byte* pLookupTable = pGsubBase + nOfsLookupList + nOfsLookupTable;
+ const USHORT eLookupType = NEXT_UShort( pLookupTable );
+ const USHORT eLookupFlag = NEXT_UShort( pLookupTable );
+ const USHORT nCntLookupSubtable = NEXT_UShort( pLookupTable );
+
+ // TODO: switch( eLookupType )
+ if( eLookupType != 1 ) // TODO: once we go beyond SingleSubst
+ continue;
+
+ for( USHORT nSubTableIdx = 0; nSubTableIdx < nCntLookupSubtable; ++nSubTableIdx )
+ {
+ const USHORT nOfsSubLookupTable = NEXT_UShort( pLookupTable );
+ const FT_Byte* pSubLookup = pGsubBase + nOfsLookupList + nOfsLookupTable + nOfsSubLookupTable;
+
+ const USHORT nFmtSubstitution = NEXT_UShort( pSubLookup );
+ const USHORT nOfsCoverage = NEXT_UShort( pSubLookup );
+
+ typedef std::pair<USHORT,USHORT> GlyphSubst;
+ typedef std::vector<GlyphSubst> SubstVector;
+ SubstVector aSubstVector;
+
+ const FT_Byte* pCoverage = pGsubBase + nOfsLookupList + nOfsLookupTable + nOfsSubLookupTable + nOfsCoverage;
+ const USHORT nFmtCoverage = NEXT_UShort( pCoverage );
+ switch( nFmtCoverage )
+ {
+ case 1: // Coverage Format 1
+ {
+ const USHORT nCntGlyph = NEXT_UShort( pCoverage );
+ aSubstVector.reserve( nCntGlyph );
+ for( USHORT i = 0; i < nCntGlyph; ++i )
+ {
+ const USHORT nGlyphId = NEXT_UShort( pCoverage );
+ aSubstVector.push_back( GlyphSubst( nGlyphId, 0 ) );
+ }
+ }
+ break;
+
+ case 2: // Coverage Format 2
+ {
+ const USHORT nCntRange = NEXT_UShort( pCoverage );
+ for( int i = nCntRange; --i >= 0; )
+ {
+ const USHORT nGlyph0 = NEXT_UShort( pCoverage );
+ const USHORT nGlyph1 = NEXT_UShort( pCoverage );
+ const USHORT nCovIdx = NEXT_UShort( pCoverage );
+ for( USHORT j = nGlyph0; j <= nGlyph1; ++j )
+ aSubstVector.push_back( GlyphSubst( j + nCovIdx, 0 ) );
+ }
+ }
+ break;
+ }
+
+ SubstVector::iterator it( aSubstVector.begin() );
+
+ switch( nFmtSubstitution )
+ {
+ case 1: // Single Substitution Format 1
+ {
+ const USHORT nDeltaGlyphId = NEXT_UShort( pSubLookup );
+ for(; it != aSubstVector.end(); ++it )
+ (*it).second = (*it).first + nDeltaGlyphId;
+ }
+ break;
+
+ case 2: // Single Substitution Format 2
+ {
+ const USHORT nCntGlyph = NEXT_UShort( pSubLookup );
+ for( int i = nCntGlyph; (it != aSubstVector.end()) && (--i>=0); ++it )
+ {
+ const USHORT nGlyphId = NEXT_UShort( pSubLookup );
+ (*it).second = nGlyphId;
+ }
+ }
+ break;
+ }
+
+ // now apply the glyph substitutions that have been collected in this subtable
+ if( aSubstVector.size() > 0 )
+ {
+ GlyphSubstitution* pGSubstitution = new GlyphSubstitution;
+ pTTFile->pGSubstitution = (void*)pGSubstitution;
+ for( it = aSubstVector.begin(); it != aSubstVector.end(); ++it )
+ (*pGSubstitution)[ (*it).first ] = (*it).second;
+ }
+ }
+ }
+
+ return true;
+}
+
+int UseGSUB( struct _TrueTypeFont* pTTFile, int nGlyph, int wmode )
+{
+ GlyphSubstitution* pGlyphSubstitution = (GlyphSubstitution*)pTTFile->pGSubstitution;
+ if( pGlyphSubstitution != 0 )
+ {
+ GlyphSubstitution::const_iterator it( pGlyphSubstitution->find( nGlyph ) );
+ if( it != pGlyphSubstitution->end() )
+ nGlyph = (*it).second;
+ }
+
+ return nGlyph;
+}
diff --git a/psprint/source/fontsubset/gsub.h b/psprint/source/fontsubset/gsub.h
new file mode 100644
index 000000000000..97ed37637c54
--- /dev/null
+++ b/psprint/source/fontsubset/gsub.h
@@ -0,0 +1,70 @@
+/*************************************************************************
+ *
+ * $RCSfile: gsub.h,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): _______________________________________
+ *
+ *
+ ************************************************************************/
+
+#ifndef _PSP_GSUB_H
+#define _PSP_GSUB_H
+
+int UseGSUB( struct _TrueTypeFont* pTTFile, int nGlyph, int wmode );
+
+int ReadGSUB( struct _TrueTypeFont* pTTFile, unsigned char* pGsubBase,
+ int nRequestedScript, int nRequestedLangsys );
+
+#endif /* _PSP_GSUB_H */
diff --git a/psprint/source/fontsubset/list.c b/psprint/source/fontsubset/list.c
new file mode 100644
index 000000000000..8bcc69f65b55
--- /dev/null
+++ b/psprint/source/fontsubset/list.c
@@ -0,0 +1,623 @@
+/*************************************************************************
+ *
+ * $RCSfile: list.c,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Alexander Gelfenbain
+ *
+ *
+ ************************************************************************/
+
+/* $Id: list.c,v 1.1.1.1 2001-05-08 11:45:36 pl Exp $ */
+
+/*[]---------------------------------------------------[]*/
+/*| |*/
+/*| list.c - bidirectional list class |*/
+/*| |*/
+/*| |*/
+/*| Author: Alexander Gelfenbain |*/
+/*[]---------------------------------------------------[]*/
+
+#include <stdlib.h>
+#include <assert.h>
+#ifdef MALLOC_TRACE
+#include <stdio.h>
+#include </usr/local/include/malloc.h>
+#endif
+#include "list.h"
+
+/*- private data types */
+typedef struct _lnode {
+ struct _lnode *next;
+ struct _lnode *prev;
+
+ void *value;
+
+} lnode;
+
+struct _list {
+ lnode *head, *tail, *cptr;
+ size_t aCount;
+ void (*eDtor)(void *);
+};
+
+/*- private methods */
+
+static lnode *newNode(void *el)
+{
+ lnode *ptr = malloc(sizeof(lnode));
+ assert(ptr != 0);
+
+ ptr->value = el;
+
+ return ptr;
+}
+
+static lnode *appendPrim(list this, void *el)
+{
+ lnode *ptr = newNode(el);
+ lnode **flink, *blink;
+
+ if (this->tail != 0) {
+ flink = &(this->tail->next);
+ blink = this->tail;
+ } else {
+ flink = &this->head;
+ blink = 0;
+ this->cptr = ptr; /*- list was empty - set current to this element */
+ }
+
+ *flink = ptr;
+ this->tail = ptr;
+
+ ptr->prev = blink;
+ ptr->next = 0;
+
+ this->aCount++;
+ return ptr;
+}
+
+static lnode *prependPrim(list this, void *el)
+{
+ lnode *ptr = newNode(el);
+ lnode *flink, **blink;
+
+ if (this->head != 0) {
+ blink = &(this->head->prev);
+ flink = this->head;
+ } else {
+ blink = &this->tail;
+ flink = 0;
+ this->cptr = ptr; /*- list was empty - set current to this element */
+ }
+
+ *blink = ptr;
+ this->head = ptr;
+
+ ptr->next = flink;
+ ptr->prev = 0;
+
+ this->aCount++;
+ return ptr;
+}
+
+
+/*- public methods */
+list listNewEmpty(void) /*- default ctor */
+{
+ list this = malloc(sizeof(struct _list));
+ assert(this != 0);
+
+ this->aCount = 0;
+ this->eDtor = 0;
+ this->head = this->tail = this->cptr = 0;
+
+ return this;
+}
+
+list listNewCopy(list l) /*- copy ctor */
+{
+ lnode *ptr, *c;
+ list this;
+ assert(l != 0);
+
+ this = malloc(sizeof(struct _list));
+ assert(this != 0);
+
+ ptr = l->head;
+
+ this->aCount = 0;
+ this->eDtor = 0;
+ this->head = this->tail = this->cptr = 0;
+
+ while (ptr) {
+ c = appendPrim(this, ptr->value);
+ if (ptr == l->cptr) this->cptr = c;
+ ptr = ptr->next;
+ }
+
+ return this;
+}
+
+void listDispose(list this) /*- dtor */
+{
+ assert(this != 0);
+ listClear(this);
+ free(this);
+}
+
+void listSetElementDtor(list this, void (*f)(void *))
+{
+ assert(this != 0);
+ this->eDtor = f;
+}
+
+
+list listCopy(list to, list from) /*- assignment */
+{
+ lnode *ptr, *c;
+ assert(to != 0);
+ assert(from != 0);
+
+ listClear(to);
+ ptr = from->head;
+
+ while (ptr) {
+ c = appendPrim(to, ptr->value);
+ if (ptr == from->cptr) to->cptr = c;
+ ptr = ptr->next;
+ }
+
+ return to;
+}
+
+
+/* calling this function on an empty list is a run-time error */
+void *listCurrent(list this)
+{
+ assert(this != 0);
+ assert(this->cptr != 0);
+ return this->cptr->value;
+}
+
+int listCount(list this)
+{
+ assert(this != 0);
+ return this->aCount;
+}
+
+int listIsEmpty(list this)
+{
+ assert(this != 0);
+ return this->aCount == 0;
+}
+
+
+int listAtFirst(list this)
+{
+ assert(this != 0);
+ return this->cptr == this->head;
+}
+
+int listAtLast(list this)
+{
+ assert(this != 0);
+ return this->cptr == this->tail;
+}
+
+int listPosition(list this)
+{
+ int res = 0;
+ lnode *ptr;
+ assert(this != 0);
+
+ ptr = this->head;
+
+ while (ptr != this->cptr) {
+ ptr = ptr->next;
+ res++;
+ }
+
+ return res;
+}
+
+int listFind(list this, void *el)
+{
+ lnode *ptr;
+ assert(this != 0);
+
+ ptr = this->head;
+
+ while (ptr) {
+ if (ptr->value == el) {
+ this->cptr = ptr;
+ return 1;
+ }
+ ptr = ptr->next;
+ }
+
+ return 0;
+}
+
+int listNext(list this)
+{
+ return listSkipForward(this, 1);
+}
+
+int listPrev(list this)
+{
+ return listSkipBackward(this, 1);
+}
+
+int listSkipForward(list this, int n)
+{
+ int m = 0;
+ assert(this != 0);
+
+ if (this->cptr == 0) return 0;
+
+ while (n != 0) {
+ if (this->cptr->next == 0) break;
+ this->cptr = this->cptr->next;
+ n--;
+ m++;
+ }
+ return m;
+}
+
+int listSkipBackward(list this, int n)
+{
+ int m = 0;
+ assert(this != 0);
+
+ if (this->cptr == 0) return 0;
+
+ while (n != 0) {
+ if (this->cptr->prev == 0) break;
+ this->cptr = this->cptr->prev;
+ n--;
+ m++;
+ }
+ return m;
+}
+
+int listToFirst(list this)
+{
+ assert(this != 0);
+
+ if (this->cptr != this->head) {
+ this->cptr = this->head;
+ return 1;
+ }
+ return 0;
+}
+
+int listToLast(list this)
+{
+ assert(this != 0);
+
+ if (this->cptr != this->tail) {
+ this->cptr = this->tail;
+ return 1;
+ }
+ return 0;
+}
+
+int listPositionAt(list this, int n) /*- returns the actual position number */
+{
+ int m = 0;
+ assert(this != 0);
+
+ this->cptr = this->head;
+ while (n != 0) {
+ if (this->cptr->next == 0) break;
+ this->cptr = this->cptr->next;
+ n--;
+ m++;
+ }
+ return m;
+}
+
+list listAppend(list this, void *el)
+{
+ assert(this != 0);
+
+ appendPrim(this, el);
+ return this;
+}
+
+list listPrepend(list this, void *el)
+{
+ assert(this != 0);
+
+ prependPrim(this, el);
+ return this;
+}
+
+list listInsertAfter(list this, void *el)
+{
+ lnode *ptr;
+ assert(this != 0);
+
+ if (this->cptr == 0) return listAppend(this, el);
+
+ ptr = newNode(el);
+
+ ptr->prev = this->cptr;
+ ptr->next = this->cptr->next;
+ this->cptr->next = ptr;
+
+ if (ptr->next != 0) {
+ ptr->next->prev = ptr;
+ } else {
+ this->tail = ptr;
+ }
+ this->aCount++;
+ return this;
+}
+
+list listInsertBefore(list this, void *el)
+{
+ lnode *ptr;
+ assert(this != 0);
+
+ if (this->cptr == 0) return listAppend(this, el);
+
+ ptr = newNode(el);
+
+ ptr->prev = this->cptr->prev;
+ ptr->next = this->cptr;
+ this->cptr->prev = ptr;
+
+ if (ptr->prev != 0) {
+ ptr->prev->next = ptr;
+ } else {
+ this->head = ptr;
+ }
+ this->aCount++;
+ return this;
+}
+
+list listRemove(list this)
+{
+ lnode *ptr = 0;
+ if (this->cptr == 0) return this;
+
+ if (this->cptr->next != 0) {
+ ptr = this->cptr->next;
+ this->cptr->next->prev = this->cptr->prev;
+ } else {
+ this->tail = this->cptr->prev;
+ }
+
+ if (this->cptr->prev != 0) {
+ if (ptr == 0) ptr = this->cptr->prev;
+ this->cptr->prev->next = this->cptr->next;
+ } else {
+ this->head = this->cptr->next;
+ }
+
+ if (this->eDtor) this->eDtor(this->cptr->value); /* call the dtor callback */
+
+ free(this->cptr);
+ this->aCount--;
+ this->cptr = ptr;
+ return this;
+}
+
+list listClear(list this)
+{
+ lnode *node = this->head, *ptr;
+
+ while (node) {
+ ptr = node->next;
+ if (this->eDtor) this->eDtor(node->value); /* call the dtor callback */
+ free(node);
+ this->aCount--;
+ node = ptr;
+ }
+
+ this->head = this->tail = this->cptr = 0;
+ assert(this->aCount == 0);
+ return this;
+}
+
+void listForAll(list this, void (*f)(void *))
+{
+ lnode *ptr = this->head;
+ while (ptr) {
+ f(ptr->value);
+ ptr = ptr->next;
+ }
+}
+
+void **listToArray(list this)
+{
+ void **res;
+ lnode *ptr = this->head;
+ int i = 0;
+
+ assert(this->aCount != 0);
+ res = calloc(this->aCount, sizeof(void *));
+ assert(res != 0);
+
+ while (ptr) {
+ res[i++] = ptr->value;
+ ptr = ptr->next;
+ }
+ return res;
+}
+
+
+/* #define TEST */
+#ifdef TEST
+#include <stdio.h>
+
+void printlist(list l)
+{
+ int saved;
+ assert(l != 0);
+ saved = listPosition(l);
+
+ printf("[ ");
+
+ if (!listIsEmpty(l)) {
+ listToFirst(l);
+ do {
+ printf("%d ", (int) listCurrent(l));
+ } while (listNext(l));
+ }
+
+ printf("]\n");
+
+ listPositionAt(l, saved);
+}
+
+void printstringlist(list l)
+{
+ int saved;
+ assert(l != 0);
+ saved = listPosition(l);
+
+ printf("[ ");
+
+ if (!listIsEmpty(l)) {
+ listToFirst(l);
+ do {
+ printf("'%s' ", (char *) listCurrent(l));
+ } while (listNext(l));
+ }
+
+ printf("]\n");
+
+ listPositionAt(l, saved);
+}
+
+void printstat(list l)
+{
+ printf("count: %d, position: %d, isEmpty: %d, atFirst: %d, atLast: %d.\n",
+ listCount(l), listPosition(l), listIsEmpty(l), listAtFirst(l), listAtLast(l));
+}
+
+void allfunc(void *e)
+{
+ printf("%d ", e);
+}
+
+void edtor(void *ptr)
+{
+ printf("element dtor: 0x%08x\n", ptr);
+ free(ptr);
+}
+
+int main()
+{
+ list l1, l2;
+ char *ptr;
+ int i;
+
+#ifdef MALLOC_TRACE
+ mal_leaktrace(1);
+ mal_debug(2);
+#endif
+
+ l1 = listNewEmpty();
+ printstat(l1);
+
+ listAppend(l1, 1);
+ printstat(l1);
+
+ listAppend(l1, 2);
+ printstat(l1);
+
+ listAppend(l1, 3);
+ printstat(l1);
+
+ printlist(l1);
+
+ listToFirst(l1);
+ listInsertBefore(l1, -5);
+ printlist(l1);
+
+ l2 = listNewCopy(l1);
+ printlist(l2);
+
+ listForAll(l2, allfunc);
+ printf("\n");
+
+ listClear(l1);
+ listSetElementDtor(l1, edtor);
+
+ for(i=0; i<10; i++) {
+ ptr = malloc(20);
+ sprintf(ptr, "element # %d", i);
+ listAppend(l1, ptr);
+ }
+
+ printstringlist(l1);
+
+
+ listDispose(l1);
+ listDispose(l2);
+
+#ifdef MALLOC_TRACE
+ mal_dumpleaktrace(stdout);
+#endif
+
+
+ return 0;
+}
+#endif
+
+
diff --git a/psprint/source/fontsubset/list.h b/psprint/source/fontsubset/list.h
new file mode 100644
index 000000000000..20f10530f78d
--- /dev/null
+++ b/psprint/source/fontsubset/list.h
@@ -0,0 +1,135 @@
+/*************************************************************************
+ *
+ * $RCSfile: list.h,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:36 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Alexander Gelfenbain
+ *
+ *
+ ************************************************************************/
+
+/* $Id: list.h,v 1.1.1.1 2001-05-08 11:45:36 pl Exp $ */
+
+/*[]---------------------------------------------------[]*/
+/*| |*/
+/*| Implementation of the list data type |*/
+/*| |*/
+/*| |*/
+/*| Author: Alexander Gelfenbain |*/
+/*[]---------------------------------------------------[]*/
+
+#ifndef __CLIST_H
+#define __CLIST_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*
+ * List of void * pointers
+ */
+
+ typedef struct _list *list;
+
+/*- constructors and a destructor */
+ list listNewEmpty(void);
+ list listNewCopy(list);
+ void listDispose(list);
+ void listSetElementDtor(list, void (*f)(void *)); /*- this function will be executed when the element is removed via listRemove() or listClear() */
+
+/*- assignment */
+ list listCopy(list to, list from);
+
+/*- queries */
+ void * listCurrent(list);
+ int listCount(list);
+ int listIsEmpty(list);
+ int listAtFirst(list);
+ int listAtLast(list);
+ int listPosition(list); /* Expensive! */
+
+/*- search */
+ int listFind(list, void *); /* Returns true/false */
+
+/*- positioning functions */
+/*- return the number of elements by which the current position in the list changes */
+ int listNext(list);
+ int listPrev(list);
+ int listSkipForward(list, int n);
+ int listSkipBackward(list, int n);
+ int listToFirst(list);
+ int listToLast(list);
+ int listPositionAt(list, int n); /* Expensive! */
+
+/*- adding and removing elements */
+ list listAppend(list, void *);
+ list listPrepend(list, void *);
+ list listInsertAfter(list, void *);
+ list listInsertBefore(list, void *);
+ list listRemove(list); /* removes the current element */
+ list listClear(list); /* removes all elements */
+
+/*- forall */
+ void listForAll(list, void (*f)(void *));
+
+/*- conversion */
+ void **listToArray(list);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* __CLIST_H */
diff --git a/psprint/source/fontsubset/makefile.mk b/psprint/source/fontsubset/makefile.mk
new file mode 100644
index 000000000000..15e389009286
--- /dev/null
+++ b/psprint/source/fontsubset/makefile.mk
@@ -0,0 +1,93 @@
+#*************************************************************************
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.1.1.1 $
+#
+# last change: $Author: pl $ $Date: 2001-05-08 11:45:36 $
+#
+# The Contents of this file are made available subject to the terms of
+# either of the following licenses
+#
+# - GNU Lesser General Public License Version 2.1
+# - Sun Industry Standards Source License Version 1.1
+#
+# Sun Microsystems Inc., October, 2000
+#
+# GNU Lesser General Public License Version 2.1
+# =============================================
+# Copyright 2000 by Sun Microsystems, Inc.
+# 901 San Antonio Road, Palo Alto, CA 94303, USA
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License version 2.1, as published by the Free Software Foundation.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+#
+# Sun Industry Standards Source License Version 1.1
+# =================================================
+# The contents of this file are subject to the Sun Industry Standards
+# Source License Version 1.1 (the "License"); You may not use this file
+# except in compliance with the License. You may obtain a copy of the
+# License at http://www.openoffice.org/license.html.
+#
+# Software provided under this License is provided on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+# WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+# MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+# See the License for the specific provisions governing your rights and
+# obligations concerning the Software.
+#
+# The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+#
+# Copyright: 2000 by Sun Microsystems, Inc.
+#
+# All Rights Reserved.
+#
+# Contributor(s): _______________________________________
+#
+#
+#
+#*************************************************************************
+
+PRJ=..$/..
+
+PRJNAME=psprint
+TARGET=fontsubset
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+
+.IF "$(OS)"=="MACOSX"
+
+dummy:
+ @echo "Nothing to build for Mac OS X"
+
+.ELSE # "$(OS)"=="MACOSX"
+
+SLOFILES=\
+ $(SLO)$/list.obj \
+ $(SLO)$/sft.obj \
+ $(SLO)$/xlat.obj \
+ $(SLO)$/crc32.obj \
+ $(SLO)$/ttcr.obj \
+ $(SLO)$/gsub.obj
+
+.ENDIF # "$(OS)"=="MACOSX"
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk
diff --git a/psprint/source/fontsubset/sft.c b/psprint/source/fontsubset/sft.c
new file mode 100644
index 000000000000..e82dac2aa573
--- /dev/null
+++ b/psprint/source/fontsubset/sft.c
@@ -0,0 +1,3074 @@
+/*************************************************************************
+ *
+ * $RCSfile: sft.c,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Alexander Gelfenbain
+ *
+ *
+ ************************************************************************/
+
+/* $Id: sft.c,v 1.1.1.1 2001-05-08 11:45:37 pl Exp $
+ * Sun Font Tools
+ *
+ * Author: Alexander Gelfenbain
+ *
+ */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include "sft.h"
+#include "gsub.h"
+#if ! (defined(NO_TTCR) && defined(NO_TYPE42))
+#include "ttcr.h"
+#endif
+#ifdef NO_LIST
+#include "list.h" /* list.h does not get included in the sft.h */
+#endif
+#ifndef NO_MAPPERS /* include MapChar() and MapString() */
+#include "xlat.h"
+#endif
+#ifndef NO_TYPE3 /* include CreateT3FromTTGlyphs() */
+#include "crc32.h"
+#endif
+
+#ifdef TEST7
+#include <ctype.h>
+#endif
+
+/*- module identification */
+
+const char *modname = "SunTypeTools-TT";
+const char *modver = "1.0";
+const char *modextra = "gelf";
+
+/*- private functions, constants and data types */ /*FOLD00*/
+
+enum PathSegmentType {
+ PS_NOOP = 0,
+ PS_MOVETO = 1,
+ PS_LINETO = 2,
+ PS_CURVETO = 3,
+ PS_CLOSEPATH = 4
+};
+
+typedef struct {
+ int type;
+ int x1, y1;
+ int x2, y2;
+ int x3, y3;
+} PSPathElement;
+
+/*- In horisontal writing mode right sidebearing is calculated using this formula
+ *- rsb = aw - (lsb + xMax - xMin) -*/
+typedef struct {
+ int16 xMin;
+ int16 yMin;
+ int16 xMax;
+ int16 yMax;
+ uint16 aw; /*- Advance Width (horisontal writing mode) */
+ int16 lsb; /*- Left sidebearing (horisontal writing mode) */
+ uint16 ah; /*- advance height (vertical writing mode) */
+ int16 tsb; /*- top sidebearing (vertical writing mode) */
+} TTGlyphMetrics;
+
+#define HFORMAT_LINELEN 64
+
+typedef struct {
+ FILE *o;
+ char buffer[HFORMAT_LINELEN];
+ int bufpos;
+ int total;
+} HexFmt;
+
+typedef struct {
+ uint32 nGlyphs; /* number of glyphs in the font + 1 */
+ uint32 *offs; /* array of nGlyphs offsets */
+} GlyphOffsets;
+
+/* private tags */
+static const uint32 TTFontClassTag = 0x74746663; /* 'ttfc' */
+
+static const uint32 T_true = 0x74727565; /* 'true' */
+static const uint32 T_ttcf = 0x74746366; /* 'ttcf' */
+
+/* standard TrueType table tags and their ordinal numbers */
+static const uint32 T_maxp = 0x6D617870; static const uint32 O_maxp = 0; /* 'maxp' */
+static const uint32 T_glyf = 0x676C7966; static const uint32 O_glyf = 1; /* 'glyf' */
+static const uint32 T_head = 0x68656164; static const uint32 O_head = 2; /* 'head' */
+static const uint32 T_loca = 0x6C6F6361; static const uint32 O_loca = 3; /* 'loca' */
+static const uint32 T_name = 0x6E616D65; static const uint32 O_name = 4; /* 'name' */
+static const uint32 T_hhea = 0x68686561; static const uint32 O_hhea = 5; /* 'hhea' */
+static const uint32 T_hmtx = 0x686D7478; static const uint32 O_hmtx = 6; /* 'hmtx' */
+static const uint32 T_cmap = 0x636D6170; static const uint32 O_cmap = 7; /* 'cmap' */
+static const uint32 T_vhea = 0x76686561; static const uint32 O_vhea = 8; /* 'vhea' */
+static const uint32 T_vmtx = 0x766D7478; static const uint32 O_vmtx = 9; /* 'vmtx' */
+static const uint32 T_OS2 = 0x4F532F32; static const uint32 O_OS2 = 10; /* 'OS/2' */
+static const uint32 T_post = 0x706F7374; static const uint32 O_post = 11; /* 'post' */
+static const uint32 T_kern = 0x6B65726E; static const uint32 O_kern = 12; /* 'kern' */
+static const uint32 T_cvt = 0x63767420; static const uint32 O_cvt = 13; /* 'cvt_' - only used in TT->TT generation */
+static const uint32 T_prep = 0x70726570; static const uint32 O_prep = 14; /* 'prep' - only used in TT->TT generation */
+static const uint32 T_fpgm = 0x6670676D; static const uint32 O_fpgm = 15; /* 'fpgm' - only used in TT->TT generation */
+static const uint32 T_gsub = 0x47535542; static const uint32 O_gsub = 16; /* 'GSUB' */
+#define NUM_TAGS 17
+
+#define LAST_URANGE_BIT 69
+const char *ulcodes[LAST_URANGE_BIT+2] = {
+ /* 0 */ "Basic Latin",
+ /* 1 */ "Latin-1 Supplement",
+ /* 2 */ "Latin Extended-A",
+ /* 3 */ "Latin Extended-B",
+ /* 4 */ "IPA Extensions",
+ /* 5 */ "Spacing Modifier Letters",
+ /* 6 */ "Combining Diacritical Marks",
+ /* 7 */ "Basic Greek",
+ /* 8 */ "Greek Symbols And Coptic",
+ /* 9 */ "Cyrillic",
+ /* 10 */ "Armenian",
+ /* 11 */ "Basic Hebrew",
+ /* 12 */ "Hebrew Extended (A and B blocks combined)",
+ /* 13 */ "Basic Arabic",
+ /* 14 */ "Arabic Extended",
+ /* 15 */ "Devanagari",
+ /* 16 */ "Bengali",
+ /* 17 */ "Gurmukhi",
+ /* 18 */ "Gujarati",
+ /* 19 */ "Oriya",
+ /* 20 */ "Tamil",
+ /* 21 */ "Telugu",
+ /* 22 */ "Kannada",
+ /* 23 */ "Malayalam",
+ /* 24 */ "Thai",
+ /* 25 */ "Lao",
+ /* 26 */ "Basic Georgian",
+ /* 27 */ "Georgian Extended",
+ /* 28 */ "Hangul Jamo",
+ /* 29 */ "Latin Extended Additional",
+ /* 30 */ "Greek Extended",
+ /* 31 */ "General Punctuation",
+ /* 32 */ "Superscripts And Subscripts",
+ /* 33 */ "Currency Symbols",
+ /* 34 */ "Combining Diacritical Marks For Symbols",
+ /* 35 */ "Letterlike Symbols",
+ /* 36 */ "Number Forms",
+ /* 37 */ "Arrows",
+ /* 38 */ "Mathematical Operators",
+ /* 39 */ "Miscellaneous Technical",
+ /* 40 */ "Control Pictures",
+ /* 41 */ "Optical Character Recognition",
+ /* 42 */ "Enclosed Alphanumerics",
+ /* 43 */ "Box Drawing",
+ /* 44 */ "Block Elements",
+ /* 45 */ "Geometric Shapes",
+ /* 46 */ "Miscellaneous Symbols",
+ /* 47 */ "Dingbats",
+ /* 48 */ "CJK Symbols And Punctuation",
+ /* 49 */ "Hiragana",
+ /* 50 */ "Katakana",
+ /* 51 */ "Bopomofo",
+ /* 52 */ "Hangul Compatibility Jamo",
+ /* 53 */ "CJK Miscellaneous",
+ /* 54 */ "Enclosed CJK Letters And Months",
+ /* 55 */ "CJK Compatibility",
+ /* 56 */ "Hangul",
+ /* 57 */ "Reserved for Unicode SubRanges",
+ /* 58 */ "Reserved for Unicode SubRanges",
+ /* 59 */ "CJK Unified Ideographs",
+ /* 60 */ "Private Use Area",
+ /* 61 */ "CJK Compatibility Ideographs",
+ /* 62 */ "Alphabetic Presentation Forms",
+ /* 63 */ "Arabic Presentation Forms-A",
+ /* 64 */ "Combining Half Marks",
+ /* 65 */ "CJK Compatibility Forms",
+ /* 66 */ "Small Form Variants",
+ /* 67 */ "Arabic Presentation Forms-B",
+ /* 68 */ "Halfwidth And Fullwidth Forms",
+ /* 69 */ "Specials",
+ /*70-127*/ "Reserved for Unicode SubRanges"
+};
+
+
+
+/*- inline functions */ /*FOLD01*/
+#ifdef __GNUC__
+#define _inline static __inline__
+#else
+#define _inline static
+#endif
+
+_inline void *smalloc(size_t size)
+{
+ void *res = malloc(size);
+ assert(res != 0);
+ return res;
+}
+
+_inline void *scalloc(size_t n, size_t size)
+{
+ void *res = calloc(n, size);
+ assert(res != 0);
+ return res;
+}
+
+_inline uint32 mkTag(byte a, byte b, byte c, byte d) {
+ return (a << 24) | (b << 16) | (c << 8) | d;
+}
+
+/*- Data access macros for data stored in big-endian or little-endian format */
+_inline int16 GetInt16(const byte *ptr, size_t offset, int bigendian)
+{
+ int16 t;
+ assert(ptr != 0);
+
+ if (bigendian) {
+ t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
+ } else {
+ t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
+ }
+
+ return t;
+}
+
+_inline uint16 GetUInt16(const byte *ptr, size_t offset, int bigendian)
+{
+ uint16 t;
+ assert(ptr != 0);
+
+ if (bigendian) {
+ t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
+ } else {
+ t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
+ }
+
+ return t;
+}
+
+_inline int32 GetInt32(const byte *ptr, size_t offset, int bigendian)
+{
+ int32 t;
+ assert(ptr != 0);
+
+ if (bigendian) {
+ t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
+ (ptr+offset)[2] << 8 | (ptr+offset)[3];
+ } else {
+ t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
+ (ptr+offset)[1] << 8 | (ptr+offset)[0];
+ }
+
+ return t;
+}
+
+_inline uint32 GetUInt32(const byte *ptr, size_t offset, int bigendian)
+{
+ uint32 t;
+ assert(ptr != 0);
+
+
+ if (bigendian) {
+ t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
+ (ptr+offset)[2] << 8 | (ptr+offset)[3];
+ } else {
+ t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
+ (ptr+offset)[1] << 8 | (ptr+offset)[0];
+ }
+
+ return t;
+}
+
+_inline void PutInt16(int16 val, byte *ptr, size_t offset, int bigendian)
+{
+ assert(ptr != 0);
+
+ if (bigendian) {
+ ptr[offset] = (val >> 8) & 0xFF;
+ ptr[offset+1] = val & 0xFF;
+ } else {
+ ptr[offset+1] = (val >> 8) & 0xFF;
+ ptr[offset] = val & 0xFF;
+ }
+
+}
+
+#if defined(G_BIG_ENDIAN)
+#define Int16FromMOTA(a) (a)
+#else
+static uint16 Int16FromMOTA(uint16 a) {
+ return (uint16) (((byte)((a) >> 8)) | ((byte)(a) << 8));
+}
+#endif
+
+_inline F16Dot16 fixedMul(F16Dot16 a, F16Dot16 b)
+{
+ unsigned int a1, b1;
+ unsigned int a2, b2;
+ F16Dot16 res;
+ int sign;
+
+ sign = (a & 0x80000000) ^ (b & 0x80000000);
+ if (a < 0) a = -a;
+ if (b < 0) b = -b;
+
+ a1 = a >> 16;
+ b1 = a & 0xFFFF;
+ a2 = b >> 16;
+ b2 = b & 0xFFFF;
+
+ res = a1 * a2;
+
+ /* if (res > 0x7FFF) assert(!"fixedMul: F16Dot16 overflow"); */
+
+ res <<= 16;
+ res += a1 * b2 + b1 * a2 + ((b1 * b2) >> 16);
+
+ return sign ? -res : res;
+}
+
+
+_inline F16Dot16 fixedDiv(F16Dot16 a, F16Dot16 b)
+{
+ unsigned int f, r;
+ F16Dot16 res;
+ int sign;
+
+ sign = (a & 0x80000000) ^ (b & 0x80000000);
+ if (a < 0) a = -a;
+ if (b < 0) b = -b;
+
+ f = a / b;
+ r = a % b;
+
+ /* if (f > 0x7FFFF) assert(!"fixedDiv: F16Dot16 overflow"); */
+
+ while (r > 0xFFFF) {
+ r >>= 1;
+ b >>= 1;
+ }
+
+ res = (f << 16) + (r << 16) / b;
+
+ return sign ? -res : res;
+}
+
+/*- returns a * b / c -*/
+/* XXX provide a real implementation that preserves accuracy */
+_inline F16Dot16 fixedMulDiv(F16Dot16 a, F16Dot16 b, F16Dot16 c)
+{
+ F16Dot16 res;
+
+ res = fixedMul(a, b);
+ return fixedDiv(res, c);
+}
+
+/*- Translate units from TT to PS (standard 1/1000) -*/
+_inline int XUnits(int unitsPerEm, int n)
+{
+ return (n * 1000) / unitsPerEm;
+}
+
+_inline const char *UnicodeRangeName(uint16 bit)
+{
+ if (bit > LAST_URANGE_BIT) bit = LAST_URANGE_BIT+1;
+
+ return ulcodes[bit];
+}
+
+
+#if 0
+/* It would have been nice if it worked, but I found so many fonts that don't
+ * follow the TrueType spec (sorted table directory) that I have to re-write this
+ * stuff.
+ */
+
+static byte *getTDEntry(TrueTypeFont *ttf, uint32 tag) /*FOLD01*/
+{
+ int l = 0, r = ttf->ntables-1, i;
+ uint32 t;
+
+ do {
+ i = (l + r) >> 1;
+ t = GetUInt32(ttf->ptr + 12, i << 4, 1);
+ if (tag >= t) l = i + 1;
+ if (tag <= t) r = i - 1;
+ } while (l <= r);
+
+ if (l - r == 2) {
+ return ttf->ptr + 12 + 16 * (l - 1);
+ }
+ return 0;
+}
+
+static byte *getTable(TrueTypeFont *ttf, uint32 tag) /*FOLD01*/
+{
+ byte *ptr = getTDEntry(ttf, tag);
+ if (!ptr) return 0;
+
+ return ttf->ptr + GetUInt32(ptr, 8, 1);
+}
+
+static uint32 getTableSize(TrueTypeFont *ttf, uint32 tag) /*FOLD01*/
+{
+ byte *ptr = getTDEntry(ttf, tag);
+ if (!ptr) return 0;
+
+ return GetUInt32(ptr, 12, 1);
+}
+
+#endif
+
+_inline byte *getTable(TrueTypeFont *ttf, uint32 ord)
+{
+ return ttf->tables[ord];
+}
+
+_inline uint32 getTableSize(TrueTypeFont *ttf, uint32 ord)
+{
+ return ttf->tlens[ord];
+}
+
+#ifndef NO_TYPE42
+/* Hex Formatter functions */
+static char HexChars[] = "0123456789ABCDEF";
+
+static HexFmt *HexFmtNew(FILE *outf)
+{
+ HexFmt *res = smalloc(sizeof(HexFmt));
+ res->bufpos = res->total = 0;
+ res->o = outf;
+ return res;
+}
+
+static void HexFmtFlush(HexFmt *_this)
+{
+ if (_this->bufpos) {
+ fwrite(_this->buffer, 1, _this->bufpos, _this->o);
+ _this->bufpos = 0;
+ }
+}
+
+
+_inline void HexFmtOpenString(HexFmt *_this)
+{
+ fputs("<\n", _this->o);
+}
+
+_inline void HexFmtCloseString(HexFmt *_this)
+{
+ HexFmtFlush(_this);
+ fputs("00\n>\n", _this->o);
+}
+
+_inline void HexFmtDispose(HexFmt *_this)
+{
+ HexFmtFlush(_this);
+ free(_this);
+}
+
+static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, off_t size)
+{
+ byte Ch;
+ off_t i;
+
+ if (_this->total + size > 65534) {
+ HexFmtFlush(_this);
+ HexFmtCloseString(_this);
+ _this->total = 0;
+ HexFmtOpenString(_this);
+ }
+ for (i=0; i<size; i++) {
+ Ch = ((byte *) ptr)[i];
+ _this->buffer[_this->bufpos++] = HexChars[Ch >> 4];
+ _this->buffer[_this->bufpos++] = HexChars[Ch & 0xF];
+ if (_this->bufpos == HFORMAT_LINELEN) {
+ HexFmtFlush(_this);
+ fputc('\n', _this->o);
+ }
+
+ }
+ _this->total += size;
+}
+#endif
+
+
+
+/* Outline Extraction functions */ /*FOLD01*/
+
+/* fills the aw and lsb entries of the TTGlyphMetrics structure from hmtx table -*/
+static void GetMetrics(TrueTypeFont *ttf, uint32 glyphID, TTGlyphMetrics *metrics)
+{
+ byte *table = getTable(ttf, O_hmtx);
+
+ metrics->aw = metrics->lsb = metrics->ah = metrics->tsb = 0;
+ if (!table || !ttf->numberOfHMetrics) return;
+
+ if (glyphID < ttf->numberOfHMetrics) {
+ metrics->aw = GetUInt16(table, 4 * glyphID, 1);
+ metrics->lsb = GetInt16(table, 4 * glyphID + 2, 1);
+ } else {
+ metrics->aw = GetUInt16(table, 4 * (ttf->numberOfHMetrics - 1), 1);
+ metrics->lsb = GetInt16(table + ttf->numberOfHMetrics * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1);
+ }
+
+ table = getTable(ttf, O_vmtx);
+ if (!table || !ttf->numOfLongVerMetrics) return;
+
+ if (glyphID < ttf->numOfLongVerMetrics) {
+ metrics->ah = GetUInt16(table, 4 * glyphID, 1);
+ metrics->tsb = GetInt16(table, 4 * glyphID + 2, 1);
+ } else {
+ metrics->ah = GetUInt16(table, 4 * (ttf->numOfLongVerMetrics - 1), 1);
+ metrics->tsb = GetInt16(table + ttf->numOfLongVerMetrics * 4, (glyphID - ttf->numOfLongVerMetrics) * 2, 1);
+ }
+}
+
+static int GetTTGlyphOutline(TrueTypeFont *, uint32 , ControlPoint **, TTGlyphMetrics *, list );
+
+/* returns the number of control points, allocates the pointArray */
+static int GetSimpleTTOutline(TrueTypeFont *ttf, uint32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics) /*FOLD02*/
+{
+ byte *table = getTable(ttf, O_glyf);
+ byte *ptr, *p, flag, n;
+ int16 numberOfContours;
+ uint16 t, instLen, lastPoint=0;
+ int i, j, z;
+ ControlPoint* pa;
+
+ *pointArray = 0;
+
+ /* printf("GetSimpleTTOutline(%d)\n", glyphID); */
+
+ if (glyphID >= ttf->nglyphs) return 0; /*- glyph is not present in the font */
+ ptr = table + ttf->goffsets[glyphID];
+ if ((numberOfContours = GetInt16(ptr, 0, 1)) <= 0) return 0; /*- glyph is not simple */
+
+ if (metrics) { /*- GetCompoundTTOutline() calls this function with NULL metrics -*/
+ metrics->xMin = GetInt16(ptr, 2, 1);
+ metrics->yMin = GetInt16(ptr, 4, 1);
+ metrics->xMax = GetInt16(ptr, 6, 1);
+ metrics->yMax = GetInt16(ptr, 8, 1);
+ GetMetrics(ttf, glyphID, metrics);
+ }
+
+ /* determine the last point and be extra safe about it. But probably this code is not needed */
+
+ for (i=0; i<numberOfContours; i++) {
+ if ((t = GetUInt16(ptr, 10+i*2, 1)) > lastPoint) lastPoint = t;
+ }
+
+ instLen = GetUInt16(ptr, 10 + numberOfContours*2, 1);
+ p = ptr + 10 + 2 * numberOfContours + 2 + instLen;
+ pa = calloc(lastPoint+1, sizeof(ControlPoint));
+
+ i = 0;
+ while (i <= lastPoint) {
+ pa[i++].flags = flag = (uint32) *p++;
+ if (flag & 8) { /*- repeat flag */
+ n = *p++;
+ for (j=0; j<n; j++) {
+ if (i > lastPoint) { /*- if the font is really broken */
+ free(pa);
+ return 0;
+ }
+ pa[i++].flags = flag;
+ }
+ }
+ }
+
+ /*- Process the X coordinate */
+ z = 0;
+ for (i = 0; i <= lastPoint; i++) {
+ if (pa[i].flags & 0x02) {
+ if (pa[i].flags & 0x10) {
+ z += (int) (*p++);
+ } else {
+ z -= (int) (*p++);
+ }
+ } else if ( !(pa[i].flags & 0x10)) {
+ z += GetInt16(p, 0, 1);
+ p += 2;
+ }
+ pa[i].x = z;
+ }
+
+ /*- Process the Y coordinate */
+ z = 0;
+ for (i = 0; i <= lastPoint; i++) {
+ if (pa[i].flags & 0x04) {
+ if (pa[i].flags & 0x20) {
+ z += *p++;
+ } else {
+ z -= *p++;
+ }
+ } else if ( !(pa[i].flags & 0x20)) {
+ z += GetInt16(p, 0, 1);
+ p += 2;
+ }
+ pa[i].y = z;
+ }
+
+ for (i=0; i<numberOfContours; i++) {
+ pa[GetUInt16(ptr, 10 + i * 2, 1)].flags |= 0x00008000; /*- set the end contour flag */
+ }
+
+ *pointArray = pa;
+ return lastPoint + 1;
+}
+
+static int GetCompoundTTOutline(TrueTypeFont *ttf, uint32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, list glyphlist) /*FOLD02*/
+{
+ uint16 flags, index;
+ int16 e, f, numberOfContours;
+ byte *table = getTable(ttf, O_glyf);
+ byte *ptr;
+ list myPoints;
+ ControlPoint *nextComponent, *pa;
+ int i, np;
+ F16Dot16 a = 0x10000, b = 0, c = 0, d = 0x10000, m, n, abs1, abs2, abs3;
+
+ *pointArray = 0;
+ /* printf("GetCompoundTTOutline(%d)\n", glyphID); */
+
+ if (glyphID >= ttf->nglyphs) { /*- incorrect glyphID */
+ return 0;
+ }
+ ptr = table + ttf->goffsets[glyphID];
+ if ((numberOfContours = GetInt16(ptr, 0, 1)) != -1) { /*- glyph is not compound */
+ return 0;
+ }
+
+ myPoints = listNewEmpty();
+ listSetElementDtor(myPoints, free);
+
+ if (metrics) {
+ metrics->xMin = GetInt16(ptr, 2, 1);
+ metrics->yMin = GetInt16(ptr, 4, 1);
+ metrics->xMax = GetInt16(ptr, 6, 1);
+ metrics->yMax = GetInt16(ptr, 8, 1);
+ GetMetrics(ttf, glyphID, metrics);
+ }
+
+ ptr += 10;
+
+ do {
+ flags = GetUInt16(ptr, 0, 1);
+ /* printf("flags: 0x%X\n", flags); */
+ index = GetUInt16(ptr, 2, 1);
+ ptr += 4;
+
+ if (listFind(glyphlist, (void *) (int) index)) {
+#ifdef DEBUG
+ fprintf(stderr, "Endless loop found in a compound glyph.\n");
+ fprintf(stderr, "%d -> ", index);
+ listToFirst(glyphlist);
+ fprintf(stderr," [");
+ do {
+ fprintf(stderr,"%d ", (int) listCurrent(glyphlist));
+ } while (listNext(glyphlist));
+ fprintf(stderr,"]\n");
+ /**/
+#endif
+ }
+
+ listAppend(glyphlist, (void *) (int) index);
+
+#ifdef DEBUG2
+ fprintf(stderr,"glyphlist: += %d\n", index);
+#endif
+
+ if ((np = GetTTGlyphOutline(ttf, index, &nextComponent, 0, glyphlist)) == 0) {
+ /* XXX that probably indicates a corrupted font */
+#ifdef DEBUG
+ fprintf(stderr, "An empty compound!\n");
+ /* assert(!"An empty compound"); */
+#endif
+ }
+
+ listToLast(glyphlist);
+#ifdef DEBUG2
+ listToFirst(glyphlist);
+ fprintf(stderr,"%d [", listCount(glyphlist));
+ if (!listIsEmpty(glyphlist)) {
+ do {
+ fprintf(stderr,"%d ", (int) listCurrent(glyphlist));
+ } while (listNext(glyphlist));
+ }
+ fprintf(stderr, "]\n");
+ fprintf(stderr, "glyphlist: -= %d\n", (int) listCurrent(glyphlist));
+
+#endif
+ listRemove(glyphlist);
+
+ if (flags & USE_MY_METRICS) {
+ if (metrics) GetMetrics(ttf, index, metrics);
+ }
+
+ if (flags & ARG_1_AND_2_ARE_WORDS) {
+ e = GetInt16(ptr, 0, 1);
+ f = GetInt16(ptr, 2, 1);
+ /* printf("ARG_1_AND_2_ARE_WORDS: %d %d\n", e & 0xFFFF, f & 0xFFFF); */
+ ptr += 4;
+ } else {
+ if (flags & ARGS_ARE_XY_VALUES) { /* args are signed */
+ e = (int8) *ptr++;
+ f = (int8) *ptr++;
+ /* printf("ARGS_ARE_XY_VALUES: %d %d\n", e & 0xFF, f & 0xFF); */
+ } else { /* args are unsigned */
+ /* printf("!ARGS_ARE_XY_VALUES\n"); */
+ e = *ptr++;
+ f = *ptr++;
+ }
+
+ }
+
+ a = d = 0x10000;
+ b = c = 0;
+
+ if (flags & WE_HAVE_A_SCALE) {
+#ifdef DEBUG2
+ fprintf(stderr, "WE_HAVE_A_SCALE\n");
+#endif
+ a = GetInt16(ptr, 0, 1) << 2;
+ d = a;
+ ptr += 2;
+ } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
+#ifdef DEBUG2
+ fprintf(stderr, "WE_HAVE_AN_X_AND_Y_SCALE\n");
+#endif
+ a = GetInt16(ptr, 0, 1) << 2;
+ d = GetInt16(ptr, 2, 1) << 2;
+ ptr += 4;
+ } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
+#ifdef DEBUG2
+ fprintf(stderr, "WE_HAVE_A_TWO_BY_TWO\n");
+#endif
+ a = GetInt16(ptr, 0, 1) << 2;
+ b = GetInt16(ptr, 2, 1) << 2;
+ c = GetInt16(ptr, 4, 1) << 2;
+ d = GetInt16(ptr, 6, 1) << 2;
+ ptr += 8;
+ }
+
+ abs1 = (a < 0) ? -a : a;
+ abs2 = (b < 0) ? -b : b;
+ m = (abs1 > abs2) ? abs1 : abs2;
+ abs3 = abs1 - abs2;
+ if (abs3 < 0) abs3 = -abs3;
+ if (abs3 <= 33) m *= 2;
+
+ abs1 = (c < 0) ? -c : c;
+ abs2 = (d < 0) ? -d : d;
+ n = (abs1 > abs2) ? abs1 : abs2;
+ abs3 = abs1 - abs2;
+ if (abs3 < 0) abs3 = -abs3;
+ if (abs3 <= 33) n *= 2;
+
+ if (!ARGS_ARE_XY_VALUES) { /* match the points */
+ assert(!"ARGS_ARE_XY_VALUES is not implemented!!!\n");
+ }
+
+#ifdef DEBUG2
+ fprintf(stderr, "a: %f, b: %f, c: %f, d: %f, e: %f, f: %f, m: %f, n: %f\n",
+ ((double) a) / 65536,
+ ((double) b) / 65536,
+ ((double) c) / 65536,
+ ((double) d) / 65536,
+ ((double) e) / 65536,
+ ((double) f) / 65536,
+ ((double) m) / 65536,
+ ((double) n) / 65536);
+#endif
+
+ for (i=0; i<np; i++) {
+ F16Dot16 t;
+ ControlPoint *cp = malloc(sizeof(ControlPoint));
+ cp->flags = nextComponent[i].flags;
+ t = fixedMulDiv(a, nextComponent[i].x << 16, m) + fixedMulDiv(c, nextComponent[i].y << 16, m) + (e << 16);
+ cp->x = fixedMul(t, m) >> 16;
+ t = fixedMulDiv(b, nextComponent[i].x << 16, n) + fixedMulDiv(d, nextComponent[i].y << 16, n) + (f << 16);
+ cp->y = fixedMul(t, n) >> 16;
+
+#ifdef DEBUG2
+ fprintf(stderr, "( %d %d ) -> ( %d %d )\n", nextComponent[i].x, nextComponent[i].y, cp->x, cp->y);
+#endif
+
+ listAppend(myPoints, cp);
+ }
+
+ free(nextComponent);
+
+ } while (flags & MORE_COMPONENTS);
+
+
+
+ np = listCount(myPoints);
+
+ pa = calloc(np, sizeof(ControlPoint));
+ assert(pa != 0);
+ listToFirst(myPoints);
+ for (i=0; i<np; i++) {
+ memcpy(pa+i, listCurrent(myPoints), sizeof(ControlPoint));
+ listNext(myPoints);
+ }
+ listDispose(myPoints);
+
+ *pointArray = pa;
+ return np;
+}
+
+/* NOTE: GetTTGlyphOutline() returns -1 if the glyphID is incorrect,
+ * but Get{Simple|Compound}GlyphOutline returns 0 in such a case.
+ *
+ * NOTE: glyphlist is the stack of glyphs traversed while constructing
+ * a composite glyph. This is a safequard against endless recursion
+ * in corrupted fonts.
+ */
+static int GetTTGlyphOutline(TrueTypeFont *ttf, uint32 glyphID, ControlPoint **pointArray, TTGlyphMetrics *metrics, list glyphlist)
+{
+ byte *ptr, *table = getTable(ttf, O_glyf);
+ int16 numberOfContours;
+ int length;
+ int res;
+ *pointArray = 0;
+
+ if (metrics) {
+ memset(metrics, 0, sizeof(TTGlyphMetrics)); /*- metrics is initialized to all zeroes */
+ }
+
+ if (glyphID >= ttf->nglyphs) return -1; /**/
+
+ ptr = table + ttf->goffsets[glyphID];
+ length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
+
+ if (length == 0) { /*- empty glyphs still have hmtx and vmtx metrics values */
+ if (metrics) GetMetrics(ttf, glyphID, metrics);
+ return 0;
+ }
+
+ numberOfContours = GetInt16(ptr, 0, 1);
+
+ if (numberOfContours >= 0) {
+ res=GetSimpleTTOutline(ttf, glyphID, pointArray, metrics);
+ } else {
+ int glyphlistFlag = 0;
+ if (!glyphlist) {
+ glyphlistFlag = 1;
+ glyphlist = listNewEmpty();
+ listAppend(glyphlist, (void *) glyphID);
+ }
+ res = GetCompoundTTOutline(ttf, glyphID, pointArray, metrics, glyphlist);
+ if (glyphlistFlag) {
+ glyphlistFlag = 0;
+ listDispose(glyphlist);
+ glyphlist = 0;
+ }
+ }
+
+#ifdef DEBUG3
+ {
+ int i;
+ FILE *out = fopen("points.dat", "a");
+ assert(out != 0);
+ fprintf(out, "Glyph: %d\nPoints: %d\n", glyphID, res);
+ for (i=0; i<res; i++) {
+ fprintf(out, "%c ", ((*pointArray)[i].flags & 0x8000) ? 'X' : '.');
+ fprintf(out, "%c ", ((*pointArray)[i].flags & 1) ? '+' : '-');
+ fprintf(out, "%d %d\n", (*pointArray)[i].x, (*pointArray)[i].y);
+ }
+ fclose(out);
+ }
+#endif
+
+ return res;
+}
+
+#ifndef NO_TYPE3
+
+static PSPathElement *newPSPathElement(int t)
+{
+ PSPathElement *p = malloc(sizeof(PSPathElement));
+ assert(p != 0);
+
+ p->type = t;
+ return p;
+}
+
+/*- returns the number of items in the path -*/
+
+static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path)
+{
+ list pList = listNewEmpty();
+ int i = 0, pCount = 0;
+ PSPathElement *p;
+
+ int x0, y0, x1, y1, x2, y2, curx, cury;
+ int lastOff = 0; /*- last point was off-contour */
+ int scflag = 1; /*- start contour flag */
+ int ecflag = 0; /*- end contour flag */
+ int cp = 0; /*- current point */
+
+ listSetElementDtor(pList, free);
+ *path = 0;
+
+ /* if (srcCount > 0) for(;;) */
+ while (srcCount > 0) { /*- srcCount does not get changed inside the loop. */
+ int StartContour, EndContour;
+
+ if (scflag) {
+ int l = cp;
+ StartContour = cp;
+ while (!(srcA[l].flags & 0x8000)) l++;
+ EndContour = l;
+ if (StartContour == EndContour) {
+ if (cp + 1 < srcCount) {
+ cp++;
+ continue;
+ } else {
+ break;
+ }
+ }
+ p = newPSPathElement(PS_MOVETO);
+ if (!(srcA[cp].flags & 1)) {
+ if (!(srcA[EndContour].flags & 1)) {
+ p->x1 = x0 = (srcA[cp].x + srcA[EndContour].x + 1) / 2;
+ p->y1 = y0 = (srcA[cp].y + srcA[EndContour].y + 1) / 2;
+ } else {
+ p->x1 = x0 = srcA[EndContour].x;
+ p->y1 = y0 = srcA[EndContour].y;
+ }
+ } else {
+ p->x1 = x0 = srcA[cp].x;
+ p->y1 = y0 = srcA[cp].y;
+ cp++;
+ }
+ listAppend(pList, p);
+ lastOff = 0;
+ scflag = 0;
+ }
+
+ curx = srcA[cp].x;
+ cury = srcA[cp].y;
+
+ if (srcA[cp].flags & 1) {
+ if (lastOff) {
+ p = newPSPathElement(PS_CURVETO);
+ p->x1 = x0 + (2 * (x1 - x0) + 1) / 3;
+ p->y1 = y0 + (2 * (y1 - y0) + 1) / 3;
+ p->x2 = x1 + (curx - x1 + 1) / 3;
+ p->y2 = y1 + (cury - y1 + 1) / 3;
+ p->x3 = curx;
+ p->y3 = cury;
+ listAppend(pList, p);
+ } else {
+ if (!(x0 == curx && y0 == cury)) { /* eliminate empty lines */
+ p = newPSPathElement(PS_LINETO);
+ p->x1 = curx;
+ p->y1 = cury;
+ listAppend(pList, p);
+ }
+ }
+
+ x0 = curx; y0 = cury; lastOff = 0;
+ } else {
+ if (lastOff) {
+ x2 = (x1 + curx + 1) / 2;
+ y2 = (y1 + cury + 1) / 2;
+ p = newPSPathElement(PS_CURVETO);
+ p->x1 = x0 + (2 * (x1 - x0) + 1) / 3;
+ p->y1 = y0 + (2 * (y1 - y0) + 1) / 3;
+ p->x2 = x1 + (x2 - x1 + 1) / 3;
+ p->y2 = y1 + (y2 - y1 + 1) / 3;
+ p->x3 = x2;
+ p->y3 = y2;
+ listAppend(pList, p);
+ x0 = x2; y0 = y2;
+ x1 = curx; y1 = cury;
+ } else {
+ x1 = curx; y1 = cury;
+ }
+ lastOff = true;
+ }
+
+ if (ecflag) {
+ listAppend(pList, newPSPathElement(PS_CLOSEPATH));
+ scflag = 1;
+ ecflag = 0;
+ cp = EndContour + 1;
+ if (cp >= srcCount) break;
+ continue;
+ }
+
+ if (cp == EndContour) {
+ cp = StartContour;
+ ecflag = true;
+ } else {
+ cp++;
+ }
+ }
+
+ if ((pCount = listCount(pList)) > 0) {
+ p = calloc(pCount, sizeof(PSPathElement));
+ assert(p != 0);
+ listToFirst(pList);
+ for (i=0; i<pCount; i++) {
+ memcpy(p + i, listCurrent(pList), sizeof(PSPathElement));
+ listNext(pList);
+ }
+ listDispose(pList);
+ *path = p;
+ }
+
+ return pCount;
+}
+
+#endif
+
+/*- Extracts a string from the name table and allocates memory for it -*/
+
+static char *nameExtract(byte *name, int n, int dbFlag)
+{
+ int i;
+ char *res;
+ byte *ptr = name + GetUInt16(name, 4, 1) + GetUInt16(name + 6, 12 * n + 10, 1);
+ int len = GetUInt16(name+6, 12 * n + 8, 1);
+
+ if (dbFlag) {
+ res = malloc(1 + len/2);
+ assert(res != 0);
+ for (i = 0; i < len/2; i++) res[i] = *(ptr + i * 2 + 1);
+ res[len/2] = 0;
+ } else {
+ res = malloc(1 + len);
+ assert(res != 0);
+ memcpy(res, ptr, len);
+ res[len] = 0;
+ }
+
+ return res;
+}
+
+static int findname(byte *name, uint16 n, uint16 platformID, uint16 encodingID, uint16 languageID, uint16 nameID)
+{
+ int l = 0, r = n-1, i;
+ uint32 t1, t2;
+ uint32 m1, m2;
+
+ if (n == 0) return -1;
+
+ m1 = (platformID << 16) | encodingID;
+ m2 = (languageID << 16) | nameID;
+
+ do {
+ i = (l + r) >> 1;
+ t1 = GetUInt32(name + 6, i * 12 + 0, 1);
+ t2 = GetUInt32(name + 6, i * 12 + 4, 1);
+
+ if (! ((m1 < t1) || ((m1 == t1) && (m2 < t2)))) l = i + 1;
+ if (! ((m1 > t1) || ((m1 == t1) && (m2 > t2)))) r = i - 1;
+ } while (l <= r);
+
+ if (l - r == 2) {
+ return l - 1;
+ }
+
+ return -1;
+}
+
+/* XXX marlett.ttf uses (3, 0, 1033) instead of (3, 1, 1033) and does not have any Apple tables.
+ * Fix: if (3, 1, 1033) is not found - need to check for (3, 0, 1033)
+ *
+ * /d/fonts/ttzh_tw/Big5/Hanyi/ma6b5p uses (1, 0, 19) for English strings, instead of (1, 0, 0)
+ * and does not have (3, 1, 1033)
+ * Fix: if (1, 0, 0) and (3, 1, 1033) are not found need to look for (1, 0, *) - that will
+ * require a change in algorithm
+ *
+ * /d/fonts/fdltest/Korean/h2drrm has unsorted names and a an unknown (to me) Mac LanguageID,
+ * but (1, 0, 1042) strings usable
+ * Fix: change algorithm, and use (1, 0, *) if both standard Mac and MS strings are not found
+ */
+
+static void GetNames(TrueTypeFont *t)
+{
+ byte *table = getTable(t, O_name);
+ uint16 n = GetUInt16(table, 2, 1);
+ int i, r;
+
+ /* PostScript name: preferred Microsoft */
+ if ((r = findname(table, n, 3, 1, 0x0409, 6)) != -1) {
+ t->psname = nameExtract(table, r, 1);
+ } else if ((r = findname(table, n, 1, 0, 0, 6)) != -1) {
+ t->psname = nameExtract(table, r, 0);
+ } else {
+ char* pReverse = t->fname + strlen(t->fname);
+ /* take only last token of filename */
+ while(pReverse != t->fname && *pReverse != '/') pReverse--;
+ if(*pReverse == '/') pReverse++;
+ t->psname = strdup(pReverse);
+ assert(t->psname != 0);
+ for (i=strlen(t->psname) - 1; i > 0; i--) { /*- Remove the suffix -*/
+ if (t->psname[i] == '.' ) {
+ t->psname[i] = 0;
+ break;
+ }
+ }
+ }
+
+ /* Font family and subfamily names: preferred Apple */
+ if ((r = findname(table, n, 1, 0, 0, 1)) != -1) {
+ t->family = nameExtract(table, r, 0);
+ } else if ((r = findname(table, n, 3, 1, 0x0409, 1)) != -1) {
+ t->family = nameExtract(table, r, 1);
+ } else {
+ t->family = strdup(t->psname);
+ assert(t->family != 0);
+ }
+
+ if ((r = findname(table, n, 1, 0, 0, 2)) != -1) {
+ t->subfamily = nameExtract(table, r, 0);
+ } else if ((r = findname(table, n, 3, 1, 0x0409, 2)) != -1) {
+ t->subfamily = nameExtract(table, r, 1);
+ } else {
+ t->subfamily = strdup("");
+ assert(t->family != 0);
+ }
+
+}
+
+enum cmapType {
+ CMAP_NOT_USABLE = -1,
+ CMAP_MS_Symbol = 10,
+ CMAP_MS_Unicode = 11,
+ CMAP_MS_ShiftJIS = 12,
+ CMAP_MS_Big5 = 13,
+ CMAP_MS_PRC = 14,
+ CMAP_MS_Wansung = 15,
+ CMAP_MS_Johab = 16
+};
+
+#define MISSING_GLYPH_INDEX 0
+
+/*
+ * All getGlyph?() functions and freinds are implemented by:
+ * @author Manpreet Singh
+ */
+static uint16 getGlyph0(const byte* cmap, uint16 c) {
+ if (c <= 255) {
+ return *(cmap + 6 + c);
+ } else {
+ return MISSING_GLYPH_INDEX;
+ }
+}
+
+typedef struct _subHeader2 {
+ uint16 firstCode;
+ uint16 entryCount;
+ uint16 idDelta;
+ uint16 idRangeOffset;
+} subHeader2;
+
+static uint16 getGlyph2(const byte *cmap, uint16 c) {
+ uint16 *CMAP2 = (uint16 *) cmap;
+ byte theHighByte;
+ byte theLowByte;
+ subHeader2* subHeader2s;
+ uint16* subHeader2Keys;
+ uint16 firstCode;
+ int k;
+ int ToReturn;
+
+ theHighByte = (byte)((c >> 8) & 0x00ff);
+ theLowByte = (byte)(c & 0x00ff);
+ subHeader2Keys = CMAP2 + 3;
+ subHeader2s = (subHeader2 *)(subHeader2Keys + 256);
+ k = Int16FromMOTA(subHeader2Keys[theHighByte]) / 8;
+
+ if(k == 0) {
+ firstCode = Int16FromMOTA(subHeader2s[k].firstCode);
+ if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) {
+ return *((&(subHeader2s[0].idRangeOffset))
+ + (Int16FromMOTA(subHeader2s[0].idRangeOffset)/2) /* + offset */
+ + theLowByte /* + to_look */
+ - Int16FromMOTA(subHeader2s[0].firstCode)
+ );
+ } else {
+ return MISSING_GLYPH_INDEX;
+ }
+ } else if (k > 0) {
+ firstCode = Int16FromMOTA(subHeader2s[k].firstCode);
+ if(theLowByte >= firstCode && theLowByte < (firstCode + Int16FromMOTA(subHeader2s[k].entryCount))) {
+ ToReturn = *((&(subHeader2s[k].idRangeOffset))
+ + (Int16FromMOTA(subHeader2s[k].idRangeOffset)/2)
+ + theLowByte - firstCode);
+ if(ToReturn == 0) {
+ return MISSING_GLYPH_INDEX;
+ } else {
+ return (uint16)((ToReturn + Int16FromMOTA(subHeader2s[k].idDelta)) % 0xFFFF);
+ }
+ } else {
+ return MISSING_GLYPH_INDEX;
+ }
+ } else {
+ return MISSING_GLYPH_INDEX;
+ }
+}
+
+static uint16 getGlyph6(const byte *cmap, uint16 c) {
+ uint16 firstCode;
+ uint16 *CMAP6 = (uint16 *) cmap;
+
+ firstCode = *(CMAP6 + 3);
+ if (c < firstCode || c > (firstCode + (*(CMAP6 + 4))/*entryCount*/ - 1)) {
+ return MISSING_GLYPH_INDEX;
+ } else {
+ return *((CMAP6 + 5)/*glyphIdArray*/ + (c - firstCode));
+ }
+}
+
+static uint16 GEbinsearch(uint16 *ar, uint16 length, uint16 toSearch) {
+ signed int low, mid, high, lastfound = 0xffff;
+ uint16 res;
+ if(length == (uint16)0 || length == (uint16)0xFFFF) {
+ return (uint16)0xFFFF;
+ }
+ low = 0;
+ high = length - 1;
+ while(high >= low) {
+ mid = (high + low)/2;
+ res = Int16FromMOTA(*(ar+mid));
+ if(res >= toSearch) {
+ lastfound = mid;
+ high = --mid;
+ } else {
+ low = ++mid;
+ }
+ }
+ return lastfound;
+}
+
+
+static uint16 getGlyph4(const byte *cmap, uint16 c) {
+ uint16 i;
+ int ToReturn;
+ uint16 segCount;
+ uint16 * startCode;
+ uint16 * endCode;
+ uint16 * idDelta;
+ /* uint16 * glyphIdArray; */
+ uint16 * idRangeOffset;
+ uint16 * glyphIndexArray;
+ uint16 *CMAP4 = (uint16 *) cmap;
+ /* uint16 GEbinsearch(uint16 *ar, uint16 length, uint16 toSearch); */
+
+ segCount = Int16FromMOTA(*(CMAP4 + 3))/2;
+ endCode = CMAP4 + 7;
+ i = GEbinsearch(endCode, segCount, c);
+
+ if (i == (uint16) 0xFFFF) {
+ return MISSING_GLYPH_INDEX;
+ }
+ startCode = endCode + segCount + 1;
+
+ if(Int16FromMOTA(startCode[i]) > c) {
+ return MISSING_GLYPH_INDEX;
+ }
+ idDelta = startCode + segCount;
+ idRangeOffset = idDelta + segCount;
+ glyphIndexArray = idRangeOffset + segCount;
+
+ if(Int16FromMOTA(idRangeOffset[i]) != 0) {
+ ToReturn = Int16FromMOTA(*(&(idRangeOffset[i]) + (Int16FromMOTA(idRangeOffset[i])/2 + (c - Int16FromMOTA(startCode[i])))));
+ } else {
+ ToReturn = (Int16FromMOTA(idDelta[i]) + c)%65536;
+ }
+ return ToReturn;
+}
+
+static void FindCmap(TrueTypeFont *ttf)
+{
+ byte *table = getTable(ttf, O_cmap);
+ uint16 ncmaps = GetUInt16(table, 2, 1);
+ int i;
+ uint32 ThreeZero = 0; /* MS Symbol */
+ uint32 ThreeOne = 0; /* MS Unicode */
+ uint32 ThreeTwo = 0; /* MS ShiftJIS */
+ uint32 ThreeThree = 0; /* MS Big5 */
+ uint32 ThreeFour = 0; /* MS PRC */
+ uint32 ThreeFive = 0; /* MS Wansung */
+ uint32 ThreeSix = 0; /* MS Johab */
+
+ for (i = 0; i < ncmaps; i++) {
+ uint32 offset;
+ uint16 pID, eID;
+
+ pID = GetUInt16(table, 4 + i * 8, 1);
+ eID = GetUInt16(table, 6 + i * 8, 1);
+ offset = GetUInt32(table, 8 + i * 8, 1);
+
+ if (pID == 3) {
+ switch (eID) {
+ case 0: ThreeZero = offset; break;
+ case 1: ThreeOne = offset; break;
+ case 2: ThreeTwo = offset; break;
+ case 3: ThreeThree = offset; break;
+ case 4: ThreeFour = offset; break;
+ case 5: ThreeFive = offset; break;
+ case 6: ThreeSix = offset; break;
+ }
+ }
+ }
+
+ if (ThreeOne) {
+ ttf->cmapType = CMAP_MS_Unicode;
+ ttf->cmap = table + ThreeOne;
+ } else if (ThreeTwo) {
+ ttf->cmapType = CMAP_MS_ShiftJIS;
+ ttf->cmap = table + ThreeTwo;
+ } else if (ThreeThree) {
+ ttf->cmapType = CMAP_MS_Big5;
+ ttf->cmap = table + ThreeThree;
+ } else if (ThreeFour) {
+ ttf->cmapType = CMAP_MS_PRC;
+ ttf->cmap = table + ThreeFour;
+ } else if (ThreeFive) {
+ ttf->cmapType = CMAP_MS_Wansung;
+ ttf->cmap = table + ThreeFive;
+ } else if (ThreeSix) {
+ ttf->cmapType = CMAP_MS_Johab;
+ ttf->cmap = table + ThreeSix;
+ } else if (ThreeZero) {
+ ttf->cmapType = CMAP_MS_Symbol;
+ ttf->cmap = table + ThreeZero;
+ } else {
+ ttf->cmapType = CMAP_NOT_USABLE;
+ ttf->cmap = 0;
+ }
+
+ if (ttf->cmapType != CMAP_NOT_USABLE) {
+
+ switch (GetUInt16(ttf->cmap, 0, 1)) {
+ case 0: ttf->mapper = getGlyph0; break;
+ case 2: ttf->mapper = getGlyph2; break;
+ case 4: ttf->mapper = getGlyph4; break;
+ case 6: ttf->mapper = getGlyph6; break;
+ default:
+#ifdef DEBUG
+ /*- if the cmap table is really broken */
+ printf("%s: %d is not a recognized cmap format.\n", ttf->fname, GetUInt16(ttf->cmap, 0, 1));
+#endif
+ ttf->cmapType = CMAP_NOT_USABLE;
+ ttf->cmap = 0;
+ ttf->mapper = 0;
+ }
+ }
+}
+
+static void GetKern(TrueTypeFont *ttf)
+{
+ byte *table = getTable(ttf, O_kern);
+ byte *ptr;
+ int i;
+ /*
+ uint16 v1;
+ uint32 v2;
+ */
+
+ if (!table) goto badtable;
+
+ if (GetUInt16(table, 0, 1) == 0) { /* Traditional Microsoft style table with USHORT version and nTables fields */
+ ttf->nkern = GetUInt16(table, 2, 1);
+ ttf->kerntables = calloc(ttf->nkern, sizeof(byte *));
+ assert(ttf->kerntables != 0);
+ memset(ttf->kerntables, 0, ttf->nkern * sizeof(byte *));
+ ttf->kerntype = KT_MICROSOFT;
+ ptr = table + 4;
+ for (i=0; i < ttf->nkern; i++) {
+ ttf->kerntables[i] = ptr;
+ ptr += GetUInt16(ptr, 2, 1);
+ }
+ return;
+ }
+
+ if (GetUInt32(table, 0, 1) == 0x00010000) { /* MacOS style kern tables: fixed32 version and uint32 nTables fields */
+ ttf->nkern = GetUInt32(table, 4, 1);
+ ttf->kerntables = calloc(ttf->nkern, sizeof(byte *));
+ assert(ttf->kerntables != 0);
+ memset(ttf->kerntables, 0, ttf->nkern * sizeof(byte *));
+ ttf->kerntype = KT_APPLE_NEW;
+ ptr = table + 8;
+ for (i = 0; i < ttf->nkern; i++) {
+ ttf->kerntables[i] = ptr;
+ ptr += GetUInt32(ptr, 0, 1);
+ }
+ return;
+ }
+
+ badtable:
+ ttf->kerntype = KT_NONE;
+ ttf->kerntables = 0;
+
+ return;
+}
+
+/* KernGlyphsPrim?() functions expect the caller to ensure the validity of their arguments and
+ * that x and y elements of the kern array are initialized to zeroes
+ */
+static void KernGlyphsPrim1(TrueTypeFont *ttf, uint16 *glyphs, int nglyphs, int wmode, KernData *kern)
+{
+ fprintf(stderr, "MacOS kerning tables have not been implemented yet!\n");
+}
+
+static void KernGlyphsPrim2(TrueTypeFont *ttf, uint16 *glyphs, int nglyphs, int wmode, KernData *kern)
+{
+ int i, j;
+ uint32 gpair;
+
+ for (i = 0; i < nglyphs - 1; i++) {
+ gpair = (glyphs[i] << 16) | glyphs[i+1];
+#ifdef DEBUG2
+ /* All fonts with MS kern table that I've seen so far contain just one kern subtable.
+ * MS kern documentation is very poor and I doubt that font developers will be using
+ * several subtables. I expect them to be using OpenType tables instead.
+ * According to MS documention, format 2 subtables are not supported by Windows and OS/2.
+ */
+ if (ttf->nkern > 1) {
+ fprintf(stderr, "KernGlyphsPrim2: %d kern tables found.\n", ttf->nkern);
+ }
+#endif
+ for (j = 0; j < ttf->nkern; j++) {
+ uint16 coverage = GetUInt16(ttf->kerntables[j], 4, 1);
+ byte *ptr;
+ int npairs;
+ uint32 t;
+ int l, r, k;
+
+ if (! ((coverage & 1) ^ wmode)) continue;
+ if ((coverage & 0xFFFE) != 0) {
+#ifdef DEBUG2
+ fprintf(stderr, "KernGlyphsPrim2: coverage flags are not supported: %04X.\n", coverage);
+#endif
+ continue;
+ }
+ ptr = ttf->kerntables[j];
+ npairs = GetUInt16(ptr, 6, 1);
+ ptr += 14;
+ l = 0;
+ r = npairs;
+ do {
+ k = (l + r) >> 1;
+ t = GetUInt32(ptr, k * 6, 1);
+ if (gpair >= t) l = k + 1;
+ if (gpair <= t) r = k - 1;
+ } while (l <= r);
+ if (l - r == 2) {
+ if (!wmode) {
+ kern[i].x = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1));
+ } else {
+ kern[i].y = XUnits(ttf->unitsPerEm, GetInt16(ptr, 4 + (l-1) * 6, 1));
+ }
+ /* !wmode ? kern[i].x : kern[i].y = GetInt16(ptr, 4 + (l-1) * 6, 1); */
+ }
+ }
+ }
+}
+
+/*- Public functions */ /*FOLD00*/
+
+int CountTTCFonts(const char* fname)
+{
+ int nFonts = 0;
+ byte buffer[12];
+ int fd = open(fname, O_RDONLY);
+ if( fd != -1 ) {
+ if (read(fd, buffer, 12) == 12) {
+ if(GetUInt32(buffer, 0, 1) == T_ttcf )
+ nFonts = GetUInt32(buffer, 8, 1);
+ }
+ close(fd);
+ }
+ return nFonts;
+}
+
+
+int OpenTTFont(const char *fname, uint32 facenum, TrueTypeFont** ttf) /*FOLD01*/
+{
+ TrueTypeFont *t;
+ int ret, i, fd = -1;
+ struct stat st;
+ uint32 version;
+ byte *table, *offset;
+ uint32 length, tag;
+ uint32 tdoffset = 0; /* offset to TableDirectory in a TTC file. For TTF files is 0 */
+
+ int indexfmt, k;
+
+ *ttf = 0;
+
+ if (!fname || !*fname) return SF_BADFILE;
+
+ t = malloc(sizeof(TrueTypeFont));
+ assert(t != 0);
+ t->tag = 0;
+ t->fname = 0;
+ t->fsize = -1;
+ t->ptr = 0;
+ t->nglyphs = 0xFFFFFFFF;
+ t->pGSubstitution = 0;
+
+ t->fname = strdup(fname);
+ assert(t->fname != 0);
+
+ fd = open(fname, O_RDONLY);
+
+ if (fd == -1) {
+ ret = SF_BADFILE;
+ goto cleanup;
+ }
+
+ if (fstat(fd, &st) == -1) {
+ ret = SF_FILEIO;
+ goto cleanup;
+ }
+ t->fsize = st.st_size;
+
+ if ((t->ptr = (byte *) mmap(0, t->fsize, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
+ ret = SF_MEMORY;
+ goto cleanup;
+ }
+ close(fd);
+
+ version = GetInt32(t->ptr, 0, 1);
+
+ if ((version == 0x00010000) || (version == T_true)) {
+ tdoffset = 0;
+ } else if (version == T_ttcf) { /*- TrueType collection */
+ if (GetUInt32(t->ptr, 4, 1) != 0x00010000) {
+ CloseTTFont(t);
+ return SF_TTFORMAT;
+ }
+ if (facenum >= GetUInt32(t->ptr, 8, 1)) {
+ CloseTTFont(t);
+ return SF_FONTNO;
+ }
+ tdoffset = GetUInt32(t->ptr, 12 + 4 * facenum, 1);
+ } else {
+ CloseTTFont(t);
+ return SF_TTFORMAT;
+ }
+
+#ifdef DEBUG2
+ fprintf(stderr, "tdoffset: %d\n", tdoffset);
+#endif
+
+ /* magic number */
+ t->tag = TTFontClassTag;
+
+ t->ntables = GetUInt16(t->ptr + tdoffset, 4, 1);
+
+ t->tables = calloc(NUM_TAGS, sizeof(void *));
+ assert(t->tables != 0);
+ t->tlens = calloc(NUM_TAGS, sizeof(uint32));
+ assert(t->tlens != 0);
+
+ memset(t->tables, 0, NUM_TAGS * sizeof(void *));
+ memset(t->tlens, 0, NUM_TAGS * sizeof(uint32));
+
+
+ /* parse the tables */
+ for (i=0; i<t->ntables; i++) {
+ tag = GetUInt32(t->ptr + tdoffset + 12, 16 * i, 1);
+ offset = t->ptr + GetUInt32(t->ptr + tdoffset + 12, 16 * i + 8, 1);
+ length = GetUInt32(t->ptr + tdoffset + 12, 16 * i + 12, 1);
+
+ if (tag == T_maxp) { t->tables[O_maxp] = offset; t->tlens[O_maxp] = length; continue; }
+ if (tag == T_glyf) { t->tables[O_glyf] = offset; t->tlens[O_glyf] = length; continue; }
+ if (tag == T_head) { t->tables[O_head] = offset; t->tlens[O_head] = length; continue; }
+ if (tag == T_loca) { t->tables[O_loca] = offset; t->tlens[O_loca] = length; continue; }
+ if (tag == T_name) { t->tables[O_name] = offset; t->tlens[O_name] = length; continue; }
+ if (tag == T_hhea) { t->tables[O_hhea] = offset; t->tlens[O_hhea] = length; continue; }
+ if (tag == T_hmtx) { t->tables[O_hmtx] = offset; t->tlens[O_hmtx] = length; continue; }
+ if (tag == T_cmap) { t->tables[O_cmap] = offset; t->tlens[O_cmap] = length; continue; }
+ if (tag == T_vhea) { t->tables[O_vhea] = offset; t->tlens[O_vhea] = length; continue; }
+ if (tag == T_vmtx) { t->tables[O_vmtx] = offset; t->tlens[O_vmtx] = length; continue; }
+ if (tag == T_OS2 ) { t->tables[O_OS2 ] = offset; t->tlens[O_OS2 ] = length; continue; }
+ if (tag == T_post) { t->tables[O_post] = offset; t->tlens[O_post] = length; continue; }
+ if (tag == T_kern) { t->tables[O_kern] = offset; t->tlens[O_kern] = length; continue; }
+ if (tag == T_cvt ) { t->tables[O_cvt ] = offset; t->tlens[O_cvt ] = length; continue; }
+ if (tag == T_prep) { t->tables[O_prep] = offset; t->tlens[O_prep] = length; continue; }
+ if (tag == T_fpgm) { t->tables[O_fpgm] = offset; t->tlens[O_fpgm] = length; continue; }
+ if (tag == T_gsub) { t->tables[O_gsub] = offset; t->tlens[O_gsub] = length; continue; }
+ }
+
+
+ /* At this point TrueTypeFont is constructed, now need to verify the font format
+ and read the basic font properties */
+
+ /* The following tables are absolutely required:
+ * maxp, head, glyf, loca, name, cmap
+ */
+
+ if (!(getTable(t, O_maxp) && getTable(t, O_head) && getTable(t, O_glyf) && getTable(t, O_loca) && getTable(t, O_name) && getTable(t, O_cmap) )) {
+ CloseTTFont(t);
+ return SF_TTFORMAT;
+ }
+
+ table = getTable(t, O_maxp);
+ t->nglyphs = GetUInt16(table, 4, 1);
+
+ table = getTable(t, O_head);
+ t->unitsPerEm = GetUInt16(table, 18, 1);
+ indexfmt = GetInt16(table, 50, 1);
+
+ if (!((indexfmt == 0) || indexfmt == 1)) {
+ CloseTTFont(t);
+ return SF_TTFORMAT;
+ }
+
+ k = (getTableSize(t, O_loca) / (indexfmt ? 4 : 2)) - 1;
+ if (k < t->nglyphs) t->nglyphs = k; /* Hack for broken Chinese fonts */
+
+ table = getTable(t, O_loca);
+
+ t->goffsets = (uint32 *) calloc(1+t->nglyphs, sizeof(uint32));
+ assert(t->goffsets != 0);
+
+ for (i = 0; i <= t->nglyphs; i++) {
+ t->goffsets[i] = indexfmt ? GetUInt32(table, i << 2, 1) : GetUInt16(table, i << 1, 1) << 1;
+ }
+
+ table = getTable(t, O_hhea);
+ t->numberOfHMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0;
+
+ table = getTable(t, O_vhea);
+ t->numOfLongVerMetrics = (table != 0) ? GetUInt16(table, 34, 1) : 0;
+
+ GetNames(t);
+ FindCmap(t);
+ GetKern(t);
+ ReadGSUB(t,t->tables[O_gsub],0,0);
+
+ *ttf = t;
+ return SF_OK;
+
+ cleanup:
+ /*- t and t->fname have been allocated! */
+ free(t->fname);
+ free(t);
+ if (fd != -1) close(fd);
+ return ret;
+}
+
+void CloseTTFont(TrueTypeFont *ttf) /*FOLD01*/
+{
+ if (ttf->tag != TTFontClassTag) return;
+
+ munmap((char *) ttf->ptr, ttf->fsize);
+ free(ttf->fname);
+ free(ttf->goffsets);
+ free(ttf->psname);
+ free(ttf->family);
+ free(ttf->subfamily);
+ free(ttf->tables);
+ free(ttf->tlens);
+ free(ttf->kerntables);
+ free(ttf);
+ return;
+}
+
+int GetTTGlyphPoints(TrueTypeFont *ttf, uint32 glyphID, ControlPoint **pointArray)
+{
+ return GetTTGlyphOutline(ttf, glyphID, pointArray, 0, 0);
+}
+
+#ifdef NO_LIST
+static
+#endif
+int GetTTGlyphComponents(TrueTypeFont *ttf, uint32 glyphID, list glyphlist)
+{
+ byte *ptr, *glyf = getTable(ttf, O_glyf);
+ int n = 1;
+
+ if (glyphID >= ttf->nglyphs) return 0;
+ ptr = glyf + ttf->goffsets[glyphID];
+
+ listAppend(glyphlist, (void *) glyphID);
+
+ if (GetInt16(ptr, 0, 1) == -1) {
+ uint16 flags, index;
+ ptr += 10;
+ do {
+ flags = GetUInt16(ptr, 0, 1);
+ index = GetUInt16(ptr, 2, 1);
+
+ ptr += 4;
+ n += GetTTGlyphComponents(ttf, index, glyphlist);
+
+ if (flags & ARG_1_AND_2_ARE_WORDS) {
+ ptr += 4;
+ } else {
+ ptr += 2;
+ }
+
+ if (flags & WE_HAVE_A_SCALE) {
+ ptr += 2;
+ } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
+ ptr += 4;
+ } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
+ ptr += 8;
+ }
+ } while (flags & MORE_COMPONENTS);
+ }
+
+ return n;
+}
+
+#ifndef NO_TYPE3
+int CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, /*FOLD00*/
+ uint16 *glyphArray, byte *encoding, int nGlyphs,
+ int wmode)
+{
+ ControlPoint *pa;
+ PSPathElement *path;
+ int i, j, r, n;
+ byte *table = getTable(ttf, O_head);
+ TTGlyphMetrics metrics;
+ int UPEm = ttf->unitsPerEm;
+
+ const char *h01 = "%%!PS-AdobeFont-%d.%d-%d.%d\n";
+ const char *h02 = "%%%%Creator: %s %s %s\n";
+ const char *h03 = "%%%%Title: %s\n";
+ const char *h04 = "%%%%CreationDate: %s\n";
+ const char *h05 = "%%%%Pages: 0\n";
+ const char *h06 = "%%%%EndComments\n";
+ const char *h07 = "%%%%BeginResource: font %s\n";
+ const char *h08 = "%%%%EndResource\n";
+ const char *h09 = "%% Original font name: %s\n";
+
+ const char *h10 =
+ "30 dict begin\n"
+ "/PaintType 0 def\n"
+ "/FontType 3 def\n"
+ "/StrokeWidth 0 def\n";
+
+ const char *h11 = "/FontName /%s def\n";
+
+ /*
+ const char *h12 = "%/UniqueID %d def\n";
+ */
+ const char *h13 = "/FontMatrix [.001 0 0 .001 0 0] def\n";
+ const char *h14 = "/FontBBox [%d %d %d %d] def\n";
+
+ const char *h15=
+ "/Encoding 256 array def\n"
+ " 0 1 255 {Encoding exch /.notdef put} for\n";
+
+ const char *h16 = " Encoding %d /glyph%d put\n";
+ const char *h17 = "/XUID [103 0 0 16#%08X %d 16#%08X 16#%08X] def\n";
+
+ const char *h30 = "/CharProcs %d dict def\n";
+ const char *h31 = " CharProcs begin\n";
+ const char *h32 = " /.notdef {} def\n";
+ const char *h33 = " /glyph%d {\n";
+ const char *h34 = " } bind def\n";
+ const char *h35 = " end\n";
+
+ const char *h40 =
+ "/BuildGlyph {\n"
+ " exch /CharProcs get exch\n"
+ " 2 copy known not\n"
+ " {pop /.notdef} if\n"
+ " get exec\n"
+ "} bind def\n"
+ "/BuildChar {\n"
+ " 1 index /Encoding get exch get\n"
+ " 1 index /BuildGlyph get exec\n"
+ "} bind def\n"
+ "currentdict end\n";
+
+ const char *h41 = "/%s exch definefont pop\n";
+
+
+ if (!((nGlyphs > 0) && (nGlyphs <= 256))) return SF_GLYPHNUM;
+ if (!glyphArray) return SF_BADARG;
+ if (!fname) fname = ttf->psname;
+
+ fprintf(outf, h01, GetInt16(table, 0, 1), GetUInt16(table, 2, 1), GetInt16(table, 4, 1), GetUInt16(table, 6, 1));
+ fprintf(outf, h02, modname, modver, modextra);
+ fprintf(outf, h03, fname);
+ fprintf(outf, h04, " ");
+ fprintf(outf, h05);
+ fprintf(outf, h06);
+ fprintf(outf, h07, fname);
+ fprintf(outf, h09, ttf->psname);
+
+ fprintf(outf, h10);
+ fprintf(outf, h11, fname);
+/* fprintf(outf, h12, 4000000); */
+
+ /* XUID generation:
+ * 103 0 0 C1 C2 C3 C4
+ * C1 - CRC-32 of the entire source TrueType font
+ * C2 - number of glyphs in the subset
+ * C3 - CRC-32 of the glyph array
+ * C4 - CRC-32 of the encoding array
+ *
+ * All CRC-32 numbers are presented as hexadecimal numbers
+ */
+
+ fprintf(outf, h17, crc32(ttf->ptr, ttf->fsize), nGlyphs, crc32(glyphArray, nGlyphs * 2), crc32(encoding, nGlyphs));
+ fprintf(outf, h13);
+ fprintf(outf, h14, XUnits(UPEm, GetInt16(table, 36, 1)), XUnits(UPEm, GetInt16(table, 38, 1)), XUnits(UPEm, GetInt16(table, 40, 1)), XUnits(UPEm, GetInt16(table, 42, 1)));
+ fprintf(outf, h15);
+
+ for (i = 0; i < nGlyphs; i++) {
+ fprintf(outf, h16, encoding[i], i);
+ }
+
+ fprintf(outf, h30, nGlyphs+1);
+ fprintf(outf, h31);
+ fprintf(outf, h32);
+
+ for (i = 0; i < nGlyphs; i++) {
+ fprintf(outf, h33, i);
+ r = GetTTGlyphOutline(ttf, glyphArray[i] < ttf->nglyphs ? glyphArray[i] : 0, &pa, &metrics, 0);
+
+ if (r > 0) {
+ n = BSplineToPSPath(pa, r, &path);
+ } else {
+ n = 0; /* glyph might have zero contours but valid metrics ??? */
+ path = 0;
+ if (r < 0) { /* glyph is not present in the font - pa array was not allocated, so no need to free it */
+ continue;
+ }
+ }
+ fprintf(outf, "\t%d %d %d %d %d %d setcachedevice\n",
+ wmode == 0 ? XUnits(UPEm, metrics.aw) : 0,
+ wmode == 0 ? 0 : -XUnits(UPEm, metrics.ah),
+ XUnits(UPEm, metrics.xMin),
+ XUnits(UPEm, metrics.yMin),
+ XUnits(UPEm, metrics.xMax),
+ XUnits(UPEm, metrics.yMax));
+
+ for (j = 0; j < n; j++) {
+ switch (path[j].type) {
+ case PS_MOVETO:
+ fprintf(outf, "\t%d %d moveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
+ break;
+
+ case PS_LINETO:
+ fprintf(outf, "\t%d %d lineto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1));
+ break;
+
+ case PS_CURVETO:
+ fprintf(outf, "\t%d %d %d %d %d %d curveto\n", XUnits(UPEm, path[j].x1), XUnits(UPEm, path[j].y1), XUnits(UPEm, path[j].x2), XUnits(UPEm, path[j].y2), XUnits(UPEm, path[j].x3), XUnits(UPEm, path[j].y3));
+ break;
+
+ case PS_CLOSEPATH:
+ fprintf(outf, "\tclosepath\n");
+ break;
+ }
+ }
+ if (n > 0) fprintf(outf, "\tfill\n"); /* if glyph is not a whitespace character */
+
+ fprintf(outf, h34);
+
+ free(pa);
+ free(path);
+ }
+ fprintf(outf, h35);
+
+ fprintf(outf, h40);
+ fprintf(outf, h41, fname);
+
+ fprintf(outf, h08);
+ return SF_OK;
+}
+#endif
+
+#ifndef NO_TTCR
+int CreateTTFromTTGlyphs(TrueTypeFont *ttf,
+ const char *fname,
+ uint16 *glyphArray,
+ byte *encoding,
+ int nGlyphs,
+ int nNameRecs,
+ NameRecord *nr,
+ uint32 flags)
+{
+ TrueTypeCreator *ttcr;
+ TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0, *cmap=0, *name=0, *post = 0, *os2 = 0;
+ byte *p;
+ int i;
+ int res;
+ uint32 *gID;
+
+ TrueTypeCreatorNewEmpty(T_true, &ttcr);
+
+ /** name **/
+
+ if (flags & TTCF_AutoName) {
+ /* not implemented yet
+ NameRecord *names;
+ NameRecord newname;
+ int n = GetTTNameRecords(ttf, &names);
+ int n1 = 0, n2 = 0, n3 = 0, n4 = 0, n5 = 0, n6 = 0;
+ byte *cp1;
+ byte suffix[32];
+ uint32 c1 = crc32(glyphArray, nGlyphs * 2);
+ uint32 c2 = crc32(encoding, nGlyphs);
+ int len;
+ snprintf(suffix, 31, "S%08X%08X-%d", c1, c2, nGlyphs);
+
+ name = TrueTypeTableNew_name(0, 0);
+ for (i = 0; i < n; i++) {
+ if (names[i].platformID == 1 && names[i].encodingID == 0 && names[i].languageID == 0 && names[i].nameID == 1) {
+
+ memcpy(newname, names+i, sizeof(NameRecord));
+ newname.slen = name[i].slen + strlen(suffix);
+ */
+ const byte ptr[] = {0,'T',0,'r',0,'u',0,'e',0,'T',0,'y',0,'p',0,'e',0,'S',0,'u',0,'b',0,'s',0,'e',0,'t'};
+ NameRecord n1 = {1, 0, 0, 6, 14, "(byte *) TrueTypeSubset"};
+ NameRecord n2 = {3, 1, 1033, 6, 28, 0};
+ n2.sptr = (byte *) ptr;
+ name = TrueTypeTableNew_name(0, 0);
+ nameAdd(name, &n1);
+ nameAdd(name, &n2);
+ } else {
+ if (nNameRecs == 0) {
+ NameRecord *names;
+ int n = GetTTNameRecords(ttf, &names);
+ name = TrueTypeTableNew_name(n, names);
+ DisposeNameRecords(names, n);
+ } else {
+ name = TrueTypeTableNew_name(nNameRecs, nr);
+ }
+ }
+
+ /** maxp **/
+ maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp));
+
+ /** hhea **/
+ p = getTable(ttf, O_hhea);
+ if (p) {
+ hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1));
+ } else {
+ hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
+ }
+
+ /** head **/
+
+ p = getTable(ttf, O_head);
+ assert(p != 0);
+ head = TrueTypeTableNew_head(GetUInt32(p, 4, 1),
+ GetUInt16(p, 16, 1),
+ GetUInt16(p, 18, 1),
+ p+20,
+ GetUInt16(p, 44, 1),
+ GetUInt16(p, 46, 1),
+ GetInt16(p, 48, 1));
+
+
+ /** glyf **/
+
+ glyf = TrueTypeTableNew_glyf();
+ gID = scalloc(nGlyphs, sizeof(uint32));
+
+ for (i = 0; i < nGlyphs; i++) {
+ gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf);
+ }
+
+
+ /** cmap **/
+ cmap = TrueTypeTableNew_cmap();
+
+ for (i=0; i < nGlyphs; i++) {
+ cmapAdd(cmap, 0x0100, encoding[i], gID[i]);
+ }
+
+ /** cvt **/
+ if ((p = getTable(ttf, O_cvt)) != 0) {
+ cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p);
+ }
+
+ /** prep **/
+ if ((p = getTable(ttf, O_prep)) != 0) {
+ prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p);
+ }
+
+ /** fpgm **/
+ if ((p = getTable(ttf, O_fpgm)) != 0) {
+ fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p);
+ }
+
+ /** post **/
+ if ((p = getTable(ttf, O_post)) != 0) {
+ post = TrueTypeTableNew_post(0x00030000,
+ GetUInt32(p, 4, 1),
+ GetUInt16(p, 8, 1),
+ GetUInt16(p, 10, 1),
+ GetUInt16(p, 12, 1));
+ } else {
+ post = TrueTypeTableNew_post(0x00030000, 0, 0, 0, 0);
+ }
+
+ if (flags & TTCF_IncludeOS2) {
+ if ((p = getTable(ttf, O_OS2)) != 0) {
+ os2 = TrueTypeTableNew(T_OS2, getTableSize(ttf, O_OS2), p);
+ }
+ }
+
+ AddTable(ttcr, name); AddTable(ttcr, maxp); AddTable(ttcr, hhea);
+ AddTable(ttcr, head); AddTable(ttcr, glyf); AddTable(ttcr, cmap);
+ AddTable(ttcr, cvt ); AddTable(ttcr, prep); AddTable(ttcr, fpgm);
+ AddTable(ttcr, post); AddTable(ttcr, os2);
+
+ if ((res = StreamToFile(ttcr, fname)) != SF_OK) {
+#ifdef DEBUG
+ fprintf(stderr, "StreamToFile: error code: %d.\n", res);
+#endif
+ }
+
+ TrueTypeCreatorDispose(ttcr);
+ free(gID);
+
+ return res;
+}
+#endif
+
+
+#ifndef NO_TYPE42
+static GlyphOffsets *GlyphOffsetsNew(byte *sfntP)
+{
+ GlyphOffsets *res = smalloc(sizeof(GlyphOffsets));
+ byte *loca;
+ uint16 i, numTables = GetUInt16(sfntP, 4, 1);
+ uint32 locaLen;
+ int16 indexToLocFormat;
+
+ for (i = 0; i < numTables; i++) {
+ uint32 tag = GetUInt32(sfntP + 12, 16 * i, 1);
+ uint32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1);
+ uint32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1);
+
+ if (tag == T_loca) {
+ loca = sfntP + off;
+ locaLen = len;
+ } else if (tag == T_head) {
+ indexToLocFormat = GetInt16(sfntP + off, 50, 1);
+ }
+ }
+
+ res->nGlyphs = locaLen / ((indexToLocFormat == 1) ? 4 : 2);
+ assert(res->nGlyphs != 0);
+ res->offs = scalloc(res->nGlyphs, sizeof(uint32));
+
+ for (i = 0; i < res->nGlyphs; i++) {
+ if (indexToLocFormat == 1) {
+ res->offs[i] = GetUInt32(loca, i * 4, 1);
+ } else {
+ res->offs[i] = GetUInt16(loca, i * 2, 1) << 1;
+ }
+ }
+ return res;
+}
+
+static void GlyphOffsetsDispose(GlyphOffsets *_this)
+{
+ if (_this) {
+ free(_this->offs);
+ free(_this);
+ }
+}
+
+static void DumpSfnts(FILE *outf, byte *sfntP)
+{
+ HexFmt *h = HexFmtNew(outf);
+ uint16 i, numTables = GetUInt16(sfntP, 4, 1);
+ uint32 j, *offs, *len;
+ GlyphOffsets *go = GlyphOffsetsNew(sfntP);
+ byte pad[] = {0,0,0,0}; /* zeroes */
+
+ assert(numTables <= 9); /* Type42 has 9 required tables */
+
+ offs = scalloc(numTables, sizeof(uint32));
+ len = scalloc(numTables, sizeof(uint32));
+
+ fputs("/sfnts [", outf);
+ HexFmtOpenString(h);
+ HexFmtBlockWrite(h, sfntP, 12); /* stream out the Offset Table */
+ HexFmtBlockWrite(h, sfntP+12, 16 * numTables); /* stream out the Table Directory */
+
+ for (i=0; i<numTables; i++) {
+ uint32 tag = GetUInt32(sfntP + 12, 16 * i, 1);
+ uint32 off = GetUInt32(sfntP + 12, 16 * i + 8, 1);
+ uint32 len = GetUInt32(sfntP + 12, 16 * i + 12, 1);
+
+ if (tag != T_glyf) {
+ HexFmtBlockWrite(h, sfntP + off, len);
+ } else {
+ byte *glyf = sfntP + off;
+ uint32 o, l;
+ for (j = 0; j < go->nGlyphs - 1; j++) {
+ o = go->offs[j];
+ l = go->offs[j + 1] - o;
+ HexFmtBlockWrite(h, glyf + o, l);
+ }
+ }
+ HexFmtBlockWrite(h, pad, (4 - (len & 3)) & 3);
+ }
+ HexFmtCloseString(h);
+ fputs("] def\n", outf);
+ GlyphOffsetsDispose(go);
+ HexFmtDispose(h);
+ free(offs);
+ free(len);
+}
+
+int CreateT42FromTTGlyphs(TrueTypeFont *ttf,
+ FILE *outf,
+ const char *psname,
+ uint16 *glyphArray,
+ byte *encoding,
+ int nGlyphs)
+{
+ TrueTypeCreator *ttcr;
+ TrueTypeTable *head=0, *hhea=0, *maxp=0, *cvt=0, *prep=0, *glyf=0, *fpgm=0;
+ byte *p;
+ int i;
+ int res;
+
+ uint32 ver, rev;
+ byte *headP;
+
+ byte *sfntP;
+ uint32 sfntLen;
+ int UPEm = ttf->unitsPerEm;
+
+ uint16 *gID;
+
+ if (nGlyphs >= 256) return SF_GLYPHNUM;
+
+ assert(psname != 0);
+
+ TrueTypeCreatorNewEmpty(T_true, &ttcr);
+
+ /* head */
+ headP = p = getTable(ttf, O_head);
+ assert(p != 0);
+ head = TrueTypeTableNew_head(GetUInt32(p, 4, 1), GetUInt16(p, 16, 1), GetUInt16(p, 18, 1), p+20, GetUInt16(p, 44, 1), GetUInt16(p, 46, 1), GetInt16(p, 48, 1));
+ ver = GetUInt32(p, 0, 1);
+ rev = GetUInt32(p, 4, 1);
+
+ /** hhea **/
+ p = getTable(ttf, O_hhea);
+ if (p) {
+ hhea = TrueTypeTableNew_hhea(GetUInt16(p, 4, 1), GetUInt16(p, 6, 1), GetUInt16(p, 8, 1), GetUInt16(p, 18, 1), GetUInt16(p, 20, 1));
+ } else {
+ hhea = TrueTypeTableNew_hhea(0, 0, 0, 0, 0);
+ }
+
+ /** maxp **/
+ maxp = TrueTypeTableNew_maxp(getTable(ttf, O_maxp), getTableSize(ttf, O_maxp));
+
+ /** cvt **/
+ if ((p = getTable(ttf, O_cvt)) != 0) {
+ cvt = TrueTypeTableNew(T_cvt, getTableSize(ttf, O_cvt), p);
+ }
+
+ /** prep **/
+ if ((p = getTable(ttf, O_prep)) != 0) {
+ prep = TrueTypeTableNew(T_prep, getTableSize(ttf, O_prep), p);
+ }
+
+ /** fpgm **/
+ if ((p = getTable(ttf, O_fpgm)) != 0) {
+ fpgm = TrueTypeTableNew(T_fpgm, getTableSize(ttf, O_fpgm), p);
+ }
+
+ /** glyf **/
+ glyf = TrueTypeTableNew_glyf();
+ gID = scalloc(nGlyphs, sizeof(uint32));
+
+ for (i = 0; i < nGlyphs; i++) {
+ gID[i] = glyfAdd(glyf, GetTTRawGlyphData(ttf, glyphArray[i]), ttf);
+ }
+
+ AddTable(ttcr, head); AddTable(ttcr, hhea); AddTable(ttcr, maxp); AddTable(ttcr, cvt);
+ AddTable(ttcr, prep); AddTable(ttcr, glyf); AddTable(ttcr, fpgm);
+
+ if ((res = StreamToMemory(ttcr, &sfntP, &sfntLen)) != SF_OK) {
+ TrueTypeCreatorDispose(ttcr);
+ free(gID);
+ return res;
+ }
+
+ fprintf(outf, "%%!PS-TrueTypeFont-%d.%d-%d.%d\n", ver>>16, ver & 0xFFFF, rev>>16, rev & 0xFFFF);
+ fprintf(outf, "%%%%Creator: %s %s %s\n", modname, modver, modextra);
+ fprintf(outf, "%%- Font subset generated from a source font file: '%s'\n", ttf->fname);
+ fprintf(outf, "%%- Original font name: %s\n", ttf->psname);
+ fprintf(outf, "%%- Original font family: %s\n", ttf->family);
+ fprintf(outf, "%%- Original font sub-family: %s\n", ttf->subfamily);
+ fprintf(outf, "11 dict begin\n");
+ fprintf(outf, "/FontName /%s def\n", psname);
+ fprintf(outf, "/PaintType 0 def\n");
+ fprintf(outf, "/FontMatrix [1 0 0 1 0 0] def\n");
+ fprintf(outf, "/FontBBox [%d %d %d %d] def\n", XUnits(UPEm, GetInt16(headP, 36, 1)), XUnits(UPEm, GetInt16(headP, 38, 1)), XUnits(UPEm, GetInt16(headP, 40, 1)), XUnits(UPEm, GetInt16(headP, 42, 1)));
+ fprintf(outf, "/FontType 42 def\n");
+ fprintf(outf, "/Encoding 256 array def\n");
+ fprintf(outf, " 0 1 255 {Encoding exch /.notdef put} for\n");
+
+ for (i = 1; i<nGlyphs; i++) {
+ fprintf(outf, "Encoding %d /glyph%d put\n", encoding[i], gID[i]);
+ }
+ fprintf(outf, "/XUID [103 0 1 16#%08X %d 16#%08X 16#%08X] def\n", crc32(ttf->ptr, ttf->fsize), nGlyphs, crc32(glyphArray, nGlyphs * 2), crc32(encoding, nGlyphs));
+
+ DumpSfnts(outf, sfntP);
+
+ /* dump charstrings */
+ fprintf(outf, "/CharStrings %d dict dup begin\n", nGlyphs);
+ fprintf(outf, "/.notdef 0 def\n");
+ for (i = 1; i < glyfCount(glyf); i++) {
+ fprintf(outf,"/glyph%d %d def\n", i, i);
+ }
+ fprintf(outf, "end readonly def\n");
+
+ fprintf(outf, "FontName currentdict end definefont pop\n");
+ TrueTypeCreatorDispose(ttcr);
+ free(gID);
+ free(sfntP);
+ return SF_OK;
+}
+#endif
+
+
+#ifndef NO_MAPPERS
+int MapString(TrueTypeFont *ttf, uint16 *str, int nchars, uint16 *glyphArray, int bvertical)
+{
+ int i;
+ uint16 *cp;
+
+ if (ttf->cmapType == CMAP_NOT_USABLE ) return -1;
+ if (!nchars) return 0;
+
+ if (glyphArray == 0) {
+ cp = str;
+ } else {
+ cp = glyphArray;
+ }
+
+ switch (ttf->cmapType) {
+ case CMAP_MS_Symbol:
+ if( ttf->mapper == getGlyph0 ) {
+ uint16 aChar;
+ for( i = 0; i < nchars; i++ ) {
+ aChar = str[i];
+ if( ( aChar & 0xf000 ) == 0xf000 )
+ aChar &= 0x00ff;
+ cp[i] = aChar;
+ }
+ }
+ else if( glyphArray )
+ memcpy(glyphArray, str, nchars * 2);
+ break;
+
+ case CMAP_MS_Unicode:
+ if (glyphArray != 0) {
+ memcpy(glyphArray, str, nchars * 2);
+ }
+ break;
+
+ case CMAP_MS_ShiftJIS: TranslateString12(str, cp, nchars); break;
+ case CMAP_MS_Big5: TranslateString13(str, cp, nchars); break;
+ case CMAP_MS_PRC: TranslateString14(str, cp, nchars); break;
+ case CMAP_MS_Wansung: TranslateString15(str, cp, nchars); break;
+ case CMAP_MS_Johab: TranslateString16(str, cp, nchars); break;
+ }
+
+ for (i = 0; i < nchars; i++) {
+ cp[i] = ttf->mapper(ttf->cmap, cp[i]);
+ if (cp[i]!=0 && bvertical!=0)
+ cp[i] = UseGSUB(ttf,cp[i],bvertical);
+ }
+ return nchars;
+}
+
+uint16 MapChar(TrueTypeFont *ttf, uint16 ch, int bvertical)
+{
+ switch (ttf->cmapType) {
+ case CMAP_MS_Symbol:
+ if( ttf->mapper == getGlyph0 && ( ch & 0xf000 ) == 0xf000 )
+ ch &= 0x00ff;
+ return ttf->mapper(ttf->cmap, ch );
+
+ case CMAP_MS_Unicode: break;
+ case CMAP_MS_ShiftJIS: ch = TranslateChar12(ch); break;
+ case CMAP_MS_Big5: ch = TranslateChar13(ch); break;
+ case CMAP_MS_PRC: ch = TranslateChar14(ch); break;
+ case CMAP_MS_Wansung: ch = TranslateChar15(ch); break;
+ case CMAP_MS_Johab: ch = TranslateChar16(ch); break;
+ default: return 0;
+ }
+ ch = ttf->mapper(ttf->cmap, ch);
+ if (ch!=0 && bvertical!=0)
+ ch = UseGSUB(ttf,ch,bvertical);
+ return ch;
+}
+#endif
+
+TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, uint16 *glyphArray, int nGlyphs, int mode)
+{
+ byte *table;
+ TTSimpleGlyphMetrics *res;
+ int i;
+ uint16 glyphID;
+ int n;
+ int UPEm = ttf->unitsPerEm;
+
+ if (mode == 0) {
+ table = getTable(ttf, O_hmtx);
+ n = ttf->numberOfHMetrics;
+ } else {
+ table = getTable(ttf, O_vmtx);
+ n = ttf->numOfLongVerMetrics;
+ }
+
+ if (!nGlyphs || !glyphArray) return 0; /* invalid parameters */
+ if (!n || !table) return 0; /* the font does not contain the requested metrics */
+
+ res = calloc(nGlyphs, sizeof(TTSimpleGlyphMetrics));
+ assert(res != 0);
+
+ for (i=0; i<nGlyphs; i++) {
+ glyphID = glyphArray[i];
+
+ if (glyphID < n) {
+ res[i].adv = XUnits(UPEm, GetUInt16(table, 4 * glyphID, 1));
+ res[i].sb = XUnits(UPEm, GetInt16(table, 4 * glyphID + 2, 1));
+ } else {
+ res[i].adv = XUnits(UPEm, GetUInt16(table, 4 * (n - 1), 1));
+ res[i].sb = XUnits(UPEm, GetInt16(table + n * 4, (glyphID - n) * 2, 1));
+ }
+ }
+
+ return res;
+}
+
+#ifndef NO_MAPPERS
+TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, uint16 firstChar, int nChars, int mode)
+{
+ TTSimpleGlyphMetrics *res = 0;
+ uint16 *str;
+ int i, n;
+
+ str = malloc(nChars * 2);
+ assert(str != 0);
+
+ for (i=0; i<nChars; i++) str[i] = firstChar + i;
+ if ((n = MapString(ttf, str, nChars, 0, mode)) != -1) {
+ res = GetTTSimpleGlyphMetrics(ttf, str, n, mode);
+ }
+
+ free(str);
+
+ return res;
+}
+#endif
+
+void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info)
+{
+ byte *table;
+ int UPEm = ttf->unitsPerEm;
+
+ memset(info, 0, sizeof(TTGlobalFontInfo));
+
+ info->family = ttf->family;
+ info->subfamily = ttf->subfamily;
+ info->psname = ttf->psname;
+ info->symbolEncoded = ttf->cmapType == CMAP_MS_Symbol ? 1 : 0;
+
+ table = getTable(ttf, O_OS2);
+ if (table) {
+ info->weight = GetUInt16(table, 4, 1);
+ info->width = GetUInt16(table, 6, 1);
+
+ /* There are 3 different versions of OS/2 table: original (68 bytes long),
+ * Microsoft old (78 bytes long) and Microsoft new (86 bytes long,)
+ * Apple's documentation recommends looking at the table length.
+ */
+ if (getTableSize(ttf, O_OS2) > 68) {
+ info->typoAscender = XUnits(UPEm,GetInt16(table, 68, 1));
+ info->typoDescender = XUnits(UPEm, GetInt16(table, 70, 1));
+ info->typoLineGap = XUnits(UPEm, GetInt16(table, 72, 1));
+ info->winAscent = XUnits(UPEm, GetUInt16(table, 74, 1));
+ info->winDescent = XUnits(UPEm, GetUInt16(table, 76, 1));
+ }
+ if (ttf->cmapType == CMAP_MS_Unicode) {
+ info->rangeFlag = 1;
+ info->ur1 = GetUInt32(table, 42, 1);
+ info->ur2 = GetUInt32(table, 46, 1);
+ info->ur3 = GetUInt32(table, 50, 1);
+ info->ur4 = GetUInt32(table, 54, 1);
+ }
+ memcpy(info->panose, table + 32, 10);
+ }
+
+
+ table = getTable(ttf, O_post);
+ if (table) {
+ info->pitch = GetUInt32(table, 12, 1);
+ info->italicAngle = GetInt32(table, 4, 1);
+ }
+
+ table = getTable(ttf, O_head); /* 'head' tables is always there */
+ info->xMin = XUnits(UPEm, GetInt16(table, 36, 1));
+ info->yMin = XUnits(UPEm, GetInt16(table, 38, 1));
+ info->xMax = XUnits(UPEm, GetInt16(table, 40, 1));
+ info->yMax = XUnits(UPEm, GetInt16(table, 42, 1));
+
+ table = getTable(ttf, O_hhea);
+ if (table) {
+ info->ascender = XUnits(UPEm, GetInt16(table, 4, 1));
+ info->descender = XUnits(UPEm, GetInt16(table, 6, 1));
+ info->linegap = XUnits(UPEm, GetInt16(table, 8, 1));
+ }
+
+ table = getTable(ttf, O_vhea);
+ if (table) {
+ info->vascent = XUnits(UPEm, GetInt16(table, 4, 1));
+ info->vdescent = XUnits(UPEm, GetInt16(table, 6, 1));
+ }
+}
+
+void KernGlyphs(TrueTypeFont *ttf, uint16 *glyphs, int nglyphs, int wmode, KernData *kern)
+{
+ int i;
+
+ if (!nglyphs || !glyphs || !kern) return;
+
+ for (i = 0; i < nglyphs-1; i++) kern[i].x = kern[i].y = 0;
+
+ switch (ttf->kerntype) {
+ case KT_APPLE_NEW: KernGlyphsPrim1(ttf, glyphs, nglyphs, wmode, kern); return;
+ case KT_MICROSOFT: KernGlyphsPrim2(ttf, glyphs, nglyphs, wmode, kern); return;
+ default: return;
+ }
+}
+
+GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, uint32 glyphID)
+{
+ byte *glyf = getTable(ttf, O_glyf);
+ byte *hmtx = getTable(ttf, O_hmtx);
+ byte *ptr;
+ uint32 length;
+ GlyphData *d;
+ ControlPoint *cp;
+ int i, n, m;
+
+ if (glyphID >= ttf->nglyphs) return 0;
+
+ ptr = glyf + ttf->goffsets[glyphID];
+ length = ttf->goffsets[glyphID+1] - ttf->goffsets[glyphID];
+
+ d = malloc(sizeof(GlyphData)); assert(d != 0);
+
+ if (length) {
+ d->ptr = malloc((length + 1) & ~1); assert(d->ptr != 0);
+ memcpy(d->ptr, ptr, length);
+ if (GetInt16(ptr, 0, 1) >= 0) {
+ d->compflag = 0;
+ } else {
+ d->compflag = 1;
+ }
+ } else {
+ d->ptr = 0;
+ d->compflag = 0;
+ }
+
+ d->glyphID = glyphID;
+ d->nbytes = (length + 1) & ~1;
+
+ /* now calculate npoints and ncontours */
+ n = GetTTGlyphPoints(ttf, glyphID, &cp);
+ if (n != -1) {
+ m = 0;
+ for (i = 0; i < n; i++) {
+ if (cp[i].flags & 0x8000) m++;
+ }
+ d->npoints = n;
+ d->ncontours = m;
+ free(cp);
+ } else {
+ d->npoints = 0;
+ d->ncontours = 0;
+ }
+
+ /* get adwance width and left sidebearing */
+ if (glyphID < ttf->numberOfHMetrics) {
+ d->aw = GetUInt16(hmtx, 4 * glyphID, 1);
+ d->lsb = GetInt16(hmtx, 4 * glyphID + 2, 1);
+ } else {
+ d->aw = GetUInt16(hmtx, 4 * (ttf->numberOfHMetrics - 1), 1);
+ d->lsb = GetInt16(hmtx + n * 4, (glyphID - ttf->numberOfHMetrics) * 2, 1);
+ }
+
+ return d;
+}
+
+int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr)
+{
+ byte *table = getTable(ttf, O_name);
+ uint16 n = GetUInt16(table, 2, 1);
+ NameRecord *rec;
+ uint16 i;
+
+ *nr = 0;
+ if (n == 0) return 0;
+
+ rec = calloc(n, sizeof(NameRecord));
+
+ for (i = 0; i < n; i++) {
+ rec[i].platformID = GetUInt16(table + 6, 12 * i, 1);
+ rec[i].encodingID = GetUInt16(table + 6, 2 + 12 * i, 1);
+ rec[i].languageID = GetUInt16(table + 6, 4 + 12 * i, 1);
+ rec[i].nameID = GetUInt16(table + 6, 6 + 12 * i, 1);
+ rec[i].slen = GetUInt16(table + 6, 8 + 12 * i, 1);
+ if (rec[i].slen) {
+ rec[i].sptr = (byte *) malloc(rec[i].slen); assert(rec[i].sptr != 0);
+ memcpy(rec[i].sptr, table + GetUInt16(table, 4, 1) + GetUInt16(table + 6, 10 + 12 * i, 1), rec[i].slen);
+ } else {
+ rec[i].sptr = 0;
+ }
+ }
+
+ *nr = rec;
+ return n;
+}
+
+void DisposeNameRecords(NameRecord* nr, int n)
+{
+ int i;
+ for (i = 0; i < n; i++) {
+ if (nr[i].sptr) free(nr[i].sptr);
+ }
+ free(nr);
+}
+
+
+
+
+#ifdef TEST1
+/* This example creates a subset of a TrueType font with two encoded characters */
+int main(int ac, char **av)
+{
+ TrueTypeFont *fnt;
+ int r;
+
+ /* Array of Unicode source characters */
+ uint16 chars[2];
+
+ /* Encoding vector maps character encoding to the ordinal number
+ * of the glyph in the output file */
+ byte encoding[2];
+
+ /* This array is for glyph IDs that source characters map to */
+ uint16 g[2];
+
+
+ if (ac < 2) return 0;
+
+ if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
+ fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
+ return 0;
+ }
+
+
+ /* We want to create the output file that only contains two Unicode characters:
+ * L'a' and L'A' */
+
+ chars[0] = L'a';
+ chars[1] = L'A';
+
+ /* Figure out what glyphs do these characters map in our font */
+ MapString(fnt, chars, 2, g);
+
+ /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the
+ * newly generated font */
+ encoding[0] = chars[0];
+ encoding[1] = chars[1];
+
+
+ /* Generate a subset */
+ CreateT3FromTTGlyphs(fnt, stdout, 0, g, encoding, 2, 0);
+
+ /* Now call the dtor for the font */
+ CloseTTFont(fnt);
+ return 0;
+}
+#endif
+
+#ifdef TEST2
+/* This example extracts first 224 glyphs from a TT fonts and encodes them starting at 32 */
+int main(int ac, char **av)
+{
+ TrueTypeFont *fnt;
+ int i, r;
+
+ /* Array of Unicode source characters */
+ uint16 glyphs[224];
+
+ /* Encoding vector maps character encoding to the ordinal number
+ * of the glyph in the output file */
+ byte encoding[224];
+
+
+
+ for (i=0; i<224; i++) {
+ glyphs[i] = i;
+ encoding[i] = 32 + i;
+ }
+
+ if (ac < 2) return 0;
+
+ if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
+ fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
+ return 0;
+ }
+
+
+ /* Encode the characters. Value of encoding[i] is the number 0..255 which maps to glyph i of the
+ * newly generated font */
+
+ /* Generate a subset */
+ CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 224, 0);
+
+ /* Now call the dtor for the font */
+ CloseTTFont(fnt);
+ return 0;
+}
+#endif
+
+#ifdef TEST3
+/* Glyph metrics example */
+int main(int ac, char **av)
+{
+ TrueTypeFont *fnt;
+ int i, r;
+ uint16 glyphs[224];
+ TTSimpleGlyphMetrics *m;
+
+ for (i=0; i<224; i++) {
+ glyphs[i] = i;
+ }
+
+ if (ac < 2) return 0;
+
+ if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
+ fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
+ return 0;
+ }
+
+ if ((m = GetTTSimpleGlyphMetrics(fnt, glyphs, 224, 0)) == 0) {
+ printf("Requested metrics is not available\n");
+ } else {
+ for (i=0; i<224; i++) {
+ printf("%d. advWid: %5d, LSBear: %5d\n", i, m[i].adv, m[i].sb);
+ }
+ }
+
+ /* Now call the dtor for the font */
+ free(m);
+ CloseTTFont(fnt);
+ return 0;
+}
+#endif
+
+#ifdef TEST4
+int main(int ac, char **av)
+{
+ TrueTypeFont *fnt;
+ TTGlobalFontInfo info;
+ int i, r;
+
+
+ if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
+ fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
+ return 0;
+ }
+
+ printf("Font file: %s\n", av[1]);
+
+#ifdef PRINT_KERN
+ switch (fnt->kerntype) {
+ case KT_MICROSOFT:
+ printf("\tkern: MICROSOFT, ntables: %d.", fnt->nkern);
+ if (fnt->nkern) {
+ printf(" [");
+ for (i=0; i<fnt->nkern; i++) {
+ printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1));
+ }
+ printf("]");
+ }
+ printf("\n");
+ break;
+
+ case KT_APPLE_NEW:
+ printf("\tkern: APPLE_NEW, ntables: %d.", fnt->nkern);
+ if (fnt->nkern) {
+ printf(" [");
+ for (i=0; i<fnt->nkern; i++) {
+ printf("%04X ", GetUInt16(fnt->kerntables[i], 4, 1));
+ }
+ printf("]");
+ }
+ printf("\n");
+ break;
+
+ case KT_NONE:
+ printf("\tkern: none.\n");
+ break;
+
+ default:
+ printf("\tkern: unrecoginzed.\n");
+ break;
+ }
+ printf("\n");
+#endif
+
+ GetTTGlobalFontInfo(fnt, &info);
+ printf("\tfamily name: `%s`\n", info.family);
+ printf("\tsubfamily name: `%s`\n", info.subfamily);
+ printf("\tpostscript name: `%s`\n", info.psname);
+ printf("\tweight: %d\n", info.weight);
+ printf("\twidth: %d\n", info.width);
+ printf("\tpitch: %d\n", info.pitch);
+ printf("\titalic angle: %d\n", info.italicAngle);
+ printf("\tbouding box: [%d %d %d %d]\n", info.xMin, info.yMin, info.xMax, info.yMax);
+ printf("\tascender: %d\n", info.ascender);
+ printf("\tdescender: %d\n", info.descender);
+ printf("\tlinegap: %d\n", info.linegap);
+ printf("\tvascent: %d\n", info.vascent);
+ printf("\tvdescent: %d\n", info.vdescent);
+ printf("\ttypoAscender: %d\n", info.typoAscender);
+ printf("\ttypoDescender: %d\n", info.typoDescender);
+ printf("\ttypoLineGap: %d\n", info.typoLineGap);
+ printf("\twinAscent: %d\n", info.winAscent);
+ printf("\twinDescent: %d\n", info.winDescent);
+ printf("\tUnicode ranges:\n");
+ for (i = 0; i < 32; i++) {
+ if ((info.ur1 >> i) & 1) {
+ printf("\t\t\t%s\n", UnicodeRangeName(i));
+ }
+ }
+ for (i = 0; i < 32; i++) {
+ if ((info.ur2 >> i) & 1) {
+ printf("\t\t\t%s\n", UnicodeRangeName(i+32));
+ }
+ }
+ for (i = 0; i < 32; i++) {
+ if ((info.ur3 >> i) & 1) {
+ printf("\t\t\t%s\n", UnicodeRangeName(i+64));
+ }
+ }
+ for (i = 0; i < 32; i++) {
+ if ((info.ur4 >> i) & 1) {
+ printf("\t\t\t%s\n", UnicodeRangeName(i+96));
+ }
+ }
+
+ CloseTTFont(fnt);
+ return 0;
+}
+#endif
+
+#ifdef TEST5
+/* Kerning example */
+int main(int ac, char **av)
+{
+ TrueTypeFont *fnt;
+ uint16 g[224];
+ KernData d[223];
+ int r, i, k = 0;
+
+ g[k++] = 11;
+ g[k++] = 36;
+ g[k++] = 11;
+ g[k++] = 98;
+ g[k++] = 11;
+ g[k++] = 144;
+ g[k++] = 41;
+ g[k++] = 171;
+ g[k++] = 51;
+ g[k++] = 15;
+
+ if (ac < 2) return 0;
+
+ if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
+ fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
+ return 0;
+ }
+
+ KernGlyphs(fnt, g, k, 0, d);
+
+ for (i = 0; i < k-1; i++) {
+ printf("%3d %3d: [%3d %3d]\n", g[i], g[i+1], d[i].x, d[i].y);
+ }
+
+ CloseTTFont(fnt);
+ return 0;
+}
+#endif
+
+
+
+#ifdef TEST6
+/* This example extracts a single glyph from a font */
+int main(int ac, char **av)
+{
+ TrueTypeFont *fnt;
+ int r, i;
+
+ uint16 glyphs[256];
+ byte encoding[256];
+
+ for (i=0; i<256; i++) {
+ glyphs[i] = 512 + i;
+ encoding[i] = i;
+ }
+
+#if 0
+ i=0;
+ glyphs[i++] = 2001;
+ glyphs[i++] = 2002;
+ glyphs[i++] = 2003;
+ glyphs[i++] = 2004;
+ glyphs[i++] = 2005;
+ glyphs[i++] = 2006;
+ glyphs[i++] = 2007;
+ glyphs[i++] = 2008;
+ glyphs[i++] = 2009;
+ glyphs[i++] = 2010;
+ glyphs[i++] = 2011;
+ glyphs[i++] = 2012;
+ glyphs[i++] = 2013;
+ glyphs[i++] = 2014;
+ glyphs[i++] = 2015;
+ glyphs[i++] = 2016;
+ glyphs[i++] = 2017;
+ glyphs[i++] = 2018;
+ glyphs[i++] = 2019;
+ glyphs[i++] = 2020;
+
+
+ r = 97;
+ i = 0;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+ encoding[i++] = r++;
+#endif
+
+ if (ac < 2) return 0;
+
+ if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
+ fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
+ return 0;
+ }
+
+ /* Generate a subset */
+ CreateT3FromTTGlyphs(fnt, stdout, 0, glyphs, encoding, 256, 0);
+
+ fprintf(stderr, "UnitsPerEm: %d.\n", fnt->unitsPerEm);
+
+ /* Now call the dtor for the font */
+ CloseTTFont(fnt);
+ return 0;
+}
+#endif
+
+#ifdef TEST7
+/* NameRecord extraction example */
+int main(int ac, char **av)
+{
+ TrueTypeFont *fnt;
+ int r, i, j, n;
+ NameRecord *nr;
+
+ if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
+ fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
+ return 0;
+ }
+
+ if ((n = GetTTNameRecords(fnt, &nr)) == 0) {
+ fprintf(stderr, "No name records in the font.\n");
+ return 0;
+ }
+
+ printf("Number of name records: %d.\n", n);
+ for (i = 0; i < n; i++) {
+ printf("%d %d %04X %d [", nr[i].platformID, nr[i].encodingID, nr[i].languageID, nr[i].nameID);
+ for (j=0; j<nr[i].slen; j++) {
+ printf("%c", isprint(nr[i].sptr[j]) ? nr[i].sptr[j] : '.');
+ }
+ printf("]\n");
+ }
+
+
+ DisposeNameRecords(nr, n);
+ CloseTTFont(fnt);
+ return 0;
+}
+#endif
+
+#ifdef TEST8
+/* TrueType -> TrueType subsetting */
+int main(int ac, char **av)
+{
+ TrueTypeFont *fnt;
+ uint16 glyphArray[] = { 0, 98, 99, 22, 24, 25, 26, 27, 28, 29, 30, 31, 1270, 1289, 34};
+ byte encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
+ int r;
+
+ if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
+ fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
+ return 0;
+ }
+
+ CreateTTFromTTGlyphs(fnt, "subfont.ttf", glyphArray, encoding, 15, 0, 0, TTCF_AutoName | TTCF_IncludeOS2);
+
+ CloseTTFont(fnt);
+
+ return 0;
+}
+#endif
+
+#ifdef TEST9
+/* TrueType -> Type42 subsetting */
+int main(int ac, char **av)
+{
+ TrueTypeFont *fnt;
+ /*
+ uint16 glyphArray[] = { 0, 20, 21, 22, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34};
+ byte encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
+ */
+ uint16 glyphArray[] = { 0, 6711, 6724, 11133, 11144, 14360, 26, 27, 28, 29, 30, 31, 1270, 1289, 34};
+ byte encoding[] = {32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46};
+ int r;
+
+ if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
+ fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
+ return 0;
+ }
+
+ CreateT42FromTTGlyphs(fnt, stdout, "testfont", glyphArray, encoding, 15);
+
+ CloseTTFont(fnt);
+
+ return 0;
+}
+#endif
+
+#ifdef TEST10
+/* Component glyph test */
+int main(int ac, char **av)
+{
+ TrueTypeFont *fnt;
+ int r, i;
+ list glyphlist = listNewEmpty();
+
+ if ((r = OpenTTFont(av[1], 0, &fnt)) != SF_OK) {
+ fprintf(stderr, "Error %d opening font file: `%s`.\n", r, av[1]);
+ return 0;
+ }
+
+ for (i = 0; i < fnt->nglyphs; i++) {
+ r = GetTTGlyphComponents(fnt, i, glyphlist);
+ if (r > 1) {
+ printf("%d -> ", i);
+ listToFirst(glyphlist);
+ do {
+ printf("%d ", (int) listCurrent(glyphlist));
+ } while (listNext(glyphlist));
+ printf("\n");
+ } else {
+ printf("%d: single glyph.\n", i);
+ }
+ listClear(glyphlist);
+ }
+
+ CloseTTFont(fnt);
+ listDispose(glyphlist);
+
+ return 0;
+}
+#endif
+
+
diff --git a/psprint/source/fontsubset/sft.h b/psprint/source/fontsubset/sft.h
new file mode 100644
index 000000000000..1c94d8bda8a7
--- /dev/null
+++ b/psprint/source/fontsubset/sft.h
@@ -0,0 +1,649 @@
+/*************************************************************************
+ *
+ * $RCSfile: sft.h,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:37 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Alexander Gelfenbain
+ *
+ *
+ ************************************************************************/
+
+/* $Id: sft.h,v 1.1.1.1 2001-05-08 11:45:37 pl Exp $ */
+
+/**
+ *
+ * @file sft.h
+ * @brief Sun Font Tools
+ * @author Alexander Gelfenbain
+ */
+
+/*
+ * If NO_MAPPERS is defined, MapChar() and MapString() and consequently GetTTSimpleCharMetrics()
+ * don't get compiled in. This is done to avoid including a large chunk of code (TranslateXY() from
+ * xlat.c in the projects that don't require it.
+ *
+ * If NO_TYPE3 is defined CreateT3FromTTGlyphs() does not get compiled in.
+ * If NO_TYPE42 is defined Type42-related code is excluded
+ * If NO_TTCR is defined TrueType creation related code is excluded\
+ * If NO_LIST is defined list.h and piblic functions that use it don't get compiled
+ */
+
+/*
+ * Generated fonts contain an XUID entry in the form of:
+ *
+ * 103 0 T C1 N C2 C3
+ *
+ * 103 - Sun's Adobe assigned XUID number. Contact person: Alexander Gelfenbain <gelf@eng.sun.com>
+ *
+ * T - font type. 0: Type 3, 1: Type 42
+ * C1 - CRC-32 of the entire source TrueType font
+ * N - number of glyphs in the subset
+ * C2 - CRC-32 of the array of glyph IDs used to generate the subset
+ * C3 - CRC-32 of the array of encoding numbers used to generate the subset
+ *
+ */
+
+
+#ifndef __SUBFONT_H
+#define __SUBFONT_H
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#ifndef NO_LIST
+#include "list.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __sparc
+#ifndef G_BIG_ENDIAN
+#define G_BIG_ENDIAN
+#endif
+#endif
+
+#ifdef __i386
+#ifndef G_LITTLE_ENDIAN
+#define G_LITTLE_ENDIAN
+#endif
+#endif
+
+#if !defined(G_BIG_ENDIAN) && !defined(G_LITTLE_ENDIAN)
+#error "Either G_BIG_ENDIAN or G_LITTLE_ENDIAN should be defined."
+#endif
+
+#if defined(G_BIG_ENDIAN) && defined(G_LITTLE_ENDIAN)
+#error "This is bizarre"
+#endif
+
+#if 0 /* These should be defined in the makefile */
+#define DEBUG /* Generate debugging output */
+#define DEBUG2 /* More detailed debugging output */
+#define DEBUG3 /* Dump of TrueType outlines */
+#endif
+
+
+
+
+/*@{*/
+#define false 0 /**< standard false value */
+#define true 1 /**< standard true value */
+/*@}*/
+
+/*- XXX These should be dynamically configured */ /*FOLD00*/
+ typedef unsigned char byte;
+ typedef unsigned char uint8;
+ typedef signed char int8;
+ typedef unsigned short int uint16;
+ typedef short int int16;
+
+ typedef unsigned int uint32;
+ typedef int int32;
+ typedef unsigned long long uint64;
+ typedef long long int64;
+
+/*@{*/
+ typedef int16 F2Dot14; /**< fixed: 2.14 */
+ typedef int32 F16Dot16; /**< fixed: 16.16 */
+/*@}*/
+
+ typedef struct {
+ uint16 s;
+ uint16 d;
+ } uint16pair;
+
+/** Return value of OpenTTFont() and CreateT3FromTTGlyphs() */
+ enum SFErrCodes {
+ SF_OK, /**< no error */
+ SF_BADFILE, /**< file not found */
+ SF_FILEIO, /**< file I/O error */
+ SF_MEMORY, /**< memory allocation error */
+ SF_GLYPHNUM, /**< incorrect number of glyphs */
+ SF_BADARG, /**< incorrect arguments */
+ SF_TTFORMAT, /**< incorrect TrueType font format */
+ SF_TABLEFORMAT, /**< incorrect format of a TrueType table */
+ SF_FONTNO /**< incorrect logical font number of a TTC font */
+ };
+
+/** Value of the weight member of the TTGlobalFontInfo struct */
+ enum WeightClass {
+ FW_THIN = 100, /**< Thin */
+ FW_EXTRALIGHT = 200, /**< Extra-light (Ultra-light) */
+ FW_LIGHT = 300, /**< Light */
+ FW_NORMAL = 400, /**< Normal (Regular) */
+ FW_MEDIUM = 500, /**< Medium */
+ FW_SEMIBOLD = 600, /**< Semi-bold (Demi-bold) */
+ FW_BOLD = 700, /**< Bold */
+ FW_EXTRABOLD = 800, /**< Extra-bold (Ultra-bold) */
+ FW_BLACK = 900 /**< Black (Heavy) */
+ };
+
+/** Value of the width member of the TTGlobalFontInfo struct */
+ enum WidthClass {
+ FWIDTH_ULTRA_CONDENSED = 1, /**< 50% of normal */
+ FWIDTH_EXTRA_CONDENSED = 2, /**< 62.5% of normal */
+ FWIDTH_CONDENSED = 3, /**< 75% of normal */
+ FWIDTH_SEMI_CONDENSED = 4, /**< 87.5% of normal */
+ FWIDTH_NORMAL = 5, /**< Medium, 100% */
+ FWIDTH_SEMI_EXPANDED = 6, /**< 112.5% of normal */
+ FWIDTH_EXPANDED = 7, /**< 125% of normal */
+ FWIDTH_EXTRA_EXPANDED = 8, /**< 150% of normal */
+ FWIDTH_ULTRA_EXPANDED = 9 /**< 200% of normal */
+ };
+
+/** Type of the 'kern' table, stored in _TrueTypeFont::kerntype */
+ enum KernType {
+
+ KT_NONE = 0, /**< no kern table */
+ KT_APPLE_NEW = 1, /**< new Apple kern table */
+ KT_MICROSOFT = 2 /**< Microsoft table */
+ };
+
+/* Composite glyph flags definition */
+ enum CompositeFlags {
+ ARG_1_AND_2_ARE_WORDS = 1,
+ ARGS_ARE_XY_VALUES = 1<<1,
+ ROUND_XY_TO_GRID = 1<<2,
+ WE_HAVE_A_SCALE = 1<<3,
+ MORE_COMPONENTS = 1<<5,
+ WE_HAVE_AN_X_AND_Y_SCALE = 1<<6,
+ WE_HAVE_A_TWO_BY_TWO = 1<<7,
+ WE_HAVE_INSTRUCTIONS = 1<<8,
+ USE_MY_METRICS = 1<<9,
+ OVERLAP_COMPOUND = 1<<10
+ };
+
+#ifndef NO_TTCR
+/** Flags for TrueType generation */
+ enum TTCreationFlags {
+ TTCF_AutoName = 1, /**< Automatically generate a compact 'name' table.
+ If this flag is not set, name table is generated
+ either from an array of NameRecord structs passed as
+ arguments or if the array is NULL, 'name' table
+ of the generated TrueType file will be a copy
+ of the name table of the original file.
+ If this flag is set the array of NameRecord structs
+ is ignored and a very compact 'name' table is automatically
+ generated. */
+
+ TTCF_IncludeOS2 = 2 /** If this flag is set OS/2 table from the original font will be
+ copied to the subset */
+ };
+#endif
+
+
+
+
+/** Structure used by GetTTSimpleGlyphMetrics() and GetTTSimpleCharMetrics() functions */
+ typedef struct {
+ uint16 adv; /**< advance width or height */
+ int16 sb; /**< left or top sidebearing */
+ } TTSimpleGlyphMetrics;
+
+
+
+/** Structure used by the TrueType Creator and GetRawGlyphData() */
+
+ typedef struct {
+ uint32 glyphID; /**< glyph ID */
+ uint16 nbytes; /**< number of bytes in glyph data */
+ byte *ptr; /**< pointer to glyph data */
+ uint16 aw; /**< advance width */
+ int16 lsb; /**< left sidebearing */
+ uint16 compflag; /**< 0- if non-composite, 1- otherwise */
+ uint16 npoints; /**< number of points */
+ uint16 ncontours; /**< number of contours */
+ /* */
+ uint32 newID; /**< used internally by the TTCR */
+ } GlyphData;
+
+/** Structure used by the TrueType Creator and CreateTTFromTTGlyphs() */
+ typedef struct {
+ uint16 platformID; /**< Platform ID */
+ uint16 encodingID; /**< Platform-specific encoding ID */
+ uint16 languageID; /**< Language ID */
+ uint16 nameID; /**< Name ID */
+ uint16 slen; /**< String length in bytes */
+ byte *sptr; /**< Pointer to string data (not zero-terminated!) */
+ } NameRecord;
+
+
+
+/** Return value of GetTTGlobalFontInfo() */
+
+ typedef struct {
+ char *family; /**< family name */
+ char *subfamily; /**< subfamily name */
+ char *psname; /**< PostScript name */
+ int weight; /**< value of WeightClass or 0 if can't be determined */
+ int width; /**< value of WidthClass or 0 if can't be determined */
+ int pitch; /**< 0: proportianal font, otherwise: monospaced */
+ int italicAngle; /**< in counter-clockwise degrees * 65536 */
+ int xMin; /**< global bounding box: xMin */
+ int yMin; /**< global bounding box: yMin */
+ int xMax; /**< global bounding box: xMax */
+ int yMax; /**< global bounding box: yMax */
+ int ascender; /**< typographic ascent. */
+ int descender; /**< typographic descent. */
+ int linegap; /**< typographic line gap.\ Negative values are treated as
+ zero in Win 3.1, System 6 and System 7. */
+ int vascent; /**< typographic ascent for vertical writing mode */
+ int vdescent; /**< typographic descent for vertical writing mode */
+ int typoAscender; /**< OS/2 portable typographic ascender */
+ int typoDescender; /**< OS/2 portable typographic descender */
+ int typoLineGap; /**< OS/2 portable typographc line gap */
+ int winAscent; /**< ascender metric for Windows */
+ int winDescent; /**< descender metric for Windows */
+ int symbolEncoded; /**< 1: MS symbol encoded 0: not symbol encoded */
+ int rangeFlag; /**< if set to 1 Unicode Range flags are applicable */
+ uint32 ur1; /**< bits 0 - 31 of Unicode Range flags */
+ uint32 ur2; /**< bits 32 - 63 of Unicode Range flags */
+ uint32 ur3; /**< bits 64 - 95 of Unicode Range flags */
+ uint32 ur4; /**< bits 96 - 127 of Unicode Range flags */
+ byte panose[10]; /**< PANOSE classification number */
+ } TTGlobalFontInfo;
+
+/** Structure used by KernGlyphs() */
+ typedef struct {
+ int x; /**< positive: right, negative: left */
+ int y; /**< positive: up, negative: down */
+ } KernData;
+
+
+/** ControlPoint structure used by GetTTGlyphPoints() */
+ typedef struct {
+ uint32 flags; /**< 00000000 00000000 e0000000 bbbbbbbb */
+ /**< b - byte flags from the glyf array */
+ /**< e == 0 - regular point */
+ /**< e == 1 - end contour */
+ int16 x; /**< X coordinate in EmSquare units */
+ int16 y; /**< Y coordinate in EmSquare units */
+ } ControlPoint;
+
+ typedef struct _TrueTypeFont TrueTypeFont;
+
+/**
+ * @defgroup sft Sun Font Tools Exported Functions
+ */
+
+
+/**
+ * Get the number of fonts contained in a TrueType collection
+ * @param fname - file name
+ * @return number of fonts or zero, if file is not a TTC file.
+ * @ingroup sft
+ */
+ int CountTTCFonts(const char* fname);
+
+
+/**
+ * TrueTypeFont constructor.
+ * Reads the font file and allocates the memory for the structure.
+ * @param facenum - logical font number within a TTC file. This value is ignored
+ * for TrueType fonts
+ * @return value of SFErrCodes enum
+ * @ingroup sft
+ */
+ int OpenTTFont(const char *fname, uint32 facenum, TrueTypeFont**);
+
+/**
+ * TrueTypeFont destructor. Deallocates the memory.
+ * @ingroup sft
+ */
+ void CloseTTFont(TrueTypeFont *);
+
+/**
+ * Extracts TrueType control points, and stores them in an allocated array pointed to
+ * by *pointArray. This function returns the number of extracted points.
+ *
+ * @param ttf pointer to the TrueTypeFont structure
+ * @param glyphID Glyph ID
+ * @param pointArray Return value - address of the pointer to the first element of the array
+ * of points allocated by the function
+ * @return Returns the number of points in *pointArray or -1 if glyphID is
+ * invalid.
+ * @ingroup sft
+ *
+ */
+ int GetTTGlyphPoints(TrueTypeFont *ttf, uint32 glyphID, ControlPoint **pointArray);
+
+/**
+ * Extracts raw glyph data from the 'glyf' table and returns it in an allocated
+ * GlyphData structure.
+ *
+ * @param ttf pointer to the TrueTypeFont structure
+ * @param glyphID Glyph ID
+ *
+ * @return pointer to an allocated GlyphData structure or NULL if
+ * glyphID is not present in the font
+ * @ingroup sft
+ *
+ */
+ GlyphData *GetTTRawGlyphData(TrueTypeFont *ttf, uint32 glyphID);
+
+#ifndef NO_LIST
+/**
+ * For a specified glyph adds all component glyphs IDs to the list and
+ * return their number. If the glyph is a single glyph it has one component
+ * glyph (which is added to the list) and the function returns 1.
+ * For a composite glyphs it returns the number of component glyphs
+ * and adds all of them to the list.
+ *
+ * @param ttf pointer to the TrueTypeFont structure
+ * @param glyphID Glyph ID
+ * @param glyphlist list of glyphs
+ *
+ * @return number of component glyphs
+ * @ingroup sft
+ *
+ */
+ int GetTTGlyphComponents(TrueTypeFont *ttf, uint32 glyphID, list glyphlist);
+#endif
+
+/**
+ * Extracts all Name Records from the font and stores them in an allocated
+ * array of NameRecord structs
+ *
+ * @param ttf pointer to the TrueTypeFont struct
+ * @param nr pointer to the array of NameRecord structs
+ *
+ * @return number of NameRecord structs
+ * @ingroup sft
+ */
+
+ int GetTTNameRecords(TrueTypeFont *ttf, NameRecord **nr);
+
+/**
+ * Deallocates previously allocated array of NameRecords.
+ *
+ * @param nr array of NameRecord structs
+ * @param n number of elements in the array
+ *
+ * @ingroup sft
+ */
+ void DisposeNameRecords(NameRecord* nr, int n);
+
+
+#ifndef NO_TYPE3
+/**
+ * Generates a new PostScript Type 3 font and dumps it to <b>outf</b> file.
+ * This functions subsititues glyph 0 for all glyphIDs that are not found in the font.
+ * @param ttf pointer to the TrueTypeFont structure
+ * @param outf the resulting font is written to this stream
+ * @param fname font name for the new font. If it is NULL the PostScript name of the
+ * original font will be used
+ * @param glyphArray pointer to an array of glyphs that are to be extracted from ttf
+ * @param encoding array of encoding values. encoding[i] specifies the position of the glyph
+ * glyphArray[i] in the encoding vector of the resulting Type3 font
+ * @param nGlyphs number of glyph IDs in glyphArray and encoding values in encoding
+ * @param wmode writing mode for the output file: 0 - horizontal, 1 - vertical
+ * @return return the value of SFErrCodes enum
+ * @see SFErrCodes
+ * @ingroup sft
+ *
+ */
+ int CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, uint16 *glyphArray, byte *encoding, int nGlyphs, int wmode);
+#endif
+
+#ifndef NO_TTCR
+/**
+ * Generates a new TrueType font and dumps it to <b>outf</b> file.
+ * This functions subsititues glyph 0 for all glyphIDs that are not found in the font.
+ * @param ttf pointer to the TrueTypeFont structure
+ * @param fname file name for the output TrueType font file
+ * @param glyphArray pointer to an array of glyphs that are to be extracted from ttf. The first
+ * element of this array has to be glyph 0 (default glyph)
+ * @param encoding array of encoding values. encoding[i] specifies character code for
+ * the glyphID glyphArray[i]. Character code 0 usually points to a default
+ * glyph (glyphID 0)
+ * @param nGlyphs number of glyph IDs in glyphArray and encoding values in encoding
+ * @param nNameRecs number of NameRecords for the font, if 0 the name table from the
+ * original font will be used
+ * @param nr array of NameRecords
+ * @param flags or'ed TTCreationFlags
+ * @return return the value of SFErrCodes enum
+ * @see SFErrCodes
+ * @ingroup sft
+ *
+ */
+ int CreateTTFromTTGlyphs(TrueTypeFont *ttf,
+ const char *fname,
+ uint16 *glyphArray,
+ byte *encoding,
+ int nGlyphs,
+ int nNameRecs,
+ NameRecord *nr,
+ uint32 flags);
+#endif
+
+#ifndef NO_TYPE42
+/**
+ * Generates a new PostScript Type42 font and dumps it to <b>outf</b> file.
+ * This functions subsititues glyph 0 for all glyphIDs that are not found in the font.
+ * @param ttf pointer to the TrueTypeFont structure
+ * @param outf output stream for a resulting font
+ * @param psname PostScript name of the resulting font
+ * @param glyphArray pointer to an array of glyphs that are to be extracted from ttf. The first
+ * element of this array has to be glyph 0 (default glyph)
+ * @param encoding array of encoding values. encoding[i] specifies character code for
+ * the glyphID glyphArray[i]. Character code 0 usually points to a default
+ * glyph (glyphID 0)
+ * @param nGlyphs number of glyph IDs in glyphArray and encoding values in encoding
+ * @return SF_OK - no errors
+ * SF_GLYPHNUM - too many glyphs (> 255)
+ * SF_TTFORMAT - corrupted TrueType fonts
+ *
+ * @see SFErrCodes
+ * @ingroup sft
+ *
+ */
+ int CreateT42FromTTGlyphs(TrueTypeFont *ttf,
+ FILE *outf,
+ const char *psname,
+ uint16 *glyphArray,
+ byte *encoding,
+ int nGlyphs);
+#endif
+
+
+/**
+ * Queries glyph metrics. Allocates an array of TTSimpleGlyphMetrics structs and returns it.
+ *
+ * @param ttf pointer to the TrueTypeFont structure
+ * @param glyphArray pointer to an array of glyphs that are to be extracted from ttf
+ * @param nGlyphs number of glyph IDs in glyphArray and encoding values in encoding
+ * @param mode writing mode: 0 - horizontal, 1 - vertical
+ * @ingroup sft
+ *
+ */
+ TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, uint16 *glyphArray, int nGlyphs, int mode);
+
+#ifndef NO_MAPPERS
+/**
+ * Queries glyph metrics. Allocates an array of TTSimpleGlyphMetrics structs and returns it.
+ * This function behaves just like GetTTSimpleGlyphMetrics() but it takes a range of Unicode
+ * characters instead of an array of glyphs.
+ *
+ * @param ttf pointer to the TrueTypeFont structure
+ * @param firstChar Unicode value of the first character in the range
+ * @param nChars number of Unicode characters in the range
+ * @param mode writing mode: 0 - horizontal, 1 - vertical
+ *
+ * @see GetTTSimpleGlyphMetrics
+ * @ingroup sft
+ *
+ */
+ TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont *ttf, uint16 firstChar, int nChars, int mode);
+
+/**
+ * Maps a Unicode (UCS-2) string to a glyph array. Returns the number of glyphs in the array,
+ * which for TrueType fonts is always the same as the number of input characters.
+ *
+ * @param ttf pointer to the TrueTypeFont structure
+ * @param str pointer to a UCS-2 string
+ * @param nchars number of characters in <b>str</b>
+ * @param glyphArray pointer to the glyph array where glyph IDs are to be recorded.
+ *
+ * @return MapString() returns -1 if the TrueType font has no usable 'cmap' tables.
+ * Otherwise it returns the number of characters processed: <b>nChars</b>
+ *
+ * glyphIDs of TrueType fonts are 2 byte positive numbers. glyphID of 0 denotes a missing
+ * glyph and traditionally defaults to an empty square.
+ * glyphArray should be at least sizeof(uint16) * nchars bytes long. If glyphArray is NULL
+ * MapString() replaces the UCS-2 characters in str with glyphIDs.
+ * @ingroup sft
+ */
+ int MapString(TrueTypeFont *ttf, uint16 *str, int nchars, uint16 *glyphArray, int bvertical);
+
+/**
+ * Maps a Unicode (UCS-2) character to a glyph ID and returns it. Missing glyph has
+ * a glyphID of 0 so this function can be used to test if a character is encoded in the font.
+ *
+ * @param ttf pointer to the TrueTypeFont structure
+ * @param ch Unicode (UCS-2) character
+ * @return glyph ID, if the character is missing in the font, the return value is 0.
+ * @ingroup sft
+ */
+ uint16 MapChar(TrueTypeFont *ttf, uint16 ch, int bvertical);
+#endif
+
+/**
+ * Returns global font information about the TrueType font.
+ * @see TTGlobalFontInfo
+ *
+ * @param ttf pointer to a TrueTypeFont structure
+ * @param info pointer to a TTGlobalFontInfo structure
+ * @ingroup sft
+ *
+ */
+ void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info);
+
+/**
+ * Returns kerning information for an array of glyphs.
+ * Kerning is not cumulative.
+ * kern[i] contains kerning information for a pair of glyphs at positions i and i+1
+ *
+ * @param ttf pointer to a TrueTypeFont structure
+ * @param glyphs array of source glyphs
+ * @param nglyphs number of glyphs in the array
+ * @param wmode writing mode: 0 - horizontal, 1 - vertical
+ * @param kern array of KernData structures. It should contain nglyphs-1 elements
+ * @see KernData
+ * @ingroup sft
+ *
+ */
+ void KernGlyphs(TrueTypeFont *ttf, uint16 *glyphs, int nglyphs, int wmode, KernData *kern);
+
+/**
+ * Returns nonzero if font is a symbol encoded font
+ */
+ int CheckSymbolEncoding(TrueTypeFont* ttf);
+
+/*- private definitions */ /*FOLD00*/
+
+ struct _TrueTypeFont {
+ uint32 tag;
+
+ char *fname;
+ off_t fsize;
+ byte *ptr;
+
+ char *psname;
+ char *family;
+ char *subfamily;
+
+ uint32 ntables;
+ uint32 *goffsets;
+ int nglyphs;
+ int unitsPerEm;
+ int numberOfHMetrics;
+ int numOfLongVerMetrics; /* if this number is not 0, font has vertical metrics information */
+ byte *cmap;
+ int cmapType;
+ uint16 (*mapper)(const byte *, uint16); /* character to glyphID translation function */
+ void **tables; /* array of pointers to tables */
+ uint32 *tlens; /* array of table lengths */
+ int kerntype; /* Defined in the KernType enum */
+ uint32 nkern; /* number of kern subtables */
+ byte **kerntables; /* array of pointers to kern subtables */
+ void *pGSubstitution; /* info provided by GSUB for UseGSUB() */
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SUBFONT_H */
diff --git a/psprint/source/fontsubset/ttcr.c b/psprint/source/fontsubset/ttcr.c
new file mode 100644
index 000000000000..4b09ff43e9a5
--- /dev/null
+++ b/psprint/source/fontsubset/ttcr.c
@@ -0,0 +1,1666 @@
+/*************************************************************************
+ *
+ * $RCSfile: ttcr.c,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Alexander Gelfenbain
+ *
+ *
+ ************************************************************************/
+
+/* $Id: ttcr.c,v 1.1.1.1 2001-05-08 11:45:38 pl Exp $ */
+
+/*
+ * TrueTypeCreator method implementation
+ *
+ * @author: Alexander Gelfenbain
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "ttcr.h"
+
+/* These must be #defined so that they can be used in initializers */
+#define T_maxp 0x6D617870
+#define T_glyf 0x676C7966
+#define T_head 0x68656164
+#define T_loca 0x6C6F6361
+#define T_name 0x6E616D65
+#define T_hhea 0x68686561
+#define T_hmtx 0x686D7478
+#define T_cmap 0x636D6170
+#define T_vhea 0x76686561
+#define T_vmtx 0x766D7478
+#define T_OS2 0x4F532F32
+#define T_post 0x706F7374
+#define T_kern 0x6B65726E
+#define T_cvt 0x63767420
+
+typedef struct {
+ uint32 tag;
+ uint32 length;
+ byte *data;
+} TableEntry;
+
+/*
+ * this is a duplicate code from sft.c but it is left here for performance reasons
+ */
+#ifdef __GNUC__
+#define _inline static __inline__
+#else
+#define _inline static
+#endif
+
+_inline uint32 mkTag(byte a, byte b, byte c, byte d) {
+ return (a << 24) | (b << 16) | (c << 8) | d;
+}
+
+/*- Data access macros for data stored in big-endian or little-endian format */
+_inline int16 GetInt16(const byte *ptr, size_t offset, int bigendian)
+{
+ int16 t;
+ assert(ptr != 0);
+
+ if (bigendian) {
+ t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
+ } else {
+ t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
+ }
+
+ return t;
+}
+
+_inline uint16 GetUInt16(const byte *ptr, size_t offset, int bigendian)
+{
+ uint16 t;
+ assert(ptr != 0);
+
+ if (bigendian) {
+ t = (ptr+offset)[0] << 8 | (ptr+offset)[1];
+ } else {
+ t = (ptr+offset)[1] << 8 | (ptr+offset)[0];
+ }
+
+ return t;
+}
+
+_inline int32 GetInt32(const byte *ptr, size_t offset, int bigendian)
+{
+ int32 t;
+ assert(ptr != 0);
+
+ if (bigendian) {
+ t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
+ (ptr+offset)[2] << 8 | (ptr+offset)[3];
+ } else {
+ t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
+ (ptr+offset)[1] << 8 | (ptr+offset)[0];
+ }
+
+ return t;
+}
+
+_inline uint32 GetUInt32(const byte *ptr, size_t offset, int bigendian)
+{
+ uint32 t;
+ assert(ptr != 0);
+
+
+ if (bigendian) {
+ t = (ptr+offset)[0] << 24 | (ptr+offset)[1] << 16 |
+ (ptr+offset)[2] << 8 | (ptr+offset)[3];
+ } else {
+ t = (ptr+offset)[3] << 24 | (ptr+offset)[2] << 16 |
+ (ptr+offset)[1] << 8 | (ptr+offset)[0];
+ }
+
+ return t;
+}
+
+
+_inline void PutInt16(int16 val, byte *ptr, size_t offset, int bigendian)
+{
+ assert(ptr != 0);
+
+ if (bigendian) {
+ ptr[offset] = (val >> 8) & 0xFF;
+ ptr[offset+1] = val & 0xFF;
+ } else {
+ ptr[offset+1] = (val >> 8) & 0xFF;
+ ptr[offset] = val & 0xFF;
+ }
+
+}
+
+_inline void PutUInt16(uint16 val, byte *ptr, size_t offset, int bigendian)
+{
+ assert(ptr != 0);
+
+ if (bigendian) {
+ ptr[offset] = (val >> 8) & 0xFF;
+ ptr[offset+1] = val & 0xFF;
+ } else {
+ ptr[offset+1] = (val >> 8) & 0xFF;
+ ptr[offset] = val & 0xFF;
+ }
+
+}
+
+
+_inline void PutUInt32(uint32 val, byte *ptr, size_t offset, int bigendian)
+{
+ assert(ptr != 0);
+
+ if (bigendian) {
+ ptr[offset] = (val >> 24) & 0xFF;
+ ptr[offset+1] = (val >> 16) & 0xFF;
+ ptr[offset+2] = (val >> 8) & 0xFF;
+ ptr[offset+3] = val & 0xFF;
+ } else {
+ ptr[offset+3] = (val >> 24) & 0xFF;
+ ptr[offset+2] = (val >> 16) & 0xFF;
+ ptr[offset+1] = (val >> 8) & 0xFF;
+ ptr[offset] = val & 0xFF;
+ }
+
+}
+
+
+_inline void PutInt32(int32 val, byte *ptr, size_t offset, int bigendian)
+{
+ assert(ptr != 0);
+
+ if (bigendian) {
+ ptr[offset] = (val >> 24) & 0xFF;
+ ptr[offset+1] = (val >> 16) & 0xFF;
+ ptr[offset+2] = (val >> 8) & 0xFF;
+ ptr[offset+3] = val & 0xFF;
+ } else {
+ ptr[offset+3] = (val >> 24) & 0xFF;
+ ptr[offset+2] = (val >> 16) & 0xFF;
+ ptr[offset+1] = (val >> 8) & 0xFF;
+ ptr[offset] = val & 0xFF;
+ }
+
+}
+
+static int TableEntryCompareF(const void *l, const void *r)
+{
+ return ((const TableEntry *) l)->tag - ((const TableEntry *) r)->tag;
+}
+
+static int NameRecordCompareF(const void *l, const void *r)
+{
+ NameRecord *ll = (NameRecord *) l;
+ NameRecord *rr = (NameRecord *) r;
+
+ if (ll->platformID != rr->platformID) {
+ return ll->platformID - rr->platformID;
+ } else if (ll->encodingID != rr->encodingID) {
+ return ll->encodingID - rr->encodingID;
+ } else if (ll->languageID != rr->languageID) {
+ return ll->languageID - rr->languageID;
+ } else if (ll->nameID != rr->nameID) {
+ return ll->nameID - rr->nameID;
+ }
+ return 0;
+}
+
+
+static uint32 CheckSum(uint32 *ptr, uint32 length)
+{
+ uint32 sum = 0;
+ uint32 *endptr = ptr + ((length + 3) & (uint32) ~3) / 4;
+
+ while (ptr < endptr) sum += *ptr++;
+
+ return sum;
+}
+
+_inline void *smalloc(size_t size)
+{
+ void *res = malloc(size);
+ assert(res != 0);
+ return res;
+}
+
+_inline void *scalloc(size_t n, size_t size)
+{
+ void *res = calloc(n, size);
+ assert(res != 0);
+ return res;
+}
+
+/*
+ * Public functions
+ */
+
+void TrueTypeCreatorNewEmpty(uint32 tag, TrueTypeCreator **_this)
+{
+ TrueTypeCreator *ptr = smalloc(sizeof(TrueTypeCreator));
+
+ ptr->tables = listNewEmpty();
+ listSetElementDtor(ptr->tables, TrueTypeTableDispose);
+
+ ptr->tag = tag;
+
+ *_this = ptr;
+}
+
+void TrueTypeCreatorDispose(TrueTypeCreator *_this)
+{
+ listDispose(_this->tables);
+ free(_this);
+}
+
+int AddTable(TrueTypeCreator *_this, TrueTypeTable *table)
+{
+ if (table != 0) {
+ listAppend(_this->tables, table);
+ }
+ return SF_OK;
+}
+
+void RemoveTable(TrueTypeCreator *_this, uint32 tag)
+{
+ int done = 0;
+
+ if (listCount(_this->tables)) {
+ listToFirst(_this->tables);
+ do {
+ if (((TrueTypeTable *) listCurrent(_this->tables))->tag == tag) {
+ listRemove(_this->tables);
+ } else {
+ if (listNext(_this->tables)) {
+ done = 1;
+ }
+ }
+ } while (!done);
+ }
+}
+
+static void ProcessTables(TrueTypeCreator *);
+
+int StreamToMemory(TrueTypeCreator *_this, byte **ptr, uint32 *length)
+{
+ uint16 numTables, searchRange=1, entrySelector=0, rangeShift;
+ uint32 s, offset, checkSumAdjustment = 0;
+ uint32 *p;
+ byte *ttf;
+ int i=0, n;
+ TableEntry *te;
+ byte *head; /* saved pointer to the head table data for checkSumAdjustment calculation */
+
+ if ((n = listCount(_this->tables)) == 0) return SF_TTFORMAT;
+
+ ProcessTables(_this);
+
+ /* ProcessTables() adds 'loca' and 'hmtx' */
+
+ n = listCount(_this->tables);
+ numTables = (uint16) n;
+
+
+ te = scalloc(n, sizeof(TableEntry));
+
+ listToFirst(_this->tables);
+ for (i = 0; i < n; i++) {
+ GetRawData((TrueTypeTable *) listCurrent(_this->tables), &te[i].data, &te[i].length, &te[i].tag);
+ listNext(_this->tables);
+ }
+
+ qsort(te, n, sizeof(TableEntry), TableEntryCompareF);
+
+ do {
+ searchRange *= 2;
+ entrySelector++;
+ } while (searchRange <= numTables);
+
+ searchRange *= 8;
+ entrySelector--;
+ rangeShift = numTables * 16 - searchRange;
+
+ s = offset = 12 + 16 * n;
+
+ for (i = 0; i < n; i++) {
+ s += (te[i].length + 3) & (uint32) ~3;
+ /* if ((te[i].length & 3) != 0) s += (4 - (te[i].length & 3)) & 3; */
+ }
+
+ ttf = smalloc(s);
+
+ /* Offset Table */
+ PutUInt32(_this->tag, ttf, 0, 1);
+ PutUInt16(numTables, ttf, 4, 1);
+ PutUInt16(searchRange, ttf, 6, 1);
+ PutUInt16(entrySelector, ttf, 8, 1);
+ PutUInt16(rangeShift, ttf, 10, 1);
+
+ /* Table Directory */
+ for (i = 0; i < n; i++) {
+ PutUInt32(te[i].tag, ttf + 12, 16 * i, 1);
+ PutUInt32(CheckSum((uint32 *) te[i].data, te[i].length), ttf + 12, 16 * i + 4, 1);
+ PutUInt32(offset, ttf + 12, 16 * i + 8, 1);
+ PutUInt32(te[i].length, ttf + 12, 16 * i + 12, 1);
+
+ if (te[i].tag == T_head) {
+ head = ttf + offset;
+ }
+
+ memcpy(ttf+offset, te[i].data, (te[i].length + 3) & (uint32) ~3 );
+ offset += (te[i].length + 3) & (uint32) ~3;
+ /* if ((te[i].length & 3) != 0) offset += (4 - (te[i].length & 3)) & 3; */
+ }
+
+ free(te);
+
+ p = (uint32 *) ttf;
+ for (i = 0; i < s / 4; i++) checkSumAdjustment += p[i];
+ PutUInt32(0xB1B0AFBA - checkSumAdjustment, head, 8, 1);
+
+ *ptr = ttf;
+ *length = s;
+
+ return SF_OK;
+}
+
+int StreamToFile(TrueTypeCreator *_this, const char* fname)
+{
+ byte *ptr;
+ uint32 length;
+ int fd, r;
+
+ if (!fname) return SF_BADFILE;
+ if ((fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) return SF_BADFILE;
+
+ if ((r = StreamToMemory(_this, &ptr, &length)) != SF_OK) return r;
+
+ if (write(fd, ptr, length) != length) {
+ r = SF_FILEIO;
+ } else {
+ r = SF_OK;
+ }
+
+ close(fd);
+ free(ptr);
+ return r;
+}
+
+
+
+/*
+ * TrueTypeTable private methods
+ */
+
+#define TABLESIZE_head 54
+#define TABLESIZE_hhea 36
+#define TABLESIZE_maxp 32
+
+
+
+/* Table data points to
+ * --------------------------------------------
+ * generic tdata_generic struct
+ * 'head' TABLESIZE_head bytes of memory
+ * 'hhea' TABLESIZE_hhea bytes of memory
+ * 'loca' tdata_loca struct
+ * 'maxp' TABLESIZE_maxp bytes of memory
+ * 'glyf' list of GlyphData structs (defined in sft.h)
+ * 'name' list of NameRecord structs (defined in sft.h)
+ * 'post' tdata_post struct
+ *
+ */
+
+
+#define CMAP_SUBTABLE_INIT 10
+#define CMAP_SUBTABLE_INCR 10
+#define CMAP_PAIR_INIT 500
+#define CMAP_PAIR_INCR 500
+
+typedef struct {
+ uint32 id; /* subtable ID (platform/encoding ID) */
+ uint32 n; /* number of used translation pairs */
+ uint32 m; /* number of allocated translation pairs */
+ uint32 *xc; /* character array */
+ uint32 *xg; /* glyph array */
+} CmapSubTable;
+
+typedef struct {
+ uint32 n; /* number of used CMAP sub-tables */
+ uint32 m; /* number of allocated CMAP sub-tables */
+ CmapSubTable *s; /* sotred array of sub-tables */
+} table_cmap;
+
+typedef struct {
+ uint32 tag;
+ uint32 nbytes;
+ byte *ptr;
+} tdata_generic;
+
+typedef struct {
+ uint32 nbytes; /* number of bytes in loca table */
+ byte *ptr; /* pointer to the data */
+} tdata_loca;
+
+typedef struct {
+ uint32 format;
+ uint32 italicAngle;
+ int16 underlinePosition;
+ int16 underlineThickness;
+ uint32 isFixedPitch;
+ void *ptr; /* format-specific pointer */
+} tdata_post;
+
+
+/* allocate memory for a TT table */
+static byte *ttmalloc(uint32 nbytes)
+{
+ uint32 n;
+ byte *res;
+
+ n = (nbytes + 3) & (uint32) ~3;
+ res = malloc(n);
+ assert(res != 0);
+ bzero(res, n);
+
+ return res;
+}
+
+static void FreeGlyphData(void *ptr)
+{
+ GlyphData *p = (GlyphData *) ptr;
+ if (p->ptr) free(p->ptr);
+ free(p);
+}
+
+static void TrueTypeTableDispose_generic(TrueTypeTable *_this)
+{
+ if (_this) {
+ if (_this->data) {
+ tdata_generic *pdata = (tdata_generic *) _this->data;
+ if (pdata->nbytes) free(pdata->ptr);
+ free(_this->data);
+ }
+ free(_this);
+ }
+}
+
+static void TrueTypeTableDispose_head(TrueTypeTable *_this)
+{
+ if (_this) {
+ if (_this->data) free(_this->data);
+ free(_this);
+ }
+}
+
+static void TrueTypeTableDispose_hhea(TrueTypeTable *_this)
+{
+ if (_this) {
+ if (_this->data) free(_this->data);
+ free(_this);
+ }
+}
+
+static void TrueTypeTableDispose_loca(TrueTypeTable *_this)
+{
+ if (_this) {
+ if (_this->data) {
+ tdata_loca *p = (tdata_loca *) _this->data;
+ if (p->ptr) free(p->ptr);
+ free(_this->data);
+ }
+ free(_this);
+ }
+}
+
+static void TrueTypeTableDispose_maxp(TrueTypeTable *_this)
+{
+ if (_this) {
+ if (_this->data) free(_this->data);
+ free(_this);
+ }
+}
+
+static void TrueTypeTableDispose_glyf(TrueTypeTable *_this)
+{
+ if (_this) {
+ if (_this->data) listDispose((list) _this->data);
+ free(_this);
+ }
+}
+
+static void TrueTypeTableDispose_cmap(TrueTypeTable *_this)
+{
+ table_cmap *t;
+ CmapSubTable *s;
+ int i;
+
+ if (_this) {
+ t = (table_cmap *) _this->data;
+ if (t) {
+ s = t->s;
+ if (s) {
+ for (i = 0; i < t->m; i++) {
+ if (s[i].xc) free(s[i].xc);
+ if (s[i].xg) free(s[i].xg);
+ }
+ free(s);
+ }
+ free(t);
+ }
+ free(_this);
+ }
+}
+
+static void TrueTypeTableDispose_name(TrueTypeTable *_this)
+{
+ if (_this) {
+ if (_this->data) listDispose((list) _this->data);
+ free(_this);
+ }
+}
+
+static void TrueTypeTableDispose_post(TrueTypeTable *_this)
+{
+ if (_this) {
+ tdata_post *p = (tdata_post *) _this->data;
+ if (p) {
+ if (p->format == 0x00030000) {
+ /* do nothing */
+ } else {
+ fprintf(stderr, "Unsupported format of a 'post' table: %08X.\n", p->format);
+ }
+ free(p);
+ }
+ free(_this);
+ }
+}
+
+/* destructor vtable */
+
+static struct {
+ uint32 tag;
+ void (*f)(TrueTypeTable *);
+} vtable1[] =
+{
+ {0, TrueTypeTableDispose_generic},
+ {T_head, TrueTypeTableDispose_head},
+ {T_hhea, TrueTypeTableDispose_hhea},
+ {T_loca, TrueTypeTableDispose_loca},
+ {T_maxp, TrueTypeTableDispose_maxp},
+ {T_glyf, TrueTypeTableDispose_glyf},
+ {T_cmap, TrueTypeTableDispose_cmap},
+ {T_name, TrueTypeTableDispose_name},
+ {T_post, TrueTypeTableDispose_post}
+
+};
+
+static int GetRawData_generic(TrueTypeTable *_this, byte **ptr, uint32 *len, uint32 *tag)
+{
+ assert(_this != 0);
+ assert(_this->data != 0);
+
+ *ptr = ((tdata_generic *) _this->data)->ptr;
+ *len = ((tdata_generic *) _this->data)->nbytes;
+ *tag = ((tdata_generic *) _this->data)->tag;
+
+ return TTCR_OK;
+}
+
+
+static int GetRawData_head(TrueTypeTable *_this, byte **ptr, uint32 *len, uint32 *tag)
+{
+ *len = TABLESIZE_head;
+ *ptr = (byte *) _this->data;
+ *tag = T_head;
+
+ return TTCR_OK;
+}
+
+static int GetRawData_hhea(TrueTypeTable *_this, byte **ptr, uint32 *len, uint32 *tag)
+{
+ *len = TABLESIZE_hhea;
+ *ptr = (byte *) _this->data;
+ *tag = T_hhea;
+
+ return TTCR_OK;
+}
+
+static int GetRawData_loca(TrueTypeTable *_this, byte **ptr, uint32 *len, uint32 *tag)
+{
+ tdata_loca *p;
+
+ assert(_this->data != 0);
+
+ p = (tdata_loca *) _this->data;
+
+ if (p->nbytes == 0) return TTCR_ZEROGLYPHS;
+
+ *ptr = p->ptr;
+ *len = p->nbytes;
+ *tag = T_loca;
+
+ return TTCR_OK;
+}
+
+static int GetRawData_maxp(TrueTypeTable *_this, byte **ptr, uint32 *len, uint32 *tag)
+{
+ *len = TABLESIZE_maxp;
+ *ptr = (byte *) _this->data;
+ *tag = T_maxp;
+
+ return TTCR_OK;
+}
+
+static int GetRawData_glyf(TrueTypeTable *_this, byte **ptr, uint32 *len, uint32 *tag)
+{
+ uint32 n, nbytes = 0;
+ list l = (list) _this->data;
+ /* uint16 curID = 0; */ /* to check if glyph IDs are sequential and start from zero */
+ byte *p;
+
+ *ptr = 0;
+ *len = 0;
+ *tag = 0;
+
+ if (listCount(l) == 0) return TTCR_ZEROGLYPHS;
+
+ listToFirst(l);
+ do {
+ /* if (((GlyphData *) listCurrent(l))->glyphID != curID++) return TTCR_GLYPHSEQ; */
+ nbytes += ((GlyphData *) listCurrent(l))->nbytes;
+ } while (listNext(l));
+
+ p = _this->rawdata = ttmalloc(nbytes);
+
+ listToFirst(l);
+ do {
+ n = ((GlyphData *) listCurrent(l))->nbytes;
+ if (n != 0) {
+ memcpy(p, ((GlyphData *) listCurrent(l))->ptr, n);
+ p += n;
+ }
+ } while (listNext(l));
+
+ *len = nbytes;
+ *ptr = _this->rawdata;
+ *tag = T_glyf;
+
+ return TTCR_OK;
+}
+
+/* cmap packers */
+static byte *PackCmapType0(CmapSubTable *s, uint32 *length)
+{
+ byte *ptr = smalloc(262);
+ byte *p = ptr + 6;
+ int i, j;
+ uint16 g;
+
+ PutUInt16(0, ptr, 0, 1);
+ PutUInt16(262, ptr, 2, 1);
+ PutUInt16(0, ptr, 4, 1);
+
+ for (i = 0; i < 256; i++) {
+ g = 0;
+ for (j = 0; j < s->n; j++) {
+ if (s->xc[j] == i) {
+ g = (uint16) s->xg[j];
+ }
+ }
+ p[i] = (byte) g;
+ }
+ *length = 262;
+ return ptr;
+}
+
+
+/* XXX it only handles Format 0 encoding tables */
+static byte *PackCmap(CmapSubTable *s, uint32 *length)
+{
+ return PackCmapType0(s, length);
+}
+
+static int GetRawData_cmap(TrueTypeTable *_this, byte **ptr, uint32 *len, uint32 *tag)
+{
+ table_cmap *t;
+ byte **subtables;
+ uint32 *sizes; /* of subtables */
+ int i;
+ uint32 tlen = 0;
+ uint32 l;
+ uint32 cmapsize;
+ byte *cmap;
+ uint32 coffset;
+
+ assert(_this != 0);
+ t = (table_cmap *) _this->data;
+ assert(t != 0);
+ assert(t->n != 0);
+
+ subtables = scalloc(t->n, sizeof(byte *));
+ sizes = scalloc(t->n, sizeof(uint32));
+
+ for (i = 0; i < t->n; i++) {
+ subtables[i] = PackCmap(t->s+i, &l);
+ sizes[i] = l;
+ tlen += l;
+ }
+
+ cmapsize = tlen + 4 + 8 * t->n;
+ _this->rawdata = cmap = ttmalloc(cmapsize);
+
+ PutUInt16(0, cmap, 0, 1);
+ PutUInt16(t->n, cmap, 2, 1);
+ coffset = 4 + t->n * 8;
+
+ for (i = 0; i < t->n; i++) {
+ PutUInt16(t->s[i].id >> 16, cmap + 4, i * 8, 1);
+ PutUInt16(t->s[i].id & 0xFF, cmap + 4, 2 + i * 8, 1);
+ PutUInt32(coffset, cmap + 4, 4 + i * 8, 1);
+ memcpy(cmap + coffset, subtables[i], sizes[i]);
+ free(subtables[i]);
+ coffset += sizes[i];
+ }
+
+ free(subtables);
+ free(sizes);
+
+ *ptr = cmap;
+ *len = cmapsize;
+ *tag = T_cmap;
+
+ return TTCR_OK;
+}
+
+
+static int GetRawData_name(TrueTypeTable *_this, byte **ptr, uint32 *len, uint32 *tag)
+{
+ list l;
+ NameRecord *nr;
+ int16 i=0, n; /* number of Name Records */
+ byte *name;
+ uint16 nameLen;
+ int stringLen = 0;
+ byte *p1, *p2;
+
+ *ptr = 0;
+ *len = 0;
+ *tag = 0;
+
+ assert(_this != 0);
+ l = (list) _this->data;
+ assert(l != 0);
+
+ if ((n = listCount(l)) == 0) return TTCR_NONAMES;
+
+ nr = scalloc(n, sizeof(NameRecord));
+
+ listToFirst(l);
+
+ do {
+ memcpy(nr+i, listCurrent(l), sizeof(NameRecord));
+ stringLen += nr[i].slen;
+ i++;
+ } while (listNext(l));
+
+ if (stringLen > 65535) {
+ free(nr);
+ return TTCR_NAMETOOLONG;
+ }
+
+ qsort(nr, n, sizeof(NameRecord), NameRecordCompareF);
+
+ nameLen = stringLen + 12 * n + 6;
+ name = ttmalloc(nameLen);
+
+ PutUInt16(0, name, 0, 1);
+ PutUInt16(n, name, 2, 1);
+ PutUInt16(6 + 12 * n, name, 4, 1);
+
+ p1 = name + 6;
+ p2 = p1 + 12 * n;
+
+ for (i = 0; i < n; i++) {
+ PutUInt16(nr[i].platformID, p1, 0, 1);
+ PutUInt16(nr[i].encodingID, p1, 2, 1);
+ PutUInt16(nr[i].languageID, p1, 4, 1);
+ PutUInt16(nr[i].nameID, p1, 6, 1);
+ PutUInt16(nr[i].slen, p1, 8, 1);
+ PutUInt16(p2 - (name + 6 + 12 * n), p1, 10, 1);
+ memcpy(p2, nr[i].sptr, nr[i].slen);
+ /* {int j; for(j=0; j<nr[i].slen; j++) printf("%c", nr[i].sptr[j]); printf("\n"); }; */
+ p2 += nr[i].slen;
+ p1 += 12;
+ }
+
+ free(nr);
+ _this->rawdata = name;
+
+ *ptr = name;
+ *len = nameLen;
+ *tag = T_name;
+
+ /*{int j; for(j=0; j<nameLen; j++) printf("%c", name[j]); }; */
+
+ return TTCR_OK;
+}
+
+static int GetRawData_post(TrueTypeTable *_this, byte **ptr, uint32 *len, uint32 *tag)
+{
+ tdata_post *p = (tdata_post *) _this->data;
+ byte *post = 0;
+ uint32 postLen = 0;
+ int ret;
+
+ if (_this->rawdata) free(_this->rawdata);
+
+ if (p->format == 0x00030000) {
+ postLen = 32;
+ post = ttmalloc(postLen);
+ PutUInt32(0x00030000, post, 0, 1);
+ PutUInt32(p->italicAngle, post, 4, 1);
+ PutUInt16(p->underlinePosition, post, 8, 1);
+ PutUInt16(p->underlineThickness, post, 10, 1);
+ PutUInt16(p->isFixedPitch, post, 12, 1);
+ ret = TTCR_OK;
+ } else {
+ fprintf(stderr, "Unrecognized format of a post table: %08X.\n", p->format);
+ ret = TTCR_POSTFORMAT;
+ }
+
+ *ptr = _this->rawdata = post;
+ *len = postLen;
+ *tag = T_post;
+
+ return ret;
+}
+
+
+
+
+
+static struct {
+ uint32 tag;
+ int (*f)(TrueTypeTable *, byte **, uint32 *, uint32 *);
+} vtable2[] =
+{
+ {0, GetRawData_generic},
+ {T_head, GetRawData_head},
+ {T_hhea, GetRawData_hhea},
+ {T_loca, GetRawData_loca},
+ {T_maxp, GetRawData_maxp},
+ {T_glyf, GetRawData_glyf},
+ {T_cmap, GetRawData_cmap},
+ {T_name, GetRawData_name},
+ {T_post, GetRawData_post}
+
+
+};
+
+/*
+ * TrueTypeTable public methods
+ */
+
+/* Note: Type42 fonts only need these tables:
+ * head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm
+ *
+ * Microsoft required tables
+ * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post, OS/2
+ *
+ * Apple required tables
+ * cmap, glyf, head, hhea, hmtx, loca, maxp, name, post
+ *
+ */
+
+TrueTypeTable *TrueTypeTableNew(uint32 tag,
+ uint32 nbytes,
+ byte *ptr)
+{
+ TrueTypeTable *table;
+ tdata_generic *pdata;
+
+ table = smalloc(sizeof(TrueTypeTable));
+ pdata = (tdata_generic *) smalloc(sizeof(tdata_generic));
+ pdata->nbytes = nbytes;
+ pdata->tag = tag;
+ if (nbytes) {
+ pdata->ptr = ttmalloc(nbytes);
+ memcpy(pdata->ptr, ptr, nbytes);
+ } else {
+ pdata->ptr = 0;
+ }
+
+ table->tag = 0;
+ table->data = pdata;
+ table->rawdata = 0;
+
+ return table;
+}
+
+TrueTypeTable *TrueTypeTableNew_head(uint32 fontRevision,
+ uint16 flags,
+ uint16 unitsPerEm,
+ byte *created,
+ uint16 macStyle,
+ uint16 lowestRecPPEM,
+ int16 fontDirectionHint)
+{
+ TrueTypeTable *table;
+ byte *ptr;
+
+ assert(created != 0);
+
+ table = smalloc(sizeof(TrueTypeTable));
+ ptr = ttmalloc(TABLESIZE_head);
+
+
+ PutUInt32(0x00010000, ptr, 0, 1); /* version */
+ PutUInt32(fontRevision, ptr, 4, 1);
+ PutUInt32(0x5F0F3CF5, ptr, 12, 1); /* magic number */
+ PutUInt16(flags, ptr, 16, 1);
+ PutUInt16(unitsPerEm, ptr, 18, 1);
+ memcpy(ptr+20, created, 8); /* Created Long Date */
+ bzero(ptr+28, 8); /* Modified Long Date */
+ PutUInt16(macStyle, ptr, 44, 1);
+ PutUInt16(lowestRecPPEM, ptr, 46, 1);
+ PutUInt16(fontDirectionHint, ptr, 48, 1);
+ PutUInt16(0, ptr, 52, 1); /* glyph data format: 0 */
+
+ table->data = (void *) ptr;
+ table->tag = T_head;
+ table->rawdata = 0;
+
+ return table;
+}
+
+TrueTypeTable *TrueTypeTableNew_hhea(int16 ascender,
+ int16 descender,
+ int16 linegap,
+ int16 caretSlopeRise,
+ int16 caretSlopeRun)
+{
+ TrueTypeTable *table;
+ byte *ptr;
+
+ table = smalloc(sizeof(TrueTypeTable));
+ ptr = ttmalloc(TABLESIZE_hhea);
+
+ PutUInt32(0x00010000, ptr, 0, 1); /* version */
+ PutUInt16(ascender, ptr, 4, 1);
+ PutUInt16(descender, ptr, 6, 1);
+ PutUInt16(linegap, ptr, 8, 1);
+ PutUInt16(caretSlopeRise, ptr, 18, 1);
+ PutUInt16(caretSlopeRun, ptr, 20, 1);
+ PutUInt16(0, ptr, 22, 1); /* reserved 1 */
+ PutUInt16(0, ptr, 24, 1); /* reserved 2 */
+ PutUInt16(0, ptr, 26, 1); /* reserved 3 */
+ PutUInt16(0, ptr, 28, 1); /* reserved 4 */
+ PutUInt16(0, ptr, 30, 1); /* reserved 5 */
+ PutUInt16(0, ptr, 32, 1); /* metricDataFormat */
+
+ table->data = (void *) ptr;
+ table->tag = T_hhea;
+ table->rawdata = 0;
+
+ return table;
+}
+
+TrueTypeTable *TrueTypeTableNew_loca(void)
+{
+ TrueTypeTable *table = smalloc(sizeof(TrueTypeTable));
+ table->data = smalloc(sizeof(tdata_loca));
+
+ ((tdata_loca *)table->data)->nbytes = 0;
+ ((tdata_loca *)table->data)->ptr = 0;
+
+ table->tag = T_loca;
+ table->rawdata = 0;
+
+ return table;
+}
+
+TrueTypeTable *TrueTypeTableNew_maxp(byte *maxp, int size)
+{
+ TrueTypeTable *table = smalloc(sizeof(TrueTypeTable));
+ table->data = ttmalloc(TABLESIZE_maxp);
+
+ if (maxp && size == TABLESIZE_maxp) {
+ memcpy(table->data, maxp, TABLESIZE_maxp);
+ }
+
+ table->tag = T_maxp;
+ table->rawdata = 0;
+
+ return table;
+}
+
+TrueTypeTable *TrueTypeTableNew_glyf(void)
+{
+ TrueTypeTable *table = smalloc(sizeof(TrueTypeTable));
+ list l = listNewEmpty();
+
+ assert(l != 0);
+
+ listSetElementDtor(l, FreeGlyphData);
+
+ table->data = l;
+ table->rawdata = 0;
+ table->tag = T_glyf;
+
+ return table;
+}
+
+TrueTypeTable *TrueTypeTableNew_cmap(void)
+{
+ TrueTypeTable *table = smalloc(sizeof(TrueTypeTable));
+ table_cmap *cmap = smalloc(sizeof(table_cmap));
+
+ cmap->n = 0;
+ cmap->m = CMAP_SUBTABLE_INIT;
+ cmap->s = (CmapSubTable *) scalloc(CMAP_SUBTABLE_INIT, sizeof(CmapSubTable));
+ memset(cmap->s, 0, sizeof(CmapSubTable) * CMAP_SUBTABLE_INIT);
+
+ table->data = (table_cmap *) cmap;
+
+ table->rawdata = 0;
+ table->tag = T_cmap;
+
+ return table;
+}
+
+static void DisposeNameRecord(void *ptr)
+{
+ if (ptr != 0) {
+ NameRecord *nr = (NameRecord *) ptr;
+ if (nr->sptr) free(nr->sptr);
+ free(ptr);
+ }
+}
+
+static NameRecord* NameRecordNewCopy(NameRecord *nr)
+{
+ NameRecord *p = smalloc(sizeof(NameRecord));
+
+ memcpy(p, nr, sizeof(NameRecord));
+
+ if (p->slen) {
+ p->sptr = smalloc(p->slen);
+ memcpy(p->sptr, nr->sptr, p->slen);
+ }
+
+ return p;
+}
+
+TrueTypeTable *TrueTypeTableNew_name(int n, NameRecord *nr)
+{
+ TrueTypeTable *table = smalloc(sizeof(TrueTypeTable));
+ list l = listNewEmpty();
+
+ assert(l != 0);
+
+ listSetElementDtor(l, DisposeNameRecord);
+
+ if (n != 0) {
+ int i;
+ for (i = 0; i < n; i++) {
+ listAppend(l, NameRecordNewCopy(nr+i));
+ }
+ }
+
+ table->data = l;
+ table->rawdata = 0;
+ table->tag = T_name;
+
+ return table;
+}
+
+TrueTypeTable *TrueTypeTableNew_post(uint32 format,
+ uint32 italicAngle,
+ int16 underlinePosition,
+ int16 underlineThickness,
+ uint32 isFixedPitch)
+{
+ TrueTypeTable *table;
+ tdata_post *post;
+
+ assert(format == 0x00030000); /* Only format 3.0 is supported at this time */
+ table = smalloc(sizeof(TrueTypeTable));
+ post = smalloc(sizeof(tdata_post));
+
+ post->format = format;
+ post->italicAngle = italicAngle;
+ post->underlinePosition = underlinePosition;
+ post->underlineThickness = underlineThickness;
+ post->isFixedPitch = isFixedPitch;
+ post->ptr = 0;
+
+ table->data = post;
+ table->rawdata = 0;
+ table->tag = T_post;
+
+ return table;
+}
+
+
+
+void TrueTypeTableDispose(TrueTypeTable *_this)
+{
+ /* XXX do a binary search */
+ int i;
+
+ assert(_this != 0);
+
+ if (_this->rawdata) free(_this->rawdata);
+
+ for(i=0; i < sizeof(vtable1)/sizeof(*vtable1); i++) {
+ if (_this->tag == vtable1[i].tag) {
+ vtable1[i].f(_this);
+ return;
+ }
+ }
+ assert(!"Unknown TrueType table.\n");
+}
+
+int GetRawData(TrueTypeTable *_this, byte **ptr, uint32 *len, uint32 *tag)
+{
+ /* XXX do a binary search */
+ int i;
+
+ assert(_this != 0);
+ assert(ptr != 0);
+ assert(len != 0);
+ assert(tag != 0);
+
+ *ptr = 0; *len = 0; *tag = 0;
+
+ if (_this->rawdata) {
+ free(_this->rawdata);
+ _this->rawdata = 0;
+ }
+
+ for(i=0; i < sizeof(vtable2)/sizeof(*vtable2); i++) {
+ if (_this->tag == vtable2[i].tag) {
+ return vtable2[i].f(_this, ptr, len, tag);
+ }
+ }
+
+ assert(!"Unknwon TrueType table.\n");
+ return TTCR_UNKNOWN;
+}
+
+void cmapAdd(TrueTypeTable *table, uint32 id, uint32 c, uint32 g)
+{
+ int i, found;
+ table_cmap *t;
+ CmapSubTable *s;
+
+ assert(table != 0);
+ assert(table->tag == T_cmap);
+ t = (table_cmap *) table->data; assert(t != 0);
+ s = t->s; assert(s != 0);
+
+ found = 0;
+
+ for (i = 0; i < t->n; i++) {
+ if (s[i].id == id) {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ if (t->n == t->m) {
+ CmapSubTable *tmp;
+ tmp = scalloc(t->m + CMAP_SUBTABLE_INCR, sizeof(CmapSubTable));
+ memset(tmp, 0, t->m + CMAP_SUBTABLE_INCR * sizeof(CmapSubTable));
+ memcpy(tmp, s, sizeof(CmapSubTable) * t->m);
+ t->m += CMAP_SUBTABLE_INCR;
+ free(s);
+ s = tmp;
+ t->s = s;
+ }
+
+ for (i = 0; i < t->n; i++) {
+ if (s[i].id > id) break;
+ }
+
+ if (i < t->n) {
+ memmove(s+i+1, s+i, t->n-i);
+ }
+
+ t->n++;
+
+ s[i].id = id;
+ s[i].n = 0;
+ s[i].m = CMAP_PAIR_INIT;
+ s[i].xc = scalloc(CMAP_PAIR_INIT, sizeof(uint32));
+ s[i].xg = scalloc(CMAP_PAIR_INIT, sizeof(uint32));
+ }
+
+ if (s[i].n == s[i].m) {
+ uint32 *tmp1 = scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(uint32));
+ uint32 *tmp2 = scalloc(s[i].m + CMAP_PAIR_INCR, sizeof(uint32));
+ assert(tmp1 != 0);
+ assert(tmp2 != 0);
+ memcpy(tmp1, s[i].xc, sizeof(uint32) * s[i].m);
+ memcpy(tmp2, s[i].xg, sizeof(uint32) * s[i].m);
+ s[i].m += CMAP_PAIR_INCR;
+ free(s[i].xc);
+ free(s[i].xg);
+ s[i].xc = tmp1;
+ s[i].xg = tmp2;
+ }
+
+ s[i].xc[s[i].n] = c;
+ s[i].xg[s[i].n] = g;
+ s[i].n++;
+}
+
+uint32 glyfAdd(TrueTypeTable *table, GlyphData *glyphdata, TrueTypeFont *fnt)
+{
+ list l;
+ uint32 currentID;
+ int ret, n, ncomponents;
+ list glyphlist;
+ GlyphData *gd;
+
+ assert(table != 0);
+ assert(table->tag == T_glyf);
+
+ if (!glyphdata) return -1;
+
+ glyphlist = listNewEmpty();
+
+ ncomponents = GetTTGlyphComponents(fnt, glyphdata->glyphID, glyphlist);
+
+ l = (list) table->data;
+ if (listCount(l) > 0) {
+ listToLast(l);
+ ret = n = ((GlyphData *) listCurrent(l))->newID + 1;
+ } else {
+ ret = n = 0;
+ }
+ glyphdata->newID = n++;
+ listAppend(l, glyphdata);
+
+ if (ncomponents > 1) {
+ listPositionAt(glyphlist, 1); /* glyphData->glyphID is always the first glyph on the list */
+ do {
+ int found = 0;
+ currentID = (uint32) listCurrent(glyphlist);
+ /* XXX expensive! should be rewritten with sorted arrays! */
+ listToFirst(l);
+ do {
+ if (((GlyphData *) listCurrent(l))->glyphID == currentID) {
+ found = 1;
+ break;
+ }
+ } while (listNext(l));
+
+ if (!found) {
+ gd = GetTTRawGlyphData(fnt, currentID);
+ gd->newID = n++;
+ listAppend(l, gd);
+ }
+ } while (listNext(glyphlist));
+ }
+
+ listDispose(glyphlist);
+ return ret;
+}
+
+uint32 glyfCount(const TrueTypeTable *table)
+{
+ assert(table != 0);
+ assert(table->tag == T_glyf);
+ return listCount((list) table->data);
+}
+
+
+void nameAdd(TrueTypeTable *table, NameRecord *nr)
+{
+ list l;
+
+ assert(table != 0);
+ assert(table->tag == T_name);
+
+ l = (list) table->data;
+
+ listAppend(l, NameRecordNewCopy(nr));
+}
+
+static TrueTypeTable *FindTable(TrueTypeCreator *tt, uint32 tag)
+{
+ if (listIsEmpty(tt->tables)) return 0;
+
+ listToFirst(tt->tables);
+
+ do {
+ if (((TrueTypeTable *) listCurrent(tt->tables))->tag == tag) {
+ return listCurrent(tt->tables);
+ }
+ } while (listNext(tt->tables));
+
+ return 0;
+}
+
+/* This function processes all the tables and synchronizes them before creating
+ * the output TrueType stream.
+ *
+ * *** It adds two TrueType tables to the font: 'loca' and 'hmtx' ***
+ *
+ * It does:
+ *
+ * - Re-numbers glyph IDs and creates 'glyf', 'loca', and 'hmtx' tables.
+ * - Calculates xMin, yMin, xMax, and yMax and stores values in 'head' table.
+ * - Stores indexToLocFormat in 'head'
+ * - updates 'maxp' table
+ * - Calculates advanceWidthMax, minLSB, minRSB, xMaxExtent and numberOfHMetrics
+ * in 'hhea' table
+ *
+ */
+static void ProcessTables(TrueTypeCreator *tt)
+{
+ TrueTypeTable *glyf, *loca, *head, *maxp, *hhea;
+ list glyphlist;
+ uint32 nGlyphs, locaLen = 0, glyfLen = 0;
+ int16 xMin = 0, yMin = 0, xMax = 0, yMax = 0;
+ int i = 0;
+ int16 indexToLocFormat;
+ byte *glyfPtr, *locaPtr, *hmtxPtr, *hheaPtr;
+ uint32 hmtxSize;
+ byte *p1, *p2;
+ uint16 maxPoints = 0, maxContours = 0, maxCompositePoints = 0, maxCompositeContours = 0;
+ TTSimpleGlyphMetrics *met;
+ int nlsb = 0;
+ uint32 *gid; /* array of old glyphIDs */
+
+ glyf = FindTable(tt, T_glyf);
+ glyphlist = (list) glyf->data;
+ nGlyphs = listCount(glyphlist);
+ assert(nGlyphs != 0);
+ gid = scalloc(nGlyphs, sizeof(uint32));
+
+ RemoveTable(tt, T_loca);
+ RemoveTable(tt, T_hmtx);
+
+ /* XXX Need to make sure that composite glyphs do not break during glyph renumbering */
+
+ listToFirst(glyphlist);
+ do {
+ GlyphData *gd = (GlyphData *) listCurrent(glyphlist);
+ int16 z;
+ glyfLen += gd->nbytes;
+ /* XXX if (gd->nbytes & 1) glyfLen++; */
+
+
+ assert(gd->newID == i);
+ gid[i++] = gd->glyphID;
+ /* gd->glyphID = i++; */
+
+ /* printf("IDs: %d %d.\n", gd->glyphID, gd->newID); */
+
+ if (gd->nbytes != 0) {
+ z = GetInt16(gd->ptr, 2, 1);
+ if (z < xMin) xMin = z;
+
+ z = GetInt16(gd->ptr, 4, 1);
+ if (z < yMin) yMin = z;
+
+ z = GetInt16(gd->ptr, 6, 1);
+ if (z > xMax) xMax = z;
+
+ z = GetInt16(gd->ptr, 8, 1);
+ if (z > yMax) yMax = z;
+ }
+
+ if (gd->compflag == 0) { /* non-composite glyph */
+ if (gd->npoints > maxPoints) maxPoints = gd->npoints;
+ if (gd->ncontours > maxContours) maxContours = gd->ncontours;
+ } else { /* composite glyph */
+ if (gd->npoints > maxCompositePoints) maxCompositePoints = gd->npoints;
+ if (gd->ncontours > maxCompositeContours) maxCompositeContours = gd->ncontours;
+ }
+
+ } while (listNext(glyphlist));
+
+ indexToLocFormat = (glyfLen / 2 > 0xFFFF) ? 1 : 0;
+ locaLen = indexToLocFormat ? (nGlyphs + 1) << 2 : (nGlyphs + 1) << 1;
+
+ glyfPtr = ttmalloc(glyfLen);
+ locaPtr = ttmalloc(locaLen);
+ met = scalloc(nGlyphs, sizeof(TTSimpleGlyphMetrics));
+ i = 0;
+
+ listToFirst(glyphlist);
+ p1 = glyfPtr;
+ p2 = locaPtr;
+ do {
+ GlyphData *gd = (GlyphData *) listCurrent(glyphlist);
+
+ if (gd->compflag) { /* re-number all components */
+ uint16 flags, index;
+ byte *ptr = gd->ptr + 10;
+ do {
+ int j;
+ flags = GetUInt16(ptr, 0, 1);
+ index = GetUInt16(ptr, 2, 1);
+ /* XXX use the sorted array of old to new glyphID mapping and do a binary search */
+ for (j = 0; j < nGlyphs; j++) {
+ if (gid[j] == index) {
+ break;
+ }
+ }
+ /* printf("X: %d -> %d.\n", index, j); */
+
+ PutUInt16((uint16) j, ptr, 2, 1);
+
+ ptr += 4;
+
+ if (flags & ARG_1_AND_2_ARE_WORDS) {
+ ptr += 4;
+ } else {
+ ptr += 2;
+ }
+
+ if (flags & WE_HAVE_A_SCALE) {
+ ptr += 2;
+ } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) {
+ ptr += 4;
+ } else if (flags & WE_HAVE_A_TWO_BY_TWO) {
+ ptr += 8;
+ }
+ } while (flags & MORE_COMPONENTS);
+ }
+
+ if (gd->nbytes != 0) {
+ memcpy(p1, gd->ptr, gd->nbytes);
+ }
+ if (indexToLocFormat == 1) {
+ PutUInt32(p1 - glyfPtr, p2, 0, 1);
+ p2 += 4;
+ } else {
+ PutUInt16((p1 - glyfPtr) >> 1, p2, 0, 1);
+ p2 += 2;
+ }
+ p1 += gd->nbytes;
+
+ /* fill the array of metrics */
+ met[i].adv = gd->aw;
+ met[i].sb = gd->lsb;
+ i++;
+ } while (listNext(glyphlist));
+
+ free(gid);
+
+ if (indexToLocFormat == 1) {
+ PutUInt32(p1 - glyfPtr, p2, 0, 1);
+ } else {
+ PutUInt16((p1 - glyfPtr) >> 1, p2, 0, 1);
+ }
+
+ glyf->rawdata = glyfPtr;
+
+ loca = TrueTypeTableNew_loca(); assert(loca != 0);
+ ((tdata_loca *) loca->data)->ptr = locaPtr;
+ ((tdata_loca *) loca->data)->nbytes = locaLen;
+
+ AddTable(tt, loca);
+
+ head = FindTable(tt, T_head);
+ PutInt16(xMin, head->data, 36, 1);
+ PutInt16(yMin, head->data, 38, 1);
+ PutInt16(xMax, head->data, 40, 1);
+ PutInt16(yMax, head->data, 42, 1);
+ PutInt16(indexToLocFormat, head->data, 50, 1);
+
+ maxp = FindTable(tt, T_maxp);
+
+ PutUInt16(nGlyphs, maxp->data, 4, 1);
+ PutUInt16(maxPoints, maxp->data, 6, 1);
+ PutUInt16(maxContours, maxp->data, 8, 1);
+ PutUInt16(maxCompositePoints, maxp->data, 10, 1);
+ PutUInt16(maxCompositeContours, maxp->data, 12, 1);
+
+#if 0
+ /* XXX do not overwrite the existing data. Fix: re-calculate these numbers here */
+ PutUInt16(2, maxp->data, 14, 1); /* maxZones is always 2 */
+ PutUInt16(0, maxp->data, 16, 1); /* maxTwilightPoints */
+ PutUInt16(0, maxp->data, 18, 1); /* maxStorage */
+ PutUInt16(0, maxp->data, 20, 1); /* maxFunctionDefs */
+ PutUint16(0, maxp->data, 22, 1); /* maxInstructionDefs */
+ PutUint16(0, maxp->data, 24, 1); /* maxStackElements */
+ PutUint16(0, maxp->data, 26, 1); /* maxSizeOfInstructions */
+ PutUint16(0, maxp->data, 28, 1); /* maxComponentElements */
+ PutUint16(0, maxp->data, 30, 1); /* maxComponentDepth */
+#endif
+
+ /*
+ * Generate an htmx table and update hhea table
+ */
+ hhea = FindTable(tt, T_hhea); assert(hhea != 0);
+ hheaPtr = (byte *) hhea->data;
+ if (nGlyphs > 2) {
+ for (i = nGlyphs - 1; i > 0; i--) {
+ if (met[i].adv != met[i-1].adv) break;
+ }
+ nlsb = nGlyphs - 1 - i;
+ }
+ hmtxSize = (nGlyphs - nlsb) * 4 + nlsb * 2;
+ hmtxPtr = ttmalloc(hmtxSize);
+ p1 = hmtxPtr;
+
+ for (i = 0; i < nGlyphs; i++) {
+ if (i < nGlyphs - nlsb) {
+ PutUInt16(met[i].adv, p1, 0, 1);
+ PutUInt16(met[i].sb, p1, 2, 1);
+ p1 += 4;
+ } else {
+ PutUInt16(met[i].sb, p1, 0, 1);
+ p1 += 2;
+ }
+ }
+
+ AddTable(tt, TrueTypeTableNew(T_hmtx, hmtxSize, hmtxPtr));
+ PutUInt16(nGlyphs - nlsb, hheaPtr, 34, 1);
+ free(hmtxPtr);
+ free(met);
+}
+
+#ifdef TEST_TTCR
+int main(void)
+{
+ TrueTypeCreator *ttcr;
+ byte *t1, *t2, *t3, *t4, *t5, *t6, *t7;
+
+ TrueTypeCreatorNewEmpty(mkTag('t','r','u','e'), &ttcr);
+
+ t1 = malloc(1000); memset(t1, 'a', 1000);
+ t2 = malloc(2000); memset(t2, 'b', 2000);
+ t3 = malloc(3000); memset(t3, 'c', 3000);
+ t4 = malloc(4000); memset(t4, 'd', 4000);
+ t5 = malloc(5000); memset(t5, 'e', 5000);
+ t6 = malloc(6000); memset(t6, 'f', 6000);
+ t7 = malloc(7000); memset(t7, 'g', 7000);
+
+ AddTable(ttcr, TrueTypeTableNew(0x6D617870, 1000, t1));
+ AddTable(ttcr, TrueTypeTableNew(0x4F532F32, 2000, t2));
+ AddTable(ttcr, TrueTypeTableNew(0x636D6170, 3000, t3));
+ AddTable(ttcr, TrueTypeTableNew(0x6C6F6361, 4000, t4));
+ AddTable(ttcr, TrueTypeTableNew(0x68686561, 5000, t5));
+ AddTable(ttcr, TrueTypeTableNew(0x676C7966, 6000, t6));
+ AddTable(ttcr, TrueTypeTableNew(0x6B65726E, 7000, t7));
+
+ free(t1);
+ free(t2);
+ free(t3);
+ free(t4);
+ free(t5);
+ free(t6);
+ free(t7);
+
+
+ StreamToFile(ttcr, "ttcrout.ttf");
+
+ TrueTypeCreatorDispose(ttcr);
+ return 0;
+}
+#endif
diff --git a/psprint/source/fontsubset/ttcr.h b/psprint/source/fontsubset/ttcr.h
new file mode 100644
index 000000000000..414b035cbe19
--- /dev/null
+++ b/psprint/source/fontsubset/ttcr.h
@@ -0,0 +1,311 @@
+/*************************************************************************
+ *
+ * $RCSfile: ttcr.h,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:38 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Alexander Gelfenbain
+ *
+ *
+ ************************************************************************/
+
+/* $Id: ttcr.h,v 1.1.1.1 2001-05-08 11:45:38 pl Exp $ */
+
+/**
+ *
+ * @file ttcr.h
+ * @brief TrueType font creator
+ * @author Alexander Gelfenbain
+ */
+
+#ifndef __TTCR_H
+#define __TTCR_H
+
+#include "sft.h"
+#include "list.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ typedef struct _TrueTypeCreator TrueTypeCreator;
+
+/* TrueType data types */
+ typedef struct {
+ uint16 aw;
+ int16 lsb;
+ } longHorMetrics;
+
+/* A generic base class for all TrueType tables */
+ typedef struct {
+ uint32 tag; /* table tag */
+ byte *rawdata; /* raw data allocated by GetRawData_*() */
+ void *data; /* table specific data */
+ } TrueTypeTable;
+
+/** Error codes for most functions */
+ enum TTCRErrCodes {
+ TTCR_OK = 0, /**< no error */
+ TTCR_ZEROGLYPHS = 1, /**< At least one glyph should be defined */
+ TTCR_UNKNOWN = 2, /**< Unknown TrueType table */
+ TTCR_GLYPHSEQ = 3, /**< Glyph IDs are not sequential in the glyf table */
+ TTCR_NONAMES = 4, /**< 'name' table does not contain any names */
+ TTCR_NAMETOOLONG = 5, /**< 'name' table is too long (string data > 64K) */
+ TTCR_POSTFORMAT = 6 /**< unsupported format of a 'post' table */
+ };
+
+/* ============================================================================
+ *
+ * TrueTypeCreator methods
+ *
+ * ============================================================================ */
+
+/**
+ * TrueTypeCreator constructor.
+ * Allocates all internal structures.
+ */
+ void TrueTypeCreatorNewEmpty(uint32 tag, TrueTypeCreator **_this);
+
+/**
+ * TrueTypeCreator destructor. It calls destructors for all TrueTypeTables added to it.
+ */
+ void TrueTypeCreatorDispose(TrueTypeCreator *_this);
+
+/**
+ * Adds a TrueType table to the TrueType creator.
+ * SF_TABLEFORMAT value.
+ * @return value of SFErrCodes type
+ */
+ int AddTable(TrueTypeCreator *_this, TrueTypeTable *table);
+
+/**
+ * Removes a TrueType table from the TrueType creator if it is stored there.
+ * It also calls a TrueTypeTable destructor.
+ * Note: all generic tables (with tag 0) will be removed if this function is
+ * called with the second argument of 0.
+ * @return value of SFErrCodes type
+ */
+ void RemoveTable(TrueTypeCreator *_this, uint32 tag);
+
+
+
+/**
+ * Writes a TrueType font generated by the TrueTypeCreator to a segment of
+ * memory that this method allocates. When it is not needed anymore the caller
+ * is supposed to call free() on it.
+ * @return value of SFErrCodes type
+ */
+ int StreamToMemory(TrueTypeCreator *_this, byte **ptr, uint32 *length);
+
+/**
+ * Writes a TrueType font generated by the TrueTypeCreator to a file
+ * @return value of SFErrCodes type
+ */
+ int StreamToFile(TrueTypeCreator *_this, const char* fname);
+
+
+/* ============================================================================
+ *
+ * TrueTypeTable methods
+ *
+ * ============================================================================ */
+
+/**
+ * Destructor for the TrueTypeTable object.
+ */
+ void TrueTypeTableDispose(TrueTypeTable *);
+
+/**
+ * This function converts the data of a TrueType table to a raw array of bytes.
+ * It may allocates the memory for it and returns the size of the raw data in bytes.
+ * If memory is allocated it does not need to be freed by the caller of this function,
+ * since the pointer to it is stored in the TrueTypeTable and it is freed by the destructor
+ * @return TTCRErrCode
+ *
+ */
+
+ int GetRawData(TrueTypeTable *, byte **ptr, uint32 *len, uint32 *tag);
+
+/**
+ *
+ * Creates a new raw TrueType table. The difference between this constructor and
+ * TrueTypeTableNew_tag constructors is that the latter create structured tables
+ * while this constructor just copies memory pointed to by ptr to its buffer
+ * and stores its length. This constructor is suitable for data that is not
+ * supposed to be processed in any way, just written to the resulting TTF file.
+ */
+ TrueTypeTable *TrueTypeTableNew(uint32 tag,
+ uint32 nbytes,
+ byte *ptr);
+
+/**
+ * Creates a new 'head' table for a TrueType font.
+ * Allocates memory for it. Since a lot of values in the 'head' table depend on the
+ * rest of the tables in the TrueType font this table should be the last one added
+ * to the font.
+ */
+ TrueTypeTable *TrueTypeTableNew_head(uint32 fontRevision,
+ uint16 flags,
+ uint16 unitsPerEm,
+ byte *created,
+ uint16 macStyle,
+ uint16 lowestRecPPEM,
+ int16 fontDirectionHint);
+
+/**
+ * Creates a new 'hhea' table for a TrueType font.
+ * Allocates memory for it and stores it in the hhea pointer.
+ */
+ TrueTypeTable *TrueTypeTableNew_hhea(int16 ascender,
+ int16 descender,
+ int16 linegap,
+ int16 caretSlopeRise,
+ int16 caretSlopeRun);
+
+/**
+ * Creates a new empty 'loca' table for a TrueType font.
+ *
+ * INTERNAL: gets called only from ProcessTables();
+ */
+ TrueTypeTable *TrueTypeTableNew_loca(void);
+
+/**
+ * Creates a new 'maxp' table based on an existing maxp table.
+ * If maxp is 0, a new empty maxp table is created
+ * size specifies the size of existing maxp table for
+ * error-checking purposes
+ */
+ TrueTypeTable *TrueTypeTableNew_maxp(byte *maxp, int size);
+
+/**
+ * Creates a new empty 'glyf' table.
+ */
+ TrueTypeTable *TrueTypeTableNew_glyf(void);
+
+/**
+ * Creates a new empty 'cmap' table.
+ */
+ TrueTypeTable *TrueTypeTableNew_cmap(void);
+
+/**
+ * Creates a new 'name' table. If n != 0 the table gets populated by
+ * the Name Records stored in the nr array. This function allocates
+ * memory for its own copy of NameRecords, so nr array has to
+ * be explicitly deallocated when it is not needed.
+ */
+ TrueTypeTable *TrueTypeTableNew_name(int n, NameRecord *nr);
+
+/**
+ * Creates a new 'post' table of one of the supported formats
+ */
+ TrueTypeTable *TrueTypeTableNew_post(uint32 format,
+ uint32 italicAngle,
+ int16 underlinePosition,
+ int16 underlineThickness,
+ uint32 isFixedPitch);
+
+
+/*------------------------------------------------------------------------------
+ *
+ * Table manipulation functions
+ *
+ *------------------------------------------------------------------------------*/
+
+
+/**
+ * Add a character/glyph pair to a cmap table
+ */
+ void cmapAdd(TrueTypeTable *, uint32 id, uint32 c, uint32 g);
+
+/**
+ * Add a glyph to a glyf table.
+ *
+ * @return glyphID of the glyph in the new font
+ *
+ * NOTE: This function does not duplicate GlyphData, so memory will be
+ * deallocated in the table destructor
+ */
+ uint32 glyfAdd(TrueTypeTable *, GlyphData *glyphdata, TrueTypeFont *fnt);
+
+/**
+ * Query the number of glyphs currently stored in the 'glyf' table
+ *
+ */
+ uint32 glyfCount(const TrueTypeTable *);
+
+/**
+ * Add a Name Record to a name table.
+ * NOTE: This function duplicates NameRecord, so the argument
+ * has to be deallocated by the caller (unlike glyfAdd)
+ */
+ void nameAdd(TrueTypeTable *, NameRecord *nr);
+
+
+
+/*
+ * Private Data Types
+ */
+
+ struct _TrueTypeCreator {
+ uint32 tag; /**< TrueType file tag */
+ list tables; /**< List of table tags and pointers */
+ };
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __TTCR_H */
diff --git a/psprint/source/fontsubset/u2big5.inc b/psprint/source/fontsubset/u2big5.inc
new file mode 100644
index 000000000000..a81b6e3a5c67
--- /dev/null
+++ b/psprint/source/fontsubset/u2big5.inc
@@ -0,0 +1,1788 @@
+/*************************************************************************
+ *
+ * $RCSfile: u2big5.inc,v $
+ *
+ * $Revision: 1.1.1.1 $
+ *
+ * last change: $Author: pl $ $Date: 2001-05-08 11:45:42 $
+ *
+ * The Contents of this file are made available subject to the terms of
+ * either of the following licenses
+ *
+ * - GNU Lesser General Public License Version 2.1
+ * - Sun Industry Standards Source License Version 1.1
+ *
+ * Sun Microsystems Inc., October, 2000
+ *
+ * GNU Lesser General Public License Version 2.1
+ * =============================================
+ * Copyright 2000 by Sun Microsystems, Inc.
+ * 901 San Antonio Road, Palo Alto, CA 94303, USA
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License version 2.1, as published by the Free Software Foundation.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ *
+ *
+ * Sun Industry Standards Source License Version 1.1
+ * =================================================
+ * The contents of this file are subject to the Sun Industry Standards
+ * Source License Version 1.1 (the "License"); You may not use this file
+ * except in compliance with the License. You may obtain a copy of the
+ * License at http://www.openoffice.org/license.html.
+ *
+ * Software provided under this License is provided on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
+ * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
+ * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
+ * See the License for the specific provisions governing your rights and
+ * obligations concerning the Software.
+ *
+ * The Initial Developer of the Original Code is: Sun Microsystems, Inc.
+ *
+ * Copyright: 2000 by Sun Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Contributor(s): Alexander Gelfenbain
+ *
+ *
+ ************************************************************************/
+
+uint16pair xlat_1_3[13798] = {
+ {0x0020, 0x0020},{0x0021, 0x0021},{0x0022, 0x0022},{0x0023, 0x0023},{0x0024, 0x0024},{0x0025, 0x0025},{0x0026, 0x0026},{0x0027, 0x0027},
+ {0x0028, 0x0028},{0x0029, 0x0029},{0x002A, 0x002A},{0x002B, 0x002B},{0x002C, 0x002C},{0x002D, 0x002D},{0x002E, 0x002E},{0x002F, 0x002F},
+ {0x0030, 0x0030},{0x0031, 0x0031},{0x0032, 0x0032},{0x0033, 0x0033},{0x0034, 0x0034},{0x0035, 0x0035},{0x0036, 0x0036},{0x0037, 0x0037},
+ {0x0038, 0x0038},{0x0039, 0x0039},{0x003A, 0x003A},{0x003B, 0x003B},{0x003C, 0x003C},{0x003D, 0x003D},{0x003E, 0x003E},{0x003F, 0x003F},
+ {0x0040, 0x0040},{0x0041, 0x0041},{0x0042, 0x0042},{0x0043, 0x0043},{0x0044, 0x0044},{0x0045, 0x0045},{0x0046, 0x0046},{0x0047, 0x0047},
+ {0x0048, 0x0048},{0x0049, 0x0049},{0x004A, 0x004A},{0x004B, 0x004B},{0x004C, 0x004C},{0x004D, 0x004D},{0x004E, 0x004E},{0x004F, 0x004F},
+ {0x0050, 0x0050},{0x0051, 0x0051},{0x0052, 0x0052},{0x0053, 0x0053},{0x0054, 0x0054},{0x0055, 0x0055},{0x0056, 0x0056},{0x0057, 0x0057},
+ {0x0058, 0x0058},{0x0059, 0x0059},{0x005A, 0x005A},{0x005B, 0x005B},{0x005C, 0x005C},{0x005D, 0x005D},{0x005E, 0x005E},{0x005F, 0x005F},
+ {0x0060, 0x0060},{0x0061, 0x0061},{0x0062, 0x0062},{0x0063, 0x0063},{0x0064, 0x0064},{0x0065, 0x0065},{0x0066, 0x0066},{0x0067, 0x0067},
+ {0x0068, 0x0068},{0x0069, 0x0069},{0x006A, 0x006A},{0x006B, 0x006B},{0x006C, 0x006C},{0x006D, 0x006D},{0x006E, 0x006E},{0x006F, 0x006F},
+ {0x0070, 0x0070},{0x0071, 0x0071},{0x0072, 0x0072},{0x0073, 0x0073},{0x0074, 0x0074},{0x0075, 0x0075},{0x0076, 0x0076},{0x0077, 0x0077},
+ {0x0078, 0x0078},{0x0079, 0x0079},{0x007A, 0x007A},{0x007B, 0x007B},{0x007C, 0x007C},{0x007D, 0x007D},{0x007E, 0x007E},{0x00A2, 0xA246},
+ {0x00A3, 0xA247},{0x00A5, 0xA244},{0x00A7, 0xA1B1},{0x00B0, 0xA258},{0x00B1, 0xA1D3},{0x00B7, 0xA150},{0x00D7, 0xA1D1},{0x00F7, 0xA1D2},
+ {0x02C7, 0xA3BE},{0x02C9, 0xA3BC},{0x02CA, 0xA3BD},{0x02CB, 0xA3BF},{0x02D9, 0xA3BB},{0x0391, 0xA344},{0x0392, 0xA345},{0x0393, 0xA346},
+ {0x0394, 0xA347},{0x0395, 0xA348},{0x0396, 0xA349},{0x0397, 0xA34A},{0x0398, 0xA34B},{0x0399, 0xA34C},{0x039A, 0xA34D},{0x039B, 0xA34E},
+ {0x039C, 0xA34F},{0x039D, 0xA350},{0x039E, 0xA351},{0x039F, 0xA352},{0x03A0, 0xA353},{0x03A1, 0xA354},{0x03A3, 0xA355},{0x03A4, 0xA356},
+ {0x03A5, 0xA357},{0x03A6, 0xA358},{0x03A7, 0xA359},{0x03A8, 0xA35A},{0x03A9, 0xA35B},{0x03B1, 0xA35C},{0x03B2, 0xA35D},{0x03B3, 0xA35E},
+ {0x03B4, 0xA35F},{0x03B5, 0xA360},{0x03B6, 0xA361},{0x03B7, 0xA362},{0x03B8, 0xA363},{0x03B9, 0xA364},{0x03BA, 0xA365},{0x03BB, 0xA366},
+ {0x03BC, 0xA367},{0x03BD, 0xA368},{0x03BE, 0xA369},{0x03BF, 0xA36A},{0x03C0, 0xA36B},{0x03C1, 0xA36C},{0x03C3, 0xA36D},{0x03C4, 0xA36E},
+ {0x03C5, 0xA36F},{0x03C6, 0xA370},{0x03C7, 0xA371},{0x03C8, 0xA372},{0x03C9, 0xA373},{0x0401, 0xC7B3},{0x0414, 0xC7B1},{0x0415, 0xC7B2},
+ {0x0416, 0xC7B4},{0x0417, 0xC7B5},{0x0418, 0xC7B6},{0x0419, 0xC7B7},{0x041A, 0xC7B8},{0x041B, 0xC7B9},{0x041C, 0xC7BA},{0x0423, 0xC7BB},
+ {0x0424, 0xC7BC},{0x0425, 0xC7BD},{0x0426, 0xC7BE},{0x0427, 0xC7BF},{0x0428, 0xC7C0},{0x0429, 0xC7C1},{0x042A, 0xC7C2},{0x042B, 0xC7C3},
+ {0x042C, 0xC7C4},{0x042D, 0xC7C5},{0x042E, 0xC7C6},{0x042F, 0xC7C7},{0x0430, 0xC7C8},{0x0431, 0xC7C9},{0x0432, 0xC7CA},{0x0433, 0xC7CB},
+ {0x0434, 0xC7CC},{0x0435, 0xC7CD},{0x0436, 0xC7CF},{0x0437, 0xC7D0},{0x0438, 0xC7D1},{0x0439, 0xC7D2},{0x043A, 0xC7D3},{0x043B, 0xC7D4},
+ {0x043C, 0xC7D5},{0x043D, 0xC7D6},{0x043E, 0xC7D7},{0x043F, 0xC7D8},{0x0440, 0xC7D9},{0x0441, 0xC7DA},{0x0442, 0xC7DB},{0x0443, 0xC7DC},
+ {0x0444, 0xC7DD},{0x0445, 0xC7DE},{0x0446, 0xC7DF},{0x0447, 0xC7E0},{0x0448, 0xC7E1},{0x0449, 0xC7E2},{0x044A, 0xC7E3},{0x044B, 0xC7E4},
+ {0x044C, 0xC7E5},{0x044D, 0xC7E6},{0x044E, 0xC7E7},{0x044F, 0xC7E8},{0x0451, 0xC7CE},{0x2013, 0xA156},{0x2014, 0xA158},{0x2018, 0xA1A5},
+ {0x2019, 0xA1A6},{0x201C, 0xA1A7},{0x201D, 0xA1A8},{0x2022, 0xA145},{0x2025, 0xA14C},{0x2026, 0xA14B},{0x2032, 0xA1AC},{0x2035, 0xA1AB},
+ {0x203B, 0xA1B0},{0x203E, 0xA1C2},{0x2103, 0xA24A},{0x2105, 0xA1C1},{0x2109, 0xA24B},{0x2160, 0xA2B9},{0x2161, 0xA2BA},{0x2162, 0xA2BB},
+ {0x2163, 0xA2BC},{0x2164, 0xA2BD},{0x2165, 0xA2BE},{0x2166, 0xA2BF},{0x2167, 0xA2C0},{0x2168, 0xA2C1},{0x2169, 0xA2C2},{0x2190, 0xA1F6},
+ {0x2191, 0xA1F4},{0x2192, 0xA1F7},{0x2193, 0xA1F5},{0x2196, 0xA1F8},{0x2197, 0xA1F9},{0x2198, 0xA1FB},{0x2199, 0xA1FA},{0x221A, 0xA1D4},
+ {0x221E, 0xA1DB},{0x221F, 0xA1E8},{0x2220, 0xA1E7},{0x2223, 0xA1FD},{0x2225, 0xA1FC},{0x2229, 0xA1E4},{0x222A, 0xA1E5},{0x222B, 0xA1EC},
+ {0x222E, 0xA1ED},{0x2234, 0xA1EF},{0x2235, 0xA1EE},{0x223C, 0xA1E3},{0x2252, 0xA1DC},{0x2260, 0xA1DA},{0x2261, 0xA1DD},{0x2266, 0xA1D8},
+ {0x2267, 0xA1D9},{0x22A5, 0xA1E6},{0x22BF, 0xA1E9},{0x2460, 0xC7E9},{0x2461, 0xC7EA},{0x2462, 0xC7EB},{0x2463, 0xC7EC},{0x2464, 0xC7ED},
+ {0x2465, 0xC7EE},{0x2466, 0xC7EF},{0x2467, 0xC7F0},{0x2468, 0xC7F1},{0x2469, 0xC7F2},{0x2474, 0xC7F3},{0x2475, 0xC7F4},{0x2476, 0xC7F5},
+ {0x2477, 0xC7F6},{0x2478, 0xC7F7},{0x2479, 0xC7F8},{0x247A, 0xC7F9},{0x247B, 0xC7FA},{0x247C, 0xC7FB},{0x247D, 0xC7FC},{0x2500, 0xA277},
+ {0x2502, 0xA278},{0x250C, 0xA27A},{0x2510, 0xA27B},{0x2514, 0xA27C},{0x2518, 0xA27D},{0x251C, 0xA275},{0x2524, 0xA274},{0x252C, 0xA273},
+ {0x2534, 0xA272},{0x253C, 0xA271},{0x2550, 0xA2A4},{0x255E, 0xA2A5},{0x2561, 0xA2A7},{0x256A, 0xA2A6},{0x256D, 0xA27E},{0x256E, 0xA2A1},
+ {0x256F, 0xA2A3},{0x2570, 0xA2A2},{0x2571, 0xA2AC},{0x2572, 0xA2AD},{0x2573, 0xA2AE},{0x2581, 0xA262},{0x2582, 0xA263},{0x2583, 0xA264},
+ {0x2584, 0xA265},{0x2585, 0xA266},{0x2586, 0xA267},{0x2587, 0xA268},{0x2588, 0xA269},{0x2589, 0xA270},{0x258A, 0xA26F},{0x258B, 0xA26E},
+ {0x258C, 0xA26D},{0x258D, 0xA26C},{0x258E, 0xA26B},{0x258F, 0xA26A},{0x2594, 0xA276},{0x2595, 0xA279},{0x25A0, 0xA1BD},{0x25A1, 0xA1BC},
+ {0x25B2, 0xA1B6},{0x25B3, 0xA1B5},{0x25BC, 0xA1BF},{0x25BD, 0xA1BE},{0x25C6, 0xA1BB},{0x25C7, 0xA1BA},{0x25CB, 0xA1B3},{0x25CE, 0xA1B7},
+ {0x25CF, 0xA1B4},{0x25E2, 0xA2A8},{0x25E3, 0xA2A9},{0x25E4, 0xA2AB},{0x25E5, 0xA2AA},{0x2605, 0xA1B9},{0x2606, 0xA1B8},{0x2609, 0xA1F3},
+ {0x2640, 0xA1F0},{0x2641, 0xA1F2},{0x2642, 0xA1F1},{0x3000, 0xA140},{0x3001, 0xA142},{0x3002, 0xA143},{0x3003, 0xA1B2},{0x3005, 0xC6A4},
+ {0x3008, 0xA171},{0x3009, 0xA172},{0x300A, 0xA16D},{0x300B, 0xA16E},{0x300C, 0xA175},{0x300D, 0xA176},{0x300E, 0xA179},{0x300F, 0xA17A},
+ {0x3010, 0xA169},{0x3011, 0xA16A},{0x3012, 0xA245},{0x3014, 0xA165},{0x3015, 0xA166},{0x301D, 0xA1A9},{0x301E, 0xA1AA},{0x3021, 0xA2C3},
+ {0x3022, 0xA2C4},{0x3023, 0xA2C5},{0x3024, 0xA2C6},{0x3025, 0xA2C7},{0x3026, 0xA2C8},{0x3027, 0xA2C9},{0x3028, 0xA2CA},{0x3029, 0xA2CB},
+ {0x3041, 0xC6A5},{0x3042, 0xC6A6},{0x3043, 0xC6A7},{0x3044, 0xC6A8},{0x3045, 0xC6A9},{0x3046, 0xC6AA},{0x3047, 0xC6AB},{0x3048, 0xC6AC},
+ {0x3049, 0xC6AD},{0x304A, 0xC6AE},{0x304B, 0xC6AF},{0x304C, 0xC6B0},{0x304D, 0xC6B1},{0x304E, 0xC6B2},{0x304F, 0xC6B3},{0x3050, 0xC6B4},
+ {0x3051, 0xC6B5},{0x3052, 0xC6B6},{0x3053, 0xC6B7},{0x3054, 0xC6B8},{0x3055, 0xC6B9},{0x3056, 0xC6BA},{0x3057, 0xC6BB},{0x3058, 0xC6BC},
+ {0x3059, 0xC6BD},{0x305A, 0xC6BE},{0x305B, 0xC6BF},{0x305C, 0xC6C0},{0x305D, 0xC6C1},{0x305E, 0xC6C2},{0x305F, 0xC6C3},{0x3060, 0xC6C4},
+ {0x3061, 0xC6C5},{0x3062, 0xC6C6},{0x3063, 0xC6C7},{0x3064, 0xC6C8},{0x3065, 0xC6C9},{0x3066, 0xC6CA},{0x3067, 0xC6CB},{0x3068, 0xC6CC},
+ {0x3069, 0xC6CD},{0x306A, 0xC6CE},{0x306B, 0xC6CF},{0x306C, 0xC6D0},{0x306D, 0xC6D1},{0x306E, 0xC6D2},{0x306F, 0xC6D3},{0x3070, 0xC6D4},
+ {0x3071, 0xC6D5},{0x3072, 0xC6D6},{0x3073, 0xC6D7},{0x3074, 0xC6D8},{0x3075, 0xC6D9},{0x3076, 0xC6DA},{0x3077, 0xC6DB},{0x3078, 0xC6DC},
+ {0x3079, 0xC6DD},{0x307A, 0xC6DE},{0x307B, 0xC6DF},{0x307C, 0xC6E0},{0x307D, 0xC6E1},{0x307E, 0xC6E2},{0x307F, 0xC6E3},{0x3080, 0xC6E4},
+ {0x3081, 0xC6E5},{0x3082, 0xC6E6},{0x3083, 0xC6E7},{0x3084, 0xC6E8},{0x3085, 0xC6E9},{0x3086, 0xC6EA},{0x3087, 0xC6EB},{0x3088, 0xC6EC},
+ {0x3089, 0xC6ED},{0x308A, 0xC6EE},{0x308B, 0xC6EF},{0x308C, 0xC6F0},{0x308D, 0xC6F1},{0x308E, 0xC6F2},{0x308F, 0xC6F3},{0x3090, 0xC6F4},
+ {0x3091, 0xC6F5},{0x3092, 0xC6F6},{0x3093, 0xC6F7},{0x309D, 0xC6A2},{0x309E, 0xC6A3},{0x30A1, 0xC6F8},{0x30A2, 0xC6F9},{0x30A3, 0xC6FA},
+ {0x30A4, 0xC6FB},{0x30A5, 0xC6FC},{0x30A6, 0xC6FD},{0x30A7, 0xC6FE},{0x30A8, 0xC740},{0x30A9, 0xC741},{0x30AA, 0xC742},{0x30AB, 0xC743},
+ {0x30AC, 0xC744},{0x30AD, 0xC745},{0x30AE, 0xC746},{0x30AF, 0xC747},{0x30B0, 0xC748},{0x30B1, 0xC749},{0x30B2, 0xC74A},{0x30B3, 0xC74B},
+ {0x30B4, 0xC74C},{0x30B5, 0xC74D},{0x30B6, 0xC74E},{0x30B7, 0xC74F},{0x30B8, 0xC750},{0x30B9, 0xC751},{0x30BA, 0xC752},{0x30BB, 0xC753},
+ {0x30BC, 0xC754},{0x30BD, 0xC755},{0x30BE, 0xC756},{0x30BF, 0xC757},{0x30C0, 0xC758},{0x30C1, 0xC759},{0x30C2, 0xC75A},{0x30C3, 0xC75B},
+ {0x30C4, 0xC75C},{0x30C5, 0xC75D},{0x30C6, 0xC75E},{0x30C7, 0xC75F},{0x30C8, 0xC760},{0x30C9, 0xC761},{0x30CA, 0xC762},{0x30CB, 0xC763},
+ {0x30CC, 0xC764},{0x30CD, 0xC765},{0x30CE, 0xC766},{0x30CF, 0xC767},{0x30D0, 0xC768},{0x30D1, 0xC769},{0x30D2, 0xC76A},{0x30D3, 0xC76B},
+ {0x30D4, 0xC76C},{0x30D5, 0xC76D},{0x30D6, 0xC76E},{0x30D7, 0xC76F},{0x30D8, 0xC770},{0x30D9, 0xC771},{0x30DA, 0xC772},{0x30DB, 0xC773},
+ {0x30DC, 0xC774},{0x30DD, 0xC775},{0x30DE, 0xC776},{0x30DF, 0xC777},{0x30E0, 0xC778},{0x30E1, 0xC779},{0x30E2, 0xC77A},{0x30E3, 0xC77B},
+ {0x30E4, 0xC77C},{0x30E5, 0xC77D},{0x30E6, 0xC77E},{0x30E7, 0xC7A1},{0x30E8, 0xC7A2},{0x30E9, 0xC7A3},{0x30EA, 0xC7A4},{0x30EB, 0xC7A5},
+ {0x30EC, 0xC7A6},{0x30ED, 0xC7A7},{0x30EE, 0xC7A8},{0x30EF, 0xC7A9},{0x30F0, 0xC7AA},{0x30F1, 0xC7AB},{0x30F2, 0xC7AC},{0x30F3, 0xC7AD},
+ {0x30F4, 0xC7AE},{0x30F5, 0xC7AF},{0x30F6, 0xC7B0},{0x30FE, 0xC6A1},{0x3105, 0xA374},{0x3106, 0xA375},{0x3107, 0xA376},{0x3108, 0xA377},
+ {0x3109, 0xA378},{0x310A, 0xA379},{0x310B, 0xA37A},{0x310C, 0xA37B},{0x310D, 0xA37C},{0x310E, 0xA37D},{0x310F, 0xA37E},{0x3110, 0xA3A1},
+ {0x3111, 0xA3A2},{0x3112, 0xA3A3},{0x3113, 0xA3A4},{0x3114, 0xA3A5},{0x3115, 0xA3A6},{0x3116, 0xA3A7},{0x3117, 0xA3A8},{0x3118, 0xA3A9},
+ {0x3119, 0xA3AA},{0x311A, 0xA3AB},{0x311B, 0xA3AC},{0x311C, 0xA3AD},{0x311D, 0xA3AE},{0x311E, 0xA3AF},{0x311F, 0xA3B0},{0x3120, 0xA3B1},
+ {0x3121, 0xA3B2},{0x3122, 0xA3B3},{0x3123, 0xA3B4},{0x3124, 0xA3B5},{0x3125, 0xA3B6},{0x3126, 0xA3B7},{0x3127, 0xA3B8},{0x3128, 0xA3B9},
+ {0x3129, 0xA3BA},{0x32A3, 0xA1C0},{0x338E, 0xA255},{0x338F, 0xA256},{0x339C, 0xA250},{0x339D, 0xA251},{0x339E, 0xA252},{0x33A1, 0xA254},
+ {0x33C4, 0xA257},{0x33CE, 0xA253},{0x33D1, 0xA1EB},{0x33D2, 0xA1EA},{0x33D5, 0xA24F},{0x4E00, 0xA440},{0x4E01, 0xA442},{0x4E03, 0xA443},
+ {0x4E07, 0xC945},{0x4E08, 0xA456},{0x4E09, 0xA454},{0x4E0A, 0xA457},{0x4E0B, 0xA455},{0x4E0C, 0xC946},{0x4E0D, 0xA4A3},{0x4E0E, 0xC94F},
+ {0x4E0F, 0xC94D},{0x4E10, 0xA4A2},{0x4E11, 0xA4A1},{0x4E14, 0xA542},{0x4E15, 0xA541},{0x4E16, 0xA540},{0x4E18, 0xA543},{0x4E19, 0xA4FE},
+ {0x4E1E, 0xA5E0},{0x4E1F, 0xA5E1},{0x4E26, 0xA8C3},{0x4E2B, 0xA458},{0x4E2D, 0xA4A4},{0x4E2E, 0xC950},{0x4E30, 0xA4A5},{0x4E31, 0xC963},
+ {0x4E32, 0xA6EA},{0x4E33, 0xCBB1},{0x4E38, 0xA459},{0x4E39, 0xA4A6},{0x4E3B, 0xA544},{0x4E3C, 0xC964},{0x4E42, 0xC940},{0x4E43, 0xA444},
+ {0x4E45, 0xA45B},{0x4E47, 0xC947},{0x4E48, 0xA45C},{0x4E4B, 0xA4A7},{0x4E4D, 0xA545},{0x4E4E, 0xA547},{0x4E4F, 0xA546},{0x4E52, 0xA5E2},
+ {0x4E53, 0xA5E3},{0x4E56, 0xA8C4},{0x4E58, 0xADBC},{0x4E59, 0xA441},{0x4E5C, 0xC941},{0x4E5D, 0xA445},{0x4E5E, 0xA45E},{0x4E5F, 0xA45D},
+ {0x4E69, 0xA5E4},{0x4E73, 0xA8C5},{0x4E7E, 0xB0AE},{0x4E7F, 0xD44B},{0x4E82, 0xB6C3},{0x4E83, 0xDCB1},{0x4E84, 0xDCB2},{0x4E86, 0xA446},
+ {0x4E88, 0xA4A9},{0x4E8B, 0xA8C6},{0x4E8C, 0xA447},{0x4E8D, 0xC948},{0x4E8E, 0xA45F},{0x4E91, 0xA4AA},{0x4E92, 0xA4AC},{0x4E93, 0xC951},
+ {0x4E94, 0xA4AD},{0x4E95, 0xA4AB},{0x4E99, 0xA5E5},{0x4E9B, 0xA8C7},{0x4E9E, 0xA8C8},{0x4E9F, 0xAB45},{0x4EA1, 0xA460},{0x4EA2, 0xA4AE},
+ {0x4EA4, 0xA5E6},{0x4EA5, 0xA5E8},{0x4EA6, 0xA5E7},{0x4EA8, 0xA6EB},{0x4EAB, 0xA8C9},{0x4EAC, 0xA8CA},{0x4EAD, 0xAB46},{0x4EAE, 0xAB47},
+ {0x4EB3, 0xADBD},{0x4EB6, 0xDCB3},{0x4EB9, 0xF6D6},{0x4EBA, 0xA448},{0x4EC0, 0xA4B0},{0x4EC1, 0xA4AF},{0x4EC2, 0xC952},{0x4EC3, 0xA4B1},
+ {0x4EC4, 0xA4B7},{0x4EC6, 0xA4B2},{0x4EC7, 0xA4B3},{0x4EC8, 0xC954},{0x4EC9, 0xC953},{0x4ECA, 0xA4B5},{0x4ECB, 0xA4B6},{0x4ECD, 0xA4B4},
+ {0x4ED4, 0xA54A},{0x4ED5, 0xA54B},{0x4ED6, 0xA54C},{0x4ED7, 0xA54D},{0x4ED8, 0xA549},{0x4ED9, 0xA550},{0x4EDA, 0xC96A},{0x4EDC, 0xC966},
+ {0x4EDD, 0xC969},{0x4EDE, 0xA551},{0x4EDF, 0xA561},{0x4EE1, 0xC968},{0x4EE3, 0xA54E},{0x4EE4, 0xA54F},{0x4EE5, 0xA548},{0x4EE8, 0xC965},
+ {0x4EE9, 0xC967},{0x4EF0, 0xA5F5},{0x4EF1, 0xC9B0},{0x4EF2, 0xA5F2},{0x4EF3, 0xA5F6},{0x4EF4, 0xC9BA},{0x4EF5, 0xC9AE},{0x4EF6, 0xA5F3},
+ {0x4EF7, 0xC9B2},{0x4EFB, 0xA5F4},{0x4EFD, 0xA5F7},{0x4EFF, 0xA5E9},{0x4F00, 0xC9B1},{0x4F01, 0xA5F8},{0x4F02, 0xC9B5},{0x4F04, 0xC9B9},
+ {0x4F05, 0xC9B6},{0x4F08, 0xC9B3},{0x4F09, 0xA5EA},{0x4F0A, 0xA5EC},{0x4F0B, 0xA5F9},{0x4F0D, 0xA5EE},{0x4F0E, 0xC9AB},{0x4F0F, 0xA5F1},
+ {0x4F10, 0xA5EF},{0x4F11, 0xA5F0},{0x4F12, 0xC9BB},{0x4F13, 0xC9B8},{0x4F14, 0xC9AF},{0x4F15, 0xA5ED},{0x4F18, 0xC9AC},{0x4F19, 0xA5EB},
+ {0x4F1D, 0xC9B4},{0x4F22, 0xC9B7},{0x4F2C, 0xC9AD},{0x4F2D, 0xCA66},{0x4F2F, 0xA742},{0x4F30, 0xA6F4},{0x4F33, 0xCA67},{0x4F34, 0xA6F1},
+ {0x4F36, 0xA744},{0x4F38, 0xA6F9},{0x4F3A, 0xA6F8},{0x4F3B, 0xCA5B},{0x4F3C, 0xA6FC},{0x4F3D, 0xA6F7},{0x4F3E, 0xCA60},{0x4F3F, 0xCA68},
+ {0x4F41, 0xCA64},{0x4F43, 0xA6FA},{0x4F46, 0xA6FD},{0x4F47, 0xA6EE},{0x4F48, 0xA747},{0x4F49, 0xCA5D},{0x4F4C, 0xCBBD},{0x4F4D, 0xA6EC},
+ {0x4F4E, 0xA743},{0x4F4F, 0xA6ED},{0x4F50, 0xA6F5},{0x4F51, 0xA6F6},{0x4F52, 0xCA62},{0x4F53, 0xCA5E},{0x4F54, 0xA6FB},{0x4F55, 0xA6F3},
+ {0x4F56, 0xCA5A},{0x4F57, 0xA6EF},{0x4F58, 0xCA65},{0x4F59, 0xA745},{0x4F5A, 0xA748},{0x4F5B, 0xA6F2},{0x4F5C, 0xA740},{0x4F5D, 0xA746},
+ {0x4F5E, 0xA6F0},{0x4F5F, 0xCA63},{0x4F60, 0xA741},{0x4F61, 0xCA69},{0x4F62, 0xCA5C},{0x4F63, 0xA6FE},{0x4F64, 0xCA5F},{0x4F67, 0xCA61},
+ {0x4F69, 0xA8D8},{0x4F6A, 0xCBBF},{0x4F6B, 0xCBCB},{0x4F6C, 0xA8D0},{0x4F6E, 0xCBCC},{0x4F6F, 0xA8CB},{0x4F70, 0xA8D5},{0x4F73, 0xA8CE},
+ {0x4F74, 0xCBB9},{0x4F75, 0xA8D6},{0x4F76, 0xCBB8},{0x4F77, 0xCBBC},{0x4F78, 0xCBC3},{0x4F79, 0xCBC1},{0x4F7A, 0xA8DE},{0x4F7B, 0xA8D9},
+ {0x4F7C, 0xCBB3},{0x4F7D, 0xCBB5},{0x4F7E, 0xA8DB},{0x4F7F, 0xA8CF},{0x4F80, 0xCBB6},{0x4F81, 0xCBC2},{0x4F82, 0xCBC9},{0x4F83, 0xA8D4},
+ {0x4F84, 0xCBBB},{0x4F85, 0xCBB4},{0x4F86, 0xA8D3},{0x4F87, 0xCBB7},{0x4F88, 0xA8D7},{0x4F89, 0xCBBA},{0x4F8B, 0xA8D2},{0x4F8D, 0xA8CD},
+ {0x4F8F, 0xA8DC},{0x4F90, 0xCBC4},{0x4F91, 0xA8DD},{0x4F92, 0xCBC8},{0x4F94, 0xCBC6},{0x4F95, 0xCBCA},{0x4F96, 0xA8DA},{0x4F97, 0xCBBE},
+ {0x4F98, 0xCBB2},{0x4F9A, 0xCBC0},{0x4F9B, 0xA8D1},{0x4F9C, 0xCBC5},{0x4F9D, 0xA8CC},{0x4F9E, 0xCBC7},{0x4FAE, 0xAB56},{0x4FAF, 0xAB4A},
+ {0x4FB2, 0xCDE0},{0x4FB3, 0xCDE8},{0x4FB5, 0xAB49},{0x4FB6, 0xAB51},{0x4FB7, 0xAB5D},{0x4FB9, 0xCDEE},{0x4FBA, 0xCDEC},{0x4FBB, 0xCDE7},
+ {0x4FBF, 0xAB4B},{0x4FC0, 0xCDED},{0x4FC1, 0xCDE3},{0x4FC2, 0xAB59},{0x4FC3, 0xAB50},{0x4FC4, 0xAB58},{0x4FC5, 0xCDDE},{0x4FC7, 0xCDEA},
+ {0x4FC9, 0xCDE1},{0x4FCA, 0xAB54},{0x4FCB, 0xCDE2},{0x4FCD, 0xCDDD},{0x4FCE, 0xAB5B},{0x4FCF, 0xAB4E},{0x4FD0, 0xAB57},{0x4FD1, 0xAB4D},
+ {0x4FD3, 0xCDDF},{0x4FD4, 0xCDE4},{0x4FD6, 0xCDEB},{0x4FD7, 0xAB55},{0x4FD8, 0xAB52},{0x4FD9, 0xCDE6},{0x4FDA, 0xAB5A},{0x4FDB, 0xCDE9},
+ {0x4FDC, 0xCDE5},{0x4FDD, 0xAB4F},{0x4FDE, 0xAB5C},{0x4FDF, 0xAB53},{0x4FE0, 0xAB4C},{0x4FE1, 0xAB48},{0x4FEC, 0xCDEF},{0x4FEE, 0xADD7},
+ {0x4FEF, 0xADC1},{0x4FF1, 0xADD1},{0x4FF3, 0xADD6},{0x4FF4, 0xD0D0},{0x4FF5, 0xD0CF},{0x4FF6, 0xD0D4},{0x4FF7, 0xD0D5},{0x4FF8, 0xADC4},
+ {0x4FFA, 0xADCD},{0x4FFE, 0xADDA},{0x5000, 0xADCE},{0x5005, 0xD0C9},{0x5006, 0xADC7},{0x5007, 0xD0CA},{0x5009, 0xADDC},{0x500B, 0xADD3},
+ {0x500C, 0xADBE},{0x500D, 0xADBF},{0x500E, 0xD0DD},{0x500F, 0xB0BF},{0x5011, 0xADCC},{0x5012, 0xADCB},{0x5013, 0xD0CB},{0x5014, 0xADCF},
+ {0x5015, 0xD45B},{0x5016, 0xADC6},{0x5017, 0xD0D6},{0x5018, 0xADD5},{0x5019, 0xADD4},{0x501A, 0xADCA},{0x501B, 0xD0CE},{0x501C, 0xD0D7},
+ {0x501E, 0xD0C8},{0x501F, 0xADC9},{0x5020, 0xD0D8},{0x5021, 0xADD2},{0x5022, 0xD0CC},{0x5023, 0xADC0},{0x5025, 0xADC3},{0x5026, 0xADC2},
+ {0x5027, 0xD0D9},{0x5028, 0xADD0},{0x5029, 0xADC5},{0x502A, 0xADD9},{0x502B, 0xADDB},{0x502C, 0xD0D3},{0x502D, 0xADD8},{0x502F, 0xD0DB},
+ {0x5030, 0xD0CD},{0x5031, 0xD0DC},{0x5033, 0xD0D1},{0x5035, 0xD0DA},{0x5037, 0xD0D2},{0x503C, 0xADC8},{0x5040, 0xD463},{0x5041, 0xD457},
+ {0x5043, 0xB0B3},{0x5045, 0xD45C},{0x5046, 0xD462},{0x5047, 0xB0B2},{0x5048, 0xD455},{0x5049, 0xB0B6},{0x504A, 0xD459},{0x504B, 0xD452},
+ {0x504C, 0xB0B4},{0x504D, 0xD456},{0x504E, 0xB0B9},{0x504F, 0xB0BE},{0x5051, 0xD467},{0x5053, 0xD451},{0x5055, 0xB0BA},{0x5057, 0xD466},
+ {0x505A, 0xB0B5},{0x505B, 0xD458},{0x505C, 0xB0B1},{0x505D, 0xD453},{0x505E, 0xD44F},{0x505F, 0xD45D},{0x5060, 0xD450},{0x5061, 0xD44E},
+ {0x5062, 0xD45A},{0x5063, 0xD460},{0x5064, 0xD461},{0x5065, 0xB0B7},{0x5068, 0xD85B},{0x5069, 0xD45E},{0x506A, 0xD44D},{0x506B, 0xD45F},
+ {0x506D, 0xB0C1},{0x506E, 0xD464},{0x506F, 0xB0C0},{0x5070, 0xD44C},{0x5072, 0xD454},{0x5073, 0xD465},{0x5074, 0xB0BC},{0x5075, 0xB0BB},
+ {0x5076, 0xB0B8},{0x5077, 0xB0BD},{0x507A, 0xB0AF},{0x507D, 0xB0B0},{0x5080, 0xB3C8},{0x5082, 0xD85E},{0x5083, 0xD857},{0x5085, 0xB3C5},
+ {0x5087, 0xD85F},{0x508B, 0xD855},{0x508C, 0xD858},{0x508D, 0xB3C4},{0x508E, 0xD859},{0x5091, 0xB3C7},{0x5092, 0xD85D},{0x5094, 0xD853},
+ {0x5095, 0xD852},{0x5096, 0xB3C9},{0x5098, 0xB3CA},{0x5099, 0xB3C6},{0x509A, 0xB3CB},{0x509B, 0xD851},{0x509C, 0xD85C},{0x509D, 0xD85A},
+ {0x509E, 0xD854},{0x50A2, 0xB3C3},{0x50A3, 0xD856},{0x50AC, 0xB6CA},{0x50AD, 0xB6C4},{0x50AE, 0xDCB7},{0x50AF, 0xB6CD},{0x50B0, 0xDCBD},
+ {0x50B1, 0xDCC0},{0x50B2, 0xB6C6},{0x50B3, 0xB6C7},{0x50B4, 0xDCBA},{0x50B5, 0xB6C5},{0x50B6, 0xDCC3},{0x50B7, 0xB6CB},{0x50B8, 0xDCC4},
+ {0x50BA, 0xDCBF},{0x50BB, 0xB6CC},{0x50BD, 0xDCB4},{0x50BE, 0xB6C9},{0x50BF, 0xDCB5},{0x50C1, 0xDCBE},{0x50C2, 0xDCBC},{0x50C4, 0xDCB8},
+ {0x50C5, 0xB6C8},{0x50C6, 0xDCB6},{0x50C7, 0xB6CE},{0x50C8, 0xDCBB},{0x50C9, 0xDCC2},{0x50CA, 0xDCB9},{0x50CB, 0xDCC1},{0x50CE, 0xB9B6},
+ {0x50CF, 0xB9B3},{0x50D1, 0xB9B4},{0x50D3, 0xE0F9},{0x50D4, 0xE0F1},{0x50D5, 0xB9B2},{0x50D6, 0xB9AF},{0x50D7, 0xE0F2},{0x50DA, 0xB9B1},
+ {0x50DB, 0xE0F5},{0x50DD, 0xE0F7},{0x50E0, 0xE0FE},{0x50E3, 0xE0FD},{0x50E4, 0xE0F8},{0x50E5, 0xB9AE},{0x50E6, 0xE0F0},{0x50E7, 0xB9AC},
+ {0x50E8, 0xE0F3},{0x50E9, 0xB9B7},{0x50EA, 0xE0F6},{0x50EC, 0xE0FA},{0x50ED, 0xB9B0},{0x50EE, 0xB9AD},{0x50EF, 0xE0FC},{0x50F0, 0xE0FB},
+ {0x50F1, 0xB9B5},{0x50F3, 0xE0F4},{0x50F5, 0xBBF8},{0x50F6, 0xE4EC},{0x50F8, 0xE4E9},{0x50F9, 0xBBF9},{0x50FB, 0xBBF7},{0x50FD, 0xE4F0},
+ {0x50FE, 0xE4ED},{0x50FF, 0xE4E6},{0x5100, 0xBBF6},{0x5102, 0xBBFA},{0x5103, 0xE4E7},{0x5104, 0xBBF5},{0x5105, 0xBBFD},{0x5106, 0xE4EA},
+ {0x5107, 0xE4EB},{0x5108, 0xBBFB},{0x5109, 0xBBFC},{0x510A, 0xE4F1},{0x510B, 0xE4EE},{0x510C, 0xE4EF},{0x5110, 0xBEAA},{0x5111, 0xE8F8},
+ {0x5112, 0xBEA7},{0x5113, 0xE8F5},{0x5114, 0xBEA9},{0x5115, 0xBEAB},{0x5117, 0xE8F6},{0x5118, 0xBEA8},{0x511A, 0xE8F7},{0x511C, 0xE8F4},
+ {0x511F, 0xC076},{0x5120, 0xECBD},{0x5121, 0xC077},{0x5122, 0xECBB},{0x5124, 0xECBC},{0x5125, 0xECBA},{0x5126, 0xECB9},{0x5129, 0xECBE},
+ {0x512A, 0xC075},{0x512D, 0xEFB8},{0x512E, 0xEFB9},{0x5130, 0xE4E8},{0x5131, 0xEFB7},{0x5132, 0xC078},{0x5133, 0xC35F},{0x5134, 0xF1EB},
+ {0x5135, 0xF1EC},{0x5137, 0xC4D7},{0x5138, 0xC4D8},{0x5139, 0xF5C1},{0x513A, 0xF5C0},{0x513B, 0xC56C},{0x513C, 0xC56B},{0x513D, 0xF7D0},
+ {0x513F, 0xA449},{0x5140, 0xA461},{0x5141, 0xA4B9},{0x5143, 0xA4B8},{0x5144, 0xA553},{0x5145, 0xA552},{0x5146, 0xA5FC},{0x5147, 0xA5FB},
+ {0x5148, 0xA5FD},{0x5149, 0xA5FA},{0x514B, 0xA74A},{0x514C, 0xA749},{0x514D, 0xA74B},{0x5152, 0xA8E0},{0x5154, 0xA8DF},{0x5155, 0xA8E1},
+ {0x5157, 0xAB5E},{0x5159, 0xA259},{0x515A, 0xD0DE},{0x515B, 0xA25A},{0x515C, 0xB0C2},{0x515D, 0xA25C},{0x515E, 0xA25B},{0x515F, 0xD860},
+ {0x5161, 0xA25D},{0x5162, 0xB9B8},{0x5163, 0xA25E},{0x5165, 0xA44A},{0x5167, 0xA4BA},{0x5168, 0xA5FE},{0x5169, 0xA8E2},{0x516B, 0xA44B},
+ {0x516C, 0xA4BD},{0x516D, 0xA4BB},{0x516E, 0xA4BC},{0x5171, 0xA640},{0x5175, 0xA74C},{0x5176, 0xA8E4},{0x5177, 0xA8E3},{0x5178, 0xA8E5},
+ {0x517C, 0xADDD},{0x5180, 0xBEAC},{0x5187, 0xC94E},{0x5189, 0xA554},{0x518A, 0xA555},{0x518D, 0xA641},{0x518F, 0xCA6A},{0x5191, 0xAB60},
+ {0x5192, 0xAB5F},{0x5193, 0xD0E0},{0x5194, 0xD0DF},{0x5195, 0xB0C3},{0x5197, 0xA4BE},{0x5198, 0xC955},{0x519E, 0xCBCD},{0x51A0, 0xAB61},
+ {0x51A2, 0xADE0},{0x51A4, 0xADDE},{0x51A5, 0xADDF},{0x51AA, 0xBEAD},{0x51AC, 0xA556},{0x51B0, 0xA642},{0x51B1, 0xC9BC},{0x51B6, 0xA74D},
+ {0x51B7, 0xA74E},{0x51B9, 0xCA6B},{0x51BC, 0xCBCE},{0x51BD, 0xA8E6},{0x51BE, 0xCBCF},{0x51C4, 0xD0E2},{0x51C5, 0xD0E3},{0x51C6, 0xADE3},
+ {0x51C8, 0xD0E4},{0x51CA, 0xD0E1},{0x51CB, 0xADE4},{0x51CC, 0xADE2},{0x51CD, 0xADE1},{0x51CE, 0xD0E5},{0x51D0, 0xD468},{0x51D4, 0xD861},
+ {0x51D7, 0xDCC5},{0x51D8, 0xE140},{0x51DC, 0xBBFE},{0x51DD, 0xBEAE},{0x51DE, 0xE8F9},{0x51E0, 0xA44C},{0x51E1, 0xA45A},{0x51F0, 0xB0C4},
+ {0x51F1, 0xB3CD},{0x51F3, 0xB9B9},{0x51F5, 0xC942},{0x51F6, 0xA4BF},{0x51F8, 0xA559},{0x51F9, 0xA557},{0x51FA, 0xA558},{0x51FD, 0xA8E7},
+ {0x5200, 0xA44D},{0x5201, 0xA44E},{0x5203, 0xA462},{0x5206, 0xA4C0},{0x5207, 0xA4C1},{0x5208, 0xA4C2},{0x5209, 0xC9BE},{0x520A, 0xA55A},
+ {0x520C, 0xC96B},{0x520E, 0xA646},{0x5210, 0xC9BF},{0x5211, 0xA644},{0x5212, 0xA645},{0x5213, 0xC9BD},{0x5216, 0xA647},{0x5217, 0xA643},
+ {0x521C, 0xCA6C},{0x521D, 0xAAEC},{0x521E, 0xCA6D},{0x5221, 0xCA6E},{0x5224, 0xA750},{0x5225, 0xA74F},{0x5228, 0xA753},{0x5229, 0xA751},
+ {0x522A, 0xA752},{0x522E, 0xA8ED},{0x5230, 0xA8EC},{0x5231, 0xCBD4},{0x5232, 0xCBD1},{0x5233, 0xCBD2},{0x5235, 0xCBD0},{0x5236, 0xA8EE},
+ {0x5237, 0xA8EA},{0x5238, 0xA8E9},{0x523A, 0xA8EB},{0x523B, 0xA8E8},{0x5241, 0xA8EF},{0x5243, 0xAB63},{0x5244, 0xCDF0},{0x5246, 0xCBD3},
+ {0x5247, 0xAB68},{0x5249, 0xCDF1},{0x524A, 0xAB64},{0x524B, 0xAB67},{0x524C, 0xAB66},{0x524D, 0xAB65},{0x524E, 0xAB62},{0x5252, 0xD0E8},
+ {0x5254, 0xADE7},{0x5255, 0xD0EB},{0x5256, 0xADE5},{0x525A, 0xD0E7},{0x525B, 0xADE8},{0x525C, 0xADE6},{0x525D, 0xADE9},{0x525E, 0xD0E9},
+ {0x525F, 0xD0EA},{0x5261, 0xD0E6},{0x5262, 0xD0EC},{0x5269, 0xB3D1},{0x526A, 0xB0C5},{0x526B, 0xD469},{0x526C, 0xD46B},{0x526D, 0xD46A},
+ {0x526E, 0xD46C},{0x526F, 0xB0C6},{0x5272, 0xB3CE},{0x5274, 0xB3CF},{0x5275, 0xB3D0},{0x5277, 0xB6D0},{0x5278, 0xDCC7},{0x527A, 0xDCC6},
+ {0x527B, 0xDCC8},{0x527C, 0xDCC9},{0x527D, 0xB6D1},{0x527F, 0xB6CF},{0x5280, 0xE141},{0x5281, 0xE142},{0x5282, 0xB9BB},{0x5283, 0xB9BA},
+ {0x5284, 0xE35A},{0x5287, 0xBC40},{0x5288, 0xBC41},{0x5289, 0xBC42},{0x528A, 0xBC44},{0x528B, 0xE4F2},{0x528C, 0xE4F3},{0x528D, 0xBC43},
+ {0x5291, 0xBEAF},{0x5293, 0xBEB0},{0x5296, 0xF1ED},{0x5297, 0xF5C3},{0x5298, 0xF5C2},{0x5299, 0xF7D1},{0x529B, 0xA44F},{0x529F, 0xA55C},
+ {0x52A0, 0xA55B},{0x52A3, 0xA648},{0x52A6, 0xC9C0},{0x52A9, 0xA755},{0x52AA, 0xA756},{0x52AB, 0xA754},{0x52AC, 0xA757},{0x52AD, 0xCA6F},
+ {0x52AE, 0xCA70},{0x52BB, 0xA8F1},{0x52BC, 0xCBD5},{0x52BE, 0xA8F0},{0x52C0, 0xCDF2},{0x52C1, 0xAB6C},{0x52C2, 0xCDF3},{0x52C3, 0xAB6B},
+ {0x52C7, 0xAB69},{0x52C9, 0xAB6A},{0x52CD, 0xD0ED},{0x52D2, 0xB0C7},{0x52D3, 0xD46E},{0x52D5, 0xB0CA},{0x52D6, 0xD46D},{0x52D7, 0xB1E5},
+ {0x52D8, 0xB0C9},{0x52D9, 0xB0C8},{0x52DB, 0xB3D4},{0x52DD, 0xB3D3},{0x52DE, 0xB3D2},{0x52DF, 0xB6D2},{0x52E2, 0xB6D5},{0x52E3, 0xB6D6},
+ {0x52E4, 0xB6D4},{0x52E6, 0xB6D3},{0x52E9, 0xE143},{0x52EB, 0xE144},{0x52EF, 0xE4F5},{0x52F0, 0xBC45},{0x52F1, 0xE4F4},{0x52F3, 0xBEB1},
+ {0x52F4, 0xECBF},{0x52F5, 0xC079},{0x52F7, 0xF1EE},{0x52F8, 0xC455},{0x52FA, 0xA463},{0x52FB, 0xA4C3},{0x52FC, 0xC956},{0x52FE, 0xA4C4},
+ {0x52FF, 0xA4C5},{0x5305, 0xA55D},{0x5306, 0xA55E},{0x5308, 0xA649},{0x5309, 0xCA71},{0x530A, 0xCBD6},{0x530B, 0xCBD7},{0x530D, 0xAB6D},
+ {0x530E, 0xD0EE},{0x530F, 0xB0CC},{0x5310, 0xB0CB},{0x5311, 0xD863},{0x5312, 0xD862},{0x5315, 0xA450},{0x5316, 0xA4C6},{0x5317, 0xA55F},
+ {0x5319, 0xB0CD},{0x531A, 0xC943},{0x531C, 0xC96C},{0x531D, 0xA560},{0x531F, 0xC9C2},{0x5320, 0xA64B},{0x5321, 0xA64A},{0x5322, 0xC9C1},
+ {0x5323, 0xA758},{0x532A, 0xADEA},{0x532D, 0xD46F},{0x532F, 0xB6D7},{0x5330, 0xE145},{0x5331, 0xB9BC},{0x5334, 0xE8FA},{0x5337, 0xF3FD},
+ {0x5339, 0xA4C7},{0x533C, 0xCBD8},{0x533D, 0xCDF4},{0x533E, 0xB0D0},{0x533F, 0xB0CE},{0x5340, 0xB0CF},{0x5341, 0xA451},{0x5343, 0xA464},
+ {0x5344, 0xA2CD},{0x5345, 0xA4CA},{0x5347, 0xA4C9},{0x5348, 0xA4C8},{0x5349, 0xA563},{0x534A, 0xA562},{0x534C, 0xC96D},{0x534D, 0xC9C3},
+ {0x5351, 0xA8F5},{0x5352, 0xA8F2},{0x5353, 0xA8F4},{0x5354, 0xA8F3},{0x5357, 0xAB6E},{0x535A, 0xB3D5},{0x535C, 0xA452},{0x535E, 0xA4CB},
+ {0x5360, 0xA565},{0x5361, 0xA564},{0x5363, 0xCA72},{0x5366, 0xA8F6},{0x536C, 0xC957},{0x536E, 0xA567},{0x536F, 0xA566},{0x5370, 0xA64C},
+ {0x5371, 0xA64D},{0x5372, 0xCA73},{0x5373, 0xA759},{0x5375, 0xA75A},{0x5377, 0xA8F7},{0x5378, 0xA8F8},{0x5379, 0xA8F9},{0x537B, 0xAB6F},
+ {0x537C, 0xCDF5},{0x537F, 0xADEB},{0x5382, 0xC944},{0x5384, 0xA4CC},{0x538A, 0xC9C4},{0x538E, 0xCA74},{0x538F, 0xCA75},{0x5392, 0xCBD9},
+ {0x5394, 0xCBDA},{0x5396, 0xCDF7},{0x5397, 0xCDF6},{0x5398, 0xCDF9},{0x5399, 0xCDF8},{0x539A, 0xAB70},{0x539C, 0xD470},{0x539D, 0xADED},
+ {0x539E, 0xD0EF},{0x539F, 0xADEC},{0x53A4, 0xD864},{0x53A5, 0xB3D6},{0x53A7, 0xD865},{0x53AC, 0xE146},{0x53AD, 0xB9BD},{0x53B2, 0xBC46},
+ {0x53B4, 0xF1EF},{0x53B9, 0xC958},{0x53BB, 0xA568},{0x53C3, 0xB0D1},{0x53C8, 0xA453},{0x53C9, 0xA465},{0x53CA, 0xA4CE},{0x53CB, 0xA4CD},
+ {0x53CD, 0xA4CF},{0x53D4, 0xA8FB},{0x53D6, 0xA8FA},{0x53D7, 0xA8FC},{0x53DB, 0xAB71},{0x53DF, 0xADEE},{0x53E1, 0xE8FB},{0x53E2, 0xC24F},
+ {0x53E3, 0xA466},{0x53E4, 0xA56A},{0x53E5, 0xA579},{0x53E6, 0xA574},{0x53E8, 0xA56F},{0x53E9, 0xA56E},{0x53EA, 0xA575},{0x53EB, 0xA573},
+ {0x53EC, 0xA56C},{0x53ED, 0xA57A},{0x53EE, 0xA56D},{0x53EF, 0xA569},{0x53F0, 0xA578},{0x53F1, 0xA577},{0x53F2, 0xA576},{0x53F3, 0xA56B},
+ {0x53F5, 0xA572},{0x53F8, 0xA571},{0x53FB, 0xA57B},{0x53FC, 0xA570},{0x5401, 0xA653},{0x5403, 0xA659},{0x5404, 0xA655},{0x5406, 0xA65B},
+ {0x5407, 0xC9C5},{0x5408, 0xA658},{0x5409, 0xA64E},{0x540A, 0xA651},{0x540B, 0xA654},{0x540C, 0xA650},{0x540D, 0xA657},{0x540E, 0xA65A},
+ {0x540F, 0xA64F},{0x5410, 0xA652},{0x5411, 0xA656},{0x5412, 0xA65C},{0x5418, 0xCA7E},{0x5419, 0xCA7B},{0x541B, 0xA767},{0x541C, 0xCA7C},
+ {0x541D, 0xA75B},{0x541E, 0xA75D},{0x541F, 0xA775},{0x5420, 0xA770},{0x5424, 0xCAA5},{0x5425, 0xCA7D},{0x5426, 0xA75F},{0x5427, 0xA761},
+ {0x5428, 0xCAA4},{0x5429, 0xA768},{0x542A, 0xCA78},{0x542B, 0xA774},{0x542C, 0xA776},{0x542D, 0xA75C},{0x542E, 0xA76D},{0x5430, 0xCA76},
+ {0x5431, 0xA773},{0x5433, 0xA764},{0x5435, 0xA76E},{0x5436, 0xA76F},{0x5437, 0xCA77},{0x5438, 0xA76C},{0x5439, 0xA76A},{0x543B, 0xA76B},
+ {0x543C, 0xA771},{0x543D, 0xCAA1},{0x543E, 0xA75E},{0x5440, 0xA772},{0x5441, 0xCAA3},{0x5442, 0xA766},{0x5443, 0xA763},{0x5445, 0xCA7A},
+ {0x5446, 0xA762},{0x5447, 0xCAA6},{0x5448, 0xA765},{0x544A, 0xA769},{0x544E, 0xA760},{0x544F, 0xCAA2},{0x5454, 0xCA79},{0x5460, 0xCBEB},
+ {0x5461, 0xCBEA},{0x5462, 0xA94F},{0x5463, 0xCBED},{0x5464, 0xCBEF},{0x5465, 0xCBE4},{0x5466, 0xCBE7},{0x5467, 0xCBEE},{0x5468, 0xA950},
+ {0x546B, 0xCBE1},{0x546C, 0xCBE5},{0x546F, 0xCBE9},{0x5470, 0xCE49},{0x5471, 0xA94B},{0x5472, 0xCE4D},{0x5473, 0xA8FD},{0x5474, 0xCBE6},
+ {0x5475, 0xA8FE},{0x5476, 0xA94C},{0x5477, 0xA945},{0x5478, 0xA941},{0x547A, 0xCBE2},{0x547B, 0xA944},{0x547C, 0xA949},{0x547D, 0xA952},
+ {0x547E, 0xCBE3},{0x547F, 0xCBDC},{0x5480, 0xA943},{0x5481, 0xCBDD},{0x5482, 0xCBDF},{0x5484, 0xA946},{0x5486, 0xA948},{0x5487, 0xCBDB},
+ {0x5488, 0xCBE0},{0x548B, 0xA951},{0x548C, 0xA94D},{0x548D, 0xCBE8},{0x548E, 0xA953},{0x5490, 0xA94A},{0x5491, 0xCBDE},{0x5492, 0xA947},
+ {0x5495, 0xA942},{0x5496, 0xA940},{0x5498, 0xCBEC},{0x549A, 0xA94E},{0x54A0, 0xCE48},{0x54A1, 0xCDFB},{0x54A2, 0xCE4B},{0x54A5, 0xCDFD},
+ {0x54A6, 0xAB78},{0x54A7, 0xABA8},{0x54A8, 0xAB74},{0x54A9, 0xABA7},{0x54AA, 0xAB7D},{0x54AB, 0xABA4},{0x54AC, 0xAB72},{0x54AD, 0xCDFC},
+ {0x54AE, 0xCE43},{0x54AF, 0xABA3},{0x54B0, 0xCE4F},{0x54B1, 0xABA5},{0x54B3, 0xAB79},{0x54B6, 0xCE45},{0x54B7, 0xCE42},{0x54B8, 0xAB77},
+ {0x54BA, 0xCDFA},{0x54BB, 0xABA6},{0x54BC, 0xCE4A},{0x54BD, 0xAB7C},{0x54BE, 0xCE4C},{0x54BF, 0xABA9},{0x54C0, 0xAB73},{0x54C1, 0xAB7E},
+ {0x54C2, 0xAB7B},{0x54C3, 0xCE40},{0x54C4, 0xABA1},{0x54C5, 0xCE46},{0x54C6, 0xCE47},{0x54C7, 0xAB7A},{0x54C8, 0xABA2},{0x54C9, 0xAB76},
+ {0x54CE, 0xAB75},{0x54CF, 0xCDFE},{0x54D6, 0xCE44},{0x54DE, 0xCE4E},{0x54E0, 0xD144},{0x54E1, 0xADFB},{0x54E2, 0xD0F1},{0x54E4, 0xD0F6},
+ {0x54E5, 0xADF4},{0x54E6, 0xAE40},{0x54E7, 0xD0F4},{0x54E8, 0xADEF},{0x54E9, 0xADF9},{0x54EA, 0xADFE},{0x54EB, 0xD0FB},{0x54ED, 0xADFA},
+ {0x54EE, 0xADFD},{0x54F1, 0xD0FE},{0x54F2, 0xADF5},{0x54F3, 0xD0F5},{0x54F7, 0xD142},{0x54F8, 0xD143},{0x54FA, 0xADF7},{0x54FB, 0xD141},
+ {0x54FC, 0xADF3},{0x54FD, 0xAE43},{0x54FF, 0xD0F8},{0x5501, 0xADF1},{0x5503, 0xD146},{0x5504, 0xD0F9},{0x5505, 0xD0FD},{0x5506, 0xADF6},
+ {0x5507, 0xAE42},{0x5508, 0xD0FA},{0x5509, 0xADFC},{0x550A, 0xD140},{0x550B, 0xD147},{0x550C, 0xD4A1},{0x550E, 0xD145},{0x550F, 0xAE44},
+ {0x5510, 0xADF0},{0x5511, 0xD0FC},{0x5512, 0xD0F3},{0x5514, 0xADF8},{0x5517, 0xD0F2},{0x551A, 0xD0F7},{0x5526, 0xD0F0},{0x5527, 0xAE41},
+ {0x552A, 0xD477},{0x552C, 0xB0E4},{0x552D, 0xD4A7},{0x552E, 0xB0E2},{0x552F, 0xB0DF},{0x5530, 0xD47C},{0x5531, 0xB0DB},{0x5532, 0xD4A2},
+ {0x5533, 0xB0E6},{0x5534, 0xD476},{0x5535, 0xD47B},{0x5536, 0xD47A},{0x5537, 0xADF2},{0x5538, 0xB0E1},{0x5539, 0xD4A5},{0x553B, 0xD4A8},
+ {0x553C, 0xD473},{0x553E, 0xB3E8},{0x5540, 0xD4A9},{0x5541, 0xB0E7},{0x5543, 0xB0D9},{0x5544, 0xB0D6},{0x5545, 0xD47E},{0x5546, 0xB0D3},
+ {0x5548, 0xD4A6},{0x554A, 0xB0DA},{0x554B, 0xD4AA},{0x554D, 0xD474},{0x554E, 0xD4A4},{0x554F, 0xB0DD},{0x5550, 0xD475},{0x5551, 0xD478},
+ {0x5552, 0xD47D},{0x5555, 0xB0DE},{0x5556, 0xB0DC},{0x5557, 0xB0E8},{0x555C, 0xB0E3},{0x555E, 0xB0D7},{0x555F, 0xB1D2},{0x5561, 0xB0D8},
+ {0x5562, 0xD479},{0x5563, 0xB0E5},{0x5564, 0xB0E0},{0x5565, 0xD4A3},{0x5566, 0xB0D5},{0x556A, 0xB0D4},{0x5575, 0xD471},{0x5576, 0xD472},
+ {0x5577, 0xD86A},{0x557B, 0xB3D7},{0x557C, 0xB3DA},{0x557D, 0xD875},{0x557E, 0xB3EE},{0x557F, 0xD878},{0x5580, 0xB3D8},{0x5581, 0xD871},
+ {0x5582, 0xB3DE},{0x5583, 0xB3E4},{0x5584, 0xB5BD},{0x5587, 0xB3E2},{0x5588, 0xD86E},{0x5589, 0xB3EF},{0x558A, 0xB3DB},{0x558B, 0xB3E3},
+ {0x558C, 0xD876},{0x558D, 0xDCD7},{0x558E, 0xD87B},{0x558F, 0xD86F},{0x5591, 0xD866},{0x5592, 0xD873},{0x5593, 0xD86D},{0x5594, 0xB3E1},
+ {0x5595, 0xD879},{0x5598, 0xB3DD},{0x5599, 0xB3F1},{0x559A, 0xB3EA},{0x559C, 0xB3DF},{0x559D, 0xB3DC},{0x559F, 0xB3E7},{0x55A1, 0xD87A},
+ {0x55A2, 0xD86C},{0x55A3, 0xD872},{0x55A4, 0xD874},{0x55A5, 0xD868},{0x55A6, 0xD877},{0x55A7, 0xB3D9},{0x55A8, 0xD867},{0x55AA, 0xB3E0},
+ {0x55AB, 0xB3F0},{0x55AC, 0xB3EC},{0x55AD, 0xD869},{0x55AE, 0xB3E6},{0x55B1, 0xB3ED},{0x55B2, 0xB3E9},{0x55B3, 0xB3E5},{0x55B5, 0xD870},
+ {0x55BB, 0xB3EB},{0x55BF, 0xDCD5},{0x55C0, 0xDCD1},{0x55C2, 0xDCE0},{0x55C3, 0xDCCA},{0x55C4, 0xDCD3},{0x55C5, 0xB6E5},{0x55C6, 0xB6E6},
+ {0x55C7, 0xB6DE},{0x55C8, 0xDCDC},{0x55C9, 0xB6E8},{0x55CA, 0xDCCF},{0x55CB, 0xDCCE},{0x55CC, 0xDCCC},{0x55CD, 0xDCDE},{0x55CE, 0xB6DC},
+ {0x55CF, 0xDCD8},{0x55D0, 0xDCCD},{0x55D1, 0xB6DF},{0x55D2, 0xDCD6},{0x55D3, 0xB6DA},{0x55D4, 0xDCD2},{0x55D5, 0xDCD9},{0x55D6, 0xDCDB},
+ {0x55D9, 0xDCDF},{0x55DA, 0xB6E3},{0x55DB, 0xDCCB},{0x55DC, 0xB6DD},{0x55DD, 0xDCD0},{0x55DF, 0xB6D8},{0x55E1, 0xB6E4},{0x55E2, 0xDCDA},
+ {0x55E3, 0xB6E0},{0x55E4, 0xB6E1},{0x55E5, 0xB6E7},{0x55E6, 0xB6DB},{0x55E7, 0xA25F},{0x55E8, 0xB6D9},{0x55E9, 0xDCD4},{0x55EF, 0xB6E2},
+ {0x55F2, 0xDCDD},{0x55F6, 0xB9CD},{0x55F7, 0xB9C8},{0x55F9, 0xE155},{0x55FA, 0xE151},{0x55FC, 0xE14B},{0x55FD, 0xB9C2},{0x55FE, 0xB9BE},
+ {0x55FF, 0xE154},{0x5600, 0xB9BF},{0x5601, 0xE14E},{0x5602, 0xE150},{0x5604, 0xE153},{0x5606, 0xB9C4},{0x5608, 0xB9CB},{0x5609, 0xB9C5},
+ {0x560C, 0xE149},{0x560D, 0xB9C6},{0x560E, 0xB9C7},{0x560F, 0xE14C},{0x5610, 0xB9CC},{0x5612, 0xE14A},{0x5613, 0xE14F},{0x5614, 0xB9C3},
+ {0x5615, 0xE148},{0x5616, 0xB9C9},{0x5617, 0xB9C1},{0x561B, 0xB9C0},{0x561C, 0xE14D},{0x561D, 0xE152},{0x561F, 0xB9CA},{0x5627, 0xE147},
+ {0x5629, 0xBC4D},{0x562A, 0xE547},{0x562C, 0xE544},{0x562E, 0xBC47},{0x562F, 0xBC53},{0x5630, 0xBC54},{0x5632, 0xBC4A},{0x5633, 0xE542},
+ {0x5634, 0xBC4C},{0x5635, 0xE4F9},{0x5636, 0xBC52},{0x5638, 0xE546},{0x5639, 0xBC49},{0x563A, 0xE548},{0x563B, 0xBC48},{0x563D, 0xE543},
+ {0x563E, 0xE545},{0x563F, 0xBC4B},{0x5640, 0xE541},{0x5641, 0xE4FA},{0x5642, 0xE4F7},{0x5645, 0xD86B},{0x5646, 0xE4FD},{0x5648, 0xE4F6},
+ {0x5649, 0xE4FC},{0x564A, 0xE4FB},{0x564C, 0xE4F8},{0x564E, 0xBC4F},{0x5653, 0xBC4E},{0x5657, 0xBC50},{0x5658, 0xE4FE},{0x5659, 0xBEB2},
+ {0x565A, 0xE540},{0x565E, 0xE945},{0x5660, 0xE8FD},{0x5662, 0xBEBE},{0x5663, 0xE942},{0x5664, 0xBEB6},{0x5665, 0xBEBA},{0x5666, 0xE941},
+ {0x5668, 0xBEB9},{0x5669, 0xBEB5},{0x566A, 0xBEB8},{0x566B, 0xBEB3},{0x566C, 0xBEBD},{0x566D, 0xE943},{0x566E, 0xE8FE},{0x566F, 0xBEBC},
+ {0x5670, 0xE8FC},{0x5671, 0xBEBB},{0x5672, 0xE944},{0x5673, 0xE940},{0x5674, 0xBC51},{0x5676, 0xBEBF},{0x5677, 0xE946},{0x5678, 0xBEB7},
+ {0x5679, 0xBEB4},{0x567E, 0xECC6},{0x567F, 0xECC8},{0x5680, 0xC07B},{0x5681, 0xECC9},{0x5682, 0xECC7},{0x5683, 0xECC5},{0x5684, 0xECC4},
+ {0x5685, 0xC07D},{0x5686, 0xECC3},{0x5687, 0xC07E},{0x568C, 0xECC1},{0x568D, 0xECC2},{0x568E, 0xC07A},{0x568F, 0xC0A1},{0x5690, 0xC07C},
+ {0x5693, 0xECC0},{0x5695, 0xC250},{0x5697, 0xEFBC},{0x5698, 0xEFBA},{0x5699, 0xEFBF},{0x569A, 0xEFBD},{0x569C, 0xEFBB},{0x569D, 0xEFBE},
+ {0x56A5, 0xC360},{0x56A6, 0xF1F2},{0x56A7, 0xF1F3},{0x56A8, 0xC456},{0x56AA, 0xF1F4},{0x56AB, 0xF1F0},{0x56AC, 0xF1F5},{0x56AD, 0xF1F1},
+ {0x56AE, 0xC251},{0x56B2, 0xF3FE},{0x56B3, 0xF441},{0x56B4, 0xC459},{0x56B5, 0xF440},{0x56B6, 0xC458},{0x56B7, 0xC457},{0x56BC, 0xC45A},
+ {0x56BD, 0xF5C5},{0x56BE, 0xF5C6},{0x56C0, 0xC4DA},{0x56C1, 0xC4D9},{0x56C2, 0xC4DB},{0x56C3, 0xF5C4},{0x56C5, 0xF6D8},{0x56C6, 0xF6D7},
+ {0x56C8, 0xC56D},{0x56C9, 0xC56F},{0x56CA, 0xC56E},{0x56CB, 0xF6D9},{0x56CC, 0xC5C8},{0x56CD, 0xF8A6},{0x56D1, 0xC5F1},{0x56D3, 0xF8A5},
+ {0x56D4, 0xF8EE},{0x56D7, 0xC949},{0x56DA, 0xA57D},{0x56DB, 0xA57C},{0x56DD, 0xA65F},{0x56DE, 0xA65E},{0x56DF, 0xC9C7},{0x56E0, 0xA65D},
+ {0x56E1, 0xC9C6},{0x56E4, 0xA779},{0x56E5, 0xCAA9},{0x56E7, 0xCAA8},{0x56EA, 0xA777},{0x56EB, 0xA77A},{0x56EE, 0xCAA7},{0x56F0, 0xA778},
+ {0x56F7, 0xCBF0},{0x56F9, 0xCBF1},{0x56FA, 0xA954},{0x56FF, 0xABAA},{0x5701, 0xD148},{0x5702, 0xD149},{0x5703, 0xAE45},{0x5704, 0xAE46},
+ {0x5707, 0xD4AC},{0x5708, 0xB0E9},{0x5709, 0xB0EB},{0x570A, 0xD4AB},{0x570B, 0xB0EA},{0x570C, 0xD87C},{0x570D, 0xB3F2},{0x5712, 0xB6E9},
+ {0x5713, 0xB6EA},{0x5714, 0xDCE1},{0x5716, 0xB9CF},{0x5718, 0xB9CE},{0x571A, 0xE549},{0x571B, 0xE948},{0x571C, 0xE947},{0x571E, 0xF96B},
+ {0x571F, 0xA467},{0x5720, 0xC959},{0x5722, 0xC96E},{0x5723, 0xC96F},{0x5728, 0xA662},{0x5729, 0xA666},{0x572A, 0xC9C9},{0x572C, 0xA664},
+ {0x572D, 0xA663},{0x572E, 0xC9C8},{0x572F, 0xA665},{0x5730, 0xA661},{0x5733, 0xA660},{0x5734, 0xC9CA},{0x573B, 0xA7A6},{0x573E, 0xA7A3},
+ {0x5740, 0xA77D},{0x5741, 0xCAAA},{0x5745, 0xCAAB},{0x5747, 0xA7A1},{0x5749, 0xCAAD},{0x574A, 0xA77B},{0x574B, 0xCAAE},{0x574C, 0xCAAC},
+ {0x574D, 0xA77E},{0x574E, 0xA7A2},{0x574F, 0xA7A5},{0x5750, 0xA7A4},{0x5751, 0xA77C},{0x5752, 0xCAAF},{0x5761, 0xA959},{0x5762, 0xCBFE},
+ {0x5764, 0xA95B},{0x5766, 0xA95A},{0x5768, 0xCC40},{0x5769, 0xA958},{0x576A, 0xA957},{0x576B, 0xCBF5},{0x576D, 0xCBF4},{0x576F, 0xCBF2},
+ {0x5770, 0xCBF7},{0x5771, 0xCBF6},{0x5772, 0xCBF3},{0x5773, 0xCBFC},{0x5774, 0xCBFD},{0x5775, 0xCBFA},{0x5776, 0xCBF8},{0x5777, 0xA956},
+ {0x577B, 0xCBFB},{0x577C, 0xA95C},{0x577D, 0xCC41},{0x5780, 0xCBF9},{0x5782, 0xABAB},{0x5783, 0xA955},{0x578B, 0xABAC},{0x578C, 0xCE54},
+ {0x578F, 0xCE5A},{0x5793, 0xABB2},{0x5794, 0xCE58},{0x5795, 0xCE5E},{0x5797, 0xCE55},{0x5798, 0xCE59},{0x5799, 0xCE5B},{0x579A, 0xCE5D},
+ {0x579B, 0xCE57},{0x579D, 0xCE56},{0x579E, 0xCE51},{0x579F, 0xCE52},{0x57A0, 0xABAD},{0x57A2, 0xABAF},{0x57A3, 0xABAE},{0x57A4, 0xCE53},
+ {0x57A5, 0xCE5C},{0x57AE, 0xABB1},{0x57B5, 0xCE50},{0x57B6, 0xD153},{0x57B8, 0xD152},{0x57B9, 0xD157},{0x57BA, 0xD14E},{0x57BC, 0xD151},
+ {0x57BD, 0xD150},{0x57BF, 0xD154},{0x57C1, 0xD158},{0x57C2, 0xAE47},{0x57C3, 0xAE4A},{0x57C6, 0xD14F},{0x57C7, 0xD155},{0x57CB, 0xAE49},
+ {0x57CC, 0xD14A},{0x57CE, 0xABB0},{0x57CF, 0xD4BA},{0x57D0, 0xD156},{0x57D2, 0xD14D},{0x57D4, 0xAE48},{0x57D5, 0xD14C},{0x57DC, 0xD4B1},
+ {0x57DF, 0xB0EC},{0x57E0, 0xB0F0},{0x57E1, 0xD4C1},{0x57E2, 0xD4AF},{0x57E3, 0xD4BD},{0x57E4, 0xB0F1},{0x57E5, 0xD4BF},{0x57E7, 0xD4C5},
+ {0x57E9, 0xD4C9},{0x57EC, 0xD4C0},{0x57ED, 0xD4B4},{0x57EE, 0xD4BC},{0x57F0, 0xD4CA},{0x57F1, 0xD4C8},{0x57F2, 0xD4BE},{0x57F3, 0xD4B9},
+ {0x57F4, 0xD4B2},{0x57F5, 0xD8A6},{0x57F6, 0xD4B0},{0x57F7, 0xB0F5},{0x57F8, 0xD4B7},{0x57F9, 0xB0F6},{0x57FA, 0xB0F2},{0x57FB, 0xD4AD},
+ {0x57FC, 0xD4C3},{0x57FD, 0xD4B5},{0x5800, 0xD4B3},{0x5801, 0xD4C6},{0x5802, 0xB0F3},{0x5804, 0xD4CC},{0x5805, 0xB0ED},{0x5806, 0xB0EF},
+ {0x5807, 0xD4BB},{0x5808, 0xD4B6},{0x5809, 0xAE4B},{0x580A, 0xB0EE},{0x580B, 0xD4B8},{0x580C, 0xD4C7},{0x580D, 0xD4CB},{0x580E, 0xD4C2},
+ {0x5810, 0xD4C4},{0x5814, 0xD4AE},{0x5819, 0xD8A1},{0x581B, 0xD8AA},{0x581C, 0xD8A9},{0x581D, 0xB3FA},{0x581E, 0xD8A2},{0x5820, 0xB3FB},
+ {0x5821, 0xB3F9},{0x5823, 0xD8A4},{0x5824, 0xB3F6},{0x5825, 0xD8A8},{0x5827, 0xD8A3},{0x5828, 0xD8A5},{0x5829, 0xD87D},{0x582A, 0xB3F4},
+ {0x582C, 0xD8B2},{0x582D, 0xD8B1},{0x582E, 0xD8AE},{0x582F, 0xB3F3},{0x5830, 0xB3F7},{0x5831, 0xB3F8},{0x5832, 0xD14B},{0x5833, 0xD8AB},
+ {0x5834, 0xB3F5},{0x5835, 0xB0F4},{0x5836, 0xD8AD},{0x5837, 0xD87E},{0x5838, 0xD8B0},{0x5839, 0xD8AF},{0x583B, 0xD8B3},{0x583D, 0xDCEF},
+ {0x583F, 0xD8AC},{0x5848, 0xD8A7},{0x5849, 0xDCE7},{0x584A, 0xB6F4},{0x584B, 0xB6F7},{0x584C, 0xB6F2},{0x584D, 0xDCE6},{0x584E, 0xDCEA},
+ {0x584F, 0xDCE5},{0x5851, 0xB6EC},{0x5852, 0xB6F6},{0x5853, 0xDCE2},{0x5854, 0xB6F0},{0x5855, 0xDCE9},{0x5857, 0xB6EE},{0x5858, 0xB6ED},
+ {0x5859, 0xDCEC},{0x585A, 0xB6EF},{0x585B, 0xDCEE},{0x585D, 0xDCEB},{0x585E, 0xB6EB},{0x5862, 0xB6F5},{0x5863, 0xDCF0},{0x5864, 0xDCE4},
+ {0x5865, 0xDCED},{0x5868, 0xDCE3},{0x586B, 0xB6F1},{0x586D, 0xB6F3},{0x586F, 0xDCE8},{0x5871, 0xDCF1},{0x5874, 0xE15D},{0x5875, 0xB9D0},
+ {0x5876, 0xE163},{0x5879, 0xB9D5},{0x587A, 0xE15F},{0x587B, 0xE166},{0x587C, 0xE157},{0x587D, 0xB9D7},{0x587E, 0xB9D1},{0x587F, 0xE15C},
+ {0x5880, 0xBC55},{0x5881, 0xE15B},{0x5882, 0xE164},{0x5883, 0xB9D2},{0x5885, 0xB9D6},{0x5886, 0xE15A},{0x5887, 0xE160},{0x5888, 0xE165},
+ {0x5889, 0xE156},{0x588A, 0xB9D4},{0x588B, 0xE15E},{0x588E, 0xE162},{0x588F, 0xE168},{0x5890, 0xE158},{0x5891, 0xE161},{0x5893, 0xB9D3},
+ {0x5894, 0xE167},{0x5898, 0xE159},{0x589C, 0xBC59},{0x589D, 0xE54B},{0x589E, 0xBC57},{0x589F, 0xBC56},{0x58A0, 0xE54D},{0x58A1, 0xE552},
+ {0x58A3, 0xE54E},{0x58A5, 0xE551},{0x58A6, 0xBC5C},{0x58A8, 0xBEA5},{0x58A9, 0xBC5B},{0x58AB, 0xE54A},{0x58AC, 0xE550},{0x58AE, 0xBC5A},
+ {0x58AF, 0xE54F},{0x58B1, 0xE54C},{0x58B3, 0xBC58},{0x58BA, 0xE94D},{0x58BC, 0xE94F},{0x58BD, 0xE94A},{0x58BE, 0xBEC1},{0x58BF, 0xE94C},
+ {0x58C1, 0xBEC0},{0x58C2, 0xE94E},{0x58C5, 0xBEC3},{0x58C6, 0xE950},{0x58C7, 0xBEC2},{0x58C8, 0xE949},{0x58C9, 0xE94B},{0x58CE, 0xC0A5},
+ {0x58CF, 0xECCC},{0x58D1, 0xC0A4},{0x58D2, 0xECCD},{0x58D3, 0xC0A3},{0x58D4, 0xECCB},{0x58D5, 0xC0A2},{0x58D6, 0xECCA},{0x58D8, 0xC253},
+ {0x58D9, 0xC252},{0x58DA, 0xF1F6},{0x58DB, 0xF1F8},{0x58DD, 0xF1F7},{0x58DE, 0xC361},{0x58DF, 0xC362},{0x58E2, 0xC363},{0x58E3, 0xF442},
+ {0x58E4, 0xC45B},{0x58E7, 0xF7D3},{0x58E8, 0xF7D2},{0x58E9, 0xC5F2},{0x58EB, 0xA468},{0x58EC, 0xA4D0},{0x58EF, 0xA7A7},{0x58F4, 0xCE5F},
+ {0x58F9, 0xB3FC},{0x58FA, 0xB3FD},{0x58FC, 0xDCF2},{0x58FD, 0xB9D8},{0x58FE, 0xE169},{0x58FF, 0xE553},{0x5903, 0xC95A},{0x5906, 0xCAB0},
+ {0x590C, 0xCC42},{0x590D, 0xCE60},{0x590E, 0xD159},{0x590F, 0xAE4C},{0x5912, 0xF1F9},{0x5914, 0xC4DC},{0x5915, 0xA469},{0x5916, 0xA57E},
+ {0x5917, 0xC970},{0x5919, 0xA667},{0x591A, 0xA668},{0x591C, 0xA95D},{0x5920, 0xB0F7},{0x5922, 0xB9DA},{0x5924, 0xB9DB},{0x5925, 0xB9D9},
+ {0x5927, 0xA46A},{0x5929, 0xA4D1},{0x592A, 0xA4D3},{0x592B, 0xA4D2},{0x592C, 0xC95B},{0x592D, 0xA4D4},{0x592E, 0xA5A1},{0x592F, 0xC971},
+ {0x5931, 0xA5A2},{0x5937, 0xA669},{0x5938, 0xA66A},{0x593C, 0xC9CB},{0x593E, 0xA7A8},{0x5940, 0xCAB1},{0x5944, 0xA961},{0x5945, 0xCC43},
+ {0x5947, 0xA95F},{0x5948, 0xA960},{0x5949, 0xA95E},{0x594A, 0xD15A},{0x594E, 0xABB6},{0x594F, 0xABB5},{0x5950, 0xABB7},{0x5951, 0xABB4},
+ {0x5953, 0xCE61},{0x5954, 0xA962},{0x5955, 0xABB3},{0x5957, 0xAE4D},{0x5958, 0xAE4E},{0x595A, 0xAE4F},{0x595C, 0xD4CD},{0x5960, 0xB3FE},
+ {0x5961, 0xD8B4},{0x5962, 0xB0F8},{0x5967, 0xB6F8},{0x5969, 0xB9DD},{0x596A, 0xB9DC},{0x596B, 0xE16A},{0x596D, 0xBC5D},{0x596E, 0xBEC4},
+ {0x5970, 0xEFC0},{0x5971, 0xF6DA},{0x5972, 0xF7D4},{0x5973, 0xA46B},{0x5974, 0xA5A3},{0x5976, 0xA5A4},{0x5977, 0xC9D1},{0x5978, 0xA66C},
+ {0x5979, 0xA66F},{0x597B, 0xC9CF},{0x597C, 0xC9CD},{0x597D, 0xA66E},{0x597E, 0xC9D0},{0x597F, 0xC9D2},{0x5980, 0xC9CC},{0x5981, 0xA671},
+ {0x5982, 0xA670},{0x5983, 0xA66D},{0x5984, 0xA66B},{0x5985, 0xC9CE},{0x598A, 0xA7B3},{0x598D, 0xA7B0},{0x598E, 0xCAB6},{0x598F, 0xCAB9},
+ {0x5990, 0xCAB8},{0x5992, 0xA7AA},{0x5993, 0xA7B2},{0x5996, 0xA7AF},{0x5997, 0xCAB5},{0x5998, 0xCAB3},{0x5999, 0xA7AE},{0x599D, 0xA7A9},
+ {0x599E, 0xA7AC},{0x59A0, 0xCAB4},{0x59A1, 0xCABB},{0x59A2, 0xCAB7},{0x59A3, 0xA7AD},{0x59A4, 0xA7B1},{0x59A5, 0xA7B4},{0x59A6, 0xCAB2},
+ {0x59A7, 0xCABA},{0x59A8, 0xA7AB},{0x59AE, 0xA967},{0x59AF, 0xA96F},{0x59B1, 0xCC4F},{0x59B2, 0xCC48},{0x59B3, 0xA970},{0x59B4, 0xCC53},
+ {0x59B5, 0xCC44},{0x59B6, 0xCC4B},{0x59B9, 0xA966},{0x59BA, 0xCC45},{0x59BB, 0xA964},{0x59BC, 0xCC4C},{0x59BD, 0xCC50},{0x59BE, 0xA963},
+ {0x59C0, 0xCC51},{0x59C1, 0xCC4A},{0x59C3, 0xCC4D},{0x59C5, 0xA972},{0x59C6, 0xA969},{0x59C7, 0xCC54},{0x59C8, 0xCC52},{0x59CA, 0xA96E},
+ {0x59CB, 0xA96C},{0x59CC, 0xCC49},{0x59CD, 0xA96B},{0x59CE, 0xCC47},{0x59CF, 0xCC46},{0x59D0, 0xA96A},{0x59D1, 0xA968},{0x59D2, 0xA971},
+ {0x59D3, 0xA96D},{0x59D4, 0xA965},{0x59D6, 0xCC4E},{0x59D8, 0xABB9},{0x59DA, 0xABC0},{0x59DB, 0xCE6F},{0x59DC, 0xABB8},{0x59DD, 0xCE67},
+ {0x59DE, 0xCE63},{0x59E0, 0xCE73},{0x59E1, 0xCE62},{0x59E3, 0xABBB},{0x59E4, 0xCE6C},{0x59E5, 0xABBE},{0x59E6, 0xABC1},{0x59E8, 0xABBC},
+ {0x59E9, 0xCE70},{0x59EA, 0xABBF},{0x59EC, 0xAE56},{0x59ED, 0xCE76},{0x59EE, 0xCE64},{0x59F1, 0xCE66},{0x59F2, 0xCE6D},{0x59F3, 0xCE71},
+ {0x59F4, 0xCE75},{0x59F5, 0xCE72},{0x59F6, 0xCE6B},{0x59F7, 0xCE6E},{0x59FA, 0xCE68},{0x59FB, 0xABC3},{0x59FC, 0xCE6A},{0x59FD, 0xCE69},
+ {0x59FE, 0xCE74},{0x59FF, 0xABBA},{0x5A00, 0xCE65},{0x5A01, 0xABC2},{0x5A03, 0xABBD},{0x5A09, 0xAE5C},{0x5A0A, 0xD162},{0x5A0C, 0xAE5B},
+ {0x5A0F, 0xD160},{0x5A11, 0xAE50},{0x5A13, 0xAE55},{0x5A15, 0xD15F},{0x5A16, 0xD15C},{0x5A17, 0xD161},{0x5A18, 0xAE51},{0x5A19, 0xD15B},
+ {0x5A1B, 0xAE54},{0x5A1C, 0xAE52},{0x5A1E, 0xD163},{0x5A1F, 0xAE53},{0x5A20, 0xAE57},{0x5A23, 0xAE58},{0x5A25, 0xAE5A},{0x5A29, 0xAE59},
+ {0x5A2D, 0xD15D},{0x5A2E, 0xD15E},{0x5A33, 0xD164},{0x5A35, 0xD4D4},{0x5A36, 0xB0F9},{0x5A37, 0xD8C2},{0x5A38, 0xD4D3},{0x5A39, 0xD4E6},
+ {0x5A3C, 0xB140},{0x5A3E, 0xD4E4},{0x5A40, 0xB0FE},{0x5A41, 0xB0FA},{0x5A42, 0xD4ED},{0x5A43, 0xD4DD},{0x5A44, 0xD4E0},{0x5A46, 0xB143},
+ {0x5A47, 0xD4EA},{0x5A48, 0xD4E2},{0x5A49, 0xB0FB},{0x5A4A, 0xB144},{0x5A4C, 0xD4E7},{0x5A4D, 0xD4E5},{0x5A50, 0xD4D6},{0x5A51, 0xD4EB},
+ {0x5A52, 0xD4DF},{0x5A53, 0xD4DA},{0x5A55, 0xD4D0},{0x5A56, 0xD4EC},{0x5A57, 0xD4DC},{0x5A58, 0xD4CF},{0x5A5A, 0xB142},{0x5A5B, 0xD4E1},
+ {0x5A5C, 0xD4EE},{0x5A5D, 0xD4DE},{0x5A5E, 0xD4D2},{0x5A5F, 0xD4D7},{0x5A60, 0xD4CE},{0x5A62, 0xB141},{0x5A64, 0xD4DB},{0x5A65, 0xD4D8},
+ {0x5A66, 0xB0FC},{0x5A67, 0xD4D1},{0x5A69, 0xD4E9},{0x5A6A, 0xB0FD},{0x5A6C, 0xD4D9},{0x5A6D, 0xD4D5},{0x5A70, 0xD4E8},{0x5A77, 0xB440},
+ {0x5A78, 0xD8BB},{0x5A7A, 0xD8B8},{0x5A7B, 0xD8C9},{0x5A7C, 0xD8BD},{0x5A7D, 0xD8CA},{0x5A7F, 0xB442},{0x5A83, 0xD8C6},{0x5A84, 0xD8C3},
+ {0x5A8A, 0xD8C4},{0x5A8B, 0xD8C7},{0x5A8C, 0xD8CB},{0x5A8E, 0xD4E3},{0x5A8F, 0xD8CD},{0x5A90, 0xDD47},{0x5A92, 0xB443},{0x5A93, 0xD8CE},
+ {0x5A94, 0xD8B6},{0x5A95, 0xD8C0},{0x5A97, 0xD8C5},{0x5A9A, 0xB441},{0x5A9B, 0xB444},{0x5A9C, 0xD8CC},{0x5A9D, 0xD8CF},{0x5A9E, 0xD8BA},
+ {0x5A9F, 0xD8B7},{0x5AA2, 0xD8B9},{0x5AA5, 0xD8BE},{0x5AA6, 0xD8BC},{0x5AA7, 0xB445},{0x5AA9, 0xD8C8},{0x5AAC, 0xD8BF},{0x5AAE, 0xD8C1},
+ {0x5AAF, 0xD8B5},{0x5AB0, 0xDCFA},{0x5AB1, 0xDCF8},{0x5AB2, 0xB742},{0x5AB3, 0xB740},{0x5AB4, 0xDD43},{0x5AB5, 0xDCF9},{0x5AB6, 0xDD44},
+ {0x5AB7, 0xDD40},{0x5AB8, 0xDCF7},{0x5AB9, 0xDD46},{0x5ABA, 0xDCF6},{0x5ABB, 0xDCFD},{0x5ABC, 0xB6FE},{0x5ABD, 0xB6FD},{0x5ABE, 0xB6FC},
+ {0x5ABF, 0xDCFB},{0x5AC0, 0xDD41},{0x5AC1, 0xB6F9},{0x5AC2, 0xB741},{0x5AC4, 0xDCF4},{0x5AC6, 0xDCFE},{0x5AC7, 0xDCF3},{0x5AC8, 0xDCFC},
+ {0x5AC9, 0xB6FA},{0x5ACA, 0xDD42},{0x5ACB, 0xDCF5},{0x5ACC, 0xB6FB},{0x5ACD, 0xDD45},{0x5AD5, 0xE16E},{0x5AD6, 0xB9E2},{0x5AD7, 0xB9E1},
+ {0x5AD8, 0xB9E3},{0x5AD9, 0xE17A},{0x5ADA, 0xE170},{0x5ADB, 0xE176},{0x5ADC, 0xE16B},{0x5ADD, 0xE179},{0x5ADE, 0xE178},{0x5ADF, 0xE17C},
+ {0x5AE0, 0xE175},{0x5AE1, 0xB9DE},{0x5AE2, 0xE174},{0x5AE3, 0xB9E4},{0x5AE5, 0xE16D},{0x5AE6, 0xB9DF},{0x5AE8, 0xE17B},{0x5AE9, 0xB9E0},
+ {0x5AEA, 0xE16F},{0x5AEB, 0xE172},{0x5AEC, 0xE177},{0x5AED, 0xE171},{0x5AEE, 0xE16C},{0x5AF3, 0xE173},{0x5AF4, 0xE555},{0x5AF5, 0xBC61},
+ {0x5AF6, 0xE558},{0x5AF7, 0xE557},{0x5AF8, 0xE55A},{0x5AF9, 0xE55C},{0x5AFB, 0xBC5F},{0x5AFD, 0xE556},{0x5AFF, 0xE554},{0x5B01, 0xE55D},
+ {0x5B02, 0xE55B},{0x5B03, 0xE559},{0x5B05, 0xE55F},{0x5B07, 0xE55E},{0x5B08, 0xBC63},{0x5B09, 0xBC5E},{0x5B0B, 0xBC60},{0x5B0C, 0xBC62},
+ {0x5B0F, 0xE560},{0x5B10, 0xE957},{0x5B13, 0xE956},{0x5B14, 0xE955},{0x5B16, 0xE958},{0x5B17, 0xE951},{0x5B19, 0xE952},{0x5B1A, 0xE95A},
+ {0x5B1B, 0xE953},{0x5B1D, 0xBEC5},{0x5B1E, 0xE95C},{0x5B20, 0xE95B},{0x5B21, 0xE954},{0x5B23, 0xECD1},{0x5B24, 0xC0A8},{0x5B25, 0xECCF},
+ {0x5B26, 0xECD4},{0x5B27, 0xECD3},{0x5B28, 0xE959},{0x5B2A, 0xC0A7},{0x5B2C, 0xECD2},{0x5B2D, 0xECCE},{0x5B2E, 0xECD6},{0x5B2F, 0xECD5},
+ {0x5B30, 0xC0A6},{0x5B32, 0xECD0},{0x5B34, 0xBEC6},{0x5B38, 0xC254},{0x5B3C, 0xEFC1},{0x5B3D, 0xF1FA},{0x5B3E, 0xF1FB},{0x5B3F, 0xF1FC},
+ {0x5B40, 0xC45C},{0x5B43, 0xC45D},{0x5B45, 0xF443},{0x5B47, 0xF5C8},{0x5B48, 0xF5C7},{0x5B4B, 0xF6DB},{0x5B4C, 0xF6DC},{0x5B4D, 0xF7D5},
+ {0x5B4E, 0xF8A7},{0x5B50, 0xA46C},{0x5B51, 0xA46D},{0x5B53, 0xA46E},{0x5B54, 0xA4D5},{0x5B55, 0xA5A5},{0x5B56, 0xC9D3},{0x5B57, 0xA672},
+ {0x5B58, 0xA673},{0x5B5A, 0xA7B7},{0x5B5B, 0xA7B8},{0x5B5C, 0xA7B6},{0x5B5D, 0xA7B5},{0x5B5F, 0xA973},{0x5B62, 0xCC55},{0x5B63, 0xA975},
+ {0x5B64, 0xA974},{0x5B65, 0xCC56},{0x5B69, 0xABC4},{0x5B6B, 0xAE5D},{0x5B6C, 0xD165},{0x5B6E, 0xD4F0},{0x5B70, 0xB145},{0x5B71, 0xB447},
+ {0x5B72, 0xD4EF},{0x5B73, 0xB446},{0x5B75, 0xB9E5},{0x5B77, 0xE17D},{0x5B78, 0xBEC7},{0x5B7A, 0xC0A9},{0x5B7B, 0xECD7},{0x5B7D, 0xC45E},
+ {0x5B7F, 0xC570},{0x5B81, 0xC972},{0x5B83, 0xA5A6},{0x5B84, 0xC973},{0x5B85, 0xA676},{0x5B87, 0xA674},{0x5B88, 0xA675},{0x5B89, 0xA677},
+ {0x5B8B, 0xA7BA},{0x5B8C, 0xA7B9},{0x5B8E, 0xCABC},{0x5B8F, 0xA7BB},{0x5B92, 0xCABD},{0x5B93, 0xCC57},{0x5B95, 0xCC58},{0x5B97, 0xA976},
+ {0x5B98, 0xA978},{0x5B99, 0xA97A},{0x5B9A, 0xA977},{0x5B9B, 0xA97B},{0x5B9C, 0xA979},{0x5BA2, 0xABC8},{0x5BA3, 0xABC5},{0x5BA4, 0xABC7},
+ {0x5BA5, 0xABC9},{0x5BA6, 0xABC6},{0x5BA7, 0xD166},{0x5BA8, 0xCE77},{0x5BAC, 0xD168},{0x5BAD, 0xD167},{0x5BAE, 0xAE63},{0x5BB0, 0xAE5F},
+ {0x5BB3, 0xAE60},{0x5BB4, 0xAE62},{0x5BB5, 0xAE64},{0x5BB6, 0xAE61},{0x5BB8, 0xAE66},{0x5BB9, 0xAE65},{0x5BBF, 0xB14A},{0x5BC0, 0xD4F2},
+ {0x5BC1, 0xD4F1},{0x5BC2, 0xB149},{0x5BC4, 0xB148},{0x5BC5, 0xB147},{0x5BC6, 0xB14B},{0x5BC7, 0xB146},{0x5BCA, 0xD8D5},{0x5BCB, 0xD8D2},
+ {0x5BCC, 0xB449},{0x5BCD, 0xD8D1},{0x5BCE, 0xD8D6},{0x5BD0, 0xB44B},{0x5BD1, 0xD8D4},{0x5BD2, 0xB448},{0x5BD3, 0xB44A},{0x5BD4, 0xD8D3},
+ {0x5BD6, 0xDD48},{0x5BD8, 0xDD49},{0x5BD9, 0xDD4A},{0x5BDE, 0xB9E6},{0x5BDF, 0xB9EE},{0x5BE0, 0xE17E},{0x5BE1, 0xB9E8},{0x5BE2, 0xB9EC},
+ {0x5BE3, 0xE1A1},{0x5BE4, 0xB9ED},{0x5BE5, 0xB9E9},{0x5BE6, 0xB9EA},{0x5BE7, 0xB9E7},{0x5BE8, 0xB9EB},{0x5BE9, 0xBC66},{0x5BEA, 0xD8D0},
+ {0x5BEB, 0xBC67},{0x5BEC, 0xBC65},{0x5BEE, 0xBC64},{0x5BEF, 0xE95D},{0x5BF0, 0xBEC8},{0x5BF1, 0xECD8},{0x5BF2, 0xECD9},{0x5BF5, 0xC364},
+ {0x5BF6, 0xC45F},{0x5BF8, 0xA46F},{0x5BFA, 0xA678},{0x5C01, 0xABCA},{0x5C03, 0xD169},{0x5C04, 0xAE67},{0x5C07, 0xB14E},{0x5C08, 0xB14D},
+ {0x5C09, 0xB14C},{0x5C0A, 0xB44C},{0x5C0B, 0xB44D},{0x5C0C, 0xD8D7},{0x5C0D, 0xB9EF},{0x5C0E, 0xBEC9},{0x5C0F, 0xA470},{0x5C10, 0xC95C},
+ {0x5C11, 0xA4D6},{0x5C12, 0xC974},{0x5C15, 0xC9D4},{0x5C16, 0xA679},{0x5C1A, 0xA97C},{0x5C1F, 0xDD4B},{0x5C22, 0xA471},{0x5C24, 0xA4D7},
+ {0x5C25, 0xC9D5},{0x5C28, 0xCABE},{0x5C2A, 0xCABF},{0x5C2C, 0xA7BC},{0x5C30, 0xD8D8},{0x5C31, 0xB44E},{0x5C33, 0xDD4C},{0x5C37, 0xC0AA},
+ {0x5C38, 0xA472},{0x5C39, 0xA4A8},{0x5C3A, 0xA4D8},{0x5C3B, 0xC975},{0x5C3C, 0xA5A7},{0x5C3E, 0xA7C0},{0x5C3F, 0xA7BF},{0x5C40, 0xA7BD},
+ {0x5C41, 0xA7BE},{0x5C44, 0xCC59},{0x5C45, 0xA97E},{0x5C46, 0xA9A1},{0x5C47, 0xCC5A},{0x5C48, 0xA97D},{0x5C4B, 0xABCE},{0x5C4C, 0xCE78},
+ {0x5C4D, 0xABCD},{0x5C4E, 0xABCB},{0x5C4F, 0xABCC},{0x5C50, 0xAE6A},{0x5C51, 0xAE68},{0x5C54, 0xD16B},{0x5C55, 0xAE69},{0x5C56, 0xD16A},
+ {0x5C58, 0xAE5E},{0x5C59, 0xD4F3},{0x5C5C, 0xB150},{0x5C5D, 0xB151},{0x5C60, 0xB14F},{0x5C62, 0xB9F0},{0x5C63, 0xE1A2},{0x5C64, 0xBC68},
+ {0x5C65, 0xBC69},{0x5C67, 0xE561},{0x5C68, 0xC0AB},{0x5C69, 0xEFC2},{0x5C6A, 0xEFC3},{0x5C6C, 0xC4DD},{0x5C6D, 0xF8A8},{0x5C6E, 0xC94B},
+ {0x5C6F, 0xA4D9},{0x5C71, 0xA473},{0x5C73, 0xC977},{0x5C74, 0xC976},{0x5C79, 0xA67A},{0x5C7A, 0xC9D7},{0x5C7B, 0xC9D8},{0x5C7C, 0xC9D6},
+ {0x5C7E, 0xC9D9},{0x5C86, 0xCAC7},{0x5C88, 0xCAC2},{0x5C89, 0xCAC4},{0x5C8A, 0xCAC6},{0x5C8B, 0xCAC3},{0x5C8C, 0xA7C4},{0x5C8D, 0xCAC0},
+ {0x5C8F, 0xCAC1},{0x5C90, 0xA7C1},{0x5C91, 0xA7C2},{0x5C92, 0xCAC5},{0x5C93, 0xCAC8},{0x5C94, 0xA7C3},{0x5C95, 0xCAC9},{0x5C9D, 0xCC68},
+ {0x5C9F, 0xCC62},{0x5CA0, 0xCC5D},{0x5CA1, 0xA9A3},{0x5CA2, 0xCC65},{0x5CA3, 0xCC63},{0x5CA4, 0xCC5C},{0x5CA5, 0xCC69},{0x5CA6, 0xCC6C},
+ {0x5CA7, 0xCC67},{0x5CA8, 0xCC60},{0x5CA9, 0xA9A5},{0x5CAA, 0xCC66},{0x5CAB, 0xA9A6},{0x5CAC, 0xCC61},{0x5CAD, 0xCC64},{0x5CAE, 0xCC5B},
+ {0x5CAF, 0xCC5F},{0x5CB0, 0xCC6B},{0x5CB1, 0xA9A7},{0x5CB3, 0xA9A8},{0x5CB5, 0xCC5E},{0x5CB6, 0xCC6A},{0x5CB7, 0xA9A2},{0x5CB8, 0xA9A4},
+ {0x5CC6, 0xCEAB},{0x5CC7, 0xCEA4},{0x5CC8, 0xCEAA},{0x5CC9, 0xCEA3},{0x5CCA, 0xCEA5},{0x5CCB, 0xCE7D},{0x5CCC, 0xCE7B},{0x5CCE, 0xCEAC},
+ {0x5CCF, 0xCEA9},{0x5CD0, 0xCE79},{0x5CD2, 0xABD0},{0x5CD3, 0xCEA7},{0x5CD4, 0xCEA8},{0x5CD6, 0xCEA6},{0x5CD7, 0xCE7C},{0x5CD8, 0xCE7A},
+ {0x5CD9, 0xABCF},{0x5CDA, 0xCEA2},{0x5CDB, 0xCE7E},{0x5CDE, 0xCEA1},{0x5CDF, 0xCEAD},{0x5CE8, 0xAE6F},{0x5CEA, 0xAE6E},{0x5CEC, 0xD16C},
+ {0x5CED, 0xAE6B},{0x5CEE, 0xD16E},{0x5CF0, 0xAE70},{0x5CF1, 0xD16F},{0x5CF4, 0xAE73},{0x5CF6, 0xAE71},{0x5CF7, 0xD170},{0x5CF8, 0xCEAE},
+ {0x5CF9, 0xD172},{0x5CFB, 0xAE6D},{0x5CFD, 0xAE6C},{0x5CFF, 0xD16D},{0x5D00, 0xD171},{0x5D01, 0xAE72},{0x5D06, 0xB153},{0x5D07, 0xB152},
+ {0x5D0B, 0xD4F5},{0x5D0C, 0xD4F9},{0x5D0D, 0xD4FB},{0x5D0E, 0xB154},{0x5D0F, 0xD4FE},{0x5D11, 0xB158},{0x5D12, 0xD541},{0x5D14, 0xB15A},
+ {0x5D16, 0xB156},{0x5D17, 0xB15E},{0x5D19, 0xB15B},{0x5D1A, 0xD4F7},{0x5D1B, 0xB155},{0x5D1D, 0xD4F6},{0x5D1E, 0xD4F4},{0x5D1F, 0xD543},
+ {0x5D20, 0xD4F8},{0x5D22, 0xB157},{0x5D23, 0xD542},{0x5D24, 0xB15C},{0x5D25, 0xD4FD},{0x5D26, 0xD4FC},{0x5D27, 0xB15D},{0x5D28, 0xD4FA},
+ {0x5D29, 0xB159},{0x5D2E, 0xD544},{0x5D30, 0xD540},{0x5D31, 0xD8E7},{0x5D32, 0xD8EE},{0x5D33, 0xD8E3},{0x5D34, 0xB451},{0x5D35, 0xD8DF},
+ {0x5D36, 0xD8EF},{0x5D37, 0xD8D9},{0x5D38, 0xD8EC},{0x5D39, 0xD8EA},{0x5D3A, 0xD8E4},{0x5D3C, 0xD8ED},{0x5D3D, 0xD8E6},{0x5D3F, 0xD8DE},
+ {0x5D40, 0xD8F0},{0x5D41, 0xD8DC},{0x5D42, 0xD8E9},{0x5D43, 0xD8DA},{0x5D45, 0xD8F1},{0x5D47, 0xB452},{0x5D49, 0xD8EB},{0x5D4A, 0xDD4F},
+ {0x5D4B, 0xD8DD},{0x5D4C, 0xB44F},{0x5D4E, 0xD8E1},{0x5D50, 0xB450},{0x5D51, 0xD8E0},{0x5D52, 0xD8E5},{0x5D55, 0xD8E2},{0x5D59, 0xD8E8},
+ {0x5D5E, 0xDD53},{0x5D62, 0xDD56},{0x5D63, 0xDD4E},{0x5D65, 0xDD50},{0x5D67, 0xDD55},{0x5D68, 0xDD54},{0x5D69, 0xB743},{0x5D6B, 0xD8DB},
+ {0x5D6C, 0xDD52},{0x5D6F, 0xB744},{0x5D71, 0xDD4D},{0x5D72, 0xDD51},{0x5D77, 0xE1A9},{0x5D79, 0xE1B0},{0x5D7A, 0xE1A7},{0x5D7C, 0xE1AE},
+ {0x5D7D, 0xE1A5},{0x5D7E, 0xE1AD},{0x5D7F, 0xE1B1},{0x5D80, 0xE1A4},{0x5D81, 0xE1A8},{0x5D82, 0xE1A3},{0x5D84, 0xB9F1},{0x5D86, 0xE1A6},
+ {0x5D87, 0xB9F2},{0x5D88, 0xE1AC},{0x5D89, 0xE1AB},{0x5D8A, 0xE1AA},{0x5D8D, 0xE1AF},{0x5D92, 0xE565},{0x5D93, 0xE567},{0x5D94, 0xBC6B},
+ {0x5D95, 0xE568},{0x5D97, 0xE563},{0x5D99, 0xE562},{0x5D9A, 0xE56C},{0x5D9C, 0xE56A},{0x5D9D, 0xBC6A},{0x5D9E, 0xE56D},{0x5D9F, 0xE564},
+ {0x5DA0, 0xE569},{0x5DA1, 0xE56B},{0x5DA2, 0xE566},{0x5DA7, 0xE961},{0x5DA8, 0xE966},{0x5DA9, 0xE960},{0x5DAA, 0xE965},{0x5DAC, 0xE95E},
+ {0x5DAD, 0xE968},{0x5DAE, 0xE964},{0x5DAF, 0xE969},{0x5DB0, 0xE963},{0x5DB1, 0xE95F},{0x5DB2, 0xE967},{0x5DB4, 0xE96A},{0x5DB5, 0xE962},
+ {0x5DB7, 0xECDA},{0x5DB8, 0xC0AF},{0x5DBA, 0xC0AD},{0x5DBC, 0xC0AC},{0x5DBD, 0xC0AE},{0x5DC0, 0xEFC4},{0x5DC2, 0xF172},{0x5DC3, 0xF1FD},
+ {0x5DC6, 0xF444},{0x5DC7, 0xF445},{0x5DC9, 0xC460},{0x5DCB, 0xF5C9},{0x5DCD, 0xC4DE},{0x5DCF, 0xF5CA},{0x5DD1, 0xF6DE},{0x5DD2, 0xC572},
+ {0x5DD4, 0xC571},{0x5DD5, 0xF6DD},{0x5DD6, 0xC5C9},{0x5DD8, 0xF7D6},{0x5DDD, 0xA474},{0x5DDE, 0xA67B},{0x5DDF, 0xC9DA},{0x5DE0, 0xCACA},
+ {0x5DE1, 0xA8B5},{0x5DE2, 0xB15F},{0x5DE5, 0xA475},{0x5DE6, 0xA5AA},{0x5DE7, 0xA5A9},{0x5DE8, 0xA5A8},{0x5DEB, 0xA7C5},{0x5DEE, 0xAE74},
+ {0x5DF0, 0xDD57},{0x5DF1, 0xA476},{0x5DF2, 0xA477},{0x5DF3, 0xA478},{0x5DF4, 0xA4DA},{0x5DF7, 0xABD1},{0x5DF9, 0xCEAF},{0x5DFD, 0xB453},
+ {0x5DFE, 0xA479},{0x5DFF, 0xC95D},{0x5E02, 0xA5AB},{0x5E03, 0xA5AC},{0x5E04, 0xC978},{0x5E06, 0xA67C},{0x5E0A, 0xCACB},{0x5E0C, 0xA7C6},
+ {0x5E0E, 0xCACC},{0x5E11, 0xA9AE},{0x5E14, 0xCC6E},{0x5E15, 0xA9AC},{0x5E16, 0xA9AB},{0x5E17, 0xCC6D},{0x5E18, 0xA9A9},{0x5E19, 0xCC6F},
+ {0x5E1A, 0xA9AA},{0x5E1B, 0xA9AD},{0x5E1D, 0xABD2},{0x5E1F, 0xABD4},{0x5E20, 0xCEB3},{0x5E21, 0xCEB0},{0x5E22, 0xCEB1},{0x5E23, 0xCEB2},
+ {0x5E24, 0xCEB4},{0x5E25, 0xABD3},{0x5E28, 0xD174},{0x5E29, 0xD173},{0x5E2B, 0xAE76},{0x5E2D, 0xAE75},{0x5E33, 0xB162},{0x5E34, 0xD546},
+ {0x5E36, 0xB161},{0x5E37, 0xB163},{0x5E38, 0xB160},{0x5E3D, 0xB455},{0x5E3E, 0xD545},{0x5E40, 0xB456},{0x5E41, 0xD8F3},{0x5E43, 0xB457},
+ {0x5E44, 0xD8F2},{0x5E45, 0xB454},{0x5E4A, 0xDD5A},{0x5E4B, 0xDD5C},{0x5E4C, 0xB745},{0x5E4D, 0xDD5B},{0x5E4E, 0xDD59},{0x5E4F, 0xDD58},
+ {0x5E53, 0xE1B4},{0x5E54, 0xB9F7},{0x5E55, 0xB9F5},{0x5E57, 0xB9F6},{0x5E58, 0xE1B2},{0x5E59, 0xE1B3},{0x5E5B, 0xB9F3},{0x5E5C, 0xE571},
+ {0x5E5D, 0xE56F},{0x5E5F, 0xBC6D},{0x5E60, 0xE570},{0x5E61, 0xBC6E},{0x5E62, 0xBC6C},{0x5E63, 0xB9F4},{0x5E66, 0xE96D},{0x5E67, 0xE96B},
+ {0x5E68, 0xE96C},{0x5E69, 0xE56E},{0x5E6A, 0xECDC},{0x5E6B, 0xC0B0},{0x5E6C, 0xECDB},{0x5E6D, 0xEFC5},{0x5E6E, 0xEFC6},{0x5E6F, 0xE96E},
+ {0x5E70, 0xF1FE},{0x5E72, 0xA47A},{0x5E73, 0xA5AD},{0x5E74, 0xA67E},{0x5E75, 0xC9DB},{0x5E76, 0xA67D},{0x5E78, 0xA9AF},{0x5E79, 0xB746},
+ {0x5E7B, 0xA4DB},{0x5E7C, 0xA5AE},{0x5E7D, 0xABD5},{0x5E7E, 0xB458},{0x5E80, 0xC979},{0x5E82, 0xC97A},{0x5E84, 0xC9DC},{0x5E87, 0xA7C8},
+ {0x5E88, 0xCAD0},{0x5E89, 0xCACE},{0x5E8A, 0xA7C9},{0x5E8B, 0xCACD},{0x5E8C, 0xCACF},{0x5E8D, 0xCAD1},{0x5E8F, 0xA7C7},{0x5E95, 0xA9B3},
+ {0x5E96, 0xA9B4},{0x5E97, 0xA9B1},{0x5E9A, 0xA9B0},{0x5E9B, 0xCEB8},{0x5E9C, 0xA9B2},{0x5EA0, 0xABD6},{0x5EA2, 0xCEB7},{0x5EA3, 0xCEB9},
+ {0x5EA4, 0xCEB6},{0x5EA5, 0xCEBA},{0x5EA6, 0xABD7},{0x5EA7, 0xAE79},{0x5EA8, 0xD175},{0x5EAA, 0xD177},{0x5EAB, 0xAE77},{0x5EAC, 0xD178},
+ {0x5EAD, 0xAE78},{0x5EAE, 0xD176},{0x5EB0, 0xCEB5},{0x5EB1, 0xD547},{0x5EB2, 0xD54A},{0x5EB3, 0xD54B},{0x5EB4, 0xD548},{0x5EB5, 0xB167},
+ {0x5EB6, 0xB166},{0x5EB7, 0xB164},{0x5EB8, 0xB165},{0x5EB9, 0xD549},{0x5EBE, 0xB168},{0x5EC1, 0xB45A},{0x5EC2, 0xB45B},{0x5EC4, 0xB45C},
+ {0x5EC5, 0xDD5D},{0x5EC6, 0xDD5F},{0x5EC7, 0xDD61},{0x5EC8, 0xB748},{0x5EC9, 0xB747},{0x5ECA, 0xB459},{0x5ECB, 0xDD60},{0x5ECC, 0xDD5E},
+ {0x5ECE, 0xE1B8},{0x5ED1, 0xE1B6},{0x5ED2, 0xE1BC},{0x5ED3, 0xB9F8},{0x5ED4, 0xE1BD},{0x5ED5, 0xE1BA},{0x5ED6, 0xB9F9},{0x5ED7, 0xE1B7},
+ {0x5ED8, 0xE1B5},{0x5ED9, 0xE1BB},{0x5EDA, 0xBC70},{0x5EDB, 0xE573},{0x5EDC, 0xE1B9},{0x5EDD, 0xBC72},{0x5EDE, 0xE574},{0x5EDF, 0xBC71},
+ {0x5EE0, 0xBC74},{0x5EE1, 0xE575},{0x5EE2, 0xBC6F},{0x5EE3, 0xBC73},{0x5EE5, 0xE973},{0x5EE6, 0xE971},{0x5EE7, 0xE970},{0x5EE8, 0xE972},
+ {0x5EE9, 0xE96F},{0x5EEC, 0xC366},{0x5EEE, 0xF446},{0x5EEF, 0xF447},{0x5EF1, 0xF5CB},{0x5EF2, 0xF6DF},{0x5EF3, 0xC655},{0x5EF6, 0xA9B5},
+ {0x5EF7, 0xA7CA},{0x5EFA, 0xABD8},{0x5EFE, 0xA47B},{0x5EFF, 0xA4DC},{0x5F01, 0xA5AF},{0x5F02, 0xC9DD},{0x5F04, 0xA7CB},{0x5F05, 0xCAD2},
+ {0x5F07, 0xCEBB},{0x5F08, 0xABD9},{0x5F0A, 0xB9FA},{0x5F0B, 0xA47C},{0x5F0F, 0xA6A1},{0x5F12, 0xB749},{0x5F13, 0xA47D},{0x5F14, 0xA4DD},
+ {0x5F15, 0xA4DE},{0x5F17, 0xA5B1},{0x5F18, 0xA5B0},{0x5F1A, 0xC9DE},{0x5F1B, 0xA6A2},{0x5F1D, 0xCAD3},{0x5F1F, 0xA7CC},{0x5F22, 0xCC71},
+ {0x5F23, 0xCC72},{0x5F24, 0xCC73},{0x5F26, 0xA9B6},{0x5F27, 0xA9B7},{0x5F28, 0xCC70},{0x5F29, 0xA9B8},{0x5F2D, 0xABDA},{0x5F2E, 0xCEBC},
+ {0x5F30, 0xD17A},{0x5F31, 0xAE7A},{0x5F33, 0xD179},{0x5F35, 0xB169},{0x5F36, 0xD54C},{0x5F37, 0xB16A},{0x5F38, 0xD54D},{0x5F3C, 0xB45D},
+ {0x5F40, 0xDD62},{0x5F43, 0xE1BF},{0x5F44, 0xE1BE},{0x5F46, 0xB9FB},{0x5F48, 0xBC75},{0x5F49, 0xE576},{0x5F4A, 0xBECA},{0x5F4B, 0xE974},
+ {0x5F4C, 0xC0B1},{0x5F4E, 0xC573},{0x5F4F, 0xF7D8},{0x5F54, 0xCC74},{0x5F56, 0xCEBD},{0x5F57, 0xB16B},{0x5F58, 0xD8F4},{0x5F59, 0xB74A},
+ {0x5F5D, 0xC255},{0x5F62, 0xA7CE},{0x5F64, 0xA7CD},{0x5F65, 0xABDB},{0x5F67, 0xD17B},{0x5F69, 0xB16D},{0x5F6A, 0xB343},{0x5F6B, 0xB16E},
+ {0x5F6C, 0xB16C},{0x5F6D, 0xB45E},{0x5F6F, 0xE1C0},{0x5F70, 0xB9FC},{0x5F71, 0xBC76},{0x5F73, 0xC94C},{0x5F74, 0xC9DF},{0x5F76, 0xCAD5},
+ {0x5F77, 0xA7CF},{0x5F78, 0xCAD4},{0x5F79, 0xA7D0},{0x5F7C, 0xA9BC},{0x5F7D, 0xCC77},{0x5F7E, 0xCC76},{0x5F7F, 0xA9BB},{0x5F80, 0xA9B9},
+ {0x5F81, 0xA9BA},{0x5F82, 0xCC75},{0x5F85, 0xABDD},{0x5F86, 0xCEBE},{0x5F87, 0xABE0},{0x5F88, 0xABDC},{0x5F89, 0xABE2},{0x5F8A, 0xABDE},
+ {0x5F8B, 0xABDF},{0x5F8C, 0xABE1},{0x5F90, 0xAE7D},{0x5F91, 0xAE7C},{0x5F92, 0xAE7B},{0x5F96, 0xD54F},{0x5F97, 0xB16F},{0x5F98, 0xB172},
+ {0x5F99, 0xB170},{0x5F9B, 0xD54E},{0x5F9C, 0xB175},{0x5F9E, 0xB171},{0x5F9F, 0xD550},{0x5FA0, 0xB174},{0x5FA1, 0xB173},{0x5FA5, 0xD8F6},
+ {0x5FA6, 0xD8F5},{0x5FA8, 0xB461},{0x5FA9, 0xB45F},{0x5FAA, 0xB460},{0x5FAB, 0xD8F7},{0x5FAC, 0xB74B},{0x5FAD, 0xDD64},{0x5FAE, 0xB74C},
+ {0x5FAF, 0xDD63},{0x5FB2, 0xE577},{0x5FB5, 0xBC78},{0x5FB6, 0xE1C1},{0x5FB7, 0xBC77},{0x5FB9, 0xB9FD},{0x5FBB, 0xECDE},{0x5FBC, 0xE975},
+ {0x5FBD, 0xC0B2},{0x5FBE, 0xECDD},{0x5FBF, 0xF240},{0x5FC0, 0xF448},{0x5FC1, 0xF449},{0x5FC3, 0xA4DF},{0x5FC5, 0xA5B2},{0x5FC9, 0xC97B},
+ {0x5FCC, 0xA7D2},{0x5FCD, 0xA7D4},{0x5FCF, 0xC9E2},{0x5FD0, 0xCAD8},{0x5FD1, 0xCAD7},{0x5FD2, 0xCAD6},{0x5FD4, 0xC9E1},{0x5FD5, 0xC9E0},
+ {0x5FD6, 0xA6A4},{0x5FD7, 0xA7D3},{0x5FD8, 0xA7D1},{0x5FD9, 0xA6A3},{0x5FDD, 0xA9BD},{0x5FDE, 0xCC78},{0x5FE0, 0xA9BE},{0x5FE1, 0xCADD},
+ {0x5FE3, 0xCADF},{0x5FE4, 0xCADE},{0x5FE5, 0xCC79},{0x5FE8, 0xCADA},{0x5FEA, 0xA7D8},{0x5FEB, 0xA7D6},{0x5FED, 0xCAD9},{0x5FEE, 0xCADB},
+ {0x5FEF, 0xCAE1},{0x5FF1, 0xA7D5},{0x5FF3, 0xCADC},{0x5FF4, 0xCAE5},{0x5FF5, 0xA9C0},{0x5FF7, 0xCAE2},{0x5FF8, 0xA7D7},{0x5FFA, 0xCAE0},
+ {0x5FFB, 0xCAE3},{0x5FFD, 0xA9BF},{0x5FFF, 0xA9C1},{0x6000, 0xCAE4},{0x6009, 0xCCAF},{0x600A, 0xCCA2},{0x600B, 0xCC7E},{0x600C, 0xCCAE},
+ {0x600D, 0xCCA9},{0x600E, 0xABE7},{0x600F, 0xA9C2},{0x6010, 0xCCAA},{0x6011, 0xCCAD},{0x6012, 0xABE3},{0x6013, 0xCCAC},{0x6014, 0xA9C3},
+ {0x6015, 0xA9C8},{0x6016, 0xA9C6},{0x6017, 0xCCA3},{0x6019, 0xCC7C},{0x601A, 0xCCA5},{0x601B, 0xA9CD},{0x601C, 0xCCB0},{0x601D, 0xABE4},
+ {0x601E, 0xCCA6},{0x6020, 0xABE5},{0x6021, 0xA9C9},{0x6022, 0xCCA8},{0x6024, 0xCECD},{0x6025, 0xABE6},{0x6026, 0xCC7B},{0x6027, 0xA9CA},
+ {0x6028, 0xABE8},{0x6029, 0xA9CB},{0x602A, 0xA9C7},{0x602B, 0xA9CC},{0x602C, 0xCCA7},{0x602D, 0xCC7A},{0x602E, 0xCCAB},{0x602F, 0xA9C4},
+ {0x6032, 0xCC7D},{0x6033, 0xCCA4},{0x6034, 0xCCA1},{0x6035, 0xA9C5},{0x6037, 0xCEBF},{0x6039, 0xCEC0},{0x6040, 0xCECA},{0x6041, 0xD1A1},
+ {0x6042, 0xCECB},{0x6043, 0xABEE},{0x6044, 0xCECE},{0x6045, 0xCEC4},{0x6046, 0xABED},{0x6047, 0xCEC6},{0x6049, 0xCEC7},{0x604C, 0xCEC9},
+ {0x604D, 0xABE9},{0x6050, 0xAEA3},{0x6053, 0xCEC5},{0x6054, 0xCEC1},{0x6055, 0xAEA4},{0x6058, 0xCECF},{0x6059, 0xAE7E},{0x605A, 0xD17D},
+ {0x605B, 0xCEC8},{0x605D, 0xD17C},{0x605E, 0xCEC3},{0x605F, 0xCECC},{0x6062, 0xABEC},{0x6063, 0xAEA1},{0x6064, 0xABF2},{0x6065, 0xAEA2},
+ {0x6066, 0xCED0},{0x6067, 0xD17E},{0x6068, 0xABEB},{0x6069, 0xAEA6},{0x606A, 0xABF1},{0x606B, 0xABF0},{0x606C, 0xABEF},{0x606D, 0xAEA5},
+ {0x606E, 0xCED1},{0x606F, 0xAEA7},{0x6070, 0xABEA},{0x6072, 0xCEC2},{0x607F, 0xB176},{0x6080, 0xD1A4},{0x6081, 0xD1A6},{0x6083, 0xD1A8},
+ {0x6084, 0xAEA8},{0x6085, 0xAEAE},{0x6086, 0xD553},{0x6087, 0xD1AC},{0x6088, 0xD1A3},{0x6089, 0xB178},{0x608A, 0xD551},{0x608C, 0xAEAD},
+ {0x608D, 0xAEAB},{0x608E, 0xD1AE},{0x6090, 0xD552},{0x6092, 0xD1A5},{0x6094, 0xAEAC},{0x6095, 0xD1A9},{0x6096, 0xAEAF},{0x6097, 0xD1AB},
+ {0x609A, 0xAEAA},{0x609B, 0xD1AA},{0x609C, 0xD1AD},{0x609D, 0xD1A7},{0x609F, 0xAEA9},{0x60A0, 0xB179},{0x60A2, 0xD1A2},{0x60A3, 0xB177},
+ {0x60A8, 0xB17A},{0x60B0, 0xD555},{0x60B1, 0xD55E},{0x60B2, 0xB464},{0x60B4, 0xB17C},{0x60B5, 0xB1A3},{0x60B6, 0xB465},{0x60B7, 0xD560},
+ {0x60B8, 0xB1AA},{0x60B9, 0xD8F9},{0x60BA, 0xD556},{0x60BB, 0xB1A2},{0x60BC, 0xB1A5},{0x60BD, 0xB17E},{0x60BE, 0xD554},{0x60BF, 0xD562},
+ {0x60C0, 0xD565},{0x60C1, 0xD949},{0x60C3, 0xD563},{0x60C4, 0xD8FD},{0x60C5, 0xB1A1},{0x60C6, 0xB1A8},{0x60C7, 0xB1AC},{0x60C8, 0xD55D},
+ {0x60C9, 0xD8F8},{0x60CA, 0xD561},{0x60CB, 0xB17B},{0x60CC, 0xD8FA},{0x60CD, 0xD564},{0x60CE, 0xD8FC},{0x60CF, 0xD559},{0x60D1, 0xB462},
+ {0x60D3, 0xD557},{0x60D4, 0xD558},{0x60D5, 0xB1A7},{0x60D8, 0xB1A6},{0x60D9, 0xD55B},{0x60DA, 0xB1AB},{0x60DB, 0xD55F},{0x60DC, 0xB1A4},
+ {0x60DD, 0xD55C},{0x60DF, 0xB1A9},{0x60E0, 0xB466},{0x60E1, 0xB463},{0x60E2, 0xD8FB},{0x60E4, 0xD55A},{0x60E6, 0xB17D},{0x60F0, 0xB46B},
+ {0x60F1, 0xB46F},{0x60F2, 0xD940},{0x60F3, 0xB751},{0x60F4, 0xB46D},{0x60F5, 0xD944},{0x60F6, 0xB471},{0x60F7, 0xDD65},{0x60F8, 0xD946},
+ {0x60F9, 0xB753},{0x60FA, 0xB469},{0x60FB, 0xB46C},{0x60FC, 0xD947},{0x60FE, 0xD948},{0x60FF, 0xD94E},{0x6100, 0xB473},{0x6101, 0xB754},
+ {0x6103, 0xD94A},{0x6104, 0xD94F},{0x6105, 0xD943},{0x6106, 0xB75E},{0x6108, 0xB755},{0x6109, 0xB472},{0x610A, 0xD941},{0x610B, 0xD950},
+ {0x610D, 0xB75D},{0x610E, 0xB470},{0x610F, 0xB74E},{0x6110, 0xD94D},{0x6112, 0xB474},{0x6113, 0xD945},{0x6114, 0xD8FE},{0x6115, 0xB46A},
+ {0x6116, 0xD942},{0x6118, 0xD94B},{0x611A, 0xB74D},{0x611B, 0xB752},{0x611C, 0xB467},{0x611D, 0xD94C},{0x611F, 0xB750},{0x6123, 0xB468},
+ {0x6127, 0xB75C},{0x6128, 0xE1C3},{0x6129, 0xDD70},{0x612B, 0xDD68},{0x612C, 0xE1C2},{0x612E, 0xDD6C},{0x612F, 0xDD6E},{0x6132, 0xDD6B},
+ {0x6134, 0xB75B},{0x6136, 0xDD6A},{0x6137, 0xB75F},{0x613B, 0xE1D2},{0x613E, 0xB75A},{0x613F, 0xBA40},{0x6140, 0xDD71},{0x6141, 0xE1C4},
+ {0x6144, 0xB758},{0x6145, 0xDD69},{0x6146, 0xDD6D},{0x6147, 0xB9FE},{0x6148, 0xB74F},{0x6149, 0xDD66},{0x614A, 0xDD67},{0x614B, 0xBA41},
+ {0x614C, 0xB757},{0x614D, 0xB759},{0x614E, 0xB756},{0x614F, 0xDD6F},{0x6152, 0xE1C8},{0x6153, 0xE1C9},{0x6154, 0xE1CE},{0x6155, 0xBC7D},
+ {0x6156, 0xE1D5},{0x6158, 0xBA47},{0x615A, 0xBA46},{0x615B, 0xE1D0},{0x615D, 0xBC7C},{0x615E, 0xE1C5},{0x615F, 0xBA45},{0x6161, 0xE1D4},
+ {0x6162, 0xBA43},{0x6163, 0xBA44},{0x6165, 0xE1D1},{0x6166, 0xE5AA},{0x6167, 0xBC7A},{0x6168, 0xB46E},{0x616A, 0xE1D3},{0x616B, 0xBCA3},
+ {0x616C, 0xE1CB},{0x616E, 0xBC7B},{0x6170, 0xBCA2},{0x6171, 0xE1C6},{0x6172, 0xE1CA},{0x6173, 0xE1C7},{0x6174, 0xE1CD},{0x6175, 0xBA48},
+ {0x6176, 0xBC79},{0x6177, 0xBA42},{0x6179, 0xE57A},{0x617A, 0xE1CF},{0x617C, 0xBCA1},{0x617E, 0xBCA4},{0x6180, 0xE1CC},{0x6182, 0xBC7E},
+ {0x6183, 0xE579},{0x6189, 0xE57E},{0x618A, 0xBECE},{0x618B, 0xE578},{0x618C, 0xE9A3},{0x618D, 0xE5A9},{0x618E, 0xBCA8},{0x6190, 0xBCA6},
+ {0x6191, 0xBECC},{0x6192, 0xE5A6},{0x6193, 0xE5A2},{0x6194, 0xBCAC},{0x6196, 0xE978},{0x619A, 0xBCAA},{0x619B, 0xE5A1},{0x619D, 0xE976},
+ {0x619F, 0xE5A5},{0x61A1, 0xE5A8},{0x61A2, 0xE57D},{0x61A4, 0xBCAB},{0x61A7, 0xBCA5},{0x61A8, 0xE977},{0x61A9, 0xBECD},{0x61AA, 0xE5A7},
+ {0x61AB, 0xBCA7},{0x61AC, 0xBCA9},{0x61AD, 0xE5A4},{0x61AE, 0xBCAD},{0x61AF, 0xE5A3},{0x61B0, 0xE57C},{0x61B1, 0xE57B},{0x61B2, 0xBECB},
+ {0x61B3, 0xE5AB},{0x61B4, 0xE97A},{0x61B5, 0xECE0},{0x61B6, 0xBED0},{0x61B8, 0xE9A2},{0x61BA, 0xE97E},{0x61BC, 0xECE1},{0x61BE, 0xBED1},
+ {0x61BF, 0xE9A1},{0x61C1, 0xE97C},{0x61C2, 0xC0B4},{0x61C3, 0xECDF},{0x61C5, 0xE979},{0x61C6, 0xE97B},{0x61C7, 0xC0B5},{0x61C8, 0xBED3},
+ {0x61C9, 0xC0B3},{0x61CA, 0xBED2},{0x61CB, 0xC0B7},{0x61CC, 0xE97D},{0x61CD, 0xBECF},{0x61D6, 0xEFCF},{0x61D8, 0xEFC7},{0x61DE, 0xECE7},
+ {0x61DF, 0xEFC8},{0x61E0, 0xECE3},{0x61E3, 0xC256},{0x61E4, 0xECE5},{0x61E5, 0xECE4},{0x61E6, 0xC0B6},{0x61E7, 0xECE2},{0x61E8, 0xECE6},
+ {0x61E9, 0xEFD0},{0x61EA, 0xEFCC},{0x61EB, 0xEFCE},{0x61ED, 0xEFC9},{0x61EE, 0xEFCA},{0x61F0, 0xEFCD},{0x61F1, 0xEFCB},{0x61F2, 0xC367},
+ {0x61F5, 0xC36A},{0x61F6, 0xC369},{0x61F7, 0xC368},{0x61F8, 0xC461},{0x61F9, 0xF44A},{0x61FA, 0xC462},{0x61FB, 0xF241},{0x61FC, 0xC4DF},
+ {0x61FD, 0xF5CC},{0x61FE, 0xC4E0},{0x61FF, 0xC574},{0x6200, 0xC5CA},{0x6201, 0xF7D9},{0x6203, 0xF7DA},{0x6204, 0xF7DB},{0x6207, 0xF9BA},
+ {0x6208, 0xA4E0},{0x6209, 0xC97C},{0x620A, 0xA5B3},{0x620C, 0xA6A6},{0x620D, 0xA6A7},{0x620E, 0xA6A5},{0x6210, 0xA6A8},{0x6211, 0xA7DA},
+ {0x6212, 0xA7D9},{0x6214, 0xCCB1},{0x6215, 0xA9CF},{0x6216, 0xA9CE},{0x6219, 0xD1AF},{0x621A, 0xB1AD},{0x621B, 0xB1AE},{0x621F, 0xB475},
+ {0x6220, 0xDD72},{0x6221, 0xB760},{0x6222, 0xB761},{0x6223, 0xDD74},{0x6224, 0xDD76},{0x6225, 0xDD75},{0x6227, 0xE1D7},{0x6229, 0xE1D6},
+ {0x622A, 0xBA49},{0x622B, 0xE1D8},{0x622D, 0xE5AC},{0x622E, 0xBCAE},{0x6230, 0xBED4},{0x6232, 0xC0B8},{0x6233, 0xC257},{0x6234, 0xC0B9},
+ {0x6236, 0xA4E1},{0x623A, 0xCAE6},{0x623D, 0xCCB2},{0x623E, 0xA9D1},{0x623F, 0xA9D0},{0x6240, 0xA9D2},{0x6241, 0xABF3},{0x6242, 0xCED2},
+ {0x6243, 0xCED3},{0x6246, 0xD1B0},{0x6247, 0xAEB0},{0x6248, 0xB1AF},{0x6249, 0xB476},{0x624A, 0xD951},{0x624B, 0xA4E2},{0x624D, 0xA47E},
+ {0x624E, 0xA4E3},{0x6250, 0xC97D},{0x6251, 0xA5B7},{0x6252, 0xA5B6},{0x6253, 0xA5B4},{0x6254, 0xA5B5},{0x6258, 0xA6AB},{0x6259, 0xC9E9},
+ {0x625A, 0xC9EB},{0x625B, 0xA6AA},{0x625C, 0xC9E3},{0x625E, 0xC9E4},{0x6260, 0xC9EA},{0x6261, 0xC9E6},{0x6262, 0xC9E8},{0x6263, 0xA6A9},
+ {0x6264, 0xC9E5},{0x6265, 0xC9EC},{0x6266, 0xC9E7},{0x626D, 0xA7E1},{0x626E, 0xA7EA},{0x626F, 0xA7E8},{0x6270, 0xCAF0},{0x6271, 0xCAED},
+ {0x6272, 0xCAF5},{0x6273, 0xA7E6},{0x6274, 0xCAF6},{0x6276, 0xA7DF},{0x6277, 0xCAF3},{0x6279, 0xA7E5},{0x627A, 0xCAEF},{0x627B, 0xCAEE},
+ {0x627C, 0xA7E3},{0x627D, 0xCAF4},{0x627E, 0xA7E4},{0x627F, 0xA9D3},{0x6280, 0xA7DE},{0x6281, 0xCAF1},{0x6283, 0xCAE7},{0x6284, 0xA7DB},
+ {0x6286, 0xA7EE},{0x6287, 0xCAEC},{0x6288, 0xCAF2},{0x6289, 0xA7E0},{0x628A, 0xA7E2},{0x628C, 0xCAE8},{0x628E, 0xCAE9},{0x628F, 0xCAEA},
+ {0x6291, 0xA7ED},{0x6292, 0xA7E7},{0x6293, 0xA7EC},{0x6294, 0xCAEB},{0x6295, 0xA7EB},{0x6296, 0xA7DD},{0x6297, 0xA7DC},{0x6298, 0xA7E9},
+ {0x62A8, 0xA9E1},{0x62A9, 0xCCBE},{0x62AA, 0xCCB7},{0x62AB, 0xA9DC},{0x62AC, 0xA9EF},{0x62AD, 0xCCB3},{0x62AE, 0xCCBA},{0x62AF, 0xCCBC},
+ {0x62B0, 0xCCBF},{0x62B1, 0xA9EA},{0x62B3, 0xCCBB},{0x62B4, 0xCCB4},{0x62B5, 0xA9E8},{0x62B6, 0xCCB8},{0x62B8, 0xCCC0},{0x62B9, 0xA9D9},
+ {0x62BB, 0xCCBD},{0x62BC, 0xA9E3},{0x62BD, 0xA9E2},{0x62BE, 0xCCB6},{0x62BF, 0xA9D7},{0x62C2, 0xA9D8},{0x62C4, 0xA9D6},{0x62C6, 0xA9EE},
+ {0x62C7, 0xA9E6},{0x62C8, 0xA9E0},{0x62C9, 0xA9D4},{0x62CA, 0xCCB9},{0x62CB, 0xA9DF},{0x62CC, 0xA9D5},{0x62CD, 0xA9E7},{0x62CE, 0xA9F0},
+ {0x62CF, 0xCED4},{0x62D0, 0xA9E4},{0x62D1, 0xCCB5},{0x62D2, 0xA9DA},{0x62D3, 0xA9DD},{0x62D4, 0xA9DE},{0x62D6, 0xA9EC},{0x62D7, 0xA9ED},
+ {0x62D8, 0xA9EB},{0x62D9, 0xA9E5},{0x62DA, 0xA9E9},{0x62DB, 0xA9DB},{0x62DC, 0xABF4},{0x62EB, 0xCEDA},{0x62EC, 0xAC41},{0x62ED, 0xABF8},
+ {0x62EE, 0xABFA},{0x62EF, 0xAC40},{0x62F0, 0xCEE6},{0x62F1, 0xABFD},{0x62F2, 0xD1B1},{0x62F3, 0xAEB1},{0x62F4, 0xAC43},{0x62F5, 0xCED7},
+ {0x62F6, 0xCEDF},{0x62F7, 0xABFE},{0x62F8, 0xCEDE},{0x62F9, 0xCEDB},{0x62FA, 0xCEE3},{0x62FB, 0xCEE5},{0x62FC, 0xABF7},{0x62FD, 0xABFB},
+ {0x62FE, 0xAC42},{0x62FF, 0xAEB3},{0x6300, 0xCEE0},{0x6301, 0xABF9},{0x6302, 0xAC45},{0x6303, 0xCED9},{0x6307, 0xABFC},{0x6308, 0xAEB2},
+ {0x6309, 0xABF6},{0x630B, 0xCED6},{0x630C, 0xCEDD},{0x630D, 0xCED5},{0x630E, 0xCED8},{0x630F, 0xCEDC},{0x6310, 0xD1B2},{0x6311, 0xAC44},
+ {0x6313, 0xCEE1},{0x6314, 0xCEE2},{0x6315, 0xCEE4},{0x6316, 0xABF5},{0x6328, 0xAEC1},{0x6329, 0xD1BE},{0x632A, 0xAEBF},{0x632B, 0xAEC0},
+ {0x632C, 0xD1B4},{0x632D, 0xD1C4},{0x632F, 0xAEB6},{0x6332, 0xD566},{0x6333, 0xD1C6},{0x6334, 0xD1C0},{0x6336, 0xD1B7},{0x6338, 0xD1C9},
+ {0x6339, 0xD1BA},{0x633A, 0xAEBC},{0x633B, 0xD57D},{0x633C, 0xD1BD},{0x633D, 0xAEBE},{0x633E, 0xAEB5},{0x6340, 0xD1CB},{0x6341, 0xD1BF},
+ {0x6342, 0xAEB8},{0x6343, 0xD1B8},{0x6344, 0xD1B5},{0x6345, 0xD1B6},{0x6346, 0xAEB9},{0x6347, 0xD1C5},{0x6348, 0xD1CC},{0x6349, 0xAEBB},
+ {0x634A, 0xD1BC},{0x634B, 0xD1BB},{0x634C, 0xAEC3},{0x634D, 0xAEC2},{0x634E, 0xAEB4},{0x634F, 0xAEBA},{0x6350, 0xAEBD},{0x6351, 0xD1C8},
+ {0x6354, 0xD1C2},{0x6355, 0xAEB7},{0x6356, 0xD1B3},{0x6357, 0xD1CA},{0x6358, 0xD1C1},{0x6359, 0xD1C3},{0x635A, 0xD1C7},{0x6365, 0xD567},
+ {0x6367, 0xB1B7},{0x6368, 0xB1CB},{0x6369, 0xB1CA},{0x636B, 0xB1BF},{0x636D, 0xD579},{0x636E, 0xD575},{0x636F, 0xD572},{0x6370, 0xD5A6},
+ {0x6371, 0xB1BA},{0x6372, 0xB1B2},{0x6375, 0xD577},{0x6376, 0xB4A8},{0x6377, 0xB1B6},{0x6378, 0xD5A1},{0x637A, 0xB1CC},{0x637B, 0xB1C9},
+ {0x637C, 0xD57B},{0x637D, 0xD56A},{0x6380, 0xB1C8},{0x6381, 0xD5A3},{0x6382, 0xD569},{0x6383, 0xB1BD},{0x6384, 0xB1C1},{0x6385, 0xD5A2},
+ {0x6387, 0xD573},{0x6388, 0xB1C2},{0x6389, 0xB1BC},{0x638A, 0xD568},{0x638C, 0xB478},{0x638D, 0xD5A5},{0x638E, 0xD571},{0x638F, 0xB1C7},
+ {0x6390, 0xD574},{0x6391, 0xD5A4},{0x6392, 0xB1C6},{0x6394, 0xD952},{0x6396, 0xB1B3},{0x6397, 0xD56F},{0x6398, 0xB1B8},{0x6399, 0xB1C3},
+ {0x639B, 0xB1BE},{0x639C, 0xD578},{0x639D, 0xD56E},{0x639E, 0xD56C},{0x639F, 0xD57E},{0x63A0, 0xB1B0},{0x63A1, 0xB1C4},{0x63A2, 0xB1B4},
+ {0x63A3, 0xB477},{0x63A4, 0xD57C},{0x63A5, 0xB1B5},{0x63A7, 0xB1B1},{0x63A8, 0xB1C0},{0x63A9, 0xB1BB},{0x63AA, 0xB1B9},{0x63AB, 0xD570},
+ {0x63AC, 0xB1C5},{0x63AD, 0xD56D},{0x63AE, 0xD57A},{0x63AF, 0xD576},{0x63B0, 0xD954},{0x63B1, 0xD953},{0x63BD, 0xD56B},{0x63BE, 0xD964},
+ {0x63C0, 0xB47A},{0x63C2, 0xD96A},{0x63C3, 0xD959},{0x63C4, 0xD967},{0x63C5, 0xDD77},{0x63C6, 0xB47D},{0x63C7, 0xD96B},{0x63C8, 0xD96E},
+ {0x63C9, 0xB47C},{0x63CA, 0xD95C},{0x63CB, 0xD96D},{0x63CC, 0xD96C},{0x63CD, 0xB47E},{0x63CE, 0xD955},{0x63CF, 0xB479},{0x63D0, 0xB4A3},
+ {0x63D2, 0xB4A1},{0x63D3, 0xD969},{0x63D5, 0xD95F},{0x63D6, 0xB4A5},{0x63D7, 0xD970},{0x63D8, 0xD968},{0x63D9, 0xD971},{0x63DA, 0xB4AD},
+ {0x63DB, 0xB4AB},{0x63DC, 0xD966},{0x63DD, 0xD965},{0x63DF, 0xD963},{0x63E0, 0xD95D},{0x63E1, 0xB4A4},{0x63E3, 0xB4A2},{0x63E4, 0xD1B9},
+ {0x63E5, 0xD956},{0x63E7, 0xDDB7},{0x63E8, 0xD957},{0x63E9, 0xB47B},{0x63EA, 0xB4AA},{0x63EB, 0xDD79},{0x63ED, 0xB4A6},{0x63EE, 0xB4A7},
+ {0x63EF, 0xD958},{0x63F0, 0xD96F},{0x63F1, 0xDD78},{0x63F2, 0xD960},{0x63F3, 0xD95B},{0x63F4, 0xB4A9},{0x63F5, 0xD961},{0x63F6, 0xD95E},
+ {0x63F9, 0xB4AE},{0x6406, 0xB770},{0x6409, 0xDD7C},{0x640A, 0xDDB1},{0x640B, 0xDDB6},{0x640C, 0xDDAA},{0x640D, 0xB76C},{0x640E, 0xDDBB},
+ {0x640F, 0xB769},{0x6410, 0xDD7A},{0x6412, 0xDD7B},{0x6413, 0xB762},{0x6414, 0xB76B},{0x6415, 0xDDA4},{0x6416, 0xB76E},{0x6417, 0xB76F},
+ {0x6418, 0xDDA5},{0x641A, 0xDDB2},{0x641B, 0xDDB8},{0x641C, 0xB76A},{0x641E, 0xB764},{0x641F, 0xDDA3},{0x6420, 0xDD7D},{0x6421, 0xDDBA},
+ {0x6422, 0xDDA8},{0x6423, 0xDDA9},{0x6424, 0xDD7E},{0x6425, 0xDDB4},{0x6426, 0xDDAB},{0x6427, 0xDDB5},{0x6428, 0xDDAD},{0x642A, 0xB765},
+ {0x642B, 0xE1D9},{0x642C, 0xB768},{0x642D, 0xB766},{0x642E, 0xDDB9},{0x642F, 0xDDB0},{0x6430, 0xDDAC},{0x6433, 0xDDA1},{0x6434, 0xBA53},
+ {0x6435, 0xDDAF},{0x6436, 0xB76D},{0x6437, 0xDDA7},{0x6439, 0xDDA6},{0x643D, 0xB767},{0x643E, 0xB763},{0x643F, 0xE1EE},{0x6440, 0xDDB3},
+ {0x6441, 0xDDAE},{0x6443, 0xDDA2},{0x644B, 0xE1E9},{0x644D, 0xE1DA},{0x644E, 0xE1E5},{0x6450, 0xE1EC},{0x6451, 0xBA51},{0x6452, 0xB4AC},
+ {0x6453, 0xE1EA},{0x6454, 0xBA4C},{0x6458, 0xBA4B},{0x6459, 0xE1F1},{0x645B, 0xE1DB},{0x645C, 0xE1E8},{0x645D, 0xE1DC},{0x645E, 0xE1E7},
+ {0x645F, 0xBA4F},{0x6460, 0xE1EB},{0x6461, 0xD962},{0x6465, 0xE1F2},{0x6466, 0xE1E3},{0x6467, 0xBA52},{0x6468, 0xE5BA},{0x6469, 0xBCAF},
+ {0x646B, 0xE1F0},{0x646C, 0xE1EF},{0x646D, 0xBA54},{0x646E, 0xE5AD},{0x646F, 0xBCB0},{0x6470, 0xE5AE},{0x6472, 0xE1DF},{0x6473, 0xE1E0},
+ {0x6474, 0xE1DD},{0x6475, 0xE1E2},{0x6476, 0xE1DE},{0x6477, 0xE1F3},{0x6478, 0xBA4E},{0x6479, 0xBCB1},{0x647A, 0xBA50},{0x647B, 0xBA55},
+ {0x647D, 0xE1E1},{0x647F, 0xE1ED},{0x6482, 0xE1E6},{0x6485, 0xE5B1},{0x6487, 0xBA4A},{0x6488, 0xBCB4},{0x6489, 0xE9AA},{0x648A, 0xE5B6},
+ {0x648B, 0xE5B5},{0x648C, 0xE5B7},{0x648F, 0xE5B4},{0x6490, 0xBCB5},{0x6492, 0xBCBB},{0x6493, 0xBCB8},{0x6495, 0xBCB9},{0x6496, 0xE5AF},
+ {0x6497, 0xE5B2},{0x6498, 0xE5BC},{0x6499, 0xBCC1},{0x649A, 0xBCBF},{0x649C, 0xE5B3},{0x649D, 0xD95A},{0x649E, 0xBCB2},{0x649F, 0xE5B9},
+ {0x64A0, 0xE5B0},{0x64A2, 0xBCC2},{0x64A3, 0xE5B8},{0x64A4, 0xBA4D},{0x64A5, 0xBCB7},{0x64A6, 0xE1E4},{0x64A9, 0xBCBA},{0x64AB, 0xBCBE},
+ {0x64AC, 0xBCC0},{0x64AD, 0xBCBD},{0x64AE, 0xBCBC},{0x64B0, 0xBCB6},{0x64B1, 0xE5BB},{0x64B2, 0xBCB3},{0x64B3, 0xBCC3},{0x64BB, 0xBED8},
+ {0x64BC, 0xBED9},{0x64BD, 0xE9A9},{0x64BE, 0xBEE2},{0x64BF, 0xBEDF},{0x64C1, 0xBED6},{0x64C2, 0xBEDD},{0x64C3, 0xE9AB},{0x64C4, 0xBEDB},
+ {0x64C5, 0xBED5},{0x64C7, 0xBEDC},{0x64C9, 0xE9A8},{0x64CA, 0xC0BB},{0x64CB, 0xBED7},{0x64CD, 0xBEDE},{0x64CE, 0xC0BA},{0x64CF, 0xE9A7},
+ {0x64D0, 0xE9A6},{0x64D2, 0xBEE0},{0x64D4, 0xBEE1},{0x64D6, 0xE9A5},{0x64D7, 0xE9A4},{0x64D8, 0xC0BC},{0x64D9, 0xE9AE},{0x64DA, 0xBEDA},
+ {0x64DB, 0xE9AC},{0x64E0, 0xC0BD},{0x64E2, 0xC0C2},{0x64E3, 0xECEA},{0x64E4, 0xECEC},{0x64E6, 0xC0BF},{0x64E8, 0xECED},{0x64E9, 0xECE9},
+ {0x64EB, 0xECEB},{0x64EC, 0xC0C0},{0x64ED, 0xC0C3},{0x64EF, 0xECE8},{0x64F0, 0xC0BE},{0x64F1, 0xC0C1},{0x64F2, 0xC259},{0x64F3, 0xE9AD},
+ {0x64F4, 0xC258},{0x64F7, 0xC25E},{0x64F8, 0xEFD4},{0x64FA, 0xC25C},{0x64FB, 0xC25D},{0x64FC, 0xEFD7},{0x64FD, 0xEFD3},{0x64FE, 0xC25A},
+ {0x64FF, 0xEFD1},{0x6500, 0xC36B},{0x6501, 0xEFD5},{0x6503, 0xEFD6},{0x6504, 0xEFD2},{0x6506, 0xC25B},{0x6507, 0xF242},{0x6509, 0xF245},
+ {0x650C, 0xF246},{0x650D, 0xF244},{0x650E, 0xF247},{0x650F, 0xC36C},{0x6510, 0xF243},{0x6513, 0xF44E},{0x6514, 0xC464},{0x6515, 0xF44D},
+ {0x6516, 0xF44C},{0x6517, 0xF44B},{0x6518, 0xC463},{0x6519, 0xC465},{0x651B, 0xF5CD},{0x651C, 0xC4E2},{0x651D, 0xC4E1},{0x6520, 0xF6E1},
+ {0x6521, 0xF6E0},{0x6522, 0xF6E3},{0x6523, 0xC5CB},{0x6524, 0xC575},{0x6525, 0xF7DD},{0x6526, 0xF6E2},{0x6529, 0xF7DC},{0x652A, 0xC5CD},
+ {0x652B, 0xC5CC},{0x652C, 0xC5F3},{0x652D, 0xF8A9},{0x652E, 0xF8EF},{0x652F, 0xA4E4},{0x6532, 0xD972},{0x6533, 0xE9AF},{0x6536, 0xA6AC},
+ {0x6537, 0xCAF7},{0x6538, 0xA7F1},{0x6539, 0xA7EF},{0x653B, 0xA7F0},{0x653D, 0xCCC1},{0x653E, 0xA9F1},{0x653F, 0xAC46},{0x6541, 0xCEE7},
+ {0x6543, 0xCEE8},{0x6545, 0xAC47},{0x6546, 0xD1CE},{0x6548, 0xAEC4},{0x6549, 0xAEC5},{0x654A, 0xD1CD},{0x654F, 0xB1D3},{0x6551, 0xB1CF},
+ {0x6553, 0xD5A7},{0x6554, 0xB1D6},{0x6555, 0xB1D5},{0x6556, 0xB1CE},{0x6557, 0xB1D1},{0x6558, 0xB1D4},{0x6559, 0xB1D0},{0x655C, 0xD976},
+ {0x655D, 0xB1CD},{0x655E, 0xB4AF},{0x6562, 0xB4B1},{0x6563, 0xB4B2},{0x6564, 0xD975},{0x6565, 0xD978},{0x6566, 0xB4B0},{0x6567, 0xD973},
+ {0x6568, 0xD977},{0x656A, 0xD974},{0x656C, 0xB771},{0x656F, 0xDDBC},{0x6572, 0xBA56},{0x6573, 0xE1F4},{0x6574, 0xBEE3},{0x6575, 0xBCC4},
+ {0x6576, 0xE5BD},{0x6577, 0xBCC5},{0x6578, 0xBCC6},{0x6579, 0xE5BF},{0x657A, 0xE5BE},{0x657B, 0xE5C0},{0x657C, 0xE9B1},{0x657F, 0xE9B0},
+ {0x6580, 0xECEF},{0x6581, 0xECEE},{0x6582, 0xC0C4},{0x6583, 0xC0C5},{0x6584, 0xF248},{0x6587, 0xA4E5},{0x658C, 0xD979},{0x6590, 0xB4B4},
+ {0x6591, 0xB4B3},{0x6592, 0xDDBD},{0x6594, 0xEFD8},{0x6595, 0xC4E3},{0x6596, 0xF7DE},{0x6597, 0xA4E6},{0x6599, 0xAEC6},{0x659B, 0xB1D8},
+ {0x659C, 0xB1D7},{0x659D, 0xD97A},{0x659E, 0xD97B},{0x659F, 0xB772},{0x65A0, 0xE1F5},{0x65A1, 0xBA57},{0x65A2, 0xE9B2},{0x65A4, 0xA4E7},
+ {0x65A5, 0xA5B8},{0x65A7, 0xA9F2},{0x65A8, 0xCCC2},{0x65AA, 0xCEE9},{0x65AB, 0xAC48},{0x65AC, 0xB1D9},{0x65AE, 0xD97C},{0x65AF, 0xB4B5},
+ {0x65B0, 0xB773},{0x65B2, 0xE5C1},{0x65B3, 0xE5C2},{0x65B6, 0xECF0},{0x65B7, 0xC25F},{0x65B8, 0xF8F0},{0x65B9, 0xA4E8},{0x65BB, 0xCCC3},
+ {0x65BC, 0xA9F3},{0x65BD, 0xAC49},{0x65BF, 0xCEEA},{0x65C1, 0xAEC7},{0x65C2, 0xD1D2},{0x65C3, 0xD1D0},{0x65C4, 0xD1D1},{0x65C5, 0xAEC8},
+ {0x65C6, 0xD1CF},{0x65CB, 0xB1DB},{0x65CC, 0xB1DC},{0x65CD, 0xD5A8},{0x65CE, 0xB1DD},{0x65CF, 0xB1DA},{0x65D0, 0xD97D},{0x65D2, 0xD97E},
+ {0x65D3, 0xDDBE},{0x65D6, 0xBA59},{0x65D7, 0xBA58},{0x65DA, 0xECF1},{0x65DB, 0xEFD9},{0x65DD, 0xF24A},{0x65DE, 0xF249},{0x65DF, 0xF44F},
+ {0x65E1, 0xC95E},{0x65E2, 0xAC4A},{0x65E5, 0xA4E9},{0x65E6, 0xA5B9},{0x65E8, 0xA6AE},{0x65E9, 0xA6AD},{0x65EC, 0xA6AF},{0x65ED, 0xA6B0},
+ {0x65EE, 0xC9EE},{0x65EF, 0xC9ED},{0x65F0, 0xCAF8},{0x65F1, 0xA7F2},{0x65F2, 0xCAFB},{0x65F3, 0xCAFA},{0x65F4, 0xCAF9},{0x65F5, 0xCAFC},
+ {0x65FA, 0xA9F4},{0x65FB, 0xCCC9},{0x65FC, 0xCCC5},{0x65FD, 0xCCCE},{0x6600, 0xA9FB},{0x6602, 0xA9F9},{0x6603, 0xCCCA},{0x6604, 0xCCC6},
+ {0x6605, 0xCCCD},{0x6606, 0xA9F8},{0x6607, 0xAA40},{0x6608, 0xCCC8},{0x6609, 0xCCC4},{0x660A, 0xA9FE},{0x660B, 0xCCCB},{0x660C, 0xA9F7},
+ {0x660D, 0xCCCC},{0x660E, 0xA9FA},{0x660F, 0xA9FC},{0x6610, 0xCCD0},{0x6611, 0xCCCF},{0x6612, 0xCCC7},{0x6613, 0xA9F6},{0x6614, 0xA9F5},
+ {0x6615, 0xA9FD},{0x661C, 0xCEEF},{0x661D, 0xCEF5},{0x661F, 0xAC50},{0x6620, 0xAC4D},{0x6621, 0xCEEC},{0x6622, 0xCEF1},{0x6624, 0xAC53},
+ {0x6625, 0xAC4B},{0x6626, 0xCEF0},{0x6627, 0xAC4E},{0x6628, 0xAC51},{0x662B, 0xCEF3},{0x662D, 0xAC4C},{0x662E, 0xCEF8},{0x662F, 0xAC4F},
+ {0x6631, 0xAC52},{0x6632, 0xCEED},{0x6633, 0xCEF2},{0x6634, 0xCEF6},{0x6635, 0xCEEE},{0x6636, 0xCEEB},{0x6639, 0xCEF7},{0x663A, 0xCEF4},
+ {0x6641, 0xAED0},{0x6642, 0xAEC9},{0x6643, 0xAECC},{0x6645, 0xAECF},{0x6647, 0xD1D5},{0x6649, 0xAECA},{0x664A, 0xD1D3},{0x664C, 0xAECE},
+ {0x664F, 0xAECB},{0x6651, 0xD1D6},{0x6652, 0xAECD},{0x6659, 0xD5AC},{0x665A, 0xB1DF},{0x665B, 0xD5AB},{0x665C, 0xD5AD},{0x665D, 0xB1DE},
+ {0x665E, 0xB1E3},{0x665F, 0xD1D4},{0x6661, 0xD5AA},{0x6662, 0xD5AE},{0x6664, 0xB1E0},{0x6665, 0xD5A9},{0x6666, 0xB1E2},{0x6668, 0xB1E1},
+ {0x666A, 0xD9A7},{0x666C, 0xD9A2},{0x666E, 0xB4B6},{0x666F, 0xB4BA},{0x6670, 0xB4B7},{0x6671, 0xD9A5},{0x6672, 0xD9A8},{0x6674, 0xB4B8},
+ {0x6676, 0xB4B9},{0x6677, 0xB4BE},{0x6678, 0xDDC7},{0x6679, 0xD9A6},{0x667A, 0xB4BC},{0x667B, 0xD9A3},{0x667C, 0xD9A1},{0x667E, 0xB4BD},
+ {0x6680, 0xD9A4},{0x6684, 0xB779},{0x6686, 0xDDBF},{0x6687, 0xB776},{0x6688, 0xB777},{0x6689, 0xB775},{0x668A, 0xDDC4},{0x668B, 0xDDC3},
+ {0x668C, 0xDDC0},{0x668D, 0xB77B},{0x6690, 0xDDC2},{0x6691, 0xB4BB},{0x6694, 0xDDC6},{0x6695, 0xDDC1},{0x6696, 0xB778},{0x6697, 0xB774},
+ {0x6698, 0xB77A},{0x6699, 0xDDC5},{0x669D, 0xBA5C},{0x669F, 0xE1F8},{0x66A0, 0xE1F7},{0x66A1, 0xE1F6},{0x66A2, 0xBA5A},{0x66A8, 0xBA5B},
+ {0x66A9, 0xE5C5},{0x66AA, 0xE5C8},{0x66AB, 0xBCC8},{0x66AE, 0xBCC7},{0x66AF, 0xE5C9},{0x66B0, 0xE5C4},{0x66B1, 0xBCCA},{0x66B2, 0xE5C6},
+ {0x66B4, 0xBCC9},{0x66B5, 0xE5C3},{0x66B7, 0xE5C7},{0x66B8, 0xBEE9},{0x66B9, 0xBEE6},{0x66BA, 0xE9BB},{0x66BB, 0xE9BA},{0x66BD, 0xE9B9},
+ {0x66BE, 0xE9B4},{0x66C0, 0xE9B5},{0x66C4, 0xBEE7},{0x66C6, 0xBEE4},{0x66C7, 0xBEE8},{0x66C8, 0xE9B3},{0x66C9, 0xBEE5},{0x66CA, 0xE9B6},
+ {0x66CB, 0xE9B7},{0x66CC, 0xE9BC},{0x66CF, 0xE9B8},{0x66D2, 0xECF2},{0x66D6, 0xC0C7},{0x66D8, 0xEFDC},{0x66D9, 0xC0C6},{0x66DA, 0xEFDA},
+ {0x66DB, 0xEFDB},{0x66DC, 0xC260},{0x66DD, 0xC36E},{0x66DE, 0xF24B},{0x66E0, 0xC36D},{0x66E3, 0xF451},{0x66E4, 0xF452},{0x66E6, 0xC466},
+ {0x66E8, 0xF450},{0x66E9, 0xC4E4},{0x66EB, 0xF7DF},{0x66EC, 0xC5CE},{0x66ED, 0xF8AA},{0x66EE, 0xF8AB},{0x66F0, 0xA4EA},{0x66F2, 0xA6B1},
+ {0x66F3, 0xA6B2},{0x66F4, 0xA7F3},{0x66F6, 0xCCD1},{0x66F7, 0xAC54},{0x66F8, 0xAED1},{0x66F9, 0xB1E4},{0x66FC, 0xB0D2},{0x66FE, 0xB4BF},
+ {0x66FF, 0xB4C0},{0x6700, 0xB3CC},{0x6701, 0xD9A9},{0x6703, 0xB77C},{0x6704, 0xE1FA},{0x6705, 0xE1F9},{0x6708, 0xA4EB},{0x6709, 0xA6B3},
+ {0x670A, 0xCCD2},{0x670B, 0xAA42},{0x670D, 0xAA41},{0x670F, 0xCEF9},{0x6710, 0xCEFA},{0x6712, 0xD1D7},{0x6713, 0xD1D8},{0x6714, 0xAED2},
+ {0x6715, 0xAED3},{0x6717, 0xAED4},{0x6718, 0xD5AF},{0x671B, 0xB1E6},{0x671D, 0xB4C2},{0x671F, 0xB4C1},{0x6720, 0xDDC8},{0x6721, 0xDF7A},
+ {0x6722, 0xE1FB},{0x6723, 0xE9BD},{0x6726, 0xC261},{0x6727, 0xC467},{0x6728, 0xA4EC},{0x672A, 0xA5BC},{0x672B, 0xA5BD},{0x672C, 0xA5BB},
+ {0x672D, 0xA5BE},{0x672E, 0xA5BA},{0x6731, 0xA6B6},{0x6733, 0xC9F6},{0x6734, 0xA6B5},{0x6735, 0xA6B7},{0x6738, 0xC9F1},{0x6739, 0xC9F0},
+ {0x673A, 0xC9F3},{0x673B, 0xC9F2},{0x673C, 0xC9F5},{0x673D, 0xA6B4},{0x673E, 0xC9EF},{0x673F, 0xC9F4},{0x6745, 0xCAFD},{0x6746, 0xA7FD},
+ {0x6747, 0xCAFE},{0x6748, 0xCB43},{0x6749, 0xA7FC},{0x674B, 0xCB47},{0x674C, 0xCB42},{0x674D, 0xCB45},{0x674E, 0xA7F5},{0x674F, 0xA7F6},
+ {0x6750, 0xA7F7},{0x6751, 0xA7F8},{0x6753, 0xA840},{0x6755, 0xCB41},{0x6756, 0xA7FA},{0x6757, 0xA841},{0x6759, 0xCB40},{0x675A, 0xCB46},
+ {0x675C, 0xA7F9},{0x675D, 0xCB44},{0x675E, 0xA7FB},{0x675F, 0xA7F4},{0x6760, 0xA7FE},{0x676A, 0xAA57},{0x676C, 0xCCD4},{0x676D, 0xAA43},
+ {0x676F, 0xAA4D},{0x6770, 0xAA4E},{0x6771, 0xAA46},{0x6772, 0xAA58},{0x6773, 0xAA48},{0x6774, 0xCCDC},{0x6775, 0xAA53},{0x6776, 0xCCD7},
+ {0x6777, 0xAA49},{0x6778, 0xCCE6},{0x6779, 0xCCE7},{0x677A, 0xCCDF},{0x677B, 0xCCD8},{0x677C, 0xAA56},{0x677D, 0xCCE4},{0x677E, 0xAA51},
+ {0x677F, 0xAA4F},{0x6781, 0xCCE5},{0x6783, 0xCCE3},{0x6784, 0xCCDB},{0x6785, 0xCCD3},{0x6786, 0xCCDA},{0x6787, 0xAA4A},{0x6789, 0xAA50},
+ {0x678B, 0xAA44},{0x678C, 0xCCDE},{0x678D, 0xCCDD},{0x678E, 0xCCD5},{0x6790, 0xAA52},{0x6791, 0xCCE1},{0x6792, 0xCCD6},{0x6793, 0xAA55},
+ {0x6794, 0xCCE8},{0x6795, 0xAA45},{0x6797, 0xAA4C},{0x6798, 0xCCD9},{0x6799, 0xCCE2},{0x679A, 0xAA54},{0x679C, 0xAA47},{0x679D, 0xAA4B},
+ {0x679F, 0xCCE0},{0x67AE, 0xCF5B},{0x67AF, 0xAC5C},{0x67B0, 0xAC69},{0x67B2, 0xCF56},{0x67B3, 0xCF4C},{0x67B4, 0xAC62},{0x67B5, 0xCF4A},
+ {0x67B6, 0xAC5B},{0x67B7, 0xCF45},{0x67B8, 0xAC65},{0x67B9, 0xCF52},{0x67BA, 0xCEFE},{0x67BB, 0xCF41},{0x67C0, 0xCF44},{0x67C1, 0xCEFB},
+ {0x67C2, 0xCF51},{0x67C3, 0xCF61},{0x67C4, 0xAC60},{0x67C5, 0xCF46},{0x67C6, 0xCF58},{0x67C8, 0xCEFD},{0x67C9, 0xCF5F},{0x67CA, 0xCF60},
+ {0x67CB, 0xCF63},{0x67CC, 0xCF5A},{0x67CD, 0xCF4B},{0x67CE, 0xCF53},{0x67CF, 0xAC66},{0x67D0, 0xAC59},{0x67D1, 0xAC61},{0x67D2, 0xAC6D},
+ {0x67D3, 0xAC56},{0x67D4, 0xAC58},{0x67D8, 0xCF43},{0x67D9, 0xAC6A},{0x67DA, 0xAC63},{0x67DB, 0xCF5D},{0x67DC, 0xCF40},{0x67DD, 0xAC6C},
+ {0x67DE, 0xAC67},{0x67DF, 0xCF49},{0x67E2, 0xAC6B},{0x67E3, 0xCF50},{0x67E4, 0xCF48},{0x67E5, 0xAC64},{0x67E6, 0xCF5C},{0x67E7, 0xCF54},
+ {0x67E9, 0xAC5E},{0x67EA, 0xCF62},{0x67EB, 0xCF47},{0x67EC, 0xAC5A},{0x67ED, 0xCF59},{0x67EE, 0xCF4F},{0x67EF, 0xAC5F},{0x67F0, 0xCF55},
+ {0x67F1, 0xAC57},{0x67F2, 0xCEFC},{0x67F3, 0xAC68},{0x67F4, 0xAEE3},{0x67F5, 0xAC5D},{0x67F6, 0xCF4E},{0x67F7, 0xCF4D},{0x67F8, 0xCF42},
+ {0x67FA, 0xCF5E},{0x67FC, 0xCF57},{0x67FF, 0xAC55},{0x6812, 0xD1EC},{0x6813, 0xAEEA},{0x6814, 0xD1ED},{0x6816, 0xD1E1},{0x6817, 0xAEDF},
+ {0x6818, 0xAEEB},{0x681A, 0xD1DA},{0x681C, 0xD1E3},{0x681D, 0xD1EB},{0x681F, 0xD1D9},{0x6820, 0xD1F4},{0x6821, 0xAED5},{0x6825, 0xD1F3},
+ {0x6826, 0xD1EE},{0x6828, 0xD1EF},{0x6829, 0xAEDD},{0x682A, 0xAEE8},{0x682B, 0xD1E5},{0x682D, 0xD1E6},{0x682E, 0xD1F0},{0x682F, 0xD1E7},
+ {0x6831, 0xD1E2},{0x6832, 0xD1DC},{0x6833, 0xD1DD},{0x6834, 0xD1EA},{0x6835, 0xD1E4},{0x6838, 0xAED6},{0x6839, 0xAEDA},{0x683A, 0xD1F2},
+ {0x683B, 0xD1DE},{0x683C, 0xAEE6},{0x683D, 0xAEE2},{0x6840, 0xAEE5},{0x6841, 0xAEEC},{0x6842, 0xAEDB},{0x6843, 0xAEE7},{0x6844, 0xD1E9},
+ {0x6845, 0xAEE9},{0x6846, 0xAED8},{0x6848, 0xAED7},{0x6849, 0xD1DB},{0x684B, 0xD1DF},{0x684C, 0xAEE0},{0x684D, 0xD1F1},{0x684E, 0xD1E8},
+ {0x684F, 0xD1E0},{0x6850, 0xAEE4},{0x6851, 0xAEE1},{0x6853, 0xAED9},{0x6854, 0xAEDC},{0x686B, 0xD5C4},{0x686D, 0xD5B4},{0x686E, 0xD5B5},
+ {0x686F, 0xD5B9},{0x6871, 0xD5C8},{0x6872, 0xD5C5},{0x6874, 0xD5BE},{0x6875, 0xD5BD},{0x6876, 0xB1ED},{0x6877, 0xD5C1},{0x6878, 0xD5D0},
+ {0x6879, 0xD5B0},{0x687B, 0xD5D1},{0x687C, 0xD5C3},{0x687D, 0xD5D5},{0x687E, 0xD5C9},{0x687F, 0xB1EC},{0x6880, 0xD5C7},{0x6881, 0xB1E7},
+ {0x6882, 0xB1FC},{0x6883, 0xB1F2},{0x6885, 0xB1F6},{0x6886, 0xB1F5},{0x6887, 0xD5B1},{0x6889, 0xD5CE},{0x688A, 0xD5D4},{0x688B, 0xD5CC},
+ {0x688C, 0xD5D3},{0x688F, 0xD5C0},{0x6890, 0xD5B2},{0x6891, 0xD5D2},{0x6892, 0xD5C2},{0x6893, 0xB1EA},{0x6894, 0xB1F7},{0x6896, 0xD5CB},
+ {0x6897, 0xB1F0},{0x689B, 0xD5CA},{0x689C, 0xD5B3},{0x689D, 0xB1F8},{0x689F, 0xB1FA},{0x68A0, 0xD5CD},{0x68A1, 0xB1FB},{0x68A2, 0xB1E9},
+ {0x68A3, 0xD5BA},{0x68A4, 0xD5CF},{0x68A7, 0xB1EF},{0x68A8, 0xB1F9},{0x68A9, 0xD5BC},{0x68AA, 0xD5C6},{0x68AB, 0xD5B7},{0x68AC, 0xD5BB},
+ {0x68AD, 0xB1F4},{0x68AE, 0xD5B6},{0x68AF, 0xB1E8},{0x68B0, 0xB1F1},{0x68B1, 0xB1EE},{0x68B2, 0xD5BF},{0x68B3, 0xAEDE},{0x68B4, 0xD9C0},
+ {0x68B5, 0xB1EB},{0x68C4, 0xB1F3},{0x68C6, 0xD9C3},{0x68C7, 0xD9D9},{0x68C8, 0xD9CE},{0x68C9, 0xB4D6},{0x68CB, 0xB4D1},{0x68CC, 0xD9BD},
+ {0x68CD, 0xB4D2},{0x68CE, 0xD9CD},{0x68D0, 0xD9C6},{0x68D1, 0xD9D3},{0x68D2, 0xB4CE},{0x68D3, 0xD9AB},{0x68D4, 0xD9D5},{0x68D5, 0xB4C4},
+ {0x68D6, 0xD9B3},{0x68D7, 0xB4C7},{0x68D8, 0xB4C6},{0x68DA, 0xB4D7},{0x68DC, 0xD9AD},{0x68DD, 0xD9CF},{0x68DE, 0xD9D0},{0x68DF, 0xB4C9},
+ {0x68E0, 0xB4C5},{0x68E1, 0xD9BB},{0x68E3, 0xB4D0},{0x68E4, 0xD9B6},{0x68E6, 0xD9D1},{0x68E7, 0xB4CC},{0x68E8, 0xD9C9},{0x68E9, 0xD9D6},
+ {0x68EA, 0xD9B0},{0x68EB, 0xD9B5},{0x68EC, 0xD9AF},{0x68EE, 0xB4CB},{0x68EF, 0xD9C2},{0x68F0, 0xDDDE},{0x68F1, 0xD9B1},{0x68F2, 0xB4CF},
+ {0x68F3, 0xD9BA},{0x68F4, 0xD9D2},{0x68F5, 0xB4CA},{0x68F6, 0xD9B7},{0x68F7, 0xD9B4},{0x68F8, 0xD9C5},{0x68F9, 0xB4CD},{0x68FA, 0xB4C3},
+ {0x68FB, 0xB4D9},{0x68FC, 0xD9C8},{0x68FD, 0xD9C7},{0x6904, 0xD9AC},{0x6905, 0xB4C8},{0x6906, 0xD9D4},{0x6907, 0xD9BC},{0x6908, 0xD9BE},
+ {0x690A, 0xD9CB},{0x690B, 0xD9CA},{0x690C, 0xD9AA},{0x690D, 0xB4D3},{0x690E, 0xB4D5},{0x690F, 0xD9B2},{0x6910, 0xD9B9},{0x6911, 0xD9C1},
+ {0x6912, 0xB4D4},{0x6913, 0xD9B8},{0x6914, 0xD9C4},{0x6915, 0xD9D7},{0x6917, 0xD9CC},{0x6925, 0xD9D8},{0x692A, 0xD9AE},{0x692F, 0xDDF2},
+ {0x6930, 0xB7A6},{0x6932, 0xDDF0},{0x6933, 0xDDDB},{0x6934, 0xDDE0},{0x6935, 0xDDD9},{0x6937, 0xDDEC},{0x6938, 0xDDCB},{0x6939, 0xDDD2},
+ {0x693B, 0xDDEA},{0x693C, 0xDDF4},{0x693D, 0xDDDC},{0x693F, 0xDDCF},{0x6940, 0xDDE2},{0x6941, 0xDDE7},{0x6942, 0xDDD3},{0x6944, 0xDDE4},
+ {0x6945, 0xDDD0},{0x6948, 0xDDD7},{0x6949, 0xDDD8},{0x694A, 0xB7A8},{0x694B, 0xDDEB},{0x694C, 0xDDE9},{0x694E, 0xDDCC},{0x694F, 0xDDEE},
+ {0x6951, 0xDDEF},{0x6952, 0xDDF1},{0x6953, 0xB7AC},{0x6954, 0xB7A4},{0x6956, 0xD5B8},{0x6957, 0xDDD4},{0x6958, 0xDDE6},{0x6959, 0xDDD5},
+ {0x695A, 0xB7A1},{0x695B, 0xB7B1},{0x695C, 0xDDED},{0x695D, 0xB7AF},{0x695E, 0xB7AB},{0x695F, 0xDDCA},{0x6960, 0xB7A3},{0x6962, 0xDDCD},
+ {0x6963, 0xB7B0},{0x6965, 0xDDDD},{0x6966, 0xDDC9},{0x6968, 0xB7A9},{0x6969, 0xDDE1},{0x696A, 0xDDD1},{0x696B, 0xB7AA},{0x696C, 0xDDDA},
+ {0x696D, 0xB77E},{0x696E, 0xB4D8},{0x696F, 0xDDE3},{0x6970, 0xD9BF},{0x6971, 0xDDCE},{0x6974, 0xDDE8},{0x6975, 0xB7A5},{0x6976, 0xDDE5},
+ {0x6977, 0xB7A2},{0x6978, 0xDDDF},{0x6979, 0xB7AD},{0x697A, 0xDDD6},{0x697B, 0xDDF3},{0x6982, 0xB7A7},{0x6983, 0xDEC6},{0x6986, 0xB7AE},
+ {0x698D, 0xE24A},{0x698E, 0xE248},{0x6990, 0xE25E},{0x6991, 0xE246},{0x6993, 0xE258},{0x6994, 0xB77D},{0x6995, 0xBA5F},{0x6996, 0xE242},
+ {0x6997, 0xE25D},{0x6999, 0xE247},{0x699A, 0xE255},{0x699B, 0xBA64},{0x699C, 0xBA5D},{0x699E, 0xE25B},{0x69A0, 0xE240},{0x69A1, 0xE25A},
+ {0x69A3, 0xBA6F},{0x69A4, 0xE251},{0x69A5, 0xE261},{0x69A6, 0xBA6D},{0x69A7, 0xE249},{0x69A8, 0xBA5E},{0x69A9, 0xE24B},{0x69AA, 0xE259},
+ {0x69AB, 0xBA67},{0x69AC, 0xE244},{0x69AD, 0xBA6B},{0x69AE, 0xBA61},{0x69AF, 0xE24D},{0x69B0, 0xE243},{0x69B1, 0xE1FC},{0x69B3, 0xE257},
+ {0x69B4, 0xBA68},{0x69B5, 0xE260},{0x69B6, 0xE1FD},{0x69B7, 0xBA65},{0x69B9, 0xE253},{0x69BB, 0xBA66},{0x69BC, 0xE245},{0x69BD, 0xE250},
+ {0x69BE, 0xE24C},{0x69BF, 0xE24E},{0x69C1, 0xBA60},{0x69C2, 0xE25F},{0x69C3, 0xBA6E},{0x69C4, 0xE24F},{0x69C6, 0xE262},{0x69C9, 0xE1FE},
+ {0x69CA, 0xE254},{0x69CB, 0xBA63},{0x69CC, 0xBA6C},{0x69CD, 0xBA6A},{0x69CE, 0xE241},{0x69CF, 0xE256},{0x69D0, 0xBA69},{0x69D3, 0xBA62},
+ {0x69D4, 0xE252},{0x69D9, 0xE25C},{0x69E2, 0xE5D5},{0x69E4, 0xE5D1},{0x69E5, 0xE5CD},{0x69E6, 0xE5E1},{0x69E7, 0xE5DE},{0x69E8, 0xBCCD},
+ {0x69EB, 0xE5E5},{0x69EC, 0xE5D4},{0x69ED, 0xBCD8},{0x69EE, 0xE5DB},{0x69F1, 0xE5D0},{0x69F2, 0xE5DA},{0x69F3, 0xBCD5},{0x69F4, 0xE5EE},
+ {0x69F6, 0xE5EB},{0x69F7, 0xE5DD},{0x69F8, 0xE5CE},{0x69FB, 0xE5E2},{0x69FC, 0xE5E4},{0x69FD, 0xBCD1},{0x69FE, 0xE5D8},{0x69FF, 0xE5D3},
+ {0x6A00, 0xE5CA},{0x6A01, 0xBCCE},{0x6A02, 0xBCD6},{0x6A04, 0xE5E7},{0x6A05, 0xBCD7},{0x6A06, 0xE5CB},{0x6A07, 0xE5ED},{0x6A08, 0xE5E0},
+ {0x6A09, 0xE5E6},{0x6A0A, 0xBCD4},{0x6A0D, 0xE5E3},{0x6A0F, 0xE5EA},{0x6A11, 0xBCD9},{0x6A13, 0xBCD3},{0x6A14, 0xE5DC},{0x6A15, 0xE5CF},
+ {0x6A16, 0xE5EF},{0x6A17, 0xE5CC},{0x6A18, 0xE5E8},{0x6A19, 0xBCD0},{0x6A1B, 0xE5D6},{0x6A1D, 0xE5D7},{0x6A1E, 0xBCCF},{0x6A1F, 0xBCCC},
+ {0x6A20, 0xE5D2},{0x6A21, 0xBCD2},{0x6A23, 0xBCCB},{0x6A25, 0xE5E9},{0x6A26, 0xE5EC},{0x6A27, 0xE5D9},{0x6A28, 0xE9CA},{0x6A32, 0xE9C2},
+ {0x6A34, 0xE9BE},{0x6A35, 0xBEF6},{0x6A38, 0xBEEB},{0x6A39, 0xBEF0},{0x6A3A, 0xBEEC},{0x6A3B, 0xE9CC},{0x6A3C, 0xE9D7},{0x6A3D, 0xBEEA},
+ {0x6A3E, 0xE9C4},{0x6A3F, 0xE9CD},{0x6A40, 0xE5DF},{0x6A41, 0xE9CE},{0x6A44, 0xBEF1},{0x6A46, 0xE9DD},{0x6A47, 0xBEF5},{0x6A48, 0xBEF8},
+ {0x6A49, 0xE9C0},{0x6A4B, 0xBEF4},{0x6A4D, 0xE9DB},{0x6A4E, 0xE9DC},{0x6A4F, 0xE9D2},{0x6A50, 0xE9D1},{0x6A51, 0xE9C9},{0x6A54, 0xE9D3},
+ {0x6A55, 0xE9DA},{0x6A56, 0xE9D9},{0x6A58, 0xBEEF},{0x6A59, 0xBEED},{0x6A5A, 0xE9CB},{0x6A5B, 0xE9C8},{0x6A5D, 0xE9C5},{0x6A5E, 0xE9D8},
+ {0x6A5F, 0xBEF7},{0x6A60, 0xE9D6},{0x6A61, 0xBEF3},{0x6A62, 0xBEF2},{0x6A64, 0xE9D0},{0x6A66, 0xE9BF},{0x6A67, 0xE9C1},{0x6A68, 0xE9C3},
+ {0x6A69, 0xE9D5},{0x6A6A, 0xE9CF},{0x6A6B, 0xBEEE},{0x6A6D, 0xE9C6},{0x6A6F, 0xE9D4},{0x6A76, 0xE9C7},{0x6A7E, 0xC0CF},{0x6A7F, 0xED45},
+ {0x6A80, 0xC0C8},{0x6A81, 0xECF5},{0x6A83, 0xED41},{0x6A84, 0xC0CA},{0x6A85, 0xED48},{0x6A87, 0xECFC},{0x6A89, 0xECF7},{0x6A8C, 0xED49},
+ {0x6A8D, 0xECF3},{0x6A8E, 0xECFE},{0x6A90, 0xC0D1},{0x6A91, 0xED44},{0x6A92, 0xED4A},{0x6A93, 0xECFD},{0x6A94, 0xC0C9},{0x6A95, 0xED40},
+ {0x6A96, 0xECF4},{0x6A97, 0xC0D0},{0x6A9A, 0xED47},{0x6A9B, 0xECF9},{0x6A9C, 0xC0CC},{0x6A9E, 0xECFB},{0x6A9F, 0xECF8},{0x6AA0, 0xC0D2},
+ {0x6AA1, 0xECFA},{0x6AA2, 0xC0CB},{0x6AA3, 0xC0CE},{0x6AA4, 0xED43},{0x6AA5, 0xECF6},{0x6AA6, 0xED46},{0x6AA8, 0xED42},{0x6AAC, 0xC263},
+ {0x6AAD, 0xEFE7},{0x6AAE, 0xC268},{0x6AAF, 0xC269},{0x6AB3, 0xC262},{0x6AB4, 0xEFE6},{0x6AB6, 0xEFE3},{0x6AB7, 0xEFE4},{0x6AB8, 0xC266},
+ {0x6AB9, 0xEFDE},{0x6ABA, 0xEFE2},{0x6ABB, 0xC265},{0x6ABD, 0xEFDF},{0x6AC2, 0xC267},{0x6AC3, 0xC264},{0x6AC5, 0xEFDD},{0x6AC6, 0xEFE1},
+ {0x6AC7, 0xEFE5},{0x6ACB, 0xF251},{0x6ACC, 0xF24E},{0x6ACD, 0xF257},{0x6ACF, 0xF256},{0x6AD0, 0xF254},{0x6AD1, 0xF24F},{0x6AD3, 0xC372},
+ {0x6AD9, 0xF250},{0x6ADA, 0xC371},{0x6ADB, 0xC0CD},{0x6ADC, 0xF253},{0x6ADD, 0xC370},{0x6ADE, 0xF258},{0x6ADF, 0xF252},{0x6AE0, 0xF24D},
+ {0x6AE1, 0xEFE0},{0x6AE5, 0xC36F},{0x6AE7, 0xF24C},{0x6AE8, 0xF456},{0x6AEA, 0xF455},{0x6AEB, 0xF255},{0x6AEC, 0xC468},{0x6AEE, 0xF459},
+ {0x6AEF, 0xF45A},{0x6AF0, 0xF454},{0x6AF1, 0xF458},{0x6AF3, 0xF453},{0x6AF8, 0xF5D1},{0x6AF9, 0xF457},{0x6AFA, 0xC4E7},{0x6AFB, 0xC4E5},
+ {0x6AFC, 0xF5CF},{0x6B00, 0xF5D2},{0x6B02, 0xF5CE},{0x6B03, 0xF5D0},{0x6B04, 0xC4E6},{0x6B08, 0xF6E5},{0x6B09, 0xF6E6},{0x6B0A, 0xC576},
+ {0x6B0B, 0xF6E4},{0x6B0F, 0xF7E2},{0x6B10, 0xC5CF},{0x6B11, 0xF7E0},{0x6B12, 0xF7E1},{0x6B13, 0xF8AC},{0x6B16, 0xC656},{0x6B17, 0xF8F3},
+ {0x6B18, 0xF8F1},{0x6B19, 0xF8F2},{0x6B1A, 0xF8F4},{0x6B1E, 0xF9BB},{0x6B20, 0xA4ED},{0x6B21, 0xA6B8},{0x6B23, 0xAA59},{0x6B25, 0xCCE9},
+ {0x6B28, 0xCF64},{0x6B2C, 0xD1F5},{0x6B2D, 0xD1F7},{0x6B2F, 0xD1F6},{0x6B31, 0xD1F8},{0x6B32, 0xB1FD},{0x6B33, 0xD5D7},{0x6B34, 0xD1F9},
+ {0x6B36, 0xD5D6},{0x6B37, 0xD5D8},{0x6B38, 0xD5D9},{0x6B39, 0xD9DA},{0x6B3A, 0xB4DB},{0x6B3B, 0xD9DB},{0x6B3C, 0xD9DD},{0x6B3D, 0xB4DC},
+ {0x6B3E, 0xB4DA},{0x6B3F, 0xD9DC},{0x6B41, 0xDDFA},{0x6B42, 0xDDF8},{0x6B43, 0xDDF7},{0x6B45, 0xDDF6},{0x6B46, 0xDDF5},{0x6B47, 0xB7B2},
+ {0x6B48, 0xDDF9},{0x6B49, 0xBA70},{0x6B4A, 0xE263},{0x6B4B, 0xE265},{0x6B4C, 0xBA71},{0x6B4D, 0xE264},{0x6B4E, 0xBCDB},{0x6B50, 0xBCDA},
+ {0x6B51, 0xE5F0},{0x6B54, 0xE9DF},{0x6B55, 0xE9DE},{0x6B56, 0xE9E0},{0x6B59, 0xBEF9},{0x6B5B, 0xED4B},{0x6B5C, 0xC0D3},{0x6B5E, 0xEFE8},
+ {0x6B5F, 0xC26A},{0x6B60, 0xF259},{0x6B61, 0xC577},{0x6B62, 0xA4EE},{0x6B63, 0xA5BF},{0x6B64, 0xA6B9},{0x6B65, 0xA842},{0x6B66, 0xAA5A},
+ {0x6B67, 0xAA5B},{0x6B6A, 0xAC6E},{0x6B6D, 0xD1FA},{0x6B72, 0xB7B3},{0x6B76, 0xE6D1},{0x6B77, 0xBEFA},{0x6B78, 0xC26B},{0x6B79, 0xA4EF},
+ {0x6B7B, 0xA6BA},{0x6B7E, 0xCCEB},{0x6B7F, 0xAA5C},{0x6B80, 0xCCEA},{0x6B82, 0xCF65},{0x6B83, 0xAC6F},{0x6B84, 0xCF66},{0x6B86, 0xAC70},
+ {0x6B88, 0xD1FC},{0x6B89, 0xAEEE},{0x6B8A, 0xAEED},{0x6B8C, 0xD5DE},{0x6B8D, 0xD5DC},{0x6B8E, 0xD5DD},{0x6B8F, 0xD5DB},{0x6B91, 0xD5DA},
+ {0x6B94, 0xD9DE},{0x6B95, 0xD9E1},{0x6B96, 0xB4DE},{0x6B97, 0xD9DF},{0x6B98, 0xB4DD},{0x6B99, 0xD9E0},{0x6B9B, 0xDDFB},{0x6B9E, 0xE266},
+ {0x6B9F, 0xE267},{0x6BA0, 0xE268},{0x6BA2, 0xE5F3},{0x6BA3, 0xE5F2},{0x6BA4, 0xBCDC},{0x6BA5, 0xE5F1},{0x6BA6, 0xE5F4},{0x6BA7, 0xE9E1},
+ {0x6BAA, 0xE9E2},{0x6BAB, 0xE9E3},{0x6BAD, 0xED4C},{0x6BAE, 0xC0D4},{0x6BAF, 0xC26C},{0x6BB0, 0xF25A},{0x6BB2, 0xC4E8},{0x6BB3, 0xC95F},
+ {0x6BB5, 0xAC71},{0x6BB6, 0xCF67},{0x6BB7, 0xAEEF},{0x6BBA, 0xB1FE},{0x6BBC, 0xB4DF},{0x6BBD, 0xD9E2},{0x6BBF, 0xB7B5},{0x6BC0, 0xB7B4},
+ {0x6BC3, 0xE269},{0x6BC4, 0xE26A},{0x6BC5, 0xBCDD},{0x6BC6, 0xBCDE},{0x6BC7, 0xE9E5},{0x6BC8, 0xE9E4},{0x6BC9, 0xEFE9},{0x6BCA, 0xF7E3},
+ {0x6BCB, 0xA4F0},{0x6BCC, 0xC960},{0x6BCD, 0xA5C0},{0x6BCF, 0xA843},{0x6BD0, 0xCB48},{0x6BD2, 0xAC72},{0x6BD3, 0xB7B6},{0x6BD4, 0xA4F1},
+ {0x6BD6, 0xCF68},{0x6BD7, 0xAC73},{0x6BD8, 0xCF69},{0x6BDA, 0xC0D5},{0x6BDB, 0xA4F2},{0x6BDE, 0xCCEC},{0x6BE0, 0xCF6A},{0x6BE2, 0xD242},
+ {0x6BE3, 0xD241},{0x6BE4, 0xD1FE},{0x6BE6, 0xD1FD},{0x6BE7, 0xD243},{0x6BE8, 0xD240},{0x6BEB, 0xB240},{0x6BEC, 0xB241},{0x6BEF, 0xB4E0},
+ {0x6BF0, 0xD9E3},{0x6BF2, 0xD9E4},{0x6BF3, 0xD9E5},{0x6BF7, 0xDE41},{0x6BF8, 0xDE42},{0x6BF9, 0xDE40},{0x6BFB, 0xDDFD},{0x6BFC, 0xDDFE},
+ {0x6BFD, 0xB7B7},{0x6BFE, 0xE26B},{0x6BFF, 0xE5F7},{0x6C00, 0xE5F6},{0x6C01, 0xE5F5},{0x6C02, 0xE5F8},{0x6C03, 0xE9E7},{0x6C04, 0xE9E6},
+ {0x6C05, 0xBEFB},{0x6C06, 0xE9E8},{0x6C08, 0xC0D6},{0x6C09, 0xED4D},{0x6C0B, 0xEFEA},{0x6C0C, 0xF25B},{0x6C0D, 0xF6E7},{0x6C0F, 0xA4F3},
+ {0x6C10, 0xA5C2},{0x6C11, 0xA5C1},{0x6C13, 0xAA5D},{0x6C14, 0xC961},{0x6C15, 0xC97E},{0x6C16, 0xA6BB},{0x6C18, 0xC9F7},{0x6C19, 0xCB49},
+ {0x6C1A, 0xCB4A},{0x6C1B, 0xAA5E},{0x6C1D, 0xCCED},{0x6C1F, 0xAC74},{0x6C20, 0xCF6B},{0x6C21, 0xCF6C},{0x6C23, 0xAEF0},{0x6C24, 0xAEF4},
+ {0x6C25, 0xD244},{0x6C26, 0xAEF3},{0x6C27, 0xAEF1},{0x6C28, 0xAEF2},{0x6C2A, 0xD5DF},{0x6C2B, 0xB242},{0x6C2C, 0xB4E3},{0x6C2E, 0xB4E1},
+ {0x6C2F, 0xB4E2},{0x6C30, 0xD9E6},{0x6C33, 0xBA72},{0x6C34, 0xA4F4},{0x6C36, 0xC9A1},{0x6C38, 0xA5C3},{0x6C3B, 0xC9A4},{0x6C3E, 0xA5C6},
+ {0x6C3F, 0xC9A3},{0x6C40, 0xA5C5},{0x6C41, 0xA5C4},{0x6C42, 0xA844},{0x6C43, 0xC9A2},{0x6C46, 0xC9F8},{0x6C4A, 0xC9FC},{0x6C4B, 0xC9FE},
+ {0x6C4C, 0xCA40},{0x6C4D, 0xA6C5},{0x6C4E, 0xA6C6},{0x6C4F, 0xC9FB},{0x6C50, 0xA6C1},{0x6C52, 0xC9F9},{0x6C54, 0xC9FD},{0x6C55, 0xA6C2},
+ {0x6C57, 0xA6BD},{0x6C59, 0xA6BE},{0x6C5B, 0xA6C4},{0x6C5C, 0xC9FA},{0x6C5D, 0xA6BC},{0x6C5E, 0xA845},{0x6C5F, 0xA6BF},{0x6C60, 0xA6C0},
+ {0x6C61, 0xA6C3},{0x6C65, 0xCB5B},{0x6C66, 0xCB59},{0x6C67, 0xCB4C},{0x6C68, 0xA851},{0x6C69, 0xCB53},{0x6C6A, 0xA84C},{0x6C6B, 0xCB4D},
+ {0x6C6D, 0xCB55},{0x6C6F, 0xCB52},{0x6C70, 0xA84F},{0x6C71, 0xCB51},{0x6C72, 0xA856},{0x6C73, 0xCB5A},{0x6C74, 0xA858},{0x6C76, 0xA85A},
+ {0x6C78, 0xCB4B},{0x6C7A, 0xA84D},{0x6C7B, 0xCB5C},{0x6C7D, 0xA854},{0x6C7E, 0xA857},{0x6C80, 0xCD45},{0x6C81, 0xA847},{0x6C82, 0xA85E},
+ {0x6C83, 0xA855},{0x6C84, 0xCB4E},{0x6C85, 0xA84A},{0x6C86, 0xA859},{0x6C87, 0xCB56},{0x6C88, 0xA848},{0x6C89, 0xA849},{0x6C8A, 0xCD43},
+ {0x6C8B, 0xCB4F},{0x6C8C, 0xA850},{0x6C8D, 0xA85B},{0x6C8E, 0xCB5D},{0x6C8F, 0xCB50},{0x6C90, 0xA84E},{0x6C92, 0xA853},{0x6C93, 0xCCEE},
+ {0x6C94, 0xA85C},{0x6C95, 0xCB57},{0x6C96, 0xA852},{0x6C98, 0xA85D},{0x6C99, 0xA846},{0x6C9A, 0xCB54},{0x6C9B, 0xA84B},{0x6C9C, 0xCB58},
+ {0x6C9D, 0xCD44},{0x6CAB, 0xAA6A},{0x6CAC, 0xAA7A},{0x6CAD, 0xCCF5},{0x6CAE, 0xAA71},{0x6CB0, 0xCD4B},{0x6CB1, 0xAA62},{0x6CB3, 0xAA65},
+ {0x6CB4, 0xCD42},{0x6CB6, 0xCCF3},{0x6CB7, 0xCCF7},{0x6CB8, 0xAA6D},{0x6CB9, 0xAA6F},{0x6CBA, 0xCCFA},{0x6CBB, 0xAA76},{0x6CBC, 0xAA68},
+ {0x6CBD, 0xAA66},{0x6CBE, 0xAA67},{0x6CBF, 0xAA75},{0x6CC0, 0xCD47},{0x6CC1, 0xAA70},{0x6CC2, 0xCCF9},{0x6CC3, 0xCCFB},{0x6CC4, 0xAA6E},
+ {0x6CC5, 0xAA73},{0x6CC6, 0xCCFC},{0x6CC7, 0xCD4A},{0x6CC9, 0xAC75},{0x6CCA, 0xAA79},{0x6CCC, 0xAA63},{0x6CCD, 0xCD49},{0x6CCF, 0xCD4D},
+ {0x6CD0, 0xCCF8},{0x6CD1, 0xCD4F},{0x6CD2, 0xCD40},{0x6CD3, 0xAA6C},{0x6CD4, 0xCCF4},{0x6CD5, 0xAA6B},{0x6CD6, 0xAA7D},{0x6CD7, 0xAA72},
+ {0x6CD9, 0xCCF2},{0x6CDA, 0xCF75},{0x6CDB, 0xAA78},{0x6CDC, 0xAA7C},{0x6CDD, 0xCD41},{0x6CDE, 0xCD46},{0x6CE0, 0xAA7E},{0x6CE1, 0xAA77},
+ {0x6CE2, 0xAA69},{0x6CE3, 0xAA5F},{0x6CE5, 0xAA64},{0x6CE7, 0xCCF6},{0x6CE8, 0xAA60},{0x6CE9, 0xCD4E},{0x6CEB, 0xCCF0},{0x6CEC, 0xCCEF},
+ {0x6CED, 0xCCFD},{0x6CEE, 0xCCF1},{0x6CEF, 0xAA7B},{0x6CF0, 0xAEF5},{0x6CF1, 0xAA74},{0x6CF2, 0xCCFE},{0x6CF3, 0xAA61},{0x6CF5, 0xACA6},
+ {0x6CF9, 0xCD4C},{0x6D00, 0xCF7C},{0x6D01, 0xCFA1},{0x6D03, 0xCFA4},{0x6D04, 0xCF77},{0x6D07, 0xCFA7},{0x6D08, 0xCFAA},{0x6D09, 0xCFAC},
+ {0x6D0A, 0xCF74},{0x6D0B, 0xAC76},{0x6D0C, 0xAC7B},{0x6D0D, 0xD249},{0x6D0E, 0xACAD},{0x6D0F, 0xCFA5},{0x6D10, 0xCFAD},{0x6D11, 0xCF7B},
+ {0x6D12, 0xCF73},{0x6D16, 0xD264},{0x6D17, 0xAC7E},{0x6D18, 0xCFA2},{0x6D19, 0xCF78},{0x6D1A, 0xCF7A},{0x6D1B, 0xACA5},{0x6D1D, 0xCF7D},
+ {0x6D1E, 0xAC7D},{0x6D1F, 0xCF70},{0x6D20, 0xCFA8},{0x6D22, 0xCFAB},{0x6D25, 0xAC7A},{0x6D27, 0xACA8},{0x6D28, 0xCF6D},{0x6D29, 0xACAA},
+ {0x6D2A, 0xAC78},{0x6D2B, 0xACAE},{0x6D2C, 0xCFA9},{0x6D2D, 0xCF6F},{0x6D2E, 0xACAB},{0x6D2F, 0xD25E},{0x6D30, 0xCD48},{0x6D31, 0xAC7C},
+ {0x6D32, 0xAC77},{0x6D33, 0xCF76},{0x6D34, 0xCF6E},{0x6D35, 0xACAC},{0x6D36, 0xACA4},{0x6D37, 0xCFA3},{0x6D38, 0xACA9},{0x6D39, 0xACA7},
+ {0x6D3A, 0xCF79},{0x6D3B, 0xACA1},{0x6D3C, 0xCF71},{0x6D3D, 0xACA2},{0x6D3E, 0xACA3},{0x6D3F, 0xCF72},{0x6D40, 0xCFA6},{0x6D41, 0xAC79},
+ {0x6D42, 0xCF7E},{0x6D58, 0xD24C},{0x6D59, 0xAEFD},{0x6D5A, 0xAF43},{0x6D5E, 0xD255},{0x6D5F, 0xD25B},{0x6D60, 0xD257},{0x6D61, 0xD24A},
+ {0x6D62, 0xD24D},{0x6D63, 0xD246},{0x6D64, 0xD247},{0x6D65, 0xAF4A},{0x6D66, 0xAEFA},{0x6D67, 0xD256},{0x6D68, 0xD25F},{0x6D69, 0xAF45},
+ {0x6D6A, 0xAEF6},{0x6D6C, 0xAF40},{0x6D6D, 0xD24E},{0x6D6E, 0xAF42},{0x6D6F, 0xD24F},{0x6D70, 0xD259},{0x6D74, 0xAF44},{0x6D75, 0xD268},
+ {0x6D76, 0xD248},{0x6D77, 0xAEFC},{0x6D78, 0xAEFB},{0x6D79, 0xAF48},{0x6D7A, 0xD245},{0x6D7B, 0xD266},{0x6D7C, 0xD25A},{0x6D7D, 0xD267},
+ {0x6D7E, 0xD261},{0x6D7F, 0xD253},{0x6D80, 0xD262},{0x6D82, 0xD25C},{0x6D83, 0xD265},{0x6D84, 0xD263},{0x6D85, 0xAF49},{0x6D86, 0xD254},
+ {0x6D87, 0xAEF9},{0x6D88, 0xAEF8},{0x6D89, 0xAF41},{0x6D8A, 0xAF47},{0x6D8B, 0xD260},{0x6D8C, 0xAF46},{0x6D8D, 0xD251},{0x6D8E, 0xB243},
+ {0x6D90, 0xD269},{0x6D91, 0xD250},{0x6D92, 0xD24B},{0x6D93, 0xAEFE},{0x6D94, 0xAF4B},{0x6D95, 0xAEF7},{0x6D97, 0xD258},{0x6D98, 0xD25D},
+ {0x6DAA, 0xB265},{0x6DAB, 0xD5E1},{0x6DAC, 0xD5E5},{0x6DAE, 0xB252},{0x6DAF, 0xB250},{0x6DB2, 0xB247},{0x6DB3, 0xD5E3},{0x6DB4, 0xD5E2},
+ {0x6DB5, 0xB25B},{0x6DB7, 0xD5E8},{0x6DB8, 0xB255},{0x6DBA, 0xD5FA},{0x6DBB, 0xD647},{0x6DBC, 0xB244},{0x6DBD, 0xD5F7},{0x6DBE, 0xD5F0},
+ {0x6DBF, 0xB267},{0x6DC0, 0xD5E0},{0x6DC2, 0xD5FC},{0x6DC4, 0xB264},{0x6DC5, 0xB258},{0x6DC6, 0xB263},{0x6DC7, 0xB24E},{0x6DC8, 0xD5EC},
+ {0x6DC9, 0xD5FE},{0x6DCA, 0xD5F6},{0x6DCB, 0xB24F},{0x6DCC, 0xB249},{0x6DCD, 0xD645},{0x6DCF, 0xD5FD},{0x6DD0, 0xD640},{0x6DD1, 0xB251},
+ {0x6DD2, 0xB259},{0x6DD3, 0xD642},{0x6DD4, 0xD5EA},{0x6DD5, 0xD5FB},{0x6DD6, 0xD5EF},{0x6DD7, 0xD644},{0x6DD8, 0xB25E},{0x6DD9, 0xB246},
+ {0x6DDA, 0xB25C},{0x6DDB, 0xD5F4},{0x6DDC, 0xD5F2},{0x6DDD, 0xD5F3},{0x6DDE, 0xB253},{0x6DDF, 0xD5EE},{0x6DE0, 0xD5ED},{0x6DE1, 0xB248},
+ {0x6DE2, 0xD5E7},{0x6DE3, 0xD646},{0x6DE4, 0xB24A},{0x6DE5, 0xD5F1},{0x6DE6, 0xB268},{0x6DE8, 0xB262},{0x6DE9, 0xD5E6},{0x6DEA, 0xB25F},
+ {0x6DEB, 0xB25D},{0x6DEC, 0xB266},{0x6DED, 0xD5F8},{0x6DEE, 0xB261},{0x6DEF, 0xD252},{0x6DF0, 0xD5F9},{0x6DF1, 0xB260},{0x6DF2, 0xD641},
+ {0x6DF3, 0xB245},{0x6DF4, 0xD5F5},{0x6DF5, 0xB257},{0x6DF6, 0xD5E9},{0x6DF7, 0xB256},{0x6DF9, 0xB254},{0x6DFA, 0xB24C},{0x6DFB, 0xB24B},
+ {0x6DFC, 0xD9E7},{0x6DFD, 0xD643},{0x6E00, 0xD5EB},{0x6E03, 0xD9FC},{0x6E05, 0xB24D},{0x6E19, 0xB541},{0x6E1A, 0xB25A},{0x6E1B, 0xB4EE},
+ {0x6E1C, 0xD9F6},{0x6E1D, 0xB4FC},{0x6E1F, 0xD9EA},{0x6E20, 0xB4EB},{0x6E21, 0xB4E7},{0x6E22, 0xDA49},{0x6E23, 0xB4ED},{0x6E24, 0xB4F1},
+ {0x6E25, 0xB4EC},{0x6E26, 0xB4F5},{0x6E27, 0xDA4D},{0x6E28, 0xDA44},{0x6E2B, 0xD9F1},{0x6E2C, 0xB4FA},{0x6E2D, 0xB4F4},{0x6E2E, 0xD9FD},
+ {0x6E2F, 0xB4E4},{0x6E30, 0xDA4A},{0x6E31, 0xDA43},{0x6E32, 0xB4E8},{0x6E33, 0xD9F7},{0x6E34, 0xB4F7},{0x6E35, 0xDA55},{0x6E36, 0xDA56},
+ {0x6E38, 0xB4E5},{0x6E39, 0xDA48},{0x6E3A, 0xB4F9},{0x6E3B, 0xD9FB},{0x6E3C, 0xD9ED},{0x6E3D, 0xD9EE},{0x6E3E, 0xB4FD},{0x6E3F, 0xD9F2},
+ {0x6E40, 0xD9F9},{0x6E41, 0xD9F3},{0x6E43, 0xB4FB},{0x6E44, 0xB544},{0x6E45, 0xD9EF},{0x6E46, 0xD9E8},{0x6E47, 0xD9E9},{0x6E49, 0xD9EB},
+ {0x6E4A, 0xB4EA},{0x6E4B, 0xD9F8},{0x6E4D, 0xB4F8},{0x6E4E, 0xB542},{0x6E51, 0xD9FA},{0x6E52, 0xDA53},{0x6E53, 0xDA4B},{0x6E54, 0xB4E6},
+ {0x6E55, 0xDA51},{0x6E56, 0xB4F2},{0x6E58, 0xB4F0},{0x6E5A, 0xDA57},{0x6E5B, 0xB4EF},{0x6E5C, 0xDA41},{0x6E5D, 0xD9F4},{0x6E5E, 0xD9FE},
+ {0x6E5F, 0xB547},{0x6E60, 0xDA45},{0x6E61, 0xDA42},{0x6E62, 0xD9F0},{0x6E63, 0xB543},{0x6E64, 0xDA4F},{0x6E65, 0xDA4C},{0x6E66, 0xDA54},
+ {0x6E67, 0xB4E9},{0x6E68, 0xDA40},{0x6E69, 0xB546},{0x6E6B, 0xDA47},{0x6E6E, 0xB4F3},{0x6E6F, 0xB4F6},{0x6E71, 0xDA46},{0x6E72, 0xB545},
+ {0x6E73, 0xD9F5},{0x6E74, 0xD5E4},{0x6E77, 0xDA50},{0x6E78, 0xDA4E},{0x6E79, 0xDA52},{0x6E88, 0xD9EC},{0x6E89, 0xB540},{0x6E8D, 0xDE61},
+ {0x6E8E, 0xDE60},{0x6E8F, 0xDE46},{0x6E90, 0xB7BD},{0x6E92, 0xDE5F},{0x6E93, 0xDE49},{0x6E94, 0xDE4A},{0x6E96, 0xB7C7},{0x6E97, 0xDE68},
+ {0x6E98, 0xB7C2},{0x6E99, 0xDE5E},{0x6E9B, 0xDE43},{0x6E9C, 0xB7C8},{0x6E9D, 0xB7BE},{0x6E9E, 0xDE52},{0x6E9F, 0xDE48},{0x6EA0, 0xDE4B},
+ {0x6EA1, 0xDE63},{0x6EA2, 0xB7B8},{0x6EA3, 0xDE6A},{0x6EA4, 0xDE62},{0x6EA5, 0xB7C1},{0x6EA6, 0xDE57},{0x6EA7, 0xB7CC},{0x6EAA, 0xB7CB},
+ {0x6EAB, 0xB7C5},{0x6EAE, 0xDE69},{0x6EAF, 0xB7B9},{0x6EB0, 0xDE55},{0x6EB1, 0xDE4C},{0x6EB2, 0xDE59},{0x6EB3, 0xDE65},{0x6EB4, 0xB7CD},
+ {0x6EB6, 0xB7BB},{0x6EB7, 0xDE54},{0x6EB9, 0xDE4D},{0x6EBA, 0xB7C4},{0x6EBC, 0xB7C3},{0x6EBD, 0xDE50},{0x6EBE, 0xDE5A},{0x6EBF, 0xDE64},
+ {0x6EC0, 0xDE47},{0x6EC1, 0xDE51},{0x6EC2, 0xB7BC},{0x6EC3, 0xDE5B},{0x6EC4, 0xB7C9},{0x6EC5, 0xB7C0},{0x6EC6, 0xDE4E},{0x6EC7, 0xB7BF},
+ {0x6EC8, 0xDE45},{0x6EC9, 0xDE53},{0x6ECA, 0xDE67},{0x6ECB, 0xB4FE},{0x6ECC, 0xBAB0},{0x6ECD, 0xDE56},{0x6ECE, 0xE26C},{0x6ECF, 0xDE58},
+ {0x6ED0, 0xDE66},{0x6ED1, 0xB7C6},{0x6ED2, 0xDE4F},{0x6ED3, 0xB7BA},{0x6ED4, 0xB7CA},{0x6ED5, 0xBCF0},{0x6ED6, 0xDE44},{0x6ED8, 0xDE5D},
+ {0x6EDC, 0xDE5C},{0x6EEB, 0xE2AA},{0x6EEC, 0xBAAD},{0x6EED, 0xE27D},{0x6EEE, 0xE2A4},{0x6EEF, 0xBAA2},{0x6EF1, 0xE26E},{0x6EF2, 0xBAAF},
+ {0x6EF4, 0xBA77},{0x6EF5, 0xE26D},{0x6EF6, 0xE2B0},{0x6EF7, 0xBAB1},{0x6EF8, 0xE271},{0x6EF9, 0xE2A3},{0x6EFB, 0xE273},{0x6EFC, 0xE2B3},
+ {0x6EFD, 0xE2AF},{0x6EFE, 0xBA75},{0x6EFF, 0xBAA1},{0x6F00, 0xE653},{0x6F01, 0xBAAE},{0x6F02, 0xBA7D},{0x6F03, 0xE26F},{0x6F05, 0xE2AE},
+ {0x6F06, 0xBAA3},{0x6F07, 0xE2AB},{0x6F08, 0xE2B8},{0x6F09, 0xE275},{0x6F0A, 0xE27E},{0x6F0D, 0xE2B6},{0x6F0E, 0xE2AC},{0x6F0F, 0xBA7C},
+ {0x6F12, 0xE27C},{0x6F13, 0xBA76},{0x6F14, 0xBA74},{0x6F15, 0xBAA8},{0x6F18, 0xE27A},{0x6F19, 0xE277},{0x6F1A, 0xE278},{0x6F1C, 0xE2B2},
+ {0x6F1E, 0xE2B7},{0x6F1F, 0xE2B5},{0x6F20, 0xBA7A},{0x6F21, 0xE2B9},{0x6F22, 0xBA7E},{0x6F23, 0xBAA7},{0x6F25, 0xE270},{0x6F26, 0xE5FA},
+ {0x6F27, 0xE279},{0x6F29, 0xBA78},{0x6F2A, 0xBAAC},{0x6F2B, 0xBAA9},{0x6F2C, 0xBA7B},{0x6F2D, 0xE2A5},{0x6F2E, 0xE274},{0x6F2F, 0xBAAA},
+ {0x6F30, 0xE2A7},{0x6F31, 0xBAA4},{0x6F32, 0xBAA6},{0x6F33, 0xBA73},{0x6F35, 0xE2A9},{0x6F36, 0xE2A1},{0x6F37, 0xE272},{0x6F38, 0xBAA5},
+ {0x6F39, 0xE2B1},{0x6F3A, 0xE2B4},{0x6F3B, 0xE27B},{0x6F3C, 0xE2A8},{0x6F3E, 0xBA79},{0x6F3F, 0xBCDF},{0x6F40, 0xE2A6},{0x6F41, 0xE5F9},
+ {0x6F43, 0xE2AD},{0x6F4E, 0xE276},{0x6F4F, 0xE644},{0x6F50, 0xE64E},{0x6F51, 0xBCE2},{0x6F52, 0xE64D},{0x6F53, 0xE659},{0x6F54, 0xBCE4},
+ {0x6F55, 0xE64B},{0x6F57, 0xE64F},{0x6F58, 0xBCEF},{0x6F5A, 0xE646},{0x6F5B, 0xBCE7},{0x6F5D, 0xE652},{0x6F5E, 0xE9F0},{0x6F5F, 0xBCF3},
+ {0x6F60, 0xBCF2},{0x6F61, 0xE654},{0x6F62, 0xE643},{0x6F63, 0xE65E},{0x6F64, 0xBCED},{0x6F66, 0xBCE3},{0x6F67, 0xE657},{0x6F69, 0xE65B},
+ {0x6F6A, 0xE660},{0x6F6B, 0xE655},{0x6F6C, 0xE649},{0x6F6D, 0xBCE6},{0x6F6E, 0xBCE9},{0x6F6F, 0xBCF1},{0x6F70, 0xBCEC},{0x6F72, 0xE64C},
+ {0x6F73, 0xE2A2},{0x6F76, 0xE648},{0x6F77, 0xE65F},{0x6F78, 0xBCE8},{0x6F7A, 0xBCEB},{0x6F7B, 0xE661},{0x6F7C, 0xBCE0},{0x6F7D, 0xE656},
+ {0x6F7E, 0xE5FB},{0x6F7F, 0xE65C},{0x6F80, 0xC0DF},{0x6F82, 0xE64A},{0x6F84, 0xBCE1},{0x6F85, 0xE645},{0x6F86, 0xBCE5},{0x6F87, 0xE5FC},
+ {0x6F88, 0xBAAB},{0x6F89, 0xE641},{0x6F8B, 0xE65A},{0x6F8C, 0xE642},{0x6F8D, 0xE640},{0x6F8E, 0xBCEA},{0x6F90, 0xE658},{0x6F92, 0xE5FE},
+ {0x6F93, 0xE651},{0x6F94, 0xE650},{0x6F95, 0xE65D},{0x6F96, 0xE647},{0x6F97, 0xBCEE},{0x6F9E, 0xE9F3},{0x6FA0, 0xBF49},{0x6FA1, 0xBEFE},
+ {0x6FA2, 0xEA40},{0x6FA3, 0xE9EB},{0x6FA4, 0xBF41},{0x6FA5, 0xE9F7},{0x6FA6, 0xBF48},{0x6FA7, 0xBF43},{0x6FA8, 0xE9F5},{0x6FA9, 0xED4F},
+ {0x6FAA, 0xE9FB},{0x6FAB, 0xEA42},{0x6FAC, 0xE9FA},{0x6FAD, 0xE9E9},{0x6FAE, 0xE9F8},{0x6FAF, 0xEA44},{0x6FB0, 0xEA46},{0x6FB1, 0xBEFD},
+ {0x6FB2, 0xEA45},{0x6FB3, 0xBF44},{0x6FB4, 0xBF4A},{0x6FB6, 0xBF47},{0x6FB8, 0xE9FE},{0x6FB9, 0xBF46},{0x6FBA, 0xE9F9},{0x6FBC, 0xE9ED},
+ {0x6FBD, 0xE9F2},{0x6FBF, 0xE9FD},{0x6FC0, 0xBF45},{0x6FC1, 0xBF42},{0x6FC2, 0xBEFC},{0x6FC3, 0xBF40},{0x6FC4, 0xE9F1},{0x6FC6, 0xE5FD},
+ {0x6FC7, 0xE9EC},{0x6FC8, 0xE9EF},{0x6FC9, 0xEA41},{0x6FCA, 0xE9F4},{0x6FCB, 0xE9EA},{0x6FCC, 0xED4E},{0x6FCD, 0xEA43},{0x6FCE, 0xE9EE},
+ {0x6FCF, 0xE9FC},{0x6FD4, 0xED51},{0x6FD5, 0xC0E3},{0x6FD8, 0xC0D7},{0x6FDB, 0xC0DB},{0x6FDC, 0xED53},{0x6FDD, 0xED59},{0x6FDE, 0xED57},
+ {0x6FDF, 0xC0D9},{0x6FE0, 0xC0DA},{0x6FE1, 0xC0E1},{0x6FE2, 0xED5A},{0x6FE3, 0xED52},{0x6FE4, 0xC0DC},{0x6FE6, 0xED56},{0x6FE7, 0xED55},
+ {0x6FE8, 0xED5B},{0x6FE9, 0xC0E2},{0x6FEB, 0xC0DD},{0x6FEC, 0xC0E0},{0x6FED, 0xED54},{0x6FEE, 0xC0E4},{0x6FEF, 0xC0DE},{0x6FF0, 0xC0E5},
+ {0x6FF1, 0xC0D8},{0x6FF2, 0xED58},{0x6FF4, 0xED50},{0x6FF7, 0xEFF7},{0x6FFA, 0xC271},{0x6FFB, 0xEFF4},{0x6FFC, 0xEFF6},{0x6FFE, 0xC26F},
+ {0x6FFF, 0xEFF2},{0x7000, 0xEFF3},{0x7001, 0xEFEE},{0x7004, 0xE9F6},{0x7005, 0xEFEF},{0x7006, 0xC270},{0x7007, 0xEFEB},{0x7009, 0xC26D},
+ {0x700A, 0xEFF8},{0x700B, 0xC26E},{0x700C, 0xEFEC},{0x700D, 0xEFED},{0x700E, 0xEFF1},{0x700F, 0xC273},{0x7011, 0xC272},{0x7014, 0xEFF0},
+ {0x7015, 0xC378},{0x7016, 0xF25F},{0x7017, 0xF265},{0x7018, 0xC379},{0x7019, 0xF25C},{0x701A, 0xC376},{0x701B, 0xC373},{0x701C, 0xF267},
+ {0x701D, 0xC377},{0x701F, 0xC374},{0x7020, 0xF25E},{0x7021, 0xF261},{0x7022, 0xF262},{0x7023, 0xF263},{0x7024, 0xF266},{0x7026, 0xEFF5},
+ {0x7027, 0xF25D},{0x7028, 0xC375},{0x7029, 0xF264},{0x702A, 0xF268},{0x702B, 0xF260},{0x702F, 0xF45D},{0x7030, 0xC46A},{0x7031, 0xF460},
+ {0x7032, 0xC46B},{0x7033, 0xF468},{0x7034, 0xF45F},{0x7035, 0xF45C},{0x7037, 0xF45E},{0x7038, 0xF462},{0x7039, 0xF465},{0x703A, 0xF464},
+ {0x703B, 0xF467},{0x703C, 0xF45B},{0x703E, 0xC469},{0x703F, 0xF463},{0x7040, 0xF466},{0x7041, 0xF469},{0x7042, 0xF461},{0x7043, 0xF5D3},
+ {0x7044, 0xF5D4},{0x7045, 0xF5D8},{0x7046, 0xF5D9},{0x7048, 0xF5D6},{0x7049, 0xF5D7},{0x704A, 0xF5D5},{0x704C, 0xC4E9},{0x7051, 0xC578},
+ {0x7052, 0xF6EB},{0x7055, 0xF6E8},{0x7056, 0xF6E9},{0x7057, 0xF6EA},{0x7058, 0xC579},{0x705A, 0xF7E5},{0x705B, 0xF7E4},{0x705D, 0xF8AF},
+ {0x705E, 0xC5F4},{0x705F, 0xF8AD},{0x7060, 0xF8B0},{0x7061, 0xF8AE},{0x7062, 0xF8F5},{0x7063, 0xC657},{0x7064, 0xC665},{0x7065, 0xF9A3},
+ {0x7066, 0xF96C},{0x7068, 0xF9A2},{0x7069, 0xF9D0},{0x706A, 0xF9D1},{0x706B, 0xA4F5},{0x7070, 0xA6C7},{0x7071, 0xCA41},{0x7074, 0xCB5E},
+ {0x7076, 0xA85F},{0x7078, 0xA862},{0x707A, 0xCB5F},{0x707C, 0xA860},{0x707D, 0xA861},{0x7082, 0xCD58},{0x7083, 0xCD5A},{0x7084, 0xCD55},
+ {0x7085, 0xCD52},{0x7086, 0xCD54},{0x708A, 0xAAA4},{0x708E, 0xAAA2},{0x7091, 0xCD56},{0x7092, 0xAAA3},{0x7093, 0xCD53},{0x7094, 0xCD50},
+ {0x7095, 0xAAA1},{0x7096, 0xCD57},{0x7098, 0xCD51},{0x7099, 0xAAA5},{0x709A, 0xCD59},{0x709F, 0xCFAF},{0x70A1, 0xCFB3},{0x70A4, 0xACB7},
+ {0x70A9, 0xCFB6},{0x70AB, 0xACAF},{0x70AC, 0xACB2},{0x70AD, 0xACB4},{0x70AE, 0xACB6},{0x70AF, 0xACB3},{0x70B0, 0xCFB2},{0x70B1, 0xCFB1},
+ {0x70B3, 0xACB1},{0x70B4, 0xCFB4},{0x70B5, 0xCFB5},{0x70B7, 0xCFAE},{0x70B8, 0xACB5},{0x70BA, 0xACB0},{0x70BE, 0xCFB0},{0x70C5, 0xD277},
+ {0x70C6, 0xD278},{0x70C7, 0xD279},{0x70C8, 0xAF50},{0x70CA, 0xAF4C},{0x70CB, 0xD26E},{0x70CD, 0xD276},{0x70CE, 0xD27B},{0x70CF, 0xAF51},
+ {0x70D1, 0xD26C},{0x70D2, 0xD272},{0x70D3, 0xD26B},{0x70D4, 0xD275},{0x70D7, 0xD271},{0x70D8, 0xAF4D},{0x70D9, 0xAF4F},{0x70DA, 0xD27A},
+ {0x70DC, 0xD26A},{0x70DD, 0xD26D},{0x70DE, 0xD273},{0x70E0, 0xD274},{0x70E1, 0xD27C},{0x70E2, 0xD270},{0x70E4, 0xAF4E},{0x70EF, 0xB26D},
+ {0x70F0, 0xD64E},{0x70F3, 0xD650},{0x70F4, 0xD64C},{0x70F6, 0xD658},{0x70F7, 0xD64A},{0x70F8, 0xD657},{0x70F9, 0xB269},{0x70FA, 0xD648},
+ {0x70FB, 0xDA5B},{0x70FC, 0xD652},{0x70FD, 0xB26C},{0x70FF, 0xD653},{0x7100, 0xD656},{0x7102, 0xD65A},{0x7104, 0xD64F},{0x7106, 0xD654},
+ {0x7109, 0xB26A},{0x710A, 0xB26B},{0x710B, 0xD659},{0x710C, 0xD64D},{0x710D, 0xD649},{0x710E, 0xD65B},{0x7110, 0xD651},{0x7113, 0xD655},
+ {0x7117, 0xD64B},{0x7119, 0xB548},{0x711A, 0xB549},{0x711B, 0xDA65},{0x711C, 0xB54F},{0x711E, 0xDA59},{0x711F, 0xDA62},{0x7120, 0xDA58},
+ {0x7121, 0xB54C},{0x7122, 0xDA60},{0x7123, 0xDA5E},{0x7125, 0xDA5F},{0x7126, 0xB54A},{0x7128, 0xDA63},{0x712E, 0xDA5C},{0x712F, 0xDA5A},
+ {0x7130, 0xB54B},{0x7131, 0xDA5D},{0x7132, 0xDA61},{0x7136, 0xB54D},{0x713A, 0xDA64},{0x7141, 0xDE70},{0x7142, 0xDE77},{0x7143, 0xDE79},
+ {0x7144, 0xDEA1},{0x7146, 0xB7DA},{0x7147, 0xDE6B},{0x7149, 0xB7D2},{0x714B, 0xDE7A},{0x714C, 0xB7D7},{0x714D, 0xDEA2},{0x714E, 0xB7CE},
+ {0x7150, 0xDE7D},{0x7152, 0xDE6D},{0x7153, 0xDE7E},{0x7154, 0xDE6C},{0x7156, 0xB7DC},{0x7158, 0xDE78},{0x7159, 0xB7CF},{0x715A, 0xDEA3},
+ {0x715C, 0xB7D4},{0x715D, 0xDE71},{0x715E, 0xB7D9},{0x715F, 0xDE7C},{0x7160, 0xDE6F},{0x7161, 0xDE76},{0x7162, 0xDE72},{0x7163, 0xDE6E},
+ {0x7164, 0xB7D1},{0x7165, 0xB7D8},{0x7166, 0xB7D6},{0x7167, 0xB7D3},{0x7168, 0xB7DB},{0x7169, 0xB7D0},{0x716A, 0xDE75},{0x716C, 0xB7D5},
+ {0x716E, 0xB54E},{0x7170, 0xDE7B},{0x7172, 0xDE73},{0x7178, 0xDE74},{0x717B, 0xE2C1},{0x717D, 0xBAB4},{0x7180, 0xE2BD},{0x7181, 0xE2C3},
+ {0x7182, 0xE2BF},{0x7184, 0xBAB6},{0x7185, 0xE2BE},{0x7186, 0xE2C2},{0x7187, 0xE2BA},{0x7189, 0xE2BC},{0x718A, 0xBAB5},{0x718F, 0xE2C0},
+ {0x7190, 0xE2BB},{0x7192, 0xBAB7},{0x7194, 0xBAB2},{0x7197, 0xE2C4},{0x7199, 0xBAB3},{0x719A, 0xE667},{0x719B, 0xE664},{0x719C, 0xE670},
+ {0x719D, 0xE66A},{0x719E, 0xE66C},{0x719F, 0xBCF4},{0x71A0, 0xE666},{0x71A1, 0xE66E},{0x71A4, 0xE66D},{0x71A5, 0xE66B},{0x71A7, 0xE671},
+ {0x71A8, 0xBCF7},{0x71A9, 0xE668},{0x71AA, 0xE66F},{0x71AC, 0xBCF5},{0x71AF, 0xE663},{0x71B0, 0xE665},{0x71B1, 0xBCF6},{0x71B2, 0xE662},
+ {0x71B3, 0xE672},{0x71B5, 0xE669},{0x71B8, 0xEA4A},{0x71B9, 0xBF51},{0x71BC, 0xEA55},{0x71BD, 0xEA53},{0x71BE, 0xBF4B},{0x71BF, 0xEA49},
+ {0x71C0, 0xEA4C},{0x71C1, 0xEA4D},{0x71C2, 0xEA48},{0x71C3, 0xBF55},{0x71C4, 0xBF56},{0x71C5, 0xEA47},{0x71C6, 0xEA56},{0x71C7, 0xEA51},
+ {0x71C8, 0xBF4F},{0x71C9, 0xBF4C},{0x71CA, 0xEA50},{0x71CB, 0xEA4E},{0x71CE, 0xBF52},{0x71CF, 0xEA52},{0x71D0, 0xBF4D},{0x71D2, 0xBF4E},
+ {0x71D4, 0xEA4F},{0x71D5, 0xBF50},{0x71D6, 0xEA4B},{0x71D8, 0xEA54},{0x71D9, 0xBF53},{0x71DA, 0xEA57},{0x71DB, 0xEA58},{0x71DC, 0xBF54},
+ {0x71DF, 0xC0E7},{0x71E0, 0xC0EE},{0x71E1, 0xED5C},{0x71E2, 0xED62},{0x71E4, 0xED60},{0x71E5, 0xC0EA},{0x71E6, 0xC0E9},{0x71E7, 0xC0E6},
+ {0x71E8, 0xED5E},{0x71EC, 0xC0EC},{0x71ED, 0xC0EB},{0x71EE, 0xC0E8},{0x71F0, 0xED61},{0x71F1, 0xED5D},{0x71F2, 0xED5F},{0x71F4, 0xC0ED},
+ {0x71F8, 0xC277},{0x71F9, 0xEFFB},{0x71FB, 0xC274},{0x71FC, 0xC275},{0x71FD, 0xEFFD},{0x71FE, 0xC276},{0x71FF, 0xEFFA},{0x7201, 0xEFF9},
+ {0x7202, 0xF26C},{0x7203, 0xEFFC},{0x7205, 0xF26D},{0x7206, 0xC37A},{0x7207, 0xF26B},{0x720A, 0xF26A},{0x720C, 0xF269},{0x720D, 0xC37B},
+ {0x7210, 0xC46C},{0x7213, 0xF46A},{0x7214, 0xF46B},{0x7219, 0xF5DC},{0x721A, 0xF5DB},{0x721B, 0xC4EA},{0x721D, 0xF5DA},{0x721E, 0xF6EC},
+ {0x721F, 0xF6ED},{0x7222, 0xF7E6},{0x7223, 0xF8B1},{0x7226, 0xF8F6},{0x7227, 0xF9BC},{0x7228, 0xC679},{0x7229, 0xF9C6},{0x722A, 0xA4F6},
+ {0x722C, 0xAAA6},{0x722D, 0xAAA7},{0x7230, 0xACB8},{0x7235, 0xC0EF},{0x7236, 0xA4F7},{0x7238, 0xAAA8},{0x7239, 0xAF52},{0x723A, 0xB7DD},
+ {0x723B, 0xA4F8},{0x723D, 0xB26E},{0x723E, 0xBAB8},{0x723F, 0xC962},{0x7241, 0xCFB7},{0x7242, 0xD27D},{0x7244, 0xE2C5},{0x7246, 0xC0F0},
+ {0x7247, 0xA4F9},{0x7248, 0xAAA9},{0x7249, 0xCFB8},{0x724A, 0xCFB9},{0x724B, 0xDA66},{0x724C, 0xB550},{0x724F, 0xDEA4},{0x7252, 0xB7DE},
+ {0x7253, 0xE2C6},{0x7256, 0xBCF8},{0x7258, 0xC37C},{0x7259, 0xA4FA},{0x725A, 0xDA67},{0x725B, 0xA4FB},{0x725D, 0xA6C9},{0x725E, 0xCA42},
+ {0x725F, 0xA6C8},{0x7260, 0xA865},{0x7261, 0xA864},{0x7262, 0xA863},{0x7263, 0xCB60},{0x7267, 0xAAAA},{0x7269, 0xAAAB},{0x726A, 0xCD5B},
+ {0x726C, 0xCFBA},{0x726E, 0xCFBD},{0x726F, 0xACBA},{0x7270, 0xCFBB},{0x7272, 0xACB9},{0x7273, 0xCFBC},{0x7274, 0xACBB},{0x7276, 0xD2A2},
+ {0x7277, 0xD2A1},{0x7278, 0xD27E},{0x7279, 0xAF53},{0x727B, 0xD65D},{0x727C, 0xD65E},{0x727D, 0xB26F},{0x727E, 0xD65C},{0x727F, 0xD65F},
+ {0x7280, 0xB552},{0x7281, 0xB270},{0x7284, 0xB551},{0x7285, 0xDA6B},{0x7286, 0xDA6A},{0x7288, 0xDA68},{0x7289, 0xDA69},{0x728B, 0xDA6C},
+ {0x728C, 0xDEA6},{0x728D, 0xDEA5},{0x728E, 0xDEA9},{0x7290, 0xDEA8},{0x7291, 0xDEA7},{0x7292, 0xBAB9},{0x7293, 0xE2C9},{0x7295, 0xE2C8},
+ {0x7296, 0xBABA},{0x7297, 0xE2C7},{0x7298, 0xE673},{0x729A, 0xE674},{0x729B, 0xBCF9},{0x729D, 0xEA59},{0x729E, 0xEA5A},{0x72A1, 0xF272},
+ {0x72A2, 0xC37D},{0x72A3, 0xF271},{0x72A4, 0xF270},{0x72A5, 0xF26E},{0x72A6, 0xF26F},{0x72A7, 0xC4EB},{0x72A8, 0xF46C},{0x72A9, 0xF6EE},
+ {0x72AA, 0xF8F7},{0x72AC, 0xA4FC},{0x72AE, 0xC9A5},{0x72AF, 0xA5C7},{0x72B0, 0xC9A6},{0x72B4, 0xCA43},{0x72B5, 0xCA44},{0x72BA, 0xCB66},
+ {0x72BD, 0xCB62},{0x72BF, 0xCB61},{0x72C0, 0xAAAC},{0x72C1, 0xCB65},{0x72C2, 0xA867},{0x72C3, 0xCB63},{0x72C4, 0xA866},{0x72C5, 0xCB67},
+ {0x72C6, 0xCB64},{0x72C9, 0xCD5F},{0x72CA, 0xCFBE},{0x72CB, 0xCD5D},{0x72CC, 0xCD64},{0x72CE, 0xAAAD},{0x72D0, 0xAAB0},{0x72D1, 0xCD65},
+ {0x72D2, 0xCD61},{0x72D4, 0xCD62},{0x72D6, 0xCD5C},{0x72D7, 0xAAAF},{0x72D8, 0xCD5E},{0x72D9, 0xAAAE},{0x72DA, 0xCD63},{0x72DC, 0xCD60},
+ {0x72DF, 0xCFC2},{0x72E0, 0xACBD},{0x72E1, 0xACBE},{0x72E3, 0xCFC5},{0x72E4, 0xCFBF},{0x72E6, 0xCFC4},{0x72E8, 0xCFC0},{0x72E9, 0xACBC},
+ {0x72EA, 0xCFC3},{0x72EB, 0xCFC1},{0x72F3, 0xD2A8},{0x72F4, 0xD2A5},{0x72F6, 0xD2A7},{0x72F7, 0xAF58},{0x72F8, 0xAF57},{0x72F9, 0xAF55},
+ {0x72FA, 0xD2A4},{0x72FB, 0xD2A9},{0x72FC, 0xAF54},{0x72FD, 0xAF56},{0x72FE, 0xD2A6},{0x72FF, 0xD667},{0x7300, 0xD2A3},{0x7301, 0xD2AA},
+ {0x7307, 0xD662},{0x7308, 0xD666},{0x730A, 0xD665},{0x730B, 0xDA6E},{0x730C, 0xDA79},{0x730F, 0xD668},{0x7311, 0xD663},{0x7312, 0xDA6D},
+ {0x7313, 0xB274},{0x7316, 0xB273},{0x7317, 0xD661},{0x7318, 0xD664},{0x7319, 0xB275},{0x731B, 0xB272},{0x731C, 0xB271},{0x731D, 0xD660},
+ {0x731E, 0xD669},{0x7322, 0xDA70},{0x7323, 0xDA77},{0x7325, 0xB554},{0x7326, 0xDA76},{0x7327, 0xDA73},{0x7329, 0xB556},{0x732D, 0xDA75},
+ {0x7330, 0xDA6F},{0x7331, 0xDA71},{0x7332, 0xDA74},{0x7333, 0xDA72},{0x7334, 0xB555},{0x7335, 0xDA78},{0x7336, 0xB553},{0x7337, 0xB7DF},
+ {0x733A, 0xDEAD},{0x733B, 0xDEAC},{0x733C, 0xDEAA},{0x733E, 0xB7E2},{0x733F, 0xB7E1},{0x7340, 0xDEAE},{0x7342, 0xDEAB},{0x7343, 0xE2CA},
+ {0x7344, 0xBABB},{0x7345, 0xB7E0},{0x7349, 0xDEB0},{0x734A, 0xDEAF},{0x734C, 0xE2CD},{0x734D, 0xE2CB},{0x734E, 0xBCFA},{0x7350, 0xBABC},
+ {0x7351, 0xE2CC},{0x7352, 0xE676},{0x7357, 0xBCFB},{0x7358, 0xE675},{0x7359, 0xE67E},{0x735A, 0xE67D},{0x735B, 0xE67B},{0x735D, 0xE67A},
+ {0x735E, 0xE677},{0x735F, 0xE678},{0x7360, 0xE679},{0x7361, 0xE67C},{0x7362, 0xE6A1},{0x7365, 0xEA5F},{0x7366, 0xEA5C},{0x7367, 0xEA5D},
+ {0x7368, 0xBF57},{0x7369, 0xEA5B},{0x736A, 0xEA61},{0x736B, 0xEA60},{0x736C, 0xEA5E},{0x736E, 0xED64},{0x736F, 0xED65},{0x7370, 0xC0F1},
+ {0x7372, 0xC0F2},{0x7373, 0xED63},{0x7375, 0xC279},{0x7376, 0xEFFE},{0x7377, 0xC278},{0x7378, 0xC37E},{0x737A, 0xC3A1},{0x737B, 0xC46D},
+ {0x737C, 0xF46E},{0x737D, 0xF46D},{0x737E, 0xF5DD},{0x737F, 0xF6EF},{0x7380, 0xC57A},{0x7381, 0xF7E8},{0x7382, 0xF7E7},{0x7383, 0xF7E9},
+ {0x7384, 0xA5C8},{0x7385, 0xCFC6},{0x7386, 0xAF59},{0x7387, 0xB276},{0x7388, 0xD66A},{0x7389, 0xA5C9},{0x738A, 0xC9A7},{0x738B, 0xA4FD},
+ {0x738E, 0xCA45},{0x7392, 0xCB6C},{0x7393, 0xCB6A},{0x7394, 0xCB6B},{0x7395, 0xCB68},{0x7396, 0xA868},{0x7397, 0xCB69},{0x739D, 0xCD6D},
+ {0x739F, 0xAAB3},{0x73A0, 0xCD6B},{0x73A1, 0xCD67},{0x73A2, 0xCD6A},{0x73A4, 0xCD66},{0x73A5, 0xAAB5},{0x73A6, 0xCD69},{0x73A8, 0xAAB2},
+ {0x73A9, 0xAAB1},{0x73AB, 0xAAB4},{0x73AC, 0xCD6C},{0x73AD, 0xCD68},{0x73B2, 0xACC2},{0x73B3, 0xACC5},{0x73B4, 0xCFCE},{0x73B5, 0xCFCD},
+ {0x73B6, 0xCFCC},{0x73B7, 0xACBF},{0x73B8, 0xCFD5},{0x73B9, 0xCFCB},{0x73BB, 0xACC1},{0x73BC, 0xD2AF},{0x73BE, 0xCFD2},{0x73BF, 0xCFD0},
+ {0x73C0, 0xACC4},{0x73C2, 0xCFC8},{0x73C3, 0xCFD3},{0x73C5, 0xCFCA},{0x73C6, 0xCFD4},{0x73C7, 0xCFD1},{0x73C8, 0xCFC9},{0x73CA, 0xACC0},
+ {0x73CB, 0xCFD6},{0x73CC, 0xCFC7},{0x73CD, 0xACC3},{0x73D2, 0xD2B4},{0x73D3, 0xD2AB},{0x73D4, 0xD2B6},{0x73D6, 0xD2AE},{0x73D7, 0xD2B9},
+ {0x73D8, 0xD2BA},{0x73D9, 0xD2AC},{0x73DA, 0xD2B8},{0x73DB, 0xD2B5},{0x73DC, 0xD2B3},{0x73DD, 0xD2B7},{0x73DE, 0xAF5F},{0x73E0, 0xAF5D},
+ {0x73E3, 0xD2B1},{0x73E5, 0xD2AD},{0x73E7, 0xD2B0},{0x73E8, 0xD2BB},{0x73E9, 0xD2B2},{0x73EA, 0xAF5E},{0x73EB, 0xCFCF},{0x73ED, 0xAF5A},
+ {0x73EE, 0xAF5C},{0x73F4, 0xD678},{0x73F5, 0xD66D},{0x73F6, 0xD66B},{0x73F8, 0xD66C},{0x73FA, 0xD673},{0x73FC, 0xD674},{0x73FD, 0xD670},
+ {0x73FE, 0xB27B},{0x73FF, 0xD675},{0x7400, 0xD672},{0x7401, 0xD66F},{0x7403, 0xB279},{0x7404, 0xD66E},{0x7405, 0xB277},{0x7406, 0xB27A},
+ {0x7407, 0xD671},{0x7408, 0xD679},{0x7409, 0xAF5B},{0x740A, 0xB278},{0x740B, 0xD677},{0x740C, 0xD676},{0x740D, 0xB27C},{0x7416, 0xDA7E},
+ {0x741A, 0xDAA1},{0x741B, 0xB560},{0x741D, 0xDAA7},{0x7420, 0xDAA9},{0x7421, 0xDAA2},{0x7422, 0xB55A},{0x7423, 0xDAA6},{0x7424, 0xDAA5},
+ {0x7425, 0xB55B},{0x7426, 0xB561},{0x7428, 0xB562},{0x7429, 0xDAA8},{0x742A, 0xB558},{0x742B, 0xDA7D},{0x742C, 0xDA7B},{0x742D, 0xDAA3},
+ {0x742E, 0xDA7A},{0x742F, 0xB55F},{0x7430, 0xDA7C},{0x7431, 0xDAA4},{0x7432, 0xDAAA},{0x7433, 0xB559},{0x7434, 0xB55E},{0x7435, 0xB55C},
+ {0x7436, 0xB55D},{0x743A, 0xB557},{0x743F, 0xB7E9},{0x7440, 0xDEB7},{0x7441, 0xB7E8},{0x7442, 0xDEBB},{0x7444, 0xDEB1},{0x7446, 0xDEBC},
+ {0x744A, 0xDEB2},{0x744B, 0xDEB3},{0x744D, 0xDEBD},{0x744E, 0xDEBA},{0x744F, 0xDEB8},{0x7450, 0xDEB9},{0x7451, 0xDEB5},{0x7452, 0xDEB4},
+ {0x7454, 0xDEBE},{0x7455, 0xB7E5},{0x7457, 0xDEB6},{0x7459, 0xB7EA},{0x745A, 0xB7E4},{0x745B, 0xB7EB},{0x745C, 0xB7EC},{0x745E, 0xB7E7},
+ {0x745F, 0xB7E6},{0x7462, 0xE2CE},{0x7463, 0xBABE},{0x7464, 0xBABD},{0x7467, 0xE2D3},{0x7469, 0xBCFC},{0x746A, 0xBABF},{0x746D, 0xBAC1},
+ {0x746E, 0xE2D4},{0x746F, 0xB7E3},{0x7470, 0xBAC0},{0x7471, 0xE2D0},{0x7472, 0xE2D2},{0x7473, 0xE2CF},{0x7475, 0xE2D1},{0x7479, 0xE6AB},
+ {0x747C, 0xE6AA},{0x747D, 0xE6A7},{0x747E, 0xBD40},{0x747F, 0xEA62},{0x7480, 0xBD41},{0x7481, 0xE6A6},{0x7483, 0xBCFE},{0x7485, 0xE6A8},
+ {0x7486, 0xE6A5},{0x7487, 0xE6A2},{0x7488, 0xE6A9},{0x7489, 0xE6A3},{0x748A, 0xE6A4},{0x748B, 0xBCFD},{0x7490, 0xED69},{0x7492, 0xEA66},
+ {0x7494, 0xEA65},{0x7495, 0xEA67},{0x7497, 0xED66},{0x7498, 0xBF5A},{0x749A, 0xEA63},{0x749C, 0xBF58},{0x749E, 0xBF5C},{0x749F, 0xBF5B},
+ {0x74A0, 0xEA64},{0x74A1, 0xEA68},{0x74A3, 0xBF59},{0x74A5, 0xED6D},{0x74A6, 0xC0F5},{0x74A7, 0xC27A},{0x74A8, 0xC0F6},{0x74A9, 0xC0F3},
+ {0x74AA, 0xED6A},{0x74AB, 0xED68},{0x74AD, 0xED6B},{0x74AF, 0xED6E},{0x74B0, 0xC0F4},{0x74B1, 0xED6C},{0x74B2, 0xED67},{0x74B5, 0xF042},
+ {0x74B6, 0xF045},{0x74B7, 0xF275},{0x74B8, 0xF040},{0x74BA, 0xF46F},{0x74BB, 0xF046},{0x74BD, 0xC3A2},{0x74BE, 0xF044},{0x74BF, 0xC27B},
+ {0x74C0, 0xF041},{0x74C1, 0xF043},{0x74C2, 0xF047},{0x74C3, 0xF276},{0x74C5, 0xF274},{0x74CA, 0xC3A3},{0x74CB, 0xF273},{0x74CF, 0xC46E},
+ {0x74D4, 0xC4ED},{0x74D5, 0xF6F1},{0x74D6, 0xC4EC},{0x74D7, 0xF6F3},{0x74D8, 0xF6F0},{0x74D9, 0xF6F2},{0x74DA, 0xC5D0},{0x74DB, 0xF8B2},
+ {0x74DC, 0xA5CA},{0x74DD, 0xCD6E},{0x74DE, 0xD2BC},{0x74DF, 0xD2BD},{0x74E0, 0xB27D},{0x74E1, 0xDEBF},{0x74E2, 0xBF5D},{0x74E3, 0xC3A4},
+ {0x74E4, 0xC57B},{0x74E5, 0xF8B3},{0x74E6, 0xA5CB},{0x74E8, 0xCD6F},{0x74E9, 0xA260},{0x74EC, 0xCFD7},{0x74EE, 0xCFD8},{0x74F4, 0xD2BE},
+ {0x74F5, 0xD2BF},{0x74F6, 0xB27E},{0x74F7, 0xB2A1},{0x74FB, 0xDAAB},{0x74FD, 0xDEC2},{0x74FE, 0xDEC1},{0x74FF, 0xDEC0},{0x7500, 0xE2D5},
+ {0x7502, 0xE2D6},{0x7503, 0xE2D7},{0x7504, 0xBAC2},{0x7507, 0xE6AD},{0x7508, 0xE6AC},{0x750B, 0xEA69},{0x750C, 0xBF5E},{0x750D, 0xBF5F},
+ {0x750F, 0xED72},{0x7510, 0xED6F},{0x7511, 0xED70},{0x7512, 0xED71},{0x7513, 0xF049},{0x7514, 0xF048},{0x7515, 0xC27C},{0x7516, 0xF277},
+ {0x7517, 0xF5DE},{0x7518, 0xA5CC},{0x751A, 0xACC6},{0x751C, 0xB2A2},{0x751D, 0xDEC3},{0x751F, 0xA5CD},{0x7521, 0xD2C0},{0x7522, 0xB2A3},
+ {0x7525, 0xB563},{0x7526, 0xB564},{0x7528, 0xA5CE},{0x7529, 0xA5CF},{0x752A, 0xCA46},{0x752B, 0xA86A},{0x752C, 0xA869},{0x752D, 0xACC7},
+ {0x752E, 0xCFD9},{0x752F, 0xDAAC},{0x7530, 0xA5D0},{0x7531, 0xA5D1},{0x7532, 0xA5D2},{0x7533, 0xA5D3},{0x7537, 0xA86B},{0x7538, 0xA86C},
+ {0x7539, 0xCB6E},{0x753A, 0xCB6D},{0x753D, 0xAAB6},{0x753E, 0xCD72},{0x753F, 0xCD70},{0x7540, 0xCD71},{0x7547, 0xCFDA},{0x7548, 0xCFDB},
+ {0x754B, 0xACCB},{0x754C, 0xACC9},{0x754E, 0xACCA},{0x754F, 0xACC8},{0x7554, 0xAF60},{0x7559, 0xAF64},{0x755A, 0xAF63},{0x755B, 0xD2C1},
+ {0x755C, 0xAF62},{0x755D, 0xAF61},{0x755F, 0xD2C2},{0x7562, 0xB2A6},{0x7563, 0xD67B},{0x7564, 0xD67A},{0x7565, 0xB2A4},{0x7566, 0xB2A5},
+ {0x756A, 0xB566},{0x756B, 0xB565},{0x756C, 0xDAAE},{0x756F, 0xDAAD},{0x7570, 0xB2A7},{0x7576, 0xB7ED},{0x7577, 0xDEC5},{0x7578, 0xB7EE},
+ {0x7579, 0xDEC4},{0x757D, 0xE2D8},{0x757E, 0xE6AE},{0x757F, 0xBD42},{0x7580, 0xEA6A},{0x7584, 0xED73},{0x7586, 0xC3A6},{0x7587, 0xC3A5},
+ {0x758A, 0xC57C},{0x758B, 0xA5D4},{0x758C, 0xCD73},{0x758F, 0xB2A8},{0x7590, 0xE2D9},{0x7591, 0xBAC3},{0x7594, 0xCB6F},{0x7595, 0xCB70},
+ {0x7598, 0xCD74},{0x7599, 0xAAB8},{0x759A, 0xAAB9},{0x759D, 0xAAB7},{0x75A2, 0xACCF},{0x75A3, 0xACD0},{0x75A4, 0xACCD},{0x75A5, 0xACCE},
+ {0x75A7, 0xCFDC},{0x75AA, 0xCFDD},{0x75AB, 0xACCC},{0x75B0, 0xD2C3},{0x75B2, 0xAF68},{0x75B3, 0xAF69},{0x75B5, 0xB2AB},{0x75B6, 0xD2C9},
+ {0x75B8, 0xAF6E},{0x75B9, 0xAF6C},{0x75BA, 0xD2CA},{0x75BB, 0xD2C5},{0x75BC, 0xAF6B},{0x75BD, 0xAF6A},{0x75BE, 0xAF65},{0x75BF, 0xD2C8},
+ {0x75C0, 0xD2C7},{0x75C1, 0xD2C4},{0x75C2, 0xAF6D},{0x75C4, 0xD2C6},{0x75C5, 0xAF66},{0x75C7, 0xAF67},{0x75CA, 0xB2AC},{0x75CB, 0xD6A1},
+ {0x75CC, 0xD6A2},{0x75CD, 0xB2AD},{0x75CE, 0xD67C},{0x75CF, 0xD67E},{0x75D0, 0xD6A4},{0x75D1, 0xD6A3},{0x75D2, 0xD67D},{0x75D4, 0xB2A9},
+ {0x75D5, 0xB2AA},{0x75D7, 0xDAB6},{0x75D8, 0xB56B},{0x75D9, 0xB56A},{0x75DA, 0xDAB0},{0x75DB, 0xB568},{0x75DD, 0xDAB3},{0x75DE, 0xB56C},
+ {0x75DF, 0xDAB4},{0x75E0, 0xB56D},{0x75E1, 0xDAB1},{0x75E2, 0xB567},{0x75E3, 0xB569},{0x75E4, 0xDAB5},{0x75E6, 0xDAB2},{0x75E7, 0xDAAF},
+ {0x75ED, 0xDED2},{0x75EF, 0xDEC7},{0x75F0, 0xB7F0},{0x75F1, 0xB7F3},{0x75F2, 0xB7F2},{0x75F3, 0xB7F7},{0x75F4, 0xB7F6},{0x75F5, 0xDED3},
+ {0x75F6, 0xDED1},{0x75F7, 0xDECA},{0x75F8, 0xDECE},{0x75F9, 0xDECD},{0x75FA, 0xB7F4},{0x75FB, 0xDED0},{0x75FC, 0xDECC},{0x75FD, 0xDED4},
+ {0x75FE, 0xDECB},{0x75FF, 0xB7F5},{0x7600, 0xB7EF},{0x7601, 0xB7F1},{0x7603, 0xDEC9},{0x7608, 0xE2DB},{0x7609, 0xBAC7},{0x760A, 0xE2DF},
+ {0x760B, 0xBAC6},{0x760C, 0xE2DC},{0x760D, 0xBAC5},{0x760F, 0xDEC8},{0x7610, 0xDECF},{0x7611, 0xE2DE},{0x7613, 0xBAC8},{0x7614, 0xE2E0},
+ {0x7615, 0xE2DD},{0x7616, 0xE2DA},{0x7619, 0xE6B1},{0x761A, 0xE6B5},{0x761B, 0xE6B7},{0x761C, 0xE6B3},{0x761D, 0xE6B2},{0x761E, 0xE6B0},
+ {0x761F, 0xBD45},{0x7620, 0xBD43},{0x7621, 0xBD48},{0x7622, 0xBD49},{0x7623, 0xE6B4},{0x7624, 0xBD46},{0x7625, 0xE6AF},{0x7626, 0xBD47},
+ {0x7627, 0xBAC4},{0x7628, 0xE6B6},{0x7629, 0xBD44},{0x762D, 0xEA6C},{0x762F, 0xEA6B},{0x7630, 0xEA73},{0x7631, 0xEA6D},{0x7632, 0xEA72},
+ {0x7633, 0xEA6F},{0x7634, 0xBF60},{0x7635, 0xEA71},{0x7638, 0xBF61},{0x763A, 0xBF62},{0x763C, 0xEA70},{0x763D, 0xEA6E},{0x7642, 0xC0F8},
+ {0x7643, 0xED74},{0x7646, 0xC0F7},{0x7647, 0xED77},{0x7648, 0xED75},{0x7649, 0xED76},{0x764C, 0xC0F9},{0x7650, 0xF04D},{0x7652, 0xC2A1},
+ {0x7653, 0xF04E},{0x7656, 0xC27D},{0x7657, 0xF04F},{0x7658, 0xC27E},{0x7659, 0xF04C},{0x765A, 0xF050},{0x765C, 0xF04A},{0x765F, 0xC3A7},
+ {0x7660, 0xF278},{0x7661, 0xC3A8},{0x7662, 0xC46F},{0x7664, 0xF04B},{0x7665, 0xC470},{0x7669, 0xC4EE},{0x766A, 0xF5DF},{0x766C, 0xC57E},
+ {0x766D, 0xF6F4},{0x766E, 0xC57D},{0x7670, 0xF7EA},{0x7671, 0xC5F5},{0x7672, 0xC5F6},{0x7675, 0xF9CC},{0x7678, 0xACD1},{0x7679, 0xCFDE},
+ {0x767B, 0xB56E},{0x767C, 0xB56F},{0x767D, 0xA5D5},{0x767E, 0xA6CA},{0x767F, 0xCA47},{0x7681, 0xCB71},{0x7682, 0xA86D},{0x7684, 0xAABA},
+ {0x7686, 0xACD2},{0x7687, 0xACD3},{0x7688, 0xACD4},{0x7689, 0xD6A6},{0x768A, 0xD2CB},{0x768B, 0xAF6F},{0x768E, 0xB2AE},{0x768F, 0xD6A5},
+ {0x7692, 0xDAB8},{0x7693, 0xB571},{0x7695, 0xDAB7},{0x7696, 0xB570},{0x7699, 0xDED5},{0x769A, 0xBD4A},{0x769B, 0xE6BB},{0x769C, 0xE6B8},
+ {0x769D, 0xE6B9},{0x769E, 0xE6BA},{0x76A4, 0xED78},{0x76A6, 0xF051},{0x76AA, 0xF471},{0x76AB, 0xF470},{0x76AD, 0xF6F5},{0x76AE, 0xA5D6},
+ {0x76AF, 0xCD75},{0x76B0, 0xAF70},{0x76B4, 0xB572},{0x76B5, 0xDED6},{0x76B8, 0xE2E1},{0x76BA, 0xBD4B},{0x76BB, 0xEA74},{0x76BD, 0xF052},
+ {0x76BE, 0xF472},{0x76BF, 0xA5D7},{0x76C2, 0xAABB},{0x76C3, 0xACD7},{0x76C4, 0xCFDF},{0x76C5, 0xACD8},{0x76C6, 0xACD6},{0x76C8, 0xACD5},
+ {0x76C9, 0xD2CC},{0x76CA, 0xAF71},{0x76CD, 0xAF72},{0x76CE, 0xAF73},{0x76D2, 0xB2B0},{0x76D3, 0xD6A7},{0x76D4, 0xB2AF},{0x76DA, 0xDAB9},
+ {0x76DB, 0xB2B1},{0x76DC, 0xB573},{0x76DD, 0xDED7},{0x76DE, 0xB7F8},{0x76DF, 0xB7F9},{0x76E1, 0xBAC9},{0x76E3, 0xBACA},{0x76E4, 0xBD4C},
+ {0x76E5, 0xBF64},{0x76E6, 0xEA75},{0x76E7, 0xBF63},{0x76E9, 0xED79},{0x76EA, 0xC0FA},{0x76EC, 0xF053},{0x76ED, 0xF473},{0x76EE, 0xA5D8},
+ {0x76EF, 0xA86E},{0x76F0, 0xCD78},{0x76F1, 0xCD77},{0x76F2, 0xAABC},{0x76F3, 0xCD76},{0x76F4, 0xAABD},{0x76F5, 0xCD79},{0x76F7, 0xCFE5},
+ {0x76F8, 0xACDB},{0x76F9, 0xACDA},{0x76FA, 0xCFE7},{0x76FB, 0xCFE6},{0x76FC, 0xACDF},{0x76FE, 0xACDE},{0x7701, 0xACD9},{0x7703, 0xCFE1},
+ {0x7704, 0xCFE2},{0x7705, 0xCFE3},{0x7707, 0xACE0},{0x7708, 0xCFE0},{0x7709, 0xACDC},{0x770A, 0xCFE4},{0x770B, 0xACDD},{0x7710, 0xD2CF},
+ {0x7711, 0xD2D3},{0x7712, 0xD2D1},{0x7713, 0xD2D0},{0x7715, 0xD2D4},{0x7719, 0xD2D5},{0x771A, 0xD2D6},{0x771B, 0xD2CE},{0x771D, 0xD2CD},
+ {0x771F, 0xAF75},{0x7720, 0xAF76},{0x7722, 0xD2D7},{0x7723, 0xD2D2},{0x7725, 0xD6B0},{0x7727, 0xD2D8},{0x7728, 0xAF77},{0x7729, 0xAF74},
+ {0x772D, 0xD6AA},{0x772F, 0xD6A9},{0x7731, 0xD6AB},{0x7732, 0xD6AC},{0x7733, 0xD6AE},{0x7734, 0xD6AD},{0x7735, 0xD6B2},{0x7736, 0xB2B5},
+ {0x7737, 0xB2B2},{0x7738, 0xB2B6},{0x7739, 0xD6A8},{0x773A, 0xB2B7},{0x773B, 0xD6B1},{0x773C, 0xB2B4},{0x773D, 0xD6AF},{0x773E, 0xB2B3},
+ {0x7744, 0xDABC},{0x7745, 0xDABE},{0x7746, 0xDABA},{0x7747, 0xDABB},{0x774A, 0xDABF},{0x774B, 0xDAC1},{0x774C, 0xDAC2},{0x774D, 0xDABD},
+ {0x774E, 0xDAC0},{0x774F, 0xB574},{0x7752, 0xDEDB},{0x7754, 0xDEE0},{0x7755, 0xDED8},{0x7756, 0xDEDC},{0x7759, 0xDEE1},{0x775A, 0xDEDD},
+ {0x775B, 0xB7FA},{0x775C, 0xB843},{0x775E, 0xB7FD},{0x775F, 0xDED9},{0x7760, 0xDEDA},{0x7761, 0xBACE},{0x7762, 0xB846},{0x7763, 0xB7FE},
+ {0x7765, 0xB844},{0x7766, 0xB7FC},{0x7767, 0xDEDF},{0x7768, 0xB845},{0x7769, 0xDEDE},{0x776A, 0xB841},{0x776B, 0xB7FB},{0x776C, 0xB842},
+ {0x776D, 0xDEE2},{0x776E, 0xE2E6},{0x776F, 0xE2E8},{0x7779, 0xB840},{0x777C, 0xE2E3},{0x777D, 0xBACC},{0x777E, 0xE2E9},{0x777F, 0xBACD},
+ {0x7780, 0xE2E7},{0x7781, 0xE2E2},{0x7782, 0xE2E5},{0x7783, 0xE2EA},{0x7784, 0xBACB},{0x7785, 0xE2E4},{0x7787, 0xBD4E},{0x7788, 0xE6BF},
+ {0x7789, 0xE6BE},{0x778B, 0xBD51},{0x778C, 0xBD4F},{0x778D, 0xE6BC},{0x778E, 0xBD4D},{0x778F, 0xE6BD},{0x7791, 0xBD50},{0x7795, 0xEA7D},
+ {0x7797, 0xEAA1},{0x7799, 0xEA7E},{0x779A, 0xEA76},{0x779B, 0xEA7A},{0x779C, 0xEA79},{0x779D, 0xEA77},{0x779E, 0xBF66},{0x779F, 0xBF67},
+ {0x77A0, 0xBF65},{0x77A1, 0xEA78},{0x77A2, 0xEA7B},{0x77A3, 0xEA7C},{0x77A5, 0xBF68},{0x77A7, 0xC140},{0x77A8, 0xEDA3},{0x77AA, 0xC0FC},
+ {0x77AB, 0xED7B},{0x77AC, 0xC0FE},{0x77AD, 0xC141},{0x77B0, 0xC0FD},{0x77B1, 0xEDA2},{0x77B2, 0xED7C},{0x77B3, 0xC0FB},{0x77B4, 0xEDA1},
+ {0x77B5, 0xED7A},{0x77B6, 0xED7E},{0x77B7, 0xED7D},{0x77BA, 0xF055},{0x77BB, 0xC2A4},{0x77BC, 0xC2A5},{0x77BD, 0xC2A2},{0x77BF, 0xC2A3},
+ {0x77C2, 0xF054},{0x77C4, 0xF27B},{0x77C7, 0xC3A9},{0x77C9, 0xF279},{0x77CA, 0xF27A},{0x77CC, 0xF474},{0x77CD, 0xF477},{0x77CE, 0xF475},
+ {0x77CF, 0xF476},{0x77D0, 0xF5E0},{0x77D3, 0xC4EF},{0x77D4, 0xF7EB},{0x77D5, 0xF8B4},{0x77D7, 0xC5F7},{0x77D8, 0xF8F8},{0x77D9, 0xF8F9},
+ {0x77DA, 0xC666},{0x77DB, 0xA5D9},{0x77DC, 0xACE1},{0x77DE, 0xDAC3},{0x77E0, 0xDEE3},{0x77E2, 0xA5DA},{0x77E3, 0xA86F},{0x77E5, 0xAABE},
+ {0x77E7, 0xCFE8},{0x77E8, 0xCFE9},{0x77E9, 0xAF78},{0x77EC, 0xDAC4},{0x77ED, 0xB575},{0x77EE, 0xB847},{0x77EF, 0xC142},{0x77F0, 0xEDA4},
+ {0x77F1, 0xF27C},{0x77F2, 0xF478},{0x77F3, 0xA5DB},{0x77F7, 0xCDA1},{0x77F8, 0xCD7A},{0x77F9, 0xCD7C},{0x77FA, 0xCD7E},{0x77FB, 0xCD7D},
+ {0x77FC, 0xCD7B},{0x77FD, 0xAABF},{0x7802, 0xACE2},{0x7803, 0xCFF2},{0x7805, 0xCFED},{0x7806, 0xCFEA},{0x7809, 0xCFF1},{0x780C, 0xACE4},
+ {0x780D, 0xACE5},{0x780E, 0xCFF0},{0x780F, 0xCFEF},{0x7810, 0xCFEE},{0x7811, 0xCFEB},{0x7812, 0xCFEC},{0x7813, 0xCFF3},{0x7814, 0xACE3},
+ {0x781D, 0xAF7C},{0x781F, 0xAFA4},{0x7820, 0xAFA3},{0x7821, 0xD2E1},{0x7822, 0xD2DB},{0x7823, 0xD2D9},{0x7825, 0xAFA1},{0x7826, 0xD6B9},
+ {0x7827, 0xAF7A},{0x7828, 0xD2DE},{0x7829, 0xD2E2},{0x782A, 0xD2E4},{0x782B, 0xD2E0},{0x782C, 0xD2DA},{0x782D, 0xAFA2},{0x782E, 0xD2DF},
+ {0x782F, 0xD2DD},{0x7830, 0xAF79},{0x7831, 0xD2E5},{0x7832, 0xAFA5},{0x7833, 0xD2E3},{0x7834, 0xAF7D},{0x7835, 0xD2DC},{0x7837, 0xAF7E},
+ {0x7838, 0xAF7B},{0x7843, 0xB2B9},{0x7845, 0xD6BA},{0x7848, 0xD6B3},{0x7849, 0xD6B5},{0x784A, 0xD6B7},{0x784C, 0xD6B8},{0x784D, 0xD6B6},
+ {0x784E, 0xB2BA},{0x7850, 0xD6BB},{0x7852, 0xD6B4},{0x785C, 0xDAC8},{0x785D, 0xB576},{0x785E, 0xDAD0},{0x7860, 0xDAC5},{0x7862, 0xDAD1},
+ {0x7864, 0xDAC6},{0x7865, 0xDAC7},{0x7868, 0xDACF},{0x7869, 0xDACE},{0x786A, 0xDACB},{0x786B, 0xB2B8},{0x786C, 0xB577},{0x786D, 0xDAC9},
+ {0x786E, 0xDACC},{0x786F, 0xB578},{0x7870, 0xDACD},{0x7871, 0xDACA},{0x7879, 0xDEEE},{0x787B, 0xDEF2},{0x787C, 0xB84E},{0x787E, 0xE2F0},
+ {0x787F, 0xB851},{0x7880, 0xDEF0},{0x7883, 0xDEED},{0x7884, 0xDEE8},{0x7885, 0xDEEA},{0x7886, 0xDEEB},{0x7887, 0xDEE4},{0x7889, 0xB84D},</