Showing
30 changed files
with
134 additions
and
94 deletions
@@ -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
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
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
-
Please register or login to post a comment