[autofit] Implement darkening computation function.
This is a crude adaption of the original `cf2_computeDarkening' function. * src/autofit/afloader.c (af_intToFixed, af_fixedToInt, af_floatToFixed): New macros, taken from `cf2fixed.h'. (af_loader_compute_darkening): New function. * src/autofit/afloader.h: Updated.
This commit is contained in:
parent
37c401ac0a
commit
bf2ba9e3d4
12
ChangeLog
12
ChangeLog
|
@ -1,3 +1,15 @@
|
|||
2015-11-02 Nikolaus Waxweiler <madigens@gmail.com>
|
||||
|
||||
[autofit] Implement darkening computation function.
|
||||
|
||||
This is a crude adaption of the original `cf2_computeDarkening'
|
||||
function.
|
||||
|
||||
* src/autofit/afloader.c (af_intToFixed, af_fixedToInt,
|
||||
af_floatToFixed): New macros, taken from `cf2fixed.h'.
|
||||
(af_loader_compute_darkening): New function.
|
||||
* src/autofit/afloader.h: Updated.
|
||||
|
||||
2015-11-02 Nikolaus Waxweiler <madigens@gmail.com>
|
||||
|
||||
[autofit] Add functions to get standard widths for writing systems.
|
||||
|
|
|
@ -405,4 +405,141 @@
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
* Compute amount of font units the face should be emboldened by, in
|
||||
* analogy to the CFF driver's `cf2_computeDarkening' function. See there
|
||||
* for details of the algorithm.
|
||||
*
|
||||
* XXX: Currently a crude adaption of the original algorithm. Do better?
|
||||
*/
|
||||
#define af_intToFixed( i ) \
|
||||
( (FT_Fixed)( (FT_UInt32)(i) << 16 ) )
|
||||
#define af_fixedToInt( x ) \
|
||||
( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
|
||||
#define af_floatToFixed( f ) \
|
||||
( (FT_Fixed)( (f) * 65536.0 + 0.5 ) )
|
||||
|
||||
FT_LOCAL_DEF( FT_Int32 )
|
||||
af_loader_compute_darkening( AF_Loader loader,
|
||||
FT_Face face,
|
||||
FT_Pos standard_width )
|
||||
{
|
||||
AF_Module module = loader->globals->module;
|
||||
|
||||
FT_UShort units_per_EM;
|
||||
FT_Fixed ppem, em_ratio;
|
||||
FT_Fixed stem_width, stem_width_per_1000, scaled_stem, darken_amount;
|
||||
FT_Int log_base_2;
|
||||
FT_Int x1, y1, x2, y2, x3, y3, x4, y4;
|
||||
|
||||
|
||||
ppem = FT_MAX( af_intToFixed( 4 ),
|
||||
af_intToFixed( face->size->metrics.x_ppem ) );
|
||||
units_per_EM = face->units_per_EM;
|
||||
|
||||
em_ratio = FT_DivFix( af_intToFixed( 1000 ),
|
||||
af_intToFixed ( units_per_EM ) );
|
||||
if ( em_ratio < af_floatToFixed( .01 ) )
|
||||
{
|
||||
/* If something goes wrong, don't embolden. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
x1 = module->darken_params[0];
|
||||
y1 = module->darken_params[1];
|
||||
x2 = module->darken_params[2];
|
||||
y2 = module->darken_params[3];
|
||||
x3 = module->darken_params[4];
|
||||
y3 = module->darken_params[5];
|
||||
x4 = module->darken_params[6];
|
||||
y4 = module->darken_params[7];
|
||||
|
||||
if ( standard_width <= 0 )
|
||||
{
|
||||
stem_width = af_intToFixed( 75 ); /* taken from cf2font.c */
|
||||
stem_width_per_1000 = stem_width;
|
||||
}
|
||||
else
|
||||
{
|
||||
stem_width = af_intToFixed( standard_width );
|
||||
stem_width_per_1000 = FT_MulFix( stem_width, em_ratio );
|
||||
}
|
||||
|
||||
log_base_2 = FT_MSB( (FT_UInt32)stem_width_per_1000 ) +
|
||||
FT_MSB( (FT_UInt32)ppem );
|
||||
|
||||
if ( log_base_2 >= 46 )
|
||||
{
|
||||
/* possible overflow */
|
||||
scaled_stem = af_intToFixed( x4 );
|
||||
}
|
||||
else
|
||||
scaled_stem = FT_MulFix( stem_width_per_1000, ppem );
|
||||
|
||||
/* now apply the darkening parameters */
|
||||
if ( scaled_stem < af_intToFixed( x1 ) )
|
||||
darken_amount = FT_DivFix( af_intToFixed( y1 ), ppem );
|
||||
|
||||
else if ( scaled_stem < af_intToFixed( x2 ) )
|
||||
{
|
||||
FT_Int xdelta = x2 - x1;
|
||||
FT_Int ydelta = y2 - y1;
|
||||
FT_Int x = stem_width_per_1000 -
|
||||
FT_DivFix( af_intToFixed( x1 ), ppem );
|
||||
|
||||
|
||||
if ( !xdelta )
|
||||
goto Try_x3;
|
||||
|
||||
darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
|
||||
FT_DivFix( af_intToFixed( y1 ), ppem );
|
||||
}
|
||||
|
||||
else if ( scaled_stem < af_intToFixed( x3 ) )
|
||||
{
|
||||
Try_x3:
|
||||
{
|
||||
FT_Int xdelta = x3 - x2;
|
||||
FT_Int ydelta = y3 - y2;
|
||||
FT_Int x = stem_width_per_1000 -
|
||||
FT_DivFix( af_intToFixed( x2 ), ppem );
|
||||
|
||||
|
||||
if ( !xdelta )
|
||||
goto Try_x4;
|
||||
|
||||
darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
|
||||
FT_DivFix( af_intToFixed( y2 ), ppem );
|
||||
}
|
||||
}
|
||||
|
||||
else if ( scaled_stem < af_intToFixed( x4 ) )
|
||||
{
|
||||
Try_x4:
|
||||
{
|
||||
FT_Int xdelta = x4 - x3;
|
||||
FT_Int ydelta = y4 - y3;
|
||||
FT_Int x = stem_width_per_1000 -
|
||||
FT_DivFix( af_intToFixed( x3 ), ppem );
|
||||
|
||||
|
||||
if ( !xdelta )
|
||||
goto Use_y4;
|
||||
|
||||
darken_amount = FT_MulDiv( x, ydelta, xdelta ) +
|
||||
FT_DivFix( af_intToFixed( y3 ), ppem );
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Use_y4:
|
||||
darken_amount = FT_DivFix( af_intToFixed( y4 ), ppem );
|
||||
}
|
||||
|
||||
/* Convert darken_amount from per 1000 em to true character space. */
|
||||
return af_fixedToInt( FT_DivFix( darken_amount, em_ratio ) );
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
|
|
|
@ -75,6 +75,11 @@ FT_BEGIN_HEADER
|
|||
FT_UInt gindex,
|
||||
FT_Int32 load_flags );
|
||||
|
||||
FT_LOCAL_DEF( FT_Int32 )
|
||||
af_loader_compute_darkening( AF_Loader loader,
|
||||
FT_Face face,
|
||||
FT_Pos standard_width );
|
||||
|
||||
/* */
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue