void OnExpose(object sender, ExposeEventArgs args) { DrawingArea area = (DrawingArea)sender; Cairo.Context cairoContext = Gdk.CairoHelper.Create(area.GdkWindow); int width = area.Allocation.Width; int height = area.Allocation.Height; PixelDimensions = new Vector2i(width, height); AxisAlignedBox2d bounds = DrawingBounds; double sx = (double)width / bounds.Width; double sy = (double)height / bounds.Height; float scale = (float)Math.Min(sx, sy); // we apply this translate after scaling to pixel coords Vector2f pixC = Zoom * scale * (Vector2f)bounds.Center; Vector2f translate = new Vector2f(width / 2, height / 2) - pixC; using (var bitmap = new SKBitmap(width, height, SkiaUtil.ColorType(), SKAlphaType.Premul)) { IntPtr len; using (var skSurface = SKSurface.Create(bitmap.Info.Width, bitmap.Info.Height, SkiaUtil.ColorType(), SKAlphaType.Premul, bitmap.GetPixels(out len), bitmap.Info.RowBytes)) { var canvas = skSurface.Canvas; // update scene xform Func <Vector2d, Vector2f> ViewTransformF = (pOrig) => { Vector2f pNew = (Vector2f)pOrig - (Vector2f)bounds.Center; pNew = Zoom * scale * pNew; pNew += (Vector2f)pixC; pNew += translate + Zoom * PixelTranslate; pNew.y = canvas.ClipBounds.Height - pNew.y; return(pNew); }; DrawScene(canvas, ViewTransformF); Cairo.Surface cairoSurf = new Cairo.ImageSurface( bitmap.GetPixels(out len), Cairo.Format.Argb32, bitmap.Width, bitmap.Height, bitmap.Width * 4); cairoSurf.MarkDirty(); cairoContext.SetSourceSurface(cairoSurf, 0, 0); cairoContext.Paint(); cairoSurf.Dispose(); } } cairoContext.Dispose(); //return true; }
public override void EndUpdate() { Interlocked.Decrement(ref lock_count); if (lock_count == 0) { surface.MarkDirty(); } }
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(); }
// 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); } } }
protected override bool OnDrawn(Cairo.Context cr) { int width, height; if (this.Log().IsEnabled(LogLevel.Trace)) { this.Log().Trace($"Render {renderCount++}"); } if (_dpi == null) { UpdateDpi(); } width = (int)AllocatedWidth; height = (int)AllocatedHeight; var scaledWidth = (int)(width * _dpi.Value); var scaledHeight = (int)(height * _dpi.Value); var info = new SKImageInfo(scaledWidth, scaledHeight, SKImageInfo.PlatformColorType, SKAlphaType.Premul); // reset the bitmap if the size has changed if (bitmap == null || info.Width != bitmap.Width || info.Height != bitmap.Height) { bitmap = new SKBitmap(scaledWidth, scaledHeight, SKColorType.Rgba8888, SKAlphaType.Premul); } using (var surface = SKSurface.Create(info, bitmap.GetPixels(out _))) { surface.Canvas.Clear(SKColors.White); surface.Canvas.Scale((float)_dpi); WUX.Window.Current.Compositor.Render(surface, info); using (var gtkSurface = new Cairo.ImageSurface( bitmap.GetPixels(out _), Cairo.Format.Argb32, bitmap.Width, bitmap.Height, bitmap.Width * 4)) { gtkSurface.MarkDirty(); cr.Scale(1 / _dpi.Value, 1 / _dpi.Value); cr.SetSourceSurface(gtkSurface, 0, 0); cr.Paint(); } } return(true); }
protected override bool OnExposeEvent(Gdk.EventExpose evnt) { var rect = Allocation; if (rect.Width > 0 && rect.Height > 0) { var area = evnt.Area; SKColorType ctype = SKColorType.Bgra8888; if (GlobalSettings.Settings.RunningPlatform() == GlobalSettings.Settings.Platform.Mac) { ctype = SKColorType.Rgba8888; } using (Cairo.Context cr = Gdk.CairoHelper.Create(base.GdkWindow)) { if (cr == null) { Console.WriteLine("Cairo Context is null"); } using (var bitmap = new SKBitmap(rect.Width, rect.Height, ctype, SKAlphaType.Premul)) { if (bitmap == null) { Console.WriteLine("Bitmap is null"); } IntPtr len; using (var skSurface = SKSurface.Create(bitmap.Info.Width, bitmap.Info.Height, ctype, SKAlphaType.Premul, bitmap.GetPixels(out len), bitmap.Info.RowBytes)) { if (skSurface == null) { Console.WriteLine("skSurface is null"); } if (fsurface != null) { fsurface.UpdateSurface(skSurface); } skSurface.Canvas.Flush(); using (Cairo.Surface surface = new Cairo.ImageSurface(bitmap.GetPixels(out len), Cairo.Format.Argb32, bitmap.Width, bitmap.Height, bitmap.Width * 4)) { surface.MarkDirty(); cr.SetSourceSurface(surface, 0, 0); cr.Paint(); } } } } } return(true); }
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(); }
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(); }
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(); }
protected override bool OnDrawn(Cairo.Context cr) { const int width = 1200; const int height = 800; using (var bitmap = new SKBitmap(width, height, SKColorType.Rgb888x, SKAlphaType.Premul)) { IntPtr len; using (var skSurface = SKSurface.Create(bitmap.Info.Width, bitmap.Info.Height, SKColorType.Rgb888x, SKAlphaType.Premul, bitmap.GetPixels(out len), bitmap.Info.RowBytes)) { var canvas = skSurface.Canvas; canvas.Clear(SKColors.White); using (var paint = new SKPaint()) { paint.TextSize = 80; canvas.DrawText("Good Luck Dale! :-)", new SKPoint() { X = 100, Y = 100 }, paint); } Cairo.Surface surface = new Cairo.ImageSurface( bitmap.GetPixels(out len), Cairo.Format.Argb32, bitmap.Width, bitmap.Height, bitmap.Width * 4); surface.MarkDirty(); cr.SetSourceSurface(surface, 0, 0); cr.Paint(); } } return(true); }
protected override bool OnDrawn(Cairo.Context cr) { const int width = 100; const int height = 100; using (var bitmap = new SKBitmap(width, height, SKColorType.N_32, SKAlphaType.Premul)) { IntPtr len; using (var skSurface = SKSurface.Create(bitmap.Info.Width, bitmap.Info.Height, SKColorType.N_32, SKAlphaType.Premul, bitmap.GetPixels(out len), bitmap.Info.RowBytes)) { var canvas = skSurface.Canvas; canvas.Clear(SKColors.White); using (var paint = new SKPaint()) { paint.StrokeWidth = 4; paint.Color = new SKColor(0x2c, 0x3e, 0x50); var rect = new SKRect(10, 10, 50, 50); canvas.DrawRect(rect, paint); } Cairo.Surface surface = new Cairo.ImageSurface( bitmap.GetPixels(out len), Cairo.Format.Argb32, bitmap.Width, bitmap.Height, bitmap.Width * 4); surface.MarkDirty(); cr.SetSourceSurface(surface, 0, 0); cr.Paint(); } } return(true); }
protected override bool OnDrawn(Cairo.Context cr) { int width, height; Console.WriteLine($"Render {renderCount++}"); width = (int)AllocatedWidth; height = (int)AllocatedHeight; var info = new SKImageInfo(width, height, SKImageInfo.PlatformColorType, SKAlphaType.Premul); // reset the bitmap if the size has changed if (bitmap == null || info.Width != bitmap.Width || info.Height != bitmap.Height) { bitmap = new SKBitmap(width, height, SKColorType.Rgba8888, SKAlphaType.Premul); } using (var surface = SKSurface.Create(info, bitmap.GetPixels(out var len))) { surface.Canvas.Clear(SKColors.White); WUX.Window.Current.Compositor.Render(surface, info); using (var gtkSurface = new Cairo.ImageSurface( bitmap.GetPixels(out _), Cairo.Format.Argb32, bitmap.Width, bitmap.Height, bitmap.Width * 4)) { gtkSurface.MarkDirty(); cr.SetSourceSurface(gtkSurface, 0, 0); cr.Paint(); } } return(true); }
/// <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(); }
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(); }
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(); }
void OnExpose(object sender, ExposeEventArgs args) { DrawingArea area = (DrawingArea)sender; Cairo.Context cr = Gdk.CairoHelper.Create(area.GdkWindow); int width = area.Allocation.Width; int height = area.Allocation.Height; AxisAlignedBox3d bounds3 = Stack.Bounds; AxisAlignedBox2d bounds = (bounds3 == AxisAlignedBox3d.Empty) ? new AxisAlignedBox2d(0, 0, 500, 500) : new AxisAlignedBox2d(bounds3.Min.x, bounds3.Min.y, bounds3.Max.x, bounds3.Max.y); double sx = (double)width / bounds.Width; double sy = (double)height / bounds.Height; float scale = (float)Math.Min(sx, sy); // we apply this translate after scaling to pixel coords Vector2f pixC = Zoom * scale * (Vector2f)bounds.Center; Vector2f translate = new Vector2f(width / 2, height / 2) - pixC; using (var bitmap = new SKBitmap(width, height, SkiaUtil.ColorType(), SKAlphaType.Premul)) { IntPtr len; using (var skSurface = SKSurface.Create(bitmap.Info.Width, bitmap.Info.Height, SkiaUtil.ColorType(), SKAlphaType.Premul, bitmap.GetPixels(out len), bitmap.Info.RowBytes)) { var canvas = skSurface.Canvas; canvas.Clear(SkiaUtil.Color(240, 240, 240, 255)); Func <Vector2d, Vector2f> xformF = (pOrig) => { Vector2f pNew = (Vector2f)pOrig; pNew -= (Vector2f)bounds.Center; pNew = Zoom * scale * pNew; pNew += (Vector2f)pixC; pNew += translate + Zoom * Translate; pNew.y = canvas.LocalClipBounds.Height - pNew.y; return(pNew); }; Func <Vector2d, SKPoint> mapToSkiaF = (pOrig) => { Vector2f p = xformF(pOrig); return(new SKPoint(p.x, p.y)); }; using (var paint = new SKPaint()) { SKBitmap sliceImg = get_slice_image(currentLayer); float w = sliceImg.Width / CurrentDPIMM, h = sliceImg.Height / CurrentDPIMM; w *= Zoom * scale; h *= Zoom * scale; SKPoint sliceCenter = mapToSkiaF(Vector2d.Zero); SKRect drawRect = new SKRect( sliceCenter.X - w / 2, sliceCenter.Y - h / 2, sliceCenter.X + w / 2, sliceCenter.Y + h / 2); canvas.DrawBitmap(sliceImg, drawRect, paint); paint.IsAntialias = true; paint.Style = SKPaintStyle.Stroke; PlanarSlice slice = Stack.Slices[currentLayer]; paint.Color = SkiaUtil.Color(255, 0, 0, 255);; paint.StrokeWidth = 2; foreach (GeneralPolygon2d poly in slice.Solids) { SKPath path = SkiaUtil.ToSKPath(poly, mapToSkiaF); canvas.DrawPath(path, paint); } } Cairo.Surface surface = new Cairo.ImageSurface( bitmap.GetPixels(out len), Cairo.Format.Argb32, bitmap.Width, bitmap.Height, bitmap.Width * 4); surface.MarkDirty(); cr.SetSourceSurface(surface, 0, 0); cr.Paint(); } } //return true; }