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