https://git.reactos.org/?p=reactos.git;a=commitdiff;h=e316d612152ae5953eb73f...
commit e316d612152ae5953eb73fbb4f7b2a4463872ab1 Author: Katayama Hirofumi MZ katayama.hirofumi.mz@gmail.com AuthorDate: Sat Dec 3 13:03:28 2022 +0900 Commit: GitHub noreply@github.com CommitDate: Sat Dec 3 13:03:28 2022 +0900
[NTGDI][FREETYPE] lfEscapement for TextOut (#4920)
Rotation and shearing transformation of font/text is now available. Retrial of PR #1207. - Rename ftGdiGetTextWidth as IntGetTextDisposition and add a Y parameter. - Apply lfEscapement values (by multiplying matrices). - Add IntEngFillPolygon and IntEngFillBox helper functions. CORE-11848 --- win32ss/gdi/ntgdi/freetype.c | 489 +++++++++++++++++++++++++++---------------- 1 file changed, 308 insertions(+), 181 deletions(-)
diff --git a/win32ss/gdi/ntgdi/freetype.c b/win32ss/gdi/ntgdi/freetype.c index fa60795b70c..9c901b10fe5 100644 --- a/win32ss/gdi/ntgdi/freetype.c +++ b/win32ss/gdi/ntgdi/freetype.c @@ -48,6 +48,7 @@ extern const MATRIX gmxWorldToDeviceDefault; extern const MATRIX gmxWorldToPageDefault; static const FT_Matrix identityMat = {(1 << 16), 0, 0, (1 << 16)}; +static POINTL PointZero = { 0, 0 };
/* HACK!! Fix XFORMOBJ then use 1:16 / 16:1 */ #define gmxWorldToDeviceDefault gmxWorldToPageDefault @@ -711,7 +712,7 @@ static LONG IntNormalizeAngle(LONG nTenthsOfDegrees) return nTenthsOfDegrees + 360 * 10; }
-VOID FASTCALL IntEscapeMatrix(FT_Matrix *pmat, LONG lfEscapement) +static VOID FASTCALL IntEscapeMatrix(FT_Matrix *pmat, LONG lfEscapement) { FT_Vector vecAngle; /* Convert the angle in tenths of degrees into degrees as a 16.16 fixed-point value */ @@ -723,7 +724,7 @@ VOID FASTCALL IntEscapeMatrix(FT_Matrix *pmat, LONG lfEscapement) pmat->yy = pmat->xx; }
-VOID FASTCALL +static VOID FASTCALL FtMatrixFromMx(FT_Matrix *pmat, const MATRIX *pmx) { FLOATOBJ ef; @@ -3562,10 +3563,20 @@ IntRequestFontSize(PDC dc, PFONTGDI FontGDI, LONG lfWidth, LONG lfHeight) EmHeight = max(EmHeight, 1); EmHeight = min(EmHeight, USHORT_MAX);
- if (pOS2 && lfWidth > 0) +#if 1 + /* I think this is wrong implementation but its test result is better. */ + if (lfWidth != 0) Width64 = FT_MulDiv(lfWidth, face->units_per_EM, pOS2->xAvgCharWidth) << 6; else Width64 = 0; +#else + /* I think this is correct implementation but it is mismatching to the + other metric functions. The test result is bad. */ + if (lfWidth != 0) + Width64 = (FT_MulDiv(lfWidth, 96 * 5, 72 * 3) << 6); /* ??? FIXME */ + else + Width64 = 0; +#endif
req.type = FT_SIZE_REQUEST_TYPE_NOMINAL; req.width = Width64; @@ -5855,17 +5866,22 @@ ScaleLong(LONG lValue, PFLOATOBJ pef) return lValue; }
-/* Calculate width of the text. */ +/* + * Calculate X and Y disposition of the text. + * NOTE: The disposition can be negative. + */ static BOOL -ftGdiGetTextWidth( - LONGLONG *pTextWidth64, - LPCWSTR String, - INT Count, - PFONT_CACHE_ENTRY Cache, - UINT fuOptions) +IntGetTextDisposition( + OUT LONGLONG *pX64, + OUT LONGLONG *pY64, + IN LPCWSTR String, + IN INT Count, + IN OPTIONAL LPINT Dx, + IN OUT PFONT_CACHE_ENTRY Cache, + IN UINT fuOptions) { - LONGLONG TextLeft64 = 0; - INT glyph_index; + LONGLONG X64 = 0, Y64 = 0; + INT i, glyph_index; FT_BitmapGlyph realglyph; FT_Face face = Cache->Hashed.Face; BOOL use_kerning = FT_HAS_KERNING(face); @@ -5874,9 +5890,9 @@ ftGdiGetTextWidth(
ASSERT_FREETYPE_LOCK_HELD();
- while (Count-- > 0) + for (i = 0; i < Count; ++i) { - glyph_index = get_glyph_index_flagged(face, *String, ETO_GLYPH_INDEX, fuOptions); + glyph_index = get_glyph_index_flagged(face, *String++, ETO_GLYPH_INDEX, fuOptions); Cache->Hashed.GlyphIndex = glyph_index;
realglyph = ftGdiGetRealGlyph(Cache); @@ -5887,22 +5903,123 @@ ftGdiGetTextWidth( if (use_kerning && previous && glyph_index) { FT_Get_Kerning(face, previous, glyph_index, 0, &delta); - TextLeft64 += delta.x; + X64 += delta.x; + Y64 -= delta.y; }
- TextLeft64 += realglyph->root.advance.x >> 10; + if (NULL == Dx) + { + X64 += realglyph->root.advance.x >> 10; + Y64 -= realglyph->root.advance.y >> 10; + } + else if (fuOptions & ETO_PDY) + { + FT_Vector vec = { Dx[2 * i + 0] << 6, Dx[2 * i + 1] << 6 }; + FT_Vector_Transform(&vec, &Cache->Hashed.matTransform); + X64 += vec.x; + Y64 -= vec.y; + } + else + { + FT_Vector vec = { Dx[i] << 6, 0 }; + FT_Vector_Transform(&vec, &Cache->Hashed.matTransform); + X64 += vec.x; + Y64 -= vec.y; + }
if (Cache->Hashed.Aspect.EmuBoldItalic) FT_Done_Glyph((FT_Glyph)realglyph);
previous = glyph_index; - String++; }
- *pTextWidth64 = TextLeft64; + *pX64 = X64; + *pY64 = Y64; return TRUE; }
+VOID APIENTRY +IntEngFillPolygon( + IN OUT PDC dc, + IN POINTL *pPoints, + IN UINT cPoints, + IN BRUSHOBJ *BrushObj) +{ + SURFACE *psurf = dc->dclevel.pSurface; + RECT Rect; + UINT i; + INT x, y; + + ASSERT_DC_PREPARED(dc); + ASSERT(psurf != NULL); + + Rect.left = Rect.right = pPoints[0].x; + Rect.top = Rect.bottom = pPoints[0].y; + for (i = 1; i < cPoints; ++i) + { + x = pPoints[i].x; + if (x < Rect.left) + Rect.left = x; + else if (Rect.right < x) + Rect.right = x; + + y = pPoints[i].y; + if (y < Rect.top) + Rect.top = y; + else if (Rect.bottom < y) + Rect.bottom = y; + } + + IntFillPolygon(dc, dc->dclevel.pSurface, BrushObj, pPoints, cPoints, Rect, &PointZero); +} + +VOID +FASTCALL +IntEngFillBox( + IN OUT PDC dc, + IN INT X, + IN INT Y, + IN INT Width, + IN INT Height, + IN BRUSHOBJ *BrushObj) +{ + RECTL DestRect; + SURFACE *psurf = dc->dclevel.pSurface; + + ASSERT_DC_PREPARED(dc); + ASSERT(psurf != NULL); + + if (Width < 0) + { + X += Width; + Width = -Width; + } + + if (Height < 0) + { + Y += Height; + Height = -Height; + } + + DestRect.left = X; + DestRect.right = X + Width; + DestRect.top = Y; + DestRect.bottom = Y + Height; + + IntEngBitBlt(&psurf->SurfObj, + NULL, + NULL, + (CLIPOBJ *)&dc->co, + NULL, + &DestRect, + NULL, + NULL, + BrushObj, + &PointZero, + ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY)); +} + + BOOL APIENTRY IntExtTextOutW( @@ -5925,13 +6042,12 @@ IntExtTextOutW( PDC_ATTR pdcattr; SURFOBJ *SurfObj, *SourceGlyphSurf; SURFACE *psurf; - INT glyph_index, i, yoff; + INT glyph_index, i; FT_Face face; FT_BitmapGlyph realglyph; - LONGLONG TextLeft64, RealXStart64, TextWidth64; - ULONG TextTop, previous; + LONGLONG X64, Y64, RealXStart64, RealYStart64, DeltaX64, DeltaY64; + ULONG previous; RECTL DestRect, MaskRect; - POINTL SourcePoint, BrushOrigin; HBITMAP HSourceGlyph; SIZEL bitSize; FONTOBJ *FontObj; @@ -5939,14 +6055,12 @@ IntExtTextOutW( PTEXTOBJ TextObj; EXLATEOBJ exloRGB2Dst, exloDst2RGB; POINT Start; - USHORT DxShift; PMATRIX pmxWorldToDevice; - LONG fixAscender, fixDescender; - FLOATOBJ Scale; + FT_Vector delta, vecAscent64, vecDescent64; LOGFONTW *plf; BOOL use_kerning, bResult, DoBreak; - FT_Vector delta; FONT_CACHE_ENTRY Cache; + FT_Matrix mat;
/* Check if String is valid */ if (Count > 0xFFFF || (Count > 0 && String == NULL)) @@ -5974,11 +6088,6 @@ IntExtTextOutW( goto Cleanup; }
- if (lprc && (fuOptions & (ETO_OPAQUE | ETO_CLIPPED))) - { - IntLPtoDP(dc, (POINT *)lprc, 2); - } - pdcattr = dc->pdcattr; if (pdcattr->flTextAlign & TA_UPDATECP) { @@ -5993,53 +6102,37 @@ IntExtTextOutW(
IntLPtoDP(dc, &Start, 1); RealXStart64 = ((LONGLONG)Start.x + dc->ptlDCOrig.x) << 6; - YStart = Start.y + dc->ptlDCOrig.y; + RealYStart64 = ((LONGLONG)Start.y + dc->ptlDCOrig.y) << 6;
- SourcePoint.x = 0; - SourcePoint.y = 0; MaskRect.left = 0; MaskRect.top = 0; - BrushOrigin.x = 0; - BrushOrigin.y = 0;
psurf = dc->dclevel.pSurface; SurfObj = &psurf->SurfObj;
- if (lprc && (fuOptions & ETO_OPAQUE)) - { - RtlCopyMemory(&DestRect, lprc, sizeof(DestRect)); - - DestRect.left += dc->ptlDCOrig.x; - DestRect.top += dc->ptlDCOrig.y; - DestRect.right += dc->ptlDCOrig.x; - DestRect.bottom += dc->ptlDCOrig.y; - - if (dc->fs & (DC_ACCUM_APP|DC_ACCUM_WMGR)) - { - IntUpdateBoundsRect(dc, &DestRect); - } - - if (pdcattr->ulDirty_ & DIRTY_BACKGROUND) - DC_vUpdateBackgroundBrush(dc); - - if (dc->dctype == DCTYPE_DIRECT) - MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom); + if (pdcattr->iGraphicsMode == GM_ADVANCED) + pmxWorldToDevice = DC_pmxWorldToDevice(dc); + else + pmxWorldToDevice = (PMATRIX)&gmxWorldToDeviceDefault;
- IntEngBitBlt(SurfObj, - NULL, - NULL, - (CLIPOBJ *)&dc->co, - NULL, - &DestRect, - &SourcePoint, - &SourcePoint, - &dc->eboBackground.BrushObject, - &BrushOrigin, - ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY)); + if (pdcattr->ulDirty_ & DIRTY_BACKGROUND) + DC_vUpdateBackgroundBrush(dc);
- if (dc->dctype == DCTYPE_DIRECT) - MouseSafetyOnDrawEnd(dc->ppdev); + if (lprc && (fuOptions & (ETO_CLIPPED | ETO_OPAQUE))) + { + IntLPtoDP(dc, (POINT*)lprc, 2); + lprc->left += dc->ptlDCOrig.x; + lprc->top += dc->ptlDCOrig.y; + lprc->right += dc->ptlDCOrig.x; + lprc->bottom += dc->ptlDCOrig.y; + }
+ if (lprc && (fuOptions & ETO_OPAQUE)) + { + IntEngFillBox(dc, + lprc->left, lprc->top, + lprc->right - lprc->left, lprc->bottom - lprc->top, + &dc->eboBackground.BrushObject); fuOptions &= ~ETO_OPAQUE; } else @@ -6083,36 +6176,41 @@ IntExtTextOutW( goto Cleanup; }
- /* NOTE: Don't trust face->size->metrics.ascender and descender values. */ - if (pdcattr->iGraphicsMode == GM_ADVANCED) - { - pmxWorldToDevice = DC_pmxWorldToDevice(dc); - FtMatrixFromMx(&Cache.Hashed.matTransform, pmxWorldToDevice); - FT_Set_Transform(face, &Cache.Hashed.matTransform, NULL); - - fixAscender = ScaleLong(FontGDI->tmAscent, &pmxWorldToDevice->efM22) << 6; - fixDescender = ScaleLong(FontGDI->tmDescent, &pmxWorldToDevice->efM22) << 6; - } + /* Apply lfEscapement */ + if (FT_IS_SCALABLE(face) && plf->lfEscapement != 0) + IntEscapeMatrix(&Cache.Hashed.matTransform, plf->lfEscapement); else - { - pmxWorldToDevice = (PMATRIX)&gmxWorldToDeviceDefault; - FtMatrixFromMx(&Cache.Hashed.matTransform, pmxWorldToDevice); - FT_Set_Transform(face, &Cache.Hashed.matTransform, NULL); - - fixAscender = FontGDI->tmAscent << 6; - fixDescender = FontGDI->tmDescent << 6; - } - - /* - * Process the vertical alignment and determine the yoff. - */ + Cache.Hashed.matTransform = identityMat; + + /* Apply the world transformation */ + FtMatrixFromMx(&mat, pmxWorldToDevice); + FT_Matrix_Multiply(&mat, &Cache.Hashed.matTransform); + FT_Set_Transform(face, &Cache.Hashed.matTransform, NULL); + + /* Calculate the ascent point and the descent point */ + vecAscent64.x = 0; + vecAscent64.y = (FontGDI->tmAscent << 6); + FT_Vector_Transform(&vecAscent64, &Cache.Hashed.matTransform); + vecDescent64.x = 0; + vecDescent64.y = -(FontGDI->tmDescent << 6); + FT_Vector_Transform(&vecDescent64, &Cache.Hashed.matTransform); + + /* Process the vertical alignment and fix the real starting point. */ #define VALIGN_MASK (TA_TOP | TA_BASELINE | TA_BOTTOM) if ((pdcattr->flTextAlign & VALIGN_MASK) == TA_BASELINE) - yoff = 0; + { + NOTHING; + } else if ((pdcattr->flTextAlign & VALIGN_MASK) == TA_BOTTOM) - yoff = -(fixDescender >> 6); + { + RealXStart64 -= vecDescent64.x; + RealYStart64 += vecDescent64.y; + } else /* TA_TOP */ - yoff = fixAscender >> 6; + { + RealXStart64 -= vecAscent64.x; + RealYStart64 += vecAscent64.y; + } #undef VALIGN_MASK
use_kerning = FT_HAS_KERNING(face); @@ -6120,7 +6218,7 @@ IntExtTextOutW( /* Calculate the text width if necessary */ if ((fuOptions & ETO_OPAQUE) || (pdcattr->flTextAlign & (TA_CENTER | TA_RIGHT))) { - if (!ftGdiGetTextWidth(&TextWidth64, String, Count, &Cache, fuOptions)) + if (!IntGetTextDisposition(&DeltaX64, &DeltaY64, String, Count, Dx, &Cache, fuOptions)) { IntUnLockFreeType(); bResult = FALSE; @@ -6129,44 +6227,41 @@ IntExtTextOutW(
/* Adjust the horizontal position by horizontal alignment */ if ((pdcattr->flTextAlign & TA_CENTER) == TA_CENTER) - RealXStart64 -= TextWidth64 / 2; + { + RealXStart64 -= DeltaX64 / 2; + RealYStart64 -= DeltaY64 / 2; + } else if ((pdcattr->flTextAlign & TA_RIGHT) == TA_RIGHT) - RealXStart64 -= TextWidth64; + { + RealXStart64 -= DeltaX64; + RealYStart64 -= DeltaY64; + }
/* Fill background */ if (fuOptions & ETO_OPAQUE) { - DestRect.left = (RealXStart64 + 32) >> 6; - DestRect.right = (RealXStart64 + TextWidth64 + 32) >> 6; - DestRect.top = YStart; - DestRect.bottom = YStart + ((fixAscender + fixDescender) >> 6); - - if (dc->fs & (DC_ACCUM_APP | DC_ACCUM_WMGR)) - IntUpdateBoundsRect(dc, &DestRect); - - if (pdcattr->ulDirty_ & DIRTY_BACKGROUND) - DC_vUpdateBackgroundBrush(dc); - - if (dc->dctype == DCTYPE_DIRECT) + INT X0 = (RealXStart64 + vecAscent64.x + 32) >> 6; + INT Y0 = (RealYStart64 - vecAscent64.y + 32) >> 6; + INT DX = (DeltaX64 >> 6); + if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0) { - MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, - DestRect.right, DestRect.bottom); + INT CY = (vecAscent64.y - vecDescent64.y + 32) >> 6; + IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboBackground.BrushObject); + } + else + { + INT DY = (DeltaY64 >> 6); + INT X1 = ((RealXStart64 + vecDescent64.x + 32) >> 6); + INT Y1 = ((RealYStart64 - vecDescent64.y + 32) >> 6); + POINT Points[4] = + { + { X0, Y0 }, + { X0 + DX, Y0 + DY }, + { X1 + DX, Y1 + DY }, + { X1, Y1 }, + }; + IntEngFillPolygon(dc, Points, 4, &dc->eboBackground.BrushObject); } - - IntEngBitBlt(SurfObj, - NULL, - NULL, - (CLIPOBJ *)&dc->co, - NULL, - &DestRect, - &SourcePoint, - &SourcePoint, - &dc->eboBackground.BrushObject, - &BrushOrigin, - ROP4_FROM_INDEX(R3_OPINDEX_PATCOPY)); - - if (dc->dctype == DCTYPE_DIRECT) - MouseSafetyOnDrawEnd(dc->ppdev); } }
@@ -6182,9 +6277,8 @@ IntExtTextOutW( /* * The main rendering loop. */ - TextLeft64 = RealXStart64; - TextTop = YStart; - DxShift = (fuOptions & ETO_PDY) ? 1 : 0; + X64 = RealXStart64; + Y64 = RealYStart64; previous = 0; DoBreak = FALSE; for (i = 0; i < Count; ++i) @@ -6203,12 +6297,12 @@ IntExtTextOutW( if (use_kerning && previous && glyph_index && NULL == Dx) { FT_Get_Kerning(face, previous, glyph_index, 0, &delta); - TextLeft64 += delta.x; + X64 += delta.x; + Y64 -= delta.y; }
- DPRINT("TextLeft64: %I64d\n", TextLeft64); - DPRINT("TextTop: %lu\n", TextTop); - DPRINT("Advance: %d\n", realglyph->root.advance.x); + DPRINT("X64, Y64: %I64d, %I64d\n", X64, Y64); + DPRINT("Advance: %d, %d\n", realglyph->root.advance.x, realglyph->root.advance.y);
bitSize.cx = realglyph->bitmap.width; bitSize.cy = realglyph->bitmap.rows; @@ -6216,9 +6310,9 @@ IntExtTextOutW( MaskRect.right = realglyph->bitmap.width; MaskRect.bottom = realglyph->bitmap.rows;
- DestRect.left = ((TextLeft64 + 32) >> 6) + realglyph->left; + DestRect.left = ((X64 + 32) >> 6) + realglyph->left; DestRect.right = DestRect.left + bitSize.cx; - DestRect.top = TextTop + yoff - realglyph->top; + DestRect.top = ((Y64 + 32) >> 6) - realglyph->top; DestRect.bottom = DestRect.top + bitSize.cy;
/* Check if the bitmap has any pixels */ @@ -6261,21 +6355,18 @@ IntExtTextOutW( // We do the check '>=' instead of '>' to possibly save an iteration // through this loop, since it's breaking after the drawing is done, // and x is always incremented. - if (DestRect.right >= lprc->right + dc->ptlDCOrig.x) + if (DestRect.right >= lprc->right) { - DestRect.right = lprc->right + dc->ptlDCOrig.x; + DestRect.right = lprc->right; DoBreak = TRUE; }
- if (DestRect.bottom >= lprc->bottom + dc->ptlDCOrig.y) + if (DestRect.bottom >= lprc->bottom) { - DestRect.bottom = lprc->bottom + dc->ptlDCOrig.y; + DestRect.bottom = lprc->bottom; } }
- if (dc->dctype == DCTYPE_DIRECT) - MouseSafetyOnDrawStart(dc->ppdev, DestRect.left, DestRect.top, DestRect.right, DestRect.bottom); - if (!IntEngMaskBlt(SurfObj, SourceGlyphSurf, (CLIPOBJ *)&dc->co, @@ -6284,14 +6375,11 @@ IntExtTextOutW( &DestRect, (PPOINTL)&MaskRect, &dc->eboText.BrushObject, - &BrushOrigin)) + &PointZero)) { DPRINT1("Failed to MaskBlt a glyph!\n"); }
- if (dc->dctype == DCTYPE_DIRECT) - MouseSafetyOnDrawEnd(dc->ppdev) ; - EngUnlockSurface(SourceGlyphSurf); EngDeleteSurface((HSURF)HSourceGlyph); } @@ -6305,27 +6393,26 @@ IntExtTextOutW(
if (NULL == Dx) { - TextLeft64 += realglyph->root.advance.x >> 10; - DPRINT("New TextLeft64: %I64d\n", TextLeft64); + X64 += realglyph->root.advance.x >> 10; + Y64 -= realglyph->root.advance.y >> 10; } - else + else if (fuOptions & ETO_PDY) { - // FIXME this should probably be a matrix transform with TextTop as well. - Scale = pdcattr->mxWorldToDevice.efM11; - if (FLOATOBJ_Equal0(&Scale)) - FLOATOBJ_Set1(&Scale); - - /* do the shift before multiplying to preserve precision */ - FLOATOBJ_MulLong(&Scale, Dx[i<<DxShift] << 6); - TextLeft64 += FLOATOBJ_GetLong(&Scale); - DPRINT("New TextLeft64 2: %I64d\n", TextLeft64); + FT_Vector vec = { Dx[2 * i + 0] << 6, Dx[2 * i + 1] << 6 }; + FT_Vector_Transform(&vec, &Cache.Hashed.matTransform); + X64 += vec.x; + Y64 -= vec.y; } - - if (DxShift) + else { - TextTop -= Dx[2 * i + 1] << 6; + FT_Vector vec = { Dx[i] << 6, 0 }; + FT_Vector_Transform(&vec, &Cache.Hashed.matTransform); + X64 += vec.x; + Y64 -= vec.y; }
+ DPRINT("New X64, New Y64: %I64d, %I64d\n", X64, Y64); + previous = glyph_index;
if (Cache.Hashed.Aspect.EmuBoldItalic) @@ -6340,7 +6427,11 @@ IntExtTextOutW( if (plf->lfUnderline || plf->lfStrikeOut) /* Underline or strike-out? */ { /* Calculate the position and the thickness */ - INT i, underline_position, thickness; + INT underline_position, thickness; + FT_Vector vecA64, vecB64; + + DeltaX64 = X64 - RealXStart64; + DeltaY64 = Y64 - RealYStart64;
if (!face->units_per_EM) { @@ -6359,33 +6450,69 @@ IntExtTextOutW(
if (plf->lfUnderline) /* Draw underline */ { - for (i = -thickness / 2; i < -thickness / 2 + thickness; ++i) + vecA64.x = 0; + vecA64.y = (-underline_position - thickness / 2) << 6; + vecB64.x = 0; + vecB64.y = vecA64.y + (thickness << 6); + FT_Vector_Transform(&vecA64, &Cache.Hashed.matTransform); + FT_Vector_Transform(&vecB64, &Cache.Hashed.matTransform); { - EngLineTo(SurfObj, - (CLIPOBJ *)&dc->co, - &dc->eboText.BrushObject, - (RealXStart64 + 32) >> 6, - TextTop + yoff - underline_position + i, - (TextLeft64 + 32) >> 6, - TextTop + yoff - underline_position + i, - NULL, - ROP2_TO_MIX(R2_COPYPEN)); + INT X0 = (RealXStart64 - vecA64.x + 32) >> 6; + INT Y0 = (RealYStart64 + vecA64.y + 32) >> 6; + INT DX = (DeltaX64 >> 6); + if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0) + { + INT CY = (vecB64.y - vecA64.y + 32) >> 6; + IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboText.BrushObject); + } + else + { + INT DY = (DeltaY64 >> 6); + INT X1 = X0 + ((vecA64.x - vecB64.x + 32) >> 6); + INT Y1 = Y0 + ((vecB64.y - vecA64.y + 32) >> 6); + POINT Points[4] = + { + { X0, Y0 }, + { X0 + DX, Y0 + DY }, + { X1 + DX, Y1 + DY }, + { X1, Y1 }, + }; + IntEngFillPolygon(dc, Points, 4, &dc->eboText.BrushObject); + } } }
if (plf->lfStrikeOut) /* Draw strike-out */ { - for (i = -thickness / 2; i < -thickness / 2 + thickness; ++i) + vecA64.x = 0; + vecA64.y = -(FontGDI->tmAscent << 6) / 3; + vecB64.x = 0; + vecB64.y = vecA64.y + (thickness << 6); + FT_Vector_Transform(&vecA64, &Cache.Hashed.matTransform); + FT_Vector_Transform(&vecB64, &Cache.Hashed.matTransform); { - EngLineTo(SurfObj, - (CLIPOBJ *)&dc->co, - &dc->eboText.BrushObject, - (RealXStart64 + 32) >> 6, - TextTop + yoff - (fixAscender >> 6) / 3 + i, - (TextLeft64 + 32) >> 6, - TextTop + yoff - (fixAscender >> 6) / 3 + i, - NULL, - ROP2_TO_MIX(R2_COPYPEN)); + INT X0 = (RealXStart64 - vecA64.x + 32) >> 6; + INT Y0 = (RealYStart64 + vecA64.y + 32) >> 6; + INT DX = (DeltaX64 >> 6); + if (Cache.Hashed.matTransform.xy == 0 && Cache.Hashed.matTransform.yx == 0) + { + INT CY = (vecB64.y - vecA64.y + 32) >> 6; + IntEngFillBox(dc, X0, Y0, DX, CY, &dc->eboText.BrushObject); + } + else + { + INT DY = (DeltaY64 >> 6); + INT X1 = X0 + ((vecA64.x - vecB64.x + 32) >> 6); + INT Y1 = Y0 + ((vecB64.y - vecA64.y + 32) >> 6); + POINT Points[4] = + { + { X0, Y0 }, + { X0 + DX, Y0 + DY }, + { X1 + DX, Y1 + DY }, + { X1, Y1 }, + }; + IntEngFillPolygon(dc, Points, 4, &dc->eboText.BrushObject); + } } } }