| Index: src/ports/SkFontHost_mac.cpp
|
| diff --git a/src/ports/SkFontHost_mac.cpp b/src/ports/SkFontHost_mac.cpp
|
| index 5eaf7df6036b281fe08560d07baeef9e418fa7fe..d97b09c6516cb8df62b0681fbb3113f17c803bad 100755
|
| --- a/src/ports/SkFontHost_mac.cpp
|
| +++ b/src/ports/SkFontHost_mac.cpp
|
| @@ -92,6 +92,12 @@ public:
|
| }
|
| }
|
|
|
| + CFRef detach() {
|
| + CFRef self = fCFRef;
|
| + fCFRef = NULL;
|
| + return self;
|
| + }
|
| +
|
| operator CFRef() const { return fCFRef; }
|
| CFRef get() const { return fCFRef; }
|
|
|
| @@ -408,34 +414,6 @@ static SkTypeface::Style computeStyleBits(CTFontRef font, bool* isFixedPitch) {
|
| return (SkTypeface::Style)style;
|
| }
|
|
|
| -static SkFontID CTFontRef_to_SkFontID(CTFontRef fontRef) {
|
| - SkFontID id = 0;
|
| -// CTFontGetPlatformFont and ATSFontRef are not supported on iOS, so we have to
|
| -// bracket this to be Mac only.
|
| -#ifdef SK_BUILD_FOR_MAC
|
| - ATSFontRef ats = CTFontGetPlatformFont(fontRef, NULL);
|
| - id = (SkFontID)ats;
|
| - if (id != 0) {
|
| - id &= 0x3FFFFFFF; // make top two bits 00
|
| - return id;
|
| - }
|
| -#endif
|
| - // CTFontGetPlatformFont returns NULL if the font is local
|
| - // (e.g., was created by a CSS3 @font-face rule).
|
| - AutoCFRelease<CGFontRef> cgFont(CTFontCopyGraphicsFont(fontRef, NULL));
|
| - AutoCGTable<SkOTTableHead> headTable(cgFont);
|
| - if (headTable.fData) {
|
| - id = (SkFontID) headTable->checksumAdjustment;
|
| - id = (id & 0x3FFFFFFF) | 0x40000000; // make top two bits 01
|
| - }
|
| - // well-formed fonts have checksums, but as a last resort, use the pointer.
|
| - if (id == 0) {
|
| - id = (SkFontID) (uintptr_t) fontRef;
|
| - id = (id & 0x3FFFFFFF) | 0x80000000; // make top two bits 10
|
| - }
|
| - return id;
|
| -}
|
| -
|
| #define WEIGHT_THRESHOLD ((SkFontStyle::kNormal_Weight + SkFontStyle::kBold_Weight)/2)
|
|
|
| // kCTFontColorGlyphsTrait was added in the Mac 10.7 and iPhone 4.3 SDKs.
|
| @@ -448,9 +426,9 @@ static const uint32_t SkCTFontColorGlyphsTrait = (1 << 13);
|
|
|
| class SkTypeface_Mac : public SkTypeface {
|
| public:
|
| - SkTypeface_Mac(const SkFontStyle& fs, SkFontID fontID, bool isFixedPitch,
|
| + SkTypeface_Mac(const SkFontStyle& fs, bool isFixedPitch,
|
| CTFontRef fontRef, const char requestedName[], bool isLocalStream)
|
| - : SkTypeface(fs, fontID, isFixedPitch)
|
| + : SkTypeface(fs, SkTypefaceCache::NewFontID(), isFixedPitch)
|
| , fRequestedName(requestedName)
|
| , fFontRef(fontRef) // caller has already called CFRetain for us
|
| , fHasColorGlyphs(SkToBool(CTFontGetSymbolicTraits(fFontRef) & SkCTFontColorGlyphsTrait))
|
| @@ -487,18 +465,24 @@ private:
|
| typedef SkTypeface INHERITED;
|
| };
|
|
|
| +/** Creates a typeface without searching the cache. Takes ownership of the CTFontRef. */
|
| static SkTypeface* NewFromFontRef(CTFontRef fontRef, const char name[], bool isLocalStream) {
|
| SkASSERT(fontRef);
|
| bool isFixedPitch;
|
| SkFontStyle style = SkFontStyle(computeStyleBits(fontRef, &isFixedPitch));
|
| - SkFontID fontID = CTFontRef_to_SkFontID(fontRef);
|
|
|
| - return new SkTypeface_Mac(style, fontID, isFixedPitch, fontRef, name, isLocalStream);
|
| + return new SkTypeface_Mac(style, isFixedPitch, fontRef, name, isLocalStream);
|
| }
|
|
|
| -static SkTypeface* NewFromName(const char familyName[], const SkFontStyle& theStyle) {
|
| - CTFontRef ctFont = NULL;
|
| +static bool find_by_CTFontRef(SkTypeface* cached, const SkFontStyle&, void* context) {
|
| + CTFontRef self = (CTFontRef)context;
|
| + CTFontRef other = ((SkTypeface_Mac*)cached)->fFontRef;
|
|
|
| + return CFEqual(self, other);
|
| +}
|
| +
|
| +/** Creates a typeface from a name, searching the cache. */
|
| +static SkTypeface* NewFromName(const char familyName[], const SkFontStyle& theStyle) {
|
| CTFontSymbolicTraits ctFontTraits = 0;
|
| if (theStyle.weight() >= SkFontStyle::kBold_Weight) {
|
| ctFontTraits |= kCTFontBoldTrait;
|
| @@ -525,22 +509,32 @@ static SkTypeface* NewFromName(const char familyName[], const SkFontStyle& theSt
|
| &kCFTypeDictionaryKeyCallBacks,
|
| &kCFTypeDictionaryValueCallBacks));
|
|
|
| - // Create the font
|
| - if (cfFontName != NULL && cfFontTraits != NULL && cfAttributes != NULL && cfTraits != NULL) {
|
| - CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits);
|
| + if (!cfFontName || !cfFontTraits || !cfAttributes || !cfTraits) {
|
| + return NULL;
|
| + }
|
|
|
| - CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName);
|
| - CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits);
|
| + CFDictionaryAddValue(cfTraits, kCTFontSymbolicTrait, cfFontTraits);
|
|
|
| - AutoCFRelease<CTFontDescriptorRef> ctFontDesc(
|
| - CTFontDescriptorCreateWithAttributes(cfAttributes));
|
| + CFDictionaryAddValue(cfAttributes, kCTFontFamilyNameAttribute, cfFontName);
|
| + CFDictionaryAddValue(cfAttributes, kCTFontTraitsAttribute, cfTraits);
|
|
|
| - if (ctFontDesc != NULL) {
|
| - ctFont = CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL);
|
| - }
|
| + AutoCFRelease<CTFontDescriptorRef> ctFontDesc(
|
| + CTFontDescriptorCreateWithAttributes(cfAttributes));
|
| + if (!ctFontDesc) {
|
| + return NULL;
|
| }
|
|
|
| - return ctFont ? NewFromFontRef(ctFont, familyName, false) : NULL;
|
| + AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(ctFontDesc, 0, NULL));
|
| + if (!ctFont) {
|
| + return NULL;
|
| + }
|
| +
|
| + SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)ctFont.get());
|
| + if (!face) {
|
| + face = NewFromFontRef(ctFont.detach(), NULL, false);
|
| + SkTypefaceCache::Add(face, face->fontStyle());
|
| + }
|
| + return face;
|
| }
|
|
|
| SK_DECLARE_STATIC_MUTEX(gGetDefaultFaceMutex);
|
| @@ -568,19 +562,12 @@ CTFontRef SkTypeface_GetCTFontRef(const SkTypeface* face) {
|
| * not found, returns a new entry (after adding it to the cache).
|
| */
|
| SkTypeface* SkCreateTypefaceFromCTFont(CTFontRef fontRef) {
|
| - SkFontID fontID = CTFontRef_to_SkFontID(fontRef);
|
| - SkTypeface* face = SkTypefaceCache::FindByID(fontID);
|
| - if (face) {
|
| - face->ref();
|
| - } else {
|
| + SkTypeface* face = SkTypefaceCache::FindByProcAndRef(find_by_CTFontRef, (void*)fontRef);
|
| + if (!face) {
|
| + CFRetain(fontRef);
|
| face = NewFromFontRef(fontRef, NULL, false);
|
| SkTypefaceCache::Add(face, face->fontStyle());
|
| - // NewFromFontRef doesn't retain the parameter, but the typeface it
|
| - // creates does release it in its destructor, so we balance that with
|
| - // a retain call here.
|
| - CFRetain(fontRef);
|
| }
|
| - SkASSERT(face->getRefCnt() > 1);
|
| return face;
|
| }
|
|
|
| @@ -2083,24 +2070,16 @@ static SkTypeface* createFromDesc(CFStringRef cfFamilyName, CTFontDescriptorRef
|
| return face;
|
| }
|
|
|
| - AutoCFRelease<CFDictionaryRef> fontFamilyNameDictionary(
|
| - CFDictionaryCreate(kCFAllocatorDefault,
|
| - (const void**)&kCTFontFamilyNameAttribute, (const void**)&cfFamilyName,
|
| - 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
|
| - AutoCFRelease<CTFontDescriptorRef> fontDescriptor(
|
| - CTFontDescriptorCreateWithAttributes(fontFamilyNameDictionary));
|
| - AutoCFRelease<CTFontRef> ctNamed(CTFontCreateWithFontDescriptor(fontDescriptor, 0, NULL));
|
| - CTFontRef ctFont = CTFontCreateCopyWithAttributes(ctNamed, 1, NULL, desc);
|
| - if (NULL == ctFont) {
|
| + AutoCFRelease<CTFontRef> ctFont(CTFontCreateWithFontDescriptor(desc, 0, NULL));
|
| + if (!ctFont) {
|
| return NULL;
|
| }
|
|
|
| bool isFixedPitch;
|
| (void)computeStyleBits(ctFont, &isFixedPitch);
|
| - SkFontID fontID = CTFontRef_to_SkFontID(ctFont);
|
|
|
| - face = SkNEW_ARGS(SkTypeface_Mac, (cacheRequest.fStyle, fontID, isFixedPitch,
|
| - ctFont, skFamilyName.c_str(), false));
|
| + face = SkNEW_ARGS(SkTypeface_Mac, (cacheRequest.fStyle, isFixedPitch,
|
| + ctFont.detach(), skFamilyName.c_str(), false));
|
| SkTypefaceCache::Add(face, face->fontStyle());
|
| return face;
|
| }
|
|
|