Index: ui/gfx/font_fallback_win.cc |
diff --git a/ui/gfx/font_fallback_win.cc b/ui/gfx/font_fallback_win.cc |
deleted file mode 100644 |
index 2e1959b1e802ff8a17ad16b9288209c937cc3e8f..0000000000000000000000000000000000000000 |
--- a/ui/gfx/font_fallback_win.cc |
+++ /dev/null |
@@ -1,323 +0,0 @@ |
-// Copyright (c) 2012 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_fallback_win.h" |
- |
-#include <usp10.h> |
- |
-#include <map> |
- |
-#include "base/memory/singleton.h" |
-#include "base/strings/string_split.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "base/win/registry.h" |
-#include "ui/gfx/font.h" |
-#include "ui/gfx/font_fallback.h" |
- |
-namespace gfx { |
- |
-namespace { |
- |
-// Queries the registry to get a mapping from font filenames to font names. |
-void QueryFontsFromRegistry(std::map<std::string, std::string>* map) { |
- const wchar_t* kFonts = |
- L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts"; |
- |
- base::win::RegistryValueIterator it(HKEY_LOCAL_MACHINE, kFonts); |
- for (; it.Valid(); ++it) { |
- const std::string filename = |
- base::StringToLowerASCII(base::WideToUTF8(it.Value())); |
- (*map)[filename] = base::WideToUTF8(it.Name()); |
- } |
-} |
- |
-// Fills |font_names| with a list of font families found in the font file at |
-// |filename|. Takes in a |font_map| from font filename to font families, which |
-// is filled-in by querying the registry, if empty. |
-void GetFontNamesFromFilename(const std::string& filename, |
- std::map<std::string, std::string>* font_map, |
- std::vector<std::string>* font_names) { |
- if (font_map->empty()) |
- QueryFontsFromRegistry(font_map); |
- |
- std::map<std::string, std::string>::const_iterator it = |
- font_map->find(base::StringToLowerASCII(filename)); |
- if (it == font_map->end()) |
- return; |
- |
- internal::ParseFontFamilyString(it->second, font_names); |
-} |
- |
-// Returns true if |text| contains only ASCII digits. |
-bool ContainsOnlyDigits(const std::string& text) { |
- return text.find_first_not_of("0123456789") == base::string16::npos; |
-} |
- |
-// Appends a Font with the given |name| and |size| to |fonts| unless the last |
-// entry is already a font with that name. |
-void AppendFont(const std::string& name, int size, std::vector<Font>* fonts) { |
- if (fonts->empty() || fonts->back().GetFontName() != name) |
- fonts->push_back(Font(name, size)); |
-} |
- |
-// Queries the registry to get a list of linked fonts for |font|. |
-void QueryLinkedFontsFromRegistry(const Font& font, |
- std::map<std::string, std::string>* font_map, |
- std::vector<Font>* linked_fonts) { |
- const wchar_t* kSystemLink = |
- L"Software\\Microsoft\\Windows NT\\CurrentVersion\\FontLink\\SystemLink"; |
- |
- base::win::RegKey key; |
- if (FAILED(key.Open(HKEY_LOCAL_MACHINE, kSystemLink, KEY_READ))) |
- return; |
- |
- const std::wstring original_font_name = base::UTF8ToWide(font.GetFontName()); |
- std::vector<std::wstring> values; |
- if (FAILED(key.ReadValues(original_font_name.c_str(), &values))) { |
- key.Close(); |
- return; |
- } |
- |
- std::string filename; |
- std::string font_name; |
- for (size_t i = 0; i < values.size(); ++i) { |
- internal::ParseFontLinkEntry( |
- base::WideToUTF8(values[i]), &filename, &font_name); |
- // If the font name is present, add that directly, otherwise add the |
- // font names corresponding to the filename. |
- if (!font_name.empty()) { |
- AppendFont(font_name, font.GetFontSize(), linked_fonts); |
- } else if (!filename.empty()) { |
- std::vector<std::string> font_names; |
- GetFontNamesFromFilename(filename, font_map, &font_names); |
- for (size_t i = 0; i < font_names.size(); ++i) |
- AppendFont(font_names[i], font.GetFontSize(), linked_fonts); |
- } |
- } |
- |
- key.Close(); |
-} |
- |
-// CachedFontLinkSettings is a singleton cache of the Windows font settings |
-// from the registry. It maintains a cached view of the registry's list of |
-// system fonts and their font link chains. |
-class CachedFontLinkSettings { |
- public: |
- static CachedFontLinkSettings* GetInstance(); |
- |
- // Returns the linked fonts list correspond to |font|. Returned value will |
- // never be null. |
- const std::vector<Font>* GetLinkedFonts(const Font& font); |
- |
- private: |
- friend struct DefaultSingletonTraits<CachedFontLinkSettings>; |
- |
- CachedFontLinkSettings(); |
- virtual ~CachedFontLinkSettings(); |
- |
- // Map of system fonts, from file names to font families. |
- std::map<std::string, std::string> cached_system_fonts_; |
- |
- // Map from font names to vectors of linked fonts. |
- std::map<std::string, std::vector<Font> > cached_linked_fonts_; |
- |
- DISALLOW_COPY_AND_ASSIGN(CachedFontLinkSettings); |
-}; |
- |
-// static |
-CachedFontLinkSettings* CachedFontLinkSettings::GetInstance() { |
- return Singleton<CachedFontLinkSettings, |
- LeakySingletonTraits<CachedFontLinkSettings> >::get(); |
-} |
- |
-const std::vector<Font>* CachedFontLinkSettings::GetLinkedFonts( |
- const Font& font) { |
- const std::string& font_name = font.GetFontName(); |
- std::map<std::string, std::vector<Font> >::const_iterator it = |
- cached_linked_fonts_.find(font_name); |
- if (it != cached_linked_fonts_.end()) |
- return &it->second; |
- |
- cached_linked_fonts_[font_name] = std::vector<Font>(); |
- std::vector<Font>* linked_fonts = &cached_linked_fonts_[font_name]; |
- QueryLinkedFontsFromRegistry(font, &cached_system_fonts_, linked_fonts); |
- return linked_fonts; |
-} |
- |
-CachedFontLinkSettings::CachedFontLinkSettings() { |
-} |
- |
-CachedFontLinkSettings::~CachedFontLinkSettings() { |
-} |
- |
-// Callback to |EnumEnhMetaFile()| to intercept font creation. |
-int CALLBACK MetaFileEnumProc(HDC hdc, |
- HANDLETABLE* table, |
- CONST ENHMETARECORD* record, |
- int table_entries, |
- LPARAM log_font) { |
- if (record->iType == EMR_EXTCREATEFONTINDIRECTW) { |
- const EMREXTCREATEFONTINDIRECTW* create_font_record = |
- reinterpret_cast<const EMREXTCREATEFONTINDIRECTW*>(record); |
- *reinterpret_cast<LOGFONT*>(log_font) = create_font_record->elfw.elfLogFont; |
- } |
- return 1; |
-} |
- |
-} // namespace |
- |
-namespace internal { |
- |
-void ParseFontLinkEntry(const std::string& entry, |
- std::string* filename, |
- std::string* font_name) { |
- std::vector<std::string> parts; |
- base::SplitString(entry, ',', &parts); |
- filename->clear(); |
- font_name->clear(); |
- if (parts.size() > 0) |
- *filename = parts[0]; |
- // The second entry may be the font name or the first scaling factor, if the |
- // entry does not contain a font name. If it contains only digits, assume it |
- // is a scaling factor. |
- if (parts.size() > 1 && !ContainsOnlyDigits(parts[1])) |
- *font_name = parts[1]; |
-} |
- |
-void ParseFontFamilyString(const std::string& family, |
- std::vector<std::string>* font_names) { |
- // The entry is comma separated, having the font filename as the first value |
- // followed optionally by the font family name and a pair of integer scaling |
- // factors. |
- // TODO(asvitkine): Should we support these scaling factors? |
- base::SplitString(family, '&', font_names); |
- if (!font_names->empty()) { |
- const size_t index = font_names->back().find('('); |
- if (index != std::string::npos) { |
- font_names->back().resize(index); |
- base::TrimWhitespace(font_names->back(), base::TRIM_TRAILING, |
- &font_names->back()); |
- } |
- } |
-} |
- |
-LinkedFontsIterator::LinkedFontsIterator(Font font) |
- : original_font_(font), |
- next_font_set_(false), |
- linked_fonts_(NULL), |
- linked_font_index_(0) { |
- SetNextFont(original_font_); |
-} |
- |
-LinkedFontsIterator::~LinkedFontsIterator() { |
-} |
- |
-void LinkedFontsIterator::SetNextFont(Font font) { |
- next_font_ = font; |
- next_font_set_ = true; |
-} |
- |
-bool LinkedFontsIterator::NextFont(Font* font) { |
- if (next_font_set_) { |
- next_font_set_ = false; |
- current_font_ = next_font_; |
- *font = current_font_; |
- return true; |
- } |
- |
- // First time through, get the linked fonts list. |
- if (linked_fonts_ == NULL) |
- linked_fonts_ = GetLinkedFonts(); |
- |
- if (linked_font_index_ == linked_fonts_->size()) |
- return false; |
- |
- current_font_ = linked_fonts_->at(linked_font_index_++); |
- *font = current_font_; |
- return true; |
-} |
- |
-const std::vector<Font>* LinkedFontsIterator::GetLinkedFonts() const { |
- CachedFontLinkSettings* font_link = CachedFontLinkSettings::GetInstance(); |
- |
- // First, try to get the list for the original font. |
- const std::vector<Font>* fonts = font_link->GetLinkedFonts(original_font_); |
- |
- // If there are no linked fonts for the original font, try querying the |
- // ones for the current font. This may happen if the first font is a custom |
- // font that has no linked fonts in the registry. |
- // |
- // Note: One possibility would be to always merge both lists of fonts, |
- // but it is not clear whether there are any real world scenarios |
- // where this would actually help. |
- if (fonts->empty()) |
- fonts = font_link->GetLinkedFonts(current_font_); |
- |
- return fonts; |
-} |
- |
-} // namespace internal |
- |
-std::vector<std::string> GetFallbackFontFamilies( |
- const std::string& font_family) { |
- // LinkedFontsIterator doesn't care about the font size, so we always pass 10. |
- internal::LinkedFontsIterator linked_fonts(Font(font_family, 10)); |
- std::vector<std::string> fallback_fonts; |
- Font current; |
- while (linked_fonts.NextFont(¤t)) |
- fallback_fonts.push_back(current.GetFontName()); |
- return fallback_fonts; |
-} |
- |
-bool GetUniscribeFallbackFont(const Font& font, |
- const wchar_t* text, |
- int text_length, |
- Font* result) { |
- // Adapted from WebKit's |FontCache::GetFontDataForCharacters()|. |
- // Uniscribe doesn't expose a method to query fallback fonts, so this works by |
- // drawing the text to an EMF object with Uniscribe's ScriptStringOut and then |
- // inspecting the EMF object to figure out which font Uniscribe used. |
- // |
- // DirectWrite in Windows 8.1 provides a cleaner alternative: |
- // http://msdn.microsoft.com/en-us/library/windows/desktop/dn280480.aspx |
- |
- static HDC hdc = CreateCompatibleDC(NULL); |
- |
- // Use a meta file to intercept the fallback font chosen by Uniscribe. |
- HDC meta_file_dc = CreateEnhMetaFile(hdc, NULL, NULL, NULL); |
- if (!meta_file_dc) |
- return false; |
- |
- SelectObject(meta_file_dc, font.GetNativeFont()); |
- |
- SCRIPT_STRING_ANALYSIS script_analysis; |
- HRESULT hresult = |
- ScriptStringAnalyse(meta_file_dc, text, text_length, 0, -1, |
- SSA_METAFILE | SSA_FALLBACK | SSA_GLYPHS | SSA_LINK, |
- 0, NULL, NULL, NULL, NULL, NULL, &script_analysis); |
- |
- if (SUCCEEDED(hresult)) { |
- hresult = ScriptStringOut(script_analysis, 0, 0, 0, NULL, 0, 0, FALSE); |
- ScriptStringFree(&script_analysis); |
- } |
- |
- bool found_fallback = false; |
- HENHMETAFILE meta_file = CloseEnhMetaFile(meta_file_dc); |
- if (SUCCEEDED(hresult)) { |
- LOGFONT log_font; |
- log_font.lfFaceName[0] = 0; |
- EnumEnhMetaFile(0, meta_file, MetaFileEnumProc, &log_font, NULL); |
- if (log_font.lfFaceName[0]) { |
- *result = Font(base::UTF16ToUTF8(log_font.lfFaceName), |
- font.GetFontSize()); |
- found_fallback = true; |
- } |
- } |
- DeleteEnhMetaFile(meta_file); |
- |
- return found_fallback; |
-} |
- |
-} // namespace gfx |