0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-13 02:28:18 -05:00

Improve path rendering performance.

This commit is contained in:
Andrey Antukh 2022-01-21 14:48:33 +01:00
parent bc04a0b9f0
commit 3d6c903273
5 changed files with 101 additions and 102 deletions

View file

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

View file

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

View file

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

View file

@ -20,21 +20,18 @@
[props]
(let [shape (unchecked-get props "shape")
content (:content shape)
pdata (mf/use-memo
(mf/deps content)
(fn []
(try
(upf/format-path content)
(catch :default e
(log/error :hint "unexpected error on formating path"
:shape-name (:name shape)
:shape-id (:id shape)
:cause e)
""))))
pdata (mf/with-memo [content]
(try
(upf/format-path content)
(catch :default e
(log/error :hint "unexpected error on formating path"
:shape-name (:name shape)
:shape-id (:id shape)
:cause e)
"")))
props (-> (attrs/extract-style-attrs shape)
(obj/merge!
#js {:d pdata}))]
(obj/set! "d" pdata))]
[:& shape-custom-stroke {:shape shape}
[:> :path props]]))

View file

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