♻️ Rename content functions and bindings to path-data

Rename local bindings, function names, parameters, and public API
functions that reference path content to use path-data consistently
across the codebase (Phase 2 + Phase 3 of the rename effort):

Phase 2 - Local bindings and data-layer functions:
- Rename functions: set-content -> set-path-data, save-path-content ->
  save-path-data, check-changed-content -> check-changed-path-data,
  apply-content-modifiers -> apply-path-data-modifiers,
  modify-content-point -> modify-path-data-point, path-content-ref ->
  path-data-ref, content->string -> path-data->string, get-content ->
  get-path-data, content-stream -> path-data-stream
- Fix 4 bugs where :content was still used instead of :path-data
- Fix extra closing paren in edition.cljs

Phase 3 - Path module public API functions:
- path.cljc facade: content? -> path-data?, content -> path-data,
  check-content -> check-path-data, schema:content -> schema:path-data,
  apply-content-modifiers -> apply-path-data-modifiers,
  transform-content -> transform-path-data, move-content -> move-path-data,
  calc-bool-content -> calc-bool-path-data
- segment.cljc: transform-content -> transform-path-data,
  move-content -> move-path-data, content->selrect -> path-data->selrect,
  content-center -> path-data-center, points->content -> points->path-data
- subpath.cljc: reverse-content -> reverse-path-data
- bool.cljc: content-intersect-split -> path-data-intersect-split,
  close-content -> close-path-data, content->geom-data -> path-data->geom-data,
  content-bool-pair -> path-data-bool-pair, calculate-content -> calculate-path-data
- impl.cljc: schema:content -> schema:path-data, check-content -> check-path-data
- Update all callers across common, frontend, and legacy migrations
- Update all test files for renamed functions

Signed-off-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
Andrey Antukh 2026-03-30 12:01:49 +00:00
parent d0eeb8cb50
commit 4dcb9d6d38
35 changed files with 541 additions and 544 deletions

View File

@ -149,8 +149,8 @@
[data _]
(letfn [(migrate-path [shape]
(if-not (contains? shape :content)
(let [content (path.segment/points->content (:segments shape) :close (:close? shape))
selrect (path.segment/content->selrect content)
(let [content (path.segment/points->path-data (:segments shape) :close (:close? shape))
selrect (path.segment/path-data->selrect content)
points (grc/rect->points selrect)]
(-> shape
(dissoc :segments)
@ -221,7 +221,7 @@
(if (= (:type shape) :path)
(let [{:keys [width height]} (grc/points->rect (:points shape))]
(if (or (mth/almost-zero? width) (mth/almost-zero? height))
(let [selrect (path.segment/content->selrect (:content shape))
(let [selrect (path.segment/path-data->selrect (:content shape))
points (grc/rect->points selrect)
transform (gmt/matrix)
transform-inv (gmt/matrix)]
@ -1336,16 +1336,16 @@
(cfh/path-shape? object))
(let [content (get object :content)
content (cond
(path/content? content)
(path/path-data? content)
content
(nil? content)
(path/content [])
(path/path-data [])
:else
(-> content
(decode-segments)
(path/content)))]
(path/path-data)))]
(assoc object :content content))
object))

View File

@ -343,11 +343,11 @@
(defn create-path-shape [name frame-id svg-data {:keys [attrs] :as data}]
(when (and (contains? attrs :d) (seq (:d attrs)))
(let [transform (csvg/parse-transform (:transform attrs))
content (cond-> (path/from-string (:d attrs))
path-data (cond-> (path/from-string (:d attrs))
(some? transform)
(path.segm/transform-content transform))
(path.segm/transform-path-data transform))
selrect (path.segm/content->selrect content)
selrect (path.segm/path-data->selrect path-data)
points (grc/rect->points selrect)
origin (gpt/negate (gpt/point svg-data))
attrs (-> (dissoc attrs :d :transform)
@ -356,7 +356,7 @@
{:type :path
:name name
:frame-id frame-id
:path-data content
:path-data path-data
:selrect selrect
:points points
:svg-viewbox selrect

View File

@ -99,7 +99,7 @@
(d/update-when :y d/safe+ dy)
(d/update-when :position-data move-position-data mvec)
(cond-> (or (= :bool type) (= :path type))
(update :path-data path/move-content mvec)))))
(update :path-data path/move-path-data mvec)))))
;; --- Absolute Movement
@ -324,7 +324,7 @@
(update shape :position-data transform-position-data transform-mtx)
shape)
shape (if (or (= type :path) (= type :bool))
(update shape :path-data path/transform-content transform-mtx)
(update shape :path-data path/transform-path-data transform-mtx)
(assoc shape
:x (dm/get-prop selrect :x)
:y (dm/get-prop selrect :y)
@ -360,7 +360,7 @@
360)
shape (if (or (= type :path) (= type :bool))
(update shape :path-data path/transform-content transform-mtx)
(update shape :path-data path/transform-path-data transform-mtx)
(assoc shape
:x (dm/get-prop selrect :x)
:y (dm/get-prop selrect :y)

View File

@ -1890,19 +1890,19 @@
(defn- set-path-new-values
[current-shape prev-shape transform]
(let [new-content (segment/transform-content
(:content current-shape)
(let [new-path-data (segment/transform-path-data
(:path-data current-shape)
(gmt/transform-in (gpt/point 0 0) transform))
new-points (-> (segment/content->selrect new-content)
new-points (-> (segment/path-data->selrect new-path-data)
(grc/rect->points))
points-center (gco/points->center new-points)
new-selrect (gsh/calculate-selrect new-points points-center)
shape (assoc current-shape
:content new-content
:path-data new-path-data
:points new-points
:selrect new-selrect)
prev-center (segment/content-center (:content prev-shape))
prev-center (segment/path-data-center (:path-data prev-shape))
delta (gpt/subtract points-center (first new-points))
new-pos (gpt/subtract prev-center delta)]
(gsh/absolute-move shape new-pos)))

View File

@ -30,20 +30,20 @@
[]
(bool/get-default-fills))
(def schema:content impl/schema:content)
(def schema:path-data impl/schema:path-data)
(def schema:segments impl/schema:segments)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; CONSTRUCTORS & TYPE METHODS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn content?
(defn path-data?
[o]
(impl/path-data? o))
(defn content
"Create path content from plain data or bytes, returns itself if it
is already PathData instance"
(defn path-data
"Create path data from plain data or bytes, returns itself if it
is already PathData instance"
[data]
(impl/path-data data))
@ -59,48 +59,48 @@
[data]
(impl/from-plain data))
(defn check-content
[content]
(impl/check-content content))
(defn check-path-data
[path-data]
(impl/check-path-data path-data))
(defn get-byte-size
"Get byte size of a path content"
[content]
(impl/-get-byte-size content))
"Get byte size of path data"
[path-data]
(impl/-get-byte-size path-data))
(defn write-to
[content buffer offset]
(impl/-write-to content buffer offset))
[path-data buffer offset]
(impl/-write-to path-data buffer offset))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; TRANSFORMATIONS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn close-subpaths
"Given a content, searches a path for possible subpaths that can
create closed loops and merge them; then return the transformed path
conten as PathData instance"
[content]
(-> (subpath/close-subpaths content)
"Given path-data, searches a path for possible subpaths that can
create closed loops and merge them; then return the transformed path
data as PathData instance"
[path-data]
(-> (subpath/close-subpaths path-data)
(impl/from-plain)))
(defn apply-content-modifiers
"Apply delta modifiers over the path content"
[content modifiers]
(assert (impl/check-content content))
(defn apply-path-data-modifiers
"Apply delta modifiers over the path data"
[path-data modifiers]
(assert (impl/check-path-data path-data))
(letfn [(apply-to-index [content [index params]]
(if (contains? content index)
(cond-> content
(letfn [(apply-to-index [path-data [index params]]
(if (contains? path-data index)
(cond-> path-data
(and
(or (:c1x params) (:c1y params) (:c2x params) (:c2y params))
(= :line-to (get-in content [index :command])))
(= :line-to (get-in path-data [index :command])))
(-> (assoc-in [index :command] :curve-to)
(assoc-in [index :params]
(helpers/make-curve-params
(get-in content [index :params])
(get-in content [(dec index) :params]))))
(get-in path-data [index :params])
(get-in path-data [(dec index) :params]))))
(:x params) (update-in [index :params :x] + (:x params))
(:y params) (update-in [index :params :y] + (:y params))
@ -110,29 +110,29 @@
(:c2x params) (update-in [index :params :c2x] + (:c2x params))
(:c2y params) (update-in [index :params :c2y] + (:c2y params)))
content))]
path-data))]
(if (some? modifiers)
(impl/path-data
(reduce apply-to-index (vec content) modifiers))
content)))
(reduce apply-to-index (vec path-data) modifiers))
path-data)))
(defn transform-content
"Applies a transformation matrix over content and returns a new
content as PathData instance."
[content transform]
(segment/transform-content content transform))
(defn transform-path-data
"Applies a transformation matrix over path-data and returns a new
path-data as PathData instance."
[path-data transform]
(segment/transform-path-data path-data transform))
(defn move-content
[content move-vec]
(defn move-path-data
[path-data move-vec]
(if (gpt/zero? move-vec)
content
(segment/move-content content move-vec)))
path-data
(segment/move-path-data path-data move-vec)))
(defn update-geometry
"Update shape with new geometry calculated from provided content"
([shape content]
(update-geometry (assoc shape :path-data content)))
"Update shape with new geometry calculated from provided path-data"
([shape path-data]
(update-geometry (assoc shape :path-data path-data)))
([shape]
(let [flip-x
(get shape :flip-x)
@ -141,7 +141,7 @@
(get shape :flip-y)
;; NOTE: we ensure that content is PathData instance
content
path-data
(impl/path-data
(get shape :path-data))
@ -159,14 +159,14 @@
center
(or (some-> (dm/get-prop shape :selrect) grc/rect->center)
(segment/content-center content))
(segment/path-data-center path-data))
base-content
(segment/transform-content content (gmt/transform-in center transform-inverse))
base-path-data
(segment/transform-path-data path-data (gmt/transform-in center transform-inverse))
;; Calculates the new selrect with points given the old center
points
(-> (segment/content->selrect base-content)
(-> (segment/path-data->selrect base-path-data)
(grc/rect->points)
(gco/transform-points center transform))
@ -181,7 +181,7 @@
(grc/points->rect))]
(-> shape
(assoc :path-data content)
(assoc :path-data path-data)
(assoc :points points)
(assoc :selrect selrect)))))
@ -190,66 +190,66 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn get-points
"Returns points for the given content. Accepts PathData instances or
plain segment vectors. Returns nil for nil content."
[content]
(when (some? content)
(let [content (if (impl/path-data? content)
content
(impl/path-data content))]
(segment/get-points content))))
"Returns points for the given path-data. Accepts PathData instances or
plain segment vectors. Returns nil for nil path-data."
[path-data]
(when (some? path-data)
(let [path-data (if (impl/path-data? path-data)
path-data
(impl/path-data path-data))]
(segment/get-points path-data))))
(defn calc-selrect
"Calculate selrect from a content. The content can be in a PathData
instance or plain vector of segments."
[content]
(segment/content->selrect content))
"Calculate selrect from path-data. The path-data can be in a PathData
instance or plain vector of segments."
[path-data]
(segment/path-data->selrect path-data))
(defn- calc-bool-content*
"Calculate the boolean content from shape and objects. Returns plain
vector of segments"
(defn- calc-bool-path-data*
"Calculate the boolean path-data from shape and objects. Returns plain
vector of segments"
[shape objects]
(let [extract-content-xf
(let [extract-path-data-xf
(comp (map (d/getf objects))
(remove :hidden)
(remove cpf/svg-raw-shape?)
(map #(stp/convert-to-path % objects))
(map :path-data))
contents
(sequence extract-content-xf (:shapes shape))]
path-data-items
(sequence extract-path-data-xf (:shapes shape))]
(ex/try!
(bool/calculate-content (:bool-type shape) contents)
(bool/calculate-path-data (:bool-type shape) path-data-items)
:on-exception
(fn [cause]
(ex/raise :type :internal
:code :invalid-path-content
:hint (str "unable to calculate bool content for shape " (:id shape))
:hint (str "unable to calculate bool path-data for shape " (:id shape))
:shapes (:shapes shape)
:type (:bool-type shape)
:path-data (vec contents)
:path-data (vec path-data-items)
:cause cause)))))
(def wasm:calc-bool-content
"A overwrite point for setup a WASM version of the `calc-bool-content*` function"
(def wasm:calc-bool-path-data
"A overwrite point for setup a WASM version of the `calc-bool-path-data*` function"
nil)
(defn calc-bool-content
"Calculate the boolean content from shape and objects. Returns a
packed PathData instance"
(defn calc-bool-path-data
"Calculate the boolean path-data from shape and objects. Returns a
packed PathData instance"
[shape objects]
(let [content (calc-bool-content* shape objects)]
(impl/path-data content)))
(let [path-data (calc-bool-path-data* shape objects)]
(impl/path-data path-data)))
(defn update-bool-shape
"Calculates the selrect+points for the boolean shape"
[shape objects]
(let [content (if (fn? wasm:calc-bool-content)
(wasm:calc-bool-content shape objects)
(calc-bool-content shape objects))
shape (assoc shape :path-data content)]
(let [path-data (if (fn? wasm:calc-bool-path-data)
(wasm:calc-bool-path-data shape objects)
(calc-bool-path-data shape objects))
shape (assoc shape :path-data path-data)]
(update-geometry shape)))
(defn shape-with-open-path?

View File

@ -33,10 +33,10 @@
[:fills :strokes]))
(defn add-previous
([content]
(add-previous content nil))
([content first]
(->> (d/with-prev content)
([path-data]
(add-previous path-data nil))
([path-data first]
(->> (d/with-prev path-data)
(mapv (fn [[cmd prev]]
(cond-> cmd
(and (nil? prev) (some? first))
@ -47,10 +47,10 @@
(defn close-paths
"Removes the :close-path commands and replace them for line-to so we can calculate
the intersections"
[content]
the intersections"
[path-data]
(loop [segments (seq content)
(loop [segments (seq path-data)
result []
last-move nil
last-point nil]
@ -117,8 +117,8 @@
:else
[[] []])))
(defn content-intersect-split
[content-a content-b sr-a sr-b]
(defn path-data-intersect-split
[path-data-a path-data-b sr-a sr-b]
(let [command->selrect (memoize helpers/command->selrect)]
@ -143,9 +143,9 @@
(-> (split-command seg-1 ts-seg-1)
(add-previous (:prev seg-1))))))
(split-segment-on-content [segment content content-sr]
(if (overlap-segment-selrect? segment content-sr)
(->> content
(split-segment-on-path-data [segment path-data path-data-sr]
(if (overlap-segment-selrect? segment path-data-sr)
(->> path-data
(filter #(overlap-segments? segment %))
(reduce
(fn [result current]
@ -153,13 +153,13 @@
[segment]))
[segment]))
(split-content [content-a content-b sr-b]
(split-path-data [path-data-a path-data-b sr-b]
(into []
(mapcat #(split-segment-on-content % content-b sr-b))
content-a))]
(mapcat #(split-segment-on-path-data % path-data-b sr-b))
path-data-a))]
[(split-content content-a content-b sr-b)
(split-content content-b content-a sr-a)])))
[(split-path-data path-data-a path-data-b sr-b)
(split-path-data path-data-b path-data-a sr-a)])))
(defn is-segment?
[cmd]
@ -167,7 +167,7 @@
(contains? #{:line-to :curve-to} (:command cmd))))
(defn contains-segment?
[segment content content-sr content-geom]
[segment path-data path-data-sr path-data-geom]
(let [point (case (:command segment)
:line-to (-> (helpers/command->line segment)
@ -176,13 +176,13 @@
:curve-to (-> (helpers/command->bezier segment)
(helpers/curve-values 0.5)))]
(and (grc/contains-point? content-sr point)
(and (grc/contains-point? path-data-sr point)
(or
(helpers/is-point-in-geom-data? point content-geom)
(helpers/is-point-in-border? point content)))))
(helpers/is-point-in-geom-data? point path-data-geom)
(helpers/is-point-in-border? point path-data)))))
(defn inside-segment?
[segment content-sr content-geom]
[segment path-data-sr path-data-geom]
(let [point (case (:command segment)
:line-to (-> (helpers/command->line segment)
(helpers/line-values 0.5))
@ -190,13 +190,13 @@
:curve-to (-> (helpers/command->bezier segment)
(helpers/curve-values 0.5)))]
(and (grc/contains-point? content-sr point)
(helpers/is-point-in-geom-data? point content-geom))))
(and (grc/contains-point? path-data-sr point)
(helpers/is-point-in-geom-data? point path-data-geom))))
(defn overlap-segment?
"Finds if the current segment is overlapping against other
segment meaning they have the same coordinates"
[segment content]
segment meaning they have the same coordinates"
[segment path-data]
(let [overlap-single?
(fn [other]
@ -228,17 +228,17 @@
[segment other])))))]
(->> content
(->> path-data
(d/seek overlap-single?)
(some?))))
(defn fix-move-to
[content]
[path-data]
;; Remove the field `:prev` and makes the necessaries `move-to`
;; then clean the subpaths
(loop [current (first content)
content (rest content)
(loop [current (first path-data)
path-data (rest path-data)
prev nil
result []]
@ -248,14 +248,14 @@
(let [result (if (not= (:prev current) prev)
(conj result (helpers/make-move-to (:prev current)))
result)]
(recur (first content)
(rest content)
(recur (first path-data)
(rest path-data)
(helpers/segment->point current)
(conj result (dissoc current :prev)))))))
(defn remove-duplicated-segments
"Remove from the content segments"
[content]
"Remove from the path-data segments"
[path-data]
(letfn [;; This is a comparator for float points with a precission
;; used to remove already existing segments
(comparator [[fx1 fy1 tx1 ty1 :as v1] [fx2 fy2 tx2 ty2 :as v2]]
@ -266,8 +266,8 @@
0 ;; equal
(compare v1 v2)))]
(loop [current (first content)
content (rest content)
(loop [current (first path-data)
path-data (rest path-data)
segments (sorted-set-by comparator)
result []]
@ -287,24 +287,24 @@
segments (conj segments [fx fy tx ty])]
(recur (first content)
(rest content)
(recur (first path-data)
(rest path-data)
segments
result))))))
(defn close-content
[content]
(defn close-path-data
[path-data]
(into []
(mapcat :data)
(->> content
(->> path-data
(subpath/close-subpaths)
(subpath/get-subpaths))))
(defn- content->geom-data
[content]
(defn- path-data->geom-data
[path-data]
(->> content
(close-content)
(->> path-data
(close-path-data)
(filter #(not= (= :line-to (:command %))
(= :curve-to (:command %))))
(mapv (fn [segment]
@ -315,115 +315,115 @@
(helpers/command->bezier segment))
:selrect (helpers/command->selrect segment)}))))
(defn create-union [content-a content-a-split content-b content-b-split sr-a sr-b]
;; Pick all segments in content-a that are not inside content-b
;; Pick all segments in content-b that are not inside content-a
(let [content-a-geom (content->geom-data content-a)
content-b-geom (content->geom-data content-b)
(defn create-union [path-data-a path-data-a-split path-data-b path-data-b-split sr-a sr-b]
;; Pick all segments in path-data-a that are not inside path-data-b
;; Pick all segments in path-data-b that are not inside path-data-a
(let [path-data-a-geom (path-data->geom-data path-data-a)
path-data-b-geom (path-data->geom-data path-data-b)
content
result
(concat
(->> content-a-split (filter #(not (contains-segment? % content-b sr-b content-b-geom))))
(->> content-b-split (filter #(not (contains-segment? % content-a sr-a content-a-geom)))))
(->> path-data-a-split (filter #(not (contains-segment? % path-data-b sr-b path-data-b-geom))))
(->> path-data-b-split (filter #(not (contains-segment? % path-data-a sr-a path-data-a-geom)))))
content-geom (content->geom-data content)
result-geom (path-data->geom-data result)
content-sr (segment/content->selrect (fix-move-to content))
result-sr (segment/path-data->selrect (fix-move-to result))
;; Overlapping segments should be added when they are part of the border
border-content
(->> content-b-split
(filter #(and (contains-segment? % content-a sr-a content-a-geom)
(overlap-segment? % content-a-split)
(not (inside-segment? % content-sr content-geom)))))]
border-path-data
(->> path-data-b-split
(filter #(and (contains-segment? % path-data-a sr-a path-data-a-geom)
(overlap-segment? % path-data-a-split)
(not (inside-segment? % result-sr result-geom)))))]
;; Ensure that the output is always a vector
(d/concat-vec content border-content)))
(d/concat-vec result border-path-data)))
(defn create-difference [content-a content-a-split content-b content-b-split sr-a sr-b]
;; Pick all segments in content-a that are not inside content-b
;; Pick all segments in content b that are inside content-a
(defn create-difference [path-data-a path-data-a-split path-data-b path-data-b-split sr-a sr-b]
;; Pick all segments in path-data-a that are not inside path-data-b
;; Pick all segments in path-data-b that are inside path-data-a
;; removing overlapping
(let [content-a-geom (content->geom-data content-a)
content-b-geom (content->geom-data content-b)]
(let [path-data-a-geom (path-data->geom-data path-data-a)
path-data-b-geom (path-data->geom-data path-data-b)]
(d/concat-vec
(->> content-a-split (filter #(not (contains-segment? % content-b sr-b content-b-geom))))
(->> path-data-a-split (filter #(not (contains-segment? % path-data-b sr-b path-data-b-geom))))
;; Reverse second content so we can have holes inside other shapes
(->> content-b-split
(filter #(and (contains-segment? % content-a sr-a content-a-geom)
(not (overlap-segment? % content-a-split))))))))
;; Reverse second path-data so we can have holes inside other shapes
(->> path-data-b-split
(filter #(and (contains-segment? % path-data-a sr-a path-data-a-geom)
(not (overlap-segment? % path-data-a-split))))))))
(defn create-intersection [content-a content-a-split content-b content-b-split sr-a sr-b]
;; Pick all segments in content-a that are inside content-b
;; Pick all segments in content-b that are inside content-a
(let [content-a-geom (content->geom-data content-a)
content-b-geom (content->geom-data content-b)]
(defn create-intersection [path-data-a path-data-a-split path-data-b path-data-b-split sr-a sr-b]
;; Pick all segments in path-data-a that are inside path-data-b
;; Pick all segments in path-data-b that are inside path-data-a
(let [path-data-a-geom (path-data->geom-data path-data-a)
path-data-b-geom (path-data->geom-data path-data-b)]
(d/concat-vec
(->> content-a-split (filter #(contains-segment? % content-b sr-b content-b-geom)))
(->> content-b-split (filter #(contains-segment? % content-a sr-a content-a-geom))))))
(->> path-data-a-split (filter #(contains-segment? % path-data-b sr-b path-data-b-geom)))
(->> path-data-b-split (filter #(contains-segment? % path-data-a sr-a path-data-a-geom))))))
(defn create-exclusion [content-a content-b]
(defn create-exclusion [path-data-a path-data-b]
;; Pick all segments
(d/concat-vec content-a content-b))
(d/concat-vec path-data-a path-data-b))
(defn content-bool-pair
[bool-type content-a content-b]
(defn path-data-bool-pair
[bool-type path-data-a path-data-b]
(let [;; We need to reverse the second path when making a difference/intersection/exclude
;; and both shapes are in the same direction
should-reverse?
(and (not= :union bool-type)
(= (subpath/clockwise? content-b)
(subpath/clockwise? content-a)))
(= (subpath/clockwise? path-data-b)
(subpath/clockwise? path-data-a)))
content-a
(-> content-a
path-data-a
(-> path-data-a
(close-paths)
(add-previous))
content-b
(-> content-b
path-data-b
(-> path-data-b
(close-paths)
(cond-> should-reverse? (subpath/reverse-content))
(cond-> should-reverse? (subpath/reverse-path-data))
(add-previous))
sr-a
(segment/content->selrect content-a)
(segment/path-data->selrect path-data-a)
sr-b
(segment/content->selrect content-b)
(segment/path-data->selrect path-data-b)
;; 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 sr-a sr-b)
;; Split path-data in new segments in the intersection with the other path
[path-data-a-split path-data-b-split]
(path-data-intersect-split path-data-a path-data-b sr-a sr-b)
content-a-split
(->> content-a-split add-previous (filter is-segment?))
path-data-a-split
(->> path-data-a-split add-previous (filter is-segment?))
content-b-split
(->> content-b-split add-previous (filter is-segment?))
path-data-b-split
(->> path-data-b-split add-previous (filter is-segment?))
content
result
(case bool-type
:union (create-union content-a content-a-split content-b content-b-split sr-a sr-b)
:difference (create-difference content-a content-a-split content-b content-b-split sr-a sr-b)
:intersection (create-intersection content-a content-a-split content-b content-b-split sr-a sr-b)
:exclude (create-exclusion content-a-split content-b-split))]
:union (create-union path-data-a path-data-a-split path-data-b path-data-b-split sr-a sr-b)
:difference (create-difference path-data-a path-data-a-split path-data-b path-data-b-split sr-a sr-b)
:intersection (create-intersection path-data-a path-data-a-split path-data-b path-data-b-split sr-a sr-b)
:exclude (create-exclusion path-data-a-split path-data-b-split))]
(-> content
(-> result
remove-duplicated-segments
fix-move-to
subpath/close-subpaths)))
(defn calculate-content
"Create a bool content from a collection of contents and specified
type. Returns plain segments"
[bool-type contents]
(defn calculate-path-data
"Create a bool path-data from a collection of path-data items and
specified type. Returns plain segments"
[bool-type path-data-items]
;; We apply the boolean operation in to each pair and the result to the next
;; element
(if (seq contents)
(->> contents
(reduce (partial content-bool-pair bool-type))
(if (seq path-data-items)
(->> path-data-items
(reduce (partial path-data-bool-pair bool-type))
(vec))
[]))

View File

@ -528,9 +528,9 @@
(declare from-string)
(declare from-plain)
(def schema:content
(def schema:path-data
(sm/type-schema
{:type ::path/content
{:type ::path/path-data
:compile
(fn [_ _ _]
(let [decoder (delay (sm/decoder schema:segments sm/json-transformer))
@ -563,8 +563,8 @@
(def check-segment
(sm/check-fn schema:segment))
(def check-content
(sm/check-fn schema:content))
(def check-path-data
(sm/check-fn schema:path-data))
(def decode-segments
(sm/lazy-decoder schema:segments sm/json-transformer))

View File

@ -303,7 +303,7 @@
(-> (get-handlers content)
(get point))
transform-content
transform-path-data
(fn [content [index prefix]]
(let [cx (d/prefix-keyword prefix :x)
cy (d/prefix-keyword prefix :y)]
@ -312,7 +312,7 @@
(assoc-in [index :params cy] (:y point)))))
content
(reduce transform-content (vec content) handlers)
(reduce transform-path-data (vec content) handlers)
content
(remove-line-curves content)]
@ -772,20 +772,20 @@
(replace-points point->merge-point)))
content)))
(defn transform-content
"Applies a transformation matrix over content and returns a new
content as PathData instance."
[content transform]
(defn transform-path-data
"Applies a transformation matrix over path-data and returns a new
path-data as PathData instance."
[path-data transform]
(if (some? transform)
(impl/-transform (impl/path-data content) transform)
content))
(impl/-transform (impl/path-data path-data) transform)
path-data))
(defn move-content
"Applies a displacement over content and returns a new content as
PathData instance. Implemented in function of `transform-content`."
[content move-vec]
(defn move-path-data
"Applies a displacement over path-data and returns a new path-data as
PathData instance. Implemented in function of `transform-path-data`."
[path-data move-vec]
(let [transform (gmt/translate-matrix move-vec)]
(transform-content content transform)))
(transform-path-data path-data transform)))
(defn calculate-extremities
"Calculate extremities for the provided content"
@ -840,13 +840,13 @@
(persistent! points)))
(persistent! points))))
(defn content->selrect
[content]
(let [extremities (calculate-extremities content)
(defn path-data->selrect
[path-data]
(let [extremities (calculate-extremities path-data)
;; We haven't found any extremes so we turn the commands to points
extremities
(if (empty? extremities)
(->> content (keep helpers/segment->point))
(->> path-data (keep helpers/segment->point))
extremities)]
;; If no points are returned we return an empty rect.
@ -854,10 +854,10 @@
(grc/points->rect extremities)
(grc/make-rect))))
(defn content-center
[content]
(-> content
content->selrect
(defn path-data-center
[path-data]
(-> path-data
path-data->selrect
grc/rect->center))
(defn append-segment
@ -873,11 +873,11 @@
content)]
(conj content (impl/check-segment segment))))
(defn points->content
"Given a vector of points generate a path content.
(defn points->path-data
"Given a vector of points generate a path-data.
Mainly used for generate a path content from user drawing points
using curve drawing tool."
Mainly used for generate a path-data from user drawing points
using curve drawing tool."
[points & {:keys [close]}]
(let [initial (first points)
point->params

View File

@ -184,7 +184,7 @@
(:bool-type shape)
content
(-> (bool/calculate-content bool-type (map :path-data children))
(-> (bool/calculate-path-data bool-type (map :path-data children))
(path.impl/path-data))]
(-> shape
@ -227,7 +227,7 @@
content
(cond-> content
(some? transform)
(segm/transform-content (gmt/transform-in (gco/shape->center shape) transform)))]
(segm/transform-path-data (gmt/transform-in (gco/shape->center shape) transform)))]
(-> shape
(assoc :type :path)

View File

@ -160,10 +160,10 @@
(into [] xf-mapcat-data closed-subpaths)))
;; FIXME: revisit this fn impl for perfromance
(defn reverse-content
"Given a content reverse the order of the commands"
[content]
(->> (get-subpaths content)
(defn reverse-path-data
"Given a path-data reverse the order of the commands"
[path-data]
(->> (get-subpaths path-data)
(mapv reverse-subpath)
(reverse)
(into [] xf-mapcat-data)))

View File

@ -238,7 +238,7 @@
[:map {:title "BoolAttrs"}
[:shapes [:vector {:gen/max 10 :gen/min 1} ::sm/uuid]]
[:bool-type [::sm/one-of bool-types]]
[:path-data path/schema:content]])
[:path-data path/schema:path-data]])
(def ^:private schema:rect-attrs
[:map {:title "RectAttrs"}])
@ -263,7 +263,7 @@
(def ^:private schema:path-attrs
[:map {:title "PathAttrs"}
[:path-data path/schema:content]])
[:path-data path/schema:path-data]])
(def ^:private schema:text-attrs
[:map {:title "TextAttrs"}
@ -590,7 +590,7 @@
points (or points
(grc/rect->points selrect))
;; Ensure we hace correct type here for Path Data
path-data (path/content path-data)]
path-data (path/path-data path-data)]
(-> shape
(assoc :selrect selrect)
(assoc :points points)

View File

@ -31,7 +31,7 @@
(if (= type :path)
(cts/setup-shape
(into {:type :path
:path-data (path/content (:path-data params default-path))}
:path-data (path/path-data (:path-data params default-path))}
params))
(cts/setup-shape
(into {:type type

View File

@ -88,7 +88,7 @@
;; This means it implements IReduceInit/IReduce protocols
(t/deftest path-data-to-vector
(let [pdata (path/content sample-content)
(let [pdata (path/path-data sample-content)
result (vec pdata)]
(t/is (= 4 (count result)))
(t/is (= (get-in sample-content [0 :command])
@ -110,7 +110,7 @@
(get-in result [3 :params])))))
(t/deftest path-data-plain-to-binary
(let [pdata (path/content sample-content)]
(let [pdata (path/path-data sample-content)]
(t/is (= sample-bytes
(vec
#?(:cljs (js/Int8Array. (.-buffer (.-buffer pdata)))
@ -129,7 +129,7 @@
{:command :curve-to :params {:x 154.0 :y 508.0}}]
binary-content
(path/content plain-content)]
(path/path-data plain-content)]
#?(:clj
(t/is (= "M480.0,839.0L439.0,802.0C264.0,634.0,264.0,634.0,264.0,634.0C154.0,508.0,154.0,508.0,154.0,508.0"
@ -147,7 +147,7 @@
(t/is (= (vec content) sample-content))))
(t/deftest path-data-transit-roundtrip
(let [pdata (path/content sample-content)
(let [pdata (path/path-data sample-content)
result1 (trans/encode-str pdata)
expected (str "[\"~#penpot/path-data\",\"~bAQAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAPBDAMBRRAIAAAAAAAAAAAAAAAAAAA"
@ -160,7 +160,7 @@
#?(:clj
(t/deftest path-data-fresian
(let [pdata (path/content sample-content)
(let [pdata (path/path-data sample-content)
result1 (fres/encode pdata)
result2 (fres/decode result1)]
(t/is (= pdata result2)))))
@ -192,9 +192,9 @@
(t/deftest path-transform-1
(let [matrix (gmt/translate-matrix 10 10)
content (path/content sample-content)
content (path/path-data sample-content)
result1 (path/transform-content content matrix)
result1 (path/transform-path-data content matrix)
result2 (transform-plain-content sample-content matrix)
result3 (transform-plain-content content matrix)]
@ -203,9 +203,9 @@
(t/deftest path-transform-2
(let [matrix (gmt/translate-matrix 10 10)
content (path/content sample-content-large)
content (path/path-data sample-content-large)
result1 (path/transform-content content matrix)
result1 (path/transform-path-data content matrix)
result2 (transform-plain-content sample-content-large matrix)
result3 (transform-plain-content content matrix)]
@ -214,9 +214,9 @@
(t/deftest path-transform-3
(let [matrix (gmt/rotate-matrix 42 (gpt/point 0 0))
content (path/content sample-content-square)
content (path/path-data sample-content-square)
result1 (path/transform-content content matrix)
result1 (path/transform-path-data content matrix)
result2 (transform-plain-content sample-content-square matrix)
result3 (transform-plain-content content matrix)]
@ -263,7 +263,7 @@
(into [] (keep segment->point)))))
(t/deftest path-get-points
(let [content (path/content sample-content-large)
(let [content (path/path-data sample-content-large)
result1 (content->points content)
result2 (content->points sample-content-large)
@ -276,7 +276,7 @@
(t/testing "path/get-points returns nil for nil content without throwing"
(t/is (nil? (path/get-points nil))))
(t/testing "path/get-points returns correct points for valid content"
(let [content (path/content sample-content)
(let [content (path/path-data sample-content)
points (path/get-points content)]
(t/is (some? points))
(t/is (= 3 (count points))))))
@ -322,7 +322,7 @@
points)))
(t/deftest extremities-1
(let [pdata (path/content sample-content)
(let [pdata (path/path-data sample-content)
result1 (calculate-extremities sample-content)
result2 (calculate-extremities pdata)
result3 (path.segment/calculate-extremities sample-content)
@ -352,7 +352,7 @@
(t/deftest extremities-3
(let [segments [{:command :move-to, :params {:x -310.5355224609375, :y 452.62115478515625}}]
content (path/content segments)
content (path/path-data segments)
result1 (calculate-extremities segments)
result2 (path.segment/calculate-extremities segments)
result3 (path.segment/calculate-extremities content)
@ -366,7 +366,7 @@
(let [initial [(gpt/point 0.0 0.0)
(gpt/point 10.0 10.0)
(gpt/point 10.0 5.0)]
content (path.segment/points->content initial)
content (path.segment/points->path-data initial)
segments (vec content)]
(t/is (= 3 (count segments)))
(t/is (= {:command :move-to, :params {:x 0.0, :y 0.0}} (nth segments 0)))
@ -374,7 +374,7 @@
(t/is (= {:command :line-to, :params {:x 10.0, :y 5.0}} (nth segments 2)))))
(t/deftest get-segments
(let [content (path/content sample-content-square)
(let [content (path/path-data sample-content-square)
points #{(gpt/point 10.0 0.0)
(gpt/point 0.0 0.0)}
result (path.segment/get-segments-with-points content points)
@ -408,7 +408,7 @@
(get params :y)))))))
(t/deftest handler-to-point
(let [content (path/content sample-content-2)
(let [content (path/path-data sample-content-2)
result1 (handler->point content 3 :c1)
result2 (handler->point content 1 :c1)
result3 (handler->point content 0 :c1)
@ -449,7 +449,7 @@
(d/mapm #(mapv second %2))))
(t/deftest content-to-handlers
(let [content (path/content sample-content-large)
(let [content (path/path-data sample-content-large)
result1 (get-handlers sample-content-large)
result2 (path.segment/get-handlers content)]
(t/is (= result1 result2))))
@ -537,7 +537,7 @@
{:command :line-to, :params {:x 1674.9000244140625, :y 45.0}}])
(t/deftest calculate-bool-content
(let [result (path.bool/calculate-content :union contents-for-bool)]
(let [result (path.bool/calculate-path-data :union contents-for-bool)]
(t/is (= result bool-result))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -677,7 +677,7 @@
(t/is (seq result)))))
(t/deftest subpath-reverse-content
(let [result (path.subpath/reverse-content simple-open-content)]
(let [result (path.subpath/reverse-path-data simple-open-content)]
(t/is (= (count simple-open-content) (count result)))
;; First command of reversed content is a move-to at old end
(t/is (= :move-to (:command (first result))))
@ -945,7 +945,7 @@
(t/is (nil? (path.segment/get-handler {:command :line-to :params {:x 1 :y 2}} :c1)))))
(t/deftest segment-handler->node
(let [content (path/content sample-content-2)]
(let [content (path/path-data sample-content-2)]
;; For :c1 prefix, the node is the previous segment
(let [node (path.segment/handler->node (vec content) 2 :c1)]
(t/is (some? node)))
@ -968,20 +968,20 @@
(t/is (mth/close? 5.0 (:y opp)))))
(t/deftest segment-point-indices
(let [content (path/content sample-content-2)
(let [content (path/path-data sample-content-2)
pt (gpt/point 480.0 839.0)
idxs (path.segment/point-indices content pt)]
(t/is (= [0] (vec idxs)))))
(t/deftest segment-opposite-index
(let [content (path/content sample-content-2)]
(let [content (path/path-data sample-content-2)]
;; Index 2 with :c2 prefix — the node is the current point of index 2
(let [result (path.segment/opposite-index content 2 :c2)]
;; result is either nil or [index prefix]
(t/is (or (nil? result) (vector? result))))))
(t/deftest segment-split-segments
(let [content (path/content sample-content-square)
(let [content (path/path-data sample-content-square)
points #{(gpt/point 10.0 0.0)
(gpt/point 0.0 0.0)}
result (path.segment/split-segments content points 0.5)]
@ -989,8 +989,8 @@
(t/is (> (count result) (count sample-content-square)))))
(t/deftest segment-content->selrect
(let [content (path/content sample-content-square)
rect (path.segment/content->selrect content)]
(let [content (path/path-data sample-content-square)
rect (path.segment/path-data->selrect content)]
(t/is (some? rect))
(t/is (mth/close? 0.0 (:x1 rect) 0.1))
(t/is (mth/close? 0.0 (:y1 rect) 0.1))
@ -998,22 +998,22 @@
(t/is (mth/close? 10.0 (:y2 rect) 0.1))))
(t/deftest segment-content-center
(let [content (path/content sample-content-square)
center (path.segment/content-center content)]
(let [content (path/path-data sample-content-square)
center (path.segment/path-data-center content)]
(t/is (some? center))
(t/is (mth/close? 5.0 (:x center) 0.1))
(t/is (mth/close? 5.0 (:y center) 0.1))))
(t/deftest segment-move-content
(let [content (path/content sample-content-square)
(let [content (path/path-data sample-content-square)
move-vec (gpt/point 5.0 5.0)
result (path.segment/move-content content move-vec)
result (path.segment/move-path-data content move-vec)
first-seg (first (vec result))]
(t/is (= :move-to (:command first-seg)))
(t/is (mth/close? 5.0 (get-in first-seg [:params :x])))))
(t/deftest segment-is-curve?
(let [content (path/content sample-content-2)]
(let [content (path/path-data sample-content-2)]
;; point at index 0 is 480,839 — no handler offset, not a curve
(let [pt (gpt/point 480.0 839.0)]
;; is-curve? can return nil (falsy) or boolean — just check it doesn't throw
@ -1024,13 +1024,13 @@
(boolean? (path.segment/is-curve? content curve-pt)))))))
(t/deftest segment-append-segment
(let [content (path/content sample-content)
(let [content (path/path-data sample-content)
seg {:command :line-to :params {:x 100.0 :y 100.0}}
result (path.segment/append-segment content seg)]
(t/is (= (inc (count (vec content))) (count result)))))
(t/deftest segment-remove-nodes
(let [content (path/content simple-open-content)
(let [content (path/path-data simple-open-content)
;; remove the midpoint
pt (gpt/point 10.0 0.0)
result (path.segment/remove-nodes content #{pt})]
@ -1038,7 +1038,7 @@
(t/is (< (count result) (count simple-open-content)))))
(t/deftest segment-join-nodes
(let [content (path/content simple-open-content)
(let [content (path/path-data simple-open-content)
pt1 (gpt/point 0.0 0.0)
pt2 (gpt/point 10.0 10.0)
result (path.segment/join-nodes content #{pt1 pt2})]
@ -1046,14 +1046,14 @@
(t/is (>= (count result) (count simple-open-content)))))
(t/deftest segment-separate-nodes
(let [content (path/content simple-open-content)
(let [content (path/path-data simple-open-content)
pt (gpt/point 10.0 0.0)
result (path.segment/separate-nodes content #{pt})]
;; separate-nodes should return a collection (vector or seq)
(t/is (coll? result))))
(t/deftest segment-make-corner-point
(let [content (path/content sample-content-2)
(let [content (path/path-data sample-content-2)
;; Take a curve point and make it a corner
pt (gpt/point 439.0 802.0)
result (path.segment/make-corner-point content pt)]
@ -1062,13 +1062,13 @@
(t/deftest segment-next-node
(t/testing "no prev-point returns move-to"
(let [content (path/content sample-content)
(let [content (path/path-data sample-content)
position (gpt/point 100.0 100.0)
result (path.segment/next-node content position nil nil)]
(t/is (= :move-to (:command result)))))
(t/testing "with prev-point and no handler and last command is not close-path"
;; Use a content that does NOT end with :close-path
(let [content (path/content simple-open-content)
(let [content (path/path-data simple-open-content)
position (gpt/point 100.0 100.0)
prev (gpt/point 50.0 50.0)
result (path.segment/next-node content position prev nil)]
@ -1080,11 +1080,11 @@
(t/deftest path-from-plain
(let [result (path/from-plain sample-content)]
(t/is (path/content? result))
(t/is (path/path-data? result))
(t/is (= (count sample-content) (count (vec result))))))
(t/deftest path-calc-selrect
(let [content (path/content sample-content-square)
(let [content (path/path-data sample-content-square)
rect (path/calc-selrect content)]
(t/is (some? rect))
(t/is (mth/close? 0.0 (:x1 rect) 0.1))
@ -1096,13 +1096,13 @@
{:command :move-to :params {:x 10.0 :y 5.0}}
{:command :line-to :params {:x 0.0 :y 0.0}}]
result (path/close-subpaths content)]
(t/is (path/content? result))
(t/is (path/path-data? result))
(t/is (seq (vec result)))))
(t/deftest path-move-content
(let [content (path/content sample-content-square)
(let [content (path/path-data sample-content-square)
move-vec (gpt/point 3.0 4.0)
result (path/move-content content move-vec)
result (path/move-path-data content move-vec)
first-r (first (vec result))]
(t/is (= :move-to (:command first-r)))
(t/is (mth/close? 3.0 (get-in first-r [:params :x])))
@ -1110,31 +1110,31 @@
(t/deftest path-move-content-zero-vec
(t/testing "moving by zero returns same content"
(let [content (path/content sample-content-square)
result (path/move-content content (gpt/point 0 0))]
(let [content (path/path-data sample-content-square)
result (path/move-path-data content (gpt/point 0 0))]
;; should return same object (identity) when zero vector
(t/is (= (vec content) (vec result))))))
(t/deftest path-shape-with-open-path?
(t/testing "path shape with open content is open"
(let [shape {:type :path
:path-data (path/content simple-open-content)}]
:path-data (path/path-data simple-open-content)}]
(t/is (path/shape-with-open-path? shape))))
(t/testing "path shape with closed content is not open"
(let [shape {:type :path
:path-data (path/content simple-closed-content)}]
:path-data (path/path-data simple-closed-content)}]
(t/is (not (path/shape-with-open-path? shape))))))
(t/deftest path-get-byte-size
(let [content (path/content sample-content)
(let [content (path/path-data sample-content)
size (path/get-byte-size content)]
(t/is (pos? size))))
(t/deftest path-apply-content-modifiers
(let [content (path/content sample-content)
(let [content (path/path-data sample-content)
;; shift the first point by x=5, y=3
modifiers {0 {:x 5.0 :y 3.0}}
result (path/apply-content-modifiers content modifiers)
result (path/apply-path-data-modifiers content modifiers)
first-seg (first (vec result))]
(t/is (mth/close? (+ 480.0 5.0) (get-in first-seg [:params :x])))
(t/is (mth/close? (+ 839.0 3.0) (get-in first-seg [:params :y])))))
@ -1169,20 +1169,20 @@
{:command :close-path :params {}}])
(t/deftest bool-difference
(let [result (path.bool/calculate-content :difference [rect-a rect-b])]
(let [result (path.bool/calculate-path-data :difference [rect-a rect-b])]
;; difference result must be a sequence (possibly empty for degenerate cases)
(t/is (or (nil? result) (sequential? result)))))
(t/deftest bool-intersection
(let [result (path.bool/calculate-content :intersection [rect-a rect-b])]
(let [result (path.bool/calculate-path-data :intersection [rect-a rect-b])]
(t/is (or (nil? result) (sequential? result)))))
(t/deftest bool-exclusion
(let [result (path.bool/calculate-content :exclude [rect-a rect-b])]
(let [result (path.bool/calculate-path-data :exclude [rect-a rect-b])]
(t/is (or (nil? result) (sequential? result)))))
(t/deftest bool-union-non-overlapping
(let [result (path.bool/calculate-content :union [rect-a rect-c])]
(let [result (path.bool/calculate-path-data :union [rect-a rect-c])]
;; non-overlapping union should contain both shapes' segments
(t/is (seq result))
(t/is (> (count result) (count rect-a)))))
@ -1199,7 +1199,7 @@
:selrect (make-selrect 0.0 0.0 100.0 50.0)}
result (path/convert-to-path shape {})]
(t/is (= :path (:type result)))
(t/is (path/content? (:path-data result)))
(t/is (path/path-data? (:path-data result)))
;; A simple rect (no radius) produces an empty path in the current impl
;; so we just check it doesn't throw and returns a :path type
(t/is (some? (:path-data result)))))
@ -1209,12 +1209,12 @@
:selrect (make-selrect 0.0 0.0 100.0 100.0)}
result (path/convert-to-path shape {})]
(t/is (= :path (:type result)))
(t/is (path/content? (:path-data result)))
(t/is (path/path-data? (:path-data result)))
;; A circle converts to bezier curves — should have multiple segments
(t/is (> (count (vec (:path-data result))) 1))))
(t/deftest shape-to-path-path
(let [shape {:type :path :path-data (path/content sample-content)}
(let [shape {:type :path :path-data (path/path-data sample-content)}
result (path/convert-to-path shape {})]
;; A path shape stays a path shape unchanged
(t/is (= :path (:type result)))))

View File

@ -113,10 +113,10 @@
{:num 500})))
(t/deftest shape-path-content-json-roundtrip
(let [encode (sm/encoder path/schema:content (sm/json-transformer))
decode (sm/decoder path/schema:content (sm/json-transformer))]
(let [encode (sm/encoder path/schema:path-data (sm/json-transformer))
decode (sm/decoder path/schema:path-data (sm/json-transformer))]
(smt/check!
(smt/for [path-content (sg/generator path/schema:content)]
(smt/for [path-content (sg/generator path/schema:path-data)]
(let [path-content-1 (encode path-content)
path-content-2 (json-roundtrip path-content-1)
path-content-3 (decode path-content-2)]

View File

@ -179,7 +179,7 @@
shape)
modifiers (dm/get-in content-modifiers [id :content-modifiers])
shape (if (some? modifiers)
(update shape :content path/apply-content-modifiers modifiers)
(update shape :path-data path/apply-path-data-modifiers modifiers)
shape)]
(assoc result id shape))
result))

View File

@ -32,8 +32,8 @@
ptk/UpdateEvent
(update [_ state]
(let [objects (dsh/lookup-page-objects state)
content (dm/get-in state [:workspace-drawing :object :path-data])
position (path.segment/get-handler-point content 0 nil)
path-data (dm/get-in state [:workspace-drawing :object :path-data])
position (path.segment/get-handler-point path-data 0 nil)
frame-id (->> (ctst/top-nested-frame objects position)
(ctn/get-first-valid-parent objects) ;; We don't want to change the structure of component copies
@ -63,14 +63,14 @@
(update [_ state]
(update-in state [:workspace-drawing :object]
(fn [object]
(let [points (-> (::points object)
(conj point))
content (path.segment/points->content points)
selrect (path.segment/content->selrect content)
points' (grc/rect->points selrect)]
(let [points (-> (::points object)
(conj point))
path-data (path.segment/points->path-data points)
selrect (path.segment/path-data->selrect path-data)
points' (grc/rect->points selrect)]
(-> object
(assoc ::points points)
(assoc :path-data content)
(assoc :path-data path-data)
(assoc :selrect selrect)
(assoc :points points'))))))))
@ -81,19 +81,19 @@
(update [_ state]
(update-in state [:workspace-drawing :object]
(fn [{:keys [::points] :as shape}]
(let [points (ups/simplify points simplify-tolerance)
content (path.segment/points->content points)
selrect (path.segment/content->selrect content)
points (grc/rect->points selrect)]
(let [points (ups/simplify points simplify-tolerance)
path-data (path.segment/points->path-data points)
selrect (path.segment/path-data->selrect path-data)
points (grc/rect->points selrect)]
(-> shape
(dissoc ::points)
(assoc :path-data content)
(assoc :path-data path-data)
(assoc :selrect selrect)
(assoc :points points)
(cond-> (or (empty? points)
(nil? selrect)
(<= (count content) 1))
(<= (count path-data) 1))
(assoc :initialized? false)))))))))

View File

@ -436,7 +436,7 @@
[objects path-modifiers]
(letfn [(apply-path-modifier
[shape {:keys [content-modifiers]}]
(let [shape (update shape :path-data upc/apply-content-modifiers content-modifiers)
(let [shape (update shape :path-data upc/apply-path-data-modifiers content-modifiers)
[points selrect] (helpers/content->points+selrect shape (:path-data shape))]
(assoc shape :selrect selrect :points points)))]
(loop [modifiers (seq path-modifiers)

View File

@ -16,11 +16,11 @@
[potok.v2.core :as ptk]))
(defn generate-path-changes
"Generates changes to update the new content of the shape"
[it objects page-id shape old-content new-content]
"Generates changes to update the new path-data of the shape"
[it objects page-id shape old-path-data new-path-data]
(assert (path/content? old-content))
(assert (path/content? new-content))
(assert (path/path-data? old-path-data))
(assert (path/path-data? new-path-data))
(let [shape-id (:id shape)
@ -29,22 +29,22 @@
(update objects shape-id
(fn [shape]
(-> shape
(assoc :path-data old-content)
(assoc :path-data old-path-data)
(path/update-geometry))))
changes
(-> (pcb/empty-changes it page-id)
(pcb/with-objects objects))
new-content
(path/content new-content)]
new-path-data
(path/path-data new-path-data)]
(cond
;; https://tree.taiga.io/project/penpot/issue/2366
(nil? shape-id)
changes
(empty? new-content)
(empty? new-path-data)
(-> changes
(pcb/remove-objects [shape-id])
(pcb/resize-parents [shape-id]))
@ -54,23 +54,23 @@
(pcb/update-shapes [shape-id]
(fn [shape]
(-> shape
(assoc :path-data new-content)
(assoc :path-data new-path-data)
(path/update-geometry))))
(pcb/resize-parents [shape-id])))))
(defn save-path-content
(defn save-path-data
([]
(save-path-content {}))
(save-path-data {}))
([{:keys [preserve-move-to] :or {preserve-move-to false}}]
(ptk/reify ::save-path-content
(ptk/reify ::save-path-data
ptk/UpdateEvent
(update [_ state]
(let [content (st/get-path state :path-data)
content (if (and (not preserve-move-to)
(= (-> content last :command) :move-to))
(path/content (take (dec (count content)) content))
(path/content content))]
(st/set-content state content)))
(let [path-data (st/get-path state :path-data)
path-data (if (and (not preserve-move-to)
(= (-> path-data last :command) :move-to))
(path/path-data (take (dec (count path-data)) path-data))
(path/path-data path-data))]
(st/set-path-data state path-data)))
ptk/WatchEvent
(watch [it state _]
@ -83,9 +83,7 @@
;; objects, if shape is a ephimeral drawing shape, we should
;; do nothing
(when-let [shape (get objects id)]
(when-let [old-content (dm/get-in local [:edit-path id :old-content])]
(let [new-content (get shape :path-data)
changes (generate-path-changes it objects page-id shape old-content new-content)]
(when-let [old-path-data (dm/get-in local [:edit-path id :old-content])]
(let [new-path-data (get shape :path-data)
changes (generate-path-changes it objects page-id shape old-path-data new-path-data)]
(rx/of (dch/commit-changes changes))))))))))

View File

@ -33,7 +33,7 @@
[potok.v2.core :as ptk]))
(declare close-path-drag-end)
(declare check-changed-content)
(declare check-changed-path-data)
(declare change-edit-mode)
(defn- end-path-event?
@ -93,13 +93,13 @@
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)
content (st/get-path state :path-data)
path-data (st/get-path state :path-data)
index (or index (count content))
index (or index (count path-data))
prefix (or prefix :c1)
position (or position (path.helpers/segment->point (nth content (dec index))))
position (or position (path.helpers/segment->point (nth path-data (dec index))))
old-handler (path.segment/get-handler-point content index prefix)
old-handler (path.segment/get-handler-point path-data index prefix)
handler-position (cond-> (gpt/point x y)
shift? (path.helpers/position-fixed-angle position))
@ -111,7 +111,7 @@
match-opposite? (not alt?)
modifiers (helpers/move-handler-modifiers content index prefix match-opposite? match-opposite? dx dy)]
modifiers (helpers/move-handler-modifiers path-data index prefix match-opposite? match-opposite? dx dy)]
(-> state
(update-in [:workspace-local :edit-path id :content-modifiers] merge modifiers)
(assoc-in [:workspace-local :edit-path id :drag-handler] handler-position)))))))
@ -123,12 +123,12 @@
(let [id (st/get-path-id state)
modifiers (get-in state [:workspace-local :edit-path id :content-modifiers])
content (-> (st/get-path state :path-data)
(path/apply-content-modifiers modifiers))
path-data (-> (st/get-path state :path-data)
(path/apply-path-data-modifiers modifiers))
handler (get-in state [:workspace-local :edit-path id :drag-handler])]
(-> state
(st/set-content content)
(st/set-path-data path-data)
(update-in [:workspace-local :edit-path id] dissoc :drag-handler)
(update-in [:workspace-local :edit-path id] dissoc :content-modifiers)
(assoc-in [:workspace-local :edit-path id :prev-handler] handler)
@ -147,8 +147,8 @@
(ptk/reify ::close-path-drag-start
ptk/WatchEvent
(watch [_ state stream]
(let [content (st/get-path state :path-data)
handlers (-> (path.segment/get-handlers content)
(let [path-data (st/get-path state :path-data)
handlers (-> (path.segment/get-handlers path-data)
(get position))
[idx prefix] (when (= (count handlers) 1)
@ -279,10 +279,10 @@
ptk/UpdateEvent
(update [_ state]
(let [objects (dsh/lookup-page-objects state)
content (get-in state [:workspace-drawing :object :path-data] [])
path-data (get-in state [:workspace-drawing :object :path-data] [])
;; FIXME: use native operation for retrieve the first position
position (-> (nth content 0)
position (-> (nth path-data 0)
(get :params)
(gpt/point))
@ -305,16 +305,16 @@
(ptk/reify ::handle-drawing-end
ptk/UpdateEvent
(update [_ state]
(let [content (some-> (dm/get-in state [:workspace-drawing :object :path-data])
(path/check-content))]
(if (> (count content) 1)
(let [path-data (some-> (dm/get-in state [:workspace-drawing :object :path-data])
(path/check-path-data))]
(if (> (count path-data) 1)
(assoc-in state [:workspace-drawing :object :initialized?] true)
state)))
ptk/WatchEvent
(watch [_ state _]
(when-let [content (dm/get-in state [:workspace-drawing :object :path-data])]
(if (> (count content) 1)
(when-let [path-data (dm/get-in state [:workspace-drawing :object :path-data])]
(if (> (count path-data) 1)
(rx/of (setup-frame)
(dwdc/handle-finish-drawing)
(dwe/start-edition-mode shape-id)
@ -350,9 +350,9 @@
(update [_ state]
(let [id (dm/get-in state [:workspace-local :edition])
objects (dsh/lookup-page-objects state)
content (dm/get-in objects [id :path-data])]
(if content
(update-in state [:workspace-local :edit-path id] assoc :old-content content)
path-data (dm/get-in objects [id :path-data])]
(if path-data
(update-in state [:workspace-local :edit-path id] assoc :old-content path-data)
state)))
ptk/WatchEvent
@ -376,7 +376,7 @@
(rx/filter (ptk/type? ::end-edition))
(rx/take 1)
(rx/mapcat (fn [_]
(rx/of (check-changed-content)
(rx/of (check-changed-path-data)
(start-draw-mode*))))))
(rx/empty))))))
@ -406,20 +406,20 @@
(let [id (st/get-path-id state)]
(assoc-in state [:workspace-local :edit-path id :prev-handler] nil)))))
(defn check-changed-content
(defn check-changed-path-data
[]
(ptk/reify ::check-changed-content
(ptk/reify ::check-changed-path-data
ptk/WatchEvent
(watch [_ state _]
(let [id (st/get-path-id state)
content (st/get-path state :path-data)
old-content (get-in state [:workspace-local :edit-path id :old-content])
path-data (st/get-path state :path-data)
old-path-data (get-in state [:workspace-local :edit-path id :old-content])
mode (get-in state [:workspace-local :edit-path id :edit-mode])
empty-content? (empty? content)]
empty-path-data? (empty? path-data)]
(cond
(and (not= content old-content) (not empty-content?))
(rx/of (changes/save-path-content))
(and (not= path-data old-path-data) (not empty-path-data?))
(rx/of (changes/save-path-data))
(= mode :draw)
(rx/of :interrupt)

View File

@ -32,18 +32,18 @@
ptk/UpdateEvent
(update [_ state]
(let [content (st/get-path state :path-data)
modifiers (helpers/move-handler-modifiers content index prefix false match-opposite? dx dy)
(let [path-data (st/get-path state :path-data)
modifiers (helpers/move-handler-modifiers path-data index prefix false match-opposite? dx dy)
[cx cy] (if (= prefix :c1) [:c1x :c1y] [:c2x :c2y])
point (gpt/point (+ (dm/get-in content [index :params cx]) dx)
(+ (dm/get-in content [index :params cy]) dy))]
point (gpt/point (+ (dm/get-in path-data [index :params cx]) dx)
(+ (dm/get-in path-data [index :params cy]) dy))]
(-> state
(update-in [:workspace-local :edit-path id :content-modifiers] merge modifiers)
(assoc-in [:workspace-local :edit-path id :moving-handler] point))))))
(defn apply-content-modifiers []
(ptk/reify ::apply-content-modifiers
(defn apply-path-data-modifiers []
(ptk/reify ::apply-path-data-modifiers
ptk/WatchEvent
(watch [it state _]
(let [id (st/get-path-id state)
@ -56,26 +56,26 @@
(let [page-id (get state :current-page-id state)
objects (dsh/lookup-page-objects state)
content (get shape :path-data)
new-content (path/apply-content-modifiers content content-modifiers)
path-data (get shape :path-data)
new-path-data (path/apply-path-data-modifiers path-data content-modifiers)
old-points (path/get-points content)
new-points (path/get-points new-content)
old-points (path/get-points path-data)
new-points (path/get-points new-path-data)
point-change (->> (map hash-map old-points new-points) (reduce merge))]
(when (and (some? new-content) (some? shape))
(let [changes (changes/generate-path-changes it objects page-id shape (:path-data shape) new-content)]
(if (empty? new-content)
(when (and (some? new-path-data) (some? shape))
(let [changes (changes/generate-path-changes it objects page-id shape (:path-data shape) new-path-data)]
(if (empty? new-path-data)
(rx/of (dch/commit-changes changes)
(dwe/clear-edition-mode))
(rx/of (dch/commit-changes changes)
(selection/update-selection point-change)
(fn [state] (update-in state [:workspace-local :edit-path id] dissoc :content-modifiers :moving-nodes :moving-handler))))))))))))
(defn modify-content-point
[content {dx :x dy :y} modifiers point]
(let [point-indices (path.segment/point-indices content point) ;; [indices]
handler-indices (path.segment/handler-indices content point) ;; [[index prefix]]
(defn modify-path-data-point
[path-data {dx :x dy :y} modifiers point]
(let [point-indices (path.segment/point-indices path-data point) ;; [indices]
handler-indices (path.segment/handler-indices path-data point) ;; [[index prefix]]
modify-point
(fn [modifiers index]
@ -99,8 +99,8 @@
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)
content (st/get-path state :path-data)
modifiers-reducer (partial modify-content-point content move-modifier)
path-data (st/get-path state :path-data)
modifiers-reducer (partial modify-path-data-point path-data move-modifier)
content-modifiers (dm/get-in state [:workspace-local :edit-path id :content-modifiers] {})
content-modifiers (->> points
(reduce modifiers-reducer content-modifiers))]
@ -113,13 +113,13 @@
ptk/UpdateEvent
(update [_ state]
(let [id (st/get-path-id state)
content (st/get-path state :path-data)
path-data (st/get-path state :path-data)
to-point (cond-> to-point
(:shift? to-point) (path.helpers/position-fixed-angle from-point))
delta (gpt/subtract to-point from-point)
modifiers-reducer (partial modify-content-point content delta)
modifiers-reducer (partial modify-path-data-point path-data delta)
points (dm/get-in state [:workspace-local :edit-path id :selected-points] #{})
@ -161,8 +161,8 @@
start-position (apply min-key #(gpt/distance start-position %) selected-points)
content (st/get-path state :path-data)
points (path/get-points content)]
path-data (st/get-path state :path-data)
points (path/get-points path-data)]
(rx/concat
;; This stream checks the consecutive mouse positions to do the dragging
@ -170,7 +170,7 @@
(streams/move-points-stream start-position selected-points)
(rx/map #(move-selected-path-point start-position %))
(rx/take-until stopper))
(rx/of (apply-content-modifiers)))))))
(rx/of (apply-path-data-modifiers)))))))
(defn- get-displacement
"Retrieve the correct displacement delta point for the
@ -237,7 +237,7 @@
;; First event is not read by the stream so we need to send it again
(rx/of (move-selected direction shift?)))
(rx/of (apply-content-modifiers)
(rx/of (apply-path-data-modifiers)
(finish-move-selected))))
(rx/empty)))))))
@ -254,14 +254,14 @@
start-delta-x (dm/get-in modifiers [index cx] 0)
start-delta-y (dm/get-in modifiers [index cy] 0)
content (st/get-path state :path-data)
points (path/get-points content)
path-data (st/get-path state :path-data)
points (path/get-points path-data)
point (-> content (nth (if (= prefix :c1) (dec index) index)) (path.helpers/segment->point))
handler (-> content (nth index) (path.segment/get-handler prefix))
point (-> path-data (nth (if (= prefix :c1) (dec index) index)) (path.helpers/segment->point))
handler (-> path-data (nth index) (path.segment/get-handler prefix))
[op-idx op-prefix] (path.segment/opposite-index content index prefix)
opposite (path.segment/get-handler-point content op-idx op-prefix)]
[op-idx op-prefix] (path.segment/opposite-index path-data index prefix)
opposite (path.segment/get-handler-point path-data op-idx op-prefix)]
(streams/drag-stream
(rx/concat
@ -284,7 +284,7 @@
(->> stream
(rx/filter streams/finish-edition?)))))
(rx/concat (rx/of (apply-content-modifiers)))))))))
(rx/concat (rx/of (apply-path-data-modifiers)))))))))
(declare stop-path-edit)
@ -298,7 +298,7 @@
shape (get objects id)]
(-> state
(st/set-content (path/close-subpaths (:path-data shape)))
(st/set-path-data (path/close-subpaths (:path-data shape)))
(update-in [:workspace-local :edit-path id]
(fn [state]
(let [state (if state
@ -340,16 +340,16 @@
(ptk/reify ::split-segments
ptk/UpdateEvent
(update [_ state]
(let [content (st/get-path state :path-data)]
(let [path-data (st/get-path state :path-data)]
(-> state
(assoc-in [:workspace-local :edit-path id :old-content] content)
(st/set-content (-> content
(path.segment/split-segments #{from-p to-p} t)
(path/content))))))
(assoc-in [:workspace-local :edit-path id :old-content] path-data)
(st/set-path-data (-> path-data
(path.segment/split-segments #{from-p to-p} t)
(path/path-data))))))
ptk/WatchEvent
(watch [_ _ _]
(rx/of (changes/save-path-content {:preserve-move-to true})))))
(rx/of (changes/save-path-data {:preserve-move-to true})))))
(defn create-node-at-position
[params]

View File

@ -58,14 +58,14 @@
(- (:y new-opposite) (:y opposite))])))
(defn move-handler-modifiers
[content index prefix match-distance? match-angle? dx dy]
[path-data index prefix match-distance? match-angle? dx dy]
(let [[cx cy] (path.helpers/prefix->coords prefix)
[op-idx op-prefix] (path.segment/opposite-index content index prefix)
[op-idx op-prefix] (path.segment/opposite-index path-data index prefix)
node (path.segment/handler->node content index prefix)
handler (path.segment/get-handler-point content index prefix)
opposite (path.segment/get-handler-point content op-idx op-prefix)
node (path.segment/handler->node path-data index prefix)
handler (path.segment/get-handler-point path-data index prefix)
opposite (path.segment/get-handler-point path-data op-idx op-prefix)
[ocx ocy] (path.helpers/prefix->coords op-prefix)
[odx ody] (calculate-opposite-delta node handler opposite match-angle? match-distance? dx dy)

View File

@ -52,7 +52,7 @@
(update [_ state]
(let [selrect (dm/get-in state [:workspace-local :selrect])
id (dm/get-in state [:workspace-local :edition])
content (st/get-path state :path-data)
path-data (st/get-path state :path-data)
selected-point? (if (some? selrect)
(partial gsh/has-point-rect? selrect)
@ -62,8 +62,8 @@
(map (comp gpt/point :params))
(filter selected-point?))
positions (if remove?
(apply disj initial-set (into #{} xform content))
(into initial-set xform content))]
(apply disj initial-set (into #{} xform path-data))
(into initial-set xform path-data))]
(cond-> state
(some? id)

View File

@ -53,7 +53,7 @@
(pcb/update-shapes
selected
(fn [shape]
(let [content (wasm.api/shape-to-path (:id shape))]
(let [path-data (wasm.api/shape-to-path (:id shape))]
(-> shape
(assoc :type :path)
(cond-> (cph/text-shape? shape)
@ -64,7 +64,7 @@
(cond-> (cph/image-shape? shape)
(assoc :fill-image (get shape :metadata)))
(d/without-keys dissoc-attrs)
(path/update-geometry content)))))
(path/update-geometry path-data)))))
(pcb/remove-objects children-ids))]
(rx/of (dch/commit-changes changes)))
@ -104,15 +104,15 @@
(into []
(keep-indexed
(fn [idx stroke]
(let [content (wasm.api/stroke-to-path (:id shape) idx)]
(when (some? content)
(let [path-data (wasm.api/stroke-to-path (:id shape) idx)]
(when (some? path-data)
(cts/setup-shape
{:type :path
:id (uuid/next)
:name (str (:name shape) " (stroke)")
:parent-id parent-id
:frame-id frame-id
:path-data content
:path-data path-data
:fills [(stroke->fill stroke)]
:strokes []})))))
(:strokes shape)))

View File

@ -34,7 +34,7 @@
shape
(get-in shape ks))))
(defn set-content
[state content]
(defn set-path-data
[state path-data]
(let [path-loc (get-path-location state :path-data)]
(assoc-in state path-loc content)))
(assoc-in state path-loc path-data)))

View File

@ -158,14 +158,14 @@
[state]
(let [zoom (get-in state [:workspace-local :zoom] 1)
d-pos (/ snap/snap-path-accuracy zoom)
get-content #(pst/get-path % :path-data)
get-path-data #(pst/get-path % :path-data)
content-stream
(-> (l/derived get-content st/state)
path-data-stream
(-> (l/derived get-path-data st/state)
(rx/from-atom {:emit-current-value? true}))
ranges-stream
(->> content-stream
(->> path-data-stream
(rx/filter some?)
(rx/map path/get-points)
(rx/map snap/create-ranges))]

View File

@ -39,17 +39,17 @@
(or points selected-points)]
(when (and (seq points) (some? shape))
(let [new-content
(let [new-path-data
(-> (tool-fn (:path-data shape) points)
(path/close-subpaths))
changes
(changes/generate-path-changes it objects page-id shape (:path-data shape) new-content)]
(changes/generate-path-changes it objects page-id shape (:path-data shape) new-path-data)]
(rx/concat
(rx/of (dwsh/update-shapes [id] path/convert-to-path)
(dch/commit-changes changes))
(when (empty? new-content)
(when (empty? new-path-data)
(rx/of (dwe/clear-edition-mode)))))))))))
(defn make-corner

View File

@ -31,18 +31,18 @@
(defn- make-entry [state]
(let [id (st/get-path-id state)
shape (st/get-path state)]
{:content (:path-data shape)
{:path-data (:path-data shape)
:selrect (:selrect shape)
:points (:points shape)
:preview (get-in state [:workspace-local :edit-path id :preview])
:last-point (get-in state [:workspace-local :edit-path id :last-point])
:prev-handler (get-in state [:workspace-local :edit-path id :prev-handler])}))
(defn- load-entry [state {:keys [content selrect points preview last-point prev-handler]}]
(defn- load-entry [state {:keys [path-data selrect points preview last-point prev-handler]}]
(let [id (st/get-path-id state)
old-content (st/get-path state :path-data)]
old-path-data (st/get-path state :path-data)]
(-> state
(d/assoc-in-when (st/get-path-location state :path-data) content)
(d/assoc-in-when (st/get-path-location state :path-data) path-data)
(d/assoc-in-when (st/get-path-location state :selrect) selrect)
(d/assoc-in-when (st/get-path-location state :points) points)
(d/update-in-when
@ -51,7 +51,7 @@
:preview preview
:last-point last-point
:prev-handler prev-handler
:old-content old-content))))
:old-content old-path-data))))
(defn undo-path []
(ptk/reify ::undo-path
@ -73,8 +73,8 @@
(let [id (st/get-path-id state)
undo-stack (get-in state [:workspace-local :edit-path id :undo-stack])]
(if (> (:index undo-stack) 0)
(rx/of (changes/save-path-content {:preserve-move-to true}))
(rx/of (changes/save-path-content {:preserve-move-to true})
(rx/of (changes/save-path-data {:preserve-move-to true}))
(rx/of (changes/save-path-data {:preserve-move-to true})
(common/finish-path)
(dwc/show-toolbar)))))))
@ -94,7 +94,7 @@
ptk/WatchEvent
(watch [_ _ _]
(rx/of (changes/save-path-content)))))
(rx/of (changes/save-path-data)))))
(defn merge-head
"Joins the head with the previous undo in one. This is done so when the user changes a
@ -138,7 +138,7 @@
(or (= ::dwe/clear-edition-mode type)
(= ::dwpg/finalize-page type))))
(def path-content-ref
(def path-data-ref
(letfn [(selector [state]
(st/get-path state :path-data))]
(l/derived selector store/state)))
@ -165,10 +165,9 @@
(rx/filter stop-undo?)
(rx/take 1))]
(rx/concat
(->> (rx/from-atom path-content-ref {:emit-current-value? true})
(->> (rx/from-atom path-data-ref {:emit-current-value? true})
(rx/take-until stop-undo-stream)
(rx/filter (comp not nil?))
(rx/map #(add-undo-entry)))
(rx/of (end-path-undo))))))))))

View File

@ -23,21 +23,21 @@
child-objs (unchecked-get props "childs")
child-objs (h/use-equal-memo child-objs)
metadata? (mf/use-ctx use/include-metadata-ctx)
content (mf/with-memo [shape child-objs]
(let [content (:path-data shape)]
(cond
(some? content)
content
metadata? (mf/use-ctx use/include-metadata-ctx)
path-data (mf/with-memo [shape child-objs]
(let [path-data (:path-data shape)]
(cond
(some? path-data)
path-data
(some? child-objs)
(path/calc-bool-content shape child-objs))))
(some? child-objs)
(path/calc-bool-path-data shape child-objs))))
shape (mf/with-memo [shape content]
(assoc shape :path-data content))]
shape (mf/with-memo [shape path-data]
(assoc shape :path-data path-data))]
[:*
(when (some? content)
(when (some? path-data)
[:& path-shape {:shape shape}])
(when metadata?

View File

@ -11,31 +11,31 @@
[app.main.ui.shapes.custom-stroke :refer [shape-custom-strokes]]
[rumext.v2 :as mf]))
(defn- content->string
[content]
(defn- path-data->string
[path-data]
(cond
(nil? content)
(nil? path-data)
""
(path/content? content)
(.toString content)
(path/path-data? path-data)
(.toString path-data)
:else
(let [content (path/content content)]
(.toString content))))
(let [path-data (path/path-data path-data)]
(.toString path-data))))
(mf/defc path-shape
{::mf/props :obj}
[{:keys [shape]}]
(let [content (get shape :path-data)
pdata (mf/with-memo [content]
(try
(content->string content)
(catch :default cause
(log/error :hint "unexpected error on formatting path"
:shape-name (:name shape)
:shape-id (:id shape)
:cause cause)
"")))]
(let [path-data (get shape :path-data)
pdata (mf/with-memo [path-data]
(try
(path-data->string path-data)
(catch :default cause
(log/error :hint "unexpected error on formatting path"
:shape-name (:name shape)
:shape-id (:id shape)
:cause cause)
"")))]
[:& shape-custom-strokes {:shape shape}
[:path {:d pdata}]]))

View File

@ -106,33 +106,33 @@
c2 (-> (get objects (second (:shapes shape)))
(path/convert-to-path objects))
content-a (:content c1)
content-b (:content c2)
path-data-a (:path-data c1)
path-data-b (:path-data c2)
bool-type (:bool-type shape)
should-reverse? (and (not= :union bool-type)
(= (path.subpath/clockwise? content-b)
(path.subpath/clockwise? content-a)))
(= (path.subpath/clockwise? path-data-b)
(path.subpath/clockwise? path-data-a)))
content-a (-> (:content c1)
(path.bool/close-paths)
(path.bool/add-previous))
path-data-a (-> (:path-data c1)
(path.bool/close-paths)
(path.bool/add-previous))
content-b (-> (:content c2)
(path.bool/close-paths)
(cond-> should-reverse? (path.subpath/reverse-content))
(path.bool/add-previous))
path-data-b (-> (:path-data c2)
(path.bool/close-paths)
(cond-> should-reverse? (path.subpath/reverse-path-data))
(path.bool/add-previous))
sr-a (path.segment/content->selrect content-a)
sr-b (path.segment/content->selrect content-b)
sr-a (path.segment/path-data->selrect path-data-a)
sr-b (path.segment/path-data->selrect path-data-b)
[content-a-split content-b-split] (path.bool/content-intersect-split content-a content-b sr-a sr-b)
[content-a-split content-b-split] (path.bool/path-data-intersect-split path-data-a path-data-b sr-a sr-b)
;;content-a-geom (path.segment/content->geom-data content-a)
;;content-b-geom (path.segment/content->geom-data content-b)
;;content-a-split (->> content-a-split #_(filter #(path.bool/contains-segment? % content-b sr-b content-b-geom)))
;;content-b-split (->> content-b-split #_(filter #(path.bool/contains-segment? % content-a sr-a content-a-geom)))
;;content-a-geom (path.bool/path-data->geom-data path-data-a)
;;content-b-geom (path.bool/path-data->geom-data path-data-b)
;;content-a-split (->> content-a-split #_(filter #(path.bool/contains-segment? % path-data-b sr-b content-b-geom)))
;;content-b-split (->> content-b-split #_(filter #(path.bool/contains-segment? % path-data-a sr-a content-a-geom)))
]
[:*
(for [[i segment] (d/enumerate content-a-split)]

View File

@ -23,7 +23,7 @@
(defn- apply-content-modifiers
[shape content-modifiers]
(let [shape (update shape :path-data types.path/apply-content-modifiers content-modifiers)]
(let [shape (update shape :path-data types.path/apply-path-data-modifiers content-modifiers)]
(types.path/update-geometry shape)))
(mf/defc path-wrapper

View File

@ -206,7 +206,7 @@
(let [segments [{:command :move-to
:params from}]
segments (conj segments segment)]
(path/content segments)))
(path/path-data segments)))
position
(mf/with-memo [segment]
@ -248,11 +248,11 @@
:style {:stroke secondary-color
:stroke-width (/ path-snap-stroke-width zoom)}}])]))
(defn- matching-handler? [content node handlers]
(defn- matching-handler? [path-data node handlers]
(when (= 2 (count handlers))
(let [[[i1 p1] [i2 p2]] handlers
p1 (path.segment/get-handler-point content i1 p1)
p2 (path.segment/get-handler-point content i2 p2)
p1 (path.segment/get-handler-point path-data i1 p1)
p2 (path.segment/get-handler-point path-data i2 p2)
v1 (gpt/to-vec node p1)
v2 (gpt/to-vec node p2)
@ -282,34 +282,34 @@
selected-points
(or selected-points #{})
base-content
base-path-data
(get shape :path-data)
base-points
(mf/with-memo [base-content]
(path/get-points base-content))
(mf/with-memo [base-path-data]
(path/get-points base-path-data))
content
(mf/with-memo [base-content content-modifiers]
(path/apply-content-modifiers base-content content-modifiers))
path-data
(mf/with-memo [base-path-data content-modifiers]
(path/apply-path-data-modifiers base-path-data content-modifiers))
content-points
(mf/with-memo [content]
(path/get-points content))
path-data-points
(mf/with-memo [path-data]
(path/get-points path-data))
point->base (->> (map hash-map content-points base-points) (reduce merge))
point->base (->> (map hash-map path-data-points base-points) (reduce merge))
base->point (map-invert point->base)
points
(mf/with-memo [content-points]
(into #{} content-points))
(mf/with-memo [path-data-points]
(into #{} path-data-points))
last-p
(->> content last path.helpers/segment->point)
(->> path-data last path.helpers/segment->point)
handlers
(mf/with-memo [content]
(path.segment/get-handlers content))
(mf/with-memo [path-data]
(path.segment/get-handlers path-data))
is-path-start
(not (some? last-point))
@ -329,13 +329,13 @@
(hooks/use-stream
ms/mouse-position
(mf/deps base-content zoom)
(mf/deps base-path-data zoom)
(fn [position]
(when-let [point (path.segment/closest-point base-content position (/ 0.01 zoom))]
(when-let [point (path.segment/closest-point base-path-data position (/ 0.01 zoom))]
(reset! hover-point (when (< (gpt/distance position point) (/ 10 zoom)) point)))))
[:g.path-editor {:ref editor-ref}
[:path {:d (.toString content)
[:path {:d (.toString path-data)
:style {:fill "none"
:stroke accent-color
:strokeWidth (/ 1 zoom)}}]
@ -367,7 +367,7 @@
(fn [[index prefix]]
;; FIXME: get-handler-point is executed twice for each
;; render, this can be optimized
(let [handler-position (path.segment/get-handler-point content index prefix)]
(let [handler-position (path.segment/get-handler-point path-data index prefix)]
(not= position handler-position)))
position-handlers
@ -390,10 +390,10 @@
[:g.path-node {:key (dm/str pos-x "-" pos-y)}
[:g.point-handlers {:pointer-events (when (= edit-mode :draw) "none")}
(for [[hindex prefix] position-handlers]
(let [handler-position (path.segment/get-handler-point content hindex prefix)
(let [handler-position (path.segment/get-handler-point path-data hindex prefix)
handler-hover? (contains? hover-handlers [hindex prefix])
moving-handler? (= handler-position moving-handler)
matching-handler? (matching-handler? content position position-handlers)]
matching-handler? (matching-handler? path-data position position-handlers)]
(when (and position handler-position)
[:> path-handler*

View File

@ -45,9 +45,9 @@
(def ^:private snap-nodes-icon
(deprecated-icon/icon-xref :snap-nodes (stl/css :snap-nodes-icon :pathbar-icon)))
(defn check-enabled [content selected-points]
(when content
(let [segments (path.segm/get-segments-with-points content selected-points)
(defn check-enabled [path-data selected-points]
(when path-data
(let [segments (path.segm/get-segments-with-points path-data selected-points)
num-segments (count segments)
num-points (count selected-points)
points-selected? (seq selected-points)
@ -56,7 +56,7 @@
max-segments (-> num-points
(* (- num-points 1))
(/ 2))
is-curve? (some #(path.segm/is-curve? content %) selected-points)]
is-curve? (some #(path.segm/is-curve? path-data %) selected-points)]
{:make-corner (and points-selected? is-curve?)
:make-curve (and points-selected? (not is-curve?))
@ -70,12 +70,12 @@
[{:keys [shape state]}]
(let [{:keys [edit-mode selected-points snap-toggled]} state
content (:content shape)
path-data (:path-data shape)
enabled-buttons
(mf/use-memo
(mf/deps content selected-points)
#(check-enabled content selected-points))
(mf/deps path-data selected-points)
#(check-enabled path-data selected-points))
on-select-draw-mode
(mf/use-fn

View File

@ -17,7 +17,7 @@
(defn initialize
[enabled?]
(if enabled?
(set! app.common.types.path/wasm:calc-bool-content wasm.api/calculate-bool)
(set! app.common.types.path/wasm:calc-bool-content nil))
(set! app.common.types.path/wasm:calc-bool-path-data wasm.api/calculate-bool)
(set! app.common.types.path/wasm:calc-bool-path-data nil))
(set! app.common.types.shape/wasm-enabled? enabled?)
(set! app.common.types.shape/wasm-create-shape wasm.shape/create-shape))

View File

@ -583,12 +583,12 @@
(defn set-shape-path-content
"Upload path content in chunks to WASM."
[content]
[path-data]
(let [chunk-size (quot MAX_BUFFER_CHUNK_SIZE 4)
buffer-size (path/get-byte-size content)
buffer-size (path/get-byte-size path-data)
padded-size (* 4 (mth/ceil (/ buffer-size 4)))
buffer (js/Uint8Array. padded-size)]
(path/write-to content (.-buffer buffer) 0)
(path/write-to path-data (.-buffer buffer) 0)
(h/call wasm/internal-module "_start_shape_path_buffer")
(let [heapu32 (mem/get-heap-u32)]
(loop [offset 0]
@ -1549,9 +1549,9 @@
data (mem/slice heap
(+ offset 1)
(* length path.impl/SEGMENT-U32-SIZE))
content (path/from-bytes data)]
path-data (path/from-bytes data)]
(mem/free)
content))
path-data))
(defn stroke-to-path
"Converts a shape's stroke at the given index into a filled path.
@ -1566,9 +1566,9 @@
(let [data (mem/slice heap
(+ offset 1)
(* length path.impl/SEGMENT-U32-SIZE))
content (path/from-bytes data)]
path-data (path/from-bytes data)]
(mem/free)
content)
path-data)
(do (mem/free)
nil))))
@ -1591,9 +1591,9 @@
data (mem/slice heap
(+ offset 1)
(* length path.impl/SEGMENT-U32-SIZE))
content (path/from-bytes data)]
path-data (path/from-bytes data)]
(mem/free)
content)))
path-data)))
(defn calculate-bool
[shape objects]
@ -1615,10 +1615,10 @@
(h/call wasm/internal-module "_init_shapes_pool" (count all-children))
(run! set-object all-children)
(let [content (-> (calculate-bool* bool-type ids)
(path.impl/path-data))]
(let [path-data (-> (calculate-bool* bool-type ids)
(path.impl/path-data))]
(h/call wasm/internal-module "_end_temp_objects")
content)))
path-data)))
(def POSITION-DATA-U8-SIZE 36)
(def POSITION-DATA-U32-SIZE (/ POSITION-DATA-U8-SIZE 4))