private static SKRect WorldToScreen(IReadOnlyViewport viewport, MRect rect) { var first = viewport.WorldToScreen(rect.Min.X, rect.Min.Y); var second = viewport.WorldToScreen(rect.Max.X, rect.Max.Y); return(new SKRect ( (float)Math.Min(first.X, second.X), (float)Math.Min(first.Y, second.Y), (float)Math.Max(first.X, second.X), (float)Math.Max(first.Y, second.Y) )); }
private static BoundingBox WorldToScreen(IReadOnlyViewport viewport, BoundingBox boundingBox) { var first = viewport.WorldToScreen(boundingBox.Min); var second = viewport.WorldToScreen(boundingBox.Max); return(new BoundingBox ( Math.Min(first.X, second.X), Math.Min(first.Y, second.Y), Math.Max(first.X, second.X), Math.Max(first.Y, second.Y) )); }
public bool Draw(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, IFeature feature, IStyle style, ISymbolCache symbolCache) { if (!(feature.Geometry is global::Mapsui.Geometries.Point worldPoint)) { return(false); } var screenPoint = viewport.WorldToScreen(worldPoint); var color = new SKColor((byte)rnd.Next(0, 256), (byte)rnd.Next(0, 256), (byte)rnd.Next(0, 256), (byte)(256.0 * layer.Opacity * style.Opacity)); var colored = new SKPaint() { Color = color, IsAntialias = true }; var black = new SKPaint() { Color = SKColors.Black, IsAntialias = true }; canvas.Translate((float)screenPoint.X, (float)screenPoint.Y); canvas.DrawCircle(0, 0, 15, colored); canvas.DrawCircle(-8, -12, 8, colored); canvas.DrawCircle(8, -12, 8, colored); canvas.DrawCircle(8, -8, 2, black); canvas.DrawCircle(-8, -8, 2, black); using (var path = new SKPath()) { path.ArcTo(new SKRect(-8, 2, 8, 10), 25, 135, true); canvas.DrawPath(path, new SKPaint() { Style = SKPaintStyle.Stroke, Color = SKColors.Black, IsAntialias = true }); } return(true); }
public bool Draw(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, IFeature feature, IStyle istyle, ISymbolCache symbolCache) { var style = ((PolylineMarkerStyle)istyle); var zoom = 1 / (float)viewport.Resolution; // var dest = viewport.WorldToScreen(style.start.X, style.start.Y); canvas.Translate((float)dest.X, (float)dest.Y); canvas.Scale(zoom, zoom); canvas.RotateDegrees((float)viewport.Rotation, 0.0f, 0.0f); //#TODO store paint with shader in the style using (SKPaint paint = new SKPaint()) { paint.Color = style.color.WithAlpha((byte)(style.Opacity * 255)); paint.StrokeWidth = 3f * (float)viewport.Resolution; paint.Style = SKPaintStyle.Stroke; paint.IsAntialias = true; canvas.DrawPath(style.path, paint); } return(true); }
public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature, IGeometry geometry, SymbolCache symbolCache, float opacity) { var point = geometry as Point; var destination = viewport.WorldToScreen(point); if (style is LabelStyle labelStyle) // case 1) LabelStyle { LabelRenderer.Draw(canvas, labelStyle, feature, (float)destination.X, (float)destination.Y, opacity); } else if (style is SymbolStyle) { var symbolStyle = (SymbolStyle)style; if (symbolStyle.BitmapId >= 0) // case 2) Bitmap Style { DrawPointWithBitmapStyle(canvas, symbolStyle, destination, symbolCache, opacity); } else // case 3) SymbolStyle without bitmap { DrawPointWithSymbolStyle(canvas, symbolStyle, destination, opacity, symbolStyle.SymbolType); } } else if (style is VectorStyle) // case 4) VectorStyle { DrawPointWithVectorStyle(canvas, (VectorStyle)style, destination, opacity); } else { throw new Exception($"Style of type '{style.GetType()}' is not supported for points"); } }
public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature, IGeometry geometry, float opacity) { if (style is LabelStyle labelStyle) { var worldCenter = geometry.BoundingBox.Centroid; var center = viewport.WorldToScreen(worldCenter); LabelRenderer.Draw(canvas, labelStyle, feature, center, opacity); } else { var lineString = ((LineString)geometry).Vertices; float lineWidth = 1; var lineColor = new Color(); var vectorStyle = style as VectorStyle; var strokeCap = PenStrokeCap.Butt; var strokeJoin = StrokeJoin.Miter; var strokeMiterLimit = 4f; var strokeStyle = PenStyle.Solid; float[] dashArray = null; float dashOffset = 0; if (vectorStyle != null) { lineWidth = (float)vectorStyle.Line.Width; lineColor = vectorStyle.Line.Color; strokeCap = vectorStyle.Line.PenStrokeCap; strokeJoin = vectorStyle.Line.StrokeJoin; strokeMiterLimit = vectorStyle.Line.StrokeMiterLimit; strokeStyle = vectorStyle.Line.PenStyle; dashArray = vectorStyle.Line.DashArray; dashOffset = vectorStyle.Line.DashOffset; } using (var path = lineString.ToSkiaPath(viewport, canvas.LocalClipBounds)) using (var paint = new SKPaint { IsAntialias = true }) { paint.IsStroke = true; paint.StrokeWidth = lineWidth; paint.Color = lineColor.ToSkia(opacity); paint.StrokeCap = strokeCap.ToSkia(); paint.StrokeJoin = strokeJoin.ToSkia(); paint.StrokeMiter = strokeMiterLimit; if (strokeStyle != PenStyle.Solid) { paint.PathEffect = strokeStyle.ToSkia(lineWidth, dashArray, dashOffset); } else { paint.PathEffect = null; } canvas.DrawPath(path, paint); } } }
public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature, LineString lineString, float opacity) { if (style is LabelStyle labelStyle) { if (feature.Extent == null) { return; } var center = viewport.WorldToScreen(feature.Extent.Centroid); LabelRenderer.Draw(canvas, labelStyle, feature, center.X, center.Y, opacity); } else { float lineWidth = 1; var lineColor = new Color(); var vectorStyle = style as VectorStyle; var strokeCap = PenStrokeCap.Butt; var strokeJoin = StrokeJoin.Miter; var strokeMiterLimit = 4f; var strokeStyle = PenStyle.Solid; float[]? dashArray = null; float dashOffset = 0; if (vectorStyle is not null && vectorStyle.Line != null) { lineWidth = (float)vectorStyle.Line.Width; lineColor = vectorStyle.Line.Color; strokeCap = vectorStyle.Line.PenStrokeCap; strokeJoin = vectorStyle.Line.StrokeJoin; strokeMiterLimit = vectorStyle.Line.StrokeMiterLimit; strokeStyle = vectorStyle.Line.PenStyle; dashArray = vectorStyle.Line.DashArray; dashOffset = vectorStyle.Line.DashOffset; } using var path = lineString.ToSkiaPath(viewport, canvas.LocalClipBounds); using var paint = new SKPaint { IsAntialias = true }; paint.IsStroke = true; paint.StrokeWidth = lineWidth; paint.Color = lineColor.ToSkia(opacity); paint.StrokeCap = strokeCap.ToSkia(); paint.StrokeJoin = strokeJoin.ToSkia(); paint.StrokeMiter = strokeMiterLimit; paint.PathEffect = strokeStyle != PenStyle.Solid ? strokeStyle.ToSkia(lineWidth, dashArray, dashOffset) : null; canvas.DrawPath(path, paint); } }
private void DrawArrows(SKSurface skSurface, IReadOnlyViewport viewport, Route route, int scale) { const string resourceId = "FamilieWandelPad.RouteImager.Arrow_Up.png"; var assembly = GetType().GetTypeInfo().Assembly; SKBitmap resourceBitmap; using (var stream = assembly.GetManifestResourceStream(resourceId)) { resourceBitmap = SKBitmap.Decode(stream); resourceBitmap = resourceBitmap.Resize(new SKSizeI(25, 25), SKFilterQuality.High); } var arrowSteps = Distance.FromMeters(50); for (var index = 0; index < route.Waypoints.Count; index++) { var waypoint = route.Waypoints[index]; var nextWaypoint = route.Waypoints[(index + 1) % route.Waypoints.Count]; var a = new Vector2((float)waypoint.Latitude, (float)waypoint.Longitude); var b = new Vector2((float)nextWaypoint.Latitude, (float)nextWaypoint.Longitude); var aToB = b - a; //Vector from A to B var steps = Math.Max( Distance.FromMiles(waypoint.Distance(nextWaypoint)).Meters / arrowSteps.Meters, 2 ); for (var step = 1; step < steps; step++) { var arrow = a + aToB * (float)(step / steps); var screenPoint = viewport.WorldToScreen( SphericalMercator.FromLonLat(arrow.Y, arrow.X) ); skSurface.Canvas.Save(); skSurface.Canvas.RotateDegrees((float)waypoint.DegreeBearing(nextWaypoint), (float)screenPoint.X, (float)screenPoint.Y); skSurface.Canvas.DrawBitmap( resourceBitmap, (float)screenPoint.X - resourceBitmap.Width / 2f, (float)screenPoint.Y - resourceBitmap.Height / 2f ); skSurface.Canvas.Restore(); // skSurface.Canvas.DrawCircle((float) screenPoint.X, (float) screenPoint.Y, 10, new SKPaint() {Color = SKColors.Blue}); } } }
public static UIElement RenderLabel(Geometries.Point position, LabelStyle labelStyle, IReadOnlyViewport viewport, string labelText) { var screenPosition = viewport.WorldToScreen(position); var windowsPosition = screenPosition.ToXaml(); // Set some defaults which should be configurable someday const double witdhMargin = 3.0; const double heightMargin = 0.0; var textblock = new TextBlock { Text = labelText, Foreground = new SolidColorBrush(labelStyle.ForeColor.ToXaml()), FontFamily = new FontFamily(labelStyle.Font.FontFamily), FontSize = labelStyle.Font.Size, Margin = new Thickness(witdhMargin, heightMargin, witdhMargin, heightMargin), }; // TODO: Halo is not supported by WPF, but we CAN do an outer glow-like effect... if (labelStyle.Halo != null) { System.Windows.Media.Effects.DropShadowEffect haloEffect = new System.Windows.Media.Effects.DropShadowEffect(); haloEffect.ShadowDepth = 0; haloEffect.Color = labelStyle.Halo.Color.ToXaml(); haloEffect.Opacity = haloEffect.Color.A / 255.0; haloEffect.BlurRadius = labelStyle.Halo.Width * 2; textblock.Effect = haloEffect; } var border = new Border { // TODO: We have no SymbolCache, so we get problems, if there is a bitmap as background Background = labelStyle.BackColor.ToXaml(rotate: (float)viewport.Rotation), CornerRadius = new CornerRadius(4), Child = textblock, Opacity = labelStyle.Opacity, }; DetermineTextWidthAndHeightWpf(out var textWidth, out var textHeight, labelStyle, labelText); var offsetX = labelStyle.Offset.IsRelative ? textWidth * labelStyle.Offset.X : labelStyle.Offset.X; var offsetY = labelStyle.Offset.IsRelative ? textHeight * labelStyle.Offset.Y : labelStyle.Offset.Y; border.SetValue(Canvas.LeftProperty, windowsPosition.X + offsetX - (textWidth + 2 * witdhMargin) * (short)labelStyle.HorizontalAlignment * 0.5f); border.SetValue(Canvas.TopProperty, windowsPosition.Y + offsetY - (textHeight + 2 * heightMargin) * (short)labelStyle.VerticalAlignment * 0.5f); return(border); }
private static void UpdateRenderTransform(UIElement renderedGeometry, IReadOnlyViewport viewport) { var matrix = XamlMedia.Matrix.Identity; if (viewport.IsRotated) { var center = viewport.WorldToScreen(viewport.Center); MatrixHelper.RotateAt(ref matrix, viewport.Rotation, center.X, center.Y); } renderedGeometry.RenderTransform = new XamlMedia.MatrixTransform { Matrix = matrix }; }
private static XamlMedia.Geometry ConvertSymbol(Point point, SymbolStyle style, IReadOnlyViewport viewport) { Point p = viewport.WorldToScreen(point); var rect = new XamlMedia.RectangleGeometry(); if (style.BitmapId >= 0) { var bitmapImage = ((Stream)BitmapRegistry.Instance.Get(style.BitmapId)).ToBitmapImage(); var width = bitmapImage.PixelWidth * style.SymbolScale; var height = bitmapImage.PixelHeight * style.SymbolScale; rect.Rect = new Rect(p.X - width * 0.5, p.Y - height * 0.5, width, height); } return(rect); }
private static void DrawPOIs(SKSurface skSurface, IReadOnlyViewport viewport, Route route, float scale) { var pois = route.Waypoints .OfType <PointOfInterest>() .OrderBy(p => p.OrderIndex) .ToList(); var poiStroke = new SKPaint { Style = SKPaintStyle.Stroke, IsAntialias = true, FilterQuality = SKFilterQuality.High, Color = Color.Black.ToSkia(), StrokeWidth = 10f * scale }; var poiFill = new SKPaint { Style = SKPaintStyle.Fill, Color = Color.White.ToSkia() }; var textPaint = new SKPaint { Color = SKColors.Black, TextSize = 32f * scale }; foreach (var pointOfInterest in pois) { var screenPoint = viewport.WorldToScreen( SphericalMercator.FromLonLat(pointOfInterest.Longitude, pointOfInterest.Latitude) ); var x = (float)screenPoint.X; var y = (float)screenPoint.Y; var text = $"{pois.IndexOf(pointOfInterest)}"; var textBounds = new SKRect(); textPaint.MeasureText(text, ref textBounds); skSurface.Canvas.DrawCircle(x, y, 30f * scale, poiFill); skSurface.Canvas.DrawCircle(x, y, 30f * scale, poiStroke); skSurface.Canvas.DrawText(text, x - textBounds.MidX, y - textBounds.MidY, textPaint); } }
public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature, IGeometry geometry, SymbolCache symbolCache, float opacity) { var point = geometry as Point; var destination = viewport.WorldToScreen(point); if (style is CalloutStyle calloutStyle) { CalloutStyleRenderer.Draw(canvas, viewport, symbolCache, opacity, destination, calloutStyle); } else if (style is LabelStyle labelStyle) { LabelRenderer.Draw(canvas, labelStyle, feature, destination, opacity); } else if (style is SymbolStyle symbolStyle) { if (symbolStyle.BitmapId >= 0) { // todo: Remove this call. ImageStyle should be used instead of SymbolStyle with BitmapId ImageStyleRenderer.Draw(canvas, symbolStyle, destination, symbolCache, opacity, viewport.Rotation); } else { SymbolStyleRenderer.Draw(canvas, symbolStyle, destination, opacity, symbolStyle.SymbolType, viewport.Rotation); } } else if (style is ImageStyle imageStyle) { ImageStyleRenderer.Draw(canvas, imageStyle, destination, symbolCache, opacity, viewport.Rotation); } else if (style is VectorStyle vectorStyle) { // Use the SymbolStyleRenderer and specify Ellipse SymbolStyleRenderer.Draw(canvas, vectorStyle, destination, opacity, SymbolType.Ellipse); } else { throw new Exception($"Style of type '{style.GetType()}' is not supported for points"); } }
public bool Draw(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, IFeature feature, IStyle istyle, ISymbolCache symbolCache) { var style = ((VelocityIndicatorStyle)istyle); var position = feature.Geometry as Point; var dest = viewport.WorldToScreen(position); var zoom = 1 / (float)viewport.Resolution; canvas.Translate((float)dest.X, (float)dest.Y); //canvas.Scale(zoom, zoom); canvas.RotateDegrees((float)viewport.Rotation, 0.0f, 0.0f); //#TODO store paint with shader as static using (SKPaint paint = new SKPaint { Style = SKPaintStyle.StrokeAndFill, Color = SKColors.Red, StrokeWidth = 4 }) { //if (style.rotation == 0) //Weird artifacting on 0 rotation, no idea why. Seems Skia bug. // style.rotation = 180; // //SKMatrix shaderTransform = // SKMatrix.CreateScale((float)viewport.Resolution, (float)viewport.Resolution); //if (style.rotation != 0) // shaderTransform = SKMatrix.Concat(shaderTransform, SKMatrix.CreateRotationDegrees(-style.rotation)); canvas.DrawLine(new SKPoint(0, 0), new SKPoint(-style.velocity.X, style.velocity.Y), paint); } return(true); }
public bool Draw(Canvas canvas, IReadOnlyViewport viewport, ILayer layer, IFeature feature, IStyle style, ISymbolCache symbolCache) { if (!(feature.Geometry is global::Mapsui.Geometries.Point worldPoint)) { return(false); } var screenPoint = viewport.WorldToScreen(worldPoint); var color = new XamlMedia.Color() { R = (byte)rnd.Next(0, 256), G = (byte)rnd.Next(0, 256), B = (byte)rnd.Next(0, 256), A = (byte)(256.0 * layer.Opacity * style.Opacity) }; var path = new XamlShapes.Path { Fill = new XamlMedia.SolidColorBrush(color), Stroke = new XamlMedia.SolidColorBrush(XamlColors.Transparent), StrokeThickness = 0, }; path.Data = new XamlMedia.EllipseGeometry { Center = new XamlPoint(0, 0), RadiusX = 20 * 0.5, RadiusY = 20 * 0.5 }; var matrix = XamlMedia.Matrix.Identity; MatrixHelper.InvertY(ref matrix); MatrixHelper.Translate(ref matrix, screenPoint.X, screenPoint.Y); canvas.Children.Add(path); return(true); }
public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature, IGeometry geometry, float opacity, SymbolCache symbolCache = null) { if (style is LabelStyle labelStyle) { var worldCenter = geometry.BoundingBox.Centroid; var center = viewport.WorldToScreen(worldCenter); LabelRenderer.Draw(canvas, labelStyle, feature, (float)center.X, (float)center.Y, opacity); } else if (style is StyleCollection styleCollection) { foreach (var s in styleCollection) { Draw(canvas, viewport, s, feature, geometry, opacity, symbolCache); } } else if (style is VectorStyle vectorStyle) { var polygon = (Polygon)geometry; float lineWidth = 1; var lineColor = Color.Black; // default var fillColor = Color.Gray; // default var strokeCap = PenStrokeCap.Butt; // default var strokeJoin = StrokeJoin.Miter; // default var strokeMiterLimit = 4f; // default var strokeStyle = PenStyle.Solid; // default float[] dashArray = null; // default if (vectorStyle.Outline != null) { lineWidth = (float)vectorStyle.Outline.Width; lineColor = vectorStyle.Outline.Color; strokeCap = vectorStyle.Outline.PenStrokeCap; strokeJoin = vectorStyle.Outline.StrokeJoin; strokeMiterLimit = vectorStyle.Outline.StrokeMiterLimit; strokeStyle = vectorStyle.Outline.PenStyle; dashArray = vectorStyle.Outline.DashArray; } if (vectorStyle.Fill != null) { fillColor = vectorStyle.Fill?.Color; } using (var path = polygon.ToSkiaPath(viewport, canvas.LocalClipBounds, lineWidth)) using (var paintFill = new SKPaint { IsAntialias = true }) { // Is there a FillStyle? if (vectorStyle.Fill?.FillStyle == FillStyle.Solid) { paintFill.StrokeWidth = 0; paintFill.Style = SKPaintStyle.Fill; paintFill.PathEffect = null; paintFill.Shader = null; paintFill.Color = fillColor.ToSkia(opacity); canvas.DrawPath(path, paintFill); } else { paintFill.StrokeWidth = 1; paintFill.Style = SKPaintStyle.Stroke; paintFill.Shader = null; paintFill.Color = fillColor.ToSkia(opacity); var scale = 10.0f; var fillPath = new SKPath(); var matrix = SKMatrix.MakeScale(scale, scale); switch (vectorStyle.Fill?.FillStyle) { case FillStyle.Cross: fillPath.MoveTo(scale * 0.8f, scale * 0.8f); fillPath.LineTo(0, 0); fillPath.MoveTo(0, scale * 0.8f); fillPath.LineTo(scale * 0.8f, 0); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.DiagonalCross: fillPath.MoveTo(scale, scale); fillPath.LineTo(0, 0); fillPath.MoveTo(0, scale); fillPath.LineTo(scale, 0); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.BackwardDiagonal: fillPath.MoveTo(0, scale); fillPath.LineTo(scale, 0); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.ForwardDiagonal: fillPath.MoveTo(scale, scale); fillPath.LineTo(0, 0); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Dotted: paintFill.Style = SKPaintStyle.StrokeAndFill; fillPath.AddCircle(scale * 0.5f, scale * 0.5f, scale * 0.35f); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Horizontal: fillPath.MoveTo(0, scale * 0.5f); fillPath.LineTo(scale, scale * 0.5f); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Vertical: fillPath.MoveTo(scale * 0.5f, 0); fillPath.LineTo(scale * 0.5f, scale); paintFill.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath); break; case FillStyle.Bitmap: paintFill.Style = SKPaintStyle.Fill; var image = GetImage(symbolCache, vectorStyle.Fill.BitmapId); if (image != null) { paintFill.Shader = image.ToShader(SKShaderTileMode.Repeat, SKShaderTileMode.Repeat); } break; case FillStyle.BitmapRotated: paintFill.Style = SKPaintStyle.Fill; image = GetImage(symbolCache, vectorStyle.Fill.BitmapId); if (image != null) { paintFill.Shader = image.ToShader(SKShaderTileMode.Repeat, SKShaderTileMode.Repeat, SKMatrix.MakeRotation((float)(viewport.Rotation * System.Math.PI / 180.0f), image.Width >> 1, image.Height >> 1)); } break; default: paintFill.PathEffect = null; break; } // Do this, because if not, path isn't filled complete using (new SKAutoCanvasRestore(canvas)) { canvas.ClipPath(path); var bounds = path.Bounds; // Make sure, that the brush starts with the correct position var inflate = ((int)path.Bounds.Width * 0.3f / scale) * scale; bounds.Inflate(inflate, inflate); // Draw rect with bigger size, which is clipped by path canvas.DrawRect(bounds, paintFill); } } if (vectorStyle.Outline != null) { using (var paintStroke = new SKPaint { IsAntialias = true }) { paintStroke.Style = SKPaintStyle.Stroke; paintStroke.StrokeWidth = lineWidth; paintStroke.Color = lineColor.ToSkia(opacity); paintStroke.StrokeCap = strokeCap.ToSkia(); paintStroke.StrokeJoin = strokeJoin.ToSkia(); paintStroke.StrokeMiter = strokeMiterLimit; if (strokeStyle != PenStyle.Solid) { paintStroke.PathEffect = strokeStyle.ToSkia(lineWidth, dashArray); } else { paintStroke.PathEffect = null; } canvas.DrawPath(path, paintStroke); } } } } }
public bool Draw(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, IFeature feature, IStyle istyle, ISymbolCache symbolCache) { var style = ((TiledBitmapStyle)istyle); if (style.image == null) { return(false); } var position = feature.Geometry.BoundingBox.Centroid; var dest = viewport.WorldToScreen(position); var zoom = 1 / (float)viewport.Resolution; canvas.Translate((float)dest.X, (float)dest.Y); canvas.Scale(zoom, zoom); canvas.RotateDegrees((float)viewport.Rotation, 0.0f, 0.0f); if (style.rotation != 0) { canvas.RotateDegrees(style.rotation, 0.0f, 0.0f); } //#TODO store paint with shader in the style using (SKPaint paint = new SKPaint()) { if (style.rotation == 0) //Weird artifacting on 0 rotation, no idea why. Seems Skia bug. { style.rotation = 180; } SKMatrix shaderTransform = SKMatrix.CreateScale((float)viewport.Resolution, (float)viewport.Resolution); if (style.rotation != 0) { shaderTransform = SKMatrix.Concat(shaderTransform, SKMatrix.CreateRotationDegrees(-style.rotation)); } paint.Shader = SKShader.CreateImage(style.image, SKShaderTileMode.Repeat, SKShaderTileMode.Repeat, shaderTransform); paint.ColorFilter = style.colorFilter; //style.image.Encode().SaveTo(File.Create($"P:/{style.image.UniqueId}.png")); if (style.ellipse) { canvas.DrawOval(0, 0, style.rect.Right, style.rect.Bottom, paint); } else { canvas.DrawRect(style.rect, paint); } if (style.border) { var borderPaint = new SKPaint { Style = SKPaintStyle.Stroke, Color = style.color }; if (style.ellipse) { canvas.DrawOval(0, 0, style.rect.Right, style.rect.Bottom, borderPaint); } else { canvas.DrawRect(style.rect, borderPaint); } } } return(true); }
public bool Draw(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, IFeature feature, IStyle istyle, ISymbolCache symbolCache) { var style = ((MarkerIconStyle)istyle); if (style.markerIcon == null) { return(false); } var position = feature.Geometry as Point; var dest = viewport.WorldToScreen(position); var zoom = 1 / (float)viewport.Resolution; canvas.Translate((float)dest.X, (float)dest.Y); canvas.Scale(0.7f, 0.7f); canvas.RotateDegrees((float)viewport.Rotation, 0.0f, 0.0f); SKPoint textOffset = new SKPoint(style.finalSize.Width, style.finalSize.Height / 2); if (!string.IsNullOrEmpty(style.text)) { if (zoom > 1.5f) { zoom = 1.5f; } if (zoom < 0.5f) { zoom = 0.5f; } renderPaint.TextSize = 32 * zoom; SKRect bounds = new SKRect(); //renderPaint.GetFontMetrics(out var fontMet); //renderPaint.MeasureText(style.text, ref bounds); var textHeight = (style.finalSize.Height / 2); //if (zoom < 1.5f) //{ // textHeight += bounds.Height/2; //} textOffset = new SKPoint(style.finalSize.Width, textHeight); } if (style.shadow) { var targetRect = style.finalRect; var shadowOffset = style.ShadowOffset; targetRect.Offset(shadowOffset); renderPaint.Color = new SKColor(0, 0, 0, (byte)(style.Opacity * 0.8f * 255)); renderPaint.ColorFilter = SkiaSharp.SKColorFilter.CreateLighting(renderPaint.Color, new SKColor(0, 0, 0)); if (style.SymbolRotation != 0) { canvas.RotateDegrees(style.SymbolRotation, 0.0f, 0.0f); } canvas.DrawImage(style.markerIcon, targetRect, renderPaint); if (style.SymbolRotation != 0) { canvas.RotateDegrees(-style.SymbolRotation, 0.0f, 0.0f); //No rotation for text } //canvas.DrawRect(targetRect, renderPaint); if (!string.IsNullOrEmpty(style.text) && zoom > 1) { canvas.DrawText(style.text, textOffset + style.ShadowOffset, renderPaint); } } renderPaint.Color = SKColor.Empty.WithAlpha((byte)(style.Opacity * 255)); renderPaint.ColorFilter = style.colorFilter; if (style.SymbolRotation != 0) { canvas.RotateDegrees(style.SymbolRotation, 0.0f, 0.0f); } canvas.DrawImage(style.markerIcon, style.finalRect, renderPaint); if (!string.IsNullOrEmpty(style.text)) { if (style.SymbolRotation != 0) { canvas.RotateDegrees(-style.SymbolRotation, 0.0f, 0.0f); //No rotation for text } renderPaint.Color = style.color.WithAlpha((byte)(style.Opacity * 255)); renderPaint.ColorFilter = null; canvas.DrawText(style.text, textOffset, renderPaint); } return(true); }