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