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