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