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