gfx/graphite2/src/TtfUtil.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /*  GRAPHITE2 LICENSING
     3     Copyright 2010, SIL International
     4     All rights reserved.
     6     This library is free software; you can redistribute it and/or modify
     7     it under the terms of the GNU Lesser General Public License as published
     8     by the Free Software Foundation; either version 2.1 of License, or
     9     (at your option) any later version.
    11     This program is distributed in the hope that it will be useful,
    12     but WITHOUT ANY WARRANTY; without even the implied warranty of
    13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    14     Lesser General Public License for more details.
    16     You should also have received a copy of the GNU Lesser General Public
    17     License along with this library in the file named "LICENSE".
    18     If not, write to the Free Software Foundation, 51 Franklin Street, 
    19     Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 
    20     internet at http://www.fsf.org/licenses/lgpl.html.
    22 Alternatively, the contents of this file may be used under the terms of the
    23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
    24 License, as published by the Free Software Foundation, either version 2
    25 of the License or (at your option) any later version.
    26 */
    27 /*--------------------------------------------------------------------*//*:Ignore this sentence.
    29 File: TtfUtil.cpp
    30 Responsibility: Alan Ward
    31 Last reviewed: Not yet.
    33 Description
    34     Implements the methods for TtfUtil class. This file should remain portable to any C++ 
    35     environment by only using standard C++ and the TTF structurs defined in Tt.h.
    36 -------------------------------------------------------------------------------*//*:End Ignore*/
    39 /***********************************************************************************************
    40     Include files
    41 ***********************************************************************************************/
    42 // Language headers
    43 //#include <algorithm>
    44 #include <cassert>
    45 #include <cstddef>
    46 #include <cstring>
    47 #include <climits>
    48 #include <cwchar>
    49 //#include <stdexcept>
    50 // Platform headers
    51 // Module headers
    52 #include "inc/TtfUtil.h"
    53 #include "inc/TtfTypes.h"
    54 #include "inc/Endian.h"
    56 /***********************************************************************************************
    57     Forward declarations
    58 ***********************************************************************************************/
    60 /***********************************************************************************************
    61     Local Constants and static variables
    62 ***********************************************************************************************/
    63 namespace 
    64 {
    65     // max number of components allowed in composite glyphs
    66     const int kMaxGlyphComponents = 8;
    68     template <int R, typename T>
    69     inline float fixed_to_float(const T f) {
    70         return float(f)/float(2^R);
    71     }
    73 /*----------------------------------------------------------------------------------------------
    74     Table of standard Postscript glyph names. From Martin Hosken. Disagress with ttfdump.exe
    75 ---------------------------------------------------------------------------------------------*/
    76 #ifdef ALL_TTFUTILS
    77     const int kcPostNames = 258;
    79     const char * rgPostName[kcPostNames] = {
    80         ".notdef", ".null", "nonmarkingreturn", "space", "exclam", "quotedbl", "numbersign", 
    81         "dollar", "percent", "ampersand", "quotesingle", "parenleft", 
    82         "parenright", "asterisk", "plus", "comma", "hyphen", "period", "slash", 
    83         "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", 
    84         "nine", "colon", "semicolon", "less", "equal", "greater", "question", 
    85         "at", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", 
    86         "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", 
    87         "bracketleft", "backslash", "bracketright", "asciicircum", 
    88         "underscore", "grave", "a", "b", "c", "d", "e", "f", "g", "h", "i", 
    89         "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", 
    90         "x", "y", "z", "braceleft", "bar", "braceright", "asciitilde", 
    91         "Adieresis", "Aring", "Ccedilla", "Eacute", "Ntilde", "Odieresis", 
    92         "Udieresis", "aacute", "agrave", "acircumflex", "adieresis", "atilde", 
    93         "aring", "ccedilla", "eacute", "egrave", "ecircumflex", "edieresis", 
    94         "iacute", "igrave", "icircumflex", "idieresis", "ntilde", "oacute", 
    95         "ograve", "ocircumflex", "odieresis", "otilde", "uacute", "ugrave", 
    96         "ucircumflex", "udieresis", "dagger", "degree", "cent", "sterling", 
    97         "section", "bullet", "paragraph", "germandbls", "registered", 
    98         "copyright", "trademark", "acute", "dieresis", "notequal", "AE", 
    99         "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", "yen", 
   100         "mu", "partialdiff", "summation", "product", "pi", "integral", 
   101         "ordfeminine", "ordmasculine", "Omega", "ae", "oslash", "questiondown", 
   102         "exclamdown", "logicalnot", "radical", "florin", "approxequal", 
   103         "Delta", "guillemotleft", "guillemotright", "ellipsis", "nonbreakingspace", 
   104         "Agrave", "Atilde", "Otilde", "OE", "oe", "endash", "emdash", 
   105         "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", 
   106         "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", 
   107         "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", "periodcentered", 
   108         "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", 
   109         "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", 
   110         "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", 
   111         "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", "dotlessi", 
   112         "circumflex", "tilde", "macron", "breve", "dotaccent", "ring", 
   113         "cedilla", "hungarumlaut", "ogonek", "caron", "Lslash", "lslash", 
   114         "Scaron", "scaron", "Zcaron", "zcaron", "brokenbar", "Eth", "eth", 
   115         "Yacute", "yacute", "Thorn", "thorn", "minus", "multiply", 
   116         "onesuperior", "twosuperior", "threesuperior", "onehalf", "onequarter", 
   117         "threequarters", "franc", "Gbreve", "gbreve", "Idotaccent", "Scedilla", 
   118         "scedilla", "Cacute", "cacute", "Ccaron", "ccaron", 
   119         "dcroat" };
   120 #endif
   122 } // end of namespace
   124 /***********************************************************************************************
   125     Methods
   126 ***********************************************************************************************/
   128 /* Note on error processing: The code guards against bad glyph ids being used to look up data
   129 in open ended tables (loca, hmtx). If the glyph id comes from a cmap this shouldn't happen 
   130 but it seems prudent to check for user errors here. The code does assume that data obtained 
   131 from the TTF file is valid otherwise (though the CheckTable method seeks to check for 
   132 obvious problems that might accompany a change in table versions). For example an invalid 
   133 offset in the loca table which could exceed the size of the glyf table is NOT trapped.
   134 Likewise if numberOf_LongHorMetrics in the hhea table is wrong, this will NOT be trapped, 
   135 which could cause a lookup in the hmtx table to exceed the table length. Of course, TTF tables
   136 that are completely corrupt will cause unpredictable results. */
   138 /* Note on composite glyphs: Glyphs that have components that are themselves composites
   139 are not supported. IsDeepComposite can be used to test for this. False is returned from many 
   140 of the methods in this cases. It is unclear how to build composite glyphs in some cases, 
   141 so this code represents my best guess until test cases can be found. See notes on the high-
   142 level GlyfPoints method. */
   143 namespace graphite2
   144 {
   145 namespace TtfUtil
   146 {
   149 /*----------------------------------------------------------------------------------------------
   150     Get offset and size of the offset table needed to find table directory.
   151     Return true if success, false otherwise.
   152     lSize excludes any table directory entries.
   153 ----------------------------------------------------------------------------------------------*/
   154 bool GetHeaderInfo(size_t & lOffset, size_t & lSize)
   155 {
   156     lOffset = 0;
   157     lSize   = offsetof(Sfnt::OffsetSubTable, table_directory);
   158     assert(sizeof(uint32) + 4*sizeof (uint16) == lSize);
   159     return true;
   160 }
   162 /*----------------------------------------------------------------------------------------------
   163     Check the offset table for expected data.
   164     Return true if success, false otherwise.
   165 ----------------------------------------------------------------------------------------------*/
   166 bool CheckHeader(const void * pHdr)
   167 {
   168     const Sfnt::OffsetSubTable * pOffsetTable  
   169         = reinterpret_cast<const Sfnt::OffsetSubTable *>(pHdr);
   171     return pHdr && be::swap(pOffsetTable->scaler_type) == Sfnt::OffsetSubTable::TrueTypeWin;
   172 }
   174 /*----------------------------------------------------------------------------------------------
   175     Get offset and size of the table directory.
   176     Return true if successful, false otherwise.
   177 ----------------------------------------------------------------------------------------------*/
   178 bool GetTableDirInfo(const void * pHdr, size_t & lOffset, size_t & lSize)
   179 {
   180     const Sfnt::OffsetSubTable * pOffsetTable
   181         = reinterpret_cast<const Sfnt::OffsetSubTable *>(pHdr);
   183     lOffset = offsetof(Sfnt::OffsetSubTable, table_directory);
   184     lSize   = be::swap(pOffsetTable->num_tables)
   185         * sizeof(Sfnt::OffsetSubTable::Entry);
   187     return true;
   188 }
   191 /*----------------------------------------------------------------------------------------------
   192     Get offset and size of the specified table.
   193     Return true if successful, false otherwise. On false, offset and size will be 0.
   194 ----------------------------------------------------------------------------------------------*/
   195 bool GetTableInfo(const Tag TableTag, const void * pHdr, const void * pTableDir,
   196                            size_t & lOffset, size_t & lSize)
   197 {
   198     const Sfnt::OffsetSubTable * pOffsetTable 
   199         = reinterpret_cast<const Sfnt::OffsetSubTable *>(pHdr);
   200     const size_t num_tables = be::swap(pOffsetTable->num_tables);
   201     const Sfnt::OffsetSubTable::Entry 
   202         * entry_itr = reinterpret_cast<const Sfnt::OffsetSubTable::Entry *>(
   203             pTableDir),
   204         * const  dir_end = entry_itr + num_tables;
   206     if (num_tables > 40)
   207         return false;
   209     for (;entry_itr != dir_end; ++entry_itr) // 40 - safe guard
   210     {
   211         if (be::swap(entry_itr->tag) == TableTag)
   212         {
   213             lOffset = be::swap(entry_itr->offset);
   214             lSize   = be::swap(entry_itr->length);
   215             return true;
   216         }
   217     }
   219     return false;
   220 }
   222 /*----------------------------------------------------------------------------------------------
   223     Check the specified table. Tests depend on the table type.
   224     Return true if successful, false otherwise.
   225 ----------------------------------------------------------------------------------------------*/
   226 bool CheckTable(const Tag TableId, const void * pTable, size_t lTableSize)
   227 {
   228     using namespace Sfnt;
   230     if (pTable == 0) return false;
   232     switch(TableId)
   233     {
   234     case Tag::cmap: // cmap
   235     {
   236         const Sfnt::CharacterCodeMap * const pCmap 
   237             = reinterpret_cast<const Sfnt::CharacterCodeMap *>(pTable);
   238         return be::swap(pCmap->version) == 0;
   239     }
   241     case Tag::head: // head
   242     {
   243         const Sfnt::FontHeader * const pHead 
   244             = reinterpret_cast<const Sfnt::FontHeader *>(pTable);
   245         bool r = be::swap(pHead->version) == OneFix
   246             && be::swap(pHead->magic_number) == FontHeader::MagicNumber
   247             && be::swap(pHead->glyph_data_format)
   248                     == FontHeader::GlypDataFormat 
   249             && (be::swap(pHead->index_to_loc_format)
   250                     == FontHeader::ShortIndexLocFormat 
   251                 || be::swap(pHead->index_to_loc_format)
   252                     == FontHeader::LongIndexLocFormat) 
   253             && sizeof(FontHeader) <= lTableSize;
   254         return r;
   255     }
   257     case Tag::post: // post
   258     {
   259         const Sfnt::PostScriptGlyphName * const pPost 
   260             = reinterpret_cast<const Sfnt::PostScriptGlyphName *>(pTable);
   261         const fixed format = be::swap(pPost->format);
   262         bool r = format == PostScriptGlyphName::Format1 
   263             || format == PostScriptGlyphName::Format2 
   264             || format == PostScriptGlyphName::Format3 
   265             || format == PostScriptGlyphName::Format25;
   266         return r;
   267     }
   269     case Tag::hhea: // hhea
   270     {
   271         const Sfnt::HorizontalHeader * pHhea = 
   272             reinterpret_cast<const Sfnt::HorizontalHeader *>(pTable);
   273         bool r = be::swap(pHhea->version) == OneFix
   274             && be::swap(pHhea->metric_data_format) == 0
   275             && sizeof (Sfnt::HorizontalHeader) <= lTableSize;
   276         return r;
   277     }
   279     case Tag::maxp: // maxp
   280     {
   281         const Sfnt::MaximumProfile * pMaxp = 
   282             reinterpret_cast<const Sfnt::MaximumProfile *>(pTable);
   283         bool r = be::swap(pMaxp->version) == OneFix
   284             && sizeof(Sfnt::MaximumProfile) <= lTableSize;
   285         return r;
   286     }
   288     case Tag::OS_2: // OS/2
   289     {
   290         const Sfnt::Compatibility * pOs2 
   291             = reinterpret_cast<const Sfnt::Compatibility *>(pTable);
   292         if (be::swap(pOs2->version) == 0)
   293         { // OS/2 table version 1 size
   294 //          if (sizeof(Sfnt::Compatibility) 
   295 //                  - sizeof(uint32)*2 - sizeof(int16)*2 
   296 //                  - sizeof(uint16)*3 <= lTableSize)
   297             if (sizeof(Sfnt::Compatibility0) <= lTableSize)
   298                 return true;
   299         }
   300         else if (be::swap(pOs2->version) == 1)
   301         { // OS/2 table version 2 size
   302 //          if (sizeof(Sfnt::Compatibility) 
   303 //                  - sizeof(int16) *2 
   304 //                  - sizeof(uint16)*3 <= lTableSize)
   305             if (sizeof(Sfnt::Compatibility1) <= lTableSize)
   306                 return true;
   307         }
   308         else if (be::swap(pOs2->version) == 2)
   309         { // OS/2 table version 3 size
   310             if (sizeof(Sfnt::Compatibility2) <= lTableSize)
   311                 return true;
   312         }
   313         else if (be::swap(pOs2->version) == 3 || be::swap(pOs2->version) == 4)
   314         { // OS/2 table version 4 size - version 4 changed the meaning of some fields which we don't use
   315             if (sizeof(Sfnt::Compatibility3) <= lTableSize)
   316                 return true;
   317         }
   318         else
   319             return false;
   320         break;
   321     }
   323     case Tag::name:
   324     {
   325         const Sfnt::FontNames * pName 
   326             = reinterpret_cast<const Sfnt::FontNames *>(pTable);
   327         return be::swap(pName->format) == 0;
   328     }
   330     default:
   331         break;
   332     }
   334     return true;
   335 }
   337 /*----------------------------------------------------------------------------------------------
   338     Return the number of glyphs in the font. Should never be less than zero.
   340     Note: this method is not currently used by the Graphite engine.
   341 ----------------------------------------------------------------------------------------------*/
   342 size_t GlyphCount(const void * pMaxp)
   343 {
   344     const Sfnt::MaximumProfile * pTable = 
   345             reinterpret_cast<const Sfnt::MaximumProfile *>(pMaxp);
   346     return be::swap(pTable->num_glyphs);
   347 }
   349 #ifdef ALL_TTFUTILS
   350 /*----------------------------------------------------------------------------------------------
   351     Return the maximum number of components for any composite glyph in the font.
   353     Note: this method is not currently used by the Graphite engine.
   354 ----------------------------------------------------------------------------------------------*/
   355 size_t  MaxCompositeComponentCount(const void * pMaxp)
   356 {
   357     const Sfnt::MaximumProfile * pTable = 
   358             reinterpret_cast<const Sfnt::MaximumProfile *>(pMaxp);
   359     return be::swap(pTable->max_component_elements);
   360 }
   362 /*----------------------------------------------------------------------------------------------
   363     Composite glyphs can be composed of glyphs that are themselves composites.
   364     This method returns the maximum number of levels like this for any glyph in the font.
   365     A non-composite glyph has a level of 1.
   367     Note: this method is not currently used by the Graphite engine.
   368 ----------------------------------------------------------------------------------------------*/
   369 size_t  MaxCompositeLevelCount(const void * pMaxp)
   370 {
   371     const Sfnt::MaximumProfile * pTable = 
   372             reinterpret_cast<const Sfnt::MaximumProfile *>(pMaxp);
   373     return be::swap(pTable->max_component_depth);
   374 }
   376 /*----------------------------------------------------------------------------------------------
   377     Return the number of glyphs in the font according to a differt source.
   378     Should never be less than zero. Return -1 on failure.
   380     Note: this method is not currently used by the Graphite engine.
   381 ----------------------------------------------------------------------------------------------*/
   382 size_t LocaGlyphCount(size_t lLocaSize, const void * pHead) //throw(std::domain_error)
   383 {
   385     const Sfnt::FontHeader * pTable 
   386         = reinterpret_cast<const Sfnt::FontHeader *>(pHead);
   388     if (be::swap(pTable->index_to_loc_format)
   389         == Sfnt::FontHeader::ShortIndexLocFormat)
   390     // loca entries are two bytes and have been divided by two
   391         return (lLocaSize >> 1) - 1;
   393     if (be::swap(pTable->index_to_loc_format)
   394         == Sfnt::FontHeader::LongIndexLocFormat)
   395      // loca entries are four bytes
   396         return (lLocaSize >> 2) - 1;
   398     return -1;
   399     //throw std::domain_error("head table in inconsistent state. The font may be corrupted");
   400 }
   401 #endif
   403 /*----------------------------------------------------------------------------------------------
   404     Return the design units the font is designed with
   405 ----------------------------------------------------------------------------------------------*/
   406 int DesignUnits(const void * pHead)
   407 {
   408     const Sfnt::FontHeader * pTable = 
   409             reinterpret_cast<const Sfnt::FontHeader *>(pHead);
   411     return be::swap(pTable->units_per_em);
   412 }
   414 #ifdef ALL_TTFUTILS
   415 /*----------------------------------------------------------------------------------------------
   416     Return the checksum from the head table, which serves as a unique identifer for the font.
   417 ----------------------------------------------------------------------------------------------*/
   418 int HeadTableCheckSum(const void * pHead)
   419 {
   420     const Sfnt::FontHeader * pTable = 
   421             reinterpret_cast<const Sfnt::FontHeader *>(pHead);
   423     return be::swap(pTable->check_sum_adjustment);
   424 }
   426 /*----------------------------------------------------------------------------------------------
   427     Return the create time from the head table. This consists of a 64-bit integer, which
   428     we return here as two 32-bit integers.
   430     Note: this method is not currently used by the Graphite engine.
   431 ----------------------------------------------------------------------------------------------*/
   432 void HeadTableCreateTime(const void * pHead,
   433     unsigned int * pnDateBC, unsigned int * pnDateAD)
   434 {
   435     const Sfnt::FontHeader * pTable = 
   436             reinterpret_cast<const Sfnt::FontHeader *>(pHead);
   438     *pnDateBC = be::swap(pTable->created[0]);
   439     *pnDateAD = be::swap(pTable->created[1]);
   440 }
   442 /*----------------------------------------------------------------------------------------------
   443     Return the modify time from the head table.This consists of a 64-bit integer, which
   444     we return here as two 32-bit integers.
   446     Note: this method is not currently used by the Graphite engine.
   447 ----------------------------------------------------------------------------------------------*/
   448 void HeadTableModifyTime(const void * pHead,
   449     unsigned int * pnDateBC, unsigned int *pnDateAD)
   450 {
   451     const Sfnt::FontHeader * pTable = 
   452             reinterpret_cast<const Sfnt::FontHeader *>(pHead);
   454     *pnDateBC = be::swap(pTable->modified[0]);
   455     *pnDateAD = be::swap(pTable->modified[1]);
   456 }
   458 /*----------------------------------------------------------------------------------------------
   459     Return true if the font is italic.
   460 ----------------------------------------------------------------------------------------------*/
   461 bool IsItalic(const void * pHead)
   462 {
   463     const Sfnt::FontHeader * pTable = 
   464             reinterpret_cast<const Sfnt::FontHeader *>(pHead);
   466     return ((be::swap(pTable->mac_style) & 0x00000002) != 0);
   467 }
   469 /*----------------------------------------------------------------------------------------------
   470     Return the ascent for the font
   471 ----------------------------------------------------------------------------------------------*/
   472 int FontAscent(const void * pOs2)
   473 {
   474     const Sfnt::Compatibility * pTable = reinterpret_cast<const Sfnt::Compatibility *>(pOs2);
   476     return be::swap(pTable->win_ascent);
   477 }
   479 /*----------------------------------------------------------------------------------------------
   480     Return the descent for the font
   481 ----------------------------------------------------------------------------------------------*/
   482 int FontDescent(const void * pOs2)
   483 {
   484     const Sfnt::Compatibility * pTable = reinterpret_cast<const Sfnt::Compatibility *>(pOs2);
   486     return be::swap(pTable->win_descent);
   487 }
   489 /*----------------------------------------------------------------------------------------------
   490     Get the bold and italic style bits.
   491     Return true if successful. false otherwise.
   492     In addition to checking the OS/2 table, one could also check
   493         the head table's macStyle field (overridden by the OS/2 table on Win)
   494         the sub-family name in the name table (though this can contain oblique, dark, etc too)
   495 ----------------------------------------------------------------------------------------------*/
   496 bool FontOs2Style(const void *pOs2, bool & fBold, bool & fItalic)
   497 {
   498     const Sfnt::Compatibility * pTable = reinterpret_cast<const Sfnt::Compatibility *>(pOs2);
   500     fBold = (be::swap(pTable->fs_selection) & Sfnt::Compatibility::Bold) != 0;
   501     fItalic = (be::swap(pTable->fs_selection) & Sfnt::Compatibility::Italic) != 0;
   503     return true;
   504 }
   505 #endif
   507 /*----------------------------------------------------------------------------------------------
   508     Method for searching name table.
   509 ----------------------------------------------------------------------------------------------*/
   510 bool GetNameInfo(const void * pName, int nPlatformId, int nEncodingId,
   511         int nLangId, int nNameId, size_t & lOffset, size_t & lSize)
   512 {
   513     lOffset = 0;
   514     lSize = 0;
   516     const Sfnt::FontNames * pTable = reinterpret_cast<const Sfnt::FontNames *>(pName);
   517     uint16 cRecord = be::swap(pTable->count);
   518     uint16 nRecordOffset = be::swap(pTable->string_offset);
   519     const Sfnt::NameRecord * pRecord = reinterpret_cast<const Sfnt::NameRecord *>(pTable + 1);
   521     for (int i = 0; i < cRecord; ++i)
   522     {
   523         if (be::swap(pRecord->platform_id) == nPlatformId &&
   524             be::swap(pRecord->platform_specific_id) == nEncodingId &&
   525             be::swap(pRecord->language_id) == nLangId &&
   526             be::swap(pRecord->name_id) == nNameId)
   527         {
   528             lOffset = be::swap(pRecord->offset) + nRecordOffset;
   529             lSize = be::swap(pRecord->length);
   530             return true;
   531         }
   532         pRecord++;
   533     }
   535     return false;
   536 }
   538 #ifdef ALL_TTFUTILS
   539 /*----------------------------------------------------------------------------------------------
   540     Return all the lang-IDs that have data for the given name-IDs. Assume that there is room
   541     in the return array (langIdList) for 128 items. The purpose of this method is to return
   542     a list of all possible lang-IDs.
   543 ----------------------------------------------------------------------------------------------*/
   544 int GetLangsForNames(const void * pName, int nPlatformId, int nEncodingId,
   545         int * nameIdList, int cNameIds, short * langIdList)
   546 {
   547     const Sfnt::FontNames * pTable = reinterpret_cast<const Sfnt::FontNames *>(pName);
   548         int cLangIds = 0;
   549     uint16 cRecord = be::swap(pTable->count);
   550         if (cRecord > 127) return cLangIds;
   551     //uint16 nRecordOffset = swapw(pTable->stringOffset);
   552     const Sfnt::NameRecord * pRecord = reinterpret_cast<const Sfnt::NameRecord *>(pTable + 1);
   554     for (int i = 0; i < cRecord; ++i)
   555     {
   556         if (be::swap(pRecord->platform_id) == nPlatformId &&
   557             be::swap(pRecord->platform_specific_id) == nEncodingId)
   558         {
   559             bool fNameFound = false;
   560             int nLangId = be::swap(pRecord->language_id);
   561             int nNameId = be::swap(pRecord->name_id);
   562             for (int j = 0; j < cNameIds; j++)
   563             {
   564                 if (nNameId == nameIdList[j])
   565                 {
   566                     fNameFound = true;
   567                     break;
   568                 }
   569             }
   570             if (fNameFound)
   571             {
   572                 // Add it if it's not there.
   573                 int ilang;
   574                 for (ilang = 0; ilang < cLangIds; ilang++)
   575                     if (langIdList[ilang] == nLangId)
   576                         break;
   577                 if (ilang >= cLangIds)
   578                 {
   579                     langIdList[cLangIds] = short(nLangId);
   580                     cLangIds++;
   581                 }
   582                 if (cLangIds == 128)
   583                     return cLangIds;
   584             }
   585         }
   586         pRecord++;
   587     }
   589     return cLangIds;
   590 }
   592 /*----------------------------------------------------------------------------------------------
   593     Get the offset and size of the font family name in English for the MS Platform with Unicode
   594     writing system. The offset is within the pName data. The string is double byte with MSB
   595     first.
   596 ----------------------------------------------------------------------------------------------*/
   597 bool Get31EngFamilyInfo(const void * pName, size_t & lOffset, size_t & lSize)
   598 {
   599     return GetNameInfo(pName, Sfnt::NameRecord::Microsoft, 1, 1033, 
   600         Sfnt::NameRecord::Family, lOffset, lSize);
   601 }
   603 /*----------------------------------------------------------------------------------------------
   604     Get the offset and size of the full font name in English for the MS Platform with Unicode
   605     writing system. The offset is within the pName data. The string is double byte with MSB
   606     first.
   608     Note: this method is not currently used by the Graphite engine.
   609 ----------------------------------------------------------------------------------------------*/
   610 bool Get31EngFullFontInfo(const void * pName, size_t & lOffset, size_t & lSize)
   611 {
   612     return GetNameInfo(pName, Sfnt::NameRecord::Microsoft, 1, 1033, 
   613         Sfnt::NameRecord::Fullname, lOffset, lSize);
   614 }
   616 /*----------------------------------------------------------------------------------------------
   617     Get the offset and size of the font family name in English for the MS Platform with Symbol
   618     writing system. The offset is within the pName data. The string is double byte with MSB
   619     first.
   620 ----------------------------------------------------------------------------------------------*/
   621 bool Get30EngFamilyInfo(const void * pName, size_t & lOffset, size_t & lSize)
   622 {
   623     return GetNameInfo(pName, Sfnt::NameRecord::Microsoft, 0, 1033, 
   624         Sfnt::NameRecord::Family, lOffset, lSize);
   625 }
   627 /*----------------------------------------------------------------------------------------------
   628     Get the offset and size of the full font name in English for the MS Platform with Symbol
   629     writing system. The offset is within the pName data. The string is double byte with MSB
   630     first.
   632     Note: this method is not currently used by the Graphite engine.
   633 ----------------------------------------------------------------------------------------------*/
   634 bool Get30EngFullFontInfo(const void * pName, size_t & lOffset, size_t & lSize)
   635 {
   636     return GetNameInfo(pName, Sfnt::NameRecord::Microsoft, 0, 1033, 
   637         Sfnt::NameRecord::Fullname, lOffset, lSize);
   638 }
   640 /*----------------------------------------------------------------------------------------------
   641     Return the Glyph ID for a given Postscript name. This method finds the first glyph which
   642     matches the requested Postscript name. Ideally every glyph should have a unique Postscript 
   643     name (except for special names such as .notdef), but this is not always true.
   644     On failure return value less than zero.
   645        -1 - table search failed
   646        -2 - format 3 table (no Postscript glyph info)
   647        -3 - other failures
   649     Note: this method is not currently used by the Graphite engine.
   650 ----------------------------------------------------------------------------------------------*/
   651 int PostLookup(const void * pPost, size_t lPostSize, const void * pMaxp, 
   652                         const char * pPostName)
   653 {
   654     using namespace Sfnt;
   656     const Sfnt::PostScriptGlyphName * pTable 
   657         = reinterpret_cast<const Sfnt::PostScriptGlyphName *>(pPost);
   658     fixed format = be::swap(pTable->format);
   660     if (format == PostScriptGlyphName::Format3)
   661     { // format 3 - no Postscript glyph info in font
   662         return -2;
   663     }
   665     // search for given Postscript name among the standard names
   666     int iPostName = -1; // index in standard names
   667     for (int i = 0; i < kcPostNames; i++)
   668     {
   669         if (!strcmp(pPostName, rgPostName[i]))
   670         {
   671             iPostName = i;
   672             break;
   673         }
   674     }
   676     if (format == PostScriptGlyphName::Format1)
   677     { // format 1 - use standard Postscript names
   678         return iPostName;
   679     }
   681     if (format == PostScriptGlyphName::Format25)
   682     { 
   683         if (iPostName == -1)
   684             return -1;
   686         const PostScriptGlyphName25 * pTable25 
   687             = static_cast<const PostScriptGlyphName25 *>(pTable);
   688         int cnGlyphs = GlyphCount(pMaxp);
   689         for (gid16 nGlyphId = 0; nGlyphId < cnGlyphs && nGlyphId < kcPostNames; 
   690                 nGlyphId++)
   691         { // glyph_name_index25 contains bytes so no byte swapping needed
   692           // search for first glyph id that uses the standard name 
   693             if (nGlyphId + pTable25->offset[nGlyphId] == iPostName)
   694                 return nGlyphId;
   695         }
   696     }
   698     if (format == PostScriptGlyphName::Format2)
   699     { // format 2
   700         const PostScriptGlyphName2 * pTable2 
   701             = static_cast<const PostScriptGlyphName2 *>(pTable);
   703         int cnGlyphs = be::swap(pTable2->number_of_glyphs);
   705         if (iPostName != -1)
   706         { // did match a standard name, look for first glyph id mapped to that name
   707             for (gid16 nGlyphId = 0; nGlyphId < cnGlyphs; nGlyphId++)
   708             {
   709                 if (be::swap(pTable2->glyph_name_index[nGlyphId]) == iPostName)
   710                     return nGlyphId;
   711             }
   712         }
   714         { // did not match a standard name, search font specific names
   715             size_t nStrSizeGoal = strlen(pPostName);
   716             const char * pFirstGlyphName = reinterpret_cast<const char *>(
   717                 &pTable2->glyph_name_index[0] + cnGlyphs);
   718             const char * pGlyphName = pFirstGlyphName;
   719             int iInNames = 0; // index in font specific names
   720             bool fFound = false;
   721             const char * const endOfTable 
   722                 = reinterpret_cast<const char *>(pTable2) + lPostSize;
   723             while (pGlyphName < endOfTable && !fFound) 
   724             { // search Pascal strings for first matching name
   725                 size_t nStringSize = size_t(*pGlyphName);
   726                 if (nStrSizeGoal != nStringSize ||
   727                     strncmp(pGlyphName + 1, pPostName, nStringSize))
   728                 { // did not match
   729                     ++iInNames;
   730                     pGlyphName += nStringSize + 1;
   731                 }
   732                 else
   733                 { // did match
   734                     fFound = true;
   735                 }
   736             }
   737             if (!fFound)
   738                 return -1; // no font specific name matches request
   740             iInNames += kcPostNames;
   741             for (gid16 nGlyphId = 0; nGlyphId < cnGlyphs; nGlyphId++)
   742             { // search for first glyph id that maps to the found string index
   743                 if (be::swap(pTable2->glyph_name_index[nGlyphId]) == iInNames)
   744                     return nGlyphId;
   745             }
   746             return -1; // no glyph mapped to this index (very strange)
   747         }
   748     }
   750     return -3;
   751 }
   753 /*----------------------------------------------------------------------------------------------
   754     Convert a Unicode character string from big endian (MSB first, Motorola) format to little 
   755     endian (LSB first, Intel) format. 
   756     nSize is the number of Unicode characters in the string. It should not include any 
   757     terminating null. If nSize is 0, it is assumed the string is null terminated. nSize 
   758     defaults to 0.
   759     Return true if successful, false otherwise. 
   760 ----------------------------------------------------------------------------------------------*/
   761 void SwapWString(void * pWStr, size_t nSize /* = 0 */) //throw (std::invalid_argument)
   762 {
   763     if (pWStr == 0)
   764     {
   765 //      throw std::invalid_argument("null pointer given");
   766         return;
   767     }
   769     uint16 * pStr = reinterpret_cast<uint16 *>(pWStr);
   770     uint16 * const pStrEnd = pStr + (nSize == 0 ? wcslen((const wchar_t*)pStr) : nSize);
   772         for (; pStr != pStrEnd; ++pStr)
   773           *pStr = be::swap(*pStr);
   774 //  std::transform(pStr, pStrEnd, pStr, read<uint16>);
   776 //      for (int i = 0; i < nSize; i++)
   777 //      { // swap the wide characters in the string
   778 //          pStr[i] = utf16(be::swap(uint16(pStr[i])));
   779 //      }
   780 }
   781 #endif
   783 /*----------------------------------------------------------------------------------------------
   784     Get the left-side bearing and and advance width based on the given tables and Glyph ID
   785     Return true if successful, false otherwise. On false, one or both value could be INT_MIN
   786 ----------------------------------------------------------------------------------------------*/
   787 bool HorMetrics(gid16 nGlyphId, const void * pHmtx, size_t lHmtxSize, const void * pHhea, 
   788                          int & nLsb, unsigned int & nAdvWid)
   789 {
   790     const Sfnt::HorizontalMetric * phmtx = 
   791         reinterpret_cast<const Sfnt::HorizontalMetric *>(pHmtx);
   793     const Sfnt::HorizontalHeader * phhea = 
   794         reinterpret_cast<const Sfnt::HorizontalHeader *>(pHhea);
   796     size_t cLongHorMetrics = be::swap(phhea->num_long_hor_metrics);
   797     if (nGlyphId < cLongHorMetrics) 
   798     {   // glyph id is acceptable
   799         if (nGlyphId * sizeof(Sfnt::HorizontalMetric) >= lHmtxSize) return false;
   800         nAdvWid = be::swap(phmtx[nGlyphId].advance_width);
   801         nLsb = be::swap(phmtx[nGlyphId].left_side_bearing);
   802     }
   803     else
   804     {
   805         // guard against bad glyph id
   806         size_t lLsbOffset = sizeof(Sfnt::HorizontalMetric) * cLongHorMetrics +
   807             sizeof(int16) * (nGlyphId - cLongHorMetrics); // offset in bytes
   808         // We test like this as LsbOffset is an offset not a length.
   809         if (lLsbOffset > lHmtxSize - sizeof(int16))
   810         {
   811             nLsb = 0;
   812             return false;
   813         }
   814         nAdvWid = be::swap(phmtx[cLongHorMetrics - 1].advance_width);
   815         nLsb = be::peek<int16>(reinterpret_cast<const byte *>(phmtx) + lLsbOffset);
   816     }
   818     return true;
   819 }
   821 /*----------------------------------------------------------------------------------------------
   822     Return a pointer to the requested cmap subtable. By default find the Microsoft Unicode
   823     subtable. Pass nEncoding as -1 to find first table that matches only nPlatformId.
   824     Return NULL if the subtable cannot be found.
   825 ----------------------------------------------------------------------------------------------*/
   826 const void * FindCmapSubtable(const void * pCmap, int nPlatformId, /* =3 */ int nEncodingId, /* = 1 */ size_t length)
   827 {
   828     const Sfnt::CharacterCodeMap * pTable = reinterpret_cast<const Sfnt::CharacterCodeMap *>(pCmap);
   829     uint16 csuPlatforms = be::swap(pTable->num_subtables);
   830     if (length && (sizeof(Sfnt::CharacterCodeMap) + 8 * (csuPlatforms - 1) > length))
   831         return NULL;
   832     for (int i = 0; i < csuPlatforms; i++)
   833     {
   834         if (be::swap(pTable->encoding[i].platform_id) == nPlatformId &&
   835                 (nEncodingId == -1 || be::swap(pTable->encoding[i].platform_specific_id) == nEncodingId))
   836         {
   837             uint32 offset = be::swap(pTable->encoding[i].offset);
   838             const uint8 * pRtn = reinterpret_cast<const uint8 *>(pCmap) + offset;
   839             if (length)
   840             {
   841                 if (offset > length) return NULL;
   842                 uint16 format = be::read<uint16>(pRtn);
   843                 if (format == 4)
   844                 {
   845                     uint16 subTableLength = be::peek<uint16>(pRtn);
   846                     if (i + 1 == csuPlatforms)
   847                     {
   848                         if (subTableLength > length - offset)
   849                             return NULL;
   850                     }
   851                     else if (subTableLength > be::swap(pTable->encoding[i+1].offset))
   852                         return NULL;
   853                 }
   854                 if (format == 12)
   855                 {
   856                     uint32 subTableLength = be::peek<uint32>(pRtn);
   857                     if (i + 1 == csuPlatforms)
   858                     {
   859                         if (subTableLength > length - offset)
   860                             return NULL;
   861                     }
   862                     else if (subTableLength > be::swap(pTable->encoding[i+1].offset))
   863                         return NULL;
   864                 }
   865             }
   866             return reinterpret_cast<const uint8 *>(pCmap) + offset;
   867         }
   868     }
   870     return 0;
   871 }
   873 /*----------------------------------------------------------------------------------------------
   874     Check the Microsoft Unicode subtable for expected values
   875 ----------------------------------------------------------------------------------------------*/
   876 bool CheckCmapSubtable4(const void * pCmapSubtable4)
   877 {
   878     if (!pCmapSubtable4) return false;
   879     const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable4);
   880     // Bob H says ome freeware TT fonts have version 1 (eg, CALIGULA.TTF) 
   881     // so don't check subtable version. 21 Mar 2002 spec changes version to language.
   882     if (be::swap(pTable->format) != 4) return false;
   883     const Sfnt::CmapSubTableFormat4 * pTable4 = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmapSubtable4);
   884     uint16 length = be::swap(pTable4->length);
   885     if (length < sizeof(Sfnt::CmapSubTableFormat4))
   886         return false;
   887     uint16 nRanges = be::swap(pTable4->seg_count_x2) >> 1;
   888     if (length < sizeof(Sfnt::CmapSubTableFormat4) + 4 * nRanges * sizeof(uint16))
   889         return false;
   890     // check last range is properly terminated
   891     uint16 chEnd = be::peek<uint16>(pTable4->end_code + nRanges - 1);
   892     return (chEnd == 0xFFFF);
   893 }
   895 /*----------------------------------------------------------------------------------------------
   896     Return the Glyph ID for the given Unicode ID in the Microsoft Unicode subtable.
   897     (Actually this code only depends on subtable being format 4.)
   898     Return 0 if the Unicode ID is not in the subtable.
   899 ----------------------------------------------------------------------------------------------*/
   900 gid16 CmapSubtable4Lookup(const void * pCmapSubtabel4, unsigned int nUnicodeId, int rangeKey)
   901 {
   902     const Sfnt::CmapSubTableFormat4 * pTable = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmapSubtabel4);
   904     uint16 nSeg = be::swap(pTable->seg_count_x2) >> 1;
   906     uint16 n;
   907         const uint16 * pLeft, * pMid;
   908     uint16 cMid, chStart, chEnd;
   910     if (rangeKey)
   911     {
   912         pMid = &(pTable->end_code[rangeKey]);
   913         chEnd = be::peek<uint16>(pMid);
   914     }
   915     else
   916     {
   917         // Binary search of the endCode[] array
   918         pLeft = &(pTable->end_code[0]);
   919         n = nSeg;
   920         while (n > 0)
   921         {
   922             cMid = n >> 1;           // Pick an element in the middle
   923             pMid = pLeft + cMid;
   924             chEnd = be::peek<uint16>(pMid);
   925             if (nUnicodeId <= chEnd)
   926             {
   927                 if (cMid == 0 || nUnicodeId > be::peek<uint16>(pMid -1))
   928                         break;          // Must be this seg or none!
   929                 n = cMid;            // Continue on left side, omitting mid point
   930             }
   931             else
   932             {
   933                 pLeft = pMid + 1;    // Continue on right side, omitting mid point
   934                 n -= (cMid + 1);
   935             }
   936         }
   938         if (!n)
   939         return 0;
   940     }
   942     // Ok, we're down to one segment and pMid points to the endCode element
   943     // Either this is it or none is.
   945     chStart = be::peek<uint16>(pMid += nSeg + 1);
   946     if (chEnd >= nUnicodeId && nUnicodeId >= chStart)
   947     {
   948         // Found correct segment. Find Glyph Id
   949         int16 idDelta = be::peek<uint16>(pMid += nSeg);
   950         uint16 idRangeOffset = be::peek<uint16>(pMid += nSeg);
   952         if (idRangeOffset == 0)
   953             return (uint16)(idDelta + nUnicodeId); // must use modulus 2^16
   955         // Look up value in glyphIdArray
   956         const ptrdiff_t offset = (nUnicodeId - chStart) + (idRangeOffset >> 1) +
   957                 (pMid - reinterpret_cast<const uint16 *>(pTable));
   958         if (offset * 2 >= be::swap<uint16>(pTable->length))
   959             return 0;
   960         gid16 nGlyphId = be::peek<uint16>(reinterpret_cast<const uint16 *>(pTable)+offset);
   961         // If this value is 0, return 0. Else add the idDelta
   962         return nGlyphId ? nGlyphId + idDelta : 0;
   963     }
   965     return 0;
   966 }
   968 /*----------------------------------------------------------------------------------------------
   969     Return the next Unicode value in the cmap. Pass 0 to obtain the first item.
   970     Returns 0xFFFF as the last item.
   971     pRangeKey is an optional key that is used to optimize the search; its value is the range
   972     in which the character is found.
   973 ----------------------------------------------------------------------------------------------*/
   974 unsigned int CmapSubtable4NextCodepoint(const void *pCmap31, unsigned int nUnicodeId, int * pRangeKey)
   975 {
   976     const Sfnt::CmapSubTableFormat4 * pTable = reinterpret_cast<const Sfnt::CmapSubTableFormat4 *>(pCmap31);
   978     uint16 nRange = be::swap(pTable->seg_count_x2) >> 1;
   980     uint32 nUnicodePrev = (uint32)nUnicodeId;
   982     const uint16 * pStartCode = &(pTable->end_code[0])
   983         + nRange // length of end code array
   984         + 1;   // reserved word
   986     if (nUnicodePrev == 0)
   987     {
   988         // return the first codepoint.
   989         if (pRangeKey)
   990             *pRangeKey = 0;
   991         return be::peek<uint16>(pStartCode);
   992     }
   993     else if (nUnicodePrev >= 0xFFFF)
   994     {
   995         if (pRangeKey)
   996             *pRangeKey = nRange - 1;
   997         return 0xFFFF;
   998     }
  1000     int iRange = (pRangeKey) ? *pRangeKey : 0;
  1001     // Just in case we have a bad key:
  1002     while (iRange > 0 && be::peek<uint16>(pStartCode + iRange) > nUnicodePrev)
  1003         iRange--;
  1004     while (be::peek<uint16>(pTable->end_code + iRange) < nUnicodePrev)
  1005         iRange++;
  1007     // Now iRange is the range containing nUnicodePrev.
  1008     unsigned int nStartCode = be::peek<uint16>(pStartCode + iRange);
  1009     unsigned int nEndCode = be::peek<uint16>(pTable->end_code + iRange);
  1011     if (nStartCode > nUnicodePrev)
  1012         // Oops, nUnicodePrev is not in the cmap! Adjust so we get a reasonable
  1013         // answer this time around.
  1014         nUnicodePrev = nStartCode - 1;
  1016     if (nEndCode > nUnicodePrev)
  1018         // Next is in the same range; it is the next successive codepoint.
  1019         if (pRangeKey)
  1020             *pRangeKey = iRange;
  1021         return nUnicodePrev + 1;
  1024     // Otherwise the next codepoint is the first one in the next range.
  1025     // There is guaranteed to be a next range because there must be one that
  1026     // ends with 0xFFFF.
  1027     if (pRangeKey)
  1028         *pRangeKey = iRange + 1;
  1029     return be::peek<uint16>(pStartCode + iRange + 1);
  1032 /*----------------------------------------------------------------------------------------------
  1033     Check the Microsoft UCS-4 subtable for expected values.
  1034 ----------------------------------------------------------------------------------------------*/
  1035 bool CheckCmapSubtable12(const void *pCmapSubtable12)
  1037     if (!pCmapSubtable12)  return false;
  1038     const Sfnt::CmapSubTable * pTable = reinterpret_cast<const Sfnt::CmapSubTable *>(pCmapSubtable12);
  1039     if (be::swap(pTable->format) != 12)
  1040         return false;
  1041     const Sfnt::CmapSubTableFormat12 * pTable12 = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmapSubtable12);
  1042     uint32 length = be::swap(pTable12->length);
  1043     if (length < sizeof(Sfnt::CmapSubTableFormat12))
  1044         return false;
  1046     return (length == (sizeof(Sfnt::CmapSubTableFormat12) + (be::swap(pTable12->num_groups) - 1)
  1047         * sizeof(uint32) * 3));
  1050 /*----------------------------------------------------------------------------------------------
  1051     Return the Glyph ID for the given Unicode ID in the Microsoft UCS-4 subtable.
  1052     (Actually this code only depends on subtable being format 12.)
  1053     Return 0 if the Unicode ID is not in the subtable.
  1054 ----------------------------------------------------------------------------------------------*/
  1055 gid16 CmapSubtable12Lookup(const void * pCmap310, unsigned int uUnicodeId, int rangeKey)
  1057     const Sfnt::CmapSubTableFormat12 * pTable = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmap310);
  1059     //uint32 uLength = be::swap(pTable->length); //could use to test for premature end of table
  1060     uint32 ucGroups = be::swap(pTable->num_groups);
  1062     for (unsigned int i = rangeKey; i < ucGroups; i++)
  1064         uint32 uStartCode = be::swap(pTable->group[i].start_char_code);
  1065         uint32 uEndCode = be::swap(pTable->group[i].end_char_code);
  1066         if (uUnicodeId >= uStartCode && uUnicodeId <= uEndCode)
  1068             uint32 uDiff = uUnicodeId - uStartCode;
  1069             uint32 uStartGid = be::swap(pTable->group[i].start_glyph_id);
  1070             return static_cast<gid16>(uStartGid + uDiff);
  1074     return 0;
  1077 /*----------------------------------------------------------------------------------------------
  1078     Return the next Unicode value in the cmap. Pass 0 to obtain the first item.
  1079     Returns 0x10FFFF as the last item.
  1080     pRangeKey is an optional key that is used to optimize the search; its value is the range
  1081     in which the character is found.
  1082 ----------------------------------------------------------------------------------------------*/
  1083 unsigned int CmapSubtable12NextCodepoint(const void *pCmap310, unsigned int nUnicodeId, int * pRangeKey)
  1085     const Sfnt::CmapSubTableFormat12 * pTable = reinterpret_cast<const Sfnt::CmapSubTableFormat12 *>(pCmap310);
  1087     int nRange = be::swap(pTable->num_groups);
  1089     uint32 nUnicodePrev = (uint32)nUnicodeId;
  1091     if (nUnicodePrev == 0)
  1093         // return the first codepoint.
  1094         if (pRangeKey)
  1095             *pRangeKey = 0;
  1096         return be::swap(pTable->group[0].start_char_code);
  1098     else if (nUnicodePrev >= 0x10FFFF)
  1100         if (pRangeKey)
  1101             *pRangeKey = nRange;
  1102         return 0x10FFFF;
  1105     int iRange = (pRangeKey) ? *pRangeKey : 0;
  1106     // Just in case we have a bad key:
  1107     while (iRange > 0 && be::swap(pTable->group[iRange].start_char_code) > nUnicodePrev)
  1108         iRange--;
  1109     while (be::swap(pTable->group[iRange].end_char_code) < nUnicodePrev)
  1110         iRange++;
  1112     // Now iRange is the range containing nUnicodePrev.
  1114     unsigned int nStartCode = be::swap(pTable->group[iRange].start_char_code);
  1115     unsigned int nEndCode = be::swap(pTable->group[iRange].end_char_code);
  1117     if (nStartCode > nUnicodePrev)
  1118         // Oops, nUnicodePrev is not in the cmap! Adjust so we get a reasonable
  1119         // answer this time around.
  1120         nUnicodePrev = nStartCode - 1;
  1122     if (nEndCode > nUnicodePrev)
  1124         // Next is in the same range; it is the next successive codepoint.
  1125         if (pRangeKey)
  1126             *pRangeKey = iRange;
  1127         return nUnicodePrev + 1;
  1130     // Otherwise the next codepoint is the first one in the next range, or 10FFFF if we're done.
  1131     if (pRangeKey)
  1132         *pRangeKey = iRange + 1;
  1133     return (iRange + 1 >= nRange) ? 0x10FFFF : be::swap(pTable->group[iRange + 1].start_char_code);
  1136 /*----------------------------------------------------------------------------------------------
  1137     Return the offset stored in the loca table for the given Glyph ID.
  1138     (This offset is into the glyf table.)
  1139     Return -1 if the lookup failed.
  1140     Technically this method should return an unsigned long but it is unlikely the offset will
  1141         exceed 2^31.
  1142 ----------------------------------------------------------------------------------------------*/
  1143 size_t LocaLookup(gid16 nGlyphId, 
  1144         const void * pLoca, size_t lLocaSize, 
  1145         const void * pHead) // throw (std::out_of_range)
  1147     const Sfnt::FontHeader * pTable = reinterpret_cast<const Sfnt::FontHeader *>(pHead);
  1149     // CheckTable verifies the index_to_loc_format is valid
  1150     if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::ShortIndexLocFormat)
  1151     { // loca entries are two bytes and have been divided by two
  1152         if (nGlyphId < (lLocaSize >> 1) - 1) // allow sentinel value to be accessed
  1154             const uint16 * pShortTable = reinterpret_cast<const uint16 *>(pLoca);
  1155             return (be::peek<uint16>(pShortTable + nGlyphId) << 1);
  1159     if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::LongIndexLocFormat)
  1160     { // loca entries are four bytes
  1161         if (nGlyphId < (lLocaSize >> 2) - 1)
  1163             const uint32 * pLongTable = reinterpret_cast<const uint32 *>(pLoca);
  1164             return be::peek<uint32>(pLongTable + nGlyphId);
  1168     // only get here if glyph id was bad
  1169     return -1;
  1170     //throw std::out_of_range("glyph id out of range for font");
  1173 /*----------------------------------------------------------------------------------------------
  1174     Return a pointer into the glyf table based on the given offset (from LocaLookup).
  1175     Return NULL on error.
  1176 ----------------------------------------------------------------------------------------------*/
  1177 void * GlyfLookup(const void * pGlyf, size_t nGlyfOffset, size_t nTableLen)
  1179     const uint8 * pByte = reinterpret_cast<const uint8 *>(pGlyf);
  1180         if (nGlyfOffset == size_t(-1) || nGlyfOffset >= nTableLen)
  1181             return NULL;
  1182     return const_cast<uint8 *>(pByte + nGlyfOffset);
  1185 /*----------------------------------------------------------------------------------------------
  1186     Get the bounding box coordinates for a simple glyf entry (non-composite).
  1187     Return true if successful, false otherwise.
  1188 ----------------------------------------------------------------------------------------------*/
  1189 bool GlyfBox(const void * pSimpleGlyf, int & xMin, int & yMin, 
  1190                       int & xMax, int & yMax)
  1192     const Sfnt::Glyph * pGlyph = reinterpret_cast<const Sfnt::Glyph *>(pSimpleGlyf);
  1194     xMin = be::swap(pGlyph->x_min);
  1195     yMin = be::swap(pGlyph->y_min);
  1196     xMax = be::swap(pGlyph->x_max);
  1197     yMax = be::swap(pGlyph->y_max);
  1199     return true;
  1202 #ifdef ALL_TTFUTILS
  1203 /*----------------------------------------------------------------------------------------------
  1204     Return the number of contours for a simple glyf entry (non-composite)
  1205     Returning -1 means this is a composite glyph
  1206 ----------------------------------------------------------------------------------------------*/
  1207 int GlyfContourCount(const void * pSimpleGlyf)
  1209     const Sfnt::Glyph * pGlyph = reinterpret_cast<const Sfnt::Glyph *>(pSimpleGlyf);
  1210     return be::swap(pGlyph->number_of_contours); // -1 means composite glyph
  1213 /*----------------------------------------------------------------------------------------------
  1214     Get the point numbers for the end points of the glyph contours for a simple
  1215     glyf entry (non-composite). 
  1216     cnPointsTotal - count of contours from GlyfContourCount(); (same as number of end points)
  1217     prgnContourEndPoints - should point to a buffer large enough to hold cnPoints integers
  1218     cnPoints - count of points placed in above range
  1219     Return true if successful, false otherwise.
  1220         False could indicate a multi-level composite glyphs.
  1221 ----------------------------------------------------------------------------------------------*/
  1222 bool GlyfContourEndPoints(const void * pSimpleGlyf, int * prgnContourEndPoint, 
  1223                                    int cnPointsTotal, int & cnPoints)
  1225     const Sfnt::SimpleGlyph * pGlyph = reinterpret_cast<const Sfnt::SimpleGlyph *>(pSimpleGlyf);
  1227     int cContours = be::swap(pGlyph->number_of_contours);
  1228     if (cContours < 0)
  1229         return false; // this method isn't supposed handle composite glyphs
  1231     for (int i = 0; i < cContours && i < cnPointsTotal; i++)
  1233         prgnContourEndPoint[i] = be::swap(pGlyph->end_pts_of_contours[i]);
  1236     cnPoints = cContours;
  1237     return true;
  1240 /*----------------------------------------------------------------------------------------------
  1241     Get the points for a simple glyf entry (non-composite)
  1242     cnPointsTotal - count of points from largest end point obtained from GlyfContourEndPoints
  1243     prgnX & prgnY - should point to buffers large enough to hold cnPointsTotal integers
  1244         The ranges are parallel so that coordinates for point(n) are found at offset n in both 
  1245         ranges. This is raw point data with relative coordinates.
  1246     prgbFlag - should point to a buffer a large enough to hold cnPointsTotal bytes
  1247         This range is parallel to the prgnX & prgnY
  1248     cnPoints - count of points placed in above ranges
  1249     Return true if successful, false otherwise. 
  1250         False could indicate a composite glyph
  1251 ----------------------------------------------------------------------------------------------*/
  1252 bool GlyfPoints(const void * pSimpleGlyf, int * prgnX, int * prgnY, 
  1253         char * prgbFlag, int cnPointsTotal, int & cnPoints)
  1255     using namespace Sfnt;
  1257     const Sfnt::SimpleGlyph * pGlyph = reinterpret_cast<const Sfnt::SimpleGlyph *>(pSimpleGlyf);
  1258     int cContours = be::swap(pGlyph->number_of_contours);
  1259     // return false for composite glyph
  1260     if (cContours <= 0)
  1261         return false;
  1262     int cPts = be::swap(pGlyph->end_pts_of_contours[cContours - 1]) + 1;
  1263     if (cPts > cnPointsTotal)
  1264         return false;
  1266     // skip over bounding box data & point to byte count of instructions (hints)
  1267     const uint8 * pbGlyph = reinterpret_cast<const uint8 *>
  1268         (&pGlyph->end_pts_of_contours[cContours]);
  1270     // skip over hints & point to first flag
  1271     int cbHints = be::swap(*(uint16 *)pbGlyph);
  1272     pbGlyph += sizeof(uint16);
  1273     pbGlyph += cbHints;
  1275     // load flags & point to first x coordinate
  1276     int iFlag = 0;
  1277     while (iFlag < cPts)
  1279         if (!(*pbGlyph & SimpleGlyph::Repeat))
  1280         { // flag isn't repeated
  1281             prgbFlag[iFlag] = (char)*pbGlyph;
  1282             pbGlyph++;
  1283             iFlag++;
  1285         else
  1286         { // flag is repeated; count specified by next byte
  1287             char chFlag = (char)*pbGlyph;
  1288             pbGlyph++;
  1289             int cFlags = (int)*pbGlyph;
  1290             pbGlyph++;
  1291             prgbFlag[iFlag] = chFlag;
  1292             iFlag++;
  1293             for (int i = 0; i < cFlags; i++)
  1295                 prgbFlag[iFlag + i] = chFlag;
  1297             iFlag += cFlags;
  1300     if (iFlag != cPts)
  1301         return false;
  1303     // load x coordinates
  1304     iFlag = 0;
  1305     while (iFlag < cPts)
  1307         if (prgbFlag[iFlag] & SimpleGlyph::XShort)
  1309             prgnX[iFlag] = *pbGlyph;
  1310             if (!(prgbFlag[iFlag] & SimpleGlyph::XIsPos))
  1312                 prgnX[iFlag] = -prgnX[iFlag];
  1314             pbGlyph++;
  1316         else
  1318             if (prgbFlag[iFlag] & SimpleGlyph::XIsSame)
  1320                 prgnX[iFlag] = 0;
  1321                 // do NOT increment pbGlyph
  1323             else
  1325                 prgnX[iFlag] = be::swap(*(int16 *)pbGlyph);
  1326                 pbGlyph += sizeof(int16);
  1329         iFlag++;
  1332     // load y coordinates
  1333     iFlag = 0;
  1334     while (iFlag < cPts)
  1336         if (prgbFlag[iFlag] & SimpleGlyph::YShort)
  1338             prgnY[iFlag] = *pbGlyph;
  1339             if (!(prgbFlag[iFlag] & SimpleGlyph::YIsPos))
  1341                 prgnY[iFlag] = -prgnY[iFlag];
  1343             pbGlyph++;
  1345         else
  1347             if (prgbFlag[iFlag] & SimpleGlyph::YIsSame)
  1349                 prgnY[iFlag] = 0;
  1350                 // do NOT increment pbGlyph
  1352             else
  1354                 prgnY[iFlag] = be::swap(*(int16 *)pbGlyph);
  1355                 pbGlyph += sizeof(int16);
  1358         iFlag++;
  1361     cnPoints = cPts;
  1362     return true;
  1365 /*----------------------------------------------------------------------------------------------
  1366     Fill prgnCompId with the component Glyph IDs from pSimpleGlyf.
  1367     Client must allocate space before calling.
  1368     pSimpleGlyf - assumed to point to a composite glyph
  1369     cCompIdTotal - the number of elements in prgnCompId 
  1370     cCompId  - the total number of Glyph IDs stored in prgnCompId
  1371     Return true if successful, false otherwise
  1372         False could indicate a non-composite glyph or the input array was not big enough
  1373 ----------------------------------------------------------------------------------------------*/
  1374 bool GetComponentGlyphIds(const void * pSimpleGlyf, int * prgnCompId, 
  1375         size_t cnCompIdTotal, size_t & cnCompId)
  1377     using namespace Sfnt;
  1379     if (GlyfContourCount(pSimpleGlyf) >= 0)
  1380         return false;
  1382     const Sfnt::SimpleGlyph * pGlyph = reinterpret_cast<const Sfnt::SimpleGlyph *>(pSimpleGlyf);
  1383     // for a composite glyph, the special data begins here
  1384     const uint8 * pbGlyph = reinterpret_cast<const uint8 *>(&pGlyph->end_pts_of_contours[0]);
  1386     uint16 GlyphFlags;
  1387     size_t iCurrentComp = 0;
  1388     do 
  1390         GlyphFlags = be::swap(*((uint16 *)pbGlyph));
  1391         pbGlyph += sizeof(uint16);
  1392         prgnCompId[iCurrentComp++] = be::swap(*((uint16 *)pbGlyph));
  1393         pbGlyph += sizeof(uint16);
  1394         if (iCurrentComp >= cnCompIdTotal) 
  1395             return false;
  1396         int nOffset = 0;
  1397         nOffset += GlyphFlags & CompoundGlyph::Arg1Arg2Words ? 4 : 2;
  1398         nOffset += GlyphFlags & CompoundGlyph::HaveScale ? 2 : 0;
  1399         nOffset += GlyphFlags & CompoundGlyph::HaveXAndYScale  ? 4 : 0;
  1400         nOffset += GlyphFlags & CompoundGlyph::HaveTwoByTwo  ? 8 :  0;
  1401         pbGlyph += nOffset;
  1402     } while (GlyphFlags & CompoundGlyph::MoreComponents);
  1404     cnCompId = iCurrentComp;
  1406     return true;
  1409 /*----------------------------------------------------------------------------------------------
  1410     Return info on how a component glyph is to be placed
  1411     pSimpleGlyph - assumed to point to a composite glyph
  1412     nCompId - glyph id for component of interest
  1413     bOffset - if true, a & b are the x & y offsets for this component
  1414               if false, b is the point on this component that is attaching to point a on the
  1415                 preceding glyph
  1416     Return true if successful, false otherwise
  1417         False could indicate a non-composite glyph or that component wasn't found
  1418 ----------------------------------------------------------------------------------------------*/
  1419 bool GetComponentPlacement(const void * pSimpleGlyf, int nCompId,
  1420                                     bool fOffset, int & a, int & b)
  1422     using namespace Sfnt;
  1424     if (GlyfContourCount(pSimpleGlyf) >= 0)
  1425         return false;
  1427     const Sfnt::SimpleGlyph * pGlyph = reinterpret_cast<const Sfnt::SimpleGlyph *>(pSimpleGlyf);
  1428     // for a composite glyph, the special data begins here
  1429     const uint8 * pbGlyph = reinterpret_cast<const uint8 *>(&pGlyph->end_pts_of_contours[0]);
  1431     uint16 GlyphFlags;
  1432     do 
  1434         GlyphFlags = be::swap(*((uint16 *)pbGlyph));
  1435         pbGlyph += sizeof(uint16);
  1436         if (be::swap(*((uint16 *)pbGlyph)) == nCompId)
  1438             pbGlyph += sizeof(uint16); // skip over glyph id of component
  1439             fOffset = (GlyphFlags & CompoundGlyph::ArgsAreXYValues) == CompoundGlyph::ArgsAreXYValues;
  1441             if (GlyphFlags & CompoundGlyph::Arg1Arg2Words )
  1443                 a = be::swap(*(int16 *)pbGlyph);
  1444                 pbGlyph += sizeof(int16);
  1445                 b = be::swap(*(int16 *)pbGlyph);
  1446                 pbGlyph += sizeof(int16);
  1448             else
  1449             { // args are signed bytes
  1450                 a = *pbGlyph++;
  1451                 b = *pbGlyph++;
  1453             return true;
  1455         pbGlyph += sizeof(uint16); // skip over glyph id of component
  1456         int nOffset = 0;
  1457         nOffset += GlyphFlags & CompoundGlyph::Arg1Arg2Words  ? 4 : 2;
  1458         nOffset += GlyphFlags & CompoundGlyph::HaveScale ? 2 : 0;
  1459         nOffset += GlyphFlags & CompoundGlyph::HaveXAndYScale  ? 4 : 0;
  1460         nOffset += GlyphFlags & CompoundGlyph::HaveTwoByTwo  ? 8 :  0;
  1461         pbGlyph += nOffset;
  1462     } while (GlyphFlags & CompoundGlyph::MoreComponents);
  1464     // didn't find requested component
  1465     fOffset = true;
  1466     a = 0;
  1467     b = 0;
  1468     return false;
  1471 /*----------------------------------------------------------------------------------------------
  1472     Return info on how a component glyph is to be transformed
  1473     pSimpleGlyph - assumed to point to a composite glyph
  1474     nCompId - glyph id for component of interest
  1475     flt11, flt11, flt11, flt11 - a 2x2 matrix giving the transform
  1476     bTransOffset - whether to transform the offset from above method 
  1477         The spec is unclear about the meaning of this flag
  1478         Currently - initialize to true for MS rasterizer and false for Mac rasterizer, then
  1479             on return it will indicate whether transform should apply to offset (MSDN CD 10/99)
  1480     Return true if successful, false otherwise
  1481         False could indicate a non-composite glyph or that component wasn't found
  1482 ----------------------------------------------------------------------------------------------*/
  1483 bool GetComponentTransform(const void * pSimpleGlyf, int nCompId, 
  1484                                     float & flt11, float & flt12, float & flt21, float & flt22, 
  1485                                     bool & fTransOffset)
  1487     using namespace Sfnt;
  1489     if (GlyfContourCount(pSimpleGlyf) >= 0)
  1490         return false;
  1492     const Sfnt::SimpleGlyph * pGlyph = reinterpret_cast<const Sfnt::SimpleGlyph *>(pSimpleGlyf);
  1493     // for a composite glyph, the special data begins here
  1494     const uint8 * pbGlyph = reinterpret_cast<const uint8 *>(&pGlyph->end_pts_of_contours[0]);
  1496     uint16 GlyphFlags;
  1497     do 
  1499         GlyphFlags = be::swap(*((uint16 *)pbGlyph));
  1500         pbGlyph += sizeof(uint16);
  1501         if (be::swap(*((uint16 *)pbGlyph)) == nCompId)
  1503             pbGlyph += sizeof(uint16); // skip over glyph id of component
  1504             pbGlyph += GlyphFlags & CompoundGlyph::Arg1Arg2Words  ? 4 : 2; // skip over placement data
  1506             if (fTransOffset) // MS rasterizer
  1507                 fTransOffset = !(GlyphFlags & CompoundGlyph::UnscaledOffset); 
  1508             else // Apple rasterizer
  1509                 fTransOffset = (GlyphFlags & CompoundGlyph::ScaledOffset) != 0;
  1511             if (GlyphFlags & CompoundGlyph::HaveScale)
  1513                 flt11 = fixed_to_float<14>(be::swap(*(uint16 *)pbGlyph));
  1514                 pbGlyph += sizeof(uint16);
  1515                 flt12 = 0;
  1516                 flt21 = 0;
  1517                 flt22 = flt11;
  1519             else if (GlyphFlags & CompoundGlyph::HaveXAndYScale)
  1521                 flt11 = fixed_to_float<14>(be::swap(*(uint16 *)pbGlyph));
  1522                 pbGlyph += sizeof(uint16);
  1523                 flt12 = 0;
  1524                 flt21 = 0;
  1525                 flt22 = fixed_to_float<14>(be::swap(*(uint16 *)pbGlyph));
  1526                 pbGlyph += sizeof(uint16);
  1528             else if (GlyphFlags & CompoundGlyph::HaveTwoByTwo)
  1530                 flt11 = fixed_to_float<14>(be::swap(*(uint16 *)pbGlyph));
  1531                 pbGlyph += sizeof(uint16);
  1532                 flt12 = fixed_to_float<14>(be::swap(*(uint16 *)pbGlyph));
  1533                 pbGlyph += sizeof(uint16);
  1534                 flt21 = fixed_to_float<14>(be::swap(*(uint16 *)pbGlyph));
  1535                 pbGlyph += sizeof(uint16);
  1536                 flt22 = fixed_to_float<14>(be::swap(*(uint16 *)pbGlyph));
  1537                 pbGlyph += sizeof(uint16);
  1539             else
  1540             { // identity transform
  1541                 flt11 = 1.0;
  1542                 flt12 = 0.0;
  1543                 flt21 = 0.0;
  1544                 flt22 = 1.0;
  1546             return true;
  1548         pbGlyph += sizeof(uint16); // skip over glyph id of component
  1549         int nOffset = 0;
  1550         nOffset += GlyphFlags & CompoundGlyph::Arg1Arg2Words  ? 4 : 2;
  1551         nOffset += GlyphFlags & CompoundGlyph::HaveScale ? 2 : 0;
  1552         nOffset += GlyphFlags & CompoundGlyph::HaveXAndYScale  ? 4 : 0;
  1553         nOffset += GlyphFlags & CompoundGlyph::HaveTwoByTwo  ? 8 :  0;
  1554         pbGlyph += nOffset;
  1555     } while (GlyphFlags & CompoundGlyph::MoreComponents);
  1557     // didn't find requested component
  1558     fTransOffset = false;
  1559     flt11 = 1;
  1560     flt12 = 0;
  1561     flt21 = 0;
  1562     flt22 = 1;
  1563     return false;
  1565 #endif
  1567 /*----------------------------------------------------------------------------------------------
  1568     Return a pointer into the glyf table based on the given tables and Glyph ID
  1569     Since this method doesn't check for spaces, it is good to call IsSpace before using it.
  1570     Return NULL on error.
  1571 ----------------------------------------------------------------------------------------------*/
  1572 void * GlyfLookup(gid16 nGlyphId, const void * pGlyf, const void * pLoca, 
  1573                            size_t lGlyfSize, size_t lLocaSize, const void * pHead)
  1575     // test for valid glyph id
  1576     // CheckTable verifies the index_to_loc_format is valid
  1578     const Sfnt::FontHeader * pTable 
  1579         = reinterpret_cast<const Sfnt::FontHeader *>(pHead);
  1581     if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::ShortIndexLocFormat)
  1582     { // loca entries are two bytes (and have been divided by two)
  1583         if (nGlyphId >= (lLocaSize >> 1) - 1) // don't allow nGlyphId to access sentinel
  1585 //          throw std::out_of_range("glyph id out of range for font");
  1586             return NULL;
  1589     if (be::swap(pTable->index_to_loc_format) == Sfnt::FontHeader::LongIndexLocFormat)
  1590     { // loca entries are four bytes
  1591         if (nGlyphId >= (lLocaSize >> 2) - 1)
  1593 //          throw std::out_of_range("glyph id out of range for font");
  1594             return NULL;
  1598     long lGlyfOffset = LocaLookup(nGlyphId, pLoca, lLocaSize, pHead);
  1599     void * pSimpleGlyf = GlyfLookup(pGlyf, lGlyfOffset, lGlyfSize); // invalid loca offset returns null
  1600     return pSimpleGlyf;
  1603 #ifdef ALL_TTFUTILS
  1604 /*----------------------------------------------------------------------------------------------
  1605     Determine if a particular Glyph ID has any data in the glyf table. If it is white space,
  1606     there will be no glyf data, though there will be metric data in hmtx, etc.
  1607 ----------------------------------------------------------------------------------------------*/
  1608 bool IsSpace(gid16 nGlyphId, const void * pLoca, size_t lLocaSize, const void * pHead)
  1610     size_t lGlyfOffset = LocaLookup(nGlyphId, pLoca, lLocaSize, pHead);
  1612     // the +1 should always work because there is a sentinel value at the end of the loca table
  1613     size_t lNextGlyfOffset = LocaLookup(nGlyphId + 1, pLoca, lLocaSize, pHead);
  1615     return (lNextGlyfOffset - lGlyfOffset) == 0;
  1618 /*----------------------------------------------------------------------------------------------
  1619     Determine if a particular Glyph ID is a multi-level composite.
  1620 ----------------------------------------------------------------------------------------------*/
  1621 bool IsDeepComposite(gid16 nGlyphId, const void * pGlyf, const void * pLoca, 
  1622                     size_t lGlyfSize, long lLocaSize, const void * pHead)
  1624     if (IsSpace(nGlyphId, pLoca, lLocaSize, pHead)) {return false;}
  1626     void * pSimpleGlyf = GlyfLookup(nGlyphId, pGlyf, pLoca, lGlyfSize, lLocaSize, pHead);
  1627     if (pSimpleGlyf == NULL)
  1628         return false; // no way to really indicate an error occured here
  1630     if (GlyfContourCount(pSimpleGlyf) >= 0)
  1631         return false;
  1633     int rgnCompId[kMaxGlyphComponents]; // assumes only a limited number of glyph components
  1634     size_t cCompIdTotal = kMaxGlyphComponents;
  1635     size_t cCompId = 0;
  1637     if (!GetComponentGlyphIds(pSimpleGlyf, rgnCompId, cCompIdTotal, cCompId))
  1638         return false;
  1640     for (size_t i = 0; i < cCompId; i++)
  1642         pSimpleGlyf = GlyfLookup(static_cast<gid16>(rgnCompId[i]), 
  1643                             pGlyf, pLoca, lGlyfSize, lLocaSize, pHead);
  1644         if (pSimpleGlyf == NULL) {return false;}
  1646         if (GlyfContourCount(pSimpleGlyf) < 0)
  1647             return true;
  1650     return false;
  1653 /*----------------------------------------------------------------------------------------------
  1654     Get the bounding box coordinates based on the given tables and Glyph ID
  1655     Handles both simple and composite glyphs.
  1656     Return true if successful, false otherwise. On false, all point values will be INT_MIN
  1657         False may indicate a white space glyph
  1658 ----------------------------------------------------------------------------------------------*/
  1659 bool GlyfBox(gid16  nGlyphId, const void * pGlyf, const void * pLoca, 
  1660         size_t lGlyfSize, size_t lLocaSize, const void * pHead, int & xMin, int & yMin, int & xMax, int & yMax)
  1662     xMin = yMin = xMax = yMax = INT_MIN;
  1664     if (IsSpace(nGlyphId, pLoca, lLocaSize, pHead)) {return false;}
  1666     void * pSimpleGlyf = GlyfLookup(nGlyphId, pGlyf, pLoca, lGlyfSize, lLocaSize, pHead);
  1667     if (pSimpleGlyf == NULL) {return false;}
  1669     return GlyfBox(pSimpleGlyf, xMin, yMin, xMax, yMax);
  1672 /*----------------------------------------------------------------------------------------------
  1673     Get the number of contours based on the given tables and Glyph ID
  1674     Handles both simple and composite glyphs.
  1675     Return true if successful, false otherwise. On false, cnContours will be INT_MIN
  1676         False may indicate a white space glyph or a multi-level composite glyph.
  1677 ----------------------------------------------------------------------------------------------*/
  1678 bool GlyfContourCount(gid16 nGlyphId, const void * pGlyf, const void * pLoca, 
  1679     size_t lGlyfSize, size_t lLocaSize, const void * pHead, size_t & cnContours)
  1681     cnContours = static_cast<size_t>(INT_MIN);
  1683     if (IsSpace(nGlyphId, pLoca, lLocaSize, pHead)) {return false;}
  1685     void * pSimpleGlyf = GlyfLookup(nGlyphId, pGlyf, pLoca, lGlyfSize, lLocaSize, pHead);
  1686     if (pSimpleGlyf == NULL) {return false;}
  1688     int cRtnContours = GlyfContourCount(pSimpleGlyf);
  1689     if (cRtnContours >= 0)
  1691         cnContours = size_t(cRtnContours);
  1692         return true;
  1695     //handle composite glyphs
  1697     int rgnCompId[kMaxGlyphComponents]; // assumes no glyph will be made of more than 8 components
  1698     size_t cCompIdTotal = kMaxGlyphComponents;
  1699     size_t cCompId = 0;
  1701     if (!GetComponentGlyphIds(pSimpleGlyf, rgnCompId, cCompIdTotal, cCompId))
  1702         return false;
  1704     cRtnContours = 0;
  1705     int cTmp = 0;
  1706     for (size_t i = 0; i < cCompId; i++)
  1708         if (IsSpace(static_cast<gid16>(rgnCompId[i]), pLoca, lLocaSize, pHead)) {return false;}
  1709         pSimpleGlyf = GlyfLookup(static_cast<gid16>(rgnCompId[i]), 
  1710                                  pGlyf, pLoca, lGlyfSize, lLocaSize, pHead);
  1711         if (pSimpleGlyf == 0) {return false;}
  1712         // return false on multi-level composite
  1713         if ((cTmp = GlyfContourCount(pSimpleGlyf)) < 0) 
  1714             return false;
  1715         cRtnContours += cTmp;
  1718     cnContours = size_t(cRtnContours);
  1719     return true;
  1722 /*----------------------------------------------------------------------------------------------
  1723     Get the point numbers for the end points of the glyph contours based on the given tables 
  1724     and Glyph ID
  1725     Handles both simple and composite glyphs.
  1726     cnPoints - count of contours from GlyfContourCount (same as number of end points)
  1727     prgnContourEndPoints - should point to a buffer large enough to hold cnPoints integers
  1728     Return true if successful, false otherwise. On false, all end points are INT_MIN
  1729         False may indicate a white space glyph or a multi-level composite glyph.
  1730 ----------------------------------------------------------------------------------------------*/
  1731 bool GlyfContourEndPoints(gid16 nGlyphId, const void * pGlyf, const void * pLoca, 
  1732     size_t lGlyfSize, size_t lLocaSize, const void * pHead,
  1733     int * prgnContourEndPoint, size_t cnPoints)
  1735         memset(prgnContourEndPoint, 0xFF, cnPoints * sizeof(int));
  1736     // std::fill_n(prgnContourEndPoint, cnPoints, INT_MIN);
  1738     if (IsSpace(nGlyphId, pLoca, lLocaSize, pHead)) {return false;}
  1740     void * pSimpleGlyf = GlyfLookup(nGlyphId, pGlyf, pLoca, lGlyfSize, lLocaSize, pHead);
  1741     if (pSimpleGlyf == NULL) {return false;}
  1743     int cContours = GlyfContourCount(pSimpleGlyf);
  1744     int cActualPts = 0;
  1745     if (cContours > 0)
  1746         return GlyfContourEndPoints(pSimpleGlyf, prgnContourEndPoint, cnPoints, cActualPts);
  1748     // handle composite glyphs
  1750     int rgnCompId[kMaxGlyphComponents]; // assumes no glyph will be made of more than 8 components
  1751     size_t cCompIdTotal = kMaxGlyphComponents;
  1752     size_t cCompId = 0;
  1754     if (!GetComponentGlyphIds(pSimpleGlyf, rgnCompId, cCompIdTotal, cCompId))
  1755         return false;
  1757     int * prgnCurrentEndPoint = prgnContourEndPoint;
  1758     int cCurrentPoints = cnPoints;
  1759     int nPrevPt = 0;
  1760     for (size_t i = 0; i < cCompId; i++)
  1762         if (IsSpace(static_cast<gid16>(rgnCompId[i]), pLoca, lLocaSize, pHead)) {return false;}
  1763         pSimpleGlyf = GlyfLookup(static_cast<gid16>(rgnCompId[i]), pGlyf, pLoca, lGlyfSize, lLocaSize, pHead);
  1764         if (pSimpleGlyf == NULL) {return false;}
  1765         // returns false on multi-level composite
  1766         if (!GlyfContourEndPoints(pSimpleGlyf, prgnCurrentEndPoint, cCurrentPoints, cActualPts))
  1767             return false;
  1768         // points in composite are numbered sequentially as components are added
  1769         //  must adjust end point numbers for new point numbers
  1770         for (int j = 0; j < cActualPts; j++)
  1771             prgnCurrentEndPoint[j] += nPrevPt;
  1772         nPrevPt = prgnCurrentEndPoint[cActualPts - 1] + 1;
  1774         prgnCurrentEndPoint += cActualPts;
  1775         cCurrentPoints -= cActualPts;
  1778     return true;
  1781 /*----------------------------------------------------------------------------------------------
  1782     Get the points for a glyph based on the given tables and Glyph ID
  1783     Handles both simple and composite glyphs.
  1784     cnPoints - count of points from largest end point obtained from GlyfContourEndPoints
  1785     prgnX & prgnY - should point to buffers large enough to hold cnPoints integers
  1786         The ranges are parallel so that coordinates for point(n) are found at offset n in 
  1787         both ranges. These points are in absolute coordinates.
  1788     prgfOnCurve - should point to a buffer a large enough to hold cnPoints bytes (bool)
  1789         This range is parallel to the prgnX & prgnY
  1790     Return true if successful, false otherwise. On false, all points may be INT_MIN
  1791         False may indicate a white space glyph, a multi-level composite, or a corrupt font
  1792     // TODO: doesn't support composite glyphs whose components are themselves components
  1793         It's not clear from the TTF spec when the transforms should be applied. Should the 
  1794         transform be done before or after attachment point calcs? (current code - before) 
  1795         Should the transform be applied to other offsets? (currently - no; however commented 
  1796         out code is in place so that if CompoundGlyph::UnscaledOffset on the MS rasterizer is 
  1797         clear (typical) then yes, and if CompoundGlyph::ScaledOffset on the Apple rasterizer is 
  1798         clear (typical?) then no). See GetComponentTransform.
  1799         It's also unclear where point numbering with attachment poinst starts 
  1800         (currently - first point number is relative to whole glyph, second point number is 
  1801         relative to current glyph). 
  1802 ----------------------------------------------------------------------------------------------*/
  1803 bool GlyfPoints(gid16 nGlyphId, const void * pGlyf,
  1804         const void * pLoca, size_t lGlyfSize, size_t lLocaSize, const void * pHead,
  1805         const int * /*prgnContourEndPoint*/, size_t /*cnEndPoints*/,
  1806         int * prgnX, int * prgnY, bool * prgfOnCurve, size_t cnPoints)
  1808         memset(prgnX, 0x7F, cnPoints * sizeof(int));
  1809         memset(prgnY, 0x7F, cnPoints * sizeof(int));
  1811     if (IsSpace(nGlyphId, pLoca, lLocaSize, pHead)) 
  1812         return false;
  1814     void * pSimpleGlyf = GlyfLookup(nGlyphId, pGlyf, pLoca, lGlyfSize, lLocaSize, pHead);
  1815     if (pSimpleGlyf == NULL)
  1816         return false;
  1818     int cContours = GlyfContourCount(pSimpleGlyf);
  1819     int cActualPts;
  1820     if (cContours > 0)
  1822         if (!GlyfPoints(pSimpleGlyf, prgnX, prgnY, (char *)prgfOnCurve, cnPoints, cActualPts))
  1823             return false;
  1824         CalcAbsolutePoints(prgnX, prgnY, cnPoints);
  1825         SimplifyFlags((char *)prgfOnCurve, cnPoints);
  1826         return true;
  1829     // handle composite glyphs  
  1830     int rgnCompId[kMaxGlyphComponents]; // assumes no glyph will be made of more than 8 components
  1831     size_t cCompIdTotal = kMaxGlyphComponents;
  1832     size_t cCompId = 0;
  1834     // this will fail if there are more components than there is room for
  1835     if (!GetComponentGlyphIds(pSimpleGlyf, rgnCompId, cCompIdTotal, cCompId))
  1836         return false;
  1838     int * prgnCurrentX = prgnX;
  1839     int * prgnCurrentY = prgnY;
  1840     char * prgbCurrentFlag = (char *)prgfOnCurve; // converting bool to char should be safe
  1841     int cCurrentPoints = cnPoints;
  1842     bool fOffset = true, fTransOff = true;
  1843     int a, b;
  1844     float flt11, flt12, flt21, flt22;
  1845     // int * prgnPrevX = prgnX; // in case first att pt number relative to preceding glyph
  1846     // int * prgnPrevY = prgnY;
  1847     for (size_t i = 0; i < cCompId; i++)
  1849         if (IsSpace(static_cast<gid16>(rgnCompId[i]), pLoca, lLocaSize, pHead)) {return false;}
  1850         void * pCompGlyf = GlyfLookup(static_cast<gid16>(rgnCompId[i]), pGlyf, pLoca, lGlyfSize, lLocaSize, pHead);
  1851         if (pCompGlyf == NULL) {return false;}
  1852         // returns false on multi-level composite
  1853         if (!GlyfPoints(pCompGlyf, prgnCurrentX, prgnCurrentY, prgbCurrentFlag, 
  1854             cCurrentPoints, cActualPts))
  1855             return false; 
  1856         if (!GetComponentPlacement(pSimpleGlyf, rgnCompId[i], fOffset, a, b))
  1857             return false;
  1858         if (!GetComponentTransform(pSimpleGlyf, rgnCompId[i], 
  1859             flt11, flt12, flt21, flt22, fTransOff))
  1860             return false;
  1861         bool fIdTrans = flt11 == 1.0 && flt12 == 0.0 && flt21 == 0.0 && flt22 == 1.0;
  1863         // convert points to absolute coordinates
  1864         // do before transform and attachment point placement are applied
  1865         CalcAbsolutePoints(prgnCurrentX, prgnCurrentY, cActualPts);
  1867         // apply transform - see main method note above
  1868         // do before attachment point calcs
  1869         if (!fIdTrans)
  1870             for (int j = 0; j < cActualPts; j++)
  1872                 int x = prgnCurrentX[j]; // store before transform applied
  1873                 int y = prgnCurrentY[j];
  1874                 prgnCurrentX[j] = (int)(x * flt11 + y * flt12);
  1875                 prgnCurrentY[j] = (int)(x * flt21 + y * flt22);
  1878         // apply placement - see main method note above
  1879         int nXOff, nYOff;
  1880         if (fOffset) // explicit x & y offsets
  1882             /* ignore fTransOff for now
  1883             if (fTransOff && !fIdTrans) 
  1884             {   // transform x & y offsets
  1885                 nXOff = (int)(a * flt11 + b * flt12);
  1886                 nYOff = (int)(a * flt21 + b * flt22);
  1888             else */ 
  1889             { // don't transform offset
  1890                 nXOff = a;
  1891                 nYOff = b;
  1894         else  // attachment points
  1895         {   // in case first point is relative to preceding glyph and second relative to current
  1896             // nXOff = prgnPrevX[a] - prgnCurrentX[b];
  1897             // nYOff = prgnPrevY[a] - prgnCurrentY[b];
  1898             // first point number relative to whole composite, second relative to current glyph
  1899             nXOff = prgnX[a] - prgnCurrentX[b];
  1900             nYOff = prgnY[a] - prgnCurrentY[b];
  1902         for (int j = 0; j < cActualPts; j++)
  1904             prgnCurrentX[j] += nXOff;
  1905             prgnCurrentY[j] += nYOff;
  1908         // prgnPrevX = prgnCurrentX;
  1909         // prgnPrevY = prgnCurrentY;
  1910         prgnCurrentX += cActualPts;
  1911         prgnCurrentY += cActualPts;
  1912         prgbCurrentFlag += cActualPts;
  1913         cCurrentPoints -= cActualPts;
  1916     SimplifyFlags((char *)prgfOnCurve, cnPoints);
  1918     return true;
  1921 /*----------------------------------------------------------------------------------------------
  1922     Simplify the meaning of flags to just indicate whether point is on-curve or off-curve.
  1923 ---------------------------------------------------------------------------------------------*/
  1924 bool SimplifyFlags(char * prgbFlags, int cnPoints)
  1926     for (int i = 0; i < cnPoints; i++)
  1927         prgbFlags[i] = static_cast<char>(prgbFlags[i] & Sfnt::SimpleGlyph::OnCurve);
  1928     return true;
  1931 /*----------------------------------------------------------------------------------------------
  1932     Convert relative point coordinates to absolute coordinates
  1933     Points are stored in the font such that they are offsets from one another except for the 
  1934         first point of a glyph.
  1935 ---------------------------------------------------------------------------------------------*/
  1936 bool CalcAbsolutePoints(int * prgnX, int * prgnY, int cnPoints)
  1938     int nX = prgnX[0];
  1939     int nY = prgnY[0];
  1940     for (int i = 1; i < cnPoints; i++)
  1942         prgnX[i] += nX;
  1943         nX = prgnX[i];
  1944         prgnY[i] += nY;
  1945         nY = prgnY[i];
  1948     return true;
  1950 #endif
  1952 /*----------------------------------------------------------------------------------------------
  1953     Return the length of the 'name' table in bytes.
  1954     Currently used.
  1955 ---------------------------------------------------------------------------------------------*/
  1956 #if 0
  1957 size_t NameTableLength(const byte * pTable)
  1959     byte * pb = (const_cast<byte *>(pTable)) + 2; // skip format
  1960     size_t cRecords = *pb++ << 8; cRecords += *pb++;
  1961     int dbStringOffset0 = (*pb++) << 8; dbStringOffset0 += *pb++;
  1962     int dbMaxStringOffset = 0;
  1963     for (size_t irec = 0; irec < cRecords; irec++)
  1965         int nPlatform = (*pb++) << 8; nPlatform += *pb++;
  1966         int nEncoding = (*pb++) << 8; nEncoding += *pb++;
  1967         int nLanguage = (*pb++) << 8; nLanguage += *pb++;
  1968         int nName = (*pb++) << 8; nName += *pb++;
  1969         int cbStringLen = (*pb++) << 8; cbStringLen += *pb++;
  1970         int dbStringOffset = (*pb++) << 8; dbStringOffset += *pb++;
  1971         if (dbMaxStringOffset < dbStringOffset + cbStringLen)
  1972             dbMaxStringOffset = dbStringOffset + cbStringLen;
  1974     return dbStringOffset0 + dbMaxStringOffset;
  1976 #endif
  1978 } // end of namespace TtfUtil
  1979 } // end of namespace graphite

mercurial