protected override void Draw(SKCanvas canvas)
        {
            var transformationMatrix = SKMatrix.CreateTranslation(Position.X - 266.75f, Position.Y - 272.15f);
            var scale = Size.Width / 200.0f;

            transformationMatrix = transformationMatrix.PostConcat(SKMatrix.CreateScale(scale, scale, Position.X, Position.Y));

            var red = SKPath.ParseSvgPathData("M272.1 107.7c38.8-.6 76.3 14 104.4 40.8l77.7-77.7C405 24.6 339.7-.8 272.1 0 169.2 0 75.1 58 28.9 150l90.4 70.1c21.5-64.5 81.8-112.4 152.8-112.4z");

            red.Transform(transformationMatrix);

            var green = SKPath.ParseSvgPathData("M272.1 544.3c73.4 0 135.3-24.1 180.4-65.7l-87.7-68c-24.4 16.6-55.9 26-92.6 26-71 0-131.2-47.9-152.8-112.3H28.9v70.1c46.2 91.9 140.3 149.9 243.2 149.9z");

            green.Transform(transformationMatrix);

            var blue = SKPath.ParseSvgPathData("M533.5 278.4c0-18.5-1.5-37.1-4.7-55.3H272.1v104.8h147c-6.1 33.8-25.7 63.7-54.4 82.7v68h87.7c51.5-47.4 81.1-117.4 81.1-200.2z");

            blue.Transform(transformationMatrix);

            var yellow = SKPath.ParseSvgPathData("M119.3 324.3c-11.4-33.8-11.4-70.4 0-104.2V150H28.9c-38.6 76.9-38.6 167.5 0 244.4l90.4-70.1z");

            yellow.Transform(transformationMatrix);

            canvas.DrawPath(red, _r);
            canvas.DrawPath(green, _g);
            canvas.DrawPath(blue, _b);
            canvas.DrawPath(yellow, _y);
        }
        public void TranslationToMatrixIsCorrect()
        {
            var m   = SKMatrix.CreateTranslation(5, 7);
            var rsm = SKRotationScaleMatrix.CreateTranslation(5, 7).ToMatrix();

            Assert.Equal(m.Values, rsm.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 MatrixCanInvert()
        {
            var m = SKMatrix.CreateTranslation(10, 20);

            Assert.True(m.TryInvert(out var inverse));
            Assert.Equal(SKMatrix.CreateTranslation(-10, -20).Values, inverse.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 MatrixMapsPoint()
        {
            var matrix         = SKMatrix.CreateTranslation(2, 4);
            var expectedResult = matrix.MapPoint(3, 6);

            Assert.Equal(new SKPoint(5, 10), expectedResult);
        }
示例#7
0
        public void MatrixMapsPoints()
        {
            var source = new[] {
                new SKPoint(0, 0),
                new SKPoint(-10, -10),
                new SKPoint(-10, 10),
                new SKPoint(10, -10),
                new SKPoint(10, 10),
                new SKPoint(-5, -5),
                new SKPoint(-5, 5),
                new SKPoint(5, -5),
                new SKPoint(5, 5),
            };

            var expectedResult = new[] {
                new SKPoint(10, 10),
                new SKPoint(0, 0),
                new SKPoint(0, 20),
                new SKPoint(20, 0),
                new SKPoint(20, 20),
                new SKPoint(5, 5),
                new SKPoint(5, 15),
                new SKPoint(15, 5),
                new SKPoint(15, 15),
            };

            var matrix = SKMatrix.CreateTranslation(10, 10);

            matrix.MapPoints(source, source);

            Assert.Equal(expectedResult, source);
        }
示例#8
0
        /// <summary>
        ///  Centers the viewport around the specified position(x-index and y-value)
        /// in the chart.Centering the viewport outside the bounds of the chart is
        /// not possible. Makes most sense in combination with the
        /// setScaleMinima(...) method.
        /// </summary>
        /// <param name="transformedPts">the position to center view viewport to</param>
        /// <param name="view"></param>
        public void CenterViewPort(SKPoint transformedPts, IChartBase view)
        {
            float x = transformedPts.X - OffsetLeft;
            float y = transformedPts.Y - OffsetTop;

            Refresh(touchMatrix.PostConcat(SKMatrix.CreateTranslation(-x, -y)), view, true);
        }
        protected override void Draw(SKCanvas canvas)
        {
            var transformationMatrix = SKMatrix.CreateTranslation(Position.X - 11.5f, Position.Y - 11.5f);
            var scale = 6.0f / Size.Width;

            transformationMatrix = transformationMatrix.PostConcat(SKMatrix.CreateScale(scale, scale, Position.X, Position.Y));

            var backgroundPath = SKPath.ParseSvgPathData("M0 0h23v23H0z");

            backgroundPath.Transform(transformationMatrix);

            var redSquarePath = SKPath.ParseSvgPathData("M1 1h10v10H1z");

            redSquarePath.Transform(transformationMatrix);

            var greenSquarePath = SKPath.ParseSvgPathData("M12 1h10v10H12z");

            greenSquarePath.Transform(transformationMatrix);

            var blueSquarePath = SKPath.ParseSvgPathData("M1 12h10v10H1z");

            blueSquarePath.Transform(transformationMatrix);

            var yellowSquarePath = SKPath.ParseSvgPathData("M12 12h10v10H12z");

            yellowSquarePath.Transform(transformationMatrix);

            canvas.DrawPath(backgroundPath, _background);
            canvas.DrawPath(redSquarePath, _r);
            canvas.DrawPath(greenSquarePath, _g);
            canvas.DrawPath(blueSquarePath, _b);
            canvas.DrawPath(yellowSquarePath, _y);
        }
示例#10
0
        /// <summary>
        /// Configure paint wrapper for using tile brush.
        /// </summary>
        /// <param name="paintWrapper">Paint wrapper.</param>
        /// <param name="targetSize">Target size.</param>
        /// <param name="tileBrush">Tile brush to use.</param>
        /// <param name="tileBrushImage">Tile brush image.</param>
        private void ConfigureTileBrush(ref PaintWrapper paintWrapper, Size targetSize, ITileBrush tileBrush, IDrawableBitmapImpl tileBrushImage)
        {
            var calc         = new TileBrushCalculator(tileBrush, tileBrushImage.PixelSize.ToSizeWithDpi(_dpi), targetSize);
            var intermediate = CreateRenderTarget(calc.IntermediateSize);

            paintWrapper.AddDisposable(intermediate);

            using (var context = intermediate.CreateDrawingContext(null))
            {
                var sourceRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(96));
                var targetRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(_dpi));

                context.Clear(Colors.Transparent);
                context.PushClip(calc.IntermediateClip);
                context.Transform = calc.IntermediateTransform;
                context.DrawBitmap(
                    RefCountable.CreateUnownedNotClonable(tileBrushImage),
                    1,
                    sourceRect,
                    targetRect,
                    tileBrush.BitmapInterpolationMode);
                context.PopClip();
            }

            var tileTransform =
                tileBrush.TileMode != TileMode.None
                    ? SKMatrix.CreateTranslation(-(float)calc.DestinationRect.X, -(float)calc.DestinationRect.Y)
                    : SKMatrix.CreateIdentity();

            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;


            var image = intermediate.SnapshotImage();

            paintWrapper.AddDisposable(image);

            var paintTransform = default(SKMatrix);

            SKMatrix.Concat(
                ref paintTransform,
                tileTransform,
                SKMatrix.CreateScale((float)(96.0 / _dpi.X), (float)(96.0 / _dpi.Y)));

            using (var shader = image.ToShader(tileX, tileY, paintTransform))
            {
                paintWrapper.Paint.Shader = shader;
            }
        }
示例#11
0
        public void Pinch(GestureState state, float scale, SKPoint origin)
        {
            switch (state)
            {
            case GestureState.Started:
                startPinchMatrix = Matrix;
                startPinchOrigin = origin;
                totalPinchScale  = 1f;
                break;

            case GestureState.Running:
                totalPinchScale *= scale;
                var pinchTranslation  = origin - startPinchOrigin;
                var canvasTranslation = SKMatrix.CreateTranslation(pinchTranslation.X, pinchTranslation.Y);
                var canvasScaling     = SKMatrix.CreateScale(totalPinchScale, totalPinchScale, origin.X, origin.Y);
                var canvasCombined    = SKMatrix.Identity;
                SKMatrix.Concat(ref canvasCombined, ref canvasScaling, ref canvasTranslation);
                SKMatrix.Concat(ref Matrix, ref canvasCombined, ref startPinchMatrix);
                break;

            default:
                startPinchMatrix = SKMatrix.Identity;
                startPinchOrigin = SKPoint.Empty;
                totalPinchScale  = 1f;
                break;
            }
        }
示例#12
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);
        }
示例#13
0
        public static void Save(Dictionary <int, ushort> characterToGlyphMap, SKTypeface typeface, float textSize, string fill, string outputDirectory, ZipArchive?zipArchive)
        {
            var skColor = new SKColor(0x00, 0x00, 0x00);

            using var skTextPaint = new SKPaint
                  {
                      IsAntialias   = true,
                      Color         = skColor,
                      Typeface      = typeface,
                      TextEncoding  = SKTextEncoding.Utf32,
                      TextSize      = textSize,
                      TextAlign     = SKTextAlign.Center,
                      LcdRenderText = true,
                      SubpixelText  = true
                  };

            var metrics  = skTextPaint.FontMetrics;
            var mAscent  = metrics.Ascent;
            var mDescent = metrics.Descent;

            foreach (var kvp in characterToGlyphMap)
            {
                var   charCode = kvp.Key;
                var   utf32    = Char.ConvertFromUtf32((int)charCode);
                float x        = 0;
                float y        = (mAscent / 2.0f) - mDescent / 2.0f;

                using var outlinePath = skTextPaint.GetTextPath(utf32, x, y);
                using var fillPath    = skTextPaint.GetFillPath(outlinePath);

                fillPath.Transform(SKMatrix.CreateTranslation(-fillPath.Bounds.Left, -fillPath.Bounds.Top));

                var bounds      = fillPath.Bounds;
                var svgPathData = fillPath.ToSvgPathData();

                var sb = new StringBuilder();

                sb.AppendLine($"<svg viewBox=\"{bounds.Left} {bounds.Top} {bounds.Width} {bounds.Height}\" xmlns=\"http://www.w3.org/2000/svg\">"); // width=\"{bounds.Width}\" height=\"{bounds.Height}\"
                sb.AppendLine($"  <path fill=\"{fill}\" d=\"{svgPathData}\"/>");
                sb.AppendLine($"</svg>");

                var svg = sb.ToString();

                var outputPath = Path.Combine(outputDirectory, $"{charCode.ToString("X2").PadLeft(5, '0')}_{typeface.FamilyName}.svg");

                if (zipArchive != null)
                {
                    var zipArchiveEntry = zipArchive.CreateEntry(outputPath);
                    using var streamWriter = new StreamWriter(zipArchiveEntry.Open());
                    streamWriter.Write(svg);
                }
                else
                {
                    using var streamWriter = File.CreateText(outputPath);
                    streamWriter.Write(svg);
                }
            }
        }
示例#14
0
        /// <summary>
        ///     Opens the render context using the dimensions of the provided path
        /// </summary>
        public void Open(SKPath path, Folder?parent)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("Renderer");
            }

            if (IsOpen)
            {
                throw new ArtemisCoreException("Cannot open render context because it is already open");
            }

            if (path.Bounds != _lastBounds || (parent != null && parent.Bounds != _lastParentBounds) || _lastGraphicsContext != Constants.ManagedGraphicsContext?.GraphicsContext)
            {
                Invalidate();
            }

            if (!_valid || Surface == null)
            {
                SKRect pathBounds = path.Bounds;
                int    width      = (int)pathBounds.Width;
                int    height     = (int)pathBounds.Height;

                SKImageInfo imageInfo = new(width, height);
                if (Constants.ManagedGraphicsContext?.GraphicsContext == null)
                {
                    Surface = SKSurface.Create(imageInfo);
                }
                else
                {
                    Surface = SKSurface.Create(Constants.ManagedGraphicsContext.GraphicsContext, true, imageInfo);
                }

                Path = new SKPath(path);
                Path.Transform(SKMatrix.CreateTranslation(pathBounds.Left * -1, pathBounds.Top * -1));

                TargetLocation = new SKPoint(pathBounds.Location.X, pathBounds.Location.Y);
                if (parent != null)
                {
                    TargetLocation -= parent.Bounds.Location;
                }

                Surface.Canvas.ClipPath(Path);

                _lastParentBounds    = parent?.Bounds ?? new SKRect();
                _lastBounds          = path.Bounds;
                _lastGraphicsContext = Constants.ManagedGraphicsContext?.GraphicsContext;
                _valid = true;
            }

            Paint = new SKPaint();

            Surface.Canvas.Clear();
            Surface.Canvas.Save();

            IsOpen = true;
        }
示例#15
0
        public void MatrixCanPostConcat()
        {
            var a = SKMatrix.CreateTranslation(10, 20);
            var b = SKMatrix.CreateTranslation(5, 7);

            var c = a.PostConcat(b);

            Assert.Equal(SKMatrix.CreateTranslation(15, 27).Values, c.Values);
        }
示例#16
0
        public void MapRectCreatesModifiedRect()
        {
            var rect = SKRect.Create(2, 4, 6, 8);

            var matrix = SKMatrix.CreateTranslation(10, 12);
            var mapped = matrix.MapRect(rect);

            Assert.Equal(SKRect.Create(12, 16, 6, 8), mapped);
        }
示例#17
0
        /// <summary>
        /// Updates the particle's position and orientation based on the given time
        /// </summary>
        /// <para>Call this method first and then <see cref="Paint"/></para>
        /// <para>This method doesn't need to be called on the UI/Main thread</para>
        /// <param name="absoluteElapsedMillis"></param>
        public virtual void Update(long absoluteElapsedMillis, SKSize scale)
        {
            // Determine elapsed time since this particles was created
            var elapsedMillis = absoluteElapsedMillis - _absoluteElapsedMillisPrevious;

            if (_absoluteElapsedMillisPrevious == 0)
            {
                _absoluteElapsedMillisPrevious = absoluteElapsedMillis;
                return;
            }

            _internalAbsoluteMillis       += elapsedMillis;
            _absoluteElapsedMillisPrevious = absoluteElapsedMillis;

            // Traversed distance = speed x time
            var dist = TranslationSpeed * _internalAbsoluteMillis * 0.001;

            // New position
            var deg2radFactor = 0.0174533;
            var angle         = Direction * deg2radFactor;

            Position = InitialPosition + new SKPoint
            {
                X = (float)(dist * Math.Cos(angle)),
                Y = (float)(dist * Math.Sin(angle))
            };

            TransformationMatrix = SKMatrix.CreateTranslation(-Position.X, -Position.Y);

            // New Scale
            TransformationMatrix = TransformationMatrix.PostConcat(SKMatrix.CreateScale(scale.Width, scale.Height));

            // New Orientation
            Orientation = InitialOrientation + new SKPoint3
            {
                X = _internalAbsoluteMillis * 0.001f * RotationSpeed.X,
                Y = _internalAbsoluteMillis * 0.001f * RotationSpeed.Y,
                Z = _internalAbsoluteMillis * 0.001f * RotationSpeed.Z
            };

            _totalRotationMatrix.SetIdentity();

            _xAxisRotationMatrix.SetRotationAboutDegrees(1, 0, 0, Orientation.X);
            _totalRotationMatrix.PostConcat(_xAxisRotationMatrix);

            _yAxisRotationMatrix.SetRotationAboutDegrees(0, 1, 0, Orientation.Y);
            _totalRotationMatrix.PostConcat(_yAxisRotationMatrix);

            _zAxisRotationMatrix.SetRotationAboutDegrees(0, 0, 1, Orientation.Z);
            _totalRotationMatrix.PostConcat(_zAxisRotationMatrix);

            TransformationMatrix = TransformationMatrix.PostConcat(_totalRotationMatrix.Matrix);

            // Translate back
            TransformationMatrix = TransformationMatrix.PostConcat(SKMatrix.CreateTranslation(Position.X, Position.Y));
        }
示例#18
0
        public static void PerformMirrorOperation(DrawItem tmpItem, float canvasWidth)
        {
            float midPoint      = canvasWidth / 2.0f;
            float drawMidXPoint = tmpItem.Path.Bounds.MidX;
            float x             = (midPoint - drawMidXPoint) * 2;

            SKMatrix translateXaxis = SKMatrix.CreateTranslation(x, 0);

            tmpItem.Path.Transform(translateXaxis);
        }
示例#19
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();
            }
        }
示例#20
0
        public virtual void Update(SKCanvas canvas, long absoluteElapsedMillis)
        {
            var elapsedMillis = absoluteElapsedMillis - _absoluteElapsedMillisPrevious;

            if (_absoluteElapsedMillisPrevious == 0)
            {
                _absoluteElapsedMillisPrevious = absoluteElapsedMillis;
                return;
            }

            _internalAbsoluteMillis       += elapsedMillis;
            _absoluteElapsedMillisPrevious = absoluteElapsedMillis;

            canvas.Save();

            // Traversed distance = speed x time
            var dist = TranslationSpeed * _internalAbsoluteMillis * 0.001;

            // New position
            var deg2radFactor = 0.0174533;
            var angle         = Direction * deg2radFactor;

            Position = InitialPosition + new SKPoint
            {
                X = (float)(dist * Math.Cos(angle)),
                Y = (float)(dist * Math.Sin(angle))
            };

            var matrix = SKMatrix.CreateTranslation(-Position.X, -Position.Y);

            // New Orientation
            Orientation = InitialOrientation + new SKPoint3
            {
                X = _internalAbsoluteMillis * 0.001f * RotationSpeed.X,
                Y = _internalAbsoluteMillis * 0.001f * RotationSpeed.Y,
                Z = _internalAbsoluteMillis * 0.001f * RotationSpeed.Z
            };

            var matrix44 = SKMatrix44.CreateIdentity();

            matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(1, 0, 0, Orientation.X));
            matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 1, 0, Orientation.Y));
            matrix44.PostConcat(SKMatrix44.CreateRotationDegrees(0, 0, 1, Orientation.Z));

            // Apply transforms
            matrix = matrix.PostConcat(matrix44.Matrix);
            matrix = matrix.PostConcat(SKMatrix.CreateTranslation(Position.X, Position.Y));
            canvas.SetMatrix(matrix);

            Draw(canvas);

            canvas.Restore();
        }
示例#21
0
        SKMatrix CreateMatrix()
        {
            SKMatrix matrix = SKMatrix.CreateIdentity();

            SKRect drawableBounds  = _drawableBounds;
            float  halfStrokeWidth = _skPaint.StrokeWidth / 2;

            drawableBounds.Left   += halfStrokeWidth;
            drawableBounds.Top    += halfStrokeWidth;
            drawableBounds.Right  -= halfStrokeWidth;
            drawableBounds.Bottom -= halfStrokeWidth;

            float widthScale  = drawableBounds.Width / _pathFillBounds.Width;
            float heightScale = drawableBounds.Height / _pathFillBounds.Height;

            switch (_stretch)
            {
            case Stretch.None:
                drawableBounds = _drawableBounds;
                float adjustX = Math.Min(0, _pathStrokeBounds.Left);
                float adjustY = Math.Min(0, _pathStrokeBounds.Top);
                if (adjustX < 0 || adjustY < 0)
                {
                    matrix = SKMatrix.CreateTranslation(-adjustX, -adjustY);
                }
                break;

            case Stretch.Fill:
                matrix = SKMatrix.CreateScale(widthScale, heightScale);
                matrix = matrix.PostConcat(
                    SKMatrix.CreateTranslation(drawableBounds.Left - widthScale * _pathFillBounds.Left,
                                               drawableBounds.Top - heightScale * _pathFillBounds.Top));
                break;

            case Stretch.Uniform:
                float minScale = Math.Min(widthScale, heightScale);
                matrix = SKMatrix.CreateScale(minScale, minScale);
                matrix = matrix.PostConcat(
                    SKMatrix.CreateTranslation(drawableBounds.Left - (minScale * _pathFillBounds.Left) + (drawableBounds.Width - (minScale * _pathFillBounds.Width)) / 2,
                                               drawableBounds.Top - (minScale * _pathFillBounds.Top) + (drawableBounds.Height - (minScale * _pathFillBounds.Height)) / 2));
                break;

            case Stretch.UniformToFill:
                float maxScale = Math.Max(widthScale, heightScale);
                matrix = SKMatrix.CreateScale(maxScale, maxScale);
                matrix = matrix.PostConcat(
                    SKMatrix.CreateTranslation(drawableBounds.Left - (maxScale * _pathFillBounds.Left),
                                               drawableBounds.Top - (maxScale * _pathFillBounds.Top)));
                break;
            }

            return(matrix);
        }
示例#22
0
        /**
         * <summary>Expands the size of this quad stretching around its center.</summary>
         * <param name="valueX">Expansion's horizontal extent.</param>
         * <param name="valueY">Expansion's vertical extent.</param>
         * <returns>This quad.</returns>
         */
        public Quad Inflate(float valueX, float valueY)
        {
            SKRect oldBounds = GetBounds();
            var    matrix    = SKMatrix.CreateTranslation(oldBounds.MidX, oldBounds.MidY);

            matrix           = matrix.PreConcat(SKMatrix.CreateScale(1 + valueX * 2 / oldBounds.Width, 1 + valueY * 2 / oldBounds.Height));
            matrix           = matrix.PreConcat(SKMatrix.CreateTranslation(-(oldBounds.MidX), -(oldBounds.MidY)));
            pointTopLeft     = matrix.MapPoint(pointTopLeft);
            pointTopRight    = matrix.MapPoint(pointTopRight);
            pointBottomRight = matrix.MapPoint(pointBottomRight);
            pointBottomLeft  = matrix.MapPoint(pointBottomLeft);
            return(this);
        }
示例#23
0
        private protected SKMatrix CreateTransformMatrix(SKRect bounds)
        {
            var transform = SKMatrix.Identity;

            // Translate to origin
            if (CenterPoint != Vector2.Zero)
            {
                transform = SKMatrix.CreateTranslation(-CenterPoint.X, -CenterPoint.Y);
            }

            // Scaling
            if (Scale != Vector2.One)
            {
                transform = transform.PostConcat(SKMatrix.CreateScale(Scale.X, Scale.Y));
            }

            // Rotating
            if (RotationAngle != 0)
            {
                transform = transform.PostConcat(SKMatrix.CreateRotation(RotationAngle));
            }

            // Translating
            if (Offset != Vector2.Zero)
            {
                transform = transform.PostConcat(SKMatrix.CreateTranslation(Offset.X, Offset.Y));
            }

            // Translate back
            if (CenterPoint != Vector2.Zero)
            {
                transform = transform.PostConcat(SKMatrix.CreateTranslation(CenterPoint.X, CenterPoint.Y));
            }

            if (!TransformMatrix.IsIdentity)
            {
                transform = transform.PostConcat(TransformMatrix.ToSKMatrix());
            }

            var relativeTransform = RelativeTransformMatrix.IsIdentity ? SKMatrix.Identity : RelativeTransformMatrix.ToSKMatrix();

            if (!relativeTransform.IsIdentity)
            {
                relativeTransform.TransX *= bounds.Width;
                relativeTransform.TransY *= bounds.Height;

                transform = transform.PostConcat(relativeTransform);
            }

            return(transform);
        }
        protected override void Draw(SKCanvas canvas)
        {
            var transformationMatrix = SKMatrix.CreateTranslation(Position.X - 8.0f, Position.Y - 8.0f);
            var scale = 6.0f / Size.Width;

            transformationMatrix = transformationMatrix.PostConcat(SKMatrix.CreateScale(scale, scale, Position.X, Position.Y));

            var backgroundPath = SKPath.ParseSvgPathData(
                "M8 0C3.58 0 0 3.58 0 8C0 11.54 2.29 14.53 5.47 15.59C5.87 15.66 6.02 15.42 6.02 15.21C6.02 15.02 6.01 14.39 6.01 13.72C4 14.09 3.48 13.23 3.32 12.78C3.23 12.55 2.84 11.84 2.5 11.65C2.22 11.5 1.82 11.13 2.49 11.12C3.12 11.11 3.57 11.7 3.72 11.94C4.44 13.15 5.59 12.81 6.05 12.6C6.12 12.08 6.33 11.73 6.56 11.53C4.78 11.33 2.92 10.64 2.92 7.58C2.92 6.71 3.23 5.99 3.74 5.43C3.66 5.23 3.38 4.41 3.82 3.31C3.82 3.31 4.49 3.1 6.02 4.13C6.66 3.95 7.34 3.86 8.02 3.86C8.7 3.86 9.38 3.95 10.02 4.13C11.55 3.09 12.22 3.31 12.22 3.31C12.66 4.41 12.38 5.23 12.3 5.43C12.81 5.99 13.12 6.7 13.12 7.58C13.12 10.65 11.25 11.33 9.47 11.53C9.76 11.78 10.01 12.26 10.01 13.01C10.01 14.08 10 14.94 10 15.21C10 15.42 10.15 15.67 10.55 15.59C13.71 14.53 16 11.53 16 8C16 3.58 12.42 0 8 0Z");

            backgroundPath.Transform(transformationMatrix);

            canvas.DrawPath(backgroundPath, _paint);
        }
 public override void PrepareMatrixOffset(bool inverted)
 {
     if (!inverted)
     {
         MatrixOffset = SKMatrix.Identity.PostConcat(SKMatrix.CreateTranslation(ViewPortHandler.OffsetLeft,
                                                                                ViewPortHandler.ChartHeight - ViewPortHandler.OffsetBottom));
     }
     else
     {
         MatrixOffset = SKMatrix
                        .CreateTranslation(ViewPortHandler.OffsetRight - ViewPortHandler.ChartWidth, ViewPortHandler.ChartHeight - ViewPortHandler.OffsetTop)
                        .PostConcat(SKMatrix.CreateScale(-1f, 1f));
     }
 }
示例#26
0
        /// <summary>
        /// 单指操纵
        /// </summary>
        /// <param name="prevPoint"></param>
        /// <param name="newPoint"></param>
        /// <param name="pivotPoint"></param>
        /// <returns></returns>
        public SKMatrix OneFingerManipulate(SKPoint prevPoint, SKPoint newPoint, SKPoint pivotPoint)
        {
            if (Mode == TouchManipulationMode.None)
            {
                return(SKMatrix.CreateIdentity());
            }

            SKMatrix touchMatrix = SKMatrix.CreateIdentity();
            SKPoint  delta       = newPoint - prevPoint;

            if (Mode == TouchManipulationMode.ScaleDualRotate)  // One-finger rotation
            {
                SKPoint oldVector = prevPoint - pivotPoint;
                SKPoint newVector = newPoint - pivotPoint;

                float scale = Magnitude(newVector) / Magnitude(oldVector);


                // Avoid rotation if fingers are too close to center
                if (Magnitude(newVector) > 30 && Magnitude(oldVector) > 30)
                {
                    float prevAngle = (float)Math.Atan2(oldVector.Y, oldVector.X);
                    float newAngle  = (float)Math.Atan2(newVector.Y, newVector.X);

                    // Calculate rotation matrix
                    float angle = newAngle - prevAngle;
                    touchMatrix = SKMatrix.CreateRotation(angle, pivotPoint.X, pivotPoint.Y);

                    // Effectively rotate the old vector
                    float magnitudeRatio = Magnitude(oldVector) / Magnitude(newVector);
                    oldVector.X = magnitudeRatio * newVector.X;
                    oldVector.Y = magnitudeRatio * newVector.Y;

                    // Recalculate delta
                    delta = newVector - oldVector;
                }

                if (!float.IsNaN(scale) && !float.IsInfinity(scale))
                {
                    var tm = SKMatrix.CreateScale(scale, scale, pivotPoint.X, pivotPoint.Y);
                    touchMatrix.PostConcat(tm);
                }
            }

            // Multiply the rotation matrix by a translation matrix
            touchMatrix.PostConcat(SKMatrix.CreateTranslation(delta.X, delta.Y));

            return(touchMatrix);
        }
示例#27
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();
            }
        }
示例#28
0
        public void CanTransform()
        {
            var radii = new[] { new SKPoint(5, 5), new SKPoint(5, 5), new SKPoint(5, 5), new SKPoint(5, 5) };

            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.CreateTranslation(2, 2));

            Assert.Equal(offset, transformed.Rect);
            Assert.Equal(radii, transformed.Radii);
        }
示例#29
0
        public static MaskDrawable Create(SvgMask svgMask, SKRect skViewport, DrawableBase?parent, IAssetLoader assetLoader, HashSet <Uri>?references, DrawAttributes ignoreAttributes = DrawAttributes.None)
        {
            var drawable = new MaskDrawable(assetLoader, references)
            {
                Element          = svgMask,
                Parent           = parent,
                IgnoreAttributes = ignoreAttributes,
                IsDrawable       = true
            };

            if (!drawable.IsDrawable)
            {
                return(drawable);
            }

            var maskUnits        = svgMask.MaskUnits;
            var maskContentUnits = svgMask.MaskContentUnits;
            var xUnit            = svgMask.X;
            var yUnit            = svgMask.Y;
            var widthUnit        = svgMask.Width;
            var heightUnit       = svgMask.Height;

            // TODO: Pass correct skViewport
            var skRectTransformed = SvgExtensions.CalculateRect(xUnit, yUnit, widthUnit, heightUnit, maskUnits, skViewport, skViewport, svgMask);

            if (skRectTransformed is null)
            {
                drawable.IsDrawable = false;
                return(drawable);
            }

            var skMatrix = SKMatrix.CreateIdentity();

            if (maskContentUnits == SvgCoordinateUnits.ObjectBoundingBox)
            {
                var skBoundsTranslateTransform = SKMatrix.CreateTranslation(skViewport.Left, skViewport.Top);
                skMatrix = skMatrix.PreConcat(skBoundsTranslateTransform);

                var skBoundsScaleTransform = SKMatrix.CreateScale(skViewport.Width, skViewport.Height);
                skMatrix = skMatrix.PreConcat(skBoundsScaleTransform);
            }

            drawable.CreateChildren(svgMask, skViewport, drawable, assetLoader, references, ignoreAttributes);

            drawable.Initialize(skRectTransformed.Value, skMatrix);

            return(drawable);
        }
示例#30
0
        /// <summary>
        ///     Opens the render context using the dimensions of the provided path
        /// </summary>
        public void Open(SKPath path, Folder?parent)
        {
            if (_disposed)
            {
                throw new ObjectDisposedException("Renderer");
            }

            if (IsOpen)
            {
                throw new ArtemisCoreException("Cannot open render context because it is already open");
            }

            if (path.Bounds != _lastBounds || (parent != null && parent.Bounds != _lastParentBounds))
            {
                Invalidate();
            }

            if (!_valid || Canvas == null)
            {
                SKRect pathBounds = path.Bounds;
                int    width      = (int)pathBounds.Width;
                int    height     = (int)pathBounds.Height;

                Bitmap = new SKBitmap(width, height);
                Path   = new SKPath(path);
                Canvas = new SKCanvas(Bitmap);
                Path.Transform(SKMatrix.CreateTranslation(pathBounds.Left * -1, pathBounds.Top * -1));

                TargetLocation = new SKPoint(pathBounds.Location.X, pathBounds.Location.Y);
                if (parent != null)
                {
                    TargetLocation -= parent.Bounds.Location;
                }

                Canvas.ClipPath(Path);

                _lastParentBounds = parent?.Bounds ?? new SKRect();
                _lastBounds       = path.Bounds;
                _valid            = true;
            }

            Paint = new SKPaint();

            Canvas.Clear();
            Canvas.Save();

            IsOpen = true;
        }