diff options
-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, 42 insertions, 55 deletions
diff --git a/ui/gfx/render_text_harfbuzz.cc b/ui/gfx/render_text_harfbuzz.cc index 6e2be3a..138cd54 100644 --- a/ui/gfx/render_text_harfbuzz.cc +++ b/ui/gfx/render_text_harfbuzz.cc @@ -863,17 +863,12 @@ 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 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. + // 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. base::i18n::BiDiLineIterator bidi_iterator; - 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; - } + bool fake_runs = !bidi_iterator.Open(text, is_text_rtl, false); // Temporarily apply composition underlines and selection colors. ApplyCompositionAndSelectionStyles(); @@ -893,34 +888,36 @@ void RenderTextHarfBuzz::ItemizeText() { run->diagonal_strike = style.style(DIAGONAL_STRIKE); run->underline = style.style(UNDERLINE); - 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; + 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; + } } } } @@ -928,7 +925,12 @@ 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 db59a02..4e27af9 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 GFX_EXPORT RenderTextHarfBuzz : public RenderText { +class RenderTextHarfBuzz : public RenderText { public: RenderTextHarfBuzz(); virtual ~RenderTextHarfBuzz(); @@ -90,9 +90,6 @@ class GFX_EXPORT 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 8cef145..6859a50 100644 --- a/ui/gfx/render_text_unittest.cc +++ b/ui/gfx/render_text_unittest.cc @@ -1977,16 +1977,4 @@ 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 |