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