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