gdi32: Add a helper function to calculate the glyph advance metric.

Signed-off-by: Akihiro Sagawa <sagawa.aki@gmail.com>
Signed-off-by: Huw Davies <huw@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Akihiro Sagawa 2016-01-13 23:09:06 +09:00 committed by Alexandre Julliard
parent e8311270ab
commit f0831ecd2f
1 changed files with 60 additions and 54 deletions

View File

@ -6444,6 +6444,57 @@ static BOOL check_unicode_tategaki(WCHAR uchar)
return (orientation == 1 || orientation == 3);
}
static FT_Vector get_advance_metric(GdiFont *incoming_font, GdiFont *font,
const FT_Glyph_Metrics *metrics,
const FT_Matrix *transMat, BOOL vertical_metrics)
{
FT_Vector adv;
FT_Fixed base_advance, em_scale = 0;
BOOL fixed_pitch_full = FALSE;
if (vertical_metrics)
base_advance = metrics->vertAdvance;
else
base_advance = metrics->horiAdvance;
adv.x = base_advance;
adv.y = 0;
/* In fixed-pitch font, we adjust the fullwidth character advance so that
they have double halfwidth character width. E.g. if the font is 19 ppem,
we return 20 (not 19) for fullwidth characters as we return 10 for
halfwidth characters. */
if(FT_IS_SCALABLE(incoming_font->ft_face) &&
(incoming_font->potm || get_outline_text_metrics(incoming_font)) &&
!font->fake_bold &&
!(incoming_font->potm->otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
UINT avg_advance;
em_scale = MulDiv(incoming_font->ppem, 1 << 16,
incoming_font->ft_face->units_per_EM);
avg_advance = pFT_MulFix(incoming_font->ntmAvgWidth, em_scale);
fixed_pitch_full = (avg_advance > 0 &&
(base_advance + 63) >> 6 ==
pFT_MulFix(incoming_font->ntmAvgWidth*2, em_scale));
if (fixed_pitch_full && !transMat)
adv.x = (avg_advance * 2) << 6;
}
if (transMat) {
pFT_Vector_Transform(&adv, transMat);
if (fixed_pitch_full && adv.y == 0) {
FT_Vector vec;
vec.x = incoming_font->ntmAvgWidth;
vec.y = 0;
pFT_Vector_Transform(&vec, transMat);
adv.x = (pFT_MulFix(vec.x, em_scale) * 2) << 6;
}
}
adv.x = (adv.x + 63) & -64;
adv.y = -((adv.y + 63) & -64);
return adv;
}
static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
{
TTPOLYGONHEADER *pph;
@ -6656,7 +6707,8 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
DWORD width, height, pitch, needed = 0;
FT_Bitmap ft_bitmap;
FT_Error err;
INT left, right, top = 0, bottom = 0, adv;
INT left, right, top = 0, bottom = 0;
FT_Vector adv;
INT origin_x = 0, origin_y = 0;
FT_Angle angle = 0;
FT_Int load_flags = FT_LOAD_DEFAULT | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
@ -6668,8 +6720,6 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
BOOL tategaki = (font->name[0] == '@');
BOOL vertical_metrics;
UINT original_index;
LONG avgAdvance = 0;
FT_Fixed em_scale;
TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm,
buflen, buf, lpmat);
@ -6868,32 +6918,13 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
/* metrics.width = min( metrics.width, ptm->tmMaxCharWidth << 6 ); */
}
em_scale = MulDiv(incoming_font->ppem, 1 << 16, incoming_font->ft_face->units_per_EM);
if(FT_IS_SCALABLE(incoming_font->ft_face) && !font->fake_bold) {
TEXTMETRICW tm;
if (get_text_metrics(incoming_font, &tm) &&
!(tm.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
avgAdvance = pFT_MulFix(incoming_font->ntmAvgWidth, em_scale);
if (avgAdvance &&
(metrics.horiAdvance+63) >> 6 == pFT_MulFix(incoming_font->ntmAvgWidth*2, em_scale))
TRACE("Fixed-pitch full-width character detected\n");
else
avgAdvance = 0; /* cancel this feature */
}
}
if(!needsTransform) {
left = (INT)(metrics.horiBearingX) & -64;
right = (INT)((metrics.horiBearingX + metrics.width) + 63) & -64;
if (!avgAdvance)
adv = (INT)(metrics.horiAdvance + 63) >> 6;
else
adv = (INT)avgAdvance * 2;
top = (metrics.horiBearingY + 63) & -64;
bottom = (metrics.horiBearingY - metrics.height) & -64;
gm.gmCellIncX = adv;
adv = get_advance_metric(incoming_font, font, &metrics, NULL, vertical_metrics);
gm.gmCellIncX = adv.x >> 6;
gm.gmCellIncY = 0;
origin_x = left;
origin_y = top;
@ -6949,36 +6980,11 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
}
TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
if (vertical_metrics)
vec.x = metrics.vertAdvance;
else
vec.x = metrics.horiAdvance;
vec.y = 0;
pFT_Vector_Transform(&vec, &transMat);
gm.gmCellIncY = -((vec.y+63) >> 6);
if (!avgAdvance || vec.y)
gm.gmCellIncX = (vec.x+63) >> 6;
else {
vec.x = incoming_font->ntmAvgWidth;
vec.y = 0;
pFT_Vector_Transform(&vec, &transMat);
gm.gmCellIncX = pFT_MulFix(vec.x, em_scale) * 2;
}
adv = get_advance_metric(incoming_font, font, &metrics, &transMat, vertical_metrics);
gm.gmCellIncX = adv.x >> 6;
gm.gmCellIncY = adv.y >> 6;
if (vertical_metrics)
vec.x = metrics.vertAdvance;
else
vec.x = metrics.horiAdvance;
vec.y = 0;
pFT_Vector_Transform(&vec, &transMatUnrotated);
if (!avgAdvance || vec.y)
adv = (vec.x+63) >> 6;
else {
vec.x = incoming_font->ntmAvgWidth;
vec.y = 0;
pFT_Vector_Transform(&vec, &transMatUnrotated);
adv = pFT_MulFix(vec.x, em_scale) * 2;
}
adv = get_advance_metric(incoming_font, font, &metrics, &transMatUnrotated, vertical_metrics);
vec.x = lsb;
vec.y = 0;
@ -7001,7 +7007,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
gm.gmptGlyphOrigin.x = origin_x >> 6;
gm.gmptGlyphOrigin.y = origin_y >> 6;
if (!abc->abcB) abc->abcB = 1;
abc->abcC = adv - abc->abcA - abc->abcB;
abc->abcC = (adv.x >> 6) - abc->abcA - abc->abcB;
TRACE("%u,%u,%s,%d,%d\n", gm.gmBlackBoxX, gm.gmBlackBoxY,
wine_dbgstr_point(&gm.gmptGlyphOrigin),