Ejemplo n.º 1
0
        private static void LockToGrid(CanvasPixelPosition canvasOffset, [NotNull] TileCanvas target, ref double x, ref double y)
        {
            if (canvasOffset == null)
            {
                return;
            }

            var scale = 1.0 / target.CurrentZoom();
            var grid  = TileCanvas.GridSize * scale;

            var bias = (3 * grid) / 5.0;

            x  = Math.Round((x + bias) / grid) * grid;
            x -= (canvasOffset.X * scale) % grid;

            y  = Math.Round((y + bias) / grid) * grid;
            y -= (canvasOffset.Y * scale) % grid;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Finish a pen stoke. It should be rendered into the tile store.
        /// </summary>
        public void CommitTo(TileCanvas tileCanvas)
        {
            if (tileCanvas == null)
            {
                return;
            }

            try
            {
                lock (_dryLock){
                    _dryingInk.Add(_stroke.ToArray());
                    _stroke.Clear(); // ready for next
                }

                // render and copy on a separate thread
                DryWaitingStroke(tileCanvas);
            }
            catch (Exception ex)
            {
                Logging.WriteLogMessage(ex.ToString());
            }
        }
Ejemplo n.º 3
0
        private void DryWaitingStroke([NotNull] TileCanvas tileCanvas)
        {
            // Try to get a waiting stroke (peek, so we can draw the waiting stroke)
            DPoint[][] waitingStrokes;
            lock (_dryLock)
            {
                waitingStrokes = _dryingInk.ToArray();
                _dryingInk.Clear();
                if (waitingStrokes != null)
                {
                    _renderingInk.UnionWith(waitingStrokes);
                }
            }

            tileCanvas.Invalidate(); // show progress if the render is slow.
            _renderTarget.Invalidate();

            if (waitingStrokes == null)
            {
                return;
            }
            foreach (var strokeToRender in waitingStrokes)
            {
                if (strokeToRender.Length < 1)
                {
                    continue;
                }

                // Figure out what part of the screen is covered
                var clipRegion  = MeasureDrawing(strokeToRender, tileCanvas.CurrentZoom());
                var pixelWidth  = (int)clipRegion.Width;
                var pixelHeight = (int)clipRegion.Height;

                // draw to an image
                byte[] bytes;
                using (var offscreen = new CanvasRenderTarget(CanvasDevice.GetSharedDevice(), pixelWidth, pixelHeight, 96,
                                                              DirectXPixelFormat.B8G8R8A8UIntNormalized, CanvasAlphaMode.Premultiplied))
                {
                    using (var ds = offscreen.CreateDrawingSession())
                    {
                        ds?.Clear(Colors.Transparent);
                        DrawToSession(ds, strokeToRender, clipRegion, tileCanvas.CurrentZoom());
                    }

                    bytes = offscreen.GetPixelBytes();
                }

                // render into tile cache
                var uncropped = new RawImageInterleaved_UInt8
                {
                    Data   = bytes,
                    Width  = pixelWidth,
                    Height = pixelHeight
                };

                var visualWidth  = (int)Math.Ceiling(pixelWidth / tileCanvas.CurrentZoom());
                var visualHeight = (int)Math.Ceiling(pixelHeight / tileCanvas.CurrentZoom());
                var visualTop    = (int)Math.Floor(clipRegion.Y + 0.5);
                var visualLeft   = (int)Math.Floor(clipRegion.X + 0.5);
                var visualRight  = visualLeft + visualWidth;
                var visualBottom = visualTop + visualHeight;

                ThreadPool.QueueUserWorkItem(canv =>
                {
                    var ok = tileCanvas.ImportBytesScaled(uncropped, visualLeft, visualTop, visualRight, visualBottom);
                    if (!ok)
                    {
                        Logging.WriteLogMessage("Tile byte import failed when drawing strokes");
                    }
                    lock (_dryLock)
                    {
                        _renderingInk.Remove(strokeToRender);
                    }
                    tileCanvas.Invalidate(); // show finished strokes
                    _renderTarget.Invalidate();
                });
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Continue a pen stroke
        /// </summary>
        public void Stroke(PointerEventArgs penEvent, CanvasPixelPosition canvasOffset, [NotNull] TileCanvas target)
        {
            try
            {
                if (penEvent?.CurrentPoint?.Properties == null)
                {
                    return;
                }

                var x        = penEvent.CurrentPoint.Position.X;
                var y        = penEvent.CurrentPoint.Position.Y;
                var isEraser = penEvent.CurrentPoint.Properties.IsEraser || penEvent.CurrentPoint.Properties.IsRightButtonPressed; // treat right-click as erase

                if (penEvent.KeyModifiers.HasFlag(VirtualKeyModifiers.Control))
                {
                    // hacky straight line tool:
                    if (_stroke.Count > 1)
                    {
                        _stroke.RemoveAt(_stroke.Count - 1);                    // replace last point instead of adding a new one
                    }
                }

                if (penEvent.KeyModifiers.HasFlag(VirtualKeyModifiers.Menu))// this is actually *ALT*
                {
                    LockToGrid(canvasOffset, target, ref x, ref y);
                }

                _stroke.Add(new DPoint
                {
                    X        = x,
                    Y        = y,
                    StylusId = GuessPointerId(penEvent.CurrentPoint),
                    Pressure = penEvent.CurrentPoint.Properties.Pressure,
                    IsErase  = isEraser
                });

                _renderTarget.Invalidate();
            }
            catch (Exception ex)
            {
                Logging.WriteLogMessage(ex.ToString());
            }
        }