Commits (2)
  • Alexei Podtelezhnikov's avatar
    [truetype/GX] Clean up phantom point adjustment. · 705f4161
    Alexei Podtelezhnikov authored
    This moves phantom point and advance variation adjustment next to
    calculations. The logic stays the same, HVAR and VVAR take priority.
    
    * src/truetype/ttgload.c (load_truetype_glyph): Move it from here...
    * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): ... to here
    and check for HVAR and VVAR presence outside the main loop.
    705f4161
  • Alexei Podtelezhnikov's avatar
    [truetype] Clean up phantom point accounting. · 47103b2f
    Alexei Podtelezhnikov authored
    This formalizes that the phantom points appended in the outline
    do not increase its point count, nor are they tagged or included
    in any additional contours.  Only their coordinates are stored.
    They are counted in the glyph zone, however.
    
    * src/truetype/ttgxvar.c (TT_Vary_Apply_Glyph_Deltas): Infer `n_points`
    from the outline size plus four phantom points.
    * src/truetype/ttgxvar.h (TT_Vary_Apply_Glyph_Deltas): Remove this
    argument.
    * src/truetype/ttgload.c (tt_prepare_zone): Add phantom four.
    (TT_Process_Simple_Glyph, load_truetype_glyph): Update all callers.
    47103b2f
......@@ -801,7 +801,7 @@
FT_UInt start_point,
FT_UInt start_contour )
{
zone->n_points = (FT_UShort)load->outline.n_points -
zone->n_points = (FT_UShort)load->outline.n_points + 4 -
(FT_UShort)start_point;
zone->n_contours = load->outline.n_contours -
(FT_Short)start_contour;
......@@ -970,11 +970,6 @@
outline->points[n_points + 2] = loader->pp3;
outline->points[n_points + 3] = loader->pp4;
outline->tags[n_points ] = 0;
outline->tags[n_points + 1] = 0;
outline->tags[n_points + 2] = 0;
outline->tags[n_points + 3] = 0;
n_points += 4;
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
......@@ -987,8 +982,7 @@
/* Deltas apply to the unscaled data. */
error = TT_Vary_Apply_Glyph_Deltas( loader,
outline,
unrounded,
(FT_UInt)n_points );
unrounded );
if ( error )
goto Exit;
}
......@@ -1000,7 +994,7 @@
tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
loader->zone.n_points + 4 );
loader->zone.n_points );
}
{
......@@ -1142,11 +1136,7 @@
}
if ( IS_HINTED( loader->load_flags ) )
{
loader->zone.n_points += 4;
error = TT_Hint_Glyph( loader, 0 );
}
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
Exit:
......@@ -1359,11 +1349,6 @@
outline->points[outline->n_points + 2] = loader->pp3;
outline->points[outline->n_points + 3] = loader->pp4;
outline->tags[outline->n_points ] = 0;
outline->tags[outline->n_points + 1] = 0;
outline->tags[outline->n_points + 2] = 0;
outline->tags[outline->n_points + 3] = 0;
#ifdef TT_USE_BYTECODE_INTERPRETER
{
......@@ -1422,11 +1407,9 @@
/* Some points are likely touched during execution of */
/* instructions on components. So let's untouch them. */
for ( i = 0; i < loader->zone.n_points; i++ )
for ( i = 0; i < loader->zone.n_points - 4; i++ )
loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
loader->zone.n_points += 4;
return TT_Hint_Glyph( loader, 1 );
}
......@@ -1747,47 +1730,29 @@
/* a small outline structure with four elements for */
/* communication with `TT_Vary_Apply_Glyph_Deltas' */
FT_Vector points[4];
char tags[4] = { 1, 1, 1, 1 };
short contours[4] = { 0, 1, 2, 3 };
FT_Outline outline;
/* unrounded values */
FT_Vector unrounded[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
points[0].x = loader->pp1.x;
points[0].y = loader->pp1.y;
points[1].x = loader->pp2.x;
points[1].y = loader->pp2.y;
points[0] = loader->pp1;
points[1] = loader->pp2;
points[2] = loader->pp3;
points[3] = loader->pp4;
points[2].x = loader->pp3.x;
points[2].y = loader->pp3.y;
points[3].x = loader->pp4.x;
points[3].y = loader->pp4.y;
outline.n_points = 4;
outline.n_contours = 4;
outline.n_points = 0;
outline.n_contours = 0;
outline.points = points;
outline.tags = tags;
outline.contours = contours;
outline.tags = NULL;
outline.contours = NULL;
/* this must be done before scaling */
error = TT_Vary_Apply_Glyph_Deltas( loader,
&outline,
unrounded,
(FT_UInt)outline.n_points );
unrounded );
if ( error )
goto Exit;
loader->pp1.x = points[0].x;
loader->pp1.y = points[0].y;
loader->pp2.x = points[1].x;
loader->pp2.y = points[1].y;
loader->pp3.x = points[2].x;
loader->pp3.y = points[2].y;
loader->pp4.x = points[3].x;
loader->pp4.y = points[3].y;
}
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
......@@ -1935,17 +1900,16 @@
/* construct an outline structure for */
/* communication with `TT_Vary_Apply_Glyph_Deltas' */
outline.n_points = (short)( gloader->current.num_subglyphs + 4 );
outline.n_contours = outline.n_points;
outline.n_contours = outline.n_points = limit;
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 ) ||
FT_NEW_ARRAY( unrounded, outline.n_points ) )
if ( FT_NEW_ARRAY( points, limit + 4 ) ||
FT_NEW_ARRAY( tags, limit + 4 ) ||
FT_NEW_ARRAY( contours, limit + 4 ) ||
FT_NEW_ARRAY( unrounded, limit + 4 ) )
goto Exit1;
subglyph = gloader->current.subglyphs;
......@@ -1961,28 +1925,10 @@
contours[i] = i;
}
points[i].x = loader->pp1.x;
points[i].y = loader->pp1.y;
tags[i] = 1;
contours[i] = i;
i++;
points[i].x = loader->pp2.x;
points[i].y = loader->pp2.y;
tags[i] = 1;
contours[i] = i;
i++;
points[i].x = loader->pp3.x;
points[i].y = loader->pp3.y;
tags[i] = 1;
contours[i] = i;
i++;
points[i].x = loader->pp4.x;
points[i].y = loader->pp4.y;
tags[i] = 1;
contours[i] = i;
points[i++] = loader->pp1;
points[i++] = loader->pp2;
points[i++] = loader->pp3;
points[i ] = loader->pp4;
outline.points = points;
outline.tags = tags;
......@@ -1990,11 +1936,9 @@
/* this call provides additional offsets */
/* for each component's translation */
if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas(
loader,
&outline,
unrounded,
(FT_UInt)outline.n_points ) ) )
if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas( loader,
&outline,
unrounded ) ) )
goto Exit1;
subglyph = gloader->current.subglyphs;
......@@ -2008,16 +1952,6 @@
}
}
loader->pp1.x = points[i + 0].x;
loader->pp1.y = points[i + 0].y;
loader->pp2.x = points[i + 1].x;
loader->pp2.y = points[i + 1].y;
loader->pp3.x = points[i + 2].x;
loader->pp3.y = points[i + 2].y;
loader->pp4.x = points[i + 3].x;
loader->pp4.y = points[i + 3].y;
Exit1:
FT_FREE( outline.points );
FT_FREE( outline.tags );
......
......@@ -3839,25 +3839,20 @@
* An array with `n_points' elements that is filled with unrounded
* point coordinates (in 26.6 format).
*
* @Input
* n_points ::
* The number of the points in the glyph, including
* phantom points.
*
* @Return:
* FreeType error code. 0 means success.
*/
FT_LOCAL_DEF( FT_Error )
TT_Vary_Apply_Glyph_Deltas( TT_Loader loader,
FT_Outline* outline,
FT_Vector* unrounded,
FT_UInt n_points )
FT_Vector* unrounded )
{
FT_Error error;
TT_Face face = loader->face;
FT_Stream stream = face->root.stream;
FT_Memory memory = stream->memory;
FT_UInt glyph_index = loader->glyph_index;
FT_UInt n_points = (FT_UInt)outline->n_points + 4;
FT_Vector* points_org = NULL; /* coordinates in 16.16 format */
FT_Vector* points_out = NULL; /* coordinates in 16.16 format */
......@@ -4075,36 +4070,8 @@
FT_Fixed point_delta_y = FT_MulFix( deltas_y[j], apply );
if ( j < n_points - 4 )
{
point_deltas_x[j] = old_point_delta_x + point_delta_x;
point_deltas_y[j] = old_point_delta_y + point_delta_y;
}
else
{
/* To avoid double adjustment of advance width or height, */
/* adjust phantom points only if there is no HVAR or VVAR */
/* support, respectively. */
if ( j == ( n_points - 4 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_LSB ) )
point_deltas_x[j] = old_point_delta_x + point_delta_x;
else if ( j == ( n_points - 3 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_HADVANCE ) )
point_deltas_x[j] = old_point_delta_x + point_delta_x;
else if ( j == ( n_points - 2 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_TSB ) )
point_deltas_y[j] = old_point_delta_y + point_delta_y;
else if ( j == ( n_points - 1 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_VADVANCE ) )
point_deltas_y[j] = old_point_delta_y + point_delta_y;
}
point_deltas_x[j] = old_point_delta_x + point_delta_x;
point_deltas_y[j] = old_point_delta_y + point_delta_y;
#ifdef FT_DEBUG_LEVEL_TRACE
if ( point_delta_x || point_delta_y )
......@@ -4177,36 +4144,8 @@
FT_Pos point_delta_y = points_out[j].y - points_org[j].y;
if ( j < n_points - 4 )
{
point_deltas_x[j] = old_point_delta_x + point_delta_x;
point_deltas_y[j] = old_point_delta_y + point_delta_y;
}
else
{
/* To avoid double adjustment of advance width or height, */
/* adjust phantom points only if there is no HVAR or VVAR */
/* support, respectively. */
if ( j == ( n_points - 4 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_LSB ) )
point_deltas_x[j] = old_point_delta_x + point_delta_x;
else if ( j == ( n_points - 3 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_HADVANCE ) )
point_deltas_x[j] = old_point_delta_x + point_delta_x;
else if ( j == ( n_points - 2 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_TSB ) )
point_deltas_y[j] = old_point_delta_y + point_delta_y;
else if ( j == ( n_points - 1 ) &&
!( face->variation_support &
TT_FACE_FLAG_VAR_VADVANCE ) )
point_deltas_y[j] = old_point_delta_y + point_delta_y;
}
point_deltas_x[j] = old_point_delta_x + point_delta_x;
point_deltas_y[j] = old_point_delta_y + point_delta_y;
#ifdef FT_DEBUG_LEVEL_TRACE
if ( point_delta_x || point_delta_y )
......@@ -4244,6 +4183,24 @@
FT_TRACE5(( "\n" ));
/* To avoid double adjustment of advance width or height, */
/* do not move phantom points if there is HVAR or VVAR */
/* support, respectively. */
if ( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE )
{
point_deltas_x[n_points - 4] = 0;
point_deltas_y[n_points - 4] = 0;
point_deltas_x[n_points - 3] = 0;
point_deltas_y[n_points - 3] = 0;
}
if ( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE )
{
point_deltas_x[n_points - 2] = 0;
point_deltas_y[n_points - 2] = 0;
point_deltas_x[n_points - 1] = 0;
point_deltas_y[n_points - 1] = 0;
}
for ( i = 0; i < n_points; i++ )
{
unrounded[i].x += FT_fixedToFdot6( point_deltas_x[i] );
......@@ -4253,14 +4210,23 @@
outline->points[i].y += FT_fixedToInt( point_deltas_y[i] );
}
/* recalculate linear horizontal and vertical advances */
/* if we don't have HVAR and VVAR, respectively */
/* To avoid double adjustment of advance width or height, */
/* adjust phantom points only if there is no HVAR or VVAR */
/* support, respectively. */
if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
{
loader->pp1 = outline->points[n_points - 4];
loader->pp2 = outline->points[n_points - 3];
loader->linear = FT_PIX_ROUND( unrounded[n_points - 3].x -
unrounded[n_points - 4].x ) / 64;
}
if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
{
loader->pp3 = outline->points[n_points - 2];
loader->pp4 = outline->points[n_points - 1];
loader->vadvance = FT_PIX_ROUND( unrounded[n_points - 1].y -
unrounded[n_points - 2].y ) / 64;
}
Fail3:
FT_FREE( point_deltas_x );
......
......@@ -363,8 +363,7 @@ FT_BEGIN_HEADER
FT_LOCAL( FT_Error )
TT_Vary_Apply_Glyph_Deltas( TT_Loader loader,
FT_Outline* outline,
FT_Vector* unrounded,
FT_UInt n_points );
FT_Vector* unrounded );
FT_LOCAL( FT_Error )
tt_hadvance_adjust( TT_Face face,
......