0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-10 17:18:21 -05:00

🐛 Fix problems with imported svgs

This commit is contained in:
alonso.torres 2021-09-28 15:55:28 +02:00
parent a189dc8243
commit 49c2cb985c
3 changed files with 69 additions and 29 deletions

View file

@ -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)

View file

@ -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))))))

View file

@ -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