David PHAM-VAN

Add dashed lines to Decoration Widgets

@@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
4 4
5 - Implement Linear and Radial gradients in BoxDecoration 5 - Implement Linear and Radial gradients in BoxDecoration
6 - Fix PdfColors.shade() 6 - Fix PdfColors.shade()
  7 +- Add dashed lines to Decoration Widgets
7 8
8 ## 1.6.2 9 ## 1.6.2
9 10
@@ -700,4 +700,9 @@ class PdfGraphics { @@ -700,4 +700,9 @@ class PdfGraphics {
700 PdfNum(limit).output(buf); 700 PdfNum(limit).output(buf);
701 buf.putString(' M\n'); 701 buf.putString(' M\n');
702 } 702 }
  703 +
  704 + void setLineDashPattern([List<int> array = const <int>[], int phase = 0]) {
  705 + PdfArray.fromNum(array).output(buf);
  706 + buf.putString(' $phase d\n');
  707 + }
703 } 708 }
@@ -20,24 +20,30 @@ part of widget; @@ -20,24 +20,30 @@ part of widget;
20 20
21 enum DecorationPosition { background, foreground } 21 enum DecorationPosition { background, foreground }
22 22
  23 +enum BorderStyle { none, solid, dashed, dotted }
  24 +
23 @immutable 25 @immutable
24 class BoxBorder { 26 class BoxBorder {
25 - const BoxBorder(  
26 - {this.left = false,  
27 - this.top = false,  
28 - this.right = false,  
29 - this.bottom = false,  
30 - this.color = PdfColors.black,  
31 - this.width = 1.0})  
32 - : assert(color != null), 27 + const BoxBorder({
  28 + this.left = false,
  29 + this.top = false,
  30 + this.right = false,
  31 + this.bottom = false,
  32 + this.color = PdfColors.black,
  33 + this.width = 1.0,
  34 + this.style = BorderStyle.solid,
  35 + }) : assert(color != null),
33 assert(width != null), 36 assert(width != null),
34 - assert(width >= 0.0); 37 + assert(width >= 0.0),
  38 + assert(style != null);
35 39
36 final bool top; 40 final bool top;
37 final bool bottom; 41 final bool bottom;
38 final bool left; 42 final bool left;
39 final bool right; 43 final bool right;
40 44
  45 + final BorderStyle style;
  46 +
41 /// The color of the 47 /// The color of the
42 final PdfColor color; 48 final PdfColor color;
43 49
@@ -50,41 +56,63 @@ class BoxBorder { @@ -50,41 +56,63 @@ class BoxBorder {
50 assert(box.width != null); 56 assert(box.width != null);
51 assert(box.height != null); 57 assert(box.height != null);
52 58
53 - if (top || bottom || left || right) {  
54 - context.canvas  
55 - ..setStrokeColor(color)  
56 - ..setLineWidth(width); 59 + if (!(top || bottom || left || right)) {
  60 + return;
  61 + }
57 62
58 - if (top) {  
59 - context.canvas.drawLine(box.x, box.top, box.right, box.top);  
60 - } 63 + switch (style) {
  64 + case BorderStyle.none:
  65 + return;
  66 + case BorderStyle.solid:
  67 + break;
  68 + case BorderStyle.dashed:
  69 + context.canvas
  70 + ..saveContext()
  71 + ..setLineDashPattern(const <int>[3, 3]);
  72 + break;
  73 + case BorderStyle.dotted:
  74 + context.canvas
  75 + ..saveContext()
  76 + ..setLineDashPattern(const <int>[1, 1]);
  77 + break;
  78 + }
61 79
62 - if (right) {  
63 - if (!top) {  
64 - context.canvas.moveTo(box.right, box.top);  
65 - }  
66 - context.canvas.lineTo(box.right, box.y); 80 + context.canvas
  81 + ..setStrokeColor(color)
  82 + ..setLineWidth(width);
  83 +
  84 + if (top) {
  85 + context.canvas.drawLine(box.x, box.top, box.right, box.top);
  86 + }
  87 +
  88 + if (right) {
  89 + if (!top) {
  90 + context.canvas.moveTo(box.right, box.top);
67 } 91 }
  92 + context.canvas.lineTo(box.right, box.y);
  93 + }
68 94
69 - if (bottom) {  
70 - if (!right) {  
71 - context.canvas.moveTo(box.right, box.y);  
72 - }  
73 - context.canvas.lineTo(box.x, box.y); 95 + if (bottom) {
  96 + if (!right) {
  97 + context.canvas.moveTo(box.right, box.y);
74 } 98 }
  99 + context.canvas.lineTo(box.x, box.y);
  100 + }
75 101
76 - if (left) {  
77 - if (!bottom) {  
78 - context.canvas.moveTo(box.x, box.y);  
79 - context.canvas.lineTo(box.x, box.top);  
80 - } else if (right && top) {  
81 - context.canvas.closePath();  
82 - } else {  
83 - context.canvas.lineTo(box.x, box.top);  
84 - } 102 + if (left) {
  103 + if (!bottom) {
  104 + context.canvas.moveTo(box.x, box.y);
  105 + context.canvas.lineTo(box.x, box.top);
  106 + } else if (right && top) {
  107 + context.canvas.closePath();
  108 + } else {
  109 + context.canvas.lineTo(box.x, box.top);
85 } 110 }
  111 + }
86 112
87 - context.canvas.strokePath(); 113 + context.canvas.strokePath();
  114 + if (style != BorderStyle.solid) {
  115 + context.canvas.restoreContext();
88 } 116 }
89 } 117 }
90 118
@@ -349,6 +377,8 @@ class RadialGradient extends Gradient { @@ -349,6 +377,8 @@ class RadialGradient extends Gradient {
349 377
350 enum BoxShape { circle, rectangle } 378 enum BoxShape { circle, rectangle }
351 379
  380 +enum PaintPhase { all, background, foreground }
  381 +
352 @immutable 382 @immutable
353 class BoxDecoration { 383 class BoxDecoration {
354 const BoxDecoration( 384 const BoxDecoration(
@@ -368,86 +398,94 @@ class BoxDecoration { @@ -368,86 +398,94 @@ class BoxDecoration {
368 final DecorationImage image; 398 final DecorationImage image;
369 final Gradient gradient; 399 final Gradient gradient;
370 400
371 - void paint(Context context, PdfRect box) { 401 + void paint(
  402 + Context context,
  403 + PdfRect box, [
  404 + PaintPhase phase = PaintPhase.all,
  405 + ]) {
372 assert(box.x != null); 406 assert(box.x != null);
373 assert(box.y != null); 407 assert(box.y != null);
374 assert(box.width != null); 408 assert(box.width != null);
375 assert(box.height != null); 409 assert(box.height != null);
376 410
377 - if (color != null) {  
378 - switch (shape) {  
379 - case BoxShape.rectangle:  
380 - if (borderRadius == null) {  
381 - context.canvas.drawRect(box.x, box.y, box.width, box.height);  
382 - } else {  
383 - context.canvas.drawRRect(box.x, box.y, box.width, box.height,  
384 - borderRadius, borderRadius);  
385 - }  
386 - break;  
387 - case BoxShape.circle:  
388 - context.canvas.drawEllipse(box.x + box.width / 2.0,  
389 - box.y + box.height / 2.0, box.width / 2.0, box.height / 2.0);  
390 - break; 411 + if (phase == PaintPhase.all || phase == PaintPhase.background) {
  412 + if (color != null) {
  413 + switch (shape) {
  414 + case BoxShape.rectangle:
  415 + if (borderRadius == null) {
  416 + context.canvas.drawRect(box.x, box.y, box.width, box.height);
  417 + } else {
  418 + context.canvas.drawRRect(box.x, box.y, box.width, box.height,
  419 + borderRadius, borderRadius);
  420 + }
  421 + break;
  422 + case BoxShape.circle:
  423 + context.canvas.drawEllipse(box.x + box.width / 2.0,
  424 + box.y + box.height / 2.0, box.width / 2.0, box.height / 2.0);
  425 + break;
  426 + }
  427 + context.canvas
  428 + ..setFillColor(color)
  429 + ..fillPath();
391 } 430 }
392 - context.canvas  
393 - ..setFillColor(color)  
394 - ..fillPath();  
395 - }  
396 431
397 - if (gradient != null) {  
398 - switch (shape) {  
399 - case BoxShape.rectangle:  
400 - if (borderRadius == null) {  
401 - context.canvas.drawRect(box.x, box.y, box.width, box.height);  
402 - } else {  
403 - context.canvas.drawRRect(box.x, box.y, box.width, box.height,  
404 - borderRadius, borderRadius);  
405 - }  
406 - break;  
407 - case BoxShape.circle:  
408 - context.canvas.drawEllipse(box.x + box.width / 2.0,  
409 - box.y + box.height / 2.0, box.width / 2.0, box.height / 2.0);  
410 - break;  
411 - } 432 + if (gradient != null) {
  433 + switch (shape) {
  434 + case BoxShape.rectangle:
  435 + if (borderRadius == null) {
  436 + context.canvas.drawRect(box.x, box.y, box.width, box.height);
  437 + } else {
  438 + context.canvas.drawRRect(box.x, box.y, box.width, box.height,
  439 + borderRadius, borderRadius);
  440 + }
  441 + break;
  442 + case BoxShape.circle:
  443 + context.canvas.drawEllipse(box.x + box.width / 2.0,
  444 + box.y + box.height / 2.0, box.width / 2.0, box.height / 2.0);
  445 + break;
  446 + }
412 447
413 - gradient.paint(context, box);  
414 - } 448 + gradient.paint(context, box);
  449 + }
415 450
416 - if (image != null) {  
417 - context.canvas.saveContext();  
418 - switch (shape) {  
419 - case BoxShape.circle:  
420 - context.canvas  
421 - ..drawEllipse(box.x + box.width / 2.0, box.y + box.height / 2.0,  
422 - box.width / 2.0, box.height / 2.0)  
423 - ..clipPath();  
424 -  
425 - break;  
426 - case BoxShape.rectangle:  
427 - if (borderRadius != null) { 451 + if (image != null) {
  452 + context.canvas.saveContext();
  453 + switch (shape) {
  454 + case BoxShape.circle:
428 context.canvas 455 context.canvas
429 - ..drawRRect(box.x, box.y, box.width, box.height, borderRadius,  
430 - borderRadius) 456 + ..drawEllipse(box.x + box.width / 2.0, box.y + box.height / 2.0,
  457 + box.width / 2.0, box.height / 2.0)
431 ..clipPath(); 458 ..clipPath();
432 - }  
433 - break; 459 +
  460 + break;
  461 + case BoxShape.rectangle:
  462 + if (borderRadius != null) {
  463 + context.canvas
  464 + ..drawRRect(box.x, box.y, box.width, box.height, borderRadius,
  465 + borderRadius)
  466 + ..clipPath();
  467 + }
  468 + break;
  469 + }
  470 + image.paint(context, box);
  471 + context.canvas.restoreContext();
434 } 472 }
435 - image.paint(context, box);  
436 - context.canvas.restoreContext();  
437 } 473 }
438 474
439 - if (border != null) {  
440 - switch (shape) {  
441 - case BoxShape.circle:  
442 - border.paintEllipse(context, box);  
443 - break;  
444 - case BoxShape.rectangle:  
445 - if (borderRadius != null) {  
446 - border.paintRRect(context, box, borderRadius);  
447 - } else {  
448 - border.paintRect(context, box);  
449 - }  
450 - break; 475 + if (phase == PaintPhase.all || phase == PaintPhase.foreground) {
  476 + if (border != null) {
  477 + switch (shape) {
  478 + case BoxShape.circle:
  479 + border.paintEllipse(context, box);
  480 + break;
  481 + case BoxShape.rectangle:
  482 + if (borderRadius != null) {
  483 + border.paintRRect(context, box, borderRadius);
  484 + } else {
  485 + border.paintRect(context, box);
  486 + }
  487 + break;
  488 + }
451 } 489 }
452 } 490 }
453 } 491 }