Home | History | Annotate | Download | only in ports
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #include "SkAdvancedTypefaceMetrics.h"
     10 #include "SkBase64.h"
     11 #include "SkColorPriv.h"
     12 #include "SkData.h"
     13 #include "SkDescriptor.h"
     14 #include "SkFontDescriptor.h"
     15 #include "SkFontHost.h"
     16 #include "SkGlyph.h"
     17 #include "SkHRESULT.h"
     18 #include "SkMaskGamma.h"
     19 #include "SkOTTable_maxp.h"
     20 #include "SkOTTable_name.h"
     21 #include "SkOTUtils.h"
     22 #include "SkPath.h"
     23 #include "SkSFNTHeader.h"
     24 #include "SkStream.h"
     25 #include "SkString.h"
     26 #include "SkTemplates.h"
     27 #include "SkThread.h"
     28 #include "SkTypeface_win.h"
     29 #include "SkTypefaceCache.h"
     30 #include "SkUtils.h"
     31 
     32 #include "SkTypes.h"
     33 #include <tchar.h>
     34 #include <usp10.h>
     35 #include <objbase.h>
     36 
     37 static void (*gEnsureLOGFONTAccessibleProc)(const LOGFONT&);
     38 
     39 void SkTypeface_SetEnsureLOGFONTAccessibleProc(void (*proc)(const LOGFONT&)) {
     40     gEnsureLOGFONTAccessibleProc = proc;
     41 }
     42 
     43 static void call_ensure_accessible(const LOGFONT& lf) {
     44     if (gEnsureLOGFONTAccessibleProc) {
     45         gEnsureLOGFONTAccessibleProc(lf);
     46     }
     47 }
     48 
     49 ///////////////////////////////////////////////////////////////////////////////
     50 
     51 // always packed xxRRGGBB
     52 typedef uint32_t SkGdiRGB;
     53 
     54 // define this in your Makefile or .gyp to enforce AA requests
     55 // which GDI ignores at small sizes. This flag guarantees AA
     56 // for rotated text, regardless of GDI's notions.
     57 //#define SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
     58 
     59 static bool isLCD(const SkScalerContext::Rec& rec) {
     60     return SkMask::kLCD16_Format == rec.fMaskFormat ||
     61            SkMask::kLCD32_Format == rec.fMaskFormat;
     62 }
     63 
     64 static bool bothZero(SkScalar a, SkScalar b) {
     65     return 0 == a && 0 == b;
     66 }
     67 
     68 // returns false if there is any non-90-rotation or skew
     69 static bool isAxisAligned(const SkScalerContext::Rec& rec) {
     70     return 0 == rec.fPreSkewX &&
     71            (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
     72             bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
     73 }
     74 
     75 static bool needToRenderWithSkia(const SkScalerContext::Rec& rec) {
     76 #ifdef SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
     77     // What we really want to catch is when GDI will ignore the AA request and give
     78     // us BW instead. Smallish rotated text is one heuristic, so this code is just
     79     // an approximation. We shouldn't need to do this for larger sizes, but at those
     80     // sizes, the quality difference gets less and less between our general
     81     // scanconverter and GDI's.
     82     if (SkMask::kA8_Format == rec.fMaskFormat && !isAxisAligned(rec)) {
     83         return true;
     84     }
     85 #endif
     86     return rec.getHinting() == SkPaint::kNo_Hinting || rec.getHinting() == SkPaint::kSlight_Hinting;
     87 }
     88 
     89 using namespace skia_advanced_typeface_metrics_utils;
     90 
     91 static void tchar_to_skstring(const TCHAR t[], SkString* s) {
     92 #ifdef UNICODE
     93     size_t sSize = WideCharToMultiByte(CP_UTF8, 0, t, -1, NULL, 0, NULL, NULL);
     94     s->resize(sSize);
     95     WideCharToMultiByte(CP_UTF8, 0, t, -1, s->writable_str(), sSize, NULL, NULL);
     96 #else
     97     s->set(t);
     98 #endif
     99 }
    100 
    101 static void dcfontname_to_skstring(HDC deviceContext, const LOGFONT& lf, SkString* familyName) {
    102     int fontNameLen; //length of fontName in TCHARS.
    103     if (0 == (fontNameLen = GetTextFace(deviceContext, 0, NULL))) {
    104         call_ensure_accessible(lf);
    105         if (0 == (fontNameLen = GetTextFace(deviceContext, 0, NULL))) {
    106             fontNameLen = 0;
    107         }
    108     }
    109 
    110     SkAutoSTArray<LF_FULLFACESIZE, TCHAR> fontName(fontNameLen+1);
    111     if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) {
    112         call_ensure_accessible(lf);
    113         if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) {
    114             fontName[0] = 0;
    115         }
    116     }
    117 
    118     tchar_to_skstring(fontName.get(), familyName);
    119 }
    120 
    121 static void make_canonical(LOGFONT* lf) {
    122     lf->lfHeight = -64;
    123     lf->lfQuality = CLEARTYPE_QUALITY;//PROOF_QUALITY;
    124     lf->lfCharSet = DEFAULT_CHARSET;
    125 //    lf->lfClipPrecision = 64;
    126 }
    127 
    128 static SkTypeface::Style get_style(const LOGFONT& lf) {
    129     unsigned style = 0;
    130     if (lf.lfWeight >= FW_BOLD) {
    131         style |= SkTypeface::kBold;
    132     }
    133     if (lf.lfItalic) {
    134         style |= SkTypeface::kItalic;
    135     }
    136     return static_cast<SkTypeface::Style>(style);
    137 }
    138 
    139 static void setStyle(LOGFONT* lf, SkTypeface::Style style) {
    140     lf->lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
    141     lf->lfItalic = ((style & SkTypeface::kItalic) != 0);
    142 }
    143 
    144 static inline FIXED SkFixedToFIXED(SkFixed x) {
    145     return *(FIXED*)(&x);
    146 }
    147 static inline SkFixed SkFIXEDToFixed(FIXED x) {
    148     return *(SkFixed*)(&x);
    149 }
    150 
    151 static inline FIXED SkScalarToFIXED(SkScalar x) {
    152     return SkFixedToFIXED(SkScalarToFixed(x));
    153 }
    154 
    155 static unsigned calculateGlyphCount(HDC hdc, const LOGFONT& lf) {
    156     TEXTMETRIC textMetric;
    157     if (0 == GetTextMetrics(hdc, &textMetric)) {
    158         textMetric.tmPitchAndFamily = TMPF_VECTOR;
    159         call_ensure_accessible(lf);
    160         GetTextMetrics(hdc, &textMetric);
    161     }
    162 
    163     if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) {
    164         return textMetric.tmLastChar;
    165     }
    166 
    167     // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes.
    168     uint16_t glyphs;
    169     if (GDI_ERROR != GetFontData(hdc, SkOTTableMaximumProfile::TAG, 4, &glyphs, sizeof(glyphs))) {
    170         return SkEndian_SwapBE16(glyphs);
    171     }
    172 
    173     // Binary search for glyph count.
    174     static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
    175     int32_t max = SK_MaxU16 + 1;
    176     int32_t min = 0;
    177     GLYPHMETRICS gm;
    178     while (min < max) {
    179         int32_t mid = min + ((max - min) / 2);
    180         if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0,
    181                              NULL, &mat2) == GDI_ERROR) {
    182             max = mid;
    183         } else {
    184             min = mid + 1;
    185         }
    186     }
    187     SkASSERT(min == max);
    188     return min;
    189 }
    190 
    191 static unsigned calculateUPEM(HDC hdc, const LOGFONT& lf) {
    192     TEXTMETRIC textMetric;
    193     if (0 == GetTextMetrics(hdc, &textMetric)) {
    194         textMetric.tmPitchAndFamily = TMPF_VECTOR;
    195         call_ensure_accessible(lf);
    196         GetTextMetrics(hdc, &textMetric);
    197     }
    198 
    199     if (!(textMetric.tmPitchAndFamily & TMPF_VECTOR)) {
    200         return textMetric.tmMaxCharWidth;
    201     }
    202 
    203     OUTLINETEXTMETRIC otm;
    204     unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
    205     if (0 == otmRet) {
    206         call_ensure_accessible(lf);
    207         otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
    208     }
    209 
    210     return (0 == otmRet) ? 0 : otm.otmEMSquare;
    211 }
    212 
    213 class LogFontTypeface : public SkTypeface {
    214 public:
    215     LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, bool serializeAsStream = false) :
    216         SkTypeface(style, fontID, false), fLogFont(lf), fSerializeAsStream(serializeAsStream) {
    217 
    218         // If the font has cubic outlines, it will not be rendered with ClearType.
    219         HFONT font = CreateFontIndirect(&lf);
    220 
    221         HDC deviceContext = ::CreateCompatibleDC(NULL);
    222         HFONT savefont = (HFONT)SelectObject(deviceContext, font);
    223 
    224         TEXTMETRIC textMetric;
    225         if (0 == GetTextMetrics(deviceContext, &textMetric)) {
    226             call_ensure_accessible(lf);
    227             if (0 == GetTextMetrics(deviceContext, &textMetric)) {
    228                 textMetric.tmPitchAndFamily = TMPF_TRUETYPE;
    229             }
    230         }
    231         if (deviceContext) {
    232             ::SelectObject(deviceContext, savefont);
    233             ::DeleteDC(deviceContext);
    234         }
    235         if (font) {
    236             ::DeleteObject(font);
    237         }
    238 
    239         // The fixed pitch bit is set if the font is *not* fixed pitch.
    240         this->setIsFixedPitch((textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
    241 
    242         // Used a logfont on a memory context, should never get a device font.
    243         // Therefore all TMPF_DEVICE will be PostScript (cubic) fonts.
    244         fCanBeLCD = !((textMetric.tmPitchAndFamily & TMPF_VECTOR) &&
    245                       (textMetric.tmPitchAndFamily & TMPF_DEVICE));
    246     }
    247 
    248     LOGFONT fLogFont;
    249     bool fSerializeAsStream;
    250     bool fCanBeLCD;
    251 
    252     static LogFontTypeface* Create(const LOGFONT& lf) {
    253         SkTypeface::Style style = get_style(lf);
    254         SkFontID fontID = SkTypefaceCache::NewFontID();
    255         return new LogFontTypeface(style, fontID, lf);
    256     }
    257 
    258     static void EnsureAccessible(const SkTypeface* face) {
    259         call_ensure_accessible(static_cast<const LogFontTypeface*>(face)->fLogFont);
    260     }
    261 
    262 protected:
    263     virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
    264     virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
    265     virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
    266     virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
    267                                 SkAdvancedTypefaceMetrics::PerGlyphInfo,
    268                                 const uint32_t*, uint32_t) const SK_OVERRIDE;
    269     virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
    270     virtual int onCharsToGlyphs(const void* chars, Encoding encoding,
    271                                 uint16_t glyphs[], int glyphCount) const SK_OVERRIDE;
    272     virtual int onCountGlyphs() const SK_OVERRIDE;
    273     virtual int onGetUPEM() const SK_OVERRIDE;
    274     virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
    275     virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
    276     virtual size_t onGetTableData(SkFontTableTag, size_t offset,
    277                                   size_t length, void* data) const SK_OVERRIDE;
    278 };
    279 
    280 class FontMemResourceTypeface : public LogFontTypeface {
    281 public:
    282     /**
    283      *  Takes ownership of fontMemResource.
    284      */
    285     FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) :
    286         LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) {
    287     }
    288 
    289     HANDLE fFontMemResource;
    290 
    291     /**
    292      *  The created FontMemResourceTypeface takes ownership of fontMemResource.
    293      */
    294     static FontMemResourceTypeface* Create(const LOGFONT& lf, HANDLE fontMemResource) {
    295         SkTypeface::Style style = get_style(lf);
    296         SkFontID fontID = SkTypefaceCache::NewFontID();
    297         return new FontMemResourceTypeface(style, fontID, lf, fontMemResource);
    298     }
    299 
    300 protected:
    301     virtual void weak_dispose() const SK_OVERRIDE {
    302         RemoveFontMemResourceEx(fFontMemResource);
    303         //SkTypefaceCache::Remove(this);
    304         INHERITED::weak_dispose();
    305     }
    306 
    307 private:
    308     typedef LogFontTypeface INHERITED;
    309 };
    310 
    311 static const LOGFONT& get_default_font() {
    312     static LOGFONT gDefaultFont;
    313     return gDefaultFont;
    314 }
    315 
    316 static bool FindByLogFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
    317     LogFontTypeface* lface = static_cast<LogFontTypeface*>(face);
    318     const LOGFONT* lf = reinterpret_cast<const LOGFONT*>(ctx);
    319 
    320     return lface &&
    321            get_style(lface->fLogFont) == requestedStyle &&
    322            !memcmp(&lface->fLogFont, lf, sizeof(LOGFONT));
    323 }
    324 
    325 /**
    326  *  This guy is public. It first searches the cache, and if a match is not found,
    327  *  it creates a new face.
    328  */
    329 SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) {
    330     LOGFONT lf = origLF;
    331     make_canonical(&lf);
    332     SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf);
    333     if (NULL == face) {
    334         face = LogFontTypeface::Create(lf);
    335         SkTypefaceCache::Add(face, get_style(lf));
    336     }
    337     return face;
    338 }
    339 
    340 /**
    341  *  The created SkTypeface takes ownership of fontMemResource.
    342  */
    343 SkTypeface* SkCreateFontMemResourceTypefaceFromLOGFONT(const LOGFONT& origLF, HANDLE fontMemResource) {
    344     LOGFONT lf = origLF;
    345     make_canonical(&lf);
    346     FontMemResourceTypeface* face = FontMemResourceTypeface::Create(lf, fontMemResource);
    347     SkTypefaceCache::Add(face, get_style(lf), false);
    348     return face;
    349 }
    350 
    351 /**
    352  *  This guy is public
    353  */
    354 void SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) {
    355     if (NULL == face) {
    356         *lf = get_default_font();
    357     } else {
    358         *lf = static_cast<const LogFontTypeface*>(face)->fLogFont;
    359     }
    360 }
    361 
    362 // Construct Glyph to Unicode table.
    363 // Unicode code points that require conjugate pairs in utf16 are not
    364 // supported.
    365 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
    366 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
    367 // of calling GetFontUnicodeRange().
    368 static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount,
    369                                       SkTDArray<SkUnichar>* glyphToUnicode) {
    370     DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, NULL);
    371     if (!glyphSetBufferSize) {
    372         return;
    373     }
    374 
    375     SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]);
    376     GLYPHSET* glyphSet =
    377         reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get());
    378     if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) {
    379         return;
    380     }
    381 
    382     glyphToUnicode->setCount(glyphCount);
    383     memset(glyphToUnicode->begin(), 0, glyphCount * sizeof(SkUnichar));
    384     for (DWORD i = 0; i < glyphSet->cRanges; ++i) {
    385         // There is no guarantee that within a Unicode range, the corresponding
    386         // glyph id in a font file are continuous. So, even if we have ranges,
    387         // we can't just use the first and last entry of the range to compute
    388         // result. We need to enumerate them one by one.
    389         int count = glyphSet->ranges[i].cGlyphs;
    390         SkAutoTArray<WCHAR> chars(count + 1);
    391         chars[count] = 0;  // termintate string
    392         SkAutoTArray<WORD> glyph(count);
    393         for (USHORT j = 0; j < count; ++j) {
    394             chars[j] = glyphSet->ranges[i].wcLow + j;
    395         }
    396         GetGlyphIndicesW(fontHdc, chars.get(), count, glyph.get(),
    397                          GGI_MARK_NONEXISTING_GLYPHS);
    398         // If the glyph ID is valid, and the glyph is not mapped, then we will
    399         // fill in the char id into the vector. If the glyph is mapped already,
    400         // skip it.
    401         // TODO(arthurhsu): better improve this. e.g. Get all used char ids from
    402         // font cache, then generate this mapping table from there. It's
    403         // unlikely to have collisions since glyph reuse happens mostly for
    404         // different Unicode pages.
    405         for (USHORT j = 0; j < count; ++j) {
    406             if (glyph[j] != 0xffff && glyph[j] < glyphCount &&
    407                 (*glyphToUnicode)[glyph[j]] == 0) {
    408                 (*glyphToUnicode)[glyph[j]] = chars[j];
    409             }
    410         }
    411     }
    412 }
    413 
    414 //////////////////////////////////////////////////////////////////////////////////////
    415 
    416 static int alignTo32(int n) {
    417     return (n + 31) & ~31;
    418 }
    419 
    420 struct MyBitmapInfo : public BITMAPINFO {
    421     RGBQUAD fMoreSpaceForColors[1];
    422 };
    423 
    424 class HDCOffscreen {
    425 public:
    426     HDCOffscreen() {
    427         fFont = 0;
    428         fDC = 0;
    429         fBM = 0;
    430         fBits = NULL;
    431         fWidth = fHeight = 0;
    432         fIsBW = false;
    433     }
    434 
    435     ~HDCOffscreen() {
    436         if (fDC) {
    437             DeleteDC(fDC);
    438         }
    439         if (fBM) {
    440             DeleteObject(fBM);
    441         }
    442     }
    443 
    444     void init(HFONT font, const XFORM& xform) {
    445         fFont = font;
    446         fXform = xform;
    447     }
    448 
    449     const void* draw(const SkGlyph&, bool isBW, size_t* srcRBPtr);
    450 
    451 private:
    452     HDC     fDC;
    453     HBITMAP fBM;
    454     HFONT   fFont;
    455     XFORM   fXform;
    456     void*   fBits;  // points into fBM
    457     int     fWidth;
    458     int     fHeight;
    459     bool    fIsBW;
    460 };
    461 
    462 const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW,
    463                                size_t* srcRBPtr) {
    464     // Can we share the scalercontext's fDDC, so we don't need to create
    465     // a separate fDC here?
    466     if (0 == fDC) {
    467         fDC = CreateCompatibleDC(0);
    468         if (0 == fDC) {
    469             return NULL;
    470         }
    471         SetGraphicsMode(fDC, GM_ADVANCED);
    472         SetBkMode(fDC, TRANSPARENT);
    473         SetTextAlign(fDC, TA_LEFT | TA_BASELINE);
    474         SelectObject(fDC, fFont);
    475 
    476         COLORREF color = 0x00FFFFFF;
    477         SkDEBUGCODE(COLORREF prev =) SetTextColor(fDC, color);
    478         SkASSERT(prev != CLR_INVALID);
    479     }
    480 
    481     if (fBM && (fIsBW != isBW || fWidth < glyph.fWidth || fHeight < glyph.fHeight)) {
    482         DeleteObject(fBM);
    483         fBM = 0;
    484     }
    485     fIsBW = isBW;
    486 
    487     fWidth = SkMax32(fWidth, glyph.fWidth);
    488     fHeight = SkMax32(fHeight, glyph.fHeight);
    489 
    490     int biWidth = isBW ? alignTo32(fWidth) : fWidth;
    491 
    492     if (0 == fBM) {
    493         MyBitmapInfo info;
    494         sk_bzero(&info, sizeof(info));
    495         if (isBW) {
    496             RGBQUAD blackQuad = { 0, 0, 0, 0 };
    497             RGBQUAD whiteQuad = { 0xFF, 0xFF, 0xFF, 0 };
    498             info.bmiColors[0] = blackQuad;
    499             info.bmiColors[1] = whiteQuad;
    500         }
    501         info.bmiHeader.biSize = sizeof(info.bmiHeader);
    502         info.bmiHeader.biWidth = biWidth;
    503         info.bmiHeader.biHeight = fHeight;
    504         info.bmiHeader.biPlanes = 1;
    505         info.bmiHeader.biBitCount = isBW ? 1 : 32;
    506         info.bmiHeader.biCompression = BI_RGB;
    507         if (isBW) {
    508             info.bmiHeader.biClrUsed = 2;
    509         }
    510         fBM = CreateDIBSection(fDC, &info, DIB_RGB_COLORS, &fBits, 0, 0);
    511         if (0 == fBM) {
    512             return NULL;
    513         }
    514         SelectObject(fDC, fBM);
    515     }
    516 
    517     // erase
    518     size_t srcRB = isBW ? (biWidth >> 3) : (fWidth << 2);
    519     size_t size = fHeight * srcRB;
    520     memset(fBits, 0, size);
    521 
    522     XFORM xform = fXform;
    523     xform.eDx = (float)-glyph.fLeft;
    524     xform.eDy = (float)-glyph.fTop;
    525     SetWorldTransform(fDC, &xform);
    526 
    527     uint16_t glyphID = glyph.getGlyphID();
    528     BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, NULL, reinterpret_cast<LPCWSTR>(&glyphID), 1, NULL);
    529     GdiFlush();
    530     if (0 == ret) {
    531         return NULL;
    532     }
    533     *srcRBPtr = srcRB;
    534     // offset to the start of the image
    535     return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB;
    536 }
    537 
    538 //////////////////////////////////////////////////////////////////////////////
    539 #define BUFFERSIZE (1 << 13)
    540 
    541 class SkScalerContext_GDI : public SkScalerContext {
    542 public:
    543     SkScalerContext_GDI(SkTypeface*, const SkDescriptor* desc);
    544     virtual ~SkScalerContext_GDI();
    545 
    546     // Returns true if the constructor was able to complete all of its
    547     // initializations (which may include calling GDI).
    548     bool isValid() const;
    549 
    550 protected:
    551     virtual unsigned generateGlyphCount() SK_OVERRIDE;
    552     virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
    553     virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
    554     virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
    555     virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
    556     virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
    557     virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
    558                                      SkPaint::FontMetrics* mY) SK_OVERRIDE;
    559 
    560 private:
    561     DWORD getGDIGlyphPath(const SkGlyph& glyph, UINT flags,
    562                           SkAutoSTMalloc<BUFFERSIZE, uint8_t>* glyphbuf);
    563 
    564     HDCOffscreen fOffscreen;
    565     /** fGsA is the non-rotational part of total matrix without the text height scale.
    566      *  Used to find the magnitude of advances.
    567      */
    568     MAT2         fGsA;
    569     /** The total matrix without the textSize. */
    570     MAT2         fMat22;
    571     /** Scales font to EM size. */
    572     MAT2         fHighResMat22;
    573     HDC          fDDC;
    574     HFONT        fSavefont;
    575     HFONT        fFont;
    576     SCRIPT_CACHE fSC;
    577     int          fGlyphCount;
    578 
    579     /** The total matrix which also removes EM scale. */
    580     SkMatrix     fHiResMatrix;
    581     /** fG_inv is the inverse of the rotational part of the total matrix.
    582      *  Used to set the direction of advances.
    583      */
    584     SkMatrix     fG_inv;
    585     enum Type {
    586         kTrueType_Type, kBitmap_Type,
    587     } fType;
    588     TEXTMETRIC fTM;
    589 };
    590 
    591 static FIXED float2FIXED(float x) {
    592     return SkFixedToFIXED(SkFloatToFixed(x));
    593 }
    594 
    595 static BYTE compute_quality(const SkScalerContext::Rec& rec) {
    596     switch (rec.fMaskFormat) {
    597         case SkMask::kBW_Format:
    598             return NONANTIALIASED_QUALITY;
    599         case SkMask::kLCD16_Format:
    600         case SkMask::kLCD32_Format:
    601             return CLEARTYPE_QUALITY;
    602         default:
    603             if (rec.fFlags & SkScalerContext::kGenA8FromLCD_Flag) {
    604                 return CLEARTYPE_QUALITY;
    605             } else {
    606                 return ANTIALIASED_QUALITY;
    607             }
    608     }
    609 }
    610 
    611 SkScalerContext_GDI::SkScalerContext_GDI(SkTypeface* rawTypeface,
    612                                                  const SkDescriptor* desc)
    613         : SkScalerContext(rawTypeface, desc)
    614         , fDDC(0)
    615         , fSavefont(0)
    616         , fFont(0)
    617         , fSC(0)
    618         , fGlyphCount(-1)
    619 {
    620     LogFontTypeface* typeface = reinterpret_cast<LogFontTypeface*>(rawTypeface);
    621 
    622     fDDC = ::CreateCompatibleDC(NULL);
    623     if (!fDDC) {
    624         return;
    625     }
    626     SetGraphicsMode(fDDC, GM_ADVANCED);
    627     SetBkMode(fDDC, TRANSPARENT);
    628 
    629     SkPoint h = SkPoint::Make(SK_Scalar1, 0);
    630     // A is the total matrix.
    631     SkMatrix A;
    632     fRec.getSingleMatrix(&A);
    633     A.mapPoints(&h, 1);
    634 
    635     // Find the Given's matrix [[c, -s],[s, c]] which rotates the baseline vector h
    636     // (where the baseline is mapped to) to the positive horizontal axis.
    637     const SkScalar& a = h.fX;
    638     const SkScalar& b = h.fY;
    639     SkScalar c, s;
    640     if (0 == b) {
    641         c = SkDoubleToScalar(_copysign(SK_Scalar1, a));
    642         s = 0;
    643     } else if (0 == a) {
    644         c = 0;
    645         s = SkDoubleToScalar(-_copysign(SK_Scalar1, b));
    646     } else if (SkScalarAbs(b) > SkScalarAbs(a)) {
    647         SkScalar t = a / b;
    648         SkScalar u = SkDoubleToScalar(_copysign(SkScalarSqrt(SK_Scalar1 + t*t), b));
    649         s = -1 / u;
    650         c = -s * t;
    651     } else {
    652         SkScalar t = b / a;
    653         SkScalar u = SkDoubleToScalar(_copysign(SkScalarSqrt(SK_Scalar1 + t*t), a));
    654         c = 1 / u;
    655         s = -c * t;
    656     }
    657 
    658     // G is the Given's Matrix for A (rotational matrix such that GA[0][1] == 0).
    659     SkMatrix G;
    660     G.setAll(c, -s, 0,
    661              s,  c, 0,
    662              0,  0, SkScalarToPersp(SK_Scalar1));
    663 
    664     // GA is the matrix A with rotation removed.
    665     SkMatrix GA(G);
    666     GA.preConcat(A);
    667 
    668     // realTextSize is the actual device size we want (as opposed to the size the user requested).
    669     // gdiTextSide is the size we request from GDI.
    670     // If the scale is negative, this means the matrix will do the flip anyway.
    671     SkScalar realTextSize = SkScalarAbs(GA.get(SkMatrix::kMScaleY));
    672     SkScalar gdiTextSize = SkScalarRoundToScalar(realTextSize);
    673     if (gdiTextSize == 0) {
    674         gdiTextSize = SK_Scalar1;
    675     }
    676 
    677     // When not hinting, remove only the gdiTextSize scale which will be applied by GDI.
    678     // When GDI hinting, remove the entire Y scale to prevent 'subpixel' metrics.
    679     SkScalar scale = (fRec.getHinting() == SkPaint::kNo_Hinting ||
    680                       fRec.getHinting() == SkPaint::kSlight_Hinting)
    681                    ? SkScalarInvert(gdiTextSize)
    682                    : SkScalarInvert(realTextSize);
    683 
    684     // sA is the total matrix A without the textSize (so GDI knows the text size separately).
    685     // When this matrix is used with GetGlyphOutline, no further processing is needed.
    686     SkMatrix sA(A);
    687     sA.preScale(scale, scale); //remove text size
    688 
    689     // GsA is the non-rotational part of A without the text height scale.
    690     // This is what is used to find the magnitude of advances.
    691     SkMatrix GsA(GA);
    692     GsA.preScale(scale, scale); //remove text size, G is rotational so reorders with the scale.
    693 
    694     fGsA.eM11 = SkScalarToFIXED(GsA.get(SkMatrix::kMScaleX));
    695     fGsA.eM12 = SkScalarToFIXED(-GsA.get(SkMatrix::kMSkewY)); // This should be ~0.
    696     fGsA.eM21 = SkScalarToFIXED(-GsA.get(SkMatrix::kMSkewX));
    697     fGsA.eM22 = SkScalarToFIXED(GsA.get(SkMatrix::kMScaleY));
    698 
    699     // fG_inv is G inverse, which is fairly simple since G is 2x2 rotational.
    700     fG_inv.setAll(G.get(SkMatrix::kMScaleX), -G.get(SkMatrix::kMSkewX), G.get(SkMatrix::kMTransX),
    701                   -G.get(SkMatrix::kMSkewY), G.get(SkMatrix::kMScaleY), G.get(SkMatrix::kMTransY),
    702                   G.get(SkMatrix::kMPersp0), G.get(SkMatrix::kMPersp1), G.get(SkMatrix::kMPersp2));
    703 
    704     LOGFONT lf = typeface->fLogFont;
    705     lf.lfHeight = -SkScalarTruncToInt(gdiTextSize);
    706     lf.lfQuality = compute_quality(fRec);
    707     fFont = CreateFontIndirect(&lf);
    708     if (!fFont) {
    709         return;
    710     }
    711 
    712     fSavefont = (HFONT)SelectObject(fDDC, fFont);
    713 
    714     if (0 == GetTextMetrics(fDDC, &fTM)) {
    715         call_ensure_accessible(lf);
    716         if (0 == GetTextMetrics(fDDC, &fTM)) {
    717             fTM.tmPitchAndFamily = TMPF_TRUETYPE;
    718         }
    719     }
    720     // Used a logfont on a memory context, should never get a device font.
    721     // Therefore all TMPF_DEVICE will be PostScript fonts.
    722 
    723     // If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE must be set,
    724     // otherwise we have a vector FON, which we don't support.
    725     // This was determined by testing with Type1 PFM/PFB and OpenTypeCFF OTF,
    726     // as well as looking at Wine bugs and sources.
    727     SkASSERT(!(fTM.tmPitchAndFamily & TMPF_VECTOR) ||
    728               (fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE)));
    729 
    730     XFORM xform;
    731     if (fTM.tmPitchAndFamily & TMPF_VECTOR) {
    732         // Truetype or PostScript.
    733         // Stroked FON also gets here (TMPF_VECTOR), but we don't handle it.
    734         fType = SkScalerContext_GDI::kTrueType_Type;
    735 
    736         // fPost2x2 is column-major, left handed (y down).
    737         // XFORM 2x2 is row-major, left handed (y down).
    738         xform.eM11 = SkScalarToFloat(sA.get(SkMatrix::kMScaleX));
    739         xform.eM12 = SkScalarToFloat(sA.get(SkMatrix::kMSkewY));
    740         xform.eM21 = SkScalarToFloat(sA.get(SkMatrix::kMSkewX));
    741         xform.eM22 = SkScalarToFloat(sA.get(SkMatrix::kMScaleY));
    742         xform.eDx = 0;
    743         xform.eDy = 0;
    744 
    745         // MAT2 is row major, right handed (y up).
    746         fMat22.eM11 = float2FIXED(xform.eM11);
    747         fMat22.eM12 = float2FIXED(-xform.eM12);
    748         fMat22.eM21 = float2FIXED(-xform.eM21);
    749         fMat22.eM22 = float2FIXED(xform.eM22);
    750 
    751         if (needToRenderWithSkia(fRec)) {
    752             this->forceGenerateImageFromPath();
    753         }
    754 
    755         // Create a hires matrix if we need linear metrics.
    756         if (this->isSubpixel()) {
    757             OUTLINETEXTMETRIC otm;
    758             UINT success = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    759             if (0 == success) {
    760                 call_ensure_accessible(lf);
    761                 success = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
    762             }
    763             if (0 != success) {
    764                 SkScalar upem = SkIntToScalar(otm.otmEMSquare);
    765 
    766                 SkScalar gdiTextSizeToEMScale = upem / gdiTextSize;
    767                 fHighResMat22.eM11 = float2FIXED(gdiTextSizeToEMScale);
    768                 fHighResMat22.eM12 = float2FIXED(0);
    769                 fHighResMat22.eM21 = float2FIXED(0);
    770                 fHighResMat22.eM22 = float2FIXED(gdiTextSizeToEMScale);
    771 
    772                 SkScalar removeEMScale = SkScalarInvert(upem);
    773                 fHiResMatrix = A;
    774                 fHiResMatrix.preScale(removeEMScale, removeEMScale);
    775             }
    776         }
    777 
    778     } else {
    779         // Assume bitmap
    780         fType = SkScalerContext_GDI::kBitmap_Type;
    781 
    782         xform.eM11 = 1.0f;
    783         xform.eM12 = 0.0f;
    784         xform.eM21 = 0.0f;
    785         xform.eM22 = 1.0f;
    786         xform.eDx = 0.0f;
    787         xform.eDy = 0.0f;
    788 
    789         // fPost2x2 is column-major, left handed (y down).
    790         // MAT2 is row major, right handed (y up).
    791         fMat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);
    792         fMat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[1][0]);
    793         fMat22.eM21 = SkScalarToFIXED(-fRec.fPost2x2[0][1]);
    794         fMat22.eM22 = SkScalarToFIXED(fRec.fPost2x2[1][1]);
    795     }
    796 
    797     fOffscreen.init(fFont, xform);
    798 }
    799 
    800 SkScalerContext_GDI::~SkScalerContext_GDI() {
    801     if (fDDC) {
    802         ::SelectObject(fDDC, fSavefont);
    803         ::DeleteDC(fDDC);
    804     }
    805     if (fFont) {
    806         ::DeleteObject(fFont);
    807     }
    808     if (fSC) {
    809         ::ScriptFreeCache(&fSC);
    810     }
    811 }
    812 
    813 bool SkScalerContext_GDI::isValid() const {
    814     return fDDC && fFont;
    815 }
    816 
    817 unsigned SkScalerContext_GDI::generateGlyphCount() {
    818     if (fGlyphCount < 0) {
    819         fGlyphCount = calculateGlyphCount(
    820                           fDDC, static_cast<const LogFontTypeface*>(this->getTypeface())->fLogFont);
    821     }
    822     return fGlyphCount;
    823 }
    824 
    825 uint16_t SkScalerContext_GDI::generateCharToGlyph(SkUnichar utf32) {
    826     uint16_t index = 0;
    827     WCHAR utf16[2];
    828     // TODO(ctguil): Support characters that generate more than one glyph.
    829     if (SkUTF16_FromUnichar(utf32, (uint16_t*)utf16) == 1) {
    830         // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0.
    831 
    832         /** Real documentation for GetGlyphIndiciesW:
    833          *
    834          *  When GGI_MARK_NONEXISTING_GLYPHS is not specified and a character does not map to a
    835          *  glyph, then the 'default character's glyph is returned instead. The 'default character'
    836          *  is available in fTM.tmDefaultChar. FON fonts have adefault character, and there exists a
    837          *  usDefaultChar in the 'OS/2' table, version 2 and later. If there is no
    838          *  'default character' specified by the font, then often the first character found is used.
    839          *
    840          *  When GGI_MARK_NONEXISTING_GLYPHS is specified and a character does not map to a glyph,
    841          *  then the glyph 0xFFFF is used. In Windows XP and earlier, Bitmap/Vector FON usually use
    842          *  glyph 0x1F instead ('Terminal' appears to be special, returning 0xFFFF).
    843          *  Type1 PFM/PFB, TT, OT TT, OT CFF all appear to use 0xFFFF, even on XP.
    844          */
    845         DWORD result = GetGlyphIndicesW(fDDC, utf16, 1, &index, GGI_MARK_NONEXISTING_GLYPHS);
    846         if (result == GDI_ERROR
    847             || 0xFFFF == index
    848             || (0x1F == index && fType == SkScalerContext_GDI::kBitmap_Type /*&& winVer < Vista */))
    849         {
    850             index = 0;
    851         }
    852     } else {
    853         // Use uniscribe to detemine glyph index for non-BMP characters.
    854         static const int numWCHAR = 2;
    855         static const int maxItems = 2;
    856         // MSDN states that this can be NULL, but some things don't work then.
    857         SCRIPT_CONTROL sc = { 0 };
    858         // Add extra item to SCRIPT_ITEM to work around a bug (now documented).
    859         // https://bugzilla.mozilla.org/show_bug.cgi?id=366643
    860         SCRIPT_ITEM si[maxItems + 1];
    861         int numItems;
    862         HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &sc, NULL, si, &numItems),
    863              "Could not itemize character.");
    864 
    865         // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2 space glyphs.
    866         static const int maxGlyphs = 2;
    867         SCRIPT_VISATTR vsa[maxGlyphs];
    868         WORD outGlyphs[maxGlyphs];
    869         WORD logClust[numWCHAR];
    870         int numGlyphs;
    871         HRZM(ScriptShape(fDDC, &fSC, utf16, numWCHAR, maxGlyphs, &si[0].a,
    872                          outGlyphs, logClust, vsa, &numGlyphs),
    873              "Could not shape character.");
    874         if (1 == numGlyphs) {
    875             index = outGlyphs[0];
    876         }
    877     }
    878     return index;
    879 }
    880 
    881 void SkScalerContext_GDI::generateAdvance(SkGlyph* glyph) {
    882     this->generateMetrics(glyph);
    883 }
    884 
    885 void SkScalerContext_GDI::generateMetrics(SkGlyph* glyph) {
    886     SkASSERT(fDDC);
    887 
    888     if (fType == SkScalerContext_GDI::kBitmap_Type) {
    889         SIZE size;
    890         WORD glyphs = glyph->getGlyphID(0);
    891         if (0 == GetTextExtentPointI(fDDC, &glyphs, 1, &size)) {
    892             glyph->fWidth = SkToS16(fTM.tmMaxCharWidth);
    893         } else {
    894             glyph->fWidth = SkToS16(size.cx);
    895         }
    896         glyph->fHeight = SkToS16(size.cy);
    897 
    898         glyph->fTop = SkToS16(-fTM.tmAscent);
    899         glyph->fLeft = SkToS16(0);
    900         glyph->fAdvanceX = SkIntToFixed(glyph->fWidth);
    901         glyph->fAdvanceY = 0;
    902 
    903         // Apply matrix to advance.
    904         glyph->fAdvanceY = SkFixedMul(SkFIXEDToFixed(fMat22.eM21), glyph->fAdvanceX);
    905         glyph->fAdvanceX = SkFixedMul(SkFIXEDToFixed(fMat22.eM11), glyph->fAdvanceX);
    906 
    907         return;
    908     }
    909 
    910     UINT glyphId = glyph->getGlyphID(0);
    911 
    912     GLYPHMETRICS gm;
    913     sk_bzero(&gm, sizeof(gm));
    914 
    915     DWORD status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
    916     if (GDI_ERROR == status) {
    917         LogFontTypeface::EnsureAccessible(this->getTypeface());
    918         status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
    919         if (GDI_ERROR == status) {
    920             glyph->zeroMetrics();
    921             return;
    922         }
    923     }
    924 
    925     bool empty = false;
    926     // The black box is either the embedded bitmap size or the outline extent.
    927     // It is 1x1 if nothing is to be drawn, but will also be 1x1 if something very small
    928     // is to be drawn, like a '.'. We need to outset '.' but do not wish to outset ' '.
    929     if (1 == gm.gmBlackBoxX && 1 == gm.gmBlackBoxY) {
    930         // If GetGlyphOutline with GGO_NATIVE returns 0, we know there was no outline.
    931         DWORD bufferSize = GetGlyphOutlineW(fDDC, glyphId, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
    932         empty = (0 == bufferSize);
    933     }
    934 
    935     glyph->fTop = SkToS16(-gm.gmptGlyphOrigin.y);
    936     glyph->fLeft = SkToS16(gm.gmptGlyphOrigin.x);
    937     if (empty) {
    938         glyph->fWidth = 0;
    939         glyph->fHeight = 0;
    940     } else {
    941         // Outset, since the image may bleed out of the black box.
    942         // For embedded bitmaps the black box should be exact.
    943         // For outlines we need to outset by 1 in all directions for bleed.
    944         // For ClearType we need to outset by 2 for bleed.
    945         glyph->fWidth = gm.gmBlackBoxX + 4;
    946         glyph->fHeight = gm.gmBlackBoxY + 4;
    947         glyph->fTop -= 2;
    948         glyph->fLeft -= 2;
    949     }
    950     glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX);
    951     glyph->fAdvanceY = SkIntToFixed(gm.gmCellIncY);
    952     glyph->fRsbDelta = 0;
    953     glyph->fLsbDelta = 0;
    954 
    955     if (this->isSubpixel()) {
    956         sk_bzero(&gm, sizeof(gm));
    957         status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fHighResMat22);
    958         if (GDI_ERROR != status) {
    959             SkPoint advance;
    960             fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance);
    961             glyph->fAdvanceX = SkScalarToFixed(advance.fX);
    962             glyph->fAdvanceY = SkScalarToFixed(advance.fY);
    963         }
    964     } else if (!isAxisAligned(this->fRec)) {
    965         status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fGsA);
    966         if (GDI_ERROR != status) {
    967             SkPoint advance;
    968             fG_inv.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance);
    969             glyph->fAdvanceX = SkScalarToFixed(advance.fX);
    970             glyph->fAdvanceY = SkScalarToFixed(advance.fY);
    971         }
    972     }
    973 }
    974 
    975 static const MAT2 gMat2Identity = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
    976 void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
    977     if (!(mx || my)) {
    978       return;
    979     }
    980 
    981     if (mx) {
    982         sk_bzero(mx, sizeof(*mx));
    983     }
    984     if (my) {
    985         sk_bzero(my, sizeof(*my));
    986     }
    987 
    988     SkASSERT(fDDC);
    989 
    990 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
    991     if (fType == SkScalerContext_GDI::kBitmap_Type) {
    992 #endif
    993         if (mx) {
    994             mx->fTop = SkIntToScalar(-fTM.tmAscent);
    995             mx->fAscent = SkIntToScalar(-fTM.tmAscent);
    996             mx->fDescent = SkIntToScalar(fTM.tmDescent);
    997             mx->fBottom = SkIntToScalar(fTM.tmDescent);
    998             mx->fLeading = SkIntToScalar(fTM.tmExternalLeading);
    999         }
   1000 
   1001         if (my) {
   1002             my->fTop = SkIntToScalar(-fTM.tmAscent);
   1003             my->fAscent = SkIntToScalar(-fTM.tmAscent);
   1004             my->fDescent = SkIntToScalar(fTM.tmDescent);
   1005             my->fBottom = SkIntToScalar(fTM.tmDescent);
   1006             my->fLeading = SkIntToScalar(fTM.tmExternalLeading);
   1007             my->fAvgCharWidth = SkIntToScalar(fTM.tmAveCharWidth);
   1008             my->fMaxCharWidth = SkIntToScalar(fTM.tmMaxCharWidth);
   1009             my->fXMin = 0;
   1010             my->fXMax = my->fMaxCharWidth;
   1011             //my->fXHeight = 0;
   1012         }
   1013 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
   1014         return;
   1015     }
   1016 #endif
   1017 
   1018     OUTLINETEXTMETRIC otm;
   1019 
   1020     uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
   1021     if (0 == ret) {
   1022         LogFontTypeface::EnsureAccessible(this->getTypeface());
   1023         ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
   1024     }
   1025     if (0 == ret) {
   1026         return;
   1027     }
   1028 
   1029     if (mx) {
   1030         mx->fTop = SkIntToScalar(-otm.otmrcFontBox.left);
   1031         mx->fAscent = SkIntToScalar(-otm.otmAscent);
   1032         mx->fDescent = SkIntToScalar(-otm.otmDescent);
   1033         mx->fBottom = SkIntToScalar(otm.otmrcFontBox.right);
   1034         mx->fLeading = SkIntToScalar(otm.otmLineGap);
   1035     }
   1036 
   1037     if (my) {
   1038 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
   1039         my->fTop = SkIntToScalar(-otm.otmrcFontBox.top);
   1040         my->fAscent = SkIntToScalar(-otm.otmAscent);
   1041         my->fDescent = SkIntToScalar(-otm.otmDescent);
   1042         my->fBottom = SkIntToScalar(-otm.otmrcFontBox.bottom);
   1043         my->fLeading = SkIntToScalar(otm.otmLineGap);
   1044         my->fAvgCharWidth = SkIntToScalar(otm.otmTextMetrics.tmAveCharWidth);
   1045         my->fMaxCharWidth = SkIntToScalar(otm.otmTextMetrics.tmMaxCharWidth);
   1046         my->fXMin = SkIntToScalar(otm.otmrcFontBox.left);
   1047         my->fXMax = SkIntToScalar(otm.otmrcFontBox.right);
   1048 #endif
   1049         my->fXHeight = SkIntToScalar(otm.otmsXHeight);
   1050 
   1051         GLYPHMETRICS gm;
   1052         sk_bzero(&gm, sizeof(gm));
   1053         DWORD len = GetGlyphOutlineW(fDDC, 'x', GGO_METRICS, &gm, 0, 0, &gMat2Identity);
   1054         if (len != GDI_ERROR && gm.gmBlackBoxY > 0) {
   1055             my->fXHeight = SkIntToScalar(gm.gmBlackBoxY);
   1056         }
   1057     }
   1058 }
   1059 
   1060 ////////////////////////////////////////////////////////////////////////////////////////
   1061 
   1062 #define SK_SHOW_TEXT_BLIT_COVERAGE 0
   1063 
   1064 static void build_power_table(uint8_t table[], float ee) {
   1065     for (int i = 0; i < 256; i++) {
   1066         float x = i / 255.f;
   1067         x = sk_float_pow(x, ee);
   1068         int xx = SkScalarRound(x * 255);
   1069         table[i] = SkToU8(xx);
   1070     }
   1071 }
   1072 
   1073 /**
   1074  *  This will invert the gamma applied by GDI (gray-scale antialiased), so we
   1075  *  can get linear values.
   1076  *
   1077  *  GDI grayscale appears to use a hard-coded gamma of 2.3.
   1078  *
   1079  *  GDI grayscale appears to draw using the black and white rasterizer at four
   1080  *  times the size and then downsamples to compute the coverage mask. As a
   1081  *  result there are only seventeen total grays. This lack of fidelity means
   1082  *  that shifting into other color spaces is imprecise.
   1083  */
   1084 static const uint8_t* getInverseGammaTableGDI() {
   1085     // Since build_power_table is idempotent, many threads can build gTableGdi
   1086     // simultaneously.
   1087 
   1088     // Microsoft Specific:
   1089     // Making gInited volatile provides read-aquire and write-release in vc++.
   1090     // In VS2012, see compiler option /volatile:(ms|iso).
   1091     // Replace with C++11 atomics when possible.
   1092     static volatile bool gInited;
   1093     static uint8_t gTableGdi[256];
   1094     if (gInited) {
   1095         // Need a L/L (read) barrier (full acquire not needed). If gInited is observed
   1096         // true then gTableGdi is observable, but it must be requested.
   1097     } else {
   1098         build_power_table(gTableGdi, 2.3f);
   1099         // Need a S/S (write) barrier (full release not needed) here so that this
   1100         // write to gInited becomes observable after gTableGdi.
   1101         gInited = true;
   1102     }
   1103     return gTableGdi;
   1104 }
   1105 
   1106 /**
   1107  *  This will invert the gamma applied by GDI ClearType, so we can get linear
   1108  *  values.
   1109  *
   1110  *  GDI ClearType uses SPI_GETFONTSMOOTHINGCONTRAST / 1000 as the gamma value.
   1111  *  If this value is not specified, the default is a gamma of 1.4.
   1112  */
   1113 static const uint8_t* getInverseGammaTableClearType() {
   1114     // We don't expect SPI_GETFONTSMOOTHINGCONTRAST to ever change, so building
   1115     // gTableClearType with build_power_table is effectively idempotent.
   1116 
   1117     // Microsoft Specific:
   1118     // Making gInited volatile provides read-aquire and write-release in vc++.
   1119     // In VS2012, see compiler option /volatile:(ms|iso).
   1120     // Replace with C++11 atomics when possible.
   1121     static volatile bool gInited;
   1122     static uint8_t gTableClearType[256];
   1123     if (gInited) {
   1124         // Need a L/L (read) barrier (acquire not needed). If gInited is observed
   1125         // true then gTableClearType is observable, but it must be requested.
   1126     } else {
   1127         UINT level = 0;
   1128         if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) {
   1129             // can't get the data, so use a default
   1130             level = 1400;
   1131         }
   1132         build_power_table(gTableClearType, level / 1000.0f);
   1133         // Need a S/S (write) barrier (release not needed) here so that this
   1134         // write to gInited becomes observable after gTableClearType.
   1135         gInited = true;
   1136     }
   1137     return gTableClearType;
   1138 }
   1139 
   1140 #include "SkColorPriv.h"
   1141 
   1142 //Cannot assume that the input rgb is gray due to possible setting of kGenA8FromLCD_Flag.
   1143 template<bool APPLY_PREBLEND>
   1144 static inline uint8_t rgb_to_a8(SkGdiRGB rgb, const uint8_t* table8) {
   1145     U8CPU r = (rgb >> 16) & 0xFF;
   1146     U8CPU g = (rgb >>  8) & 0xFF;
   1147     U8CPU b = (rgb >>  0) & 0xFF;
   1148     return sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
   1149 }
   1150 
   1151 template<bool APPLY_PREBLEND>
   1152 static inline uint16_t rgb_to_lcd16(SkGdiRGB rgb, const uint8_t* tableR,
   1153                                                   const uint8_t* tableG,
   1154                                                   const uint8_t* tableB) {
   1155     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
   1156     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
   1157     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
   1158 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1159     r = SkMax32(r, 10); g = SkMax32(g, 10); b = SkMax32(b, 10);
   1160 #endif
   1161     return SkPack888ToRGB16(r, g, b);
   1162 }
   1163 
   1164 template<bool APPLY_PREBLEND>
   1165 static inline SkPMColor rgb_to_lcd32(SkGdiRGB rgb, const uint8_t* tableR,
   1166                                                    const uint8_t* tableG,
   1167                                                    const uint8_t* tableB) {
   1168     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
   1169     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
   1170     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
   1171 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1172     r = SkMax32(r, 10); g = SkMax32(g, 10); b = SkMax32(b, 10);
   1173 #endif
   1174     return SkPackARGB32(0xFF, r, g, b);
   1175 }
   1176 
   1177 // Is this GDI color neither black nor white? If so, we have to keep this
   1178 // image as is, rather than smashing it down to a BW mask.
   1179 //
   1180 // returns int instead of bool, since we don't want/have to pay to convert
   1181 // the zero/non-zero value into a bool
   1182 static int is_not_black_or_white(SkGdiRGB c) {
   1183     // same as (but faster than)
   1184     //      c &= 0x00FFFFFF;
   1185     //      return 0 == c || 0x00FFFFFF == c;
   1186     return (c + (c & 1)) & 0x00FFFFFF;
   1187 }
   1188 
   1189 static bool is_rgb_really_bw(const SkGdiRGB* src, int width, int height, size_t srcRB) {
   1190     for (int y = 0; y < height; ++y) {
   1191         for (int x = 0; x < width; ++x) {
   1192             if (is_not_black_or_white(src[x])) {
   1193                 return false;
   1194             }
   1195         }
   1196         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1197     }
   1198     return true;
   1199 }
   1200 
   1201 // gdi's bitmap is upside-down, so we reverse dst walking in Y
   1202 // whenever we copy it into skia's buffer
   1203 static void rgb_to_bw(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
   1204                       const SkGlyph& glyph) {
   1205     const int width = glyph.fWidth;
   1206     const size_t dstRB = (width + 7) >> 3;
   1207     uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1208 
   1209     int byteCount = width >> 3;
   1210     int bitCount = width & 7;
   1211 
   1212     // adjust srcRB to skip the values in our byteCount loop,
   1213     // since we increment src locally there
   1214     srcRB -= byteCount * 8 * sizeof(SkGdiRGB);
   1215 
   1216     for (int y = 0; y < glyph.fHeight; ++y) {
   1217         if (byteCount > 0) {
   1218             for (int i = 0; i < byteCount; ++i) {
   1219                 unsigned byte = 0;
   1220                 byte |= src[0] & (1 << 7);
   1221                 byte |= src[1] & (1 << 6);
   1222                 byte |= src[2] & (1 << 5);
   1223                 byte |= src[3] & (1 << 4);
   1224                 byte |= src[4] & (1 << 3);
   1225                 byte |= src[5] & (1 << 2);
   1226                 byte |= src[6] & (1 << 1);
   1227                 byte |= src[7] & (1 << 0);
   1228                 dst[i] = byte;
   1229                 src += 8;
   1230             }
   1231         }
   1232         if (bitCount > 0) {
   1233             unsigned byte = 0;
   1234             unsigned mask = 0x80;
   1235             for (int i = 0; i < bitCount; i++) {
   1236                 byte |= src[i] & mask;
   1237                 mask >>= 1;
   1238             }
   1239             dst[byteCount] = byte;
   1240         }
   1241         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1242         dst -= dstRB;
   1243     }
   1244 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1245     if (glyph.fWidth > 0 && glyph.fHeight > 0) {
   1246         uint8_t* first = (uint8_t*)glyph.fImage;
   1247         uint8_t* last = (uint8_t*)((char*)glyph.fImage + glyph.fHeight * dstRB - 1);
   1248         *first |= 1 << 7;
   1249         *last |= bitCount == 0 ? 1 : 1 << (8 - bitCount);
   1250     }
   1251 #endif
   1252 }
   1253 
   1254 template<bool APPLY_PREBLEND>
   1255 static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
   1256                       const SkGlyph& glyph, const uint8_t* table8) {
   1257     const size_t dstRB = glyph.rowBytes();
   1258     const int width = glyph.fWidth;
   1259     uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1260 
   1261     for (int y = 0; y < glyph.fHeight; y++) {
   1262         for (int i = 0; i < width; i++) {
   1263             dst[i] = rgb_to_a8<APPLY_PREBLEND>(src[i], table8);
   1264 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1265             dst[i] = SkMax32(dst[i], 10);
   1266 #endif
   1267         }
   1268         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1269         dst -= dstRB;
   1270     }
   1271 }
   1272 
   1273 template<bool APPLY_PREBLEND>
   1274 static void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph,
   1275                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1276     const size_t dstRB = glyph.rowBytes();
   1277     const int width = glyph.fWidth;
   1278     uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1279 
   1280     for (int y = 0; y < glyph.fHeight; y++) {
   1281         for (int i = 0; i < width; i++) {
   1282             dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
   1283         }
   1284         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1285         dst = (uint16_t*)((char*)dst - dstRB);
   1286     }
   1287 }
   1288 
   1289 template<bool APPLY_PREBLEND>
   1290 static void rgb_to_lcd32(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph,
   1291                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1292     const size_t dstRB = glyph.rowBytes();
   1293     const int width = glyph.fWidth;
   1294     uint32_t* SK_RESTRICT dst = (uint32_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1295 
   1296     for (int y = 0; y < glyph.fHeight; y++) {
   1297         for (int i = 0; i < width; i++) {
   1298             dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
   1299         }
   1300         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1301         dst = (uint32_t*)((char*)dst - dstRB);
   1302     }
   1303 }
   1304 
   1305 static inline unsigned clamp255(unsigned x) {
   1306     SkASSERT(x <= 256);
   1307     return x - (x >> 8);
   1308 }
   1309 
   1310 void SkScalerContext_GDI::generateImage(const SkGlyph& glyph) {
   1311     SkASSERT(fDDC);
   1312 
   1313     const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
   1314     const bool isAA = !isLCD(fRec);
   1315 
   1316     size_t srcRB;
   1317     const void* bits = fOffscreen.draw(glyph, isBW, &srcRB);
   1318     if (NULL == bits) {
   1319         LogFontTypeface::EnsureAccessible(this->getTypeface());
   1320         bits = fOffscreen.draw(glyph, isBW, &srcRB);
   1321         if (NULL == bits) {
   1322             sk_bzero(glyph.fImage, glyph.computeImageSize());
   1323             return;
   1324         }
   1325     }
   1326 
   1327     if (!isBW) {
   1328         const uint8_t* table;
   1329         //The offscreen contains a GDI blit if isAA and kGenA8FromLCD_Flag is not set.
   1330         //Otherwise the offscreen contains a ClearType blit.
   1331         if (isAA && !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
   1332             table = getInverseGammaTableGDI();
   1333         } else {
   1334             table = getInverseGammaTableClearType();
   1335         }
   1336         //Note that the following cannot really be integrated into the
   1337         //pre-blend, since we may not be applying the pre-blend; when we aren't
   1338         //applying the pre-blend it means that a filter wants linear anyway.
   1339         //Other code may also be applying the pre-blend, so we'd need another
   1340         //one with this and one without.
   1341         SkGdiRGB* addr = (SkGdiRGB*)bits;
   1342         for (int y = 0; y < glyph.fHeight; ++y) {
   1343             for (int x = 0; x < glyph.fWidth; ++x) {
   1344                 int r = (addr[x] >> 16) & 0xFF;
   1345                 int g = (addr[x] >>  8) & 0xFF;
   1346                 int b = (addr[x] >>  0) & 0xFF;
   1347                 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
   1348             }
   1349             addr = SkTAddOffset<SkGdiRGB>(addr, srcRB);
   1350         }
   1351     }
   1352 
   1353     int width = glyph.fWidth;
   1354     size_t dstRB = glyph.rowBytes();
   1355     if (isBW) {
   1356         const uint8_t* src = (const uint8_t*)bits;
   1357         uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1358         for (int y = 0; y < glyph.fHeight; y++) {
   1359             memcpy(dst, src, dstRB);
   1360             src += srcRB;
   1361             dst -= dstRB;
   1362         }
   1363 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1364             if (glyph.fWidth > 0 && glyph.fHeight > 0) {
   1365                 int bitCount = width & 7;
   1366                 uint8_t* first = (uint8_t*)glyph.fImage;
   1367                 uint8_t* last = (uint8_t*)((char*)glyph.fImage + glyph.fHeight * dstRB - 1);
   1368                 *first |= 1 << 7;
   1369                 *last |= bitCount == 0 ? 1 : 1 << (8 - bitCount);
   1370             }
   1371 #endif
   1372     } else if (isAA) {
   1373         // since the caller may require A8 for maskfilters, we can't check for BW
   1374         // ... until we have the caller tell us that explicitly
   1375         const SkGdiRGB* src = (const SkGdiRGB*)bits;
   1376         if (fPreBlend.isApplicable()) {
   1377             rgb_to_a8<true>(src, srcRB, glyph, fPreBlend.fG);
   1378         } else {
   1379             rgb_to_a8<false>(src, srcRB, glyph, fPreBlend.fG);
   1380         }
   1381     } else {    // LCD16
   1382         const SkGdiRGB* src = (const SkGdiRGB*)bits;
   1383         if (is_rgb_really_bw(src, width, glyph.fHeight, srcRB)) {
   1384             rgb_to_bw(src, srcRB, glyph);
   1385             ((SkGlyph*)&glyph)->fMaskFormat = SkMask::kBW_Format;
   1386         } else {
   1387             if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
   1388                 if (fPreBlend.isApplicable()) {
   1389                     rgb_to_lcd16<true>(src, srcRB, glyph,
   1390                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1391                 } else {
   1392                     rgb_to_lcd16<false>(src, srcRB, glyph,
   1393                                         fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1394                 }
   1395             } else {
   1396                 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
   1397                 if (fPreBlend.isApplicable()) {
   1398                     rgb_to_lcd32<true>(src, srcRB, glyph,
   1399                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1400                 } else {
   1401                     rgb_to_lcd32<false>(src, srcRB, glyph,
   1402                                         fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1403                 }
   1404             }
   1405         }
   1406     }
   1407 }
   1408 
   1409 class GDIGlyphbufferPointIter {
   1410 public:
   1411     GDIGlyphbufferPointIter(const uint8_t* glyphbuf, DWORD total_size)
   1412         : fHeaderIter(glyphbuf, total_size), fCurveIter(), fPointIter()
   1413     { }
   1414 
   1415     POINTFX const * next() {
   1416 nextHeader:
   1417         if (!fCurveIter.isSet()) {
   1418             const TTPOLYGONHEADER* header = fHeaderIter.next();
   1419             if (NULL == header) {
   1420                 return NULL;
   1421             }
   1422             fCurveIter.set(header);
   1423             const TTPOLYCURVE* curve = fCurveIter.next();
   1424             if (NULL == curve) {
   1425                 return NULL;
   1426             }
   1427             fPointIter.set(curve);
   1428             return &header->pfxStart;
   1429         }
   1430 
   1431         const POINTFX* nextPoint = fPointIter.next();
   1432         if (NULL == nextPoint) {
   1433             const TTPOLYCURVE* curve = fCurveIter.next();
   1434             if (NULL == curve) {
   1435                 fCurveIter.set();
   1436                 goto nextHeader;
   1437             } else {
   1438                 fPointIter.set(curve);
   1439             }
   1440             nextPoint = fPointIter.next();
   1441         }
   1442         return nextPoint;
   1443     }
   1444 
   1445     WORD currentCurveType() {
   1446         return fPointIter.fCurveType;
   1447     }
   1448 
   1449 private:
   1450     /** Iterates over all of the polygon headers in a glyphbuf. */
   1451     class GDIPolygonHeaderIter {
   1452     public:
   1453         GDIPolygonHeaderIter(const uint8_t* glyphbuf, DWORD total_size)
   1454             : fCurPolygon(reinterpret_cast<const TTPOLYGONHEADER*>(glyphbuf))
   1455             , fEndPolygon(SkTAddOffset<const TTPOLYGONHEADER>(glyphbuf, total_size))
   1456         { }
   1457 
   1458         const TTPOLYGONHEADER* next() {
   1459             if (fCurPolygon >= fEndPolygon) {
   1460                 return NULL;
   1461             }
   1462             const TTPOLYGONHEADER* thisPolygon = fCurPolygon;
   1463             fCurPolygon = SkTAddOffset<const TTPOLYGONHEADER>(fCurPolygon, fCurPolygon->cb);
   1464             return thisPolygon;
   1465         }
   1466     private:
   1467         const TTPOLYGONHEADER* fCurPolygon;
   1468         const TTPOLYGONHEADER* fEndPolygon;
   1469     };
   1470 
   1471     /** Iterates over all of the polygon curves in a polygon header. */
   1472     class GDIPolygonCurveIter {
   1473     public:
   1474         GDIPolygonCurveIter() : fCurCurve(NULL), fEndCurve(NULL) { }
   1475 
   1476         GDIPolygonCurveIter(const TTPOLYGONHEADER* curPolygon)
   1477             : fCurCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOLYGONHEADER)))
   1478             , fEndCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->cb))
   1479         { }
   1480 
   1481         bool isSet() { return fCurCurve != NULL; }
   1482 
   1483         void set(const TTPOLYGONHEADER* curPolygon) {
   1484             fCurCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOLYGONHEADER));
   1485             fEndCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->cb);
   1486         }
   1487         void set() {
   1488             fCurCurve = NULL;
   1489             fEndCurve = NULL;
   1490         }
   1491 
   1492         const TTPOLYCURVE* next() {
   1493             if (fCurCurve >= fEndCurve) {
   1494                 return NULL;
   1495             }
   1496             const TTPOLYCURVE* thisCurve = fCurCurve;
   1497             fCurCurve = SkTAddOffset<const TTPOLYCURVE>(fCurCurve, size_of_TTPOLYCURVE(*fCurCurve));
   1498             return thisCurve;
   1499         }
   1500     private:
   1501         size_t size_of_TTPOLYCURVE(const TTPOLYCURVE& curve) {
   1502             return 2*sizeof(WORD) + curve.cpfx*sizeof(POINTFX);
   1503         }
   1504         const TTPOLYCURVE* fCurCurve;
   1505         const TTPOLYCURVE* fEndCurve;
   1506     };
   1507 
   1508     /** Iterates over all of the polygon points in a polygon curve. */
   1509     class GDIPolygonCurvePointIter {
   1510     public:
   1511         GDIPolygonCurvePointIter() : fCurveType(0), fCurPoint(NULL), fEndPoint(NULL) { }
   1512 
   1513         GDIPolygonCurvePointIter(const TTPOLYCURVE* curPolygon)
   1514             : fCurveType(curPolygon->wType)
   1515             , fCurPoint(&curPolygon->apfx[0])
   1516             , fEndPoint(&curPolygon->apfx[curPolygon->cpfx])
   1517         { }
   1518 
   1519         bool isSet() { return fCurPoint != NULL; }
   1520 
   1521         void set(const TTPOLYCURVE* curPolygon) {
   1522             fCurveType = curPolygon->wType;
   1523             fCurPoint = &curPolygon->apfx[0];
   1524             fEndPoint = &curPolygon->apfx[curPolygon->cpfx];
   1525         }
   1526         void set() {
   1527             fCurPoint = NULL;
   1528             fEndPoint = NULL;
   1529         }
   1530 
   1531         const POINTFX* next() {
   1532             if (fCurPoint >= fEndPoint) {
   1533                 return NULL;
   1534             }
   1535             const POINTFX* thisPoint = fCurPoint;
   1536             ++fCurPoint;
   1537             return thisPoint;
   1538         }
   1539 
   1540         WORD fCurveType;
   1541     private:
   1542         const POINTFX* fCurPoint;
   1543         const POINTFX* fEndPoint;
   1544     };
   1545 
   1546     GDIPolygonHeaderIter fHeaderIter;
   1547     GDIPolygonCurveIter fCurveIter;
   1548     GDIPolygonCurvePointIter fPointIter;
   1549 };
   1550 
   1551 static void sk_path_from_gdi_path(SkPath* path, const uint8_t* glyphbuf, DWORD total_size) {
   1552     const uint8_t* cur_glyph = glyphbuf;
   1553     const uint8_t* end_glyph = glyphbuf + total_size;
   1554 
   1555     while (cur_glyph < end_glyph) {
   1556         const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
   1557 
   1558         const uint8_t* end_poly = cur_glyph + th->cb;
   1559         const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
   1560 
   1561         path->moveTo(SkFixedToScalar( SkFIXEDToFixed(th->pfxStart.x)),
   1562                      SkFixedToScalar(-SkFIXEDToFixed(th->pfxStart.y)));
   1563 
   1564         while (cur_poly < end_poly) {
   1565             const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
   1566 
   1567             if (pc->wType == TT_PRIM_LINE) {
   1568                 for (uint16_t i = 0; i < pc->cpfx; i++) {
   1569                     path->lineTo(SkFixedToScalar( SkFIXEDToFixed(pc->apfx[i].x)),
   1570                                  SkFixedToScalar(-SkFIXEDToFixed(pc->apfx[i].y)));
   1571                 }
   1572             }
   1573 
   1574             if (pc->wType == TT_PRIM_QSPLINE) {
   1575                 for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
   1576                     POINTFX pnt_b = pc->apfx[u];    // B is always the current point
   1577                     POINTFX pnt_c = pc->apfx[u+1];
   1578 
   1579                     if (u < pc->cpfx - 2) {          // If not on last spline, compute C
   1580                         pnt_c.x = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.x),
   1581                                                             SkFIXEDToFixed(pnt_c.x)));
   1582                         pnt_c.y = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.y),
   1583                                                             SkFIXEDToFixed(pnt_c.y)));
   1584                     }
   1585 
   1586                     path->quadTo(SkFixedToScalar( SkFIXEDToFixed(pnt_b.x)),
   1587                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_b.y)),
   1588                                  SkFixedToScalar( SkFIXEDToFixed(pnt_c.x)),
   1589                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_c.y)));
   1590                 }
   1591             }
   1592             // Advance past this TTPOLYCURVE.
   1593             cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
   1594         }
   1595         cur_glyph += th->cb;
   1596         path->close();
   1597     }
   1598 }
   1599 
   1600 #define move_next_expected_hinted_point(iter, pElem) do {\
   1601     pElem = iter.next(); \
   1602     if (NULL == pElem) return false; \
   1603 } while(0)
   1604 
   1605 // It is possible for the hinted and unhinted versions of the same path to have
   1606 // a different number of points due to GDI's handling of flipped points.
   1607 // If this is detected, this will return false.
   1608 static bool sk_path_from_gdi_paths(SkPath* path, const uint8_t* glyphbuf, DWORD total_size,
   1609                                    GDIGlyphbufferPointIter hintedYs) {
   1610     const uint8_t* cur_glyph = glyphbuf;
   1611     const uint8_t* end_glyph = glyphbuf + total_size;
   1612 
   1613     POINTFX const * hintedPoint;
   1614 
   1615     while (cur_glyph < end_glyph) {
   1616         const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
   1617 
   1618         const uint8_t* end_poly = cur_glyph + th->cb;
   1619         const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
   1620 
   1621         move_next_expected_hinted_point(hintedYs, hintedPoint);
   1622         path->moveTo(SkFixedToScalar( SkFIXEDToFixed(th->pfxStart.x)),
   1623                      SkFixedToScalar(-SkFIXEDToFixed(hintedPoint->y)));
   1624 
   1625         while (cur_poly < end_poly) {
   1626             const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
   1627 
   1628             if (pc->wType == TT_PRIM_LINE) {
   1629                 for (uint16_t i = 0; i < pc->cpfx; i++) {
   1630                     move_next_expected_hinted_point(hintedYs, hintedPoint);
   1631                     path->lineTo(SkFixedToScalar( SkFIXEDToFixed(pc->apfx[i].x)),
   1632                                  SkFixedToScalar(-SkFIXEDToFixed(hintedPoint->y)));
   1633                 }
   1634             }
   1635 
   1636             if (pc->wType == TT_PRIM_QSPLINE) {
   1637                 POINTFX currentPoint = pc->apfx[0];
   1638                 move_next_expected_hinted_point(hintedYs, hintedPoint);
   1639                 // only take the hinted y if it wasn't flipped
   1640                 if (hintedYs.currentCurveType() == TT_PRIM_QSPLINE) {
   1641                     currentPoint.y = hintedPoint->y;
   1642                 }
   1643                 for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
   1644                     POINTFX pnt_b = currentPoint;//pc->apfx[u]; // B is always the current point
   1645                     POINTFX pnt_c = pc->apfx[u+1];
   1646                     move_next_expected_hinted_point(hintedYs, hintedPoint);
   1647                     // only take the hinted y if it wasn't flipped
   1648                     if (hintedYs.currentCurveType() == TT_PRIM_QSPLINE) {
   1649                         pnt_c.y = hintedPoint->y;
   1650                     }
   1651                     currentPoint.x = pnt_c.x;
   1652                     currentPoint.y = pnt_c.y;
   1653 
   1654                     if (u < pc->cpfx - 2) {          // If not on last spline, compute C
   1655                         pnt_c.x = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.x),
   1656                                                             SkFIXEDToFixed(pnt_c.x)));
   1657                         pnt_c.y = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.y),
   1658                                                             SkFIXEDToFixed(pnt_c.y)));
   1659                     }
   1660 
   1661                     path->quadTo(SkFixedToScalar( SkFIXEDToFixed(pnt_b.x)),
   1662                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_b.y)),
   1663                                  SkFixedToScalar( SkFIXEDToFixed(pnt_c.x)),
   1664                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_c.y)));
   1665                 }
   1666             }
   1667             // Advance past this TTPOLYCURVE.
   1668             cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
   1669         }
   1670         cur_glyph += th->cb;
   1671         path->close();
   1672     }
   1673     return true;
   1674 }
   1675 
   1676 DWORD SkScalerContext_GDI::getGDIGlyphPath(const SkGlyph& glyph, UINT flags,
   1677                                                SkAutoSTMalloc<BUFFERSIZE, uint8_t>* glyphbuf)
   1678 {
   1679     GLYPHMETRICS gm;
   1680 
   1681     DWORD total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, BUFFERSIZE, glyphbuf->get(), &fMat22);
   1682     // Sometimes GetGlyphOutlineW returns a number larger than BUFFERSIZE even if BUFFERSIZE > 0.
   1683     // It has been verified that this does not involve a buffer overrun.
   1684     if (GDI_ERROR == total_size || total_size > BUFFERSIZE) {
   1685         // GDI_ERROR because the BUFFERSIZE was too small, or because the data was not accessible.
   1686         // When the data is not accessable GetGlyphOutlineW fails rather quickly,
   1687         // so just try to get the size. If that fails then ensure the data is accessible.
   1688         total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22);
   1689         if (GDI_ERROR == total_size) {
   1690             LogFontTypeface::EnsureAccessible(this->getTypeface());
   1691             total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22);
   1692             if (GDI_ERROR == total_size) {
   1693                 SkASSERT(false);
   1694                 return 0;
   1695             }
   1696         }
   1697 
   1698         glyphbuf->reset(total_size);
   1699 
   1700         DWORD ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyphbuf->get(), &fMat22);
   1701         if (GDI_ERROR == ret) {
   1702             LogFontTypeface::EnsureAccessible(this->getTypeface());
   1703             ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyphbuf->get(), &fMat22);
   1704             if (GDI_ERROR == ret) {
   1705                 SkASSERT(false);
   1706                 return 0;
   1707             }
   1708         }
   1709     }
   1710     return total_size;
   1711 }
   1712 
   1713 void SkScalerContext_GDI::generatePath(const SkGlyph& glyph, SkPath* path) {
   1714     SkASSERT(&glyph && path);
   1715     SkASSERT(fDDC);
   1716 
   1717     path->reset();
   1718 
   1719     // Out of all the fonts on a typical Windows box,
   1720     // 25% of glyphs require more than 2KB.
   1721     // 1% of glyphs require more than 4KB.
   1722     // 0.01% of glyphs require more than 8KB.
   1723     // 8KB is less than 1% of the normal 1MB stack on Windows.
   1724     // Note that some web fonts glyphs require more than 20KB.
   1725     //static const DWORD BUFFERSIZE = (1 << 13);
   1726 
   1727     //GDI only uses hinted outlines when axis aligned.
   1728     UINT format = GGO_NATIVE | GGO_GLYPH_INDEX;
   1729     if (fRec.getHinting() == SkPaint::kNo_Hinting || fRec.getHinting() == SkPaint::kSlight_Hinting){
   1730         format |= GGO_UNHINTED;
   1731     }
   1732     SkAutoSTMalloc<BUFFERSIZE, uint8_t> glyphbuf(BUFFERSIZE);
   1733     DWORD total_size = getGDIGlyphPath(glyph, format, &glyphbuf);
   1734     if (0 == total_size) {
   1735         return;
   1736     }
   1737 
   1738     if (fRec.getHinting() != SkPaint::kSlight_Hinting) {
   1739         sk_path_from_gdi_path(path, glyphbuf, total_size);
   1740     } else {
   1741         //GDI only uses hinted outlines when axis aligned.
   1742         UINT format = GGO_NATIVE | GGO_GLYPH_INDEX;
   1743 
   1744         SkAutoSTMalloc<BUFFERSIZE, uint8_t> hintedGlyphbuf(BUFFERSIZE);
   1745         DWORD hinted_total_size = getGDIGlyphPath(glyph, format, &hintedGlyphbuf);
   1746         if (0 == hinted_total_size) {
   1747             return;
   1748         }
   1749 
   1750         if (!sk_path_from_gdi_paths(path, glyphbuf, total_size,
   1751                                     GDIGlyphbufferPointIter(hintedGlyphbuf, hinted_total_size)))
   1752         {
   1753             path->reset();
   1754             sk_path_from_gdi_path(path, glyphbuf, total_size);
   1755         }
   1756     }
   1757 }
   1758 
   1759 static void logfont_for_name(const char* familyName, LOGFONT* lf) {
   1760     sk_bzero(lf, sizeof(LOGFONT));
   1761 #ifdef UNICODE
   1762     // Get the buffer size needed first.
   1763     size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,
   1764                                             -1, NULL, 0);
   1765     // Allocate a buffer (str_len already has terminating null
   1766     // accounted for).
   1767     wchar_t *wideFamilyName = new wchar_t[str_len];
   1768     // Now actually convert the string.
   1769     ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
   1770                             wideFamilyName, str_len);
   1771     ::wcsncpy(lf->lfFaceName, wideFamilyName, LF_FACESIZE - 1);
   1772     delete [] wideFamilyName;
   1773     lf->lfFaceName[LF_FACESIZE-1] = L'\0';
   1774 #else
   1775     ::strncpy(lf->lfFaceName, familyName, LF_FACESIZE - 1);
   1776     lf->lfFaceName[LF_FACESIZE - 1] = '\0';
   1777 #endif
   1778 }
   1779 
   1780 void LogFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
   1781                                           bool* isLocalStream) const {
   1782     // Get the actual name of the typeface. The logfont may not know this.
   1783     HFONT font = CreateFontIndirect(&fLogFont);
   1784 
   1785     HDC deviceContext = ::CreateCompatibleDC(NULL);
   1786     HFONT savefont = (HFONT)SelectObject(deviceContext, font);
   1787 
   1788     SkString familyName;
   1789     dcfontname_to_skstring(deviceContext, fLogFont, &familyName);
   1790 
   1791     if (deviceContext) {
   1792         ::SelectObject(deviceContext, savefont);
   1793         ::DeleteDC(deviceContext);
   1794     }
   1795     if (font) {
   1796         ::DeleteObject(font);
   1797     }
   1798 
   1799     desc->setFamilyName(familyName.c_str());
   1800     *isLocalStream = this->fSerializeAsStream;
   1801 }
   1802 
   1803 static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
   1804     // Initialize the MAT2 structure to the identify transformation matrix.
   1805     static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),
   1806                         SkScalarToFIXED(0), SkScalarToFIXED(1)};
   1807     int flags = GGO_METRICS | GGO_GLYPH_INDEX;
   1808     GLYPHMETRICS gm;
   1809     if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {
   1810         return false;
   1811     }
   1812     SkASSERT(advance);
   1813     *advance = gm.gmCellIncX;
   1814     return true;
   1815 }
   1816 
   1817 SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics(
   1818         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
   1819         const uint32_t* glyphIDs,
   1820         uint32_t glyphIDsCount) const {
   1821     LOGFONT lf = fLogFont;
   1822     SkAdvancedTypefaceMetrics* info = NULL;
   1823 
   1824     HDC hdc = CreateCompatibleDC(NULL);
   1825     HFONT font = CreateFontIndirect(&lf);
   1826     HFONT savefont = (HFONT)SelectObject(hdc, font);
   1827     HFONT designFont = NULL;
   1828 
   1829     const char stem_chars[] = {'i', 'I', '!', '1'};
   1830     int16_t min_width;
   1831     unsigned glyphCount;
   1832 
   1833     // To request design units, create a logical font whose height is specified
   1834     // as unitsPerEm.
   1835     OUTLINETEXTMETRIC otm;
   1836     unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
   1837     if (0 == otmRet) {
   1838         call_ensure_accessible(lf);
   1839         otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
   1840     }
   1841     if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
   1842         goto Error;
   1843     }
   1844     lf.lfHeight = -SkToS32(otm.otmEMSquare);
   1845     designFont = CreateFontIndirect(&lf);
   1846     SelectObject(hdc, designFont);
   1847     if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {
   1848         goto Error;
   1849     }
   1850     glyphCount = calculateGlyphCount(hdc, fLogFont);
   1851 
   1852     info = new SkAdvancedTypefaceMetrics;
   1853     info->fEmSize = otm.otmEMSquare;
   1854     info->fMultiMaster = false;
   1855     info->fLastGlyphID = SkToU16(glyphCount - 1);
   1856     info->fStyle = 0;
   1857     tchar_to_skstring(lf.lfFaceName, &info->fFontName);
   1858 
   1859     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
   1860         populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode));
   1861     }
   1862 
   1863     if (glyphCount > 0 &&
   1864         (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE)) {
   1865         info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
   1866     } else {
   1867         info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
   1868         info->fItalicAngle = 0;
   1869         info->fAscent = 0;
   1870         info->fDescent = 0;
   1871         info->fStemV = 0;
   1872         info->fCapHeight = 0;
   1873         info->fBBox = SkIRect::MakeEmpty();
   1874         goto ReturnInfo;
   1875     }
   1876 
   1877     // If this bit is clear the font is a fixed pitch font.
   1878     if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
   1879         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
   1880     }
   1881     if (otm.otmTextMetrics.tmItalic) {
   1882         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
   1883     }
   1884     if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {
   1885         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
   1886     } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {
   1887             info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
   1888     }
   1889 
   1890     // The main italic angle of the font, in tenths of a degree counterclockwise
   1891     // from vertical.
   1892     info->fItalicAngle = otm.otmItalicAngle / 10;
   1893     info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);
   1894     info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);
   1895     // TODO(ctguil): Use alternate cap height calculation.
   1896     // MSDN says otmsCapEmHeight is not support but it is returning a value on
   1897     // my Win7 box.
   1898     info->fCapHeight = otm.otmsCapEmHeight;
   1899     info->fBBox =
   1900         SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,
   1901                           otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);
   1902 
   1903     // Figure out a good guess for StemV - Min width of i, I, !, 1.
   1904     // This probably isn't very good with an italic font.
   1905     min_width = SHRT_MAX;
   1906     info->fStemV = 0;
   1907     for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
   1908         ABC abcWidths;
   1909         if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
   1910             int16_t width = abcWidths.abcB;
   1911             if (width > 0 && width < min_width) {
   1912                 min_width = width;
   1913                 info->fStemV = min_width;
   1914             }
   1915         }
   1916     }
   1917 
   1918     // If bit 1 is set, the font may not be embedded in a document.
   1919     // If bit 1 is clear, the font can be embedded.
   1920     // If bit 2 is set, the embedding is read-only.
   1921     if (otm.otmfsType & 0x1) {
   1922         info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
   1923     } else if (perGlyphInfo &
   1924                SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
   1925         if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
   1926             appendRange(&info->fGlyphWidths, 0);
   1927             info->fGlyphWidths->fAdvance.append(1, &min_width);
   1928             finishRange(info->fGlyphWidths.get(), 0,
   1929                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
   1930         } else {
   1931             info->fGlyphWidths.reset(
   1932                 getAdvanceData(hdc,
   1933                                glyphCount,
   1934                                glyphIDs,
   1935                                glyphIDsCount,
   1936                                &getWidthAdvance));
   1937         }
   1938     }
   1939 
   1940 Error:
   1941 ReturnInfo:
   1942     SelectObject(hdc, savefont);
   1943     DeleteObject(designFont);
   1944     DeleteObject(font);
   1945     DeleteDC(hdc);
   1946 
   1947     return info;
   1948 }
   1949 
   1950 //Dummy representation of a Base64 encoded GUID from create_unique_font_name.
   1951 #define BASE64_GUID_ID "XXXXXXXXXXXXXXXXXXXXXXXX"
   1952 //Length of GUID representation from create_id, including NULL terminator.
   1953 #define BASE64_GUID_ID_LEN SK_ARRAY_COUNT(BASE64_GUID_ID)
   1954 
   1955 SK_COMPILE_ASSERT(BASE64_GUID_ID_LEN < LF_FACESIZE, GUID_longer_than_facesize);
   1956 
   1957 /**
   1958    NameID 6 Postscript names cannot have the character '/'.
   1959    It would be easier to hex encode the GUID, but that is 32 bytes,
   1960    and many systems have issues with names longer than 28 bytes.
   1961    The following need not be any standard base64 encoding.
   1962    The encoded value is never decoded.
   1963 */
   1964 static const char postscript_safe_base64_encode[] =
   1965     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   1966     "abcdefghijklmnopqrstuvwxyz"
   1967     "0123456789-_=";
   1968 
   1969 /**
   1970    Formats a GUID into Base64 and places it into buffer.
   1971    buffer should have space for at least BASE64_GUID_ID_LEN characters.
   1972    The string will always be null terminated.
   1973    XXXXXXXXXXXXXXXXXXXXXXXX0
   1974  */
   1975 static void format_guid_b64(const GUID& guid, char* buffer, size_t bufferSize) {
   1976     SkASSERT(bufferSize >= BASE64_GUID_ID_LEN);
   1977     size_t written = SkBase64::Encode(&guid, sizeof(guid), buffer, postscript_safe_base64_encode);
   1978     SkASSERT(written < LF_FACESIZE);
   1979     buffer[written] = '\0';
   1980 }
   1981 
   1982 /**
   1983    Creates a Base64 encoded GUID and places it into buffer.
   1984    buffer should have space for at least BASE64_GUID_ID_LEN characters.
   1985    The string will always be null terminated.
   1986    XXXXXXXXXXXXXXXXXXXXXXXX0
   1987  */
   1988 static HRESULT create_unique_font_name(char* buffer, size_t bufferSize) {
   1989     GUID guid = {};
   1990     if (FAILED(CoCreateGuid(&guid))) {
   1991         return E_UNEXPECTED;
   1992     }
   1993     format_guid_b64(guid, buffer, bufferSize);
   1994 
   1995     return S_OK;
   1996 }
   1997 
   1998 /**
   1999    Introduces a font to GDI. On failure will return NULL. The returned handle
   2000    should eventually be passed to RemoveFontMemResourceEx.
   2001 */
   2002 static HANDLE activate_font(SkData* fontData) {
   2003     DWORD numFonts = 0;
   2004     //AddFontMemResourceEx just copies the data, but does not specify const.
   2005     HANDLE fontHandle = AddFontMemResourceEx(const_cast<void*>(fontData->data()),
   2006                                              static_cast<DWORD>(fontData->size()),
   2007                                              0,
   2008                                              &numFonts);
   2009 
   2010     if (fontHandle != NULL && numFonts < 1) {
   2011         RemoveFontMemResourceEx(fontHandle);
   2012         return NULL;
   2013     }
   2014 
   2015     return fontHandle;
   2016 }
   2017 
   2018 static SkTypeface* create_from_stream(SkStream* stream) {
   2019     // Create a unique and unpredictable font name.
   2020     // Avoids collisions and access from CSS.
   2021     char familyName[BASE64_GUID_ID_LEN];
   2022     const int familyNameSize = SK_ARRAY_COUNT(familyName);
   2023     if (FAILED(create_unique_font_name(familyName, familyNameSize))) {
   2024         return NULL;
   2025     }
   2026 
   2027     // Change the name of the font.
   2028     SkAutoTUnref<SkData> rewrittenFontData(SkOTUtils::RenameFont(stream, familyName, familyNameSize-1));
   2029     if (NULL == rewrittenFontData.get()) {
   2030         return NULL;
   2031     }
   2032 
   2033     // Register the font with GDI.
   2034     HANDLE fontReference = activate_font(rewrittenFontData.get());
   2035     if (NULL == fontReference) {
   2036         return NULL;
   2037     }
   2038 
   2039     // Create the typeface.
   2040     LOGFONT lf;
   2041     logfont_for_name(familyName, &lf);
   2042 
   2043     return SkCreateFontMemResourceTypefaceFromLOGFONT(lf, fontReference);
   2044 }
   2045 
   2046 SkStream* LogFontTypeface::onOpenStream(int* ttcIndex) const {
   2047     *ttcIndex = 0;
   2048 
   2049     const DWORD kTTCTag =
   2050         SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f'));
   2051     LOGFONT lf = fLogFont;
   2052 
   2053     HDC hdc = ::CreateCompatibleDC(NULL);
   2054     HFONT font = CreateFontIndirect(&lf);
   2055     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2056 
   2057     SkMemoryStream* stream = NULL;
   2058     DWORD tables[2] = {kTTCTag, 0};
   2059     for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) {
   2060         DWORD bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
   2061         if (bufferSize == GDI_ERROR) {
   2062             call_ensure_accessible(lf);
   2063             bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
   2064         }
   2065         if (bufferSize != GDI_ERROR) {
   2066             stream = new SkMemoryStream(bufferSize);
   2067             if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(), bufferSize)) {
   2068                 break;
   2069             } else {
   2070                 delete stream;
   2071                 stream = NULL;
   2072             }
   2073         }
   2074     }
   2075 
   2076     SelectObject(hdc, savefont);
   2077     DeleteObject(font);
   2078     DeleteDC(hdc);
   2079 
   2080     return stream;
   2081 }
   2082 
   2083 static void bmpCharsToGlyphs(HDC hdc, const WCHAR* bmpChars, int count, uint16_t* glyphs,
   2084                              bool Ox1FHack)
   2085 {
   2086     DWORD result = GetGlyphIndicesW(hdc, bmpChars, count, glyphs, GGI_MARK_NONEXISTING_GLYPHS);
   2087     if (GDI_ERROR == result) {
   2088         for (int i = 0; i < count; ++i) {
   2089             glyphs[i] = 0;
   2090         }
   2091         return;
   2092     }
   2093 
   2094     if (Ox1FHack) {
   2095         for (int i = 0; i < count; ++i) {
   2096             if (0xFFFF == glyphs[i] || 0x1F == glyphs[i]) {
   2097                 glyphs[i] = 0;
   2098             }
   2099         }
   2100     } else {
   2101         for (int i = 0; i < count; ++i) {
   2102             if (0xFFFF == glyphs[i]){
   2103                 glyphs[i] = 0;
   2104             }
   2105         }
   2106     }
   2107 }
   2108 
   2109 static uint16_t nonBmpCharToGlyph(HDC hdc, SCRIPT_CACHE* scriptCache, const WCHAR utf16[2]) {
   2110     uint16_t index = 0;
   2111     // Use uniscribe to detemine glyph index for non-BMP characters.
   2112     static const int numWCHAR = 2;
   2113     static const int maxItems = 2;
   2114     // MSDN states that this can be NULL, but some things don't work then.
   2115     SCRIPT_CONTROL scriptControl = { 0 };
   2116     // Add extra item to SCRIPT_ITEM to work around a bug (now documented).
   2117     // https://bugzilla.mozilla.org/show_bug.cgi?id=366643
   2118     SCRIPT_ITEM si[maxItems + 1];
   2119     int numItems;
   2120     HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &scriptControl, NULL, si, &numItems),
   2121          "Could not itemize character.");
   2122 
   2123     // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2 space glyphs.
   2124     static const int maxGlyphs = 2;
   2125     SCRIPT_VISATTR vsa[maxGlyphs];
   2126     WORD outGlyphs[maxGlyphs];
   2127     WORD logClust[numWCHAR];
   2128     int numGlyphs;
   2129     HRZM(ScriptShape(hdc, scriptCache, utf16, numWCHAR, maxGlyphs, &si[0].a,
   2130                      outGlyphs, logClust, vsa, &numGlyphs),
   2131          "Could not shape character.");
   2132     if (1 == numGlyphs) {
   2133         index = outGlyphs[0];
   2134     }
   2135     return index;
   2136 }
   2137 
   2138 class SkAutoHDC {
   2139 public:
   2140     SkAutoHDC(const LOGFONT& lf)
   2141         : fHdc(::CreateCompatibleDC(NULL))
   2142         , fFont(::CreateFontIndirect(&lf))
   2143         , fSavefont((HFONT)SelectObject(fHdc, fFont))
   2144     { }
   2145     ~SkAutoHDC() {
   2146         SelectObject(fHdc, fSavefont);
   2147         DeleteObject(fFont);
   2148         DeleteDC(fHdc);
   2149     }
   2150     operator HDC() { return fHdc; }
   2151 private:
   2152     HDC fHdc;
   2153     HFONT fFont;
   2154     HFONT fSavefont;
   2155 };
   2156 #define SkAutoHDC(...) SK_REQUIRE_LOCAL_VAR(SkAutoHDC)
   2157 
   2158 int LogFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
   2159                                      uint16_t userGlyphs[], int glyphCount) const
   2160 {
   2161     SkAutoHDC hdc(fLogFont);
   2162 
   2163     TEXTMETRIC tm;
   2164     if (0 == GetTextMetrics(hdc, &tm)) {
   2165         call_ensure_accessible(fLogFont);
   2166         if (0 == GetTextMetrics(hdc, &tm)) {
   2167             tm.tmPitchAndFamily = TMPF_TRUETYPE;
   2168         }
   2169     }
   2170     bool Ox1FHack = !(tm.tmPitchAndFamily & TMPF_VECTOR) /*&& winVer < Vista */;
   2171 
   2172     SkAutoSTMalloc<256, uint16_t> scratchGlyphs;
   2173     uint16_t* glyphs;
   2174     if (userGlyphs != NULL) {
   2175         glyphs = userGlyphs;
   2176     } else {
   2177         glyphs = scratchGlyphs.reset(glyphCount);
   2178     }
   2179 
   2180     SCRIPT_CACHE sc = 0;
   2181     switch (encoding) {
   2182     case SkTypeface::kUTF8_Encoding: {
   2183         static const int scratchCount = 256;
   2184         WCHAR scratch[scratchCount];
   2185         int glyphIndex = 0;
   2186         const char* currentUtf8 = reinterpret_cast<const char*>(chars);
   2187         SkUnichar currentChar;
   2188         if (glyphCount) {
   2189             currentChar = SkUTF8_NextUnichar(&currentUtf8);
   2190         }
   2191         while (glyphIndex < glyphCount) {
   2192             // Try a run of bmp.
   2193             int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount);
   2194             int runLength = 0;
   2195             while (runLength < glyphsLeft && currentChar <= 0xFFFF) {
   2196                 scratch[runLength] = static_cast<WCHAR>(currentChar);
   2197                 ++runLength;
   2198                 if (runLength < glyphsLeft) {
   2199                     currentChar = SkUTF8_NextUnichar(&currentUtf8);
   2200                 }
   2201             }
   2202             if (runLength) {
   2203                 bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack);
   2204                 glyphIndex += runLength;
   2205             }
   2206 
   2207             // Try a run of non-bmp.
   2208             while (glyphIndex < glyphCount && currentChar > 0xFFFF) {
   2209                 SkUTF16_FromUnichar(currentChar, reinterpret_cast<uint16_t*>(scratch));
   2210                 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch);
   2211                 ++glyphIndex;
   2212                 if (glyphIndex < glyphCount) {
   2213                     currentChar = SkUTF8_NextUnichar(&currentUtf8);
   2214                 }
   2215             }
   2216         }
   2217         break;
   2218     }
   2219     case SkTypeface::kUTF16_Encoding: {
   2220         int glyphIndex = 0;
   2221         const WCHAR* currentUtf16 = reinterpret_cast<const WCHAR*>(chars);
   2222         while (glyphIndex < glyphCount) {
   2223             // Try a run of bmp.
   2224             int glyphsLeft = glyphCount - glyphIndex;
   2225             int runLength = 0;
   2226             while (runLength < glyphsLeft && !SkUTF16_IsHighSurrogate(currentUtf16[runLength])) {
   2227                 ++runLength;
   2228             }
   2229             if (runLength) {
   2230                 bmpCharsToGlyphs(hdc, currentUtf16, runLength, &glyphs[glyphIndex], Ox1FHack);
   2231                 glyphIndex += runLength;
   2232                 currentUtf16 += runLength;
   2233             }
   2234 
   2235             // Try a run of non-bmp.
   2236             while (glyphIndex < glyphCount && SkUTF16_IsHighSurrogate(*currentUtf16)) {
   2237                 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, currentUtf16);
   2238                 ++glyphIndex;
   2239                 currentUtf16 += 2;
   2240             }
   2241         }
   2242         break;
   2243     }
   2244     case SkTypeface::kUTF32_Encoding: {
   2245         static const int scratchCount = 256;
   2246         WCHAR scratch[scratchCount];
   2247         int glyphIndex = 0;
   2248         const uint32_t* utf32 = reinterpret_cast<const uint32_t*>(chars);
   2249         while (glyphIndex < glyphCount) {
   2250             // Try a run of bmp.
   2251             int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount);
   2252             int runLength = 0;
   2253             while (runLength < glyphsLeft && utf32[glyphIndex + runLength] <= 0xFFFF) {
   2254                 scratch[runLength] = static_cast<WCHAR>(utf32[glyphIndex + runLength]);
   2255                 ++runLength;
   2256             }
   2257             if (runLength) {
   2258                 bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack);
   2259                 glyphIndex += runLength;
   2260             }
   2261 
   2262             // Try a run of non-bmp.
   2263             while (glyphIndex < glyphCount && utf32[glyphIndex] > 0xFFFF) {
   2264                 SkUTF16_FromUnichar(utf32[glyphIndex], reinterpret_cast<uint16_t*>(scratch));
   2265                 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch);
   2266                 ++glyphIndex;
   2267             }
   2268         }
   2269         break;
   2270     }
   2271     default:
   2272         SK_CRASH();
   2273     }
   2274 
   2275     if (sc) {
   2276         ::ScriptFreeCache(&sc);
   2277     }
   2278 
   2279     for (int i = 0; i < glyphCount; ++i) {
   2280         if (0 == glyphs[i]) {
   2281             return i;
   2282         }
   2283     }
   2284     return glyphCount;
   2285 }
   2286 
   2287 int LogFontTypeface::onCountGlyphs() const {
   2288     HDC hdc = ::CreateCompatibleDC(NULL);
   2289     HFONT font = CreateFontIndirect(&fLogFont);
   2290     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2291 
   2292     unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont);
   2293 
   2294     SelectObject(hdc, savefont);
   2295     DeleteObject(font);
   2296     DeleteDC(hdc);
   2297 
   2298     return glyphCount;
   2299 }
   2300 
   2301 int LogFontTypeface::onGetUPEM() const {
   2302     HDC hdc = ::CreateCompatibleDC(NULL);
   2303     HFONT font = CreateFontIndirect(&fLogFont);
   2304     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2305 
   2306     unsigned int upem = calculateUPEM(hdc, fLogFont);
   2307 
   2308     SelectObject(hdc, savefont);
   2309     DeleteObject(font);
   2310     DeleteDC(hdc);
   2311 
   2312     return upem;
   2313 }
   2314 
   2315 SkTypeface::LocalizedStrings* LogFontTypeface::onCreateFamilyNameIterator() const {
   2316     SkTypeface::LocalizedStrings* nameIter =
   2317         SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this);
   2318     if (NULL == nameIter) {
   2319         SkString familyName;
   2320         this->getFamilyName(&familyName);
   2321         SkString language("und"); //undetermined
   2322         nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
   2323     }
   2324     return nameIter;
   2325 }
   2326 
   2327 int LogFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
   2328     SkSFNTHeader header;
   2329     if (sizeof(header) != this->onGetTableData(0, 0, sizeof(header), &header)) {
   2330         return 0;
   2331     }
   2332 
   2333     int numTables = SkEndian_SwapBE16(header.numTables);
   2334 
   2335     if (tags) {
   2336         size_t size = numTables * sizeof(SkSFNTHeader::TableDirectoryEntry);
   2337         SkAutoSTMalloc<0x20, SkSFNTHeader::TableDirectoryEntry> dir(numTables);
   2338         if (size != this->onGetTableData(0, sizeof(header), size, dir.get())) {
   2339             return 0;
   2340         }
   2341 
   2342         for (int i = 0; i < numTables; ++i) {
   2343             tags[i] = SkEndian_SwapBE32(dir[i].tag);
   2344         }
   2345     }
   2346     return numTables;
   2347 }
   2348 
   2349 size_t LogFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
   2350                                        size_t length, void* data) const
   2351 {
   2352     LOGFONT lf = fLogFont;
   2353 
   2354     HDC hdc = ::CreateCompatibleDC(NULL);
   2355     HFONT font = CreateFontIndirect(&lf);
   2356     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2357 
   2358     tag = SkEndian_SwapBE32(tag);
   2359     if (NULL == data) {
   2360         length = 0;
   2361     }
   2362     DWORD bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) length);
   2363     if (bufferSize == GDI_ERROR) {
   2364         call_ensure_accessible(lf);
   2365         bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) length);
   2366     }
   2367 
   2368     SelectObject(hdc, savefont);
   2369     DeleteObject(font);
   2370     DeleteDC(hdc);
   2371 
   2372     return bufferSize == GDI_ERROR ? 0 : bufferSize;
   2373 }
   2374 
   2375 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
   2376     SkScalerContext_GDI* ctx = SkNEW_ARGS(SkScalerContext_GDI,
   2377                                                 (const_cast<LogFontTypeface*>(this), desc));
   2378     if (!ctx->isValid()) {
   2379         SkDELETE(ctx);
   2380         ctx = NULL;
   2381     }
   2382     return ctx;
   2383 }
   2384 
   2385 void LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const {
   2386     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
   2387         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
   2388     {
   2389         rec->fMaskFormat = SkMask::kA8_Format;
   2390         rec->fFlags |= SkScalerContext::kGenA8FromLCD_Flag;
   2391     }
   2392 
   2393     unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
   2394                                   SkScalerContext::kAutohinting_Flag |
   2395                                   SkScalerContext::kEmbeddedBitmapText_Flag |
   2396                                   SkScalerContext::kEmbolden_Flag |
   2397                                   SkScalerContext::kLCD_BGROrder_Flag |
   2398                                   SkScalerContext::kLCD_Vertical_Flag;
   2399     rec->fFlags &= ~flagsWeDontSupport;
   2400 
   2401     SkPaint::Hinting h = rec->getHinting();
   2402     switch (h) {
   2403         case SkPaint::kNo_Hinting:
   2404             break;
   2405         case SkPaint::kSlight_Hinting:
   2406             // Only do slight hinting when axis aligned.
   2407             // TODO: re-enable slight hinting when FontHostTest can pass.
   2408             //if (!isAxisAligned(*rec)) {
   2409                 h = SkPaint::kNo_Hinting;
   2410             //}
   2411             break;
   2412         case SkPaint::kNormal_Hinting:
   2413         case SkPaint::kFull_Hinting:
   2414             // TODO: need to be able to distinguish subpixel positioned glyphs
   2415             // and linear metrics.
   2416             //rec->fFlags &= ~SkScalerContext::kSubpixelPositioning_Flag;
   2417             h = SkPaint::kNormal_Hinting;
   2418             break;
   2419         default:
   2420             SkDEBUGFAIL("unknown hinting");
   2421     }
   2422     //TODO: if this is a bitmap font, squash hinting and subpixel.
   2423     rec->setHinting(h);
   2424 
   2425 // turn this off since GDI might turn A8 into BW! Need a bigger fix.
   2426 #if 0
   2427     // Disable LCD when rotated, since GDI's output is ugly
   2428     if (isLCD(*rec) && !isAxisAligned(*rec)) {
   2429         rec->fMaskFormat = SkMask::kA8_Format;
   2430     }
   2431 #endif
   2432 
   2433     if (!fCanBeLCD && isLCD(*rec)) {
   2434         rec->fMaskFormat = SkMask::kA8_Format;
   2435         rec->fFlags &= ~SkScalerContext::kGenA8FromLCD_Flag;
   2436     }
   2437 }
   2438 
   2439 ///////////////////////////////////////////////////////////////////////////////
   2440 
   2441 #include "SkFontMgr.h"
   2442 #include "SkDataTable.h"
   2443 
   2444 static bool valid_logfont_for_enum(const LOGFONT& lf) {
   2445     // TODO: Vector FON is unsupported and should not be listed.
   2446     return
   2447         // Ignore implicit vertical variants.
   2448         lf.lfFaceName[0] && lf.lfFaceName[0] != '@'
   2449 
   2450         // DEFAULT_CHARSET is used to get all fonts, but also implies all
   2451         // character sets. Filter assuming all fonts support ANSI_CHARSET.
   2452         && ANSI_CHARSET == lf.lfCharSet
   2453     ;
   2454 }
   2455 
   2456 /** An EnumFontFamExProc implementation which interprets builderParam as
   2457  *  an SkTDArray<ENUMLOGFONTEX>* and appends logfonts which
   2458  *  pass the valid_logfont_for_enum predicate.
   2459  */
   2460 static int CALLBACK enum_family_proc(const LOGFONT* lf, const TEXTMETRIC*,
   2461                                      DWORD fontType, LPARAM builderParam) {
   2462     if (valid_logfont_for_enum(*lf)) {
   2463         SkTDArray<ENUMLOGFONTEX>* array = (SkTDArray<ENUMLOGFONTEX>*)builderParam;
   2464         *array->append() = *(ENUMLOGFONTEX*)lf;
   2465     }
   2466     return 1; // non-zero means continue
   2467 }
   2468 
   2469 static SkFontStyle compute_fontstyle(const LOGFONT& lf) {
   2470     return SkFontStyle(lf.lfWeight, SkFontStyle::kNormal_Width,
   2471                        lf.lfItalic ? SkFontStyle::kItalic_Slant
   2472                                    : SkFontStyle::kUpright_Slant);
   2473 }
   2474 
   2475 class SkFontStyleSetGDI : public SkFontStyleSet {
   2476 public:
   2477     SkFontStyleSetGDI(const TCHAR familyName[]) {
   2478         LOGFONT lf;
   2479         sk_bzero(&lf, sizeof(lf));
   2480         lf.lfCharSet = DEFAULT_CHARSET;
   2481         _tcscpy_s(lf.lfFaceName, familyName);
   2482 
   2483         HDC hdc = ::CreateCompatibleDC(NULL);
   2484         ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fArray, 0);
   2485         ::DeleteDC(hdc);
   2486     }
   2487 
   2488     virtual int count() SK_OVERRIDE {
   2489         return fArray.count();
   2490     }
   2491 
   2492     virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE {
   2493         if (fs) {
   2494             *fs = compute_fontstyle(fArray[index].elfLogFont);
   2495         }
   2496         if (styleName) {
   2497             const ENUMLOGFONTEX& ref = fArray[index];
   2498             // For some reason, ENUMLOGFONTEX and LOGFONT disagree on their type in the
   2499             // non-unicode version.
   2500             //      ENUMLOGFONTEX uses BYTE
   2501             //      LOGFONT uses CHAR
   2502             // Here we assert they that the style name is logically the same (size) as
   2503             // a TCHAR, so we can use the same converter function.
   2504             SkASSERT(sizeof(TCHAR) == sizeof(ref.elfStyle[0]));
   2505             tchar_to_skstring((const TCHAR*)ref.elfStyle, styleName);
   2506         }
   2507     }
   2508 
   2509     virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
   2510         return SkCreateTypefaceFromLOGFONT(fArray[index].elfLogFont);
   2511     }
   2512 
   2513     virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
   2514         // todo:
   2515         return SkCreateTypefaceFromLOGFONT(fArray[0].elfLogFont);
   2516     }
   2517 
   2518 private:
   2519     SkTDArray<ENUMLOGFONTEX> fArray;
   2520 };
   2521 
   2522 class SkFontMgrGDI : public SkFontMgr {
   2523 public:
   2524     SkFontMgrGDI() {
   2525         LOGFONT lf;
   2526         sk_bzero(&lf, sizeof(lf));
   2527         lf.lfCharSet = DEFAULT_CHARSET;
   2528 
   2529         HDC hdc = ::CreateCompatibleDC(NULL);
   2530         ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fLogFontArray, 0);
   2531         ::DeleteDC(hdc);
   2532     }
   2533 
   2534 protected:
   2535     virtual int onCountFamilies() SK_OVERRIDE {
   2536         return fLogFontArray.count();
   2537     }
   2538 
   2539     virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
   2540         SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
   2541         tchar_to_skstring(fLogFontArray[index].elfLogFont.lfFaceName, familyName);
   2542     }
   2543 
   2544     virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE {
   2545         SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
   2546         return SkNEW_ARGS(SkFontStyleSetGDI, (fLogFontArray[index].elfLogFont.lfFaceName));
   2547     }
   2548 
   2549     virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE {
   2550         if (NULL == familyName) {
   2551             familyName = "";    // do we need this check???
   2552         }
   2553         LOGFONT lf;
   2554         logfont_for_name(familyName, &lf);
   2555         return SkNEW_ARGS(SkFontStyleSetGDI, (lf.lfFaceName));
   2556     }
   2557 
   2558     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
   2559                                            const SkFontStyle& fontstyle) SK_OVERRIDE {
   2560         // could be in base impl
   2561         SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
   2562         return sset->matchStyle(fontstyle);
   2563     }
   2564 
   2565     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
   2566                                          const SkFontStyle& fontstyle) SK_OVERRIDE {
   2567         // could be in base impl
   2568         SkString familyName;
   2569         ((LogFontTypeface*)familyMember)->getFamilyName(&familyName);
   2570         return this->matchFamilyStyle(familyName.c_str(), fontstyle);
   2571     }
   2572 
   2573     virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) SK_OVERRIDE {
   2574         return create_from_stream(stream);
   2575     }
   2576 
   2577     virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) SK_OVERRIDE {
   2578         // could be in base impl
   2579         SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
   2580         return this->createFromStream(stream);
   2581     }
   2582 
   2583     virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE {
   2584         // could be in base impl
   2585         SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
   2586         return this->createFromStream(stream);
   2587     }
   2588 
   2589     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
   2590                                                unsigned styleBits) SK_OVERRIDE {
   2591         LOGFONT lf;
   2592         if (NULL == familyName) {
   2593             lf = get_default_font();
   2594         } else {
   2595             logfont_for_name(familyName, &lf);
   2596         }
   2597         setStyle(&lf, (SkTypeface::Style)styleBits);
   2598         return SkCreateTypefaceFromLOGFONT(lf);
   2599     }
   2600 
   2601 private:
   2602     SkTDArray<ENUMLOGFONTEX> fLogFontArray;
   2603 };
   2604 
   2605 ///////////////////////////////////////////////////////////////////////////////
   2606 
   2607 SkFontMgr* SkFontMgr_New_GDI() {
   2608     return SkNEW(SkFontMgrGDI);
   2609 }
   2610