🐛 Fix problem with stroke and filter ordering in frames

This commit is contained in:
alonso.torres 2024-10-09 17:18:08 +02:00 committed by Andrey Antukh
parent b7a0b7d629
commit 4f16ea2d2d
4 changed files with 43 additions and 28 deletions

View file

@ -30,6 +30,7 @@
- Fix problem with go back button on error page [Taiga #8887](https://tree.taiga.io/project/penpot/issue/8887) - Fix problem with go back button on error page [Taiga #8887](https://tree.taiga.io/project/penpot/issue/8887)
- Fix problem with shadows in text for Safari [Taiga #8770](https://tree.taiga.io/project/penpot/issue/8770) - Fix problem with shadows in text for Safari [Taiga #8770](https://tree.taiga.io/project/penpot/issue/8770)
- Fix a regression with feedback form subject and content limits [Taiga #8908](https://tree.taiga.io/project/penpot/issue/8908) - Fix a regression with feedback form subject and content limits [Taiga #8908](https://tree.taiga.io/project/penpot/issue/8908)
- Fix problem with stroke and filter ordering in frames [Github #5058](https://github.com/penpot/penpot/issues/5058)
## 2.2.1 ## 2.2.1

View file

@ -15,6 +15,7 @@
[app.main.ui.context :as muc] [app.main.ui.context :as muc]
[app.main.ui.shapes.attrs :as attrs] [app.main.ui.shapes.attrs :as attrs]
[app.main.ui.shapes.custom-stroke :refer [shape-fills shape-strokes]] [app.main.ui.shapes.custom-stroke :refer [shape-fills shape-strokes]]
[app.main.ui.shapes.filters :as filters]
[app.util.debug :as dbg] [app.util.debug :as dbg]
[app.util.object :as obj] [app.util.object :as obj]
[rumext.v2 :as mf])) [rumext.v2 :as mf]))
@ -65,6 +66,11 @@
render-id (mf/use-ctx muc/render-id) render-id (mf/use-ctx muc/render-id)
filter-id-blur (dm/fmt "filter-blur-%" render-id)
filter-id-shadows (dm/fmt "filter-shadow-%" render-id)
filter-str-blur (filters/filter-str filter-id-blur shape)
filter-str-shadows (filters/filter-str filter-id-shadows shape)
x (dm/get-prop shape :x) x (dm/get-prop shape :x)
y (dm/get-prop shape :y) y (dm/get-prop shape :y)
w (dm/get-prop shape :width) w (dm/get-prop shape :width)
@ -86,9 +92,18 @@
:className "frame-background"}))) :className "frame-background"})))
path? (some? (.-d props))] path? (some? (.-d props))]
[:* ;; We need to separate blur from shadows because the blur is applied to the strokes
[:g {:clip-path (when-not ^boolean show-content? ;; while the shadows have to be placed *under* the stroke (for example, the inner shadows)
(frame-clip-url shape render-id)) ;; and the shadows needs to be applied only to the content (without the stroke)
[:g {:filter filter-str-blur}
[:defs
[:& filters/filters {:shape (dissoc shape :blur) :filter-id filter-id-shadows}]
[:& filters/filters {:shape (assoc shape :shadow []) :filter-id filter-id-blur}]]
;; This need to be separated in two layers so the clip doesn't affect the shadow filters
;; otherwise the shadow will be clipped and not visible
[:g {:filter filter-str-shadows}
[:g {:clip-path (when-not ^boolean show-content? (frame-clip-url shape render-id))
;; A frame sets back normal fill behavior (default ;; A frame sets back normal fill behavior (default
;; transparent). It may have been changed to default black ;; transparent). It may have been changed to default black
;; if a shape coming from an imported SVG file is ;; if a shape coming from an imported SVG file is
@ -101,14 +116,13 @@
[:> :path props] [:> :path props]
[:> :rect props])] [:> :rect props])]
children] children]]
[:& shape-strokes {:shape shape} [:& shape-strokes {:shape shape}
(if ^boolean path? (if ^boolean path?
[:> :path props] [:> :path props]
[:> :rect props])]])) [:> :rect props])]]))
(mf/defc frame-thumbnail-image (mf/defc frame-thumbnail-image
{::mf/wrap-props false} {::mf/wrap-props false}
[props] [props]

View file

@ -56,7 +56,6 @@
(let [shape (unchecked-get props "shape") (let [shape (unchecked-get props "shape")
children (unchecked-get props "children") children (unchecked-get props "children")
pointer-events (unchecked-get props "pointer-events") pointer-events (unchecked-get props "pointer-events")
disable-shadows? (unchecked-get props "disable-shadows?")
shape-id (dm/get-prop shape :id) shape-id (dm/get-prop shape :id)
preview-blend-mode-ref preview-blend-mode-ref
@ -67,7 +66,6 @@
type (dm/get-prop shape :type) type (dm/get-prop shape :type)
render-id (h/use-render-id) render-id (h/use-render-id)
filter-id (dm/str "filter-" render-id)
styles (-> (obj/create) styles (-> (obj/create)
(obj/set! "pointerEvents" pointer-events) (obj/set! "pointerEvents" pointer-events)
(cond-> (not (cfh/frame-shape? shape)) (cond-> (not (cfh/frame-shape? shape))
@ -82,18 +80,16 @@
shape-without-blur (dissoc shape :blur) shape-without-blur (dissoc shape :blur)
shape-without-shadows (assoc shape :shadow []) shape-without-shadows (assoc shape :shadow [])
filter-id (dm/str "filter-" render-id)
filter-str filter-str
(when (and (or (cfh/group-shape? shape) (when (or (cfh/group-shape? shape)
(cfh/frame-shape? shape)
(cfh/svg-raw-shape? shape)) (cfh/svg-raw-shape? shape))
(not disable-shadows?))
(filters/filter-str filter-id shape)) (filters/filter-str filter-id shape))
wrapper-props wrapper-props
(-> (obj/clone props) (-> (obj/clone props)
(obj/unset! "shape") (obj/unset! "shape")
(obj/unset! "children") (obj/unset! "children")
(obj/unset! "disable-shadows?")
(obj/set! "ref" ref) (obj/set! "ref" ref)
(obj/set! "id" (dm/fmt "shape-%" shape-id)) (obj/set! "id" (dm/fmt "shape-%" shape-id))
(obj/set! "style" styles)) (obj/set! "style" styles))
@ -130,9 +126,14 @@
[:defs [:defs
[:& defs/svg-defs {:shape shape :render-id render-id}] [:& defs/svg-defs {:shape shape :render-id render-id}]
;; The filters for frames should be setup inside the container.
(when-not (cfh/frame-shape? shape)
[:*
[:& filters/filters {:shape shape :filter-id filter-id}] [:& filters/filters {:shape shape :filter-id filter-id}]
[:& filters/filters {:shape shape-without-blur :filter-id (dm/fmt "filter-shadow-%" render-id)}] [:& filters/filters {:shape shape-without-blur :filter-id (dm/fmt "filter-shadow-%" render-id)}]
[:& filters/filters {:shape shape-without-shadows :filter-id (dm/fmt "filter-blur-%" render-id)}] [:& filters/filters {:shape shape-without-shadows :filter-id (dm/fmt "filter-blur-%" render-id)}]])
[:& frame/frame-clip-def {:shape shape :render-id render-id}] [:& frame/frame-clip-def {:shape shape :render-id render-id}]
;; Text fills need to be defined afterwards because they are specified per text-block ;; Text fills need to be defined afterwards because they are specified per text-block

View file

@ -8,7 +8,6 @@
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm] [app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
[app.common.geom.shapes.bounds :as gsb] [app.common.geom.shapes.bounds :as gsb]
[app.common.math :as mth] [app.common.math :as mth]
[app.common.thumbnails :as thc] [app.common.thumbnails :as thc]
@ -45,7 +44,7 @@
(refs/children-objects shape-id)) (refs/children-objects shape-id))
childs (mf/deref childs-ref)] childs (mf/deref childs-ref)]
[:& shape-container {:shape shape :ref ref :disable-shadows? (cfh/is-direct-child-of-root? shape)} [:& shape-container {:shape shape :ref ref}
[:& frame-shape {:shape shape :childs childs}] [:& frame-shape {:shape shape :childs childs}]
(when *assert* (when *assert*
[:& wsd/shape-debug {:shape shape}])])))) [:& wsd/shape-debug {:shape shape}])]))))
@ -187,7 +186,7 @@
(fdm/use-dynamic-modifiers objects (mf/ref-val content-ref) modifiers) (fdm/use-dynamic-modifiers objects (mf/ref-val content-ref) modifiers)
[:& shape-container {:shape shape :disable-shadows? thumbnail?} [:& shape-container {:shape shape}
[:g.frame-container [:g.frame-container
{:id (dm/str "frame-container-" frame-id) {:id (dm/str "frame-container-" frame-id)
:key "frame-container" :key "frame-container"