Milad akarie
Committed by David PHAM-VAN

Add TextAlign.start and TextAlign.end and fix Line.realign accordingly

change widgets geometry to directional geometry
@@ -39,22 +39,16 @@ class LimitedBox extends SingleChildWidget { @@ -39,22 +39,16 @@ class LimitedBox extends SingleChildWidget {
39 BoxConstraints _limitConstraints(BoxConstraints constraints) { 39 BoxConstraints _limitConstraints(BoxConstraints constraints) {
40 return BoxConstraints( 40 return BoxConstraints(
41 minWidth: constraints.minWidth, 41 minWidth: constraints.minWidth,
42 - maxWidth: constraints.hasBoundedWidth  
43 - ? constraints.maxWidth  
44 - : constraints.constrainWidth(maxWidth), 42 + maxWidth: constraints.hasBoundedWidth ? constraints.maxWidth : constraints.constrainWidth(maxWidth),
45 minHeight: constraints.minHeight, 43 minHeight: constraints.minHeight,
46 - maxHeight: constraints.hasBoundedHeight  
47 - ? constraints.maxHeight  
48 - : constraints.constrainHeight(maxHeight)); 44 + maxHeight: constraints.hasBoundedHeight ? constraints.maxHeight : constraints.constrainHeight(maxHeight));
49 } 45 }
50 46
51 @override 47 @override
52 - void layout(Context context, BoxConstraints constraints,  
53 - {bool parentUsesSize = false}) { 48 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
54 PdfPoint size; 49 PdfPoint size;
55 if (child != null) { 50 if (child != null) {
56 - child!.layout(context, _limitConstraints(constraints),  
57 - parentUsesSize: true); 51 + child!.layout(context, _limitConstraints(constraints), parentUsesSize: true);
58 assert(child!.box != null); 52 assert(child!.box != null);
59 size = constraints.constrain(child!.box!.size); 53 size = constraints.constrain(child!.box!.size);
60 } else { 54 } else {
@@ -79,8 +73,7 @@ class Padding extends SingleChildWidget { @@ -79,8 +73,7 @@ class Padding extends SingleChildWidget {
79 final EdgeInsetsGeometry padding; 73 final EdgeInsetsGeometry padding;
80 74
81 @override 75 @override
82 - void layout(Context context, BoxConstraints constraints,  
83 - {bool parentUsesSize = false}) { 76 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
84 final effectivePadding = padding.resolve(Directionality.of(context)); 77 final effectivePadding = padding.resolve(Directionality.of(context));
85 if (child != null) { 78 if (child != null) {
86 final childConstraints = constraints.deflate(effectivePadding); 79 final childConstraints = constraints.deflate(effectivePadding);
@@ -90,8 +83,7 @@ class Padding extends SingleChildWidget { @@ -90,8 +83,7 @@ class Padding extends SingleChildWidget {
90 width: child!.box!.width + effectivePadding.horizontal, 83 width: child!.box!.width + effectivePadding.horizontal,
91 height: child!.box!.height + effectivePadding.vertical); 84 height: child!.box!.height + effectivePadding.vertical);
92 } else { 85 } else {
93 - box = constraints.constrainRect(  
94 - width: effectivePadding.horizontal, height: effectivePadding.vertical); 86 + box = constraints.constrainRect(width: effectivePadding.horizontal, height: effectivePadding.vertical);
95 } 87 }
96 } 88 }
97 89
@@ -114,10 +106,10 @@ class Padding extends SingleChildWidget { @@ -114,10 +106,10 @@ class Padding extends SingleChildWidget {
114 @override 106 @override
115 void paint(Context context) { 107 void paint(Context context) {
116 super.paint(context); 108 super.paint(context);
117 - final effectivePadding = padding.resolve(Directionality.of(context)); 109 + final resolvedPadding = padding.resolve(Directionality.of(context));
118 if (child != null) { 110 if (child != null) {
119 final mat = Matrix4.identity(); 111 final mat = Matrix4.identity();
120 - mat.translate(box!.x + effectivePadding.left, box!.y + effectivePadding.bottom); 112 + mat.translate(box!.x + resolvedPadding.left, box!.y + resolvedPadding.bottom);
121 context.canvas 113 context.canvas
122 ..saveContext() 114 ..saveContext()
123 ..setTransform(mat); 115 ..setTransform(mat);
@@ -190,13 +182,13 @@ class Transform extends SingleChildWidget { @@ -190,13 +182,13 @@ class Transform extends SingleChildWidget {
190 final PdfPoint? origin; 182 final PdfPoint? origin;
191 183
192 /// The alignment of the origin, relative to the size of the box. 184 /// The alignment of the origin, relative to the size of the box.
193 - final Alignment? alignment; 185 + final AlignmentGeometry? alignment;
194 186
195 final bool adjustLayout; 187 final bool adjustLayout;
196 188
197 final bool unconstrained; 189 final bool unconstrained;
198 190
199 - Matrix4 get _effectiveTransform { 191 + Matrix4 _effectiveTransform(Context context) {
200 final result = Matrix4.identity(); 192 final result = Matrix4.identity();
201 if (origin != null) { 193 if (origin != null) {
202 result.translate(origin!.x, origin!.y); 194 result.translate(origin!.x, origin!.y);
@@ -204,7 +196,8 @@ class Transform extends SingleChildWidget { @@ -204,7 +196,8 @@ class Transform extends SingleChildWidget {
204 result.translate(box!.x, box!.y); 196 result.translate(box!.x, box!.y);
205 late PdfPoint translation; 197 late PdfPoint translation;
206 if (alignment != null) { 198 if (alignment != null) {
207 - translation = alignment!.alongSize(box!.size); 199 + final resolvedAlignment = alignment!.resolve(Directionality.of(context));
  200 + translation = resolvedAlignment.alongSize(box!.size);
208 result.translate(translation.x, translation.y); 201 result.translate(translation.x, translation.y);
209 } 202 }
210 result.multiply(transform); 203 result.multiply(transform);
@@ -218,8 +211,7 @@ class Transform extends SingleChildWidget { @@ -218,8 +211,7 @@ class Transform extends SingleChildWidget {
218 } 211 }
219 212
220 @override 213 @override
221 - void layout(Context context, BoxConstraints constraints,  
222 - {bool parentUsesSize = false}) { 214 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
223 if (!adjustLayout) { 215 if (!adjustLayout) {
224 return super.layout(context, constraints, parentUsesSize: parentUsesSize); 216 return super.layout(context, constraints, parentUsesSize: parentUsesSize);
225 } 217 }
@@ -248,20 +240,14 @@ class Transform extends SingleChildWidget { @@ -248,20 +240,14 @@ class Transform extends SingleChildWidget {
248 0, 240 0,
249 ]); 241 ]);
250 242
251 - final dx = -math.min(  
252 - math.min(math.min(values[0], values[3]), values[6]), values[9]);  
253 - final dy = -math.min(  
254 - math.min(math.min(values[1], values[4]), values[7]), values[10]); 243 + final dx = -math.min(math.min(math.min(values[0], values[3]), values[6]), values[9]);
  244 + final dy = -math.min(math.min(math.min(values[1], values[4]), values[7]), values[10]);
255 245
256 box = PdfRect.fromLTRB( 246 box = PdfRect.fromLTRB(
257 0, 247 0,
258 0, 248 0,
259 - math.max(math.max(math.max(values[0], values[3]), values[6]),  
260 - values[9]) +  
261 - dx,  
262 - math.max(math.max(math.max(values[1], values[4]), values[7]),  
263 - values[10]) +  
264 - dy, 249 + math.max(math.max(math.max(values[0], values[3]), values[6]), values[9]) + dx,
  250 + math.max(math.max(math.max(values[1], values[4]), values[7]), values[10]) + dy,
265 ); 251 );
266 252
267 transform.leftTranslate(dx, dy); 253 transform.leftTranslate(dx, dy);
@@ -275,7 +261,7 @@ class Transform extends SingleChildWidget { @@ -275,7 +261,7 @@ class Transform extends SingleChildWidget {
275 super.paint(context); 261 super.paint(context);
276 262
277 if (child != null) { 263 if (child != null) {
278 - final mat = _effectiveTransform; 264 + final mat = _effectiveTransform(context);
279 context.canvas 265 context.canvas
280 ..saveContext() 266 ..saveContext()
281 ..setTransform(mat); 267 ..setTransform(mat);
@@ -288,11 +274,7 @@ class Transform extends SingleChildWidget { @@ -288,11 +274,7 @@ class Transform extends SingleChildWidget {
288 /// A widget that aligns its child within itself and optionally sizes itself 274 /// A widget that aligns its child within itself and optionally sizes itself
289 /// based on the child's size. 275 /// based on the child's size.
290 class Align extends SingleChildWidget { 276 class Align extends SingleChildWidget {
291 - Align(  
292 - {this.alignment = Alignment.center,  
293 - this.widthFactor,  
294 - this.heightFactor,  
295 - Widget? child}) 277 + Align({this.alignment = Alignment.center, this.widthFactor, this.heightFactor, Widget? child})
296 : assert(widthFactor == null || widthFactor >= 0.0), 278 : assert(widthFactor == null || widthFactor >= 0.0),
297 assert(heightFactor == null || heightFactor >= 0.0), 279 assert(heightFactor == null || heightFactor >= 0.0),
298 super(child: child); 280 super(child: child);
@@ -307,30 +289,22 @@ class Align extends SingleChildWidget { @@ -307,30 +289,22 @@ class Align extends SingleChildWidget {
307 final double? heightFactor; 289 final double? heightFactor;
308 290
309 @override 291 @override
310 - void layout(Context context, BoxConstraints constraints,  
311 - {bool parentUsesSize = false}) {  
312 - final shrinkWrapWidth =  
313 - widthFactor != null || constraints.maxWidth == double.infinity;  
314 - final shrinkWrapHeight =  
315 - heightFactor != null || constraints.maxHeight == double.infinity; 292 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
  293 + final shrinkWrapWidth = widthFactor != null || constraints.maxWidth == double.infinity;
  294 + final shrinkWrapHeight = heightFactor != null || constraints.maxHeight == double.infinity;
316 295
317 if (child != null) { 296 if (child != null) {
318 child!.layout(context, constraints.loosen(), parentUsesSize: true); 297 child!.layout(context, constraints.loosen(), parentUsesSize: true);
319 assert(child!.box != null); 298 assert(child!.box != null);
320 299
321 box = constraints.constrainRect( 300 box = constraints.constrainRect(
322 - width: shrinkWrapWidth  
323 - ? child!.box!.width * (widthFactor ?? 1.0)  
324 - : double.infinity,  
325 - height: shrinkWrapHeight  
326 - ? child!.box!.height * (heightFactor ?? 1.0)  
327 - : double.infinity); 301 + width: shrinkWrapWidth ? child!.box!.width * (widthFactor ?? 1.0) : double.infinity,
  302 + height: shrinkWrapHeight ? child!.box!.height * (heightFactor ?? 1.0) : double.infinity);
328 final resolvedAlignment = alignment.resolve(Directionality.of(context)); 303 final resolvedAlignment = alignment.resolve(Directionality.of(context));
329 child!.box = resolvedAlignment.inscribe(child!.box!.size, box!); 304 child!.box = resolvedAlignment.inscribe(child!.box!.size, box!);
330 } else { 305 } else {
331 box = constraints.constrainRect( 306 box = constraints.constrainRect(
332 - width: shrinkWrapWidth ? 0.0 : double.infinity,  
333 - height: shrinkWrapHeight ? 0.0 : double.infinity); 307 + width: shrinkWrapWidth ? 0.0 : double.infinity, height: shrinkWrapHeight ? 0.0 : double.infinity);
334 } 308 }
335 } 309 }
336 310
@@ -353,58 +327,40 @@ class Align extends SingleChildWidget { @@ -353,58 +327,40 @@ class Align extends SingleChildWidget {
353 box!.left + child!.box!.horizontalCenter, 327 box!.left + child!.box!.horizontalCenter,
354 box!.bottom, 328 box!.bottom,
355 ) 329 )
356 - ..lineTo(box!.left + child!.box!.horizontalCenter,  
357 - box!.bottom + child!.box!.bottom)  
358 - ..lineTo(box!.left + child!.box!.horizontalCenter - headSize,  
359 - box!.bottom + child!.box!.bottom - headSize)  
360 - ..moveTo(box!.left + child!.box!.horizontalCenter,  
361 - box!.bottom + child!.box!.bottom)  
362 - ..lineTo(box!.left + child!.box!.horizontalCenter + headSize,  
363 - box!.bottom + child!.box!.bottom - headSize); 330 + ..lineTo(box!.left + child!.box!.horizontalCenter, box!.bottom + child!.box!.bottom)
  331 + ..lineTo(box!.left + child!.box!.horizontalCenter - headSize, box!.bottom + child!.box!.bottom - headSize)
  332 + ..moveTo(box!.left + child!.box!.horizontalCenter, box!.bottom + child!.box!.bottom)
  333 + ..lineTo(box!.left + child!.box!.horizontalCenter + headSize, box!.bottom + child!.box!.bottom - headSize);
364 } 334 }
365 335
366 if (box!.bottom + child!.box!.top < box!.top) { 336 if (box!.bottom + child!.box!.top < box!.top) {
367 - final headSize =  
368 - math.min((box!.top - child!.box!.top - box!.bottom) * 0.2, 10); 337 + final headSize = math.min((box!.top - child!.box!.top - box!.bottom) * 0.2, 10);
369 context.canvas 338 context.canvas
370 ..moveTo(box!.left + child!.box!.horizontalCenter, box!.top) 339 ..moveTo(box!.left + child!.box!.horizontalCenter, box!.top)
371 - ..lineTo(box!.left + child!.box!.horizontalCenter,  
372 - box!.bottom + child!.box!.top)  
373 - ..lineTo(box!.left + child!.box!.horizontalCenter - headSize,  
374 - box!.bottom + child!.box!.top + headSize)  
375 - ..moveTo(box!.left + child!.box!.horizontalCenter,  
376 - box!.bottom + child!.box!.top)  
377 - ..lineTo(box!.left + child!.box!.horizontalCenter + headSize,  
378 - box!.bottom + child!.box!.top + headSize); 340 + ..lineTo(box!.left + child!.box!.horizontalCenter, box!.bottom + child!.box!.top)
  341 + ..lineTo(box!.left + child!.box!.horizontalCenter - headSize, box!.bottom + child!.box!.top + headSize)
  342 + ..moveTo(box!.left + child!.box!.horizontalCenter, box!.bottom + child!.box!.top)
  343 + ..lineTo(box!.left + child!.box!.horizontalCenter + headSize, box!.bottom + child!.box!.top + headSize);
379 } 344 }
380 345
381 if (child!.box!.left > 0) { 346 if (child!.box!.left > 0) {
382 final headSize = math.min(child!.box!.left * 0.2, 10); 347 final headSize = math.min(child!.box!.left * 0.2, 10);
383 context.canvas 348 context.canvas
384 ..moveTo(box!.left, box!.bottom + child!.box!.verticalCenter) 349 ..moveTo(box!.left, box!.bottom + child!.box!.verticalCenter)
385 - ..lineTo(box!.left + child!.box!.left,  
386 - box!.bottom + child!.box!.verticalCenter)  
387 - ..lineTo(box!.left + child!.box!.left - headSize,  
388 - box!.bottom + child!.box!.verticalCenter - headSize)  
389 - ..moveTo(box!.left + child!.box!.left,  
390 - box!.bottom + child!.box!.verticalCenter)  
391 - ..lineTo(box!.left + child!.box!.left - headSize,  
392 - box!.bottom + child!.box!.verticalCenter + headSize); 350 + ..lineTo(box!.left + child!.box!.left, box!.bottom + child!.box!.verticalCenter)
  351 + ..lineTo(box!.left + child!.box!.left - headSize, box!.bottom + child!.box!.verticalCenter - headSize)
  352 + ..moveTo(box!.left + child!.box!.left, box!.bottom + child!.box!.verticalCenter)
  353 + ..lineTo(box!.left + child!.box!.left - headSize, box!.bottom + child!.box!.verticalCenter + headSize);
393 } 354 }
394 355
395 if (box!.left + child!.box!.right < box!.right) { 356 if (box!.left + child!.box!.right < box!.right) {
396 - final headSize =  
397 - math.min((box!.right - child!.box!.right - box!.left) * 0.2, 10); 357 + final headSize = math.min((box!.right - child!.box!.right - box!.left) * 0.2, 10);
398 context.canvas 358 context.canvas
399 ..moveTo(box!.right, box!.bottom + child!.box!.verticalCenter) 359 ..moveTo(box!.right, box!.bottom + child!.box!.verticalCenter)
400 - ..lineTo(box!.left + child!.box!.right,  
401 - box!.bottom + child!.box!.verticalCenter)  
402 - ..lineTo(box!.left + child!.box!.right + headSize,  
403 - box!.bottom + child!.box!.verticalCenter - headSize)  
404 - ..moveTo(box!.left + child!.box!.right,  
405 - box!.bottom + child!.box!.verticalCenter)  
406 - ..lineTo(box!.left + child!.box!.right + headSize,  
407 - box!.bottom + child!.box!.verticalCenter + headSize); 360 + ..lineTo(box!.left + child!.box!.right, box!.bottom + child!.box!.verticalCenter)
  361 + ..lineTo(box!.left + child!.box!.right + headSize, box!.bottom + child!.box!.verticalCenter - headSize)
  362 + ..moveTo(box!.left + child!.box!.right, box!.bottom + child!.box!.verticalCenter)
  363 + ..lineTo(box!.left + child!.box!.right + headSize, box!.bottom + child!.box!.verticalCenter + headSize);
408 } 364 }
409 365
410 context.canvas.strokePath(); 366 context.canvas.strokePath();
@@ -419,23 +375,19 @@ class Align extends SingleChildWidget { @@ -419,23 +375,19 @@ class Align extends SingleChildWidget {
419 375
420 /// A widget that imposes additional constraints on its child. 376 /// A widget that imposes additional constraints on its child.
421 class ConstrainedBox extends SingleChildWidget { 377 class ConstrainedBox extends SingleChildWidget {
422 - ConstrainedBox({required this.constraints, Widget? child})  
423 - : super(child: child); 378 + ConstrainedBox({required this.constraints, Widget? child}) : super(child: child);
424 379
425 /// The additional constraints to impose on the child. 380 /// The additional constraints to impose on the child.
426 final BoxConstraints constraints; 381 final BoxConstraints constraints;
427 382
428 @override 383 @override
429 - void layout(Context context, BoxConstraints constraints,  
430 - {bool parentUsesSize = false}) { 384 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
431 if (child != null) { 385 if (child != null) {
432 - child!.layout(context, this.constraints.enforce(constraints),  
433 - parentUsesSize: true); 386 + child!.layout(context, this.constraints.enforce(constraints), parentUsesSize: true);
434 assert(child!.box != null); 387 assert(child!.box != null);
435 box = child!.box; 388 box = child!.box;
436 } else { 389 } else {
437 - box = PdfRect.fromPoints(  
438 - PdfPoint.zero, this.constraints.enforce(constraints).smallest); 390 + box = PdfRect.fromPoints(PdfPoint.zero, this.constraints.enforce(constraints).smallest);
439 } 391 }
440 } 392 }
441 393
@@ -448,8 +400,7 @@ class ConstrainedBox extends SingleChildWidget { @@ -448,8 +400,7 @@ class ConstrainedBox extends SingleChildWidget {
448 400
449 class Center extends Align { 401 class Center extends Align {
450 Center({double? widthFactor, double? heightFactor, Widget? child}) 402 Center({double? widthFactor, double? heightFactor, Widget? child})
451 - : super(  
452 - widthFactor: widthFactor, heightFactor: heightFactor, child: child); 403 + : super(widthFactor: widthFactor, heightFactor: heightFactor, child: child);
453 } 404 }
454 405
455 /// Scales and positions its child within itself according to [fit]. 406 /// Scales and positions its child within itself according to [fit].
@@ -464,17 +415,15 @@ class FittedBox extends SingleChildWidget { @@ -464,17 +415,15 @@ class FittedBox extends SingleChildWidget {
464 final BoxFit fit; 415 final BoxFit fit;
465 416
466 /// How to align the child within its parent's bounds. 417 /// How to align the child within its parent's bounds.
467 - final Alignment alignment; 418 + final AlignmentGeometry alignment;
468 419
469 @override 420 @override
470 - void layout(Context context, BoxConstraints constraints,  
471 - {bool parentUsesSize = false}) { 421 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
472 PdfPoint size; 422 PdfPoint size;
473 if (child != null) { 423 if (child != null) {
474 child!.layout(context, const BoxConstraints(), parentUsesSize: true); 424 child!.layout(context, const BoxConstraints(), parentUsesSize: true);
475 assert(child!.box != null); 425 assert(child!.box != null);
476 - size = constraints  
477 - .constrainSizeAndAttemptToPreserveAspectRatio(child!.box!.size); 426 + size = constraints.constrainSizeAndAttemptToPreserveAspectRatio(child!.box!.size);
478 } else { 427 } else {
479 size = constraints.smallest; 428 size = constraints.smallest;
480 } 429 }
@@ -486,16 +435,15 @@ class FittedBox extends SingleChildWidget { @@ -486,16 +435,15 @@ class FittedBox extends SingleChildWidget {
486 super.paint(context); 435 super.paint(context);
487 436
488 if (child != null) { 437 if (child != null) {
  438 + final resolvedAlignment = alignment.resolve(Directionality.of(context));
489 final childSize = child!.box!.size; 439 final childSize = child!.box!.size;
490 final sizes = applyBoxFit(fit, childSize, box!.size); 440 final sizes = applyBoxFit(fit, childSize, box!.size);
491 final scaleX = sizes.destination!.x / sizes.source!.x; 441 final scaleX = sizes.destination!.x / sizes.source!.x;
492 final scaleY = sizes.destination!.y / sizes.source!.y; 442 final scaleY = sizes.destination!.y / sizes.source!.y;
493 - final sourceRect = alignment.inscribe(  
494 - sizes.source!, PdfRect.fromPoints(PdfPoint.zero, childSize));  
495 - final destinationRect = alignment.inscribe(sizes.destination!, box!); 443 + final sourceRect = resolvedAlignment.inscribe(sizes.source!, PdfRect.fromPoints(PdfPoint.zero, childSize));
  444 + final destinationRect = resolvedAlignment.inscribe(sizes.destination!, box!);
496 445
497 - final mat =  
498 - Matrix4.translationValues(destinationRect.x, destinationRect.y, 0) 446 + final mat = Matrix4.translationValues(destinationRect.x, destinationRect.y, 0)
499 ..scale(scaleX, scaleY, 1) 447 ..scale(scaleX, scaleY, 1)
500 ..translate(-sourceRect.x, -sourceRect.y); 448 ..translate(-sourceRect.x, -sourceRect.y);
501 449
@@ -555,12 +503,10 @@ class AspectRatio extends SingleChildWidget { @@ -555,12 +503,10 @@ class AspectRatio extends SingleChildWidget {
555 } 503 }
556 504
557 @override 505 @override
558 - void layout(Context context, BoxConstraints constraints,  
559 - {bool parentUsesSize = false}) { 506 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
560 box = PdfRect.fromPoints(PdfPoint.zero, _applyAspectRatio(constraints)); 507 box = PdfRect.fromPoints(PdfPoint.zero, _applyAspectRatio(constraints));
561 if (child != null) { 508 if (child != null) {
562 - child!.layout(context,  
563 - BoxConstraints.tightFor(width: box!.width, height: box!.height)); 509 + child!.layout(context, BoxConstraints.tightFor(width: box!.width, height: box!.height));
564 } 510 }
565 assert(child!.box != null); 511 assert(child!.box != null);
566 } 512 }
@@ -587,8 +533,7 @@ class CustomPaint extends SingleChildWidget { @@ -587,8 +533,7 @@ class CustomPaint extends SingleChildWidget {
587 final PdfPoint size; 533 final PdfPoint size;
588 534
589 @override 535 @override
590 - void layout(Context context, BoxConstraints constraints,  
591 - {bool parentUsesSize = false}) { 536 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
592 if (child != null) { 537 if (child != null) {
593 child!.layout(context, constraints, parentUsesSize: parentUsesSize); 538 child!.layout(context, constraints, parentUsesSize: parentUsesSize);
594 assert(child!.box != null); 539 assert(child!.box != null);
@@ -655,9 +600,7 @@ class SizedBox extends StatelessWidget { @@ -655,9 +600,7 @@ class SizedBox extends StatelessWidget {
655 600
656 @override 601 @override
657 Widget build(Context context) { 602 Widget build(Context context) {
658 - return ConstrainedBox(  
659 - child: child,  
660 - constraints: BoxConstraints.tightFor(width: width, height: height)); 603 + return ConstrainedBox(child: child, constraints: BoxConstraints.tightFor(width: width, height: height));
661 } 604 }
662 } 605 }
663 606
@@ -680,8 +623,7 @@ class Builder extends StatelessWidget { @@ -680,8 +623,7 @@ class Builder extends StatelessWidget {
680 } 623 }
681 624
682 /// The signature of the [LayoutBuilder] builder function. 625 /// The signature of the [LayoutBuilder] builder function.
683 -typedef LayoutWidgetBuilder = Widget Function(  
684 - Context context, BoxConstraints? constraints); 626 +typedef LayoutWidgetBuilder = Widget Function(Context context, BoxConstraints? constraints);
685 627
686 /// Builds a widget tree that can depend on the parent widget's size. 628 /// Builds a widget tree that can depend on the parent widget's size.
687 class LayoutBuilder extends StatelessWidget { 629 class LayoutBuilder extends StatelessWidget {
@@ -696,8 +638,7 @@ class LayoutBuilder extends StatelessWidget { @@ -696,8 +638,7 @@ class LayoutBuilder extends StatelessWidget {
696 BoxConstraints? _constraints; 638 BoxConstraints? _constraints;
697 639
698 @override 640 @override
699 - void layout(Context context, BoxConstraints constraints,  
700 - {bool parentUsesSize = false}) { 641 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
701 _constraints = constraints; 642 _constraints = constraints;
702 super.layout(context, constraints); 643 super.layout(context, constraints);
703 } 644 }
@@ -744,8 +685,7 @@ class FullPage extends SingleChildWidget { @@ -744,8 +685,7 @@ class FullPage extends SingleChildWidget {
744 } 685 }
745 686
746 @override 687 @override
747 - void layout(Context context, BoxConstraints constraints,  
748 - {bool parentUsesSize = false}) { 688 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
749 final constraints = _getConstraints(context); 689 final constraints = _getConstraints(context);
750 690
751 if (child != null) { 691 if (child != null) {
@@ -937,7 +877,7 @@ class OverflowBox extends SingleChildWidget { @@ -937,7 +877,7 @@ class OverflowBox extends SingleChildWidget {
937 }) : super(child: child); 877 }) : super(child: child);
938 878
939 /// How to align the child. 879 /// How to align the child.
940 - final Alignment alignment; 880 + final AlignmentGeometry alignment;
941 881
942 /// The minimum width constraint to give the child. Set this to null (the 882 /// The minimum width constraint to give the child. Set this to null (the
943 /// default) to use the constraint from the parent instead. 883 /// default) to use the constraint from the parent instead.
@@ -965,15 +905,14 @@ class OverflowBox extends SingleChildWidget { @@ -965,15 +905,14 @@ class OverflowBox extends SingleChildWidget {
965 } 905 }
966 906
967 @override 907 @override
968 - void layout(Context context, BoxConstraints constraints,  
969 - {bool parentUsesSize = false}) { 908 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
970 box = PdfRect.fromPoints(PdfPoint.zero, constraints.smallest); 909 box = PdfRect.fromPoints(PdfPoint.zero, constraints.smallest);
971 910
972 if (child != null) { 911 if (child != null) {
973 - child!.layout(context, _getInnerConstraints(constraints),  
974 - parentUsesSize: true); 912 + child!.layout(context, _getInnerConstraints(constraints), parentUsesSize: true);
975 assert(child!.box != null); 913 assert(child!.box != null);
976 - child!.box = alignment.inscribe(child!.box!.size, box!); 914 + final resolvedAlignment = alignment.resolve(Directionality.of(context));
  915 + child!.box = resolvedAlignment.inscribe(child!.box!.size, box!);
977 } 916 }
978 } 917 }
979 918
@@ -330,9 +330,9 @@ class Footer extends StatelessWidget { @@ -330,9 +330,9 @@ class Footer extends StatelessWidget {
330 330
331 final Widget? trailing; 331 final Widget? trailing;
332 332
333 - final EdgeInsets? margin; 333 + final EdgeInsetsGeometry? margin;
334 334
335 - final EdgeInsets? padding; 335 + final EdgeInsetsGeometry? padding;
336 336
337 final BoxDecoration? decoration; 337 final BoxDecoration? decoration;
338 338
@@ -113,10 +113,10 @@ class LinearGradient extends Gradient { @@ -113,10 +113,10 @@ class LinearGradient extends Gradient {
113 }) : super(colors: colors, stops: stops); 113 }) : super(colors: colors, stops: stops);
114 114
115 /// The offset at which stop 0.0 of the gradient is placed. 115 /// The offset at which stop 0.0 of the gradient is placed.
116 - final Alignment begin; 116 + final AlignmentGeometry begin;
117 117
118 /// The offset at which stop 1.0 of the gradient is placed. 118 /// The offset at which stop 1.0 of the gradient is placed.
119 - final Alignment end; 119 + final AlignmentGeometry end;
120 120
121 /// How this gradient should tile the plane beyond in the region before 121 /// How this gradient should tile the plane beyond in the region before
122 final TileMode tileMode; 122 final TileMode tileMode;
@@ -134,7 +134,7 @@ class LinearGradient extends Gradient { @@ -134,7 +134,7 @@ class LinearGradient extends Gradient {
134 } 134 }
135 135
136 assert(stops == null || stops!.length == colors.length); 136 assert(stops == null || stops!.length == colors.length);
137 - 137 + final textDirection = Directionality.of(context);
138 context.canvas 138 context.canvas
139 ..saveContext() 139 ..saveContext()
140 ..clipPath() 140 ..clipPath()
@@ -148,8 +148,8 @@ class LinearGradient extends Gradient { @@ -148,8 +148,8 @@ class LinearGradient extends Gradient {
148 colors, 148 colors,
149 stops, 149 stops,
150 ), 150 ),
151 - start: begin.withinRect(box),  
152 - end: end.withinRect(box), 151 + start: begin.resolve(textDirection).withinRect(box),
  152 + end: end.resolve(textDirection).withinRect(box),
153 extendStart: true, 153 extendStart: true,
154 extendEnd: true, 154 extendEnd: true,
155 ), 155 ),
@@ -175,7 +175,7 @@ class RadialGradient extends Gradient { @@ -175,7 +175,7 @@ class RadialGradient extends Gradient {
175 }) : super(colors: colors, stops: stops); 175 }) : super(colors: colors, stops: stops);
176 176
177 /// The center of the gradient 177 /// The center of the gradient
178 - final Alignment center; 178 + final AlignmentGeometry center;
179 179
180 /// The radius of the gradient 180 /// The radius of the gradient
181 final double radius; 181 final double radius;
@@ -185,7 +185,7 @@ class RadialGradient extends Gradient { @@ -185,7 +185,7 @@ class RadialGradient extends Gradient {
185 final TileMode tileMode; 185 final TileMode tileMode;
186 186
187 /// The focal point of the gradient. 187 /// The focal point of the gradient.
188 - final Alignment? focal; 188 + final AlignmentGeometry? focal;
189 189
190 /// The radius of the focal point of the gradient. 190 /// The radius of the focal point of the gradient.
191 final double focalRadius; 191 final double focalRadius;
@@ -207,7 +207,7 @@ class RadialGradient extends Gradient { @@ -207,7 +207,7 @@ class RadialGradient extends Gradient {
207 final _focal = focal ?? center; 207 final _focal = focal ?? center;
208 208
209 final _radius = math.min(box.width, box.height); 209 final _radius = math.min(box.width, box.height);
210 - 210 + final textDirection = Directionality.of(context);
211 context.canvas 211 context.canvas
212 ..saveContext() 212 ..saveContext()
213 ..clipPath() 213 ..clipPath()
@@ -221,8 +221,8 @@ class RadialGradient extends Gradient { @@ -221,8 +221,8 @@ class RadialGradient extends Gradient {
221 colors, 221 colors,
222 stops, 222 stops,
223 ), 223 ),
224 - start: _focal.withinRect(box),  
225 - end: center.withinRect(box), 224 + start: _focal.resolve(textDirection).withinRect(box),
  225 + end: center.resolve(textDirection).withinRect(box),
226 radius0: focalRadius * _radius, 226 radius0: focalRadius * _radius,
227 radius1: radius * _radius, 227 radius1: radius * _radius,
228 extendStart: true, 228 extendStart: true,
@@ -227,7 +227,7 @@ class FlatButton extends SingleChildWidget with AnnotationAppearance { @@ -227,7 +227,7 @@ class FlatButton extends SingleChildWidget with AnnotationAppearance {
227 PdfColor color = PdfColors.blue, 227 PdfColor color = PdfColors.blue,
228 PdfColor colorDown = PdfColors.red, 228 PdfColor colorDown = PdfColors.red,
229 PdfColor colorRollover = PdfColors.blueAccent, 229 PdfColor colorRollover = PdfColors.blueAccent,
230 - EdgeInsets? padding, 230 + EdgeInsetsGeometry? padding,
231 BoxDecoration? decoration, 231 BoxDecoration? decoration,
232 this.flags, 232 this.flags,
233 required Widget child, 233 required Widget child,
@@ -59,13 +59,13 @@ class PageTheme { @@ -59,13 +59,13 @@ class PageTheme {
59 59
60 EdgeInsetsGeometry? get margin { 60 EdgeInsetsGeometry? get margin {
61 if (_margin != null) { 61 if (_margin != null) {
62 - final effectiveMargin = _margin!.resolve(textDirection); 62 + final resolvedMargin = _margin!.resolve(textDirection);
63 if (mustRotate) { 63 if (mustRotate) {
64 return EdgeInsets.fromLTRB( 64 return EdgeInsets.fromLTRB(
65 - effectiveMargin.bottom,  
66 - effectiveMargin.left,  
67 - effectiveMargin.top,  
68 - effectiveMargin.right, 65 + resolvedMargin.bottom,
  66 + resolvedMargin.left,
  67 + resolvedMargin.top,
  68 + resolvedMargin.right,
69 ); 69 );
70 } else { 70 } else {
71 return _margin; 71 return _margin;
@@ -40,8 +40,8 @@ mixin TableHelper { @@ -40,8 +40,8 @@ mixin TableHelper {
40 required List<List<dynamic>> data, 40 required List<List<dynamic>> data,
41 EdgeInsetsGeometry cellPadding = const EdgeInsets.all(5), 41 EdgeInsetsGeometry cellPadding = const EdgeInsets.all(5),
42 double cellHeight = 0, 42 double cellHeight = 0,
43 - Alignment cellAlignment = Alignment.topLeft,  
44 - Map<int, Alignment>? cellAlignments, 43 + AlignmentGeometry cellAlignment = Alignment.topLeft,
  44 + Map<int, AlignmentGeometry>? cellAlignments,
45 TextStyle? cellStyle, 45 TextStyle? cellStyle,
46 TextStyle? oddCellStyle, 46 TextStyle? oddCellStyle,
47 OnCellFormat? cellFormat, 47 OnCellFormat? cellFormat,
@@ -50,8 +50,8 @@ mixin TableHelper { @@ -50,8 +50,8 @@ mixin TableHelper {
50 List<dynamic>? headers, 50 List<dynamic>? headers,
51 EdgeInsetsGeometry? headerPadding, 51 EdgeInsetsGeometry? headerPadding,
52 double? headerHeight, 52 double? headerHeight,
53 - Alignment headerAlignment = Alignment.center,  
54 - Map<int, Alignment>? headerAlignments, 53 + AlignmentGeometry headerAlignment = Alignment.center,
  54 + Map<int, AlignmentGeometry>? headerAlignments,
55 TextStyle? headerStyle, 55 TextStyle? headerStyle,
56 OnCellFormat? headerFormat, 56 OnCellFormat? headerFormat,
57 TableBorder? border = const TableBorder( 57 TableBorder? border = const TableBorder(
@@ -120,14 +120,14 @@ mixin TableHelper { @@ -120,14 +120,14 @@ mixin TableHelper {
120 rowNum++; 120 rowNum++;
121 } 121 }
122 122
  123 + final textDirection = context == null ? TextDirection.ltr : Directionality.of(context);
123 for (final row in data) { 124 for (final row in data) {
124 final tableRow = <Widget>[]; 125 final tableRow = <Widget>[];
125 final isOdd = (rowNum - headerCount) % 2 != 0; 126 final isOdd = (rowNum - headerCount) % 2 != 0;
126 -  
127 if (rowNum < headerCount) { 127 if (rowNum < headerCount) {
128 for (final dynamic cell in row) { 128 for (final dynamic cell in row) {
129 final align = headerAlignments[tableRow.length] ?? headerAlignment; 129 final align = headerAlignments[tableRow.length] ?? headerAlignment;
130 - final textAlign = _textAlign(align); 130 + final textAlign = _textAlign(align.resolve(textDirection));
131 131
132 tableRow.add( 132 tableRow.add(
133 Container( 133 Container(
@@ -165,7 +165,7 @@ mixin TableHelper { @@ -165,7 +165,7 @@ mixin TableHelper {
165 ? cell.toString() 165 ? cell.toString()
166 : cellFormat(tableRow.length, cell), 166 : cellFormat(tableRow.length, cell),
167 style: isOdd ? oddCellStyle : cellStyle, 167 style: isOdd ? oddCellStyle : cellStyle,
168 - textAlign: _textAlign(align), 168 + textAlign: _textAlign(align.resolve(textDirection)),
169 textDirection: tableDirection, 169 textDirection: tableDirection,
170 ), 170 ),
171 ), 171 ),
@@ -32,7 +32,7 @@ import 'text_style.dart'; @@ -32,7 +32,7 @@ import 'text_style.dart';
32 import 'theme.dart'; 32 import 'theme.dart';
33 import 'widget.dart'; 33 import 'widget.dart';
34 34
35 -enum TextAlign { left, right, center, justify } 35 +enum TextAlign { left, right, start, end, center, justify }
36 36
37 enum TextDirection { ltr, rtl } 37 enum TextDirection { ltr, rtl }
38 38
@@ -83,8 +83,7 @@ abstract class _Span { @@ -83,8 +83,7 @@ abstract class _Span {
83 } 83 }
84 84
85 class _TextDecoration { 85 class _TextDecoration {
86 - _TextDecoration(this.style, this.annotation, this.startSpan, this.endSpan)  
87 - : assert(startSpan <= endSpan); 86 + _TextDecoration(this.style, this.annotation, this.startSpan, this.endSpan) : assert(startSpan <= endSpan);
88 87
89 static const double _space = -0.15; 88 static const double _space = -0.15;
90 89
@@ -104,8 +103,7 @@ class _TextDecoration { @@ -104,8 +103,7 @@ class _TextDecoration {
104 } 103 }
105 104
106 final x1 = spans[startSpan].offset.x + spans[startSpan].left; 105 final x1 = spans[startSpan].offset.x + spans[startSpan].left;
107 - final x2 =  
108 - spans[endSpan].offset.x + spans[endSpan].left + spans[endSpan].width; 106 + final x2 = spans[endSpan].offset.x + spans[endSpan].left + spans[endSpan].width;
109 var y1 = spans[startSpan].offset.y + spans[startSpan].top; 107 var y1 = spans[startSpan].offset.y + spans[startSpan].top;
110 var y2 = y1 + spans[startSpan].height; 108 var y2 = y1 + spans[startSpan].height;
111 109
@@ -120,8 +118,7 @@ class _TextDecoration { @@ -120,8 +118,7 @@ class _TextDecoration {
120 return _box; 118 return _box;
121 } 119 }
122 120
123 - _TextDecoration copyWith({int? endSpan}) =>  
124 - _TextDecoration(style, annotation, startSpan, endSpan ?? this.endSpan); 121 + _TextDecoration copyWith({int? endSpan}) => _TextDecoration(style, annotation, startSpan, endSpan ?? this.endSpan);
125 122
126 void backgroundPaint( 123 void backgroundPaint(
127 Context context, 124 Context context,
@@ -166,15 +163,11 @@ class _TextDecoration { @@ -166,15 +163,11 @@ class _TextDecoration {
166 final box = _getBox(spans); 163 final box = _getBox(spans);
167 164
168 final font = style.font!.getFont(context); 165 final font = style.font!.getFont(context);
169 - final space =  
170 - _space * style.fontSize! * textScaleFactor * style.decorationThickness!; 166 + final space = _space * style.fontSize! * textScaleFactor * style.decorationThickness!;
171 167
172 context.canvas 168 context.canvas
173 ..setStrokeColor(style.decorationColor ?? style.color) 169 ..setStrokeColor(style.decorationColor ?? style.color)
174 - ..setLineWidth(style.decorationThickness! *  
175 - style.fontSize! *  
176 - textScaleFactor *  
177 - 0.05); 170 + ..setLineWidth(style.decorationThickness! * style.fontSize! * textScaleFactor * 0.05);
178 171
179 if (style.decoration!.contains(TextDecoration.underline)) { 172 if (style.decoration!.contains(TextDecoration.underline)) {
180 final base = -font.descent * style.fontSize! * textScaleFactor / 2; 173 final base = -font.descent * style.fontSize! * textScaleFactor / 2;
@@ -247,8 +240,7 @@ class _TextDecoration { @@ -247,8 +240,7 @@ class _TextDecoration {
247 240
248 context.canvas 241 context.canvas
249 ..setLineWidth(.5) 242 ..setLineWidth(.5)
250 - ..drawRect(  
251 - globalBox.x + box.x, globalBox.top + box.y, box.width, box.height) 243 + ..drawRect(globalBox.x + box.x, globalBox.top + box.y, box.width, box.height)
252 ..setStrokeColor(PdfColors.yellow) 244 ..setStrokeColor(PdfColors.yellow)
253 ..strokePath(); 245 ..strokePath();
254 } 246 }
@@ -310,14 +302,11 @@ class _Word extends _Span { @@ -310,14 +302,11 @@ class _Word extends _Span {
310 302
311 context.canvas 303 context.canvas
312 ..setLineWidth(.5) 304 ..setLineWidth(.5)
313 - ..drawRect(globalBox!.x + offset.x + metrics.left,  
314 - globalBox.top + offset.y + metrics.top, metrics.width, metrics.height) 305 + ..drawRect(
  306 + globalBox!.x + offset.x + metrics.left, globalBox.top + offset.y + metrics.top, metrics.width, metrics.height)
315 ..setStrokeColor(PdfColors.orange) 307 ..setStrokeColor(PdfColors.orange)
316 ..strokePath() 308 ..strokePath()
317 - ..drawLine(  
318 - globalBox.x + offset.x - deb,  
319 - globalBox.top + offset.y,  
320 - globalBox.x + offset.x + metrics.right + deb, 309 + ..drawLine(globalBox.x + offset.x - deb, globalBox.top + offset.y, globalBox.x + offset.x + metrics.right + deb,
321 globalBox.top + offset.y) 310 globalBox.top + offset.y)
322 ..setStrokeColor(PdfColors.deepPurple) 311 ..setStrokeColor(PdfColors.deepPurple)
323 ..strokePath(); 312 ..strokePath();
@@ -363,10 +352,8 @@ class _WidgetSpan extends _Span { @@ -363,10 +352,8 @@ class _WidgetSpan extends _Span {
363 double textScaleFactor, 352 double textScaleFactor,
364 PdfPoint point, 353 PdfPoint point,
365 ) { 354 ) {
366 - widget.box = PdfRect.fromPoints(  
367 - PdfPoint(  
368 - point.x + widget.box!.offset.x, point.y + widget.box!.offset.y),  
369 - widget.box!.size); 355 + widget.box =
  356 + PdfRect.fromPoints(PdfPoint(point.x + widget.box!.offset.x, point.y + widget.box!.offset.y), widget.box!.size);
370 widget.paint(context); 357 widget.paint(context);
371 } 358 }
372 359
@@ -380,8 +367,7 @@ class _WidgetSpan extends _Span { @@ -380,8 +367,7 @@ class _WidgetSpan extends _Span {
380 367
381 context.canvas 368 context.canvas
382 ..setLineWidth(.5) 369 ..setLineWidth(.5)
383 - ..drawRect(  
384 - globalBox!.x + offset.x, globalBox.top + offset.y, width, height) 370 + ..drawRect(globalBox!.x + offset.x, globalBox.top + offset.y, width, height)
385 ..setStrokeColor(PdfColors.orange) 371 ..setStrokeColor(PdfColors.orange)
386 ..strokePath() 372 ..strokePath()
387 ..drawLine( 373 ..drawLine(
@@ -564,14 +550,11 @@ class _Line { @@ -564,14 +550,11 @@ class _Line {
564 550
565 double get height { 551 double get height {
566 final list = parent._spans.sublist(firstSpan, lastSpan); 552 final list = parent._spans.sublist(firstSpan, lastSpan);
567 - return list.isEmpty  
568 - ? 0  
569 - : list.reduce((a, b) => a.height > b.height ? a : b).height; 553 + return list.isEmpty ? 0 : list.reduce((a, b) => a.height > b.height ? a : b).height;
570 } 554 }
571 555
572 @override 556 @override
573 - String toString() =>  
574 - '$runtimeType $firstSpan-$lastSpan baseline: $baseline width:$wordsWidth'; 557 + String toString() => '$runtimeType $firstSpan-$lastSpan baseline: $baseline width:$wordsWidth';
575 558
576 void realign(double totalWidth) { 559 void realign(double totalWidth) {
577 final spans = parent._spans.sublist(firstSpan, lastSpan); 560 final spans = parent._spans.sublist(firstSpan, lastSpan);
@@ -580,38 +563,43 @@ class _Line { @@ -580,38 +563,43 @@ class _Line {
580 var delta = 0.0; 563 var delta = 0.0;
581 switch (textAlign) { 564 switch (textAlign) {
582 case TextAlign.left: 565 case TextAlign.left:
583 - delta = isRTL ? totalWidth - wordsWidth : 0; 566 + delta = isRTL ? wordsWidth : 0;
584 break; 567 break;
585 case TextAlign.right: 568 case TextAlign.right:
586 - delta = isRTL ? 0 : totalWidth - wordsWidth; 569 + delta = totalWidth - wordsWidth;
  570 + break;
  571 + case TextAlign.start:
  572 + delta = isRTL ? totalWidth : 0;
  573 + break;
  574 + case TextAlign.end:
  575 + delta = isRTL ? wordsWidth : totalWidth - wordsWidth;
587 break; 576 break;
588 case TextAlign.center: 577 case TextAlign.center:
589 delta = (totalWidth - wordsWidth) / 2.0; 578 delta = (totalWidth - wordsWidth) / 2.0;
590 break; 579 break;
591 case TextAlign.justify: 580 case TextAlign.justify:
  581 + delta = isRTL ? totalWidth : 0;
592 if (!justify) { 582 if (!justify) {
593 break; 583 break;
594 } 584 }
595 585
596 - delta = (totalWidth - wordsWidth) / (spans.length - 1); 586 + final gap = (totalWidth - wordsWidth) / (spans.length - 1);
597 var x = 0.0; 587 var x = 0.0;
598 for (final span in spans) { 588 for (final span in spans) {
599 - if (isRTL) {  
600 - final xOffset = span.offset.x + span.width;  
601 - span.offset =  
602 - PdfPoint((totalWidth - xOffset) - x, span.offset.y - baseline);  
603 - } else {  
604 - span.offset = span.offset.translate(x, -baseline);  
605 - }  
606 - x += delta; 589 + span.offset = PdfPoint(
  590 + isRTL ? delta - x - (span.offset.x + span.width) : span.offset.x + x,
  591 + span.offset.y - baseline,
  592 + );
  593 + x += gap;
607 } 594 }
  595 +
608 return; 596 return;
609 } 597 }
610 598
611 if (isRTL) { 599 if (isRTL) {
612 for (final span in spans) { 600 for (final span in spans) {
613 span.offset = PdfPoint( 601 span.offset = PdfPoint(
614 - totalWidth - (span.offset.x + span.width) - delta, 602 + delta - (span.offset.x + span.width),
615 span.offset.y - baseline, 603 span.offset.y - baseline,
616 ); 604 );
617 } 605 }
@@ -621,8 +609,6 @@ class _Line { @@ -621,8 +609,6 @@ class _Line {
621 for (final span in spans) { 609 for (final span in spans) {
622 span.offset = span.offset.translate(delta, -baseline); 610 span.offset = span.offset.translate(delta, -baseline);
623 } 611 }
624 -  
625 - return;  
626 } 612 }
627 } 613 }
628 614
@@ -646,8 +632,7 @@ class RichTextContext extends WidgetContext { @@ -646,8 +632,7 @@ class RichTextContext extends WidgetContext {
646 } 632 }
647 633
648 @override 634 @override
649 - String toString() =>  
650 - '$runtimeType Offset: $startOffset -> $endOffset Span: $spanStart -> $spanEnd'; 635 + String toString() => '$runtimeType Offset: $startOffset -> $endOffset Span: $spanStart -> $spanEnd';
651 } 636 }
652 637
653 class RichText extends Widget with SpanningWidget { 638 class RichText extends Widget with SpanningWidget {
@@ -696,8 +681,7 @@ class RichText extends Widget with SpanningWidget { @@ -696,8 +681,7 @@ class RichText extends Widget with SpanningWidget {
696 if (append && _decorations.isNotEmpty) { 681 if (append && _decorations.isNotEmpty) {
697 final last = _decorations.last; 682 final last = _decorations.last;
698 if (last.style == td.style && last.annotation == td.annotation) { 683 if (last.style == td.style && last.annotation == td.annotation) {
699 - _decorations[_decorations.length - 1] =  
700 - last.copyWith(endSpan: td.endSpan); 684 + _decorations[_decorations.length - 1] = last.copyWith(endSpan: td.endSpan);
701 return; 685 return;
702 } 686 }
703 } 687 }
@@ -867,8 +851,7 @@ class RichText extends Widget with SpanningWidget { @@ -867,8 +851,7 @@ class RichText extends Widget with SpanningWidget {
867 } 851 }
868 852
869 @override 853 @override
870 - void layout(Context context, BoxConstraints constraints,  
871 - {bool parentUsesSize = false}) { 854 + void layout(Context context, BoxConstraints constraints, {bool parentUsesSize = false}) {
872 _spans.clear(); 855 _spans.clear();
873 _decorations.clear(); 856 _decorations.clear();
874 857
@@ -876,20 +859,12 @@ class RichText extends Widget with SpanningWidget { @@ -876,20 +859,12 @@ class RichText extends Widget with SpanningWidget {
876 final _softWrap = softWrap ?? theme.softWrap; 859 final _softWrap = softWrap ?? theme.softWrap;
877 final _maxLines = maxLines ?? theme.maxLines; 860 final _maxLines = maxLines ?? theme.maxLines;
878 final _textDirection = textDirection ?? Directionality.of(context); 861 final _textDirection = textDirection ?? Directionality.of(context);
879 - _textAlign = textAlign ??  
880 - theme.textAlign ??  
881 - (_textDirection == TextDirection.rtl  
882 - ? TextAlign.right  
883 - : TextAlign.left); 862 + _textAlign = textAlign ?? theme.textAlign ?? TextAlign.start;
884 863
885 final _overflow = this.overflow ?? theme.overflow; 864 final _overflow = this.overflow ?? theme.overflow;
886 865
887 - final constraintWidth = constraints.hasBoundedWidth  
888 - ? constraints.maxWidth  
889 - : constraints.constrainWidth();  
890 - final constraintHeight = constraints.hasBoundedHeight  
891 - ? constraints.maxHeight  
892 - : constraints.constrainHeight(); 866 + final constraintWidth = constraints.hasBoundedWidth ? constraints.maxWidth : constraints.constrainWidth();
  867 + final constraintHeight = constraints.hasBoundedHeight ? constraints.maxHeight : constraints.constrainHeight();
893 868
894 var offsetX = 0.0; 869 var offsetX = 0.0;
895 var offsetY = _context.startOffset; 870 var offsetY = _context.startOffset;
@@ -916,13 +891,10 @@ class RichText extends Widget with SpanningWidget { @@ -916,13 +891,10 @@ class RichText extends Widget with SpanningWidget {
916 891
917 final font = style!.font!.getFont(context); 892 final font = style!.font!.getFont(context);
918 893
919 - final space =  
920 - font.stringMetrics(' ') * (style.fontSize! * textScaleFactor); 894 + final space = font.stringMetrics(' ') * (style.fontSize! * textScaleFactor);
921 895
922 - final spanLines = (_textDirection == TextDirection.rtl  
923 - ? bidi.logicalToVisual(span.text!)  
924 - : span.text)!  
925 - .split('\n'); 896 + final spanLines =
  897 + (_textDirection == TextDirection.rtl ? bidi.logicalToVisual(span.text!) : span.text)!.split('\n');
926 898
927 for (var line = 0; line < spanLines.length; line++) { 899 for (var line = 0; line < spanLines.length; line++) {
928 final words = spanLines[line].split(RegExp(r'\s')); 900 final words = spanLines[line].split(RegExp(r'\s'));
@@ -930,18 +902,15 @@ class RichText extends Widget with SpanningWidget { @@ -930,18 +902,15 @@ class RichText extends Widget with SpanningWidget {
930 final word = words[index]; 902 final word = words[index];
931 903
932 if (word.isEmpty) { 904 if (word.isEmpty) {
933 - offsetX += space.advanceWidth * style.wordSpacing! +  
934 - style.letterSpacing!; 905 + offsetX += space.advanceWidth * style.wordSpacing! + style.letterSpacing!;
935 continue; 906 continue;
936 } 907 }
937 908
938 - final metrics = font.stringMetrics(word,  
939 - letterSpacing: style.letterSpacing! /  
940 - (style.fontSize! * textScaleFactor)) * 909 + final metrics =
  910 + font.stringMetrics(word, letterSpacing: style.letterSpacing! / (style.fontSize! * textScaleFactor)) *
941 (style.fontSize! * textScaleFactor); 911 (style.fontSize! * textScaleFactor);
942 912
943 - if (_softWrap &&  
944 - offsetX + metrics.width > constraintWidth + 0.00001) { 913 + if (_softWrap && offsetX + metrics.width > constraintWidth + 0.00001) {
945 if (spanCount > 0 && metrics.width <= constraintWidth) { 914 if (spanCount > 0 && metrics.width <= constraintWidth) {
946 overflow = true; 915 overflow = true;
947 lines.add(_Line( 916 lines.add(_Line(
@@ -949,9 +918,7 @@ class RichText extends Widget with SpanningWidget { @@ -949,9 +918,7 @@ class RichText extends Widget with SpanningWidget {
949 spanStart, 918 spanStart,
950 spanCount, 919 spanCount,
951 bottom, 920 bottom,
952 - offsetX -  
953 - space.advanceWidth * style.wordSpacing! -  
954 - style.letterSpacing!, 921 + offsetX - space.advanceWidth * style.wordSpacing! - style.letterSpacing!,
955 _textDirection, 922 _textDirection,
956 true, 923 true,
957 )); 924 ));
@@ -1013,9 +980,7 @@ class RichText extends Widget with SpanningWidget { @@ -1013,9 +980,7 @@ class RichText extends Widget with SpanningWidget {
1013 ), 980 ),
1014 ); 981 );
1015 982
1016 - offsetX += metrics.advanceWidth +  
1017 - space.advanceWidth * style.wordSpacing! +  
1018 - style.letterSpacing!; 983 + offsetX += metrics.advanceWidth + space.advanceWidth * style.wordSpacing! + style.letterSpacing!;
1019 } 984 }
1020 985
1021 if (line < spanLines.length - 1) { 986 if (line < spanLines.length - 1) {
@@ -1024,9 +989,7 @@ class RichText extends Widget with SpanningWidget { @@ -1024,9 +989,7 @@ class RichText extends Widget with SpanningWidget {
1024 spanStart, 989 spanStart,
1025 spanCount, 990 spanCount,
1026 bottom, 991 bottom,
1027 - offsetX -  
1028 - space.advanceWidth * style.wordSpacing! -  
1029 - style.letterSpacing!, 992 + offsetX - space.advanceWidth * style.wordSpacing! - style.letterSpacing!,
1030 _textDirection, 993 _textDirection,
1031 false, 994 false,
1032 )); 995 ));
@@ -1055,8 +1018,7 @@ class RichText extends Widget with SpanningWidget { @@ -1055,8 +1018,7 @@ class RichText extends Widget with SpanningWidget {
1055 } 1018 }
1056 } 1019 }
1057 1020
1058 - offsetX -=  
1059 - space.advanceWidth * style.wordSpacing! - style.letterSpacing!; 1021 + offsetX -= space.advanceWidth * style.wordSpacing! - style.letterSpacing!;
1060 } else if (span is WidgetSpan) { 1022 } else if (span is WidgetSpan) {
1061 span.child.layout( 1023 span.child.layout(
1062 context, 1024 context,
@@ -1159,8 +1121,7 @@ class RichText extends Widget with SpanningWidget { @@ -1159,8 +1121,7 @@ class RichText extends Widget with SpanningWidget {
1159 } 1121 }
1160 } 1122 }
1161 1123
1162 - box = PdfRect(0, 0, constraints.constrainWidth(width),  
1163 - constraints.constrainHeight(offsetY)); 1124 + box = PdfRect(0, 0, constraints.constrainWidth(width), constraints.constrainHeight(offsetY));
1164 1125
1165 _context 1126 _context
1166 ..endOffset = offsetY - _context.startOffset 1127 ..endOffset = offsetY - _context.startOffset
@@ -1180,8 +1141,7 @@ class RichText extends Widget with SpanningWidget { @@ -1180,8 +1141,7 @@ class RichText extends Widget with SpanningWidget {
1180 1141
1181 for (var index = 0; index < _decorations.length; index++) { 1142 for (var index = 0; index < _decorations.length; index++) {
1182 final decoration = _decorations[index]; 1143 final decoration = _decorations[index];
1183 - if (decoration.startSpan >= _context.spanEnd ||  
1184 - decoration.endSpan < _context.spanStart) { 1144 + if (decoration.startSpan >= _context.spanEnd || decoration.endSpan < _context.spanStart) {
1185 _decorations.removeAt(index); 1145 _decorations.removeAt(index);
1186 index--; 1146 index--;
1187 } 1147 }
@@ -1276,8 +1236,7 @@ class RichText extends Widget with SpanningWidget { @@ -1276,8 +1236,7 @@ class RichText extends Widget with SpanningWidget {
1276 1236
1277 while (low + 1 < high) { 1237 while (low + 1 < high) {
1278 final metrics = font.stringMetrics(word.substring(0, pos), 1238 final metrics = font.stringMetrics(word.substring(0, pos),
1279 - letterSpacing:  
1280 - style.letterSpacing! / (style.fontSize! * textScaleFactor)) * 1239 + letterSpacing: style.letterSpacing! / (style.fontSize! * textScaleFactor)) *
1281 (style.fontSize! * textScaleFactor); 1240 (style.fontSize! * textScaleFactor);
1282 1241
1283 if (metrics.width > maxWidth) { 1242 if (metrics.width > maxWidth) {
@@ -18,6 +18,7 @@ import 'dart:collection'; @@ -18,6 +18,7 @@ import 'dart:collection';
18 import 'dart:math' as math; 18 import 'dart:math' as math;
19 19
20 import 'package:meta/meta.dart'; 20 import 'package:meta/meta.dart';
  21 +import 'package:pdf/widgets.dart';
21 import 'package:vector_math/vector_math_64.dart'; 22 import 'package:vector_math/vector_math_64.dart';
22 23
23 import '../../pdf.dart'; 24 import '../../pdf.dart';
@@ -146,7 +147,7 @@ abstract class Widget { @@ -146,7 +147,7 @@ abstract class Widget {
146 PdfGraphics? canvas, 147 PdfGraphics? canvas,
147 BoxConstraints? constraints, 148 BoxConstraints? constraints,
148 required PdfPoint offset, 149 required PdfPoint offset,
149 - Alignment? alignment, 150 + AlignmentGeometry? alignment,
150 Context? context, 151 Context? context,
151 }) { 152 }) {
152 context ??= Context( 153 context ??= Context(
@@ -165,7 +166,8 @@ abstract class Widget { @@ -165,7 +166,8 @@ abstract class Widget {
165 assert(widget.box != null); 166 assert(widget.box != null);
166 167
167 if (alignment != null) { 168 if (alignment != null) {
168 - final d = alignment.withinRect(widget.box!); 169 + final resolvedAlignment = alignment.resolve(Directionality.of(context));
  170 + final d = resolvedAlignment.withinRect(widget.box!);
169 offset = PdfPoint(offset.x - d.x, offset.y - d.y); 171 offset = PdfPoint(offset.x - d.x, offset.y - d.y);
170 } 172 }
171 173
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 16
17 import 'dart:io'; 17 import 'dart:io';
  18 +import 'dart:typed_data';
18 19
19 import 'package:pdf/pdf.dart'; 20 import 'package:pdf/pdf.dart';
20 import 'package:pdf/widgets.dart'; 21 import 'package:pdf/widgets.dart';
@@ -41,9 +42,29 @@ final _yellowBox = Container( @@ -41,9 +42,29 @@ final _yellowBox = Container(
41 ); 42 );
42 43
43 void main() { 44 void main() {
  45 + late final arabicFont;
44 setUpAll(() { 46 setUpAll(() {
45 Document.debug = true; 47 Document.debug = true;
46 pdf = Document(); 48 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 + });
  53 +
  54 + test('Should render Text aligned right', () {
  55 + pdf.addPage(
  56 + Page(
  57 + textDirection: TextDirection.rtl,
  58 + pageFormat: const PdfPageFormat(150, 50),
  59 + build: (Context context) => SizedBox(
  60 + width: 150,
  61 + child: Text(
  62 + 'مرحبا بالعالم',
  63 + style: TextStyle(font: arabicFont),
  64 + ),
  65 + ),
  66 + ),
  67 + );
47 }); 68 });
48 69
49 test('Should render a blue box followed by a red box ordered RTL aligned right', () { 70 test('Should render a blue box followed by a red box ordered RTL aligned right', () {
@@ -51,8 +72,7 @@ void main() { @@ -51,8 +72,7 @@ void main() {
51 Page( 72 Page(
52 textDirection: TextDirection.rtl, 73 textDirection: TextDirection.rtl,
53 pageFormat: const PdfPageFormat(150, 50), 74 pageFormat: const PdfPageFormat(150, 50),
54 - build: (Context context) =>  
55 - TestAnnotation( 75 + build: (Context context) => TestAnnotation(
56 anno: 'RTL Row', 76 anno: 'RTL Row',
57 child: Row( 77 child: Row(
58 children: [_blueBox, _redBox], 78 children: [_blueBox, _redBox],
@@ -67,8 +87,7 @@ void main() { @@ -67,8 +87,7 @@ void main() {
67 Page( 87 Page(
68 textDirection: TextDirection.rtl, 88 textDirection: TextDirection.rtl,
69 pageFormat: const PdfPageFormat(150, 50), 89 pageFormat: const PdfPageFormat(150, 50),
70 - build: (Context context) =>  
71 - TestAnnotation( 90 + build: (Context context) => TestAnnotation(
72 anno: 'RTL Row MainAlignment.center', 91 anno: 'RTL Row MainAlignment.center',
73 child: Row( 92 child: Row(
74 mainAxisAlignment: MainAxisAlignment.center, 93 mainAxisAlignment: MainAxisAlignment.center,
@@ -84,8 +103,7 @@ void main() { @@ -84,8 +103,7 @@ void main() {
84 Page( 103 Page(
85 pageFormat: const PdfPageFormat(150, 100), 104 pageFormat: const PdfPageFormat(150, 100),
86 textDirection: TextDirection.rtl, 105 textDirection: TextDirection.rtl,
87 - build: (Context context) =>  
88 - TestAnnotation( 106 + build: (Context context) => TestAnnotation(
89 anno: 'RTL Row CrossAlignment.end', 107 anno: 'RTL Row CrossAlignment.end',
90 child: SizedBox( 108 child: SizedBox(
91 width: 150, 109 width: 150,
@@ -103,8 +121,7 @@ void main() { @@ -103,8 +121,7 @@ void main() {
103 pdf.addPage( 121 pdf.addPage(
104 Page( 122 Page(
105 pageFormat: const PdfPageFormat(150, 50), 123 pageFormat: const PdfPageFormat(150, 50),
106 - build: (Context context) =>  
107 - TestAnnotation( 124 + build: (Context context) => TestAnnotation(
108 anno: 'LTR Row', 125 anno: 'LTR Row',
109 child: Row( 126 child: Row(
110 children: [_blueBox, _redBox], 127 children: [_blueBox, _redBox],
@@ -118,8 +135,7 @@ void main() { @@ -118,8 +135,7 @@ void main() {
118 Page( 135 Page(
119 textDirection: TextDirection.rtl, 136 textDirection: TextDirection.rtl,
120 pageFormat: const PdfPageFormat(150, 150), 137 pageFormat: const PdfPageFormat(150, 150),
121 - build: (Context context) =>  
122 - TestAnnotation( 138 + build: (Context context) => TestAnnotation(
123 anno: 'RTL Column crossAlignment.start', 139 anno: 'RTL Column crossAlignment.start',
124 child: SizedBox( 140 child: SizedBox(
125 width: 150, 141 width: 150,
@@ -138,8 +154,7 @@ void main() { @@ -138,8 +154,7 @@ void main() {
138 Page( 154 Page(
139 textDirection: TextDirection.ltr, 155 textDirection: TextDirection.ltr,
140 pageFormat: const PdfPageFormat(150, 150), 156 pageFormat: const PdfPageFormat(150, 150),
141 - build: (Context context) =>  
142 - TestAnnotation( 157 + build: (Context context) => TestAnnotation(
143 anno: 'LTR Column crossAlignment.start', 158 anno: 'LTR Column crossAlignment.start',
144 child: SizedBox( 159 child: SizedBox(
145 width: 150, 160 width: 150,
@@ -159,8 +174,7 @@ void main() { @@ -159,8 +174,7 @@ void main() {
159 Page( 174 Page(
160 textDirection: TextDirection.rtl, 175 textDirection: TextDirection.rtl,
161 pageFormat: const PdfPageFormat(150, 150), 176 pageFormat: const PdfPageFormat(150, 150),
162 - build: (Context context) =>  
163 - TestAnnotation( 177 + build: (Context context) => TestAnnotation(
164 anno: 'RTL Wrap', 178 anno: 'RTL Wrap',
165 child: SizedBox( 179 child: SizedBox(
166 width: 150, 180 width: 150,
@@ -179,8 +193,7 @@ void main() { @@ -179,8 +193,7 @@ void main() {
179 Page( 193 Page(
180 textDirection: TextDirection.ltr, 194 textDirection: TextDirection.ltr,
181 pageFormat: const PdfPageFormat(150, 150), 195 pageFormat: const PdfPageFormat(150, 150),
182 - build: (Context context) =>  
183 - TestAnnotation( 196 + build: (Context context) => TestAnnotation(
184 anno: 'LTR Wrap', 197 anno: 'LTR Wrap',
185 child: SizedBox( 198 child: SizedBox(
186 width: 150, 199 width: 150,
@@ -198,8 +211,7 @@ void main() { @@ -198,8 +211,7 @@ void main() {
198 Page( 211 Page(
199 textDirection: TextDirection.rtl, 212 textDirection: TextDirection.rtl,
200 pageFormat: const PdfPageFormat(150, 150), 213 pageFormat: const PdfPageFormat(150, 150),
201 - build: (Context context) =>  
202 - TestAnnotation( 214 + build: (Context context) => TestAnnotation(
203 anno: 'RTL Wrap WrapAlignment.center', 215 anno: 'RTL Wrap WrapAlignment.center',
204 child: SizedBox( 216 child: SizedBox(
205 width: 150, 217 width: 150,
@@ -221,8 +233,7 @@ void main() { @@ -221,8 +233,7 @@ void main() {
221 Page( 233 Page(
222 textDirection: TextDirection.rtl, 234 textDirection: TextDirection.rtl,
223 pageFormat: const PdfPageFormat(150, 150), 235 pageFormat: const PdfPageFormat(150, 150),
224 - build: (Context context) =>  
225 - TestAnnotation( 236 + build: (Context context) => TestAnnotation(
226 anno: 'RTL Wrap WrapAlignment.end', 237 anno: 'RTL Wrap WrapAlignment.end',
227 child: SizedBox( 238 child: SizedBox(
228 width: 150, 239 width: 150,
@@ -529,7 +540,9 @@ void main() { @@ -529,7 +540,9 @@ void main() {
529 textDirection: TextDirection.rtl, 540 textDirection: TextDirection.rtl,
530 pageFormat: const PdfPageFormat(150, 150), 541 pageFormat: const PdfPageFormat(150, 150),
531 build: (Context context) { 542 build: (Context context) {
532 - return TestAnnotation(anno: 'RTL GridView Axis.horizontal', child: GridView( 543 + return TestAnnotation(
  544 + anno: 'RTL GridView Axis.horizontal',
  545 + child: GridView(
533 crossAxisCount: 3, 546 crossAxisCount: 3,
534 childAspectRatio: 1, 547 childAspectRatio: 1,
535 direction: Axis.horizontal, 548 direction: Axis.horizontal,
@@ -539,7 +552,8 @@ void main() { @@ -539,7 +552,8 @@ void main() {
539 color: [PdfColors.blue, PdfColors.red, PdfColors.yellow][i % 3], 552 color: [PdfColors.blue, PdfColors.red, PdfColors.yellow][i % 3],
540 ), 553 ),
541 ], 554 ],
542 - ),); 555 + ),
  556 + );
543 }, 557 },
544 ), 558 ),
545 ); 559 );
@@ -551,7 +565,9 @@ void main() { @@ -551,7 +565,9 @@ void main() {
551 textDirection: TextDirection.ltr, 565 textDirection: TextDirection.ltr,
552 pageFormat: const PdfPageFormat(150, 150), 566 pageFormat: const PdfPageFormat(150, 150),
553 build: (Context context) { 567 build: (Context context) {
554 - return TestAnnotation(anno: 'LTR GridView Axis.horizontal', child: GridView( 568 + return TestAnnotation(
  569 + anno: 'LTR GridView Axis.horizontal',
  570 + child: GridView(
555 crossAxisCount: 3, 571 crossAxisCount: 3,
556 childAspectRatio: 1, 572 childAspectRatio: 1,
557 direction: Axis.horizontal, 573 direction: Axis.horizontal,
@@ -561,7 +577,8 @@ void main() { @@ -561,7 +577,8 @@ void main() {
561 color: [PdfColors.blue, PdfColors.red, PdfColors.yellow][i % 3], 577 color: [PdfColors.blue, PdfColors.red, PdfColors.yellow][i % 3],
562 ), 578 ),
563 ], 579 ],
564 - ),); 580 + ),
  581 + );
565 }, 582 },
566 ), 583 ),
567 ); 584 );