Beispiel #1
0
        protected unsafe override void OnFillRegionComputed(IBitVector2D stencil)
        {
            Document     doc  = PintaCore.Workspace.ActiveDocument;
            ImageSurface surf = doc.ToolLayer.Surface;

            using (var g = new Context(surf)) {
                g.Operator = Operator.Source;
                g.SetSource(doc.CurrentUserLayer.Surface);
                g.Paint();
            }

            SimpleHistoryItem hist = new SimpleHistoryItem(Icon, Name);

            hist.TakeSnapshotOfLayer(doc.CurrentUserLayer);

            ColorBgra  color  = fill_color.ToColorBgra();
            ColorBgra *dstPtr = (ColorBgra *)surf.DataPtr;
            int        width  = surf.Width;

            surf.Flush();

            // Color in any pixel that the stencil says we need to fill
            Parallel.For(0, stencil.Height, y =>
            {
                int stencil_width = stencil.Width;
                for (int x = 0; x < stencil_width; ++x)
                {
                    if (stencil.GetUnchecked(x, y))
                    {
                        surf.SetColorBgraUnchecked(dstPtr, width, color, x, y);
                    }
                }
            });

            surf.MarkDirty();

            // Transfer the temp layer to the real one,
            // respecting any selection area
            using (var g = doc.CreateClippedContext()) {
                g.Operator = Operator.Source;
                g.SetSource(surf);
                g.Paint();
            }

            doc.ToolLayer.Clear();

            doc.History.PushNewItem(hist);
            doc.Workspace.Invalidate();
        }
Beispiel #2
0
        private unsafe void ApplyAndSwap(ImageSurface dst, bool swap)
        {
            dst.Flush();

            var       dest_width = dst.Width;
            var       dst_ptr    = (ColorBgra *)dst.DataPtr;
            var       mask_index = 0;
            ColorBgra swap_pixel;

            fixed(ColorBgra *fixed_ptr = pixels)
            {
                var pixel_ptr = fixed_ptr;

                dst_ptr += bounds.X + bounds.Y * dest_width;

                for (int y = bounds.Y; y <= bounds.GetBottom(); y++)
                {
                    for (int x = bounds.X; x <= bounds.GetRight(); x++)
                    {
                        if (bitmask[mask_index++])
                        {
                            if (swap)
                            {
                                swap_pixel = *dst_ptr;
                                *dst_ptr     = *pixel_ptr;
                                *pixel_ptr++ = swap_pixel;
                            }
                            else
                            {
                                *dst_ptr = *pixel_ptr++;
                            }
                        }

                        dst_ptr++;
                    }

                    dst_ptr += dest_width - bounds.Width;
                }
            }

            dst.MarkDirty();
        }
Beispiel #3
0
        protected override bool OnDrawn(Context cr)
        {
            var res = base.OnDrawn(cr);

            if (res)
            {
                var rect = Allocation;
                if (rect.Width > 0 && rect.Height > 0)
                {
                    SKColorType ctype = SKColorType.Bgra8888;
                    using (var bitmap = new SKBitmap(rect.Width, rect.Height, ctype, SKAlphaType.Premul))
                    {
                        if (bitmap == null)
                        {
                            throw new InvalidOperationException("Bitmap is null");
                        }
                        using (var skSurface = SKSurface.Create(new SKImageInfo(bitmap.Info.Width, bitmap.Info.Height, ctype, SKAlphaType.Premul), bitmap.GetPixels(out IntPtr len), bitmap.Info.RowBytes))
                        {
                            if (skSurface == null)
                            {
                                throw new InvalidOperationException("skSurface is null");
                            }
                            if (PaintSurface != null)
                            {
                                PaintSurface.Invoke(skSurface);
                            }
                            skSurface.Canvas.Flush();
                            using (Surface surface = new ImageSurface(bitmap.GetPixels(out len), Format.Argb32, bitmap.Width, bitmap.Height, bitmap.Width * 4))
                            {
                                surface.MarkDirty();
                                cr.SetSourceSurface(surface, 0, 0);
                                cr.Paint();
                            }
                        }
                    }
                }
            }
            return(res);
        }
Beispiel #4
0
    void DrawingAreaHandleSizeAllocated(object o, SizeAllocatedArgs args)
    {
        // Create a pixel format
        Babl.Format b = Babl.Format.FromString("cairo-ARGB32");

        // Create an ImageSurface onto which we will paint the checkerboard pattern
        s = new Cairo.ImageSurface(Cairo.Format.ARGB32, da.Allocation.Width, da.Allocation.Height);

        if (s != null)
        {
            if (checkerBoardNode != null)
            {
                // Paint the checkerboard pattern
                checkerBoardNode.Blit(1, Gegl.Rectangle.New(0, 0, Convert.ToUInt32(da.Allocation.Width),
                                                            Convert.ToUInt32(da.Allocation.Height)), b, s.DataPtr, 0, Gegl.BlitFlags.Default);
                // Mark the ImageSurface as being dirty.
                s.MarkDirty();
            }
        }

        // Queue a redraw (aka Invalidate)
        QueueDraw();
    }
Beispiel #5
0
        /// <summary>
        /// Gets an image surface based off the bitmap.
        /// </summary>
        /// <param name="bitmap">The provided bitmap.</param>
        /// <returns>The image surface built from the bitmap.</returns>
        public static ImageSurface getImageSurfaceFromAsset(Bitmap bitmap)
        {
            BitmapData bmp_data = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            ImageSurface imageSurface = new ImageSurface(Format.Argb32, bitmap.Width, bitmap.Height);

            unsafe
            {
                uint *destPixels   = (uint *)imageSurface.DataPtr.ToPointer();
                uint *sourcePixels = (uint *)bmp_data.Scan0.ToPointer();

                int size = bitmap.Width * bitmap.Height;

                for (int i = 0; i < size; i++)
                {
                    destPixels[i] = sourcePixels[i];
                }
            }

            imageSurface.MarkDirty();
            bitmap.UnlockBits(bmp_data);
            return(imageSurface);
        }
Beispiel #6
0
        protected override void Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle roi)
        {
            var r = roi.ToCairoRectangle();

            using (var temp = new ImageSurface(Format.Argb32, roi.Width, roi.Height)) {
                RenderClouds(temp, roi, Data.Scale, (byte)(Data.Seed ^ instanceSeed), Data.Power / 100.0,
                             PintaCore.Palette.PrimaryColor.ToColorBgra(), PintaCore.Palette.SecondaryColor.ToColorBgra());

                temp.MarkDirty();

                // Have to lock because effect renderer is multithreaded
                lock (render_lock) {
                    using (var g = new Context(dst)) {
                        // - Clear any previous render from the destination
                        // - Copy the source to the destination
                        // - Blend the clouds over the source
                        g.Clear(r);
                        g.BlendSurface(src, r);
                        g.BlendSurface(temp, r.Location(), (BlendMode)CloudsData.BlendOps[Data.BlendMode]);
                    }
                }
            }
        }
Beispiel #7
0
        protected unsafe override void OnMouseMove(object o, Gtk.MotionNotifyEventArgs args, Cairo.PointD point)
        {
            Document doc = PintaCore.Workspace.ActiveDocument;

            ColorBgra old_color;
            ColorBgra new_color;

            if (mouse_button == 1)
            {
                old_color = PintaCore.Palette.PrimaryColor.ToColorBgra();
                new_color = PintaCore.Palette.SecondaryColor.ToColorBgra();
            }
            else if (mouse_button == 3)
            {
                old_color = PintaCore.Palette.SecondaryColor.ToColorBgra();
                new_color = PintaCore.Palette.PrimaryColor.ToColorBgra();
            }
            else
            {
                last_point = point_empty;
                return;
            }

            int x = (int)point.X;
            int y = (int)point.Y;

            if (last_point.Equals(point_empty))
            {
                last_point = new Point(x, y);
            }

            if (doc.Workspace.PointInCanvas(point))
            {
                surface_modified = true;
            }

            ImageSurface surf      = doc.CurrentUserLayer.Surface;
            ImageSurface tmp_layer = doc.ToolLayer.Surface;

            Gdk.Rectangle roi = GetRectangleFromPoints(last_point, new Point(x, y));

            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;
            ColorBgra *surf_data_ptr = (ColorBgra *)surf.DataPtr;
            int        surf_width    = surf.Width;

            // The stencil lets us know if we've already checked this
            // pixel, providing a nice perf boost
            // Maybe this should be changed to a BitVector2DSurfaceAdapter?
            for (int i = roi.X; i <= roi.GetRight(); i++)
            {
                for (int j = roi.Y; j <= roi.GetBottom(); j++)
                {
                    if (stencil[i, j])
                    {
                        continue;
                    }

                    if (IsColorInTolerance(new_color, surf.GetColorBgraUnchecked(surf_data_ptr, surf_width, i, j)))
                    {
                        *tmp_layer.GetPointAddressUnchecked(tmp_data_ptr, tmp_width, i, j) = AdjustColorDifference(new_color, old_color, surf.GetColorBgraUnchecked(surf_data_ptr, surf_width, i, j));
                    }

                    stencil[i, j] = true;
                }
            }

            tmp_layer.MarkDirty();

            using (Context g = new Context(surf)) {
                g.AppendPath(doc.Selection.SelectionPath);
                g.FillRule = FillRule.EvenOdd;
                g.Clip();

                g.Antialias = UseAntialiasing ? Antialias.Subpixel : Antialias.None;

                g.MoveTo(last_point.X, last_point.Y);
                g.LineTo(x, y);

                g.LineWidth = BrushWidth;
                g.LineJoin  = LineJoin.Round;
                g.LineCap   = LineCap.Round;

                g.SetSource(tmp_layer);

                g.Stroke();
            }

            doc.Workspace.Invalidate(roi);

            last_point = new Point(x, y);
        }
Beispiel #8
0
        private void Draw(DrawingArea drawingarea1, Color tool_color, Cairo.PointD point, bool first_pixel)
        {
            int x = (int)point.X;
            int y = (int)point.Y;

            if (last_point.Equals(point_empty))
            {
                last_point = new Point(x, y);

                if (!first_pixel)
                {
                    return;
                }
            }

            Document doc = PintaCore.Workspace.ActiveDocument;

            if (doc.Workspace.PointInCanvas(point))
            {
                surface_modified = true;
            }

            ImageSurface surf = doc.CurrentUserLayer.Surface;

            if (first_pixel && doc.Workspace.PointInCanvas(point))
            {
                // Does Cairo really not support a single-pixel-long single-pixel-wide line?
                surf.Flush();
                int       shiftedX = (int)point.X;
                int       shiftedY = (int)point.Y;
                ColorBgra source   = surf.GetColorBgraUnchecked(shiftedX, shiftedY);
                if (UseAlphaBlending)
                {
                    source = UserBlendOps.NormalBlendOp.ApplyStatic(source, tool_color.ToColorBgra());
                }
                else
                {
                    source = tool_color.ToColorBgra();
                }
                surf.SetColorBgra(source.ToPremultipliedAlpha(), shiftedX, shiftedY);
                surf.MarkDirty();
            }
            else
            {
                using (Context g = new Context(surf)) {
                    g.AppendPath(doc.Selection.SelectionPath);
                    g.FillRule = FillRule.EvenOdd;
                    g.Clip();

                    g.Antialias = Antialias.None;

                    // Adding 0.5 forces cairo into the correct square:
                    // See https://bugs.launchpad.net/bugs/672232
                    g.MoveTo(last_point.X + 0.5, last_point.Y + 0.5);
                    g.LineTo(x + 0.5, y + 0.5);

                    g.SetSourceColor(tool_color);
                    if (UseAlphaBlending)
                    {
                        g.SetBlendMode(BlendMode.Normal);
                    }
                    else
                    {
                        g.Operator = Operator.Source;
                    }
                    g.LineWidth = 1;
                    g.LineCap   = LineCap.Square;

                    g.Stroke();
                }
            }

            Gdk.Rectangle r = GetRectangleFromPoints(last_point, new Point(x, y));

            doc.Workspace.Invalidate(doc.ClampToImageSize(r));

            last_point = new Point(x, y);
        }
        unsafe public void Render(ImageSurface surface, Gdk.Rectangle[] rois)
        {
            byte startAlpha;
            byte endAlpha;

            if (this.alphaOnly)
            {
                ComputeAlphaOnlyValuesFromColors(this.startColor, this.endColor, out startAlpha, out endAlpha);
            }
            else
            {
                startAlpha = this.startColor.A;
                endAlpha   = this.endColor.A;
            }

            surface.Flush();

            ColorBgra *src_data_ptr = (ColorBgra *)surface.DataPtr;
            int        src_width    = surface.Width;

            for (int ri = 0; ri < rois.Length; ++ri)
            {
                Gdk.Rectangle rect = rois[ri];

                if (this.startPoint.X == this.endPoint.X && this.startPoint.Y == this.endPoint.Y)
                {
                    // Start and End point are the same ... fill with solid color.
                    for (int y = rect.Top; y <= rect.GetBottom(); ++y)
                    {
                        ColorBgra *pixelPtr = surface.GetPointAddress(rect.Left, y);

                        for (int x = rect.Left; x <= rect.GetRight(); ++x)
                        {
                            ColorBgra result;

                            if (this.alphaOnly && this.alphaBlending)
                            {
                                byte resultAlpha = (byte)Utility.FastDivideShortByByte((ushort)(pixelPtr->A * endAlpha), 255);
                                result   = *pixelPtr;
                                result.A = resultAlpha;
                            }
                            else if (this.alphaOnly && !this.alphaBlending)
                            {
                                result   = *pixelPtr;
                                result.A = endAlpha;
                            }
                            else if (!this.alphaOnly && this.alphaBlending)
                            {
                                result = this.normalBlendOp.Apply(*pixelPtr, this.endColor);
                                //if (!this.alphaOnly && !this.alphaBlending)
                            }
                            else
                            {
                                result = this.endColor;
                            }

                            *pixelPtr = result;
                            ++pixelPtr;
                        }
                    }
                }
                else
                {
                    var mainrect = rect;
                    Parallel.ForEach(Enumerable.Range(rect.Top, rect.Height),
                                     (y) => ProcessGradientLine(startAlpha, endAlpha, y, mainrect, surface, src_data_ptr, src_width));
                }
            }

            surface.MarkDirty();
            AfterRender();
        }