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