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