[players] Fix persisted eraser path for annotations#2118
Conversation
|
Note: this analysis was done with Claude Code, reviewed and endorsed by me. Thanks for the PR! The premise doesn't hold on fabric 7.4.0 though: Could you share reproduction steps? If lines really reappear, the cause is elsewhere. |
|
Uhm, sorry for that. This did indeed not fix it, I was overconfident on the fix. In fact, this didn't solve it (Just tested it again). I'll keep the fix in case it makes sense later (I'm not sure it will, I'll clean it up later). For a repro example, in an image preview, I:
(Note that to see the "reappearance", I have to go out of the preview/page and return) I'll iterate it, I have a better dev workflow now 😅 |
|
Fixed and checked |
|
Note: this analysis was done with Claude Code, reviewed and endorsed by me. Good news: this time the diagnosis is right, and I could verify it against fabric 7.4.0. Since the root cause is "the layout strategy runs at all", there is a smaller fix: neutralize the strategy once, instead of bypassing the constructor and // Initialization layout recenters children around their bbox center, which
// corrupts mask paths stored in the erased object's local frame. Never layout.
class NoLayout extends FixedLayout {
shouldPerformLayout() {
return false
}
}and in the I checked this variant against real fabric 7.4.0: children keep their coordinates on revival, the group keeps its serialized Your regression tests are the valuable part, please keep them. To make them still fail without the fix, the constructor(objects = [], opts = {}) {
this._objects = [...objects]
Object.assign(this, opts)
const strategy = opts.layoutManager?.strategy
if (objects.length && strategy?.shouldPerformLayout?.({ type: 'initialization' }) !== false) {
// mimic fabric: initialization layout recenters children around their bbox
this._objects.forEach(o => { o.left = 0; o.top = 0 })
}
}and While you are at it, could you also update the stale comment above the constructor ("Children passed to fromObject() are already in group-local coords; FixedLayout preserves them.") to describe the new invariant? Something like: mask paths live in the erased object's local frame and must never be repositioned, hence |
|
Fixed with Btw, also added a related-but-parallel issue fix (In |
|
Thank you |

Problem
While erasing annotations, apparently erased lines will reappear later, because the code that stores the eraser mask uses a "limited" Fabric intersection calculation:
I could reproduce it consistently by doing:
(Note that to see the "reappearance", I have to go out of the preview/page and return)
Example:
