From 664a648948e576fb5ad0cbc62d3da90a66e17e14 Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Tue, 17 May 2011 14:04:41 +0000 Subject: use hires metrics when rotated (or subpixel is requested) git-svn-id: http://skia.googlecode.com/svn/trunk/src@1342 2bbb7eff-a529-9590-31e7-b0007b416f81 --- ports/SkFontHost_win.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/ports/SkFontHost_win.cpp b/ports/SkFontHost_win.cpp index e274a988..f406f767 100755 --- a/ports/SkFontHost_win.cpp +++ b/ports/SkFontHost_win.cpp @@ -272,6 +272,10 @@ private: HFONT fFont; SCRIPT_CACHE fSC; int fGlyphCount; + + HFONT fHiResFont; + MAT2 fMat22Identity; + SkMatrix fHiResMatrix; }; static float mul2float(SkScalar a, SkScalar b) { @@ -284,6 +288,16 @@ static FIXED float2FIXED(float x) { static SkMutex gFTMutex; +#define HIRES_TEXTSIZE 2048 +#define HIRES_SHIFT 11 +static inline SkFixed HiResToFixed(int value) { + return value << (16 - HIRES_SHIFT); +} + +static bool needHiResMetrics(const SkScalar mat[2][2]) { + return mat[1][0] || mat[0][1]; +} + SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0) , fGlyphCount(-1) { @@ -304,6 +318,7 @@ SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) fMat22.eM22 = float2FIXED(-fXform.eM22); fDDC = ::CreateCompatibleDC(NULL); + SetGraphicsMode(fDDC, GM_ADVANCED); SetBkMode(fDDC, TRANSPARENT); // Scaling by the DPI is inconsistent with how Skia draws elsewhere @@ -312,6 +327,21 @@ SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) GetLogFontByID(fRec.fFontID, &lf); lf.lfHeight = -gCanonicalTextSize; fFont = CreateFontIndirect(&lf); + + // if we're rotated, or want fractional widths, create a hires font + fHiResFont = 0; + if (needHiResMetrics(fRec.fPost2x2) || (fRec.fFlags & kSubpixelPositioning_Flag)) { + lf.lfHeight = -HIRES_TEXTSIZE; + fHiResFont = CreateFontIndirect(&lf); + + fMat22Identity.eM11 = fMat22Identity.eM22 = SkFixedToFIXED(SK_Fixed1); + fMat22Identity.eM12 = fMat22Identity.eM21 = SkFixedToFIXED(0); + + // construct a matrix to go from HIRES logical units to our device units + fRec.getSingleMatrix(&fHiResMatrix); + SkScalar scale = SkScalarInvert(SkIntToScalar(HIRES_TEXTSIZE)); + fHiResMatrix.preScale(scale, scale); + } fSavefont = (HFONT)SelectObject(fDDC, fFont); } @@ -323,6 +353,9 @@ SkScalerContext_Windows::~SkScalerContext_Windows() { if (fFont) { ::DeleteObject(fFont); } + if (fHiResFont) { + ::DeleteObject(fHiResFont); + } if (fSC) { ::ScriptFreeCache(&fSC); } @@ -369,7 +402,7 @@ void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) { SkASSERT(fDDC); GLYPHMETRICS gm; - memset(&gm, 0, sizeof(gm)); + sk_bzero(&gm, sizeof(gm)); glyph->fRsbDelta = 0; glyph->fLsbDelta = 0; @@ -400,6 +433,19 @@ void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) { glyph->fTop -= 1; glyph->fLeft -= 1; } + + if (fHiResFont) { + SelectObject(fDDC, fHiResFont); + sk_bzero(&gm, sizeof(gm)); + ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22Identity); + if (GDI_ERROR != ret) { + SkPoint advance; + fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance); + glyph->fAdvanceX = SkScalarToFixed(advance.fX); + glyph->fAdvanceY = SkScalarToFixed(advance.fY); + } + SelectObject(fDDC, fFont); + } } else { glyph->fWidth = 0; } @@ -479,9 +525,9 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { size_t size = glyph.fHeight * srcRB; memset(bits, 0xFF, size); + SetGraphicsMode(dc, GM_ADVANCED); SetBkMode(dc, TRANSPARENT); SetTextAlign(dc, TA_LEFT | TA_BASELINE); - SetGraphicsMode(dc, GM_ADVANCED); XFORM xform = fXform; xform.eDx = (float)-glyph.fLeft; -- cgit v1.2.3