Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimeon Andreev2018-11-09 22:46:40 +0000
committerSimeon Andreev2018-11-14 09:07:23 +0000
commit3ea8682523dacaaa9b0f2ce65a94b5441fcde50f (patch)
treec574003ab2c1a5276ba52317e7d95c7e9c3f57fc /bundles
parent7b691dff112e6b36784fb5b87adb7861f98a4488 (diff)
downloadeclipse.platform.swt-3ea8682523dacaaa9b0f2ce65a94b5441fcde50f.tar.gz
eclipse.platform.swt-3ea8682523dacaaa9b0f2ce65a94b5441fcde50f.tar.xz
eclipse.platform.swt-3ea8682523dacaaa9b0f2ce65a94b5441fcde50f.zip
Bug 540908 - [GTK3] Poor performance in GC#setClipping on GTK3
Due to poor performance of org.eclipse.swt.graphics.Region.add(int[]), changes for bug 531667 lead to poor performance of Wire Sketcher. In particular, applying a transformation and then specifying clipping can be very slow. This is the case, since client clipping is limited by Cairo clipping, to avoid overwriting the global Cairo clipping (see bug 531667). This change adds a special case when client clipping is limited, in case the client transformation matrix has no rotation. In this case, its possible to use org.eclipse.swt.graphics.Region.add(Rectangle) which is much more efficient. Note that org.eclipse.swt.graphics.Region.add(int[]) allows adding a polygon to a Cairo region. A Cairo region however is defined by rectangles only. So client clipping rectangles which are no longer rectangles after their client transformation will be expensive. Change-Id: I9c8b2becf545d785d3b36b3773db090013937737 Signed-off-by: Simeon Andreev <simeon.danailov.andreev@gmail.com>
Diffstat (limited to 'bundles')
-rw-r--r--bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java43
1 files changed, 41 insertions, 2 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java
index 1abda4b135..aa8871cb3d 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/graphics/GC.java
@@ -2922,8 +2922,15 @@ private void limitClipping(long /*int*/ gcClipping) {
double[] invertedCurrentTransform = currentTransform.clone();
Cairo.cairo_matrix_invert(invertedCurrentTransform);
int[] clippingWithoutUserTransform = transformRectangle(invertedCurrentTransform, clipping);
- clippingRegion.add(clippingWithoutUserTransform);
- Cairo.cairo_region_intersect(gcClipping, clippingRegion.handle);
+ /* Bug 540908: limiting clipping is very slow if client uses a transformation
+ * Check if client transformation has no rotation, then use Region.add(Rectangle) as its much faster than Region.add(int[])
+ */
+ if (hasNoRotation(invertedCurrentTransform)) {
+ Rectangle rectangle = getTransformedClippingRectangle(clippingWithoutUserTransform);
+ clippingRegion.add(rectangle);
+ } else {
+ clippingRegion.add(clippingWithoutUserTransform);
+ }
} else {
clippingRegion.add(clipping);
}
@@ -2964,6 +2971,38 @@ private static int[] transformPoints(double[] transformation, Point[] points) {
return transformedPoints;
}
+private static boolean hasNoRotation(double[] matrix) {
+ /* Indices in the matrix are: (m11 m12 d1)
+ * 0: m11, 1: m12, 2: m21, 3: m22, 4: d1, 5: d2 (m21 m22 d2)
+ */
+ double m12 = matrix[1];
+ double m21 = matrix[2];
+ return m12 == 0.0 && m21 == 0.0;
+}
+
+/* input must be ordered the ordered points of a rectangle:
+ * pointsArray = {x1, y1, x2, y2, x3, y3, x4, y4}
+ * with lines (x1,y1) to (x2,y2), (x2,y2) to (x3,y3), (x3,y3) to (x4,y4), (x4,y4) to (x1,y1)
+ * the lines must be parallel or orthogonal to the x resp. y axis
+ */
+private static Rectangle getTransformedClippingRectangle(int[] pointsArray) {
+ int x1 = pointsArray[0];
+ int y1 = pointsArray[1];
+ int x2 = pointsArray[2];
+ int y2 = pointsArray[3];
+ int x3 = pointsArray[4];
+ int y3 = pointsArray[5];
+ int x4 = pointsArray[6];
+ int y4 = pointsArray[7];
+ // (x,y) is bottom left corner, so we need minimum x and y coordinates
+ int x = Math.min(Math.min(x1, x2), Math.min(x3, x4));
+ int y = Math.min(Math.min(y1, y2), Math.min(y3, y4));
+ int width = Math.abs(x1 - x2);
+ int height = Math.abs(y1 - y4);
+ Rectangle r = new Rectangle(x, y, width, height);
+ return r;
+}
+
void setClipping(long /*int*/ clipRgn) {
long /*int*/ cairo = data.cairo;
if (clipRgn == 0) {

Back to the top