mirror of
https://github.com/penpot/penpot.git
synced 2026-04-25 11:18:36 +00:00
🔥 Remove duplicate gradient helpers from app.common.colors
The five functions interpolate-color, offset-spread, uniform-spread?, uniform-spread, and interpolate-gradient duplicated the canonical implementations in app.common.types.color. The copies in colors.cljc also contained two bugs: a division-by-zero in offset-spread when num=1, and a crash on nil idx in interpolate-gradient. All production callers already use app.common.types.color. The duplicate tests that exercised the old copies are removed; their coverage is absorbed into expanded tests under the types-* suite, including a new nil-idx guard test and a single-stop no-crash test. Signed-off-by: Andrey Antukh <niwi@niwi.nz>
This commit is contained in:
parent
db7c646568
commit
1e0f10814e
@ -487,62 +487,3 @@
|
||||
b (+ (* bh 100) (* bv 10))]
|
||||
(compare a b)))
|
||||
|
||||
(defn interpolate-color
|
||||
[c1 c2 offset]
|
||||
(cond
|
||||
(<= offset (:offset c1)) (assoc c1 :offset offset)
|
||||
(>= offset (:offset c2)) (assoc c2 :offset offset)
|
||||
|
||||
:else
|
||||
(let [tr-offset (/ (- offset (:offset c1)) (- (:offset c2) (:offset c1)))
|
||||
[r1 g1 b1] (hex->rgb (:color c1))
|
||||
[r2 g2 b2] (hex->rgb (:color c2))
|
||||
a1 (:opacity c1)
|
||||
a2 (:opacity c2)
|
||||
r (+ r1 (* (- r2 r1) tr-offset))
|
||||
g (+ g1 (* (- g2 g1) tr-offset))
|
||||
b (+ b1 (* (- b2 b1) tr-offset))
|
||||
a (+ a1 (* (- a2 a1) tr-offset))]
|
||||
{:color (rgb->hex [r g b])
|
||||
:opacity a
|
||||
:r r
|
||||
:g g
|
||||
:b b
|
||||
:alpha a
|
||||
:offset offset})))
|
||||
|
||||
(defn- offset-spread
|
||||
[from to num]
|
||||
(->> (range 0 num)
|
||||
(map #(mth/precision (+ from (* (/ (- to from) (dec num)) %)) 2))))
|
||||
|
||||
(defn uniform-spread?
|
||||
"Checks if the gradient stops are spread uniformly"
|
||||
[stops]
|
||||
(let [cs (count stops)
|
||||
from (first stops)
|
||||
to (last stops)
|
||||
expect-vals (offset-spread (:offset from) (:offset to) cs)
|
||||
|
||||
calculate-expected
|
||||
(fn [expected-offset stop]
|
||||
(and (mth/close? (:offset stop) expected-offset)
|
||||
(let [ec (interpolate-color from to expected-offset)]
|
||||
(and (= (:color ec) (:color stop))
|
||||
(= (:opacity ec) (:opacity stop))))))]
|
||||
(->> (map calculate-expected expect-vals stops)
|
||||
(every? true?))))
|
||||
|
||||
(defn uniform-spread
|
||||
"Assign an uniform spread to the offset values for the gradient"
|
||||
[from to num-stops]
|
||||
(->> (offset-spread (:offset from) (:offset to) num-stops)
|
||||
(mapv (fn [offset]
|
||||
(interpolate-color from to offset)))))
|
||||
|
||||
(defn interpolate-gradient
|
||||
[stops offset]
|
||||
(let [idx (d/index-of-pred stops #(<= offset (:offset %)))
|
||||
start (if (= idx 0) (first stops) (get stops (dec idx)))
|
||||
end (if (nil? idx) (last stops) (get stops idx))]
|
||||
(interpolate-color start end offset)))
|
||||
|
||||
@ -387,44 +387,41 @@
|
||||
(t/is (= 0.25 (c/reduce-range 0.3 4)))
|
||||
(t/is (= 0.0 (c/reduce-range 0.0 10))))
|
||||
|
||||
;; --- Gradient helpers
|
||||
;; --- Gradient helpers (app.common.types.color)
|
||||
|
||||
(t/deftest ac-interpolate-color
|
||||
(let [c1 {:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
c2 {:color "#ffffff" :opacity 1.0 :offset 1.0}]
|
||||
;; At c1's offset → c1 with updated offset
|
||||
(let [result (c/interpolate-color c1 c2 0.0)]
|
||||
(t/deftest types-interpolate-color
|
||||
(t/testing "at c1 offset returns c1 color"
|
||||
(let [c1 {:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
c2 {:color "#ffffff" :opacity 1.0 :offset 1.0}
|
||||
result (colors/interpolate-color c1 c2 0.0)]
|
||||
(t/is (= "#000000" (:color result)))
|
||||
(t/is (= 0.0 (:opacity result))))
|
||||
;; At c2's offset → c2 with updated offset
|
||||
(let [result (c/interpolate-color c1 c2 1.0)]
|
||||
(t/is (= 0.0 (:opacity result)))))
|
||||
(t/testing "at c2 offset returns c2 color"
|
||||
(let [c1 {:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
c2 {:color "#ffffff" :opacity 1.0 :offset 1.0}
|
||||
result (colors/interpolate-color c1 c2 1.0)]
|
||||
(t/is (= "#ffffff" (:color result)))
|
||||
(t/is (= 1.0 (:opacity result))))
|
||||
;; At midpoint → gray
|
||||
(let [result (c/interpolate-color c1 c2 0.5)]
|
||||
(t/is (= 1.0 (:opacity result)))))
|
||||
(t/testing "at midpoint returns interpolated gray"
|
||||
(let [c1 {:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
c2 {:color "#ffffff" :opacity 1.0 :offset 1.0}
|
||||
result (colors/interpolate-color c1 c2 0.5)]
|
||||
(t/is (= "#7f7f7f" (:color result)))
|
||||
(t/is (mth/close? (:opacity result) 0.5)))))
|
||||
|
||||
(t/deftest ac-uniform-spread
|
||||
(let [c1 {:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
c2 {:color "#ffffff" :opacity 1.0 :offset 1.0}
|
||||
stops (c/uniform-spread c1 c2 3)]
|
||||
(t/is (= 3 (count stops)))
|
||||
(t/is (= 0.0 (:offset (first stops))))
|
||||
(t/is (mth/close? 0.5 (:offset (second stops))))
|
||||
(t/is (= 1.0 (:offset (last stops))))))
|
||||
|
||||
(t/deftest ac-uniform-spread?
|
||||
(let [c1 {:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
c2 {:color "#ffffff" :opacity 1.0 :offset 1.0}
|
||||
stops (c/uniform-spread c1 c2 3)]
|
||||
;; A uniformly spread result should pass the predicate
|
||||
(t/is (true? (c/uniform-spread? stops))))
|
||||
;; Manual non-uniform stops should not pass
|
||||
(let [stops [{:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
{:color "#888888" :opacity 0.5 :offset 0.3}
|
||||
{:color "#ffffff" :opacity 1.0 :offset 1.0}]]
|
||||
(t/is (false? (c/uniform-spread? stops)))))
|
||||
(t/deftest types-uniform-spread
|
||||
(t/testing "produces correct count and offsets"
|
||||
(let [c1 {:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
c2 {:color "#ffffff" :opacity 1.0 :offset 1.0}
|
||||
stops (colors/uniform-spread c1 c2 3)]
|
||||
(t/is (= 3 (count stops)))
|
||||
(t/is (= 0.0 (:offset (first stops))))
|
||||
(t/is (mth/close? 0.5 (:offset (second stops))))
|
||||
(t/is (= 1.0 (:offset (last stops))))))
|
||||
(t/testing "single stop returns a vector of one element (no division by zero)"
|
||||
(let [c1 {:color "#ff0000" :opacity 1.0 :offset 0.0}
|
||||
stops (colors/uniform-spread c1 c1 1)]
|
||||
(t/is (= 1 (count stops))))))
|
||||
|
||||
(t/deftest types-uniform-spread?
|
||||
(t/testing "uniformly spread stops are detected as uniform"
|
||||
@ -447,16 +444,25 @@
|
||||
{:color "#ffffff" :opacity 1.0 :offset 1.0}]]
|
||||
(t/is (false? (colors/uniform-spread? stops))))))
|
||||
|
||||
(t/deftest ac-interpolate-gradient
|
||||
(let [stops [{:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
{:color "#ffffff" :opacity 1.0 :offset 1.0}]]
|
||||
;; At start
|
||||
(let [result (c/interpolate-gradient stops 0.0)]
|
||||
(t/is (= "#000000" (:color result))))
|
||||
;; At end
|
||||
(let [result (c/interpolate-gradient stops 1.0)]
|
||||
(t/is (= "#ffffff" (:color result))))
|
||||
;; In the middle
|
||||
(let [result (c/interpolate-gradient stops 0.5)]
|
||||
(t/is (= "#7f7f7f" (:color result))))))
|
||||
(t/deftest types-interpolate-gradient
|
||||
(t/testing "at start offset returns first stop color"
|
||||
(let [stops [{:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
{:color "#ffffff" :opacity 1.0 :offset 1.0}]
|
||||
result (colors/interpolate-gradient stops 0.0)]
|
||||
(t/is (= "#000000" (:color result)))))
|
||||
(t/testing "at end offset returns last stop color"
|
||||
(let [stops [{:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
{:color "#ffffff" :opacity 1.0 :offset 1.0}]
|
||||
result (colors/interpolate-gradient stops 1.0)]
|
||||
(t/is (= "#ffffff" (:color result)))))
|
||||
(t/testing "at midpoint returns interpolated gray"
|
||||
(let [stops [{:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
{:color "#ffffff" :opacity 1.0 :offset 1.0}]
|
||||
result (colors/interpolate-gradient stops 0.5)]
|
||||
(t/is (= "#7f7f7f" (:color result)))))
|
||||
(t/testing "offset beyond last stop returns last stop color (nil idx guard)"
|
||||
(let [stops [{:color "#000000" :opacity 0.0 :offset 0.0}
|
||||
{:color "#ffffff" :opacity 1.0 :offset 0.5}]
|
||||
result (colors/interpolate-gradient stops 1.0)]
|
||||
(t/is (= "#ffffff" (:color result))))))
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user