public void EditRegionMask(List<Vector2> points, float zoomFactor)
{
if (regionMask == null)
{
// Demand-create our region mask image.
regionMask = new CanvasRenderTarget(SourceBitmap.Device, Parent.Size.X, Parent.Size.Y, 96);
}
else
{
// Back up the previous mask, to support undo.
previousRegionMask = currentRegionMask;
}
// Prepare an ICanvasImage holding the edit to be applied.
ICanvasImage editMask;
if (RegionSelectionMode == SelectionMode.MagicWand)
{
// Magic wand selection is already an image.
editMask = GetMagicWandMask(points, zoomFactor);
}
else
{
// Capture selection geometry into a command list.
var commandList = new CanvasCommandList(regionMask.Device);
using (var drawingSession = commandList.CreateDrawingSession())
{
// If this was just a touch without move, treat it as selecting the entire image.
var dragRange = points.Select(point => Vector2.Distance(point, points[0])).Max() * zoomFactor;
if (dragRange < 10)
{
drawingSession.Clear(Colors.White);
}
else
{
// Draw selection geometry.
var geometry = GetSelectionGeometry(drawingSession, points);
drawingSession.FillGeometry(geometry, Colors.White);
}
}
editMask = commandList;
}
// Apply the edit.
using (var drawingSession = regionMask.CreateDrawingSession())
{
CanvasComposite compositeMode;
switch (RegionSelectionOperation)
{
case SelectionOperation.Replace:
drawingSession.Clear(Colors.Transparent);
compositeMode = CanvasComposite.SourceOver;
break;
case SelectionOperation.Add:
compositeMode = CanvasComposite.SourceOver;
break;
case SelectionOperation.Subtract:
compositeMode = CanvasComposite.DestinationOut;
break;
case SelectionOperation.Invert:
compositeMode = CanvasComposite.Xor;
break;
default:
throw new NotSupportedException();
}
drawingSession.DrawImage(editMask, Vector2.Zero, regionMask.Bounds, 1, CanvasImageInterpolation.Linear, compositeMode);
}
// Back up the mask, so we can recover from lost devices.
currentRegionMask = regionMask.GetPixelBytes();
cachedRegionMask.Reset();
CanUndo = true;
}