// 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
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
\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
}\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
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
// 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
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
\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
\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
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
\r
SkAutoMutexAcquire ac(gFTMutex);\r
\r
- SkASSERT(ddc);\r
+ SkASSERT(fDDC);\r
\r
GLYPHMETRICS gm;\r
memset(&gm, 0, sizeof(gm));\r
#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
SkAutoMutexAcquire ac(gFTMutex);\r
\r
SkASSERT(&glyph && path);\r
- SkASSERT(ddc);\r
+ SkASSERT(fDDC);\r
\r
path->reset();\r
\r
#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
//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