未验证 提交 a3be1ff5 编写于 作者: J Jason Simmons 提交者: GitHub

libtxt: support justification of RTL text (#7719)

Fixes https://github.com/flutter/flutter/issues/25567
上级 694300d3
......@@ -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;
......@@ -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;
......@@ -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)) {
......
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册