David PHAM-VAN

Fix Text decoration placements

@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
10 - Add PdfColor.shade 10 - Add PdfColor.shade
11 - Uniformize examples 11 - Uniformize examples
12 - Fix context painting empty Table 12 - Fix context painting empty Table
  13 +- Fix Text decoration placements
13 14
14 ## 1.5.0 15 ## 1.5.0
15 16
@@ -52,7 +52,9 @@ abstract class _Span { @@ -52,7 +52,9 @@ abstract class _Span {
52 } 52 }
53 53
54 class _TextDecoration { 54 class _TextDecoration {
55 - _TextDecoration(this.style, this.annotation) : assert(style != null); 55 + _TextDecoration(this.style, this.annotation, this.startSpan, this.endSpan)
  56 + : assert(startSpan <= endSpan),
  57 + assert(style != null);
56 58
57 static const double _space = -0.15; 59 static const double _space = -0.15;
58 60
@@ -60,13 +62,44 @@ class _TextDecoration { @@ -60,13 +62,44 @@ class _TextDecoration {
60 62
61 final AnnotationBuilder annotation; 63 final AnnotationBuilder annotation;
62 64
63 - PdfRect box = PdfRect.zero; 65 + final int startSpan;
  66 +
  67 + final int endSpan;
  68 +
  69 + PdfRect _box;
  70 +
  71 + PdfRect _getBox(List<_Span> spans) {
  72 + if (_box != null) {
  73 + return _box;
  74 + }
  75 + final double x1 = spans[startSpan].offset.x + spans[startSpan].left;
  76 + final double x2 =
  77 + spans[endSpan].offset.x + spans[endSpan].left + spans[endSpan].width;
  78 + double y1 = spans[startSpan].offset.y + spans[startSpan].top;
  79 + double y2 = y1 + spans[startSpan].height;
  80 +
  81 + for (int n = startSpan + 1; n <= endSpan; n++) {
  82 + final double ny1 = spans[n].offset.y + spans[n].top;
  83 + final double ny2 = ny1 + spans[n].height;
  84 + y1 = math.min(y1, ny1);
  85 + y2 = math.max(y2, ny2);
  86 + }
  87 +
  88 + _box = PdfRect.fromLTRB(x1, y1, x2, y2);
  89 + return _box;
  90 + }
  91 +
  92 + _TextDecoration copyWith({int endSpan}) =>
  93 + _TextDecoration(style, annotation, startSpan, endSpan ?? this.endSpan);
64 94
65 void backgroundPaint( 95 void backgroundPaint(
66 Context context, 96 Context context,
67 double textScaleFactor, 97 double textScaleFactor,
68 PdfRect globalBox, 98 PdfRect globalBox,
  99 + List<_Span> spans,
69 ) { 100 ) {
  101 + final PdfRect box = _getBox(spans);
  102 +
70 if (annotation != null) { 103 if (annotation != null) {
71 final PdfRect spanBox = PdfRect( 104 final PdfRect spanBox = PdfRect(
72 globalBox.x + box.left, 105 globalBox.x + box.left,
@@ -93,22 +126,25 @@ class _TextDecoration { @@ -93,22 +126,25 @@ class _TextDecoration {
93 Context context, 126 Context context,
94 double textScaleFactor, 127 double textScaleFactor,
95 PdfRect globalBox, 128 PdfRect globalBox,
  129 + List<_Span> spans,
96 ) { 130 ) {
97 - if (style.decoration != null) { 131 + if (style.decoration == null) {
  132 + return;
  133 + }
  134 +
  135 + final PdfRect box = _getBox(spans);
  136 +
98 final PdfFont font = style.font.getFont(context); 137 final PdfFont font = style.font.getFont(context);
99 final double space = 138 final double space =
100 _space * style.fontSize * textScaleFactor * style.decorationThickness; 139 _space * style.fontSize * textScaleFactor * style.decorationThickness;
101 140
102 context.canvas 141 context.canvas
103 ..setStrokeColor(style.decorationColor ?? style.color) 142 ..setStrokeColor(style.decorationColor ?? style.color)
104 - ..setLineWidth(style.decorationThickness *  
105 - style.fontSize *  
106 - textScaleFactor *  
107 - 0.05); 143 + ..setLineWidth(
  144 + style.decorationThickness * style.fontSize * textScaleFactor * 0.05);
108 145
109 if (style.decoration.contains(TextDecoration.underline)) { 146 if (style.decoration.contains(TextDecoration.underline)) {
110 - final double base =  
111 - -font.descent * style.fontSize * textScaleFactor / 2; 147 + final double base = -font.descent * style.fontSize * textScaleFactor / 2;
112 148
113 context.canvas.drawLine( 149 context.canvas.drawLine(
114 globalBox.x + box.left, 150 globalBox.x + box.left,
@@ -166,13 +202,15 @@ class _TextDecoration { @@ -166,13 +202,15 @@ class _TextDecoration {
166 context.canvas.strokePath(); 202 context.canvas.strokePath();
167 } 203 }
168 } 204 }
169 - }  
170 205
171 void debugPaint( 206 void debugPaint(
172 Context context, 207 Context context,
173 double textScaleFactor, 208 double textScaleFactor,
174 PdfRect globalBox, 209 PdfRect globalBox,
  210 + List<_Span> spans,
175 ) { 211 ) {
  212 + final PdfRect box = _getBox(spans);
  213 +
176 context.canvas 214 context.canvas
177 ..setLineWidth(.5) 215 ..setLineWidth(.5)
178 ..drawRect( 216 ..drawRect(
@@ -197,13 +235,13 @@ class _Word extends _Span { @@ -197,13 +235,13 @@ class _Word extends _Span {
197 double get left => metrics.left; 235 double get left => metrics.left;
198 236
199 @override 237 @override
200 - double get top => metrics.top; 238 + double get top => metrics.descent;
201 239
202 @override 240 @override
203 double get width => metrics.width; 241 double get width => metrics.width;
204 242
205 @override 243 @override
206 - double get height => metrics.height; 244 + double get height => metrics.maxHeight;
207 245
208 @override 246 @override
209 String toString() { 247 String toString() {
@@ -464,14 +502,20 @@ class RichText extends Widget { @@ -464,14 +502,20 @@ class RichText extends Widget {
464 span.offset = span.offset.translate(delta, -baseline); 502 span.offset = span.offset.translate(delta, -baseline);
465 } 503 }
466 504
467 - for (_TextDecoration decoration in decorations) {  
468 - decoration.box = PdfRect.fromPoints(  
469 - decoration.box.offset.translate(delta, -baseline),  
470 - decoration.box.size,  
471 - ); 505 + return totalWidth;
472 } 506 }
473 507
474 - return totalWidth; 508 + void _appendDecoration(bool append, _TextDecoration td) {
  509 + if (append && _decorations.isNotEmpty) {
  510 + final _TextDecoration last = _decorations.last;
  511 + if (last.style == td.style && last.annotation == td.annotation) {
  512 + _decorations[_decorations.length - 1] =
  513 + last.copyWith(endSpan: td.endSpan);
  514 + return;
  515 + }
  516 + }
  517 +
  518 + _decorations.add(td);
475 } 519 }
476 520
477 @override 521 @override
@@ -568,16 +612,15 @@ class RichText extends Widget { @@ -568,16 +612,15 @@ class RichText extends Widget {
568 _spans.add(wd); 612 _spans.add(wd);
569 spanCount++; 613 spanCount++;
570 614
571 - final _TextDecoration td = _TextDecoration( 615 + _appendDecoration(
  616 + spanCount > 1,
  617 + _TextDecoration(
572 style, 618 style,
573 span.annotation, 619 span.annotation,
  620 + _spans.length - 1,
  621 + _spans.length - 1,
  622 + ),
574 ); 623 );
575 - td.box = PdfRect(  
576 - offsetX,  
577 - -offsetY + metrics.descent + baseline,  
578 - metrics.maxWidth + space.advanceWidth * style.wordSpacing,  
579 - metrics.maxHeight);  
580 - _decorations.add(td);  
581 624
582 offsetX += 625 offsetX +=
583 metrics.advanceWidth + space.advanceWidth * style.wordSpacing; 626 metrics.advanceWidth + space.advanceWidth * style.wordSpacing;
@@ -598,15 +641,6 @@ class RichText extends Widget { @@ -598,15 +641,6 @@ class RichText extends Widget {
598 spanStart += spanCount; 641 spanStart += spanCount;
599 decorationStart = _decorations.length; 642 decorationStart = _decorations.length;
600 643
601 - if (_decorations.isNotEmpty) {  
602 - // remove the last space  
603 - _decorations.last.box = PdfRect.fromPoints(  
604 - _decorations.last.box.offset,  
605 - _decorations.last.box.size  
606 - .translate(-space.advanceWidth * style.wordSpacing, 0),  
607 - );  
608 - }  
609 -  
610 lines++; 644 lines++;
611 if (maxLines != null && lines > maxLines) { 645 if (maxLines != null && lines > maxLines) {
612 break; 646 break;
@@ -683,12 +717,15 @@ class RichText extends Widget { @@ -683,12 +717,15 @@ class RichText extends Widget {
683 _spans.add(ws); 717 _spans.add(ws);
684 spanCount++; 718 spanCount++;
685 719
686 - final _TextDecoration td = _TextDecoration( 720 + _appendDecoration(
  721 + spanCount > 1,
  722 + _TextDecoration(
687 style, 723 style,
688 span.annotation, 724 span.annotation,
  725 + _spans.length - 1,
  726 + _spans.length - 1,
  727 + ),
689 ); 728 );
690 - td.box = PdfRect(offsetX, -offsetY + baseline, ws.width, ws.height);  
691 - _decorations.add(td);  
692 729
693 offsetX += ws.left + ws.width; 730 offsetX += ws.left + ws.width;
694 } 731 }
@@ -732,7 +769,7 @@ class RichText extends Widget { @@ -732,7 +769,7 @@ class RichText extends Widget {
732 for (_TextDecoration decoration in _decorations) { 769 for (_TextDecoration decoration in _decorations) {
733 assert(() { 770 assert(() {
734 if (Document.debug && RichText.debug) { 771 if (Document.debug && RichText.debug) {
735 - decoration.debugPaint(context, textScaleFactor, box); 772 + decoration.debugPaint(context, textScaleFactor, box, _spans);
736 } 773 }
737 return true; 774 return true;
738 }()); 775 }());
@@ -741,6 +778,7 @@ class RichText extends Widget { @@ -741,6 +778,7 @@ class RichText extends Widget {
741 context, 778 context,
742 textScaleFactor, 779 textScaleFactor,
743 box, 780 box,
  781 + _spans,
744 ); 782 );
745 } 783 }
746 784
@@ -773,6 +811,7 @@ class RichText extends Widget { @@ -773,6 +811,7 @@ class RichText extends Widget {
773 context, 811 context,
774 textScaleFactor, 812 textScaleFactor,
775 box, 813 box,
  814 + _spans,
776 ); 815 );
777 } 816 }
778 } 817 }
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type