SkFontHost_win.cpp revision 484f5bcf07c965e84cf021a6272aff73e2d7c1ec
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 "SkMaskGamma.h"
18#include "SkOTUtils.h"
19#include "SkPath.h"
20#include "SkStream.h"
21#include "SkString.h"
22#include "SkThread.h"
23#include "SkTypeface_win.h"
24#include "SkTypefaceCache.h"
25#include "SkUtils.h"
26
27#include "SkTypes.h"
28#include <tchar.h>
29#include <usp10.h>
30#include <objbase.h>
31
32static void (*gEnsureLOGFONTAccessibleProc)(const LOGFONT&);
33
34void SkTypeface_SetEnsureLOGFONTAccessibleProc(void (*proc)(const LOGFONT&)) {
35    gEnsureLOGFONTAccessibleProc = proc;
36}
37
38static void call_ensure_accessible(const LOGFONT& lf) {
39    if (gEnsureLOGFONTAccessibleProc) {
40        gEnsureLOGFONTAccessibleProc(lf);
41    }
42}
43
44///////////////////////////////////////////////////////////////////////////////
45
46// always packed xxRRGGBB
47typedef uint32_t SkGdiRGB;
48
49template <typename T> T* SkTAddByteOffset(T* ptr, size_t byteOffset) {
50    return (T*)((char*)ptr + byteOffset);
51}
52
53// define this in your Makefile or .gyp to enforce AA requests
54// which GDI ignores at small sizes. This flag guarantees AA
55// for rotated text, regardless of GDI's notions.
56//#define SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
57
58// client3d has to undefine this for now
59#define CAN_USE_LOGFONT_NAME
60
61static bool isLCD(const SkScalerContext::Rec& rec) {
62    return SkMask::kLCD16_Format == rec.fMaskFormat ||
63           SkMask::kLCD32_Format == rec.fMaskFormat;
64}
65
66static bool bothZero(SkScalar a, SkScalar b) {
67    return 0 == a && 0 == b;
68}
69
70// returns false if there is any non-90-rotation or skew
71static bool isAxisAligned(const SkScalerContext::Rec& rec) {
72    return 0 == rec.fPreSkewX &&
73           (bothZero(rec.fPost2x2[0][1], rec.fPost2x2[1][0]) ||
74            bothZero(rec.fPost2x2[0][0], rec.fPost2x2[1][1]));
75}
76
77static bool needToRenderWithSkia(const SkScalerContext::Rec& rec) {
78#ifdef SK_ENFORCE_ROTATED_TEXT_AA_ON_WINDOWS
79    // What we really want to catch is when GDI will ignore the AA request and give
80    // us BW instead. Smallish rotated text is one heuristic, so this code is just
81    // an approximation. We shouldn't need to do this for larger sizes, but at those
82    // sizes, the quality difference gets less and less between our general
83    // scanconverter and GDI's.
84    if (SkMask::kA8_Format == rec.fMaskFormat && !isAxisAligned(rec)) {
85        return true;
86    }
87#endif
88    // false means allow GDI to generate the bits
89    return false;
90}
91
92using namespace skia_advanced_typeface_metrics_utils;
93
94static const uint16_t BUFFERSIZE = (16384 - 32);
95static uint8_t glyphbuf[BUFFERSIZE];
96
97/**
98 *  Since LOGFONT wants its textsize as an int, and we support fractional sizes,
99 *  and since we have a cache of LOGFONTs for our tyepfaces, we always set the
100 *  lfHeight to a canonical size, and then we use the 2x2 matrix to achieve the
101 *  actual requested size.
102 */
103static const int gCanonicalTextSize = 64;
104
105static void tchar_to_skstring(const TCHAR* t, SkString* s) {
106#ifdef UNICODE
107    size_t sSize = WideCharToMultiByte(CP_UTF8, 0, t, -1, NULL, 0, NULL, NULL);
108    s->resize(sSize);
109    WideCharToMultiByte(CP_UTF8, 0, t, -1, s->writable_str(), sSize, NULL, NULL);
110#else
111    s->set(t);
112#endif
113}
114
115static void make_canonical(LOGFONT* lf) {
116    lf->lfHeight = -gCanonicalTextSize;
117    lf->lfQuality = CLEARTYPE_QUALITY;//PROOF_QUALITY;
118    lf->lfCharSet = DEFAULT_CHARSET;
119//    lf->lfClipPrecision = 64;
120}
121
122static SkTypeface::Style get_style(const LOGFONT& lf) {
123    unsigned style = 0;
124    if (lf.lfWeight >= FW_BOLD) {
125        style |= SkTypeface::kBold;
126    }
127    if (lf.lfItalic) {
128        style |= SkTypeface::kItalic;
129    }
130    return static_cast<SkTypeface::Style>(style);
131}
132
133static void setStyle(LOGFONT* lf, SkTypeface::Style style) {
134    lf->lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;
135    lf->lfItalic = ((style & SkTypeface::kItalic) != 0);
136}
137
138static inline FIXED SkFixedToFIXED(SkFixed x) {
139    return *(FIXED*)(&x);
140}
141static inline SkFixed SkFIXEDToFixed(FIXED x) {
142    return *(SkFixed*)(&x);
143}
144
145static inline FIXED SkScalarToFIXED(SkScalar x) {
146    return SkFixedToFIXED(SkScalarToFixed(x));
147}
148
149static unsigned calculateOutlineGlyphCount(HDC hdc) {
150    // The 'maxp' table stores the number of glyphs at offset 4, in 2 bytes.
151    const DWORD maxpTag =
152        SkEndian_SwapBE32(SkSetFourByteTag('m', 'a', 'x', 'p'));
153    uint16_t glyphs;
154    if (GetFontData(hdc, maxpTag, 4, &glyphs, sizeof(glyphs)) != GDI_ERROR) {
155        return SkEndian_SwapBE16(glyphs);
156    }
157
158    // Binary search for glyph count.
159    static const MAT2 mat2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
160    int32_t max = SK_MaxU16 + 1;
161    int32_t min = 0;
162    GLYPHMETRICS gm;
163    while (min < max) {
164        int32_t mid = min + ((max - min) / 2);
165        if (GetGlyphOutlineW(hdc, mid, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0,
166                             NULL, &mat2) == GDI_ERROR) {
167            max = mid;
168        } else {
169            min = mid + 1;
170        }
171    }
172    SkASSERT(min == max);
173    return min;
174}
175
176class LogFontTypeface : public SkTypeface {
177public:
178    LogFontTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, bool serializeAsStream = false) :
179        SkTypeface(style, fontID, false), fLogFont(lf), fSerializeAsStream(serializeAsStream) {
180
181        // If the font has cubic outlines, it will not be rendered with ClearType.
182        HFONT font = CreateFontIndirect(&lf);
183
184        HDC deviceContext = ::CreateCompatibleDC(NULL);
185        HFONT savefont = (HFONT)SelectObject(deviceContext, font);
186
187        TEXTMETRIC textMetric;
188        if (0 == GetTextMetrics(deviceContext, &textMetric)) {
189            call_ensure_accessible(lf);
190            if (0 == GetTextMetrics(deviceContext, &textMetric)) {
191                textMetric.tmPitchAndFamily = TMPF_TRUETYPE;
192            }
193        }
194        if (deviceContext) {
195            ::SelectObject(deviceContext, savefont);
196            ::DeleteDC(deviceContext);
197        }
198        if (font) {
199            ::DeleteObject(font);
200        }
201
202        // The fixed pitch bit is set if the font is *not* fixed pitch.
203        this->setIsFixedPitch((textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0);
204
205        // Used a logfont on a memory context, should never get a device font.
206        // Therefore all TMPF_DEVICE will be PostScript (cubic) fonts.
207        fCanBeLCD = !((textMetric.tmPitchAndFamily & TMPF_VECTOR) &&
208                      (textMetric.tmPitchAndFamily & TMPF_DEVICE));
209    }
210
211    void getFamilyName(SkString* name) const {
212        tchar_to_skstring(fLogFont.lfFaceName, name);
213    }
214
215    LOGFONT fLogFont;
216    bool fSerializeAsStream;
217    bool fCanBeLCD;
218
219    static LogFontTypeface* Create(const LOGFONT& lf) {
220        SkTypeface::Style style = get_style(lf);
221        SkFontID fontID = SkTypefaceCache::NewFontID();
222        return new LogFontTypeface(style, fontID, lf);
223    }
224
225    static void EnsureAccessible(const SkTypeface* face) {
226        call_ensure_accessible(static_cast<const LogFontTypeface*>(face)->fLogFont);
227    }
228
229protected:
230    virtual SkStream* onOpenStream(int* ttcIndex) const SK_OVERRIDE;
231    virtual SkScalerContext* onCreateScalerContext(const SkDescriptor*) const SK_OVERRIDE;
232    virtual void onFilterRec(SkScalerContextRec*) const SK_OVERRIDE;
233    virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics(
234                                SkAdvancedTypefaceMetrics::PerGlyphInfo,
235                                const uint32_t*, uint32_t) const SK_OVERRIDE;
236    virtual void onGetFontDescriptor(SkFontDescriptor*, bool*) const SK_OVERRIDE;
237};
238
239class FontMemResourceTypeface : public LogFontTypeface {
240public:
241    /**
242     *  Takes ownership of fontMemResource.
243     */
244    FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) :
245        LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) {
246    }
247
248    HANDLE fFontMemResource;
249
250    /**
251     *  The created FontMemResourceTypeface takes ownership of fontMemResource.
252     */
253    static FontMemResourceTypeface* Create(const LOGFONT& lf, HANDLE fontMemResource) {
254        SkTypeface::Style style = get_style(lf);
255        SkFontID fontID = SkTypefaceCache::NewFontID();
256        return new FontMemResourceTypeface(style, fontID, lf, fontMemResource);
257    }
258
259protected:
260    virtual void weak_dispose() const SK_OVERRIDE {
261        RemoveFontMemResourceEx(fFontMemResource);
262        //SkTypefaceCache::Remove(this);
263        INHERITED::weak_dispose();
264    }
265
266private:
267    typedef LogFontTypeface INHERITED;
268};
269
270static const LOGFONT& get_default_font() {
271    static LOGFONT gDefaultFont;
272    return gDefaultFont;
273}
274
275static bool FindByLogFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) {
276    LogFontTypeface* lface = static_cast<LogFontTypeface*>(face);
277    const LOGFONT* lf = reinterpret_cast<const LOGFONT*>(ctx);
278
279    return lface &&
280           get_style(lface->fLogFont) == requestedStyle &&
281           !memcmp(&lface->fLogFont, lf, sizeof(LOGFONT));
282}
283
284/**
285 *  This guy is public. It first searches the cache, and if a match is not found,
286 *  it creates a new face.
287 */
288SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) {
289    LOGFONT lf = origLF;
290    make_canonical(&lf);
291    SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf);
292    if (NULL == face) {
293        face = LogFontTypeface::Create(lf);
294        SkTypefaceCache::Add(face, get_style(lf));
295    }
296    return face;
297}
298
299/**
300 *  The created SkTypeface takes ownership of fontMemResource.
301 */
302SkTypeface* SkCreateFontMemResourceTypefaceFromLOGFONT(const LOGFONT& origLF, HANDLE fontMemResource) {
303    LOGFONT lf = origLF;
304    make_canonical(&lf);
305    FontMemResourceTypeface* face = FontMemResourceTypeface::Create(lf, fontMemResource);
306    SkTypefaceCache::Add(face, get_style(lf), false);
307    return face;
308}
309
310/**
311 *  This guy is public
312 */
313void SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) {
314    if (NULL == face) {
315        *lf = get_default_font();
316    } else {
317        *lf = static_cast<const LogFontTypeface*>(face)->fLogFont;
318    }
319}
320
321static void GetLogFontByID(SkFontID fontID, LOGFONT* lf) {
322    LogFontTypeface* face = static_cast<LogFontTypeface*>(SkTypefaceCache::FindByID(fontID));
323    if (face) {
324        *lf = face->fLogFont;
325    } else {
326        sk_bzero(lf, sizeof(LOGFONT));
327    }
328}
329
330// Construct Glyph to Unicode table.
331// Unicode code points that require conjugate pairs in utf16 are not
332// supported.
333// TODO(arthurhsu): Add support for conjugate pairs. It looks like that may
334// require parsing the TTF cmap table (platform 4, encoding 12) directly instead
335// of calling GetFontUnicodeRange().
336static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount,
337                                      SkTDArray<SkUnichar>* glyphToUnicode) {
338    DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, NULL);
339    if (!glyphSetBufferSize) {
340        return;
341    }
342
343    SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]);
344    GLYPHSET* glyphSet =
345        reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get());
346    if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) {
347        return;
348    }
349
350    glyphToUnicode->setCount(glyphCount);
351    memset(glyphToUnicode->begin(), 0, glyphCount * sizeof(SkUnichar));
352    for (DWORD i = 0; i < glyphSet->cRanges; ++i) {
353        // There is no guarantee that within a Unicode range, the corresponding
354        // glyph id in a font file are continuous. So, even if we have ranges,
355        // we can't just use the first and last entry of the range to compute
356        // result. We need to enumerate them one by one.
357        int count = glyphSet->ranges[i].cGlyphs;
358        SkAutoTArray<WCHAR> chars(count + 1);
359        chars[count] = 0;  // termintate string
360        SkAutoTArray<WORD> glyph(count);
361        for (USHORT j = 0; j < count; ++j) {
362            chars[j] = glyphSet->ranges[i].wcLow + j;
363        }
364        GetGlyphIndicesW(fontHdc, chars.get(), count, glyph.get(),
365                         GGI_MARK_NONEXISTING_GLYPHS);
366        // If the glyph ID is valid, and the glyph is not mapped, then we will
367        // fill in the char id into the vector. If the glyph is mapped already,
368        // skip it.
369        // TODO(arthurhsu): better improve this. e.g. Get all used char ids from
370        // font cache, then generate this mapping table from there. It's
371        // unlikely to have collisions since glyph reuse happens mostly for
372        // different Unicode pages.
373        for (USHORT j = 0; j < count; ++j) {
374            if (glyph[j] != 0xffff && glyph[j] < glyphCount &&
375                (*glyphToUnicode)[glyph[j]] == 0) {
376                (*glyphToUnicode)[glyph[j]] = chars[j];
377            }
378        }
379    }
380}
381
382//////////////////////////////////////////////////////////////////////////////////////
383
384static int alignTo32(int n) {
385    return (n + 31) & ~31;
386}
387
388struct MyBitmapInfo : public BITMAPINFO {
389    RGBQUAD fMoreSpaceForColors[1];
390};
391
392class HDCOffscreen {
393public:
394    HDCOffscreen() {
395        fFont = 0;
396        fDC = 0;
397        fBM = 0;
398        fBits = NULL;
399        fWidth = fHeight = 0;
400        fIsBW = false;
401    }
402
403    ~HDCOffscreen() {
404        if (fDC) {
405            DeleteDC(fDC);
406        }
407        if (fBM) {
408            DeleteObject(fBM);
409        }
410    }
411
412    void init(HFONT font, const XFORM& xform) {
413        fFont = font;
414        fXform = xform;
415    }
416
417    const void* draw(const SkGlyph&, bool isBW, size_t* srcRBPtr);
418
419private:
420    HDC     fDC;
421    HBITMAP fBM;
422    HFONT   fFont;
423    XFORM   fXform;
424    void*   fBits;  // points into fBM
425    int     fWidth;
426    int     fHeight;
427    bool    fIsBW;
428
429    enum {
430        // will always trigger us to reset the color, since we
431        // should only store 0 or 0x00FFFFFF or gray (0x007F7F7F)
432        kInvalid_Color = 12345
433    };
434};
435
436const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW,
437                               size_t* srcRBPtr) {
438    if (0 == fDC) {
439        fDC = CreateCompatibleDC(0);
440        if (0 == fDC) {
441            return NULL;
442        }
443        SetGraphicsMode(fDC, GM_ADVANCED);
444        SetBkMode(fDC, TRANSPARENT);
445        SetTextAlign(fDC, TA_LEFT | TA_BASELINE);
446        SelectObject(fDC, fFont);
447
448        COLORREF color = 0x00FFFFFF;
449        SkDEBUGCODE(COLORREF prev =) SetTextColor(fDC, color);
450        SkASSERT(prev != CLR_INVALID);
451    }
452
453    if (fBM && (fIsBW != isBW || fWidth < glyph.fWidth || fHeight < glyph.fHeight)) {
454        DeleteObject(fBM);
455        fBM = 0;
456    }
457    fIsBW = isBW;
458
459    fWidth = SkMax32(fWidth, glyph.fWidth);
460    fHeight = SkMax32(fHeight, glyph.fHeight);
461
462    int biWidth = isBW ? alignTo32(fWidth) : fWidth;
463
464    if (0 == fBM) {
465        MyBitmapInfo info;
466        sk_bzero(&info, sizeof(info));
467        if (isBW) {
468            RGBQUAD blackQuad = { 0, 0, 0, 0 };
469            RGBQUAD whiteQuad = { 0xFF, 0xFF, 0xFF, 0 };
470            info.bmiColors[0] = blackQuad;
471            info.bmiColors[1] = whiteQuad;
472        }
473        info.bmiHeader.biSize = sizeof(info.bmiHeader);
474        info.bmiHeader.biWidth = biWidth;
475        info.bmiHeader.biHeight = fHeight;
476        info.bmiHeader.biPlanes = 1;
477        info.bmiHeader.biBitCount = isBW ? 1 : 32;
478        info.bmiHeader.biCompression = BI_RGB;
479        if (isBW) {
480            info.bmiHeader.biClrUsed = 2;
481        }
482        fBM = CreateDIBSection(fDC, &info, DIB_RGB_COLORS, &fBits, 0, 0);
483        if (0 == fBM) {
484            return NULL;
485        }
486        SelectObject(fDC, fBM);
487    }
488
489    // erase
490    size_t srcRB = isBW ? (biWidth >> 3) : (fWidth << 2);
491    size_t size = fHeight * srcRB;
492    memset(fBits, 0, size);
493
494    XFORM xform = fXform;
495    xform.eDx = (float)-glyph.fLeft;
496    xform.eDy = (float)-glyph.fTop;
497    SetWorldTransform(fDC, &xform);
498
499    uint16_t glyphID = glyph.getGlyphID();
500    BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, NULL, reinterpret_cast<LPCWSTR>(&glyphID), 1, NULL);
501    GdiFlush();
502    if (0 == ret) {
503        return NULL;
504    }
505    *srcRBPtr = srcRB;
506    // offset to the start of the image
507    return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB;
508}
509
510//////////////////////////////////////////////////////////////////////////////
511
512class SkScalerContext_Windows : public SkScalerContext {
513public:
514    SkScalerContext_Windows(SkTypeface*, const SkDescriptor* desc);
515    virtual ~SkScalerContext_Windows();
516
517protected:
518    virtual unsigned generateGlyphCount() SK_OVERRIDE;
519    virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE;
520    virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE;
521    virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE;
522    virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE;
523    virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE;
524    virtual void generateFontMetrics(SkPaint::FontMetrics* mX,
525                                     SkPaint::FontMetrics* mY) SK_OVERRIDE;
526
527private:
528    HDCOffscreen fOffscreen;
529    SkScalar     fScale;  // to get from canonical size to real size
530    MAT2         fMat22;
531    HDC          fDDC;
532    HFONT        fSavefont;
533    HFONT        fFont;
534    SCRIPT_CACHE fSC;
535    int          fGlyphCount;
536
537    HFONT        fHiResFont;
538    MAT2         fMat22Identity;
539    SkMatrix     fHiResMatrix;
540    enum Type {
541        kTrueType_Type, kBitmap_Type,
542    } fType;
543    TEXTMETRIC fTM;
544};
545
546static float mul2float(SkScalar a, SkScalar b) {
547    return SkScalarToFloat(SkScalarMul(a, b));
548}
549
550static FIXED float2FIXED(float x) {
551    return SkFixedToFIXED(SkFloatToFixed(x));
552}
553
554SK_DECLARE_STATIC_MUTEX(gFTMutex);
555
556#define HIRES_TEXTSIZE  2048
557#define HIRES_SHIFT     11
558static inline SkFixed HiResToFixed(int value) {
559    return value << (16 - HIRES_SHIFT);
560}
561
562static bool needHiResMetrics(const SkScalar mat[2][2]) {
563    return mat[1][0] || mat[0][1];
564}
565
566static BYTE compute_quality(const SkScalerContext::Rec& rec) {
567    switch (rec.fMaskFormat) {
568        case SkMask::kBW_Format:
569            return NONANTIALIASED_QUALITY;
570        case SkMask::kLCD16_Format:
571        case SkMask::kLCD32_Format:
572            return CLEARTYPE_QUALITY;
573        default:
574            if (rec.fFlags & SkScalerContext::kGenA8FromLCD_Flag) {
575                return CLEARTYPE_QUALITY;
576            } else {
577                return ANTIALIASED_QUALITY;
578            }
579    }
580}
581
582SkScalerContext_Windows::SkScalerContext_Windows(SkTypeface* rawTypeface,
583                                                 const SkDescriptor* desc)
584        : SkScalerContext(rawTypeface, desc)
585        , fDDC(0)
586        , fFont(0)
587        , fSavefont(0)
588        , fSC(0)
589        , fGlyphCount(-1) {
590    SkAutoMutexAcquire  ac(gFTMutex);
591
592    LogFontTypeface* typeface = reinterpret_cast<LogFontTypeface*>(rawTypeface);
593
594    fDDC = ::CreateCompatibleDC(NULL);
595    SetGraphicsMode(fDDC, GM_ADVANCED);
596    SetBkMode(fDDC, TRANSPARENT);
597
598    // Scaling by the DPI is inconsistent with how Skia draws elsewhere
599    //SkScalar height = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);
600    LOGFONT lf = typeface->fLogFont;
601    lf.lfHeight = -gCanonicalTextSize;
602    lf.lfQuality = compute_quality(fRec);
603    fFont = CreateFontIndirect(&lf);
604
605    // if we're rotated, or want fractional widths, create a hires font
606    fHiResFont = 0;
607    if (needHiResMetrics(fRec.fPost2x2)) {
608        lf.lfHeight = -HIRES_TEXTSIZE;
609        fHiResFont = CreateFontIndirect(&lf);
610
611        fMat22Identity.eM11 = fMat22Identity.eM22 = SkFixedToFIXED(SK_Fixed1);
612        fMat22Identity.eM12 = fMat22Identity.eM21 = SkFixedToFIXED(0);
613
614        // construct a matrix to go from HIRES logical units to our device units
615        fRec.getSingleMatrix(&fHiResMatrix);
616        SkScalar scale = SkScalarInvert(SkIntToScalar(HIRES_TEXTSIZE));
617        fHiResMatrix.preScale(scale, scale);
618    }
619    fSavefont = (HFONT)SelectObject(fDDC, fFont);
620
621    if (0 == GetTextMetrics(fDDC, &fTM)) {
622        call_ensure_accessible(lf);
623        if (0 == GetTextMetrics(fDDC, &fTM)) {
624            fTM.tmPitchAndFamily = TMPF_TRUETYPE;
625        }
626    }
627    // Used a logfont on a memory context, should never get a device font.
628    // Therefore all TMPF_DEVICE will be PostScript fonts.
629
630    // If TMPF_VECTOR is set, one of TMPF_TRUETYPE or TMPF_DEVICE must be set,
631    // otherwise we have a vector FON, which we don't support.
632    // This was determined by testing with Type1 PFM/PFB and OpenTypeCFF OTF,
633    // as well as looking at Wine bugs and sources.
634    SkASSERT(!(fTM.tmPitchAndFamily & TMPF_VECTOR) ||
635              (fTM.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_DEVICE)));
636
637    XFORM xform;
638    if (fTM.tmPitchAndFamily & TMPF_VECTOR) {
639        // Truetype or PostScript.
640        // Stroked FON also gets here (TMPF_VECTOR), but we don't handle it.
641        fType = SkScalerContext_Windows::kTrueType_Type;
642        fScale = fRec.fTextSize / gCanonicalTextSize;
643
644        // fPost2x2 is column-major, left handed (y down).
645        // XFORM 2x2 is row-major, left handed (y down).
646        xform.eM11 = mul2float(fScale, fRec.fPost2x2[0][0]);
647        xform.eM12 = mul2float(fScale, fRec.fPost2x2[1][0]);
648        xform.eM21 = mul2float(fScale, fRec.fPost2x2[0][1]);
649        xform.eM22 = mul2float(fScale, fRec.fPost2x2[1][1]);
650        xform.eDx = 0;
651        xform.eDy = 0;
652
653        // MAT2 is row major, right handed (y up).
654        fMat22.eM11 = float2FIXED(xform.eM11);
655        fMat22.eM12 = float2FIXED(-xform.eM12);
656        fMat22.eM21 = float2FIXED(-xform.eM21);
657        fMat22.eM22 = float2FIXED(xform.eM22);
658
659        if (needToRenderWithSkia(fRec)) {
660            this->forceGenerateImageFromPath();
661        }
662
663    } else {
664        // Assume bitmap
665        fType = SkScalerContext_Windows::kBitmap_Type;
666        fScale = SK_Scalar1;
667
668        xform.eM11 = 1.0f;
669        xform.eM12 = 0.0f;
670        xform.eM21 = 0.0f;
671        xform.eM22 = 1.0f;
672        xform.eDx = 0.0f;
673        xform.eDy = 0.0f;
674
675        // fPost2x2 is column-major, left handed (y down).
676        // MAT2 is row major, right handed (y up).
677        fMat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);
678        fMat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[1][0]);
679        fMat22.eM21 = SkScalarToFIXED(-fRec.fPost2x2[0][1]);
680        fMat22.eM22 = SkScalarToFIXED(fRec.fPost2x2[1][1]);
681
682        lf.lfHeight = -SkScalarCeilToInt(fRec.fTextSize);
683        HFONT bitmapFont = CreateFontIndirect(&lf);
684        SelectObject(fDDC, bitmapFont);
685        ::DeleteObject(fFont);
686        fFont = bitmapFont;
687
688        if (0 == GetTextMetrics(fDDC, &fTM)) {
689            call_ensure_accessible(lf);
690            //if the following fails, we'll just draw at gCanonicalTextSize.
691            GetTextMetrics(fDDC, &fTM);
692        }
693    }
694
695    fOffscreen.init(fFont, xform);
696}
697
698SkScalerContext_Windows::~SkScalerContext_Windows() {
699    if (fDDC) {
700        ::SelectObject(fDDC, fSavefont);
701        ::DeleteDC(fDDC);
702    }
703    if (fFont) {
704        ::DeleteObject(fFont);
705    }
706    if (fHiResFont) {
707        ::DeleteObject(fHiResFont);
708    }
709    if (fSC) {
710        ::ScriptFreeCache(&fSC);
711    }
712}
713
714unsigned SkScalerContext_Windows::generateGlyphCount() {
715    if (fGlyphCount < 0) {
716        if (fType == SkScalerContext_Windows::kBitmap_Type) {
717           return fTM.tmLastChar;
718        }
719        fGlyphCount = calculateOutlineGlyphCount(fDDC);
720    }
721    return fGlyphCount;
722}
723
724uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {
725    uint16_t index = 0;
726    WCHAR c[2];
727    // TODO(ctguil): Support characters that generate more than one glyph.
728    if (SkUTF16_FromUnichar(uni, (uint16_t*)c) == 1) {
729        // Type1 fonts fail with uniscribe API. Use GetGlyphIndices for plane 0.
730        SkAssertResult(GetGlyphIndicesW(fDDC, c, 1, &index, 0));
731    } else {
732        // Use uniscribe to detemine glyph index for non-BMP characters.
733        // Need to add extra item to SCRIPT_ITEM to work around a bug in older
734        // windows versions. https://bugzilla.mozilla.org/show_bug.cgi?id=366643
735        SCRIPT_ITEM si[2 + 1];
736        int items;
737        SkAssertResult(
738            SUCCEEDED(ScriptItemize(c, 2, 2, NULL, NULL, si, &items)));
739
740        WORD log[2];
741        SCRIPT_VISATTR vsa;
742        int glyphs;
743        SkAssertResult(SUCCEEDED(ScriptShape(
744            fDDC, &fSC, c, 2, 1, &si[0].a, &index, log, &vsa, &glyphs)));
745    }
746    return index;
747}
748
749void SkScalerContext_Windows::generateAdvance(SkGlyph* glyph) {
750    this->generateMetrics(glyph);
751}
752
753void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {
754    SkASSERT(fDDC);
755
756    if (fType == SkScalerContext_Windows::kBitmap_Type) {
757        SIZE size;
758        WORD glyphs = glyph->getGlyphID(0);
759        if (0 == GetTextExtentPointI(fDDC, &glyphs, 1, &size)) {
760            glyph->fWidth = SkToS16(fTM.tmMaxCharWidth);
761        } else {
762            glyph->fWidth = SkToS16(size.cx);
763        }
764        glyph->fHeight = SkToS16(size.cy);
765
766        glyph->fTop = SkToS16(-fTM.tmAscent);
767        glyph->fLeft = SkToS16(0);
768        glyph->fAdvanceX = SkIntToFixed(glyph->fWidth);
769        glyph->fAdvanceY = 0;
770
771        // Apply matrix to advance.
772        glyph->fAdvanceY = SkFixedMul(SkFIXEDToFixed(fMat22.eM21), glyph->fAdvanceX);
773        glyph->fAdvanceX = SkFixedMul(SkFIXEDToFixed(fMat22.eM11), glyph->fAdvanceX);
774
775        return;
776    }
777
778    UINT glyphId = glyph->getGlyphID(0);
779
780    GLYPHMETRICS gm;
781    sk_bzero(&gm, sizeof(gm));
782
783    DWORD status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
784    if (GDI_ERROR == status) {
785        LogFontTypeface::EnsureAccessible(this->getTypeface());
786        status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
787        if (GDI_ERROR == status) {
788            glyph->zeroMetrics();
789            return;
790        }
791    }
792
793    bool empty = false;
794    // The black box is either the embedded bitmap size or the outline extent.
795    // It is 1x1 if nothing is to be drawn, but will also be 1x1 if something very small
796    // is to be drawn, like a '.'. We need to outset '.' but do not wish to outset ' '.
797    if (1 == gm.gmBlackBoxX && 1 == gm.gmBlackBoxY) {
798        // If GetGlyphOutline with GGO_NATIVE returns 0, we know there was no outline.
799        DWORD bufferSize = GetGlyphOutlineW(fDDC, glyphId, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22);
800        empty = (0 == bufferSize);
801    }
802
803    glyph->fTop = SkToS16(-gm.gmptGlyphOrigin.y);
804    glyph->fLeft = SkToS16(gm.gmptGlyphOrigin.x);
805    if (empty) {
806        glyph->fWidth = 0;
807        glyph->fHeight = 0;
808    } else {
809        // Outset, since the image may bleed out of the black box.
810        // For embedded bitmaps the black box should be exact.
811        // For outlines we need to outset by 1 in all directions for bleed.
812        // For ClearType we need to outset by 2 for bleed.
813        glyph->fWidth = gm.gmBlackBoxX + 4;
814        glyph->fHeight = gm.gmBlackBoxY + 4;
815        glyph->fTop -= 2;
816        glyph->fLeft -= 2;
817    }
818    glyph->fAdvanceX = SkIntToFixed(gm.gmCellIncX);
819    glyph->fAdvanceY = SkIntToFixed(gm.gmCellIncY);
820    glyph->fRsbDelta = 0;
821    glyph->fLsbDelta = 0;
822
823    if (fHiResFont) {
824        SelectObject(fDDC, fHiResFont);
825        sk_bzero(&gm, sizeof(gm));
826        status = GetGlyphOutlineW(fDDC, glyphId, GGO_METRICS | GGO_GLYPH_INDEX, &gm, 0, NULL, &fMat22Identity);
827        if (GDI_ERROR != status) {
828            SkPoint advance;
829            fHiResMatrix.mapXY(SkIntToScalar(gm.gmCellIncX), SkIntToScalar(gm.gmCellIncY), &advance);
830            glyph->fAdvanceX = SkScalarToFixed(advance.fX);
831            glyph->fAdvanceY = SkScalarToFixed(advance.fY);
832        }
833        SelectObject(fDDC, fFont);
834    }
835}
836
837void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {
838// Note: This code was borrowed from generateLineHeight, which has a note
839// stating that it may be incorrect.
840    if (!(mx || my))
841      return;
842
843    SkASSERT(fDDC);
844
845    if (fType == SkScalerContext_Windows::kBitmap_Type) {
846        if (mx) {
847            mx->fTop = SkIntToScalar(-fTM.tmAscent);
848            mx->fAscent = SkIntToScalar(-fTM.tmAscent);
849            mx->fDescent = -SkIntToScalar(fTM.tmDescent);
850            mx->fBottom = SkIntToScalar(fTM.tmDescent);
851            mx->fLeading = SkIntToScalar(fTM.tmInternalLeading
852                                         + fTM.tmExternalLeading);
853        }
854
855        if (my) {
856            my->fTop = SkIntToScalar(-fTM.tmAscent);
857            my->fAscent = SkIntToScalar(-fTM.tmAscent);
858            my->fDescent = SkIntToScalar(-fTM.tmDescent);
859            my->fBottom = SkIntToScalar(fTM.tmDescent);
860            my->fLeading = SkIntToScalar(fTM.tmInternalLeading
861                                         + fTM.tmExternalLeading);
862        }
863        return;
864    }
865
866    OUTLINETEXTMETRIC otm;
867
868    uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
869    if (GDI_ERROR == ret) {
870        LogFontTypeface::EnsureAccessible(this->getTypeface());
871        ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm);
872    }
873    if (sizeof(otm) != ret) {
874        return;
875    }
876
877    if (mx) {
878        mx->fTop = -fScale * otm.otmTextMetrics.tmAscent;
879        mx->fAscent = -fScale * otm.otmAscent;
880        mx->fDescent = -fScale * otm.otmDescent;
881        mx->fBottom = fScale * otm.otmTextMetrics.tmDescent;
882        mx->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
883                                 + otm.otmTextMetrics.tmExternalLeading);
884    }
885
886    if (my) {
887        my->fTop = -fScale * otm.otmTextMetrics.tmAscent;
888        my->fAscent = -fScale * otm.otmAscent;
889        my->fDescent = -fScale * otm.otmDescent;
890        my->fBottom = fScale * otm.otmTextMetrics.tmDescent;
891        my->fLeading = fScale * (otm.otmTextMetrics.tmInternalLeading
892                                 + otm.otmTextMetrics.tmExternalLeading);
893    }
894}
895
896////////////////////////////////////////////////////////////////////////////////////////
897
898static void build_power_table(uint8_t table[], float ee) {
899    for (int i = 0; i < 256; i++) {
900        float x = i / 255.f;
901        x = sk_float_pow(x, ee);
902        int xx = SkScalarRound(SkFloatToScalar(x * 255));
903        table[i] = SkToU8(xx);
904    }
905}
906
907/**
908 *  This will invert the gamma applied by GDI (gray-scale antialiased), so we
909 *  can get linear values.
910 *
911 *  GDI grayscale appears to use a hard-coded gamma of 2.3.
912 *
913 *  GDI grayscale appears to draw using the black and white rasterizer at four
914 *  times the size and then downsamples to compute the coverage mask. As a
915 *  result there are only seventeen total grays. This lack of fidelity means
916 *  that shifting into other color spaces is imprecise.
917 */
918static const uint8_t* getInverseGammaTableGDI() {
919    static bool gInited;
920    static uint8_t gTableGdi[256];
921    if (!gInited) {
922        build_power_table(gTableGdi, 2.3f);
923        gInited = true;
924    }
925    return gTableGdi;
926}
927
928/**
929 *  This will invert the gamma applied by GDI ClearType, so we can get linear
930 *  values.
931 *
932 *  GDI ClearType uses SPI_GETFONTSMOOTHINGCONTRAST / 1000 as the gamma value.
933 *  If this value is not specified, the default is a gamma of 1.4.
934 */
935static const uint8_t* getInverseGammaTableClearType() {
936    static bool gInited;
937    static uint8_t gTableClearType[256];
938    if (!gInited) {
939        UINT level = 0;
940        if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) {
941            // can't get the data, so use a default
942            level = 1400;
943        }
944        build_power_table(gTableClearType, level / 1000.0f);
945        gInited = true;
946    }
947    return gTableClearType;
948}
949
950#include "SkColorPriv.h"
951
952//Cannot assume that the input rgb is gray due to possible setting of kGenA8FromLCD_Flag.
953template<bool APPLY_PREBLEND>
954static inline uint8_t rgb_to_a8(SkGdiRGB rgb, const uint8_t* table8) {
955    U8CPU r = (rgb >> 16) & 0xFF;
956    U8CPU g = (rgb >>  8) & 0xFF;
957    U8CPU b = (rgb >>  0) & 0xFF;
958    return sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8);
959}
960
961template<bool APPLY_PREBLEND>
962static inline uint16_t rgb_to_lcd16(SkGdiRGB rgb, const uint8_t* tableR,
963                                                  const uint8_t* tableG,
964                                                  const uint8_t* tableB) {
965    U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
966    U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
967    U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
968    return SkPack888ToRGB16(r, g, b);
969}
970
971template<bool APPLY_PREBLEND>
972static inline SkPMColor rgb_to_lcd32(SkGdiRGB rgb, const uint8_t* tableR,
973                                                   const uint8_t* tableG,
974                                                   const uint8_t* tableB) {
975    U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR);
976    U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  8) & 0xFF, tableG);
977    U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >>  0) & 0xFF, tableB);
978    return SkPackARGB32(0xFF, r, g, b);
979}
980
981// Is this GDI color neither black nor white? If so, we have to keep this
982// image as is, rather than smashing it down to a BW mask.
983//
984// returns int instead of bool, since we don't want/have to pay to convert
985// the zero/non-zero value into a bool
986static int is_not_black_or_white(SkGdiRGB c) {
987    // same as (but faster than)
988    //      c &= 0x00FFFFFF;
989    //      return 0 == c || 0x00FFFFFF == c;
990    return (c + (c & 1)) & 0x00FFFFFF;
991}
992
993static bool is_rgb_really_bw(const SkGdiRGB* src, int width, int height, int srcRB) {
994    for (int y = 0; y < height; ++y) {
995        for (int x = 0; x < width; ++x) {
996            if (is_not_black_or_white(src[x])) {
997                return false;
998            }
999        }
1000        src = SkTAddByteOffset(src, srcRB);
1001    }
1002    return true;
1003}
1004
1005// gdi's bitmap is upside-down, so we reverse dst walking in Y
1006// whenever we copy it into skia's buffer
1007static void rgb_to_bw(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
1008                      const SkGlyph& glyph) {
1009    const int width = glyph.fWidth;
1010    const size_t dstRB = (width + 7) >> 3;
1011    uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
1012
1013    int byteCount = width >> 3;
1014    int bitCount = width & 7;
1015
1016    // adjust srcRB to skip the values in our byteCount loop,
1017    // since we increment src locally there
1018    srcRB -= byteCount * 8 * sizeof(SkGdiRGB);
1019
1020    for (int y = 0; y < glyph.fHeight; ++y) {
1021        if (byteCount > 0) {
1022            for (int i = 0; i < byteCount; ++i) {
1023                unsigned byte = 0;
1024                byte |= src[0] & (1 << 7);
1025                byte |= src[1] & (1 << 6);
1026                byte |= src[2] & (1 << 5);
1027                byte |= src[3] & (1 << 4);
1028                byte |= src[4] & (1 << 3);
1029                byte |= src[5] & (1 << 2);
1030                byte |= src[6] & (1 << 1);
1031                byte |= src[7] & (1 << 0);
1032                dst[i] = byte;
1033                src += 8;
1034            }
1035        }
1036        if (bitCount > 0) {
1037            unsigned byte = 0;
1038            unsigned mask = 0x80;
1039            for (int i = 0; i < bitCount; i++) {
1040                byte |= src[i] & mask;
1041                mask >>= 1;
1042            }
1043            dst[byteCount] = byte;
1044        }
1045        src = SkTAddByteOffset(src, srcRB);
1046        dst -= dstRB;
1047    }
1048}
1049
1050template<bool APPLY_PREBLEND>
1051static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB,
1052                      const SkGlyph& glyph, const uint8_t* table8) {
1053    const size_t dstRB = glyph.rowBytes();
1054    const int width = glyph.fWidth;
1055    uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
1056
1057    for (int y = 0; y < glyph.fHeight; y++) {
1058        for (int i = 0; i < width; i++) {
1059            dst[i] = rgb_to_a8<APPLY_PREBLEND>(src[i], table8);
1060        }
1061        src = SkTAddByteOffset(src, srcRB);
1062        dst -= dstRB;
1063    }
1064}
1065
1066template<bool APPLY_PREBLEND>
1067static void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph,
1068                         const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
1069    const size_t dstRB = glyph.rowBytes();
1070    const int width = glyph.fWidth;
1071    uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
1072
1073    for (int y = 0; y < glyph.fHeight; y++) {
1074        for (int i = 0; i < width; i++) {
1075            dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
1076        }
1077        src = SkTAddByteOffset(src, srcRB);
1078        dst = (uint16_t*)((char*)dst - dstRB);
1079    }
1080}
1081
1082template<bool APPLY_PREBLEND>
1083static void rgb_to_lcd32(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph,
1084                         const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) {
1085    const size_t dstRB = glyph.rowBytes();
1086    const int width = glyph.fWidth;
1087    uint32_t* SK_RESTRICT dst = (uint32_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
1088
1089    for (int y = 0; y < glyph.fHeight; y++) {
1090        for (int i = 0; i < width; i++) {
1091            dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(src[i], tableR, tableG, tableB);
1092        }
1093        src = SkTAddByteOffset(src, srcRB);
1094        dst = (uint32_t*)((char*)dst - dstRB);
1095    }
1096}
1097
1098static inline unsigned clamp255(unsigned x) {
1099    SkASSERT(x <= 256);
1100    return x - (x >> 8);
1101}
1102
1103void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {
1104    SkAutoMutexAcquire ac(gFTMutex);
1105    SkASSERT(fDDC);
1106
1107    const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat;
1108    const bool isAA = !isLCD(fRec);
1109
1110    size_t srcRB;
1111    const void* bits = fOffscreen.draw(glyph, isBW, &srcRB);
1112    if (NULL == bits) {
1113        LogFontTypeface::EnsureAccessible(this->getTypeface());
1114        bits = fOffscreen.draw(glyph, isBW, &srcRB);
1115        if (NULL == bits) {
1116            sk_bzero(glyph.fImage, glyph.computeImageSize());
1117            return;
1118        }
1119    }
1120
1121    if (!isBW) {
1122        const uint8_t* table;
1123        //The offscreen contains a GDI blit if isAA and kGenA8FromLCD_Flag is not set.
1124        //Otherwise the offscreen contains a ClearType blit.
1125        if (isAA && !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag)) {
1126            table = getInverseGammaTableGDI();
1127        } else {
1128            table = getInverseGammaTableClearType();
1129        }
1130        //Note that the following cannot really be integrated into the
1131        //pre-blend, since we may not be applying the pre-blend; when we aren't
1132        //applying the pre-blend it means that a filter wants linear anyway.
1133        //Other code may also be applying the pre-blend, so we'd need another
1134        //one with this and one without.
1135        SkGdiRGB* addr = (SkGdiRGB*)bits;
1136        for (int y = 0; y < glyph.fHeight; ++y) {
1137            for (int x = 0; x < glyph.fWidth; ++x) {
1138                int r = (addr[x] >> 16) & 0xFF;
1139                int g = (addr[x] >>  8) & 0xFF;
1140                int b = (addr[x] >>  0) & 0xFF;
1141                addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
1142            }
1143            addr = SkTAddByteOffset(addr, srcRB);
1144        }
1145    }
1146
1147    int width = glyph.fWidth;
1148    size_t dstRB = glyph.rowBytes();
1149    if (isBW) {
1150        const uint8_t* src = (const uint8_t*)bits;
1151        uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB);
1152        for (int y = 0; y < glyph.fHeight; y++) {
1153            memcpy(dst, src, dstRB);
1154            src += srcRB;
1155            dst -= dstRB;
1156        }
1157    } else if (isAA) {
1158        // since the caller may require A8 for maskfilters, we can't check for BW
1159        // ... until we have the caller tell us that explicitly
1160        const SkGdiRGB* src = (const SkGdiRGB*)bits;
1161        if (fPreBlend.isApplicable()) {
1162            rgb_to_a8<true>(src, srcRB, glyph, fPreBlend.fG);
1163        } else {
1164            rgb_to_a8<false>(src, srcRB, glyph, fPreBlend.fG);
1165        }
1166    } else {    // LCD16
1167        const SkGdiRGB* src = (const SkGdiRGB*)bits;
1168        if (is_rgb_really_bw(src, width, glyph.fHeight, srcRB)) {
1169            rgb_to_bw(src, srcRB, glyph);
1170            ((SkGlyph*)&glyph)->fMaskFormat = SkMask::kBW_Format;
1171        } else {
1172            if (SkMask::kLCD16_Format == glyph.fMaskFormat) {
1173                if (fPreBlend.isApplicable()) {
1174                    rgb_to_lcd16<true>(src, srcRB, glyph,
1175                                       fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1176                } else {
1177                    rgb_to_lcd16<false>(src, srcRB, glyph,
1178                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1179                }
1180            } else {
1181                SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat);
1182                if (fPreBlend.isApplicable()) {
1183                    rgb_to_lcd32<true>(src, srcRB, glyph,
1184                                       fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1185                } else {
1186                    rgb_to_lcd32<false>(src, srcRB, glyph,
1187                                        fPreBlend.fR, fPreBlend.fG, fPreBlend.fB);
1188                }
1189            }
1190        }
1191    }
1192}
1193
1194void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {
1195
1196    SkAutoMutexAcquire ac(gFTMutex);
1197
1198    SkASSERT(&glyph && path);
1199    SkASSERT(fDDC);
1200
1201    path->reset();
1202
1203    GLYPHMETRICS gm;
1204    uint32_t total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
1205    if (GDI_ERROR == total_size) {
1206        LogFontTypeface::EnsureAccessible(this->getTypeface());
1207        total_size = GetGlyphOutlineW(fDDC, glyph.fID, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, BUFFERSIZE, glyphbuf, &fMat22);
1208        if (GDI_ERROR == total_size) {
1209            SkASSERT(false);
1210            return;
1211        }
1212    }
1213
1214    const uint8_t* cur_glyph = glyphbuf;
1215    const uint8_t* end_glyph = glyphbuf + total_size;
1216
1217    while (cur_glyph < end_glyph) {
1218        const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;
1219
1220        const uint8_t* end_poly = cur_glyph + th->cb;
1221        const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);
1222
1223        path->moveTo(SkFixedToScalar( SkFIXEDToFixed(th->pfxStart.x)),
1224                     SkFixedToScalar(-SkFIXEDToFixed(th->pfxStart.y)));
1225
1226        while (cur_poly < end_poly) {
1227            const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;
1228
1229            if (pc->wType == TT_PRIM_LINE) {
1230                for (uint16_t i = 0; i < pc->cpfx; i++) {
1231                    path->lineTo(SkFixedToScalar( SkFIXEDToFixed(pc->apfx[i].x)),
1232                                 SkFixedToScalar(-SkFIXEDToFixed(pc->apfx[i].y)));
1233                }
1234            }
1235
1236            if (pc->wType == TT_PRIM_QSPLINE) {
1237                for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline
1238                    POINTFX pnt_b = pc->apfx[u];    // B is always the current point
1239                    POINTFX pnt_c = pc->apfx[u+1];
1240
1241                    if (u < pc->cpfx - 2) {          // If not on last spline, compute C
1242                        pnt_c.x = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.x),
1243                                                            SkFIXEDToFixed(pnt_c.x)));
1244                        pnt_c.y = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.y),
1245                                                            SkFIXEDToFixed(pnt_c.y)));
1246                    }
1247
1248                    path->quadTo(SkFixedToScalar( SkFIXEDToFixed(pnt_b.x)),
1249                                 SkFixedToScalar(-SkFIXEDToFixed(pnt_b.y)),
1250                                 SkFixedToScalar( SkFIXEDToFixed(pnt_c.x)),
1251                                 SkFixedToScalar(-SkFIXEDToFixed(pnt_c.y)));
1252                }
1253            }
1254            // Advance past this TTPOLYCURVE.
1255            cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx;
1256        }
1257        cur_glyph += th->cb;
1258        path->close();
1259    }
1260}
1261
1262static void logfont_for_name(const char* familyName, LOGFONT* lf) {
1263    sk_bzero(lf, sizeof(LOGFONT));
1264#ifdef UNICODE
1265    // Get the buffer size needed first.
1266    size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,
1267                                            -1, NULL, 0);
1268    // Allocate a buffer (str_len already has terminating null
1269    // accounted for).
1270    wchar_t *wideFamilyName = new wchar_t[str_len];
1271    // Now actually convert the string.
1272    ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,
1273                            wideFamilyName, str_len);
1274    ::wcsncpy(lf->lfFaceName, wideFamilyName, LF_FACESIZE - 1);
1275    delete [] wideFamilyName;
1276    lf->lfFaceName[LF_FACESIZE-1] = L'\0';
1277#else
1278    ::strncpy(lf->lfFaceName, familyName, LF_FACESIZE - 1);
1279    lf->lfFaceName[LF_FACESIZE - 1] = '\0';
1280#endif
1281}
1282
1283void LogFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc,
1284                                          bool* isLocalStream) const {
1285    // Get the actual name of the typeface. The logfont may not know this.
1286    HFONT font = CreateFontIndirect(&fLogFont);
1287
1288    HDC deviceContext = ::CreateCompatibleDC(NULL);
1289    HFONT savefont = (HFONT)SelectObject(deviceContext, font);
1290
1291    int fontNameLen; //length of fontName in TCHARS.
1292    if (0 == (fontNameLen = GetTextFace(deviceContext, 0, NULL))) {
1293        call_ensure_accessible(fLogFont);
1294        if (0 == (fontNameLen = GetTextFace(deviceContext, 0, NULL))) {
1295            fontNameLen = 0;
1296        }
1297    }
1298
1299    SkAutoSTArray<LF_FULLFACESIZE, TCHAR> fontName(fontNameLen+1);
1300    if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) {
1301        call_ensure_accessible(fLogFont);
1302        if (0 == GetTextFace(deviceContext, fontNameLen, fontName.get())) {
1303            fontName[0] = 0;
1304        }
1305    }
1306
1307    if (deviceContext) {
1308        ::SelectObject(deviceContext, savefont);
1309        ::DeleteDC(deviceContext);
1310    }
1311    if (font) {
1312        ::DeleteObject(font);
1313    }
1314
1315    SkString familyName;
1316    tchar_to_skstring(fontName.get(), &familyName);
1317
1318    desc->setFamilyName(familyName.c_str());
1319    *isLocalStream = this->fSerializeAsStream;
1320}
1321
1322static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) {
1323    // Initialize the MAT2 structure to the identify transformation matrix.
1324    static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0),
1325                        SkScalarToFIXED(0), SkScalarToFIXED(1)};
1326    int flags = GGO_METRICS | GGO_GLYPH_INDEX;
1327    GLYPHMETRICS gm;
1328    if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) {
1329        return false;
1330    }
1331    SkASSERT(advance);
1332    *advance = gm.gmCellIncX;
1333    return true;
1334}
1335
1336SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics(
1337        SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo,
1338        const uint32_t* glyphIDs,
1339        uint32_t glyphIDsCount) const {
1340    LOGFONT lf = fLogFont;
1341    SkAdvancedTypefaceMetrics* info = NULL;
1342
1343    HDC hdc = CreateCompatibleDC(NULL);
1344    HFONT font = CreateFontIndirect(&lf);
1345    HFONT savefont = (HFONT)SelectObject(hdc, font);
1346    HFONT designFont = NULL;
1347
1348    const char stem_chars[] = {'i', 'I', '!', '1'};
1349    int16_t min_width;
1350    unsigned glyphCount;
1351
1352    // To request design units, create a logical font whose height is specified
1353    // as unitsPerEm.
1354    OUTLINETEXTMETRIC otm;
1355    unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
1356    if (0 == otmRet) {
1357        call_ensure_accessible(lf);
1358        otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm);
1359    }
1360    if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) {
1361        goto Error;
1362    }
1363    lf.lfHeight = -SkToS32(otm.otmEMSquare);
1364    designFont = CreateFontIndirect(&lf);
1365    SelectObject(hdc, designFont);
1366    if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) {
1367        goto Error;
1368    }
1369    glyphCount = calculateOutlineGlyphCount(hdc);
1370
1371    info = new SkAdvancedTypefaceMetrics;
1372    info->fEmSize = otm.otmEMSquare;
1373    info->fMultiMaster = false;
1374    info->fLastGlyphID = SkToU16(glyphCount - 1);
1375    info->fStyle = 0;
1376    tchar_to_skstring(lf.lfFaceName, &info->fFontName);
1377
1378    if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) {
1379        populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode));
1380    }
1381
1382    if (glyphCount > 0 &&
1383        (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE)) {
1384        info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font;
1385    } else {
1386        info->fType = SkAdvancedTypefaceMetrics::kOther_Font;
1387        info->fItalicAngle = 0;
1388        info->fAscent = 0;
1389        info->fDescent = 0;
1390        info->fStemV = 0;
1391        info->fCapHeight = 0;
1392        info->fBBox = SkIRect::MakeEmpty();
1393        goto ReturnInfo;
1394    }
1395
1396    // If this bit is clear the font is a fixed pitch font.
1397    if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
1398        info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style;
1399    }
1400    if (otm.otmTextMetrics.tmItalic) {
1401        info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style;
1402    }
1403    if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) {
1404        info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
1405    } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) {
1406            info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
1407    }
1408
1409    // The main italic angle of the font, in tenths of a degree counterclockwise
1410    // from vertical.
1411    info->fItalicAngle = otm.otmItalicAngle / 10;
1412    info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent);
1413    info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent);
1414    // TODO(ctguil): Use alternate cap height calculation.
1415    // MSDN says otmsCapEmHeight is not support but it is returning a value on
1416    // my Win7 box.
1417    info->fCapHeight = otm.otmsCapEmHeight;
1418    info->fBBox =
1419        SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top,
1420                          otm.otmrcFontBox.right, otm.otmrcFontBox.bottom);
1421
1422    // Figure out a good guess for StemV - Min width of i, I, !, 1.
1423    // This probably isn't very good with an italic font.
1424    min_width = SHRT_MAX;
1425    info->fStemV = 0;
1426    for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) {
1427        ABC abcWidths;
1428        if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) {
1429            int16_t width = abcWidths.abcB;
1430            if (width > 0 && width < min_width) {
1431                min_width = width;
1432                info->fStemV = min_width;
1433            }
1434        }
1435    }
1436
1437    // If bit 1 is set, the font may not be embedded in a document.
1438    // If bit 1 is clear, the font can be embedded.
1439    // If bit 2 is set, the embedding is read-only.
1440    if (otm.otmfsType & 0x1) {
1441        info->fType = SkAdvancedTypefaceMetrics::kNotEmbeddable_Font;
1442    } else if (perGlyphInfo &
1443               SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) {
1444        if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) {
1445            appendRange(&info->fGlyphWidths, 0);
1446            info->fGlyphWidths->fAdvance.append(1, &min_width);
1447            finishRange(info->fGlyphWidths.get(), 0,
1448                        SkAdvancedTypefaceMetrics::WidthRange::kDefault);
1449        } else {
1450            info->fGlyphWidths.reset(
1451                getAdvanceData(hdc,
1452                               glyphCount,
1453                               glyphIDs,
1454                               glyphIDsCount,
1455                               &getWidthAdvance));
1456        }
1457    }
1458
1459Error:
1460ReturnInfo:
1461    SelectObject(hdc, savefont);
1462    DeleteObject(designFont);
1463    DeleteObject(font);
1464    DeleteDC(hdc);
1465
1466    return info;
1467}
1468
1469//Dummy representation of a Base64 encoded GUID from create_unique_font_name.
1470#define BASE64_GUID_ID "XXXXXXXXXXXXXXXXXXXXXXXX"
1471//Length of GUID representation from create_id, including NULL terminator.
1472#define BASE64_GUID_ID_LEN SK_ARRAY_COUNT(BASE64_GUID_ID)
1473
1474SK_COMPILE_ASSERT(BASE64_GUID_ID_LEN < LF_FACESIZE, GUID_longer_than_facesize);
1475
1476/**
1477   NameID 6 Postscript names cannot have the character '/'.
1478   It would be easier to hex encode the GUID, but that is 32 bytes,
1479   and many systems have issues with names longer than 28 bytes.
1480   The following need not be any standard base64 encoding.
1481   The encoded value is never decoded.
1482*/
1483static const char postscript_safe_base64_encode[] =
1484    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1485    "abcdefghijklmnopqrstuvwxyz"
1486    "0123456789-_=";
1487
1488/**
1489   Formats a GUID into Base64 and places it into buffer.
1490   buffer should have space for at least BASE64_GUID_ID_LEN characters.
1491   The string will always be null terminated.
1492   XXXXXXXXXXXXXXXXXXXXXXXX0
1493 */
1494static void format_guid_b64(const GUID& guid, char* buffer, size_t bufferSize) {
1495    SkASSERT(bufferSize >= BASE64_GUID_ID_LEN);
1496    size_t written = SkBase64::Encode(&guid, sizeof(guid), buffer, postscript_safe_base64_encode);
1497    SkASSERT(written < LF_FACESIZE);
1498    buffer[written] = '\0';
1499}
1500
1501/**
1502   Creates a Base64 encoded GUID and places it into buffer.
1503   buffer should have space for at least BASE64_GUID_ID_LEN characters.
1504   The string will always be null terminated.
1505   XXXXXXXXXXXXXXXXXXXXXXXX0
1506 */
1507static HRESULT create_unique_font_name(char* buffer, size_t bufferSize) {
1508    GUID guid = {};
1509    if (FAILED(CoCreateGuid(&guid))) {
1510        return E_UNEXPECTED;
1511    }
1512    format_guid_b64(guid, buffer, bufferSize);
1513
1514    return S_OK;
1515}
1516
1517/**
1518   Introduces a font to GDI. On failure will return NULL. The returned handle
1519   should eventually be passed to RemoveFontMemResourceEx.
1520*/
1521static HANDLE activate_font(SkData* fontData) {
1522    DWORD numFonts = 0;
1523    //AddFontMemResourceEx just copies the data, but does not specify const.
1524    HANDLE fontHandle = AddFontMemResourceEx(const_cast<void*>(fontData->data()),
1525                                             fontData->size(),
1526                                             0,
1527                                             &numFonts);
1528
1529    if (fontHandle != NULL && numFonts < 1) {
1530        RemoveFontMemResourceEx(fontHandle);
1531        return NULL;
1532    }
1533
1534    return fontHandle;
1535}
1536
1537SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {
1538    // Create a unique and unpredictable font name.
1539    // Avoids collisions and access from CSS.
1540    char familyName[BASE64_GUID_ID_LEN];
1541    const int familyNameSize = SK_ARRAY_COUNT(familyName);
1542    if (FAILED(create_unique_font_name(familyName, familyNameSize))) {
1543        return NULL;
1544    }
1545
1546    // Change the name of the font.
1547    SkAutoTUnref<SkData> rewrittenFontData(SkOTUtils::RenameFont(stream, familyName, familyNameSize-1));
1548    if (NULL == rewrittenFontData.get()) {
1549        return NULL;
1550    }
1551
1552    // Register the font with GDI.
1553    HANDLE fontReference = activate_font(rewrittenFontData.get());
1554    if (NULL == fontReference) {
1555        return NULL;
1556    }
1557
1558    // Create the typeface.
1559    LOGFONT lf;
1560    logfont_for_name(familyName, &lf);
1561
1562    return SkCreateFontMemResourceTypefaceFromLOGFONT(lf, fontReference);
1563}
1564
1565SkStream* LogFontTypeface::onOpenStream(int* ttcIndex) const {
1566    *ttcIndex = 0;
1567
1568    const DWORD kTTCTag =
1569        SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f'));
1570    LOGFONT lf = fLogFont;
1571
1572    HDC hdc = ::CreateCompatibleDC(NULL);
1573    HFONT font = CreateFontIndirect(&lf);
1574    HFONT savefont = (HFONT)SelectObject(hdc, font);
1575
1576    SkMemoryStream* stream = NULL;
1577    DWORD tables[2] = {kTTCTag, 0};
1578    for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) {
1579        size_t bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
1580        if (bufferSize == GDI_ERROR) {
1581            call_ensure_accessible(lf);
1582            bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0);
1583        }
1584        if (bufferSize != GDI_ERROR) {
1585            stream = new SkMemoryStream(bufferSize);
1586            if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(),
1587                            bufferSize)) {
1588                break;
1589            } else {
1590                delete stream;
1591                stream = NULL;
1592            }
1593        }
1594    }
1595
1596    SelectObject(hdc, savefont);
1597    DeleteObject(font);
1598    DeleteDC(hdc);
1599
1600    return stream;
1601}
1602
1603SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const {
1604    return SkNEW_ARGS(SkScalerContext_Windows, (const_cast<LogFontTypeface*>(this), desc));
1605}
1606
1607/** Return the closest matching typeface given either an existing family
1608 (specified by a typeface in that family) or by a familyName, and a
1609 requested style.
1610 1) If familyFace is null, use familyName.
1611 2) If familyName is null, use familyFace.
1612 3) If both are null, return the default font that best matches style
1613 This MUST not return NULL.
1614 */
1615
1616SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,
1617                                       const char familyName[],
1618                                       SkTypeface::Style style) {
1619    LOGFONT lf;
1620    if (NULL == familyFace && NULL == familyName) {
1621        lf = get_default_font();
1622    } else if (familyFace) {
1623        LogFontTypeface* face = (LogFontTypeface*)familyFace;
1624        lf = face->fLogFont;
1625    } else {
1626        logfont_for_name(familyName, &lf);
1627    }
1628    setStyle(&lf, style);
1629    return SkCreateTypefaceFromLOGFONT(lf);
1630}
1631
1632SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {
1633    SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path));
1634    return stream.get() ? CreateTypefaceFromStream(stream) : NULL;
1635}
1636
1637void LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const {
1638    unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag |
1639                                  SkScalerContext::kAutohinting_Flag |
1640                                  SkScalerContext::kEmbeddedBitmapText_Flag |
1641                                  SkScalerContext::kEmbolden_Flag |
1642                                  SkScalerContext::kSubpixelPositioning_Flag |
1643                                  SkScalerContext::kLCD_BGROrder_Flag |
1644                                  SkScalerContext::kLCD_Vertical_Flag;
1645    rec->fFlags &= ~flagsWeDontSupport;
1646
1647    SkPaint::Hinting h = rec->getHinting();
1648
1649    // I think we can support no-hinting, if we get hires outlines and just
1650    // use skia to rasterize into a gray-scale mask...
1651#if 0
1652    switch (h) {
1653        case SkPaint::kNo_Hinting:
1654        case SkPaint::kSlight_Hinting:
1655            h = SkPaint::kNo_Hinting;
1656            break;
1657        case SkPaint::kNormal_Hinting:
1658        case SkPaint::kFull_Hinting:
1659            h = SkPaint::kNormal_Hinting;
1660            break;
1661        default:
1662            SkDEBUGFAIL("unknown hinting");
1663    }
1664#else
1665    h = SkPaint::kNormal_Hinting;
1666#endif
1667    rec->setHinting(h);
1668
1669// turn this off since GDI might turn A8 into BW! Need a bigger fix.
1670#if 0
1671    // Disable LCD when rotated, since GDI's output is ugly
1672    if (isLCD(*rec) && !isAxisAligned(*rec)) {
1673        rec->fMaskFormat = SkMask::kA8_Format;
1674    }
1675#endif
1676
1677    if (!fCanBeLCD && isLCD(*rec)) {
1678        rec->fMaskFormat = SkMask::kA8_Format;
1679        rec->fFlags &= ~SkScalerContext::kGenA8FromLCD_Flag;
1680    }
1681}
1682
1683///////////////////////////////////////////////////////////////////////////////
1684
1685#include "SkFontMgr.h"
1686#include "SkDataTable.h"
1687
1688static bool valid_logfont_for_enum(const LOGFONT& lf, DWORD fontType) {
1689    return TRUETYPE_FONTTYPE == fontType
1690        && lf.lfFaceName[0]
1691        && lf.lfFaceName[0] != '@'
1692        && OUT_STROKE_PRECIS == lf.lfOutPrecision
1693        // without the chraset check, we got LOTS of dups of the same font
1694        // is there a better check (other than searching the array for
1695        // the same name?
1696        && 0 == lf.lfCharSet
1697        ;
1698}
1699
1700static int CALLBACK enum_fonts_proc(const LOGFONT* lf, const TEXTMETRIC*,
1701                                    DWORD fontType, LPARAM builderParam) {
1702    if (valid_logfont_for_enum(*lf, fontType)) {
1703        SkTDArray<LOGFONT>* array = (SkTDArray<LOGFONT>*)builderParam;
1704        *array->append() = *lf;
1705    }
1706    return 1; // non-zero means continue
1707}
1708
1709static SkFontStyle compute_fontstyle(const LOGFONT& lf) {
1710    return SkFontStyle(lf.lfWeight, SkFontStyle::kNormal_Width,
1711                       lf.lfItalic ? SkFontStyle::kItalic_Slant
1712                                   : SkFontStyle::kUpright_Slant);
1713}
1714
1715class SkFontStyleSetGDI : public SkFontStyleSet {
1716public:
1717    SkFontStyleSetGDI(const LOGFONT& lf) {
1718        HDC hdc = ::CreateCompatibleDC(NULL);
1719        ::EnumFonts(hdc, lf.lfFaceName, enum_fonts_proc, (LPARAM)&fArray);
1720        ::DeleteDC(hdc);
1721    }
1722
1723    virtual int count() SK_OVERRIDE {
1724        return fArray.count();
1725    }
1726
1727    virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE {
1728        if (fs) {
1729            *fs = compute_fontstyle(fArray[index]);
1730        }
1731        // todo: set the styleName
1732    }
1733
1734    virtual SkTypeface* createTypeface(int index) SK_OVERRIDE {
1735        return SkCreateTypefaceFromLOGFONT(fArray[index]);
1736    }
1737
1738    virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE {
1739        // todo:
1740        return SkCreateTypefaceFromLOGFONT(fArray[0]);
1741    }
1742
1743private:
1744    SkTDArray<LOGFONT> fArray;
1745};
1746
1747static int CALLBACK enum_family_proc(const LOGFONT* lf, const TEXTMETRIC* tm,
1748                                     DWORD fontType, LPARAM builderParam) {
1749    if (valid_logfont_for_enum(*lf, fontType)) {
1750        SkTDArray<LOGFONT>* array = (SkTDArray<LOGFONT>*)builderParam;
1751        *array->append() = *lf;
1752#if 0
1753        SkString str;
1754        tchar_to_skstring(lf->lfFaceName, &str);
1755        SkDebugf("fam:%s height:%d width:%d esc:%d orien:%d weight:%d ital:%d char:%d clip:%d qual:%d pitch:%d\n",
1756                 str.c_str(), lf->lfHeight, lf->lfWidth, lf->lfEscapement, lf->lfOrientation,
1757                 lf->lfWeight, lf->lfItalic, lf->lfCharSet, lf->lfClipPrecision, lf->lfQuality,
1758                 lf->lfPitchAndFamily);
1759#endif
1760    }
1761    return 1; // non-zero means continue
1762}
1763
1764class SkFontMgrGDI : public SkFontMgr {
1765    void init() {
1766        if (!fLogFontArray.isEmpty()) {
1767            return;
1768        }
1769
1770        LOGFONT lf;
1771        sk_bzero(&lf, sizeof(lf));
1772        lf.lfCharSet = DEFAULT_CHARSET;
1773
1774        HDC hdc = ::CreateCompatibleDC(NULL);
1775        ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fLogFontArray, 0);
1776        ::DeleteDC(hdc);
1777    }
1778
1779public:
1780    SkFontMgrGDI() {}
1781    virtual ~SkFontMgrGDI() {
1782    }
1783
1784protected:
1785    virtual int onCountFamilies() SK_OVERRIDE {
1786        this->init();
1787        return fLogFontArray.count();
1788    }
1789
1790    virtual void onGetFamilyName(int index, SkString* familyName) SK_OVERRIDE {
1791        this->init();
1792        SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
1793        tchar_to_skstring(fLogFontArray[index].lfFaceName, familyName);
1794    }
1795
1796    virtual SkFontStyleSet* onCreateStyleSet(int index) SK_OVERRIDE {
1797        this->init();
1798        SkASSERT((unsigned)index < (unsigned)fLogFontArray.count());
1799        return SkNEW_ARGS(SkFontStyleSetGDI, (fLogFontArray[index]));
1800    }
1801
1802    virtual SkFontStyleSet* onMatchFamily(const char familyName[]) SK_OVERRIDE {
1803        if (NULL == familyName) {
1804            familyName = "";    // do we need this check???
1805        }
1806        LOGFONT lf;
1807        logfont_for_name(familyName, &lf);
1808        return SkNEW_ARGS(SkFontStyleSetGDI, (lf));
1809    }
1810
1811    // this impl should be moved to base-class
1812    virtual SkTypeface* onMatchFamilyStyle(const char familyName[],
1813                                           const SkFontStyle& fontstyle) SK_OVERRIDE {
1814        SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName));
1815        return sset->matchStyle(fontstyle);
1816    }
1817
1818    virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember,
1819                                         const SkFontStyle& fontstyle) SK_OVERRIDE {
1820        SkString familyName;
1821        ((LogFontTypeface*)familyMember)->getFamilyName(&familyName);
1822        return this->matchFamilyStyle(familyName.c_str(), fontstyle);
1823    }
1824
1825    virtual SkTypeface* onCreateFromData(SkData*, int ttcIndex) SK_OVERRIDE {
1826        return NULL;
1827    }
1828    virtual SkTypeface* onCreateFromStream(SkStream*, int ttcIndex) SK_OVERRIDE {
1829        return NULL;
1830    }
1831    virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) SK_OVERRIDE {
1832        return NULL;
1833    }
1834
1835private:
1836    SkTDArray<LOGFONT> fLogFontArray;
1837};
1838
1839SkFontMgr* SkFontMgr::Factory() {
1840    return SkNEW(SkFontMgrGDI);
1841}
1842