document.dart
15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/*
* Copyright (C) 2017, David PHAM-VAN <dev.nfet.net@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import 'dart:typed_data';
import 'package:flutter/services.dart' show rootBundle;
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
import 'package:printing/printing.dart';
import '../data.dart';
Future<Uint8List> generateDocument(
PdfPageFormat format, CustomData data) async {
final doc = pw.Document(pageMode: PdfPageMode.outlines);
final font1 = await PdfGoogleFonts.openSansRegular();
final font2 = await PdfGoogleFonts.openSansBold();
final shape = await rootBundle.loadString('assets/document.svg');
final swirls = await rootBundle.loadString('assets/swirls2.svg');
doc.addPage(
pw.Page(
pageTheme: pw.PageTheme(
pageFormat: format.copyWith(
marginBottom: 0,
marginLeft: 0,
marginRight: 0,
marginTop: 0,
),
orientation: pw.PageOrientation.portrait,
buildBackground: (context) =>
pw.SvgImage(svg: shape, fit: pw.BoxFit.fill),
theme: pw.ThemeData.withFont(
base: font1,
bold: font2,
),
),
build: (context) {
return pw.Padding(
padding: const pw.EdgeInsets.only(
left: 60,
right: 60,
bottom: 30,
),
child: pw.Column(
children: [
pw.Spacer(),
pw.RichText(
text: pw.TextSpan(children: [
pw.TextSpan(
text: '${DateTime.now().year}\n',
style: pw.TextStyle(
fontWeight: pw.FontWeight.bold,
color: PdfColors.grey600,
fontSize: 40,
),
),
pw.TextSpan(
text: 'Portable Document Format',
style: pw.TextStyle(
fontWeight: pw.FontWeight.bold,
fontSize: 40,
),
),
])),
pw.Spacer(),
pw.Container(
alignment: pw.Alignment.topRight,
height: 150,
child: pw.PdfLogo(),
),
pw.Spacer(flex: 2),
pw.Align(
alignment: pw.Alignment.topLeft,
child: pw.UrlLink(
destination: 'https://wikipedia.org/wiki/PDF',
child: pw.Text(
'https://wikipedia.org/wiki/PDF',
style: const pw.TextStyle(
color: PdfColors.pink100,
),
),
),
),
],
),
);
},
),
);
doc.addPage(
pw.Page(
theme: pw.ThemeData.withFont(
base: font1,
bold: font2,
),
pageFormat: format.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
orientation: pw.PageOrientation.portrait,
build: (context) {
return pw.Column(
children: [
pw.Center(
child: pw.Text('Table of content',
style: pw.Theme.of(context).header0),
),
pw.SizedBox(height: 20),
pw.TableOfContent(),
pw.Spacer(),
pw.Center(
child: pw.SvgImage(
svg: swirls, width: 100, colorFilter: PdfColors.grey)),
pw.Spacer(),
],
);
},
),
);
doc.addPage(pw.MultiPage(
theme: pw.ThemeData.withFont(
base: font1,
bold: font2,
),
pageFormat: format.copyWith(marginBottom: 1.5 * PdfPageFormat.cm),
orientation: pw.PageOrientation.portrait,
crossAxisAlignment: pw.CrossAxisAlignment.start,
header: (pw.Context context) {
if (context.pageNumber == 1) {
return pw.SizedBox();
}
return pw.Container(
alignment: pw.Alignment.centerRight,
margin: const pw.EdgeInsets.only(bottom: 3.0 * PdfPageFormat.mm),
padding: const pw.EdgeInsets.only(bottom: 3.0 * PdfPageFormat.mm),
decoration: const pw.BoxDecoration(
border: pw.Border(
bottom: pw.BorderSide(width: 0.5, color: PdfColors.grey))),
child: pw.Text('Portable Document Format',
style: pw.Theme.of(context)
.defaultTextStyle
.copyWith(color: PdfColors.grey)));
},
footer: (pw.Context context) {
return pw.Container(
alignment: pw.Alignment.centerRight,
margin: const pw.EdgeInsets.only(top: 1.0 * PdfPageFormat.cm),
child: pw.Text(
'Page ${context.pageNumber} of ${context.pagesCount}',
style: pw.Theme.of(context)
.defaultTextStyle
.copyWith(color: PdfColors.grey)));
},
build: (pw.Context context) => <pw.Widget>[
pw.Header(
level: 0,
title: 'Portable Document Format',
child: pw.Row(
mainAxisAlignment: pw.MainAxisAlignment.spaceBetween,
children: <pw.Widget>[
pw.Text('Portable Document Format', textScaleFactor: 2),
pw.PdfLogo()
])),
pw.Paragraph(
text:
'The Portable Document Format (PDF) is a file format developed by Adobe in the 1990s to present documents, including text formatting and images, in a manner independent of application software, hardware, and operating systems. Based on the PostScript language, each PDF file encapsulates a complete description of a fixed-layout flat document, including the text, fonts, vector graphics, raster images and other information needed to display it. PDF was standardized as an open format, ISO 32000, in 2008, and no longer requires any royalties for its implementation.'),
pw.Paragraph(
text:
'Today, PDF files may contain a variety of content besides flat text and graphics including logical structuring elements, interactive elements such as annotations and form-fields, layers, rich media (including video content) and three dimensional objects using U3D or PRC, and various other data formats. The PDF specification also provides for encryption and digital signatures, file attachments and metadata to enable workflows requiring these features.'),
pw.Header(level: 1, text: 'History and standardization'),
pw.Paragraph(
text:
"Adobe Systems made the PDF specification available free of charge in 1993. In the early years PDF was popular mainly in desktop publishing workflows, and competed with a variety of formats such as DjVu, Envoy, Common Ground Digital Paper, Farallon Replica and even Adobe's own PostScript format."),
pw.Paragraph(
text:
'PDF was a proprietary format controlled by Adobe until it was released as an open standard on July 1, 2008, and published by the International Organization for Standardization as ISO 32000-1:2008, at which time control of the specification passed to an ISO Committee of volunteer industry experts. In 2008, Adobe published a Public Patent License to ISO 32000-1 granting royalty-free rights for all patents owned by Adobe that are necessary to make, use, sell, and distribute PDF compliant implementations.'),
pw.Paragraph(
text:
"PDF 1.7, the sixth edition of the PDF specification that became ISO 32000-1, includes some proprietary technologies defined only by Adobe, such as Adobe XML Forms Architecture (XFA) and JavaScript extension for Acrobat, which are referenced by ISO 32000-1 as normative and indispensable for the full implementation of the ISO 32000-1 specification. These proprietary technologies are not standardized and their specification is published only on Adobe's website. Many of them are also not supported by popular third-party implementations of PDF."),
pw.Paragraph(
text:
'On July 28, 2017, ISO 32000-2:2017 (PDF 2.0) was published. ISO 32000-2 does not include any proprietary technologies as normative references.'),
pw.Header(level: 1, text: 'Technical foundations'),
pw.Paragraph(text: 'The PDF combines three technologies:'),
pw.Bullet(
text:
'A subset of the PostScript page description programming language, for generating the layout and graphics.'),
pw.Bullet(
text:
'A font-embedding/replacement system to allow fonts to travel with the documents.'),
pw.Bullet(
text:
'A structured storage system to bundle these elements and any associated content into a single file, with data compression where appropriate.'),
pw.Header(level: 2, text: 'PostScript'),
pw.Paragraph(
text:
'PostScript is a page description language run in an interpreter to generate an image, a process requiring many resources. It can handle graphics and standard features of programming languages such as if and loop commands. PDF is largely based on PostScript but simplified to remove flow control features like these, while graphics commands such as lineto remain.'),
pw.Paragraph(
text:
'Often, the PostScript-like PDF code is generated from a source PostScript file. The graphics commands that are output by the PostScript code are collected and tokenized. Any files, graphics, or fonts to which the document refers also are collected. Then, everything is compressed to a single file. Therefore, the entire PostScript world (fonts, layout, measurements) remains intact.'),
pw.Column(
crossAxisAlignment: pw.CrossAxisAlignment.start,
children: <pw.Widget>[
pw.Paragraph(
text:
'As a document format, PDF has several advantages over PostScript:'),
pw.Bullet(
text:
'PDF contains tokenized and interpreted results of the PostScript source code, for direct correspondence between changes to items in the PDF page description and changes to the resulting page appearance.'),
pw.Bullet(
text:
'PDF (from version 1.4) supports graphic transparency; PostScript does not.'),
pw.Bullet(
text:
'PostScript is an interpreted programming language with an implicit global state, so instructions accompanying the description of one page can affect the appearance of any following page. Therefore, all preceding pages in a PostScript document must be processed to determine the correct appearance of a given page, whereas each page in a PDF document is unaffected by the others. As a result, PDF viewers allow the user to quickly jump to the final pages of a long document, whereas a PostScript viewer needs to process all pages sequentially before being able to display the destination page (unless the optional PostScript Document Structuring Conventions have been carefully complied with).'),
]),
pw.Header(level: 1, text: 'Content'),
pw.Paragraph(
text:
'A PDF file is often a combination of vector graphics, text, and bitmap graphics. The basic types of content in a PDF are:'),
pw.Bullet(
text:
'Text stored as content streams (i.e., not encoded in plain text)'),
pw.Bullet(
text:
'Vector graphics for illustrations and designs that consist of shapes and lines'),
pw.Bullet(
text:
'Raster graphics for photographs and other types of image'),
pw.Bullet(text: 'Multimedia objects in the document'),
pw.Paragraph(
text:
'In later PDF revisions, a PDF document can also support links (inside document or web page), forms, JavaScript (initially available as plugin for Acrobat 3.0), or any other types of embedded contents that can be handled using plug-ins.'),
pw.Paragraph(
text:
'PDF 1.6 supports interactive 3D documents embedded in the PDF - 3D drawings can be embedded using U3D or PRC and various other data formats.'),
pw.Paragraph(
text:
'Two PDF files that look similar on a computer screen may be of very different sizes. For example, a high resolution raster image takes more space than a low resolution one. Typically higher resolution is needed for printing documents than for displaying them on screen. Other things that may increase the size of a file is embedding full fonts, especially for Asiatic scripts, and storing text as graphics. '),
pw.Header(
level: 1, text: 'File formats and Adobe Acrobat versions'),
pw.Paragraph(
text:
'The PDF file format has changed several times, and continues to evolve, along with the release of new versions of Adobe Acrobat. There have been nine versions of PDF and the corresponding version of the software:'),
pw.Table.fromTextArray(context: context, data: const <List<String>>[
<String>['Date', 'PDF Version', 'Acrobat Version'],
<String>['1993', 'PDF 1.0', 'Acrobat 1'],
<String>['1994', 'PDF 1.1', 'Acrobat 2'],
<String>['1996', 'PDF 1.2', 'Acrobat 3'],
<String>['1999', 'PDF 1.3', 'Acrobat 4'],
<String>['2001', 'PDF 1.4', 'Acrobat 5'],
<String>['2003', 'PDF 1.5', 'Acrobat 6'],
<String>['2005', 'PDF 1.6', 'Acrobat 7'],
<String>['2006', 'PDF 1.7', 'Acrobat 8'],
<String>['2008', 'PDF 1.7', 'Acrobat 9'],
<String>['2009', 'PDF 1.7', 'Acrobat 9.1'],
<String>['2010', 'PDF 1.7', 'Acrobat X'],
<String>['2012', 'PDF 1.7', 'Acrobat XI'],
<String>['2017', 'PDF 2.0', 'Acrobat DC'],
]),
pw.Padding(padding: const pw.EdgeInsets.all(10)),
pw.Paragraph(
text:
'Text is available under the Creative Commons Attribution Share Alike License.')
]));
return await doc.save();
}