Showing
2 changed files
with
173 additions
and
13 deletions
@@ -16,6 +16,7 @@ | @@ -16,6 +16,7 @@ | ||
16 | 16 | ||
17 | import 'dart:math' as math; | 17 | import 'dart:math' as math; |
18 | 18 | ||
19 | +import 'package:pdf/widgets.dart'; | ||
19 | import 'package:vector_math/vector_math_64.dart'; | 20 | import 'package:vector_math/vector_math_64.dart'; |
20 | 21 | ||
21 | import '../../pdf.dart'; | 22 | import '../../pdf.dart'; |
@@ -396,10 +397,10 @@ class Flex extends MultiChildWidget with SpanningWidget { | @@ -396,10 +397,10 @@ class Flex extends MultiChildWidget with SpanningWidget { | ||
396 | final remainingSpace = math.max(0.0, actualSizeDelta); | 397 | final remainingSpace = math.max(0.0, actualSizeDelta); |
397 | double? leadingSpace; | 398 | double? leadingSpace; |
398 | late double betweenSpace; | 399 | late double betweenSpace; |
399 | - final flipMainAxis = (verticalDirection == VerticalDirection.down && | ||
400 | - direction == Axis.vertical) || | ||
401 | - (verticalDirection == VerticalDirection.up && | ||
402 | - direction == Axis.horizontal); | 400 | + |
401 | + final textDirection = Directionality.of(context) ; | ||
402 | + final flipMainAxis = !(_startIsTopLeft(direction, textDirection, verticalDirection) ?? true); | ||
403 | + | ||
403 | switch (mainAxisAlignment) { | 404 | switch (mainAxisAlignment) { |
404 | case MainAxisAlignment.start: | 405 | case MainAxisAlignment.start: |
405 | leadingSpace = 0.0; | 406 | leadingSpace = 0.0; |
@@ -430,10 +431,6 @@ class Flex extends MultiChildWidget with SpanningWidget { | @@ -430,10 +431,6 @@ class Flex extends MultiChildWidget with SpanningWidget { | ||
430 | } | 431 | } |
431 | 432 | ||
432 | // Position elements | 433 | // Position elements |
433 | - final flipCrossAxis = (verticalDirection == VerticalDirection.down && | ||
434 | - direction == Axis.horizontal) || | ||
435 | - (verticalDirection == VerticalDirection.up && | ||
436 | - direction == Axis.vertical); | ||
437 | var childMainPosition = | 434 | var childMainPosition = |
438 | flipMainAxis ? actualSize - leadingSpace : leadingSpace; | 435 | flipMainAxis ? actualSize - leadingSpace : leadingSpace; |
439 | 436 | ||
@@ -442,12 +439,11 @@ class Flex extends MultiChildWidget with SpanningWidget { | @@ -442,12 +439,11 @@ class Flex extends MultiChildWidget with SpanningWidget { | ||
442 | double? childCrossPosition; | 439 | double? childCrossPosition; |
443 | switch (crossAxisAlignment) { | 440 | switch (crossAxisAlignment) { |
444 | case CrossAxisAlignment.start: | 441 | case CrossAxisAlignment.start: |
445 | - childCrossPosition = | ||
446 | - flipCrossAxis ? crossSize - _getCrossSize(child) : 0.0; | ||
447 | - break; | ||
448 | case CrossAxisAlignment.end: | 442 | case CrossAxisAlignment.end: |
449 | - childCrossPosition = | ||
450 | - !flipCrossAxis ? crossSize - _getCrossSize(child) : 0.0; | 443 | + childCrossPosition = _startIsTopLeft(flipAxis(direction), textDirection, verticalDirection) |
444 | + == (crossAxisAlignment == CrossAxisAlignment.start) | ||
445 | + ? 0.0 | ||
446 | + : crossSize - _getCrossSize(child); | ||
451 | break; | 447 | break; |
452 | case CrossAxisAlignment.center: | 448 | case CrossAxisAlignment.center: |
453 | childCrossPosition = crossSize / 2.0 - _getCrossSize(child) / 2.0; | 449 | childCrossPosition = crossSize / 2.0 - _getCrossSize(child) / 2.0; |
@@ -478,6 +474,39 @@ class Flex extends MultiChildWidget with SpanningWidget { | @@ -478,6 +474,39 @@ class Flex extends MultiChildWidget with SpanningWidget { | ||
478 | } | 474 | } |
479 | } | 475 | } |
480 | 476 | ||
477 | + Axis flipAxis(Axis direction) { | ||
478 | + switch (direction) { | ||
479 | + case Axis.horizontal: | ||
480 | + return Axis.vertical; | ||
481 | + case Axis.vertical: | ||
482 | + return Axis.horizontal; | ||
483 | + } | ||
484 | + } | ||
485 | + | ||
486 | + bool? _startIsTopLeft(Axis direction, TextDirection? textDirection, VerticalDirection? verticalDirection) { | ||
487 | + // If the relevant value of textDirection or verticalDirection is null, this returns null too. | ||
488 | + switch (direction) { | ||
489 | + case Axis.horizontal: | ||
490 | + switch (textDirection) { | ||
491 | + case TextDirection.ltr: | ||
492 | + return true; | ||
493 | + case TextDirection.rtl: | ||
494 | + return false; | ||
495 | + case null: | ||
496 | + return null; | ||
497 | + } | ||
498 | + case Axis.vertical: | ||
499 | + switch (verticalDirection) { | ||
500 | + case VerticalDirection.down: | ||
501 | + return false; | ||
502 | + case VerticalDirection.up: | ||
503 | + return true; | ||
504 | + case null: | ||
505 | + return null; | ||
506 | + } | ||
507 | + } | ||
508 | + } | ||
509 | + | ||
481 | @override | 510 | @override |
482 | void paint(Context context) { | 511 | void paint(Context context) { |
483 | super.paint(context); | 512 | super.paint(context); |
pdf/test/rtl_layout_test.dart
0 → 100644
1 | +/* | ||
2 | + * Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com> | ||
3 | + * | ||
4 | + * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | + * you may not use this file except in compliance with the License. | ||
6 | + * You may obtain a copy of the License at | ||
7 | + * | ||
8 | + * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | + * | ||
10 | + * Unless required by applicable law or agreed to in writing, software | ||
11 | + * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | + * See the License for the specific language governing permissions and | ||
14 | + * limitations under the License. | ||
15 | + */ | ||
16 | + | ||
17 | +import 'dart:io'; | ||
18 | + | ||
19 | +import 'package:pdf/pdf.dart'; | ||
20 | +import 'package:pdf/widgets.dart'; | ||
21 | +import 'package:test/test.dart'; | ||
22 | + | ||
23 | +late Document pdf; | ||
24 | + | ||
25 | +final _blueBox = Container( | ||
26 | + width: 50, | ||
27 | + height: 50, | ||
28 | + color: PdfColors.blue, | ||
29 | +); | ||
30 | + | ||
31 | +final _redBox = Container( | ||
32 | + width: 50, | ||
33 | + height: 50, | ||
34 | + color: PdfColors.red, | ||
35 | +); | ||
36 | + | ||
37 | +void main() { | ||
38 | + setUpAll(() { | ||
39 | + Document.debug = true; | ||
40 | + pdf = Document(); | ||
41 | + }); | ||
42 | + | ||
43 | + test('Should render a blue box followed by a red box ordered RTL aligned right', () { | ||
44 | + pdf.addPage( | ||
45 | + Page( | ||
46 | + textDirection: TextDirection.rtl, | ||
47 | + pageFormat: const PdfPageFormat(150, 50), | ||
48 | + build: (Context context) => Row( | ||
49 | + children: [_blueBox, _redBox], | ||
50 | + ), | ||
51 | + ), | ||
52 | + ); | ||
53 | + }); | ||
54 | + | ||
55 | + test('Should render a blue box followed by a red box ordered RTL with aligned center', () { | ||
56 | + pdf.addPage( | ||
57 | + Page( | ||
58 | + textDirection: TextDirection.rtl, | ||
59 | + pageFormat: const PdfPageFormat(150, 50), | ||
60 | + build: (Context context) => Row( | ||
61 | + mainAxisAlignment: MainAxisAlignment.center, | ||
62 | + children: [_blueBox, _redBox], | ||
63 | + ), | ||
64 | + ), | ||
65 | + ); | ||
66 | + }); | ||
67 | + | ||
68 | + test('Should render a blue box followed by a red box ordered RTL with CrossAxisAlignment.end aligned right', () { | ||
69 | + pdf.addPage( | ||
70 | + Page( | ||
71 | + pageFormat: const PdfPageFormat(150, 100), | ||
72 | + textDirection: TextDirection.rtl, | ||
73 | + build: (Context context) => SizedBox( | ||
74 | + width: 150, | ||
75 | + height: 100, | ||
76 | + child: Row( | ||
77 | + crossAxisAlignment: CrossAxisAlignment.end, | ||
78 | + children: [_blueBox, _redBox], | ||
79 | + ), | ||
80 | + ), | ||
81 | + ), | ||
82 | + ); | ||
83 | + }); | ||
84 | + test('Should render a blue box followed by a red box ordered LTR aligned left', () { | ||
85 | + pdf.addPage( | ||
86 | + Page( | ||
87 | + pageFormat: const PdfPageFormat(150, 50), | ||
88 | + build: (Context context) => Row( | ||
89 | + children: [_blueBox, _redBox], | ||
90 | + ), | ||
91 | + ), | ||
92 | + ); | ||
93 | + }); | ||
94 | + test('Should render a blue box followed by a red box ordered TTB aligned right', () { | ||
95 | + pdf.addPage( | ||
96 | + Page( | ||
97 | + textDirection: TextDirection.rtl, | ||
98 | + pageFormat: const PdfPageFormat(150, 150), | ||
99 | + build: (Context context) => SizedBox( | ||
100 | + width: 150, | ||
101 | + height: 150, | ||
102 | + child: Column( | ||
103 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
104 | + children: [_blueBox, _redBox], | ||
105 | + ), | ||
106 | + ), | ||
107 | + ), | ||
108 | + ); | ||
109 | + }); | ||
110 | + test('Should render a blue box followed by a red box ordered TTB aligned left', () { | ||
111 | + pdf.addPage( | ||
112 | + Page( | ||
113 | + textDirection: TextDirection.ltr, | ||
114 | + pageFormat: const PdfPageFormat(150, 150), | ||
115 | + build: (Context context) => SizedBox( | ||
116 | + width: 150, | ||
117 | + height: 150, | ||
118 | + child: Column( | ||
119 | + crossAxisAlignment: CrossAxisAlignment.start, | ||
120 | + children: [_blueBox, _redBox], | ||
121 | + ), | ||
122 | + ), | ||
123 | + ), | ||
124 | + ); | ||
125 | + }); | ||
126 | + | ||
127 | + tearDownAll(() async { | ||
128 | + final file = File('rtl-layout.pdf'); | ||
129 | + await file.writeAsBytes(await pdf.save()); | ||
130 | + }); | ||
131 | +} |
-
Please register or login to post a comment