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