示例#1
0
        // Draw to the CanvasImageSource.
        void DrawToImageSource(Size size)
        {
            var imageSource = new CanvasImageSource(canvasControl, (float)size.Width, (float)size.Height);

            using (var ds = imageSource.CreateDrawingSession(Colors.Yellow))
            {
                DrawTextLabel(ds, "Canvas\nImage\nSource", size);
            }

            imageControl.Source = imageSource;
        }
示例#2
0
        void DrawToImageSource(CanvasDrawingSession canvasControlDrawingSession)
        {
            // XAML doesn't support nested image source drawing sessions, so we must close
            // the main CanvasControl one before drawing to a different CanvasImageSource.
            canvasControlDrawingSession.Dispose();

            using (var ds = imageSource.CreateDrawingSession(Colors.Transparent))
            {
                DrawToOutput(mainDeviceResources, ds);
            }
        }
示例#3
0
            private void UpdateImageSource(Rect updateRectangle)
            {
                if (Window.Current.Visible)
                {
                    var imageRectangle = new Rect(new Point(), _canvasImageSource.Size);
                    updateRectangle.Intersect(imageRectangle);

                    using (var drawingSession = _canvasImageSource.CreateDrawingSession(Colors.Transparent, updateRectangle))
                    {
                        drawingSession.DrawImage(_accumulationRenderTarget); // Render target has the composed frame
                    }
                }
            }
示例#4
0
        public Task <Windows.UI.Xaml.Media.ImageSource> LoadImageAsync(ImageSource imagesource,
                                                                       CancellationToken cancelationToken = default(CancellationToken))
        {
            if (!(imagesource is FontImageSource fontsource))
            {
                return(null);
            }

            var device = CanvasDevice.GetSharedDevice();
            var dpi    = Math.Max(_minimumDpi, Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi);

            // There's really no perfect solution to handle font families with fallbacks (comma-separated)
            // So if the font family has fallbacks, only the first one is taken, because CanvasTextFormat
            // only supports one font family

            var fontFamily  = fontsource.FontFamily.ToFontFamily();
            var allFamilies = fontFamily.Source.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            if (allFamilies.Length < 1)
            {
                return(null);
            }

            var textFormat = new CanvasTextFormat
            {
                FontFamily          = allFamilies[0],
                FontSize            = (float)fontsource.Size,
                HorizontalAlignment = CanvasHorizontalAlignment.Center,
                VerticalAlignment   = CanvasVerticalAlignment.Center,
                Options             = CanvasDrawTextOptions.Default
            };

            using (var layout = new CanvasTextLayout(device, fontsource.Glyph, textFormat, (float)fontsource.Size, (float)fontsource.Size))
            {
                var canvasWidth  = (float)layout.LayoutBounds.Width + 2;
                var canvasHeight = (float)layout.LayoutBounds.Height + 2;

                var imageSource = new CanvasImageSource(device, canvasWidth, canvasHeight, dpi);
                using (var ds = imageSource.CreateDrawingSession(Windows.UI.Colors.Transparent))
                {
                    var iconcolor = (fontsource.Color != Color.Default ? fontsource.Color : Color.White).ToWindowsColor();

                    // offset by 1 as we added a 1 inset
                    var x = (float)layout.DrawBounds.X * -1;

                    ds.DrawTextLayout(layout, x, 1f, iconcolor);
                }

                return(Task.FromResult((Windows.UI.Xaml.Media.ImageSource)imageSource));
            }
        }
示例#5
0
        // Draw to the CanvasImageSource.
        void DrawToImageSource(Size size)
        {
            if (size.Width <= 0 || size.Height <= 0)
            {
                imageControl.Source = null;
                return;
            }

            imageSource = new CanvasImageSource(canvasControl, size);

            using (var ds = imageSource.CreateDrawingSession(Colors.Transparent))
            {
                Draw(ds, "Canvas\nImage\nSource", size);
            }

            imageControl.Source = imageSource;
        }
示例#6
0
        // Draw to the CanvasImageSource.
        void DrawToImageSource(Size size)
        {
            if (size.Width <= 0 || size.Height <= 0)
            {
                imageControl.Source = null;
                return;
            }

            imageSource = new CanvasImageSource(canvasControl, (float)size.Width, (float)size.Height);

            using (var ds = imageSource.CreateDrawingSession(Colors.Transparent))
            {
                Draw(ds, "Canvas\nImage\nSource", size);
            }

            imageControl.Source = imageSource;
        }
示例#7
0
        public Task <Microsoft.UI.Xaml.Media.ImageSource> LoadImageAsync(ImageSource imagesource,
                                                                         CancellationToken cancelationToken = default(CancellationToken))
        {
            if (!(imagesource is FontImageSource fontsource))
            {
                return(null);
            }

            var device = CanvasDevice.GetSharedDevice();

            // https://github.com/microsoft/microsoft-ui-xaml/issues/4205#issuecomment-780204896
            // var dpi = Math.Max(_minimumDpi, Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi);

            var dpi = _minimumDpi;

            var textFormat = new CanvasTextFormat
            {
                FontFamily          = GetFontSource(fontsource),
                FontSize            = (float)fontsource.Size,
                HorizontalAlignment = CanvasHorizontalAlignment.Center,
                VerticalAlignment   = CanvasVerticalAlignment.Center,
                Options             = CanvasDrawTextOptions.Default
            };

            using (var layout = new CanvasTextLayout(device, fontsource.Glyph, textFormat, (float)fontsource.Size, (float)fontsource.Size))
            {
                var canvasWidth  = (float)layout.LayoutBounds.Width + 2;
                var canvasHeight = (float)layout.LayoutBounds.Height + 2;

                var imageSource = new CanvasImageSource(device, canvasWidth, canvasHeight, dpi);
                using (var ds = imageSource.CreateDrawingSession(Microsoft.UI.Colors.Transparent))
                {
                    var iconcolor = (fontsource.Color != null ? fontsource.Color : Colors.White).ToWindowsColor();

                    // offset by 1 as we added a 1 inset
                    var x = (float)layout.DrawBounds.X * -1;

                    ds.DrawTextLayout(layout, x, 1f, iconcolor);
                }

                return(Task.FromResult((UI.Xaml.Media.ImageSource)imageSource));
            }
        }
        internal CanvasImageSource RenderImageSource(IFontImageSource imageSource, float scale)
        {
            // TODO: The DPI not working as the view is not respecting the
            //       value, so just reset to 1 to keep the correct size.
            scale = 1;

            var dpi = scale * DeviceDisplay.BaseLogicalDpi;

            var fontFamily = GetFontSource(imageSource);
            var fontSize   = (float)imageSource.Font.Size;
            var color      = (imageSource.Color ?? Colors.White).ToWindowsColor();

            var textFormat = new CanvasTextFormat
            {
                FontFamily          = fontFamily,
                FontSize            = fontSize,
                HorizontalAlignment = CanvasHorizontalAlignment.Center,
                VerticalAlignment   = CanvasVerticalAlignment.Center,
                Options             = CanvasDrawTextOptions.Default
            };

            var device = CanvasDevice.GetSharedDevice();

            using var layout = new CanvasTextLayout(device, imageSource.Glyph, textFormat, 0, 0);

            // add a 1px padding all around
            var canvasWidth  = (float)layout.DrawBounds.Width + 2;
            var canvasHeight = (float)layout.DrawBounds.Height + 2;

            var canvasImageSource = new CanvasImageSource(device, canvasWidth, canvasHeight, dpi);

            using (var ds = canvasImageSource.CreateDrawingSession(UI.Colors.Transparent))
            {
                // offset by 1px as we added a 1px padding
                var x = (layout.DrawBounds.X * -1) + 1;
                var y = (layout.DrawBounds.Y * -1) + 1;

                ds.DrawTextLayout(layout, (float)x, (float)y, color);
            }

            return(canvasImageSource);
        }
示例#9
0
        private async Task <CanvasImageSource> SvgToImageSource(SvgElement svg)
        {
            if (svg == null)
            {
                return(null);
            }
            var device = CanvasDevice.GetSharedDevice();

            using (var win2DSvg = await Win2DSvgElement.Parse(device, svg))
            {
                win2DSvg.Progress = 1;
                var offScreen = new CanvasImageSource(device, (float)_cacheImageResolution.Width, (float)_cacheImageResolution.Height, 96);
                using (var drawingSession = offScreen.CreateDrawingSession(Colors.Transparent))
                {
                    drawingSession.Transform = Matrix3x2.CreateTranslation(new Vector2(-(float)svg.ViewBox.X, -(float)svg.ViewBox.Y)) * Matrix3x2.CreateScale((float)(200 / Math.Max(svg.ViewBox.Width, svg.ViewBox.Height)));
                    win2DSvg.Draw(drawingSession, 0);
                }
                return(offScreen);
            }
        }
示例#10
0
        private WindowsImageSource LoadImage(ImageSource imagesource)
        {
            if (!(imagesource is IconImageSource iconsource) || !FontRegistry.HasFont(iconsource.Name, out var icon))
            {
                return(null);
            }

            var device = CanvasDevice.GetSharedDevice();
            var dpi    = Math.Max(_minimumDpi, Windows.Graphics.Display.DisplayInformation.GetForCurrentView().LogicalDpi);

            var textFormat = new CanvasTextFormat
            {
                FontFamily          = icon.FontFileName,
                FontSize            = (float)iconsource.Size,
                HorizontalAlignment = CanvasHorizontalAlignment.Center,
                VerticalAlignment   = CanvasVerticalAlignment.Center,
                Options             = CanvasDrawTextOptions.Default
            };

            var glyph = icon.GetGlyph(iconsource.Name);

            using (var layout = new CanvasTextLayout(device, glyph, textFormat, (float)iconsource.Size, (float)iconsource.Size))
            {
                var canvasWidth  = (float)layout.LayoutBounds.Width + 2;
                var canvasHeight = (float)layout.LayoutBounds.Height + 2;

                var imageSource = new CanvasImageSource(device, canvasWidth, canvasHeight, dpi);
                using (var ds = imageSource.CreateDrawingSession(Windows.UI.Colors.Transparent))
                {
                    var iconcolor = (iconsource.Color != Color.Default ? iconsource.Color : Color.White).ToWindowsColor();

                    // offset by 1 as we added a 1 inset
                    var x = (float)layout.DrawBounds.X * -1;

                    ds.DrawTextLayout(layout, x, 1f, iconcolor);
                }

                return(imageSource);
            }
        }
示例#11
0
        private void UpdatePreview(int centerX, int centerY)
        {
            var halfPixelCountPerRow = (PixelCountPerRow - 1) / 2;
            var left = (int)Math.Min(_appScreenshot.SizeInPixels.Width - 1,
                                     Math.Max(centerX - halfPixelCountPerRow, 0));
            var top = (int)Math.Min(_appScreenshot.SizeInPixels.Height - 1,
                                    Math.Max(centerY - halfPixelCountPerRow, 0));
            var right  = (int)Math.Min(centerX + halfPixelCountPerRow, _appScreenshot.SizeInPixels.Width - 1);
            var bottom = (int)Math.Min(centerY + halfPixelCountPerRow, _appScreenshot.SizeInPixels.Height - 1);
            var width  = right - left + 1;
            var height = bottom - top + 1;
            var colors = _appScreenshot.GetPixelColors(left, top, width, height);


            var colorStartX = left - (centerX - halfPixelCountPerRow);
            var colorStartY = top - (centerY - halfPixelCountPerRow);
            var colorEndX   = colorStartX + width;
            var colorEndY   = colorStartY + height;

            var step       = PreviewPixelWidth / PixelCountPerRow;
            var size       = new Size(step, step);
            var startPoint = new Point(0, step * colorStartY);

            using (var drawingSession = _previewImageSource.CreateDrawingSession(Colors.White))
            {
                for (var i = colorStartY; i < colorEndY; i++)
                {
                    startPoint.X = colorStartX * step;
                    for (var j = colorStartX; j < colorEndX; j++)
                    {
                        var color = colors[(i - colorStartY) * width + (j - colorStartX)];
                        drawingSession.FillRectangle(new Rect(startPoint, size), color);
                        startPoint.X += step;
                    }

                    startPoint.Y += step;
                }
            }
        }
    public static ImageSource ToQrImageSource(this ISdp sdp, int width, int height)
    {
      var qrCodeWriter = new QRCodeWriter();
      var bitMatrix = qrCodeWriter.encode(sdp.ToString(), ZXing.BarcodeFormat.QR_CODE, width, height);

      var canvasImageSource = new CanvasImageSource(CanvasDevice.GetSharedDevice(), width, height, 96);
      using (var drawingSession = canvasImageSource.CreateDrawingSession(Color.FromArgb(255, 255, 255, 255)))
      {
        for (var y = 0; y < height; y++)
        {
          for (var x = 0; x < width; x++)
          {
            if (bitMatrix.get(x, y))
            {
              drawingSession.DrawRectangle(x, y, 1, 1, Color.FromArgb(255, 0, 0, 0));
            }
          }
        }
      }

      return canvasImageSource;
    }
示例#13
0
        /**
         * 1フレーム抽出
         */
        private void extractFrame(MediaPlayer mediaPlayer)
        {
            CanvasDevice canvasDevice   = CanvasDevice.GetSharedDevice();
            var          canvasImageSrc = new CanvasImageSource(canvasDevice, (int)mThumbnailSize.Width, (int)mThumbnailSize.Height, 96 /*DisplayInformation.GetForCurrentView().LogicalDpi*/);

            using (SoftwareBitmap softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Rgba8, (int)mThumbnailSize.Width, (int)mThumbnailSize.Height, BitmapAlphaMode.Ignore))
                using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromSoftwareBitmap(canvasDevice, softwareBitmap))
                    using (CanvasDrawingSession ds = canvasImageSrc.CreateDrawingSession(Windows.UI.Colors.Black))
                    {
                        try
                        {
                            mediaPlayer.CopyFrameToVideoSurface(inputBitmap);
                            ds.DrawImage(inputBitmap);
                        }
                        catch (Exception e)
                        {
                            // 無視する
                            Debug.WriteLine(e.ToString());
                        }
                        CTX.Frames.Add(canvasImageSrc);
                    }
        }
示例#14
0
        public static ImageSource ToQrImageSource(this ISdp sdp, int width, int height)
        {
            var qrCodeWriter = new QRCodeWriter();
            var bitMatrix    = qrCodeWriter.encode(sdp.ToString(), ZXing.BarcodeFormat.QR_CODE, width, height);

            var canvasImageSource = new CanvasImageSource(CanvasDevice.GetSharedDevice(), width, height, 96);

            using (var drawingSession = canvasImageSource.CreateDrawingSession(Color.FromArgb(255, 255, 255, 255)))
            {
                for (var y = 0; y < height; y++)
                {
                    for (var x = 0; x < width; x++)
                    {
                        if (bitMatrix.get(x, y))
                        {
                            drawingSession.DrawRectangle(x, y, 1, 1, Color.FromArgb(255, 0, 0, 0));
                        }
                    }
                }
            }

            return(canvasImageSource);
        }
示例#15
0
        /**
         * CustomDrawingモード時のフレーム描画処理
         */
        private async void MP_FrameAvailable(MediaPlayer mediaPlayer, object args)
        {
            if (mGettingFrame)
            {
                return;
            }

            CanvasDevice canvasDevice = CanvasDevice.GetSharedDevice();

            await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
            {
                if (mFrameServerDest == null)
                {
                    // FrameServerImage in this example is a XAML image control
                    var playerSize     = CTX.PlayerSize;
                    mFrameServerDest   = new SoftwareBitmap(BitmapPixelFormat.Rgba8, (int)playerSize.Width, (int)playerSize.Height, BitmapAlphaMode.Ignore);
                    mCanvasImageSource = new CanvasImageSource(canvasDevice, (int)playerSize.Width, (int)playerSize.Height, 96 /*DisplayInformation.GetForCurrentView().LogicalDpi*/);
                    mFrameImage.Source = mCanvasImageSource;
                }
                Debug.WriteLine("Frame: {0}", mediaPlayer.PlaybackSession.Position);
                updateSliderPosition(mediaPlayer.PlaybackSession.Position.TotalMilliseconds);

                using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromSoftwareBitmap(canvasDevice, mFrameServerDest))
                    using (CanvasDrawingSession ds = mCanvasImageSource.CreateDrawingSession(Windows.UI.Colors.Black))
                    {
                        MediaPlayer.CopyFrameToVideoSurface(inputBitmap);
                        if (null != CustomDraw)
                        {
                            CustomDraw(this, ds, inputBitmap);
                        }
                        else
                        {
                            ds.DrawImage(inputBitmap);
                        }
                    }
            });
        }
        public void DrawBoxes(CanvasBitmap bitmap, List <CubicBoundingBox> boxes, CanvasImageSource canvasImageSource)
        {
            var device = canvasDevice;

            //CanvasSolidColorBrush brush = new CanvasSolidColorBrush(device, Windows.UI.Color.FromArgb(255, 255, 0, 0));
            if (canvasImageSource != null)
            {
                using (var ds = canvasImageSource.CreateDrawingSession(Colors.Black))
                {
                    ds.DrawImage(bitmap);
                    if (boxes != null)
                    {
                        foreach (var box in boxes)
                        {
                            using (CanvasSolidColorBrush brush = new CanvasSolidColorBrush(device, Colors.Red))
                            {
                                var points = (from p in box.ControlPoint
                                              select new Vector2((float)(p.X * bitmap.Bounds.Width), (float)(p.Y * bitmap.Bounds.Height))).ToArray();

                                ds.DrawLine(points[0], points[1], brush);
                                ds.DrawLine(points[0], points[4], brush);
                                ds.DrawLine(points[1], points[5], brush);
                                ds.DrawLine(points[4], points[5], brush);
                                ds.DrawLine(points[5], points[7], brush);
                                ds.DrawLine(points[1], points[3], brush);
                                ds.DrawLine(points[4], points[6], brush);
                                ds.DrawLine(points[0], points[2], brush);
                                ds.DrawLine(points[2], points[6], brush);
                                ds.DrawLine(points[2], points[3], brush);
                                ds.DrawLine(points[3], points[7], brush);
                                ds.DrawLine(points[7], points[6], brush);
                            }
                        }
                    }
                }
            }
        }
示例#17
0
        public async Task <CanvasImageSource> RenderToImageSourceAsync(
            RenderTargetBitmap backgroundBitmap,
            IReadOnlyList <InkStroke> inkStrokes, IReadOnlyList <InkStroke> highlightStrokes, double width, double height)
        {
            var dpi         = DisplayInformation.GetForCurrentView().LogicalDpi;
            var imageSource = new CanvasImageSource(_canvasDevice, (float)width, (float)height, dpi);


            using (var drawingSession = imageSource.CreateDrawingSession(Colors.White))
            {
                try
                {
                    var pixels = await backgroundBitmap.GetPixelsAsync();

                    var bitmap = SoftwareBitmap.CreateCopyFromBuffer(pixels, BitmapPixelFormat.Bgra8,
                                                                     backgroundBitmap.PixelWidth, backgroundBitmap.PixelHeight);
                    var convertedImage = SoftwareBitmap.Convert(
                        bitmap,
                        BitmapPixelFormat.Bgra8,
                        BitmapAlphaMode.Premultiplied
                        );
                    var background = CanvasBitmap.CreateFromSoftwareBitmap(_canvasDevice, convertedImage);
                    drawingSession.DrawImage(background, new Rect(0, 0,
                                                                  width,
                                                                  height));
                    drawingSession.DrawInk(inkStrokes);

                    return(imageSource);
                }
                catch (Exception e) when(_canvasDevice.IsDeviceLost(e.HResult))
                {
                    _canvasDevice.RaiseDeviceLost();
                }

                return(null);
            }
        }
示例#18
0
        private void extractFrame(MediaPlayer mediaPlayer)
        {
            CanvasDevice canvasDevice   = CanvasDevice.GetSharedDevice();
            var          canvasImageSrc = new CanvasImageSource(canvasDevice, (int)mThumbnailSize.Width, (int)mThumbnailSize.Height, DisplayInformation.GetForCurrentView().LogicalDpi);//96);

            using (SoftwareBitmap softwareBitmap = new SoftwareBitmap(BitmapPixelFormat.Rgba8, (int)mThumbnailSize.Width, (int)mThumbnailSize.Height, BitmapAlphaMode.Ignore))
                using (CanvasBitmap inputBitmap = CanvasBitmap.CreateFromSoftwareBitmap(canvasDevice, softwareBitmap))
                    using (CanvasDrawingSession ds = canvasImageSrc.CreateDrawingSession(Windows.UI.Colors.Black))
                    {
                        try
                        {
                            Debug.WriteLine(string.Format("...Extract Position:{0} (State={1})", mediaPlayer.PlaybackSession.Position, mediaPlayer.PlaybackSession.PlaybackState.ToString()));

                            mediaPlayer.CopyFrameToVideoSurface(inputBitmap);
                        }
                        catch (Exception e)
                        {
                            Debug.WriteLine(e);
                            return;
                        }
                        ds.DrawImage(inputBitmap);
                        Frames.Add(canvasImageSrc);
                    }
        }
示例#19
0
            internal async Task Go(CancellationToken cancellationToken, CanvasDevice device, ScenarioData scenarioData)
            {
                var runner = MakeScenarioRunner();
                scenarioData.AddDataToScenarioRunner(runner);

                // Create the image source and the render target.  These sizes are hardcoded and independent of the 
                // display's DPI since we just want a small image to convince ourselves that the scenarios really are 
                // rendering the right thing.
                Image = new CanvasImageSource(device, 128, 128, 96);

                using (var rt = new CanvasRenderTarget(device, 128, 128, 96))
                {
                    // We actually run the scenario on the thread pool - XAML really falls down if you overload the UI thread.
                    var time = await Task.Run(() =>
                    {
                        // Run the scenario multiple times to try and avoid too much noise
                        List<CpuGpuTime> times = new List<CpuGpuTime>();

                        for (int i = 0; i < 10; ++i)
                        {
                            // Hold the device lock while we run the scenario - this prevents other threads
                            // from interacting with the device and interfering with our recorded time.
                            using (var deviceLock = device.Lock())
                            {
                                times.Add(RunScenario(runner, rt));
                            }
                            if (cancellationToken.IsCancellationRequested)
                                return new CpuGpuTime();
                        }

                        var cpuTimes = from entry in times select entry.CpuTimeInMs;
                        var gpuTimes = from entry in times select entry.GpuTimeInMs;

                        return new CpuGpuTime
                        {
                            CpuTimeInMs = GetAverage(cpuTimes),
                            GpuTimeInMs = GetAverage(gpuTimes)
                        };
                    }, cancellationToken);

                    Data[scenarioData.Value] = time;

                    if (cancellationToken.IsCancellationRequested)
                        return;

                    using (var ds = Image.CreateDrawingSession(Colors.Transparent))
                    {
                        ds.DrawImage(rt);

                        var timing = string.Format("{0:0.00}ms\n{1:0.00}ms", time.CpuTimeInMs, time.GpuTimeInMs);
                        ds.DrawText(timing, 0, 0, Colors.White);
                        ds.DrawText(timing, 1, 1, Colors.Black);
                    }
                }

                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("Image"));
                    PropertyChanged(this, new PropertyChangedEventArgs("Summary"));
                }
            }
        private void canvas_CreateResources(CanvasControl sender, CanvasCreateResourcesEventArgs args)
        {
            arrow = MakeDirectionIcon(sender);

            var bounds = arrow.ComputeStrokeBounds(3);
            var outline = arrow.Stroke(2).Outline();

            var foregroundBrush = (SolidColorBrush)directionsCombo.Foreground;
            var color = foregroundBrush.Color;

            Directions = new List<DirectionInfo>();

            foreach (CanvasTextDirection direction in Enum.GetValues(typeof(CanvasTextDirection)))
            {
                var arrowImage = new CanvasImageSource(sender, 64, 64);
                using (var ds = arrowImage.CreateDrawingSession(Colors.Transparent))
                {

                    var directionTransform = GetDirectionTransform(direction);
                    ds.Transform = directionTransform * Matrix3x2.CreateTranslation((float)(32 - bounds.Width / 2), (float)(32 - bounds.Height / 2));

                    ds.DrawGeometry(arrow, color, 1);
                }

                Directions.Add(new DirectionInfo(direction, arrowImage));
            }

            // Poke the property so that the control gets a chance to pick up the new images
            if (PropertyChanged != null)
            {
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Directions"));
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs("CurrentDirectionIndex"));
            }
        }
            internal async Task Go(CancellationToken cancellationToken, CanvasDevice device, ScenarioData scenarioData)
            {
                var runner = MakeScenarioRunner();

                scenarioData.AddDataToScenarioRunner(runner);

                // Create the image source and the render target.  These sizes are hardcoded and independent of the
                // display's DPI since we just want a small image to convince ourselves that the scenarios really are
                // rendering the right thing.
                Image = new CanvasImageSource(device, 128, 128, 96);

                using (var rt = new CanvasRenderTarget(device, 128, 128, 96))
                {
                    // We actually run the scenario on the thread pool - XAML really falls down if you overload the UI thread.
                    var time = await Task.Run(() =>
                    {
                        // Run the scenario multiple times to try and avoid too much noise
                        List <CpuGpuTime> times = new List <CpuGpuTime>();

                        for (int i = 0; i < 10; ++i)
                        {
                            // Hold the device lock while we run the scenario - this prevents other threads
                            // from interacting with the device and interfering with our recorded time.
                            using (var deviceLock = device.Lock())
                            {
                                times.Add(RunScenario(runner, rt));
                            }
                            if (cancellationToken.IsCancellationRequested)
                            {
                                return(new CpuGpuTime());
                            }
                        }

                        var cpuTimes = from entry in times select entry.CpuTimeInMs;
                        var gpuTimes = from entry in times select entry.GpuTimeInMs;

                        return(new CpuGpuTime
                        {
                            CpuTimeInMs = GetAverage(cpuTimes),
                            GpuTimeInMs = GetAverage(gpuTimes)
                        });
                    }, cancellationToken);

                    Data[scenarioData.Value] = time;

                    if (cancellationToken.IsCancellationRequested)
                    {
                        return;
                    }

                    using (var ds = Image.CreateDrawingSession(Colors.Transparent))
                    {
                        ds.DrawImage(rt);

                        var timing = string.Format("{0:0.00}ms\n{1:0.00}ms", time.CpuTimeInMs, time.GpuTimeInMs);
                        ds.DrawText(timing, 0, 0, Colors.White);
                        ds.DrawText(timing, 1, 1, Colors.Black);
                    }
                }

                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("Image"));
                    PropertyChanged(this, new PropertyChangedEventArgs("Summary"));
                }
            }