com.openhtmltopdf.pdfboxout.PdfRendererBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openhtmltopdf-pdfbox Show documentation
Show all versions of openhtmltopdf-pdfbox Show documentation
Openhtmltopdf is a CSS 2.1 renderer written in Java. This artifact supports PDF output with Apache PDF-BOX 2.
package com.openhtmltopdf.pdfboxout;
import com.openhtmltopdf.css.constants.IdentValue;
import com.openhtmltopdf.extend.*;
import com.openhtmltopdf.extend.impl.FSNoOpCacheStore;
import com.openhtmltopdf.outputdevice.helper.BaseDocument;
import com.openhtmltopdf.outputdevice.helper.BaseRendererBuilder;
import com.openhtmltopdf.outputdevice.helper.PageDimensions;
import com.openhtmltopdf.outputdevice.helper.UnicodeImplementation;
import com.openhtmltopdf.util.XRLog;
import org.apache.pdfbox.pdmodel.PDDocument;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.logging.Level;
public class PdfRendererBuilder extends BaseRendererBuilder {
public PdfRendererBuilder() {
super(new PdfRendererBuilderState());
for (CacheStore cacheStore : CacheStore.values()) {
// Use the flyweight pattern to initialize all caches with a no-op implementation to
// avoid excessive null handling.
state._caches.put(cacheStore, FSNoOpCacheStore.INSTANCE);
}
}
/**
* Run the XHTML/XML to PDF conversion and output to an output stream set by
* toStream.
*
* @throws Exception
*/
public void run() throws Exception {
PdfBoxRenderer renderer = null;
try {
renderer = this.buildPdfRenderer();
renderer.layout();
renderer.createPDF();
} finally {
if (renderer != null)
renderer.close();
}
}
/**
* Build a PdfBoxRenderer for further customization. Remember to call
* {@link PdfBoxRenderer#cleanup()} after use.
*
* @return
*/
public PdfBoxRenderer buildPdfRenderer() {
UnicodeImplementation unicode = new UnicodeImplementation(state._reorderer, state._splitter, state._lineBreaker,
state._unicodeToLowerTransformer, state._unicodeToUpperTransformer, state._unicodeToTitleTransformer, state._textDirection,
state._charBreaker);
PageDimensions pageSize = new PageDimensions(state._pageWidth, state._pageHeight, state._isPageSizeInches);
BaseDocument doc = new BaseDocument(state._baseUri, state._html, state._document, state._file, state._uri);
PdfBoxRenderer renderer = new PdfBoxRenderer(doc, unicode, pageSize, state);
/*
* Register all Fonts
*/
PdfBoxFontResolver resolver = renderer.getFontResolver();
for (AddedFont font : state._fonts) {
IdentValue fontStyle = null;
if (font.style == FontStyle.NORMAL) {
fontStyle = IdentValue.NORMAL;
} else if (font.style == FontStyle.ITALIC) {
fontStyle = IdentValue.ITALIC;
} else if (font.style == FontStyle.OBLIQUE) {
fontStyle = IdentValue.OBLIQUE;
}
if (font.supplier != null) {
resolver.addFont(font.supplier, font.family, font.weight, fontStyle, font.subset);
} else {
try {
resolver.addFont(font.fontFile, font.family, font.weight, fontStyle, font.subset);
} catch (Exception e) {
XRLog.init(Level.WARNING, "Font " + font.fontFile + " could not be loaded", e);
}
}
}
return renderer;
}
/**
* An output stream to output the resulting PDF. The caller is required to close
* the output stream after calling run.
*
* @param out
* @return
*/
public PdfRendererBuilder toStream(OutputStream out) {
state._os = out;
return this;
}
/**
* Set the PDF version, typically we use 1.7. If you set a lower version, it is
* your responsibility to make sure no more recent PDF features are used.
*
* @param version
* @return
*/
public PdfRendererBuilder usePdfVersion(float version) {
state._pdfVersion = version;
return this;
}
/**
* Set the PDF/A conformance, typically we use PDF/A-1
*
* Note: PDF/A documents require fonts to be embedded. So if this is not set to NONE,
* the built-in fonts will not be available and currently any text without a
* specified and embedded font will cause the renderer to crash with an exception.
*
* @param pdfAConformance
* @return
*/
public PdfRendererBuilder usePdfAConformance(PdfAConformance pdfAConformance) {
this.state._pdfAConformance = pdfAConformance;
return this;
}
/**
* Sets the color profile, needed for PDF/A conformance.
*
* You can use the sRGB.icc from https://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/resources/org/apache/pdfbox/resources/pdfa/
*
* @param colorProfile
* @return
*/
public PdfRendererBuilder useColorProfile(byte[] colorProfile) {
this.state._colorProfile = colorProfile;
return this;
}
/**
* By default, this project creates an entirely in-memory PDDocument
.
* The user can use this method to create a document either entirely on-disk
* or a mix of in-memory and on-disk using the PDDocument
constructor
* that takes a MemoryUsageSetting
.
* @param doc a (usually empty) PDDocument
* @return this for method chaining
*/
public PdfRendererBuilder usePDDocument(PDDocument doc) {
state.pddocument = doc;
return this;
}
/**
* Add a font programmatically. If the font is NOT subset, it will be downloaded
* when the renderer is run, otherwise the font will only be downloaded if
* needed. Therefore, the user could add many fonts, confidant that only those
* that are used will be downloaded and processed.
*
* The InputStream returned by the supplier will be closed by the caller. Fonts
* should generally be subset, except when used in form controls. FSSupplier is
* a lambda compatible interface.
*
* Fonts can also be added using a font-face at-rule in the CSS.
*
* @param supplier
* @param fontFamily
* @param fontWeight
* @param fontStyle
* @param subset
* @return
*/
public PdfRendererBuilder useFont(FSSupplier supplier, String fontFamily, Integer fontWeight,
FontStyle fontStyle, boolean subset) {
state._fonts.add(new AddedFont(supplier, null, fontWeight, fontFamily, subset, fontStyle));
return this;
}
/**
* Simpler overload for
* {@link #useFont(FSSupplier, String, Integer, FontStyle, boolean)}
*
* @param supplier
* @param fontFamily
* @return
*/
public PdfRendererBuilder useFont(FSSupplier supplier, String fontFamily) {
return this.useFont(supplier, fontFamily, 400, FontStyle.NORMAL, true);
}
/**
* Like {@link #useFont(FSSupplier, String, Integer, FontStyle, boolean)}, but
* allows to supply a font file. If the font file is a .ttc file it is handled
* as TrueTypeCollection. If you have the font in file form you should use this
* API.
*/
public PdfRendererBuilder useFont(File fontFile, String fontFamily, Integer fontWeight, FontStyle fontStyle,
boolean subset) {
state._fonts.add(new AddedFont(null, fontFile, fontWeight, fontFamily, subset, fontStyle));
return this;
}
/**
* Simpler overload for
* {@link #useFont(File, String, Integer, FontStyle, boolean)}
*
* @param fontFile
* @param fontFamily
* @return
*/
public PdfRendererBuilder useFont(File fontFile, String fontFamily) {
return this.useFont(fontFile, fontFamily, 400, FontStyle.NORMAL, true);
}
/**
* Set a producer on the output document
*
* @param producer
* the name of the producer to set defaults to openhtmltopdf.com
* @return this for method chaining
*/
public PdfRendererBuilder withProducer(String producer) {
state._producer = producer;
return this;
}
/**
* List of caches available.
*/
public static enum CacheStore {
/**
* Caches font metrics, based on a combined key of family name, weight and style.
* Using this cache avoids loading fallback fonts if the metrics are already in the cache
* and the previous fonts contain the needed characters.
*/
PDF_FONT_METRICS;
}
/**
* Use a specific cache. Cache values should be thread safe, so provided your cache store itself
* is thread safe can be used accross threads.
* @return this for method chaining.
* @see {@link CacheStore}
*/
public PdfRendererBuilder useCacheStore(CacheStore which, FSCacheEx cache) {
state._caches.put(which, cache);
return this;
}
static class AddedFont {
private final FSSupplier supplier;
private final File fontFile;
private final Integer weight;
private final String family;
private final boolean subset;
private final FontStyle style;
private AddedFont(FSSupplier supplier, File fontFile, Integer weight, String family,
boolean subset, FontStyle style) {
this.supplier = supplier;
this.fontFile = fontFile;
this.weight = weight;
this.family = family;
this.subset = subset;
this.style = style;
}
}
/**
* Various level of PDF/A conformance:
*
* PDF/A-1, PDF/A-2 and PDF/A-3
*/
public enum PdfAConformance {
NONE(""),
PDF_A_1("A"), PDF_A_2("B"), PDF_A_3("U");
PdfAConformance(String value) {
this.value = value;
}
private final String value;
public String getConformanceValue() {
return this.value;
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy