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