remove obsolete generateLineHeight
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 1 Mar 2011 15:18:14 +0000 (15:18 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 1 Mar 2011 15:18:14 +0000 (15:18 +0000)
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
src/ports/SkFontHost_win.cpp

index f8f52a2..9511914 100644 (file)
@@ -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;
 };
 
index a6d232a..17b8571 100644 (file)
@@ -51,6 +51,18 @@ static uint8_t glyphbuf[BUFFERSIZE];
 // Give 1MB font cache budget\r
 #define FONT_CACHE_MEMORY_BUDGET    (1024 * 1024)\r
 \r
+/**\r
+ *     Since LOGFONT wants its textsize as an int, and we support fractional sizes,\r
+ *  and since we have a cache of LOGFONTs for our tyepfaces, we always set the\r
+ *  lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the\r
+ *  actual requested size.\r
+ */\r
+static const int gCanonicalTextSize = 64;\r
+\r
+static void make_canonical(LOGFONT* lf) {\r
+       lf->lfHeight = -gCanonicalTextSize;\r
+}\r
+\r
 static inline FIXED SkFixedToFIXED(SkFixed x) {\r
     return *(FIXED*)(&x);\r
 }\r
@@ -85,6 +97,8 @@ public:
       SkTypeface(style, sk_atomic_inc(&gCurrId)+1), // 0 id is reserved so add 1\r
       fLogFont(logFont)\r
     {\r
+               make_canonical(&fLogFont);\r
+\r
         SkAutoMutexAcquire am(gMutex);\r
         fNext = gHead;\r
         gHead = this;\r
@@ -120,8 +134,11 @@ public:
 \r
     static LogFontTypeface* FindByLogFont(const LOGFONT& lf)\r
     {\r
+               LOGFONT canonical = lf;\r
+               make_canonical(&canonical);\r
+\r
         LogFontTypeface* curr = gHead;\r
-        while (curr && memcmp(&curr->fLogFont, &lf, sizeof(LOGFONT))) {\r
+        while (curr && memcmp(&curr->fLogFont, &canonical, sizeof(LOGFONT))) {\r
             curr = curr->fNext;\r
         }\r
         return curr;\r
@@ -155,15 +172,14 @@ static const LOGFONT& get_default_font() {
 }\r
 \r
 SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& lf) {\r
-\r
     LogFontTypeface* ptypeface = LogFontTypeface::FindByLogFont(lf);\r
 \r
     if (NULL == ptypeface) {\r
         SkTypeface::Style style = GetFontStyle(lf);\r
         ptypeface = new LogFontTypeface(style, lf);\r
     } else {\r
-        ptypeface->ref();\r
-    }\r
+           ptypeface->ref();\r
+       }\r
     return ptypeface;\r
 }\r
 \r
@@ -186,51 +202,48 @@ protected:
     virtual void generateMetrics(SkGlyph* glyph);\r
     virtual void generateImage(const SkGlyph& glyph);\r
     virtual void generatePath(const SkGlyph& glyph, SkPath* path);\r
-    virtual void generateLineHeight(SkPoint* ascent, SkPoint* descent);\r
     virtual void generateFontMetrics(SkPaint::FontMetrics* mX, SkPaint::FontMetrics* mY);\r
     //virtual SkDeviceContext getDC() {return ddc;}\r
 private:\r
-    LOGFONT      lf;\r
-    MAT2         mat22;\r
-    HDC          ddc;\r
-    HFONT        savefont;\r
-    HFONT        font;\r
-    SCRIPT_CACHE sc;\r
+       SkScalar         fScale;        // to get from canonical size to real size\r
+    MAT2         fMat22;\r
+    HDC          fDDC;\r
+    HFONT        fSavefont;\r
+    HFONT        fFont;\r
+    SCRIPT_CACHE fSC;\r
 };\r
 \r
 SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc)\r
-        : SkScalerContext(desc), ddc(0), font(0), savefont(0), sc(0) {\r
+        : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0) {\r
     SkAutoMutexAcquire  ac(gFTMutex);\r
 \r
-    lf = LogFontTypeface::FindById(fRec.fFontID)->logFont();\r
-\r
-    mat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);\r
-    mat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[0][1]);\r
-    mat22.eM21 = SkScalarToFIXED(fRec.fPost2x2[1][0]);\r
-    mat22.eM22 = SkScalarToFIXED(-fRec.fPost2x2[1][1]);\r
+       fScale = fRec.fTextSize / gCanonicalTextSize;\r
+    fMat22.eM11 = SkScalarToFIXED(SkScalarMul(fScale, fRec.fPost2x2[0][0]));\r
+    fMat22.eM12 = SkScalarToFIXED(SkScalarMul(fScale, -fRec.fPost2x2[0][1]));\r
+    fMat22.eM21 = SkScalarToFIXED(SkScalarMul(fScale, fRec.fPost2x2[1][0]));\r
+    fMat22.eM22 = SkScalarToFIXED(SkScalarMul(fScale, -fRec.fPost2x2[1][1]));\r
 \r
-    ddc = ::CreateCompatibleDC(NULL);\r
-    SetBkMode(ddc, TRANSPARENT);\r
+    fDDC = ::CreateCompatibleDC(NULL);\r
+    SetBkMode(fDDC, TRANSPARENT);\r
 \r
     // Scaling by the DPI is inconsistent with how Skia draws elsewhere\r
     //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);\r
-    SkScalar height = -fRec.fTextSize;\r
-    lf.lfHeight = SkScalarRound(height);\r
-    font = CreateFontIndirect(&lf);\r
-    savefont = (HFONT)SelectObject(ddc, font);\r
+    LOGFONT lf = LogFontTypeface::FindById(fRec.fFontID)->logFont();\r
+    lf.lfHeight = -gCanonicalTextSize;\r
+    fFont = CreateFontIndirect(&lf);\r
+    fSavefont = (HFONT)SelectObject(fDDC, fFont);\r
 }\r
 \r
 SkScalerContext_Windows::~SkScalerContext_Windows() {\r
-    if (ddc) {\r
-        ::SelectObject(ddc, savefont);\r
-        ::DeleteDC(ddc);\r
-        ddc = NULL;\r
+    if (fDDC) {\r
+        ::SelectObject(fDDC, fSavefont);\r
+        ::DeleteDC(fDDC);\r
     }\r
-    if (font) {\r
-        ::DeleteObject(font);\r
+    if (fFont) {\r
+        ::DeleteObject(fFont);\r
     }\r
-    if (sc) {\r
-        ::ScriptFreeCache(&sc);\r
+    if (fSC) {\r
+        ::ScriptFreeCache(&fSC);\r
     }\r
 }\r
 \r
@@ -245,7 +258,7 @@ uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
     // TODO(ctguil): Support characters that generate more than one glyph.\r
     if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) {\r
         // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0.\r
-        SkAssertResult(GetGlyphIndicesW(ddc, c, 1, &index, 0));\r
+        SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0));\r
     } else {\r
         // Use uniscribe to detemine glyph index for non-BMP characters.\r
         // Need to add extra item to SCRIPT_ITEM to work around a bug in older\r
@@ -259,7 +272,7 @@ uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
         SCRIPT_VISATTR vsa;\r
         int glyphs;\r
         SkAssertResult(SUCCEEDED(ScriptShape(\r
-            ddc, &sc, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs)));\r
+            fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs)));\r
     }\r
     return index;\r
 }\r
@@ -270,7 +283,7 @@ void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
 \r
 void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {\r
 \r
-    SkASSERT(ddc);\r
+    SkASSERT(fDDC);\r
 \r
     GLYPHMETRICS gm;\r
     memset(&gm, 0, sizeof(gm));\r
@@ -280,7 +293,7 @@ void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
 \r
     // Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller\r
     // BlackBlox; we need the bigger one in case we need the image.  fAdvance is the same.\r
-    uint32_t ret = GetGlyphOutlineW(ddc, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &mat22);\r
+    uint32_t ret = GetGlyphOutlineW(fDDC, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);\r
 \r
     if (GDI_ERROR != ret) {\r
         if (ret == 0) {\r
@@ -310,31 +323,31 @@ void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPa
     if (!(mx || my))\r
       return;\r
 \r
-    SkASSERT(ddc);\r
+    SkASSERT(fDDC);\r
 \r
     OUTLINETEXTMETRIC otm;\r
 \r
-    uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm);\r
+    uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);\r
     if (sizeof(otm) != ret) {\r
       return;\r
     }\r
 \r
     if (mx) {\r
-      mx->fTop = -SkIntToScalar(otm.otmTextMetrics.tmAscent);  // Actually a long.\r
-      mx->fAscent = -SkIntToScalar(otm.otmAscent);\r
-      mx->fDescent = -SkIntToScalar(otm.otmDescent);\r
-      mx->fBottom = SkIntToScalar(otm.otmTextMetrics.tmDescent);  // Long\r
-      mx->fLeading = SkIntToScalar(otm.otmTextMetrics.tmInternalLeading\r
-          + otm.otmTextMetrics.tmExternalLeading);  // Long\r
+        mx->fTop = -fScale * otm.otmTextMetrics.tmAscent;\r
+               mx->fAscent = -fScale * otm.otmAscent;\r
+               mx->fDescent = -fScale * otm.otmDescent;\r
+               mx->fBottom = fScale * otm.otmTextMetrics.tmDescent;\r
+               mx->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading\r
+                                                                + otm.otmTextMetrics.tmExternalLeading);\r
     }\r
 \r
     if (my) {\r
-      my->fTop = -SkIntToScalar(otm.otmTextMetrics.tmAscent);  // Actually a long.\r
-      my->fAscent = -SkIntToScalar(otm.otmAscent);\r
-      my->fDescent = -SkIntToScalar(otm.otmDescent);\r
-      my->fBottom = SkIntToScalar(otm.otmTextMetrics.tmDescent);  // Long\r
-      my->fLeading = SkIntToScalar(otm.otmTextMetrics.tmInternalLeading\r
-          + otm.otmTextMetrics.tmExternalLeading);  // Long\r
+               my->fTop = -fScale * otm.otmTextMetrics.tmAscent;\r
+               my->fAscent = -fScale * otm.otmAscent;\r
+               my->fDescent = -fScale * otm.otmDescent;\r
+               my->fBottom = fScale * otm.otmTextMetrics.tmDescent;\r
+               my->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading\r
+                                                                + otm.otmTextMetrics.tmExternalLeading);\r
     }\r
 }\r
 \r
@@ -342,7 +355,7 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
 \r
     SkAutoMutexAcquire  ac(gFTMutex);\r
 \r
-    SkASSERT(ddc);\r
+    SkASSERT(fDDC);\r
 \r
     GLYPHMETRICS gm;\r
     memset(&gm, 0, sizeof(gm));\r
@@ -354,11 +367,11 @@ void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
 #endif\r
 \r
     uint32_t bytecount = 0;\r
-    uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &mat22);\r
+    uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);\r
     if (GDI_ERROR != total_size && total_size > 0) {\r
         uint8_t *pBuff = new uint8_t[total_size];\r
         if (NULL != pBuff) {\r
-            total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, total_size, pBuff, &mat22);\r
+            total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_GRAY8_BITMAP | GGO_GLYPH_INDEX, &gm, total_size, pBuff, &fMat22);\r
 \r
             SkASSERT(total_size != GDI_ERROR);\r
 \r
@@ -402,7 +415,7 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
     SkAutoMutexAcquire  ac(gFTMutex);\r
 \r
     SkASSERT(&glyph && path);\r
-    SkASSERT(ddc);\r
+    SkASSERT(fDDC);\r
 \r
     path->reset();\r
 \r
@@ -413,7 +426,7 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
 #endif\r
 \r
     GLYPHMETRICS gm;\r
-    uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &mat22);\r
+    uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);\r
 \r
     if (GDI_ERROR != total_size) {\r
 \r
@@ -464,26 +477,6 @@ void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
     //OutputDebugString(buf);\r
 }\r
 \r
-\r
-// Note:  not sure this is the correct implementation\r
-void SkScalerContext_Windows::generateLineHeight(SkPoint* ascent, SkPoint* descent) {\r
-\r
-    SkASSERT(ddc);\r
-\r
-    OUTLINETEXTMETRIC otm;\r
-\r
-    uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm);\r
-\r
-    if (sizeof(otm) == ret) {\r
-        if (ascent)\r
-            ascent->iset(0, otm.otmAscent);\r
-        if (descent)\r
-            descent->iset(0, otm.otmDescent);\r
-    }\r
-\r
-    return;\r
-}\r
-\r
 void SkFontHost::Serialize(const SkTypeface* face, SkWStream* stream) {\r
     SkASSERT(!"SkFontHost::Serialize unimplemented");\r
 }\r