diff --git a/src/clj_htmltopdf/core.clj b/src/clj_htmltopdf/core.clj
index e4f9fef..8f85d0a 100644
--- a/src/clj_htmltopdf/core.clj
+++ b/src/clj_htmltopdf/core.clj
@@ -2,6 +2,7 @@
(:require
[clojure.java.io :as io]
[hiccup.page :as h]
+ [clj-htmltopdf.objects :as obj]
[clj-htmltopdf.options :as o]
[clj-htmltopdf.watermark :as w])
(:import
@@ -45,15 +46,20 @@
html-doc))
(defn write-pdf!
- ^InputStream [^Document html-doc ^String base-uri]
- (let [builder (PdfRendererBuilder.)]
+ ^InputStream [^Document html-doc options]
+ (let [builder (PdfRendererBuilder.)
+ base-uri (o/->base-uri options)]
+ (obj/set-object-drawer-factory builder options)
(.withW3cDocument builder (DOMBuilder/jsoup2DOM html-doc) base-uri)
(let [piped-in (PipedInputStream.)
piped-out (PipedOutputStream. piped-in)]
(future
- (with-open [os piped-out]
- (.toStream builder os)
- (.run builder)))
+ (try
+ (with-open [os piped-out]
+ (.toStream builder os)
+ (.run builder))
+ (catch Exception ex
+ (println "Exception while rendering PDF" ex))))
piped-in)))
(defn ->pdf
@@ -61,7 +67,7 @@
(let [options (o/get-final-options options)
html-doc (prepare-html in options)]
(configure-logging! options)
- (let [pdf (write-pdf! html-doc (o/->base-uri options))
+ (let [pdf (write-pdf! html-doc options)
out (->output-stream out)]
(if (:watermark options)
(w/write-watermark! pdf out options)
diff --git a/src/clj_htmltopdf/objects.clj b/src/clj_htmltopdf/objects.clj
new file mode 100644
index 0000000..86e6c89
--- /dev/null
+++ b/src/clj_htmltopdf/objects.clj
@@ -0,0 +1,47 @@
+(ns clj-htmltopdf.objects
+ (:require
+ [clojure.string :as string])
+ (:import
+ [com.openhtmltopdf.extend FSObjectDrawer FSObjectDrawerFactory OutputDevice OutputDeviceGraphicsDrawer]
+ [com.openhtmltopdf.pdfboxout PdfRendererBuilder]
+ [org.w3c.dom Element NamedNodeMap]))
+
+(defn element-attrs->map
+ [^Element element]
+ (let [attributes (.getAttributes element)]
+ (reduce
+ (fn [m idx]
+ (let [node (.item attributes (int idx))
+ name (.getNodeName node)
+ value (.getNodeValue node)]
+ (assoc m (keyword name) value)))
+ {}
+ (range (.getLength attributes)))))
+
+(defn ->object-drawer-by-id
+ ^FSObjectDrawer [f]
+ (reify FSObjectDrawer
+ (drawObject [_ element x y width height output-device rendering-context dots-per-pixel]
+ (.drawWithGraphics
+ ^OutputDevice output-device
+ (float x)
+ (float y)
+ (float (/ width dots-per-pixel))
+ (float (/ height dots-per-pixel))
+ (reify OutputDeviceGraphicsDrawer
+ (render [_ graphics2d]
+ (f (element-attrs->map element) graphics2d)))))))
+
+(defn ->object-drawer-by-id-factory
+ ^FSObjectDrawerFactory [options]
+ (reify FSObjectDrawerFactory
+ (^FSObjectDrawer createDrawer [_ ^Element element]
+ (if (.hasAttribute element "id")
+ (let [element-id (.getAttribute element "id")]
+ (if-let [f (get-in options [:objects :by-id element-id])]
+ (->object-drawer-by-id f)))))))
+
+(defn set-object-drawer-factory
+ [^PdfRendererBuilder builder options]
+ (let [factory (->object-drawer-by-id-factory options)]
+ (.useObjectDrawerFactory builder factory)))