[PATCH v2 3/7] gdi32: Add helper functions to compute the glyph metrics.
Huw Davies
huw at codeweavers.com
Wed Feb 6 03:51:45 CST 2019
On Wed, Jan 30, 2019 at 02:12:37AM +0900, Byeongsik Jeon wrote:
> Signed-off-by: Byeongsik Jeon <bsjeon at hanmail.net>
> ---
> dlls/gdi32/freetype.c | 250 ++++++++++++++++++++++++------------------
> 1 file changed, 145 insertions(+), 105 deletions(-)
>
> diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c
> index 7e07b22409..f996df62fe 100644
> --- a/dlls/gdi32/freetype.c
> +++ b/dlls/gdi32/freetype.c
> @@ -6873,6 +6873,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 needsTransform, const FT_Matrix *transMatTategaki )
Again, needs_transform. Let's pass the entries matrices array here for simpicity.
> +{
> + FT_BBox bbox = { 0, 0, 0, 0 };
> +
> + if (!needsTransform)
> + {
> + 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,%ld\n", vec.x, vec.y );
Add a space after comma.
> + pFT_Vector_Transform( &vec, transMatTategaki );
> + 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.yMax = (bbox.yMax + 63) & -64;
> + bbox.yMin = bbox.yMin & -64;
> + TRACE( "transformed box: (%ld,%ld - %ld,%ld)\n", bbox.xMin, bbox.yMax, bbox.xMax, bbox.yMin );
Again, spaces after commas.
> + }
> +
> + return bbox;
> +}
> +
> +static void compute_gm_abc_metrics( GdiFont *incoming_font, GdiFont *font,
I think compute_metrics should be fine.
> + FT_BBox bbox, const FT_Glyph_Metrics *metrics,
> + BOOL tategaki, BOOL vertical_metrics, BOOL needsTransform,
takegaki -> vertical
> + const FT_Matrix *transMat,
> + const FT_Matrix *transMatTategaki,
> + const FT_Matrix *transMatUnrotated,
These three become the array.
> + GLYPHMETRICS *gm, ABC *abc )
> +{
> + FT_Vector adv, vec, origin;
> +
> + if (!needsTransform)
> + {
> + 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 (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, transMat );
> + 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, transMat, vertical_metrics );
> + gm->gmCellIncX = adv.x >> 6;
> + gm->gmCellIncY = adv.y >> 6;
> +
> + adv = get_advance_metric( incoming_font, font, metrics, transMatUnrotated, vertical_metrics );
> + adv.x = pFT_Vector_Length( &adv );
> + adv.y = 0;
> +
> + vec.x = lsb;
> + vec.y = 0;
> + pFT_Vector_Transform( &vec, transMatUnrotated );
> + 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, transMatUnrotated );
> + 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\n", gm->gmBlackBoxX, gm->gmBlackBoxY,
> + wine_dbgstr_point(&gm->gmptGlyphOrigin), gm->gmCellIncX, gm->gmCellIncY );
> + TRACE( "abc: %d,%u,%d\n", abc->abcA, abc->abcB, abc->abcC );
Use the same format here as in get_cached_metrics.
> +}
> +
> static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf)
> {
> TTPOLYGONHEADER *pph;
> @@ -7116,9 +7245,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 transMat = identityMat;
> FT_Matrix transMatUnrotated;
> @@ -7191,8 +7318,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;
>
> @@ -7200,102 +7327,15 @@ 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, &transMatTategaki);
> - 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, &transMat);
> - 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;
> - }
> + bbox = get_transformed_bbox( &metrics, needsTransform, &transMatTategaki );
>
> - TRACE("transformed box: (%d,%d - %d,%d)\n", left, top, right, bottom);
> - adv = get_advance_metric(incoming_font, font, &metrics, &transMat, vertical_metrics);
> - gm.gmCellIncX = adv.x >> 6;
> - gm.gmCellIncY = adv.y >> 6;
> -
> - adv = get_advance_metric(incoming_font, font, &metrics, &transMatUnrotated, vertical_metrics);
> - adv.x = pFT_Vector_Length(&adv);
> - adv.y = 0;
> -
> - vec.x = lsb;
> - vec.y = 0;
> - pFT_Vector_Transform(&vec, &transMatUnrotated);
> - 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, &transMatUnrotated);
> - 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;
> + compute_gm_abc_metrics( incoming_font, font, bbox, &metrics,
> + tategaki, vertical_metrics, needsTransform,
> + &transMat, &transMatTategaki, &transMatUnrotated,
> + &gm, abc );
>
> - TRACE("%u,%u,%s,%d,%d\n", gm.gmBlackBoxX, gm.gmBlackBoxY,
> - wine_dbgstr_point(&gm.gmptGlyphOrigin),
> - gm.gmCellIncX, gm.gmCellIncY);
> + width = (bbox.xMax - bbox.xMin) >> 6;
> + height = (bbox.yMax - bbox.yMin) >> 6;
>
> if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) &&
> is_identity_MAT2(lpmat)) /* don't cache custom transforms */
> @@ -7358,7 +7398,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
> if(needsTransform)
> pFT_Outline_Transform(&ft_face->glyph->outline, &transMatTategaki);
>
> - 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);
> @@ -7419,7 +7459,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
> if(needsTransform)
> pFT_Outline_Transform(&ft_face->glyph->outline, &transMatTategaki);
>
> - 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);
>
> @@ -7510,13 +7550,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;
> @@ -7558,7 +7598,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;
> @@ -7570,7 +7610,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;
> --
> 2.20.1
>
>
>
More information about the wine-devel
mailing list