public void RenderInPlace(RenderArgs srcAndDstArgs, Rectangle roi) { using (PdnRegion region = new PdnRegion(roi)) { RenderInPlace(srcAndDstArgs, region); } }
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); } }
public EffectConfigDialog() { InitializeComponent(); InitialInitToken(); effectSelection = new PdnRegion(); effectSelection.MakeInfinite(); }
/// <summary> /// Constructs an outline of the given region with the given bounds /// and scaling factor. /// </summary> /// <param name="region"> /// The selection to approximate. /// </param> /// <param name="bounds"> /// The boundaries of the image. /// </param> /// <param name="scalingMultiplier"> /// The amount to scale the size of the outline by. /// </param> public static PdnRegion ConstructOutline( this PdnRegion region, RectangleF bounds, float scalingMultiplier) { GraphicsPath path = new GraphicsPath(); PdnRegion newRegion = region.Clone(); //The size to scale the region by. Matrix scalematrix = new Matrix( bounds, new PointF[] { new PointF(bounds.Left, bounds.Top), new PointF(bounds.Right * scalingMultiplier, bounds.Top), new PointF(bounds.Left, bounds.Bottom * scalingMultiplier) }); newRegion.Transform(scalematrix); //Makes the new region slightly larger by inflating rectangles. foreach (RectangleF rect in newRegion.GetRegionScans()) { path.AddRectangle(RectangleF.Inflate(rect, 1, 1)); } //Subtracts the old region, leaving an outline from the expansion. PdnRegion result = new PdnRegion(path); result.Exclude(newRegion); return(result); }
private void Constructor() { InitializeComponent(); InitialInitToken(); effectSelection = new PdnRegion(); effectSelection.MakeInfinite(); }
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(); } } }
public EffectEnvironmentParameters(ColorBgra primaryColor, ColorBgra secondaryColor, float brushWidth, PdnRegion selection) { this.primaryColor = primaryColor; this.secondaryColor = secondaryColor; this.brushWidth = brushWidth; this.selection = (PdnRegion)selection.Clone(); }
public BackgroundEffectRenderer(Effect effect, EffectConfigToken effectToken, RenderArgs dstArgs, RenderArgs srcArgs, PdnRegion renderRegion, IRenderer <ColorAlpha8> clipMaskRenderer, int tileCount, int workerThreads) { this.effect = effect; this.effectToken = effectToken; this.dstArgs = dstArgs; this.srcArgs = srcArgs; this.renderRegion = renderRegion; this.renderRegion.Intersect(dstArgs.Bounds); this.tileCount = tileCount; if (effect.CheckForEffectFlags(EffectFlags.None | EffectFlags.SingleRenderCall)) { this.tileCount = 1; } this.tileRegions = this.SliceUpRegion(renderRegion, this.tileCount, dstArgs.Bounds); this.tilePdnRegions = new PdnRegion[this.tileRegions.Length]; for (int i = 0; i < this.tileRegions.Length; i++) { this.tilePdnRegions[i] = PdnRegion.FromRectangles(this.tileRegions[i]); } this.workerThreads = workerThreads; if (effect.CheckForEffectFlags(EffectFlags.None | EffectFlags.SingleThreaded)) { this.workerThreads = 1; } this.clipMaskRenderer = clipMaskRenderer; this.threadPool = new EffectRendererWorkItemQueue(WorkItemDispatcher.Default, WorkItemQueuePriority.Normal, workerThreads); }
private Rectangle[][] SliceUpRegion(PdnRegion region, int sliceCount, Rectangle layerBounds) { if (sliceCount <= 0) { throw new ArgumentOutOfRangeException("sliceCount"); } Rectangle[][] rectangleArray = new Rectangle[sliceCount][]; Scanline[] regionScanlines = GetRegionScanlines(region.GetRegionScansReadOnlyInt()); for (int i = 0; i < sliceCount; i++) { int num2 = (regionScanlines.Length * i) / sliceCount; int num3 = Math.Min(regionScanlines.Length, (regionScanlines.Length * (i + 1)) / sliceCount); if (sliceCount > 1) { switch (i) { case 0: num3 = Math.Min(num3, num2 + 1); break; case 1: num2 = Math.Min(num2, 1); break; } } Rectangle[] scans = ScanlinesToRectangles(regionScanlines, num2, num3 - num2); for (int j = 0; j < scans.Length; j++) { scans[j].Intersect(layerBounds); } rectangleArray[i] = this.ConsolidateRects(scans); } return(rectangleArray); }
protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (mouseDown) { OnMouseMove(e); mouseDown = false; if (savedRects.Count > 0) { Rectangle[] savedScans = this.savedRects.ToArray(); PdnRegion saveMeRegion = Utility.RectanglesToRegion(savedScans); HistoryMemento ha = new BitmapHistoryMemento(Name, Image, DocumentWorkspace, ActiveLayerIndex, saveMeRegion, ScratchSurface); HistoryStack.PushNewMemento(ha); saveMeRegion.Dispose(); this.savedRects.Clear(); ClearSavedMemory(); } tracePoints = null; } }
private void RenderImpl() { int threadCount = BackRenderer.WorkerThreads; int start = ThreadNumber + (StartOffset * threadCount); int max = BackRenderer.TileCount; //try { for (int tile = start; tile < max; tile += threadCount) { if (BackRenderer.ThreadShouldStop) { BackRenderer.Aborted = true; break; } Rectangle[] subRegion = BackRenderer.TileRegions[tile]; BackRenderer.Effect.Render(Token, BackRenderer.DstArgs, BackRenderer.SrcArgs, subRegion); PdnRegion subPdnRegion = BackRenderer.TilePdnRegions[tile]; BackRenderer.OnRenderedTile(new RenderedTileEventArgs(subPdnRegion, BackRenderer.TileCount, tile)); } } //catch (Exception ex) { //BackRenderer.Exceptions.Add(ex); } }
public void RenderText(PdnRegion selection, Settings settings) { var selectionRegion = selection; Bounds = selectionRegion.GetBoundsInt(); try { TypeSetter setter = new TypeSetter(settings, selectionRegion); setter.SetText(); setter.AlignText(); Renderer renderer = new Renderer(settings, selectionRegion); Bitmap resultImage = renderer.Draw(setter.Lines); #if DEBUG resultImage.Save("C:\\dev\\redo_bm.png", ImageFormat.Png); #endif BufferSurface = Surface.CopyFromBitmap(resultImage); } catch (OutOfMemoryException) { //scale back anti-aliasing if (settings.AntiAliasLevel > 1) { settings.AntiAliasLevel--; } } }
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; }
private Rectangle[][] SliceUpRegion(PdnRegion region, int sliceCount, Rectangle layerBounds) { Rectangle[][] slices = new Rectangle[sliceCount][]; Rectangle[] regionRects = region.GetRegionScansReadOnlyInt(); Scanline[] regionScans = Utility.GetRegionScans(regionRects); for (int i = 0; i < sliceCount; ++i) { int beginScan = (regionScans.Length * i) / sliceCount; int endScan = Math.Min(regionScans.Length, (regionScans.Length * (i + 1)) / sliceCount); // Try to arrange it such that the maximum size of the first region // is 1-pixel tall if (i == 0) { endScan = Math.Min(endScan, beginScan + 1); } else if (i == 1) { beginScan = Math.Min(beginScan, 1); } Rectangle[] newRects = Utility.ScanlinesToRectangles(regionScans, beginScan, endScan - beginScan); for (int j = 0; j < newRects.Length; ++j) { newRects[j].Intersect(layerBounds); } slices[i] = newRects; } return(slices); }
public BackgroundEffectRenderer(Effect effect, EffectConfigToken effectToken, RenderArgs dstArgs, RenderArgs srcArgs, PdnRegion renderRegion, int tileCount, int workerThreads) { this.effect = effect; this.effectToken = effectToken; this.dstArgs = dstArgs; this.srcArgs = srcArgs; this.renderRegion = renderRegion; this.renderRegion.Intersect(dstArgs.Bounds); this.tileRegions = SliceUpRegion(renderRegion, tileCount, dstArgs.Bounds); this.tilePdnRegions = new PdnRegion[this.tileRegions.Length]; for (int i = 0; i < this.tileRegions.Length; ++i) { PdnRegion pdnRegion = Utility.RectanglesToRegion(this.tileRegions[i]); this.tilePdnRegions[i] = pdnRegion; } this.tileCount = tileCount; this.workerThreads = workerThreads; if ((effect.EffectDirectives & EffectDirectives.SingleThreaded) != 0) { this.workerThreads = 1; } this.threadPool = new Threading.ThreadPool(this.workerThreads, false); }
private void CommitGradient() { if (!this.gradientActive) { throw new InvalidOperationException("CommitGradient() called when a gradient was not active"); } RenderGradient(); using (PdnRegion clipRegion = DocumentWorkspace.Selection.CreateRegion()) { BitmapHistoryMemento bhm = new BitmapHistoryMemento( StaticName, StaticImage, DocumentWorkspace, DocumentWorkspace.ActiveLayerIndex, clipRegion, this.ScratchSurface); this.historyMemento.PushNewAction(bhm); // We assume this.historyMemento has already been pushed on to the HistoryStack this.historyMemento = null; } this.startNub.Visible = false; this.endNub.Visible = false; ClearSavedRegion(); ClearSavedMemory(); this.gradientActive = false; SetStatus(this.toolIcon, this.helpTextInitial); }
private void RenderImpl() { int inc = ber.workerThreads; int start = this.threadNumber + (this.startOffset * inc); int max = ber.tileCount; try { for (int tile = start; tile < max; tile += inc) { if (ber.threadShouldStop) { this.ber.aborted = true; break; } Rectangle[] subRegion = ber.tileRegions[tile]; ber.effect.Render(this.token, ber.dstArgs, ber.srcArgs, subRegion); PdnRegion subPdnRegion = ber.tilePdnRegions[tile]; ber.OnRenderedTile(new RenderedTileEventArgs(subPdnRegion, ber.tileCount, tile)); } } catch (Exception ex) { ber.exceptions.Add(ex); } }
public override void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length) { if (needReRender == false || length == 0) { return; } needReRender = false; PdnRegion selection = EnvironmentParameters.GetSelectionAsPdnRegion(); using (Surface tmp = new Surface(srcArgs.Size)) { tmp.CopySurface(srcArgs.Surface); Effect effect = null; EffectConfigToken token = null; int count = this.effects.Count; for (int i = 0; i < count; i++) { effect = this.effects[i]; token = this.dialogs[i]?.EffectToken; effect.SetRenderInfo(token, dstArgs, new RenderArgs(tmp)); effect.Render(token, dstArgs, new RenderArgs(tmp), selection); tmp.CopySurface(dstArgs.Surface); } dstArgs.Surface.CopySurface(tmp); } }
public static PdnRegion GetOutline(this PdnRegion region, RectangleF bounds, float scalefactor) { GraphicsPath path = new GraphicsPath(); PdnRegion region2 = region.Clone(); Matrix scalematrix = new Matrix( bounds, new PointF[] { new PointF(bounds.Left, bounds.Top), new PointF(bounds.Right * scalefactor, bounds.Top), new PointF(bounds.Left, bounds.Bottom * scalefactor) }); region2.Transform(scalematrix); foreach (RectangleF rect in region2.GetRegionScans()) { path.AddRectangle(RectangleF.Inflate(rect, 1, 1)); } PdnRegion retval = new PdnRegion(path); retval.Exclude(region2); return(retval); }
public Renderer(Settings settings, PdnRegion selectionRegion) { //convert to AA space selectionBounds = selectionRegion.GetBoundsInt(); var scaledBounds = selectionBounds.Multiply(settings.AntiAliasLevel); font = settings.GetAntiAliasSizeFont(); image = new Bitmap(scaledBounds.Width, scaledBounds.Height); graphics = Graphics.FromImage(image); graphics.Clear(Color.Black); graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; this.settings = settings; //map color black to transparent ColorMap[] colorMap = { new ColorMap { OldColor = Color.Black, NewColor = Color.Transparent } }; imageAttributes = new ImageAttributes(); imageAttributes.SetRemapTable(colorMap); }
protected override void OnStylusUp(StylusEventArgs e) { base.OnStylusUp(e); Cursor = cursorMouseUp; if (mouseDown) { this.previewRenderer.Visible = true; mouseDown = false; if (this.savedRects.Count > 0) { PdnRegion saveMeRegion = Utility.RectanglesToRegion(this.savedRects.ToArray()); HistoryMemento ha = new BitmapHistoryMemento(Name, Image, DocumentWorkspace, ActiveLayerIndex, saveMeRegion, this.ScratchSurface); HistoryStack.PushNewMemento(ha); saveMeRegion.Dispose(); this.savedRects.Clear(); this.ClearSavedMemory(); } this.brush.Dispose(); this.brush = null; } }
public BitmapHistoryMemento(string name, ImageResource image, IHistoryWorkspace historyWorkspace, int layerIndex, PdnRegion changedRegion, Surface copyFromThisSurface) : base(name, image) { this.historyWorkspace = historyWorkspace; this.layerIndex = layerIndex; PdnRegion region = changedRegion.Clone(); this.tempFileName = FileSystem.GetTempFileName(); FileStream outputStream = null; try { outputStream = FileSystem.OpenStreamingFile(this.tempFileName, FileAccess.Write); SaveSurfaceRegion(outputStream, copyFromThisSurface, region); } finally { if (outputStream != null) { outputStream.Dispose(); outputStream = null; } } this.tempFileHandle = new DeleteFileOnFree(this.tempFileName); BitmapHistoryMementoData data = new BitmapHistoryMementoData(null, region); this.Data = data; }
public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace) { if (historyWorkspace.Selection.IsEmpty) { return(null); } PdnRegion region = historyWorkspace.Selection.CreateRegion(); BitmapLayer layer = ((BitmapLayer)historyWorkspace.ActiveLayer); PdnRegion simplifiedRegion = Utility.SimplifyAndInflateRegion(region); HistoryMemento hm = new BitmapHistoryMemento( StaticName, StaticImage, historyWorkspace, historyWorkspace.ActiveLayerIndex, simplifiedRegion); EnterCriticalRegion(); layer.Surface.Clear(region, this.fillColor); layer.Invalidate(simplifiedRegion); simplifiedRegion.Dispose(); region.Dispose(); return(hm); }
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (mouseDown) { return; } if (((e.Button & MouseButtons.Left) == MouseButtons.Left) || ((e.Button & MouseButtons.Right) == MouseButtons.Right)) { mouseDown = true; mouseButton = e.Button; tracePoints = new List <Point>(); bitmapLayer = (BitmapLayer)ActiveLayer; renderArgs = new RenderArgs(bitmapLayer.Surface); clipRegion?.Dispose(); clipRegion = null; clipRegion = Selection.CreateRegion(); renderArgs.Graphics.SetClip(clipRegion.GetRegionReadOnly(), CombineMode.Replace); OnMouseMove(e); } }
protected override void OnDeactivate() { base.OnDeactivate(); pencilToolCursor?.Dispose(); pencilToolCursor = null; if (mouseDown) { Point lastTracePoint = (Point)tracePoints[tracePoints.Count - 1]; OnMouseUp(new MouseEventArgs(mouseButton, 0, lastTracePoint.X, lastTracePoint.Y, 0)); } this.savedRects = null; this.tracePoints = null; this.bitmapLayer = null; renderArgs?.Dispose(); renderArgs = null; this.mouseDown = false; clipRegion?.Dispose(); clipRegion = null; }
protected override void OnSetRenderInfo(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs) { base.OnSetRenderInfo(parameters, dstArgs, srcArgs); PdnRegion rgn = EnvironmentParameters.GetSelection(EnvironmentParameters.SourceSurface.Bounds); bounds = rgn.GetBoundsInt(); }
public EffectEnvironmentParameters(ColorBgra primaryColor, ColorBgra secondaryColor, float brushWidth, PdnRegion selection, Surface sourceSurface) { this.PrimaryColor = primaryColor; this.SecondaryColor = secondaryColor; this.BrushWidth = brushWidth; this.selection = (PdnRegion)selection.Clone(); this.SourceSurface = sourceSurface; }
private void RepeatEffectMenuItem_Click(object sender, EventArgs e) { Exception exception = null; Effect effect = null; DocumentWorkspace activeDW = AppWorkspace.ActiveDocumentWorkspace; if (activeDW != null) { using (new PushNullToolMode(activeDW)) { Surface copy = activeDW.BorrowScratchSurface(this.GetType() + ".RepeatEffectMenuItem_Click() utilizing scratch for rendering"); try { using (new WaitCursorChanger(AppWorkspace)) { copy.CopySurface(((BitmapLayer)activeDW.ActiveLayer).Surface); } PdnRegion selectedRegion = activeDW.Selection.CreateRegion(); EffectEnvironmentParameters eep = new EffectEnvironmentParameters( AppWorkspace.AppEnvironment.PrimaryColor, AppWorkspace.AppEnvironment.SecondaryColor, AppWorkspace.AppEnvironment.PenInfo.Width, selectedRegion, copy); effect = (Effect)Activator.CreateInstance(this.lastEffect.GetType()); effect.EnvironmentParameters = eep; EffectConfigToken token; if (this.lastEffectToken == null) { token = null; } else { token = (EffectConfigToken)this.lastEffectToken.Clone(); } DoEffect(effect, token, selectedRegion, selectedRegion, copy, out exception); } finally { activeDW.ReturnScratchSurface(copy); } } } if (exception != null) { HandleEffectException(AppWorkspace, effect, exception); } }
public BitmapHistoryMementoData(IrregularSurface undoImage, PdnRegion savedRegion) { if (undoImage != null && savedRegion != null) { throw new ArgumentException("Only one of undoImage or savedRegion may be non-null"); } this.UndoImage = undoImage; this.SavedRegion = savedRegion; }
protected override void OnSelectionChanged() { if (this.clipRegion != null) { this.clipRegion.Dispose(); this.clipRegion = null; } base.OnSelectionChanged(); }
public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace) { if (this.layerIndex < 1 || this.layerIndex >= historyWorkspace.Document.Layers.Count) { throw new ArgumentException("layerIndex must be greater than or equal to 1, and a valid layer index. layerIndex=" + layerIndex + ", allowableRange=[0," + historyWorkspace.Document.Layers.Count + ")"); } int bottomLayerIndex = this.layerIndex - 1; Rectangle bounds = historyWorkspace.Document.Bounds; PdnRegion region = new PdnRegion(bounds); BitmapHistoryMemento bhm = new BitmapHistoryMemento( null, null, historyWorkspace, bottomLayerIndex, region); BitmapLayer topLayer = (BitmapLayer)historyWorkspace.Document.Layers[this.layerIndex]; BitmapLayer bottomLayer = (BitmapLayer)historyWorkspace.Document.Layers[bottomLayerIndex]; RenderArgs bottomRA = new RenderArgs(bottomLayer.Surface); EnterCriticalRegion(); topLayer.Render(bottomRA, region); bottomLayer.Invalidate(); bottomRA.Dispose(); bottomRA = null; region.Dispose(); region = null; DeleteLayerFunction dlf = new DeleteLayerFunction(this.layerIndex); HistoryMemento dlhm = dlf.Execute(historyWorkspace); CompoundHistoryMemento chm = new CompoundHistoryMemento(StaticName, StaticImage, new HistoryMemento[] { bhm, dlhm }); return chm; }
private void Dispose(bool disposing) { if (disposing) { if (this.selection != null) { this.selection.Dispose(); this.selection = null; } } }
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (mouseDown) { return; } if (BtnDownMouseLeft(e) || BtnDownMouseRight(e)) { this.previewRenderer.Visible = false; mouseDown = true; Cursor = cursorMouseDown; if ((!KeyDownControlOnly()) && (!KeyDownShiftOnly())) { mouseButton = e.Button; lastMouseXY.X = e.X; lastMouseXY.Y = e.Y; // parses and establishes the active selection area if (clipRegion != null) { clipRegion.Dispose(); clipRegion = null; } clipRegion = Selection.CreateRegion(); renderArgs.Graphics.SetClip(clipRegion.GetRegionReadOnly(), CombineMode.Replace); // find the replacement color and the color to replace colorReplacing = AppEnvironment.PrimaryColor; colorToReplace = AppEnvironment.SecondaryColor; penWidth = AppEnvironment.PenInfo.Width; // get the pen width find the ceiling integer of half of the pen width ceilingPenWidth = (int)Math.Max(Math.Ceiling(penWidth), 3); // used only for cursor positioning halfPenWidth = (int)Math.Ceiling(penWidth / 2.0f); // set hasDrawn to false since nothing has been drawn hasDrawn = false; // render the circle via GDI+ so the AA techniques can precisely // mimic GDI+. this.brushRenderArgs = RenderCircleBrush(); // establish tolerance myTolerance = (int)(AppEnvironment.Tolerance * 256); // restrict tolerance so no overlap is permitted RestrictTolerance(); OnMouseMove(e); } else { modifierDown = ModifierKeys; OnMouseMove(e); } } }
protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp(e); if (!KeyDownShiftOnly() && !KeyDownControlOnly()) { Cursor = cursorMouseUp; } if (mouseDown) { this.previewRenderer.Visible = true; OnMouseMove(e); if (savedSurfaces.Count > 0) { PdnRegion saveMeRegion = new PdnRegion(); saveMeRegion.MakeEmpty(); foreach (PlacedSurface pi1 in savedSurfaces) { saveMeRegion.Union(pi1.Bounds); } PdnRegion simplifiedRegion = Utility.SimplifyAndInflateRegion(saveMeRegion); using (IrregularSurface weDrewThis = new IrregularSurface(renderArgs.Surface, simplifiedRegion)) { for (int i = savedSurfaces.Count - 1; i >= 0; --i) { PlacedSurface ps = (PlacedSurface)savedSurfaces[i]; ps.Draw(renderArgs.Surface); ps.Dispose(); } savedSurfaces.Clear(); if (hasDrawn) { HistoryMemento ha = new BitmapHistoryMemento(Name, Image, DocumentWorkspace, ActiveLayerIndex, simplifiedRegion); weDrewThis.Draw(bitmapLayer.Surface); HistoryStack.PushNewMemento(ha); } } } mouseDown = false; modifierDown = 0; } if (brushRenderArgs != null) { if (brushRenderArgs.Surface != null) { brushRenderArgs.Surface.Dispose(); } } }
public void RunEffect(Type effectType) { bool oldDirtyValue = AppWorkspace.ActiveDocumentWorkspace.Document.Dirty; bool resetDirtyValue = false; AppWorkspace.Update(); // make sure the window is done 'closing' AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar(); DocumentWorkspace activeDW = AppWorkspace.ActiveDocumentWorkspace; PdnRegion selectedRegion; if (activeDW.Selection.IsEmpty) { selectedRegion = new PdnRegion(activeDW.Document.Bounds); } else { selectedRegion = activeDW.Selection.CreateRegion(); } BitmapLayer layer = (BitmapLayer)activeDW.ActiveLayer; using (new PushNullToolMode(activeDW)) { try { Effect effect = (Effect)Activator.CreateInstance(effectType); EffectEnvironmentParameters eep = new EffectEnvironmentParameters( AppWorkspace.AppEnvironment.PrimaryColor, AppWorkspace.AppEnvironment.SecondaryColor, AppWorkspace.AppEnvironment.PenInfo.Width, selectedRegion); string name = effect.Name; EffectConfigToken newLastToken = null; effect.EnvironmentParameters = eep; if (!(effect.IsConfigurable)) { Surface copy = activeDW.BorrowScratchSurface(this.GetType() + ".RunEffect() using scratch surface for non-configurable rendering"); try { using (new WaitCursorChanger(AppWorkspace)) { copy.CopySurface(layer.Surface); } DoEffect(effect, null, selectedRegion, selectedRegion, copy); } finally { activeDW.ReturnScratchSurface(copy); } } else { PdnRegion previewRegion = (PdnRegion)selectedRegion.Clone(); previewRegion.Intersect(RectangleF.Inflate(activeDW.VisibleDocumentRectangleF, 1, 1)); Surface originalSurface = activeDW.BorrowScratchSurface(this.GetType() + ".RunEffect() using scratch surface for rendering during configuration"); try { using (new WaitCursorChanger(AppWorkspace)) { originalSurface.CopySurface(layer.Surface); } // AppWorkspace.SuspendThumbnailUpdates(); // using (EffectConfigDialog configDialog = effect.CreateConfigDialog()) { configDialog.Opacity = 0.9; configDialog.Effect = effect; configDialog.EffectSourceSurface = originalSurface; configDialog.Selection = selectedRegion; EventHandler eh = new EventHandler(EffectConfigTokenChangedHandler); configDialog.EffectTokenChanged += eh; if (this.effectTokens.ContainsKey(effectType)) { EffectConfigToken oldToken = (EffectConfigToken)effectTokens[effectType].Clone(); configDialog.EffectToken = oldToken; } BackgroundEffectRenderer ber = new BackgroundEffectRenderer( effect, configDialog.EffectToken, new RenderArgs(layer.Surface), new RenderArgs(originalSurface), previewRegion, tilesPerCpu * renderingThreadCount, renderingThreadCount); ber.RenderedTile += new RenderedTileEventHandler(RenderedTileHandler); ber.StartingRendering += new EventHandler(StartingRenderingHandler); ber.FinishedRendering += new EventHandler(FinishedRenderingHandler); configDialog.Tag = ber; invalidateTimer.Enabled = true; DialogResult dr = Utility.ShowDialog(configDialog, AppWorkspace); invalidateTimer.Enabled = false; this.InvalidateTimer_Tick(invalidateTimer, EventArgs.Empty); if (dr == DialogResult.OK) { this.effectTokens[effectType] = (EffectConfigToken)configDialog.EffectToken.Clone(); } using (new WaitCursorChanger(AppWorkspace)) { ber.Abort(); ber.Join(); ber.Dispose(); ber = null; if (dr != DialogResult.OK) { ((BitmapLayer)activeDW.ActiveLayer).Surface.CopySurface(originalSurface); activeDW.ActiveLayer.Invalidate(); } configDialog.EffectTokenChanged -= eh; configDialog.Hide(); AppWorkspace.Update(); previewRegion.Dispose(); } // AppWorkspace.ResumeThumbnailUpdates(); // if (dr == DialogResult.OK) { PdnRegion remainingToRender = selectedRegion.Clone(); PdnRegion alreadyRendered = PdnRegion.CreateEmpty(); for (int i = 0; i < this.progressRegions.Length; ++i) { if (this.progressRegions[i] == null) { break; } else { remainingToRender.Exclude(this.progressRegions[i]); alreadyRendered.Union(this.progressRegions[i]); } } activeDW.ActiveLayer.Invalidate(alreadyRendered); newLastToken = (EffectConfigToken)configDialog.EffectToken.Clone(); AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar(); DoEffect(effect, newLastToken, selectedRegion, remainingToRender, originalSurface); } else // if (dr == DialogResult.Cancel) { using (new WaitCursorChanger(AppWorkspace)) { activeDW.ActiveLayer.Invalidate(); Utility.GCFullCollect(); } resetDirtyValue = true; return; } } } finally { activeDW.ReturnScratchSurface(originalSurface); } } // if it was from the Effects menu, save it as the "Repeat ...." item if (effect.Category == EffectCategory.Effect) { this.lastEffect = effect; if (newLastToken == null) { this.lastEffectToken = null; } else { this.lastEffectToken = (EffectConfigToken)newLastToken.Clone(); } PopulateMenu(true); } } finally { selectedRegion.Dispose(); AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar(); AppWorkspace.Widgets.StatusBarProgress.EraseProgressStatusBar(); AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = true; for (int i = 0; i < this.progressRegions.Length; ++i) { if (this.progressRegions[i] != null) { this.progressRegions[i].Dispose(); this.progressRegions[i] = null; } } if (resetDirtyValue) { AppWorkspace.ActiveDocumentWorkspace.Document.Dirty = oldDirtyValue; } } } }
public static unsafe void FillStencilFromPoint(Surface surface, IBitVector2D stencil, Point start, int tolerance, out Rectangle boundingBox, PdnRegion limitRegion, bool limitToSelection) { ColorBgra cmp = surface[start]; int top = int.MaxValue; int bottom = int.MinValue; int left = int.MaxValue; int right = int.MinValue; Rectangle[] scans; stencil.Clear(false); if (limitToSelection) { using (PdnRegion excluded = new PdnRegion(new Rectangle(0, 0, stencil.Width, stencil.Height))) { excluded.Xor(limitRegion); scans = excluded.GetRegionScansReadOnlyInt(); } } else { scans = new Rectangle[0]; } foreach (Rectangle rect in scans) { stencil.Set(rect, true); } Queue<Point> queue = new Queue<Point>(16); queue.Enqueue(start); while (queue.Count > 0) { Point pt = queue.Dequeue(); ColorBgra* rowPtr = surface.GetRowAddressUnchecked(pt.Y); int localLeft = pt.X - 1; int localRight = pt.X; while (localLeft >= 0 && !stencil.GetUnchecked(localLeft, pt.Y) && CheckColor(cmp, rowPtr[localLeft], tolerance)) { stencil.SetUnchecked(localLeft, pt.Y, true); --localLeft; } while (localRight < surface.Width && !stencil.GetUnchecked(localRight, pt.Y) && CheckColor(cmp, rowPtr[localRight], tolerance)) { stencil.SetUnchecked(localRight, pt.Y, true); ++localRight; } ++localLeft; --localRight; if (pt.Y > 0) { int sleft = localLeft; int sright = localLeft; ColorBgra* rowPtrUp = surface.GetRowAddressUnchecked(pt.Y - 1); for (int sx = localLeft; sx <= localRight; ++sx) { if (!stencil.GetUnchecked(sx, pt.Y - 1) && CheckColor(cmp, rowPtrUp[sx], tolerance)) { ++sright; } else { if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y - 1)); } ++sright; sleft = sright; } } if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y - 1)); } } if (pt.Y < surface.Height - 1) { int sleft = localLeft; int sright = localLeft; ColorBgra* rowPtrDown = surface.GetRowAddressUnchecked(pt.Y + 1); for (int sx = localLeft; sx <= localRight; ++sx) { if (!stencil.GetUnchecked(sx, pt.Y + 1) && CheckColor(cmp, rowPtrDown[sx], tolerance)) { ++sright; } else { if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y + 1)); } ++sright; sleft = sright; } } if (sright - sleft > 0) { queue.Enqueue(new Point(sleft, pt.Y + 1)); } } if (localLeft < left) { left = localLeft; } if (localRight > right) { right = localRight; } if (pt.Y < top) { top = pt.Y; } if (pt.Y > bottom) { bottom = pt.Y; } } foreach (Rectangle rect in scans) { stencil.Set(rect, false); } boundingBox = Rectangle.FromLTRB(left, top, right + 1, bottom + 1); }
/// <summary> /// This is a helper function. It allows you to render an effect "in place." /// That is, you don't need both a destination and a source Surface. /// </summary> public void RenderInPlace(RenderArgs srcAndDstArgs, PdnRegion roi) { using (Surface renderSurface = new Surface(srcAndDstArgs.Surface.Size)) { using (RenderArgs renderArgs = new RenderArgs(renderSurface)) { Rectangle[] scans = roi.GetRegionScansReadOnlyInt(); Render(null, renderArgs, srcAndDstArgs, scans); srcAndDstArgs.Surface.CopySurface(renderSurface, roi); } } }
private Rectangle[][] SliceUpRegion(PdnRegion region, int sliceCount, Rectangle layerBounds) { Rectangle[][] slices = new Rectangle[sliceCount][]; Rectangle[] regionRects = region.GetRegionScansReadOnlyInt(); Scanline[] regionScans = Utility.GetRegionScans(regionRects); for (int i = 0; i < sliceCount; ++i) { int beginScan = (regionScans.Length * i) / sliceCount; int endScan = Math.Min(regionScans.Length, (regionScans.Length * (i + 1)) / sliceCount); // Try to arrange it such that the maximum size of the first region // is 1-pixel tall if (i == 0) { endScan = Math.Min(endScan, beginScan + 1); } else if (i == 1) { beginScan = Math.Min(beginScan, 1); } Rectangle[] newRects = Utility.ScanlinesToRectangles(regionScans, beginScan, endScan - beginScan); for (int j = 0; j < newRects.Length; ++j) { newRects[j].Intersect(layerBounds); } slices[i] = newRects; } return slices; }
protected override void Dispose(bool disposing) { if (disposing) { if (undoImage != null) { undoImage.Dispose(); undoImage = null; } if (savedRegion != null) { savedRegion.Dispose(); savedRegion = null; } } base.Dispose(disposing); }
protected override void OnMouseDown(MouseEventArgs e) { base.OnMouseDown(e); if (mouseDown) { return; } if (((e.Button & MouseButtons.Left) == MouseButtons.Left) || ((e.Button & MouseButtons.Right) == MouseButtons.Right)) { mouseDown = true; mouseButton = e.Button; tracePoints = new List<Point>(); bitmapLayer = (BitmapLayer)ActiveLayer; renderArgs = new RenderArgs(bitmapLayer.Surface); if (clipRegion != null) { clipRegion.Dispose(); clipRegion = null; } clipRegion = Selection.CreateRegion(); renderArgs.Graphics.SetClip(clipRegion.GetRegionReadOnly(), CombineMode.Replace); OnMouseMove(e); } }
public BitmapHistoryMementoData(IrregularSurface undoImage, PdnRegion savedRegion) { if (undoImage != null && savedRegion != null) { throw new ArgumentException("Only one of undoImage or savedRegion may be non-null"); } this.undoImage = undoImage; this.savedRegion = savedRegion; }
public BitmapHistoryMemento(string name, ImageResource image, IHistoryWorkspace historyWorkspace, int layerIndex, PdnRegion changedRegion) : this(name, image, historyWorkspace, layerIndex, changedRegion, ((BitmapLayer)historyWorkspace.Document.Layers[layerIndex]).Surface) { }
private static unsafe void LoadSurfaceRegion(FileStream inputHandle, Surface surface, PdnRegion region) { LoadOrSaveSurfaceRegion(inputHandle, surface, region, false); }
private static unsafe void SaveSurfaceRegion(FileStream outputHandle, Surface surface, PdnRegion region) { LoadOrSaveSurfaceRegion(outputHandle, surface, region, true); }
private static unsafe void LoadOrSaveSurfaceRegion(FileStream fileHandle, Surface surface, PdnRegion region, bool trueForSave) { Rectangle[] scans = region.GetRegionScansReadOnlyInt(); Rectangle regionBounds = region.GetBoundsInt(); Rectangle surfaceBounds = surface.Bounds; int scanCount = 0; void*[] ppvBuffers; uint[] lengths; regionBounds.Intersect(surfaceBounds); long length = (long)regionBounds.Width * (long)regionBounds.Height * (long)ColorBgra.SizeOf; if (scans.Length == 1 && length <= uint.MaxValue && surface.IsContiguousMemoryRegion(regionBounds)) { ppvBuffers = new void*[1]; lengths = new uint[1]; ppvBuffers[0] = surface.GetPointAddressUnchecked(regionBounds.Location); lengths[0] = (uint)length; } else { for (int i = 0; i < scans.Length; ++i) { Rectangle rect = scans[i]; rect.Intersect(surfaceBounds); if (rect.Width != 0 && rect.Height != 0) { scanCount += rect.Height; } } int scanIndex = 0; ppvBuffers = new void*[scanCount]; lengths = new uint[scanCount]; for (int i = 0; i < scans.Length; ++i) { Rectangle rect = scans[i]; rect.Intersect(surfaceBounds); if (rect.Width != 0 && rect.Height != 0) { for (int y = rect.Top; y < rect.Bottom; ++y) { ppvBuffers[scanIndex] = surface.GetPointAddressUnchecked(rect.Left, y); lengths[scanIndex] = (uint)(rect.Width * ColorBgra.SizeOf); ++scanIndex; } } } } if (trueForSave) { FileSystem.WriteToStreamingFileGather(fileHandle, ppvBuffers, lengths); } else { FileSystem.ReadFromStreamScatter(fileHandle, ppvBuffers, lengths); } }
public void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, PdnRegion roi) { Rectangle[] scans = roi.GetRegionScansReadOnlyInt(); Render(parameters, dstArgs, srcArgs, scans, 0, scans.Length); }
public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace) { if (historyWorkspace.Selection.IsEmpty) { return null; } else { PdnRegion selectionRegion = historyWorkspace.Selection.CreateRegion(); if (selectionRegion.GetArea() == 0) { selectionRegion.Dispose(); return null; } SelectionHistoryMemento sha = new SelectionHistoryMemento(StaticName, null, historyWorkspace); ReplaceDocumentHistoryMemento rdha = new ReplaceDocumentHistoryMemento(StaticName, null, historyWorkspace); Rectangle boundingBox; Rectangle[] inverseRegionRects = null; boundingBox = Utility.GetRegionBounds(selectionRegion); using (PdnRegion inverseRegion = new PdnRegion(boundingBox)) { inverseRegion.Exclude(selectionRegion); inverseRegionRects = Utility.TranslateRectangles( inverseRegion.GetRegionScansReadOnlyInt(), -boundingBox.X, -boundingBox.Y); } selectionRegion.Dispose(); selectionRegion = null; Document oldDocument = historyWorkspace.Document; // TODO: serialize this to disk so we don't *have* to store the full thing Document newDocument = new Document(boundingBox.Width, boundingBox.Height); // copy the document's meta data over newDocument.ReplaceMetaDataFrom(oldDocument); foreach (Layer layer in oldDocument.Layers) { if (layer is BitmapLayer) { BitmapLayer oldLayer = (BitmapLayer)layer; Surface croppedSurface = oldLayer.Surface.CreateWindow(boundingBox); BitmapLayer newLayer = new BitmapLayer(croppedSurface); ColorBgra clearWhite = ColorBgra.White.NewAlpha(0); foreach (Rectangle rect in inverseRegionRects) { newLayer.Surface.Clear(rect, clearWhite); } newLayer.LoadProperties(oldLayer.SaveProperties()); newDocument.Layers.Add(newLayer); } else { throw new InvalidOperationException("Crop does not support Layers that are not BitmapLayers"); } } CompoundHistoryMemento cha = new CompoundHistoryMemento( StaticName, PdnResources.GetImageResource("Icons.MenuImageCropIcon.png"), new HistoryMemento[] { sha, rdha }); EnterCriticalRegion(); historyWorkspace.Document = newDocument; return cha; } }
/// <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 void OnDeactivate() { base.OnDeactivate(); if (mouseDown) { OnMouseUp(new MouseEventArgs(mouseButton, 0, lastMouseXY.X, lastMouseXY.Y, 0)); } this.RendererList.Remove(this.previewRenderer); this.previewRenderer.Dispose(); this.previewRenderer = null; if (savedSurfaces != null) { if (savedSurfaces != null) { foreach (PlacedSurface ps in savedSurfaces) { ps.Dispose(); } } savedSurfaces.Clear(); savedSurfaces = null; } renderArgs.Dispose();; renderArgs = null; aaPoints = null; renderArgs = null; bitmapLayer = null; if (clipRegion != null) { clipRegion.Dispose(); clipRegion = null; } if (cursorMouseUp != null) { cursorMouseUp.Dispose(); cursorMouseUp = null; } if (cursorMouseDown != null) { cursorMouseDown.Dispose(); cursorMouseDown = null; } if (cursorMouseDownPickColor != null) { cursorMouseDownPickColor.Dispose(); cursorMouseDownPickColor = null; } if (cursorMouseDownAdjustColor != null) { cursorMouseDownAdjustColor.Dispose(); cursorMouseDownAdjustColor = null; } }
protected override void OnActivate() { base.OnActivate(); outlineSaveRegion = null; interiorSaveRegion = null; // creates a bitmap layer from the active layer bitmapLayer = (BitmapLayer)ActiveLayer; // create Graphics object renderArgs = new RenderArgs(bitmapLayer.Surface); lastDrawnRegion = new PdnRegion(); lastDrawnRegion.MakeEmpty(); }
protected void CommitShape() { OnShapeCommitting(); mouseDown = false; ArrayList has = new ArrayList(); PdnRegion activeRegion = Selection.CreateRegion(); if (outlineSaveRegion != null) { using (PdnRegion clipTest = activeRegion.Clone()) { clipTest.Intersect(outlineSaveRegion); if (!clipTest.IsEmpty()) { BitmapHistoryMemento bha = new BitmapHistoryMemento(Name, Image, this.DocumentWorkspace, ActiveLayerIndex, outlineSaveRegion, this.ScratchSurface); has.Add(bha); outlineSaveRegion.Dispose(); outlineSaveRegion = null; } } } if (interiorSaveRegion != null) { using (PdnRegion clipTest = activeRegion.Clone()) { clipTest.Intersect(interiorSaveRegion); if (!clipTest.IsEmpty()) { BitmapHistoryMemento bha = new BitmapHistoryMemento(Name, Image, this.DocumentWorkspace, ActiveLayerIndex, interiorSaveRegion, this.ScratchSurface); has.Add(bha); interiorSaveRegion.Dispose(); interiorSaveRegion = null; } } } if (has.Count > 0) { CompoundHistoryMemento cha = new CompoundHistoryMemento(Name, Image, (HistoryMemento[])has.ToArray(typeof(HistoryMemento))); if (this.chaAlreadyOnStack == null) { HistoryStack.PushNewMemento(cha); } else { this.chaAlreadyOnStack.PushNewAction(cha); this.chaAlreadyOnStack = null; } } activeRegion.Dispose(); points = null; Update(); this.shapeWasCommited = true; }
protected override void OnDeactivate() { base.OnDeactivate(); if (this.pencilToolCursor != null) { this.pencilToolCursor.Dispose(); this.pencilToolCursor = null; } if (mouseDown) { Point lastTracePoint = (Point)tracePoints[tracePoints.Count - 1]; OnMouseUp(new MouseEventArgs(mouseButton, 0, lastTracePoint.X, lastTracePoint.Y, 0)); } this.savedRects = null; this.tracePoints = null; this.bitmapLayer = null; if (this.renderArgs != null) { this.renderArgs.Dispose(); this.renderArgs = null; } this.mouseDown = false; if (clipRegion != null) { clipRegion.Dispose(); clipRegion = null; } }
protected override void OnDeactivate() { base.OnDeactivate(); if (mouseDown) { PointF lastPoint = (PointF)points[points.Count - 1]; OnStylusUp(new StylusEventArgs(mouseButton, 0, lastPoint.X, lastPoint.Y, 0)); } if (!this.shapeWasCommited) { CommitShape(); } bitmapLayer = null; if (renderArgs != null) { renderArgs.Dispose(); renderArgs = null; } if (outlineSaveRegion != null) { outlineSaveRegion.Dispose(); outlineSaveRegion = null; } if (interiorSaveRegion != null) { interiorSaveRegion.Dispose(); interiorSaveRegion = null; } points = null; }
public static unsafe void FillStencilByColor(Surface surface, IBitVector2D stencil, ColorBgra cmp, int tolerance, out Rectangle boundingBox, PdnRegion limitRegion, bool limitToSelection) { int top = int.MaxValue; int bottom = int.MinValue; int left = int.MaxValue; int right = int.MinValue; Rectangle[] scans; stencil.Clear(false); if (limitToSelection) { using (PdnRegion excluded = new PdnRegion(new Rectangle(0, 0, stencil.Width, stencil.Height))) { excluded.Xor(limitRegion); scans = excluded.GetRegionScansReadOnlyInt(); } } else { scans = new Rectangle[0]; } foreach (Rectangle rect in scans) { stencil.Set(rect, true); } for (int y = 0; y < surface.Height; ++y) { bool foundPixelInRow = false; ColorBgra *ptr = surface.GetRowAddressUnchecked(y); for (int x = 0; x < surface.Width; ++x) { if (CheckColor(cmp, *ptr, tolerance)) { stencil.SetUnchecked(x, y, true); if (x < left) { left = x; } if (x > right) { right = x; } foundPixelInRow = true; } ++ptr; } if (foundPixelInRow) { if (y < top) { top = y; } if (y >= bottom) { bottom = y; } } } foreach (Rectangle rect in scans) { stencil.Set(rect, false); } boundingBox = Rectangle.FromLTRB(left, top, right + 1, bottom + 1); }
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(); }