diff --git a/frontend/src/app/main/ui/shapes/gradients.cljs b/frontend/src/app/main/ui/shapes/gradients.cljs index 8a78d190f..2eb3b16cc 100644 --- a/frontend/src/app/main/ui/shapes/gradients.cljs +++ b/frontend/src/app/main/ui/shapes/gradients.cljs @@ -10,13 +10,16 @@ [app.common.data.macros :as dm] [app.common.geom.matrix :as gmt] [app.common.geom.point :as gpt] + [app.common.geom.rect :as grc] [app.common.geom.shapes :as gsh] + [app.common.pages.helpers :as cph] [app.main.ui.context :as muc] [app.main.ui.shapes.export :as ed] [app.util.object :as obj] [rumext.v2 :as mf])) -(defn add-metadata [props gradient] +(defn- add-metadata! + [props gradient] (-> props (obj/set! "penpot:gradient" "true") (obj/set! "penpot:start-x" (:start-x gradient)) @@ -25,75 +28,90 @@ (obj/set! "penpot:end-y" (:end-y gradient)) (obj/set! "penpot:width" (:width gradient)))) -(mf/defc linear-gradient [{:keys [id gradient shape]}] - (let [transform (when (= :path (:type shape)) - (gsh/transform-matrix shape nil (gpt/point 0.5 0.5))) +(mf/defc linear-gradient + {::mf/wrap-props false} + [{:keys [id gradient shape]}] + (let [transform (mf/with-memo [shape] + (when (cph/frame-shape? shape) + (gsh/transform-matrix shape nil (gpt/point 0.5 0.5)))) - base-props #js {:id id - :x1 (:start-x gradient) - :y1 (:start-y gradient) - :x2 (:end-x gradient) - :y2 (:end-y gradient) - :gradientTransform (dm/str transform)} + metadata? (mf/use-ctx ed/include-metadata-ctx) + props #js {:id id + :x1 (:start-x gradient) + :y1 (:start-y gradient) + :x2 (:end-x gradient) + :y2 (:end-y gradient) + :gradientTransform (dm/str transform)}] - include-metadata? (mf/use-ctx ed/include-metadata-ctx) - - props (cond-> base-props - include-metadata? - (add-metadata gradient))] + (when ^boolean metadata? + (add-metadata! props gradient)) [:> :linearGradient props (for [{:keys [offset color opacity]} (:stops gradient)] [:stop {:key (dm/str id "-stop-" offset) - :offset (or offset 0) + :offset (d/nilv offset 0) :stop-color color :stop-opacity opacity}])])) -(mf/defc radial-gradient [{:keys [id gradient shape]}] - (let [path? (= :path (:type shape)) - shape-transform (or (when path? (:transform shape)) (gmt/matrix)) - shape-transform-inv (or (when path? (:transform-inverse shape)) (gmt/matrix)) +(mf/defc radial-gradient + {::mf/wrap-props false} + [{:keys [id gradient shape]}] + (let [path? (cph/path-shape? shape) + + transform (when ^boolean path? + (dm/get-prop shape :transform)) + transform (d/nilv transform gmt/base) + + transform-inv (when ^boolean path? + (dm/get-prop shape :transform-inverse)) + transform-inv (d/nilv transform-inv gmt/base) {:keys [start-x start-y end-x end-y] gwidth :width} gradient - gradient-vec (gpt/to-vec (gpt/point start-x start-y) - (gpt/point end-x end-y)) + gstart-pt (gpt/point start-x start-y) + gend-pt (gpt/point end-x end-y) + gradient-vec (gpt/to-vec gstart-pt gend-pt) - angle (+ (gpt/angle gradient-vec) 90) + angle (+ (gpt/angle gradient-vec) 90) - bb-shape (gsh/shapes->rect [shape]) + points (dm/get-prop shape :points) + bounds (mf/with-memo [points] + (grc/points->rect points)) + selrect (dm/get-prop shape :selrect) - ;; Paths don't have a transform in SVG because we transform the points - ;; we need to compensate the difference between the original rectangle - ;; and the transformed one. This factor is that calculation. - factor (if path? - (/ (:height (:selrect shape)) (:height bb-shape)) - 1.0) + ;; Paths don't have a transform in SVG because we transform + ;; the points we need to compensate the difference between the + ;; original rectangle and the transformed one. This factor is + ;; that calculation. + factor (if ^boolean path? + (/ (dm/get-prop selrect :height) + (dm/get-prop bounds :height)) + 1.0) - transform (-> (gmt/matrix) - (gmt/translate (gpt/point start-x start-y)) - (gmt/multiply shape-transform) - (gmt/rotate angle) - (gmt/scale (gpt/point gwidth factor)) - (gmt/multiply shape-transform-inv) - (gmt/translate (gpt/negate (gpt/point start-x start-y)))) + transform (mf/with-memo [gradient transform transform-inv factor] + (-> (gmt/matrix) + (gmt/translate gstart-pt) + (gmt/multiply transform) + (gmt/rotate angle) + (gmt/scale (gpt/point gwidth factor)) + (gmt/multiply transform-inv) + (gmt/translate (gpt/negate gstart-pt)))) - gradient-radius (gpt/length gradient-vec) - base-props #js {:id id - :cx start-x - :cy start-y - :r gradient-radius - :gradientTransform transform} + metadata? (mf/use-ctx ed/include-metadata-ctx) - include-metadata? (mf/use-ctx ed/include-metadata-ctx) + props #js {:id id + :cx start-x + :cy start-y + :r (gpt/length gradient-vec) + :gradientTransform transform}] + + (when ^boolean metadata? + (add-metadata! props gradient)) - props (cond-> base-props - include-metadata? - (add-metadata gradient))] [:> :radialGradient props (for [{:keys [offset color opacity]} (:stops gradient)] [:stop {:key (dm/str id "-stop-" offset) - :offset (or offset 0) + :offset (d/nilv offset 0) :stop-color color :stop-opacity opacity}])]))