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