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