diff --git a/include/core/SkScalerContext.h b/include/core/SkScalerContext.h index 5937819cb..317658dbd 100644 --- a/include/core/SkScalerContext.h +++ b/include/core/SkScalerContext.h @@ -230,7 +230,7 @@ public: */ SkUnichar glyphIDToChar(uint16_t glyphID); - unsigned getGlyphCount() const { return this->generateGlyphCount(); } + unsigned getGlyphCount() { return this->generateGlyphCount(); } void getAdvance(SkGlyph*); void getMetrics(SkGlyph*); void getImage(const SkGlyph&); @@ -245,7 +245,7 @@ protected: Rec fRec; unsigned fBaseGlyphCount; - virtual unsigned generateGlyphCount() const = 0; + virtual unsigned generateGlyphCount() = 0; virtual uint16_t generateCharToGlyph(SkUnichar) = 0; virtual void generateAdvance(SkGlyph*) = 0; virtual void generateMetrics(SkGlyph*) = 0; diff --git a/src/core/SkGlyphCache.cpp b/src/core/SkGlyphCache.cpp index 5ed738611..b97699c2d 100644 --- a/src/core/SkGlyphCache.cpp +++ b/src/core/SkGlyphCache.cpp @@ -117,6 +117,10 @@ SkUnichar SkGlyphCache::glyphToUnichar(uint16_t glyphID) { return fScalerContext->glyphIDToChar(glyphID); } +unsigned SkGlyphCache::getGlyphCount() { + return fScalerContext->getGlyphCount(); +} + /////////////////////////////////////////////////////////////////////////////// const SkGlyph& SkGlyphCache::getUnicharAdvance(SkUnichar charCode) { diff --git a/src/core/SkGlyphCache.h b/src/core/SkGlyphCache.h index 16330f87a..d6b4fd631 100644 --- a/src/core/SkGlyphCache.h +++ b/src/core/SkGlyphCache.h @@ -77,6 +77,10 @@ public: */ SkUnichar glyphToUnichar(uint16_t); + /** Returns the number of glyphs for this strike. + */ + unsigned getGlyphCount(); + /** Return the image associated with the glyph. If it has not been generated this will trigger that. */ diff --git a/src/core/SkScalerContext.cpp b/src/core/SkScalerContext.cpp index 697917ab0..bbe01585e 100644 --- a/src/core/SkScalerContext.cpp +++ b/src/core/SkScalerContext.cpp @@ -645,7 +645,7 @@ public: SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {} protected: - virtual unsigned generateGlyphCount() const { + virtual unsigned generateGlyphCount() { return 0; } virtual uint16_t generateCharToGlyph(SkUnichar uni) { diff --git a/src/ports/SkFontHost_FreeType.cpp b/src/ports/SkFontHost_FreeType.cpp index 1a22972bb..5fb3245a5 100644 --- a/src/ports/SkFontHost_FreeType.cpp +++ b/src/ports/SkFontHost_FreeType.cpp @@ -121,7 +121,7 @@ public: } protected: - virtual unsigned generateGlyphCount() const; + virtual unsigned generateGlyphCount(); virtual uint16_t generateCharToGlyph(SkUnichar uni); virtual void generateAdvance(SkGlyph* glyph); virtual void generateMetrics(SkGlyph* glyph); @@ -731,7 +731,7 @@ void SkScalerContext_FreeType::emboldenOutline(FT_Outline* outline) { FT_Outline_Embolden(outline, strength); } -unsigned SkScalerContext_FreeType::generateGlyphCount() const { +unsigned SkScalerContext_FreeType::generateGlyphCount() { return fFace->num_glyphs; } diff --git a/src/ports/SkFontHost_ascender.cpp b/src/ports/SkFontHost_ascender.cpp index 88cde3868..6f5cf0bbb 100644 --- a/src/ports/SkFontHost_ascender.cpp +++ b/src/ports/SkFontHost_ascender.cpp @@ -22,7 +22,7 @@ public: virtual ~SkScalerContext_Ascender(); protected: - virtual unsigned generateGlyphCount() const; + virtual unsigned generateGlyphCount(); virtual uint16_t generateCharToGlyph(SkUnichar uni); virtual void generateMetrics(SkGlyph* glyph); virtual void generateImage(const SkGlyph& glyph); @@ -102,7 +102,7 @@ SkScalerContext_Ascender::~SkScalerContext_Ascender() sk_free(fHandle); } -unsigned SkScalerContext_Ascender::generateGlyphCount() const +unsigned SkScalerContext_Ascender::generateGlyphCount() { return 1000; } diff --git a/src/ports/SkFontHost_mac_atsui.cpp b/src/ports/SkFontHost_mac_atsui.cpp index 518373032..1d40a42a9 100644 --- a/src/ports/SkFontHost_mac_atsui.cpp +++ b/src/ports/SkFontHost_mac_atsui.cpp @@ -87,7 +87,7 @@ public: virtual ~SkScalerContext_Mac(); protected: - virtual unsigned generateGlyphCount() const; + virtual unsigned generateGlyphCount(); virtual uint16_t generateCharToGlyph(SkUnichar uni); virtual void generateAdvance(SkGlyph* glyph); virtual void generateMetrics(SkGlyph* glyph); @@ -184,7 +184,7 @@ SkScalerContext_Mac::~SkScalerContext_Mac() { // man, we need to consider caching this, since it is just dependent on // fFontID, and not on any of the other settings like matrix or flags -unsigned SkScalerContext_Mac::generateGlyphCount() const { +unsigned SkScalerContext_Mac::generateGlyphCount() { // The 'maxp' table stores the number of glyphs a offset 4, in 2 bytes uint16_t numGlyphs; if (SkFontHost::GetTableData(fRec.fFontID, diff --git a/src/ports/SkFontHost_mac_coretext.cpp b/src/ports/SkFontHost_mac_coretext.cpp index 4b5c36d4a..c1540278f 100644 --- a/src/ports/SkFontHost_mac_coretext.cpp +++ b/src/ports/SkFontHost_mac_coretext.cpp @@ -314,7 +314,7 @@ public: protected: - unsigned generateGlyphCount(void) const; + unsigned generateGlyphCount(void); uint16_t generateCharToGlyph(SkUnichar uni); void generateAdvance(SkGlyph* glyph); void generateMetrics(SkGlyph* glyph); @@ -373,7 +373,7 @@ SkScalerContext_Mac::~SkScalerContext_Mac(void) CFSafeRelease(mFont); } -unsigned SkScalerContext_Mac::generateGlyphCount(void) const +unsigned SkScalerContext_Mac::generateGlyphCount(void) { return(mGlyphCount); } diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index 85a3763b3..04a50cb75 100644 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -17,6 +17,7 @@ #include "SkString.h" //#include "SkStream.h" +#include "SkEndian.h" #include "SkFontHost.h" #include "SkDescriptor.h" #include "SkAdvancedTypefaceMetrics.h" @@ -63,6 +64,32 @@ static inline FIXED SkScalarToFIXED(SkScalar x) { return SkFixedToFIXED(SkScalarToFixed(x)); } +static unsigned calculateGlyphCount(HDC hdc) { + // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes. + const DWORD maxpTag = *(DWORD*) "maxp"; + uint16_t glyphs; + if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) { + return SkEndian_SwapBE16(glyphs); + } + + // Binary search for glyph count. + static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; + int32_t max = SK_MaxU16 + 1; + int32_t min = 0; + GLYPHMETRICS gm; + while (min < max) { + int32_t mid = min + ((max - min) / 2); + if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, + NULL, &mat2) == GDI_ERROR) { + max = mid; + } else { + min = mid + 1; + } + } + SkASSERT(min == max); + return min; +} + static SkTypeface::Style GetFontStyle(const LOGFONT& lf) { int style = SkTypeface::kNormal; if (lf.lfWeight == FW_SEMIBOLD || lf.lfWeight == FW_DEMIBOLD || lf.lfWeight == FW_BOLD) @@ -188,7 +215,7 @@ public: virtual ~SkScalerContext_Windows(); protected: - virtual unsigned generateGlyphCount() const; + virtual unsigned generateGlyphCount(); virtual uint16_t generateCharToGlyph(SkUnichar uni); virtual void generateAdvance(SkGlyph* glyph); virtual void generateMetrics(SkGlyph* glyph); @@ -203,10 +230,12 @@ private: HFONT fSavefont; HFONT fFont; SCRIPT_CACHE fSC; + int fGlyphCount; }; SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) - : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0) { + : SkScalerContext(desc), fDDC(0), fFont(0), fSavefont(0), fSC(0) + , fGlyphCount(-1) { SkAutoMutexAcquire ac(gFTMutex); fScale = fRec.fTextSize / gCanonicalTextSize; @@ -239,9 +268,11 @@ SkScalerContext_Windows::~SkScalerContext_Windows() { } } -unsigned SkScalerContext_Windows::generateGlyphCount() const { - return 0xFFFF; - // return fFace->num_glyphs; +unsigned SkScalerContext_Windows::generateGlyphCount() { + if (fGlyphCount < 0) { + fGlyphCount = calculateGlyphCount(fDDC); + } + return fGlyphCount; } uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {