1 package javajs.export;
\r
3 import java.io.ByteArrayOutputStream;
\r
4 import java.io.IOException;
\r
5 import java.io.OutputStream;
\r
6 import java.util.Hashtable;
\r
7 import java.util.Map;
\r
8 import java.util.Map.Entry;
\r
9 import java.util.zip.Deflater;
\r
10 import java.util.zip.DeflaterOutputStream;
\r
12 import javajs.util.SB;
\r
16 * A rudimentary class for working with PDF document creation.
\r
17 * Written from scratch based on PDF Reference 13.
\r
19 * @author hansonr Bob Hanson hansonr@stolaf.edu 10/28/2013
\r
22 class PDFObject extends SB {
\r
23 private Map<String, Object> dictionary;
\r
24 private byte[] stream;
\r
30 PDFObject(int index) {
\r
35 return index + " 0 R";
\r
39 return type.substring(0, 1) + index;
\r
43 return "Font".equals(type);
\r
46 void setStream(byte[] stream) {
\r
47 this.stream = stream;
\r
50 Object getDef(String key) {
\r
51 return dictionary.get(key);
\r
54 void addDef(String key, Object value) {
\r
55 if (dictionary == null)
\r
56 dictionary = new Hashtable<String, Object>();
\r
57 dictionary.put(key, value);
\r
58 if (key.equals("Type"))
\r
59 type = ((String) value).substring(1);
\r
62 void setAsStream() {
\r
63 stream = toBytes(0, -1);
\r
67 int output(OutputStream os) throws IOException {
\r
69 String s = index + " 0 obj\n";
\r
70 write(os, s.getBytes(), 0);
\r
73 if (dictionary != null) {
\r
74 if (dictionary.containsKey("Length")) {
\r
77 streamLen = stream.length;
\r
78 boolean doDeflate = (streamLen > 1000);
\r
80 Deflater deflater = new Deflater(9);
\r
81 ByteArrayOutputStream outBytes = new ByteArrayOutputStream(1024);
\r
82 DeflaterOutputStream compBytes = new DeflaterOutputStream(outBytes,
\r
84 compBytes.write(stream, 0, streamLen);
\r
86 stream = outBytes.toByteArray();
\r
87 dictionary.put("Filter", "/FlateDecode");
\r
88 streamLen = stream.length;
\r
90 dictionary.put("Length", "" + streamLen);
\r
92 write(os, getDictionaryText(dictionary, "\n").getBytes(), 0);
\r
95 write(os, this.toString().getBytes(), 0);
\r
96 if (stream != null) {
\r
97 write(os, "stream\r\n".getBytes(), 0);
\r
98 write(os, stream, streamLen);
\r
99 write(os, "\r\nendstream\r\n".getBytes(), 0);
\r
102 write(os, "endobj\n".getBytes(), 0);
\r
106 private void write(OutputStream os, byte[] bytes, int nBytes) throws IOException {
\r
108 nBytes = bytes.length;
\r
110 os.write(bytes, 0, nBytes);
\r
113 @SuppressWarnings("unchecked")
\r
114 private String getDictionaryText(Map<String, Object> d, String nl) {
\r
117 if (d.containsKey("Type"))
\r
118 sb.append("/Type").appendO(d.get("Type"));
\r
119 for (Entry<String, Object> e : d.entrySet()) {
\r
120 String s = e.getKey();
\r
121 if (s.equals("Type") || s.startsWith("!"))
\r
123 sb.append("/" + s);
\r
124 Object o = e.getValue();
\r
125 if (o instanceof Map<?, ?>) {
\r
126 sb.append((getDictionaryText((Map<String, Object>) o, "")));
\r
129 s = (String) e.getValue();
\r
130 if (!s.startsWith("/"))
\r
134 return (sb.length() > 3 ? sb.append(">>").append(nl).toString() : "");
\r
137 @SuppressWarnings("unchecked")
\r
138 private Map<String, Object> createSubdict(Map<String, Object> d0, String dict) {
\r
139 Map<String, Object> d = (Map<String, Object>) d0.get(dict);
\r
141 d0.put(dict, d = new Hashtable<String, Object>());
\r
145 void addResource(String type, String key, String value) {
\r
146 Map<String, Object> r = createSubdict(dictionary, "Resources");
\r
148 r = createSubdict(r, type);
\r