diff options
author | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-29 23:45:28 +0000 |
---|---|---|
committer | avi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-29 23:45:28 +0000 |
commit | 84683f0a267ff5f9396321a546615a64566ff444 (patch) | |
tree | b9b21f7e24b3f7d92e5e6933551d3bdd23a855ff | |
parent | 42b80efc8d8588bf369f428129333c7447070ebd (diff) | |
download | chromium_src-84683f0a267ff5f9396321a546615a64566ff444.zip chromium_src-84683f0a267ff5f9396321a546615a64566ff444.tar.gz chromium_src-84683f0a267ff5f9396321a546615a64566ff444.tar.bz2 |
Make RenderTextMac more efficient by caching fonts and taking advantage of toll-free bridging of CT/NSFont.
BUG=312436
TEST=no console spew as in bug
R=asvitkine@chromium.org, mark@chromium.org, shess@chromium.org
Review URL: https://codereview.chromium.org/49503003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@231670 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/mac/foundation_util.h | 10 | ||||
-rw-r--r-- | base/mac/foundation_util.mm | 60 | ||||
-rw-r--r-- | ui/gfx/platform_font_mac.h | 13 | ||||
-rw-r--r-- | ui/gfx/platform_font_mac.mm | 97 | ||||
-rw-r--r-- | ui/gfx/render_text_mac.cc | 5 |
5 files changed, 122 insertions, 63 deletions
diff --git a/base/mac/foundation_util.h b/base/mac/foundation_util.h index 447f7bf..46ea3c3 100644 --- a/base/mac/foundation_util.h +++ b/base/mac/foundation_util.h @@ -16,10 +16,14 @@ #if defined(__OBJC__) #import <Foundation/Foundation.h> +@class NSFont; +@class UIFont; #else // __OBJC__ #include <CoreFoundation/CoreFoundation.h> class NSBundle; +class NSFont; class NSString; +class UIFont; #endif // __OBJC__ #if defined(OS_IOS) @@ -225,6 +229,12 @@ CF_TO_NS_CAST_DECL(CFWriteStream, NSOutputStream); CF_TO_NS_MUTABLE_CAST_DECL(String); CF_TO_NS_CAST_DECL(CFURL, NSURL); +#if defined(OS_IOS) +CF_TO_NS_CAST_DECL(CTFont, UIFont); +#else +CF_TO_NS_CAST_DECL(CTFont, NSFont); +#endif + #undef CF_TO_NS_CAST_DECL #undef CF_TO_NS_MUTABLE_CAST_DECL #undef OBJC_CPP_CLASS_DECL diff --git a/base/mac/foundation_util.mm b/base/mac/foundation_util.mm index 5f8f694..1c75349 100644 --- a/base/mac/foundation_util.mm +++ b/base/mac/foundation_util.mm @@ -17,6 +17,7 @@ extern "C" { CFTypeID SecACLGetTypeID(); CFTypeID SecTrustedApplicationGetTypeID(); +Boolean _CFIsObjC(CFTypeID typeID, CFTypeRef obj); } // extern "C" #endif @@ -312,6 +313,31 @@ CF_TO_NS_CAST_DEFN(CFWriteStream, NSOutputStream); CF_TO_NS_MUTABLE_CAST_DEFN(String); CF_TO_NS_CAST_DEFN(CFURL, NSURL); +#if defined(OS_IOS) +CF_TO_NS_CAST_DEFN(CTFont, UIFont); +#else +// The NSFont/CTFont toll-free bridging is broken when it comes to type +// checking, so do some special-casing. +// http://www.openradar.me/15341349 rdar://15341349 +NSFont* CFToNSCast(CTFontRef cf_val) { + NSFont* ns_val = + const_cast<NSFont*>(reinterpret_cast<const NSFont*>(cf_val)); + DCHECK(!cf_val || + CTFontGetTypeID() == CFGetTypeID(cf_val) || + (_CFIsObjC(CTFontGetTypeID(), cf_val) && + [ns_val isKindOfClass:NSClassFromString(@"NSFont")])); + return ns_val; +} + +CTFontRef NSToCFCast(NSFont* ns_val) { + CTFontRef cf_val = reinterpret_cast<CTFontRef>(ns_val); + DCHECK(!cf_val || + CTFontGetTypeID() == CFGetTypeID(cf_val) || + [ns_val isKindOfClass:NSClassFromString(@"NSFont")]); + return cf_val; +} +#endif + #undef CF_TO_NS_CAST_DEFN #undef CF_TO_NS_MUTABLE_CAST_DEFN @@ -349,9 +375,41 @@ CF_CAST_DEFN(CFUUID); CF_CAST_DEFN(CGColor); -CF_CAST_DEFN(CTFont); CF_CAST_DEFN(CTRun); +#if defined(OS_IOS) +CF_CAST_DEFN(CTFont); +#else +// The NSFont/CTFont toll-free bridging is broken when it comes to type +// checking, so do some special-casing. +// http://www.openradar.me/15341349 rdar://15341349 +template<> CTFontRef +CFCast<CTFontRef>(const CFTypeRef& cf_val) { + if (cf_val == NULL) { + return NULL; + } + if (CFGetTypeID(cf_val) == CTFontGetTypeID()) { + return (CTFontRef)(cf_val); + } + + if (!_CFIsObjC(CTFontGetTypeID(), cf_val)) + return NULL; + + id<NSObject> ns_val = reinterpret_cast<id>(const_cast<void*>(cf_val)); + if ([ns_val isKindOfClass:NSClassFromString(@"NSFont")]) { + return (CTFontRef)(cf_val); + } + return NULL; +} + +template<> CTFontRef +CFCastStrict<CTFontRef>(const CFTypeRef& cf_val) { + CTFontRef rv = CFCast<CTFontRef>(cf_val); + DCHECK(cf_val == NULL || rv); + return rv; +} +#endif + #if !defined(OS_IOS) CF_CAST_DEFN(SecACL); CF_CAST_DEFN(SecTrustedApplication); diff --git a/ui/gfx/platform_font_mac.h b/ui/gfx/platform_font_mac.h index e9d0714..7137278 100644 --- a/ui/gfx/platform_font_mac.h +++ b/ui/gfx/platform_font_mac.h @@ -6,6 +6,7 @@ #define UI_GFX_PLATFORM_FONT_MAC_H_ #include "base/compiler_specific.h" +#include "base/mac/scoped_nsobject.h" #include "ui/gfx/platform_font.h" namespace gfx { @@ -31,16 +32,12 @@ class PlatformFontMac : public PlatformFont { virtual NativeFont GetNativeFont() const OVERRIDE; private: - PlatformFontMac(const std::string& font_name, int font_size, int style); - virtual ~PlatformFontMac() {} + virtual ~PlatformFontMac(); - // Initialize the object with the specified parameters. - void InitWithNameSizeAndStyle(const std::string& font_name, - int font_size, - int style); + // Initialize the object, and calculate and cache the font metrics. + void InitAndCalculateMetrics(); - // Calculate and cache the font metrics. - void CalculateMetrics(); + base::scoped_nsobject<NSFont> native_font_; std::string font_name_; int font_size_; diff --git a/ui/gfx/platform_font_mac.mm b/ui/gfx/platform_font_mac.mm index c75bf66..ab4c6dd 100644 --- a/ui/gfx/platform_font_mac.mm +++ b/ui/gfx/platform_font_mac.mm @@ -18,37 +18,52 @@ namespace gfx { //////////////////////////////////////////////////////////////////////////////// // PlatformFontMac, public: -PlatformFontMac::PlatformFontMac() { - font_size_ = [NSFont systemFontSize]; - style_ = gfx::Font::NORMAL; - NSFont* system_font = [NSFont systemFontOfSize:font_size_]; - font_name_ = base::SysNSStringToUTF8([system_font fontName]); - CalculateMetrics(); +PlatformFontMac::PlatformFontMac() + : native_font_([[NSFont systemFontOfSize:[NSFont systemFontSize]] retain]) { + InitAndCalculateMetrics(); } -PlatformFontMac::PlatformFontMac(NativeFont native_font) { - int style = 0; - NSFontSymbolicTraits traits = [[native_font fontDescriptor] symbolicTraits]; - if (traits & NSFontItalicTrait) - style |= Font::ITALIC; - if (traits & NSFontBoldTrait) - style |= Font::BOLD; - - InitWithNameSizeAndStyle(base::SysNSStringToUTF8([native_font familyName]), - [native_font pointSize], - style); +PlatformFontMac::PlatformFontMac(NativeFont native_font) + : native_font_([native_font retain]) { + InitAndCalculateMetrics(); } PlatformFontMac::PlatformFontMac(const std::string& font_name, int font_size) { - InitWithNameSizeAndStyle(font_name, font_size, gfx::Font::NORMAL); + native_font_.reset([[NSFont fontWithName:base::SysUTF8ToNSString(font_name) + size:font_size] retain]); + InitAndCalculateMetrics(); } //////////////////////////////////////////////////////////////////////////////// // PlatformFontMac, PlatformFont implementation: Font PlatformFontMac::DeriveFont(int size_delta, int style) const { - return Font(new PlatformFontMac(font_name_, font_size_ + size_delta, style)); + NSFont* font = native_font_.get(); + NSFontManager* font_manager = [NSFontManager sharedFontManager]; + + if (size_delta) { + font = [font_manager convertFont:font + toSize:font_size_ + size_delta]; + } + if (style & Font::BOLD) { + font = [font_manager convertFont:font + toHaveTrait:NSBoldFontMask]; + } else { + font = [font_manager convertFont:font + toNotHaveTrait:NSBoldFontMask]; + } + if (style & Font::ITALIC) { + font = [font_manager convertFont:font + toHaveTrait:NSItalicFontMask]; + } else { + font = [font_manager convertFont:font + toNotHaveTrait:NSItalicFontMask]; + } + // The Mac doesn't support underline as a font trait, so just drop it. + // Underlines can instead be added as an attribute on an NSAttributedString. + + return Font(new PlatformFontMac(font)); } int PlatformFontMac::GetHeight() const { @@ -89,45 +104,27 @@ int PlatformFontMac::GetFontSize() const { } NativeFont PlatformFontMac::GetNativeFont() const { - // We could cache this, but then we'd have to conditionally change the - // dtor just for MacOS. Not sure if we want to/need to do that. - NSFont* font = [NSFont fontWithName:base::SysUTF8ToNSString(font_name_) - size:font_size_]; - - if (style_ & Font::BOLD) { - font = [[NSFontManager sharedFontManager] convertFont:font - toHaveTrait:NSBoldFontMask]; - } - if (style_ & Font::ITALIC) { - font = [[NSFontManager sharedFontManager] convertFont:font - toHaveTrait:NSItalicFontMask]; - } - // Mac doesn't support underline as a font trait, just drop it. Underlines - // can instead be added as an attribute on an NSAttributedString. - - return font; + return native_font_.get(); } //////////////////////////////////////////////////////////////////////////////// // PlatformFontMac, private: -PlatformFontMac::PlatformFontMac(const std::string& font_name, - int font_size, - int style) { - InitWithNameSizeAndStyle(font_name, font_size, style); +PlatformFontMac::~PlatformFontMac() { } -void PlatformFontMac::InitWithNameSizeAndStyle(const std::string& font_name, - int font_size, - int style) { - font_name_ = font_name; - font_size_ = font_size; - style_ = style; - CalculateMetrics(); -} +void PlatformFontMac::InitAndCalculateMetrics() { + NSFont* font = native_font_.get(); + + font_name_ = base::SysNSStringToUTF8([font familyName]); + font_size_ = [font pointSize]; + style_ = 0; + NSFontSymbolicTraits traits = [[font fontDescriptor] symbolicTraits]; + if (traits & NSFontItalicTrait) + style_ |= Font::ITALIC; + if (traits & NSFontBoldTrait) + style_ |= Font::BOLD; -void PlatformFontMac::CalculateMetrics() { - NSFont* font = GetNativeFont(); base::scoped_nsobject<NSLayoutManager> layout_manager( [[NSLayoutManager alloc] init]); height_ = [layout_manager defaultLineHeightForFont:font]; diff --git a/ui/gfx/render_text_mac.cc b/ui/gfx/render_text_mac.cc index d86975d..327fc52 100644 --- a/ui/gfx/render_text_mac.cc +++ b/ui/gfx/render_text_mac.cc @@ -112,10 +112,7 @@ void RenderTextMac::EnsureLayout() { runs_valid_ = false; const Font& font = GetPrimaryFont(); - base::ScopedCFTypeRef<CFStringRef> font_name_cf_string( - base::SysUTF8ToCFStringRef(font.GetFontName())); - base::ScopedCFTypeRef<CTFontRef> ct_font( - CTFontCreateWithName(font_name_cf_string, font.GetFontSize(), NULL)); + CTFontRef ct_font = base::mac::NSToCFCast(font.GetNativeFont()); const void* keys[] = { kCTFontAttributeName }; const void* values[] = { ct_font }; |