public bool IsVisible(Point pt) { using (PdnGraphicsPath path = CreatePath()) { return(path.IsVisible(pt)); } }
public PdnRegion CreateRegionRaw() { using (PdnGraphicsPath path = CreatePath()) { return(new PdnRegion(path)); } }
// only works if base is empty public void SetContinuation(PdnGraphicsPath path, CombineMode combineMode, bool takeOwnership) { lock (this.syncRoot) { if (!this.data.basePath.IsEmpty) { throw new InvalidOperationException("base path must be empty to use this overload of SetContinuation"); } OnChanging(); CommitInterimTransform(); ResetCumulativeTransform(); this.data.continuationCombineMode = combineMode; if (takeOwnership) { this.data.continuation.Dispose(); this.data.continuation = path; } else { this.data.continuation.Reset(); this.data.continuation.AddPath(path, false); } OnChanged(); } }
protected override void Dispose(bool disposing) { if (disposing) { if (this.components != null) { this.components.Dispose(); this.components = null; } if (this.selectionTimer != null) { this.selectionTimer.Dispose(); this.selectionTimer = null; } if (this.zoomInSelectedPath != null) { this.zoomInSelectedPath.Dispose(); this.zoomInSelectedPath = null; } } base.Dispose(disposing); }
public static PdnGraphicsPath FromRegion(PdnRegion region) { Rectangle bounds = region.GetBoundsInt(); Rectangle[] scans = region.GetRegionScansReadOnlyInt(); BitVector2D stencil = new BitVector2D(bounds.Width, bounds.Height); for (int i = 0; i < scans.Length; ++i) { Rectangle rect = scans[i]; rect.X -= bounds.X; rect.Y -= bounds.Y; stencil.SetUnchecked(rect, true); } PdnGraphicsPath path = PathFromStencil(stencil, new Rectangle(0, 0, stencil.Width, stencil.Height)); using (Matrix matrix = new Matrix()) { matrix.Reset(); matrix.Translate(bounds.X, bounds.Y); path.Transform(matrix); } return(path); }
public MaskedSurface(Surface source, PdnGraphicsPath path) { RectangleF boundsF = path.GetBounds(); Rectangle bounds = Utility.RoundRectangle(boundsF); Rectangle boundsClipped = Rectangle.Intersect(bounds, source.Bounds); Rectangle boundsRead; if (bounds != boundsClipped) { PdnRegion region = new PdnRegion(path); region.Intersect(source.Bounds); SetPathField(PdnGraphicsPath.FromRegion(region)); this.region = region; boundsRead = region.GetBoundsInt(); } else { SetPathField(path.Clone()); this.region = new PdnRegion(this.path); boundsRead = boundsClipped; } if (boundsRead.Width > 0 && boundsRead.Height > 0) { this.surface = new Surface(boundsRead.Size); this.surface.CopySurface(source, boundsRead); } else { this.surface = null; } }
private void Dispose(bool disposing) { if (disposing) { if (this.surface != null) { this.surface.Dispose(); this.surface = null; } if (this.region != null) { this.region.Dispose(); this.region = null; } if (this.path != null) { this.path.Dispose(); this.path = null; } if (this.shadowPath != null) { this.shadowPath.Dispose(); this.shadowPath = null; } } this.disposed = true; }
private void Dispose(bool disposing) { if (disposing) { if (this.SurfaceReadOnly != null) { this.SurfaceReadOnly.Dispose(); this.SurfaceReadOnly = null; } if (this.region != null) { this.region.Dispose(); this.region = null; } if (this.path != null) { this.path.Dispose(); this.path = null; } if (this.shadowPath != null) { this.shadowPath.Dispose(); this.shadowPath = null; } } this.IsDisposed = true; }
public PdnGraphicsPath Clone() { PdnGraphicsPath path = new PdnGraphicsPath((GraphicsPath)gdiPath.Clone()); path.tooComplex = this.tooComplex; return(path); }
public static PdnGraphicsPath Combine(PdnGraphicsPath subjectPath, CombineMode combineMode, PdnGraphicsPath clipPath) { switch (combineMode) { case CombineMode.Complement: return(Combine(clipPath, CombineMode.Exclude, subjectPath)); case CombineMode.Replace: return(clipPath.Clone()); case CombineMode.Xor: case CombineMode.Intersect: case CombineMode.Union: case CombineMode.Exclude: if (subjectPath.IsEmpty && clipPath.IsEmpty) { return(new PdnGraphicsPath()); // empty path } else if (subjectPath.IsEmpty) { switch (combineMode) { case CombineMode.Xor: case CombineMode.Union: return(clipPath.Clone()); case CombineMode.Intersect: case CombineMode.Exclude: return(new PdnGraphicsPath()); default: throw new InvalidEnumArgumentException(); } } else if (clipPath.IsEmpty) { switch (combineMode) { case CombineMode.Exclude: case CombineMode.Xor: case CombineMode.Union: return(subjectPath.Clone()); case CombineMode.Intersect: return(new PdnGraphicsPath()); default: throw new InvalidEnumArgumentException(); } } else { GraphicsPath resultPath = PdnGraphics.ClipPath(subjectPath, combineMode, clipPath); return(new PdnGraphicsPath(resultPath)); } default: throw new InvalidEnumArgumentException(); } }
public void Dispose(bool disposing) { if (disposing) { if (this.basePath != null) { this.basePath.Dispose(); this.basePath = null; } if (this.continuation != null) { this.continuation.Dispose(); this.continuation = null; } if (this.cumulativeTransform != null) { this.cumulativeTransform.Dispose(); this.cumulativeTransform = null; } if (this.interimTransform != null) { this.interimTransform.Dispose(); this.interimTransform = null; } } }
public bool IsVisible(Point pt) { using (PdnGraphicsPath path = CreatePath()) //PdnGraphicsPath path = GetPathReadOnly(); { return(path.IsVisible(pt)); } }
public PdnRegion CreateRegionRaw() { using (PdnGraphicsPath path = CreatePath()) //PdnGraphicsPath path = GetPathReadOnly(); { return(new PdnRegion(path)); } }
public RectangleF GetBoundsF(bool applyInterimTransformation) { using (PdnGraphicsPath path = this.CreatePath(applyInterimTransformation)) { RectangleF bounds2 = path.GetBounds2(); return(bounds2); } }
public void OnDeserialization(object sender) { threadPool = new PaintDotNet.Threading.ThreadPool(); if (this.path != null) { this.shadowPath = this.path.Clone(); } }
private PdnGraphicsPath GetPath() { if (this.path == null) { SetPathField(PdnGraphicsPath.FromRegion(this.region)); } return(this.shadowPath); }
public Data() { this.basePath = new PdnGraphicsPath(); this.continuation = new PdnGraphicsPath(); this.continuationCombineMode = CombineMode.Xor; this.cumulativeTransform = new Matrix(); this.cumulativeTransform.Reset(); this.interimTransform = new Matrix(); this.interimTransform.Reset(); }
public Data() { BasePath = new PdnGraphicsPath(); ContinuationPath = new PdnGraphicsPath(); ContinuationCombineMode = CombineMode.Xor; CumulativeTransform = new Matrix(); CumulativeTransform.Reset(); InterimTransform = new Matrix(); InterimTransform.Reset(); }
private PdnGraphicsPath GetPath() { if (this.path == null) { // TODO: FromRegion() is a VERY expensive call! PdnGraphicsPath newPath = PdnGraphicsPath.FromRegion(this.region); SetPathField(newPath); } return(this.shadowPath); }
public PdnGraphicsPath CreatePixelatedPath() { using (PdnGraphicsPath path = CreatePath()) { using (PdnRegion region = new PdnRegion(path)) { PdnGraphicsPath pixellatedPath = PdnGraphicsPath.FromRegion(region); return(pixellatedPath); } } }
private void DrawSelectionOutline(Graphics g, PdnGraphicsPath outline) { if (outline == null) { return; } if (outlinePen1 == null) { outlinePen1 = new Pen(Color.FromArgb(160, Color.Black), 1.0f); outlinePen1.Alignment = PenAlignment.Outset; outlinePen1.LineJoin = LineJoin.Bevel; outlinePen1.Width = -1; } if (outlinePen2 == null) { outlinePen2 = new Pen(Color.White, 1.0f); outlinePen2.Alignment = PenAlignment.Outset; outlinePen2.LineJoin = LineJoin.Bevel; outlinePen2.MiterLimit = 2; outlinePen2.Width = -1; outlinePen2.DashStyle = DashStyle.Dash; outlinePen2.DashPattern = new float[] { 4, 4 }; outlinePen2.Color = Color.White; outlinePen2.DashOffset = 4.0f; } PixelOffsetMode oldPOM = g.PixelOffsetMode; g.PixelOffsetMode = PixelOffsetMode.None; SmoothingMode oldSM = g.SmoothingMode; g.SmoothingMode = SmoothingMode.AntiAlias; outline.Draw(g, outlinePen1); float offset = (float)((double)dancingAntsT / OwnerList.ScaleFactor.Ratio); outlinePen2.DashOffset += offset; if (whiteOpacity != 0) { outlinePen2.Color = Color.FromArgb(whiteOpacity, Color.White); outline.Draw(g, outlinePen2); } outlinePen2.DashOffset -= offset; g.SmoothingMode = oldSM; g.PixelOffsetMode = oldPOM; }
public PdnGraphicsPath CreatePath(bool applyInterimTransform) { lock (this.syncRoot) { PdnGraphicsPath returnPath = PdnGraphicsPath.Combine(this.data.basePath, this.data.continuationCombineMode, this.data.continuation); if (applyInterimTransform) { returnPath.Transform(this.data.interimTransform); } return(returnPath); } }
public void CommitContinuation() { lock (this.syncRoot) { OnChanging(); this.data.continuation.CloseAllFigures(); PdnGraphicsPath newBasePath = CreatePath(); this.data.basePath.Dispose(); this.data.basePath = newBasePath; this.data.continuation.Reset(); this.data.continuationCombineMode = CombineMode.Xor; OnChanged(); } }
private void DrawSelectionTinting(Graphics g, PdnGraphicsPath outline) { if (outline == null) { return; } CompositingMode oldCM = g.CompositingMode; g.CompositingMode = CompositingMode.SourceOver; SmoothingMode oldSM = g.SmoothingMode; g.SmoothingMode = SmoothingMode.AntiAlias; PixelOffsetMode oldPOM = g.PixelOffsetMode; g.PixelOffsetMode = PixelOffsetMode.None; Region oldClipRegion = null; RectangleF outlineBounds = outline.GetBounds(); if (outlineBounds.Left < 0 || outlineBounds.Top < 0 || outlineBounds.Right >= this.SourceSize.Width || outlineBounds.Bottom >= this.SourceSize.Height) { oldClipRegion = g.Clip; Region newClipRegion = oldClipRegion.Clone(); newClipRegion.Intersect(new Rectangle(0, 0, this.SourceSize.Width, this.SourceSize.Height)); g.Clip = newClipRegion; newClipRegion.Dispose(); } g.FillPath(InteriorBrush, outline); if (oldClipRegion != null) { g.Clip = oldClipRegion; oldClipRegion.Dispose(); } g.PixelOffsetMode = oldPOM; g.SmoothingMode = oldSM; g.CompositingMode = oldCM; }
/// <summary> /// Constructs a MaskSurface by copying the given region-of-interest from an Image. /// </summary> /// <param name="source">The Surface to copy pixels from.</param> /// <param name="roi">Defines the Region from which to copy pixels from the Image.</param> public MaskedSurface(Surface source, PdnRegion roi) { PdnRegion roiClipped = (PdnRegion)roi.Clone(); roiClipped.Intersect(source.Bounds); Rectangle boundsClipped = roiClipped.GetBoundsInt(); this.surface = new Surface(boundsClipped.Size); this.surface.Clear(ColorBgra.FromUInt32(0x00ffffff)); Rectangle rect = boundsClipped; Point dstOffset = new Point(rect.X - boundsClipped.X, rect.Y - boundsClipped.Y); this.surface.CopySurface(source, dstOffset, rect); this.region = roiClipped; SetPathField(PdnGraphicsPath.FromRegion(this.region)); }
/// <summary> /// When we zoom in, we want to "stair-step" the selected path. /// </summary> /// <returns></returns> private PdnGraphicsPath GetZoomInPath() { lock (this.SyncRoot) { if (this.zoomInSelectedPath == null) { if (this.selectedPath == null) { this.zoomInSelectedPath = new PdnGraphicsPath(); } else { this.zoomInSelectedPath = this.selection.CreatePixelatedPath(); } } return(this.zoomInSelectedPath); } }
private void DrawSelection(Graphics gdiG, PdnGraphicsPath outline) { if (outline == null) { return; } float ratio = (float)OwnerList.ScaleFactor.Ratio; gdiG.ScaleTransform(ratio, ratio); if (EnableSelectionTinting) { PdnGraphicsPath outline2; if (invertedTinting) { outline2 = (PdnGraphicsPath)outline.Clone(); outline2.AddRectangle(new Rectangle(-1, -1, this.SourceSize.Width + 1, this.SourceSize.Height + 1)); outline2.CloseAllFigures(); } else { outline2 = outline; } DrawSelectionTinting(gdiG, outline2); if (invertedTinting) { outline2.Dispose(); } } if (EnableSelectionOutline) { DrawSelectionOutline(gdiG, outline); } gdiG.ScaleTransform(1 / ratio, 1 / ratio); }
public override void RenderToGraphics(Graphics g, Point offset) { double start = timer.GetTickCountDouble(); lock (SyncRoot) { PdnGraphicsPath path = GetAppropriateRenderPath(); if (path == null || path.IsEmpty) { this.render = false; // will be reset next time selection changes } else { g.TranslateTransform(-offset.X, -offset.Y); DrawSelection(g, path); } double end = timer.GetTickCountDouble(); this.renderTime += (end - start); } }
/// <summary> /// Constructs a MaskSurface by copying the given region-of-interest from an Image. /// </summary> /// <param name="source">The Surface to copy pixels from.</param> /// <param name="roi">Defines the Region from which to copy pixels from the Image.</param> public MaskedSurface(Surface source, PdnRegion roi) { PdnRegion roiClipped = (PdnRegion)roi.Clone(); roiClipped.Intersect(source.Bounds); Rectangle boundsClipped = roiClipped.GetBoundsInt(); this.SurfaceReadOnly = new Surface(boundsClipped.Size); this.SurfaceReadOnly.Clear(ColorBgra.FromUInt32(0x00ffffff)); Rectangle rect = boundsClipped; Point dstOffset = new Point(rect.X - boundsClipped.X, rect.Y - boundsClipped.Y); this.SurfaceReadOnly.CopySurface(source, dstOffset, rect); this.region = roiClipped; // TODO: FromRegion() is a VERY expensive call for what we are doing! PdnGraphicsPath newPath = PdnGraphicsPath.FromRegion(this.region); SetPathField(newPath); }
/// <summary> /// Creates a graphics path from the given stencil buffer. It should be filled with 'true' values /// to indicate the areas that should be outlined. /// </summary> /// <param name="stencil">The stencil buffer to read from. NOTE: The contents of this will be destroyed when this method returns.</param> /// <param name="bounds">The bounding box within the stencil buffer to limit discovery to.</param> /// <returns>A PdnGraphicsPath with traces that outline the various areas from the given stencil buffer.</returns> public unsafe static PdnGraphicsPath PathFromStencil(IBitVector2D stencil, Rectangle bounds) { if (stencil.IsEmpty) { return(new PdnGraphicsPath()); } PdnGraphicsPath ret = new PdnGraphicsPath(); Point start = bounds.Location; Vector <Point> pts = new Vector <Point>(); int count = 0; // find all islands while (true) { bool startFound = false; while (true) { if (stencil[start]) { startFound = true; break; } ++start.X; if (start.X >= bounds.Right) { ++start.Y; start.X = bounds.Left; if (start.Y >= bounds.Bottom) { break; } } } if (!startFound) { break; } pts.Clear(); Point last = new Point(start.X, start.Y + 1); Point curr = new Point(start.X, start.Y); Point next = curr; Point left = Point.Empty; Point right = Point.Empty; // trace island outline while (true) { left.X = ((curr.X - last.X) + (curr.Y - last.Y) + 2) / 2 + curr.X - 1; left.Y = ((curr.Y - last.Y) - (curr.X - last.X) + 2) / 2 + curr.Y - 1; right.X = ((curr.X - last.X) - (curr.Y - last.Y) + 2) / 2 + curr.X - 1; right.Y = ((curr.Y - last.Y) + (curr.X - last.X) + 2) / 2 + curr.Y - 1; if (bounds.Contains(left) && stencil[left]) { // go left next.X += curr.Y - last.Y; next.Y -= curr.X - last.X; } else if (bounds.Contains(right) && stencil[right]) { // go straight next.X += curr.X - last.X; next.Y += curr.Y - last.Y; } else { // turn right next.X -= curr.Y - last.Y; next.Y += curr.X - last.X; } if (Math.Sign(next.X - curr.X) != Math.Sign(curr.X - last.X) || Math.Sign(next.Y - curr.Y) != Math.Sign(curr.Y - last.Y)) { pts.Add(curr); ++count; } last = curr; curr = next; if (next.X == start.X && next.Y == start.Y) { break; } } Point[] points = pts.ToArray(); Scanline[] scans = Utility.GetScans(points); foreach (Scanline scan in scans) { stencil.Invert(scan); } ret.AddLines(points); ret.CloseFigure(); } return(ret); }
public PdnGraphicsPath CreatePath(bool applyInterimTransform) { lock (this.syncRoot) { PdnGraphicsPath returnPath; switch (this.data.continuationCombineMode) { case CombineMode.Complement: case CombineMode.Intersect: throw new NotSupportedException("Complement and Intersect are not supported"); case CombineMode.Replace: returnPath = this.data.continuation.Clone(); break; case CombineMode.Xor: returnPath = this.data.basePath.Clone(); returnPath.CloseAllFigures(); returnPath.AddPath(this.data.continuation, false); break; case CombineMode.Union: if (this.data.basePath.IsEmpty) { goto case CombineMode.Replace; } else { using (PdnRegion baseRegion = new PdnRegion(this.data.basePath)) { using (PdnRegion continuationRegion = new PdnRegion(this.data.continuation)) { returnPath = PdnGraphicsPath.FromRegions(baseRegion, CombineMode.Union, continuationRegion); } } } break; case CombineMode.Exclude: if (this.data.basePath.IsEmpty) { returnPath = new PdnGraphicsPath(); } else { using (PdnRegion baseRegion = new PdnRegion(this.data.basePath)) { using (PdnRegion continuationRegion = new PdnRegion(this.data.continuation)) { returnPath = PdnGraphicsPath.FromRegions(baseRegion, CombineMode.Exclude, continuationRegion); } } } break; default: throw new InvalidEnumArgumentException(); } if (applyInterimTransform) { returnPath.Transform(this.data.interimTransform); } return returnPath; } }
/// <summary> /// Found on Google Groups when searching for "Region.Union" while looking /// for bugs: /// --- /// Hello, /// /// I did not run your code, but I know Region.Union is flawed in both 1.0 and /// 1.1, so I assume it is in the gdi+ unmanged code dll. The best workaround, /// in terms of speed, is to use a PdnGraphicsPath, but it must be a path with /// FillMode = FillMode.Winding. You add the rectangles to the path, then you do /// union onto an empty region with the path. The important point is to do only /// one union call on a given empty region. We created a "super region" object /// to hide all these bugs and optimize clipping operations. In fact, it is much /// faster to use the path than to call Region.Union for each rectangle. /// /// Too bad about Region.Union. A lot of people will hit this bug, as it is /// essential in high-performance animation. /// /// Regards, /// Frank Hileman /// Prodige Software Corporation /// --- /// </summary> /// <param name="rectsF"></param> /// <param name="startIndex"></param> /// <param name="length"></param> /// <returns></returns> public static PdnRegion RectanglesToRegion(RectangleF[] rectsF, int startIndex, int length) { PdnRegion region; if (rectsF == null || rectsF.Length == 0 || length == 0) { region = PdnRegion.CreateEmpty(); } else { using (PdnGraphicsPath path = new PdnGraphicsPath()) { path.FillMode = FillMode.Winding; if (startIndex == 0 && length == rectsF.Length) { path.AddRectangles(rectsF); } else { for (int i = startIndex; i < startIndex + length; ++i) { path.AddRectangle(rectsF[i]); } } region = new PdnRegion(path); } } return region; }
public PdnRegion(PdnGraphicsPath pdnPath) : this(pdnPath.GetRegionCache()) { }
public static PdnGraphicsPath FromRegion(PdnRegion region) { Rectangle[] scans = region.GetRegionScansReadOnlyInt(); if (scans.Length == 1) { PdnGraphicsPath path = new PdnGraphicsPath(); path.AddRectangle(scans[0]); path.CloseFigure(); return path; } else { Rectangle bounds = region.GetBoundsInt(); BitVector2D stencil = new BitVector2D(bounds.Width, bounds.Height); for (int i = 0; i < scans.Length; ++i) { Rectangle rect = scans[i]; rect.X -= bounds.X; rect.Y -= bounds.Y; stencil.SetUnchecked(rect, true); } PdnGraphicsPath path = PathFromStencil(stencil, new Rectangle(0, 0, stencil.Width, stencil.Height)); using (Matrix matrix = new Matrix()) { matrix.Reset(); matrix.Translate(bounds.X, bounds.Y); path.Transform(matrix); } return path; } }
/// <summary> /// Creates a graphics path from the given stencil buffer. It should be filled with 'true' values /// to indicate the areas that should be outlined. /// </summary> /// <param name="stencil">The stencil buffer to read from. NOTE: The contents of this will be destroyed when this method returns.</param> /// <param name="bounds">The bounding box within the stencil buffer to limit discovery to.</param> /// <returns>A PdnGraphicsPath with traces that outline the various areas from the given stencil buffer.</returns> public unsafe static PdnGraphicsPath PathFromStencil(IBitVector2D stencil, Rectangle bounds) { if (stencil.IsEmpty) { return new PdnGraphicsPath(); } PdnGraphicsPath ret = new PdnGraphicsPath(); Point start = bounds.Location; Vector<Point> pts = new Vector<Point>(); int count = 0; // find all islands while (true) { bool startFound = false; while (true) { if (stencil[start]) { startFound = true; break; } ++start.X; if (start.X >= bounds.Right) { ++start.Y; start.X = bounds.Left; if (start.Y >= bounds.Bottom) { break; } } } if (!startFound) { break; } pts.Clear(); Point last = new Point(start.X, start.Y + 1); Point curr = new Point(start.X, start.Y); Point next = curr; Point left = Point.Empty; Point right = Point.Empty; // trace island outline while (true) { left.X = ((curr.X - last.X) + (curr.Y - last.Y) + 2) / 2 + curr.X - 1; left.Y = ((curr.Y - last.Y) - (curr.X - last.X) + 2) / 2 + curr.Y - 1; right.X = ((curr.X - last.X) - (curr.Y - last.Y) + 2) / 2 + curr.X - 1; right.Y = ((curr.Y - last.Y) + (curr.X - last.X) + 2) / 2 + curr.Y - 1; if (bounds.Contains(left) && stencil[left]) { // go left next.X += curr.Y - last.Y; next.Y -= curr.X - last.X; } else if (bounds.Contains(right) && stencil[right]) { // go straight next.X += curr.X - last.X; next.Y += curr.Y - last.Y; } else { // turn right next.X -= curr.Y - last.Y; next.Y += curr.X - last.X; } if (Math.Sign(next.X - curr.X) != Math.Sign(curr.X - last.X) || Math.Sign(next.Y - curr.Y) != Math.Sign(curr.Y - last.Y)) { pts.Add(curr); ++count; } last = curr; curr = next; if (next.X == start.X && next.Y == start.Y) { break; } } Point[] points = pts.ToArray(); Scanline[] scans = Utility.GetScans(points); foreach (Scanline scan in scans) { stencil.Invert(scan); } ret.AddLines(points); ret.CloseFigure(); } return ret; }
public static PdnGraphicsPath Combine(PdnGraphicsPath subjectPath, CombineMode combineMode, PdnGraphicsPath clipPath) { switch (combineMode) { case CombineMode.Complement: return Combine(clipPath, CombineMode.Exclude, subjectPath); case CombineMode.Replace: return clipPath.Clone(); case CombineMode.Xor: case CombineMode.Intersect: case CombineMode.Union: case CombineMode.Exclude: if (subjectPath.IsEmpty && clipPath.IsEmpty) { return new PdnGraphicsPath(); // empty path } else if (subjectPath.IsEmpty) { switch (combineMode) { case CombineMode.Xor: case CombineMode.Union: return clipPath.Clone(); case CombineMode.Intersect: case CombineMode.Exclude: return new PdnGraphicsPath(); default: throw new InvalidEnumArgumentException(); } } else if (clipPath.IsEmpty) { switch (combineMode) { case CombineMode.Exclude: case CombineMode.Xor: case CombineMode.Union: return subjectPath.Clone(); case CombineMode.Intersect: return new PdnGraphicsPath(); default: throw new InvalidEnumArgumentException(); } } else { GraphicsPath resultPath = PdnGraphics.ClipPath(subjectPath, combineMode, clipPath); return new PdnGraphicsPath(resultPath); } default: throw new InvalidEnumArgumentException(); } }
public GraphicsPathWrapper(PdnGraphicsPath path) { points = (PointF[])path.PathPoints.Clone(); types = (byte[])path.PathTypes.Clone(); fillMode = path.FillMode; }
public PdnGraphicsPath Clone() { PdnGraphicsPath path = new PdnGraphicsPath((GraphicsPath)gdiPath.Clone()); path.tooComplex = this.tooComplex; return path; }
private void OnSelectionChanged(object sender, EventArgs e) { this.render = true; PdnGraphicsPath path = this.selection.CreatePath(); //this.selection.GetPathReadOnly(); if (this.selectedPath == null) { Invalidate(); } else { this.selectedPath.Dispose(); // this.selectedPath = null; } bool fullInvalidate = false; this.selectedPath = path; // HACK: Sometimes the selection leaves behind artifacts. So do a full invalidate // every 1 second. if (this.selectedPath.PointCount > 10 && (DateTime.Now - lastFullInvalidate > new TimeSpan(0, 0, 0, 1, 0))) { fullInvalidate = true; } // if we're moving to a simpler selection region ... if (this.selectedPath == null)// || this.selectedPath.PointCount == 0) { // then invalidate everything fullInvalidate = true; } else { // otherwise, be intelligent about it and only redraw the 'new' area PdnRegion xorMe = new PdnRegion(this.selectedPath); selectionRedrawInterior.Xor(xorMe); xorMe.Dispose(); } float ratio = 1.0f / (float)OwnerList.ScaleFactor.Ratio; int ratioInt = (int)Math.Ceiling(ratio); if (this.Visible && (this.EnableSelectionOutline || this.EnableSelectionTinting)) { using (PdnRegion simplified = Utility.SimplifyAndInflateRegion(selectionRedrawInterior, Utility.DefaultSimplificationFactor, 2 * ratioInt)) { Invalidate(simplified); } } if (fullInvalidate) { Rectangle rect = Rectangle.Inflate(Rectangle.Truncate(selectionRedrawOutline.GetBounds2()), 1, 1); Invalidate(rect); lastFullInvalidate = DateTime.Now; } this.selectionRedrawInterior.Dispose(); this.selectionRedrawInterior = null; if (this.zoomInSelectedPath != null) { this.zoomInSelectedPath.Dispose(); this.zoomInSelectedPath = null; } this.simplifiedRegionForTimer = null; // prepare for next call if (this.selectedPath != null && !this.selectedPath.IsEmpty) { this.selectionRedrawOutline = (PdnGraphicsPath)this.selectedPath.Clone(); this.selectionRedrawInterior = new PdnRegion(this.selectedPath); } else { if (invertedTinting) { this.selectionRedrawInterior = new PdnRegion(new Rectangle(0, 0, this.SourceSize.Width, this.SourceSize.Height)); } else { this.selectionRedrawInterior = new PdnRegion(); this.selectionRedrawInterior.MakeEmpty(); } Invalidate(); this.selectionRedrawOutline = new PdnGraphicsPath(); } }
protected override void Dispose(bool disposing) { if (disposing) { if (this.components != null) { this.components.Dispose(); this.components = null; } if (this.selectionTimer != null) { this.selectionTimer.Dispose(); this.selectionTimer = null; } if (this.zoomInSelectedPath != null) { this.zoomInSelectedPath.Dispose(); this.zoomInSelectedPath = null; } } base.Dispose (disposing); }
static void Main(string[] args) { for (int i = 0; i < args.Length; i++) { switch (args[i]) { case "/proc": if (i + 1 == args.Length) { Console.WriteLine("Use /proc <N> to specify number of processors"); return; } int numProcs; if (Int32.TryParse(args[i + 1], out numProcs)) { // only increment i if successful b/c we're going to continue the run // with the default # of processors and don't want to automatically // eat the next parameter. ++i; Processor.LogicalCpuCount = numProcs; } else { Console.WriteLine("You must specify a integer for /proc <N>, continuing with default"); } break; case "/image": if (i + 1 == args.Length) { Console.WriteLine("Use /image <filename> to specify a file to perform benchmark with"); return; } ++i; benchmarkImageName = args[i]; if (!System.IO.File.Exists(benchmarkImageName)) { Console.WriteLine("Specified image doesn't exist"); return; } break; case "/tsv": useTsvOutput = true; break; case "/?": PrintHelp(); return; default: break; } } //Processor.LogicalCpuCount = 1; Console.WriteLine("PdnBench v" + PdnInfo.GetVersion()); Console.WriteLine("Running in " + (8 * Marshal.SizeOf(typeof(IntPtr))) + "-bit mode on Windows " + Environment.OSVersion.Version.ToString() + " " + OS.Revision + (OS.Revision.Length > 0 ? " " : string.Empty) + OS.Type + " " + Processor.NativeArchitecture.ToString().ToLower()); Console.WriteLine("Processor: " + Processor.LogicalCpuCount + "x \"" + Processor.CpuName + "\" @ ~" + GetCpuSpeed() + " MHz"); Console.WriteLine("Memory: " + ((Memory.TotalPhysicalBytes / 1024) / 1024) + " MB"); Console.WriteLine(); Console.WriteLine("Using " + Processor.LogicalCpuCount + " threads."); ArrayList benchmarks = new ArrayList(); Document document; Console.Write("Loading image ... "); Stream imageStream = null; try { imageStream = (defaultImageName == benchmarkImageName) ? Assembly.GetExecutingAssembly().GetManifestResourceStream(benchmarkImageName) : new FileStream(benchmarkImageName, FileMode.Open); JpegFileType jft = new JpegFileType(); document = jft.Load(imageStream); } finally { if (imageStream != null) { imageStream.Dispose(); } } Console.WriteLine("(" + document.Width + " x " + document.Height + ") done"); Surface surface = ((BitmapLayer)document.Layers[0]).Surface; #if EFFECTS for (double i = 0; i < (2 * Math.PI); i += 70.0 * ((2 * Math.PI) / 360.0)) { benchmarks.Add( new EffectBenchmark("Rotate/Zoom at " + ((i * 180.0) / Math.PI).ToString("F2") + " degrees", 3, new PaintDotNet.Effects.RotateZoomEffect(), new PaintDotNet.Effects.RotateZoomEffectConfigToken( true, (float)(Math.PI * 0.3f), (float)((Math.PI * -0.4) + i), 50, 0.5f, new PointF(-0.2f, 0.3f), false, true), surface)); } for (int i = 1; i <= 4; i += 3) { for (int j = 10; j < 100; j += 75) { benchmarks.Add( new EffectBenchmark( "Oil Painting, brush size = " + i + ", coarseness = " + j, 1, new OilPaintingEffect(), new TwoAmountsConfigToken(i, j), surface)); } } for (int i = 2; i <= 50; i += i) { benchmarks.Add( new EffectBenchmark( "Blur with radius of " + i, 1, new BlurEffect(), new AmountEffectConfigToken(i), surface)); } for (int i = 1; i <= 4; i += 3) { benchmarks.Add( new EffectBenchmark( "Sharpen with value of " + i, 1, new SharpenEffect(), new AmountEffectConfigToken(i), surface)); } benchmarks.Add( new EffectBenchmark( "Auto-Levels", 50, new AutoLevelEffect(), null, surface)); for (int i = 81; i >= 5; i /= 3) { benchmarks.Add( new EffectBenchmark( "Clouds, roughness = " + i, 2, new CloudsEffect(), new CloudsEffectConfigToken(50, i, 12345, new UserBlendOps.NormalBlendOp()), surface)); } for (int i = 4; i <= 64; i *= 4) { benchmarks.Add( new EffectBenchmark( "Median, radius " + i, 1, new MedianEffect(), new TwoAmountsConfigToken(/*radius*/i, /*roughness*/50), surface)); } for (int i = 4; i <= 64; i *= 4) { benchmarks.Add( new EffectBenchmark( "Unfocus, radius " + i, 1, new UnfocusEffect(), new AmountEffectConfigToken(i), surface)); } benchmarks.Add( new EffectBenchmark( "Motion Blur, Horizontal", 1, new MotionBlurEffect(), new MotionBlurEffectConfigToken(0, 100, true), surface)); benchmarks.Add( new EffectBenchmark( "Motion Blur, Vertical", 1, new MotionBlurEffect(), new MotionBlurEffectConfigToken(90, 100, true), surface)); #endif Surface dst = new Surface(surface.Width * 4, surface.Height * 4); #if RESIZE // Resize benchmarks for (int i = 1; i < 8; i += 2) { int newWidth = i * (dst.Width / 8); int newHeight = i * (dst.Height / 8); Surface dstWindow = dst.CreateWindow(new Rectangle(0, 0, newWidth, newHeight)); benchmarks.Add(new ResizeBenchmark("Resize from " + surface.Width + "x" + surface.Height + " to " + newWidth + "x" + newHeight, surface, dstWindow)); benchmarks.Add(new ResizeBenchmark("Resize from " + newWidth + "x" + newHeight + " to " + surface.Width + "x" + surface.Height, dstWindow, surface)); } #endif #if GRADIENT // Gradient benchmarks benchmarks.Add(new GradientBenchmark( "Linear reflected gradient @ " + dst.Width + "x" + dst.Height + " (5x)", dst, new GradientRenderers.LinearReflected(false, new UserBlendOps.NormalBlendOp()), 2)); benchmarks.Add(new GradientBenchmark( "Conical gradient @ " + dst.Width + "x" + dst.Height + " (5x)", dst, new GradientRenderers.Conical(false, new UserBlendOps.NormalBlendOp()), 2)); benchmarks.Add(new GradientBenchmark( "Radial gradient @ " + dst.Width + "x" + dst.Height + " (5x)", dst, new GradientRenderers.Radial(false, new UserBlendOps.NormalBlendOp()), 2)); #endif #if COMPOSITION // Composition benchmarks Document doc1 = new Document(surface.Size); BitmapLayer layer1 = Layer.CreateBackgroundLayer(doc1.Width, doc1.Height); layer1.Surface.CopySurface(surface); doc1.Layers.Add(layer1); doc1.Layers.Add(layer1.Clone()); doc1.Layers.Add(layer1.Clone()); doc1.Layers.Add(layer1.Clone()); benchmarks.Add(new CompositionBenchmark("Compositing one layer, Normal blend mode, 255 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { if (layerIndex == 0) { layer.Visible = true; layer.Opacity = 255; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); } else { layer.Visible = false; } })); benchmarks.Add(new CompositionBenchmark("Compositing one layer, Normal blend mode, 128 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { if (layerIndex == 0) { layer.Visible = true; layer.Opacity = 128; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); } else { layer.Visible = false; } })); benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 255 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { layer.Visible = true; layer.Opacity = 255; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); })); benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 255 (layer 0) and 128 (layer 1-3) opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { layer.Visible = true; layer.Opacity = 128; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); })); benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 128 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { layer.Visible = true; layer.Opacity = 128; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); })); benchmarks.Add(new CompositionBenchmark("Compositing three layers, Normal+Multiply+Overlay blending, 150+255+170 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface, delegate(int layerIndex, Layer layer) { if (layerIndex == 0) { layer.Visible = true; layer.Opacity = 150; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp()); } else if (layerIndex == 1) { layer.Visible = true; layer.Opacity = 255; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.MultiplyBlendOp()); } else if (layerIndex == 2) { layer.Visible = true; layer.Opacity = 170; ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.OverlayBlendOp()); } else { layer.Visible = false; } })); #endif #if TRANSFORM // Transform benchmarks Matrix m = new Matrix(); m.Reset(); MaskedSurface msSimple = new MaskedSurface(surface, new PdnRegion(surface.Bounds)); // simple masked surface PdnRegion complexRegion = new PdnRegion(surface.Bounds); // cut 4 holes in region 1 to form a complex clipping surface for (int x = -1; x < 3; ++x) { for (int y = -1; y < 3; ++y) { int left = (1 + (x * 3)) * (surface.Width / 6); int top = (1 + (x * 3)) * (surface.Height / 6); int right = (2 + (x * 3)) * (surface.Width / 6); int bottom = (2 + (x * 3)) * (surface.Height / 6); Rectangle rect = Rectangle.FromLTRB(left, top, right, bottom); PdnGraphicsPath path = new PdnGraphicsPath(); path.AddEllipse(rect); complexRegion.Exclude(path); } } MaskedSurface msComplex = new MaskedSurface(surface, complexRegion); benchmarks.Add(new TransformBenchmark("Transform simple surface, no transform, nearest neighbor resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, false)); benchmarks.Add(new TransformBenchmark("Transform complex surface, no transform, nearest neighbor resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, false)); benchmarks.Add(new TransformBenchmark("Transform simple surface, no transform, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, true)); benchmarks.Add(new TransformBenchmark("Transform complex surface, no transform, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m, true)); Matrix m2 = m.Clone(); m2.RotateAt(45.0f, new PointF(surface.Width / 2, surface.Height / 2)); benchmarks.Add(new TransformBenchmark("Transform simple surface, 45 deg. rotation about center, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m2, true)); benchmarks.Add(new TransformBenchmark("Transform complex surface, 45 deg. rotation about center, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m2, true)); Matrix m3 = m.Clone(); m3.Scale(0.5f, 0.75f); benchmarks.Add(new TransformBenchmark("Transform simple surface, 50% x-scaling 75% y-scaling, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m3, true)); benchmarks.Add(new TransformBenchmark("Transform complex surface, 50% x-scaling 75% y-scaling, bilinear resampling (" + TransformBenchmark.Iterations + "x)", surface, msSimple, m3, true)); #endif #if BLIT // Blit benchmarks benchmarks.Add(new ZoomOutBlitBenchmark("Zoom out, rotated grid multisampling, 66% (" + ZoomOutBlitBenchmark.IterationCount + "x)", surface, dst, new Size((surface.Width * 2) / 3, (surface.Height * 2) / 3))); benchmarks.Add(new ZoomOutBlitBenchmark("Zoom out, rotated grid multisampling, 28% (" + ZoomOutBlitBenchmark.IterationCount + "x)", surface, dst, new Size((surface.Width * 28) / 100, (surface.Height * 28) / 100))); benchmarks.Add(new ZoomOneToOneBlitBenchmark("Zoom 1:1, straight blit (" + ZoomOneToOneBlitBenchmark.IterationCount + "x)", surface, dst.CreateWindow(new Rectangle(0, 0, surface.Width, surface.Height)))); #endif // Run benchmarks! Timing timing = new Timing(); ulong start = timing.GetTickCount(); foreach (Benchmark benchmark in benchmarks) { Console.Write(benchmark.Name + (useTsvOutput ? "\t" : " ... ")); TimeSpan timeSpan = benchmark.Execute(); Console.WriteLine(" " + timeSpan.TotalMilliseconds.ToString() + (useTsvOutput ? "\t" : "") + " milliseconds"); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); } ulong end = timing.GetTickCount(); Console.WriteLine(); Console.WriteLine("Total time: " + (useTsvOutput ? "\t" : "") + (end - start).ToString() + (useTsvOutput ? "\t" : "") + " milliseconds"); Console.WriteLine(); }
private void SetPathField(PdnGraphicsPath newPath) { this.path = newPath; this.shadowPath = newPath.Clone(); }
/// <summary> /// When we zoom in, we want to "stair-step" the selected path. /// </summary> /// <returns></returns> private PdnGraphicsPath GetZoomInPath() { lock (this.SyncRoot) { if (this.zoomInSelectedPath == null) { if (this.selectedPath == null) { this.zoomInSelectedPath = new PdnGraphicsPath(); } else { this.zoomInSelectedPath = this.selection.CreatePixelatedPath(); } } return this.zoomInSelectedPath; } }