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