public static bool DrawSymbol(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, double x, double y, SymbolStyle symbolStyle) { var opacity = (float)(layer.Opacity * symbolStyle.Opacity); var(destX, destY) = viewport.WorldToScreenXY(x, y); canvas.Save(); canvas.Translate((float)destX, (float)destY); canvas.Scale((float)symbolStyle.SymbolScale, (float)symbolStyle.SymbolScale); if (symbolStyle.SymbolOffset.IsRelative) { canvas.Translate((float)(SymbolStyle.DefaultWidth * symbolStyle.SymbolOffset.X), (float)(-SymbolStyle.DefaultWidth * symbolStyle.SymbolOffset.Y)); } else { canvas.Translate((float)symbolStyle.SymbolOffset.X, (float)-symbolStyle.SymbolOffset.Y); } if (symbolStyle.SymbolRotation != 0) { var rotation = symbolStyle.SymbolRotation; if (symbolStyle.RotateWithMap) { rotation += viewport.Rotation; } canvas.RotateDegrees((float)rotation); } var width = (float)SymbolStyle.DefaultWidth; var halfWidth = width / 2; var halfHeight = (float)SymbolStyle.DefaultHeight / 2; using var fillPaint = CreateFillPaint(symbolStyle.Fill, opacity); using var linePaint = CreateLinePaint(symbolStyle.Outline, opacity); switch (symbolStyle.SymbolType) { case SymbolType.Ellipse: DrawCircle(canvas, 0, 0, halfWidth, fillPaint, linePaint); break; case SymbolType.Rectangle: var rect = new SKRect(-halfWidth, -halfHeight, halfWidth, halfHeight); DrawRect(canvas, rect, fillPaint, linePaint); break; case SymbolType.Triangle: DrawTriangle(canvas, 0, 0, width, fillPaint, linePaint); break; default: // Invalid value throw new ArgumentOutOfRangeException(); } canvas.Restore(); return(true); }
public static void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IStyle style, IFeature feature, double x, double y, SymbolCache symbolCache, float opacity) { var(destX, destY) = viewport.WorldToScreenXY(x, y); if (style is CalloutStyle calloutStyle) { CalloutStyleRenderer.Draw(canvas, viewport, opacity, destX, destY, calloutStyle); } else if (style is LabelStyle labelStyle) { LabelRenderer.Draw(canvas, labelStyle, feature, destX, destY, 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, destX, destY, symbolCache, opacity, viewport.Rotation); } else { SymbolStyleRenderer.Draw(canvas, symbolStyle, destX, destY, opacity, symbolStyle.SymbolType, viewport.Rotation); } } else if (style is ImageStyle imageStyle) { ImageStyleRenderer.Draw(canvas, imageStyle, destX, destY, symbolCache, opacity, viewport.Rotation); } else if (style is VectorStyle vectorStyle) { // Use the SymbolStyleRenderer and specify Ellipse SymbolStyleRenderer.Draw(canvas, vectorStyle, destX, destY, 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, Styles.IStyle style, ISymbolCache symbolCache, long iteration) { var centroid = feature.Extent?.Centroid; if (centroid is null) { return(false); } var calloutStyle = (CalloutStyle)style; // Todo: Use opacity var opacity = (float)(layer.Opacity * style.Opacity); var(x, y) = viewport.WorldToScreenXY(centroid.X, centroid.Y); if (calloutStyle.BitmapId < 0 || calloutStyle.Invalidated) { if (calloutStyle.Content < 0 && calloutStyle.Type == CalloutType.Custom) { return(false); } if (calloutStyle.Invalidated) { UpdateContent(calloutStyle); } RenderCallout(calloutStyle); } // Now we have the complete callout rendered, so we could draw it if (calloutStyle.BitmapId < 0) { return(false); } var picture = (SKPicture)BitmapRegistry.Instance.Get(calloutStyle.BitmapId); // Calc offset (relative or absolute) MPoint symbolOffset = calloutStyle.SymbolOffset.ToPoint(); if (calloutStyle.SymbolOffset.IsRelative) { symbolOffset.X *= picture.CullRect.Width; symbolOffset.Y *= picture.CullRect.Height; } var rotation = (float)calloutStyle.SymbolRotation; if (viewport.Rotation != 0) { if (calloutStyle.RotateWithMap) { rotation += (float)viewport.Rotation; } if (calloutStyle.SymbolOffsetRotatesWithMap) { symbolOffset = symbolOffset.Rotate(-viewport.Rotation); } } // Save state of the canvas, so we could move and rotate the canvas canvas.Save(); // Move 0/0 to the Anchor point of Callout canvas.Translate((float)(x - symbolOffset.X), (float)(y - symbolOffset.Y)); canvas.Scale((float)calloutStyle.SymbolScale, (float)calloutStyle.SymbolScale); // 0/0 are assumed at center of image, but Picture has 0/0 at left top position canvas.RotateDegrees(rotation); canvas.Translate((float)calloutStyle.Offset.X, (float)calloutStyle.Offset.Y); using var skPaint = new SKPaint() { IsAntialias = true }; canvas.DrawPicture(picture, skPaint); canvas.Restore(); return(true); }
private static bool DrawImage(SKCanvas canvas, IReadOnlyViewport viewport, ILayer layer, double x, double y, SymbolStyle symbolStyle, ISymbolCache symbolCache) { var opacity = (float)(layer.Opacity * symbolStyle.Opacity); var(destX, destY) = viewport.WorldToScreenXY(x, y); if (symbolStyle.BitmapId < 0) { return(false); } var bitmap = (BitmapInfo)symbolCache.GetOrCreate(symbolStyle.BitmapId); if (bitmap == null) { return(false); } // Calc offset (relative or absolute) var offsetX = symbolStyle.SymbolOffset.IsRelative ? bitmap.Width * symbolStyle.SymbolOffset.X : symbolStyle.SymbolOffset.X; var offsetY = symbolStyle.SymbolOffset.IsRelative ? bitmap.Height * symbolStyle.SymbolOffset.Y : symbolStyle.SymbolOffset.Y; var rotation = (float)symbolStyle.SymbolRotation; if (symbolStyle.RotateWithMap) { rotation += (float)viewport.Rotation; } switch (bitmap.Type) { case BitmapType.Bitmap: if (bitmap.Bitmap == null) { return(false); } BitmapRenderer.Draw(canvas, bitmap.Bitmap, (float)destX, (float)destY, rotation, (float)offsetX, (float)offsetY, opacity: opacity, scale: (float)symbolStyle.SymbolScale); break; case BitmapType.Picture: if (bitmap.Picture == null) { return(false); } PictureRenderer.Draw(canvas, bitmap.Picture, (float)destX, (float)destY, rotation, (float)offsetX, (float)offsetY, opacity: opacity, scale: (float)symbolStyle.SymbolScale, blendModeColor: symbolStyle.BlendModeColor); break; case BitmapType.Svg: // Todo: Perhaps remove BitmapType.Svg and SvgRenderer? // It looks like Bitmaptype.Svg is not use at all the the momement. if (bitmap.Svg == null) { return(false); } SvgRenderer.Draw(canvas, bitmap.Svg, (float)destX, (float)destY, rotation, (float)offsetX, (float)offsetY, opacity: opacity, scale: (float)symbolStyle.SymbolScale); break; case BitmapType.Sprite: if (bitmap.Sprite == null) { return(false); } var sprite = bitmap.Sprite; if (sprite.Data == null) { var bitmapAtlas = (BitmapInfo)symbolCache.GetOrCreate(sprite.Atlas); sprite.Data = bitmapAtlas?.Bitmap?.Subset(new SKRectI(sprite.X, sprite.Y, sprite.X + sprite.Width, sprite.Y + sprite.Height)); } if (sprite.Data is SKImage skImage) { BitmapRenderer.Draw(canvas, skImage, (float)destX, (float)destY, rotation, (float)offsetX, (float)offsetY, opacity: opacity, scale: (float)symbolStyle.SymbolScale); } break; } return(true); }