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