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

Unified Diff: ui/gfx/font_fallback_win.cc

Issue 2054273002: Font fallback for UI (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Actually delete old TextAnalysisSource Created 4 years, 6 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 8b45b2e53b14bb654e603013490dc0547a649028..0f222c4e016dea2aa959578c3294ef75563d5683 100644
--- a/ui/gfx/font_fallback_win.cc
+++ b/ui/gfx/font_fallback_win.cc
@@ -4,7 +4,9 @@
#include "ui/gfx/font_fallback_win.h"
+#include <dwrite_2.h>
#include <usp10.h>
+#include <wrl.h>
#include <map>
@@ -15,8 +17,12 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
+#include "base/win/scoped_comptr.h"
#include "ui/gfx/font.h"
#include "ui/gfx/font_fallback.h"
+#include "ui/gfx/platform_font_win.h"
msw 2016/06/23 20:59:37 q: what is this used for?
Ilya Kulshin 2016/06/24 20:48:24 This is needed for GetFamilyNameFromDirectWriteFon
msw 2016/06/27 20:45:36 Acknowledged.
+#include "ui/gfx/win/direct_write.h"
+#include "ui/gfx/win/dwrite_text_analysis_source.h"
namespace gfx {
@@ -175,6 +181,55 @@ int CALLBACK MetaFileEnumProc(HDC hdc,
return 1;
}
+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
namespace internal {
@@ -282,53 +337,53 @@ std::vector<Font> GetFallbackFonts(const Font& font) {
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 GetFallbackFont(const Font& font,
+ const wchar_t* text,
+ int text_length,
+ Font* result) {
+ // Creating a DirectWrite font fallback can be expensive. It's ok in the
+ // browser process because we can use the shared system fallback, but in the
+ // renderer this can cause hangs. Code that needs font fallback in the
+ // renderer should instead use the font proxy.
+ DCHECK(base::MessageLoopForUI::IsCurrent());
+
+ base::win::ScopedComPtr<IDWriteFactory> factory;
+ gfx::win::CreateDWriteFactory(factory.Receive());
msw 2016/06/23 20:59:38 Is it unreasonably expensive for every fallback at
Ilya Kulshin 2016/06/24 20:48:24 Now that we no longer need to support XP and Vista
msw 2016/06/27 20:45:36 Is it not easily feasible to cache an instance in
msw 2016/06/28 18:37:23 Ping?
Ilya Kulshin 2016/06/28 20:32:52 Sorry, didn't notice this comment. I did some meas
+ base::win::ScopedComPtr<IDWriteFactory2> factory2;
+ factory.QueryInterface(factory2.Receive());
+ if (!factory2) {
+ // IDWriteFactory2 is not available before Win8.1
+ return GetUniscribeFallbackFont(font, text, text_length, result);
}
- 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;
- }
+ base::win::ScopedComPtr<IDWriteFontFallback> fallback;
+ factory2->GetSystemFontFallback(fallback.Receive());
+
+ base::win::ScopedComPtr<IDWriteNumberSubstitution> number_substitution;
+ factory2->CreateNumberSubstitution(
+ DWRITE_NUMBER_SUBSTITUTION_METHOD_NONE, L"" /* locale */,
msw 2016/06/23 20:59:37 Can/should we use the actual locale from base::18n
Ilya Kulshin 2016/06/24 20:48:24 Done.
+ true /* ignoreUserOverride */, number_substitution.Receive());
+
+ uint32_t mapped_length = 0;
+ base::win::ScopedComPtr<IDWriteFont> mapped_font;
+ float scale = 0;
+ base::win::ScopedComPtr<IDWriteTextAnalysisSource> text_analysis;
+ Microsoft::WRL::MakeAndInitialize<gfx::win::TextAnalysisSource>(
msw 2016/06/23 20:59:38 This can fail; try uniscribe (or bail?) if it does
Ilya Kulshin 2016/06/24 20:48:24 This would only fail if we fail to alloc memory. I
msw 2016/06/27 20:45:36 Acknowledged.
+ text_analysis.Receive(), text, L"" /* locale */,
msw 2016/06/23 20:59:37 ditto locale q
Ilya Kulshin 2016/06/24 20:48:24 Done.
+ number_substitution.get(), DWRITE_READING_DIRECTION_LEFT_TO_RIGHT);
msw 2016/06/23 20:59:38 Can/should we use the actual text direction here?
Ilya Kulshin 2016/06/24 20:48:24 Done.
+ base::string16 original_name = base::UTF8ToUTF16(font.GetFontName());
+ fallback->MapCharacters(text_analysis.get(), 0, text_length, nullptr,
+ original_name.c_str(), DWRITE_FONT_WEIGHT_NORMAL,
msw 2016/06/23 20:59:37 Can/should we use the weight and style of the inpu
Ilya Kulshin 2016/06/24 20:48:24 Weight was fairly simple to pipe through. Style wa
msw 2016/06/27 20:45:36 Acknowledged.
+ DWRITE_FONT_STYLE_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
+ &mapped_length, mapped_font.Receive(), &scale);
+
+ if (mapped_font) {
+ base::string16 family_name;
+ GetFamilyNameFromDirectWriteFont(mapped_font.get(), &family_name);
msw 2016/06/23 20:59:38 Check the result here (or remove the result and ju
Ilya Kulshin 2016/06/24 20:48:24 Done.
+ *result = Font(base::UTF16ToUTF8(family_name), font.GetFontSize() * scale);
+ return true;
}
- DeleteEnhMetaFile(meta_file);
-
- return found_fallback;
+ return false;
msw 2016/06/23 20:59:38 Fall back to uniscribe here?
Ilya Kulshin 2016/06/24 20:48:24 DirectWrite returns a null mapped_font if it canno
msw 2016/06/27 20:45:36 Acknowledged.
}
} // namespace gfx
« no previous file with comments | « ui/gfx/font_fallback_win.h ('k') | ui/gfx/gfx.gyp » ('j') | ui/gfx/platform_font_win.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698