Skip to content

Commit

Permalink
libtxt: support justification of RTL text (flutter#7719)
Browse files Browse the repository at this point in the history
  • Loading branch information
jason-simmons authored Feb 11, 2019
1 parent 694300d commit a3be1ff
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 8 deletions.
36 changes: 28 additions & 8 deletions third_party/txt/src/txt/paragraph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -534,11 +534,12 @@ void Paragraph::Layout(double width, bool force) {
}
}

// Exclude trailing whitespace from right and center-justified lines so the
// last visible character in the line will be flush with the right margin.
// Exclude trailing whitespace from justified lines so the last visible
// character in the line will be flush with the right margin.
size_t line_end_index =
(paragraph_style_.effective_align() == TextAlign::right ||
paragraph_style_.effective_align() == TextAlign::center)
paragraph_style_.effective_align() == TextAlign::center ||
paragraph_style_.effective_align() == TextAlign::justify)
? line_range.end_excluding_whitespace
: line_range.end;

Expand All @@ -552,6 +553,14 @@ void Paragraph::Layout(double width, bool force) {
bidi_run.direction(), bidi_run.style());
}
}
bool line_runs_all_rtl =
line_runs.size() &&
std::accumulate(
line_runs.begin(), line_runs.end(), true,
[](const bool a, const BidiRun& b) { return a && b.is_rtl(); });
if (line_runs_all_rtl) {
std::reverse(words.begin(), words.end());
}

std::vector<GlyphPosition> line_glyph_positions;
std::vector<CodeUnitRun> line_code_unit_runs;
Expand Down Expand Up @@ -720,15 +729,26 @@ void Paragraph::Layout(double width, bool force) {
grapheme_code_unit_counts[i]);
}

if (word_index < words.size() &&
words[word_index].start == run.start() + glyph_code_units.start) {
bool at_word_start = false;
bool at_word_end = false;
if (word_index < words.size()) {
at_word_start =
words[word_index].start == run.start() + glyph_code_units.start;
at_word_end =
words[word_index].end == run.start() + glyph_code_units.end;
if (line_runs_all_rtl) {
std::swap(at_word_start, at_word_end);
}
}

if (at_word_start) {
word_start_position = run_x_offset + glyph_x_offset;
}

if (word_index < words.size() &&
words[word_index].end == run.start() + glyph_code_units.end) {
if (justify_line)
if (at_word_end) {
if (justify_line) {
justify_x_offset += word_gap_width;
}
word_index++;

if (!isnan(word_start_position)) {
Expand Down
1 change: 1 addition & 0 deletions third_party/txt/src/txt/paragraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,7 @@ class Paragraph {
FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, RightAlignParagraph);
FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, CenterAlignParagraph);
FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, JustifyAlignParagraph);
FRIEND_TEST_WINDOWS_DISABLED(ParagraphTest, JustifyRTL);
FRIEND_TEST(ParagraphTest, DecorationsParagraph);
FRIEND_TEST(ParagraphTest, ItalicsParagraph);
FRIEND_TEST(ParagraphTest, ChineseParagraph);
Expand Down
47 changes: 47 additions & 0 deletions third_party/txt/tests/paragraph_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,53 @@ TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(JustifyAlignParagraph)) {
ASSERT_TRUE(Snapshot());
}

TEST_F(ParagraphTest, DISABLE_ON_WINDOWS(JustifyRTL)) {
const char* text =
"אאא בּבּבּבּ אאאא בּבּ אאא בּבּבּ אאאאא בּבּבּבּ אאאא בּבּבּבּבּ "
"אאאאא בּבּבּבּבּ אאאבּבּבּבּבּבּאאאאא בּבּבּבּבּבּאאאאאבּבּבּבּבּבּ אאאאא בּבּבּבּבּ "
"אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ אאאאא בּבּבּבּבּבּ";

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;
txt::ParagraphBuilder builder(paragraph_style, GetTestFontCollection());

txt::TextStyle text_style;
text_style.font_families = std::vector<std::string>(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 = builder.Build();
size_t paragraph_width = GetTestCanvasWidth() - 100;
paragraph->Layout(paragraph_width);

paragraph->Paint(GetCanvas(), 0, 0);

ASSERT_TRUE(Snapshot());

auto glyph_line_width = [&paragraph](int index) {
return paragraph->glyph_lines_[index].positions.back().x_pos.end;
};

// All lines except the last should be justified to the width of the
// paragraph.
for (size_t i = 0; i < paragraph->glyph_lines_.size() - 1; ++i) {
ASSERT_EQ(glyph_line_width(i), paragraph_width);
}
ASSERT_NE(glyph_line_width(paragraph->glyph_lines_.size() - 1),
paragraph_width);
}

TEST_F(ParagraphTest, DecorationsParagraph) {
txt::ParagraphStyle paragraph_style;
paragraph_style.max_lines = 14;
Expand Down

0 comments on commit a3be1ff

Please sign in to comment.