1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* t1objs.c */ |
|
4 /* */ |
|
5 /* Type 1 objects manager (body). */ |
|
6 /* */ |
|
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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_CALC_H |
|
21 #include FT_INTERNAL_DEBUG_H |
|
22 #include FT_INTERNAL_STREAM_H |
|
23 #include FT_TRUETYPE_IDS_H |
|
24 |
|
25 #include "t1gload.h" |
|
26 #include "t1load.h" |
|
27 |
|
28 #include "t1errors.h" |
|
29 |
|
30 #ifndef T1_CONFIG_OPTION_NO_AFM |
|
31 #include "t1afm.h" |
|
32 #endif |
|
33 |
|
34 #include FT_SERVICE_POSTSCRIPT_CMAPS_H |
|
35 #include FT_INTERNAL_POSTSCRIPT_AUX_H |
|
36 |
|
37 |
|
38 /*************************************************************************/ |
|
39 /* */ |
|
40 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
|
41 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
|
42 /* messages during execution. */ |
|
43 /* */ |
|
44 #undef FT_COMPONENT |
|
45 #define FT_COMPONENT trace_t1objs |
|
46 |
|
47 |
|
48 /*************************************************************************/ |
|
49 /* */ |
|
50 /* SIZE FUNCTIONS */ |
|
51 /* */ |
|
52 /* note that we store the global hints in the size's "internal" root */ |
|
53 /* field */ |
|
54 /* */ |
|
55 /*************************************************************************/ |
|
56 |
|
57 |
|
58 static PSH_Globals_Funcs |
|
59 T1_Size_Get_Globals_Funcs( T1_Size size ) |
|
60 { |
|
61 T1_Face face = (T1_Face)size->root.face; |
|
62 PSHinter_Service pshinter = (PSHinter_Service)face->pshinter; |
|
63 FT_Module module; |
|
64 |
|
65 |
|
66 module = FT_Get_Module( size->root.face->driver->root.library, |
|
67 "pshinter" ); |
|
68 return ( module && pshinter && pshinter->get_globals_funcs ) |
|
69 ? pshinter->get_globals_funcs( module ) |
|
70 : 0 ; |
|
71 } |
|
72 |
|
73 |
|
74 FT_LOCAL_DEF( void ) |
|
75 T1_Size_Done( T1_Size size ) |
|
76 { |
|
77 if ( size->root.internal ) |
|
78 { |
|
79 PSH_Globals_Funcs funcs; |
|
80 |
|
81 |
|
82 funcs = T1_Size_Get_Globals_Funcs( size ); |
|
83 if ( funcs ) |
|
84 funcs->destroy( (PSH_Globals)size->root.internal ); |
|
85 |
|
86 size->root.internal = 0; |
|
87 } |
|
88 } |
|
89 |
|
90 |
|
91 FT_LOCAL_DEF( FT_Error ) |
|
92 T1_Size_Init( T1_Size size ) |
|
93 { |
|
94 FT_Error error = T1_Err_Ok; |
|
95 PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size ); |
|
96 |
|
97 |
|
98 if ( funcs ) |
|
99 { |
|
100 PSH_Globals globals; |
|
101 T1_Face face = (T1_Face)size->root.face; |
|
102 |
|
103 |
|
104 error = funcs->create( size->root.face->memory, |
|
105 &face->type1.private_dict, &globals ); |
|
106 if ( !error ) |
|
107 size->root.internal = (FT_Size_Internal)(void*)globals; |
|
108 } |
|
109 |
|
110 return error; |
|
111 } |
|
112 |
|
113 |
|
114 FT_LOCAL_DEF( FT_Error ) |
|
115 T1_Size_Request( T1_Size size, |
|
116 FT_Size_Request req ) |
|
117 { |
|
118 PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size ); |
|
119 |
|
120 |
|
121 FT_Request_Metrics( size->root.face, req ); |
|
122 |
|
123 if ( funcs ) |
|
124 funcs->set_scale( (PSH_Globals)size->root.internal, |
|
125 size->root.metrics.x_scale, |
|
126 size->root.metrics.y_scale, |
|
127 0, 0 ); |
|
128 |
|
129 return T1_Err_Ok; |
|
130 } |
|
131 |
|
132 |
|
133 /*************************************************************************/ |
|
134 /* */ |
|
135 /* SLOT FUNCTIONS */ |
|
136 /* */ |
|
137 /*************************************************************************/ |
|
138 |
|
139 FT_LOCAL_DEF( void ) |
|
140 T1_GlyphSlot_Done( T1_GlyphSlot slot ) |
|
141 { |
|
142 slot->root.internal->glyph_hints = 0; |
|
143 } |
|
144 |
|
145 |
|
146 FT_LOCAL_DEF( FT_Error ) |
|
147 T1_GlyphSlot_Init( T1_GlyphSlot slot ) |
|
148 { |
|
149 T1_Face face; |
|
150 PSHinter_Service pshinter; |
|
151 |
|
152 |
|
153 face = (T1_Face)slot->root.face; |
|
154 pshinter = (PSHinter_Service)face->pshinter; |
|
155 |
|
156 if ( pshinter ) |
|
157 { |
|
158 FT_Module module; |
|
159 |
|
160 |
|
161 module = FT_Get_Module( slot->root.face->driver->root.library, "pshinter" ); |
|
162 if (module) |
|
163 { |
|
164 T1_Hints_Funcs funcs; |
|
165 |
|
166 funcs = pshinter->get_t1_funcs( module ); |
|
167 slot->root.internal->glyph_hints = (void*)funcs; |
|
168 } |
|
169 } |
|
170 return 0; |
|
171 } |
|
172 |
|
173 |
|
174 /*************************************************************************/ |
|
175 /* */ |
|
176 /* FACE FUNCTIONS */ |
|
177 /* */ |
|
178 /*************************************************************************/ |
|
179 |
|
180 |
|
181 /*************************************************************************/ |
|
182 /* */ |
|
183 /* <Function> */ |
|
184 /* T1_Face_Done */ |
|
185 /* */ |
|
186 /* <Description> */ |
|
187 /* The face object destructor. */ |
|
188 /* */ |
|
189 /* <Input> */ |
|
190 /* face :: A typeless pointer to the face object to destroy. */ |
|
191 /* */ |
|
192 FT_LOCAL_DEF( void ) |
|
193 T1_Face_Done( T1_Face face ) |
|
194 { |
|
195 FT_Memory memory; |
|
196 T1_Font type1; |
|
197 |
|
198 |
|
199 if ( !face ) |
|
200 return; |
|
201 |
|
202 memory = face->root.memory; |
|
203 type1 = &face->type1; |
|
204 |
|
205 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
|
206 /* release multiple masters information */ |
|
207 FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); |
|
208 |
|
209 if ( face->buildchar ) |
|
210 { |
|
211 FT_FREE( face->buildchar ); |
|
212 |
|
213 face->buildchar = NULL; |
|
214 face->len_buildchar = 0; |
|
215 } |
|
216 |
|
217 T1_Done_Blend( face ); |
|
218 face->blend = 0; |
|
219 #endif |
|
220 |
|
221 /* release font info strings */ |
|
222 { |
|
223 PS_FontInfo info = &type1->font_info; |
|
224 |
|
225 |
|
226 FT_FREE( info->version ); |
|
227 FT_FREE( info->notice ); |
|
228 FT_FREE( info->full_name ); |
|
229 FT_FREE( info->family_name ); |
|
230 FT_FREE( info->weight ); |
|
231 } |
|
232 |
|
233 /* release top dictionary */ |
|
234 FT_FREE( type1->charstrings_len ); |
|
235 FT_FREE( type1->charstrings ); |
|
236 FT_FREE( type1->glyph_names ); |
|
237 |
|
238 FT_FREE( type1->subrs ); |
|
239 FT_FREE( type1->subrs_len ); |
|
240 |
|
241 FT_FREE( type1->subrs_block ); |
|
242 FT_FREE( type1->charstrings_block ); |
|
243 FT_FREE( type1->glyph_names_block ); |
|
244 |
|
245 FT_FREE( type1->encoding.char_index ); |
|
246 FT_FREE( type1->encoding.char_name ); |
|
247 FT_FREE( type1->font_name ); |
|
248 |
|
249 #ifndef T1_CONFIG_OPTION_NO_AFM |
|
250 /* release afm data if present */ |
|
251 if ( face->afm_data ) |
|
252 T1_Done_Metrics( memory, (AFM_FontInfo)face->afm_data ); |
|
253 #endif |
|
254 |
|
255 /* release unicode map, if any */ |
|
256 #if 0 |
|
257 FT_FREE( face->unicode_map_rec.maps ); |
|
258 face->unicode_map_rec.num_maps = 0; |
|
259 face->unicode_map = NULL; |
|
260 #endif |
|
261 |
|
262 face->root.family_name = NULL; |
|
263 face->root.style_name = NULL; |
|
264 } |
|
265 |
|
266 |
|
267 /*************************************************************************/ |
|
268 /* */ |
|
269 /* <Function> */ |
|
270 /* T1_Face_Init */ |
|
271 /* */ |
|
272 /* <Description> */ |
|
273 /* The face object constructor. */ |
|
274 /* */ |
|
275 /* <Input> */ |
|
276 /* stream :: input stream where to load font data. */ |
|
277 /* */ |
|
278 /* face_index :: The index of the font face in the resource. */ |
|
279 /* */ |
|
280 /* num_params :: Number of additional generic parameters. Ignored. */ |
|
281 /* */ |
|
282 /* params :: Additional generic parameters. Ignored. */ |
|
283 /* */ |
|
284 /* <InOut> */ |
|
285 /* face :: The face record to build. */ |
|
286 /* */ |
|
287 /* <Return> */ |
|
288 /* FreeType error code. 0 means success. */ |
|
289 /* */ |
|
290 FT_LOCAL_DEF( FT_Error ) |
|
291 T1_Face_Init( FT_Stream stream, |
|
292 T1_Face face, |
|
293 FT_Int face_index, |
|
294 FT_Int num_params, |
|
295 FT_Parameter* params ) |
|
296 { |
|
297 FT_Error error; |
|
298 FT_Service_PsCMaps psnames; |
|
299 PSAux_Service psaux; |
|
300 T1_Font type1 = &face->type1; |
|
301 PS_FontInfo info = &type1->font_info; |
|
302 |
|
303 FT_UNUSED( num_params ); |
|
304 FT_UNUSED( params ); |
|
305 FT_UNUSED( stream ); |
|
306 |
|
307 |
|
308 face->root.num_faces = 1; |
|
309 |
|
310 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); |
|
311 face->psnames = psnames; |
|
312 |
|
313 face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), |
|
314 "psaux" ); |
|
315 psaux = (PSAux_Service)face->psaux; |
|
316 |
|
317 face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), |
|
318 "pshinter" ); |
|
319 |
|
320 /* open the tokenizer; this will also check the font format */ |
|
321 error = T1_Open_Face( face ); |
|
322 if ( error ) |
|
323 goto Exit; |
|
324 |
|
325 /* if we just wanted to check the format, leave successfully now */ |
|
326 if ( face_index < 0 ) |
|
327 goto Exit; |
|
328 |
|
329 /* check the face index */ |
|
330 if ( face_index > 0 ) |
|
331 { |
|
332 FT_ERROR(( "T1_Face_Init: invalid face index\n" )); |
|
333 error = T1_Err_Invalid_Argument; |
|
334 goto Exit; |
|
335 } |
|
336 |
|
337 /* now load the font program into the face object */ |
|
338 |
|
339 /* initialize the face object fields */ |
|
340 |
|
341 /* set up root face fields */ |
|
342 { |
|
343 FT_Face root = (FT_Face)&face->root; |
|
344 |
|
345 |
|
346 root->num_glyphs = type1->num_glyphs; |
|
347 root->face_index = 0; |
|
348 |
|
349 root->face_flags = FT_FACE_FLAG_SCALABLE | |
|
350 FT_FACE_FLAG_HORIZONTAL | |
|
351 FT_FACE_FLAG_GLYPH_NAMES | |
|
352 FT_FACE_FLAG_HINTER; |
|
353 |
|
354 if ( info->is_fixed_pitch ) |
|
355 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; |
|
356 |
|
357 if ( face->blend ) |
|
358 root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; |
|
359 |
|
360 /* XXX: TODO -- add kerning with .afm support */ |
|
361 |
|
362 |
|
363 /* The following code to extract the family and the style is very */ |
|
364 /* simplistic and might get some things wrong. For a full-featured */ |
|
365 /* algorithm you might have a look at the whitepaper given at */ |
|
366 /* */ |
|
367 /* http://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */ |
|
368 |
|
369 /* get style name -- be careful, some broken fonts only */ |
|
370 /* have a `/FontName' dictionary entry! */ |
|
371 root->family_name = info->family_name; |
|
372 root->style_name = NULL; |
|
373 |
|
374 if ( root->family_name ) |
|
375 { |
|
376 char* full = info->full_name; |
|
377 char* family = root->family_name; |
|
378 |
|
379 |
|
380 if ( full ) |
|
381 { |
|
382 FT_Bool the_same = TRUE; |
|
383 |
|
384 |
|
385 while ( *full ) |
|
386 { |
|
387 if ( *full == *family ) |
|
388 { |
|
389 family++; |
|
390 full++; |
|
391 } |
|
392 else |
|
393 { |
|
394 if ( *full == ' ' || *full == '-' ) |
|
395 full++; |
|
396 else if ( *family == ' ' || *family == '-' ) |
|
397 family++; |
|
398 else |
|
399 { |
|
400 the_same = FALSE; |
|
401 |
|
402 if ( !*family ) |
|
403 root->style_name = full; |
|
404 break; |
|
405 } |
|
406 } |
|
407 } |
|
408 |
|
409 if ( the_same ) |
|
410 root->style_name = (char *)"Regular"; |
|
411 } |
|
412 } |
|
413 else |
|
414 { |
|
415 /* do we have a `/FontName'? */ |
|
416 if ( type1->font_name ) |
|
417 root->family_name = type1->font_name; |
|
418 } |
|
419 |
|
420 if ( !root->style_name ) |
|
421 { |
|
422 if ( info->weight ) |
|
423 root->style_name = info->weight; |
|
424 else |
|
425 /* assume `Regular' style because we don't know better */ |
|
426 root->style_name = (char *)"Regular"; |
|
427 } |
|
428 |
|
429 /* compute style flags */ |
|
430 root->style_flags = 0; |
|
431 if ( info->italic_angle ) |
|
432 root->style_flags |= FT_STYLE_FLAG_ITALIC; |
|
433 if ( info->weight ) |
|
434 { |
|
435 if ( !ft_strcmp( info->weight, "Bold" ) || |
|
436 !ft_strcmp( info->weight, "Black" ) ) |
|
437 root->style_flags |= FT_STYLE_FLAG_BOLD; |
|
438 } |
|
439 |
|
440 /* no embedded bitmap support */ |
|
441 root->num_fixed_sizes = 0; |
|
442 root->available_sizes = 0; |
|
443 |
|
444 root->bbox.xMin = type1->font_bbox.xMin >> 16; |
|
445 root->bbox.yMin = type1->font_bbox.yMin >> 16; |
|
446 /* no `U' suffix here to 0xFFFF! */ |
|
447 root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16; |
|
448 root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16; |
|
449 |
|
450 /* Set units_per_EM if we didn't set it in parse_font_matrix. */ |
|
451 if ( !root->units_per_EM ) |
|
452 root->units_per_EM = 1000; |
|
453 |
|
454 root->ascender = (FT_Short)( root->bbox.yMax ); |
|
455 root->descender = (FT_Short)( root->bbox.yMin ); |
|
456 |
|
457 root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 ); |
|
458 if ( root->height < root->ascender - root->descender ) |
|
459 root->height = (FT_Short)( root->ascender - root->descender ); |
|
460 |
|
461 /* now compute the maximum advance width */ |
|
462 root->max_advance_width = |
|
463 (FT_Short)( root->bbox.xMax ); |
|
464 { |
|
465 FT_Pos max_advance; |
|
466 |
|
467 |
|
468 error = T1_Compute_Max_Advance( face, &max_advance ); |
|
469 |
|
470 /* in case of error, keep the standard width */ |
|
471 if ( !error ) |
|
472 root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance ); |
|
473 else |
|
474 error = T1_Err_Ok; /* clear error */ |
|
475 } |
|
476 |
|
477 root->max_advance_height = root->height; |
|
478 |
|
479 root->underline_position = (FT_Short)info->underline_position; |
|
480 root->underline_thickness = (FT_Short)info->underline_thickness; |
|
481 } |
|
482 |
|
483 { |
|
484 FT_Face root = &face->root; |
|
485 |
|
486 |
|
487 if ( psnames && psaux ) |
|
488 { |
|
489 FT_CharMapRec charmap; |
|
490 T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; |
|
491 FT_CMap_Class clazz; |
|
492 |
|
493 |
|
494 charmap.face = root; |
|
495 |
|
496 /* first of all, try to synthesize a Unicode charmap */ |
|
497 charmap.platform_id = TT_PLATFORM_MICROSOFT; |
|
498 charmap.encoding_id = TT_MS_ID_UNICODE_CS; |
|
499 charmap.encoding = FT_ENCODING_UNICODE; |
|
500 |
|
501 error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); |
|
502 if ( error && FT_Err_No_Unicode_Glyph_Name != error ) |
|
503 goto Exit; |
|
504 error = FT_Err_Ok; |
|
505 |
|
506 /* now, generate an Adobe Standard encoding when appropriate */ |
|
507 charmap.platform_id = TT_PLATFORM_ADOBE; |
|
508 clazz = NULL; |
|
509 |
|
510 switch ( type1->encoding_type ) |
|
511 { |
|
512 case T1_ENCODING_TYPE_STANDARD: |
|
513 charmap.encoding = FT_ENCODING_ADOBE_STANDARD; |
|
514 charmap.encoding_id = TT_ADOBE_ID_STANDARD; |
|
515 clazz = cmap_classes->standard; |
|
516 break; |
|
517 |
|
518 case T1_ENCODING_TYPE_EXPERT: |
|
519 charmap.encoding = FT_ENCODING_ADOBE_EXPERT; |
|
520 charmap.encoding_id = TT_ADOBE_ID_EXPERT; |
|
521 clazz = cmap_classes->expert; |
|
522 break; |
|
523 |
|
524 case T1_ENCODING_TYPE_ARRAY: |
|
525 charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; |
|
526 charmap.encoding_id = TT_ADOBE_ID_CUSTOM; |
|
527 clazz = cmap_classes->custom; |
|
528 break; |
|
529 |
|
530 case T1_ENCODING_TYPE_ISOLATIN1: |
|
531 charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; |
|
532 charmap.encoding_id = TT_ADOBE_ID_LATIN_1; |
|
533 clazz = cmap_classes->unicode; |
|
534 break; |
|
535 |
|
536 default: |
|
537 ; |
|
538 } |
|
539 |
|
540 if ( clazz ) |
|
541 error = FT_CMap_New( clazz, NULL, &charmap, NULL ); |
|
542 |
|
543 #if 0 |
|
544 /* Select default charmap */ |
|
545 if (root->num_charmaps) |
|
546 root->charmap = root->charmaps[0]; |
|
547 #endif |
|
548 } |
|
549 } |
|
550 |
|
551 Exit: |
|
552 return error; |
|
553 } |
|
554 |
|
555 |
|
556 /*************************************************************************/ |
|
557 /* */ |
|
558 /* <Function> */ |
|
559 /* T1_Driver_Init */ |
|
560 /* */ |
|
561 /* <Description> */ |
|
562 /* Initializes a given Type 1 driver object. */ |
|
563 /* */ |
|
564 /* <Input> */ |
|
565 /* driver :: A handle to the target driver object. */ |
|
566 /* */ |
|
567 /* <Return> */ |
|
568 /* FreeType error code. 0 means success. */ |
|
569 /* */ |
|
570 FT_LOCAL_DEF( FT_Error ) |
|
571 T1_Driver_Init( T1_Driver driver ) |
|
572 { |
|
573 FT_UNUSED( driver ); |
|
574 |
|
575 return T1_Err_Ok; |
|
576 } |
|
577 |
|
578 |
|
579 /*************************************************************************/ |
|
580 /* */ |
|
581 /* <Function> */ |
|
582 /* T1_Driver_Done */ |
|
583 /* */ |
|
584 /* <Description> */ |
|
585 /* Finalizes a given Type 1 driver. */ |
|
586 /* */ |
|
587 /* <Input> */ |
|
588 /* driver :: A handle to the target Type 1 driver. */ |
|
589 /* */ |
|
590 FT_LOCAL_DEF( void ) |
|
591 T1_Driver_Done( T1_Driver driver ) |
|
592 { |
|
593 FT_UNUSED( driver ); |
|
594 } |
|
595 |
|
596 |
|
597 /* END */ |
|