Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3918 | Serge | 1 | /***************************************************************************/ |
2 | /* */ |
||
3 | /* t1gload.c */ |
||
4 | /* */ |
||
5 | /* Type 1 Glyph Loader (body). */ |
||
6 | /* */ |
||
7 | /* Copyright 1996-2006, 2008-2010, 2013 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 |
||
20 | #include "t1gload.h" |
||
21 | #include FT_INTERNAL_CALC_H |
||
22 | #include FT_INTERNAL_DEBUG_H |
||
23 | #include FT_INTERNAL_STREAM_H |
||
24 | #include FT_OUTLINE_H |
||
25 | #include FT_INTERNAL_POSTSCRIPT_AUX_H |
||
26 | |||
27 | #include "t1errors.h" |
||
28 | |||
29 | |||
30 | /*************************************************************************/ |
||
31 | /* */ |
||
32 | /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
||
33 | /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
||
34 | /* messages during execution. */ |
||
35 | /* */ |
||
36 | #undef FT_COMPONENT |
||
37 | #define FT_COMPONENT trace_t1gload |
||
38 | |||
39 | |||
40 | /*************************************************************************/ |
||
41 | /*************************************************************************/ |
||
42 | /*************************************************************************/ |
||
43 | /********** *********/ |
||
44 | /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ |
||
45 | /********** *********/ |
||
46 | /********** The following code is in charge of computing *********/ |
||
47 | /********** the maximum advance width of the font. It *********/ |
||
48 | /********** quickly processes each glyph charstring to *********/ |
||
49 | /********** extract the value from either a `sbw' or `seac' *********/ |
||
50 | /********** operator. *********/ |
||
51 | /********** *********/ |
||
52 | /*************************************************************************/ |
||
53 | /*************************************************************************/ |
||
54 | /*************************************************************************/ |
||
55 | |||
56 | |||
57 | FT_LOCAL_DEF( FT_Error ) |
||
58 | T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder, |
||
59 | FT_UInt glyph_index, |
||
60 | FT_Data* char_string ) |
||
61 | { |
||
62 | T1_Face face = (T1_Face)decoder->builder.face; |
||
63 | T1_Font type1 = &face->type1; |
||
64 | FT_Error error = FT_Err_Ok; |
||
65 | |||
66 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
||
67 | FT_Incremental_InterfaceRec *inc = |
||
68 | face->root.internal->incremental_interface; |
||
69 | #endif |
||
70 | |||
71 | |||
72 | decoder->font_matrix = type1->font_matrix; |
||
73 | decoder->font_offset = type1->font_offset; |
||
74 | |||
75 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
||
76 | |||
77 | /* For incremental fonts get the character data using the */ |
||
78 | /* callback function. */ |
||
79 | if ( inc ) |
||
80 | error = inc->funcs->get_glyph_data( inc->object, |
||
81 | glyph_index, char_string ); |
||
82 | else |
||
83 | |||
84 | #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
||
85 | |||
86 | /* For ordinary fonts get the character data stored in the face record. */ |
||
87 | { |
||
88 | char_string->pointer = type1->charstrings[glyph_index]; |
||
89 | char_string->length = (FT_Int)type1->charstrings_len[glyph_index]; |
||
90 | } |
||
91 | |||
92 | if ( !error ) |
||
93 | error = decoder->funcs.parse_charstrings( |
||
94 | decoder, (FT_Byte*)char_string->pointer, |
||
95 | char_string->length ); |
||
96 | |||
97 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
||
98 | |||
99 | /* Incremental fonts can optionally override the metrics. */ |
||
100 | if ( !error && inc && inc->funcs->get_glyph_metrics ) |
||
101 | { |
||
102 | FT_Incremental_MetricsRec metrics; |
||
103 | |||
104 | |||
105 | metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x ); |
||
106 | metrics.bearing_y = 0; |
||
107 | metrics.advance = FIXED_TO_INT( decoder->builder.advance.x ); |
||
108 | metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y ); |
||
109 | |||
110 | error = inc->funcs->get_glyph_metrics( inc->object, |
||
111 | glyph_index, FALSE, &metrics ); |
||
112 | |||
113 | decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x ); |
||
114 | decoder->builder.advance.x = INT_TO_FIXED( metrics.advance ); |
||
115 | decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v ); |
||
116 | } |
||
117 | |||
118 | #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
||
119 | |||
120 | return error; |
||
121 | } |
||
122 | |||
123 | |||
124 | FT_CALLBACK_DEF( FT_Error ) |
||
125 | T1_Parse_Glyph( T1_Decoder decoder, |
||
126 | FT_UInt glyph_index ) |
||
127 | { |
||
128 | FT_Data glyph_data; |
||
129 | FT_Error error = T1_Parse_Glyph_And_Get_Char_String( |
||
130 | decoder, glyph_index, &glyph_data ); |
||
131 | |||
132 | |||
133 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
||
134 | |||
135 | if ( !error ) |
||
136 | { |
||
137 | T1_Face face = (T1_Face)decoder->builder.face; |
||
138 | |||
139 | |||
140 | if ( face->root.internal->incremental_interface ) |
||
141 | face->root.internal->incremental_interface->funcs->free_glyph_data( |
||
142 | face->root.internal->incremental_interface->object, |
||
143 | &glyph_data ); |
||
144 | } |
||
145 | |||
146 | #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
||
147 | |||
148 | return error; |
||
149 | } |
||
150 | |||
151 | |||
152 | FT_LOCAL_DEF( FT_Error ) |
||
153 | T1_Compute_Max_Advance( T1_Face face, |
||
154 | FT_Pos* max_advance ) |
||
155 | { |
||
156 | FT_Error error; |
||
157 | T1_DecoderRec decoder; |
||
158 | FT_Int glyph_index; |
||
159 | T1_Font type1 = &face->type1; |
||
160 | PSAux_Service psaux = (PSAux_Service)face->psaux; |
||
161 | |||
162 | |||
163 | FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); |
||
164 | |||
165 | *max_advance = 0; |
||
166 | |||
167 | /* initialize load decoder */ |
||
168 | error = psaux->t1_decoder_funcs->init( &decoder, |
||
169 | (FT_Face)face, |
||
170 | 0, /* size */ |
||
171 | 0, /* glyph slot */ |
||
172 | (FT_Byte**)type1->glyph_names, |
||
173 | face->blend, |
||
174 | 0, |
||
175 | FT_RENDER_MODE_NORMAL, |
||
176 | T1_Parse_Glyph ); |
||
177 | if ( error ) |
||
178 | return error; |
||
179 | |||
180 | decoder.builder.metrics_only = 1; |
||
181 | decoder.builder.load_points = 0; |
||
182 | |||
183 | decoder.num_subrs = type1->num_subrs; |
||
184 | decoder.subrs = type1->subrs; |
||
185 | decoder.subrs_len = type1->subrs_len; |
||
186 | |||
187 | decoder.buildchar = face->buildchar; |
||
188 | decoder.len_buildchar = face->len_buildchar; |
||
189 | |||
190 | *max_advance = 0; |
||
191 | |||
192 | /* for each glyph, parse the glyph charstring and extract */ |
||
193 | /* the advance width */ |
||
194 | for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ ) |
||
195 | { |
||
196 | /* now get load the unscaled outline */ |
||
197 | error = T1_Parse_Glyph( &decoder, glyph_index ); |
||
198 | if ( glyph_index == 0 || decoder.builder.advance.x > *max_advance ) |
||
199 | *max_advance = decoder.builder.advance.x; |
||
200 | |||
201 | /* ignore the error if one occurred - skip to next glyph */ |
||
202 | } |
||
203 | |||
204 | psaux->t1_decoder_funcs->done( &decoder ); |
||
205 | |||
206 | return FT_Err_Ok; |
||
207 | } |
||
208 | |||
209 | |||
210 | FT_LOCAL_DEF( FT_Error ) |
||
211 | T1_Get_Advances( FT_Face t1face, /* T1_Face */ |
||
212 | FT_UInt first, |
||
213 | FT_UInt count, |
||
214 | FT_Int32 load_flags, |
||
215 | FT_Fixed* advances ) |
||
216 | { |
||
217 | T1_Face face = (T1_Face)t1face; |
||
218 | T1_DecoderRec decoder; |
||
219 | T1_Font type1 = &face->type1; |
||
220 | PSAux_Service psaux = (PSAux_Service)face->psaux; |
||
221 | FT_UInt nn; |
||
222 | FT_Error error; |
||
223 | |||
224 | |||
225 | if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) |
||
226 | { |
||
227 | for ( nn = 0; nn < count; nn++ ) |
||
228 | advances[nn] = 0; |
||
229 | |||
230 | return FT_Err_Ok; |
||
231 | } |
||
232 | |||
233 | error = psaux->t1_decoder_funcs->init( &decoder, |
||
234 | (FT_Face)face, |
||
235 | 0, /* size */ |
||
236 | 0, /* glyph slot */ |
||
237 | (FT_Byte**)type1->glyph_names, |
||
238 | face->blend, |
||
239 | 0, |
||
240 | FT_RENDER_MODE_NORMAL, |
||
241 | T1_Parse_Glyph ); |
||
242 | if ( error ) |
||
243 | return error; |
||
244 | |||
245 | decoder.builder.metrics_only = 1; |
||
246 | decoder.builder.load_points = 0; |
||
247 | |||
248 | decoder.num_subrs = type1->num_subrs; |
||
249 | decoder.subrs = type1->subrs; |
||
250 | decoder.subrs_len = type1->subrs_len; |
||
251 | |||
252 | decoder.buildchar = face->buildchar; |
||
253 | decoder.len_buildchar = face->len_buildchar; |
||
254 | |||
255 | for ( nn = 0; nn < count; nn++ ) |
||
256 | { |
||
257 | error = T1_Parse_Glyph( &decoder, first + nn ); |
||
258 | if ( !error ) |
||
259 | advances[nn] = FIXED_TO_INT( decoder.builder.advance.x ); |
||
260 | else |
||
261 | advances[nn] = 0; |
||
262 | } |
||
263 | |||
264 | return FT_Err_Ok; |
||
265 | } |
||
266 | |||
267 | |||
268 | FT_LOCAL_DEF( FT_Error ) |
||
269 | T1_Load_Glyph( FT_GlyphSlot t1glyph, /* T1_GlyphSlot */ |
||
270 | FT_Size t1size, /* T1_Size */ |
||
271 | FT_UInt glyph_index, |
||
272 | FT_Int32 load_flags ) |
||
273 | { |
||
274 | T1_GlyphSlot glyph = (T1_GlyphSlot)t1glyph; |
||
275 | FT_Error error; |
||
276 | T1_DecoderRec decoder; |
||
277 | T1_Face face = (T1_Face)t1glyph->face; |
||
278 | FT_Bool hinting; |
||
279 | T1_Font type1 = &face->type1; |
||
280 | PSAux_Service psaux = (PSAux_Service)face->psaux; |
||
281 | const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; |
||
282 | |||
283 | FT_Matrix font_matrix; |
||
284 | FT_Vector font_offset; |
||
285 | FT_Data glyph_data; |
||
286 | FT_Bool must_finish_decoder = FALSE; |
||
287 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
||
288 | FT_Bool glyph_data_loaded = 0; |
||
289 | #endif |
||
290 | |||
291 | |||
292 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
||
293 | if ( glyph_index >= (FT_UInt)face->root.num_glyphs && |
||
294 | !face->root.internal->incremental_interface ) |
||
295 | #else |
||
296 | if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) |
||
297 | #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
||
298 | { |
||
299 | error = FT_THROW( Invalid_Argument ); |
||
300 | goto Exit; |
||
301 | } |
||
302 | |||
303 | FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); |
||
304 | |||
305 | if ( load_flags & FT_LOAD_NO_RECURSE ) |
||
306 | load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; |
||
307 | |||
308 | if ( t1size ) |
||
309 | { |
||
310 | glyph->x_scale = t1size->metrics.x_scale; |
||
311 | glyph->y_scale = t1size->metrics.y_scale; |
||
312 | } |
||
313 | else |
||
314 | { |
||
315 | glyph->x_scale = 0x10000L; |
||
316 | glyph->y_scale = 0x10000L; |
||
317 | } |
||
318 | |||
319 | t1glyph->outline.n_points = 0; |
||
320 | t1glyph->outline.n_contours = 0; |
||
321 | |||
322 | hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && |
||
323 | ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); |
||
324 | |||
325 | t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; |
||
326 | |||
327 | error = decoder_funcs->init( &decoder, |
||
328 | t1glyph->face, |
||
329 | t1size, |
||
330 | t1glyph, |
||
331 | (FT_Byte**)type1->glyph_names, |
||
332 | face->blend, |
||
333 | FT_BOOL( hinting ), |
||
334 | FT_LOAD_TARGET_MODE( load_flags ), |
||
335 | T1_Parse_Glyph ); |
||
336 | if ( error ) |
||
337 | goto Exit; |
||
338 | |||
339 | must_finish_decoder = TRUE; |
||
340 | |||
341 | decoder.builder.no_recurse = FT_BOOL( |
||
342 | ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); |
||
343 | |||
344 | decoder.num_subrs = type1->num_subrs; |
||
345 | decoder.subrs = type1->subrs; |
||
346 | decoder.subrs_len = type1->subrs_len; |
||
347 | |||
348 | decoder.buildchar = face->buildchar; |
||
349 | decoder.len_buildchar = face->len_buildchar; |
||
350 | |||
351 | /* now load the unscaled outline */ |
||
352 | error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index, |
||
353 | &glyph_data ); |
||
354 | if ( error ) |
||
355 | goto Exit; |
||
356 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
||
357 | glyph_data_loaded = 1; |
||
358 | #endif |
||
359 | |||
360 | font_matrix = decoder.font_matrix; |
||
361 | font_offset = decoder.font_offset; |
||
362 | |||
363 | /* save new glyph tables */ |
||
364 | decoder_funcs->done( &decoder ); |
||
365 | |||
366 | must_finish_decoder = FALSE; |
||
367 | |||
368 | /* now, set the metrics -- this is rather simple, as */ |
||
369 | /* the left side bearing is the xMin, and the top side */ |
||
370 | /* bearing the yMax */ |
||
371 | if ( !error ) |
||
372 | { |
||
373 | t1glyph->outline.flags &= FT_OUTLINE_OWNER; |
||
374 | t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; |
||
375 | |||
376 | /* for composite glyphs, return only left side bearing and */ |
||
377 | /* advance width */ |
||
378 | if ( load_flags & FT_LOAD_NO_RECURSE ) |
||
379 | { |
||
380 | FT_Slot_Internal internal = t1glyph->internal; |
||
381 | |||
382 | |||
383 | t1glyph->metrics.horiBearingX = |
||
384 | FIXED_TO_INT( decoder.builder.left_bearing.x ); |
||
385 | t1glyph->metrics.horiAdvance = |
||
386 | FIXED_TO_INT( decoder.builder.advance.x ); |
||
387 | |||
388 | internal->glyph_matrix = font_matrix; |
||
389 | internal->glyph_delta = font_offset; |
||
390 | internal->glyph_transformed = 1; |
||
391 | } |
||
392 | else |
||
393 | { |
||
394 | FT_BBox cbox; |
||
395 | FT_Glyph_Metrics* metrics = &t1glyph->metrics; |
||
396 | FT_Vector advance; |
||
397 | |||
398 | |||
399 | /* copy the _unscaled_ advance width */ |
||
400 | metrics->horiAdvance = |
||
401 | FIXED_TO_INT( decoder.builder.advance.x ); |
||
402 | t1glyph->linearHoriAdvance = |
||
403 | FIXED_TO_INT( decoder.builder.advance.x ); |
||
404 | t1glyph->internal->glyph_transformed = 0; |
||
405 | |||
406 | if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) |
||
407 | { |
||
408 | /* make up vertical ones */ |
||
409 | metrics->vertAdvance = ( face->type1.font_bbox.yMax - |
||
410 | face->type1.font_bbox.yMin ) >> 16; |
||
411 | t1glyph->linearVertAdvance = metrics->vertAdvance; |
||
412 | } |
||
413 | else |
||
414 | { |
||
415 | metrics->vertAdvance = |
||
416 | FIXED_TO_INT( decoder.builder.advance.y ); |
||
417 | t1glyph->linearVertAdvance = |
||
418 | FIXED_TO_INT( decoder.builder.advance.y ); |
||
419 | } |
||
420 | |||
421 | t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; |
||
422 | |||
423 | if ( t1size && t1size->metrics.y_ppem < 24 ) |
||
424 | t1glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; |
||
425 | |||
426 | #if 1 |
||
427 | /* apply the font matrix, if any */ |
||
428 | if ( font_matrix.xx != 0x10000L || font_matrix.yy != font_matrix.xx || |
||
429 | font_matrix.xy != 0 || font_matrix.yx != 0 ) |
||
430 | FT_Outline_Transform( &t1glyph->outline, &font_matrix ); |
||
431 | |||
432 | if ( font_offset.x || font_offset.y ) |
||
433 | FT_Outline_Translate( &t1glyph->outline, |
||
434 | font_offset.x, |
||
435 | font_offset.y ); |
||
436 | |||
437 | advance.x = metrics->horiAdvance; |
||
438 | advance.y = 0; |
||
439 | FT_Vector_Transform( &advance, &font_matrix ); |
||
440 | metrics->horiAdvance = advance.x + font_offset.x; |
||
441 | advance.x = 0; |
||
442 | advance.y = metrics->vertAdvance; |
||
443 | FT_Vector_Transform( &advance, &font_matrix ); |
||
444 | metrics->vertAdvance = advance.y + font_offset.y; |
||
445 | #endif |
||
446 | |||
447 | if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
||
448 | { |
||
449 | /* scale the outline and the metrics */ |
||
450 | FT_Int n; |
||
451 | FT_Outline* cur = decoder.builder.base; |
||
452 | FT_Vector* vec = cur->points; |
||
453 | FT_Fixed x_scale = glyph->x_scale; |
||
454 | FT_Fixed y_scale = glyph->y_scale; |
||
455 | |||
456 | |||
457 | /* First of all, scale the points, if we are not hinting */ |
||
458 | if ( !hinting || ! decoder.builder.hints_funcs ) |
||
459 | for ( n = cur->n_points; n > 0; n--, vec++ ) |
||
460 | { |
||
461 | vec->x = FT_MulFix( vec->x, x_scale ); |
||
462 | vec->y = FT_MulFix( vec->y, y_scale ); |
||
463 | } |
||
464 | |||
465 | /* Then scale the metrics */ |
||
466 | metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); |
||
467 | metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); |
||
468 | } |
||
469 | |||
470 | /* compute the other metrics */ |
||
471 | FT_Outline_Get_CBox( &t1glyph->outline, &cbox ); |
||
472 | |||
473 | metrics->width = cbox.xMax - cbox.xMin; |
||
474 | metrics->height = cbox.yMax - cbox.yMin; |
||
475 | |||
476 | metrics->horiBearingX = cbox.xMin; |
||
477 | metrics->horiBearingY = cbox.yMax; |
||
478 | |||
479 | if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) |
||
480 | { |
||
481 | /* make up vertical ones */ |
||
482 | ft_synthesize_vertical_metrics( metrics, |
||
483 | metrics->vertAdvance ); |
||
484 | } |
||
485 | } |
||
486 | |||
487 | /* Set control data to the glyph charstrings. Note that this is */ |
||
488 | /* _not_ zero-terminated. */ |
||
489 | t1glyph->control_data = (FT_Byte*)glyph_data.pointer; |
||
490 | t1glyph->control_len = glyph_data.length; |
||
491 | } |
||
492 | |||
493 | |||
494 | Exit: |
||
495 | |||
496 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
||
497 | if ( glyph_data_loaded && face->root.internal->incremental_interface ) |
||
498 | { |
||
499 | face->root.internal->incremental_interface->funcs->free_glyph_data( |
||
500 | face->root.internal->incremental_interface->object, |
||
501 | &glyph_data ); |
||
502 | |||
503 | /* Set the control data to null - it is no longer available if */ |
||
504 | /* loaded incrementally. */ |
||
505 | t1glyph->control_data = 0; |
||
506 | t1glyph->control_len = 0; |
||
507 | } |
||
508 | #endif |
||
509 | |||
510 | if ( must_finish_decoder ) |
||
511 | decoder_funcs->done( &decoder ); |
||
512 | |||
513 | return error; |
||
514 | } |
||
515 | |||
516 | |||
517 | /* END */>>>> |