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