gfx/skia/trunk/src/ports/SkFontHost_win.cpp

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

mercurial