Showing
5 changed files
with
145 additions
and
10 deletions
| @@ -19,6 +19,7 @@ library widget; | @@ -19,6 +19,7 @@ library widget; | ||
| 19 | import 'dart:collection'; | 19 | import 'dart:collection'; |
| 20 | import 'dart:math' as math; | 20 | import 'dart:math' as math; |
| 21 | import 'dart:typed_data'; | 21 | import 'dart:typed_data'; |
| 22 | +import 'package:image/image.dart' as im; | ||
| 22 | 23 | ||
| 23 | import 'package:barcode/barcode.dart'; | 24 | import 'package:barcode/barcode.dart'; |
| 24 | import 'package:meta/meta.dart'; | 25 | import 'package:meta/meta.dart'; |
| @@ -375,20 +375,94 @@ class RadialGradient extends Gradient { | @@ -375,20 +375,94 @@ class RadialGradient extends Gradient { | ||
| 375 | } | 375 | } |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | +class BoxShadow { | ||
| 379 | + const BoxShadow({ | ||
| 380 | + this.color = PdfColors.black, | ||
| 381 | + this.offset = PdfPoint.zero, | ||
| 382 | + this.blurRadius = 0.0, | ||
| 383 | + this.spreadRadius = 0.0, | ||
| 384 | + }); | ||
| 385 | + | ||
| 386 | + final PdfColor color; | ||
| 387 | + final PdfPoint offset; | ||
| 388 | + final double blurRadius; | ||
| 389 | + final double spreadRadius; | ||
| 390 | + | ||
| 391 | + im.Image _rect(double width, double height) { | ||
| 392 | + final im.Image shadow = im.Image( | ||
| 393 | + (width + spreadRadius * 2).round(), | ||
| 394 | + (height + spreadRadius * 2).round(), | ||
| 395 | + ); | ||
| 396 | + | ||
| 397 | + im.fillRect( | ||
| 398 | + shadow, | ||
| 399 | + spreadRadius.round(), | ||
| 400 | + spreadRadius.round(), | ||
| 401 | + (spreadRadius + width).round(), | ||
| 402 | + (spreadRadius + height).round(), | ||
| 403 | + color.toInt(), | ||
| 404 | + ); | ||
| 405 | + | ||
| 406 | + im.gaussianBlur(shadow, blurRadius.round()); | ||
| 407 | + | ||
| 408 | + return shadow; | ||
| 409 | + } | ||
| 410 | + | ||
| 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) { | ||
| 432 | + final im.Image shadow = im.Image( | ||
| 433 | + (width + spreadRadius * 2).round(), | ||
| 434 | + (height + spreadRadius * 2).round(), | ||
| 435 | + ); | ||
| 436 | + | ||
| 437 | + im.fillCircle( | ||
| 438 | + shadow, | ||
| 439 | + (spreadRadius + width / 2).round(), | ||
| 440 | + (spreadRadius + height / 2).round(), | ||
| 441 | + (width / 2).round(), | ||
| 442 | + color.toInt(), | ||
| 443 | + ); | ||
| 444 | + | ||
| 445 | + im.gaussianBlur(shadow, blurRadius.round()); | ||
| 446 | + | ||
| 447 | + return shadow; | ||
| 448 | + } | ||
| 449 | +} | ||
| 450 | + | ||
| 378 | enum BoxShape { circle, rectangle } | 451 | enum BoxShape { circle, rectangle } |
| 379 | 452 | ||
| 380 | enum PaintPhase { all, background, foreground } | 453 | enum PaintPhase { all, background, foreground } |
| 381 | 454 | ||
| 382 | @immutable | 455 | @immutable |
| 383 | class BoxDecoration { | 456 | class BoxDecoration { |
| 384 | - const BoxDecoration( | ||
| 385 | - {this.color, | ||
| 386 | - this.border, | ||
| 387 | - this.borderRadius, | ||
| 388 | - this.gradient, | ||
| 389 | - this.image, | ||
| 390 | - this.shape = BoxShape.rectangle}) | ||
| 391 | - : assert(shape != null); | 457 | + const BoxDecoration({ |
| 458 | + this.color, | ||
| 459 | + this.border, | ||
| 460 | + this.borderRadius, | ||
| 461 | + this.boxShadow, | ||
| 462 | + this.gradient, | ||
| 463 | + this.image, | ||
| 464 | + this.shape = BoxShape.rectangle, | ||
| 465 | + }) : assert(shape != null); | ||
| 392 | 466 | ||
| 393 | /// The color to fill in the background of the box. | 467 | /// The color to fill in the background of the box. |
| 394 | final PdfColor color; | 468 | final PdfColor color; |
| @@ -397,6 +471,7 @@ class BoxDecoration { | @@ -397,6 +471,7 @@ class BoxDecoration { | ||
| 397 | final BoxShape shape; | 471 | final BoxShape shape; |
| 398 | final DecorationImage image; | 472 | final DecorationImage image; |
| 399 | final Gradient gradient; | 473 | final Gradient gradient; |
| 474 | + final List<BoxShadow> boxShadow; | ||
| 400 | 475 | ||
| 401 | void paint( | 476 | void paint( |
| 402 | Context context, | 477 | Context context, |
| @@ -413,13 +488,50 @@ class BoxDecoration { | @@ -413,13 +488,50 @@ class BoxDecoration { | ||
| 413 | switch (shape) { | 488 | switch (shape) { |
| 414 | case BoxShape.rectangle: | 489 | case BoxShape.rectangle: |
| 415 | if (borderRadius == null) { | 490 | if (borderRadius == null) { |
| 491 | + if (boxShadow != null) { | ||
| 492 | + for (final BoxShadow s in boxShadow) { | ||
| 493 | + final im.Image i = s._rect(box.width, box.height); | ||
| 494 | + final PdfImage m = | ||
| 495 | + PdfImage.fromImage(context.document, image: i); | ||
| 496 | + context.canvas.drawImage( | ||
| 497 | + m, | ||
| 498 | + box.x + s.offset.x - s.spreadRadius, | ||
| 499 | + box.y - s.offset.y - s.spreadRadius, | ||
| 500 | + ); | ||
| 501 | + } | ||
| 502 | + } | ||
| 416 | context.canvas.drawRect(box.x, box.y, box.width, box.height); | 503 | context.canvas.drawRect(box.x, box.y, box.width, box.height); |
| 417 | } else { | 504 | } else { |
| 505 | + if (boxShadow != null) { | ||
| 506 | + for (final BoxShadow s in boxShadow) { | ||
| 507 | + final im.Image i = s._rRect( | ||
| 508 | + box.width, box.height, borderRadius, borderRadius); | ||
| 509 | + final PdfImage m = | ||
| 510 | + PdfImage.fromImage(context.document, image: i); | ||
| 511 | + context.canvas.drawImage( | ||
| 512 | + m, | ||
| 513 | + box.x + s.offset.x - s.spreadRadius, | ||
| 514 | + box.y - s.offset.y - s.spreadRadius, | ||
| 515 | + ); | ||
| 516 | + } | ||
| 517 | + } | ||
| 418 | context.canvas.drawRRect(box.x, box.y, box.width, box.height, | 518 | context.canvas.drawRRect(box.x, box.y, box.width, box.height, |
| 419 | borderRadius, borderRadius); | 519 | borderRadius, borderRadius); |
| 420 | } | 520 | } |
| 421 | break; | 521 | break; |
| 422 | case BoxShape.circle: | 522 | case BoxShape.circle: |
| 523 | + if (boxShadow != null && box.width == box.height) { | ||
| 524 | + for (final BoxShadow s in boxShadow) { | ||
| 525 | + final im.Image i = s._ellipse(box.width, box.height); | ||
| 526 | + final PdfImage m = | ||
| 527 | + PdfImage.fromImage(context.document, image: i); | ||
| 528 | + context.canvas.drawImage( | ||
| 529 | + m, | ||
| 530 | + box.x + s.offset.x - s.spreadRadius, | ||
| 531 | + box.y - s.offset.y - s.spreadRadius, | ||
| 532 | + ); | ||
| 533 | + } | ||
| 534 | + } | ||
| 423 | context.canvas.drawEllipse(box.x + box.width / 2.0, | 535 | context.canvas.drawEllipse(box.x + box.width / 2.0, |
| 424 | box.y + box.height / 2.0, box.width / 2.0, box.height / 2.0); | 536 | box.y + box.height / 2.0, box.width / 2.0, box.height / 2.0); |
| 425 | break; | 537 | break; |
| @@ -204,6 +204,27 @@ void main() { | @@ -204,6 +204,27 @@ void main() { | ||
| 204 | )); | 204 | )); |
| 205 | }); | 205 | }); |
| 206 | 206 | ||
| 207 | + test('Container Widgets BoxShadow', () { | ||
| 208 | + pdf.addPage(Page( | ||
| 209 | + build: (Context context) => Container( | ||
| 210 | + margin: const EdgeInsets.all(30), | ||
| 211 | + padding: const EdgeInsets.all(20), | ||
| 212 | + decoration: const BoxDecoration( | ||
| 213 | + boxShadow: <BoxShadow>[ | ||
| 214 | + BoxShadow( | ||
| 215 | + blurRadius: 4, | ||
| 216 | + spreadRadius: 10, | ||
| 217 | + offset: PdfPoint(2, 2), | ||
| 218 | + ), | ||
| 219 | + ], | ||
| 220 | + color: PdfColors.blue, | ||
| 221 | + ), | ||
| 222 | + width: 200, | ||
| 223 | + height: 400, | ||
| 224 | + ), | ||
| 225 | + )); | ||
| 226 | + }); | ||
| 227 | + | ||
| 207 | tearDownAll(() { | 228 | tearDownAll(() { |
| 208 | final File file = File('widgets-container.pdf'); | 229 | final File file = File('widgets-container.pdf'); |
| 209 | file.writeAsBytesSync(pdf.save()); | 230 | file.writeAsBytesSync(pdf.save()); |
No preview for this file type
-
Please register or login to post a comment