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