1 /***************************************************************************/
5 /* TrueType Glyph Loader (body). */
7 /* Copyright 1996-2000 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 /***************************************************************************/
19 #include <freetype/internal/ftdebug.h>
20 #include <freetype/internal/ftcalc.h>
21 #include <freetype/internal/ftstream.h>
22 #include <freetype/internal/sfnt.h>
23 #include <freetype/tttags.h>
24 #include <freetype/ftoutln.h>
27 #ifdef FT_FLAT_COMPILE
33 #include <truetype/ttgload.h>
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 0x001
53 #define ARGS_ARE_XY_VALUES 0x002
54 #define ROUND_XY_TO_GRID 0x004
55 #define WE_HAVE_A_SCALE 0x008
57 #define MORE_COMPONENTS 0x020
58 #define WE_HAVE_AN_XY_SCALE 0x040
59 #define WE_HAVE_A_2X2 0x080
60 #define WE_HAVE_INSTR 0x100
61 #define USE_MY_METRICS 0x200
65 /*************************************************************************/
71 /* Returns the horizontal or vertical metrics in font units for a */
72 /* given glyph. The metrics are the left side bearing (resp. top */
73 /* side bearing) and advance width (resp. advance height). */
76 /* header :: A pointer to either the horizontal or vertical metrics */
79 /* index :: The glyph index. */
82 /* bearing :: The bearing, either left side or top side. */
84 /* advance :: The advance width resp. advance height. */
87 /* This function will much probably move to another component in the */
88 /* near future, but I haven't decided which yet. */
91 void TT_Get_Metrics( TT_HoriHeader
* header
,
96 TT_LongMetrics
* longs_m
;
97 FT_UShort k
= header
->number_Of_HMetrics
;
102 longs_m
= (TT_LongMetrics
*)header
->long_metrics
+ index
;
103 *bearing
= longs_m
->bearing
;
104 *advance
= longs_m
->advance
;
108 *bearing
= ((TT_ShortMetrics
*)header
->short_metrics
)[index
- k
];
109 *advance
= ((TT_LongMetrics
*)header
->long_metrics
)[k
- 1].advance
;
114 /*************************************************************************/
116 /* Returns the horizontal metrics in font units for a given glyph. If */
117 /* `check' is true, take care of monospaced fonts by returning the */
118 /* advance width maximum. */
121 void Get_HMetrics( TT_Face face
,
127 TT_Get_Metrics( &face
->horizontal
, index
, lsb
, aw
);
129 if ( check
&& face
->postscript
.isFixedPitch
)
130 *aw
= face
->horizontal
.advance_Width_Max
;
134 /*************************************************************************/
136 /* Returns the advance width table for a given pixel size if it is */
137 /* found in the font's `hdmx' table (if any). */
140 FT_Byte
* Get_Advance_Widths( TT_Face face
,
145 for ( n
= 0; n
< face
->hdmx
.num_records
; n
++ )
146 if ( face
->hdmx
.records
[n
].ppem
== ppem
)
147 return face
->hdmx
.records
[n
].widths
;
153 #define cur_to_org( n, zone ) \
154 MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( FT_Vector ) )
156 #define org_to_cur( n, zone ) \
157 MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( FT_Vector ) )
160 /*************************************************************************/
162 /* Translates an array of coordinates. */
165 void translate_array( FT_UInt n
,
174 for ( k
= 0; k
< n
; k
++ )
175 coords
[k
].x
+= delta_x
;
178 for ( k
= 0; k
< n
; k
++ )
179 coords
[k
].y
+= delta_y
;
184 void tt_prepare_zone( TT_GlyphZone
* zone
,
187 FT_UInt start_contour
)
189 zone
->n_points
= load
->outline
.n_points
- start_point
;
190 zone
->n_contours
= load
->outline
.n_contours
- start_contour
;
191 zone
->org
= load
->extra_points
+ start_point
;
192 zone
->cur
= load
->outline
.points
+ start_point
;
193 zone
->tags
= (FT_Byte
*)load
->outline
.tags
+ start_point
;
194 zone
->contours
= (FT_UShort
*)load
->outline
.contours
+ start_contour
;
199 #define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
202 /*************************************************************************/
204 /* The following functions are used by default with TrueType fonts. */
205 /* However, they can be replaced by alternatives if we need to support */
206 /* TrueType-compressed formats (like MicroType) in the future. */
208 /*************************************************************************/
211 FT_Error
TT_Access_Glyph_Frame( TT_Loader
* loader
,
217 FT_Stream stream
= loader
->stream
;
220 /* the following line sets the `error' variable through macros! */
221 (void)( FILE_Seek( offset
) || ACCESS_Frame( byte_count
) );
223 FT_TRACE5(( "Glyph %ld\n", glyph_index
));
229 void TT_Forget_Glyph_Frame( TT_Loader
* loader
)
231 FT_Stream stream
= loader
->stream
;
239 FT_Error
TT_Load_Glyph_Header( TT_Loader
* loader
)
241 FT_Stream stream
= loader
->stream
;
244 loader
->n_contours
= GET_Short();
246 loader
->bbox
.xMin
= GET_Short();
247 loader
->bbox
.yMin
= GET_Short();
248 loader
->bbox
.xMax
= GET_Short();
249 loader
->bbox
.yMax
= GET_Short();
251 FT_TRACE5(( " # of contours: %d\n", loader
->n_contours
));
252 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader
->bbox
.xMin
,
253 loader
->bbox
.xMax
));
254 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader
->bbox
.yMin
,
255 loader
->bbox
.yMax
));
262 FT_Error
TT_Load_Simple_Glyph( TT_Loader
* load
)
265 FT_Stream stream
= load
->stream
;
266 FT_GlyphLoader
* gloader
= load
->gloader
;
267 FT_Int n_contours
= load
->n_contours
;
269 TT_Face face
= (TT_Face
)load
->face
;
270 TT_GlyphSlot slot
= (TT_GlyphSlot
)load
->glyph
;
275 /* reading the contours endpoints & number of points */
277 short* cur
= gloader
->current
.outline
.contours
;
278 short* limit
= cur
+ n_contours
;
281 for ( ; cur
< limit
; cur
++ )
282 cur
[0] = GET_UShort();
285 if ( n_contours
> 0 )
286 n_points
= cur
[-1] + 1;
288 error
= FT_GlyphLoader_Check_Points( gloader
, n_points
+ 2, 0 );
292 outline
= &gloader
->current
.outline
;
295 /* reading the bytecode instructions */
296 slot
->control_len
= 0;
297 slot
->control_data
= 0;
299 n_ins
= GET_UShort();
301 FT_TRACE5(( " Instructions size: %d\n", n_ins
));
303 if ( n_ins
> face
->max_profile
.maxSizeOfInstructions
)
305 FT_TRACE0(( "ERROR: Too many instructions!\n" ));
306 error
= TT_Err_Too_Many_Ins
;
310 if ( stream
->cursor
+ n_ins
> stream
->limit
)
312 FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
313 error
= TT_Err_Too_Many_Ins
;
317 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
319 if ( ( load
->load_flags
&
320 ( FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
) ) == 0 &&
323 slot
->control_len
= n_ins
;
324 slot
->control_data
= load
->instructions
;
326 MEM_Copy( load
->instructions
, stream
->cursor
, n_ins
);
329 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
331 stream
->cursor
+= n_ins
;
333 /* reading the point tags */
336 FT_Byte
* flag
= (FT_Byte
*)outline
->tags
;
337 FT_Byte
* limit
= flag
+ n_points
;
341 for ( ; flag
< limit
; flag
++ )
343 *flag
= c
= GET_Byte();
346 for ( count
= GET_Byte(); count
> 0; count
-- )
352 /* reading the X coordinates */
355 FT_Vector
* vec
= outline
->points
;
356 FT_Vector
* limit
= vec
+ n_points
;
357 FT_Byte
* flag
= (FT_Byte
*)outline
->tags
;
361 for ( ; vec
< limit
; vec
++, flag
++ )
369 if ( ( *flag
& 16 ) == 0 )
372 else if ( ( *flag
& 16 ) == 0 )
380 /* reading the Y coordinates */
383 FT_Vector
* vec
= gloader
->current
.outline
.points
;
384 FT_Vector
* limit
= vec
+ n_points
;
385 FT_Byte
* flag
= (FT_Byte
*)outline
->tags
;
389 for ( ; vec
< limit
; vec
++, flag
++ )
397 if ( ( *flag
& 32 ) == 0 )
400 else if ( ( *flag
& 32 ) == 0 )
408 /* clear the touch tags */
409 for ( n
= 0; n
< n_points
; n
++ )
410 outline
->tags
[n
] &= FT_Curve_Tag_On
;
412 outline
->n_points
= n_points
;
413 outline
->n_contours
= n_contours
;
421 FT_Error
TT_Load_Composite_Glyph( TT_Loader
* loader
)
424 FT_Stream stream
= loader
->stream
;
425 FT_GlyphLoader
* gloader
= loader
->gloader
;
426 FT_SubGlyph
* subglyph
;
427 FT_UInt num_subglyphs
;
434 FT_Fixed xx
, xy
, yy
, yx
;
437 /* check that we can load a new subglyph */
438 error
= FT_GlyphLoader_Check_Subglyphs( gloader
, num_subglyphs
+ 1 );
442 subglyph
= gloader
->current
.subglyphs
+ num_subglyphs
;
444 subglyph
->arg1
= subglyph
->arg2
= 0;
446 subglyph
->flags
= GET_UShort();
447 subglyph
->index
= GET_UShort();
450 if ( subglyph
->flags
& ARGS_ARE_WORDS
)
452 subglyph
->arg1
= GET_Short();
453 subglyph
->arg2
= GET_Short();
457 subglyph
->arg1
= GET_Char();
458 subglyph
->arg2
= GET_Char();
465 if ( subglyph
->flags
& WE_HAVE_A_SCALE
)
467 xx
= (FT_Fixed
)GET_Short() << 2;
470 else if ( subglyph
->flags
& WE_HAVE_AN_XY_SCALE
)
472 xx
= (FT_Fixed
)GET_Short() << 2;
473 yy
= (FT_Fixed
)GET_Short() << 2;
475 else if ( subglyph
->flags
& WE_HAVE_A_2X2
)
477 xx
= (FT_Fixed
)GET_Short() << 2;
478 xy
= (FT_Fixed
)GET_Short() << 2;
479 yx
= (FT_Fixed
)GET_Short() << 2;
480 yy
= (FT_Fixed
)GET_Short() << 2;
483 subglyph
->transform
.xx
= xx
;
484 subglyph
->transform
.xy
= xy
;
485 subglyph
->transform
.yx
= yx
;
486 subglyph
->transform
.yy
= yy
;
490 } while ( subglyph
->flags
& MORE_COMPONENTS
);
492 gloader
->current
.num_subglyphs
= num_subglyphs
;
494 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
496 /* we must undo the ACCESS_Frame in order to point to the */
497 /* composite instructions, if we find some. */
498 /* we will process them later... */
500 loader
->ins_pos
= FILE_Pos() + stream
->cursor
- stream
->limit
;
510 void TT_Init_Glyph_Loading( TT_Face face
)
512 face
->access_glyph_frame
= TT_Access_Glyph_Frame
;
513 face
->read_glyph_header
= TT_Load_Glyph_Header
;
514 face
->read_simple_glyph
= TT_Load_Simple_Glyph
;
515 face
->read_composite_glyph
= TT_Load_Composite_Glyph
;
516 face
->forget_glyph_frame
= TT_Forget_Glyph_Frame
;
520 /*************************************************************************/
523 /* TT_Process_Simple_Glyph */
526 /* Once a simple glyph has been loaded, it needs to be processed. */
527 /* Usually, this means scaling and hinting through bytecode */
528 /* interpretation. */
531 FT_Error
TT_Process_Simple_Glyph( TT_Loader
* load
,
534 FT_GlyphLoader
* gloader
= load
->gloader
;
535 FT_Outline
* outline
= &gloader
->current
.outline
;
536 FT_UInt n_points
= outline
->n_points
;
538 TT_GlyphZone
* zone
= &load
->zone
;
539 FT_Error error
= FT_Err_Ok
;
542 n_ins
= load
->glyph
->control_len
;
544 /* add shadow points */
546 /* Now add the two shadow points at n and n + 1. */
547 /* We need the left side bearing and advance width. */
554 /* pp1 = xMin - lsb */
555 pp1
= outline
->points
+ n_points
;
556 pp1
->x
= load
->bbox
.xMin
- load
->left_bearing
;
561 pp2
->x
= pp1
->x
+ load
->advance
;
564 outline
->tags
[n_points
] = 0;
565 outline
->tags
[n_points
+ 1] = 0;
568 /* Note that we return two more points that are not */
569 /* part of the glyph outline. */
573 /* set up zone for hinting */
574 tt_prepare_zone( zone
, &gloader
->current
, 0, 0 );
576 /* eventually scale the glyph */
577 if ( !( load
->load_flags
& FT_LOAD_NO_SCALE
) )
579 FT_Vector
* vec
= zone
->cur
;
580 FT_Vector
* limit
= vec
+ n_points
;
581 FT_Fixed x_scale
= load
->size
->metrics
.x_scale
;
582 FT_Fixed y_scale
= load
->size
->metrics
.y_scale
;
585 /* first scale the glyph points */
586 for ( ; vec
< limit
; vec
++ )
588 vec
->x
= FT_MulFix( vec
->x
, x_scale
);
589 vec
->y
= FT_MulFix( vec
->y
, y_scale
);
593 cur_to_org( n_points
, zone
);
595 /* eventually hint the glyph */
596 if ( IS_HINTED( load
->load_flags
) )
598 FT_Pos x
= zone
->org
[n_points
-2].x
;
601 x
= ( ( x
+ 32 ) & -64 ) - x
;
602 translate_array( n_points
, zone
->org
, x
, 0 );
604 org_to_cur( n_points
, zone
);
606 zone
->cur
[n_points
- 1].x
= ( zone
->cur
[n_points
- 1].x
+ 32 ) & -64;
608 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
610 /* now consider hinting */
613 error
= TT_Set_CodeRange( load
->exec
, tt_coderange_glyph
,
614 load
->exec
->glyphIns
, n_ins
);
618 load
->exec
->is_composite
= FALSE
;
619 load
->exec
->pedantic_hinting
= (FT_Bool
)( load
->load_flags
&
621 load
->exec
->pts
= *zone
;
622 load
->exec
->pts
.n_points
+= 2;
624 error
= TT_Run_Context( load
->exec
, debug
);
625 if ( error
&& load
->exec
->pedantic_hinting
)
628 error
= FT_Err_Ok
; /* ignore bytecode errors in non-pedantic mode */
631 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
635 /* save glyph phantom points */
636 if ( !load
->preserve_pps
)
638 load
->pp1
= zone
->cur
[n_points
- 2];
639 load
->pp2
= zone
->cur
[n_points
- 1];
642 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
649 /*************************************************************************/
652 /* load_truetype_glyph */
655 /* Loads a given truetype glyph. Handles composites and uses a */
656 /* TT_Loader object. */
659 FT_Error
load_truetype_glyph( TT_Loader
* loader
,
660 FT_UInt glyph_index
)
662 FT_Stream stream
= loader
->stream
;
664 TT_Face face
= (TT_Face
)loader
->face
;
666 FT_Int contours_count
;
667 FT_UInt index
, num_points
, num_contours
, count
;
668 FT_Fixed x_scale
, y_scale
;
670 FT_GlyphLoader
* gloader
= loader
->gloader
;
671 FT_Bool opened_frame
= 0;
674 /* check glyph index */
676 if ( index
>= (FT_UInt
)face
->root
.num_glyphs
)
678 error
= TT_Err_Invalid_Glyph_Index
;
682 loader
->glyph_index
= glyph_index
;
689 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
691 x_scale
= loader
->size
->metrics
.x_scale
;
692 y_scale
= loader
->size
->metrics
.y_scale
;
695 /* get horizontal metrics */
697 FT_Short left_bearing
;
698 FT_UShort advance_width
;
701 Get_HMetrics( face
, index
,
702 (FT_Bool
)!(loader
->load_flags
&
703 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
),
707 loader
->left_bearing
= left_bearing
;
708 loader
->advance
= advance_width
;
711 offset
= face
->glyph_locations
[index
];
714 if ( index
< (FT_UInt
)face
->num_locations
- 1 )
715 count
= face
->glyph_locations
[index
+ 1] - offset
;
719 /* as described by Frederic Loyer, these are spaces, and */
720 /* not the unknown glyph. */
721 loader
->bbox
.xMin
= 0;
722 loader
->bbox
.xMax
= 0;
723 loader
->bbox
.yMin
= 0;
724 loader
->bbox
.yMax
= 0;
727 loader
->pp2
.x
= loader
->advance
;
729 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
730 loader
->pp2
.x
= FT_MulFix( loader
->pp2
.x
, x_scale
);
732 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
735 loader
->exec
->glyphSize
= 0;
743 offset
= loader
->glyf_offset
+ offset
;
745 /* access glyph frame */
746 error
= face
->access_glyph_frame( loader
, glyph_index
, offset
, count
);
752 /* read first glyph header */
753 error
= face
->read_glyph_header( loader
);
757 contours_count
= loader
->n_contours
;
761 loader
->pp1
.x
= loader
->bbox
.xMin
- loader
->left_bearing
;
763 loader
->pp2
.x
= loader
->pp1
.x
+ loader
->advance
;
766 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
768 loader
->pp1
.x
= FT_MulFix( loader
->pp1
.x
, x_scale
);
769 loader
->pp2
.x
= FT_MulFix( loader
->pp2
.x
, x_scale
);
772 /***********************************************************************/
773 /***********************************************************************/
774 /***********************************************************************/
776 /* if it is a simple glyph, load it */
778 if ( contours_count
>= 0 )
780 /* check that we can add the contours to the glyph */
781 error
= FT_GlyphLoader_Check_Points( gloader
, 0, contours_count
);
785 error
= face
->read_simple_glyph( loader
);
789 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
792 TT_Size size
= (TT_Size
)loader
->size
;
795 error
= TT_Process_Simple_Glyph( loader
,
796 (FT_Bool
)( size
&& size
->debug
) );
801 error
= TT_Process_Simple_Glyph( loader
, 0 );
808 FT_GlyphLoader_Add( gloader
);
810 /* Note: We could have put the simple loader source there */
811 /* but the code is fat enough already :-) */
814 /***********************************************************************/
815 /***********************************************************************/
816 /***********************************************************************/
818 /* otherwise, load a composite! */
821 TT_GlyphSlot glyph
= (TT_GlyphSlot
)loader
->glyph
;
822 FT_UInt start_point
, start_contour
;
823 FT_ULong ins_pos
; /* position of composite instructions, if any */
826 /* for each subglyph, read composite header */
827 start_point
= gloader
->base
.outline
.n_points
;
828 start_contour
= gloader
->base
.outline
.n_contours
;
830 error
= face
->read_composite_glyph( loader
);
834 ins_pos
= loader
->ins_pos
;
835 face
->forget_glyph_frame( loader
);
838 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
839 /* `as is' in the glyph slot (the client application will be */
840 /* responsible for interpreting this data)... */
842 if ( loader
->load_flags
& FT_LOAD_NO_RECURSE
)
844 /* set up remaining glyph fields */
845 FT_GlyphLoader_Add( gloader
);
847 glyph
->num_subglyphs
= gloader
->base
.num_subglyphs
;
848 glyph
->format
= ft_glyph_format_composite
;
849 glyph
->subglyphs
= gloader
->base
.subglyphs
;
854 /*********************************************************************/
855 /*********************************************************************/
856 /*********************************************************************/
858 /* Now, read each subglyph independently. */
860 FT_Int n
, num_base_points
, num_new_points
;
861 FT_SubGlyph
* subglyph
= 0;
863 FT_UInt num_subglyphs
= gloader
->current
.num_subglyphs
;
864 FT_UInt num_base_subgs
= gloader
->base
.num_subglyphs
;
867 FT_GlyphLoader_Add( gloader
);
869 for ( n
= 0; n
< (FT_Int
)num_subglyphs
; n
++ )
875 /* Each time we call load_truetype_glyph in this loop, the */
876 /* value of `gloader.base.subglyphs' can change due to table */
877 /* reallocations. We thus need to recompute the subglyph */
878 /* pointer on each iteration. */
879 subglyph
= gloader
->base
.subglyphs
+ num_base_subgs
+ n
;
884 num_base_points
= gloader
->base
.outline
.n_points
;
886 error
= load_truetype_glyph( loader
, subglyph
->index
);
890 subglyph
= gloader
->base
.subglyphs
+ num_base_subgs
+ n
;
892 if ( subglyph
->flags
& USE_MY_METRICS
)
903 num_points
= gloader
->base
.outline
.n_points
;
905 num_new_points
= num_points
- num_base_points
;
907 /* now perform the transform required for this subglyph */
909 if ( subglyph
->flags
& ( WE_HAVE_A_SCALE
|
910 WE_HAVE_AN_XY_SCALE
|
913 FT_Vector
* cur
= gloader
->base
.outline
.points
+
915 FT_Vector
* org
= gloader
->base
.extra_points
+
917 FT_Vector
* limit
= cur
+ num_new_points
;
920 for ( ; cur
< limit
; cur
++, org
++ )
922 FT_Vector_Transform( cur
, &subglyph
->transform
);
923 FT_Vector_Transform( org
, &subglyph
->transform
);
929 if ( !( subglyph
->flags
& ARGS_ARE_XY_VALUES
) )
931 FT_UInt k
= subglyph
->arg1
;
932 FT_UInt l
= subglyph
->arg2
;
937 if ( start_point
+ k
>= (FT_UInt
)num_base_points
||
938 l
>= (FT_UInt
)num_new_points
)
940 error
= TT_Err_Invalid_Composite
;
944 l
+= num_base_points
;
946 p1
= gloader
->base
.outline
.points
+ start_point
+ k
;
947 p2
= gloader
->base
.outline
.points
+ start_point
+ l
;
957 if ( !( loader
->load_flags
& FT_LOAD_NO_SCALE
) )
959 x
= FT_MulFix( x
, x_scale
);
960 y
= FT_MulFix( y
, y_scale
);
962 if ( subglyph
->flags
& ROUND_XY_TO_GRID
)
964 x
= ( x
+ 32 ) & -64;
965 y
= ( y
+ 32 ) & -64;
970 translate_array( num_new_points
, loader
->zone
.cur
, x
, y
);
971 cur_to_org( num_new_points
, &loader
->zone
);
974 /*******************************************************************/
975 /*******************************************************************/
976 /*******************************************************************/
978 /* we have finished loading all sub-glyphs; now, look for */
979 /* instructions for this composite! */
981 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
983 if ( num_subglyphs
> 0 &&
986 subglyph
->flags
& WE_HAVE_INSTR
)
989 TT_ExecContext exec
= loader
->exec
;
994 /* read size of instructions */
995 if ( FILE_Seek( ins_pos
) ||
996 READ_UShort( n_ins
) )
998 FT_TRACE5(( " Instructions size = %d\n", n_ins
));
1000 /* in some fonts? */
1001 if ( n_ins
== 0xFFFF )
1005 if ( n_ins
> face
->max_profile
.maxSizeOfInstructions
)
1007 FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
1008 n_ins
, subglyph
->index
));
1009 return TT_Err_Too_Many_Ins
;
1012 /* read the instructions */
1013 if ( FILE_Read( exec
->glyphIns
, n_ins
) )
1016 glyph
->control_data
= exec
->glyphIns
;
1017 glyph
->control_len
= n_ins
;
1019 error
= TT_Set_CodeRange( exec
,
1026 /* prepare the execution context */
1027 tt_prepare_zone( &exec
->pts
, &gloader
->base
,
1028 start_point
, start_contour
);
1031 pts
->n_points
= num_points
+ 2;
1032 pts
->n_contours
= gloader
->base
.outline
.n_contours
;
1034 /* add phantom points */
1035 pp1
= pts
->cur
+ num_points
;
1036 pp1
[0] = loader
->pp1
;
1037 pp1
[1] = loader
->pp2
;
1039 pts
->tags
[num_points
] = 0;
1040 pts
->tags
[num_points
+ 1] = 0;
1042 /* if hinting, round the phantom points */
1043 if ( IS_HINTED( loader
->load_flags
) )
1045 pp1
[0].x
= ( ( loader
->pp1
.x
+ 32 ) & -64 );
1046 pp1
[1].x
= ( ( loader
->pp2
.x
+ 32 ) & -64 );
1053 for ( k
= 0; k
< num_points
; k
++ )
1054 pts
->tags
[k
] &= FT_Curve_Tag_On
;
1057 cur_to_org( num_points
+ 2, pts
);
1059 /* now consider hinting */
1060 if ( IS_HINTED( loader
->load_flags
) && n_ins
> 0 )
1062 exec
->is_composite
= TRUE
;
1063 exec
->pedantic_hinting
=
1064 (FT_Bool
)( loader
->load_flags
& FT_LOAD_PEDANTIC
);
1066 error
= TT_Run_Context( exec
, ((TT_Size
)loader
->size
)->debug
);
1067 if ( error
&& exec
->pedantic_hinting
)
1071 /* save glyph origin and advance points */
1072 loader
->pp1
= pp1
[0];
1073 loader
->pp2
= pp1
[1];
1076 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1079 /* end of composite loading */
1082 /***********************************************************************/
1083 /***********************************************************************/
1084 /***********************************************************************/
1088 face
->forget_glyph_frame( loader
);
1096 void compute_glyph_metrics( TT_Loader
* loader
,
1097 FT_UInt glyph_index
)
1100 TT_Face face
= (TT_Face
)loader
->face
;
1101 FT_Fixed x_scale
, y_scale
;
1102 TT_GlyphSlot glyph
= loader
->glyph
;
1103 TT_Size size
= (TT_Size
)loader
->size
;
1108 if ( ( loader
->load_flags
& FT_LOAD_NO_SCALE
) == 0 )
1110 x_scale
= size
->root
.metrics
.x_scale
;
1111 y_scale
= size
->root
.metrics
.y_scale
;
1114 if ( glyph
->format
!= ft_glyph_format_composite
)
1116 glyph
->outline
.flags
&= ~ft_outline_single_pass
;
1118 /* copy outline to our glyph slot */
1119 FT_GlyphLoader_Copy_Points( glyph
->loader
, loader
->gloader
);
1120 glyph
->outline
= glyph
->loader
->base
.outline
;
1122 /* translate array so that (0,0) is the glyph's origin */
1123 FT_Outline_Translate( &glyph
->outline
, -loader
->pp1
.x
, 0 );
1125 FT_Outline_Get_CBox( &glyph
->outline
, &bbox
);
1127 if ( IS_HINTED( loader
->load_flags
) )
1129 /* grid-fit the bounding box */
1132 bbox
.xMax
= ( bbox
.xMax
+ 63 ) & -64;
1133 bbox
.yMax
= ( bbox
.yMax
+ 63 ) & -64;
1137 bbox
= loader
->bbox
;
1139 /* get the device-independent horizontal advance. It is scaled later */
1140 /* by the base layer. */
1142 FT_Pos advance
= loader
->advance
;
1145 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1146 /* correctly support DynaLab fonts, which have an incorrect */
1147 /* `advance_Width_Max' field! It is used, to my knowledge, */
1148 /* exclusively in the X-TrueType font server. */
1150 if ( face
->postscript
.isFixedPitch
&&
1151 ( loader
->load_flags
& FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
) == 0 )
1152 advance
= face
->horizontal
.advance_Width_Max
;
1154 /* we need to return the advance in font units in linearHoriAdvance, */
1155 /* it will be scaled later by the base layer. */
1156 glyph
->linearHoriAdvance
= advance
;
1159 glyph
->metrics
.horiBearingX
= bbox
.xMin
;
1160 glyph
->metrics
.horiBearingY
= bbox
.yMax
;
1161 glyph
->metrics
.horiAdvance
= loader
->pp2
.x
- loader
->pp1
.x
;
1163 /* Now take care of vertical metrics. In the case where there is */
1164 /* no vertical information within the font (relatively common), make */
1165 /* up some metrics by `hand'... */
1168 FT_Short top_bearing
; /* vertical top side bearing (EM units) */
1169 FT_UShort advance_height
; /* vertical advance height (EM units) */
1171 FT_Pos left
; /* scaled vertical left side bearing */
1172 FT_Pos Top
; /* scaled original vertical top side bearing */
1173 FT_Pos top
; /* scaled vertical top side bearing */
1174 FT_Pos advance
; /* scaled vertical advance height */
1177 /* Get the unscaled `tsb' and `ah' */
1178 if ( face
->vertical_info
&&
1179 face
->vertical
.number_Of_VMetrics
> 0 )
1181 /* Don't assume that both the vertical header and vertical */
1182 /* metrics are present in the same font :-) */
1184 TT_Get_Metrics( (TT_HoriHeader
*)&face
->vertical
,
1191 /* Make up the distances from the horizontal header. */
1193 /* NOTE: The OS/2 values are the only `portable' ones, */
1194 /* which is why we use them, if there is an OS/2 */
1195 /* table in the font. Otherwise, we use the */
1196 /* values defined in the horizontal header. */
1198 /* NOTE2: The sTypoDescender is negative, which is why */
1199 /* we compute the baseline-to-baseline distance */
1201 /* ascender - descender + linegap */
1203 if ( face
->os2
.version
!= 0xFFFF )
1205 top_bearing
= face
->os2
.sTypoLineGap
/ 2;
1206 advance_height
= (FT_UShort
)( face
->os2
.sTypoAscender
-
1207 face
->os2
.sTypoDescender
+
1208 face
->os2
.sTypoLineGap
);
1212 top_bearing
= face
->horizontal
.Line_Gap
/ 2;
1213 advance_height
= (FT_UShort
)( face
->horizontal
.Ascender
+
1214 face
->horizontal
.Descender
+
1215 face
->horizontal
.Line_Gap
);
1219 /* We must adjust the top_bearing value from the bounding box given */
1220 /* in the glyph header to te bounding box calculated with */
1221 /* FT_Get_Outline_CBox(). */
1223 /* scale the metrics */
1224 if ( !( loader
->load_flags
& FT_LOAD_NO_SCALE
) )
1226 Top
= FT_MulFix( top_bearing
, y_scale
);
1227 top
= FT_MulFix( top_bearing
+ loader
->bbox
.yMax
, y_scale
)
1229 advance
= FT_MulFix( advance_height
, y_scale
);
1234 top
= top_bearing
+ loader
->bbox
.yMax
- bbox
.yMax
;
1235 advance
= advance_height
;
1238 /* set the advance height in design units. It is scaled later by */
1239 /* the base layer. */
1240 glyph
->linearVertAdvance
= advance_height
;
1242 /* XXX: for now, we have no better algorithm for the lsb, but it */
1243 /* should work fine. */
1245 left
= ( bbox
.xMin
- bbox
.xMax
) / 2;
1247 /* grid-fit them if necessary */
1248 if ( IS_HINTED( loader
->load_flags
) )
1251 top
= ( top
+ 63 ) & -64;
1252 advance
= ( advance
+ 32 ) & -64;
1255 glyph
->metrics
.vertBearingX
= left
;
1256 glyph
->metrics
.vertBearingY
= top
;
1257 glyph
->metrics
.vertAdvance
= advance
;
1260 /* adjust advance width to the value contained in the hdmx table */
1261 if ( !face
->postscript
.isFixedPitch
&& size
&&
1262 IS_HINTED( loader
->load_flags
) )
1264 FT_Byte
* widths
= Get_Advance_Widths( face
,
1265 size
->root
.metrics
.x_ppem
);
1269 glyph
->metrics
.horiAdvance
= widths
[glyph_index
] << 6;
1272 /* set glyph dimensions */
1273 glyph
->metrics
.width
= bbox
.xMax
- bbox
.xMin
;
1274 glyph
->metrics
.height
= bbox
.yMax
- bbox
.yMin
;
1278 /*************************************************************************/
1284 /* A function used to load a single glyph within a given glyph slot, */
1285 /* for a given size. */
1288 /* glyph :: A handle to a target slot object where the glyph */
1289 /* will be loaded. */
1291 /* size :: A handle to the source face size at which the glyph */
1292 /* must be scaled/loaded. */
1294 /* glyph_index :: The index of the glyph in the font file. */
1296 /* load_flags :: A flag indicating what to load for this glyph. The */
1297 /* FT_LOAD_XXX constants can be used to control the */
1298 /* glyph loading process (e.g., whether the outline */
1299 /* should be scaled, whether to load bitmaps or not, */
1300 /* whether to hint the outline, etc). */
1303 /* FreeType error code. 0 means success. */
1306 FT_Error
TT_Load_Glyph( TT_Size size
,
1308 FT_UShort glyph_index
,
1309 FT_UInt load_flags
)
1311 SFNT_Interface
* sfnt
;
1319 face
= (TT_Face
)glyph
->face
;
1320 sfnt
= (SFNT_Interface
*)face
->sfnt
;
1321 stream
= face
->root
.stream
;
1322 memory
= face
->root
.memory
;
1325 if ( !size
|| ( load_flags
& FT_LOAD_NO_SCALE
) ||
1326 ( load_flags
& FT_LOAD_NO_RECURSE
) )
1329 load_flags
|= FT_LOAD_NO_SCALE
|
1330 FT_LOAD_NO_HINTING
|
1334 glyph
->num_subglyphs
= 0;
1336 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1338 /* try to load embedded bitmap if any */
1340 ( load_flags
& FT_LOAD_NO_BITMAP
) == 0 &&
1343 TT_SBit_Metrics metrics
;
1346 error
= sfnt
->load_sbit_image( face
,
1347 size
->root
.metrics
.x_ppem
,
1348 size
->root
.metrics
.y_ppem
,
1356 glyph
->outline
.n_points
= 0;
1357 glyph
->outline
.n_contours
= 0;
1359 glyph
->metrics
.width
= (FT_Pos
)metrics
.width
<< 6;
1360 glyph
->metrics
.height
= (FT_Pos
)metrics
.height
<< 6;
1362 glyph
->metrics
.horiBearingX
= (FT_Pos
)metrics
.horiBearingX
<< 6;
1363 glyph
->metrics
.horiBearingY
= (FT_Pos
)metrics
.horiBearingY
<< 6;
1364 glyph
->metrics
.horiAdvance
= (FT_Pos
)metrics
.horiAdvance
<< 6;
1366 glyph
->metrics
.vertBearingX
= (FT_Pos
)metrics
.vertBearingX
<< 6;
1367 glyph
->metrics
.vertBearingY
= (FT_Pos
)metrics
.vertBearingY
<< 6;
1368 glyph
->metrics
.vertAdvance
= (FT_Pos
)metrics
.vertAdvance
<< 6;
1370 glyph
->format
= ft_glyph_format_bitmap
;
1371 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
1373 glyph
->bitmap_left
= metrics
.vertBearingX
;
1374 glyph
->bitmap_top
= metrics
.vertBearingY
;
1378 glyph
->bitmap_left
= metrics
.horiBearingX
;
1379 glyph
->bitmap_top
= metrics
.horiBearingY
;
1385 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1387 /* seek to the beginning of the glyph table. For Type 42 fonts */
1388 /* the table might be accessed from a Postscript stream or something */
1391 error
= face
->goto_table( face
, TTAG_glyf
, stream
, 0 );
1394 FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
1398 MEM_Set( &loader
, 0, sizeof ( loader
) );
1400 /* update the glyph zone bounds */
1402 FT_GlyphLoader
* gloader
= FT_FACE_DRIVER(face
)->glyph_loader
;
1405 loader
.gloader
= gloader
;
1407 FT_GlyphLoader_Rewind( gloader
);
1409 tt_prepare_zone( &loader
.zone
, &gloader
->base
, 0, 0 );
1410 tt_prepare_zone( &loader
.base
, &gloader
->base
, 0, 0 );
1413 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1417 /* query new execution context */
1418 loader
.exec
= size
->debug
? size
->context
: TT_New_Context( face
);
1420 return TT_Err_Could_Not_Find_Context
;
1422 TT_Load_Context( loader
.exec
, face
, size
);
1423 loader
.instructions
= loader
.exec
->glyphIns
;
1425 /* load default graphics state - if needed */
1426 if ( size
->GS
.instruct_control
& 2 )
1427 loader
.exec
->GS
= tt_default_graphics_state
;
1430 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1432 /* clear all outline flags, except the `owner' one */
1433 glyph
->outline
.flags
= 0;
1435 if ( size
&& size
->root
.metrics
.y_ppem
< 24 )
1436 glyph
->outline
.flags
|= ft_outline_high_precision
;
1438 /* let's initialize the rest of our loader now */
1440 loader
.load_flags
= load_flags
;
1442 loader
.face
= (FT_Face
)face
;
1443 loader
.size
= (FT_Size
)size
;
1444 loader
.glyph
= (FT_GlyphSlot
)glyph
;
1445 loader
.stream
= stream
;
1447 loader
.glyf_offset
= FILE_Pos();
1449 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1451 /* if the cvt program has disabled hinting, the argument */
1453 if ( size
&& ( size
->GS
.instruct_control
& 1 ) )
1454 loader
.load_flags
|= FT_LOAD_NO_HINTING
;
1456 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1458 /* Main loading loop */
1459 glyph
->format
= ft_glyph_format_outline
;
1460 glyph
->num_subglyphs
= 0;
1461 error
= load_truetype_glyph( &loader
, glyph_index
);
1463 compute_glyph_metrics( &loader
, glyph_index
);
1465 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1467 if ( !size
|| !size
->debug
)
1468 TT_Done_Context( loader
.exec
);
1470 #endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */