1/****************************************************************************
2 *
3 * ttgload.c
4 *
5 * TrueType Glyph Loader (body).
6 *
7 * Copyright (C) 1996-2019 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 <ft2build.h>
20#include FT_INTERNAL_DEBUG_H
21#include FT_CONFIG_CONFIG_H
22#include FT_INTERNAL_CALC_H
23#include FT_INTERNAL_STREAM_H
24#include FT_INTERNAL_SFNT_H
25#include FT_TRUETYPE_TAGS_H
26#include FT_OUTLINE_H
27#include FT_DRIVER_H
28#include FT_LIST_H
29
30#include "ttgload.h"
31#include "ttpload.h"
32
33#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
34#include "ttgxvar.h"
35#endif
36
37#include "tterrors.h"
38#include "ttsubpix.h"
39
40
41 /**************************************************************************
42 *
43 * The macro FT_COMPONENT is used in trace mode. It is an implicit
44 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
45 * messages during execution.
46 */
47#undef FT_COMPONENT
48#define FT_COMPONENT ttgload
49
50
51 /**************************************************************************
52 *
53 * Simple glyph flags.
54 */
55#define ON_CURVE_POINT 0x01 /* same value as FT_CURVE_TAG_ON */
56#define X_SHORT_VECTOR 0x02
57#define Y_SHORT_VECTOR 0x04
58#define REPEAT_FLAG 0x08
59#define X_POSITIVE 0x10 /* two meanings depending on X_SHORT_VECTOR */
60#define SAME_X 0x10
61#define Y_POSITIVE 0x20 /* two meanings depending on Y_SHORT_VECTOR */
62#define SAME_Y 0x20
63#define OVERLAP_SIMPLE 0x40 /* we ignore this value */
64
65
66 /**************************************************************************
67 *
68 * Composite glyph flags.
69 */
70#define ARGS_ARE_WORDS 0x0001
71#define ARGS_ARE_XY_VALUES 0x0002
72#define ROUND_XY_TO_GRID 0x0004
73#define WE_HAVE_A_SCALE 0x0008
74/* reserved 0x0010 */
75#define MORE_COMPONENTS 0x0020
76#define WE_HAVE_AN_XY_SCALE 0x0040
77#define WE_HAVE_A_2X2 0x0080
78#define WE_HAVE_INSTR 0x0100
79#define USE_MY_METRICS 0x0200
80#define OVERLAP_COMPOUND 0x0400 /* we ignore this value */
81#define SCALED_COMPONENT_OFFSET 0x0800
82#define UNSCALED_COMPONENT_OFFSET 0x1000
83
84
85 /**************************************************************************
86 *
87 * Return the horizontal metrics in font units for a given glyph.
88 */
89 FT_LOCAL_DEF( void )
90 TT_Get_HMetrics( TT_Face face,
91 FT_UInt idx,
92 FT_Short* lsb,
93 FT_UShort* aw )
94 {
95 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
96
97 FT_TRACE5(( " advance width (font units): %d\n", *aw ));
98 FT_TRACE5(( " left side bearing (font units): %d\n", *lsb ));
99 }
100
101
102 /**************************************************************************
103 *
104 * Return the vertical metrics in font units for a given glyph.
105 * See function `tt_loader_set_pp' below for explanations.
106 */
107 FT_LOCAL_DEF( void )
108 TT_Get_VMetrics( TT_Face face,
109 FT_UInt idx,
110 FT_Pos yMax,
111 FT_Short* tsb,
112 FT_UShort* ah )
113 {
114 if ( face->vertical_info )
115 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
116
117 else if ( face->os2.version != 0xFFFFU )
118 {
119 *tsb = (FT_Short)( face->os2.sTypoAscender - yMax );
120 *ah = (FT_UShort)FT_ABS( face->os2.sTypoAscender -
121 face->os2.sTypoDescender );
122 }
123
124 else
125 {
126 *tsb = (FT_Short)( face->horizontal.Ascender - yMax );
127 *ah = (FT_UShort)FT_ABS( face->horizontal.Ascender -
128 face->horizontal.Descender );
129 }
130
131 FT_TRACE5(( " advance height (font units): %d\n", *ah ));
132 FT_TRACE5(( " top side bearing (font units): %d\n", *tsb ));
133 }
134
135
136 static FT_Error
137 tt_get_metrics( TT_Loader loader,
138 FT_UInt glyph_index )
139 {
140 TT_Face face = loader->face;
141#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
142 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
143#endif
144
145 FT_Error error;
146 FT_Stream stream = loader->stream;
147
148 FT_Short left_bearing = 0, top_bearing = 0;
149 FT_UShort advance_width = 0, advance_height = 0;
150
151 /* we must preserve the stream position */
152 /* (which gets altered by the metrics functions) */
153 FT_ULong pos = FT_STREAM_POS();
154
155
156 TT_Get_HMetrics( face, glyph_index,
157 &left_bearing,
158 &advance_width );
159 TT_Get_VMetrics( face, glyph_index,
160 loader->bbox.yMax,
161 &top_bearing,
162 &advance_height );
163
164 if ( FT_STREAM_SEEK( pos ) )
165 return error;
166
167 loader->left_bearing = left_bearing;
168 loader->advance = advance_width;
169 loader->top_bearing = top_bearing;
170 loader->vadvance = advance_height;
171
172#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
173 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
174 loader->exec )
175 {
176 loader->exec->sph_tweak_flags = 0;
177
178 /* This may not be the right place for this, but it works... */
179 /* Note that we have to unconditionally load the tweaks since */
180 /* it is possible that glyphs individually switch ClearType's */
181 /* backward compatibility mode on and off. */
182 sph_set_tweaks( loader, glyph_index );
183 }
184#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
185
186 if ( !loader->linear_def )
187 {
188 loader->linear_def = 1;
189 loader->linear = advance_width;
190 }
191
192 return FT_Err_Ok;
193 }
194
195
196#ifdef FT_CONFIG_OPTION_INCREMENTAL
197
198 static void
199 tt_get_metrics_incr_overrides( TT_Loader loader,
200 FT_UInt glyph_index )
201 {
202 TT_Face face = loader->face;
203
204 FT_Short left_bearing = 0, top_bearing = 0;
205 FT_UShort advance_width = 0, advance_height = 0;
206
207
208 /* If this is an incrementally loaded font check whether there are */
209 /* overriding metrics for this glyph. */
210 if ( face->root.internal->incremental_interface &&
211 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
212 {
213 FT_Incremental_MetricsRec incr_metrics;
214 FT_Error error;
215
216
217 incr_metrics.bearing_x = loader->left_bearing;
218 incr_metrics.bearing_y = 0;
219 incr_metrics.advance = loader->advance;
220 incr_metrics.advance_v = 0;
221
222 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
223 face->root.internal->incremental_interface->object,
224 glyph_index, FALSE, &incr_metrics );
225 if ( error )
226 goto Exit;
227
228 left_bearing = (FT_Short)incr_metrics.bearing_x;
229 advance_width = (FT_UShort)incr_metrics.advance;
230
231#if 0
232
233 /* GWW: Do I do the same for vertical metrics? */
234 incr_metrics.bearing_x = 0;
235 incr_metrics.bearing_y = loader->top_bearing;
236 incr_metrics.advance = loader->vadvance;
237
238 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
239 face->root.internal->incremental_interface->object,
240 glyph_index, TRUE, &incr_metrics );
241 if ( error )
242 goto Exit;
243
244 top_bearing = (FT_Short)incr_metrics.bearing_y;
245 advance_height = (FT_UShort)incr_metrics.advance;
246
247#endif /* 0 */
248
249 loader->left_bearing = left_bearing;
250 loader->advance = advance_width;
251 loader->top_bearing = top_bearing;
252 loader->vadvance = advance_height;
253
254 if ( !loader->linear_def )
255 {
256 loader->linear_def = 1;
257 loader->linear = advance_width;
258 }
259 }
260
261 Exit:
262 return;
263 }
264
265#endif /* FT_CONFIG_OPTION_INCREMENTAL */
266
267
268 /**************************************************************************
269 *
270 * The following functions are used by default with TrueType fonts.
271 * However, they can be replaced by alternatives if we need to support
272 * TrueType-compressed formats (like MicroType) in the future.
273 *
274 */
275
276 FT_CALLBACK_DEF( FT_Error )
277 TT_Access_Glyph_Frame( TT_Loader loader,
278 FT_UInt glyph_index,
279 FT_ULong offset,
280 FT_UInt byte_count )
281 {
282 FT_Error error;
283 FT_Stream stream = loader->stream;
284
285 FT_UNUSED( glyph_index );
286
287
288 /* the following line sets the `error' variable through macros! */
289 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
290 return error;
291
292 loader->cursor = stream->cursor;
293 loader->limit = stream->limit;
294
295 return FT_Err_Ok;
296 }
297
298
299 FT_CALLBACK_DEF( void )
300 TT_Forget_Glyph_Frame( TT_Loader loader )
301 {
302 FT_Stream stream = loader->stream;
303
304
305 FT_FRAME_EXIT();
306 }
307
308
309 FT_CALLBACK_DEF( FT_Error )
310 TT_Load_Glyph_Header( TT_Loader loader )
311 {
312 FT_Byte* p = loader->cursor;
313 FT_Byte* limit = loader->limit;
314
315
316 if ( p + 10 > limit )
317 return FT_THROW( Invalid_Outline );
318
319 loader->n_contours = FT_NEXT_SHORT( p );
320
321 loader->bbox.xMin = FT_NEXT_SHORT( p );
322 loader->bbox.yMin = FT_NEXT_SHORT( p );
323 loader->bbox.xMax = FT_NEXT_SHORT( p );
324 loader->bbox.yMax = FT_NEXT_SHORT( p );
325
326 FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
327 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
328 loader->bbox.xMax ));
329 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
330 loader->bbox.yMax ));
331 loader->cursor = p;
332
333 return FT_Err_Ok;
334 }
335
336
337 FT_CALLBACK_DEF( FT_Error )
338 TT_Load_Simple_Glyph( TT_Loader load )
339 {
340 FT_Error error;
341 FT_Byte* p = load->cursor;
342 FT_Byte* limit = load->limit;
343 FT_GlyphLoader gloader = load->gloader;
344 FT_Int n_contours = load->n_contours;
345 FT_Outline* outline;
346 FT_UShort n_ins;
347 FT_Int n_points;
348
349 FT_Byte *flag, *flag_limit;
350 FT_Byte c, count;
351 FT_Vector *vec, *vec_limit;
352 FT_Pos x, y;
353 FT_Short *cont, *cont_limit, prev_cont;
354 FT_Int xy_size = 0;
355
356
357 /* check that we can add the contours to the glyph */
358 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
359 if ( error )
360 goto Fail;
361
362 /* reading the contours' endpoints & number of points */
363 cont = gloader->current.outline.contours;
364 cont_limit = cont + n_contours;
365
366 /* check space for contours array + instructions count */
367 if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
368 goto Invalid_Outline;
369
370 prev_cont = FT_NEXT_SHORT( p );
371
372 if ( n_contours > 0 )
373 cont[0] = prev_cont;
374
375 if ( prev_cont < 0 )
376 goto Invalid_Outline;
377
378 for ( cont++; cont < cont_limit; cont++ )
379 {
380 cont[0] = FT_NEXT_SHORT( p );
381 if ( cont[0] <= prev_cont )
382 {
383 /* unordered contours: this is invalid */
384 goto Invalid_Outline;
385 }
386 prev_cont = cont[0];
387 }
388
389 n_points = 0;
390 if ( n_contours > 0 )
391 {
392 n_points = cont[-1] + 1;
393 if ( n_points < 0 )
394 goto Invalid_Outline;
395 }
396
397 FT_TRACE5(( " # of points: %d\n", n_points ));
398
399 /* note that we will add four phantom points later */
400 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
401 if ( error )
402 goto Fail;
403
404 /* reading the bytecode instructions */
405 load->glyph->control_len = 0;
406 load->glyph->control_data = NULL;
407
408 if ( p + 2 > limit )
409 goto Invalid_Outline;
410
411 n_ins = FT_NEXT_USHORT( p );
412
413 FT_TRACE5(( " Instructions size: %u\n", n_ins ));
414
415#ifdef TT_USE_BYTECODE_INTERPRETER
416
417 if ( IS_HINTED( load->load_flags ) )
418 {
419 FT_ULong tmp;
420
421
422 /* check instructions size */
423 if ( ( limit - p ) < n_ins )
424 {
425 FT_TRACE1(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
426 error = FT_THROW( Too_Many_Hints );
427 goto Fail;
428 }
429
430 /* we don't trust `maxSizeOfInstructions' in the `maxp' table */
431 /* and thus update the bytecode array size by ourselves */
432
433 tmp = load->exec->glyphSize;
434 error = Update_Max( load->exec->memory,
435 &tmp,
436 sizeof ( FT_Byte ),
437 (void*)&load->exec->glyphIns,
438 n_ins );
439
440 load->exec->glyphSize = (FT_UShort)tmp;
441 if ( error )
442 return error;
443
444 load->glyph->control_len = n_ins;
445 load->glyph->control_data = load->exec->glyphIns;
446
447 if ( n_ins )
448 FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
449 }
450
451#endif /* TT_USE_BYTECODE_INTERPRETER */
452
453 p += n_ins;
454
455 outline = &gloader->current.outline;
456
457 /* reading the point tags */
458 flag = (FT_Byte*)outline->tags;
459 flag_limit = flag + n_points;
460
461 FT_ASSERT( flag );
462
463 while ( flag < flag_limit )
464 {
465 if ( p + 1 > limit )
466 goto Invalid_Outline;
467
468 *flag++ = c = FT_NEXT_BYTE( p );
469 if ( c & REPEAT_FLAG )
470 {
471 if ( p + 1 > limit )
472 goto Invalid_Outline;
473
474 count = FT_NEXT_BYTE( p );
475 if ( flag + (FT_Int)count > flag_limit )
476 goto Invalid_Outline;
477
478 for ( ; count > 0; count-- )
479 *flag++ = c;
480 }
481 }
482
483 /* reading the X coordinates */
484
485 vec = outline->points;
486 vec_limit = vec + n_points;
487 flag = (FT_Byte*)outline->tags;
488 x = 0;
489
490 if ( p + xy_size > limit )
491 goto Invalid_Outline;
492
493 for ( ; vec < vec_limit; vec++, flag++ )
494 {
495 FT_Pos delta = 0;
496 FT_Byte f = *flag;
497
498
499 if ( f & X_SHORT_VECTOR )
500 {
501 if ( p + 1 > limit )
502 goto Invalid_Outline;
503
504 delta = (FT_Pos)FT_NEXT_BYTE( p );
505 if ( !( f & X_POSITIVE ) )
506 delta = -delta;
507 }
508 else if ( !( f & SAME_X ) )
509 {
510 if ( p + 2 > limit )
511 goto Invalid_Outline;
512
513 delta = (FT_Pos)FT_NEXT_SHORT( p );
514 }
515
516 x += delta;
517 vec->x = x;
518 }
519
520 /* reading the Y coordinates */
521
522 vec = gloader->current.outline.points;
523 vec_limit = vec + n_points;
524 flag = (FT_Byte*)outline->tags;
525 y = 0;
526
527 for ( ; vec < vec_limit; vec++, flag++ )
528 {
529 FT_Pos delta = 0;
530 FT_Byte f = *flag;
531
532
533 if ( f & Y_SHORT_VECTOR )
534 {
535 if ( p + 1 > limit )
536 goto Invalid_Outline;
537
538 delta = (FT_Pos)FT_NEXT_BYTE( p );
539 if ( !( f & Y_POSITIVE ) )
540 delta = -delta;
541 }
542 else if ( !( f & SAME_Y ) )
543 {
544 if ( p + 2 > limit )
545 goto Invalid_Outline;
546
547 delta = (FT_Pos)FT_NEXT_SHORT( p );
548 }
549
550 y += delta;
551 vec->y = y;
552
553 /* the cast is for stupid compilers */
554 *flag = (FT_Byte)( f & ON_CURVE_POINT );
555 }
556
557 outline->n_points = (FT_Short)n_points;
558 outline->n_contours = (FT_Short)n_contours;
559
560 load->cursor = p;
561
562 Fail:
563 return error;
564
565 Invalid_Outline:
566 error = FT_THROW( Invalid_Outline );
567 goto Fail;
568 }
569
570
571 FT_CALLBACK_DEF( FT_Error )
572 TT_Load_Composite_Glyph( TT_Loader loader )
573 {
574 FT_Error error;
575 FT_Byte* p = loader->cursor;
576 FT_Byte* limit = loader->limit;
577 FT_GlyphLoader gloader = loader->gloader;
578 FT_Long num_glyphs = loader->face->root.num_glyphs;
579 FT_SubGlyph subglyph;
580 FT_UInt num_subglyphs;
581
582
583 num_subglyphs = 0;
584
585 do
586 {
587 FT_Fixed xx, xy, yy, yx;
588 FT_UInt count;
589
590
591 /* check that we can load a new subglyph */
592 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
593 if ( error )
594 goto Fail;
595
596 /* check space */
597 if ( p + 4 > limit )
598 goto Invalid_Composite;
599
600 subglyph = gloader->current.subglyphs + num_subglyphs;
601
602 subglyph->arg1 = subglyph->arg2 = 0;
603
604 subglyph->flags = FT_NEXT_USHORT( p );
605 subglyph->index = FT_NEXT_USHORT( p );
606
607 /* we reject composites that have components */
608 /* with invalid glyph indices */
609 if ( subglyph->index >= num_glyphs )
610 goto Invalid_Composite;
611
612 /* check space */
613 count = 2;
614 if ( subglyph->flags & ARGS_ARE_WORDS )
615 count += 2;
616 if ( subglyph->flags & WE_HAVE_A_SCALE )
617 count += 2;
618 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
619 count += 4;
620 else if ( subglyph->flags & WE_HAVE_A_2X2 )
621 count += 8;
622
623 if ( p + count > limit )
624 goto Invalid_Composite;
625
626 /* read arguments */
627 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
628 {
629 if ( subglyph->flags & ARGS_ARE_WORDS )
630 {
631 subglyph->arg1 = FT_NEXT_SHORT( p );
632 subglyph->arg2 = FT_NEXT_SHORT( p );
633 }
634 else
635 {
636 subglyph->arg1 = FT_NEXT_CHAR( p );
637 subglyph->arg2 = FT_NEXT_CHAR( p );
638 }
639 }
640 else
641 {
642 if ( subglyph->flags & ARGS_ARE_WORDS )
643 {
644 subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p );
645 subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p );
646 }
647 else
648 {
649 subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p );
650 subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p );
651 }
652 }
653
654 /* read transform */
655 xx = yy = 0x10000L;
656 xy = yx = 0;
657
658 if ( subglyph->flags & WE_HAVE_A_SCALE )
659 {
660 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
661 yy = xx;
662 }
663 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
664 {
665 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
666 yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
667 }
668 else if ( subglyph->flags & WE_HAVE_A_2X2 )
669 {
670 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
671 yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
672 xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
673 yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
674 }
675
676 subglyph->transform.xx = xx;
677 subglyph->transform.xy = xy;
678 subglyph->transform.yx = yx;
679 subglyph->transform.yy = yy;
680
681 num_subglyphs++;
682
683 } while ( subglyph->flags & MORE_COMPONENTS );
684
685 gloader->current.num_subglyphs = num_subglyphs;
686 FT_TRACE5(( " %d component%s\n",
687 num_subglyphs,
688 num_subglyphs > 1 ? "s" : "" ));
689
690#ifdef FT_DEBUG_LEVEL_TRACE
691 {
692 FT_UInt i;
693
694
695 subglyph = gloader->current.subglyphs;
696
697 for ( i = 0; i < num_subglyphs; i++ )
698 {
699 if ( num_subglyphs > 1 )
700 FT_TRACE7(( " subglyph %d:\n", i ));
701
702 FT_TRACE7(( " glyph index: %d\n", subglyph->index ));
703
704 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
705 FT_TRACE7(( " offset: x=%d, y=%d\n",
706 subglyph->arg1,
707 subglyph->arg2 ));
708 else
709 FT_TRACE7(( " matching points: base=%d, component=%d\n",
710 subglyph->arg1,
711 subglyph->arg2 ));
712
713 if ( subglyph->flags & WE_HAVE_A_SCALE )
714 FT_TRACE7(( " scaling: %f\n",
715 subglyph->transform.xx / 65536.0 ));
716 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
717 FT_TRACE7(( " scaling: x=%f, y=%f\n",
718 subglyph->transform.xx / 65536.0,
719 subglyph->transform.yy / 65536.0 ));
720 else if ( subglyph->flags & WE_HAVE_A_2X2 )
721 FT_TRACE7(( " scaling: xx=%f, yx=%f\n"
722 " xy=%f, yy=%f\n",
723 subglyph->transform.xx / 65536.0,
724 subglyph->transform.yx / 65536.0,
725 subglyph->transform.xy / 65536.0,
726 subglyph->transform.yy / 65536.0 ));
727
728 subglyph++;
729 }
730 }
731#endif /* FT_DEBUG_LEVEL_TRACE */
732
733#ifdef TT_USE_BYTECODE_INTERPRETER
734
735 {
736 FT_Stream stream = loader->stream;
737
738
739 /* we must undo the FT_FRAME_ENTER in order to point */
740 /* to the composite instructions, if we find some. */
741 /* We will process them later. */
742 /* */
743 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
744 p - limit );
745 }
746
747#endif
748
749 loader->cursor = p;
750
751 Fail:
752 return error;
753
754 Invalid_Composite:
755 error = FT_THROW( Invalid_Composite );
756 goto Fail;
757 }
758
759
760 FT_LOCAL_DEF( void )
761 TT_Init_Glyph_Loading( TT_Face face )
762 {
763 face->access_glyph_frame = TT_Access_Glyph_Frame;
764 face->read_glyph_header = TT_Load_Glyph_Header;
765 face->read_simple_glyph = TT_Load_Simple_Glyph;
766 face->read_composite_glyph = TT_Load_Composite_Glyph;
767 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
768 }
769
770
771 static void
772 tt_prepare_zone( TT_GlyphZone zone,
773 FT_GlyphLoad load,
774 FT_UInt start_point,
775 FT_UInt start_contour )
776 {
777 zone->n_points = (FT_UShort)load->outline.n_points -
778 (FT_UShort)start_point;
779 zone->n_contours = load->outline.n_contours -
780 (FT_Short)start_contour;
781 zone->org = load->extra_points + start_point;
782 zone->cur = load->outline.points + start_point;
783 zone->orus = load->extra_points2 + start_point;
784 zone->tags = (FT_Byte*)load->outline.tags + start_point;
785 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
786 zone->first_point = (FT_UShort)start_point;
787 }
788
789
790 /**************************************************************************
791 *
792 * @Function:
793 * TT_Hint_Glyph
794 *
795 * @Description:
796 * Hint the glyph using the zone prepared by the caller. Note that
797 * the zone is supposed to include four phantom points.
798 */
799 static FT_Error
800 TT_Hint_Glyph( TT_Loader loader,
801 FT_Bool is_composite )
802 {
803#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
804 defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
805 TT_Face face = loader->face;
806 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
807#endif
808
809 TT_GlyphZone zone = &loader->zone;
810
811#ifdef TT_USE_BYTECODE_INTERPRETER
812 FT_Long n_ins;
813#else
814 FT_UNUSED( is_composite );
815#endif
816
817
818#ifdef TT_USE_BYTECODE_INTERPRETER
819 n_ins = loader->glyph->control_len;
820
821 /* save original point positions in `org' array */
822 if ( n_ins > 0 )
823 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
824
825 /* Reset graphics state. */
826 loader->exec->GS = loader->size->GS;
827
828 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
829 /* completely refer to the (already) hinted subglyphs. */
830 if ( is_composite )
831 {
832 loader->exec->metrics.x_scale = 1 << 16;
833 loader->exec->metrics.y_scale = 1 << 16;
834
835 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
836 }
837 else
838 {
839 loader->exec->metrics.x_scale = loader->size->metrics->x_scale;
840 loader->exec->metrics.y_scale = loader->size->metrics->y_scale;
841 }
842#endif
843
844 /* round phantom points */
845 zone->cur[zone->n_points - 4].x =
846 FT_PIX_ROUND( zone->cur[zone->n_points - 4].x );
847 zone->cur[zone->n_points - 3].x =
848 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
849 zone->cur[zone->n_points - 2].y =
850 FT_PIX_ROUND( zone->cur[zone->n_points - 2].y );
851 zone->cur[zone->n_points - 1].y =
852 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
853
854#ifdef TT_USE_BYTECODE_INTERPRETER
855
856 if ( n_ins > 0 )
857 {
858 FT_Error error;
859
860 FT_GlyphLoader gloader = loader->gloader;
861 FT_Outline current_outline = gloader->current.outline;
862
863
864 TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
865 loader->exec->glyphIns, n_ins );
866
867 loader->exec->is_composite = is_composite;
868 loader->exec->pts = *zone;
869
870 error = TT_Run_Context( loader->exec );
871 if ( error && loader->exec->pedantic_hinting )
872 return error;
873
874 /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
875 current_outline.tags[0] |=
876 ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
877 }
878
879#endif
880
881#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
882 /* Save possibly modified glyph phantom points unless in v40 backward */
883 /* compatibility mode, where no movement on the x axis means no reason */
884 /* to change bearings or advance widths. */
885 if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
886 loader->exec->backward_compatibility ) )
887 {
888#endif
889 loader->pp1 = zone->cur[zone->n_points - 4];
890 loader->pp2 = zone->cur[zone->n_points - 3];
891 loader->pp3 = zone->cur[zone->n_points - 2];
892 loader->pp4 = zone->cur[zone->n_points - 1];
893#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
894 }
895#endif
896
897#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
898 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
899 {
900 if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
901 FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 );
902
903 else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
904 FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
905 }
906#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
907
908 return FT_Err_Ok;
909 }
910
911
912 /**************************************************************************
913 *
914 * @Function:
915 * TT_Process_Simple_Glyph
916 *
917 * @Description:
918 * Once a simple glyph has been loaded, it needs to be processed.
919 * Usually, this means scaling and hinting through bytecode
920 * interpretation.
921 */
922 static FT_Error
923 TT_Process_Simple_Glyph( TT_Loader loader )
924 {
925 FT_GlyphLoader gloader = loader->gloader;
926 FT_Error error = FT_Err_Ok;
927 FT_Outline* outline;
928 FT_Int n_points;
929
930
931 outline = &gloader->current.outline;
932 n_points = outline->n_points;
933
934 /* set phantom points */
935
936 outline->points[n_points ] = loader->pp1;
937 outline->points[n_points + 1] = loader->pp2;
938 outline->points[n_points + 2] = loader->pp3;
939 outline->points[n_points + 3] = loader->pp4;
940
941 outline->tags[n_points ] = 0;
942 outline->tags[n_points + 1] = 0;
943 outline->tags[n_points + 2] = 0;
944 outline->tags[n_points + 3] = 0;
945
946 n_points += 4;
947
948#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
949
950 if ( FT_IS_NAMED_INSTANCE( FT_FACE( loader->face ) ) ||
951 FT_IS_VARIATION( FT_FACE( loader->face ) ) )
952 {
953 /* Deltas apply to the unscaled data. */
954 error = TT_Vary_Apply_Glyph_Deltas( loader->face,
955 loader->glyph_index,
956 outline,
957 (FT_UInt)n_points );
958
959 /* recalculate linear horizontal and vertical advances */
960 /* if we don't have HVAR and VVAR, respectively */
961 if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
962 loader->linear = outline->points[n_points - 3].x -
963 outline->points[n_points - 4].x;
964 if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
965 loader->vadvance = outline->points[n_points - 1].x -
966 outline->points[n_points - 2].x;
967
968 if ( error )
969 return error;
970 }
971
972#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
973
974 if ( IS_HINTED( loader->load_flags ) )
975 {
976 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
977
978 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
979 loader->zone.n_points + 4 );
980 }
981
982 {
983#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
984 TT_Face face = loader->face;
985 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
986
987 FT_String* family = face->root.family_name;
988 FT_UInt ppem = loader->size->metrics->x_ppem;
989 FT_String* style = face->root.style_name;
990 FT_UInt x_scale_factor = 1000;
991#endif
992
993 FT_Vector* vec = outline->points;
994 FT_Vector* limit = outline->points + n_points;
995
996 FT_Fixed x_scale = 0; /* pacify compiler */
997 FT_Fixed y_scale = 0;
998
999 FT_Bool do_scale = FALSE;
1000
1001
1002#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1003
1004 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
1005 {
1006 /* scale, but only if enabled and only if TT hinting is being used */
1007 if ( IS_HINTED( loader->load_flags ) )
1008 x_scale_factor = sph_test_tweak_x_scaling( face,
1009 family,
1010 ppem,
1011 style,
1012 loader->glyph_index );
1013 /* scale the glyph */
1014 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
1015 x_scale_factor != 1000 )
1016 {
1017 x_scale = FT_MulDiv( loader->size->metrics->x_scale,
1018 (FT_Long)x_scale_factor, 1000 );
1019 y_scale = loader->size->metrics->y_scale;
1020
1021 /* compensate for any scaling by de/emboldening; */
1022 /* the amount was determined via experimentation */
1023 if ( x_scale_factor != 1000 && ppem > 11 )
1024 FT_Outline_EmboldenXY( outline,
1025 FT_MulFix( 1280 * ppem,
1026 1000 - x_scale_factor ),
1027 0 );
1028 do_scale = TRUE;
1029 }
1030 }
1031 else
1032
1033#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
1034
1035 {
1036 /* scale the glyph */
1037 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1038 {
1039 x_scale = loader->size->metrics->x_scale;
1040 y_scale = loader->size->metrics->y_scale;
1041
1042 do_scale = TRUE;
1043 }
1044 }
1045
1046 if ( do_scale )
1047 {
1048 for ( ; vec < limit; vec++ )
1049 {
1050 vec->x = FT_MulFix( vec->x, x_scale );
1051 vec->y = FT_MulFix( vec->y, y_scale );
1052 }
1053 }
1054
1055#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1056 /* if we have a HVAR table, `pp1' and/or `pp2' are already adjusted */
1057 if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ||
1058 !IS_HINTED( loader->load_flags ) )
1059#endif
1060 {
1061 loader->pp1 = outline->points[n_points - 4];
1062 loader->pp2 = outline->points[n_points - 3];
1063 }
1064
1065#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1066 /* if we have a VVAR table, `pp3' and/or `pp4' are already adjusted */
1067 if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ||
1068 !IS_HINTED( loader->load_flags ) )
1069#endif
1070 {
1071 loader->pp3 = outline->points[n_points - 2];
1072 loader->pp4 = outline->points[n_points - 1];
1073 }
1074 }
1075
1076 if ( IS_HINTED( loader->load_flags ) )
1077 {
1078 loader->zone.n_points += 4;
1079
1080 error = TT_Hint_Glyph( loader, 0 );
1081 }
1082
1083 return error;
1084 }
1085
1086
1087 /**************************************************************************
1088 *
1089 * @Function:
1090 * TT_Process_Composite_Component
1091 *
1092 * @Description:
1093 * Once a composite component has been loaded, it needs to be
1094 * processed. Usually, this means transforming and translating.
1095 */
1096 static FT_Error
1097 TT_Process_Composite_Component( TT_Loader loader,
1098 FT_SubGlyph subglyph,
1099 FT_UInt start_point,
1100 FT_UInt num_base_points )
1101 {
1102 FT_GlyphLoader gloader = loader->gloader;
1103 FT_Outline current;
1104 FT_Bool have_scale;
1105 FT_Pos x, y;
1106
1107
1108 current.points = gloader->base.outline.points +
1109 num_base_points;
1110 current.n_points = gloader->base.outline.n_points -
1111 (short)num_base_points;
1112
1113 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
1114 WE_HAVE_AN_XY_SCALE |
1115 WE_HAVE_A_2X2 ) );
1116
1117 /* perform the transform required for this subglyph */
1118 if ( have_scale )
1119 FT_Outline_Transform( &current, &subglyph->transform );
1120
1121 /* get offset */
1122 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
1123 {
1124 FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points;
1125 FT_UInt k = (FT_UInt)subglyph->arg1;
1126 FT_UInt l = (FT_UInt)subglyph->arg2;
1127 FT_Vector* p1;
1128 FT_Vector* p2;
1129
1130
1131 /* match l-th point of the newly loaded component to the k-th point */
1132 /* of the previously loaded components. */
1133
1134 /* change to the point numbers used by our outline */
1135 k += start_point;
1136 l += num_base_points;
1137 if ( k >= num_base_points ||
1138 l >= num_points )
1139 return FT_THROW( Invalid_Composite );
1140
1141 p1 = gloader->base.outline.points + k;
1142 p2 = gloader->base.outline.points + l;
1143
1144 x = p1->x - p2->x;
1145 y = p1->y - p2->y;
1146 }
1147 else
1148 {
1149 x = subglyph->arg1;
1150 y = subglyph->arg2;
1151
1152 if ( !x && !y )
1153 return FT_Err_Ok;
1154
1155 /* Use a default value dependent on */
1156 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old */
1157 /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit. */
1158
1159 if ( have_scale &&
1160#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
1161 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
1162#else
1163 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
1164#endif
1165 {
1166
1167#if 0
1168
1169 /********************************************************************
1170 *
1171 * This algorithm is what Apple documents. But it doesn't work.
1172 */
1173 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
1174 : -subglyph->transform.xx;
1175 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
1176 : -subglyph->transform.yx;
1177 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
1178 : -subglyph->transform.xy;
1179 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
1180 : -subglyph->transform.yy;
1181 int m = a > b ? a : b;
1182 int n = c > d ? c : d;
1183
1184
1185 if ( a - b <= 33 && a - b >= -33 )
1186 m *= 2;
1187 if ( c - d <= 33 && c - d >= -33 )
1188 n *= 2;
1189 x = FT_MulFix( x, m );
1190 y = FT_MulFix( y, n );
1191
1192#else /* 1 */
1193
1194 /********************************************************************
1195 *
1196 * This algorithm is a guess and works much better than the above.
1197 */
1198 FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx,
1199 subglyph->transform.xy );
1200 FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy,
1201 subglyph->transform.yx );
1202
1203
1204 x = FT_MulFix( x, mac_xscale );
1205 y = FT_MulFix( y, mac_yscale );
1206
1207#endif /* 1 */
1208
1209 }
1210
1211 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1212 {
1213 FT_Fixed x_scale = loader->size->metrics->x_scale;
1214 FT_Fixed y_scale = loader->size->metrics->y_scale;
1215
1216
1217 x = FT_MulFix( x, x_scale );
1218 y = FT_MulFix( y, y_scale );
1219
1220 if ( subglyph->flags & ROUND_XY_TO_GRID )
1221 {
1222 TT_Face face = loader->face;
1223 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
1224
1225
1226 if ( IS_HINTED( loader->load_flags ) )
1227 {
1228 /*
1229 * We round the horizontal offset only if there is hinting along
1230 * the x axis; this corresponds to integer advance width values.
1231 *
1232 * Theoretically, a glyph's bytecode can toggle ClearType's
1233 * `backward compatibility' mode, which would allow modification
1234 * of the advance width. In reality, however, applications
1235 * neither allow nor expect modified advance widths if subpixel
1236 * rendering is active.
1237 *
1238 */
1239 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_35 )
1240 x = FT_PIX_ROUND( x );
1241
1242 y = FT_PIX_ROUND( y );
1243 }
1244 }
1245 }
1246 }
1247
1248 if ( x || y )
1249 FT_Outline_Translate( &current, x, y );
1250
1251 return FT_Err_Ok;
1252 }
1253
1254
1255 /**************************************************************************
1256 *
1257 * @Function:
1258 * TT_Process_Composite_Glyph
1259 *
1260 * @Description:
1261 * This is slightly different from TT_Process_Simple_Glyph, in that
1262 * its sole purpose is to hint the glyph. Thus this function is
1263 * only available when bytecode interpreter is enabled.
1264 */
1265 static FT_Error
1266 TT_Process_Composite_Glyph( TT_Loader loader,
1267 FT_UInt start_point,
1268 FT_UInt start_contour )
1269 {
1270 FT_Error error;
1271 FT_Outline* outline;
1272 FT_UInt i;
1273
1274
1275 outline = &loader->gloader->base.outline;
1276
1277 /* make room for phantom points */
1278 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
1279 outline->n_points + 4,
1280 0 );
1281 if ( error )
1282 return error;
1283
1284 outline->points[outline->n_points ] = loader->pp1;
1285 outline->points[outline->n_points + 1] = loader->pp2;
1286 outline->points[outline->n_points + 2] = loader->pp3;
1287 outline->points[outline->n_points + 3] = loader->pp4;
1288
1289 outline->tags[outline->n_points ] = 0;
1290 outline->tags[outline->n_points + 1] = 0;
1291 outline->tags[outline->n_points + 2] = 0;
1292 outline->tags[outline->n_points + 3] = 0;
1293
1294#ifdef TT_USE_BYTECODE_INTERPRETER
1295
1296 {
1297 FT_Stream stream = loader->stream;
1298 FT_UShort n_ins, max_ins;
1299 FT_ULong tmp;
1300
1301
1302 /* TT_Load_Composite_Glyph only gives us the offset of instructions */
1303 /* so we read them here */
1304 if ( FT_STREAM_SEEK( loader->ins_pos ) ||
1305 FT_READ_USHORT( n_ins ) )
1306 return error;
1307
1308 FT_TRACE5(( " Instructions size = %d\n", n_ins ));
1309
1310 /* check it */
1311 max_ins = loader->face->max_profile.maxSizeOfInstructions;
1312 if ( n_ins > max_ins )
1313 {
1314 /* don't trust `maxSizeOfInstructions'; */
1315 /* only do a rough safety check */
1316 if ( (FT_Int)n_ins > loader->byte_len )
1317 {
1318 FT_TRACE1(( "TT_Process_Composite_Glyph:"
1319 " too many instructions (%d) for glyph with length %d\n",
1320 n_ins, loader->byte_len ));
1321 return FT_THROW( Too_Many_Hints );
1322 }
1323
1324 tmp = loader->exec->glyphSize;
1325 error = Update_Max( loader->exec->memory,
1326 &tmp,
1327 sizeof ( FT_Byte ),
1328 (void*)&loader->exec->glyphIns,
1329 n_ins );
1330
1331 loader->exec->glyphSize = (FT_UShort)tmp;
1332 if ( error )
1333 return error;
1334 }
1335 else if ( n_ins == 0 )
1336 return FT_Err_Ok;
1337
1338 if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
1339 return error;
1340
1341 loader->glyph->control_data = loader->exec->glyphIns;
1342 loader->glyph->control_len = n_ins;
1343 }
1344
1345#endif
1346
1347 tt_prepare_zone( &loader->zone, &loader->gloader->base,
1348 start_point, start_contour );
1349
1350 /* Some points are likely touched during execution of */
1351 /* instructions on components. So let's untouch them. */
1352 for ( i = 0; i < loader->zone.n_points; i++ )
1353 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
1354
1355 loader->zone.n_points += 4;
1356
1357 return TT_Hint_Glyph( loader, 1 );
1358 }
1359
1360
1361 /*
1362 * Calculate the phantom points
1363 *
1364 * Defining the right side bearing (rsb) as
1365 *
1366 * rsb = aw - (lsb + xmax - xmin)
1367 *
1368 * (with `aw' the advance width, `lsb' the left side bearing, and `xmin'
1369 * and `xmax' the glyph's minimum and maximum x value), the OpenType
1370 * specification defines the initial position of horizontal phantom points
1371 * as
1372 *
1373 * pp1 = (round(xmin - lsb), 0) ,
1374 * pp2 = (round(pp1 + aw), 0) .
1375 *
1376 * Note that the rounding to the grid (in the device space) is not
1377 * documented currently in the specification.
1378 *
1379 * However, the specification lacks the precise definition of vertical
1380 * phantom points. Greg Hitchcock provided the following explanation.
1381 *
1382 * - a `vmtx' table is present
1383 *
1384 * For any glyph, the minimum and maximum y values (`ymin' and `ymax')
1385 * are given in the `glyf' table, the top side bearing (tsb) and advance
1386 * height (ah) are given in the `vmtx' table. The bottom side bearing
1387 * (bsb) is then calculated as
1388 *
1389 * bsb = ah - (tsb + ymax - ymin) ,
1390 *
1391 * and the initial position of vertical phantom points is
1392 *
1393 * pp3 = (x, round(ymax + tsb)) ,
1394 * pp4 = (x, round(pp3 - ah)) .
1395 *
1396 * See below for value `x'.
1397 *
1398 * - no `vmtx' table in the font
1399 *
1400 * If there is an `OS/2' table, we set
1401 *
1402 * DefaultAscender = sTypoAscender ,
1403 * DefaultDescender = sTypoDescender ,
1404 *
1405 * otherwise we use data from the `hhea' table:
1406 *
1407 * DefaultAscender = Ascender ,
1408 * DefaultDescender = Descender .
1409 *
1410 * With these two variables we can now set
1411 *
1412 * ah = DefaultAscender - sDefaultDescender ,
1413 * tsb = DefaultAscender - yMax ,
1414 *
1415 * and proceed as if a `vmtx' table was present.
1416 *
1417 * Usually we have
1418 *
1419 * x = aw / 2 , (1)
1420 *
1421 * but there is one compatibility case where it can be set to
1422 *
1423 * x = -DefaultDescender -
1424 * ((DefaultAscender - DefaultDescender - aw) / 2) . (2)
1425 *
1426 * and another one with
1427 *
1428 * x = 0 . (3)
1429 *
1430 * In Windows, the history of those values is quite complicated,
1431 * depending on the hinting engine (that is, the graphics framework).
1432 *
1433 * framework from to formula
1434 * ----------------------------------------------------------
1435 * GDI Windows 98 current (1)
1436 * (Windows 2000 for NT)
1437 * GDI+ Windows XP Windows 7 (2)
1438 * GDI+ Windows 8 current (3)
1439 * DWrite Windows 7 current (3)
1440 *
1441 * For simplicity, FreeType uses (1) for grayscale subpixel hinting and
1442 * (3) for everything else.
1443 *
1444 */
1445 static void
1446 tt_loader_set_pp( TT_Loader loader )
1447 {
1448 FT_Bool subpixel_hinting = 0;
1449 FT_Bool grayscale = 0;
1450 FT_Bool use_aw_2 = 0;
1451
1452#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
1453 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
1454#endif
1455
1456
1457#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1458 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
1459 {
1460 subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting
1461 : 0;
1462 grayscale = loader->exec ? loader->exec->grayscale
1463 : 0;
1464 }
1465#endif
1466#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1467 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
1468 {
1469 subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting_lean
1470 : 0;
1471 grayscale = loader->exec ? loader->exec->grayscale_cleartype
1472 : 0;
1473 }
1474#endif
1475
1476 use_aw_2 = FT_BOOL( subpixel_hinting && grayscale );
1477
1478 loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
1479 loader->pp1.y = 0;
1480 loader->pp2.x = loader->pp1.x + loader->advance;
1481 loader->pp2.y = 0;
1482
1483 loader->pp3.x = use_aw_2 ? loader->advance / 2 : 0;
1484 loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
1485 loader->pp4.x = use_aw_2 ? loader->advance / 2 : 0;
1486 loader->pp4.y = loader->pp3.y - loader->vadvance;
1487 }
1488
1489
1490 /* a utility function to retrieve i-th node from given FT_List */
1491 static FT_ListNode
1492 ft_list_get_node_at( FT_List list,
1493 FT_UInt idx )
1494 {
1495 FT_ListNode cur;
1496
1497
1498 if ( !list )
1499 return NULL;
1500
1501 for ( cur = list->head; cur; cur = cur->next )
1502 {
1503 if ( !idx )
1504 return cur;
1505
1506 idx--;
1507 }
1508
1509 return NULL;
1510 }
1511
1512
1513 /**************************************************************************
1514 *
1515 * @Function:
1516 * load_truetype_glyph
1517 *
1518 * @Description:
1519 * Loads a given truetype glyph. Handles composites and uses a
1520 * TT_Loader object.
1521 */
1522 static FT_Error
1523 load_truetype_glyph( TT_Loader loader,
1524 FT_UInt glyph_index,
1525 FT_UInt recurse_count,
1526 FT_Bool header_only )
1527 {
1528 FT_Error error = FT_Err_Ok;
1529 FT_Fixed x_scale, y_scale;
1530 FT_ULong offset;
1531 TT_Face face = loader->face;
1532 FT_GlyphLoader gloader = loader->gloader;
1533
1534 FT_Bool opened_frame = 0;
1535
1536#ifdef FT_CONFIG_OPTION_INCREMENTAL
1537 FT_StreamRec inc_stream;
1538 FT_Data glyph_data;
1539 FT_Bool glyph_data_loaded = 0;
1540#endif
1541
1542
1543#ifdef FT_DEBUG_LEVEL_TRACE
1544 if ( recurse_count )
1545 FT_TRACE5(( " nesting level: %d\n", recurse_count ));
1546#endif
1547
1548 /* some fonts have an incorrect value of `maxComponentDepth' */
1549 if ( recurse_count > face->max_profile.maxComponentDepth )
1550 {
1551 FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %d\n",
1552 recurse_count ));
1553 face->max_profile.maxComponentDepth = (FT_UShort)recurse_count;
1554 }
1555
1556#ifndef FT_CONFIG_OPTION_INCREMENTAL
1557 /* check glyph index */
1558 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
1559 {
1560 error = FT_THROW( Invalid_Glyph_Index );
1561 goto Exit;
1562 }
1563#endif
1564
1565 loader->glyph_index = glyph_index;
1566
1567 if ( loader->load_flags & FT_LOAD_NO_SCALE )
1568 {
1569 x_scale = 0x10000L;
1570 y_scale = 0x10000L;
1571 }
1572 else
1573 {
1574 x_scale = loader->size->metrics->x_scale;
1575 y_scale = loader->size->metrics->y_scale;
1576 }
1577
1578 /* Set `offset' to the start of the glyph relative to the start of */
1579 /* the `glyf' table, and `byte_len' to the length of the glyph in */
1580 /* bytes. */
1581
1582#ifdef FT_CONFIG_OPTION_INCREMENTAL
1583
1584 /* If we are loading glyph data via the incremental interface, set */
1585 /* the loader stream to a memory stream reading the data returned */
1586 /* by the interface. */
1587 if ( face->root.internal->incremental_interface )
1588 {
1589 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1590 face->root.internal->incremental_interface->object,
1591 glyph_index, &glyph_data );
1592 if ( error )
1593 goto Exit;
1594
1595 glyph_data_loaded = 1;
1596 offset = 0;
1597 loader->byte_len = glyph_data.length;
1598
1599 FT_ZERO( &inc_stream );
1600 FT_Stream_OpenMemory( &inc_stream,
1601 glyph_data.pointer,
1602 (FT_ULong)glyph_data.length );
1603
1604 loader->stream = &inc_stream;
1605 }
1606 else
1607
1608#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1609
1610 offset = tt_face_get_location( face, glyph_index,
1611 (FT_UInt*)&loader->byte_len );
1612
1613 if ( loader->byte_len > 0 )
1614 {
1615#ifdef FT_CONFIG_OPTION_INCREMENTAL
1616 /* for the incremental interface, `glyf_offset' is always zero */
1617 if ( !face->glyf_offset &&
1618 !face->root.internal->incremental_interface )
1619#else
1620 if ( !face->glyf_offset )
1621#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1622 {
1623 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
1624 error = FT_THROW( Invalid_Table );
1625 goto Exit;
1626 }
1627
1628 error = face->access_glyph_frame( loader, glyph_index,
1629 face->glyf_offset + offset,
1630 (FT_UInt)loader->byte_len );
1631 if ( error )
1632 goto Exit;
1633
1634 /* read glyph header first */
1635 error = face->read_glyph_header( loader );
1636
1637 face->forget_glyph_frame( loader );
1638
1639 if ( error )
1640 goto Exit;
1641 }
1642
1643 /* a space glyph */
1644 if ( loader->byte_len == 0 || loader->n_contours == 0 )
1645 {
1646 loader->bbox.xMin = 0;
1647 loader->bbox.xMax = 0;
1648 loader->bbox.yMin = 0;
1649 loader->bbox.yMax = 0;
1650 }
1651
1652 /* the metrics must be computed after loading the glyph header */
1653 /* since we need the glyph's `yMax' value in case the vertical */
1654 /* metrics must be emulated */
1655 error = tt_get_metrics( loader, glyph_index );
1656 if ( error )
1657 goto Exit;
1658
1659 if ( header_only )
1660 goto Exit;
1661
1662 if ( loader->byte_len == 0 || loader->n_contours == 0 )
1663 {
1664 /* must initialize points before (possibly) overriding */
1665 /* glyph metrics from the incremental interface */
1666 tt_loader_set_pp( loader );
1667
1668#ifdef FT_CONFIG_OPTION_INCREMENTAL
1669 tt_get_metrics_incr_overrides( loader, glyph_index );
1670#endif
1671
1672#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1673
1674 if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1675 FT_IS_VARIATION( FT_FACE( face ) ) )
1676 {
1677 /* a small outline structure with four elements for */
1678 /* communication with `TT_Vary_Apply_Glyph_Deltas' */
1679 FT_Vector points[4];
1680 char tags[4] = { 1, 1, 1, 1 };
1681 short contours[4] = { 0, 1, 2, 3 };
1682 FT_Outline outline;
1683
1684
1685 points[0].x = loader->pp1.x;
1686 points[0].y = loader->pp1.y;
1687 points[1].x = loader->pp2.x;
1688 points[1].y = loader->pp2.y;
1689
1690 points[2].x = loader->pp3.x;
1691 points[2].y = loader->pp3.y;
1692 points[3].x = loader->pp4.x;
1693 points[3].y = loader->pp4.y;
1694
1695 outline.n_points = 4;
1696 outline.n_contours = 4;
1697 outline.points = points;
1698 outline.tags = tags;
1699 outline.contours = contours;
1700
1701 /* this must be done before scaling */
1702 error = TT_Vary_Apply_Glyph_Deltas( loader->face,
1703 glyph_index,
1704 &outline,
1705 (FT_UInt)outline.n_points );
1706 if ( error )
1707 goto Exit;
1708
1709 loader->pp1.x = points[0].x;
1710 loader->pp1.y = points[0].y;
1711 loader->pp2.x = points[1].x;
1712 loader->pp2.y = points[1].y;
1713
1714 loader->pp3.x = points[2].x;
1715 loader->pp3.y = points[2].y;
1716 loader->pp4.x = points[3].x;
1717 loader->pp4.y = points[3].y;
1718
1719 /* recalculate linear horizontal and vertical advances */
1720 /* if we don't have HVAR and VVAR, respectively */
1721 if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
1722 loader->linear = loader->pp2.x - loader->pp1.x;
1723 if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
1724 loader->vadvance = loader->pp4.x - loader->pp3.x;
1725 }
1726
1727#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1728
1729 /* scale phantom points, if necessary; */
1730 /* they get rounded in `TT_Hint_Glyph' */
1731 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1732 {
1733 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1734 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1735 /* pp1.y and pp2.y are always zero */
1736
1737 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1738 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1739 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1740 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1741 }
1742
1743 error = FT_Err_Ok;
1744 goto Exit;
1745 }
1746
1747 /* must initialize phantom points before (possibly) overriding */
1748 /* glyph metrics from the incremental interface */
1749 tt_loader_set_pp( loader );
1750
1751#ifdef FT_CONFIG_OPTION_INCREMENTAL
1752 tt_get_metrics_incr_overrides( loader, glyph_index );
1753#endif
1754
1755 /***********************************************************************/
1756 /***********************************************************************/
1757 /***********************************************************************/
1758
1759 /* we now open a frame again, right after the glyph header */
1760 /* (which consists of 10 bytes) */
1761 error = face->access_glyph_frame( loader, glyph_index,
1762 face->glyf_offset + offset + 10,
1763 (FT_UInt)loader->byte_len - 10 );
1764 if ( error )
1765 goto Exit;
1766
1767 opened_frame = 1;
1768
1769 /* if it is a simple glyph, load it */
1770
1771 if ( loader->n_contours > 0 )
1772 {
1773 error = face->read_simple_glyph( loader );
1774 if ( error )
1775 goto Exit;
1776
1777 /* all data have been read */
1778 face->forget_glyph_frame( loader );
1779 opened_frame = 0;
1780
1781 error = TT_Process_Simple_Glyph( loader );
1782 if ( error )
1783 goto Exit;
1784
1785 FT_GlyphLoader_Add( gloader );
1786 }
1787
1788 /***********************************************************************/
1789 /***********************************************************************/
1790 /***********************************************************************/
1791
1792 /* otherwise, load a composite! */
1793 else if ( loader->n_contours < 0 )
1794 {
1795 FT_Memory memory = face->root.memory;
1796
1797 FT_UInt start_point;
1798 FT_UInt start_contour;
1799 FT_ULong ins_pos; /* position of composite instructions, if any */
1800
1801 FT_ListNode node, node2;
1802
1803
1804 /* normalize the `n_contours' value */
1805 loader->n_contours = -1;
1806
1807 /*
1808 * We store the glyph index directly in the `node->data' pointer,
1809 * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
1810 * double cast to make this portable. Note, however, that this needs
1811 * pointers with a width of at least 32 bits.
1812 */
1813
1814 /* clear the nodes filled by sibling chains */
1815 node = ft_list_get_node_at( &loader->composites, recurse_count );
1816 for ( node2 = node; node2; node2 = node2->next )
1817 node2->data = (void*)FT_ULONG_MAX;
1818
1819 /* check whether we already have a composite glyph with this index */
1820 if ( FT_List_Find( &loader->composites,
1821 FT_UINT_TO_POINTER( glyph_index ) ) )
1822 {
1823 FT_TRACE1(( "TT_Load_Composite_Glyph:"
1824 " infinite recursion detected\n" ));
1825 error = FT_THROW( Invalid_Composite );
1826 goto Exit;
1827 }
1828
1829 else if ( node )
1830 node->data = FT_UINT_TO_POINTER( glyph_index );
1831
1832 else
1833 {
1834 if ( FT_NEW( node ) )
1835 goto Exit;
1836 node->data = FT_UINT_TO_POINTER( glyph_index );
1837 FT_List_Add( &loader->composites, node );
1838 }
1839
1840 start_point = (FT_UInt)gloader->base.outline.n_points;
1841 start_contour = (FT_UInt)gloader->base.outline.n_contours;
1842
1843 /* for each subglyph, read composite header */
1844 error = face->read_composite_glyph( loader );
1845 if ( error )
1846 goto Exit;
1847
1848 /* store the offset of instructions */
1849 ins_pos = loader->ins_pos;
1850
1851 /* all data we need are read */
1852 face->forget_glyph_frame( loader );
1853 opened_frame = 0;
1854
1855#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1856
1857 if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1858 FT_IS_VARIATION( FT_FACE( face ) ) )
1859 {
1860 short i, limit;
1861 FT_SubGlyph subglyph;
1862
1863 FT_Outline outline;
1864 FT_Vector* points = NULL;
1865 char* tags = NULL;
1866 short* contours = NULL;
1867
1868
1869 limit = (short)gloader->current.num_subglyphs;
1870
1871 /* construct an outline structure for */
1872 /* communication with `TT_Vary_Apply_Glyph_Deltas' */
1873 outline.n_points = (short)( gloader->current.num_subglyphs + 4 );
1874 outline.n_contours = outline.n_points;
1875
1876 outline.points = NULL;
1877 outline.tags = NULL;
1878 outline.contours = NULL;
1879
1880 if ( FT_NEW_ARRAY( points, outline.n_points ) ||
1881 FT_NEW_ARRAY( tags, outline.n_points ) ||
1882 FT_NEW_ARRAY( contours, outline.n_points ) )
1883 goto Exit1;
1884
1885 subglyph = gloader->current.subglyphs;
1886
1887 for ( i = 0; i < limit; i++, subglyph++ )
1888 {
1889 /* applying deltas for anchor points doesn't make sense, */
1890 /* but we don't have to specially check this since */
1891 /* unused delta values are zero anyways */
1892 points[i].x = subglyph->arg1;
1893 points[i].y = subglyph->arg2;
1894 tags[i] = 1;
1895 contours[i] = i;
1896 }
1897
1898 points[i].x = loader->pp1.x;
1899 points[i].y = loader->pp1.y;
1900 tags[i] = 1;
1901 contours[i] = i;
1902
1903 i++;
1904 points[i].x = loader->pp2.x;
1905 points[i].y = loader->pp2.y;
1906 tags[i] = 1;
1907 contours[i] = i;
1908
1909 i++;
1910 points[i].x = loader->pp3.x;
1911 points[i].y = loader->pp3.y;
1912 tags[i] = 1;
1913 contours[i] = i;
1914
1915 i++;
1916 points[i].x = loader->pp4.x;
1917 points[i].y = loader->pp4.y;
1918 tags[i] = 1;
1919 contours[i] = i;
1920
1921 outline.points = points;
1922 outline.tags = tags;
1923 outline.contours = contours;
1924
1925 /* this call provides additional offsets */
1926 /* for each component's translation */
1927 if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas(
1928 face,
1929 glyph_index,
1930 &outline,
1931 (FT_UInt)outline.n_points ) ) )
1932 goto Exit1;
1933
1934 subglyph = gloader->current.subglyphs;
1935
1936 for ( i = 0; i < limit; i++, subglyph++ )
1937 {
1938 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1939 {
1940 subglyph->arg1 = (FT_Int16)points[i].x;
1941 subglyph->arg2 = (FT_Int16)points[i].y;
1942 }
1943 }
1944
1945 loader->pp1.x = points[i + 0].x;
1946 loader->pp1.y = points[i + 0].y;
1947 loader->pp2.x = points[i + 1].x;
1948 loader->pp2.y = points[i + 1].y;
1949
1950 loader->pp3.x = points[i + 2].x;
1951 loader->pp3.y = points[i + 2].y;
1952 loader->pp4.x = points[i + 3].x;
1953 loader->pp4.y = points[i + 3].y;
1954
1955 /* recalculate linear horizontal and vertical advances */
1956 /* if we don't have HVAR and VVAR, respectively */
1957 if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
1958 loader->linear = loader->pp2.x - loader->pp1.x;
1959 if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
1960 loader->vadvance = loader->pp4.x - loader->pp3.x;
1961
1962 Exit1:
1963 FT_FREE( outline.points );
1964 FT_FREE( outline.tags );
1965 FT_FREE( outline.contours );
1966
1967 if ( error )
1968 goto Exit;
1969 }
1970
1971#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1972
1973 /* scale phantom points, if necessary; */
1974 /* they get rounded in `TT_Hint_Glyph' */
1975 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1976 {
1977 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1978 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1979 /* pp1.y and pp2.y are always zero */
1980
1981 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1982 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1983 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1984 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1985 }
1986
1987 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
1988 /* `as is' in the glyph slot (the client application will be */
1989 /* responsible for interpreting these data)... */
1990 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1991 {
1992 FT_GlyphLoader_Add( gloader );
1993 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
1994
1995 goto Exit;
1996 }
1997
1998 /*********************************************************************/
1999 /*********************************************************************/
2000 /*********************************************************************/
2001
2002 {
2003 FT_UInt n, num_base_points;
2004 FT_SubGlyph subglyph = NULL;
2005
2006 FT_UInt num_points = start_point;
2007 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
2008 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
2009
2010 FT_Stream old_stream = loader->stream;
2011 FT_Int old_byte_len = loader->byte_len;
2012
2013
2014 FT_GlyphLoader_Add( gloader );
2015
2016 /* read each subglyph independently */
2017 for ( n = 0; n < num_subglyphs; n++ )
2018 {
2019 FT_Vector pp[4];
2020
2021 FT_Int linear_hadvance;
2022 FT_Int linear_vadvance;
2023
2024
2025 /* Each time we call `load_truetype_glyph' in this loop, the */
2026 /* value of `gloader.base.subglyphs' can change due to table */
2027 /* reallocations. We thus need to recompute the subglyph */
2028 /* pointer on each iteration. */
2029 subglyph = gloader->base.subglyphs + num_base_subgs + n;
2030
2031 pp[0] = loader->pp1;
2032 pp[1] = loader->pp2;
2033 pp[2] = loader->pp3;
2034 pp[3] = loader->pp4;
2035
2036 linear_hadvance = loader->linear;
2037 linear_vadvance = loader->vadvance;
2038
2039 num_base_points = (FT_UInt)gloader->base.outline.n_points;
2040
2041 error = load_truetype_glyph( loader,
2042 (FT_UInt)subglyph->index,
2043 recurse_count + 1,
2044 FALSE );
2045 if ( error )
2046 goto Exit;
2047
2048 /* restore subglyph pointer */
2049 subglyph = gloader->base.subglyphs + num_base_subgs + n;
2050
2051 /* restore phantom points if necessary */
2052 if ( !( subglyph->flags & USE_MY_METRICS ) )
2053 {
2054 loader->pp1 = pp[0];
2055 loader->pp2 = pp[1];
2056 loader->pp3 = pp[2];
2057 loader->pp4 = pp[3];
2058
2059 loader->linear = linear_hadvance;
2060 loader->vadvance = linear_vadvance;
2061 }
2062
2063 num_points = (FT_UInt)gloader->base.outline.n_points;
2064
2065 if ( num_points == num_base_points )
2066 continue;
2067
2068 /* gloader->base.outline consists of three parts: */
2069 /* */
2070 /* 0 ----> start_point ----> num_base_points ----> n_points */
2071 /* (1) (2) (3) */
2072 /* */
2073 /* (1) points that exist from the beginning */
2074 /* (2) component points that have been loaded so far */
2075 /* (3) points of the newly loaded component */
2076 error = TT_Process_Composite_Component( loader,
2077 subglyph,
2078 start_point,
2079 num_base_points );
2080 if ( error )
2081 goto Exit;
2082 }
2083
2084 loader->stream = old_stream;
2085 loader->byte_len = old_byte_len;
2086
2087 /* process the glyph */
2088 loader->ins_pos = ins_pos;
2089 if ( IS_HINTED( loader->load_flags ) &&
2090#ifdef TT_USE_BYTECODE_INTERPRETER
2091 subglyph->flags & WE_HAVE_INSTR &&
2092#endif
2093 num_points > start_point )
2094 {
2095 error = TT_Process_Composite_Glyph( loader,
2096 start_point,
2097 start_contour );
2098 if ( error )
2099 goto Exit;
2100 }
2101 }
2102 }
2103
2104 /***********************************************************************/
2105 /***********************************************************************/
2106 /***********************************************************************/
2107
2108 Exit:
2109
2110 if ( opened_frame )
2111 face->forget_glyph_frame( loader );
2112
2113#ifdef FT_CONFIG_OPTION_INCREMENTAL
2114
2115 if ( glyph_data_loaded )
2116 face->root.internal->incremental_interface->funcs->free_glyph_data(
2117 face->root.internal->incremental_interface->object,
2118 &glyph_data );
2119
2120#endif
2121
2122 return error;
2123 }
2124
2125
2126 static FT_Error
2127 compute_glyph_metrics( TT_Loader loader,
2128 FT_UInt glyph_index )
2129 {
2130 TT_Face face = loader->face;
2131#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
2132 defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2133 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
2134#endif
2135
2136 FT_BBox bbox;
2137 FT_Fixed y_scale;
2138 TT_GlyphSlot glyph = loader->glyph;
2139 TT_Size size = loader->size;
2140
2141
2142 y_scale = 0x10000L;
2143 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
2144 y_scale = size->metrics->y_scale;
2145
2146 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
2147 FT_Outline_Get_CBox( &glyph->outline, &bbox );
2148 else
2149 bbox = loader->bbox;
2150
2151 /* get the device-independent horizontal advance; it is scaled later */
2152 /* by the base layer. */
2153 glyph->linearHoriAdvance = loader->linear;
2154
2155 glyph->metrics.horiBearingX = bbox.xMin;
2156 glyph->metrics.horiBearingY = bbox.yMax;
2157 glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x);
2158
2159 /* Adjust advance width to the value contained in the hdmx table */
2160 /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */
2161 /* mode of the v40 interpreter is active. See `ttinterp.h' for */
2162 /* details on backward compatibility mode. */
2163 if (
2164#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2165 !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
2166 ( loader->exec && loader->exec->backward_compatibility ) ) &&
2167#endif
2168 !face->postscript.isFixedPitch &&
2169 IS_HINTED( loader->load_flags ) &&
2170 !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
2171 {
2172 FT_Byte* widthp;
2173
2174
2175 widthp = tt_face_get_device_metrics( face,
2176 size->metrics->x_ppem,
2177 glyph_index );
2178
2179#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2180
2181 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
2182 {
2183 FT_Bool ignore_x_mode;
2184
2185
2186 ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) !=
2187 FT_RENDER_MODE_MONO );
2188
2189 if ( widthp &&
2190 ( ( ignore_x_mode && loader->exec->compatible_widths ) ||
2191 !ignore_x_mode ||
2192 SPH_OPTION_BITMAP_WIDTHS ) )
2193 glyph->metrics.horiAdvance = *widthp * 64;
2194 }
2195 else
2196
2197#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2198
2199 {
2200 if ( widthp )
2201 glyph->metrics.horiAdvance = *widthp * 64;
2202 }
2203 }
2204
2205 /* set glyph dimensions */
2206 glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin );
2207 glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin );
2208
2209 /* Now take care of vertical metrics. In the case where there is */
2210 /* no vertical information within the font (relatively common), */
2211 /* create some metrics manually */
2212 {
2213 FT_Pos top; /* scaled vertical top side bearing */
2214 FT_Pos advance; /* scaled vertical advance height */
2215
2216
2217 /* Get the unscaled top bearing and advance height. */
2218 if ( face->vertical_info &&
2219 face->vertical.number_Of_VMetrics > 0 )
2220 {
2221 top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
2222 y_scale );
2223
2224 if ( loader->pp3.y <= loader->pp4.y )
2225 advance = 0;
2226 else
2227 advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
2228 y_scale );
2229 }
2230 else
2231 {
2232 FT_Pos height;
2233
2234
2235 /* XXX Compute top side bearing and advance height in */
2236 /* Get_VMetrics instead of here. */
2237
2238 /* NOTE: The OS/2 values are the only `portable' ones, */
2239 /* which is why we use them, if there is an OS/2 */
2240 /* table in the font. Otherwise, we use the */
2241 /* values defined in the horizontal header. */
2242
2243 height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax,
2244 bbox.yMin ),
2245 y_scale );
2246 if ( face->os2.version != 0xFFFFU )
2247 advance = (FT_Pos)( face->os2.sTypoAscender -
2248 face->os2.sTypoDescender );
2249 else
2250 advance = (FT_Pos)( face->horizontal.Ascender -
2251 face->horizontal.Descender );
2252
2253 top = ( advance - height ) / 2;
2254 }
2255
2256#ifdef FT_CONFIG_OPTION_INCREMENTAL
2257 {
2258 FT_Incremental_InterfaceRec* incr;
2259 FT_Incremental_MetricsRec incr_metrics;
2260 FT_Error error;
2261
2262
2263 incr = face->root.internal->incremental_interface;
2264
2265 /* If this is an incrementally loaded font see if there are */
2266 /* overriding metrics for this glyph. */
2267 if ( incr && incr->funcs->get_glyph_metrics )
2268 {
2269 incr_metrics.bearing_x = 0;
2270 incr_metrics.bearing_y = top;
2271 incr_metrics.advance = advance;
2272
2273 error = incr->funcs->get_glyph_metrics( incr->object,
2274 glyph_index,
2275 TRUE,
2276 &incr_metrics );
2277 if ( error )
2278 return error;
2279
2280 top = incr_metrics.bearing_y;
2281 advance = incr_metrics.advance;
2282 }
2283 }
2284
2285 /* GWW: Do vertical metrics get loaded incrementally too? */
2286
2287#endif /* FT_CONFIG_OPTION_INCREMENTAL */
2288
2289 glyph->linearVertAdvance = advance;
2290
2291 /* scale the metrics */
2292 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
2293 {
2294 top = FT_MulFix( top, y_scale );
2295 advance = FT_MulFix( advance, y_scale );
2296 }
2297
2298 /* XXX: for now, we have no better algorithm for the lsb, but it */
2299 /* should work fine. */
2300 /* */
2301 glyph->metrics.vertBearingX = SUB_LONG( glyph->metrics.horiBearingX,
2302 glyph->metrics.horiAdvance / 2 );
2303 glyph->metrics.vertBearingY = top;
2304 glyph->metrics.vertAdvance = advance;
2305 }
2306
2307 return FT_Err_Ok;
2308 }
2309
2310
2311#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2312
2313 static FT_Error
2314 load_sbit_image( TT_Size size,
2315 TT_GlyphSlot glyph,
2316 FT_UInt glyph_index,
2317 FT_Int32 load_flags )
2318 {
2319 TT_Face face;
2320 SFNT_Service sfnt;
2321 FT_Stream stream;
2322 FT_Error error;
2323 TT_SBit_MetricsRec sbit_metrics;
2324
2325
2326 face = (TT_Face)glyph->face;
2327 sfnt = (SFNT_Service)face->sfnt;
2328 stream = face->root.stream;
2329
2330 error = sfnt->load_sbit_image( face,
2331 size->strike_index,
2332 glyph_index,
2333 (FT_UInt)load_flags,
2334 stream,
2335 &glyph->bitmap,
2336 &sbit_metrics );
2337 if ( !error )
2338 {
2339 glyph->outline.n_points = 0;
2340 glyph->outline.n_contours = 0;
2341
2342 glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64;
2343 glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64;
2344
2345 glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64;
2346 glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64;
2347 glyph->metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64;
2348
2349 glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64;
2350 glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64;
2351 glyph->metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64;
2352
2353 glyph->format = FT_GLYPH_FORMAT_BITMAP;
2354
2355 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2356 {
2357 glyph->bitmap_left = sbit_metrics.vertBearingX;
2358 glyph->bitmap_top = sbit_metrics.vertBearingY;
2359 }
2360 else
2361 {
2362 glyph->bitmap_left = sbit_metrics.horiBearingX;
2363 glyph->bitmap_top = sbit_metrics.horiBearingY;
2364 }
2365 }
2366
2367 return error;
2368 }
2369
2370#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2371
2372
2373 static FT_Error
2374 tt_loader_init( TT_Loader loader,
2375 TT_Size size,
2376 TT_GlyphSlot glyph,
2377 FT_Int32 load_flags,
2378 FT_Bool glyf_table_only )
2379 {
2380 TT_Face face;
2381 FT_Stream stream;
2382
2383#ifdef TT_USE_BYTECODE_INTERPRETER
2384 FT_Error error;
2385 FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2386#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
2387 defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2388 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
2389#endif
2390#endif
2391
2392
2393 face = (TT_Face)glyph->face;
2394 stream = face->root.stream;
2395
2396 FT_ZERO( loader );
2397
2398#ifdef TT_USE_BYTECODE_INTERPRETER
2399
2400 /* load execution context */
2401 if ( IS_HINTED( load_flags ) && !glyf_table_only )
2402 {
2403 TT_ExecContext exec;
2404 FT_Bool grayscale = TRUE;
2405#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2406 FT_Bool subpixel_hinting_lean;
2407 FT_Bool grayscale_cleartype;
2408#endif
2409
2410#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2411 FT_Bool subpixel_hinting = FALSE;
2412
2413#if 0
2414 /* not used yet */
2415 FT_Bool compatible_widths;
2416 FT_Bool symmetrical_smoothing;
2417 FT_Bool bgr;
2418 FT_Bool vertical_lcd;
2419 FT_Bool subpixel_positioned;
2420 FT_Bool gray_cleartype;
2421#endif
2422#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2423
2424 FT_Bool reexecute = FALSE;
2425
2426
2427 if ( size->bytecode_ready < 0 || size->cvt_ready < 0 )
2428 {
2429 error = tt_size_ready_bytecode( size, pedantic );
2430 if ( error )
2431 return error;
2432 }
2433 else if ( size->bytecode_ready )
2434 return size->bytecode_ready;
2435 else if ( size->cvt_ready )
2436 return size->cvt_ready;
2437
2438 /* query new execution context */
2439 exec = size->context;
2440 if ( !exec )
2441 return FT_THROW( Could_Not_Find_Context );
2442
2443#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2444 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2445 {
2446 subpixel_hinting_lean =
2447 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2448 FT_RENDER_MODE_MONO );
2449 grayscale_cleartype =
2450 FT_BOOL( subpixel_hinting_lean &&
2451 !( ( load_flags &
2452 FT_LOAD_TARGET_LCD ) ||
2453 ( load_flags &
2454 FT_LOAD_TARGET_LCD_V ) ) );
2455 exec->vertical_lcd_lean =
2456 FT_BOOL( subpixel_hinting_lean &&
2457 ( load_flags &
2458 FT_LOAD_TARGET_LCD_V ) );
2459 }
2460 else
2461 {
2462 subpixel_hinting_lean = FALSE;
2463 grayscale_cleartype = FALSE;
2464 exec->vertical_lcd_lean = FALSE;
2465 }
2466#endif
2467
2468#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2469
2470 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
2471 {
2472 subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
2473 FT_RENDER_MODE_MONO ) &&
2474 SPH_OPTION_SET_SUBPIXEL );
2475
2476 if ( subpixel_hinting )
2477 grayscale = FALSE;
2478 else if ( SPH_OPTION_SET_GRAYSCALE )
2479 {
2480 grayscale = TRUE;
2481 subpixel_hinting = FALSE;
2482 }
2483 else
2484 grayscale = FALSE;
2485
2486 if ( FT_IS_TRICKY( glyph->face ) )
2487 subpixel_hinting = FALSE;
2488
2489 exec->ignore_x_mode = subpixel_hinting || grayscale;
2490 exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
2491 if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
2492 exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
2493
2494#if 1
2495 exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS;
2496 exec->symmetrical_smoothing = TRUE;
2497 exec->bgr = FALSE;
2498 exec->vertical_lcd = FALSE;
2499 exec->subpixel_positioned = TRUE;
2500 exec->gray_cleartype = FALSE;
2501#else /* 0 */
2502 exec->compatible_widths =
2503 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2504 TT_LOAD_COMPATIBLE_WIDTHS );
2505 exec->symmetrical_smoothing =
2506 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2507 TT_LOAD_SYMMETRICAL_SMOOTHING );
2508 exec->bgr =
2509 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2510 TT_LOAD_BGR );
2511 exec->vertical_lcd =
2512 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2513 TT_LOAD_VERTICAL_LCD );
2514 exec->subpixel_positioned =
2515 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2516 TT_LOAD_SUBPIXEL_POSITIONED );
2517 exec->gray_cleartype =
2518 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2519 TT_LOAD_GRAY_CLEARTYPE );
2520#endif /* 0 */
2521
2522 }
2523 else
2524
2525#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2526
2527#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2528 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2529 grayscale = FT_BOOL( !subpixel_hinting_lean &&
2530 FT_LOAD_TARGET_MODE( load_flags ) !=
2531 FT_RENDER_MODE_MONO );
2532 else
2533#endif
2534 grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2535 FT_RENDER_MODE_MONO );
2536
2537 error = TT_Load_Context( exec, face, size );
2538 if ( error )
2539 return error;
2540
2541#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2542
2543 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
2544 {
2545 /* a change from mono to subpixel rendering (and vice versa) */
2546 /* requires a re-execution of the CVT program */
2547 if ( subpixel_hinting != exec->subpixel_hinting )
2548 {
2549 FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
2550 " re-executing `prep' table\n" ));
2551
2552 exec->subpixel_hinting = subpixel_hinting;
2553 reexecute = TRUE;
2554 }
2555
2556 /* a change from mono to grayscale rendering (and vice versa) */
2557 /* requires a re-execution of the CVT program */
2558 if ( grayscale != exec->grayscale )
2559 {
2560 FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
2561 " re-executing `prep' table\n" ));
2562
2563 exec->grayscale = grayscale;
2564 reexecute = TRUE;
2565 }
2566 }
2567 else
2568
2569#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2570
2571 {
2572
2573#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2574 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2575 {
2576 /* a change from mono to subpixel rendering (and vice versa) */
2577 /* requires a re-execution of the CVT program */
2578 if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
2579 {
2580 FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
2581 " re-executing `prep' table\n" ));
2582
2583 exec->subpixel_hinting_lean = subpixel_hinting_lean;
2584 reexecute = TRUE;
2585 }
2586
2587 /* a change from colored to grayscale subpixel rendering (and */
2588 /* vice versa) requires a re-execution of the CVT program */
2589 if ( grayscale_cleartype != exec->grayscale_cleartype )
2590 {
2591 FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
2592 " re-executing `prep' table\n" ));
2593
2594 exec->grayscale_cleartype = grayscale_cleartype;
2595 reexecute = TRUE;
2596 }
2597 }
2598#endif
2599
2600 /* a change from mono to grayscale rendering (and vice versa) */
2601 /* requires a re-execution of the CVT program */
2602 if ( grayscale != exec->grayscale )
2603 {
2604 FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
2605 " re-executing `prep' table\n" ));
2606
2607 exec->grayscale = grayscale;
2608 reexecute = TRUE;
2609 }
2610 }
2611
2612 if ( reexecute )
2613 {
2614 FT_UInt i;
2615
2616
2617 for ( i = 0; i < size->cvt_size; i++ )
2618 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
2619 error = tt_size_run_prep( size, pedantic );
2620 if ( error )
2621 return error;
2622 }
2623
2624 /* check whether the cvt program has disabled hinting */
2625 if ( exec->GS.instruct_control & 1 )
2626 load_flags |= FT_LOAD_NO_HINTING;
2627
2628 /* load default graphics state -- if needed */
2629 if ( exec->GS.instruct_control & 2 )
2630 exec->GS = tt_default_graphics_state;
2631
2632#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2633 /* check whether we have a font hinted for ClearType -- */
2634 /* note that this flag can also be modified in a glyph's bytecode */
2635 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
2636 exec->GS.instruct_control & 4 )
2637 exec->ignore_x_mode = 0;
2638#endif
2639
2640 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2641 loader->exec = exec;
2642 loader->instructions = exec->glyphIns;
2643 }
2644
2645#endif /* TT_USE_BYTECODE_INTERPRETER */
2646
2647 /* get face's glyph loader */
2648 if ( !glyf_table_only )
2649 {
2650 FT_GlyphLoader gloader = glyph->internal->loader;
2651
2652
2653 FT_GlyphLoader_Rewind( gloader );
2654 loader->gloader = gloader;
2655 }
2656
2657 loader->load_flags = (FT_ULong)load_flags;
2658
2659 loader->face = face;
2660 loader->size = size;
2661 loader->glyph = (FT_GlyphSlot)glyph;
2662 loader->stream = stream;
2663
2664 loader->composites.head = NULL;
2665 loader->composites.tail = NULL;
2666
2667 return FT_Err_Ok;
2668 }
2669
2670
2671 static void
2672 tt_loader_done( TT_Loader loader )
2673 {
2674 FT_List_Finalize( &loader->composites,
2675 NULL,
2676 loader->face->root.memory,
2677 NULL );
2678 }
2679
2680
2681 /**************************************************************************
2682 *
2683 * @Function:
2684 * TT_Load_Glyph
2685 *
2686 * @Description:
2687 * A function used to load a single glyph within a given glyph slot,
2688 * for a given size.
2689 *
2690 * @Input:
2691 * glyph ::
2692 * A handle to a target slot object where the glyph
2693 * will be loaded.
2694 *
2695 * size ::
2696 * A handle to the source face size at which the glyph
2697 * must be scaled/loaded.
2698 *
2699 * glyph_index ::
2700 * The index of the glyph in the font file.
2701 *
2702 * load_flags ::
2703 * A flag indicating what to load for this glyph. The
2704 * FT_LOAD_XXX constants can be used to control the
2705 * glyph loading process (e.g., whether the outline
2706 * should be scaled, whether to load bitmaps or not,
2707 * whether to hint the outline, etc).
2708 *
2709 * @Return:
2710 * FreeType error code. 0 means success.
2711 */
2712 FT_LOCAL_DEF( FT_Error )
2713 TT_Load_Glyph( TT_Size size,
2714 TT_GlyphSlot glyph,
2715 FT_UInt glyph_index,
2716 FT_Int32 load_flags )
2717 {
2718 FT_Error error;
2719 TT_LoaderRec loader;
2720
2721#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
2722#define IS_DEFAULT_INSTANCE ( !( FT_IS_NAMED_INSTANCE( glyph->face ) || \
2723 FT_IS_VARIATION( glyph->face ) ) )
2724#else
2725#define IS_DEFAULT_INSTANCE 1
2726#endif
2727
2728
2729 FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
2730
2731#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2732
2733 /* try to load embedded bitmap (if any) */
2734 if ( size->strike_index != 0xFFFFFFFFUL &&
2735 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
2736 IS_DEFAULT_INSTANCE )
2737 {
2738 FT_Fixed x_scale = size->root.metrics.x_scale;
2739 FT_Fixed y_scale = size->root.metrics.y_scale;
2740
2741
2742 error = load_sbit_image( size, glyph, glyph_index, load_flags );
2743 if ( FT_ERR_EQ( error, Missing_Bitmap ) )
2744 {
2745 /* the bitmap strike is incomplete and misses the requested glyph; */
2746 /* if we have a bitmap-only font, return an empty glyph */
2747 if ( !FT_IS_SCALABLE( glyph->face ) )
2748 {
2749 TT_Face face = (TT_Face)glyph->face;
2750
2751 FT_Short left_bearing = 0;
2752 FT_Short top_bearing = 0;
2753
2754 FT_UShort advance_width = 0;
2755 FT_UShort advance_height = 0;
2756
2757
2758 /* to return an empty glyph, however, we need metrics data */
2759 /* from the `hmtx' (or `vmtx') table; the assumption is that */
2760 /* empty glyphs are missing intentionally, representing */
2761 /* whitespace - not having at least horizontal metrics is */
2762 /* thus considered an error */
2763 if ( !face->horz_metrics_size )
2764 return error;
2765
2766 /* we now construct an empty bitmap glyph */
2767 TT_Get_HMetrics( face, glyph_index,
2768 &left_bearing,
2769 &advance_width );
2770 TT_Get_VMetrics( face, glyph_index,
2771 0,
2772 &top_bearing,
2773 &advance_height );
2774
2775 glyph->outline.n_points = 0;
2776 glyph->outline.n_contours = 0;
2777
2778 glyph->metrics.width = 0;
2779 glyph->metrics.height = 0;
2780
2781 glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale );
2782 glyph->metrics.horiBearingY = 0;
2783 glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale );
2784
2785 glyph->metrics.vertBearingX = 0;
2786 glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale );
2787 glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale );
2788
2789 glyph->format = FT_GLYPH_FORMAT_BITMAP;
2790 glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
2791
2792 glyph->bitmap_left = 0;
2793 glyph->bitmap_top = 0;
2794
2795 return FT_Err_Ok;
2796 }
2797 }
2798 else if ( error )
2799 {
2800 /* return error if font is not scalable */
2801 if ( !FT_IS_SCALABLE( glyph->face ) )
2802 return error;
2803 }
2804 else
2805 {
2806 if ( FT_IS_SCALABLE( glyph->face ) )
2807 {
2808 /* for the bbox we need the header only */
2809 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
2810 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
2811 tt_loader_done( &loader );
2812 glyph->linearHoriAdvance = loader.linear;
2813 glyph->linearVertAdvance = loader.vadvance;
2814
2815 /* sanity checks: if `xxxAdvance' in the sbit metric */
2816 /* structure isn't set, use `linearXXXAdvance' */
2817 if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
2818 glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance,
2819 x_scale );
2820 if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
2821 glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance,
2822 y_scale );
2823 }
2824
2825 return FT_Err_Ok;
2826 }
2827 }
2828
2829#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2830
2831 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
2832 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
2833 {
2834 error = FT_THROW( Invalid_Size_Handle );
2835 goto Exit;
2836 }
2837
2838 if ( load_flags & FT_LOAD_SBITS_ONLY )
2839 {
2840 error = FT_THROW( Invalid_Argument );
2841 goto Exit;
2842 }
2843
2844 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
2845 if ( error )
2846 goto Exit;
2847
2848 glyph->format = FT_GLYPH_FORMAT_OUTLINE;
2849 glyph->num_subglyphs = 0;
2850 glyph->outline.flags = 0;
2851
2852 /* main loading loop */
2853 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
2854 if ( !error )
2855 {
2856 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
2857 {
2858 glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
2859 glyph->subglyphs = loader.gloader->base.subglyphs;
2860 }
2861 else
2862 {
2863 glyph->outline = loader.gloader->base.outline;
2864 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
2865
2866 /* Translate array so that (0,0) is the glyph's origin. Note */
2867 /* that this behaviour is independent on the value of bit 1 of */
2868 /* the `flags' field in the `head' table -- at least major */
2869 /* applications like Acroread indicate that. */
2870 if ( loader.pp1.x )
2871 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
2872 }
2873
2874#ifdef TT_USE_BYTECODE_INTERPRETER
2875
2876 if ( IS_HINTED( load_flags ) )
2877 {
2878 if ( loader.exec->GS.scan_control )
2879 {
2880 /* convert scan conversion mode to FT_OUTLINE_XXX flags */
2881 switch ( loader.exec->GS.scan_type )
2882 {
2883 case 0: /* simple drop-outs including stubs */
2884 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
2885 break;
2886 case 1: /* simple drop-outs excluding stubs */
2887 /* nothing; it's the default rendering mode */
2888 break;
2889 case 4: /* smart drop-outs including stubs */
2890 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
2891 FT_OUTLINE_INCLUDE_STUBS;
2892 break;
2893 case 5: /* smart drop-outs excluding stubs */
2894 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
2895 break;
2896
2897 default: /* no drop-out control */
2898 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2899 break;
2900 }
2901 }
2902 else
2903 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2904 }
2905
2906#endif /* TT_USE_BYTECODE_INTERPRETER */
2907
2908 error = compute_glyph_metrics( &loader, glyph_index );
2909 }
2910
2911 tt_loader_done( &loader );
2912
2913 /* Set the `high precision' bit flag. */
2914 /* This is _critical_ to get correct output for monochrome */
2915 /* TrueType glyphs at all sizes using the bytecode interpreter. */
2916 /* */
2917 if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
2918 size->metrics->y_ppem < 24 )
2919 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
2920
2921 Exit:
2922#ifdef FT_DEBUG_LEVEL_TRACE
2923 if ( error )
2924 FT_TRACE1(( " failed (error code 0x%x)\n",
2925 error ));
2926#endif
2927
2928 return error;
2929 }
2930
2931
2932/* END */
2933