1 /****************************************************************************
5 * TrueType Glyph Loader (body).
7 * Copyright (C) 1996-2023 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.
20 #include <freetype/internal/ftdebug.h>
21 #include FT_CONFIG_CONFIG_H
22 #include <freetype/internal/ftcalc.h>
23 #include <freetype/internal/ftstream.h>
24 #include <freetype/internal/sfnt.h>
25 #include <freetype/tttags.h>
26 #include <freetype/ftoutln.h>
27 #include <freetype/ftdriver.h>
28 #include <freetype/ftlist.h>
33 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
40 /**************************************************************************
42 * The macro FT_COMPONENT is used in trace mode. It is an implicit
43 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
44 * messages during execution.
47 #define FT_COMPONENT ttgload
50 /**************************************************************************
54 #define ON_CURVE_POINT 0x01 /* same value as FT_CURVE_TAG_ON */
55 #define X_SHORT_VECTOR 0x02
56 #define Y_SHORT_VECTOR 0x04
57 #define REPEAT_FLAG 0x08
58 #define X_POSITIVE 0x10 /* two meanings depending on X_SHORT_VECTOR */
60 #define Y_POSITIVE 0x20 /* two meanings depending on Y_SHORT_VECTOR */
62 #define OVERLAP_SIMPLE 0x40 /* retained as FT_OUTLINE_OVERLAP */
65 /**************************************************************************
67 * Composite glyph flags.
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 /* retained as FT_OUTLINE_OVERLAP */
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
93 /**************************************************************************
95 * Return the horizontal metrics in font units for a given glyph.
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 ));
110 /**************************************************************************
112 * Return the vertical metrics in font units for a given glyph.
113 * See function `tt_loader_set_pp' below for explanations.
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;
161 /* we must preserve the stream position */
162 /* (which gets altered by the metrics functions) */
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
183 /* With the incremental interface, these values are set by */
184 /* a call to `tt_get_metrics_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;
211 /* If this is an incrementally loaded font check whether there are */
212 /* overriding metrics for this glyph. */
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;
236 /* GWW: Do I do the same for vertical metrics? */
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;
268 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
271 /**************************************************************************
273 * The following functions are used by default with TrueType fonts.
274 * However, they can be replaced by alternatives if we need to support
275 * TrueType-compressed formats (like MicroType) in the future.
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 );
291 /* the following line sets the `error' variable through macros! */
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_Short *cont, *cont_limit, last;
359 /* check that we can add the contours to the glyph */
360 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
364 /* check space for contours array + instructions count */
365 if ( n_contours >= 0xFFF || p + 2 * n_contours + 2 > limit )
366 goto Invalid_Outline;
368 /* reading the contours' endpoints & number of points */
369 cont = outline->contours;
370 cont_limit = cont + n_contours;
373 for ( ; cont < cont_limit; cont++ )
375 *cont = FT_NEXT_SHORT( p );
378 goto Invalid_Outline;
385 FT_TRACE5(( " # of points: %d\n", n_points ));
387 /* note that we will add four phantom points later */
388 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
392 /* space checked above */
393 n_ins = FT_NEXT_USHORT( p );
395 FT_TRACE5(( " Instructions size: %u\n", n_ins ));
397 /* check instructions size */
398 if ( p + n_ins > limit )
400 FT_TRACE1(( "TT_Load_Simple_Glyph: excessive instruction count\n" ));
401 error = FT_THROW( Too_Many_Hints );
405 #ifdef TT_USE_BYTECODE_INTERPRETER
407 if ( IS_HINTED( load->load_flags ) )
409 TT_ExecContext exec = load->exec;
410 FT_Memory memory = exec->memory;
413 if ( exec->glyphSize )
414 FT_FREE( exec->glyphIns );
417 /* we don't trust `maxSizeOfInstructions' in the `maxp' table */
418 /* and thus allocate the bytecode array size by ourselves */
421 if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) )
424 FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins );
426 exec->glyphSize = n_ins;
430 #endif /* TT_USE_BYTECODE_INTERPRETER */
434 /* reading the point tags */
435 flag = (FT_Byte*)outline->tags;
436 flag_limit = flag + n_points;
440 while ( flag < flag_limit )
443 goto Invalid_Outline;
445 *flag++ = c = FT_NEXT_BYTE( p );
446 if ( c & REPEAT_FLAG )
449 goto Invalid_Outline;
451 count = FT_NEXT_BYTE( p );
452 if ( flag + (FT_Int)count > flag_limit )
453 goto Invalid_Outline;
455 for ( ; count > 0; count-- )
460 /* retain the overlap flag */
461 if ( n_points && outline->tags[0] & OVERLAP_SIMPLE )
462 gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
464 /* reading the X coordinates */
466 vec = outline->points;
467 vec_limit = vec + n_points;
468 flag = (FT_Byte*)outline->tags;
471 for ( ; vec < vec_limit; vec++, flag++ )
477 if ( f & X_SHORT_VECTOR )
480 goto Invalid_Outline;
482 delta = (FT_Pos)FT_NEXT_BYTE( p );
483 if ( !( f & X_POSITIVE ) )
486 else if ( !( f & SAME_X ) )
489 goto Invalid_Outline;
491 delta = (FT_Pos)FT_NEXT_SHORT( p );
498 /* reading the Y coordinates */
500 vec = outline->points;
501 vec_limit = vec + n_points;
502 flag = (FT_Byte*)outline->tags;
505 for ( ; vec < vec_limit; vec++, flag++ )
511 if ( f & Y_SHORT_VECTOR )
514 goto Invalid_Outline;
516 delta = (FT_Pos)FT_NEXT_BYTE( p );
517 if ( !( f & Y_POSITIVE ) )
520 else if ( !( f & SAME_Y ) )
523 goto Invalid_Outline;
525 delta = (FT_Pos)FT_NEXT_SHORT( p );
531 /* the cast is for stupid compilers */
532 *flag = (FT_Byte)( f & ON_CURVE_POINT );
535 outline->n_points = (FT_Short)n_points;
536 outline->n_contours = (FT_Short)n_contours;
544 error = FT_THROW( Invalid_Outline );
549 FT_CALLBACK_DEF( FT_Error )
550 TT_Load_Composite_Glyph( TT_Loader loader )
553 FT_Byte* p = loader->cursor;
554 FT_Byte* limit = loader->limit;
555 FT_GlyphLoader gloader = loader->gloader;
556 FT_Long num_glyphs = loader->face->root.num_glyphs;
557 FT_SubGlyph subglyph;
558 FT_UInt num_subglyphs;
565 FT_Fixed xx, xy, yy, yx;
569 /* check that we can load a new subglyph */
570 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
576 goto Invalid_Composite;
578 subglyph = gloader->current.subglyphs + num_subglyphs;
580 subglyph->arg1 = subglyph->arg2 = 0;
582 subglyph->flags = FT_NEXT_USHORT( p );
583 subglyph->index = FT_NEXT_USHORT( p );
585 /* we reject composites that have components */
586 /* with invalid glyph indices */
587 if ( subglyph->index >= num_glyphs )
588 goto Invalid_Composite;
592 if ( subglyph->flags & ARGS_ARE_WORDS )
594 if ( subglyph->flags & WE_HAVE_A_SCALE )
596 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
598 else if ( subglyph->flags & WE_HAVE_A_2X2 )
601 if ( p + count > limit )
602 goto Invalid_Composite;
605 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
607 if ( subglyph->flags & ARGS_ARE_WORDS )
609 subglyph->arg1 = FT_NEXT_SHORT( p );
610 subglyph->arg2 = FT_NEXT_SHORT( p );
614 subglyph->arg1 = FT_NEXT_CHAR( p );
615 subglyph->arg2 = FT_NEXT_CHAR( p );
620 if ( subglyph->flags & ARGS_ARE_WORDS )
622 subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p );
623 subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p );
627 subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p );
628 subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p );
636 if ( subglyph->flags & WE_HAVE_A_SCALE )
638 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
641 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
643 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
644 yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
646 else if ( subglyph->flags & WE_HAVE_A_2X2 )
648 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
649 yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
650 xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
651 yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
654 subglyph->transform.xx = xx;
655 subglyph->transform.xy = xy;
656 subglyph->transform.yx = yx;
657 subglyph->transform.yy = yy;
661 } while ( subglyph->flags & MORE_COMPONENTS );
663 gloader->current.num_subglyphs = num_subglyphs;
664 FT_TRACE5(( " %d component%s\n",
666 num_subglyphs > 1 ? "s" : "" ));
668 #ifdef FT_DEBUG_LEVEL_TRACE
673 subglyph = gloader->current.subglyphs;
675 for ( i = 0; i < num_subglyphs; i++ )
677 if ( num_subglyphs > 1 )
678 FT_TRACE7(( " subglyph %d:\n", i ));
680 FT_TRACE7(( " glyph index: %d\n", subglyph->index ));
682 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
683 FT_TRACE7(( " offset: x=%d, y=%d\n",
687 FT_TRACE7(( " matching points: base=%d, component=%d\n",
691 if ( subglyph->flags & WE_HAVE_A_SCALE )
692 FT_TRACE7(( " scaling: %f\n",
693 (double)subglyph->transform.xx / 65536 ));
694 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
695 FT_TRACE7(( " scaling: x=%f, y=%f\n",
696 (double)subglyph->transform.xx / 65536,
697 (double)subglyph->transform.yy / 65536 ));
698 else if ( subglyph->flags & WE_HAVE_A_2X2 )
700 FT_TRACE7(( " scaling: xx=%f, yx=%f\n",
701 (double)subglyph->transform.xx / 65536,
702 (double)subglyph->transform.yx / 65536 ));
703 FT_TRACE7(( " xy=%f, yy=%f\n",
704 (double)subglyph->transform.xy / 65536,
705 (double)subglyph->transform.yy / 65536 ));
711 #endif /* FT_DEBUG_LEVEL_TRACE */
713 #ifdef TT_USE_BYTECODE_INTERPRETER
716 FT_Stream stream = loader->stream;
719 /* we must undo the FT_FRAME_ENTER in order to point */
720 /* to the composite instructions, if we find some. */
721 /* We will process them later. */
723 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
735 error = FT_THROW( Invalid_Composite );
741 TT_Init_Glyph_Loading( TT_Face face )
743 face->access_glyph_frame = TT_Access_Glyph_Frame;
744 face->read_glyph_header = TT_Load_Glyph_Header;
745 face->read_simple_glyph = TT_Load_Simple_Glyph;
746 face->read_composite_glyph = TT_Load_Composite_Glyph;
747 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
752 tt_prepare_zone( TT_GlyphZone zone,
755 FT_UInt start_contour )
757 zone->n_points = (FT_UShort)load->outline.n_points + 4 -
758 (FT_UShort)start_point;
759 zone->n_contours = load->outline.n_contours -
760 (FT_Short)start_contour;
761 zone->org = load->extra_points + start_point;
762 zone->cur = load->outline.points + start_point;
763 zone->orus = load->extra_points2 + start_point;
764 zone->tags = (FT_Byte*)load->outline.tags + start_point;
765 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
766 zone->first_point = (FT_UShort)start_point;
770 /**************************************************************************
776 * Hint the glyph using the zone prepared by the caller. Note that
777 * the zone is supposed to include four phantom points.
780 TT_Hint_Glyph( TT_Loader loader,
781 FT_Bool is_composite )
783 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
784 TT_Face face = loader->face;
785 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
788 TT_GlyphZone zone = &loader->zone;
790 #ifdef TT_USE_BYTECODE_INTERPRETER
791 TT_ExecContext exec = loader->exec;
792 FT_Long n_ins = exec->glyphSize;
794 FT_UNUSED( is_composite );
798 #ifdef TT_USE_BYTECODE_INTERPRETER
799 /* save original point positions in `org' array */
801 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
803 /* Reset graphics state. */
804 exec->GS = loader->size->GS;
806 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
807 /* completely refer to the (already) hinted subglyphs. */
810 exec->metrics.x_scale = 1 << 16;
811 exec->metrics.y_scale = 1 << 16;
813 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
817 exec->metrics.x_scale = loader->size->metrics->x_scale;
818 exec->metrics.y_scale = loader->size->metrics->y_scale;
822 /* round phantom points */
823 zone->cur[zone->n_points - 4].x =
824 FT_PIX_ROUND( zone->cur[zone->n_points - 4].x );
825 zone->cur[zone->n_points - 3].x =
826 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
827 zone->cur[zone->n_points - 2].y =
828 FT_PIX_ROUND( zone->cur[zone->n_points - 2].y );
829 zone->cur[zone->n_points - 1].y =
830 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
832 #ifdef TT_USE_BYTECODE_INTERPRETER
839 TT_Set_CodeRange( exec, tt_coderange_glyph, exec->glyphIns, n_ins );
841 exec->is_composite = is_composite;
844 error = TT_Run_Context( exec );
845 if ( error && exec->pedantic_hinting )
848 /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
849 loader->gloader->current.outline.tags[0] |=
850 ( exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
855 /* Save possibly modified glyph phantom points unless in v40 backward */
856 /* compatibility mode, where no movement on the x axis means no reason */
857 /* to change bearings or advance widths. */
859 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
860 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
861 exec->backward_compatibility )
865 loader->pp1 = zone->cur[zone->n_points - 4];
866 loader->pp2 = zone->cur[zone->n_points - 3];
867 loader->pp3 = zone->cur[zone->n_points - 2];
868 loader->pp4 = zone->cur[zone->n_points - 1];
874 /**************************************************************************
877 * TT_Process_Simple_Glyph
880 * Once a simple glyph has been loaded, it needs to be processed.
881 * Usually, this means scaling and hinting through bytecode
885 TT_Process_Simple_Glyph( TT_Loader loader )
887 FT_Error error = FT_Err_Ok;
888 FT_GlyphLoader gloader = loader->gloader;
889 FT_Outline* outline = &gloader->current.outline;
890 FT_Int n_points = outline->n_points;
892 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
893 FT_Memory memory = loader->face->root.memory;
894 FT_Vector* unrounded = NULL;
898 /* set phantom points */
899 outline->points[n_points ] = loader->pp1;
900 outline->points[n_points + 1] = loader->pp2;
901 outline->points[n_points + 2] = loader->pp3;
902 outline->points[n_points + 3] = loader->pp4;
906 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
908 if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
910 if ( FT_QNEW_ARRAY( unrounded, n_points ) )
913 /* Deltas apply to the unscaled data. */
914 error = TT_Vary_Apply_Glyph_Deltas( loader,
921 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
923 if ( IS_HINTED( loader->load_flags ) )
925 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
927 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
928 loader->zone.n_points );
932 FT_Vector* vec = outline->points;
933 FT_Vector* limit = outline->points + n_points;
935 FT_Fixed x_scale = 0; /* pacify compiler */
936 FT_Fixed y_scale = 0;
938 FT_Bool do_scale = FALSE;
942 /* scale the glyph */
943 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
945 x_scale = loader->size->metrics->x_scale;
946 y_scale = loader->size->metrics->y_scale;
954 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
955 if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
957 FT_Vector* u = unrounded;
960 for ( ; vec < limit; vec++, u++ )
962 vec->x = ADD_LONG( FT_MulFix( u->x, x_scale ), 32 ) >> 6;
963 vec->y = ADD_LONG( FT_MulFix( u->y, y_scale ), 32 ) >> 6;
967 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
969 for ( ; vec < limit; vec++ )
971 vec->x = FT_MulFix( vec->x, x_scale );
972 vec->y = FT_MulFix( vec->y, y_scale );
977 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
978 /* if we have a HVAR table, `pp1' and/or `pp2' */
979 /* are already adjusted but unscaled */
980 if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) &&
981 IS_HINTED( loader->load_flags ) )
983 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
984 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
985 /* pp1.y and pp2.y are always zero */
990 loader->pp1 = outline->points[n_points - 4];
991 loader->pp2 = outline->points[n_points - 3];
994 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
995 /* if we have a VVAR table, `pp3' and/or `pp4' */
996 /* are already adjusted but unscaled */
997 if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) &&
998 IS_HINTED( loader->load_flags ) )
1000 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1001 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1002 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1003 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1008 loader->pp3 = outline->points[n_points - 2];
1009 loader->pp4 = outline->points[n_points - 1];
1013 if ( IS_HINTED( loader->load_flags ) )
1014 error = TT_Hint_Glyph( loader, 0 );
1016 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1018 FT_FREE( unrounded );
1025 /**************************************************************************
1028 * TT_Process_Composite_Component
1031 * Once a composite component has been loaded, it needs to be
1032 * processed. Usually, this means transforming and translating.
1035 TT_Process_Composite_Component( TT_Loader loader,
1036 FT_SubGlyph subglyph,
1037 FT_UInt start_point,
1038 FT_UInt num_base_points )
1040 FT_GlyphLoader gloader = loader->gloader;
1046 current.points = gloader->base.outline.points +
1048 current.n_points = gloader->base.outline.n_points -
1049 (short)num_base_points;
1051 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
1052 WE_HAVE_AN_XY_SCALE |
1055 /* perform the transform required for this subglyph */
1057 FT_Outline_Transform( ¤t, &subglyph->transform );
1060 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
1062 FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points;
1063 FT_UInt k = (FT_UInt)subglyph->arg1;
1064 FT_UInt l = (FT_UInt)subglyph->arg2;
1069 /* match l-th point of the newly loaded component to the k-th point */
1070 /* of the previously loaded components. */
1072 /* change to the point numbers used by our outline */
1074 l += num_base_points;
1075 if ( k >= num_base_points ||
1077 return FT_THROW( Invalid_Composite );
1079 p1 = gloader->base.outline.points + k;
1080 p2 = gloader->base.outline.points + l;
1082 x = SUB_LONG( p1->x, p2->x );
1083 y = SUB_LONG( p1->y, p2->y );
1093 /* Use a default value dependent on */
1094 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old */
1095 /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit. */
1098 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
1099 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
1101 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
1107 /********************************************************************
1109 * This algorithm is what Apple documents. But it doesn't work.
1111 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
1112 : -subglyph->transform.xx;
1113 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
1114 : -subglyph->transform.yx;
1115 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
1116 : -subglyph->transform.xy;
1117 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
1118 : -subglyph->transform.yy;
1119 int m = a > b ? a : b;
1120 int n = c > d ? c : d;
1123 if ( a - b <= 33 && a - b >= -33 )
1125 if ( c - d <= 33 && c - d >= -33 )
1127 x = FT_MulFix( x, m );
1128 y = FT_MulFix( y, n );
1132 /********************************************************************
1134 * This algorithm is a guess and works much better than the above.
1136 FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx,
1137 subglyph->transform.xy );
1138 FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy,
1139 subglyph->transform.yx );
1142 x = FT_MulFix( x, mac_xscale );
1143 y = FT_MulFix( y, mac_yscale );
1149 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1151 FT_Fixed x_scale = loader->size->metrics->x_scale;
1152 FT_Fixed y_scale = loader->size->metrics->y_scale;
1155 x = FT_MulFix( x, x_scale );
1156 y = FT_MulFix( y, y_scale );
1158 if ( subglyph->flags & ROUND_XY_TO_GRID )
1160 TT_Face face = loader->face;
1161 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
1164 if ( IS_HINTED( loader->load_flags ) )
1167 * We round the horizontal offset only if there is hinting along
1168 * the x axis; this corresponds to integer advance width values.
1170 * Theoretically, a glyph's bytecode can toggle ClearType's
1171 * `backward compatibility' mode, which would allow modification
1172 * of the advance width. In reality, however, applications
1173 * neither allow nor expect modified advance widths if subpixel
1174 * rendering is active.
1177 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_35 )
1178 x = FT_PIX_ROUND( x );
1180 y = FT_PIX_ROUND( y );
1187 FT_Outline_Translate( ¤t, x, y );
1193 /**************************************************************************
1196 * TT_Process_Composite_Glyph
1199 * This is slightly different from TT_Process_Simple_Glyph, in that
1200 * its sole purpose is to hint the glyph. Thus this function is
1201 * only available when bytecode interpreter is enabled.
1204 TT_Process_Composite_Glyph( TT_Loader loader,
1205 FT_UInt start_point,
1206 FT_UInt start_contour )
1209 FT_Outline* outline = &loader->gloader->base.outline;
1210 FT_Stream stream = loader->stream;
1215 /* make room for phantom points */
1216 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
1217 outline->n_points + 4,
1222 outline->points[outline->n_points ] = loader->pp1;
1223 outline->points[outline->n_points + 1] = loader->pp2;
1224 outline->points[outline->n_points + 2] = loader->pp3;
1225 outline->points[outline->n_points + 3] = loader->pp4;
1227 #ifdef TT_USE_BYTECODE_INTERPRETER
1230 TT_ExecContext exec = loader->exec;
1231 FT_Memory memory = exec->memory;
1234 if ( exec->glyphSize )
1235 FT_FREE( exec->glyphIns );
1236 exec->glyphSize = 0;
1238 /* TT_Load_Composite_Glyph only gives us the offset of instructions */
1239 /* so we read them here */
1240 if ( FT_STREAM_SEEK( loader->ins_pos ) ||
1241 FT_READ_USHORT( n_ins ) )
1244 FT_TRACE5(( " Instructions size = %hu\n", n_ins ));
1249 /* don't trust `maxSizeOfInstructions'; */
1250 /* only do a rough safety check */
1251 if ( n_ins > loader->byte_len )
1253 FT_TRACE1(( "TT_Process_Composite_Glyph:"
1254 " too many instructions (%hu) for glyph with length %u\n",
1255 n_ins, loader->byte_len ));
1256 return FT_THROW( Too_Many_Hints );
1259 if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) ||
1260 FT_STREAM_READ( exec->glyphIns, n_ins ) )
1263 exec->glyphSize = n_ins;
1268 tt_prepare_zone( &loader->zone, &loader->gloader->base,
1269 start_point, start_contour );
1271 /* Some points are likely touched during execution of */
1272 /* instructions on components. So let's untouch them. */
1273 for ( i = 0; i < loader->zone.n_points - 4U; i++ )
1274 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
1276 return TT_Hint_Glyph( loader, 1 );
1281 * Calculate the phantom points
1283 * Defining the right side bearing (rsb) as
1285 * rsb = aw - (lsb + xmax - xmin)
1287 * (with `aw' the advance width, `lsb' the left side bearing, and `xmin'
1288 * and `xmax' the glyph's minimum and maximum x value), the OpenType
1289 * specification defines the initial position of horizontal phantom points
1292 * pp1 = (round(xmin - lsb), 0) ,
1293 * pp2 = (round(pp1 + aw), 0) .
1295 * Note that the rounding to the grid (in the device space) is not
1296 * documented currently in the specification.
1298 * However, the specification lacks the precise definition of vertical
1299 * phantom points. Greg Hitchcock provided the following explanation.
1301 * - a `vmtx' table is present
1303 * For any glyph, the minimum and maximum y values (`ymin' and `ymax')
1304 * are given in the `glyf' table, the top side bearing (tsb) and advance
1305 * height (ah) are given in the `vmtx' table. The bottom side bearing
1306 * (bsb) is then calculated as
1308 * bsb = ah - (tsb + ymax - ymin) ,
1310 * and the initial position of vertical phantom points is
1312 * pp3 = (x, round(ymax + tsb)) ,
1313 * pp4 = (x, round(pp3 - ah)) .
1315 * See below for value `x'.
1317 * - no `vmtx' table in the font
1319 * If there is an `OS/2' table, we set
1321 * DefaultAscender = sTypoAscender ,
1322 * DefaultDescender = sTypoDescender ,
1324 * otherwise we use data from the `hhea' table:
1326 * DefaultAscender = Ascender ,
1327 * DefaultDescender = Descender .
1329 * With these two variables we can now set
1331 * ah = DefaultAscender - sDefaultDescender ,
1332 * tsb = DefaultAscender - yMax ,
1334 * and proceed as if a `vmtx' table was present.
1340 * but there is one compatibility case where it can be set to
1342 * x = -DefaultDescender -
1343 * ((DefaultAscender - DefaultDescender - aw) / 2) . (2)
1345 * and another one with
1349 * In Windows, the history of those values is quite complicated,
1350 * depending on the hinting engine (that is, the graphics framework).
1352 * framework from to formula
1353 * ----------------------------------------------------------
1354 * GDI Windows 98 current (1)
1355 * (Windows 2000 for NT)
1356 * GDI+ Windows XP Windows 7 (2)
1357 * GDI+ Windows 8 current (3)
1358 * DWrite Windows 7 current (3)
1360 * For simplicity, FreeType uses (1) for grayscale subpixel hinting and
1361 * (3) for everything else.
1365 tt_loader_set_pp( TT_Loader loader )
1367 loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
1369 loader->pp2.x = loader->pp1.x + loader->advance;
1373 loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
1375 loader->pp4.y = loader->pp3.y - loader->vadvance;
1377 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1379 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
1382 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
1384 loader->exec->subpixel_hinting_lean &&
1385 loader->exec->grayscale_cleartype )
1387 loader->pp3.x = loader->advance / 2;
1388 loader->pp4.x = loader->advance / 2;
1395 /* a utility function to retrieve i-th node from given FT_List */
1397 ft_list_get_node_at( FT_List list,
1406 for ( cur = list->head; cur; cur = cur->next )
1418 /**************************************************************************
1421 * load_truetype_glyph
1424 * Loads a given truetype glyph. Handles composites and uses a
1428 load_truetype_glyph( TT_Loader loader,
1429 FT_UInt glyph_index,
1430 FT_UInt recurse_count,
1431 FT_Bool header_only )
1433 FT_Error error = FT_Err_Ok;
1434 FT_Fixed x_scale, y_scale;
1436 TT_Face face = loader->face;
1437 FT_GlyphLoader gloader = loader->gloader;
1439 FT_Bool opened_frame = 0;
1441 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1442 FT_StreamRec inc_stream;
1444 FT_Bool glyph_data_loaded = 0;
1448 #ifdef FT_DEBUG_LEVEL_TRACE
1449 if ( recurse_count )
1450 FT_TRACE5(( " nesting level: %d\n", recurse_count ));
1453 /* some fonts have an incorrect value of `maxComponentDepth' */
1454 if ( recurse_count > face->max_profile.maxComponentDepth )
1456 FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %d\n",
1458 face->max_profile.maxComponentDepth = (FT_UShort)recurse_count;
1461 #ifndef FT_CONFIG_OPTION_INCREMENTAL
1462 /* check glyph index */
1463 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
1465 error = FT_THROW( Invalid_Glyph_Index );
1470 loader->glyph_index = glyph_index;
1472 if ( loader->load_flags & FT_LOAD_NO_SCALE )
1479 x_scale = loader->size->metrics->x_scale;
1480 y_scale = loader->size->metrics->y_scale;
1483 /* Set `offset' to the start of the glyph relative to the start of */
1484 /* the `glyf' table, and `byte_len' to the length of the glyph in */
1487 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1489 /* If we are loading glyph data via the incremental interface, set */
1490 /* the loader stream to a memory stream reading the data returned */
1491 /* by the interface. */
1492 if ( face->root.internal->incremental_interface )
1494 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1495 face->root.internal->incremental_interface->object,
1496 glyph_index, &glyph_data );
1500 glyph_data_loaded = 1;
1502 loader->byte_len = glyph_data.length;
1504 FT_ZERO( &inc_stream );
1505 FT_Stream_OpenMemory( &inc_stream,
1507 glyph_data.length );
1509 loader->stream = &inc_stream;
1513 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1518 offset = tt_face_get_location( FT_FACE( face ), glyph_index, &len );
1520 loader->byte_len = (FT_UInt)len;
1523 if ( loader->byte_len > 0 )
1525 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1526 /* for the incremental interface, `glyf_offset' is always zero */
1527 if ( !face->glyf_offset &&
1528 !face->root.internal->incremental_interface )
1530 if ( !face->glyf_offset )
1531 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1533 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
1534 error = FT_THROW( Invalid_Table );
1538 error = face->access_glyph_frame( loader, glyph_index,
1539 face->glyf_offset + offset,
1544 /* read glyph header first */
1545 error = face->read_glyph_header( loader );
1547 face->forget_glyph_frame( loader );
1554 if ( loader->byte_len == 0 || loader->n_contours == 0 )
1556 loader->bbox.xMin = 0;
1557 loader->bbox.xMax = 0;
1558 loader->bbox.yMin = 0;
1559 loader->bbox.yMax = 0;
1562 /* the metrics must be computed after loading the glyph header */
1563 /* since we need the glyph's `yMax' value in case the vertical */
1564 /* metrics must be emulated */
1565 error = tt_get_metrics( loader, glyph_index );
1572 if ( loader->byte_len == 0 || loader->n_contours == 0 )
1574 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1575 tt_get_metrics_incremental( loader, glyph_index );
1577 tt_loader_set_pp( loader );
1580 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1582 if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1583 FT_IS_VARIATION( FT_FACE( face ) ) )
1585 /* a small outline structure with four elements for */
1586 /* communication with `TT_Vary_Apply_Glyph_Deltas' */
1587 FT_Vector points[4];
1590 /* unrounded values */
1591 FT_Vector unrounded[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1594 points[0] = loader->pp1;
1595 points[1] = loader->pp2;
1596 points[2] = loader->pp3;
1597 points[3] = loader->pp4;
1599 outline.n_points = 0;
1600 outline.n_contours = 0;
1601 outline.points = points;
1602 outline.tags = NULL;
1603 outline.contours = NULL;
1605 /* this must be done before scaling */
1606 error = TT_Vary_Apply_Glyph_Deltas( loader,
1613 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1615 /* scale phantom points, if necessary; */
1616 /* they get rounded in `TT_Hint_Glyph' */
1617 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1619 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1620 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1621 /* pp1.y and pp2.y are always zero */
1623 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1624 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1625 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1626 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1633 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1634 tt_get_metrics_incremental( loader, glyph_index );
1636 tt_loader_set_pp( loader );
1639 /***********************************************************************/
1640 /***********************************************************************/
1641 /***********************************************************************/
1643 /* we now open a frame again, right after the glyph header */
1644 /* (which consists of 10 bytes) */
1645 error = face->access_glyph_frame( loader, glyph_index,
1646 face->glyf_offset + offset + 10,
1647 loader->byte_len - 10 );
1653 /* if it is a simple glyph, load it */
1655 if ( loader->n_contours > 0 )
1657 error = face->read_simple_glyph( loader );
1661 /* all data have been read */
1662 face->forget_glyph_frame( loader );
1665 error = TT_Process_Simple_Glyph( loader );
1669 FT_GlyphLoader_Add( gloader );
1672 /***********************************************************************/
1673 /***********************************************************************/
1674 /***********************************************************************/
1676 /* otherwise, load a composite! */
1677 else if ( loader->n_contours < 0 )
1679 FT_Memory memory = face->root.memory;
1681 FT_UInt start_point;
1682 FT_UInt start_contour;
1683 FT_ULong ins_pos; /* position of composite instructions, if any */
1685 FT_ListNode node, node2;
1688 /* normalize the `n_contours' value */
1689 loader->n_contours = -1;
1692 * We store the glyph index directly in the `node->data' pointer,
1693 * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
1694 * double cast to make this portable. Note, however, that this needs
1695 * pointers with a width of at least 32 bits.
1698 /* clear the nodes filled by sibling chains */
1699 node = ft_list_get_node_at( &loader->composites, recurse_count );
1700 for ( node2 = node; node2; node2 = node2->next )
1701 node2->data = (void*)-1;
1703 /* check whether we already have a composite glyph with this index */
1704 if ( FT_List_Find( &loader->composites,
1705 FT_UINT_TO_POINTER( glyph_index ) ) )
1707 FT_TRACE1(( "TT_Load_Composite_Glyph:"
1708 " infinite recursion detected\n" ));
1709 error = FT_THROW( Invalid_Composite );
1714 node->data = FT_UINT_TO_POINTER( glyph_index );
1718 if ( FT_QNEW( node ) )
1720 node->data = FT_UINT_TO_POINTER( glyph_index );
1721 FT_List_Add( &loader->composites, node );
1724 start_point = (FT_UInt)gloader->base.outline.n_points;
1725 start_contour = (FT_UInt)gloader->base.outline.n_contours;
1727 /* for each subglyph, read composite header */
1728 error = face->read_composite_glyph( loader );
1732 /* store the offset of instructions */
1733 ins_pos = loader->ins_pos;
1735 /* all data we need are read */
1736 face->forget_glyph_frame( loader );
1739 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1741 if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1742 FT_IS_VARIATION( FT_FACE( face ) ) )
1745 FT_SubGlyph subglyph;
1747 FT_Outline outline = { 0, 0, NULL, NULL, NULL, 0 };
1748 FT_Vector* unrounded = NULL;
1751 limit = (short)gloader->current.num_subglyphs;
1753 /* construct an outline structure for */
1754 /* communication with `TT_Vary_Apply_Glyph_Deltas' */
1755 if ( FT_QNEW_ARRAY( outline.points, limit + 4 ) ||
1756 FT_QNEW_ARRAY( outline.tags, limit ) ||
1757 FT_QNEW_ARRAY( outline.contours, limit ) ||
1758 FT_QNEW_ARRAY( unrounded, limit + 4 ) )
1761 outline.n_contours = outline.n_points = limit;
1763 subglyph = gloader->current.subglyphs;
1765 for ( i = 0; i < limit; i++, subglyph++ )
1767 /* applying deltas for anchor points doesn't make sense, */
1768 /* but we don't have to specially check this since */
1769 /* unused delta values are zero anyways */
1770 outline.points[i].x = subglyph->arg1;
1771 outline.points[i].y = subglyph->arg2;
1772 outline.tags[i] = ON_CURVE_POINT;
1773 outline.contours[i] = i;
1776 outline.points[i++] = loader->pp1;
1777 outline.points[i++] = loader->pp2;
1778 outline.points[i++] = loader->pp3;
1779 outline.points[i ] = loader->pp4;
1781 /* this call provides additional offsets */
1782 /* for each component's translation */
1783 if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas( loader,
1788 subglyph = gloader->current.subglyphs;
1790 for ( i = 0; i < limit; i++, subglyph++ )
1792 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1794 subglyph->arg1 = (FT_Int16)outline.points[i].x;
1795 subglyph->arg2 = (FT_Int16)outline.points[i].y;
1800 FT_FREE( outline.points );
1801 FT_FREE( outline.tags );
1802 FT_FREE( outline.contours );
1803 FT_FREE( unrounded );
1809 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1811 /* scale phantom points, if necessary; */
1812 /* they get rounded in `TT_Hint_Glyph' */
1813 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1815 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1816 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1817 /* pp1.y and pp2.y are always zero */
1819 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1820 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1821 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1822 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1825 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
1826 /* `as is' in the glyph slot (the client application will be */
1827 /* responsible for interpreting these data)... */
1828 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1830 FT_GlyphLoader_Add( gloader );
1831 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
1836 /*********************************************************************/
1837 /*********************************************************************/
1838 /*********************************************************************/
1841 FT_UInt n, num_base_points;
1842 FT_SubGlyph subglyph = NULL;
1844 FT_UInt num_points = start_point;
1845 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
1846 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
1848 FT_Stream old_stream = loader->stream;
1849 FT_UInt old_byte_len = loader->byte_len;
1852 FT_GlyphLoader_Add( gloader );
1854 /* read each subglyph independently */
1855 for ( n = 0; n < num_subglyphs; n++ )
1859 FT_Int linear_hadvance;
1860 FT_Int linear_vadvance;
1863 /* Each time we call `load_truetype_glyph' in this loop, the */
1864 /* value of `gloader.base.subglyphs' can change due to table */
1865 /* reallocations. We thus need to recompute the subglyph */
1866 /* pointer on each iteration. */
1867 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1869 pp[0] = loader->pp1;
1870 pp[1] = loader->pp2;
1871 pp[2] = loader->pp3;
1872 pp[3] = loader->pp4;
1874 linear_hadvance = loader->linear;
1875 linear_vadvance = loader->vadvance;
1877 num_base_points = (FT_UInt)gloader->base.outline.n_points;
1879 error = load_truetype_glyph( loader,
1880 (FT_UInt)subglyph->index,
1886 /* restore subglyph pointer */
1887 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1889 /* restore phantom points if necessary */
1890 if ( !( subglyph->flags & USE_MY_METRICS ) )
1892 loader->pp1 = pp[0];
1893 loader->pp2 = pp[1];
1894 loader->pp3 = pp[2];
1895 loader->pp4 = pp[3];
1897 loader->linear = linear_hadvance;
1898 loader->vadvance = linear_vadvance;
1901 num_points = (FT_UInt)gloader->base.outline.n_points;
1903 if ( num_points == num_base_points )
1906 /* gloader->base.outline consists of three parts: */
1908 /* 0 ----> start_point ----> num_base_points ----> n_points */
1911 /* (1) points that exist from the beginning */
1912 /* (2) component points that have been loaded so far */
1913 /* (3) points of the newly loaded component */
1914 error = TT_Process_Composite_Component( loader,
1922 loader->stream = old_stream;
1923 loader->byte_len = old_byte_len;
1925 /* process the glyph */
1926 loader->ins_pos = ins_pos;
1927 if ( IS_HINTED( loader->load_flags ) &&
1928 #ifdef TT_USE_BYTECODE_INTERPRETER
1930 subglyph->flags & WE_HAVE_INSTR &&
1932 num_points > start_point )
1934 error = TT_Process_Composite_Glyph( loader,
1942 /* retain the overlap flag */
1943 if ( gloader->base.num_subglyphs &&
1944 gloader->base.subglyphs[0].flags & OVERLAP_COMPOUND )
1945 gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
1948 /***********************************************************************/
1949 /***********************************************************************/
1950 /***********************************************************************/
1955 face->forget_glyph_frame( loader );
1957 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1959 if ( glyph_data_loaded )
1960 face->root.internal->incremental_interface->funcs->free_glyph_data(
1961 face->root.internal->incremental_interface->object,
1971 compute_glyph_metrics( TT_Loader loader,
1972 FT_UInt glyph_index )
1974 TT_Face face = loader->face;
1975 TT_Size size = loader->size;
1976 TT_GlyphSlot glyph = loader->glyph;
1982 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1983 y_scale = size->metrics->y_scale;
1985 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
1986 FT_Outline_Get_CBox( &glyph->outline, &bbox );
1988 bbox = loader->bbox;
1990 /* get the device-independent horizontal advance; it is scaled later */
1991 /* by the base layer. */
1992 glyph->linearHoriAdvance = loader->linear;
1994 glyph->metrics.horiBearingX = bbox.xMin;
1995 glyph->metrics.horiBearingY = bbox.yMax;
1996 if ( loader->widthp )
1997 glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64;
1999 glyph->metrics.horiAdvance = SUB_LONG( loader->pp2.x, loader->pp1.x );
2001 /* set glyph dimensions */
2002 glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin );
2003 glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin );
2005 /* Now take care of vertical metrics. In the case where there is */
2006 /* no vertical information within the font (relatively common), */
2007 /* create some metrics manually */
2009 FT_Pos top; /* scaled vertical top side bearing */
2010 FT_Pos advance; /* scaled vertical advance height */
2013 /* Get the unscaled top bearing and advance height. */
2014 if ( face->vertical_info &&
2015 face->vertical.number_Of_VMetrics > 0 )
2017 top = (FT_Short)FT_DivFix( SUB_LONG( loader->pp3.y, bbox.yMax ),
2020 if ( loader->pp3.y <= loader->pp4.y )
2023 advance = (FT_UShort)FT_DivFix( SUB_LONG( loader->pp3.y,
2032 /* XXX Compute top side bearing and advance height in */
2033 /* Get_VMetrics instead of here. */
2035 /* NOTE: The OS/2 values are the only `portable' ones, */
2036 /* which is why we use them, if there is an OS/2 */
2037 /* table in the font. Otherwise, we use the */
2038 /* values defined in the horizontal header. */
2040 height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax,
2043 if ( face->os2.version != 0xFFFFU )
2044 advance = (FT_Pos)( face->os2.sTypoAscender -
2045 face->os2.sTypoDescender );
2047 advance = (FT_Pos)( face->horizontal.Ascender -
2048 face->horizontal.Descender );
2050 top = ( advance - height ) / 2;
2053 #ifdef FT_CONFIG_OPTION_INCREMENTAL
2055 FT_Incremental_InterfaceRec* incr;
2056 FT_Incremental_MetricsRec incr_metrics;
2060 incr = face->root.internal->incremental_interface;
2062 /* If this is an incrementally loaded font see if there are */
2063 /* overriding metrics for this glyph. */
2064 if ( incr && incr->funcs->get_glyph_metrics )
2066 incr_metrics.bearing_x = 0;
2067 incr_metrics.bearing_y = top;
2068 incr_metrics.advance = advance;
2070 error = incr->funcs->get_glyph_metrics( incr->object,
2077 top = incr_metrics.bearing_y;
2078 advance = incr_metrics.advance;
2082 /* GWW: Do vertical metrics get loaded incrementally too? */
2084 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
2086 glyph->linearVertAdvance = advance;
2088 /* scale the metrics */
2089 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
2091 top = FT_MulFix( top, y_scale );
2092 advance = FT_MulFix( advance, y_scale );
2095 /* XXX: for now, we have no better algorithm for the lsb, but it */
2096 /* should work fine. */
2098 glyph->metrics.vertBearingX = SUB_LONG( glyph->metrics.horiBearingX,
2099 glyph->metrics.horiAdvance / 2 );
2100 glyph->metrics.vertBearingY = top;
2101 glyph->metrics.vertAdvance = advance;
2108 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2111 load_sbit_image( TT_Size size,
2113 FT_UInt glyph_index,
2114 FT_Int32 load_flags )
2116 TT_Face face = (TT_Face)glyph->face;
2117 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
2118 FT_Stream stream = face->root.stream;
2120 TT_SBit_MetricsRec sbit_metrics;
2123 error = sfnt->load_sbit_image( face,
2126 (FT_UInt)load_flags,
2132 glyph->outline.n_points = 0;
2133 glyph->outline.n_contours = 0;
2135 glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64;
2136 glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64;
2138 glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64;
2139 glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64;
2140 glyph->metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64;
2142 glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64;
2143 glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64;
2144 glyph->metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64;
2146 glyph->format = FT_GLYPH_FORMAT_BITMAP;
2148 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2150 glyph->bitmap_left = sbit_metrics.vertBearingX;
2151 glyph->bitmap_top = sbit_metrics.vertBearingY;
2155 glyph->bitmap_left = sbit_metrics.horiBearingX;
2156 glyph->bitmap_top = sbit_metrics.horiBearingY;
2163 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2167 tt_loader_init( TT_Loader loader,
2170 FT_Int32 load_flags,
2171 FT_Bool glyf_table_only )
2173 TT_Face face = (TT_Face)glyph->face;
2174 FT_Stream stream = face->root.stream;
2176 #ifdef TT_USE_BYTECODE_INTERPRETER
2178 FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2179 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2180 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face );
2187 #ifdef TT_USE_BYTECODE_INTERPRETER
2189 /* load execution context */
2190 if ( IS_HINTED( load_flags ) && !glyf_table_only )
2192 TT_ExecContext exec;
2193 FT_Bool grayscale = TRUE;
2194 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2195 FT_Bool subpixel_hinting_lean;
2196 FT_Bool grayscale_cleartype;
2199 FT_Bool reexecute = FALSE;
2202 if ( size->bytecode_ready < 0 || size->cvt_ready < 0 )
2204 error = tt_size_ready_bytecode( size, pedantic );
2208 else if ( size->bytecode_ready )
2209 return size->bytecode_ready;
2210 else if ( size->cvt_ready )
2211 return size->cvt_ready;
2213 /* query new execution context */
2214 exec = size->context;
2216 return FT_THROW( Could_Not_Find_Context );
2218 grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2219 FT_RENDER_MODE_MONO );
2221 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2222 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2224 subpixel_hinting_lean =
2225 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2226 FT_RENDER_MODE_MONO );
2227 grayscale_cleartype =
2228 FT_BOOL( subpixel_hinting_lean &&
2230 FT_LOAD_TARGET_LCD ) ||
2232 FT_LOAD_TARGET_LCD_V ) ) );
2233 exec->vertical_lcd_lean =
2234 FT_BOOL( subpixel_hinting_lean &&
2236 FT_LOAD_TARGET_LCD_V ) );
2237 grayscale = FT_BOOL( grayscale && !subpixel_hinting_lean );
2241 subpixel_hinting_lean = FALSE;
2242 grayscale_cleartype = FALSE;
2243 exec->vertical_lcd_lean = FALSE;
2247 error = TT_Load_Context( exec, face, size );
2252 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2253 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2255 /* a change from mono to subpixel rendering (and vice versa) */
2256 /* requires a re-execution of the CVT program */
2257 if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
2259 FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
2260 " re-executing `prep' table\n" ));
2262 exec->subpixel_hinting_lean = subpixel_hinting_lean;
2266 /* a change from colored to grayscale subpixel rendering (and */
2267 /* vice versa) requires a re-execution of the CVT program */
2268 if ( grayscale_cleartype != exec->grayscale_cleartype )
2270 FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
2271 " re-executing `prep' table\n" ));
2273 exec->grayscale_cleartype = grayscale_cleartype;
2279 /* a change from mono to grayscale rendering (and vice versa) */
2280 /* requires a re-execution of the CVT program */
2281 if ( grayscale != exec->grayscale )
2283 FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
2284 " re-executing `prep' table\n" ));
2286 exec->grayscale = grayscale;
2293 error = tt_size_run_prep( size, pedantic );
2296 error = TT_Load_Context( exec, face, size );
2301 /* check whether the cvt program has disabled hinting */
2302 if ( exec->GS.instruct_control & 1 )
2303 load_flags |= FT_LOAD_NO_HINTING;
2305 /* load default graphics state -- if needed */
2306 if ( exec->GS.instruct_control & 2 )
2307 exec->GS = tt_default_graphics_state;
2309 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2311 * Toggle backward compatibility according to what font wants, except
2314 * 1) we have a `tricky' font that heavily relies on the interpreter to
2315 * render glyphs correctly, for example DFKai-SB, or
2316 * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
2318 * In those cases, backward compatibility needs to be turned off to get
2319 * correct rendering. The rendering is then completely up to the
2320 * font's programming.
2323 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
2324 subpixel_hinting_lean &&
2325 !FT_IS_TRICKY( glyph->face ) )
2326 exec->backward_compatibility = !( exec->GS.instruct_control & 4 );
2328 exec->backward_compatibility = FALSE;
2329 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
2331 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2332 loader->exec = exec;
2333 loader->instructions = exec->glyphIns;
2335 /* Use the hdmx table if any unless FT_LOAD_COMPUTE_METRICS */
2336 /* is set or backward compatibility mode of the v38 or v40 */
2337 /* interpreters is active. See `ttinterp.h' for details on */
2338 /* backward compatibility mode. */
2339 if ( IS_HINTED( loader->load_flags ) &&
2340 !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) &&
2341 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2342 !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
2343 exec->backward_compatibility ) &&
2345 !face->postscript.isFixedPitch )
2347 loader->widthp = size->widthp;
2350 loader->widthp = NULL;
2353 #endif /* TT_USE_BYTECODE_INTERPRETER */
2355 /* get face's glyph loader */
2356 if ( !glyf_table_only )
2358 FT_GlyphLoader gloader = glyph->internal->loader;
2361 FT_GlyphLoader_Rewind( gloader );
2362 loader->gloader = gloader;
2365 loader->load_flags = (FT_ULong)load_flags;
2367 loader->face = face;
2368 loader->size = size;
2369 loader->glyph = (FT_GlyphSlot)glyph;
2370 loader->stream = stream;
2372 loader->composites.head = NULL;
2373 loader->composites.tail = NULL;
2380 tt_loader_done( TT_Loader loader )
2382 FT_List_Finalize( &loader->composites,
2384 loader->face->root.memory,
2389 /**************************************************************************
2395 * A function used to load a single glyph within a given glyph slot,
2400 * A handle to a target slot object where the glyph
2405 * A handle to the source face size at which the glyph
2406 * must be scaled/loaded.
2409 * The index of the glyph in the font file.
2412 * A flag indicating what to load for this glyph. The
2413 * FT_LOAD_XXX constants can be used to control the
2414 * glyph loading process (e.g., whether the outline
2415 * should be scaled, whether to load bitmaps or not,
2416 * whether to hint the outline, etc).
2419 * FreeType error code. 0 means success.
2421 FT_LOCAL_DEF( FT_Error )
2422 TT_Load_Glyph( TT_Size size,
2424 FT_UInt glyph_index,
2425 FT_Int32 load_flags )
2427 TT_Face face = (TT_Face)glyph->face;
2429 TT_LoaderRec loader;
2432 FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
2434 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2436 /* try to load embedded bitmap (if any) */
2437 if ( size->strike_index != 0xFFFFFFFFUL &&
2438 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
2439 IS_DEFAULT_INSTANCE( glyph->face ) )
2441 FT_Fixed x_scale = size->root.metrics.x_scale;
2442 FT_Fixed y_scale = size->root.metrics.y_scale;
2445 error = load_sbit_image( size, glyph, glyph_index, load_flags );
2446 if ( FT_ERR_EQ( error, Missing_Bitmap ) )
2448 /* the bitmap strike is incomplete and misses the requested glyph; */
2449 /* if we have a bitmap-only font, return an empty glyph */
2450 if ( !FT_IS_SCALABLE( glyph->face ) )
2452 FT_Short left_bearing = 0;
2453 FT_Short top_bearing = 0;
2455 FT_UShort advance_width = 0;
2456 FT_UShort advance_height = 0;
2459 /* to return an empty glyph, however, we need metrics data */
2460 /* from the `hmtx' (or `vmtx') table; the assumption is that */
2461 /* empty glyphs are missing intentionally, representing */
2462 /* whitespace - not having at least horizontal metrics is */
2463 /* thus considered an error */
2464 if ( !face->horz_metrics_size )
2467 /* we now construct an empty bitmap glyph */
2468 TT_Get_HMetrics( face, glyph_index,
2471 TT_Get_VMetrics( face, glyph_index,
2476 glyph->outline.n_points = 0;
2477 glyph->outline.n_contours = 0;
2479 glyph->metrics.width = 0;
2480 glyph->metrics.height = 0;
2482 glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale );
2483 glyph->metrics.horiBearingY = 0;
2484 glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale );
2486 glyph->metrics.vertBearingX = 0;
2487 glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale );
2488 glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale );
2490 glyph->format = FT_GLYPH_FORMAT_BITMAP;
2491 glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
2493 glyph->bitmap_left = 0;
2494 glyph->bitmap_top = 0;
2501 /* return error if font is not scalable */
2502 if ( !FT_IS_SCALABLE( glyph->face ) )
2507 if ( FT_IS_SCALABLE( glyph->face ) ||
2508 FT_HAS_SBIX( glyph->face ) )
2510 /* for the bbox we need the header only */
2511 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
2512 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
2513 tt_loader_done( &loader );
2514 glyph->linearHoriAdvance = loader.linear;
2515 glyph->linearVertAdvance = loader.vadvance;
2517 /* Bitmaps from the 'sbix' table need special treatment: */
2518 /* if there is a glyph contour, the bitmap origin must be */
2519 /* shifted to be relative to the lower left corner of the */
2520 /* glyph bounding box, also taking the left-side bearing */
2521 /* (or top bearing) into account. */
2522 if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX &&
2523 loader.n_contours > 0 )
2529 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2531 /* This is a guess, since Apple's CoreText engine doesn't */
2532 /* really do vertical typesetting. */
2533 bitmap_left = loader.bbox.xMin;
2534 bitmap_top = loader.top_bearing;
2538 bitmap_left = loader.left_bearing;
2539 bitmap_top = loader.bbox.yMin;
2542 glyph->bitmap_left += FT_MulFix( bitmap_left, x_scale ) >> 6;
2543 glyph->bitmap_top += FT_MulFix( bitmap_top, y_scale ) >> 6;
2546 /* sanity checks: if `xxxAdvance' in the sbit metric */
2547 /* structure isn't set, use `linearXXXAdvance' */
2548 if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
2549 glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance,
2551 if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
2552 glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance,
2560 if ( load_flags & FT_LOAD_SBITS_ONLY )
2562 error = FT_THROW( Invalid_Argument );
2566 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2568 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
2569 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
2571 error = FT_THROW( Invalid_Size_Handle );
2575 #ifdef FT_CONFIG_OPTION_SVG
2577 /* check for OT-SVG */
2578 if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 &&
2579 ( load_flags & FT_LOAD_COLOR ) &&
2582 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
2585 FT_TRACE3(( "Trying to load SVG glyph\n" ));
2587 error = sfnt->load_svg_doc( glyph, glyph_index );
2590 FT_Fixed x_scale = size->root.metrics.x_scale;
2591 FT_Fixed y_scale = size->root.metrics.y_scale;
2593 FT_Short leftBearing;
2594 FT_Short topBearing;
2599 FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
2601 glyph->format = FT_GLYPH_FORMAT_SVG;
2603 sfnt->get_metrics( face,
2608 sfnt->get_metrics( face,
2614 glyph->linearHoriAdvance = advanceX;
2615 glyph->linearVertAdvance = advanceY;
2617 glyph->metrics.horiAdvance = FT_MulFix( advanceX, x_scale );
2618 glyph->metrics.vertAdvance = FT_MulFix( advanceY, y_scale );
2623 FT_TRACE3(( "Failed to load SVG glyph\n" ));
2626 /* return immediately if we only want SVG glyphs */
2627 if ( load_flags & FT_LOAD_SVG_ONLY )
2629 error = FT_THROW( Invalid_Argument );
2633 #endif /* FT_CONFIG_OPTION_SVG */
2635 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
2639 /* done if we are only interested in the `hdmx` advance */
2640 if ( load_flags & FT_LOAD_ADVANCE_ONLY &&
2641 !( load_flags & FT_LOAD_VERTICAL_LAYOUT ) &&
2644 glyph->metrics.horiAdvance = loader.widthp[glyph_index] * 64;
2648 glyph->format = FT_GLYPH_FORMAT_OUTLINE;
2649 glyph->num_subglyphs = 0;
2650 glyph->outline.flags = 0;
2652 /* main loading loop */
2653 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
2656 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
2658 glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
2659 glyph->subglyphs = loader.gloader->base.subglyphs;
2663 glyph->outline = loader.gloader->base.outline;
2664 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
2666 /* Translate array so that (0,0) is the glyph's origin. Note */
2667 /* that this behaviour is independent on the value of bit 1 of */
2668 /* the `flags' field in the `head' table -- at least major */
2669 /* applications like Acroread indicate that. */
2671 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
2674 #ifdef TT_USE_BYTECODE_INTERPRETER
2676 if ( IS_HINTED( load_flags ) )
2678 glyph->control_data = loader.exec->glyphIns;
2679 glyph->control_len = loader.exec->glyphSize;
2681 if ( loader.exec->GS.scan_control )
2683 /* convert scan conversion mode to FT_OUTLINE_XXX flags */
2684 switch ( loader.exec->GS.scan_type )
2686 case 0: /* simple drop-outs including stubs */
2687 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
2689 case 1: /* simple drop-outs excluding stubs */
2690 /* nothing; it's the default rendering mode */
2692 case 4: /* smart drop-outs including stubs */
2693 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
2694 FT_OUTLINE_INCLUDE_STUBS;
2696 case 5: /* smart drop-outs excluding stubs */
2697 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
2700 default: /* no drop-out control */
2701 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2706 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2709 #endif /* TT_USE_BYTECODE_INTERPRETER */
2711 error = compute_glyph_metrics( &loader, glyph_index );
2714 /* Set the `high precision' bit flag. */
2715 /* This is _critical_ to get correct output for monochrome */
2716 /* TrueType glyphs at all sizes using the bytecode interpreter. */
2718 if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
2719 size->metrics->y_ppem < 24 )
2720 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
2722 FT_TRACE1(( " subglyphs = %u, contours = %hd, points = %hd,"
2723 " flags = 0x%.3x\n",
2724 loader.gloader->base.num_subglyphs,
2725 glyph->outline.n_contours,
2726 glyph->outline.n_points,
2727 glyph->outline.flags ));
2730 tt_loader_done( &loader );
2733 #ifdef FT_DEBUG_LEVEL_TRACE
2735 FT_TRACE1(( " failed (error code 0x%x)\n",