Commits (5)
  • Alexei Podtelezhnikov's avatar
    [truetype] Relocate subpixel flag setting. · 34fc55de
    Alexei Podtelezhnikov authored
    Eventually, we will use these flags to assess the `hdmx` usability
    prior to the glyph parsing.
    
    * src/truetype/ttinterp.c (TT_RunIns): Move the flag setting to...
    * src/truetype/ttgload.c (tt_loader_init): ...here where it belongs
    and which is executed before each glyph is loaded.
    34fc55de
  • Alexei Podtelezhnikov's avatar
    [truetype] Limit INSTCTRL appication within specs. · 2e3455b1
    Alexei Podtelezhnikov authored
    * src/truetype/ttinterp.c (Ins_INSTCTRL): Limit its global effects
    to the CVT program and local effects to the glyph program.
    2e3455b1
  • Alexei Podtelezhnikov's avatar
    [truetype] Initialize the loader with `hdmx` data. · fa353701
    Alexei Podtelezhnikov authored
    * include/freetype/internal/tttypes.h (TT_LoaderRec): Add field.
    * src/truetype/ttgload.c (compute_glyph_metrics): Relocate the `hdmx`
    code from here...
    (tt_loader_init): ... to here, before the glyph is loaded.
    fa353701
  • Alexei Podtelezhnikov's avatar
    [truetype] Honor FT_LOAD_ADVANCE_ONLY if `hdmx` is usable. · eaa10b99
    Alexei Podtelezhnikov authored
    This simply shortcuts the glyph loading if FT_LOAD_ADVANCE_ONLY
    is specified and the `hdmx` data are located.
    
    * src/truetype/ttgload.c (TT_Load_Glyph): Insert the shortcut.
    eaa10b99
  • Alexei Podtelezhnikov's avatar
    [truetype] Binary search through `hdmx` records. · 0dc811b5
    Alexei Podtelezhnikov authored
    The `hdmx` table is supposed to be sorted by ppem size, which
    enables binary search.  We also drop the check for the sufficient
    length of the record because it is now enforced when the table
    is loaded.
    
    * include/freetype/internal/tttypes.h (TT_FaceRec): Store the `hdmx`
    record pointers sorted by ppem instead of ppem's themselves.
    * src/truetype/ttpload.c (tt_face_load_hdmx): Prudently sort records.
    (tt_face_get_device_metrics): Implement binary search to retrieve
    advances.
    0dc811b5
......@@ -1390,8 +1390,8 @@ FT_BEGIN_HEADER
* hdmx_record_size ::
* The size of a single hdmx record.
*
* hdmx_record_sizes ::
* An array holding the ppem sizes available in the 'hdmx' table.
* hdmx_records ::
* A array of pointers to the 'hdmx' table records sorted by ppem.
*
* sbit_table ::
* A pointer to the font's embedded bitmap location table.
......@@ -1605,7 +1605,7 @@ FT_BEGIN_HEADER
FT_ULong hdmx_table_size;
FT_UInt hdmx_record_count;
FT_ULong hdmx_record_size;
FT_Byte* hdmx_record_sizes;
FT_Byte** hdmx_records;
FT_Byte* sbit_table;
FT_ULong sbit_table_size;
......@@ -1769,6 +1769,9 @@ FT_BEGIN_HEADER
/* since version 2.6.2 */
FT_ListRec composites;
/* since version 2.11.2 */
FT_Byte* widthp;
} TT_LoaderRec;
......
......@@ -2230,10 +2230,6 @@
FT_UInt glyph_index )
{
TT_Face face = loader->face;
#if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face );
#endif
FT_BBox bbox;
FT_Fixed y_scale;
......@@ -2256,37 +2252,10 @@
glyph->metrics.horiBearingX = bbox.xMin;
glyph->metrics.horiBearingY = bbox.yMax;
glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x);
/* 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 ( IS_HINTED( loader->load_flags ) &&
!( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) &&
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
!( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
( loader->exec && loader->exec->backward_compatibility ) ) &&
#endif
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
!( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
!SPH_OPTION_BITMAP_WIDTHS &&
FT_LOAD_TARGET_MODE( loader->load_flags ) !=
FT_RENDER_MODE_MONO &&
( loader->exec && !loader->exec->compatible_widths ) ) &&
#endif
!face->postscript.isFixedPitch )
{
FT_Byte* widthp;
widthp = tt_face_get_device_metrics( face,
size->metrics->x_ppem,
glyph_index );
if ( widthp )
glyph->metrics.horiAdvance = *widthp * 64;
}
if ( loader->widthp )
glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64;
else
glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x);
/* set glyph dimensions */
glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin );
......@@ -2720,11 +2689,64 @@
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
exec->GS.instruct_control & 4 )
exec->ignore_x_mode = 0;
#endif
exec->iup_called = FALSE;
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
/*
* Toggle backward compatibility according to what font wants, except
* when
*
* 1) we have a `tricky' font that heavily relies on the interpreter to
* render glyphs correctly, for example DFKai-SB, or
* 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
*
* In those cases, backward compatibility needs to be turned off to get
* correct rendering. The rendering is then completely up to the
* font's programming.
*
*/
if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
subpixel_hinting_lean &&
!FT_IS_TRICKY( glyph->face ) )
exec->backward_compatibility = !( exec->GS.instruct_control & 4 );
else
exec->backward_compatibility = FALSE;
exec->iupx_called = FALSE;
exec->iupy_called = FALSE;
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
loader->exec = exec;
loader->instructions = exec->glyphIns;
/* Use the hdmx table if any unless FT_LOAD_COMPUTE_METRICS */
/* is set or backward compatibility mode of the v38 or v40 */
/* interpreters is active. See `ttinterp.h' for details on */
/* backward compatibility mode. */
if ( IS_HINTED( loader->load_flags ) &&
!( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) &&
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
!( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
exec->backward_compatibility ) &&
#endif
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
!( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
!SPH_OPTION_BITMAP_WIDTHS &&
FT_LOAD_TARGET_MODE( loader->load_flags ) !=
FT_RENDER_MODE_MONO &&
exec->compatible_widths ) &&
#endif
!face->postscript.isFixedPitch )
{
loader->widthp = tt_face_get_device_metrics( face,
size->metrics->x_ppem,
0 );
}
else
loader->widthp = NULL;
}
#endif /* TT_USE_BYTECODE_INTERPRETER */
......@@ -2923,6 +2945,15 @@
if ( error )
goto Exit;
/* done if we are only interested in the `hdmx` advance */
if ( load_flags & FT_LOAD_ADVANCE_ONLY &&
!( load_flags & FT_LOAD_VERTICAL_LAYOUT ) &&
loader.widthp )
{
glyph->metrics.horiAdvance = loader.widthp[glyph_index] * 64;
goto Done;
}
glyph->format = FT_GLYPH_FORMAT_OUTLINE;
glyph->num_subglyphs = 0;
glyph->outline.flags = 0;
......@@ -3001,6 +3032,7 @@
glyph->outline.n_points,
glyph->outline.flags ));
Done:
tt_loader_done( &loader );
Exit:
......
......@@ -5260,10 +5260,15 @@
}
}
exc->GS.instruct_control &= ~(FT_Byte)Kf;
exc->GS.instruct_control |= (FT_Byte)L;
/* INSTCTRL should only be used in the CVT program */
if ( exc->iniRange == tt_coderange_cvt )
{
exc->GS.instruct_control &= ~(FT_Byte)Kf;
exc->GS.instruct_control |= (FT_Byte)L;
}
if ( K == 3 )
/* except to change the subpixel flags temporarily */
else if ( exc->iniRange == tt_coderange_glyph && K == 3 )
{
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
/* INSTCTRL modifying flag 3 also has an effect */
......@@ -7755,35 +7760,6 @@
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
exc->iup_called = FALSE;
#endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
/*
* Toggle backward compatibility according to what font wants, except
* when
*
* 1) we have a `tricky' font that heavily relies on the interpreter to
* render glyphs correctly, for example DFKai-SB, or
* 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested.
*
* In those cases, backward compatibility needs to be turned off to get
* correct rendering. The rendering is then completely up to the
* font's programming.
*
*/
if ( SUBPIXEL_HINTING_MINIMAL &&
exc->subpixel_hinting_lean &&
!FT_IS_TRICKY( &exc->face->root ) )
exc->backward_compatibility = !( exc->GS.instruct_control & 4 );
else
exc->backward_compatibility = FALSE;
exc->iupx_called = FALSE;
exc->iupy_called = FALSE;
#endif
/* We restrict the number of twilight points to a reasonable, */
/* heuristic value to avoid slow execution of malformed bytecode. */
num_twilight_points = FT_MAX( 30,
......
......@@ -498,6 +498,14 @@
}
FT_COMPARE_DEF( int )
compare_ppem( const void* a,
const void* b )
{
return **(FT_Byte**)a - **(FT_Byte**)b;
}
/**************************************************************************
*
* @Function:
......@@ -574,20 +582,21 @@
goto Fail;
}
if ( FT_QNEW_ARRAY( face->hdmx_record_sizes, num_records ) )
if ( FT_QNEW_ARRAY( face->hdmx_records, num_records ) )
goto Fail;
/* XXX: We do not check if the records are sorted by ppem */
/* and cannot use binary search later. */
for ( nn = 0; nn < num_records; nn++ )
{
if ( p + record_size > limit )
break;
face->hdmx_record_sizes[nn] = p[0];
p += record_size;
face->hdmx_records[nn] = p;
p += record_size;
}
/* The records must be already sorted by ppem but it does not */
/* hurt to make sure so that the binary search works later. */
ft_qsort( face->hdmx_records, nn, sizeof ( FT_Byte* ), compare_ppem );
face->hdmx_record_count = nn;
face->hdmx_table_size = table_size;
face->hdmx_record_size = record_size;
......@@ -611,7 +620,7 @@
FT_Memory memory = stream->memory;
FT_FREE( face->hdmx_record_sizes );
FT_FREE( face->hdmx_records );
FT_FRAME_RELEASE( face->hdmx_table );
}
......@@ -619,27 +628,34 @@
/**************************************************************************
*
* Return the advance width table for a given pixel size if it is found
* in the font's `hdmx' table (if any).
* in the font's `hdmx' table (if any). The records must be sorted for
* the binary search to work properly.
*/
FT_LOCAL_DEF( FT_Byte* )
tt_face_get_device_metrics( TT_Face face,
FT_UInt ppem,
FT_UInt gindex )
{
FT_UInt nn;
FT_Byte* result = NULL;
FT_ULong record_size = face->hdmx_record_size;
FT_Byte* record = FT_OFFSET( face->hdmx_table, 8 );
FT_UInt min = 0;
FT_UInt max = face->hdmx_record_count;
FT_UInt mid;
FT_Byte* result = NULL;
while ( min < max )
{
mid = ( min + max ) >> 1;
for ( nn = 0; nn < face->hdmx_record_count; nn++ )
if ( face->hdmx_record_sizes[nn] == ppem )
if ( face->hdmx_records[mid][0] > ppem )
max = mid;
else if ( face->hdmx_records[mid][0] < ppem )
min = mid + 1;
else
{
gindex += 2;
if ( gindex < record_size )
result = record + nn * record_size + gindex;
result = face->hdmx_records[mid] + 2 + gindex;
break;
}
}
return result;
}
......