1 /***************************************************************************/
5 /* TrueType Glyph Loader (body). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
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
30 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
37 /*************************************************************************/
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. */
44 #define FT_COMPONENT trace_ttgload
47 /*************************************************************************/
49 /* Composite font flags. */
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
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
66 /*************************************************************************/
68 /* Returns the horizontal metrics in font units for a given glyph. If */
69 /* `check' is true, take care of monospaced fonts by returning the */
70 /* advance width maximum. */
73 Get_HMetrics( TT_Face face
,
79 ( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 0, idx
, lsb
, aw
);
81 if ( check
&& face
->postscript
.isFixedPitch
)
82 *aw
= face
->horizontal
.advance_Width_Max
;
86 /*************************************************************************/
88 /* Returns the vertical metrics in font units for a given glyph. */
89 /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
90 /* table, typoAscender/Descender from the `OS/2' table would be used */
91 /* instead, and if there were no `OS/2' table, use ascender/descender */
92 /* from the `hhea' table. But that is not what Microsoft's rasterizer */
93 /* apparently does: It uses the ppem value as the advance height, and */
94 /* sets the top side bearing to be zero. */
96 /* The monospace `check' is probably not meaningful here, but we leave */
97 /* it in for a consistent interface. */
100 Get_VMetrics( TT_Face face
,
108 if ( face
->vertical_info
)
109 ( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 1, idx
, tsb
, ah
);
111 #if 1 /* Empirically determined, at variance with what MS said */
116 *ah
= face
->root
.units_per_EM
;
119 #else /* This is what MS said to do. It isn't what they do, however. */
121 else if ( face
->os2
.version
!= 0xFFFFU
)
123 *tsb
= face
->os2
.sTypoAscender
;
124 *ah
= face
->os2
.sTypoAscender
- face
->os2
.sTypoDescender
;
128 *tsb
= face
->horizontal
.Ascender
;
129 *ah
= face
->horizontal
.Ascender
- face
->horizontal
.Descender
;
137 /*************************************************************************/
139 /* Translates an array of coordinates. */
142 translate_array( FT_UInt n
,
151 for ( k
= 0; k
< n
; k
++ )
152 coords
[k
].x
+= delta_x
;
155 for ( k
= 0; k
< n
; k
++ )
156 coords
[k
].y
+= delta_y
;
161 #define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
164 /*************************************************************************/
166 /* The following functions are used by default with TrueType fonts. */
167 /* However, they can be replaced by alternatives if we need to support */
168 /* TrueType-compressed formats (like MicroType) in the future. */
170 /*************************************************************************/
172 FT_CALLBACK_DEF( FT_Error
)
173 TT_Access_Glyph_Frame( TT_Loader loader
,
179 FT_Stream stream
= loader
->stream
;
181 /* for non-debug mode */
182 FT_UNUSED( glyph_index
);
185 FT_TRACE5(( "Glyph %ld\n", glyph_index
));
187 /* the following line sets the `error' variable through macros! */
188 if ( FT_STREAM_SEEK( offset
) || FT_FRAME_ENTER( byte_count
) )
191 loader
->cursor
= stream
->cursor
;
192 loader
->limit
= stream
->limit
;
198 FT_CALLBACK_DEF( void )
199 TT_Forget_Glyph_Frame( TT_Loader loader
)
201 FT_Stream stream
= loader
->stream
;
208 FT_CALLBACK_DEF( FT_Error
)
209 TT_Load_Glyph_Header( TT_Loader loader
)
211 FT_Byte
* p
= loader
->cursor
;
212 FT_Byte
* limit
= loader
->limit
;
215 if ( p
+ 10 > limit
)
216 return TT_Err_Invalid_Outline
;
218 loader
->n_contours
= FT_NEXT_SHORT( p
);
220 loader
->bbox
.xMin
= FT_NEXT_SHORT( p
);
221 loader
->bbox
.yMin
= FT_NEXT_SHORT( p
);
222 loader
->bbox
.xMax
= FT_NEXT_SHORT( p
);
223 loader
->bbox
.yMax
= FT_NEXT_SHORT( p
);
225 FT_TRACE5(( " # of contours: %d\n", loader
->n_contours
));
226 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader
->bbox
.xMin
,
227 loader
->bbox
.xMax
));
228 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader
->bbox
.yMin
,
229 loader
->bbox
.yMax
));
236 FT_CALLBACK_DEF( FT_Error
)
237 TT_Load_Simple_Glyph( TT_Loader load
)
240 FT_Byte
* p
= load
->cursor
;
241 FT_Byte
* limit
= load
->limit
;
242 FT_GlyphLoader gloader
= load
->gloader
;
243 FT_Int n_contours
= load
->n_contours
;
245 TT_Face face
= (TT_Face
)load
->face
;
249 FT_Byte
*flag
, *flag_limit
;
251 FT_Vector
*vec
, *vec_limit
;
253 FT_Short
*cont
, *cont_limit
, prev_cont
;
257 /* check that we can add the contours to the glyph */
258 error
= FT_GLYPHLOADER_CHECK_POINTS( gloader
, 0, n_contours
);
262 /* reading the contours' endpoints & number of points */
263 cont
= gloader
->current
.outline
.contours
;
264 cont_limit
= cont
+ n_contours
;
266 /* check space for contours array + instructions count */
267 if ( n_contours
>= 0xFFF || p
+ ( n_contours
+ 1 ) * 2 > limit
)
268 goto Invalid_Outline
;
270 prev_cont
= FT_NEXT_USHORT( p
);
272 if ( n_contours
> 0 )
275 for ( cont
++; cont
< cont_limit
; cont
++ )
277 cont
[0] = FT_NEXT_USHORT( p
);
278 if ( cont
[0] <= prev_cont
)
280 /* unordered contours: this is invalid */
281 error
= FT_Err_Invalid_Table
;
288 if ( n_contours
> 0 )
290 n_points
= cont
[-1] + 1;
292 goto Invalid_Outline
;
295 /* note that we will add four phantom points later */
296 error
= FT_GLYPHLOADER_CHECK_POINTS( gloader
, n_points
+ 4, 0 );
300 /* we'd better check the contours table right now */
301 outline
= &gloader
->current
.outline
;
303 for ( cont
= outline
->contours
+ 1; cont
< cont_limit
; cont
++ )
304 if ( cont
[-1] >= cont
[0] )
305 goto Invalid_Outline
;
307 /* reading the bytecode instructions */
308 load
->glyph
->control_len
= 0;
309 load
->glyph
->control_data
= 0;
312 goto Invalid_Outline
;
314 n_ins
= FT_NEXT_USHORT( p
);
316 FT_TRACE5(( " Instructions size: %u\n", n_ins
));
318 if ( n_ins
> face
->max_profile
.maxSizeOfInstructions
)
320 FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions (%d)\n",
322 error
= TT_Err_Too_Many_Hints
;
326 if ( ( limit
- p
) < n_ins
)
328 FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" ));
329 error
= TT_Err_Too_Many_Hints
;
333 #ifdef TT_USE_BYTECODE_INTERPRETER
335 if ( IS_HINTED( load
->load_flags
) )
337 load
->glyph
->control_len
= n_ins
;
338 load
->glyph
->control_data
= load
->exec
->glyphIns
;
340 FT_MEM_COPY( load
->exec
->glyphIns
, p
, (FT_Long
)n_ins
);
343 #endif /* TT_USE_BYTECODE_INTERPRETER */
347 /* reading the point tags */
348 flag
= (FT_Byte
*)outline
->tags
;
349 flag_limit
= flag
+ n_points
;
351 FT_ASSERT( flag
!= NULL
);
353 while ( flag
< flag_limit
)
356 goto Invalid_Outline
;
358 *flag
++ = c
= FT_NEXT_BYTE( p
);
362 goto Invalid_Outline
;
364 count
= FT_NEXT_BYTE( p
);
365 if ( flag
+ (FT_Int
)count
> flag_limit
)
366 goto Invalid_Outline
;
368 for ( ; count
> 0; count
-- )
373 /* reading the X coordinates */
375 vec
= outline
->points
;
376 vec_limit
= vec
+ n_points
;
377 flag
= (FT_Byte
*)outline
->tags
;
380 if ( p
+ xy_size
> limit
)
381 goto Invalid_Outline
;
383 for ( ; vec
< vec_limit
; vec
++, flag
++ )
392 goto Invalid_Outline
;
394 y
= (FT_Pos
)FT_NEXT_BYTE( p
);
395 if ( ( f
& 16 ) == 0 )
398 else if ( ( f
& 16 ) == 0 )
401 goto Invalid_Outline
;
403 y
= (FT_Pos
)FT_NEXT_SHORT( p
);
408 *flag
= f
& ~( 2 | 16 );
411 /* reading the Y coordinates */
413 vec
= gloader
->current
.outline
.points
;
414 vec_limit
= vec
+ n_points
;
415 flag
= (FT_Byte
*)outline
->tags
;
418 for ( ; vec
< vec_limit
; vec
++, flag
++ )
427 goto Invalid_Outline
;
429 y
= (FT_Pos
)FT_NEXT_BYTE( p
);
430 if ( ( f
& 32 ) == 0 )
433 else if ( ( f
& 32 ) == 0 )
436 goto Invalid_Outline
;
438 y
= (FT_Pos
)FT_NEXT_SHORT( p
);
443 *flag
= f
& FT_CURVE_TAG_ON
;
446 outline
->n_points
= (FT_UShort
)n_points
;
447 outline
->n_contours
= (FT_Short
) n_contours
;
455 error
= TT_Err_Invalid_Outline
;
460 FT_CALLBACK_DEF( FT_Error
)
461 TT_Load_Composite_Glyph( TT_Loader loader
)
464 FT_Byte
* p
= loader
->cursor
;
465 FT_Byte
* limit
= loader
->limit
;
466 FT_GlyphLoader gloader
= loader
->gloader
;
467 FT_SubGlyph subglyph
;
468 FT_UInt num_subglyphs
;
475 FT_Fixed xx
, xy
, yy
, yx
;
479 /* check that we can load a new subglyph */
480 error
= FT_GlyphLoader_CheckSubGlyphs( gloader
, num_subglyphs
+ 1 );
486 goto Invalid_Composite
;
488 subglyph
= gloader
->current
.subglyphs
+ num_subglyphs
;
490 subglyph
->arg1
= subglyph
->arg2
= 0;
492 subglyph
->flags
= FT_NEXT_USHORT( p
);
493 subglyph
->index
= FT_NEXT_USHORT( p
);
497 if ( subglyph
->flags
& ARGS_ARE_WORDS
)
499 if ( subglyph
->flags
& WE_HAVE_A_SCALE
)
501 else if ( subglyph
->flags
& WE_HAVE_AN_XY_SCALE
)
503 else if ( subglyph
->flags
& WE_HAVE_A_2X2
)
506 if ( p
+ count
> limit
)
507 goto Invalid_Composite
;
510 if ( subglyph
->flags
& ARGS_ARE_WORDS
)
512 subglyph
->arg1
= FT_NEXT_SHORT( p
);
513 subglyph
->arg2
= FT_NEXT_SHORT( p
);
517 subglyph
->arg1
= FT_NEXT_CHAR( p
);
518 subglyph
->arg2
= FT_NEXT_CHAR( p
);
525 if ( subglyph
->flags
& WE_HAVE_A_SCALE
)
527 xx
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
530 else if ( subglyph
->flags
& WE_HAVE_AN_XY_SCALE
)
532 xx
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
533 yy
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
535 else if ( subglyph
->flags
& WE_HAVE_A_2X2
)
537 xx
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
538 yx
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
539 xy
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
540 yy
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
543 subglyph
->transform
.xx
= xx
;
544 subglyph
->transform
.xy
= xy
;
545 subglyph
->transform
.yx
= yx
;
546 subglyph
->transform
.yy
= yy
;
550 } while ( subglyph
->flags
& MORE_COMPONENTS
);
552 gloader
->current
.num_subglyphs
= num_subglyphs
;
554 #ifdef TT_USE_BYTECODE_INTERPRETER
557 FT_Stream stream
= loader
->stream
;
560 /* we must undo the FT_FRAME_ENTER in order to point */
561 /* to the composite instructions, if we find some. */
562 /* We will process them later. */
564 loader
->ins_pos
= (FT_ULong
)( FT_STREAM_POS() +
576 error
= TT_Err_Invalid_Composite
;
582 TT_Init_Glyph_Loading( TT_Face face
)
584 face
->access_glyph_frame
= TT_Access_Glyph_Frame
;
585 face
->read_glyph_header
= TT_Load_Glyph_Header
;
586 face
->read_simple_glyph
= TT_Load_Simple_Glyph
;
587 face
->read_composite_glyph
= TT_Load_Composite_Glyph
;
588 face
->forget_glyph_frame
= TT_Forget_Glyph_Frame
;
593 tt_prepare_zone( TT_GlyphZone zone
,
596 FT_UInt start_contour
)
598 zone
->n_points
= (FT_UShort
)( load
->outline
.n_points
- start_point
);
599 zone
->n_contours
= (FT_Short
) ( load
->outline
.n_contours
-
601 zone
->org
= load
->extra_points
+ start_point
;
602 zone
->cur
= load
->outline
.points
+ start_point
;
603 zone
->orus
= load
->extra_points2
+ start_point
;
604 zone
->tags
= (FT_Byte
*)load
->outline
.tags
+ start_point
;
605 zone
->contours
= (FT_UShort
*)load
->outline
.contours
+ start_contour
;
606 zone
->first_point
= (FT_UShort
)start_point
;
610 /*************************************************************************/
616 /* Hint the glyph using the zone prepared by the caller. Note that */
617 /* the zone is supposed to include four phantom points. */
620 TT_Hint_Glyph( TT_Loader loader
,
621 FT_Bool is_composite
)
623 TT_GlyphZone zone
= &loader
->zone
;
626 #ifdef TT_USE_BYTECODE_INTERPRETER
629 FT_UNUSED( is_composite
);
633 #ifdef TT_USE_BYTECODE_INTERPRETER
634 n_ins
= loader
->glyph
->control_len
;
637 origin
= zone
->cur
[zone
->n_points
- 4].x
;
638 origin
= FT_PIX_ROUND( origin
) - origin
;
640 translate_array( zone
->n_points
, zone
->cur
, origin
, 0 );
642 #ifdef TT_USE_BYTECODE_INTERPRETER
643 /* save original point position in org */
645 FT_ARRAY_COPY( zone
->org
, zone
->cur
, zone
->n_points
);
647 /* Reset graphics state. */
648 loader
->exec
->GS
= ((TT_Size
)loader
->size
)->GS
;
650 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
651 /* completely refer to the (already) hinted subglyphs. */
654 loader
->exec
->metrics
.x_scale
= 1 << 16;
655 loader
->exec
->metrics
.y_scale
= 1 << 16;
657 FT_ARRAY_COPY( zone
->orus
, zone
->cur
, zone
->n_points
);
661 loader
->exec
->metrics
.x_scale
=
662 ((TT_Size
)loader
->size
)->metrics
.x_scale
;
663 loader
->exec
->metrics
.y_scale
=
664 ((TT_Size
)loader
->size
)->metrics
.y_scale
;
668 /* round pp2 and pp4 */
669 zone
->cur
[zone
->n_points
- 3].x
=
670 FT_PIX_ROUND( zone
->cur
[zone
->n_points
- 3].x
);
671 zone
->cur
[zone
->n_points
- 1].y
=
672 FT_PIX_ROUND( zone
->cur
[zone
->n_points
- 1].y
);
674 #ifdef TT_USE_BYTECODE_INTERPRETER
682 error
= TT_Set_CodeRange( loader
->exec
, tt_coderange_glyph
,
683 loader
->exec
->glyphIns
, n_ins
);
687 loader
->exec
->is_composite
= is_composite
;
688 loader
->exec
->pts
= *zone
;
690 debug
= FT_BOOL( !( loader
->load_flags
& FT_LOAD_NO_SCALE
) &&
691 ((TT_Size
)loader
->size
)->debug
);
693 error
= TT_Run_Context( loader
->exec
, debug
);
694 if ( error
&& loader
->exec
->pedantic_hinting
)
700 /* save glyph phantom points */
701 if ( !loader
->preserve_pps
)
703 loader
->pp1
= zone
->cur
[zone
->n_points
- 4];
704 loader
->pp2
= zone
->cur
[zone
->n_points
- 3];
705 loader
->pp3
= zone
->cur
[zone
->n_points
- 2];
706 loader
->pp4
= zone
->cur
[zone
->n_points
- 1];
713 /*************************************************************************/
716 /* TT_Process_Simple_Glyph */
719 /* Once a simple glyph has been loaded, it needs to be processed. */
720 /* Usually, this means scaling and hinting through bytecode */
721 /* interpretation. */
724 TT_Process_Simple_Glyph( TT_Loader loader
)
726 FT_GlyphLoader gloader
= loader
->gloader
;
727 FT_Error error
= TT_Err_Ok
;
732 outline
= &gloader
->current
.outline
;
733 n_points
= outline
->n_points
;
735 /* set phantom points */
737 outline
->points
[n_points
] = loader
->pp1
;
738 outline
->points
[n_points
+ 1] = loader
->pp2
;
739 outline
->points
[n_points
+ 2] = loader
->pp3
;
740 outline
->points
[n_points
+ 3] = loader
->pp4
;
742 outline
->tags
[n_points
] = 0;
743 outline
->tags
[n_points
+ 1] = 0;
744 outline
->tags
[n_points
+ 2] = 0;
745 outline
->tags
[n_points
+ 3] = 0;
749 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
751 if ( ((TT_Face
)loader
->face
)->doblend
)
753 /* Deltas apply to the unscaled data. */
755 FT_Memory memory
= loader
->face
->memory
;
759 error
= TT_Vary_Get_Glyph_Deltas( (TT_Face
)(loader
->face
),
766 for ( i
= 0; i
< n_points
; ++i
)
768 outline
->points
[i
].x
+= deltas
[i
].x
;
769 outline
->points
[i
].y
+= deltas
[i
].y
;
775 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
777 if ( IS_HINTED( loader
->load_flags
) )
779 tt_prepare_zone( &loader
->zone
, &gloader
->current
, 0, 0 );
781 FT_ARRAY_COPY( loader
->zone
.orus
, loader
->zone
.cur
,
782 loader
->zone
.n_points
+ 4 );
785 /* scale the glyph */
786 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
788 FT_Vector
* vec
= outline
->points
;
789 FT_Vector
* limit
= outline
->points
+ n_points
;
790 FT_Fixed x_scale
= ((TT_Size
)loader
->size
)->metrics
.x_scale
;
791 FT_Fixed y_scale
= ((TT_Size
)loader
->size
)->metrics
.y_scale
;
794 for ( ; vec
< limit
; vec
++ )
796 vec
->x
= FT_MulFix( vec
->x
, x_scale
);
797 vec
->y
= FT_MulFix( vec
->y
, y_scale
);
800 loader
->pp1
= outline
->points
[n_points
- 4];
801 loader
->pp2
= outline
->points
[n_points
- 3];
802 loader
->pp3
= outline
->points
[n_points
- 2];
803 loader
->pp4
= outline
->points
[n_points
- 1];
806 if ( IS_HINTED( loader
->load_flags
) )
808 loader
->zone
.n_points
+= 4;
810 error
= TT_Hint_Glyph( loader
, 0 );
817 /*************************************************************************/
820 /* TT_Process_Composite_Component */
823 /* Once a composite component has been loaded, it needs to be */
824 /* processed. Usually, this means transforming and translating. */
827 TT_Process_Composite_Component( TT_Loader loader
,
828 FT_SubGlyph subglyph
,
830 FT_UInt num_base_points
)
832 FT_GlyphLoader gloader
= loader
->gloader
;
833 FT_Vector
* base_vec
= gloader
->base
.outline
.points
;
834 FT_UInt num_points
= gloader
->base
.outline
.n_points
;
839 have_scale
= FT_BOOL( subglyph
->flags
& ( WE_HAVE_A_SCALE
|
840 WE_HAVE_AN_XY_SCALE
|
843 /* perform the transform required for this subglyph */
849 for ( i
= num_base_points
; i
< num_points
; i
++ )
850 FT_Vector_Transform( base_vec
+ i
, &subglyph
->transform
);
854 if ( !( subglyph
->flags
& ARGS_ARE_XY_VALUES
) )
856 FT_UInt k
= subglyph
->arg1
;
857 FT_UInt l
= subglyph
->arg2
;
862 /* match l-th point of the newly loaded component to the k-th point */
863 /* of the previously loaded components. */
865 /* change to the point numbers used by our outline */
867 l
+= num_base_points
;
868 if ( k
>= num_base_points
||
870 return TT_Err_Invalid_Composite
;
872 p1
= gloader
->base
.outline
.points
+ k
;
873 p2
= gloader
->base
.outline
.points
+ l
;
886 /* Use a default value dependent on */
887 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */
888 /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */
891 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
892 !( subglyph
->flags
& UNSCALED_COMPONENT_OFFSET
) )
894 ( subglyph
->flags
& SCALED_COMPONENT_OFFSET
) )
900 /*************************************************************************/
902 /* This algorithm is what Apple documents. But it doesn't work. */
904 int a
= subglyph
->transform
.xx
> 0 ? subglyph
->transform
.xx
905 : -subglyph
->transform
.xx
;
906 int b
= subglyph
->transform
.yx
> 0 ? subglyph
->transform
.yx
907 : -subglyph
->transform
.yx
;
908 int c
= subglyph
->transform
.xy
> 0 ? subglyph
->transform
.xy
909 : -subglyph
->transform
.xy
;
910 int d
= subglyph
->transform
.yy
> 0 ? subglyph
->transform
.yy
911 : -subglyph
->transform
.yy
;
912 int m
= a
> b
? a
: b
;
913 int n
= c
> d
? c
: d
;
916 if ( a
- b
<= 33 && a
- b
>= -33 )
918 if ( c
- d
<= 33 && c
- d
>= -33 )
920 x
= FT_MulFix( x
, m
);
921 y
= FT_MulFix( y
, n
);
925 /*************************************************************************/
927 /* This algorithm is a guess and works much better than the above. */
929 FT_Fixed mac_xscale
= FT_SqrtFixed(
930 FT_MulFix( subglyph
->transform
.xx
,
931 subglyph
->transform
.xx
) +
932 FT_MulFix( subglyph
->transform
.xy
,
933 subglyph
->transform
.xy
) );
934 FT_Fixed mac_yscale
= FT_SqrtFixed(
935 FT_MulFix( subglyph
->transform
.yy
,
936 subglyph
->transform
.yy
) +
937 FT_MulFix( subglyph
->transform
.yx
,
938 subglyph
->transform
.yx
) );
941 x
= FT_MulFix( x
, mac_xscale
);
942 y
= FT_MulFix( y
, mac_yscale
);
948 if ( !( loader
->load_flags
& FT_LOAD_NO_SCALE
) )
950 FT_Fixed x_scale
= ((TT_Size
)loader
->size
)->metrics
.x_scale
;
951 FT_Fixed y_scale
= ((TT_Size
)loader
->size
)->metrics
.y_scale
;
954 x
= FT_MulFix( x
, x_scale
);
955 y
= FT_MulFix( y
, y_scale
);
957 if ( subglyph
->flags
& ROUND_XY_TO_GRID
)
959 x
= FT_PIX_ROUND( x
);
960 y
= FT_PIX_ROUND( y
);
966 translate_array( num_points
- num_base_points
,
967 base_vec
+ num_base_points
,
974 /*************************************************************************/
977 /* TT_Process_Composite_Glyph */
980 /* This is slightly different from TT_Process_Simple_Glyph, in that */
981 /* its sole purpose is to hint the glyph. Thus this function is */
982 /* only available when bytecode interpreter is enabled. */
985 TT_Process_Composite_Glyph( TT_Loader loader
,
987 FT_UInt start_contour
)
994 outline
= &loader
->gloader
->base
.outline
;
996 /* make room for phantom points */
997 error
= FT_GLYPHLOADER_CHECK_POINTS( loader
->gloader
,
998 outline
->n_points
+ 4,
1003 outline
->points
[outline
->n_points
] = loader
->pp1
;
1004 outline
->points
[outline
->n_points
+ 1] = loader
->pp2
;
1005 outline
->points
[outline
->n_points
+ 2] = loader
->pp3
;
1006 outline
->points
[outline
->n_points
+ 3] = loader
->pp4
;
1008 outline
->tags
[outline
->n_points
] = 0;
1009 outline
->tags
[outline
->n_points
+ 1] = 0;
1010 outline
->tags
[outline
->n_points
+ 2] = 0;
1011 outline
->tags
[outline
->n_points
+ 3] = 0;
1013 #ifdef TT_USE_BYTECODE_INTERPRETER
1016 FT_Stream stream
= loader
->stream
;
1020 /* TT_Load_Composite_Glyph only gives us the offset of instructions */
1021 /* so we read them here */
1022 if ( FT_STREAM_SEEK( loader
->ins_pos
) ||
1023 FT_READ_USHORT( n_ins
) )
1026 FT_TRACE5(( " Instructions size = %d\n", n_ins
));
1029 if ( n_ins
> ((TT_Face
)loader
->face
)->max_profile
.maxSizeOfInstructions
)
1031 FT_TRACE0(( "TT_Process_Composite_Glyph: Too many instructions (%d)\n",
1034 return TT_Err_Too_Many_Hints
;
1036 else if ( n_ins
== 0 )
1039 if ( FT_STREAM_READ( loader
->exec
->glyphIns
, n_ins
) )
1042 loader
->glyph
->control_data
= loader
->exec
->glyphIns
;
1043 loader
->glyph
->control_len
= n_ins
;
1048 tt_prepare_zone( &loader
->zone
, &loader
->gloader
->base
,
1049 start_point
, start_contour
);
1051 /* Some points are likely touched during execution of */
1052 /* instructions on components. So let's untouch them. */
1053 for ( i
= start_point
; i
< loader
->zone
.n_points
; i
++ )
1054 loader
->zone
.tags
[i
] &= ~( FT_CURVE_TAG_TOUCH_X
|
1055 FT_CURVE_TAG_TOUCH_Y
);
1057 loader
->zone
.n_points
+= 4;
1059 return TT_Hint_Glyph( loader
, 1 );
1063 /* Calculate the four phantom points. */
1064 /* The first two stand for horizontal origin and advance. */
1065 /* The last two stand for vertical origin and advance. */
1066 #define TT_LOADER_SET_PP( loader ) \
1068 (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
1069 (loader)->pp1.y = 0; \
1070 (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
1071 (loader)->pp2.y = 0; \
1072 (loader)->pp3.x = 0; \
1073 (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \
1074 (loader)->pp4.x = 0; \
1075 (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
1079 /*************************************************************************/
1082 /* load_truetype_glyph */
1085 /* Loads a given truetype glyph. Handles composites and uses a */
1086 /* TT_Loader object. */
1089 load_truetype_glyph( TT_Loader loader
,
1090 FT_UInt glyph_index
,
1091 FT_UInt recurse_count
)
1094 FT_Fixed x_scale
, y_scale
;
1096 TT_Face face
= (TT_Face
)loader
->face
;
1097 FT_GlyphLoader gloader
= loader
->gloader
;
1098 FT_Bool opened_frame
= 0;
1100 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1101 FT_Vector
* deltas
= NULL
;
1104 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1105 FT_StreamRec inc_stream
;
1107 FT_Bool glyph_data_loaded
= 0;
1111 /* some fonts have an incorrect value of `maxComponentDepth', */
1112 /* thus we allow depth 1 to catch the majority of them */
1113 if ( recurse_count
> 1 &&
1114 recurse_count
> face
->max_profile
.maxComponentDepth
)
1116 error
= TT_Err_Invalid_Composite
;
1120 /* check glyph index */
1121 if ( glyph_index
>= (FT_UInt
)face
->root
.num_glyphs
)
1123 error
= TT_Err_Invalid_Glyph_Index
;
1127 loader
->glyph_index
= glyph_index
;
1129 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1131 x_scale
= ((TT_Size
)loader
->size
)->metrics
.x_scale
;
1132 y_scale
= ((TT_Size
)loader
->size
)->metrics
.y_scale
;
1140 /* get metrics, horizontal and vertical */
1142 FT_Short left_bearing
= 0, top_bearing
= 0;
1143 FT_UShort advance_width
= 0, advance_height
= 0;
1146 Get_HMetrics( face
, glyph_index
,
1147 (FT_Bool
)!( loader
->load_flags
&
1148 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
),
1151 Get_VMetrics( face
, glyph_index
,
1152 (FT_Bool
)!( loader
->load_flags
&
1153 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
),
1157 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1159 /* If this is an incrementally loaded font see if there are */
1160 /* overriding metrics for this glyph. */
1161 if ( face
->root
.internal
->incremental_interface
&&
1162 face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics
)
1164 FT_Incremental_MetricsRec metrics
;
1167 metrics
.bearing_x
= left_bearing
;
1168 metrics
.bearing_y
= 0;
1169 metrics
.advance
= advance_width
;
1170 error
= face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics(
1171 face
->root
.internal
->incremental_interface
->object
,
1172 glyph_index
, FALSE
, &metrics
);
1175 left_bearing
= (FT_Short
)metrics
.bearing_x
;
1176 advance_width
= (FT_UShort
)metrics
.advance
;
1180 /* GWW: Do I do the same for vertical metrics? */
1181 metrics
.bearing_x
= 0;
1182 metrics
.bearing_y
= top_bearing
;
1183 metrics
.advance
= advance_height
;
1184 error
= face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics(
1185 face
->root
.internal
->incremental_interface
->object
,
1186 glyph_index
, TRUE
, &metrics
);
1189 top_bearing
= (FT_Short
)metrics
.bearing_y
;
1190 advance_height
= (FT_UShort
)metrics
.advance
;
1196 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1198 loader
->left_bearing
= left_bearing
;
1199 loader
->advance
= advance_width
;
1200 loader
->top_bearing
= top_bearing
;
1201 loader
->vadvance
= advance_height
;
1203 if ( !loader
->linear_def
)
1205 loader
->linear_def
= 1;
1206 loader
->linear
= advance_width
;
1210 /* Set `offset' to the start of the glyph relative to the start of */
1211 /* the `glyf' table, and `byte_len' to the length of the glyph in */
1214 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1216 /* If we are loading glyph data via the incremental interface, set */
1217 /* the loader stream to a memory stream reading the data returned */
1218 /* by the interface. */
1219 if ( face
->root
.internal
->incremental_interface
)
1221 error
= face
->root
.internal
->incremental_interface
->funcs
->get_glyph_data(
1222 face
->root
.internal
->incremental_interface
->object
,
1223 glyph_index
, &glyph_data
);
1227 glyph_data_loaded
= 1;
1229 loader
->byte_len
= glyph_data
.length
;
1231 FT_MEM_ZERO( &inc_stream
, sizeof ( inc_stream
) );
1232 FT_Stream_OpenMemory( &inc_stream
,
1233 glyph_data
.pointer
, glyph_data
.length
);
1235 loader
->stream
= &inc_stream
;
1239 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1241 offset
= tt_face_get_location( face
, glyph_index
,
1242 (FT_UInt
*)&loader
->byte_len
);
1244 if ( loader
->byte_len
> 0 )
1246 error
= face
->access_glyph_frame( loader
, glyph_index
,
1247 loader
->glyf_offset
+ offset
,
1254 /* read first glyph header */
1255 error
= face
->read_glyph_header( loader
);
1260 if ( loader
->byte_len
== 0 || loader
->n_contours
== 0 )
1262 loader
->bbox
.xMin
= 0;
1263 loader
->bbox
.xMax
= 0;
1264 loader
->bbox
.yMin
= 0;
1265 loader
->bbox
.yMax
= 0;
1267 TT_LOADER_SET_PP( loader
);
1269 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1271 if ( ((TT_Face
)(loader
->face
))->doblend
)
1273 /* this must be done before scaling */
1274 FT_Memory memory
= loader
->face
->memory
;
1277 error
= TT_Vary_Get_Glyph_Deltas( (TT_Face
)(loader
->face
),
1278 glyph_index
, &deltas
, 4 );
1282 loader
->pp1
.x
+= deltas
[0].x
; loader
->pp1
.y
+= deltas
[0].y
;
1283 loader
->pp2
.x
+= deltas
[1].x
; loader
->pp2
.y
+= deltas
[1].y
;
1284 loader
->pp3
.x
+= deltas
[2].x
; loader
->pp3
.y
+= deltas
[2].y
;
1285 loader
->pp4
.x
+= deltas
[3].x
; loader
->pp4
.y
+= deltas
[3].y
;
1292 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1294 loader
->pp1
.x
= FT_MulFix( loader
->pp1
.x
, x_scale
);
1295 loader
->pp2
.x
= FT_MulFix( loader
->pp2
.x
, x_scale
);
1296 loader
->pp3
.y
= FT_MulFix( loader
->pp3
.y
, y_scale
);
1297 loader
->pp4
.y
= FT_MulFix( loader
->pp4
.y
, y_scale
);
1304 TT_LOADER_SET_PP( loader
);
1306 /***********************************************************************/
1307 /***********************************************************************/
1308 /***********************************************************************/
1310 /* if it is a simple glyph, load it */
1312 if ( loader
->n_contours
> 0 )
1314 error
= face
->read_simple_glyph( loader
);
1318 /* all data have been read */
1319 face
->forget_glyph_frame( loader
);
1322 error
= TT_Process_Simple_Glyph( loader
);
1326 FT_GlyphLoader_Add( gloader
);
1329 /***********************************************************************/
1330 /***********************************************************************/
1331 /***********************************************************************/
1333 /* otherwise, load a composite! */
1334 else if ( loader
->n_contours
== -1 )
1336 FT_UInt start_point
;
1337 FT_UInt start_contour
;
1338 FT_ULong ins_pos
; /* position of composite instructions, if any */
1341 start_point
= gloader
->base
.outline
.n_points
;
1342 start_contour
= gloader
->base
.outline
.n_contours
;
1344 /* for each subglyph, read composite header */
1345 error
= face
->read_composite_glyph( loader
);
1349 /* store the offset of instructions */
1350 ins_pos
= loader
->ins_pos
;
1352 /* all data we need are read */
1353 face
->forget_glyph_frame( loader
);
1356 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1358 if ( face
->doblend
)
1361 FT_SubGlyph subglyph
;
1362 FT_Memory memory
= face
->root
.memory
;
1365 /* this provides additional offsets */
1366 /* for each component's translation */
1368 if ( ( error
= TT_Vary_Get_Glyph_Deltas(
1372 gloader
->current
.num_subglyphs
+ 4 )) != 0 )
1375 subglyph
= gloader
->current
.subglyphs
+ gloader
->base
.num_subglyphs
;
1376 limit
= gloader
->current
.num_subglyphs
;
1378 for ( i
= 0; i
< limit
; ++i
, ++subglyph
)
1380 if ( subglyph
->flags
& ARGS_ARE_XY_VALUES
)
1382 subglyph
->arg1
+= deltas
[i
].x
;
1383 subglyph
->arg2
+= deltas
[i
].y
;
1387 loader
->pp1
.x
+= deltas
[i
+ 0].x
; loader
->pp1
.y
+= deltas
[i
+ 0].y
;
1388 loader
->pp2
.x
+= deltas
[i
+ 1].x
; loader
->pp2
.y
+= deltas
[i
+ 1].y
;
1389 loader
->pp3
.x
+= deltas
[i
+ 2].x
; loader
->pp3
.y
+= deltas
[i
+ 2].y
;
1390 loader
->pp4
.x
+= deltas
[i
+ 3].x
; loader
->pp4
.y
+= deltas
[i
+ 3].y
;
1395 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1397 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1399 loader
->pp1
.x
= FT_MulFix( loader
->pp1
.x
, x_scale
);
1400 loader
->pp2
.x
= FT_MulFix( loader
->pp2
.x
, x_scale
);
1401 loader
->pp3
.y
= FT_MulFix( loader
->pp3
.y
, y_scale
);
1402 loader
->pp4
.y
= FT_MulFix( loader
->pp4
.y
, y_scale
);
1405 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
1406 /* `as is' in the glyph slot (the client application will be */
1407 /* responsible for interpreting these data)... */
1408 if ( loader
->load_flags
& FT_LOAD_NO_RECURSE
)
1410 FT_GlyphLoader_Add( gloader
);
1411 loader
->glyph
->format
= FT_GLYPH_FORMAT_COMPOSITE
;
1416 /*********************************************************************/
1417 /*********************************************************************/
1418 /*********************************************************************/
1421 FT_UInt n
, num_base_points
;
1422 FT_SubGlyph subglyph
= 0;
1424 FT_UInt num_points
= start_point
;
1425 FT_UInt num_subglyphs
= gloader
->current
.num_subglyphs
;
1426 FT_UInt num_base_subgs
= gloader
->base
.num_subglyphs
;
1428 FT_Stream old_stream
= loader
->stream
;
1431 FT_GlyphLoader_Add( gloader
);
1433 /* read each subglyph independently */
1434 for ( n
= 0; n
< num_subglyphs
; n
++ )
1439 /* Each time we call load_truetype_glyph in this loop, the */
1440 /* value of `gloader.base.subglyphs' can change due to table */
1441 /* reallocations. We thus need to recompute the subglyph */
1442 /* pointer on each iteration. */
1443 subglyph
= gloader
->base
.subglyphs
+ num_base_subgs
+ n
;
1445 pp
[0] = loader
->pp1
;
1446 pp
[1] = loader
->pp2
;
1447 pp
[2] = loader
->pp3
;
1448 pp
[3] = loader
->pp4
;
1450 num_base_points
= gloader
->base
.outline
.n_points
;
1452 error
= load_truetype_glyph( loader
, subglyph
->index
,
1453 recurse_count
+ 1 );
1457 /* restore subglyph pointer */
1458 subglyph
= gloader
->base
.subglyphs
+ num_base_subgs
+ n
;
1460 if ( !( subglyph
->flags
& USE_MY_METRICS
) )
1462 loader
->pp1
= pp
[0];
1463 loader
->pp2
= pp
[1];
1464 loader
->pp3
= pp
[2];
1465 loader
->pp4
= pp
[3];
1468 num_points
= gloader
->base
.outline
.n_points
;
1470 if ( num_points
== num_base_points
)
1473 /* gloader->base.outline consists of three parts: */
1474 /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
1476 /* (1): exists from the beginning */
1477 /* (2): components that have been loaded so far */
1478 /* (3): the newly loaded component */
1479 TT_Process_Composite_Component( loader
, subglyph
, start_point
,
1483 loader
->stream
= old_stream
;
1485 /* process the glyph */
1486 loader
->ins_pos
= ins_pos
;
1487 if ( IS_HINTED( loader
->load_flags
) &&
1489 #ifdef TT_USE_BYTECODE_INTERPRETER
1491 subglyph
->flags
& WE_HAVE_INSTR
&&
1495 num_points
> start_point
)
1496 TT_Process_Composite_Glyph( loader
, start_point
, start_contour
);
1502 /* invalid composite count (negative but not -1) */
1503 error
= TT_Err_Invalid_Outline
;
1507 /***********************************************************************/
1508 /***********************************************************************/
1509 /***********************************************************************/
1514 face
->forget_glyph_frame( loader
);
1516 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1518 if ( glyph_data_loaded
)
1519 face
->root
.internal
->incremental_interface
->funcs
->free_glyph_data(
1520 face
->root
.internal
->incremental_interface
->object
,
1530 compute_glyph_metrics( TT_Loader loader
,
1531 FT_UInt glyph_index
)
1534 TT_Face face
= (TT_Face
)loader
->face
;
1536 TT_GlyphSlot glyph
= loader
->glyph
;
1537 TT_Size size
= (TT_Size
)loader
->size
;
1541 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1542 y_scale
= size
->root
.metrics
.y_scale
;
1544 if ( glyph
->format
!= FT_GLYPH_FORMAT_COMPOSITE
)
1545 FT_Outline_Get_CBox( &glyph
->outline
, &bbox
);
1547 bbox
= loader
->bbox
;
1549 /* get the device-independent horizontal advance; it is scaled later */
1550 /* by the base layer. */
1552 FT_Pos advance
= loader
->linear
;
1555 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1556 /* correctly support DynaLab fonts, which have an incorrect */
1557 /* `advance_Width_Max' field! It is used, to my knowledge, */
1558 /* exclusively in the X-TrueType font server. */
1560 if ( face
->postscript
.isFixedPitch
&&
1561 ( loader
->load_flags
& FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
) == 0 )
1562 advance
= face
->horizontal
.advance_Width_Max
;
1564 /* we need to return the advance in font units in linearHoriAdvance, */
1565 /* it will be scaled later by the base layer. */
1566 glyph
->linearHoriAdvance
= advance
;
1569 glyph
->metrics
.horiBearingX
= bbox
.xMin
;
1570 glyph
->metrics
.horiBearingY
= bbox
.yMax
;
1571 glyph
->metrics
.horiAdvance
= loader
->pp2
.x
- loader
->pp1
.x
;
1573 /* Now take care of vertical metrics. In the case where there is */
1574 /* no vertical information within the font (relatively common), make */
1575 /* up some metrics by `hand'... */
1578 FT_Pos top
; /* scaled vertical top side bearing */
1579 FT_Pos advance
; /* scaled vertical advance height */
1582 /* Get the unscaled top bearing and advance height. */
1583 if ( face
->vertical_info
&&
1584 face
->vertical
.number_Of_VMetrics
> 0 )
1586 top
= (FT_Short
)FT_DivFix( loader
->pp3
.y
- bbox
.yMax
,
1589 if ( loader
->pp3
.y
<= loader
->pp4
.y
)
1592 advance
= (FT_UShort
)FT_DivFix( loader
->pp3
.y
- loader
->pp4
.y
,
1600 /* XXX Compute top side bearing and advance height in */
1601 /* Get_VMetrics instead of here. */
1603 /* NOTE: The OS/2 values are the only `portable' ones, */
1604 /* which is why we use them, if there is an OS/2 */
1605 /* table in the font. Otherwise, we use the */
1606 /* values defined in the horizontal header. */
1608 height
= (FT_Short
)FT_DivFix( bbox
.yMax
- bbox
.yMin
,
1610 if ( face
->os2
.version
!= 0xFFFFU
)
1611 advance
= (FT_Pos
)( face
->os2
.sTypoAscender
-
1612 face
->os2
.sTypoDescender
);
1614 advance
= (FT_Pos
)( face
->horizontal
.Ascender
-
1615 face
->horizontal
.Descender
);
1617 top
= ( advance
- height
) / 2;
1620 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1622 FT_Incremental_InterfaceRec
* incr
;
1623 FT_Incremental_MetricsRec metrics
;
1627 incr
= face
->root
.internal
->incremental_interface
;
1629 /* If this is an incrementally loaded font see if there are */
1630 /* overriding metrics for this glyph. */
1631 if ( incr
&& incr
->funcs
->get_glyph_metrics
)
1633 metrics
.bearing_x
= 0;
1634 metrics
.bearing_y
= top
;
1635 metrics
.advance
= advance
;
1637 error
= incr
->funcs
->get_glyph_metrics( incr
->object
,
1644 top
= metrics
.bearing_y
;
1645 advance
= metrics
.advance
;
1649 /* GWW: Do vertical metrics get loaded incrementally too? */
1651 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1653 glyph
->linearVertAdvance
= advance
;
1655 /* scale the metrics */
1656 if ( !( loader
->load_flags
& FT_LOAD_NO_SCALE
) )
1658 top
= FT_MulFix( top
, y_scale
);
1659 advance
= FT_MulFix( advance
, y_scale
);
1662 /* XXX: for now, we have no better algorithm for the lsb, but it */
1663 /* should work fine. */
1665 glyph
->metrics
.vertBearingX
= ( bbox
.xMin
- bbox
.xMax
) / 2;
1666 glyph
->metrics
.vertBearingY
= top
;
1667 glyph
->metrics
.vertAdvance
= advance
;
1670 /* adjust advance width to the value contained in the hdmx table */
1671 if ( !face
->postscript
.isFixedPitch
&&
1672 IS_HINTED( loader
->load_flags
) )
1677 widthp
= tt_face_get_device_metrics( face
,
1678 size
->root
.metrics
.x_ppem
,
1682 glyph
->metrics
.horiAdvance
= *widthp
<< 6;
1685 /* set glyph dimensions */
1686 glyph
->metrics
.width
= bbox
.xMax
- bbox
.xMin
;
1687 glyph
->metrics
.height
= bbox
.yMax
- bbox
.yMin
;
1693 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1696 load_sbit_image( TT_Size size
,
1698 FT_UInt glyph_index
,
1699 FT_Int32 load_flags
)
1705 TT_SBit_MetricsRec metrics
;
1708 face
= (TT_Face
)glyph
->face
;
1709 sfnt
= (SFNT_Service
)face
->sfnt
;
1710 stream
= face
->root
.stream
;
1712 error
= sfnt
->load_sbit_image( face
,
1721 glyph
->outline
.n_points
= 0;
1722 glyph
->outline
.n_contours
= 0;
1724 glyph
->metrics
.width
= (FT_Pos
)metrics
.width
<< 6;
1725 glyph
->metrics
.height
= (FT_Pos
)metrics
.height
<< 6;
1727 glyph
->metrics
.horiBearingX
= (FT_Pos
)metrics
.horiBearingX
<< 6;
1728 glyph
->metrics
.horiBearingY
= (FT_Pos
)metrics
.horiBearingY
<< 6;
1729 glyph
->metrics
.horiAdvance
= (FT_Pos
)metrics
.horiAdvance
<< 6;
1731 glyph
->metrics
.vertBearingX
= (FT_Pos
)metrics
.vertBearingX
<< 6;
1732 glyph
->metrics
.vertBearingY
= (FT_Pos
)metrics
.vertBearingY
<< 6;
1733 glyph
->metrics
.vertAdvance
= (FT_Pos
)metrics
.vertAdvance
<< 6;
1735 glyph
->format
= FT_GLYPH_FORMAT_BITMAP
;
1736 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
1738 glyph
->bitmap_left
= metrics
.vertBearingX
;
1739 glyph
->bitmap_top
= metrics
.vertBearingY
;
1743 glyph
->bitmap_left
= metrics
.horiBearingX
;
1744 glyph
->bitmap_top
= metrics
.horiBearingY
;
1751 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1755 tt_loader_init( TT_Loader loader
,
1758 FT_Int32 load_flags
)
1764 face
= (TT_Face
)glyph
->face
;
1765 stream
= face
->root
.stream
;
1767 FT_MEM_ZERO( loader
, sizeof ( TT_LoaderRec
) );
1769 #ifdef TT_USE_BYTECODE_INTERPRETER
1771 /* load execution context */
1772 if ( IS_HINTED( load_flags
) )
1774 TT_ExecContext exec
;
1778 if ( !size
->cvt_ready
)
1780 FT_Error error
= tt_size_ready_bytecode( size
);
1785 /* query new execution context */
1786 exec
= size
->debug
? size
->context
1787 : ( (TT_Driver
)FT_FACE_DRIVER( face
) )->context
;
1789 return TT_Err_Could_Not_Find_Context
;
1792 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags
) != FT_RENDER_MODE_MONO
);
1794 TT_Load_Context( exec
, face
, size
);
1796 /* a change from mono to grayscale rendering (and vice versa) */
1797 /* requires a re-execution of the CVT program */
1798 if ( grayscale
!= exec
->grayscale
)
1803 exec
->grayscale
= grayscale
;
1805 for ( i
= 0; i
< size
->cvt_size
; i
++ )
1806 size
->cvt
[i
] = FT_MulFix( face
->cvt
[i
], size
->ttmetrics
.scale
);
1807 tt_size_run_prep( size
);
1810 /* see whether the cvt program has disabled hinting */
1811 if ( exec
->GS
.instruct_control
& 1 )
1812 load_flags
|= FT_LOAD_NO_HINTING
;
1814 /* load default graphics state -- if needed */
1815 if ( exec
->GS
.instruct_control
& 2 )
1816 exec
->GS
= tt_default_graphics_state
;
1818 exec
->pedantic_hinting
= FT_BOOL( load_flags
& FT_LOAD_PEDANTIC
);
1819 loader
->exec
= exec
;
1820 loader
->instructions
= exec
->glyphIns
;
1823 #endif /* TT_USE_BYTECODE_INTERPRETER */
1825 /* seek to the beginning of the glyph table -- for Type 42 fonts */
1826 /* the table might be accessed from a Postscript stream or something */
1829 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1831 if ( face
->root
.internal
->incremental_interface
)
1832 loader
->glyf_offset
= 0;
1838 FT_Error error
= face
->goto_table( face
, TTAG_glyf
, stream
, 0 );
1843 FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
1846 loader
->glyf_offset
= FT_STREAM_POS();
1849 /* get face's glyph loader */
1851 FT_GlyphLoader gloader
= glyph
->internal
->loader
;
1854 FT_GlyphLoader_Rewind( gloader
);
1855 loader
->gloader
= gloader
;
1858 loader
->load_flags
= load_flags
;
1860 loader
->face
= (FT_Face
)face
;
1861 loader
->size
= (FT_Size
)size
;
1862 loader
->glyph
= (FT_GlyphSlot
)glyph
;
1863 loader
->stream
= stream
;
1869 /*************************************************************************/
1875 /* A function used to load a single glyph within a given glyph slot, */
1876 /* for a given size. */
1879 /* glyph :: A handle to a target slot object where the glyph */
1880 /* will be loaded. */
1882 /* size :: A handle to the source face size at which the glyph */
1883 /* must be scaled/loaded. */
1885 /* glyph_index :: The index of the glyph in the font file. */
1887 /* load_flags :: A flag indicating what to load for this glyph. The */
1888 /* FT_LOAD_XXX constants can be used to control the */
1889 /* glyph loading process (e.g., whether the outline */
1890 /* should be scaled, whether to load bitmaps or not, */
1891 /* whether to hint the outline, etc). */
1894 /* FreeType error code. 0 means success. */
1896 FT_LOCAL_DEF( FT_Error
)
1897 TT_Load_Glyph( TT_Size size
,
1899 FT_UInt glyph_index
,
1900 FT_Int32 load_flags
)
1904 TT_LoaderRec loader
;
1907 face
= (TT_Face
)glyph
->face
;
1910 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1912 /* try to load embedded bitmap if any */
1914 /* XXX: The convention should be emphasized in */
1915 /* the documents because it can be confusing. */
1916 if ( size
->strike_index
!= 0xFFFFFFFFUL
&&
1917 ( load_flags
& FT_LOAD_NO_BITMAP
) == 0 )
1919 error
= load_sbit_image( size
, glyph
, glyph_index
, load_flags
);
1924 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1926 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
1927 if ( !( load_flags
& FT_LOAD_NO_SCALE
) && !size
->ttmetrics
.valid
)
1928 return TT_Err_Invalid_Size_Handle
;
1930 if ( load_flags
& FT_LOAD_SBITS_ONLY
)
1931 return TT_Err_Invalid_Argument
;
1933 error
= tt_loader_init( &loader
, size
, glyph
, load_flags
);
1937 glyph
->format
= FT_GLYPH_FORMAT_OUTLINE
;
1938 glyph
->num_subglyphs
= 0;
1939 glyph
->outline
.flags
= 0;
1941 /* main loading loop */
1942 error
= load_truetype_glyph( &loader
, glyph_index
, 0 );
1945 if ( glyph
->format
== FT_GLYPH_FORMAT_COMPOSITE
)
1947 glyph
->num_subglyphs
= loader
.gloader
->base
.num_subglyphs
;
1948 glyph
->subglyphs
= loader
.gloader
->base
.subglyphs
;
1952 glyph
->outline
= loader
.gloader
->base
.outline
;
1953 glyph
->outline
.flags
&= ~FT_OUTLINE_SINGLE_PASS
;
1955 /* In case bit 1 of the `flags' field in the `head' table isn't */
1956 /* set, translate array so that (0,0) is the glyph's origin. */
1957 if ( ( face
->header
.Flags
& 2 ) == 0 && loader
.pp1
.x
)
1958 FT_Outline_Translate( &glyph
->outline
, -loader
.pp1
.x
, 0 );
1961 #ifdef TT_USE_BYTECODE_INTERPRETER
1963 if ( IS_HINTED( load_flags
) )
1965 if ( loader
.exec
->GS
.scan_control
)
1967 /* convert scan conversion mode to FT_OUTLINE_XXX flags */
1968 switch ( loader
.exec
->GS
.scan_type
)
1970 case 0: /* simple drop-outs including stubs */
1971 glyph
->outline
.flags
|= FT_OUTLINE_INCLUDE_STUBS
;
1973 case 1: /* simple drop-outs excluding stubs */
1974 /* nothing; it's the default rendering mode */
1976 case 4: /* smart drop-outs including stubs */
1977 glyph
->outline
.flags
|= FT_OUTLINE_SMART_DROPOUTS
|
1978 FT_OUTLINE_INCLUDE_STUBS
;
1980 case 5: /* smart drop-outs excluding stubs */
1981 glyph
->outline
.flags
|= FT_OUTLINE_SMART_DROPOUTS
;
1984 default: /* no drop-out control */
1985 glyph
->outline
.flags
|= FT_OUTLINE_IGNORE_DROPOUTS
;
1990 glyph
->outline
.flags
|= FT_OUTLINE_IGNORE_DROPOUTS
;
1993 #endif /* TT_USE_BYTECODE_INTERPRETER */
1995 compute_glyph_metrics( &loader
, glyph_index
);
1998 /* Set the `high precision' bit flag. */
1999 /* This is _critical_ to get correct output for monochrome */
2000 /* TrueType glyphs at all sizes using the bytecode interpreter. */
2002 if ( !( load_flags
& FT_LOAD_NO_SCALE
) &&
2003 size
->root
.metrics
.y_ppem
< 24 )
2004 glyph
->outline
.flags
|= FT_OUTLINE_HIGH_PRECISION
;