1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ui/gfx/platform_font_mac.h" 6 7 #include <Cocoa/Cocoa.h> 8 9 #include "base/basictypes.h" 10 #include "base/mac/scoped_nsobject.h" 11 #include "base/strings/sys_string_conversions.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "ui/gfx/canvas.h" 14 #include "ui/gfx/font.h" 15 16 namespace gfx { 17 18 namespace { 19 20 // Returns an autoreleased NSFont created with the passed-in specifications. 21 NSFont* NSFontWithSpec(const std::string& font_name, 22 int font_size, 23 int font_style) { 24 NSFontSymbolicTraits trait_bits = 0; 25 if (font_style & Font::BOLD) 26 trait_bits |= NSFontBoldTrait; 27 if (font_style & Font::ITALIC) 28 trait_bits |= NSFontItalicTrait; 29 // The Mac doesn't support underline as a font trait, so just drop it. 30 // (Underlines must be added as an attribute on an NSAttributedString.) 31 NSDictionary* traits = @{ NSFontSymbolicTrait : @(trait_bits) }; 32 33 NSDictionary* attrs = @{ 34 NSFontFamilyAttribute : base::SysUTF8ToNSString(font_name), 35 NSFontTraitsAttribute : traits 36 }; 37 NSFontDescriptor* descriptor = 38 [NSFontDescriptor fontDescriptorWithFontAttributes:attrs]; 39 NSFont* font = [NSFont fontWithDescriptor:descriptor size:font_size]; 40 if (font) 41 return font; 42 43 // Make one fallback attempt by looking up via font name rather than font 44 // family name. 45 attrs = @{ 46 NSFontNameAttribute : base::SysUTF8ToNSString(font_name), 47 NSFontTraitsAttribute : traits 48 }; 49 descriptor = [NSFontDescriptor fontDescriptorWithFontAttributes:attrs]; 50 return [NSFont fontWithDescriptor:descriptor size:font_size]; 51 } 52 53 } // namespace 54 55 //////////////////////////////////////////////////////////////////////////////// 56 // PlatformFontMac, public: 57 58 PlatformFontMac::PlatformFontMac() 59 : native_font_([[NSFont systemFontOfSize:[NSFont systemFontSize]] retain]), 60 font_name_(base::SysNSStringToUTF8([native_font_ familyName])), 61 font_size_([NSFont systemFontSize]), 62 font_style_(Font::NORMAL) { 63 CalculateMetrics(); 64 } 65 66 PlatformFontMac::PlatformFontMac(NativeFont native_font) 67 : native_font_([native_font retain]), 68 font_name_(base::SysNSStringToUTF8([native_font_ familyName])), 69 font_size_([native_font_ pointSize]), 70 font_style_(Font::NORMAL) { 71 NSFontSymbolicTraits traits = [[native_font fontDescriptor] symbolicTraits]; 72 if (traits & NSFontItalicTrait) 73 font_style_ |= Font::ITALIC; 74 if (traits & NSFontBoldTrait) 75 font_style_ |= Font::BOLD; 76 77 CalculateMetrics(); 78 } 79 80 PlatformFontMac::PlatformFontMac(const std::string& font_name, 81 int font_size) 82 : native_font_([NSFontWithSpec(font_name, font_size, Font::NORMAL) retain]), 83 font_name_(font_name), 84 font_size_(font_size), 85 font_style_(Font::NORMAL) { 86 CalculateMetrics(); 87 } 88 89 //////////////////////////////////////////////////////////////////////////////// 90 // PlatformFontMac, PlatformFont implementation: 91 92 Font PlatformFontMac::DeriveFont(int size_delta, int style) const { 93 return Font(new PlatformFontMac(font_name_, font_size_ + size_delta, style)); 94 } 95 96 int PlatformFontMac::GetHeight() const { 97 return height_; 98 } 99 100 int PlatformFontMac::GetBaseline() const { 101 return ascent_; 102 } 103 104 int PlatformFontMac::GetCapHeight() const { 105 return cap_height_; 106 } 107 108 int PlatformFontMac::GetExpectedTextWidth(int length) const { 109 return length * average_width_; 110 } 111 112 int PlatformFontMac::GetStyle() const { 113 return font_style_; 114 } 115 116 std::string PlatformFontMac::GetFontName() const { 117 return font_name_; 118 } 119 120 std::string PlatformFontMac::GetActualFontNameForTesting() const { 121 return base::SysNSStringToUTF8([native_font_ familyName]); 122 } 123 124 int PlatformFontMac::GetFontSize() const { 125 return font_size_; 126 } 127 128 NativeFont PlatformFontMac::GetNativeFont() const { 129 return [[native_font_.get() retain] autorelease]; 130 } 131 132 //////////////////////////////////////////////////////////////////////////////// 133 // PlatformFontMac, private: 134 135 PlatformFontMac::PlatformFontMac(const std::string& font_name, 136 int font_size, 137 int font_style) 138 : native_font_([NSFontWithSpec(font_name, font_size, font_style) retain]), 139 font_name_(font_name), 140 font_size_(font_size), 141 font_style_(font_style) { 142 CalculateMetrics(); 143 } 144 145 PlatformFontMac::~PlatformFontMac() { 146 } 147 148 void PlatformFontMac::CalculateMetrics() { 149 NSFont* font = native_font_.get(); 150 if (!font) { 151 // This object was constructed from a font name that doesn't correspond to 152 // an actual font. Don't waste time working out metrics. 153 height_ = 0; 154 ascent_ = 0; 155 cap_height_ = 0; 156 average_width_ = 0; 157 return; 158 } 159 160 base::scoped_nsobject<NSLayoutManager> layout_manager( 161 [[NSLayoutManager alloc] init]); 162 height_ = [layout_manager defaultLineHeightForFont:font]; 163 ascent_ = [font ascender]; 164 cap_height_ = [font capHeight]; 165 average_width_ = 166 NSWidth([font boundingRectForGlyph:[font glyphWithName:@"x"]]); 167 } 168 169 //////////////////////////////////////////////////////////////////////////////// 170 // PlatformFont, public: 171 172 // static 173 PlatformFont* PlatformFont::CreateDefault() { 174 return new PlatformFontMac; 175 } 176 177 // static 178 PlatformFont* PlatformFont::CreateFromNativeFont(NativeFont native_font) { 179 return new PlatformFontMac(native_font); 180 } 181 182 // static 183 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, 184 int font_size) { 185 return new PlatformFontMac(font_name, font_size); 186 } 187 188 } // namespace gfx 189