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