Chromium Code Reviews| 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 |