David PHAM-VAN

Allow Annotations in TextSpan

1 # 1.3.8 1 # 1.3.8
2 * Add jpeg image loading function 2 * Add jpeg image loading function
3 * Add Theme::copyFrom() method 3 * Add Theme::copyFrom() method
  4 +* Allow Annotations in TextSpan
4 5
5 # 1.3.7 6 # 1.3.7
6 * Add Pdf Creation date 7 * Add Pdf Creation date
@@ -42,69 +42,76 @@ class Anchor extends SingleChildWidget { @@ -42,69 +42,76 @@ class Anchor extends SingleChildWidget {
42 } 42 }
43 } 43 }
44 44
45 -class _Annotation extends SingleChildWidget {  
46 - _Annotation({Widget child}) : super(child: child);  
47 -  
48 - @override  
49 - void debugPaint(Context context) {  
50 - context.canvas  
51 - ..setFillColor(PdfColors.pink)  
52 - ..drawRect(box.x, box.y, box.width, box.height)  
53 - ..fillPath(); 45 +abstract class AnnotationBuilder {
  46 + PdfRect localToGlobal(Context context, PdfRect box) {
  47 + final Matrix4 mat = context.canvas.getTransform();
  48 + final Vector3 lt = mat.transform3(Vector3(box.left, box.bottom, 0));
  49 + final Vector3 rb = mat.transform3(Vector3(box.right, box.top, 0));
  50 + return PdfRect.fromLTRB(lt.x, lt.y, rb.x, rb.y);
54 } 51 }
55 52
56 - @override  
57 - void paint(Context context) {  
58 - super.paint(context);  
59 - paintChild(context);  
60 - } 53 + void build(Context context, PdfRect box);
61 } 54 }
62 55
63 -class Link extends _Annotation {  
64 - Link({@required Widget child, this.destination})  
65 - : assert(child != null),  
66 - super(child: child); 56 +class AnnotationLink extends AnnotationBuilder {
  57 + AnnotationLink(this.destination) : assert(destination != null);
67 58
68 final String destination; 59 final String destination;
69 60
70 @override 61 @override
71 - void paint(Context context) {  
72 - super.paint(context);  
73 -  
74 - if (destination != null) {  
75 - final Matrix4 mat = context.canvas.getTransform();  
76 - final Vector3 lt = mat.transform3(Vector3(box.left, box.bottom, 0));  
77 - final Vector3 rb = mat.transform3(Vector3(box.right, box.top, 0));  
78 - final PdfRect ibox = PdfRect.fromLTRB(lt.x, lt.y, rb.x, rb.y); 62 + void build(Context context, PdfRect box) {
79 PdfAnnot.namedLink( 63 PdfAnnot.namedLink(
80 context.page, 64 context.page,
81 - rect: ibox, 65 + rect: localToGlobal(context, box),
82 dest: destination, 66 dest: destination,
83 ); 67 );
84 } 68 }
85 - }  
86 } 69 }
87 70
88 -class UrlLink extends _Annotation {  
89 - UrlLink({@required Widget child, @required this.destination})  
90 - : assert(child != null),  
91 - assert(destination != null),  
92 - super(child: child); 71 +class AnnotationUrl extends AnnotationBuilder {
  72 + AnnotationUrl(this.destination) : assert(destination != null);
93 73
94 final String destination; 74 final String destination;
95 75
96 @override 76 @override
97 - void paint(Context context) {  
98 - super.paint(context);  
99 -  
100 - final Matrix4 mat = context.canvas.getTransform();  
101 - final Vector3 lt = mat.transform3(Vector3(box.left, box.bottom, 0));  
102 - final Vector3 rb = mat.transform3(Vector3(box.right, box.top, 0));  
103 - final PdfRect ibox = PdfRect.fromLTRB(lt.x, lt.y, rb.x, rb.y); 77 + void build(Context context, PdfRect box) {
104 PdfAnnot.urlLink( 78 PdfAnnot.urlLink(
105 context.page, 79 context.page,
106 - rect: ibox, 80 + rect: localToGlobal(context, box),
107 dest: destination, 81 dest: destination,
108 ); 82 );
109 } 83 }
110 } 84 }
  85 +
  86 +class Annotation extends SingleChildWidget {
  87 + Annotation({Widget child, this.builder}) : super(child: child);
  88 +
  89 + final AnnotationBuilder builder;
  90 +
  91 + @override
  92 + void debugPaint(Context context) {
  93 + context.canvas
  94 + ..setFillColor(PdfColors.pink)
  95 + ..drawRect(box.x, box.y, box.width, box.height)
  96 + ..fillPath();
  97 + }
  98 +
  99 + @override
  100 + void paint(Context context) {
  101 + super.paint(context);
  102 + paintChild(context);
  103 + builder?.build(context, box);
  104 + }
  105 +}
  106 +
  107 +class Link extends Annotation {
  108 + Link({@required Widget child, String destination})
  109 + : assert(child != null),
  110 + super(child: child, builder: AnnotationLink(destination));
  111 +}
  112 +
  113 +class UrlLink extends Annotation {
  114 + UrlLink({@required Widget child, String destination})
  115 + : assert(child != null),
  116 + super(child: child, builder: AnnotationUrl(destination));
  117 +}
@@ -19,7 +19,7 @@ part of widget; @@ -19,7 +19,7 @@ part of widget;
19 enum TextAlign { left, right, center, justify } 19 enum TextAlign { left, right, center, justify }
20 20
21 class _Word { 21 class _Word {
22 - _Word(this.text, this.style, this.metrics); 22 + _Word(this.text, this.style, this.metrics, this.annotation);
23 23
24 final String text; 24 final String text;
25 25
@@ -29,6 +29,8 @@ class _Word { @@ -29,6 +29,8 @@ class _Word {
29 29
30 PdfPoint offset = PdfPoint.zero; 30 PdfPoint offset = PdfPoint.zero;
31 31
  32 + final AnnotationBuilder annotation;
  33 +
32 @override 34 @override
33 String toString() { 35 String toString() {
34 return 'Word "$text" offset:$offset metrics:$metrics style:$style'; 36 return 'Word "$text" offset:$offset metrics:$metrics style:$style';
@@ -53,7 +55,7 @@ class _Word { @@ -53,7 +55,7 @@ class _Word {
53 } 55 }
54 56
55 class TextSpan { 57 class TextSpan {
56 - const TextSpan({this.style, this.text, this.children}); 58 + const TextSpan({this.style, this.text, this.children, this.annotation});
57 59
58 final TextStyle style; 60 final TextStyle style;
59 61
@@ -61,6 +63,8 @@ class TextSpan { @@ -61,6 +63,8 @@ class TextSpan {
61 63
62 final List<TextSpan> children; 64 final List<TextSpan> children;
63 65
  66 + final AnnotationBuilder annotation;
  67 +
64 String toPlainText() { 68 String toPlainText() {
65 final StringBuffer buffer = StringBuffer(); 69 final StringBuffer buffer = StringBuffer();
66 visitTextSpan((TextSpan span) { 70 visitTextSpan((TextSpan span) {
@@ -210,7 +214,7 @@ class RichText extends Widget { @@ -210,7 +214,7 @@ class RichText extends Widget {
210 top = math.min(top ?? metrics.top, metrics.top); 214 top = math.min(top ?? metrics.top, metrics.top);
211 bottom = math.max(bottom ?? metrics.bottom, metrics.bottom); 215 bottom = math.max(bottom ?? metrics.bottom, metrics.bottom);
212 216
213 - final _Word wd = _Word(word, style, metrics); 217 + final _Word wd = _Word(word, style, metrics, span.annotation);
214 wd.offset = PdfPoint(offsetX, -offsetY); 218 wd.offset = PdfPoint(offsetX, -offsetY);
215 219
216 _words.add(wd); 220 _words.add(wd);
@@ -264,6 +268,15 @@ class RichText extends Widget { @@ -264,6 +268,15 @@ class RichText extends Widget {
264 } 268 }
265 } 269 }
266 270
  271 + if (word.annotation != null) {
  272 + final PdfRect wordBox = PdfRect(
  273 + box.x + word.offset.x + word.metrics.left,
  274 + box.top + word.offset.y + word.metrics.top,
  275 + word.metrics.width,
  276 + word.metrics.height);
  277 + word.annotation.build(context, wordBox);
  278 + }
  279 +
267 context.canvas.drawString( 280 context.canvas.drawString(
268 currentStyle.font.getFont(context), 281 currentStyle.font.getFont(context),
269 currentStyle.fontSize * textScaleFactor, 282 currentStyle.fontSize * textScaleFactor,