diff options
author | ckocagil@chromium.org <ckocagil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-11 13:29:42 +0000 |
---|---|---|
committer | ckocagil@chromium.org <ckocagil@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-06-11 13:29:42 +0000 |
commit | 06a2742e0efecdf5e39fd4510d9d513b92beb782 (patch) | |
tree | 4f9a62ea13a199375ee653e673ee28b6edf7e5ad /ui/gfx | |
parent | b62dcb867c6576b1d730fd6b68f2f55bfda66eda (diff) | |
download | chromium_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.cc | 80 | ||||
-rw-r--r-- | ui/gfx/render_text_harfbuzz.h | 5 | ||||
-rw-r--r-- | ui/gfx/render_text_unittest.cc | 12 |
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 |