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