mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Implement initial version of text justification, new tests, and fix bugs
with right and center alignment. Change-Id: I3b6a547e1d81c966b82108c02d60aa7181cb0b87
This commit is contained in:
parent
c553c87792
commit
19bb52f360
@ -56,14 +56,14 @@ class PaintRecord {
|
||||
|
||||
const TextStyle& style() const { return style_; }
|
||||
|
||||
double line() const { return line_; }
|
||||
size_t line() const { return line_; }
|
||||
|
||||
private:
|
||||
TextStyle style_;
|
||||
SkPoint offset_;
|
||||
sk_sp<SkTextBlob> text_;
|
||||
SkPaint::FontMetrics metrics_;
|
||||
int line_;
|
||||
size_t line_;
|
||||
|
||||
FTL_DISALLOW_COPY_AND_ASSIGN(PaintRecord);
|
||||
};
|
||||
|
||||
104
src/paragraph.cc
104
src/paragraph.cc
@ -24,6 +24,7 @@
|
||||
|
||||
#include <minikin/Layout.h>
|
||||
#include "lib/ftl/logging.h"
|
||||
#include "lib/txt/libs/minikin/LayoutUtils.h"
|
||||
#include "lib/txt/src/font_collection.h"
|
||||
#include "lib/txt/src/font_skia.h"
|
||||
#include "minikin/LineBreaker.h"
|
||||
@ -96,7 +97,7 @@ void GetFontAndMinikinPaint(const TextStyle& style,
|
||||
*font = minikin::FontStyle(GetWeight(style), GetItalic(style));
|
||||
paint->size = style.font_size;
|
||||
paint->letterSpacing = style.letter_spacing;
|
||||
paint->wordSpacing = style.word_spacing; // Likely not working yet.
|
||||
paint->wordSpacing = style.word_spacing;
|
||||
// TODO(abarth): word_spacing.
|
||||
}
|
||||
|
||||
@ -148,8 +149,9 @@ void Paragraph::Layout(double width,
|
||||
|
||||
width_ = width;
|
||||
|
||||
breaker_.setLineWidths(0.0f, 0, width);
|
||||
breaker_.setLineWidths(0.0f, 0, width_);
|
||||
AddRunsToLineBreaker(rootdir);
|
||||
breaker_.setJustified(paragraph_style_.text_align == TextAlign::justify);
|
||||
size_t breaks_count = breaker_.computeBreaks();
|
||||
const int* breaks = breaker_.getBreaks();
|
||||
|
||||
@ -171,12 +173,12 @@ void Paragraph::Layout(double width,
|
||||
SkScalar y = y_offset;
|
||||
size_t break_index = 0;
|
||||
double letter_spacing_offset = 0.0f;
|
||||
double word_spacing_offset = 0.0f;
|
||||
double max_line_spacing = 0.0f;
|
||||
double max_descent = 0.0f;
|
||||
double prev_max_descent = 0.0f;
|
||||
double line_width = 0.0f;
|
||||
std::vector<SkScalar> x_queue;
|
||||
size_t character_index = 0;
|
||||
|
||||
auto flush = [this, &x_queue, &y]() -> void {
|
||||
for (size_t i = 0; i < x_queue.size(); ++i) {
|
||||
@ -209,28 +211,44 @@ void Paragraph::Layout(double width,
|
||||
int bidiFlags = 0;
|
||||
layout.doLayout(text_.data(), layout_start, layout_end - layout_start,
|
||||
text_.size(), bidiFlags, font, minikin_paint, collection);
|
||||
|
||||
const size_t glyph_count = layout.nGlyphs();
|
||||
size_t blob_start = 0;
|
||||
// Each word/blob.
|
||||
// Each blob.
|
||||
std::vector<const SkTextBlobBuilder::RunBuffer*> buffers;
|
||||
std::vector<size_t> buffer_sizes;
|
||||
int word_count = 0;
|
||||
while (blob_start < glyph_count) {
|
||||
const size_t blob_length = GetBlobLength(layout, blob_start);
|
||||
buffer_sizes.push_back(blob_length);
|
||||
// TODO(abarth): Precompute when we can use allocRunPosH.
|
||||
paint.setTypeface(GetTypefaceForGlyph(layout, blob_start));
|
||||
|
||||
auto buffer = builder.allocRunPos(paint, blob_length);
|
||||
buffers.push_back(&builder.allocRunPos(paint, blob_length));
|
||||
|
||||
letter_spacing_offset += run.style.letter_spacing;
|
||||
|
||||
// Each Glyph/Letter.
|
||||
bool whitespace_ended = true;
|
||||
for (size_t blob_index = 0; blob_index < blob_length; ++blob_index) {
|
||||
const size_t glyph_index = blob_start + blob_index;
|
||||
buffer.glyphs[blob_index] = layout.getGlyphId(glyph_index);
|
||||
buffers.back()->glyphs[blob_index] = layout.getGlyphId(glyph_index);
|
||||
// Check if the current Glyph is a whitespace and handle multiple
|
||||
// whitespaces in a row.
|
||||
if (minikin::isWordSpace(text_[character_index])) {
|
||||
// Only increment word_count if it is the first in a series of
|
||||
// whitespaces.
|
||||
if (whitespace_ended)
|
||||
++word_count;
|
||||
whitespace_ended = false;
|
||||
} else {
|
||||
whitespace_ended = true;
|
||||
}
|
||||
++character_index;
|
||||
const size_t pos_index = 2 * blob_index;
|
||||
|
||||
buffer.pos[pos_index] = layout.getX(glyph_index) +
|
||||
letter_spacing_offset + word_spacing_offset;
|
||||
buffer.pos[pos_index + 1] = layout.getY(glyph_index);
|
||||
buffers.back()->pos[pos_index] =
|
||||
layout.getX(glyph_index) + letter_spacing_offset;
|
||||
buffers.back()->pos[pos_index + 1] = layout.getY(glyph_index);
|
||||
|
||||
letter_spacing_offset += run.style.letter_spacing;
|
||||
}
|
||||
@ -240,22 +258,21 @@ void Paragraph::Layout(double width,
|
||||
// removed depending on the specifications for letter spacing.
|
||||
// letter_spacing_offset -= run.style.letter_spacing;
|
||||
|
||||
word_spacing_offset += run.style.word_spacing;
|
||||
|
||||
max_intrinsic_width_ +=
|
||||
layout.getX(blob_start - 1) + letter_spacing_offset;
|
||||
}
|
||||
|
||||
// Subtract word offset to avoid big gap at end of run. This my be
|
||||
// removed depending on the specificatins for word spacing.
|
||||
word_spacing_offset -= run.style.word_spacing;
|
||||
|
||||
// TODO(abarth): We could keep the same SkTextBlobBuilder as long as the
|
||||
// color stayed the same.
|
||||
// TODO(garyq): Ensure that the typeface does not change throughout a
|
||||
// run.
|
||||
SkPaint::FontMetrics metrics;
|
||||
paint.getFontMetrics(&metrics);
|
||||
// Apply additional word spacing if the text is justified.
|
||||
if (paragraph_style_.text_align == TextAlign::justify &&
|
||||
buffer_sizes.size() > 0) {
|
||||
JustifyLine(buffers, buffer_sizes, word_count, character_index);
|
||||
}
|
||||
records_.push_back(
|
||||
PaintRecord{run.style, builder.make(), metrics, lines_});
|
||||
line_width +=
|
||||
@ -293,7 +310,7 @@ void Paragraph::Layout(double width,
|
||||
max_descent = 0.0f;
|
||||
x = 0.0f;
|
||||
letter_spacing_offset = 0.0f;
|
||||
word_spacing_offset = 0.0f;
|
||||
word_count = 0;
|
||||
line_width = 0.0f;
|
||||
// TODO(abarth): Use the line height, which is something like the max
|
||||
// font_size for runs in this line times the paragraph's line height.
|
||||
@ -314,6 +331,45 @@ void Paragraph::Layout(double width,
|
||||
height_ = y + max_descent;
|
||||
}
|
||||
|
||||
// Amends the buffers to incorporate justification.
|
||||
void Paragraph::JustifyLine(
|
||||
std::vector<const SkTextBlobBuilder::RunBuffer*>& buffers,
|
||||
std::vector<size_t>& buffer_sizes,
|
||||
int word_count,
|
||||
size_t character_index) {
|
||||
// TODO(garyq): Add letter_spacing_offset back in. It is Temporarily
|
||||
// removed.
|
||||
double justify_spacing =
|
||||
(width_ - breaker_.getWidths()[lines_]) / (word_count - 1);
|
||||
word_count = 0;
|
||||
// Set up index to properly access text_ because minikin::isWordSpace()
|
||||
// takes uint_16 instead of GlyphIDs.
|
||||
size_t line_character_index = character_index;
|
||||
for (size_t i = 0; i < buffers.size(); ++i)
|
||||
line_character_index -= buffer_sizes[i];
|
||||
bool whitespace_ended = true;
|
||||
for (size_t i = 0; i < buffers.size(); ++i) {
|
||||
for (size_t glyph_index = 0; glyph_index < buffer_sizes[i]; ++glyph_index) {
|
||||
// Check if the current Glyph is a whitespace and handle multiple
|
||||
// whitespaces in a row.
|
||||
if (minikin::isWordSpace(text_[line_character_index])) {
|
||||
// Only increment word_count and add justification spacing to
|
||||
// whitespace if it is the first in a series of whitespaces.
|
||||
if (whitespace_ended) {
|
||||
++word_count;
|
||||
buffers[i]->pos[glyph_index * 2] += justify_spacing * word_count;
|
||||
}
|
||||
whitespace_ended = false;
|
||||
} else {
|
||||
// Add justification spacing for all non-whitespace glyphs.
|
||||
buffers[i]->pos[glyph_index * 2] += justify_spacing * word_count;
|
||||
whitespace_ended = true;
|
||||
}
|
||||
++line_character_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const ParagraphStyle& Paragraph::GetParagraphStyle() const {
|
||||
return paragraph_style_;
|
||||
}
|
||||
@ -346,8 +402,8 @@ void Paragraph::SetParagraphStyle(const ParagraphStyle& style) {
|
||||
}
|
||||
|
||||
void Paragraph::Paint(SkCanvas* canvas, double x, double y) {
|
||||
SkPaint paint;
|
||||
for (const auto& record : records_) {
|
||||
SkPaint paint;
|
||||
paint.setColor(record.style().color);
|
||||
SkPoint offset = record.offset();
|
||||
// TODO(garyq): Fix alignment for paragraphs with multiple styles per line.
|
||||
@ -355,15 +411,15 @@ void Paragraph::Paint(SkCanvas* canvas, double x, double y) {
|
||||
case TextAlign::left:
|
||||
break;
|
||||
case TextAlign::right: {
|
||||
offset.offset(width_ - line_widths_[record.line()], 0);
|
||||
offset.offset(width_ - breaker_.getWidths()[record.line()], 0);
|
||||
break;
|
||||
}
|
||||
case TextAlign::center: {
|
||||
offset.offset((width_ - line_widths_[record.line()]) / 2, 0);
|
||||
offset.offset((width_ - breaker_.getWidths()[record.line()]) / 2, 0);
|
||||
break;
|
||||
}
|
||||
case TextAlign::justify: {
|
||||
// TODO(garyq): implement justify.
|
||||
// Justify is performed in the Layout().
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -371,12 +427,6 @@ void Paragraph::Paint(SkCanvas* canvas, double x, double y) {
|
||||
PaintDecorations(canvas, x + offset.x(), y + offset.y(), record.style(),
|
||||
record.metrics(), record.text());
|
||||
}
|
||||
|
||||
paint.setStyle(SkPaint::kFill_Style);
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStrokeWidth(4);
|
||||
paint.setColor(0xffFE938C);
|
||||
canvas->drawCircle(x, y, 3, paint);
|
||||
}
|
||||
|
||||
void Paragraph::PaintDecorations(SkCanvas* canvas,
|
||||
|
||||
@ -68,7 +68,10 @@ class Paragraph {
|
||||
FRIEND_TEST(RenderTest, RainbowParagraph);
|
||||
FRIEND_TEST(RenderTest, DefaultStyleParagraph);
|
||||
FRIEND_TEST(RenderTest, BoldParagraph);
|
||||
FRIEND_TEST(RenderTest, LinebreakParagraph);
|
||||
FRIEND_TEST(RenderTest, LeftAlignParagraph);
|
||||
FRIEND_TEST(RenderTest, RightAlignParagraph);
|
||||
FRIEND_TEST(RenderTest, CenterAlignParagraph);
|
||||
FRIEND_TEST(RenderTest, JustifyAlignParagraph);
|
||||
FRIEND_TEST(RenderTest, ItalicsParagraph);
|
||||
|
||||
std::vector<uint16_t> text_;
|
||||
@ -80,7 +83,7 @@ class Paragraph {
|
||||
// TODO(garyq): Height of the paragraph after Layout().
|
||||
SkScalar height_ = 0.0f;
|
||||
double width_ = 0.0f;
|
||||
int lines_ = 1;
|
||||
size_t lines_ = 0;
|
||||
double max_intrinsic_width_ = 0.0f;
|
||||
double min_intrinsic_width_ = 0.0f;
|
||||
double alphabetic_baseline_ = FLT_MAX;
|
||||
@ -93,6 +96,11 @@ class Paragraph {
|
||||
|
||||
void AddRunsToLineBreaker(const std::string& rootdir = "");
|
||||
|
||||
void JustifyLine(std::vector<const SkTextBlobBuilder::RunBuffer*>& buffers,
|
||||
std::vector<size_t>& buffer_sizes,
|
||||
int word_count,
|
||||
size_t character_index);
|
||||
|
||||
void PaintDecorations(SkCanvas* canvas,
|
||||
double x,
|
||||
double y,
|
||||
|
||||
@ -32,7 +32,7 @@ class ParagraphStyle {
|
||||
FontStyle font_style = FontStyle::normal;
|
||||
std::string font_family = "";
|
||||
double font_size = 14;
|
||||
int max_lines = 1;
|
||||
size_t max_lines = 1;
|
||||
double line_height = 1.0;
|
||||
std::string ellipsis;
|
||||
};
|
||||
|
||||
@ -60,7 +60,10 @@ class StyledRuns {
|
||||
FRIEND_TEST(RenderTest, RainbowParagraph);
|
||||
FRIEND_TEST(RenderTest, DefaultStyleParagraph);
|
||||
FRIEND_TEST(RenderTest, BoldParagraph);
|
||||
FRIEND_TEST(RenderTest, LinebreakParagraph);
|
||||
FRIEND_TEST(RenderTest, LeftAlignParagraph);
|
||||
FRIEND_TEST(RenderTest, RightAlignParagraph);
|
||||
FRIEND_TEST(RenderTest, CenterAlignParagraph);
|
||||
FRIEND_TEST(RenderTest, JustifyAlignParagraph);
|
||||
FRIEND_TEST(RenderTest, ItalicsParagraph);
|
||||
|
||||
struct IndexedRun {
|
||||
|
||||
@ -252,28 +252,132 @@ TEST_F(RenderTest, BoldParagraph) {
|
||||
ASSERT_TRUE(Snapshot());
|
||||
}
|
||||
|
||||
TEST_F(RenderTest, LinebreakParagraph) {
|
||||
TEST_F(RenderTest, LeftAlignParagraph) {
|
||||
const char* text =
|
||||
"This is a very long sentence to test if the text will properly wrap "
|
||||
"around and go to the next line. Sometimes, short sentence. Longer "
|
||||
"sentences are okay too because they are nessecary. Very short."
|
||||
"sentences are okay too because they are nessecary. Very short. "
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
|
||||
"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
|
||||
"commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
|
||||
"velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
|
||||
"occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
|
||||
"mollit anim id est laborum. "
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
|
||||
"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
|
||||
"commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
|
||||
"velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
|
||||
"occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
|
||||
"mollit anim id est laborum.";
|
||||
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::left;
|
||||
txt::ParagraphBuilder builder(paragraph_style);
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_size = 26;
|
||||
text_style.letter_spacing = 1;
|
||||
text_style.word_spacing = 5;
|
||||
text_style.color = SK_ColorBLACK;
|
||||
text_style.height = 1.15;
|
||||
text_style.decoration = txt::TextDecoration(0x1);
|
||||
text_style.decoration_color = SK_ColorBLACK;
|
||||
builder.PushStyle(text_style);
|
||||
|
||||
builder.AddText(u16_text);
|
||||
|
||||
builder.Pop();
|
||||
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->Layout(GetTestCanvasWidth() - 100, txt::GetFontDir());
|
||||
|
||||
paragraph->Paint(GetCanvas(), 0, 0);
|
||||
ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
|
||||
for (size_t i = 0; i < u16_text.length(); i++) {
|
||||
ASSERT_EQ(paragraph->text_[i], u16_text[i]);
|
||||
}
|
||||
ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
|
||||
ASSERT_EQ(paragraph->runs_.styles_.size(), 1ull);
|
||||
ASSERT_TRUE(paragraph->runs_.styles_[0].equals(text_style));
|
||||
ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
|
||||
ASSERT_TRUE(Snapshot());
|
||||
}
|
||||
|
||||
TEST_F(RenderTest, RightAlignParagraph) {
|
||||
const char* text =
|
||||
"This is a very long sentence to test if the text will properly wrap "
|
||||
"around and go to the next line. Sometimes, short sentence. Longer "
|
||||
"sentences are okay too because they are nessecary. Very short."
|
||||
"sentences are okay too because they are nessecary. Very short. "
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
|
||||
"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
|
||||
"commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
|
||||
"velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
|
||||
"occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
|
||||
"mollit anim id est laborum."
|
||||
"mollit anim id est laborum. "
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
|
||||
"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
|
||||
"commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
|
||||
"velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
|
||||
"occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
|
||||
"mollit anim id est laborum."
|
||||
"mollit anim id est laborum.";
|
||||
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::right;
|
||||
txt::ParagraphBuilder builder(paragraph_style);
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_size = 26;
|
||||
text_style.letter_spacing = 1;
|
||||
text_style.word_spacing = 5;
|
||||
text_style.color = SK_ColorBLACK;
|
||||
text_style.height = 1.15;
|
||||
text_style.decoration = txt::TextDecoration(0x1);
|
||||
text_style.decoration_color = SK_ColorBLACK;
|
||||
builder.PushStyle(text_style);
|
||||
|
||||
builder.AddText(u16_text);
|
||||
|
||||
builder.Pop();
|
||||
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->Layout(GetTestCanvasWidth() - 100, txt::GetFontDir());
|
||||
|
||||
paragraph->Paint(GetCanvas(), 0, 0);
|
||||
ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
|
||||
for (size_t i = 0; i < u16_text.length(); i++) {
|
||||
ASSERT_EQ(paragraph->text_[i], u16_text[i]);
|
||||
}
|
||||
ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
|
||||
ASSERT_EQ(paragraph->runs_.styles_.size(), 1ull);
|
||||
ASSERT_TRUE(paragraph->runs_.styles_[0].equals(text_style));
|
||||
ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
|
||||
ASSERT_TRUE(Snapshot());
|
||||
}
|
||||
|
||||
TEST_F(RenderTest, CenterAlignParagraph) {
|
||||
const char* text =
|
||||
"This is a very long sentence to test if the text will properly wrap "
|
||||
"around and go to the next line. Sometimes, short sentence. Longer "
|
||||
"sentences are okay too because they are nessecary. Very short. "
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
|
||||
"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
|
||||
"commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
|
||||
"velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
|
||||
"occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
|
||||
"mollit anim id est laborum. "
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
|
||||
"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
|
||||
@ -292,8 +396,8 @@ TEST_F(RenderTest, LinebreakParagraph) {
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_size = 26;
|
||||
// Letter spacing not yet implemented
|
||||
text_style.letter_spacing = 0;
|
||||
text_style.letter_spacing = 1;
|
||||
text_style.word_spacing = 5;
|
||||
text_style.color = SK_ColorBLACK;
|
||||
text_style.height = 1.15;
|
||||
text_style.decoration = txt::TextDecoration(0x1);
|
||||
@ -307,8 +411,64 @@ TEST_F(RenderTest, LinebreakParagraph) {
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->Layout(GetTestCanvasWidth() - 100, txt::GetFontDir());
|
||||
|
||||
paragraph->Paint(GetCanvas(), 0, 30.0);
|
||||
paragraph->Paint(GetCanvas(), 0, 0);
|
||||
ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
|
||||
for (size_t i = 0; i < u16_text.length(); i++) {
|
||||
ASSERT_EQ(paragraph->text_[i], u16_text[i]);
|
||||
}
|
||||
ASSERT_EQ(paragraph->runs_.runs_.size(), 1ull);
|
||||
ASSERT_EQ(paragraph->runs_.styles_.size(), 1ull);
|
||||
ASSERT_TRUE(paragraph->runs_.styles_[0].equals(text_style));
|
||||
ASSERT_EQ(paragraph->records_[0].style().color, text_style.color);
|
||||
ASSERT_TRUE(Snapshot());
|
||||
}
|
||||
|
||||
TEST_F(RenderTest, JustifyAlignParagraph) {
|
||||
const char* text =
|
||||
"This is a very long sentence to test if the text will properly wrap "
|
||||
"around and go to the next line. Sometimes, short sentence. Longer "
|
||||
"sentences are okay too because they are nessecary. Very short. "
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
|
||||
"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
|
||||
"commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
|
||||
"velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
|
||||
"occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
|
||||
"mollit anim id est laborum. "
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod "
|
||||
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
|
||||
"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
|
||||
"commodo consequat. Duis aute irure dolor in reprehenderit in voluptate "
|
||||
"velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint "
|
||||
"occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
|
||||
"mollit anim id est laborum.";
|
||||
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);
|
||||
|
||||
txt::TextStyle text_style;
|
||||
text_style.font_size = 26;
|
||||
text_style.letter_spacing = 1;
|
||||
text_style.word_spacing = 5;
|
||||
text_style.color = SK_ColorBLACK;
|
||||
text_style.height = 1.15;
|
||||
text_style.decoration = txt::TextDecoration(0x1);
|
||||
text_style.decoration_color = SK_ColorBLACK;
|
||||
builder.PushStyle(text_style);
|
||||
|
||||
builder.AddText(u16_text);
|
||||
|
||||
builder.Pop();
|
||||
|
||||
auto paragraph = builder.Build();
|
||||
paragraph->Layout(GetTestCanvasWidth() - 100, txt::GetFontDir());
|
||||
|
||||
paragraph->Paint(GetCanvas(), 0, 0);
|
||||
ASSERT_EQ(paragraph->text_.size(), std::string{text}.length());
|
||||
for (size_t i = 0; i < u16_text.length(); i++) {
|
||||
ASSERT_EQ(paragraph->text_[i], u16_text[i]);
|
||||
@ -321,7 +481,7 @@ TEST_F(RenderTest, LinebreakParagraph) {
|
||||
}
|
||||
|
||||
TEST_F(RenderTest, ItalicsParagraph) {
|
||||
const char* text = "I am Italicized!";
|
||||
const char* text = "I am Italicized! ";
|
||||
auto icu_text = icu::UnicodeString::fromUTF8(text);
|
||||
std::u16string u16_text(icu_text.getBuffer(),
|
||||
icu_text.getBuffer() + icu_text.length());
|
||||
|
||||
@ -47,7 +47,7 @@ bool RenderTest::Snapshot() {
|
||||
}
|
||||
|
||||
size_t RenderTest::GetTestCanvasWidth() const {
|
||||
return 800;
|
||||
return 1000;
|
||||
}
|
||||
|
||||
size_t RenderTest::GetTestCanvasHeight() const {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user