forked from Mapsui/Mapsui
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathPictureRenderer.cs
95 lines (80 loc) · 3.71 KB
/
PictureRenderer.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using System;
using Mapsui.Styles;
using SkiaSharp;
namespace Mapsui.Rendering.Skia
{
internal class PictureRenderer
{
// The field below is static for performance. Effect has not been measured.
// Note that the default FilterQuality is None. Setting it explicitly to Low increases the quality.
private static readonly SKPaint DefaultPaint = new() { FilterQuality = SKFilterQuality.Low };
public static void Draw(SKCanvas canvas, SKPicture picture, SKRect rect, float layerOpacity = 1f)
{
var skPaint = GetPaint(layerOpacity, out var dispose);
var scaleX = rect.Width / picture.CullRect.Width;
var scaleY = rect.Height / picture.CullRect.Height;
var matrix = SKMatrix.CreateTranslation(rect.Left, rect.Top);
matrix.PostConcat(SKMatrix.CreateScale(scaleX, scaleY));
canvas.DrawPicture(picture, ref matrix, skPaint);
if (dispose)
{
skPaint.Dispose();
}
}
public static void Draw(SKCanvas canvas, SKPicture? picture, float x, float y, float rotation = 0,
float offsetX = 0, float offsetY = 0,
LabelStyle.HorizontalAlignmentEnum horizontalAlignment = LabelStyle.HorizontalAlignmentEnum.Center,
LabelStyle.VerticalAlignmentEnum verticalAlignment = LabelStyle.VerticalAlignmentEnum.Center,
float opacity = 1f,
float scale = 1f)
{
if (picture == null)
return;
canvas.Save();
canvas.Translate(x, y);
if (rotation != 0)
canvas.RotateDegrees(rotation, 0, 0);
canvas.Scale(scale, scale);
var width = picture.CullRect.Width;
var height = picture.CullRect.Height;
x = offsetX + DetermineHorizontalAlignmentCorrection(horizontalAlignment, width);
y = -offsetY + DetermineVerticalAlignmentCorrection(verticalAlignment, height);
var halfWidth = width / 2;
var halfHeight = height / 2;
var rect = new SKRect(x - halfWidth, y - halfHeight, x + halfWidth, y + halfHeight);
Draw(canvas, picture, rect, opacity);
canvas.Restore();
}
private static float DetermineHorizontalAlignmentCorrection(
LabelStyle.HorizontalAlignmentEnum horizontalAlignment, float width)
{
if (horizontalAlignment == LabelStyle.HorizontalAlignmentEnum.Left) return width / 2;
if (horizontalAlignment == LabelStyle.HorizontalAlignmentEnum.Right) return - (width / 2);
return 0; // center
}
private static float DetermineVerticalAlignmentCorrection(
LabelStyle.VerticalAlignmentEnum verticalAlignment, float height)
{
if (verticalAlignment == LabelStyle.VerticalAlignmentEnum.Top) return -(height / 2);
if (verticalAlignment == LabelStyle.VerticalAlignmentEnum.Bottom) return height / 2;
return 0; // center
}
private static SKPaint GetPaint(float layerOpacity, out bool dispose)
{
if (Math.Abs(layerOpacity - 1) > Utilities.Constants.Epsilon)
{
// Unfortunately for opacity we need to set the Color and the Color
// is part of the Paint object. So we need to recreate the paint on
// every draw.
dispose = true;
return new SKPaint
{
FilterQuality = SKFilterQuality.Low,
Color = new SKColor(255, 255, 255, (byte)(255 * layerOpacity))
};
}
dispose = false;
return DefaultPaint;
}
}
}