summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/freetype/src/truetype/ttgload.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/freetype/src/truetype/ttgload.c')
-rw-r--r--src/3rdparty/freetype/src/truetype/ttgload.c795
1 files changed, 569 insertions, 226 deletions
diff --git a/src/3rdparty/freetype/src/truetype/ttgload.c b/src/3rdparty/freetype/src/truetype/ttgload.c
index a792ad44a0..39d9c3f736 100644
--- a/src/3rdparty/freetype/src/truetype/ttgload.c
+++ b/src/3rdparty/freetype/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
/* */
/* TrueType Glyph Loader (body). */
/* */
-/* Copyright 1996-2015 by */
+/* Copyright 1996-2018 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -18,12 +18,14 @@
#include <ft2build.h>
#include FT_INTERNAL_DEBUG_H
+#include FT_CONFIG_CONFIG_H
#include FT_INTERNAL_CALC_H
#include FT_INTERNAL_STREAM_H
#include FT_INTERNAL_SFNT_H
#include FT_TRUETYPE_TAGS_H
#include FT_OUTLINE_H
-#include FT_TRUETYPE_DRIVER_H
+#include FT_DRIVER_H
+#include FT_LIST_H
#include "ttgload.h"
#include "ttpload.h"
@@ -85,7 +87,7 @@
/*************************************************************************/
/* */
/* Return the vertical metrics in font units for a given glyph. */
- /* See macro `TT_LOADER_SET_PP' below for explanations. */
+ /* See function `tt_loader_set_pp' below for explanations. */
/* */
FT_LOCAL_DEF( void )
TT_Get_VMetrics( TT_Face face,
@@ -121,7 +123,7 @@
FT_UInt glyph_index )
{
TT_Face face = loader->face;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@@ -152,7 +154,7 @@
loader->top_bearing = top_bearing;
loader->vadvance = advance_height;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
loader->exec )
{
@@ -161,10 +163,10 @@
/* This may not be the right place for this, but it works... */
/* Note that we have to unconditionally load the tweaks since */
/* it is possible that glyphs individually switch ClearType's */
- /* backwards compatibility mode on and off. */
+ /* backward compatibility mode on and off. */
sph_set_tweaks( loader, glyph_index );
}
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
if ( !loader->linear_def )
{
@@ -193,39 +195,39 @@
if ( face->root.internal->incremental_interface &&
face->root.internal->incremental_interface->funcs->get_glyph_metrics )
{
- FT_Incremental_MetricsRec metrics;
+ FT_Incremental_MetricsRec incr_metrics;
FT_Error error;
- metrics.bearing_x = loader->left_bearing;
- metrics.bearing_y = 0;
- metrics.advance = loader->advance;
- metrics.advance_v = 0;
+ incr_metrics.bearing_x = loader->left_bearing;
+ incr_metrics.bearing_y = 0;
+ incr_metrics.advance = loader->advance;
+ incr_metrics.advance_v = 0;
error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
face->root.internal->incremental_interface->object,
- glyph_index, FALSE, &metrics );
+ glyph_index, FALSE, &incr_metrics );
if ( error )
goto Exit;
- left_bearing = (FT_Short)metrics.bearing_x;
- advance_width = (FT_UShort)metrics.advance;
+ left_bearing = (FT_Short)incr_metrics.bearing_x;
+ advance_width = (FT_UShort)incr_metrics.advance;
#if 0
/* GWW: Do I do the same for vertical metrics? */
- metrics.bearing_x = 0;
- metrics.bearing_y = loader->top_bearing;
- metrics.advance = loader->vadvance;
+ incr_metrics.bearing_x = 0;
+ incr_metrics.bearing_y = loader->top_bearing;
+ incr_metrics.advance = loader->vadvance;
error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
face->root.internal->incremental_interface->object,
- glyph_index, TRUE, &metrics );
+ glyph_index, TRUE, &incr_metrics );
if ( error )
goto Exit;
- top_bearing = (FT_Short)metrics.bearing_y;
- advance_height = (FT_UShort)metrics.advance;
+ top_bearing = (FT_Short)incr_metrics.bearing_y;
+ advance_height = (FT_UShort)incr_metrics.advance;
#endif /* 0 */
@@ -331,7 +333,6 @@
FT_Outline* outline;
FT_UShort n_ins;
FT_Int n_points;
- FT_ULong tmp;
FT_Byte *flag, *flag_limit;
FT_Byte c, count;
@@ -397,18 +398,21 @@
FT_TRACE5(( " Instructions size: %u\n", n_ins ));
- /* check it */
- if ( ( limit - p ) < n_ins )
- {
- FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
- error = FT_THROW( Too_Many_Hints );
- goto Fail;
- }
-
#ifdef TT_USE_BYTECODE_INTERPRETER
if ( IS_HINTED( load->load_flags ) )
{
+ FT_ULong tmp;
+
+
+ /* check instructions size */
+ if ( ( limit - p ) < n_ins )
+ {
+ FT_TRACE1(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
+ error = FT_THROW( Too_Many_Hints );
+ goto Fail;
+ }
+
/* we don't trust `maxSizeOfInstructions' in the `maxp' table */
/* and thus update the bytecode array size by ourselves */
@@ -426,7 +430,8 @@
load->glyph->control_len = n_ins;
load->glyph->control_data = load->exec->glyphIns;
- FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
+ if ( n_ins )
+ FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
}
#endif /* TT_USE_BYTECODE_INTERPRETER */
@@ -439,7 +444,7 @@
flag = (FT_Byte*)outline->tags;
flag_limit = flag + n_points;
- FT_ASSERT( flag != NULL );
+ FT_ASSERT( flag );
while ( flag < flag_limit )
{
@@ -659,6 +664,52 @@
} while ( subglyph->flags & MORE_COMPONENTS );
gloader->current.num_subglyphs = num_subglyphs;
+ FT_TRACE5(( " %d component%s\n",
+ num_subglyphs,
+ num_subglyphs > 1 ? "s" : "" ));
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ {
+ FT_UInt i;
+
+
+ subglyph = gloader->current.subglyphs;
+
+ for ( i = 0; i < num_subglyphs; i++ )
+ {
+ if ( num_subglyphs > 1 )
+ FT_TRACE7(( " subglyph %d:\n", i ));
+
+ FT_TRACE7(( " glyph index: %d\n", subglyph->index ));
+
+ if ( subglyph->flags & ARGS_ARE_XY_VALUES )
+ FT_TRACE7(( " offset: x=%d, y=%d\n",
+ subglyph->arg1,
+ subglyph->arg2 ));
+ else
+ FT_TRACE7(( " matching points: base=%d, component=%d\n",
+ subglyph->arg1,
+ subglyph->arg2 ));
+
+ if ( subglyph->flags & WE_HAVE_A_SCALE )
+ FT_TRACE7(( " scaling: %f\n",
+ subglyph->transform.xx / 65536.0 ));
+ else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
+ FT_TRACE7(( " scaling: x=%f, y=%f\n",
+ subglyph->transform.xx / 65536.0,
+ subglyph->transform.yy / 65536.0 ));
+ else if ( subglyph->flags & WE_HAVE_A_2X2 )
+ FT_TRACE7(( " scaling: xx=%f, yx=%f\n"
+ " xy=%f, yy=%f\n",
+ subglyph->transform.xx / 65536.0,
+ subglyph->transform.yx / 65536.0,
+ subglyph->transform.xy / 65536.0,
+ subglyph->transform.yy / 65536.0 ));
+
+ subglyph++;
+ }
+ }
+#endif /* FT_DEBUG_LEVEL_TRACE */
#ifdef TT_USE_BYTECODE_INTERPRETER
@@ -730,7 +781,8 @@
TT_Hint_Glyph( TT_Loader loader,
FT_Bool is_composite )
{
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
+ defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
TT_Face face = loader->face;
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@@ -749,7 +801,7 @@
{
FT_TRACE1(( "TT_Hint_Glyph: too long instructions" ));
FT_TRACE1(( " (0x%lx byte) is truncated\n",
- loader->glyph->control_len ));
+ loader->glyph->control_len ));
}
n_ins = loader->glyph->control_len;
@@ -771,8 +823,8 @@
}
else
{
- loader->exec->metrics.x_scale = loader->size->metrics.x_scale;
- loader->exec->metrics.y_scale = loader->size->metrics.y_scale;
+ loader->exec->metrics.x_scale = loader->size->metrics->x_scale;
+ loader->exec->metrics.y_scale = loader->size->metrics->y_scale;
}
#endif
@@ -813,13 +865,23 @@
#endif
- /* save glyph phantom points */
- loader->pp1 = zone->cur[zone->n_points - 4];
- loader->pp2 = zone->cur[zone->n_points - 3];
- loader->pp3 = zone->cur[zone->n_points - 2];
- loader->pp4 = zone->cur[zone->n_points - 1];
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ /* Save possibly modified glyph phantom points unless in v40 backward */
+ /* compatibility mode, where no movement on the x axis means no reason */
+ /* to change bearings or advance widths. */
+ if ( !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
+ loader->exec->backward_compatibility ) )
+ {
+#endif
+ loader->pp1 = zone->cur[zone->n_points - 4];
+ loader->pp2 = zone->cur[zone->n_points - 3];
+ loader->pp3 = zone->cur[zone->n_points - 2];
+ loader->pp4 = zone->cur[zone->n_points - 1];
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ }
+#endif
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
@@ -828,7 +890,7 @@
else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
}
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
return FT_Err_Ok;
}
@@ -872,13 +934,24 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( loader->face->doblend )
+ if ( FT_IS_NAMED_INSTANCE( FT_FACE( loader->face ) ) ||
+ FT_IS_VARIATION( FT_FACE( loader->face ) ) )
{
/* Deltas apply to the unscaled data. */
error = TT_Vary_Apply_Glyph_Deltas( loader->face,
loader->glyph_index,
outline,
(FT_UInt)n_points );
+
+ /* recalculate linear horizontal and vertical advances */
+ /* if we don't have HVAR and VVAR, respectively */
+ if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+ loader->linear = outline->points[n_points - 3].x -
+ outline->points[n_points - 4].x;
+ if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+ loader->vadvance = outline->points[n_points - 1].x -
+ outline->points[n_points - 2].x;
+
if ( error )
return error;
}
@@ -894,12 +967,12 @@
}
{
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
TT_Face face = loader->face;
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
FT_String* family = face->root.family_name;
- FT_UInt ppem = loader->size->metrics.x_ppem;
+ FT_UInt ppem = loader->size->metrics->x_ppem;
FT_String* style = face->root.style_name;
FT_UInt x_scale_factor = 1000;
#endif
@@ -913,7 +986,7 @@
FT_Bool do_scale = FALSE;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
@@ -928,9 +1001,9 @@
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
x_scale_factor != 1000 )
{
- x_scale = FT_MulDiv( loader->size->metrics.x_scale,
+ x_scale = FT_MulDiv( loader->size->metrics->x_scale,
(FT_Long)x_scale_factor, 1000 );
- y_scale = loader->size->metrics.y_scale;
+ y_scale = loader->size->metrics->y_scale;
/* compensate for any scaling by de/emboldening; */
/* the amount was determined via experimentation */
@@ -944,14 +1017,14 @@
}
else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
{
/* scale the glyph */
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
- x_scale = loader->size->metrics.x_scale;
- y_scale = loader->size->metrics.y_scale;
+ x_scale = loader->size->metrics->x_scale;
+ y_scale = loader->size->metrics->y_scale;
do_scale = TRUE;
}
@@ -964,9 +1037,24 @@
vec->x = FT_MulFix( vec->x, x_scale );
vec->y = FT_MulFix( vec->y, y_scale );
}
+ }
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* if we have a HVAR table, `pp1' and/or `pp2' are already adjusted */
+ if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ||
+ !IS_HINTED( loader->load_flags ) )
+#endif
+ {
loader->pp1 = outline->points[n_points - 4];
loader->pp2 = outline->points[n_points - 3];
+ }
+
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+ /* if we have a VVAR table, `pp3' and/or `pp4' are already adjusted */
+ if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ||
+ !IS_HINTED( loader->load_flags ) )
+#endif
+ {
loader->pp3 = outline->points[n_points - 2];
loader->pp4 = outline->points[n_points - 1];
}
@@ -1075,7 +1163,7 @@
: -subglyph->transform.yx;
int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
: -subglyph->transform.xy;
- int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
+ int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
: -subglyph->transform.yy;
int m = a > b ? a : b;
int n = c > d ? c : d;
@@ -1109,8 +1197,8 @@
if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
{
- FT_Fixed x_scale = loader->size->metrics.x_scale;
- FT_Fixed y_scale = loader->size->metrics.y_scale;
+ FT_Fixed x_scale = loader->size->metrics->x_scale;
+ FT_Fixed y_scale = loader->size->metrics->y_scale;
x = FT_MulFix( x, x_scale );
@@ -1118,8 +1206,28 @@
if ( subglyph->flags & ROUND_XY_TO_GRID )
{
- x = FT_PIX_ROUND( x );
- y = FT_PIX_ROUND( y );
+ TT_Face face = loader->face;
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
+
+
+ if ( IS_HINTED( loader->load_flags ) )
+ {
+ /*
+ * We round the horizontal offset only if there is hinting along
+ * the x axis; this corresponds to integer advance width values.
+ *
+ * Theoretically, a glyph's bytecode can toggle ClearType's
+ * `backward compatibility' mode, which would allow modification
+ * of the advance width. In reality, however, applications
+ * neither allow nor expect modified advance widths if subpixel
+ * rendering is active.
+ *
+ */
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_35 )
+ x = FT_PIX_ROUND( x );
+
+ y = FT_PIX_ROUND( y );
+ }
}
}
}
@@ -1321,49 +1429,72 @@
* (3) for everything else.
*
*/
+ static void
+ tt_loader_set_pp( TT_Loader loader )
+ {
+ FT_Bool subpixel_hinting = 0;
+ FT_Bool grayscale = 0;
+ FT_Bool use_aw_2 = 0;
+
#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
+#endif
+
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+ {
+ subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting
+ : 0;
+ grayscale = loader->exec ? loader->exec->grayscale
+ : 0;
+ }
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+ {
+ subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting_lean
+ : 0;
+ grayscale = loader->exec ? loader->exec->grayscale_cleartype
+ : 0;
+ }
+#endif
+
+ use_aw_2 = (FT_Bool)( subpixel_hinting && grayscale );
+
+ loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
+ loader->pp1.y = 0;
+ loader->pp2.x = loader->pp1.x + loader->advance;
+ loader->pp2.y = 0;
+
+ loader->pp3.x = use_aw_2 ? loader->advance / 2 : 0;
+ loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
+ loader->pp4.x = use_aw_2 ? loader->advance / 2 : 0;
+ loader->pp4.y = loader->pp3.y - loader->vadvance;
+ }
+
+
+ /* a utility function to retrieve i-th node from given FT_List */
+ static FT_ListNode
+ ft_list_get_node_at( FT_List list,
+ FT_UInt idx )
+ {
+ FT_ListNode cur;
+
-#define TT_LOADER_SET_PP( loader ) \
- do \
- { \
- FT_Bool subpixel_hinting_ = loader->exec \
- ? loader->exec->subpixel_hinting \
- : 0; \
- FT_Bool grayscale_ = loader->exec \
- ? loader->exec->grayscale \
- : 0; \
- FT_Bool use_aw_2_ = (FT_Bool)( subpixel_hinting_ && \
- grayscale_ ); \
- \
- \
- (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
- (loader)->pp1.y = 0; \
- (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
- (loader)->pp2.y = 0; \
- \
- (loader)->pp3.x = use_aw_2_ ? (loader)->advance / 2 : 0; \
- (loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing; \
- (loader)->pp4.x = use_aw_2_ ? (loader)->advance / 2 : 0; \
- (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
- } while ( 0 )
-
-#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
-
-#define TT_LOADER_SET_PP( loader ) \
- do \
- { \
- (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
- (loader)->pp1.y = 0; \
- (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
- (loader)->pp2.y = 0; \
- \
- (loader)->pp3.x = 0; \
- (loader)->pp3.y = (loader)->bbox.yMax + (loader)->top_bearing; \
- (loader)->pp4.x = 0; \
- (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
- } while ( 0 )
-
-#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+ if ( !list )
+ return NULL;
+
+ for ( cur = list->head; cur; cur = cur->next )
+ {
+ if ( !idx )
+ return cur;
+
+ idx--;
+ }
+
+ return NULL;
+ }
/*************************************************************************/
@@ -1395,13 +1526,17 @@
#endif
- /* some fonts have an incorrect value of `maxComponentDepth', */
- /* thus we allow depth 1 to catch the majority of them */
- if ( recurse_count > 1 &&
- recurse_count > face->max_profile.maxComponentDepth )
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( recurse_count )
+ FT_TRACE5(( " nesting level: %d\n", recurse_count ));
+#endif
+
+ /* some fonts have an incorrect value of `maxComponentDepth' */
+ if ( recurse_count > face->max_profile.maxComponentDepth )
{
- error = FT_THROW( Invalid_Composite );
- goto Exit;
+ FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %d\n",
+ recurse_count ));
+ face->max_profile.maxComponentDepth = (FT_UShort)recurse_count;
}
#ifndef FT_CONFIG_OPTION_INCREMENTAL
@@ -1417,8 +1552,8 @@
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
- x_scale = loader->size->metrics.x_scale;
- y_scale = loader->size->metrics.y_scale;
+ x_scale = loader->size->metrics->x_scale;
+ y_scale = loader->size->metrics->y_scale;
}
else
{
@@ -1447,7 +1582,7 @@
offset = 0;
loader->byte_len = glyph_data.length;
- FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
+ FT_ZERO( &inc_stream );
FT_Stream_OpenMemory( &inc_stream,
glyph_data.pointer,
(FT_ULong)glyph_data.length );
@@ -1465,10 +1600,10 @@
{
#ifdef FT_CONFIG_OPTION_INCREMENTAL
/* for the incremental interface, `glyf_offset' is always zero */
- if ( !loader->glyf_offset &&
+ if ( !face->glyf_offset &&
!face->root.internal->incremental_interface )
#else
- if ( !loader->glyf_offset )
+ if ( !face->glyf_offset )
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
{
FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
@@ -1477,7 +1612,7 @@
}
error = face->access_glyph_frame( loader, glyph_index,
- loader->glyf_offset + offset,
+ face->glyf_offset + offset,
(FT_UInt)loader->byte_len );
if ( error )
goto Exit;
@@ -1516,7 +1651,7 @@
/* must initialize points before (possibly) overriding */
/* glyph metrics from the incremental interface */
- TT_LOADER_SET_PP( loader );
+ tt_loader_set_pp( loader );
#ifdef FT_CONFIG_OPTION_INCREMENTAL
tt_get_metrics_incr_overrides( loader, glyph_index );
@@ -1524,7 +1659,8 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( loader->face->doblend )
+ if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
+ FT_IS_VARIATION( FT_FACE( face ) ) )
{
/* a small outline structure with four elements for */
/* communication with `TT_Vary_Apply_Glyph_Deltas' */
@@ -1567,6 +1703,14 @@
loader->pp3.y = points[2].y;
loader->pp4.x = points[3].x;
loader->pp4.y = points[3].y;
+
+
+ /* recalculate linear horizontal and vertical advances */
+ /* if we don't have HVAR and VVAR, respectively */
+ if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+ loader->linear = loader->pp2.x - loader->pp1.x;
+ if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+ loader->vadvance = loader->pp4.x - loader->pp3.x;
}
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
@@ -1591,7 +1735,7 @@
/* must initialize phantom points before (possibly) overriding */
/* glyph metrics from the incremental interface */
- TT_LOADER_SET_PP( loader );
+ tt_loader_set_pp( loader );
#ifdef FT_CONFIG_OPTION_INCREMENTAL
tt_get_metrics_incr_overrides( loader, glyph_index );
@@ -1625,12 +1769,53 @@
/***********************************************************************/
/* otherwise, load a composite! */
- else if ( loader->n_contours == -1 )
+ else if ( loader->n_contours < 0 )
{
+ FT_Memory memory = face->root.memory;
+
FT_UInt start_point;
FT_UInt start_contour;
FT_ULong ins_pos; /* position of composite instructions, if any */
+ FT_ListNode node, node2;
+
+
+ /* normalize the `n_contours' value */
+ loader->n_contours = -1;
+
+ /*
+ * We store the glyph index directly in the `node->data' pointer,
+ * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
+ * double cast to make this portable. Note, however, that this needs
+ * pointers with a width of at least 32 bits.
+ */
+
+
+ /* clear the nodes filled by sibling chains */
+ node = ft_list_get_node_at( &loader->composites, recurse_count );
+ for ( node2 = node; node2; node2 = node2->next )
+ node2->data = (void*)FT_ULONG_MAX;
+
+ /* check whether we already have a composite glyph with this index */
+ if ( FT_List_Find( &loader->composites,
+ FT_UINT_TO_POINTER( glyph_index ) ) )
+ {
+ FT_TRACE1(( "TT_Load_Composite_Glyph:"
+ " infinite recursion detected\n" ));
+ error = FT_THROW( Invalid_Composite );
+ goto Exit;
+ }
+
+ else if ( node )
+ node->data = FT_UINT_TO_POINTER( glyph_index );
+
+ else
+ {
+ if ( FT_NEW( node ) )
+ goto Exit;
+ node->data = FT_UINT_TO_POINTER( glyph_index );
+ FT_List_Add( &loader->composites, node );
+ }
start_point = (FT_UInt)gloader->base.outline.n_points;
start_contour = (FT_UInt)gloader->base.outline.n_contours;
@@ -1649,7 +1834,8 @@
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
- if ( face->doblend )
+ if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
+ FT_IS_VARIATION( FT_FACE( face ) ) )
{
short i, limit;
FT_SubGlyph subglyph;
@@ -1659,8 +1845,6 @@
char* tags = NULL;
short* contours = NULL;
- FT_Memory memory = face->root.memory;
-
limit = (short)gloader->current.num_subglyphs;
@@ -1669,6 +1853,10 @@
outline.n_points = (short)( gloader->current.num_subglyphs + 4 );
outline.n_contours = outline.n_points;
+ outline.points = NULL;
+ outline.tags = NULL;
+ outline.contours = NULL;
+
if ( FT_NEW_ARRAY( points, outline.n_points ) ||
FT_NEW_ARRAY( tags, outline.n_points ) ||
FT_NEW_ARRAY( contours, outline.n_points ) )
@@ -1716,22 +1904,22 @@
/* this call provides additional offsets */
/* for each component's translation */
- if ( ( error = TT_Vary_Apply_Glyph_Deltas(
- face,
- glyph_index,
- &outline,
- (FT_UInt)outline.n_points ) ) != 0 )
+ if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas(
+ face,
+ glyph_index,
+ &outline,
+ (FT_UInt)outline.n_points ) ) )
goto Exit1;
subglyph = gloader->current.subglyphs;
for ( i = 0; i < limit; i++, subglyph++ )
{
- /* XXX: overflow check for subglyph->{arg1,arg2}. */
- /* Deltas must be within signed 16-bit, */
- /* but the restriction of summed deltas is not clear */
- subglyph->arg1 = (FT_Int16)points[i].x;
- subglyph->arg2 = (FT_Int16)points[i].y;
+ if ( subglyph->flags & ARGS_ARE_XY_VALUES )
+ {
+ subglyph->arg1 = (FT_Int16)points[i].x;
+ subglyph->arg2 = (FT_Int16)points[i].y;
+ }
}
loader->pp1.x = points[i + 0].x;
@@ -1744,6 +1932,13 @@
loader->pp4.x = points[i + 3].x;
loader->pp4.y = points[i + 3].y;
+ /* recalculate linear horizontal and vertical advances */
+ /* if we don't have HVAR and VVAR, respectively */
+ if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
+ loader->linear = loader->pp2.x - loader->pp1.x;
+ if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
+ loader->vadvance = loader->pp4.x - loader->pp3.x;
+
Exit1:
FT_FREE( outline.points );
FT_FREE( outline.tags );
@@ -1803,6 +1998,9 @@
{
FT_Vector pp[4];
+ FT_Int linear_hadvance;
+ FT_Int linear_vadvance;
+
/* Each time we call load_truetype_glyph in this loop, the */
/* value of `gloader.base.subglyphs' can change due to table */
@@ -1815,6 +2013,9 @@
pp[2] = loader->pp3;
pp[3] = loader->pp4;
+ linear_hadvance = loader->linear;
+ linear_vadvance = loader->vadvance;
+
num_base_points = (FT_UInt)gloader->base.outline.n_points;
error = load_truetype_glyph( loader,
@@ -1834,6 +2035,9 @@
loader->pp2 = pp[1];
loader->pp3 = pp[2];
loader->pp4 = pp[3];
+
+ loader->linear = linear_hadvance;
+ loader->vadvance = linear_vadvance;
}
num_points = (FT_UInt)gloader->base.outline.n_points;
@@ -1874,12 +2078,6 @@
}
}
}
- else
- {
- /* invalid composite count (negative but not -1) */
- error = FT_THROW( Invalid_Outline );
- goto Exit;
- }
/***********************************************************************/
/***********************************************************************/
@@ -1908,7 +2106,8 @@
FT_UInt glyph_index )
{
TT_Face face = loader->face;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
+ defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
@@ -1920,7 +2119,7 @@
y_scale = 0x10000L;
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
- y_scale = size->root.metrics.y_scale;
+ y_scale = size->metrics->y_scale;
if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
FT_Outline_Get_CBox( &glyph->outline, &bbox );
@@ -1935,20 +2134,27 @@
glyph->metrics.horiBearingY = bbox.yMax;
glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
- /* adjust advance width to the value contained in the hdmx table */
- /* unless FT_LOAD_COMPUTE_METRICS is set */
- if ( !face->postscript.isFixedPitch &&
- IS_HINTED( loader->load_flags ) &&
- !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
+ /* Adjust advance width to the value contained in the hdmx table */
+ /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */
+ /* mode of the v40 interpreter is active. See `ttinterp.h' for */
+ /* details on backward compatibility mode. */
+ if (
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
+ ( loader->exec && loader->exec->backward_compatibility ) ) &&
+#endif
+ !face->postscript.isFixedPitch &&
+ IS_HINTED( loader->load_flags ) &&
+ !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) )
{
FT_Byte* widthp;
widthp = tt_face_get_device_metrics( face,
- size->root.metrics.x_ppem,
+ size->metrics->x_ppem,
glyph_index );
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
@@ -1966,7 +2172,7 @@
}
else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
{
if ( widthp )
@@ -1975,8 +2181,8 @@
}
/* set glyph dimensions */
- glyph->metrics.width = bbox.xMax - bbox.xMin;
- glyph->metrics.height = bbox.yMax - bbox.yMin;
+ glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin );
+ glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin );
/* Now take care of vertical metrics. In the case where there is */
/* no vertical information within the font (relatively common), */
@@ -2012,7 +2218,8 @@
/* table in the font. Otherwise, we use the */
/* values defined in the horizontal header. */
- height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
+ height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax,
+ bbox.yMin ),
y_scale );
if ( face->os2.version != 0xFFFFU )
advance = (FT_Pos)( face->os2.sTypoAscender -
@@ -2027,7 +2234,7 @@
#ifdef FT_CONFIG_OPTION_INCREMENTAL
{
FT_Incremental_InterfaceRec* incr;
- FT_Incremental_MetricsRec metrics;
+ FT_Incremental_MetricsRec incr_metrics;
FT_Error error;
@@ -2037,19 +2244,19 @@
/* overriding metrics for this glyph. */
if ( incr && incr->funcs->get_glyph_metrics )
{
- metrics.bearing_x = 0;
- metrics.bearing_y = top;
- metrics.advance = advance;
+ incr_metrics.bearing_x = 0;
+ incr_metrics.bearing_y = top;
+ incr_metrics.advance = advance;
error = incr->funcs->get_glyph_metrics( incr->object,
glyph_index,
TRUE,
- &metrics );
+ &incr_metrics );
if ( error )
return error;
- top = metrics.bearing_y;
- advance = metrics.advance;
+ top = incr_metrics.bearing_y;
+ advance = incr_metrics.advance;
}
}
@@ -2091,7 +2298,7 @@
SFNT_Service sfnt;
FT_Stream stream;
FT_Error error;
- TT_SBit_MetricsRec metrics;
+ TT_SBit_MetricsRec sbit_metrics;
face = (TT_Face)glyph->face;
@@ -2104,34 +2311,34 @@
(FT_UInt)load_flags,
stream,
&glyph->bitmap,
- &metrics );
+ &sbit_metrics );
if ( !error )
{
glyph->outline.n_points = 0;
glyph->outline.n_contours = 0;
- glyph->metrics.width = (FT_Pos)metrics.width * 64;
- glyph->metrics.height = (FT_Pos)metrics.height * 64;
+ glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64;
+ glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64;
- glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX * 64;
- glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY * 64;
- glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance * 64;
+ glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64;
+ glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64;
+ glyph->metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64;
- glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX * 64;
- glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY * 64;
- glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance * 64;
+ glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64;
+ glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64;
+ glyph->metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64;
glyph->format = FT_GLYPH_FORMAT_BITMAP;
if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
{
- glyph->bitmap_left = metrics.vertBearingX;
- glyph->bitmap_top = metrics.vertBearingY;
+ glyph->bitmap_left = sbit_metrics.vertBearingX;
+ glyph->bitmap_top = sbit_metrics.vertBearingY;
}
else
{
- glyph->bitmap_left = metrics.horiBearingX;
- glyph->bitmap_top = metrics.horiBearingY;
+ glyph->bitmap_left = sbit_metrics.horiBearingX;
+ glyph->bitmap_top = sbit_metrics.horiBearingY;
}
}
@@ -2148,19 +2355,23 @@
FT_Int32 load_flags,
FT_Bool glyf_table_only )
{
- FT_Error error;
-
TT_Face face;
FT_Stream stream;
+
#ifdef TT_USE_BYTECODE_INTERPRETER
+ FT_Error error;
FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
+#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
+ defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
+#endif
#endif
face = (TT_Face)glyph->face;
stream = face->root.stream;
- FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
+ FT_ZERO( loader );
#ifdef TT_USE_BYTECODE_INTERPRETER
@@ -2168,11 +2379,13 @@
if ( IS_HINTED( load_flags ) && !glyf_table_only )
{
TT_ExecContext exec;
- FT_Bool grayscale;
-
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
- TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
+ FT_Bool grayscale = TRUE;
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ FT_Bool subpixel_hinting_lean;
+ FT_Bool grayscale_cleartype;
+#endif
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
FT_Bool subpixel_hinting = FALSE;
#if 0
@@ -2184,7 +2397,7 @@
FT_Bool subpixel_positioned;
FT_Bool gray_cleartype;
#endif
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
FT_Bool reexecute = FALSE;
@@ -2205,7 +2418,32 @@
if ( !exec )
return FT_THROW( Could_Not_Find_Context );
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+ {
+ subpixel_hinting_lean =
+ FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+ FT_RENDER_MODE_MONO );
+ grayscale_cleartype =
+ FT_BOOL( subpixel_hinting_lean &&
+ !( ( load_flags &
+ FT_LOAD_TARGET_LCD ) ||
+ ( load_flags &
+ FT_LOAD_TARGET_LCD_V ) ) );
+ exec->vertical_lcd_lean =
+ FT_BOOL( subpixel_hinting_lean &&
+ ( load_flags &
+ FT_LOAD_TARGET_LCD_V ) );
+ }
+ else
+ {
+ subpixel_hinting_lean = FALSE;
+ grayscale_cleartype = FALSE;
+ exec->vertical_lcd_lean = FALSE;
+ }
+#endif
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
@@ -2262,18 +2500,23 @@
}
else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
- {
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+ grayscale = FT_BOOL( !subpixel_hinting_lean &&
+ FT_LOAD_TARGET_MODE( load_flags ) !=
+ FT_RENDER_MODE_MONO );
+ else
+#endif
grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
- FT_RENDER_MODE_MONO );
- }
+ FT_RENDER_MODE_MONO );
error = TT_Load_Context( exec, face, size );
if ( error )
return error;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
{
@@ -2301,9 +2544,37 @@
}
else
-#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
{
+
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
+ {
+ /* a change from mono to subpixel rendering (and vice versa) */
+ /* requires a re-execution of the CVT program */
+ if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
+ {
+ FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
+ " re-executing `prep' table\n" ));
+
+ exec->subpixel_hinting_lean = subpixel_hinting_lean;
+ reexecute = TRUE;
+ }
+
+ /* a change from colored to grayscale subpixel rendering (and */
+ /* vice versa) requires a re-execution of the CVT program */
+ if ( grayscale_cleartype != exec->grayscale_cleartype )
+ {
+ FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
+ " re-executing `prep' table\n" ));
+
+ exec->grayscale_cleartype = grayscale_cleartype;
+ reexecute = TRUE;
+ }
+ }
+#endif
+
/* a change from mono to grayscale rendering (and vice versa) */
/* requires a re-execution of the CVT program */
if ( grayscale != exec->grayscale )
@@ -2336,10 +2607,11 @@
if ( exec->GS.instruct_control & 2 )
exec->GS = tt_default_graphics_state;
-#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
/* check whether we have a font hinted for ClearType -- */
/* note that this flag can also be modified in a glyph's bytecode */
- if ( exec->GS.instruct_control & 4 )
+ if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
+ exec->GS.instruct_control & 4 )
exec->ignore_x_mode = 0;
#endif
@@ -2350,32 +2622,6 @@
#endif /* TT_USE_BYTECODE_INTERPRETER */
- /* seek to the beginning of the glyph table -- for Type 42 fonts */
- /* the table might be accessed from a Postscript stream or something */
- /* else... */
-
-#ifdef FT_CONFIG_OPTION_INCREMENTAL
-
- if ( face->root.internal->incremental_interface )
- loader->glyf_offset = 0;
- else
-
-#endif
-
- {
- error = face->goto_table( face, TTAG_glyf, stream, 0 );
-
- if ( FT_ERR_EQ( error, Table_Missing ) )
- loader->glyf_offset = 0;
- else if ( error )
- {
- FT_ERROR(( "tt_loader_init: could not access glyph table\n" ));
- return error;
- }
- else
- loader->glyf_offset = FT_STREAM_POS();
- }
-
/* get face's glyph loader */
if ( !glyf_table_only )
{
@@ -2393,10 +2639,23 @@
loader->glyph = (FT_GlyphSlot)glyph;
loader->stream = stream;
+ loader->composites.head = NULL;
+ loader->composites.tail = NULL;
+
return FT_Err_Ok;
}
+ static void
+ tt_loader_done( TT_Loader loader )
+ {
+ FT_List_Finalize( &loader->composites,
+ NULL,
+ loader->face->root.memory,
+ NULL );
+ }
+
+
/*************************************************************************/
/* */
/* <Function> */
@@ -2433,39 +2692,108 @@
FT_Error error;
TT_LoaderRec loader;
+#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
+#define IS_DEFAULT_INSTANCE ( !( FT_IS_NAMED_INSTANCE( glyph->face ) || \
+ FT_IS_VARIATION( glyph->face ) ) )
+#else
+#define IS_DEFAULT_INSTANCE 1
+#endif
+
FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
- /* try to load embedded bitmap if any */
- /* */
- /* XXX: The convention should be emphasized in */
- /* the documents because it can be confusing. */
+ /* try to load embedded bitmap (if any) */
if ( size->strike_index != 0xFFFFFFFFUL &&
- ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
+ ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
+ IS_DEFAULT_INSTANCE )
{
+ FT_Fixed x_scale = size->root.metrics.x_scale;
+ FT_Fixed y_scale = size->root.metrics.y_scale;
+
+
error = load_sbit_image( size, glyph, glyph_index, load_flags );
- if ( !error )
+ if ( FT_ERR_EQ( error, Missing_Bitmap ) )
+ {
+ /* the bitmap strike is incomplete and misses the requested glyph; */
+ /* if we have a bitmap-only font, return an empty glyph */
+ if ( !FT_IS_SCALABLE( glyph->face ) )
+ {
+ TT_Face face = (TT_Face)glyph->face;
+
+ FT_Short left_bearing = 0;
+ FT_Short top_bearing = 0;
+
+ FT_UShort advance_width = 0;
+ FT_UShort advance_height = 0;
+
+
+ /* to return an empty glyph, however, we need metrics data */
+ /* from the `hmtx' (or `vmtx') table; the assumption is that */
+ /* empty glyphs are missing intentionally, representing */
+ /* whitespace - not having at least horizontal metrics is */
+ /* thus considered an error */
+ if ( !face->horz_metrics_size )
+ return error;
+
+ /* we now construct an empty bitmap glyph */
+ TT_Get_HMetrics( face, glyph_index,
+ &left_bearing,
+ &advance_width );
+ TT_Get_VMetrics( face, glyph_index,
+ 0,
+ &top_bearing,
+ &advance_height );
+
+ glyph->outline.n_points = 0;
+ glyph->outline.n_contours = 0;
+
+ glyph->metrics.width = 0;
+ glyph->metrics.height = 0;
+
+ glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale );
+ glyph->metrics.horiBearingY = 0;
+ glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale );
+
+ glyph->metrics.vertBearingX = 0;
+ glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale );
+ glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale );
+
+ glyph->format = FT_GLYPH_FORMAT_BITMAP;
+ glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
+
+ glyph->bitmap_left = 0;
+ glyph->bitmap_top = 0;
+
+ return FT_Err_Ok;
+ }
+ }
+ else if ( error )
+ {
+ /* return error if font is not scalable */
+ if ( !FT_IS_SCALABLE( glyph->face ) )
+ return error;
+ }
+ else
{
if ( FT_IS_SCALABLE( glyph->face ) )
{
/* for the bbox we need the header only */
(void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
(void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
+ tt_loader_done( &loader );
glyph->linearHoriAdvance = loader.linear;
glyph->linearVertAdvance = loader.vadvance;
/* sanity checks: if `xxxAdvance' in the sbit metric */
/* structure isn't set, use `linearXXXAdvance' */
if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
- glyph->metrics.horiAdvance =
- FT_MulFix( glyph->linearHoriAdvance,
- size->root.metrics.x_scale );
+ glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance,
+ x_scale );
if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
- glyph->metrics.vertAdvance =
- FT_MulFix( glyph->linearVertAdvance,
- size->root.metrics.y_scale );
+ glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance,
+ y_scale );
}
return FT_Err_Ok;
@@ -2476,14 +2804,20 @@
/* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
- return FT_THROW( Invalid_Size_Handle );
+ {
+ error = FT_THROW( Invalid_Size_Handle );
+ goto Exit;
+ }
if ( load_flags & FT_LOAD_SBITS_ONLY )
- return FT_THROW( Invalid_Argument );
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
if ( error )
- return error;
+ goto Exit;
glyph->format = FT_GLYPH_FORMAT_OUTLINE;
glyph->num_subglyphs = 0;
@@ -2548,14 +2882,23 @@
error = compute_glyph_metrics( &loader, glyph_index );
}
+ tt_loader_done( &loader );
+
/* Set the `high precision' bit flag. */
/* This is _critical_ to get correct output for monochrome */
/* TrueType glyphs at all sizes using the bytecode interpreter. */
/* */
if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
- size->root.metrics.y_ppem < 24 )
+ size->metrics->y_ppem < 24 )
glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
+ Exit:
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( error )
+ FT_TRACE1(( " failed (error code 0x%x)\n",
+ error ));
+#endif
+
return error;
}