mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
remove usage of Dart_New for paragraph/libtxt (flutter/engine#16837)
This commit is contained in:
parent
5ad713ed0d
commit
81efbea9a8
@ -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
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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;
|
||||
@ -1843,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.
|
||||
@ -1914,6 +1923,21 @@ class Paragraph extends NativeFieldWrapperClass2 {
|
||||
void layout(ParagraphConstraints constraints) => _layout(constraints.width);
|
||||
void _layout(double width) native 'Paragraph_layout';
|
||||
|
||||
List<TextBox> _decodeTextBoxes(Float32List encoded) {
|
||||
final int count = encoded.length ~/ 5;
|
||||
final List<TextBox> boxes = List<TextBox>(count);
|
||||
int position = 0;
|
||||
for (int index = 0; index < count; index += 1) {
|
||||
boxes[index] = TextBox.fromLTRBD(
|
||||
encoded[position++],
|
||||
encoded[position++],
|
||||
encoded[position++],
|
||||
encoded[position++],
|
||||
TextDirection.values[encoded[position++].toInt()],
|
||||
);
|
||||
}
|
||||
return boxes;
|
||||
}
|
||||
/// Returns a list of text boxes that enclose the given text range.
|
||||
///
|
||||
/// The [boxHeightStyle] and [boxWidthStyle] parameters allow customization
|
||||
@ -1930,9 +1954,10 @@ class Paragraph extends NativeFieldWrapperClass2 {
|
||||
List<TextBox> 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<TextBox> _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 +1965,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<TextBox> getBoxesForPlaceholders() native 'Paragraph_getRectsForPlaceholders';
|
||||
List<TextBox> getBoxesForPlaceholders() {
|
||||
return _decodeTextBoxes(_getBoxesForPlaceholders());
|
||||
}
|
||||
Float32List _getBoxesForPlaceholders() native 'Paragraph_getRectsForPlaceholders';
|
||||
|
||||
/// Returns the text position closest to the given offset.
|
||||
TextPosition getPositionForOffset(Offset offset) {
|
||||
@ -1987,7 +2015,27 @@ 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<LineMetrics> computeLineMetrics() native 'Paragraph_computeLineMetrics';
|
||||
List<LineMetrics> computeLineMetrics() {
|
||||
final Float64List encoded = _computeLineMetrics();
|
||||
final int count = encoded.length ~/ 9;
|
||||
int position = 0;
|
||||
final List<LineMetrics> metrics = List<LineMetrics>(count);
|
||||
for (int index = 0; index < metrics.length; index += 1) {
|
||||
metrics[index] = LineMetrics(
|
||||
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;
|
||||
}
|
||||
Float64List _computeLineMetrics() native 'Paragraph_computeLineMetrics';
|
||||
}
|
||||
|
||||
/// Builds a [Paragraph] containing text with the given styling information.
|
||||
@ -2195,7 +2243,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.
|
||||
|
||||
@ -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<flutter::LineMetrics>::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<flutter::LineMetrics>::NewList(intptr_t length) {
|
||||
return Dart_NewListOfType(GetLineMetricsType(), length);
|
||||
}
|
||||
|
||||
} // namespace tonic
|
||||
@ -59,17 +59,4 @@ struct LineMetrics {
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
namespace tonic {
|
||||
template <>
|
||||
struct DartConverter<flutter::LineMetrics> {
|
||||
static Dart_Handle ToDart(const flutter::LineMetrics& val);
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DartListFactory<flutter::LineMetrics> {
|
||||
static Dart_Handle NewList(intptr_t length);
|
||||
};
|
||||
|
||||
} // namespace tonic
|
||||
|
||||
#endif // FLUTTER_LIB_UI_TEXT_LINE_METRICS_H_
|
||||
|
||||
@ -94,28 +94,40 @@ void Paragraph::paint(Canvas* canvas, double x, double y) {
|
||||
m_paragraph->Paint(sk_canvas, x, y);
|
||||
}
|
||||
|
||||
std::vector<TextBox> Paragraph::getRectsForRange(unsigned start,
|
||||
unsigned end,
|
||||
unsigned boxHeightStyle,
|
||||
unsigned boxWidthStyle) {
|
||||
std::vector<TextBox> result;
|
||||
std::vector<txt::Paragraph::TextBox> boxes = m_paragraph->GetRectsForRange(
|
||||
start, end, static_cast<txt::Paragraph::RectHeightStyle>(boxHeightStyle),
|
||||
static_cast<txt::Paragraph::RectWidthStyle>(boxWidthStyle));
|
||||
for (const txt::Paragraph::TextBox& box : boxes) {
|
||||
result.emplace_back(box.rect, static_cast<TextDirection>(box.direction));
|
||||
static tonic::Float32List EncodeTextBoxes(
|
||||
const std::vector<txt::Paragraph::TextBox>& 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.
|
||||
tonic::Float32List result(
|
||||
Dart_NewTypedData(Dart_TypedData_kFloat32, boxes.size() * 5));
|
||||
unsigned long position = 0;
|
||||
for (unsigned long i = 0; i < boxes.size(); i++) {
|
||||
const txt::Paragraph::TextBox& box = boxes[i];
|
||||
result[position++] = box.rect.fLeft;
|
||||
result[position++] = box.rect.fTop;
|
||||
result[position++] = box.rect.fRight;
|
||||
result[position++] = box.rect.fBottom;
|
||||
result[position++] = static_cast<float>(box.direction);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<TextBox> Paragraph::getRectsForPlaceholders() {
|
||||
std::vector<TextBox> result;
|
||||
tonic::Float32List Paragraph::getRectsForRange(unsigned start,
|
||||
unsigned end,
|
||||
unsigned boxHeightStyle,
|
||||
unsigned boxWidthStyle) {
|
||||
std::vector<txt::Paragraph::TextBox> boxes = m_paragraph->GetRectsForRange(
|
||||
start, end, static_cast<txt::Paragraph::RectHeightStyle>(boxHeightStyle),
|
||||
static_cast<txt::Paragraph::RectWidthStyle>(boxWidthStyle));
|
||||
return EncodeTextBoxes(boxes);
|
||||
}
|
||||
|
||||
tonic::Float32List Paragraph::getRectsForPlaceholders() {
|
||||
std::vector<txt::Paragraph::TextBox> boxes =
|
||||
m_paragraph->GetRectsForPlaceholders();
|
||||
for (const txt::Paragraph::TextBox& box : boxes) {
|
||||
result.emplace_back(box.rect, static_cast<TextDirection>(box.direction));
|
||||
}
|
||||
return result;
|
||||
return EncodeTextBoxes(boxes);
|
||||
}
|
||||
|
||||
Dart_Handle Paragraph::getPositionForOffset(double dx, double dy) {
|
||||
@ -152,14 +164,31 @@ Dart_Handle Paragraph::getLineBoundary(unsigned offset) {
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<LineMetrics> Paragraph::computeLineMetrics() {
|
||||
std::vector<LineMetrics> result;
|
||||
tonic::Float64List Paragraph::computeLineMetrics() {
|
||||
std::vector<txt::LineMetrics> 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:
|
||||
// boxes.size() groups of 9 which are the line metrics
|
||||
// properties
|
||||
tonic::Float64List result(
|
||||
Dart_NewTypedData(Dart_TypedData_kFloat64, metrics.size() * 9));
|
||||
unsigned long position = 0;
|
||||
for (unsigned long i = 0; i < metrics.size(); i++) {
|
||||
const txt::LineMetrics& line = metrics[i];
|
||||
result[position++] = static_cast<double>(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++] = round(line.ascent + line.descent);
|
||||
result[position++] = line.width;
|
||||
result[position++] = line.left;
|
||||
result[position++] = line.baseline;
|
||||
result[position++] = static_cast<double>(line.line_number);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@ -23,9 +23,10 @@ class Paragraph : public RefCountedDartWrappable<Paragraph> {
|
||||
FML_FRIEND_MAKE_REF_COUNTED(Paragraph);
|
||||
|
||||
public:
|
||||
static fml::RefPtr<Paragraph> Create(
|
||||
std::unique_ptr<txt::Paragraph> paragraph) {
|
||||
return fml::MakeRefCounted<Paragraph>(std::move(paragraph));
|
||||
static void Create(Dart_Handle paragraph_handle,
|
||||
std::unique_ptr<txt::Paragraph> txt_paragraph) {
|
||||
auto paragraph = fml::MakeRefCounted<Paragraph>(std::move(txt_paragraph));
|
||||
paragraph->AssociateWithDartWrapper(paragraph_handle);
|
||||
}
|
||||
|
||||
~Paragraph() override;
|
||||
@ -42,15 +43,15 @@ class Paragraph : public RefCountedDartWrappable<Paragraph> {
|
||||
void layout(double width);
|
||||
void paint(Canvas* canvas, double x, double y);
|
||||
|
||||
std::vector<TextBox> getRectsForRange(unsigned start,
|
||||
unsigned end,
|
||||
unsigned boxHeightStyle,
|
||||
unsigned boxWidthStyle);
|
||||
std::vector<TextBox> 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<LineMetrics> computeLineMetrics();
|
||||
tonic::Float64List computeLineMetrics();
|
||||
|
||||
size_t GetAllocationSize() override;
|
||||
|
||||
|
||||
@ -493,8 +493,8 @@ Dart_Handle ParagraphBuilder::addPlaceholder(double width,
|
||||
return Dart_Null();
|
||||
}
|
||||
|
||||
fml::RefPtr<Paragraph> ParagraphBuilder::build() {
|
||||
return Paragraph::Create(m_paragraphBuilder->Build());
|
||||
void ParagraphBuilder::build(Dart_Handle paragraph_handle) {
|
||||
Paragraph::Create(paragraph_handle, m_paragraphBuilder->Build());
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -69,7 +69,7 @@ class ParagraphBuilder : public RefCountedDartWrappable<ParagraphBuilder> {
|
||||
double baseline_offset,
|
||||
unsigned baseline);
|
||||
|
||||
fml::RefPtr<Paragraph> build();
|
||||
void build(Dart_Handle paragraph_handle);
|
||||
|
||||
static void RegisterNatives(tonic::DartLibraryNatives* natives);
|
||||
|
||||
|
||||
@ -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<flutter::TextBox>::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<int>(val.direction)),
|
||||
};
|
||||
return Dart_New(GetTextBoxType(), tonic::ToDart("_"), argc, argv);
|
||||
}
|
||||
|
||||
Dart_Handle DartListFactory<flutter::TextBox>::NewList(intptr_t length) {
|
||||
return Dart_NewListOfType(GetTextBoxType(), length);
|
||||
}
|
||||
|
||||
} // namespace tonic
|
||||
@ -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');
|
||||
@ -25,4 +28,46 @@ 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<TextBox> boxes = paragraph.getBoxesForRange(0, 3);
|
||||
expect(boxes.length, 1);
|
||||
expect(boxes.first.left, 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);
|
||||
});
|
||||
|
||||
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<LineMetrics> metrics = paragraph.computeLineMetrics();
|
||||
expect(metrics.length, 1);
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user