OLD | NEW |
---|---|
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkTypes.h" // Keep this before any #ifdef ... | 9 #include "SkTypes.h" // Keep this before any #ifdef ... |
10 | 10 |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 explicit AutoCFRelease(CFRef cfRef = NULL) : fCFRef(cfRef) { } | 85 explicit AutoCFRelease(CFRef cfRef = NULL) : fCFRef(cfRef) { } |
86 ~AutoCFRelease() { CFSafeRelease(fCFRef); } | 86 ~AutoCFRelease() { CFSafeRelease(fCFRef); } |
87 | 87 |
88 void reset(CFRef that = NULL) { | 88 void reset(CFRef that = NULL) { |
89 if (that != fCFRef) { | 89 if (that != fCFRef) { |
90 CFSafeRelease(fCFRef); | 90 CFSafeRelease(fCFRef); |
91 fCFRef = that; | 91 fCFRef = that; |
92 } | 92 } |
93 } | 93 } |
94 | 94 |
95 CFRef detach() { | |
96 CFRef self = fCFRef; | |
97 fCFRef = NULL; | |
98 return self; | |
99 } | |
100 | |
95 operator CFRef() const { return fCFRef; } | 101 operator CFRef() const { return fCFRef; } |
96 CFRef get() const { return fCFRef; } | 102 CFRef get() const { return fCFRef; } |
97 | 103 |
98 CFRef* operator&() { SkASSERT(fCFRef == NULL); return &fCFRef; } | 104 CFRef* operator&() { SkASSERT(fCFRef == NULL); return &fCFRef; } |
99 private: | 105 private: |
100 CFRef fCFRef; | 106 CFRef fCFRef; |
101 }; | 107 }; |
102 | 108 |
103 static CFStringRef make_CFString(const char str[]) { | 109 static CFStringRef make_CFString(const char str[]) { |
104 return CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8); | 110 return CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8); |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
401 } | 407 } |
402 if (traits & kCTFontItalicTrait) { | 408 if (traits & kCTFontItalicTrait) { |
403 style |= SkTypeface::kItalic; | 409 style |= SkTypeface::kItalic; |
404 } | 410 } |
405 if (isFixedPitch) { | 411 if (isFixedPitch) { |
406 *isFixedPitch = (traits & kCTFontMonoSpaceTrait) != 0; | 412 *isFixedPitch = (traits & kCTFontMonoSpaceTrait) != 0; |
407 } | 413 } |
408 return (SkTypeface::Style)style; | 414 return (SkTypeface::Style)style; |
409 } | 415 } |
410 | 416 |
411 static SkFontID CTFontRef_to_SkFontID(CTFontRef fontRef) { | |
412 SkFontID id = 0; | |
413 // CTFontGetPlatformFont and ATSFontRef are not supported on iOS, so we have to | |
414 // bracket this to be Mac only. | |
415 #ifdef SK_BUILD_FOR_MAC | |
416 ATSFontRef ats = CTFontGetPlatformFont(fontRef, NULL); | |
bungeman-skia
2015/05/04 18:34:05
This is known to cause a separate copy of the font
| |
417 id = (SkFontID)ats; | |
418 if (id != 0) { | |
419 id &= 0x3FFFFFFF; // make top two bits 00 | |
420 return id; | |
421 } | |
422 #endif | |
423 // CTFontGetPlatformFont returns NULL if the font is local | |
424 // (e.g., was created by a CSS3 @font-face rule). | |
425 AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fontRef, NULL)); | |
426 AutoCGTable<SkOTTableHead> headTable(cgFont); | |
427 if (headTable.fData) { | |
428 id = (SkFontID) headTable->checksumAdjustment; | |
429 id = (id & 0x3FFFFFFF) | 0x40000000; // make top two bits 01 | |
430 } | |
431 // well-formed fonts have checksums, but as a last resort, use the pointer. | |
432 if (id == 0) { | |
433 id = (SkFontID) (uintptr_t) fontRef; | |
434 id = (id & 0x3FFFFFFF) | 0x80000000; // make top two bits 10 | |
435 } | |
436 return id; | |
437 } | |
438 | |
439 #define WEIGHT_THRESHOLD ((SkFontStyle::kNormal_Weight + SkFontStyle::kBold_W eight)/2) | 417 #define WEIGHT_THRESHOLD ((SkFontStyle::kNormal_Weight + SkFontStyle::kBold_W eight)/2) |
440 | 418 |
441 // kCTFontColorGlyphsTrait was added in the Mac 10.7 and iPhone 4.3 SDKs. | 419 // kCTFontColorGlyphsTrait was added in the Mac 10.7 and iPhone 4.3 SDKs. |
442 // Being an enum value it is not guarded by version macros, but old SDKs must st ill be supported. | 420 // Being an enum value it is not guarded by version macros, but old SDKs must st ill be supported. |
443 #if defined(__MAC_10_7) || defined(__IPHONE_4_3) | 421 #if defined(__MAC_10_7) || defined(__IPHONE_4_3) |
444 static const uint32_t SkCTFontColorGlyphsTrait = kCTFontColorGlyphsTrait; | 422 static const uint32_t SkCTFontColorGlyphsTrait = kCTFontColorGlyphsTrait; |
445 #else | 423 #else |
446 static const uint32_t SkCTFontColorGlyphsTrait = (1 << 13); | 424 static const uint32_t SkCTFontColorGlyphsTrait = (1 << 13); |
447 #endif | 425 #endif |
448 | 426 |
449 class SkTypeface_Mac : public SkTypeface { | 427 class SkTypeface_Mac : public SkTypeface { |
450 public: | 428 public: |
451 SkTypeface_Mac(const SkFontStyle& fs, SkFontID fontID, bool isFixedPitch, | 429 SkTypeface_Mac(const SkFontStyle& fs, bool isFixedPitch, |
452 CTFontRef fontRef, const char requestedName[], bool isLocalSt ream) | 430 CTFontRef fontRef, const char requestedName[], bool isLocalSt ream) |
453 : SkTypeface(fs, fontID, isFixedPitch) | 431 : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch) |
454 , fRequestedName(requestedName) | 432 , fRequestedName(requestedName) |
455 , fFontRef(fontRef) // caller has already called CFRetain for us | 433 , fFontRef(fontRef) // caller has already called CFRetain for us |
456 , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontC olorGlyphsTrait)) | 434 , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontC olorGlyphsTrait)) |
457 , fIsLocalStream(isLocalStream) | 435 , fIsLocalStream(isLocalStream) |
458 { | 436 { |
459 SkASSERT(fontRef); | 437 SkASSERT(fontRef); |
460 } | 438 } |
461 | 439 |
462 SkString fRequestedName; | 440 SkString fRequestedName; |
463 AutoCFRelease<CTFontRef> fFontRef; | 441 AutoCFRelease<CTFontRef> fFontRef; |
(...skipping 16 matching lines...) Expand all Loading... | |
480 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], | 458 virtual int onCharsToGlyphs(const void* chars, Encoding, uint16_t glyphs[], |
481 int glyphCount) const override; | 459 int glyphCount) const override; |
482 int onCountGlyphs() const override; | 460 int onCountGlyphs() const override; |
483 | 461 |
484 private: | 462 private: |
485 bool fIsLocalStream; | 463 bool fIsLocalStream; |
486 | 464 |
487 typedef SkTypeface INHERITED; | 465 typedef SkTypeface INHERITED; |
488 }; | 466 }; |
489 | 467 |
468 /** Creates a typeface without searching the cache. Takes ownership of the CTFon tRef. */ | |
490 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isL ocalStream) { | 469 static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isL ocalStream) { |
491 SkASSERT(fontRef); | 470 SkASSERT(fontRef); |
492 bool isFixedPitch; | 471 bool isFixedPitch; |
493 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch)); | 472 SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch)); |
494 SkFontID fontID = CTFontRef_to_SkFontID(fontRef); | |
495 | 473 |
496 return new SkTypeface_Mac(style, fontID, isFixedPitch, fontRef, name, isLoca lStream); | 474 return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream) ; |
497 } | 475 } |
498 | 476 |
477 static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* cont ext) { | |
478 CTFontRef self = (CTFontRef)context; | |
479 CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef; | |
480 | |
481 return CFEqual(self, other); | |
482 } | |
483 | |
484 /** Creates a typeface from a name, searching the cache. */ | |
499 static SkTypeface* NewFromName(const char familyName[], const SkFontStyle& theSt yle) { | 485 static SkTypeface* NewFromName(const char familyName[], const SkFontStyle& theSt yle) { |
500 CTFontRef ctFont = NULL; | |
501 | |
502 CTFontSymbolicTraits ctFontTraits = 0; | 486 CTFontSymbolicTraits ctFontTraits = 0; |
503 if (theStyle.weight() >= SkFontStyle::kBold_Weight) { | 487 if (theStyle.weight() >= SkFontStyle::kBold_Weight) { |
504 ctFontTraits |= kCTFontBoldTrait; | 488 ctFontTraits |= kCTFontBoldTrait; |
505 } | 489 } |
506 if (theStyle.slant() != SkFontStyle::kUpright_Slant) { | 490 if (theStyle.slant() != SkFontStyle::kUpright_Slant) { |
507 ctFontTraits |= kCTFontItalicTrait; | 491 ctFontTraits |= kCTFontItalicTrait; |
508 } | 492 } |
509 | 493 |
510 //TODO: add weight width slant | 494 //TODO: add weight width slant |
511 | 495 |
512 // Create the font info | 496 // Create the font info |
513 AutoCFRelease<CFStringRef> cfFontName(make_CFString(familyName)); | 497 AutoCFRelease<CFStringRef> cfFontName(make_CFString(familyName)); |
514 | 498 |
515 AutoCFRelease<CFNumberRef> cfFontTraits( | 499 AutoCFRelease<CFNumberRef> cfFontTraits( |
516 CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTrai ts)); | 500 CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &ctFontTrai ts)); |
517 | 501 |
518 AutoCFRelease<CFMutableDictionaryRef> cfAttributes( | 502 AutoCFRelease<CFMutableDictionaryRef> cfAttributes( |
519 CFDictionaryCreateMutable(kCFAllocatorDefault, 0, | 503 CFDictionaryCreateMutable(kCFAllocatorDefault, 0, |
520 &kCFTypeDictionaryKeyCallBacks, | 504 &kCFTypeDictionaryKeyCallBacks, |
521 &kCFTypeDictionaryValueCallBacks)); | 505 &kCFTypeDictionaryValueCallBacks)); |
522 | 506 |
523 AutoCFRelease<CFMutableDictionaryRef> cfTraits( | 507 AutoCFRelease<CFMutableDictionaryRef> cfTraits( |
524 CFDictionaryCreateMutable(kCFAllocatorDefault, 0, | 508 CFDictionaryCreateMutable(kCFAllocatorDefault, 0, |
525 &kCFTypeDictionaryKeyCallBacks, | 509 &kCFTypeDictionaryKeyCallBacks, |
526 &kCFTypeDictionaryValueCallBacks)); | 510 &kCFTypeDictionaryValueCallBacks)); |
527 | 511 |
528 // Create the font | 512 if (!cfFontName || !cfFontTraits || !cfAttributes || !cfTraits) { |
529 if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cf Traits != NULL) { | 513 return NULL; |
530 CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits); | |
531 | |
532 CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontNam e); | |
533 CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits); | |
534 | |
535 AutoCFRelease<CTFontDescriptorRef> ctFontDesc( | |
536 CTFontDescriptorCreateWithAttributes(cfAttributes)); | |
537 | |
538 if (ctFontDesc != NULL) { | |
539 ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL); | |
540 } | |
541 } | 514 } |
542 | 515 |
543 return ctFont ? NewFromFontRef(ctFont, familyName, false) : NULL; | 516 CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits); |
517 | |
518 CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName); | |
519 CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits); | |
520 | |
521 AutoCFRelease<CTFontDescriptorRef> ctFontDesc( | |
522 CTFontDescriptorCreateWithAttributes(cfAttributes)); | |
523 if (!ctFontDesc) { | |
524 return NULL; | |
525 } | |
526 | |
527 AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(ctFontDesc, 0 , NULL)); | |
528 if (!ctFont) { | |
529 return NULL; | |
530 } | |
531 | |
532 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (voi d*)ctFont.get()); | |
533 if (face) { | |
534 face->ref(); | |
535 } else { | |
536 face = NewFromFontRef(ctFont.detach(), NULL, false); | |
537 SkTypefaceCache::Add(face, face->fontStyle()); | |
538 } | |
539 return face; | |
544 } | 540 } |
545 | 541 |
546 SK_DECLARE_STATIC_MUTEX(gGetDefaultFaceMutex); | 542 SK_DECLARE_STATIC_MUTEX(gGetDefaultFaceMutex); |
547 static SkTypeface* GetDefaultFace() { | 543 static SkTypeface* GetDefaultFace() { |
548 SkAutoMutexAcquire ma(gGetDefaultFaceMutex); | 544 SkAutoMutexAcquire ma(gGetDefaultFaceMutex); |
549 | 545 |
550 static SkTypeface* gDefaultFace; | 546 static SkTypeface* gDefaultFace; |
551 | 547 |
552 if (NULL == gDefaultFace) { | 548 if (NULL == gDefaultFace) { |
553 gDefaultFace = NewFromName(FONT_DEFAULT_NAME, SkFontStyle()); | 549 gDefaultFace = NewFromName(FONT_DEFAULT_NAME, SkFontStyle()); |
554 SkTypefaceCache::Add(gDefaultFace, SkFontStyle()); | 550 SkTypefaceCache::Add(gDefaultFace, SkFontStyle()); |
555 } | 551 } |
556 return gDefaultFace; | 552 return gDefaultFace; |
557 } | 553 } |
558 | 554 |
559 /////////////////////////////////////////////////////////////////////////////// | 555 /////////////////////////////////////////////////////////////////////////////// |
560 | 556 |
561 extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face); | 557 extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face); |
562 CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) { | 558 CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) { |
563 const SkTypeface_Mac* macface = (const SkTypeface_Mac*)face; | 559 const SkTypeface_Mac* macface = (const SkTypeface_Mac*)face; |
564 return macface ? macface->fFontRef.get() : NULL; | 560 return macface ? macface->fFontRef.get() : NULL; |
565 } | 561 } |
566 | 562 |
567 /* This function is visible on the outside. It first searches the cache, and if | 563 /* This function is visible on the outside. It first searches the cache, and if |
568 * not found, returns a new entry (after adding it to the cache). | 564 * not found, returns a new entry (after adding it to the cache). |
569 */ | 565 */ |
570 SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef) { | 566 SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef) { |
571 SkFontID fontID = CTFontRef_to_SkFontID(fontRef); | 567 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (voi d*)fontRef); |
572 SkTypeface* face = SkTypefaceCache::FindByID(fontID); | |
573 if (face) { | 568 if (face) { |
574 face->ref(); | 569 face->ref(); |
bungeman-skia
2015/05/04 18:34:05
This is a race. FindByID doesn't ref what it retur
| |
575 } else { | 570 } else { |
571 CFRetain(fontRef); | |
576 face = NewFromFontRef(fontRef, NULL, false); | 572 face = NewFromFontRef(fontRef, NULL, false); |
577 SkTypefaceCache::Add(face, face->fontStyle()); | 573 SkTypefaceCache::Add(face, face->fontStyle()); |
578 // NewFromFontRef doesn't retain the parameter, but the typeface it | |
579 // creates does release it in its destructor, so we balance that with | |
580 // a retain call here. | |
581 CFRetain(fontRef); | |
582 } | 574 } |
583 SkASSERT(face->getRefCnt() > 1); | 575 SkASSERT(face->getRefCnt() > 1); |
584 return face; | 576 return face; |
585 } | 577 } |
586 | 578 |
587 struct NameStyle { | 579 struct NameStyle { |
588 const char* fName; | 580 const char* fName; |
589 SkFontStyle fStyle; | 581 SkFontStyle fStyle; |
590 }; | 582 }; |
591 | 583 |
(...skipping 1484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2076 SkString skFamilyName; | 2068 SkString skFamilyName; |
2077 CFStringToSkString(cfFamilyName, &skFamilyName); | 2069 CFStringToSkString(cfFamilyName, &skFamilyName); |
2078 cacheRequest.fName = skFamilyName.c_str(); | 2070 cacheRequest.fName = skFamilyName.c_str(); |
2079 cacheRequest.fStyle = fontstyle_from_descriptor(desc); | 2071 cacheRequest.fStyle = fontstyle_from_descriptor(desc); |
2080 | 2072 |
2081 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &cac heRequest); | 2073 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &cac heRequest); |
2082 if (face) { | 2074 if (face) { |
2083 return face; | 2075 return face; |
2084 } | 2076 } |
2085 | 2077 |
2086 AutoCFRelease<CFDictionaryRef> fontFamilyNameDictionary( | 2078 CTFontRef ctFont(CTFontCreateWithFontDescriptor(desc, 0, NULL)); |
bungeman-skia
2015/05/04 18:34:05
This block of code does not appear to help us in a
| |
2087 CFDictionaryCreate(kCFAllocatorDefault, | 2079 if (!ctFont) { |
2088 (const void**)&kCTFontFamilyNameAttribute, (const voi d**)&cfFamilyName, | |
2089 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionary ValueCallBacks)); | |
2090 AutoCFRelease<CTFontDescriptorRef> fontDescriptor( | |
2091 CTFontDescriptorCreateWithAttributes(fontFamilyNameDictionary)); | |
2092 AutoCFRelease<CTFontRef> ctNamed(CTFontCreateWithFontDescriptor(fontDescript or, 0, NULL)); | |
2093 CTFontRef ctFont = CTFontCreateCopyWithAttributes(ctNamed, 1, NULL, desc); | |
2094 if (NULL == ctFont) { | |
2095 return NULL; | 2080 return NULL; |
2096 } | 2081 } |
2097 | 2082 |
2098 bool isFixedPitch; | 2083 bool isFixedPitch; |
2099 (void)computeStyleBits(ctFont, &isFixedPitch); | 2084 (void)computeStyleBits(ctFont, &isFixedPitch); |
2100 SkFontID fontID = CTFontRef_to_SkFontID(ctFont); | |
2101 | 2085 |
2102 face = SkNEW_ARGS(SkTypeface_Mac, (cacheRequest.fStyle, fontID, isFixedPitch , | 2086 face = SkNEW_ARGS(SkTypeface_Mac, (cacheRequest.fStyle, isFixedPitch, |
2103 ctFont, skFamilyName.c_str(), false)); | 2087 ctFont, skFamilyName.c_str(), false)); |
2104 SkTypefaceCache::Add(face, face->fontStyle()); | 2088 SkTypefaceCache::Add(face, face->fontStyle()); |
2105 return face; | 2089 return face; |
2106 } | 2090 } |
2107 | 2091 |
2108 class SkFontStyleSet_Mac : public SkFontStyleSet { | 2092 class SkFontStyleSet_Mac : public SkFontStyleSet { |
2109 public: | 2093 public: |
2110 SkFontStyleSet_Mac(CFStringRef familyName, CTFontDescriptorRef desc) | 2094 SkFontStyleSet_Mac(CFStringRef familyName, CTFontDescriptorRef desc) |
2111 : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, NULL)) | 2095 : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, NULL)) |
2112 , fFamilyName(familyName) | 2096 , fFamilyName(familyName) |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2301 } | 2285 } |
2302 return face; | 2286 return face; |
2303 } | 2287 } |
2304 }; | 2288 }; |
2305 | 2289 |
2306 /////////////////////////////////////////////////////////////////////////////// | 2290 /////////////////////////////////////////////////////////////////////////////// |
2307 | 2291 |
2308 SkFontMgr* SkFontMgr::Factory() { | 2292 SkFontMgr* SkFontMgr::Factory() { |
2309 return SkNEW(SkFontMgr_Mac); | 2293 return SkNEW(SkFontMgr_Mac); |
2310 } | 2294 } |
OLD | NEW |