コード例 #1
0
        /// <returns>Skew-X matrix.</returns>
        public static Matrix3X2 <float> SkewX(float a)
        {
            Matrix3X2 <float> matrix = Matrix3X2 <float> .Identity;

            matrix.M21 = MathF.Tan(a);
            return(matrix);
        }
コード例 #2
0
        public static float GetAverageScale(Matrix3X2 <float> t)
        {
            float sx = MathF.Sqrt(t.M11 * t.M11 + t.M21 * t.M21);
            float sy = MathF.Sqrt(t.M12 * t.M12 + t.M22 * t.M22);

            return((sx + sy) * 0.5f);
        }
コード例 #3
0
 public static bool Equal(Matrix3X2 <float> a, Matrix3X2 <float> b)
 {
     return
         (Equal(a.M11, b.M11) && Equal(a.M12, b.M12) &&
          Equal(a.M21, b.M21) && Equal(a.M22, b.M22) &&
          Equal(a.M31, b.M31) && Equal(a.M32, b.M32));
 }
コード例 #4
0
        /// <returns>Scale matrix.</returns>
        public static Matrix3X2 <float> Scale(Vector2D <float> s)
        {
            Matrix3X2 <float> matrix = Matrix3X2 <float> .Identity;

            matrix.M11 = s.X;
            matrix.M22 = s.Y;
            return(matrix);
        }
コード例 #5
0
        /// <summary>
        /// Transforms the vector by the matrix.
        /// </summary>
        /// <param name="v">Vector2 to transform.  Considered to be a row vector for purposes of multiplication.</param>
        /// <param name="matrix">Matrix to use as the transformation.</param>
        /// <param name="result">Row vector product of the transformation.</param>
        public static void Transform(ref Vector3 v, ref Matrix3X2 matrix, out Vector2 result)
        {
#if !WINDOWS
            result = new Vector2();
#endif
            result.X = v.X * matrix.M11 + v.Y * matrix.M21 + v.Z * matrix.M31;
            result.Y = v.X * matrix.M12 + v.Y * matrix.M22 + v.Z * matrix.M32;
        }
コード例 #6
0
        /// <summary>Transforms a point by given transform.</summary>
        public static Vector2D <float> Point(Matrix3X2 <float> t, Vector2D <float> s)
        {
            Vector2D <float> d = default;

            d.X = s.X * t.M11 + s.Y * t.M21 + t.M31;
            d.Y = s.X * t.M12 + s.Y * t.M22 + t.M32;
            return(d);
        }
コード例 #7
0
ファイル: Matrix2x2.cs プロジェクト: ErtyHackward/utopia
        /// <summary>
        /// Multiplies the two matrices.
        /// </summary>
        /// <param name="a">First matrix to multiply.</param>
        /// <param name="b">Second matrix to multiply.</param>
        /// <param name="result">Product of the multiplication.</param>
        public static void Multiply(ref Matrix2X3 a, ref Matrix3X2 b, out Matrix2X2 result)
        {
            result.M11 = a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31;
            result.M12 = a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32;

            result.M21 = a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31;
            result.M22 = a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32;
        }
コード例 #8
0
        /// <returns>The result of multiplication of two transforms, of A = B * A</returns>
        public static Matrix3X2 <float> Premultiply(Matrix3X2 <float> t, Matrix3X2 <float> s)
        {
            Matrix3X2 <float> s2 = s;

            s2 = Multiply(s2, t);
            t  = s2;
            return(t);
        }
コード例 #9
0
        /// <returns>Translation matrix.</returns>
        public static Matrix3X2 <float> Translate(Vector2D <float> t)
        {
            Matrix3X2 <float> matrix = Matrix3X2 <float> .Identity;

            matrix.M31 = t.X;
            matrix.M32 = t.Y;
            return(matrix);
        }
コード例 #10
0
        /// <summary>
        /// Transforms the vector by the matrix.
        /// </summary>
        /// <param name="v">Vector2 to transform.  Considered to be a column vector for purposes of multiplication.</param>
        /// <param name="matrix">Matrix to use as the transformation.</param>
        /// <param name="result">Column vector product of the transformation.</param>
        public static void Transform(ref Vector2 v, ref Matrix3X2 matrix, out Vector3 result)
        {
#if !WINDOWS
            result = new Vector3();
#endif
            result.X = matrix.M11 * v.X + matrix.M12 * v.Y;
            result.Y = matrix.M21 * v.X + matrix.M22 * v.Y;
            result.Z = matrix.M31 * v.X + matrix.M32 * v.Y;
        }
コード例 #11
0
ファイル: Paint.cs プロジェクト: MatijaBrown/SilkyNvg
 public Paint(Matrix3X2 <float> transform, Vector2D <float> extent, float radius, float feather, Colour innerColour, Colour outerColour, int image)
 {
     Transform   = transform;
     Extent      = extent;
     Radius      = radius;
     Feather     = feather;
     InnerColour = innerColour;
     OuterColour = outerColour;
     Image       = image;
 }
コード例 #12
0
ファイル: Paint.cs プロジェクト: MatijaBrown/SilkyNvg
        /// <summary>
        /// Creates and returns an image pattern.
        /// The gradient is transformed by the current transform when it is passed to Nvg.FillPaint() or Nvg.StrokePaint().
        /// </summary>
        /// <param name="bounds">Specifies the bounds of the image pattern.</param>
        /// <param name="angle">Specified rotation around the top-left corner</param>
        /// <param name="image">Is handle to the image to render</param>
        /// <returns>An image pattern.</returns>
        public static Paint ImagePattern(Rectangle <float> bounds, float angle, int image, float alpha)
        {
            Matrix3X2 <float> transform = Matrix3X2.CreateRotation(angle);

            transform.M31 = bounds.Origin.X;
            transform.M32 = bounds.Origin.Y;

            Vector2D <float> extent = bounds.Size;

            return(new Paint(transform, extent, default, default, new Colour(1.0f, 1.0f, 1.0f, alpha), new Colour(1.0f, 1.0f, 1.0f, alpha), image));
コード例 #13
0
        /// <summary>
        /// Computes the transposed matrix of a matrix.
        /// </summary>
        /// <param name="matrix">Matrix to transpose.</param>
        /// <param name="result">Transposed matrix.</param>
        public static void Transpose(ref Matrix3X2 matrix, out Matrix2X3 result)
        {
            result.M11 = matrix.M11;
            result.M12 = matrix.M21;
            result.M13 = matrix.M31;

            result.M21 = matrix.M12;
            result.M22 = matrix.M22;
            result.M23 = matrix.M32;
        }
コード例 #14
0
        public override int GetHashCode()
        {
            int hash = 1;

            if (Topic.Length != 0)
            {
                hash ^= Topic.GetHashCode();
            }
            if (typeCase_ == TypeOneofCase.Number)
            {
                hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(Number);
            }
            if (typeCase_ == TypeOneofCase.Boolean)
            {
                hash ^= Boolean.GetHashCode();
            }
            if (typeCase_ == TypeOneofCase.String)
            {
                hash ^= String.GetHashCode();
            }
            if (typeCase_ == TypeOneofCase.Vector2)
            {
                hash ^= Vector2.GetHashCode();
            }
            if (typeCase_ == TypeOneofCase.Vector3)
            {
                hash ^= Vector3.GetHashCode();
            }
            if (typeCase_ == TypeOneofCase.Vector4)
            {
                hash ^= Vector4.GetHashCode();
            }
            if (typeCase_ == TypeOneofCase.Quaternion)
            {
                hash ^= Quaternion.GetHashCode();
            }
            if (typeCase_ == TypeOneofCase.Matrix3X2)
            {
                hash ^= Matrix3X2.GetHashCode();
            }
            if (typeCase_ == TypeOneofCase.Matrix4X4)
            {
                hash ^= Matrix4X4.GetHashCode();
            }
            if (typeCase_ == TypeOneofCase.Color)
            {
                hash ^= Color.GetHashCode();
            }
            hash ^= (int)typeCase_;
            if (_unknownFields != null)
            {
                hash ^= _unknownFields.GetHashCode();
            }
            return(hash);
        }
コード例 #15
0
ファイル: Paint.cs プロジェクト: MatijaBrown/SilkyNvg
        /// <summary>
        /// Creates and returns a linear gradient. Box gradient is a feathered rounded rectangle, it is useful for rendering
        /// drop shadows or highlitghts for boxes. Feather defines how blurry the corner of the rectangle is. The gradient
        /// is transformed by the current transform when it is passed to NvgRenderStyle.FillPaint() or NvgRenderStyle.StrokePaint();
        /// </summary>
        /// <param name="box">The rectangle.</param>
        /// <param name="r">Defines the corner radius.</param>
        /// <param name="f">Defines the feather.</param>
        /// <param name="icol">Inner colour of the gradient.</param>
        /// <param name="ocol">Outer colour of the gradient.</param>
        /// <returns></returns>
        public static Paint BoxGradient(Rectangle <float> box, float r, float f, Colour icol, Colour ocol)
        {
            Matrix3X2 <float> transform = Matrix3X2 <float> .Identity;

            transform.M31 = box.Center.X;
            transform.M32 = box.Center.Y;

            Vector2D <float> extent = box.Size * 0.5f;

            return(new Paint(transform, extent, r, MathF.Max(1.0f, f), icol, ocol, default));
        }
コード例 #16
0
        /// <param name="a">Is specified in radians.</param>
        /// <returns>Rotation matrix.</returns>
        public static Matrix3X2 <float> Rotate(float a)
        {
            float             cs     = MathF.Cos(a);
            float             sn     = MathF.Sin(a);
            Matrix3X2 <float> matrix = Matrix3X2 <float> .Identity;

            matrix.M11 = cs;
            matrix.M12 = sn;
            matrix.M21 = -sn;
            matrix.M22 = cs;
            return(matrix);
        }
コード例 #17
0
        public void Vector2TransformNormal3x2Test()
        {
            Vector2D <float>  v = new Vector2D <float>(1.0f, 2.0f);
            Matrix3X2 <float> m = Matrix3X2.CreateRotation <float>(MathHelper.ToRadians(30.0f));

            m.M31 = 10.0f;
            m.M32 = 20.0f;

            Vector2D <float> expected = new Vector2D <float>(-0.133974612f, 2.232051f);
            Vector2D <float> actual;

            actual = Vector2D.TransformNormal(v, m);
            Assert.True(MathHelper.Equal(expected, actual), "Vector2f.Transform did not return the expected value.");
        }
コード例 #18
0
ファイル: Paint.cs プロジェクト: MatijaBrown/SilkyNvg
        /// <summary>
        /// Creates and returns a radial gradient.
        /// The gradient is transformed by the current transform when it is passed to NvgRenderStyle.FillPaint() or NvgRenderStyle.StrokePaint().
        /// </summary>
        /// <param name="c">The centre.</param>
        /// <param name="inr">Specifies the inner radius of the gradient.</param>
        /// <param name="outr">Specifies the outer radius of the gradient.</param>
        /// <param name="icol">Specifies the start colour.</param>
        /// <param name="ocol">Specifies the end colour.</param>
        /// <returns></returns>
        public static Paint RadialGradient(Vector2D <float> c, float inr, float outr, Colour icol, Colour ocol)
        {
            float r = (inr + outr) * 0.5f;
            float f = (outr - inr);

            Matrix3X2 <float> transform = Matrix3X2 <float> .Identity;

            transform.M31 = c.X;
            transform.M32 = c.Y;

            Vector2D <float> extent = new(r);

            return(new Paint(transform, extent, r, MathF.Max(1.0f, f), icol, ocol, default));
        }
コード例 #19
0
        public static Matrix3X2 <float> Multiply(Matrix3X2 <float> t, Matrix3X2 <float> s)
        {
            float t0 = t.M11 * s.M11 + t.M12 * s.M21;
            float t2 = t.M21 * s.M11 + t.M22 * s.M21;
            float t4 = t.M31 * s.M11 + t.M32 * s.M21 + s.M31;

            t.M12 = t.M11 * s.M12 + t.M12 * s.M22;
            t.M22 = t.M21 * s.M12 + t.M22 * s.M22;
            t.M32 = t.M31 * s.M12 + t.M32 * s.M22 + s.M32;
            t.M11 = t0;
            t.M21 = t2;
            t.M31 = t4;
            return(t);
        }
コード例 #20
0
ファイル: NvgScissoring.cs プロジェクト: MatijaBrown/SilkyNvg
        /// <summary>
        /// Sets the current scissor rectangle.
        /// The scissor rectangle is transformed by the current transform.
        /// </summary>
        public static void Scissor(this Nvg nvg, Rectangle <float> rect)
        {
            Vector2D <float> pos  = rect.Origin;
            Vector2D <float> size = rect.Size;

            size.X = MathF.Max(0.0f, size.X);
            size.Y = MathF.Max(0.0f, size.Y);

            Vector2D <float>  lastRow   = pos + size * 0.5f;
            Matrix3X2 <float> transform = Matrix3X2 <float> .Identity;

            transform.M31 = lastRow.X;
            transform.M32 = lastRow.Y;

            nvg.stateStack.CurrentState.Scissor = new(
                Transforms.NvgTransforms.Multiply(transform, nvg.stateStack.CurrentState.Transform),
                size * 0.5f
                );
        }
コード例 #21
0
        /// <summary>Sets the destination to inverse of specified transform.</summary>
        /// <returns><value>true</value> if the inverse could be calculated, else <value>false</value></returns>
        public static bool Inverse(out Matrix3X2 <float> inv, Matrix3X2 <float> t)
        {
            double det = (double)t.M11 * t.M22 - (double)t.M21 * t.M12;

            if (det > -1e-6 && det < 1e-6)
            {
                inv = Identity;
                return(false);
            }
            inv = default;
            double invdet = 1.0 / det;

            inv.M11 = (float)(t.M22 * invdet);
            inv.M21 = (float)(-t.M21 * invdet);
            inv.M31 = (float)(((double)t.M21 * t.M32 - (double)t.M22 * t.M31) * invdet);
            inv.M12 = (float)(-t.M12 * invdet);
            inv.M22 = (float)(t.M11 * invdet);
            inv.M32 = (float)(((double)t.M12 * t.M31 - (double)t.M11 * t.M32) * invdet);
            return(true);
        }
コード例 #22
0
        /// <summary>
        /// Adds the two matrices together on a per-element basis.
        /// </summary>
        /// <param name="a">First matrix to add.</param>
        /// <param name="b">Second matrix to add.</param>
        /// <param name="result">Sum of the two matrices.</param>
        public static void Add(ref Matrix3X2 a, ref Matrix3X2 b, out Matrix3X2 result)
        {
            float m11 = a.M11 + b.M11;
            float m12 = a.M12 + b.M12;

            float m21 = a.M21 + b.M21;
            float m22 = a.M22 + b.M22;

            float m31 = a.M31 + b.M31;
            float m32 = a.M32 + b.M32;

            result.M11 = m11;
            result.M12 = m12;

            result.M21 = m21;
            result.M22 = m22;

            result.M31 = m31;
            result.M32 = m32;
        }
コード例 #23
0
        /// <summary>
        /// Multiplies the two matrices.
        /// </summary>
        /// <param name="a">First matrix to multiply.</param>
        /// <param name="b">Second matrix to multiply.</param>
        /// <param name="result">Product of the multiplication.</param>
        public static void Multiply(ref Matrix3X3 a, ref Matrix3X2 b, out Matrix3X2 result)
        {
            float resultM11 = a.M11 * b.M11 + a.M12 * b.M21 + a.M13 * b.M31;
            float resultM12 = a.M11 * b.M12 + a.M12 * b.M22 + a.M13 * b.M32;

            float resultM21 = a.M21 * b.M11 + a.M22 * b.M21 + a.M23 * b.M31;
            float resultM22 = a.M21 * b.M12 + a.M22 * b.M22 + a.M23 * b.M32;

            float resultM31 = a.M31 * b.M11 + a.M32 * b.M21 + a.M33 * b.M31;
            float resultM32 = a.M31 * b.M12 + a.M32 * b.M22 + a.M33 * b.M32;

            result.M11 = resultM11;
            result.M12 = resultM12;

            result.M21 = resultM21;
            result.M22 = resultM22;

            result.M31 = resultM31;
            result.M32 = resultM32;
        }
コード例 #24
0
        /// <summary>
        /// Subtracts the two matrices from each other on a per-element basis.
        /// </summary>
        /// <param name="a">First matrix to subtract.</param>
        /// <param name="b">Second matrix to subtract.</param>
        /// <param name="result">Difference of the two matrices.</param>
        public static void Subtract(ref Matrix3X2 a, ref Matrix3X2 b, out Matrix3X2 result)
        {
            float m11 = a.M11 - b.M11;
            float m12 = a.M12 - b.M12;

            float m21 = a.M21 - b.M21;
            float m22 = a.M22 - b.M22;

            float m31 = a.M31 - b.M31;
            float m32 = a.M32 - b.M32;

            result.M11 = m11;
            result.M12 = m12;

            result.M21 = m21;
            result.M22 = m22;

            result.M31 = m31;
            result.M32 = m32;
        }
コード例 #25
0
        /// <summary>
        /// Negates every element in the matrix.
        /// </summary>
        /// <param name="matrix">Matrix to negate.</param>
        /// <param name="result">Negated matrix.</param>
        public static void Negate(ref Matrix3X2 matrix, out Matrix3X2 result)
        {
            float m11 = -matrix.M11;
            float m12 = -matrix.M12;

            float m21 = -matrix.M21;
            float m22 = -matrix.M22;

            float m31 = -matrix.M31;
            float m32 = -matrix.M32;

            result.M11 = m11;
            result.M12 = m12;

            result.M21 = m21;
            result.M22 = m22;

            result.M31 = m31;
            result.M32 = m32;
        }
コード例 #26
0
ファイル: Painter.cs プロジェクト: fealty/Frost
        public void Transform(ref Matrix3X2 transformation)
        {
            Contract.Requires(Thread.CurrentThread == BoundThread);
            Contract.Requires(ActiveTarget != null);

            Matrix3X2 result;

            transformation.Multiply(ref _ActiveTransformation, out result);

            if(_IsTransformationInvalid || !result.Equals(_ActiveTransformation))
            {
                _ActiveTransformation = result;

                _IsTransformationInvalid = true;
            }
        }
コード例 #27
0
        public FragUniforms(Paint paint, Scissor scissor, float width, float fringe, float strokeThr, VulkanRenderer renderer)
        {
            Matrix3X2 <float> invtransform;

            _innerCol = paint.InnerColour.Premult();
            _outerCol = paint.OuterColour.Premult();

            if (scissor.Extent.X < -0.5f || scissor.Extent.Y < -0.5f)
            {
                _scissorMat   = new Matrix3X4 <float>();
                _scissorExt   = new Vector2D <float>(1.0f);
                _scissorScale = new Vector2D <float>(1.0f);
            }
            else
            {
                _             = Matrix3X2.Invert(scissor.Transform, out invtransform);
                _scissorMat   = new Matrix3X4 <float>(invtransform);
                _scissorExt   = scissor.Extent;
                _scissorScale = new Vector2D <float>(
                    MathF.Sqrt(scissor.Transform.M11 * scissor.Transform.M11 + scissor.Transform.M21 * scissor.Transform.M21) / fringe,
                    MathF.Sqrt(scissor.Transform.M21 * scissor.Transform.M21 + scissor.Transform.M22 * scissor.Transform.M22) / fringe
                    );
            }

            _extent     = paint.Extent;
            _strokeMult = (width * 0.5f + fringe * 0.5f) / fringe;
            _strokeThr  = strokeThr;

            if (paint.Image != 0)
            {
                ref var tex = ref renderer.TextureManager.FindTexture(paint.Image);
                if (tex.Id == 0)
                {
                    _type    = (int)ShaderType.Fillgrad;
                    _radius  = paint.Radius;
                    _feather = paint.Feather;
                    _texType = 0;

                    _ = Matrix3X2.Invert(paint.Transform, out invtransform);
                }
                else
                {
                    if (tex.HasFlag(ImageFlags.FlipY))
                    {
                        Matrix3X2 <float> m1, m2;
                        m1 = Matrix3X2.CreateTranslation(new Vector2D <float>(0.0f, _extent.Y * 0.5f));
                        m1 = Transforms.NvgTransforms.Multiply(m1, paint.Transform);
                        m2 = Matrix3X2.CreateScale(new Vector2D <float>(1.0f, -1.0f));
                        m2 = Transforms.NvgTransforms.Multiply(m2, m1);
                        m1 = Matrix3X2.CreateTranslation(new Vector2D <float>(0.0f, -_extent.Y * 0.5f));
                        m1 = Transforms.NvgTransforms.Multiply(m1, m2);
                        _  = Matrix3X2.Invert(m1, out invtransform);
                    }
                    else
                    {
                        _ = Matrix3X2.Invert(paint.Transform, out invtransform);
                    }
                    _type = (int)ShaderType.FillImg;

                    if (tex.TextureType == Texture.Rgba)
                    {
                        _texType = tex.HasFlag(ImageFlags.Premultiplied) ? 0 : 1;
                    }
                    else
                    {
                        _texType = 2;
                    }

                    _radius = _feather = 0.0f;
                }
            }
コード例 #28
0
ファイル: Painter.cs プロジェクト: fealty/Frost
        public void Scale(float width, float height, float originX, float originY)
        {
            Contract.Requires(Thread.CurrentThread == BoundThread);
            Contract.Requires(ActiveTarget != null);
            Contract.Requires(Check.IsPositive(width));
            Contract.Requires(Check.IsPositive(height));
            Contract.Requires(Check.IsFinite(originX));
            Contract.Requires(Check.IsFinite(originY));

            Matrix3X2 result;

            _ActiveTransformation.Scale(width, height, originX, originY, out result);

            if(_IsTransformationInvalid || !result.Equals(_ActiveTransformation))
            {
                _ActiveTransformation = result;

                _IsTransformationInvalid = true;
            }
        }
コード例 #29
0
ファイル: Painter.cs プロジェクト: fealty/Frost
        public void Rotate(float angle, float originX, float originY)
        {
            Contract.Requires(Thread.CurrentThread == BoundThread);
            Contract.Requires(ActiveTarget != null);
            Contract.Requires(Check.IsDegrees(angle));
            Contract.Requires(Check.IsFinite(originX));
            Contract.Requires(Check.IsFinite(originY));

            Matrix3X2 result;

            _ActiveTransformation.Rotate(angle, originX, originY, out result);

            if(_IsTransformationInvalid || !result.Equals(_ActiveTransformation))
            {
                _ActiveTransformation = result;

                _IsTransformationInvalid = true;
            }
        }
コード例 #30
0
ファイル: Painter.cs プロジェクト: fealty/Frost
        public void Skew(float angleX, float angleY)
        {
            Contract.Requires(Thread.CurrentThread == BoundThread);
            Contract.Requires(ActiveTarget != null);
            Contract.Requires(Check.IsDegrees(angleX));
            Contract.Requires(Check.IsDegrees(angleY));

            Matrix3X2 result;

            _ActiveTransformation.Skew(angleX, angleY, out result);

            if(_IsTransformationInvalid || !result.Equals(_ActiveTransformation))
            {
                _ActiveTransformation = result;

                _IsTransformationInvalid = true;
            }
        }
コード例 #31
0
        /// <summary>
        /// Scales current coordinate system.
        /// </summary>
        public static void Scale(this Nvg nvg, Vector2D <float> scale)
        {
            Matrix3X2 <float> t = nvg.TransformScale(scale);

            nvg.stateStack.CurrentState.Transform = nvg.TransformPremultiply(nvg.stateStack.CurrentState.Transform, t);
        }
コード例 #32
0
        /// <summary>
        /// Skews the current coordinate system along Y axis.
        /// </summary>
        /// <param name="angle">Is specified in radians.</param>
        public static void SkewY(this Nvg nvg, float angle)
        {
            Matrix3X2 <float> t = nvg.TransformSkewY(angle);

            nvg.stateStack.CurrentState.Transform = nvg.TransformPremultiply(nvg.stateStack.CurrentState.Transform, t);
        }
コード例 #33
0
        /// <summary>
        /// Translates current coordinate system.
        /// </summary>
        public static void Translate(this Nvg nvg, Vector2D <float> position)
        {
            Matrix3X2 <float> t = nvg.TransformTranslate(position);

            nvg.stateStack.CurrentState.Transform = nvg.TransformPremultiply(nvg.stateStack.CurrentState.Transform, t);
        }
コード例 #34
0
 /// <summary>
 /// Premultiplies currentn coordinate system by specified matrix.
 /// For matrix layout <see cref="NvgTransforms"/>
 /// </summary>
 public static void Transform(this Nvg nvg, Matrix3X2 <float> transform)
 {
     nvg.stateStack.CurrentState.Transform = nvg.TransformPremultiply(nvg.stateStack.CurrentState.Transform, transform);
 }