gdi32: Add helper functions to compute the glyph metrics.
Signed-off-by: Byeongsik Jeon <bsjeon@hanmail.net> Signed-off-by: Huw Davies <huw@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6c32ce64e9
commit
fe5f0ebf0c
|
@ -6859,6 +6859,135 @@ static FT_Vector get_advance_metric(GdiFont *incoming_font, GdiFont *font,
|
|||
return adv;
|
||||
}
|
||||
|
||||
static FT_BBox get_transformed_bbox( const FT_Glyph_Metrics *metrics,
|
||||
BOOL needs_transform, const FT_Matrix metrices[3] )
|
||||
{
|
||||
FT_BBox bbox = { 0, 0, 0, 0 };
|
||||
|
||||
if (!needs_transform)
|
||||
{
|
||||
bbox.xMin = (metrics->horiBearingX) & -64;
|
||||
bbox.xMax = (metrics->horiBearingX + metrics->width + 63) & -64;
|
||||
bbox.yMax = (metrics->horiBearingY + 63) & -64;
|
||||
bbox.yMin = (metrics->horiBearingY - metrics->height) & -64;
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_Vector vec;
|
||||
INT xc, yc;
|
||||
|
||||
for (xc = 0; xc < 2; xc++)
|
||||
{
|
||||
for (yc = 0; yc < 2; yc++)
|
||||
{
|
||||
vec.x = metrics->horiBearingX + xc * metrics->width;
|
||||
vec.y = metrics->horiBearingY - yc * metrics->height;
|
||||
TRACE( "Vec %ld,i %ld\n", vec.x, vec.y );
|
||||
pFT_Vector_Transform( &vec, &metrices[matrix_vert] );
|
||||
if (xc == 0 && yc == 0)
|
||||
{
|
||||
bbox.xMin = bbox.xMax = vec.x;
|
||||
bbox.yMin = bbox.yMax = vec.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vec.x < bbox.xMin) bbox.xMin = vec.x;
|
||||
else if (vec.x > bbox.xMax) bbox.xMax = vec.x;
|
||||
if (vec.y < bbox.yMin) bbox.yMin = vec.y;
|
||||
else if (vec.y > bbox.yMax) bbox.yMax = vec.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
bbox.xMin = bbox.xMin & -64;
|
||||
bbox.xMax = (bbox.xMax + 63) & -64;
|
||||
bbox.yMin = bbox.yMin & -64;
|
||||
bbox.yMax = (bbox.yMax + 63) & -64;
|
||||
TRACE( "transformed box: (%ld, %ld - %ld, %ld)\n", bbox.xMin, bbox.yMax, bbox.xMax, bbox.yMin );
|
||||
}
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
static void compute_metrics( GdiFont *incoming_font, GdiFont *font,
|
||||
FT_BBox bbox, const FT_Glyph_Metrics *metrics,
|
||||
BOOL vertical, BOOL vertical_metrics,
|
||||
BOOL needs_transform, const FT_Matrix matrices[3],
|
||||
GLYPHMETRICS *gm, ABC *abc )
|
||||
{
|
||||
FT_Vector adv, vec, origin;
|
||||
|
||||
if (!needs_transform)
|
||||
{
|
||||
adv = get_advance_metric( incoming_font, font, metrics, NULL, vertical_metrics );
|
||||
gm->gmCellIncX = adv.x >> 6;
|
||||
gm->gmCellIncY = 0;
|
||||
origin.x = bbox.xMin;
|
||||
origin.y = bbox.yMax;
|
||||
abc->abcA = origin.x >> 6;
|
||||
abc->abcB = (metrics->width + 63) >> 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
FT_Pos lsb;
|
||||
|
||||
if (vertical && (font->potm || get_outline_text_metrics( font )))
|
||||
{
|
||||
if (vertical_metrics)
|
||||
lsb = metrics->horiBearingY + metrics->vertBearingY;
|
||||
else
|
||||
lsb = metrics->vertAdvance + (font->potm->otmDescent << 6);
|
||||
vec.x = lsb;
|
||||
vec.y = font->potm->otmDescent << 6;
|
||||
TRACE( "Vec %ld,%ld\n", vec.x>>6, vec.y>>6 );
|
||||
pFT_Vector_Transform( &vec, &matrices[matrix_hori] );
|
||||
origin.x = (vec.x + bbox.xMin) & -64;
|
||||
origin.y = (vec.y + bbox.yMax + 63) & -64;
|
||||
lsb -= metrics->horiBearingY;
|
||||
}
|
||||
else
|
||||
{
|
||||
origin.x = bbox.xMin;
|
||||
origin.y = bbox.yMax;
|
||||
lsb = metrics->horiBearingX;
|
||||
}
|
||||
|
||||
adv = get_advance_metric( incoming_font, font, metrics, &matrices[matrix_hori],
|
||||
vertical_metrics );
|
||||
gm->gmCellIncX = adv.x >> 6;
|
||||
gm->gmCellIncY = adv.y >> 6;
|
||||
|
||||
adv = get_advance_metric( incoming_font, font, metrics, &matrices[matrix_unrotated],
|
||||
vertical_metrics );
|
||||
adv.x = pFT_Vector_Length( &adv );
|
||||
adv.y = 0;
|
||||
|
||||
vec.x = lsb;
|
||||
vec.y = 0;
|
||||
pFT_Vector_Transform( &vec, &matrices[matrix_unrotated] );
|
||||
if (lsb > 0) abc->abcA = pFT_Vector_Length( &vec ) >> 6;
|
||||
else abc->abcA = -((pFT_Vector_Length( &vec ) + 63) >> 6);
|
||||
|
||||
/* We use lsb again to avoid rounding errors */
|
||||
vec.x = lsb + (vertical ? metrics->height : metrics->width);
|
||||
vec.y = 0;
|
||||
pFT_Vector_Transform( &vec, &matrices[matrix_unrotated] );
|
||||
abc->abcB = ((pFT_Vector_Length( &vec ) + 63) >> 6) - abc->abcA;
|
||||
}
|
||||
if (!abc->abcB) abc->abcB = 1;
|
||||
abc->abcC = (adv.x >> 6) - abc->abcA - abc->abcB;
|
||||
|
||||
gm->gmptGlyphOrigin.x = origin.x >> 6;
|
||||
gm->gmptGlyphOrigin.y = origin.y >> 6;
|
||||
gm->gmBlackBoxX = (bbox.xMax - bbox.xMin) >> 6;
|
||||
gm->gmBlackBoxY = (bbox.yMax - bbox.yMin) >> 6;
|
||||
if (!gm->gmBlackBoxX) gm->gmBlackBoxX = 1;
|
||||
if (!gm->gmBlackBoxY) gm->gmBlackBoxY = 1;
|
||||
|
||||
TRACE( "gm: %u, %u, %s, %d, %d abc %d, %u, %d\n",
|
||||
gm->gmBlackBoxX, gm->gmBlackBoxY, wine_dbgstr_point(&gm->gmptGlyphOrigin),
|
||||
gm->gmCellIncX, gm->gmCellIncY, abc->abcA, abc->abcB, abc->abcC );
|
||||
}
|
||||
|
||||
static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
|
||||
{
|
||||
TTPOLYGONHEADER *pph;
|
||||
|
@ -7101,9 +7230,7 @@ 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;
|
||||
FT_Vector adv;
|
||||
INT origin_x = 0, origin_y = 0;
|
||||
FT_BBox bbox;
|
||||
FT_Int load_flags = get_load_flags(format);
|
||||
FT_Matrix matrices[3];
|
||||
BOOL needsTransform = FALSE;
|
||||
|
@ -7173,8 +7300,8 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||
if(incoming_font->potm || get_outline_text_metrics(incoming_font) ||
|
||||
get_bitmap_text_metrics(incoming_font)) {
|
||||
TEXTMETRICW *ptm = &incoming_font->potm->otmTextMetrics;
|
||||
top = min( metrics.horiBearingY, ptm->tmAscent << 6 );
|
||||
bottom = max( metrics.horiBearingY - metrics.height, -(ptm->tmDescent << 6) );
|
||||
INT top = min( metrics.horiBearingY, ptm->tmAscent << 6 );
|
||||
INT bottom = max( metrics.horiBearingY - metrics.height, -(ptm->tmDescent << 6) );
|
||||
metrics.horiBearingY = top;
|
||||
metrics.height = top - bottom;
|
||||
|
||||
|
@ -7182,102 +7309,10 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||
/* metrics.width = min( metrics.width, ptm->tmMaxCharWidth << 6 ); */
|
||||
}
|
||||
|
||||
if(!needsTransform) {
|
||||
left = (INT)(metrics.horiBearingX) & -64;
|
||||
right = (INT)((metrics.horiBearingX + metrics.width) + 63) & -64;
|
||||
top = (metrics.horiBearingY + 63) & -64;
|
||||
bottom = (metrics.horiBearingY - metrics.height) & -64;
|
||||
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;
|
||||
abc->abcA = origin_x >> 6;
|
||||
abc->abcB = (metrics.width + 63) >> 6;
|
||||
} else {
|
||||
INT xc, yc;
|
||||
FT_Vector vec;
|
||||
FT_Pos lsb;
|
||||
|
||||
left = right = 0;
|
||||
|
||||
for(xc = 0; xc < 2; xc++) {
|
||||
for(yc = 0; yc < 2; yc++) {
|
||||
vec.x = metrics.horiBearingX + xc * metrics.width;
|
||||
vec.y = metrics.horiBearingY - yc * metrics.height;
|
||||
TRACE("Vec %ld,%ld\n", vec.x, vec.y);
|
||||
pFT_Vector_Transform( &vec, &matrices[matrix_vert] );
|
||||
if(xc == 0 && yc == 0) {
|
||||
left = right = vec.x;
|
||||
top = bottom = vec.y;
|
||||
} else {
|
||||
if(vec.x < left) left = vec.x;
|
||||
else if(vec.x > right) right = vec.x;
|
||||
if(vec.y < bottom) bottom = vec.y;
|
||||
else if(vec.y > top) top = vec.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
left = left & -64;
|
||||
right = (right + 63) & -64;
|
||||
bottom = bottom & -64;
|
||||
top = (top + 63) & -64;
|
||||
|
||||
if (tategaki && (font->potm || get_outline_text_metrics(font)))
|
||||
{
|
||||
if (vertical_metrics)
|
||||
lsb = metrics.horiBearingY + metrics.vertBearingY;
|
||||
else
|
||||
lsb = metrics.vertAdvance + (font->potm->otmDescent << 6);
|
||||
vec.x = lsb;
|
||||
vec.y = font->potm->otmDescent << 6;
|
||||
TRACE ("Vec %ld,%ld\n", vec.x>>6, vec.y>>6);
|
||||
pFT_Vector_Transform( &vec, &matrices[matrix_hori] );
|
||||
origin_x = (vec.x + left) & -64;
|
||||
origin_y = (vec.y + top + 63) & -64;
|
||||
lsb -= metrics.horiBearingY;
|
||||
}
|
||||
else
|
||||
{
|
||||
origin_x = left;
|
||||
origin_y = top;
|
||||
lsb = metrics.horiBearingX;
|
||||
}
|
||||
|
||||
TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
|
||||
adv = get_advance_metric(incoming_font, font, &metrics, &matrices[matrix_hori], vertical_metrics);
|
||||
gm.gmCellIncX = adv.x >> 6;
|
||||
gm.gmCellIncY = adv.y >> 6;
|
||||
|
||||
adv = get_advance_metric(incoming_font, font, &metrics, &matrices[matrix_unrotated], vertical_metrics);
|
||||
adv.x = pFT_Vector_Length(&adv);
|
||||
adv.y = 0;
|
||||
|
||||
vec.x = lsb;
|
||||
vec.y = 0;
|
||||
pFT_Vector_Transform( &vec, &matrices[matrix_unrotated] );
|
||||
if(lsb > 0) abc->abcA = pFT_Vector_Length(&vec) >> 6;
|
||||
else abc->abcA = -((pFT_Vector_Length(&vec) + 63) >> 6);
|
||||
|
||||
/* We use lsb again to avoid rounding errors */
|
||||
vec.x = lsb + (tategaki ? metrics.height : metrics.width);
|
||||
vec.y = 0;
|
||||
pFT_Vector_Transform( &vec, &matrices[matrix_unrotated] );
|
||||
abc->abcB = ((pFT_Vector_Length(&vec) + 63) >> 6) - abc->abcA;
|
||||
}
|
||||
|
||||
width = (right - left) >> 6;
|
||||
height = (top - bottom) >> 6;
|
||||
gm.gmBlackBoxX = width ? width : 1;
|
||||
gm.gmBlackBoxY = height ? height : 1;
|
||||
gm.gmptGlyphOrigin.x = origin_x >> 6;
|
||||
gm.gmptGlyphOrigin.y = origin_y >> 6;
|
||||
if (!abc->abcB) abc->abcB = 1;
|
||||
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),
|
||||
gm.gmCellIncX, gm.gmCellIncY);
|
||||
bbox = get_transformed_bbox( &metrics, needsTransform, matrices );
|
||||
compute_metrics( incoming_font, font, bbox, &metrics,
|
||||
tategaki, vertical_metrics, needsTransform, matrices,
|
||||
&gm, abc );
|
||||
|
||||
if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) &&
|
||||
is_identity_MAT2(lpmat)) /* don't cache custom transforms */
|
||||
|
@ -7296,6 +7331,9 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||
return GDI_ERROR;
|
||||
}
|
||||
|
||||
width = (bbox.xMax - bbox.xMin ) >> 6;
|
||||
height = (bbox.yMax - bbox.yMin ) >> 6;
|
||||
|
||||
switch(format) {
|
||||
case GGO_BITMAP:
|
||||
pitch = ((width + 31) >> 5) << 2;
|
||||
|
@ -7340,7 +7378,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||
if(needsTransform)
|
||||
pFT_Outline_Transform( &ft_face->glyph->outline, &matrices[matrix_vert] );
|
||||
|
||||
pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
|
||||
pFT_Outline_Translate(&ft_face->glyph->outline, -bbox.xMin, -bbox.yMin );
|
||||
|
||||
/* Note: FreeType will only set 'black' bits for us. */
|
||||
memset(buf, 0, needed);
|
||||
|
@ -7401,7 +7439,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||
if(needsTransform)
|
||||
pFT_Outline_Transform( &ft_face->glyph->outline, &matrices[matrix_vert] );
|
||||
|
||||
pFT_Outline_Translate(&ft_face->glyph->outline, -left, -bottom );
|
||||
pFT_Outline_Translate(&ft_face->glyph->outline, -bbox.xMin, -bbox.yMin );
|
||||
|
||||
memset(ft_bitmap.buffer, 0, buflen);
|
||||
|
||||
|
@ -7492,13 +7530,13 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||
{
|
||||
gm.gmBlackBoxX += 2;
|
||||
gm.gmptGlyphOrigin.x -= 1;
|
||||
left -= (1 << 6);
|
||||
bbox.xMin -= (1 << 6);
|
||||
}
|
||||
else
|
||||
{
|
||||
gm.gmBlackBoxY += 2;
|
||||
gm.gmptGlyphOrigin.y += 1;
|
||||
top += (1 << 6);
|
||||
bbox.yMax += (1 << 6);
|
||||
}
|
||||
|
||||
width = gm.gmBlackBoxX;
|
||||
|
@ -7540,7 +7578,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||
vmul = 3;
|
||||
}
|
||||
|
||||
x_shift = ft_face->glyph->bitmap_left - (left >> 6);
|
||||
x_shift = ft_face->glyph->bitmap_left - (bbox.xMin >> 6);
|
||||
if ( x_shift < 0 )
|
||||
{
|
||||
src += hmul * -x_shift;
|
||||
|
@ -7552,7 +7590,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
|
|||
width -= x_shift;
|
||||
}
|
||||
|
||||
y_shift = (top >> 6) - ft_face->glyph->bitmap_top;
|
||||
y_shift = (bbox.yMax >> 6) - ft_face->glyph->bitmap_top;
|
||||
if ( y_shift < 0 )
|
||||
{
|
||||
src += src_pitch * vmul * -y_shift;
|
||||
|
|
Loading…
Reference in New Issue