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