public Context(Context cloneMe) { this.lifted = cloneMe.lifted; this.seriesGuid = cloneMe.seriesGuid; if (cloneMe.baseTransform != null) { this.baseTransform = cloneMe.baseTransform.Clone(); } if (cloneMe.deltaTransform != null) { this.deltaTransform = cloneMe.deltaTransform.Clone(); } if (cloneMe.liftTransform != null) { this.liftTransform = cloneMe.liftTransform.Clone(); } this.liftedBounds = cloneMe.liftedBounds; this.startBounds = cloneMe.startBounds; this.startAngle = cloneMe.startAngle; if (cloneMe.startPath != null) { this.startPath = cloneMe.startPath.Clone(); } this.currentMode = cloneMe.currentMode; this.startEdge = cloneMe.startEdge; this.startMouseXY = cloneMe.startMouseXY; this.offset = cloneMe.offset; }
protected override SegmentedList <PointDouble> CreateShape(SegmentedList <PointDouble> tracePoints) { RectDouble num5; PointDouble a = tracePoints[0]; PointDouble b = tracePoints[tracePoints.Count - 1]; PointDouble num3 = new PointDouble(b.X - a.X, b.Y - a.Y); double num4 = Math.Sqrt((num3.X * num3.X) + (num3.Y * num3.Y)); if ((base.ModifierKeys & Keys.Shift) != Keys.None) { PointDouble center = new PointDouble((a.X + b.X) / 2.0, (a.Y + b.Y) / 2.0); double num7 = num4 / 2.0; num5 = RectDouble.FromCenter(center, (double)(num7 * 2.0)); } else { num5 = RectDoubleUtil.FromPixelPoints(a, b); } PdnGraphicsPath path = new PdnGraphicsPath(); path.AddEllipse(num5.ToGdipRectangleF()); using (Matrix matrix = new Matrix()) { path.Flatten(matrix, 0.1f); } SegmentedList <PointDouble> list = new SegmentedList <PointDouble>(path.PathPoints.Select <PointF, PointDouble>(pt => pt.ToDoublePoint()), 7); path.Dispose(); return(list); }
protected virtual void Dispose(bool disposing) { if (disposing) { if (this.baseTransform != null) { this.baseTransform.Dispose(); this.baseTransform = null; } if (this.deltaTransform != null) { this.deltaTransform.Dispose(); this.deltaTransform = null; } if (this.liftTransform != null) { this.liftTransform.Dispose(); this.liftTransform = null; } if (this.startPath != null) { this.startPath.Dispose(); this.startPath = null; } } }
public static Surface CreateThumbnail(Surface sourceSurface, PdnGraphicsPath maskPath, Rectangle bounds, int thumbSideLength) { Size thumbSize = Utility.ComputeThumbnailSize(bounds.Size, thumbSideLength); Surface thumb = new Surface(Math.Max(5, thumbSize.Width + 4), Math.Max(5, thumbSize.Height + 4)); thumb.Clear(ColorBgra.Transparent); thumb.Clear(new Rectangle(1, 1, thumb.Width - 2, thumb.Height - 2), ColorBgra.Black); Rectangle insetRect = new Rectangle(2, 2, thumb.Width - 4, thumb.Height - 4); Surface thumbInset = thumb.CreateWindow(insetRect); thumbInset.Clear(ColorBgra.Transparent); float scaleX = (float)thumbInset.Width / (float)bounds.Width; float scaleY = (float)thumbInset.Height / (float)bounds.Height; Matrix scaleMatrix = new Matrix(); scaleMatrix.Translate(-bounds.X, -bounds.Y, System.Drawing.Drawing2D.MatrixOrder.Append); scaleMatrix.Scale(scaleX, scaleY, System.Drawing.Drawing2D.MatrixOrder.Append); thumbInset.SuperSamplingFitSurface(sourceSurface); Surface maskInset = new Surface(thumbInset.Size); maskInset.Clear(ColorBgra.Black); using (RenderArgs maskInsetRA = new RenderArgs(maskInset)) { maskInsetRA.Graphics.SmoothingMode = SmoothingMode.AntiAlias; maskInsetRA.Graphics.Transform = scaleMatrix; maskInsetRA.Graphics.FillPath(Brushes.White, maskPath); maskInsetRA.Graphics.DrawPath(Pens.White, maskPath); } scaleMatrix.Dispose(); scaleMatrix = null; IntensityMaskOp maskOp = new IntensityMaskOp(); maskOp.Apply(maskInset, thumbInset, maskInset); UserBlendOps.NormalBlendOp normalOp = new UserBlendOps.NormalBlendOp(); thumbInset.ClearWithCheckboardPattern(); normalOp.Apply(thumbInset, thumbInset, maskInset); maskInset.Dispose(); maskInset = null; thumbInset.Dispose(); thumbInset = null; using (RenderArgs thumbRA = new RenderArgs(thumb)) { Utility.DrawDropShadow1px(thumbRA.Graphics, thumb.Bounds); } return(thumb); }
protected override void OnFillRegionComputed(Point[][] polygonSet) { using (PdnGraphicsPath path = new PdnGraphicsPath()) { path.AddPolygons(polygonSet); using (PdnRegion fillRegion = new PdnRegion(path)) { Rectangle boundingBox = fillRegion.GetBoundsInt(); Surface surface = ((BitmapLayer)ActiveLayer).Surface; RenderArgs ra = new RenderArgs(surface); HistoryMemento ha; using (PdnRegion affected = Utility.SimplifyAndInflateRegion(fillRegion)) { ha = new BitmapHistoryMemento(Name, Image, DocumentWorkspace, DocumentWorkspace.ActiveLayerIndex, affected); } ra.Graphics.CompositingMode = AppEnvironment.GetCompositingMode(); ra.Graphics.FillRegion(brush, fillRegion.GetRegionReadOnly()); HistoryStack.PushNewMemento(ha); ActiveLayer.Invalidate(boundingBox); Update(); } } }
protected override PdnGraphicsPath CreateShapePath(PointF[] points) { // make sure we don't screw them up if (points.Length < 2) { return(null); } // make sure the shape has an area of at least 1 // we can determine this by making sure that all the Points in points are not all the same bool allTheSame = true; foreach (PointF pt in points) { if (pt != points[0]) { allTheSame = false; break; } } if (allTheSame) { return(null); } PdnGraphicsPath path = new PdnGraphicsPath(); path.AddLines(points); path.AddLine(points[points.Length - 1], points[0]); path.CloseAllFigures(); return(path); }
public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace) { if (historyWorkspace.Selection.IsEmpty) { return(null); } else { SelectionHistoryMemento sha = new SelectionHistoryMemento( StaticName, StaticImage, historyWorkspace); PdnRegion selectedRegion = historyWorkspace.Selection.CreateRegion(); selectedRegion.Xor(historyWorkspace.Document.Bounds); PdnGraphicsPath invertedSelection = PdnGraphicsPath.FromRegion(selectedRegion); selectedRegion.Dispose(); EnterCriticalRegion(); historyWorkspace.Selection.PerformChanging(); historyWorkspace.Selection.Reset(); historyWorkspace.Selection.SetContinuation(invertedSelection, CombineMode.Xor, true); historyWorkspace.Selection.CommitContinuation(); historyWorkspace.Selection.PerformChanged(); return(sha); } }
protected override PdnGraphicsPath CreateShapePath(PointF[] points) { // make sure we don't screw them up if (points.Length < 2) { return null; } // make sure the shape has an area of at least 1 // we can determine this by making sure that all the Points in points are not all the same bool allTheSame = true; foreach (PointF pt in points) { if (pt != points[0]) { allTheSame = false; break; } } if (allTheSame) { return null; } PdnGraphicsPath path = new PdnGraphicsPath(); path.AddLines(points); path.AddLine(points[points.Length - 1], points[0]); path.CloseAllFigures(); return path; }
protected override void OnLift(MouseEventArgs e) { PdnGraphicsPath liftPath = Selection.CreatePath(); PdnRegion liftRegion = Selection.CreateRegion(); this.ourContext.LiftedPixels = new MaskedSurface(activeLayer.Surface, liftPath); HistoryMemento bitmapAction = new BitmapHistoryMemento( Name, Image, DocumentWorkspace, ActiveLayerIndex, this.ourContext.poLiftedPixelsGuid); this.currentHistoryMementos.Add(bitmapAction); // If the user is holding down the control key, we want to *copy* the pixels // and not "lift and erase" if ((ModifierKeys & Keys.Control) == Keys.None) { ColorBgra fill = AppEnvironment.SecondaryColor; fill.A = 0; UnaryPixelOp op = new UnaryPixelOps.Constant(fill); op.Apply(this.renderArgs.Surface, liftRegion); } liftRegion.Dispose(); liftRegion = null; liftPath.Dispose(); liftPath = null; }
protected override PdnGraphicsPath CreateShapePath(PointF[] points) { PointF a = points[0]; PointF b = points[points.Length - 1]; RectangleF rect; if ((ModifierKeys & Keys.Shift) != 0) { rect = Utility.PointsToConstrainedRectangle(a, b); } else { rect = Utility.PointsToRectangle(a, b); } PdnGraphicsPath path = new PdnGraphicsPath(); path.AddRectangle(rect); path.CloseFigure(); path.Reverse(); MeasurementUnit units = AppWorkspace.Units; double widthPhysical = Math.Abs(Document.PixelToPhysicalX(rect.Width, units)); double heightPhysical = Math.Abs(Document.PixelToPhysicalY(rect.Height, units)); double areaPhysical = widthPhysical * heightPhysical; string numberFormat; string unitsAbbreviation; if (units != MeasurementUnit.Pixel) { string unitsAbbreviationName = "MeasurementUnit." + units.ToString() + ".Abbreviation"; unitsAbbreviation = PdnResources.GetString(unitsAbbreviationName); numberFormat = "F2"; } else { unitsAbbreviation = string.Empty; numberFormat = "F0"; } string unitsString = PdnResources.GetString("MeasurementUnit." + units.ToString() + ".Plural"); string statusText = string.Format( this.statusTextFormat, widthPhysical.ToString(numberFormat), unitsAbbreviation, heightPhysical.ToString(numberFormat), unitsAbbreviation, areaPhysical.ToString(numberFormat), unitsString); this.SetStatus(this.rectangleToolIcon, statusText); return(path); }
protected override PdnGraphicsPath CreateShapePath(PointF[] points) { PointF a = points[0]; PointF b = points[points.Length - 1]; RectangleF rect; if ((ModifierKeys & Keys.Shift) != 0) { rect = Utility.PointsToConstrainedRectangle(a, b); } else { rect = Utility.PointsToRectangle(a, b); } PdnGraphicsPath path = new PdnGraphicsPath(); path.AddRectangle(rect); path.CloseFigure(); path.Reverse(); MeasurementUnit units = AppWorkspace.Units; double widthPhysical = Math.Abs(Document.PixelToPhysicalX(rect.Width, units)); double heightPhysical = Math.Abs(Document.PixelToPhysicalY(rect.Height, units)); double areaPhysical = widthPhysical * heightPhysical; string numberFormat; string unitsAbbreviation; if (units != MeasurementUnit.Pixel) { string unitsAbbreviationName = "MeasurementUnit." + units.ToString() + ".Abbreviation"; unitsAbbreviation = PdnResources.GetString(unitsAbbreviationName); numberFormat = "F2"; } else { unitsAbbreviation = string.Empty; numberFormat = "F0"; } string unitsString = PdnResources.GetString("MeasurementUnit." + units.ToString() + ".Plural"); string statusText = string.Format( this.statusTextFormat, widthPhysical.ToString(numberFormat), unitsAbbreviation, heightPhysical.ToString(numberFormat), unitsAbbreviation, areaPhysical.ToString(numberFormat), unitsString); this.SetStatus(this.rectangleToolIcon, statusText); return path; }
protected override PdnGraphicsPath CreateShapePath(PointF[] points) { PointF a = points[0]; PointF b = points[points.Length - 1]; RectangleF rect; if ((ModifierKeys & Keys.Shift) != 0) { PointF dir = new PointF(b.X - a.X, b.Y - a.Y); float len = (float)Math.Sqrt(dir.X * dir.X + dir.Y * dir.Y); PointF center = new PointF((a.X + b.X) / 2.0f, (a.Y + b.Y) / 2.0f); float radius = len / 2.0f; rect = Utility.RectangleFromCenter(center, radius); } else { rect = Utility.PointsToRectangle(a, b); } if (rect.Width == 0 || rect.Height == 0) { return(null); } PdnGraphicsPath path = new PdnGraphicsPath(); path.AddEllipse(rect); path.Flatten(Utility.IdentityMatrix, 0.10f); double widthPhysical = Math.Abs(rect.Width); double heightPhysical = Math.Abs(rect.Height); double areaPhysical = Math.PI * (widthPhysical / 2.0) * (heightPhysical / 2.0); string numberFormat; string unitsAbbreviation; unitsAbbreviation = string.Empty; numberFormat = "F0"; string unitsString = PdnResources.GetString("MeasurementUnit." + "Pixel" + ".Plural"); string statusText = string.Format( this.statusTextFormat, widthPhysical.ToString(numberFormat), unitsAbbreviation, heightPhysical.ToString(numberFormat), unitsAbbreviation, areaPhysical.ToString(numberFormat), unitsString); this.SetStatus(this.ellipseToolIcon, statusText); return(path); }
protected override PdnGraphicsPath CreateShapePath(PointF[] points) { PointF a = points[0]; PointF b = points[points.Length - 1]; RectangleF rect; float radius = 10; if ((ModifierKeys & Keys.Shift) != 0) { rect = Utility.PointsToConstrainedRectangle(a, b); } else { rect = Utility.PointsToRectangle(a, b); } PdnGraphicsPath path = this.GetRoundedRect(rect, radius); path.Flatten(); if (path.PathPoints[0] != path.PathPoints[path.PathPoints.Length - 1]) { path.AddLine(path.PathPoints[0], path.PathPoints[path.PathPoints.Length - 1]); path.CloseFigure(); } string numberFormat; string unitsAbbreviation; { unitsAbbreviation = string.Empty; numberFormat = "F0"; } string unitsString = PdnResources.GetString("MeasurementUnit." + "Pixels" + ".Plural"); string statusText = string.Format( this.statusTextFormat, rect.Width, unitsAbbreviation, rect.Height, unitsAbbreviation, "0", unitsString); this.SetStatus(this.roundedRectangleToolIcon, statusText); return(path); }
private static Surface CreateThumbnail(SurfaceForClipboard surfaceForClipboard) { const int thumbLength96dpi = 120; int thumbSizeOurDpi = SystemLayer.UI.ScaleWidth(thumbLength96dpi); Surface surface = surfaceForClipboard.MaskedSurface.SurfaceReadOnly; PdnGraphicsPath maskPath = surfaceForClipboard.MaskedSurface.CreatePath(); Rectangle bounds = surfaceForClipboard.Bounds; Surface thumb = CreateThumbnail(surface, maskPath, bounds, thumbSizeOurDpi); maskPath.Dispose(); return(thumb); }
public Context(SerializationInfo info, StreamingContext context) { this.lifted = (bool)info.GetValue("lifted", typeof(bool)); this.seriesGuid = (Guid)info.GetValue("seriesGuid", typeof(Guid)); this.baseTransform = ReadMatrix(info, context, "baseTransform"); this.deltaTransform = ReadMatrix(info, context, "deltaTransform"); this.liftTransform = ReadMatrix(info, context, "liftTransform"); this.liftedBounds = (RectangleF)info.GetValue("liftedBounds", typeof(RectangleF)); this.startBounds = (RectangleF)info.GetValue("startBounds", typeof(RectangleF)); this.startAngle = (float)info.GetValue("startAngle", typeof(float)); this.startPath = (PdnGraphicsPath)info.GetValue("startPath", typeof(PdnGraphicsPath)); this.currentMode = (Mode)info.GetValue("currentMode", typeof(Mode)); this.startEdge = (Edge)info.GetValue("startEdge", typeof(Edge)); this.startMouseXY = (Point)info.GetValue("startMouseXY", typeof(Point)); this.offset = (Point)info.GetValue("offset", typeof(Point)); }
// credit for the this function is given to Aaron Reginald http://www.codeproject.com/cs/media/ExtendedGraphics.asp private PdnGraphicsPath GetCapsule(RectangleF baseRect) { float diameter; RectangleF arc; PdnGraphicsPath path = new PdnGraphicsPath(); try { if (baseRect.Width > baseRect.Height) { // return horizontal capsule diameter = baseRect.Height; SizeF sizeF = new SizeF(diameter, diameter); arc = new RectangleF(baseRect.Location, sizeF); path.AddArc(arc, 90, 180); arc.X = baseRect.Right - diameter; path.AddArc(arc, 270, 180); } else if (baseRect.Width < baseRect.Height) { // return vertical capsule diameter = baseRect.Width; SizeF sizeF = new SizeF(diameter, diameter); arc = new RectangleF(baseRect.Location, sizeF); path.AddArc(arc, 180, 180); arc.Y = baseRect.Bottom - diameter; path.AddArc(arc, 0, 180); } else { // return circle path.AddEllipse(baseRect); } } catch (Exception) { path.AddEllipse(baseRect); } finally { path.CloseFigure(); } return(path); }
// credit for the this function is given to Aaron Reginald http://www.codeproject.com/cs/media/ExtendedGraphics.asp protected PdnGraphicsPath GetRoundedRect(RectangleF baseRect, float radius) { // if corner radius is less than or equal to zero, // return the original rectangle if (radius <= 0.0f) { PdnGraphicsPath mPath = new PdnGraphicsPath(); mPath.AddRectangle(baseRect); mPath.CloseFigure(); return(mPath); } // if the corner radius is greater than or equal to // half the width, or height (whichever is shorter) // then return a capsule instead of a lozenge if (radius >= (Math.Min(baseRect.Width, baseRect.Height)) / 2.0) { return(GetCapsule(baseRect)); } // create the arc for the rectangle sides and declare // a graphics path object for the drawing float diameter = radius * 2.0f; SizeF sizeF = new SizeF(diameter, diameter); RectangleF arc = new RectangleF(baseRect.Location, sizeF); PdnGraphicsPath path = new PdnGraphicsPath(); // top left arc path.AddArc(arc, 180, 90); // top right arc arc.X = baseRect.Right - diameter; path.AddArc(arc, 270, 90); // bottom right arc arc.Y = baseRect.Bottom - diameter; path.AddArc(arc, 0, 90); // bottom left arc arc.X = baseRect.Left; path.AddArc(arc, 90, 90); path.CloseFigure(); return(path); }
protected override void OnMouseDown(MouseEventArgs e) { Point pos = new Point(e.X, e.Y); this.contiguous = ((ModifierKeys & Keys.Shift) == 0); if (Document.Bounds.Contains(pos)) { base.OnMouseDown(e); PdnRegion currentRegion = Selection.CreateRegion(); // See if the mouse click is valid if (!currentRegion.IsVisible(pos) && limitToSelection) { currentRegion.Dispose(); currentRegion = null; return; } // Set the current surface, color picked and color to draw Surface surface = ((BitmapLayer)ActiveLayer).Surface; IBitVector2D stencilBuffer = new BitVector2DSurfaceAdapter(this.ScratchSurface); Rectangle boundingBox; int tolerance = (int)(AppEnvironment.Tolerance * AppEnvironment.Tolerance * 256); if (contiguous) { FillStencilFromPoint(surface, stencilBuffer, pos, tolerance, out boundingBox, currentRegion, limitToSelection); } else { FillStencilByColor(surface, stencilBuffer, surface[pos], tolerance, out boundingBox, currentRegion, limitToSelection); } Point[][] polygonSet = PdnGraphicsPath.PolygonSetFromStencil(stencilBuffer, boundingBox, 0, 0); OnFillRegionComputed(polygonSet); } base.OnMouseDown(e); }
public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace) { if (historyWorkspace.Selection.IsEmpty) { return(null); } else { SelectionHistoryMemento sha = new SelectionHistoryMemento( StaticName, StaticImage, historyWorkspace); //PdnGraphicsPath selectedPath = historyWorkspace.Selection.GetPathReadOnly(); PdnGraphicsPath selectedPath = historyWorkspace.Selection.CreatePath(); PdnGraphicsPath boundsOutline = new PdnGraphicsPath(); boundsOutline.AddRectangle(historyWorkspace.Document.Bounds); PdnGraphicsPath clippedPath = PdnGraphicsPath.Combine(selectedPath, CombineMode.Intersect, boundsOutline); PdnGraphicsPath invertedPath = PdnGraphicsPath.Combine(clippedPath, CombineMode.Xor, boundsOutline); selectedPath.Dispose(); selectedPath = null; clippedPath.Dispose(); clippedPath = null; EnterCriticalRegion(); historyWorkspace.Selection.PerformChanging(); historyWorkspace.Selection.Reset(); historyWorkspace.Selection.SetContinuation(invertedPath, CombineMode.Replace, true); historyWorkspace.Selection.CommitContinuation(); historyWorkspace.Selection.PerformChanged(); boundsOutline.Dispose(); boundsOutline = null; return(sha); } }
public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace) { if (historyWorkspace.Selection.IsEmpty) { return null; } else { SelectionHistoryMemento sha = new SelectionHistoryMemento( StaticName, StaticImage, historyWorkspace); //PdnGraphicsPath selectedPath = historyWorkspace.Selection.GetPathReadOnly(); PdnGraphicsPath selectedPath = historyWorkspace.Selection.CreatePath(); PdnGraphicsPath boundsOutline = new PdnGraphicsPath(); boundsOutline.AddRectangle(historyWorkspace.Document.Bounds); PdnGraphicsPath clippedPath = PdnGraphicsPath.Combine(selectedPath, CombineMode.Intersect, boundsOutline); PdnGraphicsPath invertedPath = PdnGraphicsPath.Combine(clippedPath, CombineMode.Xor, boundsOutline); selectedPath.Dispose(); selectedPath = null; clippedPath.Dispose(); clippedPath = null; EnterCriticalRegion(); historyWorkspace.Selection.PerformChanging(); historyWorkspace.Selection.Reset(); historyWorkspace.Selection.SetContinuation(invertedPath, CombineMode.Replace, true); historyWorkspace.Selection.CommitContinuation(); historyWorkspace.Selection.PerformChanged(); boundsOutline.Dispose(); boundsOutline = null; return sha; } }
protected override List <PointF> CreateShape(List <Point> tracePoints) { Point a = tracePoints[0]; Point b = tracePoints[tracePoints.Count - 1]; Point dir = new Point(b.X - a.X, b.Y - a.Y); float len = (float)Math.Sqrt(dir.X * dir.X + dir.Y * dir.Y); RectangleF rectF; if ((ModifierKeys & Keys.Shift) != 0) { PointF center = new PointF((float)(a.X + b.X) / 2.0f, (float)(a.Y + b.Y) / 2.0f); float radius = len / 2; rectF = Rectangle.Truncate(Utility.RectangleFromCenter(center, radius)); } else { rectF = Utility.PointsToRectangle(a, b); } Rectangle rect = Utility.RoundRectangle(rectF); PdnGraphicsPath path = new PdnGraphicsPath(); path.AddEllipse(rect); // Avoid asymmetrical circles where the left or right side of the ellipse has a pixel jutting out using (Matrix m = new Matrix()) { m.Reset(); m.Translate(-0.5f, -0.5f, MatrixOrder.Append); path.Transform(m); } path.Flatten(Utility.IdentityMatrix, 0.1f); PointF[] pointsF = path.PathPoints; path.Dispose(); return(new List <PointF>(pointsF)); }
protected override List<PointF> CreateShape(List<Point> tracePoints) { Point a = tracePoints[0]; Point b = tracePoints[tracePoints.Count - 1]; Point dir = new Point(b.X - a.X, b.Y - a.Y); float len = (float)Math.Sqrt(dir.X * dir.X + dir.Y * dir.Y); RectangleF rectF; if ((ModifierKeys & Keys.Shift) != 0) { PointF center = new PointF((float)(a.X + b.X) / 2.0f, (float)(a.Y + b.Y) / 2.0f); float radius = len / 2; rectF = Rectangle.Truncate(Utility.RectangleFromCenter(center, radius)); } else { rectF = Utility.PointsToRectangle(a, b); } Rectangle rect = Utility.RoundRectangle(rectF); PdnGraphicsPath path = new PdnGraphicsPath(); path.AddEllipse(rect); // Avoid asymmetrical circles where the left or right side of the ellipse has a pixel jutting out using (Matrix m = new Matrix()) { m.Reset(); m.Translate(-0.5f, -0.5f, MatrixOrder.Append); path.Transform(m); } path.Flatten(Utility.IdentityMatrix, 0.1f); PointF[] pointsF = path.PathPoints; path.Dispose(); return new List<PointF>(pointsF); }
public static Surface CreateThumbnail(Surface sourceSurface, GeometryList maskGeometry, RectInt32 maskBounds, int thumbSideLength) { Surface dst = new Surface(ThumbnailHelpers.ComputeThumbnailSize(sourceSurface.Size <ColorBgra>(), thumbSideLength)); dst.Clear(ColorBgra.Transparent); sourceSurface.ResizeFant(dst.Size <ColorBgra>()).Parallelize <ColorBgra>(TilingStrategy.HorizontalSlices, 5, WorkItemQueuePriority.Normal).Render <ColorBgra>(dst); Surface surface = new Surface(dst.Size <ColorBgra>()); surface.Clear(ColorBgra.Black); using (PdnGraphicsPath path = new PdnGraphicsPath()) { path.AddGeometryList(maskGeometry); double scaleX = (maskBounds.Width == 0) ? 0.0 : (((double)dst.Width) / ((double)maskBounds.Width)); double scaleY = (maskBounds.Height == 0) ? 0.0 : (((double)dst.Height) / ((double)maskBounds.Height)); Matrix3x2Double m = Matrix3x2Double.Translation((double)-maskBounds.X, (double)-maskBounds.Y) * Matrix3x2Double.Scaling(scaleX, scaleY); using (RenderArgs args = new RenderArgs(surface)) { args.Graphics.SmoothingMode = SmoothingMode.AntiAlias; using (Matrix matrix = m.ToGdipMatrix()) { args.Graphics.Transform = matrix; } args.Graphics.FillPath(Brushes.White, (GraphicsPath)path); args.Graphics.DrawPath(Pens.White, (GraphicsPath)path); } } new IntensityMaskOp().Apply(surface, dst, surface); RendererBgra.Checkers(dst.Size <ColorBgra>()).Render <ColorBgra>(dst); CompositionOps.Normal.Static.Apply(dst, dst, surface); surface.Dispose(); surface = null; int recommendedExtent = DropShadow.GetRecommendedExtent(dst.Size <ColorBgra>()); ShadowDecorationRenderer renderer = new ShadowDecorationRenderer(dst, recommendedExtent); Surface surface3 = new Surface(renderer.Size <ColorBgra>()); renderer.Render <ColorBgra>(surface3); return(surface3); }
protected override PdnGraphicsPath CreateShapePath(PointF[] points) { if (points.Length >= 4) { PdnGraphicsPath path = new PdnGraphicsPath(); switch (this.curveType) { default: case CurveType.Spline: path.AddCurve(points); break; case CurveType.Bezier: path.AddBezier(points[0], points[1], points[2], points[3]); break; } path.Flatten(Utility.IdentityMatrix, flattenConstant); return path; } else //if (points.Length <= 2) { PointF a = points[0]; PointF b = points[points.Length - 1]; if (0 != (ModifierKeys & Keys.Shift) && a != b) { ConstrainPoints(ref a, ref b); } double angle = -180.0 * Math.Atan2(b.Y - a.Y, b.X - a.X) / Math.PI; MeasurementUnit units = AppWorkspace.Units; double offsetXPhysical = Document.PixelToPhysicalX(b.X - a.X, units); double offsetYPhysical = Document.PixelToPhysicalY(b.Y - a.Y, units); double offsetLengthPhysical = Math.Sqrt(offsetXPhysical * offsetXPhysical + offsetYPhysical * offsetYPhysical); string numberFormat; string unitsAbbreviation; if (units != MeasurementUnit.Pixel) { string unitsAbbreviationName = "MeasurementUnit." + units.ToString() + ".Abbreviation"; unitsAbbreviation = PdnResources.GetString(unitsAbbreviationName); numberFormat = "F2"; } else { unitsAbbreviation = string.Empty; numberFormat = "F0"; } string unitsString = PdnResources.GetString("MeasurementUnit." + units.ToString() + ".Plural"); string statusText = string.Format( this.statusTextFormat, offsetXPhysical.ToString(numberFormat), unitsAbbreviation, offsetYPhysical.ToString(numberFormat), unitsAbbreviation, offsetLengthPhysical.ToString("F2"), unitsString, angle.ToString("F2")); SetStatus(this.lineToolIcon, statusText); if (a == b) { return null; } else { PdnGraphicsPath path = new PdnGraphicsPath(); PointF[] spline = LineToSpline(a, b, controlPointCount); path.AddCurve(spline); path.Flatten(Utility.IdentityMatrix, flattenConstant); return path; } } }
protected override PdnGraphicsPath CreateShapePath(PointF[] points) { if (points.Length >= 4) { PdnGraphicsPath path = new PdnGraphicsPath(); switch (this.curveType) { default: case CurveType.Spline: path.AddCurve(points); break; case CurveType.Bezier: path.AddBezier(points[0], points[1], points[2], points[3]); break; } path.Flatten(Utility.IdentityMatrix, flattenConstant); return(path); } else //if (points.Length <= 2) { PointF a = points[0]; PointF b = points[points.Length - 1]; if (0 != (ModifierKeys & Keys.Shift) && a != b) { ConstrainPoints(ref a, ref b); } double angle = -180.0 * Math.Atan2(b.Y - a.Y, b.X - a.X) / Math.PI; MeasurementUnit units = AppWorkspace.Units; double offsetXPhysical = Document.PixelToPhysicalX(b.X - a.X, units); double offsetYPhysical = Document.PixelToPhysicalY(b.Y - a.Y, units); double offsetLengthPhysical = Math.Sqrt(offsetXPhysical * offsetXPhysical + offsetYPhysical * offsetYPhysical); string numberFormat; string unitsAbbreviation; if (units != MeasurementUnit.Pixel) { string unitsAbbreviationName = "MeasurementUnit." + units.ToString() + ".Abbreviation"; unitsAbbreviation = PdnResources.GetString(unitsAbbreviationName); numberFormat = "F2"; } else { unitsAbbreviation = string.Empty; numberFormat = "F0"; } string unitsString = PdnResources.GetString("MeasurementUnit." + units.ToString() + ".Plural"); string statusText = string.Format( this.statusTextFormat, offsetXPhysical.ToString(numberFormat), unitsAbbreviation, offsetYPhysical.ToString(numberFormat), unitsAbbreviation, offsetLengthPhysical.ToString("F2"), unitsString, angle.ToString("F2")); SetStatus(this.lineToolIcon, statusText); if (a == b) { return(null); } else { PdnGraphicsPath path = new PdnGraphicsPath(); PointF[] spline = LineToSpline(a, b, controlPointCount); path.AddCurve(spline); path.Flatten(Utility.IdentityMatrix, flattenConstant); return(path); } } }
protected override PdnGraphicsPath CreateShapePath(PointF[] points) { PointF a = points[0]; PointF b = points[points.Length - 1]; RectangleF rect; if ((ModifierKeys & Keys.Shift) != 0) { PointF dir = new PointF(b.X - a.X, b.Y - a.Y); float len = (float)Math.Sqrt(dir.X * dir.X + dir.Y * dir.Y); PointF center = new PointF((a.X + b.X) / 2.0f, (a.Y + b.Y) / 2.0f); float radius = len / 2.0f; rect = Utility.RectangleFromCenter(center, radius); } else { rect = Utility.PointsToRectangle(a, b); } if (rect.Width == 0 || rect.Height == 0) { return null; } PdnGraphicsPath path = new PdnGraphicsPath(); path.AddEllipse(rect); path.Flatten(Utility.IdentityMatrix, 0.10f); MeasurementUnit units = AppWorkspace.Units; double widthPhysical = Math.Abs(Document.PixelToPhysicalX(rect.Width, units)); double heightPhysical = Math.Abs(Document.PixelToPhysicalY(rect.Height, units)); double areaPhysical = Math.PI * (widthPhysical / 2.0) * (heightPhysical / 2.0); string numberFormat; string unitsAbbreviation; if (units != MeasurementUnit.Pixel) { string unitsAbbreviationName = "MeasurementUnit." + units.ToString() + ".Abbreviation"; unitsAbbreviation = PdnResources.GetString(unitsAbbreviationName); numberFormat = "F2"; } else { unitsAbbreviation = string.Empty; numberFormat = "F0"; } string unitsString = PdnResources.GetString("MeasurementUnit." + units.ToString() + ".Plural"); string statusText = string.Format( this.statusTextFormat, widthPhysical.ToString(numberFormat), unitsAbbreviation, heightPhysical.ToString(numberFormat), unitsAbbreviation, areaPhysical.ToString(numberFormat), unitsString); this.SetStatus(this.ellipseToolIcon, statusText); return path; }
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); this.Cursor = GetCursor(); if (tracking) { moveOriginMode = true; lastXY = new Point(e.X, e.Y); OnMouseMove(e); } else if ((e.Button & MouseButtons.Left) == MouseButtons.Left || (e.Button & MouseButtons.Right) == MouseButtons.Right) { tracking = true; hasMoved = false; startTime = DateTime.Now; tracePoints = new List <Point>(); tracePoints.Add(new Point(e.X, e.Y)); undoAction = new SelectionHistoryMemento("sentinel", this.Image, DocumentWorkspace); wasNotEmpty = !Selection.IsEmpty; // Determine this.combineMode if ((ModifierKeys & Keys.Control) != 0 && e.Button == MouseButtons.Left) { this.combineMode = CombineMode.Union; } else if ((ModifierKeys & Keys.Alt) != 0 && e.Button == MouseButtons.Left) { this.combineMode = CombineMode.Exclude; } else if ((ModifierKeys & Keys.Control) != 0 && e.Button == MouseButtons.Right) { this.combineMode = CombineMode.Xor; } else if ((ModifierKeys & Keys.Alt) != 0 && e.Button == MouseButtons.Right) { this.combineMode = CombineMode.Intersect; } else { this.combineMode = AppEnvironment.SelectionCombineMode; } DocumentWorkspace.EnableSelectionOutline = false; this.newSelection.Reset(); PdnGraphicsPath basePath = Selection.CreatePath(); this.newSelection.SetContinuation(basePath, CombineMode.Replace, true); this.newSelection.CommitContinuation(); bool newSelectionRendererVisible = true; // Act on this.combineMode switch (this.combineMode) { case CombineMode.Xor: append = true; Selection.ResetContinuation(); break; case CombineMode.Union: append = true; Selection.ResetContinuation(); break; case CombineMode.Exclude: append = true; Selection.ResetContinuation(); break; case CombineMode.Replace: append = false; Selection.Reset(); break; case CombineMode.Intersect: append = true; Selection.ResetContinuation(); break; default: throw new InvalidEnumArgumentException(); } this.newSelectionRenderer.Visible = newSelectionRendererVisible; } }
/// <summary> /// Override this function to return an "optimized" region that encompasses /// the shape's outline. For example, a circle would return a list of rectangles /// that traces the outline. This is necessary because normally simplification /// will produce a region that, for a circle's outline, encompasses its /// interior as well. If you return null, then the default simplification /// algorithm will be used. /// </summary> /// <param name="points"></param> /// <param name="path"></param> /// <returns></returns> protected virtual RectangleF[] GetOptimizedShapeOutlineRegion(PointF[] optimizeThesePoints, PdnGraphicsPath path) { return(null); }
protected void RenderShape() { // create the Pen we will use to draw with Pen outlinePen = null; Brush interiorBrush = null; PenInfo pi = AppEnvironment.PenInfo; BrushInfo bi = AppEnvironment.BrushInfo; ColorBgra primary = AppEnvironment.PrimaryColor; ColorBgra secondary = AppEnvironment.SecondaryColor; if (!ForceShapeDrawType && AppEnvironment.ShapeDrawType == ShapeDrawType.Interior) { Utility.Swap(ref primary, ref secondary); } // Initialize pens and brushes to the correct colors if ((mouseButton & MouseButtons.Left) == MouseButtons.Left) { outlinePen = pi.CreatePen(AppEnvironment.BrushInfo, primary.ToColor(), secondary.ToColor()); interiorBrush = bi.CreateBrush(secondary.ToColor(), primary.ToColor()); } else if ((mouseButton & MouseButtons.Right) == MouseButtons.Right) { outlinePen = pi.CreatePen(AppEnvironment.BrushInfo, secondary.ToColor(), primary.ToColor()); interiorBrush = bi.CreateBrush(primary.ToColor(), secondary.ToColor()); } if (!this.UseDashStyle) { outlinePen.DashStyle = DashStyle.Solid; } outlinePen.LineJoin = LineJoin.MiterClipped; outlinePen.MiterLimit = 2; // redraw the old saveSurface if (interiorSaveRegion != null) { RestoreRegion(interiorSaveRegion); interiorSaveRegion.Dispose(); interiorSaveRegion = null; } if (outlineSaveRegion != null) { RestoreRegion(outlineSaveRegion); outlineSaveRegion.Dispose(); outlineSaveRegion = null; } // anti-aliasing? Don't mind if I do if (AppEnvironment.AntiAliasing) { renderArgs.Graphics.SmoothingMode = SmoothingMode.AntiAlias; } else { renderArgs.Graphics.SmoothingMode = SmoothingMode.None; } // also set the pixel offset mode renderArgs.Graphics.PixelOffsetMode = GetPixelOffsetMode(); // figure out how we're going to draw ShapeDrawType drawType; if (ForceShapeDrawType) { drawType = ForcedShapeDrawType; } else { drawType = AppEnvironment.ShapeDrawType; } // get the region we want to save points = this.TrimShapePath(points); PointF[] pointsArray = points.ToArray(); PdnGraphicsPath shapePath = CreateShapePath(pointsArray); if (shapePath != null) { // create non-optimized interior region PdnRegion interiorRegion = new PdnRegion(shapePath); // create non-optimized outline region PdnRegion outlineRegion; using (PdnGraphicsPath outlinePath = (PdnGraphicsPath)shapePath.Clone()) { try { outlinePath.Widen(outlinePen); outlineRegion = new PdnRegion(outlinePath); } // Sometimes GDI+ gets cranky if we have a very small shape (e.g. all points // are coincident). catch (OutOfMemoryException) { outlineRegion = new PdnRegion(shapePath); } } // create optimized outlineRegion for purposes of rendering, if it is possible to do so // shapes will often provide an "optimized" region that circumvents the fact that // we'd otherwise get a region that encompasses the outline *and* the interior, thus // slowing rendering significantly in many cases. RectangleF[] optimizedOutlineRegion = GetOptimizedShapeOutlineRegion(pointsArray, shapePath); PdnRegion invalidOutlineRegion; if (optimizedOutlineRegion != null) { Utility.InflateRectanglesInPlace(optimizedOutlineRegion, (int)(outlinePen.Width + 2)); invalidOutlineRegion = Utility.RectanglesToRegion(optimizedOutlineRegion); } else { invalidOutlineRegion = Utility.SimplifyAndInflateRegion(outlineRegion, Utility.DefaultSimplificationFactor, (int)(outlinePen.Width + 2)); } // create optimized interior region PdnRegion invalidInteriorRegion = Utility.SimplifyAndInflateRegion(interiorRegion, Utility.DefaultSimplificationFactor, 3); PdnRegion invalidRegion = new PdnRegion(); invalidRegion.MakeEmpty(); // set up alpha blending renderArgs.Graphics.CompositingMode = AppEnvironment.GetCompositingMode(); SaveRegion(invalidOutlineRegion, invalidOutlineRegion.GetBoundsInt()); this.outlineSaveRegion = invalidOutlineRegion; if ((drawType & ShapeDrawType.Outline) != 0) { shapePath.Draw(renderArgs.Graphics, outlinePen); } invalidRegion.Union(invalidOutlineRegion); // draw shape if ((drawType & ShapeDrawType.Interior) != 0) { SaveRegion(invalidInteriorRegion, invalidInteriorRegion.GetBoundsInt()); this.interiorSaveRegion = invalidInteriorRegion; renderArgs.Graphics.FillPath(interiorBrush, shapePath); invalidRegion.Union(invalidInteriorRegion); } else { invalidInteriorRegion.Dispose(); invalidInteriorRegion = null; } bitmapLayer.Invalidate(invalidRegion); invalidRegion.Dispose(); invalidRegion = null; outlineRegion.Dispose(); outlineRegion = null; interiorRegion.Dispose(); interiorRegion = null; } Update(); if (shapePath != null) { shapePath.Dispose(); shapePath = null; } outlinePen.Dispose(); interiorBrush.Dispose(); }
public GraphicsPathWrapper(PdnGraphicsPath path) { this.points = (PointF[])path.PathPoints.Clone(); this.types = (byte[])path.PathTypes.Clone(); this.fillMode = path.FillMode; }
/// <summary> /// Provided as a special entry point so that Paste can work well. /// </summary> /// <param name="surface">What you want to paste.</param> /// <param name="offset">Where you want to paste it.</param> public void PasteMouseDown(SurfaceForClipboard sfc, Point offset) { if (this.context.lifted) { Drop(); } MaskedSurface pixels = sfc.MaskedSurface; PdnGraphicsPath pastePath = pixels.CreatePath(); PdnRegion pasteRegion = new PdnRegion(pastePath); PdnRegion simplifiedPasteRegion = Utility.SimplifyAndInflateRegion(pasteRegion); HistoryMemento bitmapAction = new BitmapHistoryMemento(Name, Image, DocumentWorkspace, ActiveLayerIndex, simplifiedPasteRegion); // SLOW (110ms) this.currentHistoryMementos.Add(bitmapAction); PushContextHistoryMemento(); this.context.seriesGuid = Guid.NewGuid(); this.context.currentMode = Mode.Translate; this.context.startEdge = Edge.None; this.context.startAngle = 0.0f; this.ourContext.LiftedPixels = pixels; this.context.lifted = true; this.context.liftTransform = new Matrix(); this.context.liftTransform.Reset(); this.context.deltaTransform = new Matrix(); this.context.deltaTransform.Reset(); this.context.offset = new Point(0, 0); bool oldDD = this.dontDrop; this.dontDrop = true; SelectionHistoryMemento sha = new SelectionHistoryMemento(null, null, DocumentWorkspace); this.currentHistoryMementos.Add(sha); Selection.PerformChanging(); Selection.Reset(); Selection.SetContinuation(pastePath, CombineMode.Replace, true); pastePath = null; Selection.CommitContinuation(); Selection.PerformChanged(); PushContextHistoryMemento(); this.context.liftedBounds = Selection.GetBoundsF(false); this.context.startBounds = this.context.liftedBounds; this.context.baseTransform = new Matrix(); this.context.baseTransform.Reset(); this.tracking = true; this.dontDrop = oldDD; this.didPaste = true; this.tracking = true; DestroyNubs(); PositionNubs(this.context.currentMode); // we use the value 70,000 to simulate mouse input because that's guaranteed to be out of bounds of where // the mouse can actually be -- PDN is limited to 65536 x 65536 images by design MouseEventArgs mea1 = new MouseEventArgs(MouseButtons.Left, 0, 70000, 70000, 0); MouseEventArgs mea2 = new MouseEventArgs(MouseButtons.Left, 0, 70000 + offset.X, 70000 + offset.Y, 0); this.context.startMouseXY = new Point(70000, 70000); OnMouseDown(mea1); OnMouseMove(mea2); // SLOW (200ms) OnMouseUp(mea2); }
protected override RectangleF[] GetOptimizedShapeOutlineRegion(PointF[] points, PdnGraphicsPath path) { return(Utility.SimplifyTrace(path.PathPoints)); }
public static Surface CreateThumbnail(Surface sourceSurface, PdnGraphicsPath maskPath, Rectangle bounds, int thumbSideLength) { Size thumbSize = Utility.ComputeThumbnailSize(bounds.Size, thumbSideLength); Surface thumb = new Surface(Math.Max(5, thumbSize.Width + 4), Math.Max(5, thumbSize.Height + 4)); thumb.Clear(ColorBgra.Transparent); thumb.Clear(new Rectangle(1, 1, thumb.Width - 2, thumb.Height - 2), ColorBgra.Black); Rectangle insetRect = new Rectangle(2, 2, thumb.Width - 4, thumb.Height - 4); Surface thumbInset = thumb.CreateWindow(insetRect); thumbInset.Clear(ColorBgra.Transparent); float scaleX = (float)thumbInset.Width / (float)bounds.Width; float scaleY = (float)thumbInset.Height / (float)bounds.Height; Matrix scaleMatrix = new Matrix(); scaleMatrix.Translate(-bounds.X, -bounds.Y, System.Drawing.Drawing2D.MatrixOrder.Append); scaleMatrix.Scale(scaleX, scaleY, System.Drawing.Drawing2D.MatrixOrder.Append); thumbInset.SuperSamplingFitSurface(sourceSurface); Surface maskInset = new Surface(thumbInset.Size); maskInset.Clear(ColorBgra.Black); using (RenderArgs maskInsetRA = new RenderArgs(maskInset)) { maskInsetRA.Graphics.SmoothingMode = SmoothingMode.AntiAlias; maskInsetRA.Graphics.Transform = scaleMatrix; maskInsetRA.Graphics.FillPath(Brushes.White, maskPath); maskInsetRA.Graphics.DrawPath(Pens.White, maskPath); } scaleMatrix.Dispose(); scaleMatrix = null; IntensityMaskOp maskOp = new IntensityMaskOp(); maskOp.Apply(maskInset, thumbInset, maskInset); UserBlendOps.NormalBlendOp normalOp = new UserBlendOps.NormalBlendOp(); thumbInset.ClearWithCheckboardPattern(); normalOp.Apply(thumbInset, thumbInset, maskInset); maskInset.Dispose(); maskInset = null; thumbInset.Dispose(); thumbInset = null; using (RenderArgs thumbRA = new RenderArgs(thumb)) { Utility.DrawDropShadow1px(thumbRA.Graphics, thumb.Bounds); } return thumb; }
// credit for the this function is given to Aaron Reginald http://www.codeproject.com/cs/media/ExtendedGraphics.asp protected PdnGraphicsPath GetRoundedRect(RectangleF baseRect, float radius) { // if corner radius is less than or equal to zero, // return the original rectangle if (radius <= 0.0f) { PdnGraphicsPath mPath = new PdnGraphicsPath(); mPath.AddRectangle(baseRect); mPath.CloseFigure(); return mPath; } // if the corner radius is greater than or equal to // half the width, or height (whichever is shorter) // then return a capsule instead of a lozenge if (radius >= (Math.Min(baseRect.Width, baseRect.Height)) / 2.0) { return GetCapsule(baseRect); } // create the arc for the rectangle sides and declare // a graphics path object for the drawing float diameter = radius * 2.0f; SizeF sizeF = new SizeF(diameter, diameter); RectangleF arc = new RectangleF(baseRect.Location, sizeF); PdnGraphicsPath path = new PdnGraphicsPath(); // top left arc path.AddArc (arc, 180, 90); // top right arc arc.X = baseRect.Right - diameter; path.AddArc (arc, 270, 90); // bottom right arc arc.Y = baseRect.Bottom - diameter; path.AddArc (arc, 0, 90); // bottom left arc arc.X = baseRect.Left; path.AddArc (arc, 90, 90); path.CloseFigure(); return path; }
protected override RectangleF[] GetOptimizedShapeOutlineRegion(PointF[] points, PdnGraphicsPath path) { return Utility.SimplifyTrace(path.PathPoints); }
// credit for the this function is given to Aaron Reginald http://www.codeproject.com/cs/media/ExtendedGraphics.asp private PdnGraphicsPath GetCapsule(RectangleF baseRect) { float diameter; RectangleF arc; PdnGraphicsPath path = new PdnGraphicsPath(); try { if (baseRect.Width>baseRect.Height) { // return horizontal capsule diameter = baseRect.Height; SizeF sizeF = new SizeF(diameter, diameter); arc = new RectangleF(baseRect.Location, sizeF); path.AddArc(arc, 90, 180); arc.X = baseRect.Right-diameter; path.AddArc(arc, 270, 180); } else if (baseRect.Width < baseRect.Height) { // return vertical capsule diameter = baseRect.Width; SizeF sizeF = new SizeF(diameter, diameter); arc = new RectangleF(baseRect.Location, sizeF); path.AddArc(arc, 180, 180); arc.Y = baseRect.Bottom-diameter; path.AddArc(arc, 0, 180); } else { // return circle path.AddEllipse(baseRect); } } catch (Exception) { path.AddEllipse(baseRect); } finally { path.CloseFigure(); } return path; }
public bool PerformAction() { bool success = true; if (this.documentWorkspace.Selection.IsEmpty || !(this.documentWorkspace.ActiveLayer is BitmapLayer)) { return(false); } try { using (new WaitCursorChanger(this.documentWorkspace)) { Utility.GCFullCollect(); PdnRegion selectionRegion = this.documentWorkspace.Selection.CreateRegion(); PdnGraphicsPath selectionOutline = this.documentWorkspace.Selection.CreatePath(); BitmapLayer activeLayer = (BitmapLayer)this.documentWorkspace.ActiveLayer; RenderArgs renderArgs = new RenderArgs(activeLayer.Surface); MaskedSurface maskedSurface = new MaskedSurface(renderArgs.Surface, selectionOutline); SurfaceForClipboard surfaceForClipboard = new SurfaceForClipboard(maskedSurface); Rectangle selectionBounds = Utility.GetRegionBounds(selectionRegion); if (selectionBounds.Width > 0 && selectionBounds.Height > 0) { Surface copySurface = new Surface(selectionBounds.Width, selectionBounds.Height); Bitmap copyBitmap = copySurface.CreateAliasedBitmap(); Bitmap copyOpaqueBitmap = new Bitmap(copySurface.Width, copySurface.Height, PixelFormat.Format24bppRgb); using (Graphics copyBitmapGraphics = Graphics.FromImage(copyBitmap)) { copyBitmapGraphics.Clear(Color.White); } maskedSurface.Draw(copySurface, -selectionBounds.X, -selectionBounds.Y); using (Graphics copyOpaqueBitmapGraphics = Graphics.FromImage(copyOpaqueBitmap)) { copyOpaqueBitmapGraphics.Clear(Color.White); copyOpaqueBitmapGraphics.DrawImage(copyBitmap, 0, 0); } DataObject dataObject = new DataObject(); dataObject.SetData(DataFormats.Bitmap, copyOpaqueBitmap); dataObject.SetData(surfaceForClipboard); int retryCount = 2; while (retryCount >= 0) { try { using (new WaitCursorChanger(this.documentWorkspace)) { Clipboard.SetDataObject(dataObject, true); } break; } catch { if (retryCount == 0) { success = false; Utility.ErrorBox(this.documentWorkspace, PdnResources.GetString("CopyAction.Error.TransferToClipboard")); } else { Thread.Sleep(200); } } finally { --retryCount; } } copySurface.Dispose(); copyBitmap.Dispose(); copyOpaqueBitmap.Dispose(); } selectionRegion.Dispose(); selectionOutline.Dispose(); renderArgs.Dispose(); maskedSurface.Dispose(); } } catch (OutOfMemoryException) { success = false; Utility.ErrorBox(this.documentWorkspace, PdnResources.GetString("CopyAction.Error.OutOfMemory")); } catch (Exception) { success = false; Utility.ErrorBox(this.documentWorkspace, PdnResources.GetString("CopyAction.Error.Generic")); } Utility.GCFullCollect(); return(success); }
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 " + Processor.NativeArchitecture.ToString().ToLower() + " OS"); Console.WriteLine("Processor: " + Processor.LogicalCpuCount + "x " + Processor.CpuName); 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(); }
/// <summary> /// Override this function to return an "optimized" region that encompasses /// the shape's outline. For example, a circle would return a list of rectangles /// that traces the outline. This is necessary because normally simplification /// will produce a region that, for a circle's outline, encompasses its /// interior as well. If you return null, then the default simplification /// algorithm will be used. /// </summary> /// <param name="points"></param> /// <param name="path"></param> /// <returns></returns> protected virtual RectangleF[] GetOptimizedShapeOutlineRegion(PointF[] optimizeThesePoints, PdnGraphicsPath path) { return null; }
private void OnMouseMoveImpl(MouseEventArgs e, StringBuilder sbLogger) { if (!this.tracking) { sbLogger.Append("1 "); Cursor cursor = this.moveToolCursor; for (int i = 0; i < this.moveNubs.Length; ++i) { sbLogger.Append("2 "); MoveNubRenderer nub = this.moveNubs[i]; sbLogger.Append("3 "); if (nub.Visible && nub.IsPointTouching(new Point(e.X, e.Y), true)) { sbLogger.Append("4 "); cursor = this.handCursor; break; } } this.Cursor = cursor; sbLogger.Append("5 "); } else { sbLogger.Append("6 "); if (this.context.currentMode != Mode.Translate) { sbLogger.Append("7 "); this.Cursor = this.handCursorMouseDown; } sbLogger.Append("8 "); Point newMouseXY = new Point(e.X, e.Y); Point newOffset = new Point(newMouseXY.X - context.startMouseXY.X, newMouseXY.Y - context.startMouseXY.Y); PreRender(); this.dontDrop = true; sbLogger.Append("9 "); Selection.PerformChanging(); using (Matrix translateMatrix = new Matrix()) { RectangleF rect; translateMatrix.Reset(); if (this.context.baseTransform != null) { Selection.SetInterimTransform(this.context.baseTransform); } Matrix interim = Selection.GetInterimTransformCopy(); switch (this.context.currentMode) { case Mode.Translate: translateMatrix.Translate((float)newOffset.X, (float)newOffset.Y, MatrixOrder.Append); break; case Mode.Rotate: rect = this.context.liftedBounds; PointF center = new PointF(rect.X + (rect.Width / 2.0f), rect.Y + (rect.Height / 2.0f)); center = Utility.TransformOnePoint(interim, center); double theta1 = Math.Atan2(context.startMouseXY.Y - center.Y, context.startMouseXY.X - center.X); double theta2 = Math.Atan2(e.Y - center.Y, e.X - center.X); double thetaDelta = theta2 - theta1; this.angleDelta = (float)(thetaDelta * (180.0f / Math.PI)); float angle = this.context.startAngle + this.angleDelta; if ((ModifierKeys & Keys.Shift) != 0) { angle = ConstrainAngle(angle); angleDelta = angle - this.context.startAngle; } translateMatrix.RotateAt(angleDelta, center, MatrixOrder.Append); this.rotateNub.Location = center; this.rotateNub.Angle = this.context.startAngle + angleDelta; break; case Mode.Scale: PointF xyAxes = GetEdgeVector(this.context.startEdge); PointF xAxis = new PointF(xyAxes.X, 0); PointF yAxis = new PointF(0, xyAxes.Y); PointF edgeX = Utility.TransformOneVector(interim, xAxis); PointF edgeY = Utility.TransformOneVector(interim, yAxis); PointF edgeXN = Utility.NormalizeVector2(edgeX); PointF edgeYN = Utility.NormalizeVector2(edgeY); PointF xu; float xulen; PointF xv; Utility.GetProjection((PointF)newOffset, edgeXN, out xu, out xulen, out xv); PointF yu; float yulen; PointF yv; Utility.GetProjection((PointF)newOffset, edgeYN, out yu, out yulen, out yv); PdnGraphicsPath startPath2 = this.context.startPath.Clone(); RectangleF sp2Bounds = startPath2.GetBounds(); PointF sp2BoundsCenter = new PointF((sp2Bounds.Left + sp2Bounds.Right) / 2.0f, (sp2Bounds.Top + sp2Bounds.Bottom) / 2.0f); float tAngle = Utility.GetAngleOfTransform(interim); bool isFlipped = Utility.IsTransformFlipped(interim); using (Matrix spm = new Matrix()) { spm.Reset(); spm.RotateAt(-tAngle, sp2BoundsCenter, MatrixOrder.Append); translateMatrix.RotateAt(-tAngle, sp2BoundsCenter, MatrixOrder.Append); startPath2.Transform(spm); } RectangleF spBounds2 = startPath2.GetBounds(); startPath2.Dispose(); startPath2 = null; float xTranslate; float yTranslate; bool allowConstrain; Edge theEdge = this.context.startEdge; // If the transform is flipped, then GetTransformAngle will return 180 degrees // even though no rotation has actually taken place. Thus we have to scratch // our head and go "hmm, let's make some adjustments to this." Otherwise stretching // the top and bottom nubs goes in the wrong direction. if (isFlipped) { theEdge = FlipEdgeVertically(theEdge); } switch (theEdge) { default: throw new InvalidEnumArgumentException(); case Edge.TopLeft: allowConstrain = true; xTranslate = -spBounds2.X - spBounds2.Width; yTranslate = -spBounds2.Y - spBounds2.Height; break; case Edge.Top: allowConstrain = false; xTranslate = 0; yTranslate = -spBounds2.Y - spBounds2.Height; break; case Edge.TopRight: allowConstrain = true; xTranslate = -spBounds2.X; yTranslate = -spBounds2.Y - spBounds2.Height; break; case Edge.Left: allowConstrain = false; xTranslate = -spBounds2.X - spBounds2.Width; yTranslate = 0; break; case Edge.Right: allowConstrain = false; xTranslate = -spBounds2.X; yTranslate = 0; break; case Edge.BottomLeft: allowConstrain = true; xTranslate = -spBounds2.X - spBounds2.Width; yTranslate = -spBounds2.Y; break; case Edge.Bottom: allowConstrain = false; xTranslate = 0; yTranslate = -spBounds2.Y; break; case Edge.BottomRight: allowConstrain = true; xTranslate = -spBounds2.X; yTranslate = -spBounds2.Y; break; } translateMatrix.Translate(xTranslate, yTranslate, MatrixOrder.Append); float newWidth = spBounds2.Width + xulen; float newHeight = spBounds2.Height + yulen; float xScale = newWidth / spBounds2.Width; float yScale = newHeight / spBounds2.Height; if (allowConstrain && (this.ModifierKeys & Keys.Shift) != 0) { ConstrainScaling(this.context.liftedBounds, spBounds2.Width, spBounds2.Height, newWidth, newHeight, out xScale, out yScale); } translateMatrix.Scale(xScale, yScale, MatrixOrder.Append); translateMatrix.Translate(-xTranslate, -yTranslate, MatrixOrder.Append); translateMatrix.RotateAt(+tAngle, sp2BoundsCenter, MatrixOrder.Append); break; default: throw new InvalidEnumArgumentException(); } this.context.deltaTransform.Reset(); this.context.deltaTransform.Multiply(this.context.liftTransform, MatrixOrder.Append); this.context.deltaTransform.Multiply(translateMatrix, MatrixOrder.Append); translateMatrix.Multiply(this.context.baseTransform, MatrixOrder.Prepend); Selection.SetInterimTransform(translateMatrix); interim.Dispose(); interim = null; } // advertise our angle of rotation to any host (i.e. mainform) that might want to use that information this.hostShouldShowAngle = this.rotateNub.Visible; this.hostAngle = -this.rotateNub.Angle; Selection.PerformChanged(); dontDrop = false; Render(newOffset, true); Update(); sbLogger.Append("a "); this.context.offset = newOffset; sbLogger.Append("b "); if (this.enableOutline) { DocumentWorkspace.ResetOutlineWhiteOpacity(); } sbLogger.Append("c "); } sbLogger.Append("d "); }