w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

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