Graphite icon indicating copy to clipboard operation
Graphite copied to clipboard

Zooming in, then panning, then zooming back to 100% breaks pixel-perfect rendering

Open Keavon opened this issue 2 years ago • 0 comments

When we zoom in, then pan around, then zoom back out to 100%, we are left with a misalignment between document and viewport coordinates and the entire artwork becomes antialiased. We could check whenever we return to a 100% zoom and round it back. But then there are other zoom factors that aren't 100%— say, 99.999% should probably also snap back, or 50% or 200%, since those exact doublings/halvings should would also experience the pixel shift and resulting antialiasing (for example, if you zoomed to 358.245% then back to 200%, you'd also see the antialising). We need to figure out when to round the values, and if we want to save those updated values to the root layer transformation matrix or round them during the rendering process.

One option is to do it conditionally. Detect when the zoom is an exact multiple or divisor of 100% and apply the snapping in that case. But using conditionals is sort of a discontinuous solution to the problem, and I feel like there might be some sort of continuous solution (formula) that can be applied at any scale to apply the snapping in a consistent way where the result is as intended for multiples/divisors of 100%, without using a conditional.

Maybe something like transforming the origin point (from which the scaling is based) to the document space position that's in the center of the viewport, then round that, then transform the origin back. That way the AA is minimal near the center and gets worse near the edges of the view (if you're at something like 99.9% zoom), rather than being minimal near the origin (which is likely off-screen) and gets progressively worse as it goes further away and into viewport space.

It's sort of like a moiré pattern where the overlapping grids of viewport/screen space (always 100%) and document space (some other scale, but sometimes close to 100% which is when it matters most) are scaled differently and misaligned, causing the severity of misalignment (the resulting AA fuzziness) to have a wave-like pattern radially outwards from the origin (and any phase offset essentially transforms the origin). So we need to cause a phase offset to make the moiré pattern originate from the center of the viewport instead of somewhere random, and at that point we apply the rounding to the nearest pixel.

Keavon avatar Jul 26 '21 00:07 Keavon