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