David PHAM-VAN

RTL Fixes and changelog

... ... @@ -4,6 +4,7 @@
- Improve TTF writer with multi-compound characters
- Partially revert underline on spans changes
- Add RTL support [Milad-Akarie]
## 3.10.4
... ...
... ... @@ -22,7 +22,8 @@ import 'point.dart';
class PdfRect {
const PdfRect(this.x, this.y, this.width, this.height);
factory PdfRect.fromLTRB(double left, double top, double right, double bottom) {
factory PdfRect.fromLTRB(
double left, double top, double right, double bottom) {
return PdfRect(left, top, right - left, bottom - top);
}
... ... @@ -70,7 +71,8 @@ class PdfRect {
/// Returns a new rectangle with edges moved outwards by the given delta.
PdfRect inflate(double delta) {
return PdfRect.fromLTRB(left - delta, top - delta, right + delta, bottom + delta);
return PdfRect.fromLTRB(
left - delta, top - delta, right + delta, bottom + delta);
}
/// Returns a new rectangle with edges moved inwards by the given delta.
... ...
... ... @@ -39,16 +39,22 @@ class LimitedBox extends SingleChildWidget {
BoxConstraints _limitConstraints(BoxConstraints constraints) {
return BoxConstraints(
minWidth: constraints.minWidth,
maxWidth: constraints.hasBoundedWidth ? constraints.maxWidth : constraints.constrainWidth(maxWidth),
maxWidth: constraints.hasBoundedWidth
? constraints.maxWidth
: constraints.constrainWidth(maxWidth),
minHeight: constraints.minHeight,
maxHeight: constraints.hasBoundedHeight ? constraints.maxHeight : constraints.constrainHeight(maxHeight));
maxHeight: constraints.hasBoundedHeight
? constraints.maxHeight
: constraints.constrainHeight(maxHeight));
}
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
PdfPoint size;
if (child != null) {
child!.layout(context, _limitConstraints(constraints), parentUsesSize: true);
child!.layout(context, _limitConstraints(constraints),
parentUsesSize: true);
assert(child!.box != null);
size = constraints.constrain(child!.box!.size);
} else {
... ... @@ -73,16 +79,19 @@ class Padding extends SingleChildWidget {
final EdgeInsetsGeometry padding;
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
final resolvedPadding = padding.resolve(Directionality.of(context));
if (child != null) {
final childConstraints = constraints.deflate(resolvedPadding);
child!.layout(context, childConstraints, parentUsesSize: parentUsesSize);
assert(child!.box != null);
box = constraints.constrainRect(
width: child!.box!.width + resolvedPadding.horizontal, height: child!.box!.height + resolvedPadding.vertical);
width: child!.box!.width + resolvedPadding.horizontal,
height: child!.box!.height + resolvedPadding.vertical);
} else {
box = constraints.constrainRect(width: resolvedPadding.horizontal, height: resolvedPadding.vertical);
box = constraints.constrainRect(
width: resolvedPadding.horizontal, height: resolvedPadding.vertical);
}
}
... ... @@ -97,8 +106,10 @@ class Padding extends SingleChildWidget {
..lineTo(box!.x, box!.top)
..moveTo(box!.x + resolvedPadding.left, box!.y + resolvedPadding.bottom)
..lineTo(box!.x + resolvedPadding.left, box!.top - resolvedPadding.top)
..lineTo(box!.right - resolvedPadding.right, box!.top - resolvedPadding.top)
..lineTo(box!.right - resolvedPadding.right, box!.y + resolvedPadding.bottom)
..lineTo(
box!.right - resolvedPadding.right, box!.top - resolvedPadding.top)
..lineTo(
box!.right - resolvedPadding.right, box!.y + resolvedPadding.bottom)
..fillPath();
}
... ... @@ -108,7 +119,8 @@ class Padding extends SingleChildWidget {
final resolvedPadding = padding.resolve(Directionality.of(context));
if (child != null) {
final mat = Matrix4.identity();
mat.translate(box!.x + resolvedPadding.left, box!.y + resolvedPadding.bottom);
mat.translate(
box!.x + resolvedPadding.left, box!.y + resolvedPadding.bottom);
context.canvas
..saveContext()
..setTransform(mat);
... ... @@ -210,7 +222,8 @@ class Transform extends SingleChildWidget {
}
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
if (!adjustLayout) {
return super.layout(context, constraints, parentUsesSize: parentUsesSize);
}
... ... @@ -239,14 +252,20 @@ class Transform extends SingleChildWidget {
0,
]);
final dx = -math.min(math.min(math.min(values[0], values[3]), values[6]), values[9]);
final dy = -math.min(math.min(math.min(values[1], values[4]), values[7]), values[10]);
final dx = -math.min(
math.min(math.min(values[0], values[3]), values[6]), values[9]);
final dy = -math.min(
math.min(math.min(values[1], values[4]), values[7]), values[10]);
box = PdfRect.fromLTRB(
0,
0,
math.max(math.max(math.max(values[0], values[3]), values[6]), values[9]) + dx,
math.max(math.max(math.max(values[1], values[4]), values[7]), values[10]) + dy,
math.max(math.max(math.max(values[0], values[3]), values[6]),
values[9]) +
dx,
math.max(math.max(math.max(values[1], values[4]), values[7]),
values[10]) +
dy,
);
transform.leftTranslate(dx, dy);
... ... @@ -273,7 +292,11 @@ class Transform extends SingleChildWidget {
/// A widget that aligns its child within itself and optionally sizes itself
/// based on the child's size.
class Align extends SingleChildWidget {
Align({this.alignment = Alignment.center, this.widthFactor, this.heightFactor, Widget? child})
Align(
{this.alignment = Alignment.center,
this.widthFactor,
this.heightFactor,
Widget? child})
: assert(widthFactor == null || widthFactor >= 0.0),
assert(heightFactor == null || heightFactor >= 0.0),
super(child: child);
... ... @@ -288,22 +311,30 @@ class Align extends SingleChildWidget {
final double? heightFactor;
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
final shrinkWrapWidth = widthFactor != null || constraints.maxWidth == double.infinity;
final shrinkWrapHeight = heightFactor != null || constraints.maxHeight == double.infinity;
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
final shrinkWrapWidth =
widthFactor != null || constraints.maxWidth == double.infinity;
final shrinkWrapHeight =
heightFactor != null || constraints.maxHeight == double.infinity;
if (child != null) {
child!.layout(context, constraints.loosen(), parentUsesSize: true);
assert(child!.box != null);
box = constraints.constrainRect(
width: shrinkWrapWidth ? child!.box!.width * (widthFactor ?? 1.0) : double.infinity,
height: shrinkWrapHeight ? child!.box!.height * (heightFactor ?? 1.0) : double.infinity);
width: shrinkWrapWidth
? child!.box!.width * (widthFactor ?? 1.0)
: double.infinity,
height: shrinkWrapHeight
? child!.box!.height * (heightFactor ?? 1.0)
: double.infinity);
final resolvedAlignment = alignment.resolve(Directionality.of(context));
child!.box = resolvedAlignment.inscribe(child!.box!.size, box!);
} else {
box = constraints.constrainRect(
width: shrinkWrapWidth ? 0.0 : double.infinity, height: shrinkWrapHeight ? 0.0 : double.infinity);
width: shrinkWrapWidth ? 0.0 : double.infinity,
height: shrinkWrapHeight ? 0.0 : double.infinity);
}
}
... ... @@ -326,40 +357,58 @@ class Align extends SingleChildWidget {
box!.left + child!.box!.horizontalCenter,
box!.bottom,
)
..lineTo(box!.left + child!.box!.horizontalCenter, box!.bottom + child!.box!.bottom)
..lineTo(box!.left + child!.box!.horizontalCenter - headSize, box!.bottom + child!.box!.bottom - headSize)
..moveTo(box!.left + child!.box!.horizontalCenter, box!.bottom + child!.box!.bottom)
..lineTo(box!.left + child!.box!.horizontalCenter + headSize, box!.bottom + child!.box!.bottom - headSize);
..lineTo(box!.left + child!.box!.horizontalCenter,
box!.bottom + child!.box!.bottom)
..lineTo(box!.left + child!.box!.horizontalCenter - headSize,
box!.bottom + child!.box!.bottom - headSize)
..moveTo(box!.left + child!.box!.horizontalCenter,
box!.bottom + child!.box!.bottom)
..lineTo(box!.left + child!.box!.horizontalCenter + headSize,
box!.bottom + child!.box!.bottom - headSize);
}
if (box!.bottom + child!.box!.top < box!.top) {
final headSize = math.min((box!.top - child!.box!.top - box!.bottom) * 0.2, 10);
final headSize =
math.min((box!.top - child!.box!.top - box!.bottom) * 0.2, 10);
context.canvas
..moveTo(box!.left + child!.box!.horizontalCenter, box!.top)
..lineTo(box!.left + child!.box!.horizontalCenter, box!.bottom + child!.box!.top)
..lineTo(box!.left + child!.box!.horizontalCenter - headSize, box!.bottom + child!.box!.top + headSize)
..moveTo(box!.left + child!.box!.horizontalCenter, box!.bottom + child!.box!.top)
..lineTo(box!.left + child!.box!.horizontalCenter + headSize, box!.bottom + child!.box!.top + headSize);
..lineTo(box!.left + child!.box!.horizontalCenter,
box!.bottom + child!.box!.top)
..lineTo(box!.left + child!.box!.horizontalCenter - headSize,
box!.bottom + child!.box!.top + headSize)
..moveTo(box!.left + child!.box!.horizontalCenter,
box!.bottom + child!.box!.top)
..lineTo(box!.left + child!.box!.horizontalCenter + headSize,
box!.bottom + child!.box!.top + headSize);
}
if (child!.box!.left > 0) {
final headSize = math.min(child!.box!.left * 0.2, 10);
context.canvas
..moveTo(box!.left, box!.bottom + child!.box!.verticalCenter)
..lineTo(box!.left + child!.box!.left, box!.bottom + child!.box!.verticalCenter)
..lineTo(box!.left + child!.box!.left - headSize, box!.bottom + child!.box!.verticalCenter - headSize)
..moveTo(box!.left + child!.box!.left, box!.bottom + child!.box!.verticalCenter)
..lineTo(box!.left + child!.box!.left - headSize, box!.bottom + child!.box!.verticalCenter + headSize);
..lineTo(box!.left + child!.box!.left,
box!.bottom + child!.box!.verticalCenter)
..lineTo(box!.left + child!.box!.left - headSize,
box!.bottom + child!.box!.verticalCenter - headSize)
..moveTo(box!.left + child!.box!.left,
box!.bottom + child!.box!.verticalCenter)
..lineTo(box!.left + child!.box!.left - headSize,
box!.bottom + child!.box!.verticalCenter + headSize);
}
if (box!.left + child!.box!.right < box!.right) {
final headSize = math.min((box!.right - child!.box!.right - box!.left) * 0.2, 10);
final headSize =
math.min((box!.right - child!.box!.right - box!.left) * 0.2, 10);
context.canvas
..moveTo(box!.right, box!.bottom + child!.box!.verticalCenter)
..lineTo(box!.left + child!.box!.right, box!.bottom + child!.box!.verticalCenter)
..lineTo(box!.left + child!.box!.right + headSize, box!.bottom + child!.box!.verticalCenter - headSize)
..moveTo(box!.left + child!.box!.right, box!.bottom + child!.box!.verticalCenter)
..lineTo(box!.left + child!.box!.right + headSize, box!.bottom + child!.box!.verticalCenter + headSize);
..lineTo(box!.left + child!.box!.right,
box!.bottom + child!.box!.verticalCenter)
..lineTo(box!.left + child!.box!.right + headSize,
box!.bottom + child!.box!.verticalCenter - headSize)
..moveTo(box!.left + child!.box!.right,
box!.bottom + child!.box!.verticalCenter)
..lineTo(box!.left + child!.box!.right + headSize,
box!.bottom + child!.box!.verticalCenter + headSize);
}
context.canvas.strokePath();
... ... @@ -374,19 +423,23 @@ class Align extends SingleChildWidget {
/// A widget that imposes additional constraints on its child.
class ConstrainedBox extends SingleChildWidget {
ConstrainedBox({required this.constraints, Widget? child}) : super(child: child);
ConstrainedBox({required this.constraints, Widget? child})
: super(child: child);
/// The additional constraints to impose on the child.
final BoxConstraints constraints;
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
if (child != null) {
child!.layout(context, this.constraints.enforce(constraints), parentUsesSize: true);
child!.layout(context, this.constraints.enforce(constraints),
parentUsesSize: true);
assert(child!.box != null);
box = child!.box;
} else {
box = PdfRect.fromPoints(PdfPoint.zero, this.constraints.enforce(constraints).smallest);
box = PdfRect.fromPoints(
PdfPoint.zero, this.constraints.enforce(constraints).smallest);
}
}
... ... @@ -399,7 +452,8 @@ class ConstrainedBox extends SingleChildWidget {
class Center extends Align {
Center({double? widthFactor, double? heightFactor, Widget? child})
: super(widthFactor: widthFactor, heightFactor: heightFactor, child: child);
: super(
widthFactor: widthFactor, heightFactor: heightFactor, child: child);
}
/// Scales and positions its child within itself according to [fit].
... ... @@ -417,12 +471,14 @@ class FittedBox extends SingleChildWidget {
final AlignmentGeometry alignment;
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
PdfPoint size;
if (child != null) {
child!.layout(context, const BoxConstraints(), parentUsesSize: true);
assert(child!.box != null);
size = constraints.constrainSizeAndAttemptToPreserveAspectRatio(child!.box!.size);
size = constraints
.constrainSizeAndAttemptToPreserveAspectRatio(child!.box!.size);
} else {
size = constraints.smallest;
}
... ... @@ -439,12 +495,15 @@ class FittedBox extends SingleChildWidget {
final sizes = applyBoxFit(fit, childSize, box!.size);
final scaleX = sizes.destination!.x / sizes.source!.x;
final scaleY = sizes.destination!.y / sizes.source!.y;
final sourceRect = resolvedAlignment.inscribe(sizes.source!, PdfRect.fromPoints(PdfPoint.zero, childSize));
final destinationRect = resolvedAlignment.inscribe(sizes.destination!, box!);
final sourceRect = resolvedAlignment.inscribe(
sizes.source!, PdfRect.fromPoints(PdfPoint.zero, childSize));
final destinationRect =
resolvedAlignment.inscribe(sizes.destination!, box!);
final mat = Matrix4.translationValues(destinationRect.x, destinationRect.y, 0)
..scale(scaleX, scaleY, 1)
..translate(-sourceRect.x, -sourceRect.y);
final mat =
Matrix4.translationValues(destinationRect.x, destinationRect.y, 0)
..scale(scaleX, scaleY, 1)
..translate(-sourceRect.x, -sourceRect.y);
context.canvas
..saveContext()
... ... @@ -502,10 +561,12 @@ class AspectRatio extends SingleChildWidget {
}
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
box = PdfRect.fromPoints(PdfPoint.zero, _applyAspectRatio(constraints));
if (child != null) {
child!.layout(context, BoxConstraints.tightFor(width: box!.width, height: box!.height));
child!.layout(context,
BoxConstraints.tightFor(width: box!.width, height: box!.height));
}
assert(child!.box != null);
}
... ... @@ -532,7 +593,8 @@ class CustomPaint extends SingleChildWidget {
final PdfPoint size;
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
if (child != null) {
child!.layout(context, constraints, parentUsesSize: parentUsesSize);
assert(child!.box != null);
... ... @@ -599,7 +661,9 @@ class SizedBox extends StatelessWidget {
@override
Widget build(Context context) {
return ConstrainedBox(child: child, constraints: BoxConstraints.tightFor(width: width, height: height));
return ConstrainedBox(
child: child,
constraints: BoxConstraints.tightFor(width: width, height: height));
}
}
... ... @@ -622,7 +686,8 @@ class Builder extends StatelessWidget {
}
/// The signature of the [LayoutBuilder] builder function.
typedef LayoutWidgetBuilder = Widget Function(Context context, BoxConstraints? constraints);
typedef LayoutWidgetBuilder = Widget Function(
Context context, BoxConstraints? constraints);
/// Builds a widget tree that can depend on the parent widget's size.
class LayoutBuilder extends StatelessWidget {
... ... @@ -637,7 +702,8 @@ class LayoutBuilder extends StatelessWidget {
BoxConstraints? _constraints;
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
_constraints = constraints;
super.layout(context, constraints);
}
... ... @@ -684,7 +750,8 @@ class FullPage extends SingleChildWidget {
}
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
final constraints = _getConstraints(context);
if (child != null) {
... ... @@ -904,11 +971,13 @@ class OverflowBox extends SingleChildWidget {
}
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
box = PdfRect.fromPoints(PdfPoint.zero, constraints.smallest);
if (child != null) {
child!.layout(context, _getInnerConstraints(constraints), parentUsesSize: true);
child!.layout(context, _getInnerConstraints(constraints),
parentUsesSize: true);
assert(child!.box != null);
final resolvedAlignment = alignment.resolve(Directionality.of(context));
child!.box = resolvedAlignment.inscribe(child!.box!.size, box!);
... ...
... ... @@ -85,7 +85,9 @@ abstract class BorderRadiusGeometry {
@override
String toString() {
String? visual, logical;
if (_topLeft == _topRight && _topRight == _bottomLeft && _bottomLeft == _bottomRight) {
if (_topLeft == _topRight &&
_topRight == _bottomLeft &&
_bottomLeft == _bottomRight) {
if (_topLeft != Radius.zero) {
if (_topLeft.x == _topLeft.y) {
visual = 'BorderRadius.circular(${_topLeft.x.toStringAsFixed(1)})';
... ... @@ -125,10 +127,13 @@ abstract class BorderRadiusGeometry {
result.write(')');
visual = result.toString();
}
if (_topStart == _topEnd && _topEnd == _bottomEnd && _bottomEnd == _bottomStart) {
if (_topStart == _topEnd &&
_topEnd == _bottomEnd &&
_bottomEnd == _bottomStart) {
if (_topStart != Radius.zero) {
if (_topStart.x == _topStart.y) {
logical = 'BorderRadiusDirectional.circular(${_topStart.x.toStringAsFixed(1)})';
logical =
'BorderRadiusDirectional.circular(${_topStart.x.toStringAsFixed(1)})';
} else {
logical = 'BorderRadiusDirectional.all($_topStart)';
}
... ... @@ -228,8 +233,6 @@ class BorderRadius extends BorderRadiusGeometry {
this.bottomRight = Radius.zero,
});
/// A border radius with all zero radii.
static const BorderRadius zero = BorderRadius.all(Radius.zero);
... ... @@ -245,14 +248,13 @@ class BorderRadius extends BorderRadiusGeometry {
/// The bottom-right [Radius].
final Radius bottomRight;
@override
bool get isUniform => topLeft == topRight && topLeft == bottomLeft && topLeft == bottomRight;
bool get isUniform =>
topLeft == topRight && topLeft == bottomLeft && topLeft == bottomRight;
@override
Radius get uniform => isUniform ? topLeft : Radius.zero;
void paint(Context context, PdfRect box) {
// Ellipse 4-spline magic number
const _m4 = 0.551784;
... ... @@ -261,13 +263,23 @@ class BorderRadius extends BorderRadiusGeometry {
// Start
..moveTo(box.x, box.y + bottomLeft.y)
// bottomLeft
..curveTo(box.x, box.y - _m4 * bottomLeft.y + bottomLeft.y, box.x - _m4 * bottomLeft.x + bottomLeft.x, box.y,
box.x + bottomLeft.x, box.y)
..curveTo(
box.x,
box.y - _m4 * bottomLeft.y + bottomLeft.y,
box.x - _m4 * bottomLeft.x + bottomLeft.x,
box.y,
box.x + bottomLeft.x,
box.y)
// bottom
..lineTo(box.x + box.width - bottomRight.x, box.y)
// bottomRight
..curveTo(box.x + _m4 * bottomRight.x + box.width - bottomRight.x, box.y, box.x + box.width,
box.y - _m4 * bottomRight.y + bottomRight.y, box.x + box.width, box.y + bottomRight.y)
..curveTo(
box.x + _m4 * bottomRight.x + box.width - bottomRight.x,
box.y,
box.x + box.width,
box.y - _m4 * bottomRight.y + bottomRight.y,
box.x + box.width,
box.y + bottomRight.y)
// right
..lineTo(box.x + box.width, box.y + box.height - topRight.y)
// topRight
... ... @@ -281,8 +293,13 @@ class BorderRadius extends BorderRadiusGeometry {
// top
..lineTo(box.x + topLeft.x, box.y + box.height)
// topLeft
..curveTo(box.x - _m4 * topLeft.x + topLeft.x, box.y + box.height, box.x,
box.y + _m4 * topLeft.y + box.height - topLeft.y, box.x, box.y + box.height - topLeft.y)
..curveTo(
box.x - _m4 * topLeft.x + topLeft.x,
box.y + box.height,
box.x,
box.y + _m4 * topLeft.y + box.height - topLeft.y,
box.x,
box.y + box.height - topLeft.y)
// left
..lineTo(box.x, box.y + bottomLeft.y);
}
... ... @@ -329,17 +346,19 @@ class BorderRadius extends BorderRadiusGeometry {
/// `topRight` instead of `topStart` and `topEnd`).
class BorderRadiusDirectional extends BorderRadiusGeometry {
/// Creates a border radius where all radii are [radius].
const BorderRadiusDirectional.all(Radius radius) : this.only(
topStart: radius,
topEnd: radius,
bottomStart: radius,
bottomEnd: radius,
);
const BorderRadiusDirectional.all(Radius radius)
: this.only(
topStart: radius,
topEnd: radius,
bottomStart: radius,
bottomEnd: radius,
);
/// Creates a border radius where all radii are [Radius.circular(radius)].
BorderRadiusDirectional.circular(double radius) : this.all(
Radius.circular(radius),
);
BorderRadiusDirectional.circular(double radius)
: this.all(
Radius.circular(radius),
);
/// Creates a vertically symmetric border radius where the top and bottom
/// sides of the rectangle have the same radii.
... ... @@ -347,11 +366,11 @@ class BorderRadiusDirectional extends BorderRadiusGeometry {
Radius top = Radius.zero,
Radius bottom = Radius.zero,
}) : this.only(
topStart: top,
topEnd: top,
bottomStart: bottom,
bottomEnd: bottom,
);
topStart: top,
topEnd: top,
bottomStart: bottom,
bottomEnd: bottom,
);
/// Creates a horizontally symmetrical border radius where the start and end
/// sides of the rectangle have the same radii.
... ... @@ -359,11 +378,11 @@ class BorderRadiusDirectional extends BorderRadiusGeometry {
Radius start = Radius.zero,
Radius end = Radius.zero,
}) : this.only(
topStart: start,
topEnd: end,
bottomStart: start,
bottomEnd: end,
);
topStart: start,
topEnd: end,
bottomStart: start,
bottomEnd: end,
);
/// Creates a border radius with only the given non-zero values. The other
/// corners will be right angles.
... ... @@ -378,7 +397,8 @@ class BorderRadiusDirectional extends BorderRadiusGeometry {
///
/// Consider using [BorderRadius.zero] instead, since that object has the same
/// effect, but will be cheaper to [resolve].
static const BorderRadiusDirectional zero = BorderRadiusDirectional.all(Radius.zero);
static const BorderRadiusDirectional zero =
BorderRadiusDirectional.all(Radius.zero);
/// The top-start [Radius].
final Radius topStart;
... ... @@ -417,7 +437,8 @@ class BorderRadiusDirectional extends BorderRadiusGeometry {
Radius get _bottomRight => Radius.zero;
@override
bool get isUniform => topStart == topEnd && topStart == bottomStart && topStart == bottomEnd;
bool get isUniform =>
topStart == topEnd && topStart == bottomStart && topStart == bottomEnd;
@override
Radius get uniform => isUniform ? topStart : Radius.zero;
... ... @@ -442,4 +463,4 @@ class BorderRadiusDirectional extends BorderRadiusGeometry {
);
}
}
}
\ No newline at end of file
}
... ...
... ... @@ -207,7 +207,7 @@ class RadialGradient extends Gradient {
final _focal = focal ?? center;
final _radius = math.min(box.width, box.height);
final textDirection = Directionality.of(context);
final textDirection = Directionality.of(context);
context.canvas
..saveContext()
..clipPath()
... ... @@ -277,7 +277,8 @@ class BoxDecoration {
PdfRect box, [
PaintPhase phase = PaintPhase.all,
]) {
final resolvedBorderRadius = borderRadius?.resolve(Directionality.of(context));
final resolvedBorderRadius =
borderRadius?.resolve(Directionality.of(context));
if (phase == PaintPhase.all || phase == PaintPhase.background) {
if (color != null) {
switch (shape) {
... ... @@ -363,7 +364,7 @@ class BoxDecoration {
break;
case BoxShape.rectangle:
if (resolvedBorderRadius!= null) {
if (resolvedBorderRadius != null) {
resolvedBorderRadius.paint(context, box);
context.canvas.clipPath();
}
... ...
... ... @@ -394,8 +394,9 @@ class Flex extends MultiChildWidget with SpanningWidget {
double? leadingSpace;
late double betweenSpace;
final textDirection = Directionality.of(context) ;
final flipMainAxis = !(_startIsTopLeft(direction, textDirection, verticalDirection) ?? true);
final textDirection = Directionality.of(context);
final flipMainAxis =
!(_startIsTopLeft(direction, textDirection, verticalDirection) ?? true);
switch (mainAxisAlignment) {
case MainAxisAlignment.start:
... ... @@ -436,8 +437,9 @@ class Flex extends MultiChildWidget with SpanningWidget {
switch (crossAxisAlignment) {
case CrossAxisAlignment.start:
case CrossAxisAlignment.end:
childCrossPosition = _startIsTopLeft(flipAxis(direction), textDirection, verticalDirection)
== (crossAxisAlignment == CrossAxisAlignment.start)
childCrossPosition = _startIsTopLeft(
flipAxis(direction), textDirection, verticalDirection) ==
(crossAxisAlignment == CrossAxisAlignment.start)
? 0.0
: crossSize - _getCrossSize(child);
break;
... ... @@ -479,7 +481,8 @@ class Flex extends MultiChildWidget with SpanningWidget {
}
}
bool? _startIsTopLeft(Axis direction, TextDirection? textDirection, VerticalDirection? verticalDirection) {
bool? _startIsTopLeft(Axis direction, TextDirection? textDirection,
VerticalDirection? verticalDirection) {
// If the relevant value of textDirection or verticalDirection is null, this returns null too.
switch (direction) {
case Axis.horizontal:
... ...
... ... @@ -26,7 +26,10 @@ import '../../widgets.dart';
class BoxConstraints {
/// Creates box constraints with the given constraints.
const BoxConstraints(
{this.minWidth = 0.0, this.maxWidth = double.infinity, this.minHeight = 0.0, this.maxHeight = double.infinity});
{this.minWidth = 0.0,
this.maxWidth = double.infinity,
this.minHeight = 0.0,
this.maxHeight = double.infinity});
/// Creates box constraints that require the given width or height.
const BoxConstraints.tightFor({double? width, double? height})
... ... @@ -101,7 +104,8 @@ class BoxConstraints {
return result;
}
PdfRect constrainRect({double width = double.infinity, double height = double.infinity}) {
PdfRect constrainRect(
{double width = double.infinity, double height = double.infinity}) {
final result = PdfPoint(constrainWidth(width), constrainHeight(height));
return PdfRect.fromPoints(PdfPoint.zero, result);
}
... ... @@ -158,8 +162,10 @@ class BoxConstraints {
return BoxConstraints(
minWidth: width == null ? minWidth : width.clamp(minWidth, maxWidth),
maxWidth: width == null ? maxWidth : width.clamp(minWidth, maxWidth),
minHeight: height == null ? minHeight : height.clamp(minHeight, maxHeight),
maxHeight: height == null ? maxHeight : height.clamp(minHeight, maxHeight));
minHeight:
height == null ? minHeight : height.clamp(minHeight, maxHeight),
maxHeight:
height == null ? maxHeight : height.clamp(minHeight, maxHeight));
}
/// Returns new box constraints that are smaller by the given edge dimensions.
... ... @@ -191,11 +197,17 @@ class BoxConstraints {
return BoxConstraints(
minWidth: minWidth.clamp(constraints.minWidth, constraints.maxWidth),
maxWidth: maxWidth.clamp(constraints.minWidth, constraints.maxWidth),
minHeight: minHeight.clamp(constraints.minHeight, constraints.maxHeight),
maxHeight: maxHeight.clamp(constraints.minHeight, constraints.maxHeight));
minHeight:
minHeight.clamp(constraints.minHeight, constraints.maxHeight),
maxHeight:
maxHeight.clamp(constraints.minHeight, constraints.maxHeight));
}
BoxConstraints copyWith({double? minWidth, double? maxWidth, double? minHeight, double? maxHeight}) {
BoxConstraints copyWith(
{double? minWidth,
double? maxWidth,
double? minHeight,
double? maxHeight}) {
return BoxConstraints(
minWidth: minWidth ?? this.minWidth,
maxWidth: maxWidth ?? this.maxWidth,
... ... @@ -308,7 +320,8 @@ class EdgeInsets extends EdgeInsetsGeometry {
right = value,
bottom = value;
const EdgeInsets.only({this.left = 0.0, this.top = 0.0, this.right = 0.0, this.bottom = 0.0});
const EdgeInsets.only(
{this.left = 0.0, this.top = 0.0, this.right = 0.0, this.bottom = 0.0});
const EdgeInsets.symmetric({double vertical = 0.0, double horizontal = 0.0})
: left = horizontal,
... ... @@ -385,7 +398,8 @@ class EdgeInsets extends EdgeInsetsGeometry {
}
class _MixedEdgeInsets extends EdgeInsetsGeometry {
const _MixedEdgeInsets.fromLRSETB(this._left, this._right, this._start, this._end, this._top, this._bottom);
const _MixedEdgeInsets.fromLRSETB(
this._left, this._right, this._start, this._end, this._top, this._bottom);
@override
final double _left;
... ... @@ -410,9 +424,11 @@ class _MixedEdgeInsets extends EdgeInsetsGeometry {
assert(direction != null);
switch (direction!) {
case TextDirection.rtl:
return EdgeInsets.fromLTRB(_end + _left, _top, _start + _right, _bottom);
return EdgeInsets.fromLTRB(
_end + _left, _top, _start + _right, _bottom);
case TextDirection.ltr:
return EdgeInsets.fromLTRB(_start + _left, _top, _end + _right, _bottom);
return EdgeInsets.fromLTRB(
_start + _left, _top, _end + _right, _bottom);
}
}
}
... ... @@ -430,7 +446,8 @@ class _MixedEdgeInsets extends EdgeInsetsGeometry {
/// of start and end).
class EdgeInsetsDirectional extends EdgeInsetsGeometry {
/// Creates insets from offsets from the start, top, end, and bottom.
const EdgeInsetsDirectional.fromSTEB(this.start, this.top, this.end, this.bottom);
const EdgeInsetsDirectional.fromSTEB(
this.start, this.top, this.end, this.bottom);
/// Creates insets with only the given values non-zero.
///
... ... @@ -580,7 +597,6 @@ abstract class AlignmentGeometry {
/// const constructors so that they can be used in const expressions.
const AlignmentGeometry();
/// Convert this instance into an [Alignment], which uses literal
/// coordinates (the `x` coordinate being explicitly a distance from the
/// left).
... ... @@ -591,7 +607,6 @@ abstract class AlignmentGeometry {
/// * [AlignmentDirectional], which flips the horizontal direction
/// based on the `direction` argument.
Alignment resolve(TextDirection? direction);
}
class Alignment extends AlignmentGeometry {
... ... @@ -753,7 +768,8 @@ class AlignmentDirectional extends AlignmentGeometry {
static const AlignmentDirectional topEnd = AlignmentDirectional(1.0, -1.0);
/// The center point along the "start" edge.
static const AlignmentDirectional centerStart = AlignmentDirectional(-1.0, 0.0);
static const AlignmentDirectional centerStart =
AlignmentDirectional(-1.0, 0.0);
/// The center point, both horizontally and vertically.
///
... ... @@ -765,13 +781,15 @@ class AlignmentDirectional extends AlignmentGeometry {
static const AlignmentDirectional centerEnd = AlignmentDirectional(1.0, 0.0);
/// The bottom corner on the "start" side.
static const AlignmentDirectional bottomStart = AlignmentDirectional(-1.0, 1.0);
static const AlignmentDirectional bottomStart =
AlignmentDirectional(-1.0, 1.0);
/// The center point along the bottom edge.
///
/// Consider using [Alignment.bottomCenter] instead, as it does not
/// need to be [resolve]d to be used.
static const AlignmentDirectional bottomCenter = AlignmentDirectional(0.0, 1.0);
static const AlignmentDirectional bottomCenter =
AlignmentDirectional(0.0, 1.0);
/// The bottom corner on the "end" side.
static const AlignmentDirectional bottomEnd = AlignmentDirectional(1.0, 1.0);
... ... @@ -813,7 +831,8 @@ class AlignmentDirectional extends AlignmentGeometry {
@override
Alignment resolve(TextDirection? direction) {
assert(direction != null, 'Cannot resolve $runtimeType without a TextDirection.');
assert(direction != null,
'Cannot resolve $runtimeType without a TextDirection.');
switch (direction!) {
case TextDirection.rtl:
return Alignment(-start, y);
... ... @@ -823,7 +842,6 @@ class AlignmentDirectional extends AlignmentGeometry {
}
}
/// An offset that's expressed as a fraction of a [PdfPoint].
@immutable
class FractionalOffset extends Alignment {
... ... @@ -844,7 +862,10 @@ class FittedSizes {
}
FittedSizes applyBoxFit(BoxFit fit, PdfPoint inputSize, PdfPoint outputSize) {
if (inputSize.y <= 0.0 || inputSize.x <= 0.0 || outputSize.y <= 0.0 || outputSize.x <= 0.0) {
if (inputSize.y <= 0.0 ||
inputSize.x <= 0.0 ||
outputSize.y <= 0.0 ||
outputSize.x <= 0.0) {
return const FittedSizes(PdfPoint.zero, PdfPoint.zero);
}
... ... @@ -857,29 +878,38 @@ FittedSizes applyBoxFit(BoxFit fit, PdfPoint inputSize, PdfPoint outputSize) {
case BoxFit.contain:
sourceSize = inputSize;
if (outputSize.x / outputSize.y > sourceSize.x / sourceSize.y) {
destinationSize = PdfPoint(sourceSize.x * outputSize.y / sourceSize.y, outputSize.y);
destinationSize =
PdfPoint(sourceSize.x * outputSize.y / sourceSize.y, outputSize.y);
} else {
destinationSize = PdfPoint(outputSize.x, sourceSize.y * outputSize.x / sourceSize.x);
destinationSize =
PdfPoint(outputSize.x, sourceSize.y * outputSize.x / sourceSize.x);
}
break;
case BoxFit.cover:
if (outputSize.x / outputSize.y > inputSize.x / inputSize.y) {
sourceSize = PdfPoint(inputSize.x, inputSize.x * outputSize.y / outputSize.x);
sourceSize =
PdfPoint(inputSize.x, inputSize.x * outputSize.y / outputSize.x);
} else {
sourceSize = PdfPoint(inputSize.y * outputSize.x / outputSize.y, inputSize.y);
sourceSize =
PdfPoint(inputSize.y * outputSize.x / outputSize.y, inputSize.y);
}
destinationSize = outputSize;
break;
case BoxFit.fitWidth:
sourceSize = PdfPoint(inputSize.x, inputSize.x * outputSize.y / outputSize.x);
destinationSize = PdfPoint(outputSize.x, sourceSize.y * outputSize.x / sourceSize.x);
sourceSize =
PdfPoint(inputSize.x, inputSize.x * outputSize.y / outputSize.x);
destinationSize =
PdfPoint(outputSize.x, sourceSize.y * outputSize.x / sourceSize.x);
break;
case BoxFit.fitHeight:
sourceSize = PdfPoint(inputSize.y * outputSize.x / outputSize.y, inputSize.y);
destinationSize = PdfPoint(sourceSize.x * outputSize.y / sourceSize.y, outputSize.y);
sourceSize =
PdfPoint(inputSize.y * outputSize.x / outputSize.y, inputSize.y);
destinationSize =
PdfPoint(sourceSize.x * outputSize.y / sourceSize.y, outputSize.y);
break;
case BoxFit.none:
sourceSize = PdfPoint(math.min(inputSize.x, outputSize.x), math.min(inputSize.y, outputSize.y));
sourceSize = PdfPoint(math.min(inputSize.x, outputSize.x),
math.min(inputSize.y, outputSize.y));
destinationSize = sourceSize;
break;
case BoxFit.scaleDown:
... ...
... ... @@ -200,7 +200,6 @@ class GridPaper extends SingleChildWidget {
@override
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
final resolvedMargin = margin.resolve(Directionality.of(context));
box = PdfRect.fromPoints(PdfPoint.zero, constraints.biggest);
if (child != null) {
... ... @@ -216,7 +215,8 @@ class GridPaper extends SingleChildWidget {
assert(child!.box != null);
child!.box = PdfRect.fromPoints(
PdfPoint(resolvedMargin.left, box!.top - resolvedMargin.top - child!.box!.height),
PdfPoint(resolvedMargin.left,
box!.top - resolvedMargin.top - child!.box!.height),
child!.box!.size);
}
}
... ... @@ -273,8 +273,8 @@ class GridPaper extends SingleChildWidget {
context.canvas
..setStrokeColor(border.left.color)
..setLineWidth(border.left.width)
..drawLine(box!.left + resolvedMargin.left, box!.top, box!.left + resolvedMargin.left,
box!.bottom)
..drawLine(box!.left + resolvedMargin.left, box!.top,
box!.left + resolvedMargin.left, box!.bottom)
..strokePath();
border.left.style.unsetStyle(context);
}
... ... @@ -293,8 +293,8 @@ class GridPaper extends SingleChildWidget {
context.canvas
..setStrokeColor(border.top.color)
..setLineWidth(border.top.width)
..drawLine(
box!.left, box!.top - resolvedMargin.top, box!.right, box!.top - resolvedMargin.top)
..drawLine(box!.left, box!.top - resolvedMargin.top, box!.right,
box!.top - resolvedMargin.top)
..strokePath();
border.top.style.unsetStyle(context);
}
... ...
... ... @@ -47,7 +47,8 @@ class GridViewContext extends WidgetContext {
}
@override
String toString() => '$runtimeType first:$firstChild last:$lastChild size:${childCrossAxis}x$childMainAxis';
String toString() =>
'$runtimeType first:$firstChild last:$lastChild size:${childCrossAxis}x$childMainAxis';
}
class GridView extends MultiChildWidget with SpanningWidget {
... ... @@ -73,7 +74,8 @@ class GridView extends MultiChildWidget with SpanningWidget {
int? _mainAxisCount;
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
if (children.isEmpty) {
box = PdfRect.zero;
return;
... ... @@ -81,7 +83,8 @@ class GridView extends MultiChildWidget with SpanningWidget {
assert(() {
if (constraints.maxHeight.isInfinite && childAspectRatio.isInfinite) {
print('Unable to calculate the GridView dimensions. Please set the height constraints or childAspectRatio.');
print(
'Unable to calculate the GridView dimensions. Please set the height constraints or childAspectRatio.');
return false;
}
return true;
... ... @@ -102,19 +105,25 @@ class GridView extends MultiChildWidget with SpanningWidget {
}
if (constraints.maxHeight.isInfinite || _mainAxisCount == null) {
_mainAxisCount = ((children.length - _context.firstChild) / crossAxisCount).ceil();
_mainAxisCount =
((children.length - _context.firstChild) / crossAxisCount).ceil();
_context.childCrossAxis =
crossAxisExtent / crossAxisCount - (crossAxisSpacing * (crossAxisCount - 1) / crossAxisCount);
_context.childCrossAxis = crossAxisExtent / crossAxisCount -
(crossAxisSpacing * (crossAxisCount - 1) / crossAxisCount);
_context.childMainAxis = math.min(_context.childCrossAxis! * childAspectRatio,
mainAxisExtent / _mainAxisCount! - (mainAxisSpacing * (_mainAxisCount! - 1) / _mainAxisCount!));
_context.childMainAxis = math.min(
_context.childCrossAxis! * childAspectRatio,
mainAxisExtent / _mainAxisCount! -
(mainAxisSpacing * (_mainAxisCount! - 1) / _mainAxisCount!));
if (_context.childCrossAxis!.isInfinite) {
throw Exception('Unable to calculate child height as the height constraint is infinite.');
throw Exception(
'Unable to calculate child height as the height constraint is infinite.');
}
} else {
_mainAxisCount = ((mainAxisExtent + mainAxisSpacing) / (mainAxisSpacing + _context.childMainAxis!)).floor();
_mainAxisCount = ((mainAxisExtent + mainAxisSpacing) /
(mainAxisSpacing + _context.childMainAxis!))
.floor();
if (_mainAxisCount! < 0) {
// Not enough space to put one line, try to ask for more space.
... ... @@ -122,8 +131,12 @@ class GridView extends MultiChildWidget with SpanningWidget {
}
}
final totalMain = (_context.childMainAxis! + mainAxisSpacing) * _mainAxisCount! - mainAxisSpacing;
final totalCross = (_context.childCrossAxis! + crossAxisSpacing) * crossAxisCount - crossAxisSpacing;
final totalMain =
(_context.childMainAxis! + mainAxisSpacing) * _mainAxisCount! -
mainAxisSpacing;
final totalCross =
(_context.childCrossAxis! + crossAxisSpacing) * crossAxisCount -
crossAxisSpacing;
final startX = resolvedPadding.left;
const startY = 0.0;
... ... @@ -132,12 +145,14 @@ class GridView extends MultiChildWidget with SpanningWidget {
BoxConstraints? innerConstraints;
switch (direction) {
case Axis.vertical:
innerConstraints = BoxConstraints.tightFor(width: _context.childCrossAxis, height: _context.childMainAxis);
innerConstraints = BoxConstraints.tightFor(
width: _context.childCrossAxis, height: _context.childMainAxis);
crossAxis = startX;
mainAxis = startY;
break;
case Axis.horizontal:
innerConstraints = BoxConstraints.tightFor(width: _context.childMainAxis, height: _context.childCrossAxis);
innerConstraints = BoxConstraints.tightFor(
width: _context.childMainAxis, height: _context.childCrossAxis);
mainAxis = startX;
crossAxis = startY;
break;
... ... @@ -148,7 +163,9 @@ class GridView extends MultiChildWidget with SpanningWidget {
final isRtl = textDirection == TextDirection.rtl;
for (final child in children.sublist(
_context.firstChild, math.min(children.length, _context.firstChild + crossAxisCount * _mainAxisCount!))) {
_context.firstChild,
math.min(children.length,
_context.firstChild + crossAxisCount * _mainAxisCount!))) {
child.layout(context, innerConstraints);
assert(child.box != null);
... ... @@ -158,7 +175,8 @@ class GridView extends MultiChildWidget with SpanningWidget {
PdfPoint(
isRtl
? (_context.childCrossAxis! + child.box!.width - crossAxis)
: (_context.childCrossAxis! - child.box!.width) / 2.0 + crossAxis,
: (_context.childCrossAxis! - child.box!.width) / 2.0 +
crossAxis,
totalMain +
resolvedPadding.bottom -
(_context.childMainAxis! - child.box!.height) / 2.0 -
... ... @@ -172,8 +190,9 @@ class GridView extends MultiChildWidget with SpanningWidget {
child.box = PdfRect.fromPoints(
PdfPoint(
isRtl
? totalMain - (child.box!.width + mainAxis)
: (_context.childMainAxis! - child.box!.width) / 2.0 + mainAxis,
? totalMain - (child.box!.width + mainAxis)
: (_context.childMainAxis! - child.box!.width) / 2.0 +
mainAxis,
totalCross +
resolvedPadding.bottom -
(_context.childCrossAxis! - child.box!.height) / 2.0 -
... ... @@ -208,10 +227,14 @@ class GridView extends MultiChildWidget with SpanningWidget {
switch (direction) {
case Axis.vertical:
box = constraints.constrainRect(width: totalCross + padding.horizontal, height: totalMain + padding.vertical);
box = constraints.constrainRect(
width: totalCross + padding.horizontal,
height: totalMain + padding.vertical);
break;
case Axis.horizontal:
box = constraints.constrainRect(width: totalMain + padding.horizontal, height: totalCross + padding.vertical);
box = constraints.constrainRect(
width: totalMain + padding.horizontal,
height: totalCross + padding.vertical);
break;
}
}
... ... @@ -231,25 +254,37 @@ class GridView extends MultiChildWidget with SpanningWidget {
..lineTo(box!.right, box!.bottom)
..lineTo(box!.right, box!.top)
..lineTo(box!.left, box!.top)
..moveTo(box!.left + resolvedPadding.left, box!.bottom + resolvedPadding.bottom)
..moveTo(box!.left + resolvedPadding.left,
box!.bottom + resolvedPadding.bottom)
..lineTo(box!.left + resolvedPadding.left, box!.top - resolvedPadding.top)
..lineTo(box!.right - resolvedPadding.right, box!.top - resolvedPadding.top)
..lineTo(box!.right - resolvedPadding.right, box!.bottom + resolvedPadding.bottom)
..lineTo(
box!.right - resolvedPadding.right, box!.top - resolvedPadding.top)
..lineTo(box!.right - resolvedPadding.right,
box!.bottom + resolvedPadding.bottom)
..fillPath();
for (var c = 1; c < crossAxisCount; c++) {
switch (direction) {
case Axis.vertical:
context.canvas
..drawRect(box!.left + resolvedPadding.left + (_context.childCrossAxis! + crossAxisSpacing) * c - crossAxisSpacing,
box!.bottom + resolvedPadding.bottom, math.max(crossAxisSpacing, 1), box!.height - resolvedPadding.vertical)
..drawRect(
box!.left +
resolvedPadding.left +
(_context.childCrossAxis! + crossAxisSpacing) * c -
crossAxisSpacing,
box!.bottom + resolvedPadding.bottom,
math.max(crossAxisSpacing, 1),
box!.height - resolvedPadding.vertical)
..fillPath();
break;
case Axis.horizontal:
context.canvas
..drawRect(
box!.left + resolvedPadding.left,
box!.bottom + resolvedPadding.bottom + (_context.childCrossAxis! + crossAxisSpacing) * c - crossAxisSpacing,
box!.bottom +
resolvedPadding.bottom +
(_context.childCrossAxis! + crossAxisSpacing) * c -
crossAxisSpacing,
box!.width - resolvedPadding.horizontal,
math.max(crossAxisSpacing, 1))
..fillPath();
... ... @@ -263,15 +298,24 @@ class GridView extends MultiChildWidget with SpanningWidget {
context.canvas
..drawRect(
box!.left + resolvedPadding.left,
box!.bottom + resolvedPadding.bottom + (_context.childMainAxis! + mainAxisSpacing) * c - mainAxisSpacing,
box!.bottom +
resolvedPadding.bottom +
(_context.childMainAxis! + mainAxisSpacing) * c -
mainAxisSpacing,
box!.width - resolvedPadding.horizontal,
math.max(mainAxisSpacing, 1))
..fillPath();
break;
case Axis.horizontal:
context.canvas
..drawRect(box!.left + resolvedPadding.left + (_context.childMainAxis! + mainAxisSpacing) * c - mainAxisSpacing,
box!.bottom + resolvedPadding.bottom, math.max(mainAxisSpacing, 1), box!.height - resolvedPadding.vertical)
..drawRect(
box!.left +
resolvedPadding.left +
(_context.childMainAxis! + mainAxisSpacing) * c -
mainAxisSpacing,
box!.bottom + resolvedPadding.bottom,
math.max(mainAxisSpacing, 1),
box!.height - resolvedPadding.vertical)
..fillPath();
break;
}
... ... @@ -288,7 +332,8 @@ class GridView extends MultiChildWidget with SpanningWidget {
..saveContext()
..setTransform(mat);
for (var child in children.sublist(_context.firstChild, _context.lastChild)) {
for (var child
in children.sublist(_context.firstChild, _context.lastChild)) {
child.paint(context);
}
context.canvas.restoreContext();
... ...
... ... @@ -61,12 +61,14 @@ mixin SpanningWidget on Widget {
/// Called before relayout to restore the saved state and
/// restart the layout in the same conditions
@protected
void applyContext(covariant WidgetContext context) => saveContext().apply(context);
void applyContext(covariant WidgetContext context) =>
saveContext().apply(context);
}
class NewPage extends Widget {
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
box = PdfRect.zero;
}
}
... ... @@ -183,7 +185,8 @@ class MultiPage extends Page {
/// This is not checked with a Release build.
final int maxPages;
void _paintChild(Context context, Widget child, double x, double y, double pageHeight) {
void _paintChild(
Context context, Widget child, double x, double y, double pageHeight) {
if (mustRotate) {
final _margin = resolvedMargin!;
context.canvas
... ... @@ -212,23 +215,30 @@ class MultiPage extends Page {
final _margin = resolvedMargin!;
final _mustRotate = mustRotate;
final pageHeight = _mustRotate ? pageFormat.width : pageFormat.height;
final pageHeightMargin = _mustRotate ? _margin.horizontal : _margin.vertical;
final pageHeightMargin =
_mustRotate ? _margin.horizontal : _margin.vertical;
final constraints = BoxConstraints(
maxWidth: _mustRotate ? (pageFormat.height - _margin.vertical) : (pageFormat.width - _margin.horizontal));
maxWidth: _mustRotate
? (pageFormat.height - _margin.vertical)
: (pageFormat.width - _margin.horizontal));
final fullConstraints = mustRotate
? BoxConstraints(
maxWidth: pageFormat.height - _margin.vertical, maxHeight: pageFormat.width - _margin.horizontal)
maxWidth: pageFormat.height - _margin.vertical,
maxHeight: pageFormat.width - _margin.horizontal)
: BoxConstraints(
maxWidth: pageFormat.width - _margin.horizontal, maxHeight: pageFormat.height - _margin.vertical);
maxWidth: pageFormat.width - _margin.horizontal,
maxHeight: pageFormat.height - _margin.vertical);
final calculatedTheme = theme ?? document.theme ?? ThemeData.base();
Context? context;
late double offsetEnd;
double? offsetStart;
var _index = 0;
var sameCount = 0;
final baseContext = Context(document: document.document).inheritFromAll(<Inherited>[
final baseContext =
Context(document: document.document).inheritFromAll(<Inherited>[
calculatedTheme,
if (pageTheme.textDirection != null) InheritedDirectionality(pageTheme.textDirection),
if (pageTheme.textDirection != null)
InheritedDirectionality(pageTheme.textDirection),
]);
final children = _buildList(baseContext);
WidgetContext? widgetContext;
... ... @@ -263,8 +273,10 @@ class MultiPage extends Page {
return true;
}());
offsetStart = pageHeight - (_mustRotate ? pageHeightMargin - _margin.bottom : _margin.top);
offsetEnd = _mustRotate ? pageHeightMargin - _margin.left : _margin.bottom;
offsetStart = pageHeight -
(_mustRotate ? pageHeightMargin - _margin.bottom : _margin.top);
offsetEnd =
_mustRotate ? pageHeightMargin - _margin.left : _margin.bottom;
_pages.add(_MultiPageInstance(
context: context,
... ... @@ -316,7 +328,8 @@ class MultiPage extends Page {
// Else we crash if the widget is too big and cannot be separated
if (!canSpan) {
throw Exception('Widget won\'t fit into the page as its height (${child.box!.height}) '
throw Exception(
'Widget won\'t fit into the page as its height (${child.box!.height}) '
'exceed a page height (${pageHeight - pageHeightMargin}). '
'You probably need a SpanningWidget or use a single page layout');
}
... ... @@ -328,7 +341,8 @@ class MultiPage extends Page {
span.applyContext(savedContext);
}
final localConstraints = constraints.copyWith(maxHeight: offsetStart - offsetEnd);
final localConstraints =
constraints.copyWith(maxHeight: offsetStart - offsetEnd);
span.layout(context, localConstraints, parentUsesSize: false);
assert(span.box != null);
widgetContext = span.saveContext();
... ... @@ -355,7 +369,8 @@ class MultiPage extends Page {
_MultiPageWidget(
child: child,
constraints: constraints,
widgetContext: child is SpanningWidget && canSpan ? child.cloneContext() : null,
widgetContext:
child is SpanningWidget && canSpan ? child.cloneContext() : null,
),
);
... ... @@ -371,21 +386,27 @@ class MultiPage extends Page {
final _mustRotate = mustRotate;
final pageHeight = _mustRotate ? pageFormat.width : pageFormat.height;
final pageWidth = _mustRotate ? pageFormat.height : pageFormat.width;
final pageHeightMargin = _mustRotate ? _margin.horizontal : _margin.vertical;
final pageHeightMargin =
_mustRotate ? _margin.horizontal : _margin.vertical;
final pageWidthMargin = _mustRotate ? _margin.vertical : _margin.horizontal;
final availableWidth = pageWidth - pageWidthMargin;
final isRTL = pageTheme.textDirection == TextDirection.rtl;
for (final page in _pages) {
var offsetStart = pageHeight - (_mustRotate ? pageHeightMargin - _margin.bottom : _margin.top);
var offsetEnd = _mustRotate ? pageHeightMargin - _margin.left : _margin.bottom;
var offsetStart = pageHeight -
(_mustRotate ? pageHeightMargin - _margin.bottom : _margin.top);
var offsetEnd =
_mustRotate ? pageHeightMargin - _margin.left : _margin.bottom;
if (pageTheme.buildBackground != null) {
final child = pageTheme.buildBackground!(page.context);
child.layout(page.context, page.fullConstraints, parentUsesSize: false);
assert(child.box != null);
final xPos = isRTL ? _margin.left + (availableWidth - child.box!.width) : _margin.left;
_paintChild(page.context, child, xPos, _margin.bottom, pageFormat.height);
final xPos = isRTL
? _margin.left + (availableWidth - child.box!.width)
: _margin.left;
_paintChild(
page.context, child, xPos, _margin.bottom, pageFormat.height);
}
var totalFlex = 0;
... ... @@ -410,20 +431,28 @@ class MultiPage extends Page {
if (header != null) {
final headerWidget = header!(page.context);
headerWidget.layout(page.context, page.constraints, parentUsesSize: false);
headerWidget.layout(page.context, page.constraints,
parentUsesSize: false);
assert(headerWidget.box != null);
offsetStart -= headerWidget.box!.height;
final xPos = isRTL ? _margin.left + (availableWidth - headerWidget.box!.width) : _margin.left;
_paintChild(page.context, headerWidget, xPos, page.offsetStart! - headerWidget.box!.height, pageFormat.height);
final xPos = isRTL
? _margin.left + (availableWidth - headerWidget.box!.width)
: _margin.left;
_paintChild(page.context, headerWidget, xPos,
page.offsetStart! - headerWidget.box!.height, pageFormat.height);
}
if (footer != null) {
final footerWidget = footer!(page.context);
footerWidget.layout(page.context, page.constraints, parentUsesSize: false);
footerWidget.layout(page.context, page.constraints,
parentUsesSize: false);
assert(footerWidget.box != null);
final xPos = isRTL ? _margin.left + (availableWidth - footerWidget.box!.width) : _margin.left;
final xPos = isRTL
? _margin.left + (availableWidth - footerWidget.box!.width)
: _margin.left;
offsetEnd += footerWidget.box!.height;
_paintChild(page.context, footerWidget, xPos, _margin.bottom, pageFormat.height);
_paintChild(page.context, footerWidget, xPos, _margin.bottom,
pageFormat.height);
}
final freeSpace = math.max(0.0, offsetStart - offsetEnd - allocatedSize);
... ... @@ -452,14 +481,16 @@ class MultiPage extends Page {
break;
case MainAxisAlignment.spaceBetween:
leadingSpace = 0.0;
betweenSpace = totalChildren > 1 ? freeSpace / (totalChildren - 1) : 0.0;
betweenSpace =
totalChildren > 1 ? freeSpace / (totalChildren - 1) : 0.0;
break;
case MainAxisAlignment.spaceAround:
betweenSpace = totalChildren > 0 ? freeSpace / totalChildren : 0.0;
leadingSpace = betweenSpace / 2.0;
break;
case MainAxisAlignment.spaceEvenly:
betweenSpace = totalChildren > 0 ? freeSpace / (totalChildren + 1) : 0.0;
betweenSpace =
totalChildren > 0 ? freeSpace / (totalChildren + 1) : 0.0;
leadingSpace = betweenSpace;
break;
}
... ... @@ -471,8 +502,11 @@ class MultiPage extends Page {
final flex = child is Flexible ? child.flex : 0;
final fit = child is Flexible ? child.fit : FlexFit.loose;
if (flex > 0) {
assert(child is! SpanningWidget || child.canSpan == false, 'Cannot have a spanning widget flexible');
final maxChildExtent = child == lastFlexChild ? (freeSpace - allocatedFlexSpace) : spacePerFlex * flex;
assert(child is! SpanningWidget || child.canSpan == false,
'Cannot have a spanning widget flexible');
final maxChildExtent = child == lastFlexChild
? (freeSpace - allocatedFlexSpace)
: spacePerFlex * flex;
late double minChildExtent;
switch (fit) {
case FlexFit.tight:
... ... @@ -526,7 +560,8 @@ class MultiPage extends Page {
if (child is SpanningWidget && child.canSpan) {
child.applyContext(widget.widgetContext!);
}
_paintChild(page.context, widget.child, _margin.left + x, pos, pageFormat.height);
_paintChild(page.context, widget.child, _margin.left + x, pos,
pageFormat.height);
pos -= betweenSpace;
}
... ... @@ -535,8 +570,11 @@ class MultiPage extends Page {
child.layout(page.context, page.fullConstraints, parentUsesSize: false);
assert(child.box != null);
final xPos = isRTL ? _margin.left + (availableWidth - child.box!.width) : _margin.left;
_paintChild(page.context, child, xPos, _margin.bottom, pageFormat.height);
final xPos = isRTL
? _margin.left + (availableWidth - child.box!.width)
: _margin.left;
_paintChild(
page.context, child, xPos, _margin.bottom, pageFormat.height);
}
}
}
... ...
... ... @@ -93,7 +93,8 @@ class Page {
..lineTo(0, pageFormat.height)
..moveTo(_margin.left, _margin.bottom)
..lineTo(_margin.left, pageFormat.height - _margin.top)
..lineTo(pageFormat.width - _margin.right, pageFormat.height - _margin.top)
..lineTo(
pageFormat.width - _margin.right, pageFormat.height - _margin.top)
..lineTo(pageFormat.width - _margin.right, _margin.bottom)
..fillPath();
}
... ... @@ -101,7 +102,8 @@ class Page {
void generate(Document document, {bool insert = true, int? index}) {
if (index != null) {
if (insert) {
_pdfPage = PdfPage(document.document, pageFormat: pageFormat, index: index);
_pdfPage =
PdfPage(document.document, pageFormat: pageFormat, index: index);
} else {
_pdfPage = document.document.page(index);
}
... ... @@ -116,9 +118,11 @@ class Page {
final _margin = resolvedMargin;
var constraints = mustRotate
? BoxConstraints(
maxWidth: pageFormat.height - _margin!.vertical, maxHeight: pageFormat.width - _margin.horizontal)
maxWidth: pageFormat.height - _margin!.vertical,
maxHeight: pageFormat.width - _margin.horizontal)
: BoxConstraints(
maxWidth: pageFormat.width - _margin!.horizontal, maxHeight: pageFormat.height - _margin.vertical);
maxWidth: pageFormat.width - _margin!.horizontal,
maxHeight: pageFormat.height - _margin.vertical);
final calculatedTheme = theme ?? document.theme ?? ThemeData.base();
final context = Context(
... ... @@ -127,7 +131,8 @@ class Page {
canvas: canvas,
).inheritFromAll(<Inherited>[
calculatedTheme,
if (pageTheme.textDirection != null) InheritedDirectionality(pageTheme.textDirection),
if (pageTheme.textDirection != null)
InheritedDirectionality(pageTheme.textDirection),
]);
Widget? background;
... ... @@ -139,7 +144,8 @@ class Page {
final size = layout(content, context, constraints);
if (_pdfPage!.pageFormat.height == double.infinity) {
_pdfPage!.pageFormat = _pdfPage!.pageFormat.copyWith(width: size.x, height: size.y);
_pdfPage!.pageFormat =
_pdfPage!.pageFormat.copyWith(width: size.x, height: size.y);
constraints = mustRotate
? BoxConstraints(
maxWidth: _pdfPage!.pageFormat.height - _margin.vertical,
... ... @@ -178,18 +184,22 @@ class Page {
}
@protected
PdfPoint layout(Widget child, Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
PdfPoint layout(Widget child, Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
final _margin = resolvedMargin!;
child.layout(context, constraints, parentUsesSize: parentUsesSize);
assert(child.box != null);
final width =
pageFormat.width == double.infinity ? child.box!.width + _margin.left + _margin.right : pageFormat.width;
final width = pageFormat.width == double.infinity
? child.box!.width + _margin.left + _margin.right
: pageFormat.width;
final height =
pageFormat.height == double.infinity ? child.box!.height + _margin.top + _margin.bottom : pageFormat.height;
final height = pageFormat.height == double.infinity
? child.box!.height + _margin.top + _margin.bottom
: pageFormat.height;
child.box = PdfRect(_margin.left, height - child.box!.height - _margin.top, child.box!.width, child.box!.height);
child.box = PdfRect(_margin.left, height - child.box!.height - _margin.top,
child.box!.width, child.box!.height);
return PdfPoint(width, height);
}
... ... @@ -212,7 +222,8 @@ class Page {
if (pageTheme.textDirection == TextDirection.rtl) {
child.box = PdfRect(
((mustRotate ? box.height : box.width) - child.box!.width) + child.box!.x,
((mustRotate ? box.height : box.width) - child.box!.width) +
child.box!.x,
child.box!.y,
child.box!.width,
child.box!.height,
... ...
... ... @@ -54,8 +54,10 @@ class PageTheme {
final TextDirection? textDirection;
bool get mustRotate =>
(orientation == PageOrientation.landscape && pageFormat.height > pageFormat.width) ||
(orientation == PageOrientation.portrait && pageFormat.width > pageFormat.height);
(orientation == PageOrientation.landscape &&
pageFormat.height > pageFormat.width) ||
(orientation == PageOrientation.portrait &&
pageFormat.width > pageFormat.height);
EdgeInsetsGeometry? get margin {
if (_margin != null) {
... ... @@ -73,11 +75,11 @@ class PageTheme {
}
if (mustRotate) {
return EdgeInsets.fromLTRB(
pageFormat.marginBottom, pageFormat.marginLeft, pageFormat.marginTop, pageFormat.marginRight);
return EdgeInsets.fromLTRB(pageFormat.marginBottom, pageFormat.marginLeft,
pageFormat.marginTop, pageFormat.marginRight);
} else {
return EdgeInsets.fromLTRB(
pageFormat.marginLeft, pageFormat.marginTop, pageFormat.marginRight, pageFormat.marginBottom);
return EdgeInsets.fromLTRB(pageFormat.marginLeft, pageFormat.marginTop,
pageFormat.marginRight, pageFormat.marginBottom);
}
}
... ...
... ... @@ -146,7 +146,8 @@ class PositionedDirectional extends Positioned {
final double? end;
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
super.layout(context, constraints, parentUsesSize: parentUsesSize);
switch (Directionality.of(context)) {
case TextDirection.rtl:
... ... @@ -181,7 +182,8 @@ class Stack extends MultiChildWidget {
final Overflow overflow;
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
final childCount = children.length;
var hasNonPositionedChildren = false;
... ... @@ -230,22 +232,27 @@ class Stack extends MultiChildWidget {
final resolvedAlignment = alignment.resolve(Directionality.of(context));
for (final child in children) {
if (child is! Positioned) {
child.box = PdfRect.fromPoints(resolvedAlignment.inscribe(child.box!.size, box!).offset, child.box!.size);
child.box = PdfRect.fromPoints(
resolvedAlignment.inscribe(child.box!.size, box!).offset,
child.box!.size);
} else {
final positioned = child;
var childConstraints = const BoxConstraints();
if (positioned.left != null && positioned.right != null) {
childConstraints = childConstraints.tighten(width: box!.width - positioned.right! - positioned.left!);
childConstraints = childConstraints.tighten(
width: box!.width - positioned.right! - positioned.left!);
} else if (positioned.width != null) {
childConstraints = childConstraints.tighten(width: positioned.width);
}
if (positioned.top != null && positioned.bottom != null) {
childConstraints = childConstraints.tighten(height: box!.height - positioned.bottom! - positioned.top!);
childConstraints = childConstraints.tighten(
height: box!.height - positioned.bottom! - positioned.top!);
} else if (positioned.height != null) {
childConstraints = childConstraints.tighten(height: positioned.height);
childConstraints =
childConstraints.tighten(height: positioned.height);
}
positioned.layout(context, childConstraints, parentUsesSize: true);
... ... @@ -269,7 +276,8 @@ class Stack extends MultiChildWidget {
y = resolvedAlignment.inscribe(positioned.box!.size, box!).y;
}
positioned.box = PdfRect.fromPoints(PdfPoint(x!, y!), positioned.box!.size);
positioned.box =
PdfRect.fromPoints(PdfPoint(x!, y!), positioned.box!.size);
}
}
}
... ...
... ... @@ -120,7 +120,8 @@ mixin TableHelper {
rowNum++;
}
final textDirection = context == null ? TextDirection.ltr : Directionality.of(context);
final textDirection =
context == null ? TextDirection.ltr : Directionality.of(context);
for (final row in data) {
final tableRow = <Widget>[];
final isOdd = (rowNum - headerCount) % 2 != 0;
... ...
... ... @@ -83,7 +83,8 @@ abstract class _Span {
}
class _TextDecoration {
_TextDecoration(this.style, this.annotation, this.startSpan, this.endSpan) : assert(startSpan <= endSpan);
_TextDecoration(this.style, this.annotation, this.startSpan, this.endSpan)
: assert(startSpan <= endSpan);
static const double _space = -0.15;
... ... @@ -103,7 +104,8 @@ class _TextDecoration {
}
final x1 = spans[startSpan].offset.x + spans[startSpan].left;
final x2 = spans[endSpan].offset.x + spans[endSpan].left + spans[endSpan].width;
final x2 =
spans[endSpan].offset.x + spans[endSpan].left + spans[endSpan].width;
var y1 = spans[startSpan].offset.y + spans[startSpan].top;
var y2 = y1 + spans[startSpan].height;
... ... @@ -118,7 +120,8 @@ class _TextDecoration {
return _box;
}
_TextDecoration copyWith({int? endSpan}) => _TextDecoration(style, annotation, startSpan, endSpan ?? this.endSpan);
_TextDecoration copyWith({int? endSpan}) =>
_TextDecoration(style, annotation, startSpan, endSpan ?? this.endSpan);
void backgroundPaint(
Context context,
... ... @@ -163,11 +166,15 @@ class _TextDecoration {
final box = _getBox(spans);
final font = style.font!.getFont(context);
final space = _space * style.fontSize! * textScaleFactor * style.decorationThickness!;
final space =
_space * style.fontSize! * textScaleFactor * style.decorationThickness!;
context.canvas
..setStrokeColor(style.decorationColor ?? style.color)
..setLineWidth(style.decorationThickness! * style.fontSize! * textScaleFactor * 0.05);
..setLineWidth(style.decorationThickness! *
style.fontSize! *
textScaleFactor *
0.05);
if (style.decoration!.contains(TextDecoration.underline)) {
final base = -font.descent * style.fontSize! * textScaleFactor / 2;
... ... @@ -240,7 +247,8 @@ class _TextDecoration {
context.canvas
..setLineWidth(.5)
..drawRect(globalBox.x + box.x, globalBox.top + box.y, box.width, box.height)
..drawRect(
globalBox.x + box.x, globalBox.top + box.y, box.width, box.height)
..setStrokeColor(PdfColors.yellow)
..strokePath();
}
... ... @@ -302,11 +310,14 @@ class _Word extends _Span {
context.canvas
..setLineWidth(.5)
..drawRect(
globalBox!.x + offset.x + metrics.left, globalBox.top + offset.y + metrics.top, metrics.width, metrics.height)
..drawRect(globalBox!.x + offset.x + metrics.left,
globalBox.top + offset.y + metrics.top, metrics.width, metrics.height)
..setStrokeColor(PdfColors.orange)
..strokePath()
..drawLine(globalBox.x + offset.x - deb, globalBox.top + offset.y, globalBox.x + offset.x + metrics.right + deb,
..drawLine(
globalBox.x + offset.x - deb,
globalBox.top + offset.y,
globalBox.x + offset.x + metrics.right + deb,
globalBox.top + offset.y)
..setStrokeColor(PdfColors.deepPurple)
..strokePath();
... ... @@ -352,8 +363,10 @@ class _WidgetSpan extends _Span {
double textScaleFactor,
PdfPoint point,
) {
widget.box =
PdfRect.fromPoints(PdfPoint(point.x + widget.box!.offset.x, point.y + widget.box!.offset.y), widget.box!.size);
widget.box = PdfRect.fromPoints(
PdfPoint(
point.x + widget.box!.offset.x, point.y + widget.box!.offset.y),
widget.box!.size);
widget.paint(context);
}
... ... @@ -367,7 +380,8 @@ class _WidgetSpan extends _Span {
context.canvas
..setLineWidth(.5)
..drawRect(globalBox!.x + offset.x, globalBox.top + offset.y, width, height)
..drawRect(
globalBox!.x + offset.x, globalBox.top + offset.y, width, height)
..setStrokeColor(PdfColors.orange)
..strokePath()
..drawLine(
... ... @@ -550,11 +564,14 @@ class _Line {
double get height {
final list = parent._spans.sublist(firstSpan, lastSpan);
return list.isEmpty ? 0 : list.reduce((a, b) => a.height > b.height ? a : b).height;
return list.isEmpty
? 0
: list.reduce((a, b) => a.height > b.height ? a : b).height;
}
@override
String toString() => '$runtimeType $firstSpan-$lastSpan baseline: $baseline width:$wordsWidth';
String toString() =>
'$runtimeType $firstSpan-$lastSpan baseline: $baseline width:$wordsWidth';
void realign(double totalWidth) {
final spans = parent._spans.sublist(firstSpan, lastSpan);
... ... @@ -566,7 +583,7 @@ class _Line {
delta = isRTL ? wordsWidth : 0;
break;
case TextAlign.right:
delta = isRTL ? totalWidth: totalWidth - wordsWidth;
delta = isRTL ? totalWidth : totalWidth - wordsWidth;
break;
case TextAlign.start:
delta = isRTL ? totalWidth : 0;
... ... @@ -576,7 +593,7 @@ class _Line {
break;
case TextAlign.center:
delta = (totalWidth - wordsWidth) / 2.0;
if(isRTL) {
if (isRTL) {
delta += wordsWidth;
}
break;
... ... @@ -590,7 +607,9 @@ class _Line {
var x = 0.0;
for (final span in spans) {
span.offset = PdfPoint(
isRTL ? delta - x - (span.offset.x + span.width) : span.offset.x + x,
isRTL
? delta - x - (span.offset.x + span.width)
: span.offset.x + x,
span.offset.y - baseline,
);
x += gap;
... ... @@ -635,7 +654,8 @@ class RichTextContext extends WidgetContext {
}
@override
String toString() => '$runtimeType Offset: $startOffset -> $endOffset Span: $spanStart -> $spanEnd';
String toString() =>
'$runtimeType Offset: $startOffset -> $endOffset Span: $spanStart -> $spanEnd';
}
class RichText extends Widget with SpanningWidget {
... ... @@ -684,7 +704,8 @@ class RichText extends Widget with SpanningWidget {
if (append && _decorations.isNotEmpty) {
final last = _decorations.last;
if (last.style == td.style && last.annotation == td.annotation) {
_decorations[_decorations.length - 1] = last.copyWith(endSpan: td.endSpan);
_decorations[_decorations.length - 1] =
last.copyWith(endSpan: td.endSpan);
return;
}
}
... ... @@ -854,7 +875,8 @@ class RichText extends Widget with SpanningWidget {
}
@override
void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
_spans.clear();
_decorations.clear();
... ... @@ -866,8 +888,12 @@ class RichText extends Widget with SpanningWidget {
final _overflow = this.overflow ?? theme.overflow;
final constraintWidth = constraints.hasBoundedWidth ? constraints.maxWidth : constraints.constrainWidth();
final constraintHeight = constraints.hasBoundedHeight ? constraints.maxHeight : constraints.constrainHeight();
final constraintWidth = constraints.hasBoundedWidth
? constraints.maxWidth
: constraints.constrainWidth();
final constraintHeight = constraints.hasBoundedHeight
? constraints.maxHeight
: constraints.constrainHeight();
var offsetX = 0.0;
var offsetY = _context.startOffset;
... ... @@ -894,10 +920,13 @@ class RichText extends Widget with SpanningWidget {
final font = style!.font!.getFont(context);
final space = font.stringMetrics(' ') * (style.fontSize! * textScaleFactor);
final space =
font.stringMetrics(' ') * (style.fontSize! * textScaleFactor);
final spanLines =
(_textDirection == TextDirection.rtl ? bidi.logicalToVisual(span.text!) : span.text)!.split('\n');
final spanLines = (_textDirection == TextDirection.rtl
? bidi.logicalToVisual(span.text!)
: span.text)!
.split('\n');
for (var line = 0; line < spanLines.length; line++) {
final words = spanLines[line].split(RegExp(r'\s'));
... ... @@ -905,15 +934,18 @@ class RichText extends Widget with SpanningWidget {
final word = words[index];
if (word.isEmpty) {
offsetX += space.advanceWidth * style.wordSpacing! + style.letterSpacing!;
offsetX += space.advanceWidth * style.wordSpacing! +
style.letterSpacing!;
continue;
}
final metrics =
font.stringMetrics(word, letterSpacing: style.letterSpacing! / (style.fontSize! * textScaleFactor)) *
(style.fontSize! * textScaleFactor);
final metrics = font.stringMetrics(word,
letterSpacing: style.letterSpacing! /
(style.fontSize! * textScaleFactor)) *
(style.fontSize! * textScaleFactor);
if (_softWrap && offsetX + metrics.width > constraintWidth + 0.00001) {
if (_softWrap &&
offsetX + metrics.width > constraintWidth + 0.00001) {
if (spanCount > 0 && metrics.width <= constraintWidth) {
overflow = true;
lines.add(_Line(
... ... @@ -921,7 +953,9 @@ class RichText extends Widget with SpanningWidget {
spanStart,
spanCount,
bottom,
offsetX - space.advanceWidth * style.wordSpacing! - style.letterSpacing!,
offsetX -
space.advanceWidth * style.wordSpacing! -
style.letterSpacing!,
_textDirection,
true,
));
... ... @@ -983,7 +1017,9 @@ class RichText extends Widget with SpanningWidget {
),
);
offsetX += metrics.advanceWidth + space.advanceWidth * style.wordSpacing! + style.letterSpacing!;
offsetX += metrics.advanceWidth +
space.advanceWidth * style.wordSpacing! +
style.letterSpacing!;
}
if (line < spanLines.length - 1) {
... ... @@ -992,7 +1028,9 @@ class RichText extends Widget with SpanningWidget {
spanStart,
spanCount,
bottom,
offsetX - space.advanceWidth * style.wordSpacing! - style.letterSpacing!,
offsetX -
space.advanceWidth * style.wordSpacing! -
style.letterSpacing!,
_textDirection,
false,
));
... ... @@ -1021,7 +1059,8 @@ class RichText extends Widget with SpanningWidget {
}
}
offsetX -= space.advanceWidth * style.wordSpacing! - style.letterSpacing!;
offsetX -=
space.advanceWidth * style.wordSpacing! - style.letterSpacing!;
} else if (span is WidgetSpan) {
span.child.layout(
context,
... ... @@ -1124,7 +1163,8 @@ class RichText extends Widget with SpanningWidget {
}
}
box = PdfRect(0, 0, constraints.constrainWidth(width), constraints.constrainHeight(offsetY));
box = PdfRect(0, 0, constraints.constrainWidth(width),
constraints.constrainHeight(offsetY));
_context
..endOffset = offsetY - _context.startOffset
... ... @@ -1144,7 +1184,8 @@ class RichText extends Widget with SpanningWidget {
for (var index = 0; index < _decorations.length; index++) {
final decoration = _decorations[index];
if (decoration.startSpan >= _context.spanEnd || decoration.endSpan < _context.spanStart) {
if (decoration.startSpan >= _context.spanEnd ||
decoration.endSpan < _context.spanStart) {
_decorations.removeAt(index);
index--;
}
... ... @@ -1239,7 +1280,8 @@ class RichText extends Widget with SpanningWidget {
while (low + 1 < high) {
final metrics = font.stringMetrics(word.substring(0, pos),
letterSpacing: style.letterSpacing! / (style.fontSize! * textScaleFactor)) *
letterSpacing:
style.letterSpacing! / (style.fontSize! * textScaleFactor)) *
(style.fontSize! * textScaleFactor);
if (metrics.width > maxWidth) {
... ...
... ... @@ -46,8 +46,6 @@ void main() {
pdf = Document();
});
test('RTL Text', () {
pdf.addPage(
Page(
... ... @@ -134,7 +132,9 @@ void main() {
);
});
test('Should render a blue box followed by a red box ordered RTL aligned right', () {
test(
'Should render a blue box followed by a red box ordered RTL aligned right',
() {
pdf.addPage(
Page(
textDirection: TextDirection.rtl,
... ... @@ -149,7 +149,9 @@ void main() {
);
});
test('Should render a blue box followed by a red box ordered RTL with aligned center', () {
test(
'Should render a blue box followed by a red box ordered RTL with aligned center',
() {
pdf.addPage(
Page(
textDirection: TextDirection.rtl,
... ... @@ -165,7 +167,9 @@ void main() {
);
});
test('Should render a blue box followed by a red box ordered RTL with CrossAxisAlignment.end aligned right', () {
test(
'Should render a blue box followed by a red box ordered RTL with CrossAxisAlignment.end aligned right',
() {
pdf.addPage(
Page(
pageFormat: const PdfPageFormat(150, 100),
... ... @@ -184,7 +188,9 @@ void main() {
),
);
});
test('Should render a blue box followed by a red box ordered LTR aligned left', () {
test(
'Should render a blue box followed by a red box ordered LTR aligned left',
() {
pdf.addPage(
Page(
pageFormat: const PdfPageFormat(150, 50),
... ... @@ -197,7 +203,9 @@ void main() {
),
);
});
test('Should render a blue box followed by a red box ordered TTB aligned right', () {
test(
'Should render a blue box followed by a red box ordered TTB aligned right',
() {
pdf.addPage(
Page(
textDirection: TextDirection.rtl,
... ... @@ -216,7 +224,9 @@ void main() {
),
);
});
test('Should render a blue box followed by a red box ordered TTB aligned left', () {
test(
'Should render a blue box followed by a red box ordered TTB aligned left',
() {
pdf.addPage(
Page(
textDirection: TextDirection.ltr,
... ... @@ -569,7 +579,11 @@ void main() {
children: [
for (int i = 0; i < 7; i++)
Container(
color: [PdfColors.blue, PdfColors.red, PdfColors.yellow][i % 3],
color: [
PdfColors.blue,
PdfColors.red,
PdfColors.yellow
][i % 3],
),
],
),
... ... @@ -594,7 +608,11 @@ void main() {
children: [
for (int i = 0; i < 7; i++)
Container(
color: [PdfColors.blue, PdfColors.red, PdfColors.yellow][i % 3],
color: [
PdfColors.blue,
PdfColors.red,
PdfColors.yellow
][i % 3],
),
],
),
... ... @@ -618,7 +636,11 @@ void main() {
children: [
for (int i = 0; i < 7; i++)
Container(
color: [PdfColors.blue, PdfColors.red, PdfColors.yellow][i % 3],
color: [
PdfColors.blue,
PdfColors.red,
PdfColors.yellow
][i % 3],
),
],
),
... ... @@ -643,7 +665,11 @@ void main() {
children: [
for (int i = 0; i < 7; i++)
Container(
color: [PdfColors.blue, PdfColors.red, PdfColors.yellow][i % 3],
color: [
PdfColors.blue,
PdfColors.red,
PdfColors.yellow
][i % 3],
),
],
),
... ...
No preview for this file type