mirror of
https://github.com/penpot/penpot.git
synced 2026-05-23 00:43:41 +00:00
111 lines
4.2 KiB
Clojure
111 lines
4.2 KiB
Clojure
;; 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) UXBOX Labs SL
|
|
|
|
(ns app.main.ui.shapes.shape
|
|
(:require
|
|
[app.common.data :as d]
|
|
[app.common.uuid :as uuid]
|
|
[app.common.geom.matrix :as gmt]
|
|
[app.main.ui.context :as muc]
|
|
[app.main.ui.shapes.custom-stroke :as cs]
|
|
[app.main.ui.shapes.fill-image :as fim]
|
|
[app.main.ui.shapes.filters :as filters]
|
|
[app.main.ui.shapes.gradients :as grad]
|
|
[app.main.ui.shapes.svg-defs :as defs]
|
|
[app.util.object :as obj]
|
|
[rumext.alpha :as mf]
|
|
[app.util.json :as json]))
|
|
|
|
(defn add-metadata
|
|
"Adds as metadata properties that we cannot deduce from the exported SVG"
|
|
[props shape]
|
|
(let [add!
|
|
(fn [props attr val]
|
|
(let [ns-attr (str "penpot:" (-> attr d/name))]
|
|
(-> props
|
|
(obj/set! ns-attr val))))
|
|
frame? (= :frame (:type shape))
|
|
group? (= :group (:type shape))
|
|
rect? (= :text (:type shape))
|
|
text? (= :text (:type shape))
|
|
mask? (and group? (:masked-group? shape))]
|
|
(-> props
|
|
(add! :name (-> shape :name))
|
|
(add! :blocked (-> shape (:blocked false) str))
|
|
(add! :hidden (-> shape (:hidden false) str))
|
|
(add! :type (-> shape :type d/name))
|
|
|
|
(add! :stroke-style (-> shape (:stroke-style :none) d/name))
|
|
(add! :stroke-alignment (-> shape (:stroke-alignment :center) d/name))
|
|
|
|
(add! :transform (-> shape (:transform (gmt/matrix)) str))
|
|
(add! :transform-inverse (-> shape (:transform-inverse (gmt/matrix)) str))
|
|
|
|
(cond-> (and rect? (some? (:r1 shape)))
|
|
(-> (add! :r1 (-> shape (:r1 0) str))
|
|
(add! :r2 (-> shape (:r2 0) str))
|
|
(add! :r3 (-> shape (:r3 0) str))
|
|
(add! :r4 (-> shape (:r4 0) str))))
|
|
|
|
(cond-> text?
|
|
(-> (add! :grow-type (-> shape :grow-type))
|
|
(add! :content (-> shape :content json/encode))))
|
|
|
|
(cond-> mask?
|
|
(add! :masked-group "true"))
|
|
|
|
(cond-> frame?
|
|
(obj/set! "xmlns:penpot" "https://penpot.app/xmlns")))))
|
|
|
|
(mf/defc shape-container
|
|
{::mf/forward-ref true
|
|
::mf/wrap-props false}
|
|
[props ref]
|
|
(let [shape (obj/get props "shape")
|
|
children (obj/get props "children")
|
|
pointer-events (obj/get props "pointer-events")
|
|
render-id (mf/use-memo #(str (uuid/next)))
|
|
filter-id (str "filter_" render-id)
|
|
styles (-> (obj/new)
|
|
(obj/set! "pointerEvents" pointer-events)
|
|
|
|
(cond-> (and (:blend-mode shape) (not= (:blend-mode shape) :normal))
|
|
(obj/set! "mixBlendMode" (d/name (:blend-mode shape)))))
|
|
|
|
{:keys [x y width height type]} shape
|
|
frame? (= :frame type)
|
|
|
|
wrapper-props
|
|
(-> (obj/clone props)
|
|
(obj/without ["shape" "children"])
|
|
(obj/set! "ref" ref)
|
|
(obj/set! "id" (str "shape-" (:id shape)))
|
|
(obj/set! "filter" (filters/filter-str filter-id shape))
|
|
(obj/set! "style" styles)
|
|
|
|
(cond-> frame?
|
|
(-> (obj/set! "x" x)
|
|
(obj/set! "y" y)
|
|
(obj/set! "width" width)
|
|
(obj/set! "height" height)
|
|
(obj/set! "xmlnsXlink" "http://www.w3.org/1999/xlink")
|
|
(obj/set! "xmlns" "http://www.w3.org/2000/svg")))
|
|
|
|
(add-metadata shape))
|
|
|
|
wrapper-tag (if frame? "svg" "g")]
|
|
|
|
[:& (mf/provider muc/render-ctx) {:value render-id}
|
|
[:> wrapper-tag wrapper-props
|
|
[:defs
|
|
[:& defs/svg-defs {:shape shape :render-id render-id}]
|
|
[:& filters/filters {:shape shape :filter-id filter-id}]
|
|
[:& grad/gradient {:shape shape :attr :fill-color-gradient}]
|
|
[:& grad/gradient {:shape shape :attr :stroke-color-gradient}]
|
|
[:& fim/fill-image-pattern {:shape shape :render-id render-id}]
|
|
[:& cs/stroke-defs {:shape shape :render-id render-id}]]
|
|
children]]))
|