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

Unified Diff: ui/gfx/render_text_win.cc

Issue 23522018: RenderTextWin: Break runs between any two characters that are not in the same code block (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: added test case Created 7 years, 3 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
« no previous file with comments | « ui/gfx/render_text_win.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ui/gfx/render_text_win.cc
diff --git a/ui/gfx/render_text_win.cc b/ui/gfx/render_text_win.cc
index ac018de3f446226f8e39276ee65f24ebf1e76478..5e716376c4dcd7e4e94f5c528bac479702285899 100644
--- a/ui/gfx/render_text_win.cc
+++ b/ui/gfx/render_text_win.cc
@@ -7,11 +7,13 @@
#include <algorithm>
#include "base/i18n/break_iterator.h"
+#include "base/i18n/char_iterator.h"
#include "base/i18n/rtl.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
+#include "third_party/icu/source/common/unicode/uchar.h"
#include "ui/base/text/utf16_indexing.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font_fallback_win.h"
@@ -543,13 +545,14 @@ void RenderTextWin::ItemizeLogicalText() {
script_state_.uBidiLevel =
(GetTextDirection() == base::i18n::RIGHT_TO_LEFT) ? 1 : 0;
- if (text().empty())
+ const base::string16& layout_text = GetLayoutText();
+ if (layout_text.empty())
return;
HRESULT hr = E_OUTOFMEMORY;
int script_items_count = 0;
std::vector<SCRIPT_ITEM> script_items;
- const size_t layout_text_length = GetLayoutText().length();
+ const size_t layout_text_length = layout_text.length();
// Ensure that |kMaxRuns| is attempted and the loop terminates afterward.
for (size_t runs = kGuessRuns; hr == E_OUTOFMEMORY && runs <= kMaxRuns;
runs = std::max(runs + 1, std::min(runs * 2, kMaxRuns))) {
@@ -557,9 +560,9 @@ void RenderTextWin::ItemizeLogicalText() {
// ScriptItemize always adds a terminal array item so that the length of
// the last item can be derived from the terminal SCRIPT_ITEM::iCharPos.
script_items.resize(runs);
- hr = ScriptItemize(GetLayoutText().c_str(), layout_text_length,
- runs - 1, &script_control_, &script_state_,
- &script_items[0], &script_items_count);
+ hr = ScriptItemize(layout_text.c_str(), layout_text_length, runs - 1,
+ &script_control_, &script_state_, &script_items[0],
+ &script_items_count);
}
DCHECK(SUCCEEDED(hr));
if (!SUCCEEDED(hr) || script_items_count <= 0)
@@ -571,7 +574,7 @@ void RenderTextWin::ItemizeLogicalText() {
// Build the list of runs from the script items and ranged styles. Use an
// empty color BreakList to avoid breaking runs at color boundaries.
BreakList<SkColor> empty_colors;
- empty_colors.SetMax(text().length());
+ empty_colors.SetMax(layout_text_length);
internal::StyleIterator style(empty_colors, styles());
SCRIPT_ITEM* script_item = &script_items[0];
const size_t max_run_length = kMaxGlyphs / 2;
@@ -592,9 +595,35 @@ void RenderTextWin::ItemizeLogicalText() {
const size_t script_item_break = (script_item + 1)->iCharPos;
run_break = std::min(script_item_break,
TextIndexToLayoutIndex(style.GetRange().end()));
+
// Clamp run lengths to avoid exceeding the maximum supported glyph count.
- if ((run_break - run->range.start()) > max_run_length)
+ if ((run_break - run->range.start()) > max_run_length) {
run_break = run->range.start() + max_run_length;
+ if (run_break < layout_text_length &&
+ !ui::IsValidCodePointIndex(layout_text, run_break))
Alexei Svitkine (slow) 2013/09/05 20:32:41 Nit: Add {}'s.
+ --run_break;
+ }
+
+ // Break runs between characters in different code blocks. This avoids using
+ // fallback fonts for more characters than needed. http://crbug.com/278913
+ if (run_break > run->range.start()) {
+ size_t run_start = run->range.start();
+ if (!ui::IsValidCodePointIndex(layout_text, run_start))
Alexei Svitkine (slow) 2013/09/05 20:32:41 I'm not a fan of this logic here. Decrementing run
ckocagil 2013/09/05 21:08:57 |run_start| doesn't change |run->range.start()|. T
Alexei Svitkine (slow) 2013/09/06 13:28:42 Right, I understand this, but still am not a fan o
Alexei Svitkine (slow) 2013/09/06 13:36:18 Plus, looking at the UTF16CharIterator() code, it
+ --run_start;
+ int32 run_length = static_cast<int32>(run_break - run_start);
+ if (!ui::IsValidCodePointIndex(layout_text, run_break))
Alexei Svitkine (slow) 2013/09/05 20:32:41 In what cases could this be the case? For example,
ckocagil 2013/09/05 21:08:57 I'm not sure, style ranges maybe? Do they contain
msw 2013/09/06 16:51:28 Uniscribe or style ranges theoretically could, but
+ ++run_length;
+ base::i18n::UTF16CharIterator iter(layout_text.c_str() + run_start,
+ run_length);
+ const UBlockCode first_block = ublock_getCode(iter.get());
+ while (iter.Advance() && iter.array_pos() < run_length) {
+ if (ublock_getCode(iter.get()) != first_block) {
+ run_break = std::min(run_break, iter.array_pos() + run_start);
Alexei Svitkine (slow) 2013/09/05 20:32:41 The mins is only necessary because your code above
ckocagil 2013/09/05 21:08:57 No, it is necessary because of the ++run_length (t
+ break;
+ }
+ }
+ }
+
style.UpdatePosition(LayoutIndexToTextIndex(run_break));
if (script_item_break == run_break)
script_item++;
« no previous file with comments | « ui/gfx/render_text_win.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698