diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 8f0d02f1fa2a29de522f7cb24b567e511e838e65..df416b3b1c9db51a9784ef95e52b8db2dda48bf0 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1116,7 +1116,6 @@ FILE: ../../../flutter/third_party/txt/src/txt/font_skia.cc FILE: ../../../flutter/third_party/txt/src/txt/font_skia.h FILE: ../../../flutter/third_party/txt/src/txt/font_style.h FILE: ../../../flutter/third_party/txt/src/txt/font_weight.h -FILE: ../../../flutter/third_party/txt/src/txt/line_metrics.h FILE: ../../../flutter/third_party/txt/src/txt/paint_record.cc FILE: ../../../flutter/third_party/txt/src/txt/paint_record.h FILE: ../../../flutter/third_party/txt/src/txt/paragraph.h @@ -1130,7 +1129,6 @@ FILE: ../../../flutter/third_party/txt/src/txt/paragraph_txt.cc FILE: ../../../flutter/third_party/txt/src/txt/paragraph_txt.h FILE: ../../../flutter/third_party/txt/src/txt/placeholder_run.cc FILE: ../../../flutter/third_party/txt/src/txt/placeholder_run.h -FILE: ../../../flutter/third_party/txt/src/txt/run_metrics.h FILE: ../../../flutter/third_party/txt/src/txt/styled_runs.cc FILE: ../../../flutter/third_party/txt/src/txt/styled_runs.h FILE: ../../../flutter/third_party/txt/src/txt/test_font_manager.cc diff --git a/third_party/txt/BUILD.gn b/third_party/txt/BUILD.gn index c713fbeb0593e5863d644948818dc5055712e361..d77d4b9c9f41da945ed24d58de061550ce503e79 100644 --- a/third_party/txt/BUILD.gn +++ b/third_party/txt/BUILD.gn @@ -87,7 +87,6 @@ source_set("txt") { "src/txt/font_skia.h", "src/txt/font_style.h", "src/txt/font_weight.h", - "src/txt/line_metrics.h", "src/txt/paint_record.cc", "src/txt/paint_record.h", "src/txt/paragraph.h", @@ -102,7 +101,6 @@ source_set("txt") { "src/txt/placeholder_run.cc", "src/txt/placeholder_run.h", "src/txt/platform.h", - "src/txt/run_metrics.h", "src/txt/styled_runs.cc", "src/txt/styled_runs.h", "src/txt/test_font_manager.cc", diff --git a/third_party/txt/src/txt/line_metrics.h b/third_party/txt/src/txt/line_metrics.h deleted file mode 100644 index 38cecd1dc717d920dd85ce2bcc2b6f1e6c74abb1..0000000000000000000000000000000000000000 --- a/third_party/txt/src/txt/line_metrics.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LIB_TXT_SRC_LINE_METRICS_H_ -#define LIB_TXT_SRC_LINE_METRICS_H_ - -#include -#include - -#include "run_metrics.h" - -namespace txt { - -class LineMetrics { - public: - // The following fields are used in the layout process itself. - - // The indexes in the text buffer the line begins and ends. - size_t start_index = 0; - size_t end_index = 0; - size_t end_excluding_whitespace = 0; - size_t end_including_newline = 0; - bool hard_break = false; - - // The following fields are tracked after or during layout to provide to - // the user as well as for computing bounding boxes. - - // The final computed ascent and descent for the line. This can be impacted by - // the strut, height, scaling, as well as outlying runs that are very tall. - // - // The top edge is `baseline - ascent` and the bottom edge is `baseline + - // descent`. Ascent and descent are provided as positive numbers. Raw numbers - // for specific runs of text can be obtained in run_metrics_map. These values - // are the cumulative metrics for the entire line. - double ascent = 0.0; - double descent = 0.0; - double unscaled_ascent = 0.0; - // Height of the line. - double height = 0.0; - // Width of the line. - double width = 0.0; - // The left edge of the line. The right edge can be obtained with `left + - // width` - double left = 0.0; - // The y position of the baseline for this line from the top of the paragraph. - double baseline = 0.0; - // Zero indexed line number. - size_t line_number = 0; - - // Mapping between text index ranges and the FontMetrics associated with - // them. The first run will be keyed under start_index. The metrics here - // are before layout and are the base values we calculate from. - std::map run_metrics; - - LineMetrics(); - - LineMetrics(size_t start, - size_t end, - size_t end_excluding_whitespace, - size_t end_including_newline, - bool hard_break) - : start_index(start), - end_index(end), - end_excluding_whitespace(end_excluding_whitespace), - end_including_newline(end_including_newline), - hard_break(hard_break) {} -}; - -} // namespace txt - -#endif // LIB_TXT_SRC_LINE_METRICS_H_ diff --git a/third_party/txt/src/txt/paragraph.h b/third_party/txt/src/txt/paragraph.h index 19710c464cf1b7ba82eb4427efa49dc54a807235..a197cddd8315f7f743587089d81429adf191c02b 100644 --- a/third_party/txt/src/txt/paragraph.h +++ b/third_party/txt/src/txt/paragraph.h @@ -1,4 +1,3 @@ - /* * Copyright 2017 Google Inc. * @@ -18,7 +17,6 @@ #ifndef LIB_TXT_SRC_PARAGRAPH_H_ #define LIB_TXT_SRC_PARAGRAPH_H_ -#include "line_metrics.h" #include "paragraph_style.h" class SkCanvas; @@ -173,8 +171,6 @@ class Paragraph { // Finds the first and last glyphs that define a word containing the glyph at // index offset. virtual Range GetWordBoundary(size_t offset) = 0; - - virtual std::vector& GetLineMetrics() = 0; }; } // namespace txt diff --git a/third_party/txt/src/txt/paragraph_txt.cc b/third_party/txt/src/txt/paragraph_txt.cc index c3887cacc883361c60f787415f3b1290ace75291..8cf2e78232b51cfe7a6152b57202f15137671c55 100644 --- a/third_party/txt/src/txt/paragraph_txt.cc +++ b/third_party/txt/src/txt/paragraph_txt.cc @@ -211,7 +211,6 @@ ParagraphTxt::CodeUnitRun::CodeUnitRun(std::vector&& p, Range x, size_t line, const SkFontMetrics& metrics, - const TextStyle& st, TextDirection dir, const PlaceholderRun* placeholder) : positions(std::move(p)), @@ -219,7 +218,6 @@ ParagraphTxt::CodeUnitRun::CodeUnitRun(std::vector&& p, x_pos(x), line_number(line), font_metrics(metrics), - style(&st), direction(dir), placeholder_run(placeholder) {} @@ -252,7 +250,7 @@ void ParagraphTxt::SetInlinePlaceholders( } bool ParagraphTxt::ComputeLineBreaks() { - line_metrics_.clear(); + line_ranges_.clear(); line_widths_.clear(); max_intrinsic_width_ = 0; @@ -278,8 +276,8 @@ bool ParagraphTxt::ComputeLineBreaks() { size_t block_size = block_end - block_start; if (block_size == 0) { - line_metrics_.emplace_back(block_start, block_end, block_end, - block_end + 1, true); + line_ranges_.emplace_back(block_start, block_end, block_end, + block_end + 1, true); line_widths_.push_back(0); continue; } @@ -371,9 +369,9 @@ bool ParagraphTxt::ComputeLineBreaks() { minikin::isLineEndSpace(text_[line_end_excluding_whitespace - 1])) { line_end_excluding_whitespace--; } - line_metrics_.emplace_back(line_start, line_end, - line_end_excluding_whitespace, - line_end_including_newline, hard_break); + line_ranges_.emplace_back(line_start, line_end, + line_end_excluding_whitespace, + line_end_including_newline, hard_break); line_widths_.push_back(breaker_.getWidths()[i]); } @@ -656,14 +654,6 @@ void ParagraphTxt::Layout(double width) { needs_layout_ = false; - records_.clear(); - glyph_lines_.clear(); - code_unit_runs_.clear(); - inline_placeholder_code_unit_runs_.clear(); - max_right_ = FLT_MIN; - min_left_ = FLT_MAX; - final_line_count_ = 0; - if (!ComputeLineBreaks()) return; @@ -676,6 +666,18 @@ void ParagraphTxt::Layout(double width) { font.setSubpixel(true); font.setHinting(SkFontHinting::kSlight); + records_.clear(); + line_heights_.clear(); + line_baselines_.clear(); + glyph_lines_.clear(); + code_unit_runs_.clear(); + inline_placeholder_code_unit_runs_.clear(); + line_max_spacings_.clear(); + line_max_descent_.clear(); + line_max_ascent_.clear(); + max_right_ = FLT_MIN; + min_left_ = FLT_MAX; + minikin::Layout layout; SkTextBlobBuilder builder; double y_offset = 0; @@ -686,13 +688,12 @@ void ParagraphTxt::Layout(double width) { ComputeStrut(&strut_, font); // Paragraph bounds tracking. - size_t line_limit = - std::min(paragraph_style_.max_lines, line_metrics_.size()); - did_exceed_max_lines_ = (line_metrics_.size() > paragraph_style_.max_lines); + size_t line_limit = std::min(paragraph_style_.max_lines, line_ranges_.size()); + did_exceed_max_lines_ = (line_ranges_.size() > paragraph_style_.max_lines); size_t placeholder_run_index = 0; for (size_t line_number = 0; line_number < line_limit; ++line_number) { - LineMetrics& line_metrics = line_metrics_[line_number]; + const LineRange& line_range = line_ranges_[line_number]; // Break the line into words if justification should be applied. std::vector> words; @@ -700,8 +701,8 @@ void ParagraphTxt::Layout(double width) { size_t word_index = 0; bool justify_line = (paragraph_style_.text_align == TextAlign::justify && - line_number != line_limit - 1 && !line_metrics.hard_break); - FindWords(text_, line_metrics.start_index, line_metrics.end_index, &words); + line_number != line_limit - 1 && !line_range.hard_break); + FindWords(text_, line_range.start, line_range.end, &words); if (justify_line) { if (words.size() > 1) { word_gap_width = @@ -715,8 +716,8 @@ void ParagraphTxt::Layout(double width) { (paragraph_style_.effective_align() == TextAlign::right || paragraph_style_.effective_align() == TextAlign::center || paragraph_style_.effective_align() == TextAlign::justify) - ? line_metrics.end_excluding_whitespace - : line_metrics.end_index; + ? line_range.end_excluding_whitespace + : line_range.end; // Find the runs comprising this line. std::vector line_runs; @@ -732,13 +733,13 @@ void ParagraphTxt::Layout(double width) { // impact on the layout. std::unique_ptr ghost_run = nullptr; if (paragraph_style_.ellipsis.empty() && - line_metrics.end_excluding_whitespace < line_metrics.end_index && - bidi_run.start() <= line_metrics.end_index && + line_range.end_excluding_whitespace < line_range.end && + bidi_run.start() <= line_range.end && bidi_run.end() > line_end_index) { ghost_run = std::make_unique( std::max(bidi_run.start(), line_end_index), - std::min(bidi_run.end(), line_metrics.end_index), - bidi_run.direction(), bidi_run.style(), true); + std::min(bidi_run.end(), line_range.end), bidi_run.direction(), + bidi_run.style(), true); } // Include the ghost run before normal run if RTL if (bidi_run.direction() == TextDirection::rtl && ghost_run != nullptr) { @@ -746,22 +747,21 @@ void ParagraphTxt::Layout(double width) { } // Emplace a normal line run. if (bidi_run.start() < line_end_index && - bidi_run.end() > line_metrics.start_index) { + bidi_run.end() > line_range.start) { // The run is a placeholder run. if (bidi_run.size() == 1 && text_[bidi_run.start()] == objReplacementChar && obj_replacement_char_indexes_.count(bidi_run.start()) != 0 && placeholder_run_index < inline_placeholders_.size()) { - line_runs.emplace_back( - std::max(bidi_run.start(), line_metrics.start_index), - std::min(bidi_run.end(), line_end_index), bidi_run.direction(), - bidi_run.style(), inline_placeholders_[placeholder_run_index]); + line_runs.emplace_back(std::max(bidi_run.start(), line_range.start), + std::min(bidi_run.end(), line_end_index), + bidi_run.direction(), bidi_run.style(), + inline_placeholders_[placeholder_run_index]); placeholder_run_index++; } else { - line_runs.emplace_back( - std::max(bidi_run.start(), line_metrics.start_index), - std::min(bidi_run.end(), line_end_index), bidi_run.direction(), - bidi_run.style()); + line_runs.emplace_back(std::max(bidi_run.start(), line_range.start), + std::min(bidi_run.end(), line_end_index), + bidi_run.direction(), bidi_run.style()); } } // Include the ghost run after normal run if LTR @@ -781,7 +781,6 @@ void ParagraphTxt::Layout(double width) { std::vector line_glyph_positions; std::vector line_code_unit_runs; std::vector line_inline_placeholder_code_unit_runs; - double run_x_offset = 0; double justify_x_offset = 0; std::vector paint_records; @@ -807,7 +806,7 @@ void ParagraphTxt::Layout(double width) { // is the last line (or lines are unlimited). const std::u16string& ellipsis = paragraph_style_.ellipsis; std::vector ellipsized_text; - if (ellipsis.length() && !isinf(width_) && !line_metrics.hard_break && + if (ellipsis.length() && !isinf(width_) && !line_range.hard_break && line_run_it == line_runs.end() - 1 && (line_number == line_limit - 1 || paragraph_style_.unlimited_lines())) { @@ -992,30 +991,22 @@ void ParagraphTxt::Layout(double width) { if (glyph_positions.empty()) continue; - // Store the font metrics and TextStyle in the LineMetrics for this line - // to provide metrics upon user request. We index this RunMetrics - // instance at `run.end() - 1` to allow map::lower_bound to access the - // correct RunMetrics at any text index. - size_t run_key = run.end() - 1; - line_metrics.run_metrics.emplace(run_key, &run.style()); - font.getMetrics(&line_metrics.run_metrics.at(run_key).GetFontMetrics()); - - SkFontMetrics* metrics; - metrics = &line_metrics.run_metrics.at(run_key).GetFontMetrics(); + SkFontMetrics metrics; + font.getMetrics(&metrics); Range record_x_pos( glyph_positions.front().x_pos.start - run_x_offset, glyph_positions.back().x_pos.end - run_x_offset); if (run.is_placeholder_run()) { paint_records.emplace_back( run.style(), SkPoint::Make(run_x_offset + justify_x_offset, 0), - builder.make(), *metrics, line_number, record_x_pos.start, + builder.make(), metrics, line_number, record_x_pos.start, record_x_pos.start + run.placeholder_run()->width, run.is_ghost(), run.placeholder_run()); run_x_offset += run.placeholder_run()->width; } else { paint_records.emplace_back( run.style(), SkPoint::Make(run_x_offset + justify_x_offset, 0), - builder.make(), *metrics, line_number, record_x_pos.start, + builder.make(), metrics, line_number, record_x_pos.start, record_x_pos.end, run.is_ghost()); } justify_x_offset += justify_x_offset_delta; @@ -1039,9 +1030,7 @@ void ParagraphTxt::Layout(double width) { ? glyph_positions.back().x_pos.start + run.placeholder_run()->width : glyph_positions.back().x_pos.end), - line_number, *metrics, run.style(), run.direction(), - run.placeholder_run()); - + line_number, metrics, run.direction(), run.placeholder_run()); if (run.is_placeholder_run()) { line_inline_placeholder_code_unit_runs.push_back( line_code_unit_runs.back()); @@ -1079,11 +1068,11 @@ void ParagraphTxt::Layout(double width) { } } - size_t next_line_start = (line_number < line_metrics_.size() - 1) - ? line_metrics_[line_number + 1].start_index + size_t next_line_start = (line_number < line_ranges_.size() - 1) + ? line_ranges_[line_number + 1].start : text_.size(); glyph_lines_.emplace_back(std::move(line_glyph_positions), - next_line_start - line_metrics.start_index); + next_line_start - line_range.start); code_unit_runs_.insert(code_unit_runs_.end(), line_code_unit_runs.begin(), line_code_unit_runs.end()); inline_placeholder_code_unit_runs_.insert( @@ -1151,22 +1140,17 @@ void ParagraphTxt::Layout(double width) { ideographic_baseline_ = (max_ascent + max_descent); } - line_metrics.height = - (line_number == 0 ? 0 : line_metrics_[line_number - 1].height) + - round(max_ascent + max_descent); - line_metrics.baseline = line_metrics.height - max_descent; - + line_heights_.push_back((line_heights_.empty() ? 0 : line_heights_.back()) + + round(max_ascent + max_descent)); + line_baselines_.push_back(line_heights_.back() - max_descent); y_offset += round(max_ascent + prev_max_descent); prev_max_descent = max_descent; - line_metrics.line_number = line_number; - line_metrics.ascent = max_ascent; - line_metrics.descent = max_descent; - line_metrics.unscaled_ascent = max_unscaled_ascent; - line_metrics.width = line_widths_[line_number]; - line_metrics.left = line_x_offset; - - final_line_count_++; + // The max line spacing and ascent have been multiplied by -1 to make math + // in GetRectsForRange more logical/readable. + line_max_spacings_.push_back(max_ascent); + line_max_descent_.push_back(max_descent); + line_max_ascent_.push_back(max_unscaled_ascent); for (PaintRecord& paint_record : paint_records) { paint_record.SetOffset( @@ -1237,8 +1221,7 @@ size_t ParagraphTxt::TextSize() const { } double ParagraphTxt::GetHeight() { - return final_line_count_ == 0 ? 0 - : line_metrics_[final_line_count_ - 1].height; + return line_heights_.size() ? line_heights_.back() : 0; } double ParagraphTxt::GetMaxWidth() { @@ -1556,7 +1539,7 @@ std::vector ParagraphTxt::GetRectsForRange( SkScalar min_left = FLT_MAX; }; - std::map line_box_metrics; + std::map line_metrics; // Text direction of the first line so we can extend the correct side for // RectWidthStyle::kMax. TextDirection first_line_dir = TextDirection::ltr; @@ -1574,7 +1557,7 @@ std::vector ParagraphTxt::GetRectsForRange( if (run.code_units.end <= start) continue; - double baseline = line_metrics_[run.line_number].baseline; + double baseline = line_baselines_[run.line_number]; SkScalar top = baseline + run.font_metrics.fAscent; SkScalar bottom = baseline + run.font_metrics.fDescent; @@ -1617,40 +1600,39 @@ std::vector ParagraphTxt::GetRectsForRange( // Keep track of the min and max horizontal coordinates over all lines. Not // needed for kTight. if (rect_width_style == RectWidthStyle::kMax) { - line_box_metrics[run.line_number].max_right = - std::max(line_box_metrics[run.line_number].max_right, right); - line_box_metrics[run.line_number].min_left = - std::min(line_box_metrics[run.line_number].min_left, left); + line_metrics[run.line_number].max_right = + std::max(line_metrics[run.line_number].max_right, right); + line_metrics[run.line_number].min_left = + std::min(line_metrics[run.line_number].min_left, left); if (min_line == run.line_number) { first_line_dir = run.direction; } } - line_box_metrics[run.line_number].boxes.emplace_back( + line_metrics[run.line_number].boxes.emplace_back( SkRect::MakeLTRB(left, top, right, bottom), run.direction); } // Add empty rectangles representing any newline characters within the // range. - for (size_t line_number = 0; line_number < line_metrics_.size(); + for (size_t line_number = 0; line_number < line_ranges_.size(); ++line_number) { - LineMetrics& line = line_metrics_[line_number]; - if (line.start_index >= end) + const LineRange& line = line_ranges_[line_number]; + if (line.start >= end) break; if (line.end_including_newline <= start) continue; - if (line_box_metrics.find(line_number) == line_box_metrics.end()) { - if (line.end_index != line.end_including_newline && - line.end_index >= start && line.end_including_newline <= end) { + if (line_metrics.find(line_number) == line_metrics.end()) { + if (line.end != line.end_including_newline && line.end >= start && + line.end_including_newline <= end) { SkScalar x = line_widths_[line_number]; // Move empty box to center if center aligned and is an empty line. if (x == 0 && !isinf(width_) && paragraph_style_.effective_align() == TextAlign::center) { x = width_ / 2; } - SkScalar top = - (line_number > 0) ? line_metrics_[line_number - 1].height : 0; - SkScalar bottom = line_metrics_[line_number].height; - line_box_metrics[line_number].boxes.emplace_back( + SkScalar top = (line_number > 0) ? line_heights_[line_number - 1] : 0; + SkScalar bottom = line_heights_[line_number]; + line_metrics[line_number].boxes.emplace_back( SkRect::MakeLTRB(x, top, x, bottom), TextDirection::ltr); } } @@ -1658,30 +1640,28 @@ std::vector ParagraphTxt::GetRectsForRange( // "Post-process" metrics and aggregate final rects to return. std::vector boxes; - for (const auto& kv : line_box_metrics) { + for (const auto& kv : line_metrics) { // Handle rect_width_styles. We skip the last line because not everything is // selected. if (rect_width_style == RectWidthStyle::kMax && kv.first != max_line) { - if (line_box_metrics[kv.first].min_left > min_left_ && + if (line_metrics[kv.first].min_left > min_left_ && (kv.first != min_line || first_line_dir == TextDirection::rtl)) { - line_box_metrics[kv.first].boxes.emplace_back( - SkRect::MakeLTRB(min_left_, - line_metrics_[kv.first].baseline - - line_metrics_[kv.first].unscaled_ascent, - line_box_metrics[kv.first].min_left, - line_metrics_[kv.first].baseline + - line_metrics_[kv.first].descent), + line_metrics[kv.first].boxes.emplace_back( + SkRect::MakeLTRB( + min_left_, + line_baselines_[kv.first] - line_max_ascent_[kv.first], + line_metrics[kv.first].min_left, + line_baselines_[kv.first] + line_max_descent_[kv.first]), TextDirection::rtl); } - if (line_box_metrics[kv.first].max_right < max_right_ && + if (line_metrics[kv.first].max_right < max_right_ && (kv.first != min_line || first_line_dir == TextDirection::ltr)) { - line_box_metrics[kv.first].boxes.emplace_back( - SkRect::MakeLTRB(line_box_metrics[kv.first].max_right, - line_metrics_[kv.first].baseline - - line_metrics_[kv.first].unscaled_ascent, - max_right_, - line_metrics_[kv.first].baseline + - line_metrics_[kv.first].descent), + line_metrics[kv.first].boxes.emplace_back( + SkRect::MakeLTRB( + line_metrics[kv.first].max_right, + line_baselines_[kv.first] - line_max_ascent_[kv.first], + max_right_, + line_baselines_[kv.first] + line_max_descent_[kv.first]), TextDirection::ltr); } } @@ -1694,29 +1674,27 @@ std::vector ParagraphTxt::GetRectsForRange( } else if (rect_height_style == RectHeightStyle::kMax) { for (const Paragraph::TextBox& box : kv.second.boxes) { boxes.emplace_back( - SkRect::MakeLTRB(box.rect.fLeft, - line_metrics_[kv.first].baseline - - line_metrics_[kv.first].unscaled_ascent, - box.rect.fRight, - line_metrics_[kv.first].baseline + - line_metrics_[kv.first].descent), + SkRect::MakeLTRB( + box.rect.fLeft, + line_baselines_[kv.first] - line_max_ascent_[kv.first], + box.rect.fRight, + line_baselines_[kv.first] + line_max_descent_[kv.first]), box.direction); } } else if (rect_height_style == RectHeightStyle::kIncludeLineSpacingMiddle) { SkScalar adjusted_bottom = - line_metrics_[kv.first].baseline + line_metrics_[kv.first].descent; - if (kv.first < line_metrics_.size() - 1) { - adjusted_bottom += (line_metrics_[kv.first + 1].ascent - - line_metrics_[kv.first + 1].unscaled_ascent) / + line_baselines_[kv.first] + line_max_descent_[kv.first]; + if (kv.first < line_ranges_.size() - 1) { + adjusted_bottom += (line_max_spacings_[kv.first + 1] - + line_max_ascent_[kv.first + 1]) / 2; } - SkScalar adjusted_top = line_metrics_[kv.first].baseline - - line_metrics_[kv.first].unscaled_ascent; + SkScalar adjusted_top = + line_baselines_[kv.first] - line_max_ascent_[kv.first]; if (kv.first != 0) { - adjusted_top -= (line_metrics_[kv.first].ascent - - line_metrics_[kv.first].unscaled_ascent) / - 2; + adjusted_top -= + (line_max_spacings_[kv.first] - line_max_ascent_[kv.first]) / 2; } for (const Paragraph::TextBox& box : kv.second.boxes) { boxes.emplace_back(SkRect::MakeLTRB(box.rect.fLeft, adjusted_top, @@ -1726,41 +1704,37 @@ std::vector ParagraphTxt::GetRectsForRange( } else if (rect_height_style == RectHeightStyle::kIncludeLineSpacingTop) { for (const Paragraph::TextBox& box : kv.second.boxes) { SkScalar adjusted_top = - kv.first == 0 ? line_metrics_[kv.first].baseline - - line_metrics_[kv.first].unscaled_ascent - : line_metrics_[kv.first].baseline - - line_metrics_[kv.first].ascent; + kv.first == 0 + ? line_baselines_[kv.first] - line_max_ascent_[kv.first] + : line_baselines_[kv.first] - line_max_spacings_[kv.first]; boxes.emplace_back( - SkRect::MakeLTRB(box.rect.fLeft, adjusted_top, box.rect.fRight, - line_metrics_[kv.first].baseline + - line_metrics_[kv.first].descent), + SkRect::MakeLTRB( + box.rect.fLeft, adjusted_top, box.rect.fRight, + line_baselines_[kv.first] + line_max_descent_[kv.first]), box.direction); } } else if (rect_height_style == RectHeightStyle::kIncludeLineSpacingBottom) { for (const Paragraph::TextBox& box : kv.second.boxes) { SkScalar adjusted_bottom = - line_metrics_[kv.first].baseline + line_metrics_[kv.first].descent; - if (kv.first < line_metrics_.size() - 1) { - adjusted_bottom += -line_metrics_[kv.first].unscaled_ascent + - line_metrics_[kv.first].ascent; + line_baselines_[kv.first] + line_max_descent_[kv.first]; + if (kv.first < line_ranges_.size() - 1) { + adjusted_bottom += + -line_max_ascent_[kv.first] + line_max_spacings_[kv.first]; } - boxes.emplace_back( - SkRect::MakeLTRB(box.rect.fLeft, - line_metrics_[kv.first].baseline - - line_metrics_[kv.first].unscaled_ascent, - box.rect.fRight, adjusted_bottom), - box.direction); + boxes.emplace_back(SkRect::MakeLTRB(box.rect.fLeft, + line_baselines_[kv.first] - + line_max_ascent_[kv.first], + box.rect.fRight, adjusted_bottom), + box.direction); } } else if (rect_height_style == RectHeightStyle::kStrut) { if (IsStrutValid()) { for (const Paragraph::TextBox& box : kv.second.boxes) { boxes.emplace_back( SkRect::MakeLTRB( - box.rect.fLeft, - line_metrics_[kv.first].baseline - strut_.ascent, - box.rect.fRight, - line_metrics_[kv.first].baseline + strut_.descent), + box.rect.fLeft, line_baselines_[kv.first] - strut_.ascent, + box.rect.fRight, line_baselines_[kv.first] + strut_.descent), box.direction); } } else { @@ -1776,12 +1750,12 @@ std::vector ParagraphTxt::GetRectsForRange( Paragraph::PositionWithAffinity ParagraphTxt::GetGlyphPositionAtCoordinate( double dx, double dy) { - if (line_metrics_.empty()) + if (line_heights_.empty()) return PositionWithAffinity(0, DOWNSTREAM); size_t y_index; - for (y_index = 0; y_index < line_metrics_.size() - 1; ++y_index) { - if (dy < line_metrics_[y_index].height) + for (y_index = 0; y_index < line_heights_.size() - 1; ++y_index) { + if (dy < line_heights_[y_index]) break; } @@ -1871,7 +1845,7 @@ std::vector ParagraphTxt::GetRectsForPlaceholders() { // Generate initial boxes and calculate metrics. for (const CodeUnitRun& run : inline_placeholder_code_unit_runs_) { // Check to see if we are finished. - double baseline = line_metrics_[run.line_number].baseline; + double baseline = line_baselines_[run.line_number]; SkScalar top = baseline + run.font_metrics.fAscent; SkScalar bottom = baseline + run.font_metrics.fDescent; @@ -1917,7 +1891,7 @@ Paragraph::Range ParagraphTxt::GetWordBoundary(size_t offset) { } size_t ParagraphTxt::GetLineCount() { - return final_line_count_; + return line_heights_.size(); } bool ParagraphTxt::DidExceedMaxLines() { @@ -1928,8 +1902,4 @@ void ParagraphTxt::SetDirty(bool dirty) { needs_layout_ = dirty; } -std::vector& ParagraphTxt::GetLineMetrics() { - return line_metrics_; -} - } // namespace txt diff --git a/third_party/txt/src/txt/paragraph_txt.h b/third_party/txt/src/txt/paragraph_txt.h index aa79df9c8d14dcc988c03050d3ed39da28e5a441..c023f0d0762c25f7c145622b74bfa5feef3656fb 100644 --- a/third_party/txt/src/txt/paragraph_txt.h +++ b/third_party/txt/src/txt/paragraph_txt.h @@ -24,13 +24,11 @@ #include "flutter/fml/compiler_specific.h" #include "flutter/fml/macros.h" #include "font_collection.h" -#include "line_metrics.h" #include "minikin/LineBreaker.h" #include "paint_record.h" #include "paragraph.h" #include "paragraph_style.h" #include "placeholder_run.h" -#include "run_metrics.h" #include "styled_runs.h" #include "third_party/googletest/googletest/include/gtest/gtest_prod.h" // nogncheck #include "third_party/skia/include/core/SkFontMetrics.h" @@ -115,10 +113,6 @@ class ParagraphTxt : public Paragraph { bool DidExceedMaxLines() override; - // Gets the full vector of LineMetrics which includes detailed data on each - // line in the final layout. - std::vector& GetLineMetrics() override; - // Sets the needs_layout_ to dirty. When Layout() is called, a new Layout will // be performed when this is set to true. Can also be used to prevent a new // Layout from being calculated by setting to false. @@ -178,13 +172,26 @@ class ParagraphTxt : public Paragraph { minikin::LineBreaker breaker_; mutable std::unique_ptr word_breaker_; - std::vector line_metrics_; - size_t final_line_count_; + struct LineRange { + LineRange(size_t s, size_t e, size_t eew, size_t ein, bool h) + : start(s), + end(e), + end_excluding_whitespace(eew), + end_including_newline(ein), + hard_break(h) {} + size_t start, end; + size_t end_excluding_whitespace; + size_t end_including_newline; + bool hard_break; + }; + std::vector line_ranges_; std::vector line_widths_; // Stores the result of Layout(). std::vector records_; + std::vector line_heights_; + std::vector line_baselines_; bool did_exceed_max_lines_; // Strut metrics of zero will have no effect on the layout. @@ -199,6 +206,11 @@ class ParagraphTxt : public Paragraph { StrutMetrics strut_; + // Metrics for use in GetRectsForRange(...); + // Per-line max metrics over all runs in a given line. + std::vector line_max_spacings_; + std::vector line_max_descent_; + std::vector line_max_ascent_; // Overall left and right extremes over all lines. double max_right_; double min_left_; @@ -281,7 +293,6 @@ class ParagraphTxt : public Paragraph { Range x_pos; size_t line_number; SkFontMetrics font_metrics; - const TextStyle* style; TextDirection direction; const PlaceholderRun* placeholder_run; @@ -290,7 +301,6 @@ class ParagraphTxt : public Paragraph { Range x, size_t line, const SkFontMetrics& metrics, - const TextStyle& st, TextDirection dir, const PlaceholderRun* placeholder); diff --git a/third_party/txt/src/txt/run_metrics.h b/third_party/txt/src/txt/run_metrics.h deleted file mode 100644 index a51f91230f96b633033c2f6db527b9b2001a9ee1..0000000000000000000000000000000000000000 --- a/third_party/txt/src/txt/run_metrics.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2017 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LIB_TXT_SRC_RUN_METRICS_H_ -#define LIB_TXT_SRC_RUN_METRICS_H_ - -#include "text_style.h" -#include "third_party/skia/include/core/SkFontMetrics.h" - -namespace txt { - -// Contains the font metrics and TextStyle of a unique run. -class RunMetrics { - public: - RunMetrics(const TextStyle* style) : text_style_(style) {} - - RunMetrics(const TextStyle* style, SkFontMetrics& metrics) - : text_style_(style), font_metrics_(metrics) {} - - SkFontMetrics& GetFontMetrics() { return font_metrics_; } - - const TextStyle& GetTextStyle() const { return *text_style_; } - - private: - const TextStyle* text_style_; - - // SkFontMetrics contains the following metrics: - // - // * Top distance to reserve above baseline - // * Ascent distance to reserve below baseline - // * Descent extent below baseline - // * Bottom extent below baseline - // * Leading distance to add between lines - // * AvgCharWidth average character width - // * MaxCharWidth maximum character width - // * XMin minimum x - // * XMax maximum x - // * XHeight height of lower-case 'x' - // * CapHeight height of an upper-case letter - // * UnderlineThickness underline thickness - // * UnderlinePosition underline position relative to baseline - // * StrikeoutThickness strikeout thickness - // * StrikeoutPosition strikeout position relative to baseline - SkFontMetrics font_metrics_; -}; - -} // namespace txt - -#endif // LIB_TXT_SRC_RUN_METRICS_H_ diff --git a/third_party/txt/tests/paragraph_unittests.cc b/third_party/txt/tests/paragraph_unittests.cc index 5dac97c4f8beed8353ed96eceb0e3e6db9d3b4c6..30e7c076a58e57f867301ba4db6df7ba8110d01f 100644 --- a/third_party/txt/tests/paragraph_unittests.cc +++ b/third_party/txt/tests/paragraph_unittests.cc @@ -34,349 +34,6 @@ namespace txt { using ParagraphTest = RenderTest; -TEST_F(ParagraphTest, LineMetricsParagraph1) { - const char* text = "Hello! What is going on?\nSecond line \nthirdline"; - auto icu_text = icu::UnicodeString::fromUTF8(text); - std::u16string u16_text(icu_text.getBuffer(), - icu_text.getBuffer() + icu_text.length()); - - txt::ParagraphStyle paragraph_style; - txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); - - txt::TextStyle text_style; - // We must supply a font here, as the default is Arial, and we do not - // include Arial in our test fonts as it is proprietary. We want it to - // be Arial default though as it is one of the most common fonts on host - // platforms. On real devices/apps, Arial should be able to be resolved. - text_style.font_families = std::vector(1, "Roboto"); - text_style.color = SK_ColorBLACK; - builder.PushStyle(text_style); - builder.AddText(u16_text); - - builder.Pop(); - - auto paragraph = BuildParagraph(builder); - paragraph->Layout(GetTestCanvasWidth()); - - paragraph->Paint(GetCanvas(), 0, 0); - - ASSERT_TRUE(Snapshot()); - - ASSERT_EQ(paragraph->GetLineMetrics().size(), 3ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].start_index, 0ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].end_index, 24ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].end_including_newline, 25ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].end_excluding_whitespace, 24ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].hard_break, true); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].ascent, 12.988281); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].descent, 3.4179688); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].width, 149.67578); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].left, 0.0); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].baseline, 12.582031); - ASSERT_EQ(paragraph->GetLineMetrics()[0].line_number, 0ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].run_metrics.size(), 1ull); - ASSERT_EQ( - paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) - ->second.GetTextStyle() - .color, - SK_ColorBLACK); - ASSERT_EQ( - paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) - ->second.GetTextStyle() - .font_families, - std::vector(1, "Roboto")); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) - ->second.GetFontMetrics() - .fAscent, - -12.988281); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) - ->second.GetFontMetrics() - .fDescent, - 3.4179688); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) - ->second.GetFontMetrics() - .fXHeight, - 7.3964844); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) - ->second.GetFontMetrics() - .fLeading, - 0); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) - ->second.GetFontMetrics() - .fTop, - -14.786133); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[0].start_index) - ->second.GetFontMetrics() - .fUnderlinePosition, - 1.0253906); - - ASSERT_EQ(paragraph->GetLineMetrics()[1].start_index, 25ull); - ASSERT_EQ(paragraph->GetLineMetrics()[1].end_index, 37ull); - ASSERT_EQ(paragraph->GetLineMetrics()[1].end_including_newline, 38ull); - ASSERT_EQ(paragraph->GetLineMetrics()[1].end_excluding_whitespace, 36ull); - ASSERT_EQ(paragraph->GetLineMetrics()[1].hard_break, true); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].ascent, 12.988281); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].descent, 3.4179688); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].width, 72.039062); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].left, 0.0); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].baseline, 28.582031); - ASSERT_EQ(paragraph->GetLineMetrics()[1].line_number, 1ull); - ASSERT_EQ(paragraph->GetLineMetrics()[1].run_metrics.size(), 1ull); - ASSERT_EQ( - paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) - ->second.GetTextStyle() - .color, - SK_ColorBLACK); - ASSERT_EQ( - paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) - ->second.GetTextStyle() - .font_families, - std::vector(1, "Roboto")); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) - ->second.GetFontMetrics() - .fAscent, - -12.988281); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) - ->second.GetFontMetrics() - .fDescent, - 3.4179688); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) - ->second.GetFontMetrics() - .fXHeight, - 7.3964844); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) - ->second.GetFontMetrics() - .fLeading, - 0); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) - ->second.GetFontMetrics() - .fTop, - -14.786133); - ASSERT_FLOAT_EQ( - paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(paragraph->GetLineMetrics()[1].start_index) - ->second.GetFontMetrics() - .fUnderlinePosition, - 1.0253906); -} - -TEST_F(ParagraphTest, LineMetricsParagraph2) { - const char* text = "test string alphabetic"; - auto icu_text = icu::UnicodeString::fromUTF8(text); - std::u16string alphabetic(icu_text.getBuffer(), - icu_text.getBuffer() + icu_text.length()); - - const char* text2 = "测试中文日本語한국어"; - auto icu_text2 = icu::UnicodeString::fromUTF8(text2); - std::u16string cjk(icu_text2.getBuffer(), - icu_text2.getBuffer() + icu_text2.length()); - - txt::ParagraphStyle paragraph_style; - txt::ParagraphBuilderTxt builder(paragraph_style, GetTestFontCollection()); - - txt::TextStyle text_style; - text_style.font_families = std::vector(1, "Roboto"); - text_style.font_families.push_back("Noto Sans CJK JP"); - text_style.font_size = 27; - text_style.color = SK_ColorBLACK; - builder.PushStyle(text_style); - builder.AddText(alphabetic); - - text_style.font_size = 24; - builder.PushStyle(text_style); - builder.AddText(cjk); - - builder.Pop(); - - auto paragraph = BuildParagraph(builder); - paragraph->Layout(350); - - paragraph->Paint(GetCanvas(), 0, 0); - - ASSERT_TRUE(Snapshot()); - - ASSERT_EQ(paragraph->GetLineMetrics().size(), 2ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].start_index, 0ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].end_index, 26ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].end_including_newline, 26ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].end_excluding_whitespace, 26ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].hard_break, false); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].ascent, 27.84); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].descent, 7.6799998); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].width, 349.22266); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].left, 0.0); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0].baseline, 28.32); - ASSERT_EQ(paragraph->GetLineMetrics()[0].line_number, 0ull); - ASSERT_EQ(paragraph->GetLineMetrics()[0].run_metrics.size(), 2ull); - // First run - ASSERT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(2) - ->second.GetTextStyle() - .font_size, - 27); - ASSERT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(2) - ->second.GetTextStyle() - .font_families, - text_style.font_families); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(2) - ->second.GetFontMetrics() - .fAscent, - -25.048828); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(2) - ->second.GetFontMetrics() - .fDescent, - 6.5917969); - - ASSERT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(21) - ->second.GetTextStyle() - .font_size, - 27); - ASSERT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(21) - ->second.GetTextStyle() - .font_families, - text_style.font_families); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(21) - ->second.GetFontMetrics() - .fAscent, - -25.048828); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(21) - ->second.GetFontMetrics() - .fDescent, - 6.5917969); - - // Second run - ASSERT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(22) - ->second.GetTextStyle() - .font_size, - 24); - ASSERT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(22) - ->second.GetTextStyle() - .font_families, - text_style.font_families); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(22) - ->second.GetFontMetrics() - .fAscent, - -27.84); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(22) - ->second.GetFontMetrics() - .fDescent, - 7.6799998); - - ASSERT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(24) - ->second.GetTextStyle() - .font_size, - 24); - ASSERT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(24) - ->second.GetTextStyle() - .font_families, - text_style.font_families); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(24) - ->second.GetFontMetrics() - .fAscent, - -27.84); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[0] - .run_metrics.lower_bound(24) - ->second.GetFontMetrics() - .fDescent, - 7.6799998); - - ASSERT_EQ(paragraph->GetLineMetrics()[1].start_index, 26ull); - ASSERT_EQ(paragraph->GetLineMetrics()[1].end_index, 32ull); - ASSERT_EQ(paragraph->GetLineMetrics()[1].end_including_newline, 32ull); - ASSERT_EQ(paragraph->GetLineMetrics()[1].end_excluding_whitespace, 32ull); - ASSERT_EQ(paragraph->GetLineMetrics()[1].hard_break, true); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].ascent, 27.84); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].descent, 7.6799998); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].width, 138.23438); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].left, 0.0); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1].baseline, 64.32); - ASSERT_EQ(paragraph->GetLineMetrics()[1].line_number, 1ull); - ASSERT_EQ(paragraph->GetLineMetrics()[1].run_metrics.size(), 1ull); - // Indexing below the line will just resolve to the first run in the line. - ASSERT_EQ(paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(3) - ->second.GetTextStyle() - .font_size, - 24); - ASSERT_EQ(paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(3) - ->second.GetTextStyle() - .font_families, - text_style.font_families); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(3) - ->second.GetFontMetrics() - .fAscent, - -27.84); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(3) - ->second.GetFontMetrics() - .fDescent, - 7.6799998); - - // Indexing within the line - ASSERT_EQ(paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(31) - ->second.GetTextStyle() - .font_size, - 24); - ASSERT_EQ(paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(31) - ->second.GetTextStyle() - .font_families, - text_style.font_families); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(31) - ->second.GetFontMetrics() - .fAscent, - -27.84); - ASSERT_FLOAT_EQ(paragraph->GetLineMetrics()[1] - .run_metrics.lower_bound(31) - ->second.GetFontMetrics() - .fDescent, - 7.6799998); -} - TEST_F(ParagraphTest, SimpleParagraph) { const char* text = "Hello World Text Dialog"; auto icu_text = icu::UnicodeString::fromUTF8(text);