Visualization Library 2.0.0-b5

A lightweight C++ OpenGL middleware for 2D/3D graphics

VL     Star     Watch     Fork     Issue

[Download] [Tutorials] [All Classes] [Grouped Classes]
ttcmap.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* ttcmap.c */
4 /* */
5 /* TrueType character mapping table (cmap) support (body). */
6 /* */
7 /* Copyright 2002-2010, 2012, 2013 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
15 /* */
16 /***************************************************************************/
17 
18 
19 #include <ft2build.h>
20 #include FT_INTERNAL_DEBUG_H
21 
22 #include "sferrors.h" /* must come before FT_INTERNAL_VALIDATE_H */
23 
24 #include FT_INTERNAL_VALIDATE_H
25 #include FT_INTERNAL_STREAM_H
26 #include "ttload.h"
27 #include "ttcmap.h"
28 #include "sfntpic.h"
29 
30 
31  /*************************************************************************/
32  /* */
33  /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
34  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
35  /* messages during execution. */
36  /* */
37 #undef FT_COMPONENT
38 #define FT_COMPONENT trace_ttcmap
39 
40 
41 #define TT_PEEK_SHORT FT_PEEK_SHORT
42 #define TT_PEEK_USHORT FT_PEEK_USHORT
43 #define TT_PEEK_UINT24 FT_PEEK_UOFF3
44 #define TT_PEEK_LONG FT_PEEK_LONG
45 #define TT_PEEK_ULONG FT_PEEK_ULONG
46 
47 #define TT_NEXT_SHORT FT_NEXT_SHORT
48 #define TT_NEXT_USHORT FT_NEXT_USHORT
49 #define TT_NEXT_UINT24 FT_NEXT_UOFF3
50 #define TT_NEXT_LONG FT_NEXT_LONG
51 #define TT_NEXT_ULONG FT_NEXT_ULONG
52 
53 
56  FT_Byte* table )
57  {
58  cmap->data = table;
59  return FT_Err_Ok;
60  }
61 
62 
63  /*************************************************************************/
64  /*************************************************************************/
65  /***** *****/
66  /***** FORMAT 0 *****/
67  /***** *****/
68  /*************************************************************************/
69  /*************************************************************************/
70 
71  /*************************************************************************/
72  /* */
73  /* TABLE OVERVIEW */
74  /* -------------- */
75  /* */
76  /* NAME OFFSET TYPE DESCRIPTION */
77  /* */
78  /* format 0 USHORT must be 0 */
79  /* length 2 USHORT table length in bytes */
80  /* language 4 USHORT Mac language code */
81  /* glyph_ids 6 BYTE[256] array of glyph indices */
82  /* 262 */
83  /* */
84 
85 #ifdef TT_CONFIG_CMAP_FORMAT_0
86 
88  tt_cmap0_validate( FT_Byte* table,
89  FT_Validator valid )
90  {
91  FT_Byte* p = table + 2;
93 
94 
95  if ( table + length > valid->limit || length < 262 )
97 
98  /* check glyph indices whenever necessary */
99  if ( valid->level >= FT_VALIDATE_TIGHT )
100  {
101  FT_UInt n, idx;
102 
103 
104  p = table + 6;
105  for ( n = 0; n < 256; n++ )
106  {
107  idx = *p++;
108  if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
110  }
111  }
112 
113  return FT_Err_Ok;
114  }
115 
116 
118  tt_cmap0_char_index( TT_CMap cmap,
119  FT_UInt32 char_code )
120  {
121  FT_Byte* table = cmap->data;
122 
123 
124  return char_code < 256 ? table[6 + char_code] : 0;
125  }
126 
127 
129  tt_cmap0_char_next( TT_CMap cmap,
130  FT_UInt32 *pchar_code )
131  {
132  FT_Byte* table = cmap->data;
133  FT_UInt32 charcode = *pchar_code;
134  FT_UInt32 result = 0;
135  FT_UInt gindex = 0;
136 
137 
138  table += 6; /* go to glyph IDs */
139  while ( ++charcode < 256 )
140  {
141  gindex = table[charcode];
142  if ( gindex != 0 )
143  {
144  result = charcode;
145  break;
146  }
147  }
148 
149  *pchar_code = result;
150  return gindex;
151  }
152 
153 
155  tt_cmap0_get_info( TT_CMap cmap,
157  {
158  FT_Byte* p = cmap->data + 4;
159 
160 
161  cmap_info->format = 0;
162  cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
163 
164  return FT_Err_Ok;
165  }
166 
167 
169  tt_cmap0_class_rec,
170  sizeof ( TT_CMapRec ),
171 
174  (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
175  (FT_CMap_CharNextFunc) tt_cmap0_char_next,
176 
177  NULL,
178  NULL,
179  NULL,
180  NULL,
181  NULL,
182 
183  0,
184  (TT_CMap_ValidateFunc)tt_cmap0_validate,
185  (TT_CMap_Info_GetFunc)tt_cmap0_get_info )
186 
187 #endif /* TT_CONFIG_CMAP_FORMAT_0 */
188 
189 
190  /*************************************************************************/
191  /*************************************************************************/
192  /***** *****/
193  /***** FORMAT 2 *****/
194  /***** *****/
195  /***** This is used for certain CJK encodings that encode text in a *****/
196  /***** mixed 8/16 bits encoding along the following lines: *****/
197  /***** *****/
198  /***** * Certain byte values correspond to an 8-bit character code *****/
199  /***** (typically in the range 0..127 for ASCII compatibility). *****/
200  /***** *****/
201  /***** * Certain byte values signal the first byte of a 2-byte *****/
202  /***** character code (but these values are also valid as the *****/
203  /***** second byte of a 2-byte character). *****/
204  /***** *****/
205  /***** The following charmap lookup and iteration functions all *****/
206  /***** assume that the value "charcode" correspond to following: *****/
207  /***** *****/
208  /***** - For one byte characters, "charcode" is simply the *****/
209  /***** character code. *****/
210  /***** *****/
211  /***** - For two byte characters, "charcode" is the 2-byte *****/
212  /***** character code in big endian format. More exactly: *****/
213  /***** *****/
214  /***** (charcode >> 8) is the first byte value *****/
215  /***** (charcode & 0xFF) is the second byte value *****/
216  /***** *****/
217  /***** Note that not all values of "charcode" are valid according *****/
218  /***** to these rules, and the function moderately check the *****/
219  /***** arguments. *****/
220  /***** *****/
221  /*************************************************************************/
222  /*************************************************************************/
223 
224  /*************************************************************************/
225  /* */
226  /* TABLE OVERVIEW */
227  /* -------------- */
228  /* */
229  /* NAME OFFSET TYPE DESCRIPTION */
230  /* */
231  /* format 0 USHORT must be 2 */
232  /* length 2 USHORT table length in bytes */
233  /* language 4 USHORT Mac language code */
234  /* keys 6 USHORT[256] sub-header keys */
235  /* subs 518 SUBHEAD[NSUBS] sub-headers array */
236  /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */
237  /* */
238  /* The `keys' table is used to map charcode high-bytes to sub-headers. */
239  /* The value of `NSUBS' is the number of sub-headers defined in the */
240  /* table and is computed by finding the maximum of the `keys' table. */
241  /* */
242  /* Note that for any n, `keys[n]' is a byte offset within the `subs' */
243  /* table, i.e., it is the corresponding sub-header index multiplied */
244  /* by 8. */
245  /* */
246  /* Each sub-header has the following format: */
247  /* */
248  /* NAME OFFSET TYPE DESCRIPTION */
249  /* */
250  /* first 0 USHORT first valid low-byte */
251  /* count 2 USHORT number of valid low-bytes */
252  /* delta 4 SHORT see below */
253  /* offset 6 USHORT see below */
254  /* */
255  /* A sub-header defines, for each high-byte, the range of valid */
256  /* low-bytes within the charmap. Note that the range defined by `first' */
257  /* and `count' must be completely included in the interval [0..255] */
258  /* according to the specification. */
259  /* */
260  /* If a character code is contained within a given sub-header, then */
261  /* mapping it to a glyph index is done as follows: */
262  /* */
263  /* * The value of `offset' is read. This is a _byte_ distance from the */
264  /* location of the `offset' field itself into a slice of the */
265  /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[] too). */
266  /* */
267  /* * The value `slice[char.lo - first]' is read. If it is 0, there is */
268  /* no glyph for the charcode. Otherwise, the value of `delta' is */
269  /* added to it (modulo 65536) to form a new glyph index. */
270  /* */
271  /* It is up to the validation routine to check that all offsets fall */
272  /* within the glyph IDs table (and not within the `subs' table itself or */
273  /* outside of the CMap). */
274  /* */
275 
276 #ifdef TT_CONFIG_CMAP_FORMAT_2
277 
279  tt_cmap2_validate( FT_Byte* table,
280  FT_Validator valid )
281  {
282  FT_Byte* p = table + 2; /* skip format */
284  FT_UInt n, max_subs;
285  FT_Byte* keys; /* keys table */
286  FT_Byte* subs; /* sub-headers */
287  FT_Byte* glyph_ids; /* glyph ID array */
288 
289 
290  if ( table + length > valid->limit || length < 6 + 512 )
292 
293  keys = table + 6;
294 
295  /* parse keys to compute sub-headers count */
296  p = keys;
297  max_subs = 0;
298  for ( n = 0; n < 256; n++ )
299  {
300  FT_UInt idx = TT_NEXT_USHORT( p );
301 
302 
303  /* value must be multiple of 8 */
304  if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
306 
307  idx >>= 3;
308 
309  if ( idx > max_subs )
310  max_subs = idx;
311  }
312 
313  FT_ASSERT( p == table + 518 );
314 
315  subs = p;
316  glyph_ids = subs + (max_subs + 1) * 8;
317  if ( glyph_ids > valid->limit )
319 
320  /* parse sub-headers */
321  for ( n = 0; n <= max_subs; n++ )
322  {
323  FT_UInt first_code, code_count, offset;
324  FT_Int delta;
325  FT_Byte* ids;
326 
327 
328  first_code = TT_NEXT_USHORT( p );
329  code_count = TT_NEXT_USHORT( p );
330  delta = TT_NEXT_SHORT( p );
331  offset = TT_NEXT_USHORT( p );
332 
333  /* many Dynalab fonts have empty sub-headers */
334  if ( code_count == 0 )
335  continue;
336 
337  /* check range within 0..255 */
338  if ( valid->level >= FT_VALIDATE_PARANOID )
339  {
340  if ( first_code >= 256 || first_code + code_count > 256 )
342  }
343 
344  /* check offset */
345  if ( offset != 0 )
346  {
347  ids = p - 2 + offset;
350 
351  /* check glyph IDs */
352  if ( valid->level >= FT_VALIDATE_TIGHT )
353  {
354  FT_Byte* limit = p + code_count * 2;
355  FT_UInt idx;
356 
357 
358  for ( ; p < limit; )
359  {
360  idx = TT_NEXT_USHORT( p );
361  if ( idx != 0 )
362  {
363  idx = ( idx + delta ) & 0xFFFFU;
364  if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
366  }
367  }
368  }
369  }
370  }
371 
372  return FT_Err_Ok;
373  }
374 
375 
376  /* return sub header corresponding to a given character code */
377  /* NULL on invalid charcode */
378  static FT_Byte*
379  tt_cmap2_get_subheader( FT_Byte* table,
380  FT_UInt32 char_code )
381  {
382  FT_Byte* result = NULL;
383 
384 
385  if ( char_code < 0x10000UL )
386  {
387  FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
388  FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
389  FT_Byte* p = table + 6; /* keys table */
390  FT_Byte* subs = table + 518; /* subheaders table */
391  FT_Byte* sub;
392 
393 
394  if ( char_hi == 0 )
395  {
396  /* an 8-bit character code -- we use subHeader 0 in this case */
397  /* to test whether the character code is in the charmap */
398  /* */
399  sub = subs; /* jump to first sub-header */
400 
401  /* check that the sub-header for this byte is 0, which */
402  /* indicates that it is really a valid one-byte value */
403  /* Otherwise, return 0 */
404  /* */
405  p += char_lo * 2;
406  if ( TT_PEEK_USHORT( p ) != 0 )
407  goto Exit;
408  }
409  else
410  {
411  /* a 16-bit character code */
412 
413  /* jump to key entry */
414  p += char_hi * 2;
415  /* jump to sub-header */
416  sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
417 
418  /* check that the high byte isn't a valid one-byte value */
419  if ( sub == subs )
420  goto Exit;
421  }
422  result = sub;
423  }
424  Exit:
425  return result;
426  }
427 
428 
430  tt_cmap2_char_index( TT_CMap cmap,
431  FT_UInt32 char_code )
432  {
433  FT_Byte* table = cmap->data;
434  FT_UInt result = 0;
435  FT_Byte* subheader;
436 
437 
438  subheader = tt_cmap2_get_subheader( table, char_code );
439  if ( subheader )
440  {
441  FT_Byte* p = subheader;
442  FT_UInt idx = (FT_UInt)(char_code & 0xFF);
444  FT_Int delta;
445  FT_UInt offset;
446 
447 
448  start = TT_NEXT_USHORT( p );
449  count = TT_NEXT_USHORT( p );
450  delta = TT_NEXT_SHORT ( p );
451  offset = TT_PEEK_USHORT( p );
452 
453  idx -= start;
454  if ( idx < count && offset != 0 )
455  {
456  p += offset + 2 * idx;
457  idx = TT_PEEK_USHORT( p );
458 
459  if ( idx != 0 )
460  result = (FT_UInt)( idx + delta ) & 0xFFFFU;
461  }
462  }
463  return result;
464  }
465 
466 
468  tt_cmap2_char_next( TT_CMap cmap,
469  FT_UInt32 *pcharcode )
470  {
471  FT_Byte* table = cmap->data;
472  FT_UInt gindex = 0;
473  FT_UInt32 result = 0;
474  FT_UInt32 charcode = *pcharcode + 1;
475  FT_Byte* subheader;
476 
477 
478  while ( charcode < 0x10000UL )
479  {
480  subheader = tt_cmap2_get_subheader( table, charcode );
481  if ( subheader )
482  {
483  FT_Byte* p = subheader;
486  FT_Int delta = TT_NEXT_SHORT ( p );
488  FT_UInt char_lo = (FT_UInt)( charcode & 0xFF );
489  FT_UInt pos, idx;
490 
491 
492  if ( offset == 0 )
493  goto Next_SubHeader;
494 
495  if ( char_lo < start )
496  {
497  char_lo = start;
498  pos = 0;
499  }
500  else
501  pos = (FT_UInt)( char_lo - start );
502 
503  p += offset + pos * 2;
504  charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
505 
506  for ( ; pos < count; pos++, charcode++ )
507  {
508  idx = TT_NEXT_USHORT( p );
509 
510  if ( idx != 0 )
511  {
512  gindex = ( idx + delta ) & 0xFFFFU;
513  if ( gindex != 0 )
514  {
515  result = charcode;
516  goto Exit;
517  }
518  }
519  }
520  }
521 
522  /* jump to next sub-header, i.e. higher byte value */
523  Next_SubHeader:
524  charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
525  }
526 
527  Exit:
528  *pcharcode = result;
529 
530  return gindex;
531  }
532 
533 
535  tt_cmap2_get_info( TT_CMap cmap,
536  TT_CMapInfo *cmap_info )
537  {
538  FT_Byte* p = cmap->data + 4;
539 
540 
541  cmap_info->format = 2;
542  cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
543 
544  return FT_Err_Ok;
545  }
546 
547 
549  tt_cmap2_class_rec,
550  sizeof ( TT_CMapRec ),
551 
554  (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
555  (FT_CMap_CharNextFunc) tt_cmap2_char_next,
556 
557  NULL,
558  NULL,
559  NULL,
560  NULL,
561  NULL,
562 
563  2,
564  (TT_CMap_ValidateFunc)tt_cmap2_validate,
565  (TT_CMap_Info_GetFunc)tt_cmap2_get_info )
566 
567 #endif /* TT_CONFIG_CMAP_FORMAT_2 */
568 
569 
570  /*************************************************************************/
571  /*************************************************************************/
572  /***** *****/
573  /***** FORMAT 4 *****/
574  /***** *****/
575  /*************************************************************************/
576  /*************************************************************************/
577 
578  /*************************************************************************/
579  /* */
580  /* TABLE OVERVIEW */
581  /* -------------- */
582  /* */
583  /* NAME OFFSET TYPE DESCRIPTION */
584  /* */
585  /* format 0 USHORT must be 4 */
586  /* length 2 USHORT table length */
587  /* in bytes */
588  /* language 4 USHORT Mac language code */
589  /* */
590  /* segCountX2 6 USHORT 2*NUM_SEGS */
591  /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */
592  /* entrySelector 10 USHORT LOG_SEGS */
593  /* rangeShift 12 USHORT segCountX2 - */
594  /* searchRange */
595  /* */
596  /* endCount 14 USHORT[NUM_SEGS] end charcode for */
597  /* each segment; last */
598  /* is 0xFFFF */
599  /* */
600  /* pad 14+NUM_SEGS*2 USHORT padding */
601  /* */
602  /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */
603  /* each segment */
604  /* */
605  /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */
606  /* segment */
607  /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */
608  /* each segment; can be */
609  /* zero */
610  /* */
611  /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */
612  /* ranges */
613  /* */
614  /* Character codes are modelled by a series of ordered (increasing) */
615  /* intervals called segments. Each segment has start and end codes, */
616  /* provided by the `startCount' and `endCount' arrays. Segments must */
617  /* not overlap, and the last segment should always contain the value */
618  /* 0xFFFF for `endCount'. */
619  /* */
620  /* The fields `searchRange', `entrySelector' and `rangeShift' are better */
621  /* ignored (they are traces of over-engineering in the TrueType */
622  /* specification). */
623  /* */
624  /* Each segment also has a signed `delta', as well as an optional offset */
625  /* within the `glyphIds' table. */
626  /* */
627  /* If a segment's idOffset is 0, the glyph index corresponding to any */
628  /* charcode within the segment is obtained by adding the value of */
629  /* `idDelta' directly to the charcode, modulo 65536. */
630  /* */
631  /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */
632  /* the segment, and the value of `idDelta' is added to it. */
633  /* */
634  /* */
635  /* Finally, note that a lot of fonts contain an invalid last segment, */
636  /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */
637  /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */
638  /* OpenOffice.org). We need special code to deal with them correctly. */
639  /* */
640 
641 #ifdef TT_CONFIG_CMAP_FORMAT_4
642 
643  typedef struct TT_CMap4Rec_
644  {
645  TT_CMapRec cmap;
646  FT_UInt32 cur_charcode; /* current charcode */
647  FT_UInt cur_gindex; /* current glyph index */
648 
649  FT_UInt num_ranges;
650  FT_UInt cur_range;
651  FT_UInt cur_start;
652  FT_UInt cur_end;
653  FT_Int cur_delta;
654  FT_Byte* cur_values;
655 
656  } TT_CMap4Rec, *TT_CMap4;
657 
658 
660  tt_cmap4_init( TT_CMap4 cmap,
661  FT_Byte* table )
662  {
663  FT_Byte* p;
664 
665 
666  cmap->cmap.data = table;
667 
668  p = table + 6;
669  cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1;
670  cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
671  cmap->cur_gindex = 0;
672 
673  return FT_Err_Ok;
674  }
675 
676 
677  static FT_Int
678  tt_cmap4_set_range( TT_CMap4 cmap,
679  FT_UInt range_index )
680  {
681  FT_Byte* table = cmap->cmap.data;
682  FT_Byte* p;
683  FT_UInt num_ranges = cmap->num_ranges;
684 
685 
686  while ( range_index < num_ranges )
687  {
688  FT_UInt offset;
689 
690 
691  p = table + 14 + range_index * 2;
692  cmap->cur_end = FT_PEEK_USHORT( p );
693 
694  p += 2 + num_ranges * 2;
695  cmap->cur_start = FT_PEEK_USHORT( p );
696 
697  p += num_ranges * 2;
698  cmap->cur_delta = FT_PEEK_SHORT( p );
699 
700  p += num_ranges * 2;
701  offset = FT_PEEK_USHORT( p );
702 
703  /* some fonts have an incorrect last segment; */
704  /* we have to catch it */
705  if ( range_index >= num_ranges - 1 &&
706  cmap->cur_start == 0xFFFFU &&
707  cmap->cur_end == 0xFFFFU )
708  {
709  TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face;
710  FT_Byte* limit = face->cmap_table + face->cmap_size;
711 
712 
713  if ( offset && p + offset + 2 > limit )
714  {
715  cmap->cur_delta = 1;
716  offset = 0;
717  }
718  }
719 
720  if ( offset != 0xFFFFU )
721  {
722  cmap->cur_values = offset ? p + offset : NULL;
723  cmap->cur_range = range_index;
724  return 0;
725  }
726 
727  /* we skip empty segments */
728  range_index++;
729  }
730 
731  return -1;
732  }
733 
734 
735  /* search the index of the charcode next to cmap->cur_charcode; */
736  /* caller should call tt_cmap4_set_range with proper range */
737  /* before calling this function */
738  /* */
739  static void
740  tt_cmap4_next( TT_CMap4 cmap )
741  {
742  FT_UInt charcode;
743 
744 
745  if ( cmap->cur_charcode >= 0xFFFFUL )
746  goto Fail;
747 
748  charcode = (FT_UInt)cmap->cur_charcode + 1;
749 
750  if ( charcode < cmap->cur_start )
751  charcode = cmap->cur_start;
752 
753  for ( ;; )
754  {
755  FT_Byte* values = cmap->cur_values;
756  FT_UInt end = cmap->cur_end;
757  FT_Int delta = cmap->cur_delta;
758 
759 
760  if ( charcode <= end )
761  {
762  if ( values )
763  {
764  FT_Byte* p = values + 2 * ( charcode - cmap->cur_start );
765 
766 
767  do
768  {
769  FT_UInt gindex = FT_NEXT_USHORT( p );
770 
771 
772  if ( gindex != 0 )
773  {
774  gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
775  if ( gindex != 0 )
776  {
777  cmap->cur_charcode = charcode;
778  cmap->cur_gindex = gindex;
779  return;
780  }
781  }
782  } while ( ++charcode <= end );
783  }
784  else
785  {
786  do
787  {
788  FT_UInt gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
789 
790 
791  if ( gindex != 0 )
792  {
793  cmap->cur_charcode = charcode;
794  cmap->cur_gindex = gindex;
795  return;
796  }
797  } while ( ++charcode <= end );
798  }
799  }
800 
801  /* we need to find another range */
802  if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
803  break;
804 
805  if ( charcode < cmap->cur_start )
806  charcode = cmap->cur_start;
807  }
808 
809  Fail:
810  cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
811  cmap->cur_gindex = 0;
812  }
813 
814 
816  tt_cmap4_validate( FT_Byte* table,
817  FT_Validator valid )
818  {
819  FT_Byte* p = table + 2; /* skip format */
821  FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;
822  FT_UInt num_segs;
824 
825 
826  if ( length < 16 )
828 
829  /* in certain fonts, the `length' field is invalid and goes */
830  /* out of bound. We try to correct this here... */
831  if ( table + length > valid->limit )
832  {
833  if ( valid->level >= FT_VALIDATE_TIGHT )
835 
836  length = (FT_UInt)( valid->limit - table );
837  }
838 
839  p = table + 6;
840  num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */
841 
842  if ( valid->level >= FT_VALIDATE_PARANOID )
843  {
844  /* check that we have an even value here */
845  if ( num_segs & 1 )
847  }
848 
849  num_segs /= 2;
850 
851  if ( length < 16 + num_segs * 2 * 4 )
853 
854  /* check the search parameters - even though we never use them */
855  /* */
856  if ( valid->level >= FT_VALIDATE_PARANOID )
857  {
858  /* check the values of `searchRange', `entrySelector', `rangeShift' */
859  FT_UInt search_range = TT_NEXT_USHORT( p );
860  FT_UInt entry_selector = TT_NEXT_USHORT( p );
861  FT_UInt range_shift = TT_NEXT_USHORT( p );
862 
863 
864  if ( ( search_range | range_shift ) & 1 ) /* must be even values */
866 
867  search_range /= 2;
868  range_shift /= 2;
869 
870  /* `search range' is the greatest power of 2 that is <= num_segs */
871 
872  if ( search_range > num_segs ||
873  search_range * 2 < num_segs ||
874  search_range + range_shift != num_segs ||
875  search_range != ( 1U << entry_selector ) )
877  }
878 
879  ends = table + 14;
880  starts = table + 16 + num_segs * 2;
881  deltas = starts + num_segs * 2;
882  offsets = deltas + num_segs * 2;
883  glyph_ids = offsets + num_segs * 2;
884 
885  /* check last segment; its end count value must be 0xFFFF */
886  if ( valid->level >= FT_VALIDATE_PARANOID )
887  {
888  p = ends + ( num_segs - 1 ) * 2;
889  if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
891  }
892 
893  {
894  FT_UInt start, end, offset, n;
895  FT_UInt last_start = 0, last_end = 0;
896  FT_Int delta;
897  FT_Byte* p_start = starts;
898  FT_Byte* p_end = ends;
899  FT_Byte* p_delta = deltas;
900  FT_Byte* p_offset = offsets;
901 
902 
903  for ( n = 0; n < num_segs; n++ )
904  {
905  p = p_offset;
906  start = TT_NEXT_USHORT( p_start );
907  end = TT_NEXT_USHORT( p_end );
908  delta = TT_NEXT_SHORT( p_delta );
909  offset = TT_NEXT_USHORT( p_offset );
910 
911  if ( start > end )
913 
914  /* this test should be performed at default validation level; */
915  /* unfortunately, some popular Asian fonts have overlapping */
916  /* ranges in their charmaps */
917  /* */
918  if ( start <= last_end && n > 0 )
919  {
920  if ( valid->level >= FT_VALIDATE_TIGHT )
922  else
923  {
924  /* allow overlapping segments, provided their start points */
925  /* and end points, respectively, are in ascending order */
926  /* */
927  if ( last_start > start || last_end > end )
928  error |= TT_CMAP_FLAG_UNSORTED;
929  else
930  error |= TT_CMAP_FLAG_OVERLAPPING;
931  }
932  }
933 
934  if ( offset && offset != 0xFFFFU )
935  {
936  p += offset; /* start of glyph ID array */
937 
938  /* check that we point within the glyph IDs table only */
939  if ( valid->level >= FT_VALIDATE_TIGHT )
940  {
941  if ( p < glyph_ids ||
942  p + ( end - start + 1 ) * 2 > table + length )
944  }
945  /* Some fonts handle the last segment incorrectly. In */
946  /* theory, 0xFFFF might point to an ordinary glyph -- */
947  /* a cmap 4 is versatile and could be used for any */
948  /* encoding, not only Unicode. However, reality shows */
949  /* that far too many fonts are sloppy and incorrectly */
950  /* set all fields but `start' and `end' for the last */
951  /* segment if it contains only a single character. */
952  /* */
953  /* We thus omit the test here, delaying it to the */
954  /* routines which actually access the cmap. */
955  else if ( n != num_segs - 1 ||
956  !( start == 0xFFFFU && end == 0xFFFFU ) )
957  {
958  if ( p < glyph_ids ||
959  p + ( end - start + 1 ) * 2 > valid->limit )
961  }
962 
963  /* check glyph indices within the segment range */
964  if ( valid->level >= FT_VALIDATE_TIGHT )
965  {
966  FT_UInt i, idx;
967 
968 
969  for ( i = start; i < end; i++ )
970  {
971  idx = FT_NEXT_USHORT( p );
972  if ( idx != 0 )
973  {
974  idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
975 
976  if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
978  }
979  }
980  }
981  }
982  else if ( offset == 0xFFFFU )
983  {
984  /* some fonts (erroneously?) use a range offset of 0xFFFF */
985  /* to mean missing glyph in cmap table */
986  /* */
987  if ( valid->level >= FT_VALIDATE_PARANOID ||
988  n != num_segs - 1 ||
989  !( start == 0xFFFFU && end == 0xFFFFU ) )
991  }
992 
993  last_start = start;
994  last_end = end;
995  }
996  }
997 
998  return error;
999  }
1000 
1001 
1002  static FT_UInt
1003  tt_cmap4_char_map_linear( TT_CMap cmap,
1004  FT_UInt32* pcharcode,
1005  FT_Bool next )
1006  {
1007  FT_UInt num_segs2, start, end, offset;
1008  FT_Int delta;
1009  FT_UInt i, num_segs;
1010  FT_UInt32 charcode = *pcharcode;
1011  FT_UInt gindex = 0;
1012  FT_Byte* p;
1013 
1014 
1015  p = cmap->data + 6;
1016  num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1017 
1018  num_segs = num_segs2 >> 1;
1019 
1020  if ( !num_segs )
1021  return 0;
1022 
1023  if ( next )
1024  charcode++;
1025 
1026  /* linear search */
1027  for ( ; charcode <= 0xFFFFU; charcode++ )
1028  {
1029  FT_Byte* q;
1030 
1031 
1032  p = cmap->data + 14; /* ends table */
1033  q = cmap->data + 16 + num_segs2; /* starts table */
1034 
1035  for ( i = 0; i < num_segs; i++ )
1036  {
1037  end = TT_NEXT_USHORT( p );
1038  start = TT_NEXT_USHORT( q );
1039 
1040  if ( charcode >= start && charcode <= end )
1041  {
1042  p = q - 2 + num_segs2;
1043  delta = TT_PEEK_SHORT( p );
1044  p += num_segs2;
1045  offset = TT_PEEK_USHORT( p );
1046 
1047  /* some fonts have an incorrect last segment; */
1048  /* we have to catch it */
1049  if ( i >= num_segs - 1 &&
1050  start == 0xFFFFU && end == 0xFFFFU )
1051  {
1052  TT_Face face = (TT_Face)cmap->cmap.charmap.face;
1053  FT_Byte* limit = face->cmap_table + face->cmap_size;
1054 
1055 
1056  if ( offset && p + offset + 2 > limit )
1057  {
1058  delta = 1;
1059  offset = 0;
1060  }
1061  }
1062 
1063  if ( offset == 0xFFFFU )
1064  continue;
1065 
1066  if ( offset )
1067  {
1068  p += offset + ( charcode - start ) * 2;
1069  gindex = TT_PEEK_USHORT( p );
1070  if ( gindex != 0 )
1071  gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1072  }
1073  else
1074  gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
1075 
1076  break;
1077  }
1078  }
1079 
1080  if ( !next || gindex )
1081  break;
1082  }
1083 
1084  if ( next && gindex )
1085  *pcharcode = charcode;
1086 
1087  return gindex;
1088  }
1089 
1090 
1091  static FT_UInt
1092  tt_cmap4_char_map_binary( TT_CMap cmap,
1093  FT_UInt32* pcharcode,
1094  FT_Bool next )
1095  {
1096  FT_UInt num_segs2, start, end, offset;
1097  FT_Int delta;
1098  FT_UInt max, min, mid, num_segs;
1099  FT_UInt charcode = (FT_UInt)*pcharcode;
1100  FT_UInt gindex = 0;
1101  FT_Byte* p;
1102 
1103 
1104  p = cmap->data + 6;
1105  num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
1106 
1107  if ( !num_segs2 )
1108  return 0;
1109 
1110  num_segs = num_segs2 >> 1;
1111 
1112  /* make compiler happy */
1113  mid = num_segs;
1114  end = 0xFFFFU;
1115 
1116  if ( next )
1117  charcode++;
1118 
1119  min = 0;
1120  max = num_segs;
1121 
1122  /* binary search */
1123  while ( min < max )
1124  {
1125  mid = ( min + max ) >> 1;
1126  p = cmap->data + 14 + mid * 2;
1127  end = TT_PEEK_USHORT( p );
1128  p += 2 + num_segs2;
1129  start = TT_PEEK_USHORT( p );
1130 
1131  if ( charcode < start )
1132  max = mid;
1133  else if ( charcode > end )
1134  min = mid + 1;
1135  else
1136  {
1137  p += num_segs2;
1138  delta = TT_PEEK_SHORT( p );
1139  p += num_segs2;
1140  offset = TT_PEEK_USHORT( p );
1141 
1142  /* some fonts have an incorrect last segment; */
1143  /* we have to catch it */
1144  if ( mid >= num_segs - 1 &&
1145  start == 0xFFFFU && end == 0xFFFFU )
1146  {
1147  TT_Face face = (TT_Face)cmap->cmap.charmap.face;
1148  FT_Byte* limit = face->cmap_table + face->cmap_size;
1149 
1150 
1151  if ( offset && p + offset + 2 > limit )
1152  {
1153  delta = 1;
1154  offset = 0;
1155  }
1156  }
1157 
1158  /* search the first segment containing `charcode' */
1159  if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
1160  {
1161  FT_UInt i;
1162 
1163 
1164  /* call the current segment `max' */
1165  max = mid;
1166 
1167  if ( offset == 0xFFFFU )
1168  mid = max + 1;
1169 
1170  /* search in segments before the current segment */
1171  for ( i = max ; i > 0; i-- )
1172  {
1173  FT_UInt prev_end;
1174  FT_Byte* old_p;
1175 
1176 
1177  old_p = p;
1178  p = cmap->data + 14 + ( i - 1 ) * 2;
1179  prev_end = TT_PEEK_USHORT( p );
1180 
1181  if ( charcode > prev_end )
1182  {
1183  p = old_p;
1184  break;
1185  }
1186 
1187  end = prev_end;
1188  p += 2 + num_segs2;
1189  start = TT_PEEK_USHORT( p );
1190  p += num_segs2;
1191  delta = TT_PEEK_SHORT( p );
1192  p += num_segs2;
1193  offset = TT_PEEK_USHORT( p );
1194 
1195  if ( offset != 0xFFFFU )
1196  mid = i - 1;
1197  }
1198 
1199  /* no luck */
1200  if ( mid == max + 1 )
1201  {
1202  if ( i != max )
1203  {
1204  p = cmap->data + 14 + max * 2;
1205  end = TT_PEEK_USHORT( p );
1206  p += 2 + num_segs2;
1207  start = TT_PEEK_USHORT( p );
1208  p += num_segs2;
1209  delta = TT_PEEK_SHORT( p );
1210  p += num_segs2;
1211  offset = TT_PEEK_USHORT( p );
1212  }
1213 
1214  mid = max;
1215 
1216  /* search in segments after the current segment */
1217  for ( i = max + 1; i < num_segs; i++ )
1218  {
1219  FT_UInt next_end, next_start;
1220 
1221 
1222  p = cmap->data + 14 + i * 2;
1223  next_end = TT_PEEK_USHORT( p );
1224  p += 2 + num_segs2;
1225  next_start = TT_PEEK_USHORT( p );
1226 
1227  if ( charcode < next_start )
1228  break;
1229 
1230  end = next_end;
1231  start = next_start;
1232  p += num_segs2;
1233  delta = TT_PEEK_SHORT( p );
1234  p += num_segs2;
1235  offset = TT_PEEK_USHORT( p );
1236 
1237  if ( offset != 0xFFFFU )
1238  mid = i;
1239  }
1240  i--;
1241 
1242  /* still no luck */
1243  if ( mid == max )
1244  {
1245  mid = i;
1246 
1247  break;
1248  }
1249  }
1250 
1251  /* end, start, delta, and offset are for the i'th segment */
1252  if ( mid != i )
1253  {
1254  p = cmap->data + 14 + mid * 2;
1255  end = TT_PEEK_USHORT( p );
1256  p += 2 + num_segs2;
1257  start = TT_PEEK_USHORT( p );
1258  p += num_segs2;
1259  delta = TT_PEEK_SHORT( p );
1260  p += num_segs2;
1261  offset = TT_PEEK_USHORT( p );
1262  }
1263  }
1264  else
1265  {
1266  if ( offset == 0xFFFFU )
1267  break;
1268  }
1269 
1270  if ( offset )
1271  {
1272  p += offset + ( charcode - start ) * 2;
1273  gindex = TT_PEEK_USHORT( p );
1274  if ( gindex != 0 )
1275  gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
1276  }
1277  else
1278  gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
1279 
1280  break;
1281  }
1282  }
1283 
1284  if ( next )
1285  {
1286  TT_CMap4 cmap4 = (TT_CMap4)cmap;
1287 
1288 
1289  /* if `charcode' is not in any segment, then `mid' is */
1290  /* the segment nearest to `charcode' */
1291  /* */
1292 
1293  if ( charcode > end )
1294  {
1295  mid++;
1296  if ( mid == num_segs )
1297  return 0;
1298  }
1299 
1300  if ( tt_cmap4_set_range( cmap4, mid ) )
1301  {
1302  if ( gindex )
1303  *pcharcode = charcode;
1304  }
1305  else
1306  {
1307  cmap4->cur_charcode = charcode;
1308 
1309  if ( gindex )
1310  cmap4->cur_gindex = gindex;
1311  else
1312  {
1313  cmap4->cur_charcode = charcode;
1314  tt_cmap4_next( cmap4 );
1315  gindex = cmap4->cur_gindex;
1316  }
1317 
1318  if ( gindex )
1319  *pcharcode = cmap4->cur_charcode;
1320  }
1321  }
1322 
1323  return gindex;
1324  }
1325 
1326 
1328  tt_cmap4_char_index( TT_CMap cmap,
1329  FT_UInt32 char_code )
1330  {
1331  if ( char_code >= 0x10000UL )
1332  return 0;
1333 
1334  if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1335  return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
1336  else
1337  return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
1338  }
1339 
1340 
1342  tt_cmap4_char_next( TT_CMap cmap,
1343  FT_UInt32 *pchar_code )
1344  {
1345  FT_UInt gindex;
1346 
1347 
1348  if ( *pchar_code >= 0xFFFFU )
1349  return 0;
1350 
1351  if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
1352  gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
1353  else
1354  {
1355  TT_CMap4 cmap4 = (TT_CMap4)cmap;
1356 
1357 
1358  /* no need to search */
1359  if ( *pchar_code == cmap4->cur_charcode )
1360  {
1361  tt_cmap4_next( cmap4 );
1362  gindex = cmap4->cur_gindex;
1363  if ( gindex )
1364  *pchar_code = cmap4->cur_charcode;
1365  }
1366  else
1367  gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
1368  }
1369 
1370  return gindex;
1371  }
1372 
1373 
1375  tt_cmap4_get_info( TT_CMap cmap,
1376  TT_CMapInfo *cmap_info )
1377  {
1378  FT_Byte* p = cmap->data + 4;
1379 
1380 
1381  cmap_info->format = 4;
1382  cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1383 
1384  return FT_Err_Ok;
1385  }
1386 
1387 
1389  tt_cmap4_class_rec,
1390  sizeof ( TT_CMap4Rec ),
1391  (FT_CMap_InitFunc) tt_cmap4_init,
1393  (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
1394  (FT_CMap_CharNextFunc) tt_cmap4_char_next,
1395 
1396  NULL,
1397  NULL,
1398  NULL,
1399  NULL,
1400  NULL,
1401 
1402  4,
1403  (TT_CMap_ValidateFunc)tt_cmap4_validate,
1404  (TT_CMap_Info_GetFunc)tt_cmap4_get_info )
1405 
1406 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
1407 
1408 
1409  /*************************************************************************/
1410  /*************************************************************************/
1411  /***** *****/
1412  /***** FORMAT 6 *****/
1413  /***** *****/
1414  /*************************************************************************/
1415  /*************************************************************************/
1416 
1417  /*************************************************************************/
1418  /* */
1419  /* TABLE OVERVIEW */
1420  /* -------------- */
1421  /* */
1422  /* NAME OFFSET TYPE DESCRIPTION */
1423  /* */
1424  /* format 0 USHORT must be 4 */
1425  /* length 2 USHORT table length in bytes */
1426  /* language 4 USHORT Mac language code */
1427  /* */
1428  /* first 6 USHORT first segment code */
1429  /* count 8 USHORT segment size in chars */
1430  /* glyphIds 10 USHORT[count] glyph IDs */
1431  /* */
1432  /* A very simplified segment mapping. */
1433  /* */
1434 
1435 #ifdef TT_CONFIG_CMAP_FORMAT_6
1436 
1438  tt_cmap6_validate( FT_Byte* table,
1439  FT_Validator valid )
1440  {
1441  FT_Byte* p;
1442  FT_UInt length, count;
1443 
1444 
1445  if ( table + 10 > valid->limit )
1447 
1448  p = table + 2;
1449  length = TT_NEXT_USHORT( p );
1450 
1451  p = table + 8; /* skip language and start index */
1452  count = TT_NEXT_USHORT( p );
1453 
1454  if ( table + length > valid->limit || length < 10 + count * 2 )
1456 
1457  /* check glyph indices */
1458  if ( valid->level >= FT_VALIDATE_TIGHT )
1459  {
1460  FT_UInt gindex;
1461 
1462 
1463  for ( ; count > 0; count-- )
1464  {
1465  gindex = TT_NEXT_USHORT( p );
1466  if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1468  }
1469  }
1470 
1471  return FT_Err_Ok;
1472  }
1473 
1474 
1476  tt_cmap6_char_index( TT_CMap cmap,
1477  FT_UInt32 char_code )
1478  {
1479  FT_Byte* table = cmap->data;
1480  FT_UInt result = 0;
1481  FT_Byte* p = table + 6;
1482  FT_UInt start = TT_NEXT_USHORT( p );
1483  FT_UInt count = TT_NEXT_USHORT( p );
1484  FT_UInt idx = (FT_UInt)( char_code - start );
1485 
1486 
1487  if ( idx < count )
1488  {
1489  p += 2 * idx;
1490  result = TT_PEEK_USHORT( p );
1491  }
1492  return result;
1493  }
1494 
1495 
1497  tt_cmap6_char_next( TT_CMap cmap,
1498  FT_UInt32 *pchar_code )
1499  {
1500  FT_Byte* table = cmap->data;
1501  FT_UInt32 result = 0;
1502  FT_UInt32 char_code = *pchar_code + 1;
1503  FT_UInt gindex = 0;
1504 
1505  FT_Byte* p = table + 6;
1506  FT_UInt start = TT_NEXT_USHORT( p );
1507  FT_UInt count = TT_NEXT_USHORT( p );
1508  FT_UInt idx;
1509 
1510 
1511  if ( char_code >= 0x10000UL )
1512  goto Exit;
1513 
1514  if ( char_code < start )
1515  char_code = start;
1516 
1517  idx = (FT_UInt)( char_code - start );
1518  p += 2 * idx;
1519 
1520  for ( ; idx < count; idx++ )
1521  {
1522  gindex = TT_NEXT_USHORT( p );
1523  if ( gindex != 0 )
1524  {
1525  result = char_code;
1526  break;
1527  }
1528  char_code++;
1529  }
1530 
1531  Exit:
1532  *pchar_code = result;
1533  return gindex;
1534  }
1535 
1536 
1538  tt_cmap6_get_info( TT_CMap cmap,
1539  TT_CMapInfo *cmap_info )
1540  {
1541  FT_Byte* p = cmap->data + 4;
1542 
1543 
1544  cmap_info->format = 6;
1545  cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
1546 
1547  return FT_Err_Ok;
1548  }
1549 
1550 
1552  tt_cmap6_class_rec,
1553  sizeof ( TT_CMapRec ),
1554 
1557  (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
1558  (FT_CMap_CharNextFunc) tt_cmap6_char_next,
1559 
1560  NULL,
1561  NULL,
1562  NULL,
1563  NULL,
1564  NULL,
1565 
1566  6,
1567  (TT_CMap_ValidateFunc)tt_cmap6_validate,
1568  (TT_CMap_Info_GetFunc)tt_cmap6_get_info )
1569 
1570 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
1571 
1572 
1573  /*************************************************************************/
1574  /*************************************************************************/
1575  /***** *****/
1576  /***** FORMAT 8 *****/
1577  /***** *****/
1578  /***** It is hard to completely understand what the OpenType spec *****/
1579  /***** says about this format, but here is my conclusion. *****/
1580  /***** *****/
1581  /***** The purpose of this format is to easily map UTF-16 text to *****/
1582  /***** glyph indices. Basically, the `char_code' must be in one of *****/
1583  /***** the following formats: *****/
1584  /***** *****/
1585  /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
1586  /***** Area (i.e. U+D800-U+DFFF). *****/
1587  /***** *****/
1588  /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/
1589  /***** `char_code = (char_hi << 16) | char_lo', then both *****/
1590  /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/
1591  /***** Area. *****/
1592  /***** *****/
1593  /***** The `is32' table embedded in the charmap indicates whether a *****/
1594  /***** given 16-bit value is in the surrogates area or not. *****/
1595  /***** *****/
1596  /***** So, for any given `char_code', we can assert the following: *****/
1597  /***** *****/
1598  /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
1599  /***** *****/
1600  /***** If `char_hi != 0' then we must have both *****/
1601  /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/
1602  /***** *****/
1603  /*************************************************************************/
1604  /*************************************************************************/
1605 
1606  /*************************************************************************/
1607  /* */
1608  /* TABLE OVERVIEW */
1609  /* -------------- */
1610  /* */
1611  /* NAME OFFSET TYPE DESCRIPTION */
1612  /* */
1613  /* format 0 USHORT must be 8 */
1614  /* reserved 2 USHORT reserved */
1615  /* length 4 ULONG length in bytes */
1616  /* language 8 ULONG Mac language code */
1617  /* is32 12 BYTE[8192] 32-bitness bitmap */
1618  /* count 8204 ULONG number of groups */
1619  /* */
1620  /* This header is followed by `count' groups of the following format: */
1621  /* */
1622  /* start 0 ULONG first charcode */
1623  /* end 4 ULONG last charcode */
1624  /* startId 8 ULONG start glyph ID for the group */
1625  /* */
1626 
1627 #ifdef TT_CONFIG_CMAP_FORMAT_8
1628 
1630  tt_cmap8_validate( FT_Byte* table,
1631  FT_Validator valid )
1632  {
1633  FT_Byte* p = table + 4;
1634  FT_Byte* is32;
1635  FT_UInt32 length;
1636  FT_UInt32 num_groups;
1637 
1638 
1639  if ( table + 16 + 8192 > valid->limit )
1641 
1642  length = TT_NEXT_ULONG( p );
1643  if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 )
1645 
1646  is32 = table + 12;
1647  p = is32 + 8192; /* skip `is32' array */
1648  num_groups = TT_NEXT_ULONG( p );
1649 
1650  if ( p + num_groups * 12 > valid->limit )
1652 
1653  /* check groups, they must be in increasing order */
1654  {
1655  FT_UInt32 n, start, end, start_id, count, last = 0;
1656 
1657 
1658  for ( n = 0; n < num_groups; n++ )
1659  {
1660  FT_UInt hi, lo;
1661 
1662 
1663  start = TT_NEXT_ULONG( p );
1664  end = TT_NEXT_ULONG( p );
1665  start_id = TT_NEXT_ULONG( p );
1666 
1667  if ( start > end )
1669 
1670  if ( n > 0 && start <= last )
1672 
1673  if ( valid->level >= FT_VALIDATE_TIGHT )
1674  {
1675  if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
1677 
1678  count = (FT_UInt32)( end - start + 1 );
1679 
1680  if ( start & ~0xFFFFU )
1681  {
1682  /* start_hi != 0; check that is32[i] is 1 for each i in */
1683  /* the `hi' and `lo' of the range [start..end] */
1684  for ( ; count > 0; count--, start++ )
1685  {
1686  hi = (FT_UInt)( start >> 16 );
1687  lo = (FT_UInt)( start & 0xFFFFU );
1688 
1689  if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
1691 
1692  if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
1694  }
1695  }
1696  else
1697  {
1698  /* start_hi == 0; check that is32[i] is 0 for each i in */
1699  /* the range [start..end] */
1700 
1701  /* end_hi cannot be != 0! */
1702  if ( end & ~0xFFFFU )
1704 
1705  for ( ; count > 0; count--, start++ )
1706  {
1707  lo = (FT_UInt)( start & 0xFFFFU );
1708 
1709  if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
1711  }
1712  }
1713  }
1714 
1715  last = end;
1716  }
1717  }
1718 
1719  return FT_Err_Ok;
1720  }
1721 
1722 
1724  tt_cmap8_char_index( TT_CMap cmap,
1725  FT_UInt32 char_code )
1726  {
1727  FT_Byte* table = cmap->data;
1728  FT_UInt result = 0;
1729  FT_Byte* p = table + 8204;
1730  FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1731  FT_UInt32 start, end, start_id;
1732 
1733 
1734  for ( ; num_groups > 0; num_groups-- )
1735  {
1736  start = TT_NEXT_ULONG( p );
1737  end = TT_NEXT_ULONG( p );
1738  start_id = TT_NEXT_ULONG( p );
1739 
1740  if ( char_code < start )
1741  break;
1742 
1743  if ( char_code <= end )
1744  {
1745  result = (FT_UInt)( start_id + char_code - start );
1746  break;
1747  }
1748  }
1749  return result;
1750  }
1751 
1752 
1754  tt_cmap8_char_next( TT_CMap cmap,
1755  FT_UInt32 *pchar_code )
1756  {
1757  FT_UInt32 result = 0;
1758  FT_UInt32 char_code = *pchar_code + 1;
1759  FT_UInt gindex = 0;
1760  FT_Byte* table = cmap->data;
1761  FT_Byte* p = table + 8204;
1762  FT_UInt32 num_groups = TT_NEXT_ULONG( p );
1763  FT_UInt32 start, end, start_id;
1764 
1765 
1766  p = table + 8208;
1767 
1768  for ( ; num_groups > 0; num_groups-- )
1769  {
1770  start = TT_NEXT_ULONG( p );
1771  end = TT_NEXT_ULONG( p );
1772  start_id = TT_NEXT_ULONG( p );
1773 
1774  if ( char_code < start )
1775  char_code = start;
1776 
1777  if ( char_code <= end )
1778  {
1779  gindex = (FT_UInt)( char_code - start + start_id );
1780  if ( gindex != 0 )
1781  {
1782  result = char_code;
1783  goto Exit;
1784  }
1785  }
1786  }
1787 
1788  Exit:
1789  *pchar_code = result;
1790  return gindex;
1791  }
1792 
1793 
1795  tt_cmap8_get_info( TT_CMap cmap,
1796  TT_CMapInfo *cmap_info )
1797  {
1798  FT_Byte* p = cmap->data + 8;
1799 
1800 
1801  cmap_info->format = 8;
1802  cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1803 
1804  return FT_Err_Ok;
1805  }
1806 
1807 
1809  tt_cmap8_class_rec,
1810  sizeof ( TT_CMapRec ),
1811 
1814  (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
1815  (FT_CMap_CharNextFunc) tt_cmap8_char_next,
1816 
1817  NULL,
1818  NULL,
1819  NULL,
1820  NULL,
1821  NULL,
1822 
1823  8,
1824  (TT_CMap_ValidateFunc)tt_cmap8_validate,
1825  (TT_CMap_Info_GetFunc)tt_cmap8_get_info )
1826 
1827 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
1828 
1829 
1830  /*************************************************************************/
1831  /*************************************************************************/
1832  /***** *****/
1833  /***** FORMAT 10 *****/
1834  /***** *****/
1835  /*************************************************************************/
1836  /*************************************************************************/
1837 
1838  /*************************************************************************/
1839  /* */
1840  /* TABLE OVERVIEW */
1841  /* -------------- */
1842  /* */
1843  /* NAME OFFSET TYPE DESCRIPTION */
1844  /* */
1845  /* format 0 USHORT must be 10 */
1846  /* reserved 2 USHORT reserved */
1847  /* length 4 ULONG length in bytes */
1848  /* language 8 ULONG Mac language code */
1849  /* */
1850  /* start 12 ULONG first char in range */
1851  /* count 16 ULONG number of chars in range */
1852  /* glyphIds 20 USHORT[count] glyph indices covered */
1853  /* */
1854 
1855 #ifdef TT_CONFIG_CMAP_FORMAT_10
1856 
1858  tt_cmap10_validate( FT_Byte* table,
1859  FT_Validator valid )
1860  {
1861  FT_Byte* p = table + 4;
1863 
1864 
1865  if ( table + 20 > valid->limit )
1867 
1868  length = TT_NEXT_ULONG( p );
1869  p = table + 16;
1870  count = TT_NEXT_ULONG( p );
1871 
1872  if ( length > (FT_ULong)( valid->limit - table ) ||
1873  length < 20 + count * 2 )
1875 
1876  /* check glyph indices */
1877  if ( valid->level >= FT_VALIDATE_TIGHT )
1878  {
1879  FT_UInt gindex;
1880 
1881 
1882  for ( ; count > 0; count-- )
1883  {
1884  gindex = TT_NEXT_USHORT( p );
1885  if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
1887  }
1888  }
1889 
1890  return FT_Err_Ok;
1891  }
1892 
1893 
1895  tt_cmap10_char_index( TT_CMap cmap,
1896  FT_UInt32 char_code )
1897  {
1898  FT_Byte* table = cmap->data;
1899  FT_UInt result = 0;
1900  FT_Byte* p = table + 12;
1901  FT_UInt32 start = TT_NEXT_ULONG( p );
1902  FT_UInt32 count = TT_NEXT_ULONG( p );
1903  FT_UInt32 idx = (FT_ULong)( char_code - start );
1904 
1905 
1906  if ( idx < count )
1907  {
1908  p += 2 * idx;
1909  result = TT_PEEK_USHORT( p );
1910  }
1911  return result;
1912  }
1913 
1914 
1916  tt_cmap10_char_next( TT_CMap cmap,
1917  FT_UInt32 *pchar_code )
1918  {
1919  FT_Byte* table = cmap->data;
1920  FT_UInt32 char_code = *pchar_code + 1;
1921  FT_UInt gindex = 0;
1922  FT_Byte* p = table + 12;
1923  FT_UInt32 start = TT_NEXT_ULONG( p );
1924  FT_UInt32 count = TT_NEXT_ULONG( p );
1925  FT_UInt32 idx;
1926 
1927 
1928  if ( char_code < start )
1929  char_code = start;
1930 
1931  idx = (FT_UInt32)( char_code - start );
1932  p += 2 * idx;
1933 
1934  for ( ; idx < count; idx++ )
1935  {
1936  gindex = TT_NEXT_USHORT( p );
1937  if ( gindex != 0 )
1938  break;
1939  char_code++;
1940  }
1941 
1942  *pchar_code = char_code;
1943  return gindex;
1944  }
1945 
1946 
1948  tt_cmap10_get_info( TT_CMap cmap,
1949  TT_CMapInfo *cmap_info )
1950  {
1951  FT_Byte* p = cmap->data + 8;
1952 
1953 
1954  cmap_info->format = 10;
1955  cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
1956 
1957  return FT_Err_Ok;
1958  }
1959 
1960 
1962  tt_cmap10_class_rec,
1963  sizeof ( TT_CMapRec ),
1964 
1967  (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
1968  (FT_CMap_CharNextFunc) tt_cmap10_char_next,
1969 
1970  NULL,
1971  NULL,
1972  NULL,
1973  NULL,
1974  NULL,
1975 
1976  10,
1977  (TT_CMap_ValidateFunc)tt_cmap10_validate,
1978  (TT_CMap_Info_GetFunc)tt_cmap10_get_info )
1979 
1980 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
1981 
1982 
1983  /*************************************************************************/
1984  /*************************************************************************/
1985  /***** *****/
1986  /***** FORMAT 12 *****/
1987  /***** *****/
1988  /*************************************************************************/
1989  /*************************************************************************/
1990 
1991  /*************************************************************************/
1992  /* */
1993  /* TABLE OVERVIEW */
1994  /* -------------- */
1995  /* */
1996  /* NAME OFFSET TYPE DESCRIPTION */
1997  /* */
1998  /* format 0 USHORT must be 12 */
1999  /* reserved 2 USHORT reserved */
2000  /* length 4 ULONG length in bytes */
2001  /* language 8 ULONG Mac language code */
2002  /* count 12 ULONG number of groups */
2003  /* 16 */
2004  /* */
2005  /* This header is followed by `count' groups of the following format: */
2006  /* */
2007  /* start 0 ULONG first charcode */
2008  /* end 4 ULONG last charcode */
2009  /* startId 8 ULONG start glyph ID for the group */
2010  /* */
2011 
2012 #ifdef TT_CONFIG_CMAP_FORMAT_12
2013 
2014  typedef struct TT_CMap12Rec_
2015  {
2016  TT_CMapRec cmap;
2017  FT_Bool valid;
2018  FT_ULong cur_charcode;
2019  FT_UInt cur_gindex;
2020  FT_ULong cur_group;
2021  FT_ULong num_groups;
2022 
2023  } TT_CMap12Rec, *TT_CMap12;
2024 
2025 
2027  tt_cmap12_init( TT_CMap12 cmap,
2028  FT_Byte* table )
2029  {
2030  cmap->cmap.data = table;
2031 
2032  table += 12;
2033  cmap->num_groups = FT_PEEK_ULONG( table );
2034 
2035  cmap->valid = 0;
2036 
2037  return FT_Err_Ok;
2038  }
2039 
2040 
2042  tt_cmap12_validate( FT_Byte* table,
2043  FT_Validator valid )
2044  {
2045  FT_Byte* p;
2046  FT_ULong length;
2047  FT_ULong num_groups;
2048 
2049 
2050  if ( table + 16 > valid->limit )
2052 
2053  p = table + 4;
2054  length = TT_NEXT_ULONG( p );
2055 
2056  p = table + 12;
2057  num_groups = TT_NEXT_ULONG( p );
2058 
2059  if ( length > (FT_ULong)( valid->limit - table ) ||
2060  length < 16 + 12 * num_groups )
2062 
2063  /* check groups, they must be in increasing order */
2064  {
2065  FT_ULong n, start, end, start_id, last = 0;
2066 
2067 
2068  for ( n = 0; n < num_groups; n++ )
2069  {
2070  start = TT_NEXT_ULONG( p );
2071  end = TT_NEXT_ULONG( p );
2072  start_id = TT_NEXT_ULONG( p );
2073 
2074  if ( start > end )
2076 
2077  if ( n > 0 && start <= last )
2079 
2080  if ( valid->level >= FT_VALIDATE_TIGHT )
2081  {
2082  if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
2084  }
2085 
2086  last = end;
2087  }
2088  }
2089 
2090  return FT_Err_Ok;
2091  }
2092 
2093 
2094  /* search the index of the charcode next to cmap->cur_charcode */
2095  /* cmap->cur_group should be set up properly by caller */
2096  /* */
2097  static void
2098  tt_cmap12_next( TT_CMap12 cmap )
2099  {
2100  FT_Byte* p;
2101  FT_ULong start, end, start_id, char_code;
2102  FT_ULong n;
2103  FT_UInt gindex;
2104 
2105 
2106  if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2107  goto Fail;
2108 
2109  char_code = cmap->cur_charcode + 1;
2110 
2111  n = cmap->cur_group;
2112 
2113  for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2114  {
2115  p = cmap->cmap.data + 16 + 12 * n;
2116  start = TT_NEXT_ULONG( p );
2117  end = TT_NEXT_ULONG( p );
2118  start_id = TT_PEEK_ULONG( p );
2119 
2120  if ( char_code < start )
2121  char_code = start;
2122 
2123  for ( ; char_code <= end; char_code++ )
2124  {
2125  gindex = (FT_UInt)( start_id + char_code - start );
2126 
2127  if ( gindex )
2128  {
2129  cmap->cur_charcode = char_code;;
2130  cmap->cur_gindex = gindex;
2131  cmap->cur_group = n;
2132 
2133  return;
2134  }
2135  }
2136  }
2137 
2138  Fail:
2139  cmap->valid = 0;
2140  }
2141 
2142 
2143  static FT_UInt
2144  tt_cmap12_char_map_binary( TT_CMap cmap,
2145  FT_UInt32* pchar_code,
2146  FT_Bool next )
2147  {
2148  FT_UInt gindex = 0;
2149  FT_Byte* p = cmap->data + 12;
2150  FT_UInt32 num_groups = TT_PEEK_ULONG( p );
2151  FT_UInt32 char_code = *pchar_code;
2152  FT_UInt32 start, end, start_id;
2153  FT_UInt32 max, min, mid;
2154 
2155 
2156  if ( !num_groups )
2157  return 0;
2158 
2159  /* make compiler happy */
2160  mid = num_groups;
2161  end = 0xFFFFFFFFUL;
2162 
2163  if ( next )
2164  char_code++;
2165 
2166  min = 0;
2167  max = num_groups;
2168 
2169  /* binary search */
2170  while ( min < max )
2171  {
2172  mid = ( min + max ) >> 1;
2173  p = cmap->data + 16 + 12 * mid;
2174 
2175  start = TT_NEXT_ULONG( p );
2176  end = TT_NEXT_ULONG( p );
2177 
2178  if ( char_code < start )
2179  max = mid;
2180  else if ( char_code > end )
2181  min = mid + 1;
2182  else
2183  {
2184  start_id = TT_PEEK_ULONG( p );
2185  gindex = (FT_UInt)( start_id + char_code - start );
2186 
2187  break;
2188  }
2189  }
2190 
2191  if ( next )
2192  {
2193  TT_CMap12 cmap12 = (TT_CMap12)cmap;
2194 
2195 
2196  /* if `char_code' is not in any group, then `mid' is */
2197  /* the group nearest to `char_code' */
2198  /* */
2199 
2200  if ( char_code > end )
2201  {
2202  mid++;
2203  if ( mid == num_groups )
2204  return 0;
2205  }
2206 
2207  cmap12->valid = 1;
2208  cmap12->cur_charcode = char_code;
2209  cmap12->cur_group = mid;
2210 
2211  if ( !gindex )
2212  {
2213  tt_cmap12_next( cmap12 );
2214 
2215  if ( cmap12->valid )
2216  gindex = cmap12->cur_gindex;
2217  }
2218  else
2219  cmap12->cur_gindex = gindex;
2220 
2221  if ( gindex )
2222  *pchar_code = cmap12->cur_charcode;
2223  }
2224 
2225  return gindex;
2226  }
2227 
2228 
2230  tt_cmap12_char_index( TT_CMap cmap,
2231  FT_UInt32 char_code )
2232  {
2233  return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
2234  }
2235 
2236 
2238  tt_cmap12_char_next( TT_CMap cmap,
2239  FT_UInt32 *pchar_code )
2240  {
2241  TT_CMap12 cmap12 = (TT_CMap12)cmap;
2242  FT_ULong gindex;
2243 
2244 
2245  if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
2246  return 0;
2247 
2248  /* no need to search */
2249  if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
2250  {
2251  tt_cmap12_next( cmap12 );
2252  if ( cmap12->valid )
2253  {
2254  gindex = cmap12->cur_gindex;
2255 
2256  /* XXX: check cur_charcode overflow is expected */
2257  if ( gindex )
2258  *pchar_code = (FT_UInt32)cmap12->cur_charcode;
2259  }
2260  else
2261  gindex = 0;
2262  }
2263  else
2264  gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
2265 
2266  /* XXX: check gindex overflow is expected */
2267  return (FT_UInt32)gindex;
2268  }
2269 
2270 
2272  tt_cmap12_get_info( TT_CMap cmap,
2273  TT_CMapInfo *cmap_info )
2274  {
2275  FT_Byte* p = cmap->data + 8;
2276 
2277 
2278  cmap_info->format = 12;
2279  cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2280 
2281  return FT_Err_Ok;
2282  }
2283 
2284 
2286  tt_cmap12_class_rec,
2287  sizeof ( TT_CMap12Rec ),
2288 
2289  (FT_CMap_InitFunc) tt_cmap12_init,
2291  (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
2292  (FT_CMap_CharNextFunc) tt_cmap12_char_next,
2293 
2294  NULL,
2295  NULL,
2296  NULL,
2297  NULL,
2298  NULL,
2299 
2300  12,
2301  (TT_CMap_ValidateFunc)tt_cmap12_validate,
2302  (TT_CMap_Info_GetFunc)tt_cmap12_get_info )
2303 
2304 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
2305 
2306 
2307  /*************************************************************************/
2308  /*************************************************************************/
2309  /***** *****/
2310  /***** FORMAT 13 *****/
2311  /***** *****/
2312  /*************************************************************************/
2313  /*************************************************************************/
2314 
2315  /*************************************************************************/
2316  /* */
2317  /* TABLE OVERVIEW */
2318  /* -------------- */
2319  /* */
2320  /* NAME OFFSET TYPE DESCRIPTION */
2321  /* */
2322  /* format 0 USHORT must be 13 */
2323  /* reserved 2 USHORT reserved */
2324  /* length 4 ULONG length in bytes */
2325  /* language 8 ULONG Mac language code */
2326  /* count 12 ULONG number of groups */
2327  /* 16 */
2328  /* */
2329  /* This header is followed by `count' groups of the following format: */
2330  /* */
2331  /* start 0 ULONG first charcode */
2332  /* end 4 ULONG last charcode */
2333  /* glyphId 8 ULONG glyph ID for the whole group */
2334  /* */
2335 
2336 #ifdef TT_CONFIG_CMAP_FORMAT_13
2337 
2338  typedef struct TT_CMap13Rec_
2339  {
2340  TT_CMapRec cmap;
2341  FT_Bool valid;
2342  FT_ULong cur_charcode;
2343  FT_UInt cur_gindex;
2344  FT_ULong cur_group;
2345  FT_ULong num_groups;
2346 
2347  } TT_CMap13Rec, *TT_CMap13;
2348 
2349 
2351  tt_cmap13_init( TT_CMap13 cmap,
2352  FT_Byte* table )
2353  {
2354  cmap->cmap.data = table;
2355 
2356  table += 12;
2357  cmap->num_groups = FT_PEEK_ULONG( table );
2358 
2359  cmap->valid = 0;
2360 
2361  return FT_Err_Ok;
2362  }
2363 
2364 
2366  tt_cmap13_validate( FT_Byte* table,
2367  FT_Validator valid )
2368  {
2369  FT_Byte* p;
2370  FT_ULong length;
2371  FT_ULong num_groups;
2372 
2373 
2374  if ( table + 16 > valid->limit )
2376 
2377  p = table + 4;
2378  length = TT_NEXT_ULONG( p );
2379 
2380  p = table + 12;
2381  num_groups = TT_NEXT_ULONG( p );
2382 
2383  if ( length > (FT_ULong)( valid->limit - table ) ||
2384  length < 16 + 12 * num_groups )
2386 
2387  /* check groups, they must be in increasing order */
2388  {
2389  FT_ULong n, start, end, glyph_id, last = 0;
2390 
2391 
2392  for ( n = 0; n < num_groups; n++ )
2393  {
2394  start = TT_NEXT_ULONG( p );
2395  end = TT_NEXT_ULONG( p );
2396  glyph_id = TT_NEXT_ULONG( p );
2397 
2398  if ( start > end )
2400 
2401  if ( n > 0 && start <= last )
2403 
2404  if ( valid->level >= FT_VALIDATE_TIGHT )
2405  {
2406  if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
2408  }
2409 
2410  last = end;
2411  }
2412  }
2413 
2414  return FT_Err_Ok;
2415  }
2416 
2417 
2418  /* search the index of the charcode next to cmap->cur_charcode */
2419  /* cmap->cur_group should be set up properly by caller */
2420  /* */
2421  static void
2422  tt_cmap13_next( TT_CMap13 cmap )
2423  {
2424  FT_Byte* p;
2425  FT_ULong start, end, glyph_id, char_code;
2426  FT_ULong n;
2427  FT_UInt gindex;
2428 
2429 
2430  if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
2431  goto Fail;
2432 
2433  char_code = cmap->cur_charcode + 1;
2434 
2435  n = cmap->cur_group;
2436 
2437  for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
2438  {
2439  p = cmap->cmap.data + 16 + 12 * n;
2440  start = TT_NEXT_ULONG( p );
2441  end = TT_NEXT_ULONG( p );
2442  glyph_id = TT_PEEK_ULONG( p );
2443 
2444  if ( char_code < start )
2445  char_code = start;
2446 
2447  if ( char_code <= end )
2448  {
2449  gindex = (FT_UInt)glyph_id;
2450 
2451  if ( gindex )
2452  {
2453  cmap->cur_charcode = char_code;;
2454  cmap->cur_gindex = gindex;
2455  cmap->cur_group = n;
2456 
2457  return;
2458  }
2459  }
2460  }
2461 
2462  Fail:
2463  cmap->valid = 0;
2464  }
2465 
2466 
2467  static FT_UInt
2468  tt_cmap13_char_map_binary( TT_CMap cmap,
2469  FT_UInt32* pchar_code,
2470  FT_Bool next )
2471  {
2472  FT_UInt gindex = 0;
2473  FT_Byte* p = cmap->data + 12;
2474  FT_UInt32 num_groups = TT_PEEK_ULONG( p );
2475  FT_UInt32 char_code = *pchar_code;
2476  FT_UInt32 start, end;
2477  FT_UInt32 max, min, mid;
2478 
2479 
2480  if ( !num_groups )
2481  return 0;
2482 
2483  /* make compiler happy */
2484  mid = num_groups;
2485  end = 0xFFFFFFFFUL;
2486 
2487  if ( next )
2488  char_code++;
2489 
2490  min = 0;
2491  max = num_groups;
2492 
2493  /* binary search */
2494  while ( min < max )
2495  {
2496  mid = ( min + max ) >> 1;
2497  p = cmap->data + 16 + 12 * mid;
2498 
2499  start = TT_NEXT_ULONG( p );
2500  end = TT_NEXT_ULONG( p );
2501 
2502  if ( char_code < start )
2503  max = mid;
2504  else if ( char_code > end )
2505  min = mid + 1;
2506  else
2507  {
2508  gindex = (FT_UInt)TT_PEEK_ULONG( p );
2509 
2510  break;
2511  }
2512  }
2513 
2514  if ( next )
2515  {
2516  TT_CMap13 cmap13 = (TT_CMap13)cmap;
2517 
2518 
2519  /* if `char_code' is not in any group, then `mid' is */
2520  /* the group nearest to `char_code' */
2521 
2522  if ( char_code > end )
2523  {
2524  mid++;
2525  if ( mid == num_groups )
2526  return 0;
2527  }
2528 
2529  cmap13->valid = 1;
2530  cmap13->cur_charcode = char_code;
2531  cmap13->cur_group = mid;
2532 
2533  if ( !gindex )
2534  {
2535  tt_cmap13_next( cmap13 );
2536 
2537  if ( cmap13->valid )
2538  gindex = cmap13->cur_gindex;
2539  }
2540  else
2541  cmap13->cur_gindex = gindex;
2542 
2543  if ( gindex )
2544  *pchar_code = cmap13->cur_charcode;
2545  }
2546 
2547  return gindex;
2548  }
2549 
2550 
2552  tt_cmap13_char_index( TT_CMap cmap,
2553  FT_UInt32 char_code )
2554  {
2555  return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
2556  }
2557 
2558 
2560  tt_cmap13_char_next( TT_CMap cmap,
2561  FT_UInt32 *pchar_code )
2562  {
2563  TT_CMap13 cmap13 = (TT_CMap13)cmap;
2564  FT_UInt gindex;
2565 
2566 
2567  if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
2568  return 0;
2569 
2570  /* no need to search */
2571  if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
2572  {
2573  tt_cmap13_next( cmap13 );
2574  if ( cmap13->valid )
2575  {
2576  gindex = cmap13->cur_gindex;
2577  if ( gindex )
2578  *pchar_code = cmap13->cur_charcode;
2579  }
2580  else
2581  gindex = 0;
2582  }
2583  else
2584  gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
2585 
2586  return gindex;
2587  }
2588 
2589 
2591  tt_cmap13_get_info( TT_CMap cmap,
2592  TT_CMapInfo *cmap_info )
2593  {
2594  FT_Byte* p = cmap->data + 8;
2595 
2596 
2597  cmap_info->format = 13;
2598  cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
2599 
2600  return FT_Err_Ok;
2601  }
2602 
2603 
2605  tt_cmap13_class_rec,
2606  sizeof ( TT_CMap13Rec ),
2607 
2608  (FT_CMap_InitFunc) tt_cmap13_init,
2610  (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
2611  (FT_CMap_CharNextFunc) tt_cmap13_char_next,
2612 
2613  NULL,
2614  NULL,
2615  NULL,
2616  NULL,
2617  NULL,
2618 
2619  13,
2620  (TT_CMap_ValidateFunc)tt_cmap13_validate,
2621  (TT_CMap_Info_GetFunc)tt_cmap13_get_info )
2622 
2623 #endif /* TT_CONFIG_CMAP_FORMAT_13 */
2624 
2625 
2626  /*************************************************************************/
2627  /*************************************************************************/
2628  /***** *****/
2629  /***** FORMAT 14 *****/
2630  /***** *****/
2631  /*************************************************************************/
2632  /*************************************************************************/
2633 
2634  /*************************************************************************/
2635  /* */
2636  /* TABLE OVERVIEW */
2637  /* -------------- */
2638  /* */
2639  /* NAME OFFSET TYPE DESCRIPTION */
2640  /* */
2641  /* format 0 USHORT must be 14 */
2642  /* length 2 ULONG table length in bytes */
2643  /* numSelector 6 ULONG number of variation sel. records */
2644  /* */
2645  /* Followed by numSelector records, each of which looks like */
2646  /* */
2647  /* varSelector 0 UINT24 Unicode codepoint of sel. */
2648  /* defaultOff 3 ULONG offset to a default UVS table */
2649  /* describing any variants to be found in */
2650  /* the normal Unicode subtable. */
2651  /* nonDefOff 7 ULONG offset to a non-default UVS table */
2652  /* describing any variants not in the */
2653  /* standard cmap, with GIDs here */
2654  /* (either offset may be 0 NULL) */
2655  /* */
2656  /* Selectors are sorted by code point. */
2657  /* */
2658  /* A default Unicode Variation Selector (UVS) subtable is just a list of */
2659  /* ranges of code points which are to be found in the standard cmap. No */
2660  /* glyph IDs (GIDs) here. */
2661  /* */
2662  /* numRanges 0 ULONG number of ranges following */
2663  /* */
2664  /* A range looks like */
2665  /* */
2666  /* uniStart 0 UINT24 code point of the first character in */
2667  /* this range */
2668  /* additionalCnt 3 UBYTE count of additional characters in this */
2669  /* range (zero means a range of a single */
2670  /* character) */
2671  /* */
2672  /* Ranges are sorted by `uniStart'. */
2673  /* */
2674  /* A non-default Unicode Variation Selector (UVS) subtable is a list of */
2675  /* mappings from codepoint to GID. */
2676  /* */
2677  /* numMappings 0 ULONG number of mappings */
2678  /* */
2679  /* A range looks like */
2680  /* */
2681  /* uniStart 0 UINT24 code point of the first character in */
2682  /* this range */
2683  /* GID 3 USHORT and its GID */
2684  /* */
2685  /* Ranges are sorted by `uniStart'. */
2686 
2687 #ifdef TT_CONFIG_CMAP_FORMAT_14
2688 
2689  typedef struct TT_CMap14Rec_
2690  {
2691  TT_CMapRec cmap;
2692  FT_ULong num_selectors;
2693 
2694  /* This array is used to store the results of various
2695  * cmap 14 query functions. The data is overwritten
2696  * on each call to these functions.
2697  */
2698  FT_UInt32 max_results;
2699  FT_UInt32* results;
2700  FT_Memory memory;
2701 
2702  } TT_CMap14Rec, *TT_CMap14;
2703 
2704 
2705  FT_CALLBACK_DEF( void )
2706  tt_cmap14_done( TT_CMap14 cmap )
2707  {
2708  FT_Memory memory = cmap->memory;
2709 
2710 
2711  cmap->max_results = 0;
2712  if ( memory != NULL && cmap->results != NULL )
2713  FT_FREE( cmap->results );
2714  }
2715 
2716 
2717  static FT_Error
2718  tt_cmap14_ensure( TT_CMap14 cmap,
2719  FT_UInt32 num_results,
2720  FT_Memory memory )
2721  {
2722  FT_UInt32 old_max = cmap->max_results;
2724 
2725 
2726  if ( num_results > cmap->max_results )
2727  {
2728  cmap->memory = memory;
2729 
2730  if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
2731  return error;
2732 
2733  cmap->max_results = num_results;
2734  }
2735 
2736  return error;
2737  }
2738 
2739 
2741  tt_cmap14_init( TT_CMap14 cmap,
2742  FT_Byte* table )
2743  {
2744  cmap->cmap.data = table;
2745 
2746  table += 6;
2747  cmap->num_selectors = FT_PEEK_ULONG( table );
2748  cmap->max_results = 0;
2749  cmap->results = NULL;
2750 
2751  return FT_Err_Ok;
2752  }
2753 
2754 
2756  tt_cmap14_validate( FT_Byte* table,
2757  FT_Validator valid )
2758  {
2759  FT_Byte* p = table + 2;
2760  FT_ULong length = TT_NEXT_ULONG( p );
2761  FT_ULong num_selectors = TT_NEXT_ULONG( p );
2762 
2763 
2764  if ( length > (FT_ULong)( valid->limit - table ) ||
2765  length < 10 + 11 * num_selectors )
2767 
2768  /* check selectors, they must be in increasing order */
2769  {
2770  /* we start lastVarSel at 1 because a variant selector value of 0
2771  * isn't valid.
2772  */
2773  FT_ULong n, lastVarSel = 1;
2774 
2775 
2776  for ( n = 0; n < num_selectors; n++ )
2777  {
2778  FT_ULong varSel = TT_NEXT_UINT24( p );
2779  FT_ULong defOff = TT_NEXT_ULONG( p );
2780  FT_ULong nondefOff = TT_NEXT_ULONG( p );
2781 
2782 
2783  if ( defOff >= length || nondefOff >= length )
2785 
2786  if ( varSel < lastVarSel )
2788 
2789  lastVarSel = varSel + 1;
2790 
2791  /* check the default table (these glyphs should be reached */
2792  /* through the normal Unicode cmap, no GIDs, just check order) */
2793  if ( defOff != 0 )
2794  {
2795  FT_Byte* defp = table + defOff;
2796  FT_ULong numRanges = TT_NEXT_ULONG( defp );
2797  FT_ULong i;
2798  FT_ULong lastBase = 0;
2799 
2800 
2801  if ( defp + numRanges * 4 > valid->limit )
2803 
2804  for ( i = 0; i < numRanges; ++i )
2805  {
2806  FT_ULong base = TT_NEXT_UINT24( defp );
2807  FT_ULong cnt = FT_NEXT_BYTE( defp );
2808 
2809 
2810  if ( base + cnt >= 0x110000UL ) /* end of Unicode */
2812 
2813  if ( base < lastBase )
2815 
2816  lastBase = base + cnt + 1U;
2817  }
2818  }
2819 
2820  /* and the non-default table (these glyphs are specified here) */
2821  if ( nondefOff != 0 )
2822  {
2823  FT_Byte* ndp = table + nondefOff;
2824  FT_ULong numMappings = TT_NEXT_ULONG( ndp );
2825  FT_ULong i, lastUni = 0;
2826 
2827 
2828  if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )
2830 
2831  for ( i = 0; i < numMappings; ++i )
2832  {
2833  FT_ULong uni = TT_NEXT_UINT24( ndp );
2834  FT_ULong gid = TT_NEXT_USHORT( ndp );
2835 
2836 
2837  if ( uni >= 0x110000UL ) /* end of Unicode */
2839 
2840  if ( uni < lastUni )
2842 
2843  lastUni = uni + 1U;
2844 
2845  if ( valid->level >= FT_VALIDATE_TIGHT &&
2846  gid >= TT_VALID_GLYPH_COUNT( valid ) )
2848  }
2849  }
2850  }
2851  }
2852 
2853  return FT_Err_Ok;
2854  }
2855 
2856 
2858  tt_cmap14_char_index( TT_CMap cmap,
2859  FT_UInt32 char_code )
2860  {
2861  FT_UNUSED( cmap );
2862  FT_UNUSED( char_code );
2863 
2864  /* This can't happen */
2865  return 0;
2866  }
2867 
2868 
2870  tt_cmap14_char_next( TT_CMap cmap,
2871  FT_UInt32 *pchar_code )
2872  {
2873  FT_UNUSED( cmap );
2874 
2875  /* This can't happen */
2876  *pchar_code = 0;
2877  return 0;
2878  }
2879 
2880 
2882  tt_cmap14_get_info( TT_CMap cmap,
2883  TT_CMapInfo *cmap_info )
2884  {
2885  FT_UNUSED( cmap );
2886 
2887  cmap_info->format = 14;
2888  /* subtable 14 does not define a language field */
2889  cmap_info->language = 0xFFFFFFFFUL;
2890 
2891  return FT_Err_Ok;
2892  }
2893 
2894 
2895  static FT_UInt
2896  tt_cmap14_char_map_def_binary( FT_Byte *base,
2897  FT_UInt32 char_code )
2898  {
2899  FT_UInt32 numRanges = TT_PEEK_ULONG( base );
2900  FT_UInt32 max, min;
2901 
2902 
2903  min = 0;
2904  max = numRanges;
2905 
2906  base += 4;
2907 
2908  /* binary search */
2909  while ( min < max )
2910  {
2911  FT_UInt32 mid = ( min + max ) >> 1;
2912  FT_Byte* p = base + 4 * mid;
2913  FT_ULong start = TT_NEXT_UINT24( p );
2914  FT_UInt cnt = FT_NEXT_BYTE( p );
2915 
2916 
2917  if ( char_code < start )
2918  max = mid;
2919  else if ( char_code > start+cnt )
2920  min = mid + 1;
2921  else
2922  return TRUE;
2923  }
2924 
2925  return FALSE;
2926  }
2927 
2928 
2929  static FT_UInt
2930  tt_cmap14_char_map_nondef_binary( FT_Byte *base,
2931  FT_UInt32 char_code )
2932  {
2933  FT_UInt32 numMappings = TT_PEEK_ULONG( base );
2934  FT_UInt32 max, min;
2935 
2936 
2937  min = 0;
2938  max = numMappings;
2939 
2940  base += 4;
2941 
2942  /* binary search */
2943  while ( min < max )
2944  {
2945  FT_UInt32 mid = ( min + max ) >> 1;
2946  FT_Byte* p = base + 5 * mid;
2947  FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );
2948 
2949 
2950  if ( char_code < uni )
2951  max = mid;
2952  else if ( char_code > uni )
2953  min = mid + 1;
2954  else
2955  return TT_PEEK_USHORT( p );
2956  }
2957 
2958  return 0;
2959  }
2960 
2961 
2962  static FT_Byte*
2963  tt_cmap14_find_variant( FT_Byte *base,
2964  FT_UInt32 variantCode )
2965  {
2966  FT_UInt32 numVar = TT_PEEK_ULONG( base );
2967  FT_UInt32 max, min;
2968 
2969 
2970  min = 0;
2971  max = numVar;
2972 
2973  base += 4;
2974 
2975  /* binary search */
2976  while ( min < max )
2977  {
2978  FT_UInt32 mid = ( min + max ) >> 1;
2979  FT_Byte* p = base + 11 * mid;
2980  FT_ULong varSel = TT_NEXT_UINT24( p );
2981 
2982 
2983  if ( variantCode < varSel )
2984  max = mid;
2985  else if ( variantCode > varSel )
2986  min = mid + 1;
2987  else
2988  return p;
2989  }
2990 
2991  return NULL;
2992  }
2993 
2994 
2996  tt_cmap14_char_var_index( TT_CMap cmap,
2997  TT_CMap ucmap,
2998  FT_UInt32 charcode,
2999  FT_UInt32 variantSelector )
3000  {
3001  FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3002  FT_ULong defOff;
3003  FT_ULong nondefOff;
3004 
3005 
3006  if ( !p )
3007  return 0;
3008 
3009  defOff = TT_NEXT_ULONG( p );
3010  nondefOff = TT_PEEK_ULONG( p );
3011 
3012  if ( defOff != 0 &&
3013  tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3014  {
3015  /* This is the default variant of this charcode. GID not stored */
3016  /* here; stored in the normal Unicode charmap instead. */
3017  return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
3018  }
3019 
3020  if ( nondefOff != 0 )
3021  return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3022  charcode );
3023 
3024  return 0;
3025  }
3026 
3027 
3029  tt_cmap14_char_var_isdefault( TT_CMap cmap,
3030  FT_UInt32 charcode,
3031  FT_UInt32 variantSelector )
3032  {
3033  FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
3034  FT_ULong defOff;
3035  FT_ULong nondefOff;
3036 
3037 
3038  if ( !p )
3039  return -1;
3040 
3041  defOff = TT_NEXT_ULONG( p );
3042  nondefOff = TT_NEXT_ULONG( p );
3043 
3044  if ( defOff != 0 &&
3045  tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
3046  return 1;
3047 
3048  if ( nondefOff != 0 &&
3049  tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3050  charcode ) != 0 )
3051  return 0;
3052 
3053  return -1;
3054  }
3055 
3056 
3058  tt_cmap14_variants( TT_CMap cmap,
3059  FT_Memory memory )
3060  {
3061  TT_CMap14 cmap14 = (TT_CMap14)cmap;
3062  FT_UInt32 count = cmap14->num_selectors;
3063  FT_Byte* p = cmap->data + 10;
3064  FT_UInt32* result;
3065  FT_UInt32 i;
3066 
3067 
3068  if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3069  return NULL;
3070 
3071  result = cmap14->results;
3072  for ( i = 0; i < count; ++i )
3073  {
3074  result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3075  p += 8;
3076  }
3077  result[i] = 0;
3078 
3079  return result;
3080  }
3081 
3082 
3084  tt_cmap14_char_variants( TT_CMap cmap,
3085  FT_Memory memory,
3086  FT_UInt32 charCode )
3087  {
3088  TT_CMap14 cmap14 = (TT_CMap14) cmap;
3089  FT_UInt32 count = cmap14->num_selectors;
3090  FT_Byte* p = cmap->data + 10;
3091  FT_UInt32* q;
3092 
3093 
3094  if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
3095  return NULL;
3096 
3097  for ( q = cmap14->results; count > 0; --count )
3098  {
3099  FT_UInt32 varSel = TT_NEXT_UINT24( p );
3100  FT_ULong defOff = TT_NEXT_ULONG( p );
3101  FT_ULong nondefOff = TT_NEXT_ULONG( p );
3102 
3103 
3104  if ( ( defOff != 0 &&
3105  tt_cmap14_char_map_def_binary( cmap->data + defOff,
3106  charCode ) ) ||
3107  ( nondefOff != 0 &&
3108  tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
3109  charCode ) != 0 ) )
3110  {
3111  q[0] = varSel;
3112  q++;
3113  }
3114  }
3115  q[0] = 0;
3116 
3117  return cmap14->results;
3118  }
3119 
3120 
3121  static FT_UInt
3122  tt_cmap14_def_char_count( FT_Byte *p )
3123  {
3124  FT_UInt32 numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3125  FT_UInt tot = 0;
3126 
3127 
3128  p += 3; /* point to the first `cnt' field */
3129  for ( ; numRanges > 0; numRanges-- )
3130  {
3131  tot += 1 + p[0];
3132  p += 4;
3133  }
3134 
3135  return tot;
3136  }
3137 
3138 
3139  static FT_UInt32*
3140  tt_cmap14_get_def_chars( TT_CMap cmap,
3141  FT_Byte* p,
3142  FT_Memory memory )
3143  {
3144  TT_CMap14 cmap14 = (TT_CMap14) cmap;
3145  FT_UInt32 numRanges;
3146  FT_UInt cnt;
3147  FT_UInt32* q;
3148 
3149 
3150  cnt = tt_cmap14_def_char_count( p );
3151  numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
3152 
3153  if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
3154  return NULL;
3155 
3156  for ( q = cmap14->results; numRanges > 0; --numRanges )
3157  {
3158  FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );
3159 
3160 
3161  cnt = FT_NEXT_BYTE( p ) + 1;
3162  do
3163  {
3164  q[0] = uni;
3165  uni += 1;
3166  q += 1;
3167 
3168  } while ( --cnt != 0 );
3169  }
3170  q[0] = 0;
3171 
3172  return cmap14->results;
3173  }
3174 
3175 
3176  static FT_UInt32*
3177  tt_cmap14_get_nondef_chars( TT_CMap cmap,
3178  FT_Byte *p,
3179  FT_Memory memory )
3180  {
3181  TT_CMap14 cmap14 = (TT_CMap14) cmap;
3182  FT_UInt32 numMappings;
3183  FT_UInt i;
3184  FT_UInt32 *ret;
3185 
3186 
3187  numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3188 
3189  if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
3190  return NULL;
3191 
3192  ret = cmap14->results;
3193  for ( i = 0; i < numMappings; ++i )
3194  {
3195  ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
3196  p += 2;
3197  }
3198  ret[i] = 0;
3199 
3200  return ret;
3201  }
3202 
3203 
3205  tt_cmap14_variant_chars( TT_CMap cmap,
3206  FT_Memory memory,
3207  FT_UInt32 variantSelector )
3208  {
3209  FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6,
3210  variantSelector );
3211  FT_UInt32 *ret;
3212  FT_Int i;
3213  FT_ULong defOff;
3214  FT_ULong nondefOff;
3215 
3216 
3217  if ( !p )
3218  return NULL;
3219 
3220  defOff = TT_NEXT_ULONG( p );
3221  nondefOff = TT_NEXT_ULONG( p );
3222 
3223  if ( defOff == 0 && nondefOff == 0 )
3224  return NULL;
3225 
3226  if ( defOff == 0 )
3227  return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3228  memory );
3229  else if ( nondefOff == 0 )
3230  return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3231  memory );
3232  else
3233  {
3234  /* Both a default and a non-default glyph set? That's probably not */
3235  /* good font design, but the spec allows for it... */
3236  TT_CMap14 cmap14 = (TT_CMap14) cmap;
3237  FT_UInt32 numRanges;
3238  FT_UInt32 numMappings;
3239  FT_UInt32 duni;
3240  FT_UInt32 dcnt;
3241  FT_UInt32 nuni;
3242  FT_Byte* dp;
3243  FT_UInt di, ni, k;
3244 
3245 
3246  p = cmap->data + nondefOff;
3247  dp = cmap->data + defOff;
3248 
3249  numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
3250  dcnt = tt_cmap14_def_char_count( dp );
3251  numRanges = (FT_UInt32)TT_NEXT_ULONG( dp );
3252 
3253  if ( numMappings == 0 )
3254  return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
3255  memory );
3256  if ( dcnt == 0 )
3257  return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
3258  memory );
3259 
3260  if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
3261  return NULL;
3262 
3263  ret = cmap14->results;
3264  duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3265  dcnt = FT_NEXT_BYTE( dp );
3266  di = 1;
3267  nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3268  p += 2;
3269  ni = 1;
3270  i = 0;
3271 
3272  for ( ;; )
3273  {
3274  if ( nuni > duni + dcnt )
3275  {
3276  for ( k = 0; k <= dcnt; ++k )
3277  ret[i++] = duni + k;
3278 
3279  ++di;
3280 
3281  if ( di > numRanges )
3282  break;
3283 
3284  duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3285  dcnt = FT_NEXT_BYTE( dp );
3286  }
3287  else
3288  {
3289  if ( nuni < duni )
3290  ret[i++] = nuni;
3291  /* If it is within the default range then ignore it -- */
3292  /* that should not have happened */
3293  ++ni;
3294  if ( ni > numMappings )
3295  break;
3296 
3297  nuni = (FT_UInt32)TT_NEXT_UINT24( p );
3298  p += 2;
3299  }
3300  }
3301 
3302  if ( ni <= numMappings )
3303  {
3304  /* If we get here then we have run out of all default ranges. */
3305  /* We have read one non-default mapping which we haven't stored */
3306  /* and there may be others that need to be read. */
3307  ret[i++] = nuni;
3308  while ( ni < numMappings )
3309  {
3310  ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
3311  p += 2;
3312  ++ni;
3313  }
3314  }
3315  else if ( di <= numRanges )
3316  {
3317  /* If we get here then we have run out of all non-default */
3318  /* mappings. We have read one default range which we haven't */
3319  /* stored and there may be others that need to be read. */
3320  for ( k = 0; k <= dcnt; ++k )
3321  ret[i++] = duni + k;
3322 
3323  while ( di < numRanges )
3324  {
3325  duni = (FT_UInt32)TT_NEXT_UINT24( dp );
3326  dcnt = FT_NEXT_BYTE( dp );
3327 
3328  for ( k = 0; k <= dcnt; ++k )
3329  ret[i++] = duni + k;
3330  ++di;
3331  }
3332  }
3333 
3334  ret[i] = 0;
3335 
3336  return ret;
3337  }
3338  }
3339 
3340 
3342  tt_cmap14_class_rec,
3343  sizeof ( TT_CMap14Rec ),
3344 
3345  (FT_CMap_InitFunc) tt_cmap14_init,
3346  (FT_CMap_DoneFunc) tt_cmap14_done,
3347  (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
3348  (FT_CMap_CharNextFunc) tt_cmap14_char_next,
3349 
3350  /* Format 14 extension functions */
3351  (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index,
3352  (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
3353  (FT_CMap_VariantListFunc) tt_cmap14_variants,
3354  (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
3355  (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
3356 
3357  14,
3358  (TT_CMap_ValidateFunc)tt_cmap14_validate,
3359  (TT_CMap_Info_GetFunc)tt_cmap14_get_info )
3360 
3361 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
3362 
3363 
3364 #ifndef FT_CONFIG_OPTION_PIC
3365 
3366  static const TT_CMap_Class tt_cmap_classes[] =
3367  {
3368 #define TTCMAPCITEM( a ) &a,
3369 #include "ttcmapc.h"
3370  NULL,
3371  };
3372 
3373 #else /*FT_CONFIG_OPTION_PIC*/
3374 
3375  void
3376  FT_Destroy_Class_tt_cmap_classes( FT_Library library,
3377  TT_CMap_Class* clazz )
3378  {
3379  FT_Memory memory = library->memory;
3380 
3381 
3382  if ( clazz )
3383  FT_FREE( clazz );
3384  }
3385 
3386 
3387  FT_Error
3388  FT_Create_Class_tt_cmap_classes( FT_Library library,
3389  TT_CMap_Class** output_class )
3390  {
3391  TT_CMap_Class* clazz = NULL;
3392  TT_CMap_ClassRec* recs;
3393  FT_Error error;
3394  FT_Memory memory = library->memory;
3395 
3396  int i = 0;
3397 
3398 
3399 #define TTCMAPCITEM( a ) i++;
3400 #include "ttcmapc.h"
3401 
3402  /* allocate enough space for both the pointers */
3403  /* plus terminator and the class instances */
3404  if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) +
3405  sizeof ( TT_CMap_ClassRec ) * i ) )
3406  return error;
3407 
3408  /* the location of the class instances follows the array of pointers */
3409  recs = (TT_CMap_ClassRec*)( (char*)clazz +
3410  sizeof ( *clazz ) * ( i + 1 ) );
3411  i = 0;
3412 
3413 #undef TTCMAPCITEM
3414 #define TTCMAPCITEM( a ) \
3415  FT_Init_Class_ ## a( &recs[i] ); \
3416  clazz[i] = &recs[i]; \
3417  i++;
3418 #include "ttcmapc.h"
3419 
3420  clazz[i] = NULL;
3421 
3422  *output_class = clazz;
3423  return FT_Err_Ok;
3424  }
3425 
3426 #endif /*FT_CONFIG_OPTION_PIC*/
3427 
3428 
3429  /* parse the `cmap' table and build the corresponding TT_CMap objects */
3430  /* in the current face */
3431  /* */
3434  {
3435  FT_Byte* table = face->cmap_table;
3436  FT_Byte* limit = table + face->cmap_size;
3437  FT_UInt volatile num_cmaps;
3438  FT_Byte* volatile p = table;
3439  FT_Library library = FT_FACE_LIBRARY( face );
3440 
3441  FT_UNUSED( library );
3442 
3443 
3444  if ( !p || p + 4 > limit )
3445  return FT_THROW( Invalid_Table );
3446 
3447  /* only recognize format 0 */
3448  if ( TT_NEXT_USHORT( p ) != 0 )
3449  {
3450  p -= 2;
3451  FT_ERROR(( "tt_face_build_cmaps:"
3452  " unsupported `cmap' table format = %d\n",
3453  TT_PEEK_USHORT( p ) ));
3454  return FT_THROW( Invalid_Table );
3455  }
3456 
3457  num_cmaps = TT_NEXT_USHORT( p );
3458 
3459 #ifdef FT_MAX_CHARMAP_CACHEABLE
3460  if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE )
3461  FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables (%d)\n"
3462  " subtable #%d and higher are loaded"
3463  " but cannot be searched\n",
3464  num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 ));
3465 #endif
3466 
3467  for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
3468  {
3469  FT_CharMapRec charmap;
3470  FT_UInt32 offset;
3471 
3472 
3473  charmap.platform_id = TT_NEXT_USHORT( p );
3474  charmap.encoding_id = TT_NEXT_USHORT( p );
3475  charmap.face = FT_FACE( face );
3476  charmap.encoding = FT_ENCODING_NONE; /* will be filled later */
3477  offset = TT_NEXT_ULONG( p );
3478 
3479  if ( offset && offset <= face->cmap_size - 2 )
3480  {
3481  FT_Byte* volatile cmap = table + offset;
3482  volatile FT_UInt format = TT_PEEK_USHORT( cmap );
3483  const TT_CMap_Class* volatile pclazz = TT_CMAP_CLASSES_GET;
3484  TT_CMap_Class volatile clazz;
3485 
3486 
3487  for ( ; *pclazz; pclazz++ )
3488  {
3489  clazz = *pclazz;
3490  if ( clazz->format == format )
3491  {
3492  volatile TT_ValidatorRec valid;
3493  volatile FT_Error error = FT_Err_Ok;
3494 
3495 
3496  ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
3498 
3499  valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
3500 
3501  if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 )
3502  {
3503  /* validate this cmap sub-table */
3504  error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
3505  }
3506 
3507  if ( valid.validator.error == 0 )
3508  {
3509  FT_CMap ttcmap;
3510 
3511 
3512  /* It might make sense to store the single variation */
3513  /* selector cmap somewhere special. But it would have to be */
3514  /* in the public FT_FaceRec, and we can't change that. */
3515 
3516  if ( !FT_CMap_New( (FT_CMap_Class)clazz,
3517  cmap, &charmap, &ttcmap ) )
3518  {
3519  /* it is simpler to directly set `flags' than adding */
3520  /* a parameter to FT_CMap_New */
3521  ((TT_CMap)ttcmap)->flags = (FT_Int)error;
3522  }
3523  }
3524  else
3525  {
3526  FT_TRACE0(( "tt_face_build_cmaps:"
3527  " broken cmap sub-table ignored\n" ));
3528  }
3529  break;
3530  }
3531  }
3532 
3533  if ( *pclazz == NULL )
3534  {
3535  FT_TRACE0(( "tt_face_build_cmaps:"
3536  " unsupported cmap sub-table ignored\n" ));
3537  }
3538  }
3539  }
3540 
3541  return FT_Err_Ok;
3542  }
3543 
3544 
3545  FT_LOCAL( FT_Error )
3547  TT_CMapInfo *cmap_info )
3548  {
3549  FT_CMap cmap = (FT_CMap)charmap;
3550  TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz;
3551 
3552 
3553  return clazz->get_cmap_info( charmap, cmap_info );
3554  }
3555 
3556 
3557 /* END */
GLenum GLuint GLenum GLsizei length
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:260
int FT_Error
Definition: fttypes.h:296
#define FT_QRENEW_ARRAY(ptr, curcnt, newcnt)
Definition: ftmemory.h:302
unsigned long FT_ULong
Definition: fttypes.h:249
GLfloat GLfloat p
FT_UInt(* FT_CMap_CharIndexFunc)(FT_CMap cmap, FT_UInt32 char_code)
Definition: ftobjs.h:157
#define NULL
Definition: ftobjs.h:61
FT_Error(* TT_CMap_ValidateFunc)(FT_Byte *data, FT_Validator valid)
Definition: ttcmap.h:46
tt_face_build_cmaps(TT_Face face)
Definition: ttcmap.c:3433
signed int FT_Int
Definition: fttypes.h:216
GLdouble GLdouble GLdouble GLdouble q
FT_UInt32 *(* FT_CMap_VariantCharListFunc)(FT_CMap cmap, FT_Memory mem, FT_UInt32 variant_selector)
Definition: ftobjs.h:185
return FT_THROW(Missing_Property)
tt_cmap_init(TT_CMap cmap, FT_Byte *table)
Definition: ttcmap.c:55
void(* FT_CMap_DoneFunc)(FT_CMap cmap)
Definition: ftobjs.h:154
#define FT_NEXT_BYTE(buffer)
Definition: ftstream.h:220
#define FT_UNUSED(arg)
Definition: ftconfig.h:76
GLuint start
FT_CMapRec cmap
Definition: ttcmap.h:36
FT_UShort platform_id
Definition: freetype.h:744
#define FT_INVALID_TOO_SHORT
Definition: ftvalid.h:125
#define FT_PAD_FLOOR(x, n)
Definition: ftobjs.h:76
unsigned int FT_UInt32
Definition: ftconfig.h:133
TT_CMap_ValidateFunc validate
Definition: ttcmap.h:53
FT_Library library
Definition: cffdrivr.c:414
return FT_Err_Ok
Definition: ftbbox.c:645
tt_get_cmap_info(FT_CharMap charmap, TT_CMapInfo *cmap_info)
Definition: ttcmap.c:3546
png_uint_32 i
Definition: png.h:2640
FT_UShort encoding_id
Definition: freetype.h:745
FT_BEGIN_HEADER typedef unsigned char FT_Bool
Definition: fttypes.h:104
FT_Face face
Definition: freetype.h:742
#define TT_NEXT_SHORT
Definition: ttcmap.c:47
GLenum GLuint GLint GLenum face
#define TT_PEEK_SHORT
Definition: ttcmap.c:41
TT_CMap_Info_GetFunc get_cmap_info
Definition: ttcmap.h:54
TT_CMapInfo * cmap_info
Definition: cffdrivr.c:409
FT_Error error
Definition: ftvalid.h:85
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
const struct TT_CMap_ClassRec_ * TT_CMap_Class
Definition: ttcmap.h:42
unsigned char FT_Byte
Definition: fttypes.h:150
#define FT_ASSERT(condition)
Definition: ftdebug.h:211
#define TT_PEEK_ULONG
Definition: ttcmap.c:45
FT_CMap_CharIndexFunc char_index
Definition: ftobjs.h:195
struct FT_CMapRec_ * FT_CMap
Definition: ftobjs.h:125
GLuint * ids
FT_Memory memory
Definition: ftobjs.h:860
FT_UInt32 *(* FT_CMap_VariantListFunc)(FT_CMap cmap, FT_Memory mem)
Definition: ftobjs.h:176
#define FT_PEEK_ULONG(p)
Definition: ftstream.h:179
#define TT_NEXT_ULONG
Definition: ttcmap.c:51
#define FT_FREE(ptr)
Definition: ftmemory.h:286
#define FT_LOCAL(x)
Definition: ftconfig.h:235
struct TT_FaceRec_ * TT_Face
Definition: tttypes.h:951
FT_UInt idx
Definition: cffcmap.c:127
FT_Error error
Definition: cffdrivr.c:411
FT_ULong cmap_size
Definition: tttypes.h:1286
float min(float a, float b)
Definition: Vector2.hpp:307
GLdouble n
typedefFT_BEGIN_HEADER struct FT_ValidatorRec_ volatile * FT_Validator
Definition: ftvalid.h:42
#define TT_NEXT_USHORT
Definition: ttcmap.c:48
#define ft_setjmp(b)
Definition: ftstdlib.h:162
#define FT_CALLBACK_DEF(x)
Definition: ftconfig.h:323
FT_Encoding encoding
Definition: freetype.h:743
#define FT_VALIDATOR(x)
Definition: ftvalid.h:92
FT_Long format
Definition: svttcmap.h:62
FT_ValidatorRec validator
Definition: ttcmap.h:134
GLintptr offset
#define FT_PEEK_USHORT(p)
Definition: ftstream.h:171
#define FALSE
Definition: ftobjs.h:57
#define FT_DEFINE_TT_CMAP(class_, size_, init_, done_, char_index_, char_next_, char_var_index_, char_var_default_, variant_list_, charvariant_list_, variantchar_list_, format_, validate_, get_cmap_info_)
Definition: ttcmap.h:61
GLuint GLuint end
#define TT_PEEK_USHORT
Definition: ttcmap.c:42
GLboolean GLenum GLenum GLvoid * values
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
local int max
Definition: enough.c:170
#define TT_NEXT_UINT24
Definition: ttcmap.c:49
#define FT_NEXT_USHORT(buffer)
Definition: ftstream.h:226
FT_Error(* TT_CMap_Info_GetFunc)(FT_CharMap charmap, TT_CMapInfo *cmap_info)
Definition: svttcmap.h:68
if(!abbox) return FT_THROW(Invalid_Argument)
struct TT_CMapRec_ * TT_CMap
#define FT_INVALID_OFFSET
Definition: ftvalid.h:129
FT_CMap_New(FT_CMap_Class clazz, FT_Pointer init_data, FT_CharMap charmap, FT_CMap *acmap)
Definition: ftobjs.c:3248
FT_Int flags
Definition: ttcmap.h:38
FT_UInt num_glyphs
Definition: ttcmap.h:135
FT_Byte * cmap_table
Definition: tttypes.h:1285
#define FT_FACE(x)
Definition: ftobjs.h:557
GLuint64EXT * result
unsigned int FT_UInt
Definition: fttypes.h:227
FT_ULong language
Definition: svttcmap.h:61
#define TT_VALID_GLYPH_COUNT(x)
Definition: ttcmap.h:141
#define TT_CMAP_FLAG_UNSORTED
Definition: ttcmap.h:31
ft_validator_init(FT_Validator valid, const FT_Byte *base, const FT_Byte *limit, FT_ValidationLevel level)
Definition: ftobjs.c:82
#define TT_CMAP_FLAG_OVERLAPPING
Definition: ttcmap.h:32
FT_UInt(* FT_CMap_CharNextFunc)(FT_CMap cmap, FT_UInt32 *achar_code)
Definition: ftobjs.h:161
GLuint GLuint GLsizei count
#define FT_INVALID_DATA
Definition: ftvalid.h:141
#define TT_CMAP_CLASSES_GET
Definition: sfntpic.h:35
#define FT_INVALID_GLYPH_ID
Definition: ftvalid.h:137
FT_TRACE0(("cff_property_set: missing property `%s'\, property_name))
FT_Byte * data
Definition: ttcmap.h:37
FT_CharMapRec charmap
Definition: ftobjs.h:133
FT_CMap_Class clazz
Definition: ftobjs.h:134
#define FT_FACE_LIBRARY(x)
Definition: ftobjs.h:562
GLenum GLsizei GLenum GLenum const GLvoid * table
FT_Error(* FT_CMap_InitFunc)(FT_CMap cmap, FT_Pointer init_data)
Definition: ftobjs.h:150
FT_UInt32 *(* FT_CMap_CharVariantListFunc)(FT_CMap cmap, FT_Memory mem, FT_UInt32 char_code)
Definition: ftobjs.h:180
#define TRUE
Definition: ftobjs.h:53
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
FT_UInt(* FT_CMap_CharVarIndexFunc)(FT_CMap cmap, FT_CMap unicode_cmap, FT_UInt32 char_code, FT_UInt32 variant_selector)
Definition: ftobjs.h:165
GLint limit
FT_UInt format
Definition: ttcmap.h:52
FT_Bool(* FT_CMap_CharVarIsDefaultFunc)(FT_CMap cmap, FT_UInt32 char_code, FT_UInt32 variant_selector)
Definition: ftobjs.h:171
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:236
#define FT_PEEK_SHORT(p)
Definition: ftstream.h:168