Skip to main content
aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorSimeon Andreev2018-03-01 10:49:59 +0000
committerSimeon Andreev2018-03-05 12:48:16 +0000
commite78489ee67784eb3704ba210de1effcb777e0126 (patch)
tree67ba42dbc5b0cc34d78e6c451d21856272584acc /tests
parentfc1ec028ce6bb1b1df3db750ba0696e56156b5d4 (diff)
downloadeclipse.platform.swt-e78489ee67784eb3704ba210de1effcb777e0126.tar.gz
eclipse.platform.swt-e78489ee67784eb3704ba210de1effcb777e0126.tar.xz
eclipse.platform.swt-e78489ee67784eb3704ba210de1effcb777e0126.zip
Bug 531667 - [GTK3] Cannot draw Canvas with Control.print(GC)
Calling Canvas.pring(GC) results in no painted canvas on the GC. This is caused by a regression from the fix for Bug 421127. Control.print propagates the GC.handle as the last argument to Control.gtk_draw. With changes for Bug 421127 in Control.gtk_draw, the handle is no longer propagated to the actual onPaint event. The canvas (and canvas derived widgets) therefore no longer paint themselves on the GC. The problem which was fixed with the change in Control.gtk_draw, for Bug 421127, was that CTabFolder tabs were not painted. This is the case, since GC.getClipping returned broken values with GTK 3.10 and above. CTabFolder checks for intersection with the clipping region and doesn't paint itself. The clipping region was not computed properly, due to transformations done with the device space transformation matrix provided by Cairo. From GTK 3.10 onward, this matrix contains absolute coordinates of the widget, with respect to the shell. This causes the method to malfunction. With the fix for Bug 421127, the Cairo matrix is no longer propagated. As a result GC.getClipping only works with the identity matrix, resulting in correct clipping. This change reverts the change for Bug 421127 in Control.gtk_draw, for GTK versions 3.14 and above. The GC.getClipping method is adapted to first transform the local GC bounds to device space, before computing the intersection with the clipping region. This is done for GTK 3.14 and above. We validated the change with GTK 3.14 and GTK 3.22. A bug snippet is provided, show-casing clipping region and Cairo device space transformation matrix. Change-Id: Ib1d6bb866bcffa010a9e8f2a5e4296eba4e1d852 Signed-off-by: Simeon Andreev <simeon.danailov.andreev@gmail.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug421127_Clipping_is_wrong.java205
-rw-r--r--tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CanvasPrint_does_not_work.java96
2 files changed, 301 insertions, 0 deletions
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug421127_Clipping_is_wrong.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug421127_Clipping_is_wrong.java
new file mode 100644
index 0000000000..949a49cecc
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug421127_Clipping_is_wrong.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt). The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html. If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ *
+ * Contributors:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.swt.tests.gtk.snippets;
+
+
+import java.util.Arrays;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.GCData;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.internal.cairo.Cairo;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+
+/**
+ * Description: Clipping computed by {@link GC#getClipping()} is wrong.
+ * Steps to reproduce:
+ * <ol>
+ * <li>Run the snippet.</li>
+ * </ol>
+ * Expected results: All canvases are green, indicating that their bounds intersect with the clipping provided by {@link GC#getClipping()}.
+ * Actual results: Only the top-left canvas is green, the rest of the canvases are red.
+ * Further notes: The clipping of {@link GC#getClipping()} is shown below each colored canvas.
+ */
+public class Bug421127_Clipping_is_wrong {
+
+ public static void main (String [] args) {
+ Display display = new Display();
+ Shell shell = new Shell(display);
+ shell.setSize(800, 800);
+ shell.setText("Display clipping bounds");
+ shell.setLayout(new FillLayout());
+ Composite main = new Composite(shell, SWT.NONE);
+ main.setLayout(new FillLayout());
+
+ /*
+ * Splits the shell into some composites.
+ *
+ * The composites each contain:
+ * a) A canvas, which paints red or green depending on whether it intersects with GC.getClipping.
+ * b) A text, which displays computed GC.getClipping and Cairo.cairo_get_matrix for the composite.
+ */
+ Composite[] squares = showCaseClipping(main);
+ for (Composite square : squares) {
+ // comment in for a more complex example
+ //showCaseClipping(square);
+ square.layout();
+ }
+
+ shell.open ();
+ while (!shell.isDisposed ()) {
+ if (!display.readAndDispatch ()) display.sleep ();
+ }
+ display.dispose ();
+ }
+
+ private static Composite[] showCaseClipping(Composite main) {
+ Composite composite = new Composite(main, SWT.NONE);
+ composite.setLayout(new FillLayout());
+
+ Composite left = new Composite(composite, SWT.NONE);
+ left.setLayout(new FillLayout(SWT.VERTICAL));
+ Composite upperLeft = new Composite(left, SWT.BORDER);
+ Composite bottomLeft = new Composite(left, SWT.BORDER);
+
+ Composite right = new Composite(composite, SWT.NONE);
+ right.setLayout(new FillLayout(SWT.VERTICAL));
+ Composite upperRight = new Composite(right, SWT.BORDER);
+ Composite bottomRight = new Composite(right, SWT.BORDER);
+
+ Composite[] squares = { upperLeft, bottomLeft, upperRight, bottomRight };
+ for (Composite square : squares) {
+ square.setLayout(new FillLayout(SWT.VERTICAL));
+
+ final Canvas canvas = new Canvas(square, SWT.BORDER);
+ final Canvas text = new Canvas(square, SWT.BORDER);
+
+ class PaintCanvas implements PaintListener {
+ @Override
+ public void paintControl(PaintEvent event) {
+ paintCanvas(event, canvas);
+ }
+ }
+
+ class PrintClipping implements PaintListener {
+ @Override
+ public void paintControl(PaintEvent event) {
+ clippingText(event, text);
+ }
+ }
+
+ canvas.addPaintListener(new PaintCanvas());
+ text.addPaintListener(new PrintClipping());
+ }
+
+ return squares;
+ }
+
+ private static void paintCanvas(PaintEvent event, Canvas canvas) {
+ GC gc = gc(event);
+ Rectangle bounds = canvas.getBounds();
+ Rectangle clipping = gc.getClipping();
+ Device device = gc.getDevice();
+ int color = SWT.COLOR_GREEN;
+ String text = "CLIPPING AND BOUNDS INTERSECT";
+ if (!clipping.intersects(bounds)) {
+ color = SWT.COLOR_RED;
+ text = "CLIPPING AND BOUNDS DON'T INTERSECT";
+ }
+ gc.drawText(text, 0, 0);
+ gc.setAlpha(25);
+ gc.setBackground(device.getSystemColor(color));
+ gc.fillRectangle(bounds);
+ gc.setAlpha(255);
+ }
+
+ private static void clippingText(PaintEvent event, Canvas text) {
+ StringBuilder clipping = new StringBuilder();
+ appendCairoMatrix(event, clipping);
+ clipping.append(System.lineSeparator());
+ appendClippingRegion(event, clipping);
+
+ GC gc = gc(event);
+ gc.drawText(clipping.toString(), 0, 0);
+ }
+
+ private static void appendCairoMatrix(PaintEvent event, StringBuilder clipping) {
+ long cairo = cairo(event);
+ clipping.append("Cairo Matrix: ");
+ if (cairo != 0) {
+ double[] matrix = new double[6];
+ Cairo.cairo_get_matrix(cairo, matrix);
+ clipping.append(Arrays.toString(matrix));
+ } else {
+ clipping.append("--");
+ }
+ }
+
+ private static void appendClippingRegion(PaintEvent event, StringBuilder clipping) {
+ clipping.append("GC clipping: ");
+ Rectangle region = clipping(event);
+ if (region != null) {
+ clipping.append(region.x);
+ clipping.append(' ');
+ clipping.append(region.y);
+ clipping.append(' ');
+ clipping.append(region.width);
+ clipping.append(' ');
+ clipping.append(region.height);
+ } else {
+ clipping.append("--");
+ }
+ }
+
+ private static GC gc(PaintEvent event) {
+ if (event != null) {
+ return event.gc;
+ }
+ return null;
+ }
+
+ private static Rectangle clipping(PaintEvent event) {
+ GC gc = gc(event);
+ if (gc != null) {
+ Rectangle region = gc.getClipping();
+ return region;
+ }
+ return null;
+ }
+
+ private static long cairo(PaintEvent event) {
+ GC gc = gc(event);
+ if (gc != null) {
+ if (event.gc != null) {
+ GCData data = event.gc.getGCData();
+ if (data != null) {
+ return data.cairo;
+ }
+ }
+ }
+ return 0;
+ }
+
+}
diff --git a/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CanvasPrint_does_not_work.java b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CanvasPrint_does_not_work.java
new file mode 100644
index 0000000000..97a6567e6f
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/ManualTests/org/eclipse/swt/tests/gtk/snippets/Bug531667_CanvasPrint_does_not_work.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Simeon Andreev and others. All rights reserved.
+ * The contents of this file are made available under the terms
+ * of the GNU Lesser General Public License (LGPL) Version 2.1 that
+ * accompanies this distribution (lgpl-v21.txt). The LGPL is also
+ * available at http://www.gnu.org/licenses/lgpl.html. If the version
+ * of the LGPL at http://www.gnu.org is different to the version of
+ * the LGPL accompanying this distribution and there is any conflict
+ * between the two license versions, the terms of the LGPL accompanying
+ * this distribution shall govern.
+ *
+ * Contributors:
+ * Simeon Andreev - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.swt.tests.gtk.snippets;
+
+import java.io.File;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.ImageLoader;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * Description: {@link Canvas#print(GC)} does not print the canvas.
+ * Steps to reproduce:
+ * <ol>
+ * <li>Run the snippet.</li>
+ * <li>Examine the contents of {@code some_canvas.png}, absolute location is printed on the standard out.</li>
+ * </ol>
+ * Expected results: The image contains a white circle on a black background, similar to the canvas.
+ * Actual results: The image contains only black background.
+ */
+public class Bug531667_CanvasPrint_does_not_work {
+
+ public static void main(String[] args) {
+ String filename = "some_canvas.png";
+
+ Display display = new Display();
+ Shell shell = new Shell(display);
+ shell.setLayout(new FillLayout());
+ shell.setSize(200, 200);
+ shell.setText("Bug 531667");
+
+ Composite composite = canvas(display, shell);
+
+ shell.open();
+
+ snapshot(display, composite, filename);
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ display.dispose();
+ }
+
+ private static Composite canvas(Display display, Shell shell) {
+ Composite composite = new Composite(shell, SWT.NONE);
+ composite.setLayout(new FillLayout());
+ Canvas canvas = new Canvas(composite, SWT.NONE);
+ canvas.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
+ Color white = display.getSystemColor(SWT.COLOR_WHITE);
+
+ canvas.addPaintListener(e -> {
+ Rectangle clientArea = canvas.getClientArea();
+ e.gc.setBackground(white);
+ e.gc.fillOval(0, 0, clientArea.width, clientArea.height);
+ });
+ return composite;
+ }
+
+ private static void snapshot(Display display, Composite composite, String filename) {
+ Rectangle bounds = composite.getBounds();
+ Image image = new Image(display, bounds);
+ GC gc = new GC(image);
+ composite.print(gc);
+ gc.dispose();
+
+ ImageLoader loader = new ImageLoader();
+ loader.data = new ImageData[] { image.getImageData() };
+ File output = new File(filename);
+ output.delete();
+ loader.save(filename, SWT.IMAGE_PNG);
+ System.out.println("Image saved to: " + output.getAbsolutePath());
+ }
+}

Back to the top