aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-03-01 15:18:14 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2011-03-01 15:18:14 +0000
commitb652427197ddaac5d35010e1b199bcb431e656b7 (patch)
tree881345894396be575261aff9f1c3ee2b2fcc234f
parentf9bb7a8e2052d21e6a7f48d5b73d2ef97637a09e (diff)
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
-rw-r--r--samplecode/SampleTextBox.cpp43
-rw-r--r--src/ports/SkFontHost_win.cpp143
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");
}