add object drawer support

This commit is contained in:
Gered 2017-08-17 19:46:21 -04:00
parent d9e61030e5
commit 797232f2a6
2 changed files with 59 additions and 6 deletions

View file

@ -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)

View file

@ -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)))