]>
Commit | Line | Data |
---|---|---|
cabec872 RR |
1 | /***************************************************************************/ |
2 | /* */ | |
3 | /* t1objs.c */ | |
4 | /* */ | |
5 | /* Type 1 objects manager (body). */ | |
6 | /* */ | |
7 | /* Copyright 1996-2000 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 <freetype/internal/ftdebug.h> | |
20 | #include <freetype/internal/ftstream.h> | |
21 | ||
22 | ||
23 | #ifdef FT_FLAT_COMPILE | |
24 | ||
25 | #include "t1gload.h" | |
26 | #include "t1load.h" | |
27 | #include "t1afm.h" | |
28 | ||
29 | #ifndef T1_CONFIG_OPTION_DISABLE_HINTER | |
30 | #include "t1hinter.h" | |
31 | #endif | |
32 | ||
33 | #else /* FT_FLAT_COMPILE */ | |
34 | ||
35 | #include <type1/t1gload.h> | |
36 | #include <type1/t1load.h> | |
37 | #include <type1/t1afm.h> | |
38 | ||
39 | #ifndef T1_CONFIG_OPTION_DISABLE_HINTER | |
40 | #include <type1/t1hinter.h> | |
41 | #endif | |
42 | ||
43 | #endif /* FT_FLAT_COMPILE */ | |
44 | ||
45 | ||
46 | #include <freetype/internal/psnames.h> | |
47 | ||
48 | ||
49 | /*************************************************************************/ | |
50 | /* */ | |
51 | /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | |
52 | /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | |
53 | /* messages during execution. */ | |
54 | /* */ | |
55 | #undef FT_COMPONENT | |
56 | #define FT_COMPONENT trace_t1objs | |
57 | ||
58 | ||
59 | /*************************************************************************/ | |
60 | /* */ | |
61 | /* SIZE FUNCTIONS */ | |
62 | /* */ | |
63 | /*************************************************************************/ | |
64 | ||
65 | ||
66 | /*************************************************************************/ | |
67 | /* */ | |
68 | /* <Function> */ | |
69 | /* T1_Done_Size */ | |
70 | /* */ | |
71 | /* <Description> */ | |
72 | /* The Type 1 size object destructor. Used to discard a given size */ | |
73 | /* object. */ | |
74 | /* */ | |
75 | /* <Input> */ | |
76 | /* size :: A handle to the target size object. */ | |
77 | /* */ | |
78 | LOCAL_FUNC | |
79 | void T1_Done_Size( T1_Size size ) | |
80 | { | |
81 | if ( size ) | |
82 | { | |
83 | ||
84 | #ifndef T1_CONFIG_OPTION_DISABLE_HINTER | |
85 | T1_Done_Size_Hinter( size ); | |
86 | #endif | |
87 | ||
88 | size->valid = 0; | |
89 | } | |
90 | } | |
91 | ||
92 | ||
93 | /*************************************************************************/ | |
94 | /* */ | |
95 | /* <Function> */ | |
96 | /* T1_Init_Size */ | |
97 | /* */ | |
98 | /* <Description> */ | |
99 | /* The size object initializer. */ | |
100 | /* */ | |
101 | /* <Input> */ | |
102 | /* size :: A handle to the target size object. */ | |
103 | /* */ | |
104 | /* <Return> */ | |
105 | /* FreeTrue error code. 0 means success. */ | |
106 | /* */ | |
107 | LOCAL_DEF | |
108 | FT_Error T1_Init_Size( T1_Size size ) | |
109 | { | |
110 | FT_Error error; | |
111 | ||
112 | ||
113 | size->valid = 0; | |
114 | ||
115 | #ifndef T1_CONFIG_OPTION_DISABLE_HINTER | |
116 | error = T1_New_Size_Hinter( size ); | |
117 | ||
118 | return error; | |
119 | #else | |
120 | ||
121 | FT_UNUSED( error ); | |
122 | ||
123 | return T1_Err_Ok; | |
124 | ||
125 | #endif | |
126 | } | |
127 | ||
128 | ||
129 | /*************************************************************************/ | |
130 | /* */ | |
131 | /* <Function> */ | |
132 | /* T1_Reset_Size */ | |
133 | /* */ | |
134 | /* <Description> */ | |
135 | /* Resets an instance to a new pointsize/transform. This function is */ | |
136 | /* in charge of resetting the blue zones,a s well as the stem snap */ | |
137 | /* tables for a given size. */ | |
138 | /* */ | |
139 | /* <Input> */ | |
140 | /* size :: The target size object. */ | |
141 | /* */ | |
142 | /* <Output> */ | |
143 | /* FreeType error code. 0 means success. */ | |
144 | /* */ | |
145 | LOCAL_FUNC | |
146 | FT_Error T1_Reset_Size( T1_Size size ) | |
147 | { | |
148 | /* recompute ascender, descender, etc. */ | |
149 | T1_Face face = (T1_Face)size->root.face; | |
150 | FT_Size_Metrics* metrics = &size->root.metrics; | |
151 | ||
152 | ||
153 | if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) | |
154 | return FT_Err_Invalid_Argument; | |
155 | ||
156 | /* Compute root ascender, descender, test height, and max_advance */ | |
157 | metrics->ascender = ( FT_MulFix( face->root.ascender, | |
158 | metrics->y_scale ) + 32 ) & -64; | |
159 | metrics->descender = ( FT_MulFix( face->root.descender, | |
160 | metrics->y_scale ) + 32 ) & -64; | |
161 | metrics->height = ( FT_MulFix( face->root.height, | |
162 | metrics->y_scale ) + 32 ) & -64; | |
163 | metrics->max_advance = ( FT_MulFix( face->root.max_advance_width, | |
164 | metrics->x_scale ) + 32 ) & -64; | |
165 | ||
166 | #ifndef T1_CONFIG_OPTION_DISABLE_HINTER | |
167 | return T1_Reset_Size_Hinter( size ); | |
168 | #else | |
169 | return 0; | |
170 | #endif | |
171 | } | |
172 | ||
173 | ||
174 | /*************************************************************************/ | |
175 | /* */ | |
176 | /* FACE FUNCTIONS */ | |
177 | /* */ | |
178 | /*************************************************************************/ | |
179 | ||
180 | ||
181 | /*************************************************************************/ | |
182 | /* */ | |
183 | /* <Function> */ | |
184 | /* T1_Done_Face */ | |
185 | /* */ | |
186 | /* <Description> */ | |
187 | /* The face object destructor. */ | |
188 | /* */ | |
189 | /* <Input> */ | |
190 | /* face :: A typeless pointer to the face object to destroy. */ | |
191 | /* */ | |
192 | LOCAL_FUNC | |
193 | void T1_Done_Face( T1_Face face ) | |
194 | { | |
195 | FT_Memory memory; | |
196 | T1_Font* type1 = &face->type1; | |
197 | ||
198 | ||
199 | if ( face ) | |
200 | { | |
201 | memory = face->root.memory; | |
202 | ||
203 | /* release font info strings */ | |
204 | { | |
205 | T1_FontInfo* info = &type1->font_info; | |
206 | ||
207 | ||
208 | FREE( info->version ); | |
209 | FREE( info->notice ); | |
210 | FREE( info->full_name ); | |
211 | FREE( info->family_name ); | |
212 | FREE( info->weight ); | |
213 | } | |
214 | ||
215 | /* release top dictionary */ | |
216 | FREE( type1->charstrings_len ); | |
217 | FREE( type1->charstrings ); | |
218 | FREE( type1->glyph_names ); | |
219 | ||
220 | FREE( type1->subrs ); | |
221 | FREE( type1->subrs_len ); | |
222 | ||
223 | FREE( type1->subrs_block ); | |
224 | FREE( type1->charstrings_block ); | |
225 | FREE( type1->glyph_names_block ); | |
226 | ||
227 | FREE( type1->encoding.char_index ); | |
228 | FREE( type1->font_name ); | |
229 | ||
230 | #ifndef T1_CONFIG_OPTION_NO_AFM | |
231 | /* release afm data if present */ | |
232 | if ( face->afm_data ) | |
233 | T1_Done_AFM( memory, (T1_AFM*)face->afm_data ); | |
234 | #endif | |
235 | ||
236 | /* release unicode map, if any */ | |
237 | FREE( face->unicode_map.maps ); | |
238 | face->unicode_map.num_maps = 0; | |
239 | ||
240 | face->root.family_name = 0; | |
241 | face->root.style_name = 0; | |
242 | } | |
243 | } | |
244 | ||
245 | ||
246 | /*************************************************************************/ | |
247 | /* */ | |
248 | /* <Function> */ | |
249 | /* T1_Init_Face */ | |
250 | /* */ | |
251 | /* <Description> */ | |
252 | /* The face object constructor. */ | |
253 | /* */ | |
254 | /* <Input> */ | |
255 | /* stream :: input stream where to load font data. */ | |
256 | /* */ | |
257 | /* face_index :: The index of the font face in the resource. */ | |
258 | /* */ | |
259 | /* num_params :: Number of additional generic parameters. Ignored. */ | |
260 | /* */ | |
261 | /* params :: Additional generic parameters. Ignored. */ | |
262 | /* */ | |
263 | /* <InOut> */ | |
264 | /* face :: The face record to build. */ | |
265 | /* */ | |
266 | /* <Return> */ | |
267 | /* FreeType error code. 0 means success. */ | |
268 | /* */ | |
269 | LOCAL_FUNC | |
270 | FT_Error T1_Init_Face( FT_Stream stream, | |
271 | T1_Face face, | |
272 | FT_Int face_index, | |
273 | FT_Int num_params, | |
274 | FT_Parameter* params ) | |
275 | { | |
276 | T1_Tokenizer tokenizer; | |
277 | FT_Error error; | |
278 | PSNames_Interface* psnames; | |
279 | ||
280 | FT_UNUSED( num_params ); | |
281 | FT_UNUSED( params ); | |
282 | FT_UNUSED( face_index ); | |
283 | FT_UNUSED( face ); | |
284 | ||
285 | ||
286 | face->root.num_faces = 1; | |
287 | ||
288 | psnames = (PSNames_Interface*)face->psnames; | |
289 | if ( !psnames ) | |
290 | { | |
291 | psnames = (PSNames_Interface*) | |
292 | FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), | |
293 | "psnames" ); | |
294 | ||
295 | face->psnames = psnames; | |
296 | } | |
297 | ||
298 | /* open the tokenizer, this will also check the font format */ | |
299 | error = New_Tokenizer( stream, &tokenizer ); | |
300 | if ( error ) | |
301 | goto Fail; | |
302 | ||
303 | /* if we just wanted to check the format, leave successfully now */ | |
304 | if ( face_index < 0 ) | |
305 | goto Leave; | |
306 | ||
307 | /* check the face index */ | |
308 | if ( face_index != 0 ) | |
309 | { | |
310 | FT_ERROR(( "T1_Init_Face: invalid face index\n" )); | |
311 | error = T1_Err_Invalid_Argument; | |
312 | goto Leave; | |
313 | } | |
314 | ||
315 | /* Now, load the font program into the face object */ | |
316 | { | |
317 | T1_Parser parser; | |
318 | ||
319 | ||
320 | Init_T1_Parser( &parser, face, tokenizer ); | |
321 | error = Parse_T1_FontProgram( &parser ); | |
322 | if ( error ) | |
323 | goto Leave; | |
324 | ||
325 | /* Init the face object fields */ | |
326 | /* Now set up root face fields */ | |
327 | { | |
328 | FT_Face root = (FT_Face)&face->root; | |
329 | T1_Font* type1 = &face->type1; | |
330 | ||
331 | ||
332 | root->num_glyphs = type1->num_glyphs; | |
333 | root->num_charmaps = 1; | |
334 | ||
335 | root->face_index = face_index; | |
336 | root->face_flags = FT_FACE_FLAG_SCALABLE; | |
337 | ||
338 | root->face_flags |= FT_FACE_FLAG_HORIZONTAL; | |
339 | ||
340 | root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; | |
341 | ||
342 | if ( type1->font_info.is_fixed_pitch ) | |
343 | root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; | |
344 | ||
345 | /* XXX: TODO -- add kerning with .afm support */ | |
346 | ||
347 | /* get style name - be careful, some broken fonts only */ | |
348 | /* have a `/FontName' dictionary entry! */ | |
349 | root->family_name = type1->font_info.family_name; | |
350 | if ( root->family_name ) | |
351 | { | |
352 | char* full = type1->font_info.full_name; | |
353 | char* family = root->family_name; | |
354 | ||
355 | ||
356 | while ( *family && *full == *family ) | |
357 | { | |
358 | family++; | |
359 | full++; | |
360 | } | |
361 | ||
362 | root->style_name = ( *full == ' ' ? full + 1 | |
363 | : (char *)"Regular" ); | |
364 | } | |
365 | else | |
366 | { | |
367 | /* do we have a `/FontName'? */ | |
368 | if (type1->font_name) | |
369 | { | |
370 | root->family_name = type1->font_name; | |
371 | root->style_name = "Regular"; | |
372 | } | |
373 | } | |
374 | ||
375 | /* no embedded bitmap support */ | |
376 | root->num_fixed_sizes = 0; | |
377 | root->available_sizes = 0; | |
378 | ||
379 | root->bbox = type1->font_bbox; | |
380 | root->units_per_EM = 1000; | |
381 | root->ascender = (FT_Short)type1->font_bbox.yMax; | |
382 | root->descender = -(FT_Short)type1->font_bbox.yMin; | |
383 | root->height = ( ( root->ascender + root->descender) * 12 ) | |
384 | / 10; | |
385 | ||
386 | /* now compute the maximum advance width */ | |
387 | ||
388 | root->max_advance_width = type1->private_dict.standard_width[0]; | |
389 | ||
390 | /* compute max advance width for proportional fonts */ | |
391 | if ( !type1->font_info.is_fixed_pitch ) | |
392 | { | |
393 | FT_Int max_advance; | |
394 | ||
395 | ||
396 | error = T1_Compute_Max_Advance( face, &max_advance ); | |
397 | ||
398 | /* in case of error, keep the standard width */ | |
399 | if ( !error ) | |
400 | root->max_advance_width = max_advance; | |
401 | else | |
402 | error = 0; /* clear error */ | |
403 | } | |
404 | ||
405 | root->max_advance_height = root->height; | |
406 | ||
407 | root->underline_position = type1->font_info.underline_position; | |
408 | root->underline_thickness = type1->font_info.underline_thickness; | |
409 | ||
410 | root->max_points = 0; | |
411 | root->max_contours = 0; | |
412 | } | |
413 | } | |
414 | ||
415 | /* charmap support - synthetize unicode charmap when possible */ | |
416 | { | |
417 | FT_Face root = &face->root; | |
418 | FT_CharMap charmap = face->charmaprecs; | |
419 | ||
420 | ||
421 | /* synthesize a Unicode charmap if there is support in the `PSNames' */ | |
422 | /* module.. */ | |
423 | if ( face->psnames ) | |
424 | { | |
425 | PSNames_Interface* psnames = (PSNames_Interface*)face->psnames; | |
426 | ||
427 | ||
428 | if ( psnames->unicode_value ) | |
429 | { | |
430 | error = psnames->build_unicodes( | |
431 | root->memory, | |
432 | face->type1.num_glyphs, | |
433 | (const char**)face->type1.glyph_names, | |
434 | &face->unicode_map ); | |
435 | if ( !error ) | |
436 | { | |
437 | root->charmap = charmap; | |
438 | charmap->face = (FT_Face)face; | |
439 | charmap->encoding = ft_encoding_unicode; | |
440 | charmap->platform_id = 3; | |
441 | charmap->encoding_id = 1; | |
442 | charmap++; | |
443 | } | |
444 | ||
445 | /* simply clear the error in case of failure (which really) */ | |
446 | /* means that out of memory or no unicode glyph names */ | |
447 | error = 0; | |
448 | } | |
449 | } | |
450 | ||
451 | /* now, support either the standard, expert, or custom encodings */ | |
452 | charmap->face = (FT_Face)face; | |
453 | charmap->platform_id = 7; /* a new platform id for Adobe fonts ?? */ | |
454 | ||
455 | switch ( face->type1.encoding_type ) | |
456 | { | |
457 | case t1_encoding_standard: | |
458 | charmap->encoding = ft_encoding_adobe_standard; | |
459 | charmap->encoding_id = 0; | |
460 | break; | |
461 | ||
462 | case t1_encoding_expert: | |
463 | charmap->encoding = ft_encoding_adobe_expert; | |
464 | charmap->encoding_id = 1; | |
465 | break; | |
466 | ||
467 | default: | |
468 | charmap->encoding = ft_encoding_adobe_custom; | |
469 | charmap->encoding_id = 2; | |
470 | break; | |
471 | } | |
472 | ||
473 | root->charmaps = face->charmaps; | |
474 | root->num_charmaps = charmap - face->charmaprecs + 1; | |
475 | face->charmaps[0] = &face->charmaprecs[0]; | |
476 | face->charmaps[1] = &face->charmaprecs[1]; | |
477 | } | |
478 | ||
479 | Leave: | |
480 | Done_Tokenizer( tokenizer ); | |
481 | ||
482 | Fail: | |
483 | return error; | |
484 | } | |
485 | ||
486 | ||
487 | /*************************************************************************/ | |
488 | /* */ | |
489 | /* <Function> */ | |
490 | /* T1_Done_GlyphSlot */ | |
491 | /* */ | |
492 | /* <Description> */ | |
493 | /* The glyph slot object destructor. */ | |
494 | /* */ | |
495 | /* <Input> */ | |
496 | /* glyph :: The glyph slot handle to destroy. */ | |
497 | /* */ | |
498 | LOCAL_FUNC | |
499 | void T1_Done_GlyphSlot( T1_GlyphSlot glyph ) | |
500 | { | |
501 | #ifndef T1_CONFIG_OPTION_DISABLE_HINTER | |
502 | ||
503 | T1_Done_Glyph_Hinter( glyph ); | |
504 | ||
505 | #else | |
506 | ||
507 | FT_UNUSED( glyph ); | |
508 | ||
509 | #endif | |
510 | } | |
511 | ||
512 | ||
513 | /*************************************************************************/ | |
514 | /* */ | |
515 | /* <Function> */ | |
516 | /* T1_Init_GlyphSlot */ | |
517 | /* */ | |
518 | /* <Description> */ | |
519 | /* The glyph slot object constructor. */ | |
520 | /* */ | |
521 | /* <Input> */ | |
522 | /* glyph :: The glyph slot handle to initialize. */ | |
523 | /* */ | |
524 | LOCAL_FUNC | |
525 | FT_Error T1_Init_GlyphSlot( T1_GlyphSlot glyph ) | |
526 | { | |
527 | FT_Error error = FT_Err_Ok; | |
528 | ||
529 | ||
530 | #ifndef T1_CONFIG_OPTION_DISABLE_HINTER | |
531 | ||
532 | error = T1_New_Glyph_Hinter( glyph ); | |
533 | ||
534 | #else | |
535 | ||
536 | FT_UNUSED( glyph ); | |
537 | ||
538 | #endif | |
539 | ||
540 | return error; | |
541 | } | |
542 | ||
543 | ||
544 | /* END */ |