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 "SkTypes.h" // Keep this before any #ifdef ... 10 #if defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) 11 12 #ifdef SK_BUILD_FOR_MAC 13 #import <ApplicationServices/ApplicationServices.h> 14 #endif 15 16 #ifdef SK_BUILD_FOR_IOS 17 #include <CoreText/CoreText.h> 18 #include <CoreText/CTFontManager.h> 19 #include <CoreGraphics/CoreGraphics.h> 20 #include <CoreFoundation/CoreFoundation.h> 21 #endif 22 23 #include "SkAdvancedTypefaceMetrics.h" 24 #include "SkCGUtils.h" 25 #include "SkColorPriv.h" 26 #include "SkDescriptor.h" 27 #include "SkEndian.h" 28 #include "SkFloatingPoint.h" 29 #include "SkFontDescriptor.h" 30 #include "SkFontMgr.h" 31 #include "SkGlyph.h" 32 #include "SkMaskGamma.h" 33 #include "SkMutex.h" 34 #include "SkOTTable_glyf.h" 35 #include "SkOTTable_head.h" 36 #include "SkOTTable_hhea.h" 37 #include "SkOTTable_loca.h" 38 #include "SkOTUtils.h" 39 #include "SkOncePtr.h" 40 #include "SkPaint.h" 41 #include "SkPath.h" 42 #include "SkSFNTHeader.h" 43 #include "SkStream.h" 44 #include "SkString.h" 45 #include "SkTemplates.h" 46 #include "SkTypefaceCache.h" 47 #include "SkTypeface_mac.h" 48 #include "SkUtils.h" 49 #include "SkUtils.h" 50 51 #include <dlfcn.h> 52 53 // Experimental code to use a global lock whenever we access CG, to see if this reduces 54 // crashes in Chrome 55 #define USE_GLOBAL_MUTEX_FOR_CG_ACCESS 56 57 #ifdef USE_GLOBAL_MUTEX_FOR_CG_ACCESS 58 SK_DECLARE_STATIC_MUTEX(gCGMutex); 59 #define AUTO_CG_LOCK() SkAutoMutexAcquire amc(gCGMutex) 60 #else 61 #define AUTO_CG_LOCK() 62 #endif 63 64 // Set to make glyph bounding boxes visible. 65 #define SK_SHOW_TEXT_BLIT_COVERAGE 0 66 67 class SkScalerContext_Mac; 68 69 // CTFontManagerCopyAvailableFontFamilyNames() is not always available, so we 70 // provide a wrapper here that will return an empty array if need be. 71 static CFArrayRef SkCTFontManagerCopyAvailableFontFamilyNames() { 72 #ifdef SK_BUILD_FOR_IOS 73 return CFArrayCreate(nullptr, nullptr, 0, nullptr); 74 #else 75 return CTFontManagerCopyAvailableFontFamilyNames(); 76 #endif 77 } 78 79 80 // Being templated and taking const T* prevents calling 81 // CFSafeRelease(autoCFRelease) through implicit conversion. 82 template <typename T> static void CFSafeRelease(/*CFTypeRef*/const T* cfTypeRef) { 83 if (cfTypeRef) { 84 CFRelease(cfTypeRef); 85 } 86 } 87 88 // Being templated and taking const T* prevents calling 89 // CFSafeRetain(autoCFRelease) through implicit conversion. 90 template <typename T> static void CFSafeRetain(/*CFTypeRef*/const T* cfTypeRef) { 91 if (cfTypeRef) { 92 CFRetain(cfTypeRef); 93 } 94 } 95 96 /** Acts like a CFRef, but calls CFSafeRelease when it goes out of scope. */ 97 template<typename CFRef> class AutoCFRelease : private SkNoncopyable { 98 public: 99 explicit AutoCFRelease(CFRef cfRef = nullptr) : fCFRef(cfRef) { } 100 ~AutoCFRelease() { CFSafeRelease(fCFRef); } 101 102 void reset(CFRef that = nullptr) { 103 if (that != fCFRef) { 104 CFSafeRelease(fCFRef); 105 fCFRef = that; 106 } 107 } 108 109 CFRef detach() { 110 CFRef self = fCFRef; 111 fCFRef = nullptr; 112 return self; 113 } 114 115 operator CFRef() const { return fCFRef; } 116 CFRef get() const { return fCFRef; } 117 118 CFRef* operator&() { SkASSERT(fCFRef == nullptr); return &fCFRef; } 119 private: 120 CFRef fCFRef; 121 }; 122 123 static CFStringRef make_CFString(const char str[]) { 124 return CFStringCreateWithCString(nullptr, str, kCFStringEncodingUTF8); 125 } 126 127 template<typename T> class AutoCGTable : SkNoncopyable { 128 public: 129 AutoCGTable(CGFontRef font) 130 //Undocumented: the tag parameter in this call is expected in machine order and not BE order. 131 : fCFData(CGFontCopyTableForTag(font, SkSetFourByteTag(T::TAG0, T::TAG1, T::TAG2, T::TAG3))) 132 , fData(fCFData ? reinterpret_cast<const T*>(CFDataGetBytePtr(fCFData)) : nullptr) 133 { } 134 135 const T* operator->() const { return fData; } 136 137 private: 138 AutoCFRelease<CFDataRef> fCFData; 139 public: 140 const T* fData; 141 }; 142 143 // inline versions of these rect helpers 144 145 static bool CGRectIsEmpty_inline(const CGRect& rect) { 146 return rect.size.width <= 0 || rect.size.height <= 0; 147 } 148 149 static CGFloat CGRectGetMinX_inline(const CGRect& rect) { 150 return rect.origin.x; 151 } 152 153 static CGFloat CGRectGetMaxX_inline(const CGRect& rect) { 154 return rect.origin.x + rect.size.width; 155 } 156 157 static CGFloat CGRectGetMinY_inline(const CGRect& rect) { 158 return rect.origin.y; 159 } 160 161 static CGFloat CGRectGetMaxY_inline(const CGRect& rect) { 162 return rect.origin.y + rect.size.height; 163 } 164 165 static CGFloat CGRectGetWidth_inline(const CGRect& rect) { 166 return rect.size.width; 167 } 168 169 /////////////////////////////////////////////////////////////////////////////// 170 171 static void sk_memset_rect32(uint32_t* ptr, uint32_t value, 172 int width, int height, size_t rowBytes) { 173 SkASSERT(width); 174 SkASSERT(width * sizeof(uint32_t) <= rowBytes); 175 176 if (width >= 32) { 177 while (height) { 178 sk_memset32(ptr, value, width); 179 ptr = (uint32_t*)((char*)ptr + rowBytes); 180 height -= 1; 181 } 182 return; 183 } 184 185 rowBytes -= width * sizeof(uint32_t); 186 187 if (width >= 8) { 188 while (height) { 189 int w = width; 190 do { 191 *ptr++ = value; *ptr++ = value; 192 *ptr++ = value; *ptr++ = value; 193 *ptr++ = value; *ptr++ = value; 194 *ptr++ = value; *ptr++ = value; 195 w -= 8; 196 } while (w >= 8); 197 while (--w >= 0) { 198 *ptr++ = value; 199 } 200 ptr = (uint32_t*)((char*)ptr + rowBytes); 201 height -= 1; 202 } 203 } else { 204 while (height) { 205 int w = width; 206 do { 207 *ptr++ = value; 208 } while (--w > 0); 209 ptr = (uint32_t*)((char*)ptr + rowBytes); 210 height -= 1; 211 } 212 } 213 } 214 215 #include <sys/utsname.h> 216 217 typedef uint32_t CGRGBPixel; 218 219 static unsigned CGRGBPixel_getAlpha(CGRGBPixel pixel) { 220 return pixel & 0xFF; 221 } 222 223 static const char FONT_DEFAULT_NAME[] = "Lucida Sans"; 224 225 // See Source/WebKit/chromium/base/mac/mac_util.mm DarwinMajorVersionInternal for original source. 226 static int readVersion() { 227 struct utsname info; 228 if (uname(&info) != 0) { 229 SkDebugf("uname failed\n"); 230 return 0; 231 } 232 if (strcmp(info.sysname, "Darwin") != 0) { 233 SkDebugf("unexpected uname sysname %s\n", info.sysname); 234 return 0; 235 } 236 char* dot = strchr(info.release, '.'); 237 if (!dot) { 238 SkDebugf("expected dot in uname release %s\n", info.release); 239 return 0; 240 } 241 int version = atoi(info.release); 242 if (version == 0) { 243 SkDebugf("could not parse uname release %s\n", info.release); 244 } 245 return version; 246 } 247 248 static int darwinVersion() { 249 static int darwin_version = readVersion(); 250 return darwin_version; 251 } 252 253 static bool isSnowLeopard() { 254 return darwinVersion() == 10; 255 } 256 257 static bool isLion() { 258 return darwinVersion() == 11; 259 } 260 261 static bool isMountainLion() { 262 return darwinVersion() == 12; 263 } 264 265 static bool isLCDFormat(unsigned format) { 266 return SkMask::kLCD16_Format == format; 267 } 268 269 static CGFloat ScalarToCG(SkScalar scalar) { 270 if (sizeof(CGFloat) == sizeof(float)) { 271 return SkScalarToFloat(scalar); 272 } else { 273 SkASSERT(sizeof(CGFloat) == sizeof(double)); 274 return (CGFloat) SkScalarToDouble(scalar); 275 } 276 } 277 278 static SkScalar CGToScalar(CGFloat cgFloat) { 279 if (sizeof(CGFloat) == sizeof(float)) { 280 return cgFloat; 281 } else { 282 SkASSERT(sizeof(CGFloat) == sizeof(double)); 283 return SkDoubleToScalar(cgFloat); 284 } 285 } 286 287 static CGAffineTransform MatrixToCGAffineTransform(const SkMatrix& matrix, 288 SkScalar sx = SK_Scalar1, 289 SkScalar sy = SK_Scalar1) { 290 return CGAffineTransformMake( ScalarToCG(matrix[SkMatrix::kMScaleX] * sx), 291 -ScalarToCG(matrix[SkMatrix::kMSkewY] * sy), 292 -ScalarToCG(matrix[SkMatrix::kMSkewX] * sx), 293 ScalarToCG(matrix[SkMatrix::kMScaleY] * sy), 294 ScalarToCG(matrix[SkMatrix::kMTransX] * sx), 295 ScalarToCG(matrix[SkMatrix::kMTransY] * sy)); 296 } 297 298 /////////////////////////////////////////////////////////////////////////////// 299 300 #define BITMAP_INFO_RGB (kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host) 301 302 /** 303 * There does not appear to be a publicly accessable API for determining if lcd 304 * font smoothing will be applied if we request it. The main issue is that if 305 * smoothing is applied a gamma of 2.0 will be used, if not a gamma of 1.0. 306 */ 307 static bool supports_LCD() { 308 static int gSupportsLCD = -1; 309 if (gSupportsLCD >= 0) { 310 return (bool) gSupportsLCD; 311 } 312 uint32_t rgb = 0; 313 AutoCFRelease<CGColorSpaceRef> colorspace(CGColorSpaceCreateDeviceRGB()); 314 AutoCFRelease<CGContextRef> cgContext(CGBitmapContextCreate(&rgb, 1, 1, 8, 4, 315 colorspace, BITMAP_INFO_RGB)); 316 CGContextSelectFont(cgContext, "Helvetica", 16, kCGEncodingMacRoman); 317 CGContextSetShouldSmoothFonts(cgContext, true); 318 CGContextSetShouldAntialias(cgContext, true); 319 CGContextSetTextDrawingMode(cgContext, kCGTextFill); 320 CGContextSetGrayFillColor(cgContext, 1, 1); 321 CGContextShowTextAtPoint(cgContext, -1, 0, "|", 1); 322 uint32_t r = (rgb >> 16) & 0xFF; 323 uint32_t g = (rgb >> 8) & 0xFF; 324 uint32_t b = (rgb >> 0) & 0xFF; 325 gSupportsLCD = (r != g || r != b); 326 return (bool) gSupportsLCD; 327 } 328 329 class Offscreen { 330 public: 331 Offscreen() 332 : fRGBSpace(nullptr) 333 , fCG(nullptr) 334 , fDoAA(false) 335 , fDoLCD(false) 336 { 337 fSize.set(0, 0); 338 } 339 340 CGRGBPixel* getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph, 341 CGGlyph glyphID, size_t* rowBytesPtr, 342 bool generateA8FromLCD); 343 344 private: 345 enum { 346 kSize = 32 * 32 * sizeof(CGRGBPixel) 347 }; 348 SkAutoSMalloc<kSize> fImageStorage; 349 AutoCFRelease<CGColorSpaceRef> fRGBSpace; 350 351 // cached state 352 AutoCFRelease<CGContextRef> fCG; 353 SkISize fSize; 354 bool fDoAA; 355 bool fDoLCD; 356 357 static int RoundSize(int dimension) { 358 return SkNextPow2(dimension); 359 } 360 }; 361 362 /////////////////////////////////////////////////////////////////////////////// 363 364 static bool find_dict_float(CFDictionaryRef dict, CFStringRef name, float* value) { 365 CFNumberRef num; 366 return CFDictionaryGetValueIfPresent(dict, name, (const void**)&num) 367 && CFNumberIsFloatType(num) 368 && CFNumberGetValue(num, kCFNumberFloatType, value); 369 } 370 371 static int unit_weight_to_fontstyle(float unit) { 372 float value; 373 if (unit < 0) { 374 value = 100 + (1 + unit) * 300; 375 } else { 376 value = 400 + unit * 500; 377 } 378 return sk_float_round2int(value); 379 } 380 381 static int unit_width_to_fontstyle(float unit) { 382 float value; 383 if (unit < 0) { 384 value = 1 + (1 + unit) * 4; 385 } else { 386 value = 5 + unit * 4; 387 } 388 return sk_float_round2int(value); 389 } 390 391 static SkFontStyle fontstyle_from_descriptor(CTFontDescriptorRef desc) { 392 AutoCFRelease<CFDictionaryRef> dict( 393 (CFDictionaryRef)CTFontDescriptorCopyAttribute(desc, kCTFontTraitsAttribute)); 394 if (nullptr == dict.get()) { 395 return SkFontStyle(); 396 } 397 398 float weight, width, slant; 399 if (!find_dict_float(dict, kCTFontWeightTrait, &weight)) { 400 weight = 0; 401 } 402 if (!find_dict_float(dict, kCTFontWidthTrait, &width)) { 403 width = 0; 404 } 405 if (!find_dict_float(dict, kCTFontSlantTrait, &slant)) { 406 slant = 0; 407 } 408 409 return SkFontStyle(unit_weight_to_fontstyle(weight), 410 unit_width_to_fontstyle(width), 411 slant ? SkFontStyle::kItalic_Slant 412 : SkFontStyle::kUpright_Slant); 413 } 414 415 static SkTypeface::Style computeStyleBits(CTFontRef font, bool* isFixedPitch) { 416 unsigned style = SkTypeface::kNormal; 417 CTFontSymbolicTraits traits = CTFontGetSymbolicTraits(font); 418 419 if (traits & kCTFontBoldTrait) { 420 style |= SkTypeface::kBold; 421 } 422 if (traits & kCTFontItalicTrait) { 423 style |= SkTypeface::kItalic; 424 } 425 if (isFixedPitch) { 426 *isFixedPitch = (traits & kCTFontMonoSpaceTrait) != 0; 427 } 428 return (SkTypeface::Style)style; 429 } 430 431 #define WEIGHT_THRESHOLD ((SkFontStyle::kNormal_Weight + SkFontStyle::kBold_Weight)/2) 432 433 // kCTFontColorGlyphsTrait was added in the Mac 10.7 and iPhone 4.3 SDKs. 434 // Being an enum value it is not guarded by version macros, but old SDKs must still be supported. 435 #if defined(__MAC_10_7) || defined(__IPHONE_4_3) 436 static const uint32_t SkCTFontColorGlyphsTrait = kCTFontColorGlyphsTrait; 437 #else 438 static const uint32_t SkCTFontColorGlyphsTrait = (1 << 13); 439 #endif 440 441 class SkTypeface_Mac : public SkTypeface { 442 public: 443 SkTypeface_Mac(CTFontRef fontRef, CFTypeRef resourceRef, 444 const SkFontStyle& fs, bool isFixedPitch, 445 const char requestedName[], bool isLocalStream) 446 : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch) 447 , fRequestedName(requestedName) 448 , fFontRef(fontRef) // caller has already called CFRetain for us 449 , fOriginatingCFTypeRef(resourceRef) // caller has already called CFRetain for us 450 , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontColorGlyphsTrait)) 451 , fIsLocalStream(isLocalStream) 452 { 453 SkASSERT(fontRef); 454 } 455 456 SkString fRequestedName; 457 AutoCFRelease<CTFontRef> fFontRef; 458 AutoCFRelease<CFTypeRef> fOriginatingCFTypeRef; 459 const bool fHasColorGlyphs; 460 461 protected: 462 int onGetUPEM() const override; 463 SkStreamAsset* onOpenStream(int* ttcIndex) const override; 464 SkFontData* onCreateFontData() const override; 465 void onGetFamilyName(SkString* familyName) const override; 466 SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override; 467 int onGetTableTags(SkFontTableTag tags[]) const override; 468 virtual size_t onGetTableData(SkFontTableTag, size_t offset, 469 size_t length, void* data) const override; 470 SkScalerContext* onCreateScalerContext(const SkDescriptor*) const override; 471 void onFilterRec(SkScalerContextRec*) const override; 472 void onGetFontDescriptor(SkFontDescriptor*, bool*) const override; 473 virtual SkAdvancedTypefaceMetrics* onGetAdvancedTypefaceMetrics( 474 PerGlyphInfo, 475 const uint32_t*, uint32_t) const override; 476 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], 477 int glyphCount) const override; 478 int onCountGlyphs() const override; 479 480 private: 481 bool fIsLocalStream; 482 483 typedef SkTypeface INHERITED; 484 }; 485 486 /** Creates a typeface without searching the cache. Takes ownership of the CTFontRef. */ 487 static SkTypeface* NewFromFontRef(CTFontRef fontRef, CFTypeRef resourceRef, 488 const char name[], bool isLocalStream) 489 { 490 SkASSERT(fontRef); 491 bool isFixedPitch; 492 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch)); 493 494 return new SkTypeface_Mac(fontRef, resourceRef, style, isFixedPitch, name, isLocalStream); 495 } 496 497 static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* context) { 498 CTFontRef self = (CTFontRef)context; 499 CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef; 500 501 return CFEqual(self, other); 502 } 503 504 /** Creates a typeface from a name, searching the cache. */ 505 static SkTypeface* NewFromName(const char familyName[], const SkFontStyle& theStyle) { 506 CTFontSymbolicTraits ctFontTraits = 0; 507 if (theStyle.weight() >= SkFontStyle::kBold_Weight) { 508 ctFontTraits |= kCTFontBoldTrait; 509 } 510 if (theStyle.slant() != SkFontStyle::kUpright_Slant) { 511 ctFontTraits |= kCTFontItalicTrait; 512 } 513 514 //TODO: add weight width slant 515 516 // Create the font info 517 AutoCFRelease<CFStringRef> cfFontName(make_CFString(familyName)); 518 519 AutoCFRelease<CFNumberRef> cfFontTraits( 520 CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTraits)); 521 522 AutoCFRelease<CFMutableDictionaryRef> cfAttributes( 523 CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 524 &kCFTypeDictionaryKeyCallBacks, 525 &kCFTypeDictionaryValueCallBacks)); 526 527 AutoCFRelease<CFMutableDictionaryRef> cfTraits( 528 CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 529 &kCFTypeDictionaryKeyCallBacks, 530 &kCFTypeDictionaryValueCallBacks)); 531 532 if (!cfFontName || !cfFontTraits || !cfAttributes || !cfTraits) { 533 return nullptr; 534 } 535 536 CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits); 537 538 CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName); 539 CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits); 540 541 AutoCFRelease<CTFontDescriptorRef> ctFontDesc( 542 CTFontDescriptorCreateWithAttributes(cfAttributes)); 543 if (!ctFontDesc) { 544 return nullptr; 545 } 546 547 AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(ctFontDesc, 0, nullptr)); 548 if (!ctFont) { 549 return nullptr; 550 } 551 552 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)ctFont.get()); 553 if (!face) { 554 face = NewFromFontRef(ctFont.detach(), nullptr, nullptr, false); 555 SkTypefaceCache::Add(face, face->fontStyle()); 556 } 557 return face; 558 } 559 560 SK_DECLARE_STATIC_MUTEX(gGetDefaultFaceMutex); 561 static SkTypeface* GetDefaultFace() { 562 SkAutoMutexAcquire ma(gGetDefaultFaceMutex); 563 564 static SkTypeface* gDefaultFace; 565 566 if (nullptr == gDefaultFace) { 567 gDefaultFace = NewFromName(FONT_DEFAULT_NAME, SkFontStyle()); 568 SkTypefaceCache::Add(gDefaultFace, SkFontStyle()); 569 } 570 return gDefaultFace; 571 } 572 573 /////////////////////////////////////////////////////////////////////////////// 574 575 extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face); 576 CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) { 577 const SkTypeface_Mac* macface = (const SkTypeface_Mac*)face; 578 return macface ? macface->fFontRef.get() : nullptr; 579 } 580 581 /* This function is visible on the outside. It first searches the cache, and if 582 * not found, returns a new entry (after adding it to the cache). 583 */ 584 SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef, CFTypeRef resourceRef) { 585 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)fontRef); 586 if (!face) { 587 CFRetain(fontRef); 588 if (resourceRef) { 589 CFRetain(resourceRef); 590 } 591 face = NewFromFontRef(fontRef, resourceRef, nullptr, false); 592 SkTypefaceCache::Add(face, face->fontStyle()); 593 } 594 return face; 595 } 596 597 struct NameStyle { 598 const char* fName; 599 SkFontStyle fStyle; 600 }; 601 602 static bool find_by_NameStyle(SkTypeface* cachedFace, const SkFontStyle& cachedStyle, void* ctx) { 603 const SkTypeface_Mac* cachedMacFace = static_cast<SkTypeface_Mac*>(cachedFace); 604 const NameStyle* requested = static_cast<const NameStyle*>(ctx); 605 606 return cachedStyle == requested->fStyle 607 && cachedMacFace->fRequestedName.equals(requested->fName); 608 } 609 610 static const char* map_css_names(const char* name) { 611 static const struct { 612 const char* fFrom; // name the caller specified 613 const char* fTo; // "canonical" name we map to 614 } gPairs[] = { 615 { "sans-serif", "Helvetica" }, 616 { "serif", "Times" }, 617 { "monospace", "Courier" } 618 }; 619 620 for (size_t i = 0; i < SK_ARRAY_COUNT(gPairs); i++) { 621 if (strcmp(name, gPairs[i].fFrom) == 0) { 622 return gPairs[i].fTo; 623 } 624 } 625 return name; // no change 626 } 627 628 /////////////////////////////////////////////////////////////////////////////// 629 630 /** GlyphRect is in FUnits (em space, y up). */ 631 struct GlyphRect { 632 int16_t fMinX; 633 int16_t fMinY; 634 int16_t fMaxX; 635 int16_t fMaxY; 636 }; 637 638 class SkScalerContext_Mac : public SkScalerContext { 639 public: 640 SkScalerContext_Mac(SkTypeface_Mac*, const SkDescriptor*); 641 642 protected: 643 unsigned generateGlyphCount(void) override; 644 uint16_t generateCharToGlyph(SkUnichar uni) override; 645 void generateAdvance(SkGlyph* glyph) override; 646 void generateMetrics(SkGlyph* glyph) override; 647 void generateImage(const SkGlyph& glyph) override; 648 void generatePath(const SkGlyph& glyph, SkPath* path) override; 649 void generateFontMetrics(SkPaint::FontMetrics*) override; 650 651 private: 652 static void CTPathElement(void *info, const CGPathElement *element); 653 654 /** Returns the offset from the horizontal origin to the vertical origin in SkGlyph units. */ 655 void getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const; 656 657 /** Initializes and returns the value of fFBoundingBoxesGlyphOffset. 658 * 659 * For use with (and must be called before) generateBBoxes. 660 */ 661 uint16_t getFBoundingBoxesGlyphOffset(); 662 663 /** Initializes fFBoundingBoxes and returns true on success. 664 * 665 * On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug which causes it to 666 * return a bad value in bounds.origin.x for SFNT fonts whose hhea::numberOfHMetrics is 667 * less than its maxp::numGlyphs. When this is the case we try to read the bounds from the 668 * font directly. 669 * 670 * This routine initializes fFBoundingBoxes to an array of 671 * fGlyphCount - fFBoundingBoxesGlyphOffset GlyphRects which contain the bounds in FUnits 672 * (em space, y up) of glyphs with ids in the range [fFBoundingBoxesGlyphOffset, fGlyphCount). 673 * 674 * Returns true if fFBoundingBoxes is properly initialized. The table can only be properly 675 * initialized for a TrueType font with 'head', 'loca', and 'glyf' tables. 676 * 677 * TODO: A future optimization will compute fFBoundingBoxes once per fCTFont. 678 */ 679 bool generateBBoxes(); 680 681 /** Converts from FUnits (em space, y up) to SkGlyph units (pixels, y down). 682 * 683 * Used on Snow Leopard to correct CTFontGetVerticalTranslationsForGlyphs. 684 * Used on Lion to correct CTFontGetBoundingRectsForGlyphs. 685 */ 686 SkMatrix fFUnitMatrix; 687 688 Offscreen fOffscreen; 689 690 /** Unrotated variant of fCTFont. 691 * 692 * In 10.10.1 CTFontGetAdvancesForGlyphs applies the font transform to the width of the 693 * advances, but always sets the height to 0. This font is used to get the advances of the 694 * unrotated glyph, and then the rotation is applied separately. 695 * 696 * CT vertical metrics are pre-rotated (in em space, before transform) 90deg clock-wise. 697 * This makes kCTFontDefaultOrientation dangerous, because the metrics from 698 * kCTFontHorizontalOrientation are in a different space from kCTFontVerticalOrientation. 699 * With kCTFontVerticalOrientation the advances must be unrotated. 700 * 701 * Sometimes, creating a copy of a CTFont with the same size but different trasform will select 702 * different underlying font data. As a result, avoid ever creating more than one CTFont per 703 * SkScalerContext to ensure that only one CTFont is used. 704 * 705 * As a result of the above (and other constraints) this font contains the size, but not the 706 * transform. The transform must always be applied separately. 707 */ 708 AutoCFRelease<CTFontRef> fCTFont; 709 710 /** The transform without the font size. */ 711 CGAffineTransform fTransform; 712 CGAffineTransform fInvTransform; 713 714 AutoCFRelease<CGFontRef> fCGFont; 715 SkAutoTMalloc<GlyphRect> fFBoundingBoxes; 716 uint16_t fFBoundingBoxesGlyphOffset; 717 uint16_t fGlyphCount; 718 bool fGeneratedFBoundingBoxes; 719 const bool fDoSubPosition; 720 const bool fVertical; 721 722 friend class Offscreen; 723 724 typedef SkScalerContext INHERITED; 725 }; 726 727 // CTFontCreateCopyWithAttributes or CTFontCreateCopyWithSymbolicTraits cannot be used on 10.10 728 // and later, as they will return different underlying fonts depending on the size requested. 729 // It is not possible to use descriptors with CTFontCreateWithFontDescriptor, since that does not 730 // work with non-system fonts. As a result, create the strike specific CTFonts from the underlying 731 // CGFont. 732 static CTFontRef ctfont_create_exact_copy(CTFontRef baseFont, CGFloat textSize, 733 const CGAffineTransform* transform) 734 { 735 AutoCFRelease<CGFontRef> baseCGFont(CTFontCopyGraphicsFont(baseFont, nullptr)); 736 737 // The last parameter (CTFontDescriptorRef attributes) *must* be nullptr. 738 // If non-nullptr then with fonts with variation axes, the copy will fail in 739 // CGFontVariationFromDictCallback when it assumes kCGFontVariationAxisName is CFNumberRef 740 // which it quite obviously is not. 741 742 // Because we cannot setup the CTFont descriptor to match, the same restriction applies here 743 // as other uses of CTFontCreateWithGraphicsFont which is that such CTFonts should not escape 744 // the scaler context, since they aren't 'normal'. 745 return CTFontCreateWithGraphicsFont(baseCGFont, textSize, transform, nullptr); 746 } 747 748 SkScalerContext_Mac::SkScalerContext_Mac(SkTypeface_Mac* typeface, 749 const SkDescriptor* desc) 750 : INHERITED(typeface, desc) 751 , fFBoundingBoxes() 752 , fFBoundingBoxesGlyphOffset(0) 753 , fGeneratedFBoundingBoxes(false) 754 , fDoSubPosition(SkToBool(fRec.fFlags & kSubpixelPositioning_Flag)) 755 , fVertical(SkToBool(fRec.fFlags & kVertical_Flag)) 756 757 { 758 AUTO_CG_LOCK(); 759 760 CTFontRef ctFont = typeface->fFontRef.get(); 761 CFIndex numGlyphs = CTFontGetGlyphCount(ctFont); 762 SkASSERT(numGlyphs >= 1 && numGlyphs <= 0xFFFF); 763 fGlyphCount = SkToU16(numGlyphs); 764 765 // CT on (at least) 10.9 will size color glyphs down from the requested size, but not up. 766 // As a result, it is necessary to know the actual device size and request that. 767 SkVector scale; 768 SkMatrix skTransform; 769 fRec.computeMatrices(SkScalerContextRec::kVertical_PreMatrixScale, &scale, &skTransform, 770 nullptr, nullptr, &fFUnitMatrix); 771 fTransform = MatrixToCGAffineTransform(skTransform); 772 fInvTransform = CGAffineTransformInvert(fTransform); 773 774 // The transform contains everything except the requested text size. 775 // Some properties, like 'trak', are based on the text size (before applying the matrix). 776 CGFloat textSize = ScalarToCG(scale.y()); 777 fCTFont.reset(ctfont_create_exact_copy(ctFont, textSize, nullptr)); 778 fCGFont.reset(CTFontCopyGraphicsFont(fCTFont, nullptr)); 779 780 // The fUnitMatrix includes the text size (and em) as it is used to scale the raw font data. 781 SkScalar emPerFUnit = SkScalarInvert(SkIntToScalar(CGFontGetUnitsPerEm(fCGFont))); 782 fFUnitMatrix.preScale(emPerFUnit, -emPerFUnit); 783 } 784 785 /** This is an implementation of CTFontDrawGlyphs for 10.6; it was introduced in 10.7. */ 786 static void legacy_CTFontDrawGlyphs(CTFontRef, const CGGlyph glyphs[], const CGPoint points[], 787 size_t count, CGContextRef cg) { 788 CGContextShowGlyphsAtPositions(cg, glyphs, points, count); 789 } 790 791 typedef decltype(legacy_CTFontDrawGlyphs) CTFontDrawGlyphsProc; 792 793 static CTFontDrawGlyphsProc* choose_CTFontDrawGlyphs() { 794 if (void* real = dlsym(RTLD_DEFAULT, "CTFontDrawGlyphs")) { 795 return (CTFontDrawGlyphsProc*)real; 796 } 797 return &legacy_CTFontDrawGlyphs; 798 } 799 800 SK_DECLARE_STATIC_ONCE_PTR(CTFontDrawGlyphsProc, gCTFontDrawGlyphs); 801 802 CGRGBPixel* Offscreen::getCG(const SkScalerContext_Mac& context, const SkGlyph& glyph, 803 CGGlyph glyphID, size_t* rowBytesPtr, 804 bool generateA8FromLCD) { 805 auto ctFontDrawGlyphs = gCTFontDrawGlyphs.get(choose_CTFontDrawGlyphs); 806 807 if (!fRGBSpace) { 808 //It doesn't appear to matter what color space is specified. 809 //Regular blends and antialiased text are always (s*a + d*(1-a)) 810 //and smoothed text is always g=2.0. 811 fRGBSpace.reset(CGColorSpaceCreateDeviceRGB()); 812 } 813 814 // default to kBW_Format 815 bool doAA = false; 816 bool doLCD = false; 817 818 if (SkMask::kBW_Format != glyph.fMaskFormat) { 819 doLCD = true; 820 doAA = true; 821 } 822 823 // FIXME: lcd smoothed un-hinted rasterization unsupported. 824 if (!generateA8FromLCD && SkMask::kA8_Format == glyph.fMaskFormat) { 825 doLCD = false; 826 doAA = true; 827 } 828 829 // If this font might have color glyphs, disable LCD as there's no way to support it. 830 // CoreText doesn't tell us which format it ended up using, so we can't detect it. 831 // A8 will end up black on transparent, but TODO: we can detect gray and set to A8. 832 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { 833 doLCD = false; 834 } 835 836 size_t rowBytes = fSize.fWidth * sizeof(CGRGBPixel); 837 if (!fCG || fSize.fWidth < glyph.fWidth || fSize.fHeight < glyph.fHeight) { 838 if (fSize.fWidth < glyph.fWidth) { 839 fSize.fWidth = RoundSize(glyph.fWidth); 840 } 841 if (fSize.fHeight < glyph.fHeight) { 842 fSize.fHeight = RoundSize(glyph.fHeight); 843 } 844 845 rowBytes = fSize.fWidth * sizeof(CGRGBPixel); 846 void* image = fImageStorage.reset(rowBytes * fSize.fHeight); 847 const CGImageAlphaInfo alpha = (SkMask::kARGB32_Format == glyph.fMaskFormat) 848 ? kCGImageAlphaPremultipliedFirst 849 : kCGImageAlphaNoneSkipFirst; 850 const CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host | alpha; 851 fCG.reset(CGBitmapContextCreate(image, fSize.fWidth, fSize.fHeight, 8, 852 rowBytes, fRGBSpace, bitmapInfo)); 853 854 // Skia handles quantization and subpixel positioning, 855 // so disable quantization and enabe subpixel positioning in CG. 856 CGContextSetAllowsFontSubpixelQuantization(fCG, false); 857 CGContextSetShouldSubpixelQuantizeFonts(fCG, false); 858 859 // Because CG always draws from the horizontal baseline, 860 // if there is a non-integral translation from the horizontal origin to the vertical origin, 861 // then CG cannot draw the glyph in the correct location without subpixel positioning. 862 CGContextSetAllowsFontSubpixelPositioning(fCG, true); 863 CGContextSetShouldSubpixelPositionFonts(fCG, true); 864 865 CGContextSetTextDrawingMode(fCG, kCGTextFill); 866 867 // Draw black on white to create mask. (Special path exists to speed this up in CG.) 868 CGContextSetGrayFillColor(fCG, 0.0f, 1.0f); 869 870 // force our checks below to happen 871 fDoAA = !doAA; 872 fDoLCD = !doLCD; 873 874 if (legacy_CTFontDrawGlyphs == ctFontDrawGlyphs) { 875 // CTFontDrawGlyphs will apply the font, font size, and font matrix to the CGContext. 876 // Our 'fake' one does not, so set up the CGContext here. 877 CGContextSetFont(fCG, context.fCGFont); 878 CGContextSetFontSize(fCG, CTFontGetSize(context.fCTFont)); 879 } 880 CGContextSetTextMatrix(fCG, context.fTransform); 881 } 882 883 if (fDoAA != doAA) { 884 CGContextSetShouldAntialias(fCG, doAA); 885 fDoAA = doAA; 886 } 887 if (fDoLCD != doLCD) { 888 CGContextSetShouldSmoothFonts(fCG, doLCD); 889 fDoLCD = doLCD; 890 } 891 892 CGRGBPixel* image = (CGRGBPixel*)fImageStorage.get(); 893 // skip rows based on the glyph's height 894 image += (fSize.fHeight - glyph.fHeight) * fSize.fWidth; 895 896 // Erase to white (or transparent black if it's a color glyph, to not composite against white). 897 uint32_t bgColor = (SkMask::kARGB32_Format != glyph.fMaskFormat) ? 0xFFFFFFFF : 0x00000000; 898 sk_memset_rect32(image, bgColor, glyph.fWidth, glyph.fHeight, rowBytes); 899 900 float subX = 0; 901 float subY = 0; 902 if (context.fDoSubPosition) { 903 subX = SkFixedToFloat(glyph.getSubXFixed()); 904 subY = SkFixedToFloat(glyph.getSubYFixed()); 905 } 906 907 // CoreText and CoreGraphics always draw using the horizontal baseline origin. 908 if (context.fVertical) { 909 SkPoint offset; 910 context.getVerticalOffset(glyphID, &offset); 911 subX += offset.fX; 912 subY += offset.fY; 913 } 914 915 CGPoint point = CGPointMake(-glyph.fLeft + subX, glyph.fTop + glyph.fHeight - subY); 916 // Prior to 10.10, CTFontDrawGlyphs acted like CGContextShowGlyphsAtPositions and took 917 // 'positions' which are in text space. The glyph location (in device space) must be 918 // mapped into text space, so that CG can convert it back into device space. 919 // In 10.10.1, this is handled directly inCTFontDrawGlyphs. 920 // 921 // However, in 10.10.2 color glyphs no longer rotate based on the font transform. 922 // So always make the font transform identity and place the transform on the context. 923 point = CGPointApplyAffineTransform(point, context.fInvTransform); 924 925 ctFontDrawGlyphs(context.fCTFont, &glyphID, &point, 1, fCG); 926 927 SkASSERT(rowBytesPtr); 928 *rowBytesPtr = rowBytes; 929 return image; 930 } 931 932 void SkScalerContext_Mac::getVerticalOffset(CGGlyph glyphID, SkPoint* offset) const { 933 // Snow Leopard returns cgVertOffset in completely un-transformed FUnits (em space, y up). 934 // Lion and Leopard return cgVertOffset in CG units (pixels, y up). 935 CGSize cgVertOffset; 936 CTFontGetVerticalTranslationsForGlyphs(fCTFont, &glyphID, &cgVertOffset, 1); 937 if (isSnowLeopard()) { 938 SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOffset.height) }; 939 // From FUnits (em space, y up) to SkGlyph units (pixels, y down). 940 fFUnitMatrix.mapPoints(&skVertOffset, 1); 941 *offset = skVertOffset; 942 return; 943 } 944 cgVertOffset = CGSizeApplyAffineTransform(cgVertOffset, fTransform); 945 SkPoint skVertOffset = { CGToScalar(cgVertOffset.width), CGToScalar(cgVertOffset.height) }; 946 // From CG units (pixels, y up) to SkGlyph units (pixels, y down). 947 skVertOffset.fY = -skVertOffset.fY; 948 *offset = skVertOffset; 949 } 950 951 uint16_t SkScalerContext_Mac::getFBoundingBoxesGlyphOffset() { 952 if (fFBoundingBoxesGlyphOffset) { 953 return fFBoundingBoxesGlyphOffset; 954 } 955 fFBoundingBoxesGlyphOffset = fGlyphCount; // fallback for all fonts 956 AutoCGTable<SkOTTableHorizontalHeader> hheaTable(fCGFont); 957 if (hheaTable.fData) { 958 fFBoundingBoxesGlyphOffset = SkEndian_SwapBE16(hheaTable->numberOfHMetrics); 959 } 960 return fFBoundingBoxesGlyphOffset; 961 } 962 963 bool SkScalerContext_Mac::generateBBoxes() { 964 if (fGeneratedFBoundingBoxes) { 965 return SkToBool(fFBoundingBoxes.get()); 966 } 967 fGeneratedFBoundingBoxes = true; 968 969 AutoCGTable<SkOTTableHead> headTable(fCGFont); 970 if (!headTable.fData) { 971 return false; 972 } 973 974 AutoCGTable<SkOTTableIndexToLocation> locaTable(fCGFont); 975 if (!locaTable.fData) { 976 return false; 977 } 978 979 AutoCGTable<SkOTTableGlyph> glyfTable(fCGFont); 980 if (!glyfTable.fData) { 981 return false; 982 } 983 984 uint16_t entries = fGlyphCount - fFBoundingBoxesGlyphOffset; 985 fFBoundingBoxes.reset(entries); 986 987 SkOTTableHead::IndexToLocFormat locaFormat = headTable->indexToLocFormat; 988 SkOTTableGlyph::Iterator glyphDataIter(*glyfTable.fData, *locaTable.fData, locaFormat); 989 glyphDataIter.advance(fFBoundingBoxesGlyphOffset); 990 for (uint16_t boundingBoxesIndex = 0; boundingBoxesIndex < entries; ++boundingBoxesIndex) { 991 const SkOTTableGlyphData* glyphData = glyphDataIter.next(); 992 GlyphRect& rect = fFBoundingBoxes[boundingBoxesIndex]; 993 rect.fMinX = SkEndian_SwapBE16(glyphData->xMin); 994 rect.fMinY = SkEndian_SwapBE16(glyphData->yMin); 995 rect.fMaxX = SkEndian_SwapBE16(glyphData->xMax); 996 rect.fMaxY = SkEndian_SwapBE16(glyphData->yMax); 997 } 998 999 return true; 1000 } 1001 1002 unsigned SkScalerContext_Mac::generateGlyphCount(void) { 1003 return fGlyphCount; 1004 } 1005 1006 uint16_t SkScalerContext_Mac::generateCharToGlyph(SkUnichar uni) { 1007 AUTO_CG_LOCK(); 1008 1009 CGGlyph cgGlyph[2]; 1010 UniChar theChar[2]; // UniChar is a UTF-16 16-bit code unit. 1011 1012 // Get the glyph 1013 size_t numUniChar = SkUTF16_FromUnichar(uni, theChar); 1014 SkASSERT(sizeof(CGGlyph) <= sizeof(uint16_t)); 1015 1016 // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points: 1017 // When a surrogate pair is detected, the glyph index used is the index of the high surrogate. 1018 // It is documented that if a mapping is unavailable, the glyph will be set to 0. 1019 CTFontGetGlyphsForCharacters(fCTFont, theChar, cgGlyph, numUniChar); 1020 return cgGlyph[0]; 1021 } 1022 1023 void SkScalerContext_Mac::generateAdvance(SkGlyph* glyph) { 1024 this->generateMetrics(glyph); 1025 } 1026 1027 void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) { 1028 AUTO_CG_LOCK(); 1029 1030 const CGGlyph cgGlyph = (CGGlyph) glyph->getGlyphID(); 1031 glyph->zeroMetrics(); 1032 1033 // The following block produces cgAdvance in CG units (pixels, y up). 1034 CGSize cgAdvance; 1035 if (fVertical) { 1036 CTFontGetAdvancesForGlyphs(fCTFont, kCTFontVerticalOrientation, 1037 &cgGlyph, &cgAdvance, 1); 1038 // Vertical advances are returned as widths instead of heights. 1039 SkTSwap(cgAdvance.height, cgAdvance.width); 1040 cgAdvance.height = -cgAdvance.height; 1041 } else { 1042 CTFontGetAdvancesForGlyphs(fCTFont, kCTFontHorizontalOrientation, 1043 &cgGlyph, &cgAdvance, 1); 1044 } 1045 cgAdvance = CGSizeApplyAffineTransform(cgAdvance, fTransform); 1046 glyph->fAdvanceX = SkFloatToFixed_Check(cgAdvance.width); 1047 glyph->fAdvanceY = -SkFloatToFixed_Check(cgAdvance.height); 1048 1049 // The following produces skBounds in SkGlyph units (pixels, y down), 1050 // or returns early if skBounds would be empty. 1051 SkRect skBounds; 1052 1053 // On Mountain Lion, CTFontGetBoundingRectsForGlyphs with kCTFontVerticalOrientation and 1054 // CTFontGetVerticalTranslationsForGlyphs do not agree when using OTF CFF fonts. 1055 // For TTF fonts these two do agree and we can use CTFontGetBoundingRectsForGlyphs to get 1056 // the bounding box and CTFontGetVerticalTranslationsForGlyphs to then draw the glyph 1057 // inside that bounding box. However, with OTF CFF fonts this does not work. It appears that 1058 // CTFontGetBoundingRectsForGlyphs with kCTFontVerticalOrientation on OTF CFF fonts tries 1059 // to center the glyph along the vertical baseline and also perform some mysterious shift 1060 // along the baseline. CTFontGetVerticalTranslationsForGlyphs does not appear to perform 1061 // these steps. 1062 // 1063 // It is not known which is correct (or if either is correct). However, we must always draw 1064 // from the horizontal origin and must use CTFontGetVerticalTranslationsForGlyphs to draw. 1065 // As a result, we do not call CTFontGetBoundingRectsForGlyphs for vertical glyphs. 1066 1067 // On Snow Leopard, CTFontGetBoundingRectsForGlyphs ignores kCTFontVerticalOrientation and 1068 // returns horizontal bounds. 1069 1070 // On Lion and Mountain Lion, CTFontGetBoundingRectsForGlyphs has a bug which causes it to 1071 // return a bad value in cgBounds.origin.x for SFNT fonts whose hhea::numberOfHMetrics is 1072 // less than its maxp::numGlyphs. When this is the case we try to read the bounds from the 1073 // font directly. 1074 if ((isLion() || isMountainLion()) && 1075 (cgGlyph < fGlyphCount && cgGlyph >= getFBoundingBoxesGlyphOffset() && generateBBoxes())) 1076 { 1077 const GlyphRect& gRect = fFBoundingBoxes[cgGlyph - fFBoundingBoxesGlyphOffset]; 1078 if (gRect.fMinX >= gRect.fMaxX || gRect.fMinY >= gRect.fMaxY) { 1079 return; 1080 } 1081 skBounds = SkRect::MakeLTRB(gRect.fMinX, gRect.fMinY, gRect.fMaxX, gRect.fMaxY); 1082 // From FUnits (em space, y up) to SkGlyph units (pixels, y down). 1083 fFUnitMatrix.mapRect(&skBounds); 1084 1085 } else { 1086 // CTFontGetBoundingRectsForGlyphs produces cgBounds in CG units (pixels, y up). 1087 CGRect cgBounds; 1088 CTFontGetBoundingRectsForGlyphs(fCTFont, kCTFontHorizontalOrientation, 1089 &cgGlyph, &cgBounds, 1); 1090 cgBounds = CGRectApplyAffineTransform(cgBounds, fTransform); 1091 1092 // BUG? 1093 // 0x200B (zero-advance space) seems to return a huge (garbage) bounds, when 1094 // it should be empty. So, if we see a zero-advance, we check if it has an 1095 // empty path or not, and if so, we jam the bounds to 0. Hopefully a zero-advance 1096 // is rare, so we won't incur a big performance cost for this extra check. 1097 if (0 == cgAdvance.width && 0 == cgAdvance.height) { 1098 AutoCFRelease<CGPathRef> path(CTFontCreatePathForGlyph(fCTFont, cgGlyph, nullptr)); 1099 if (nullptr == path || CGPathIsEmpty(path)) { 1100 return; 1101 } 1102 } 1103 1104 if (CGRectIsEmpty_inline(cgBounds)) { 1105 return; 1106 } 1107 1108 // Convert cgBounds to SkGlyph units (pixels, y down). 1109 skBounds = SkRect::MakeXYWH(cgBounds.origin.x, -cgBounds.origin.y - cgBounds.size.height, 1110 cgBounds.size.width, cgBounds.size.height); 1111 } 1112 1113 if (fVertical) { 1114 // Due to all of the vertical bounds bugs, skBounds is always the horizontal bounds. 1115 // Convert these horizontal bounds into vertical bounds. 1116 SkPoint offset; 1117 getVerticalOffset(cgGlyph, &offset); 1118 skBounds.offset(offset); 1119 } 1120 1121 // Currently the bounds are based on being rendered at (0,0). 1122 // The top left must not move, since that is the base from which subpixel positioning is offset. 1123 if (fDoSubPosition) { 1124 skBounds.fRight += SkFixedToFloat(glyph->getSubXFixed()); 1125 skBounds.fBottom += SkFixedToFloat(glyph->getSubYFixed()); 1126 } 1127 1128 SkIRect skIBounds; 1129 skBounds.roundOut(&skIBounds); 1130 // Expand the bounds by 1 pixel, to give CG room for anti-aliasing. 1131 // Note that this outset is to allow room for LCD smoothed glyphs. However, the correct outset 1132 // is not currently known, as CG dilates the outlines by some percentage. 1133 // Note that if this context is A8 and not back-forming from LCD, there is no need to outset. 1134 skIBounds.outset(1, 1); 1135 glyph->fLeft = SkToS16(skIBounds.fLeft); 1136 glyph->fTop = SkToS16(skIBounds.fTop); 1137 glyph->fWidth = SkToU16(skIBounds.width()); 1138 glyph->fHeight = SkToU16(skIBounds.height()); 1139 } 1140 1141 #include "SkColorPriv.h" 1142 1143 static void build_power_table(uint8_t table[]) { 1144 for (int i = 0; i < 256; i++) { 1145 float x = i / 255.f; 1146 int xx = SkScalarRoundToInt(x * x * 255); 1147 table[i] = SkToU8(xx); 1148 } 1149 } 1150 1151 /** 1152 * This will invert the gamma applied by CoreGraphics, so we can get linear 1153 * values. 1154 * 1155 * CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value. 1156 * The color space used does not appear to affect this choice. 1157 */ 1158 static const uint8_t* getInverseGammaTableCoreGraphicSmoothing() { 1159 static bool gInited; 1160 static uint8_t gTableCoreGraphicsSmoothing[256]; 1161 if (!gInited) { 1162 build_power_table(gTableCoreGraphicsSmoothing); 1163 gInited = true; 1164 } 1165 return gTableCoreGraphicsSmoothing; 1166 } 1167 1168 static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) { 1169 while (count > 0) { 1170 uint8_t mask = 0; 1171 for (int i = 7; i >= 0; --i) { 1172 mask |= ((CGRGBPixel_getAlpha(*src++) >> 7) ^ 0x1) << i; 1173 if (0 == --count) { 1174 break; 1175 } 1176 } 1177 *dst++ = mask; 1178 } 1179 } 1180 1181 template<bool APPLY_PREBLEND> 1182 static inline uint8_t rgb_to_a8(CGRGBPixel rgb, const uint8_t* table8) { 1183 U8CPU r = 0xFF - ((rgb >> 16) & 0xFF); 1184 U8CPU g = 0xFF - ((rgb >> 8) & 0xFF); 1185 U8CPU b = 0xFF - ((rgb >> 0) & 0xFF); 1186 U8CPU lum = sk_apply_lut_if<APPLY_PREBLEND>(SkComputeLuminance(r, g, b), table8); 1187 #if SK_SHOW_TEXT_BLIT_COVERAGE 1188 lum = SkTMax(lum, (U8CPU)0x30); 1189 #endif 1190 return lum; 1191 } 1192 template<bool APPLY_PREBLEND> 1193 static void rgb_to_a8(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, 1194 const SkGlyph& glyph, const uint8_t* table8) { 1195 const int width = glyph.fWidth; 1196 size_t dstRB = glyph.rowBytes(); 1197 uint8_t* SK_RESTRICT dst = (uint8_t*)glyph.fImage; 1198 1199 for (int y = 0; y < glyph.fHeight; y++) { 1200 for (int i = 0; i < width; ++i) { 1201 dst[i] = rgb_to_a8<APPLY_PREBLEND>(cgPixels[i], table8); 1202 } 1203 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1204 dst += dstRB; 1205 } 1206 } 1207 1208 template<bool APPLY_PREBLEND> 1209 static inline uint16_t rgb_to_lcd16(CGRGBPixel rgb, const uint8_t* tableR, 1210 const uint8_t* tableG, 1211 const uint8_t* tableB) { 1212 U8CPU r = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 16) & 0xFF), tableR); 1213 U8CPU g = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 8) & 0xFF), tableG); 1214 U8CPU b = sk_apply_lut_if<APPLY_PREBLEND>(0xFF - ((rgb >> 0) & 0xFF), tableB); 1215 #if SK_SHOW_TEXT_BLIT_COVERAGE 1216 r = SkTMax(r, (U8CPU)0x30); 1217 g = SkTMax(g, (U8CPU)0x30); 1218 b = SkTMax(b, (U8CPU)0x30); 1219 #endif 1220 return SkPack888ToRGB16(r, g, b); 1221 } 1222 template<bool APPLY_PREBLEND> 1223 static void rgb_to_lcd16(const CGRGBPixel* SK_RESTRICT cgPixels, size_t cgRowBytes, const SkGlyph& glyph, 1224 const uint8_t* tableR, const uint8_t* tableG, const uint8_t* tableB) { 1225 const int width = glyph.fWidth; 1226 size_t dstRB = glyph.rowBytes(); 1227 uint16_t* SK_RESTRICT dst = (uint16_t*)glyph.fImage; 1228 1229 for (int y = 0; y < glyph.fHeight; y++) { 1230 for (int i = 0; i < width; i++) { 1231 dst[i] = rgb_to_lcd16<APPLY_PREBLEND>(cgPixels[i], tableR, tableG, tableB); 1232 } 1233 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1234 dst = (uint16_t*)((char*)dst + dstRB); 1235 } 1236 } 1237 1238 static SkPMColor cgpixels_to_pmcolor(CGRGBPixel rgb) { 1239 U8CPU a = (rgb >> 24) & 0xFF; 1240 U8CPU r = (rgb >> 16) & 0xFF; 1241 U8CPU g = (rgb >> 8) & 0xFF; 1242 U8CPU b = (rgb >> 0) & 0xFF; 1243 #if SK_SHOW_TEXT_BLIT_COVERAGE 1244 a = SkTMax(a, (U8CPU)0x30); 1245 #endif 1246 return SkPackARGB32(a, r, g, b); 1247 } 1248 1249 void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) { 1250 CGGlyph cgGlyph = (CGGlyph) glyph.getGlyphID(); 1251 1252 // FIXME: lcd smoothed un-hinted rasterization unsupported. 1253 bool generateA8FromLCD = fRec.getHinting() != SkPaint::kNo_Hinting; 1254 1255 // Draw the glyph 1256 size_t cgRowBytes; 1257 CGRGBPixel* cgPixels = fOffscreen.getCG(*this, glyph, cgGlyph, &cgRowBytes, generateA8FromLCD); 1258 if (cgPixels == nullptr) { 1259 return; 1260 } 1261 1262 // Fix the glyph 1263 const bool isLCD = isLCDFormat(glyph.fMaskFormat); 1264 if (isLCD || (glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && generateA8FromLCD)) { 1265 const uint8_t* table = getInverseGammaTableCoreGraphicSmoothing(); 1266 1267 //Note that the following cannot really be integrated into the 1268 //pre-blend, since we may not be applying the pre-blend; when we aren't 1269 //applying the pre-blend it means that a filter wants linear anyway. 1270 //Other code may also be applying the pre-blend, so we'd need another 1271 //one with this and one without. 1272 CGRGBPixel* addr = cgPixels; 1273 for (int y = 0; y < glyph.fHeight; ++y) { 1274 for (int x = 0; x < glyph.fWidth; ++x) { 1275 int r = (addr[x] >> 16) & 0xFF; 1276 int g = (addr[x] >> 8) & 0xFF; 1277 int b = (addr[x] >> 0) & 0xFF; 1278 addr[x] = (table[r] << 16) | (table[g] << 8) | table[b]; 1279 } 1280 addr = SkTAddOffset<CGRGBPixel>(addr, cgRowBytes); 1281 } 1282 } 1283 1284 // Convert glyph to mask 1285 switch (glyph.fMaskFormat) { 1286 case SkMask::kLCD16_Format: { 1287 if (fPreBlend.isApplicable()) { 1288 rgb_to_lcd16<true>(cgPixels, cgRowBytes, glyph, 1289 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1290 } else { 1291 rgb_to_lcd16<false>(cgPixels, cgRowBytes, glyph, 1292 fPreBlend.fR, fPreBlend.fG, fPreBlend.fB); 1293 } 1294 } break; 1295 case SkMask::kA8_Format: { 1296 if (fPreBlend.isApplicable()) { 1297 rgb_to_a8<true>(cgPixels, cgRowBytes, glyph, fPreBlend.fG); 1298 } else { 1299 rgb_to_a8<false>(cgPixels, cgRowBytes, glyph, fPreBlend.fG); 1300 } 1301 } break; 1302 case SkMask::kBW_Format: { 1303 const int width = glyph.fWidth; 1304 size_t dstRB = glyph.rowBytes(); 1305 uint8_t* dst = (uint8_t*)glyph.fImage; 1306 for (int y = 0; y < glyph.fHeight; y++) { 1307 cgpixels_to_bits(dst, cgPixels, width); 1308 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1309 dst += dstRB; 1310 } 1311 } break; 1312 case SkMask::kARGB32_Format: { 1313 const int width = glyph.fWidth; 1314 size_t dstRB = glyph.rowBytes(); 1315 SkPMColor* dst = (SkPMColor*)glyph.fImage; 1316 for (int y = 0; y < glyph.fHeight; y++) { 1317 for (int x = 0; x < width; ++x) { 1318 dst[x] = cgpixels_to_pmcolor(cgPixels[x]); 1319 } 1320 cgPixels = (CGRGBPixel*)((char*)cgPixels + cgRowBytes); 1321 dst = (SkPMColor*)((char*)dst + dstRB); 1322 } 1323 } break; 1324 default: 1325 SkDEBUGFAIL("unexpected mask format"); 1326 break; 1327 } 1328 } 1329 1330 /* 1331 * Our subpixel resolution is only 2 bits in each direction, so a scale of 4 1332 * seems sufficient, and possibly even correct, to allow the hinted outline 1333 * to be subpixel positioned. 1334 */ 1335 #define kScaleForSubPixelPositionHinting (4.0f) 1336 1337 void SkScalerContext_Mac::generatePath(const SkGlyph& glyph, SkPath* path) { 1338 AUTO_CG_LOCK(); 1339 1340 SkScalar scaleX = SK_Scalar1; 1341 SkScalar scaleY = SK_Scalar1; 1342 1343 CGAffineTransform xform = fTransform; 1344 /* 1345 * For subpixel positioning, we want to return an unhinted outline, so it 1346 * can be positioned nicely at fractional offsets. However, we special-case 1347 * if the baseline of the (horizontal) text is axis-aligned. In those cases 1348 * we want to retain hinting in the direction orthogonal to the baseline. 1349 * e.g. for horizontal baseline, we want to retain hinting in Y. 1350 * The way we remove hinting is to scale the font by some value (4) in that 1351 * direction, ask for the path, and then scale the path back down. 1352 */ 1353 if (fDoSubPosition) { 1354 SkMatrix m; 1355 fRec.getSingleMatrix(&m); 1356 1357 // start out by assuming that we want no hining in X and Y 1358 scaleX = scaleY = kScaleForSubPixelPositionHinting; 1359 // now see if we need to restore hinting for axis-aligned baselines 1360 switch (SkComputeAxisAlignmentForHText(m)) { 1361 case kX_SkAxisAlignment: 1362 scaleY = SK_Scalar1; // want hinting in the Y direction 1363 break; 1364 case kY_SkAxisAlignment: 1365 scaleX = SK_Scalar1; // want hinting in the X direction 1366 break; 1367 default: 1368 break; 1369 } 1370 1371 CGAffineTransform scale(CGAffineTransformMakeScale(ScalarToCG(scaleX), ScalarToCG(scaleY))); 1372 xform = CGAffineTransformConcat(fTransform, scale); 1373 } 1374 1375 CGGlyph cgGlyph = (CGGlyph)glyph.getGlyphID(); 1376 AutoCFRelease<CGPathRef> cgPath(CTFontCreatePathForGlyph(fCTFont, cgGlyph, &xform)); 1377 1378 path->reset(); 1379 if (cgPath != nullptr) { 1380 CGPathApply(cgPath, path, SkScalerContext_Mac::CTPathElement); 1381 } 1382 1383 if (fDoSubPosition) { 1384 SkMatrix m; 1385 m.setScale(SkScalarInvert(scaleX), SkScalarInvert(scaleY)); 1386 path->transform(m); 1387 } 1388 if (fVertical) { 1389 SkPoint offset; 1390 getVerticalOffset(cgGlyph, &offset); 1391 path->offset(offset.fX, offset.fY); 1392 } 1393 } 1394 1395 void SkScalerContext_Mac::generateFontMetrics(SkPaint::FontMetrics* metrics) { 1396 if (nullptr == metrics) { 1397 return; 1398 } 1399 1400 AUTO_CG_LOCK(); 1401 1402 CGRect theBounds = CTFontGetBoundingBox(fCTFont); 1403 1404 metrics->fTop = CGToScalar(-CGRectGetMaxY_inline(theBounds)); 1405 metrics->fAscent = CGToScalar(-CTFontGetAscent(fCTFont)); 1406 metrics->fDescent = CGToScalar( CTFontGetDescent(fCTFont)); 1407 metrics->fBottom = CGToScalar(-CGRectGetMinY_inline(theBounds)); 1408 metrics->fLeading = CGToScalar( CTFontGetLeading(fCTFont)); 1409 metrics->fAvgCharWidth = CGToScalar( CGRectGetWidth_inline(theBounds)); 1410 metrics->fXMin = CGToScalar( CGRectGetMinX_inline(theBounds)); 1411 metrics->fXMax = CGToScalar( CGRectGetMaxX_inline(theBounds)); 1412 metrics->fMaxCharWidth = metrics->fXMax - metrics->fXMin; 1413 metrics->fXHeight = CGToScalar( CTFontGetXHeight(fCTFont)); 1414 metrics->fCapHeight = CGToScalar( CTFontGetCapHeight(fCTFont)); 1415 metrics->fUnderlineThickness = CGToScalar( CTFontGetUnderlineThickness(fCTFont)); 1416 metrics->fUnderlinePosition = -CGToScalar( CTFontGetUnderlinePosition(fCTFont)); 1417 1418 metrics->fFlags |= SkPaint::FontMetrics::kUnderlineThinknessIsValid_Flag; 1419 metrics->fFlags |= SkPaint::FontMetrics::kUnderlinePositionIsValid_Flag; 1420 } 1421 1422 void SkScalerContext_Mac::CTPathElement(void *info, const CGPathElement *element) { 1423 SkPath* skPath = (SkPath*)info; 1424 1425 // Process the path element 1426 switch (element->type) { 1427 case kCGPathElementMoveToPoint: 1428 skPath->moveTo(element->points[0].x, -element->points[0].y); 1429 break; 1430 1431 case kCGPathElementAddLineToPoint: 1432 skPath->lineTo(element->points[0].x, -element->points[0].y); 1433 break; 1434 1435 case kCGPathElementAddQuadCurveToPoint: 1436 skPath->quadTo(element->points[0].x, -element->points[0].y, 1437 element->points[1].x, -element->points[1].y); 1438 break; 1439 1440 case kCGPathElementAddCurveToPoint: 1441 skPath->cubicTo(element->points[0].x, -element->points[0].y, 1442 element->points[1].x, -element->points[1].y, 1443 element->points[2].x, -element->points[2].y); 1444 break; 1445 1446 case kCGPathElementCloseSubpath: 1447 skPath->close(); 1448 break; 1449 1450 default: 1451 SkDEBUGFAIL("Unknown path element!"); 1452 break; 1453 } 1454 } 1455 1456 1457 /////////////////////////////////////////////////////////////////////////////// 1458 1459 // Returns nullptr on failure 1460 // Call must still manage its ownership of provider 1461 static SkTypeface* create_from_dataProvider(CGDataProviderRef provider) { 1462 AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider)); 1463 if (nullptr == cg) { 1464 return nullptr; 1465 } 1466 CTFontRef ct = CTFontCreateWithGraphicsFont(cg, 0, nullptr, nullptr); 1467 return ct ? NewFromFontRef(ct, nullptr, nullptr, true) : nullptr; 1468 } 1469 1470 // Web fonts added to the the CTFont registry do not return their character set. 1471 // Iterate through the font in this case. The existing caller caches the result, 1472 // so the performance impact isn't too bad. 1473 static void populate_glyph_to_unicode_slow(CTFontRef ctFont, CFIndex glyphCount, 1474 SkTDArray<SkUnichar>* glyphToUnicode) { 1475 glyphToUnicode->setCount(SkToInt(glyphCount)); 1476 SkUnichar* out = glyphToUnicode->begin(); 1477 sk_bzero(out, glyphCount * sizeof(SkUnichar)); 1478 UniChar unichar = 0; 1479 while (glyphCount > 0) { 1480 CGGlyph glyph; 1481 if (CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) { 1482 out[glyph] = unichar; 1483 --glyphCount; 1484 } 1485 if (++unichar == 0) { 1486 break; 1487 } 1488 } 1489 } 1490 1491 // Construct Glyph to Unicode table. 1492 // Unicode code points that require conjugate pairs in utf16 are not 1493 // supported. 1494 static void populate_glyph_to_unicode(CTFontRef ctFont, CFIndex glyphCount, 1495 SkTDArray<SkUnichar>* glyphToUnicode) { 1496 AutoCFRelease<CFCharacterSetRef> charSet(CTFontCopyCharacterSet(ctFont)); 1497 if (!charSet) { 1498 populate_glyph_to_unicode_slow(ctFont, glyphCount, glyphToUnicode); 1499 return; 1500 } 1501 1502 AutoCFRelease<CFDataRef> bitmap(CFCharacterSetCreateBitmapRepresentation(kCFAllocatorDefault, 1503 charSet)); 1504 if (!bitmap) { 1505 return; 1506 } 1507 CFIndex length = CFDataGetLength(bitmap); 1508 if (!length) { 1509 return; 1510 } 1511 if (length > 8192) { 1512 // TODO: Add support for Unicode above 0xFFFF 1513 // Consider only the BMP portion of the Unicode character points. 1514 // The bitmap may contain other planes, up to plane 16. 1515 // See http://developer.apple.com/library/ios/#documentation/CoreFoundation/Reference/CFCharacterSetRef/Reference/reference.html 1516 length = 8192; 1517 } 1518 const UInt8* bits = CFDataGetBytePtr(bitmap); 1519 glyphToUnicode->setCount(SkToInt(glyphCount)); 1520 SkUnichar* out = glyphToUnicode->begin(); 1521 sk_bzero(out, glyphCount * sizeof(SkUnichar)); 1522 for (int i = 0; i < length; i++) { 1523 int mask = bits[i]; 1524 if (!mask) { 1525 continue; 1526 } 1527 for (int j = 0; j < 8; j++) { 1528 CGGlyph glyph; 1529 UniChar unichar = static_cast<UniChar>((i << 3) + j); 1530 if (mask & (1 << j) && CTFontGetGlyphsForCharacters(ctFont, &unichar, &glyph, 1)) { 1531 out[glyph] = unichar; 1532 } 1533 } 1534 } 1535 } 1536 1537 static bool getWidthAdvance(CTFontRef ctFont, int gId, int16_t* data) { 1538 CGSize advance; 1539 advance.width = 0; 1540 CGGlyph glyph = gId; 1541 CTFontGetAdvancesForGlyphs(ctFont, kCTFontHorizontalOrientation, &glyph, &advance, 1); 1542 *data = sk_float_round2int(advance.width); 1543 return true; 1544 } 1545 1546 /** Assumes src and dst are not nullptr. */ 1547 static void CFStringToSkString(CFStringRef src, SkString* dst) { 1548 // Reserve enough room for the worst-case string, 1549 // plus 1 byte for the trailing null. 1550 CFIndex length = CFStringGetMaximumSizeForEncoding(CFStringGetLength(src), 1551 kCFStringEncodingUTF8) + 1; 1552 dst->resize(length); 1553 CFStringGetCString(src, dst->writable_str(), length, kCFStringEncodingUTF8); 1554 // Resize to the actual UTF-8 length used, stripping the null character. 1555 dst->resize(strlen(dst->c_str())); 1556 } 1557 1558 SkAdvancedTypefaceMetrics* SkTypeface_Mac::onGetAdvancedTypefaceMetrics( 1559 PerGlyphInfo perGlyphInfo, 1560 const uint32_t* glyphIDs, 1561 uint32_t glyphIDsCount) const { 1562 1563 AUTO_CG_LOCK(); 1564 1565 CTFontRef originalCTFont = fFontRef.get(); 1566 AutoCFRelease<CTFontRef> ctFont(ctfont_create_exact_copy( 1567 originalCTFont, CTFontGetUnitsPerEm(originalCTFont), nullptr)); 1568 1569 SkAdvancedTypefaceMetrics* info = new SkAdvancedTypefaceMetrics; 1570 1571 { 1572 AutoCFRelease<CFStringRef> fontName(CTFontCopyPostScriptName(ctFont)); 1573 if (fontName.get()) { 1574 CFStringToSkString(fontName, &info->fFontName); 1575 } 1576 } 1577 1578 CFIndex glyphCount = CTFontGetGlyphCount(ctFont); 1579 info->fLastGlyphID = SkToU16(glyphCount - 1); 1580 info->fEmSize = CTFontGetUnitsPerEm(ctFont); 1581 1582 if (perGlyphInfo & kToUnicode_PerGlyphInfo) { 1583 populate_glyph_to_unicode(ctFont, glyphCount, &info->fGlyphToUnicode); 1584 } 1585 1586 // If it's not a truetype font, mark it as 'other'. Assume that TrueType 1587 // fonts always have both glyf and loca tables. At the least, this is what 1588 // sfntly needs to subset the font. CTFontCopyAttribute() does not always 1589 // succeed in determining this directly. 1590 if (!this->getTableSize('glyf') || !this->getTableSize('loca')) { 1591 return info; 1592 } 1593 1594 info->fType = SkAdvancedTypefaceMetrics::kTrueType_Font; 1595 CTFontSymbolicTraits symbolicTraits = CTFontGetSymbolicTraits(ctFont); 1596 if (symbolicTraits & kCTFontMonoSpaceTrait) { 1597 info->fStyle |= SkAdvancedTypefaceMetrics::kFixedPitch_Style; 1598 } 1599 if (symbolicTraits & kCTFontItalicTrait) { 1600 info->fStyle |= SkAdvancedTypefaceMetrics::kItalic_Style; 1601 } 1602 CTFontStylisticClass stylisticClass = symbolicTraits & kCTFontClassMaskTrait; 1603 if (stylisticClass >= kCTFontOldStyleSerifsClass && stylisticClass <= kCTFontSlabSerifsClass) { 1604 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 1605 } else if (stylisticClass & kCTFontScriptsClass) { 1606 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 1607 } 1608 info->fItalicAngle = (int16_t) CTFontGetSlantAngle(ctFont); 1609 info->fAscent = (int16_t) CTFontGetAscent(ctFont); 1610 info->fDescent = (int16_t) CTFontGetDescent(ctFont); 1611 info->fCapHeight = (int16_t) CTFontGetCapHeight(ctFont); 1612 CGRect bbox = CTFontGetBoundingBox(ctFont); 1613 1614 SkRect r; 1615 r.set( CGToScalar(CGRectGetMinX_inline(bbox)), // Left 1616 CGToScalar(CGRectGetMaxY_inline(bbox)), // Top 1617 CGToScalar(CGRectGetMaxX_inline(bbox)), // Right 1618 CGToScalar(CGRectGetMinY_inline(bbox))); // Bottom 1619 1620 r.roundOut(&(info->fBBox)); 1621 1622 // Figure out a good guess for StemV - Min width of i, I, !, 1. 1623 // This probably isn't very good with an italic font. 1624 int16_t min_width = SHRT_MAX; 1625 info->fStemV = 0; 1626 static const UniChar stem_chars[] = {'i', 'I', '!', '1'}; 1627 const size_t count = sizeof(stem_chars) / sizeof(stem_chars[0]); 1628 CGGlyph glyphs[count]; 1629 CGRect boundingRects[count]; 1630 if (CTFontGetGlyphsForCharacters(ctFont, stem_chars, glyphs, count)) { 1631 CTFontGetBoundingRectsForGlyphs(ctFont, kCTFontHorizontalOrientation, 1632 glyphs, boundingRects, count); 1633 for (size_t i = 0; i < count; i++) { 1634 int16_t width = (int16_t) boundingRects[i].size.width; 1635 if (width > 0 && width < min_width) { 1636 min_width = width; 1637 info->fStemV = min_width; 1638 } 1639 } 1640 } 1641 1642 if (perGlyphInfo & kHAdvance_PerGlyphInfo) { 1643 if (info->fStyle & SkAdvancedTypefaceMetrics::kFixedPitch_Style) { 1644 skia_advanced_typeface_metrics_utils::appendRange(&info->fGlyphWidths, 0); 1645 info->fGlyphWidths->fAdvance.append(1, &min_width); 1646 skia_advanced_typeface_metrics_utils::finishRange(info->fGlyphWidths.get(), 0, 1647 SkAdvancedTypefaceMetrics::WidthRange::kDefault); 1648 } else { 1649 info->fGlyphWidths.reset( 1650 skia_advanced_typeface_metrics_utils::getAdvanceData(ctFont.get(), 1651 SkToInt(glyphCount), 1652 glyphIDs, 1653 glyphIDsCount, 1654 &getWidthAdvance)); 1655 } 1656 } 1657 return info; 1658 } 1659 1660 /////////////////////////////////////////////////////////////////////////////// 1661 1662 static SK_SFNT_ULONG get_font_type_tag(const SkTypeface_Mac* typeface) { 1663 CTFontRef ctFont = typeface->fFontRef.get(); 1664 AutoCFRelease<CFNumberRef> fontFormatRef( 1665 static_cast<CFNumberRef>(CTFontCopyAttribute(ctFont, kCTFontFormatAttribute))); 1666 if (!fontFormatRef) { 1667 return 0; 1668 } 1669 1670 SInt32 fontFormatValue; 1671 if (!CFNumberGetValue(fontFormatRef, kCFNumberSInt32Type, &fontFormatValue)) { 1672 return 0; 1673 } 1674 1675 switch (fontFormatValue) { 1676 case kCTFontFormatOpenTypePostScript: 1677 return SkSFNTHeader::fontType_OpenTypeCFF::TAG; 1678 case kCTFontFormatOpenTypeTrueType: 1679 return SkSFNTHeader::fontType_WindowsTrueType::TAG; 1680 case kCTFontFormatTrueType: 1681 return SkSFNTHeader::fontType_MacTrueType::TAG; 1682 case kCTFontFormatPostScript: 1683 return SkSFNTHeader::fontType_PostScript::TAG; 1684 case kCTFontFormatBitmap: 1685 return SkSFNTHeader::fontType_MacTrueType::TAG; 1686 case kCTFontFormatUnrecognized: 1687 default: 1688 //CT seems to be unreliable in being able to obtain the type, 1689 //even if all we want is the first four bytes of the font resource. 1690 //Just the presence of the FontForge 'FFTM' table seems to throw it off. 1691 return SkSFNTHeader::fontType_WindowsTrueType::TAG; 1692 } 1693 } 1694 1695 SkStreamAsset* SkTypeface_Mac::onOpenStream(int* ttcIndex) const { 1696 SK_SFNT_ULONG fontType = get_font_type_tag(this); 1697 if (0 == fontType) { 1698 return nullptr; 1699 } 1700 1701 // get table tags 1702 int numTables = this->countTables(); 1703 SkTDArray<SkFontTableTag> tableTags; 1704 tableTags.setCount(numTables); 1705 this->getTableTags(tableTags.begin()); 1706 1707 // calc total size for font, save sizes 1708 SkTDArray<size_t> tableSizes; 1709 size_t totalSize = sizeof(SkSFNTHeader) + sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables; 1710 for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) { 1711 size_t tableSize = this->getTableSize(tableTags[tableIndex]); 1712 totalSize += (tableSize + 3) & ~3; 1713 *tableSizes.append() = tableSize; 1714 } 1715 1716 // reserve memory for stream, and zero it (tables must be zero padded) 1717 SkMemoryStream* stream = new SkMemoryStream(totalSize); 1718 char* dataStart = (char*)stream->getMemoryBase(); 1719 sk_bzero(dataStart, totalSize); 1720 char* dataPtr = dataStart; 1721 1722 // compute font header entries 1723 uint16_t entrySelector = 0; 1724 uint16_t searchRange = 1; 1725 while (searchRange < numTables >> 1) { 1726 entrySelector++; 1727 searchRange <<= 1; 1728 } 1729 searchRange <<= 4; 1730 uint16_t rangeShift = (numTables << 4) - searchRange; 1731 1732 // write font header 1733 SkSFNTHeader* header = (SkSFNTHeader*)dataPtr; 1734 header->fontType = fontType; 1735 header->numTables = SkEndian_SwapBE16(numTables); 1736 header->searchRange = SkEndian_SwapBE16(searchRange); 1737 header->entrySelector = SkEndian_SwapBE16(entrySelector); 1738 header->rangeShift = SkEndian_SwapBE16(rangeShift); 1739 dataPtr += sizeof(SkSFNTHeader); 1740 1741 // write tables 1742 SkSFNTHeader::TableDirectoryEntry* entry = (SkSFNTHeader::TableDirectoryEntry*)dataPtr; 1743 dataPtr += sizeof(SkSFNTHeader::TableDirectoryEntry) * numTables; 1744 for (int tableIndex = 0; tableIndex < numTables; ++tableIndex) { 1745 size_t tableSize = tableSizes[tableIndex]; 1746 this->getTableData(tableTags[tableIndex], 0, tableSize, dataPtr); 1747 entry->tag = SkEndian_SwapBE32(tableTags[tableIndex]); 1748 entry->checksum = SkEndian_SwapBE32(SkOTUtils::CalcTableChecksum((SK_OT_ULONG*)dataPtr, 1749 tableSize)); 1750 entry->offset = SkEndian_SwapBE32(SkToU32(dataPtr - dataStart)); 1751 entry->logicalLength = SkEndian_SwapBE32(SkToU32(tableSize)); 1752 1753 dataPtr += (tableSize + 3) & ~3; 1754 ++entry; 1755 } 1756 1757 *ttcIndex = 0; 1758 return stream; 1759 } 1760 1761 struct NonDefaultAxesContext { 1762 SkFixed* axisValue; 1763 CFArrayRef cgAxes; 1764 }; 1765 static void set_non_default_axes(CFTypeRef key, CFTypeRef value, void* context) { 1766 NonDefaultAxesContext* self = static_cast<NonDefaultAxesContext*>(context); 1767 1768 if (CFGetTypeID(key) != CFStringGetTypeID() || CFGetTypeID(value) != CFNumberGetTypeID()) { 1769 return; 1770 } 1771 1772 // The key is a CFString which is a string from the 'name' table. 1773 // Search the cgAxes for an axis with this name, and use its index to store the value. 1774 CFIndex keyIndex = -1; 1775 CFStringRef keyString = static_cast<CFStringRef>(key); 1776 for (CFIndex i = 0; i < CFArrayGetCount(self->cgAxes); ++i) { 1777 CFTypeRef cgAxis = CFArrayGetValueAtIndex(self->cgAxes, i); 1778 if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) { 1779 continue; 1780 } 1781 1782 CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis); 1783 CFTypeRef cgAxisName = CFDictionaryGetValue(cgAxisDict, kCGFontVariationAxisName); 1784 if (!cgAxisName || CFGetTypeID(cgAxisName) != CFStringGetTypeID()) { 1785 continue; 1786 } 1787 CFStringRef cgAxisNameString = static_cast<CFStringRef>(cgAxisName); 1788 if (CFStringCompare(keyString, cgAxisNameString, 0) == kCFCompareEqualTo) { 1789 keyIndex = i; 1790 break; 1791 } 1792 } 1793 if (keyIndex == -1) { 1794 return; 1795 } 1796 1797 CFNumberRef valueNumber = static_cast<CFNumberRef>(value); 1798 double valueDouble; 1799 if (!CFNumberGetValue(valueNumber, kCFNumberDoubleType, &valueDouble) || 1800 valueDouble < SkFixedToDouble(SK_FixedMin) || SkFixedToDouble(SK_FixedMax) < valueDouble) 1801 { 1802 return; 1803 } 1804 self->axisValue[keyIndex] = SkDoubleToFixed(valueDouble); 1805 } 1806 static bool get_variations(CTFontRef fFontRef, CFIndex* cgAxisCount, 1807 SkAutoSTMalloc<4, SkFixed>* axisValues) 1808 { 1809 // CTFontCopyVariationAxes and CTFontCopyVariation do not work when applied to fonts which 1810 // started life with CGFontCreateWithDataProvider (they simply always return nullptr). 1811 // As a result, we are limited to CGFontCopyVariationAxes and CGFontCopyVariations. 1812 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, nullptr)); 1813 1814 AutoCFRelease<CFDictionaryRef> cgVariations(CGFontCopyVariations(cgFont)); 1815 // If a font has no variations CGFontCopyVariations returns nullptr (instead of an empty dict). 1816 if (!cgVariations.get()) { 1817 return false; 1818 } 1819 1820 AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cgFont)); 1821 *cgAxisCount = CFArrayGetCount(cgAxes); 1822 axisValues->reset(*cgAxisCount); 1823 1824 // Set all of the axes to their default values. 1825 // Fail if any default value cannot be determined. 1826 for (CFIndex i = 0; i < *cgAxisCount; ++i) { 1827 CFTypeRef cgAxis = CFArrayGetValueAtIndex(cgAxes, i); 1828 if (CFGetTypeID(cgAxis) != CFDictionaryGetTypeID()) { 1829 return false; 1830 } 1831 1832 CFDictionaryRef cgAxisDict = static_cast<CFDictionaryRef>(cgAxis); 1833 CFTypeRef axisDefaultValue = CFDictionaryGetValue(cgAxisDict, 1834 kCGFontVariationAxisDefaultValue); 1835 if (!axisDefaultValue || CFGetTypeID(axisDefaultValue) != CFNumberGetTypeID()) { 1836 return false; 1837 } 1838 CFNumberRef axisDefaultValueNumber = static_cast<CFNumberRef>(axisDefaultValue); 1839 double axisDefaultValueDouble; 1840 if (!CFNumberGetValue(axisDefaultValueNumber, kCFNumberDoubleType, &axisDefaultValueDouble)) 1841 { 1842 return false; 1843 } 1844 if (axisDefaultValueDouble < SkFixedToDouble(SK_FixedMin) || 1845 SkFixedToDouble(SK_FixedMax) < axisDefaultValueDouble) 1846 { 1847 return false; 1848 } 1849 (*axisValues)[(int)i] = SkDoubleToFixed(axisDefaultValueDouble); 1850 } 1851 1852 // Override the default values with the given font's stated axis values. 1853 NonDefaultAxesContext c = { axisValues->get(), cgAxes.get() }; 1854 CFDictionaryApplyFunction(cgVariations, set_non_default_axes, &c); 1855 1856 return true; 1857 } 1858 SkFontData* SkTypeface_Mac::onCreateFontData() const { 1859 int index; 1860 SkAutoTDelete<SkStreamAsset> stream(this->onOpenStream(&index)); 1861 1862 CFIndex cgAxisCount; 1863 SkAutoSTMalloc<4, SkFixed> axisValues; 1864 if (get_variations(fFontRef, &cgAxisCount, &axisValues)) { 1865 return new SkFontData(stream.detach(), index, axisValues.get(), cgAxisCount); 1866 } 1867 return new SkFontData(stream.detach(), index, nullptr, 0); 1868 } 1869 1870 /////////////////////////////////////////////////////////////////////////////// 1871 /////////////////////////////////////////////////////////////////////////////// 1872 1873 int SkTypeface_Mac::onGetUPEM() const { 1874 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fFontRef, nullptr)); 1875 return CGFontGetUnitsPerEm(cgFont); 1876 } 1877 1878 SkTypeface::LocalizedStrings* SkTypeface_Mac::onCreateFamilyNameIterator() const { 1879 SkTypeface::LocalizedStrings* nameIter = 1880 SkOTUtils::LocalizedStrings_NameTable::CreateForFamilyNames(*this); 1881 if (nullptr == nameIter) { 1882 AutoCFRelease<CFStringRef> cfLanguage; 1883 AutoCFRelease<CFStringRef> cfFamilyName( 1884 CTFontCopyLocalizedName(fFontRef, kCTFontFamilyNameKey, &cfLanguage)); 1885 1886 SkString skLanguage; 1887 SkString skFamilyName; 1888 if (cfLanguage.get()) { 1889 CFStringToSkString(cfLanguage.get(), &skLanguage); 1890 } else { 1891 skLanguage = "und"; //undetermined 1892 } 1893 if (cfFamilyName.get()) { 1894 CFStringToSkString(cfFamilyName.get(), &skFamilyName); 1895 } 1896 1897 nameIter = new SkOTUtils::LocalizedStrings_SingleName(skFamilyName, skLanguage); 1898 } 1899 return nameIter; 1900 } 1901 1902 // If, as is the case with web fonts, the CTFont data isn't available, 1903 // the CGFont data may work. While the CGFont may always provide the 1904 // right result, leave the CTFont code path to minimize disruption. 1905 static CFDataRef copyTableFromFont(CTFontRef ctFont, SkFontTableTag tag) { 1906 CFDataRef data = CTFontCopyTable(ctFont, (CTFontTableTag) tag, 1907 kCTFontTableOptionNoOptions); 1908 if (nullptr == data) { 1909 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(ctFont, nullptr)); 1910 data = CGFontCopyTableForTag(cgFont, tag); 1911 } 1912 return data; 1913 } 1914 1915 int SkTypeface_Mac::onGetTableTags(SkFontTableTag tags[]) const { 1916 AutoCFRelease<CFArrayRef> cfArray(CTFontCopyAvailableTables(fFontRef, 1917 kCTFontTableOptionNoOptions)); 1918 if (nullptr == cfArray) { 1919 return 0; 1920 } 1921 int count = SkToInt(CFArrayGetCount(cfArray)); 1922 if (tags) { 1923 for (int i = 0; i < count; ++i) { 1924 uintptr_t fontTag = reinterpret_cast<uintptr_t>(CFArrayGetValueAtIndex(cfArray, i)); 1925 tags[i] = static_cast<SkFontTableTag>(fontTag); 1926 } 1927 } 1928 return count; 1929 } 1930 1931 size_t SkTypeface_Mac::onGetTableData(SkFontTableTag tag, size_t offset, 1932 size_t length, void* dstData) const { 1933 AutoCFRelease<CFDataRef> srcData(copyTableFromFont(fFontRef, tag)); 1934 if (nullptr == srcData) { 1935 return 0; 1936 } 1937 1938 size_t srcSize = CFDataGetLength(srcData); 1939 if (offset >= srcSize) { 1940 return 0; 1941 } 1942 if (length > srcSize - offset) { 1943 length = srcSize - offset; 1944 } 1945 if (dstData) { 1946 memcpy(dstData, CFDataGetBytePtr(srcData) + offset, length); 1947 } 1948 return length; 1949 } 1950 1951 SkScalerContext* SkTypeface_Mac::onCreateScalerContext(const SkDescriptor* desc) const { 1952 return new SkScalerContext_Mac(const_cast<SkTypeface_Mac*>(this), desc); 1953 } 1954 1955 void SkTypeface_Mac::onFilterRec(SkScalerContextRec* rec) const { 1956 if (rec->fFlags & SkScalerContext::kLCD_BGROrder_Flag || 1957 rec->fFlags & SkScalerContext::kLCD_Vertical_Flag) 1958 { 1959 rec->fMaskFormat = SkMask::kA8_Format; 1960 // Render the glyphs as close as possible to what was requested. 1961 // The above turns off subpixel rendering, but the user requested it. 1962 // Normal hinting will cause the A8 masks to be generated from CoreGraphics subpixel masks. 1963 // See comments below for more details. 1964 rec->setHinting(SkPaint::kNormal_Hinting); 1965 } 1966 1967 unsigned flagsWeDontSupport = SkScalerContext::kDevKernText_Flag | 1968 SkScalerContext::kForceAutohinting_Flag | 1969 SkScalerContext::kLCD_BGROrder_Flag | 1970 SkScalerContext::kLCD_Vertical_Flag; 1971 1972 rec->fFlags &= ~flagsWeDontSupport; 1973 1974 bool lcdSupport = supports_LCD(); 1975 1976 // Only two levels of hinting are supported. 1977 // kNo_Hinting means avoid CoreGraphics outline dilation. 1978 // kNormal_Hinting means CoreGraphics outline dilation is allowed. 1979 // If there is no lcd support, hinting (dilation) cannot be supported. 1980 SkPaint::Hinting hinting = rec->getHinting(); 1981 if (SkPaint::kSlight_Hinting == hinting || !lcdSupport) { 1982 hinting = SkPaint::kNo_Hinting; 1983 } else if (SkPaint::kFull_Hinting == hinting) { 1984 hinting = SkPaint::kNormal_Hinting; 1985 } 1986 rec->setHinting(hinting); 1987 1988 // FIXME: lcd smoothed un-hinted rasterization unsupported. 1989 // Tracked by http://code.google.com/p/skia/issues/detail?id=915 . 1990 // There is no current means to honor a request for unhinted lcd, 1991 // so arbitrarilly ignore the hinting request and honor lcd. 1992 1993 // Hinting and smoothing should be orthogonal, but currently they are not. 1994 // CoreGraphics has no API to influence hinting. However, its lcd smoothed 1995 // output is drawn from auto-dilated outlines (the amount of which is 1996 // determined by AppleFontSmoothing). Its regular anti-aliased output is 1997 // drawn from un-dilated outlines. 1998 1999 // The behavior of Skia is as follows: 2000 // [AA][no-hint]: generate AA using CoreGraphic's AA output. 2001 // [AA][yes-hint]: use CoreGraphic's LCD output and reduce it to a single 2002 // channel. This matches [LCD][yes-hint] in weight. 2003 // [LCD][no-hint]: curently unable to honor, and must pick which to respect. 2004 // Currenly side with LCD, effectively ignoring the hinting setting. 2005 // [LCD][yes-hint]: generate LCD using CoreGraphic's LCD output. 2006 2007 if (isLCDFormat(rec->fMaskFormat)) { 2008 if (lcdSupport) { 2009 //CoreGraphics creates 555 masks for smoothed text anyway. 2010 rec->fMaskFormat = SkMask::kLCD16_Format; 2011 rec->setHinting(SkPaint::kNormal_Hinting); 2012 } else { 2013 rec->fMaskFormat = SkMask::kA8_Format; 2014 } 2015 } 2016 2017 // CoreText provides no information as to whether a glyph will be color or not. 2018 // Fonts may mix outlines and bitmaps, so information is needed on a glyph by glyph basis. 2019 // If a font contains an 'sbix' table, consider it to be a color font, and disable lcd. 2020 if (fHasColorGlyphs) { 2021 rec->fMaskFormat = SkMask::kARGB32_Format; 2022 } 2023 2024 // Unhinted A8 masks (those not derived from LCD masks) must respect SK_GAMMA_APPLY_TO_A8. 2025 // All other masks can use regular gamma. 2026 if (SkMask::kA8_Format == rec->fMaskFormat && SkPaint::kNo_Hinting == hinting) { 2027 #ifndef SK_GAMMA_APPLY_TO_A8 2028 rec->ignorePreBlend(); 2029 #endif 2030 } else { 2031 //CoreGraphics dialates smoothed text as needed. 2032 rec->setContrast(0); 2033 } 2034 } 2035 2036 // we take ownership of the ref 2037 static const char* get_str(CFStringRef ref, SkString* str) { 2038 if (nullptr == ref) { 2039 return nullptr; 2040 } 2041 CFStringToSkString(ref, str); 2042 CFSafeRelease(ref); 2043 return str->c_str(); 2044 } 2045 2046 void SkTypeface_Mac::onGetFamilyName(SkString* familyName) const { 2047 get_str(CTFontCopyFamilyName(fFontRef), familyName); 2048 } 2049 2050 void SkTypeface_Mac::onGetFontDescriptor(SkFontDescriptor* desc, 2051 bool* isLocalStream) const { 2052 SkString tmpStr; 2053 2054 desc->setFamilyName(get_str(CTFontCopyFamilyName(fFontRef), &tmpStr)); 2055 desc->setFullName(get_str(CTFontCopyFullName(fFontRef), &tmpStr)); 2056 desc->setPostscriptName(get_str(CTFontCopyPostScriptName(fFontRef), &tmpStr)); 2057 *isLocalStream = fIsLocalStream; 2058 } 2059 2060 int SkTypeface_Mac::onCharsToGlyphs(const void* chars, Encoding encoding, 2061 uint16_t glyphs[], int glyphCount) const 2062 { 2063 // Undocumented behavior of CTFontGetGlyphsForCharacters with non-bmp code points: 2064 // When a surrogate pair is detected, the glyph index used is the index of the high surrogate. 2065 // It is documented that if a mapping is unavailable, the glyph will be set to 0. 2066 2067 SkAutoSTMalloc<1024, UniChar> charStorage; 2068 const UniChar* src; // UniChar is a UTF-16 16-bit code unit. 2069 int srcCount; 2070 switch (encoding) { 2071 case kUTF8_Encoding: { 2072 const char* utf8 = reinterpret_cast<const char*>(chars); 2073 UniChar* utf16 = charStorage.reset(2 * glyphCount); 2074 src = utf16; 2075 for (int i = 0; i < glyphCount; ++i) { 2076 SkUnichar uni = SkUTF8_NextUnichar(&utf8); 2077 utf16 += SkUTF16_FromUnichar(uni, utf16); 2078 } 2079 srcCount = SkToInt(utf16 - src); 2080 break; 2081 } 2082 case kUTF16_Encoding: { 2083 src = reinterpret_cast<const UniChar*>(chars); 2084 int extra = 0; 2085 for (int i = 0; i < glyphCount; ++i) { 2086 if (SkUTF16_IsHighSurrogate(src[i + extra])) { 2087 ++extra; 2088 } 2089 } 2090 srcCount = glyphCount + extra; 2091 break; 2092 } 2093 case kUTF32_Encoding: { 2094 const SkUnichar* utf32 = reinterpret_cast<const SkUnichar*>(chars); 2095 UniChar* utf16 = charStorage.reset(2 * glyphCount); 2096 src = utf16; 2097 for (int i = 0; i < glyphCount; ++i) { 2098 utf16 += SkUTF16_FromUnichar(utf32[i], utf16); 2099 } 2100 srcCount = SkToInt(utf16 - src); 2101 break; 2102 } 2103 } 2104 2105 // If glyphs is nullptr, CT still needs glyph storage for finding the first failure. 2106 // Also, if there are any non-bmp code points, the provided 'glyphs' storage will be inadequate. 2107 SkAutoSTMalloc<1024, uint16_t> glyphStorage; 2108 uint16_t* macGlyphs = glyphs; 2109 if (nullptr == macGlyphs || srcCount > glyphCount) { 2110 macGlyphs = glyphStorage.reset(srcCount); 2111 } 2112 2113 bool allEncoded = CTFontGetGlyphsForCharacters(fFontRef, src, macGlyphs, srcCount); 2114 2115 // If there were any non-bmp, then copy and compact. 2116 // If 'glyphs' is nullptr, then compact glyphStorage in-place. 2117 // If all are bmp and 'glyphs' is non-nullptr, 'glyphs' already contains the compact glyphs. 2118 // If some are non-bmp and 'glyphs' is non-nullptr, copy and compact into 'glyphs'. 2119 uint16_t* compactedGlyphs = glyphs; 2120 if (nullptr == compactedGlyphs) { 2121 compactedGlyphs = macGlyphs; 2122 } 2123 if (srcCount > glyphCount) { 2124 int extra = 0; 2125 for (int i = 0; i < glyphCount; ++i) { 2126 compactedGlyphs[i] = macGlyphs[i + extra]; 2127 if (SkUTF16_IsHighSurrogate(src[i + extra])) { 2128 ++extra; 2129 } 2130 } 2131 } 2132 2133 if (allEncoded) { 2134 return glyphCount; 2135 } 2136 2137 // If we got false, then we need to manually look for first failure. 2138 for (int i = 0; i < glyphCount; ++i) { 2139 if (0 == compactedGlyphs[i]) { 2140 return i; 2141 } 2142 } 2143 // Odd to get here, as we expected CT to have returned true up front. 2144 return glyphCount; 2145 } 2146 2147 int SkTypeface_Mac::onCountGlyphs() const { 2148 return SkToInt(CTFontGetGlyphCount(fFontRef)); 2149 } 2150 2151 /////////////////////////////////////////////////////////////////////////////// 2152 /////////////////////////////////////////////////////////////////////////////// 2153 2154 static bool find_desc_str(CTFontDescriptorRef desc, CFStringRef name, SkString* value) { 2155 AutoCFRelease<CFStringRef> ref((CFStringRef)CTFontDescriptorCopyAttribute(desc, name)); 2156 if (nullptr == ref.get()) { 2157 return false; 2158 } 2159 CFStringToSkString(ref, value); 2160 return true; 2161 } 2162 2163 #include "SkFontMgr.h" 2164 2165 static inline int sqr(int value) { 2166 SkASSERT(SkAbs32(value) < 0x7FFF); // check for overflow 2167 return value * value; 2168 } 2169 2170 // We normalize each axis (weight, width, italic) to be base-900 2171 static int compute_metric(const SkFontStyle& a, const SkFontStyle& b) { 2172 return sqr(a.weight() - b.weight()) + 2173 sqr((a.width() - b.width()) * 100) + 2174 sqr((a.isItalic() != b.isItalic()) * 900); 2175 } 2176 2177 static SkTypeface* createFromDesc(CFStringRef cfFamilyName, CTFontDescriptorRef desc) { 2178 NameStyle cacheRequest; 2179 SkString skFamilyName; 2180 CFStringToSkString(cfFamilyName, &skFamilyName); 2181 cacheRequest.fName = skFamilyName.c_str(); 2182 cacheRequest.fStyle = fontstyle_from_descriptor(desc); 2183 2184 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &cacheRequest); 2185 if (face) { 2186 return face; 2187 } 2188 2189 AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, nullptr)); 2190 if (!ctFont) { 2191 return nullptr; 2192 } 2193 2194 bool isFixedPitch; 2195 (void)computeStyleBits(ctFont, &isFixedPitch); 2196 2197 face = new SkTypeface_Mac(ctFont.detach(), nullptr, cacheRequest.fStyle, isFixedPitch, 2198 skFamilyName.c_str(), false); 2199 SkTypefaceCache::Add(face, face->fontStyle()); 2200 return face; 2201 } 2202 2203 class SkFontStyleSet_Mac : public SkFontStyleSet { 2204 public: 2205 SkFontStyleSet_Mac(CFStringRef familyName, CTFontDescriptorRef desc) 2206 : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, nullptr)) 2207 , fFamilyName(familyName) 2208 , fCount(0) { 2209 CFRetain(familyName); 2210 if (nullptr == fArray) { 2211 fArray = CFArrayCreate(nullptr, nullptr, 0, nullptr); 2212 } 2213 fCount = SkToInt(CFArrayGetCount(fArray)); 2214 } 2215 2216 virtual ~SkFontStyleSet_Mac() { 2217 CFRelease(fArray); 2218 CFRelease(fFamilyName); 2219 } 2220 2221 int count() override { 2222 return fCount; 2223 } 2224 2225 void getStyle(int index, SkFontStyle* style, SkString* name) override { 2226 SkASSERT((unsigned)index < (unsigned)fCount); 2227 CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, index); 2228 if (style) { 2229 *style = fontstyle_from_descriptor(desc); 2230 } 2231 if (name) { 2232 if (!find_desc_str(desc, kCTFontStyleNameAttribute, name)) { 2233 name->reset(); 2234 } 2235 } 2236 } 2237 2238 SkTypeface* createTypeface(int index) override { 2239 SkASSERT((unsigned)index < (unsigned)CFArrayGetCount(fArray)); 2240 CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, index); 2241 2242 return createFromDesc(fFamilyName, desc); 2243 } 2244 2245 SkTypeface* matchStyle(const SkFontStyle& pattern) override { 2246 if (0 == fCount) { 2247 return nullptr; 2248 } 2249 return createFromDesc(fFamilyName, findMatchingDesc(pattern)); 2250 } 2251 2252 private: 2253 CFArrayRef fArray; 2254 CFStringRef fFamilyName; 2255 int fCount; 2256 2257 CTFontDescriptorRef findMatchingDesc(const SkFontStyle& pattern) const { 2258 int bestMetric = SK_MaxS32; 2259 CTFontDescriptorRef bestDesc = nullptr; 2260 2261 for (int i = 0; i < fCount; ++i) { 2262 CTFontDescriptorRef desc = (CTFontDescriptorRef)CFArrayGetValueAtIndex(fArray, i); 2263 int metric = compute_metric(pattern, fontstyle_from_descriptor(desc)); 2264 if (0 == metric) { 2265 return desc; 2266 } 2267 if (metric < bestMetric) { 2268 bestMetric = metric; 2269 bestDesc = desc; 2270 } 2271 } 2272 SkASSERT(bestDesc); 2273 return bestDesc; 2274 } 2275 }; 2276 2277 class SkFontMgr_Mac : public SkFontMgr { 2278 CFArrayRef fNames; 2279 int fCount; 2280 2281 CFStringRef stringAt(int index) const { 2282 SkASSERT((unsigned)index < (unsigned)fCount); 2283 return (CFStringRef)CFArrayGetValueAtIndex(fNames, index); 2284 } 2285 2286 static SkFontStyleSet* CreateSet(CFStringRef cfFamilyName) { 2287 AutoCFRelease<CFMutableDictionaryRef> cfAttr( 2288 CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 2289 &kCFTypeDictionaryKeyCallBacks, 2290 &kCFTypeDictionaryValueCallBacks)); 2291 2292 CFDictionaryAddValue(cfAttr, kCTFontFamilyNameAttribute, cfFamilyName); 2293 2294 AutoCFRelease<CTFontDescriptorRef> desc( 2295 CTFontDescriptorCreateWithAttributes(cfAttr)); 2296 return new SkFontStyleSet_Mac(cfFamilyName, desc); 2297 } 2298 2299 public: 2300 SkFontMgr_Mac() 2301 : fNames(SkCTFontManagerCopyAvailableFontFamilyNames()) 2302 , fCount(fNames ? SkToInt(CFArrayGetCount(fNames)) : 0) {} 2303 2304 virtual ~SkFontMgr_Mac() { 2305 CFSafeRelease(fNames); 2306 } 2307 2308 protected: 2309 int onCountFamilies() const override { 2310 return fCount; 2311 } 2312 2313 void onGetFamilyName(int index, SkString* familyName) const override { 2314 if ((unsigned)index < (unsigned)fCount) { 2315 CFStringToSkString(this->stringAt(index), familyName); 2316 } else { 2317 familyName->reset(); 2318 } 2319 } 2320 2321 SkFontStyleSet* onCreateStyleSet(int index) const override { 2322 if ((unsigned)index >= (unsigned)fCount) { 2323 return nullptr; 2324 } 2325 return CreateSet(this->stringAt(index)); 2326 } 2327 2328 SkFontStyleSet* onMatchFamily(const char familyName[]) const override { 2329 AutoCFRelease<CFStringRef> cfName(make_CFString(familyName)); 2330 return CreateSet(cfName); 2331 } 2332 2333 virtual SkTypeface* onMatchFamilyStyle(const char familyName[], 2334 const SkFontStyle& fontStyle) const override { 2335 SkAutoTUnref<SkFontStyleSet> sset(this->matchFamily(familyName)); 2336 return sset->matchStyle(fontStyle); 2337 } 2338 2339 virtual SkTypeface* onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle&, 2340 const char* bcp47[], int bcp47Count, 2341 SkUnichar character) const override { 2342 return nullptr; 2343 } 2344 2345 virtual SkTypeface* onMatchFaceStyle(const SkTypeface* familyMember, 2346 const SkFontStyle&) const override { 2347 return nullptr; 2348 } 2349 2350 SkTypeface* onCreateFromData(SkData* data, int ttcIndex) const override { 2351 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromData(data)); 2352 if (nullptr == pr) { 2353 return nullptr; 2354 } 2355 return create_from_dataProvider(pr); 2356 } 2357 2358 SkTypeface* onCreateFromStream(SkStreamAsset* stream, int ttcIndex) const override { 2359 AutoCFRelease<CGDataProviderRef> pr(SkCreateDataProviderFromStream(stream)); 2360 if (nullptr == pr) { 2361 return nullptr; 2362 } 2363 return create_from_dataProvider(pr); 2364 } 2365 2366 static CFNumberRef get_tag_for_name(CFStringRef name, CFArrayRef ctAxes) { 2367 CFIndex ctAxisCount = CFArrayGetCount(ctAxes); 2368 for (int i = 0; i < ctAxisCount; ++i) { 2369 CFTypeRef ctAxisInfo = CFArrayGetValueAtIndex(ctAxes, i); 2370 if (CFDictionaryGetTypeID() != CFGetTypeID(ctAxisInfo)) { 2371 return nullptr; 2372 } 2373 CFDictionaryRef ctAxisInfoDict = static_cast<CFDictionaryRef>(ctAxisInfo); 2374 2375 CFTypeRef ctAxisName = CFDictionaryGetValue(ctAxisInfoDict, 2376 kCTFontVariationAxisNameKey); 2377 if (!ctAxisName || CFGetTypeID(ctAxisName) != CFStringGetTypeID()) { 2378 return nullptr; 2379 } 2380 2381 if (CFEqual(name, ctAxisName)) { 2382 CFTypeRef tag = CFDictionaryGetValue(ctAxisInfoDict, 2383 kCTFontVariationAxisIdentifierKey); 2384 if (!tag || CFGetTypeID(tag) != CFNumberGetTypeID()) { 2385 return nullptr; 2386 } 2387 return static_cast<CFNumberRef>(tag); 2388 } 2389 } 2390 return nullptr; 2391 } 2392 static CFDictionaryRef get_axes(CGFontRef cg, const FontParameters& params) { 2393 AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg)); 2394 if (!cgAxes) { 2395 return nullptr; 2396 } 2397 CFIndex axisCount = CFArrayGetCount(cgAxes); 2398 2399 // The CGFont variation data is keyed by name, and lacks the tag. 2400 // The CTFont variation data is keyed by tag, and also has the name. 2401 // We would like to work with CTFont variaitons, but creating a CTFont font with 2402 // CTFont variation dictionary runs into bugs. So use the CTFont variation data 2403 // to match names to tags to create the appropriate CGFont. 2404 AutoCFRelease<CTFontRef> ct(CTFontCreateWithGraphicsFont(cg, 0, nullptr, nullptr)); 2405 AutoCFRelease<CFArrayRef> ctAxes(CTFontCopyVariationAxes(ct)); 2406 if (!ctAxes || CFArrayGetCount(ctAxes) != axisCount) { 2407 return nullptr; 2408 } 2409 2410 int paramAxisCount; 2411 const FontParameters::Axis* paramAxes = params.getAxes(¶mAxisCount); 2412 2413 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount, 2414 &kCFTypeDictionaryKeyCallBacks, 2415 &kCFTypeDictionaryValueCallBacks); 2416 for (int i = 0; i < axisCount; ++i) { 2417 CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes, i); 2418 if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) { 2419 return nullptr; 2420 } 2421 CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo); 2422 2423 CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisName); 2424 if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) { 2425 return nullptr; 2426 } 2427 2428 CFNumberRef tagNumber = get_tag_for_name(static_cast<CFStringRef>(axisName), ctAxes); 2429 if (!tagNumber) { 2430 // Could not find a tag to go with the name of this index. 2431 // This would be a bug in CG/CT. 2432 continue; 2433 } 2434 int64_t tagLong; 2435 if (!CFNumberGetValue(tagNumber, kCFNumberSInt64Type, &tagLong)) { 2436 return nullptr; 2437 } 2438 2439 // The variation axes can be set to any value, but cg will effectively pin them. 2440 // Pin them here to normalize. 2441 CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMinValue); 2442 CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMaxValue); 2443 CFTypeRef def = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisDefaultValue); 2444 if (!min || CFGetTypeID(min) != CFNumberGetTypeID() || 2445 !max || CFGetTypeID(max) != CFNumberGetTypeID() || 2446 !def || CFGetTypeID(def) != CFNumberGetTypeID()) 2447 { 2448 return nullptr; 2449 } 2450 CFNumberRef minNumber = static_cast<CFNumberRef>(min); 2451 CFNumberRef maxNumber = static_cast<CFNumberRef>(max); 2452 CFNumberRef defNumber = static_cast<CFNumberRef>(def); 2453 double minDouble; 2454 double maxDouble; 2455 double defDouble; 2456 if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) || 2457 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble) || 2458 !CFNumberGetValue(defNumber, kCFNumberDoubleType, &defDouble)) 2459 { 2460 return nullptr; 2461 } 2462 2463 double value = defDouble; 2464 for (int j = 0; j < paramAxisCount; ++j) { 2465 if (paramAxes[j].fTag == tagLong) { 2466 value = SkTPin(SkScalarToDouble(paramAxes[j].fStyleValue),minDouble,maxDouble); 2467 break; 2468 } 2469 } 2470 CFNumberRef valueNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, 2471 &value); 2472 CFDictionaryAddValue(dict, axisName, valueNumber); 2473 CFRelease(valueNumber); 2474 } 2475 return dict; 2476 } 2477 SkTypeface* onCreateFromStream(SkStreamAsset* s, const FontParameters& params) const override { 2478 AutoCFRelease<CGDataProviderRef> provider(SkCreateDataProviderFromStream(s)); 2479 if (nullptr == provider) { 2480 return nullptr; 2481 } 2482 AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider)); 2483 if (nullptr == cg) { 2484 return nullptr; 2485 } 2486 2487 AutoCFRelease<CFDictionaryRef> cgVariations(get_axes(cg, params)); 2488 // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was 2489 // created from a data provider does not appear to have any ownership of the underlying 2490 // data. The original CGFontRef must be kept alive until the copy will no longer be used. 2491 AutoCFRelease<CGFontRef> cgVariant; 2492 if (cgVariations) { 2493 cgVariant.reset(CGFontCreateCopyWithVariations(cg, cgVariations)); 2494 } else { 2495 cgVariant.reset(cg.detach()); 2496 } 2497 2498 CTFontRef ct = CTFontCreateWithGraphicsFont(cgVariant, 0, nullptr, nullptr); 2499 if (!ct) { 2500 return nullptr; 2501 } 2502 return NewFromFontRef(ct, cg.detach(), nullptr, true); 2503 } 2504 2505 static CFDictionaryRef get_axes(CGFontRef cg, SkFontData* fontData) { 2506 AutoCFRelease<CFArrayRef> cgAxes(CGFontCopyVariationAxes(cg)); 2507 if (!cgAxes) { 2508 return nullptr; 2509 } 2510 2511 CFIndex axisCount = CFArrayGetCount(cgAxes); 2512 if (0 == axisCount || axisCount != fontData->getAxisCount()) { 2513 return nullptr; 2514 } 2515 2516 CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault, axisCount, 2517 &kCFTypeDictionaryKeyCallBacks, 2518 &kCFTypeDictionaryValueCallBacks); 2519 for (int i = 0; i < fontData->getAxisCount(); ++i) { 2520 CFTypeRef axisInfo = CFArrayGetValueAtIndex(cgAxes, i); 2521 if (CFDictionaryGetTypeID() != CFGetTypeID(axisInfo)) { 2522 return nullptr; 2523 } 2524 CFDictionaryRef axisInfoDict = static_cast<CFDictionaryRef>(axisInfo); 2525 2526 CFTypeRef axisName = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisName); 2527 if (!axisName || CFGetTypeID(axisName) != CFStringGetTypeID()) { 2528 return nullptr; 2529 } 2530 2531 // The variation axes can be set to any value, but cg will effectively pin them. 2532 // Pin them here to normalize. 2533 CFTypeRef min = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMinValue); 2534 CFTypeRef max = CFDictionaryGetValue(axisInfoDict, kCGFontVariationAxisMaxValue); 2535 if (!min || CFGetTypeID(min) != CFNumberGetTypeID() || 2536 !max || CFGetTypeID(max) != CFNumberGetTypeID()) 2537 { 2538 return nullptr; 2539 } 2540 CFNumberRef minNumber = static_cast<CFNumberRef>(min); 2541 CFNumberRef maxNumber = static_cast<CFNumberRef>(max); 2542 double minDouble; 2543 double maxDouble; 2544 if (!CFNumberGetValue(minNumber, kCFNumberDoubleType, &minDouble) || 2545 !CFNumberGetValue(maxNumber, kCFNumberDoubleType, &maxDouble)) 2546 { 2547 return nullptr; 2548 } 2549 double value = SkTPin(SkFixedToDouble(fontData->getAxis()[i]), minDouble, maxDouble); 2550 CFNumberRef valueNumber = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, 2551 &value); 2552 2553 CFDictionaryAddValue(dict, axisName, valueNumber); 2554 CFRelease(valueNumber); 2555 } 2556 return dict; 2557 } 2558 SkTypeface* onCreateFromFontData(SkFontData* data) const override { 2559 SkAutoTDelete<SkFontData> fontData(data); 2560 SkStreamAsset* stream = fontData->detachStream(); 2561 AutoCFRelease<CGDataProviderRef> provider(SkCreateDataProviderFromStream(stream)); 2562 if (nullptr == provider) { 2563 return nullptr; 2564 } 2565 AutoCFRelease<CGFontRef> cg(CGFontCreateWithDataProvider(provider)); 2566 if (nullptr == cg) { 2567 return nullptr; 2568 } 2569 2570 AutoCFRelease<CFDictionaryRef> cgVariations(get_axes(cg, fontData)); 2571 // The CGFontRef returned by CGFontCreateCopyWithVariations when the passed CGFontRef was 2572 // created from a data provider does not appear to have any ownership of the underlying 2573 // data. The original CGFontRef must be kept alive until the copy will no longer be used. 2574 AutoCFRelease<CGFontRef> cgVariant; 2575 if (cgVariations) { 2576 cgVariant.reset(CGFontCreateCopyWithVariations(cg, cgVariations)); 2577 } else { 2578 cgVariant.reset(cg.detach()); 2579 } 2580 2581 CTFontRef ct = CTFontCreateWithGraphicsFont(cgVariant, 0, nullptr, nullptr); 2582 if (!ct) { 2583 return nullptr; 2584 } 2585 return NewFromFontRef(ct, cg.detach(), nullptr, true); 2586 } 2587 2588 SkTypeface* onCreateFromFile(const char path[], int ttcIndex) const override { 2589 AutoCFRelease<CGDataProviderRef> pr(CGDataProviderCreateWithFilename(path)); 2590 if (nullptr == pr) { 2591 return nullptr; 2592 } 2593 return create_from_dataProvider(pr); 2594 } 2595 2596 virtual SkTypeface* onLegacyCreateTypeface(const char familyName[], 2597 unsigned styleBits) const override { 2598 2599 SkFontStyle style = SkFontStyle((SkTypeface::Style)styleBits); 2600 if (familyName) { 2601 familyName = map_css_names(familyName); 2602 } 2603 2604 if (!familyName || !*familyName) { 2605 familyName = FONT_DEFAULT_NAME; 2606 } 2607 2608 NameStyle cacheRequest = { familyName, style }; 2609 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &cacheRequest); 2610 2611 if (nullptr == face) { 2612 face = NewFromName(familyName, style); 2613 if (face) { 2614 SkTypefaceCache::Add(face, style); 2615 } else { 2616 face = GetDefaultFace(); 2617 face->ref(); 2618 } 2619 } 2620 return face; 2621 } 2622 }; 2623 2624 /////////////////////////////////////////////////////////////////////////////// 2625 2626 SkFontMgr* SkFontMgr::Factory() { return new SkFontMgr_Mac; } 2627 2628 #endif//defined(SK_BUILD_FOR_MAC) || defined(SK_BUILD_FOR_IOS) 2629