mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
libtxt: make the min/max intrinsic width calculations match expectations of the framework (flutter/engine#4220)
maxIntrinsicWidth is the sum of the width of all lines in the input (if the width were any smaller, the renderer might have to wrap a line) minIntrinsicWidth is the maximum width of a word (if the paragraph were any narrower, the renderer would have to truncate a word)
This commit is contained in:
parent
16934d4f9e
commit
df55d4f337
@ -249,6 +249,7 @@ void Paragraph::Layout(double width, bool force) {
|
||||
|
||||
records_.clear();
|
||||
line_heights_.clear();
|
||||
glyph_position_x_.clear();
|
||||
|
||||
minikin::Layout layout;
|
||||
SkTextBlobBuilder builder;
|
||||
@ -256,6 +257,7 @@ void Paragraph::Layout(double width, bool force) {
|
||||
size_t run_index = 0;
|
||||
double y_offset = 0;
|
||||
double prev_max_descent = 0;
|
||||
double max_word_width = 0;
|
||||
|
||||
for (size_t line_number = 0; line_number < line_limit; ++line_number) {
|
||||
size_t line_start = (line_number > 0) ? breaks[line_number - 1] : 0;
|
||||
@ -268,8 +270,8 @@ void Paragraph::Layout(double width, bool force) {
|
||||
bool justify_line =
|
||||
(paragraph_style_.text_align == TextAlign::justify &&
|
||||
line_number != line_limit - 1 && text_[line_end - 1] != '\n');
|
||||
FindWords(text_, line_start, line_end, &words);
|
||||
if (justify_line) {
|
||||
FindWords(text_, line_start, line_end, &words);
|
||||
if (words.size() > 1) {
|
||||
word_gap_width =
|
||||
(width_ - breaker_.getWidths()[line_number]) / (words.size() - 1);
|
||||
@ -370,6 +372,7 @@ void Paragraph::Layout(double width, bool force) {
|
||||
|
||||
double justify_x_offset = 0;
|
||||
size_t code_unit_index = 0;
|
||||
double word_start_position = std::numeric_limits<double>::quiet_NaN();
|
||||
|
||||
for (const Range& glyph_blob : glyph_blobs) {
|
||||
paint.setTypeface(GetTypefaceForGlyph(layout, glyph_blob.start));
|
||||
@ -386,6 +389,11 @@ void Paragraph::Layout(double width, bool force) {
|
||||
blob_buffer.pos[pos_index] = glyph_x_offset;
|
||||
blob_buffer.pos[pos_index + 1] = layout.getY(glyph_index);
|
||||
|
||||
if (word_index < words.size() &&
|
||||
code_unit_index == words[word_index].start) {
|
||||
word_start_position = run_x_offset + glyph_x_offset;
|
||||
}
|
||||
|
||||
float glyph_advance = layout.getCharAdvance(code_unit_index);
|
||||
|
||||
// The glyph may be a ligature. Determine how many input characters
|
||||
@ -416,10 +424,19 @@ void Paragraph::Layout(double width, bool force) {
|
||||
subglyph_advance, subglyph_code_unit_counts[i]);
|
||||
}
|
||||
|
||||
if (justify_line && word_index < words.size() &&
|
||||
if (word_index < words.size() &&
|
||||
code_unit_index == words[word_index].end) {
|
||||
justify_x_offset += word_gap_width;
|
||||
if (justify_line)
|
||||
justify_x_offset += word_gap_width;
|
||||
word_index++;
|
||||
|
||||
if (!isnan(word_start_position)) {
|
||||
double word_width =
|
||||
glyph_single_line_position_x.back().glyph_end() -
|
||||
word_start_position;
|
||||
max_word_width = std::max(word_width, max_word_width);
|
||||
word_start_position = std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -470,12 +487,17 @@ void Paragraph::Layout(double width, bool force) {
|
||||
glyph_position_x_.emplace_back(std::move(glyph_single_line_position_x));
|
||||
}
|
||||
|
||||
CalculateIntrinsicWidths();
|
||||
max_intrinsic_width_ = 0;
|
||||
for (size_t i = 0; i < breaks_count_; ++i) {
|
||||
max_intrinsic_width_ += breaker_.getWidths()[i];
|
||||
}
|
||||
min_intrinsic_width_ = std::min(max_word_width, max_intrinsic_width_);
|
||||
|
||||
breaker_.finish();
|
||||
}
|
||||
|
||||
double Paragraph::GetLineXOffset(size_t line) {
|
||||
if (line >= breaks_count_)
|
||||
if (line >= breaks_count_ || isinf(width_))
|
||||
return 0;
|
||||
|
||||
TextAlign align = paragraph_style_.text_align;
|
||||
@ -506,25 +528,6 @@ double Paragraph::GetIdeographicBaseline() const {
|
||||
return ideographic_baseline_;
|
||||
}
|
||||
|
||||
void Paragraph::CalculateIntrinsicWidths() {
|
||||
max_intrinsic_width_ = 0;
|
||||
for (size_t i = 0; i < GetLineCount(); ++i) {
|
||||
max_intrinsic_width_ += breaker_.getWidths()[i];
|
||||
}
|
||||
|
||||
// TODO(garyq): Investigate correctness of the following implementation of min
|
||||
// intrinsic width. This is currently the longest line in the text after
|
||||
// layout.
|
||||
min_intrinsic_width_ = 0;
|
||||
for (size_t i = 0; i < GetLineCount(); ++i) {
|
||||
min_intrinsic_width_ = fmax(min_intrinsic_width_, breaker_.getWidths()[i]);
|
||||
}
|
||||
|
||||
// Ensure that min < max widths.
|
||||
min_intrinsic_width_ = std::min(max_intrinsic_width_, min_intrinsic_width_);
|
||||
max_intrinsic_width_ = std::max(max_intrinsic_width_, min_intrinsic_width_);
|
||||
}
|
||||
|
||||
double Paragraph::GetMaxIntrinsicWidth() const {
|
||||
return max_intrinsic_width_;
|
||||
}
|
||||
|
||||
@ -260,8 +260,6 @@ class Paragraph {
|
||||
double y,
|
||||
size_t record_index);
|
||||
|
||||
void CalculateIntrinsicWidths();
|
||||
|
||||
FXL_DISALLOW_COPY_AND_ASSIGN(Paragraph);
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user