Signed-off-by: Byeongsik Jeon [email protected] --- Each helper function can be further refactored, but at this point, it has kept the existing code. In my personal git branch, I am modifying other issues, and these structural change seems appropriate.
I will send patches that actually fix metric problems separately.
dlls/gdi32/freetype.c | 234 ++++++++++++++++++++++-------------------- 1 file changed, 125 insertions(+), 109 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index c38108eece..a522bcaba6 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -6588,6 +6588,129 @@ static inline FT_Vector normalize_vector(FT_Vector *vec) return out; }
+static BOOL get_transform_matrix( GdiFont *font, BOOL tategaki, const MAT2 *lpmat, + FT_Matrix *transMat, FT_Matrix *transMatTategaki, + FT_Matrix *transMatUnrotated ) +{ + double widthRatio; + BOOL needsTransform = FALSE; + + /* Scaling factor */ + if (font->aveWidth) + { + TEXTMETRICW tm; + get_text_metrics( font, &tm ); + + widthRatio = (double)font->aveWidth; + widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth; + } + else + widthRatio = font->scale_y; + + /* Scaling transform */ + if (widthRatio != 1.0 || font->scale_y != 1.0) + { + FT_Matrix scaleMat; + scaleMat.xx = FT_FixedFromFloat( widthRatio ); + scaleMat.xy = 0; + scaleMat.yx = 0; + scaleMat.yy = FT_FixedFromFloat( font->scale_y ); + + pFT_Matrix_Multiply( &scaleMat, transMat ); + needsTransform = TRUE; + } + + /* Slant transform */ + if (font->fake_italic) + { + FT_Matrix slantMat; + slantMat.xx = (1 << 16); + slantMat.xy = (1 << 16) >> 2; + slantMat.yx = 0; + slantMat.yy = (1 << 16); + + pFT_Matrix_Multiply( &slantMat, transMat ); + needsTransform = TRUE; + } + + /* Rotation transform */ + *transMatUnrotated = *transMat; + *transMatTategaki = *transMat; + if (font->orientation || tategaki) + { + FT_Matrix rotationMat; + FT_Matrix taterotationMat; + FT_Vector vecAngle; + FT_Angle angle; + + double orient = font->orientation / 10.0; + double tate_orient = 0.f; + + if (tategaki) + tate_orient = ((font->orientation + 900) % 3600) / 10.0; + else + tate_orient = font->orientation / 10.0; + + if (orient) + { + angle = FT_FixedFromFloat( orient ); + pFT_Vector_Unit( &vecAngle, angle ); + rotationMat.xx = vecAngle.x; + rotationMat.xy = -vecAngle.y; + rotationMat.yx = -rotationMat.xy; + rotationMat.yy = rotationMat.xx; + + pFT_Matrix_Multiply( &rotationMat, transMat ); + } + + if (tate_orient) + { + angle = FT_FixedFromFloat( tate_orient ); + pFT_Vector_Unit( &vecAngle, angle ); + taterotationMat.xx = vecAngle.x; + taterotationMat.xy = -vecAngle.y; + taterotationMat.yx = -taterotationMat.xy; + taterotationMat.yy = taterotationMat.xx; + + pFT_Matrix_Multiply( &taterotationMat, transMatTategaki ); + } + + needsTransform = TRUE; + } + + /* World transform */ + if (!is_identity_FMAT2( &font->font_desc.matrix )) + { + FT_Matrix worldMat; + worldMat.xx = FT_FixedFromFloat( font->font_desc.matrix.eM11 ); + worldMat.xy = -FT_FixedFromFloat( font->font_desc.matrix.eM21 ); + worldMat.yx = -FT_FixedFromFloat( font->font_desc.matrix.eM12 ); + worldMat.yy = FT_FixedFromFloat( font->font_desc.matrix.eM22 ); + + pFT_Matrix_Multiply( &worldMat, transMat ); + pFT_Matrix_Multiply( &worldMat, transMatUnrotated ); + pFT_Matrix_Multiply( &worldMat, transMatTategaki ); + needsTransform = TRUE; + } + + /* Extra transformation specified by caller */ + if (!is_identity_MAT2( lpmat )) + { + FT_Matrix extraMat; + extraMat.xx = FT_FixedFromFIXED( lpmat->eM11 ); + extraMat.xy = FT_FixedFromFIXED( lpmat->eM21 ); + extraMat.yx = FT_FixedFromFIXED( lpmat->eM12 ); + extraMat.yy = FT_FixedFromFIXED( lpmat->eM22 ); + + pFT_Matrix_Multiply( &extraMat, transMat ); + pFT_Matrix_Multiply( &extraMat, transMatUnrotated ); + pFT_Matrix_Multiply( &extraMat, transMatTategaki ); + needsTransform = TRUE; + } + + return needsTransform; +} + static BOOL get_bold_glyph_outline(FT_GlyphSlot glyph, LONG ppem, FT_Glyph_Metrics *metrics) { FT_Error err; @@ -6946,9 +7069,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, 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 = get_load_flags(format); - double widthRatio = 1.0; FT_Matrix transMat = identityMat; FT_Matrix transMatUnrotated; FT_Matrix transMatTategaki; @@ -7008,113 +7129,8 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, if (!font->gm[original_index / GM_BLOCK_SIZE]) font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
- /* Scaling factor */ - if (font->aveWidth) - { - TEXTMETRICW tm; - - get_text_metrics(font, &tm); - - widthRatio = (double)font->aveWidth; - widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth; - } - else - widthRatio = font->scale_y; - - /* Scaling transform */ - if (widthRatio != 1.0 || font->scale_y != 1.0) - { - FT_Matrix scaleMat; - scaleMat.xx = FT_FixedFromFloat(widthRatio); - scaleMat.xy = 0; - scaleMat.yx = 0; - scaleMat.yy = FT_FixedFromFloat(font->scale_y); - - pFT_Matrix_Multiply(&scaleMat, &transMat); - needsTransform = TRUE; - } - - /* Slant transform */ - if (font->fake_italic) { - FT_Matrix slantMat; - - slantMat.xx = (1 << 16); - slantMat.xy = ((1 << 16) >> 2); - slantMat.yx = 0; - slantMat.yy = (1 << 16); - pFT_Matrix_Multiply(&slantMat, &transMat); - needsTransform = TRUE; - } - - /* Rotation transform */ - transMatUnrotated = transMat; - transMatTategaki = transMat; - if(font->orientation || tategaki) { - FT_Matrix rotationMat; - FT_Matrix taterotationMat; - FT_Vector vecAngle; - - double orient = font->orientation / 10.0; - double tate_orient = 0.f; - - if (tategaki) - tate_orient = ((font->orientation+900)%3600)/10.0; - else - tate_orient = font->orientation/10.0; - - if (orient) - { - angle = FT_FixedFromFloat(orient); - pFT_Vector_Unit(&vecAngle, angle); - rotationMat.xx = vecAngle.x; - rotationMat.xy = -vecAngle.y; - rotationMat.yx = -rotationMat.xy; - rotationMat.yy = rotationMat.xx; - - pFT_Matrix_Multiply(&rotationMat, &transMat); - } - - if (tate_orient) - { - angle = FT_FixedFromFloat(tate_orient); - pFT_Vector_Unit(&vecAngle, angle); - taterotationMat.xx = vecAngle.x; - taterotationMat.xy = -vecAngle.y; - taterotationMat.yx = -taterotationMat.xy; - taterotationMat.yy = taterotationMat.xx; - pFT_Matrix_Multiply(&taterotationMat, &transMatTategaki); - } - - needsTransform = TRUE; - } - - /* World transform */ - if (!is_identity_FMAT2(&font->font_desc.matrix)) - { - FT_Matrix worldMat; - worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11); - worldMat.xy = -FT_FixedFromFloat(font->font_desc.matrix.eM21); - worldMat.yx = -FT_FixedFromFloat(font->font_desc.matrix.eM12); - worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22); - pFT_Matrix_Multiply(&worldMat, &transMat); - pFT_Matrix_Multiply(&worldMat, &transMatUnrotated); - pFT_Matrix_Multiply(&worldMat, &transMatTategaki); - needsTransform = TRUE; - } - - /* Extra transformation specified by caller */ - if (!is_identity_MAT2(lpmat)) - { - FT_Matrix extraMat; - extraMat.xx = FT_FixedFromFIXED(lpmat->eM11); - extraMat.xy = FT_FixedFromFIXED(lpmat->eM21); - extraMat.yx = FT_FixedFromFIXED(lpmat->eM12); - extraMat.yy = FT_FixedFromFIXED(lpmat->eM22); - pFT_Matrix_Multiply(&extraMat, &transMat); - pFT_Matrix_Multiply(&extraMat, &transMatUnrotated); - pFT_Matrix_Multiply(&extraMat, &transMatTategaki); - needsTransform = TRUE; - } + needsTransform = get_transform_matrix( font, tategaki, lpmat, + &transMat, &transMatTategaki, &transMatUnrotated );
vertical_metrics = (tategaki && FT_HAS_VERTICAL(ft_face)); /* there is a freetype bug where vertical metrics are only
Signed-off-by: Byeongsik Jeon [email protected] --- dlls/gdi32/freetype.c | 81 ++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 27 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index a522bcaba6..7e07b22409 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -4697,6 +4697,56 @@ static void free_font(GdiFont *font) HeapFree(GetProcessHeap(), 0, font); }
+/* TODO: GGO format support */ +static GM *get_cached_gm_abc_metrics( GdiFont *font, UINT index, + GLYPHMETRICS *gm, ABC *abc ) +{ + UINT block = index / GM_BLOCK_SIZE; + UINT entry = index % GM_BLOCK_SIZE; + GM *ret = NULL; + + if (block < font->gmsize && font->gm[block] && font->gm[block][entry].init) + { + *gm = font->gm[block][entry].gm; + *abc = font->gm[block][entry].abc; + ret = &font->gm[block][entry]; + + TRACE( "cached gm: %u,%u,%s,%d,%d\n", gm->gmBlackBoxX, gm->gmBlackBoxY, + wine_dbgstr_point( &gm->gmptGlyphOrigin ), + gm->gmCellIncX, gm->gmCellIncY ); + TRACE( "cached abc: %d,%u,%d\n", abc->abcA, abc->abcB, abc->abcC ); + } + + return ret; +} + +static void cache_gm_abc_metrics( GdiFont *font, UINT index, + const GLYPHMETRICS *gm, const ABC *abc ) +{ + UINT block = index / GM_BLOCK_SIZE; + UINT entry = index % GM_BLOCK_SIZE; + + if (block >= font->gmsize) + { + GM **ptr = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + font->gm, (block + 1) * sizeof(GM *) ); + if (!ptr) return; + + font->gmsize = block + 1; + font->gm = ptr; + } + + if (!font->gm[block]) + { + font->gm[block] = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, + sizeof(GM) * GM_BLOCK_SIZE ); + if (!font->gm[block]) return; + } + + font->gm[block][entry].gm = *gm; + font->gm[block][entry].abc = *abc; + font->gm[block][entry].init = TRUE; +}
static DWORD get_font_data( GdiFont *font, DWORD table, DWORD offset, LPVOID buf, DWORD cbData) { @@ -7076,7 +7126,6 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, BOOL needsTransform = FALSE; BOOL tategaki = (font->name[0] == '@'); BOOL vertical_metrics; - UINT original_index;
TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm, buflen, buf, lpmat); @@ -7093,7 +7142,6 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, TRACE("translate glyph index %04x -> %04x\n", glyph, glyph_index); } else glyph_index = glyph; - original_index = glyph_index; format &= ~GGO_GLYPH_INDEX; /* TODO: Window also turns off tategaki for glyphs passed in by index if their unicode code points fall outside of the range that is @@ -7102,32 +7150,15 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, BOOL vert; get_glyph_index_linked(incoming_font, glyph, &font, &glyph_index, &vert); ft_face = font->ft_face; - original_index = glyph_index; if (!vert && tategaki) tategaki = check_unicode_tategaki(glyph); }
format &= ~GGO_UNHINTED;
- if(original_index >= font->gmsize * GM_BLOCK_SIZE) { - font->gmsize = (original_index / GM_BLOCK_SIZE + 1); - font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm, - font->gmsize * sizeof(GM*)); - } else { - if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL && - FONT_GM(font,original_index)->init && is_identity_MAT2(lpmat)) - { - *lpgm = FONT_GM(font,original_index)->gm; - *abc = FONT_GM(font,original_index)->abc; - TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY, - wine_dbgstr_point(&lpgm->gmptGlyphOrigin), - lpgm->gmCellIncX, lpgm->gmCellIncY); - return 1; /* FIXME */ - } - } - - if (!font->gm[original_index / GM_BLOCK_SIZE]) - font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE); + if (format == GGO_METRICS && is_identity_MAT2(lpmat) && + get_cached_gm_abc_metrics( font, glyph_index, lpgm, abc )) + return 1; /* FIXME */
needsTransform = get_transform_matrix( font, tategaki, lpmat, &transMat, &transMatTategaki, &transMatUnrotated ); @@ -7268,11 +7299,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) && is_identity_MAT2(lpmat)) /* don't cache custom transforms */ - { - FONT_GM(font,original_index)->gm = gm; - FONT_GM(font,original_index)->abc = *abc; - FONT_GM(font,original_index)->init = TRUE; - } + cache_gm_abc_metrics( font, glyph_index, &gm, abc );
if(format == GGO_METRICS) {
On Wed, Jan 30, 2019 at 02:12:36AM +0900, Byeongsik Jeon wrote:
Signed-off-by: Byeongsik Jeon [email protected]
dlls/gdi32/freetype.c | 81 ++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 27 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index a522bcaba6..7e07b22409 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -4697,6 +4697,56 @@ static void free_font(GdiFont *font) HeapFree(GetProcessHeap(), 0, font); }
+/* TODO: GGO format support */ +static GM *get_cached_gm_abc_metrics( GdiFont *font, UINT index,
GLYPHMETRICS *gm, ABC *abc )
"get_cached_matrics" should be clear enough.
+{
- UINT block = index / GM_BLOCK_SIZE;
- UINT entry = index % GM_BLOCK_SIZE;
- GM *ret = NULL;
- if (block < font->gmsize && font->gm[block] && font->gm[block][entry].init)
- {
*gm = font->gm[block][entry].gm;
*abc = font->gm[block][entry].abc;
ret = &font->gm[block][entry];
TRACE( "cached gm: %u,%u,%s,%d,%d\n", gm->gmBlackBoxX, gm->gmBlackBoxY,
wine_dbgstr_point( &gm->gmptGlyphOrigin ),
gm->gmCellIncX, gm->gmCellIncY );
TRACE( "cached abc: %d,%u,%d\n", abc->abcA, abc->abcB, abc->abcC );
Let's put all of these in one line "cached gm: %u, %u, %s, %d, %d abc: %d, %u, %d\n"
- }
- return ret;
+}
+static void cache_gm_abc_metrics( GdiFont *font, UINT index,
const GLYPHMETRICS *gm, const ABC *abc )
"set_cached_matrics"
+{
- UINT block = index / GM_BLOCK_SIZE;
- UINT entry = index % GM_BLOCK_SIZE;
- if (block >= font->gmsize)
- {
GM **ptr = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
font->gm, (block + 1) * sizeof(GM *) );
if (!ptr) return;
font->gmsize = block + 1;
font->gm = ptr;
- }
- if (!font->gm[block])
- {
font->gm[block] = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(GM) * GM_BLOCK_SIZE );
if (!font->gm[block]) return;
- }
- font->gm[block][entry].gm = *gm;
- font->gm[block][entry].abc = *abc;
- font->gm[block][entry].init = TRUE;
+}
static DWORD get_font_data( GdiFont *font, DWORD table, DWORD offset, LPVOID buf, DWORD cbData) { @@ -7076,7 +7126,6 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, BOOL needsTransform = FALSE; BOOL tategaki = (font->name[0] == '@'); BOOL vertical_metrics;
UINT original_index;
TRACE("%p, %04x, %08x, %p, %08x, %p, %p\n", font, glyph, format, lpgm, buflen, buf, lpmat);
@@ -7093,7 +7142,6 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, TRACE("translate glyph index %04x -> %04x\n", glyph, glyph_index); } else glyph_index = glyph;
format &= ~GGO_GLYPH_INDEX; /* TODO: Window also turns off tategaki for glyphs passed in by index if their unicode code points fall outside of the range that isoriginal_index = glyph_index;
@@ -7102,32 +7150,15 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, BOOL vert; get_glyph_index_linked(incoming_font, glyph, &font, &glyph_index, &vert); ft_face = font->ft_face;
original_index = glyph_index; if (!vert && tategaki) tategaki = check_unicode_tategaki(glyph);
}
format &= ~GGO_UNHINTED;
if(original_index >= font->gmsize * GM_BLOCK_SIZE) {
font->gmsize = (original_index / GM_BLOCK_SIZE + 1);
font->gm = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, font->gm,
font->gmsize * sizeof(GM*));
} else {
if (format == GGO_METRICS && font->gm[original_index / GM_BLOCK_SIZE] != NULL &&
FONT_GM(font,original_index)->init && is_identity_MAT2(lpmat))
{
*lpgm = FONT_GM(font,original_index)->gm;
*abc = FONT_GM(font,original_index)->abc;
TRACE("cached: %u,%u,%s,%d,%d\n", lpgm->gmBlackBoxX, lpgm->gmBlackBoxY,
wine_dbgstr_point(&lpgm->gmptGlyphOrigin),
lpgm->gmCellIncX, lpgm->gmCellIncY);
return 1; /* FIXME */
}
}
if (!font->gm[original_index / GM_BLOCK_SIZE])
font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
if (format == GGO_METRICS && is_identity_MAT2(lpmat) &&
get_cached_gm_abc_metrics( font, glyph_index, lpgm, abc ))
return 1; /* FIXME */
needsTransform = get_transform_matrix( font, tategaki, lpmat, &transMat, &transMatTategaki, &transMatUnrotated );
@@ -7268,11 +7299,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format,
if ((format == GGO_METRICS || format == GGO_BITMAP || format == WINE_GGO_GRAY16_BITMAP) && is_identity_MAT2(lpmat)) /* don't cache custom transforms */
- {
FONT_GM(font,original_index)->gm = gm;
FONT_GM(font,original_index)->abc = *abc;
FONT_GM(font,original_index)->init = TRUE;
- }
cache_gm_abc_metrics( font, glyph_index, &gm, abc );
if(format == GGO_METRICS) {
-- 2.20.1
Signed-off-by: Byeongsik Jeon [email protected] --- 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 ) +{ + 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 ); + 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 ); + } + + return bbox; +} + +static void compute_gm_abc_metrics( GdiFont *incoming_font, GdiFont *font, + FT_BBox bbox, const FT_Glyph_Metrics *metrics, + BOOL tategaki, BOOL vertical_metrics, BOOL needsTransform, + const FT_Matrix *transMat, + const FT_Matrix *transMatTategaki, + const FT_Matrix *transMatUnrotated, + 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 ); +} + 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;
On Wed, Jan 30, 2019 at 02:12:37AM +0900, Byeongsik Jeon wrote:
Signed-off-by: Byeongsik Jeon [email protected]
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
Add missing variable name modification from cf891b04a087bcbc713e704c1adbf6b88243e996.
Signed-off-by: Byeongsik Jeon [email protected] --- dlls/gdi32/freetype.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index f996df62fe..e5e3af2fe4 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -7676,7 +7676,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, if(buflen == 0) buf = NULL;
if (needsTransform && buf) - pFT_Outline_Transform(outline, &transMat); + pFT_Outline_Transform(outline, &transMatTategaki);
needed = get_bezier_glyph_outline(outline, buflen, NULL);
Signed-off-by: Byeongsik Jeon [email protected] --- dlls/gdi32/freetype.c | 698 +++++++++++++++++++++--------------------- 1 file changed, 351 insertions(+), 347 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index e5e3af2fe4..8e4d8e33ad 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -7002,7 +7002,7 @@ static void compute_gm_abc_metrics( GdiFont *incoming_font, GdiFont *font, TRACE( "abc: %d,%u,%d\n", abc->abcA, abc->abcB, abc->abcC ); }
-static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf) +static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int buflen, BYTE *buf) { TTPOLYGONHEADER *pph; TTPOLYCURVE *ppc; @@ -7075,7 +7075,7 @@ static unsigned int get_native_glyph_outline(FT_Outline *outline, unsigned int b return needed; }
-static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int buflen, char *buf) +static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int buflen, BYTE *buf) { /* Convert the quadratic Beziers to cubic Beziers. The parametric eqn for a cubic Bezier is, from PLRM: @@ -7199,6 +7199,345 @@ static unsigned int get_bezier_glyph_outline(FT_Outline *outline, unsigned int b return needed; }
+static DWORD get_ggo_glyph_from_outline( FT_GlyphSlot glyph, UINT format, FT_BBox bbox, + GLYPHMETRICS *gm, + BOOL needsTransform, FT_Matrix *transMatTategaki, + DWORD buflen, BYTE *buf ) +{ + DWORD width = (bbox.xMax - bbox.xMin) >> 6; + DWORD height = (bbox.yMax - bbox.yMin) >> 6; + FT_Outline *outline = &glyph->outline; + DWORD max_level, pitch, needed = 0; + FT_Bitmap ft_bitmap; + + switch (format) + { + case GGO_BITMAP: + pitch = ((width + 31) >> 5) << 2; + needed = pitch * height; + + if (!buf || !buflen) break; + if (!needed) return GDI_ERROR; /* empty glyph */ + if (needed > buflen) return GDI_ERROR; + + ft_bitmap.width = width; + ft_bitmap.rows = height; + ft_bitmap.pitch = pitch; + ft_bitmap.pixel_mode = FT_PIXEL_MODE_MONO; + ft_bitmap.buffer = buf; + + if (needsTransform) + pFT_Outline_Transform( outline, transMatTategaki ); + pFT_Outline_Translate( outline, -bbox.xMin, -bbox.yMin ); + + /* Note: FreeType will only set 'black' bits for us. */ + memset( buf, 0, needed ); + pFT_Outline_Get_Bitmap( library, outline, &ft_bitmap ); + break; + + case GGO_GRAY2_BITMAP: + case GGO_GRAY4_BITMAP: + case GGO_GRAY8_BITMAP: + case WINE_GGO_GRAY16_BITMAP: + pitch = (width + 3) / 4 * 4; + needed = pitch * height; + + if (!buf || !buflen) break; + if (!needed) return GDI_ERROR; /* empty glyph */ + if (needed > buflen) return GDI_ERROR; + + ft_bitmap.width = width; + ft_bitmap.rows = height; + ft_bitmap.pitch = pitch; + ft_bitmap.pixel_mode = FT_PIXEL_MODE_GRAY; + ft_bitmap.buffer = buf; + + if (needsTransform) + pFT_Outline_Transform( outline, transMatTategaki ); + pFT_Outline_Translate( outline, -bbox.xMin, -bbox.yMin ); + + memset( ft_bitmap.buffer, 0, buflen ); + pFT_Outline_Get_Bitmap( library, outline, &ft_bitmap ); + + max_level = get_max_level( format ); + if (max_level != 255) + { + BYTE *start, *ptr; + UINT row, col; + + for (row = 0, start = buf; row < height; row++) + { + for (col = 0, ptr = start; col < width; col++, ptr++) + *ptr = (((int)*ptr) * (max_level + 1)) / 256; + start += pitch; + } + } + break; + + case WINE_GGO_HRGB_BITMAP: + case WINE_GGO_HBGR_BITMAP: + case WINE_GGO_VRGB_BITMAP: + case WINE_GGO_VBGR_BITMAP: + { + BYTE *src; + unsigned int *dst; + INT x, rgb_interval, hmul, vmul; + INT src_pitch, src_width, src_height, x_shift, y_shift; + const INT *sub_order; + const INT rgb_order[3] = { 0, 1, 2 }; + const INT bgr_order[3] = { 2, 1, 0 }; + FT_Render_Mode render_mode = + (format == WINE_GGO_HRGB_BITMAP || + format == WINE_GGO_HBGR_BITMAP) ? FT_RENDER_MODE_LCD: FT_RENDER_MODE_LCD_V; + + if (!width || !height) /* empty glyph */ + { + if (!buf || !buflen) break; + return GDI_ERROR; + } + + if (render_mode == FT_RENDER_MODE_LCD) + { + gm->gmBlackBoxX += 2; + gm->gmptGlyphOrigin.x -= 1; + bbox.xMin -= (1 << 6); + } + else + { + gm->gmBlackBoxY += 2; + gm->gmptGlyphOrigin.y += 1; + bbox.yMax += (1 << 6); + } + + width = gm->gmBlackBoxX; + height = gm->gmBlackBoxY; + pitch = width * 4; + needed = pitch * height; + + if (!buf || !buflen) break; + if (needed > buflen) return GDI_ERROR; + + memset( buf, 0, buflen ); + dst = (unsigned int *)buf; + + if (needsTransform) + pFT_Outline_Transform( outline, transMatTategaki ); + +#ifdef FT_LCD_FILTER_H + if (pFT_Library_SetLcdFilter) + pFT_Library_SetLcdFilter( library, FT_LCD_FILTER_DEFAULT ); +#endif + pFT_Render_Glyph( glyph, render_mode ); + + src = glyph->bitmap.buffer; + src_pitch = glyph->bitmap.pitch; + src_width = glyph->bitmap.width; + src_height = glyph->bitmap.rows; + + rgb_interval = render_mode == FT_RENDER_MODE_LCD ? 1 : src_pitch; + hmul = render_mode == FT_RENDER_MODE_LCD ? 3 : 1; + vmul = render_mode == FT_RENDER_MODE_LCD ? 1 : 3; + + x_shift = glyph->bitmap_left - (bbox.xMin >> 6); + if (x_shift < 0) + { + src += hmul * -x_shift; + src_width -= hmul * -x_shift; + } + else if (x_shift > 0) + { + dst += x_shift; + width -= x_shift; + } + + y_shift = (bbox.yMax >> 6) - glyph->bitmap_top; + if (y_shift < 0) + { + src += src_pitch * vmul * -y_shift; + src_height -= vmul * -y_shift; + } + else if (y_shift > 0) + { + dst += y_shift * (pitch / sizeof(*dst)); + height -= y_shift; + } + + width = min( width, src_width / hmul ); + height = min( height, src_height / vmul ); + + sub_order = (format == WINE_GGO_HRGB_BITMAP || + format == WINE_GGO_VRGB_BITMAP) ? rgb_order : bgr_order; + + while (height--) + { + for (x = 0; x < width; x++) + { + dst[x] = ((unsigned int)src[hmul * x + rgb_interval * sub_order[0]] << 16) | + ((unsigned int)src[hmul * x + rgb_interval * sub_order[1]] << 8) | + ((unsigned int)src[hmul * x + rgb_interval * sub_order[2]]); + } + src += src_pitch * vmul; + dst += pitch / sizeof(*dst); + } + break; + } + case GGO_NATIVE: + if (buflen == 0) buf = NULL; + + if (needsTransform && buf) + pFT_Outline_Transform( outline, transMatTategaki ); + + needed = get_native_glyph_outline( outline, buflen, NULL ); + + if (!buf || !buflen) break; + if (needed > buflen) return GDI_ERROR; + + get_native_glyph_outline( outline, buflen, buf ); + break; + + case GGO_BEZIER: + if (buflen == 0) buf = NULL; + + if (needsTransform && buf) + pFT_Outline_Transform( outline, transMatTategaki ); + + needed = get_bezier_glyph_outline( outline, buflen, NULL ); + + if (!buf || !buflen) break; + if (needed > buflen) return GDI_ERROR; + + get_bezier_glyph_outline( outline, buflen, buf ); + break; + + default: + FIXME("Unsupported format %d\n", format); + return GDI_ERROR; + } + + return needed; +} + +static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; + +static DWORD get_ggo_glyph_from_bitmap( FT_GlyphSlot glyph, UINT format, FT_BBox bbox, + GdiFont *font, + DWORD buflen, BYTE *buf ) +{ + DWORD width = (bbox.xMax - bbox.xMin) >> 6; + DWORD height = (bbox.yMax - bbox.yMin) >> 6; + DWORD max_level, pitch, needed = 0; + BYTE *src, *dst; + INT x, w, h; + + switch (format) + { + case GGO_BITMAP: + pitch = ((width + 31) >> 5) << 2; + needed = pitch * height; + + if (!buf || !buflen) break; + if (!needed) return GDI_ERROR; /* empty glyph */ + if (needed > buflen) return GDI_ERROR; + + src = glyph->bitmap.buffer; + dst = buf; + w = min( pitch, (glyph->bitmap.width + 7) >> 3 ); + h = min( height, glyph->bitmap.rows ); + while (h--) + { + if (!font->fake_bold) + memcpy( dst, src, w ); + else + { + dst[0] = 0; + for (x = 0; x < w; x++) + { + dst[x] = (dst[x] & 0x80) | (src[x] >> 1) | src[x]; + if (x + 1 < pitch) + dst[x + 1] = (src[x] & 0x01) << 7; + } + } + src += glyph->bitmap.pitch; + dst += pitch; + } + break; + + case GGO_GRAY2_BITMAP: + case GGO_GRAY4_BITMAP: + case GGO_GRAY8_BITMAP: + case WINE_GGO_GRAY16_BITMAP: + pitch = (width + 3) / 4 * 4; + needed = pitch * height; + + if(!buf || !buflen) break; + if (!needed) return GDI_ERROR; /* empty glyph */ + if (needed > buflen) return GDI_ERROR; + + src = glyph->bitmap.buffer; + dst = buf; + memset( buf, 0, buflen ); + max_level = get_max_level( format ); + h = min( height, glyph->bitmap.rows ); + while (h--) + { + for (x = 0; x < pitch && x < glyph->bitmap.width; x++) + { + if (src[x / 8] & masks[x % 8]) + { + dst[x] = max_level; + if (font->fake_bold && x + 1 < pitch) + dst[x+1] = max_level; + } + } + src += glyph->bitmap.pitch; + dst += pitch; + } + break; + + case WINE_GGO_HRGB_BITMAP: + case WINE_GGO_HBGR_BITMAP: + case WINE_GGO_VRGB_BITMAP: + case WINE_GGO_VBGR_BITMAP: + pitch = width * 4; + needed = pitch * height; + + if (!buf || !buflen) break; + if (!needed) return GDI_ERROR; /* empty glyph */ + if (needed > buflen) return GDI_ERROR; + + src = glyph->bitmap.buffer; + dst = buf; + memset(buf, 0, buflen); + h = min( height, glyph->bitmap.rows ); + while (h--) + { + for (x = 0; x < width && x < glyph->bitmap.width; x++) + { + if (src[x / 8] & masks[x % 8]) + { + ((unsigned int *)dst)[x] = ~0u; + if (font->fake_bold && x + 1 < width) + ((unsigned int *)dst)[x + 1] = ~0u; + } + } + src += glyph->bitmap.pitch; + dst += pitch; + } + break; + + case GGO_NATIVE: + case GGO_BEZIER: + TRACE("loaded a bitmap\n"); + return GDI_ERROR; + + default: + FIXME("Unsupported format %d\n", format); + return GDI_ERROR; + } + + return needed; +} + static FT_Int get_load_flags( UINT format ) { FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH; @@ -7230,8 +7569,6 @@ static FT_Int get_load_flags( UINT format ) return load_flags; }
-static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01}; - static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, LPGLYPHMETRICS lpgm, ABC *abc, DWORD buflen, LPVOID buf, const MAT2* lpmat) @@ -7242,8 +7579,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, GdiFont *font = incoming_font; FT_Glyph_Metrics metrics; FT_UInt glyph_index; - DWORD width, height, pitch, needed = 0; - FT_Bitmap ft_bitmap; + DWORD needed = 0; FT_Error err; FT_BBox bbox; FT_Int load_flags = get_load_flags(format); @@ -7334,9 +7670,6 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, &transMat, &transMatTategaki, &transMatUnrotated, &gm, abc );
- 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 */ cache_gm_abc_metrics( font, glyph_index, &gm, abc ); @@ -7347,352 +7680,23 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, return 1; /* FIXME */ }
- if(ft_face->glyph->format != ft_glyph_format_outline && - (format == GGO_NATIVE || format == GGO_BEZIER)) + switch (ft_face->glyph->format) { - TRACE("loaded a bitmap\n"); - return GDI_ERROR; - } - - switch(format) { - case GGO_BITMAP: - pitch = ((width + 31) >> 5) << 2; - needed = pitch * height; - - if(!buf || !buflen) break; - if (!needed) return GDI_ERROR; /* empty glyph */ - if (needed > buflen) - return GDI_ERROR; - - switch(ft_face->glyph->format) { - case ft_glyph_format_bitmap: - { - BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf; - INT w = min( pitch, (ft_face->glyph->bitmap.width + 7) >> 3 ); - INT h = min( height, ft_face->glyph->bitmap.rows ); - while(h--) { - if (!font->fake_bold) - memcpy(dst, src, w); - else { - INT x; - dst[0] = 0; - for (x = 0; x < w; x++) { - dst[x ] = (dst[x] & 0x80) | (src[x] >> 1) | src[x]; - if (x+1 < pitch) - dst[x+1] = (src[x] & 0x01) << 7; - } - } - src += ft_face->glyph->bitmap.pitch; - dst += pitch; - } - break; - } - - case ft_glyph_format_outline: - ft_bitmap.width = width; - ft_bitmap.rows = height; - ft_bitmap.pitch = pitch; - ft_bitmap.pixel_mode = ft_pixel_mode_mono; - ft_bitmap.buffer = buf; - - if(needsTransform) - pFT_Outline_Transform(&ft_face->glyph->outline, &transMatTategaki); - - pFT_Outline_Translate(&ft_face->glyph->outline, -bbox.xMin, -bbox.yMin ); - - /* Note: FreeType will only set 'black' bits for us. */ - memset(buf, 0, needed); - pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); - break; - - default: - FIXME("loaded glyph format %x\n", ft_face->glyph->format); - return GDI_ERROR; - } - break; - - case GGO_GRAY2_BITMAP: - case GGO_GRAY4_BITMAP: - case GGO_GRAY8_BITMAP: - case WINE_GGO_GRAY16_BITMAP: - { - unsigned int max_level, row, col; - BYTE *start, *ptr; - - pitch = (width + 3) / 4 * 4; - needed = pitch * height; - - if(!buf || !buflen) break; - if (!needed) return GDI_ERROR; /* empty glyph */ - if (needed > buflen) - return GDI_ERROR; - - max_level = get_max_level( format ); - - switch(ft_face->glyph->format) { - case ft_glyph_format_bitmap: - { - BYTE *src = ft_face->glyph->bitmap.buffer, *dst = buf; - INT h = min( height, ft_face->glyph->bitmap.rows ); - INT x; - memset( buf, 0, needed ); - while(h--) { - for(x = 0; x < pitch && x < ft_face->glyph->bitmap.width; x++) { - if (src[x / 8] & masks[x % 8]) { - dst[x] = max_level; - if (font->fake_bold && x+1 < pitch) dst[x+1] = max_level; - } - } - src += ft_face->glyph->bitmap.pitch; - dst += pitch; - } - break; - } - case ft_glyph_format_outline: - { - ft_bitmap.width = width; - ft_bitmap.rows = height; - ft_bitmap.pitch = pitch; - ft_bitmap.pixel_mode = ft_pixel_mode_grays; - ft_bitmap.buffer = buf; - - if(needsTransform) - pFT_Outline_Transform(&ft_face->glyph->outline, &transMatTategaki); - - pFT_Outline_Translate(&ft_face->glyph->outline, -bbox.xMin, -bbox.yMin ); - - memset(ft_bitmap.buffer, 0, buflen); - - pFT_Outline_Get_Bitmap(library, &ft_face->glyph->outline, &ft_bitmap); - - if (max_level != 255) - { - for (row = 0, start = buf; row < height; row++) - { - for (col = 0, ptr = start; col < width; col++, ptr++) - *ptr = (((int)*ptr) * (max_level + 1)) / 256; - start += pitch; - } - } - break; - } - - default: - FIXME("loaded glyph format %x\n", ft_face->glyph->format); - return GDI_ERROR; - } - break; - } - - case WINE_GGO_HRGB_BITMAP: - case WINE_GGO_HBGR_BITMAP: - case WINE_GGO_VRGB_BITMAP: - case WINE_GGO_VBGR_BITMAP: - { - switch (ft_face->glyph->format) - { case FT_GLYPH_FORMAT_BITMAP: - { - BYTE *src, *dst; - INT src_pitch, x; - - pitch = width * 4; - needed = pitch * height; - - if (!buf || !buflen) break; - if (!needed) return GDI_ERROR; /* empty glyph */ - if (needed > buflen) - return GDI_ERROR; - - memset(buf, 0, buflen); - dst = buf; - src = ft_face->glyph->bitmap.buffer; - src_pitch = ft_face->glyph->bitmap.pitch; - - height = min( height, ft_face->glyph->bitmap.rows ); - while ( height-- ) - { - for (x = 0; x < width && x < ft_face->glyph->bitmap.width; x++) - { - if ( src[x / 8] & masks[x % 8] ) - { - ((unsigned int *)dst)[x] = ~0u; - if (font->fake_bold && x+1 < width) ((unsigned int *)dst)[x+1] = ~0u; - } - } - src += src_pitch; - dst += pitch; - } - + needed = get_ggo_glyph_from_bitmap( ft_face->glyph, format, bbox, font, + buflen, buf ); break; - } - case FT_GLYPH_FORMAT_OUTLINE: - { - unsigned int *dst; - BYTE *src; - INT x, src_pitch, src_width, src_height, rgb_interval, hmul, vmul; - INT x_shift, y_shift; - const INT *sub_order; - const INT rgb_order[3] = { 0, 1, 2 }; - const INT bgr_order[3] = { 2, 1, 0 }; - FT_Render_Mode render_mode = - (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_HBGR_BITMAP)? - FT_RENDER_MODE_LCD: FT_RENDER_MODE_LCD_V; - - if (!width || !height) - { - if (!buf || !buflen) break; - return GDI_ERROR; - } - - if ( render_mode == FT_RENDER_MODE_LCD) - { - gm.gmBlackBoxX += 2; - gm.gmptGlyphOrigin.x -= 1; - bbox.xMin -= (1 << 6); - } - else - { - gm.gmBlackBoxY += 2; - gm.gmptGlyphOrigin.y += 1; - bbox.yMax += (1 << 6); - } - - width = gm.gmBlackBoxX; - height = gm.gmBlackBoxY; - pitch = width * 4; - needed = pitch * height; - - if (!buf || !buflen) break; - if (needed > buflen) - return GDI_ERROR; - - memset(buf, 0, buflen); - dst = buf; - - if ( needsTransform ) - pFT_Outline_Transform (&ft_face->glyph->outline, &transMatTategaki); - -#ifdef FT_LCD_FILTER_H - if ( pFT_Library_SetLcdFilter ) - pFT_Library_SetLcdFilter( library, FT_LCD_FILTER_DEFAULT ); -#endif - pFT_Render_Glyph (ft_face->glyph, render_mode); - - src = ft_face->glyph->bitmap.buffer; - src_pitch = ft_face->glyph->bitmap.pitch; - src_width = ft_face->glyph->bitmap.width; - src_height = ft_face->glyph->bitmap.rows; - - if ( render_mode == FT_RENDER_MODE_LCD) - { - rgb_interval = 1; - hmul = 3; - vmul = 1; - } - else - { - rgb_interval = src_pitch; - hmul = 1; - vmul = 3; - } - - x_shift = ft_face->glyph->bitmap_left - (bbox.xMin >> 6); - if ( x_shift < 0 ) - { - src += hmul * -x_shift; - src_width -= hmul * -x_shift; - } - else if ( x_shift > 0 ) - { - dst += x_shift; - width -= x_shift; - } - - y_shift = (bbox.yMax >> 6) - ft_face->glyph->bitmap_top; - if ( y_shift < 0 ) - { - src += src_pitch * vmul * -y_shift; - src_height -= vmul * -y_shift; - } - else if ( y_shift > 0 ) - { - dst += y_shift * ( pitch / sizeof(*dst) ); - height -= y_shift; - } - - width = min( width, src_width / hmul ); - height = min( height, src_height / vmul ); - - sub_order = (format == WINE_GGO_HRGB_BITMAP || format == WINE_GGO_VRGB_BITMAP)? - rgb_order : bgr_order; - - while ( height-- ) - { - for ( x = 0; x < width; x++ ) - { - dst[x] = ((unsigned int)src[hmul * x + rgb_interval * sub_order[0]] << 16) | - ((unsigned int)src[hmul * x + rgb_interval * sub_order[1]] << 8) | - ((unsigned int)src[hmul * x + rgb_interval * sub_order[2]]); - } - src += src_pitch * vmul; - dst += pitch / sizeof(*dst); - } - + needed = get_ggo_glyph_from_outline( ft_face->glyph, format, bbox, &gm, + needsTransform, &transMatTategaki, + buflen, buf ); break; - } - default: - FIXME ("loaded glyph format %x\n", ft_face->glyph->format); - return GDI_ERROR; - } - - break; - } - - case GGO_NATIVE: - { - FT_Outline *outline = &ft_face->glyph->outline; - - if(buflen == 0) buf = NULL; - - if (needsTransform && buf) - pFT_Outline_Transform(outline, &transMatTategaki); - - needed = get_native_glyph_outline(outline, buflen, NULL); - - if (!buf || !buflen) - break; - if (needed > buflen) - return GDI_ERROR; - - get_native_glyph_outline(outline, buflen, buf); - break; - } - case GGO_BEZIER: - { - FT_Outline *outline = &ft_face->glyph->outline; - if(buflen == 0) buf = NULL; - - if (needsTransform && buf) - pFT_Outline_Transform(outline, &transMatTategaki); - - needed = get_bezier_glyph_outline(outline, buflen, NULL); - - if (!buf || !buflen) - break; - if (needed > buflen) + FIXME("loaded glyph format %x\n", ft_face->glyph->format); return GDI_ERROR; - - get_bezier_glyph_outline(outline, buflen, buf); - break; - } - - default: - FIXME("Unsupported format %d\n", format); - return GDI_ERROR; } + if (needed == GDI_ERROR) return GDI_ERROR; + *lpgm = gm; return needed; }
On Wed, Jan 30, 2019 at 02:12:39AM +0900, Byeongsik Jeon wrote:
Signed-off-by: Byeongsik Jeon [email protected]
dlls/gdi32/freetype.c | 698 +++++++++++++++++++++--------------------- 1 file changed, 351 insertions(+), 347 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index e5e3af2fe4..8e4d8e33ad 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -7347,352 +7680,23 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, return 1; /* FIXME */ }
- if(ft_face->glyph->format != ft_glyph_format_outline &&
(format == GGO_NATIVE || format == GGO_BEZIER))
- switch (ft_face->glyph->format) {
TRACE("loaded a bitmap\n");
- return GDI_ERROR;
- }
- switch(format) {
I'm not sure inverting the switch order between requested format and loaded format makes it any better, though adding the helpers is good.
I'd suggest keeping the original switch but adding
get_mono_glyph_bitmap() for GGO_BITMAP get_antialias_glyph_bitmap() for GGO_GRAY*_BITMAP get_subpixel_glyph_bitmap() for the subpixel formats.
Also, please align the cases with the switch.
- case GGO_BITMAP:
- pitch = ((width + 31) >> 5) << 2;
needed = pitch * height;
- if(!buf || !buflen) break;
if (!needed) return GDI_ERROR; /* empty glyph */
if (needed > buflen)
return GDI_ERROR;
- switch(ft_face->glyph->format) {
- case ft_glyph_format_bitmap:
Signed-off-by: Byeongsik Jeon [email protected] --- dlls/gdi32/freetype.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index 8e4d8e33ad..bddcd56837 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -130,6 +130,7 @@ typedef struct } FT_Version_t; static FT_Version_t FT_Version; static DWORD FT_SimpleVersion; +#define FT_VERSION_VALUE(major, minor, patch) (((major) << 16) | ((minor) << 8) | (patch))
static void *ft_handle = NULL;
@@ -1003,7 +1004,7 @@ static BOOL is_subpixel_rendering_enabled( void ) if (enabled == -1) { /* FreeType >= 2.8.1 offers LCD-optimezed rendering without lcd filters. */ - if (FT_SimpleVersion >= ((2 << 16) | (8 << 8) | (1 << 0))) + if (FT_SimpleVersion >= FT_VERSION_VALUE(2, 8, 1)) enabled = TRUE; #ifdef FT_LCD_FILTER_H else if (pFT_Library_SetLcdFilter && @@ -2188,7 +2189,7 @@ static FT_Face new_ft_face( const char *file, void *font_data_ptr, DWORD font_da }
/* There are too many bugs in FreeType < 2.1.9 for bitmap font support */ - if (!FT_IS_SCALABLE( ft_face ) && FT_SimpleVersion < ((2 << 16) | (1 << 8) | (9 << 0))) + if (!FT_IS_SCALABLE( ft_face ) && FT_SimpleVersion < FT_VERSION_VALUE(2, 1, 9)) { WARN("FreeType version < 2.1.9, skipping bitmap font %s/%p\n", debugstr_a(file), font_data_ptr); goto fail; @@ -7629,7 +7630,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, vertical_metrics = (tategaki && FT_HAS_VERTICAL(ft_face)); /* there is a freetype bug where vertical metrics are only properly scaled and correct in 2.4.0 or greater */ - if ((vertical_metrics) && (FT_Version.major < 2 || (FT_Version.major == 2 && FT_Version.minor < 4))) + if (vertical_metrics && FT_SimpleVersion < FT_VERSION_VALUE(2, 4, 0)) vertical_metrics = FALSE;
if (needsTransform || format != GGO_BITMAP) load_flags |= FT_LOAD_NO_BITMAP;
Signed-off-by: Byeongsik Jeon [email protected] --- At the MS Korean dual-width fonts embedded bitmap, full-width character's advance width is smaller than expected in wine. We can solve this problem by slightly changing the logic.
Ex. gulim.ttc:GulimChe EM=1024 AvgWidth=512 ppem=19px half-width character advance = 10px ppem=19px full-width character advance = 18px But, Wine expects 19px.
dlls/gdi32/freetype.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index bddcd56837..cb804f8e5c 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -6839,9 +6839,7 @@ static FT_Vector get_advance_metric(GdiFont *incoming_font, GdiFont *font, 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)); + fixed_pitch_full = avg_advance > 0 && (base_advance + 63) >> 6 != avg_advance; if (fixed_pitch_full && !transMat) adv.x = (avg_advance * 2) << 6; }
On Wed, 30 Jan 2019 02:12:41 +0900, Byeongsik Jeon wrote:
Signed-off-by: Byeongsik Jeon [email protected]
At the MS Korean dual-width fonts embedded bitmap, full-width character's advance width is smaller than expected in wine. We can solve this problem by slightly changing the logic.
Ex. gulim.ttc:GulimChe EM=1024 AvgWidth=512 ppem=19px half-width character advance = 10px ppem=19px full-width character advance = 18px But, Wine expects 19px.
dlls/gdi32/freetype.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index bddcd56837..cb804f8e5c 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -6839,9 +6839,7 @@ static FT_Vector get_advance_metric(GdiFont *incoming_font, GdiFont *font, 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));
fixed_pitch_full = avg_advance > 0 && (base_advance + 63) >> 6 != avg_advance; if (fixed_pitch_full && !transMat) adv.x = (avg_advance * 2) << 6;
In my opinion, why don't we test the following condition for fixed_pitch_full? fixed_pitch_full = avg_advance > 0 && (base_advance + 63) >> 6 >= pFT_MulFix(MulDiv(incoming_font->ntmAvgWidth, x, y), em_scale); The x and y are heuristic ratio. I think they will be 1.5~1.8.
Because base_advance can be based on linked font, i.e. another font replaced by get_glyph_index_linked(), the glyph might be a proportional typeface. In that case, "(base_advance + 63) >> 6 != avg_advance" is very loose restriction. A narrow character may be treated as a Full-width character in that case.
Regards, Akihiro Sagawa
Akihiro Sagawa wrote:
In my opinion, why don't we test the following condition for fixed_pitch_full? fixed_pitch_full = avg_advance > 0 && (base_advance + 63) >> 6 >= pFT_MulFix(MulDiv(incoming_font->ntmAvgWidth, x, y), em_scale); The x and y are heuristic ratio. I think they will be 1.5~1.8.
Because base_advance can be based on linked font, i.e. another font replaced by get_glyph_index_linked(), the glyph might be a proportional typeface. In that case, "(base_advance + 63) >> 6 != avg_advance" is very loose restriction. A narrow character may be treated as a Full-width character in that case.
Regards, Akihiro Sagawa
Yes. It's absolutely correct.
I thought about this possibility, but I wanted to leave it as a different issue. So I wrote 'slightly logic change'. Of course, it is my fault that I did not make any further comments.
To deal with this, I need to create a real test case and investigate the behavior of the native Windows.
I have a variety of other issues besides this. In the process of resolving an issue, another issue is revealed. So when I deal with them together, patch issues of various topics are mixed up. Then Huw's patch review becomes difficult, and my patch process will also take a long time.
This patch is still lacking, but it is slightly better than it is now.
Thank you.
Byeongsik Jeon wrote:
Akihiro Sagawa wrote:
In my opinion, why don't we test the following condition for fixed_pitch_full? fixed_pitch_full = avg_advance > 0 && (base_advance + 63) >> 6 >= pFT_MulFix(MulDiv(incoming_font->ntmAvgWidth, x, y), em_scale); The x and y are heuristic ratio. I think they will be 1.5~1.8.
Because base_advance can be based on linked font, i.e. another font replaced by get_glyph_index_linked(), the glyph might be a proportional typeface. In that case, "(base_advance + 63) >> 6 != avg_advance" is very loose restriction. A narrow character may be treated as a Full-width character in that case.
Regards, Akihiro Sagawa
Yes. It's absolutely correct.
I looked at the behavior on Windows with a test font that manipulated the OS/2 table(Panose, AvgCharWidth). It didn't work as I thought. IMO, Windows seems to be doing something related to the following document. Surprisingly, Wine already has the scripts needed for conversion, so I can work easily.
https://www.unicode.org/Public/11.0/udd/EasasianWidth.txt
This is a temporary patch. Please review if possible. It is also good to post more improved patch directly.
Thank you.
On Sat, 2 Feb 2019 05:11:58 +0900, Byeongsik Jeon wrote:
I looked at the behavior on Windows with a test font that manipulated the OS/2 table(Panose, AvgCharWidth). It didn't work as I thought. IMO, Windows seems to be doing something related to the following document. Surprisingly, Wine already has the scripts needed for conversion, so I can work easily.
https://www.unicode.org/Public/11.0/udd/EasasianWidth.txt
This is a temporary patch. Please review if possible. It is also good to post more improved patch directly.
I agree with that Windows uses some sort of fullwidth character table, but I'm not sure about EasAsianWidth.txt. At least, there are two issues, 1. We can't get an Unicode code point when GetGlyphOutline function called with GGO_GLYPH_INDEX flag. 2. There are ambiguous width characters. For instance, is U+20AC a fullwidth character or a halfwidth one?
By the way, when I tested with Gulim on Windows, I got 19 px as gmCellIncX value at 19 ppem for U+C640 (see attachment for details). Gulium shares the embedded bitmap with GuliumChe. So, why don't you fix up base_advance when using embedded bitmaps? By doing so, the advance will be 19 (not 18) before calculating fixed_pitch_full. And, we don't have to update the formula.
Akihiro Sagawa
I'm late. I'm sorry. Because of my personal situation, I had to be in a network-disconnected environment for the last few days.
Akihiro Sagawa wrote:
On Sat, 2 Feb 2019 05:11:58 +0900, Byeongsik Jeon wrote:
I looked at the behavior on Windows with a test font that manipulated the OS/2 table(Panose, AvgCharWidth). It didn't work as I thought. IMO, Windows seems to be doing something related to the following document. Surprisingly, Wine already has the scripts needed for conversion, so I can work easily.
https://www.unicode.org/Public/11.0/udd/EasasianWidth.txt
This is a temporary patch. Please review if possible. It is also good to post more improved patch directly.
I agree with that Windows uses some sort of fullwidth character table, but I'm not sure about EasAsianWidth.txt. At least, there are two issues,
- We can't get an Unicode code point when GetGlyphOutline function
called with GGO_GLYPH_INDEX flag.
It's a good point. This is the similar case as Tategaki. ---- In get_glyph_outline(),
TODO: Window also turns off tategaki for glyphs passed in by index if their unicode code points fall outside of the range that is rotated. ---- I assume the solution will be similar.
- There are ambiguous width characters. For instance, is U+20AC a
fullwidth character or a halfwidth one?
In my test, Type 'A', 'F' and 'W' of EastAsianWidth.txt were full-length characters. However, I have not yet examined the entire code area.
This may depend on Windows locale. Also, Unicode versions that are supported by each version of Windows may differ.
By the way, when I tested with Gulim on Windows, I got 19 px as gmCellIncX value at 19 ppem for U+C640 (see attachment for details). Gulium shares the embedded bitmap with GuliumChe. So, why don't you fix up base_advance when using embedded bitmaps? By doing so, the advance will be 19 (not 18) before calculating fixed_pitch_full. And, we don't have to update the formula.
This is not applicable. This is a special case for the 'ttc' font file.
Because Windows built-in fonts are well-adjusted fonts, it is difficult to figure out exactly what Windows is doing. I think we can test this with fonts that manipulate the AveCharWidth value.
Because of other issues, it would have to be delayed later to investigate this.
Thank you.
On Wed, Jan 30, 2019 at 02:12:35AM +0900, Byeongsik Jeon wrote:
Signed-off-by: Byeongsik Jeon [email protected]
Each helper function can be further refactored, but at this point, it has kept the existing code. In my personal git branch, I am modifying other issues, and these structural change seems appropriate.
I will send patches that actually fix metric problems separately.
dlls/gdi32/freetype.c | 234 ++++++++++++++++++++++-------------------- 1 file changed, 125 insertions(+), 109 deletions(-)
diff --git a/dlls/gdi32/freetype.c b/dlls/gdi32/freetype.c index c38108eece..a522bcaba6 100644 --- a/dlls/gdi32/freetype.c +++ b/dlls/gdi32/freetype.c @@ -6588,6 +6588,129 @@ static inline FT_Vector normalize_vector(FT_Vector *vec) return out; }
This is a good opportunity to tidy up some of the code while we're doing this. I'll outline a few things below.
+static BOOL get_transform_matrix( GdiFont *font, BOOL tategaki, const MAT2 *lpmat,
"get_transform_matrices" since it gets more than one.
Let's try to move away from having the word "tategaki" in the code, what this really means is "vertical", so let's start by renaming this param to that.
Let's rename "lpmat" to "user_transform"
FT_Matrix *transMat, FT_Matrix *transMatTategaki,
FT_Matrix *transMatUnrotated )
Let's use a FT_Matrix matrices[3] array for these. It'll obviously need changes to the calling function too. We'd define an enum (matrix_hori, matrix_vert, matrix_unrotated) to index into the array.
+{
- double widthRatio;
width_ratio
- BOOL needsTransform = FALSE;
needs_transform
- /* Scaling factor */
- if (font->aveWidth)
- {
TEXTMETRICW tm;
get_text_metrics( font, &tm );
widthRatio = (double)font->aveWidth;
widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
- }
- else
widthRatio = font->scale_y;
- /* Scaling transform */
- if (widthRatio != 1.0 || font->scale_y != 1.0)
- {
FT_Matrix scaleMat;
scaleMat.xx = FT_FixedFromFloat( widthRatio );
scaleMat.xy = 0;
scaleMat.yx = 0;
scaleMat.yy = FT_FixedFromFloat( font->scale_y );
pFT_Matrix_Multiply( &scaleMat, transMat );
needsTransform = TRUE;
- }
- /* Slant transform */
- if (font->fake_italic)
- {
FT_Matrix slantMat;
slantMat.xx = (1 << 16);
slantMat.xy = (1 << 16) >> 2;
slantMat.yx = 0;
slantMat.yy = (1 << 16);
pFT_Matrix_Multiply( &slantMat, transMat );
needsTransform = TRUE;
- }
- /* Rotation transform */
- *transMatUnrotated = *transMat;
- *transMatTategaki = *transMat;
- if (font->orientation || tategaki)
- {
FT_Matrix rotationMat;
FT_Matrix taterotationMat;
FT_Vector vecAngle;
FT_Angle angle;
double orient = font->orientation / 10.0;
double tate_orient = 0.f;
"vert_orient" which should be initialed to orient so we don't need the else block below.
if (tategaki)
tate_orient = ((font->orientation + 900) % 3600) / 10.0;
else
tate_orient = font->orientation / 10.0;
if (orient)
{
angle = FT_FixedFromFloat( orient );
pFT_Vector_Unit( &vecAngle, angle );
rotationMat.xx = vecAngle.x;
rotationMat.xy = -vecAngle.y;
rotationMat.yx = -rotationMat.xy;
rotationMat.yy = rotationMat.xx;
pFT_Matrix_Multiply( &rotationMat, transMat );
}
if (tate_orient)
{
angle = FT_FixedFromFloat( tate_orient );
pFT_Vector_Unit( &vecAngle, angle );
taterotationMat.xx = vecAngle.x;
taterotationMat.xy = -vecAngle.y;
taterotationMat.yx = -taterotationMat.xy;
taterotationMat.yy = taterotationMat.xx;
pFT_Matrix_Multiply( &taterotationMat, transMatTategaki );
}
needsTransform = TRUE;
- }
- /* World transform */
- if (!is_identity_FMAT2( &font->font_desc.matrix ))
- {
FT_Matrix worldMat;
worldMat.xx = FT_FixedFromFloat( font->font_desc.matrix.eM11 );
worldMat.xy = -FT_FixedFromFloat( font->font_desc.matrix.eM21 );
worldMat.yx = -FT_FixedFromFloat( font->font_desc.matrix.eM12 );
worldMat.yy = FT_FixedFromFloat( font->font_desc.matrix.eM22 );
pFT_Matrix_Multiply( &worldMat, transMat );
pFT_Matrix_Multiply( &worldMat, transMatUnrotated );
pFT_Matrix_Multiply( &worldMat, transMatTategaki );
Using a matrices array, the above three lines can be written as a loop.
needsTransform = TRUE;
- }
- /* Extra transformation specified by caller */
- if (!is_identity_MAT2( lpmat ))
- {
FT_Matrix extraMat;
extraMat.xx = FT_FixedFromFIXED( lpmat->eM11 );
extraMat.xy = FT_FixedFromFIXED( lpmat->eM21 );
extraMat.yx = FT_FixedFromFIXED( lpmat->eM12 );
extraMat.yy = FT_FixedFromFIXED( lpmat->eM22 );
pFT_Matrix_Multiply( &extraMat, transMat );
pFT_Matrix_Multiply( &extraMat, transMatUnrotated );
pFT_Matrix_Multiply( &extraMat, transMatTategaki );
As can these.
needsTransform = TRUE;
- }
- return needsTransform;
+}
static BOOL get_bold_glyph_outline(FT_GlyphSlot glyph, LONG ppem, FT_Glyph_Metrics *metrics) { FT_Error err; @@ -6946,9 +7069,7 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, 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 = get_load_flags(format);
- double widthRatio = 1.0; FT_Matrix transMat = identityMat; FT_Matrix transMatUnrotated; FT_Matrix transMatTategaki;
@@ -7008,113 +7129,8 @@ static DWORD get_glyph_outline(GdiFont *incoming_font, UINT glyph, UINT format, if (!font->gm[original_index / GM_BLOCK_SIZE]) font->gm[original_index / GM_BLOCK_SIZE] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, sizeof(GM) * GM_BLOCK_SIZE);
- /* Scaling factor */
- if (font->aveWidth)
- {
TEXTMETRICW tm;
get_text_metrics(font, &tm);
widthRatio = (double)font->aveWidth;
widthRatio /= (double)font->potm->otmTextMetrics.tmAveCharWidth;
- }
- else
widthRatio = font->scale_y;
- /* Scaling transform */
- if (widthRatio != 1.0 || font->scale_y != 1.0)
- {
FT_Matrix scaleMat;
scaleMat.xx = FT_FixedFromFloat(widthRatio);
scaleMat.xy = 0;
scaleMat.yx = 0;
scaleMat.yy = FT_FixedFromFloat(font->scale_y);
pFT_Matrix_Multiply(&scaleMat, &transMat);
needsTransform = TRUE;
- }
- /* Slant transform */
- if (font->fake_italic) {
FT_Matrix slantMat;
slantMat.xx = (1 << 16);
slantMat.xy = ((1 << 16) >> 2);
slantMat.yx = 0;
slantMat.yy = (1 << 16);
pFT_Matrix_Multiply(&slantMat, &transMat);
needsTransform = TRUE;
- }
- /* Rotation transform */
- transMatUnrotated = transMat;
- transMatTategaki = transMat;
- if(font->orientation || tategaki) {
FT_Matrix rotationMat;
FT_Matrix taterotationMat;
FT_Vector vecAngle;
double orient = font->orientation / 10.0;
double tate_orient = 0.f;
if (tategaki)
tate_orient = ((font->orientation+900)%3600)/10.0;
else
tate_orient = font->orientation/10.0;
if (orient)
{
angle = FT_FixedFromFloat(orient);
pFT_Vector_Unit(&vecAngle, angle);
rotationMat.xx = vecAngle.x;
rotationMat.xy = -vecAngle.y;
rotationMat.yx = -rotationMat.xy;
rotationMat.yy = rotationMat.xx;
pFT_Matrix_Multiply(&rotationMat, &transMat);
}
if (tate_orient)
{
angle = FT_FixedFromFloat(tate_orient);
pFT_Vector_Unit(&vecAngle, angle);
taterotationMat.xx = vecAngle.x;
taterotationMat.xy = -vecAngle.y;
taterotationMat.yx = -taterotationMat.xy;
taterotationMat.yy = taterotationMat.xx;
pFT_Matrix_Multiply(&taterotationMat, &transMatTategaki);
}
needsTransform = TRUE;
- }
- /* World transform */
- if (!is_identity_FMAT2(&font->font_desc.matrix))
- {
FT_Matrix worldMat;
worldMat.xx = FT_FixedFromFloat(font->font_desc.matrix.eM11);
worldMat.xy = -FT_FixedFromFloat(font->font_desc.matrix.eM21);
worldMat.yx = -FT_FixedFromFloat(font->font_desc.matrix.eM12);
worldMat.yy = FT_FixedFromFloat(font->font_desc.matrix.eM22);
pFT_Matrix_Multiply(&worldMat, &transMat);
pFT_Matrix_Multiply(&worldMat, &transMatUnrotated);
pFT_Matrix_Multiply(&worldMat, &transMatTategaki);
needsTransform = TRUE;
- }
- /* Extra transformation specified by caller */
- if (!is_identity_MAT2(lpmat))
- {
FT_Matrix extraMat;
extraMat.xx = FT_FixedFromFIXED(lpmat->eM11);
extraMat.xy = FT_FixedFromFIXED(lpmat->eM21);
extraMat.yx = FT_FixedFromFIXED(lpmat->eM12);
extraMat.yy = FT_FixedFromFIXED(lpmat->eM22);
pFT_Matrix_Multiply(&extraMat, &transMat);
pFT_Matrix_Multiply(&extraMat, &transMatUnrotated);
pFT_Matrix_Multiply(&extraMat, &transMatTategaki);
needsTransform = TRUE;
- }
needsTransform = get_transform_matrix( font, tategaki, lpmat,
&transMat, &transMatTategaki, &transMatUnrotated );
vertical_metrics = (tategaki && FT_HAS_VERTICAL(ft_face)); /* there is a freetype bug where vertical metrics are only
-- 2.20.1