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