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 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE;
    280     virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE;
    281     virtual size_t onGetTableData(SkFontTableTag, size_t offset,
    282                                   size_t length, void* data) const SK_OVERRIDE;
    283 };
    284 
    285 class FontMemResourceTypeface : public LogFontTypeface {
    286 public:
    287     /**
    288      *  The created FontMemResourceTypeface takes ownership of fontMemResource.
    289      */
    290     static FontMemResourceTypeface* Create(const LOGFONT& lf, HANDLE fontMemResource) {
    291         SkTypeface::Style style = get_style(lf);
    292         SkFontID fontID = SkTypefaceCache::NewFontID();
    293         return new FontMemResourceTypeface(style, fontID, lf, fontMemResource);
    294     }
    295 
    296 protected:
    297     virtual void weak_dispose() const SK_OVERRIDE {
    298         RemoveFontMemResourceEx(fFontMemResource);
    299         //SkTypefaceCache::Remove(this);
    300         INHERITED::weak_dispose();
    301     }
    302 
    303 private:
    304     /**
    305      *  Takes ownership of fontMemResource.
    306      */
    307     FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) :
    308         LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) {
    309     }
    310 
    311     HANDLE fFontMemResource;
    312 
    313     typedef LogFontTypeface INHERITED;
    314 };
    315 
    316 static const LOGFONT& get_default_font() {
    317     static LOGFONT gDefaultFont;
    318     return gDefaultFont;
    319 }
    320 
    321 static bool FindByLogFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
    322     LogFontTypeface* lface = static_cast<LogFontTypeface*>(face);
    323     const LOGFONT* lf = reinterpret_cast<const LOGFONT*>(ctx);
    324 
    325     return lface &&
    326            get_style(lface->fLogFont) == requestedStyle &&
    327            !memcmp(&lface->fLogFont, lf, sizeof(LOGFONT));
    328 }
    329 
    330 /**
    331  *  This guy is public. It first searches the cache, and if a match is not found,
    332  *  it creates a new face.
    333  */
    334 SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) {
    335     LOGFONT lf = origLF;
    336     make_canonical(&lf);
    337     SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf);
    338     if (NULL == face) {
    339         face = LogFontTypeface::Create(lf);
    340         SkTypefaceCache::Add(face, get_style(lf));
    341     }
    342     return face;
    343 }
    344 
    345 /**
    346  *  The created SkTypeface takes ownership of fontMemResource.
    347  */
    348 SkTypeface* SkCreateFontMemResourceTypefaceFromLOGFONT(const LOGFONT& origLF, HANDLE fontMemResource) {
    349     LOGFONT lf = origLF;
    350     make_canonical(&lf);
    351     FontMemResourceTypeface* face = FontMemResourceTypeface::Create(lf, fontMemResource);
    352     SkTypefaceCache::Add(face, get_style(lf), false);
    353     return face;
    354 }
    355 
    356 /**
    357  *  This guy is public
    358  */
    359 void SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) {
    360     if (NULL == face) {
    361         *lf = get_default_font();
    362     } else {
    363         *lf = static_cast<const LogFontTypeface*>(face)->fLogFont;
    364     }
    365 }
    366 
    367 // Construct Glyph to Unicode table.
    368 // Unicode code points that require conjugate pairs in utf16 are not
    369 // supported.
    370 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
    371 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead
    372 // of calling GetFontUnicodeRange().
    373 static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount,
    374                                       SkTDArray<SkUnichar>* glyphToUnicode) {
    375     DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, NULL);
    376     if (!glyphSetBufferSize) {
    377         return;
    378     }
    379 
    380     SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]);
    381     GLYPHSET* glyphSet =
    382         reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get());
    383     if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) {
    384         return;
    385     }
    386 
    387     glyphToUnicode->setCount(glyphCount);
    388     memset(glyphToUnicode->begin(), 0, glyphCount * sizeof(SkUnichar));
    389     for (DWORD i = 0; i < glyphSet->cRanges; ++i) {
    390         // There is no guarantee that within a Unicode range, the corresponding
    391         // glyph id in a font file are continuous. So, even if we have ranges,
    392         // we can't just use the first and last entry of the range to compute
    393         // result. We need to enumerate them one by one.
    394         int count = glyphSet->ranges[i].cGlyphs;
    395         SkAutoTArray<WCHAR> chars(count + 1);
    396         chars[count] = 0;  // termintate string
    397         SkAutoTArray<WORD> glyph(count);
    398         for (USHORT j = 0; j < count; ++j) {
    399             chars[j] = glyphSet->ranges[i].wcLow + j;
    400         }
    401         GetGlyphIndicesW(fontHdc, chars.get(), count, glyph.get(),
    402                          GGI_MARK_NONEXISTING_GLYPHS);
    403         // If the glyph ID is valid, and the glyph is not mapped, then we will
    404         // fill in the char id into the vector. If the glyph is mapped already,
    405         // skip it.
    406         // TODO(arthurhsu): better improve this. e.g. Get all used char ids from
    407         // font cache, then generate this mapping table from there. It's
    408         // unlikely to have collisions since glyph reuse happens mostly for
    409         // different Unicode pages.
    410         for (USHORT j = 0; j < count; ++j) {
    411             if (glyph[j] != 0xffff && glyph[j] < glyphCount &&
    412                 (*glyphToUnicode)[glyph[j]] == 0) {
    413                 (*glyphToUnicode)[glyph[j]] = chars[j];
    414             }
    415         }
    416     }
    417 }
    418 
    419 //////////////////////////////////////////////////////////////////////////////////////
    420 
    421 static int alignTo32(int n) {
    422     return (n + 31) & ~31;
    423 }
    424 
    425 struct MyBitmapInfo : public BITMAPINFO {
    426     RGBQUAD fMoreSpaceForColors[1];
    427 };
    428 
    429 class HDCOffscreen {
    430 public:
    431     HDCOffscreen() {
    432         fFont = 0;
    433         fDC = 0;
    434         fBM = 0;
    435         fBits = NULL;
    436         fWidth = fHeight = 0;
    437         fIsBW = false;
    438     }
    439 
    440     ~HDCOffscreen() {
    441         if (fDC) {
    442             DeleteDC(fDC);
    443         }
    444         if (fBM) {
    445             DeleteObject(fBM);
    446         }
    447     }
    448 
    449     void init(HFONT font, const XFORM& xform) {
    450         fFont = font;
    451         fXform = xform;
    452     }
    453 
    454     const void* draw(const SkGlyph&, bool isBW, size_t* srcRBPtr);
    455 
    456 private:
    457     HDC     fDC;
    458     HBITMAP fBM;
    459     HFONT   fFont;
    460     XFORM   fXform;
    461     void*   fBits;  // points into fBM
    462     int     fWidth;
    463     int     fHeight;
    464     bool    fIsBW;
    465 };
    466 
    467 const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW,
    468                                size_t* srcRBPtr) {
    469     // Can we share the scalercontext's fDDC, so we don't need to create
    470     // a separate fDC here?
    471     if (0 == fDC) {
    472         fDC = CreateCompatibleDC(0);
    473         if (0 == fDC) {
    474             return NULL;
    475         }
    476         SetGraphicsMode(fDC, GM_ADVANCED);
    477         SetBkMode(fDC, TRANSPARENT);
    478         SetTextAlign(fDC, TA_LEFT | TA_BASELINE);
    479         SelectObject(fDC, fFont);
    480 
    481         COLORREF color = 0x00FFFFFF;
    482         SkDEBUGCODE(COLORREF prev =) SetTextColor(fDC, color);
    483         SkASSERT(prev != CLR_INVALID);
    484     }
    485 
    486     if (fBM && (fIsBW != isBW || fWidth < glyph.fWidth || fHeight < glyph.fHeight)) {
    487         DeleteObject(fBM);
    488         fBM = 0;
    489     }
    490     fIsBW = isBW;
    491 
    492     fWidth = SkMax32(fWidth, glyph.fWidth);
    493     fHeight = SkMax32(fHeight, glyph.fHeight);
    494 
    495     int biWidth = isBW ? alignTo32(fWidth) : fWidth;
    496 
    497     if (0 == fBM) {
    498         MyBitmapInfo info;
    499         sk_bzero(&info, sizeof(info));
    500         if (isBW) {
    501             RGBQUAD blackQuad = { 0, 0, 0, 0 };
    502             RGBQUAD whiteQuad = { 0xFF, 0xFF, 0xFF, 0 };
    503             info.bmiColors[0] = blackQuad;
    504             info.bmiColors[1] = whiteQuad;
    505         }
    506         info.bmiHeader.biSize = sizeof(info.bmiHeader);
    507         info.bmiHeader.biWidth = biWidth;
    508         info.bmiHeader.biHeight = fHeight;
    509         info.bmiHeader.biPlanes = 1;
    510         info.bmiHeader.biBitCount = isBW ? 1 : 32;
    511         info.bmiHeader.biCompression = BI_RGB;
    512         if (isBW) {
    513             info.bmiHeader.biClrUsed = 2;
    514         }
    515         fBM = CreateDIBSection(fDC, &info, DIB_RGB_COLORS, &fBits, 0, 0);
    516         if (0 == fBM) {
    517             return NULL;
    518         }
    519         SelectObject(fDC, fBM);
    520     }
    521 
    522     // erase
    523     size_t srcRB = isBW ? (biWidth >> 3) : (fWidth << 2);
    524     size_t size = fHeight * srcRB;
    525     memset(fBits, 0, size);
    526 
    527     XFORM xform = fXform;
    528     xform.eDx = (float)-glyph.fLeft;
    529     xform.eDy = (float)-glyph.fTop;
    530     SetWorldTransform(fDC, &xform);
    531 
    532     uint16_t glyphID = glyph.getGlyphID();
    533     BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, NULL, reinterpret_cast<LPCWSTR>(&glyphID), 1, NULL);
    534     GdiFlush();
    535     if (0 == ret) {
    536         return NULL;
    537     }
    538     *srcRBPtr = srcRB;
    539     // offset to the start of the image
    540     return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB;
    541 }
    542 
    543 //////////////////////////////////////////////////////////////////////////////
    544 #define BUFFERSIZE (1 << 13)
    545 
    546 class SkScalerContext_GDI : public SkScalerContext {
    547 public:
    548     SkScalerContext_GDI(SkTypeface*, const SkDescriptor* desc);
    549     virtual ~SkScalerContext_GDI();
    550 
    551     // Returns true if the constructor was able to complete all of its
    552     // initializations (which may include calling GDI).
    553     bool isValid() const;
    554 
    555 protected:
    556     virtual unsigned generateGlyphCount() SK_OVERRIDE;
    557     virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
    558     virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
    559     virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
    560     virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
    561     virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
    562     virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
    563                                      SkPaint::FontMetrics* mY) 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(0);
    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(0);
    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* mx, SkPaint::FontMetrics* my) {
    982     if (!(mx || my)) {
    983       return;
    984     }
    985 
    986     if (mx) {
    987         sk_bzero(mx, sizeof(*mx));
    988     }
    989     if (my) {
    990         sk_bzero(my, sizeof(*my));
    991     }
    992 
    993     SkASSERT(fDDC);
    994 
    995 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
    996     if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) {
    997 #endif
    998         if (mx) {
    999             mx->fTop = SkIntToScalar(-fTM.tmAscent);
   1000             mx->fAscent = SkIntToScalar(-fTM.tmAscent);
   1001             mx->fDescent = SkIntToScalar(fTM.tmDescent);
   1002             mx->fBottom = SkIntToScalar(fTM.tmDescent);
   1003             mx->fLeading = SkIntToScalar(fTM.tmExternalLeading);
   1004         }
   1005 
   1006         if (my) {
   1007             my->fTop = SkIntToScalar(-fTM.tmAscent);
   1008             my->fAscent = SkIntToScalar(-fTM.tmAscent);
   1009             my->fDescent = SkIntToScalar(fTM.tmDescent);
   1010             my->fBottom = SkIntToScalar(fTM.tmDescent);
   1011             my->fLeading = SkIntToScalar(fTM.tmExternalLeading);
   1012             my->fAvgCharWidth = SkIntToScalar(fTM.tmAveCharWidth);
   1013             my->fMaxCharWidth = SkIntToScalar(fTM.tmMaxCharWidth);
   1014             my->fXMin = 0;
   1015             my->fXMax = my->fMaxCharWidth;
   1016             //my->fXHeight = 0;
   1017         }
   1018 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
   1019         return;
   1020     }
   1021 #endif
   1022 
   1023     OUTLINETEXTMETRIC otm;
   1024 
   1025     uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
   1026     if (0 == ret) {
   1027         LogFontTypeface::EnsureAccessible(this->getTypeface());
   1028         ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
   1029     }
   1030     if (0 == ret) {
   1031         return;
   1032     }
   1033 
   1034     if (mx) {
   1035         mx->fTop = SkIntToScalar(-otm.otmrcFontBox.left);
   1036         mx->fAscent = SkIntToScalar(-otm.otmAscent);
   1037         mx->fDescent = SkIntToScalar(-otm.otmDescent);
   1038         mx->fBottom = SkIntToScalar(otm.otmrcFontBox.right);
   1039         mx->fLeading = SkIntToScalar(otm.otmLineGap);
   1040         mx->fUnderlineThickness = SkIntToScalar(otm.otmsUnderscoreSize);
   1041         mx->fUnderlinePosition = -SkIntToScalar(otm.otmsUnderscorePosition);
   1042 
   1043         mx->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
   1044         mx->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
   1045     }
   1046 
   1047     if (my) {
   1048 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS
   1049         my->fTop = SkIntToScalar(-otm.otmrcFontBox.top);
   1050         my->fAscent = SkIntToScalar(-otm.otmAscent);
   1051         my->fDescent = SkIntToScalar(-otm.otmDescent);
   1052         my->fBottom = SkIntToScalar(-otm.otmrcFontBox.bottom);
   1053         my->fLeading = SkIntToScalar(otm.otmLineGap);
   1054         my->fAvgCharWidth = SkIntToScalar(otm.otmTextMetrics.tmAveCharWidth);
   1055         my->fMaxCharWidth = SkIntToScalar(otm.otmTextMetrics.tmMaxCharWidth);
   1056         my->fXMin = SkIntToScalar(otm.otmrcFontBox.left);
   1057         my->fXMax = SkIntToScalar(otm.otmrcFontBox.right);
   1058 #endif
   1059         my->fUnderlineThickness = SkIntToScalar(otm.otmsUnderscoreSize);
   1060         my->fUnderlinePosition = -SkIntToScalar(otm.otmsUnderscorePosition);
   1061 
   1062         my->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag;
   1063         my->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag;
   1064 
   1065         my->fXHeight = SkIntToScalar(otm.otmsXHeight);
   1066 
   1067         GLYPHMETRICS gm;
   1068         sk_bzero(&gm, sizeof(gm));
   1069         DWORD len = GetGlyphOutlineW(fDDC, 'x', GGO_METRICS, &gm, 0, 0, &gMat2Identity);
   1070         if (len != GDI_ERROR && gm.gmBlackBoxY > 0) {
   1071             my->fXHeight = SkIntToScalar(gm.gmBlackBoxY);
   1072         }
   1073     }
   1074 }
   1075 
   1076 ////////////////////////////////////////////////////////////////////////////////////////
   1077 
   1078 #define SK_SHOW_TEXT_BLIT_COVERAGE 0
   1079 
   1080 static void build_power_table(uint8_t table[], float ee) {
   1081     for (int i = 0; i < 256; i++) {
   1082         float x = i / 255.f;
   1083         x = sk_float_pow(x, ee);
   1084         int xx = SkScalarRoundToInt(x * 255);
   1085         table[i] = SkToU8(xx);
   1086     }
   1087 }
   1088 
   1089 /**
   1090  *  This will invert the gamma applied by GDI (gray-scale antialiased), so we
   1091  *  can get linear values.
   1092  *
   1093  *  GDI grayscale appears to use a hard-coded gamma of 2.3.
   1094  *
   1095  *  GDI grayscale appears to draw using the black and white rasterizer at four
   1096  *  times the size and then downsamples to compute the coverage mask. As a
   1097  *  result there are only seventeen total grays. This lack of fidelity means
   1098  *  that shifting into other color spaces is imprecise.
   1099  */
   1100 static const uint8_t* getInverseGammaTableGDI() {
   1101     // Since build_power_table is idempotent, many threads can build gTableGdi
   1102     // simultaneously.
   1103 
   1104     // Microsoft Specific:
   1105     // Making gInited volatile provides read-aquire and write-release in vc++.
   1106     // In VS2012, see compiler option /volatile:(ms|iso).
   1107     // Replace with C++11 atomics when possible.
   1108     static volatile bool gInited;
   1109     static uint8_t gTableGdi[256];
   1110     if (gInited) {
   1111         // Need a L/L (read) barrier (full acquire not needed). If gInited is observed
   1112         // true then gTableGdi is observable, but it must be requested.
   1113     } else {
   1114         build_power_table(gTableGdi, 2.3f);
   1115         // Need a S/S (write) barrier (full release not needed) here so that this
   1116         // write to gInited becomes observable after gTableGdi.
   1117         gInited = true;
   1118     }
   1119     return gTableGdi;
   1120 }
   1121 
   1122 /**
   1123  *  This will invert the gamma applied by GDI ClearType, so we can get linear
   1124  *  values.
   1125  *
   1126  *  GDI ClearType uses SPI_GETFONTSMOOTHINGCONTRAST / 1000 as the gamma value.
   1127  *  If this value is not specified, the default is a gamma of 1.4.
   1128  */
   1129 static const uint8_t* getInverseGammaTableClearType() {
   1130     // We don't expect SPI_GETFONTSMOOTHINGCONTRAST to ever change, so building
   1131     // gTableClearType with build_power_table is effectively idempotent.
   1132 
   1133     // Microsoft Specific:
   1134     // Making gInited volatile provides read-aquire and write-release in vc++.
   1135     // In VS2012, see compiler option /volatile:(ms|iso).
   1136     // Replace with C++11 atomics when possible.
   1137     static volatile bool gInited;
   1138     static uint8_t gTableClearType[256];
   1139     if (gInited) {
   1140         // Need a L/L (read) barrier (acquire not needed). If gInited is observed
   1141         // true then gTableClearType is observable, but it must be requested.
   1142     } else {
   1143         UINT level = 0;
   1144         if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) {
   1145             // can't get the data, so use a default
   1146             level = 1400;
   1147         }
   1148         build_power_table(gTableClearType, level / 1000.0f);
   1149         // Need a S/S (write) barrier (release not needed) here so that this
   1150         // write to gInited becomes observable after gTableClearType.
   1151         gInited = true;
   1152     }
   1153     return gTableClearType;
   1154 }
   1155 
   1156 #include "SkColorPriv.h"
   1157 
   1158 //Cannot assume that the input rgb is gray due to possible setting of kGenA8FromLCD_Flag.
   1159 template<bool APPLY_PREBLEND>
   1160 static inline uint8_t rgb_to_a8(SkGdiRGB rgb, const uint8_t* table8) {
   1161     U8CPU r = (rgb >> 16) & 0xFF;
   1162     U8CPU g = (rgb >>  8) & 0xFF;
   1163     U8CPU b = (rgb >>  0) & 0xFF;
   1164     return sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
   1165 }
   1166 
   1167 template<bool APPLY_PREBLEND>
   1168 static inline uint16_t rgb_to_lcd16(SkGdiRGB rgb, const uint8_t* tableR,
   1169                                                   const uint8_t* tableG,
   1170                                                   const uint8_t* tableB) {
   1171     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
   1172     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
   1173     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
   1174 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1175     r = SkMax32(r, 10); g = SkMax32(g, 10); b = SkMax32(b, 10);
   1176 #endif
   1177     return SkPack888ToRGB16(r, g, b);
   1178 }
   1179 
   1180 template<bool APPLY_PREBLEND>
   1181 static inline SkPMColor rgb_to_lcd32(SkGdiRGB rgb, const uint8_t* tableR,
   1182                                                    const uint8_t* tableG,
   1183                                                    const uint8_t* tableB) {
   1184     U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
   1185     U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
   1186     U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
   1187 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1188     r = SkMax32(r, 10); g = SkMax32(g, 10); b = SkMax32(b, 10);
   1189 #endif
   1190     return SkPackARGB32(0xFF, r, g, b);
   1191 }
   1192 
   1193 // Is this GDI color neither black nor white? If so, we have to keep this
   1194 // image as is, rather than smashing it down to a BW mask.
   1195 //
   1196 // returns int instead of bool, since we don't want/have to pay to convert
   1197 // the zero/non-zero value into a bool
   1198 static int is_not_black_or_white(SkGdiRGB c) {
   1199     // same as (but faster than)
   1200     //      c &= 0x00FFFFFF;
   1201     //      return 0 == c || 0x00FFFFFF == c;
   1202     return (c + (c & 1)) & 0x00FFFFFF;
   1203 }
   1204 
   1205 static bool is_rgb_really_bw(const SkGdiRGB* src, int width, int height, size_t srcRB) {
   1206     for (int y = 0; y < height; ++y) {
   1207         for (int x = 0; x < width; ++x) {
   1208             if (is_not_black_or_white(src[x])) {
   1209                 return false;
   1210             }
   1211         }
   1212         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1213     }
   1214     return true;
   1215 }
   1216 
   1217 // gdi's bitmap is upside-down, so we reverse dst walking in Y
   1218 // whenever we copy it into skia's buffer
   1219 static void rgb_to_bw(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
   1220                       const SkGlyph& glyph) {
   1221     const int width = glyph.fWidth;
   1222     const size_t dstRB = (width + 7) >> 3;
   1223     uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1224 
   1225     int byteCount = width >> 3;
   1226     int bitCount = width & 7;
   1227 
   1228     // adjust srcRB to skip the values in our byteCount loop,
   1229     // since we increment src locally there
   1230     srcRB -= byteCount * 8 * sizeof(SkGdiRGB);
   1231 
   1232     for (int y = 0; y < glyph.fHeight; ++y) {
   1233         if (byteCount > 0) {
   1234             for (int i = 0; i < byteCount; ++i) {
   1235                 unsigned byte = 0;
   1236                 byte |= src[0] & (1 << 7);
   1237                 byte |= src[1] & (1 << 6);
   1238                 byte |= src[2] & (1 << 5);
   1239                 byte |= src[3] & (1 << 4);
   1240                 byte |= src[4] & (1 << 3);
   1241                 byte |= src[5] & (1 << 2);
   1242                 byte |= src[6] & (1 << 1);
   1243                 byte |= src[7] & (1 << 0);
   1244                 dst[i] = byte;
   1245                 src += 8;
   1246             }
   1247         }
   1248         if (bitCount > 0) {
   1249             unsigned byte = 0;
   1250             unsigned mask = 0x80;
   1251             for (int i = 0; i < bitCount; i++) {
   1252                 byte |= src[i] & mask;
   1253                 mask >>= 1;
   1254             }
   1255             dst[byteCount] = byte;
   1256         }
   1257         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1258         dst -= dstRB;
   1259     }
   1260 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1261     if (glyph.fWidth > 0 && glyph.fHeight > 0) {
   1262         uint8_t* first = (uint8_t*)glyph.fImage;
   1263         uint8_t* last = (uint8_t*)((char*)glyph.fImage + glyph.fHeight * dstRB - 1);
   1264         *first |= 1 << 7;
   1265         *last |= bitCount == 0 ? 1 : 1 << (8 - bitCount);
   1266     }
   1267 #endif
   1268 }
   1269 
   1270 template<bool APPLY_PREBLEND>
   1271 static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
   1272                       const SkGlyph& glyph, const uint8_t* table8) {
   1273     const size_t dstRB = glyph.rowBytes();
   1274     const int width = glyph.fWidth;
   1275     uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1276 
   1277     for (int y = 0; y < glyph.fHeight; y++) {
   1278         for (int i = 0; i < width; i++) {
   1279             dst[i] = rgb_to_a8<APPLY_PREBLEND>(src[i], table8);
   1280 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1281             dst[i] = SkMax32(dst[i], 10);
   1282 #endif
   1283         }
   1284         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1285         dst -= dstRB;
   1286     }
   1287 }
   1288 
   1289 template<bool APPLY_PREBLEND>
   1290 static void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph,
   1291                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1292     const size_t dstRB = glyph.rowBytes();
   1293     const int width = glyph.fWidth;
   1294     uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1295 
   1296     for (int y = 0; y < glyph.fHeight; y++) {
   1297         for (int i = 0; i < width; i++) {
   1298             dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
   1299         }
   1300         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1301         dst = (uint16_t*)((char*)dst - dstRB);
   1302     }
   1303 }
   1304 
   1305 template<bool APPLY_PREBLEND>
   1306 static void rgb_to_lcd32(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph,
   1307                          const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
   1308     const size_t dstRB = glyph.rowBytes();
   1309     const int width = glyph.fWidth;
   1310     uint32_t* SK_RESTRICT dst = (uint32_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1311 
   1312     for (int y = 0; y < glyph.fHeight; y++) {
   1313         for (int i = 0; i < width; i++) {
   1314             dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
   1315         }
   1316         src = SkTAddOffset<const SkGdiRGB>(src, srcRB);
   1317         dst = (uint32_t*)((char*)dst - dstRB);
   1318     }
   1319 }
   1320 
   1321 static inline unsigned clamp255(unsigned x) {
   1322     SkASSERT(x <= 256);
   1323     return x - (x >> 8);
   1324 }
   1325 
   1326 void SkScalerContext_GDI::generateImage(const SkGlyph& glyph) {
   1327     SkASSERT(fDDC);
   1328 
   1329     const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
   1330     const bool isAA = !isLCD(fRec);
   1331 
   1332     size_t srcRB;
   1333     const void* bits = fOffscreen.draw(glyph, isBW, &srcRB);
   1334     if (NULL == bits) {
   1335         LogFontTypeface::EnsureAccessible(this->getTypeface());
   1336         bits = fOffscreen.draw(glyph, isBW, &srcRB);
   1337         if (NULL == bits) {
   1338             sk_bzero(glyph.fImage, glyph.computeImageSize());
   1339             return;
   1340         }
   1341     }
   1342 
   1343     if (!isBW) {
   1344         const uint8_t* table;
   1345         //The offscreen contains a GDI blit if isAA and kGenA8FromLCD_Flag is not set.
   1346         //Otherwise the offscreen contains a ClearType blit.
   1347         if (isAA && !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
   1348             table = getInverseGammaTableGDI();
   1349         } else {
   1350             table = getInverseGammaTableClearType();
   1351         }
   1352         //Note that the following cannot really be integrated into the
   1353         //pre-blend, since we may not be applying the pre-blend; when we aren't
   1354         //applying the pre-blend it means that a filter wants linear anyway.
   1355         //Other code may also be applying the pre-blend, so we'd need another
   1356         //one with this and one without.
   1357         SkGdiRGB* addr = (SkGdiRGB*)bits;
   1358         for (int y = 0; y < glyph.fHeight; ++y) {
   1359             for (int x = 0; x < glyph.fWidth; ++x) {
   1360                 int r = (addr[x] >> 16) & 0xFF;
   1361                 int g = (addr[x] >>  8) & 0xFF;
   1362                 int b = (addr[x] >>  0) & 0xFF;
   1363                 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
   1364             }
   1365             addr = SkTAddOffset<SkGdiRGB>(addr, srcRB);
   1366         }
   1367     }
   1368 
   1369     int width = glyph.fWidth;
   1370     size_t dstRB = glyph.rowBytes();
   1371     if (isBW) {
   1372         const uint8_t* src = (const uint8_t*)bits;
   1373         uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
   1374         for (int y = 0; y < glyph.fHeight; y++) {
   1375             memcpy(dst, src, dstRB);
   1376             src += srcRB;
   1377             dst -= dstRB;
   1378         }
   1379 #if SK_SHOW_TEXT_BLIT_COVERAGE
   1380             if (glyph.fWidth > 0 && glyph.fHeight > 0) {
   1381                 int bitCount = width & 7;
   1382                 uint8_t* first = (uint8_t*)glyph.fImage;
   1383                 uint8_t* last = (uint8_t*)((char*)glyph.fImage + glyph.fHeight * dstRB - 1);
   1384                 *first |= 1 << 7;
   1385                 *last |= bitCount == 0 ? 1 : 1 << (8 - bitCount);
   1386             }
   1387 #endif
   1388     } else if (isAA) {
   1389         // since the caller may require A8 for maskfilters, we can't check for BW
   1390         // ... until we have the caller tell us that explicitly
   1391         const SkGdiRGB* src = (const SkGdiRGB*)bits;
   1392         if (fPreBlend.isApplicable()) {
   1393             rgb_to_a8<true>(src, srcRB, glyph, fPreBlend.fG);
   1394         } else {
   1395             rgb_to_a8<false>(src, srcRB, glyph, fPreBlend.fG);
   1396         }
   1397     } else {    // LCD16
   1398         const SkGdiRGB* src = (const SkGdiRGB*)bits;
   1399         if (is_rgb_really_bw(src, width, glyph.fHeight, srcRB)) {
   1400             rgb_to_bw(src, srcRB, glyph);
   1401             ((SkGlyph*)&glyph)->fMaskFormat = SkMask::kBW_Format;
   1402         } else {
   1403             if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
   1404                 if (fPreBlend.isApplicable()) {
   1405                     rgb_to_lcd16<true>(src, srcRB, glyph,
   1406                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1407                 } else {
   1408                     rgb_to_lcd16<false>(src, srcRB, glyph,
   1409                                         fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1410                 }
   1411             } else {
   1412                 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
   1413                 if (fPreBlend.isApplicable()) {
   1414                     rgb_to_lcd32<true>(src, srcRB, glyph,
   1415                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1416                 } else {
   1417                     rgb_to_lcd32<false>(src, srcRB, glyph,
   1418                                         fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
   1419                 }
   1420             }
   1421         }
   1422     }
   1423 }
   1424 
   1425 class GDIGlyphbufferPointIter {
   1426 public:
   1427     GDIGlyphbufferPointIter(const uint8_t* glyphbuf, DWORD total_size)
   1428         : fHeaderIter(glyphbuf, total_size), fCurveIter(), fPointIter()
   1429     { }
   1430 
   1431     POINTFX const * next() {
   1432 nextHeader:
   1433         if (!fCurveIter.isSet()) {
   1434             const TTPOLYGONHEADER* header = fHeaderIter.next();
   1435             if (NULL == header) {
   1436                 return NULL;
   1437             }
   1438             fCurveIter.set(header);
   1439             const TTPOLYCURVE* curve = fCurveIter.next();
   1440             if (NULL == curve) {
   1441                 return NULL;
   1442             }
   1443             fPointIter.set(curve);
   1444             return &header->pfxStart;
   1445         }
   1446 
   1447         const POINTFX* nextPoint = fPointIter.next();
   1448         if (NULL == nextPoint) {
   1449             const TTPOLYCURVE* curve = fCurveIter.next();
   1450             if (NULL == curve) {
   1451                 fCurveIter.set();
   1452                 goto nextHeader;
   1453             } else {
   1454                 fPointIter.set(curve);
   1455             }
   1456             nextPoint = fPointIter.next();
   1457         }
   1458         return nextPoint;
   1459     }
   1460 
   1461     WORD currentCurveType() {
   1462         return fPointIter.fCurveType;
   1463     }
   1464 
   1465 private:
   1466     /** Iterates over all of the polygon headers in a glyphbuf. */
   1467     class GDIPolygonHeaderIter {
   1468     public:
   1469         GDIPolygonHeaderIter(const uint8_t* glyphbuf, DWORD total_size)
   1470             : fCurPolygon(reinterpret_cast<const TTPOLYGONHEADER*>(glyphbuf))
   1471             , fEndPolygon(SkTAddOffset<const TTPOLYGONHEADER>(glyphbuf, total_size))
   1472         { }
   1473 
   1474         const TTPOLYGONHEADER* next() {
   1475             if (fCurPolygon >= fEndPolygon) {
   1476                 return NULL;
   1477             }
   1478             const TTPOLYGONHEADER* thisPolygon = fCurPolygon;
   1479             fCurPolygon = SkTAddOffset<const TTPOLYGONHEADER>(fCurPolygon, fCurPolygon->cb);
   1480             return thisPolygon;
   1481         }
   1482     private:
   1483         const TTPOLYGONHEADER* fCurPolygon;
   1484         const TTPOLYGONHEADER* fEndPolygon;
   1485     };
   1486 
   1487     /** Iterates over all of the polygon curves in a polygon header. */
   1488     class GDIPolygonCurveIter {
   1489     public:
   1490         GDIPolygonCurveIter() : fCurCurve(NULL), fEndCurve(NULL) { }
   1491 
   1492         GDIPolygonCurveIter(const TTPOLYGONHEADER* curPolygon)
   1493             : fCurCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOLYGONHEADER)))
   1494             , fEndCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->cb))
   1495         { }
   1496 
   1497         bool isSet() { return fCurCurve != NULL; }
   1498 
   1499         void set(const TTPOLYGONHEADER* curPolygon) {
   1500             fCurCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOLYGONHEADER));
   1501             fEndCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->cb);
   1502         }
   1503         void set() {
   1504             fCurCurve = NULL;
   1505             fEndCurve = NULL;
   1506         }
   1507 
   1508         const TTPOLYCURVE* next() {
   1509             if (fCurCurve >= fEndCurve) {
   1510                 return NULL;
   1511             }
   1512             const TTPOLYCURVE* thisCurve = fCurCurve;
   1513             fCurCurve = SkTAddOffset<const TTPOLYCURVE>(fCurCurve, size_of_TTPOLYCURVE(*fCurCurve));
   1514             return thisCurve;
   1515         }
   1516     private:
   1517         size_t size_of_TTPOLYCURVE(const TTPOLYCURVE& curve) {
   1518             return 2*sizeof(WORD) + curve.cpfx*sizeof(POINTFX);
   1519         }
   1520         const TTPOLYCURVE* fCurCurve;
   1521         const TTPOLYCURVE* fEndCurve;
   1522     };
   1523 
   1524     /** Iterates over all of the polygon points in a polygon curve. */
   1525     class GDIPolygonCurvePointIter {
   1526     public:
   1527         GDIPolygonCurvePointIter() : fCurveType(0), fCurPoint(NULL), fEndPoint(NULL) { }
   1528 
   1529         GDIPolygonCurvePointIter(const TTPOLYCURVE* curPolygon)
   1530             : fCurveType(curPolygon->wType)
   1531             , fCurPoint(&curPolygon->apfx[0])
   1532             , fEndPoint(&curPolygon->apfx[curPolygon->cpfx])
   1533         { }
   1534 
   1535         bool isSet() { return fCurPoint != NULL; }
   1536 
   1537         void set(const TTPOLYCURVE* curPolygon) {
   1538             fCurveType = curPolygon->wType;
   1539             fCurPoint = &curPolygon->apfx[0];
   1540             fEndPoint = &curPolygon->apfx[curPolygon->cpfx];
   1541         }
   1542         void set() {
   1543             fCurPoint = NULL;
   1544             fEndPoint = NULL;
   1545         }
   1546 
   1547         const POINTFX* next() {
   1548             if (fCurPoint >= fEndPoint) {
   1549                 return NULL;
   1550             }
   1551             const POINTFX* thisPoint = fCurPoint;
   1552             ++fCurPoint;
   1553             return thisPoint;
   1554         }
   1555 
   1556         WORD fCurveType;
   1557     private:
   1558         const POINTFX* fCurPoint;
   1559         const POINTFX* fEndPoint;
   1560     };
   1561 
   1562     GDIPolygonHeaderIter fHeaderIter;
   1563     GDIPolygonCurveIter fCurveIter;
   1564     GDIPolygonCurvePointIter fPointIter;
   1565 };
   1566 
   1567 static void sk_path_from_gdi_path(SkPath* path, const uint8_t* glyphbuf, DWORD total_size) {
   1568     const uint8_t* cur_glyph = glyphbuf;
   1569     const uint8_t* end_glyph = glyphbuf + total_size;
   1570 
   1571     while (cur_glyph < end_glyph) {
   1572         const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
   1573 
   1574         const uint8_t* end_poly = cur_glyph + th->cb;
   1575         const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
   1576 
   1577         path->moveTo(SkFixedToScalar( SkFIXEDToFixed(th->pfxStart.x)),
   1578                      SkFixedToScalar(-SkFIXEDToFixed(th->pfxStart.y)));
   1579 
   1580         while (cur_poly < end_poly) {
   1581             const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
   1582 
   1583             if (pc->wType == TT_PRIM_LINE) {
   1584                 for (uint16_t i = 0; i < pc->cpfx; i++) {
   1585                     path->lineTo(SkFixedToScalar( SkFIXEDToFixed(pc->apfx[i].x)),
   1586                                  SkFixedToScalar(-SkFIXEDToFixed(pc->apfx[i].y)));
   1587                 }
   1588             }
   1589 
   1590             if (pc->wType == TT_PRIM_QSPLINE) {
   1591                 for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
   1592                     POINTFX pnt_b = pc->apfx[u];    // B is always the current point
   1593                     POINTFX pnt_c = pc->apfx[u+1];
   1594 
   1595                     if (u < pc->cpfx - 2) {          // If not on last spline, compute C
   1596                         pnt_c.x = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.x),
   1597                                                             SkFIXEDToFixed(pnt_c.x)));
   1598                         pnt_c.y = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.y),
   1599                                                             SkFIXEDToFixed(pnt_c.y)));
   1600                     }
   1601 
   1602                     path->quadTo(SkFixedToScalar( SkFIXEDToFixed(pnt_b.x)),
   1603                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_b.y)),
   1604                                  SkFixedToScalar( SkFIXEDToFixed(pnt_c.x)),
   1605                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_c.y)));
   1606                 }
   1607             }
   1608             // Advance past this TTPOLYCURVE.
   1609             cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
   1610         }
   1611         cur_glyph += th->cb;
   1612         path->close();
   1613     }
   1614 }
   1615 
   1616 #define move_next_expected_hinted_point(iter, pElem) do {\
   1617     pElem = iter.next(); \
   1618     if (NULL == pElem) return false; \
   1619 } while(0)
   1620 
   1621 // It is possible for the hinted and unhinted versions of the same path to have
   1622 // a different number of points due to GDI's handling of flipped points.
   1623 // If this is detected, this will return false.
   1624 static bool sk_path_from_gdi_paths(SkPath* path, const uint8_t* glyphbuf, DWORD total_size,
   1625                                    GDIGlyphbufferPointIter hintedYs) {
   1626     const uint8_t* cur_glyph = glyphbuf;
   1627     const uint8_t* end_glyph = glyphbuf + total_size;
   1628 
   1629     POINTFX const * hintedPoint;
   1630 
   1631     while (cur_glyph < end_glyph) {
   1632         const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
   1633 
   1634         const uint8_t* end_poly = cur_glyph + th->cb;
   1635         const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
   1636 
   1637         move_next_expected_hinted_point(hintedYs, hintedPoint);
   1638         path->moveTo(SkFixedToScalar( SkFIXEDToFixed(th->pfxStart.x)),
   1639                      SkFixedToScalar(-SkFIXEDToFixed(hintedPoint->y)));
   1640 
   1641         while (cur_poly < end_poly) {
   1642             const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
   1643 
   1644             if (pc->wType == TT_PRIM_LINE) {
   1645                 for (uint16_t i = 0; i < pc->cpfx; i++) {
   1646                     move_next_expected_hinted_point(hintedYs, hintedPoint);
   1647                     path->lineTo(SkFixedToScalar( SkFIXEDToFixed(pc->apfx[i].x)),
   1648                                  SkFixedToScalar(-SkFIXEDToFixed(hintedPoint->y)));
   1649                 }
   1650             }
   1651 
   1652             if (pc->wType == TT_PRIM_QSPLINE) {
   1653                 POINTFX currentPoint = pc->apfx[0];
   1654                 move_next_expected_hinted_point(hintedYs, hintedPoint);
   1655                 // only take the hinted y if it wasn't flipped
   1656                 if (hintedYs.currentCurveType() == TT_PRIM_QSPLINE) {
   1657                     currentPoint.y = hintedPoint->y;
   1658                 }
   1659                 for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
   1660                     POINTFX pnt_b = currentPoint;//pc->apfx[u]; // B is always the current point
   1661                     POINTFX pnt_c = pc->apfx[u+1];
   1662                     move_next_expected_hinted_point(hintedYs, hintedPoint);
   1663                     // only take the hinted y if it wasn't flipped
   1664                     if (hintedYs.currentCurveType() == TT_PRIM_QSPLINE) {
   1665                         pnt_c.y = hintedPoint->y;
   1666                     }
   1667                     currentPoint.x = pnt_c.x;
   1668                     currentPoint.y = pnt_c.y;
   1669 
   1670                     if (u < pc->cpfx - 2) {          // If not on last spline, compute C
   1671                         pnt_c.x = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.x),
   1672                                                             SkFIXEDToFixed(pnt_c.x)));
   1673                         pnt_c.y = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.y),
   1674                                                             SkFIXEDToFixed(pnt_c.y)));
   1675                     }
   1676 
   1677                     path->quadTo(SkFixedToScalar( SkFIXEDToFixed(pnt_b.x)),
   1678                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_b.y)),
   1679                                  SkFixedToScalar( SkFIXEDToFixed(pnt_c.x)),
   1680                                  SkFixedToScalar(-SkFIXEDToFixed(pnt_c.y)));
   1681                 }
   1682             }
   1683             // Advance past this TTPOLYCURVE.
   1684             cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
   1685         }
   1686         cur_glyph += th->cb;
   1687         path->close();
   1688     }
   1689     return true;
   1690 }
   1691 
   1692 DWORD SkScalerContext_GDI::getGDIGlyphPath(const SkGlyph& glyph, UINT flags,
   1693                                                SkAutoSTMalloc<BUFFERSIZE, uint8_t>* glyphbuf)
   1694 {
   1695     GLYPHMETRICS gm;
   1696 
   1697     DWORD total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, BUFFERSIZE, glyphbuf->get(), &fMat22);
   1698     // Sometimes GetGlyphOutlineW returns a number larger than BUFFERSIZE even if BUFFERSIZE > 0.
   1699     // It has been verified that this does not involve a buffer overrun.
   1700     if (GDI_ERROR == total_size || total_size > BUFFERSIZE) {
   1701         // GDI_ERROR because the BUFFERSIZE was too small, or because the data was not accessible.
   1702         // When the data is not accessable GetGlyphOutlineW fails rather quickly,
   1703         // so just try to get the size. If that fails then ensure the data is accessible.
   1704         total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22);
   1705         if (GDI_ERROR == total_size) {
   1706             LogFontTypeface::EnsureAccessible(this->getTypeface());
   1707             total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22);
   1708             if (GDI_ERROR == total_size) {
   1709                 SkASSERT(false);
   1710                 return 0;
   1711             }
   1712         }
   1713 
   1714         glyphbuf->reset(total_size);
   1715 
   1716         DWORD ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyphbuf->get(), &fMat22);
   1717         if (GDI_ERROR == ret) {
   1718             LogFontTypeface::EnsureAccessible(this->getTypeface());
   1719             ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyphbuf->get(), &fMat22);
   1720             if (GDI_ERROR == ret) {
   1721                 SkASSERT(false);
   1722                 return 0;
   1723             }
   1724         }
   1725     }
   1726     return total_size;
   1727 }
   1728 
   1729 void SkScalerContext_GDI::generatePath(const SkGlyph& glyph, SkPath* path) {
   1730     SkASSERT(&glyph && path);
   1731     SkASSERT(fDDC);
   1732 
   1733     path->reset();
   1734 
   1735     // Out of all the fonts on a typical Windows box,
   1736     // 25% of glyphs require more than 2KB.
   1737     // 1% of glyphs require more than 4KB.
   1738     // 0.01% of glyphs require more than 8KB.
   1739     // 8KB is less than 1% of the normal 1MB stack on Windows.
   1740     // Note that some web fonts glyphs require more than 20KB.
   1741     //static const DWORD BUFFERSIZE = (1 << 13);
   1742 
   1743     //GDI only uses hinted outlines when axis aligned.
   1744     UINT format = GGO_NATIVE | GGO_GLYPH_INDEX;
   1745     if (fRec.getHinting() == SkPaint::kNo_Hinting || fRec.getHinting() == SkPaint::kSlight_Hinting){
   1746         format |= GGO_UNHINTED;
   1747     }
   1748     SkAutoSTMalloc<BUFFERSIZE, uint8_t> glyphbuf(BUFFERSIZE);
   1749     DWORD total_size = getGDIGlyphPath(glyph, format, &glyphbuf);
   1750     if (0 == total_size) {
   1751         return;
   1752     }
   1753 
   1754     if (fRec.getHinting() != SkPaint::kSlight_Hinting) {
   1755         sk_path_from_gdi_path(path, glyphbuf, total_size);
   1756     } else {
   1757         //GDI only uses hinted outlines when axis aligned.
   1758         UINT format = GGO_NATIVE | GGO_GLYPH_INDEX;
   1759 
   1760         SkAutoSTMalloc<BUFFERSIZE, uint8_t> hintedGlyphbuf(BUFFERSIZE);
   1761         DWORD hinted_total_size = getGDIGlyphPath(glyph, format, &hintedGlyphbuf);
   1762         if (0 == hinted_total_size) {
   1763             return;
   1764         }
   1765 
   1766         if (!sk_path_from_gdi_paths(path, glyphbuf, total_size,
   1767                                     GDIGlyphbufferPointIter(hintedGlyphbuf, hinted_total_size)))
   1768         {
   1769             path->reset();
   1770             sk_path_from_gdi_path(path, glyphbuf, total_size);
   1771         }
   1772     }
   1773 }
   1774 
   1775 static void logfont_for_name(const char* familyName, LOGFONT* lf) {
   1776     sk_bzero(lf, sizeof(LOGFONT));
   1777 #ifdef UNICODE
   1778     // Get the buffer size needed first.
   1779     size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,
   1780                                             -1, NULL, 0);
   1781     // Allocate a buffer (str_len already has terminating null
   1782     // accounted for).
   1783     wchar_t *wideFamilyName = new wchar_t[str_len];
   1784     // Now actually convert the string.
   1785     ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
   1786                             wideFamilyName, str_len);
   1787     ::wcsncpy(lf->lfFaceName, wideFamilyName, LF_FACESIZE - 1);
   1788     delete [] wideFamilyName;
   1789     lf->lfFaceName[LF_FACESIZE-1] = L'\0';
   1790 #else
   1791     ::strncpy(lf->lfFaceName, familyName, LF_FACESIZE - 1);
   1792     lf->lfFaceName[LF_FACESIZE - 1] = '\0';
   1793 #endif
   1794 }
   1795 
   1796 void LogFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
   1797                                           bool* isLocalStream) const {
   1798     // Get the actual name of the typeface. The logfont may not know this.
   1799     HFONT font = CreateFontIndirect(&fLogFont);
   1800 
   1801     HDC deviceContext = ::CreateCompatibleDC(NULL);
   1802     HFONT savefont = (HFONT)SelectObject(deviceContext, font);
   1803 
   1804     SkString familyName;
   1805     dcfontname_to_skstring(deviceContext, fLogFont, &familyName);
   1806 
   1807     if (deviceContext) {
   1808         ::SelectObject(deviceContext, savefont);
   1809         ::DeleteDC(deviceContext);
   1810     }
   1811     if (font) {
   1812         ::DeleteObject(font);
   1813     }
   1814 
   1815     desc->setFamilyName(familyName.c_str());
   1816     *isLocalStream = this->fSerializeAsStream;
   1817 }
   1818 
   1819 static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
   1820     // Initialize the MAT2 structure to the identify transformation matrix.
   1821     static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),
   1822                         SkScalarToFIXED(0), SkScalarToFIXED(1)};
   1823     int flags = GGO_METRICS | GGO_GLYPH_INDEX;
   1824     GLYPHMETRICS gm;
   1825     if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {
   1826         return false;
   1827     }
   1828     SkASSERT(advance);
   1829     *advance = gm.gmCellIncX;
   1830     return true;
   1831 }
   1832 
   1833 SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics(
   1834         SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
   1835         const uint32_t* glyphIDs,
   1836         uint32_t glyphIDsCount) const {
   1837     LOGFONT lf = fLogFont;
   1838     SkAdvancedTypefaceMetrics* info = NULL;
   1839 
   1840     HDC hdc = CreateCompatibleDC(NULL);
   1841     HFONT font = CreateFontIndirect(&lf);
   1842     HFONT savefont = (HFONT)SelectObject(hdc, font);
   1843     HFONT designFont = NULL;
   1844 
   1845     const char stem_chars[] = {'i', 'I', '!', '1'};
   1846     int16_t min_width;
   1847     unsigned glyphCount;
   1848 
   1849     // To request design units, create a logical font whose height is specified
   1850     // as unitsPerEm.
   1851     OUTLINETEXTMETRIC otm;
   1852     unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
   1853     if (0 == otmRet) {
   1854         call_ensure_accessible(lf);
   1855         otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
   1856     }
   1857     if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
   1858         goto Error;
   1859     }
   1860     lf.lfHeight = -SkToS32(otm.otmEMSquare);
   1861     designFont = CreateFontIndirect(&lf);
   1862     SelectObject(hdc, designFont);
   1863     if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {
   1864         goto Error;
   1865     }
   1866     glyphCount = calculateGlyphCount(hdc, fLogFont);
   1867 
   1868     info = new SkAdvancedTypefaceMetrics;
   1869     info->fEmSize = otm.otmEMSquare;
   1870     info->fLastGlyphID = SkToU16(glyphCount - 1);
   1871     info->fStyle = 0;
   1872     tchar_to_skstring(lf.lfFaceName, &info->fFontName);
   1873     info->fFlags = SkAdvancedTypefaceMetrics::kEmpty_FontFlag;
   1874     // If bit 1 is set, the font may not be embedded in a document.
   1875     // If bit 1 is clear, the font can be embedded.
   1876     // If bit 2 is set, the embedding is read-only.
   1877     if (otm.otmfsType & 0x1) {
   1878         info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>(
   1879                 info->fFlags,
   1880                 SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag);
   1881     }
   1882 
   1883     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
   1884         populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode));
   1885     }
   1886 
   1887     if (glyphCount > 0 &&
   1888         (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE)) {
   1889         info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
   1890     } else {
   1891         info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
   1892         info->fItalicAngle = 0;
   1893         info->fAscent = 0;
   1894         info->fDescent = 0;
   1895         info->fStemV = 0;
   1896         info->fCapHeight = 0;
   1897         info->fBBox = SkIRect::MakeEmpty();
   1898         goto ReturnInfo;
   1899     }
   1900 
   1901     // If this bit is clear the font is a fixed pitch font.
   1902     if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
   1903         info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
   1904     }
   1905     if (otm.otmTextMetrics.tmItalic) {
   1906         info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
   1907     }
   1908     if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {
   1909         info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
   1910     } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {
   1911             info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
   1912     }
   1913 
   1914     // The main italic angle of the font, in tenths of a degree counterclockwise
   1915     // from vertical.
   1916     info->fItalicAngle = otm.otmItalicAngle / 10;
   1917     info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);
   1918     info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);
   1919     // TODO(ctguil): Use alternate cap height calculation.
   1920     // MSDN says otmsCapEmHeight is not support but it is returning a value on
   1921     // my Win7 box.
   1922     info->fCapHeight = otm.otmsCapEmHeight;
   1923     info->fBBox =
   1924         SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,
   1925                           otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);
   1926 
   1927     // Figure out a good guess for StemV - Min width of i, I, !, 1.
   1928     // This probably isn't very good with an italic font.
   1929     min_width = SHRT_MAX;
   1930     info->fStemV = 0;
   1931     for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
   1932         ABC abcWidths;
   1933         if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
   1934             int16_t width = abcWidths.abcB;
   1935             if (width > 0 && width < min_width) {
   1936                 min_width = width;
   1937                 info->fStemV = min_width;
   1938             }
   1939         }
   1940     }
   1941 
   1942     if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
   1943         if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
   1944             appendRange(&info->fGlyphWidths, 0);
   1945             info->fGlyphWidths->fAdvance.append(1, &min_width);
   1946             finishRange(info->fGlyphWidths.get(), 0,
   1947                         SkAdvancedTypefaceMetrics::WidthRange::kDefault);
   1948         } else {
   1949             info->fGlyphWidths.reset(
   1950                 getAdvanceData(hdc,
   1951                                glyphCount,
   1952                                glyphIDs,
   1953                                glyphIDsCount,
   1954                                &getWidthAdvance));
   1955         }
   1956     }
   1957 
   1958 Error:
   1959 ReturnInfo:
   1960     SelectObject(hdc, savefont);
   1961     DeleteObject(designFont);
   1962     DeleteObject(font);
   1963     DeleteDC(hdc);
   1964 
   1965     return info;
   1966 }
   1967 
   1968 //Dummy representation of a Base64 encoded GUID from create_unique_font_name.
   1969 #define BASE64_GUID_ID "XXXXXXXXXXXXXXXXXXXXXXXX"
   1970 //Length of GUID representation from create_id, including NULL terminator.
   1971 #define BASE64_GUID_ID_LEN SK_ARRAY_COUNT(BASE64_GUID_ID)
   1972 
   1973 SK_COMPILE_ASSERT(BASE64_GUID_ID_LEN < LF_FACESIZE, GUID_longer_than_facesize);
   1974 
   1975 /**
   1976    NameID 6 Postscript names cannot have the character '/'.
   1977    It would be easier to hex encode the GUID, but that is 32 bytes,
   1978    and many systems have issues with names longer than 28 bytes.
   1979    The following need not be any standard base64 encoding.
   1980    The encoded value is never decoded.
   1981 */
   1982 static const char postscript_safe_base64_encode[] =
   1983     "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
   1984     "abcdefghijklmnopqrstuvwxyz"
   1985     "0123456789-_=";
   1986 
   1987 /**
   1988    Formats a GUID into Base64 and places it into buffer.
   1989    buffer should have space for at least BASE64_GUID_ID_LEN characters.
   1990    The string will always be null terminated.
   1991    XXXXXXXXXXXXXXXXXXXXXXXX0
   1992  */
   1993 static void format_guid_b64(const GUID& guid, char* buffer, size_t bufferSize) {
   1994     SkASSERT(bufferSize >= BASE64_GUID_ID_LEN);
   1995     size_t written = SkBase64::Encode(&guid, sizeof(guid), buffer, postscript_safe_base64_encode);
   1996     SkASSERT(written < LF_FACESIZE);
   1997     buffer[written] = '\0';
   1998 }
   1999 
   2000 /**
   2001    Creates a Base64 encoded GUID and places it into buffer.
   2002    buffer should have space for at least BASE64_GUID_ID_LEN characters.
   2003    The string will always be null terminated.
   2004    XXXXXXXXXXXXXXXXXXXXXXXX0
   2005  */
   2006 static HRESULT create_unique_font_name(char* buffer, size_t bufferSize) {
   2007     GUID guid = {};
   2008     if (FAILED(CoCreateGuid(&guid))) {
   2009         return E_UNEXPECTED;
   2010     }
   2011     format_guid_b64(guid, buffer, bufferSize);
   2012 
   2013     return S_OK;
   2014 }
   2015 
   2016 /**
   2017    Introduces a font to GDI. On failure will return NULL. The returned handle
   2018    should eventually be passed to RemoveFontMemResourceEx.
   2019 */
   2020 static HANDLE activate_font(SkData* fontData) {
   2021     DWORD numFonts = 0;
   2022     //AddFontMemResourceEx just copies the data, but does not specify const.
   2023     HANDLE fontHandle = AddFontMemResourceEx(const_cast<void*>(fontData->data()),
   2024                                              static_cast<DWORD>(fontData->size()),
   2025                                              0,
   2026                                              &numFonts);
   2027 
   2028     if (fontHandle != NULL && numFonts < 1) {
   2029         RemoveFontMemResourceEx(fontHandle);
   2030         return NULL;
   2031     }
   2032 
   2033     return fontHandle;
   2034 }
   2035 
   2036 static SkTypeface* create_from_stream(SkStream* stream) {
   2037     // Create a unique and unpredictable font name.
   2038     // Avoids collisions and access from CSS.
   2039     char familyName[BASE64_GUID_ID_LEN];
   2040     const int familyNameSize = SK_ARRAY_COUNT(familyName);
   2041     if (FAILED(create_unique_font_name(familyName, familyNameSize))) {
   2042         return NULL;
   2043     }
   2044 
   2045     // Change the name of the font.
   2046     SkAutoTUnref<SkData> rewrittenFontData(SkOTUtils::RenameFont(stream, familyName, familyNameSize-1));
   2047     if (NULL == rewrittenFontData.get()) {
   2048         return NULL;
   2049     }
   2050 
   2051     // Register the font with GDI.
   2052     HANDLE fontReference = activate_font(rewrittenFontData.get());
   2053     if (NULL == fontReference) {
   2054         return NULL;
   2055     }
   2056 
   2057     // Create the typeface.
   2058     LOGFONT lf;
   2059     logfont_for_name(familyName, &lf);
   2060 
   2061     return SkCreateFontMemResourceTypefaceFromLOGFONT(lf, fontReference);
   2062 }
   2063 
   2064 SkStream* LogFontTypeface::onOpenStream(int* ttcIndex) const {
   2065     *ttcIndex = 0;
   2066 
   2067     const DWORD kTTCTag =
   2068         SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f'));
   2069     LOGFONT lf = fLogFont;
   2070 
   2071     HDC hdc = ::CreateCompatibleDC(NULL);
   2072     HFONT font = CreateFontIndirect(&lf);
   2073     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2074 
   2075     SkMemoryStream* stream = NULL;
   2076     DWORD tables[2] = {kTTCTag, 0};
   2077     for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) {
   2078         DWORD bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
   2079         if (bufferSize == GDI_ERROR) {
   2080             call_ensure_accessible(lf);
   2081             bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
   2082         }
   2083         if (bufferSize != GDI_ERROR) {
   2084             stream = new SkMemoryStream(bufferSize);
   2085             if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(), bufferSize)) {
   2086                 break;
   2087             } else {
   2088                 delete stream;
   2089                 stream = NULL;
   2090             }
   2091         }
   2092     }
   2093 
   2094     SelectObject(hdc, savefont);
   2095     DeleteObject(font);
   2096     DeleteDC(hdc);
   2097 
   2098     return stream;
   2099 }
   2100 
   2101 static void bmpCharsToGlyphs(HDC hdc, const WCHAR* bmpChars, int count, uint16_t* glyphs,
   2102                              bool Ox1FHack)
   2103 {
   2104     DWORD result = GetGlyphIndicesW(hdc, bmpChars, count, glyphs, GGI_MARK_NONEXISTING_GLYPHS);
   2105     if (GDI_ERROR == result) {
   2106         for (int i = 0; i < count; ++i) {
   2107             glyphs[i] = 0;
   2108         }
   2109         return;
   2110     }
   2111 
   2112     if (Ox1FHack) {
   2113         for (int i = 0; i < count; ++i) {
   2114             if (0xFFFF == glyphs[i] || 0x1F == glyphs[i]) {
   2115                 glyphs[i] = 0;
   2116             }
   2117         }
   2118     } else {
   2119         for (int i = 0; i < count; ++i) {
   2120             if (0xFFFF == glyphs[i]){
   2121                 glyphs[i] = 0;
   2122             }
   2123         }
   2124     }
   2125 }
   2126 
   2127 static uint16_t nonBmpCharToGlyph(HDC hdc, SCRIPT_CACHE* scriptCache, const WCHAR utf16[2]) {
   2128     uint16_t index = 0;
   2129     // Use uniscribe to detemine glyph index for non-BMP characters.
   2130     static const int numWCHAR = 2;
   2131     static const int maxItems = 2;
   2132     // MSDN states that this can be NULL, but some things don't work then.
   2133     SCRIPT_CONTROL scriptControl = { 0 };
   2134     // Add extra item to SCRIPT_ITEM to work around a bug (now documented).
   2135     // https://bugzilla.mozilla.org/show_bug.cgi?id=366643
   2136     SCRIPT_ITEM si[maxItems + 1];
   2137     int numItems;
   2138     HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &scriptControl, NULL, si, &numItems),
   2139          "Could not itemize character.");
   2140 
   2141     // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2 space glyphs.
   2142     static const int maxGlyphs = 2;
   2143     SCRIPT_VISATTR vsa[maxGlyphs];
   2144     WORD outGlyphs[maxGlyphs];
   2145     WORD logClust[numWCHAR];
   2146     int numGlyphs;
   2147     HRZM(ScriptShape(hdc, scriptCache, utf16, numWCHAR, maxGlyphs, &si[0].a,
   2148                      outGlyphs, logClust, vsa, &numGlyphs),
   2149          "Could not shape character.");
   2150     if (1 == numGlyphs) {
   2151         index = outGlyphs[0];
   2152     }
   2153     return index;
   2154 }
   2155 
   2156 class SkAutoHDC {
   2157 public:
   2158     SkAutoHDC(const LOGFONT& lf)
   2159         : fHdc(::CreateCompatibleDC(NULL))
   2160         , fFont(::CreateFontIndirect(&lf))
   2161         , fSavefont((HFONT)SelectObject(fHdc, fFont))
   2162     { }
   2163     ~SkAutoHDC() {
   2164         SelectObject(fHdc, fSavefont);
   2165         DeleteObject(fFont);
   2166         DeleteDC(fHdc);
   2167     }
   2168     operator HDC() { return fHdc; }
   2169 private:
   2170     HDC fHdc;
   2171     HFONT fFont;
   2172     HFONT fSavefont;
   2173 };
   2174 #define SkAutoHDC(...) SK_REQUIRE_LOCAL_VAR(SkAutoHDC)
   2175 
   2176 int LogFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding,
   2177                                      uint16_t userGlyphs[], int glyphCount) const
   2178 {
   2179     SkAutoHDC hdc(fLogFont);
   2180 
   2181     TEXTMETRIC tm;
   2182     if (0 == GetTextMetrics(hdc, &tm)) {
   2183         call_ensure_accessible(fLogFont);
   2184         if (0 == GetTextMetrics(hdc, &tm)) {
   2185             tm.tmPitchAndFamily = TMPF_TRUETYPE;
   2186         }
   2187     }
   2188     bool Ox1FHack = !(tm.tmPitchAndFamily & TMPF_VECTOR) /*&& winVer < Vista */;
   2189 
   2190     SkAutoSTMalloc<256, uint16_t> scratchGlyphs;
   2191     uint16_t* glyphs;
   2192     if (userGlyphs != NULL) {
   2193         glyphs = userGlyphs;
   2194     } else {
   2195         glyphs = scratchGlyphs.reset(glyphCount);
   2196     }
   2197 
   2198     SCRIPT_CACHE sc = 0;
   2199     switch (encoding) {
   2200     case SkTypeface::kUTF8_Encoding: {
   2201         static const int scratchCount = 256;
   2202         WCHAR scratch[scratchCount];
   2203         int glyphIndex = 0;
   2204         const char* currentUtf8 = reinterpret_cast<const char*>(chars);
   2205         SkUnichar currentChar;
   2206         if (glyphCount) {
   2207             currentChar = SkUTF8_NextUnichar(&currentUtf8);
   2208         }
   2209         while (glyphIndex < glyphCount) {
   2210             // Try a run of bmp.
   2211             int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount);
   2212             int runLength = 0;
   2213             while (runLength < glyphsLeft && currentChar <= 0xFFFF) {
   2214                 scratch[runLength] = static_cast<WCHAR>(currentChar);
   2215                 ++runLength;
   2216                 if (runLength < glyphsLeft) {
   2217                     currentChar = SkUTF8_NextUnichar(&currentUtf8);
   2218                 }
   2219             }
   2220             if (runLength) {
   2221                 bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack);
   2222                 glyphIndex += runLength;
   2223             }
   2224 
   2225             // Try a run of non-bmp.
   2226             while (glyphIndex < glyphCount && currentChar > 0xFFFF) {
   2227                 SkUTF16_FromUnichar(currentChar, reinterpret_cast<uint16_t*>(scratch));
   2228                 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch);
   2229                 ++glyphIndex;
   2230                 if (glyphIndex < glyphCount) {
   2231                     currentChar = SkUTF8_NextUnichar(&currentUtf8);
   2232                 }
   2233             }
   2234         }
   2235         break;
   2236     }
   2237     case SkTypeface::kUTF16_Encoding: {
   2238         int glyphIndex = 0;
   2239         const WCHAR* currentUtf16 = reinterpret_cast<const WCHAR*>(chars);
   2240         while (glyphIndex < glyphCount) {
   2241             // Try a run of bmp.
   2242             int glyphsLeft = glyphCount - glyphIndex;
   2243             int runLength = 0;
   2244             while (runLength < glyphsLeft && !SkUTF16_IsHighSurrogate(currentUtf16[runLength])) {
   2245                 ++runLength;
   2246             }
   2247             if (runLength) {
   2248                 bmpCharsToGlyphs(hdc, currentUtf16, runLength, &glyphs[glyphIndex], Ox1FHack);
   2249                 glyphIndex += runLength;
   2250                 currentUtf16 += runLength;
   2251             }
   2252 
   2253             // Try a run of non-bmp.
   2254             while (glyphIndex < glyphCount && SkUTF16_IsHighSurrogate(*currentUtf16)) {
   2255                 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, currentUtf16);
   2256                 ++glyphIndex;
   2257                 currentUtf16 += 2;
   2258             }
   2259         }
   2260         break;
   2261     }
   2262     case SkTypeface::kUTF32_Encoding: {
   2263         static const int scratchCount = 256;
   2264         WCHAR scratch[scratchCount];
   2265         int glyphIndex = 0;
   2266         const uint32_t* utf32 = reinterpret_cast<const uint32_t*>(chars);
   2267         while (glyphIndex < glyphCount) {
   2268             // Try a run of bmp.
   2269             int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount);
   2270             int runLength = 0;
   2271             while (runLength < glyphsLeft && utf32[glyphIndex + runLength] <= 0xFFFF) {
   2272                 scratch[runLength] = static_cast<WCHAR>(utf32[glyphIndex + runLength]);
   2273                 ++runLength;
   2274             }
   2275             if (runLength) {
   2276                 bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack);
   2277                 glyphIndex += runLength;
   2278             }
   2279 
   2280             // Try a run of non-bmp.
   2281             while (glyphIndex < glyphCount && utf32[glyphIndex] > 0xFFFF) {
   2282                 SkUTF16_FromUnichar(utf32[glyphIndex], reinterpret_cast<uint16_t*>(scratch));
   2283                 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch);
   2284                 ++glyphIndex;
   2285             }
   2286         }
   2287         break;
   2288     }
   2289     default:
   2290         SK_CRASH();
   2291     }
   2292 
   2293     if (sc) {
   2294         ::ScriptFreeCache(&sc);
   2295     }
   2296 
   2297     for (int i = 0; i < glyphCount; ++i) {
   2298         if (0 == glyphs[i]) {
   2299             return i;
   2300         }
   2301     }
   2302     return glyphCount;
   2303 }
   2304 
   2305 int LogFontTypeface::onCountGlyphs() const {
   2306     HDC hdc = ::CreateCompatibleDC(NULL);
   2307     HFONT font = CreateFontIndirect(&fLogFont);
   2308     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2309 
   2310     unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont);
   2311 
   2312     SelectObject(hdc, savefont);
   2313     DeleteObject(font);
   2314     DeleteDC(hdc);
   2315 
   2316     return glyphCount;
   2317 }
   2318 
   2319 int LogFontTypeface::onGetUPEM() const {
   2320     HDC hdc = ::CreateCompatibleDC(NULL);
   2321     HFONT font = CreateFontIndirect(&fLogFont);
   2322     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2323 
   2324     unsigned int upem = calculateUPEM(hdc, fLogFont);
   2325 
   2326     SelectObject(hdc, savefont);
   2327     DeleteObject(font);
   2328     DeleteDC(hdc);
   2329 
   2330     return upem;
   2331 }
   2332 
   2333 SkTypeface::LocalizedStrings* LogFontTypeface::onCreateFamilyNameIterator() const {
   2334     SkTypeface::LocalizedStrings* nameIter =
   2335         SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this);
   2336     if (NULL == nameIter) {
   2337         SkString familyName;
   2338         this->getFamilyName(&familyName);
   2339         SkString language("und"); //undetermined
   2340         nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language);
   2341     }
   2342     return nameIter;
   2343 }
   2344 
   2345 int LogFontTypeface::onGetTableTags(SkFontTableTag tags[]) const {
   2346     SkSFNTHeader header;
   2347     if (sizeof(header) != this->onGetTableData(0, 0, sizeof(header), &header)) {
   2348         return 0;
   2349     }
   2350 
   2351     int numTables = SkEndian_SwapBE16(header.numTables);
   2352 
   2353     if (tags) {
   2354         size_t size = numTables * sizeof(SkSFNTHeader::TableDirectoryEntry);
   2355         SkAutoSTMalloc<0x20, SkSFNTHeader::TableDirectoryEntry> dir(numTables);
   2356         if (size != this->onGetTableData(0, sizeof(header), size, dir.get())) {
   2357             return 0;
   2358         }
   2359 
   2360         for (int i = 0; i < numTables; ++i) {
   2361             tags[i] = SkEndian_SwapBE32(dir[i].tag);
   2362         }
   2363     }
   2364     return numTables;
   2365 }
   2366 
   2367 size_t LogFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset,
   2368                                        size_t length, void* data) const
   2369 {
   2370     LOGFONT lf = fLogFont;
   2371 
   2372     HDC hdc = ::CreateCompatibleDC(NULL);
   2373     HFONT font = CreateFontIndirect(&lf);
   2374     HFONT savefont = (HFONT)SelectObject(hdc, font);
   2375 
   2376     tag = SkEndian_SwapBE32(tag);
   2377     if (NULL == data) {
   2378         length = 0;
   2379     }
   2380     DWORD bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) length);
   2381     if (bufferSize == GDI_ERROR) {
   2382         call_ensure_accessible(lf);
   2383         bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) length);
   2384     }
   2385 
   2386     SelectObject(hdc, savefont);
   2387     DeleteObject(font);
   2388     DeleteDC(hdc);
   2389 
   2390     return bufferSize == GDI_ERROR ? 0 : bufferSize;
   2391 }
   2392 
   2393 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
   2394     SkScalerContext_GDI* ctx = SkNEW_ARGS(SkScalerContext_GDI,
   2395                                                 (const_cast<LogFontTypeface*>(this), desc));
   2396     if (!ctx->isValid()) {
   2397         SkDELETE(ctx);
   2398         ctx = NULL;
   2399     }
   2400     return ctx;
   2401 }
   2402 
   2403 void LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const {
   2404     if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag ||
   2405         rec->fFlags & SkScalerContext::kLCD_Vertical_Flag)
   2406     {
   2407         rec->fMaskFormat = SkMask::kA8_Format;
   2408         rec->fFlags |= SkScalerContext::kGenA8FromLCD_Flag;
   2409     }
   2410 
   2411     unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
   2412                                   SkScalerContext::kForceAutohinting_Flag |
   2413                                   SkScalerContext::kEmbeddedBitmapText_Flag |
   2414                                   SkScalerContext::kEmbolden_Flag |
   2415                                   SkScalerContext::kLCD_BGROrder_Flag |
   2416                                   SkScalerContext::kLCD_Vertical_Flag;
   2417     rec->fFlags &= ~flagsWeDontSupport;
   2418 
   2419     SkPaint::Hinting h = rec->getHinting();
   2420     switch (h) {
   2421         case SkPaint::kNo_Hinting:
   2422             break;
   2423         case SkPaint::kSlight_Hinting:
   2424             // Only do slight hinting when axis aligned.
   2425             // TODO: re-enable slight hinting when FontHostTest can pass.
   2426             //if (!isAxisAligned(*rec)) {
   2427                 h = SkPaint::kNo_Hinting;
   2428             //}
   2429             break;
   2430         case SkPaint::kNormal_Hinting:
   2431         case SkPaint::kFull_Hinting:
   2432             // TODO: need to be able to distinguish subpixel positioned glyphs
   2433             // and linear metrics.
   2434             //rec->fFlags &= ~SkScalerContext::kSubpixelPositioning_Flag;
   2435             h = SkPaint::kNormal_Hinting;
   2436             break;
   2437         default:
   2438             SkDEBUGFAIL("unknown hinting");
   2439     }
   2440     //TODO: if this is a bitmap font, squash hinting and subpixel.
   2441     rec->setHinting(h);
   2442 
   2443 // turn this off since GDI might turn A8 into BW! Need a bigger fix.
   2444 #if 0
   2445     // Disable LCD when rotated, since GDI's output is ugly
   2446     if (isLCD(*rec) && !isAxisAligned(*rec)) {
   2447         rec->fMaskFormat = SkMask::kA8_Format;
   2448     }
   2449 #endif
   2450 
   2451     if (!fCanBeLCD && isLCD(*rec)) {
   2452         rec->fMaskFormat = SkMask::kA8_Format;
   2453         rec->fFlags &= ~SkScalerContext::kGenA8FromLCD_Flag;
   2454     }
   2455 }
   2456 
   2457 ///////////////////////////////////////////////////////////////////////////////
   2458 
   2459 #include "SkFontMgr.h"
   2460 #include "SkDataTable.h"
   2461 
   2462 static bool valid_logfont_for_enum(const LOGFONT& lf) {
   2463     // TODO: Vector FON is unsupported and should not be listed.
   2464     return
   2465         // Ignore implicit vertical variants.
   2466         lf.lfFaceName[0] && lf.lfFaceName[0] != '@'
   2467 
   2468         // DEFAULT_CHARSET is used to get all fonts, but also implies all
   2469         // character sets. Filter assuming all fonts support ANSI_CHARSET.
   2470         && ANSI_CHARSET == lf.lfCharSet
   2471     ;
   2472 }
   2473 
   2474 /** An EnumFontFamExProc implementation which interprets builderParam as
   2475  *  an SkTDArray<ENUMLOGFONTEX>* and appends logfonts which
   2476  *  pass the valid_logfont_for_enum predicate.
   2477  */
   2478 static int CALLBACK enum_family_proc(const LOGFONT* lf, const TEXTMETRIC*,
   2479                                      DWORD fontType, LPARAM builderParam) {
   2480     if (valid_logfont_for_enum(*lf)) {
   2481         SkTDArray<ENUMLOGFONTEX>* array = (SkTDArray<ENUMLOGFONTEX>*)builderParam;
   2482         *array->append() = *(ENUMLOGFONTEX*)lf;
   2483     }
   2484     return 1; // non-zero means continue
   2485 }
   2486 
   2487 static SkFontStyle compute_fontstyle(const LOGFONT& lf) {
   2488     return SkFontStyle(lf.lfWeight, SkFontStyle::kNormal_Width,
   2489                        lf.lfItalic ? SkFontStyle::kItalic_Slant
   2490                                    : SkFontStyle::kUpright_Slant);
   2491 }
   2492 
   2493 class SkFontStyleSetGDI : public SkFontStyleSet {
   2494 public:
   2495     SkFontStyleSetGDI(const TCHAR familyName[]) {
   2496         LOGFONT lf;
   2497         sk_bzero(&lf, sizeof(lf));
   2498         lf.lfCharSet = DEFAULT_CHARSET;
   2499         _tcscpy_s(lf.lfFaceName, familyName);
   2500 
   2501         HDC hdc = ::CreateCompatibleDC(NULL);
   2502         ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fArray, 0);
   2503         ::DeleteDC(hdc);
   2504     }
   2505 
   2506     virtual int count() SK_OVERRIDE {
   2507         return fArray.count();
   2508     }
   2509 
   2510     virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE {
   2511         if (fs) {
   2512             *fs = compute_fontstyle(fArray[index].elfLogFont);
   2513         }
   2514         if (styleName) {
   2515             const ENUMLOGFONTEX& ref = fArray[index];
   2516             // For some reason, ENUMLOGFONTEX and LOGFONT disagree on their type in the
   2517             // non-unicode version.
   2518             //      ENUMLOGFONTEX uses BYTE
   2519             //      LOGFONT uses CHAR
   2520             // Here we assert they that the style name is logically the same (size) as
   2521             // a TCHAR, so we can use the same converter function.
   2522             SkASSERT(sizeof(TCHAR) == sizeof(ref.elfStyle[0]));
   2523             tchar_to_skstring((const TCHAR*)ref.elfStyle, styleName);
   2524         }
   2525     }
   2526 
   2527     virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
   2528         return SkCreateTypefaceFromLOGFONT(fArray[index].elfLogFont);
   2529     }
   2530 
   2531     virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
   2532         // todo:
   2533         return SkCreateTypefaceFromLOGFONT(fArray[0].elfLogFont);
   2534     }
   2535 
   2536 private:
   2537     SkTDArray<ENUMLOGFONTEX> fArray;
   2538 };
   2539 
   2540 class SkFontMgrGDI : public SkFontMgr {
   2541 public:
   2542     SkFontMgrGDI() {
   2543         LOGFONT lf;
   2544         sk_bzero(&lf, sizeof(lf));
   2545         lf.lfCharSet = DEFAULT_CHARSET;
   2546 
   2547         HDC hdc = ::CreateCompatibleDC(NULL);
   2548         ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fLogFontArray, 0);
   2549         ::DeleteDC(hdc);
   2550     }
   2551 
   2552 protected:
   2553     virtual int onCountFamilies() const SK_OVERRIDE {
   2554         return fLogFontArray.count();
   2555     }
   2556 
   2557     virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE {
   2558         SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
   2559         tchar_to_skstring(fLogFontArray[index].elfLogFont.lfFaceName, familyName);
   2560     }
   2561 
   2562     virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE {
   2563         SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
   2564         return SkNEW_ARGS(SkFontStyleSetGDI, (fLogFontArray[index].elfLogFont.lfFaceName));
   2565     }
   2566 
   2567     virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE {
   2568         if (NULL == familyName) {
   2569             familyName = "";    // do we need this check???
   2570         }
   2571         LOGFONT lf;
   2572         logfont_for_name(familyName, &lf);
   2573         return SkNEW_ARGS(SkFontStyleSetGDI, (lf.lfFaceName));
   2574     }
   2575 
   2576     virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
   2577                                            const SkFontStyle& fontstyle) const SK_OVERRIDE {
   2578         // could be in base impl
   2579         SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
   2580         return sset->matchStyle(fontstyle);
   2581     }
   2582 
   2583     virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
   2584                                          const SkFontStyle& fontstyle) const SK_OVERRIDE {
   2585         // could be in base impl
   2586         SkString familyName;
   2587         ((LogFontTypeface*)familyMember)->getFamilyName(&familyName);
   2588         return this->matchFamilyStyle(familyName.c_str(), fontstyle);
   2589     }
   2590 
   2591     virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE {
   2592         return create_from_stream(stream);
   2593     }
   2594 
   2595     virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE {
   2596         // could be in base impl
   2597         SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data)));
   2598         return this->createFromStream(stream);
   2599     }
   2600 
   2601     virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE {
   2602         // could be in base impl
   2603         SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
   2604         return this->createFromStream(stream);
   2605     }
   2606 
   2607     virtual SkTypeface* onLegacyCreateTypeface(const char familyName[],
   2608                                                unsigned styleBits) const SK_OVERRIDE {
   2609         LOGFONT lf;
   2610         if (NULL == familyName) {
   2611             lf = get_default_font();
   2612         } else {
   2613             logfont_for_name(familyName, &lf);
   2614         }
   2615         setStyle(&lf, (SkTypeface::Style)styleBits);
   2616         return SkCreateTypefaceFromLOGFONT(lf);
   2617     }
   2618 
   2619 private:
   2620     SkTDArray<ENUMLOGFONTEX> fLogFontArray;
   2621 };
   2622 
   2623 ///////////////////////////////////////////////////////////////////////////////
   2624 
   2625 SkFontMgr* SkFontMgr_New_GDI() {
   2626     return SkNEW(SkFontMgrGDI);
   2627 }
   2628