예제 #1
0
        protected override GeometryList CreateSelectionGeometry(MagicWandToolChanges changes, AsyncSelectionToolCreateGeometryContext context, CancellationToken cancellationToken)
        {
            GeometryList          list;
            Result <BitVector2D>  lazyBaseStencil;
            IRenderer <ColorBgra> sampleSource = ((MagicWandToolCreateGeometryContext)context).SampleSource;
            byte       x         = (byte)Math.Round((double)(changes.Tolerance * 255.0), MidpointRounding.AwayFromZero);
            byte       tolerance = ByteUtil.FastScale(x, x);
            PointInt32 pt        = changes.OriginPointInt32;

            if (!sampleSource.Bounds <ColorBgra>().Contains(pt))
            {
                switch (changes.SelectionCombineMode)
                {
                case SelectionCombineMode.Replace:
                case SelectionCombineMode.Intersect:
                    return(new GeometryList());

                case SelectionCombineMode.Union:
                case SelectionCombineMode.Exclude:
                case SelectionCombineMode.Xor:
                    return(changes.BaseGeometry);
                }
                throw ExceptionUtil.InvalidEnumArgumentException <SelectionCombineMode>(changes.SelectionCombineMode, "changes.SelectionCombineMode");
            }
            if (cancellationToken.IsCancellationRequested)
            {
                return(null);
            }
            Func <bool>       isCancellationRequestedFn = () => cancellationToken.IsCancellationRequested;
            ColorBgra         basis             = sampleSource.GetPointSlow(pt);
            int               width             = ((sampleSource.Width + 0x1f) / 0x20) * 0x20;
            BitVector2D       newStencil        = new BitVector2D(width, sampleSource.Height);
            BitVector2DStruct newStencilWrapper = new BitVector2DStruct(newStencil);

            if (((changes.SelectionCombineMode != SelectionCombineMode.Replace) && sampleSource.Bounds <ColorBgra>().Contains(changes.BaseGeometry.Bounds.Int32Bound)) && changes.BaseGeometry.IsPixelated)
            {
                lazyBaseStencil = LazyResult.New <BitVector2D>(() => PixelatedGeometryListToBitVector2D(changes.BaseGeometry, newStencil.Width, newStencil.Height, cancellationToken), LazyThreadSafetyMode.ExecutionAndPublication, new SingleUseCriticalSection());
                ThreadPool.QueueUserWorkItem(delegate(object _) {
                    lazyBaseStencil.EnsureEvaluated();
                });
            }
            else
            {
                lazyBaseStencil = null;
            }
            FloodMode floodMode = changes.FloodMode;

            if (floodMode != FloodMode.Local)
            {
                if (floodMode != FloodMode.Global)
                {
                    throw ExceptionUtil.InvalidEnumArgumentException <FloodMode>(changes.FloodMode, "changes.FloodMode");
                }
            }
            else
            {
                RectInt32 num4;
                FloodFillAlgorithm.FillStencilFromPoint <BitVector2DStruct>(sampleSource, newStencilWrapper, pt, tolerance, isCancellationRequestedFn, out num4);
                goto Label_0293;
            }
            TileMathHelper tileMathHelper = new TileMathHelper(sampleSource.Width, sampleSource.Height, 7);

            Work.ParallelForEach <PointInt32>(WaitType.Pumping, tileMathHelper.EnumerateTileOffsets(), delegate(PointInt32 tileOffset) {
                if (!cancellationToken.IsCancellationRequested)
                {
                    RectInt32 clipRect = tileMathHelper.GetTileSourceRect(tileOffset);
                    FloodFillAlgorithm.FillStencilByColor <BitVector2DStruct>(sampleSource, newStencilWrapper, basis, tolerance, isCancellationRequestedFn, clipRect);
                }
            }, WorkItemQueuePriority.Normal, null);
Label_0293:
            if (cancellationToken.IsCancellationRequested)
            {
                return(null);
            }
            if (changes.SelectionCombineMode == SelectionCombineMode.Replace)
            {
                list = GeometryList.FromStencil <BitVector2DStruct>(newStencilWrapper, cancellationToken);
            }
            else if (lazyBaseStencil == null)
            {
                GeometryList rhs = GeometryList.FromStencil <BitVector2DStruct>(newStencilWrapper, cancellationToken);
                if (cancellationToken.IsCancellationRequested)
                {
                    return(null);
                }
                list = GeometryList.Combine(changes.BaseGeometry, changes.SelectionCombineMode.ToGeometryCombineMode(), rhs);
            }
            else
            {
                BitVector2D other = lazyBaseStencil.Value;
                if (cancellationToken.IsCancellationRequested)
                {
                    return(null);
                }
                switch (changes.SelectionCombineMode)
                {
                case SelectionCombineMode.Replace:
                    throw new InternalErrorException();

                case SelectionCombineMode.Union:
                    newStencil.Or(other);
                    break;

                case SelectionCombineMode.Exclude:
                    newStencil.Invert();
                    if (cancellationToken.IsCancellationRequested)
                    {
                        return(null);
                    }
                    newStencil.And(other);
                    break;

                case SelectionCombineMode.Intersect:
                    newStencil.And(other);
                    break;

                case SelectionCombineMode.Xor:
                    newStencil.Xor(other);
                    break;

                default:
                    throw ExceptionUtil.InvalidEnumArgumentException <SelectionCombineMode>(changes.SelectionCombineMode, "changes.SelectionCombineMode");
                }
                if (cancellationToken.IsCancellationRequested)
                {
                    return(null);
                }
                list = GeometryList.FromStencil <BitVector2DStruct>(newStencilWrapper, cancellationToken);
            }
            if (cancellationToken.IsCancellationRequested)
            {
                return(null);
            }
            list.Freeze();
            return(list);
        }
예제 #2
0
        public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace)
        {
            if (historyWorkspace.Selection.IsEmpty)
            {
                return(null);
            }
            SelectionHistoryMemento             memento      = new SelectionHistoryMemento(StaticName, StaticImage, historyWorkspace);
            GeometryList                        selectedPath = historyWorkspace.Selection.GetCachedGeometryList();
            SelectionRenderingQuality           selectionRenderingQuality = historyWorkspace.ToolSettings.Selection.RenderingQuality.Value;
            Result <IReadOnlyList <RectInt32> > selectedPathScansLazy     = historyWorkspace.Selection.GetCachedLazyClippingMaskScans();
            RectInt32           documentBounds = historyWorkspace.Document.Bounds();
            Func <GeometryList> invertedPathFn = delegate {
                if ((selectionRenderingQuality == SelectionRenderingQuality.Aliased) || selectedPath.IsPixelated)
                {
                    GeometryList list2 = GeometryList.FromNonOverlappingSortedScans(selectedPathScansLazy.Value);
                    list2.AddRect(documentBounds);
                    SegmentedList <RectInt32> scans = new SegmentedList <RectInt32>();
                    foreach (RectInt32 num in list2.EnumerateInteriorScans())
                    {
                        if (documentBounds.Contains(num))
                        {
                            scans.Add(num);
                        }
                        else if (documentBounds.IntersectsWith(num))
                        {
                            scans.Add(RectInt32.Intersect(documentBounds, num));
                        }
                    }
                    return(GeometryList.FromNonOverlappingScans(scans));
                }
                GeometryList lhs = documentBounds.Contains(selectedPath.Bounds) ? selectedPath : GeometryList.ClipToRect(selectedPath, documentBounds);
                return(GeometryList.Combine(lhs, GeometryCombineMode.Xor, documentBounds));
            };
            ThreadTask <GeometryList> task = historyWorkspace.TaskManager.StartNewThreadTask <GeometryList>(task => invertedPathFn(), ApartmentState.MTA);
            ManualResetEvent          taskFinishedEvent = new ManualResetEvent(false);

            task.ResultAsync <GeometryList>().Receive(delegate(Result <GeometryList> r) {
                taskFinishedEvent.Set();
            }).Observe();
            if (!taskFinishedEvent.WaitOne(0x3e8))
            {
                using (TaskProgressDialog dialog = new TaskProgressDialog())
                {
                    dialog.Task       = task;
                    dialog.Text       = StaticName;
                    dialog.Icon       = StaticImage.Reference.ToIcon();
                    dialog.HeaderText = PdnResources.GetString("SaveConfigDialog.Finishing.Text");
                    dialog.ShowDialog(historyWorkspace.Window);
                }
            }
            Result <GeometryList> taskResult = task.TaskResult;

            if (taskResult.IsError)
            {
                if (taskResult.Error is OutOfMemoryException)
                {
                    throw new OutOfMemoryException(null, taskResult.Error);
                }
                throw new AggregateException(null, taskResult.Error);
            }
            GeometryList geometry = task.TaskResult.Value;

            base.EnterCriticalRegion();
            using (historyWorkspace.Selection.UseChangeScope())
            {
                historyWorkspace.Selection.Reset();
                geometry.Freeze();
                historyWorkspace.Selection.SetContinuation(geometry, SelectionCombineMode.Replace);
                historyWorkspace.Selection.CommitContinuation();
            }
            return(memento);
        }