1 /***************************************************************************/
5 /* TrueType Glyph Loader (body). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
11 /* This file is part of the FreeType project, and may only be used, */
12 /* modified, and distributed under the terms of the FreeType project */
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
14 /* this file you indicate that you have read the license and */
15 /* understand and accept it fully. */
17 /***************************************************************************/
21 #include FT_INTERNAL_DEBUG_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
31 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
38 /*************************************************************************/
40 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
41 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
42 /* messages during execution. */
45 #define FT_COMPONENT trace_ttgload
48 /*************************************************************************/
50 /* Composite font flags. */
52 #define ARGS_ARE_WORDS 0x0001
53 #define ARGS_ARE_XY_VALUES 0x0002
54 #define ROUND_XY_TO_GRID 0x0004
55 #define WE_HAVE_A_SCALE 0x0008
57 #define MORE_COMPONENTS 0x0020
58 #define WE_HAVE_AN_XY_SCALE 0x0040
59 #define WE_HAVE_A_2X2 0x0080
60 #define WE_HAVE_INSTR 0x0100
61 #define USE_MY_METRICS 0x0200
62 #define OVERLAP_COMPOUND 0x0400
63 #define SCALED_COMPONENT_OFFSET 0x0800
64 #define UNSCALED_COMPONENT_OFFSET 0x1000
67 /*************************************************************************/
69 /* Returns the horizontal metrics in font units for a given glyph. If */
70 /* `check' is true, take care of monospaced fonts by returning the */
71 /* advance width maximum. */
74 TT_Get_HMetrics( TT_Face face
,
80 ( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 0, idx
, lsb
, aw
);
82 if ( check
&& face
->postscript
.isFixedPitch
)
83 *aw
= face
->horizontal
.advance_Width_Max
;
85 FT_TRACE5(( " advance width (font units): %d\n", *aw
));
86 FT_TRACE5(( " left side bearing (font units): %d\n", *lsb
));
90 /*************************************************************************/
92 /* Returns the vertical metrics in font units for a given glyph. */
93 /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
94 /* table, typoAscender/Descender from the `OS/2' table would be used */
95 /* instead, and if there were no `OS/2' table, use ascender/descender */
96 /* from the `hhea' table. But that is not what Microsoft's rasterizer */
97 /* apparently does: It uses the ppem value as the advance height, and */
98 /* sets the top side bearing to be zero. */
100 /* The monospace `check' is probably not meaningful here, but we leave */
101 /* it in for a consistent interface. */
104 TT_Get_VMetrics( TT_Face face
,
112 if ( face
->vertical_info
)
113 ( (SFNT_Service
)face
->sfnt
)->get_metrics( face
, 1, idx
, tsb
, ah
);
115 #if 1 /* Empirically determined, at variance with what MS said */
120 *ah
= face
->root
.units_per_EM
;
123 #else /* This is what MS said to do. It isn't what they do, however. */
125 else if ( face
->os2
.version
!= 0xFFFFU
)
127 *tsb
= face
->os2
.sTypoAscender
;
128 *ah
= face
->os2
.sTypoAscender
- face
->os2
.sTypoDescender
;
132 *tsb
= face
->horizontal
.Ascender
;
133 *ah
= face
->horizontal
.Ascender
- face
->horizontal
.Descender
;
138 FT_TRACE5(( " advance height (font units): %d\n", *ah
));
139 FT_TRACE5(( " top side bearing (font units): %d\n", *tsb
));
144 tt_get_metrics( TT_Loader loader
,
145 FT_UInt glyph_index
)
147 TT_Face face
= (TT_Face
)loader
->face
;
149 FT_Short left_bearing
= 0, top_bearing
= 0;
150 FT_UShort advance_width
= 0, advance_height
= 0;
153 TT_Get_HMetrics( face
, glyph_index
,
154 (FT_Bool
)!( loader
->load_flags
&
155 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
),
158 TT_Get_VMetrics( face
, glyph_index
,
159 (FT_Bool
)!( loader
->load_flags
&
160 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
),
164 #ifdef FT_CONFIG_OPTION_INCREMENTAL
166 /* If this is an incrementally loaded font check whether there are */
167 /* overriding metrics for this glyph. */
168 if ( face
->root
.internal
->incremental_interface
&&
169 face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics
)
171 FT_Incremental_MetricsRec metrics
;
175 metrics
.bearing_x
= left_bearing
;
176 metrics
.bearing_y
= 0;
177 metrics
.advance
= advance_width
;
178 metrics
.advance_v
= 0;
180 error
= face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics(
181 face
->root
.internal
->incremental_interface
->object
,
182 glyph_index
, FALSE
, &metrics
);
186 left_bearing
= (FT_Short
)metrics
.bearing_x
;
187 advance_width
= (FT_UShort
)metrics
.advance
;
191 /* GWW: Do I do the same for vertical metrics? */
192 metrics
.bearing_x
= 0;
193 metrics
.bearing_y
= top_bearing
;
194 metrics
.advance
= advance_height
;
196 error
= face
->root
.internal
->incremental_interface
->funcs
->get_glyph_metrics(
197 face
->root
.internal
->incremental_interface
->object
,
198 glyph_index
, TRUE
, &metrics
);
202 top_bearing
= (FT_Short
)metrics
.bearing_y
;
203 advance_height
= (FT_UShort
)metrics
.advance
;
211 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
213 loader
->left_bearing
= left_bearing
;
214 loader
->advance
= advance_width
;
215 loader
->top_bearing
= top_bearing
;
216 loader
->vadvance
= advance_height
;
218 if ( !loader
->linear_def
)
220 loader
->linear_def
= 1;
221 loader
->linear
= advance_width
;
226 /*************************************************************************/
228 /* Translates an array of coordinates. */
231 translate_array( FT_UInt n
,
240 for ( k
= 0; k
< n
; k
++ )
241 coords
[k
].x
+= delta_x
;
244 for ( k
= 0; k
< n
; k
++ )
245 coords
[k
].y
+= delta_y
;
250 #define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
253 /*************************************************************************/
255 /* The following functions are used by default with TrueType fonts. */
256 /* However, they can be replaced by alternatives if we need to support */
257 /* TrueType-compressed formats (like MicroType) in the future. */
259 /*************************************************************************/
261 FT_CALLBACK_DEF( FT_Error
)
262 TT_Access_Glyph_Frame( TT_Loader loader
,
268 FT_Stream stream
= loader
->stream
;
270 /* for non-debug mode */
271 FT_UNUSED( glyph_index
);
274 FT_TRACE5(( "Glyph %ld\n", glyph_index
));
276 /* the following line sets the `error' variable through macros! */
277 if ( FT_STREAM_SEEK( offset
) || FT_FRAME_ENTER( byte_count
) )
280 loader
->cursor
= stream
->cursor
;
281 loader
->limit
= stream
->limit
;
287 FT_CALLBACK_DEF( void )
288 TT_Forget_Glyph_Frame( TT_Loader loader
)
290 FT_Stream stream
= loader
->stream
;
297 FT_CALLBACK_DEF( FT_Error
)
298 TT_Load_Glyph_Header( TT_Loader loader
)
300 FT_Byte
* p
= loader
->cursor
;
301 FT_Byte
* limit
= loader
->limit
;
304 if ( p
+ 10 > limit
)
305 return TT_Err_Invalid_Outline
;
307 loader
->n_contours
= FT_NEXT_SHORT( p
);
309 loader
->bbox
.xMin
= FT_NEXT_SHORT( p
);
310 loader
->bbox
.yMin
= FT_NEXT_SHORT( p
);
311 loader
->bbox
.xMax
= FT_NEXT_SHORT( p
);
312 loader
->bbox
.yMax
= FT_NEXT_SHORT( p
);
314 FT_TRACE5(( " # of contours: %d\n", loader
->n_contours
));
315 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader
->bbox
.xMin
,
316 loader
->bbox
.xMax
));
317 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader
->bbox
.yMin
,
318 loader
->bbox
.yMax
));
325 FT_CALLBACK_DEF( FT_Error
)
326 TT_Load_Simple_Glyph( TT_Loader load
)
329 FT_Byte
* p
= load
->cursor
;
330 FT_Byte
* limit
= load
->limit
;
331 FT_GlyphLoader gloader
= load
->gloader
;
332 FT_Int n_contours
= load
->n_contours
;
334 TT_Face face
= (TT_Face
)load
->face
;
338 FT_Byte
*flag
, *flag_limit
;
340 FT_Vector
*vec
, *vec_limit
;
342 FT_Short
*cont
, *cont_limit
, prev_cont
;
346 /* check that we can add the contours to the glyph */
347 error
= FT_GLYPHLOADER_CHECK_POINTS( gloader
, 0, n_contours
);
351 /* reading the contours' endpoints & number of points */
352 cont
= gloader
->current
.outline
.contours
;
353 cont_limit
= cont
+ n_contours
;
355 /* check space for contours array + instructions count */
356 if ( n_contours
>= 0xFFF || p
+ ( n_contours
+ 1 ) * 2 > limit
)
357 goto Invalid_Outline
;
359 prev_cont
= FT_NEXT_USHORT( p
);
361 if ( n_contours
> 0 )
364 for ( cont
++; cont
< cont_limit
; cont
++ )
366 cont
[0] = FT_NEXT_USHORT( p
);
367 if ( cont
[0] <= prev_cont
)
369 /* unordered contours: this is invalid */
370 error
= FT_Err_Invalid_Table
;
377 if ( n_contours
> 0 )
379 n_points
= cont
[-1] + 1;
381 goto Invalid_Outline
;
384 /* note that we will add four phantom points later */
385 error
= FT_GLYPHLOADER_CHECK_POINTS( gloader
, n_points
+ 4, 0 );
389 /* we'd better check the contours table right now */
390 outline
= &gloader
->current
.outline
;
392 for ( cont
= outline
->contours
+ 1; cont
< cont_limit
; cont
++ )
393 if ( cont
[-1] >= cont
[0] )
394 goto Invalid_Outline
;
396 /* reading the bytecode instructions */
397 load
->glyph
->control_len
= 0;
398 load
->glyph
->control_data
= 0;
401 goto Invalid_Outline
;
403 n_ins
= FT_NEXT_USHORT( p
);
405 FT_TRACE5(( " Instructions size: %u\n", n_ins
));
407 if ( n_ins
> face
->max_profile
.maxSizeOfInstructions
)
409 FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",
411 error
= TT_Err_Too_Many_Hints
;
415 if ( ( limit
- p
) < n_ins
)
417 FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
418 error
= TT_Err_Too_Many_Hints
;
422 #ifdef TT_USE_BYTECODE_INTERPRETER
424 if ( IS_HINTED( load
->load_flags
) )
426 load
->glyph
->control_len
= n_ins
;
427 load
->glyph
->control_data
= load
->exec
->glyphIns
;
429 FT_MEM_COPY( load
->exec
->glyphIns
, p
, (FT_Long
)n_ins
);
432 #endif /* TT_USE_BYTECODE_INTERPRETER */
436 /* reading the point tags */
437 flag
= (FT_Byte
*)outline
->tags
;
438 flag_limit
= flag
+ n_points
;
440 FT_ASSERT( flag
!= NULL
);
442 while ( flag
< flag_limit
)
445 goto Invalid_Outline
;
447 *flag
++ = c
= FT_NEXT_BYTE( p
);
451 goto Invalid_Outline
;
453 count
= FT_NEXT_BYTE( p
);
454 if ( flag
+ (FT_Int
)count
> flag_limit
)
455 goto Invalid_Outline
;
457 for ( ; count
> 0; count
-- )
462 /* reading the X coordinates */
464 vec
= outline
->points
;
465 vec_limit
= vec
+ n_points
;
466 flag
= (FT_Byte
*)outline
->tags
;
469 if ( p
+ xy_size
> limit
)
470 goto Invalid_Outline
;
472 for ( ; vec
< vec_limit
; vec
++, flag
++ )
481 goto Invalid_Outline
;
483 y
= (FT_Pos
)FT_NEXT_BYTE( p
);
484 if ( ( f
& 16 ) == 0 )
487 else if ( ( f
& 16 ) == 0 )
490 goto Invalid_Outline
;
492 y
= (FT_Pos
)FT_NEXT_SHORT( p
);
497 /* the cast is for stupid compilers */
498 *flag
= (FT_Byte
)( f
& ~( 2 | 16 ) );
501 /* reading the Y coordinates */
503 vec
= gloader
->current
.outline
.points
;
504 vec_limit
= vec
+ n_points
;
505 flag
= (FT_Byte
*)outline
->tags
;
508 for ( ; vec
< vec_limit
; vec
++, flag
++ )
517 goto Invalid_Outline
;
519 y
= (FT_Pos
)FT_NEXT_BYTE( p
);
520 if ( ( f
& 32 ) == 0 )
523 else if ( ( f
& 32 ) == 0 )
526 goto Invalid_Outline
;
528 y
= (FT_Pos
)FT_NEXT_SHORT( p
);
533 /* the cast is for stupid compilers */
534 *flag
= (FT_Byte
)( f
& FT_CURVE_TAG_ON
);
537 outline
->n_points
= (FT_UShort
)n_points
;
538 outline
->n_contours
= (FT_Short
) n_contours
;
546 error
= TT_Err_Invalid_Outline
;
551 FT_CALLBACK_DEF( FT_Error
)
552 TT_Load_Composite_Glyph( TT_Loader loader
)
555 FT_Byte
* p
= loader
->cursor
;
556 FT_Byte
* limit
= loader
->limit
;
557 FT_GlyphLoader gloader
= loader
->gloader
;
558 FT_SubGlyph subglyph
;
559 FT_UInt num_subglyphs
;
566 FT_Fixed xx
, xy
, yy
, yx
;
570 /* check that we can load a new subglyph */
571 error
= FT_GlyphLoader_CheckSubGlyphs( gloader
, num_subglyphs
+ 1 );
577 goto Invalid_Composite
;
579 subglyph
= gloader
->current
.subglyphs
+ num_subglyphs
;
581 subglyph
->arg1
= subglyph
->arg2
= 0;
583 subglyph
->flags
= FT_NEXT_USHORT( p
);
584 subglyph
->index
= FT_NEXT_USHORT( p
);
588 if ( subglyph
->flags
& ARGS_ARE_WORDS
)
590 if ( subglyph
->flags
& WE_HAVE_A_SCALE
)
592 else if ( subglyph
->flags
& WE_HAVE_AN_XY_SCALE
)
594 else if ( subglyph
->flags
& WE_HAVE_A_2X2
)
597 if ( p
+ count
> limit
)
598 goto Invalid_Composite
;
601 if ( subglyph
->flags
& ARGS_ARE_WORDS
)
603 subglyph
->arg1
= FT_NEXT_SHORT( p
);
604 subglyph
->arg2
= FT_NEXT_SHORT( p
);
608 subglyph
->arg1
= FT_NEXT_CHAR( p
);
609 subglyph
->arg2
= FT_NEXT_CHAR( p
);
616 if ( subglyph
->flags
& WE_HAVE_A_SCALE
)
618 xx
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
621 else if ( subglyph
->flags
& WE_HAVE_AN_XY_SCALE
)
623 xx
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
624 yy
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
626 else if ( subglyph
->flags
& WE_HAVE_A_2X2
)
628 xx
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
629 yx
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
630 xy
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
631 yy
= (FT_Fixed
)FT_NEXT_SHORT( p
) << 2;
634 subglyph
->transform
.xx
= xx
;
635 subglyph
->transform
.xy
= xy
;
636 subglyph
->transform
.yx
= yx
;
637 subglyph
->transform
.yy
= yy
;
641 } while ( subglyph
->flags
& MORE_COMPONENTS
);
643 gloader
->current
.num_subglyphs
= num_subglyphs
;
645 #ifdef TT_USE_BYTECODE_INTERPRETER
648 FT_Stream stream
= loader
->stream
;
651 /* we must undo the FT_FRAME_ENTER in order to point */
652 /* to the composite instructions, if we find some. */
653 /* We will process them later. */
655 loader
->ins_pos
= (FT_ULong
)( FT_STREAM_POS() +
667 error
= TT_Err_Invalid_Composite
;
673 TT_Init_Glyph_Loading( TT_Face face
)
675 face
->access_glyph_frame
= TT_Access_Glyph_Frame
;
676 face
->read_glyph_header
= TT_Load_Glyph_Header
;
677 face
->read_simple_glyph
= TT_Load_Simple_Glyph
;
678 face
->read_composite_glyph
= TT_Load_Composite_Glyph
;
679 face
->forget_glyph_frame
= TT_Forget_Glyph_Frame
;
684 tt_prepare_zone( TT_GlyphZone zone
,
687 FT_UInt start_contour
)
689 zone
->n_points
= (FT_UShort
)( load
->outline
.n_points
- start_point
);
690 zone
->n_contours
= (FT_Short
) ( load
->outline
.n_contours
-
692 zone
->org
= load
->extra_points
+ start_point
;
693 zone
->cur
= load
->outline
.points
+ start_point
;
694 zone
->orus
= load
->extra_points2
+ start_point
;
695 zone
->tags
= (FT_Byte
*)load
->outline
.tags
+ start_point
;
696 zone
->contours
= (FT_UShort
*)load
->outline
.contours
+ start_contour
;
697 zone
->first_point
= (FT_UShort
)start_point
;
701 /*************************************************************************/
707 /* Hint the glyph using the zone prepared by the caller. Note that */
708 /* the zone is supposed to include four phantom points. */
711 TT_Hint_Glyph( TT_Loader loader
,
712 FT_Bool is_composite
)
714 TT_GlyphZone zone
= &loader
->zone
;
717 #ifdef TT_USE_BYTECODE_INTERPRETER
720 FT_UNUSED( is_composite
);
724 #ifdef TT_USE_BYTECODE_INTERPRETER
725 if ( loader
->glyph
->control_len
> 0xFFFFL
)
727 FT_TRACE1(( "TT_Hint_Glyph: too long instructions " ));
728 FT_TRACE1(( "(0x%lx byte) is truncated\n",
729 loader
->glyph
->control_len
));
731 n_ins
= (FT_UInt
)( loader
->glyph
->control_len
);
734 origin
= zone
->cur
[zone
->n_points
- 4].x
;
735 origin
= FT_PIX_ROUND( origin
) - origin
;
737 translate_array( zone
->n_points
, zone
->cur
, origin
, 0 );
739 #ifdef TT_USE_BYTECODE_INTERPRETER
740 /* save original point position in org */
742 FT_ARRAY_COPY( zone
->org
, zone
->cur
, zone
->n_points
);
744 /* Reset graphics state. */
745 loader
->exec
->GS
= ((TT_Size
)loader
->size
)->GS
;
747 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
748 /* completely refer to the (already) hinted subglyphs. */
751 loader
->exec
->metrics
.x_scale
= 1 << 16;
752 loader
->exec
->metrics
.y_scale
= 1 << 16;
754 FT_ARRAY_COPY( zone
->orus
, zone
->cur
, zone
->n_points
);
758 loader
->exec
->metrics
.x_scale
=
759 ((TT_Size
)loader
->size
)->metrics
.x_scale
;
760 loader
->exec
->metrics
.y_scale
=
761 ((TT_Size
)loader
->size
)->metrics
.y_scale
;
765 /* round pp2 and pp4 */
766 zone
->cur
[zone
->n_points
- 3].x
=
767 FT_PIX_ROUND( zone
->cur
[zone
->n_points
- 3].x
);
768 zone
->cur
[zone
->n_points
- 1].y
=
769 FT_PIX_ROUND( zone
->cur
[zone
->n_points
- 1].y
);
771 #ifdef TT_USE_BYTECODE_INTERPRETER
778 FT_GlyphLoader gloader
= loader
->gloader
;
779 FT_Outline current_outline
= gloader
->current
.outline
;
782 error
= TT_Set_CodeRange( loader
->exec
, tt_coderange_glyph
,
783 loader
->exec
->glyphIns
, n_ins
);
787 loader
->exec
->is_composite
= is_composite
;
788 loader
->exec
->pts
= *zone
;
790 debug
= FT_BOOL( !( loader
->load_flags
& FT_LOAD_NO_SCALE
) &&
791 ((TT_Size
)loader
->size
)->debug
);
793 error
= TT_Run_Context( loader
->exec
, debug
);
794 if ( error
&& loader
->exec
->pedantic_hinting
)
797 /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
798 current_outline
.tags
[0] |=
799 ( loader
->exec
->GS
.scan_type
<< 5 ) | FT_CURVE_TAG_HAS_SCANMODE
;
804 /* save glyph phantom points */
805 if ( !loader
->preserve_pps
)
807 loader
->pp1
= zone
->cur
[zone
->n_points
- 4];
808 loader
->pp2
= zone
->cur
[zone
->n_points
- 3];
809 loader
->pp3
= zone
->cur
[zone
->n_points
- 2];
810 loader
->pp4
= zone
->cur
[zone
->n_points
- 1];
817 /*************************************************************************/
820 /* TT_Process_Simple_Glyph */
823 /* Once a simple glyph has been loaded, it needs to be processed. */
824 /* Usually, this means scaling and hinting through bytecode */
825 /* interpretation. */
828 TT_Process_Simple_Glyph( TT_Loader loader
)
830 FT_GlyphLoader gloader
= loader
->gloader
;
831 FT_Error error
= TT_Err_Ok
;
836 outline
= &gloader
->current
.outline
;
837 n_points
= outline
->n_points
;
839 /* set phantom points */
841 outline
->points
[n_points
] = loader
->pp1
;
842 outline
->points
[n_points
+ 1] = loader
->pp2
;
843 outline
->points
[n_points
+ 2] = loader
->pp3
;
844 outline
->points
[n_points
+ 3] = loader
->pp4
;
846 outline
->tags
[n_points
] = 0;
847 outline
->tags
[n_points
+ 1] = 0;
848 outline
->tags
[n_points
+ 2] = 0;
849 outline
->tags
[n_points
+ 3] = 0;
853 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
855 if ( ((TT_Face
)loader
->face
)->doblend
)
857 /* Deltas apply to the unscaled data. */
859 FT_Memory memory
= loader
->face
->memory
;
863 error
= TT_Vary_Get_Glyph_Deltas( (TT_Face
)(loader
->face
),
870 for ( i
= 0; i
< n_points
; ++i
)
872 outline
->points
[i
].x
+= deltas
[i
].x
;
873 outline
->points
[i
].y
+= deltas
[i
].y
;
879 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
881 if ( IS_HINTED( loader
->load_flags
) )
883 tt_prepare_zone( &loader
->zone
, &gloader
->current
, 0, 0 );
885 FT_ARRAY_COPY( loader
->zone
.orus
, loader
->zone
.cur
,
886 loader
->zone
.n_points
+ 4 );
889 /* scale the glyph */
890 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
892 FT_Vector
* vec
= outline
->points
;
893 FT_Vector
* limit
= outline
->points
+ n_points
;
894 FT_Fixed x_scale
= ((TT_Size
)loader
->size
)->metrics
.x_scale
;
895 FT_Fixed y_scale
= ((TT_Size
)loader
->size
)->metrics
.y_scale
;
898 for ( ; vec
< limit
; vec
++ )
900 vec
->x
= FT_MulFix( vec
->x
, x_scale
);
901 vec
->y
= FT_MulFix( vec
->y
, y_scale
);
904 loader
->pp1
= outline
->points
[n_points
- 4];
905 loader
->pp2
= outline
->points
[n_points
- 3];
906 loader
->pp3
= outline
->points
[n_points
- 2];
907 loader
->pp4
= outline
->points
[n_points
- 1];
910 if ( IS_HINTED( loader
->load_flags
) )
912 loader
->zone
.n_points
+= 4;
914 error
= TT_Hint_Glyph( loader
, 0 );
921 /*************************************************************************/
924 /* TT_Process_Composite_Component */
927 /* Once a composite component has been loaded, it needs to be */
928 /* processed. Usually, this means transforming and translating. */
931 TT_Process_Composite_Component( TT_Loader loader
,
932 FT_SubGlyph subglyph
,
934 FT_UInt num_base_points
)
936 FT_GlyphLoader gloader
= loader
->gloader
;
937 FT_Vector
* base_vec
= gloader
->base
.outline
.points
;
938 FT_UInt num_points
= gloader
->base
.outline
.n_points
;
943 have_scale
= FT_BOOL( subglyph
->flags
& ( WE_HAVE_A_SCALE
|
944 WE_HAVE_AN_XY_SCALE
|
947 /* perform the transform required for this subglyph */
953 for ( i
= num_base_points
; i
< num_points
; i
++ )
954 FT_Vector_Transform( base_vec
+ i
, &subglyph
->transform
);
958 if ( !( subglyph
->flags
& ARGS_ARE_XY_VALUES
) )
960 FT_UInt k
= subglyph
->arg1
;
961 FT_UInt l
= subglyph
->arg2
;
966 /* match l-th point of the newly loaded component to the k-th point */
967 /* of the previously loaded components. */
969 /* change to the point numbers used by our outline */
971 l
+= num_base_points
;
972 if ( k
>= num_base_points
||
974 return TT_Err_Invalid_Composite
;
976 p1
= gloader
->base
.outline
.points
+ k
;
977 p2
= gloader
->base
.outline
.points
+ l
;
990 /* Use a default value dependent on */
991 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */
992 /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */
995 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
996 !( subglyph
->flags
& UNSCALED_COMPONENT_OFFSET
) )
998 ( subglyph
->flags
& SCALED_COMPONENT_OFFSET
) )
1004 /*************************************************************************/
1006 /* This algorithm is what Apple documents. But it doesn't work. */
1008 int a
= subglyph
->transform
.xx
> 0 ? subglyph
->transform
.xx
1009 : -subglyph
->transform
.xx
;
1010 int b
= subglyph
->transform
.yx
> 0 ? subglyph
->transform
.yx
1011 : -subglyph
->transform
.yx
;
1012 int c
= subglyph
->transform
.xy
> 0 ? subglyph
->transform
.xy
1013 : -subglyph
->transform
.xy
;
1014 int d
= subglyph
->transform
.yy
> 0 ? subglyph
->transform
.yy
1015 : -subglyph
->transform
.yy
;
1016 int m
= a
> b
? a
: b
;
1017 int n
= c
> d
? c
: d
;
1020 if ( a
- b
<= 33 && a
- b
>= -33 )
1022 if ( c
- d
<= 33 && c
- d
>= -33 )
1024 x
= FT_MulFix( x
, m
);
1025 y
= FT_MulFix( y
, n
);
1029 /*************************************************************************/
1031 /* This algorithm is a guess and works much better than the above. */
1033 FT_Fixed mac_xscale
= FT_SqrtFixed(
1034 (FT_Int32
)FT_MulFix( subglyph
->transform
.xx
,
1035 subglyph
->transform
.xx
) +
1036 (FT_Int32
)FT_MulFix( subglyph
->transform
.xy
,
1037 subglyph
->transform
.xy
) );
1038 FT_Fixed mac_yscale
= FT_SqrtFixed(
1039 (FT_Int32
)FT_MulFix( subglyph
->transform
.yy
,
1040 subglyph
->transform
.yy
) +
1041 (FT_Int32
)FT_MulFix( subglyph
->transform
.yx
,
1042 subglyph
->transform
.yx
) );
1045 x
= FT_MulFix( x
, mac_xscale
);
1046 y
= FT_MulFix( y
, mac_yscale
);
1052 if ( !( loader
->load_flags
& FT_LOAD_NO_SCALE
) )
1054 FT_Fixed x_scale
= ((TT_Size
)loader
->size
)->metrics
.x_scale
;
1055 FT_Fixed y_scale
= ((TT_Size
)loader
->size
)->metrics
.y_scale
;
1058 x
= FT_MulFix( x
, x_scale
);
1059 y
= FT_MulFix( y
, y_scale
);
1061 if ( subglyph
->flags
& ROUND_XY_TO_GRID
)
1063 x
= FT_PIX_ROUND( x
);
1064 y
= FT_PIX_ROUND( y
);
1070 translate_array( num_points
- num_base_points
,
1071 base_vec
+ num_base_points
,
1078 /*************************************************************************/
1081 /* TT_Process_Composite_Glyph */
1084 /* This is slightly different from TT_Process_Simple_Glyph, in that */
1085 /* its sole purpose is to hint the glyph. Thus this function is */
1086 /* only available when bytecode interpreter is enabled. */
1089 TT_Process_Composite_Glyph( TT_Loader loader
,
1090 FT_UInt start_point
,
1091 FT_UInt start_contour
)
1094 FT_Outline
* outline
;
1098 outline
= &loader
->gloader
->base
.outline
;
1100 /* make room for phantom points */
1101 error
= FT_GLYPHLOADER_CHECK_POINTS( loader
->gloader
,
1102 outline
->n_points
+ 4,
1107 outline
->points
[outline
->n_points
] = loader
->pp1
;
1108 outline
->points
[outline
->n_points
+ 1] = loader
->pp2
;
1109 outline
->points
[outline
->n_points
+ 2] = loader
->pp3
;
1110 outline
->points
[outline
->n_points
+ 3] = loader
->pp4
;
1112 outline
->tags
[outline
->n_points
] = 0;
1113 outline
->tags
[outline
->n_points
+ 1] = 0;
1114 outline
->tags
[outline
->n_points
+ 2] = 0;
1115 outline
->tags
[outline
->n_points
+ 3] = 0;
1117 #ifdef TT_USE_BYTECODE_INTERPRETER
1120 FT_Stream stream
= loader
->stream
;
1124 /* TT_Load_Composite_Glyph only gives us the offset of instructions */
1125 /* so we read them here */
1126 if ( FT_STREAM_SEEK( loader
->ins_pos
) ||
1127 FT_READ_USHORT( n_ins
) )
1130 FT_TRACE5(( " Instructions size = %d\n", n_ins
));
1133 if ( n_ins
> ((TT_Face
)loader
->face
)->max_profile
.maxSizeOfInstructions
)
1135 FT_TRACE0(( "TT_Process_Composite_Glyph: too many instructions (%d)\n",
1138 return TT_Err_Too_Many_Hints
;
1140 else if ( n_ins
== 0 )
1143 if ( FT_STREAM_READ( loader
->exec
->glyphIns
, n_ins
) )
1146 loader
->glyph
->control_data
= loader
->exec
->glyphIns
;
1147 loader
->glyph
->control_len
= n_ins
;
1152 tt_prepare_zone( &loader
->zone
, &loader
->gloader
->base
,
1153 start_point
, start_contour
);
1155 /* Some points are likely touched during execution of */
1156 /* instructions on components. So let's untouch them. */
1157 for ( i
= start_point
; i
< loader
->zone
.n_points
; i
++ )
1158 loader
->zone
.tags
[i
] &= ~FT_CURVE_TAG_TOUCH_BOTH
;
1160 loader
->zone
.n_points
+= 4;
1162 return TT_Hint_Glyph( loader
, 1 );
1166 /* Calculate the four phantom points. */
1167 /* The first two stand for horizontal origin and advance. */
1168 /* The last two stand for vertical origin and advance. */
1169 #define TT_LOADER_SET_PP( loader ) \
1171 (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
1172 (loader)->pp1.y = 0; \
1173 (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
1174 (loader)->pp2.y = 0; \
1175 (loader)->pp3.x = 0; \
1176 (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \
1177 (loader)->pp4.x = 0; \
1178 (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
1182 /*************************************************************************/
1185 /* load_truetype_glyph */
1188 /* Loads a given truetype glyph. Handles composites and uses a */
1189 /* TT_Loader object. */
1192 load_truetype_glyph( TT_Loader loader
,
1193 FT_UInt glyph_index
,
1194 FT_UInt recurse_count
,
1195 FT_Bool header_only
)
1197 FT_Error error
= TT_Err_Ok
;
1198 FT_Fixed x_scale
, y_scale
;
1200 TT_Face face
= (TT_Face
)loader
->face
;
1201 FT_GlyphLoader gloader
= loader
->gloader
;
1202 FT_Bool opened_frame
= 0;
1204 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1205 FT_Vector
* deltas
= NULL
;
1208 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1209 FT_StreamRec inc_stream
;
1211 FT_Bool glyph_data_loaded
= 0;
1215 /* some fonts have an incorrect value of `maxComponentDepth', */
1216 /* thus we allow depth 1 to catch the majority of them */
1217 if ( recurse_count
> 1 &&
1218 recurse_count
> face
->max_profile
.maxComponentDepth
)
1220 error
= TT_Err_Invalid_Composite
;
1224 /* check glyph index */
1225 if ( glyph_index
>= (FT_UInt
)face
->root
.num_glyphs
)
1227 error
= TT_Err_Invalid_Glyph_Index
;
1231 loader
->glyph_index
= glyph_index
;
1233 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1235 x_scale
= ((TT_Size
)loader
->size
)->metrics
.x_scale
;
1236 y_scale
= ((TT_Size
)loader
->size
)->metrics
.y_scale
;
1244 tt_get_metrics( loader
, glyph_index
);
1246 /* Set `offset' to the start of the glyph relative to the start of */
1247 /* the `glyf' table, and `byte_len' to the length of the glyph in */
1250 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1252 /* If we are loading glyph data via the incremental interface, set */
1253 /* the loader stream to a memory stream reading the data returned */
1254 /* by the interface. */
1255 if ( face
->root
.internal
->incremental_interface
)
1257 error
= face
->root
.internal
->incremental_interface
->funcs
->get_glyph_data(
1258 face
->root
.internal
->incremental_interface
->object
,
1259 glyph_index
, &glyph_data
);
1263 glyph_data_loaded
= 1;
1265 loader
->byte_len
= glyph_data
.length
;
1267 FT_MEM_ZERO( &inc_stream
, sizeof ( inc_stream
) );
1268 FT_Stream_OpenMemory( &inc_stream
,
1269 glyph_data
.pointer
, glyph_data
.length
);
1271 loader
->stream
= &inc_stream
;
1275 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1277 offset
= tt_face_get_location( face
, glyph_index
,
1278 (FT_UInt
*)&loader
->byte_len
);
1280 if ( loader
->byte_len
> 0 )
1282 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1283 /* for the incremental interface, `glyf_offset' is always zero */
1284 if ( !loader
->glyf_offset
&&
1285 !face
->root
.internal
->incremental_interface
)
1287 if ( !loader
->glyf_offset
)
1288 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1290 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
1291 error
= TT_Err_Invalid_Table
;
1295 error
= face
->access_glyph_frame( loader
, glyph_index
,
1296 loader
->glyf_offset
+ offset
,
1303 /* read glyph header first */
1304 error
= face
->read_glyph_header( loader
);
1305 if ( error
|| header_only
)
1309 if ( loader
->byte_len
== 0 || loader
->n_contours
== 0 )
1311 loader
->bbox
.xMin
= 0;
1312 loader
->bbox
.xMax
= 0;
1313 loader
->bbox
.yMin
= 0;
1314 loader
->bbox
.yMax
= 0;
1319 TT_LOADER_SET_PP( loader
);
1321 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1323 if ( ((TT_Face
)(loader
->face
))->doblend
)
1325 /* this must be done before scaling */
1326 FT_Memory memory
= loader
->face
->memory
;
1329 error
= TT_Vary_Get_Glyph_Deltas( (TT_Face
)(loader
->face
),
1330 glyph_index
, &deltas
, 4 );
1334 loader
->pp1
.x
+= deltas
[0].x
; loader
->pp1
.y
+= deltas
[0].y
;
1335 loader
->pp2
.x
+= deltas
[1].x
; loader
->pp2
.y
+= deltas
[1].y
;
1336 loader
->pp3
.x
+= deltas
[2].x
; loader
->pp3
.y
+= deltas
[2].y
;
1337 loader
->pp4
.x
+= deltas
[3].x
; loader
->pp4
.y
+= deltas
[3].y
;
1344 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1346 loader
->pp1
.x
= FT_MulFix( loader
->pp1
.x
, x_scale
);
1347 loader
->pp2
.x
= FT_MulFix( loader
->pp2
.x
, x_scale
);
1348 loader
->pp3
.y
= FT_MulFix( loader
->pp3
.y
, y_scale
);
1349 loader
->pp4
.y
= FT_MulFix( loader
->pp4
.y
, y_scale
);
1356 TT_LOADER_SET_PP( loader
);
1358 /***********************************************************************/
1359 /***********************************************************************/
1360 /***********************************************************************/
1362 /* if it is a simple glyph, load it */
1364 if ( loader
->n_contours
> 0 )
1366 error
= face
->read_simple_glyph( loader
);
1370 /* all data have been read */
1371 face
->forget_glyph_frame( loader
);
1374 error
= TT_Process_Simple_Glyph( loader
);
1378 FT_GlyphLoader_Add( gloader
);
1381 /***********************************************************************/
1382 /***********************************************************************/
1383 /***********************************************************************/
1385 /* otherwise, load a composite! */
1386 else if ( loader
->n_contours
== -1 )
1388 FT_UInt start_point
;
1389 FT_UInt start_contour
;
1390 FT_ULong ins_pos
; /* position of composite instructions, if any */
1393 start_point
= gloader
->base
.outline
.n_points
;
1394 start_contour
= gloader
->base
.outline
.n_contours
;
1396 /* for each subglyph, read composite header */
1397 error
= face
->read_composite_glyph( loader
);
1401 /* store the offset of instructions */
1402 ins_pos
= loader
->ins_pos
;
1404 /* all data we need are read */
1405 face
->forget_glyph_frame( loader
);
1408 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1410 if ( face
->doblend
)
1413 FT_SubGlyph subglyph
;
1414 FT_Memory memory
= face
->root
.memory
;
1417 /* this provides additional offsets */
1418 /* for each component's translation */
1420 if ( ( error
= TT_Vary_Get_Glyph_Deltas(
1424 gloader
->current
.num_subglyphs
+ 4 )) != 0 )
1427 subglyph
= gloader
->current
.subglyphs
+ gloader
->base
.num_subglyphs
;
1428 limit
= gloader
->current
.num_subglyphs
;
1430 for ( i
= 0; i
< limit
; ++i
, ++subglyph
)
1432 if ( subglyph
->flags
& ARGS_ARE_XY_VALUES
)
1434 /* XXX: overflow check for subglyph->{arg1,arg2}. */
1435 /* deltas[i].{x,y} must be within signed 16-bit, */
1436 /* but the restriction of summed delta is not clear */
1437 subglyph
->arg1
+= (FT_Int16
)deltas
[i
].x
;
1438 subglyph
->arg2
+= (FT_Int16
)deltas
[i
].y
;
1442 loader
->pp1
.x
+= deltas
[i
+ 0].x
; loader
->pp1
.y
+= deltas
[i
+ 0].y
;
1443 loader
->pp2
.x
+= deltas
[i
+ 1].x
; loader
->pp2
.y
+= deltas
[i
+ 1].y
;
1444 loader
->pp3
.x
+= deltas
[i
+ 2].x
; loader
->pp3
.y
+= deltas
[i
+ 2].y
;
1445 loader
->pp4
.x
+= deltas
[i
+ 3].x
; loader
->pp4
.y
+= deltas
[i
+ 3].y
;
1450 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1452 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1454 loader
->pp1
.x
= FT_MulFix( loader
->pp1
.x
, x_scale
);
1455 loader
->pp2
.x
= FT_MulFix( loader
->pp2
.x
, x_scale
);
1456 loader
->pp3
.y
= FT_MulFix( loader
->pp3
.y
, y_scale
);
1457 loader
->pp4
.y
= FT_MulFix( loader
->pp4
.y
, y_scale
);
1460 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
1461 /* `as is' in the glyph slot (the client application will be */
1462 /* responsible for interpreting these data)... */
1463 if ( loader
->load_flags
& FT_LOAD_NO_RECURSE
)
1465 FT_GlyphLoader_Add( gloader
);
1466 loader
->glyph
->format
= FT_GLYPH_FORMAT_COMPOSITE
;
1471 /*********************************************************************/
1472 /*********************************************************************/
1473 /*********************************************************************/
1476 FT_UInt n
, num_base_points
;
1477 FT_SubGlyph subglyph
= 0;
1479 FT_UInt num_points
= start_point
;
1480 FT_UInt num_subglyphs
= gloader
->current
.num_subglyphs
;
1481 FT_UInt num_base_subgs
= gloader
->base
.num_subglyphs
;
1483 FT_Stream old_stream
= loader
->stream
;
1486 FT_GlyphLoader_Add( gloader
);
1488 /* read each subglyph independently */
1489 for ( n
= 0; n
< num_subglyphs
; n
++ )
1494 /* Each time we call load_truetype_glyph in this loop, the */
1495 /* value of `gloader.base.subglyphs' can change due to table */
1496 /* reallocations. We thus need to recompute the subglyph */
1497 /* pointer on each iteration. */
1498 subglyph
= gloader
->base
.subglyphs
+ num_base_subgs
+ n
;
1500 pp
[0] = loader
->pp1
;
1501 pp
[1] = loader
->pp2
;
1502 pp
[2] = loader
->pp3
;
1503 pp
[3] = loader
->pp4
;
1505 num_base_points
= gloader
->base
.outline
.n_points
;
1507 error
= load_truetype_glyph( loader
, subglyph
->index
,
1508 recurse_count
+ 1, FALSE
);
1512 /* restore subglyph pointer */
1513 subglyph
= gloader
->base
.subglyphs
+ num_base_subgs
+ n
;
1515 if ( !( subglyph
->flags
& USE_MY_METRICS
) )
1517 loader
->pp1
= pp
[0];
1518 loader
->pp2
= pp
[1];
1519 loader
->pp3
= pp
[2];
1520 loader
->pp4
= pp
[3];
1523 num_points
= gloader
->base
.outline
.n_points
;
1525 if ( num_points
== num_base_points
)
1528 /* gloader->base.outline consists of three parts: */
1529 /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
1531 /* (1): exists from the beginning */
1532 /* (2): components that have been loaded so far */
1533 /* (3): the newly loaded component */
1534 TT_Process_Composite_Component( loader
, subglyph
, start_point
,
1538 loader
->stream
= old_stream
;
1540 /* process the glyph */
1541 loader
->ins_pos
= ins_pos
;
1542 if ( IS_HINTED( loader
->load_flags
) &&
1544 #ifdef TT_USE_BYTECODE_INTERPRETER
1546 subglyph
->flags
& WE_HAVE_INSTR
&&
1550 num_points
> start_point
)
1551 TT_Process_Composite_Glyph( loader
, start_point
, start_contour
);
1557 /* invalid composite count (negative but not -1) */
1558 error
= TT_Err_Invalid_Outline
;
1562 /***********************************************************************/
1563 /***********************************************************************/
1564 /***********************************************************************/
1569 face
->forget_glyph_frame( loader
);
1571 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1573 if ( glyph_data_loaded
)
1574 face
->root
.internal
->incremental_interface
->funcs
->free_glyph_data(
1575 face
->root
.internal
->incremental_interface
->object
,
1585 compute_glyph_metrics( TT_Loader loader
,
1586 FT_UInt glyph_index
)
1589 TT_Face face
= (TT_Face
)loader
->face
;
1591 TT_GlyphSlot glyph
= loader
->glyph
;
1592 TT_Size size
= (TT_Size
)loader
->size
;
1596 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1597 y_scale
= size
->root
.metrics
.y_scale
;
1599 if ( glyph
->format
!= FT_GLYPH_FORMAT_COMPOSITE
)
1600 FT_Outline_Get_CBox( &glyph
->outline
, &bbox
);
1602 bbox
= loader
->bbox
;
1604 /* get the device-independent horizontal advance; it is scaled later */
1605 /* by the base layer. */
1607 FT_Pos advance
= loader
->linear
;
1610 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1611 /* correctly support DynaLab fonts, which have an incorrect */
1612 /* `advance_Width_Max' field! It is used, to my knowledge, */
1613 /* exclusively in the X-TrueType font server. */
1615 if ( face
->postscript
.isFixedPitch
&&
1616 ( loader
->load_flags
& FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
) == 0 )
1617 advance
= face
->horizontal
.advance_Width_Max
;
1619 /* we need to return the advance in font units in linearHoriAdvance, */
1620 /* it will be scaled later by the base layer. */
1621 glyph
->linearHoriAdvance
= advance
;
1624 glyph
->metrics
.horiBearingX
= bbox
.xMin
;
1625 glyph
->metrics
.horiBearingY
= bbox
.yMax
;
1626 glyph
->metrics
.horiAdvance
= loader
->pp2
.x
- loader
->pp1
.x
;
1628 /* adjust advance width to the value contained in the hdmx table */
1629 if ( !face
->postscript
.isFixedPitch
&&
1630 IS_HINTED( loader
->load_flags
) )
1635 widthp
= tt_face_get_device_metrics( face
,
1636 size
->root
.metrics
.x_ppem
,
1640 glyph
->metrics
.horiAdvance
= *widthp
<< 6;
1643 /* set glyph dimensions */
1644 glyph
->metrics
.width
= bbox
.xMax
- bbox
.xMin
;
1645 glyph
->metrics
.height
= bbox
.yMax
- bbox
.yMin
;
1647 /* Now take care of vertical metrics. In the case where there is */
1648 /* no vertical information within the font (relatively common), */
1649 /* create some metrics manually */
1651 FT_Pos top
; /* scaled vertical top side bearing */
1652 FT_Pos advance
; /* scaled vertical advance height */
1655 /* Get the unscaled top bearing and advance height. */
1656 if ( face
->vertical_info
&&
1657 face
->vertical
.number_Of_VMetrics
> 0 )
1659 top
= (FT_Short
)FT_DivFix( loader
->pp3
.y
- bbox
.yMax
,
1662 if ( loader
->pp3
.y
<= loader
->pp4
.y
)
1665 advance
= (FT_UShort
)FT_DivFix( loader
->pp3
.y
- loader
->pp4
.y
,
1673 /* XXX Compute top side bearing and advance height in */
1674 /* Get_VMetrics instead of here. */
1676 /* NOTE: The OS/2 values are the only `portable' ones, */
1677 /* which is why we use them, if there is an OS/2 */
1678 /* table in the font. Otherwise, we use the */
1679 /* values defined in the horizontal header. */
1681 height
= (FT_Short
)FT_DivFix( bbox
.yMax
- bbox
.yMin
,
1683 if ( face
->os2
.version
!= 0xFFFFU
)
1684 advance
= (FT_Pos
)( face
->os2
.sTypoAscender
-
1685 face
->os2
.sTypoDescender
);
1687 advance
= (FT_Pos
)( face
->horizontal
.Ascender
-
1688 face
->horizontal
.Descender
);
1690 top
= ( advance
- height
) / 2;
1693 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1695 FT_Incremental_InterfaceRec
* incr
;
1696 FT_Incremental_MetricsRec metrics
;
1700 incr
= face
->root
.internal
->incremental_interface
;
1702 /* If this is an incrementally loaded font see if there are */
1703 /* overriding metrics for this glyph. */
1704 if ( incr
&& incr
->funcs
->get_glyph_metrics
)
1706 metrics
.bearing_x
= 0;
1707 metrics
.bearing_y
= top
;
1708 metrics
.advance
= advance
;
1710 error
= incr
->funcs
->get_glyph_metrics( incr
->object
,
1717 top
= metrics
.bearing_y
;
1718 advance
= metrics
.advance
;
1722 /* GWW: Do vertical metrics get loaded incrementally too? */
1724 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1726 glyph
->linearVertAdvance
= advance
;
1728 /* scale the metrics */
1729 if ( !( loader
->load_flags
& FT_LOAD_NO_SCALE
) )
1731 top
= FT_MulFix( top
, y_scale
);
1732 advance
= FT_MulFix( advance
, y_scale
);
1735 /* XXX: for now, we have no better algorithm for the lsb, but it */
1736 /* should work fine. */
1738 glyph
->metrics
.vertBearingX
= glyph
->metrics
.horiBearingX
-
1739 glyph
->metrics
.horiAdvance
/ 2;
1740 glyph
->metrics
.vertBearingY
= top
;
1741 glyph
->metrics
.vertAdvance
= advance
;
1748 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1751 load_sbit_image( TT_Size size
,
1753 FT_UInt glyph_index
,
1754 FT_Int32 load_flags
)
1760 TT_SBit_MetricsRec metrics
;
1763 face
= (TT_Face
)glyph
->face
;
1764 sfnt
= (SFNT_Service
)face
->sfnt
;
1765 stream
= face
->root
.stream
;
1767 error
= sfnt
->load_sbit_image( face
,
1776 glyph
->outline
.n_points
= 0;
1777 glyph
->outline
.n_contours
= 0;
1779 glyph
->metrics
.width
= (FT_Pos
)metrics
.width
<< 6;
1780 glyph
->metrics
.height
= (FT_Pos
)metrics
.height
<< 6;
1782 glyph
->metrics
.horiBearingX
= (FT_Pos
)metrics
.horiBearingX
<< 6;
1783 glyph
->metrics
.horiBearingY
= (FT_Pos
)metrics
.horiBearingY
<< 6;
1784 glyph
->metrics
.horiAdvance
= (FT_Pos
)metrics
.horiAdvance
<< 6;
1786 glyph
->metrics
.vertBearingX
= (FT_Pos
)metrics
.vertBearingX
<< 6;
1787 glyph
->metrics
.vertBearingY
= (FT_Pos
)metrics
.vertBearingY
<< 6;
1788 glyph
->metrics
.vertAdvance
= (FT_Pos
)metrics
.vertAdvance
<< 6;
1790 glyph
->format
= FT_GLYPH_FORMAT_BITMAP
;
1792 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
1794 glyph
->bitmap_left
= metrics
.vertBearingX
;
1795 glyph
->bitmap_top
= metrics
.vertBearingY
;
1799 glyph
->bitmap_left
= metrics
.horiBearingX
;
1800 glyph
->bitmap_top
= metrics
.horiBearingY
;
1807 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1811 tt_loader_init( TT_Loader loader
,
1814 FT_Int32 load_flags
,
1815 FT_Bool glyf_table_only
)
1821 face
= (TT_Face
)glyph
->face
;
1822 stream
= face
->root
.stream
;
1824 FT_MEM_ZERO( loader
, sizeof ( TT_LoaderRec
) );
1826 #ifdef TT_USE_BYTECODE_INTERPRETER
1828 /* load execution context */
1829 if ( IS_HINTED( load_flags
) && !glyf_table_only
)
1831 TT_ExecContext exec
;
1835 if ( !size
->cvt_ready
)
1837 FT_Error error
= tt_size_ready_bytecode( size
);
1842 /* query new execution context */
1843 exec
= size
->debug
? size
->context
1844 : ( (TT_Driver
)FT_FACE_DRIVER( face
) )->context
;
1846 return TT_Err_Could_Not_Find_Context
;
1849 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags
) != FT_RENDER_MODE_MONO
);
1851 TT_Load_Context( exec
, face
, size
);
1853 /* a change from mono to grayscale rendering (and vice versa) */
1854 /* requires a re-execution of the CVT program */
1855 if ( grayscale
!= exec
->grayscale
)
1860 exec
->grayscale
= grayscale
;
1862 for ( i
= 0; i
< size
->cvt_size
; i
++ )
1863 size
->cvt
[i
] = FT_MulFix( face
->cvt
[i
], size
->ttmetrics
.scale
);
1864 tt_size_run_prep( size
);
1867 /* see whether the cvt program has disabled hinting */
1868 if ( exec
->GS
.instruct_control
& 1 )
1869 load_flags
|= FT_LOAD_NO_HINTING
;
1871 /* load default graphics state -- if needed */
1872 if ( exec
->GS
.instruct_control
& 2 )
1873 exec
->GS
= tt_default_graphics_state
;
1875 exec
->pedantic_hinting
= FT_BOOL( load_flags
& FT_LOAD_PEDANTIC
);
1876 loader
->exec
= exec
;
1877 loader
->instructions
= exec
->glyphIns
;
1880 #endif /* TT_USE_BYTECODE_INTERPRETER */
1882 /* seek to the beginning of the glyph table -- for Type 42 fonts */
1883 /* the table might be accessed from a Postscript stream or something */
1886 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1888 if ( face
->root
.internal
->incremental_interface
)
1889 loader
->glyf_offset
= 0;
1895 FT_Error error
= face
->goto_table( face
, TTAG_glyf
, stream
, 0 );
1898 if ( error
== TT_Err_Table_Missing
)
1899 loader
->glyf_offset
= 0;
1902 FT_ERROR(( "tt_loader_init: could not access glyph table\n" ));
1906 loader
->glyf_offset
= FT_STREAM_POS();
1909 /* get face's glyph loader */
1910 if ( !glyf_table_only
)
1912 FT_GlyphLoader gloader
= glyph
->internal
->loader
;
1915 FT_GlyphLoader_Rewind( gloader
);
1916 loader
->gloader
= gloader
;
1919 loader
->load_flags
= load_flags
;
1921 loader
->face
= (FT_Face
)face
;
1922 loader
->size
= (FT_Size
)size
;
1923 loader
->glyph
= (FT_GlyphSlot
)glyph
;
1924 loader
->stream
= stream
;
1930 /*************************************************************************/
1936 /* A function used to load a single glyph within a given glyph slot, */
1937 /* for a given size. */
1940 /* glyph :: A handle to a target slot object where the glyph */
1941 /* will be loaded. */
1943 /* size :: A handle to the source face size at which the glyph */
1944 /* must be scaled/loaded. */
1946 /* glyph_index :: The index of the glyph in the font file. */
1948 /* load_flags :: A flag indicating what to load for this glyph. The */
1949 /* FT_LOAD_XXX constants can be used to control the */
1950 /* glyph loading process (e.g., whether the outline */
1951 /* should be scaled, whether to load bitmaps or not, */
1952 /* whether to hint the outline, etc). */
1955 /* FreeType error code. 0 means success. */
1957 FT_LOCAL_DEF( FT_Error
)
1958 TT_Load_Glyph( TT_Size size
,
1960 FT_UInt glyph_index
,
1961 FT_Int32 load_flags
)
1965 TT_LoaderRec loader
;
1968 face
= (TT_Face
)glyph
->face
;
1971 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1973 /* try to load embedded bitmap if any */
1975 /* XXX: The convention should be emphasized in */
1976 /* the documents because it can be confusing. */
1977 if ( size
->strike_index
!= 0xFFFFFFFFUL
&&
1978 ( load_flags
& FT_LOAD_NO_BITMAP
) == 0 )
1980 error
= load_sbit_image( size
, glyph
, glyph_index
, load_flags
);
1983 FT_Face root
= &face
->root
;
1986 if ( FT_IS_SCALABLE( root
) )
1988 /* for the bbox we need the header only */
1989 (void)tt_loader_init( &loader
, size
, glyph
, load_flags
, TRUE
);
1990 (void)load_truetype_glyph( &loader
, glyph_index
, 0, TRUE
);
1991 glyph
->linearHoriAdvance
= loader
.linear
;
1992 glyph
->linearVertAdvance
= loader
.top_bearing
+ loader
.bbox
.yMax
-
1994 if ( face
->postscript
.isFixedPitch
&&
1995 ( load_flags
& FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
) == 0 )
1996 glyph
->linearHoriAdvance
= face
->horizontal
.advance_Width_Max
;
2003 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2005 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
2006 if ( !( load_flags
& FT_LOAD_NO_SCALE
) && !size
->ttmetrics
.valid
)
2007 return TT_Err_Invalid_Size_Handle
;
2009 if ( load_flags
& FT_LOAD_SBITS_ONLY
)
2010 return TT_Err_Invalid_Argument
;
2012 error
= tt_loader_init( &loader
, size
, glyph
, load_flags
, FALSE
);
2016 glyph
->format
= FT_GLYPH_FORMAT_OUTLINE
;
2017 glyph
->num_subglyphs
= 0;
2018 glyph
->outline
.flags
= 0;
2020 /* main loading loop */
2021 error
= load_truetype_glyph( &loader
, glyph_index
, 0, FALSE
);
2024 if ( glyph
->format
== FT_GLYPH_FORMAT_COMPOSITE
)
2026 glyph
->num_subglyphs
= loader
.gloader
->base
.num_subglyphs
;
2027 glyph
->subglyphs
= loader
.gloader
->base
.subglyphs
;
2031 glyph
->outline
= loader
.gloader
->base
.outline
;
2032 glyph
->outline
.flags
&= ~FT_OUTLINE_SINGLE_PASS
;
2034 /* In case bit 1 of the `flags' field in the `head' table isn't */
2035 /* set, translate array so that (0,0) is the glyph's origin. */
2036 if ( ( face
->header
.Flags
& 2 ) == 0 && loader
.pp1
.x
)
2037 FT_Outline_Translate( &glyph
->outline
, -loader
.pp1
.x
, 0 );
2040 #ifdef TT_USE_BYTECODE_INTERPRETER
2042 if ( IS_HINTED( load_flags
) )
2044 if ( loader
.exec
->GS
.scan_control
)
2046 /* convert scan conversion mode to FT_OUTLINE_XXX flags */
2047 switch ( loader
.exec
->GS
.scan_type
)
2049 case 0: /* simple drop-outs including stubs */
2050 glyph
->outline
.flags
|= FT_OUTLINE_INCLUDE_STUBS
;
2052 case 1: /* simple drop-outs excluding stubs */
2053 /* nothing; it's the default rendering mode */
2055 case 4: /* smart drop-outs including stubs */
2056 glyph
->outline
.flags
|= FT_OUTLINE_SMART_DROPOUTS
|
2057 FT_OUTLINE_INCLUDE_STUBS
;
2059 case 5: /* smart drop-outs excluding stubs */
2060 glyph
->outline
.flags
|= FT_OUTLINE_SMART_DROPOUTS
;
2063 default: /* no drop-out control */
2064 glyph
->outline
.flags
|= FT_OUTLINE_IGNORE_DROPOUTS
;
2069 glyph
->outline
.flags
|= FT_OUTLINE_IGNORE_DROPOUTS
;
2072 #endif /* TT_USE_BYTECODE_INTERPRETER */
2074 compute_glyph_metrics( &loader
, glyph_index
);
2077 /* Set the `high precision' bit flag. */
2078 /* This is _critical_ to get correct output for monochrome */
2079 /* TrueType glyphs at all sizes using the bytecode interpreter. */
2081 if ( !( load_flags
& FT_LOAD_NO_SCALE
) &&
2082 size
->root
.metrics
.y_ppem
< 24 )
2083 glyph
->outline
.flags
|= FT_OUTLINE_HIGH_PRECISION
;