mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 05:50:35 +00:00
🐛 Compare measured text at its oriented corner
Keep auto-width and auto-height text positions in design comparison by using the first oriented corner. Measurement can change unrotated x/y while retaining that corner. Requested geometry also checks this anchor. The new matrix failed 29 of 88 assertions before the correction. Controls cover four rotations, reflection, one-pixel drift, fixed width and raw undo state without changing the geometry tolerance. The older matrix fixture now anchors both measured versions at the oriented corner; its assertions remain unchanged. Combined generator/oracle checks pass 139 tests / 899 assertions with 40 programs per property at seed 712. Original auto-height WASM replay passes 51 checks with exact undo/redo and full-sync consistency. The original page and normal focus are restored; no pending work remains. No production geometry, golden data or benchmark baseline changes. AI-assisted-by: gpt-6
This commit is contained in:
parent
7e2f8b8781
commit
00b743da0b
@ -145,6 +145,12 @@ first can split two positions 7e-7 px apart across a 0.005 boundary (F150).
|
||||
Scalar values and touched stay exact. comp/undo-check/same-state? supplies
|
||||
the shared comparison; its undo default remains 1e-10.
|
||||
|
||||
Measured auto-width/auto-height text compares its oriented first corner,
|
||||
not the unrotated selrect x/y, which can move as height/width changes
|
||||
(F220). Canonical comparison and requested geometry both retain that
|
||||
anchor at the existing 0.01 tolerance. Layout-owned positions remain
|
||||
derived; fixed text dimensions and raw undo geometry remain checked.
|
||||
|
||||
Swapped-head dimensions use the content main; position, rotation, flips,
|
||||
constraints and layout-item inputs use the position source (F151).
|
||||
When sizes differ, expected geometry keeps the position source's
|
||||
|
||||
@ -106,6 +106,12 @@
|
||||
(assoc moved
|
||||
:transform (matrix-effect shape (:transform moved) derived)
|
||||
:transform-inverse (matrix-effect shape (:transform-inverse moved) derived))))
|
||||
;; Measurement preserves the oriented first
|
||||
;; corner, not the unrotated rectangle's x/y.
|
||||
(cond-> (and (= :text (:type shape))
|
||||
(#{:auto-width :auto-height} (:grow-type shape)))
|
||||
(as-> moved (assoc moved :x (:x (first (:points moved)))
|
||||
:y (:y (first (:points moved))))))
|
||||
(as-> shape (apply dissoc shape
|
||||
(cond-> (derived-attributes objects shape)
|
||||
(and free-head-placement (:component-id shape) (:shape-ref shape)
|
||||
@ -273,6 +279,9 @@
|
||||
(not= (boolean (:flip-y shape)) (boolean (:flip-y expected))) (conj :flip-y)
|
||||
(and (not width-owned) (not (mth/close? (:width shape) (:width expected) 0.01))) (conj :width)
|
||||
(and (not height-owned) (not (mth/close? (:height shape) (:height expected) 0.01))) (conj :height)
|
||||
(and (not layout-child) auto-height
|
||||
(not (gsh/close-attrs? :points [(first (:points shape))]
|
||||
[(first (:points expected))] 0.01))) (conj :position)
|
||||
(and (not layout-child) (not auto-width) (not auto-height)
|
||||
(not (gsh/close-attrs? :points (:points shape) (:points expected) 0.01))) (conj :points))))
|
||||
|
||||
|
||||
@ -409,6 +409,43 @@
|
||||
(t/is (= equal? (oracle/equivalent? (oracle/canonical (tm/make-situation file))
|
||||
(oracle/canonical (tm/make-situation changed))))))))
|
||||
|
||||
(t/deftest measured-text-comparison-keeps-the-oriented-first-corner
|
||||
(doseq [grow-type [:auto-height :auto-width]
|
||||
angle [0 45 90 135]
|
||||
reflected? [false true]]
|
||||
(let [file (-> (thf/sample-file :file)
|
||||
(ths/add-sample-shape :text :type :text :grow-type grow-type
|
||||
:width 70 :height 25))
|
||||
page-id (:id (thf/current-page file))
|
||||
path [:data :pages-index page-id :objects (thi/id :text)]
|
||||
orient (fn [shape]
|
||||
(cond-> (gsh/transform-shape shape (n/geometry-modifiers shape :rotate angle))
|
||||
reflected? (as-> shape (gsh/transform-shape shape (n/geometry-modifiers shape :flip-x nil)))))
|
||||
file (update-in file path orient)
|
||||
original (get-in file path)
|
||||
measured (update-in file path
|
||||
(fn [shape]
|
||||
(let [resized (gsh/transform-shape
|
||||
shape (ctm/change-size shape
|
||||
(if (= :auto-width grow-type) 55 70) 17))]
|
||||
(gsh/move resized (gpt/subtract (first (:points shape))
|
||||
(first (:points resized)))))))
|
||||
shifted (update-in measured path gsh/move (gpt/point 1 0))
|
||||
wrong-width (assoc-in measured (conj path :width) 60)
|
||||
design #(oracle/canonical (tm/make-situation %) {:free-head-placement false})]
|
||||
(t/testing (str grow-type ", angle " angle ", reflected " reflected?)
|
||||
(t/is (oracle/equivalent? (design file) (design measured))))
|
||||
(t/is (not (oracle/equivalent? (design file) (design shifted))))
|
||||
(t/is (not= (oracle/snapshot (tm/make-situation file))
|
||||
(oracle/snapshot (tm/make-situation measured))))
|
||||
(t/is (nil? (oracle/check-requested-geometry (:objects (thf/current-page measured))
|
||||
(get-in measured path) original)))
|
||||
(t/is (thrown? #?(:clj Exception :cljs js/Error)
|
||||
(oracle/check-requested-geometry (:objects (thf/current-page shifted))
|
||||
(get-in shifted path) original)))
|
||||
(when (= :auto-height grow-type)
|
||||
(t/is (not (oracle/equivalent? (design file) (design wrong-width))))))))
|
||||
|
||||
(t/deftest matrix-comparison-does-not-reintroduce-derived-text-dimensions
|
||||
(doseq [grow-type [:auto-height :auto-width]]
|
||||
(let [file (-> (thf/sample-file :file)
|
||||
@ -423,8 +460,10 @@
|
||||
changed (assoc-in measured (conj path :transform) (gmt/matrix 1 0 0 1 2 0))
|
||||
stretched (assoc-in measured (conj path :transform) (gmt/matrix 1 0 0 1.1 0 0))
|
||||
fixed-width (assoc-in measured (conj path :width) 60)
|
||||
turn #(gsh/absolute-move (gsh/transform-shape % (n/geometry-modifiers % :rotate 45))
|
||||
(gpt/point 0 0))
|
||||
;; Both measured versions use the renderer's oriented corner anchor.
|
||||
turn (fn [shape]
|
||||
(let [turned (gsh/transform-shape shape (n/geometry-modifiers shape :rotate 45))]
|
||||
(gsh/move turned (gpt/negate (first (:points turned))))))
|
||||
rotated (update-in file path turn)
|
||||
rotated-measured (update-in measured path turn)
|
||||
design #(oracle/canonical (tm/make-situation %))]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user