Package: pinta
Version: 0.4+dfsg-1

Cairo 1.9 implements caching for image surfaces, which means that
Pinta (which uses Cairo image surfaces as its internal representation)
doesn't work correctly with direct pixel operations manipulating the
underlying pixel array through pointers.

This problem is fixed by surrounding said direct pixel operations with
Flush and MarkDirty calls, which is what the attached patch does. I
also uploaded it to Ubuntu Maverick immediately, since it's a grave
bug that renders the application unusable.
Index: pinta-0.4+dfsg/Pinta.Core/Classes/AsyncEffectRenderer.cs
===================================================================
--- pinta-0.4+dfsg.orig/Pinta.Core/Classes/AsyncEffectRenderer.cs	2010-07-13 12:21:45.113280805 +0700
+++ pinta-0.4+dfsg/Pinta.Core/Classes/AsyncEffectRenderer.cs	2010-07-13 12:27:34.000000000 +0700
@@ -256,7 +256,7 @@
 				bounds = GetTileBounds (tileIndex);
 				
 				if (!cancel_render_flag)
-					effect.RenderEffect (source_surface, dest_surface, new [] { bounds });
+					effect.DoRenderEffect (source_surface, dest_surface, new [] { bounds });
 				
 			} catch (Exception ex) {		
 				exception = ex;
Index: pinta-0.4+dfsg/Pinta.Core/Classes/GradientRenderer.cs
===================================================================
--- pinta-0.4+dfsg.orig/Pinta.Core/Classes/GradientRenderer.cs	2010-07-13 12:21:45.081280921 +0700
+++ pinta-0.4+dfsg/Pinta.Core/Classes/GradientRenderer.cs	2010-07-13 12:27:34.000000000 +0700
@@ -121,6 +121,8 @@
 				endAlpha = this.endColor.A;
 			}
 			
+			surface.Flush ();
+			
 			ColorBgra* src_data_ptr = (ColorBgra*)surface.DataPtr;
 			int src_width = surface.Width;
 			
@@ -202,6 +204,7 @@
 				}
 			}
 			
+			surface.MarkDirty ();
 			AfterRender ();
 		}
 
Index: pinta-0.4+dfsg/Pinta.Core/Effects/BaseEffect.cs
===================================================================
--- pinta-0.4+dfsg.orig/Pinta.Core/Effects/BaseEffect.cs	2010-07-13 12:21:45.061280329 +0700
+++ pinta-0.4+dfsg/Pinta.Core/Effects/BaseEffect.cs	2010-07-13 12:33:00.701279409 +0700
@@ -51,6 +51,15 @@
 		}
 
 		#region Overrideable Render Methods
+		public void DoRenderEffect (ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
+		{
+			dst.Flush ();
+			RenderEffect (src, dst, rois);
+			dst.MarkDirty ();
+		}
+
+		// This function should not be public! It is only like this to minimize the diff.
+		// It should be changed to protected in upstream git here and in all derived classes.
 		public virtual void RenderEffect (ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)
 		{
 			foreach (var rect in rois)
Index: pinta-0.4+dfsg/Pinta.Core/Extensions/CairoExtensions.cs
===================================================================
--- pinta-0.4+dfsg.orig/Pinta.Core/Extensions/CairoExtensions.cs	2010-07-13 12:21:45.149279527 +0700
+++ pinta-0.4+dfsg/Pinta.Core/Extensions/CairoExtensions.cs	2010-07-13 12:27:34.000000000 +0700
@@ -652,6 +652,8 @@
 		public unsafe static Gdk.Pixbuf ToPixbuf (this Cairo.ImageSurface surfSource)
 		{
 			Cairo.ImageSurface surf = surfSource.Clone ();
+			surf.Flush ();
+			
 			ColorBgra* dstPtr = (ColorBgra*)surf.DataPtr;
 			int len = surf.Data.Length / 4;
 
Index: pinta-0.4+dfsg/Pinta.Gui.Widgets/Widgets/Canvas/CanvasRenderer.cs
===================================================================
--- pinta-0.4+dfsg.orig/Pinta.Gui.Widgets/Widgets/Canvas/CanvasRenderer.cs	2010-07-13 12:21:44.985279589 +0700
+++ pinta-0.4+dfsg/Pinta.Gui.Widgets/Widgets/Canvas/CanvasRenderer.cs	2010-07-13 12:27:34.000000000 +0700
@@ -45,12 +45,16 @@
 
 		public void Render (Cairo.ImageSurface src, Cairo.ImageSurface dst, Gdk.Point offset, bool checker)
 		{
+			dst.Flush ();
+		
 			if (scale_factor.Ratio == 1)
 				RenderOneToOne (src, dst, offset, checker);
 			else if (scale_factor.Ratio < 1)
 				RenderZoomIn (src, dst, offset, checker);
 			else
 				RenderZoomOut (src, dst, offset, destination_size, checker);
+			
+			dst.MarkDirty ();
 		}
 
 		#region Algorithms ported from PDN
Index: pinta-0.4+dfsg/Pinta.Gui.Widgets/Widgets/Canvas/GridRenderer.cs
===================================================================
--- pinta-0.4+dfsg.orig/Pinta.Gui.Widgets/Widgets/Canvas/GridRenderer.cs	2010-07-13 12:21:45.025279096 +0700
+++ pinta-0.4+dfsg/Pinta.Gui.Widgets/Widgets/Canvas/GridRenderer.cs	2010-07-13 12:27:34.000000000 +0700
@@ -40,6 +40,8 @@
 			int sTop = d2SLookupY[offset.Y];
 			int sBottom = d2SLookupY[offset.Y + dstHeight];
 
+			dst.Flush ();
+
 			for (int srcY = sTop; srcY <= sBottom; ++srcY) {
 				int dstY = s2DLookupY[srcY];
 				int dstRow = dstY - offset.Y;
@@ -77,6 +79,8 @@
 					}
 				}
 			}
+			
+			dst.MarkDirty ();
 		}
 	}
 }
Index: pinta-0.4+dfsg/Pinta.Tools/FloodTool.cs
===================================================================
--- pinta-0.4+dfsg.orig/Pinta.Tools/FloodTool.cs	2010-07-13 12:21:45.237279852 +0700
+++ pinta-0.4+dfsg/Pinta.Tools/FloodTool.cs	2010-07-13 12:27:34.000000000 +0700
@@ -118,11 +118,14 @@
 			int tol = (int)(Tolerance * Tolerance * 256);
 			Rectangle boundingBox;
 
+			surface.Flush ();
+
 			if (IsContinguousMode)
 				FillStencilFromPoint (surface, stencilBuffer, pos, tol, out boundingBox, currentRegion, limitToSelection);
 			else
 				FillStencilByColor (surface, stencilBuffer, surface.GetColorBgra (pos.X, pos.Y), tol, out boundingBox, currentRegion, LimitToSelection);
-				
+			
+			surface.MarkDirty ();
 			stencil = stencilBuffer;
 			
 			Point[][] polygonSet = PathManager.PolygonSetFromStencil (stencilBuffer, boundingBox, 0, 0);
Index: pinta-0.4+dfsg/Pinta.Tools/RecolorTool.cs
===================================================================
--- pinta-0.4+dfsg.orig/Pinta.Tools/RecolorTool.cs	2010-07-13 12:21:45.201279732 +0700
+++ pinta-0.4+dfsg/Pinta.Tools/RecolorTool.cs	2010-07-13 12:27:34.000000000 +0700
@@ -122,6 +122,8 @@
 			
 			roi = PintaCore.Workspace.ClampToImageSize (roi);
 			myTolerance = (int)(Tolerance * 256);
+			
+			tmp_layer.Flush ();
 
 			ColorBgra* tmp_data_ptr = (ColorBgra*)tmp_layer.DataPtr;
 			int tmp_width = tmp_layer.Width;
@@ -141,8 +143,9 @@
 
 					stencil[i, j] = true;
 				}
-
 			
+			tmp_layer.MarkDirty ();
+
 			using (Context g = new Context (surf)) {
 				g.AppendPath (PintaCore.Layers.SelectionPath);
 				g.FillRule = FillRule.EvenOdd;
Index: pinta-0.4+dfsg/Pinta.Tools/TextTool.cs
===================================================================
--- pinta-0.4+dfsg.orig/Pinta.Tools/TextTool.cs	2010-07-13 12:21:45.177279745 +0700
+++ pinta-0.4+dfsg/Pinta.Tools/TextTool.cs	2010-07-13 12:27:34.000000000 +0700
@@ -962,6 +962,7 @@
 				int xEnd = Math.Min (dst.Width, pt.X + measuredSize.Width);
 				
 				bool blending = false;
+				dst.Flush ();
 				//AppEnvironment.AlphaBlending;
 				//if (dst.IsColumnVisible(pt.X + skipX))
 				//{
@@ -1000,7 +1001,7 @@
 					}
 				}
 				//}
-				
+				dst.MarkDirty ();
 			}
 		}
 
@@ -1710,4 +1711,4 @@
                    ToolBarConfigItems.Brush | ToolBarConfigItems.Text | ToolBarConfigItems.AlphaBlending | ToolBarConfigItems.Antialiasing)
         {
         }*/	
-}
\ No newline at end of file
+}

Reply via email to