diff options
author | bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-07-15 19:42:57 +0000 |
---|---|---|
committer | bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-07-15 19:42:57 +0000 |
commit | 7bdd614a1940935d3badeb54f7aae75d76ea830d (patch) | |
tree | aeb3d7e8d8b68cb9d1fb77a0def97f689a2876d7 | |
parent | 78b38b130deb8bcfa41611039875ce0162542ac1 (diff) |
Implement onCountGlyphs and onGetUPEM on Windows.
R=vandebo@chromium.org
Review URL: https://codereview.chromium.org/19231003
git-svn-id: http://skia.googlecode.com/svn/trunk@10089 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | include/core/SkTypeface.h | 4 | ||||
-rw-r--r-- | src/core/SkTypeface.cpp | 5 | ||||
-rwxr-xr-x | src/ports/SkFontHost_win.cpp | 78 | ||||
-rw-r--r-- | src/ports/SkFontHost_win_dw.cpp | 12 | ||||
-rw-r--r-- | tests/FontHostTest.cpp | 35 |
5 files changed, 111 insertions, 23 deletions
diff --git a/include/core/SkTypeface.h b/include/core/SkTypeface.h index c84ae288a6..0fd2ddba1f 100644 --- a/include/core/SkTypeface.h +++ b/include/core/SkTypeface.h @@ -272,9 +272,9 @@ protected: virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], int glyphCount) const; - virtual int onCountGlyphs() const; + virtual int onCountGlyphs() const = 0; - virtual int onGetUPEM() const; + virtual int onGetUPEM() const = 0; virtual int onGetTableTags(SkFontTableTag tags[]) const; virtual size_t onGetTableData(SkFontTableTag, size_t offset, diff --git a/src/core/SkTypeface.cpp b/src/core/SkTypeface.cpp index dcdd5e29f3..294323841c 100644 --- a/src/core/SkTypeface.cpp +++ b/src/core/SkTypeface.cpp @@ -214,11 +214,6 @@ int SkTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, return 0; } -int SkTypeface::onCountGlyphs() const { - SkDebugf("onCountGlyphs unimplemented\n"); - return 0; -} - int SkTypeface::onGetUPEM() const { int upem = 0; diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index d07307e6fd..22385934ed 100755 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -15,6 +15,7 @@ #include "SkFontHost.h" #include "SkGlyph.h" #include "SkMaskGamma.h" +#include "SkOTTable_maxp.h" #include "SkOTUtils.h" #include "SkPath.h" #include "SkStream.h" @@ -140,12 +141,21 @@ static inline FIXED SkScalarToFIXED(SkScalar x) { return SkFixedToFIXED(SkScalarToFixed(x)); } -static unsigned calculateOutlineGlyphCount(HDC hdc) { +static unsigned calculateGlyphCount(HDC hdc, const LOGFONT& lf) { + TEXTMETRIC textMetric; + if (0 == GetTextMetrics(hdc, &textMetric)) { + textMetric.tmPitchAndFamily = TMPF_VECTOR; + call_ensure_accessible(lf); + GetTextMetrics(hdc, &textMetric); + } + + if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) { + return textMetric.tmLastChar; + } + // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes. - const DWORD maxpTag = - SkEndian_SwapBE32(SkSetFourByteTag('m', 'a', 'x', 'p')); uint16_t glyphs; - if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) { + if (GDI_ERROR != GetFontData(hdc, SkOTTableMaximumProfile::TAG, 4, &glyphs, sizeof(glyphs))) { return SkEndian_SwapBE16(glyphs); } @@ -167,6 +177,28 @@ static unsigned calculateOutlineGlyphCount(HDC hdc) { return min; } +static unsigned calculateUPEM(HDC hdc, const LOGFONT& lf) { + TEXTMETRIC textMetric; + if (0 == GetTextMetrics(hdc, &textMetric)) { + textMetric.tmPitchAndFamily = TMPF_VECTOR; + call_ensure_accessible(lf); + GetTextMetrics(hdc, &textMetric); + } + + if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) { + return textMetric.tmMaxCharWidth; + } + + OUTLINETEXTMETRIC otm; + unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); + if (0 == otmRet) { + call_ensure_accessible(lf); + otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); + } + + return (0 == otmRet) ? 0 : otm.otmEMSquare; +} + class LogFontTypeface : public SkTypeface { public: LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, bool serializeAsStream = false) : @@ -228,6 +260,8 @@ protected: SkAdvancedTypefaceMetrics::PerGlyphInfo, const uint32_t*, uint32_t) const SK_OVERRIDE; virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE; + virtual int onCountGlyphs() const SK_OVERRIDE; + virtual int onGetUPEM() const SK_OVERRIDE; }; class FontMemResourceTypeface : public LogFontTypeface { @@ -724,10 +758,8 @@ bool SkScalerContext_Windows::isValid() const { unsigned SkScalerContext_Windows::generateGlyphCount() { if (fGlyphCount < 0) { - if (fType == SkScalerContext_Windows::kBitmap_Type) { - return fTM.tmLastChar; - } - fGlyphCount = calculateOutlineGlyphCount(fDDC); + fGlyphCount = calculateGlyphCount( + fDDC, static_cast<const LogFontTypeface*>(this->getTypeface())->fLogFont); } return fGlyphCount; } @@ -1446,7 +1478,7 @@ SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics( if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) { goto Error; } - glyphCount = calculateOutlineGlyphCount(hdc); + glyphCount = calculateGlyphCount(hdc, fLogFont); info = new SkAdvancedTypefaceMetrics; info->fEmSize = otm.otmEMSquare; @@ -1684,6 +1716,34 @@ SkStream* LogFontTypeface::onOpenStream(int* ttcIndex) const { return stream; } +int LogFontTypeface::onCountGlyphs() const { + HDC hdc = ::CreateCompatibleDC(NULL); + HFONT font = CreateFontIndirect(&fLogFont); + HFONT savefont = (HFONT)SelectObject(hdc, font); + + unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont); + + SelectObject(hdc, savefont); + DeleteObject(font); + DeleteDC(hdc); + + return glyphCount; +} + +int LogFontTypeface::onGetUPEM() const { + HDC hdc = ::CreateCompatibleDC(NULL); + HFONT font = CreateFontIndirect(&fLogFont); + HFONT savefont = (HFONT)SelectObject(hdc, font); + + unsigned int upem = calculateUPEM(hdc, fLogFont); + + SelectObject(hdc, savefont); + DeleteObject(font); + DeleteDC(hdc); + + return upem; +} + SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const { SkScalerContext_Windows* ctx = SkNEW_ARGS(SkScalerContext_Windows, (const_cast<LogFontTypeface*>(this), desc)); diff --git a/src/ports/SkFontHost_win_dw.cpp b/src/ports/SkFontHost_win_dw.cpp index 29fa09857b..3772a092d3 100644 --- a/src/ports/SkFontHost_win_dw.cpp +++ b/src/ports/SkFontHost_win_dw.cpp @@ -492,6 +492,8 @@ protected: SkAdvancedTypefaceMetrics::PerGlyphInfo, const uint32_t*, uint32_t) const SK_OVERRIDE; virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE; + virtual int onCountGlyphs() const SK_OVERRIDE; + virtual int onGetUPEM() const SK_OVERRIDE; }; class SkScalerContext_Windows : public SkScalerContext { @@ -1071,6 +1073,16 @@ void DWriteFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, *isLocalStream = SkToBool(fDWriteFontFileLoader.get()); } +int DWriteFontTypeface::onCountGlyphs() const { + return fDWriteFontFace->GetGlyphCount(); +} + +int DWriteFontTypeface::onGetUPEM() const { + DWRITE_FONT_METRICS metrics; + fDWriteFontFace->GetMetrics(&metrics); + return metrics.designUnitsPerEm; +} + template <typename T> class SkAutoIDWriteUnregister { public: SkAutoIDWriteUnregister(IDWriteFactory* factory, T* unregister) diff --git a/tests/FontHostTest.cpp b/tests/FontHostTest.cpp index 9a186dd57d..7358b1089a 100644 --- a/tests/FontHostTest.cpp +++ b/tests/FontHostTest.cpp @@ -29,20 +29,18 @@ static const struct TagSize { }; // Test that getUnitsPerEm() agrees with a direct lookup in the 'head' table -// (if that table is available. +// (if that table is available). static void test_unitsPerEm(skiatest::Reporter* reporter, SkTypeface* face) { - int nativeUPEM = face->getUnitsPerEm();; + int nativeUPEM = face->getUnitsPerEm(); int tableUPEM = -1; size_t size = face->getTableSize(kFontTableTag_head); if (size) { - SkAutoMalloc storage(size); - char* ptr = (char*)storage.get(); - face->getTableData(kFontTableTag_head, 0, size, ptr); // unitsPerEm is at offset 18 into the 'head' table. - tableUPEM = SkEndian_SwapBE16(*(uint16_t*)&ptr[18]); + uint16_t rawUPEM; + face->getTableData(kFontTableTag_head, 18, sizeof(rawUPEM), &rawUPEM); + tableUPEM = SkEndian_SwapBE16(rawUPEM); } -// SkDebugf("--- typeface returned %d upem [%X]\n", nativeUPEM, face->uniqueID()); if (tableUPEM >= 0) { REPORTER_ASSERT(reporter, tableUPEM == nativeUPEM); @@ -52,6 +50,28 @@ static void test_unitsPerEm(skiatest::Reporter* reporter, SkTypeface* face) { } } +// Test that countGlyphs() agrees with a direct lookup in the 'maxp' table +// (if that table is available). +static void test_countGlyphs(skiatest::Reporter* reporter, SkTypeface* face) { + int nativeGlyphs = face->countGlyphs(); + + int tableGlyphs = -1; + size_t size = face->getTableSize(kFontTableTag_maxp); + if (size) { + // glyphs is at offset 4 into the 'maxp' table. + uint16_t rawGlyphs; + face->getTableData(kFontTableTag_maxp, 4, sizeof(rawGlyphs), &rawGlyphs); + tableGlyphs = SkEndian_SwapBE16(rawGlyphs); + } + + if (tableGlyphs >= 0) { + REPORTER_ASSERT(reporter, tableGlyphs == nativeGlyphs); + } else { + // not sure this is a bug, but lets report it for now as info. + SkDebugf("--- typeface returned 0 glyphs [%X]\n", face->uniqueID()); + } +} + static void test_fontstream(skiatest::Reporter* reporter, SkStream* stream, int ttcIndex) { int n = SkFontStream::GetTableTags(stream, ttcIndex, NULL); @@ -157,6 +177,7 @@ static void test_tables(skiatest::Reporter* reporter) { #endif test_tables(reporter, face); test_unitsPerEm(reporter, face); + test_countGlyphs(reporter, face); face->unref(); } } |