Showing
5 changed files
with
141 additions
and
6 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, | 457 | + const BoxDecoration({ |
458 | + this.color, | ||
386 | this.border, | 459 | this.border, |
387 | this.borderRadius, | 460 | this.borderRadius, |
461 | + this.boxShadow, | ||
388 | this.gradient, | 462 | this.gradient, |
389 | this.image, | 463 | this.image, |
390 | - this.shape = BoxShape.rectangle}) | ||
391 | - : assert(shape != null); | 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