21#include FT_CONFIG_CONFIG_H
33#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
47#define FT_COMPONENT ttgload
54#define ON_CURVE_POINT 0x01
55#define X_SHORT_VECTOR 0x02
56#define Y_SHORT_VECTOR 0x04
57#define REPEAT_FLAG 0x08
58#define X_POSITIVE 0x10
60#define Y_POSITIVE 0x20
62#define OVERLAP_SIMPLE 0x40
69#define ARGS_ARE_WORDS 0x0001
70#define ARGS_ARE_XY_VALUES 0x0002
71#define ROUND_XY_TO_GRID 0x0004
72#define WE_HAVE_A_SCALE 0x0008
74#define MORE_COMPONENTS 0x0020
75#define WE_HAVE_AN_XY_SCALE 0x0040
76#define WE_HAVE_A_2X2 0x0080
77#define WE_HAVE_INSTR 0x0100
78#define USE_MY_METRICS 0x0200
79#define OVERLAP_COMPOUND 0x0400
80#define SCALED_COMPONENT_OFFSET 0x0800
81#define UNSCALED_COMPONENT_OFFSET 0x1000
84#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
85#define IS_DEFAULT_INSTANCE( _face ) \
86 ( !( FT_IS_NAMED_INSTANCE( _face ) || \
87 FT_IS_VARIATION( _face ) ) )
89#define IS_DEFAULT_INSTANCE( _face ) 1
98 TT_Get_HMetrics( TT_Face face,
103 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
105 FT_TRACE5((
" advance width (font units): %d\n", *aw ));
106 FT_TRACE5((
" left side bearing (font units): %d\n", *lsb ));
116 TT_Get_VMetrics( TT_Face face,
122 if ( face->vertical_info )
123 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
125 else if ( face->os2.version != 0xFFFFU )
127 *tsb = (FT_Short)( face->os2.sTypoAscender - yMax );
128 *ah = (FT_UShort)FT_ABS( face->os2.sTypoAscender -
129 face->os2.sTypoDescender );
134 *tsb = (FT_Short)( face->horizontal.Ascender - yMax );
135 *ah = (FT_UShort)FT_ABS( face->horizontal.Ascender -
136 face->horizontal.Descender );
139#ifdef FT_DEBUG_LEVEL_TRACE
140 if ( !face->vertical_info )
141 FT_TRACE5((
" [vertical metrics missing, computing values]\n" ));
144 FT_TRACE5((
" advance height (font units): %d\n", *ah ));
145 FT_TRACE5((
" top side bearing (font units): %d\n", *tsb ));
150 tt_get_metrics( TT_Loader loader,
151 FT_UInt glyph_index )
153 TT_Face face = loader->face;
156 FT_Stream stream = loader->stream;
158 FT_Short left_bearing = 0, top_bearing = 0;
159 FT_UShort advance_width = 0, advance_height = 0;
163 FT_ULong pos = FT_STREAM_POS();
166 TT_Get_HMetrics( face, glyph_index,
169 TT_Get_VMetrics( face, glyph_index,
174 if ( FT_STREAM_SEEK( pos ) )
177 loader->left_bearing = left_bearing;
178 loader->advance = advance_width;
179 loader->top_bearing = top_bearing;
180 loader->vadvance = advance_height;
182#ifdef FT_CONFIG_OPTION_INCREMENTAL
185 if ( face->root.internal->incremental_interface == NULL )
188 if ( !loader->linear_def )
190 loader->linear_def = 1;
191 loader->linear = advance_width;
199#ifdef FT_CONFIG_OPTION_INCREMENTAL
202 tt_get_metrics_incremental( TT_Loader loader,
203 FT_UInt glyph_index )
205 TT_Face face = loader->face;
207 FT_Short left_bearing = 0, top_bearing = 0;
208 FT_UShort advance_width = 0, advance_height = 0;
213 if ( face->root.internal->incremental_interface &&
214 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
216 FT_Incremental_MetricsRec incr_metrics;
220 incr_metrics.bearing_x = loader->left_bearing;
221 incr_metrics.bearing_y = 0;
222 incr_metrics.advance = loader->advance;
223 incr_metrics.advance_v = 0;
225 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
226 face->root.internal->incremental_interface->object,
227 glyph_index, FALSE, &incr_metrics );
231 left_bearing = (FT_Short)incr_metrics.bearing_x;
232 advance_width = (FT_UShort)incr_metrics.advance;
237 incr_metrics.bearing_x = 0;
238 incr_metrics.bearing_y = loader->top_bearing;
239 incr_metrics.advance = loader->vadvance;
241 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
242 face->root.internal->incremental_interface->object,
243 glyph_index, TRUE, &incr_metrics );
247 top_bearing = (FT_Short)incr_metrics.bearing_y;
248 advance_height = (FT_UShort)incr_metrics.advance;
252 loader->left_bearing = left_bearing;
253 loader->advance = advance_width;
254 loader->top_bearing = top_bearing;
255 loader->vadvance = advance_height;
257 if ( !loader->linear_def )
259 loader->linear_def = 1;
260 loader->linear = advance_width;
279 FT_CALLBACK_DEF( FT_Error )
280 TT_Access_Glyph_Frame( TT_Loader loader,
286 FT_Stream stream = loader->stream;
288 FT_UNUSED( glyph_index );
292 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
295 loader->cursor = stream->cursor;
296 loader->limit = stream->limit;
302 FT_CALLBACK_DEF(
void )
303 TT_Forget_Glyph_Frame( TT_Loader loader )
305 FT_Stream stream = loader->stream;
312 FT_CALLBACK_DEF( FT_Error )
313 TT_Load_Glyph_Header( TT_Loader loader )
315 FT_Byte* p = loader->cursor;
316 FT_Byte* limit = loader->limit;
319 if ( p + 10 > limit )
320 return FT_THROW( Invalid_Outline );
322 loader->n_contours = FT_NEXT_SHORT( p );
324 loader->bbox.xMin = FT_NEXT_SHORT( p );
325 loader->bbox.yMin = FT_NEXT_SHORT( p );
326 loader->bbox.xMax = FT_NEXT_SHORT( p );
327 loader->bbox.yMax = FT_NEXT_SHORT( p );
329 FT_TRACE5((
" # of contours: %d\n", loader->n_contours ));
330 FT_TRACE5((
" xMin: %4ld xMax: %4ld\n", loader->bbox.xMin,
331 loader->bbox.xMax ));
332 FT_TRACE5((
" yMin: %4ld yMax: %4ld\n", loader->bbox.yMin,
333 loader->bbox.yMax ));
340 FT_CALLBACK_DEF( FT_Error )
341 TT_Load_Simple_Glyph( TT_Loader load )
344 FT_Byte* p = load->cursor;
345 FT_Byte* limit = load->limit;
346 FT_GlyphLoader gloader = load->gloader;
347 FT_Outline* outline = &gloader->current.outline;
348 FT_Int n_contours = load->n_contours;
352 FT_Byte *flag, *flag_limit;
354 FT_Vector *vec, *vec_limit;
356 FT_UShort *cont, *cont_limit;
361 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
366 if ( n_contours >= 0xFFF || p + 2 * n_contours + 2 > limit )
367 goto Invalid_Outline;
370 cont = outline->contours;
371 cont_limit = cont + n_contours;
374 for ( ; cont < cont_limit; cont++ )
376 *cont = FT_NEXT_USHORT( p );
379 goto Invalid_Outline;
386 FT_TRACE5((
" # of points: %d\n", n_points ));
389 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
394 n_ins = FT_NEXT_USHORT( p );
396 FT_TRACE5((
" Instructions size: %u\n", n_ins ));
399 if ( p + n_ins > limit )
401 FT_TRACE1((
"TT_Load_Simple_Glyph: excessive instruction count\n" ));
402 error = FT_THROW( Too_Many_Hints );
406#ifdef TT_USE_BYTECODE_INTERPRETER
408 if ( IS_HINTED( load->load_flags ) )
410 TT_ExecContext exec = load->exec;
411 FT_Memory memory = exec->memory;
414 if ( exec->glyphSize )
415 FT_FREE( exec->glyphIns );
422 if ( FT_DUP( exec->glyphIns, p, n_ins ) )
425 exec->glyphSize = n_ins;
434 flag = outline->tags;
435 flag_limit = flag + n_points;
439 while ( flag < flag_limit )
442 goto Invalid_Outline;
444 *flag++ = c = FT_NEXT_BYTE( p );
445 if ( c & REPEAT_FLAG )
448 goto Invalid_Outline;
450 count = FT_NEXT_BYTE( p );
451 if ( flag + (FT_Int)count > flag_limit )
452 goto Invalid_Outline;
454 for ( ; count > 0; count-- )
460 if ( n_points && outline->tags[0] & OVERLAP_SIMPLE )
461 gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
465 vec = outline->points;
466 vec_limit = vec + n_points;
467 flag = outline->tags;
470 for ( ; vec < vec_limit; vec++, flag++ )
476 if ( f & X_SHORT_VECTOR )
479 goto Invalid_Outline;
481 delta = (FT_Pos)FT_NEXT_BYTE( p );
482 if ( !( f & X_POSITIVE ) )
485 else if ( !( f & SAME_X ) )
488 goto Invalid_Outline;
490 delta = (FT_Pos)FT_NEXT_SHORT( p );
499 vec = outline->points;
500 vec_limit = vec + n_points;
501 flag = outline->tags;
504 for ( ; vec < vec_limit; vec++, flag++ )
510 if ( f & Y_SHORT_VECTOR )
513 goto Invalid_Outline;
515 delta = (FT_Pos)FT_NEXT_BYTE( p );
516 if ( !( f & Y_POSITIVE ) )
519 else if ( !( f & SAME_Y ) )
522 goto Invalid_Outline;
524 delta = (FT_Pos)FT_NEXT_SHORT( p );
531 *flag = (FT_Byte)( f & ON_CURVE_POINT );
534 outline->n_points = (FT_UShort)n_points;
535 outline->n_contours = (FT_UShort)n_contours;
543 error = FT_THROW( Invalid_Outline );
548 FT_CALLBACK_DEF( FT_Error )
549 TT_Load_Composite_Glyph( TT_Loader loader )
552 FT_Byte* p = loader->cursor;
553 FT_Byte* limit = loader->limit;
554 FT_GlyphLoader gloader = loader->gloader;
555 FT_Long num_glyphs = loader->face->root.num_glyphs;
556 FT_SubGlyph subglyph;
557 FT_UInt num_subglyphs;
564 FT_Fixed xx, xy, yy, yx;
569 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
575 goto Invalid_Composite;
577 subglyph = gloader->current.subglyphs + num_subglyphs;
579 subglyph->arg1 = subglyph->arg2 = 0;
581 subglyph->flags = FT_NEXT_USHORT( p );
582 subglyph->index = FT_NEXT_USHORT( p );
586 if ( subglyph->index >= num_glyphs )
587 goto Invalid_Composite;
591 if ( subglyph->flags & ARGS_ARE_WORDS )
593 if ( subglyph->flags & WE_HAVE_A_SCALE )
595 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
597 else if ( subglyph->flags & WE_HAVE_A_2X2 )
600 if ( p + count > limit )
601 goto Invalid_Composite;
604 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
606 if ( subglyph->flags & ARGS_ARE_WORDS )
608 subglyph->arg1 = FT_NEXT_SHORT( p );
609 subglyph->arg2 = FT_NEXT_SHORT( p );
613 subglyph->arg1 = FT_NEXT_CHAR( p );
614 subglyph->arg2 = FT_NEXT_CHAR( p );
619 if ( subglyph->flags & ARGS_ARE_WORDS )
621 subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p );
622 subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p );
626 subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p );
627 subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p );
635 if ( subglyph->flags & WE_HAVE_A_SCALE )
637 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
640 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
642 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
643 yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
645 else if ( subglyph->flags & WE_HAVE_A_2X2 )
647 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
648 yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
649 xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
650 yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
653 subglyph->transform.xx = xx;
654 subglyph->transform.xy = xy;
655 subglyph->transform.yx = yx;
656 subglyph->transform.yy = yy;
660 }
while ( subglyph->flags & MORE_COMPONENTS );
662 gloader->current.num_subglyphs = num_subglyphs;
663 FT_TRACE5((
" %u component%s\n",
665 num_subglyphs > 1 ?
"s" :
"" ));
667#ifdef FT_DEBUG_LEVEL_TRACE
672 subglyph = gloader->current.subglyphs;
674 for ( i = 0; i < num_subglyphs; i++ )
676 if ( num_subglyphs > 1 )
677 FT_TRACE7((
" subglyph %u:\n", i ));
679 FT_TRACE7((
" glyph index: %d\n", subglyph->index ));
681 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
682 FT_TRACE7((
" offset: x=%d, y=%d\n",
686 FT_TRACE7((
" matching points: base=%d, component=%d\n",
690 if ( subglyph->flags & WE_HAVE_A_SCALE )
691 FT_TRACE7((
" scaling: %f\n",
692 (
double)subglyph->transform.xx / 65536 ));
693 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
694 FT_TRACE7((
" scaling: x=%f, y=%f\n",
695 (
double)subglyph->transform.xx / 65536,
696 (
double)subglyph->transform.yy / 65536 ));
697 else if ( subglyph->flags & WE_HAVE_A_2X2 )
699 FT_TRACE7((
" scaling: xx=%f, yx=%f\n",
700 (
double)subglyph->transform.xx / 65536,
701 (
double)subglyph->transform.yx / 65536 ));
702 FT_TRACE7((
" xy=%f, yy=%f\n",
703 (
double)subglyph->transform.xy / 65536,
704 (
double)subglyph->transform.yy / 65536 ));
712#ifdef TT_USE_BYTECODE_INTERPRETER
715 FT_Stream stream = loader->stream;
722 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
734 error = FT_THROW( Invalid_Composite );
740 TT_Init_Glyph_Loading( TT_Face face )
742 face->access_glyph_frame = TT_Access_Glyph_Frame;
743 face->read_glyph_header = TT_Load_Glyph_Header;
744 face->read_simple_glyph = TT_Load_Simple_Glyph;
745 face->read_composite_glyph = TT_Load_Composite_Glyph;
746 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
751 tt_prepare_zone( TT_GlyphZone zone,
754 FT_UInt start_contour )
756 zone->n_points = load->outline.n_points + 4 - (FT_UShort)start_point;
757 zone->n_contours = load->outline.n_contours - (FT_UShort)start_contour;
758 zone->org = load->extra_points + start_point;
759 zone->cur = load->outline.points + start_point;
760 zone->orus = load->extra_points2 + start_point;
761 zone->tags = load->outline.tags + start_point;
762 zone->contours = load->outline.contours + start_contour;
763 zone->first_point = (FT_UShort)start_point;
777 TT_Hint_Glyph( TT_Loader loader,
778 FT_Bool is_composite )
780 TT_GlyphZone zone = &loader->zone;
782#ifdef TT_USE_BYTECODE_INTERPRETER
783 TT_ExecContext exec = loader->exec;
784 TT_Size size = loader->size;
785 FT_Long n_ins = exec->glyphSize;
787 FT_UNUSED( is_composite );
791#ifdef TT_USE_BYTECODE_INTERPRETER
794 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
800 exec->metrics.x_scale = 1 << 16;
801 exec->metrics.y_scale = 1 << 16;
803 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
807 exec->metrics.x_scale = size->metrics->x_scale;
808 exec->metrics.y_scale = size->metrics->y_scale;
813 zone->cur[zone->n_points - 4].x =
814 FT_PIX_ROUND( zone->cur[zone->n_points - 4].x );
815 zone->cur[zone->n_points - 3].x =
816 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
817 zone->cur[zone->n_points - 2].y =
818 FT_PIX_ROUND( zone->cur[zone->n_points - 2].y );
819 zone->cur[zone->n_points - 1].y =
820 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
822#ifdef TT_USE_BYTECODE_INTERPRETER
829 TT_Set_CodeRange( exec, tt_coderange_glyph, exec->glyphIns, n_ins );
831 exec->is_composite = is_composite;
834 error = TT_Run_Context( exec, size );
835 if ( error && exec->pedantic_hinting )
839 loader->gloader->current.outline.tags[0] |=
840 ( exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
849#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
850 if ( exec->backward_compatibility )
854 loader->pp1 = zone->cur[zone->n_points - 4];
855 loader->pp2 = zone->cur[zone->n_points - 3];
856 loader->pp3 = zone->cur[zone->n_points - 2];
857 loader->pp4 = zone->cur[zone->n_points - 1];
874 TT_Process_Simple_Glyph( TT_Loader loader )
876 FT_Error error = FT_Err_Ok;
877 FT_GlyphLoader gloader = loader->gloader;
878 FT_Outline* outline = &gloader->current.outline;
879 FT_Int n_points = outline->n_points;
881#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
882 FT_Memory memory = loader->face->root.memory;
883 FT_Vector* unrounded = NULL;
888 outline->points[n_points ] = loader->pp1;
889 outline->points[n_points + 1] = loader->pp2;
890 outline->points[n_points + 2] = loader->pp3;
891 outline->points[n_points + 3] = loader->pp4;
895#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
897 if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
899 if ( FT_QNEW_ARRAY( unrounded, n_points ) )
903 error = TT_Vary_Apply_Glyph_Deltas( loader,
912 if ( IS_HINTED( loader->load_flags ) )
914 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
916 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
917 loader->zone.n_points );
921 FT_Vector* vec = outline->points;
922 FT_Vector* limit = outline->points + n_points;
924 FT_Fixed x_scale = 0;
925 FT_Fixed y_scale = 0;
927 FT_Bool do_scale = FALSE;
932 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
934 x_scale = loader->size->metrics->x_scale;
935 y_scale = loader->size->metrics->y_scale;
943#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
944 if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
946 FT_Vector* u = unrounded;
949 for ( ; vec < limit; vec++, u++ )
951 vec->x = ADD_LONG( FT_MulFix( u->x, x_scale ), 32 ) >> 6;
952 vec->y = ADD_LONG( FT_MulFix( u->y, y_scale ), 32 ) >> 6;
958 for ( ; vec < limit; vec++ )
960 vec->x = FT_MulFix( vec->x, x_scale );
961 vec->y = FT_MulFix( vec->y, y_scale );
966#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
969 if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) &&
970 IS_HINTED( loader->load_flags ) )
972 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
973 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
979 loader->pp1 = outline->points[n_points - 4];
980 loader->pp2 = outline->points[n_points - 3];
983#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
986 if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) &&
987 IS_HINTED( loader->load_flags ) )
989 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
990 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
991 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
992 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
997 loader->pp3 = outline->points[n_points - 2];
998 loader->pp4 = outline->points[n_points - 1];
1002 if ( IS_HINTED( loader->load_flags ) )
1003 error = TT_Hint_Glyph( loader, 0 );
1005#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1007 FT_FREE( unrounded );
1024 TT_Process_Composite_Component( TT_Loader loader,
1025 FT_SubGlyph subglyph,
1026 FT_UInt start_point,
1027 FT_UInt num_base_points )
1029 FT_GlyphLoader gloader = loader->gloader;
1035 current.points = gloader->base.outline.points +
1037 current.n_points = gloader->base.outline.n_points -
1038 (FT_UShort)num_base_points;
1040 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
1041 WE_HAVE_AN_XY_SCALE |
1046 FT_Outline_Transform( ¤t, &subglyph->transform );
1049 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
1051 FT_UInt num_points = gloader->base.outline.n_points;
1052 FT_UInt k = (FT_UInt)subglyph->arg1;
1053 FT_UInt l = (FT_UInt)subglyph->arg2;
1063 l += num_base_points;
1064 if ( k >= num_base_points ||
1066 return FT_THROW( Invalid_Composite );
1068 p1 = gloader->base.outline.points + k;
1069 p2 = gloader->base.outline.points + l;
1071 x = SUB_LONG( p1->x, p2->x );
1072 y = SUB_LONG( p1->y, p2->y );
1087#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
1088 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
1090 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
1100 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
1101 : -subglyph->transform.xx;
1102 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
1103 : -subglyph->transform.yx;
1104 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
1105 : -subglyph->transform.xy;
1106 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
1107 : -subglyph->transform.yy;
1108 int m = a > b ? a : b;
1109 int n = c > d ? c : d;
1112 if ( a - b <= 33 && a - b >= -33 )
1114 if ( c - d <= 33 && c - d >= -33 )
1116 x = FT_MulFix( x, m );
1117 y = FT_MulFix( y, n );
1125 FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx,
1126 subglyph->transform.xy );
1127 FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy,
1128 subglyph->transform.yx );
1131 x = FT_MulFix( x, mac_xscale );
1132 y = FT_MulFix( y, mac_yscale );
1138 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1140 FT_Fixed x_scale = loader->size->metrics->x_scale;
1141 FT_Fixed y_scale = loader->size->metrics->y_scale;
1144 x = FT_MulFix( x, x_scale );
1145 y = FT_MulFix( y, y_scale );
1147 if ( subglyph->flags & ROUND_XY_TO_GRID &&
1148 IS_HINTED( loader->load_flags ) )
1150#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1151 if ( !loader->exec->backward_compatibility )
1153 x = FT_PIX_ROUND( x );
1155 y = FT_PIX_ROUND( y );
1161 FT_Outline_Translate( ¤t, x, y );
1178 TT_Process_Composite_Glyph( TT_Loader loader,
1179 FT_UInt start_point,
1180 FT_UInt start_contour )
1183 FT_Outline* outline = &loader->gloader->base.outline;
1188 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
1189 outline->n_points + 4,
1194 outline->points[outline->n_points ] = loader->pp1;
1195 outline->points[outline->n_points + 1] = loader->pp2;
1196 outline->points[outline->n_points + 2] = loader->pp3;
1197 outline->points[outline->n_points + 3] = loader->pp4;
1199#ifdef TT_USE_BYTECODE_INTERPRETER
1202 TT_ExecContext exec = loader->exec;
1203 FT_Memory memory = exec->memory;
1204 FT_Stream stream = loader->stream;
1208 if ( exec->glyphSize )
1209 FT_FREE( exec->glyphIns );
1210 exec->glyphSize = 0;
1214 if ( FT_STREAM_SEEK( loader->ins_pos ) ||
1215 FT_READ_USHORT( n_ins ) )
1218 FT_TRACE5((
" Instructions size = %hu\n", n_ins ));
1225 if ( n_ins > loader->byte_len )
1227 FT_TRACE1((
"TT_Process_Composite_Glyph:"
1228 " too many instructions (%hu) for glyph with length %u\n",
1229 n_ins, loader->byte_len ));
1230 return FT_THROW( Too_Many_Hints );
1233 if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) ||
1234 FT_STREAM_READ( exec->glyphIns, n_ins ) )
1237 exec->glyphSize = n_ins;
1242 tt_prepare_zone( &loader->zone, &loader->gloader->base,
1243 start_point, start_contour );
1247 for ( i = 0; i < loader->zone.n_points - 4U; i++ )
1248 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
1250 return TT_Hint_Glyph( loader, 1 );
1339 tt_loader_set_pp( TT_Loader loader )
1341 loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
1343 loader->pp2.x = loader->pp1.x + loader->advance;
1347 loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
1349 loader->pp4.y = loader->pp3.y - loader->vadvance;
1351#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1353 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
1356 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
1358 loader->exec->mode != FT_RENDER_MODE_MONO &&
1359 loader->exec->mode != FT_RENDER_MODE_LCD &&
1360 loader->exec->mode != FT_RENDER_MODE_LCD_V )
1362 loader->pp3.x = loader->advance / 2;
1363 loader->pp4.x = loader->advance / 2;
1372 ft_list_get_node_at( FT_List list,
1381 for ( cur = list->head; cur; cur = cur->next )
1403 load_truetype_glyph( TT_Loader loader,
1404 FT_UInt glyph_index,
1405 FT_UInt recurse_count,
1406 FT_Bool header_only )
1408 FT_Error error = FT_Err_Ok;
1409 FT_Fixed x_scale, y_scale;
1411 TT_Face face = loader->face;
1412 FT_GlyphLoader gloader = loader->gloader;
1414 FT_Bool opened_frame = 0;
1416#ifdef FT_CONFIG_OPTION_INCREMENTAL
1417 FT_StreamRec inc_stream;
1419 FT_Bool glyph_data_loaded = 0;
1423#ifdef FT_DEBUG_LEVEL_TRACE
1424 if ( recurse_count )
1425 FT_TRACE5((
" nesting level: %u\n", recurse_count ));
1429 if ( recurse_count > face->max_profile.maxComponentDepth )
1431 FT_TRACE1((
"load_truetype_glyph: maxComponentDepth set to %u\n",
1433 face->max_profile.maxComponentDepth = (FT_UShort)recurse_count;
1436#ifndef FT_CONFIG_OPTION_INCREMENTAL
1438 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
1440 error = FT_THROW( Invalid_Glyph_Index );
1445 loader->glyph_index = glyph_index;
1447 if ( loader->load_flags & FT_LOAD_NO_SCALE )
1454 x_scale = loader->size->metrics->x_scale;
1455 y_scale = loader->size->metrics->y_scale;
1462#ifdef FT_CONFIG_OPTION_INCREMENTAL
1467 if ( face->root.internal->incremental_interface )
1469 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1470 face->root.internal->incremental_interface->object,
1471 glyph_index, &glyph_data );
1475 glyph_data_loaded = 1;
1477 loader->byte_len = glyph_data.length;
1479 FT_ZERO( &inc_stream );
1480 FT_Stream_OpenMemory( &inc_stream,
1482 glyph_data.length );
1484 loader->stream = &inc_stream;
1493 offset = tt_face_get_location( FT_FACE( face ), glyph_index, &len );
1495 loader->byte_len = (FT_UInt)len;
1498 if ( loader->byte_len > 0 )
1500#ifdef FT_CONFIG_OPTION_INCREMENTAL
1502 if ( !face->glyf_offset &&
1503 !face->root.internal->incremental_interface )
1505 if ( !face->glyf_offset )
1508 FT_TRACE2((
"no `glyf' table but non-zero `loca' entry\n" ));
1509 error = FT_THROW( Invalid_Table );
1513 error = face->access_glyph_frame( loader, glyph_index,
1514 face->glyf_offset + offset,
1520 error = face->read_glyph_header( loader );
1522 face->forget_glyph_frame( loader );
1529 if ( loader->byte_len == 0 || loader->n_contours == 0 )
1531 loader->bbox.xMin = 0;
1532 loader->bbox.xMax = 0;
1533 loader->bbox.yMin = 0;
1534 loader->bbox.yMax = 0;
1540 error = tt_get_metrics( loader, glyph_index );
1547#ifdef FT_CONFIG_OPTION_INCREMENTAL
1548 tt_get_metrics_incremental( loader, glyph_index );
1550 tt_loader_set_pp( loader );
1553 if ( loader->byte_len == 0 || loader->n_contours == 0 )
1556#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1558 if ( !IS_DEFAULT_INSTANCE( FT_FACE( face ) ) )
1562 FT_Vector points[4];
1566 FT_Vector unrounded[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1569 points[0] = loader->pp1;
1570 points[1] = loader->pp2;
1571 points[2] = loader->pp3;
1572 points[3] = loader->pp4;
1574 outline.n_points = 0;
1575 outline.n_contours = 0;
1576 outline.points = points;
1577 outline.tags = NULL;
1578 outline.contours = NULL;
1581 error = TT_Vary_Apply_Glyph_Deltas( loader,
1592 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1594 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1595 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1598 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1599 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1600 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1601 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1615 error = face->access_glyph_frame( loader, glyph_index,
1616 face->glyf_offset + offset + 10,
1617 loader->byte_len - 10 );
1625 if ( loader->n_contours > 0 )
1627 error = face->read_simple_glyph( loader );
1632 face->forget_glyph_frame( loader );
1635 error = TT_Process_Simple_Glyph( loader );
1639 FT_GlyphLoader_Add( gloader );
1647 else if ( loader->n_contours < 0 )
1649 FT_Memory memory = face->root.memory;
1651 FT_UInt start_point;
1652 FT_UInt start_contour;
1655 FT_ListNode node, node2;
1659 loader->n_contours = -1;
1669 node = ft_list_get_node_at( &loader->composites, recurse_count );
1670 for ( node2 = node; node2; node2 = node2->next )
1671 node2->data = (
void*)-1;
1674 if ( FT_List_Find( &loader->composites,
1675 FT_UINT_TO_POINTER( glyph_index ) ) )
1677 FT_TRACE1((
"TT_Load_Composite_Glyph:"
1678 " infinite recursion detected\n" ));
1679 error = FT_THROW( Invalid_Composite );
1684 node->data = FT_UINT_TO_POINTER( glyph_index );
1688 if ( FT_QNEW( node ) )
1690 node->data = FT_UINT_TO_POINTER( glyph_index );
1691 FT_List_Add( &loader->composites, node );
1694 start_point = gloader->base.outline.n_points;
1695 start_contour = gloader->base.outline.n_contours;
1698 error = face->read_composite_glyph( loader );
1703 ins_pos = loader->ins_pos;
1706 face->forget_glyph_frame( loader );
1709#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1711 if ( !IS_DEFAULT_INSTANCE( FT_FACE( face ) ) )
1714 FT_SubGlyph subglyph;
1716 FT_Outline outline = { 0, 0, NULL, NULL, NULL, 0 };
1717 FT_Vector* unrounded = NULL;
1720 limit = (FT_UShort)gloader->current.num_subglyphs;
1724 if ( FT_QNEW_ARRAY( outline.points, limit + 4 ) ||
1725 FT_QNEW_ARRAY( outline.tags, limit ) ||
1726 FT_QNEW_ARRAY( outline.contours, limit ) ||
1727 FT_QNEW_ARRAY( unrounded, limit + 4 ) )
1730 outline.n_contours = outline.n_points = limit;
1732 subglyph = gloader->current.subglyphs;
1734 for ( i = 0; i < limit; i++, subglyph++ )
1739 outline.points[i].x = subglyph->arg1;
1740 outline.points[i].y = subglyph->arg2;
1741 outline.tags[i] = ON_CURVE_POINT;
1742 outline.contours[i] = i;
1745 outline.points[i++] = loader->pp1;
1746 outline.points[i++] = loader->pp2;
1747 outline.points[i++] = loader->pp3;
1748 outline.points[i ] = loader->pp4;
1752 if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas( loader,
1757 subglyph = gloader->current.subglyphs;
1759 for ( i = 0; i < limit; i++, subglyph++ )
1761 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1763 subglyph->arg1 = (FT_Int16)outline.points[i].x;
1764 subglyph->arg2 = (FT_Int16)outline.points[i].y;
1769 FT_FREE( outline.points );
1770 FT_FREE( outline.tags );
1771 FT_FREE( outline.contours );
1772 FT_FREE( unrounded );
1782 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1784 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1785 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1788 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1789 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1790 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1791 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1797 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1799 FT_GlyphLoader_Add( gloader );
1800 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
1810 FT_UInt n, num_base_points;
1811 FT_SubGlyph subglyph = NULL;
1813 FT_UInt num_points = start_point;
1814 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
1815 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
1817 FT_Stream old_stream = loader->stream;
1818 FT_UInt old_byte_len = loader->byte_len;
1821 FT_GlyphLoader_Add( gloader );
1824 for ( n = 0; n < num_subglyphs; n++ )
1828 FT_Int linear_hadvance;
1829 FT_Int linear_vadvance;
1836 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1838 pp[0] = loader->pp1;
1839 pp[1] = loader->pp2;
1840 pp[2] = loader->pp3;
1841 pp[3] = loader->pp4;
1843 linear_hadvance = loader->linear;
1844 linear_vadvance = loader->vadvance;
1846 num_base_points = gloader->base.outline.n_points;
1848 error = load_truetype_glyph( loader,
1849 (FT_UInt)subglyph->index,
1856 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1859 if ( !( subglyph->flags & USE_MY_METRICS ) )
1861 loader->pp1 = pp[0];
1862 loader->pp2 = pp[1];
1863 loader->pp3 = pp[2];
1864 loader->pp4 = pp[3];
1866 loader->linear = linear_hadvance;
1867 loader->vadvance = linear_vadvance;
1870 num_points = gloader->base.outline.n_points;
1872 if ( num_points == num_base_points )
1883 error = TT_Process_Composite_Component( loader,
1891 loader->stream = old_stream;
1892 loader->byte_len = old_byte_len;
1895 loader->ins_pos = ins_pos;
1896 if ( IS_HINTED( loader->load_flags ) &&
1897#ifdef TT_USE_BYTECODE_INTERPRETER
1899 subglyph->flags & WE_HAVE_INSTR &&
1901 num_points > start_point )
1903 error = TT_Process_Composite_Glyph( loader,
1912 if ( gloader->base.num_subglyphs &&
1913 gloader->base.subglyphs[0].flags & OVERLAP_COMPOUND )
1914 gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
1924 face->forget_glyph_frame( loader );
1926#ifdef FT_CONFIG_OPTION_INCREMENTAL
1929 loader->stream = face->root.stream;
1931 if ( glyph_data_loaded )
1932 face->root.internal->incremental_interface->funcs->free_glyph_data(
1933 face->root.internal->incremental_interface->object,
1943 compute_glyph_metrics( TT_Loader loader,
1944 FT_UInt glyph_index )
1946 TT_Face face = loader->face;
1947 TT_Size size = loader->size;
1948 TT_GlyphSlot glyph = loader->glyph;
1954 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1955 y_scale = size->metrics->y_scale;
1957 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
1958 FT_Outline_Get_CBox( &glyph->outline, &bbox );
1960 bbox = loader->bbox;
1964 glyph->linearHoriAdvance = loader->linear;
1966 glyph->metrics.horiBearingX = bbox.xMin;
1967 glyph->metrics.horiBearingY = bbox.yMax;
1968 if ( loader->widthp )
1969 glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64;
1971 glyph->metrics.horiAdvance = SUB_LONG( loader->pp2.x, loader->pp1.x );
1974 glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin );
1975 glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin );
1986 if ( face->vertical_info &&
1987 face->vertical.number_Of_VMetrics > 0 )
1989 top = (FT_Short)FT_DivFix( SUB_LONG( loader->pp3.y, bbox.yMax ),
1992 if ( loader->pp3.y <= loader->pp4.y )
1995 advance = (FT_UShort)FT_DivFix( SUB_LONG( loader->pp3.y,
2012 height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax,
2015 if ( face->os2.version != 0xFFFFU )
2016 advance = (FT_Pos)( face->os2.sTypoAscender -
2017 face->os2.sTypoDescender );
2019 advance = (FT_Pos)( face->horizontal.Ascender -
2020 face->horizontal.Descender );
2022 top = ( advance - height ) / 2;
2025#ifdef FT_CONFIG_OPTION_INCREMENTAL
2027 FT_Incremental_InterfaceRec* incr;
2028 FT_Incremental_MetricsRec incr_metrics;
2032 incr = face->root.internal->incremental_interface;
2036 if ( incr && incr->funcs->get_glyph_metrics )
2038 incr_metrics.bearing_x = 0;
2039 incr_metrics.bearing_y = top;
2040 incr_metrics.advance = advance;
2042 error = incr->funcs->get_glyph_metrics( incr->object,
2049 top = incr_metrics.bearing_y;
2050 advance = incr_metrics.advance;
2058 glyph->linearVertAdvance = advance;
2061 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
2063 top = FT_MulFix( top, y_scale );
2064 advance = FT_MulFix( advance, y_scale );
2070 glyph->metrics.vertBearingX = SUB_LONG( glyph->metrics.horiBearingX,
2071 glyph->metrics.horiAdvance / 2 );
2072 glyph->metrics.vertBearingY = top;
2073 glyph->metrics.vertAdvance = advance;
2080#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2083 load_sbit_image( TT_Size size,
2085 FT_UInt glyph_index,
2086 FT_Int32 load_flags )
2088 TT_Face face = (TT_Face)glyph->face;
2089 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
2091 TT_SBit_MetricsRec sbit_metrics;
2094 error = sfnt->load_sbit_image( face,
2097 (FT_UInt)load_flags,
2103 glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64;
2104 glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64;
2106 glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64;
2107 glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64;
2108 glyph->metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64;
2110 glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64;
2111 glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64;
2112 glyph->metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64;
2114 glyph->format = FT_GLYPH_FORMAT_BITMAP;
2116 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2118 glyph->bitmap_left = sbit_metrics.vertBearingX;
2119 glyph->bitmap_top = sbit_metrics.vertBearingY;
2123 glyph->bitmap_left = sbit_metrics.horiBearingX;
2124 glyph->bitmap_top = sbit_metrics.horiBearingY;
2130 else if ( FT_ERR_EQ( error, Missing_Bitmap ) &&
2131 !FT_IS_SCALABLE( glyph->face ) &&
2132 face->horz_metrics_size )
2134 FT_Fixed x_scale = size->root.metrics.x_scale;
2135 FT_Fixed y_scale = size->root.metrics.y_scale;
2137 FT_Short left_bearing = 0;
2138 FT_Short top_bearing = 0;
2140 FT_UShort advance_width = 0;
2141 FT_UShort advance_height = 0;
2144 TT_Get_HMetrics( face, glyph_index,
2147 TT_Get_VMetrics( face, glyph_index,
2152 glyph->metrics.width = 0;
2153 glyph->metrics.height = 0;
2155 glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale );
2156 glyph->metrics.horiBearingY = 0;
2157 glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale );
2159 glyph->metrics.vertBearingX = 0;
2160 glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale );
2161 glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale );
2163 glyph->format = FT_GLYPH_FORMAT_BITMAP;
2164 glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
2166 glyph->bitmap_left = 0;
2167 glyph->bitmap_top = 0;
2179 tt_loader_init( TT_Loader loader,
2182 FT_Int32 load_flags,
2183 FT_Bool glyf_table_only )
2185 TT_Face face = (TT_Face)glyph->face;
2190#ifdef TT_USE_BYTECODE_INTERPRETER
2193 if ( IS_HINTED( load_flags ) && !glyf_table_only )
2196 TT_ExecContext exec;
2197 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
2198 FT_Bool grayscale = FT_BOOL( mode != FT_RENDER_MODE_MONO );
2199 FT_Bool reexecute = FALSE;
2200#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2201 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face );
2205 if ( size->bytecode_ready > 0 )
2206 return size->bytecode_ready;
2207 if ( size->bytecode_ready < 0 )
2209 FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2212 error = tt_size_init_bytecode( size, pedantic );
2217 exec = size->context;
2219#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2220 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2225 if ( mode != exec->mode )
2227 FT_TRACE4((
"tt_loader_init: render mode change,"
2228 " re-executing `prep' table\n" ));
2238 if ( grayscale != exec->grayscale )
2240 FT_TRACE4((
"tt_loader_init: grayscale hinting change,"
2241 " re-executing `prep' table\n" ));
2243 exec->grayscale = grayscale;
2247 if ( size->cvt_ready > 0 )
2248 return size->cvt_ready;
2249 if ( size->cvt_ready < 0 || reexecute )
2251 error = tt_size_run_prep( size );
2256 error = TT_Load_Context( exec, face, size );
2261 if ( size->GS.instruct_control & 1 )
2262 load_flags |= FT_LOAD_NO_HINTING;
2265 if ( size->GS.instruct_control & 2 )
2266 size->GS = tt_default_graphics_state;
2268#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2282 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
2283 mode != FT_RENDER_MODE_MONO &&
2284 !FT_IS_TRICKY( glyph->face ) )
2285 exec->backward_compatibility = ( size->GS.instruct_control & 4 ) ^ 4;
2287 exec->backward_compatibility = 0;
2290 loader->exec = exec;
2296 if ( IS_HINTED( load_flags ) &&
2297 !( load_flags & FT_LOAD_COMPUTE_METRICS ) &&
2298#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2299 !exec->backward_compatibility &&
2301 !face->postscript.isFixedPitch )
2303 loader->widthp = size->widthp;
2306 loader->widthp = NULL;
2312 if ( !glyf_table_only )
2314 FT_GlyphLoader gloader = glyph->internal->loader;
2317 FT_GlyphLoader_Rewind( gloader );
2318 loader->gloader = gloader;
2321 loader->load_flags = (FT_ULong)load_flags;
2323 loader->face = face;
2324 loader->size = size;
2325 loader->glyph = (FT_GlyphSlot)glyph;
2326 loader->stream = face->root.stream;
2328 loader->composites.head = NULL;
2329 loader->composites.tail = NULL;
2336 tt_loader_done( TT_Loader loader )
2338 FT_List_Finalize( &loader->composites,
2340 loader->face->root.memory,
2377 FT_LOCAL_DEF( FT_Error )
2378 TT_Load_Glyph( TT_Size size,
2380 FT_UInt glyph_index,
2381 FT_Int32 load_flags )
2383 TT_Face face = (TT_Face)glyph->face;
2385 TT_LoaderRec loader;
2388 FT_TRACE1((
"TT_Load_Glyph: glyph index %u\n", glyph_index ));
2390#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2393 if ( size->strike_index != 0xFFFFFFFFUL &&
2394 !( load_flags & FT_LOAD_NO_BITMAP &&
2395 FT_IS_SCALABLE( glyph->face ) ) &&
2396 IS_DEFAULT_INSTANCE( glyph->face ) )
2398 error = load_sbit_image( size, glyph, glyph_index, load_flags );
2401 if ( FT_IS_SCALABLE( glyph->face ) ||
2402 FT_HAS_SBIX( glyph->face ) )
2404 FT_Fixed x_scale = size->root.metrics.x_scale;
2405 FT_Fixed y_scale = size->root.metrics.y_scale;
2409 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
2410 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
2411 tt_loader_done( &loader );
2412 glyph->linearHoriAdvance = loader.linear;
2413 glyph->linearVertAdvance = loader.vadvance;
2420 if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX &&
2421 loader.n_contours > 0 )
2427 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2431 bitmap_left = loader.bbox.xMin;
2432 bitmap_top = loader.top_bearing;
2436 bitmap_left = loader.left_bearing;
2437 bitmap_top = loader.bbox.yMin;
2440 glyph->bitmap_left += FT_MulFix( bitmap_left, x_scale ) >> 6;
2441 glyph->bitmap_top += FT_MulFix( bitmap_top, y_scale ) >> 6;
2446 if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
2447 glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance,
2449 if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
2450 glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance,
2456 else if ( !FT_IS_SCALABLE( glyph->face ) )
2460 if ( load_flags & FT_LOAD_SBITS_ONLY )
2462 error = FT_THROW( Invalid_Argument );
2469 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.ppem )
2471 error = FT_THROW( Invalid_Size_Handle );
2475#ifdef FT_CONFIG_OPTION_SVG
2478 if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 &&
2479 ( load_flags & FT_LOAD_COLOR ) &&
2482 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
2485 FT_TRACE3((
"Trying to load SVG glyph\n" ));
2487 error = sfnt->load_svg_doc( glyph, glyph_index );
2490 FT_Fixed x_scale = size->root.metrics.x_scale;
2491 FT_Fixed y_scale = size->root.metrics.y_scale;
2493 FT_Short leftBearing;
2494 FT_Short topBearing;
2499 FT_TRACE3((
"Successfully loaded SVG glyph\n" ));
2501 glyph->format = FT_GLYPH_FORMAT_SVG;
2503 sfnt->get_metrics( face,
2508 sfnt->get_metrics( face,
2514 glyph->linearHoriAdvance = advanceX;
2515 glyph->linearVertAdvance = advanceY;
2517 glyph->metrics.horiAdvance = FT_MulFix( advanceX, x_scale );
2518 glyph->metrics.vertAdvance = FT_MulFix( advanceY, y_scale );
2523 FT_TRACE3((
"Failed to load SVG glyph\n" ));
2527 if ( load_flags & FT_LOAD_SVG_ONLY )
2529 error = FT_THROW( Invalid_Argument );
2535 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
2540 if ( load_flags & FT_LOAD_ADVANCE_ONLY &&
2541 !( load_flags & FT_LOAD_VERTICAL_LAYOUT ) &&
2544 glyph->metrics.horiAdvance = loader.widthp[glyph_index] * 64;
2549 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
2552 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
2554 glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
2555 glyph->subglyphs = loader.gloader->base.subglyphs;
2559 glyph->format = FT_GLYPH_FORMAT_OUTLINE;
2561 glyph->outline = loader.gloader->base.outline;
2562 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
2567 if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
2568 size->metrics->y_ppem < 24 )
2569 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
2576 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
2579#ifdef TT_USE_BYTECODE_INTERPRETER
2581 if ( IS_HINTED( load_flags ) )
2583 glyph->control_data = loader.exec->glyphIns;
2584 glyph->control_len = loader.exec->glyphSize;
2586 if ( loader.exec->GS.scan_control )
2589 switch ( loader.exec->GS.scan_type )
2592 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
2598 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
2599 FT_OUTLINE_INCLUDE_STUBS;
2602 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
2606 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2611 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2616 error = compute_glyph_metrics( &loader, glyph_index );
2619 FT_TRACE1((
" subglyphs = %u, contours = %hu, points = %hu,"
2620 " flags = 0x%.3x\n",
2621 loader.gloader->base.num_subglyphs,
2622 glyph->outline.n_contours,
2623 glyph->outline.n_points,
2624 glyph->outline.flags ));
2627 tt_loader_done( &loader );
2630 FT_TRACE1(( error ?
" failed (error code 0x%x)\n" :
"",