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