gpu: Tweak Android WebGL test expectations
[chromium-blink-merge.git] / ui / gfx / font_fallback_win.cc
blob40666ee239abd44d6493e74308cf7639b72bfab0
1 // Copyright (c) 2012 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.
5 #include "ui/gfx/font_fallback_win.h"
7 #include <map>
9 #include "base/memory/singleton.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/win/registry.h"
14 #include "ui/gfx/font.h"
16 namespace gfx {
18 namespace {
20 // Queries the registry to get a mapping from font filenames to font names.
21 void QueryFontsFromRegistry(std::map<std::string, std::string>* map) {
22 const wchar_t* kFonts =
23 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
25 base::win::RegistryValueIterator it(HKEY_LOCAL_MACHINE, kFonts);
26 for (; it.Valid(); ++it) {
27 const std::string filename = StringToLowerASCII(WideToUTF8(it.Value()));
28 (*map)[filename] = WideToUTF8(it.Name());
32 // Fills |font_names| with a list of font families found in the font file at
33 // |filename|. Takes in a |font_map| from font filename to font families, which
34 // is filled-in by querying the registry, if empty.
35 void GetFontNamesFromFilename(const std::string& filename,
36 std::map<std::string, std::string>* font_map,
37 std::vector<std::string>* font_names) {
38 if (font_map->empty())
39 QueryFontsFromRegistry(font_map);
41 std::map<std::string, std::string>::const_iterator it =
42 font_map->find(StringToLowerASCII(filename));
43 if (it == font_map->end())
44 return;
46 internal::ParseFontFamilyString(it->second, font_names);
49 // Returns true if |text| contains only ASCII digits.
50 bool ContainsOnlyDigits(const std::string& text) {
51 return text.find_first_not_of("0123456789") == base::string16::npos;
54 // Appends a Font with the given |name| and |size| to |fonts| unless the last
55 // entry is already a font with that name.
56 void AppendFont(const std::string& name, int size, std::vector<Font>* fonts) {
57 if (fonts->empty() || fonts->back().GetFontName() != name)
58 fonts->push_back(Font(name, size));
61 // Queries the registry to get a list of linked fonts for |font|.
62 void QueryLinkedFontsFromRegistry(const Font& font,
63 std::map<std::string, std::string>* font_map,
64 std::vector<Font>* linked_fonts) {
65 const wchar_t* kSystemLink =
66 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink";
68 base::win::RegKey key;
69 if (FAILED(key.Open(HKEY_LOCAL_MACHINE, kSystemLink, KEY_READ)))
70 return;
72 const std::wstring original_font_name = UTF8ToWide(font.GetFontName());
73 std::vector<std::wstring> values;
74 if (FAILED(key.ReadValues(original_font_name.c_str(), &values))) {
75 key.Close();
76 return;
79 std::string filename;
80 std::string font_name;
81 for (size_t i = 0; i < values.size(); ++i) {
82 internal::ParseFontLinkEntry(WideToUTF8(values[i]), &filename, &font_name);
83 // If the font name is present, add that directly, otherwise add the
84 // font names corresponding to the filename.
85 if (!font_name.empty()) {
86 AppendFont(font_name, font.GetFontSize(), linked_fonts);
87 } else if (!filename.empty()) {
88 std::vector<std::string> font_names;
89 GetFontNamesFromFilename(filename, font_map, &font_names);
90 for (size_t i = 0; i < font_names.size(); ++i)
91 AppendFont(font_names[i], font.GetFontSize(), linked_fonts);
95 key.Close();
98 // CachedFontLinkSettings is a singleton cache of the Windows font settings
99 // from the registry. It maintains a cached view of the registry's list of
100 // system fonts and their font link chains.
101 class CachedFontLinkSettings {
102 public:
103 static CachedFontLinkSettings* GetInstance();
105 // Returns the linked fonts list correspond to |font|. Returned value will
106 // never be null.
107 const std::vector<Font>* GetLinkedFonts(const Font& font);
109 private:
110 friend struct DefaultSingletonTraits<CachedFontLinkSettings>;
112 CachedFontLinkSettings();
113 virtual ~CachedFontLinkSettings();
115 // Map of system fonts, from file names to font families.
116 std::map<std::string, std::string> cached_system_fonts_;
118 // Map from font names to vectors of linked fonts.
119 std::map<std::string, std::vector<Font> > cached_linked_fonts_;
121 DISALLOW_COPY_AND_ASSIGN(CachedFontLinkSettings);
124 // static
125 CachedFontLinkSettings* CachedFontLinkSettings::GetInstance() {
126 return Singleton<CachedFontLinkSettings,
127 LeakySingletonTraits<CachedFontLinkSettings> >::get();
130 const std::vector<Font>* CachedFontLinkSettings::GetLinkedFonts(
131 const Font& font) {
132 const std::string& font_name = font.GetFontName();
133 std::map<std::string, std::vector<Font> >::const_iterator it =
134 cached_linked_fonts_.find(font_name);
135 if (it != cached_linked_fonts_.end())
136 return &it->second;
138 cached_linked_fonts_[font_name] = std::vector<Font>();
139 std::vector<Font>* linked_fonts = &cached_linked_fonts_[font_name];
140 QueryLinkedFontsFromRegistry(font, &cached_system_fonts_, linked_fonts);
141 return linked_fonts;
144 CachedFontLinkSettings::CachedFontLinkSettings() {
147 CachedFontLinkSettings::~CachedFontLinkSettings() {
150 } // namespace
152 namespace internal {
154 void ParseFontLinkEntry(const std::string& entry,
155 std::string* filename,
156 std::string* font_name) {
157 std::vector<std::string> parts;
158 base::SplitString(entry, ',', &parts);
159 filename->clear();
160 font_name->clear();
161 if (parts.size() > 0)
162 *filename = parts[0];
163 // The second entry may be the font name or the first scaling factor, if the
164 // entry does not contain a font name. If it contains only digits, assume it
165 // is a scaling factor.
166 if (parts.size() > 1 && !ContainsOnlyDigits(parts[1]))
167 *font_name = parts[1];
170 void ParseFontFamilyString(const std::string& family,
171 std::vector<std::string>* font_names) {
172 // The entry is comma separated, having the font filename as the first value
173 // followed optionally by the font family name and a pair of integer scaling
174 // factors.
175 // TODO(asvitkine): Should we support these scaling factors?
176 base::SplitString(family, '&', font_names);
177 if (!font_names->empty()) {
178 const size_t index = font_names->back().find('(');
179 if (index != std::string::npos) {
180 font_names->back().resize(index);
181 TrimWhitespace(font_names->back(), TRIM_TRAILING, &font_names->back());
186 } // namespace internal
188 LinkedFontsIterator::LinkedFontsIterator(Font font)
189 : original_font_(font),
190 next_font_set_(false),
191 linked_fonts_(NULL),
192 linked_font_index_(0) {
193 SetNextFont(original_font_);
196 LinkedFontsIterator::~LinkedFontsIterator() {
199 void LinkedFontsIterator::SetNextFont(Font font) {
200 next_font_ = font;
201 next_font_set_ = true;
204 bool LinkedFontsIterator::NextFont(Font* font) {
205 if (next_font_set_) {
206 next_font_set_ = false;
207 current_font_ = next_font_;
208 *font = current_font_;
209 return true;
212 // First time through, get the linked fonts list.
213 if (linked_fonts_ == NULL)
214 linked_fonts_ = GetLinkedFonts();
216 if (linked_font_index_ == linked_fonts_->size())
217 return false;
219 current_font_ = linked_fonts_->at(linked_font_index_++);
220 *font = current_font_;
221 return true;
224 const std::vector<Font>* LinkedFontsIterator::GetLinkedFonts() const {
225 CachedFontLinkSettings* font_link = CachedFontLinkSettings::GetInstance();
227 // First, try to get the list for the original font.
228 const std::vector<Font>* fonts = font_link->GetLinkedFonts(original_font_);
230 // If there are no linked fonts for the original font, try querying the
231 // ones for the current font. This may happen if the first font is a custom
232 // font that has no linked fonts in the registry.
234 // Note: One possibility would be to always merge both lists of fonts,
235 // but it is not clear whether there are any real world scenarios
236 // where this would actually help.
237 if (fonts->empty())
238 fonts = font_link->GetLinkedFonts(current_font_);
240 return fonts;
243 } // namespace gfx