/// <summary> /// Draws an area of the SurfaceBox. /// </summary> /// <param name="ra">The rendering surface object to draw to.</param> /// <param name="offset">The virtual offset of ra, in client (destination) coordinates.</param> /// <remarks> /// If drawing to ra.Surface or ra.Bitmap, copy the roi of the source surface to (0,0) of ra.Surface or ra.Bitmap /// If drawing to ra.Graphics, copy the roi of the surface to (roi.X, roi.Y) of ra.Graphics /// </remarks> private unsafe void DrawArea(RenderArgs ra, Point offset) { if (surface == null) { return; } if (renderContext == null || (renderContext.windows != null && renderContext.windows.Length != Processor.LogicalCpuCount)) { renderContext = new RenderContext(); renderContext.owner = this; renderContext.waitCallback = new WaitCallback(renderContext.RenderThreadMethod); renderContext.windows = new Surface[Processor.LogicalCpuCount]; renderContext.offsets = new Point[Processor.LogicalCpuCount]; renderContext.rects = new Rectangle[Processor.LogicalCpuCount]; } Utility.SplitRectangle(ra.Bounds, renderContext.rects); for (int i = 0; i < renderContext.rects.Length; ++i) { if (renderContext.rects[i].Width > 0 && renderContext.rects[i].Height > 0) { renderContext.offsets[i] = new Point(renderContext.rects[i].X + offset.X, renderContext.rects[i].Y + offset.Y); renderContext.windows[i] = ra.Surface.CreateWindow(renderContext.rects[i]); } else { renderContext.windows[i] = null; } } for (int i = 0; i < renderContext.windows.Length; ++i) { if (renderContext.windows[i] != null) { this.threadPool.QueueUserWorkItem(renderContext.waitCallback, BoxedConstants.GetInt32(i)); } } this.threadPool.Drain(); }
public unsafe void Draw(Surface dst, Matrix transform, ResamplingAlgorithm sampling) { if (this.disposed) { throw new ObjectDisposedException("MaskedSurface"); } if (this.surface == null || !transform.IsInvertible) { return; } PdnRegion theRegion; Rectangle regionBounds; if (this.path == null) { theRegion = this.region.Clone(); regionBounds = this.region.GetBoundsInt(); theRegion.Transform(transform); } else { using (PdnGraphicsPath mPath = this.shadowPath.Clone()) { regionBounds = Rectangle.Truncate(mPath.GetBounds()); mPath.Transform(transform); theRegion = new PdnRegion(mPath); } } DrawContext dc = new DrawContext(); dc.boundsX = regionBounds.X; dc.boundsY = regionBounds.Y; Matrix inverse = transform.Clone(); inverse.Invert(); dc.inverses = new Matrix[Processor.LogicalCpuCount]; for (int i = 0; i < dc.inverses.Length; ++i) { dc.inverses[i] = inverse.Clone(); } // change in source-[X|Y] w.r.t. destination-[X|Y] PointF[] pts = new PointF[] { new PointF(1, 0), new PointF(0, 1) }; inverse.TransformVectors(pts); inverse.Dispose(); inverse = null; dc.dsxddx = pts[0].X; if (Math.Abs(dc.dsxddx) > fp_MaxValue) { dc.dsxddx = 0.0f; } dc.dsyddx = pts[0].Y; if (Math.Abs(dc.dsyddx) > fp_MaxValue) { dc.dsyddx = 0.0f; } dc.dsxddy = pts[1].X; if (Math.Abs(dc.dsxddy) > fp_MaxValue) { dc.dsxddy = 0.0f; } dc.dsyddy = pts[1].Y; if (Math.Abs(dc.dsyddy) > fp_MaxValue) { dc.dsyddy = 0.0f; } dc.fp_dsxddx = (int)(dc.dsxddx * fp_MultFactor); dc.fp_dsyddx = (int)(dc.dsyddx * fp_MultFactor); dc.fp_dsxddy = (int)(dc.dsxddy * fp_MultFactor); dc.fp_dsyddy = (int)(dc.dsyddy * fp_MultFactor); dc.dst = dst; dc.src = this.surface; Rectangle[] scans = theRegion.GetRegionScansReadOnlyInt(); if (scans.Length == 1) { dc.dstScans = new Rectangle[Processor.LogicalCpuCount]; Utility.SplitRectangle(scans[0], dc.dstScans); } else { dc.dstScans = scans; } WaitCallback wc; switch (sampling) { case ResamplingAlgorithm.NearestNeighbor: wc = new WaitCallback(dc.DrawScansNearestNeighbor); break; case ResamplingAlgorithm.Bilinear: wc = new WaitCallback(dc.DrawScansBilinear); break; default: throw new System.ComponentModel.InvalidEnumArgumentException(); } for (int i = 0; i < Processor.LogicalCpuCount; ++i) { if (i == Processor.LogicalCpuCount - 1) { // Don't queue the last work item into a separate thread wc(BoxedConstants.GetInt32(i)); } else { threadPool.QueueUserWorkItem(wc, BoxedConstants.GetInt32(i)); } } threadPool.Drain(); for (int i = 0; i < Processor.LogicalCpuCount; ++i) { dc.inverses[i].Dispose(); dc.inverses[i] = null; } dc.src = null; theRegion.Dispose(); theRegion = null; }