| 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) {
|
| + 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
|
|
|