public Cairo.Pattern GetPattern(ApplicationContext actx, double scaleFactor)
 {
     if (pattern == null || currentScaleFactor != scaleFactor)
     {
         if (pattern != null)
         {
             pattern.Dispose();
         }
         Gdk.Pixbuf pb = ((GtkImage)Image.Backend).GetBestFrame(actx, scaleFactor, Image.Size.Width, Image.Size.Height, false);
         using (var imgs = new Cairo.ImageSurface(Cairo.Format.ARGB32, (int)(Image.Size.Width * scaleFactor), (int)(Image.Size.Height * scaleFactor))) {
             var ic = new Cairo.Context(imgs);
             ic.Scale((double)imgs.Width / (double)pb.Width, (double)imgs.Height / (double)pb.Height);
             Gdk.CairoHelper.SetSourcePixbuf(ic, pb, 0, 0);
             ic.Paint();
             imgs.Flush();
             ((IDisposable)ic).Dispose();
             pattern = new Cairo.SurfacePattern(imgs);
         }
         pattern.Extend = Cairo.Extend.Repeat;
         var cm = new Cairo.Matrix();
         cm.Scale(scaleFactor, scaleFactor);
         pattern.Matrix     = cm;
         currentScaleFactor = scaleFactor;
     }
     return(pattern);
 }
Exemplo n.º 2
0
        void Flush(bool recreate)
        {
#if GTK2
            if (Control != null)
            {
                // Analysis disable once RedundantCast - backward compatibility
                ((IDisposable)Control).Dispose();
                if (recreate)
                {
                    if (surface != null)
                    {
                        Control = new Cairo.Context(surface);
                    }
                    else if (drawable != null)
                    {
                        Control = Gdk.CairoHelper.Create(drawable);
                    }
                }
            }
#endif
            if (image != null)
            {
                var handler = (BitmapHandler)image.Handler;

                surface.Flush();
                handler.Surface = surface;
                if (!recreate)
                {
                    surface = null;
                }
            }
        }
Exemplo n.º 3
0
        public void Render(List <Layer> layers, Cairo.ImageSurface dst, Point offset)
        {
            dst.Flush();

            // Our rectangle of interest
            var r   = new Rectangle(offset, dst.GetBounds().Size).ToCairoRectangle();
            var doc = PintaCore.Workspace.ActiveDocument;

            using (var g = new Cairo.Context(dst)) {
                // Create the transparent checkerboard background
                g.Translate(-offset.X, -offset.Y);
                g.FillRectangle(r, tranparent_pattern, new Cairo.PointD(offset.X, offset.Y));

                for (var i = 0; i < layers.Count; i++)
                {
                    var layer = layers[i];

                    // If we're in LivePreview, substitute current layer with the preview layer
                    if (layer == doc.Layers.CurrentUserLayer && PintaCore.LivePreview.IsEnabled)
                    {
                        layer = CreateLivePreviewLayer(layer);
                    }

                    // If the layer is offset, handle it here
                    if (!layer.Transform.IsIdentity())
                    {
                        layer = CreateOffsetLayer(layer);
                    }

                    // No need to resize the surface if we're at 100% zoom
                    if (scale_factor.Ratio == 1)
                    {
                        layer.Draw(g, layer.Surface, layer.Opacity, false);
                    }
                    else
                    {
                        using (var scaled = CairoExtensions.CreateImageSurface(Cairo.Format.Argb32, dst.Width, dst.Height)) {
                            g.Save();
                            // Have to undo the translate set above
                            g.Translate(offset.X, offset.Y);
                            CopyScaled(layer.Surface, scaled, r.ToGdkRectangle());
                            layer.Draw(g, scaled, layer.Opacity, false);
                            g.Restore();
                        }
                    }
                }
            }

            // If we are at least 200% and grid is requested, draw it
            if (enable_pixel_grid && PintaCore.Actions.View.PixelGrid.Value && scale_factor.Ratio <= 0.5d)
            {
                RenderPixelGrid(dst, offset);
            }

            dst.MarkDirty();
        }
        public override void BeginUpdate()
        {
            Interlocked.Increment(ref lock_count);

            if (lock_count > 1)
            {
                return;
            }

            surface.Flush();
        }
Exemplo n.º 5
0
        // Runs on a background thread.
        void RenderTile(int renderId, int threadId, int tileIndex)
        {
            Exception exception = null;

            Gdk.Rectangle bounds = new Gdk.Rectangle();

            try {
                bounds = GetTileBounds(tileIndex);

                if (!cancel_render_flag)
                {
                    dest_surface.Flush();
                    effect.Render(source_surface, dest_surface, new [] { bounds });
                    dest_surface.MarkDirty(bounds.ToCairoRectangle());
                }
            } catch (Exception ex) {
                exception = ex;
                Debug.WriteLine("AsyncEffectRenderer Error while rendering effect: " + effect.Name + " exception: " + ex.Message + "\n" + ex.StackTrace);
            }

            // Ignore completions of tiles after a cancel or from a previous render.
            if (!IsRendering || renderId != render_id)
            {
                return;
            }

            // Update bounds to be shown on next expose.
            lock (updated_lock) {
                if (is_updated)
                {
                    updated_x1 = Math.Min(bounds.X, updated_x1);
                    updated_y1 = Math.Min(bounds.Y, updated_y1);
                    updated_x2 = Math.Max(bounds.X + bounds.Width, updated_x2);
                    updated_y2 = Math.Max(bounds.Y + bounds.Height, updated_y2);
                }
                else
                {
                    is_updated = true;
                    updated_x1 = bounds.X;
                    updated_y1 = bounds.Y;
                    updated_x2 = bounds.X + bounds.Width;
                    updated_y2 = bounds.Y + bounds.Height;
                }
            }

            if (exception != null)
            {
                lock (render_exceptions) {
                    render_exceptions.Add(exception);
                }
            }
        }
Exemplo n.º 6
0
 public override object Create(object img)
 {
     Gdk.Pixbuf pb = (Gdk.Pixbuf)img;
     var imgs = new Cairo.ImageSurface (Cairo.Format.ARGB32, pb.Width, pb.Height);
     var ic = new Cairo.Context (imgs);
     Gdk.CairoHelper.SetSourcePixbuf (ic, pb, 0, 0);
     ic.Paint ();
     imgs.Flush ();
     ((IDisposable)ic).Dispose ();
     var p = new Cairo.SurfacePattern (imgs);
     p.Extend = Cairo.Extend.Repeat;
     return p;
 }
Exemplo n.º 7
0
        public object Create(object img)
        {
            Gdk.Pixbuf pb   = (Gdk.Pixbuf)img;
            var        imgs = new Cairo.ImageSurface(Cairo.Format.ARGB32, pb.Width, pb.Height);
            var        ic   = new Cairo.Context(imgs);

            Gdk.CairoHelper.SetSourcePixbuf(ic, pb, 0, 0);
            ic.Paint();
            imgs.Flush();
            ((IDisposable)ic).Dispose();
            var p = new Cairo.SurfacePattern(imgs);

            p.Extend = Cairo.Extend.Repeat;
            return(p);
        }
Exemplo n.º 8
0
        public void Flush()
        {
            if (image != null)
            {
                var        handler = (BitmapHandler)image.Handler;
                Gdk.Pixbuf pb      = handler.GetPixbuf(Size.MaxValue);
                if (pb != null)
                {
                    surface.Flush();
                    var bd = handler.Lock();
                    unsafe
                    {
                        var srcrow  = (byte *)surface.DataPtr;
                        var destrow = (byte *)bd.Data;
                        for (int y = 0; y < image.Size.Height; y++)
                        {
                            var src  = (uint *)srcrow;
                            var dest = (uint *)destrow;
                            for (int x = 0; x < image.Size.Width; x++)
                            {
                                *dest = bd.TranslateArgbToData(*src);
                                dest++;
                                src++;
                            }
                            destrow += bd.ScanWidth;
                            srcrow  += surface.Stride;
                        }
                    }
                    handler.Unlock(bd);
                }
            }
#if GTK2
            if (Control != null)
            {
                // Analysis disable once RedundantCast - backward compatibility
                ((IDisposable)Control).Dispose();
                if (surface != null)
                {
                    Control = new Cairo.Context(surface);
                }
                else if (drawable != null)
                {
                    Control = Gdk.CairoHelper.Create(drawable);
                }
            }
#endif
        }
Exemplo n.º 9
0
        public void Render(List <Layer> layers, Cairo.ImageSurface dst, Gdk.Point offset)
        {
            dst.Flush();

            if (scale_factor.Ratio == 1)
            {
                RenderOneToOne(layers, dst, offset);
            }
            else if (scale_factor.Ratio < 1)
            {
                RenderZoomIn(layers, dst, offset);
            }
            else
            {
                RenderZoomOut(layers, dst, offset, destination_size);
            }

            dst.MarkDirty();
        }
Exemplo n.º 10
0
        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();
        }
Exemplo n.º 11
0
 public void Flush()
 {
     if (image != null)
     {
         var        handler = (BitmapHandler)image.Handler;
         Gdk.Pixbuf pb      = (Gdk.Pixbuf)image.ControlObject;
         if (pb != null)
         {
             surface.Flush();
             var bd = handler.Lock();
             unsafe {
                 byte *srcrow  = (byte *)surface.DataPtr;
                 byte *destrow = (byte *)bd.Data;
                 for (int y = 0; y < image.Size.Height; y++)
                 {
                     uint *src  = (uint *)srcrow;
                     uint *dest = (uint *)destrow;
                     for (int x = 0; x < image.Size.Width; x++)
                     {
                         *dest = bd.TranslateArgbToData(*src);
                         dest++;
                         src++;
                     }
                     destrow += bd.ScanWidth;
                     srcrow  += surface.Stride;
                 }
             }
             handler.Unlock(bd);
         }
     }
     if (Control != null)
     {
         ((IDisposable)Control).Dispose();
         if (surface != null)
         {
             this.Control = new Cairo.Context(surface);
         }
         else if (drawable != null)
         {
             this.Control = Gdk.CairoHelper.Create(drawable);
         }
     }
 }
Exemplo n.º 12
0
        private unsafe void CopyScaledZoomIn(Cairo.ImageSurface src, Cairo.ImageSurface dst, Rectangle roi)
        {
            // Tell Cairo we need the latest raw data
            dst.Flush();

            EnsureLookupTablesCreated();

            // Cache pointers to surface raw data
            var src_ptr = (ColorBgra *)src.DataPtr;
            var dst_ptr = (ColorBgra *)dst.DataPtr;

            // Cache surface sizes
            var src_width  = src.Width;
            var dst_width  = dst.Width;
            var dst_height = dst.Height;

            for (var dst_row = 0; dst_row < dst_height; ++dst_row)
            {
                // For each dest row, look up the src row to copy from
                var nnY  = dst_row + roi.Y;
                var srcY = d2sLookupY[nnY];

                // Get pointers to src and dest rows
                var dst_row_ptr = dst.GetRowAddressUnchecked(dst_ptr, dst_width, dst_row);
                var src_row_ptr = src.GetRowAddressUnchecked(src_ptr, src_width, srcY);

                for (var dstCol = 0; dstCol < dst_width; ++dstCol)
                {
                    // Look up the src column to copy from
                    var nnX  = dstCol + roi.X;
                    var srcX = d2sLookupX[nnX];

                    // Copy source to destination
                    *dst_row_ptr++ = *(src_row_ptr + srcX);
                }
            }

            // Tell Cairo we changed the raw data
            dst.MarkDirty();
        }
Exemplo n.º 13
0
		public Cairo.Pattern GetPattern (ApplicationContext actx, double scaleFactor)
		{
			if (pattern == null || currentScaleFactor != scaleFactor) {
				if (pattern != null)
					pattern.Dispose ();
				Gdk.Pixbuf pb = ((GtkImage)Image.Backend).GetBestFrame (actx, scaleFactor, Image.Size.Width, Image.Size.Height, false);
				using (var imgs = new Cairo.ImageSurface (Cairo.Format.ARGB32, (int)(Image.Size.Width * scaleFactor), (int)(Image.Size.Height * scaleFactor))) {
					var ic = new Cairo.Context (imgs);
					ic.Scale ((double)imgs.Width / (double)pb.Width, (double)imgs.Height / (double)pb.Height);
					Gdk.CairoHelper.SetSourcePixbuf (ic, pb, 0, 0);
					ic.Paint ();
					imgs.Flush ();
					((IDisposable)ic).Dispose ();
					pattern = new Cairo.SurfacePattern (imgs);
				}
				pattern.Extend = Cairo.Extend.Repeat;
				var cm = new Cairo.Matrix ();
				cm.Scale (scaleFactor, scaleFactor);
				pattern.Matrix = cm;
				currentScaleFactor = scaleFactor;
			}
			return pattern;
		}
Exemplo n.º 14
0
        /// <summary>
        /// Copy image data to the layer's surface.
        /// </summary>
        /// <param name="image_data">Array of image data in RGBA format.</param>
        private static unsafe void CopyToSurface(byte[] image_data, Cairo.ImageSurface surf)
        {
            if (image_data.Length != surf.Data.Length)
            {
                throw new ArgumentException("Mismatched image sizes");
            }

            surf.Flush();

            ColorBgra *dst = (ColorBgra *)surf.DataPtr;
            int        len = image_data.Length / ColorBgra.SizeOf;

            fixed(byte *src_bytes = image_data)
            {
                ColorBgra *src = (ColorBgra *)src_bytes;

                for (int i = 0; i < len; ++i)
                {
                    *dst++ = *src++;
                }
            }

            surf.MarkDirty();
        }
Exemplo n.º 15
0
        private unsafe void CopyScaledZoomOut(Cairo.ImageSurface src, Cairo.ImageSurface dst, Rectangle roi)
        {
            // Tell Cairo we need the latest raw data
            dst.Flush();

            const int fpShift  = 12;
            const int fpFactor = (1 << fpShift);

            var source_size = src.GetBounds().Size;

            // Find destination bounds
            var dst_left   = (int)(((long)roi.X * fpFactor * (long)source_size.Width) / (long)destination_size.Width);
            var dst_top    = (int)(((long)roi.Y * fpFactor * (long)source_size.Height) / (long)destination_size.Height);
            var dst_right  = (int)(((long)(roi.X + dst.Width) * fpFactor * (long)source_size.Width) / (long)destination_size.Width);
            var dst_bottom = (int)(((long)(roi.Y + dst.Height) * fpFactor * (long)source_size.Height) / (long)destination_size.Height);
            var dx         = (dst_right - dst_left) / dst.Width;
            var dy         = (dst_bottom - dst_top) / dst.Height;

            // Cache pointers to surface raw data and sizes
            var src_ptr    = (ColorBgra *)src.DataPtr;
            var dst_ptr    = (ColorBgra *)dst.DataPtr;
            var src_width  = src.Width;
            var dst_width  = dst.Width;
            var dst_height = dst.Height;

            for (int dstRow = 0, fDstY = dst_top; dstRow < dst_height && fDstY < dst_bottom; ++dstRow, fDstY += dy)
            {
                var srcY1 = fDstY >> fpShift;                                            // y
                var srcY2 = (fDstY + (dy >> 2)) >> fpShift;                              // y + 0.25
                var srcY3 = (fDstY + (dy >> 1)) >> fpShift;                              // y + 0.50
                var srcY4 = (fDstY + (dy >> 1) + (dy >> 2)) >> fpShift;                  // y + 0.75

                var src1   = src.GetRowAddressUnchecked(src_ptr, src_width, srcY1);
                var src2   = src.GetRowAddressUnchecked(src_ptr, src_width, srcY2);
                var src3   = src.GetRowAddressUnchecked(src_ptr, src_width, srcY3);
                var src4   = src.GetRowAddressUnchecked(src_ptr, src_width, srcY4);
                var dstPtr = dst.GetRowAddressUnchecked(dst_ptr, dst_width, dstRow);

                var checkerY    = dstRow + roi.Y;
                var checkerX    = roi.X;
                var maxCheckerX = checkerX + dst.Width;

                for (var fDstX = dst_left; checkerX < maxCheckerX && fDstX < dst_right; ++checkerX, fDstX += dx)
                {
                    var srcX1 = (fDstX + (dx >> 2)) >> fpShift;                                 // x + 0.25
                    var srcX2 = (fDstX + (dx >> 1) + (dx >> 2)) >> fpShift;                     // x + 0.75
                    var srcX3 = fDstX >> fpShift;                                               // x
                    var srcX4 = (fDstX + (dx >> 1)) >> fpShift;                                 // x + 0.50

                    var p1 = src1 + srcX1;
                    var p2 = src2 + srcX2;
                    var p3 = src3 + srcX3;
                    var p4 = src4 + srcX4;

                    var r = (2 + p1->R + p2->R + p3->R + p4->R) >> 2;
                    var g = (2 + p1->G + p2->G + p3->G + p4->G) >> 2;
                    var b = (2 + p1->B + p2->B + p3->B + p4->B) >> 2;
                    var a = (2 + p1->A + p2->A + p3->A + p4->A) >> 2;

                    // Copy color to destination
                    *dstPtr++ = ColorBgra.FromUInt32((uint)b + ((uint)g << 8) + ((uint)r << 16) + ((uint)a << 24));
                }
            }

            // Tell Cairo we changed the raw data
            dst.MarkDirty();
        }
Exemplo n.º 16
0
        public unsafe void Render(Cairo.ImageSurface dst, Gdk.Point offset)
        {
            if (cr.ScaleFactor > new ScaleFactor(1, 2))
            {
                return;
            }

            int[] d2SLookupX = cr.Dst2SrcLookupX;
            int[] d2SLookupY = cr.Dst2SrcLookupY;
            int[] s2DLookupX = cr.Src2DstLookupX;
            int[] s2DLookupY = cr.Src2DstLookupY;

            ColorBgra[] blackAndWhite = new ColorBgra[2] {
                ColorBgra.White, ColorBgra.Black
            };

            // draw horizontal lines
            int dstHeight = dst.Height;
            int dstWidth  = dst.Width;
            int dstStride = dst.Stride;
            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;

                if (dstRow >= 0 && dstRow < dstHeight)
                {
                    ColorBgra *dstRowPtr    = dst.GetRowAddressUnchecked(dstRow);
                    ColorBgra *dstRowEndPtr = dstRowPtr + dstWidth;

                    dstRowPtr += offset.X & 1;

                    while (dstRowPtr < dstRowEndPtr)
                    {
                        *dstRowPtr = ColorBgra.Black;
                        dstRowPtr += 2;
                    }
                }
            }

            // draw vertical lines
            int sLeft  = d2SLookupX[offset.X];
            int sRight = d2SLookupX[offset.X + dstWidth];

            for (int srcX = sLeft; srcX <= sRight; ++srcX)
            {
                int dstX   = s2DLookupX[srcX];
                int dstCol = dstX - offset.X;

                if (dstCol >= 0 && dstCol < dstWidth)
                {
                    byte *dstColPtr    = (byte *)dst.GetPointAddress(dstCol, 0);
                    byte *dstColEndPtr = dstColPtr + dstStride * dstHeight;

                    dstColPtr += (offset.Y & 1) * dstStride;

                    while (dstColPtr < dstColEndPtr)
                    {
                        *((ColorBgra *)dstColPtr) = ColorBgra.Black;
                        dstColPtr += 2 * dstStride;
                    }
                }
            }

            dst.MarkDirty();
        }