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