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