public override Surface RenderThumbnail(int maxEdgeLength) { Size thumbSize = Utility.ComputeThumbnailSize(this.Size, maxEdgeLength); Surface thumb = new Surface(thumbSize); thumb.SuperSamplingFitSurface(this.surface); Surface thumb2 = new Surface(thumbSize); thumb2.ClearWithCheckboardPattern(); UserBlendOps.NormalBlendOp nbop = new UserBlendOps.NormalBlendOp(); nbop.Apply(thumb2, thumb); thumb.Dispose(); thumb = null; return thumb2; }
protected void RenderCompositionTo(Surface dst, bool highQuality, bool forceUpToDate) { if (forceUpToDate) { UpdateComposition(false); } if (dst.Width == this.compositionSurface.Width && dst.Height == this.compositionSurface.Height) { dst.ClearWithCheckboardPattern(); new UserBlendOps.NormalBlendOp().Apply(dst, this.compositionSurface); } else if (highQuality) { Surface thumb = new Surface(dst.Size); thumb.SuperSamplingFitSurface(this.compositionSurface); dst.ClearWithCheckboardPattern(); new UserBlendOps.NormalBlendOp().Apply(dst, thumb); thumb.Dispose(); } else { this.surfaceBox.RenderTo(dst); } }
private void DrawGradient(Graphics g) { g.PixelOffsetMode = PixelOffsetMode.Half; Rectangle gradientRect; float gradientAngle; switch (this.orientation) { case Orientation.Horizontal: gradientAngle = 180.0f; break; case Orientation.Vertical: gradientAngle = 90.0f; break; default: throw new InvalidEnumArgumentException(); } // draw gradient gradientRect = ClientRectangle; switch (this.orientation) { case Orientation.Horizontal: gradientRect.Inflate(-triangleHalfLength, -triangleSize + 3); break; case Orientation.Vertical: gradientRect.Inflate(-triangleSize + 3, -triangleHalfLength); break; default: throw new InvalidEnumArgumentException(); } if (this.customGradient != null && gradientRect.Width > 1 && gradientRect.Height > 1) { Surface gradientSurface = new Surface(gradientRect.Size); using (RenderArgs ra = new RenderArgs(gradientSurface)) { Utility.DrawColorRectangle(ra.Graphics, ra.Bounds, Color.Transparent, false); if (Orientation == Orientation.Horizontal) { for (int x = 0; x < gradientSurface.Width; ++x) { // TODO: refactor, double buffer, save this computation in a bitmap somewhere double index = (double)(x * (this.customGradient.Length - 1)) / (double)(gradientSurface.Width - 1); int indexL = (int)Math.Floor(index); double t = 1.0 - (index - indexL); int indexR = (int)Math.Min(this.customGradient.Length - 1, Math.Ceiling(index)); Color colorL = this.customGradient[indexL]; Color colorR = this.customGradient[indexR]; double a1 = colorL.A / 255.0; double r1 = colorL.R / 255.0; double g1 = colorL.G / 255.0; double b1 = colorL.B / 255.0; double a2 = colorR.A / 255.0; double r2 = colorR.R / 255.0; double g2 = colorR.G / 255.0; double b2 = colorR.B / 255.0; double at = (t * a1) + ((1.0 - t) * a2); double rt; double gt; double bt; if (at == 0) { rt = 0; gt = 0; bt = 0; } else { rt = ((t * a1 * r1) + ((1.0 - t) * a2 * r2)) / at; gt = ((t * a1 * g1) + ((1.0 - t) * a2 * g2)) / at; bt = ((t * a1 * b1) + ((1.0 - t) * a2 * b2)) / at; } int ap = Utility.Clamp((int)Math.Round(at * 255.0), 0, 255); int rp = Utility.Clamp((int)Math.Round(rt * 255.0), 0, 255); int gp = Utility.Clamp((int)Math.Round(gt * 255.0), 0, 255); int bp = Utility.Clamp((int)Math.Round(bt * 255.0), 0, 255); for (int y = 0; y < gradientSurface.Height; ++y) { ColorBgra src = gradientSurface[x, y]; // we are assuming that src.A = 255 int rd = ((rp * ap) + (src.R * (255 - ap))) / 255; int gd = ((gp * ap) + (src.G * (255 - ap))) / 255; int bd = ((bp * ap) + (src.B * (255 - ap))) / 255; // TODO: proper alpha blending! gradientSurface[x, y] = ColorBgra.FromBgra((byte)bd, (byte)gd, (byte)rd, 255); } } g.DrawImage(ra.Bitmap, gradientRect, ra.Bounds, GraphicsUnit.Pixel); } else if (Orientation == Orientation.Vertical) { // TODO } else { throw new InvalidEnumArgumentException(); } } gradientSurface.Dispose(); } else { using (LinearGradientBrush lgb = new LinearGradientBrush(this.ClientRectangle, maxColor, minColor, gradientAngle, false)) { g.FillRectangle(lgb, gradientRect); } } // fill background using (PdnRegion nonGradientRegion = new PdnRegion()) { nonGradientRegion.MakeInfinite(); nonGradientRegion.Exclude(gradientRect); using (SolidBrush sb = new SolidBrush(this.BackColor)) { g.FillRegion(sb, nonGradientRegion.GetRegionReadOnly()); } } // draw value triangles for (int i = 0; i < this.vals.Length; i++) { int pos = ValueToPosition(vals[i]); Brush brush; Pen pen; if (i == highlight) { brush = Brushes.Blue; pen = (Pen)Pens.White.Clone(); } else { brush = Brushes.Black; pen = (Pen)Pens.Gray.Clone(); } g.SmoothingMode = SmoothingMode.AntiAlias; Point a1; Point b1; Point c1; Point a2; Point b2; Point c2; switch (this.orientation) { case Orientation.Horizontal: a1 = new Point(pos - triangleHalfLength, 0); b1 = new Point(pos, triangleSize - 1); c1 = new Point(pos + triangleHalfLength, 0); a2 = new Point(a1.X, Height - 1 - a1.Y); b2 = new Point(b1.X, Height - 1 - b1.Y); c2 = new Point(c1.X, Height - 1 - c1.Y); break; case Orientation.Vertical: a1 = new Point(0, pos - triangleHalfLength); b1 = new Point(triangleSize - 1, pos); c1 = new Point(0, pos + triangleHalfLength); a2 = new Point(Width - 1 - a1.X, a1.Y); b2 = new Point(Width - 1 - b1.X, b1.Y); c2 = new Point(Width - 1 - c1.X, c1.Y); break; default: throw new InvalidEnumArgumentException(); } if (this.drawNearNub) { g.FillPolygon(brush, new Point[] { a1, b1, c1, a1 }); } if (this.drawFarNub) { g.FillPolygon(brush, new Point[] { a2, b2, c2, a2 }); } if (pen != null) { if (this.drawNearNub) { g.DrawPolygon(pen, new Point[] { a1, b1, c1, a1 }); } if (this.drawFarNub) { g.DrawPolygon(pen, new Point[] { a2, b2, c2, a2 }); } pen.Dispose(); } } }
private void ResizeDocument() { this.pleaseStop = false; // This is only sort of a hack: we must try and allocate enough for 2 extra layer-sized buffers // Then we free them immediately. This is just so that if we don't have enough memory that we'll // fail sooner rather than later. Surface s1 = new Surface(this.newSize); Surface s2 = new Surface(this.newSize); try { foreach (Layer layer in src.Layers) { if (this.pleaseStop) { this.returnVal = false; return; } if (layer is BitmapLayer) { Layer newLayer = ResizeLayer((BitmapLayer)layer, this.newSize.Width, this.newSize.Height, this.algorithm, this.tilesPerLayer, new Procedure(RenderedRectHandler), ref this.pleaseStop); if (newLayer == null) { this.returnVal = false; return; } dst.Layers.Add(newLayer); } else { throw new InvalidOperationException("Resize does not support Layers that are not BitmapLayers"); } } } finally { s1.Dispose(); s2.Dispose(); } this.returnVal = true; }
private static BitmapLayer ResizeLayer(BitmapLayer layer, int width, int height, ResamplingAlgorithm algorithm, int tileCount, Procedure progressCallback, ref bool pleaseStopMonitor) { Surface surface = new Surface(width, height); surface.Clear(ColorBgra.FromBgra(255, 255, 255, 0)); PaintDotNet.Threading.ThreadPool threadPool = new PaintDotNet.Threading.ThreadPool(); int rectCount; if (tileCount == 0) { rectCount = Processor.LogicalCpuCount; } else { rectCount = tileCount; } Rectangle[] rects = new Rectangle[rectCount]; Utility.SplitRectangle(surface.Bounds, rects); FitSurfaceContext fsc = new FitSurfaceContext(surface, layer.Surface, rects, algorithm); if (progressCallback != null) { fsc.RenderedRect += progressCallback; } WaitCallback callback = new WaitCallback(fsc.FitSurface); for (int i = 0; i < rects.Length; ++i) { if (pleaseStopMonitor) { break; } else { threadPool.QueueUserWorkItem(callback, BoxedConstants.GetInt32(i)); } } threadPool.Drain(); threadPool.DrainExceptions(); if (pleaseStopMonitor) { surface.Dispose(); surface = null; } BitmapLayer newLayer; if (surface == null) { newLayer = null; } else { newLayer = new BitmapLayer(surface, true); newLayer.LoadProperties(layer.SaveProperties()); } if (progressCallback != null) { fsc.RenderedRect -= progressCallback; } return newLayer; }
private Surface GetDoubleBuffer(Size size) { Surface localDBSurface = null; Size oldSize = new Size(0, 0); // If we already have a double buffer surface reference, but if that surface // is already disposed then don't worry about it. if (this.doubleBufferSurface != null && this.doubleBufferSurface.IsDisposed) { oldSize = this.doubleBufferSurface.Size; this.doubleBufferSurface = null; } // If we already have a double buffer surface reference, but if that surface // is too small, then nuke it. if (this.doubleBufferSurface != null && (this.doubleBufferSurface.Width < size.Width || this.doubleBufferSurface.Height < size.Height)) { oldSize = this.doubleBufferSurface.Size; this.doubleBufferSurface.Dispose(); this.doubleBufferSurface = null; doubleBufferSurfaceWeakRef = null; } // If we don't have a double buffer, then we'd better get one. if (this.doubleBufferSurface != null) { // Got one! localDBSurface = this.doubleBufferSurface; } else if (doubleBufferSurfaceWeakRef != null) { // First, try to get the one that's already shared amongst all SurfaceBox instances. localDBSurface = doubleBufferSurfaceWeakRef.Target; // If it's disposed, then forget about it. if (localDBSurface != null && localDBSurface.IsDisposed) { oldSize = localDBSurface.Size; localDBSurface = null; doubleBufferSurfaceWeakRef = null; } } // Make sure the surface is big enough. if (localDBSurface != null && (localDBSurface.Width < size.Width || localDBSurface.Height < size.Height)) { oldSize = localDBSurface.Size; localDBSurface.Dispose(); localDBSurface = null; doubleBufferSurfaceWeakRef = null; } // So, do we have a surface? If not then we'd better make one. if (localDBSurface == null) { Size newSize = new Size(Math.Max(size.Width, oldSize.Width), Math.Max(size.Height, oldSize.Height)); localDBSurface = new Surface(newSize.Width, newSize.Height); doubleBufferSurfaceWeakRef = new WeakReference <Surface>(localDBSurface); } this.doubleBufferSurface = localDBSurface; Surface window = localDBSurface.CreateWindow(0, 0, size.Width, size.Height); return(window); }
private void DrawGradient(Graphics g) { g.PixelOffsetMode = PixelOffsetMode.Half; Rectangle gradientRect; float gradientAngle; switch (this.orientation) { case Orientation.Horizontal: gradientAngle = 180.0f; break; case Orientation.Vertical: gradientAngle = 90.0f; break; default: throw new InvalidEnumArgumentException(); } // draw gradient gradientRect = ClientRectangle; switch (this.orientation) { case Orientation.Horizontal: gradientRect.Inflate(-triangleHalfLength, -triangleSize + 3); break; case Orientation.Vertical: gradientRect.Inflate(-triangleSize + 3, -triangleHalfLength); break; default: throw new InvalidEnumArgumentException(); } if (this.customGradient != null && gradientRect.Width > 1 && gradientRect.Height > 1) { Surface gradientSurface = new Surface(gradientRect.Width, gradientRect.Height); using (RenderArgs ra = new RenderArgs(gradientSurface)) { Utility.DrawColorRectangle(ra.Graphics, ra.Bounds, Color.Transparent, false); if (Orientation == Orientation.Horizontal) { for (int x = 0; x < gradientSurface.Width; ++x) { // TODO: refactor, double buffer, save this computation in a bitmap somewhere double index = (double)(x * (this.customGradient.Length - 1)) / (double)(gradientSurface.Width - 1); int indexL = (int)Math.Floor(index); double t = 1.0 - (index - indexL); int indexR = (int)Math.Min(this.customGradient.Length - 1, Math.Ceiling(index)); Color colorL = this.customGradient[indexL]; Color colorR = this.customGradient[indexR]; double a1 = colorL.A / 255.0; double r1 = colorL.R / 255.0; double g1 = colorL.G / 255.0; double b1 = colorL.B / 255.0; double a2 = colorR.A / 255.0; double r2 = colorR.R / 255.0; double g2 = colorR.G / 255.0; double b2 = colorR.B / 255.0; double at = (t * a1) + ((1.0 - t) * a2); double rt; double gt; double bt; if (at == 0) { rt = 0; gt = 0; bt = 0; } else { rt = ((t * a1 * r1) + ((1.0 - t) * a2 * r2)) / at; gt = ((t * a1 * g1) + ((1.0 - t) * a2 * g2)) / at; bt = ((t * a1 * b1) + ((1.0 - t) * a2 * b2)) / at; } int ap = Utility.Clamp((int)Math.Round(at * 255.0), 0, 255); int rp = Utility.Clamp((int)Math.Round(rt * 255.0), 0, 255); int gp = Utility.Clamp((int)Math.Round(gt * 255.0), 0, 255); int bp = Utility.Clamp((int)Math.Round(bt * 255.0), 0, 255); for (int y = 0; y < gradientSurface.Height; ++y) { ColorBgra src = gradientSurface[x, y]; // we are assuming that src.A = 255 int rd = ((rp * ap) + (src.R * (255 - ap))) / 255; int gd = ((gp * ap) + (src.G * (255 - ap))) / 255; int bd = ((bp * ap) + (src.B * (255 - ap))) / 255; // TODO: proper alpha blending! gradientSurface[x, y] = ColorBgra.FromBgra((byte)bd, (byte)gd, (byte)rd, 255); } } g.DrawImage(ra.Bitmap, gradientRect, ra.Bounds, GraphicsUnit.Pixel); } else if (Orientation == Orientation.Vertical) { // TODO } else { throw new InvalidEnumArgumentException(); } } gradientSurface.Dispose(); } else { using (LinearGradientBrush lgb = new LinearGradientBrush(this.ClientRectangle, maxColor, minColor, gradientAngle, false)) { g.FillRectangle(lgb, gradientRect); } } // fill background using (Region nonGradientRegion = new Region()) { nonGradientRegion.MakeInfinite(); nonGradientRegion.Exclude(gradientRect); using (SolidBrush sb = new SolidBrush(this.BackColor)) { g.FillRegion(sb, nonGradientRegion); } } // draw value triangles for (int i = 0; i < this.vals.Length; i++) { int pos = ValueToPosition(vals[i]); Brush brush; Pen pen; if (i == highlight) { brush = Brushes.Blue; pen = (Pen)Pens.White.Clone(); } else { brush = Brushes.Black; pen = (Pen)Pens.Gray.Clone(); } g.SmoothingMode = SmoothingMode.AntiAlias; Point a1; Point b1; Point c1; Point a2; Point b2; Point c2; switch (this.orientation) { case Orientation.Horizontal: a1 = new Point(pos - triangleHalfLength, 0); b1 = new Point(pos, triangleSize - 1); c1 = new Point(pos + triangleHalfLength, 0); a2 = new Point(a1.X, Height - 1 - a1.Y); b2 = new Point(b1.X, Height - 1 - b1.Y); c2 = new Point(c1.X, Height - 1 - c1.Y); break; case Orientation.Vertical: a1 = new Point(0, pos - triangleHalfLength); b1 = new Point(triangleSize - 1, pos); c1 = new Point(0, pos + triangleHalfLength); a2 = new Point(Width - 1 - a1.X, a1.Y); b2 = new Point(Width - 1 - b1.X, b1.Y); c2 = new Point(Width - 1 - c1.X, c1.Y); break; default: throw new InvalidEnumArgumentException(); } if (this.drawNearNub) { g.FillPolygon(brush, new Point[] { a1, b1, c1, a1 }); } if (this.drawFarNub) { g.FillPolygon(brush, new Point[] { a2, b2, c2, a2 }); } if (pen != null) { if (this.drawNearNub) { g.DrawPolygon(pen, new Point[] { a1, b1, c1, a1 }); } if (this.drawFarNub) { g.DrawPolygon(pen, new Point[] { a2, b2, c2, a2 }); } pen.Dispose(); } } }
protected virtual void OnPreRenderComplete(RenderArgs dstArgs, RenderArgs srcArgs) { Rectangle[] rois; Surface surfaceCopy; RenderArgs args; RenderArgs currentSourceArgs; RenderArgs currentDestinationArgs; Rectangle boundingTile; if (FullImageSelected(srcArgs.Bounds)) { boundingTile = dstArgs.Bounds; } else { boundingTile = this.EnvironmentParameters.GetSelection(dstArgs.Bounds).GetBoundsInt(); boundingTile.Inflate(base.ApronSize, base.ApronSize); boundingTile.Intersect(dstArgs.Bounds); } rois = base.SliceRectangles(new Rectangle[] { boundingTile }); surfaceCopy = new Surface(dstArgs.Width, dstArgs.Height, SurfaceCreationFlags.DoNotZeroFillHint); //dstArgs.Surface.Clone(); args = new RenderArgs(surfaceCopy); currentSourceArgs = srcArgs; currentDestinationArgs = args; this.pass = 1; OnBeginPass(this.pass, currentDestinationArgs, currentSourceArgs); OnRenderRegion(rois, currentDestinationArgs, currentSourceArgs); if (Passes == 1) { CopyRois(this.EnvironmentParameters.GetSelection(dstArgs.Bounds).GetRegionScansInt(), dstArgs.Surface, surfaceCopy); surfaceCopy.Dispose(); } else { if (base.tmr != null) { base.tmr = new System.Diagnostics.Stopwatch(); base.tmr.Start(); } this.pass = 2; if (FullImageSelected(srcArgs.Bounds)) { currentSourceArgs = args; currentDestinationArgs = dstArgs; OnBeginPass(this.pass, currentDestinationArgs, currentSourceArgs); OnRenderRegion(rois, currentDestinationArgs, currentSourceArgs); surfaceCopy.Dispose(); } else { Surface surfaceCopy2; RenderArgs args2; surfaceCopy2 = new Surface(dstArgs.Width, dstArgs.Height, SurfaceCreationFlags.DoNotZeroFillHint); args2 = new RenderArgs(surfaceCopy2); currentSourceArgs = args; currentDestinationArgs = args2; OnBeginPass(this.pass, currentDestinationArgs, currentSourceArgs); OnRenderRegion(rois, currentDestinationArgs, currentSourceArgs); surfaceCopy.Dispose(); CopyRois(this.EnvironmentParameters.GetSelection(dstArgs.Bounds).GetRegionScansInt(), dstArgs.Surface, surfaceCopy2); surfaceCopy2.Dispose(); } } }