001/* 002 * $Id: DocWriter.java 4784 2011-03-15 08:33:00Z blowagie $ 003 * 004 * This file is part of the iText (R) project. 005 * Copyright (c) 1998-2011 1T3XT BVBA 006 * Authors: Bruno Lowagie, Paulo Soares, et al. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Affero General Public License version 3 010 * as published by the Free Software Foundation with the addition of the 011 * following permission added to Section 15 as permitted in Section 7(a): 012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT, 013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 014 * 015 * This program is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 017 * or FITNESS FOR A PARTICULAR PURPOSE. 018 * See the GNU Affero General Public License for more details. 019 * You should have received a copy of the GNU Affero General Public License 020 * along with this program; if not, see http://www.gnu.org/licenses or write to 021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 022 * Boston, MA, 02110-1301 USA, or download the license from the following URL: 023 * http://itextpdf.com/terms-of-use/ 024 * 025 * The interactive user interfaces in modified source and object code versions 026 * of this program must display Appropriate Legal Notices, as required under 027 * Section 5 of the GNU Affero General Public License. 028 * 029 * In accordance with Section 7(b) of the GNU Affero General Public License, 030 * a covered work must retain the producer line in every PDF that is created 031 * or manipulated using iText. 032 * 033 * You can be released from the requirements of the license by purchasing 034 * a commercial license. Buying such a license is mandatory as soon as you 035 * develop commercial activities involving the iText software without 036 * disclosing the source code of your own applications. 037 * These activities include: offering paid services to customers as an ASP, 038 * serving PDFs on the fly in a web application, shipping iText with a closed 039 * source product. 040 * 041 * For more information, please contact iText Software Corp. at this 042 * address: sales@itextpdf.com 043 */ 044package com.itextpdf.text; 045 046import java.io.BufferedOutputStream; 047import java.io.IOException; 048import java.io.OutputStream; 049import java.util.Iterator; 050import java.util.Properties; 051 052import com.itextpdf.text.pdf.OutputStreamCounter; 053 054/** 055 * An abstract <CODE>Writer</CODE> class for documents. 056 * <P> 057 * <CODE>DocWriter</CODE> is the abstract class of several writers such 058 * as <CODE>PdfWriter</CODE> and <CODE>HtmlWriter</CODE>. 059 * A <CODE>DocWriter</CODE> can be added as a <CODE>DocListener</CODE> 060 * to a certain <CODE>Document</CODE> by getting an instance (see method 061 * <CODE>getInstance()</CODE> in the specific writer-classes). 062 * Every <CODE>Element</CODE> added to the original <CODE>Document</CODE> 063 * will be written to the <CODE>OutputStream</CODE> of the listening 064 * <CODE>DocWriter</CODE>. 065 * 066 * @see Document 067 * @see DocListener 068 */ 069 070public abstract class DocWriter implements DocListener { 071 072/** This is some byte that is often used. */ 073 public static final byte NEWLINE = (byte)'\n'; 074 075/** This is some byte that is often used. */ 076 public static final byte TAB = (byte)'\t'; 077 078/** This is some byte that is often used. */ 079 public static final byte LT = (byte)'<'; 080 081/** This is some byte that is often used. */ 082 public static final byte SPACE = (byte)' '; 083 084/** This is some byte that is often used. */ 085 public static final byte EQUALS = (byte)'='; 086 087/** This is some byte that is often used. */ 088 public static final byte QUOTE = (byte)'\"'; 089 090/** This is some byte that is often used. */ 091 public static final byte GT = (byte)'>'; 092 093/** This is some byte that is often used. */ 094 public static final byte FORWARD = (byte)'/'; 095 096 // membervariables 097 098/** The pageSize. */ 099 protected Rectangle pageSize; 100 101/** This is the document that has to be written. */ 102 protected Document document; 103 104/** The outputstream of this writer. */ 105 protected OutputStreamCounter os; 106 107/** Is the writer open for writing? */ 108 protected boolean open = false; 109 110/** Do we have to pause all writing actions? */ 111 protected boolean pause = false; 112 113/** Closes the stream on document close */ 114 protected boolean closeStream = true; 115 116 // constructor 117 118 protected DocWriter() { 119 } 120 121/** 122 * Constructs a <CODE>DocWriter</CODE>. 123 * 124 * @param document The <CODE>Document</CODE> that has to be written 125 * @param os The <CODE>OutputStream</CODE> the writer has to write to. 126 */ 127 128 protected DocWriter(Document document, OutputStream os) { 129 this.document = document; 130 this.os = new OutputStreamCounter(new BufferedOutputStream(os)); 131 } 132 133 // implementation of the DocListener methods 134 135/** 136 * Signals that an <CODE>Element</CODE> was added to the <CODE>Document</CODE>. 137 * <P> 138 * This method should be overridden in the specific <CODE>DocWriter<CODE> classes 139 * derived from this abstract class. 140 * 141 * @param element A high level object to add 142 * @return <CODE>false</CODE> 143 * @throws DocumentException when a document isn't open yet, or has been closed 144 */ 145 146 public boolean add(Element element) throws DocumentException { 147 return false; 148 } 149 150/** 151 * Signals that the <CODE>Document</CODE> was opened. 152 */ 153 154 public void open() { 155 open = true; 156 } 157 158/** 159 * Sets the pagesize. 160 * 161 * @param pageSize the new pagesize 162 * @return a <CODE>boolean</CODE> 163 */ 164 165 public boolean setPageSize(Rectangle pageSize) { 166 this.pageSize = pageSize; 167 return true; 168 } 169 170/** 171 * Sets the margins. 172 * <P> 173 * This does nothing. Has to be overridden if needed. 174 * 175 * @param marginLeft the margin on the left 176 * @param marginRight the margin on the right 177 * @param marginTop the margin on the top 178 * @param marginBottom the margin on the bottom 179 * @return <CODE>false</CODE> 180 */ 181 182 public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) { 183 return false; 184 } 185 186/** 187 * Signals that an new page has to be started. 188 * <P> 189 * This does nothing. Has to be overridden if needed. 190 * 191 * @return <CODE>true</CODE> if the page was added, <CODE>false</CODE> if not. 192 */ 193 194 public boolean newPage() { 195 if (!open) { 196 return false; 197 } 198 return true; 199 } 200 201/** 202 * Sets the page number to 0. 203 * <P> 204 * This method should be overridden in the specific <CODE>DocWriter<CODE> classes 205 * derived from this abstract class if they actually support the use of 206 * pagenumbers. 207 */ 208 209 public void resetPageCount() { 210 } 211 212/** 213 * Sets the page number. 214 * <P> 215 * This method should be overridden in the specific <CODE>DocWriter<CODE> classes 216 * derived from this abstract class if they actually support the use of 217 * pagenumbers. 218 * 219 * @param pageN the new page number 220 */ 221 222 public void setPageCount(int pageN) { 223 } 224 225/** 226 * Signals that the <CODE>Document</CODE> was closed and that no other 227 * <CODE>Elements</CODE> will be added. 228 */ 229 230 public void close() { 231 open = false; 232 try { 233 os.flush(); 234 if (closeStream) 235 os.close(); 236 } 237 catch(IOException ioe) { 238 throw new ExceptionConverter(ioe); 239 } 240 } 241 242 // methods 243 244/** Converts a <CODE>String</CODE> into a <CODE>Byte</CODE> array 245 * according to the ISO-8859-1 codepage. 246 * @param text the text to be converted 247 * @return the conversion result 248 */ 249 250 public static final byte[] getISOBytes(String text) 251 { 252 if (text == null) 253 return null; 254 int len = text.length(); 255 byte b[] = new byte[len]; 256 for (int k = 0; k < len; ++k) 257 b[k] = (byte)text.charAt(k); 258 return b; 259 } 260 261/** 262 * Let the writer know that all writing has to be paused. 263 */ 264 265 public void pause() { 266 pause = true; 267 } 268 269 /** 270 * Checks if writing is paused. 271 * 272 * @return <CODE>true</CODE> if writing temporarily has to be paused, <CODE>false</CODE> otherwise. 273 */ 274 275 public boolean isPaused() { 276 return pause; 277 } 278 279/** 280 * Let the writer know that writing may be resumed. 281 */ 282 283 public void resume() { 284 pause = false; 285 } 286 287/** 288 * Flushes the <CODE>BufferedOutputStream</CODE>. 289 */ 290 291 public void flush() { 292 try { 293 os.flush(); 294 } 295 catch(IOException ioe) { 296 throw new ExceptionConverter(ioe); 297 } 298 } 299 300/** 301 * Writes a <CODE>String</CODE> to the <CODE>OutputStream</CODE>. 302 * 303 * @param string the <CODE>String</CODE> to write 304 * @throws IOException 305 */ 306 307 protected void write(String string) throws IOException { 308 os.write(getISOBytes(string)); 309 } 310 311/** 312 * Writes a number of tabs. 313 * 314 * @param indent the number of tabs to add 315 * @throws IOException 316 */ 317 318 protected void addTabs(int indent) throws IOException { 319 os.write(NEWLINE); 320 for (int i = 0; i < indent; i++) { 321 os.write(TAB); 322 } 323 } 324 325/** 326 * Writes a key-value pair to the outputstream. 327 * 328 * @param key the name of an attribute 329 * @param value the value of an attribute 330 * @throws IOException 331 */ 332 333 protected void write(String key, String value) 334 throws IOException { 335 os.write(SPACE); 336 write(key); 337 os.write(EQUALS); 338 os.write(QUOTE); 339 write(value); 340 os.write(QUOTE); 341 } 342 343/** 344 * Writes a starttag to the outputstream. 345 * 346 * @param tag the name of the tag 347 * @throws IOException 348 */ 349 350 protected void writeStart(String tag) 351 throws IOException { 352 os.write(LT); 353 write(tag); 354 } 355 356/** 357 * Writes an endtag to the outputstream. 358 * 359 * @param tag the name of the tag 360 * @throws IOException 361 */ 362 363 protected void writeEnd(String tag) 364 throws IOException { 365 os.write(LT); 366 os.write(FORWARD); 367 write(tag); 368 os.write(GT); 369 } 370 371/** 372 * Writes an endtag to the outputstream. 373 * @throws IOException 374 */ 375 376 protected void writeEnd() 377 throws IOException { 378 os.write(SPACE); 379 os.write(FORWARD); 380 os.write(GT); 381 } 382 383/** 384 * Writes the markup attributes of the specified <CODE>MarkupAttributes</CODE> 385 * object to the <CODE>OutputStream</CODE>. 386 * @param markup a <CODE>Properties</CODE> collection to write. 387 * @return true, if writing the markup attributes succeeded 388 * @throws IOException 389 */ 390 protected boolean writeMarkupAttributes(Properties markup) 391 throws IOException { 392 if (markup == null) return false; 393 Iterator<Object> attributeIterator = markup.keySet().iterator(); 394 String name; 395 while (attributeIterator.hasNext()) { 396 name = String.valueOf(attributeIterator.next()); 397 write(name, markup.getProperty(name)); 398 } 399 markup.clear(); 400 return true; 401 } 402 403 /** Checks if the stream is to be closed on document close 404 * @return true if the stream is closed on document close 405 * 406 */ 407 public boolean isCloseStream() { 408 return closeStream; 409 } 410 411 /** Sets the close state of the stream after document close 412 * @param closeStream true if the stream is closed on document close 413 * 414 */ 415 public void setCloseStream(boolean closeStream) { 416 this.closeStream = closeStream; 417 } 418 419 /** 420 * @see com.itextpdf.text.DocListener#setMarginMirroring(boolean) 421 */ 422 public boolean setMarginMirroring(boolean MarginMirroring) { 423 return false; 424 } 425 426 /** 427 * @see com.itextpdf.text.DocListener#setMarginMirroring(boolean) 428 * @since 2.1.6 429 */ 430 public boolean setMarginMirroringTopBottom(boolean MarginMirroring) { 431 return false; 432 } 433 434}