From 65894bf5822c0eaf69a25b3a2a7e4909231034e0 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Oct 2021 14:34:45 +0200 Subject: [PATCH 01/11] :bug: Fix problem inheriting attributes from SVG root when importing --- CHANGES.md | 1 + .../app/main/data/workspace/svg_upload.cljs | 29 +++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d80b785b85..1da95403b4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ - Fix zoom context menu in viewer [Taiga #2041](https://tree.taiga.io/project/penpot/issue/2041) - Fix stroke caps adjustments in relation with stroke size [Taiga #2123](https://tree.taiga.io/project/penpot/issue/2123) - Fix problem duplicating paths [Taiga #2147](https://tree.taiga.io/project/penpot/issue/2147) +- Fix problem inheriting attributes from SVG root when importing [Taiga #2124](https://tree.taiga.io/project/penpot/issue/2124) ### :arrow_up: Deps updates ### :boom: Breaking changes diff --git a/frontend/src/app/main/data/workspace/svg_upload.cljs b/frontend/src/app/main/data/workspace/svg_upload.cljs index 3193b549dc..2b253738af 100644 --- a/frontend/src/app/main/data/workspace/svg_upload.cljs +++ b/frontend/src/app/main/data/workspace/svg_upload.cljs @@ -178,7 +178,8 @@ :y (+ y offset-y)} (gsh/setup-selrect) (assoc :svg-attrs (-> (:attrs svg-data) - (dissoc :viewBox :xmlns)))))) + (dissoc :viewBox :xmlns) + (d/without-keys usvg/inheritable-props)))))) (defn create-group [name frame-id svg-data {:keys [attrs]}] (let [svg-transform (usvg/parse-transform (:transform attrs)) @@ -368,16 +369,16 @@ ;; SVG graphic elements ;; :circle :ellipse :image :line :path :polygon :polyline :rect :text :use (let [shape (-> (case tag - (:g :a :svg) (create-group name frame-id svg-data element-data) - :rect (create-rect-shape name frame-id svg-data element-data) + (:g :a :svg) (create-group name frame-id svg-data element-data) + :rect (create-rect-shape name frame-id svg-data element-data) (:circle - :ellipse) (create-circle-shape name frame-id svg-data element-data) - :path (create-path-shape name frame-id svg-data element-data) - :polyline (create-path-shape name frame-id svg-data (-> element-data usvg/polyline->path)) - :polygon (create-path-shape name frame-id svg-data (-> element-data usvg/polygon->path)) - :line (create-path-shape name frame-id svg-data (-> element-data usvg/line->path)) - :image (create-image-shape name frame-id svg-data element-data) - #_other (create-raw-svg name frame-id svg-data element-data)) + :ellipse) (create-circle-shape name frame-id svg-data element-data) + :path (create-path-shape name frame-id svg-data element-data) + :polyline (create-path-shape name frame-id svg-data (-> element-data usvg/polyline->path)) + :polygon (create-path-shape name frame-id svg-data (-> element-data usvg/polygon->path)) + :line (create-path-shape name frame-id svg-data (-> element-data usvg/line->path)) + :image (create-image-shape name frame-id svg-data element-data) + #_other (create-raw-svg name frame-id svg-data element-data)) ) shape (when (some? shape) @@ -387,7 +388,7 @@ (setup-stroke))) children (cond->> (:content element-data) - (= tag :g) + (or (= tag :g) (= tag :svg)) (mapv #(usvg/inherit-attributes attrs %)))] [shape children])))) @@ -487,11 +488,15 @@ ;; Creates the root shape changes (dwc/add-shape-changes page-id objects selected root-shape false) + root-attrs (-> (:attrs svg-data) + (usvg/format-styles)) + ;; Reduces the children to create the changes to add the children shapes [_ [rchanges uchanges]] (reduce (partial add-svg-child-changes page-id objects selected frame-id root-id svg-data) [unames changes] - (d/enumerate (:content svg-data))) + (d/enumerate (->> (:content svg-data) + (mapv #(usvg/inherit-attributes root-attrs %))))) reg-objects-action {:type :reg-objects :page-id page-id From 0ca7d074acbd6d2582dd0bf52351c6c4ead995dc Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Oct 2021 15:53:19 +0200 Subject: [PATCH 02/11] :bug: Fix problem with lines and inside/outside stroke --- CHANGES.md | 1 + common/src/app/common/geom/shapes.cljc | 1 + common/src/app/common/geom/shapes/path.cljc | 11 +++++ .../src/app/main/ui/shapes/custom_stroke.cljs | 41 +++++++++++-------- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1da95403b4..b894c61543 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -27,6 +27,7 @@ - Fix stroke caps adjustments in relation with stroke size [Taiga #2123](https://tree.taiga.io/project/penpot/issue/2123) - Fix problem duplicating paths [Taiga #2147](https://tree.taiga.io/project/penpot/issue/2147) - Fix problem inheriting attributes from SVG root when importing [Taiga #2124](https://tree.taiga.io/project/penpot/issue/2124) +- Fix problem with lines and inside/outside stroke [Taiga #2146](https://tree.taiga.io/project/penpot/issue/2146) ### :arrow_up: Deps updates ### :boom: Breaking changes diff --git a/common/src/app/common/geom/shapes.cljc b/common/src/app/common/geom/shapes.cljc index 30b3cb357c..86cd32d813 100644 --- a/common/src/app/common/geom/shapes.cljc +++ b/common/src/app/common/geom/shapes.cljc @@ -160,6 +160,7 @@ ;; PATHS (d/export gsp/content->selrect) (d/export gsp/transform-content) +(d/export gsp/open-path?) ;; Intersection (d/export gin/overlaps?) diff --git a/common/src/app/common/geom/shapes/path.cljc b/common/src/app/common/geom/shapes/path.cljc index b50a4ba76a..ed67249043 100644 --- a/common/src/app/common/geom/shapes/path.cljc +++ b/common/src/app/common/geom/shapes/path.cljc @@ -948,3 +948,14 @@ (gsc/transform-points points-center transform-inverse) (gpr/points->selrect))] [points selrect])) + + +(defn open-path? + [shape] + + (and (= :path (:type shape)) + (not (->> shape + :content + (sp/close-subpaths) + (sp/get-subpaths) + (every? sp/is-closed?))))) diff --git a/frontend/src/app/main/ui/shapes/custom_stroke.cljs b/frontend/src/app/main/ui/shapes/custom_stroke.cljs index 1ce51046d2..619e9954e6 100644 --- a/frontend/src/app/main/ui/shapes/custom_stroke.cljs +++ b/frontend/src/app/main/ui/shapes/custom_stroke.cljs @@ -7,6 +7,7 @@ (ns app.main.ui.shapes.custom-stroke (:require [app.common.data :as d] + [app.common.geom.shapes :as gsh] [app.main.ui.context :as muc] [app.util.object :as obj] [cuerdas.core :as str] @@ -145,22 +146,24 @@ (mf/defc stroke-defs [{:keys [shape render-id]}] - (cond - (and (= :inner (:stroke-alignment shape :center)) - (> (:stroke-width shape 0) 0)) - [:& inner-stroke-clip-path {:shape shape - :render-id render-id}] + (when (and (= (:type shape) :path) + (gsh/open-path? shape)) + (cond + (and (= :inner (:stroke-alignment shape :center)) + (> (:stroke-width shape 0) 0)) + [:& inner-stroke-clip-path {:shape shape + :render-id render-id}] - (and (= :outer (:stroke-alignment shape :center)) - (> (:stroke-width shape 0) 0)) - [:& outer-stroke-mask {:shape shape - :render-id render-id}] + (and (= :outer (:stroke-alignment shape :center)) + (> (:stroke-width shape 0) 0)) + [:& outer-stroke-mask {:shape shape + :render-id render-id}] - (and (or (some? (:stroke-cap-start shape)) - (some? (:stroke-cap-end shape))) - (= (:stroke-alignment shape) :center)) - [:& cap-markers {:shape shape - :render-id render-id}])) + (and (or (some? (:stroke-cap-start shape)) + (some? (:stroke-cap-end shape))) + (= (:stroke-alignment shape) :center)) + [:& cap-markers {:shape shape + :render-id render-id}]))) ;; Outer alingmnent: display the shape in two layers. One ;; without stroke (only fill), and another one only with stroke @@ -253,15 +256,17 @@ stroke-position (:stroke-alignment shape :center) has-stroke? (and (> stroke-width 0) (not= stroke-style :none)) - inner? (= :inner stroke-position) - outer? (= :outer stroke-position)] + closed? (or (not= :path (:type shape)) + (not (gsh/open-path? shape))) + inner? (= :inner stroke-position) + outer? (= :outer stroke-position)] (cond - (and has-stroke? inner?) + (and has-stroke? inner? closed?) [:& inner-stroke {:shape shape} child] - (and has-stroke? outer?) + (and has-stroke? outer? closed?) [:& outer-stroke {:shape shape} child] From dbbb0a4a3da32642882f59372582ef7fc2c7f556 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Oct 2021 16:07:52 +0200 Subject: [PATCH 03/11] :bug: Add stroke width in selection calculation --- CHANGES.md | 1 + .../src/app/common/geom/shapes/intersect.cljc | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b894c61543..3458549410 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -28,6 +28,7 @@ - Fix problem duplicating paths [Taiga #2147](https://tree.taiga.io/project/penpot/issue/2147) - Fix problem inheriting attributes from SVG root when importing [Taiga #2124](https://tree.taiga.io/project/penpot/issue/2124) - Fix problem with lines and inside/outside stroke [Taiga #2146](https://tree.taiga.io/project/penpot/issue/2146) +- Add stroke width in selection calculation [Taiga #2146](https://tree.taiga.io/project/penpot/issue/2146) ### :arrow_up: Deps updates ### :boom: Breaking changes diff --git a/common/src/app/common/geom/shapes/intersect.cljc b/common/src/app/common/geom/shapes/intersect.cljc index 796daf0997..3cc3589652 100644 --- a/common/src/app/common/geom/shapes/intersect.cljc +++ b/common/src/app/common/geom/shapes/intersect.cljc @@ -284,12 +284,19 @@ (defn overlaps? "General case to check for overlaping between shapes and a rectangle" [shape rect] - (or (not shape) - (let [path? (= :path (:type shape)) - circle? (= :circle (:type shape))] - (and (overlaps-rect-points? rect (:points shape)) - (or (not path?) (overlaps-path? shape rect)) - (or (not circle?) (overlaps-ellipse? shape rect)))))) + (let [stroke-width (/ (or (:stroke-width shape) 0) 2) + rect (-> rect + (update :x - stroke-width) + (update :y - stroke-width) + (update :width + (* 2 stroke-width)) + (update :height + (* 2 stroke-width)) + )] + (or (not shape) + (let [path? (= :path (:type shape)) + circle? (= :circle (:type shape))] + (and (overlaps-rect-points? rect (:points shape)) + (or (not path?) (overlaps-path? shape rect)) + (or (not circle?) (overlaps-ellipse? shape rect))))))) (defn has-point-rect? [rect point] From 679c630a4da5e40e9f77f4d97ab64f12eb8aafb8 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Oct 2021 17:01:19 +0200 Subject: [PATCH 04/11] :bug: Fix shift+wheel to horizontal scrolling in MacOS --- CHANGES.md | 1 + frontend/src/app/main/ui/workspace/viewport/actions.cljs | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 3458549410..f238908cb8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -29,6 +29,7 @@ - Fix problem inheriting attributes from SVG root when importing [Taiga #2124](https://tree.taiga.io/project/penpot/issue/2124) - Fix problem with lines and inside/outside stroke [Taiga #2146](https://tree.taiga.io/project/penpot/issue/2146) - Add stroke width in selection calculation [Taiga #2146](https://tree.taiga.io/project/penpot/issue/2146) +- Fix shift+wheel to horizontal scrolling in MacOS [#1217](https://github.com/penpot/penpot/issues/1217) ### :arrow_up: Deps updates ### :boom: Breaking changes diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs index 8ee77b05ab..b5427fb4e7 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -363,12 +363,14 @@ delta-y (-> (.-deltaY ^js event) (* unit) (/ zoom)) + delta-x (-> (.-deltaX ^js event) (* unit) (/ zoom))] (dom/prevent-default event) (dom/stop-propagation event) - (if (kbd/shift? event) + (if (and (not (cfg/check-platform? :macos)) ;; macos sends delta-x automaticaly, don't need to do it + (kbd/shift? event)) (st/emit! (dw/update-viewport-position {:x #(+ % delta-y)})) (st/emit! (dw/update-viewport-position {:x #(+ % delta-x) :y #(+ % delta-y)}))))))))) From 350c44f56f20a7a18162e7e9ff943f1d68a764b6 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 7 Oct 2021 17:53:22 +0200 Subject: [PATCH 05/11] :bug: Fix problem when calculating group bounds --- frontend/src/app/main/ui/render.cljs | 32 +++++++++++++++------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/frontend/src/app/main/ui/render.cljs b/frontend/src/app/main/ui/render.cljs index 9e550db3e0..a0a3b81dc4 100644 --- a/frontend/src/app/main/ui/render.cljs +++ b/frontend/src/app/main/ui/render.cljs @@ -25,22 +25,24 @@ [cuerdas.core :as str] [rumext.alpha :as mf])) -(defn bounds +(defn calc-bounds [object objects] - (if (= :group (:type object)) - (let [children-bounds - (into [] - (comp (map #(get objects %)) - (map #(bounds % objects))) - (:shapes object))] - (gsh/join-rects children-bounds)) - (let [padding (filters/calculate-padding object)] - (-> (filters/get-filters-bounds object) - (update :x - padding) - (update :y - padding) - (update :width + (* 2 padding)) - (update :height + (* 2 padding)))))) + (let [xf-get-bounds (comp (map #(get objects %)) (map #(calc-bounds % objects))) + padding (filters/calculate-padding object) + obj-bounds + (-> (filters/get-filters-bounds object) + (update :x - padding) + (update :y - padding) + (update :width + (* 2 padding)) + (update :height + (* 2 padding)))] + + (if (= :group (:type object)) + (->> (:shapes object) + (into [obj-bounds] xf-get-bounds) + (gsh/join-rects)) + + obj-bounds))) (mf/defc object-svg {::mf/wrap [mf/memo]} @@ -64,7 +66,7 @@ objects (reduce updt-fn objects mod-ids) object (get objects object-id) - {:keys [x y width height] :as bs} (bounds object objects) + {:keys [x y width height] :as bs} (calc-bounds object objects) [_ _ width height :as coords] (->> [x y width height] (map #(* % zoom))) vbox (str/join " " coords) From 4bf5434e8f0ee546c5813cb4babbb4ec3ac06541 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 8 Oct 2021 13:37:06 +0200 Subject: [PATCH 06/11] :bug: Fix problem when ctrl+d when moving --- common/src/app/common/path/subpaths.cljc | 10 +++- .../app/main/data/workspace/selection.cljs | 47 ++++++++++--------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/common/src/app/common/path/subpaths.cljc b/common/src/app/common/path/subpaths.cljc index 7dc19720d5..202e273b1d 100644 --- a/common/src/app/common/path/subpaths.cljc +++ b/common/src/app/common/path/subpaths.cljc @@ -73,9 +73,15 @@ (fn [subpaths current] (let [is-move? (= :move-to (:command current)) last-idx (dec (count subpaths))] - (if is-move? + (cond + is-move? (conj subpaths (make-subpath current)) - (update subpaths last-idx add-subpath-command current))))] + + (>= last-idx 0) + (update subpaths last-idx add-subpath-command current) + + :else + subpaths)))] (->> content (reduce reduce-subpath [])))) diff --git a/frontend/src/app/main/data/workspace/selection.cljs b/frontend/src/app/main/data/workspace/selection.cljs index 53127984d2..3c2e7df944 100644 --- a/frontend/src/app/main/data/workspace/selection.cljs +++ b/frontend/src/app/main/data/workspace/selection.cljs @@ -432,36 +432,37 @@ (ptk/reify ::duplicate-selected ptk/WatchEvent (watch [it state _] - (let [page-id (:current-page-id state) - objects (wsh/lookup-page-objects state page-id) - selected (wsh/lookup-selected state) - delta (if (and move-delta? (= (count selected) 1)) - (let [obj (get objects (first selected))] - (calc-duplicate-delta obj state objects)) - (gpt/point 0 0)) + (when (nil? (get-in state [:workspace-local :transform])) + (let [page-id (:current-page-id state) + objects (wsh/lookup-page-objects state page-id) + selected (wsh/lookup-selected state) + delta (if (and move-delta? (= (count selected) 1)) + (let [obj (get objects (first selected))] + (calc-duplicate-delta obj state objects)) + (gpt/point 0 0)) - unames (dwc/retrieve-used-names objects) + unames (dwc/retrieve-used-names objects) - rchanges (->> (prepare-duplicate-changes objects page-id unames selected delta) - (duplicate-changes-update-indices objects selected)) + rchanges (->> (prepare-duplicate-changes objects page-id unames selected delta) + (duplicate-changes-update-indices objects selected)) - uchanges (mapv #(array-map :type :del-obj :page-id page-id :id (:id %)) - (reverse rchanges)) + uchanges (mapv #(array-map :type :del-obj :page-id page-id :id (:id %)) + (reverse rchanges)) - id-original (when (= (count selected) 1) (first selected)) + id-original (when (= (count selected) 1) (first selected)) - selected (->> rchanges - (filter #(selected (:old-id %))) - (map #(get-in % [:obj :id])) - (into (d/ordered-set))) + selected (->> rchanges + (filter #(selected (:old-id %))) + (map #(get-in % [:obj :id])) + (into (d/ordered-set))) - id-duplicated (when (= (count selected) 1) (first selected))] + id-duplicated (when (= (count selected) 1) (first selected))] - (rx/of (dch/commit-changes {:redo-changes rchanges - :undo-changes uchanges - :origin it}) - (select-shapes selected) - (memorize-duplicated id-original id-duplicated)))))) + (rx/of (dch/commit-changes {:redo-changes rchanges + :undo-changes uchanges + :origin it}) + (select-shapes selected) + (memorize-duplicated id-original id-duplicated))))))) (defn change-hover-state [id value] From 703859ac75c8f78591951f3d4487495b5b1f8208 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Fri, 8 Oct 2021 15:00:22 +0200 Subject: [PATCH 07/11] :sparkles: Change order of the teams menu so it's in the joined time order --- CHANGES.md | 9 +++++---- backend/src/app/rpc/queries/teams.clj | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f238908cb8..63c4b1e2b7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,10 +3,15 @@ ## :rocket: Next ### :boom: Breaking changes + +- Some stroke-caps can change behaviour +- Text display bug fix could potentialy make some texts jump a line + ### :sparkles: New features - Add boolean shapes: intersections, unions, difference and exclusions. - Add advanced prototyping [#244](https://tree.taiga.io/project/penpot/us/244). +- Change order of the teams menu so it's in the joined time order ### :bug: Bugs fixed @@ -32,10 +37,6 @@ - Fix shift+wheel to horizontal scrolling in MacOS [#1217](https://github.com/penpot/penpot/issues/1217) ### :arrow_up: Deps updates -### :boom: Breaking changes - -- Some stroke-caps can change behaviour -- Text display bug fix could potentialy make some texts jump a line ### :heart: Community contributions by (Thank you!) diff --git a/backend/src/app/rpc/queries/teams.clj b/backend/src/app/rpc/queries/teams.clj index 7bad8ba598..0404d300d7 100644 --- a/backend/src/app/rpc/queries/teams.clj +++ b/backend/src/app/rpc/queries/teams.clj @@ -58,7 +58,7 @@ join team as t on (t.id = tp.team_id) where t.deleted_at is null and tp.profile_id = ? - order by t.created_at asc") + order by tp.created_at asc") (defn retrieve-teams [conn profile-id] From 950367b055a9e608e96cd5056a20d73b1fdd88db Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 11 Oct 2021 08:35:01 +0200 Subject: [PATCH 08/11] :bug: Fix path stroke is not working properly with high thickness --- CHANGES.md | 1 + frontend/src/app/main/ui/shapes/attrs.cljs | 21 ++++++++++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 63c4b1e2b7..4d18f210c6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -35,6 +35,7 @@ - Fix problem with lines and inside/outside stroke [Taiga #2146](https://tree.taiga.io/project/penpot/issue/2146) - Add stroke width in selection calculation [Taiga #2146](https://tree.taiga.io/project/penpot/issue/2146) - Fix shift+wheel to horizontal scrolling in MacOS [#1217](https://github.com/penpot/penpot/issues/1217) +- Fix path stroke is not working properly with high thickness [Taiga #2154](https://tree.taiga.io/project/penpot/issue/2154) ### :arrow_up: Deps updates diff --git a/frontend/src/app/main/ui/shapes/attrs.cljs b/frontend/src/app/main/ui/shapes/attrs.cljs index 973a155a4b..e9ca5a9669 100644 --- a/frontend/src/app/main/ui/shapes/attrs.cljs +++ b/frontend/src/app/main/ui/shapes/attrs.cljs @@ -14,12 +14,14 @@ [rumext.alpha :as mf])) (defn- stroke-type->dasharray - [style] - (case style - :mixed "5,5,1,5" - :dotted "5,5" - :dashed "10,10" - nil)) + [width style] + (let [values (case style + :mixed [5 5 1 5] + :dotted [5 5] + :dashed [10 10] + nil)] + + (->> values (map #(+ % width)) (str/join ",")))) (defn- truncate-side [shape ra-attr rb-attr dimension-attr] @@ -102,10 +104,11 @@ (defn add-stroke [attrs shape render-id] (let [stroke-style (:stroke-style shape :none) - stroke-color-gradient-id (str "stroke-color-gradient_" render-id)] + stroke-color-gradient-id (str "stroke-color-gradient_" render-id) + stroke-width (:stroke-width shape 1)] (if (not= stroke-style :none) (let [stroke-attrs - (cond-> {:strokeWidth (:stroke-width shape 1)} + (cond-> {:strokeWidth stroke-width} (:stroke-color-gradient shape) (assoc :stroke (str/format "url(#%s)" stroke-color-gradient-id)) @@ -118,7 +121,7 @@ (assoc :strokeOpacity (:stroke-opacity shape nil)) (not= stroke-style :svg) - (assoc :strokeDasharray (stroke-type->dasharray stroke-style)) + (assoc :strokeDasharray (stroke-type->dasharray stroke-width stroke-style)) ;; For simple line caps we use svg stroke-line-cap attribute. This ;; only works if all caps are the same and we are not using the tricks From 2833d3126ff1c12864ab758e4d735a04cdd0e7e7 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 11 Oct 2021 10:50:18 +0200 Subject: [PATCH 09/11] :bug: Fix bug with transformation operations --- CHANGES.md | 1 + .../app/main/data/workspace/transforms.cljs | 67 ++++++++++--------- .../main/ui/workspace/viewport/selection.cljs | 9 ++- 3 files changed, 43 insertions(+), 34 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4d18f210c6..1ad8cea695 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -36,6 +36,7 @@ - Add stroke width in selection calculation [Taiga #2146](https://tree.taiga.io/project/penpot/issue/2146) - Fix shift+wheel to horizontal scrolling in MacOS [#1217](https://github.com/penpot/penpot/issues/1217) - Fix path stroke is not working properly with high thickness [Taiga #2154](https://tree.taiga.io/project/penpot/issue/2154) +- Fix bug with transformation operations [Taiga #2155](https://tree.taiga.io/project/penpot/issue/2155) ### :arrow_up: Deps updates diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index b6f660ea44..8180690bf8 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -70,23 +70,19 @@ (defn- fix-init-point "Fix the initial point so the resizes are accurate" [initial handler shape] - (let [{:keys [x y width height]} (:selrect shape) - {:keys [rotation]} shape - rotation (or rotation 0)] - (if (= rotation 0) - (cond-> initial - (contains? #{:left :top-left :bottom-left} handler) - (assoc :x x) + (let [{:keys [x y width height]} (:selrect shape)] + (cond-> initial + (contains? #{:left :top-left :bottom-left} handler) + (assoc :x x) - (contains? #{:right :top-right :bottom-right} handler) - (assoc :x (+ x width)) + (contains? #{:right :top-right :bottom-right} handler) + (assoc :x (+ x width)) - (contains? #{:top :top-right :top-left} handler) - (assoc :y y) + (contains? #{:top :top-right :top-left} handler) + (assoc :y y) - (contains? #{:bottom :bottom-right :bottom-left} handler) - (assoc :y (+ y height))) - initial))) + (contains? #{:bottom :bottom-right :bottom-left} handler) + (assoc :y (+ y height))))) (defn finish-transform [] (ptk/reify ::finish-transform @@ -285,10 +281,19 @@ (letfn [(resize [shape initial layout [point lock? center? point-snap]] (let [{:keys [width height]} (:selrect shape) {:keys [rotation]} shape + + shape-center (gsh/center-shape shape) + shape-transform (:transform shape (gmt/matrix)) + shape-transform-inverse (:transform-inverse shape (gmt/matrix)) + rotation (or rotation 0) + initial (gsh/transform-point-center initial shape-center shape-transform-inverse) initial (fix-init-point initial handler shape) + point (gsh/transform-point-center (if (= rotation 0) point-snap point) + shape-center shape-transform-inverse) + shapev (-> (gpt/point width height)) scale-text (:scale-text layout) @@ -300,8 +305,7 @@ handler-mult (let [[x y] (handler-multipliers handler)] (gpt/point x y)) ;; Difference between the origin point in the coordinate system of the rotation - deltav (-> (gpt/to-vec initial (if (= rotation 0) point-snap point)) - (gpt/transform (gmt/rotate-matrix (- rotation))) + deltav (-> (gpt/to-vec initial point) (gpt/multiply handler-mult)) ;; Resize vector @@ -317,26 +321,25 @@ scalev) ;; Resize origin point given the selected handler - origin (handler-resize-origin (:selrect shape) handler) + handler-origin (handler-resize-origin (:selrect shape) handler) - shape-center (gsh/center-shape shape) - shape-transform (:transform shape (gmt/matrix)) - shape-transform-inverse (:transform-inverse shape (gmt/matrix)) ;; If we want resize from center, displace the shape ;; so it is still centered after resize. - displacement (when center? - (-> shape-center - (gpt/subtract origin) - (gpt/multiply scalev) - (gpt/add origin) - (gpt/subtract shape-center) - (gpt/multiply (gpt/point -1 -1)) - (gpt/transform shape-transform))) + displacement + (when center? + (-> shape-center + (gpt/subtract handler-origin) + (gpt/multiply scalev) + (gpt/add handler-origin) + (gpt/subtract shape-center) + (gpt/multiply (gpt/point -1 -1)) + (gpt/transform shape-transform))) - origin (cond-> (gsh/transform-point-center origin shape-center shape-transform) - (some? displacement) - (gpt/add displacement)) + resize-origin + (cond-> (gsh/transform-point-center handler-origin shape-center shape-transform) + (some? displacement) + (gpt/add displacement)) displacement (when (some? displacement) (gmt/translate-matrix displacement))] @@ -344,7 +347,7 @@ (rx/of (set-modifiers ids {:displacement displacement :resize-vector scalev - :resize-origin origin + :resize-origin resize-origin :resize-transform shape-transform :resize-scale-text scale-text :resize-transform-inverse shape-transform-inverse})))) diff --git a/frontend/src/app/main/ui/workspace/viewport/selection.cljs b/frontend/src/app/main/ui/workspace/viewport/selection.cljs index b8282b5d8a..9dc30ad5d2 100644 --- a/frontend/src/app/main/ui/workspace/viewport/selection.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/selection.cljs @@ -229,7 +229,12 @@ current-transform (mf/deref refs/current-transform) selrect (:selrect shape) - transform (geom/transform-matrix shape {:no-flip true})] + transform (geom/transform-matrix shape {:no-flip true}) + + rotation (-> (gpt/point 1 0) + (gpt/transform (:transform shape)) + (gpt/angle) + (mod 360))] (when (not (#{:move :rotate} current-transform)) [:g.controls {:pointer-events (if disable-handlers "none" "visible")} @@ -249,7 +254,7 @@ :on-rotate on-rotate :on-resize (partial on-resize position) :transform transform - :rotation (:rotation shape) + :rotation rotation :color color :overflow-text overflow-text} props (map->obj (merge common-props props))] From d2d506dbf03232fb315b5bc90a5d382e88805634 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 11 Oct 2021 11:54:50 +0200 Subject: [PATCH 10/11] :bug: Fix problem with mix between open/closed and line/curves --- common/src/app/common/geom/shapes/path.cljc | 33 ++++++++++----------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/common/src/app/common/geom/shapes/path.cljc b/common/src/app/common/geom/shapes/path.cljc index ed67249043..d8bd67cfc8 100644 --- a/common/src/app/common/geom/shapes/path.cljc +++ b/common/src/app/common/geom/shapes/path.cljc @@ -126,8 +126,8 @@ (let [tangent (curve-tangent curve t)] (cond - (> (:y tangent) 0) 1 - (< (:y tangent) 0) -1 + (> (:y tangent) 0) -1 + (< (:y tangent) 0) 1 :else 0))) (defn curve-split @@ -822,30 +822,27 @@ (let [selrect (content->selrect content) ray-line [point (gpt/point (inc (:x point)) (:y point))] - closed-subpaths - (->> content - (sp/close-subpaths) - (sp/get-subpaths) - (filterv sp/is-closed?)) + closed-content + (into [] + (comp (filter sp/is-closed?) + (mapcat :data)) + (->> content + (sp/close-subpaths) + (sp/get-subpaths))) cast-ray (fn [cmd] (case (:command cmd) :line-to (ray-line-intersect point (command->line cmd)) :curve-to (ray-curve-intersect ray-line (command->bezier cmd)) - #_:else [])) - - is-point-in-subpath? - (fn [subpath] - (and (gpr/contains-point? (content->selrect (:data subpath)) point) - (->> (:data subpath) - (mapcat cast-ray) - (map second) - (reduce +) - (not= 0))))] + #_:else []))] (and (gpr/contains-point? selrect point) - (some is-point-in-subpath? closed-subpaths)))) + (->> closed-content + (mapcat cast-ray) + (map second) + (reduce +) + (not= 0))))) (defn split-line-to "Given a point and a line-to command will create a two new line-to commands From ad18604552dc5cfffbc6fbfc0c9b55fd2a83386f Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 11 Oct 2021 12:15:38 +0200 Subject: [PATCH 11/11] :bug: Fix bug in firefox when a text box is inside a mask --- CHANGES.md | 1 + frontend/src/app/main/ui/shapes/group.cljs | 26 +++++++++++++++------- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1ad8cea695..2d51f8099e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -37,6 +37,7 @@ - Fix shift+wheel to horizontal scrolling in MacOS [#1217](https://github.com/penpot/penpot/issues/1217) - Fix path stroke is not working properly with high thickness [Taiga #2154](https://tree.taiga.io/project/penpot/issue/2154) - Fix bug with transformation operations [Taiga #2155](https://tree.taiga.io/project/penpot/issue/2155) +- Fix bug in firefox when a text box is inside a mask [Taiga #2152](https://tree.taiga.io/project/penpot/issue/2152) ### :arrow_up: Deps updates diff --git a/frontend/src/app/main/ui/shapes/group.cljs b/frontend/src/app/main/ui/shapes/group.cljs index 2dafc7bff5..49a6283508 100644 --- a/frontend/src/app/main/ui/shapes/group.cljs +++ b/frontend/src/app/main/ui/shapes/group.cljs @@ -27,21 +27,31 @@ [(first childs) (rest childs)] [nil childs]) + ;; We need to separate mask and clip into two because a bug in Firefox + ;; breaks when the group has clip+mask+foreignObject + ;; Clip and mask separated will work in every platform + ; Firefox bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1734805 + [clip-wrapper clip-props] + (if masked-group? + ["g" (-> (obj/new) + (obj/set! "clipPath" (clip-url render-id mask)))] + [mf/Fragment nil]) + [mask-wrapper mask-props] (if masked-group? ["g" (-> (obj/new) - (obj/set! "clipPath" (clip-url render-id mask)) (obj/set! "mask" (mask-url render-id mask)))] [mf/Fragment nil])] - [:> mask-wrapper mask-props - (when masked-group? - [:> render-mask #js {:frame frame :mask mask}]) + [:> clip-wrapper clip-props + [:> mask-wrapper mask-props + (when masked-group? + [:> render-mask #js {:frame frame :mask mask}]) - (for [item childs] - [:& shape-wrapper {:frame frame - :shape item - :key (:id item)}])])))) + (for [item childs] + [:& shape-wrapper {:frame frame + :shape item + :key (:id item)}])]]))))