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