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