Coverage Report

Created: 2025-07-07 10:01

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