diff options
-rw-r--r-- | content/browser/renderer_host/render_message_filter.cc | 34 | ||||
-rw-r--r-- | content/browser/renderer_host/render_message_filter.h | 5 | ||||
-rw-r--r-- | content/common/view_messages.h | 10 | ||||
-rw-r--r-- | content/renderer/render_thread_impl.cc | 6 | ||||
-rw-r--r-- | content/renderer/render_thread_impl.h | 5 | ||||
-rw-r--r-- | content/renderer/renderer_main_platform_delegate_win.cc | 16 | ||||
-rw-r--r-- | skia/ext/vector_platform_device_emf_win.cc | 72 | ||||
-rw-r--r-- | skia/ext/vector_platform_device_emf_win.h | 6 |
8 files changed, 146 insertions, 8 deletions
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index f5d3063..9d6b5b9 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc @@ -76,6 +76,7 @@ #endif #if defined(OS_WIN) #include "content/browser/renderer_host/backing_store_win.h" +#include "content/common/font_cache_dispatcher_win.h" #endif using net::CookieStore; @@ -362,6 +363,10 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message, bool* message_was_ok) { bool handled = true; IPC_BEGIN_MESSAGE_MAP_EX(RenderMessageFilter, message, *message_was_ok) +#if defined(OS_WIN) + IPC_MESSAGE_HANDLER(ViewHostMsg_PreCacheFontCharacters, + OnPreCacheFontCharacters) +#endif IPC_MESSAGE_HANDLER(ViewHostMsg_GenerateRoutingID, OnGenerateRoutingID) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWindow, OnMsgCreateWindow) IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget) @@ -1102,4 +1107,33 @@ void RenderMessageFilter::OnDidLose3DContext( top_origin_url, guilt); } +#if defined(OS_WIN) +void RenderMessageFilter::OnPreCacheFontCharacters(const LOGFONT& font, + const string16& str) { + // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too. + // Except that for True Type fonts, + // GetTextMetrics will not load the font in memory. + // The only way windows seem to load properly, it is to create a similar + // device (like the one in which we print), then do an ExtTextOut, + // as we do in the printing thread, which is sandboxed. + HDC hdc = CreateEnhMetaFile(NULL, NULL, NULL, NULL); + HFONT font_handle = CreateFontIndirect(&font); + DCHECK(NULL != font_handle); + + HGDIOBJ old_font = SelectObject(hdc, font_handle); + DCHECK(NULL != old_font); + + ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), NULL); + + SelectObject(hdc, old_font); + DeleteObject(font_handle); + + HENHMETAFILE metafile = CloseEnhMetaFile(hdc); + + if (metafile) { + DeleteEnhMetaFile(metafile); + } +} +#endif + } // namespace content diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index 9431aca..f52f86f 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h @@ -144,6 +144,11 @@ class RenderMessageFilter : public BrowserMessageFilter { void SendLoadFontReply(IPC::Message* reply, FontLoader::Result* result); #endif +#if defined(OS_WIN) + void OnPreCacheFontCharacters(const LOGFONT& log_font, + const string16& characters); +#endif + void OnGetPlugins(bool refresh, IPC::Message* reply_msg); void GetPluginsCallback(IPC::Message* reply_msg, const std::vector<webkit::WebPluginInfo>& plugins); diff --git a/content/common/view_messages.h b/content/common/view_messages.h index 2ab5da9..e67f08f 100644 --- a/content/common/view_messages.h +++ b/content/common/view_messages.h @@ -7,6 +7,7 @@ #include "base/process.h" #include "base/shared_memory.h" +#include "base/string16.h" #include "content/common/content_export.h" #include "content/common/content_param_traits.h" #include "content/common/edit_command.h" @@ -2425,3 +2426,12 @@ IPC_MESSAGE_CONTROL3(ViewHostMsg_DidLose3DContext, GURL /* top_origin_url */, content::ThreeDAPIType /* context_type */, int /* arb_robustness_status_code */) + +#if defined(OS_WIN) +// Request that the given font characters be loaded by the browser so it's +// cached by the OS. Please see RenderMessageFilter::OnPreCacheFontCharacters +// for details. +IPC_SYNC_MESSAGE_CONTROL2_0(ViewHostMsg_PreCacheFontCharacters, + LOGFONT /* font_data */, + string16 /* characters */) +#endif diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index 8e46b50..502b930 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc @@ -19,6 +19,7 @@ #include "base/metrics/stats_table.h" #include "base/path_service.h" #include "base/shared_memory.h" +#include "base/string16.h" #include "base/string_number_conversions.h" // Temporary #include "base/threading/thread_local.h" #include "base/utf_string_conversions.h" @@ -852,6 +853,11 @@ AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() { } #if defined(OS_WIN) +void RenderThreadImpl::PreCacheFontCharacters(const LOGFONT& log_font, + const string16& str) { + Send(new ViewHostMsg_PreCacheFontCharacters(log_font, str)); +} + void RenderThreadImpl::PreCacheFont(const LOGFONT& log_font) { Send(new ChildProcessHostMsg_PreCacheFont(log_font)); } diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index c370d78..4a076a3 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h @@ -10,6 +10,7 @@ #include <vector> #include "base/observer_list.h" +#include "base/string16.h" #include "base/timer.h" #include "build/build_config.h" #include "content/common/child_process.h" @@ -239,6 +240,10 @@ class CONTENT_EXPORT RenderThreadImpl : public RenderThread, // first call. AudioRendererMixerManager* GetAudioRendererMixerManager(); +#if defined(OS_WIN) + void PreCacheFontCharacters(const LOGFONT& log_font, const string16& str); +#endif + // For producing custom V8 histograms. Custom histograms are produced if all // RenderViews share the same host, and the host is in the pre-specified set // of hosts we want to produce custom diagrams for. The name for a custom diff --git a/content/renderer/renderer_main_platform_delegate_win.cc b/content/renderer/renderer_main_platform_delegate_win.cc index 316fcc0..27d2bbf 100644 --- a/content/renderer/renderer_main_platform_delegate_win.cc +++ b/content/renderer/renderer_main_platform_delegate_win.cc @@ -9,12 +9,15 @@ #include "base/command_line.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/string16.h" #include "base/win/win_util.h" #include "content/public/common/content_switches.h" #include "content/public/common/injection_test_win.h" #include "content/public/renderer/render_thread.h" +#include "content/renderer/render_thread_impl.h" #include "sandbox/win/src/sandbox.h" #include "skia/ext/skia_sandbox_support_win.h" +#include "skia/ext/vector_platform_device_emf_win.h" #include "unicode/timezone.h" namespace content { @@ -28,6 +31,17 @@ void SkiaPreCacheFont(const LOGFONT& logfont) { } } +void SkiaPreCacheFontCharacters(const LOGFONT& logfont, + const wchar_t* text, + unsigned int text_length) { + content::RenderThreadImpl* render_thread_impl = + content::RenderThreadImpl::current(); + if (render_thread_impl) { + render_thread_impl->PreCacheFontCharacters(logfont, + string16(text, text_length)); + } +} + void __cdecl ForceCrashOnSigAbort(int) { *((int*)0) = 0x1337; } @@ -78,6 +92,8 @@ void RendererMainPlatformDelegate::PlatformInitialize() { // is disabled, we don't have to make this dummy call. scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault()); SetSkiaEnsureTypefaceAccessible(SkiaPreCacheFont); + skia::SetSkiaEnsureTypefaceCharactersAccessible( + SkiaPreCacheFontCharacters); } } diff --git a/skia/ext/vector_platform_device_emf_win.cc b/skia/ext/vector_platform_device_emf_win.cc index 73be491..243e808 100644 --- a/skia/ext/vector_platform_device_emf_win.cc +++ b/skia/ext/vector_platform_device_emf_win.cc @@ -2,12 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include <windows.h> - #include "skia/ext/vector_platform_device_emf_win.h" +#include <windows.h> + +#include "base/logging.h" +#include "base/string16.h" #include "skia/ext/bitmap_platform_device.h" #include "skia/ext/skia_utils_win.h" +#include "third_party/skia/include/core/SkFontHost.h" #include "third_party/skia/include/core/SkPathEffect.h" #include "third_party/skia/include/core/SkTemplates.h" #include "third_party/skia/include/core/SkUtils.h" @@ -366,6 +369,48 @@ static UINT getTextOutOptions(const SkPaint& paint) { } } +static SkiaEnsureTypefaceCharactersAccessible + g_skia_ensure_typeface_characters_accessible = NULL; + +SK_API void SetSkiaEnsureTypefaceCharactersAccessible( + SkiaEnsureTypefaceCharactersAccessible func) { + // This function is supposed to be called once in process life time. + SkASSERT(g_skia_ensure_typeface_characters_accessible == NULL); + g_skia_ensure_typeface_characters_accessible = func; +} + +void EnsureTypefaceCharactersAccessible( + const SkTypeface& typeface, const wchar_t* text, unsigned int text_length) { + LOGFONT lf; + SkLOGFONTFromTypeface(&typeface, &lf); + g_skia_ensure_typeface_characters_accessible(lf, text, text_length); +} + +bool EnsureExtTextOut(HDC hdc, int x, int y, UINT options, const RECT * lprect, + LPCWSTR text, unsigned int characters, const int * lpDx, + SkTypeface* const typeface) { + bool success = ExtTextOut(hdc, x, y, options, lprect, text, characters, lpDx); + if (!success) { + if (typeface) { + EnsureTypefaceCharactersAccessible(*typeface, + text, + characters); + success = ExtTextOut(hdc, x, y, options, lprect, text, characters, lpDx); + if (!success) { + LOGFONT lf; + SkLOGFONTFromTypeface(typeface, &lf); + VLOG(1) << "SkFontHost::EnsureTypefaceCharactersAccessible FAILED for " + << " FaceName = " << lf.lfFaceName + << " and characters: " << string16(text, characters); + } + } else { + VLOG(1) << "ExtTextOut FAILED for default FaceName " + << " and characters: " << string16(text, characters); + } + } + return success; +} + void VectorPlatformDeviceEmf::drawText(const SkDraw& draw, const void* text, size_t byteLength, @@ -373,13 +418,19 @@ void VectorPlatformDeviceEmf::drawText(const SkDraw& draw, SkScalar y, const SkPaint& paint) { SkGDIFontSetup setup; + bool useDrawPath = true; + if (SkPaint::kUTF8_TextEncoding != paint.getTextEncoding() && setup.useGDI(hdc_, paint)) { UINT options = getTextOutOptions(paint); UINT count = byteLength >> 1; - ExtTextOut(hdc_, SkScalarRound(x), SkScalarRound(y + getAscent(paint)), - options, 0, reinterpret_cast<const wchar_t*>(text), count, NULL); - } else { + useDrawPath = !EnsureExtTextOut(hdc_, SkScalarRound(x), + SkScalarRound(y + getAscent(paint)), options, 0, + reinterpret_cast<const wchar_t*>(text), count, NULL, + paint.getTypeface()); + } + + if (useDrawPath) { SkPath path; paint.getTextPath(text, byteLength, x, y, &path); drawPath(draw, path, paint); @@ -407,6 +458,8 @@ void VectorPlatformDeviceEmf::drawPosText(const SkDraw& draw, int scalarsPerPos, const SkPaint& paint) { SkGDIFontSetup setup; + bool useDrawText = true; + if (2 == scalarsPerPos && SkPaint::kUTF8_TextEncoding != paint.getTextEncoding() && setup.useGDI(hdc_, paint)) { @@ -419,9 +472,12 @@ void VectorPlatformDeviceEmf::drawPosText(const SkDraw& draw, advances[i] = SkScalarRound(pos[2] - pos[0]); pos += 2; } - ExtTextOut(hdc_, startX, startY, getTextOutOptions(paint), 0, - reinterpret_cast<const wchar_t*>(text), count, advances); - } else { + useDrawText = !EnsureExtTextOut(hdc_, startX, startY, + getTextOutOptions(paint), 0, reinterpret_cast<const wchar_t*>(text), + count, advances, paint.getTypeface()); + } + + if (useDrawText) { size_t (*bytesPerCodePoint)(const char*); switch (paint.getTextEncoding()) { case SkPaint::kUTF8_TextEncoding: diff --git a/skia/ext/vector_platform_device_emf_win.h b/skia/ext/vector_platform_device_emf_win.h index 6d84d3a..af0e429 100644 --- a/skia/ext/vector_platform_device_emf_win.h +++ b/skia/ext/vector_platform_device_emf_win.h @@ -127,6 +127,12 @@ class VectorPlatformDeviceEmf : public SkDevice, public PlatformDevice { DISALLOW_COPY_AND_ASSIGN(VectorPlatformDeviceEmf); }; +typedef void (*SkiaEnsureTypefaceCharactersAccessible) + (const LOGFONT& font, const wchar_t* text, unsigned int text_length); + +SK_API void SetSkiaEnsureTypefaceCharactersAccessible( + SkiaEnsureTypefaceCharactersAccessible func); + } // namespace skia #endif // SKIA_EXT_VECTOR_PLATFORM_DEVICE_EMF_WIN_H_ |