blob: 3bab76feacefdc025d3418f227b6d89f2fcca31b [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"
14#include "ui/gfx/font.h"
derat23144a62015-02-10 14:48:2515#include "ui/gfx/font_list.h"
[email protected]2a25d8022014-02-09 03:12:5516
17namespace {
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,
22 int size_pixels) {
brettwd94a22142015-07-15 05:19:2623 std::string description = base::JoinString(families, ",");
derat23144a62015-02-10 14:48:2524 description += ",";
[email protected]2a25d8022014-02-09 03:12:5525
derat23144a62015-02-10 14:48:2526 if (style & gfx::Font::BOLD)
27 description += "Bold ";
28 if (style & gfx::Font::ITALIC)
29 description += "Italic ";
[email protected]2a25d8022014-02-09 03:12:5530
derat23144a62015-02-10 14:48:2531 description += base::IntToString(size_pixels);
32 description += "px";
[email protected]2a25d8022014-02-09 03:12:5533
[email protected]2a25d8022014-02-09 03:12:5534 return description;
35}
36
37} // namespace
38
39namespace gfx {
40
41FontListImpl::FontListImpl(const std::string& font_description_string)
42 : font_description_string_(font_description_string),
43 common_height_(-1),
44 common_baseline_(-1),
45 font_style_(-1),
46 font_size_(-1) {
47 DCHECK(!font_description_string.empty());
48 // DCHECK description string ends with "px" for size in pixel.
brettwa7ff1b292015-07-16 17:49:2949 DCHECK(base::EndsWith(font_description_string, "px",
50 base::CompareCase::SENSITIVE));
[email protected]2a25d8022014-02-09 03:12:5551}
52
53FontListImpl::FontListImpl(const std::vector<std::string>& font_names,
54 int font_style,
55 int font_size)
derat23144a62015-02-10 14:48:2556 : font_description_string_(BuildDescription(font_names, font_style,
57 font_size)),
[email protected]2a25d8022014-02-09 03:12:5558 common_height_(-1),
59 common_baseline_(-1),
60 font_style_(font_style),
61 font_size_(font_size) {
62 DCHECK(!font_names.empty());
63 DCHECK(!font_names[0].empty());
64}
65
66FontListImpl::FontListImpl(const std::vector<Font>& fonts)
67 : fonts_(fonts),
68 common_height_(-1),
69 common_baseline_(-1),
70 font_style_(-1),
71 font_size_(-1) {
72 DCHECK(!fonts.empty());
73 font_style_ = fonts[0].GetStyle();
74 font_size_ = fonts[0].GetFontSize();
danakje649f572015-01-08 23:35:5875#if DCHECK_IS_ON()
[email protected]c02cb8012014-03-14 18:39:5376 for (size_t i = 1; i < fonts.size(); ++i) {
77 DCHECK_EQ(fonts[i].GetStyle(), font_style_);
78 DCHECK_EQ(fonts[i].GetFontSize(), font_size_);
[email protected]2a25d8022014-02-09 03:12:5579 }
[email protected]c02cb8012014-03-14 18:39:5380#endif
[email protected]2a25d8022014-02-09 03:12:5581}
82
83FontListImpl::FontListImpl(const Font& font)
84 : common_height_(-1),
85 common_baseline_(-1),
86 font_style_(-1),
87 font_size_(-1) {
88 fonts_.push_back(font);
89}
90
91FontListImpl* FontListImpl::Derive(int size_delta, int font_style) const {
92 // If there is a font vector, derive from that.
93 if (!fonts_.empty()) {
94 std::vector<Font> fonts = fonts_;
95 for (size_t i = 0; i < fonts.size(); ++i)
[email protected]01430822014-02-13 15:41:4596 fonts[i] = fonts[i].Derive(size_delta, font_style);
[email protected]2a25d8022014-02-09 03:12:5597 return new FontListImpl(fonts);
98 }
99
100 // Otherwise, parse the font description string to derive from it.
101 std::vector<std::string> font_names;
102 int old_size;
103 int old_style;
derat23144a62015-02-10 14:48:25104 CHECK(FontList::ParseDescription(font_description_string_, &font_names,
105 &old_style, &old_size));
[email protected]2a25d8022014-02-09 03:12:55106 const int size = std::max(1, old_size + size_delta);
107 return new FontListImpl(font_names, font_style, size);
108}
109
110int FontListImpl::GetHeight() const {
111 if (common_height_ == -1)
112 CacheCommonFontHeightAndBaseline();
113 return common_height_;
114}
115
116int FontListImpl::GetBaseline() const {
117 if (common_baseline_ == -1)
118 CacheCommonFontHeightAndBaseline();
119 return common_baseline_;
120}
121
122int FontListImpl::GetCapHeight() const {
123 // Assume the primary font is used to render Latin characters.
124 return GetPrimaryFont().GetCapHeight();
125}
126
127int FontListImpl::GetExpectedTextWidth(int length) const {
128 // Rely on the primary font metrics for the time being.
129 return GetPrimaryFont().GetExpectedTextWidth(length);
130}
131
132int FontListImpl::GetFontStyle() const {
133 if (font_style_ == -1)
134 CacheFontStyleAndSize();
135 return font_style_;
136}
137
[email protected]2a25d8022014-02-09 03:12:55138int FontListImpl::GetFontSize() const {
139 if (font_size_ == -1)
140 CacheFontStyleAndSize();
141 return font_size_;
142}
143
144const std::vector<Font>& FontListImpl::GetFonts() const {
145 if (fonts_.empty()) {
146 DCHECK(!font_description_string_.empty());
147
148 std::vector<std::string> font_names;
149 // It's possible that gfx::Font::UNDERLINE is specified and it's already
150 // stored in |font_style_| but |font_description_string_| doesn't have the
151 // underline info. So we should respect |font_style_| as long as it's
152 // valid.
153 int style = 0;
derat23144a62015-02-10 14:48:25154 CHECK(FontList::ParseDescription(font_description_string_, &font_names,
155 &style, &font_size_));
[email protected]2a25d8022014-02-09 03:12:55156 if (font_style_ == -1)
157 font_style_ = style;
158 for (size_t i = 0; i < font_names.size(); ++i) {
159 DCHECK(!font_names[i].empty());
160
161 Font font(font_names[i], font_size_);
162 if (font_style_ == Font::NORMAL)
163 fonts_.push_back(font);
164 else
[email protected]01430822014-02-13 15:41:45165 fonts_.push_back(font.Derive(0, font_style_));
[email protected]2a25d8022014-02-09 03:12:55166 }
167 }
168 return fonts_;
169}
170
171const Font& FontListImpl::GetPrimaryFont() const {
172 return GetFonts()[0];
173}
174
175FontListImpl::~FontListImpl() {}
176
177void FontListImpl::CacheCommonFontHeightAndBaseline() const {
178 int ascent = 0;
179 int descent = 0;
180 const std::vector<Font>& fonts = GetFonts();
181 for (std::vector<Font>::const_iterator i = fonts.begin();
182 i != fonts.end(); ++i) {
183 ascent = std::max(ascent, i->GetBaseline());
184 descent = std::max(descent, i->GetHeight() - i->GetBaseline());
185 }
186 common_height_ = ascent + descent;
187 common_baseline_ = ascent;
188}
189
190void FontListImpl::CacheFontStyleAndSize() const {
191 if (!fonts_.empty()) {
192 font_style_ = fonts_[0].GetStyle();
193 font_size_ = fonts_[0].GetFontSize();
194 } else {
195 std::vector<std::string> font_names;
derat23144a62015-02-10 14:48:25196 CHECK(FontList::ParseDescription(font_description_string_, &font_names,
197 &font_style_, &font_size_));
[email protected]2a25d8022014-02-09 03:12:55198 }
199}
200
201} // namespace gfx