Example #1
0
        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, center, 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
                float   dashOffset       = 0;                 // 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;
                    dashOffset       = vectorStyle.Outline.DashOffset;
                }

                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.CreateScale(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.CreateRotation((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, dashOffset);
                                }
                                else
                                {
                                    paintStroke.PathEffect = null;
                                }
                                canvas.DrawPath(path, paintStroke);
                            }
                        }
                    }
            }
        }
Example #2
0
        public static void Draw(SKCanvas canvas, IViewport viewport, IStyle style, IFeature feature, IGeometry geometry,
                                float opacity, SymbolCache symbolCache = null)
        {
            if (style is LabelStyle)
            {
                var worldCenter = geometry.GetBoundingBox().GetCentroid();
                var center      = viewport.WorldToScreen(worldCenter);
                LabelRenderer.Draw(canvas, (LabelStyle)style, feature, (float)center.X, (float)center.Y, opacity);
            }
            else
            {
                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

                var vectorStyle = style as VectorStyle;

                if (vectorStyle != 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;

                    fillColor = vectorStyle.Fill?.Color;
                }

                using (var path = ToSkia(viewport, polygon))
                {
                    using (var paint = new SKPaint())
                    {
                        paint.IsAntialias = true;

                        // Is there a FillStyle?
                        if (vectorStyle.Fill?.FillStyle == FillStyle.Solid)
                        {
                            paint.StrokeWidth = lineWidth;
                            paint.Style       = SKPaintStyle.Fill;
                            paint.Color       = fillColor.ToSkia(opacity);
                            canvas.DrawPath(path, paint);
                        }
                        else
                        {
                            paint.StrokeWidth = 1;
                            paint.Style       = SKPaintStyle.Stroke;
                            paint.Color       = fillColor.ToSkia(opacity);
                            float    scale    = 10.0f;
                            SKPath   fillPath = new SKPath();
                            SKMatrix 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);
                                paint.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);
                                paint.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath);
                                break;

                            case FillStyle.BackwardDiagonal:
                                fillPath.MoveTo(0, scale);
                                fillPath.LineTo(scale, 0);
                                paint.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath);
                                break;

                            case FillStyle.ForwardDiagonal:
                                fillPath.MoveTo(scale, scale);
                                fillPath.LineTo(0, 0);
                                paint.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath);
                                break;

                            case FillStyle.Dotted:
                                paint.Style = SKPaintStyle.StrokeAndFill;
                                fillPath.AddCircle(scale * 0.5f, scale * 0.5f, scale * 0.35f);
                                paint.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath);
                                break;

                            case FillStyle.Horizontal:
                                fillPath.MoveTo(0, scale * 0.5f);
                                fillPath.LineTo(scale, scale * 0.5f);
                                paint.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath);
                                break;

                            case FillStyle.Vertical:
                                fillPath.MoveTo(scale * 0.5f, 0);
                                fillPath.LineTo(scale * 0.5f, scale);
                                paint.PathEffect = SKPathEffect.Create2DPath(matrix, fillPath);
                                break;

                            case FillStyle.Bitmap:
                                paint.Style  = SKPaintStyle.Fill;
                                paint.Shader = symbolCache.GetOrCreate(vectorStyle.Fill.BitmapId).Bitmap.ToShader(SKShaderTileMode.Repeat, SKShaderTileMode.Repeat);
                                break;

                            case FillStyle.BitmapRotated:
                                paint.Style = SKPaintStyle.Fill;
                                SKImage bitmap = symbolCache.GetOrCreate(vectorStyle.Fill.BitmapId).Bitmap;
                                paint.Shader = bitmap.ToShader(SKShaderTileMode.Repeat,
                                                               SKShaderTileMode.Repeat,
                                                               SKMatrix.MakeRotation((float)(viewport.Rotation * System.Math.PI / 180.0f), bitmap.Width >> 1, bitmap.Height >> 1));
                                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, paint);
                            }
                        }
                    }

                    using (var paint = new SKPaint())
                    {
                        paint.IsAntialias = true;
                        paint.Style       = SKPaintStyle.Stroke;
                        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);
                        }
                        canvas.DrawPath(path, paint);
                    }
                }
            }
        }