David PHAM-VAN

Improve Annotations

1 # Changelog 1 # Changelog
2 2
  3 +## 1.6.0
  4 +
  5 +- Improve Annotations
  6 +
3 ## 1.5.0 7 ## 1.5.0
4 8
5 - Fix Align debug painting 9 - Fix Align debug painting
@@ -19,125 +19,138 @@ @@ -19,125 +19,138 @@
19 part of pdf; 19 part of pdf;
20 20
21 class PdfAnnot extends PdfObject { 21 class PdfAnnot extends PdfObject {
22 - PdfAnnot._create(PdfPage pdfPage,  
23 - {String type,  
24 - this.content,  
25 - this.srcRect,  
26 - @required this.subtype,  
27 - this.dest,  
28 - this.destRect,  
29 - this.border,  
30 - this.url,  
31 - this.name})  
32 - : assert(subtype != null),  
33 - super(pdfPage.pdfDocument, type ?? '/Annot') { 22 + PdfAnnot(this.pdfPage, this.annot)
  23 + : assert(annot != null),
  24 + super(pdfPage.pdfDocument, '/Annot') {
34 pdfPage.annotations.add(this); 25 pdfPage.annotations.add(this);
35 } 26 }
36 27
37 - /// Creates a text annotation  
38 - /// @param rect coordinates  
39 - /// @param s Text for this annotation 28 + /// Create a text annotation
  29 + @deprecated
40 factory PdfAnnot.text( 30 factory PdfAnnot.text(
41 PdfPage pdfPage, { 31 PdfPage pdfPage, {
42 @required PdfRect rect, 32 @required PdfRect rect,
43 @required String content, 33 @required String content,
44 PdfBorder border, 34 PdfBorder border,
45 }) => 35 }) =>
46 - PdfAnnot._create( 36 + PdfAnnot(
47 pdfPage, 37 pdfPage,
48 - subtype: '/Text',  
49 - srcRect: rect, 38 + PdfAnnotText(
  39 + rect: rect,
50 content: content, 40 content: content,
51 border: border, 41 border: border,
52 - );  
53 -  
54 - /// Creates a link annotation  
55 - /// @param srcRect coordinates  
56 - /// @param dest Destination for this link. The page will fit the display.  
57 - /// @param destRect Rectangle describing what part of the page to be displayed  
58 - /// (must be in User Coordinates)  
59 - factory PdfAnnot.link(  
60 - PdfPage pdfPage, {  
61 - @required PdfRect srcRect,  
62 - @required PdfPage dest,  
63 - PdfRect destRect,  
64 - PdfBorder border,  
65 - }) =>  
66 - PdfAnnot._create(  
67 - pdfPage,  
68 - subtype: '/Link',  
69 - srcRect: srcRect,  
70 - dest: dest,  
71 - destRect: destRect,  
72 - border: border,  
73 - ); 42 + ));
74 43
75 /// Creates an external link annotation 44 /// Creates an external link annotation
  45 + @deprecated
76 factory PdfAnnot.urlLink( 46 factory PdfAnnot.urlLink(
77 PdfPage pdfPage, { 47 PdfPage pdfPage, {
78 @required PdfRect rect, 48 @required PdfRect rect,
79 @required String dest, 49 @required String dest,
80 PdfBorder border, 50 PdfBorder border,
81 }) => 51 }) =>
82 - PdfAnnot._create( 52 + PdfAnnot(
83 pdfPage, 53 pdfPage,
84 - subtype: '/Link',  
85 - srcRect: rect, 54 + PdfAnnotUrlLink(
  55 + rect: rect,
86 url: dest, 56 url: dest,
87 border: border, 57 border: border,
88 - ); 58 + ));
89 59
90 /// Creates a link annotation to a named destination 60 /// Creates a link annotation to a named destination
  61 + @deprecated
91 factory PdfAnnot.namedLink( 62 factory PdfAnnot.namedLink(
92 PdfPage pdfPage, { 63 PdfPage pdfPage, {
93 @required PdfRect rect, 64 @required PdfRect rect,
94 @required String dest, 65 @required String dest,
95 PdfBorder border, 66 PdfBorder border,
96 }) => 67 }) =>
97 - PdfAnnot._create( 68 + PdfAnnot(
98 pdfPage, 69 pdfPage,
99 - subtype: '/Link',  
100 - srcRect: rect,  
101 - name: dest, 70 + PdfAnnotNamedLink(
  71 + rect: rect,
  72 + dest: dest,
102 border: border, 73 border: border,
  74 + ),
103 ); 75 );
104 76
105 - /// The subtype of the outline, ie text, note, etc  
106 - final String subtype; 77 + /// The annotation content
  78 + final PdfAnnotBase annot;
107 79
108 - /// The size of the annotation  
109 - final PdfRect srcRect; 80 + /// The page where the annotation will display
  81 + final PdfPage pdfPage;
110 82
111 - /// The text of a text annotation  
112 - final String content; 83 + /// Output the annotation
  84 + ///
  85 + /// @param os OutputStream to send the object to
  86 + @override
  87 + void _prepare() {
  88 + super._prepare();
  89 + annot.build(pdfPage, params);
  90 + }
  91 +}
113 92
114 - /// Link to the Destination page  
115 - final PdfObject dest; 93 +enum PdfAnnotFlags {
  94 + invisible,
  95 + hidden,
  96 + print,
  97 + noZoom,
  98 + noRotate,
  99 + noView,
  100 + readOnly,
  101 + locked,
  102 + toggleNoView,
  103 + lockedContent
  104 +}
116 105
117 - /// If destRect is null then this is the region of the destination page shown.  
118 - /// Otherwise they are ignored.  
119 - final PdfRect destRect; 106 +abstract class PdfAnnotBase {
  107 + const PdfAnnotBase({
  108 + @required this.subtype,
  109 + @required this.rect,
  110 + this.border,
  111 + this.content,
  112 + this.name,
  113 + this.flags,
  114 + this.date,
  115 + this.color,
  116 + }) : assert(subtype != null),
  117 + assert(rect != null);
  118 +
  119 + /// The subtype of the outline, ie text, note, etc
  120 + final String subtype;
  121 +
  122 + final PdfRect rect;
120 123
121 /// the border for this annotation 124 /// the border for this annotation
122 final PdfBorder border; 125 final PdfBorder border;
123 126
124 - /// The external url for a link  
125 - final String url; 127 + /// The text of a text annotation
  128 + final String content;
126 129
127 /// The internal name for a link 130 /// The internal name for a link
128 final String name; 131 final String name;
129 132
130 - /// Output the annotation  
131 - ///  
132 - /// @param os OutputStream to send the object to  
133 - @override  
134 - void _prepare() {  
135 - super._prepare(); 133 + /// Flags specifying various characteristics of the annotation
  134 + final Set<PdfAnnotFlags> flags;
  135 +
  136 + /// Last modification date
  137 + final DateTime date;
136 138
  139 + /// Color
  140 + final PdfColor color;
  141 +
  142 + int get flagValue => flags
  143 + ?.map<int>((PdfAnnotFlags e) => 1 >> e.index)
  144 + ?.reduce((int a, int b) => a | b);
  145 +
  146 + @protected
  147 + @mustCallSuper
  148 + void build(PdfPage page, Map<String, PdfStream> params) {
137 params['/Subtype'] = PdfStream.string(subtype); 149 params['/Subtype'] = PdfStream.string(subtype);
138 params['/Rect'] = PdfStream() 150 params['/Rect'] = PdfStream()
139 - ..putNumArray(  
140 - <double>[srcRect.left, srcRect.bottom, srcRect.right, srcRect.top]); 151 + ..putNumArray(<double>[rect.left, rect.bottom, rect.right, rect.top]);
  152 +
  153 + params['/P'] = page.ref();
141 154
142 // handle the border 155 // handle the border
143 if (border == null) { 156 if (border == null) {
@@ -146,39 +159,194 @@ class PdfAnnot extends PdfObject { @@ -146,39 +159,194 @@ class PdfAnnot extends PdfObject {
146 params['/BS'] = border.ref(); 159 params['/BS'] = border.ref();
147 } 160 }
148 161
149 - // Now the annotation subtypes  
150 - if (subtype == '/Text') { 162 + if (content != null) {
151 params['/Contents'] = PdfStream()..putLiteral(content); 163 params['/Contents'] = PdfStream()..putLiteral(content);
152 - } else if (subtype == '/Link') {  
153 - if (url != null) { 164 + }
  165 +
  166 + if (name != null) {
  167 + params['/NM'] = PdfStream()..putLiteral(name);
  168 + }
  169 +
  170 + if (flags != null) {
  171 + params['/F'] = PdfStream.intNum(flagValue);
  172 + }
  173 +
  174 + if (date != null) {
  175 + params['/M'] = PdfStream()..putDate(date);
  176 + }
  177 +
  178 + if (color != null) {
  179 + if (color is PdfColorCmyk) {
  180 + final PdfColorCmyk k = color;
  181 + params['/C'] = PdfStream()
  182 + ..putNumList(<double>[k.cyan, k.magenta, k.yellow, k.black]);
  183 + } else {
  184 + params['/C'] = PdfStream()
  185 + ..putNumList(<double>[color.red, color.green, color.blue]);
  186 + }
  187 + }
  188 + }
  189 +}
  190 +
  191 +class PdfAnnotText extends PdfAnnotBase {
  192 + /// Create a text annotation
  193 + const PdfAnnotText({
  194 + @required PdfRect rect,
  195 + @required String content,
  196 + PdfBorder border,
  197 + String name,
  198 + Set<PdfAnnotFlags> flags,
  199 + DateTime date,
  200 + PdfColor color,
  201 + }) : super(
  202 + subtype: '/Text',
  203 + rect: rect,
  204 + border: border,
  205 + content: content,
  206 + name: name,
  207 + flags: flags,
  208 + date: date,
  209 + color: color,
  210 + );
  211 +}
  212 +
  213 +class PdfAnnotNamedLink extends PdfAnnotBase {
  214 + /// Create a named link annotation
  215 + const PdfAnnotNamedLink({
  216 + @required PdfRect rect,
  217 + @required this.dest,
  218 + PdfBorder border,
  219 + Set<PdfAnnotFlags> flags,
  220 + DateTime date,
  221 + PdfColor color,
  222 + }) : super(
  223 + subtype: '/Link',
  224 + rect: rect,
  225 + border: border,
  226 + flags: flags,
  227 + date: date,
  228 + color: color,
  229 + );
  230 +
  231 + final String dest;
  232 +
  233 + @override
  234 + void build(PdfPage page, Map<String, PdfStream> params) {
  235 + super.build(page, params);
  236 + params['/A'] = PdfStream()
  237 + ..putDictionary(
  238 + <String, PdfStream>{
  239 + '/S': PdfStream()..putString('/GoTo'),
  240 + '/D': PdfStream()..putText(dest),
  241 + },
  242 + );
  243 + }
  244 +}
  245 +
  246 +class PdfAnnotUrlLink extends PdfAnnotBase {
  247 + /// Create an url link annotation
  248 + const PdfAnnotUrlLink({
  249 + @required PdfRect rect,
  250 + @required this.url,
  251 + PdfBorder border,
  252 + Set<PdfAnnotFlags> flags,
  253 + DateTime date,
  254 + PdfColor color,
  255 + }) : super(
  256 + subtype: '/Link',
  257 + rect: rect,
  258 + border: border,
  259 + flags: flags,
  260 + date: date,
  261 + color: color,
  262 + );
  263 +
  264 + final String url;
  265 +
  266 + @override
  267 + void build(PdfPage page, Map<String, PdfStream> params) {
  268 + super.build(page, params);
154 params['/A'] = PdfStream() 269 params['/A'] = PdfStream()
155 - ..putDictionary(<String, PdfStream>{ 270 + ..putDictionary(
  271 + <String, PdfStream>{
156 '/S': PdfStream()..putString('/URI'), 272 '/S': PdfStream()..putString('/URI'),
157 '/URI': PdfStream()..putText(url), 273 '/URI': PdfStream()..putText(url),
158 - });  
159 - } else if (name != null) {  
160 - params['/A'] = PdfStream()  
161 - ..putDictionary(<String, PdfStream>{  
162 - '/S': PdfStream()..putString('/GoTo'),  
163 - '/D': PdfStream()..putText(name),  
164 - });  
165 - } else {  
166 - final List<PdfStream> dests = <PdfStream>[];  
167 - dests.add(dest.ref());  
168 - if (destRect == null) {  
169 - dests.add(PdfStream.string('/Fit'));  
170 - } else {  
171 - dests.add(PdfStream.string('/FitR '));  
172 - dests.add(PdfStream()  
173 - ..putNumList(<double>[  
174 - destRect.left,  
175 - destRect.bottom,  
176 - destRect.right,  
177 - destRect.top  
178 - ])); 274 + },
  275 + );
179 } 276 }
180 - params['/Dest'] = PdfStream.array(dests); 277 +}
  278 +
  279 +enum PdfAnnotHighlighting { none, invert, outline, push, toggle }
  280 +
  281 +abstract class PdfAnnotWidget extends PdfAnnotBase {
  282 + /// Create an url link annotation
  283 + const PdfAnnotWidget(
  284 + PdfRect rect,
  285 + this.fieldType, {
  286 + this.fieldName,
  287 + PdfBorder border,
  288 + Set<PdfAnnotFlags> flags,
  289 + DateTime date,
  290 + PdfColor color,
  291 + this.highlighting,
  292 + this.value,
  293 + }) : super(
  294 + subtype: '/Widget',
  295 + rect: rect,
  296 + border: border,
  297 + flags: flags,
  298 + date: date,
  299 + color: color,
  300 + );
  301 +
  302 + final String fieldType;
  303 +
  304 + final String fieldName;
  305 +
  306 + final PdfAnnotHighlighting highlighting;
  307 +
  308 + final PdfStream value;
  309 +
  310 + @override
  311 + void build(PdfPage page, Map<String, PdfStream> params) {
  312 + super.build(page, params);
  313 +
  314 + params['/FT'] = PdfStream.string(fieldType);
  315 +
  316 + if (fieldName != null) {
  317 + params['/T'] = PdfStream()..putLiteral(fieldName);
  318 + }
  319 +
  320 + if (value != null) {
  321 + params['/V'] = value;
181 } 322 }
182 } 323 }
  324 +}
  325 +
  326 +class PdfAnnotSign extends PdfAnnotWidget {
  327 + const PdfAnnotSign(
  328 + PdfRect rect, {
  329 + String fieldName,
  330 + PdfBorder border,
  331 + Set<PdfAnnotFlags> flags,
  332 + DateTime date,
  333 + PdfColor color,
  334 + PdfAnnotHighlighting highlighting,
  335 + }) : super(
  336 + rect,
  337 + '/Sig',
  338 + fieldName: fieldName,
  339 + border: border,
  340 + flags: flags,
  341 + date: date,
  342 + color: color,
  343 + highlighting: highlighting,
  344 + );
  345 +
  346 + @override
  347 + void build(PdfPage page, Map<String, PdfStream> params) {
  348 + super.build(page, params);
  349 + assert(page.pdfDocument.sign != null);
  350 + params['/V'] = page.pdfDocument.sign.ref();
183 } 351 }
184 } 352 }
@@ -14,6 +14,8 @@ @@ -14,6 +14,8 @@
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 16
  17 +// ignore_for_file: omit_local_variable_types
  18 +
17 part of pdf; 19 part of pdf;
18 20
19 class PdfCatalog extends PdfObject { 21 class PdfCatalog extends PdfObject {
@@ -67,8 +69,25 @@ class PdfCatalog extends PdfObject { @@ -67,8 +69,25 @@ class PdfCatalog extends PdfObject {
67 PdfStream.string(PdfDocument._PdfPageModes[pageMode.index]); 69 PdfStream.string(PdfDocument._PdfPageModes[pageMode.index]);
68 70
69 if (pdfDocument.sign != null) { 71 if (pdfDocument.sign != null) {
70 - params['/Perms'] = PdfStream.dictionary(  
71 - <String, PdfStream>{'/DocMDP': pdfDocument.sign.ref()}); 72 + params['/Perms'] = PdfStream.dictionary(<String, PdfStream>{
  73 + '/DocMDP': pdfDocument.sign.ref(),
  74 + });
  75 + }
  76 +
  77 + final List<PdfAnnot> widgets = <PdfAnnot>[];
  78 + for (PdfPage page in pdfDocument.pdfPageList.pages) {
  79 + for (PdfAnnot annot in page.annotations) {
  80 + if (annot.annot.subtype == '/Widget') {
  81 + widgets.add(annot);
  82 + }
  83 + }
  84 + }
  85 +
  86 + if (widgets.isNotEmpty) {
  87 + params['/AcroForm'] = PdfStream.dictionary(<String, PdfStream>{
  88 + '/SigFlags': PdfStream.intNum(pdfDocument.sign?.flagsValue ?? 0),
  89 + '/Fields': PdfStream()..putObjectArray(widgets),
  90 + });
72 } 91 }
73 } 92 }
74 } 93 }
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 16
17 // ignore_for_file: omit_local_variable_types 17 // ignore_for_file: omit_local_variable_types
  18 +// ignore_for_file: avoid_unused_constructor_parameters
18 19
19 part of pdf; 20 part of pdf;
20 21
@@ -33,13 +34,7 @@ class PDFAnnot extends PdfAnnot { @@ -33,13 +34,7 @@ class PDFAnnot extends PdfAnnot {
33 double fb, 34 double fb,
34 double fr, 35 double fr,
35 double ft}) 36 double ft})
36 - : super._create(pdfPage,  
37 - type: type,  
38 - content: s,  
39 - srcRect: PdfRect.fromLTRB(l, t, r, b),  
40 - subtype: subtype,  
41 - dest: dest,  
42 - destRect: PdfRect.fromLTRB(fl, ft, fr, fb)); 37 + : super(pdfPage, PdfAnnotText(rect: PdfRect(l, b, r, t), content: s));
43 38
44 factory PDFAnnot.annotation( 39 factory PDFAnnot.annotation(
45 PdfPage pdfPage, String s, double l, double b, double r, double t) => 40 PdfPage pdfPage, String s, double l, double b, double r, double t) =>
@@ -342,12 +337,11 @@ class PDFPage extends PdfPage { @@ -342,12 +337,11 @@ class PDFPage extends PdfPage {
342 double vh = PDFAnnot.FULL_PAGE]) { 337 double vh = PDFAnnot.FULL_PAGE]) {
343 final PdfPoint xy1 = cxy(x, y + h); 338 final PdfPoint xy1 = cxy(x, y + h);
344 final PdfPoint xy2 = cxy(x + w, y); 339 final PdfPoint xy2 = cxy(x + w, y);
345 - final PdfPoint xy3 = cxy(vx, vy + vh);  
346 - final PdfPoint xy4 = cxy(vx + vw, vy);  
347 - final PdfAnnot ob = PdfAnnot.link(this,  
348 - srcRect: PdfRect.fromLTRB(xy1.x, xy1.y, xy2.x, xy2.y),  
349 - dest: dest,  
350 - destRect: PdfRect.fromLTRB(xy3.x, xy3.y, xy4.x, xy4.y)); 340 + final PdfAnnot ob = PdfAnnot.urlLink(
  341 + this,
  342 + rect: PdfRect.fromLTRB(xy1.x, xy1.y, xy2.x, xy2.y),
  343 + dest: 'https://github.com/DavBfr/dart_pdf',
  344 + );
351 return ob; 345 return ob;
352 } 346 }
353 347
@@ -107,7 +107,7 @@ class PdfPage extends PdfObject { @@ -107,7 +107,7 @@ class PdfPage extends PdfObject {
107 // the /Contents pages object 107 // the /Contents pages object
108 if (contents.isNotEmpty) { 108 if (contents.isNotEmpty) {
109 if (contents.length == 1) { 109 if (contents.length == 1) {
110 - params['/Contents'] = contents[0].ref(); 110 + params['/Contents'] = contents.first.ref();
111 } else { 111 } else {
112 params['/Contents'] = PdfStream()..putObjectArray(contents); 112 params['/Contents'] = PdfStream()..putObjectArray(contents);
113 } 113 }
@@ -18,29 +18,33 @@ @@ -18,29 +18,33 @@
18 18
19 part of pdf; 19 part of pdf;
20 20
21 -@immutable  
22 -class PdfSignatureRange {  
23 - const PdfSignatureRange(this.start, this.end); 21 +enum PdfSigFlags { signaturesExist, appendOnly }
24 22
25 - final int start;  
26 - final int end;  
27 -} 23 +class PdfSignature extends PdfObject {
  24 + PdfSignature(
  25 + PdfDocument pdfDocument, {
  26 + @required this.crypto,
  27 + Set<PdfSigFlags> flags,
  28 + }) : assert(crypto != null),
  29 + flags = flags ?? const <PdfSigFlags>{PdfSigFlags.signaturesExist},
  30 + super(pdfDocument, '/Sig');
28 31
29 -abstract class PdfSignature extends PdfObject {  
30 - PdfSignature(PdfDocument pdfDocument) : super(pdfDocument, '/Sig'); 32 + final Set<PdfSigFlags> flags;
31 33
32 - int _offsetStart;  
33 - int _offsetEnd; 34 + final PdfSignatureBase crypto;
34 35
35 - void preSign(); 36 + int get flagsValue => flags
  37 + .map<int>((PdfSigFlags e) => 1 >> e.index)
  38 + .reduce((int a, int b) => a | b);
36 39
37 - void sign(PdfStream os, List<PdfSignatureRange> ranges); 40 + int _offsetStart;
  41 + int _offsetEnd;
38 42
39 @override 43 @override
40 void _write(PdfStream os) { 44 void _write(PdfStream os) {
41 - preSign(); 45 + crypto.preSign(params);
42 46
43 - _offsetStart = os.offset; 47 + _offsetStart = os.offset + '$objser $objgen obj\n'.length;
44 super._write(os); 48 super._write(os);
45 _offsetEnd = os.offset; 49 _offsetEnd = os.offset;
46 } 50 }
@@ -49,16 +53,13 @@ abstract class PdfSignature extends PdfObject { @@ -49,16 +53,13 @@ abstract class PdfSignature extends PdfObject {
49 assert(_offsetStart != null && _offsetEnd != null, 53 assert(_offsetStart != null && _offsetEnd != null,
50 'Must reserve the object space before signing the document'); 54 'Must reserve the object space before signing the document');
51 55
52 - final List<PdfSignatureRange> ranges = <PdfSignatureRange>[  
53 - PdfSignatureRange(0, _offsetStart),  
54 - PdfSignatureRange(_offsetEnd, os.offset),  
55 - ]; 56 + crypto.sign(os, params, _offsetStart, _offsetEnd);
  57 + }
  58 +}
56 59
57 - sign(os, ranges);  
58 - final PdfStream signature = PdfStream();  
59 - super._write(signature); 60 +abstract class PdfSignatureBase {
  61 + void preSign(Map<String, PdfStream> params);
60 62
61 - assert(signature.offset == _offsetEnd - _offsetStart);  
62 - os.output().replaceRange(_offsetStart, _offsetEnd, signature.output());  
63 - } 63 + void sign(PdfStream os, Map<String, PdfStream> params, int offsetStart,
  64 + int offsetEnd);
64 } 65 }
@@ -39,7 +39,7 @@ class Anchor extends SingleChildWidget { @@ -39,7 +39,7 @@ class Anchor extends SingleChildWidget {
39 if (description != null) { 39 if (description != null) {
40 final Vector3 rb = mat.transform3(Vector3(box.right, box.top, 0)); 40 final Vector3 rb = mat.transform3(Vector3(box.right, box.top, 0));
41 final PdfRect ibox = PdfRect.fromLTRB(lt.x, lt.y, rb.x, rb.y); 41 final PdfRect ibox = PdfRect.fromLTRB(lt.x, lt.y, rb.x, rb.y);
42 - PdfAnnot.text(context.page, content: description, rect: ibox); 42 + PdfAnnot(context.page, PdfAnnotText(rect: ibox, content: description));
43 } 43 }
44 } 44 }
45 } 45 }
@@ -62,10 +62,12 @@ class AnnotationLink extends AnnotationBuilder { @@ -62,10 +62,12 @@ class AnnotationLink extends AnnotationBuilder {
62 62
63 @override 63 @override
64 void build(Context context, PdfRect box) { 64 void build(Context context, PdfRect box) {
65 - PdfAnnot.namedLink( 65 + PdfAnnot(
66 context.page, 66 context.page,
  67 + PdfAnnotNamedLink(
67 rect: localToGlobal(context, box), 68 rect: localToGlobal(context, box),
68 dest: destination, 69 dest: destination,
  70 + ),
69 ); 71 );
70 } 72 }
71 } 73 }
@@ -77,10 +79,63 @@ class AnnotationUrl extends AnnotationBuilder { @@ -77,10 +79,63 @@ class AnnotationUrl extends AnnotationBuilder {
77 79
78 @override 80 @override
79 void build(Context context, PdfRect box) { 81 void build(Context context, PdfRect box) {
80 - PdfAnnot.urlLink( 82 + PdfAnnot(
81 context.page, 83 context.page,
  84 + PdfAnnotUrlLink(
82 rect: localToGlobal(context, box), 85 rect: localToGlobal(context, box),
83 - dest: destination, 86 + url: destination,
  87 + ),
  88 + );
  89 + }
  90 +}
  91 +
  92 +class AnnotationSignature extends AnnotationBuilder {
  93 + AnnotationSignature(
  94 + this.crypto, {
  95 + this.name,
  96 + this.signFlags,
  97 + this.border,
  98 + this.flags,
  99 + this.date,
  100 + this.color,
  101 + this.highlighting,
  102 + }) : assert(crypto != null);
  103 +
  104 + final Set<PdfSigFlags> signFlags;
  105 +
  106 + final PdfSignatureBase crypto;
  107 +
  108 + final String name;
  109 +
  110 + final PdfBorder border;
  111 +
  112 + final Set<PdfAnnotFlags> flags;
  113 +
  114 + final DateTime date;
  115 +
  116 + final PdfColor color;
  117 +
  118 + final PdfAnnotHighlighting highlighting;
  119 +
  120 + @override
  121 + void build(Context context, PdfRect box) {
  122 + context.document.sign ??= PdfSignature(
  123 + context.document,
  124 + crypto: crypto,
  125 + flags: signFlags,
  126 + );
  127 +
  128 + PdfAnnot(
  129 + context.page,
  130 + PdfAnnotSign(
  131 + localToGlobal(context, box),
  132 + fieldName: name,
  133 + border: border,
  134 + flags: flags,
  135 + date: date,
  136 + color: color,
  137 + highlighting: highlighting,
  138 + ),
84 ); 139 );
85 } 140 }
86 } 141 }
@@ -117,3 +172,30 @@ class UrlLink extends Annotation { @@ -117,3 +172,30 @@ class UrlLink extends Annotation {
117 : assert(child != null), 172 : assert(child != null),
118 super(child: child, builder: AnnotationUrl(destination)); 173 super(child: child, builder: AnnotationUrl(destination));
119 } 174 }
  175 +
  176 +class Signature extends Annotation {
  177 + Signature({
  178 + @required Widget child,
  179 + @required PdfSignatureBase crypto,
  180 + @required String name,
  181 + Set<PdfSigFlags> signFlags,
  182 + PdfBorder border,
  183 + Set<PdfAnnotFlags> flags,
  184 + DateTime date,
  185 + PdfColor color,
  186 + PdfAnnotHighlighting highlighting,
  187 + }) : assert(child != null),
  188 + assert(crypto != null),
  189 + super(
  190 + child: child,
  191 + builder: AnnotationSignature(
  192 + crypto,
  193 + signFlags: signFlags,
  194 + name: name,
  195 + border: border,
  196 + flags: flags,
  197 + date: date,
  198 + color: color,
  199 + highlighting: highlighting,
  200 + ));
  201 +}
@@ -4,7 +4,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl @@ -4,7 +4,7 @@ description: A pdf producer for Dart. It can create pdf files for both web or fl
4 homepage: https://github.com/DavBfr/dart_pdf/tree/master/pdf 4 homepage: https://github.com/DavBfr/dart_pdf/tree/master/pdf
5 repository: https://github.com/DavBfr/dart_pdf 5 repository: https://github.com/DavBfr/dart_pdf
6 issue_tracker: https://github.com/DavBfr/dart_pdf/issues 6 issue_tracker: https://github.com/DavBfr/dart_pdf/issues
7 -version: 1.5.0 7 +version: 1.6.0
8 8
9 environment: 9 environment:
10 sdk: ">=2.3.0 <3.0.0" 10 sdk: ">=2.3.0 <3.0.0"
@@ -29,18 +29,35 @@ void main() { @@ -29,18 +29,35 @@ void main() {
29 final PdfPage page1 = 29 final PdfPage page1 =
30 PdfPage(pdf, pageFormat: const PdfPageFormat(500, 300)); 30 PdfPage(pdf, pageFormat: const PdfPageFormat(500, 300));
31 31
  32 + pdf.pdfNames.addDest('target', page1, posY: 100);
  33 +
32 final PdfGraphics g = page.getGraphics(); 34 final PdfGraphics g = page.getGraphics();
33 35
34 - PdfAnnot.text(page,  
35 - content: 'Hello', rect: const PdfRect(100, 100, 50, 50)); 36 + PdfAnnot(
  37 + page,
  38 + const PdfAnnotText(
  39 + rect: PdfRect(100, 100, 50, 50),
  40 + content: 'Hello',
  41 + ),
  42 + );
36 43
37 - PdfAnnot.link(page, dest: page1, srcRect: const PdfRect(100, 150, 50, 50)); 44 + PdfAnnot(
  45 + page,
  46 + const PdfAnnotNamedLink(
  47 + dest: 'target',
  48 + rect: PdfRect(100, 150, 50, 50),
  49 + ),
  50 + );
38 g.drawRect(100, 150, 50, 50); 51 g.drawRect(100, 150, 50, 50);
39 g.strokePath(); 52 g.strokePath();
40 53
41 - PdfAnnot.urlLink(page,  
42 - rect: const PdfRect(100, 250, 50, 50),  
43 - dest: 'https://github.com/DavBfr/dart_pdf/'); 54 + PdfAnnot(
  55 + page,
  56 + const PdfAnnotUrlLink(
  57 + rect: PdfRect(100, 250, 50, 50),
  58 + url: 'https://github.com/DavBfr/dart_pdf/',
  59 + ),
  60 + );
44 g.drawRect(100, 250, 50, 50); 61 g.drawRect(100, 250, 50, 50);
45 g.strokePath(); 62 g.strokePath();
46 63