Home | History | Annotate | Download | only in gfx
      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