1 /***************************************************************************/
5 /* TrueType Glyph Loader (body). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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;
256 /* check that we can add the contours to the glyph */
257 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
261 /* reading the contours' endpoints & number of points */
262 cont = gloader->current.outline.contours;
263 cont_limit = cont + n_contours;
265 /* check space for contours array + instructions count */
266 if ( n_contours >= 0xFFF || p + (n_contours + 1) * 2 > limit )
267 goto Invalid_Outline;
269 for ( ; cont < cont_limit; cont++ )
270 cont[0] = FT_NEXT_USHORT( p );
273 if ( n_contours > 0 )
274 n_points = cont[-1] + 1;
276 /* note that we will add four phantom points later */
277 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
281 /* we'd better check the contours table right now */
282 outline = &gloader->current.outline;
284 for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
285 if ( cont[-1] >= cont[0] )
286 goto Invalid_Outline;
288 /* reading the bytecode instructions */
289 load->glyph->control_len = 0;
290 load->glyph->control_data = 0;
293 goto Invalid_Outline;
295 n_ins = FT_NEXT_USHORT( p );
297 FT_TRACE5(( " Instructions size: %u\n", n_ins ));
299 if ( n_ins > face->max_profile.maxSizeOfInstructions )
301 FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions!\n" ));
302 error = TT_Err_Too_Many_Hints;
306 if ( ( limit - p ) < n_ins )
308 FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" ));
309 error = TT_Err_Too_Many_Hints;
313 #ifdef TT_USE_BYTECODE_INTERPRETER
315 if ( IS_HINTED( load->load_flags ) )
317 load->glyph->control_len = n_ins;
318 load->glyph->control_data = load->exec->glyphIns;
320 FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
323 #endif /* TT_USE_BYTECODE_INTERPRETER */
327 /* reading the point tags */
328 flag = (FT_Byte*)outline->tags;
329 flag_limit = flag + n_points;
331 FT_ASSERT( flag != NULL );
333 while ( flag < flag_limit )
336 goto Invalid_Outline;
338 *flag++ = c = FT_NEXT_BYTE( p );
342 goto Invalid_Outline;
344 count = FT_NEXT_BYTE( p );
345 if ( flag + (FT_Int)count > flag_limit )
346 goto Invalid_Outline;
348 for ( ; count > 0; count-- )
353 /* reading the X coordinates */
355 vec = outline->points;
356 vec_limit = vec + n_points;
357 flag = (FT_Byte*)outline->tags;
360 for ( ; vec < vec_limit; vec++, flag++ )
368 goto Invalid_Outline;
370 y = (FT_Pos)FT_NEXT_BYTE( p );
371 if ( ( *flag & 16 ) == 0 )
374 else if ( ( *flag & 16 ) == 0 )
377 goto Invalid_Outline;
379 y = (FT_Pos)FT_NEXT_SHORT( p );
386 /* reading the Y coordinates */
388 vec = gloader->current.outline.points;
389 vec_limit = vec + n_points;
390 flag = (FT_Byte*)outline->tags;
393 for ( ; vec < vec_limit; vec++, flag++ )
401 goto Invalid_Outline;
403 y = (FT_Pos)FT_NEXT_BYTE( p );
404 if ( ( *flag & 32 ) == 0 )
407 else if ( ( *flag & 32 ) == 0 )
410 goto Invalid_Outline;
412 y = (FT_Pos)FT_NEXT_SHORT( p );
419 /* clear the touch tags */
420 for ( n = 0; n < n_points; n++ )
421 outline->tags[n] &= FT_CURVE_TAG_ON;
423 outline->n_points = (FT_UShort)n_points;
424 outline->n_contours = (FT_Short) n_contours;
432 error = TT_Err_Invalid_Outline;
437 FT_CALLBACK_DEF( FT_Error )
438 TT_Load_Composite_Glyph( TT_Loader loader )
441 FT_Byte* p = loader->cursor;
442 FT_Byte* limit = loader->limit;
443 FT_GlyphLoader gloader = loader->gloader;
444 FT_SubGlyph subglyph;
445 FT_UInt num_subglyphs;
452 FT_Fixed xx, xy, yy, yx;
456 /* check that we can load a new subglyph */
457 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
463 goto Invalid_Composite;
465 subglyph = gloader->current.subglyphs + num_subglyphs;
467 subglyph->arg1 = subglyph->arg2 = 0;
469 subglyph->flags = FT_NEXT_USHORT( p );
470 subglyph->index = FT_NEXT_USHORT( p );
474 if ( subglyph->flags & ARGS_ARE_WORDS )
476 if ( subglyph->flags & WE_HAVE_A_SCALE )
478 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
480 else if ( subglyph->flags & WE_HAVE_A_2X2 )
483 if ( p + count > limit )
484 goto Invalid_Composite;
487 if ( subglyph->flags & ARGS_ARE_WORDS )
489 subglyph->arg1 = FT_NEXT_SHORT( p );
490 subglyph->arg2 = FT_NEXT_SHORT( p );
494 subglyph->arg1 = FT_NEXT_CHAR( p );
495 subglyph->arg2 = FT_NEXT_CHAR( p );
502 if ( subglyph->flags & WE_HAVE_A_SCALE )
504 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
507 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
509 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
510 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
512 else if ( subglyph->flags & WE_HAVE_A_2X2 )
514 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
515 yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
516 xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
517 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
520 subglyph->transform.xx = xx;
521 subglyph->transform.xy = xy;
522 subglyph->transform.yx = yx;
523 subglyph->transform.yy = yy;
527 } while ( subglyph->flags & MORE_COMPONENTS );
529 gloader->current.num_subglyphs = num_subglyphs;
531 #ifdef TT_USE_BYTECODE_INTERPRETER
534 FT_Stream stream = loader->stream;
537 /* we must undo the FT_FRAME_ENTER in order to point to the */
538 /* composite instructions, if we find some. */
539 /* we will process them later... */
541 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
553 error = TT_Err_Invalid_Composite;
559 TT_Init_Glyph_Loading( TT_Face face )
561 face->access_glyph_frame = TT_Access_Glyph_Frame;
562 face->read_glyph_header = TT_Load_Glyph_Header;
563 face->read_simple_glyph = TT_Load_Simple_Glyph;
564 face->read_composite_glyph = TT_Load_Composite_Glyph;
565 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
570 tt_prepare_zone( TT_GlyphZone zone,
573 FT_UInt start_contour )
575 zone->n_points = (FT_UShort)( load->outline.n_points - start_point );
576 zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour );
577 zone->org = load->extra_points + start_point;
578 zone->cur = load->outline.points + start_point;
579 zone->orus = load->extra_points2 + start_point;
580 zone->tags = (FT_Byte*)load->outline.tags + start_point;
581 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
582 zone->first_point = (FT_UShort)start_point;
586 /*************************************************************************/
592 /* Hint the glyph using the zone prepared by the caller. Note that */
593 /* the zone is supposed to include four phantom points. */
596 TT_Hint_Glyph( TT_Loader loader,
597 FT_Bool is_composite )
599 TT_GlyphZone zone = &loader->zone;
602 #ifdef TT_USE_BYTECODE_INTERPRETER
605 FT_UNUSED( is_composite );
609 #ifdef TT_USE_BYTECODE_INTERPRETER
610 n_ins = loader->glyph->control_len;
613 origin = zone->cur[zone->n_points - 4].x;
614 origin = FT_PIX_ROUND( origin ) - origin;
616 translate_array( zone->n_points, zone->cur, origin, 0 );
618 #ifdef TT_USE_BYTECODE_INTERPRETER
619 /* save original point position in org */
621 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
624 /* round pp2 and pp4 */
625 zone->cur[zone->n_points - 3].x =
626 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
627 zone->cur[zone->n_points - 1].y =
628 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
630 #ifdef TT_USE_BYTECODE_INTERPRETER
638 error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
639 loader->exec->glyphIns, n_ins );
643 loader->exec->is_composite = is_composite;
644 loader->exec->pts = *zone;
646 debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
647 ((TT_Size)loader->size)->debug );
649 error = TT_Run_Context( loader->exec, debug );
650 if ( error && loader->exec->pedantic_hinting )
656 /* save glyph phantom points */
657 if ( !loader->preserve_pps )
659 loader->pp1 = zone->cur[zone->n_points - 4];
660 loader->pp2 = zone->cur[zone->n_points - 3];
661 loader->pp3 = zone->cur[zone->n_points - 2];
662 loader->pp4 = zone->cur[zone->n_points - 1];
669 /*************************************************************************/
672 /* TT_Process_Simple_Glyph */
675 /* Once a simple glyph has been loaded, it needs to be processed. */
676 /* Usually, this means scaling and hinting through bytecode */
677 /* interpretation. */
680 TT_Process_Simple_Glyph( TT_Loader loader )
682 FT_GlyphLoader gloader = loader->gloader;
683 FT_Error error = TT_Err_Ok;
688 outline = &gloader->current.outline;
689 n_points = outline->n_points;
691 /* set phantom points */
693 outline->points[n_points ] = loader->pp1;
694 outline->points[n_points + 1] = loader->pp2;
695 outline->points[n_points + 2] = loader->pp3;
696 outline->points[n_points + 3] = loader->pp4;
698 outline->tags[n_points ] = 0;
699 outline->tags[n_points + 1] = 0;
700 outline->tags[n_points + 2] = 0;
701 outline->tags[n_points + 3] = 0;
705 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
707 if ( ((TT_Face)loader->face)->doblend )
709 /* Deltas apply to the unscaled data. */
711 FT_Memory memory = loader->face->memory;
715 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
722 for ( i = 0; i < n_points; ++i )
724 outline->points[i].x += deltas[i].x;
725 outline->points[i].y += deltas[i].y;
731 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
733 if ( IS_HINTED( loader->load_flags ) )
735 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
737 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
738 loader->zone.n_points + 4 );
741 /* scale the glyph */
742 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
744 FT_Vector* vec = outline->points;
745 FT_Vector* limit = outline->points + n_points;
746 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
747 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
750 for ( ; vec < limit; vec++ )
752 vec->x = FT_MulFix( vec->x, x_scale );
753 vec->y = FT_MulFix( vec->y, y_scale );
756 loader->pp1 = outline->points[n_points - 4];
757 loader->pp2 = outline->points[n_points - 3];
758 loader->pp3 = outline->points[n_points - 2];
759 loader->pp4 = outline->points[n_points - 1];
762 if ( IS_HINTED( loader->load_flags ) )
764 loader->zone.n_points += 4;
766 error = TT_Hint_Glyph( loader, 0 );
773 /*************************************************************************/
776 /* TT_Process_Composite_Component */
779 /* Once a composite component has been loaded, it needs to be */
780 /* processed. Usually, this means transforming and translating. */
783 TT_Process_Composite_Component( TT_Loader loader,
784 FT_SubGlyph subglyph,
786 FT_UInt num_base_points )
788 FT_GlyphLoader gloader = loader->gloader;
789 FT_Vector* base_vec = gloader->base.outline.points;
790 FT_UInt num_points = gloader->base.outline.n_points;
795 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
796 WE_HAVE_AN_XY_SCALE |
799 /* perform the transform required for this subglyph */
805 for ( i = num_base_points; i < num_points; i++ )
806 FT_Vector_Transform( base_vec + i, &subglyph->transform );
810 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
812 FT_UInt k = subglyph->arg1;
813 FT_UInt l = subglyph->arg2;
818 /* match l-th point of the newly loaded component to the k-th point */
819 /* of the previously loaded components. */
821 /* change to the point numbers used by our outline */
823 l += num_base_points;
824 if ( k >= num_base_points ||
826 return TT_Err_Invalid_Composite;
828 p1 = gloader->base.outline.points + k;
829 p2 = gloader->base.outline.points + l;
842 /* Use a default value dependent on */
843 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */
844 /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */
847 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
848 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
850 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
856 /*************************************************************************/
858 /* This algorithm is what Apple documents. But it doesn't work. */
860 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
861 : -subglyph->transform.xx;
862 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
863 : -subglyph->transform.yx;
864 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
865 : -subglyph->transform.xy;
866 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
867 : -subglyph->transform.yy;
868 int m = a > b ? a : b;
869 int n = c > d ? c : d;
872 if ( a - b <= 33 && a - b >= -33 )
874 if ( c - d <= 33 && c - d >= -33 )
876 x = FT_MulFix( x, m );
877 y = FT_MulFix( y, n );
881 /*************************************************************************/
883 /* This algorithm is a guess and works much better than the above. */
885 FT_Fixed mac_xscale = FT_SqrtFixed(
886 FT_MulFix( subglyph->transform.xx,
887 subglyph->transform.xx ) +
888 FT_MulFix( subglyph->transform.xy,
889 subglyph->transform.xy ) );
890 FT_Fixed mac_yscale = FT_SqrtFixed(
891 FT_MulFix( subglyph->transform.yy,
892 subglyph->transform.yy ) +
893 FT_MulFix( subglyph->transform.yx,
894 subglyph->transform.yx ) );
897 x = FT_MulFix( x, mac_xscale );
898 y = FT_MulFix( y, mac_yscale );
904 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
906 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
907 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
910 x = FT_MulFix( x, x_scale );
911 y = FT_MulFix( y, y_scale );
913 if ( subglyph->flags & ROUND_XY_TO_GRID )
915 x = FT_PIX_ROUND( x );
916 y = FT_PIX_ROUND( y );
922 translate_array( num_points - num_base_points,
923 base_vec + num_base_points,
930 /*************************************************************************/
933 /* TT_Process_Composite_Glyph */
936 /* This is slightly different from TT_Process_Simple_Glyph, in that */
937 /* its sole purpose is to hint the glyph. Thus this function is */
938 /* only available when bytecode interpreter is enabled. */
941 TT_Process_Composite_Glyph( TT_Loader loader,
943 FT_UInt start_contour )
950 outline = &loader->gloader->base.outline;
952 /* make room for phantom points */
953 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
954 outline->n_points + 4,
959 outline->points[outline->n_points ] = loader->pp1;
960 outline->points[outline->n_points + 1] = loader->pp2;
961 outline->points[outline->n_points + 2] = loader->pp3;
962 outline->points[outline->n_points + 3] = loader->pp4;
964 outline->tags[outline->n_points ] = 0;
965 outline->tags[outline->n_points + 1] = 0;
966 outline->tags[outline->n_points + 2] = 0;
967 outline->tags[outline->n_points + 3] = 0;
969 #ifdef TT_USE_BYTECODE_INTERPRETER
972 FT_Stream stream = loader->stream;
976 /* TT_Load_Composite_Glyph only gives us the offset of instructions */
977 /* so we read them here */
978 if ( FT_STREAM_SEEK( loader->ins_pos ) ||
979 FT_READ_USHORT( n_ins ) )
982 FT_TRACE5(( " Instructions size = %d\n", n_ins ));
985 if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions )
987 FT_TRACE0(( "Too many instructions (%d)\n", n_ins ));
989 return TT_Err_Too_Many_Hints;
991 else if ( n_ins == 0 )
994 if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
997 loader->glyph->control_data = loader->exec->glyphIns;
998 loader->glyph->control_len = n_ins;
1003 tt_prepare_zone( &loader->zone, &loader->gloader->base,
1004 start_point, start_contour );
1006 /* Some points are likely touched during execution of */
1007 /* instructions on components. So let's untouch them. */
1008 for ( i = start_point; i < loader->zone.n_points; i++ )
1009 loader->zone.tags[i] &= ~( FT_CURVE_TAG_TOUCH_X |
1010 FT_CURVE_TAG_TOUCH_Y );
1012 loader->zone.n_points += 4;
1014 return TT_Hint_Glyph( loader, 1 );
1018 /* Calculate the four phantom points. */
1019 /* The first two stand for horizontal origin and advance. */
1020 /* The last two stand for vertical origin and advance. */
1021 #define TT_LOADER_SET_PP( loader ) \
1023 (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
1024 (loader)->pp1.y = 0; \
1025 (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
1026 (loader)->pp2.y = 0; \
1027 (loader)->pp3.x = 0; \
1028 (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \
1029 (loader)->pp4.x = 0; \
1030 (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
1034 /*************************************************************************/
1037 /* load_truetype_glyph */
1040 /* Loads a given truetype glyph. Handles composites and uses a */
1041 /* TT_Loader object. */
1044 load_truetype_glyph( TT_Loader loader,
1045 FT_UInt glyph_index,
1046 FT_UInt recurse_count )
1049 FT_Fixed x_scale, y_scale;
1051 TT_Face face = (TT_Face)loader->face;
1052 FT_GlyphLoader gloader = loader->gloader;
1053 FT_Bool opened_frame = 0;
1055 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1056 FT_Vector* deltas = NULL;
1059 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1060 FT_StreamRec inc_stream;
1062 FT_Bool glyph_data_loaded = 0;
1066 if ( recurse_count > face->max_profile.maxComponentDepth )
1068 error = TT_Err_Invalid_Composite;
1072 /* check glyph index */
1073 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
1075 error = TT_Err_Invalid_Glyph_Index;
1079 loader->glyph_index = glyph_index;
1081 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1083 x_scale = ((TT_Size)loader->size)->metrics.x_scale;
1084 y_scale = ((TT_Size)loader->size)->metrics.y_scale;
1092 /* get metrics, horizontal and vertical */
1094 FT_Short left_bearing = 0, top_bearing = 0;
1095 FT_UShort advance_width = 0, advance_height = 0;
1098 Get_HMetrics( face, glyph_index,
1099 (FT_Bool)!( loader->load_flags &
1100 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
1103 Get_VMetrics( face, glyph_index,
1104 (FT_Bool)!( loader->load_flags &
1105 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
1109 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1111 /* If this is an incrementally loaded font see if there are */
1112 /* overriding metrics for this glyph. */
1113 if ( face->root.internal->incremental_interface &&
1114 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
1116 FT_Incremental_MetricsRec metrics;
1119 metrics.bearing_x = left_bearing;
1120 metrics.bearing_y = 0;
1121 metrics.advance = advance_width;
1122 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
1123 face->root.internal->incremental_interface->object,
1124 glyph_index, FALSE, &metrics );
1127 left_bearing = (FT_Short)metrics.bearing_x;
1128 advance_width = (FT_UShort)metrics.advance;
1132 /* GWW: Do I do the same for vertical metrics? */
1133 metrics.bearing_x = 0;
1134 metrics.bearing_y = top_bearing;
1135 metrics.advance = advance_height;
1136 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
1137 face->root.internal->incremental_interface->object,
1138 glyph_index, TRUE, &metrics );
1141 top_bearing = (FT_Short)metrics.bearing_y;
1142 advance_height = (FT_UShort)metrics.advance;
1148 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1150 loader->left_bearing = left_bearing;
1151 loader->advance = advance_width;
1152 loader->top_bearing = top_bearing;
1153 loader->vadvance = advance_height;
1155 if ( !loader->linear_def )
1157 loader->linear_def = 1;
1158 loader->linear = advance_width;
1162 /* Set `offset' to the start of the glyph relative to the start of */
1163 /* the `glyf' table, and `byte_len' to the length of the glyph in */
1166 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1168 /* If we are loading glyph data via the incremental interface, set */
1169 /* the loader stream to a memory stream reading the data returned */
1170 /* by the interface. */
1171 if ( face->root.internal->incremental_interface )
1173 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1174 face->root.internal->incremental_interface->object,
1175 glyph_index, &glyph_data );
1179 glyph_data_loaded = 1;
1181 loader->byte_len = glyph_data.length;
1183 FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
1184 FT_Stream_OpenMemory( &inc_stream,
1185 glyph_data.pointer, glyph_data.length );
1187 loader->stream = &inc_stream;
1191 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1193 offset = tt_face_get_location( face, glyph_index,
1194 (FT_UInt*)&loader->byte_len );
1196 if ( loader->byte_len == 0 )
1198 /* as described by Frederic Loyer, these are spaces or */
1199 /* the unknown glyph. */
1200 loader->bbox.xMin = 0;
1201 loader->bbox.xMax = 0;
1202 loader->bbox.yMin = 0;
1203 loader->bbox.yMax = 0;
1205 TT_LOADER_SET_PP( loader );
1207 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1209 if ( ((TT_Face)(loader->face))->doblend )
1211 /* this must be done before scaling */
1212 FT_Memory memory = loader->face->memory;
1215 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
1216 glyph_index, &deltas, 4 );
1220 loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
1221 loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
1222 loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
1223 loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
1230 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1232 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1233 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1234 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1235 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1242 error = face->access_glyph_frame( loader, glyph_index,
1243 loader->glyf_offset + offset,
1250 /* read first glyph header */
1251 error = face->read_glyph_header( loader );
1255 TT_LOADER_SET_PP( loader );
1257 /***********************************************************************/
1258 /***********************************************************************/
1259 /***********************************************************************/
1261 /* if it is a simple glyph, load it */
1263 if ( loader->n_contours >= 0 )
1265 error = face->read_simple_glyph( loader );
1269 /* all data have been read */
1270 face->forget_glyph_frame( loader );
1273 error = TT_Process_Simple_Glyph( loader );
1277 FT_GlyphLoader_Add( gloader );
1280 /***********************************************************************/
1281 /***********************************************************************/
1282 /***********************************************************************/
1284 /* otherwise, load a composite! */
1285 else if ( loader->n_contours == -1 )
1287 FT_UInt start_point;
1288 FT_UInt start_contour;
1289 FT_ULong ins_pos; /* position of composite instructions, if any */
1292 start_point = gloader->base.outline.n_points;
1293 start_contour = gloader->base.outline.n_contours;
1295 /* for each subglyph, read composite header */
1296 error = face->read_composite_glyph( loader );
1300 /* store the offset of instructions */
1301 ins_pos = loader->ins_pos;
1303 /* all data we need are read */
1304 face->forget_glyph_frame( loader );
1307 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1309 if ( face->doblend )
1312 FT_SubGlyph subglyph;
1313 FT_Memory memory = face->root.memory;
1316 /* this provides additional offsets */
1317 /* for each component's translation */
1319 if ( (error = TT_Vary_Get_Glyph_Deltas(
1323 gloader->current.num_subglyphs + 4 )) != 0 )
1326 subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
1327 limit = gloader->current.num_subglyphs;
1329 for ( i = 0; i < limit; ++i, ++subglyph )
1331 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1333 subglyph->arg1 += deltas[i].x;
1334 subglyph->arg2 += deltas[i].y;
1338 loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
1339 loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
1340 loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
1341 loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
1346 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1348 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1350 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1351 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1352 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1353 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1356 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
1357 /* `as is' in the glyph slot (the client application will be */
1358 /* responsible for interpreting these data)... */
1360 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1362 FT_GlyphLoader_Add( gloader );
1363 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
1368 /*********************************************************************/
1369 /*********************************************************************/
1370 /*********************************************************************/
1373 FT_UInt n, num_base_points;
1374 FT_SubGlyph subglyph = 0;
1376 FT_UInt num_points = start_point;
1377 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
1378 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
1381 FT_GlyphLoader_Add( gloader );
1383 /* read each subglyph independently */
1384 for ( n = 0; n < num_subglyphs; n++ )
1389 /* Each time we call load_truetype_glyph in this loop, the */
1390 /* value of `gloader.base.subglyphs' can change due to table */
1391 /* reallocations. We thus need to recompute the subglyph */
1392 /* pointer on each iteration. */
1393 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1395 pp[0] = loader->pp1;
1396 pp[1] = loader->pp2;
1397 pp[2] = loader->pp3;
1398 pp[3] = loader->pp4;
1400 num_base_points = gloader->base.outline.n_points;
1402 error = load_truetype_glyph( loader, subglyph->index,
1403 recurse_count + 1 );
1407 /* restore subglyph pointer */
1408 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1410 if ( !( subglyph->flags & USE_MY_METRICS ) )
1412 loader->pp1 = pp[0];
1413 loader->pp2 = pp[1];
1414 loader->pp3 = pp[2];
1415 loader->pp4 = pp[3];
1418 num_points = gloader->base.outline.n_points;
1420 if ( num_points == num_base_points )
1423 /* gloader->base.outline consists of three part: */
1424 /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
1426 /* (1): exist from the beginning */
1427 /* (2): components that have been loaded so far */
1428 /* (3): the newly loaded component */
1429 TT_Process_Composite_Component( loader, subglyph, start_point,
1434 /* process the glyph */
1435 loader->ins_pos = ins_pos;
1436 if ( IS_HINTED( loader->load_flags ) &&
1438 #ifdef TT_USE_BYTECODE_INTERPRETER
1440 subglyph->flags & WE_HAVE_INSTR &&
1444 num_points > start_point )
1445 TT_Process_Composite_Glyph( loader, start_point, start_contour );
1451 /* invalid composite count ( negative but not -1 ) */
1452 error = TT_Err_Invalid_Outline;
1456 /***********************************************************************/
1457 /***********************************************************************/
1458 /***********************************************************************/
1463 face->forget_glyph_frame( loader );
1465 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1467 if ( glyph_data_loaded )
1468 face->root.internal->incremental_interface->funcs->free_glyph_data(
1469 face->root.internal->incremental_interface->object,
1479 compute_glyph_metrics( TT_Loader loader,
1480 FT_UInt glyph_index )
1483 TT_Face face = (TT_Face)loader->face;
1485 TT_GlyphSlot glyph = loader->glyph;
1486 TT_Size size = (TT_Size)loader->size;
1490 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1491 y_scale = size->root.metrics.y_scale;
1493 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
1494 FT_Outline_Get_CBox( &glyph->outline, &bbox );
1496 bbox = loader->bbox;
1498 /* get the device-independent horizontal advance. It is scaled later */
1499 /* by the base layer. */
1501 FT_Pos advance = loader->linear;
1504 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1505 /* correctly support DynaLab fonts, which have an incorrect */
1506 /* `advance_Width_Max' field! It is used, to my knowledge, */
1507 /* exclusively in the X-TrueType font server. */
1509 if ( face->postscript.isFixedPitch &&
1510 ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
1511 advance = face->horizontal.advance_Width_Max;
1513 /* we need to return the advance in font units in linearHoriAdvance, */
1514 /* it will be scaled later by the base layer. */
1515 glyph->linearHoriAdvance = advance;
1518 glyph->metrics.horiBearingX = bbox.xMin;
1519 glyph->metrics.horiBearingY = bbox.yMax;
1520 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
1522 /* Now take care of vertical metrics. In the case where there is */
1523 /* no vertical information within the font (relatively common), make */
1524 /* up some metrics by `hand'... */
1527 FT_Pos top; /* scaled vertical top side bearing */
1528 FT_Pos advance; /* scaled vertical advance height */
1531 /* Get the unscaled top bearing and advance height. */
1532 if ( face->vertical_info &&
1533 face->vertical.number_Of_VMetrics > 0 )
1535 top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
1538 if ( loader->pp3.y <= loader->pp4.y )
1541 advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
1549 /* XXX Compute top side bearing and advance height in */
1550 /* Get_VMetrics instead of here. */
1552 /* NOTE: The OS/2 values are the only `portable' ones, */
1553 /* which is why we use them, if there is an OS/2 */
1554 /* table in the font. Otherwise, we use the */
1555 /* values defined in the horizontal header. */
1557 height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
1559 if ( face->os2.version != 0xFFFFU )
1560 advance = (FT_Pos)( face->os2.sTypoAscender -
1561 face->os2.sTypoDescender );
1563 advance = (FT_Pos)( face->horizontal.Ascender -
1564 face->horizontal.Descender );
1566 top = ( advance - height ) / 2;
1569 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1571 FT_Incremental_InterfaceRec* incr;
1572 FT_Incremental_MetricsRec metrics;
1576 incr = face->root.internal->incremental_interface;
1578 /* If this is an incrementally loaded font see if there are */
1579 /* overriding metrics for this glyph. */
1580 if ( incr && incr->funcs->get_glyph_metrics )
1582 metrics.bearing_x = 0;
1583 metrics.bearing_y = top;
1584 metrics.advance = advance;
1586 error = incr->funcs->get_glyph_metrics( incr->object,
1593 top = metrics.bearing_y;
1594 advance = metrics.advance;
1598 /* GWW: Do vertical metrics get loaded incrementally too? */
1600 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1602 glyph->linearVertAdvance = advance;
1604 /* scale the metrics */
1605 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1607 top = FT_MulFix( top, y_scale );
1608 advance = FT_MulFix( advance, y_scale );
1611 /* XXX: for now, we have no better algorithm for the lsb, but it */
1612 /* should work fine. */
1614 glyph->metrics.vertBearingX = ( bbox.xMin - bbox.xMax ) / 2;
1615 glyph->metrics.vertBearingY = top;
1616 glyph->metrics.vertAdvance = advance;
1619 /* adjust advance width to the value contained in the hdmx table */
1620 if ( !face->postscript.isFixedPitch &&
1621 IS_HINTED( loader->load_flags ) )
1626 widthp = tt_face_get_device_metrics( face,
1627 size->root.metrics.x_ppem,
1631 glyph->metrics.horiAdvance = *widthp << 6;
1634 /* set glyph dimensions */
1635 glyph->metrics.width = bbox.xMax - bbox.xMin;
1636 glyph->metrics.height = bbox.yMax - bbox.yMin;
1642 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1645 load_sbit_image( TT_Size size,
1647 FT_UInt glyph_index,
1648 FT_Int32 load_flags )
1654 TT_SBit_MetricsRec metrics;
1657 face = (TT_Face)glyph->face;
1658 sfnt = (SFNT_Service)face->sfnt;
1659 stream = face->root.stream;
1661 error = sfnt->load_sbit_image( face,
1670 glyph->outline.n_points = 0;
1671 glyph->outline.n_contours = 0;
1673 glyph->metrics.width = (FT_Pos)metrics.width << 6;
1674 glyph->metrics.height = (FT_Pos)metrics.height << 6;
1676 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1677 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1678 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
1680 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1681 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1682 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
1684 glyph->format = FT_GLYPH_FORMAT_BITMAP;
1685 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1687 glyph->bitmap_left = metrics.vertBearingX;
1688 glyph->bitmap_top = metrics.vertBearingY;
1692 glyph->bitmap_left = metrics.horiBearingX;
1693 glyph->bitmap_top = metrics.horiBearingY;
1700 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1704 tt_loader_init( TT_Loader loader,
1707 FT_Int32 load_flags )
1713 face = (TT_Face)glyph->face;
1714 stream = face->root.stream;
1716 FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
1718 #ifdef TT_USE_BYTECODE_INTERPRETER
1720 /* load execution context */
1721 if ( IS_HINTED( load_flags ) )
1723 TT_ExecContext exec;
1727 if ( !size->cvt_ready )
1729 FT_Error error = tt_size_ready_bytecode( size );
1734 /* query new execution context */
1735 exec = size->debug ? size->context
1736 : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
1738 return TT_Err_Could_Not_Find_Context;
1741 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
1743 TT_Load_Context( exec, face, size );
1745 /* a change from mono to grayscale rendering (and vice versa) */
1746 /* requires a re-execution of the CVT program */
1747 if ( grayscale != exec->grayscale )
1752 exec->grayscale = grayscale;
1754 for ( i = 0; i < size->cvt_size; i++ )
1755 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
1756 tt_size_run_prep( size );
1759 /* see if the cvt program has disabled hinting */
1760 if ( exec->GS.instruct_control & 1 )
1761 load_flags |= FT_LOAD_NO_HINTING;
1763 /* load default graphics state - if needed */
1764 if ( exec->GS.instruct_control & 2 )
1765 exec->GS = tt_default_graphics_state;
1767 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
1768 loader->exec = exec;
1769 loader->instructions = exec->glyphIns;
1772 #endif /* TT_USE_BYTECODE_INTERPRETER */
1774 /* seek to the beginning of the glyph table. For Type 42 fonts */
1775 /* the table might be accessed from a Postscript stream or something */
1778 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1780 if ( face->root.internal->incremental_interface )
1781 loader->glyf_offset = 0;
1787 FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 );
1792 FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
1795 loader->glyf_offset = FT_STREAM_POS();
1798 /* get face's glyph loader */
1800 FT_GlyphLoader gloader = glyph->internal->loader;
1803 FT_GlyphLoader_Rewind( gloader );
1804 loader->gloader = gloader;
1807 loader->load_flags = load_flags;
1809 loader->face = (FT_Face)face;
1810 loader->size = (FT_Size)size;
1811 loader->glyph = (FT_GlyphSlot)glyph;
1812 loader->stream = stream;
1818 /*************************************************************************/
1824 /* A function used to load a single glyph within a given glyph slot, */
1825 /* for a given size. */
1828 /* glyph :: A handle to a target slot object where the glyph */
1829 /* will be loaded. */
1831 /* size :: A handle to the source face size at which the glyph */
1832 /* must be scaled/loaded. */
1834 /* glyph_index :: The index of the glyph in the font file. */
1836 /* load_flags :: A flag indicating what to load for this glyph. The */
1837 /* FT_LOAD_XXX constants can be used to control the */
1838 /* glyph loading process (e.g., whether the outline */
1839 /* should be scaled, whether to load bitmaps or not, */
1840 /* whether to hint the outline, etc). */
1843 /* FreeType error code. 0 means success. */
1845 FT_LOCAL_DEF( FT_Error )
1846 TT_Load_Glyph( TT_Size size,
1848 FT_UInt glyph_index,
1849 FT_Int32 load_flags )
1854 TT_LoaderRec loader;
1857 face = (TT_Face)glyph->face;
1858 stream = face->root.stream;
1861 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1863 /* try to load embedded bitmap if any */
1865 /* XXX: The convention should be emphasized in */
1866 /* the documents because it can be confusing. */
1867 if ( size->strike_index != 0xFFFFFFFFUL &&
1868 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
1870 error = load_sbit_image( size, glyph, glyph_index, load_flags );
1875 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1877 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
1878 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
1879 return TT_Err_Invalid_Size_Handle;
1881 if ( load_flags & FT_LOAD_SBITS_ONLY )
1882 return TT_Err_Invalid_Argument;
1884 error = tt_loader_init( &loader, size, glyph, load_flags );
1888 glyph->format = FT_GLYPH_FORMAT_OUTLINE;
1889 glyph->num_subglyphs = 0;
1890 glyph->outline.flags = 0;
1892 /* Main loading loop */
1893 error = load_truetype_glyph( &loader, glyph_index, 0 );
1896 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
1898 glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
1899 glyph->subglyphs = loader.gloader->base.subglyphs;
1903 glyph->outline = loader.gloader->base.outline;
1904 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
1906 /* In case bit 1 of the `flags' field in the `head' table isn't */
1907 /* set, translate array so that (0,0) is the glyph's origin. */
1908 if ( ( face->header.Flags & 2 ) == 0 && loader.pp1.x )
1909 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
1912 compute_glyph_metrics( &loader, glyph_index );
1915 /* Set the `high precision' bit flag. */
1916 /* This is _critical_ to get correct output for monochrome */
1917 /* TrueType glyphs at all sizes using the bytecode interpreter. */
1919 if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
1920 size->root.metrics.y_ppem < 24 )
1921 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;