예제 #1
0
        private static SKMatrix CreateRotationMatrix(IReadOnlyViewport viewport, MRect rect, SKMatrix priorMatrix)
        {
            // The front-end sets up the canvas with a matrix based on screen scaling (e.g. retina).
            // We need to retain that effect by combining our matrix with the incoming matrix.

            // We'll create four matrices in addition to the incoming matrix. They perform the
            // zoom scale, focal point offset, user rotation and finally, centering in the screen.

            var userRotation     = SKMatrix.CreateRotationDegrees((float)viewport.Rotation);
            var focalPointOffset = SKMatrix.CreateTranslation(
                (float)(rect.Left - viewport.Center.X),
                (float)(viewport.Center.Y - rect.Top));
            var zoomScale      = SKMatrix.CreateScale((float)(1.0 / viewport.Resolution), (float)(1.0 / viewport.Resolution));
            var centerInScreen = SKMatrix.CreateTranslation((float)(viewport.Width / 2.0), (float)(viewport.Height / 2.0));

            // We'll concatenate them like so: incomingMatrix * centerInScreen * userRotation * zoomScale * focalPointOffset

            var matrix = SKMatrix.Concat(zoomScale, focalPointOffset);

            matrix = SKMatrix.Concat(userRotation, matrix);
            matrix = SKMatrix.Concat(centerInScreen, matrix);
            matrix = SKMatrix.Concat(priorMatrix, matrix);

            return(matrix);
        }
예제 #2
0
        public void TransformConvertsToMatrix()
        {
            var matrix44 = SKMatrix44.CreateRotationDegrees(0, 0, 1, 45);
            var matrix   = SKMatrix.CreateRotationDegrees(45);

            Assert.Equal(matrix.Values, matrix44.Matrix.Values);
        }
예제 #3
0
        /// <inheritdoc />
        public override void Render(SKCanvas canvas, SKRect bounds, SKPaint paint)
        {
            _lastBounds = bounds;

            // For brevity's sake
            ColorGradient gradient = Properties.Colors.BaseValue;

            SKMatrix matrix = SKMatrix.Concat(
                SKMatrix.CreateRotationDegrees(Properties.Rotation, bounds.MidX, bounds.MidY),
                SKMatrix.CreateTranslation(_scrollX, _scrollY)
                );

            // LinearGradientRepeatMode.Mirror is currently the only setting that requires a different tile mode
            SKShaderTileMode tileMode = Properties.RepeatMode.CurrentValue == LinearGradientRepeatMode.Mirror
                ? SKShaderTileMode.Mirror
                : SKShaderTileMode.Repeat;

            // Render gradient
            paint.Shader = SKShader.CreateLinearGradient(
                new SKPoint(bounds.Left, bounds.Top),
                new SKPoint(
                    (Properties.Orientation == LinearGradientOrientationMode.Horizontal ? bounds.Right : bounds.Left) * Properties.WaveSize / 100,
                    (Properties.Orientation == LinearGradientOrientationMode.Horizontal ? bounds.Top : bounds.Bottom) * Properties.WaveSize / 100
                    ),
                gradient.GetColorsArray(0, Properties.RepeatMode.CurrentValue == LinearGradientRepeatMode.RepeatSeamless),
                gradient.GetPositionsArray(0, Properties.RepeatMode.CurrentValue == LinearGradientRepeatMode.RepeatSeamless),
                tileMode,
                matrix
                );

            canvas.DrawRect(bounds, paint);
            paint.Shader?.Dispose();
            paint.Shader = null;
        }
예제 #4
0
        public void ImplicitFromMatrix()
        {
            var matrix   = SKMatrix.CreateRotationDegrees(45);
            var matrix44 = (SKMatrix44)matrix;

            Assert.Equal(matrix.Values, matrix44.Matrix.Values);
        }
예제 #5
0
        internal override void Render(SKSurface surface)
        {
            foreach (var shape in Shapes)
            {
                surface.Canvas.Save();

                var visualMatrix = surface.Canvas.TotalMatrix;

                visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(shape.Offset.X, shape.Offset.Y));

                if (shape.Scale != new Vector2(1, 1))
                {
                    visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateScale(shape.Scale.X, shape.Scale.Y));
                }

                if (shape.RotationAngleInDegrees != 0)
                {
                    visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateRotationDegrees(shape.RotationAngleInDegrees, shape.CenterPoint.X, shape.CenterPoint.Y));
                }

                if (shape.TransformMatrix != Matrix3x2.Identity)
                {
                    visualMatrix = visualMatrix.PreConcat(shape.TransformMatrix.ToSKMatrix44().Matrix);
                }

                surface.Canvas.SetMatrix(visualMatrix);

                shape.Render(surface);

                surface.Canvas.Restore();
            }
        }
예제 #6
0
        public void RotationToMatrixIsCorrect()
        {
            var m   = SKMatrix.CreateRotationDegrees(45);
            var rsm = SKRotationScaleMatrix.CreateRotationDegrees(45, 0, 0).ToMatrix();

            Assert.Equal(m.Values, rsm.Values);
        }
예제 #7
0
        public void ImplicitFromRotationScale()
        {
            var rs       = SKRotationScaleMatrix.CreateRotationDegrees(45, 0, 0);
            var matrix   = SKMatrix.CreateRotationDegrees(45);
            var matrix44 = (SKMatrix44)rs.ToMatrix();

            Assert.Equal(matrix.Values, matrix44.Matrix.Values);
        }
예제 #8
0
 public SkiaHatchBrush(ArgbColor color, float angle, float distance = 5, float widh = 2f)
 {
     _skPaint = new SKPaint()
     {
         PathEffect  = SKPathEffect.Create2DLine(widh, Multiply(SKMatrix.CreateRotationDegrees(angle), SKMatrix.CreateScale(1.007f, distance))),
         Color       = color.ToSKColor(),
         IsAntialias = true,
     };
 }
예제 #9
0
        public void Rotate90(bool left)
        {
            float degree = left ? -90 : 90;

            _rotatedDegrees += degree;

            Matrix = Matrix.PostConcat(SKMatrix.CreateRotationDegrees(degree));

            CanvasView?.InvalidateSurface();
        }
예제 #10
0
        public void CanRotatePoints()
        {
            var point = new SKPoint(40, -10);

            var matrix   = SKMatrix.CreateRotationDegrees(90);
            var newPoint = matrix.MapPoint(point);

            Assert.Equal(10, newPoint.X, PRECISION);
            Assert.Equal(40, newPoint.Y, PRECISION);
        }
예제 #11
0
        private void AddRectangle2()
        {
            var rectangle = new SkiaSharp.Elements.Rectangle(SKRect.Create(120, 150, 100, 100))
            {
                FillColor      = new SKColor(SKColors.SkyBlue.Red, SKColors.SkyBlue.Green, SKColors.SkyBlue.Blue, 200),
                Transformation = SKMatrix.CreateRotationDegrees(45)
            };

            canvas.Elements.Add(rectangle);
        }
예제 #12
0
        public static void AddOpenArrow(this SKPath path, SKPoint point, SKPoint normal)
        {
            var matrix1  = SKMatrix.CreateRotationDegrees(35);
            var rotated1 = matrix1.MapVector(normal.X, normal.Y);
            var matrix2  = SKMatrix.CreateRotationDegrees(-35);
            var rotated2 = matrix2.MapVector(normal.X, normal.Y);

            path.MoveTo(point + new SKPoint(rotated1.X * 8, rotated1.Y * 8));
            path.LineTo(point);
            path.LineTo(point + new SKPoint(rotated2.X * 8, rotated2.Y * 8));
        }
예제 #13
0
        private static void RenderVisual(SKSurface surface, SKImageInfo info, Visual visual)
        {
            if (visual.Opacity != 0)
            {
                surface.Canvas.Save();

                var visualMatrix = surface.Canvas.TotalMatrix;

                visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(visual.Offset.X, visual.Offset.Y));

                if (visual.RotationAngleInDegrees != 0)
                {
                    visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateRotationDegrees(visual.RotationAngleInDegrees, visual.CenterPoint.X, visual.CenterPoint.Y));
                }

                if (visual.TransformMatrix != Matrix4x4.Identity)
                {
                    visualMatrix = visualMatrix.PreConcat(visual.TransformMatrix.ToSKMatrix44().Matrix);
                }

                surface.Canvas.SetMatrix(visualMatrix);

                if (visual.Clip is InsetClip insetClip)
                {
                    surface.Canvas.ClipRect(new SKRect {
                        Top    = insetClip.TopInset,
                        Bottom = insetClip.BottomInset,
                        Left   = insetClip.LeftInset,
                        Right  = insetClip.RightInset
                    });
                }

                visual.Render(surface, info);

                switch (visual)
                {
                case SpriteVisual spriteVisual:
                    foreach (var inner in spriteVisual.Children)
                    {
                        RenderVisual(surface, info, inner);
                    }
                    break;

                case ContainerVisual containerVisual:
                    foreach (var inner in containerVisual.Children)
                    {
                        RenderVisual(surface, info, inner);
                    }
                    break;
                }

                surface.Canvas.Restore();
            }
        }
예제 #14
0
        public void WillFailToTransformWithInvalidTransformation()
        {
            var rect   = SKRect.Create(10, 10, 100, 100);
            var offset = rect;

            offset.Offset(2, 2);

            var rrect       = new SKRoundRect(rect, 5, 5);
            var transformed = rrect.Transform(SKMatrix.CreateRotationDegrees(30));

            Assert.Null(transformed);
        }
예제 #15
0
        /**********************************************************************
         *********************************************************************/
        // draws an arrow from receiver to sender for the given round
        static void DrawAckArrow(SKCanvas canvas, int round, SKPaint paint, String part, String dupAck, String cwnd, String tresh)
        {
            SKPoint arrowBegin, arrowEnd;

            arrowBegin = new SKPoint();
            arrowEnd   = new SKPoint();

            switch (part)
            {
            case "start":
                // arrow start
                arrowBegin = new SKPoint(xEnd * xe, (yStart + yWidthStep * round) * ye);
                arrowEnd   = new SKPoint((xEnd - arrowLength) * xe, (yStart + yWidthStep * round) * ye);
                break;

            case "arrive":
                // arrow arrive
                arrowBegin = new SKPoint((xStart + arrowLength) * xe, (yStart + yWidthStep * round) * ye);
                arrowEnd   = new SKPoint(xStart * xe, (yStart + yWidthStep * round) * ye);
                DrawTextDupAck(canvas, round, dupAck, sk_blackTextSmall);
                DrawTextCwnd(canvas, round, cwnd, sk_blackTextSmall);
                DrawTextTresh(canvas, round, tresh, sk_blackTextSmall);
                break;
            }
            canvas.DrawLine(arrowBegin, arrowEnd, paint);

            // arrow head
            //calculate stuff
            double a = Math.Abs(arrowBegin.Y - arrowEnd.Y);
            double b = Math.Abs(arrowBegin.X - arrowEnd.X);

            //arrow head: calculate rotation degree
            double cos            = a / b;
            double arcCos         = Math.Acos(cos);
            double degree         = arcCos * (180.0 / Math.PI);
            float  rotationDegree = (float)degree - 45f;

            //arrow head: draw
            SKPath head = new SKPath();

            head.MoveTo(arrowEnd);
            head.RLineTo(xPercent(0.02f), -xPercent(0.01f));
            head.RLineTo(xPercent(0.0f), xPercent(0.02f));
            head.Close();
            var rotate = SKMatrix.CreateRotationDegrees(rotationDegree, arrowEnd.X, arrowEnd.Y);

            //head.Transform(rotate);
            canvas.DrawPath(head, paint);
        }
예제 #16
0
        private void RenderVisual(SKSurface surface, SKImageInfo info, Visual visual)
        {
            if (visual.Opacity != 0 && visual.IsVisible)
            {
                surface.Canvas.Save();

                var visualMatrix = surface.Canvas.TotalMatrix;

                visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(visual.Offset.X, visual.Offset.Y));
                visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(visual.AnchorPoint.X, visual.AnchorPoint.Y));

                if (visual.RotationAngleInDegrees != 0)
                {
                    visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateRotationDegrees(visual.RotationAngleInDegrees, visual.CenterPoint.X, visual.CenterPoint.Y));
                }

                if (visual.TransformMatrix != Matrix4x4.Identity)
                {
                    visualMatrix = visualMatrix.PreConcat(visual.TransformMatrix.ToSKMatrix44().Matrix);
                }

                surface.Canvas.SetMatrix(visualMatrix);

                ApplyClip(surface, visual);

                using var opacityDisposable = PushOpacity(visual.Opacity);

                visual.Render(surface, info);

                switch (visual)
                {
                case SpriteVisual spriteVisual:
                    foreach (var inner in spriteVisual.Children)
                    {
                        RenderVisual(surface, info, inner);
                    }
                    break;

                case ContainerVisual containerVisual:
                    foreach (var inner in containerVisual.Children)
                    {
                        RenderVisual(surface, info, inner);
                    }
                    break;
                }

                surface.Canvas.Restore();
            }
        }
예제 #17
0
        private void Play()
        {
            new Animation((value) =>
            {
                canvas.SuspendLayout();

                _rectangle.Transformation = SKMatrix.CreateRotationDegrees(360 * (float)value);

                _rectangle.Location = new SKPoint(_startLocation.X + (100 * (float)value),
                                                  _startLocation.Y + (100 * (float)value));

                canvas.ResumeLayout(true);
            })
            .Commit(this, "Anim", length: 2000, easing: Easing.SpringOut);
        }
예제 #18
0
        public static SKMatrix ToSKMatrix(this IViewport viewport)
        {
            var mapCenterX         = (float)viewport.Width * 0.5f;
            var mapCenterY         = (float)viewport.Height * 0.5f;
            var invertedResolution = 1f / (float)viewport.Resolution;

            var matrix = SKMatrix.CreateScale(invertedResolution, invertedResolution, mapCenterX, mapCenterY);

            matrix = SKMatrix.Concat(matrix, SKMatrix.CreateScale(1, -1, 0, -mapCenterY)); // As a consequence images will be up side down :(
            if (viewport.IsRotated)
            {
                matrix = SKMatrix.Concat(matrix, SKMatrix.CreateRotationDegrees((float)-viewport.Rotation));
            }
            matrix = SKMatrix.Concat(matrix, SKMatrix.CreateTranslation((float)-viewport.Center.X, (float)-viewport.Center.Y));
            return(matrix);
        }
예제 #19
0
        internal void RenderVisual(SKSurface surface, Visual visual)
        {
            if (visual.Opacity != 0 && visual.IsVisible)
            {
                if (visual.ShadowState is { } shadow)
                {
                    surface.Canvas.SaveLayer(shadow.Paint);
                }
                else
                {
                    surface.Canvas.Save();
                }

                var visualMatrix = surface.Canvas.TotalMatrix;

                visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(visual.Offset.X, visual.Offset.Y));
                visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateTranslation(visual.AnchorPoint.X, visual.AnchorPoint.Y));

                if (visual.RotationAngleInDegrees != 0)
                {
                    visualMatrix = visualMatrix.PreConcat(SKMatrix.CreateRotationDegrees(visual.RotationAngleInDegrees, visual.CenterPoint.X, visual.CenterPoint.Y));
                }

                if (visual.TransformMatrix != Matrix4x4.Identity)
                {
                    visualMatrix = visualMatrix.PreConcat(visual.TransformMatrix.ToSKMatrix44().Matrix);
                }

                surface.Canvas.SetMatrix(visualMatrix);

                ApplyClip(surface, visual);

                using var opacityDisposable = PushOpacity(visual.Opacity);

                visual.Render(surface);

                if (visual is ContainerVisual containerVisual)
                {
                    var children = containerVisual.GetChildrenInRenderOrder();
                    for (var i = 0; i < children.Count; i++)
                    {
                        RenderVisual(surface, children[i]);
                    }
                }

                surface.Canvas.Restore();
            }
예제 #20
0
        /// <inheritdoc />
        public override void Render(SKCanvas canvas, SKRect bounds, SKPaint paint)
        {
            // TODO: Investigate performance
            paint.Shader = SKShader.CreateSweepGradient(
                new SKPoint(bounds.MidX, bounds.MidY),
                Properties.Colors.BaseValue.GetColorsArray(Properties.ColorsMultiplier),
                Properties.Colors.BaseValue.GetPositionsArray(Properties.ColorsMultiplier),
                SKShaderTileMode.Clamp,
                Properties.StartAngle,
                Properties.EndAngle,
                SKMatrix.CreateRotationDegrees(_rotation, bounds.MidX, bounds.MidY)
                );

            canvas.DrawRect(bounds, paint);
            paint.Shader?.Dispose();
            paint.Shader = null;
        }
예제 #21
0
        void DrawRotatedWithMatrices(SKCanvas canvas, SKPath path, SKPaint fill, SKPaint outline, ChartData item, float degrees, int cx, int cy)
        {
            var identity  = SKMatrix.CreateIdentity();
            var translate = SKMatrix.CreateTranslation(-cx, -cy);
            var rotate    = SKMatrix.CreateRotationDegrees(degrees);

            //angleBox.Text = degrees.ToString();
            var translate2 = SKMatrix.CreateTranslation(cx, cy);

            SKMatrix.PostConcat(ref identity, translate);
            SKMatrix.PostConcat(ref identity, rotate);
            SKMatrix.PostConcat(ref identity, translate2);


            path.Transform(identity);
            canvas.DrawPath(path, fill);
            canvas.DrawPath(path, outline);
        }
예제 #22
0
        /// <inheritdoc />
        public override void Render(SKCanvas canvas, SKRect bounds, SKPaint paint)
        {
            SKMatrix matrix = SKMatrix.Concat(
                SKMatrix.CreateTranslation(_scrollX, _scrollY),
                SKMatrix.CreateRotationDegrees(Properties.Rotation, bounds.MidX, bounds.MidY)
                );

            paint.Shader = SKShader.CreateLinearGradient(
                new SKPoint(bounds.Left, bounds.Top),
                new SKPoint(bounds.Right, bounds.Top),
                Properties.Colors.BaseValue.GetColorsArray(Properties.ColorsMultiplier),
                Properties.Colors.BaseValue.GetPositionsArray(Properties.ColorsMultiplier),
                SKShaderTileMode.Repeat,
                matrix
                );
            canvas.DrawRect(bounds, paint);
            paint.Shader?.Dispose();
            paint.Shader = null;
        }
예제 #23
0
        private void Play()
        {
            new Animation((value) =>
            {
                canvas.SuspendLayout();

                for (var y = 0; y < 10; y++)
                {
                    var index = y * 10;
                    for (var x = 0; x < 10; x++)
                    {
                        var ele = canvas.Elements[index + x];

                        var startX = ((x + 1) * 40);
                        var diffX  = startX - 400;
                        if (diffX < 0)
                        {
                            diffX *= -1;
                        }
                        diffX   = diffX - startX;
                        startX += 60;

                        var startY = ((y + 1) * 40);
                        var diffY  = startY - 400;
                        if (diffY < 0)
                        {
                            diffY *= -1;
                        }
                        diffY   = diffY - startY;
                        startY += 60;

                        ele.Location = new SKPoint(startX + (diffX * (float)value),
                                                   startY + (diffY * (float)value));

                        ele.Transformation = SKMatrix.CreateRotationDegrees(360 * (float)value);
                    }
                }

                canvas.ResumeLayout(true);
            })
            .Commit(this, "Anim", length: 3000, easing: Easing.SpringOut, repeat: () => true);
        }
예제 #24
0
        public void Draw(SKCanvas canvas, IReadOnlyViewport viewport, IWidget widget, float layerOpacity)
        {
            var button = (ButtonWidget)widget;

            if (button.Picture == null && string.IsNullOrEmpty(button.SvgImage))
            {
                return;
            }

            button.Picture ??= button.SvgImage?.LoadSvg();

            var picture = button.Picture as SKPicture;

            if (picture == null)
            {
                return;
            }

            if (button.Envelope == null)
            {
                return;
            }

            // Get the scale for picture in each direction
            var scaleX = (float)(button.Envelope.Width / picture.CullRect.Width);
            var scaleY = (float)(button.Envelope.Height / picture.CullRect.Height);

            // Rotate picture
            var matrix = SKMatrix.CreateRotationDegrees(button.Rotation, picture.CullRect.Width / 2f, picture.CullRect.Height / 2f);

            // Create a scale matrix
            matrix = matrix.PostConcat(SKMatrix.CreateScale(scaleX, scaleY));

            // Translate picture to right place
            matrix = matrix.PostConcat(SKMatrix.CreateTranslation((float)button.Envelope.MinX, (float)button.Envelope.MinY));

            using var skPaint = new SKPaint { IsAntialias = true };
            canvas.DrawPicture(picture, ref matrix, skPaint);
        }
예제 #25
0
        public static SKMatrix GetMatrix(SvgImage svg, float left, float top, float widthR, float heightR, float rotate = 0)
        {
            float canvasMin = Math.Min(widthR, heightR);
            // get the size of the picture
            float svgMax = Math.Max(svg.ViewBox.Width, svg.ViewBox.Height);
            // get the scale to fill the screen
            float scale  = canvasMin / svgMax;
            var   width  = svg.ViewBox.Width * scale;
            var   height = svg.ViewBox.Height * scale;

            var matrix = SKMatrix.Identity;

            if (rotate > 0)
            {
                matrix = matrix.PreConcat(SKMatrix.CreateRotationDegrees(rotate, (left + widthR / 2), (top + heightR / 2)));
            }

            matrix = matrix.PreConcat(SKMatrix.CreateTranslation(left + (widthR - width) / 2F, top + (heightR - height) / 2F));
            matrix = matrix.PreConcat(SKMatrix.CreateScale(scale, scale));

            return(matrix);
        }
예제 #26
0
        /// <inheritdoc />
        public SKPath GetLayerPath(Layer layer, bool includeTranslation, bool includeScale, bool includeRotation, SKPoint?anchorOverride = null)
        {
            SKRect layerBounds = GetLayerBounds(layer).ToSKRect();

            // Apply transformation like done by the core during layer rendering (same differences apply as in GetLayerTransformGroup)
            SKPoint anchorPosition = GetLayerAnchorPosition(layer).ToSKPoint();

            if (anchorOverride != null)
            {
                anchorPosition = anchorOverride.Value;
            }

            SKPoint anchorProperty = layer.Transform.AnchorPoint.CurrentValue;

            // Translation originates from the unscaled center of the shape and is tied to the anchor
            float x = anchorPosition.X - layerBounds.MidX - anchorProperty.X * layerBounds.Width;
            float y = anchorPosition.Y - layerBounds.MidY - anchorProperty.Y * layerBounds.Height;

            SKPath path = new();

            path.AddRect(layerBounds);
            if (includeTranslation)
            {
                path.Transform(SKMatrix.CreateTranslation(x, y));
            }
            if (includeScale)
            {
                path.Transform(SKMatrix.CreateScale(layer.Transform.Scale.CurrentValue.Width / 100f, layer.Transform.Scale.CurrentValue.Height / 100f, anchorPosition.X, anchorPosition.Y));
            }
            if (includeRotation)
            {
                path.Transform(SKMatrix.CreateRotationDegrees(layer.Transform.Rotation.CurrentValue, anchorPosition.X, anchorPosition.Y));
            }

            return(path);
        }
예제 #27
0
        /// <summary>
        /// Configure paint wrapper for using gradient brush.
        /// </summary>
        /// <param name="paintWrapper">Paint wrapper.</param>
        /// <param name="targetSize">Target size.</param>
        /// <param name="gradientBrush">Gradient brush.</param>
        private void ConfigureGradientBrush(ref PaintWrapper paintWrapper, Size targetSize, IGradientBrush gradientBrush)
        {
            var tileMode    = gradientBrush.SpreadMethod.ToSKShaderTileMode();
            var stopColors  = gradientBrush.GradientStops.Select(s => s.Color.ToSKColor()).ToArray();
            var stopOffsets = gradientBrush.GradientStops.Select(s => (float)s.Offset).ToArray();

            switch (gradientBrush)
            {
            case ILinearGradientBrush linearGradient:
            {
                var start = linearGradient.StartPoint.ToPixels(targetSize).ToSKPoint();
                var end   = linearGradient.EndPoint.ToPixels(targetSize).ToSKPoint();

                // would be nice to cache these shaders possibly?
                using (var shader =
                           SKShader.CreateLinearGradient(start, end, stopColors, stopOffsets, tileMode))
                {
                    paintWrapper.Paint.Shader = shader;
                }

                break;
            }

            case IRadialGradientBrush radialGradient:
            {
                var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint();
                var radius = (float)(radialGradient.Radius * targetSize.Width);

                var origin = radialGradient.GradientOrigin.ToPixels(targetSize).ToSKPoint();

                if (origin.Equals(center))
                {
                    // when the origin is the same as the center the Skia RadialGradient acts the same as D2D
                    using (var shader =
                               SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode))
                    {
                        paintWrapper.Paint.Shader = shader;
                    }
                }
                else
                {
                    // when the origin is different to the center use a two point ConicalGradient to match the behaviour of D2D

                    // reverse the order of the stops to match D2D
                    var reversedColors = new SKColor[stopColors.Length];
                    Array.Copy(stopColors, reversedColors, stopColors.Length);
                    Array.Reverse(reversedColors);

                    // and then reverse the reference point of the stops
                    var reversedStops = new float[stopOffsets.Length];
                    for (var i = 0; i < stopOffsets.Length; i++)
                    {
                        reversedStops[i] = stopOffsets[i];
                        if (reversedStops[i] > 0 && reversedStops[i] < 1)
                        {
                            reversedStops[i] = Math.Abs(1 - stopOffsets[i]);
                        }
                    }

                    // compose with a background colour of the final stop to match D2D's behaviour of filling with the final color
                    using (var shader = SKShader.CreateCompose(
                               SKShader.CreateColor(reversedColors[0]),
                               SKShader.CreateTwoPointConicalGradient(center, radius, origin, 0, reversedColors, reversedStops, tileMode)
                               ))
                    {
                        paintWrapper.Paint.Shader = shader;
                    }
                }

                break;
            }

            case IConicGradientBrush conicGradient:
            {
                var center = conicGradient.Center.ToPixels(targetSize).ToSKPoint();

                // Skia's default is that angle 0 is from the right hand side of the center point
                // but we are matching CSS where the vertical point above the center is 0.
                var angle    = (float)(conicGradient.Angle - 90);
                var rotation = SKMatrix.CreateRotationDegrees(angle, center.X, center.Y);

                using (var shader =
                           SKShader.CreateSweepGradient(center, stopColors, stopOffsets, rotation))
                {
                    paintWrapper.Paint.Shader = shader;
                }

                break;
            }
            }
        }
예제 #28
0
        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);
        }
예제 #29
0
 public static SKMatrix CreateRotationDegrees(float angle, SKPoint p)
 {
     return(SKMatrix.CreateRotationDegrees(angle, p.X, p.Y));
 }
예제 #30
0
        /// <summary>
        /// Get arrow path for the specified annotation position
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="position"></param>
        /// <returns></returns>
        private SKPath GetArrowPath(
            ChartGraphics graphics,
            SKRect position)
        {
            // Get absolute position
            SKRect  positionAbs = graphics.GetAbsoluteRectangle(position);
            SKPoint firstPoint  = positionAbs.Location;
            SKPoint secondPoint = new(positionAbs.Right, positionAbs.Bottom);

            // Calculate arrow length
            float deltaX      = secondPoint.X - firstPoint.X;
            float deltaY      = secondPoint.Y - firstPoint.Y;
            float arrowLength = (float)Math.Sqrt(deltaX * deltaX + deltaY * deltaY);

            // Create unrotated graphics path for the arrow started at the annotation location
            // and going to the right for the length of the rotated arrow.
            SKPath path         = new();
            float  pointerRatio = 2.1f;

            SKPoint[] points;
            if (ArrowStyle == ArrowStyle.Simple)
            {
                points = new SKPoint[] {
                    firstPoint,
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize),
                    new SKPoint(firstPoint.X + arrowLength, firstPoint.Y - ArrowSize),
                    new SKPoint(firstPoint.X + arrowLength, firstPoint.Y + ArrowSize),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio)
                };
            }
            else if (ArrowStyle == ArrowStyle.DoubleArrow)
            {
                points = new SKPoint[] {
                    firstPoint,
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize),
                    new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y - ArrowSize),
                    new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio),
                    new SKPoint(firstPoint.X + arrowLength, firstPoint.Y),
                    new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio),
                    new SKPoint(firstPoint.X + arrowLength - ArrowSize * pointerRatio, firstPoint.Y + ArrowSize),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio)
                };
            }
            else if (ArrowStyle == ArrowStyle.Tailed)
            {
                float tailRatio = 2.1f;
                points = new SKPoint[] {
                    firstPoint,
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize * pointerRatio),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y - ArrowSize),
                    new SKPoint(firstPoint.X + arrowLength, firstPoint.Y - ArrowSize * tailRatio),
                    new SKPoint(firstPoint.X + arrowLength - ArrowSize * tailRatio, firstPoint.Y),
                    new SKPoint(firstPoint.X + arrowLength, firstPoint.Y + ArrowSize * tailRatio),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize),
                    new SKPoint(firstPoint.X + ArrowSize * pointerRatio, firstPoint.Y + ArrowSize * pointerRatio)
                };
            }
            else
            {
                throw (new InvalidOperationException(SR.ExceptionAnnotationArrowStyleUnknown));
            }

            path.AddLines(points);
            path.Close();

            // Calculate arrow angle
            float angle = (float)(Math.Atan(deltaY / deltaX) * 180f / Math.PI);

            if (deltaX < 0)
            {
                angle += 180f;
            }

            // Rotate arrow path around the first point
            SKMatrix matrix = SKMatrix.CreateRotationDegrees(angle, firstPoint.X, firstPoint.Y);

            path.Transform(matrix);

            return(path);
        }