ref: cdee7d1423f8c498d1c131adc82079ffb462fb07
parent: a678560dc23f7dfa6d6cda8d0d35be37c04713e2
author: Werner Lemberg <[email protected]>
date: Sun May 31 07:54:42 EDT 2015
[truetype] Add tracing information to GX code. * src/truetype/ttgxvar.c (ft_var_load_avar, ft_var_load_gvar, ft_var_apply_tuple, TT_Get_MM_Var, TT_Set_MM_Blend, TT_Set_Var_Design, tt_face_vary_cvt): Do it.
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2015-05-31 Werner Lemberg <[email protected]>
+
+ [truetype] Add tracing information to GX code.
+
+ * src/truetype/ttgxvar.c (ft_var_load_avar, ft_var_load_gvar,
+ ft_var_apply_tuple, TT_Get_MM_Var, TT_Set_MM_Blend,
+ TT_Set_Var_Design, tt_face_vary_cvt): Do it.
+
2015-05-28 Werner Lemberg <[email protected]>
* src/tools/apinames.c (names_dump): Fix invalid reference.
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -301,12 +301,15 @@
FT_UNUSED( error );
+ FT_TRACE2(( "AVAR " ));
+
blend->avar_checked = TRUE;
- if ( ( error = face->goto_table( face,
- TTAG_avar,
- stream,
- &table_len ) ) != 0 )
+ error = face->goto_table( face, TTAG_avar, stream, &table_len );
+ if ( error )
+ {
+ FT_TRACE2(( "is missing\n" ));
return;
+ }
if ( FT_FRAME_ENTER( table_len ) )
return;
@@ -314,10 +317,21 @@
version = FT_GET_LONG();
axisCount = FT_GET_LONG();
- if ( version != 0x00010000L ||
- axisCount != (FT_Long)blend->mmvar->num_axis )
+ if ( version != 0x00010000L )
+ {
+ FT_TRACE2(( "bad table version\n" ));
goto Exit;
+ }
+ FT_TRACE2(( "loaded\n" ));
+
+ if ( axisCount != (FT_Long)blend->mmvar->num_axis )
+ {
+ FT_TRACE2(( "ft_var_load_avar: number of axes in `avar' and `cvar'\n"
+ " table are different\n" ));
+ goto Exit;
+ }
+
if ( FT_NEW_ARRAY( blend->avar_segment, axisCount ) )
goto Exit;
@@ -324,6 +338,8 @@
segment = &blend->avar_segment[0];
for ( i = 0; i < axisCount; i++, segment++ )
{
+ FT_TRACE5(( " axis %d:\n", i ));
+
segment->pairCount = FT_GET_USHORT();
if ( FT_NEW_ARRAY( segment->correspondence, segment->pairCount ) )
{
@@ -343,7 +359,13 @@
/* convert to Fixed */
segment->correspondence[j].fromCoord = FT_GET_SHORT() << 2;
segment->correspondence[j].toCoord = FT_GET_SHORT() << 2;
+
+ FT_TRACE5(( " mapping %.4f to %.4f\n",
+ segment->correspondence[j].fromCoord / 65536.0,
+ segment->correspondence[j].toCoord / 65536.0 ));
}
+
+ FT_TRACE5(( "\n" ));
}
Exit:
@@ -410,11 +432,16 @@
};
+ FT_TRACE2(( "GVAR " ));
+
if ( ( error = face->goto_table( face,
TTAG_gvar,
stream,
&table_len ) ) != 0 )
+ {
+ FT_TRACE2(( "is missing\n" ));
goto Exit;
+ }
gvar_start = FT_STREAM_POS( );
if ( FT_STREAM_READ_FIELDS( gvar_fields, &gvar_head ) )
@@ -424,13 +451,26 @@
blend->gv_glyphcnt = gvar_head.glyphCount;
offsetToData = gvar_start + gvar_head.offsetToData;
- if ( gvar_head.version != (FT_Long)0x00010000L ||
- gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
+ if ( gvar_head.version != 0x00010000L )
{
+ FT_TRACE1(( "bad table version\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
+ FT_TRACE2(( "loaded\n" ));
+
+ if ( gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
+ {
+ FT_TRACE1(( "ft_var_load_gvar: number of axes in `gvar' and `cvar'\n"
+ " table are different\n" ));
+ error = FT_THROW( Invalid_Table );
+ goto Exit;
+ }
+
+ FT_TRACE5(( "gvar: there are %d shared coordinates:\n",
+ blend->tuplecount ));
+
if ( FT_NEW_ARRAY( blend->glyphoffsets, blend->gv_glyphcnt + 1 ) )
goto Exit;
@@ -469,10 +509,20 @@
goto Exit;
for ( i = 0; i < blend->tuplecount; i++ )
+ {
+ FT_TRACE5(( " [ " ));
for ( j = 0 ; j < (FT_UInt)gvar_head.axisCount; j++ )
+ {
blend->tuplecoords[i * gvar_head.axisCount + j] =
FT_GET_SHORT() << 2; /* convert to FT_Fixed */
+ FT_TRACE5(( "%.4f ",
+ blend->tuplecoords[i * gvar_head.axisCount + j] / 65536.0 ));
+ }
+ FT_TRACE5(( "]\n" ));
+ }
+ FT_TRACE5(( "\n" ));
+
FT_FRAME_EXIT();
}
@@ -521,46 +571,81 @@
for ( i = 0; i < blend->num_axis; i++ )
{
+ FT_TRACE6(( " axis coordinate %d (%.4f):\n",
+ i, blend->normalizedcoords[i] / 65536.0 ));
+
+ /* It's not clear why (for intermediate tuples) we don't need */
+ /* to check against start/end -- the documentation says we don't. */
+ /* Similarly, it's unclear why we don't need to scale along the */
+ /* axis. */
+
if ( tuple_coords[i] == 0 )
- /* It's not clear why (for intermediate tuples) we don't need */
- /* to check against start/end -- the documentation says we don't. */
- /* Similarly, it's unclear why we don't need to scale along the */
- /* axis. */
+ {
+ FT_TRACE6(( " tuple coordinate is zero, ignored\n", i ));
continue;
+ }
- else if ( blend->normalizedcoords[i] == 0 ||
- ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
+ else if ( blend->normalizedcoords[i] == 0 )
+ {
+ FT_TRACE6(( " axis coordinate is zero, stop\n" ));
+ apply = 0;
+ break;
+ }
+
+ else if ( ( blend->normalizedcoords[i] < 0 && tuple_coords[i] > 0 ) ||
( blend->normalizedcoords[i] > 0 && tuple_coords[i] < 0 ) )
{
+ FT_TRACE6(( " tuple coordinate value %.4f is exceeded, stop\n",
+ tuple_coords[i] / 65536.0 ));
apply = 0;
break;
}
else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
+ {
+ FT_TRACE6(( " tuple coordinate value %.4f fits\n",
+ tuple_coords[i] / 65536.0 ));
/* not an intermediate tuple */
apply = FT_MulFix( apply,
blend->normalizedcoords[i] > 0
? blend->normalizedcoords[i]
: -blend->normalizedcoords[i] );
+ }
else if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
blend->normalizedcoords[i] >= im_end_coords[i] )
{
+ FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] is exceeded,"
+ " stop\n",
+ im_start_coords[i] / 65536.0,
+ im_end_coords[i] / 65536.0 ));
apply = 0;
break;
}
else if ( blend->normalizedcoords[i] < tuple_coords[i] )
+ {
+ FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n",
+ im_start_coords[i] / 65536.0,
+ im_end_coords[i] / 65536.0 ));
apply = FT_MulDiv( apply,
blend->normalizedcoords[i] - im_start_coords[i],
tuple_coords[i] - im_start_coords[i] );
+ }
else
+ {
+ FT_TRACE6(( " intermediate tuple range [%.4f;%.4f] fits\n",
+ im_start_coords[i] / 65536.0,
+ im_end_coords[i] / 65536.0 ));
apply = FT_MulDiv( apply,
im_end_coords[i] - blend->normalizedcoords[i],
im_end_coords[i] - tuple_coords[i] );
+ }
}
+ FT_TRACE6(( " apply factor is %.4f\n", apply / 65536.0 ));
+
return apply;
}
@@ -674,14 +759,23 @@
if ( face->blend == NULL )
{
+ FT_TRACE2(( "FVAR " ));
+
/* both `fvar' and `gvar' must be present */
if ( ( error = face->goto_table( face, TTAG_gvar,
stream, &table_len ) ) != 0 )
+ {
+ FT_TRACE1(( "\n"
+ "TT_Get_MM_Var: `gvar' table is missing\n" ));
goto Exit;
+ }
if ( ( error = face->goto_table( face, TTAG_fvar,
stream, &table_len ) ) != 0 )
+ {
+ FT_TRACE1(( "is missing\n" ));
goto Exit;
+ }
fvar_start = FT_STREAM_POS( );
@@ -704,10 +798,16 @@
fvar_head.offsetToData + fvar_head.axisCount * 20U +
fvar_head.instanceCount * fvar_head.instanceSize > table_len )
{
+ FT_TRACE1(( "\n"
+ "TT_Get_MM_Var: invalid `fvar' header\n" ));
error = FT_THROW( Invalid_Table );
goto Exit;
}
+ FT_TRACE2(( "loaded\n" ));
+
+ FT_TRACE5(( "number of GX style axes: %d\n", fvar_head.axisCount ));
+
if ( FT_NEW( face->blend ) )
goto Exit;
@@ -779,9 +879,17 @@
a->name[3] = (FT_String)( ( a->tag ) & 0xFF );
a->name[4] = '\0';
+ FT_TRACE5(( " \"%s\": minimum=%.4f, default=%.4f, maximum=%.4f\n",
+ a->name,
+ a->minimum / 65536.0,
+ a->def / 65536.0,
+ a->maximum / 65536.0 ));
+
a++;
}
+ FT_TRACE5(( "\n" ));
+
ns = mmvar->namedstyle;
for ( i = 0; i < fvar_head.instanceCount; i++, ns++ )
{
@@ -907,15 +1015,29 @@
mmvar = blend->mmvar;
if ( num_coords > mmvar->num_axis )
+ {
+ FT_TRACE2(( "TT_Set_MM_Blend: only using first %d of %d coordinates\n",
+ mmvar->num_axis, num_coords ));
num_coords = mmvar->num_axis;
+ }
+ FT_TRACE5(( "normalized design coordinates:\n" ));
+
for ( i = 0; i < num_coords; i++ )
+ {
+ FT_TRACE5(( " %.4f\n", coords[i] / 65536.0 ));
if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
{
+ FT_TRACE1(( "TT_Set_MM_Blend: normalized design coordinate %.4f\n"
+ " is out of range [-1;1]\n",
+ coords[i] / 65536.0 ));
error = FT_THROW( Invalid_Argument );
goto Exit;
}
+ }
+ FT_TRACE5(( "\n" ));
+
if ( blend->glyphoffsets == NULL )
if ( ( error = ft_var_load_gvar( face ) ) != 0 )
goto Exit;
@@ -1046,7 +1168,12 @@
mmvar = blend->mmvar;
if ( num_coords > mmvar->num_axis )
+ {
+ FT_TRACE2(( "TT_Set_Var_Design:"
+ " only using first %d of %d coordinates\n",
+ mmvar->num_axis, num_coords ));
num_coords = mmvar->num_axis;
+ }
/* Axis normalization is a two stage process. First we normalize */
/* based on the [min,def,max] values for the axis to be [-1,0,1]. */
@@ -1055,11 +1182,19 @@
if ( FT_NEW_ARRAY( normalized, mmvar->num_axis ) )
goto Exit;
+ FT_TRACE5(( "design coordinates:\n" ));
+
a = mmvar->axis;
for ( i = 0; i < num_coords; i++, a++ )
{
+ FT_TRACE5(( " %.4f\n", coords[i] / 65536.0 ));
if ( coords[i] > a->maximum || coords[i] < a->minimum )
{
+ FT_TRACE1(( "TT_Set_Var_Design: normalized design coordinate %.4f\n"
+ " is out of range [%.4f;%.4f]\n",
+ coords[i] / 65536.0,
+ a->minimum / 65536.0,
+ a->maximum / 65536.0 ));
error = FT_THROW( Invalid_Argument );
goto Exit;
}
@@ -1074,6 +1209,8 @@
a->maximum - a->def );
}
+ FT_TRACE5(( "\n" ));
+
for ( ; i < mmvar->num_axis; i++ )
normalized[i] = 0;
@@ -1082,10 +1219,15 @@
if ( blend->avar_segment != NULL )
{
+ FT_TRACE5(( "normalized design coordinates"
+ " before applying `avar' data:\n" ));
+
av = blend->avar_segment;
for ( i = 0; i < mmvar->num_axis; i++, av++ )
{
for ( j = 1; j < (FT_UInt)av->pairCount; j++ )
+ {
+ FT_TRACE5(( " %.4f\n", normalized[i] / 65536.0 ));
if ( normalized[i] < av->correspondence[j].fromCoord )
{
normalized[i] =
@@ -1097,6 +1239,7 @@
av->correspondence[j - 1].toCoord;
break;
}
+ }
}
}
@@ -1163,8 +1306,8 @@
if ( blend == NULL )
{
- FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
-
+ FT_TRACE2(( "\n"
+ "tt_face_vary_cvt: no blend specified\n" ));
error = FT_Err_Ok;
goto Exit;
}
@@ -1171,8 +1314,8 @@
if ( face->cvt == NULL )
{
- FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
-
+ FT_TRACE2(( "\n"
+ "tt_face_vary_cvt: no `cvt ' table\n" ));
error = FT_Err_Ok;
goto Exit;
}
@@ -1201,6 +1344,8 @@
goto FExit;
}
+ FT_TRACE2(( "loaded\n" ));
+
if ( FT_NEW_ARRAY( tuple_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_start_coords, blend->num_axis ) ||
FT_NEW_ARRAY( im_end_coords, blend->num_axis ) )
@@ -1213,6 +1358,8 @@
/* tuplecount, but John Jenkins says that shared points don't apply */
/* to `cvar', and no other flags are defined. */
+ FT_TRACE5(( "cvar: there are %d tuples:\n", tupleCount ));
+
for ( i = 0; i < ( tupleCount & 0xFFF ); i++ )
{
FT_UInt tupleDataSize;
@@ -1220,6 +1367,8 @@
FT_Fixed apply;
+ FT_TRACE6(( " tuple %d:\n", i ));
+
tupleDataSize = FT_GET_USHORT();
tupleIndex = FT_GET_USHORT();
@@ -1280,22 +1429,70 @@
else if ( localpoints == ALL_POINTS )
{
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int count = 0;
+#endif
+
+
+ FT_TRACE7(( " CVT deltas:\n" ));
+
/* this means that there are deltas for every entry in cvt */
for ( j = 0; j < face->cvt_size; j++ )
- face->cvt[j] = (FT_Short)( face->cvt[j] +
+ {
+ FT_Long orig_cvt = face->cvt[j];
+
+
+ face->cvt[j] = (FT_Short)( orig_cvt +
FT_MulFix( deltas[j], apply ) );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( orig_cvt != face->cvt[j] )
+ {
+ FT_TRACE7(( " %d: %d -> %d\n",
+ j, orig_cvt, face->cvt[j] ));
+ count++;
+ }
+#endif
+ }
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE7(( " none\n" ));
+#endif
}
else
{
+#ifdef FT_DEBUG_LEVEL_TRACE
+ int count = 0;
+#endif
+
+
+ FT_TRACE7(( " CVT deltas:\n" ));
+
for ( j = 0; j < point_count; j++ )
{
- int pindex = localpoints[j];
+ int pindex = localpoints[j];
+ FT_Long orig_cvt = face->cvt[pindex];
- face->cvt[pindex] = (FT_Short)( face->cvt[pindex] +
+ face->cvt[pindex] = (FT_Short)( orig_cvt +
FT_MulFix( deltas[j], apply ) );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( orig_cvt != face->cvt[pindex] )
+ {
+ FT_TRACE7(( " %d: %d -> %d\n",
+ pindex, orig_cvt, face->cvt[pindex] ));
+ count++;
+ }
+#endif
}
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+ if ( !count )
+ FT_TRACE7(( " none\n" ));
+#endif
}
if ( localpoints != ALL_POINTS )
@@ -1306,6 +1503,8 @@
FT_Stream_SeekSet( stream, here );
}
+
+ FT_TRACE5(( "\n" ));
FExit:
FT_FRAME_EXIT();