From 25106df293e8a793725bb73471fc0bf38658c181 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 27 Feb 2020 15:15:23 -0800 Subject: [PATCH 1/5] remove usage of Dart_New for paragraph/libtxt --- ci/licenses_golden/licenses_flutter | 2 - lib/ui/BUILD.gn | 2 - lib/ui/text.dart | 76 ++++++++++++++++++----------- lib/ui/text/line_metrics.cc | 48 ------------------ lib/ui/text/line_metrics.h | 13 ----- lib/ui/text/paragraph.cc | 73 +++++++++++++++++++-------- lib/ui/text/paragraph.h | 19 ++++---- lib/ui/text/paragraph_builder.cc | 4 +- lib/ui/text/paragraph_builder.h | 2 +- lib/ui/text/text_box.cc | 45 ----------------- 10 files changed, 112 insertions(+), 172 deletions(-) delete mode 100644 lib/ui/text/line_metrics.cc delete mode 100644 lib/ui/text/text_box.cc diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 21d438c4a7b41..d0182f4580ab0 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -354,13 +354,11 @@ FILE: ../../../flutter/lib/ui/text/asset_manager_font_provider.cc FILE: ../../../flutter/lib/ui/text/asset_manager_font_provider.h FILE: ../../../flutter/lib/ui/text/font_collection.cc FILE: ../../../flutter/lib/ui/text/font_collection.h -FILE: ../../../flutter/lib/ui/text/line_metrics.cc FILE: ../../../flutter/lib/ui/text/line_metrics.h FILE: ../../../flutter/lib/ui/text/paragraph.cc FILE: ../../../flutter/lib/ui/text/paragraph.h FILE: ../../../flutter/lib/ui/text/paragraph_builder.cc FILE: ../../../flutter/lib/ui/text/paragraph_builder.h -FILE: ../../../flutter/lib/ui/text/text_box.cc FILE: ../../../flutter/lib/ui/text/text_box.h FILE: ../../../flutter/lib/ui/ui.dart FILE: ../../../flutter/lib/ui/ui_dart_state.cc diff --git a/lib/ui/BUILD.gn b/lib/ui/BUILD.gn index 4cc81dff2154d..c904141b338e8 100644 --- a/lib/ui/BUILD.gn +++ b/lib/ui/BUILD.gn @@ -81,13 +81,11 @@ source_set("ui") { "text/asset_manager_font_provider.h", "text/font_collection.cc", "text/font_collection.h", - "text/line_metrics.cc", "text/line_metrics.h", "text/paragraph.cc", "text/paragraph.h", "text/paragraph_builder.cc", "text/paragraph_builder.h", - "text/text_box.cc", "text/text_box.h", "ui_dart_state.cc", "ui_dart_state.h", diff --git a/lib/ui/text.dart b/lib/ui/text.dart index bba18ded716be..f33ffbcc3762c 100644 --- a/lib/ui/text.dart +++ b/lib/ui/text.dart @@ -1306,16 +1306,6 @@ class TextBox { this.direction, ); - @pragma('vm:entry-point') - // ignore: unused_element - TextBox._( - this.left, - this.top, - this.right, - this.bottom, - int directionIndex, - ) : direction = TextDirection.values[directionIndex]; - /// The left edge of the text box, irrespective of direction. /// /// To get the leading edge (which may depend on the [direction]), consider [start]. @@ -1764,20 +1754,6 @@ class LineMetrics { this.lineNumber, }); - @pragma('vm:entry-point') - // ignore: unused_element - LineMetrics._( - this.hardBreak, - this.ascent, - this.descent, - this.unscaledAscent, - this.height, - this.width, - this.left, - this.baseline, - this.lineNumber, - ); - /// True if this line ends with an explicit line break (e.g. '\n') or is the end /// of the paragraph. False otherwise. final bool hardBreak; @@ -1914,6 +1890,20 @@ class Paragraph extends NativeFieldWrapperClass2 { void layout(ParagraphConstraints constraints) => _layout(constraints.width); void _layout(double width) native 'Paragraph_layout'; + List _decodeTextBoxes(Float32List encoded) { + final List boxes = List(encoded[0].toInt()); + for (int index = 0; index < boxes.length; index += 1) { + final int position = (index * 5) + 1; + boxes[index] = TextBox.fromLTRBD( + encoded[position + 0], + encoded[position + 1], + encoded[position + 2], + encoded[position + 3], + TextDirection.values[encoded[position + 4].toInt()], + ); + } + return boxes; + } /// Returns a list of text boxes that enclose the given text range. /// /// The [boxHeightStyle] and [boxWidthStyle] parameters allow customization @@ -1930,9 +1920,10 @@ class Paragraph extends NativeFieldWrapperClass2 { List getBoxesForRange(int start, int end, {BoxHeightStyle boxHeightStyle = BoxHeightStyle.tight, BoxWidthStyle boxWidthStyle = BoxWidthStyle.tight}) { assert(boxHeightStyle != null); assert(boxWidthStyle != null); - return _getBoxesForRange(start, end, boxHeightStyle.index, boxWidthStyle.index); + return _decodeTextBoxes(_getBoxesForRange(start, end, boxHeightStyle.index, boxWidthStyle.index)); } - List _getBoxesForRange(int start, int end, int boxHeightStyle, int boxWidthStyle) native 'Paragraph_getRectsForRange'; + // See paragraph.cc for the layout of this return value. + Float32List _getBoxesForRange(int start, int end, int boxHeightStyle, int boxWidthStyle) native 'Paragraph_getRectsForRange'; /// Returns a list of text boxes that enclose all placeholders in the paragraph. /// @@ -1940,7 +1931,10 @@ class Paragraph extends NativeFieldWrapperClass2 { /// /// Coordinates of the [TextBox] are relative to the upper-left corner of the paragraph, /// where positive y values indicate down. - List getBoxesForPlaceholders() native 'Paragraph_getRectsForPlaceholders'; + List getBoxesForPlaceholders() { + return _decodeTextBoxes(_getBoxesForPlaceholders()); + } + Float32List _getBoxesForPlaceholders() native 'Paragraph_getRectsForPlaceholders'; /// Returns the text position closest to the given offset. TextPosition getPositionForOffset(Offset offset) { @@ -1987,7 +1981,26 @@ class Paragraph extends NativeFieldWrapperClass2 { /// /// This can potentially return a large amount of data, so it is not recommended /// to repeatedly call this. Instead, cache the results. - List computeLineMetrics() native 'Paragraph_computeLineMetrics'; + List computeLineMetrics() { + final Float64List encoded = _computeLineMetrics(); + final List metrics = List(encoded[0].toInt()); + for (int index = 0; index < metrics.length; index += 1) { + final int position = (index * 5) + 1; + metrics[index] = LineMetrics( + hardBreak: encoded[position + 0] != 0, + ascent: encoded[position + 1], + descent: encoded[position + 2], + unscaledAscent: encoded[position + 3], + height: encoded[position + 4], + width: encoded[position + 5], + left: encoded[position + 6], + baseline: encoded[position + 7], + lineNumber: encoded[position + 8].toInt(), + ); + } + return metrics; + } + Float64List _computeLineMetrics() native 'Paragraph_computeLineMetrics'; } /// Builds a [Paragraph] containing text with the given styling information. @@ -2195,7 +2208,12 @@ class ParagraphBuilder extends NativeFieldWrapperClass2 { /// /// After calling this function, the paragraph builder object is invalid and /// cannot be used further. - Paragraph build() native 'ParagraphBuilder_build'; + Paragraph build() { + final Paragraph paragraph = Paragraph._(); + _build(paragraph); + return paragraph; + } + void _build(Paragraph outParagraph) native 'ParagraphBuilder_build'; } /// Loads a font from a buffer and makes it available for rendering text. diff --git a/lib/ui/text/line_metrics.cc b/lib/ui/text/line_metrics.cc deleted file mode 100644 index a224e9b29b66c..0000000000000 --- a/lib/ui/text/line_metrics.cc +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/lib/ui/text/line_metrics.h" - -#include "flutter/fml/logging.h" -#include "third_party/tonic/dart_class_library.h" -#include "third_party/tonic/dart_state.h" -#include "third_party/tonic/logging/dart_error.h" - -using namespace flutter; - -namespace tonic { - -namespace { - -Dart_Handle GetLineMetricsType() { - DartClassLibrary& class_library = DartState::Current()->class_library(); - Dart_Handle type = - Dart_HandleFromPersistent(class_library.GetClass("ui", "LineMetrics")); - FML_DCHECK(!LogIfError(type)); - return type; -} - -} // anonymous namespace - -Dart_Handle DartConverter::ToDart( - const flutter::LineMetrics& val) { - constexpr int argc = 9; - - Dart_Handle argv[argc] = { - tonic::ToDart(*val.hard_break), tonic::ToDart(*val.ascent), - tonic::ToDart(*val.descent), tonic::ToDart(*val.unscaled_ascent), - // We add then round to get the height. The - // definition of height here is different - // than the one in LibTxt. - tonic::ToDart(round(*val.ascent + *val.descent)), - tonic::ToDart(*val.width), tonic::ToDart(*val.left), - tonic::ToDart(*val.baseline), tonic::ToDart(*val.line_number)}; - return Dart_New(GetLineMetricsType(), tonic::ToDart("_"), argc, argv); -} - -Dart_Handle DartListFactory::NewList(intptr_t length) { - return Dart_NewListOfType(GetLineMetricsType(), length); -} - -} // namespace tonic diff --git a/lib/ui/text/line_metrics.h b/lib/ui/text/line_metrics.h index bcd53c3d276a9..f5f656cd816f9 100644 --- a/lib/ui/text/line_metrics.h +++ b/lib/ui/text/line_metrics.h @@ -59,17 +59,4 @@ struct LineMetrics { } // namespace flutter -namespace tonic { -template <> -struct DartConverter { - static Dart_Handle ToDart(const flutter::LineMetrics& val); -}; - -template <> -struct DartListFactory { - static Dart_Handle NewList(intptr_t length); -}; - -} // namespace tonic - #endif // FLUTTER_LIB_UI_TEXT_LINE_METRICS_H_ diff --git a/lib/ui/text/paragraph.cc b/lib/ui/text/paragraph.cc index 2618c3f08406a..2776dfd7629af 100644 --- a/lib/ui/text/paragraph.cc +++ b/lib/ui/text/paragraph.cc @@ -94,28 +94,40 @@ void Paragraph::paint(Canvas* canvas, double x, double y) { m_paragraph->Paint(sk_canvas, x, y); } -std::vector Paragraph::getRectsForRange(unsigned start, - unsigned end, - unsigned boxHeightStyle, - unsigned boxWidthStyle) { - std::vector result; +static tonic::Float32List EncodeTextBoxes(const std::vector& boxes) { + // Layout: + // First value is the number of values. + // Then there are boxes.size() groups of 5 which are LTRBD, where D is the + // text direction index. + auto count = boxes.size() * 5; + tonic::Float32List result(Dart_NewTypedData(Dart_TypedData_kFloat32, 1 + count)); + result[0] = count; + for (unsigned long i = 0; i < boxes.size(); i++) { + auto position = (i * 5) + 1; + const txt::Paragraph::TextBox& box = boxes[i]; + result[position + 0] = box.rect.fLeft; + result[position + 1] = box.rect.fTop; + result[position + 2] = box.rect.fRight; + result[position + 3] = box.rect.fBottom; + result[position + 4] = static_cast(box.direction); + } + return result; +} + +tonic::Float32List Paragraph::getRectsForRange(unsigned start, + unsigned end, + unsigned boxHeightStyle, + unsigned boxWidthStyle) { std::vector boxes = m_paragraph->GetRectsForRange( start, end, static_cast(boxHeightStyle), static_cast(boxWidthStyle)); - for (const txt::Paragraph::TextBox& box : boxes) { - result.emplace_back(box.rect, static_cast(box.direction)); - } - return result; + return EncodeTextBoxes(boxes); } -std::vector Paragraph::getRectsForPlaceholders() { - std::vector result; +tonic::Float32List Paragraph::getRectsForPlaceholders() { std::vector boxes = m_paragraph->GetRectsForPlaceholders(); - for (const txt::Paragraph::TextBox& box : boxes) { - result.emplace_back(box.rect, static_cast(box.direction)); - } - return result; + return EncodeTextBoxes(boxes); } Dart_Handle Paragraph::getPositionForOffset(double dx, double dy) { @@ -152,14 +164,33 @@ Dart_Handle Paragraph::getLineBoundary(unsigned offset) { return result; } -std::vector Paragraph::computeLineMetrics() { - std::vector result; +tonic::Float64List Paragraph::computeLineMetrics() { std::vector metrics = m_paragraph->GetLineMetrics(); - for (txt::LineMetrics& line : metrics) { - result.emplace_back(&line.hard_break, &line.ascent, &line.descent, - &line.unscaled_ascent, &line.height, &line.width, - &line.left, &line.baseline, &line.line_number); + + // Layout: + // First value is the number of values. + // Then there are boxes.size() groups of 9 which are the line metrics + // properties + auto count = metrics.size() * 9; + tonic::Float64List result(Dart_NewTypedData(Dart_TypedData_kFloat64, 1 + count)); + result[0] = count; + for (unsigned long i = 0; i < metrics.size(); i++) { + auto position = (i * 9) + 1; + const txt::LineMetrics& line = metrics[i]; + result[position + 0] = static_cast(line.hard_break); + result[position + 1] = line.ascent; + result[position + 2] = line.descent; + result[position + 3] = line.unscaled_ascent; + // We add then round to get the height. The + // definition of height here is different + // than the one in LibTxt. + result[position + 4] = round(line.ascent + line.descent); + result[position + 5] = line.width; + result[position + 6] = line.left; + result[position + 7] = line.baseline; + result[position + 8] = static_cast(line.line_number); } + return result; } diff --git a/lib/ui/text/paragraph.h b/lib/ui/text/paragraph.h index 7aea6079378e1..73c79d3c67de3 100644 --- a/lib/ui/text/paragraph.h +++ b/lib/ui/text/paragraph.h @@ -23,9 +23,10 @@ class Paragraph : public RefCountedDartWrappable { FML_FRIEND_MAKE_REF_COUNTED(Paragraph); public: - static fml::RefPtr Create( - std::unique_ptr paragraph) { - return fml::MakeRefCounted(std::move(paragraph)); + static void Create(Dart_Handle paragraph_handle, + std::unique_ptr txt_paragraph) { + auto paragraph = fml::MakeRefCounted(std::move(txt_paragraph)); + paragraph->AssociateWithDartWrapper(paragraph_handle); } ~Paragraph() override; @@ -42,15 +43,15 @@ class Paragraph : public RefCountedDartWrappable { void layout(double width); void paint(Canvas* canvas, double x, double y); - std::vector getRectsForRange(unsigned start, - unsigned end, - unsigned boxHeightStyle, - unsigned boxWidthStyle); - std::vector getRectsForPlaceholders(); + tonic::Float32List getRectsForRange(unsigned start, + unsigned end, + unsigned boxHeightStyle, + unsigned boxWidthStyle); + tonic::Float32List getRectsForPlaceholders(); Dart_Handle getPositionForOffset(double dx, double dy); Dart_Handle getWordBoundary(unsigned offset); Dart_Handle getLineBoundary(unsigned offset); - std::vector computeLineMetrics(); + tonic::Float64List computeLineMetrics(); size_t GetAllocationSize() override; diff --git a/lib/ui/text/paragraph_builder.cc b/lib/ui/text/paragraph_builder.cc index 51739fc2cf3fd..0b6eea6e0abfd 100644 --- a/lib/ui/text/paragraph_builder.cc +++ b/lib/ui/text/paragraph_builder.cc @@ -493,8 +493,8 @@ Dart_Handle ParagraphBuilder::addPlaceholder(double width, return Dart_Null(); } -fml::RefPtr ParagraphBuilder::build() { - return Paragraph::Create(m_paragraphBuilder->Build()); +void ParagraphBuilder::build(Dart_Handle paragraph_handle) { + Paragraph::Create(paragraph_handle, m_paragraphBuilder->Build()); } } // namespace flutter diff --git a/lib/ui/text/paragraph_builder.h b/lib/ui/text/paragraph_builder.h index eebc5e7f26868..4f4a00b5b94ab 100644 --- a/lib/ui/text/paragraph_builder.h +++ b/lib/ui/text/paragraph_builder.h @@ -69,7 +69,7 @@ class ParagraphBuilder : public RefCountedDartWrappable { double baseline_offset, unsigned baseline); - fml::RefPtr build(); + void build(Dart_Handle paragraph_handle); static void RegisterNatives(tonic::DartLibraryNatives* natives); diff --git a/lib/ui/text/text_box.cc b/lib/ui/text/text_box.cc deleted file mode 100644 index 99438cf4b87cb..0000000000000 --- a/lib/ui/text/text_box.cc +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/lib/ui/text/text_box.h" - -#include "flutter/fml/logging.h" -#include "third_party/tonic/dart_class_library.h" -#include "third_party/tonic/dart_state.h" -#include "third_party/tonic/logging/dart_error.h" - -using namespace flutter; - -namespace tonic { - -namespace { - -Dart_Handle GetTextBoxType() { - DartClassLibrary& class_library = DartState::Current()->class_library(); - Dart_Handle type = - Dart_HandleFromPersistent(class_library.GetClass("ui", "TextBox")); - FML_DCHECK(!LogIfError(type)); - return type; -} - -} // anonymous namespace - -Dart_Handle DartConverter::ToDart( - const flutter::TextBox& val) { - constexpr int argc = 5; - Dart_Handle argv[argc] = { - tonic::ToDart(val.rect.fLeft), - tonic::ToDart(val.rect.fTop), - tonic::ToDart(val.rect.fRight), - tonic::ToDart(val.rect.fBottom), - tonic::ToDart(static_cast(val.direction)), - }; - return Dart_New(GetTextBoxType(), tonic::ToDart("_"), argc, argv); -} - -Dart_Handle DartListFactory::NewList(intptr_t length) { - return Dart_NewListOfType(GetTextBoxType(), length); -} - -} // namespace tonic From 600ff75e3f75ef325b1c82bc11beb0788893dd56 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 27 Feb 2020 15:21:35 -0800 Subject: [PATCH 2/5] format --- lib/ui/text/paragraph.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/ui/text/paragraph.cc b/lib/ui/text/paragraph.cc index 2776dfd7629af..c40c810263e7e 100644 --- a/lib/ui/text/paragraph.cc +++ b/lib/ui/text/paragraph.cc @@ -94,13 +94,15 @@ void Paragraph::paint(Canvas* canvas, double x, double y) { m_paragraph->Paint(sk_canvas, x, y); } -static tonic::Float32List EncodeTextBoxes(const std::vector& boxes) { +static tonic::Float32List EncodeTextBoxes( + const std::vector& boxes) { // Layout: // First value is the number of values. // Then there are boxes.size() groups of 5 which are LTRBD, where D is the // text direction index. auto count = boxes.size() * 5; - tonic::Float32List result(Dart_NewTypedData(Dart_TypedData_kFloat32, 1 + count)); + tonic::Float32List result( + Dart_NewTypedData(Dart_TypedData_kFloat32, 1 + count)); result[0] = count; for (unsigned long i = 0; i < boxes.size(); i++) { auto position = (i * 5) + 1; @@ -172,7 +174,8 @@ tonic::Float64List Paragraph::computeLineMetrics() { // Then there are boxes.size() groups of 9 which are the line metrics // properties auto count = metrics.size() * 9; - tonic::Float64List result(Dart_NewTypedData(Dart_TypedData_kFloat64, 1 + count)); + tonic::Float64List result( + Dart_NewTypedData(Dart_TypedData_kFloat64, 1 + count)); result[0] = count; for (unsigned long i = 0; i < metrics.size(); i++) { auto position = (i * 9) + 1; From 33cc2e53b7376aa5e9eb8b1baa2ae63fb1030422 Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 27 Feb 2020 17:45:50 -0800 Subject: [PATCH 3/5] review, fixes, tests --- lib/ui/text.dart | 73 ++++++++++++++++++------ lib/ui/text/paragraph.cc | 43 ++++++-------- testing/dart/paragraph_builder_test.dart | 40 +++++++++++++ 3 files changed, 113 insertions(+), 43 deletions(-) diff --git a/lib/ui/text.dart b/lib/ui/text.dart index f33ffbcc3762c..01b4b8c754beb 100644 --- a/lib/ui/text.dart +++ b/lib/ui/text.dart @@ -1819,6 +1819,39 @@ class LineMetrics { /// /// For example, the first line is line 0, second line is line 1. final int lineNumber; + + @override + bool operator ==(Object other) { + if (other.runtimeType != runtimeType) { + return false; + } + return other is LineMetrics + && other.hardBreak == hardBreak + && other.ascent == ascent + && other.descent == descent + && other.unscaledAscent == unscaledAscent + && other.height == height + && other.width == width + && other.left == left + && other.baseline == baseline + && other.lineNumber == lineNumber; + } + + @override + int get hashCode => hashValues(hardBreak, ascent, descent, unscaledAscent, height, width, left, baseline, lineNumber); + + @override + String toString() { + return 'LineMetrics(hardBreak: $hardBreak, ' + 'ascent: $ascent, ' + 'descent: $descent, ' + 'unscaledAscent: $unscaledAscent, ' + 'height: $height, ' + 'width: $width, ' + 'left: $left, ' + 'baseline: $baseline, ' + 'lineNumber: $lineNumber)'; + } } /// A paragraph of text. @@ -1891,15 +1924,16 @@ class Paragraph extends NativeFieldWrapperClass2 { void _layout(double width) native 'Paragraph_layout'; List _decodeTextBoxes(Float32List encoded) { - final List boxes = List(encoded[0].toInt()); - for (int index = 0; index < boxes.length; index += 1) { - final int position = (index * 5) + 1; + final int count = encoded.length ~/ 5; + final List boxes = List(count); + int position = 0; + for (int index = 0; index < count; index += 1) { boxes[index] = TextBox.fromLTRBD( - encoded[position + 0], - encoded[position + 1], - encoded[position + 2], - encoded[position + 3], - TextDirection.values[encoded[position + 4].toInt()], + encoded[position++], + encoded[position++], + encoded[position++], + encoded[position++], + TextDirection.values[encoded[position++].toInt()], ); } return boxes; @@ -1983,19 +2017,20 @@ class Paragraph extends NativeFieldWrapperClass2 { /// to repeatedly call this. Instead, cache the results. List computeLineMetrics() { final Float64List encoded = _computeLineMetrics(); - final List metrics = List(encoded[0].toInt()); + final int count = encoded.length ~/ 9; + int position = 0; + final List metrics = List(count); for (int index = 0; index < metrics.length; index += 1) { - final int position = (index * 5) + 1; metrics[index] = LineMetrics( - hardBreak: encoded[position + 0] != 0, - ascent: encoded[position + 1], - descent: encoded[position + 2], - unscaledAscent: encoded[position + 3], - height: encoded[position + 4], - width: encoded[position + 5], - left: encoded[position + 6], - baseline: encoded[position + 7], - lineNumber: encoded[position + 8].toInt(), + hardBreak: encoded[position++] != 0, + ascent: encoded[position++], + descent: encoded[position++], + unscaledAscent: encoded[position++], + height: encoded[position++], + width: encoded[position++], + left: encoded[position++], + baseline: encoded[position++], + lineNumber: encoded[position++].toInt(), ); } return metrics; diff --git a/lib/ui/text/paragraph.cc b/lib/ui/text/paragraph.cc index c40c810263e7e..92800db2ebd67 100644 --- a/lib/ui/text/paragraph.cc +++ b/lib/ui/text/paragraph.cc @@ -100,18 +100,16 @@ static tonic::Float32List EncodeTextBoxes( // First value is the number of values. // Then there are boxes.size() groups of 5 which are LTRBD, where D is the // text direction index. - auto count = boxes.size() * 5; tonic::Float32List result( - Dart_NewTypedData(Dart_TypedData_kFloat32, 1 + count)); - result[0] = count; + Dart_NewTypedData(Dart_TypedData_kFloat32, boxes.size() * 5)); + unsigned long position = 0; for (unsigned long i = 0; i < boxes.size(); i++) { - auto position = (i * 5) + 1; const txt::Paragraph::TextBox& box = boxes[i]; - result[position + 0] = box.rect.fLeft; - result[position + 1] = box.rect.fTop; - result[position + 2] = box.rect.fRight; - result[position + 3] = box.rect.fBottom; - result[position + 4] = static_cast(box.direction); + result[position++] = box.rect.fLeft; + result[position++] = box.rect.fTop; + result[position++] = box.rect.fRight; + result[position++] = box.rect.fBottom; + result[position++] = static_cast(box.direction); } return result; } @@ -170,28 +168,25 @@ tonic::Float64List Paragraph::computeLineMetrics() { std::vector metrics = m_paragraph->GetLineMetrics(); // Layout: - // First value is the number of values. - // Then there are boxes.size() groups of 9 which are the line metrics + // boxes.size() groups of 9 which are the line metrics // properties - auto count = metrics.size() * 9; tonic::Float64List result( - Dart_NewTypedData(Dart_TypedData_kFloat64, 1 + count)); - result[0] = count; + Dart_NewTypedData(Dart_TypedData_kFloat64, metrics.size() * 9)); + unsigned long position = 0; for (unsigned long i = 0; i < metrics.size(); i++) { - auto position = (i * 9) + 1; const txt::LineMetrics& line = metrics[i]; - result[position + 0] = static_cast(line.hard_break); - result[position + 1] = line.ascent; - result[position + 2] = line.descent; - result[position + 3] = line.unscaled_ascent; + result[position++] = static_cast(line.hard_break); + result[position++] = line.ascent; + result[position++] = line.descent; + result[position++] = line.unscaled_ascent; // We add then round to get the height. The // definition of height here is different // than the one in LibTxt. - result[position + 4] = round(line.ascent + line.descent); - result[position + 5] = line.width; - result[position + 6] = line.left; - result[position + 7] = line.baseline; - result[position + 8] = static_cast(line.line_number); + result[position++] = round(line.ascent + line.descent); + result[position++] = line.width; + result[position++] = line.left; + result[position++] = line.baseline; + result[position++] = static_cast(line.line_number); } return result; diff --git a/testing/dart/paragraph_builder_test.dart b/testing/dart/paragraph_builder_test.dart index 81862dd9772bd..8cabfce9bf566 100644 --- a/testing/dart/paragraph_builder_test.dart +++ b/testing/dart/paragraph_builder_test.dart @@ -25,4 +25,44 @@ void main() { paragraphBuilder.build(); paragraphBuilder.pushStyle(TextStyle()); }); + + test('GetRectsForRange smoke test', () { + final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle()); + builder.addText('Hello'); + final Paragraph paragraph = builder.build(); + expect(paragraph, isNotNull); + + paragraph.layout(const ParagraphConstraints(width: 800.0)); + expect(paragraph.width, isNonZero); + expect(paragraph.height, isNonZero); + + final List boxes = paragraph.getBoxesForRange(0, 3); + expect(boxes.length, 1); + expect(boxes.first, const TextBox.fromLTRBD(0, 0, 42, 14, TextDirection.ltr)); + }); + + test('LineMetrics smoke test', () { + final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle()); + builder.addText('Hello'); + final Paragraph paragraph = builder.build(); + expect(paragraph, isNotNull); + + paragraph.layout(const ParagraphConstraints(width: 800.0)); + expect(paragraph.width, isNonZero); + expect(paragraph.height, isNonZero); + + final List metrics = paragraph.computeLineMetrics(); + expect(metrics.length, 1); + // The actual values here will vary by platform slightly. + const double epsillon = 0.00001; + expect(metrics.first.hardBreak, true); + expect(metrics.first.ascent, closeTo(11.200042724609375, epsillon)); + expect(metrics.first.descent, closeTo(2.799957275390625, epsillon)); + expect(metrics.first.unscaledAscent, closeTo(11.200042724609375, epsillon)); + expect(metrics.first.height, 14.0); + expect(metrics.first.width, 70.0); + expect(metrics.first.left, 0.0); + expect(metrics.first.baseline, closeTo(11.200042724609375, epsillon)); + expect(metrics.first.lineNumber, 0); + }); } From cbd75686c6acff6682f9b856e33a882ca1db5dcc Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 27 Feb 2020 21:19:16 -0800 Subject: [PATCH 4/5] more permissive test --- testing/dart/paragraph_builder_test.dart | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/testing/dart/paragraph_builder_test.dart b/testing/dart/paragraph_builder_test.dart index 8cabfce9bf566..2ec44109fe878 100644 --- a/testing/dart/paragraph_builder_test.dart +++ b/testing/dart/paragraph_builder_test.dart @@ -8,6 +8,9 @@ import 'dart:ui'; import 'package:test/test.dart'; void main() { + // The actual values for font measurements will vary by platform slightly. + const double epsillon = 0.0001; + test('Should be able to build and layout a paragraph', () { final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle()); builder.addText('Hello'); @@ -38,7 +41,11 @@ void main() { final List boxes = paragraph.getBoxesForRange(0, 3); expect(boxes.length, 1); - expect(boxes.first, const TextBox.fromLTRBD(0, 0, 42, 14, TextDirection.ltr)); + expect(boxes.first.left, 0); + expect(boxes.first.top, 0); + expect(boxes.first.right, closeTo(42, epsillon)); + expect(boxes.first.bottom, closeTo(14, epsillon)); + expect(boxes.first.direction, TextDirection.ltr); }); test('LineMetrics smoke test', () { @@ -53,8 +60,6 @@ void main() { final List metrics = paragraph.computeLineMetrics(); expect(metrics.length, 1); - // The actual values here will vary by platform slightly. - const double epsillon = 0.00001; expect(metrics.first.hardBreak, true); expect(metrics.first.ascent, closeTo(11.200042724609375, epsillon)); expect(metrics.first.descent, closeTo(2.799957275390625, epsillon)); From b648364b619bccb2bdf328473afa32517f4032ef Mon Sep 17 00:00:00 2001 From: Dan Field Date: Thu, 27 Feb 2020 23:20:45 -0800 Subject: [PATCH 5/5] epsillon for top --- testing/dart/paragraph_builder_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/dart/paragraph_builder_test.dart b/testing/dart/paragraph_builder_test.dart index 2ec44109fe878..cf8ccce0bf8b1 100644 --- a/testing/dart/paragraph_builder_test.dart +++ b/testing/dart/paragraph_builder_test.dart @@ -42,7 +42,7 @@ void main() { final List boxes = paragraph.getBoxesForRange(0, 3); expect(boxes.length, 1); expect(boxes.first.left, 0); - expect(boxes.first.top, 0); + expect(boxes.first.top, closeTo(0, epsillon)); expect(boxes.first.right, closeTo(42, epsillon)); expect(boxes.first.bottom, closeTo(14, epsillon)); expect(boxes.first.direction, TextDirection.ltr);