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; }
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(); }); } }