diff --git a/third_party/txt/src/txt/paragraph_txt.cc b/third_party/txt/src/txt/paragraph_txt.cc index 122c1de39a988..e0c406de21361 100644 --- a/third_party/txt/src/txt/paragraph_txt.cc +++ b/third_party/txt/src/txt/paragraph_txt.cc @@ -415,6 +415,9 @@ bool ParagraphTxt::ComputeBidiRuns(std::vector* result) { // // This only applies to the final whitespace at the end as other whitespace is // no longer ambiguous when surrounded by additional text. + + // TODO(garyq): Handle this in the text editor caret code instead at layout + // level. bool has_trailing_whitespace = false; int32_t bidi_run_start, bidi_run_length; if (bidi_run_count > 1) { @@ -427,8 +430,17 @@ bool ParagraphTxt::ComputeBidiRuns(std::vector* result) { U16_GET(text_.data(), 0, bidi_run_start + bidi_run_length - 1, static_cast(text_.size()), last_char); if (u_hasBinaryProperty(last_char, UCHAR_WHITE_SPACE)) { - has_trailing_whitespace = true; - bidi_run_count--; + // Check if the trailing whitespace occurs before the previous run or + // not. If so, this trailing whitespace was a leading whitespace. + int32_t second_last_bidi_run_start, second_last_bidi_run_length; + ubidi_getVisualRun(bidi.get(), bidi_run_count - 2, + &second_last_bidi_run_start, + &second_last_bidi_run_length); + if (bidi_run_start == + second_last_bidi_run_start + second_last_bidi_run_length) { + has_trailing_whitespace = true; + bidi_run_count--; + } } } } diff --git a/third_party/txt/tests/paragraph_unittests.cc b/third_party/txt/tests/paragraph_unittests.cc index 78e28d771ad84..afe70ef1a84e9 100644 --- a/third_party/txt/tests/paragraph_unittests.cc +++ b/third_party/txt/tests/paragraph_unittests.cc @@ -2327,6 +2327,57 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(JustifyRTLNewLine)) { } } +TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(LeadingSpaceRTL)) { + const char* text = " leading space"; + + auto icu_text = icu::UnicodeString::fromUTF8(text); + std::u16string u16_text(icu_text.getBuffer(), + icu_text.getBuffer() + icu_text.length()); + + txt::ParagraphStyle paragraph_style; + paragraph_style.max_lines = 14; + paragraph_style.text_align = TextAlign::justify; + paragraph_style.text_direction = TextDirection::rtl; + txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); + + txt::TextStyle text_style; + text_style.font_families = std::vector(1, "Ahem"); + text_style.font_size = 26; + text_style.color = SK_ColorBLACK; + text_style.height = 1; + builder.PushStyle(text_style); + + builder.AddText(u16_text); + + builder.Pop(); + + auto paragraph = BuildParagraph(builder); + size_t paragraph_width = GetTestCanvasWidth() - 100; + paragraph->Layout(paragraph_width); + + paragraph->Paint(GetCanvas(), 0, 0); + + SkPaint paint; + paint.setStyle(SkPaint::kStroke_Style); + paint.setAntiAlias(true); + paint.setStrokeWidth(1); + + // Tests for GetRectsForRange() + Paragraph::RectHeightStyle rect_height_style = + Paragraph::RectHeightStyle::kMax; + Paragraph::RectWidthStyle rect_width_style = + Paragraph::RectWidthStyle::kTight; + paint.setColor(SK_ColorRED); + std::vector boxes = + paragraph->GetRectsForRange(0, 100, rect_height_style, rect_width_style); + for (size_t i = 0; i < boxes.size(); ++i) { + GetCanvas()->drawRect(boxes[i].rect, paint); + } + ASSERT_EQ(boxes.size(), 2ull); + + // This test should crash if behavior regresses. +} + TEST_F(ParagraphTest, DecorationsParagraph) { txt::ParagraphStyle paragraph_style; paragraph_style.max_lines = 14;