summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoravi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-29 23:45:28 +0000
committeravi@chromium.org <avi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-29 23:45:28 +0000
commit84683f0a267ff5f9396321a546615a64566ff444 (patch)
treeb9b21f7e24b3f7d92e5e6933551d3bdd23a855ff
parent42b80efc8d8588bf369f428129333c7447070ebd (diff)
downloadchromium_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.h10
-rw-r--r--base/mac/foundation_util.mm60
-rw-r--r--ui/gfx/platform_font_mac.h13
-rw-r--r--ui/gfx/platform_font_mac.mm97
-rw-r--r--ui/gfx/render_text_mac.cc5
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 };