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