All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.lowagie.text.Document Maven / Gradle / Ivy

There is a newer version: 2.0.3
Show newest version
/*
 * $Id: Document.java 4106 2009-11-27 12:59:39Z blowagie $
 *
 * Copyright 1999, 2000, 2001, 2002 by Bruno Lowagie.
 *
 * The contents of this file are subject to the Mozilla Public License Version 1.1
 * (the "License"); you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the License.
 *
 * The Original Code is 'iText, a free JAVA-PDF library'.
 *
 * The Initial Developer of the Original Code is Bruno Lowagie. Portions created by
 * the Initial Developer are Copyright (C) 1999, 2000, 2001, 2002 by Bruno Lowagie.
 * All Rights Reserved.
 * Co-Developer of the code is Paulo Soares. Portions created by the Co-Developer
 * are Copyright (C) 2000, 2001, 2002 by Paulo Soares. All Rights Reserved.
 *
 * Contributor(s): all the names of the contributors are added in the source code
 * where applicable.
 *
 * Alternatively, the contents of this file may be used under the terms of the
 * LGPL license (the "GNU LIBRARY GENERAL PUBLIC LICENSE"), in which case the
 * provisions of LGPL are applicable instead of those above.  If you wish to
 * allow use of your version of this file only under the terms of the LGPL
 * License and not to allow others to use your version of this file under
 * the MPL, indicate your decision by deleting the provisions above and
 * replace them with the notice and other provisions required by the LGPL.
 * If you do not delete the provisions above, a recipient may use your version
 * of this file under either the MPL or the GNU LIBRARY GENERAL PUBLIC LICENSE.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the MPL as stated above or under the terms of the GNU
 * Library General Public License as published by the Free Software Foundation;
 * either version 2 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Library general Public License for more
 * details.
 *
 * If you didn't download this code from the following link, you should check if
 * you aren't using an obsolete version:
 * https://github.com/LibrePDF/OpenPDF
 */

package com.lowagie.text;

import com.lowagie.text.error_messages.MessageLocalization;
import com.lowagie.text.pdf.FopGlyphProcessor;
import com.lowagie.text.pdf.PdfDate;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;


/**
 * A generic Document class.
 * 

* All kinds of Text-elements can be added to a HTMLDocument. * The Document signals all the listeners when an element has * been added. *

* Remark: *

    *
  1. Once a document is created you can add some meta information. *
  2. You can also set the headers/footers. *
  3. You have to open the document before you can write content. *
  4. You can only write content (no more meta-formation!) once a document is * opened. *
  5. When you change the header/footer on a certain page, this will be * effective starting on the next page. *
  6. After closing the document, every listener (as well as its * OutputStream) is closed too. *
* Example:
* *
// creation of the document with a certain size and certain margins
 * Document document = new Document(PageSize.A4, 50, 50, 50, 50);
 *  try { 
 *   // creation of the different writers 
 *   HtmlWriter.getInstance(document , System.out);
 *   PdfWriter.getInstance(document , new FileOutputStream("text.pdf"));
 *   // we add some meta information to the document
 *   document.addAuthor("Bruno Lowagie"); 
 *   document.addSubject("This is the result of a Test."); 
 *   // we open the document for writing
 *   document.open(); 
 *   document.add(new Paragraph("Hello world"));
 *  } catch(DocumentException de) {
 *   System.err.println(de.getMessage());
 *  }
 *  document.close();
 * 
* *
*/ public class Document implements DocListener { // membervariables private static final String VERSION_PROPERTIES = "com/lowagie/text/version.properties"; private static final String OPENPDF = "OpenPDF"; private static final String RELEASE; private static final String OPENPDF_VERSION; static { RELEASE = getVersionNumber(); OPENPDF_VERSION = OPENPDF + " " + RELEASE; } private static String getVersionNumber() { String releaseVersion = "UNKNOWN"; try (InputStream input = Document.class.getClassLoader() .getResourceAsStream(VERSION_PROPERTIES)) { if (input != null) { Properties prop = new Properties(); prop.load(input); releaseVersion = prop.getProperty("bundleVersion", releaseVersion); } } catch (IOException ignored) { // ignore this and leave the default } return releaseVersion; } /** * Allows the pdf documents to be produced without compression for debugging * purposes. */ public static boolean compress = true; /** * When true the file access is not done through a memory mapped file. Use it if the file * is too big to be mapped in your address space. */ public static boolean plainRandomAccess = false; /** Scales the WMF font size. The default value is 0.86. */ public static float wmfFontCorrection = 0.86f; /** The DocListener. */ private List listeners = new ArrayList<>(); /** Is the document open or not? */ protected boolean open; /** Has the document already been closed? */ protected boolean close; // membervariables concerning the layout /** The size of the page. */ protected Rectangle pageSize; /** margin in x direction starting from the left */ protected float marginLeft = 0; /** margin in x direction starting from the right */ protected float marginRight = 0; /** margin in y direction starting from the top */ protected float marginTop = 0; /** margin in y direction starting from the bottom */ protected float marginBottom = 0; /** mirroring of the left/right margins */ protected boolean marginMirroring = false; /** * mirroring of the top/bottom margins * @since 2.1.6 */ protected boolean marginMirroringTopBottom = false; /** Content of JavaScript onLoad function */ protected String javaScript_onLoad = null; /** Content of JavaScript onUnLoad function */ protected String javaScript_onUnLoad = null; /** Style class in HTML body tag */ protected String htmlStyleClass = null; // headers, footers /** Current pagenumber */ protected int pageN = 0; /** This is the textual part of a Page; it can contain a header */ protected HeaderFooter header = null; /** This is the textual part of the footer */ protected HeaderFooter footer = null; /** This is a chapter number in case ChapterAutoNumber is used. */ protected int chapternumber = 0; /** * Text rendering options, including the default language of the document and a flag * to enable font glyph substitution (if FOP is available) * * @since 3.1.15 */ TextRenderingOptions textRenderingOptions = new TextRenderingOptions(); // constructor /** * Constructs a new Document -object with the default page size as PageSize.A4 . */ public Document() { this(PageSize.A4); } /** * Constructs a new Document -object using the given rectangle as page size and default margin of 36. * * @param pageSize * the pageSize */ public Document(Rectangle pageSize) { this(pageSize, 36, 36, 36, 36); } /** * Constructs a new Document -object. * * @param pageSize * the pageSize * @param marginLeft * the margin on the left * @param marginRight * the margin on the right * @param marginTop * the margin on the top * @param marginBottom * the margin on the bottom */ public Document(Rectangle pageSize, float marginLeft, float marginRight, float marginTop, float marginBottom) { this.pageSize = pageSize; this.marginLeft = marginLeft; this.marginRight = marginRight; this.marginTop = marginTop; this.marginBottom = marginBottom; } // listener methods /** * Adds a DocListener to the Document. * * @param listener * the new DocListener. */ public void addDocListener(DocListener listener) { listeners.add(listener); } /** * Removes a DocListener from the Document. * * @param listener * the DocListener that has to be removed. */ public void removeDocListener(DocListener listener) { listeners.remove(listener); } // methods implementing the DocListener interface /** * Adds an Element to the Document. * * @param element * the Element to add * @return true if the element was added, false * if not * @throws DocumentException * when a document isn't open yet, or has been closed */ public boolean add(Element element) throws DocumentException { if (close) { throw new DocumentException(MessageLocalization.getComposedMessage("the.document.has.been.closed.you.can.t.add.any.elements")); } if (!open && element.isContent()) { throw new DocumentException(MessageLocalization.getComposedMessage("the.document.is.not.open.yet.you.can.only.add.meta.information")); } boolean success = false; if (element instanceof ChapterAutoNumber) { chapternumber = ((ChapterAutoNumber)element).setAutomaticNumber(chapternumber); } for (DocListener listener : listeners) { success |= listener.add(element); } if (element instanceof LargeElement) { LargeElement e = (LargeElement)element; if (!e.isComplete()) e.flushContent(); } return success; } /** * Opens the document. *

* Once the document is opened, you can't write any meta-information anymore. * If you change the header/footer after opening the document, the change will be effective * starting from the second page. * You have to open the document before you can begin to add content to the body of the * document. */ public void open() { if (!close) { open = true; } for (DocListener listener : listeners) { listener.setPageSize(pageSize); listener.setMargins(marginLeft, marginRight, marginTop, marginBottom); listener.open(); } } /** * Sets the pagesize. *

* This change will be effective starting from the next page. If you want to change the page size of * the first page, you need to set it before opening the document. * * @param pageSize * the new pagesize * @return a boolean */ public boolean setPageSize(Rectangle pageSize) { this.pageSize = pageSize; for (DocListener listener : listeners) { listener.setPageSize(pageSize); } return true; } /** * Sets the margins. *

* This change will be effective starting from the next page. If you want to change margins on * the first page, you need to set it before opening the document. * * @param marginLeft the margin on the left * @param marginRight the margin on the right * @param marginTop the margin on the top * @param marginBottom the margin on the bottom * @return a boolean */ public boolean setMargins(float marginLeft, float marginRight, float marginTop, float marginBottom) { this.marginLeft = marginLeft; this.marginRight = marginRight; this.marginTop = marginTop; this.marginBottom = marginBottom; for (DocListener listener : listeners) { listener.setMargins(marginLeft, marginRight, marginTop, marginBottom); } return true; } /** * Signals to all listeners, that a new page has to be started. * New pages can only be added on already opened and not yet closed documents. * * @return true if the page was added, false * if not. */ public boolean newPage() { if (!open || close) { return false; } for (DocListener listener : listeners) { listener.newPage(); } return true; } /** * Changes the header of this document. *

* This change will be effective starting from the next page. If you want to have a header on * the first page, you need to set it before opening the document. * * @param header the new header */ public void setHeader(HeaderFooter header) { this.header = header; for (DocListener listener : listeners) { listener.setHeader(header); } } /** * Resets the header of this document. *

* This change will be effective starting from the next page. */ public void resetHeader() { this.header = null; for (DocListener listener : listeners) { listener.resetHeader(); } } /** * Changes the footer of this document. *

* This change will be effective starting from the next page. If you want to have a footer on * the first page, you need to set it before opening the document. * * @param footer the new footer */ public void setFooter(HeaderFooter footer) { this.footer = footer; for (DocListener listener : listeners) { listener.setFooter(footer); } } /** * Resets the footer of this document. *

* This change will be effective starting from the next page. */ public void resetFooter() { this.footer = null; for (DocListener listener : listeners) { listener.resetFooter(); } } /** * Sets the page number to 0. *

* This change will be effective starting from the next page. */ public void resetPageCount() { pageN = 0; for (DocListener listener : listeners) { listener.resetPageCount(); } } /** * Sets the page number. *

* This change will be effective starting from the next page. *

* The page number of the next new page will be: pageN + 1 * * @param pageN the new page number */ public void setPageCount(int pageN) { this.pageN = pageN; for (DocListener listener : listeners) { listener.setPageCount(pageN); } } /** * Returns the current page number. * * @return the current page number */ public int getPageNumber() { return this.pageN; } /** * Closes the document. *

* Once all the content has been written in the body, you have to close the * body. After that nothing can be written to the body anymore. */ @Override public void close() { if (!close) { open = false; close = true; } for (DocListener listener : listeners) { listener.close(); } } // methods concerning the header or some meta information /** * Adds a user defined header to the document. *

* Shortcut method to call: add(new Header(name, content)) * * @param name the name of the header * @param content the content of the header * @return true if successful, false otherwise */ public boolean addHeader(String name, String content) { try { return add(new Header(name, content)); } catch (DocumentException de) { throw new ExceptionConverter(de); } } /** * Adds the title to a Document. *

* In case of a PDF this will be visible in the document properties panel. *

* In case of a HTML file this will be visible as the title meta tag in the * HEAD part of the file. *

* Shortcut method to call: add(new Meta(Element.TITLE, title)) * * @param title the title * @return true if successful, false otherwise */ public boolean addTitle(String title) { try { return add(new Meta(Element.TITLE, title)); } catch (DocumentException de) { throw new ExceptionConverter(de); } } /** * Adds the subject to a Document. *

* In case of a PDF this will be visible in the document properties panel. *

* In case of a HTML file this will be visible as the subject meta tag in the * HEAD part of the file. * * @param subject the subject * @return true if successful, false otherwise */ public boolean addSubject(String subject) { try { return add(new Meta(Element.SUBJECT, subject)); } catch (DocumentException de) { throw new ExceptionConverter(de); } } /** * Adds the keywords to a Document. *

* In case of a PDF this will be visible in the document properties panel. *

* In case of a HTML file this will be visible as the keywords meta tag in the * HEAD part of the file. * * @param keywords adds the keywords to the document * @return true if successful, false otherwise */ public boolean addKeywords(String keywords) { try { return add(new Meta(Element.KEYWORDS, keywords)); } catch (DocumentException de) { throw new ExceptionConverter(de); } } /** * Adds the author to a Document. *

* In case of a PDF this will be visible in the document properties panel. *

* In case of a HTML file this will be visible as the author meta tag in the * HEAD part of the file. * * @param author the name of the author * @return true if successful, false otherwise */ public boolean addAuthor(String author) { try { return add(new Meta(Element.AUTHOR, author)); } catch (DocumentException de) { throw new ExceptionConverter(de); } } /** * Adds the creator to a Document. *

* In case of a PDF this will be visible in the document properties panel. *

* In case of a HTML file this will be visible as comment in the HEAD part of the file. * * @param creator * the name of the creator * @return true if successful, false otherwise */ public boolean addCreator(String creator) { try { return add(new Meta(Element.CREATOR, creator)); } catch (DocumentException de) { throw new ExceptionConverter(de); } } /** * Adds the producer to a Document. *

* In case of a PDF this will be visible in the document properties panel. *

* In case of a HTML file this will be visible as comment in the HEAD part of the file. * * @return true if successful, false otherwise */ public boolean addProducer() { return this.addProducer(getVersion()); } /** * Adds the provided value as the producer to a Document. *

* The default producer is OpenPDF XX.YY.ZZ where XX.YY.ZZ is the version of the OpenPDF * library used to produce the document *

* In case of a PDF this will be visible in the document properties panel. *

* In case of a HTML file this will be visible as comment in the HEAD part of the file. * * @param producer new producer line value * @return true if successful, false otherwise */ public boolean addProducer(final String producer) { return add(new Meta(Element.PRODUCER, producer)); } /** * Adds the current date and time to a Document. *

* In case of a PDF this will be visible in the document properties panel. *

* In case of a HTML file this will be visible as comment in the HEAD part of the file. * * @return true if successful, false otherwise */ public boolean addCreationDate() { try { /* bugfix by 'taqua' (Thomas) */ final SimpleDateFormat sdf = new SimpleDateFormat( "EEE MMM dd HH:mm:ss zzz yyyy"); return add(new Meta(Element.CREATIONDATE, sdf.format(new Date()))); } catch (DocumentException de) { throw new ExceptionConverter(de); } } /** * Adds the current date and time to a Document. * * @return true if successful, false otherwise */ public boolean addCreationDate(PdfDate date) { try { return add(new Meta(Element.CREATIONDATE, date.toString())); } catch (DocumentException de) { throw new ExceptionConverter(de); } } /** * Adds the current date and time to a Document. * * @return true if successful, false otherwise */ public boolean addModificationDate() { try { return add(new Meta(Element.MODIFICATIONDATE, new PdfDate().toString())); } catch (DocumentException de) { throw new ExceptionConverter(de); } } /** * Adds the current date and time to a Document. * * @return true if successful, false otherwise */ public boolean addModificationDate(PdfDate date) { try { return add(new Meta(Element.MODIFICATIONDATE, date.toString())); } catch (DocumentException de) { throw new ExceptionConverter(de); } } // methods to get the layout of the document. /** * Returns the left margin. * * @return the left margin */ public float leftMargin() { return marginLeft; } /** * Return the right margin. * * @return the right margin */ public float rightMargin() { return marginRight; } /** * Returns the top margin. * * @return the top margin */ public float topMargin() { return marginTop; } /** * Returns the bottom margin. * * @return the bottom margin */ public float bottomMargin() { return marginBottom; } /** * Returns the lower left x-coordinate. * * @return the lower left x-coordinate */ public float left() { return pageSize.getLeft(marginLeft); } /** * Returns the upper right x-coordinate. * * @return the upper right x-coordinate */ public float right() { return pageSize.getRight(marginRight); } /** * Returns the upper right y-coordinate. * * @return the upper right y-coordinate */ public float top() { return pageSize.getTop(marginTop); } /** * Returns the lower left y-coordinate. * * @return the lower left y-coordinate */ public float bottom() { return pageSize.getBottom(marginBottom); } /** * Returns the lower left x-coordinate considering a given margin. * * @param margin * a margin * @return the lower left x-coordinate */ public float left(float margin) { return pageSize.getLeft(marginLeft + margin); } /** * Returns the upper right x-coordinate, considering a given margin. * * @param margin * a margin * @return the upper right x-coordinate */ public float right(float margin) { return pageSize.getRight(marginRight + margin); } /** * Returns the upper right y-coordinate, considering a given margin. * * @param margin * a margin * @return the upper right y-coordinate */ public float top(float margin) { return pageSize.getTop(marginTop + margin); } /** * Returns the lower left y-coordinate, considering a given margin. * * @param margin * a margin * @return the lower left y-coordinate */ public float bottom(float margin) { return pageSize.getBottom(marginBottom + margin); } /** * Gets the pagesize. * * @return the page size */ public Rectangle getPageSize() { return this.pageSize; } /** * Checks if the document is open. * * @return true if the document is open */ public boolean isOpen() { return open; } /** * Gets the product name. * * @return the product name * @since 2.1.6 */ public static String getProduct() { return OPENPDF; } /** * Gets the release number. * * @return the product name * @since 2.1.6 */ public static String getRelease() { return RELEASE; } /** * Gets the iText version. * * @return iText version */ public static String getVersion() { return OPENPDF_VERSION; } /** * Adds a JavaScript onLoad function to the HTML body tag * * @param code * the JavaScript code to be executed on load of the HTML page */ public void setJavaScript_onLoad(String code) { this.javaScript_onLoad = code; } /** * Gets the JavaScript onLoad command. * * @return the JavaScript onLoad command */ public String getJavaScript_onLoad() { return this.javaScript_onLoad; } /** * Adds a JavaScript onUnLoad function to the HTML body tag * * @param code * the JavaScript code to be executed on unload of the HTML page */ public void setJavaScript_onUnLoad(String code) { this.javaScript_onUnLoad = code; } /** * Gets the JavaScript onUnLoad command. * * @return the JavaScript onUnLoad command */ public String getJavaScript_onUnLoad() { return this.javaScript_onUnLoad; } /** * Adds a style class to the HTML body tag * * @param htmlStyleClass * the style class for the HTML body tag */ public void setHtmlStyleClass(String htmlStyleClass) { this.htmlStyleClass = htmlStyleClass; } /** * Gets the style class of the HTML body tag * * @return the style class of the HTML body tag */ public String getHtmlStyleClass() { return this.htmlStyleClass; } /** * Set the margin mirroring. It will mirror right/left margins for odd/even pages. *

* Note: it will not work with {@link Table}. * * @param marginMirroring * true to mirror the margins * @return always true */ public boolean setMarginMirroring(boolean marginMirroring) { this.marginMirroring = marginMirroring; for (DocListener listener : listeners) { listener.setMarginMirroring(marginMirroring); } return true; } /** * Set the margin mirroring. It will mirror top/bottom margins for odd/even pages. *

* Note: it will not work with {@link Table}. * * @param marginMirroringTopBottom * true to mirror the margins * @return always true * @since 2.1.6 */ public boolean setMarginMirroringTopBottom(boolean marginMirroringTopBottom) { this.marginMirroringTopBottom = marginMirroringTopBottom; for (DocListener listener : listeners) { listener.setMarginMirroringTopBottom(marginMirroringTopBottom); } return true; } /** * Gets the margin mirroring flag. * * @return the margin mirroring flag */ public boolean isMarginMirroring() { return marginMirroring; } /** * The new document language. * This language is used in FopGlyphProcessor to determine which glyphs are to be substituted. *

* The default "dflt" means that all glyphs which can be replaced will be substituted. * * @param documentLanguage the wanted language */ public void setDocumentLanguage(String documentLanguage) { textRenderingOptions.setDocumentLanguage(documentLanguage); } /** * The default language of the document. Can be set to values like "en_US". This language is used in * FopGlyphProcessor to determine which glyphs are to be substituted. *

* The default "dflt" means that all glyphs which can be replaced will be substituted. * * @return the current document language */ public String getDocumentLanguage() { return textRenderingOptions.getDocumentLanguage(); } /** * Set a flag that determine whether glyph substion is enabled when FOP is available. * * @param glyphSubstitutionEnabled the glyph substitution enabled flag * @see FopGlyphProcessor * @see #setDocumentLanguage(String) */ public void setGlyphSubstitutionEnabled(boolean glyphSubstitutionEnabled) { textRenderingOptions.setGlyphSubstitutionEnabled(glyphSubstitutionEnabled); } /** * Returns the glyph substitution enabled flag. * * @return the glyph substitution enabled flag * @see #setGlyphSubstitutionEnabled(boolean) */ public boolean isGlyphSubstitutionEnabled() { return textRenderingOptions.isGlyphSubstitutionEnabled(); } /** * Sets the text rendering options. * * @param textRenderingOptions the text rendering options * @see #setDocumentLanguage(String) * @see Document#setGlyphSubstitutionsEnabled(boolean) */ public void setTextRenderingOptions(TextRenderingOptions textRenderingOptions) { this.textRenderingOptions = textRenderingOptions == null ? new TextRenderingOptions() : textRenderingOptions; } /** * Gets the text rendering options. * * @return the text rendering options * @see #getDocumentLanguage() * @see #isGlyphSubstitutionEnabled() */ public TextRenderingOptions getTextRenderingOptions() { return textRenderingOptions; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy