font_list_impl.cc 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // 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. #include "ui/gfx/font_list_impl.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include "base/check_op.h"
  8. #include "base/strings/string_number_conversions.h"
  9. #include "base/strings/string_util.h"
  10. #include "ui/gfx/font_list.h"
  11. namespace gfx {
  12. namespace {
  13. // Returns a font description from |families|, |style|, and |size_pixels|.
  14. std::string BuildDescription(const std::vector<std::string>& families,
  15. int style,
  16. int size_pixels,
  17. Font::Weight weight) {
  18. std::string description = base::JoinString(families, ",");
  19. description += ",";
  20. if (style & Font::ITALIC)
  21. description += "Italic ";
  22. switch (weight) {
  23. case Font::Weight::THIN:
  24. description += "Thin ";
  25. break;
  26. case Font::Weight::EXTRA_LIGHT:
  27. description += "Ultra-Light ";
  28. break;
  29. case Font::Weight::LIGHT:
  30. description += "Light ";
  31. break;
  32. case Font::Weight::MEDIUM:
  33. description += "Medium ";
  34. break;
  35. case Font::Weight::SEMIBOLD:
  36. description += "Semi-Bold ";
  37. break;
  38. case Font::Weight::BOLD:
  39. description += "Bold ";
  40. break;
  41. case Font::Weight::EXTRA_BOLD:
  42. description += "Ultra-Bold ";
  43. break;
  44. case Font::Weight::BLACK:
  45. description += "Heavy ";
  46. break;
  47. case Font::Weight::NORMAL:
  48. case Font::Weight::INVALID:
  49. break;
  50. }
  51. description += base::NumberToString(size_pixels);
  52. description += "px";
  53. return description;
  54. }
  55. } // namespace
  56. FontListImpl::FontListImpl(const std::string& font_description_string)
  57. : font_description_string_(font_description_string),
  58. common_height_(-1),
  59. common_baseline_(-1),
  60. font_style_(-1),
  61. font_size_(-1),
  62. font_weight_(Font::Weight::INVALID) {
  63. DCHECK(!font_description_string.empty());
  64. // DCHECK description string ends with "px" for size in pixel.
  65. DCHECK(base::EndsWith(font_description_string, "px",
  66. base::CompareCase::SENSITIVE));
  67. }
  68. FontListImpl::FontListImpl(const std::vector<std::string>& font_names,
  69. int font_style,
  70. int font_size,
  71. Font::Weight font_weight)
  72. : font_description_string_(
  73. BuildDescription(font_names, font_style, font_size, font_weight)),
  74. common_height_(-1),
  75. common_baseline_(-1),
  76. font_style_(font_style),
  77. font_size_(font_size),
  78. font_weight_(font_weight) {
  79. DCHECK(!font_names.empty());
  80. DCHECK(!font_names[0].empty());
  81. }
  82. FontListImpl::FontListImpl(const std::vector<Font>& fonts)
  83. : fonts_(fonts),
  84. common_height_(-1),
  85. common_baseline_(-1),
  86. font_style_(-1),
  87. font_size_(-1),
  88. font_weight_(Font::Weight::INVALID) {
  89. DCHECK(!fonts.empty());
  90. font_style_ = fonts[0].GetStyle();
  91. font_size_ = fonts[0].GetFontSize();
  92. font_weight_ = fonts[0].GetWeight();
  93. #if DCHECK_IS_ON()
  94. for (size_t i = 1; i < fonts.size(); ++i) {
  95. DCHECK_EQ(fonts[i].GetStyle(), font_style_);
  96. DCHECK_EQ(fonts[i].GetFontSize(), font_size_);
  97. }
  98. #endif
  99. }
  100. FontListImpl::FontListImpl(const Font& font)
  101. : common_height_(-1),
  102. common_baseline_(-1),
  103. font_style_(-1),
  104. font_size_(-1),
  105. font_weight_(Font::Weight::INVALID) {
  106. fonts_.push_back(font);
  107. }
  108. FontListImpl* FontListImpl::Derive(int size_delta,
  109. int font_style,
  110. Font::Weight weight) const {
  111. // If there is a font vector, derive from that.
  112. if (!fonts_.empty()) {
  113. std::vector<Font> fonts = fonts_;
  114. for (size_t i = 0; i < fonts.size(); ++i)
  115. fonts[i] = fonts[i].Derive(size_delta, font_style, weight);
  116. return new FontListImpl(fonts);
  117. }
  118. // Otherwise, parse the font description string to derive from it.
  119. std::vector<std::string> font_names;
  120. int old_size;
  121. int old_style;
  122. Font::Weight old_weight;
  123. CHECK(FontList::ParseDescription(font_description_string_, &font_names,
  124. &old_style, &old_size, &old_weight));
  125. const int size = std::max(1, old_size + size_delta);
  126. return new FontListImpl(font_names, font_style, size, weight);
  127. }
  128. int FontListImpl::GetHeight() const {
  129. if (common_height_ == -1)
  130. CacheCommonFontHeightAndBaseline();
  131. return common_height_;
  132. }
  133. int FontListImpl::GetBaseline() const {
  134. if (common_baseline_ == -1)
  135. CacheCommonFontHeightAndBaseline();
  136. return common_baseline_;
  137. }
  138. int FontListImpl::GetCapHeight() const {
  139. // Assume the primary font is used to render Latin characters.
  140. return GetPrimaryFont().GetCapHeight();
  141. }
  142. int FontListImpl::GetExpectedTextWidth(int length) const {
  143. // Rely on the primary font metrics for the time being.
  144. return GetPrimaryFont().GetExpectedTextWidth(length);
  145. }
  146. int FontListImpl::GetFontStyle() const {
  147. if (font_style_ == -1)
  148. CacheFontStyleAndSize();
  149. return font_style_;
  150. }
  151. int FontListImpl::GetFontSize() const {
  152. if (font_size_ == -1)
  153. CacheFontStyleAndSize();
  154. return font_size_;
  155. }
  156. Font::Weight FontListImpl::GetFontWeight() const {
  157. if (font_weight_ == Font::Weight::INVALID)
  158. CacheFontStyleAndSize();
  159. return font_weight_;
  160. }
  161. const std::vector<Font>& FontListImpl::GetFonts() const {
  162. if (fonts_.empty()) {
  163. DCHECK(!font_description_string_.empty());
  164. std::vector<std::string> font_names;
  165. // It's possible that Font::UNDERLINE is specified and it's already
  166. // stored in |font_style_| but |font_description_string_| doesn't have the
  167. // underline info. So we should respect |font_style_| as long as it's
  168. // valid.
  169. int style = 0;
  170. CHECK(FontList::ParseDescription(font_description_string_, &font_names,
  171. &style, &font_size_, &font_weight_));
  172. if (font_style_ == -1)
  173. font_style_ = style;
  174. for (size_t i = 0; i < font_names.size(); ++i) {
  175. DCHECK(!font_names[i].empty());
  176. Font font(font_names[i], font_size_);
  177. if (font_style_ == Font::NORMAL && font_weight_ == Font::Weight::NORMAL)
  178. fonts_.push_back(font);
  179. else
  180. fonts_.push_back(font.Derive(0, font_style_, font_weight_));
  181. }
  182. }
  183. return fonts_;
  184. }
  185. const Font& FontListImpl::GetPrimaryFont() const {
  186. return GetFonts()[0];
  187. }
  188. FontListImpl::~FontListImpl() {}
  189. void FontListImpl::CacheCommonFontHeightAndBaseline() const {
  190. int ascent = 0;
  191. int descent = 0;
  192. const std::vector<Font>& fonts = GetFonts();
  193. for (auto i = fonts.begin(); i != fonts.end(); ++i) {
  194. ascent = std::max(ascent, i->GetBaseline());
  195. descent = std::max(descent, i->GetHeight() - i->GetBaseline());
  196. }
  197. common_height_ = ascent + descent;
  198. common_baseline_ = ascent;
  199. }
  200. void FontListImpl::CacheFontStyleAndSize() const {
  201. if (!fonts_.empty()) {
  202. font_style_ = fonts_[0].GetStyle();
  203. font_size_ = fonts_[0].GetFontSize();
  204. font_weight_ = fonts_[0].GetWeight();
  205. } else {
  206. std::vector<std::string> font_names;
  207. CHECK(FontList::ParseDescription(font_description_string_, &font_names,
  208. &font_style_, &font_size_, &font_weight_));
  209. }
  210. }
  211. } // namespace gfx