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