mirror of
https://github.com/penpot/penpot.git
synced 2025-02-11 01:28:30 -05:00
🐛 Fix problems with imported svgs
This commit is contained in:
parent
a189dc8243
commit
49c2cb985c
3 changed files with 69 additions and 29 deletions
|
@ -13,23 +13,6 @@
|
|||
[app.common.path.commands :as upc]
|
||||
[app.common.path.subpaths :as ups]))
|
||||
|
||||
(defn- reverse-command
|
||||
"Reverses a single command"
|
||||
[command]
|
||||
|
||||
(let [{old-x :x old-y :y} (:params command)
|
||||
{:keys [x y]} (:prev command)
|
||||
{:keys [c1x c1y c2x c2y]} (:params command)]
|
||||
|
||||
(-> command
|
||||
(assoc :prev (gpt/point old-x old-y))
|
||||
(update :params assoc :x x :y y)
|
||||
|
||||
(cond-> (= :curve-to (:command command))
|
||||
(update :params assoc
|
||||
:c1x c2x :c1y c2y
|
||||
:c2x c1x :c2y c1y)))))
|
||||
|
||||
(defn add-previous
|
||||
([content]
|
||||
(add-previous content nil))
|
||||
|
@ -43,6 +26,37 @@
|
|||
(some? prev)
|
||||
(assoc :prev (gsp/command->point prev))))))))
|
||||
|
||||
(defn close-paths
|
||||
"Removes the :close-path commands and replace them for line-to so we can calculate
|
||||
the intersections"
|
||||
[content]
|
||||
|
||||
(loop [head (first content)
|
||||
content (rest content)
|
||||
result []
|
||||
last-move nil]
|
||||
|
||||
(if (nil? head)
|
||||
result
|
||||
(let [head-p (gsp/command->point head)
|
||||
head (cond
|
||||
(and (= :close-path (:command head))
|
||||
(< (gpt/distance head-p last-move) 0.01))
|
||||
nil
|
||||
|
||||
(= :close-path (:command head))
|
||||
(upc/make-line-to last-move)
|
||||
|
||||
:else
|
||||
head)]
|
||||
|
||||
(recur (first content)
|
||||
(rest content)
|
||||
(cond-> result (some? head) (conj head))
|
||||
(if (= :move-to (:command head))
|
||||
head-p
|
||||
last-move))))))
|
||||
|
||||
(defn- split-command
|
||||
[cmd values]
|
||||
(case (:command cmd)
|
||||
|
@ -192,8 +206,6 @@
|
|||
|
||||
;; Reverse second content so we can have holes inside other shapes
|
||||
(->> content-b-split
|
||||
(reverse)
|
||||
(mapv reverse-command)
|
||||
(filter #(and (contains-segment? % content-a)
|
||||
(not (overlap-segment? % content-a-split)))))))
|
||||
|
||||
|
@ -207,10 +219,8 @@
|
|||
|
||||
|
||||
(defn create-exclusion [content-a content-b]
|
||||
;; Pick all segments but reverse content-b (so it makes an exclusion)
|
||||
(let [content-b' (->> (reverse content-b)
|
||||
(mapv reverse-command))]
|
||||
(d/concat [] content-a content-b')))
|
||||
;; Pick all segments
|
||||
(d/concat [] content-a content-b))
|
||||
|
||||
|
||||
(defn fix-move-to
|
||||
|
@ -237,8 +247,13 @@
|
|||
(defn content-bool-pair
|
||||
[bool-type content-a content-b]
|
||||
|
||||
(let [content-a (add-previous content-a)
|
||||
content-b (add-previous content-b)
|
||||
(let [content-a (-> content-a (close-paths) (add-previous))
|
||||
|
||||
content-b (-> content-b
|
||||
(close-paths)
|
||||
(cond-> (ups/clockwise? content-b)
|
||||
(ups/reverse-content))
|
||||
(add-previous))
|
||||
|
||||
;; Split content in new segments in the intersection with the other path
|
||||
[content-a-split content-b-split] (content-intersect-split content-a content-b)
|
||||
|
|
|
@ -158,3 +158,27 @@
|
|||
(reverse)
|
||||
(mapcat :data)
|
||||
(into [])))
|
||||
|
||||
;; https://mathworld.wolfram.com/PolygonArea.html
|
||||
(defn clockwise?
|
||||
"Check whether the first subpath is clockwise or counter-clock wise"
|
||||
[content]
|
||||
(let [subpath (->> content get-subpaths first :data)]
|
||||
(loop [current (first subpath)
|
||||
subpath (rest subpath)
|
||||
first-point nil
|
||||
signed-area 0]
|
||||
|
||||
(if (nil? current)
|
||||
(> signed-area 0)
|
||||
|
||||
(let [{x1 :x y1 :y :as p} (upc/command->point current)
|
||||
last? (nil? (first subpath))
|
||||
first-point (if (nil? first-point) p first-point)
|
||||
{x2 :x y2 :y} (if last? first-point (upc/command->point (first subpath)))
|
||||
signed-area (+ signed-area (- (* x1 y2) (* x2 y1)))]
|
||||
|
||||
(recur (first subpath)
|
||||
(rest subpath)
|
||||
first-point
|
||||
signed-area))))))
|
||||
|
|
|
@ -35,8 +35,9 @@
|
|||
(map #(get childs %))
|
||||
(filter #(not (:hidden %)))
|
||||
(map #(stp/convert-to-path % childs))
|
||||
(mapv :content)
|
||||
(mapv pb/add-previous))]
|
||||
(map :content)
|
||||
(map pb/close-paths)
|
||||
(map pb/add-previous))]
|
||||
(pb/content-intersect-split content-a content-b))))]
|
||||
[:g.debug-bool
|
||||
[:g.shape-a
|
||||
|
@ -49,7 +50,7 @@
|
|||
(dissoc :fill-color :fill-opacity)
|
||||
(assoc :content content-b))
|
||||
:frame frame}]
|
||||
(for [{:keys [x y]} (gsp/content->points content-b)]
|
||||
(for [{:keys [x y]} (gsp/content->points (pb/close-paths content-b))]
|
||||
[:circle {:cx x
|
||||
:cy y
|
||||
:r 2.5
|
||||
|
@ -65,7 +66,7 @@
|
|||
(dissoc :fill-color :fill-opacity)
|
||||
(assoc :content content-a))
|
||||
:frame frame}]
|
||||
(for [{:keys [x y]} (gsp/content->points content-a)]
|
||||
(for [{:keys [x y]} (gsp/content->points (pb/close-paths content-a))]
|
||||
[:circle {:cx x
|
||||
:cy y
|
||||
:r 1.25
|
||||
|
|
Loading…
Add table
Reference in a new issue