diff --git a/frontend/src/app/main/data/workspace/persistence.cljs b/frontend/src/app/main/data/workspace/persistence.cljs index c7e57e890..c4fb4c05b 100644 --- a/frontend/src/app/main/data/workspace/persistence.cljs +++ b/frontend/src/app/main/data/workspace/persistence.cljs @@ -50,7 +50,7 @@ (ptk/reify ::initialize-persistence ptk/EffectEvent (effect [_ _ stream] - (let [stoper (rx/filter #(= :app.main.data.workspace/finalize %) stream) + (let [stoper (rx/filter #(= ::finalize %) stream) forcer (rx/filter #(= ::force-persist %) stream) notifier (->> stream (rx/filter dch/commit-changes?) diff --git a/frontend/src/app/main/ui/shapes/mask.cljs b/frontend/src/app/main/ui/shapes/mask.cljs index 9a0470901..f50145291 100644 --- a/frontend/src/app/main/ui/shapes/mask.cljs +++ b/frontend/src/app/main/ui/shapes/mask.cljs @@ -51,42 +51,30 @@ render-id (mf/use-ctx muc/render-ctx) svg-text? (and (= :text (:type mask)) (some? (:position-data mask))) - mask (cond-> mask svg-text? set-white-fill) - mask-bb - (cond - svg-text? - (gst/position-data-points mask) + (-> (gsh/transform-shape mask) + (:points))] + [:defs + [:filter {:id (filter-id render-id mask)} + [:feFlood {:flood-color "white" + :result "FloodResult"}] + [:feComposite {:in "FloodResult" + :in2 "SourceGraphic" + :operator "in" + :result "comp"}]] + ;; Clip path is necessary so the elements inside the mask won't affect + ;; the events outside. Clip hides the elements but mask doesn't (like display vs visibility) + ;; we cannot use clips instead of mask because clips can only be simple shapes + [:clipPath {:class "mask-clip-path" + :id (clip-id render-id mask)} + [:polyline {:points (->> mask-bb + (map #(str (:x %) "," (:y %))) + (str/join " "))}]] - :else - (-> (gsh/transform-shape mask) - (:points)))] - [:* - [:g {:opacity 0} - [:g {:id (str "shape-" (mask-id render-id mask))} - [:& shape-wrapper {:shape (dissoc mask :shadow :blur)}]]] - - [:defs - [:filter {:id (filter-id render-id mask)} - [:feFlood {:flood-color "white" - :result "FloodResult"}] - [:feComposite {:in "FloodResult" - :in2 "SourceGraphic" - :operator "in" - :result "comp"}]] - ;; Clip path is necessary so the elements inside the mask won't affect - ;; the events outside. Clip hides the elements but mask doesn't (like display vs visibility) - ;; we cannot use clips instead of mask because clips can only be simple shapes - [:clipPath {:class "mask-clip-path" - :id (clip-id render-id mask)} - [:polyline {:points (->> mask-bb - (map #(str (:x %) "," (:y %))) - (str/join " "))}]] - - [:mask {:class "mask-shape" - :id (mask-id render-id mask)} - ;; SVG texts are broken in Firefox with the filter. When the masking shapes is a text - ;; we use the `set-white-fill` instead of using the filter - [:g {:filter (when-not svg-text? (filter-url render-id mask))} - [:use {:href (str "#shape-" (mask-id render-id mask))}]]]]]))) + ;; When te shape is a text we pass to the shape the info and disable the filter. + ;; There is a bug in Firefox with filters and texts. We change the text to white at shape level + [:mask {:class "mask-shape" + :id (mask-id render-id mask)} + [:g {:filter (when-not svg-text? (filter-url render-id mask))} + [:& shape-wrapper {:shape (-> mask (dissoc :shadow :blur) (assoc :is-mask? true))}]]]]))) diff --git a/frontend/src/app/main/ui/shapes/text/svg_text.cljs b/frontend/src/app/main/ui/shapes/text/svg_text.cljs index 05c259503..03cfd7235 100644 --- a/frontend/src/app/main/ui/shapes/text/svg_text.cljs +++ b/frontend/src/app/main/ui/shapes/text/svg_text.cljs @@ -19,13 +19,27 @@ (def fill-attrs [:fill-color :fill-color-gradient :fill-opacity]) +(defn set-white-fill + [shape] + (let [update-color + (fn [data] + (-> data + (dissoc :fill-color :fill-opacity :fill-color-gradient) + (assoc :fills [{:fill-color "#FFFFFF" :fill-opacity 1}])))] + (-> shape + (d/update-when :position-data #(mapv update-color %)) + (assoc :stroke-color "#FFFFFF" :stroke-opacity 1)))) + (mf/defc text-shape {::mf/wrap-props false ::mf/wrap [mf/memo]} [props] (let [render-id (mf/use-ctx muc/render-ctx) - {:keys [x y width height position-data] :as shape} (obj/get props "shape") + shape (obj/get props "shape") + shape (cond-> shape (:is-mask? shape) set-white-fill) + + {:keys [x y width height position-data]} shape transform (str (gsh/transform-matrix shape))