Cut a region of a transparent layer in Photoshop, switch layers, and paste, and the paste lands at (0, 0), while in GIMP it lands at the cursor and in Krita at the layer origin, and none of them land where you cut from, because the position is recoverable in some editors, lost in others, and never consistently tested; the position isn’t part of the data, and it’s a side effect of whichever application happens to be in front of you when you hit paste.

Arte Ogre is the image editor we built to fix this, and it’s also the test that pins the fix in place.

The data-model fix

Arte Ogre is a Rust-native, GPU-accelerated, layered image editor with sparse tiled copy-on-write buffers, and when you cut a region from a layer, the engine stores the exact canvas coordinates alongside the pixel data, in the layer record, not in the clipboard; when you paste, the new layer is created at those coordinates, and that’s it, no UI math, no “snap to cursor,” no fallback to origin, because the paste position is a property of the data, not the gesture.

The reason this works is that cut and paste are symmetric in the data model, and the layer record carries the coordinates with the pixels, so there is no step in the pipeline where the coordinates can be lost, because they live in the same record as the data.

Why we test byte-identical round-trips

The cut/paste fix is invisible from the UI until you try it, since a pixel diff at the cursor catches the case where the paste lands somewhere wrong and the user notices but does not catch the case where the paste lands slightly off and the user does not notice, while the byte-identical round-trip test catches both, plus a hundred intermediate cases the user would never see.

The test is invariant, and it works like this: cut a 64-by-64 region at (120, 340) from a painted layer, paste into a new layer, hash the result, and check it against the committed reference hash; if the hash changes between commits, CI fails, and any movement of pixels, even by one byte, fails the build.

This is the same discipline as database ACID tests, where we do not test that “the write succeeded” but rather that “the bytes on disk match what I wrote”, same intent, applied to a different layer of the stack.

The cost

Every round-trip test is slow, as it hashes a multi-megapixel canvas on every PR, and we accept the cost, because tests that pin invariants are the tests that age best, while a test that asserts “the UI looks right” needs to be rewritten every time the UI changes and a test that asserts “this canvas hash equals that canvas hash” needs to be rewritten only when the data format changes, so spend CI seconds to skip design review cycles and the next refactor ships without a debate about where the cursor lands.

What changed since 2008

In 2008 we tested image editors by eyeballing the canvas, because we didn’t have anything better, and a pixel diff at the cursor was the best automated tool available, catching regressions but not invariants, because the invariant (“the paste lands where the cut was”) was a feature of the data model, not the test.

The modern equivalent is a content hash, same intent and a sharper test, and the hash does not know what an image editor is and does not need to.