;; This Source Code Form is subject to the terms of the Mozilla Public ;; License, v. 2.0. If a copy of the MPL was not distributed with this ;; file, You can obtain one at http://mozilla.org/MPL/2.0/. ;; ;; Copyright (c) KALEIDOS INC (ns app.rasterizer "A main entry point for the rasterizer process that is executed on a separated iframe." (:require [app.common.data :as d] [app.common.data.macros :as dm] [app.common.exceptions :as ex] [app.common.logging :as log] [app.config :as cf] [app.util.dom :as dom] [app.util.http :as http] [app.util.object :as obj] [app.util.webapi :as wapi] [beicon.core :as rx] [cuerdas.core :as str])) (log/set-level! :trace) (declare send-success!) (declare send-failure!) (defonce parent-origin (dm/str cf/public-uri)) (defn- get-document-element [^js svg] (.-documentElement svg)) (defn- create-image [uri] (rx/create (fn [subs] (let [image (js/Image.)] (obj/set! image "onload" #(do (rx/push! subs image) (rx/end! subs))) (obj/set! image "crossOrigin" "anonymous") (obj/set! image "onerror" #(rx/error! subs %)) (obj/set! image "onabort" #(rx/error! subs (ex/error :type :internal :code :abort :hint "operation aborted"))) (obj/set! image "src" uri) (fn [] (obj/set! image "src" "") (obj/set! image "onload" nil) (obj/set! image "onerror" nil) (obj/set! image "onabort" nil)))))) (defn- svg-get-size [svg max] (let [doc (get-document-element svg) vbox (dom/get-attribute doc "viewBox")] (when (string? vbox) (let [[_ _ width height] (str/split vbox #"\s+") width (d/parse-integer width 0) height (d/parse-integer height 0) ratio (/ width height)] (if (> width height) [max (* max (/ 1 ratio))] [(* max ratio) max]))))) (defn- svg-has-intrinsic-size? "Returns true if the SVG has an intrinsic size." [svg] (let [doc (get-document-element svg) width (dom/get-attribute doc "width") height (dom/get-attribute doc "height")] (d/num? width height))) (defn- svg-set-intrinsic-size! "Sets the intrinsic size of an SVG to the given max size." [^js svg max] (when-not (svg-has-intrinsic-size? svg) (let [doc (get-document-element svg) [w h] (svg-get-size svg max)] (dom/set-attribute! doc "width" (dm/str w)) (dom/set-attribute! doc "height" (dm/str h)))) svg) (defn- fetch-as-data-uri "Fetches a URL as a Data URI." [uri] (->> (http/send! {:uri uri :response-type :blob :method :get :mode :cors :omit-default-headers true}) (rx/map :body) (rx/mapcat wapi/read-file-as-data-url))) (defn- svg-update-image! "Updates an image in an SVG to a Data URI." [image] (if-let [href (dom/get-attribute image "href")] (->> (fetch-as-data-uri href) (rx/map (fn [url] (dom/set-attribute! image "href" url) image))) (rx/empty))) (defn- svg-resolve-images! "Resolves all images in an SVG to Data URIs." [svg] (->> (rx/from (dom/query-all svg "image")) (rx/mapcat svg-update-image!) (rx/ignore))) (defn- svg-add-style! "Adds a