diff --git a/engine/src/flutter/src/paragraph.cc b/engine/src/flutter/src/paragraph.cc index f59dde05f25..a2d2e03a773 100644 --- a/engine/src/flutter/src/paragraph.cc +++ b/engine/src/flutter/src/paragraph.cc @@ -203,8 +203,8 @@ void Paragraph::Layout(double width, bool force) { double line_width = 0.0f; std::vector x_queue; double justify_spacing = 0; + double prev_word_pos = 0; - // Each blob. std::vector buffers; std::vector buffer_sizes; int word_count = 0; @@ -327,17 +327,6 @@ void Paragraph::Layout(double width, bool force) { ++blob_index) { const size_t glyph_index = blob_start + blob_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 (whitespace_set_.count(layout.getGlyphId(glyph_index)) > 0) { - // 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; - } const size_t pos_index = 2 * blob_index; @@ -347,10 +336,36 @@ void Paragraph::Layout(double width, bool force) { buffers.back()->pos[pos_index]); buffers.back()->pos[pos_index + 1] = layout.getY(glyph_index); + // Check if the current Glyph is a whitespace and handle multiple + // whitespaces in a row. + if (whitespace_set_.count(layout.getGlyphId(glyph_index)) > 0) { + // Only increment word_count if it is the first in a series of + // whitespaces. + if (whitespace_ended) { + ++word_count; + word_widths_.push_back(buffers.back()->pos[pos_index] + + layout.getCharAdvance(glyph_index) - + prev_word_pos); + prev_word_pos = buffers.back()->pos[pos_index] + + layout.getCharAdvance(glyph_index); + } + whitespace_ended = false; + } else { + whitespace_ended = true; + } + letter_spacing_offset += run.style.letter_spacing; } blob_start += blob_length; + // Add on the last word if the blob break was not on whitespace. + if (whitespace_ended) { + word_widths_.push_back( + layout.getX(blob_start - 1) + letter_spacing_offset - + run.style.letter_spacing + layout.getCharAdvance(blob_start - 1) - + prev_word_pos); + } + // Subtract letter offset to avoid big gap at end of run. This my be // removed depending on the specifications for letter spacing. // letter_spacing_offset -= run.style.letter_spacing; @@ -412,7 +427,7 @@ void Paragraph::Layout(double width, bool force) { max_descent = 0.0f; x = 0.0f; letter_spacing_offset = 0.0f; - // word_count = 0; + prev_word_pos = 0; line_width = 0.0f; break_index += 1; lines_++; @@ -440,6 +455,7 @@ void Paragraph::Layout(double width, bool force) { buffer_sizes.size() > 0) { JustifyLine(buffers, buffer_sizes, word_count, justify_spacing, -1); } + CalculateIntrinsicWidths(); } // Amends the buffers to incorporate justification. @@ -492,13 +508,22 @@ double Paragraph::GetIdeographicBaseline() const { return ideographic_baseline_; } +void Paragraph::CalculateIntrinsicWidths() { + for (size_t i = 0; i < word_widths_.size(); ++i) { + max_intrinsic_width_ += word_widths_[i]; + } + + // TODO(garyq): Implement the DP algorithm version instead of this stand in! + min_intrinsic_width_ = max_intrinsic_width_ / paragraph_style_.max_lines; +} + double Paragraph::GetMaxIntrinsicWidth() const { return max_intrinsic_width_; } double Paragraph::GetMinIntrinsicWidth() const { // TODO(garyq): This is a lower bound. Actual value may be slightly higher. - return max_intrinsic_width_ / paragraph_style_.max_lines; + return min_intrinsic_width_; } size_t Paragraph::TextSize() const { diff --git a/engine/src/flutter/src/paragraph.h b/engine/src/flutter/src/paragraph.h index a0785e647ab..870e64f4310 100644 --- a/engine/src/flutter/src/paragraph.h +++ b/engine/src/flutter/src/paragraph.h @@ -115,8 +115,11 @@ class Paragraph { SkScalar height_ = 0.0f; double width_ = 0.0f; size_t lines_ = 0; - double max_intrinsic_width_ = 0.0f; - double min_intrinsic_width_ = 0.0f; + double max_intrinsic_width_ = -1; + double min_intrinsic_width_ = -1; + // TODO(garyq): Instead of using whitespace to delimit "words", use the + // results of minikin breaker. + std::vector word_widths_; double alphabetic_baseline_ = FLT_MAX; double ideographic_baseline_ = FLT_MAX; bool needs_layout_ = true; @@ -167,6 +170,8 @@ class Paragraph { double y_offset, double width); + void CalculateIntrinsicWidths(); + FTL_DISALLOW_COPY_AND_ASSIGN(Paragraph); };