Add vertical phantom points.

* include/freetype/internal/tttypes.h (TT_LoaderRec): Add
`top_bearing', `vadvance', `pp3, and `pp4'.

* src/autofit/afloader.c (af_loader_load_g): Handle two more points.

* src/autohint/ahhint.c (ah_hinter_load): Handle two more points.
* src/truetype/ttgload.c (Get_VMetrics): New function.
(TT_Load_Simple_Glyph, TT_Process_Simple_Glyph): Handle two more
points.
(load_truetype_glyph): Use Get_VMetrics.
Handle two more points.
(compute_glyph_metrics): Thanks to vertical phantom points we now
can always compute `advance_height' and `top_bearing'.
* src/truetype/ttobjs.h (TT_SubglyphRec): Add vertical phantom
points.


* src/autohint/ahglyph.c (ah_outline_load): Fix allocation of
`news'.

Converting some files to Unix end-of-line convention.
This commit is contained in:
Werner Lemberg 2004-03-27 08:43:17 +00:00
parent 60e0a4d5db
commit 8bb07e6386
15 changed files with 3975 additions and 3812 deletions

View File

@ -1,3 +1,27 @@
2004-13-26 George Williams <gww@silcom.com>
Add vertical phantom points.
* include/freetype/internal/tttypes.h (TT_LoaderRec): Add
`top_bearing', `vadvance', `pp3, and `pp4'.
* src/autofit/afloader.c (af_loader_load_g): Handle two more points.
* src/autohint/ahhint.c (ah_hinter_load): Handle two more points.
* src/truetype/ttgload.c (Get_VMetrics): New function.
(TT_Load_Simple_Glyph, TT_Process_Simple_Glyph): Handle two more
points.
(load_truetype_glyph): Use Get_VMetrics.
Handle two more points.
(compute_glyph_metrics): Thanks to vertical phantom points we now
can always compute `advance_height' and `top_bearing'.
* src/truetype/ttobjs.h (TT_SubglyphRec): Add vertical phantom
points.
* src/autohint/ahglyph.c (ah_outline_load): Fix allocation of
`news'.
2004-03-21 Werner Lemberg <wl@gnu.org>
* src/bdf/bdfdrivr.c (BDF_Glyph_Load): Fix left side bearing.

View File

@ -1342,11 +1342,15 @@ FT_BEGIN_HEADER
FT_BBox bbox;
FT_Int left_bearing;
FT_Int advance;
FT_Int top_bearing;
FT_Int vadvance;
FT_Int linear;
FT_Bool linear_def;
FT_Bool preserve_pps;
FT_Vector pp1;
FT_Vector pp2;
FT_Vector pp3;
FT_Vector pp4;
FT_ULong glyf_offset;

View File

@ -120,7 +120,7 @@
/* copy the outline points in the loader's current */
/* extra points which is used to keep original glyph coordinates */
error = FT_GlyphLoader_CheckPoints( gloader,
slot->outline.n_points + 2,
slot->outline.n_points + 4,
slot->outline.n_contours );
if ( error )
goto Exit;
@ -144,7 +144,8 @@
gloader->current.outline.n_points = slot->outline.n_points;
gloader->current.outline.n_contours = slot->outline.n_contours;
/* compute original phantom points */
/* compute original horizontal phantom points (and ignore */
/* vertical ones) */
loader->pp1.x = hints->x_delta;
loader->pp1.y = hints->y_delta;
loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,

View File

@ -18,6 +18,7 @@ FT_BEGIN_HEADER
FT_Vector trans_delta;
FT_Vector pp1;
FT_Vector pp2;
/* we don't handle vertical phantom points */
} AF_LoaderRec, *AF_Loader;

View File

@ -435,7 +435,7 @@
/* */
if ( num_points + 2 > outline->max_points )
{
FT_Int news = FT_PAD_CEIL( num_points, 8 );
FT_Int news = FT_PAD_CEIL( num_points + 2, 8 );
FT_Int max = outline->max_points;

View File

@ -1489,7 +1489,7 @@
/* copy the outline points in the loader's current */
/* extra points which is used to keep original glyph coordinates */
error = ah_loader_check_points( gloader, slot->outline.n_points + 2,
error = ah_loader_check_points( gloader, slot->outline.n_points + 4,
slot->outline.n_contours );
if ( error )
goto Exit;
@ -1506,7 +1506,7 @@
gloader->current.outline.n_points = slot->outline.n_points;
gloader->current.outline.n_contours = slot->outline.n_contours;
/* compute original phantom points */
/* compute original horizontal phantom points, ignoring vertical ones */
hinter->pp1.x = 0;
hinter->pp1.y = 0;
hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale );

View File

@ -5,7 +5,7 @@
/* General types and definitions for the auto-hint module */
/* (specification only). */
/* */
/* Copyright 2000-2001, 2002, 2003 Catharon Productions Inc. */
/* Copyright 2000-2001, 2002, 2003, 2004 Catharon Productions Inc. */
/* Author: David Turner */
/* */
/* This file is part of the Catharon Typography Project and shall only */
@ -492,8 +492,9 @@ FT_BEGIN_HEADER
AH_Outline glyph;
AH_Loader loader;
FT_Vector pp1;
FT_Vector pp1; /* horizontal phantom points */
FT_Vector pp2;
/* we ignore vertical phantom points */
FT_Bool transformed;
FT_Vector trans_delta;

View File

@ -162,6 +162,57 @@
}
/*************************************************************************/
/* */
/* Returns the vertical metrics in font units for a given glyph. */
/* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
/* table, typoAscender/Descender from the `OS/2' table would be used */
/* instead, and if there were no `OS/2' table, use ascender/descender */
/* from the `hhea' table. But that is not what Microsoft's rasterizer */
/* apparently does: It uses the ppem value as the advance height, and */
/* sets the top side bearing to be zero. */
/* */
/* The monospace `check' is probably not meaningful here, but we leave */
/* it in for a consistent interface. */
/* */
static void
Get_VMetrics( TT_Face face,
FT_UInt idx,
FT_Bool check,
FT_Short* tsb,
FT_UShort* ah )
{
FT_UNUSED( check );
if ( face->vertical_info )
TT_Get_Metrics( (TT_HoriHeader *)&face->vertical, idx, tsb, ah );
#if 1 /* Emperically determined, at variance with what MS said */
else
{
*tsb = 0;
*ah = face->root.units_per_EM;
}
#else /* This is what MS said to do. It isn't what they do, however. */
else if ( face->os2.version != 0xFFFFU )
{
*tsb = face->os2.sTypoAscender;
*ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
}
else
{
*tsb = face->horizontal.Ascender;
*ah = face->horizontal.Ascender - face->horizontal.Descender;
}
#endif
}
#define cur_to_org( n, zone ) \
FT_ARRAY_COPY( (zone)->org, (zone)->cur, (n) )
@ -317,7 +368,7 @@
if ( n_contours > 0 )
n_points = cont[-1] + 1;
error = FT_GlyphLoader_CheckPoints( gloader, n_points + 2, 0 );
error = FT_GlyphLoader_CheckPoints( gloader, n_points + 4, 0 );
if ( error )
goto Fail;
@ -635,12 +686,16 @@
/* add shadow points */
/* Now add the two shadow points at n and n + 1. */
/* Add two horizontal shadow points at n and n+1. */
/* We need the left side bearing and advance width. */
/* Add two vertical shadow points at n+2 and n+3. */
/* We need the top side bearing and advance height. */
{
FT_Vector* pp1;
FT_Vector* pp2;
FT_Vector* pp3;
FT_Vector* pp4;
/* pp1 = xMin - lsb */
@ -653,14 +708,26 @@
pp2->x = pp1->x + load->advance;
pp2->y = 0;
/* pp3 = top side bearing */
pp3 = pp1 + 2;
pp3->x = 0;
pp3->y = load->top_bearing + load->bbox.yMax;
/* pp4 = pp3 - ah */
pp4 = pp1 + 3;
pp4->x = 0;
pp4->y = pp3->y - load->vadvance;
outline->tags[n_points ] = 0;
outline->tags[n_points + 1] = 0;
outline->tags[n_points + 2] = 0;
outline->tags[n_points + 3] = 0;
}
/* Note that we return two more points that are not */
/* part of the glyph outline. */
n_points += 2;
n_points += 4;
/* set up zone for hinting */
tt_prepare_zone( zone, &gloader->current, 0, 0 );
@ -687,15 +754,18 @@
/* eventually hint the glyph */
if ( IS_HINTED( load->load_flags ) )
{
FT_Pos x = zone->org[n_points-2].x;
FT_Pos x = zone->org[n_points-4].x;
FT_Pos y = zone->org[n_points-2].y;
x = FT_PIX_ROUND( x ) - x;
translate_array( n_points, zone->org, x, 0 );
y = FT_PIX_ROUND( y ) - y;
translate_array( n_points, zone->org, x, y );
org_to_cur( n_points, zone );
zone->cur[n_points - 1].x = FT_PIX_ROUND( zone->cur[n_points - 1].x );
zone->cur[n_points - 3].x = FT_PIX_ROUND( zone->cur[n_points - 3].x );
zone->cur[n_points - 1].y = FT_PIX_ROUND( zone->cur[n_points - 1].y );
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
@ -711,7 +781,7 @@
load->exec->pedantic_hinting = (FT_Bool)( load->load_flags &
FT_LOAD_PEDANTIC );
load->exec->pts = *zone;
load->exec->pts.n_points += 2;
load->exec->pts.n_points += 4;
error = TT_Run_Context( load->exec, debug );
if ( error && load->exec->pedantic_hinting )
@ -727,8 +797,10 @@
/* save glyph phantom points */
if ( !load->preserve_pps )
{
load->pp1 = zone->cur[n_points - 2];
load->pp2 = zone->cur[n_points - 1];
load->pp1 = zone->cur[n_points - 4];
load->pp2 = zone->cur[n_points - 3];
load->pp3 = zone->cur[n_points - 2];
load->pp4 = zone->cur[n_points - 1];
}
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
@ -797,16 +869,22 @@
y_scale = loader->size->metrics.y_scale;
}
/* get horizontal metrics */
/* get metrics, horizontal and vertical */
{
FT_Short left_bearing = 0;
FT_UShort advance_width = 0;
FT_Short left_bearing = 0, top_bearing = 0;
FT_UShort advance_width = 0, advance_height = 0;
Get_HMetrics( face, glyph_index,
(FT_Bool)!( loader->load_flags &
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&left_bearing,
&advance_width );
Get_VMetrics( face, glyph_index,
(FT_Bool)!( loader->load_flags &
FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
&top_bearing,
&advance_height );
#ifdef FT_CONFIG_OPTION_INCREMENTAL
@ -830,10 +908,33 @@
advance_width = (FT_UShort)metrics.advance;
}
# if 0
/* GWW: Do I do the same for vertical metrics ??? */
if ( face->root.internal->incremental_interface &&
face->root.internal->incremental_interface->funcs->get_glyph_metrics )
{
FT_Incremental_MetricsRec metrics;
metrics.bearing_x = 0;
metrics.bearing_y = top_bearing;
metrics.advance = advance_height;
error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
face->root.internal->incremental_interface->object,
glyph_index, TRUE, &metrics );
if ( error )
goto Exit;
top_bearing = (FT_Short)metrics.bearing_y;
advance_height = (FT_UShort)metrics.advance;
}
# endif
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
loader->left_bearing = left_bearing;
loader->advance = advance_width;
loader->top_bearing = top_bearing;
loader->vadvance = advance_height;
if ( !loader->linear_def )
{
@ -893,9 +994,14 @@
loader->pp1.x = 0;
loader->pp2.x = loader->advance;
loader->pp3.y = 0;
loader->pp4.y = loader->pp3.y-loader->vadvance;
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
}
#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
@ -933,10 +1039,17 @@
loader->pp2.x = loader->pp1.x + loader->advance;
loader->pp2.y = 0;
loader->pp3.x = 0;
loader->pp3.y = loader->top_bearing + loader->bbox.yMax;
loader->pp4.x = 0;
loader->pp4.y = loader->pp3.y - loader->vadvance;
if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
{
loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
}
/***********************************************************************/
@ -1045,7 +1158,7 @@
for ( n = 0; n < (FT_Int)num_subglyphs; n++ )
{
FT_Vector pp1, pp2;
FT_Vector pp1, pp2, pp3, pp4;
FT_Pos x, y;
@ -1057,6 +1170,8 @@
pp1 = loader->pp1;
pp2 = loader->pp2;
pp3 = loader->pp3;
pp4 = loader->pp4;
num_base_points = gloader->base.outline.n_points;
@ -1072,11 +1187,15 @@
{
pp1 = loader->pp1;
pp2 = loader->pp2;
pp3 = loader->pp3;
pp4 = loader->pp4;
}
else
{
loader->pp1 = pp1;
loader->pp2 = pp2;
loader->pp3 = pp3;
loader->pp4 = pp4;
}
num_points = gloader->base.outline.n_points;
@ -1273,7 +1392,7 @@
if ( error )
goto Fail;
error = FT_GlyphLoader_CheckPoints( gloader, num_points + 2, 0 );
error = FT_GlyphLoader_CheckPoints( gloader, num_points + 4, 0 );
if ( error )
goto Fail;
@ -1282,22 +1401,28 @@
start_point, start_contour );
pts = &exec->pts;
pts->n_points = (short)(num_points + 2);
pts->n_points = (short)( num_points + 4 );
pts->n_contours = gloader->base.outline.n_contours;
/* add phantom points */
pp1 = pts->cur + num_points;
pp1[0] = loader->pp1;
pp1[1] = loader->pp2;
pp1[2] = loader->pp3;
pp1[3] = loader->pp4;
pts->tags[num_points ] = 0;
pts->tags[num_points + 1] = 0;
pts->tags[num_points + 2] = 0;
pts->tags[num_points + 3] = 0;
/* if hinting, round the phantom points */
if ( IS_HINTED( loader->load_flags ) )
{
pp1[0].x = FT_PIX_ROUND( loader->pp1.x );
pp1[1].x = FT_PIX_ROUND( loader->pp2.x );
pp1[2].y = FT_PIX_ROUND( loader->pp3.y );
pp1[3].y = FT_PIX_ROUND( loader->pp4.y );
}
{
@ -1308,7 +1433,7 @@
pts->tags[k] &= FT_CURVE_TAG_ON;
}
cur_to_org( num_points + 2, pts );
cur_to_org( num_points + 4, pts );
/* now consider hinting */
if ( IS_HINTED( loader->load_flags ) && n_ins > 0 )
@ -1324,6 +1449,8 @@
/* save glyph origin and advance points */
loader->pp1 = pp1[0];
loader->pp2 = pp1[1];
loader->pp3 = pp1[2];
loader->pp4 = pp1[3];
}
#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
@ -1443,13 +1570,9 @@
if ( face->vertical_info &&
face->vertical.number_Of_VMetrics > 0 )
{
/* Don't assume that both the vertical header and vertical */
/* metrics are present in the same font :-) */
advance_height = loader->pp4.y - loader->pp3.y;
top_bearing = loader->pp3.y - bbox.yMax;
TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
glyph_index,
&top_bearing,
&advance_height );
}
else
{
@ -1465,6 +1588,12 @@
/* here with: */
/* ascender - descender + linegap */
/* */
/* NOTE3: This is different from what MS's rasterizer */
/* appears to do when getting default values */
/* for the vertical phantom points. We leave */
/* the old code untouched, but relying on */
/* phantom points alone might be reasonable */
/* (i.e., removing the `if' above). */
if ( face->os2.version != 0xFFFFU )
{
top_bearing = (FT_Short)( face->os2.sTypoLineGap / 2 );
@ -1507,6 +1636,8 @@
advance_height = (FT_UShort)metrics.advance;
}
/* GWW: Do vertical metrics get loaded incrementally too? */
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
/* We must adjust the top_bearing value from the bounding box given */

View File

@ -4,7 +4,7 @@
/* */
/* Objects manager (specification). */
/* */
/* Copyright 1996-2001, 2002, 2003 by */
/* Copyright 1996-2001, 2002, 2003, 2004 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@ -216,7 +216,8 @@ FT_BEGIN_HEADER
TT_Transform transform; /* transformation matrix */
FT_Vector pp1, pp2; /* phantom points */
FT_Vector pp1, pp2; /* phantom points (horizontal) */
FT_Vector pp3, pp4; /* phantom points (vertical) */
} TT_SubGlyphRec, *TT_SubGlyph_Stack;