blob: 3eb55be5933a9e26abef16505a130d8be9e5639b [file] [log] [blame]
[email protected]2a25d8022014-02-09 03:12:551// Copyright 2014 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_impl.h"
6
7#include <algorithm>
8
9#include "base/logging.h"
10#include "base/strings/string_number_conversions.h"
[email protected]2a25d8022014-02-09 03:12:5511#include "base/strings/string_util.h"
12#include "ui/gfx/font.h"
derat23144a62015-02-10 14:48:2513#include "ui/gfx/font_list.h"
[email protected]2a25d8022014-02-09 03:12:5514
15namespace {
16
derat23144a62015-02-10 14:48:2517// Returns a font description from |families|, |style|, and |size_pixels|.
18std::string BuildDescription(const std::vector<std::string>& families,
19 int style,
20 int size_pixels) {
brettwd94a22142015-07-15 05:19:2621 std::string description = base::JoinString(families, ",");
derat23144a62015-02-10 14:48:2522 description += ",";
[email protected]2a25d8022014-02-09 03:12:5523
derat23144a62015-02-10 14:48:2524 if (style & gfx::Font::BOLD)
25 description += "Bold ";
26 if (style & gfx::Font::ITALIC)
27 description += "Italic ";
[email protected]2a25d8022014-02-09 03:12:5528
derat23144a62015-02-10 14:48:2529 description += base::IntToString(size_pixels);
30 description += "px";
[email protected]2a25d8022014-02-09 03:12:5531
[email protected]2a25d8022014-02-09 03:12:5532 return description;
33}
34
35} // namespace
36
37namespace gfx {
38
39FontListImpl::FontListImpl(const std::string& font_description_string)
40 : font_description_string_(font_description_string),
41 common_height_(-1),
42 common_baseline_(-1),
43 font_style_(-1),
44 font_size_(-1) {
45 DCHECK(!font_description_string.empty());
46 // DCHECK description string ends with "px" for size in pixel.
brettwa7ff1b292015-07-16 17:49:2947 DCHECK(base::EndsWith(font_description_string, "px",
48 base::CompareCase::SENSITIVE));
[email protected]2a25d8022014-02-09 03:12:5549}
50
51FontListImpl::FontListImpl(const std::vector<std::string>& font_names,
52 int font_style,
53 int font_size)
derat23144a62015-02-10 14:48:2554 : font_description_string_(BuildDescription(font_names, font_style,
55 font_size)),
[email protected]2a25d8022014-02-09 03:12:5556 common_height_(-1),
57 common_baseline_(-1),
58 font_style_(font_style),
59 font_size_(font_size) {
60 DCHECK(!font_names.empty());
61 DCHECK(!font_names[0].empty());
62}
63
64FontListImpl::FontListImpl(const std::vector<Font>& fonts)
65 : fonts_(fonts),
66 common_height_(-1),
67 common_baseline_(-1),
68 font_style_(-1),
69 font_size_(-1) {
70 DCHECK(!fonts.empty());
71 font_style_ = fonts[0].GetStyle();
72 font_size_ = fonts[0].GetFontSize();
danakje649f572015-01-08 23:35:5873#if DCHECK_IS_ON()
[email protected]c02cb8012014-03-14 18:39:5374 for (size_t i = 1; i < fonts.size(); ++i) {
75 DCHECK_EQ(fonts[i].GetStyle(), font_style_);
76 DCHECK_EQ(fonts[i].GetFontSize(), font_size_);
[email protected]2a25d8022014-02-09 03:12:5577 }
[email protected]c02cb8012014-03-14 18:39:5378#endif
[email protected]2a25d8022014-02-09 03:12:5579}
80
81FontListImpl::FontListImpl(const Font& font)
82 : common_height_(-1),
83 common_baseline_(-1),
84 font_style_(-1),
85 font_size_(-1) {
86 fonts_.push_back(font);
87}
88
89FontListImpl* FontListImpl::Derive(int size_delta, int font_style) const {
90 // If there is a font vector, derive from that.
91 if (!fonts_.empty()) {
92 std::vector<Font> fonts = fonts_;
93 for (size_t i = 0; i < fonts.size(); ++i)
[email protected]01430822014-02-13 15:41:4594 fonts[i] = fonts[i].Derive(size_delta, font_style);
[email protected]2a25d8022014-02-09 03:12:5595 return new FontListImpl(fonts);
96 }
97
98 // Otherwise, parse the font description string to derive from it.
99 std::vector<std::string> font_names;
100 int old_size;
101 int old_style;
derat23144a62015-02-10 14:48:25102 CHECK(FontList::ParseDescription(font_description_string_, &font_names,
103 &old_style, &old_size));
[email protected]2a25d8022014-02-09 03:12:55104 const int size = std::max(1, old_size + size_delta);
105 return new FontListImpl(font_names, font_style, size);
106}
107
108int FontListImpl::GetHeight() const {
109 if (common_height_ == -1)
110 CacheCommonFontHeightAndBaseline();
111 return common_height_;
112}
113
114int FontListImpl::GetBaseline() const {
115 if (common_baseline_ == -1)
116 CacheCommonFontHeightAndBaseline();
117 return common_baseline_;
118}
119
120int FontListImpl::GetCapHeight() const {
121 // Assume the primary font is used to render Latin characters.
122 return GetPrimaryFont().GetCapHeight();
123}
124
125int FontListImpl::GetExpectedTextWidth(int length) const {
126 // Rely on the primary font metrics for the time being.
127 return GetPrimaryFont().GetExpectedTextWidth(length);
128}
129
130int FontListImpl::GetFontStyle() const {
131 if (font_style_ == -1)
132 CacheFontStyleAndSize();
133 return font_style_;
134}
135
[email protected]2a25d8022014-02-09 03:12:55136int FontListImpl::GetFontSize() const {
137 if (font_size_ == -1)
138 CacheFontStyleAndSize();
139 return font_size_;
140}
141
142const std::vector<Font>& FontListImpl::GetFonts() const {
143 if (fonts_.empty()) {
144 DCHECK(!font_description_string_.empty());
145
146 std::vector<std::string> font_names;
147 // It's possible that gfx::Font::UNDERLINE is specified and it's already
148 // stored in |font_style_| but |font_description_string_| doesn't have the
149 // underline info. So we should respect |font_style_| as long as it's
150 // valid.
151 int style = 0;
derat23144a62015-02-10 14:48:25152 CHECK(FontList::ParseDescription(font_description_string_, &font_names,
153 &style, &font_size_));
[email protected]2a25d8022014-02-09 03:12:55154 if (font_style_ == -1)
155 font_style_ = style;
156 for (size_t i = 0; i < font_names.size(); ++i) {
157 DCHECK(!font_names[i].empty());
158
159 Font font(font_names[i], font_size_);
160 if (font_style_ == Font::NORMAL)
161 fonts_.push_back(font);
162 else
[email protected]01430822014-02-13 15:41:45163 fonts_.push_back(font.Derive(0, font_style_));
[email protected]2a25d8022014-02-09 03:12:55164 }
165 }
166 return fonts_;
167}
168
169const Font& FontListImpl::GetPrimaryFont() const {
170 return GetFonts()[0];
171}
172
173FontListImpl::~FontListImpl() {}
174
175void FontListImpl::CacheCommonFontHeightAndBaseline() const {
176 int ascent = 0;
177 int descent = 0;
178 const std::vector<Font>& fonts = GetFonts();
179 for (std::vector<Font>::const_iterator i = fonts.begin();
180 i != fonts.end(); ++i) {
181 ascent = std::max(ascent, i->GetBaseline());
182 descent = std::max(descent, i->GetHeight() - i->GetBaseline());
183 }
184 common_height_ = ascent + descent;
185 common_baseline_ = ascent;
186}
187
188void FontListImpl::CacheFontStyleAndSize() const {
189 if (!fonts_.empty()) {
190 font_style_ = fonts_[0].GetStyle();
191 font_size_ = fonts_[0].GetFontSize();
192 } else {
193 std::vector<std::string> font_names;
derat23144a62015-02-10 14:48:25194 CHECK(FontList::ParseDescription(font_description_string_, &font_names,
195 &font_style_, &font_size_));
[email protected]2a25d8022014-02-09 03:12:55196 }
197}
198
199} // namespace gfx