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 40 void SkTypeface_SetEnsureLOGFONTAccessibleProc(void (*proc)(const LOGFONT&)) { 41 gEnsureLOGFONTAccessibleProc = proc; 42 } 43 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 60 static bool isLCD(const SkScalerContext::Rec& rec) { 61 return SkMask::kLCD16_Format == rec.fMaskFormat || 62 SkMask::kLCD32_Format == rec.fMaskFormat; 63 } 64 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 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 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 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 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 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 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 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 145 static inline FIXED SkFixedToFIXED(SkFixed x) { 146 return *(FIXED*)(&x); 147 } 148 static inline SkFixed SkFIXEDToFixed(FIXED x) { 149 return *(SkFixed*)(&x); 150 } 151 152 static inline FIXED SkScalarToFIXED(SkScalar x) { 153 return SkFixedToFIXED(SkScalarToFixed(x)); 154 } 155 156 static inline SkScalar SkFIXEDToScalar(FIXED x) { 157 return SkFixedToScalar(SkFIXEDToFixed(x)); 158 } 159 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 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: 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 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 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 void onGetFamilyName(SkString* familyName) const SK_OVERRIDE; 280 virtual SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const SK_OVERRIDE; 281 virtual int onGetTableTags(SkFontTableTag tags[]) const SK_OVERRIDE; 282 virtual size_t onGetTableData(SkFontTableTag, size_t offset, 283 size_t length, void* data) const SK_OVERRIDE; 284 }; 285 286 class FontMemResourceTypeface : public LogFontTypeface { 287 public: 288 /** 289 * The created FontMemResourceTypeface takes ownership of fontMemResource. 290 */ 291 static FontMemResourceTypeface* Create(const LOGFONT& lf, HANDLE fontMemResource) { 292 SkTypeface::Style style = get_style(lf); 293 SkFontID fontID = SkTypefaceCache::NewFontID(); 294 return new FontMemResourceTypeface(style, fontID, lf, fontMemResource); 295 } 296 297 protected: 298 virtual void weak_dispose() const SK_OVERRIDE { 299 RemoveFontMemResourceEx(fFontMemResource); 300 //SkTypefaceCache::Remove(this); 301 INHERITED::weak_dispose(); 302 } 303 304 private: 305 /** 306 * Takes ownership of fontMemResource. 307 */ 308 FontMemResourceTypeface(SkTypeface::Style style, SkFontID fontID, const LOGFONT& lf, HANDLE fontMemResource) : 309 LogFontTypeface(style, fontID, lf, true), fFontMemResource(fontMemResource) { 310 } 311 312 HANDLE fFontMemResource; 313 314 typedef LogFontTypeface INHERITED; 315 }; 316 317 static const LOGFONT& get_default_font() { 318 static LOGFONT gDefaultFont; 319 return gDefaultFont; 320 } 321 322 static bool FindByLogFont(SkTypeface* face, SkTypeface::Style requestedStyle, void* ctx) { 323 LogFontTypeface* lface = static_cast<LogFontTypeface*>(face); 324 const LOGFONT* lf = reinterpret_cast<const LOGFONT*>(ctx); 325 326 return lface && 327 get_style(lface->fLogFont) == requestedStyle && 328 !memcmp(&lface->fLogFont, lf, sizeof(LOGFONT)); 329 } 330 331 /** 332 * This guy is public. It first searches the cache, and if a match is not found, 333 * it creates a new face. 334 */ 335 SkTypeface* SkCreateTypefaceFromLOGFONT(const LOGFONT& origLF) { 336 LOGFONT lf = origLF; 337 make_canonical(&lf); 338 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(FindByLogFont, &lf); 339 if (NULL == face) { 340 face = LogFontTypeface::Create(lf); 341 SkTypefaceCache::Add(face, get_style(lf)); 342 } 343 return face; 344 } 345 346 /** 347 * The created SkTypeface takes ownership of fontMemResource. 348 */ 349 SkTypeface* SkCreateFontMemResourceTypefaceFromLOGFONT(const LOGFONT& origLF, HANDLE fontMemResource) { 350 LOGFONT lf = origLF; 351 make_canonical(&lf); 352 FontMemResourceTypeface* face = FontMemResourceTypeface::Create(lf, fontMemResource); 353 SkTypefaceCache::Add(face, get_style(lf), false); 354 return face; 355 } 356 357 /** 358 * This guy is public 359 */ 360 void SkLOGFONTFromTypeface(const SkTypeface* face, LOGFONT* lf) { 361 if (NULL == face) { 362 *lf = get_default_font(); 363 } else { 364 *lf = static_cast<const LogFontTypeface*>(face)->fLogFont; 365 } 366 } 367 368 // Construct Glyph to Unicode table. 369 // Unicode code points that require conjugate pairs in utf16 are not 370 // supported. 371 // TODO(arthurhsu): Add support for conjugate pairs. It looks like that may 372 // require parsing the TTF cmap table (platform 4, encoding 12) directly instead 373 // of calling GetFontUnicodeRange(). 374 static void populate_glyph_to_unicode(HDC fontHdc, const unsigned glyphCount, 375 SkTDArray<SkUnichar>* glyphToUnicode) { 376 DWORD glyphSetBufferSize = GetFontUnicodeRanges(fontHdc, NULL); 377 if (!glyphSetBufferSize) { 378 return; 379 } 380 381 SkAutoTDeleteArray<BYTE> glyphSetBuffer(new BYTE[glyphSetBufferSize]); 382 GLYPHSET* glyphSet = 383 reinterpret_cast<LPGLYPHSET>(glyphSetBuffer.get()); 384 if (GetFontUnicodeRanges(fontHdc, glyphSet) != glyphSetBufferSize) { 385 return; 386 } 387 388 glyphToUnicode->setCount(glyphCount); 389 memset(glyphToUnicode->begin(), 0, glyphCount * sizeof(SkUnichar)); 390 for (DWORD i = 0; i < glyphSet->cRanges; ++i) { 391 // There is no guarantee that within a Unicode range, the corresponding 392 // glyph id in a font file are continuous. So, even if we have ranges, 393 // we can't just use the first and last entry of the range to compute 394 // result. We need to enumerate them one by one. 395 int count = glyphSet->ranges[i].cGlyphs; 396 SkAutoTArray<WCHAR> chars(count + 1); 397 chars[count] = 0; // termintate string 398 SkAutoTArray<WORD> glyph(count); 399 for (USHORT j = 0; j < count; ++j) { 400 chars[j] = glyphSet->ranges[i].wcLow + j; 401 } 402 GetGlyphIndicesW(fontHdc, chars.get(), count, glyph.get(), 403 GGI_MARK_NONEXISTING_GLYPHS); 404 // If the glyph ID is valid, and the glyph is not mapped, then we will 405 // fill in the char id into the vector. If the glyph is mapped already, 406 // skip it. 407 // TODO(arthurhsu): better improve this. e.g. Get all used char ids from 408 // font cache, then generate this mapping table from there. It's 409 // unlikely to have collisions since glyph reuse happens mostly for 410 // different Unicode pages. 411 for (USHORT j = 0; j < count; ++j) { 412 if (glyph[j] != 0xffff && glyph[j] < glyphCount && 413 (*glyphToUnicode)[glyph[j]] == 0) { 414 (*glyphToUnicode)[glyph[j]] = chars[j]; 415 } 416 } 417 } 418 } 419 420 ////////////////////////////////////////////////////////////////////////////////////// 421 422 static int alignTo32(int n) { 423 return (n + 31) & ~31; 424 } 425 426 struct MyBitmapInfo : public BITMAPINFO { 427 RGBQUAD fMoreSpaceForColors[1]; 428 }; 429 430 class HDCOffscreen { 431 public: 432 HDCOffscreen() { 433 fFont = 0; 434 fDC = 0; 435 fBM = 0; 436 fBits = NULL; 437 fWidth = fHeight = 0; 438 fIsBW = false; 439 } 440 441 ~HDCOffscreen() { 442 if (fDC) { 443 DeleteDC(fDC); 444 } 445 if (fBM) { 446 DeleteObject(fBM); 447 } 448 } 449 450 void init(HFONT font, const XFORM& xform) { 451 fFont = font; 452 fXform = xform; 453 } 454 455 const void* draw(const SkGlyph&, bool isBW, size_t* srcRBPtr); 456 457 private: 458 HDC fDC; 459 HBITMAP fBM; 460 HFONT fFont; 461 XFORM fXform; 462 void* fBits; // points into fBM 463 int fWidth; 464 int fHeight; 465 bool fIsBW; 466 }; 467 468 const void* HDCOffscreen::draw(const SkGlyph& glyph, bool isBW, 469 size_t* srcRBPtr) { 470 // Can we share the scalercontext's fDDC, so we don't need to create 471 // a separate fDC here? 472 if (0 == fDC) { 473 fDC = CreateCompatibleDC(0); 474 if (0 == fDC) { 475 return NULL; 476 } 477 SetGraphicsMode(fDC, GM_ADVANCED); 478 SetBkMode(fDC, TRANSPARENT); 479 SetTextAlign(fDC, TA_LEFT | TA_BASELINE); 480 SelectObject(fDC, fFont); 481 482 COLORREF color = 0x00FFFFFF; 483 SkDEBUGCODE(COLORREF prev =) SetTextColor(fDC, color); 484 SkASSERT(prev != CLR_INVALID); 485 } 486 487 if (fBM && (fIsBW != isBW || fWidth < glyph.fWidth || fHeight < glyph.fHeight)) { 488 DeleteObject(fBM); 489 fBM = 0; 490 } 491 fIsBW = isBW; 492 493 fWidth = SkMax32(fWidth, glyph.fWidth); 494 fHeight = SkMax32(fHeight, glyph.fHeight); 495 496 int biWidth = isBW ? alignTo32(fWidth) : fWidth; 497 498 if (0 == fBM) { 499 MyBitmapInfo info; 500 sk_bzero(&info, sizeof(info)); 501 if (isBW) { 502 RGBQUAD blackQuad = { 0, 0, 0, 0 }; 503 RGBQUAD whiteQuad = { 0xFF, 0xFF, 0xFF, 0 }; 504 info.bmiColors[0] = blackQuad; 505 info.bmiColors[1] = whiteQuad; 506 } 507 info.bmiHeader.biSize = sizeof(info.bmiHeader); 508 info.bmiHeader.biWidth = biWidth; 509 info.bmiHeader.biHeight = fHeight; 510 info.bmiHeader.biPlanes = 1; 511 info.bmiHeader.biBitCount = isBW ? 1 : 32; 512 info.bmiHeader.biCompression = BI_RGB; 513 if (isBW) { 514 info.bmiHeader.biClrUsed = 2; 515 } 516 fBM = CreateDIBSection(fDC, &info, DIB_RGB_COLORS, &fBits, 0, 0); 517 if (0 == fBM) { 518 return NULL; 519 } 520 SelectObject(fDC, fBM); 521 } 522 523 // erase 524 size_t srcRB = isBW ? (biWidth >> 3) : (fWidth << 2); 525 size_t size = fHeight * srcRB; 526 memset(fBits, 0, size); 527 528 XFORM xform = fXform; 529 xform.eDx = (float)-glyph.fLeft; 530 xform.eDy = (float)-glyph.fTop; 531 SetWorldTransform(fDC, &xform); 532 533 uint16_t glyphID = glyph.getGlyphID(); 534 BOOL ret = ExtTextOutW(fDC, 0, 0, ETO_GLYPH_INDEX, NULL, reinterpret_cast<LPCWSTR>(&glyphID), 1, NULL); 535 GdiFlush(); 536 if (0 == ret) { 537 return NULL; 538 } 539 *srcRBPtr = srcRB; 540 // offset to the start of the image 541 return (const char*)fBits + (fHeight - glyph.fHeight) * srcRB; 542 } 543 544 ////////////////////////////////////////////////////////////////////////////// 545 #define BUFFERSIZE (1 << 13) 546 547 class SkScalerContext_GDI : public SkScalerContext { 548 public: 549 SkScalerContext_GDI(SkTypeface*, const SkDescriptor* desc); 550 virtual ~SkScalerContext_GDI(); 551 552 // Returns true if the constructor was able to complete all of its 553 // initializations (which may include calling GDI). 554 bool isValid() const; 555 556 protected: 557 virtual unsigned generateGlyphCount() SK_OVERRIDE; 558 virtual uint16_t generateCharToGlyph(SkUnichar uni) SK_OVERRIDE; 559 virtual void generateAdvance(SkGlyph* glyph) SK_OVERRIDE; 560 virtual void generateMetrics(SkGlyph* glyph) SK_OVERRIDE; 561 virtual void generateImage(const SkGlyph& glyph) SK_OVERRIDE; 562 virtual void generatePath(const SkGlyph& glyph, SkPath* path) SK_OVERRIDE; 563 virtual void generateFontMetrics(SkPaint::FontMetrics*) 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 596 static FIXED float2FIXED(float x) { 597 return SkFixedToFIXED(SkFloatToFixed(x)); 598 } 599 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 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 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 796 bool SkScalerContext_GDI::isValid() const { 797 return fDDC && fFont; 798 } 799 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 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 868 void SkScalerContext_GDI::generateAdvance(SkGlyph* glyph) { 869 this->generateMetrics(glyph); 870 } 871 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(); 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(); 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}}; 981 void SkScalerContext_GDI::generateFontMetrics(SkPaint::FontMetrics* metrics) { 982 if (NULL == metrics) { 983 return; 984 } 985 sk_bzero(metrics, sizeof(*metrics)); 986 987 SkASSERT(fDDC); 988 989 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS 990 if (fType == SkScalerContext_GDI::kBitmap_Type || fType == SkScalerContext_GDI::kLine_Type) { 991 #endif 992 metrics->fTop = SkIntToScalar(-fTM.tmAscent); 993 metrics->fAscent = SkIntToScalar(-fTM.tmAscent); 994 metrics->fDescent = SkIntToScalar(fTM.tmDescent); 995 metrics->fBottom = SkIntToScalar(fTM.tmDescent); 996 metrics->fLeading = SkIntToScalar(fTM.tmExternalLeading); 997 metrics->fAvgCharWidth = SkIntToScalar(fTM.tmAveCharWidth); 998 metrics->fMaxCharWidth = SkIntToScalar(fTM.tmMaxCharWidth); 999 metrics->fXMin = 0; 1000 metrics->fXMax = metrics->fMaxCharWidth; 1001 //metrics->fXHeight = 0; 1002 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS 1003 return; 1004 } 1005 #endif 1006 1007 OUTLINETEXTMETRIC otm; 1008 1009 uint32_t ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm); 1010 if (0 == ret) { 1011 LogFontTypeface::EnsureAccessible(this->getTypeface()); 1012 ret = GetOutlineTextMetrics(fDDC, sizeof(otm), &otm); 1013 } 1014 if (0 == ret) { 1015 return; 1016 } 1017 1018 #ifndef SK_GDI_ALWAYS_USE_TEXTMETRICS_FOR_FONT_METRICS 1019 metrics->fTop = SkIntToScalar(-otm.otmrcFontBox.top); 1020 metrics->fAscent = SkIntToScalar(-otm.otmAscent); 1021 metrics->fDescent = SkIntToScalar(-otm.otmDescent); 1022 metrics->fBottom = SkIntToScalar(-otm.otmrcFontBox.bottom); 1023 metrics->fLeading = SkIntToScalar(otm.otmLineGap); 1024 metrics->fAvgCharWidth = SkIntToScalar(otm.otmTextMetrics.tmAveCharWidth); 1025 metrics->fMaxCharWidth = SkIntToScalar(otm.otmTextMetrics.tmMaxCharWidth); 1026 metrics->fXMin = SkIntToScalar(otm.otmrcFontBox.left); 1027 metrics->fXMax = SkIntToScalar(otm.otmrcFontBox.right); 1028 #endif 1029 metrics->fUnderlineThickness = SkIntToScalar(otm.otmsUnderscoreSize); 1030 metrics->fUnderlinePosition = -SkIntToScalar(otm.otmsUnderscorePosition); 1031 1032 metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1033 metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1034 1035 metrics->fXHeight = SkIntToScalar(otm.otmsXHeight); 1036 GLYPHMETRICS gm; 1037 sk_bzero(&gm, sizeof(gm)); 1038 DWORD len = GetGlyphOutlineW(fDDC, 'x', GGO_METRICS, &gm, 0, 0, &gMat2Identity); 1039 if (len != GDI_ERROR && gm.gmBlackBoxY > 0) { 1040 metrics->fXHeight = SkIntToScalar(gm.gmBlackBoxY); 1041 } 1042 } 1043 1044 //////////////////////////////////////////////////////////////////////////////////////// 1045 1046 #define SK_SHOW_TEXT_BLIT_COVERAGE 0 1047 1048 static void build_power_table(uint8_t table[], float ee) { 1049 for (int i = 0; i < 256; i++) { 1050 float x = i / 255.f; 1051 x = sk_float_pow(x, ee); 1052 int xx = SkScalarRoundToInt(x * 255); 1053 table[i] = SkToU8(xx); 1054 } 1055 } 1056 1057 /** 1058 * This will invert the gamma applied by GDI (gray-scale antialiased), so we 1059 * can get linear values. 1060 * 1061 * GDI grayscale appears to use a hard-coded gamma of 2.3. 1062 * 1063 * GDI grayscale appears to draw using the black and white rasterizer at four 1064 * times the size and then downsamples to compute the coverage mask. As a 1065 * result there are only seventeen total grays. This lack of fidelity means 1066 * that shifting into other color spaces is imprecise. 1067 */ 1068 static const uint8_t* getInverseGammaTableGDI() { 1069 // Since build_power_table is idempotent, many threads can build gTableGdi 1070 // simultaneously. 1071 1072 // Microsoft Specific: 1073 // Making gInited volatile provides read-aquire and write-release in vc++. 1074 // In VS2012, see compiler option /volatile:(ms|iso). 1075 // Replace with C++11 atomics when possible. 1076 static volatile bool gInited; 1077 static uint8_t gTableGdi[256]; 1078 if (gInited) { 1079 // Need a L/L (read) barrier (full acquire not needed). If gInited is observed 1080 // true then gTableGdi is observable, but it must be requested. 1081 } else { 1082 build_power_table(gTableGdi, 2.3f); 1083 // Need a S/S (write) barrier (full release not needed) here so that this 1084 // write to gInited becomes observable after gTableGdi. 1085 gInited = true; 1086 } 1087 return gTableGdi; 1088 } 1089 1090 /** 1091 * This will invert the gamma applied by GDI ClearType, so we can get linear 1092 * values. 1093 * 1094 * GDI ClearType uses SPI_GETFONTSMOOTHINGCONTRAST / 1000 as the gamma value. 1095 * If this value is not specified, the default is a gamma of 1.4. 1096 */ 1097 static const uint8_t* getInverseGammaTableClearType() { 1098 // We don't expect SPI_GETFONTSMOOTHINGCONTRAST to ever change, so building 1099 // gTableClearType with build_power_table is effectively idempotent. 1100 1101 // Microsoft Specific: 1102 // Making gInited volatile provides read-aquire and write-release in vc++. 1103 // In VS2012, see compiler option /volatile:(ms|iso). 1104 // Replace with C++11 atomics when possible. 1105 static volatile bool gInited; 1106 static uint8_t gTableClearType[256]; 1107 if (gInited) { 1108 // Need a L/L (read) barrier (acquire not needed). If gInited is observed 1109 // true then gTableClearType is observable, but it must be requested. 1110 } else { 1111 UINT level = 0; 1112 if (!SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &level, 0) || !level) { 1113 // can't get the data, so use a default 1114 level = 1400; 1115 } 1116 build_power_table(gTableClearType, level / 1000.0f); 1117 // Need a S/S (write) barrier (release not needed) here so that this 1118 // write to gInited becomes observable after gTableClearType. 1119 gInited = true; 1120 } 1121 return gTableClearType; 1122 } 1123 1124 #include "SkColorPriv.h" 1125 1126 //Cannot assume that the input rgb is gray due to possible setting of kGenA8FromLCD_Flag. 1127 template<bool APPLY_PREBLEND> 1128 static inline uint8_t rgb_to_a8(SkGdiRGB rgb, const uint8_t* table8) { 1129 U8CPU r = (rgb >> 16) & 0xFF; 1130 U8CPU g = (rgb >> 8) & 0xFF; 1131 U8CPU b = (rgb >> 0) & 0xFF; 1132 return sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8); 1133 } 1134 1135 template<bool APPLY_PREBLEND> 1136 static inline uint16_t rgb_to_lcd16(SkGdiRGB rgb, const uint8_t* tableR, 1137 const uint8_t* tableG, 1138 const uint8_t* tableB) { 1139 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR); 1140 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 8) & 0xFF, tableG); 1141 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 0) & 0xFF, tableB); 1142 #if SK_SHOW_TEXT_BLIT_COVERAGE 1143 r = SkMax32(r, 10); g = SkMax32(g, 10); b = SkMax32(b, 10); 1144 #endif 1145 return SkPack888ToRGB16(r, g, b); 1146 } 1147 1148 template<bool APPLY_PREBLEND> 1149 static inline SkPMColor rgb_to_lcd32(SkGdiRGB rgb, const uint8_t* tableR, 1150 const uint8_t* tableG, 1151 const uint8_t* tableB) { 1152 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 16) & 0xFF, tableR); 1153 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 8) & 0xFF, tableG); 1154 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>((rgb >> 0) & 0xFF, tableB); 1155 #if SK_SHOW_TEXT_BLIT_COVERAGE 1156 r = SkMax32(r, 10); g = SkMax32(g, 10); b = SkMax32(b, 10); 1157 #endif 1158 return SkPackARGB32(0xFF, r, g, b); 1159 } 1160 1161 // Is this GDI color neither black nor white? If so, we have to keep this 1162 // image as is, rather than smashing it down to a BW mask. 1163 // 1164 // returns int instead of bool, since we don't want/have to pay to convert 1165 // the zero/non-zero value into a bool 1166 static int is_not_black_or_white(SkGdiRGB c) { 1167 // same as (but faster than) 1168 // c &= 0x00FFFFFF; 1169 // return 0 == c || 0x00FFFFFF == c; 1170 return (c + (c & 1)) & 0x00FFFFFF; 1171 } 1172 1173 static bool is_rgb_really_bw(const SkGdiRGB* src, int width, int height, size_t srcRB) { 1174 for (int y = 0; y < height; ++y) { 1175 for (int x = 0; x < width; ++x) { 1176 if (is_not_black_or_white(src[x])) { 1177 return false; 1178 } 1179 } 1180 src = SkTAddOffset<const SkGdiRGB>(src, srcRB); 1181 } 1182 return true; 1183 } 1184 1185 // gdi's bitmap is upside-down, so we reverse dst walking in Y 1186 // whenever we copy it into skia's buffer 1187 static void rgb_to_bw(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, 1188 const SkGlyph& glyph) { 1189 const int width = glyph.fWidth; 1190 const size_t dstRB = (width + 7) >> 3; 1191 uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 1192 1193 int byteCount = width >> 3; 1194 int bitCount = width & 7; 1195 1196 // adjust srcRB to skip the values in our byteCount loop, 1197 // since we increment src locally there 1198 srcRB -= byteCount * 8 * sizeof(SkGdiRGB); 1199 1200 for (int y = 0; y < glyph.fHeight; ++y) { 1201 if (byteCount > 0) { 1202 for (int i = 0; i < byteCount; ++i) { 1203 unsigned byte = 0; 1204 byte |= src[0] & (1 << 7); 1205 byte |= src[1] & (1 << 6); 1206 byte |= src[2] & (1 << 5); 1207 byte |= src[3] & (1 << 4); 1208 byte |= src[4] & (1 << 3); 1209 byte |= src[5] & (1 << 2); 1210 byte |= src[6] & (1 << 1); 1211 byte |= src[7] & (1 << 0); 1212 dst[i] = byte; 1213 src += 8; 1214 } 1215 } 1216 if (bitCount > 0) { 1217 unsigned byte = 0; 1218 unsigned mask = 0x80; 1219 for (int i = 0; i < bitCount; i++) { 1220 byte |= src[i] & mask; 1221 mask >>= 1; 1222 } 1223 dst[byteCount] = byte; 1224 } 1225 src = SkTAddOffset<const SkGdiRGB>(src, srcRB); 1226 dst -= dstRB; 1227 } 1228 #if SK_SHOW_TEXT_BLIT_COVERAGE 1229 if (glyph.fWidth > 0 && glyph.fHeight > 0) { 1230 uint8_t* first = (uint8_t*)glyph.fImage; 1231 uint8_t* last = (uint8_t*)((char*)glyph.fImage + glyph.fHeight * dstRB - 1); 1232 *first |= 1 << 7; 1233 *last |= bitCount == 0 ? 1 : 1 << (8 - bitCount); 1234 } 1235 #endif 1236 } 1237 1238 template<bool APPLY_PREBLEND> 1239 static void rgb_to_a8(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, 1240 const SkGlyph& glyph, const uint8_t* table8) { 1241 const size_t dstRB = glyph.rowBytes(); 1242 const int width = glyph.fWidth; 1243 uint8_t* SK_RESTRICT dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 1244 1245 for (int y = 0; y < glyph.fHeight; y++) { 1246 for (int i = 0; i < width; i++) { 1247 dst[i] = rgb_to_a8<APPLY_PREBLEND>(src[i], table8); 1248 #if SK_SHOW_TEXT_BLIT_COVERAGE 1249 dst[i] = SkMax32(dst[i], 10); 1250 #endif 1251 } 1252 src = SkTAddOffset<const SkGdiRGB>(src, srcRB); 1253 dst -= dstRB; 1254 } 1255 } 1256 1257 template<bool APPLY_PREBLEND> 1258 static void rgb_to_lcd16(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph, 1259 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 1260 const size_t dstRB = glyph.rowBytes(); 1261 const int width = glyph.fWidth; 1262 uint16_t* SK_RESTRICT dst = (uint16_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 1263 1264 for (int y = 0; y < glyph.fHeight; y++) { 1265 for (int i = 0; i < width; i++) { 1266 dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(src[i], tableR, tableG, tableB); 1267 } 1268 src = SkTAddOffset<const SkGdiRGB>(src, srcRB); 1269 dst = (uint16_t*)((char*)dst - dstRB); 1270 } 1271 } 1272 1273 template<bool APPLY_PREBLEND> 1274 static void rgb_to_lcd32(const SkGdiRGB* SK_RESTRICT src, size_t srcRB, const SkGlyph& glyph, 1275 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 1276 const size_t dstRB = glyph.rowBytes(); 1277 const int width = glyph.fWidth; 1278 uint32_t* SK_RESTRICT dst = (uint32_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 1279 1280 for (int y = 0; y < glyph.fHeight; y++) { 1281 for (int i = 0; i < width; i++) { 1282 dst[i] = rgb_to_lcd32<APPLY_PREBLEND>(src[i], tableR, tableG, tableB); 1283 } 1284 src = SkTAddOffset<const SkGdiRGB>(src, srcRB); 1285 dst = (uint32_t*)((char*)dst - dstRB); 1286 } 1287 } 1288 1289 static inline unsigned clamp255(unsigned x) { 1290 SkASSERT(x <= 256); 1291 return x - (x >> 8); 1292 } 1293 1294 void SkScalerContext_GDI::generateImage(const SkGlyph& glyph) { 1295 SkASSERT(fDDC); 1296 1297 const bool isBW = SkMask::kBW_Format == fRec.fMaskFormat; 1298 const bool isAA = !isLCD(fRec); 1299 1300 size_t srcRB; 1301 const void* bits = fOffscreen.draw(glyph, isBW, &srcRB); 1302 if (NULL == bits) { 1303 LogFontTypeface::EnsureAccessible(this->getTypeface()); 1304 bits = fOffscreen.draw(glyph, isBW, &srcRB); 1305 if (NULL == bits) { 1306 sk_bzero(glyph.fImage, glyph.computeImageSize()); 1307 return; 1308 } 1309 } 1310 1311 if (!isBW) { 1312 const uint8_t* table; 1313 //The offscreen contains a GDI blit if isAA and kGenA8FromLCD_Flag is not set. 1314 //Otherwise the offscreen contains a ClearType blit. 1315 if (isAA && !(fRec.fFlags & SkScalerContext::kGenA8FromLCD_Flag)) { 1316 table = getInverseGammaTableGDI(); 1317 } else { 1318 table = getInverseGammaTableClearType(); 1319 } 1320 //Note that the following cannot really be integrated into the 1321 //pre-blend, since we may not be applying the pre-blend; when we aren't 1322 //applying the pre-blend it means that a filter wants linear anyway. 1323 //Other code may also be applying the pre-blend, so we'd need another 1324 //one with this and one without. 1325 SkGdiRGB* addr = (SkGdiRGB*)bits; 1326 for (int y = 0; y < glyph.fHeight; ++y) { 1327 for (int x = 0; x < glyph.fWidth; ++x) { 1328 int r = (addr[x] >> 16) & 0xFF; 1329 int g = (addr[x] >> 8) & 0xFF; 1330 int b = (addr[x] >> 0) & 0xFF; 1331 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b]; 1332 } 1333 addr = SkTAddOffset<SkGdiRGB>(addr, srcRB); 1334 } 1335 } 1336 1337 int width = glyph.fWidth; 1338 size_t dstRB = glyph.rowBytes(); 1339 if (isBW) { 1340 const uint8_t* src = (const uint8_t*)bits; 1341 uint8_t* dst = (uint8_t*)((char*)glyph.fImage + (glyph.fHeight - 1) * dstRB); 1342 for (int y = 0; y < glyph.fHeight; y++) { 1343 memcpy(dst, src, dstRB); 1344 src += srcRB; 1345 dst -= dstRB; 1346 } 1347 #if SK_SHOW_TEXT_BLIT_COVERAGE 1348 if (glyph.fWidth > 0 && glyph.fHeight > 0) { 1349 int bitCount = width & 7; 1350 uint8_t* first = (uint8_t*)glyph.fImage; 1351 uint8_t* last = (uint8_t*)((char*)glyph.fImage + glyph.fHeight * dstRB - 1); 1352 *first |= 1 << 7; 1353 *last |= bitCount == 0 ? 1 : 1 << (8 - bitCount); 1354 } 1355 #endif 1356 } else if (isAA) { 1357 // since the caller may require A8 for maskfilters, we can't check for BW 1358 // ... until we have the caller tell us that explicitly 1359 const SkGdiRGB* src = (const SkGdiRGB*)bits; 1360 if (fPreBlend.isApplicable()) { 1361 rgb_to_a8<true>(src, srcRB, glyph, fPreBlend.fG); 1362 } else { 1363 rgb_to_a8<false>(src, srcRB, glyph, fPreBlend.fG); 1364 } 1365 } else { // LCD16 1366 const SkGdiRGB* src = (const SkGdiRGB*)bits; 1367 if (is_rgb_really_bw(src, width, glyph.fHeight, srcRB)) { 1368 rgb_to_bw(src, srcRB, glyph); 1369 ((SkGlyph*)&glyph)->fMaskFormat = SkMask::kBW_Format; 1370 } else { 1371 if (SkMask::kLCD16_Format == glyph.fMaskFormat) { 1372 if (fPreBlend.isApplicable()) { 1373 rgb_to_lcd16<true>(src, srcRB, glyph, 1374 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1375 } else { 1376 rgb_to_lcd16<false>(src, srcRB, glyph, 1377 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1378 } 1379 } else { 1380 SkASSERT(SkMask::kLCD32_Format == glyph.fMaskFormat); 1381 if (fPreBlend.isApplicable()) { 1382 rgb_to_lcd32<true>(src, srcRB, glyph, 1383 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1384 } else { 1385 rgb_to_lcd32<false>(src, srcRB, glyph, 1386 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1387 } 1388 } 1389 } 1390 } 1391 } 1392 1393 class GDIGlyphbufferPointIter { 1394 public: 1395 GDIGlyphbufferPointIter(const uint8_t* glyphbuf, DWORD total_size) 1396 : fHeaderIter(glyphbuf, total_size), fCurveIter(), fPointIter() 1397 { } 1398 1399 POINTFX const * next() { 1400 nextHeader: 1401 if (!fCurveIter.isSet()) { 1402 const TTPOLYGONHEADER* header = fHeaderIter.next(); 1403 if (NULL == header) { 1404 return NULL; 1405 } 1406 fCurveIter.set(header); 1407 const TTPOLYCURVE* curve = fCurveIter.next(); 1408 if (NULL == curve) { 1409 return NULL; 1410 } 1411 fPointIter.set(curve); 1412 return &header->pfxStart; 1413 } 1414 1415 const POINTFX* nextPoint = fPointIter.next(); 1416 if (NULL == nextPoint) { 1417 const TTPOLYCURVE* curve = fCurveIter.next(); 1418 if (NULL == curve) { 1419 fCurveIter.set(); 1420 goto nextHeader; 1421 } else { 1422 fPointIter.set(curve); 1423 } 1424 nextPoint = fPointIter.next(); 1425 } 1426 return nextPoint; 1427 } 1428 1429 WORD currentCurveType() { 1430 return fPointIter.fCurveType; 1431 } 1432 1433 private: 1434 /** Iterates over all of the polygon headers in a glyphbuf. */ 1435 class GDIPolygonHeaderIter { 1436 public: 1437 GDIPolygonHeaderIter(const uint8_t* glyphbuf, DWORD total_size) 1438 : fCurPolygon(reinterpret_cast<const TTPOLYGONHEADER*>(glyphbuf)) 1439 , fEndPolygon(SkTAddOffset<const TTPOLYGONHEADER>(glyphbuf, total_size)) 1440 { } 1441 1442 const TTPOLYGONHEADER* next() { 1443 if (fCurPolygon >= fEndPolygon) { 1444 return NULL; 1445 } 1446 const TTPOLYGONHEADER* thisPolygon = fCurPolygon; 1447 fCurPolygon = SkTAddOffset<const TTPOLYGONHEADER>(fCurPolygon, fCurPolygon->cb); 1448 return thisPolygon; 1449 } 1450 private: 1451 const TTPOLYGONHEADER* fCurPolygon; 1452 const TTPOLYGONHEADER* fEndPolygon; 1453 }; 1454 1455 /** Iterates over all of the polygon curves in a polygon header. */ 1456 class GDIPolygonCurveIter { 1457 public: 1458 GDIPolygonCurveIter() : fCurCurve(NULL), fEndCurve(NULL) { } 1459 1460 GDIPolygonCurveIter(const TTPOLYGONHEADER* curPolygon) 1461 : fCurCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOLYGONHEADER))) 1462 , fEndCurve(SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->cb)) 1463 { } 1464 1465 bool isSet() { return fCurCurve != NULL; } 1466 1467 void set(const TTPOLYGONHEADER* curPolygon) { 1468 fCurCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, sizeof(TTPOLYGONHEADER)); 1469 fEndCurve = SkTAddOffset<const TTPOLYCURVE>(curPolygon, curPolygon->cb); 1470 } 1471 void set() { 1472 fCurCurve = NULL; 1473 fEndCurve = NULL; 1474 } 1475 1476 const TTPOLYCURVE* next() { 1477 if (fCurCurve >= fEndCurve) { 1478 return NULL; 1479 } 1480 const TTPOLYCURVE* thisCurve = fCurCurve; 1481 fCurCurve = SkTAddOffset<const TTPOLYCURVE>(fCurCurve, size_of_TTPOLYCURVE(*fCurCurve)); 1482 return thisCurve; 1483 } 1484 private: 1485 size_t size_of_TTPOLYCURVE(const TTPOLYCURVE& curve) { 1486 return 2*sizeof(WORD) + curve.cpfx*sizeof(POINTFX); 1487 } 1488 const TTPOLYCURVE* fCurCurve; 1489 const TTPOLYCURVE* fEndCurve; 1490 }; 1491 1492 /** Iterates over all of the polygon points in a polygon curve. */ 1493 class GDIPolygonCurvePointIter { 1494 public: 1495 GDIPolygonCurvePointIter() : fCurveType(0), fCurPoint(NULL), fEndPoint(NULL) { } 1496 1497 GDIPolygonCurvePointIter(const TTPOLYCURVE* curPolygon) 1498 : fCurveType(curPolygon->wType) 1499 , fCurPoint(&curPolygon->apfx[0]) 1500 , fEndPoint(&curPolygon->apfx[curPolygon->cpfx]) 1501 { } 1502 1503 bool isSet() { return fCurPoint != NULL; } 1504 1505 void set(const TTPOLYCURVE* curPolygon) { 1506 fCurveType = curPolygon->wType; 1507 fCurPoint = &curPolygon->apfx[0]; 1508 fEndPoint = &curPolygon->apfx[curPolygon->cpfx]; 1509 } 1510 void set() { 1511 fCurPoint = NULL; 1512 fEndPoint = NULL; 1513 } 1514 1515 const POINTFX* next() { 1516 if (fCurPoint >= fEndPoint) { 1517 return NULL; 1518 } 1519 const POINTFX* thisPoint = fCurPoint; 1520 ++fCurPoint; 1521 return thisPoint; 1522 } 1523 1524 WORD fCurveType; 1525 private: 1526 const POINTFX* fCurPoint; 1527 const POINTFX* fEndPoint; 1528 }; 1529 1530 GDIPolygonHeaderIter fHeaderIter; 1531 GDIPolygonCurveIter fCurveIter; 1532 GDIPolygonCurvePointIter fPointIter; 1533 }; 1534 1535 static void sk_path_from_gdi_path(SkPath* path, const uint8_t* glyphbuf, DWORD total_size) { 1536 const uint8_t* cur_glyph = glyphbuf; 1537 const uint8_t* end_glyph = glyphbuf + total_size; 1538 1539 while (cur_glyph < end_glyph) { 1540 const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph; 1541 1542 const uint8_t* end_poly = cur_glyph + th->cb; 1543 const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER); 1544 1545 path->moveTo(SkFixedToScalar( SkFIXEDToFixed(th->pfxStart.x)), 1546 SkFixedToScalar(-SkFIXEDToFixed(th->pfxStart.y))); 1547 1548 while (cur_poly < end_poly) { 1549 const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly; 1550 1551 if (pc->wType == TT_PRIM_LINE) { 1552 for (uint16_t i = 0; i < pc->cpfx; i++) { 1553 path->lineTo(SkFixedToScalar( SkFIXEDToFixed(pc->apfx[i].x)), 1554 SkFixedToScalar(-SkFIXEDToFixed(pc->apfx[i].y))); 1555 } 1556 } 1557 1558 if (pc->wType == TT_PRIM_QSPLINE) { 1559 for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline 1560 POINTFX pnt_b = pc->apfx[u]; // B is always the current point 1561 POINTFX pnt_c = pc->apfx[u+1]; 1562 1563 if (u < pc->cpfx - 2) { // If not on last spline, compute C 1564 pnt_c.x = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.x), 1565 SkFIXEDToFixed(pnt_c.x))); 1566 pnt_c.y = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.y), 1567 SkFIXEDToFixed(pnt_c.y))); 1568 } 1569 1570 path->quadTo(SkFixedToScalar( SkFIXEDToFixed(pnt_b.x)), 1571 SkFixedToScalar(-SkFIXEDToFixed(pnt_b.y)), 1572 SkFixedToScalar( SkFIXEDToFixed(pnt_c.x)), 1573 SkFixedToScalar(-SkFIXEDToFixed(pnt_c.y))); 1574 } 1575 } 1576 // Advance past this TTPOLYCURVE. 1577 cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx; 1578 } 1579 cur_glyph += th->cb; 1580 path->close(); 1581 } 1582 } 1583 1584 #define move_next_expected_hinted_point(iter, pElem) do {\ 1585 pElem = iter.next(); \ 1586 if (NULL == pElem) return false; \ 1587 } while(0) 1588 1589 // It is possible for the hinted and unhinted versions of the same path to have 1590 // a different number of points due to GDI's handling of flipped points. 1591 // If this is detected, this will return false. 1592 static bool sk_path_from_gdi_paths(SkPath* path, const uint8_t* glyphbuf, DWORD total_size, 1593 GDIGlyphbufferPointIter hintedYs) { 1594 const uint8_t* cur_glyph = glyphbuf; 1595 const uint8_t* end_glyph = glyphbuf + total_size; 1596 1597 POINTFX const * hintedPoint; 1598 1599 while (cur_glyph < end_glyph) { 1600 const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph; 1601 1602 const uint8_t* end_poly = cur_glyph + th->cb; 1603 const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER); 1604 1605 move_next_expected_hinted_point(hintedYs, hintedPoint); 1606 path->moveTo(SkFixedToScalar( SkFIXEDToFixed(th->pfxStart.x)), 1607 SkFixedToScalar(-SkFIXEDToFixed(hintedPoint->y))); 1608 1609 while (cur_poly < end_poly) { 1610 const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly; 1611 1612 if (pc->wType == TT_PRIM_LINE) { 1613 for (uint16_t i = 0; i < pc->cpfx; i++) { 1614 move_next_expected_hinted_point(hintedYs, hintedPoint); 1615 path->lineTo(SkFixedToScalar( SkFIXEDToFixed(pc->apfx[i].x)), 1616 SkFixedToScalar(-SkFIXEDToFixed(hintedPoint->y))); 1617 } 1618 } 1619 1620 if (pc->wType == TT_PRIM_QSPLINE) { 1621 POINTFX currentPoint = pc->apfx[0]; 1622 move_next_expected_hinted_point(hintedYs, hintedPoint); 1623 // only take the hinted y if it wasn't flipped 1624 if (hintedYs.currentCurveType() == TT_PRIM_QSPLINE) { 1625 currentPoint.y = hintedPoint->y; 1626 } 1627 for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline 1628 POINTFX pnt_b = currentPoint;//pc->apfx[u]; // B is always the current point 1629 POINTFX pnt_c = pc->apfx[u+1]; 1630 move_next_expected_hinted_point(hintedYs, hintedPoint); 1631 // only take the hinted y if it wasn't flipped 1632 if (hintedYs.currentCurveType() == TT_PRIM_QSPLINE) { 1633 pnt_c.y = hintedPoint->y; 1634 } 1635 currentPoint.x = pnt_c.x; 1636 currentPoint.y = pnt_c.y; 1637 1638 if (u < pc->cpfx - 2) { // If not on last spline, compute C 1639 pnt_c.x = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.x), 1640 SkFIXEDToFixed(pnt_c.x))); 1641 pnt_c.y = SkFixedToFIXED(SkFixedAve(SkFIXEDToFixed(pnt_b.y), 1642 SkFIXEDToFixed(pnt_c.y))); 1643 } 1644 1645 path->quadTo(SkFixedToScalar( SkFIXEDToFixed(pnt_b.x)), 1646 SkFixedToScalar(-SkFIXEDToFixed(pnt_b.y)), 1647 SkFixedToScalar( SkFIXEDToFixed(pnt_c.x)), 1648 SkFixedToScalar(-SkFIXEDToFixed(pnt_c.y))); 1649 } 1650 } 1651 // Advance past this TTPOLYCURVE. 1652 cur_poly += sizeof(WORD) * 2 + sizeof(POINTFX) * pc->cpfx; 1653 } 1654 cur_glyph += th->cb; 1655 path->close(); 1656 } 1657 return true; 1658 } 1659 1660 DWORD SkScalerContext_GDI::getGDIGlyphPath(const SkGlyph& glyph, UINT flags, 1661 SkAutoSTMalloc<BUFFERSIZE, uint8_t>* glyphbuf) 1662 { 1663 GLYPHMETRICS gm; 1664 1665 DWORD total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, BUFFERSIZE, glyphbuf->get(), &fMat22); 1666 // Sometimes GetGlyphOutlineW returns a number larger than BUFFERSIZE even if BUFFERSIZE > 0. 1667 // It has been verified that this does not involve a buffer overrun. 1668 if (GDI_ERROR == total_size || total_size > BUFFERSIZE) { 1669 // GDI_ERROR because the BUFFERSIZE was too small, or because the data was not accessible. 1670 // When the data is not accessable GetGlyphOutlineW fails rather quickly, 1671 // so just try to get the size. If that fails then ensure the data is accessible. 1672 total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22); 1673 if (GDI_ERROR == total_size) { 1674 LogFontTypeface::EnsureAccessible(this->getTypeface()); 1675 total_size = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, 0, NULL, &fMat22); 1676 if (GDI_ERROR == total_size) { 1677 // GetGlyphOutlineW is known to fail for some characters, such as spaces. 1678 // In these cases, just return that the glyph does not have a shape. 1679 return 0; 1680 } 1681 } 1682 1683 glyphbuf->reset(total_size); 1684 1685 DWORD ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyphbuf->get(), &fMat22); 1686 if (GDI_ERROR == ret) { 1687 LogFontTypeface::EnsureAccessible(this->getTypeface()); 1688 ret = GetGlyphOutlineW(fDDC, glyph.fID, flags, &gm, total_size, glyphbuf->get(), &fMat22); 1689 if (GDI_ERROR == ret) { 1690 SkASSERT(false); 1691 return 0; 1692 } 1693 } 1694 } 1695 return total_size; 1696 } 1697 1698 void SkScalerContext_GDI::generatePath(const SkGlyph& glyph, SkPath* path) { 1699 SkASSERT(&glyph && path); 1700 SkASSERT(fDDC); 1701 1702 path->reset(); 1703 1704 // Out of all the fonts on a typical Windows box, 1705 // 25% of glyphs require more than 2KB. 1706 // 1% of glyphs require more than 4KB. 1707 // 0.01% of glyphs require more than 8KB. 1708 // 8KB is less than 1% of the normal 1MB stack on Windows. 1709 // Note that some web fonts glyphs require more than 20KB. 1710 //static const DWORD BUFFERSIZE = (1 << 13); 1711 1712 //GDI only uses hinted outlines when axis aligned. 1713 UINT format = GGO_NATIVE | GGO_GLYPH_INDEX; 1714 if (fRec.getHinting() == SkPaint::kNo_Hinting || fRec.getHinting() == SkPaint::kSlight_Hinting){ 1715 format |= GGO_UNHINTED; 1716 } 1717 SkAutoSTMalloc<BUFFERSIZE, uint8_t> glyphbuf(BUFFERSIZE); 1718 DWORD total_size = getGDIGlyphPath(glyph, format, &glyphbuf); 1719 if (0 == total_size) { 1720 return; 1721 } 1722 1723 if (fRec.getHinting() != SkPaint::kSlight_Hinting) { 1724 sk_path_from_gdi_path(path, glyphbuf, total_size); 1725 } else { 1726 //GDI only uses hinted outlines when axis aligned. 1727 UINT format = GGO_NATIVE | GGO_GLYPH_INDEX; 1728 1729 SkAutoSTMalloc<BUFFERSIZE, uint8_t> hintedGlyphbuf(BUFFERSIZE); 1730 DWORD hinted_total_size = getGDIGlyphPath(glyph, format, &hintedGlyphbuf); 1731 if (0 == hinted_total_size) { 1732 return; 1733 } 1734 1735 if (!sk_path_from_gdi_paths(path, glyphbuf, total_size, 1736 GDIGlyphbufferPointIter(hintedGlyphbuf, hinted_total_size))) 1737 { 1738 path->reset(); 1739 sk_path_from_gdi_path(path, glyphbuf, total_size); 1740 } 1741 } 1742 } 1743 1744 static void logfont_for_name(const char* familyName, LOGFONT* lf) { 1745 sk_bzero(lf, sizeof(LOGFONT)); 1746 #ifdef UNICODE 1747 // Get the buffer size needed first. 1748 size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName, 1749 -1, NULL, 0); 1750 // Allocate a buffer (str_len already has terminating null 1751 // accounted for). 1752 wchar_t *wideFamilyName = new wchar_t[str_len]; 1753 // Now actually convert the string. 1754 ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1, 1755 wideFamilyName, str_len); 1756 ::wcsncpy(lf->lfFaceName, wideFamilyName, LF_FACESIZE - 1); 1757 delete [] wideFamilyName; 1758 lf->lfFaceName[LF_FACESIZE-1] = L'\0'; 1759 #else 1760 ::strncpy(lf->lfFaceName, familyName, LF_FACESIZE - 1); 1761 lf->lfFaceName[LF_FACESIZE - 1] = '\0'; 1762 #endif 1763 } 1764 1765 void LogFontTypeface::onGetFamilyName(SkString* familyName) const { 1766 // Get the actual name of the typeface. The logfont may not know this. 1767 HFONT font = CreateFontIndirect(&fLogFont); 1768 1769 HDC deviceContext = ::CreateCompatibleDC(NULL); 1770 HFONT savefont = (HFONT)SelectObject(deviceContext, font); 1771 1772 dcfontname_to_skstring(deviceContext, fLogFont, familyName); 1773 1774 if (deviceContext) { 1775 ::SelectObject(deviceContext, savefont); 1776 ::DeleteDC(deviceContext); 1777 } 1778 if (font) { 1779 ::DeleteObject(font); 1780 } 1781 } 1782 1783 void LogFontTypeface::onGetFontDescriptor(SkFontDescriptor* desc, 1784 bool* isLocalStream) const { 1785 SkString familyName; 1786 this->onGetFamilyName(&familyName); 1787 desc->setFamilyName(familyName.c_str()); 1788 *isLocalStream = this->fSerializeAsStream; 1789 } 1790 1791 static bool getWidthAdvance(HDC hdc, int gId, int16_t* advance) { 1792 // Initialize the MAT2 structure to the identify transformation matrix. 1793 static const MAT2 mat2 = {SkScalarToFIXED(1), SkScalarToFIXED(0), 1794 SkScalarToFIXED(0), SkScalarToFIXED(1)}; 1795 int flags = GGO_METRICS | GGO_GLYPH_INDEX; 1796 GLYPHMETRICS gm; 1797 if (GDI_ERROR == GetGlyphOutline(hdc, gId, flags, &gm, 0, NULL, &mat2)) { 1798 return false; 1799 } 1800 SkASSERT(advance); 1801 *advance = gm.gmCellIncX; 1802 return true; 1803 } 1804 1805 SkAdvancedTypefaceMetrics* LogFontTypeface::onGetAdvancedTypefaceMetrics( 1806 SkAdvancedTypefaceMetrics::PerGlyphInfo perGlyphInfo, 1807 const uint32_t* glyphIDs, 1808 uint32_t glyphIDsCount) const { 1809 LOGFONT lf = fLogFont; 1810 SkAdvancedTypefaceMetrics* info = NULL; 1811 1812 HDC hdc = CreateCompatibleDC(NULL); 1813 HFONT font = CreateFontIndirect(&lf); 1814 HFONT savefont = (HFONT)SelectObject(hdc, font); 1815 HFONT designFont = NULL; 1816 1817 const char stem_chars[] = {'i', 'I', '!', '1'}; 1818 int16_t min_width; 1819 unsigned glyphCount; 1820 1821 // To request design units, create a logical font whose height is specified 1822 // as unitsPerEm. 1823 OUTLINETEXTMETRIC otm; 1824 unsigned int otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); 1825 if (0 == otmRet) { 1826 call_ensure_accessible(lf); 1827 otmRet = GetOutlineTextMetrics(hdc, sizeof(otm), &otm); 1828 } 1829 if (!otmRet || !GetTextFace(hdc, LF_FACESIZE, lf.lfFaceName)) { 1830 goto Error; 1831 } 1832 lf.lfHeight = -SkToS32(otm.otmEMSquare); 1833 designFont = CreateFontIndirect(&lf); 1834 SelectObject(hdc, designFont); 1835 if (!GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) { 1836 goto Error; 1837 } 1838 glyphCount = calculateGlyphCount(hdc, fLogFont); 1839 1840 info = new SkAdvancedTypefaceMetrics; 1841 info->fEmSize = otm.otmEMSquare; 1842 info->fLastGlyphID = SkToU16(glyphCount - 1); 1843 info->fStyle = 0; 1844 tchar_to_skstring(lf.lfFaceName, &info->fFontName); 1845 info->fFlags = SkAdvancedTypefaceMetrics::kEmpty_FontFlag; 1846 // If bit 1 is set, the font may not be embedded in a document. 1847 // If bit 1 is clear, the font can be embedded. 1848 // If bit 2 is set, the embedding is read-only. 1849 if (otm.otmfsType & 0x1) { 1850 info->fFlags = SkTBitOr<SkAdvancedTypefaceMetrics::FontFlags>( 1851 info->fFlags, 1852 SkAdvancedTypefaceMetrics::kNotEmbeddable_FontFlag); 1853 } 1854 1855 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kToUnicode_PerGlyphInfo) { 1856 populate_glyph_to_unicode(hdc, glyphCount, &(info->fGlyphToUnicode)); 1857 } 1858 1859 if (glyphCount > 0 && 1860 (otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE)) { 1861 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 1862 } else { 1863 info->fType = SkAdvancedTypefaceMetrics::kOther_Font; 1864 info->fItalicAngle = 0; 1865 info->fAscent = 0; 1866 info->fDescent = 0; 1867 info->fStemV = 0; 1868 info->fCapHeight = 0; 1869 info->fBBox = SkIRect::MakeEmpty(); 1870 goto ReturnInfo; 1871 } 1872 1873 // If this bit is clear the font is a fixed pitch font. 1874 if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)) { 1875 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 1876 } 1877 if (otm.otmTextMetrics.tmItalic) { 1878 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 1879 } 1880 if (otm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN) { 1881 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 1882 } else if (otm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT) { 1883 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 1884 } 1885 1886 // The main italic angle of the font, in tenths of a degree counterclockwise 1887 // from vertical. 1888 info->fItalicAngle = otm.otmItalicAngle / 10; 1889 info->fAscent = SkToS16(otm.otmTextMetrics.tmAscent); 1890 info->fDescent = SkToS16(-otm.otmTextMetrics.tmDescent); 1891 // TODO(ctguil): Use alternate cap height calculation. 1892 // MSDN says otmsCapEmHeight is not support but it is returning a value on 1893 // my Win7 box. 1894 info->fCapHeight = otm.otmsCapEmHeight; 1895 info->fBBox = 1896 SkIRect::MakeLTRB(otm.otmrcFontBox.left, otm.otmrcFontBox.top, 1897 otm.otmrcFontBox.right, otm.otmrcFontBox.bottom); 1898 1899 // Figure out a good guess for StemV - Min width of i, I, !, 1. 1900 // This probably isn't very good with an italic font. 1901 min_width = SHRT_MAX; 1902 info->fStemV = 0; 1903 for (size_t i = 0; i < SK_ARRAY_COUNT(stem_chars); i++) { 1904 ABC abcWidths; 1905 if (GetCharABCWidths(hdc, stem_chars[i], stem_chars[i], &abcWidths)) { 1906 int16_t width = abcWidths.abcB; 1907 if (width > 0 && width < min_width) { 1908 min_width = width; 1909 info->fStemV = min_width; 1910 } 1911 } 1912 } 1913 1914 if (perGlyphInfo & SkAdvancedTypefaceMetrics::kHAdvance_PerGlyphInfo) { 1915 if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) { 1916 appendRange(&info->fGlyphWidths, 0); 1917 info->fGlyphWidths->fAdvance.append(1, &min_width); 1918 finishRange(info->fGlyphWidths.get(), 0, 1919 SkAdvancedTypefaceMetrics::WidthRange::kDefault); 1920 } else { 1921 info->fGlyphWidths.reset( 1922 getAdvanceData(hdc, 1923 glyphCount, 1924 glyphIDs, 1925 glyphIDsCount, 1926 &getWidthAdvance)); 1927 } 1928 } 1929 1930 Error: 1931 ReturnInfo: 1932 SelectObject(hdc, savefont); 1933 DeleteObject(designFont); 1934 DeleteObject(font); 1935 DeleteDC(hdc); 1936 1937 return info; 1938 } 1939 1940 //Dummy representation of a Base64 encoded GUID from create_unique_font_name. 1941 #define BASE64_GUID_ID "XXXXXXXXXXXXXXXXXXXXXXXX" 1942 //Length of GUID representation from create_id, including NULL terminator. 1943 #define BASE64_GUID_ID_LEN SK_ARRAY_COUNT(BASE64_GUID_ID) 1944 1945 SK_COMPILE_ASSERT(BASE64_GUID_ID_LEN < LF_FACESIZE, GUID_longer_than_facesize); 1946 1947 /** 1948 NameID 6 Postscript names cannot have the character '/'. 1949 It would be easier to hex encode the GUID, but that is 32 bytes, 1950 and many systems have issues with names longer than 28 bytes. 1951 The following need not be any standard base64 encoding. 1952 The encoded value is never decoded. 1953 */ 1954 static const char postscript_safe_base64_encode[] = 1955 "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 1956 "abcdefghijklmnopqrstuvwxyz" 1957 "0123456789-_="; 1958 1959 /** 1960 Formats a GUID into Base64 and places it into buffer. 1961 buffer should have space for at least BASE64_GUID_ID_LEN characters. 1962 The string will always be null terminated. 1963 XXXXXXXXXXXXXXXXXXXXXXXX0 1964 */ 1965 static void format_guid_b64(const GUID& guid, char* buffer, size_t bufferSize) { 1966 SkASSERT(bufferSize >= BASE64_GUID_ID_LEN); 1967 size_t written = SkBase64::Encode(&guid, sizeof(guid), buffer, postscript_safe_base64_encode); 1968 SkASSERT(written < LF_FACESIZE); 1969 buffer[written] = '\0'; 1970 } 1971 1972 /** 1973 Creates a Base64 encoded GUID and places it into buffer. 1974 buffer should have space for at least BASE64_GUID_ID_LEN characters. 1975 The string will always be null terminated. 1976 XXXXXXXXXXXXXXXXXXXXXXXX0 1977 */ 1978 static HRESULT create_unique_font_name(char* buffer, size_t bufferSize) { 1979 GUID guid = {}; 1980 if (FAILED(CoCreateGuid(&guid))) { 1981 return E_UNEXPECTED; 1982 } 1983 format_guid_b64(guid, buffer, bufferSize); 1984 1985 return S_OK; 1986 } 1987 1988 /** 1989 Introduces a font to GDI. On failure will return NULL. The returned handle 1990 should eventually be passed to RemoveFontMemResourceEx. 1991 */ 1992 static HANDLE activate_font(SkData* fontData) { 1993 DWORD numFonts = 0; 1994 //AddFontMemResourceEx just copies the data, but does not specify const. 1995 HANDLE fontHandle = AddFontMemResourceEx(const_cast<void*>(fontData->data()), 1996 static_cast<DWORD>(fontData->size()), 1997 0, 1998 &numFonts); 1999 2000 if (fontHandle != NULL && numFonts < 1) { 2001 RemoveFontMemResourceEx(fontHandle); 2002 return NULL; 2003 } 2004 2005 return fontHandle; 2006 } 2007 2008 static SkTypeface* create_from_stream(SkStream* stream) { 2009 // Create a unique and unpredictable font name. 2010 // Avoids collisions and access from CSS. 2011 char familyName[BASE64_GUID_ID_LEN]; 2012 const int familyNameSize = SK_ARRAY_COUNT(familyName); 2013 if (FAILED(create_unique_font_name(familyName, familyNameSize))) { 2014 return NULL; 2015 } 2016 2017 // Change the name of the font. 2018 SkAutoTUnref<SkData> rewrittenFontData(SkOTUtils::RenameFont(stream, familyName, familyNameSize-1)); 2019 if (NULL == rewrittenFontData.get()) { 2020 return NULL; 2021 } 2022 2023 // Register the font with GDI. 2024 HANDLE fontReference = activate_font(rewrittenFontData.get()); 2025 if (NULL == fontReference) { 2026 return NULL; 2027 } 2028 2029 // Create the typeface. 2030 LOGFONT lf; 2031 logfont_for_name(familyName, &lf); 2032 2033 return SkCreateFontMemResourceTypefaceFromLOGFONT(lf, fontReference); 2034 } 2035 2036 SkStream* LogFontTypeface::onOpenStream(int* ttcIndex) const { 2037 *ttcIndex = 0; 2038 2039 const DWORD kTTCTag = 2040 SkEndian_SwapBE32(SkSetFourByteTag('t', 't', 'c', 'f')); 2041 LOGFONT lf = fLogFont; 2042 2043 HDC hdc = ::CreateCompatibleDC(NULL); 2044 HFONT font = CreateFontIndirect(&lf); 2045 HFONT savefont = (HFONT)SelectObject(hdc, font); 2046 2047 SkMemoryStream* stream = NULL; 2048 DWORD tables[2] = {kTTCTag, 0}; 2049 for (int i = 0; i < SK_ARRAY_COUNT(tables); i++) { 2050 DWORD bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0); 2051 if (bufferSize == GDI_ERROR) { 2052 call_ensure_accessible(lf); 2053 bufferSize = GetFontData(hdc, tables[i], 0, NULL, 0); 2054 } 2055 if (bufferSize != GDI_ERROR) { 2056 stream = new SkMemoryStream(bufferSize); 2057 if (GetFontData(hdc, tables[i], 0, (void*)stream->getMemoryBase(), bufferSize)) { 2058 break; 2059 } else { 2060 delete stream; 2061 stream = NULL; 2062 } 2063 } 2064 } 2065 2066 SelectObject(hdc, savefont); 2067 DeleteObject(font); 2068 DeleteDC(hdc); 2069 2070 return stream; 2071 } 2072 2073 static void bmpCharsToGlyphs(HDC hdc, const WCHAR* bmpChars, int count, uint16_t* glyphs, 2074 bool Ox1FHack) 2075 { 2076 DWORD result = GetGlyphIndicesW(hdc, bmpChars, count, glyphs, GGI_MARK_NONEXISTING_GLYPHS); 2077 if (GDI_ERROR == result) { 2078 for (int i = 0; i < count; ++i) { 2079 glyphs[i] = 0; 2080 } 2081 return; 2082 } 2083 2084 if (Ox1FHack) { 2085 for (int i = 0; i < count; ++i) { 2086 if (0xFFFF == glyphs[i] || 0x1F == glyphs[i]) { 2087 glyphs[i] = 0; 2088 } 2089 } 2090 } else { 2091 for (int i = 0; i < count; ++i) { 2092 if (0xFFFF == glyphs[i]){ 2093 glyphs[i] = 0; 2094 } 2095 } 2096 } 2097 } 2098 2099 static uint16_t nonBmpCharToGlyph(HDC hdc, SCRIPT_CACHE* scriptCache, const WCHAR utf16[2]) { 2100 uint16_t index = 0; 2101 // Use uniscribe to detemine glyph index for non-BMP characters. 2102 static const int numWCHAR = 2; 2103 static const int maxItems = 2; 2104 // MSDN states that this can be NULL, but some things don't work then. 2105 SCRIPT_CONTROL scriptControl = { 0 }; 2106 // Add extra item to SCRIPT_ITEM to work around a bug (now documented). 2107 // https://bugzilla.mozilla.org/show_bug.cgi?id=366643 2108 SCRIPT_ITEM si[maxItems + 1]; 2109 int numItems; 2110 HRZM(ScriptItemize(utf16, numWCHAR, maxItems, &scriptControl, NULL, si, &numItems), 2111 "Could not itemize character."); 2112 2113 // Sometimes ScriptShape cannot find a glyph for a non-BMP and returns 2 space glyphs. 2114 static const int maxGlyphs = 2; 2115 SCRIPT_VISATTR vsa[maxGlyphs]; 2116 WORD outGlyphs[maxGlyphs]; 2117 WORD logClust[numWCHAR]; 2118 int numGlyphs; 2119 HRZM(ScriptShape(hdc, scriptCache, utf16, numWCHAR, maxGlyphs, &si[0].a, 2120 outGlyphs, logClust, vsa, &numGlyphs), 2121 "Could not shape character."); 2122 if (1 == numGlyphs) { 2123 index = outGlyphs[0]; 2124 } 2125 return index; 2126 } 2127 2128 class SkAutoHDC { 2129 public: 2130 SkAutoHDC(const LOGFONT& lf) 2131 : fHdc(::CreateCompatibleDC(NULL)) 2132 , fFont(::CreateFontIndirect(&lf)) 2133 , fSavefont((HFONT)SelectObject(fHdc, fFont)) 2134 { } 2135 ~SkAutoHDC() { 2136 SelectObject(fHdc, fSavefont); 2137 DeleteObject(fFont); 2138 DeleteDC(fHdc); 2139 } 2140 operator HDC() { return fHdc; } 2141 private: 2142 HDC fHdc; 2143 HFONT fFont; 2144 HFONT fSavefont; 2145 }; 2146 #define SkAutoHDC(...) SK_REQUIRE_LOCAL_VAR(SkAutoHDC) 2147 2148 int LogFontTypeface::onCharsToGlyphs(const void* chars, Encoding encoding, 2149 uint16_t userGlyphs[], int glyphCount) const 2150 { 2151 SkAutoHDC hdc(fLogFont); 2152 2153 TEXTMETRIC tm; 2154 if (0 == GetTextMetrics(hdc, &tm)) { 2155 call_ensure_accessible(fLogFont); 2156 if (0 == GetTextMetrics(hdc, &tm)) { 2157 tm.tmPitchAndFamily = TMPF_TRUETYPE; 2158 } 2159 } 2160 bool Ox1FHack = !(tm.tmPitchAndFamily & TMPF_VECTOR) /*&& winVer < Vista */; 2161 2162 SkAutoSTMalloc<256, uint16_t> scratchGlyphs; 2163 uint16_t* glyphs; 2164 if (userGlyphs != NULL) { 2165 glyphs = userGlyphs; 2166 } else { 2167 glyphs = scratchGlyphs.reset(glyphCount); 2168 } 2169 2170 SCRIPT_CACHE sc = 0; 2171 switch (encoding) { 2172 case SkTypeface::kUTF8_Encoding: { 2173 static const int scratchCount = 256; 2174 WCHAR scratch[scratchCount]; 2175 int glyphIndex = 0; 2176 const char* currentUtf8 = reinterpret_cast<const char*>(chars); 2177 SkUnichar currentChar; 2178 if (glyphCount) { 2179 currentChar = SkUTF8_NextUnichar(¤tUtf8); 2180 } 2181 while (glyphIndex < glyphCount) { 2182 // Try a run of bmp. 2183 int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount); 2184 int runLength = 0; 2185 while (runLength < glyphsLeft && currentChar <= 0xFFFF) { 2186 scratch[runLength] = static_cast<WCHAR>(currentChar); 2187 ++runLength; 2188 if (runLength < glyphsLeft) { 2189 currentChar = SkUTF8_NextUnichar(¤tUtf8); 2190 } 2191 } 2192 if (runLength) { 2193 bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack); 2194 glyphIndex += runLength; 2195 } 2196 2197 // Try a run of non-bmp. 2198 while (glyphIndex < glyphCount && currentChar > 0xFFFF) { 2199 SkUTF16_FromUnichar(currentChar, reinterpret_cast<uint16_t*>(scratch)); 2200 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch); 2201 ++glyphIndex; 2202 if (glyphIndex < glyphCount) { 2203 currentChar = SkUTF8_NextUnichar(¤tUtf8); 2204 } 2205 } 2206 } 2207 break; 2208 } 2209 case SkTypeface::kUTF16_Encoding: { 2210 int glyphIndex = 0; 2211 const WCHAR* currentUtf16 = reinterpret_cast<const WCHAR*>(chars); 2212 while (glyphIndex < glyphCount) { 2213 // Try a run of bmp. 2214 int glyphsLeft = glyphCount - glyphIndex; 2215 int runLength = 0; 2216 while (runLength < glyphsLeft && !SkUTF16_IsHighSurrogate(currentUtf16[runLength])) { 2217 ++runLength; 2218 } 2219 if (runLength) { 2220 bmpCharsToGlyphs(hdc, currentUtf16, runLength, &glyphs[glyphIndex], Ox1FHack); 2221 glyphIndex += runLength; 2222 currentUtf16 += runLength; 2223 } 2224 2225 // Try a run of non-bmp. 2226 while (glyphIndex < glyphCount && SkUTF16_IsHighSurrogate(*currentUtf16)) { 2227 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, currentUtf16); 2228 ++glyphIndex; 2229 currentUtf16 += 2; 2230 } 2231 } 2232 break; 2233 } 2234 case SkTypeface::kUTF32_Encoding: { 2235 static const int scratchCount = 256; 2236 WCHAR scratch[scratchCount]; 2237 int glyphIndex = 0; 2238 const uint32_t* utf32 = reinterpret_cast<const uint32_t*>(chars); 2239 while (glyphIndex < glyphCount) { 2240 // Try a run of bmp. 2241 int glyphsLeft = SkTMin(glyphCount - glyphIndex, scratchCount); 2242 int runLength = 0; 2243 while (runLength < glyphsLeft && utf32[glyphIndex + runLength] <= 0xFFFF) { 2244 scratch[runLength] = static_cast<WCHAR>(utf32[glyphIndex + runLength]); 2245 ++runLength; 2246 } 2247 if (runLength) { 2248 bmpCharsToGlyphs(hdc, scratch, runLength, &glyphs[glyphIndex], Ox1FHack); 2249 glyphIndex += runLength; 2250 } 2251 2252 // Try a run of non-bmp. 2253 while (glyphIndex < glyphCount && utf32[glyphIndex] > 0xFFFF) { 2254 SkUTF16_FromUnichar(utf32[glyphIndex], reinterpret_cast<uint16_t*>(scratch)); 2255 glyphs[glyphIndex] = nonBmpCharToGlyph(hdc, &sc, scratch); 2256 ++glyphIndex; 2257 } 2258 } 2259 break; 2260 } 2261 default: 2262 SK_CRASH(); 2263 } 2264 2265 if (sc) { 2266 ::ScriptFreeCache(&sc); 2267 } 2268 2269 for (int i = 0; i < glyphCount; ++i) { 2270 if (0 == glyphs[i]) { 2271 return i; 2272 } 2273 } 2274 return glyphCount; 2275 } 2276 2277 int LogFontTypeface::onCountGlyphs() const { 2278 HDC hdc = ::CreateCompatibleDC(NULL); 2279 HFONT font = CreateFontIndirect(&fLogFont); 2280 HFONT savefont = (HFONT)SelectObject(hdc, font); 2281 2282 unsigned int glyphCount = calculateGlyphCount(hdc, fLogFont); 2283 2284 SelectObject(hdc, savefont); 2285 DeleteObject(font); 2286 DeleteDC(hdc); 2287 2288 return glyphCount; 2289 } 2290 2291 int LogFontTypeface::onGetUPEM() const { 2292 HDC hdc = ::CreateCompatibleDC(NULL); 2293 HFONT font = CreateFontIndirect(&fLogFont); 2294 HFONT savefont = (HFONT)SelectObject(hdc, font); 2295 2296 unsigned int upem = calculateUPEM(hdc, fLogFont); 2297 2298 SelectObject(hdc, savefont); 2299 DeleteObject(font); 2300 DeleteDC(hdc); 2301 2302 return upem; 2303 } 2304 2305 SkTypeface::LocalizedStrings* LogFontTypeface::onCreateFamilyNameIterator() const { 2306 SkTypeface::LocalizedStrings* nameIter = 2307 SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); 2308 if (NULL == nameIter) { 2309 SkString familyName; 2310 this->getFamilyName(&familyName); 2311 SkString language("und"); //undetermined 2312 nameIter = new SkOTUtils::LocalizedStrings_SingleName(familyName, language); 2313 } 2314 return nameIter; 2315 } 2316 2317 int LogFontTypeface::onGetTableTags(SkFontTableTag tags[]) const { 2318 SkSFNTHeader header; 2319 if (sizeof(header) != this->onGetTableData(0, 0, sizeof(header), &header)) { 2320 return 0; 2321 } 2322 2323 int numTables = SkEndian_SwapBE16(header.numTables); 2324 2325 if (tags) { 2326 size_t size = numTables * sizeof(SkSFNTHeader::TableDirectoryEntry); 2327 SkAutoSTMalloc<0x20, SkSFNTHeader::TableDirectoryEntry> dir(numTables); 2328 if (size != this->onGetTableData(0, sizeof(header), size, dir.get())) { 2329 return 0; 2330 } 2331 2332 for (int i = 0; i < numTables; ++i) { 2333 tags[i] = SkEndian_SwapBE32(dir[i].tag); 2334 } 2335 } 2336 return numTables; 2337 } 2338 2339 size_t LogFontTypeface::onGetTableData(SkFontTableTag tag, size_t offset, 2340 size_t length, void* data) const 2341 { 2342 LOGFONT lf = fLogFont; 2343 2344 HDC hdc = ::CreateCompatibleDC(NULL); 2345 HFONT font = CreateFontIndirect(&lf); 2346 HFONT savefont = (HFONT)SelectObject(hdc, font); 2347 2348 tag = SkEndian_SwapBE32(tag); 2349 if (NULL == data) { 2350 length = 0; 2351 } 2352 DWORD bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) length); 2353 if (bufferSize == GDI_ERROR) { 2354 call_ensure_accessible(lf); 2355 bufferSize = GetFontData(hdc, tag, (DWORD) offset, data, (DWORD) length); 2356 } 2357 2358 SelectObject(hdc, savefont); 2359 DeleteObject(font); 2360 DeleteDC(hdc); 2361 2362 return bufferSize == GDI_ERROR ? 0 : bufferSize; 2363 } 2364 2365 SkScalerContext* LogFontTypeface::onCreateScalerContext(const SkDescriptor* desc) const { 2366 SkScalerContext_GDI* ctx = SkNEW_ARGS(SkScalerContext_GDI, 2367 (const_cast<LogFontTypeface*>(this), desc)); 2368 if (!ctx->isValid()) { 2369 SkDELETE(ctx); 2370 ctx = NULL; 2371 } 2372 return ctx; 2373 } 2374 2375 void LogFontTypeface::onFilterRec(SkScalerContextRec* rec) const { 2376 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || 2377 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) 2378 { 2379 rec->fMaskFormat = SkMask::kA8_Format; 2380 rec->fFlags |= SkScalerContext::kGenA8FromLCD_Flag; 2381 } 2382 2383 unsigned flagsWeDontSupport = SkScalerContext::kVertical_Flag | 2384 SkScalerContext::kDevKernText_Flag | 2385 SkScalerContext::kForceAutohinting_Flag | 2386 SkScalerContext::kEmbeddedBitmapText_Flag | 2387 SkScalerContext::kEmbolden_Flag | 2388 SkScalerContext::kLCD_BGROrder_Flag | 2389 SkScalerContext::kLCD_Vertical_Flag; 2390 rec->fFlags &= ~flagsWeDontSupport; 2391 2392 SkPaint::Hinting h = rec->getHinting(); 2393 switch (h) { 2394 case SkPaint::kNo_Hinting: 2395 break; 2396 case SkPaint::kSlight_Hinting: 2397 // Only do slight hinting when axis aligned. 2398 // TODO: re-enable slight hinting when FontHostTest can pass. 2399 //if (!isAxisAligned(*rec)) { 2400 h = SkPaint::kNo_Hinting; 2401 //} 2402 break; 2403 case SkPaint::kNormal_Hinting: 2404 case SkPaint::kFull_Hinting: 2405 // TODO: need to be able to distinguish subpixel positioned glyphs 2406 // and linear metrics. 2407 //rec->fFlags &= ~SkScalerContext::kSubpixelPositioning_Flag; 2408 h = SkPaint::kNormal_Hinting; 2409 break; 2410 default: 2411 SkDEBUGFAIL("unknown hinting"); 2412 } 2413 //TODO: if this is a bitmap font, squash hinting and subpixel. 2414 rec->setHinting(h); 2415 2416 // turn this off since GDI might turn A8 into BW! Need a bigger fix. 2417 #if 0 2418 // Disable LCD when rotated, since GDI's output is ugly 2419 if (isLCD(*rec) && !isAxisAligned(*rec)) { 2420 rec->fMaskFormat = SkMask::kA8_Format; 2421 } 2422 #endif 2423 2424 if (!fCanBeLCD && isLCD(*rec)) { 2425 rec->fMaskFormat = SkMask::kA8_Format; 2426 rec->fFlags &= ~SkScalerContext::kGenA8FromLCD_Flag; 2427 } 2428 } 2429 2430 /////////////////////////////////////////////////////////////////////////////// 2431 2432 #include "SkFontMgr.h" 2433 #include "SkDataTable.h" 2434 2435 static bool valid_logfont_for_enum(const LOGFONT& lf) { 2436 // TODO: Vector FON is unsupported and should not be listed. 2437 return 2438 // Ignore implicit vertical variants. 2439 lf.lfFaceName[0] && lf.lfFaceName[0] != '@' 2440 2441 // DEFAULT_CHARSET is used to get all fonts, but also implies all 2442 // character sets. Filter assuming all fonts support ANSI_CHARSET. 2443 && ANSI_CHARSET == lf.lfCharSet 2444 ; 2445 } 2446 2447 /** An EnumFontFamExProc implementation which interprets builderParam as 2448 * an SkTDArray<ENUMLOGFONTEX>* and appends logfonts which 2449 * pass the valid_logfont_for_enum predicate. 2450 */ 2451 static int CALLBACK enum_family_proc(const LOGFONT* lf, const TEXTMETRIC*, 2452 DWORD fontType, LPARAM builderParam) { 2453 if (valid_logfont_for_enum(*lf)) { 2454 SkTDArray<ENUMLOGFONTEX>* array = (SkTDArray<ENUMLOGFONTEX>*)builderParam; 2455 *array->append() = *(ENUMLOGFONTEX*)lf; 2456 } 2457 return 1; // non-zero means continue 2458 } 2459 2460 static SkFontStyle compute_fontstyle(const LOGFONT& lf) { 2461 return SkFontStyle(lf.lfWeight, SkFontStyle::kNormal_Width, 2462 lf.lfItalic ? SkFontStyle::kItalic_Slant 2463 : SkFontStyle::kUpright_Slant); 2464 } 2465 2466 class SkFontStyleSetGDI : public SkFontStyleSet { 2467 public: 2468 SkFontStyleSetGDI(const TCHAR familyName[]) { 2469 LOGFONT lf; 2470 sk_bzero(&lf, sizeof(lf)); 2471 lf.lfCharSet = DEFAULT_CHARSET; 2472 _tcscpy_s(lf.lfFaceName, familyName); 2473 2474 HDC hdc = ::CreateCompatibleDC(NULL); 2475 ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fArray, 0); 2476 ::DeleteDC(hdc); 2477 } 2478 2479 virtual int count() SK_OVERRIDE { 2480 return fArray.count(); 2481 } 2482 2483 virtual void getStyle(int index, SkFontStyle* fs, SkString* styleName) SK_OVERRIDE { 2484 if (fs) { 2485 *fs = compute_fontstyle(fArray[index].elfLogFont); 2486 } 2487 if (styleName) { 2488 const ENUMLOGFONTEX& ref = fArray[index]; 2489 // For some reason, ENUMLOGFONTEX and LOGFONT disagree on their type in the 2490 // non-unicode version. 2491 // ENUMLOGFONTEX uses BYTE 2492 // LOGFONT uses CHAR 2493 // Here we assert they that the style name is logically the same (size) as 2494 // a TCHAR, so we can use the same converter function. 2495 SkASSERT(sizeof(TCHAR) == sizeof(ref.elfStyle[0])); 2496 tchar_to_skstring((const TCHAR*)ref.elfStyle, styleName); 2497 } 2498 } 2499 2500 virtual SkTypeface* createTypeface(int index) SK_OVERRIDE { 2501 return SkCreateTypefaceFromLOGFONT(fArray[index].elfLogFont); 2502 } 2503 2504 virtual SkTypeface* matchStyle(const SkFontStyle& pattern) SK_OVERRIDE { 2505 // todo: 2506 return SkCreateTypefaceFromLOGFONT(fArray[0].elfLogFont); 2507 } 2508 2509 private: 2510 SkTDArray<ENUMLOGFONTEX> fArray; 2511 }; 2512 2513 class SkFontMgrGDI : public SkFontMgr { 2514 public: 2515 SkFontMgrGDI() { 2516 LOGFONT lf; 2517 sk_bzero(&lf, sizeof(lf)); 2518 lf.lfCharSet = DEFAULT_CHARSET; 2519 2520 HDC hdc = ::CreateCompatibleDC(NULL); 2521 ::EnumFontFamiliesEx(hdc, &lf, enum_family_proc, (LPARAM)&fLogFontArray, 0); 2522 ::DeleteDC(hdc); 2523 } 2524 2525 protected: 2526 virtual int onCountFamilies() const SK_OVERRIDE { 2527 return fLogFontArray.count(); 2528 } 2529 2530 virtual void onGetFamilyName(int index, SkString* familyName) const SK_OVERRIDE { 2531 SkASSERT((unsigned)index < (unsigned)fLogFontArray.count()); 2532 tchar_to_skstring(fLogFontArray[index].elfLogFont.lfFaceName, familyName); 2533 } 2534 2535 virtual SkFontStyleSet* onCreateStyleSet(int index) const SK_OVERRIDE { 2536 SkASSERT((unsigned)index < (unsigned)fLogFontArray.count()); 2537 return SkNEW_ARGS(SkFontStyleSetGDI, (fLogFontArray[index].elfLogFont.lfFaceName)); 2538 } 2539 2540 virtual SkFontStyleSet* onMatchFamily(const char familyName[]) const SK_OVERRIDE { 2541 if (NULL == familyName) { 2542 familyName = ""; // do we need this check??? 2543 } 2544 LOGFONT lf; 2545 logfont_for_name(familyName, &lf); 2546 return SkNEW_ARGS(SkFontStyleSetGDI, (lf.lfFaceName)); 2547 } 2548 2549 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 2550 const SkFontStyle& fontstyle) const SK_OVERRIDE { 2551 // could be in base impl 2552 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 2553 return sset->matchStyle(fontstyle); 2554 } 2555 2556 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 2557 const SkFontStyle& fontstyle) const SK_OVERRIDE { 2558 // could be in base impl 2559 SkString familyName; 2560 ((LogFontTypeface*)familyMember)->getFamilyName(&familyName); 2561 return this->matchFamilyStyle(familyName.c_str(), fontstyle); 2562 } 2563 2564 virtual SkTypeface* onCreateFromStream(SkStream* stream, int ttcIndex) const SK_OVERRIDE { 2565 return create_from_stream(stream); 2566 } 2567 2568 virtual SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const SK_OVERRIDE { 2569 // could be in base impl 2570 SkAutoTUnref<SkStream> stream(SkNEW_ARGS(SkMemoryStream, (data))); 2571 return this->createFromStream(stream); 2572 } 2573 2574 virtual SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const SK_OVERRIDE { 2575 // could be in base impl 2576 SkAutoTUnref<SkStream> stream(SkStream::NewFromFile(path)); 2577 return this->createFromStream(stream); 2578 } 2579 2580 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 2581 unsigned styleBits) const SK_OVERRIDE { 2582 LOGFONT lf; 2583 if (NULL == familyName) { 2584 lf = get_default_font(); 2585 } else { 2586 logfont_for_name(familyName, &lf); 2587 } 2588 setStyle(&lf, (SkTypeface::Style)styleBits); 2589 return SkCreateTypefaceFromLOGFONT(lf); 2590 } 2591 2592 private: 2593 SkTDArray<ENUMLOGFONTEX> fLogFontArray; 2594 }; 2595 2596 /////////////////////////////////////////////////////////////////////////////// 2597 2598 SkFontMgr* SkFontMgr_New_GDI() { 2599 return SkNEW(SkFontMgrGDI); 2600 } 2601