Coverage Report

Created: 2026-06-30 11:14

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