Skip to content

Commit 67cd5aa

Browse files
committed
GC.setClipping(Path) doesn't paint on Linux when transformed #3120
The fix for Bug 531667 (d7ce597) is incomplete and doesn't properly update the clipping of a `Path` when a `Transform` is set. This is because the clipping is calculated by intersecting the clipping rectangle when the GC instance was created with the `Path`. The region described by the `Path` is affected by the transformation, while the region of the rectangle is not. To fix this problem, the transformation needs to be cleared and re-applied when resetting the clipping, so that the region of the clipping rectangle is properly updated. Closes #3120
1 parent 5ac1e10 commit 67cd5aa

2 files changed

Lines changed: 128 additions & 0 deletions

File tree

bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3094,7 +3094,19 @@ public void setClipping(int x, int y, int width, int height) {
30943094
public void setClipping(Path path) {
30953095
if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
30963096
if (path != null && path.isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
3097+
3098+
Transform t = null;
3099+
if (currentTransform != null) {
3100+
t = new Transform(getDevice());
3101+
getTransform(t);
3102+
setTransform(null);
3103+
}
30973104
resetClipping();
3105+
if (t != null) {
3106+
setTransform(t);
3107+
t.dispose();
3108+
}
3109+
30983110
if (path != null) {
30993111
initCairo();
31003112
long cairo = data.cairo;
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2026 Patrick Ziegler and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Patrick Ziegler - initial API and implementation
12+
*******************************************************************************/
13+
package org.eclipse.swt.tests.gtk.snippets;
14+
15+
import java.util.function.Consumer;
16+
17+
import org.eclipse.swt.SWT;
18+
import org.eclipse.swt.graphics.Color;
19+
import org.eclipse.swt.graphics.GC;
20+
import org.eclipse.swt.graphics.Path;
21+
import org.eclipse.swt.graphics.Transform;
22+
import org.eclipse.swt.layout.FillLayout;
23+
import org.eclipse.swt.widgets.Composite;
24+
import org.eclipse.swt.widgets.Display;
25+
import org.eclipse.swt.widgets.Shell;
26+
27+
/**
28+
* Description: {@link GC#setClipping(Path)} doesn't respect a previous call to
29+
* {@link GC#setTransform(Transform)}.
30+
* <ol>
31+
* <li>Run the snippet.</li>
32+
* </ol>
33+
* Expected results: All painted rectangle should be green.<br>
34+
* Actual results: The rectangles are at least partially painted red.
35+
*
36+
* @see <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=531667">Bug
37+
* 531667 - [GTK3] Cannot draw Canvas with Control.print(GC) </a>
38+
*/
39+
public class Issue3120_GC_setClipping_with_Transform {
40+
private static Display DISPLAY = Display.getDefault();
41+
private static Color COLOR_RED = DISPLAY.getSystemColor(SWT.COLOR_RED);
42+
private static Color COLOR_GREEN = DISPLAY.getSystemColor(SWT.COLOR_GREEN);
43+
44+
public static void main(String[] args) {
45+
Shell shell = new Shell();
46+
shell.setLayout(new FillLayout());
47+
shell.setSize(800, 300);
48+
49+
Composite composite1 = new Composite(shell, SWT.BORDER);
50+
composite1.addPaintListener(
51+
event -> paint(event.gc, p -> p.addRectangle(310, 310, 100, 100), t -> t.translate(-300, -300)));
52+
53+
Composite composite2 = new Composite(shell, SWT.BORDER);
54+
composite2.addPaintListener(
55+
event -> paint(event.gc, p -> p.addRectangle(20, 5, 200, 50), t -> t.scale(0.5f, 2.0f)));
56+
57+
Composite composite3 = new Composite(shell, SWT.BORDER);
58+
composite3.addPaintListener(
59+
event -> paint(event.gc, p -> p.addRectangle(10, 10, 100, 100), t -> t.shear(1.0f, 0.0f)));
60+
61+
Composite composite4 = new Composite(shell, SWT.BORDER);
62+
composite4.addPaintListener(event -> paint(event.gc, p -> p.addRectangle(10, 605, 100, 50), t -> {
63+
t.scale(1.0f, 2.0f);
64+
t.translate(0, -600);
65+
}));
66+
67+
Composite composite5 = new Composite(shell, SWT.BORDER);
68+
composite5.addPaintListener(event -> paint(event.gc, p -> p.addRectangle(10, 10, 100, 100), t -> {}, gc -> {
69+
Path p = new Path(DISPLAY);
70+
p.addRectangle(55, 55, 10, 10);
71+
gc.setClipping(p);
72+
p.dispose();
73+
}));
74+
75+
Composite composite6 = new Composite(shell, SWT.BORDER);
76+
composite6.addPaintListener(event -> paint(event.gc, p -> p.addRectangle(10, 275, 100, 50), t -> {
77+
t.scale(1.0f, 2.0f);
78+
t.translate(0, -270);
79+
}, gc -> {
80+
gc.setClipping(10, 10, 100, 100);
81+
}));
82+
83+
shell.open();
84+
85+
while(!shell.isDisposed()) {
86+
if (!DISPLAY.readAndDispatch()) {
87+
DISPLAY.sleep();
88+
}
89+
}
90+
}
91+
92+
private static void paint(GC gc, Consumer<Path> c1, Consumer<Transform> c2) {
93+
paint(gc, c1, c2, ignore -> {
94+
});
95+
}
96+
97+
private static void paint(GC gc, Consumer<Path> c1, Consumer<Transform> c2, Consumer<GC> c3) {
98+
Path p = new Path(DISPLAY);
99+
c1.accept(p);
100+
101+
Transform t = new Transform(DISPLAY);
102+
c2.accept(t);
103+
104+
gc.setTransform(t);
105+
t.dispose();
106+
107+
gc.setBackground(COLOR_RED);
108+
gc.fillPath(p);
109+
c3.accept(gc);
110+
gc.setClipping(p);
111+
gc.setBackground(COLOR_GREEN);
112+
gc.fillPath(p);
113+
114+
p.dispose();
115+
}
116+
}

0 commit comments

Comments
 (0)