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