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