Skip to content

Commit 643d401

Browse files
committed
Add Windows device zoom support for diagram image scaling
- This is a best effort to get an image that doesn't clip text on Windows - But lines are blurred - A mixture of things from ImagePrintFigureOperation and from eclipse-gef/gef-classic#1151
1 parent b29c3d6 commit 643d401

1 file changed

Lines changed: 80 additions & 23 deletions

File tree

com.archimatetool.editor/src/com/archimatetool/editor/diagram/util/DiagramUtils.java

Lines changed: 80 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import org.eclipse.draw2d.FreeformFigure;
99
import org.eclipse.draw2d.IFigure;
1010
import org.eclipse.draw2d.SWTGraphics;
11+
import org.eclipse.draw2d.geometry.Dimension;
1112
import org.eclipse.draw2d.geometry.Rectangle;
1213
import org.eclipse.gef.EditPartFactory;
1314
import org.eclipse.gef.GraphicalViewer;
@@ -16,17 +17,17 @@
1617
import org.eclipse.gef.editparts.FreeformGraphicalRootEditPart;
1718
import org.eclipse.gef.editparts.LayerManager;
1819
import org.eclipse.gef.ui.parts.GraphicalViewerImpl;
19-
import org.eclipse.swt.graphics.AutoscalingMode;
2020
import org.eclipse.swt.graphics.GC;
2121
import org.eclipse.swt.graphics.Image;
22-
import org.eclipse.swt.layout.FillLayout;
22+
import org.eclipse.swt.graphics.ImageData;
23+
import org.eclipse.swt.internal.DPIUtil;
2324
import org.eclipse.swt.widgets.Composite;
24-
import org.eclipse.swt.widgets.Display;
2525
import org.eclipse.swt.widgets.Shell;
2626

2727
import com.archimatetool.editor.diagram.DiagramEditorFactoryExtensionHandler;
2828
import com.archimatetool.editor.diagram.IDiagramEditorFactory;
2929
import com.archimatetool.editor.diagram.editparts.ArchimateDiagramEditPartFactory;
30+
import com.archimatetool.editor.diagram.figures.FigureUtils;
3031
import com.archimatetool.editor.diagram.sketch.editparts.SketchEditPartFactory;
3132
import com.archimatetool.model.IArchimateDiagramModel;
3233
import com.archimatetool.model.IDiagramModel;
@@ -70,8 +71,7 @@ else if(model instanceof ISketchModel) {
7071
}
7172

7273
GraphicalViewerImpl viewer = new GraphicalViewerImpl();
73-
viewer.createControl(parent).setAutoscalingMode(AutoscalingMode.ENABLED); // Stops text clipping on Windows
74-
74+
viewer.createControl(parent);
7575
viewer.setEditPartFactory(editPartFactory);
7676

7777
RootEditPart rootPart = new FreeformGraphicalRootEditPart();
@@ -105,13 +105,13 @@ public static Image createImage(IDiagramModel model, double scale, int margin) {
105105
*/
106106
public static ModelReferencedImage createModelReferencedImage(IDiagramModel model, double scale, int margin) {
107107
Shell shell = new Shell();
108-
shell.setLayout(new FillLayout());
109-
110-
GraphicalViewer viewer = createViewer(model, shell);
111-
ModelReferencedImage image = createModelReferencedImage(viewer, scale, margin);
112-
shell.dispose();
113-
114-
return image;
108+
try {
109+
GraphicalViewer viewer = createViewer(model, shell);
110+
return createModelReferencedImage(viewer, scale, margin);
111+
}
112+
finally {
113+
shell.dispose();
114+
}
115115
}
116116

117117
/**
@@ -155,27 +155,84 @@ private static ModelReferencedImage createModelReferencedImage(IFigure figure, d
155155
bounds.expand(margin / scale, margin / scale);
156156
}
157157

158-
Image image = new Image(Display.getDefault(), (int)(bounds.width * scale), (int)(bounds.height * scale));
158+
// On Windows use the scaled method else just create image with scale
159+
Image image = FigureUtils.isAutoScaleEnabled() ? createAutoScaledImage(figure, bounds, scale) : createImageAtScale(figure, bounds, 1.0, scale);
160+
return new ModelReferencedImage(image, bounds);
161+
}
162+
163+
/**
164+
* Create a scaled image on Windows depending on device zoom
165+
* Comes from https://github.com/eclipse-gef/gef-classic/discussions/1151
166+
*/
167+
@SuppressWarnings("restriction")
168+
private static Image createAutoScaledImage(IFigure figure, Rectangle bounds, double imageScale) {
169+
int deviceZoom = DPIUtil.getDeviceZoom();
170+
double displayScale = deviceZoom / 100.0;
171+
172+
// Create the image at scale
173+
Image imageZoom = createImageAtScale(figure, bounds, displayScale, imageScale);
174+
175+
// If device zoom is 100% no need for any more processing
176+
if(deviceZoom == 100) {
177+
return imageZoom;
178+
}
179+
180+
// Image is stored at 100% zoom, but is scaled by the monitor zoom
181+
ImageData imageDataZoom = imageZoom.getImageData(100);
182+
Image tmp = new Image(null, imageDataZoom);
183+
imageZoom.dispose();
184+
185+
int width100 = imageDataZoom.width * 100 / deviceZoom;
186+
int height100 = imageDataZoom.height * 100 / deviceZoom;
187+
Image image = new Image(null, width100, height100);
188+
159189
GC gc = new GC(image);
160-
SWTGraphics graphics = new ImageGraphics(gc); // Use ImageGraphics so we can get actual scale
190+
image.getImageData(deviceZoom);
191+
gc.drawImage(tmp, 0, 0, width100, height100);
192+
gc.dispose();
193+
194+
tmp.dispose();
161195

162-
if(scale != 1) {
163-
graphics.scale(scale);
196+
return image;
197+
}
198+
199+
/**
200+
* Create a scaled image
201+
* Parts from https://github.com/eclipse-gef/gef-classic/discussions/1151
202+
*/
203+
private static Image createImageAtScale(IFigure figure, Rectangle bounds, double displayScale, double imageScale) {
204+
Dimension size = bounds.getSize();
205+
206+
// Scale size by display scale * image scale
207+
size.scale(displayScale * imageScale);
208+
209+
Image image = new Image(null, size.width, size.height);
210+
211+
GC gc = new GC(image);
212+
213+
// Force image to be drawn as if at 100% zoom
214+
// This is the magic that stops text clipping
215+
if(FigureUtils.isAutoScaleEnabled()) {
216+
image.getImageData(100);
164217
}
218+
219+
SWTGraphics graphics = new ImageGraphics(gc);
220+
221+
// Scale by display and image scale
222+
graphics.scale(displayScale * imageScale);
165223

166224
// Compensate for negative co-ordinates
167225
graphics.translate(bounds.x * -1, bounds.y * -1);
168-
169-
// Paint onto graphics
170-
figure.paint(graphics);
171226

172-
// Dispose
173-
gc.dispose();
227+
// Paint figure
228+
figure.paint(graphics);
229+
174230
graphics.dispose();
231+
gc.dispose();
175232

176-
return new ModelReferencedImage(image, bounds);
233+
return image;
177234
}
178-
235+
179236
/**
180237
* Return the extents of the diagram by extending from the left-topmost child to the right-bottom-most child.
181238
* If there are no children in the diagram a minimal size of 100x100 is returned.

0 commit comments

Comments
 (0)