Index: chrome/renderer/print_web_view_helper_win.cc |
diff --git a/chrome/renderer/print_web_view_helper_win.cc b/chrome/renderer/print_web_view_helper_win.cc |
index 4ee351ba67cfc6c271a6d5aa113560abf9dac663..1128e01a5790cff22e35a0a4d04be4dbbea09320 100644 |
--- a/chrome/renderer/print_web_view_helper_win.cc |
+++ b/chrome/renderer/print_web_view_helper_win.cc |
@@ -4,6 +4,7 @@ |
#include "chrome/renderer/print_web_view_helper.h" |
+#include "base/i18n/rtl.h" |
#include "base/logging.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/metrics/histogram.h" |
@@ -20,6 +21,7 @@ |
#include "skia/ext/vector_canvas.h" |
#include "skia/ext/platform_device.h" |
#include "third_party/skia/include/core/SkRefCnt.h" |
+#include "third_party/skia/include/ports/SkTypeface_win.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
#include "ui/gfx/gdi_util.h" |
#include "ui/gfx/point.h" |
@@ -327,3 +329,100 @@ bool PrintWebViewHelper::CopyMetafileDataToSharedMem( |
shared_mem_handle)); |
return true; |
} |
+ |
+#if defined(USE_SKIA) |
+ |
+// Uniscribe generation is very time consuming so a global cache for previous |
+// results are needed. |
+SCRIPT_CACHE PrintWebViewHelper::g_script_cache_; |
+SCRIPT_ANALYSIS PrintWebViewHelper::g_script_analysis_; |
jungshik at Google
2012/01/06 22:38:45
In the past, we used to have UniscribeHelper class
xji
2012/01/07 01:21:15
Mike (msw@) implemented RenderText in Windows.
The
|
+ |
+// static |
+bool PrintWebViewHelper::ConvertTextToGlyphs(SkTypeface* typeface, |
+ const string16& text, |
+ std::vector<uint16_t>* glyphs) { |
+ bool rtl = base::i18n::IsRTL() && |
+ base::i18n::StringContainsStrongRTLChars(text); |
+ HRESULT hr = ScriptIsComplex(text.c_str(), text.size(), SIC_COMPLEX); |
+ if (hr != S_OK && !rtl) { |
+ return false; // Script is neither complex nor BiDi. |
+ } |
+ |
+ // Complex script handling started here. |
+ std::vector<SCRIPT_ITEM> items; |
+ int max_items = text.size(); |
+ int generated_items; |
+ for (;;) { |
+ items.resize(max_items); |
+ hr = ScriptItemize(text.c_str(), text.size(), max_items - 1, NULL, NULL, |
+ &items[0], &generated_items); |
+ if (SUCCEEDED(hr)) { |
+ items.resize(generated_items + 1); |
+ break; |
+ } |
+ if (hr != E_OUTOFMEMORY) { |
+ return false; |
+ } |
+ max_items *= 2; |
+ } |
+ |
+ std::vector<int> visual_to_logical(generated_items + 1); |
+ std::vector<int> logical_to_visual(generated_items + 1); |
+ std::vector<BYTE> directions(generated_items); |
+ for (int i = 0; i < generated_items; ++i) { |
+ directions[i] = items[i].a.s.uBidiLevel; |
+ } |
+ |
+ ScriptLayout(generated_items, &directions[0], &visual_to_logical[0], |
+ &logical_to_visual[0]); |
+ visual_to_logical.push_back(generated_items); |
+ logical_to_visual.push_back(generated_items); |
+ |
+ base::win::ScopedCreateDC dc(CreateCompatibleDC(GetDC(NULL))); |
+ LOGFONT lf; |
+ SkLOGFONTFromTypeface(typeface, &lf); |
+ HFONT font_handle = CreateFontIndirect(&lf); |
+ if (font_handle == NULL) { |
+ return false; |
+ } |
+ SelectObject(dc.Get(), font_handle); |
+ |
+ for (size_t i = 0; i < items.size() - 1; ++i) { |
+ int index = logical_to_visual[i]; |
+ int input_length = items[index + 1].iCharPos - items[index].iCharPos; |
+ |
+ // Initial size guess suggested by MSDN. |
+ std::vector<WORD> logs(input_length); |
+ int max_glyph_len = input_length * 3 / 2 + 16; |
+ std::vector<WORD> glyph_buffer; |
+ std::vector<SCRIPT_VISATTR> visattr; |
+ |
+ for (;;) { |
+ int glyphs_used; |
+ glyph_buffer.resize(max_glyph_len); |
+ visattr.resize(max_glyph_len); |
+ items[index].a.fLogicalOrder = FALSE; |
+ hr = ScriptShape(dc, &g_script_cache_, &text[items[index].iCharPos], |
+ input_length, max_glyph_len, &(items[index].a), |
+ &glyph_buffer[0], &logs[0], &visattr[0], &glyphs_used); |
+ if (SUCCEEDED(hr)) { |
+ // We are not supposed to handle Kashidas in Arabic, so reverting the |
+ // glyph order shall be good enough for all RTLs. |
+ glyph_buffer.resize(glyphs_used); |
+ glyphs->insert(glyphs->end(), glyph_buffer.begin(),glyph_buffer.end()); |
+ break; |
+ } |
+ |
+ if (hr == E_PENDING) { |
+ // keep waiting |
+ } else if (hr != E_OUTOFMEMORY) { |
+ return false; |
+ } |
+ |
jungshik at Google
2012/01/06 22:38:45
After calling ScriptShape, ScriptPlace (?) has to
|
+ max_glyph_len *= 2; |
+ } |
+ } |
+ |
+ return true; |
+} |
+#endif |