Skip to content

Commit

Permalink
Fix Mid-word line break inside table
Browse files Browse the repository at this point in the history
  • Loading branch information
MathanM committed Aug 11, 2024
1 parent 4146df6 commit f78d73b
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 22 deletions.
20 changes: 12 additions & 8 deletions pdf/lib/src/pdf/rect.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,20 @@ import 'point.dart';

@immutable
class PdfRect {
const PdfRect(this.x, this.y, this.width, this.height);
const PdfRect(this.x, this.y, this.width, this.height, [this.minWidth]);

factory PdfRect.fromLTRB(
double left, double top, double right, double bottom) {
return PdfRect(left, top, right - left, bottom - top);
factory PdfRect.fromLTRB(double left, double top, double right, double bottom,
[double? minWidth]) {
return PdfRect(left, top, right - left, bottom - top, minWidth);
}

factory PdfRect.fromPoints(PdfPoint offset, PdfPoint size) {
return PdfRect(offset.x, offset.y, size.x, size.y);
factory PdfRect.fromPoints(PdfPoint offset, PdfPoint size,
[double? minWidth]) {
return PdfRect(offset.x, offset.y, size.x, size.y, minWidth);
}

final double x, y, width, height;
final double? minWidth;

static const PdfRect zero = PdfRect(0, 0, 0, 0);

Expand Down Expand Up @@ -70,9 +72,9 @@ class PdfRect {
PdfPoint get bottomRight => PdfPoint(right, top);

/// Returns a new rectangle with edges moved outwards by the given delta.
PdfRect inflate(double delta) {
PdfRect inflate(double delta, [double? minWidth]) {
return PdfRect.fromLTRB(
left - delta, top - delta, right + delta, bottom + delta);
left - delta, top - delta, right + delta, bottom + delta, minWidth);
}

/// Returns a new rectangle with edges moved inwards by the given delta.
Expand All @@ -83,12 +85,14 @@ class PdfRect {
double? y,
double? width,
double? height,
double? minWidth,
}) {
return PdfRect(
x ?? this.x,
y ?? this.y,
width ?? this.width,
height ?? this.height,
minWidth ?? this.minWidth,
);
}
}
24 changes: 16 additions & 8 deletions pdf/lib/src/widgets/basic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,12 @@ class Padding extends SingleChildWidget {
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,
minWidth: child!.box!.minWidth != null
? child!.box!.minWidth! + resolvedPadding.horizontal
: null,
);
} else {
box = constraints.constrainRect(
width: resolvedPadding.horizontal, height: resolvedPadding.vertical);
Expand Down Expand Up @@ -323,12 +327,16 @@ class Align extends SingleChildWidget {
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,
minWidth: child!.box!.minWidth != null && shrinkWrapWidth
? child!.box!.minWidth! * (widthFactor ?? 1.0)
: null,
);
final resolvedAlignment = alignment.resolve(Directionality.of(context));
child!.box = resolvedAlignment.inscribe(child!.box!.size, box!);
} else {
Expand Down
10 changes: 7 additions & 3 deletions pdf/lib/src/widgets/geometry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,13 @@ class BoxConstraints {
return result;
}

PdfRect constrainRect(
{double width = double.infinity, double height = double.infinity}) {
PdfRect constrainRect({
double width = double.infinity,
double height = double.infinity,
double? minWidth,
}) {
final result = PdfPoint(constrainWidth(width), constrainHeight(height));
return PdfRect.fromPoints(PdfPoint.zero, result);
return PdfRect.fromPoints(PdfPoint.zero, result, minWidth);
}

double constrainWidth([double width = double.infinity]) {
Expand Down Expand Up @@ -672,6 +675,7 @@ class Alignment extends AlignmentGeometry {
rect.y + halfHeightDelta + y * halfHeightDelta,
size.x,
size.y,
rect.minWidth,
);
}

Expand Down
34 changes: 32 additions & 2 deletions pdf/lib/src/widgets/table.dart
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,11 @@ class TableContext extends WidgetContext {
}

class ColumnLayout {
ColumnLayout(this.width, this.flex);
ColumnLayout(this.width, this.flex, [this.minWidth]);

final double? width;
final double? flex;
final double? minWidth;
}

abstract class TableColumnWidth {
Expand Down Expand Up @@ -180,7 +181,7 @@ class IntrinsicColumnWidth extends TableColumnWidth {
(child is Expanded
? child.flex.toDouble()
: (child.box!.width == double.infinity ? 1 : 0));
return ColumnLayout(calculatedWidth, childFlex);
return ColumnLayout(calculatedWidth, childFlex, child.box!.minWidth);
}
}

Expand Down Expand Up @@ -317,6 +318,7 @@ class Table extends Widget with SpanningWidget {

final List<double?> _widths = <double?>[];
final List<double> _heights = <double>[];
final List<double?> _minWidths = <double>[];

final TableContext _context = TableContext();

Expand All @@ -341,6 +343,7 @@ class Table extends Widget with SpanningWidget {
final flex = <double?>[];
_widths.clear();
_heights.clear();
_minWidths.clear();
var index = 0;

for (final row in children) {
Expand All @@ -353,11 +356,13 @@ class Table extends Widget with SpanningWidget {
if (flex.length < n + 1) {
flex.add(columnLayout.flex);
_widths.add(columnLayout.width);
_minWidths.add(columnLayout.minWidth ?? 0);
} else {
if (columnLayout.flex! > 0) {
flex[n] = math.max(flex[n]!, columnLayout.flex!);
}
_widths[n] = math.max(_widths[n]!, columnLayout.width!);
_minWidths[n] = math.max(_minWidths[n]!, columnLayout.minWidth ?? 0);
}
n++;
}
Expand All @@ -380,10 +385,35 @@ class Table extends Widget with SpanningWidget {
if ((tableWidth == TableWidth.max && totalFlex == 0.0) ||
newWidth < _widths[n]!) {
_widths[n] = newWidth;
_widths[n] = math.max(newWidth, _minWidths[n]!);
}
flexSpace += _widths[n]!;
}
}

final totalWidth = flexSpace;
final remainingSpace = constraints.maxWidth - totalWidth;
flexSpace = 0.0;
if (remainingSpace < 0) {
// Deficit: reduce widths proportionally
for (var i = 0; i < _widths.length; i++) {
if (_widths[i]! > _minWidths[i]!) {
final proportion = (_widths[i]! / totalWidth);
final adjustment = remainingSpace * proportion;
_widths[i] = math.max(_minWidths[i]!, _widths[i]! + adjustment);
}
flexSpace += _widths[i]!;
}
} else if (remainingSpace > 0) {
// Surplus: distribute extra space proportionally
for (var i = 0; i < _widths.length; i++) {
final proportion = (_widths[i]! / totalWidth);
final adjustment = remainingSpace * proportion;
_widths[i] = _widths[i]! + adjustment;
flexSpace += _widths[i]!;
}
}

final spacePerFlex = totalFlex > 0.0
? ((constraints.maxWidth - flexSpace) / totalFlex)
: double.nan;
Expand Down
5 changes: 4 additions & 1 deletion pdf/lib/src/widgets/text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -907,6 +907,7 @@ class RichText extends Widget with SpanningWidget {

var top = 0.0;
var bottom = 0.0;
var minWidth = 0.0;

final lines = <_Line>[];
var spanCount = 0;
Expand Down Expand Up @@ -953,6 +954,8 @@ class RichText extends Widget with SpanningWidget {
(style.fontSize! * textScaleFactor)) *
(style.fontSize! * textScaleFactor);

minWidth = math.max(minWidth, metrics.width);

if (_softWrap &&
offsetX + metrics.width > constraintWidth + 0.00001) {
if (hyphenation != null) {
Expand Down Expand Up @@ -1200,7 +1203,7 @@ class RichText extends Widget with SpanningWidget {
}

box = PdfRect(0, 0, constraints.constrainWidth(width),
constraints.constrainHeight(offsetY));
constraints.constrainHeight(offsetY), minWidth);

_context
..endOffset = offsetY - _context.startOffset
Expand Down

0 comments on commit f78d73b

Please sign in to comment.