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