tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

TtfUtil.cpp (86268B)


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