Skip to content

RegionEditCommand<TPixel>

Namespace Nfty.Core.Editing in assembly Nfty.Core.

public abstract class RegionEditCommand<TPixel> : IEditCommand<TPixel>

Base for edits expressed as "these pixels get these new values". The new pixels are computed once, before any mutation, and the prior pixels are snapshotted for undo — so redo is just Apply again. Region-scoped, so history stays memory-light even on a large canvas.

Type parameters

  • TPixel - The pixel the target surface stores.

Remarks

Generic over the pixel rather than duplicated per surface specifically because of the undo snapshot: two copies of that could diverge silently and corrupt history rather than failing to compile. It is also where the OpacityLock is enforced — on the way into _after, so every command obeys, including ones that take their alpha from the surface (flood fill's seed match, move's copied pixels) rather than from a brush, and including any command written later that never thinks about opacity at all.

Constructors

RegionEditCommand(OpacityLock)

protected RegionEditCommand(OpacityLock opacity);

Creates the edit under an opacity mode.

Parameters

  • opacity (OpacityLock) - Whether partial alpha is admitted; locked by default everywhere.

Methods

Admit(IEditSurface<TPixel>, TPixel)

protected TPixel Admit(IEditSurface<TPixel> surface, TPixel pixel);

The pixel as this edit is actually allowed to write it: unchanged when unlocked, alpha snapped to 255 or 0 when locked. RegionEditCommand<TPixel>.Apply() puts every computed pixel through this, so a subclass never has to; it is exposed only so a command can ask "would this write change anything?" before doing expensive work, and it is idempotent, so asking twice is harmless.

Parameters

  • surface (IEditSurface<TPixel>) - The surface being edited; knows where its pixel keeps its alpha.
  • pixel (TPixel) - The pixel the edit computed.

Returns. The pixel the opacity mode admits.

Apply(IEditSurface<TPixel>)

public bool Apply(IEditSurface<TPixel> surface);

Applies the edit, snapshotting the pixels it is about to overwrite so RegionEditCommand<TPixel>.Undo() can put them back.

Parameters

  • surface (IEditSurface<TPixel>) - The surface to edit.

Returns. True when the edit changed anything.

ComputePixels(IEditSurface<TPixel>)

protected abstract IReadOnlyList<(int, int, TPixel)> ComputePixels(IEditSurface<TPixel> surface);

Target pixels and their new values. Only in-bounds pixels, each coordinate at most once; computed before any mutation.

Parameters

  • surface (IEditSurface<TPixel>) - The surface being edited, for reading the pixels the edit depends on.

Returns. The pixels to write, before the opacity lock is applied to them.

StampDiscs(IEditSurface<TPixel>, IReadOnlyList<(int, int)>, int, Func<int, int, TPixel>)

protected static List<(int, int, TPixel)> StampDiscs(IEditSurface<TPixel> surface, IReadOnlyList<(int, int)> path, int size, Func<int, int, TPixel> paint);

Stamps a filled round disc of diameter size along path, visiting each in-bounds pixel at most once. Only the pixel a coordinate takes differs between edits — brush paints its own pixel, erase keeps what is there and drops the alpha — so paint supplies that per pixel and the disc geometry lives here once, payload-free.

Parameters

  • surface (IEditSurface<TPixel>) - The surface being edited; supplies bounds and any read-back the paint needs.
  • path (IReadOnlyList<(int, int)>) - The gesture's pixel path; discs are stamped along it.
  • size (int) - Disc diameter in pixels; anything below 1 is treated as 1.
  • paint (Func<int, int, TPixel>) - What the pixel at a coordinate becomes.

Returns. The stamped pixels, deduplicated and clipped to the surface.

Remarks

The geometry, including joining the path so a fast stroke has no gaps, is Footprint.Discs(); this only projects it onto pixels.

Undo(IEditSurface<TPixel>)

public void Undo(IEditSurface<TPixel> surface);

Restores the snapshot taken by RegionEditCommand<TPixel>.Apply().

Parameters

  • surface (IEditSurface<TPixel>) - The surface to restore.