summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/renderer_host/render_message_filter.cc34
-rw-r--r--content/browser/renderer_host/render_message_filter.h5
-rw-r--r--content/common/view_messages.h10
-rw-r--r--content/renderer/render_thread_impl.cc6
-rw-r--r--content/renderer/render_thread_impl.h5
-rw-r--r--content/renderer/renderer_main_platform_delegate_win.cc16
-rw-r--r--skia/ext/vector_platform_device_emf_win.cc72
-rw-r--r--skia/ext/vector_platform_device_emf_win.h6
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_