Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 486664

Summary: [FX Zoom] Diagram is blurred after zooming in/out
Product: [Tools] GEF Reporter: Camille Letavernier <cletavernier>
Component: GEF FXAssignee: gef-inbox <gef-inbox>
Status: RESOLVED FIXED QA Contact:
Severity: minor    
Priority: P3 CC: matthias.wienand
Version: 0.2.0   
Target Milestone: 5.0.0 (Oxygen) M6   
Hardware: All   
OS: All   
Whiteboard:

Description Camille Letavernier CLA 2016-01-27 11:32:01 EST
Due to the (im)precision of doubles, zooming in and out around 1.0 results in blurred lines/elements. For example, we often end up with a zoom of 0.999[...]997 instead of 1.0 which, when rendered, gives very visible blurred lines/text/images

For example, here's the transformation applied to the viewport after a few zoom in/out operations (+ irrelevant scrolling):

AffineTransform[[0.999999999999997, 0.0, 707.4296889707344], [0.0, 0.999999999999997, -2710.1944145297266]]

The transformations should be rounded after the concatenation occurs. This might also make sense for scrolling (I don't know if moving a vertical line from 0.0001px to the right also results in a blurred line. It's probably the case, but I've not experienced it so far)
Comment 1 Matthias Wienand CLA 2016-09-08 10:51:42 EDT
I think we should provide methods for setting the absolute zoom level, as well as a method for normalizing the zoom level. The latter would round the absolute zoom level to the next multiple of, for example, 0.0078125 (so that it divides one: 1/0.0078125 = 128).
Comment 2 Matthias Wienand CLA 2016-09-09 09:00:20 EDT
I experimented a bit with the zoom level and adjusted the code as follows:
 - Added methods to FXChangeViewportPolicy:
   * setZoomLevel(zoomLevel): Sets the zoom level within the transformation matrix without altering any other values.
   * roundAndZoomRelative(zoomFactor,pivotX,pivotY): Computes the final zoom level, rounds it to 6 decimal places, ensures that integral zoom levels are not skipped (e.g. when zooming at a level of 0.99 by 1.05 the integral zoom level of 1 will be applied), applies the resulting zoom level using #zoomRelative(), and counter-acts any floating point errors by overwriting the zoom level in the transformation matrix (using #setZoomLevel()) if it is incorrect after #zoomRelative().
 - Renamed FXChangeViewportOperation#getNewTransform() to #getNewContentTransform() in alignment with #getInitialContentTransform().
 - Use the new roundAndZoomRelative() method within the zooming interaction policies.

The code is published on the master branch, therefore, I resolve this ticket as fixed for 5.0.0 M2. If you encounter a problem with this approach, or have a better mechanism in mind, feel free to re-open this ticket.
Comment 3 Matthias Wienand CLA 2016-10-04 11:39:39 EDT
Reopen to enhance and finalize the API:

 - Remove the confusing "Absolute"/"Relative" suffixes from the methods. They are meant to signify if the respective transformation is applied to the initial transformation or to the current transformation (which is important in the context of an interaction that continuously changes the zoom level, for example). Instead, a boolean parameter with a more expressive name should be used, such as "concatenate".
 => zoom(double factor, boolean concatenate)
 => scroll(double tx, double ty, boolean concatenate)

 - Remove the roundAndZoomRelative() method. Instead, add parameters "round" and "discretize" that can be used to control if the resulting final zoom factor should be rounded, and if zooming should be done discretely (so that some zoom levels cannot be skipped), respectively.
 => zoom(double factor, boolean concatenate, boolean round, boolean discretize)

 - The same set of parameters should be provided for scroll(), too.
 => scroll(double tx, double ty, boolean concatenate, boolean round, boolean discretize)

 - Add methods for setting the absolute scroll offsets / zoom level.
 => setAbsoluteZoom(double factor)
 => setAbsoluteScroll(double tx, double ty)
Comment 4 Matthias Wienand CLA 2019-09-12 08:46:34 EDT
I consider the API ready. Therefore, I resolve this ticket as fixed for 5.0.0 M6 where the latest change to the file was released.