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