From b652427197ddaac5d35010e1b199bcb431e656b7 Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Tue, 1 Mar 2011 15:18:14 +0000 Subject: remove obsolete generateLineHeight use canonical lfHeight so we can compare different LOGFONTs and map equivalent fonts (except for height) to the same typeface. To do this I add fSize to scale the output from GDI to get from the canonical int textSize to the actual fractional size. git-svn-id: http://skia.googlecode.com/svn/trunk@871 2bbb7eff-a529-9590-31e7-b0007b416f81 --- samplecode/SampleTextBox.cpp | 43 +++++-------- src/ports/SkFontHost_win.cpp | 143 ++++++++++++++++++++----------------------- 2 files changed, 85 insertions(+), 101 deletions(-) diff --git a/samplecode/SampleTextBox.cpp b/samplecode/SampleTextBox.cpp index f8f52a2f71..9511914ab6 100644 --- a/samplecode/SampleTextBox.cpp +++ b/samplecode/SampleTextBox.cpp @@ -20,6 +20,8 @@ #include "SkStream.h" #include "SkKey.h" +extern SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT&); + static const char gText[] = "When in the Course of human events it becomes necessary for one people " "to dissolve the political bands which have connected them with another " @@ -31,7 +33,16 @@ static const char gText[] = class TextBoxView : public SkView { public: TextBoxView() { - fTextSize = SkIntToScalar(32); + LOGFONT lf; + sk_bzero(&lf, sizeof(lf)); + lf.lfHeight = 9; + SkTypeface* tf0 = SkCreateTypefaceFromLOGFONT(lf); + lf.lfHeight = 12; + SkTypeface* tf1 = SkCreateTypefaceFromLOGFONT(lf); + // we assert that different sizes should not affect which face we get + SkASSERT(tf0 == tf1); + tf0->unref(); + tf1->unref(); } protected: @@ -61,36 +72,16 @@ protected: SkPaint paint; paint.setAntiAlias(true); - paint.setTextSize(fTextSize); + tbox.setText(gText, strlen(gText), paint); - tbox.draw(canvas, gText, strlen(gText), paint); - } - - virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y) { - return new Click(this); - } - - virtual bool onClick(Click* click) { - const SkScalar delta = SkIntToScalar(3); - if (click->fState == Click::kUp_State) { - if (click->fCurr.fY < this->height()/2) { - fTextSize += delta; - this->inval(NULL); - return true; - } else { - if (fTextSize > delta) { - fTextSize -= delta; - this->inval(NULL); - return true; - } - } + for (int i = 9; i < 24; i += 2) { + paint.setTextSize(SkIntToScalar(i)); + tbox.draw(canvas); + canvas->translate(0, tbox.getTextHeight() + paint.getFontSpacing()); } - return this->INHERITED::onClick(click); } private: - SkScalar fTextSize; - typedef SkView INHERITED; }; diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index a6d232a82f..17b8571e8d 100644 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -51,6 +51,18 @@ static uint8_t glyphbuf[BUFFERSIZE]; // Give 1MB font cache budget #define FONT_CACHE_MEMORY_BUDGET (1024 * 1024) +/** + * Since LOGFONT wants its textsize as an int, and we support fractional sizes, + * and since we have a cache of LOGFONTs for our tyepfaces, we always set the + * lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the + * actual requested size. + */ +static const int gCanonicalTextSize = 64; + +static void make_canonical(LOGFONT* lf) { + lf->lfHeight = -gCanonicalTextSize; +} + static inline FIXED SkFixedToFIXED(SkFixed x) { return *(FIXED*)(&x); } @@ -85,6 +97,8 @@ public: SkTypeface(style, sk_atomic_inc(&gCurrId)+1), // 0 id is reserved so add 1 fLogFont(logFont) { + make_canonical(&fLogFont); + SkAutoMutexAcquire am(gMutex); fNext = gHead; gHead = this; @@ -120,8 +134,11 @@ public: static LogFontTypeface* FindByLogFont(const LOGFONT& lf) { + LOGFONT canonical = lf; + make_canonical(&canonical); + LogFontTypeface* curr = gHead; - while (curr && memcmp(&curr->fLogFont, &lf, sizeof(LOGFONT))) { + while (curr && memcmp(&curr->fLogFont, &canonical, sizeof(LOGFONT))) { curr = curr->fNext; } return curr; @@ -155,15 +172,14 @@ static const LOGFONT& get_default_font() { } SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& lf) { - LogFontTypeface* ptypeface = LogFontTypeface::FindByLogFont(lf); if (NULL == ptypeface) { SkTypeface::Style style = GetFontStyle(lf); ptypeface = new LogFontTypeface(style, lf); } else { - ptypeface->ref(); - } + ptypeface->ref(); + } return ptypeface; } @@ -186,51 +202,48 @@ protected: virtual void generateMetrics(SkGlyph* glyph); virtual void generateImage(const SkGlyph& glyph); virtual void generatePath(const SkGlyph& glyph, SkPath* path); - virtual void generateLineHeight(SkPoint* ascent, SkPoint* descent); virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY); //virtual SkDeviceContext getDC() {return ddc;} private: - LOGFONT lf; - MAT2 mat22; - HDC ddc; - HFONT savefont; - HFONT font; - SCRIPT_CACHE sc; + SkScalar fScale; // to get from canonical size to real size + MAT2 fMat22; + HDC fDDC; + HFONT fSavefont; + HFONT fFont; + SCRIPT_CACHE fSC; }; SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) - : SkScalerContext(desc), ddc(0), font(0), savefont(0), sc(0) { + : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0) { SkAutoMutexAcquire ac(gFTMutex); - lf = LogFontTypeface::FindById(fRec.fFontID)->logFont(); - - mat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]); - mat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[0][1]); - mat22.eM21 = SkScalarToFIXED(fRec.fPost2x2[1][0]); - mat22.eM22 = SkScalarToFIXED(-fRec.fPost2x2[1][1]); + fScale = fRec.fTextSize / gCanonicalTextSize; + fMat22.eM11 = SkScalarToFIXED(SkScalarMul(fScale, fRec.fPost2x2[0][0])); + fMat22.eM12 = SkScalarToFIXED(SkScalarMul(fScale, -fRec.fPost2x2[0][1])); + fMat22.eM21 = SkScalarToFIXED(SkScalarMul(fScale, fRec.fPost2x2[1][0])); + fMat22.eM22 = SkScalarToFIXED(SkScalarMul(fScale, -fRec.fPost2x2[1][1])); - ddc = ::CreateCompatibleDC(NULL); - SetBkMode(ddc, TRANSPARENT); + fDDC = ::CreateCompatibleDC(NULL); + SetBkMode(fDDC, TRANSPARENT); // Scaling by the DPI is inconsistent with how Skia draws elsewhere //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72); - SkScalar height = -fRec.fTextSize; - lf.lfHeight = SkScalarRound(height); - font = CreateFontIndirect(&lf); - savefont = (HFONT)SelectObject(ddc, font); + LOGFONT lf = LogFontTypeface::FindById(fRec.fFontID)->logFont(); + lf.lfHeight = -gCanonicalTextSize; + fFont = CreateFontIndirect(&lf); + fSavefont = (HFONT)SelectObject(fDDC, fFont); } SkScalerContext_Windows::~SkScalerContext_Windows() { - if (ddc) { - ::SelectObject(ddc, savefont); - ::DeleteDC(ddc); - ddc = NULL; + if (fDDC) { + ::SelectObject(fDDC, fSavefont); + ::DeleteDC(fDDC); } - if (font) { - ::DeleteObject(font); + if (fFont) { + ::DeleteObject(fFont); } - if (sc) { - ::ScriptFreeCache(&sc); + if (fSC) { + ::ScriptFreeCache(&fSC); } } @@ -245,7 +258,7 @@ uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) { // TODO(ctguil): Support characters that generate more than one glyph. if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) { // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0. - SkAssertResult(GetGlyphIndicesW(ddc, c, 1, &index, 0)); + SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0)); } else { // Use uniscribe to detemine glyph index for non-BMP characters. // Need to add extra item to SCRIPT_ITEM to work around a bug in older @@ -259,7 +272,7 @@ uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) { SCRIPT_VISATTR vsa; int glyphs; SkAssertResult(SUCCEEDED(ScriptShape( - ddc, &sc, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs))); + fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs))); } return index; } @@ -270,7 +283,7 @@ void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) { void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) { - SkASSERT(ddc); + SkASSERT(fDDC); GLYPHMETRICS gm; memset(&gm, 0, sizeof(gm)); @@ -280,7 +293,7 @@ void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) { // Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller // BlackBlox; we need the bigger one in case we need the image. fAdvance is the same. - uint32_t ret = GetGlyphOutlineW(ddc, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &mat22); + uint32_t ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22); if (GDI_ERROR != ret) { if (ret == 0) { @@ -310,31 +323,31 @@ void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPa if (!(mx || my)) return; - SkASSERT(ddc); + SkASSERT(fDDC); OUTLINETEXTMETRIC otm; - uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm); + uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm); if (sizeof(otm) != ret) { return; } if (mx) { - mx->fTop = -SkIntToScalar(otm.otmTextMetrics.tmAscent); // Actually a long. - mx->fAscent = -SkIntToScalar(otm.otmAscent); - mx->fDescent = -SkIntToScalar(otm.otmDescent); - mx->fBottom = SkIntToScalar(otm.otmTextMetrics.tmDescent); // Long - mx->fLeading = SkIntToScalar(otm.otmTextMetrics.tmInternalLeading - + otm.otmTextMetrics.tmExternalLeading); // Long + mx->fTop = -fScale * otm.otmTextMetrics.tmAscent; + mx->fAscent = -fScale * otm.otmAscent; + mx->fDescent = -fScale * otm.otmDescent; + mx->fBottom = fScale * otm.otmTextMetrics.tmDescent; + mx->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading + + otm.otmTextMetrics.tmExternalLeading); } if (my) { - my->fTop = -SkIntToScalar(otm.otmTextMetrics.tmAscent); // Actually a long. - my->fAscent = -SkIntToScalar(otm.otmAscent); - my->fDescent = -SkIntToScalar(otm.otmDescent); - my->fBottom = SkIntToScalar(otm.otmTextMetrics.tmDescent); // Long - my->fLeading = SkIntToScalar(otm.otmTextMetrics.tmInternalLeading - + otm.otmTextMetrics.tmExternalLeading); // Long + my->fTop = -fScale * otm.otmTextMetrics.tmAscent; + my->fAscent = -fScale * otm.otmAscent; + my->fDescent = -fScale * otm.otmDescent; + my->fBottom = fScale * otm.otmTextMetrics.tmDescent; + my->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading + + otm.otmTextMetrics.tmExternalLeading); } } @@ -342,7 +355,7 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { SkAutoMutexAcquire ac(gFTMutex); - SkASSERT(ddc); + SkASSERT(fDDC); GLYPHMETRICS gm; memset(&gm, 0, sizeof(gm)); @@ -354,11 +367,11 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) { #endif uint32_t bytecount = 0; - uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &mat22); + uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22); if (GDI_ERROR != total_size && total_size > 0) { uint8_t *pBuff = new uint8_t[total_size]; if (NULL != pBuff) { - total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, total_size, pBuff, &mat22); + total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, total_size, pBuff, &fMat22); SkASSERT(total_size != GDI_ERROR); @@ -402,7 +415,7 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { SkAutoMutexAcquire ac(gFTMutex); SkASSERT(&glyph && path); - SkASSERT(ddc); + SkASSERT(fDDC); path->reset(); @@ -413,7 +426,7 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { #endif GLYPHMETRICS gm; - uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &mat22); + uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22); if (GDI_ERROR != total_size) { @@ -464,26 +477,6 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) { //OutputDebugString(buf); } - -// Note: not sure this is the correct implementation -void SkScalerContext_Windows::generateLineHeight(SkPoint* ascent, SkPoint* descent) { - - SkASSERT(ddc); - - OUTLINETEXTMETRIC otm; - - uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm); - - if (sizeof(otm) == ret) { - if (ascent) - ascent->iset(0, otm.otmAscent); - if (descent) - descent->iset(0, otm.otmDescent); - } - - return; -} - void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) { SkASSERT(!"SkFontHost::Serialize unimplemented"); } -- cgit v1.2.3