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::GetAverageCharacterWidth() const { 109 return average_width_; 110 } 111 112 int PlatformFontMac::GetStringWidth(const base::string16& text) const { 113 return Canvas::GetStringWidth(text, 114 Font(const_cast<PlatformFontMac*>(this))); 115 } 116 117 int PlatformFontMac::GetExpectedTextWidth(int length) const { 118 return length * average_width_; 119 } 120 121 int PlatformFontMac::GetStyle() const { 122 return font_style_; 123 } 124 125 std::string PlatformFontMac::GetFontName() const { 126 return font_name_; 127 } 128 129 std::string PlatformFontMac::GetActualFontNameForTesting() const { 130 return base::SysNSStringToUTF8([native_font_ familyName]); 131 } 132 133 int PlatformFontMac::GetFontSize() const { 134 return font_size_; 135 } 136 137 NativeFont PlatformFontMac::GetNativeFont() const { 138 return [[native_font_.get() retain] autorelease]; 139 } 140 141 //////////////////////////////////////////////////////////////////////////////// 142 // PlatformFontMac, private: 143 144 PlatformFontMac::PlatformFontMac(const std::string& font_name, 145 int font_size, 146 int font_style) 147 : native_font_([NSFontWithSpec(font_name, font_size, font_style) retain]), 148 font_name_(font_name), 149 font_size_(font_size), 150 font_style_(font_style) { 151 CalculateMetrics(); 152 } 153 154 PlatformFontMac::~PlatformFontMac() { 155 } 156 157 void PlatformFontMac::CalculateMetrics() { 158 NSFont* font = native_font_.get(); 159 if (!font) { 160 // This object was constructed from a font name that doesn't correspond to 161 // an actual font. Don't waste time working out metrics. 162 height_ = 0; 163 ascent_ = 0; 164 cap_height_ = 0; 165 average_width_ = 0; 166 return; 167 } 168 169 base::scoped_nsobject<NSLayoutManager> layout_manager( 170 [[NSLayoutManager alloc] init]); 171 height_ = [layout_manager defaultLineHeightForFont:font]; 172 ascent_ = [font ascender]; 173 cap_height_ = [font capHeight]; 174 average_width_ = 175 NSWidth([font boundingRectForGlyph:[font glyphWithName:@"x"]]); 176 } 177 178 //////////////////////////////////////////////////////////////////////////////// 179 // PlatformFont, public: 180 181 // static 182 PlatformFont* PlatformFont::CreateDefault() { 183 return new PlatformFontMac; 184 } 185 186 // static 187 PlatformFont* PlatformFont::CreateFromNativeFont(NativeFont native_font) { 188 return new PlatformFontMac(native_font); 189 } 190 191 // static 192 PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name, 193 int font_size) { 194 return new PlatformFontMac(font_name, font_size); 195 } 196 197 } // namespace gfx 198