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