blob: 6decee94999bc263c1596713ed5c8fb0708faee5 [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
avic89eb8d42015-12-23 08:08:187#include <stddef.h>
8
[email protected]2a25d8022014-02-09 03:12:559#include <algorithm>
10
11#include "base/logging.h"
12#include "base/strings/string_number_conversions.h"
[email protected]2a25d8022014-02-09 03:12:5513#include "base/strings/string_util.h"
derat23144a62015-02-10 14:48:2514#include "ui/gfx/font_list.h"
[email protected]2a25d8022014-02-09 03:12:5515
mboc998e8902016-06-02 11:40:3516namespace gfx {
[email protected]2a25d8022014-02-09 03:12:5517namespace {
18
derat23144a62015-02-10 14:48:2519// Returns a font description from |families|, |style|, and |size_pixels|.
20std::string BuildDescription(const std::vector<std::string>& families,
21 int style,
mboc998e8902016-06-02 11:40:3522 int size_pixels,
23 Font::Weight weight) {
brettwd94a22142015-07-15 05:19:2624 std::string description = base::JoinString(families, ",");
derat23144a62015-02-10 14:48:2525 description += ",";
[email protected]2a25d8022014-02-09 03:12:5526
mboc998e8902016-06-02 11:40:3527 if (style & Font::ITALIC)
derat23144a62015-02-10 14:48:2528 description += "Italic ";
mboc998e8902016-06-02 11:40:3529 switch (weight) {
30 case Font::Weight::THIN:
31 description += "Thin ";
32 break;
33 case Font::Weight::EXTRA_LIGHT:
34 description += "Ultra-Light ";
35 break;
36 case Font::Weight::LIGHT:
37 description += "Light ";
38 break;
39 case Font::Weight::MEDIUM:
40 description += "Medium ";
41 break;
42 case Font::Weight::SEMIBOLD:
43 description += "Semi-Bold ";
44 break;
45 case Font::Weight::BOLD:
46 description += "Bold ";
47 break;
48 case Font::Weight::EXTRA_BOLD:
49 description += "Ultra-Bold ";
50 break;
51 case Font::Weight::BLACK:
52 description += "Heavy ";
53 break;
54 case Font::Weight::NORMAL:
55 case Font::Weight::INVALID:
56 break;
57 }
[email protected]2a25d8022014-02-09 03:12:5558
derat23144a62015-02-10 14:48:2559 description += base::IntToString(size_pixels);
60 description += "px";
[email protected]2a25d8022014-02-09 03:12:5561
[email protected]2a25d8022014-02-09 03:12:5562 return description;
63}
64
65} // namespace
66
[email protected]2a25d8022014-02-09 03:12:5567FontListImpl::FontListImpl(const std::string& font_description_string)
68 : font_description_string_(font_description_string),
69 common_height_(-1),
70 common_baseline_(-1),
71 font_style_(-1),
mboc998e8902016-06-02 11:40:3572 font_size_(-1),
73 font_weight_(Font::Weight::INVALID) {
[email protected]2a25d8022014-02-09 03:12:5574 DCHECK(!font_description_string.empty());
75 // DCHECK description string ends with "px" for size in pixel.
brettwa7ff1b292015-07-16 17:49:2976 DCHECK(base::EndsWith(font_description_string, "px",
77 base::CompareCase::SENSITIVE));
[email protected]2a25d8022014-02-09 03:12:5578}
79
80FontListImpl::FontListImpl(const std::vector<std::string>& font_names,
81 int font_style,
mboc998e8902016-06-02 11:40:3582 int font_size,
83 Font::Weight font_weight)
84 : font_description_string_(
85 BuildDescription(font_names, font_style, font_size, font_weight)),
[email protected]2a25d8022014-02-09 03:12:5586 common_height_(-1),
87 common_baseline_(-1),
88 font_style_(font_style),
mboc998e8902016-06-02 11:40:3589 font_size_(font_size),
90 font_weight_(font_weight) {
[email protected]2a25d8022014-02-09 03:12:5591 DCHECK(!font_names.empty());
92 DCHECK(!font_names[0].empty());
93}
94
95FontListImpl::FontListImpl(const std::vector<Font>& fonts)
96 : fonts_(fonts),
97 common_height_(-1),
98 common_baseline_(-1),
99 font_style_(-1),
mboc998e8902016-06-02 11:40:35100 font_size_(-1),
101 font_weight_(Font::Weight::INVALID) {
[email protected]2a25d8022014-02-09 03:12:55102 DCHECK(!fonts.empty());
103 font_style_ = fonts[0].GetStyle();
104 font_size_ = fonts[0].GetFontSize();
mboc998e8902016-06-02 11:40:35105 font_weight_ = fonts[0].GetWeight();
danakje649f572015-01-08 23:35:58106#if DCHECK_IS_ON()
[email protected]c02cb8012014-03-14 18:39:53107 for (size_t i = 1; i < fonts.size(); ++i) {
108 DCHECK_EQ(fonts[i].GetStyle(), font_style_);
109 DCHECK_EQ(fonts[i].GetFontSize(), font_size_);
[email protected]2a25d8022014-02-09 03:12:55110 }
[email protected]c02cb8012014-03-14 18:39:53111#endif
[email protected]2a25d8022014-02-09 03:12:55112}
113
114FontListImpl::FontListImpl(const Font& font)
115 : common_height_(-1),
116 common_baseline_(-1),
117 font_style_(-1),
mboc998e8902016-06-02 11:40:35118 font_size_(-1),
119 font_weight_(Font::Weight::INVALID) {
[email protected]2a25d8022014-02-09 03:12:55120 fonts_.push_back(font);
121}
122
mboc998e8902016-06-02 11:40:35123FontListImpl* FontListImpl::Derive(int size_delta,
124 int font_style,
125 Font::Weight weight) const {
[email protected]2a25d8022014-02-09 03:12:55126 // If there is a font vector, derive from that.
127 if (!fonts_.empty()) {
128 std::vector<Font> fonts = fonts_;
129 for (size_t i = 0; i < fonts.size(); ++i)
mboc998e8902016-06-02 11:40:35130 fonts[i] = fonts[i].Derive(size_delta, font_style, weight);
[email protected]2a25d8022014-02-09 03:12:55131 return new FontListImpl(fonts);
132 }
133
134 // Otherwise, parse the font description string to derive from it.
135 std::vector<std::string> font_names;
136 int old_size;
137 int old_style;
mboc998e8902016-06-02 11:40:35138 Font::Weight old_weight;
derat23144a62015-02-10 14:48:25139 CHECK(FontList::ParseDescription(font_description_string_, &font_names,
mboc998e8902016-06-02 11:40:35140 &old_style, &old_size, &old_weight));
[email protected]2a25d8022014-02-09 03:12:55141 const int size = std::max(1, old_size + size_delta);
mboc998e8902016-06-02 11:40:35142 return new FontListImpl(font_names, font_style, size, weight);
[email protected]2a25d8022014-02-09 03:12:55143}
144
145int FontListImpl::GetHeight() const {
146 if (common_height_ == -1)
147 CacheCommonFontHeightAndBaseline();
148 return common_height_;
149}
150
151int FontListImpl::GetBaseline() const {
152 if (common_baseline_ == -1)
153 CacheCommonFontHeightAndBaseline();
154 return common_baseline_;
155}
156
157int FontListImpl::GetCapHeight() const {
158 // Assume the primary font is used to render Latin characters.
159 return GetPrimaryFont().GetCapHeight();
160}
161
162int FontListImpl::GetExpectedTextWidth(int length) const {
163 // Rely on the primary font metrics for the time being.
164 return GetPrimaryFont().GetExpectedTextWidth(length);
165}
166
167int FontListImpl::GetFontStyle() const {
168 if (font_style_ == -1)
169 CacheFontStyleAndSize();
170 return font_style_;
171}
172
[email protected]2a25d8022014-02-09 03:12:55173int FontListImpl::GetFontSize() const {
174 if (font_size_ == -1)
175 CacheFontStyleAndSize();
176 return font_size_;
177}
178
mboc998e8902016-06-02 11:40:35179Font::Weight FontListImpl::GetFontWeight() const {
180 if (font_weight_ == Font::Weight::INVALID)
181 CacheFontStyleAndSize();
182 return font_weight_;
183}
184
[email protected]2a25d8022014-02-09 03:12:55185const std::vector<Font>& FontListImpl::GetFonts() const {
186 if (fonts_.empty()) {
187 DCHECK(!font_description_string_.empty());
188
189 std::vector<std::string> font_names;
mboc998e8902016-06-02 11:40:35190 // It's possible that Font::UNDERLINE is specified and it's already
[email protected]2a25d8022014-02-09 03:12:55191 // stored in |font_style_| but |font_description_string_| doesn't have the
192 // underline info. So we should respect |font_style_| as long as it's
193 // valid.
194 int style = 0;
derat23144a62015-02-10 14:48:25195 CHECK(FontList::ParseDescription(font_description_string_, &font_names,
mboc998e8902016-06-02 11:40:35196 &style, &font_size_, &font_weight_));
[email protected]2a25d8022014-02-09 03:12:55197 if (font_style_ == -1)
198 font_style_ = style;
199 for (size_t i = 0; i < font_names.size(); ++i) {
200 DCHECK(!font_names[i].empty());
201
202 Font font(font_names[i], font_size_);
mboc998e8902016-06-02 11:40:35203 if (font_style_ == Font::NORMAL && font_weight_ == Font::Weight::NORMAL)
[email protected]2a25d8022014-02-09 03:12:55204 fonts_.push_back(font);
205 else
mboc998e8902016-06-02 11:40:35206 fonts_.push_back(font.Derive(0, font_style_, font_weight_));
[email protected]2a25d8022014-02-09 03:12:55207 }
208 }
209 return fonts_;
210}
211
212const Font& FontListImpl::GetPrimaryFont() const {
213 return GetFonts()[0];
214}
215
216FontListImpl::~FontListImpl() {}
217
218void FontListImpl::CacheCommonFontHeightAndBaseline() const {
219 int ascent = 0;
220 int descent = 0;
221 const std::vector<Font>& fonts = GetFonts();
222 for (std::vector<Font>::const_iterator i = fonts.begin();
223 i != fonts.end(); ++i) {
224 ascent = std::max(ascent, i->GetBaseline());
225 descent = std::max(descent, i->GetHeight() - i->GetBaseline());
226 }
227 common_height_ = ascent + descent;
228 common_baseline_ = ascent;
229}
230
231void FontListImpl::CacheFontStyleAndSize() const {
232 if (!fonts_.empty()) {
233 font_style_ = fonts_[0].GetStyle();
234 font_size_ = fonts_[0].GetFontSize();
mboc998e8902016-06-02 11:40:35235 font_weight_ = fonts_[0].GetWeight();
[email protected]2a25d8022014-02-09 03:12:55236 } else {
237 std::vector<std::string> font_names;
derat23144a62015-02-10 14:48:25238 CHECK(FontList::ParseDescription(font_description_string_, &font_names,
mboc998e8902016-06-02 11:40:35239 &font_style_, &font_size_, &font_weight_));
[email protected]2a25d8022014-02-09 03:12:55240 }
241}
242
243} // namespace gfx