From 7fa47d68a8fce8ed21203ab9fb125ea79fab0e1e Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 1 Feb 2024 16:30:54 +0100 Subject: [PATCH] :bug: Fix problems with text gradients --- .../app/common/geom/shapes/transforms.cljc | 37 +++++++------ common/src/app/common/text.cljc | 22 +++++++- frontend/src/app/main/ui/shapes/fills.cljs | 52 ++++++++++++++----- .../src/app/main/ui/shapes/text/styles.cljs | 2 +- .../main/ui/workspace/viewport/gradients.cljs | 28 +++++----- 5 files changed, 95 insertions(+), 46 deletions(-) diff --git a/common/src/app/common/geom/shapes/transforms.cljc b/common/src/app/common/geom/shapes/transforms.cljc index f9be02ada..f6ee1ea00 100644 --- a/common/src/app/common/geom/shapes/transforms.cljc +++ b/common/src/app/common/geom/shapes/transforms.cljc @@ -140,6 +140,28 @@ (gmt/translate (gpt/negate shape-center))))) +(defn inverse-transform-matrix + ([shape] + (inverse-transform-matrix shape nil)) + + ([shape params] + (inverse-transform-matrix shape params (or (gco/shape->center shape) (gpt/point 0 0)))) + + ([{:keys [flip-x flip-y transform-inverse] :as shape} {:keys [no-flip]} shape-center] + (-> (gmt/matrix) + (gmt/translate shape-center) + + (cond-> (and flip-x no-flip) + (gmt/scale (gpt/point -1 1))) + + (cond-> (and flip-y no-flip) + (gmt/scale (gpt/point 1 -1))) + + (cond-> (some? transform-inverse) + (gmt/multiply transform-inverse)) + + (gmt/translate (gpt/negate shape-center))))) + (defn transform-str ([shape] (transform-str shape nil)) @@ -152,21 +174,6 @@ (dm/str (transform-matrix shape params)) ""))) -;; FIXME: performance -(defn inverse-transform-matrix - ([shape] - (let [shape-center (or (gco/shape->center shape) - (gpt/point 0 0))] - (inverse-transform-matrix shape shape-center))) - ([{:keys [flip-x flip-y] :as shape} center] - (-> (gmt/matrix) - (gmt/translate center) - (cond-> - flip-x (gmt/scale (gpt/point -1 1)) - flip-y (gmt/scale (gpt/point 1 -1))) - (gmt/multiply (:transform-inverse shape (gmt/matrix))) - (gmt/translate (gpt/negate center))))) - ;; FIXME: move to geom rect? (defn transform-rect "Transform a rectangles and changes its attributes" diff --git a/common/src/app/common/text.cljc b/common/src/app/common/text.cljc index f8297843d..8b301d2d4 100644 --- a/common/src/app/common/text.cljc +++ b/common/src/app/common/text.cljc @@ -244,6 +244,21 @@ (run! #(.appendCodePoint sb (int %)) (subvec cpoints start end)) (.toString sb)))) +(defn- fix-gradients + "Conversion from draft doesn't convert correctly the fills gradient types. This + function change the type from string to keyword of the gradient type" + [data] + (letfn [(fix-type [type] + (cond-> type + (string? type) keyword)) + + (update-fill [fill] + (d/update-in-when fill [:fill-color-gradient :type] fix-type)) + + (update-all-fills [fills] + (mapv update-fill fills))] + (d/update-when data :fills update-all-fills))) + (defn convert-from-draft [content] (letfn [(extract-text [cpoints part] @@ -251,7 +266,9 @@ end (inc (first (last part))) text (code-points->text cpoints start end) attrs (second (first part))] - (assoc attrs :text text))) + (-> attrs + (fix-gradients) + (assoc :text text)))) (split-texts [text styles] (let [cpoints (text->code-points text) @@ -268,7 +285,8 @@ (let [key (get block :key) text (get block :text) styles (get block :inlineStyleRanges) - data (get block :data)] + data (->> (get block :data) + fix-gradients)] (-> data (assoc :key key) (assoc :type "paragraph") diff --git a/frontend/src/app/main/ui/shapes/fills.cljs b/frontend/src/app/main/ui/shapes/fills.cljs index 518222bcf..e4cb1eee3 100644 --- a/frontend/src/app/main/ui/shapes/fills.cljs +++ b/frontend/src/app/main/ui/shapes/fills.cljs @@ -8,7 +8,10 @@ (:require [app.common.data :as d] [app.common.data.macros :as dm] + [app.common.files.helpers :as cfh] + [app.common.geom.point :as gpt] [app.common.geom.shapes :as gsh] + [app.common.geom.shapes.text :as gst] [app.config :as cf] [app.main.ui.shapes.attrs :as attrs] [app.main.ui.shapes.gradients :as grad] @@ -28,7 +31,12 @@ fills (get shape :fills []) selrect (dm/get-prop shape :selrect) + + bounds (when (cfh/text-shape? shape) + (gst/shape->rect shape)) + metadata (get shape :metadata) + x (dm/get-prop selrect :x) y (dm/get-prop selrect :y) width (dm/get-prop selrect :width) @@ -62,32 +70,50 @@ (obj/set! pat-props "patternTransform" transform) pat-props)] - (for [[shape-index shape] (d/enumerate (or (:position-data shape) [shape]))] - [:* {:key (dm/str shape-index)} - (for [[fill-index value] (reverse (d/enumerate (get shape :fills [])))] + (for [[obj-index obj] (d/enumerate (or (:position-data shape) [shape]))] + [:* {:key (dm/str obj-index)} + (for [[fill-index value] (reverse (d/enumerate (get obj :fills [])))] (when (some? (:fill-color-gradient value)) (let [gradient (:fill-color-gradient value) + + from-p (-> (gpt/point (+ x (* width (:start-x gradient))) + (+ y (* height (:start-y gradient))))) + to-p (-> (gpt/point (+ x (* width (:end-x gradient))) + (+ y (* height (:end-y gradient))))) + + gradient + (cond-> gradient + (some? bounds) + (assoc + :start-x (/ (- (:x from-p) (:x bounds)) (:width bounds)) + :start-y (/ (- (:y from-p) (:y bounds)) (:height bounds)) + :end-x (/ (- (:x to-p) (:x bounds)) (:width bounds)) + :end-y (/ (- (:y to-p) (:y bounds)) (:height bounds)))) + props #js {:id (dm/str "fill-color-gradient-" render-id "-" fill-index) :key (dm/str fill-index) :gradient gradient - :shape shape}] - (case (:type gradient) - :linear [:> grad/linear-gradient props] - :radial [:> grad/radial-gradient props])))) + :shape obj}] + (case (d/name (:type gradient)) + "linear" [:> grad/linear-gradient props] + "radial" [:> grad/radial-gradient props])))) - (let [fill-id (dm/str "fill-" shape-index "-" render-id)] + (let [fill-id (dm/str "fill-" obj-index "-" render-id)] [:> :pattern (-> (obj/clone pat-props) (obj/set! "id" fill-id) - (cond-> has-image? + (cond-> (and has-image? (nil? bounds)) (-> (obj/set! "width" (* width no-repeat-padding)) - (obj/set! "height" (* height no-repeat-padding))))) + (obj/set! "height" (* height no-repeat-padding)))) + (cond-> (some? bounds) + (-> (obj/set! "width" (:width bounds)) + (obj/set! "height" (:height bounds))))) [:g - (for [[fill-index value] (reverse (d/enumerate (get shape :fills [])))] + (for [[fill-index value] (reverse (d/enumerate (get obj :fills [])))] (let [style (attrs/get-fill-style value fill-index render-id type) props #js {:key (dm/str fill-index) - :width width - :height height + :width (d/nilv (:width bounds) width) + :height (d/nilv (:height bounds) height) :style style}] (if (:fill-image value) (let [uri (cf/resolve-file-media (:fill-image value)) diff --git a/frontend/src/app/main/ui/shapes/text/styles.cljs b/frontend/src/app/main/ui/shapes/text/styles.cljs index 64a8f34ef..0b4e325d9 100644 --- a/frontend/src/app/main/ui/shapes/text/styles.cljs +++ b/frontend/src/app/main/ui/shapes/text/styles.cljs @@ -93,7 +93,7 @@ :textTransform text-transform :color (if (and show-text? (not gradient?)) text-color "transparent") :background (when (and show-text? gradient?) text-color) - :caretColor (or text-color "black") + :caretColor (if (and (not gradient?) text-color) text-color "black") :overflowWrap "initial" :lineBreak "auto" :whiteSpace "break-spaces" diff --git a/frontend/src/app/main/ui/workspace/viewport/gradients.cljs b/frontend/src/app/main/ui/workspace/viewport/gradients.cljs index e2bf517d1..c035b3134 100644 --- a/frontend/src/app/main/ui/workspace/viewport/gradients.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/gradients.cljs @@ -118,7 +118,7 @@ :on-pointer-up on-pointer-up}]]) (mf/defc gradient-handler-transformed - [{:keys [from-p to-p width-p from-color to-color zoom editing transform + [{:keys [from-p to-p width-p from-color to-color zoom editing on-change-start on-change-finish on-change-width]}] (let [moving-point (mf/use-var nil) angle (+ 90 (gpt/angle from-p to-p)) @@ -151,7 +151,7 @@ (reset! moving-point nil))] (mf/use-effect - (mf/deps @moving-point from-p to-p width-p transform) + (mf/deps @moving-point from-p to-p width-p) (fn [] (let [subs (->> st/stream (rx/filter mse/pointer-event?) @@ -159,18 +159,17 @@ (rx/map mse/get-pointer-position) (rx/subs! (fn [pt] - (let [pt (gpt/transform pt transform)] - (case @moving-point - :from-p (when on-change-start (on-change-start pt)) - :to-p (when on-change-finish (on-change-finish pt)) - :width-p (when on-change-width - (let [width-v (gpt/unit (gpt/to-vec from-p width-p)) - distance (gpt/point-line-distance pt from-p to-p) - new-width-p (gpt/add - from-p - (gpt/multiply width-v (gpt/point distance)))] - (on-change-width new-width-p))) - nil)))))] + (case @moving-point + :from-p (when on-change-start (on-change-start pt)) + :to-p (when on-change-finish (on-change-finish pt)) + :width-p (when on-change-width + (let [width-v (gpt/unit (gpt/to-vec from-p width-p)) + distance (gpt/point-line-distance pt from-p to-p) + new-width-p (gpt/add + from-p + (gpt/multiply width-v (gpt/point distance)))] + (on-change-width new-width-p))) + nil))))] (fn [] (rx/dispose! subs))))) [:g.gradient-handlers [:defs @@ -296,7 +295,6 @@ :width-p (when (= :radial (:type gradient)) width-p) :from-color {:value start-color :opacity start-opacity} :to-color {:value end-color :opacity end-opacity} - :transform transform :zoom zoom :on-change-start on-change-start :on-change-finish on-change-finish