Showing
7 changed files
with
177 additions
and
49 deletions
| @@ -158,7 +158,8 @@ class Invoice { | @@ -158,7 +158,8 @@ class Invoice { | ||
| 158 | ), | 158 | ), |
| 159 | pw.Container( | 159 | pw.Container( |
| 160 | decoration: pw.BoxDecoration( | 160 | decoration: pw.BoxDecoration( |
| 161 | - borderRadius: 2, | 161 | + borderRadiusEx: |
| 162 | + pw.BorderRadius.all(pw.Radius.circular(2)), | ||
| 162 | color: accentColor, | 163 | color: accentColor, |
| 163 | ), | 164 | ), |
| 164 | padding: const pw.EdgeInsets.only( | 165 | padding: const pw.EdgeInsets.only( |
| @@ -497,7 +498,7 @@ class Invoice { | @@ -497,7 +498,7 @@ class Invoice { | ||
| 497 | border: null, | 498 | border: null, |
| 498 | cellAlignment: pw.Alignment.centerLeft, | 499 | cellAlignment: pw.Alignment.centerLeft, |
| 499 | headerDecoration: pw.BoxDecoration( | 500 | headerDecoration: pw.BoxDecoration( |
| 500 | - borderRadius: 2, | 501 | + borderRadiusEx: pw.BorderRadius.all(pw.Radius.circular(2)), |
| 501 | color: baseColor, | 502 | color: baseColor, |
| 502 | ), | 503 | ), |
| 503 | headerHeight: 25, | 504 | headerHeight: 25, |
| @@ -262,7 +262,10 @@ class _Category extends pw.StatelessWidget { | @@ -262,7 +262,10 @@ class _Category extends pw.StatelessWidget { | ||
| 262 | @override | 262 | @override |
| 263 | pw.Widget build(pw.Context context) { | 263 | pw.Widget build(pw.Context context) { |
| 264 | return pw.Container( | 264 | return pw.Container( |
| 265 | - decoration: const pw.BoxDecoration(color: lightGreen, borderRadius: 6), | 265 | + decoration: const pw.BoxDecoration( |
| 266 | + color: lightGreen, | ||
| 267 | + borderRadiusEx: pw.BorderRadius.all(pw.Radius.circular(6)), | ||
| 268 | + ), | ||
| 266 | margin: const pw.EdgeInsets.only(bottom: 10, top: 20), | 269 | margin: const pw.EdgeInsets.only(bottom: 10, top: 20), |
| 267 | padding: const pw.EdgeInsets.fromLTRB(10, 7, 10, 4), | 270 | padding: const pw.EdgeInsets.fromLTRB(10, 7, 10, 4), |
| 268 | child: pw.Text(title, textScaleFactor: 1.5)); | 271 | child: pw.Text(title, textScaleFactor: 1.5)); |
| @@ -130,7 +130,7 @@ class BoxBorder { | @@ -130,7 +130,7 @@ class BoxBorder { | ||
| 130 | ..strokePath(); | 130 | ..strokePath(); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | - void paintRRect(Context context, PdfRect box, double borderRadius) { | 133 | + void paintRRect(Context context, PdfRect box, BorderRadius borderRadius) { |
| 134 | assert(box.x != null); | 134 | assert(box.x != null); |
| 135 | assert(box.y != null); | 135 | assert(box.y != null); |
| 136 | assert(box.width != null); | 136 | assert(box.width != null); |
| @@ -138,10 +138,9 @@ class BoxBorder { | @@ -138,10 +138,9 @@ class BoxBorder { | ||
| 138 | 138 | ||
| 139 | context.canvas | 139 | context.canvas |
| 140 | ..setStrokeColor(color) | 140 | ..setStrokeColor(color) |
| 141 | - ..setLineWidth(width) | ||
| 142 | - ..drawRRect( | ||
| 143 | - box.x, box.y, box.width, box.height, borderRadius, borderRadius) | ||
| 144 | - ..strokePath(); | 141 | + ..setLineWidth(width); |
| 142 | + borderRadius.paint(context, box); | ||
| 143 | + context.canvas.strokePath(); | ||
| 145 | } | 144 | } |
| 146 | } | 145 | } |
| 147 | 146 | ||
| @@ -408,26 +407,6 @@ class BoxShadow { | @@ -408,26 +407,6 @@ class BoxShadow { | ||
| 408 | return shadow; | 407 | return shadow; |
| 409 | } | 408 | } |
| 410 | 409 | ||
| 411 | - im.Image _rRect(double width, double height, double rv, double rh) { | ||
| 412 | - final im.Image shadow = im.Image( | ||
| 413 | - (width + spreadRadius * 2).round(), | ||
| 414 | - (height + spreadRadius * 2).round(), | ||
| 415 | - ); | ||
| 416 | - | ||
| 417 | - im.fillRect( | ||
| 418 | - shadow, | ||
| 419 | - spreadRadius.round(), | ||
| 420 | - spreadRadius.round(), | ||
| 421 | - (spreadRadius + width).round(), | ||
| 422 | - (spreadRadius + height).round(), | ||
| 423 | - color.toInt(), | ||
| 424 | - ); | ||
| 425 | - | ||
| 426 | - im.gaussianBlur(shadow, blurRadius.round()); | ||
| 427 | - | ||
| 428 | - return shadow; | ||
| 429 | - } | ||
| 430 | - | ||
| 431 | im.Image _ellipse(double width, double height) { | 410 | im.Image _ellipse(double width, double height) { |
| 432 | final im.Image shadow = im.Image( | 411 | final im.Image shadow = im.Image( |
| 433 | (width + spreadRadius * 2).round(), | 412 | (width + spreadRadius * 2).round(), |
| @@ -452,27 +431,171 @@ enum BoxShape { circle, rectangle } | @@ -452,27 +431,171 @@ enum BoxShape { circle, rectangle } | ||
| 452 | 431 | ||
| 453 | enum PaintPhase { all, background, foreground } | 432 | enum PaintPhase { all, background, foreground } |
| 454 | 433 | ||
| 434 | +/// A radius for either circular or elliptical shapes. | ||
| 435 | +class Radius { | ||
| 436 | + /// Constructs a circular radius. [x] and [y] will have the same radius value. | ||
| 437 | + const Radius.circular(double radius) : this.elliptical(radius, radius); | ||
| 438 | + | ||
| 439 | + /// Constructs an elliptical radius with the given radii. | ||
| 440 | + const Radius.elliptical(this.x, this.y); | ||
| 441 | + | ||
| 442 | + /// The radius value on the horizontal axis. | ||
| 443 | + final double x; | ||
| 444 | + | ||
| 445 | + /// The radius value on the vertical axis. | ||
| 446 | + final double y; | ||
| 447 | + | ||
| 448 | + /// A radius with [x] and [y] values set to zero. | ||
| 449 | + static const Radius zero = Radius.circular(0.0); | ||
| 450 | +} | ||
| 451 | + | ||
| 452 | +/// An immutable set of radii for each corner of a rectangle. | ||
| 453 | +class BorderRadius { | ||
| 454 | + /// Creates a border radius where all radii are [radius]. | ||
| 455 | + const BorderRadius.all(Radius radius) | ||
| 456 | + : this.only( | ||
| 457 | + topLeft: radius, | ||
| 458 | + topRight: radius, | ||
| 459 | + bottomLeft: radius, | ||
| 460 | + bottomRight: radius, | ||
| 461 | + ); | ||
| 462 | + | ||
| 463 | + /// Creates a border radius where all radii are [Radius.circular(radius)]. | ||
| 464 | + BorderRadius.circular(double radius) | ||
| 465 | + : this.all( | ||
| 466 | + Radius.circular(radius), | ||
| 467 | + ); | ||
| 468 | + | ||
| 469 | + /// Creates a vertically symmetric border radius where the top and bottom | ||
| 470 | + /// sides of the rectangle have the same radii. | ||
| 471 | + const BorderRadius.vertical({ | ||
| 472 | + Radius top = Radius.zero, | ||
| 473 | + Radius bottom = Radius.zero, | ||
| 474 | + }) : this.only( | ||
| 475 | + topLeft: top, | ||
| 476 | + topRight: top, | ||
| 477 | + bottomLeft: bottom, | ||
| 478 | + bottomRight: bottom, | ||
| 479 | + ); | ||
| 480 | + | ||
| 481 | + /// Creates a horizontally symmetrical border radius where the left and right | ||
| 482 | + /// sides of the rectangle have the same radii. | ||
| 483 | + const BorderRadius.horizontal({ | ||
| 484 | + Radius left = Radius.zero, | ||
| 485 | + Radius right = Radius.zero, | ||
| 486 | + }) : this.only( | ||
| 487 | + topLeft: left, | ||
| 488 | + topRight: right, | ||
| 489 | + bottomLeft: left, | ||
| 490 | + bottomRight: right, | ||
| 491 | + ); | ||
| 492 | + | ||
| 493 | + /// Creates a border radius with only the given non-zero values. The other | ||
| 494 | + /// corners will be right angles. | ||
| 495 | + const BorderRadius.only({ | ||
| 496 | + this.topLeft = Radius.zero, | ||
| 497 | + this.topRight = Radius.zero, | ||
| 498 | + this.bottomLeft = Radius.zero, | ||
| 499 | + this.bottomRight = Radius.zero, | ||
| 500 | + }); | ||
| 501 | + | ||
| 502 | + /// A border radius with all zero radii. | ||
| 503 | + static const BorderRadius zero = BorderRadius.all(Radius.zero); | ||
| 504 | + | ||
| 505 | + /// The top-left [Radius]. | ||
| 506 | + final Radius topLeft; | ||
| 507 | + | ||
| 508 | + /// The top-right [Radius]. | ||
| 509 | + final Radius topRight; | ||
| 510 | + | ||
| 511 | + /// The bottom-left [Radius]. | ||
| 512 | + final Radius bottomLeft; | ||
| 513 | + | ||
| 514 | + /// The bottom-right [Radius]. | ||
| 515 | + final Radius bottomRight; | ||
| 516 | + | ||
| 517 | + void paint(Context context, PdfRect box) { | ||
| 518 | + // Ellipse 4-spline magic number | ||
| 519 | + const double _m4 = 0.551784; | ||
| 520 | + | ||
| 521 | + context.canvas | ||
| 522 | + // Start | ||
| 523 | + ..moveTo(box.x, box.y + bottomLeft.y) | ||
| 524 | + // bottomLeft | ||
| 525 | + ..curveTo( | ||
| 526 | + box.x, | ||
| 527 | + box.y - _m4 * bottomLeft.y + bottomLeft.y, | ||
| 528 | + box.x - _m4 * bottomLeft.x + bottomLeft.x, | ||
| 529 | + box.y, | ||
| 530 | + box.x + bottomLeft.x, | ||
| 531 | + box.y) | ||
| 532 | + // bottom | ||
| 533 | + ..lineTo(box.x + box.width - bottomRight.x, box.y) | ||
| 534 | + // bottomRight | ||
| 535 | + ..curveTo( | ||
| 536 | + box.x + _m4 * bottomRight.x + box.width - bottomRight.x, | ||
| 537 | + box.y, | ||
| 538 | + box.x + box.width, | ||
| 539 | + box.y - _m4 * bottomRight.y + bottomRight.y, | ||
| 540 | + box.x + box.width, | ||
| 541 | + box.y + bottomRight.y) | ||
| 542 | + // right | ||
| 543 | + ..lineTo(box.x + box.width, box.y + box.height - topRight.y) | ||
| 544 | + // topRight | ||
| 545 | + ..curveTo( | ||
| 546 | + box.x + box.width, | ||
| 547 | + box.y + _m4 * topRight.y + box.height - topRight.y, | ||
| 548 | + box.x + _m4 * topRight.x + box.width - topRight.x, | ||
| 549 | + box.y + box.height, | ||
| 550 | + box.x + box.width - topRight.x, | ||
| 551 | + box.y + box.height) | ||
| 552 | + // top | ||
| 553 | + ..lineTo(box.x + topLeft.x, box.y + box.height) | ||
| 554 | + // topLeft | ||
| 555 | + ..curveTo( | ||
| 556 | + box.x - _m4 * topLeft.x + topLeft.x, | ||
| 557 | + box.y + box.height, | ||
| 558 | + box.x, | ||
| 559 | + box.y + _m4 * topLeft.y + box.height - topLeft.y, | ||
| 560 | + box.x, | ||
| 561 | + box.y + box.height - topLeft.y) | ||
| 562 | + // left | ||
| 563 | + ..lineTo(box.x, box.y + bottomLeft.y); | ||
| 564 | + } | ||
| 565 | +} | ||
| 566 | + | ||
| 455 | @immutable | 567 | @immutable |
| 456 | class BoxDecoration { | 568 | class BoxDecoration { |
| 457 | const BoxDecoration({ | 569 | const BoxDecoration({ |
| 458 | this.color, | 570 | this.color, |
| 459 | this.border, | 571 | this.border, |
| 460 | - this.borderRadius, | 572 | + @Deprecated('Use borderRadiusEx with `BorderRadius.all(Radius.circular(20))`') |
| 573 | + double borderRadius, | ||
| 574 | + BorderRadius borderRadiusEx, | ||
| 461 | this.boxShadow, | 575 | this.boxShadow, |
| 462 | this.gradient, | 576 | this.gradient, |
| 463 | this.image, | 577 | this.image, |
| 464 | this.shape = BoxShape.rectangle, | 578 | this.shape = BoxShape.rectangle, |
| 465 | - }) : assert(shape != null); | 579 | + }) : assert(shape != null), |
| 580 | + assert(!(borderRadius != null && borderRadiusEx != null), | ||
| 581 | + 'Don\'t set both borderRadius and borderRadiusEx'), | ||
| 582 | + _borderRadius = borderRadiusEx, | ||
| 583 | + _radius = borderRadius; | ||
| 466 | 584 | ||
| 467 | /// The color to fill in the background of the box. | 585 | /// The color to fill in the background of the box. |
| 468 | final PdfColor color; | 586 | final PdfColor color; |
| 469 | final BoxBorder border; | 587 | final BoxBorder border; |
| 470 | - final double borderRadius; | 588 | + final BorderRadius _borderRadius; |
| 589 | + final double _radius; | ||
| 471 | final BoxShape shape; | 590 | final BoxShape shape; |
| 472 | final DecorationImage image; | 591 | final DecorationImage image; |
| 473 | final Gradient gradient; | 592 | final Gradient gradient; |
| 474 | final List<BoxShadow> boxShadow; | 593 | final List<BoxShadow> boxShadow; |
| 475 | 594 | ||
| 595 | + BorderRadius get borderRadius => | ||
| 596 | + _borderRadius ?? | ||
| 597 | + (_radius == null ? null : BorderRadius.all(Radius.circular(_radius))); | ||
| 598 | + | ||
| 476 | void paint( | 599 | void paint( |
| 477 | Context context, | 600 | Context context, |
| 478 | PdfRect box, [ | 601 | PdfRect box, [ |
| @@ -504,8 +627,7 @@ class BoxDecoration { | @@ -504,8 +627,7 @@ class BoxDecoration { | ||
| 504 | } else { | 627 | } else { |
| 505 | if (boxShadow != null) { | 628 | if (boxShadow != null) { |
| 506 | for (final BoxShadow s in boxShadow) { | 629 | for (final BoxShadow s in boxShadow) { |
| 507 | - final im.Image i = s._rRect( | ||
| 508 | - box.width, box.height, borderRadius, borderRadius); | 630 | + final im.Image i = s._rect(box.width, box.height); |
| 509 | final PdfImage m = | 631 | final PdfImage m = |
| 510 | PdfImage.fromImage(context.document, image: i); | 632 | PdfImage.fromImage(context.document, image: i); |
| 511 | context.canvas.drawImage( | 633 | context.canvas.drawImage( |
| @@ -515,8 +637,7 @@ class BoxDecoration { | @@ -515,8 +637,7 @@ class BoxDecoration { | ||
| 515 | ); | 637 | ); |
| 516 | } | 638 | } |
| 517 | } | 639 | } |
| 518 | - context.canvas.drawRRect(box.x, box.y, box.width, box.height, | ||
| 519 | - borderRadius, borderRadius); | 640 | + borderRadius.paint(context, box); |
| 520 | } | 641 | } |
| 521 | break; | 642 | break; |
| 522 | case BoxShape.circle: | 643 | case BoxShape.circle: |
| @@ -547,8 +668,7 @@ class BoxDecoration { | @@ -547,8 +668,7 @@ class BoxDecoration { | ||
| 547 | if (borderRadius == null) { | 668 | if (borderRadius == null) { |
| 548 | context.canvas.drawRect(box.x, box.y, box.width, box.height); | 669 | context.canvas.drawRect(box.x, box.y, box.width, box.height); |
| 549 | } else { | 670 | } else { |
| 550 | - context.canvas.drawRRect(box.x, box.y, box.width, box.height, | ||
| 551 | - borderRadius, borderRadius); | 671 | + borderRadius.paint(context, box); |
| 552 | } | 672 | } |
| 553 | break; | 673 | break; |
| 554 | case BoxShape.circle: | 674 | case BoxShape.circle: |
| @@ -572,10 +692,8 @@ class BoxDecoration { | @@ -572,10 +692,8 @@ class BoxDecoration { | ||
| 572 | break; | 692 | break; |
| 573 | case BoxShape.rectangle: | 693 | case BoxShape.rectangle: |
| 574 | if (borderRadius != null) { | 694 | if (borderRadius != null) { |
| 575 | - context.canvas | ||
| 576 | - ..drawRRect(box.x, box.y, box.width, box.height, borderRadius, | ||
| 577 | - borderRadius) | ||
| 578 | - ..clipPath(); | 695 | + borderRadius.paint(context, box); |
| 696 | + context.canvas.clipPath(); | ||
| 579 | } | 697 | } |
| 580 | break; | 698 | break; |
| 581 | } | 699 | } |
| @@ -4,7 +4,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl | @@ -4,7 +4,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl | ||
| 4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/pdf | 4 | homepage: https://github.com/DavBfr/dart_pdf/tree/master/pdf |
| 5 | repository: https://github.com/DavBfr/dart_pdf | 5 | repository: https://github.com/DavBfr/dart_pdf |
| 6 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues | 6 | issue_tracker: https://github.com/DavBfr/dart_pdf/issues |
| 7 | -version: 1.12.0 | 7 | +version: 1.13.0 |
| 8 | 8 | ||
| 9 | environment: | 9 | environment: |
| 10 | sdk: ">=2.3.0 <3.0.0" | 10 | sdk: ">=2.3.0 <3.0.0" |
| @@ -40,7 +40,7 @@ void main() { | @@ -40,7 +40,7 @@ void main() { | ||
| 40 | padding: const EdgeInsets.all(20), | 40 | padding: const EdgeInsets.all(20), |
| 41 | decoration: const BoxDecoration( | 41 | decoration: const BoxDecoration( |
| 42 | color: PdfColors.blue, | 42 | color: PdfColors.blue, |
| 43 | - borderRadius: 20, | 43 | + borderRadiusEx: BorderRadius.all(Radius.circular(20)), |
| 44 | border: BoxBorder( | 44 | border: BoxBorder( |
| 45 | color: PdfColors.blue800, | 45 | color: PdfColors.blue800, |
| 46 | top: true, | 46 | top: true, |
| @@ -67,7 +67,7 @@ void main() { | @@ -67,7 +67,7 @@ void main() { | ||
| 67 | alignment: Alignment.center, | 67 | alignment: Alignment.center, |
| 68 | decoration: BoxDecoration( | 68 | decoration: BoxDecoration( |
| 69 | shape: shape, | 69 | shape: shape, |
| 70 | - borderRadius: 10, | 70 | + borderRadiusEx: const BorderRadius.all(Radius.circular(10)), |
| 71 | image: DecorationImage(image: image, fit: fit), | 71 | image: DecorationImage(image: image, fit: fit), |
| 72 | ), | 72 | ), |
| 73 | width: 100, | 73 | width: 100, |
| @@ -121,7 +121,7 @@ void main() { | @@ -121,7 +121,7 @@ void main() { | ||
| 121 | width: 200.0, | 121 | width: 200.0, |
| 122 | decoration: const BoxDecoration( | 122 | decoration: const BoxDecoration( |
| 123 | shape: BoxShape.rectangle, | 123 | shape: BoxShape.rectangle, |
| 124 | - borderRadius: 40, | 124 | + borderRadiusEx: BorderRadius.all(Radius.circular(40)), |
| 125 | border: BoxBorder( | 125 | border: BoxBorder( |
| 126 | bottom: true, | 126 | bottom: true, |
| 127 | top: true, | 127 | top: true, |
| @@ -144,7 +144,7 @@ void main() { | @@ -144,7 +144,7 @@ void main() { | ||
| 144 | margin: const EdgeInsets.all(30), | 144 | margin: const EdgeInsets.all(30), |
| 145 | padding: const EdgeInsets.all(20), | 145 | padding: const EdgeInsets.all(20), |
| 146 | decoration: const BoxDecoration( | 146 | decoration: const BoxDecoration( |
| 147 | - borderRadius: 20, | 147 | + borderRadiusEx: BorderRadius.all(Radius.circular(20)), |
| 148 | gradient: LinearGradient( | 148 | gradient: LinearGradient( |
| 149 | colors: <PdfColor>[ | 149 | colors: <PdfColor>[ |
| 150 | PdfColors.blue, | 150 | PdfColors.blue, |
| @@ -177,7 +177,7 @@ void main() { | @@ -177,7 +177,7 @@ void main() { | ||
| 177 | margin: const EdgeInsets.all(30), | 177 | margin: const EdgeInsets.all(30), |
| 178 | padding: const EdgeInsets.all(20), | 178 | padding: const EdgeInsets.all(20), |
| 179 | decoration: const BoxDecoration( | 179 | decoration: const BoxDecoration( |
| 180 | - borderRadius: 20, | 180 | + borderRadiusEx: BorderRadius.all(Radius.circular(20)), |
| 181 | gradient: RadialGradient( | 181 | gradient: RadialGradient( |
| 182 | colors: <PdfColor>[ | 182 | colors: <PdfColor>[ |
| 183 | PdfColors.blue, | 183 | PdfColors.blue, |
| @@ -51,7 +51,10 @@ List<TableRow> buildTable( | @@ -51,7 +51,10 @@ List<TableRow> buildTable( | ||
| 51 | child: Text('${h.toInt()}°', style: Theme.of(context).tableCell)), | 51 | child: Text('${h.toInt()}°', style: Theme.of(context).tableCell)), |
| 52 | Container( | 52 | Container( |
| 53 | margin: const EdgeInsets.all(5), | 53 | margin: const EdgeInsets.all(5), |
| 54 | - decoration: BoxDecoration(color: color, borderRadius: 5), | 54 | + decoration: BoxDecoration( |
| 55 | + color: color, | ||
| 56 | + borderRadiusEx: const BorderRadius.all(Radius.circular(5)), | ||
| 57 | + ), | ||
| 55 | height: Theme.of(context).tableCell.fontSize), | 58 | height: Theme.of(context).tableCell.fontSize), |
| 56 | Container( | 59 | Container( |
| 57 | margin: const EdgeInsets.all(5), | 60 | margin: const EdgeInsets.all(5), |
| @@ -208,7 +211,7 @@ void main() { | @@ -208,7 +211,7 @@ void main() { | ||
| 208 | border: null, | 211 | border: null, |
| 209 | cellAlignment: Alignment.center, | 212 | cellAlignment: Alignment.center, |
| 210 | headerDecoration: const BoxDecoration( | 213 | headerDecoration: const BoxDecoration( |
| 211 | - borderRadius: 2, | 214 | + borderRadiusEx: BorderRadius.all(Radius.circular(2)), |
| 212 | color: PdfColors.indigo, | 215 | color: PdfColors.indigo, |
| 213 | ), | 216 | ), |
| 214 | headerHeight: 25, | 217 | headerHeight: 25, |
-
Please register or login to post a comment