From cb1bbb375aa4fdd099dc60302ca1712f04607782 Mon Sep 17 00:00:00 2001 From: "bungeman@google.com" Date: Fri, 12 Oct 2012 18:48:35 +0000 Subject: [PATCH] Fonts with cubic outlines are rendered without ClearType by GDI. https://codereview.appspot.com/6643060/ git-svn-id: http://skia.googlecode.com/svn/trunk@5929 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/core/SkFontHost.h | 4 +++- include/core/SkTypeface.h | 3 +++ src/core/SkPaint.cpp | 8 +++++-- src/core/SkTypeface.cpp | 4 ++-- src/ports/SkFontHost_FreeType.cpp | 2 +- src/ports/SkFontHost_mac_atsui.cpp | 2 +- src/ports/SkFontHost_mac_coretext.cpp | 2 +- src/ports/SkFontHost_none.cpp | 2 +- src/ports/SkFontHost_win.cpp | 45 ++++++++++++++++++++++++++++------- src/ports/SkFontHost_win_dw.cpp | 2 +- src/utils/ios/SkFontHost_iOS.mm | 2 +- 11 files changed, 56 insertions(+), 20 deletions(-) diff --git a/include/core/SkFontHost.h b/include/core/SkFontHost.h index 86fcac0..737b2eb 100644 --- a/include/core/SkFontHost.h +++ b/include/core/SkFontHost.h @@ -167,8 +167,10 @@ public: the same output. A lazy (but valid) fonthost can do nothing in its FilterRec routine. + + The provided typeface corresponds to the fFontID field. */ - static void FilterRec(SkScalerContextRec* rec); + static void FilterRec(SkScalerContextRec* rec, SkTypeface* typeface); /////////////////////////////////////////////////////////////////////////// diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h index 78ec9f7..7fb6b81 100644 --- a/include/core/SkTypeface.h +++ b/include/core/SkTypeface.h @@ -189,6 +189,9 @@ protected: SkTypeface(Style style, SkFontID uniqueID, bool isFixedWidth = false); virtual ~SkTypeface(); + friend class SkScalerContext; + static SkTypeface* GetDefaultTypeface(); + private: SkFontID fUniqueID; Style fStyle; diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 58a8c1c..c517663 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -1505,7 +1505,11 @@ void SkScalerContext::MakeRec(const SkPaint& paint, const SkMatrix* deviceMatrix, Rec* rec) { SkASSERT(deviceMatrix == NULL || !deviceMatrix->hasPerspective()); - rec->fOrigFontID = SkTypeface::UniqueID(paint.getTypeface()); + SkTypeface* typeface = paint.getTypeface(); + if (NULL == typeface) { + typeface = SkTypeface::GetDefaultTypeface(); + } + rec->fOrigFontID = typeface->uniqueID(); rec->fFontID = rec->fOrigFontID; rec->fTextSize = paint.getTextSize(); rec->fPreScaleX = paint.getTextScaleX(); @@ -1622,7 +1626,7 @@ void SkScalerContext::MakeRec(const SkPaint& paint, they can modify our rec up front, so we don't create duplicate cache entries. */ - SkFontHost::FilterRec(rec); + SkFontHost::FilterRec(rec, typeface); // be sure to call PostMakeRec(rec) before you actually use it! } diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index 3a40e01..94bb237 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -36,7 +36,7 @@ SkTypeface::~SkTypeface() { /////////////////////////////////////////////////////////////////////////////// -static SkTypeface* get_default_typeface() { +SkTypeface* SkTypeface::GetDefaultTypeface() { // we keep a reference to this guy for all time, since if we return its // fontID, the font cache may later on ask to resolve that back into a // typeface object. @@ -51,7 +51,7 @@ static SkTypeface* get_default_typeface() { uint32_t SkTypeface::UniqueID(const SkTypeface* face) { if (NULL == face) { - face = get_default_typeface(); + face = GetDefaultTypeface(); } return face->uniqueID(); } diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index 5d35133..ce8f409 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -637,7 +637,7 @@ static bool isAxisAligned(const SkScalerContext::Rec& rec) { bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1])); } -void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { +void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { //BOGUS: http://code.google.com/p/chromium/issues/detail?id=121119 //Cap the requested size as larger sizes give bogus values. //Remove when http://code.google.com/p/skia/issues/detail?id=554 is fixed. diff --git a/src/ports/SkFontHost_mac_atsui.cpp b/src/ports/SkFontHost_mac_atsui.cpp index f8251ab..84f7f0b 100644 --- a/src/ports/SkFontHost_mac_atsui.cpp +++ b/src/ports/SkFontHost_mac_atsui.cpp @@ -97,7 +97,7 @@ private: static OSStatus Close(void *cb); }; -void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { +void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { // we only support 2 levels of hinting SkPaint::Hinting h = rec->getHinting(); if (SkPaint::kSlight_Hinting == h) { diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp index 622b8ed..e385337 100644 --- a/src/ports/SkFontHost_mac_coretext.cpp +++ b/src/ports/SkFontHost_mac_coretext.cpp @@ -1811,7 +1811,7 @@ SkFontID SkFontHost::NextLogicalFont(SkFontID currFontID, SkFontID origFontID) { return nextFontID; } -void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { +void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | SkScalerContext::kAutohinting_Flag; diff --git a/src/ports/SkFontHost_none.cpp b/src/ports/SkFontHost_none.cpp index a683919..21eda8e 100644 --- a/src/ports/SkFontHost_none.cpp +++ b/src/ports/SkFontHost_none.cpp @@ -37,7 +37,7 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( return NULL; } -void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { +void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index 015df78..f2603e9 100755 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -210,11 +210,39 @@ static unsigned calculateOutlineGlyphCount(HDC hdc) { class LogFontTypeface : public SkTypeface { public: - LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf) : - SkTypeface(style, fontID, false), fLogFont(lf), fSerializeAsStream(false) {} + LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, bool serializeAsStream = false) : + SkTypeface(style, fontID, false), fLogFont(lf), fSerializeAsStream(serializeAsStream) { + + // If the font has cubic outlines, it will not be rendered with ClearType. + HFONT font = CreateFontIndirect(&lf); + + HDC deviceContext = ::CreateCompatibleDC(NULL); + HFONT savefont = (HFONT)SelectObject(deviceContext, font); + + TEXTMETRIC textMetric; + if (0 == GetTextMetrics(deviceContext, &textMetric)) { + SkFontHost::EnsureTypefaceAccessible(*this); + if (0 == GetTextMetrics(deviceContext, &textMetric)) { + textMetric.tmPitchAndFamily = TMPF_TRUETYPE; + } + } + if (deviceContext) { + ::SelectObject(deviceContext, savefont); + ::DeleteDC(deviceContext); + } + if (font) { + ::DeleteObject(font); + } + + // Used a logfont on a memory context, should never get a device font. + // Therefore all TMPF_DEVICE will be PostScript (cubic) fonts. + fCanBeLCD = !((textMetric.tmPitchAndFamily & TMPF_VECTOR) && + (textMetric.tmPitchAndFamily & TMPF_DEVICE)); + } LOGFONT fLogFont; bool fSerializeAsStream; + bool fCanBeLCD; static LogFontTypeface* Create(const LOGFONT& lf) { SkTypeface::Style style = get_style(lf); @@ -229,8 +257,7 @@ public: * Takes ownership of fontMemResource. */ FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) : - LogFontTypeface(style, fontID, lf), fFontMemResource(fontMemResource) { - fSerializeAsStream = true; + LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) { } HANDLE fFontMemResource; @@ -1673,7 +1700,7 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { return face; } -void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { +void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface* typeface) { unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | SkScalerContext::kAutohinting_Flag | SkScalerContext::kEmbeddedBitmapText_Flag | @@ -1713,9 +1740,9 @@ void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { } #endif -#if 0 - if (SkMask::kLCD16_Format == rec->fMaskFormat) { - rec->fMaskFormat = SkMask::kLCD32_Format; + LogFontTypeface* logfontTypeface = static_cast(typeface); + if (!logfontTypeface->fCanBeLCD && isLCD(*rec)) { + rec->fMaskFormat = SkMask::kA8_Format; + rec->fFlags &= ~SkScalerContext::kGenA8FromLCD_Flag; } -#endif } diff --git a/src/ports/SkFontHost_win_dw.cpp b/src/ports/SkFontHost_win_dw.cpp index d91cfa9..82d44ee 100644 --- a/src/ports/SkFontHost_win_dw.cpp +++ b/src/ports/SkFontHost_win_dw.cpp @@ -1264,7 +1264,7 @@ SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) { return NULL; } -void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { +void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | SkScalerContext::kAutohinting_Flag | SkScalerContext::kEmbeddedBitmapText_Flag | diff --git a/src/utils/ios/SkFontHost_iOS.mm b/src/utils/ios/SkFontHost_iOS.mm index b74b29f..60f111c 100755 --- a/src/utils/ios/SkFontHost_iOS.mm +++ b/src/utils/ios/SkFontHost_iOS.mm @@ -253,7 +253,7 @@ SkAdvancedTypefaceMetrics* SkFontHost::GetAdvancedTypefaceMetrics( return NULL; } -void SkFontHost::FilterRec(SkScalerContext::Rec* rec) { +void SkFontHost::FilterRec(SkScalerContext::Rec* rec, SkTypeface*) { } SkScalerContext* SkFontHost::CreateScalerContext(const SkDescriptor* desc) { -- 2.7.4