0

I'm new at using Mapsui/SkiaSharp so forgive me if this is obvious.

I'm trying to print! A map is rendered to an image using Mapsui using the "Render" method below (calls Mapsui.Rendering.Skia.MapRenderer) which takes a map, the world extents in Spherical Mercator, and the size of the image (or window). This works fine for screen resolutions.

When I print, because the DPI is higher for the printer, the on-map text is tiny and unreadable.

It may be my inexperience, but I know Skia is accomplished at cross platform rendering for device independence. Mapsui also has a specific section in the documentation about scaling but it references using SKCanvasView.IgnorePixelScaling which I don't have access to via the MapRenderer which only acts on a SKCanvas.

Is there something I am missing about rendering for printing?

Is there a printing specific rendering context or pipeline I can use that automatically scales the fonts appropriately, rather than writing the bitmap to the GDI Graphics context?

(code below is the OnPrintPage override from PrintDocument).

    /// <summary>
    /// Do the printing
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPrintPage(PrintPageEventArgs e)
    { 
        try
        {
            // divide by 100 because e.PageBounds is inches times 100
            Size size = new Size(
                e.PageBounds.Width * (int)(e.Graphics.DpiX / 100.0f),
                e.PageBounds.Height * (int)(e.Graphics.DpiY / 100.0f));

            // draw the bitmap to the graphics context
            using (var image = Renderer.Render(Map, Extents, size))
                e.Graphics.DrawImage(image, 0, 0, e.PageBounds.Width, e.PageBounds.Height);

        }
        catch (Exception ex)
        {
            Trace.TraceError("MapReportPrintDocument.OnPrintPage: Error printing document\r\n{0}", ex);
        }
    }

Edited to add more details; One method of inquiry that's given me some results is the following: rendering to an XpsDocument creates a context where I can let the document context know the DPI, and it automatically adjusts the scaling of the fonts for me. This is not ideal as now I need to manipulate the XPS file to get it printed and there's some wrinkles with that.

    public string RenderToXps(IMap map, Extents extents, SizeF size, float dpi = 72)
    {
        var resolution = Mapsui.Utilities.ZoomHelper.DetermineResolution(extents.Width, extents.Height, size.Width, size.Height);
        var viewport = new Mapsui.Viewport()
        {
            Center = extents.Center.ToMapsui(),
            Resolution = resolution,
            Width = size.Width,
            Height = size.Height
        };

        var msMap = map.GetMapsuiMap();

        var path = Path.GetTempFileName();
        using (var stream = new SkiaSharp.SKFileWStream(path))
        {
            using (var document = SkiaSharp.SKDocument.CreateXps(stream, dpi))
            {

                var canvas = document.BeginPage(size.Width, size.Height);
                Renderer.Render(canvas, viewport, msMap.Layers, msMap.Widgets);
                document.EndPage();
            }
        }

        return path;
    }
Blue Toque
  • 1,775
  • 13
  • 24
  • Which version of Mapsui are you using? – pauldendulk Mar 01 '19 at 19:59
  • I see a method Renderer.Render(Map, Extents, size). Is this your custom method or a Mapsui method? because I am not aware of this signature anywhere. – pauldendulk Mar 01 '19 at 20:00
  • Hi @pauldendulk I'm encapsulating the Mapsui methods because I have pre-existing Map and Extents classes. I'm using MapRenderer.RenderToBitmapStream inside after constructing Viewport, resolution etc. – Blue Toque Mar 01 '19 at 23:37
  • And which platform are you using? (WPF, Android, iOS, UWP) – pauldendulk Mar 02 '19 at 07:05

1 Answers1

0

I assume the line below creates an SKCanvas.

using (var image = Renderer.Render(Map, Extents, size))

You can adjust the scale of that canvas with:

canvas.Scale(myCustomScale, myCustomScale);  

You might also need to also need to adjust the Viewport's Width, Height and Resolution.

Note, that because of the scaling the SKCanvas Width and Height might need to be different from the Viewport Width and Height.

pauldendulk
  • 1,378
  • 12
  • 23
  • Thanks for the reply I'm using the latest Beta and in particular I am using that method. I may be misunderstanding the resolution parameter, but changing it seems to change the zoom. Do I scale the resolution linearly with the increase in DPI? – Blue Toque Mar 01 '19 at 23:39
  • I updated my question with some code where I create a Xps document with a dpi parameter, and render into that canvas. I assume I could just create the canvas with the scale as you suggest, and calculate the scale difference between the screen and the printer manually? – Blue Toque Mar 04 '19 at 18:59
  • I have no experience with the SkiaSharp XPS document. I don't know how canvas.Scale relates to dpi. It might be totally unrelated. – pauldendulk Mar 04 '19 at 19:54