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
diff --git a/samplecode/SampleTextBox.cpp b/samplecode/SampleTextBox.cpp
index f8f52a2..9511914 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 @@
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 @@
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 a6d232a..17b8571 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -51,6 +51,18 @@
// 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 @@
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 @@
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 @@
}
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 @@
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();
+ 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]));
- 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]);
-
- 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 @@
// 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 @@
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::generateMetrics(SkGlyph* glyph) {
- SkASSERT(ddc);
+ SkASSERT(fDDC);
GLYPHMETRICS gm;
memset(&gm, 0, sizeof(gm));
@@ -280,7 +293,7 @@
// 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 @@
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 @@
SkAutoMutexAcquire ac(gFTMutex);
- SkASSERT(ddc);
+ SkASSERT(fDDC);
GLYPHMETRICS gm;
memset(&gm, 0, sizeof(gm));
@@ -354,11 +367,11 @@
#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 @@
SkAutoMutexAcquire ac(gFTMutex);
SkASSERT(&glyph && path);
- SkASSERT(ddc);
+ SkASSERT(fDDC);
path->reset();
@@ -413,7 +426,7 @@
#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 @@
//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");
}