1/****************************************************************************
2 *
3 * cffobjs.c
4 *
5 * OpenType objects manager (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
20#include <freetype/internal/ftdebug.h>
21#include <freetype/internal/ftcalc.h>
22#include <freetype/internal/ftstream.h>
23#include <freetype/fterrors.h>
24#include <freetype/ttnameid.h>
25#include <freetype/tttags.h>
26#include <freetype/internal/sfnt.h>
27#include <freetype/ftdriver.h>
28
29#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
30#include <freetype/ftmm.h>
31#include <freetype/internal/services/svmm.h>
32#include <freetype/internal/services/svmetric.h>
33#endif
34
35#include <freetype/internal/cffotypes.h>
36#include "cffobjs.h"
37#include "cffload.h"
38#include "cffcmap.h"
39
40#include "cfferrs.h"
41
42#include <freetype/internal/psaux.h>
43#include <freetype/internal/services/svcfftl.h>
44
45
46 /**************************************************************************
47 *
48 * The macro FT_COMPONENT is used in trace mode. It is an implicit
49 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
50 * messages during execution.
51 */
52#undef FT_COMPONENT
53#define FT_COMPONENT cffobjs
54
55
56 /**************************************************************************
57 *
58 * SIZE FUNCTIONS
59 *
60 */
61
62
63 static PSH_Globals_Funcs
64 cff_size_get_globals_funcs( CFF_Size size )
65 {
66 CFF_Face face = (CFF_Face)size->root.face;
67 CFF_Font font = (CFF_Font)face->extra.data;
68 PSHinter_Service pshinter = font->pshinter;
69 FT_Module module;
70
71
72 module = FT_Get_Module( font->library, "pshinter" );
73
74 return ( module && pshinter && pshinter->get_globals_funcs )
75 ? pshinter->get_globals_funcs( module )
76 : 0;
77 }
78
79
80 FT_LOCAL_DEF( void )
81 cff_size_done( FT_Size cffsize ) /* CFF_Size */
82 {
83 FT_Memory memory = cffsize->face->memory;
84 CFF_Size size = (CFF_Size)cffsize;
85 CFF_Face face = (CFF_Face)size->root.face;
86 CFF_Font font = (CFF_Font)face->extra.data;
87 CFF_Internal internal = (CFF_Internal)cffsize->internal->module_data;
88
89
90 if ( internal )
91 {
92 PSH_Globals_Funcs funcs;
93
94
95 funcs = cff_size_get_globals_funcs( size );
96 if ( funcs )
97 {
98 FT_UInt i;
99
100
101 funcs->destroy( internal->topfont );
102
103 for ( i = font->num_subfonts; i > 0; i-- )
104 funcs->destroy( internal->subfonts[i - 1] );
105 }
106
107 FT_FREE( internal );
108 }
109 }
110
111
112 /* CFF and Type 1 private dictionaries have slightly different */
113 /* structures; we need to synthesize a Type 1 dictionary on the fly */
114
115 static void
116 cff_make_private_dict( CFF_SubFont subfont,
117 PS_Private priv )
118 {
119 CFF_Private cpriv = &subfont->private_dict;
120 FT_UInt n, count;
121
122
123 FT_ZERO( priv );
124
125 count = priv->num_blue_values = cpriv->num_blue_values;
126 for ( n = 0; n < count; n++ )
127 priv->blue_values[n] = (FT_Short)cpriv->blue_values[n];
128
129 count = priv->num_other_blues = cpriv->num_other_blues;
130 for ( n = 0; n < count; n++ )
131 priv->other_blues[n] = (FT_Short)cpriv->other_blues[n];
132
133 count = priv->num_family_blues = cpriv->num_family_blues;
134 for ( n = 0; n < count; n++ )
135 priv->family_blues[n] = (FT_Short)cpriv->family_blues[n];
136
137 count = priv->num_family_other_blues = cpriv->num_family_other_blues;
138 for ( n = 0; n < count; n++ )
139 priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
140
141 priv->blue_scale = cpriv->blue_scale;
142 priv->blue_shift = (FT_Int)cpriv->blue_shift;
143 priv->blue_fuzz = (FT_Int)cpriv->blue_fuzz;
144
145 priv->standard_width[0] = (FT_UShort)cpriv->standard_width;
146 priv->standard_height[0] = (FT_UShort)cpriv->standard_height;
147
148 count = priv->num_snap_widths = cpriv->num_snap_widths;
149 for ( n = 0; n < count; n++ )
150 priv->snap_widths[n] = (FT_Short)cpriv->snap_widths[n];
151
152 count = priv->num_snap_heights = cpriv->num_snap_heights;
153 for ( n = 0; n < count; n++ )
154 priv->snap_heights[n] = (FT_Short)cpriv->snap_heights[n];
155
156 priv->force_bold = cpriv->force_bold;
157 priv->language_group = cpriv->language_group;
158 priv->lenIV = cpriv->lenIV;
159 }
160
161
162 FT_LOCAL_DEF( FT_Error )
163 cff_size_init( FT_Size cffsize ) /* CFF_Size */
164 {
165 CFF_Size size = (CFF_Size)cffsize;
166 FT_Error error = FT_Err_Ok;
167 PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size );
168
169 FT_Memory memory = cffsize->face->memory;
170 CFF_Internal internal = NULL;
171 CFF_Face face = (CFF_Face)cffsize->face;
172 CFF_Font font = (CFF_Font)face->extra.data;
173
174 PS_PrivateRec priv;
175
176 FT_UInt i;
177
178 if ( !funcs )
179 goto Exit;
180
181 if ( FT_NEW( internal ) )
182 goto Exit;
183
184 cff_make_private_dict( &font->top_font, &priv );
185 error = funcs->create( memory, &priv, &internal->topfont );
186 if ( error )
187 goto Exit;
188
189 for ( i = font->num_subfonts; i > 0; i-- )
190 {
191 CFF_SubFont sub = font->subfonts[i - 1];
192
193
194 cff_make_private_dict( sub, &priv );
195 error = funcs->create( memory, &priv, &internal->subfonts[i - 1] );
196 if ( error )
197 goto Exit;
198 }
199
200 cffsize->internal->module_data = internal;
201
202 size->strike_index = 0xFFFFFFFFUL;
203
204 Exit:
205 if ( error )
206 {
207 if ( internal )
208 {
209 for ( i = font->num_subfonts; i > 0; i-- )
210 FT_FREE( internal->subfonts[i - 1] );
211 FT_FREE( internal->topfont );
212 }
213
214 FT_FREE( internal );
215 }
216
217 return error;
218 }
219
220
221#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
222
223 FT_LOCAL_DEF( FT_Error )
224 cff_size_select( FT_Size size,
225 FT_ULong strike_index )
226 {
227 CFF_Size cffsize = (CFF_Size)size;
228 PSH_Globals_Funcs funcs;
229
230
231 cffsize->strike_index = strike_index;
232
233 FT_Select_Metrics( size->face, strike_index );
234
235 funcs = cff_size_get_globals_funcs( cffsize );
236
237 if ( funcs )
238 {
239 CFF_Face face = (CFF_Face)size->face;
240 CFF_Font font = (CFF_Font)face->extra.data;
241 CFF_Internal internal = (CFF_Internal)size->internal->module_data;
242
243 FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em;
244 FT_UInt i;
245
246
247 funcs->set_scale( internal->topfont,
248 size->metrics.x_scale, size->metrics.y_scale,
249 0, 0 );
250
251 for ( i = font->num_subfonts; i > 0; i-- )
252 {
253 CFF_SubFont sub = font->subfonts[i - 1];
254 FT_Long sub_upm = (FT_Long)sub->font_dict.units_per_em;
255 FT_Pos x_scale, y_scale;
256
257
258 if ( top_upm != sub_upm )
259 {
260 x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );
261 y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );
262 }
263 else
264 {
265 x_scale = size->metrics.x_scale;
266 y_scale = size->metrics.y_scale;
267 }
268
269 funcs->set_scale( internal->subfonts[i - 1],
270 x_scale, y_scale, 0, 0 );
271 }
272 }
273
274 return FT_Err_Ok;
275 }
276
277#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
278
279
280 FT_LOCAL_DEF( FT_Error )
281 cff_size_request( FT_Size size,
282 FT_Size_Request req )
283 {
284 FT_Error error;
285
286 CFF_Size cffsize = (CFF_Size)size;
287 PSH_Globals_Funcs funcs;
288
289
290#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
291
292 if ( FT_HAS_FIXED_SIZES( size->face ) )
293 {
294 CFF_Face cffface = (CFF_Face)size->face;
295 SFNT_Service sfnt = (SFNT_Service)cffface->sfnt;
296 FT_ULong strike_index;
297
298
299 if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) )
300 cffsize->strike_index = 0xFFFFFFFFUL;
301 else
302 return cff_size_select( size, strike_index );
303 }
304
305#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
306
307 error = FT_Request_Metrics( size->face, req );
308 if ( error )
309 goto Exit;
310
311 funcs = cff_size_get_globals_funcs( cffsize );
312
313 if ( funcs )
314 {
315 CFF_Face cffface = (CFF_Face)size->face;
316 CFF_Font font = (CFF_Font)cffface->extra.data;
317 CFF_Internal internal = (CFF_Internal)size->internal->module_data;
318
319 FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em;
320 FT_UInt i;
321
322
323 funcs->set_scale( internal->topfont,
324 size->metrics.x_scale, size->metrics.y_scale,
325 0, 0 );
326
327 for ( i = font->num_subfonts; i > 0; i-- )
328 {
329 CFF_SubFont sub = font->subfonts[i - 1];
330 FT_Long sub_upm = (FT_Long)sub->font_dict.units_per_em;
331 FT_Pos x_scale, y_scale;
332
333
334 if ( top_upm != sub_upm )
335 {
336 x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );
337 y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );
338 }
339 else
340 {
341 x_scale = size->metrics.x_scale;
342 y_scale = size->metrics.y_scale;
343 }
344
345 funcs->set_scale( internal->subfonts[i - 1],
346 x_scale, y_scale, 0, 0 );
347 }
348 }
349
350 Exit:
351 return error;
352 }
353
354
355 /**************************************************************************
356 *
357 * SLOT FUNCTIONS
358 *
359 */
360
361 FT_LOCAL_DEF( void )
362 cff_slot_done( FT_GlyphSlot slot )
363 {
364 if ( slot->internal )
365 slot->internal->glyph_hints = NULL;
366 }
367
368
369 FT_LOCAL_DEF( FT_Error )
370 cff_slot_init( FT_GlyphSlot slot )
371 {
372 CFF_Face face = (CFF_Face)slot->face;
373 CFF_Font font = (CFF_Font)face->extra.data;
374 PSHinter_Service pshinter = font->pshinter;
375
376
377 if ( pshinter )
378 {
379 FT_Module module;
380
381
382 module = FT_Get_Module( slot->library, "pshinter" );
383 if ( module )
384 {
385 T2_Hints_Funcs funcs;
386
387
388 funcs = pshinter->get_t2_funcs( module );
389 slot->internal->glyph_hints = (void*)funcs;
390 }
391 }
392
393 return FT_Err_Ok;
394 }
395
396
397 /**************************************************************************
398 *
399 * FACE FUNCTIONS
400 *
401 */
402
403 static FT_String*
404 cff_strcpy( FT_Memory memory,
405 const FT_String* source )
406 {
407 FT_Error error;
408 FT_String* result;
409
410
411 FT_MEM_STRDUP( result, source );
412
413 return result;
414 }
415
416
417 /* Strip all subset prefixes of the form `ABCDEF+'. Usually, there */
418 /* is only one, but font names like `APCOOG+JFABTD+FuturaBQ-Bold' */
419 /* have been seen in the wild. */
420
421 static void
422 remove_subset_prefix( FT_String* name )
423 {
424 FT_Int32 idx = 0;
425 FT_Int32 length = (FT_Int32)ft_strlen( name ) + 1;
426 FT_Bool continue_search = 1;
427
428
429 while ( continue_search )
430 {
431 if ( length >= 7 && name[6] == '+' )
432 {
433 for ( idx = 0; idx < 6; idx++ )
434 {
435 /* ASCII uppercase letters */
436 if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) )
437 continue_search = 0;
438 }
439
440 if ( continue_search )
441 {
442 for ( idx = 7; idx < length; idx++ )
443 name[idx - 7] = name[idx];
444 length -= 7;
445 }
446 }
447 else
448 continue_search = 0;
449 }
450 }
451
452
453 /* Remove the style part from the family name (if present). */
454
455 static void
456 remove_style( FT_String* family_name,
457 const FT_String* style_name )
458 {
459 FT_Int32 family_name_length, style_name_length;
460
461
462 family_name_length = (FT_Int32)ft_strlen( family_name );
463 style_name_length = (FT_Int32)ft_strlen( style_name );
464
465 if ( family_name_length > style_name_length )
466 {
467 FT_Int idx;
468
469
470 for ( idx = 1; idx <= style_name_length; idx++ )
471 {
472 if ( family_name[family_name_length - idx] !=
473 style_name[style_name_length - idx] )
474 break;
475 }
476
477 if ( idx > style_name_length )
478 {
479 /* family_name ends with style_name; remove it */
480 idx = family_name_length - style_name_length - 1;
481
482 /* also remove special characters */
483 /* between real family name and style */
484 while ( idx > 0 &&
485 ( family_name[idx] == '-' ||
486 family_name[idx] == ' ' ||
487 family_name[idx] == '_' ||
488 family_name[idx] == '+' ) )
489 idx--;
490
491 if ( idx > 0 )
492 family_name[idx + 1] = '\0';
493 }
494 }
495 }
496
497
498 FT_LOCAL_DEF( FT_Error )
499 cff_face_init( FT_Stream stream,
500 FT_Face cffface, /* CFF_Face */
501 FT_Int face_index,
502 FT_Int num_params,
503 FT_Parameter* params )
504 {
505 CFF_Face face = (CFF_Face)cffface;
506 FT_Error error;
507 SFNT_Service sfnt;
508 FT_Service_PsCMaps psnames;
509 PSHinter_Service pshinter;
510 PSAux_Service psaux;
511 FT_Service_CFFLoad cffload;
512 FT_Bool pure_cff = 1;
513 FT_Bool cff2 = 0;
514 FT_Bool sfnt_format = 0;
515 FT_Library library = cffface->driver->root.library;
516
517
518 sfnt = (SFNT_Service)FT_Get_Module_Interface( library,
519 "sfnt" );
520 if ( !sfnt )
521 {
522 FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" ));
523 error = FT_THROW( Missing_Module );
524 goto Exit;
525 }
526
527 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
528
529 pshinter = (PSHinter_Service)FT_Get_Module_Interface( library,
530 "pshinter" );
531
532 psaux = (PSAux_Service)FT_Get_Module_Interface( library,
533 "psaux" );
534 if ( !psaux )
535 {
536 FT_ERROR(( "cff_face_init: cannot access `psaux' module\n" ));
537 error = FT_THROW( Missing_Module );
538 goto Exit;
539 }
540 face->psaux = psaux;
541
542 FT_FACE_FIND_GLOBAL_SERVICE( face, cffload, CFF_LOAD );
543
544 FT_TRACE2(( "CFF driver\n" ));
545
546 /* create input stream from resource */
547 if ( FT_STREAM_SEEK( 0 ) )
548 goto Exit;
549
550 /* check whether we have a valid OpenType file */
551 FT_TRACE2(( " " ));
552 error = sfnt->init_face( stream, face, face_index, num_params, params );
553 if ( !error )
554 {
555 if ( face->format_tag != TTAG_OTTO ) /* `OTTO'; OpenType/CFF font */
556 {
557 FT_TRACE2(( " not an OpenType/CFF font\n" ));
558 error = FT_THROW( Unknown_File_Format );
559 goto Exit;
560 }
561
562 /* if we are performing a simple font format check, exit immediately */
563 if ( face_index < 0 )
564 return FT_Err_Ok;
565
566 sfnt_format = 1;
567
568 /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
569 /* font; in the latter case it doesn't have a `head' table */
570 error = face->goto_table( face, TTAG_head, stream, 0 );
571 if ( !error )
572 {
573 pure_cff = 0;
574
575 /* load font directory */
576 error = sfnt->load_face( stream, face, face_index,
577 num_params, params );
578 if ( error )
579 goto Exit;
580 }
581 else
582 {
583 /* load the `cmap' table explicitly */
584 error = sfnt->load_cmap( face, stream );
585 if ( error )
586 goto Exit;
587 }
588
589 /* now load the CFF part of the file; */
590 /* give priority to CFF2 */
591 error = face->goto_table( face, TTAG_CFF2, stream, 0 );
592 if ( !error )
593 {
594 cff2 = 1;
595 face->is_cff2 = cff2;
596 }
597
598 if ( FT_ERR_EQ( error, Table_Missing ) )
599 error = face->goto_table( face, TTAG_CFF, stream, 0 );
600
601 if ( error )
602 goto Exit;
603 }
604 else
605 {
606 /* rewind to start of file; we are going to load a pure-CFF font */
607 if ( FT_STREAM_SEEK( 0 ) )
608 goto Exit;
609 error = FT_Err_Ok;
610 }
611
612 /* now load and parse the CFF table in the file */
613 {
614 CFF_Font cff = NULL;
615 CFF_FontRecDict dict;
616 FT_Memory memory = cffface->memory;
617 FT_Int32 flags;
618 FT_UInt i;
619
620
621 if ( FT_NEW( cff ) )
622 goto Exit;
623
624 face->extra.data = cff;
625 error = cff_font_load( library,
626 stream,
627 face_index,
628 cff,
629 face,
630 pure_cff,
631 cff2 );
632 if ( error )
633 goto Exit;
634
635 /* if we are performing a simple font format check, exit immediately */
636 /* (this is here for pure CFF) */
637 if ( face_index < 0 )
638 {
639 cffface->num_faces = (FT_Long)cff->num_faces;
640 return FT_Err_Ok;
641 }
642
643 cff->pshinter = pshinter;
644 cff->psnames = psnames;
645 cff->cffload = cffload;
646
647 cffface->face_index = face_index & 0xFFFF;
648
649 /* Complement the root flags with some interesting information. */
650 /* Note that this is only necessary for pure CFF and CEF fonts; */
651 /* SFNT based fonts use the `name' table instead. */
652
653 cffface->num_glyphs = (FT_Long)cff->num_glyphs;
654
655 dict = &cff->top_font.font_dict;
656
657 /* we need the `psnames' module for CFF and CEF formats */
658 /* which aren't CID-keyed */
659 if ( dict->cid_registry == 0xFFFFU && !psnames )
660 {
661 FT_ERROR(( "cff_face_init:"
662 " cannot open CFF & CEF fonts\n" ));
663 FT_ERROR(( " "
664 " without the `psnames' module\n" ));
665 error = FT_THROW( Missing_Module );
666 goto Exit;
667 }
668
669#ifdef FT_DEBUG_LEVEL_TRACE
670 {
671 FT_UInt idx;
672 FT_String* s;
673
674
675 FT_TRACE4(( "SIDs\n" ));
676
677 /* dump string index, including default strings for convenience */
678 for ( idx = 0; idx <= 390; idx++ )
679 {
680 s = cff_index_get_sid_string( cff, idx );
681 if ( s )
682 FT_TRACE4(( " %5d %s\n", idx, s ));
683 }
684
685 /* In Multiple Master CFFs, two SIDs hold the Normalize Design */
686 /* Vector (NDV) and Convert Design Vector (CDV) charstrings, */
687 /* which may contain null bytes in the middle of the data, too. */
688 /* We thus access `cff->strings' directly. */
689 for ( idx = 1; idx < cff->num_strings; idx++ )
690 {
691 FT_Byte* s1 = cff->strings[idx - 1];
692 FT_Byte* s2 = cff->strings[idx];
693 FT_PtrDist s1len = s2 - s1 - 1; /* without the final null byte */
694 FT_PtrDist l;
695
696
697 FT_TRACE4(( " %5d ", idx + 390 ));
698 for ( l = 0; l < s1len; l++ )
699 FT_TRACE4(( "%c", s1[l] ));
700 FT_TRACE4(( "\n" ));
701 }
702
703 /* print last element */
704 if ( cff->num_strings )
705 {
706 FT_Byte* s1 = cff->strings[cff->num_strings - 1];
707 FT_Byte* s2 = cff->string_pool + cff->string_pool_size;
708 FT_PtrDist s1len = s2 - s1 - 1;
709 FT_PtrDist l;
710
711
712 FT_TRACE4(( " %5d ", cff->num_strings + 390 ));
713 for ( l = 0; l < s1len; l++ )
714 FT_TRACE4(( "%c", s1[l] ));
715 FT_TRACE4(( "\n" ));
716 }
717 }
718#endif /* FT_DEBUG_LEVEL_TRACE */
719
720#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
721 {
722 FT_UInt instance_index = (FT_UInt)face_index >> 16;
723
724
725 if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
726 instance_index > 0 )
727 {
728 error = FT_Set_Named_Instance( cffface, instance_index );
729 if ( error )
730 goto Exit;
731 }
732 }
733#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
734
735 if ( !dict->has_font_matrix )
736 dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
737
738 /* Normalize the font matrix so that `matrix->yy' is 1; if */
739 /* it is zero, we use `matrix->yx' instead. The scaling is */
740 /* done with `units_per_em' then (at this point, it already */
741 /* contains the scaling factor, but without normalization */
742 /* of the matrix). */
743 /* */
744 /* Note that the offsets must be expressed in integer font */
745 /* units. */
746
747 {
748 FT_Matrix* matrix = &dict->font_matrix;
749 FT_Vector* offset = &dict->font_offset;
750 FT_ULong* upm = &dict->units_per_em;
751 FT_Fixed temp;
752
753
754 temp = matrix->yy ? FT_ABS( matrix->yy )
755 : FT_ABS( matrix->yx );
756
757 if ( temp != 0x10000L )
758 {
759 *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
760
761 matrix->xx = FT_DivFix( matrix->xx, temp );
762 matrix->yx = FT_DivFix( matrix->yx, temp );
763 matrix->xy = FT_DivFix( matrix->xy, temp );
764 matrix->yy = FT_DivFix( matrix->yy, temp );
765 offset->x = FT_DivFix( offset->x, temp );
766 offset->y = FT_DivFix( offset->y, temp );
767 }
768
769 offset->x >>= 16;
770 offset->y >>= 16;
771 }
772
773 for ( i = cff->num_subfonts; i > 0; i-- )
774 {
775 CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict;
776 CFF_FontRecDict top = &cff->top_font.font_dict;
777
778 FT_Matrix* matrix;
779 FT_Vector* offset;
780 FT_ULong* upm;
781 FT_Fixed temp;
782
783
784 if ( sub->has_font_matrix )
785 {
786 FT_Long scaling;
787
788
789 /* if we have a top-level matrix, */
790 /* concatenate the subfont matrix */
791
792 if ( top->has_font_matrix )
793 {
794 if ( top->units_per_em > 1 && sub->units_per_em > 1 )
795 scaling = (FT_Long)FT_MIN( top->units_per_em,
796 sub->units_per_em );
797 else
798 scaling = 1;
799
800 FT_Matrix_Multiply_Scaled( &top->font_matrix,
801 &sub->font_matrix,
802 scaling );
803 FT_Vector_Transform_Scaled( &sub->font_offset,
804 &top->font_matrix,
805 scaling );
806
807 sub->units_per_em = (FT_ULong)
808 FT_MulDiv( (FT_Long)sub->units_per_em,
809 (FT_Long)top->units_per_em,
810 scaling );
811 }
812 }
813 else
814 {
815 sub->font_matrix = top->font_matrix;
816 sub->font_offset = top->font_offset;
817
818 sub->units_per_em = top->units_per_em;
819 }
820
821 matrix = &sub->font_matrix;
822 offset = &sub->font_offset;
823 upm = &sub->units_per_em;
824
825 temp = matrix->yy ? FT_ABS( matrix->yy )
826 : FT_ABS( matrix->yx );
827
828
829 if ( temp != 0x10000L )
830 {
831 *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
832
833 matrix->xx = FT_DivFix( matrix->xx, temp );
834 matrix->yx = FT_DivFix( matrix->yx, temp );
835 matrix->xy = FT_DivFix( matrix->xy, temp );
836 matrix->yy = FT_DivFix( matrix->yy, temp );
837 offset->x = FT_DivFix( offset->x, temp );
838 offset->y = FT_DivFix( offset->y, temp );
839 }
840
841 offset->x >>= 16;
842 offset->y >>= 16;
843 }
844
845 if ( pure_cff )
846 {
847 char* style_name = NULL;
848
849
850 /* set up num_faces */
851 cffface->num_faces = (FT_Long)cff->num_faces;
852
853 /* compute number of glyphs */
854 if ( dict->cid_registry != 0xFFFFU )
855 cffface->num_glyphs = (FT_Long)( cff->charset.max_cid + 1 );
856 else
857 cffface->num_glyphs = (FT_Long)cff->charstrings_index.count;
858
859 /* set global bbox, as well as EM size */
860 cffface->bbox.xMin = dict->font_bbox.xMin >> 16;
861 cffface->bbox.yMin = dict->font_bbox.yMin >> 16;
862 /* no `U' suffix here to 0xFFFF! */
863 cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16;
864 cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16;
865
866 cffface->units_per_EM = (FT_UShort)( dict->units_per_em );
867
868 cffface->ascender = (FT_Short)( cffface->bbox.yMax );
869 cffface->descender = (FT_Short)( cffface->bbox.yMin );
870
871 cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 );
872 if ( cffface->height < cffface->ascender - cffface->descender )
873 cffface->height = (FT_Short)( cffface->ascender -
874 cffface->descender );
875
876 cffface->underline_position =
877 (FT_Short)( dict->underline_position >> 16 );
878 cffface->underline_thickness =
879 (FT_Short)( dict->underline_thickness >> 16 );
880
881 /* retrieve font family & style name */
882 if ( dict->family_name )
883 {
884 char* family_name;
885
886
887 family_name = cff_index_get_sid_string( cff, dict->family_name );
888 if ( family_name )
889 cffface->family_name = cff_strcpy( memory, family_name );
890 }
891
892 if ( !cffface->family_name )
893 {
894 cffface->family_name = cff_index_get_name(
895 cff,
896 (FT_UInt)( face_index & 0xFFFF ) );
897 if ( cffface->family_name )
898 remove_subset_prefix( cffface->family_name );
899 }
900
901 if ( cffface->family_name )
902 {
903 char* full = cff_index_get_sid_string( cff,
904 dict->full_name );
905 char* fullp = full;
906 char* family = cffface->family_name;
907
908
909 /* We try to extract the style name from the full name. */
910 /* We need to ignore spaces and dashes during the search. */
911 if ( full && family )
912 {
913 while ( *fullp )
914 {
915 /* skip common characters at the start of both strings */
916 if ( *fullp == *family )
917 {
918 family++;
919 fullp++;
920 continue;
921 }
922
923 /* ignore spaces and dashes in full name during comparison */
924 if ( *fullp == ' ' || *fullp == '-' )
925 {
926 fullp++;
927 continue;
928 }
929
930 /* ignore spaces and dashes in family name during comparison */
931 if ( *family == ' ' || *family == '-' )
932 {
933 family++;
934 continue;
935 }
936
937 if ( !*family && *fullp )
938 {
939 /* The full name begins with the same characters as the */
940 /* family name, with spaces and dashes removed. In this */
941 /* case, the remaining string in `fullp' will be used as */
942 /* the style name. */
943 style_name = cff_strcpy( memory, fullp );
944
945 /* remove the style part from the family name (if present) */
946 if ( style_name )
947 remove_style( cffface->family_name, style_name );
948 }
949 break;
950 }
951 }
952 }
953 else
954 {
955 char *cid_font_name =
956 cff_index_get_sid_string( cff,
957 dict->cid_font_name );
958
959
960 /* do we have a `/FontName' for a CID-keyed font? */
961 if ( cid_font_name )
962 cffface->family_name = cff_strcpy( memory, cid_font_name );
963 }
964
965 if ( style_name )
966 cffface->style_name = style_name;
967 else
968 /* assume "Regular" style if we don't know better */
969 cffface->style_name = cff_strcpy( memory, "Regular" );
970
971 /********************************************************************
972 *
973 * Compute face flags.
974 */
975 flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */
976 FT_FACE_FLAG_HORIZONTAL | /* horizontal data */
977 FT_FACE_FLAG_HINTER; /* has native hinter */
978
979 if ( sfnt_format )
980 flags |= FT_FACE_FLAG_SFNT;
981
982 /* fixed width font? */
983 if ( dict->is_fixed_pitch )
984 flags |= FT_FACE_FLAG_FIXED_WIDTH;
985
986 /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
987#if 0
988 /* kerning available? */
989 if ( face->kern_pairs )
990 flags |= FT_FACE_FLAG_KERNING;
991#endif
992
993 cffface->face_flags |= flags;
994
995 /********************************************************************
996 *
997 * Compute style flags.
998 */
999 flags = 0;
1000
1001 if ( dict->italic_angle )
1002 flags |= FT_STYLE_FLAG_ITALIC;
1003
1004 {
1005 char *weight = cff_index_get_sid_string( cff,
1006 dict->weight );
1007
1008
1009 if ( weight )
1010 if ( !ft_strcmp( weight, "Bold" ) ||
1011 !ft_strcmp( weight, "Black" ) )
1012 flags |= FT_STYLE_FLAG_BOLD;
1013 }
1014
1015 /* double check */
1016 if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name )
1017 if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) ||
1018 !ft_strncmp( cffface->style_name, "Black", 5 ) )
1019 flags |= FT_STYLE_FLAG_BOLD;
1020
1021 cffface->style_flags = flags;
1022 }
1023
1024 /* CID-keyed CFF or CFF2 fonts don't have glyph names -- the SFNT */
1025 /* loader has unset this flag because of the 3.0 `post' table. */
1026 if ( dict->cid_registry == 0xFFFFU && !cff2 )
1027 cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
1028
1029 if ( dict->cid_registry != 0xFFFFU && pure_cff )
1030 cffface->face_flags |= FT_FACE_FLAG_CID_KEYED;
1031
1032 /********************************************************************
1033 *
1034 * Compute char maps.
1035 */
1036
1037 /* Try to synthesize a Unicode charmap if there is none available */
1038 /* already. If an OpenType font contains a Unicode "cmap", we */
1039 /* will use it, whatever be in the CFF part of the file. */
1040 {
1041 FT_CharMapRec cmaprec;
1042 FT_CharMap cmap;
1043 FT_Int nn;
1044 CFF_Encoding encoding = &cff->encoding;
1045
1046
1047 for ( nn = 0; nn < cffface->num_charmaps; nn++ )
1048 {
1049 cmap = cffface->charmaps[nn];
1050
1051 /* Windows Unicode? */
1052 if ( cmap->platform_id == TT_PLATFORM_MICROSOFT &&
1053 cmap->encoding_id == TT_MS_ID_UNICODE_CS )
1054 goto Skip_Unicode;
1055
1056 /* Apple Unicode platform id? */
1057 if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE )
1058 goto Skip_Unicode; /* Apple Unicode */
1059 }
1060
1061 /* since CID-keyed fonts don't contain glyph names, we can't */
1062 /* construct a cmap */
1063 if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
1064 goto Exit;
1065
1066 /* we didn't find a Unicode charmap -- synthesize one */
1067 cmaprec.face = cffface;
1068 cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
1069 cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;
1070 cmaprec.encoding = FT_ENCODING_UNICODE;
1071
1072 nn = cffface->num_charmaps;
1073
1074 error = FT_CMap_New( &cff_cmap_unicode_class_rec, NULL,
1075 &cmaprec, NULL );
1076 if ( error &&
1077 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
1078 FT_ERR_NEQ( error, Unimplemented_Feature ) )
1079 goto Exit;
1080 error = FT_Err_Ok;
1081
1082 /* if no Unicode charmap was previously selected, select this one */
1083 if ( !cffface->charmap && nn != cffface->num_charmaps )
1084 cffface->charmap = cffface->charmaps[nn];
1085
1086 Skip_Unicode:
1087 if ( encoding->count > 0 )
1088 {
1089 FT_CMap_Class clazz;
1090
1091
1092 cmaprec.face = cffface;
1093 cmaprec.platform_id = TT_PLATFORM_ADOBE; /* Adobe platform id */
1094
1095 if ( encoding->offset == 0 )
1096 {
1097 cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
1098 cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD;
1099 clazz = &cff_cmap_encoding_class_rec;
1100 }
1101 else if ( encoding->offset == 1 )
1102 {
1103 cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
1104 cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT;
1105 clazz = &cff_cmap_encoding_class_rec;
1106 }
1107 else
1108 {
1109 cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
1110 cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM;
1111 clazz = &cff_cmap_encoding_class_rec;
1112 }
1113
1114 error = FT_CMap_New( clazz, NULL, &cmaprec, NULL );
1115 }
1116 }
1117 }
1118
1119 Exit:
1120 return error;
1121 }
1122
1123
1124 FT_LOCAL_DEF( void )
1125 cff_face_done( FT_Face cffface ) /* CFF_Face */
1126 {
1127 CFF_Face face = (CFF_Face)cffface;
1128 FT_Memory memory;
1129 SFNT_Service sfnt;
1130
1131
1132 if ( !face )
1133 return;
1134
1135 memory = cffface->memory;
1136 sfnt = (SFNT_Service)face->sfnt;
1137
1138 if ( sfnt )
1139 sfnt->done_face( face );
1140
1141 {
1142 CFF_Font cff = (CFF_Font)face->extra.data;
1143
1144
1145 if ( cff )
1146 {
1147 cff_font_done( cff );
1148 FT_FREE( face->extra.data );
1149 }
1150 }
1151
1152#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1153 cff_done_blend( cffface );
1154 face->blend = NULL;
1155#endif
1156 }
1157
1158
1159 FT_LOCAL_DEF( FT_Error )
1160 cff_driver_init( FT_Module module ) /* CFF_Driver */
1161 {
1162 PS_Driver driver = (PS_Driver)module;
1163
1164 FT_UInt32 seed;
1165
1166
1167 /* set default property values, cf. `ftcffdrv.h' */
1168 driver->hinting_engine = FT_HINTING_ADOBE;
1169
1170 driver->no_stem_darkening = TRUE;
1171
1172 driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
1173 driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
1174 driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
1175 driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
1176 driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
1177 driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
1178 driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
1179 driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
1180
1181 /* compute random seed from some memory addresses */
1182 seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^
1183 (FT_Offset)(char*)&module ^
1184 (FT_Offset)(char*)module->memory );
1185 seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
1186
1187 driver->random_seed = (FT_Int32)seed;
1188 if ( driver->random_seed < 0 )
1189 driver->random_seed = -driver->random_seed;
1190 else if ( driver->random_seed == 0 )
1191 driver->random_seed = 123456789;
1192
1193 return FT_Err_Ok;
1194 }
1195
1196
1197 FT_LOCAL_DEF( void )
1198 cff_driver_done( FT_Module module ) /* CFF_Driver */
1199 {
1200 FT_UNUSED( module );
1201 }
1202
1203
1204/* END */
1205