0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-15 03:28:25 -05:00

Improve path rendering performance.

This commit is contained in:
Andrey Antukh 2022-01-21 14:48:33 +01:00 committed by Andrés Moya
parent ffa134f824
commit 8f6fdf361b
5 changed files with 95 additions and 92 deletions

View file

@ -376,19 +376,20 @@
set-tr set-tr
(fn [params px py] (fn [params px py]
(assoc params (-> params
px (+ (get params px) dx) (update px + dx)
py (+ (get params py) dy))) (update py + dy)))
transform-params transform-params
(fn [params] (fn [{:keys [x c1x c2x] :as params}]
(cond-> params (cond-> params
(contains? params :x) (set-tr :x :y) (some? x) (set-tr :x :y)
(contains? params :c1x) (set-tr :c1x :c1y) (some? c1x) (set-tr :c1x :c1y)
(contains? params :c2x) (set-tr :c2x :c2y)))] (some? c2x) (set-tr :c2x :c2y)))]
(->> content (into []
(mapv #(d/update-when % :params transform-params))))) (map #(update % :params transform-params))
content)))
(defn transform-content (defn transform-content
[content transform] [content transform]

View file

@ -42,9 +42,9 @@
(defn move (defn move
"Move the shape relatively to its current "Move the shape relatively to its current
position applying the provided delta." position applying the provided delta."
[shape {dx :x dy :y}] [{:keys [type] :as shape} {dx :x dy :y}]
(let [dx (d/check-num dx) (let [dx (d/check-num dx)
dy (d/check-num dy) dy (d/check-num dy)
move-vec (gpt/point dx dy)] move-vec (gpt/point dx dy)]
(-> shape (-> shape
@ -52,11 +52,8 @@
(update :points move-points move-vec) (update :points move-points move-vec)
(d/update-when :x + dx) (d/update-when :x + dx)
(d/update-when :y + dy) (d/update-when :y + dy)
(cond-> (= :bool (:type shape)) (cond-> (= :bool type) (update :bool-content gpa/move-content move-vec))
(update :bool-content gpa/move-content move-vec)) (cond-> (= :path type) (update :content gpa/move-content move-vec)))))
(cond-> (= :path (:type shape))
(update :content gpa/move-content move-vec)))))
;; --- Absolute Movement ;; --- Absolute Movement

View file

@ -17,8 +17,8 @@
(command->point command)))) (command->point command))))
([command] ([command]
(when-not (nil? command) (when command
(let [{{:keys [x y]} :params} command] (let [{:keys [x y]} (:params command)]
(gpt/point x y))))) (gpt/point x y)))))

View file

@ -19,10 +19,11 @@
[props] [props]
(let [shape (unchecked-get props "shape") (let [shape (unchecked-get props "shape")
content (:content shape) content (:content shape)
pdata (mf/use-memo (mf/deps content) #(upf/format-path content)) pdata (mf/with-memo [content]
(upf/format-path content))
props (-> (attrs/extract-style-attrs shape) props (-> (attrs/extract-style-attrs shape)
(obj/merge! (obj/set! "d" pdata))]
#js {:d pdata}))]
[:& shape-custom-stroke {:shape shape} [:& shape-custom-stroke {:shape shape}
[:> :path props]])) [:> :path props]]))

View file

@ -8,88 +8,92 @@
(:require (:require
[app.common.path.commands :as upc] [app.common.path.commands :as upc]
[app.common.path.subpaths :refer [pt=]] [app.common.path.subpaths :refer [pt=]]
[cuerdas.core :as str])) [app.util.array :as arr]))
(defn command->param-list [command] (defn- join-params
(let [params (:params command)] ([a]
(case (:command command) (js* "\"\"+~{}" a))
(:move-to :line-to :smooth-quadratic-bezier-curve-to) ([a b]
(str (:x params) "," (js* "\"\"+~{}+\",\"+~{}" a b))
(:y params)) ([a b c]
(js* "\"\"+~{}+\",\"+~{}+\",\"+~{}" a b c))
([a b c d]
(js* "\"\"+~{}+\",\"+~{}+\",\"+~{}+\",\"+~{}" a b c d))
([a b c d e]
(js* "\"\"+~{}+\",\"+~{}+\",\"+~{}+\",\"+~{}+\",\"+~{}" a b c d e))
([a b c d e f]
(js* "\"\"+~{}+\",\"+~{}+\",\"+~{}+\",\"+~{}+\",\"+~{}+\",\"+~{}" a b c d e f))
([a b c d e f g]
(js* "\"\"+~{}+\",\"+~{}+\",\"+~{}+\",\"+~{}+\",\"+~{}+\",\"+~{}+\",\"+~{}" a b c d e f g)))
:close-path (defn- translate-params
"" [command {:keys [x y] :as params}]
(case command
(:move-to :line-to :smooth-quadratic-bezier-curve-to)
(join-params x y)
(:line-to-horizontal :line-to-vertical) :close-path
(str (:value params)) ""
:curve-to (:line-to-horizontal :line-to-vertical)
(str (:c1x params) "," (:value params)
(:c1y params) ","
(:c2x params) ","
(:c2y params) ","
(:x params) ","
(:y params))
(:smooth-curve-to :quadratic-bezier-curve-to) :curve-to
(str (:cx params) "," (let [{:keys [c1x c1y c2x c2y]} params]
(:cy params) "," (join-params c1x c1y c2x c2y x y))
(:x params) ","
(:y params))
:elliptical-arc (:smooth-curve-to :quadratic-bezier-curve-to)
(str (:rx params) "," (let [{:keys [cx cy]} params]
(:ry params) "," (join-params cx cy x y))
(:x-axis-rotation params) ","
(:large-arc-flag params) ","
(:sweep-flag params) ","
(:x params) ","
(:y params))
""))) :elliptical-arc
(let [{:keys [rx ry x-axis-rotation large-arc-flag sweep-flag]} params]
(join-params rx ry x-axis-rotation large-arc-flag sweep-flag x y))
(defn command->string [{:keys [command relative] :as entry}] ""))
(let [command-str (case command
:move-to "M" (defn- translate-command
:close-path "Z" [cname]
:line-to "L" (case cname
:line-to-horizontal "H" :move-to "M"
:line-to-vertical "V" :close-path "Z"
:curve-to "C" :line-to "L"
:smooth-curve-to "S" :line-to-horizontal "H"
:quadratic-bezier-curve-to "Q" :line-to-vertical "V"
:smooth-quadratic-bezier-curve-to "T" :curve-to "C"
:elliptical-arc "A" :smooth-curve-to "S"
"") :quadratic-bezier-curve-to "Q"
command-str (if relative (str/lower command-str) command-str) :smooth-quadratic-bezier-curve-to "T"
param-list (command->param-list entry)] :elliptical-arc "A"
(str command-str param-list))) ""))
(defn set-point (defn- command->string
[command point] [{:keys [command relative params]}]
(-> command (let [cmd (cond-> (translate-command command)
(assoc-in [:params :x] (:x point)) relative (.toLowerCase))
(assoc-in [:params :y] (:y point)))) prm (translate-params command params)]
(js* "~{} + ~{}" cmd prm)))
(defn- set-point
[command {:keys [x y]}]
(update command :params assoc :x x :y y))
(defn format-path [content] (defn format-path [content]
(with-out-str (let [result (make-array (count content))]
(loop [last-move nil (reduce (fn [last-move current]
current (first content) (let [point (upc/command->point current)
content (rest content)] current-move? (= :move-to (:command current))
last-move (if current-move? point last-move)]
(when (some? current) (if (and (not current-move?) (pt= last-move point))
(let [point (upc/command->point current) (arr/conj! result (command->string (set-point current last-move)))
current-move? (= :move-to (:command current)) (arr/conj! result (command->string current)))
last-move (if current-move? point last-move)]
(if (and (not current-move?) (pt= last-move point)) (when (and (not current-move?) (pt= last-move point))
(print (command->string (set-point current last-move))) (arr/conj! result "Z"))
(print (command->string current)))
(when (and (not current-move?) (pt= last-move point)) last-move))
(print "Z")) nil
content)
(recur last-move (.join ^js result "")))
(first content)
(rest content)))))))