1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* ttgload.c */ |
|
4 /* */ |
|
5 /* TrueType Glyph Loader (body). */ |
|
6 /* */ |
|
7 /* Copyright 1996-2011 */ |
|
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_CALC_H |
|
22 #include FT_INTERNAL_STREAM_H |
|
23 #include FT_INTERNAL_SFNT_H |
|
24 #include FT_TRUETYPE_TAGS_H |
|
25 #include FT_OUTLINE_H |
|
26 |
|
27 #include "ttgload.h" |
|
28 #include "ttpload.h" |
|
29 |
|
30 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
|
31 #include "ttgxvar.h" |
|
32 #endif |
|
33 |
|
34 #include "tterrors.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_ttgload |
|
45 |
|
46 |
|
47 /*************************************************************************/ |
|
48 /* */ |
|
49 /* Composite glyph flags. */ |
|
50 /* */ |
|
51 #define ARGS_ARE_WORDS 0x0001 |
|
52 #define ARGS_ARE_XY_VALUES 0x0002 |
|
53 #define ROUND_XY_TO_GRID 0x0004 |
|
54 #define WE_HAVE_A_SCALE 0x0008 |
|
55 /* reserved 0x0010 */ |
|
56 #define MORE_COMPONENTS 0x0020 |
|
57 #define WE_HAVE_AN_XY_SCALE 0x0040 |
|
58 #define WE_HAVE_A_2X2 0x0080 |
|
59 #define WE_HAVE_INSTR 0x0100 |
|
60 #define USE_MY_METRICS 0x0200 |
|
61 #define OVERLAP_COMPOUND 0x0400 |
|
62 #define SCALED_COMPONENT_OFFSET 0x0800 |
|
63 #define UNSCALED_COMPONENT_OFFSET 0x1000 |
|
64 |
|
65 |
|
66 /*************************************************************************/ |
|
67 /* */ |
|
68 /* Return the horizontal metrics in font units for a given glyph. */ |
|
69 /* */ |
|
70 FT_LOCAL_DEF( void ) |
|
71 TT_Get_HMetrics( TT_Face face, |
|
72 FT_UInt idx, |
|
73 FT_Short* lsb, |
|
74 FT_UShort* aw ) |
|
75 { |
|
76 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw ); |
|
77 |
|
78 FT_TRACE5(( " advance width (font units): %d\n", *aw )); |
|
79 FT_TRACE5(( " left side bearing (font units): %d\n", *lsb )); |
|
80 } |
|
81 |
|
82 |
|
83 /*************************************************************************/ |
|
84 /* */ |
|
85 /* Return the vertical metrics in font units for a given glyph. */ |
|
86 /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */ |
|
87 /* table, typoAscender/Descender from the `OS/2' table would be used */ |
|
88 /* instead, and if there were no `OS/2' table, use ascender/descender */ |
|
89 /* from the `hhea' table. But that is not what Microsoft's rasterizer */ |
|
90 /* apparently does: It uses the ppem value as the advance height, and */ |
|
91 /* sets the top side bearing to be zero. */ |
|
92 /* */ |
|
93 FT_LOCAL_DEF( void ) |
|
94 TT_Get_VMetrics( TT_Face face, |
|
95 FT_UInt idx, |
|
96 FT_Short* tsb, |
|
97 FT_UShort* ah ) |
|
98 { |
|
99 if ( face->vertical_info ) |
|
100 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah ); |
|
101 |
|
102 #if 1 /* Empirically determined, at variance with what MS said */ |
|
103 |
|
104 else |
|
105 { |
|
106 *tsb = 0; |
|
107 *ah = face->root.units_per_EM; |
|
108 } |
|
109 |
|
110 #else /* This is what MS said to do. It isn't what they do, however. */ |
|
111 |
|
112 else if ( face->os2.version != 0xFFFFU ) |
|
113 { |
|
114 *tsb = face->os2.sTypoAscender; |
|
115 *ah = face->os2.sTypoAscender - face->os2.sTypoDescender; |
|
116 } |
|
117 else |
|
118 { |
|
119 *tsb = face->horizontal.Ascender; |
|
120 *ah = face->horizontal.Ascender - face->horizontal.Descender; |
|
121 } |
|
122 |
|
123 #endif |
|
124 |
|
125 FT_TRACE5(( " advance height (font units): %d\n", *ah )); |
|
126 FT_TRACE5(( " top side bearing (font units): %d\n", *tsb )); |
|
127 } |
|
128 |
|
129 |
|
130 static void |
|
131 tt_get_metrics( TT_Loader loader, |
|
132 FT_UInt glyph_index ) |
|
133 { |
|
134 TT_Face face = (TT_Face)loader->face; |
|
135 |
|
136 FT_Short left_bearing = 0, top_bearing = 0; |
|
137 FT_UShort advance_width = 0, advance_height = 0; |
|
138 |
|
139 |
|
140 TT_Get_HMetrics( face, glyph_index, |
|
141 &left_bearing, |
|
142 &advance_width ); |
|
143 TT_Get_VMetrics( face, glyph_index, |
|
144 &top_bearing, |
|
145 &advance_height ); |
|
146 |
|
147 loader->left_bearing = left_bearing; |
|
148 loader->advance = advance_width; |
|
149 loader->top_bearing = top_bearing; |
|
150 loader->vadvance = advance_height; |
|
151 |
|
152 if ( !loader->linear_def ) |
|
153 { |
|
154 loader->linear_def = 1; |
|
155 loader->linear = advance_width; |
|
156 } |
|
157 } |
|
158 |
|
159 |
|
160 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
161 |
|
162 static void |
|
163 tt_get_metrics_incr_overrides( TT_Loader loader, |
|
164 FT_UInt glyph_index ) |
|
165 { |
|
166 TT_Face face = (TT_Face)loader->face; |
|
167 |
|
168 FT_Short left_bearing = 0, top_bearing = 0; |
|
169 FT_UShort advance_width = 0, advance_height = 0; |
|
170 |
|
171 |
|
172 /* If this is an incrementally loaded font check whether there are */ |
|
173 /* overriding metrics for this glyph. */ |
|
174 if ( face->root.internal->incremental_interface && |
|
175 face->root.internal->incremental_interface->funcs->get_glyph_metrics ) |
|
176 { |
|
177 FT_Incremental_MetricsRec metrics; |
|
178 FT_Error error; |
|
179 |
|
180 |
|
181 metrics.bearing_x = loader->left_bearing; |
|
182 metrics.bearing_y = 0; |
|
183 metrics.advance = loader->advance; |
|
184 metrics.advance_v = 0; |
|
185 |
|
186 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( |
|
187 face->root.internal->incremental_interface->object, |
|
188 glyph_index, FALSE, &metrics ); |
|
189 if ( error ) |
|
190 goto Exit; |
|
191 |
|
192 left_bearing = (FT_Short)metrics.bearing_x; |
|
193 advance_width = (FT_UShort)metrics.advance; |
|
194 |
|
195 #if 0 |
|
196 |
|
197 /* GWW: Do I do the same for vertical metrics? */ |
|
198 metrics.bearing_x = 0; |
|
199 metrics.bearing_y = loader->top_bearing; |
|
200 metrics.advance = loader->vadvance; |
|
201 |
|
202 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( |
|
203 face->root.internal->incremental_interface->object, |
|
204 glyph_index, TRUE, &metrics ); |
|
205 if ( error ) |
|
206 goto Exit; |
|
207 |
|
208 top_bearing = (FT_Short)metrics.bearing_y; |
|
209 advance_height = (FT_UShort)metrics.advance; |
|
210 |
|
211 #endif /* 0 */ |
|
212 |
|
213 loader->left_bearing = left_bearing; |
|
214 loader->advance = advance_width; |
|
215 loader->top_bearing = top_bearing; |
|
216 loader->vadvance = advance_height; |
|
217 |
|
218 if ( !loader->linear_def ) |
|
219 { |
|
220 loader->linear_def = 1; |
|
221 loader->linear = advance_width; |
|
222 } |
|
223 } |
|
224 |
|
225 Exit: |
|
226 return; |
|
227 } |
|
228 |
|
229 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
|
230 |
|
231 |
|
232 /*************************************************************************/ |
|
233 /* */ |
|
234 /* Translates an array of coordinates. */ |
|
235 /* */ |
|
236 static void |
|
237 translate_array( FT_UInt n, |
|
238 FT_Vector* coords, |
|
239 FT_Pos delta_x, |
|
240 FT_Pos delta_y ) |
|
241 { |
|
242 FT_UInt k; |
|
243 |
|
244 |
|
245 if ( delta_x ) |
|
246 for ( k = 0; k < n; k++ ) |
|
247 coords[k].x += delta_x; |
|
248 |
|
249 if ( delta_y ) |
|
250 for ( k = 0; k < n; k++ ) |
|
251 coords[k].y += delta_y; |
|
252 } |
|
253 |
|
254 |
|
255 #undef IS_HINTED |
|
256 #define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 ) |
|
257 |
|
258 |
|
259 /*************************************************************************/ |
|
260 /* */ |
|
261 /* The following functions are used by default with TrueType fonts. */ |
|
262 /* However, they can be replaced by alternatives if we need to support */ |
|
263 /* TrueType-compressed formats (like MicroType) in the future. */ |
|
264 /* */ |
|
265 /*************************************************************************/ |
|
266 |
|
267 FT_CALLBACK_DEF( FT_Error ) |
|
268 TT_Access_Glyph_Frame( TT_Loader loader, |
|
269 FT_UInt glyph_index, |
|
270 FT_ULong offset, |
|
271 FT_UInt byte_count ) |
|
272 { |
|
273 FT_Error error; |
|
274 FT_Stream stream = loader->stream; |
|
275 |
|
276 /* for non-debug mode */ |
|
277 FT_UNUSED( glyph_index ); |
|
278 |
|
279 |
|
280 FT_TRACE4(( "Glyph %ld\n", glyph_index )); |
|
281 |
|
282 /* the following line sets the `error' variable through macros! */ |
|
283 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) ) |
|
284 return error; |
|
285 |
|
286 loader->cursor = stream->cursor; |
|
287 loader->limit = stream->limit; |
|
288 |
|
289 return TT_Err_Ok; |
|
290 } |
|
291 |
|
292 |
|
293 FT_CALLBACK_DEF( void ) |
|
294 TT_Forget_Glyph_Frame( TT_Loader loader ) |
|
295 { |
|
296 FT_Stream stream = loader->stream; |
|
297 |
|
298 |
|
299 FT_FRAME_EXIT(); |
|
300 } |
|
301 |
|
302 |
|
303 FT_CALLBACK_DEF( FT_Error ) |
|
304 TT_Load_Glyph_Header( TT_Loader loader ) |
|
305 { |
|
306 FT_Byte* p = loader->cursor; |
|
307 FT_Byte* limit = loader->limit; |
|
308 |
|
309 |
|
310 if ( p + 10 > limit ) |
|
311 return TT_Err_Invalid_Outline; |
|
312 |
|
313 loader->n_contours = FT_NEXT_SHORT( p ); |
|
314 |
|
315 loader->bbox.xMin = FT_NEXT_SHORT( p ); |
|
316 loader->bbox.yMin = FT_NEXT_SHORT( p ); |
|
317 loader->bbox.xMax = FT_NEXT_SHORT( p ); |
|
318 loader->bbox.yMax = FT_NEXT_SHORT( p ); |
|
319 |
|
320 FT_TRACE5(( " # of contours: %d\n", loader->n_contours )); |
|
321 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin, |
|
322 loader->bbox.xMax )); |
|
323 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin, |
|
324 loader->bbox.yMax )); |
|
325 loader->cursor = p; |
|
326 |
|
327 return TT_Err_Ok; |
|
328 } |
|
329 |
|
330 |
|
331 FT_CALLBACK_DEF( FT_Error ) |
|
332 TT_Load_Simple_Glyph( TT_Loader load ) |
|
333 { |
|
334 FT_Error error; |
|
335 FT_Byte* p = load->cursor; |
|
336 FT_Byte* limit = load->limit; |
|
337 FT_GlyphLoader gloader = load->gloader; |
|
338 FT_Int n_contours = load->n_contours; |
|
339 FT_Outline* outline; |
|
340 TT_Face face = (TT_Face)load->face; |
|
341 FT_UShort n_ins; |
|
342 FT_Int n_points; |
|
343 |
|
344 FT_Byte *flag, *flag_limit; |
|
345 FT_Byte c, count; |
|
346 FT_Vector *vec, *vec_limit; |
|
347 FT_Pos x; |
|
348 FT_Short *cont, *cont_limit, prev_cont; |
|
349 FT_Int xy_size = 0; |
|
350 |
|
351 |
|
352 /* check that we can add the contours to the glyph */ |
|
353 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours ); |
|
354 if ( error ) |
|
355 goto Fail; |
|
356 |
|
357 /* reading the contours' endpoints & number of points */ |
|
358 cont = gloader->current.outline.contours; |
|
359 cont_limit = cont + n_contours; |
|
360 |
|
361 /* check space for contours array + instructions count */ |
|
362 if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit ) |
|
363 goto Invalid_Outline; |
|
364 |
|
365 prev_cont = FT_NEXT_USHORT( p ); |
|
366 |
|
367 if ( n_contours > 0 ) |
|
368 cont[0] = prev_cont; |
|
369 |
|
370 for ( cont++; cont < cont_limit; cont++ ) |
|
371 { |
|
372 cont[0] = FT_NEXT_USHORT( p ); |
|
373 if ( cont[0] <= prev_cont ) |
|
374 { |
|
375 /* unordered contours: this is invalid */ |
|
376 error = TT_Err_Invalid_Table; |
|
377 goto Fail; |
|
378 } |
|
379 prev_cont = cont[0]; |
|
380 } |
|
381 |
|
382 n_points = 0; |
|
383 if ( n_contours > 0 ) |
|
384 { |
|
385 n_points = cont[-1] + 1; |
|
386 if ( n_points < 0 ) |
|
387 goto Invalid_Outline; |
|
388 } |
|
389 |
|
390 /* note that we will add four phantom points later */ |
|
391 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 ); |
|
392 if ( error ) |
|
393 goto Fail; |
|
394 |
|
395 /* we'd better check the contours table right now */ |
|
396 outline = &gloader->current.outline; |
|
397 |
|
398 for ( cont = outline->contours + 1; cont < cont_limit; cont++ ) |
|
399 if ( cont[-1] >= cont[0] ) |
|
400 goto Invalid_Outline; |
|
401 |
|
402 /* reading the bytecode instructions */ |
|
403 load->glyph->control_len = 0; |
|
404 load->glyph->control_data = 0; |
|
405 |
|
406 if ( p + 2 > limit ) |
|
407 goto Invalid_Outline; |
|
408 |
|
409 n_ins = FT_NEXT_USHORT( p ); |
|
410 |
|
411 FT_TRACE5(( " Instructions size: %u\n", n_ins )); |
|
412 |
|
413 if ( n_ins > face->max_profile.maxSizeOfInstructions ) |
|
414 { |
|
415 FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n", |
|
416 n_ins )); |
|
417 error = TT_Err_Too_Many_Hints; |
|
418 goto Fail; |
|
419 } |
|
420 |
|
421 if ( ( limit - p ) < n_ins ) |
|
422 { |
|
423 FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); |
|
424 error = TT_Err_Too_Many_Hints; |
|
425 goto Fail; |
|
426 } |
|
427 |
|
428 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
429 |
|
430 if ( IS_HINTED( load->load_flags ) ) |
|
431 { |
|
432 load->glyph->control_len = n_ins; |
|
433 load->glyph->control_data = load->exec->glyphIns; |
|
434 |
|
435 FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins ); |
|
436 } |
|
437 |
|
438 #endif /* TT_USE_BYTECODE_INTERPRETER */ |
|
439 |
|
440 p += n_ins; |
|
441 |
|
442 /* reading the point tags */ |
|
443 flag = (FT_Byte*)outline->tags; |
|
444 flag_limit = flag + n_points; |
|
445 |
|
446 FT_ASSERT( flag != NULL ); |
|
447 |
|
448 while ( flag < flag_limit ) |
|
449 { |
|
450 if ( p + 1 > limit ) |
|
451 goto Invalid_Outline; |
|
452 |
|
453 *flag++ = c = FT_NEXT_BYTE( p ); |
|
454 if ( c & 8 ) |
|
455 { |
|
456 if ( p + 1 > limit ) |
|
457 goto Invalid_Outline; |
|
458 |
|
459 count = FT_NEXT_BYTE( p ); |
|
460 if ( flag + (FT_Int)count > flag_limit ) |
|
461 goto Invalid_Outline; |
|
462 |
|
463 for ( ; count > 0; count-- ) |
|
464 *flag++ = c; |
|
465 } |
|
466 } |
|
467 |
|
468 /* reading the X coordinates */ |
|
469 |
|
470 vec = outline->points; |
|
471 vec_limit = vec + n_points; |
|
472 flag = (FT_Byte*)outline->tags; |
|
473 x = 0; |
|
474 |
|
475 if ( p + xy_size > limit ) |
|
476 goto Invalid_Outline; |
|
477 |
|
478 for ( ; vec < vec_limit; vec++, flag++ ) |
|
479 { |
|
480 FT_Pos y = 0; |
|
481 FT_Byte f = *flag; |
|
482 |
|
483 |
|
484 if ( f & 2 ) |
|
485 { |
|
486 if ( p + 1 > limit ) |
|
487 goto Invalid_Outline; |
|
488 |
|
489 y = (FT_Pos)FT_NEXT_BYTE( p ); |
|
490 if ( ( f & 16 ) == 0 ) |
|
491 y = -y; |
|
492 } |
|
493 else if ( ( f & 16 ) == 0 ) |
|
494 { |
|
495 if ( p + 2 > limit ) |
|
496 goto Invalid_Outline; |
|
497 |
|
498 y = (FT_Pos)FT_NEXT_SHORT( p ); |
|
499 } |
|
500 |
|
501 x += y; |
|
502 vec->x = x; |
|
503 /* the cast is for stupid compilers */ |
|
504 *flag = (FT_Byte)( f & ~( 2 | 16 ) ); |
|
505 } |
|
506 |
|
507 /* reading the Y coordinates */ |
|
508 |
|
509 vec = gloader->current.outline.points; |
|
510 vec_limit = vec + n_points; |
|
511 flag = (FT_Byte*)outline->tags; |
|
512 x = 0; |
|
513 |
|
514 for ( ; vec < vec_limit; vec++, flag++ ) |
|
515 { |
|
516 FT_Pos y = 0; |
|
517 FT_Byte f = *flag; |
|
518 |
|
519 |
|
520 if ( f & 4 ) |
|
521 { |
|
522 if ( p + 1 > limit ) |
|
523 goto Invalid_Outline; |
|
524 |
|
525 y = (FT_Pos)FT_NEXT_BYTE( p ); |
|
526 if ( ( f & 32 ) == 0 ) |
|
527 y = -y; |
|
528 } |
|
529 else if ( ( f & 32 ) == 0 ) |
|
530 { |
|
531 if ( p + 2 > limit ) |
|
532 goto Invalid_Outline; |
|
533 |
|
534 y = (FT_Pos)FT_NEXT_SHORT( p ); |
|
535 } |
|
536 |
|
537 x += y; |
|
538 vec->y = x; |
|
539 /* the cast is for stupid compilers */ |
|
540 *flag = (FT_Byte)( f & FT_CURVE_TAG_ON ); |
|
541 } |
|
542 |
|
543 outline->n_points = (FT_UShort)n_points; |
|
544 outline->n_contours = (FT_Short) n_contours; |
|
545 |
|
546 load->cursor = p; |
|
547 |
|
548 Fail: |
|
549 return error; |
|
550 |
|
551 Invalid_Outline: |
|
552 error = TT_Err_Invalid_Outline; |
|
553 goto Fail; |
|
554 } |
|
555 |
|
556 |
|
557 FT_CALLBACK_DEF( FT_Error ) |
|
558 TT_Load_Composite_Glyph( TT_Loader loader ) |
|
559 { |
|
560 FT_Error error; |
|
561 FT_Byte* p = loader->cursor; |
|
562 FT_Byte* limit = loader->limit; |
|
563 FT_GlyphLoader gloader = loader->gloader; |
|
564 FT_SubGlyph subglyph; |
|
565 FT_UInt num_subglyphs; |
|
566 |
|
567 |
|
568 num_subglyphs = 0; |
|
569 |
|
570 do |
|
571 { |
|
572 FT_Fixed xx, xy, yy, yx; |
|
573 FT_UInt count; |
|
574 |
|
575 |
|
576 /* check that we can load a new subglyph */ |
|
577 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 ); |
|
578 if ( error ) |
|
579 goto Fail; |
|
580 |
|
581 /* check space */ |
|
582 if ( p + 4 > limit ) |
|
583 goto Invalid_Composite; |
|
584 |
|
585 subglyph = gloader->current.subglyphs + num_subglyphs; |
|
586 |
|
587 subglyph->arg1 = subglyph->arg2 = 0; |
|
588 |
|
589 subglyph->flags = FT_NEXT_USHORT( p ); |
|
590 subglyph->index = FT_NEXT_USHORT( p ); |
|
591 |
|
592 /* check space */ |
|
593 count = 2; |
|
594 if ( subglyph->flags & ARGS_ARE_WORDS ) |
|
595 count += 2; |
|
596 if ( subglyph->flags & WE_HAVE_A_SCALE ) |
|
597 count += 2; |
|
598 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) |
|
599 count += 4; |
|
600 else if ( subglyph->flags & WE_HAVE_A_2X2 ) |
|
601 count += 8; |
|
602 |
|
603 if ( p + count > limit ) |
|
604 goto Invalid_Composite; |
|
605 |
|
606 /* read arguments */ |
|
607 if ( subglyph->flags & ARGS_ARE_WORDS ) |
|
608 { |
|
609 subglyph->arg1 = FT_NEXT_SHORT( p ); |
|
610 subglyph->arg2 = FT_NEXT_SHORT( p ); |
|
611 } |
|
612 else |
|
613 { |
|
614 subglyph->arg1 = FT_NEXT_CHAR( p ); |
|
615 subglyph->arg2 = FT_NEXT_CHAR( p ); |
|
616 } |
|
617 |
|
618 /* read transform */ |
|
619 xx = yy = 0x10000L; |
|
620 xy = yx = 0; |
|
621 |
|
622 if ( subglyph->flags & WE_HAVE_A_SCALE ) |
|
623 { |
|
624 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; |
|
625 yy = xx; |
|
626 } |
|
627 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) |
|
628 { |
|
629 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; |
|
630 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; |
|
631 } |
|
632 else if ( subglyph->flags & WE_HAVE_A_2X2 ) |
|
633 { |
|
634 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; |
|
635 yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; |
|
636 xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; |
|
637 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; |
|
638 } |
|
639 |
|
640 subglyph->transform.xx = xx; |
|
641 subglyph->transform.xy = xy; |
|
642 subglyph->transform.yx = yx; |
|
643 subglyph->transform.yy = yy; |
|
644 |
|
645 num_subglyphs++; |
|
646 |
|
647 } while ( subglyph->flags & MORE_COMPONENTS ); |
|
648 |
|
649 gloader->current.num_subglyphs = num_subglyphs; |
|
650 |
|
651 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
652 |
|
653 { |
|
654 FT_Stream stream = loader->stream; |
|
655 |
|
656 |
|
657 /* we must undo the FT_FRAME_ENTER in order to point */ |
|
658 /* to the composite instructions, if we find some. */ |
|
659 /* We will process them later. */ |
|
660 /* */ |
|
661 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() + |
|
662 p - limit ); |
|
663 } |
|
664 |
|
665 #endif |
|
666 |
|
667 loader->cursor = p; |
|
668 |
|
669 Fail: |
|
670 return error; |
|
671 |
|
672 Invalid_Composite: |
|
673 error = TT_Err_Invalid_Composite; |
|
674 goto Fail; |
|
675 } |
|
676 |
|
677 |
|
678 FT_LOCAL_DEF( void ) |
|
679 TT_Init_Glyph_Loading( TT_Face face ) |
|
680 { |
|
681 face->access_glyph_frame = TT_Access_Glyph_Frame; |
|
682 face->read_glyph_header = TT_Load_Glyph_Header; |
|
683 face->read_simple_glyph = TT_Load_Simple_Glyph; |
|
684 face->read_composite_glyph = TT_Load_Composite_Glyph; |
|
685 face->forget_glyph_frame = TT_Forget_Glyph_Frame; |
|
686 } |
|
687 |
|
688 |
|
689 static void |
|
690 tt_prepare_zone( TT_GlyphZone zone, |
|
691 FT_GlyphLoad load, |
|
692 FT_UInt start_point, |
|
693 FT_UInt start_contour ) |
|
694 { |
|
695 zone->n_points = (FT_UShort)( load->outline.n_points - start_point ); |
|
696 zone->n_contours = (FT_Short) ( load->outline.n_contours - |
|
697 start_contour ); |
|
698 zone->org = load->extra_points + start_point; |
|
699 zone->cur = load->outline.points + start_point; |
|
700 zone->orus = load->extra_points2 + start_point; |
|
701 zone->tags = (FT_Byte*)load->outline.tags + start_point; |
|
702 zone->contours = (FT_UShort*)load->outline.contours + start_contour; |
|
703 zone->first_point = (FT_UShort)start_point; |
|
704 } |
|
705 |
|
706 |
|
707 /*************************************************************************/ |
|
708 /* */ |
|
709 /* <Function> */ |
|
710 /* TT_Hint_Glyph */ |
|
711 /* */ |
|
712 /* <Description> */ |
|
713 /* Hint the glyph using the zone prepared by the caller. Note that */ |
|
714 /* the zone is supposed to include four phantom points. */ |
|
715 /* */ |
|
716 static FT_Error |
|
717 TT_Hint_Glyph( TT_Loader loader, |
|
718 FT_Bool is_composite ) |
|
719 { |
|
720 TT_GlyphZone zone = &loader->zone; |
|
721 FT_Pos origin; |
|
722 |
|
723 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
724 FT_UInt n_ins; |
|
725 #else |
|
726 FT_UNUSED( is_composite ); |
|
727 #endif |
|
728 |
|
729 |
|
730 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
731 if ( loader->glyph->control_len > 0xFFFFL ) |
|
732 { |
|
733 FT_TRACE1(( "TT_Hint_Glyph: too long instructions " )); |
|
734 FT_TRACE1(( "(0x%lx byte) is truncated\n", |
|
735 loader->glyph->control_len )); |
|
736 } |
|
737 n_ins = (FT_UInt)( loader->glyph->control_len ); |
|
738 #endif |
|
739 |
|
740 origin = zone->cur[zone->n_points - 4].x; |
|
741 origin = FT_PIX_ROUND( origin ) - origin; |
|
742 if ( origin ) |
|
743 translate_array( zone->n_points, zone->cur, origin, 0 ); |
|
744 |
|
745 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
746 /* save original point position in org */ |
|
747 if ( n_ins > 0 ) |
|
748 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points ); |
|
749 |
|
750 /* Reset graphics state. */ |
|
751 loader->exec->GS = ((TT_Size)loader->size)->GS; |
|
752 |
|
753 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */ |
|
754 /* completely refer to the (already) hinted subglyphs. */ |
|
755 if ( is_composite ) |
|
756 { |
|
757 loader->exec->metrics.x_scale = 1 << 16; |
|
758 loader->exec->metrics.y_scale = 1 << 16; |
|
759 |
|
760 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points ); |
|
761 } |
|
762 else |
|
763 { |
|
764 loader->exec->metrics.x_scale = |
|
765 ((TT_Size)loader->size)->metrics.x_scale; |
|
766 loader->exec->metrics.y_scale = |
|
767 ((TT_Size)loader->size)->metrics.y_scale; |
|
768 } |
|
769 #endif |
|
770 |
|
771 /* round pp2 and pp4 */ |
|
772 zone->cur[zone->n_points - 3].x = |
|
773 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x ); |
|
774 zone->cur[zone->n_points - 1].y = |
|
775 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y ); |
|
776 |
|
777 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
778 |
|
779 if ( n_ins > 0 ) |
|
780 { |
|
781 FT_Bool debug; |
|
782 FT_Error error; |
|
783 |
|
784 FT_GlyphLoader gloader = loader->gloader; |
|
785 FT_Outline current_outline = gloader->current.outline; |
|
786 |
|
787 |
|
788 error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph, |
|
789 loader->exec->glyphIns, n_ins ); |
|
790 if ( error ) |
|
791 return error; |
|
792 |
|
793 loader->exec->is_composite = is_composite; |
|
794 loader->exec->pts = *zone; |
|
795 |
|
796 debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) && |
|
797 ((TT_Size)loader->size)->debug ); |
|
798 |
|
799 error = TT_Run_Context( loader->exec, debug ); |
|
800 if ( error && loader->exec->pedantic_hinting ) |
|
801 return error; |
|
802 |
|
803 /* store drop-out mode in bits 5-7; set bit 2 also as a marker */ |
|
804 current_outline.tags[0] |= |
|
805 ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; |
|
806 } |
|
807 |
|
808 #endif |
|
809 |
|
810 /* save glyph phantom points */ |
|
811 if ( !loader->preserve_pps ) |
|
812 { |
|
813 loader->pp1 = zone->cur[zone->n_points - 4]; |
|
814 loader->pp2 = zone->cur[zone->n_points - 3]; |
|
815 loader->pp3 = zone->cur[zone->n_points - 2]; |
|
816 loader->pp4 = zone->cur[zone->n_points - 1]; |
|
817 } |
|
818 |
|
819 return TT_Err_Ok; |
|
820 } |
|
821 |
|
822 |
|
823 /*************************************************************************/ |
|
824 /* */ |
|
825 /* <Function> */ |
|
826 /* TT_Process_Simple_Glyph */ |
|
827 /* */ |
|
828 /* <Description> */ |
|
829 /* Once a simple glyph has been loaded, it needs to be processed. */ |
|
830 /* Usually, this means scaling and hinting through bytecode */ |
|
831 /* interpretation. */ |
|
832 /* */ |
|
833 static FT_Error |
|
834 TT_Process_Simple_Glyph( TT_Loader loader ) |
|
835 { |
|
836 FT_GlyphLoader gloader = loader->gloader; |
|
837 FT_Error error = TT_Err_Ok; |
|
838 FT_Outline* outline; |
|
839 FT_Int n_points; |
|
840 |
|
841 |
|
842 outline = &gloader->current.outline; |
|
843 n_points = outline->n_points; |
|
844 |
|
845 /* set phantom points */ |
|
846 |
|
847 outline->points[n_points ] = loader->pp1; |
|
848 outline->points[n_points + 1] = loader->pp2; |
|
849 outline->points[n_points + 2] = loader->pp3; |
|
850 outline->points[n_points + 3] = loader->pp4; |
|
851 |
|
852 outline->tags[n_points ] = 0; |
|
853 outline->tags[n_points + 1] = 0; |
|
854 outline->tags[n_points + 2] = 0; |
|
855 outline->tags[n_points + 3] = 0; |
|
856 |
|
857 n_points += 4; |
|
858 |
|
859 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
|
860 |
|
861 if ( ((TT_Face)loader->face)->doblend ) |
|
862 { |
|
863 /* Deltas apply to the unscaled data. */ |
|
864 FT_Vector* deltas; |
|
865 FT_Memory memory = loader->face->memory; |
|
866 FT_Int i; |
|
867 |
|
868 |
|
869 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face), |
|
870 loader->glyph_index, |
|
871 &deltas, |
|
872 n_points ); |
|
873 if ( error ) |
|
874 return error; |
|
875 |
|
876 for ( i = 0; i < n_points; ++i ) |
|
877 { |
|
878 outline->points[i].x += deltas[i].x; |
|
879 outline->points[i].y += deltas[i].y; |
|
880 } |
|
881 |
|
882 FT_FREE( deltas ); |
|
883 } |
|
884 |
|
885 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ |
|
886 |
|
887 if ( IS_HINTED( loader->load_flags ) ) |
|
888 { |
|
889 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 ); |
|
890 |
|
891 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur, |
|
892 loader->zone.n_points + 4 ); |
|
893 } |
|
894 |
|
895 /* scale the glyph */ |
|
896 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
|
897 { |
|
898 FT_Vector* vec = outline->points; |
|
899 FT_Vector* limit = outline->points + n_points; |
|
900 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale; |
|
901 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale; |
|
902 |
|
903 |
|
904 for ( ; vec < limit; vec++ ) |
|
905 { |
|
906 vec->x = FT_MulFix( vec->x, x_scale ); |
|
907 vec->y = FT_MulFix( vec->y, y_scale ); |
|
908 } |
|
909 |
|
910 loader->pp1 = outline->points[n_points - 4]; |
|
911 loader->pp2 = outline->points[n_points - 3]; |
|
912 loader->pp3 = outline->points[n_points - 2]; |
|
913 loader->pp4 = outline->points[n_points - 1]; |
|
914 } |
|
915 |
|
916 if ( IS_HINTED( loader->load_flags ) ) |
|
917 { |
|
918 loader->zone.n_points += 4; |
|
919 |
|
920 error = TT_Hint_Glyph( loader, 0 ); |
|
921 } |
|
922 |
|
923 return error; |
|
924 } |
|
925 |
|
926 |
|
927 /*************************************************************************/ |
|
928 /* */ |
|
929 /* <Function> */ |
|
930 /* TT_Process_Composite_Component */ |
|
931 /* */ |
|
932 /* <Description> */ |
|
933 /* Once a composite component has been loaded, it needs to be */ |
|
934 /* processed. Usually, this means transforming and translating. */ |
|
935 /* */ |
|
936 static FT_Error |
|
937 TT_Process_Composite_Component( TT_Loader loader, |
|
938 FT_SubGlyph subglyph, |
|
939 FT_UInt start_point, |
|
940 FT_UInt num_base_points ) |
|
941 { |
|
942 FT_GlyphLoader gloader = loader->gloader; |
|
943 FT_Vector* base_vec = gloader->base.outline.points; |
|
944 FT_UInt num_points = gloader->base.outline.n_points; |
|
945 FT_Bool have_scale; |
|
946 FT_Pos x, y; |
|
947 |
|
948 |
|
949 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE | |
|
950 WE_HAVE_AN_XY_SCALE | |
|
951 WE_HAVE_A_2X2 ) ); |
|
952 |
|
953 /* perform the transform required for this subglyph */ |
|
954 if ( have_scale ) |
|
955 { |
|
956 FT_UInt i; |
|
957 |
|
958 |
|
959 for ( i = num_base_points; i < num_points; i++ ) |
|
960 FT_Vector_Transform( base_vec + i, &subglyph->transform ); |
|
961 } |
|
962 |
|
963 /* get offset */ |
|
964 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) |
|
965 { |
|
966 FT_UInt k = subglyph->arg1; |
|
967 FT_UInt l = subglyph->arg2; |
|
968 FT_Vector* p1; |
|
969 FT_Vector* p2; |
|
970 |
|
971 |
|
972 /* match l-th point of the newly loaded component to the k-th point */ |
|
973 /* of the previously loaded components. */ |
|
974 |
|
975 /* change to the point numbers used by our outline */ |
|
976 k += start_point; |
|
977 l += num_base_points; |
|
978 if ( k >= num_base_points || |
|
979 l >= num_points ) |
|
980 return TT_Err_Invalid_Composite; |
|
981 |
|
982 p1 = gloader->base.outline.points + k; |
|
983 p2 = gloader->base.outline.points + l; |
|
984 |
|
985 x = p1->x - p2->x; |
|
986 y = p1->y - p2->y; |
|
987 } |
|
988 else |
|
989 { |
|
990 x = subglyph->arg1; |
|
991 y = subglyph->arg2; |
|
992 |
|
993 if ( !x && !y ) |
|
994 return TT_Err_Ok; |
|
995 |
|
996 /* Use a default value dependent on */ |
|
997 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */ |
|
998 /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */ |
|
999 |
|
1000 if ( have_scale && |
|
1001 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED |
|
1002 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) ) |
|
1003 #else |
|
1004 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) ) |
|
1005 #endif |
|
1006 { |
|
1007 |
|
1008 #if 0 |
|
1009 |
|
1010 /*************************************************************************/ |
|
1011 /* */ |
|
1012 /* This algorithm is what Apple documents. But it doesn't work. */ |
|
1013 /* */ |
|
1014 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx |
|
1015 : -subglyph->transform.xx; |
|
1016 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx |
|
1017 : -subglyph->transform.yx; |
|
1018 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy |
|
1019 : -subglyph->transform.xy; |
|
1020 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy |
|
1021 : -subglyph->transform.yy; |
|
1022 int m = a > b ? a : b; |
|
1023 int n = c > d ? c : d; |
|
1024 |
|
1025 |
|
1026 if ( a - b <= 33 && a - b >= -33 ) |
|
1027 m *= 2; |
|
1028 if ( c - d <= 33 && c - d >= -33 ) |
|
1029 n *= 2; |
|
1030 x = FT_MulFix( x, m ); |
|
1031 y = FT_MulFix( y, n ); |
|
1032 |
|
1033 #else /* 0 */ |
|
1034 |
|
1035 /*************************************************************************/ |
|
1036 /* */ |
|
1037 /* This algorithm is a guess and works much better than the above. */ |
|
1038 /* */ |
|
1039 FT_Fixed mac_xscale = FT_SqrtFixed( |
|
1040 (FT_Int32)FT_MulFix( subglyph->transform.xx, |
|
1041 subglyph->transform.xx ) + |
|
1042 (FT_Int32)FT_MulFix( subglyph->transform.xy, |
|
1043 subglyph->transform.xy ) ); |
|
1044 FT_Fixed mac_yscale = FT_SqrtFixed( |
|
1045 (FT_Int32)FT_MulFix( subglyph->transform.yy, |
|
1046 subglyph->transform.yy ) + |
|
1047 (FT_Int32)FT_MulFix( subglyph->transform.yx, |
|
1048 subglyph->transform.yx ) ); |
|
1049 |
|
1050 |
|
1051 x = FT_MulFix( x, mac_xscale ); |
|
1052 y = FT_MulFix( y, mac_yscale ); |
|
1053 |
|
1054 #endif /* 0 */ |
|
1055 |
|
1056 } |
|
1057 |
|
1058 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) |
|
1059 { |
|
1060 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale; |
|
1061 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale; |
|
1062 |
|
1063 |
|
1064 x = FT_MulFix( x, x_scale ); |
|
1065 y = FT_MulFix( y, y_scale ); |
|
1066 |
|
1067 if ( subglyph->flags & ROUND_XY_TO_GRID ) |
|
1068 { |
|
1069 x = FT_PIX_ROUND( x ); |
|
1070 y = FT_PIX_ROUND( y ); |
|
1071 } |
|
1072 } |
|
1073 } |
|
1074 |
|
1075 if ( x || y ) |
|
1076 translate_array( num_points - num_base_points, |
|
1077 base_vec + num_base_points, |
|
1078 x, y ); |
|
1079 |
|
1080 return TT_Err_Ok; |
|
1081 } |
|
1082 |
|
1083 |
|
1084 /*************************************************************************/ |
|
1085 /* */ |
|
1086 /* <Function> */ |
|
1087 /* TT_Process_Composite_Glyph */ |
|
1088 /* */ |
|
1089 /* <Description> */ |
|
1090 /* This is slightly different from TT_Process_Simple_Glyph, in that */ |
|
1091 /* its sole purpose is to hint the glyph. Thus this function is */ |
|
1092 /* only available when bytecode interpreter is enabled. */ |
|
1093 /* */ |
|
1094 static FT_Error |
|
1095 TT_Process_Composite_Glyph( TT_Loader loader, |
|
1096 FT_UInt start_point, |
|
1097 FT_UInt start_contour ) |
|
1098 { |
|
1099 FT_Error error; |
|
1100 FT_Outline* outline; |
|
1101 FT_UInt i; |
|
1102 |
|
1103 |
|
1104 outline = &loader->gloader->base.outline; |
|
1105 |
|
1106 /* make room for phantom points */ |
|
1107 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader, |
|
1108 outline->n_points + 4, |
|
1109 0 ); |
|
1110 if ( error ) |
|
1111 return error; |
|
1112 |
|
1113 outline->points[outline->n_points ] = loader->pp1; |
|
1114 outline->points[outline->n_points + 1] = loader->pp2; |
|
1115 outline->points[outline->n_points + 2] = loader->pp3; |
|
1116 outline->points[outline->n_points + 3] = loader->pp4; |
|
1117 |
|
1118 outline->tags[outline->n_points ] = 0; |
|
1119 outline->tags[outline->n_points + 1] = 0; |
|
1120 outline->tags[outline->n_points + 2] = 0; |
|
1121 outline->tags[outline->n_points + 3] = 0; |
|
1122 |
|
1123 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
1124 |
|
1125 { |
|
1126 FT_Stream stream = loader->stream; |
|
1127 FT_UShort n_ins, max_ins; |
|
1128 FT_ULong tmp; |
|
1129 |
|
1130 |
|
1131 /* TT_Load_Composite_Glyph only gives us the offset of instructions */ |
|
1132 /* so we read them here */ |
|
1133 if ( FT_STREAM_SEEK( loader->ins_pos ) || |
|
1134 FT_READ_USHORT( n_ins ) ) |
|
1135 return error; |
|
1136 |
|
1137 FT_TRACE5(( " Instructions size = %d\n", n_ins )); |
|
1138 |
|
1139 /* check it */ |
|
1140 max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions; |
|
1141 if ( n_ins > max_ins ) |
|
1142 { |
|
1143 /* acroread ignores this field, so we only do a rough safety check */ |
|
1144 if ( (FT_Int)n_ins > loader->byte_len ) |
|
1145 { |
|
1146 FT_TRACE1(( "TT_Process_Composite_Glyph: " |
|
1147 "too many instructions (%d) for glyph with length %d\n", |
|
1148 n_ins, loader->byte_len )); |
|
1149 return TT_Err_Too_Many_Hints; |
|
1150 } |
|
1151 |
|
1152 tmp = loader->exec->glyphSize; |
|
1153 error = Update_Max( loader->exec->memory, |
|
1154 &tmp, |
|
1155 sizeof ( FT_Byte ), |
|
1156 (void*)&loader->exec->glyphIns, |
|
1157 n_ins ); |
|
1158 loader->exec->glyphSize = (FT_UShort)tmp; |
|
1159 if ( error ) |
|
1160 return error; |
|
1161 } |
|
1162 else if ( n_ins == 0 ) |
|
1163 return TT_Err_Ok; |
|
1164 |
|
1165 if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) ) |
|
1166 return error; |
|
1167 |
|
1168 loader->glyph->control_data = loader->exec->glyphIns; |
|
1169 loader->glyph->control_len = n_ins; |
|
1170 } |
|
1171 |
|
1172 #endif |
|
1173 |
|
1174 tt_prepare_zone( &loader->zone, &loader->gloader->base, |
|
1175 start_point, start_contour ); |
|
1176 |
|
1177 /* Some points are likely touched during execution of */ |
|
1178 /* instructions on components. So let's untouch them. */ |
|
1179 for ( i = start_point; i < loader->zone.n_points; i++ ) |
|
1180 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH; |
|
1181 |
|
1182 loader->zone.n_points += 4; |
|
1183 |
|
1184 return TT_Hint_Glyph( loader, 1 ); |
|
1185 } |
|
1186 |
|
1187 |
|
1188 /* Calculate the four phantom points. */ |
|
1189 /* The first two stand for horizontal origin and advance. */ |
|
1190 /* The last two stand for vertical origin and advance. */ |
|
1191 #define TT_LOADER_SET_PP( loader ) \ |
|
1192 do { \ |
|
1193 (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \ |
|
1194 (loader)->pp1.y = 0; \ |
|
1195 (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \ |
|
1196 (loader)->pp2.y = 0; \ |
|
1197 (loader)->pp3.x = 0; \ |
|
1198 (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \ |
|
1199 (loader)->pp4.x = 0; \ |
|
1200 (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \ |
|
1201 } while ( 0 ) |
|
1202 |
|
1203 |
|
1204 /*************************************************************************/ |
|
1205 /* */ |
|
1206 /* <Function> */ |
|
1207 /* load_truetype_glyph */ |
|
1208 /* */ |
|
1209 /* <Description> */ |
|
1210 /* Loads a given truetype glyph. Handles composites and uses a */ |
|
1211 /* TT_Loader object. */ |
|
1212 /* */ |
|
1213 static FT_Error |
|
1214 load_truetype_glyph( TT_Loader loader, |
|
1215 FT_UInt glyph_index, |
|
1216 FT_UInt recurse_count, |
|
1217 FT_Bool header_only ) |
|
1218 { |
|
1219 FT_Error error = TT_Err_Ok; |
|
1220 FT_Fixed x_scale, y_scale; |
|
1221 FT_ULong offset; |
|
1222 TT_Face face = (TT_Face)loader->face; |
|
1223 FT_GlyphLoader gloader = loader->gloader; |
|
1224 FT_Bool opened_frame = 0; |
|
1225 |
|
1226 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
|
1227 FT_Vector* deltas = NULL; |
|
1228 #endif |
|
1229 |
|
1230 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
1231 FT_StreamRec inc_stream; |
|
1232 FT_Data glyph_data; |
|
1233 FT_Bool glyph_data_loaded = 0; |
|
1234 #endif |
|
1235 |
|
1236 |
|
1237 /* some fonts have an incorrect value of `maxComponentDepth', */ |
|
1238 /* thus we allow depth 1 to catch the majority of them */ |
|
1239 if ( recurse_count > 1 && |
|
1240 recurse_count > face->max_profile.maxComponentDepth ) |
|
1241 { |
|
1242 error = TT_Err_Invalid_Composite; |
|
1243 goto Exit; |
|
1244 } |
|
1245 |
|
1246 /* check glyph index */ |
|
1247 if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) |
|
1248 { |
|
1249 error = TT_Err_Invalid_Glyph_Index; |
|
1250 goto Exit; |
|
1251 } |
|
1252 |
|
1253 loader->glyph_index = glyph_index; |
|
1254 |
|
1255 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
|
1256 { |
|
1257 x_scale = ((TT_Size)loader->size)->metrics.x_scale; |
|
1258 y_scale = ((TT_Size)loader->size)->metrics.y_scale; |
|
1259 } |
|
1260 else |
|
1261 { |
|
1262 x_scale = 0x10000L; |
|
1263 y_scale = 0x10000L; |
|
1264 } |
|
1265 |
|
1266 tt_get_metrics( loader, glyph_index ); |
|
1267 |
|
1268 /* Set `offset' to the start of the glyph relative to the start of */ |
|
1269 /* the `glyf' table, and `byte_len' to the length of the glyph in */ |
|
1270 /* bytes. */ |
|
1271 |
|
1272 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
1273 |
|
1274 /* If we are loading glyph data via the incremental interface, set */ |
|
1275 /* the loader stream to a memory stream reading the data returned */ |
|
1276 /* by the interface. */ |
|
1277 if ( face->root.internal->incremental_interface ) |
|
1278 { |
|
1279 error = face->root.internal->incremental_interface->funcs->get_glyph_data( |
|
1280 face->root.internal->incremental_interface->object, |
|
1281 glyph_index, &glyph_data ); |
|
1282 if ( error ) |
|
1283 goto Exit; |
|
1284 |
|
1285 glyph_data_loaded = 1; |
|
1286 offset = 0; |
|
1287 loader->byte_len = glyph_data.length; |
|
1288 |
|
1289 FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) ); |
|
1290 FT_Stream_OpenMemory( &inc_stream, |
|
1291 glyph_data.pointer, glyph_data.length ); |
|
1292 |
|
1293 loader->stream = &inc_stream; |
|
1294 } |
|
1295 else |
|
1296 |
|
1297 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
|
1298 |
|
1299 offset = tt_face_get_location( face, glyph_index, |
|
1300 (FT_UInt*)&loader->byte_len ); |
|
1301 |
|
1302 if ( loader->byte_len > 0 ) |
|
1303 { |
|
1304 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
1305 /* for the incremental interface, `glyf_offset' is always zero */ |
|
1306 if ( !loader->glyf_offset && |
|
1307 !face->root.internal->incremental_interface ) |
|
1308 #else |
|
1309 if ( !loader->glyf_offset ) |
|
1310 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
|
1311 { |
|
1312 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" )); |
|
1313 error = TT_Err_Invalid_Table; |
|
1314 goto Exit; |
|
1315 } |
|
1316 |
|
1317 error = face->access_glyph_frame( loader, glyph_index, |
|
1318 loader->glyf_offset + offset, |
|
1319 loader->byte_len ); |
|
1320 if ( error ) |
|
1321 goto Exit; |
|
1322 |
|
1323 opened_frame = 1; |
|
1324 |
|
1325 /* read glyph header first */ |
|
1326 error = face->read_glyph_header( loader ); |
|
1327 if ( error || header_only ) |
|
1328 goto Exit; |
|
1329 } |
|
1330 |
|
1331 if ( loader->byte_len == 0 || loader->n_contours == 0 ) |
|
1332 { |
|
1333 loader->bbox.xMin = 0; |
|
1334 loader->bbox.xMax = 0; |
|
1335 loader->bbox.yMin = 0; |
|
1336 loader->bbox.yMax = 0; |
|
1337 |
|
1338 if ( header_only ) |
|
1339 goto Exit; |
|
1340 |
|
1341 /* must initialize points before (possibly) overriding */ |
|
1342 /* glyph metrics from the incremental interface */ |
|
1343 TT_LOADER_SET_PP( loader ); |
|
1344 |
|
1345 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
1346 tt_get_metrics_incr_overrides( loader, glyph_index ); |
|
1347 #endif |
|
1348 |
|
1349 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
|
1350 |
|
1351 if ( ((TT_Face)(loader->face))->doblend ) |
|
1352 { |
|
1353 /* this must be done before scaling */ |
|
1354 FT_Memory memory = loader->face->memory; |
|
1355 |
|
1356 |
|
1357 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face), |
|
1358 glyph_index, &deltas, 4 ); |
|
1359 if ( error ) |
|
1360 goto Exit; |
|
1361 |
|
1362 loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y; |
|
1363 loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y; |
|
1364 loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y; |
|
1365 loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y; |
|
1366 |
|
1367 FT_FREE( deltas ); |
|
1368 } |
|
1369 |
|
1370 #endif |
|
1371 |
|
1372 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
|
1373 { |
|
1374 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); |
|
1375 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); |
|
1376 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); |
|
1377 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); |
|
1378 } |
|
1379 |
|
1380 error = TT_Err_Ok; |
|
1381 goto Exit; |
|
1382 } |
|
1383 |
|
1384 /* must initialize points before (possibly) overriding */ |
|
1385 /* glyph metrics from the incremental interface */ |
|
1386 TT_LOADER_SET_PP( loader ); |
|
1387 |
|
1388 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
1389 tt_get_metrics_incr_overrides( loader, glyph_index ); |
|
1390 #endif |
|
1391 |
|
1392 /***********************************************************************/ |
|
1393 /***********************************************************************/ |
|
1394 /***********************************************************************/ |
|
1395 |
|
1396 /* if it is a simple glyph, load it */ |
|
1397 |
|
1398 if ( loader->n_contours > 0 ) |
|
1399 { |
|
1400 error = face->read_simple_glyph( loader ); |
|
1401 if ( error ) |
|
1402 goto Exit; |
|
1403 |
|
1404 /* all data have been read */ |
|
1405 face->forget_glyph_frame( loader ); |
|
1406 opened_frame = 0; |
|
1407 |
|
1408 error = TT_Process_Simple_Glyph( loader ); |
|
1409 if ( error ) |
|
1410 goto Exit; |
|
1411 |
|
1412 FT_GlyphLoader_Add( gloader ); |
|
1413 } |
|
1414 |
|
1415 /***********************************************************************/ |
|
1416 /***********************************************************************/ |
|
1417 /***********************************************************************/ |
|
1418 |
|
1419 /* otherwise, load a composite! */ |
|
1420 else if ( loader->n_contours == -1 ) |
|
1421 { |
|
1422 FT_UInt start_point; |
|
1423 FT_UInt start_contour; |
|
1424 FT_ULong ins_pos; /* position of composite instructions, if any */ |
|
1425 |
|
1426 |
|
1427 start_point = gloader->base.outline.n_points; |
|
1428 start_contour = gloader->base.outline.n_contours; |
|
1429 |
|
1430 /* for each subglyph, read composite header */ |
|
1431 error = face->read_composite_glyph( loader ); |
|
1432 if ( error ) |
|
1433 goto Exit; |
|
1434 |
|
1435 /* store the offset of instructions */ |
|
1436 ins_pos = loader->ins_pos; |
|
1437 |
|
1438 /* all data we need are read */ |
|
1439 face->forget_glyph_frame( loader ); |
|
1440 opened_frame = 0; |
|
1441 |
|
1442 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
|
1443 |
|
1444 if ( face->doblend ) |
|
1445 { |
|
1446 FT_Int i, limit; |
|
1447 FT_SubGlyph subglyph; |
|
1448 FT_Memory memory = face->root.memory; |
|
1449 |
|
1450 |
|
1451 /* this provides additional offsets */ |
|
1452 /* for each component's translation */ |
|
1453 |
|
1454 if ( ( error = TT_Vary_Get_Glyph_Deltas( |
|
1455 face, |
|
1456 glyph_index, |
|
1457 &deltas, |
|
1458 gloader->current.num_subglyphs + 4 )) != 0 ) |
|
1459 goto Exit; |
|
1460 |
|
1461 subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs; |
|
1462 limit = gloader->current.num_subglyphs; |
|
1463 |
|
1464 for ( i = 0; i < limit; ++i, ++subglyph ) |
|
1465 { |
|
1466 if ( subglyph->flags & ARGS_ARE_XY_VALUES ) |
|
1467 { |
|
1468 /* XXX: overflow check for subglyph->{arg1,arg2}. */ |
|
1469 /* deltas[i].{x,y} must be within signed 16-bit, */ |
|
1470 /* but the restriction of summed delta is not clear */ |
|
1471 subglyph->arg1 += (FT_Int16)deltas[i].x; |
|
1472 subglyph->arg2 += (FT_Int16)deltas[i].y; |
|
1473 } |
|
1474 } |
|
1475 |
|
1476 loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y; |
|
1477 loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y; |
|
1478 loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y; |
|
1479 loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y; |
|
1480 |
|
1481 FT_FREE( deltas ); |
|
1482 } |
|
1483 |
|
1484 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ |
|
1485 |
|
1486 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
|
1487 { |
|
1488 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); |
|
1489 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); |
|
1490 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); |
|
1491 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); |
|
1492 } |
|
1493 |
|
1494 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ |
|
1495 /* `as is' in the glyph slot (the client application will be */ |
|
1496 /* responsible for interpreting these data)... */ |
|
1497 if ( loader->load_flags & FT_LOAD_NO_RECURSE ) |
|
1498 { |
|
1499 FT_GlyphLoader_Add( gloader ); |
|
1500 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE; |
|
1501 |
|
1502 goto Exit; |
|
1503 } |
|
1504 |
|
1505 /*********************************************************************/ |
|
1506 /*********************************************************************/ |
|
1507 /*********************************************************************/ |
|
1508 |
|
1509 { |
|
1510 FT_UInt n, num_base_points; |
|
1511 FT_SubGlyph subglyph = 0; |
|
1512 |
|
1513 FT_UInt num_points = start_point; |
|
1514 FT_UInt num_subglyphs = gloader->current.num_subglyphs; |
|
1515 FT_UInt num_base_subgs = gloader->base.num_subglyphs; |
|
1516 |
|
1517 FT_Stream old_stream = loader->stream; |
|
1518 FT_Int old_byte_len = loader->byte_len; |
|
1519 |
|
1520 |
|
1521 FT_GlyphLoader_Add( gloader ); |
|
1522 |
|
1523 /* read each subglyph independently */ |
|
1524 for ( n = 0; n < num_subglyphs; n++ ) |
|
1525 { |
|
1526 FT_Vector pp[4]; |
|
1527 |
|
1528 |
|
1529 /* Each time we call load_truetype_glyph in this loop, the */ |
|
1530 /* value of `gloader.base.subglyphs' can change due to table */ |
|
1531 /* reallocations. We thus need to recompute the subglyph */ |
|
1532 /* pointer on each iteration. */ |
|
1533 subglyph = gloader->base.subglyphs + num_base_subgs + n; |
|
1534 |
|
1535 pp[0] = loader->pp1; |
|
1536 pp[1] = loader->pp2; |
|
1537 pp[2] = loader->pp3; |
|
1538 pp[3] = loader->pp4; |
|
1539 |
|
1540 num_base_points = gloader->base.outline.n_points; |
|
1541 |
|
1542 error = load_truetype_glyph( loader, subglyph->index, |
|
1543 recurse_count + 1, FALSE ); |
|
1544 if ( error ) |
|
1545 goto Exit; |
|
1546 |
|
1547 /* restore subglyph pointer */ |
|
1548 subglyph = gloader->base.subglyphs + num_base_subgs + n; |
|
1549 |
|
1550 if ( !( subglyph->flags & USE_MY_METRICS ) ) |
|
1551 { |
|
1552 loader->pp1 = pp[0]; |
|
1553 loader->pp2 = pp[1]; |
|
1554 loader->pp3 = pp[2]; |
|
1555 loader->pp4 = pp[3]; |
|
1556 } |
|
1557 |
|
1558 num_points = gloader->base.outline.n_points; |
|
1559 |
|
1560 if ( num_points == num_base_points ) |
|
1561 continue; |
|
1562 |
|
1563 /* gloader->base.outline consists of three parts: */ |
|
1564 /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */ |
|
1565 /* */ |
|
1566 /* (1): exists from the beginning */ |
|
1567 /* (2): components that have been loaded so far */ |
|
1568 /* (3): the newly loaded component */ |
|
1569 TT_Process_Composite_Component( loader, subglyph, start_point, |
|
1570 num_base_points ); |
|
1571 } |
|
1572 |
|
1573 loader->stream = old_stream; |
|
1574 loader->byte_len = old_byte_len; |
|
1575 |
|
1576 /* process the glyph */ |
|
1577 loader->ins_pos = ins_pos; |
|
1578 if ( IS_HINTED( loader->load_flags ) && |
|
1579 |
|
1580 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
1581 |
|
1582 subglyph->flags & WE_HAVE_INSTR && |
|
1583 |
|
1584 #endif |
|
1585 |
|
1586 num_points > start_point ) |
|
1587 TT_Process_Composite_Glyph( loader, start_point, start_contour ); |
|
1588 |
|
1589 } |
|
1590 } |
|
1591 else |
|
1592 { |
|
1593 /* invalid composite count (negative but not -1) */ |
|
1594 error = TT_Err_Invalid_Outline; |
|
1595 goto Exit; |
|
1596 } |
|
1597 |
|
1598 /***********************************************************************/ |
|
1599 /***********************************************************************/ |
|
1600 /***********************************************************************/ |
|
1601 |
|
1602 Exit: |
|
1603 |
|
1604 if ( opened_frame ) |
|
1605 face->forget_glyph_frame( loader ); |
|
1606 |
|
1607 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
1608 |
|
1609 if ( glyph_data_loaded ) |
|
1610 face->root.internal->incremental_interface->funcs->free_glyph_data( |
|
1611 face->root.internal->incremental_interface->object, |
|
1612 &glyph_data ); |
|
1613 |
|
1614 #endif |
|
1615 |
|
1616 return error; |
|
1617 } |
|
1618 |
|
1619 |
|
1620 static FT_Error |
|
1621 compute_glyph_metrics( TT_Loader loader, |
|
1622 FT_UInt glyph_index ) |
|
1623 { |
|
1624 FT_BBox bbox; |
|
1625 TT_Face face = (TT_Face)loader->face; |
|
1626 FT_Fixed y_scale; |
|
1627 TT_GlyphSlot glyph = loader->glyph; |
|
1628 TT_Size size = (TT_Size)loader->size; |
|
1629 |
|
1630 |
|
1631 y_scale = 0x10000L; |
|
1632 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) |
|
1633 y_scale = size->root.metrics.y_scale; |
|
1634 |
|
1635 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE ) |
|
1636 FT_Outline_Get_CBox( &glyph->outline, &bbox ); |
|
1637 else |
|
1638 bbox = loader->bbox; |
|
1639 |
|
1640 /* get the device-independent horizontal advance; it is scaled later */ |
|
1641 /* by the base layer. */ |
|
1642 glyph->linearHoriAdvance = loader->linear; |
|
1643 |
|
1644 glyph->metrics.horiBearingX = bbox.xMin; |
|
1645 glyph->metrics.horiBearingY = bbox.yMax; |
|
1646 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; |
|
1647 |
|
1648 /* adjust advance width to the value contained in the hdmx table */ |
|
1649 if ( !face->postscript.isFixedPitch && |
|
1650 IS_HINTED( loader->load_flags ) ) |
|
1651 { |
|
1652 FT_Byte* widthp; |
|
1653 |
|
1654 |
|
1655 widthp = tt_face_get_device_metrics( face, |
|
1656 size->root.metrics.x_ppem, |
|
1657 glyph_index ); |
|
1658 |
|
1659 if ( widthp ) |
|
1660 glyph->metrics.horiAdvance = *widthp << 6; |
|
1661 } |
|
1662 |
|
1663 /* set glyph dimensions */ |
|
1664 glyph->metrics.width = bbox.xMax - bbox.xMin; |
|
1665 glyph->metrics.height = bbox.yMax - bbox.yMin; |
|
1666 |
|
1667 /* Now take care of vertical metrics. In the case where there is */ |
|
1668 /* no vertical information within the font (relatively common), */ |
|
1669 /* create some metrics manually */ |
|
1670 { |
|
1671 FT_Pos top; /* scaled vertical top side bearing */ |
|
1672 FT_Pos advance; /* scaled vertical advance height */ |
|
1673 |
|
1674 |
|
1675 /* Get the unscaled top bearing and advance height. */ |
|
1676 if ( face->vertical_info && |
|
1677 face->vertical.number_Of_VMetrics > 0 ) |
|
1678 { |
|
1679 top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax, |
|
1680 y_scale ); |
|
1681 |
|
1682 if ( loader->pp3.y <= loader->pp4.y ) |
|
1683 advance = 0; |
|
1684 else |
|
1685 advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y, |
|
1686 y_scale ); |
|
1687 } |
|
1688 else |
|
1689 { |
|
1690 FT_Pos height; |
|
1691 |
|
1692 |
|
1693 /* XXX Compute top side bearing and advance height in */ |
|
1694 /* Get_VMetrics instead of here. */ |
|
1695 |
|
1696 /* NOTE: The OS/2 values are the only `portable' ones, */ |
|
1697 /* which is why we use them, if there is an OS/2 */ |
|
1698 /* table in the font. Otherwise, we use the */ |
|
1699 /* values defined in the horizontal header. */ |
|
1700 |
|
1701 height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin, |
|
1702 y_scale ); |
|
1703 if ( face->os2.version != 0xFFFFU ) |
|
1704 advance = (FT_Pos)( face->os2.sTypoAscender - |
|
1705 face->os2.sTypoDescender ); |
|
1706 else |
|
1707 advance = (FT_Pos)( face->horizontal.Ascender - |
|
1708 face->horizontal.Descender ); |
|
1709 |
|
1710 top = ( advance - height ) / 2; |
|
1711 } |
|
1712 |
|
1713 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
1714 { |
|
1715 FT_Incremental_InterfaceRec* incr; |
|
1716 FT_Incremental_MetricsRec metrics; |
|
1717 FT_Error error; |
|
1718 |
|
1719 |
|
1720 incr = face->root.internal->incremental_interface; |
|
1721 |
|
1722 /* If this is an incrementally loaded font see if there are */ |
|
1723 /* overriding metrics for this glyph. */ |
|
1724 if ( incr && incr->funcs->get_glyph_metrics ) |
|
1725 { |
|
1726 metrics.bearing_x = 0; |
|
1727 metrics.bearing_y = top; |
|
1728 metrics.advance = advance; |
|
1729 |
|
1730 error = incr->funcs->get_glyph_metrics( incr->object, |
|
1731 glyph_index, |
|
1732 TRUE, |
|
1733 &metrics ); |
|
1734 if ( error ) |
|
1735 return error; |
|
1736 |
|
1737 top = metrics.bearing_y; |
|
1738 advance = metrics.advance; |
|
1739 } |
|
1740 } |
|
1741 |
|
1742 /* GWW: Do vertical metrics get loaded incrementally too? */ |
|
1743 |
|
1744 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ |
|
1745 |
|
1746 glyph->linearVertAdvance = advance; |
|
1747 |
|
1748 /* scale the metrics */ |
|
1749 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) |
|
1750 { |
|
1751 top = FT_MulFix( top, y_scale ); |
|
1752 advance = FT_MulFix( advance, y_scale ); |
|
1753 } |
|
1754 |
|
1755 /* XXX: for now, we have no better algorithm for the lsb, but it */ |
|
1756 /* should work fine. */ |
|
1757 /* */ |
|
1758 glyph->metrics.vertBearingX = glyph->metrics.horiBearingX - |
|
1759 glyph->metrics.horiAdvance / 2; |
|
1760 glyph->metrics.vertBearingY = top; |
|
1761 glyph->metrics.vertAdvance = advance; |
|
1762 } |
|
1763 |
|
1764 return 0; |
|
1765 } |
|
1766 |
|
1767 |
|
1768 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
|
1769 |
|
1770 static FT_Error |
|
1771 load_sbit_image( TT_Size size, |
|
1772 TT_GlyphSlot glyph, |
|
1773 FT_UInt glyph_index, |
|
1774 FT_Int32 load_flags ) |
|
1775 { |
|
1776 TT_Face face; |
|
1777 SFNT_Service sfnt; |
|
1778 FT_Stream stream; |
|
1779 FT_Error error; |
|
1780 TT_SBit_MetricsRec metrics; |
|
1781 |
|
1782 |
|
1783 face = (TT_Face)glyph->face; |
|
1784 sfnt = (SFNT_Service)face->sfnt; |
|
1785 stream = face->root.stream; |
|
1786 |
|
1787 error = sfnt->load_sbit_image( face, |
|
1788 size->strike_index, |
|
1789 glyph_index, |
|
1790 (FT_Int)load_flags, |
|
1791 stream, |
|
1792 &glyph->bitmap, |
|
1793 &metrics ); |
|
1794 if ( !error ) |
|
1795 { |
|
1796 glyph->outline.n_points = 0; |
|
1797 glyph->outline.n_contours = 0; |
|
1798 |
|
1799 glyph->metrics.width = (FT_Pos)metrics.width << 6; |
|
1800 glyph->metrics.height = (FT_Pos)metrics.height << 6; |
|
1801 |
|
1802 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; |
|
1803 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; |
|
1804 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; |
|
1805 |
|
1806 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; |
|
1807 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; |
|
1808 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; |
|
1809 |
|
1810 glyph->format = FT_GLYPH_FORMAT_BITMAP; |
|
1811 |
|
1812 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) |
|
1813 { |
|
1814 glyph->bitmap_left = metrics.vertBearingX; |
|
1815 glyph->bitmap_top = metrics.vertBearingY; |
|
1816 } |
|
1817 else |
|
1818 { |
|
1819 glyph->bitmap_left = metrics.horiBearingX; |
|
1820 glyph->bitmap_top = metrics.horiBearingY; |
|
1821 } |
|
1822 } |
|
1823 |
|
1824 return error; |
|
1825 } |
|
1826 |
|
1827 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ |
|
1828 |
|
1829 |
|
1830 static FT_Error |
|
1831 tt_loader_init( TT_Loader loader, |
|
1832 TT_Size size, |
|
1833 TT_GlyphSlot glyph, |
|
1834 FT_Int32 load_flags, |
|
1835 FT_Bool glyf_table_only ) |
|
1836 { |
|
1837 TT_Face face; |
|
1838 FT_Stream stream; |
|
1839 FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); |
|
1840 |
|
1841 |
|
1842 face = (TT_Face)glyph->face; |
|
1843 stream = face->root.stream; |
|
1844 |
|
1845 FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) ); |
|
1846 |
|
1847 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
1848 |
|
1849 /* load execution context */ |
|
1850 if ( IS_HINTED( load_flags ) && !glyf_table_only ) |
|
1851 { |
|
1852 TT_ExecContext exec; |
|
1853 FT_Bool grayscale; |
|
1854 |
|
1855 |
|
1856 if ( !size->cvt_ready ) |
|
1857 { |
|
1858 FT_Error error = tt_size_ready_bytecode( size, pedantic ); |
|
1859 |
|
1860 |
|
1861 if ( error ) |
|
1862 return error; |
|
1863 } |
|
1864 |
|
1865 /* query new execution context */ |
|
1866 exec = size->debug ? size->context |
|
1867 : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; |
|
1868 if ( !exec ) |
|
1869 return TT_Err_Could_Not_Find_Context; |
|
1870 |
|
1871 grayscale = |
|
1872 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO ); |
|
1873 |
|
1874 TT_Load_Context( exec, face, size ); |
|
1875 |
|
1876 /* a change from mono to grayscale rendering (and vice versa) */ |
|
1877 /* requires a re-execution of the CVT program */ |
|
1878 if ( grayscale != exec->grayscale ) |
|
1879 { |
|
1880 FT_UInt i; |
|
1881 |
|
1882 |
|
1883 FT_TRACE4(( "tt_loader_init: grayscale change," |
|
1884 " re-executing `prep' table\n" )); |
|
1885 |
|
1886 exec->grayscale = grayscale; |
|
1887 |
|
1888 for ( i = 0; i < size->cvt_size; i++ ) |
|
1889 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); |
|
1890 tt_size_run_prep( size, pedantic ); |
|
1891 } |
|
1892 |
|
1893 /* see whether the cvt program has disabled hinting */ |
|
1894 if ( exec->GS.instruct_control & 1 ) |
|
1895 load_flags |= FT_LOAD_NO_HINTING; |
|
1896 |
|
1897 /* load default graphics state -- if needed */ |
|
1898 if ( exec->GS.instruct_control & 2 ) |
|
1899 exec->GS = tt_default_graphics_state; |
|
1900 |
|
1901 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); |
|
1902 loader->exec = exec; |
|
1903 loader->instructions = exec->glyphIns; |
|
1904 } |
|
1905 |
|
1906 #endif /* TT_USE_BYTECODE_INTERPRETER */ |
|
1907 |
|
1908 /* seek to the beginning of the glyph table -- for Type 42 fonts */ |
|
1909 /* the table might be accessed from a Postscript stream or something */ |
|
1910 /* else... */ |
|
1911 |
|
1912 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
|
1913 |
|
1914 if ( face->root.internal->incremental_interface ) |
|
1915 loader->glyf_offset = 0; |
|
1916 else |
|
1917 |
|
1918 #endif |
|
1919 |
|
1920 { |
|
1921 FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 ); |
|
1922 |
|
1923 |
|
1924 if ( error == TT_Err_Table_Missing ) |
|
1925 loader->glyf_offset = 0; |
|
1926 else if ( error ) |
|
1927 { |
|
1928 FT_ERROR(( "tt_loader_init: could not access glyph table\n" )); |
|
1929 return error; |
|
1930 } |
|
1931 else |
|
1932 loader->glyf_offset = FT_STREAM_POS(); |
|
1933 } |
|
1934 |
|
1935 /* get face's glyph loader */ |
|
1936 if ( !glyf_table_only ) |
|
1937 { |
|
1938 FT_GlyphLoader gloader = glyph->internal->loader; |
|
1939 |
|
1940 |
|
1941 FT_GlyphLoader_Rewind( gloader ); |
|
1942 loader->gloader = gloader; |
|
1943 } |
|
1944 |
|
1945 loader->load_flags = load_flags; |
|
1946 |
|
1947 loader->face = (FT_Face)face; |
|
1948 loader->size = (FT_Size)size; |
|
1949 loader->glyph = (FT_GlyphSlot)glyph; |
|
1950 loader->stream = stream; |
|
1951 |
|
1952 return TT_Err_Ok; |
|
1953 } |
|
1954 |
|
1955 |
|
1956 /*************************************************************************/ |
|
1957 /* */ |
|
1958 /* <Function> */ |
|
1959 /* TT_Load_Glyph */ |
|
1960 /* */ |
|
1961 /* <Description> */ |
|
1962 /* A function used to load a single glyph within a given glyph slot, */ |
|
1963 /* for a given size. */ |
|
1964 /* */ |
|
1965 /* <Input> */ |
|
1966 /* glyph :: A handle to a target slot object where the glyph */ |
|
1967 /* will be loaded. */ |
|
1968 /* */ |
|
1969 /* size :: A handle to the source face size at which the glyph */ |
|
1970 /* must be scaled/loaded. */ |
|
1971 /* */ |
|
1972 /* glyph_index :: The index of the glyph in the font file. */ |
|
1973 /* */ |
|
1974 /* load_flags :: A flag indicating what to load for this glyph. The */ |
|
1975 /* FT_LOAD_XXX constants can be used to control the */ |
|
1976 /* glyph loading process (e.g., whether the outline */ |
|
1977 /* should be scaled, whether to load bitmaps or not, */ |
|
1978 /* whether to hint the outline, etc). */ |
|
1979 /* */ |
|
1980 /* <Return> */ |
|
1981 /* FreeType error code. 0 means success. */ |
|
1982 /* */ |
|
1983 FT_LOCAL_DEF( FT_Error ) |
|
1984 TT_Load_Glyph( TT_Size size, |
|
1985 TT_GlyphSlot glyph, |
|
1986 FT_UInt glyph_index, |
|
1987 FT_Int32 load_flags ) |
|
1988 { |
|
1989 TT_Face face; |
|
1990 FT_Error error; |
|
1991 TT_LoaderRec loader; |
|
1992 |
|
1993 |
|
1994 face = (TT_Face)glyph->face; |
|
1995 error = TT_Err_Ok; |
|
1996 |
|
1997 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
|
1998 |
|
1999 /* try to load embedded bitmap if any */ |
|
2000 /* */ |
|
2001 /* XXX: The convention should be emphasized in */ |
|
2002 /* the documents because it can be confusing. */ |
|
2003 if ( size->strike_index != 0xFFFFFFFFUL && |
|
2004 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) |
|
2005 { |
|
2006 error = load_sbit_image( size, glyph, glyph_index, load_flags ); |
|
2007 if ( !error ) |
|
2008 { |
|
2009 FT_Face root = &face->root; |
|
2010 |
|
2011 |
|
2012 if ( FT_IS_SCALABLE( root ) ) |
|
2013 { |
|
2014 /* for the bbox we need the header only */ |
|
2015 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE ); |
|
2016 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE ); |
|
2017 glyph->linearHoriAdvance = loader.linear; |
|
2018 glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax - |
|
2019 loader.vadvance; |
|
2020 } |
|
2021 |
|
2022 return TT_Err_Ok; |
|
2023 } |
|
2024 } |
|
2025 |
|
2026 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ |
|
2027 |
|
2028 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ |
|
2029 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid ) |
|
2030 return TT_Err_Invalid_Size_Handle; |
|
2031 |
|
2032 if ( load_flags & FT_LOAD_SBITS_ONLY ) |
|
2033 return TT_Err_Invalid_Argument; |
|
2034 |
|
2035 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); |
|
2036 if ( error ) |
|
2037 return error; |
|
2038 |
|
2039 glyph->format = FT_GLYPH_FORMAT_OUTLINE; |
|
2040 glyph->num_subglyphs = 0; |
|
2041 glyph->outline.flags = 0; |
|
2042 |
|
2043 /* main loading loop */ |
|
2044 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE ); |
|
2045 if ( !error ) |
|
2046 { |
|
2047 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE ) |
|
2048 { |
|
2049 glyph->num_subglyphs = loader.gloader->base.num_subglyphs; |
|
2050 glyph->subglyphs = loader.gloader->base.subglyphs; |
|
2051 } |
|
2052 else |
|
2053 { |
|
2054 glyph->outline = loader.gloader->base.outline; |
|
2055 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; |
|
2056 |
|
2057 /* Translate array so that (0,0) is the glyph's origin. Note */ |
|
2058 /* that this behaviour is independent on the value of bit 1 of */ |
|
2059 /* the `flags' field in the `head' table -- at least major */ |
|
2060 /* applications like Acroread indicate that. */ |
|
2061 if ( loader.pp1.x ) |
|
2062 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 ); |
|
2063 } |
|
2064 |
|
2065 #ifdef TT_USE_BYTECODE_INTERPRETER |
|
2066 |
|
2067 if ( IS_HINTED( load_flags ) ) |
|
2068 { |
|
2069 if ( loader.exec->GS.scan_control ) |
|
2070 { |
|
2071 /* convert scan conversion mode to FT_OUTLINE_XXX flags */ |
|
2072 switch ( loader.exec->GS.scan_type ) |
|
2073 { |
|
2074 case 0: /* simple drop-outs including stubs */ |
|
2075 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS; |
|
2076 break; |
|
2077 case 1: /* simple drop-outs excluding stubs */ |
|
2078 /* nothing; it's the default rendering mode */ |
|
2079 break; |
|
2080 case 4: /* smart drop-outs including stubs */ |
|
2081 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS | |
|
2082 FT_OUTLINE_INCLUDE_STUBS; |
|
2083 break; |
|
2084 case 5: /* smart drop-outs excluding stubs */ |
|
2085 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS; |
|
2086 break; |
|
2087 |
|
2088 default: /* no drop-out control */ |
|
2089 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; |
|
2090 break; |
|
2091 } |
|
2092 } |
|
2093 else |
|
2094 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; |
|
2095 } |
|
2096 |
|
2097 #endif /* TT_USE_BYTECODE_INTERPRETER */ |
|
2098 |
|
2099 compute_glyph_metrics( &loader, glyph_index ); |
|
2100 } |
|
2101 |
|
2102 /* Set the `high precision' bit flag. */ |
|
2103 /* This is _critical_ to get correct output for monochrome */ |
|
2104 /* TrueType glyphs at all sizes using the bytecode interpreter. */ |
|
2105 /* */ |
|
2106 if ( !( load_flags & FT_LOAD_NO_SCALE ) && |
|
2107 size->root.metrics.y_ppem < 24 ) |
|
2108 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; |
|
2109 |
|
2110 return error; |
|
2111 } |
|
2112 |
|
2113 |
|
2114 /* END */ |
|