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(); }
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(); }
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); }
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(); }
/// <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); }
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]); } } } }
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); }
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(); }