Skip to content

Commit

Permalink
For #14 - Implements fluent builder api for PDF conversion.
Browse files Browse the repository at this point in the history
Examples in readme for fluent api and pluggable HTTP client - #13
  • Loading branch information
danfickle committed Mar 27, 2016
1 parent 1396f7e commit 5f0b5f2
Show file tree
Hide file tree
Showing 3 changed files with 259 additions and 13 deletions.
66 changes: 55 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ import java.io.IOException;
import java.io.OutputStream;
import com.openhtmltopdf.bidi.support.ICUBidiReorderer;
import com.openhtmltopdf.bidi.support.ICUBidiSplitter;
import com.openhtmltopdf.pdfboxout.PdfBoxRenderer;
import com.openhtmltopdf.pdfboxout.PdfRendererBuilder;
import com.openhtmltopdf.pdfboxout.PdfRendererBuilder.TextDirection;

public class SimpleUsage
{
Expand All @@ -78,18 +79,19 @@ public class SimpleUsage
os = new FileOutputStream(out);

try {
PdfBoxRenderer renderer = new PdfBoxRenderer(/* testMode = */ false);
// There are more options on the builder than shown below.
PdfRendererBuilder builder = new PdfRendererBuilder();

// The following three lines are optional. Leave them out if you do not need
// RTL or bi-directional text layout.
renderer.setBidiSplitter(new ICUBidiSplitter.ICUBidiSplitterFactory());
renderer.setDefaultTextDirection(false);
renderer.setBidiReorderer(new ICUBidiReorderer());
renderer.setDocument(url);
renderer.layout();

renderer.createPDF(os);
builder.useBidiSplitter(new ICUBidiSplitter.ICUBidiSplitterFactory());
builder.useBidiReorderer(new ICUBidiReorderer());
builder.defaultTextDirection(TextDirection.LTR);
builder.withUri(url);
builder.toStream(os);
builder.run();

} catch (Exception e) {
e.printStackTrace();
// LOG exception
Expand Down Expand Up @@ -138,7 +140,47 @@ Then you can use one of the ````Jsoup.parse```` methods to parse HTML5 and ````D
return DOMBuilder.jsoup2DOM(doc);
}
````
Then you can set the renderer document with ````renderer.setDocument(doc, url)```` in place of ````renderer.setDocument(url)````.
Then you can set the renderer document with ````builder.withW3cDocument(doc, url)```` in place of ````builder.withUri(url)````.

PLUGGABLE HTTP CLIENT
=================
Open HTML to PDF makes it simple to plugin an external client for HTTP and HTTPS requests. In fact this is recommended if you are using
HTTP/HTTPS resources, as the built-in Java client is showing its age. For example, to use the excellent [OkHttp](http://square.github.io/okhttp/) library is
as simple as adding the following code:
````java
public static class OkHttpStreamFactory implements HttpStreamFactory {
private final OkHttpClient client = new OkHttpClient();

@Override
public HttpStream getUrl(String url) {
Request request = new Request.Builder()
.url(url)
.build();

try {
final Response response = client.newCall(request).execute();

return new HttpStream() {
@Override
public InputStream getStream() {
return response.body().byteStream();
}

@Override
public Reader getReader() {
return response.body().charStream();
}
};
}
catch (IOException e) {
e.printStackTrace();
}

return null;
}
}
````
Then use ````builder.useHttpStreamImplementation(new OkHttpStreamFactory())````.

LOGGING
=======
Expand Down Expand Up @@ -182,6 +224,8 @@ CHANGELOG

head
========
+ [Added fluent builder style API for PDF conversion](https://github.com/danfickle/openhtmltopdf/issues/14)
+ [Added ability to plugin external HTTP/HTTPS implementation](https://github.com/danfickle/openhtmltopdf/issues/13)
+ [Added Jsoup HTML5 to DOM converter module](https://github.com/danfickle/openhtmltopdf/issues/12)
+ Fixed divide-by-zero error in BorderPainter class. Thanks @fenrhil
+ [Added slf4j logging facade adapter](https://github.com/danfickle/openhtmltopdf/issues/11)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,12 @@
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Rectangle2D;
import java.awt.geom.Rectangle2D.Float;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.List;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -99,6 +97,8 @@ public class PdfBoxRenderer {
private boolean _testMode;

private PDFCreationListener _listener;

private OutputStream _os;

public PdfBoxRenderer(boolean testMode) {
this(DEFAULT_DOTS_PER_POINT, DEFAULT_DOTS_PER_PIXEL, true, testMode, null);
Expand Down Expand Up @@ -137,6 +137,41 @@ public PdfBoxRenderer(float dotsPerPoint, int dotsPerPixel, boolean useSubsets,
_sharedContext.setInteractive(false);
}

public PdfBoxRenderer(boolean textDirection, boolean testMode,
boolean useSubsets, HttpStreamFactory httpStreamFactory,
BidiSplitterFactory splitterFactory, BidiReorderer reorderer, String html,
Document document, String baseUri, String uri, File file,
OutputStream os) {
this(DEFAULT_DOTS_PER_POINT, DEFAULT_DOTS_PER_PIXEL, useSubsets, testMode, httpStreamFactory);

if (splitterFactory != null) {
this.setBidiSplitter(splitterFactory);
}

if (reorderer != null) {
this.setBidiReorderer(reorderer);
}

if (html != null) {
this.setDocumentFromString(html, baseUri);
}
else if (document != null) {
this.setDocument(document, baseUri);
}
else if (uri != null) {
this.setDocument(uri);
}
else if (file != null) {
try {
this.setDocument(file);
} catch (IOException e) {
throw new RuntimeException("File IO problem", e);
}
}

this._os = os;
}

public Document getDocument() {
return _doc;
}
Expand Down Expand Up @@ -280,6 +315,10 @@ private LayoutContext newLayoutContext() {
return result;
}

public void createPDF() throws IOException {
createPDF(_os);
}

public void createPDF(OutputStream os) throws IOException {
createPDF(os, true, 0);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
package com.openhtmltopdf.pdfboxout;

import java.io.File;
import java.io.OutputStream;

import org.w3c.dom.Document;

import com.openhtmltopdf.bidi.BidiReorderer;
import com.openhtmltopdf.bidi.BidiSplitterFactory;
import com.openhtmltopdf.extend.HttpStreamFactory;
import com.openhtmltopdf.swing.NaiveUserAgent;

public class PdfRendererBuilder
{
public static enum TextDirection { RTL, LTR; }

private boolean _textDirection = false;
private boolean _testMode = false;
private boolean _useSubsets = true;
private HttpStreamFactory _httpStreamFactory = new NaiveUserAgent.DefaultHttpStreamFactory();
private BidiSplitterFactory _splitter;
private BidiReorderer _reorderer;
private String _html;
private Document _document;
private String _baseUri;
private String _uri;
private File _file;
private OutputStream _os;

/**
* 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 = this.buildPdfRenderer();
renderer.layout();
renderer.createPDF();
}

/**
* Build a PdfBoxRenderer for further customization.
* @return
*/
public PdfBoxRenderer buildPdfRenderer() {
return new PdfBoxRenderer(_textDirection, _testMode, _useSubsets, _httpStreamFactory, _splitter, _reorderer, _html, _document, _baseUri, _uri, _file, _os);
}

/**
* The default text direction of the document. LTR by default.
* @param textDirection
* @return
*/
public PdfRendererBuilder defaultTextDirection(TextDirection textDirection) {
this._textDirection = textDirection == TextDirection.RTL;
return this;
}

/**
* Whether to use test mode and output the PDF uncompressed. Turned off by default.
* @param mode
* @return
*/
public PdfRendererBuilder testMode(boolean mode) {
this._testMode = mode;
return this;
}

/**
* Whether to subset fonts, resulting in a smaller PDF. Turned on by default.
* @param subset
* @return
*/
public PdfRendererBuilder subsetFonts(boolean subset) {
this._useSubsets = subset;
return this;
}

/**
* Provides an HttpStreamFactory implementation if the user desires to use an external
* HTTP/HTTPS implementation. Uses URL::openStream by default.
* @param factory
* @return
*/
public PdfRendererBuilder useHttpStreamImplementation(HttpStreamFactory factory) {
this._httpStreamFactory = factory;
return this;
}

/**
* Provides a text splitter to split text into directional runs. Does nothing by default.
* @param splitter
* @return
*/
public PdfRendererBuilder useBidiSplitter(BidiSplitterFactory splitter) {
this._splitter = splitter;
return this;
}

/**
* Provides a reorderer to properly reverse RTL text. No-op by default.
* @param reorderer
* @return
*/
public PdfRendererBuilder useBidiReorderer(BidiReorderer reorderer) {
this._reorderer = reorderer;
return this;
}

/**
* Provides a string containing XHTML/XML to convert to PDF.
* @param html
* @param baseUri
* @return
*/
public PdfRendererBuilder withHtmlContent(String html, String baseUri) {
this._html = html;
this._baseUri = baseUri;
return this;
}

/**
* Provides a w3c DOM Document acquired from an external source.
* @param doc
* @param baseUri
* @return
*/
public PdfRendererBuilder withW3cDocument(org.w3c.dom.Document doc, String baseUri) {
this._document = doc;
this._baseUri = baseUri;
return this;
}

/**
* Provides a URI to convert to PDF. The URI MUST point to a strict XHTML/XML document.
* @param uri
* @return
*/
public PdfRendererBuilder withUri(String uri) {
this._uri = uri;
return this;
}

/**
* Provides a file to convert to PDF. The file MUST contain XHTML/XML in UTF-8 encoding.
* @param file
* @return
*/
public PdfRendererBuilder withFile(File file) {
this._file = file;
return this;
}

/**
* 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) {
this._os = out;
return this;
}
}

0 comments on commit 5f0b5f2

Please sign in to comment.