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