From 33346487cbb64134d7204abe32d9318c1b511aa8 Mon Sep 17 00:00:00 2001 From: "bungeman@google.com" Date: Tue, 27 Aug 2013 19:05:32 +0000 Subject: [PATCH] Fix _GDI::generateCharToGlyph to properly handle missing glyphs. git-svn-id: http://skia.googlecode.com/svn/trunk@10945 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gm/verttext.cpp | 6 +++--- src/ports/SkFontHost_win.cpp | 32 ++++++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/gm/verttext.cpp b/gm/verttext.cpp index 164f99091..1f1c64dfe 100644 --- a/gm/verttext.cpp +++ b/gm/verttext.cpp @@ -23,7 +23,7 @@ static const char gText[] = "Hello"; //static const char gText[] = "﹁テスト︒﹂"; //static const char gText[] = {0xEF,0xB9,0x81, 0xE3,0x83,0x86, 0xE3,0x82,0xB9, 0xE3,0x83,0x88, 0xEF,0xB8,0x92, 0xEF,0xB9,0x82, 0x0}; -static const size_t gLen = sizeof(gText) - 1; +static const size_t gLen = sizeof(gText) - sizeof(gText[0]); class VertTextGM : public GM { public: @@ -70,8 +70,8 @@ protected: p.setColor(0xFF0000FF); SkScalar adv[gLen]; - paint.getTextWidths(gText, gLen, adv, NULL); - for (size_t i = 0; i < gLen; ++i) { + int numChars = paint.getTextWidths(gText, gLen, adv, NULL); + for (int i = 0; i < numChars; ++i) { canvas->drawCircle(x, y, SK_Scalar1 * 3 / 2, p); if (paint.isVerticalText()) { y += adv[i]; diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp index 68210ba46..56dbca6fb 100755 --- a/src/ports/SkFontHost_win.cpp +++ b/src/ports/SkFontHost_win.cpp @@ -812,13 +812,33 @@ unsigned SkScalerContext_GDI::generateGlyphCount() { return fGlyphCount; } -uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar uni) { +uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar utf32) { uint16_t index = 0; - WCHAR c[2]; + WCHAR utf16[2]; // TODO(ctguil): Support characters that generate more than one glyph. - if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) { + if (SkUTF16_FromUnichar(utf32, (uint16_t*)utf16) == 1) { // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0. - SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0)); + + /** Real documentation for GetGlyphIndiciesW: + * + * When GGI_MARK_NONEXISTING_GLYPHS is not specified and a character does not map to a + * glyph, then the 'default character's glyph is returned instead. The 'default character' + * is available in fTM.tmDefaultChar. FON fonts have adefault character, and there exists a + * usDefaultChar in the 'OS/2' table, version 2 and later. If there is no + * 'default character' specified by the font, then often the first character found is used. + * + * When GGI_MARK_NONEXISTING_GLYPHS is specified and a character does not map to a glyph, + * then the glyph 0xFFFF is used. In Windows XP and earlier, Bitmap/Vector FON usually use + * glyph 0x1F instead ('Terminal' appears to be special, returning 0xFFFF). + * Type1 PFM/PFB, TT, OT TT, OT CFF all appear to use 0xFFFF, even on XP. + */ + DWORD result = GetGlyphIndicesW(fDDC, utf16, 1, &index, GGI_MARK_NONEXISTING_GLYPHS); + if (result == GDI_ERROR + || 0xFFFF == index + || (0x1F == index && fType == SkScalerContext_GDI::kBitmap_Type /*&& winVer < Vista */)) + { + 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 @@ -826,13 +846,13 @@ uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar uni) { SCRIPT_ITEM si[2 + 1]; int items; SkAssertResult( - SUCCEEDED(ScriptItemize(c, 2, 2, NULL, NULL, si, &items))); + SUCCEEDED(ScriptItemize(utf16, 2, 2, NULL, NULL, si, &items))); WORD log[2]; SCRIPT_VISATTR vsa; int glyphs; SkAssertResult(SUCCEEDED(ScriptShape( - fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs))); + fDDC, &fSC, utf16, 2, 1, &si[0].a, &index, log, &vsa, &glyphs))); } return index; }