Milad akarie
Committed by David PHAM-VAN

support multi page slots alignments

@@ -188,28 +188,18 @@ class MultiPage extends Page { @@ -188,28 +188,18 @@ class MultiPage extends Page {
188 final _margin = resolvedMargin!; 188 final _margin = resolvedMargin!;
189 context.canvas 189 context.canvas
190 ..saveContext() 190 ..saveContext()
191 - ..setTransform(Matrix4.identity()  
192 - ..rotateZ(-math.pi / 2)  
193 - ..translate(  
194 - x - pageHeight + _margin.top - _margin.left,  
195 - y + _margin.left - _margin.bottom,  
196 - ));  
197 -  
198 - final availableWidth = pageHeight - resolvedMargin!.vertical;  
199 - if (pageTheme.textDirection == TextDirection.rtl) {  
200 - child.box = child.box!.copyWith(  
201 - x: (availableWidth - child.box!.width) + child.box!.x, 191 + ..setTransform(
  192 + Matrix4.identity()
  193 + ..rotateZ(-math.pi / 2)
  194 + ..translate(
  195 + x - pageHeight + _margin.top - _margin.left,
  196 + y + _margin.left - _margin.bottom,
  197 + ),
202 ); 198 );
203 - }  
204 child.paint(context); 199 child.paint(context);
205 context.canvas.restoreContext(); 200 context.canvas.restoreContext();
206 } else { 201 } else {
207 - var childXPos = x;  
208 - if (pageTheme.textDirection == TextDirection.rtl) {  
209 - final availableWidth = pageFormat.width - resolvedMargin!.horizontal;  
210 - childXPos = (availableWidth - child.box!.width) + x;  
211 - }  
212 - child.box = child.box!.copyWith(x: childXPos, y: y); 202 + child.box = child.box!.copyWith(x: x, y: y);
213 child.paint(context); 203 child.paint(context);
214 } 204 }
215 } 205 }
@@ -384,7 +374,7 @@ class MultiPage extends Page { @@ -384,7 +374,7 @@ class MultiPage extends Page {
384 final pageHeightMargin = _mustRotate ? _margin.horizontal : _margin.vertical; 374 final pageHeightMargin = _mustRotate ? _margin.horizontal : _margin.vertical;
385 final pageWidthMargin = _mustRotate ? _margin.vertical : _margin.horizontal; 375 final pageWidthMargin = _mustRotate ? _margin.vertical : _margin.horizontal;
386 final availableWidth = pageWidth - pageWidthMargin; 376 final availableWidth = pageWidth - pageWidthMargin;
387 - 377 + final isRTL = pageTheme.textDirection == TextDirection.rtl;
388 for (final page in _pages) { 378 for (final page in _pages) {
389 var offsetStart = pageHeight - (_mustRotate ? pageHeightMargin - _margin.bottom : _margin.top); 379 var offsetStart = pageHeight - (_mustRotate ? pageHeightMargin - _margin.bottom : _margin.top);
390 var offsetEnd = _mustRotate ? pageHeightMargin - _margin.left : _margin.bottom; 380 var offsetEnd = _mustRotate ? pageHeightMargin - _margin.left : _margin.bottom;
@@ -394,7 +384,8 @@ class MultiPage extends Page { @@ -394,7 +384,8 @@ class MultiPage extends Page {
394 384
395 child.layout(page.context, page.fullConstraints, parentUsesSize: false); 385 child.layout(page.context, page.fullConstraints, parentUsesSize: false);
396 assert(child.box != null); 386 assert(child.box != null);
397 - _paintChild(page.context, child, _margin.left, _margin.bottom, pageFormat.height); 387 + final xPos = isRTL ? _margin.left + (availableWidth - child.box!.width) : _margin.left;
  388 + _paintChild(page.context, child, xPos, _margin.bottom, pageFormat.height);
398 } 389 }
399 390
400 var totalFlex = 0; 391 var totalFlex = 0;
@@ -419,21 +410,20 @@ class MultiPage extends Page { @@ -419,21 +410,20 @@ class MultiPage extends Page {
419 410
420 if (header != null) { 411 if (header != null) {
421 final headerWidget = header!(page.context); 412 final headerWidget = header!(page.context);
422 -  
423 headerWidget.layout(page.context, page.constraints, parentUsesSize: false); 413 headerWidget.layout(page.context, page.constraints, parentUsesSize: false);
424 assert(headerWidget.box != null); 414 assert(headerWidget.box != null);
425 offsetStart -= headerWidget.box!.height; 415 offsetStart -= headerWidget.box!.height;
426 - _paintChild(  
427 - page.context, headerWidget, _margin.left, page.offsetStart! - headerWidget.box!.height, pageFormat.height); 416 + final xPos = isRTL ? _margin.left + (availableWidth - headerWidget.box!.width) : _margin.left;
  417 + _paintChild(page.context, headerWidget, xPos, page.offsetStart! - headerWidget.box!.height, pageFormat.height);
428 } 418 }
429 419
430 if (footer != null) { 420 if (footer != null) {
431 final footerWidget = footer!(page.context); 421 final footerWidget = footer!(page.context);
432 -  
433 footerWidget.layout(page.context, page.constraints, parentUsesSize: false); 422 footerWidget.layout(page.context, page.constraints, parentUsesSize: false);
434 assert(footerWidget.box != null); 423 assert(footerWidget.box != null);
  424 + final xPos = isRTL ? _margin.left + (availableWidth - footerWidget.box!.width) : _margin.left;
435 offsetEnd += footerWidget.box!.height; 425 offsetEnd += footerWidget.box!.height;
436 - _paintChild(page.context, footerWidget, _margin.left, _margin.bottom, pageFormat.height); 426 + _paintChild(page.context, footerWidget, xPos, _margin.bottom, pageFormat.height);
437 } 427 }
438 428
439 final freeSpace = math.max(0.0, offsetStart - offsetEnd - allocatedSize); 429 final freeSpace = math.max(0.0, offsetStart - offsetEnd - allocatedSize);
@@ -508,24 +498,29 @@ class MultiPage extends Page { @@ -508,24 +498,29 @@ class MultiPage extends Page {
508 allocatedFlexSpace += maxChildExtent; 498 allocatedFlexSpace += maxChildExtent;
509 } 499 }
510 } 500 }
511 -  
512 var pos = offsetStart - leadingSpace; 501 var pos = offsetStart - leadingSpace;
513 for (final widget in page.widgets) { 502 for (final widget in page.widgets) {
514 pos -= widget.child.box!.height; 503 pos -= widget.child.box!.height;
515 late double x; 504 late double x;
516 switch (crossAxisAlignment) { 505 switch (crossAxisAlignment) {
  506 + case CrossAxisAlignment.stretch:
517 case CrossAxisAlignment.start: 507 case CrossAxisAlignment.start:
518 - x = 0; 508 + if (isRTL) {
  509 + x = availableWidth - widget.child.box!.width;
  510 + } else {
  511 + x = 0;
  512 + }
519 break; 513 break;
520 case CrossAxisAlignment.end: 514 case CrossAxisAlignment.end:
521 - x = availableWidth - widget.child.box!.width; 515 + if (isRTL) {
  516 + x = 0;
  517 + } else {
  518 + x = availableWidth - widget.child.box!.width;
  519 + }
522 break; 520 break;
523 case CrossAxisAlignment.center: 521 case CrossAxisAlignment.center:
524 x = availableWidth / 2 - widget.child.box!.width / 2; 522 x = availableWidth / 2 - widget.child.box!.width / 2;
525 break; 523 break;
526 - case CrossAxisAlignment.stretch:  
527 - x = 0;  
528 - break;  
529 } 524 }
530 final child = widget.child; 525 final child = widget.child;
531 if (child is SpanningWidget && child.canSpan) { 526 if (child is SpanningWidget && child.canSpan) {
@@ -540,7 +535,8 @@ class MultiPage extends Page { @@ -540,7 +535,8 @@ class MultiPage extends Page {
540 535
541 child.layout(page.context, page.fullConstraints, parentUsesSize: false); 536 child.layout(page.context, page.fullConstraints, parentUsesSize: false);
542 assert(child.box != null); 537 assert(child.box != null);
543 - _paintChild(page.context, child, _margin.left, _margin.bottom, pageFormat.height); 538 + final xPos = isRTL ? _margin.left + (availableWidth - child.box!.width) : _margin.left;
  539 + _paintChild(page.context, child, xPos, _margin.bottom, pageFormat.height);
544 } 540 }
545 } 541 }
546 } 542 }
@@ -566,7 +566,7 @@ class _Line { @@ -566,7 +566,7 @@ class _Line {
566 delta = isRTL ? wordsWidth : 0; 566 delta = isRTL ? wordsWidth : 0;
567 break; 567 break;
568 case TextAlign.right: 568 case TextAlign.right:
569 - delta = totalWidth - wordsWidth; 569 + delta = isRTL ? totalWidth: totalWidth - wordsWidth;
570 break; 570 break;
571 case TextAlign.start: 571 case TextAlign.start:
572 delta = isRTL ? totalWidth : 0; 572 delta = isRTL ? totalWidth : 0;
@@ -576,6 +576,9 @@ class _Line { @@ -576,6 +576,9 @@ class _Line {
576 break; 576 break;
577 case TextAlign.center: 577 case TextAlign.center:
578 delta = (totalWidth - wordsWidth) / 2.0; 578 delta = (totalWidth - wordsWidth) / 2.0;
  579 + if(isRTL) {
  580 + delta += wordsWidth;
  581 + }
579 break; 582 break;
580 case TextAlign.justify: 583 case TextAlign.justify:
581 delta = isRTL ? totalWidth : 0; 584 delta = isRTL ? totalWidth : 0;
@@ -15,7 +15,6 @@ @@ -15,7 +15,6 @@
15 */ 15 */
16 16
17 import 'dart:io'; 17 import 'dart:io';
18 -import 'dart:typed_data';  
19 18
20 import 'package:pdf/pdf.dart'; 19 import 'package:pdf/pdf.dart';
21 import 'package:pdf/widgets.dart'; 20 import 'package:pdf/widgets.dart';
@@ -42,16 +41,38 @@ final _yellowBox = Container( @@ -42,16 +41,38 @@ final _yellowBox = Container(
42 ); 41 );
43 42
44 void main() { 43 void main() {
45 - late final arabicFont;  
46 setUpAll(() { 44 setUpAll(() {
47 Document.debug = true; 45 Document.debug = true;
48 pdf = Document(); 46 pdf = Document();
49 - final fontData = File('test/fonts/cairo.ttf').readAsBytesSync();  
50 - // final fontData = File('test/fonts/hacen_tunisia.ttf').readAsBytesSync();  
51 - arabicFont = Font.ttf(fontData.buffer.asByteData());  
52 }); 47 });
53 48
54 - test('Should render Text aligned right', () { 49 + test('Should render a blue box followed by a red box ordered RTL aligned right', () {
  50 + pdf.addPage(
  51 + Page(
  52 + textDirection: TextDirection.rtl,
  53 + pageFormat: const PdfPageFormat(150, 50),
  54 + build: (Context context) => TestAnnotation(
  55 + anno: 'RTL Row',
  56 + child: Row(
  57 + children: [_blueBox, _redBox],
  58 + ),
  59 + ),
  60 + ),
  61 + );
  62 + });
  63 +
  64 + test('RTL Text', () {
  65 + pdf.addPage(
  66 + Page(
  67 + textDirection: TextDirection.rtl,
  68 + pageFormat: const PdfPageFormat(150, 50),
  69 + build: (Context context) => Text(
  70 + 'RTL Text',
  71 + ),
  72 + ),
  73 + );
  74 + });
  75 + test('RTL Text TextAlign.end', () {
55 pdf.addPage( 76 pdf.addPage(
56 Page( 77 Page(
57 textDirection: TextDirection.rtl, 78 textDirection: TextDirection.rtl,
@@ -59,23 +80,67 @@ void main() { @@ -59,23 +80,67 @@ void main() {
59 build: (Context context) => SizedBox( 80 build: (Context context) => SizedBox(
60 width: 150, 81 width: 150,
61 child: Text( 82 child: Text(
62 - 'مرحبا بالعالم',  
63 - style: TextStyle(font: arabicFont), 83 + 'RTL Text : TextAlign.end',
  84 + textAlign: TextAlign.end,
64 ), 85 ),
65 ), 86 ),
66 ), 87 ),
67 ); 88 );
68 }); 89 });
69 90
70 - test('Should render a blue box followed by a red box ordered RTL aligned right', () { 91 + test('RTL Text TextAlign.left', () {
71 pdf.addPage( 92 pdf.addPage(
72 Page( 93 Page(
73 textDirection: TextDirection.rtl, 94 textDirection: TextDirection.rtl,
74 pageFormat: const PdfPageFormat(150, 50), 95 pageFormat: const PdfPageFormat(150, 50),
75 - build: (Context context) => TestAnnotation(  
76 - anno: 'RTL Row',  
77 - child: Row(  
78 - children: [_blueBox, _redBox], 96 + build: (Context context) => SizedBox(
  97 + width: 150,
  98 + child: Text(
  99 + 'RTL Text : TextAlign.left',
  100 + textAlign: TextAlign.left,
  101 + ),
  102 + ),
  103 + ),
  104 + );
  105 + });
  106 +
  107 + test('LTR Text', () {
  108 + pdf.addPage(
  109 + Page(
  110 + textDirection: TextDirection.ltr,
  111 + pageFormat: const PdfPageFormat(150, 50),
  112 + build: (Context context) => Text(
  113 + 'LTR Text',
  114 + ),
  115 + ),
  116 + );
  117 + });
  118 + test('LTR Text TextAlign.end', () {
  119 + pdf.addPage(
  120 + Page(
  121 + textDirection: TextDirection.ltr,
  122 + pageFormat: const PdfPageFormat(150, 50),
  123 + build: (Context context) => SizedBox(
  124 + width: 150,
  125 + child: Text(
  126 + 'RTL Text : TextAlign.end',
  127 + textAlign: TextAlign.end,
  128 + ),
  129 + ),
  130 + ),
  131 + );
  132 + });
  133 +
  134 + test('LTR Text TextAlign.right', () {
  135 + pdf.addPage(
  136 + Page(
  137 + textDirection: TextDirection.ltr,
  138 + pageFormat: const PdfPageFormat(150, 50),
  139 + build: (Context context) => SizedBox(
  140 + width: 150,
  141 + child: Text(
  142 + 'LTR Text : TextAlign.right',
  143 + textAlign: TextAlign.right,
79 ), 144 ),
80 ), 145 ),
81 ), 146 ),
@@ -286,10 +351,12 @@ void main() { @@ -286,10 +351,12 @@ void main() {
286 pageFormat: const PdfPageFormat(150, 150), 351 pageFormat: const PdfPageFormat(150, 150),
287 build: (Context context) { 352 build: (Context context) {
288 return [ 353 return [
289 - ListView(children: [  
290 - Text('RTL MultiPage'),  
291 - for (int i = 0; i < 15; i++) Text('List item'),  
292 - ]), 354 + Text('RTL MultiPage', style: const TextStyle(fontSize: 9)),
  355 + ListView(
  356 + children: [
  357 + for (int i = 0; i < 15; i++) Text('List item'),
  358 + ],
  359 + ),
293 ]; 360 ];
294 }, 361 },
295 ), 362 ),
@@ -303,7 +370,7 @@ void main() { @@ -303,7 +370,7 @@ void main() {
303 pageFormat: const PdfPageFormat(150, 150), 370 pageFormat: const PdfPageFormat(150, 150),
304 build: (Context context) { 371 build: (Context context) {
305 return [ 372 return [
306 - Text('LTR MultiPage'), 373 + Text('LTR MultiPage', style: const TextStyle(fontSize: 9)),
307 ListView(children: [ 374 ListView(children: [
308 for (int i = 0; i < 15; i++) Text('List item'), 375 for (int i = 0; i < 15; i++) Text('List item'),
309 ]), 376 ]),
@@ -444,7 +511,7 @@ void main() { @@ -444,7 +511,7 @@ void main() {
444 return TestAnnotation( 511 return TestAnnotation(
445 anno: 'LTR RadiusDirectional.horizontal end', 512 anno: 'LTR RadiusDirectional.horizontal end',
446 child: Container( 513 child: Container(
447 - margin: const EdgeInsets.only(top: 22), 514 + margin: const EdgeInsets.only(top: 11),
448 decoration: const BoxDecoration( 515 decoration: const BoxDecoration(
449 color: PdfColors.blue, 516 color: PdfColors.blue,
450 borderRadius: BorderRadiusDirectional.horizontal( 517 borderRadius: BorderRadiusDirectional.horizontal(
@@ -609,6 +676,7 @@ class TestAnnotation extends StatelessWidget { @@ -609,6 +676,7 @@ class TestAnnotation extends StatelessWidget {
609 child: Text( 676 child: Text(
610 anno, 677 anno,
611 style: const TextStyle(color: PdfColors.black, fontSize: 9), 678 style: const TextStyle(color: PdfColors.black, fontSize: 9),
  679 + textDirection: TextDirection.ltr,
612 textAlign: TextAlign.center, 680 textAlign: TextAlign.center,
613 ), 681 ),
614 ), 682 ),