Пример #1
0
        public static SKMatrix BuildTransformMatrix(string Transform)
        {
            var Output = SKMatrix.MakeIdentity();

            char[] delim = { ',', ' ', '(', ')' };
            var    v_s   = Transform.Split(delim, StringSplitOptions.RemoveEmptyEntries);

            if (v_s.Length == 0)
            {
                throw (new Exception("Malformed transform."));
            }

            //Get the name of the transform type
            int i    = 0;
            var Type = v_s[i++].ToLower();

            //Switch to correct transform type
            switch (Type)
            {
            case "matrix":
                var a = float.Parse(v_s[i++]);
                var b = float.Parse(v_s[i++]);
                var c = float.Parse(v_s[i++]);
                var d = float.Parse(v_s[i++]);
                var e = float.Parse(v_s[i++]);
                var f = float.Parse(v_s[i++]);


                Output.ScaleX = a;
                Output.ScaleY = d;
                Output.SkewX  = c;
                Output.SkewY  = b;
                Output.TransX = e;
                Output.TransY = f;

                break;

            case "translate":
                var tx = float.Parse(v_s[i++]);

                var ty = 0.0f;
                if (i < v_s.Length)
                {
                    ty = float.Parse(v_s[i++]);
                }

                //
                Output = SKMatrix.MakeTranslation(tx, ty);
                break;

            case "scale":
                var sx = float.Parse(v_s[i++]);

                var sy = 0.0f;
                if (i < v_s.Length)
                {
                    sy = float.Parse(v_s[i++]);
                }

                //
                Output = SKMatrix.MakeScale(sx, sy);
                break;

            case "rotate":
                //
                var angle = float.Parse(v_s[i++]);

                //
                var cx = 0.0f;
                if (i < v_s.Length)
                {
                    cx = float.Parse(v_s[i++]);
                }

                //
                var cy = 0.0f;
                if (i < v_s.Length)
                {
                    cy = float.Parse(v_s[i++]);
                }

                //
                Output = SKMatrix.MakeRotationDegrees(angle, cx, cy);
                break;

            case "skewX":
                var sk_x_angle    = float.Parse(v_s[i++]);
                var anglx_radians = ((float)Math.PI / 180.0f) * sk_x_angle;
                Output = SKMatrix.MakeSkew((float)Math.Tan(anglx_radians), 0);
                break;

            case "skewY":
                var sk_y_angle    = float.Parse(v_s[i++]);
                var angly_radians = ((float)Math.PI / 180.0f) * sk_y_angle;
                Output = SKMatrix.MakeSkew(0, (float)Math.Tan(angly_radians));
                break;
            }
            ;

            // SVG always have these settings
            Output.Persp0 = 0;
            Output.Persp1 = 0;
            Output.Persp2 = 1;
            return(Output);
        }
        void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
        {
            SKImageInfo info    = args.Info;
            SKSurface   surface = args.Surface;
            SKCanvas    canvas  = surface.Canvas;

            canvas.Clear();

            float xCenter = info.Width / 2;
            float yCenter = info.Height / 2;
            float radius  = 0.24f * Math.Min(info.Width, info.Height);

            using (SKRegion wholeScreenRegion = new SKRegion())
            {
                wholeScreenRegion.SetRect(new SKRectI(0, 0, info.Width, info.Height));

                using (SKRegion leftRegion = new SKRegion(wholeScreenRegion))
                    using (SKRegion rightRegion = new SKRegion(wholeScreenRegion))
                        using (SKRegion topRegion = new SKRegion(wholeScreenRegion))
                            using (SKRegion bottomRegion = new SKRegion(wholeScreenRegion))
                            {
                                using (SKPath circlePath = new SKPath())
                                {
                                    // Make basic circle path
                                    circlePath.AddCircle(xCenter, yCenter, radius);

                                    // Left leaf
                                    circlePath.Transform(SKMatrix.MakeTranslation(-radius, 0));
                                    leftRegion.SetPath(circlePath);

                                    // Right leaf
                                    circlePath.Transform(SKMatrix.MakeTranslation(2 * radius, 0));
                                    rightRegion.SetPath(circlePath);

                                    // Make union of right with left
                                    leftRegion.Op(rightRegion, SKRegionOperation.Union);

                                    // Top leaf
                                    circlePath.Transform(SKMatrix.MakeTranslation(-radius, -radius));
                                    topRegion.SetPath(circlePath);

                                    // Combine with bottom leaf
                                    circlePath.Transform(SKMatrix.MakeTranslation(0, 2 * radius));
                                    bottomRegion.SetPath(circlePath);

                                    // Make union of top with bottom
                                    bottomRegion.Op(topRegion, SKRegionOperation.Union);

                                    // Exclusive-OR left and right with top and bottom
                                    leftRegion.Op(bottomRegion, SKRegionOperation.XOR);

                                    // Set that as clip region
                                    canvas.ClipRegion(leftRegion);

                                    // Set transform for drawing lines from center
                                    canvas.Translate(xCenter, yCenter);

                                    // Draw 360 lines
                                    for (double angle = 0; angle < 360; angle++)
                                    {
                                        float x = 2 * radius * (float)Math.Cos(Math.PI * angle / 180);
                                        float y = 2 * radius * (float)Math.Sin(Math.PI * angle / 180);

                                        using (SKPaint strokePaint = new SKPaint())
                                        {
                                            strokePaint.Color       = SKColors.Green;
                                            strokePaint.StrokeWidth = 2;

                                            canvas.DrawLine(0, 0, x, y, strokePaint);
                                        }
                                    }
                                }
                            }
            }
        }
Пример #3
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);
        }
Пример #4
0
 public static SKMatrix Invert(this SKMatrix m)
 {
     m.TryInvert(out var m2);
     return(m2);
 }
Пример #5
0
 public void UpdateTransform(SKMatrix transform)
 {
     UpdateShapeTransform(transform);
 }
Пример #6
0
        // Every 1/60th second, update bitmap with user drawings
        bool OnTimerTick()
        {
            if (bitmap == null)
            {
                return(true);
            }

            // Determine the current color.
            float tColor = stopwatch.ElapsedMilliseconds % 10000 / 10000f;

            fingerPaint.Color    = SKColor.FromHsl(360 * tColor, 100, 50);
            titleLabel.TextColor = fingerPaint.Color.ToFormsColor();

            // Determine the rotation angle.
            float tAngle = stopwatch.ElapsedMilliseconds % 5000 / 5000f;

            angle = 360 * tAngle;
            SKMatrix matrix = SKMatrix.MakeRotationDegrees(-angle, bitmap.Width / 2, bitmap.Height / 2);

            // Loop trough the fingers touching the screen.
            foreach (long id in idDictionary.Keys)
            {
                FingerInfo fingerInfo = idDictionary[id];

                // Get the canvas size in pixels. It's square so it's only one number.
                float canvasSize = 0;

                if (canvasView is SKCanvasView)
                {
                    canvasSize = (canvasView as SKCanvasView).CanvasSize.Width;
                }
                else
                {
                    canvasSize = (canvasView as SKGLView).CanvasSize.Width;
                }

                // Convert Xamarin.Forms coordinates to pixels for drawing on the bitmap.
                // Also, make an offset factor if there's been resizing and the bitmap
                //      is now larger than the canvas. (It's never smaller.)
                float factor = canvasSize / (float)canvasView.Width;    // scaling factor
                float offset = (bitmapSize - canvasSize) / 2;           // bitmap always >= canvas

                SKPoint convertedPoint = new SKPoint(factor * (float)fingerInfo.ThisPosition.X + offset,
                                                     factor * (float)fingerInfo.ThisPosition.Y + offset);

                // Now rotate the point based on the rotation angle
                SKPoint pt0 = matrix.MapPoint(convertedPoint);

                if (!float.IsPositiveInfinity(fingerInfo.LastPosition.X))
                {
                    // Draw four lines in four quadrants.
                    SKPoint pt1 = fingerInfo.LastPosition;
                    bitmapCanvas.DrawLine(pt0.X, pt0.Y, pt1.X, pt1.Y, fingerPaint);

                    float x0Flip = bitmap.Width - pt0.X;
                    float y0Flip = bitmap.Height - pt0.Y;
                    float x1Flip = bitmap.Width - pt1.X;
                    float y1Flip = bitmap.Height - pt1.Y;

                    bitmapCanvas.DrawLine(x0Flip, pt0.Y, x1Flip, pt1.Y, fingerPaint);
                    bitmapCanvas.DrawLine(pt0.X, y0Flip, pt1.X, y1Flip, fingerPaint);
                    bitmapCanvas.DrawLine(x0Flip, y0Flip, x1Flip, y1Flip, fingerPaint);
                }

                // Save the current point for next time through.
                fingerInfo.LastPosition = pt0;
            }

            // Redraw the canvas.
            if (canvasView is SKCanvasView)
            {
                (canvasView as SKCanvasView).InvalidateSurface();
            }
            else
            {
                (canvasView as SKGLView).InvalidateSurface();
            }
            return(true);
        }
Пример #7
0
 public static SKMatrix Scale(this SKMatrix m, float sx, float sy)
 {
     return(m.Concat(SKMatrix.MakeScale(sx, sy)));
 }
Пример #8
0
 public void ClipRoundRect(SKRoundRect rect, SKClipOperation operation)
 {
     rect.Transform(SKMatrix.CreateScale(CurrentState.ScaleX, CurrentState.ScaleY));
     Canvas.ClipRoundRect(rect, operation, true);
 }
Пример #9
0
        public async Task <Tuple <Stream, LoadingResult, ImageInformation> > Resolve(string identifier, TaskParameter parameters, CancellationToken token)
        {
            ImageSource source = parameters.Source;

            if (!string.IsNullOrWhiteSpace(parameters.LoadingPlaceholderPath) && parameters.LoadingPlaceholderPath == identifier)
            {
                source = parameters.LoadingPlaceholderSource;
            }
            else if (!string.IsNullOrWhiteSpace(parameters.ErrorPlaceholderPath) && parameters.ErrorPlaceholderPath == identifier)
            {
                source = parameters.ErrorPlaceholderSource;
            }

            var resolvedData = await(Configuration.DataResolverFactory ?? new DataResolverFactory())
                               .GetResolver(identifier, source, parameters, Configuration)
                               .Resolve(identifier, parameters, token);

            if (resolvedData?.Item1 == null)
            {
                throw new FileNotFoundException(identifier);
            }

            var svg = new SKSvg()
            {
                ThrowOnUnsupportedElement = false,
            };
            SKPicture picture;

            using (var svgStream = resolvedData.Item1)
            {
                picture = svg.Load(resolvedData?.Item1);
            }

            float sizeX = 0;
            float sizeY = 0;

            if (VectorWidth == 0 && VectorHeight == 0)
            {
                sizeX = 200;
                sizeY = (VectorWidth / picture.Bounds.Width) * picture.Bounds.Height;
            }
            else if (VectorWidth > 0 && VectorHeight > 0)
            {
                sizeX = VectorWidth;
                sizeY = VectorHeight;
            }
            else if (VectorWidth > 0)
            {
                sizeX = VectorWidth;
                sizeY = (VectorWidth / picture.Bounds.Width) * picture.Bounds.Height;
            }
            else
            {
                sizeX = (VectorHeight / picture.Bounds.Height) * picture.Bounds.Width;
                sizeY = VectorHeight;
            }

            using (var bitmap = new SKBitmap((int)sizeX, (int)sizeY))
                using (var canvas = new SKCanvas(bitmap))
                    using (var paint = new SKPaint())
                    {
                        canvas.Clear(SKColors.Transparent);
                        float scaleX = sizeX / picture.Bounds.Width;
                        float scaleY = sizeY / picture.Bounds.Height;
                        var   matrix = SKMatrix.MakeScale(scaleX, scaleY);

                        canvas.DrawPicture(picture, ref matrix, paint);
                        canvas.Flush();

                        using (var image = SKImage.FromBitmap(bitmap))
                            using (var data = image.Encode(SKImageEncodeFormat.Png, 80))
                            {
                                var stream = new MemoryStream();
                                data.SaveTo(stream);
                                stream.Position = 0;
                                //var stream = data?.AsStream();
                                return(new Tuple <Stream, LoadingResult, ImageInformation>(stream, resolvedData.Item2, resolvedData.Item3));
                            }
                    }
        }
Пример #10
0
        public virtual void Draw(SKCanvas canvas, Attributes ignoreAttributes, Drawable?until)
        {
            if (!IsDrawable)
            {
                return;
            }

            if (until != null && this == until)
            {
                return;
            }

            var enableClip    = !ignoreAttributes.HasFlag(Attributes.ClipPath);
            var enableMask    = !ignoreAttributes.HasFlag(Attributes.Mask);
            var enableOpacity = !ignoreAttributes.HasFlag(Attributes.Opacity);
            var enableFilter  = !ignoreAttributes.HasFlag(Attributes.Filter);

            canvas.Save();

            if (Overflow != null)
            {
                canvas.ClipRect(Overflow.Value, SKClipOperation.Intersect);
            }

            var skMatrixTotal = canvas.TotalMatrix;

            SKMatrix.PreConcat(ref skMatrixTotal, ref Transform);
            canvas.SetMatrix(skMatrixTotal);

            if (Clip != null)
            {
                canvas.ClipRect(Clip.Value, SKClipOperation.Intersect);
            }

            if (ClipPath != null && enableClip == true)
            {
                canvas.ClipPath(ClipPath, SKClipOperation.Intersect, IsAntialias);
            }

            if (MaskDrawable != null && enableMask == true)
            {
                canvas.SaveLayer(Mask);
            }

            if (Opacity != null && enableOpacity == true)
            {
                canvas.SaveLayer(Opacity);
            }

            if (Filter != null && enableFilter == true)
            {
                canvas.SaveLayer(Filter);
            }

            OnDraw(canvas, ignoreAttributes, until);

            if (Filter != null && enableFilter == true)
            {
                canvas.Restore();
            }

            if (Opacity != null && enableOpacity == true)
            {
                canvas.Restore();
            }

            if (MaskDrawable != null && enableMask == true)
            {
                canvas.SaveLayer(MaskDstIn);
                MaskDrawable.Draw(canvas, ignoreAttributes, until);
                canvas.Restore();
                canvas.Restore();
            }

            canvas.Restore();
        }
Пример #11
0
 public void ClipPath(SKPath path, SKClipOperation operation)
 {
     path.Transform(SKMatrix.CreateScale(CurrentState.ScaleX, CurrentState.ScaleY));
     Canvas.ClipPath(path, operation);
 }
Пример #12
0
 public static Matrix3x2 ToNumerics(this SKMatrix matrix) => new Matrix3x2(matrix.ScaleX, matrix.SkewY, matrix.SkewX, matrix.ScaleY, matrix.TransX, matrix.TransY);
Пример #13
0
        public void EmptyMatrixForNonInvertableMatrix()
        {
            var matrix = SKMatrix.CreateScale(0, 1);

            Assert.Equal(SKMatrix.Empty, matrix.Invert());
        }
Пример #14
0
        internal PaintWrapper CreatePaint(IBrush brush, Size targetSize)
        {
            SKPaint paint = new SKPaint();
            var     rv    = new PaintWrapper(paint);

            paint.IsStroke = false;

            // TODO: SkiaSharp does not contain alpha yet!
            double opacity = brush.Opacity * _currentOpacity;

            //paint.SetAlpha(paint.GetAlpha() * opacity);
            paint.IsAntialias = true;

            SKColor color = new SKColor(255, 255, 255, 255);

            var solid = brush as ISolidColorBrush;

            if (solid != null)
            {
                color = solid.Color.ToSKColor();
            }

            paint.Color = (new SKColor(color.Red, color.Green, color.Blue, (byte)(color.Alpha * opacity)));

            if (solid != null)
            {
                return(rv);
            }

            var gradient = brush as IGradientBrush;

            if (gradient != null)
            {
                var tileMode    = gradient.SpreadMethod.ToSKShaderTileMode();
                var stopColors  = gradient.GradientStops.Select(s => s.Color.ToSKColor()).ToArray();
                var stopOffsets = gradient.GradientStops.Select(s => (float)s.Offset).ToArray();

                var linearGradient = brush as ILinearGradientBrush;
                if (linearGradient != null)
                {
                    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))
                        paint.Shader = shader;
                }
                else
                {
                    var radialGradient = brush as IRadialGradientBrush;
                    if (radialGradient != null)
                    {
                        var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint();
                        var radius = (float)radialGradient.Radius;

                        // TODO: There is no SetAlpha in SkiaSharp
                        //paint.setAlpha(128);

                        // would be nice to cache these shaders possibly?
                        using (var shader = SKShader.CreateRadialGradient(center, radius, stopColors, stopOffsets, tileMode))
                            paint.Shader = shader;
                    }
                }

                return(rv);
            }

            var tileBrush = brush as ITileBrush;

            if (tileBrush != null)
            {
                var helper = new TileBrushImplHelper(tileBrush, targetSize);
                var bitmap = new BitmapImpl((int)helper.IntermediateSize.Width, (int)helper.IntermediateSize.Height);
                rv.AddDisposable(bitmap);
                using (var ctx = bitmap.CreateDrawingContext())
                    helper.DrawIntermediate(ctx);
                SKMatrix         translation = SKMatrix.MakeTranslation(-(float)helper.DestinationRect.X, -(float)helper.DestinationRect.Y);
                SKShaderTileMode tileX       =
                    tileBrush.TileMode == TileMode.None
                        ? SKShaderTileMode.Clamp
                        : tileBrush.TileMode == TileMode.FlipX || tileBrush.TileMode == TileMode.FlipXY
                            ? SKShaderTileMode.Mirror
                            : SKShaderTileMode.Repeat;

                SKShaderTileMode tileY =
                    tileBrush.TileMode == TileMode.None
                        ? SKShaderTileMode.Clamp
                        : tileBrush.TileMode == TileMode.FlipY || tileBrush.TileMode == TileMode.FlipXY
                            ? SKShaderTileMode.Mirror
                            : SKShaderTileMode.Repeat;
                using (var shader = SKShader.CreateBitmap(bitmap.Bitmap, tileX, tileY, translation))
                    paint.Shader = shader;
            }

            return(rv);
        }
Пример #15
0
        public override void DrawContent(SKCanvas canvas, int width, int height)
        {
            var total = Inputs?.Count() ?? 0;

            if (total > 0)
            {
                var captionHeight = Inputs.Max(x =>
                {
                    var result = 0.0f;

                    var hasLabel      = !string.IsNullOrEmpty(x.Label);
                    var hasValueLabel = !string.IsNullOrEmpty(x.DisplayValue);
                    if (hasLabel || hasValueLabel)
                    {
                        var hasOffset     = hasLabel && hasValueLabel;
                        var captionMargin = LabelTextSize * 0.60f;
                        var space         = hasOffset ? captionMargin : 0;

                        if (hasLabel)
                        {
                            result += LabelTextSize;
                        }

                        if (hasValueLabel)
                        {
                            result += LabelTextSize;
                        }
                    }

                    return(result);
                });

                var center     = new SKPoint(width / 2, height / 2);
                var radius     = ((Math.Min(width, height) - (2 * Margin)) / 2) - captionHeight;
                var rangeAngle = (float)((Math.PI * 2) / total);
                var startAngle = (float)Math.PI;

                var nextInput = Inputs.First();
                var nextAngle = startAngle;
                var nextPoint = GetPoint(nextInput.Value * AnimationProgress, center, nextAngle, radius);

                DrawBorder(canvas, center, radius);

                using (var clip = new SKPath())
                {
                    clip.AddCircle(center.X, center.Y, radius);

                    for (int i = 0; i < total; i++)
                    {
                        var angle = nextAngle;
                        var input = nextInput;
                        var point = nextPoint;

                        var nextIndex = (i + 1) % total;
                        nextAngle = startAngle + (rangeAngle * nextIndex);
                        nextInput = Inputs.ElementAt(nextIndex);
                        nextPoint = GetPoint(nextInput.Value * AnimationProgress, center, nextAngle, radius);

                        canvas.Save();
                        canvas.ClipPath(clip);

                        // Border center bars
                        using (var paint = new SKPaint()
                        {
                            Style = SKPaintStyle.Stroke,
                            StrokeWidth = BorderLineSize,
                            Color = BorderLineColor,
                            IsAntialias = true,
                        })
                        {
                            var borderPoint = GetPoint(MaxValue, center, angle, radius);
                            canvas.DrawLine(point.X, point.Y, borderPoint.X, borderPoint.Y, paint);
                        }

                        // Values points and lines
                        using (var paint = new SKPaint()
                        {
                            Style = SKPaintStyle.Stroke,
                            StrokeWidth = BorderLineSize,
                            Color = input.Color.WithAlpha((byte)(input.Color.Alpha * 0.75f * AnimationProgress)),
                            PathEffect = SKPathEffect.CreateDash(new[] { BorderLineSize, BorderLineSize * 2 }, 0),
                            IsAntialias = true,
                        })
                        {
                            var amount = Math.Abs(input.Value - AbsoluteMinimum) / ValueRange;
                            canvas.DrawCircle(center.X, center.Y, radius * amount, paint);
                        }

                        canvas.DrawGradientLine(center, input.Color.WithAlpha(0), point, input.Color.WithAlpha((byte)(input.Color.Alpha * 0.75f)), LineSize);
                        canvas.DrawGradientLine(point, input.Color, nextPoint, nextInput.Color, LineSize);
                        canvas.DrawPoint(point, input.Color, PointSize, PointMode);

                        canvas.Restore();

                        // Labels
                        var labelPoint = new SKPoint(0, radius + LabelTextSize + (PointSize / 2));
                        var rotation   = SKMatrix.MakeRotation(angle);
                        labelPoint = center + rotation.MapPoint(labelPoint);
                        var alignment = SKTextAlign.Left;

                        if ((Math.Abs(angle - (startAngle + Math.PI)) < Epsilon) || (Math.Abs(angle - Math.PI) < Epsilon))
                        {
                            alignment = SKTextAlign.Center;
                        }
                        else if (angle > (float)(startAngle + Math.PI))
                        {
                            alignment = SKTextAlign.Right;
                        }

                        canvas.DrawCaptionLabels(input.Label, input.TextColor, input.DisplayValue, input.Color.WithAlpha((byte)(255 * AnimationProgress)), LabelTextSize, labelPoint, alignment, base.Typeface);
                    }
                }
            }
        }
Пример #16
0
        /// <summary>
        /// Paint checkbox
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaintSelectionElement(SKPaintSurfaceEventArgs e)
        {
            if (_checkMarkSvg == null && string.IsNullOrEmpty(CheckMarkIconAssemblyName) == false && string.IsNullOrEmpty(CheckMarkIconResourceKey) == false)
            {
                _checkMarkSvg = SvgImage.GetSvgImage(CheckMarkIconAssemblyName, CheckMarkIconResourceKey);
            }

            Rectangle checkBoxAvailableLocation = new Rectangle();
            Rectangle availableSpace            = new Rectangle(EllipseDiameter, EllipseDiameter, Width, Height - Padding.VerticalThickness);

            if (CheckBoxLocation == HorizontalLocations.Left)
            {
                checkBoxAvailableLocation = availableSpace;
            }
            else
            {
                checkBoxAvailableLocation = new Rectangle(availableSpace.Width - CheckBoxWidthRequest - CheckBoxMargin.HorizontalThickness + EllipseDiameter, EllipseDiameter, availableSpace.Width, availableSpace.Height);
            }

            Rectangle checkBoxActualLocation = CheckBoxActualLocation(checkBoxAvailableLocation);

            float skCheckBoxBorderThickness = (float)CheckBoxBorderThickness * DeviceScale;
            float skCheckBoxX      = (float)checkBoxActualLocation.X * DeviceScale;
            float skCheckBoxY      = (float)checkBoxActualLocation.Y * DeviceScale;
            float skCheckBoxWidth  = (float)CheckBoxWidthRequest * DeviceScale;
            float skCheckBoxHeight = (float)CheckBoxHeightRequest * DeviceScale;
            float skCornerRadius   = (float)CheckBoxCornerRadius * DeviceScale;

            SKMatrix checkMarkMatrix   = new SKMatrix();
            SKPoint  checkMarkPosition = new SKPoint();

            Size checkMarkIconSize = new Size(CheckBoxWidthRequest - CheckMarkIconMargin.HorizontalThickness, CheckBoxHeightRequest - CheckMarkIconMargin.VerticalThickness);

            float scale = SvgImage.CalculateScale(_checkMarkSvg.Picture.CullRect.Size, checkMarkIconSize.Width, checkMarkIconSize.Height);

            Size actualCheckMarkIconSize = new Size(_checkMarkSvg.Picture.CullRect.Width * scale, _checkMarkSvg.Picture.CullRect.Height * scale);

            scale = scale * DeviceScale;

            checkMarkPosition.X = (float)skCheckBoxX + (float)((CheckBoxWidthRequest - actualCheckMarkIconSize.Width) / 2) * DeviceScale;
            checkMarkPosition.Y = (float)skCheckBoxY + (float)((CheckBoxHeightRequest - actualCheckMarkIconSize.Height) / 2) * DeviceScale;
            checkMarkMatrix.SetScaleTranslate(scale, scale, checkMarkPosition.X, checkMarkPosition.Y);

            SKRect checkBoxPaintRect = new SKRect(skCheckBoxX + skCheckBoxBorderThickness / 2,
                                                  skCheckBoxY + skCheckBoxBorderThickness / 2,
                                                  skCheckBoxX + skCheckBoxWidth - skCheckBoxBorderThickness / 2,
                                                  skCheckBoxY + skCheckBoxHeight - skCheckBoxBorderThickness / 2);

            if (EllipseDiameter > 0 && _toggledAnimationProcess > 0 && _toggledAnimationProcess < 1 && IsEllipseAnimationEnabled)
            {
                SKPaint ellipsePaint = new SKPaint()
                {
                    IsAntialias = true,
                    Style       = SKPaintStyle.Fill,
                };

                if (_toggledAnimationProcess <= 0.5)
                {
                    ellipsePaint.Color = EllipseColor.MultiplyAlpha(_toggledAnimationProcessWithoutEasing * 2).ToSKColor();
                }
                else
                {
                    ellipsePaint.Color = EllipseColor.MultiplyAlpha(1 - (_toggledAnimationProcessWithoutEasing - 0.5) * 2).ToSKColor();
                }

                e.Surface.Canvas.DrawCircle(new SKPoint(checkBoxPaintRect.MidX, checkBoxPaintRect.MidY), (float)(EllipseDiameter / 2) * DeviceScale, ellipsePaint);
            }

            Color backgroundColor = Color.Transparent;

            if (CheckBoxBackgroundColor != null && CheckBoxBackgroundColor != Color.Transparent && ToggledCheckBoxBackgroundColor != null && ToggledCheckBoxBackgroundColor != Color.Transparent)
            {
                backgroundColor = AnimationUtils.ColorTransform(_toggledAnimationProcess, CheckBoxBackgroundColor, ToggledCheckBoxBackgroundColor);
            }
            else if ((CheckBoxBackgroundColor == null || CheckBoxBackgroundColor == Color.Transparent) && ToggledCheckBoxBackgroundColor != null && ToggledCheckBoxBackgroundColor != Color.Transparent)
            {
                backgroundColor = ToggledCheckBoxBackgroundColor;
            }
            else
            {
                backgroundColor = CheckBoxBackgroundColor;
            }

            SKPaint checkBoxBackgroundPaint = new SKPaint
            {
                Style       = SKPaintStyle.Fill,
                IsAntialias = true,
                Color       = backgroundColor.ToSKColor(),
            };

            SKRect rect = new SKRect(
                skCheckBoxX + skCheckBoxBorderThickness,
                skCheckBoxY + skCheckBoxBorderThickness,
                skCheckBoxX + skCheckBoxWidth - skCheckBoxBorderThickness,
                skCheckBoxY + skCheckBoxHeight - skCheckBoxBorderThickness);

            e.Surface.Canvas.Save();

            SKRect r = SKRect.Create(rect.Left, rect.Top, rect.Width, rect.Height);

            if (_toggledAnimationProcess <= 0.75)
            {
                float v = (float)(_toggledAnimationProcess * (1 / 0.75));
                r.Inflate(-rect.Width * v / 2, -rect.Height * v / 2);
                e.Surface.Canvas.ClipRect(r, SKClipOperation.Difference);
            }

            e.Surface.Canvas.DrawRoundRect(checkBoxPaintRect, skCornerRadius, skCornerRadius, checkBoxBackgroundPaint);
            e.Surface.Canvas.Restore();

            SKPaint checkBoxBorderPaint = new SKPaint
            {
                Style       = SKPaintStyle.Stroke,
                IsAntialias = true,
                StrokeWidth = skCheckBoxBorderThickness,
                Color       = AnimationUtils.ColorTransform(_toggledAnimationProcess, CheckBoxBorderColor, ToggledCheckBoxBorderColor).ToSKColor(),
            };

            e.Surface.Canvas.DrawRoundRect(checkBoxPaintRect, skCornerRadius, skCornerRadius, checkBoxBorderPaint);

            using (var paint = new SKPaint())
            {
                Color color = Color.Transparent;

                if (_toggledAnimationProcess > 0.75)
                {
                    float v = (float)((_toggledAnimationProcess - 0.75) * (1 / 0.25));
                    color = AnimationUtils.ColorTransform(v, CheckMarkIconColor, ToggledCheckMarkIconColor);
                }

                if (color != Color.Transparent)
                {
                    paint.ColorFilter = SKColorFilter.CreateBlendMode(color.ToSKColor(), SKBlendMode.SrcIn);
                    paint.Style       = SKPaintStyle.Fill;
                    paint.IsAntialias = true;

                    e.Surface.Canvas.DrawPicture(_checkMarkSvg.Picture, ref checkMarkMatrix, paint);
                }
            }
        }
Пример #17
0
        public static SKMatrix Make(SKSize size, TaperSide taperSide, TaperCorner taperCorner, float taperFraction)
        {
            var matrix = SKMatrix.MakeIdentity();

            switch (taperSide)
            {
            case TaperSide.Left:
                matrix.ScaleX = taperFraction;
                matrix.ScaleY = taperFraction;
                matrix.Persp0 = (taperFraction - 1) / size.Width;

                switch (taperCorner)
                {
                case TaperCorner.RightOrBottom:
                    break;

                case TaperCorner.LeftOrTop:
                    matrix.SkewY  = size.Height * matrix.Persp0;
                    matrix.TransY = size.Height * (1 - taperFraction);
                    break;

                case TaperCorner.Both:
                    matrix.SkewY  = (size.Height / 2) * matrix.Persp0;
                    matrix.TransY = size.Height * (1 - taperFraction) / 2;
                    break;
                }
                break;

            case TaperSide.Top:
                matrix.ScaleX = taperFraction;
                matrix.ScaleY = taperFraction;
                matrix.Persp1 = (taperFraction - 1) / size.Height;

                switch (taperCorner)
                {
                case TaperCorner.RightOrBottom:
                    break;

                case TaperCorner.LeftOrTop:
                    matrix.SkewX  = size.Width * matrix.Persp1;
                    matrix.TransX = size.Width * (1 - taperFraction);
                    break;

                case TaperCorner.Both:
                    matrix.SkewX  = (size.Width / 2) * matrix.Persp1;
                    matrix.TransX = size.Width * (1 - taperFraction) / 2;
                    break;
                }
                break;

            case TaperSide.Right:
                matrix.ScaleX = 1 / taperFraction;
                matrix.Persp0 = (1 - taperFraction) / (size.Width * taperFraction);

                switch (taperCorner)
                {
                case TaperCorner.RightOrBottom:
                    break;

                case TaperCorner.LeftOrTop:
                    matrix.SkewY = size.Height * matrix.Persp0;
                    break;

                case TaperCorner.Both:
                    matrix.SkewY = (size.Height / 2) * matrix.Persp0;
                    break;
                }
                break;

            case TaperSide.Bottom:
                matrix.ScaleY = 1 / taperFraction;
                matrix.Persp1 = (1 - taperFraction) / (size.Height * taperFraction);

                switch (taperCorner)
                {
                case TaperCorner.RightOrBottom:
                    break;

                case TaperCorner.LeftOrTop:
                    matrix.SkewX = size.Width * matrix.Persp1;
                    break;

                case TaperCorner.Both:
                    matrix.SkewX = (size.Width / 2) * matrix.Persp1;
                    break;
                }
                break;
            }
            return(matrix);
        }
Пример #18
0
        public override void DrawImage(SKCanvas dc)
        {
            var     rect_Car  = GetMainRect();
            SKPoint pt_Center = new SKPoint(rect_Car.Left + (rect_Car.Width / 2), rect_Car.Top + (rect_Car.Height / 2));
            SKRect  rect_Body;
            SKPath  gp_Body;
            SKRect  rect_Tire;
            float   int_TireHeight;

            SKPoint[] pts_Body;
            SKRect    rect_Hole;
            int       int_Row;
            int       int_Col;
            float     int_HoleWidth;
            int       int_Count;
            CustomBasicList <SKRect> arr_Holes;
            SKColor  clr_Peg;
            SKMatrix tmp_Matrix = new SKMatrix();

            if (CarType == EnumTypesOfCars.Minivan)
            {
                // *** Draw tires
                int_TireHeight = (rect_Car.Height / 5);
                rect_Tire      = SKRect.Create(rect_Car.Left, rect_Car.Top + (rect_Car.Height / 10), rect_Car.Width, int_TireHeight);
                dc.DrawRect(rect_Tire, _blackPaint);
                rect_Tire = SKRect.Create(rect_Car.Left, (rect_Car.Top + rect_Car.Height) - (rect_Car.Height / 10) - int_TireHeight, rect_Car.Width, int_TireHeight);
                dc.DrawRect(rect_Tire, _blackPaint);
                // *** Draw the body outline
                gp_Body     = new SKPath();
                rect_Body   = SKRect.Create(rect_Car.Left + (rect_Car.Width / 12), rect_Car.Top, rect_Car.Width - (rect_Car.Width / 6), rect_Car.Height);
                pts_Body    = new SKPoint[4];
                pts_Body[0] = new SKPoint(System.Convert.ToInt32(rect_Body.Left), rect_Body.Top + (rect_Body.Height / 30));
                pts_Body[1] = new SKPoint(System.Convert.ToInt32((rect_Body.Left + rect_Body.Width)), rect_Body.Top + (rect_Body.Height / 30));
                pts_Body[2] = new SKPoint(System.Convert.ToInt32(((rect_Body.Left + rect_Body.Width) - (rect_Car.Width / 15))), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 30));
                pts_Body[3] = new SKPoint(System.Convert.ToInt32((rect_Body.Left + (rect_Car.Width / 15))), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 30));
                gp_Body.AddPoly(pts_Body);
                SKMatrix.RotateDegrees(ref tmp_Matrix, 180, pt_Center.X, pt_Center.Y);
                gp_Body.Transform(tmp_Matrix);
                dc.DrawPath(gp_Body, MainPaint);
                dc.DrawPath(gp_Body, _borderPaint);
                gp_Body     = new SKPath();
                pts_Body    = new SKPoint[3];
                pts_Body[0] = new SKPoint(rect_Body.Left + (rect_Body.Width / 15), rect_Body.Top + (rect_Body.Height / 15));
                pts_Body[1] = new SKPoint(rect_Body.Left + (rect_Body.Width / 2), rect_Body.Top + (rect_Body.Height / 100));
                pts_Body[2] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 15), rect_Body.Top + (rect_Body.Height / 15));
                gp_Body.AddPoly(pts_Body);
                SKMatrix.RotateDegrees(ref tmp_Matrix, 180, pt_Center.X, pt_Center.Y);
                gp_Body.Transform(tmp_Matrix);
                dc.DrawPath(gp_Body, _blackPaint);
                // *** Draw the front window
                gp_Body     = new SKPath();
                pts_Body    = new SKPoint[8];
                pts_Body[0] = new SKPoint(rect_Body.Left + (rect_Body.Width / 12), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3));
                pts_Body[1] = new SKPoint(rect_Body.Left + (rect_Body.Width / 2), ((rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3)) + (rect_Body.Height / 30));
                pts_Body[2] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 12), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3));
                pts_Body[3] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 12), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3));
                pts_Body[4] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 6), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 4));
                pts_Body[5] = new SKPoint(rect_Body.Left + (rect_Body.Width / 2), ((rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 4)) + (rect_Body.Height / 30));
                pts_Body[6] = new SKPoint(rect_Body.Left + (rect_Body.Width / 6), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 4));
                pts_Body[7] = new SKPoint(rect_Body.Left + (rect_Body.Width / 12), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3));
                gp_Body.AddPoly(pts_Body);
                SKMatrix.RotateDegrees(ref tmp_Matrix, 180, pt_Center.X, pt_Center.Y);
                gp_Body.Transform(tmp_Matrix);
                dc.DrawPath(gp_Body, _blackPaint);
                // *** Draw the hood
                gp_Body     = new SKPath();
                pts_Body    = new SKPoint[8];
                pts_Body[0] = new SKPoint(rect_Body.Left + (rect_Body.Width / 8), ((rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3)) + (rect_Body.Height / 10));
                pts_Body[1] = new SKPoint(rect_Body.Left + (rect_Body.Width / 2), ((rect_Body.Top + rect_Body.Height) - ((rect_Body.Height * 2) / 6)) + (rect_Body.Height / 30) + (rect_Body.Height / 10));
                pts_Body[2] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 8), ((rect_Body.Top + rect_Body.Height) - ((rect_Body.Height * 2) / 6)) + (rect_Body.Height / 10));
                pts_Body[3] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 8), ((rect_Body.Top + rect_Body.Height) - ((rect_Body.Height * 2) / 6)) + (rect_Body.Height / 10));
                pts_Body[4] = new SKPoint((rect_Body.Left + rect_Body.Width) - (rect_Body.Width / 5), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 30));
                pts_Body[5] = new SKPoint(rect_Body.Left + (rect_Body.Width / 2), rect_Body.Top + rect_Body.Height);
                pts_Body[6] = new SKPoint(rect_Body.Left + (rect_Body.Width / 5), (rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 30));
                pts_Body[7] = new SKPoint(rect_Body.Left + (rect_Body.Width / 8), ((rect_Body.Top + rect_Body.Height) - (rect_Body.Height / 3)) + (rect_Body.Height / 10));
                gp_Body.AddPoly(pts_Body);
                SKMatrix.RotateDegrees(ref tmp_Matrix, 180, pt_Center.X, pt_Center.Y);
                gp_Body.Transform(tmp_Matrix);
                dc.DrawPath(gp_Body, MainPaint);
            }
            else if (CarType == EnumTypesOfCars.Car)
            {
            }
            // *** Draw the holes
            arr_Holes     = new CustomBasicList <SKRect>();
            int_HoleWidth = rect_Car.Width * 2 / 9;
            for (int_Row = 0; int_Row <= 2; int_Row++)
            {
                for (int_Col = 0; int_Col <= 1; int_Col++)
                {
                    if (int_Col == 0)
                    {
                        rect_Hole = SKRect.Create(rect_Car.Left + (rect_Car.Width / 5), rect_Car.Top + (rect_Car.Height * 2 / 5) + (int_Row * (int_HoleWidth + (int_HoleWidth / 4))), int_HoleWidth, int_HoleWidth);
                    }
                    else
                    {
                        rect_Hole = SKRect.Create(rect_Car.Left + rect_Car.Width - (rect_Car.Width / 5) - int_HoleWidth, rect_Car.Top + (rect_Car.Height * 2 / 5) + (int_Row * (int_HoleWidth + (int_HoleWidth / 4))), int_HoleWidth, int_HoleWidth);
                    }

                    arr_Holes.Add(rect_Hole);
                }
            }
            var loopTo = arr_Holes.Count;

            for (int_Count = 1; int_Count <= loopTo; int_Count++)
            {
                rect_Hole = arr_Holes[int_Count - 1];
                dc.DrawOval(rect_Hole, _blackPaint);

                if (_arr_Pegs.Count >= int_Count)
                {
                    clr_Peg = _arr_Pegs[int_Count - 1].ToSKColor();
                    DrawPeg(dc, rect_Hole, clr_Peg);
                }
            }
        }
Пример #19
0
 public static SKMatrix RotateDegrees(this SKMatrix m, float andegrees)
 {
     return(m.Concat(SKMatrix.MakeRotationDegrees(andegrees)));
 }
Пример #20
0
 public SKLinearGradient(float startX, float startY, float endX, float endY, float[] positions, SKColor[] colors, SKShaderTileMode tileMode, SKMatrix gradientTransform)
 {
     StartX            = startX;
     StartY            = startY;
     EndX              = endX;
     EndY              = endY;
     Positions         = positions;
     Colors            = colors;
     TileMode          = tileMode;
     GradientTransform = gradientTransform;
 }
Пример #21
0
 public static SKMatrix Translate(this SKMatrix m, float dx, float dy)
 {
     return(m.Concat(SKMatrix.MakeTranslation(dx, dy)));
 }
Пример #22
0
        private void ReadElement(XElement e, SKCanvas canvas, SKPaint stroke, SKPaint fill)
        {
            ReadPaints(e, ref stroke, ref fill);

            // transform matrix
            var transform = ReadTransform(e.Attribute("transform")?.Value ?? string.Empty);

            canvas.Save();
            canvas.Concat(ref transform);

            // SVG elements
            var elementName = e.Name.LocalName;

            switch (elementName)
            {
            case "text":
                if (stroke != null || fill != null)
                {
                    ReadText(e, canvas, stroke?.Clone(), fill?.Clone());
                }
                break;

            case "rect":
                if (stroke != null || fill != null)
                {
                    var x      = ReadNumber(e.Attribute("x"));
                    var y      = ReadNumber(e.Attribute("y"));
                    var width  = ReadNumber(e.Attribute("width"));
                    var height = ReadNumber(e.Attribute("height"));
                    var rx     = ReadNumber(e.Attribute("rx"));
                    var ry     = ReadNumber(e.Attribute("ry"));
                    var rect   = SKRect.Create(x, y, width, height);
                    if (rx > 0 || ry > 0)
                    {
                        if (fill != null)
                        {
                            canvas.DrawRoundRect(rect, rx, ry, fill);
                        }
                        if (stroke != null)
                        {
                            canvas.DrawRoundRect(rect, rx, ry, stroke);
                        }
                    }
                    else
                    {
                        if (fill != null)
                        {
                            canvas.DrawRect(rect, fill);
                        }
                        if (stroke != null)
                        {
                            canvas.DrawRect(rect, stroke);
                        }
                    }
                }
                break;

            case "ellipse":
                if (stroke != null || fill != null)
                {
                    var cx = ReadNumber(e.Attribute("cx"));
                    var cy = ReadNumber(e.Attribute("cy"));
                    var rx = ReadNumber(e.Attribute("rx"));
                    var ry = ReadNumber(e.Attribute("ry"));
                    if (fill != null)
                    {
                        canvas.DrawOval(cx, cy, rx, ry, fill);
                    }
                    if (stroke != null)
                    {
                        canvas.DrawOval(cx, cy, rx, ry, stroke);
                    }
                }
                break;

            case "circle":
                if (stroke != null || fill != null)
                {
                    var cx = ReadNumber(e.Attribute("cx"));
                    var cy = ReadNumber(e.Attribute("cy"));
                    var rr = ReadNumber(e.Attribute("r"));
                    if (fill != null)
                    {
                        canvas.DrawCircle(cx, cy, rr, fill);
                    }
                    if (stroke != null)
                    {
                        canvas.DrawCircle(cx, cy, rr, stroke);
                    }
                }
                break;

            case "path":
                if (stroke != null || fill != null)
                {
                    var d = e.Attribute("d")?.Value;
                    if (!string.IsNullOrWhiteSpace(d))
                    {
                        var path = SKPath.ParseSvgPathData(d);
                        if (fill != null)
                        {
                            canvas.DrawPath(path, fill);
                        }
                        if (stroke != null)
                        {
                            canvas.DrawPath(path, stroke);
                        }
                    }
                }
                break;

            case "polygon":
            case "polyline":
                if (stroke != null || fill != null)
                {
                    var close = elementName == "polygon";
                    var p     = e.Attribute("points")?.Value;
                    if (!string.IsNullOrWhiteSpace(p))
                    {
                        var path = ReadPolyPath(p, close);
                        if (fill != null)
                        {
                            canvas.DrawPath(path, fill);
                        }
                        if (stroke != null)
                        {
                            canvas.DrawPath(path, stroke);
                        }
                    }
                }
                break;

            case "g":
                if (e.HasElements)
                {
                    foreach (var gElement in e.Elements())
                    {
                        ReadElement(gElement, canvas, stroke?.Clone(), fill?.Clone());
                    }
                }
                break;

            case "use":
                if (e.HasAttributes)
                {
                    var href = ReadHref(e);
                    if (href != null)
                    {
                        // TODO: copy/process other attributes

                        var x            = ReadNumber(e.Attribute("x"));
                        var y            = ReadNumber(e.Attribute("y"));
                        var useTransform = SKMatrix.MakeTranslation(x, y);

                        canvas.Save();
                        canvas.Concat(ref useTransform);

                        ReadElement(href, canvas, stroke?.Clone(), fill?.Clone());

                        canvas.Restore();
                    }
                }
                break;

            case "line":
                if (stroke != null)
                {
                    var x1 = ReadNumber(e.Attribute("x1"));
                    var x2 = ReadNumber(e.Attribute("x2"));
                    var y1 = ReadNumber(e.Attribute("y1"));
                    var y2 = ReadNumber(e.Attribute("y2"));
                    canvas.DrawLine(x1, y1, x2, y2, stroke);
                }
                break;

            case "switch":
                if (e.HasElements)
                {
                    foreach (var ee in e.Elements())
                    {
                        var requiredFeatures   = ee.Attribute("requiredFeatures");
                        var requiredExtensions = ee.Attribute("requiredExtensions");
                        var systemLanguage     = ee.Attribute("systemLanguage");

                        // TODO: evaluate requiredFeatures, requiredExtensions and systemLanguage
                        var isVisible =
                            requiredFeatures == null &&
                            requiredExtensions == null &&
                            systemLanguage == null;

                        if (isVisible)
                        {
                            ReadElement(ee, canvas, stroke?.Clone(), fill?.Clone());
                        }
                    }
                }
                break;

            case "defs":
            case "title":
            case "desc":
            case "description":
                // already read earlier
                break;

            default:
                LogOrThrow($"SVG element '{elementName}' is not supported");
                break;
            }

            // restore matrix
            canvas.Restore();
        }
Пример #23
0
 public static SKMatrix Rotate(this SKMatrix m, float angle)
 {
     return(m.Concat(SKMatrix.MakeRotation(angle)));
 }
Пример #24
0
        private SKMatrix ReadTransform(string raw)
        {
            var t = SKMatrix.MakeIdentity();

            if (string.IsNullOrWhiteSpace(raw))
            {
                return(t);
            }

            var calls = raw.Trim().Split(new[] { ')' }, StringSplitOptions.RemoveEmptyEntries);

            foreach (var c in calls)
            {
                var args = c.Split(new[] { '(', ',', ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                var nt   = SKMatrix.MakeIdentity();
                switch (args[0])
                {
                case "matrix":
                    if (args.Length == 7)
                    {
                        nt.Values = new float[]
                        {
                            ReadNumber(args[1]), ReadNumber(args[3]), ReadNumber(args[5]),
                            ReadNumber(args[2]), ReadNumber(args[4]), ReadNumber(args[6]),
                            0, 0, 1
                        };
                    }
                    else
                    {
                        LogOrThrow($"Matrices are expected to have 6 elements, this one has {args.Length - 1}");
                    }
                    break;

                case "translate":
                    if (args.Length >= 3)
                    {
                        nt = SKMatrix.MakeTranslation(ReadNumber(args[1]), ReadNumber(args[2]));
                    }
                    else if (args.Length >= 2)
                    {
                        nt = SKMatrix.MakeTranslation(ReadNumber(args[1]), 0);
                    }
                    break;

                case "scale":
                    if (args.Length >= 3)
                    {
                        nt = SKMatrix.MakeScale(ReadNumber(args[1]), ReadNumber(args[2]));
                    }
                    else if (args.Length >= 2)
                    {
                        var sx = ReadNumber(args[1]);
                        nt = SKMatrix.MakeScale(sx, sx);
                    }
                    break;

                case "rotate":
                    var a = ReadNumber(args[1]);
                    if (args.Length >= 4)
                    {
                        var x  = ReadNumber(args[2]);
                        var y  = ReadNumber(args[3]);
                        var t1 = SKMatrix.MakeTranslation(x, y);
                        var t2 = SKMatrix.MakeRotationDegrees(a);
                        var t3 = SKMatrix.MakeTranslation(-x, -y);
                        SKMatrix.Concat(ref nt, ref t1, ref t2);
                        SKMatrix.Concat(ref nt, ref nt, ref t3);
                    }
                    else
                    {
                        nt = SKMatrix.MakeRotationDegrees(a);
                    }
                    break;

                default:
                    LogOrThrow($"Can't transform {args[0]}");
                    break;
                }
                SKMatrix.Concat(ref t, ref t, ref nt);
            }

            return(t);
        }
Пример #25
0
 public SKRadialGradient(SKPoint center, float radius, float[] positions, SKColor[] colors, SKShaderTileMode tileMode, SKMatrix matrix)
 {
     Center    = center;
     Radius    = radius;
     Positions = positions;
     Colors    = colors;
     TileMode  = tileMode;
     Matrix    = matrix;
 }
Пример #26
0
        private void PaintSVTriangle(SKCanvas canvas, float canvasRadius)
        {
            canvas.Save();

            SKMatrix rotationHue = SKMatrix.MakeRotation(-(float)((2D * Math.PI * lastHue) + (Math.PI / 2D))
                                                         , canvasRadius, canvasRadius);

            if (RotateTriangleByHue)
            {
                canvas.SetMatrix(rotationHue);
            }

            var point1 = new SKPoint(canvasRadius, canvasRadius - WheelSVRadius(canvasRadius));
            var point2 = new SKPoint(canvasRadius + (triangleSide * WheelSVRadius(canvasRadius))
                                     , canvasRadius + (triangleVerticalOffset * WheelSVRadius(canvasRadius)));
            var point3 = new SKPoint(canvasRadius - (triangleSide * WheelSVRadius(canvasRadius))
                                     , canvasRadius + (triangleVerticalOffset * WheelSVRadius(canvasRadius)));

            using (SKPath pathTriangle = new SKPath())
            {
                pathTriangle.MoveTo(point1);
                pathTriangle.LineTo(point2);
                pathTriangle.LineTo(point3);
                canvas.ClipPath(pathTriangle, SKClipOperation.Intersect, true);
            }

            SKMatrix matrix = SKMatrix.MakeRotation(-(float)Math.PI / 3F, point3.X, point3.Y);

            if (RotateTriangleByHue)
            {
                SKMatrix.Concat(ref matrix, rotationHue, matrix);
            }

            var shader = SKShader.CreateSweepGradient(point3, new SKColor[] { Color.FromHsla(lastHue, 1, 0.5).ToSKColor()
                                                                              , Color.White.ToSKColor(), Color.FromHsla(lastHue, 1, 0.5).ToSKColor() }
                                                      , new float[] { 0F, 0.16666666666666F, 1F });

            var paint = new SKPaint
            {
                IsAntialias = true,
                Shader      = shader,
                Style       = SKPaintStyle.Fill
            };

            canvas.SetMatrix(matrix);
            canvas.DrawCircle(point3, WheelSVRadius(canvasRadius) * 2, paint);

            if (RotateTriangleByHue)
            {
                canvas.SetMatrix(rotationHue);
            }
            else
            {
                canvas.ResetMatrix();
            }

            var colors = new SKColor[] {
                SKColors.Black,
                SKColors.Transparent
            };

            PaintGradient(canvas, canvasRadius, colors, point3);

            canvas.ResetMatrix();
            canvas.Restore();
        }
Пример #27
0
 public Glyph(SvgGlyph svgGlyph)
 {
     matrix = SvgHelper.GetSKMatrix(svgGlyph.Transforms);
 }
Пример #28
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);
        }
Пример #29
0
        /// <summary>
        /// Configure paint wrapper for using gradient brush.
        /// </summary>
        /// <param name="paintWrapper">Paint wrapper.</param>
        /// <param name="targetRect">Target bound rect.</param>
        /// <param name="gradientBrush">Gradient brush.</param>
        private void ConfigureGradientBrush(ref PaintWrapper paintWrapper, Rect targetRect, 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();
            var position    = targetRect.Position.ToSKPoint();

            switch (gradientBrush)
            {
            case ILinearGradientBrush linearGradient:
            {
                var start = position + linearGradient.StartPoint.ToPixels(targetRect.Size).ToSKPoint();
                var end   = position + linearGradient.EndPoint.ToPixels(targetRect.Size).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 = position + radialGradient.Center.ToPixels(targetRect.Size).ToSKPoint();
                var radius = (float)(radialGradient.Radius * targetRect.Width);

                var origin = position + radialGradient.GradientOrigin.ToPixels(targetRect.Size).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 = position + conicGradient.Center.ToPixels(targetRect.Size).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;
            }
            }
        }
Пример #30
0
 public SVGPath(string pPath, string Transform)
 {
     //Identity matrix must always be default
     LocalTransform = SKMatrix.MakeIdentity();
 }