summaryrefslogtreecommitdiffstats
path: root/ui/gfx
diff options
context:
space:
mode:
authorckocagil@chromium.org <ckocagil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-11 13:29:42 +0000
committerckocagil@chromium.org <ckocagil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-11 13:29:42 +0000
commit06a2742e0efecdf5e39fd4510d9d513b92beb782 (patch)
tree4f9a62ea13a199375ee653e673ee28b6edf7e5ad /ui/gfx
parentb62dcb867c6576b1d730fd6b68f2f55bfda66eda (diff)
downloadchromium_src-06a2742e0efecdf5e39fd4510d9d513b92beb782.zip
chromium_src-06a2742e0efecdf5e39fd4510d9d513b92beb782.tar.gz
chromium_src-06a2742e0efecdf5e39fd4510d9d513b92beb782.tar.bz2
RenderTextHarfBuzz: Decide run direction by BiDi embedding level
BUG=382178 NOTRY=true R=msw Review URL: https://codereview.chromium.org/326123003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@276379 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gfx')
-rw-r--r--ui/gfx/render_text_harfbuzz.cc80
-rw-r--r--ui/gfx/render_text_harfbuzz.h5
-rw-r--r--ui/gfx/render_text_unittest.cc12
3 files changed, 55 insertions, 42 deletions
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc
index 138cd54..6e2be3a 100644
--- a/ui/gfx/render_text_harfbuzz.cc
+++ b/ui/gfx/render_text_harfbuzz.cc
@@ -863,12 +863,17 @@ void RenderTextHarfBuzz::ItemizeText() {
const bool is_text_rtl = GetTextDirection() == base::i18n::RIGHT_TO_LEFT;
DCHECK_NE(0U, text.length());
- // If ICU fails to itemize the text, we set |fake_runs| and create a run that
- // spans the entire text. This is needed because early returning and leaving
- // the runs set empty causes some clients to crash/misbehave since they expect
- // non-zero text metrics from a non-empty text.
+ // If ICU fails to itemize the text, we create a run that spans the entire
+ // text. This is needed because leaving the runs set empty causes some clients
+ // to misbehave since they expect non-zero text metrics from a non-empty text.
base::i18n::BiDiLineIterator bidi_iterator;
- bool fake_runs = !bidi_iterator.Open(text, is_text_rtl, false);
+ if (!bidi_iterator.Open(text, is_text_rtl, false)) {
+ internal::TextRunHarfBuzz* run = new internal::TextRunHarfBuzz;
+ run->range = Range(0, text.length());
+ runs_.push_back(run);
+ visual_to_logical_ = logical_to_visual_ = std::vector<int32_t>(1, 0);
+ return;
+ }
// Temporarily apply composition underlines and selection colors.
ApplyCompositionAndSelectionStyles();
@@ -888,36 +893,34 @@ void RenderTextHarfBuzz::ItemizeText() {
run->diagonal_strike = style.style(DIAGONAL_STRIKE);
run->underline = style.style(UNDERLINE);
- if (fake_runs) {
- run_break = text.length();
- } else {
- int32 script_item_break = 0;
- bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level);
- // Find the length and script of this script run.
- script_item_break = ScriptInterval(text, run_break,
- script_item_break - run_break, &run->script) + run_break;
-
- // Find the next break and advance the iterators as needed.
- run_break = std::min(static_cast<size_t>(script_item_break),
- TextIndexToLayoutIndex(style.GetRange().end()));
-
- // Break runs adjacent to character substrings in certain code blocks.
- // This avoids using their fallback fonts for more characters than needed,
- // in cases like "\x25B6 Media Title", etc. http://crbug.com/278913
- if (run_break > run->range.start()) {
- const size_t run_start = run->range.start();
- const int32 run_length = static_cast<int32>(run_break - run_start);
- base::i18n::UTF16CharIterator iter(text.c_str() + run_start,
- run_length);
- const UBlockCode first_block_code = ublock_getCode(iter.get());
- const bool first_block_unusual = IsUnusualBlockCode(first_block_code);
- while (iter.Advance() && iter.array_pos() < run_length) {
- const UBlockCode current_block_code = ublock_getCode(iter.get());
- if (current_block_code != first_block_code &&
- (first_block_unusual || IsUnusualBlockCode(current_block_code))) {
- run_break = run_start + iter.array_pos();
- break;
- }
+ int32 script_item_break = 0;
+ bidi_iterator.GetLogicalRun(run_break, &script_item_break, &run->level);
+ // Odd BiDi embedding levels correspond to RTL runs.
+ run->is_rtl = (run->level % 2) == 1;
+ // Find the length and script of this script run.
+ script_item_break = ScriptInterval(text, run_break,
+ script_item_break - run_break, &run->script) + run_break;
+
+ // Find the next break and advance the iterators as needed.
+ run_break = std::min(static_cast<size_t>(script_item_break),
+ TextIndexToLayoutIndex(style.GetRange().end()));
+
+ // Break runs adjacent to character substrings in certain code blocks.
+ // This avoids using their fallback fonts for more characters than needed,
+ // in cases like "\x25B6 Media Title", etc. http://crbug.com/278913
+ if (run_break > run->range.start()) {
+ const size_t run_start = run->range.start();
+ const int32 run_length = static_cast<int32>(run_break - run_start);
+ base::i18n::UTF16CharIterator iter(text.c_str() + run_start,
+ run_length);
+ const UBlockCode first_block_code = ublock_getCode(iter.get());
+ const bool first_block_unusual = IsUnusualBlockCode(first_block_code);
+ while (iter.Advance() && iter.array_pos() < run_length) {
+ const UBlockCode current_block_code = ublock_getCode(iter.get());
+ if (current_block_code != first_block_code &&
+ (first_block_unusual || IsUnusualBlockCode(current_block_code))) {
+ run_break = run_start + iter.array_pos();
+ break;
}
}
}
@@ -925,12 +928,7 @@ void RenderTextHarfBuzz::ItemizeText() {
DCHECK(IsValidCodePointIndex(text, run_break));
style.UpdatePosition(LayoutIndexToTextIndex(run_break));
run->range.set_end(run_break);
- UBiDiDirection direction = ubidi_getBaseDirection(
- text.c_str() + run->range.start(), run->range.length());
- if (direction == UBIDI_NEUTRAL)
- run->is_rtl = is_text_rtl;
- else
- run->is_rtl = direction == UBIDI_RTL;
+
runs_.push_back(run);
}
diff --git a/ui/gfx/render_text_harfbuzz.h b/ui/gfx/render_text_harfbuzz.h
index 4e27af9..db59a02 100644
--- a/ui/gfx/render_text_harfbuzz.h
+++ b/ui/gfx/render_text_harfbuzz.h
@@ -61,7 +61,7 @@ struct GFX_EXPORT TextRunHarfBuzz {
} // namespace internal
-class RenderTextHarfBuzz : public RenderText {
+class GFX_EXPORT RenderTextHarfBuzz : public RenderText {
public:
RenderTextHarfBuzz();
virtual ~RenderTextHarfBuzz();
@@ -90,6 +90,9 @@ class RenderTextHarfBuzz : public RenderText {
virtual void DrawVisualText(Canvas* canvas) OVERRIDE;
private:
+ friend class RenderTextTest;
+ FRIEND_TEST_ALL_PREFIXES(RenderTextTest, HarfBuzz_RunDirection);
+
// Return the run index that contains the argument; or the length of the
// |runs_| vector if argument exceeds the text length or width.
size_t GetRunContainingCaret(const SelectionModel& caret) const;
diff --git a/ui/gfx/render_text_unittest.cc b/ui/gfx/render_text_unittest.cc
index 6859a50..8cef145 100644
--- a/ui/gfx/render_text_unittest.cc
+++ b/ui/gfx/render_text_unittest.cc
@@ -1977,4 +1977,16 @@ TEST_F(RenderTextTest, HarfBuzz_CharToGlyph) {
}
+TEST_F(RenderTextTest, HarfBuzz_RunDirection) {
+ RenderTextHarfBuzz render_text;
+ const base::string16 mixed =
+ WideToUTF16(L"\x05D0\x05D1" L"1234" L"\x05D2\x05D3");
+ render_text.SetText(mixed);
+ render_text.EnsureLayout();
+ ASSERT_EQ(3U, render_text.runs_.size());
+ EXPECT_TRUE(render_text.runs_[0]->is_rtl);
+ EXPECT_FALSE(render_text.runs_[1]->is_rtl);
+ EXPECT_TRUE(render_text.runs_[2]->is_rtl);
+}
+
} // namespace gfx