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/font_list.h"
6
7#include "base/lazy_instance.h"
8#include "base/strings/string_util.h"
9#include "ui/gfx/font_list_impl.h"
10
11namespace {
12
13// Font description of the default font set.
14base::LazyInstance<std::string>::Leaky g_default_font_description =
15    LAZY_INSTANCE_INITIALIZER;
16
17// The default instance of gfx::FontListImpl.
18base::LazyInstance<scoped_refptr<gfx::FontListImpl> >::Leaky g_default_impl =
19    LAZY_INSTANCE_INITIALIZER;
20bool g_default_impl_initialized = false;
21
22}  // namespace
23
24namespace gfx {
25
26FontList::FontList() : impl_(GetDefaultImpl()) {}
27
28FontList::FontList(const FontList& other) : impl_(other.impl_) {}
29
30FontList::FontList(const std::string& font_description_string)
31    : impl_(new FontListImpl(font_description_string)) {}
32
33FontList::FontList(const std::vector<std::string>& font_names,
34                   int font_style,
35                   int font_size)
36    : impl_(new FontListImpl(font_names, font_style, font_size)) {}
37
38FontList::FontList(const std::vector<Font>& fonts)
39    : impl_(new FontListImpl(fonts)) {}
40
41FontList::FontList(const Font& font) : impl_(new FontListImpl(font)) {}
42
43FontList::~FontList() {}
44
45FontList& FontList::operator=(const FontList& other) {
46  impl_ = other.impl_;
47  return *this;
48}
49
50// static
51void FontList::SetDefaultFontDescription(const std::string& font_description) {
52  // The description string must end with "px" for size in pixel, or must be
53  // the empty string, which specifies to use a single default font.
54  DCHECK(font_description.empty() ||
55         EndsWith(font_description, "px", true));
56
57  g_default_font_description.Get() = font_description;
58  g_default_impl_initialized = false;
59}
60
61FontList FontList::Derive(int size_delta, int font_style) const {
62  return FontList(impl_->Derive(size_delta, font_style));
63}
64
65FontList FontList::DeriveWithSizeDelta(int size_delta) const {
66  return Derive(size_delta, GetFontStyle());
67}
68
69FontList FontList::DeriveWithStyle(int font_style) const {
70  return Derive(0, font_style);
71}
72
73gfx::FontList FontList::DeriveWithHeightUpperBound(int height) const {
74  gfx::FontList font_list(*this);
75  for (int font_size = font_list.GetFontSize(); font_size > 1; --font_size) {
76    const int internal_leading =
77        font_list.GetBaseline() - font_list.GetCapHeight();
78    // Some platforms don't support getting the cap height, and simply return
79    // the entire font ascent from GetCapHeight().  Centering the ascent makes
80    // the font look too low, so if GetCapHeight() returns the ascent, center
81    // the entire font height instead.
82    const int space =
83        height - ((internal_leading != 0) ?
84                  font_list.GetCapHeight() : font_list.GetHeight());
85    const int y_offset = space / 2 - internal_leading;
86    const int space_at_bottom = height - (y_offset + font_list.GetHeight());
87    if ((y_offset >= 0) && (space_at_bottom >= 0))
88      break;
89    font_list = font_list.DeriveWithSizeDelta(-1);
90  }
91  return font_list;
92}
93
94int FontList::GetHeight() const {
95  return impl_->GetHeight();
96}
97
98int FontList::GetBaseline() const {
99  return impl_->GetBaseline();
100}
101
102int FontList::GetCapHeight() const {
103  return impl_->GetCapHeight();
104}
105
106int FontList::GetExpectedTextWidth(int length) const {
107  return impl_->GetExpectedTextWidth(length);
108}
109
110int FontList::GetFontStyle() const {
111  return impl_->GetFontStyle();
112}
113
114const std::string& FontList::GetFontDescriptionString() const {
115  return impl_->GetFontDescriptionString();
116}
117
118int FontList::GetFontSize() const {
119  return impl_->GetFontSize();
120}
121
122const std::vector<Font>& FontList::GetFonts() const {
123  return impl_->GetFonts();
124}
125
126const Font& FontList::GetPrimaryFont() const {
127  return impl_->GetPrimaryFont();
128}
129
130FontList::FontList(FontListImpl* impl) : impl_(impl) {}
131
132// static
133const scoped_refptr<FontListImpl>& FontList::GetDefaultImpl() {
134  // SetDefaultFontDescription() must be called and the default font description
135  // must be set earlier than any call of this function.
136  DCHECK(!(g_default_font_description == NULL))  // != is not overloaded.
137      << "SetDefaultFontDescription has not been called.";
138
139  if (!g_default_impl_initialized) {
140    g_default_impl.Get() =
141        g_default_font_description.Get().empty() ?
142            new FontListImpl(Font()) :
143            new FontListImpl(g_default_font_description.Get());
144    g_default_impl_initialized = true;
145  }
146
147  return g_default_impl.Get();
148}
149
150}  // namespace gfx
151