123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- // Copyright 2014 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ui/gfx/font_list_impl.h"
- #include <stddef.h>
- #include <algorithm>
- #include "base/check_op.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_util.h"
- #include "ui/gfx/font_list.h"
- namespace gfx {
- namespace {
- // Returns a font description from |families|, |style|, and |size_pixels|.
- std::string BuildDescription(const std::vector<std::string>& families,
- int style,
- int size_pixels,
- Font::Weight weight) {
- std::string description = base::JoinString(families, ",");
- description += ",";
- if (style & Font::ITALIC)
- description += "Italic ";
- switch (weight) {
- case Font::Weight::THIN:
- description += "Thin ";
- break;
- case Font::Weight::EXTRA_LIGHT:
- description += "Ultra-Light ";
- break;
- case Font::Weight::LIGHT:
- description += "Light ";
- break;
- case Font::Weight::MEDIUM:
- description += "Medium ";
- break;
- case Font::Weight::SEMIBOLD:
- description += "Semi-Bold ";
- break;
- case Font::Weight::BOLD:
- description += "Bold ";
- break;
- case Font::Weight::EXTRA_BOLD:
- description += "Ultra-Bold ";
- break;
- case Font::Weight::BLACK:
- description += "Heavy ";
- break;
- case Font::Weight::NORMAL:
- case Font::Weight::INVALID:
- break;
- }
- description += base::NumberToString(size_pixels);
- description += "px";
- return description;
- }
- } // namespace
- FontListImpl::FontListImpl(const std::string& font_description_string)
- : font_description_string_(font_description_string),
- common_height_(-1),
- common_baseline_(-1),
- font_style_(-1),
- font_size_(-1),
- font_weight_(Font::Weight::INVALID) {
- DCHECK(!font_description_string.empty());
- // DCHECK description string ends with "px" for size in pixel.
- DCHECK(base::EndsWith(font_description_string, "px",
- base::CompareCase::SENSITIVE));
- }
- FontListImpl::FontListImpl(const std::vector<std::string>& font_names,
- int font_style,
- int font_size,
- Font::Weight font_weight)
- : font_description_string_(
- BuildDescription(font_names, font_style, font_size, font_weight)),
- common_height_(-1),
- common_baseline_(-1),
- font_style_(font_style),
- font_size_(font_size),
- font_weight_(font_weight) {
- DCHECK(!font_names.empty());
- DCHECK(!font_names[0].empty());
- }
- FontListImpl::FontListImpl(const std::vector<Font>& fonts)
- : fonts_(fonts),
- common_height_(-1),
- common_baseline_(-1),
- font_style_(-1),
- font_size_(-1),
- font_weight_(Font::Weight::INVALID) {
- DCHECK(!fonts.empty());
- font_style_ = fonts[0].GetStyle();
- font_size_ = fonts[0].GetFontSize();
- font_weight_ = fonts[0].GetWeight();
- #if DCHECK_IS_ON()
- for (size_t i = 1; i < fonts.size(); ++i) {
- DCHECK_EQ(fonts[i].GetStyle(), font_style_);
- DCHECK_EQ(fonts[i].GetFontSize(), font_size_);
- }
- #endif
- }
- FontListImpl::FontListImpl(const Font& font)
- : common_height_(-1),
- common_baseline_(-1),
- font_style_(-1),
- font_size_(-1),
- font_weight_(Font::Weight::INVALID) {
- fonts_.push_back(font);
- }
- FontListImpl* FontListImpl::Derive(int size_delta,
- int font_style,
- Font::Weight weight) const {
- // If there is a font vector, derive from that.
- if (!fonts_.empty()) {
- std::vector<Font> fonts = fonts_;
- for (size_t i = 0; i < fonts.size(); ++i)
- fonts[i] = fonts[i].Derive(size_delta, font_style, weight);
- return new FontListImpl(fonts);
- }
- // Otherwise, parse the font description string to derive from it.
- std::vector<std::string> font_names;
- int old_size;
- int old_style;
- Font::Weight old_weight;
- CHECK(FontList::ParseDescription(font_description_string_, &font_names,
- &old_style, &old_size, &old_weight));
- const int size = std::max(1, old_size + size_delta);
- return new FontListImpl(font_names, font_style, size, weight);
- }
- int FontListImpl::GetHeight() const {
- if (common_height_ == -1)
- CacheCommonFontHeightAndBaseline();
- return common_height_;
- }
- int FontListImpl::GetBaseline() const {
- if (common_baseline_ == -1)
- CacheCommonFontHeightAndBaseline();
- return common_baseline_;
- }
- int FontListImpl::GetCapHeight() const {
- // Assume the primary font is used to render Latin characters.
- return GetPrimaryFont().GetCapHeight();
- }
- int FontListImpl::GetExpectedTextWidth(int length) const {
- // Rely on the primary font metrics for the time being.
- return GetPrimaryFont().GetExpectedTextWidth(length);
- }
- int FontListImpl::GetFontStyle() const {
- if (font_style_ == -1)
- CacheFontStyleAndSize();
- return font_style_;
- }
- int FontListImpl::GetFontSize() const {
- if (font_size_ == -1)
- CacheFontStyleAndSize();
- return font_size_;
- }
- Font::Weight FontListImpl::GetFontWeight() const {
- if (font_weight_ == Font::Weight::INVALID)
- CacheFontStyleAndSize();
- return font_weight_;
- }
- const std::vector<Font>& FontListImpl::GetFonts() const {
- if (fonts_.empty()) {
- DCHECK(!font_description_string_.empty());
- std::vector<std::string> font_names;
- // It's possible that Font::UNDERLINE is specified and it's already
- // stored in |font_style_| but |font_description_string_| doesn't have the
- // underline info. So we should respect |font_style_| as long as it's
- // valid.
- int style = 0;
- CHECK(FontList::ParseDescription(font_description_string_, &font_names,
- &style, &font_size_, &font_weight_));
- if (font_style_ == -1)
- font_style_ = style;
- for (size_t i = 0; i < font_names.size(); ++i) {
- DCHECK(!font_names[i].empty());
- Font font(font_names[i], font_size_);
- if (font_style_ == Font::NORMAL && font_weight_ == Font::Weight::NORMAL)
- fonts_.push_back(font);
- else
- fonts_.push_back(font.Derive(0, font_style_, font_weight_));
- }
- }
- return fonts_;
- }
- const Font& FontListImpl::GetPrimaryFont() const {
- return GetFonts()[0];
- }
- FontListImpl::~FontListImpl() {}
- void FontListImpl::CacheCommonFontHeightAndBaseline() const {
- int ascent = 0;
- int descent = 0;
- const std::vector<Font>& fonts = GetFonts();
- for (auto i = fonts.begin(); i != fonts.end(); ++i) {
- ascent = std::max(ascent, i->GetBaseline());
- descent = std::max(descent, i->GetHeight() - i->GetBaseline());
- }
- common_height_ = ascent + descent;
- common_baseline_ = ascent;
- }
- void FontListImpl::CacheFontStyleAndSize() const {
- if (!fonts_.empty()) {
- font_style_ = fonts_[0].GetStyle();
- font_size_ = fonts_[0].GetFontSize();
- font_weight_ = fonts_[0].GetWeight();
- } else {
- std::vector<std::string> font_names;
- CHECK(FontList::ParseDescription(font_description_string_, &font_names,
- &font_style_, &font_size_, &font_weight_));
- }
- }
- } // namespace gfx
|