[cff] Add `darkening-parameters' property.
* include/freetype/ftcffdrv.h: Document it. * src/cff/cffdrivr.c (cff_property_set, cff_property_get): Handle `darkening-parameters' property. * src/cff/cf2font.h (CF2_FontRec): Add `darkenParams' array. * src/cff/cf2font.c (cf2_computeDarkening): Add `darkenParams' argument and use it. Update all callers. * src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Copy `darken_params' values. * src/cff/cffobjs.h (CFF_DriverRec): Add `darken_params' array. * src/cff/cffobjs.c (cff_driver_init): Set default values for `darken_params'.
This commit is contained in:
parent
fad93267a2
commit
89ca1fd6d7
23
ChangeLog
23
ChangeLog
|
@ -1,3 +1,26 @@
|
|||
2013-06-25 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[cff] Add `darkening-parameters' property.
|
||||
|
||||
* include/freetype/ftcffdrv.h: Document it.
|
||||
|
||||
* src/cff/cffdrivr.c (cff_property_set, cff_property_get): Handle
|
||||
`darkening-parameters' property.
|
||||
|
||||
* src/cff/cf2font.h (CF2_FontRec): Add `darkenParams' array.
|
||||
|
||||
* src/cff/cf2font.c (cf2_computeDarkening): Add `darkenParams'
|
||||
argument and use it.
|
||||
Update all callers.
|
||||
|
||||
* src/cff/cf2ft.c (cf2_decoder_parse_charstrings): Copy
|
||||
`darken_params' values.
|
||||
|
||||
* src/cff/cffobjs.h (CFF_DriverRec): Add `darken_params' array.
|
||||
|
||||
* src/cff/cffobjs.c (cff_driver_init): Set default values for
|
||||
`darken_params'.
|
||||
|
||||
2013-06-25 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[docmaker] Code shuffling.
|
||||
|
|
|
@ -73,7 +73,6 @@ FT_BEGIN_HEADER
|
|||
*
|
||||
* {
|
||||
* FT_Library library;
|
||||
* FT_Face face;
|
||||
* FT_UInt hinting_engine = FT_CFF_HINTING_ADOBE;
|
||||
*
|
||||
*
|
||||
|
@ -124,7 +123,6 @@ FT_BEGIN_HEADER
|
|||
*
|
||||
* {
|
||||
* FT_Library library;
|
||||
* FT_Face face;
|
||||
* FT_Bool no_stem_darkening = TRUE;
|
||||
*
|
||||
*
|
||||
|
@ -140,6 +138,50 @@ FT_BEGIN_HEADER
|
|||
*/
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
*
|
||||
* @property:
|
||||
* darkening-parameters
|
||||
*
|
||||
* @description:
|
||||
* By default, the Adobe CFF engine darkens stems as follows (if the
|
||||
* `no-stem-darkening' property isn't set):
|
||||
*
|
||||
* {
|
||||
* stem width <= 0.5px: darkening amount = 0.4px
|
||||
* stem width = 1px: darkening amount = 0.275px
|
||||
* stem width = 1.667px: darkening amount = 0.275px
|
||||
* stem width >= 2.333px: darkening amount = 0px
|
||||
* }
|
||||
*
|
||||
* and piecewise linear in-between. Using the `darkening-parameters'
|
||||
* property, these four control points can be changed, as the following
|
||||
* example demonstrates.
|
||||
*
|
||||
* {
|
||||
* FT_Library library;
|
||||
* FT_Int darken_params[8] = { 500, 300, // x1, y1
|
||||
* 1000, 200, // x2, y2
|
||||
* 1500, 100, // x3, y3
|
||||
* 2000, 0 }; // x4, y4
|
||||
*
|
||||
*
|
||||
* FT_Init_FreeType( &library );
|
||||
*
|
||||
* FT_Property_Set( library, "cff",
|
||||
* "darkening-parameters", darken_params );
|
||||
* }
|
||||
*
|
||||
* The x~values give the stem width, and the y~values the darkening
|
||||
* amount. All coordinate values must be positive and monotonically
|
||||
* increasing along the x~axis; the unit is 1000th of pixels.
|
||||
*
|
||||
* @note:
|
||||
* This property can be used with @FT_Property_Get also.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* */
|
||||
|
||||
FT_END_HEADER
|
||||
|
|
|
@ -51,15 +51,57 @@
|
|||
CF2_Fixed stemWidth,
|
||||
CF2_Fixed* darkenAmount,
|
||||
CF2_Fixed boldenAmount,
|
||||
FT_Bool stemDarkened )
|
||||
FT_Bool stemDarkened,
|
||||
FT_Int* darkenParams )
|
||||
{
|
||||
/*
|
||||
* Total darkening amount is computed in 1000 unit character space
|
||||
* using the modified 5 part curve as Adobe's Avalon rasterizer.
|
||||
* The darkening amount is smaller for thicker stems.
|
||||
* It becomes zero when the stem is thicker than 2.333 pixels.
|
||||
*
|
||||
* By default, we use
|
||||
*
|
||||
* darkenAmount = 0.4 pixels if scaledStem <= 0.5 pixels,
|
||||
* darkenAmount = 0.275 pixels if 1 <= scaledStem <= 1.667 pixels,
|
||||
* darkenAmount = 0 pixel if scaledStem >= 2.333 pixels,
|
||||
*
|
||||
* and piecewise linear in-between:
|
||||
*
|
||||
*
|
||||
* darkening
|
||||
* ^
|
||||
* |
|
||||
* | (x1,y1)
|
||||
* |--------+
|
||||
* | \
|
||||
* | \
|
||||
* | \ (x3,y3)
|
||||
* | +----------+
|
||||
* | (x2,y2) \
|
||||
* | \
|
||||
* | \
|
||||
* | +-----------------
|
||||
* | (x4,y4)
|
||||
* +---------------------------------------------> stem
|
||||
* thickness
|
||||
*
|
||||
*
|
||||
* This corresponds to the following values for the
|
||||
* `darkening-parameters' property:
|
||||
*
|
||||
* (x1, y1) = (500, 400)
|
||||
* (x2, y2) = (1000, 275)
|
||||
* (x3, y3) = (1667, 275)
|
||||
* (x4, y4) = (2333, 0)
|
||||
*
|
||||
*/
|
||||
|
||||
/* Internal calculations are done in units per thousand for */
|
||||
/* convenience. */
|
||||
CF2_Fixed stemWidthPer1000, scaledStem;
|
||||
|
||||
|
||||
*darkenAmount = 0;
|
||||
|
||||
if ( boldenAmount == 0 && !stemDarkened )
|
||||
return;
|
||||
|
||||
|
@ -69,6 +111,16 @@
|
|||
|
||||
if ( stemDarkened )
|
||||
{
|
||||
FT_Int x1 = darkenParams[0];
|
||||
FT_Int y1 = darkenParams[1];
|
||||
FT_Int x2 = darkenParams[2];
|
||||
FT_Int y2 = darkenParams[3];
|
||||
FT_Int x3 = darkenParams[4];
|
||||
FT_Int y3 = darkenParams[5];
|
||||
FT_Int x4 = darkenParams[6];
|
||||
FT_Int y4 = darkenParams[7];
|
||||
|
||||
|
||||
/* convert from true character space to 1000 unit character space; */
|
||||
/* add synthetic emboldening effect */
|
||||
|
||||
|
@ -81,7 +133,7 @@
|
|||
stemWidthPer1000 <= ( stemWidth + boldenAmount ) )
|
||||
{
|
||||
stemWidthPer1000 = 0; /* to pacify compiler */
|
||||
scaledStem = cf2_intToFixed( 2333 );
|
||||
scaledStem = cf2_intToFixed( x4 );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -89,39 +141,70 @@
|
|||
|
||||
if ( ppem > CF2_FIXED_ONE &&
|
||||
scaledStem <= stemWidthPer1000 )
|
||||
scaledStem = cf2_intToFixed( 2333 );
|
||||
scaledStem = cf2_intToFixed( x4 );
|
||||
}
|
||||
|
||||
/*
|
||||
* Total darkening amount is computed in 1000 unit character space
|
||||
* using the modified 5 part curve as Avalon rasterizer.
|
||||
* The darkening amount is smaller for thicker stems.
|
||||
* It becomes zero when the stem is thicker than 2.333 pixels.
|
||||
*
|
||||
* By default, we use
|
||||
*
|
||||
* darkenAmount = 0.4 pixels if scaledStem <= 0.5 pixels,
|
||||
* darkenAmount = 0.275 pixels if 1 <= scaledStem <= 1.667 pixels,
|
||||
* darkenAmount = 0 pixel if scaledStem >= 2.333 pixels,
|
||||
*
|
||||
* and piecewise linear in-between.
|
||||
*
|
||||
*/
|
||||
if ( scaledStem < cf2_intToFixed( 500 ) )
|
||||
*darkenAmount = FT_DivFix( cf2_intToFixed( 400 ), ppem );
|
||||
/* now apply the darkening parameters */
|
||||
|
||||
else if ( scaledStem < cf2_intToFixed( 1000 ) )
|
||||
*darkenAmount = FT_DivFix( cf2_intToFixed( 525 ), ppem ) -
|
||||
FT_MulFix( stemWidthPer1000,
|
||||
cf2_floatToFixed( .25 ) );
|
||||
if ( scaledStem < cf2_intToFixed( x1 ) )
|
||||
*darkenAmount = FT_DivFix( cf2_intToFixed( y1 ), ppem );
|
||||
|
||||
else if ( scaledStem < cf2_intToFixed( 1667 ) )
|
||||
*darkenAmount = FT_DivFix( cf2_intToFixed( 275 ), ppem );
|
||||
else if ( scaledStem < cf2_intToFixed( x2 ) )
|
||||
{
|
||||
FT_Int xdelta = x2 - x1;
|
||||
FT_Int ydelta = y2 - y1;
|
||||
FT_Int x = stemWidthPer1000 -
|
||||
FT_DivFix( cf2_intToFixed( x1 ), ppem );
|
||||
|
||||
else if ( scaledStem < cf2_intToFixed( 2333 ) )
|
||||
*darkenAmount = FT_DivFix( cf2_intToFixed( 963 ), ppem ) -
|
||||
FT_MulFix( stemWidthPer1000,
|
||||
cf2_floatToFixed( .413 ) );
|
||||
|
||||
if ( !ydelta )
|
||||
goto Try_x3;
|
||||
|
||||
*darkenAmount = FT_MulFix( x, FT_DivFix( ydelta, xdelta ) ) +
|
||||
FT_DivFix( cf2_intToFixed( y1 ), ppem );
|
||||
}
|
||||
|
||||
else if ( scaledStem < cf2_intToFixed( x3 ) )
|
||||
{
|
||||
Try_x3:
|
||||
{
|
||||
FT_Int xdelta = x3 - x2;
|
||||
FT_Int ydelta = y3 - y2;
|
||||
FT_Int x = stemWidthPer1000 -
|
||||
FT_DivFix( cf2_intToFixed( x2 ), ppem );
|
||||
|
||||
|
||||
if ( !ydelta )
|
||||
goto Try_x4;
|
||||
|
||||
*darkenAmount = FT_MulFix( x, FT_DivFix( ydelta, xdelta ) ) +
|
||||
FT_DivFix( cf2_intToFixed( y2 ), ppem );
|
||||
}
|
||||
}
|
||||
|
||||
else if ( scaledStem < cf2_intToFixed( x4 ) )
|
||||
{
|
||||
Try_x4:
|
||||
{
|
||||
FT_Int xdelta = x4 - x3;
|
||||
FT_Int ydelta = y4 - y3;
|
||||
FT_Int x = stemWidthPer1000 -
|
||||
FT_DivFix( cf2_intToFixed( x3 ), ppem );
|
||||
|
||||
|
||||
if ( !ydelta )
|
||||
goto Use_y4;
|
||||
|
||||
*darkenAmount = FT_MulFix( x, FT_DivFix( ydelta, xdelta ) ) +
|
||||
FT_DivFix( cf2_intToFixed( y3 ), ppem );
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Use_y4:
|
||||
*darkenAmount = FT_DivFix( cf2_intToFixed( y4 ), ppem );
|
||||
}
|
||||
|
||||
/* use half the amount on each side and convert back to true */
|
||||
/* character space */
|
||||
|
@ -268,7 +351,8 @@
|
|||
font->stdVW,
|
||||
&font->darkenX,
|
||||
boldenX,
|
||||
FALSE );
|
||||
FALSE,
|
||||
font->darkenParams );
|
||||
}
|
||||
else
|
||||
cf2_computeDarkening( emRatio,
|
||||
|
@ -276,7 +360,8 @@
|
|||
font->stdVW,
|
||||
&font->darkenX,
|
||||
0,
|
||||
font->stemDarkened );
|
||||
font->stemDarkened,
|
||||
font->darkenParams );
|
||||
|
||||
#if 0
|
||||
/* since hstem is measured in the y-direction, we use the `d' member */
|
||||
|
@ -303,7 +388,8 @@
|
|||
font->stdHW,
|
||||
&font->darkenY,
|
||||
boldenY,
|
||||
font->stemDarkened );
|
||||
font->stemDarkened,
|
||||
font->darkenParams );
|
||||
|
||||
if ( font->darkenX != 0 || font->darkenY != 0 )
|
||||
font->darkened = TRUE;
|
||||
|
|
|
@ -85,6 +85,8 @@ FT_BEGIN_HEADER
|
|||
/* i.e. darkenX != 0 || darkenY != 0 */
|
||||
FT_Bool stemDarkened;
|
||||
|
||||
FT_Int darkenParams[8]; /* 1000 unit character space */
|
||||
|
||||
/* variables that depend on both FontDict and Transform */
|
||||
CF2_Fixed stdVW; /* in character space; depends on dict entry */
|
||||
CF2_Fixed stdHW; /* in character space; depends on dict entry */
|
||||
|
|
|
@ -344,6 +344,15 @@
|
|||
if ( scaled && !driver->no_stem_darkening )
|
||||
font->renderingFlags |= CF2_FlagsDarkened;
|
||||
|
||||
font->darkenParams[0] = driver->darken_params[0];
|
||||
font->darkenParams[1] = driver->darken_params[1];
|
||||
font->darkenParams[2] = driver->darken_params[2];
|
||||
font->darkenParams[3] = driver->darken_params[3];
|
||||
font->darkenParams[4] = driver->darken_params[4];
|
||||
font->darkenParams[5] = driver->darken_params[5];
|
||||
font->darkenParams[6] = driver->darken_params[6];
|
||||
font->darkenParams[7] = driver->darken_params[7];
|
||||
|
||||
/* now get an outline for this glyph; */
|
||||
/* also get units per em to validate scale */
|
||||
font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
|
||||
|
|
|
@ -586,7 +586,37 @@
|
|||
CFF_Driver driver = (CFF_Driver)module;
|
||||
|
||||
|
||||
if ( !ft_strcmp( property_name, "hinting-engine" ) )
|
||||
if ( !ft_strcmp( property_name, "darkening-parameters" ) )
|
||||
{
|
||||
FT_Int* darken_params = (FT_Int*)value;
|
||||
|
||||
FT_Int x1 = darken_params[0];
|
||||
FT_Int y1 = darken_params[1];
|
||||
FT_Int x2 = darken_params[2];
|
||||
FT_Int y2 = darken_params[3];
|
||||
FT_Int x3 = darken_params[4];
|
||||
FT_Int y3 = darken_params[5];
|
||||
FT_Int x4 = darken_params[6];
|
||||
FT_Int y4 = darken_params[7];
|
||||
|
||||
|
||||
if ( x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 ||
|
||||
y1 < 0 || y2 < 0 || y3 < 0 || y4 < 0 ||
|
||||
x1 > x2 || x2 > x3 || x3 > x4 )
|
||||
return FT_THROW( Invalid_Argument );
|
||||
|
||||
driver->darken_params[0] = x1;
|
||||
driver->darken_params[1] = y1;
|
||||
driver->darken_params[2] = x2;
|
||||
driver->darken_params[3] = y2;
|
||||
driver->darken_params[4] = x3;
|
||||
driver->darken_params[5] = y3;
|
||||
driver->darken_params[6] = x4;
|
||||
driver->darken_params[7] = y4;
|
||||
|
||||
return error;
|
||||
}
|
||||
else if ( !ft_strcmp( property_name, "hinting-engine" ) )
|
||||
{
|
||||
FT_UInt* hinting_engine = (FT_UInt*)value;
|
||||
|
||||
|
@ -624,13 +654,28 @@
|
|||
FT_Error error = FT_Err_Ok;
|
||||
CFF_Driver driver = (CFF_Driver)module;
|
||||
|
||||
FT_UInt hinting_engine = driver->hinting_engine;
|
||||
FT_Bool no_stem_darkening = driver->no_stem_darkening;
|
||||
|
||||
|
||||
if ( !ft_strcmp( property_name, "hinting-engine" ) )
|
||||
if ( !ft_strcmp( property_name, "darkening-parameters" ) )
|
||||
{
|
||||
FT_UInt* val = (FT_UInt*)value;
|
||||
FT_Int* darken_params = driver->darken_params;
|
||||
FT_Int* val = (FT_Int*)value;
|
||||
|
||||
|
||||
val[0] = darken_params[0];
|
||||
val[1] = darken_params[1];
|
||||
val[2] = darken_params[2];
|
||||
val[3] = darken_params[3];
|
||||
val[4] = darken_params[4];
|
||||
val[5] = darken_params[5];
|
||||
val[6] = darken_params[6];
|
||||
val[7] = darken_params[7];
|
||||
|
||||
return error;
|
||||
}
|
||||
else if ( !ft_strcmp( property_name, "hinting-engine" ) )
|
||||
{
|
||||
FT_UInt hinting_engine = driver->hinting_engine;
|
||||
FT_UInt* val = (FT_UInt*)value;
|
||||
|
||||
|
||||
*val = hinting_engine;
|
||||
|
@ -639,7 +684,8 @@
|
|||
}
|
||||
else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
|
||||
{
|
||||
FT_Bool* val = (FT_Bool*)value;
|
||||
FT_Bool no_stem_darkening = driver->no_stem_darkening;
|
||||
FT_Bool* val = (FT_Bool*)value;
|
||||
|
||||
|
||||
*val = no_stem_darkening;
|
||||
|
|
|
@ -1055,7 +1055,7 @@
|
|||
CFF_Driver driver = (CFF_Driver)module;
|
||||
|
||||
|
||||
/* set default property values */
|
||||
/* set default property values, cf `ftcffdrv.h' */
|
||||
#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
|
||||
driver->hinting_engine = FT_CFF_HINTING_FREETYPE;
|
||||
#else
|
||||
|
@ -1063,6 +1063,15 @@
|
|||
#endif
|
||||
driver->no_stem_darkening = FALSE;
|
||||
|
||||
driver->darken_params[0] = 500;
|
||||
driver->darken_params[1] = 400;
|
||||
driver->darken_params[2] = 1000;
|
||||
driver->darken_params[3] = 275;
|
||||
driver->darken_params[4] = 1667;
|
||||
driver->darken_params[5] = 275;
|
||||
driver->darken_params[6] = 2333;
|
||||
driver->darken_params[7] = 0;
|
||||
|
||||
return FT_Err_Ok;
|
||||
}
|
||||
|
||||
|
|
|
@ -121,6 +121,8 @@ FT_BEGIN_HEADER
|
|||
FT_UInt hinting_engine;
|
||||
FT_Bool no_stem_darkening;
|
||||
|
||||
FT_Int darken_params[8];
|
||||
|
||||
} CFF_DriverRec;
|
||||
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ re_markup_tags = [re_markup_tag1, re_markup_tag2]
|
|||
#
|
||||
# used to detect a cross-reference, after markup tags have been stripped
|
||||
#
|
||||
re_crossref = re.compile( r'@((?:\w|-)*)(.*)' )
|
||||
re_crossref = re.compile( r'@((?:\w|-)*)(.*)' ) # @foo
|
||||
|
||||
#
|
||||
# used to detect italic and bold styles in paragraph text
|
||||
|
|
Loading…
Reference in New Issue