Showing
2 changed files
with
83 additions
and
49 deletions
@@ -34,8 +34,8 @@ class PdfOutput { | @@ -34,8 +34,8 @@ class PdfOutput { | ||
34 | /// This is the actual [PdfStream] used to write to. | 34 | /// This is the actual [PdfStream] used to write to. |
35 | final PdfStream os; | 35 | final PdfStream os; |
36 | 36 | ||
37 | - /// This vector contains offsets of each object | ||
38 | - List<PdfXref> offsets = <PdfXref>[]; | 37 | + /// Cross reference table |
38 | + final xref = PdfXrefTable(); | ||
39 | 39 | ||
40 | /// This is used to track the /Root object (catalog) | 40 | /// This is used to track the /Root object (catalog) |
41 | PdfObject? rootID; | 41 | PdfObject? rootID; |
@@ -63,41 +63,18 @@ class PdfOutput { | @@ -63,41 +63,18 @@ class PdfOutput { | ||
63 | signatureID = ob; | 63 | signatureID = ob; |
64 | } | 64 | } |
65 | 65 | ||
66 | - offsets.add(PdfXref(ob.objser, os.offset)); | 66 | + xref.add(PdfXref(ob.objser, os.offset)); |
67 | ob.write(os); | 67 | ob.write(os); |
68 | } | 68 | } |
69 | 69 | ||
70 | /// This closes the Stream, writing the xref table | 70 | /// This closes the Stream, writing the xref table |
71 | Future<void> close() async { | 71 | Future<void> close() async { |
72 | - final xref = os.offset; | ||
73 | - os.putString('xref\n'); | ||
74 | - | ||
75 | - // Now scan through the offsets list. They should be in sequence. | ||
76 | - offsets.sort((a, b) => a.id.compareTo(b.id)); | ||
77 | - | ||
78 | - var firstid = 0; // First id in block | ||
79 | - var lastid = 0; // The last id used | ||
80 | - final block = <PdfXref>[]; // xrefs in this block | ||
81 | - | ||
82 | - // We need block 0 to exist | ||
83 | - block.add(PdfXref(0, 0, generation: 65535)); | ||
84 | - | ||
85 | - for (var x in offsets) { | ||
86 | - // check to see if block is in range | ||
87 | - if (x.id != (lastid + 1)) { | ||
88 | - // no, so write this block, and reset | ||
89 | - writeblock(firstid, block); | ||
90 | - block.clear(); | ||
91 | - firstid = x.id; | ||
92 | - } | ||
93 | - | ||
94 | - // now add to block | ||
95 | - block.add(x); | ||
96 | - lastid = x.id; | 72 | + if (rootID == null) { |
73 | + throw Exception('Root object is not present in document'); | ||
97 | } | 74 | } |
98 | 75 | ||
99 | - // now write the last block | ||
100 | - writeblock(firstid, block); | 76 | + final _xref = os.offset; |
77 | + xref.output(os); | ||
101 | 78 | ||
102 | // now the trailer object | 79 | // now the trailer object |
103 | os.putString('trailer\n'); | 80 | os.putString('trailer\n'); |
@@ -108,14 +85,10 @@ class PdfOutput { | @@ -108,14 +85,10 @@ class PdfOutput { | ||
108 | params['/Size'] = PdfNum(rootID!.pdfDocument.objser); | 85 | params['/Size'] = PdfNum(rootID!.pdfDocument.objser); |
109 | 86 | ||
110 | // the /Root catalog indirect reference (REQUIRED) | 87 | // the /Root catalog indirect reference (REQUIRED) |
111 | - if (rootID != null) { | ||
112 | - params['/Root'] = rootID!.ref(); | ||
113 | - final id = | ||
114 | - PdfString(rootID!.pdfDocument.documentID, PdfStringFormat.binary); | ||
115 | - params['/ID'] = PdfArray([id, id]); | ||
116 | - } else { | ||
117 | - throw Exception('Root object is not present in document'); | ||
118 | - } | 88 | + params['/Root'] = rootID!.ref(); |
89 | + final id = | ||
90 | + PdfString(rootID!.pdfDocument.documentID, PdfStringFormat.binary); | ||
91 | + params['/ID'] = PdfArray([id, id]); | ||
119 | 92 | ||
120 | // the /Info reference (OPTIONAL) | 93 | // the /Info reference (OPTIONAL) |
121 | if (infoID != null) { | 94 | if (infoID != null) { |
@@ -133,20 +106,10 @@ class PdfOutput { | @@ -133,20 +106,10 @@ class PdfOutput { | ||
133 | 106 | ||
134 | // end the trailer object | 107 | // end the trailer object |
135 | params.output(os); | 108 | params.output(os); |
136 | - os.putString('\nstartxref\n$xref\n%%EOF\n'); | 109 | + os.putString('\nstartxref\n$_xref\n%%EOF\n'); |
137 | 110 | ||
138 | if (signatureID != null) { | 111 | if (signatureID != null) { |
139 | await signatureID!.writeSignature(os); | 112 | await signatureID!.writeSignature(os); |
140 | } | 113 | } |
141 | } | 114 | } |
142 | - | ||
143 | - /// Writes a block of references to the Pdf file | ||
144 | - void writeblock(int firstid, List<PdfXref> block) { | ||
145 | - os.putString('$firstid ${block.length}\n'); | ||
146 | - | ||
147 | - for (var x in block) { | ||
148 | - os.putString(x.ref()); | ||
149 | - os.putString('\n'); | ||
150 | - } | ||
151 | - } | ||
152 | } | 115 | } |
@@ -14,6 +14,11 @@ | @@ -14,6 +14,11 @@ | ||
14 | * limitations under the License. | 14 | * limitations under the License. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | +import 'package:pdf/src/pdf/stream.dart'; | ||
18 | + | ||
19 | +import 'data_types.dart'; | ||
20 | +import 'object.dart'; | ||
21 | + | ||
17 | /// Cross-reference for a Pdf Object | 22 | /// Cross-reference for a Pdf Object |
18 | class PdfXref { | 23 | class PdfXref { |
19 | /// Creates a cross-reference for a Pdf Object | 24 | /// Creates a cross-reference for a Pdf Object |
@@ -41,5 +46,71 @@ class PdfXref { | @@ -41,5 +46,71 @@ class PdfXref { | ||
41 | } | 46 | } |
42 | 47 | ||
43 | @override | 48 | @override |
49 | + bool operator ==(Object other) { | ||
50 | + if (other is PdfXref) { | ||
51 | + return offset == other.offset; | ||
52 | + } | ||
53 | + | ||
54 | + return false; | ||
55 | + } | ||
56 | + | ||
57 | + @override | ||
44 | String toString() => '$runtimeType $id $generation $offset'; | 58 | String toString() => '$runtimeType $id $generation $offset'; |
59 | + | ||
60 | + @override | ||
61 | + int get hashCode => offset; | ||
62 | +} | ||
63 | + | ||
64 | +class PdfXrefTable extends PdfDataType { | ||
65 | + PdfXrefTable(); | ||
66 | + | ||
67 | + /// Contains offsets of each object | ||
68 | + final offsets = <PdfXref>[]; | ||
69 | + | ||
70 | + /// Add a xross reference element to the set | ||
71 | + void add(PdfXref xref) { | ||
72 | + offsets.add(xref); | ||
73 | + } | ||
74 | + | ||
75 | + /// Writes a block of references to the Pdf file | ||
76 | + void _writeblock(PdfStream s, int firstid, List<PdfXref> block) { | ||
77 | + s.putString('$firstid ${block.length}\n'); | ||
78 | + | ||
79 | + for (var x in block) { | ||
80 | + s.putString(x.ref()); | ||
81 | + s.putByte(0x0a); | ||
82 | + } | ||
83 | + } | ||
84 | + | ||
85 | + @override | ||
86 | + void output(PdfStream s) { | ||
87 | + s.putString('xref\n'); | ||
88 | + | ||
89 | + // Now scan through the offsets list. They should be in sequence. | ||
90 | + offsets.sort((a, b) => a.id.compareTo(b.id)); | ||
91 | + | ||
92 | + var firstid = 0; // First id in block | ||
93 | + var lastid = 0; // The last id used | ||
94 | + final block = <PdfXref>[]; // xrefs in this block | ||
95 | + | ||
96 | + // We need block 0 to exist | ||
97 | + block.add(PdfXref(0, 0, generation: 65535)); | ||
98 | + | ||
99 | + for (var x in offsets) { | ||
100 | + // check to see if block is in range | ||
101 | + if (x.id != (lastid + 1)) { | ||
102 | + // no, so write this block, and reset | ||
103 | + _writeblock(s, firstid, block); | ||
104 | + block.clear(); | ||
105 | + firstid = x.id; | ||
106 | + } | ||
107 | + | ||
108 | + // now add to block | ||
109 | + block.add(x); | ||
110 | + lastid = x.id; | ||
111 | + } | ||
112 | + | ||
113 | + // now write the last block | ||
114 | + _writeblock(s, firstid, block); | ||
115 | + } | ||
45 | } | 116 | } |
-
Please register or login to post a comment