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

Unified 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: comments addressed 4 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 side-by-side diff with in-line comments
Download patch
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(&current))
+ 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

Powered by Google App Engine
This is Rietveld 408576698