Skip to content

Commit

Permalink
support multi page slots alignments
Browse files Browse the repository at this point in the history
  • Loading branch information
Milad-Akarie authored and DavBfr committed Jul 24, 2023
1 parent 97490bd commit 81ba6e8
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 52 deletions.
60 changes: 28 additions & 32 deletions pdf/lib/src/widgets/multi_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -188,28 +188,18 @@ class MultiPage extends Page {
final _margin = resolvedMargin!;
context.canvas
..saveContext()
..setTransform(Matrix4.identity()
..rotateZ(-math.pi / 2)
..translate(
x - pageHeight + _margin.top - _margin.left,
y + _margin.left - _margin.bottom,
));

final availableWidth = pageHeight - resolvedMargin!.vertical;
if (pageTheme.textDirection == TextDirection.rtl) {
child.box = child.box!.copyWith(
x: (availableWidth - child.box!.width) + child.box!.x,
..setTransform(
Matrix4.identity()
..rotateZ(-math.pi / 2)
..translate(
x - pageHeight + _margin.top - _margin.left,
y + _margin.left - _margin.bottom,
),
);
}
child.paint(context);
context.canvas.restoreContext();
} else {
var childXPos = x;
if (pageTheme.textDirection == TextDirection.rtl) {
final availableWidth = pageFormat.width - resolvedMargin!.horizontal;
childXPos = (availableWidth - child.box!.width) + x;
}
child.box = child.box!.copyWith(x: childXPos, y: y);
child.box = child.box!.copyWith(x: x, y: y);
child.paint(context);
}
}
Expand Down Expand Up @@ -384,7 +374,7 @@ class MultiPage extends Page {
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;
Expand All @@ -394,7 +384,8 @@ class MultiPage extends Page {

child.layout(page.context, page.fullConstraints, parentUsesSize: false);
assert(child.box != null);
_paintChild(page.context, child, _margin.left, _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;
Expand All @@ -419,21 +410,20 @@ class MultiPage extends Page {

if (header != null) {
final headerWidget = header!(page.context);

headerWidget.layout(page.context, page.constraints, parentUsesSize: false);
assert(headerWidget.box != null);
offsetStart -= headerWidget.box!.height;
_paintChild(
page.context, headerWidget, _margin.left, 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);
assert(footerWidget.box != null);
final xPos = isRTL ? _margin.left + (availableWidth - footerWidget.box!.width) : _margin.left;
offsetEnd += footerWidget.box!.height;
_paintChild(page.context, footerWidget, _margin.left, _margin.bottom, pageFormat.height);
_paintChild(page.context, footerWidget, xPos, _margin.bottom, pageFormat.height);
}

final freeSpace = math.max(0.0, offsetStart - offsetEnd - allocatedSize);
Expand Down Expand Up @@ -508,24 +498,29 @@ class MultiPage extends Page {
allocatedFlexSpace += maxChildExtent;
}
}

var pos = offsetStart - leadingSpace;
for (final widget in page.widgets) {
pos -= widget.child.box!.height;
late double x;
switch (crossAxisAlignment) {
case CrossAxisAlignment.stretch:
case CrossAxisAlignment.start:
x = 0;
if (isRTL) {
x = availableWidth - widget.child.box!.width;
} else {
x = 0;
}
break;
case CrossAxisAlignment.end:
x = availableWidth - widget.child.box!.width;
if (isRTL) {
x = 0;
} else {
x = availableWidth - widget.child.box!.width;
}
break;
case CrossAxisAlignment.center:
x = availableWidth / 2 - widget.child.box!.width / 2;
break;
case CrossAxisAlignment.stretch:
x = 0;
break;
}
final child = widget.child;
if (child is SpanningWidget && child.canSpan) {
Expand All @@ -540,7 +535,8 @@ class MultiPage extends Page {

child.layout(page.context, page.fullConstraints, parentUsesSize: false);
assert(child.box != null);
_paintChild(page.context, child, _margin.left, _margin.bottom, pageFormat.height);
final xPos = isRTL ? _margin.left + (availableWidth - child.box!.width) : _margin.left;
_paintChild(page.context, child, xPos, _margin.bottom, pageFormat.height);
}
}
}
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 @@ -566,7 +566,7 @@ class _Line {
delta = isRTL ? wordsWidth : 0;
break;
case TextAlign.right:
delta = totalWidth - wordsWidth;
delta = isRTL ? totalWidth: totalWidth - wordsWidth;
break;
case TextAlign.start:
delta = isRTL ? totalWidth : 0;
Expand All @@ -576,6 +576,9 @@ class _Line {
break;
case TextAlign.center:
delta = (totalWidth - wordsWidth) / 2.0;
if(isRTL) {
delta += wordsWidth;
}
break;
case TextAlign.justify:
delta = isRTL ? totalWidth : 0;
Expand Down
106 changes: 87 additions & 19 deletions pdf/test/rtl_layout_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/

import 'dart:io';
import 'dart:typed_data';

import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
Expand All @@ -42,40 +41,106 @@ final _yellowBox = Container(
);

void main() {
late final arabicFont;
setUpAll(() {
Document.debug = true;
pdf = Document();
final fontData = File('test/fonts/cairo.ttf').readAsBytesSync();
// final fontData = File('test/fonts/hacen_tunisia.ttf').readAsBytesSync();
arabicFont = Font.ttf(fontData.buffer.asByteData());
});

test('Should render Text aligned right', () {
test('Should render a blue box followed by a red box ordered RTL aligned right', () {
pdf.addPage(
Page(
textDirection: TextDirection.rtl,
pageFormat: const PdfPageFormat(150, 50),
build: (Context context) => TestAnnotation(
anno: 'RTL Row',
child: Row(
children: [_blueBox, _redBox],
),
),
),
);
});

test('RTL Text', () {
pdf.addPage(
Page(
textDirection: TextDirection.rtl,
pageFormat: const PdfPageFormat(150, 50),
build: (Context context) => Text(
'RTL Text',
),
),
);
});
test('RTL Text TextAlign.end', () {
pdf.addPage(
Page(
textDirection: TextDirection.rtl,
pageFormat: const PdfPageFormat(150, 50),
build: (Context context) => SizedBox(
width: 150,
child: Text(
'مرحبا بالعالم',
style: TextStyle(font: arabicFont),
'RTL Text : TextAlign.end',
textAlign: TextAlign.end,
),
),
),
);
});

test('Should render a blue box followed by a red box ordered RTL aligned right', () {
test('RTL Text TextAlign.left', () {
pdf.addPage(
Page(
textDirection: TextDirection.rtl,
pageFormat: const PdfPageFormat(150, 50),
build: (Context context) => TestAnnotation(
anno: 'RTL Row',
child: Row(
children: [_blueBox, _redBox],
build: (Context context) => SizedBox(
width: 150,
child: Text(
'RTL Text : TextAlign.left',
textAlign: TextAlign.left,
),
),
),
);
});

test('LTR Text', () {
pdf.addPage(
Page(
textDirection: TextDirection.ltr,
pageFormat: const PdfPageFormat(150, 50),
build: (Context context) => Text(
'LTR Text',
),
),
);
});
test('LTR Text TextAlign.end', () {
pdf.addPage(
Page(
textDirection: TextDirection.ltr,
pageFormat: const PdfPageFormat(150, 50),
build: (Context context) => SizedBox(
width: 150,
child: Text(
'RTL Text : TextAlign.end',
textAlign: TextAlign.end,
),
),
),
);
});

test('LTR Text TextAlign.right', () {
pdf.addPage(
Page(
textDirection: TextDirection.ltr,
pageFormat: const PdfPageFormat(150, 50),
build: (Context context) => SizedBox(
width: 150,
child: Text(
'LTR Text : TextAlign.right',
textAlign: TextAlign.right,
),
),
),
Expand Down Expand Up @@ -286,10 +351,12 @@ void main() {
pageFormat: const PdfPageFormat(150, 150),
build: (Context context) {
return [
ListView(children: [
Text('RTL MultiPage'),
for (int i = 0; i < 15; i++) Text('List item'),
]),
Text('RTL MultiPage', style: const TextStyle(fontSize: 9)),
ListView(
children: [
for (int i = 0; i < 15; i++) Text('List item'),
],
),
];
},
),
Expand All @@ -303,7 +370,7 @@ void main() {
pageFormat: const PdfPageFormat(150, 150),
build: (Context context) {
return [
Text('LTR MultiPage'),
Text('LTR MultiPage', style: const TextStyle(fontSize: 9)),
ListView(children: [
for (int i = 0; i < 15; i++) Text('List item'),
]),
Expand Down Expand Up @@ -444,7 +511,7 @@ void main() {
return TestAnnotation(
anno: 'LTR RadiusDirectional.horizontal end',
child: Container(
margin: const EdgeInsets.only(top: 22),
margin: const EdgeInsets.only(top: 11),
decoration: const BoxDecoration(
color: PdfColors.blue,
borderRadius: BorderRadiusDirectional.horizontal(
Expand Down Expand Up @@ -609,6 +676,7 @@ class TestAnnotation extends StatelessWidget {
child: Text(
anno,
style: const TextStyle(color: PdfColors.black, fontSize: 9),
textDirection: TextDirection.ltr,
textAlign: TextAlign.center,
),
),
Expand Down

0 comments on commit 81ba6e8

Please sign in to comment.