• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * sfdriver.c
4  *
5  *   High-level SFNT driver interface (body).
6  *
7  * Copyright (C) 1996-2023 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 <freetype/internal/ftdebug.h>
20 #include <freetype/internal/sfnt.h>
21 #include <freetype/internal/ftobjs.h>
22 #include <freetype/ttnameid.h>
23 
24 #include "sfdriver.h"
25 #include "ttload.h"
26 #include "sfobjs.h"
27 
28 #include "sferrors.h"
29 
30 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
31 #include "ttsbit.h"
32 #endif
33 
34 #ifdef TT_CONFIG_OPTION_COLOR_LAYERS
35 #include "ttcolr.h"
36 #include "ttcpal.h"
37 #endif
38 
39 #ifdef FT_CONFIG_OPTION_SVG
40 #include "ttsvg.h"
41 #endif
42 
43 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
44 #include "ttpost.h"
45 #endif
46 
47 #ifdef TT_CONFIG_OPTION_BDF
48 #include "ttbdf.h"
49 #include <freetype/internal/services/svbdf.h>
50 #endif
51 
52 #include "ttcmap.h"
53 #include "ttkern.h"
54 #include "ttmtx.h"
55 
56 #include <freetype/internal/services/svgldict.h>
57 #include <freetype/internal/services/svpostnm.h>
58 #include <freetype/internal/services/svsfnt.h>
59 #include <freetype/internal/services/svttcmap.h>
60 
61 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
62 #include <freetype/ftmm.h>
63 #include <freetype/internal/services/svmm.h>
64 #endif
65 
66 
67   /**************************************************************************
68    *
69    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
70    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
71    * messages during execution.
72    */
73 #undef  FT_COMPONENT
74 #define FT_COMPONENT  sfdriver
75 
76 
77   /*
78    * SFNT TABLE SERVICE
79    *
80    */
81 
82   static void*
get_sfnt_table(TT_Face face,FT_Sfnt_Tag tag)83   get_sfnt_table( TT_Face      face,
84                   FT_Sfnt_Tag  tag )
85   {
86     void*  table;
87 
88 
89     switch ( tag )
90     {
91     case FT_SFNT_HEAD:
92       table = &face->header;
93       break;
94 
95     case FT_SFNT_HHEA:
96       table = &face->horizontal;
97       break;
98 
99     case FT_SFNT_VHEA:
100       table = face->vertical_info ? &face->vertical : NULL;
101       break;
102 
103     case FT_SFNT_OS2:
104       table = ( face->os2.version == 0xFFFFU ) ? NULL : &face->os2;
105       break;
106 
107     case FT_SFNT_POST:
108       table = &face->postscript;
109       break;
110 
111     case FT_SFNT_MAXP:
112       table = &face->max_profile;
113       break;
114 
115     case FT_SFNT_PCLT:
116       table = face->pclt.Version ? &face->pclt : NULL;
117       break;
118 
119     default:
120       table = NULL;
121     }
122 
123     return table;
124   }
125 
126 
127   static FT_Error
sfnt_table_info(TT_Face face,FT_UInt idx,FT_ULong * tag,FT_ULong * offset,FT_ULong * length)128   sfnt_table_info( TT_Face    face,
129                    FT_UInt    idx,
130                    FT_ULong  *tag,
131                    FT_ULong  *offset,
132                    FT_ULong  *length )
133   {
134     if ( !offset || !length )
135       return FT_THROW( Invalid_Argument );
136 
137     if ( !tag )
138       *length = face->num_tables;
139     else
140     {
141       if ( idx >= face->num_tables )
142         return FT_THROW( Table_Missing );
143 
144       *tag    = face->dir_tables[idx].Tag;
145       *offset = face->dir_tables[idx].Offset;
146       *length = face->dir_tables[idx].Length;
147     }
148 
149     return FT_Err_Ok;
150   }
151 
152 
153   FT_DEFINE_SERVICE_SFNT_TABLEREC(
154     sfnt_service_sfnt_table,
155 
156     (FT_SFNT_TableLoadFunc)tt_face_load_any,     /* load_table */
157     (FT_SFNT_TableGetFunc) get_sfnt_table,       /* get_table  */
158     (FT_SFNT_TableInfoFunc)sfnt_table_info       /* table_info */
159   )
160 
161 
162 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
163 
164   /*
165    * GLYPH DICT SERVICE
166    *
167    */
168 
169   static FT_Error
sfnt_get_glyph_name(FT_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)170   sfnt_get_glyph_name( FT_Face     face,
171                        FT_UInt     glyph_index,
172                        FT_Pointer  buffer,
173                        FT_UInt     buffer_max )
174   {
175     FT_String*  gname;
176     FT_Error    error;
177 
178 
179     error = tt_face_get_ps_name( (TT_Face)face, glyph_index, &gname );
180     if ( !error )
181       FT_STRCPYN( buffer, gname, buffer_max );
182 
183     return error;
184   }
185 
186 
187   static FT_UInt
sfnt_get_name_index(FT_Face face,const FT_String * glyph_name)188   sfnt_get_name_index( FT_Face           face,
189                        const FT_String*  glyph_name )
190   {
191     TT_Face  ttface = (TT_Face)face;
192 
193     FT_UInt  i, max_gid = FT_UINT_MAX;
194 
195 
196     if ( face->num_glyphs < 0 )
197       return 0;
198     else if ( (FT_ULong)face->num_glyphs < FT_UINT_MAX )
199       max_gid = (FT_UInt)face->num_glyphs;
200     else
201       FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08lx\n",
202                   FT_UINT_MAX, face->num_glyphs ));
203 
204     for ( i = 0; i < max_gid; i++ )
205     {
206       FT_String*  gname;
207       FT_Error    error = tt_face_get_ps_name( ttface, i, &gname );
208 
209 
210       if ( error )
211         continue;
212 
213       if ( !ft_strcmp( glyph_name, gname ) )
214         return i;
215     }
216 
217     return 0;
218   }
219 
220 
221   FT_DEFINE_SERVICE_GLYPHDICTREC(
222     sfnt_service_glyph_dict,
223 
224     (FT_GlyphDict_GetNameFunc)  sfnt_get_glyph_name,    /* get_name   */
225     (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index     /* name_index */
226   )
227 
228 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
229 
230 
231   /*
232    * POSTSCRIPT NAME SERVICE
233    *
234    */
235 
236   /* an array representing allowed ASCII characters in a PS string */
237   static const unsigned char sfnt_ps_map[16] =
238   {
239                 /*             4        0        C        8 */
240     0x00, 0x00, /* 0x00: 0 0 0 0  0 0 0 0  0 0 0 0  0 0 0 0 */
241     0x00, 0x00, /* 0x10: 0 0 0 0  0 0 0 0  0 0 0 0  0 0 0 0 */
242     0xDE, 0x7C, /* 0x20: 1 1 0 1  1 1 1 0  0 1 1 1  1 1 0 0 */
243     0xFF, 0xAF, /* 0x30: 1 1 1 1  1 1 1 1  1 0 1 0  1 1 1 1 */
244     0xFF, 0xFF, /* 0x40: 1 1 1 1  1 1 1 1  1 1 1 1  1 1 1 1 */
245     0xFF, 0xD7, /* 0x50: 1 1 1 1  1 1 1 1  1 1 0 1  0 1 1 1 */
246     0xFF, 0xFF, /* 0x60: 1 1 1 1  1 1 1 1  1 1 1 1  1 1 1 1 */
247     0xFF, 0x57  /* 0x70: 1 1 1 1  1 1 1 1  0 1 0 1  0 1 1 1 */
248   };
249 
250 
251   static int
sfnt_is_postscript(int c)252   sfnt_is_postscript( int  c )
253   {
254     unsigned int  cc;
255 
256 
257     if ( c < 0 || c >= 0x80 )
258       return 0;
259 
260     cc = (unsigned int)c;
261 
262     return sfnt_ps_map[cc >> 3] & ( 1 << ( cc & 0x07 ) );
263   }
264 
265 
266 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
267 
268   /* Only ASCII letters and digits are taken for a variation font */
269   /* instance's PostScript name.                                  */
270   /*                                                              */
271   /* `ft_isalnum' is a macro, but we need a function here, thus   */
272   /* this definition.                                             */
273   static int
sfnt_is_alphanumeric(int c)274   sfnt_is_alphanumeric( int  c )
275   {
276     return ft_isalnum( c );
277   }
278 
279 
280   /* the implementation of MurmurHash3 is taken and adapted from          */
281   /* https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp */
282 
283 #define ROTL32( x, r )  ( x << r ) | ( x >> ( 32 - r ) )
284 
285 
286   static FT_UInt32
fmix32(FT_UInt32 h)287   fmix32( FT_UInt32  h )
288   {
289     h ^= h >> 16;
290     h *= 0x85ebca6b;
291     h ^= h >> 13;
292     h *= 0xc2b2ae35;
293     h ^= h >> 16;
294 
295     return h;
296   }
297 
298 
299   static void
murmur_hash_3_128(const void * key,const unsigned int len,FT_UInt32 seed,void * out)300   murmur_hash_3_128( const void*         key,
301                      const unsigned int  len,
302                      FT_UInt32           seed,
303                      void*               out )
304   {
305     const FT_Byte*  data    = (const FT_Byte*)key;
306     const int       nblocks = (int)len / 16;
307 
308     FT_UInt32  h1 = seed;
309     FT_UInt32  h2 = seed;
310     FT_UInt32  h3 = seed;
311     FT_UInt32  h4 = seed;
312 
313     const FT_UInt32  c1 = 0x239b961b;
314     const FT_UInt32  c2 = 0xab0e9789;
315     const FT_UInt32  c3 = 0x38b34ae5;
316     const FT_UInt32  c4 = 0xa1e38b93;
317 
318     const FT_UInt32*  blocks = (const FT_UInt32*)( data + nblocks * 16 );
319 
320     int  i;
321 
322 
323     for( i = -nblocks; i; i++ )
324     {
325       FT_UInt32  k1 = blocks[i * 4 + 0];
326       FT_UInt32  k2 = blocks[i * 4 + 1];
327       FT_UInt32  k3 = blocks[i * 4 + 2];
328       FT_UInt32  k4 = blocks[i * 4 + 3];
329 
330 
331       k1 *= c1;
332       k1  = ROTL32( k1, 15 );
333       k1 *= c2;
334       h1 ^= k1;
335 
336       h1  = ROTL32( h1, 19 );
337       h1 += h2;
338       h1  = h1 * 5 + 0x561ccd1b;
339 
340       k2 *= c2;
341       k2  = ROTL32( k2, 16 );
342       k2 *= c3;
343       h2 ^= k2;
344 
345       h2  = ROTL32( h2, 17 );
346       h2 += h3;
347       h2  = h2 * 5 + 0x0bcaa747;
348 
349       k3 *= c3;
350       k3  = ROTL32( k3, 17 );
351       k3 *= c4;
352       h3 ^= k3;
353 
354       h3  = ROTL32( h3, 15 );
355       h3 += h4;
356       h3  = h3 * 5 + 0x96cd1c35;
357 
358       k4 *= c4;
359       k4  = ROTL32( k4, 18 );
360       k4 *= c1;
361       h4 ^= k4;
362 
363       h4  = ROTL32( h4, 13 );
364       h4 += h1;
365       h4  = h4 * 5 + 0x32ac3b17;
366     }
367 
368     {
369       const FT_Byte*  tail = (const FT_Byte*)( data + nblocks * 16 );
370 
371       FT_UInt32  k1 = 0;
372       FT_UInt32  k2 = 0;
373       FT_UInt32  k3 = 0;
374       FT_UInt32  k4 = 0;
375 
376 
377       switch ( len & 15 )
378       {
379       case 15:
380         k4 ^= (FT_UInt32)tail[14] << 16;
381         FALL_THROUGH;
382       case 14:
383         k4 ^= (FT_UInt32)tail[13] << 8;
384         FALL_THROUGH;
385       case 13:
386         k4 ^= (FT_UInt32)tail[12];
387         k4 *= c4;
388         k4  = ROTL32( k4, 18 );
389         k4 *= c1;
390         h4 ^= k4;
391         FALL_THROUGH;
392 
393       case 12:
394         k3 ^= (FT_UInt32)tail[11] << 24;
395         FALL_THROUGH;
396       case 11:
397         k3 ^= (FT_UInt32)tail[10] << 16;
398         FALL_THROUGH;
399       case 10:
400         k3 ^= (FT_UInt32)tail[9] << 8;
401         FALL_THROUGH;
402       case 9:
403         k3 ^= (FT_UInt32)tail[8];
404         k3 *= c3;
405         k3  = ROTL32( k3, 17 );
406         k3 *= c4;
407         h3 ^= k3;
408         FALL_THROUGH;
409 
410       case 8:
411         k2 ^= (FT_UInt32)tail[7] << 24;
412         FALL_THROUGH;
413       case 7:
414         k2 ^= (FT_UInt32)tail[6] << 16;
415         FALL_THROUGH;
416       case 6:
417         k2 ^= (FT_UInt32)tail[5] << 8;
418         FALL_THROUGH;
419       case 5:
420         k2 ^= (FT_UInt32)tail[4];
421         k2 *= c2;
422         k2  = ROTL32( k2, 16 );
423         k2 *= c3;
424         h2 ^= k2;
425         FALL_THROUGH;
426 
427       case 4:
428         k1 ^= (FT_UInt32)tail[3] << 24;
429         FALL_THROUGH;
430       case 3:
431         k1 ^= (FT_UInt32)tail[2] << 16;
432         FALL_THROUGH;
433       case 2:
434         k1 ^= (FT_UInt32)tail[1] << 8;
435         FALL_THROUGH;
436       case 1:
437         k1 ^= (FT_UInt32)tail[0];
438         k1 *= c1;
439         k1  = ROTL32( k1, 15 );
440         k1 *= c2;
441         h1 ^= k1;
442       }
443     }
444 
445     h1 ^= len;
446     h2 ^= len;
447     h3 ^= len;
448     h4 ^= len;
449 
450     h1 += h2;
451     h1 += h3;
452     h1 += h4;
453 
454     h2 += h1;
455     h3 += h1;
456     h4 += h1;
457 
458     h1 = fmix32( h1 );
459     h2 = fmix32( h2 );
460     h3 = fmix32( h3 );
461     h4 = fmix32( h4 );
462 
463     h1 += h2;
464     h1 += h3;
465     h1 += h4;
466 
467     h2 += h1;
468     h3 += h1;
469     h4 += h1;
470 
471     ((FT_UInt32*)out)[0] = h1;
472     ((FT_UInt32*)out)[1] = h2;
473     ((FT_UInt32*)out)[2] = h3;
474     ((FT_UInt32*)out)[3] = h4;
475   }
476 
477 
478 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
479 
480 
481   typedef int (*char_type_func)( int  c );
482 
483 
484   /* Handling of PID/EID 3/0 and 3/1 is the same. */
485 #define IS_WIN( n )  ( (n)->platformID == 3                             && \
486                        ( (n)->encodingID == 1 || (n)->encodingID == 0 ) )
487 
488 #define IS_APPLE( n )  ( (n)->platformID == 1 && \
489                          (n)->encodingID == 0 )
490 
491   static char*
get_win_string(FT_Memory memory,FT_Stream stream,TT_Name entry,char_type_func char_type,FT_Bool report_invalid_characters)492   get_win_string( FT_Memory       memory,
493                   FT_Stream       stream,
494                   TT_Name         entry,
495                   char_type_func  char_type,
496                   FT_Bool         report_invalid_characters )
497   {
498     FT_Error  error;
499 
500     char*       result = NULL;
501     FT_String*  r;
502     FT_Char*    p;
503     FT_UInt     len;
504 
505 
506     if ( FT_QALLOC( result, entry->stringLength / 2 + 1 ) )
507       return NULL;
508 
509     if ( FT_STREAM_SEEK( entry->stringOffset ) ||
510          FT_FRAME_ENTER( entry->stringLength ) )
511       goto get_win_string_error;
512 
513     r = (FT_String*)result;
514     p = (FT_Char*)stream->cursor;
515 
516     for ( len = entry->stringLength / 2; len > 0; len--, p += 2 )
517     {
518       if ( p[0] == 0 && char_type( p[1] ) )
519         *r++ = p[1];
520       else
521       {
522         if ( report_invalid_characters )
523           FT_TRACE0(( "get_win_string:"
524                       " Character 0x%X invalid in PS name string\n",
525                       ((unsigned)p[0])*256 + (unsigned)p[1] ));
526         break;
527       }
528     }
529     if ( !len )
530       *r = '\0';
531 
532     FT_FRAME_EXIT();
533 
534     if ( !len )
535       return result;
536 
537   get_win_string_error:
538     FT_FREE( result );
539 
540     entry->stringLength = 0;
541     entry->stringOffset = 0;
542     FT_FREE( entry->string );
543 
544     return NULL;
545   }
546 
547 
548   static char*
get_apple_string(FT_Memory memory,FT_Stream stream,TT_Name entry,char_type_func char_type,FT_Bool report_invalid_characters)549   get_apple_string( FT_Memory       memory,
550                     FT_Stream       stream,
551                     TT_Name         entry,
552                     char_type_func  char_type,
553                     FT_Bool         report_invalid_characters )
554   {
555     FT_Error  error;
556 
557     char*       result = NULL;
558     FT_String*  r;
559     FT_Char*    p;
560     FT_UInt     len;
561 
562 
563     if ( FT_QALLOC( result, entry->stringLength + 1 ) )
564       return NULL;
565 
566     if ( FT_STREAM_SEEK( entry->stringOffset ) ||
567          FT_FRAME_ENTER( entry->stringLength ) )
568       goto get_apple_string_error;
569 
570     r = (FT_String*)result;
571     p = (FT_Char*)stream->cursor;
572 
573     for ( len = entry->stringLength; len > 0; len--, p++ )
574     {
575       if ( char_type( *p ) )
576         *r++ = *p;
577       else
578       {
579         if ( report_invalid_characters )
580           FT_TRACE0(( "get_apple_string:"
581                       " Character `%c' (0x%X) invalid in PS name string\n",
582                       *p, *p ));
583         break;
584       }
585     }
586     if ( !len )
587       *r = '\0';
588 
589     FT_FRAME_EXIT();
590 
591     if ( !len )
592       return result;
593 
594   get_apple_string_error:
595     FT_FREE( result );
596 
597     entry->stringOffset = 0;
598     entry->stringLength = 0;
599     FT_FREE( entry->string );
600 
601     return NULL;
602   }
603 
604 
605   static FT_Bool
sfnt_get_name_id(TT_Face face,FT_UShort id,FT_Int * win,FT_Int * apple)606   sfnt_get_name_id( TT_Face    face,
607                     FT_UShort  id,
608                     FT_Int    *win,
609                     FT_Int    *apple )
610   {
611     FT_Int  n;
612 
613 
614     *win   = -1;
615     *apple = -1;
616 
617     for ( n = 0; n < face->num_names; n++ )
618     {
619       TT_Name  name = face->name_table.names + n;
620 
621 
622       if ( name->nameID == id && name->stringLength > 0 )
623       {
624         if ( IS_WIN( name ) && ( name->languageID == 0x409 || *win == -1 ) )
625           *win = n;
626 
627         if ( IS_APPLE( name ) && ( name->languageID == 0 || *apple == -1 ) )
628           *apple = n;
629       }
630     }
631 
632     return ( *win >= 0 ) || ( *apple >= 0 );
633   }
634 
635 
636 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
637 
638   /*
639       The maximum length of an axis value descriptor.
640 
641       We need 65536 different values for the decimal fraction; this fits
642       nicely into five decimal places.  Consequently, it consists of
643 
644         . the minus sign if the number is negative,
645         . up to five characters for the digits before the decimal point,
646         . the decimal point if there is a fractional part, and
647         . up to five characters for the digits after the decimal point.
648 
649       We also need one byte for the leading `_' character and up to four
650       bytes for the axis tag.
651    */
652 #define MAX_VALUE_DESCRIPTOR_LEN  ( 1 + 5 + 1 + 5 + 1 + 4 )
653 
654 
655   /* the maximum length of PostScript font names */
656 #define MAX_PS_NAME_LEN  127
657 
658 
659   /*
660    * Find the shortest decimal representation of a 16.16 fixed-point
661    * number.  The function fills `buf' with the result, returning a pointer
662    * to the position after the representation's last byte.
663    */
664 
665   static char*
fixed2float(FT_Int fixed,char * buf)666   fixed2float( FT_Int  fixed,
667                char*   buf )
668   {
669     char*  p;
670     char*  q;
671     char   tmp[5];
672 
673     FT_Int  int_part;
674     FT_Int  frac_part;
675 
676     FT_Int  i;
677 
678 
679     p = buf;
680 
681     if ( fixed == 0 )
682     {
683       *p++ = '0';
684       return p;
685     }
686 
687     if ( fixed < 0 )
688     {
689       *p++ = '-';
690       fixed = NEG_INT( fixed );
691     }
692 
693     int_part  = ( fixed >> 16 ) & 0xFFFF;
694     frac_part = fixed & 0xFFFF;
695 
696     /* get digits of integer part (in reverse order) */
697     q = tmp;
698     while ( int_part > 0 )
699     {
700       *q++      = '0' + int_part % 10;
701       int_part /= 10;
702     }
703 
704     /* copy digits in correct order to buffer */
705     while ( q > tmp )
706       *p++ = *--q;
707 
708     if ( !frac_part )
709       return p;
710 
711     /* save position of point */
712     q    = p;
713     *p++ = '.';
714 
715     /* apply rounding */
716     frac_part = frac_part * 10 + 5;
717 
718     /* get digits of fractional part */
719     for ( i = 0; i < 5; i++ )
720     {
721       *p++ = '0' + (char)( frac_part / 0x10000L );
722 
723       frac_part %= 0x10000L;
724       if ( !frac_part )
725         break;
726 
727       frac_part *= 10;
728     }
729 
730     /*
731         If the remainder stored in `frac_part' (after the last FOR loop) is
732         smaller than 34480*10, the resulting decimal value minus 0.00001 is
733         an equivalent representation of `fixed'.
734 
735         The above FOR loop always finds the larger of the two values; I
736         verified this by iterating over all possible fixed-point numbers.
737 
738         If the remainder is 17232*10, both values are equally good, and we
739         take the next even number (following IEEE 754's `round to nearest,
740         ties to even' rounding rule).
741 
742         If the remainder is smaller than 17232*10, the lower of the two
743         numbers is nearer to the exact result (values 17232 and 34480 were
744         also found by testing all possible fixed-point values).
745 
746         We use this to find a shorter decimal representation.  If not ending
747         with digit zero, we take the representation with less error.
748      */
749     p--;
750     if ( p - q == 5 )  /* five digits? */
751     {
752       /* take the representation that has zero as the last digit */
753       if ( frac_part < 34480 * 10 &&
754            *p == '1'              )
755         *p = '0';
756 
757       /* otherwise use the one with less error */
758       else if ( frac_part == 17232 * 10 &&
759                 *p & 1                  )
760         *p -= 1;
761 
762       else if ( frac_part < 17232 * 10 &&
763                 *p != '0'              )
764         *p -= 1;
765     }
766 
767     /* remove trailing zeros */
768     while ( *p == '0' )
769       *p-- = '\0';
770 
771     return p + 1;
772   }
773 
774 
775   static const char  hexdigits[16] =
776   {
777     '0', '1', '2', '3', '4', '5', '6', '7',
778     '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
779   };
780 
781 
782   static const char*
sfnt_get_var_ps_name(TT_Face face)783   sfnt_get_var_ps_name( TT_Face  face )
784   {
785     FT_Error   error;
786     FT_Memory  memory = face->root.memory;
787 
788     FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
789 
790     FT_UInt     num_coords;
791     FT_Fixed*   coords;
792     FT_MM_Var*  mm_var;
793 
794     FT_Int   found, win, apple;
795     FT_UInt  i, j;
796 
797     char*  result = NULL;
798     char*  p;
799 
800 
801     if ( !face->var_postscript_prefix )
802     {
803       FT_UInt  len;
804 
805 
806       /* check whether we have a Variations PostScript Name Prefix */
807       found = sfnt_get_name_id( face,
808                                 TT_NAME_ID_VARIATIONS_PREFIX,
809                                 &win,
810                                 &apple );
811       if ( !found )
812       {
813         /* otherwise use the typographic family name */
814         found = sfnt_get_name_id( face,
815                                   TT_NAME_ID_TYPOGRAPHIC_FAMILY,
816                                   &win,
817                                   &apple );
818       }
819 
820       if ( !found )
821       {
822         /* as a last resort we try the family name; note that this is */
823         /* not in the Adobe TechNote, but GX fonts (which predate the */
824         /* TechNote) benefit from this behaviour                      */
825         found = sfnt_get_name_id( face,
826                                   TT_NAME_ID_FONT_FAMILY,
827                                   &win,
828                                   &apple );
829       }
830 
831       if ( !found )
832       {
833         FT_TRACE0(( "sfnt_get_var_ps_name:"
834                     " Can't construct PS name prefix for font instances\n" ));
835         return NULL;
836       }
837 
838       /* prefer Windows entries over Apple */
839       if ( win != -1 )
840         result = get_win_string( face->root.memory,
841                                  face->name_table.stream,
842                                  face->name_table.names + win,
843                                  sfnt_is_alphanumeric,
844                                  0 );
845       if ( !result && apple != -1 )
846         result = get_apple_string( face->root.memory,
847                                    face->name_table.stream,
848                                    face->name_table.names + apple,
849                                    sfnt_is_alphanumeric,
850                                    0 );
851 
852       if ( !result )
853       {
854         FT_TRACE0(( "sfnt_get_var_ps_name:"
855                     " No valid PS name prefix for font instances found\n" ));
856         return NULL;
857       }
858 
859       len = ft_strlen( result );
860 
861       /* sanitize if necessary; we reserve space for 36 bytes (a 128bit  */
862       /* checksum as a hex number, preceded by `-' and followed by three */
863       /* ASCII dots, to be used if the constructed PS name would be too  */
864       /* long); this is also sufficient for a single instance            */
865       if ( len > MAX_PS_NAME_LEN - ( 1 + 32 + 3 ) )
866       {
867         len         = MAX_PS_NAME_LEN - ( 1 + 32 + 3 );
868         result[len] = '\0';
869 
870         FT_TRACE0(( "sfnt_get_var_ps_name:"
871                     " Shortening variation PS name prefix\n" ));
872         FT_TRACE0(( "                     "
873                     " to %d characters\n", len ));
874       }
875 
876       face->var_postscript_prefix     = result;
877       face->var_postscript_prefix_len = len;
878     }
879 
880     mm->get_var_blend( FT_FACE( face ),
881                        &num_coords,
882                        &coords,
883                        NULL,
884                        &mm_var );
885 
886     if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) &&
887          !FT_IS_VARIATION( FT_FACE( face ) )     )
888     {
889       SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
890 
891       FT_Long  instance = ( ( face->root.face_index & 0x7FFF0000L ) >> 16 ) - 1;
892       FT_UInt  psid     = mm_var->namedstyle[instance].psid;
893 
894       char*  ps_name = NULL;
895 
896 
897       /* try first to load the name string with index `postScriptNameID' */
898       if ( psid == 6                      ||
899            ( psid > 255 && psid < 32768 ) )
900         (void)sfnt->get_name( face, (FT_UShort)psid, &ps_name );
901 
902       if ( ps_name )
903       {
904         result = ps_name;
905         p      = result + ft_strlen( result ) + 1;
906 
907         goto check_length;
908       }
909       else
910       {
911         /* otherwise construct a name using `subfamilyNameID' */
912         FT_UInt  strid = mm_var->namedstyle[instance].strid;
913 
914         char*  subfamily_name;
915         char*  s;
916 
917 
918         (void)sfnt->get_name( face, (FT_UShort)strid, &subfamily_name );
919 
920         if ( !subfamily_name )
921         {
922           FT_TRACE1(( "sfnt_get_var_ps_name:"
923                       " can't construct named instance PS name;\n" ));
924           FT_TRACE1(( "                     "
925                       " trying to construct normal instance PS name\n" ));
926           goto construct_instance_name;
927         }
928 
929         /* after the prefix we have character `-' followed by the   */
930         /* subfamily name (using only characters a-z, A-Z, and 0-9) */
931         if ( FT_QALLOC( result, face->var_postscript_prefix_len +
932                                 1 + ft_strlen( subfamily_name ) + 1 ) )
933           return NULL;
934 
935         ft_strcpy( result, face->var_postscript_prefix );
936 
937         p = result + face->var_postscript_prefix_len;
938         *p++ = '-';
939 
940         s = subfamily_name;
941         while ( *s )
942         {
943           if ( ft_isalnum( *s ) )
944             *p++ = *s;
945           s++;
946         }
947         *p++ = '\0';
948 
949         FT_FREE( subfamily_name );
950       }
951     }
952     else
953     {
954       FT_Var_Axis*  axis;
955 
956 
957     construct_instance_name:
958       axis = mm_var->axis;
959 
960       if ( FT_QALLOC( result,
961                       face->var_postscript_prefix_len +
962                         num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) )
963         return NULL;
964 
965       p = result;
966 
967       ft_strcpy( p, face->var_postscript_prefix );
968       p += face->var_postscript_prefix_len;
969 
970       for ( i = 0; i < num_coords; i++, coords++, axis++ )
971       {
972         char  t;
973 
974 
975         /* omit axis value descriptor if it is identical */
976         /* to the default axis value                     */
977         if ( *coords == axis->def )
978           continue;
979 
980         *p++ = '_';
981         p    = fixed2float( *coords, p );
982 
983         t = (char)( axis->tag >> 24 );
984         if ( t != ' ' && ft_isalnum( t ) )
985           *p++ = t;
986         t = (char)( axis->tag >> 16 );
987         if ( t != ' ' && ft_isalnum( t ) )
988           *p++ = t;
989         t = (char)( axis->tag >> 8 );
990         if ( t != ' ' && ft_isalnum( t ) )
991           *p++ = t;
992         t = (char)axis->tag;
993         if ( t != ' ' && ft_isalnum( t ) )
994           *p++ = t;
995       }
996       *p++ = '\0';
997     }
998 
999   check_length:
1000     if ( p - result > MAX_PS_NAME_LEN )
1001     {
1002       /* the PS name is too long; replace the part after the prefix with */
1003       /* a checksum; we use MurmurHash 3 with a hash length of 128 bit   */
1004 
1005       FT_UInt32  seed = 123456789;
1006 
1007       FT_UInt32   hash[4];
1008       FT_UInt32*  h;
1009 
1010 
1011       murmur_hash_3_128( result, p - result, seed, hash );
1012 
1013       p = result + face->var_postscript_prefix_len;
1014       *p++ = '-';
1015 
1016       /* we convert the hash value to hex digits from back to front */
1017       p += 32 + 3;
1018       h  = hash + 3;
1019 
1020       *p-- = '\0';
1021       *p-- = '.';
1022       *p-- = '.';
1023       *p-- = '.';
1024 
1025       for ( i = 0; i < 4; i++, h-- )
1026       {
1027         FT_UInt32  v = *h;
1028 
1029 
1030         for ( j = 0; j < 8; j++ )
1031         {
1032           *p--   = hexdigits[v & 0xF];
1033           v    >>= 4;
1034         }
1035       }
1036     }
1037 
1038     return result;
1039   }
1040 
1041 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1042 
1043 
1044   static const char*
sfnt_get_ps_name(TT_Face face)1045   sfnt_get_ps_name( TT_Face  face )
1046   {
1047     FT_Int       found, win, apple;
1048     const char*  result = NULL;
1049 
1050 
1051     if ( face->postscript_name )
1052       return face->postscript_name;
1053 
1054 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1055     if ( face->blend                                 &&
1056          ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1057            FT_IS_VARIATION( FT_FACE( face ) )      ) )
1058     {
1059       face->postscript_name = sfnt_get_var_ps_name( face );
1060       return face->postscript_name;
1061     }
1062 #endif
1063 
1064     /* scan the name table to see whether we have a Postscript name here, */
1065     /* either in Macintosh or Windows platform encodings                  */
1066     found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple );
1067     if ( !found )
1068       return NULL;
1069 
1070     /* prefer Windows entries over Apple */
1071     if ( win != -1 )
1072       result = get_win_string( face->root.memory,
1073                                face->name_table.stream,
1074                                face->name_table.names + win,
1075                                sfnt_is_postscript,
1076                                1 );
1077     if ( !result && apple != -1 )
1078       result = get_apple_string( face->root.memory,
1079                                  face->name_table.stream,
1080                                  face->name_table.names + apple,
1081                                  sfnt_is_postscript,
1082                                  1 );
1083 
1084     face->postscript_name = result;
1085 
1086     return result;
1087   }
1088 
1089 
1090   FT_DEFINE_SERVICE_PSFONTNAMEREC(
1091     sfnt_service_ps_name,
1092 
1093     (FT_PsName_GetFunc)sfnt_get_ps_name       /* get_ps_font_name */
1094   )
1095 
1096 
1097   /*
1098    * TT CMAP INFO
1099    */
1100   FT_DEFINE_SERVICE_TTCMAPSREC(
1101     tt_service_get_cmap_info,
1102 
1103     (TT_CMap_Info_GetFunc)tt_get_cmap_info    /* get_cmap_info */
1104   )
1105 
1106 
1107 #ifdef TT_CONFIG_OPTION_BDF
1108 
1109   static FT_Error
sfnt_get_charset_id(TT_Face face,const char ** acharset_encoding,const char ** acharset_registry)1110   sfnt_get_charset_id( TT_Face       face,
1111                        const char*  *acharset_encoding,
1112                        const char*  *acharset_registry )
1113   {
1114     BDF_PropertyRec  encoding, registry;
1115     FT_Error         error;
1116 
1117 
1118     /* XXX: I don't know whether this is correct, since
1119      *      tt_face_find_bdf_prop only returns something correct if we have
1120      *      previously selected a size that is listed in the BDF table.
1121      *      Should we change the BDF table format to include single offsets
1122      *      for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?
1123      */
1124     error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", &registry );
1125     if ( !error )
1126     {
1127       error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );
1128       if ( !error )
1129       {
1130         if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
1131              encoding.type == BDF_PROPERTY_TYPE_ATOM )
1132         {
1133           *acharset_encoding = encoding.u.atom;
1134           *acharset_registry = registry.u.atom;
1135         }
1136         else
1137           error = FT_THROW( Invalid_Argument );
1138       }
1139     }
1140 
1141     return error;
1142   }
1143 
1144 
1145   FT_DEFINE_SERVICE_BDFRec(
1146     sfnt_service_bdf,
1147 
1148     (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id,     /* get_charset_id */
1149     (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop    /* get_property   */
1150   )
1151 
1152 
1153 #endif /* TT_CONFIG_OPTION_BDF */
1154 
1155 
1156   /*
1157    * SERVICE LIST
1158    */
1159 
1160 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
1161   FT_DEFINE_SERVICEDESCREC5(
1162     sfnt_services,
1163 
1164     FT_SERVICE_ID_SFNT_TABLE,           &sfnt_service_sfnt_table,
1165     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
1166     FT_SERVICE_ID_GLYPH_DICT,           &sfnt_service_glyph_dict,
1167     FT_SERVICE_ID_BDF,                  &sfnt_service_bdf,
1168     FT_SERVICE_ID_TT_CMAP,              &tt_service_get_cmap_info )
1169 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
1170   FT_DEFINE_SERVICEDESCREC4(
1171     sfnt_services,
1172 
1173     FT_SERVICE_ID_SFNT_TABLE,           &sfnt_service_sfnt_table,
1174     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
1175     FT_SERVICE_ID_GLYPH_DICT,           &sfnt_service_glyph_dict,
1176     FT_SERVICE_ID_TT_CMAP,              &tt_service_get_cmap_info )
1177 #elif defined TT_CONFIG_OPTION_BDF
1178   FT_DEFINE_SERVICEDESCREC4(
1179     sfnt_services,
1180 
1181     FT_SERVICE_ID_SFNT_TABLE,           &sfnt_service_sfnt_table,
1182     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
1183     FT_SERVICE_ID_BDF,                  &sfnt_service_bdf,
1184     FT_SERVICE_ID_TT_CMAP,              &tt_service_get_cmap_info )
1185 #else
1186   FT_DEFINE_SERVICEDESCREC3(
1187     sfnt_services,
1188 
1189     FT_SERVICE_ID_SFNT_TABLE,           &sfnt_service_sfnt_table,
1190     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
1191     FT_SERVICE_ID_TT_CMAP,              &tt_service_get_cmap_info )
1192 #endif
1193 
1194 
FT_CALLBACK_DEF(FT_Module_Interface)1195   FT_CALLBACK_DEF( FT_Module_Interface )
1196   sfnt_get_interface( FT_Module    module,
1197                       const char*  module_interface )
1198   {
1199     FT_UNUSED( module );
1200 
1201     return ft_service_list_lookup( sfnt_services, module_interface );
1202   }
1203 
1204 
1205 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1206 #define PUT_EMBEDDED_BITMAPS( a )  a
1207 #else
1208 #define PUT_EMBEDDED_BITMAPS( a )  NULL
1209 #endif
1210 
1211 #ifdef TT_CONFIG_OPTION_COLOR_LAYERS
1212 #define PUT_COLOR_LAYERS( a )  a
1213 #else
1214 #define PUT_COLOR_LAYERS( a )  NULL
1215 #endif
1216 
1217 #ifdef FT_CONFIG_OPTION_SVG
1218 #define PUT_SVG_SUPPORT( a )  a
1219 #else
1220 #define PUT_SVG_SUPPORT( a )  NULL
1221 #endif
1222 
1223 #define PUT_COLOR_LAYERS_V1( a )  PUT_COLOR_LAYERS( a )
1224 
1225 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
1226 #define PUT_PS_NAMES( a )  a
1227 #else
1228 #define PUT_PS_NAMES( a )  NULL
1229 #endif
1230 
1231   FT_DEFINE_SFNT_INTERFACE(
1232     sfnt_interface,
1233 
1234     tt_face_goto_table,     /* TT_Loader_GotoTableFunc goto_table      */
1235 
1236     sfnt_init_face,         /* TT_Init_Face_Func       init_face       */
1237     sfnt_load_face,         /* TT_Load_Face_Func       load_face       */
1238     sfnt_done_face,         /* TT_Done_Face_Func       done_face       */
1239     sfnt_get_interface,     /* FT_Module_Requester     get_interface   */
1240 
1241     tt_face_load_any,       /* TT_Load_Any_Func        load_any        */
1242 
1243     tt_face_load_head,      /* TT_Load_Table_Func      load_head       */
1244     tt_face_load_hhea,      /* TT_Load_Metrics_Func    load_hhea       */
1245     tt_face_load_cmap,      /* TT_Load_Table_Func      load_cmap       */
1246     tt_face_load_maxp,      /* TT_Load_Table_Func      load_maxp       */
1247     tt_face_load_os2,       /* TT_Load_Table_Func      load_os2        */
1248     tt_face_load_post,      /* TT_Load_Table_Func      load_post       */
1249 
1250     tt_face_load_name,      /* TT_Load_Table_Func      load_name       */
1251     tt_face_free_name,      /* TT_Free_Table_Func      free_name       */
1252 
1253     tt_face_load_kern,      /* TT_Load_Table_Func      load_kern       */
1254     tt_face_load_gasp,      /* TT_Load_Table_Func      load_gasp       */
1255     tt_face_load_pclt,      /* TT_Load_Table_Func      load_init       */
1256 
1257     /* see `ttload.h' */
1258     PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ),
1259                             /* TT_Load_Table_Func      load_bhed       */
1260     PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ),
1261                             /* TT_Load_SBit_Image_Func load_sbit_image */
1262 
1263     /* see `ttpost.h' */
1264     PUT_PS_NAMES( tt_face_get_ps_name   ),
1265                             /* TT_Get_PS_Name_Func     get_psname      */
1266     PUT_PS_NAMES( tt_face_free_ps_names ),
1267                             /* TT_Free_Table_Func      free_psnames    */
1268 
1269     /* since version 2.1.8 */
1270     tt_face_get_kerning,    /* TT_Face_GetKerningFunc  get_kerning     */
1271 
1272     /* since version 2.2 */
1273     tt_face_load_font_dir,  /* TT_Load_Table_Func      load_font_dir   */
1274     tt_face_load_hmtx,      /* TT_Load_Metrics_Func    load_hmtx       */
1275 
1276     /* see `ttsbit.h' and `sfnt.h' */
1277     PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ),
1278                             /* TT_Load_Table_Func      load_eblc       */
1279     PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
1280                             /* TT_Free_Table_Func      free_eblc       */
1281 
1282     PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike     ),
1283                   /* TT_Set_SBit_Strike_Func      set_sbit_strike      */
1284     PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
1285                   /* TT_Load_Strike_Metrics_Func  load_strike_metrics  */
1286 
1287     PUT_COLOR_LAYERS( tt_face_load_cpal ),
1288                             /* TT_Load_Table_Func      load_cpal       */
1289     PUT_COLOR_LAYERS( tt_face_load_colr ),
1290                             /* TT_Load_Table_Func      load_colr       */
1291     PUT_COLOR_LAYERS( tt_face_free_cpal ),
1292                             /* TT_Free_Table_Func      free_cpal       */
1293     PUT_COLOR_LAYERS( tt_face_free_colr ),
1294                             /* TT_Free_Table_Func      free_colr       */
1295     PUT_COLOR_LAYERS( tt_face_palette_set ),
1296                             /* TT_Set_Palette_Func     set_palette     */
1297     PUT_COLOR_LAYERS( tt_face_get_colr_layer ),
1298                             /* TT_Get_Colr_Layer_Func  get_colr_layer  */
1299 
1300     PUT_COLOR_LAYERS_V1( tt_face_get_colr_glyph_paint ),
1301               /* TT_Get_Color_Glyph_Paint_Func    get_colr_glyph_paint */
1302     PUT_COLOR_LAYERS_V1( tt_face_get_color_glyph_clipbox ),
1303               /* TT_Get_Color_Glyph_ClipBox_Func  get_clipbox          */
1304     PUT_COLOR_LAYERS_V1( tt_face_get_paint_layers ),
1305               /* TT_Get_Paint_Layers_Func         get_paint_layers     */
1306     PUT_COLOR_LAYERS_V1( tt_face_get_colorline_stops ),
1307               /* TT_Get_Paint                     get_paint            */
1308     PUT_COLOR_LAYERS_V1( tt_face_get_paint ),
1309               /* TT_Get_Colorline_Stops_Func      get_colorline_stops  */
1310 
1311     PUT_COLOR_LAYERS( tt_face_colr_blend_layer ),
1312                             /* TT_Blend_Colr_Func      colr_blend      */
1313 
1314     tt_face_get_metrics,    /* TT_Get_Metrics_Func     get_metrics     */
1315 
1316     tt_face_get_name,       /* TT_Get_Name_Func        get_name        */
1317     sfnt_get_name_id,       /* TT_Get_Name_ID_Func     get_name_id     */
1318 
1319     PUT_SVG_SUPPORT( tt_face_load_svg ),
1320                             /* TT_Load_Table_Func      load_svg        */
1321     PUT_SVG_SUPPORT( tt_face_free_svg ),
1322                             /* TT_Free_Table_Func      free_svg        */
1323     PUT_SVG_SUPPORT( tt_face_load_svg_doc )
1324                             /* TT_Load_Svg_Doc_Func    load_svg_doc    */
1325   )
1326 
1327 
1328   FT_DEFINE_MODULE(
1329     sfnt_module_class,
1330 
1331     0,  /* not a font driver or renderer */
1332     sizeof ( FT_ModuleRec ),
1333 
1334     "sfnt",     /* driver name                            */
1335     0x10000L,   /* driver version 1.0                     */
1336     0x20000L,   /* driver requires FreeType 2.0 or higher */
1337 
1338     (const void*)&sfnt_interface,  /* module specific interface */
1339 
1340     (FT_Module_Constructor)NULL,               /* module_init   */
1341     (FT_Module_Destructor) NULL,               /* module_done   */
1342     (FT_Module_Requester)  sfnt_get_interface  /* get_interface */
1343   )
1344 
1345 
1346 /* END */
1347