Chromium Code Reviews| Index: ui/gfx/font_fallback_win.cc |
| diff --git a/ui/gfx/font_fallback_win.cc b/ui/gfx/font_fallback_win.cc |
| index 4426718959b3be04a65160f23b808036d94dc64d..1ce3e54c32ae1aa02f00b522046448703d5e5b3f 100644 |
| --- a/ui/gfx/font_fallback_win.cc |
| +++ b/ui/gfx/font_fallback_win.cc |
| @@ -4,6 +4,8 @@ |
| #include "ui/gfx/font_fallback_win.h" |
| +#include <usp10.h> |
| + |
| #include <map> |
| #include "base/memory/singleton.h" |
| @@ -12,6 +14,7 @@ |
| #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 { |
| @@ -149,6 +152,20 @@ 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 { |
| @@ -186,8 +203,6 @@ void ParseFontFamilyString(const std::string& family, |
| } |
| } |
| -} // namespace internal |
| - |
| LinkedFontsIterator::LinkedFontsIterator(Font font) |
| : original_font_(font), |
| next_font_set_(false), |
| @@ -243,4 +258,62 @@ const std::vector<Font>* LinkedFontsIterator::GetLinkedFonts() const { |
| return fonts; |
| } |
| +} // namespace internal |
| + |
| +std::vector<std::string> GetFallbackFontFamilies(std::string font_family) { |
|
msw
2014/07/12 17:41:11
In another patch, it might make sense to expose a
ckocagil
2014/07/12 19:53:26
I don't see how this would improve performance (we
msw
2014/07/12 22:03:38
Your comment in RenderTextHarfBuzz illustrates my
|
| + 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; |
| +} |
| + |
| +// 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 |
| +bool GetUniscribeFallbackFont(HDC hdc, |
| + const Font& font, |
| + const wchar_t* text, |
| + int text_length, |
| + Font* result) { |
| + // 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 |