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