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..338e978d85c8a23331dcf639a0431d4ac192940c 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,68 @@ const std::vector<Font>* LinkedFontsIterator::GetLinkedFonts() const { |
return fonts; |
} |
+} // namespace internal |
+ |
+std::vector<std::string> GetFallbackFontFamilies( |
+ const std::string& font_family) { |
+ internal::LinkedFontsIterator linked_fonts(Font(font_family, 10)); |
Alexei Svitkine (slow)
2014/07/17 21:22:00
Please add a comment about the hard-coded 10.
ckocagil
2014/07/17 23:12:00
Done.
|
+ 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 |
Alexei Svitkine (slow)
2014/07/17 21:22:00
This comment should either be in the header or wit
ckocagil
2014/07/17 23:12:00
Done, moved into the body.
|
+bool GetUniscribeFallbackFont(const Font& font, |
+ const wchar_t* text, |
+ int text_length, |
+ Font* result) { |
+ static HDC hdc = NULL; |
+ if (hdc == NULL) { |
+ hdc = CreateCompatibleDC(NULL); |
msw
2014/07/17 00:08:04
nit: can you inline this with the static decl?
ckocagil
2014/07/17 00:10:49
Wouldn't that cause a static initializer to be add
msw
2014/07/17 00:15:35
I thought this was okay for function-scoped static
Daniel Erat
2014/07/17 02:22:24
function-scoped static initializers are fine, per
ckocagil
2014/07/17 23:12:00
Oh, now I read the thread and came to the same con
|
+ DCHECK(hdc) << GetLastError(); |
+ } |
+ |
+ // 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 |