001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.quercus.lib.pdf;
031:
032: import com.caucho.util.L10N;
033: import com.caucho.vfs.WriteStream;
034:
035: import java.io.IOException;
036: import java.util.ArrayList;
037: import java.util.logging.Logger;
038:
039: /**
040: * pdf object oriented API facade
041: */
042: public class PDFWriter {
043: private static final Logger log = Logger.getLogger(PDFWriter.class
044: .getName());
045: private static final L10N L = new L10N(PDFWriter.class);
046:
047: private long _offset;
048: private WriteStream _out;
049:
050: private int _objectId = 1;
051:
052: private int _lastObject;
053:
054: private String _creator = "Quercus PDF";
055: private String _author;
056: private String _title;
057:
058: private ArrayList<PDFObject> _pendingObjects = new ArrayList<PDFObject>();
059:
060: private ArrayList<ObjectDef> _xref = new ArrayList<ObjectDef>();
061:
062: PDFWriter(WriteStream out) {
063: _out = out;
064: }
065:
066: public void setCreator(String creator) {
067: _creator = creator;
068: }
069:
070: public void setAuthor(String author) {
071: _author = author;
072: }
073:
074: public void setTitle(String title) {
075: _title = title;
076: }
077:
078: public void beginDocument() throws IOException {
079: println("%PDF-1.4");
080: println("#\u00c0\u00c3\u00c4\u00c9");
081: }
082:
083: public void writeCatalog(int catalogId, int pagesId,
084: ArrayList<Integer> pagesList, int pageCount)
085: throws IOException {
086: int pageId = pagesId;
087:
088: if (pagesList.size() > 0)
089: pageId = allocateId(1);
090:
091: beginObject(catalogId);
092:
093: println(" << /Type /Catalog");
094: println(" /Pages " + pageId + " 0 R");
095: println(" >>");
096:
097: endObject();
098:
099: if (pagesList.size() > 0) {
100: beginObject(pageId);
101:
102: println(" << /Type /Pages");
103: print(" /Kids [");
104:
105: for (int i = 0; i < pagesList.size(); i++) {
106: if (i != 0)
107: print(" ");
108:
109: print(pagesList.get(i) + " 0 R");
110: }
111:
112: println("]");
113: println(" /Count " + pageCount);
114: println(" >>");
115:
116: endObject();
117: }
118: }
119:
120: public void writePageGroup(int id, ArrayList<PDFPage> pages)
121: throws IOException {
122: beginObject(id);
123: println(" << /Type /Pages");
124: print(" /Kids [");
125:
126: for (int i = 0; i < pages.size(); i++) {
127: if (i != 0)
128: print(" ");
129:
130: print(pages.get(i).getId() + " 0 R");
131: }
132:
133: println("]");
134: println(" /Count " + pages.size());
135: println(" >>");
136: endObject();
137:
138: for (int i = 0; i < pages.size(); i++) {
139: pages.get(i).write(this );
140: }
141: }
142:
143: public void writeStream(int id, PDFStream stream)
144: throws IOException {
145: stream.flush();
146: int length = stream.getLength();
147:
148: beginObject(id);
149: println(" << /Length " + length + " >>");
150:
151: println("stream");
152: stream.writeToStream(_out);
153: _offset += length;
154: println();
155: println("endstream");
156: endObject();
157: }
158:
159: public void endDocument() throws IOException {
160: long xrefOffset = _offset;
161:
162: println("xref");
163: println("0 " + (_xref.size() + 1) + "");
164: println("0000000000 65535 f");
165:
166: for (int i = 0; i < _xref.size(); i++)
167: _xref.get(i).write();
168:
169: println("trailer");
170: println(" << /Size " + (_xref.size() + 1));
171: println(" /Root 1 0 R");
172: println(" >>");
173: println("startxref");
174: println(xrefOffset);
175: println("%%EOF");
176: }
177:
178: public int allocateId(int count) {
179: int id = _objectId;
180:
181: _objectId += count;
182:
183: return id;
184: }
185:
186: public void addPendingObject(PDFObject obj) throws IOException {
187: if (_lastObject + 1 == obj.getId()) {
188: beginObject(obj.getId());
189: obj.writeObject(this );
190: endObject();
191: } else
192: _pendingObjects.add(obj);
193: }
194:
195: public void beginObject(int id) throws IOException {
196: while (_xref.size() < id)
197: _xref.add(null);
198:
199: _xref.set(id - 1, new ObjectDef(id, _offset));
200:
201: println(id + " 0 obj");
202: }
203:
204: public void endObject() throws IOException {
205: println("endobj");
206:
207: _lastObject++;
208:
209: for (int i = _pendingObjects.size() - 1; i >= 0; i--) {
210: PDFObject obj = _pendingObjects.get(i);
211:
212: if (_lastObject + 1 == obj.getId()) {
213: _pendingObjects.remove(i);
214:
215: beginObject(obj.getId());
216: obj.writeObject(this );
217: endObject();
218: break;
219: }
220: }
221: }
222:
223: public void write(byte[] buffer, int offset, int length)
224: throws IOException {
225: _out.write(buffer, offset, length);
226:
227: _offset += length;
228: }
229:
230: public void print(String s) throws IOException {
231: _out.print(s);
232:
233: _offset += s.length();
234: }
235:
236: public void println(String s) throws IOException {
237: _out.println(s);
238:
239: _offset += s.length() + 1;
240: }
241:
242: public void println() throws IOException {
243: _out.println();
244:
245: _offset += 1;
246: }
247:
248: public void print(long v) throws IOException {
249: println(String.valueOf(v));
250: }
251:
252: public void println(long v) throws IOException {
253: println(String.valueOf(v));
254: }
255:
256: public void print(double v) throws IOException {
257: if ((long) v == v)
258: print(String.valueOf((long) v));
259: else
260: print(String.valueOf(v));
261: }
262:
263: public void println(double v) throws IOException {
264: if ((long) v == v)
265: println(String.valueOf((long) v));
266: else
267: println(String.valueOf(v));
268: }
269:
270: public String toString() {
271: return "PDF[]";
272: }
273:
274: class ObjectDef {
275: private int _id;
276: private long _offset;
277:
278: ObjectDef(int id, long offset) {
279: _id = id;
280: _offset = offset;
281: }
282:
283: void write() throws IOException {
284: _out.print(_offset / 1000000000L % 10);
285: _out.print(_offset / 100000000L % 10);
286: _out.print(_offset / 10000000L % 10);
287: _out.print(_offset / 1000000L % 10);
288: _out.print(_offset / 100000L % 10);
289:
290: _out.print(_offset / 10000L % 10);
291: _out.print(_offset / 1000L % 10);
292: _out.print(_offset / 100L % 10);
293: _out.print(_offset / 10L % 10);
294: _out.print(_offset % 10);
295:
296: _out.print(' ');
297: _out.println("00000 n");
298:
299: _offset += 19;
300: }
301: }
302: }
|