mirror of https://github.com/freetype/freetype
support for FT_LOAD_NO_RECURSE needed by the auto-hinter
This commit is contained in:
parent
7024ca1a37
commit
ed7f62aca5
|
@ -474,7 +474,7 @@
|
|||
TT_ULong ins_offset;
|
||||
|
||||
/* check glyph index */
|
||||
index = (TT_UInt)glyph_index;
|
||||
index = glyph_index;
|
||||
if ( index >= (TT_UInt)face->root.num_glyphs )
|
||||
{
|
||||
error = TT_Err_Invalid_Glyph_Index;
|
||||
|
@ -698,9 +698,39 @@
|
|||
/* composite instructions, if we find some .. */
|
||||
/* we will process them later.. */
|
||||
ins_offset = FILE_Pos() + stream->cursor - stream->limit;
|
||||
FORGET_Frame();
|
||||
}
|
||||
#endif
|
||||
FORGET_Frame();
|
||||
|
||||
/* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
|
||||
/* "as is" in the glyph slot (the client application will be */
|
||||
/* responsible for interpreting this data..) */
|
||||
if ( loader->load_flags & FT_LOAD_NO_RECURSE )
|
||||
{
|
||||
FT_GlyphSlot glyph = loader->glyph;
|
||||
|
||||
/* reallocate subglyph array if necessary */
|
||||
if (glyph->max_subglyphs < num_subglyphs)
|
||||
{
|
||||
FT_Memory memory = loader->face->root.memory;
|
||||
|
||||
if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
|
||||
num_subglyphs, FT_SubGlyph ) )
|
||||
goto Fail;
|
||||
|
||||
glyph->max_subglyphs = num_subglyphs;
|
||||
}
|
||||
|
||||
/* copy subglyph array */
|
||||
MEM_Copy( glyph->subglyphs, subglyphs,
|
||||
num_subglyphs*sizeof(FT_SubGlyph));
|
||||
|
||||
/* set up remaining glyph fields */
|
||||
glyph->num_subglyphs = num_subglyphs;
|
||||
glyph->format = ft_glyph_format_composite;
|
||||
goto Load_End;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************/
|
||||
/*************************************************************************/
|
||||
|
@ -954,6 +984,7 @@
|
|||
y_scale = size->root.metrics.y_scale;
|
||||
}
|
||||
|
||||
if ( glyph->format != ft_glyph_format_composite )
|
||||
{
|
||||
TT_UInt u;
|
||||
for ( u = 0; u < num_points + 2; u++ )
|
||||
|
@ -964,30 +995,31 @@
|
|||
|
||||
for ( u = 0; u < num_contours; u++ )
|
||||
glyph->outline.contours[u] = loader->base.contours[u];
|
||||
|
||||
/* glyph->outline.second_pass = TRUE; */
|
||||
glyph->outline.flags &= ~ft_outline_single_pass;
|
||||
glyph->outline.n_points = num_points;
|
||||
glyph->outline.n_contours = num_contours;
|
||||
|
||||
/* translate array so that (0,0) is the glyph's origin */
|
||||
translate_array( (TT_UShort)(num_points + 2),
|
||||
glyph->outline.points,
|
||||
-loader->pp1.x,
|
||||
0 );
|
||||
|
||||
FT_Outline_Get_CBox( &glyph->outline, &bbox );
|
||||
|
||||
if ( IS_HINTED(loader->load_flags) )
|
||||
{
|
||||
/* grid-fit the bounding box */
|
||||
bbox.xMin &= -64;
|
||||
bbox.yMin &= -64;
|
||||
bbox.xMax = (bbox.xMax + 63) & -64;
|
||||
bbox.yMax = (bbox.yMax + 63) & -64;
|
||||
}
|
||||
}
|
||||
|
||||
glyph->outline.n_points = num_points;
|
||||
glyph->outline.n_contours = num_contours;
|
||||
|
||||
/* glyph->outline.second_pass = TRUE; */
|
||||
glyph->outline.flags &= ~ft_outline_single_pass;
|
||||
|
||||
/* translate array so that (0,0) is the glyph's origin */
|
||||
translate_array( (TT_UShort)(num_points + 2),
|
||||
glyph->outline.points,
|
||||
-loader->pp1.x,
|
||||
0 );
|
||||
|
||||
FT_Outline_Get_CBox( &glyph->outline, &bbox );
|
||||
|
||||
if ( IS_HINTED(loader->load_flags) )
|
||||
{
|
||||
/* grid-fit the bounding box */
|
||||
bbox.xMin &= -64;
|
||||
bbox.yMin &= -64;
|
||||
bbox.xMax = (bbox.xMax + 63) & -64;
|
||||
bbox.yMax = (bbox.yMax + 63) & -64;
|
||||
}
|
||||
else
|
||||
bbox = loader->bbox;
|
||||
|
||||
/* get the device-independent scaled horizontal metrics */
|
||||
/* take care of fixed-pitch fonts... */
|
||||
|
@ -1141,7 +1173,6 @@
|
|||
glyph->metrics.width = bbox.xMax - bbox.xMin;
|
||||
glyph->metrics.height = bbox.yMax - bbox.yMin;
|
||||
|
||||
glyph->format = ft_glyph_format_outline;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1174,8 +1205,9 @@
|
|||
stream = face->root.stream;
|
||||
memory = face->root.memory;
|
||||
error = 0;
|
||||
|
||||
if ( !size || (load_flags & FT_LOAD_NO_SCALE) )
|
||||
|
||||
if ( !size || (load_flags & FT_LOAD_NO_SCALE) ||
|
||||
(load_flags & FT_LOAD_NO_RECURSE ))
|
||||
{
|
||||
size = NULL;
|
||||
load_flags |= FT_LOAD_NO_SCALE |
|
||||
|
@ -1183,6 +1215,8 @@
|
|||
FT_LOAD_NO_BITMAP;
|
||||
}
|
||||
|
||||
glyph->num_subglyphs = 0;
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
|
||||
/*********************************************************************/
|
||||
/* Try to load embedded bitmap if any */
|
||||
|
@ -1245,6 +1279,9 @@
|
|||
goto Exit;
|
||||
}
|
||||
loader.base = *zone;
|
||||
|
||||
loader.zone.n_points = 0;
|
||||
loader.zone.n_contours = 0;
|
||||
|
||||
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
|
||||
if ( size )
|
||||
|
@ -1289,6 +1326,7 @@
|
|||
#endif
|
||||
|
||||
/* Main loading loop */
|
||||
glyph->format = ft_glyph_format_outline;
|
||||
error = load_truetype_glyph( &loader, glyph_index );
|
||||
if (!error)
|
||||
compute_glyph_metrics( &loader, glyph_index );
|
||||
|
@ -1304,28 +1342,4 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* END */
|
||||
|
|
|
@ -255,7 +255,7 @@
|
|||
cur->n_points = 0;
|
||||
cur->n_contours = 0;
|
||||
cur->points = base->points + base->n_points;
|
||||
cur->tags = base->tags + base->n_points;
|
||||
cur->tags = base->tags + base->n_points;
|
||||
cur->contours = base->contours + base->n_contours;
|
||||
|
||||
error = T1_Parse_CharStrings( decoder,
|
||||
|
@ -268,48 +268,88 @@
|
|||
|
||||
n_base_points = cur->n_points;
|
||||
|
||||
/* save the left bearing and width of the base character */
|
||||
/* as they will be erased by the next load.. */
|
||||
left_bearing = decoder->builder.left_bearing;
|
||||
advance = decoder->builder.advance;
|
||||
|
||||
decoder->builder.left_bearing.x = 0;
|
||||
decoder->builder.left_bearing.y = 0;
|
||||
|
||||
/* Now load "achar" on top of */
|
||||
/* the base outline */
|
||||
/* */
|
||||
cur->n_points = 0;
|
||||
cur->n_contours = 0;
|
||||
cur->points = base->points + base->n_points;
|
||||
cur->tags = base->tags + base->n_points;
|
||||
cur->contours = base->contours + base->n_contours;
|
||||
|
||||
error = T1_Parse_CharStrings( decoder,
|
||||
type1->charstrings [achar_index],
|
||||
type1->charstrings_len[achar_index],
|
||||
type1->num_subrs,
|
||||
type1->subrs,
|
||||
type1->subrs_len );
|
||||
if (error) return error;
|
||||
|
||||
/* adjust contours in accented character outline */
|
||||
if ( decoder->builder.no_recurse )
|
||||
{
|
||||
T1_Int n;
|
||||
/* if we're trying to load a composite glyph, do not load the */
|
||||
/* accent character and return the array of subglyphs.. */
|
||||
FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
|
||||
FT_SubGlyph* subg;
|
||||
|
||||
for ( n = 0; n < cur->n_contours; n++ )
|
||||
cur->contours[n] += n_base_points;
|
||||
/* reallocate subglyph array if necessary */
|
||||
if (glyph->max_subglyphs < 2)
|
||||
{
|
||||
FT_Memory memory = decoder->builder.face->root.memory;
|
||||
|
||||
if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
|
||||
2, FT_SubGlyph ) )
|
||||
return error;
|
||||
|
||||
glyph->max_subglyphs = 2;
|
||||
}
|
||||
|
||||
subg = glyph->subglyphs;
|
||||
|
||||
/* subglyph 0 = base character */
|
||||
subg->index = bchar_index;
|
||||
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
|
||||
FT_SUBGLYPH_FLAG_USE_MY_METRICS;
|
||||
subg->arg1 = 0;
|
||||
subg->arg2 = 0;
|
||||
subg++;
|
||||
|
||||
/* subglyph 1 = accent character */
|
||||
subg->index = achar_index;
|
||||
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
|
||||
subg->arg1 = adx - asb;
|
||||
subg->arg2 = ady;
|
||||
|
||||
/* set up remaining glyph fields */
|
||||
glyph->num_subglyphs = 2;
|
||||
glyph->format = ft_glyph_format_composite;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save the left bearing and width of the base character */
|
||||
/* as they will be erased by the next load.. */
|
||||
left_bearing = decoder->builder.left_bearing;
|
||||
advance = decoder->builder.advance;
|
||||
|
||||
decoder->builder.left_bearing.x = 0;
|
||||
decoder->builder.left_bearing.y = 0;
|
||||
|
||||
/* Now load "achar" on top of */
|
||||
/* the base outline */
|
||||
/* */
|
||||
cur->n_points = 0;
|
||||
cur->n_contours = 0;
|
||||
cur->points = base->points + base->n_points;
|
||||
cur->tags = base->tags + base->n_points;
|
||||
cur->contours = base->contours + base->n_contours;
|
||||
|
||||
error = T1_Parse_CharStrings( decoder,
|
||||
type1->charstrings [achar_index],
|
||||
type1->charstrings_len[achar_index],
|
||||
type1->num_subrs,
|
||||
type1->subrs,
|
||||
type1->subrs_len );
|
||||
if (error) return error;
|
||||
|
||||
/* adjust contours in accented character outline */
|
||||
{
|
||||
T1_Int n;
|
||||
|
||||
for ( n = 0; n < cur->n_contours; n++ )
|
||||
cur->contours[n] += n_base_points;
|
||||
}
|
||||
|
||||
/* restore the left side bearing and */
|
||||
/* advance width of the base character */
|
||||
decoder->builder.left_bearing = left_bearing;
|
||||
decoder->builder.advance = advance;
|
||||
|
||||
/* Finally, move the accent */
|
||||
FT_Outline_Translate( cur, adx - asb, ady );
|
||||
}
|
||||
|
||||
/* restore the left side bearing and */
|
||||
/* advance width of the base character */
|
||||
decoder->builder.left_bearing = left_bearing;
|
||||
decoder->builder.advance = advance;
|
||||
|
||||
/* Finally, move the accent */
|
||||
FT_Outline_Translate( cur, adx - asb, ady );
|
||||
|
||||
(void)asb; /* ignore this parameter */
|
||||
return T1_Err_Ok;
|
||||
}
|
||||
|
||||
|
@ -1416,6 +1456,9 @@
|
|||
T1_Bool hinting;
|
||||
T1_Font* type1 = &face->type1;
|
||||
|
||||
if (load_flags & FT_LOAD_NO_RECURSE)
|
||||
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
|
||||
|
||||
glyph->x_scale = size->root.metrics.x_scale;
|
||||
glyph->y_scale = size->root.metrics.y_scale;
|
||||
|
||||
|
@ -1470,6 +1513,7 @@
|
|||
&gload_builder_interface );
|
||||
|
||||
decoder.builder.pass = 1;
|
||||
decoder.builder.no_recurse = 0;
|
||||
|
||||
error = T1_Parse_CharStrings( &decoder,
|
||||
type1->charstrings [glyph_index],
|
||||
|
@ -1483,12 +1527,15 @@
|
|||
}
|
||||
else
|
||||
#endif
|
||||
|
||||
{
|
||||
T1_Init_Decoder( &decoder, &gload_hinter_interface );
|
||||
|
||||
T1_Init_Builder( &decoder.builder, face, size, glyph,
|
||||
&gload_builder_interface );
|
||||
|
||||
decoder.builder.no_recurse = !!(load_flags & FT_LOAD_NO_RECURSE);
|
||||
|
||||
/* now load the unscaled outline */
|
||||
error = T1_Parse_CharStrings( &decoder,
|
||||
type1->charstrings [glyph_index],
|
||||
|
@ -1507,82 +1554,92 @@
|
|||
/* bearing the yMax.. */
|
||||
if (!error)
|
||||
{
|
||||
FT_BBox cbox;
|
||||
FT_Glyph_Metrics* metrics = &glyph->root.metrics;
|
||||
|
||||
FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
|
||||
|
||||
/* grid fit the bounding box if necessary */
|
||||
if (hinting)
|
||||
/* for composite glyphs, return only the left side bearing and the */
|
||||
/* advance width.. */
|
||||
if ( load_flags & FT_LOAD_NO_RECURSE )
|
||||
{
|
||||
cbox.xMin &= -64;
|
||||
cbox.yMin &= -64;
|
||||
cbox.xMax = ( cbox.xMax+63 ) & -64;
|
||||
cbox.yMax = ( cbox.yMax+63 ) & -64;
|
||||
glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
|
||||
glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
|
||||
}
|
||||
|
||||
metrics->width = cbox.xMax - cbox.xMin;
|
||||
metrics->height = cbox.yMax - cbox.yMin;
|
||||
|
||||
metrics->horiBearingX = cbox.xMin;
|
||||
metrics->horiBearingY = cbox.yMax;
|
||||
|
||||
/* copy the _unscaled_ advance width */
|
||||
metrics->horiAdvance = decoder.builder.advance.x;
|
||||
|
||||
/* make up vertical metrics */
|
||||
metrics->vertBearingX = 0;
|
||||
metrics->vertBearingY = 0;
|
||||
metrics->vertAdvance = 0;
|
||||
|
||||
glyph->root.format = ft_glyph_format_outline;
|
||||
|
||||
glyph->root.outline.flags &= ft_outline_owner;
|
||||
|
||||
if ( size->root.metrics.y_ppem < 24 )
|
||||
glyph->root.outline.flags |= ft_outline_high_precision;
|
||||
|
||||
/*
|
||||
glyph->root.outline.second_pass = TRUE;
|
||||
glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
|
||||
glyph->root.outline.dropout_mode = 2;
|
||||
*/
|
||||
|
||||
if ( hinting )
|
||||
else
|
||||
{
|
||||
/* adjust the advance width */
|
||||
/* XXX : TODO : consider stem hints grid-fit */
|
||||
metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
|
||||
glyph->x_scale );
|
||||
}
|
||||
else if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
|
||||
{
|
||||
/* scale the outline and the metrics */
|
||||
T1_Int n;
|
||||
FT_Outline* cur = &decoder.builder.base;
|
||||
T1_Vector* vec = cur->points;
|
||||
T1_Fixed x_scale = glyph->x_scale;
|
||||
T1_Fixed y_scale = glyph->y_scale;
|
||||
|
||||
/* First of all, scale the points */
|
||||
for ( n = cur->n_points; n > 0; n--, vec++ )
|
||||
FT_BBox cbox;
|
||||
FT_Glyph_Metrics* metrics = &glyph->root.metrics;
|
||||
|
||||
FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
|
||||
|
||||
/* grid fit the bounding box if necessary */
|
||||
if (hinting)
|
||||
{
|
||||
vec->x = FT_MulFix( vec->x, x_scale );
|
||||
vec->y = FT_MulFix( vec->y, y_scale );
|
||||
cbox.xMin &= -64;
|
||||
cbox.yMin &= -64;
|
||||
cbox.xMax = ( cbox.xMax+63 ) & -64;
|
||||
cbox.yMax = ( cbox.yMax+63 ) & -64;
|
||||
}
|
||||
|
||||
metrics->width = cbox.xMax - cbox.xMin;
|
||||
metrics->height = cbox.yMax - cbox.yMin;
|
||||
|
||||
metrics->horiBearingX = cbox.xMin;
|
||||
metrics->horiBearingY = cbox.yMax;
|
||||
|
||||
/* copy the _unscaled_ advance width */
|
||||
metrics->horiAdvance = decoder.builder.advance.x;
|
||||
|
||||
/* make up vertical metrics */
|
||||
metrics->vertBearingX = 0;
|
||||
metrics->vertBearingY = 0;
|
||||
metrics->vertAdvance = 0;
|
||||
|
||||
glyph->root.format = ft_glyph_format_outline;
|
||||
|
||||
glyph->root.outline.flags &= ft_outline_owner;
|
||||
|
||||
if ( size->root.metrics.y_ppem < 24 )
|
||||
glyph->root.outline.flags |= ft_outline_high_precision;
|
||||
|
||||
/*
|
||||
glyph->root.outline.second_pass = TRUE;
|
||||
glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
|
||||
glyph->root.outline.dropout_mode = 2;
|
||||
*/
|
||||
|
||||
if ( hinting )
|
||||
{
|
||||
/* adjust the advance width */
|
||||
/* XXX : TODO : consider stem hints grid-fit */
|
||||
metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
|
||||
glyph->x_scale );
|
||||
}
|
||||
else if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
|
||||
{
|
||||
/* scale the outline and the metrics */
|
||||
T1_Int n;
|
||||
FT_Outline* cur = &decoder.builder.base;
|
||||
T1_Vector* vec = cur->points;
|
||||
T1_Fixed x_scale = glyph->x_scale;
|
||||
T1_Fixed y_scale = glyph->y_scale;
|
||||
|
||||
/* First of all, scale the points */
|
||||
for ( n = cur->n_points; n > 0; n--, vec++ )
|
||||
{
|
||||
vec->x = FT_MulFix( vec->x, x_scale );
|
||||
vec->y = FT_MulFix( vec->y, y_scale );
|
||||
}
|
||||
|
||||
/* Then scale the metrics */
|
||||
metrics->width = FT_MulFix( metrics->width, x_scale );
|
||||
metrics->height = FT_MulFix( metrics->height, y_scale );
|
||||
|
||||
metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
|
||||
metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
|
||||
metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
|
||||
|
||||
metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
|
||||
metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
|
||||
metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale );
|
||||
|
||||
}
|
||||
|
||||
/* Then scale the metrics */
|
||||
metrics->width = FT_MulFix( metrics->width, x_scale );
|
||||
metrics->height = FT_MulFix( metrics->height, y_scale );
|
||||
|
||||
metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
|
||||
metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
|
||||
metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
|
||||
|
||||
metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
|
||||
metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
|
||||
metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -159,6 +159,7 @@
|
|||
|
||||
T1_Vector left_bearing;
|
||||
T1_Vector advance;
|
||||
T1_Bool no_recurse;
|
||||
|
||||
T1_BBox bbox; /* bounding box */
|
||||
T1_Bool path_begun;
|
||||
|
|
|
@ -475,50 +475,90 @@
|
|||
|
||||
n_base_points = cur->n_points;
|
||||
|
||||
/* save the left bearing and width of the base character */
|
||||
/* as they will be erase by the next load.. */
|
||||
left_bearing = decoder->builder.left_bearing;
|
||||
advance = decoder->builder.advance;
|
||||
|
||||
decoder->builder.left_bearing.x = 0;
|
||||
decoder->builder.left_bearing.y = 0;
|
||||
|
||||
/* Now load "achar" on top of */
|
||||
/* the base outline */
|
||||
/* */
|
||||
cur->n_points = 0;
|
||||
cur->n_contours = 0;
|
||||
cur->points = base->points + base->n_points;
|
||||
cur->tags = base->tags + base->n_points;
|
||||
cur->contours = base->contours + base->n_contours;
|
||||
|
||||
error = T1_Parse_CharStrings( decoder,
|
||||
type1->charstrings [achar_index],
|
||||
type1->charstrings_len[achar_index],
|
||||
type1->num_subrs,
|
||||
type1->subrs,
|
||||
type1->subrs_len );
|
||||
if (error) return error;
|
||||
|
||||
/* adjust contours in accented character outline */
|
||||
if (decoder->builder.load_points)
|
||||
if ( decoder->builder.no_recurse )
|
||||
{
|
||||
T1_Int n;
|
||||
/* if we're trying to load a composite glyph, do not load the */
|
||||
/* accent character and return the array of subglyphs.. */
|
||||
FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
|
||||
FT_SubGlyph* subg;
|
||||
|
||||
for ( n = 0; n < cur->n_contours; n++ )
|
||||
cur->contours[n] += n_base_points;
|
||||
/* reallocate subglyph array if necessary */
|
||||
if (glyph->max_subglyphs < 2)
|
||||
{
|
||||
FT_Memory memory = decoder->builder.face->root.memory;
|
||||
|
||||
if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
|
||||
2, FT_SubGlyph ) )
|
||||
return error;
|
||||
|
||||
glyph->max_subglyphs = 2;
|
||||
}
|
||||
|
||||
subg = glyph->subglyphs;
|
||||
|
||||
/* subglyph 0 = base character */
|
||||
subg->index = bchar_index;
|
||||
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
|
||||
FT_SUBGLYPH_FLAG_USE_MY_METRICS;
|
||||
subg->arg1 = 0;
|
||||
subg->arg2 = 0;
|
||||
subg++;
|
||||
|
||||
/* subglyph 1 = accent character */
|
||||
subg->index = achar_index;
|
||||
subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
|
||||
subg->arg1 = adx - asb;
|
||||
subg->arg2 = ady;
|
||||
|
||||
/* set up remaining glyph fields */
|
||||
glyph->num_subglyphs = 2;
|
||||
glyph->format = ft_glyph_format_composite;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* save the left bearing and width of the base character */
|
||||
/* as they will be erase by the next load.. */
|
||||
left_bearing = decoder->builder.left_bearing;
|
||||
advance = decoder->builder.advance;
|
||||
|
||||
decoder->builder.left_bearing.x = 0;
|
||||
decoder->builder.left_bearing.y = 0;
|
||||
|
||||
/* Now load "achar" on top of */
|
||||
/* the base outline */
|
||||
/* */
|
||||
cur->n_points = 0;
|
||||
cur->n_contours = 0;
|
||||
cur->points = base->points + base->n_points;
|
||||
cur->tags = base->tags + base->n_points;
|
||||
cur->contours = base->contours + base->n_contours;
|
||||
|
||||
error = T1_Parse_CharStrings( decoder,
|
||||
type1->charstrings [achar_index],
|
||||
type1->charstrings_len[achar_index],
|
||||
type1->num_subrs,
|
||||
type1->subrs,
|
||||
type1->subrs_len );
|
||||
if (error) return error;
|
||||
|
||||
/* adjust contours in accented character outline */
|
||||
if (decoder->builder.load_points)
|
||||
{
|
||||
T1_Int n;
|
||||
|
||||
for ( n = 0; n < cur->n_contours; n++ )
|
||||
cur->contours[n] += n_base_points;
|
||||
}
|
||||
|
||||
/* restore the left side bearing and */
|
||||
/* advance width of the base character */
|
||||
decoder->builder.left_bearing = left_bearing;
|
||||
decoder->builder.advance = advance;
|
||||
|
||||
/* Finally, move the accent */
|
||||
if (decoder->builder.load_points)
|
||||
FT_Outline_Translate( cur, adx - asb, ady );
|
||||
}
|
||||
|
||||
/* restore the left side bearing and */
|
||||
/* advance width of the base character */
|
||||
decoder->builder.left_bearing = left_bearing;
|
||||
decoder->builder.advance = advance;
|
||||
|
||||
/* Finally, move the accent */
|
||||
if (decoder->builder.load_points)
|
||||
FT_Outline_Translate( cur, adx - asb, ady );
|
||||
|
||||
(void)asb; /* ignore this parameter */
|
||||
return T1_Err_Ok;
|
||||
}
|
||||
|
||||
|
@ -1213,6 +1253,9 @@
|
|||
T1_Bool hinting;
|
||||
T1_Font* type1 = &face->type1;
|
||||
|
||||
if (load_flags & FT_LOAD_NO_RECURSE)
|
||||
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
|
||||
|
||||
glyph->x_scale = size->root.metrics.x_scale;
|
||||
glyph->y_scale = size->root.metrics.y_scale;
|
||||
|
||||
|
@ -1228,6 +1271,8 @@
|
|||
T1_Init_Decoder( &decoder );
|
||||
T1_Init_Builder( &decoder.builder, face, size, glyph );
|
||||
|
||||
decoder.builder.no_recurse = !!(load_flags & FT_LOAD_NO_RECURSE);
|
||||
|
||||
/* now load the unscaled outline */
|
||||
error = T1_Parse_CharStrings( &decoder,
|
||||
type1->charstrings [glyph_index],
|
||||
|
@ -1245,72 +1290,82 @@
|
|||
/* bearing the yMax.. */
|
||||
if (!error)
|
||||
{
|
||||
FT_BBox cbox;
|
||||
FT_Glyph_Metrics* metrics = &glyph->root.metrics;
|
||||
|
||||
FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
|
||||
|
||||
/* grid fit the bounding box if necessary */
|
||||
if (hinting)
|
||||
/* for composite glyphs, return only the left side bearing and the */
|
||||
/* advance width.. */
|
||||
if ( load_flags & FT_LOAD_NO_RECURSE )
|
||||
{
|
||||
cbox.xMin &= -64;
|
||||
cbox.yMin &= -64;
|
||||
cbox.xMax = ( cbox.xMax+63 ) & -64;
|
||||
cbox.yMax = ( cbox.yMax+63 ) & -64;
|
||||
glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
|
||||
glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
|
||||
}
|
||||
|
||||
metrics->width = cbox.xMax - cbox.xMin;
|
||||
metrics->height = cbox.yMax - cbox.yMin;
|
||||
|
||||
metrics->horiBearingX = cbox.xMin;
|
||||
metrics->horiBearingY = cbox.yMax;
|
||||
|
||||
/* copy the _unscaled_ advance width */
|
||||
metrics->horiAdvance = decoder.builder.advance.x;
|
||||
|
||||
/* make up vertical metrics */
|
||||
metrics->vertBearingX = 0;
|
||||
metrics->vertBearingY = 0;
|
||||
metrics->vertAdvance = 0;
|
||||
|
||||
glyph->root.format = ft_glyph_format_outline;
|
||||
|
||||
glyph->root.outline.flags &= ft_outline_owner;
|
||||
if ( size->root.metrics.y_ppem < 24 )
|
||||
glyph->root.outline.flags |= ft_outline_high_precision;
|
||||
/*
|
||||
glyph->root.outline.second_pass = TRUE;
|
||||
glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
|
||||
glyph->root.outline.dropout_mode = 2;
|
||||
*/
|
||||
|
||||
if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
|
||||
else
|
||||
{
|
||||
/* scale the outline and the metrics */
|
||||
T1_Int n;
|
||||
FT_Outline* cur = &decoder.builder.base;
|
||||
T1_Vector* vec = cur->points;
|
||||
T1_Fixed x_scale = glyph->x_scale;
|
||||
T1_Fixed y_scale = glyph->y_scale;
|
||||
|
||||
/* First of all, scale the points */
|
||||
for ( n = cur->n_points; n > 0; n--, vec++ )
|
||||
FT_BBox cbox;
|
||||
FT_Glyph_Metrics* metrics = &glyph->root.metrics;
|
||||
|
||||
FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
|
||||
|
||||
/* grid fit the bounding box if necessary */
|
||||
if (hinting)
|
||||
{
|
||||
vec->x = FT_MulFix( vec->x, x_scale );
|
||||
vec->y = FT_MulFix( vec->y, y_scale );
|
||||
cbox.xMin &= -64;
|
||||
cbox.yMin &= -64;
|
||||
cbox.xMax = ( cbox.xMax+63 ) & -64;
|
||||
cbox.yMax = ( cbox.yMax+63 ) & -64;
|
||||
}
|
||||
|
||||
metrics->width = cbox.xMax - cbox.xMin;
|
||||
metrics->height = cbox.yMax - cbox.yMin;
|
||||
|
||||
metrics->horiBearingX = cbox.xMin;
|
||||
metrics->horiBearingY = cbox.yMax;
|
||||
|
||||
/* copy the _unscaled_ advance width */
|
||||
metrics->horiAdvance = decoder.builder.advance.x;
|
||||
|
||||
/* make up vertical metrics */
|
||||
metrics->vertBearingX = 0;
|
||||
metrics->vertBearingY = 0;
|
||||
metrics->vertAdvance = 0;
|
||||
|
||||
glyph->root.format = ft_glyph_format_outline;
|
||||
|
||||
glyph->root.outline.flags &= ft_outline_owner;
|
||||
if ( size->root.metrics.y_ppem < 24 )
|
||||
glyph->root.outline.flags |= ft_outline_high_precision;
|
||||
/*
|
||||
glyph->root.outline.second_pass = TRUE;
|
||||
glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
|
||||
glyph->root.outline.dropout_mode = 2;
|
||||
*/
|
||||
|
||||
if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
|
||||
{
|
||||
/* scale the outline and the metrics */
|
||||
T1_Int n;
|
||||
FT_Outline* cur = &decoder.builder.base;
|
||||
T1_Vector* vec = cur->points;
|
||||
T1_Fixed x_scale = glyph->x_scale;
|
||||
T1_Fixed y_scale = glyph->y_scale;
|
||||
|
||||
/* First of all, scale the points */
|
||||
for ( n = cur->n_points; n > 0; n--, vec++ )
|
||||
{
|
||||
vec->x = FT_MulFix( vec->x, x_scale );
|
||||
vec->y = FT_MulFix( vec->y, y_scale );
|
||||
}
|
||||
|
||||
/* Then scale the metrics */
|
||||
metrics->width = FT_MulFix( metrics->width, x_scale );
|
||||
metrics->height = FT_MulFix( metrics->height, y_scale );
|
||||
|
||||
metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
|
||||
metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
|
||||
metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
|
||||
|
||||
metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
|
||||
metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
|
||||
metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale );
|
||||
}
|
||||
|
||||
/* Then scale the metrics */
|
||||
metrics->width = FT_MulFix( metrics->width, x_scale );
|
||||
metrics->height = FT_MulFix( metrics->height, y_scale );
|
||||
|
||||
metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
|
||||
metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
|
||||
metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
|
||||
|
||||
metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
|
||||
metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
|
||||
metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale );
|
||||
}
|
||||
}
|
||||
return error;
|
||||
|
|
|
@ -107,6 +107,7 @@
|
|||
T1_BBox bbox; /* bounding box */
|
||||
T1_Bool path_begun;
|
||||
T1_Bool load_points;
|
||||
T1_Bool no_recurse;
|
||||
|
||||
T1_Error error; /* only used for memory errors */
|
||||
T1_Bool metrics_only;
|
||||
|
|
Loading…
Reference in New Issue