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