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