Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[rap-dev] Setting clip on GC destroys recent state (+patch)

Hi there,

I've discovered an issue with the Canvas implementation when it comes to clipping

Unfortunately the only practical way to reset the clip of a HTML5 2D canvas context is to save/restore its state - however this does not only affect its clipping state but all other properties.

The current implementation of GCOperationWriter doesn't take this into account and therefore causes incorrect behaviour when clipping is used.
E.g. the following code should fill two blue rectangles - instead a yellow and a blue one is filled:

gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_YELLOW));
gc.setClipping(0, 0, 300, 300);
gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_BLUE));
gc.fillRectangle(10, 10, 20, 20);
gc.setClipping(1, 1, 300, 300);
gc.fillRectangle(30, 30, 20, 20);

The issue can be resolved by remembering the state that has been changed since the last GC.save() call - so that it can set up again properly after GC.restore() has to be called to get rid of the clip.

Please find below the suggested fix (ECA is signed).

Best regards, Clemens


--- rap_untouched/org.eclipse.rap/bundles/org.eclipse.rap.rwt/widgetkits/org/eclipse/swt/internal/widgets/canvaskit/GCOperationWriter.java    2017-02-16 02:18:46.739449633 +0100
+++ org.eclipse.rap/bundles/org.eclipse.rap.rwt/widgetkits/org/eclipse/swt/internal/widgets/canvaskit/GCOperationWriter.java    2017-02-16 01:50:44.164810648 +0100
@@ -50,9 +50,11 @@
   private int lineWidth;
   private RGB foreground;
   private RGB background;
+  private JsonArray[] currProperties;
 
   GCOperationWriter( Control control ) {
     this.control = control;
+    currProperties = new JsonArray[8];
   }
 
   void initialize() {
@@ -367,14 +369,25 @@
         String msg = "Unsupported operation id: " + operation.id;
         throw new RuntimeException( msg );
     }
-    operations.add( new JsonArray().add( name ).add( value ) );
+
+    JsonArray jsonPropArray = new JsonArray().add( name ).add( value );
+    currProperties[operation.id] = jsonPropArray;
+    operations.add( jsonPropArray );
   }
 
   private void setClipping( SetClipping operation ) {
     if( operation.isReset() ) {
       addClientOperation( "restore" );
+     
+      for(int i=0; i < currProperties.length; i++) {
+          if(currProperties[i] != null) {
+            operations.add( currProperties[i] );
+        }
+      }
     } else {
       addClientOperation( "save" );
+      currProperties = new JsonArray[currProperties.length];
+     
       if( operation.isRectangular() ) {
         Rectangle rect = operation.rectangle;
         addClientOperation( "beginPath" );
@@ -387,7 +400,8 @@
   }
 
   private void setTransform( SetTransform operation ) {
-    addClientOperation( "setTransform", operation.elements );
+    currProperties[7] = addClientOperation( "setTransform",
+      operation.elements );
   }
 
   private void renderPath( byte[] types, float[] points ) {
@@ -426,20 +440,22 @@
     }
   }
 
-  private void addClientOperation( String name, float... args ) {
+  private JsonArray addClientOperation( String name, float... args ) {
     JsonArray operation = new JsonArray().add( name );
     for( int i = 0; i < args.length; i++ ) {
       operation.add( args[ i ] );
     }
     operations.add( operation );
+    return operation;
   }
 
-  private void addClientOperation( String name, String argText, float... args ) {
+  private JsonArray addClientOperation( String name, String argText, float... args ) {
     JsonArray operation = new JsonArray().add( name ).add( argText );
     for( int i = 0; i < args.length; i++ ) {
       operation.add( args[ i ] );
     }
     operations.add( operation );
+    return operation;
   }
 
   private float getOffset( boolean fill ) {


Back to the top