OLD | NEW |
| (Empty) |
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 "../../include/ft2build.h" | |
20 #include "t1gload.h" | |
21 #include "../../include/freetype/internal/ftcalc.h" | |
22 #include "../../include/freetype/internal/ftdebug.h" | |
23 #include "../../include/freetype/internal/ftstream.h" | |
24 #include "../../include/freetype/ftoutln.h" | |
25 #include "../../include/freetype/internal/psaux.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 = {0, 0}; | |
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 */ | |
OLD | NEW |