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); | |
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 = NewFromFontRef(ctFont.detach(), NULL, false); |
| 535 SkTypefaceCache::Add(face, face->fontStyle()); |
| 536 } |
| 537 return face; |
544 } | 538 } |
545 | 539 |
546 SK_DECLARE_STATIC_MUTEX(gGetDefaultFaceMutex); | 540 SK_DECLARE_STATIC_MUTEX(gGetDefaultFaceMutex); |
547 static SkTypeface* GetDefaultFace() { | 541 static SkTypeface* GetDefaultFace() { |
548 SkAutoMutexAcquire ma(gGetDefaultFaceMutex); | 542 SkAutoMutexAcquire ma(gGetDefaultFaceMutex); |
549 | 543 |
550 static SkTypeface* gDefaultFace; | 544 static SkTypeface* gDefaultFace; |
551 | 545 |
552 if (NULL == gDefaultFace) { | 546 if (NULL == gDefaultFace) { |
553 gDefaultFace = NewFromName(FONT_DEFAULT_NAME, SkFontStyle()); | 547 gDefaultFace = NewFromName(FONT_DEFAULT_NAME, SkFontStyle()); |
554 SkTypefaceCache::Add(gDefaultFace, SkFontStyle()); | 548 SkTypefaceCache::Add(gDefaultFace, SkFontStyle()); |
555 } | 549 } |
556 return gDefaultFace; | 550 return gDefaultFace; |
557 } | 551 } |
558 | 552 |
559 /////////////////////////////////////////////////////////////////////////////// | 553 /////////////////////////////////////////////////////////////////////////////// |
560 | 554 |
561 extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face); | 555 extern CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face); |
562 CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) { | 556 CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) { |
563 const SkTypeface_Mac* macface = (const SkTypeface_Mac*)face; | 557 const SkTypeface_Mac* macface = (const SkTypeface_Mac*)face; |
564 return macface ? macface->fFontRef.get() : NULL; | 558 return macface ? macface->fFontRef.get() : NULL; |
565 } | 559 } |
566 | 560 |
567 /* This function is visible on the outside. It first searches the cache, and if | 561 /* 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). | 562 * not found, returns a new entry (after adding it to the cache). |
569 */ | 563 */ |
570 SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef) { | 564 SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef) { |
571 SkFontID fontID = CTFontRef_to_SkFontID(fontRef); | 565 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (voi
d*)fontRef); |
572 SkTypeface* face = SkTypefaceCache::FindByID(fontID); | 566 if (!face) { |
573 if (face) { | 567 CFRetain(fontRef); |
574 face->ref(); | |
575 } else { | |
576 face = NewFromFontRef(fontRef, NULL, false); | 568 face = NewFromFontRef(fontRef, NULL, false); |
577 SkTypefaceCache::Add(face, face->fontStyle()); | 569 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 } | 570 } |
583 SkASSERT(face->getRefCnt() > 1); | |
584 return face; | 571 return face; |
585 } | 572 } |
586 | 573 |
587 struct NameStyle { | 574 struct NameStyle { |
588 const char* fName; | 575 const char* fName; |
589 SkFontStyle fStyle; | 576 SkFontStyle fStyle; |
590 }; | 577 }; |
591 | 578 |
592 static bool find_by_NameStyle(SkTypeface* cachedFace, const SkFontStyle& cachedS
tyle, void* ctx) { | 579 static bool find_by_NameStyle(SkTypeface* cachedFace, const SkFontStyle& cachedS
tyle, void* ctx) { |
593 const SkTypeface_Mac* cachedMacFace = static_cast<SkTypeface_Mac*>(cachedFac
e); | 580 const SkTypeface_Mac* cachedMacFace = static_cast<SkTypeface_Mac*>(cachedFac
e); |
(...skipping 1482 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2076 SkString skFamilyName; | 2063 SkString skFamilyName; |
2077 CFStringToSkString(cfFamilyName, &skFamilyName); | 2064 CFStringToSkString(cfFamilyName, &skFamilyName); |
2078 cacheRequest.fName = skFamilyName.c_str(); | 2065 cacheRequest.fName = skFamilyName.c_str(); |
2079 cacheRequest.fStyle = fontstyle_from_descriptor(desc); | 2066 cacheRequest.fStyle = fontstyle_from_descriptor(desc); |
2080 | 2067 |
2081 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &cac
heRequest); | 2068 SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_NameStyle, &cac
heRequest); |
2082 if (face) { | 2069 if (face) { |
2083 return face; | 2070 return face; |
2084 } | 2071 } |
2085 | 2072 |
2086 AutoCFRelease<CFDictionaryRef> fontFamilyNameDictionary( | 2073 AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, NULL
)); |
2087 CFDictionaryCreate(kCFAllocatorDefault, | 2074 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; | 2075 return NULL; |
2096 } | 2076 } |
2097 | 2077 |
2098 bool isFixedPitch; | 2078 bool isFixedPitch; |
2099 (void)computeStyleBits(ctFont, &isFixedPitch); | 2079 (void)computeStyleBits(ctFont, &isFixedPitch); |
2100 SkFontID fontID = CTFontRef_to_SkFontID(ctFont); | |
2101 | 2080 |
2102 face = SkNEW_ARGS(SkTypeface_Mac, (cacheRequest.fStyle, fontID, isFixedPitch
, | 2081 face = SkNEW_ARGS(SkTypeface_Mac, (cacheRequest.fStyle, isFixedPitch, |
2103 ctFont, skFamilyName.c_str(), false)); | 2082 ctFont.detach(), skFamilyName.c_str(), fa
lse)); |
2104 SkTypefaceCache::Add(face, face->fontStyle()); | 2083 SkTypefaceCache::Add(face, face->fontStyle()); |
2105 return face; | 2084 return face; |
2106 } | 2085 } |
2107 | 2086 |
2108 class SkFontStyleSet_Mac : public SkFontStyleSet { | 2087 class SkFontStyleSet_Mac : public SkFontStyleSet { |
2109 public: | 2088 public: |
2110 SkFontStyleSet_Mac(CFStringRef familyName, CTFontDescriptorRef desc) | 2089 SkFontStyleSet_Mac(CFStringRef familyName, CTFontDescriptorRef desc) |
2111 : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, NULL)) | 2090 : fArray(CTFontDescriptorCreateMatchingFontDescriptors(desc, NULL)) |
2112 , fFamilyName(familyName) | 2091 , fFamilyName(familyName) |
2113 , fCount(0) { | 2092 , fCount(0) { |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2301 } | 2280 } |
2302 return face; | 2281 return face; |
2303 } | 2282 } |
2304 }; | 2283 }; |
2305 | 2284 |
2306 /////////////////////////////////////////////////////////////////////////////// | 2285 /////////////////////////////////////////////////////////////////////////////// |
2307 | 2286 |
2308 SkFontMgr* SkFontMgr::Factory() { | 2287 SkFontMgr* SkFontMgr::Factory() { |
2309 return SkNEW(SkFontMgr_Mac); | 2288 return SkNEW(SkFontMgr_Mac); |
2310 } | 2289 } |
OLD | NEW |