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