Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(373)

Side by Side Diff: ui/gfx/font_fallback_win.cc

Issue 331713003: RenderTextHarfBuzz: Implement font fallback for Win and Linux (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: gyp -> gn Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/font_fallback_win.h" 5 #include "ui/gfx/font_fallback_win.h"
6 6
7 #include <usp10.h>
8
7 #include <map> 9 #include <map>
8 10
9 #include "base/memory/singleton.h" 11 #include "base/memory/singleton.h"
10 #include "base/strings/string_split.h" 12 #include "base/strings/string_split.h"
11 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
12 #include "base/strings/utf_string_conversions.h" 14 #include "base/strings/utf_string_conversions.h"
13 #include "base/win/registry.h" 15 #include "base/win/registry.h"
14 #include "ui/gfx/font.h" 16 #include "ui/gfx/font.h"
17 #include "ui/gfx/font_fallback.h"
15 18
16 namespace gfx { 19 namespace gfx {
17 20
18 namespace { 21 namespace {
19 22
20 // Queries the registry to get a mapping from font filenames to font names. 23 // Queries the registry to get a mapping from font filenames to font names.
21 void QueryFontsFromRegistry(std::map<std::string, std::string>* map) { 24 void QueryFontsFromRegistry(std::map<std::string, std::string>* map) {
22 const wchar_t* kFonts = 25 const wchar_t* kFonts =
23 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"; 26 L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
24 27
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 QueryLinkedFontsFromRegistry(font, &cached_system_fonts_, linked_fonts); 145 QueryLinkedFontsFromRegistry(font, &cached_system_fonts_, linked_fonts);
143 return linked_fonts; 146 return linked_fonts;
144 } 147 }
145 148
146 CachedFontLinkSettings::CachedFontLinkSettings() { 149 CachedFontLinkSettings::CachedFontLinkSettings() {
147 } 150 }
148 151
149 CachedFontLinkSettings::~CachedFontLinkSettings() { 152 CachedFontLinkSettings::~CachedFontLinkSettings() {
150 } 153 }
151 154
155 // Callback to |EnumEnhMetaFile()| to intercept font creation.
156 int CALLBACK MetaFileEnumProc(HDC hdc,
157 HANDLETABLE* table,
158 CONST ENHMETARECORD* record,
159 int table_entries,
160 LPARAM log_font) {
161 if (record->iType == EMR_EXTCREATEFONTINDIRECTW) {
162 const EMREXTCREATEFONTINDIRECTW* create_font_record =
163 reinterpret_cast<const EMREXTCREATEFONTINDIRECTW*>(record);
164 *reinterpret_cast<LOGFONT*>(log_font) = create_font_record->elfw.elfLogFont;
165 }
166 return 1;
167 }
168
152 } // namespace 169 } // namespace
153 170
154 namespace internal { 171 namespace internal {
155 172
156 void ParseFontLinkEntry(const std::string& entry, 173 void ParseFontLinkEntry(const std::string& entry,
157 std::string* filename, 174 std::string* filename,
158 std::string* font_name) { 175 std::string* font_name) {
159 std::vector<std::string> parts; 176 std::vector<std::string> parts;
160 base::SplitString(entry, ',', &parts); 177 base::SplitString(entry, ',', &parts);
161 filename->clear(); 178 filename->clear();
(...skipping 17 matching lines...) Expand all
179 if (!font_names->empty()) { 196 if (!font_names->empty()) {
180 const size_t index = font_names->back().find('('); 197 const size_t index = font_names->back().find('(');
181 if (index != std::string::npos) { 198 if (index != std::string::npos) {
182 font_names->back().resize(index); 199 font_names->back().resize(index);
183 base::TrimWhitespace(font_names->back(), base::TRIM_TRAILING, 200 base::TrimWhitespace(font_names->back(), base::TRIM_TRAILING,
184 &font_names->back()); 201 &font_names->back());
185 } 202 }
186 } 203 }
187 } 204 }
188 205
189 } // namespace internal
190
191 LinkedFontsIterator::LinkedFontsIterator(Font font) 206 LinkedFontsIterator::LinkedFontsIterator(Font font)
192 : original_font_(font), 207 : original_font_(font),
193 next_font_set_(false), 208 next_font_set_(false),
194 linked_fonts_(NULL), 209 linked_fonts_(NULL),
195 linked_font_index_(0) { 210 linked_font_index_(0) {
196 SetNextFont(original_font_); 211 SetNextFont(original_font_);
197 } 212 }
198 213
199 LinkedFontsIterator::~LinkedFontsIterator() { 214 LinkedFontsIterator::~LinkedFontsIterator() {
200 } 215 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 // 251 //
237 // Note: One possibility would be to always merge both lists of fonts, 252 // Note: One possibility would be to always merge both lists of fonts,
238 // but it is not clear whether there are any real world scenarios 253 // but it is not clear whether there are any real world scenarios
239 // where this would actually help. 254 // where this would actually help.
240 if (fonts->empty()) 255 if (fonts->empty())
241 fonts = font_link->GetLinkedFonts(current_font_); 256 fonts = font_link->GetLinkedFonts(current_font_);
242 257
243 return fonts; 258 return fonts;
244 } 259 }
245 260
261 } // namespace internal
262
263 std::vector<std::string> GetFallbackFontFamilies(
264 const std::string& font_family) {
265 // LinkedFontsIterator doesn't care about the font size, so we always pass 10.
266 internal::LinkedFontsIterator linked_fonts(Font(font_family, 10));
267 std::vector<std::string> fallback_fonts;
268 Font current;
269 while (linked_fonts.NextFont(&current))
270 fallback_fonts.push_back(current.GetFontName());
271 return fallback_fonts;
272 }
273
274 bool GetUniscribeFallbackFont(const Font& font,
275 const wchar_t* text,
276 int text_length,
277 Font* result) {
278 // Adapted from WebKit's |FontCache::GetFontDataForCharacters()|.
279 // Uniscribe doesn't expose a method to query fallback fonts, so this works by
280 // drawing the text to an EMF object with Uniscribe's ScriptStringOut and then
281 // inspecting the EMF object to figure out which font Uniscribe used.
282 //
283 // DirectWrite in Windows 8.1 provides a cleaner alternative:
284 // http://msdn.microsoft.com/en-us/library/windows/desktop/dn280480.aspx
285
286 static HDC hdc = CreateCompatibleDC(NULL);
287
288 // Use a meta file to intercept the fallback font chosen by Uniscribe.
289 HDC meta_file_dc = CreateEnhMetaFile(hdc, NULL, NULL, NULL);
290 if (!meta_file_dc)
291 return false;
292
293 SelectObject(meta_file_dc, font.GetNativeFont());
294
295 SCRIPT_STRING_ANALYSIS script_analysis;
296 HRESULT hresult =
297 ScriptStringAnalyse(meta_file_dc, text, text_length, 0, -1,
298 SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK,
299 0, NULL, NULL, NULL, NULL, NULL, &script_analysis);
300
301 if (SUCCEEDED(hresult)) {
302 hresult = ScriptStringOut(script_analysis, 0, 0, 0, NULL, 0, 0, FALSE);
303 ScriptStringFree(&script_analysis);
304 }
305
306 bool found_fallback = false;
307 HENHMETAFILE meta_file = CloseEnhMetaFile(meta_file_dc);
308 if (SUCCEEDED(hresult)) {
309 LOGFONT log_font;
310 log_font.lfFaceName[0] = 0;
311 EnumEnhMetaFile(0, meta_file, MetaFileEnumProc, &log_font, NULL);
312 if (log_font.lfFaceName[0]) {
313 *result = Font(base::UTF16ToUTF8(log_font.lfFaceName),
314 font.GetFontSize());
315 found_fallback = true;
316 }
317 }
318 DeleteEnhMetaFile(meta_file);
319
320 return found_fallback;
321 }
322
246 } // namespace gfx 323 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698