Added bindings for SKRoundRect

This commit is contained in:
Matthew Leibowitz 2018-05-29 03:43:29 +02:00
Родитель 7ace45c131
Коммит ff838ceccb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 3650EBE4AA155AF9
10 изменённых файлов: 556 добавлений и 5 удалений

Просмотреть файл

@ -2468,4 +2468,20 @@ namespace SkiaSharp
set { fUnpremulBehavior = value; }
}
}
public enum SKRoundRectType {
Empty,
Rect,
Oval,
Simple,
NinePatch,
Complex,
}
public enum SKRoundRectCorner {
UpperLeft,
UpperRight,
LowerRight,
LowerLeft,
}
}

Просмотреть файл

@ -188,6 +188,14 @@ namespace SkiaSharp
SkiaApi.sk_canvas_clip_rect_with_operation (Handle, ref rect, operation, antialias);
}
public void ClipRoundRect (SKRoundRect rect, SKClipOperation operation = SKClipOperation.Intersect, bool antialias = false)
{
if (rect == null)
throw new ArgumentNullException (nameof (rect));
SkiaApi.sk_canvas_clip_rrect_with_operation (Handle, rect.Handle, operation, antialias);
}
public void ClipPath (SKPath path, SKClipOperation operation = SKClipOperation.Intersect, bool antialias = false)
{
if (path == null)
@ -258,6 +266,15 @@ namespace SkiaSharp
SkiaApi.sk_canvas_draw_rect (Handle, ref rect, paint.Handle);
}
public void DrawRoundRect (SKRoundRect rect, SKPaint paint)
{
if (rect == null)
throw new ArgumentNullException (nameof (rect));
if (paint == null)
throw new ArgumentNullException (nameof (paint));
SkiaApi.sk_canvas_draw_rrect (Handle, rect.Handle, paint.Handle);
}
public void DrawRoundRect (float x, float y, float w, float h, float rx, float ry, SKPaint paint)
{
DrawRoundRect (SKRect.Create (x, y, w, h), rx, ry, paint);

Просмотреть файл

@ -341,6 +341,20 @@ namespace SkiaSharp
SkiaApi.sk_path_add_rect_start (Handle, ref rect, direction, startIndex);
}
public void AddRoundRect (SKRoundRect rect, SKPathDirection direction = SKPathDirection.Clockwise)
{
if (rect == null)
throw new ArgumentNullException (nameof (rect));
SkiaApi.sk_path_add_rrect (Handle, rect.Handle, direction);
}
public void AddRoundRect (SKRoundRect rect, SKPathDirection direction, uint startIndex)
{
if (rect == null)
throw new ArgumentNullException (nameof (rect));
SkiaApi.sk_path_add_rrect_start (Handle, rect.Handle, direction, startIndex);
}
public void AddOval (SKRect rect, SKPathDirection direction = SKPathDirection.Clockwise)
{
SkiaApi.sk_path_add_oval (Handle, ref rect, direction);
@ -400,11 +414,17 @@ namespace SkiaSharp
SkiaApi.sk_path_add_path_reverse (Handle, other.Handle);
}
public void AddRoundedRect (SKRect rect, float rx, float ry, SKPathDirection dir = SKPathDirection.Clockwise)
public void AddRoundRect (SKRect rect, float rx, float ry, SKPathDirection dir = SKPathDirection.Clockwise)
{
SkiaApi.sk_path_add_rounded_rect (Handle, ref rect, rx, ry, dir);
}
[Obsolete ("Use AddRoundRect instead.")]
public void AddRoundedRect (SKRect rect, float rx, float ry, SKPathDirection dir = SKPathDirection.Clockwise)
{
AddRoundRect (rect, rx, ry, dir);
}
public void AddCircle (float x, float y, float radius, SKPathDirection dir = SKPathDirection.Clockwise)
{
SkiaApi.sk_path_add_circle (Handle, x, y, radius, dir);

Просмотреть файл

@ -0,0 +1,170 @@
//
// Bindings for SKRoundRect
//
// Author:
// Matthew Leibowitz
//
// Copyright 2018 Xamarin Inc
//
using System;
namespace SkiaSharp
{
public class SKRoundRect : SKObject
{
[Preserve]
internal SKRoundRect (IntPtr handle, bool owns)
: base (handle, owns)
{
}
public SKRoundRect ()
: this (SkiaApi.sk_rrect_new (), true)
{
if (Handle == IntPtr.Zero) {
throw new InvalidOperationException ("Unable to create a new SKRoundRect instance.");
}
SetEmpty ();
}
public SKRoundRect (SKRect rect)
: this (SkiaApi.sk_rrect_new (), true)
{
if (Handle == IntPtr.Zero) {
throw new InvalidOperationException ("Unable to create a new SKRoundRect instance.");
}
SetRect (rect);
}
public SKRoundRect (SKRect rect, float xRadius, float yRadius)
: this (SkiaApi.sk_rrect_new (), true)
{
if (Handle == IntPtr.Zero) {
throw new InvalidOperationException ("Unable to create a new SKRoundRect instance.");
}
SetRect (rect, xRadius, yRadius);
}
public SKRoundRect (SKRoundRect rrect)
: this (SkiaApi.sk_rrect_new_copy (rrect.Handle), true)
{
}
protected override void Dispose (bool disposing)
{
if (Handle != IntPtr.Zero && OwnsHandle) {
SkiaApi.sk_rrect_delete (Handle);
}
base.Dispose (disposing);
}
public SKRect Rect {
get {
SkiaApi.sk_rrect_get_rect (Handle, out var rect);
return rect;
}
}
public SKRoundRectType Type => SkiaApi.sk_rrect_get_type (Handle);
public float Width => SkiaApi.sk_rrect_get_width (Handle);
public float Height => SkiaApi.sk_rrect_get_height (Handle);
public bool IsValid => SkiaApi.sk_rrect_is_valid (Handle);
public bool AllCornersCircular => CheckAllCornersCircular (Utils.NearlyZero);
public bool CheckAllCornersCircular (float tolerance)
{
return SkiaApi.sk_rrect_all_corners_circular (Handle, tolerance);
}
public void SetEmpty ()
{
SkiaApi.sk_rrect_set_empty (Handle);
}
public void SetRect (SKRect rect)
{
SkiaApi.sk_rrect_set_rect (Handle, ref rect);
}
public void SetRect (SKRect rect, float xRadius, float yRadius)
{
SkiaApi.sk_rrect_set_rect_xy (Handle, ref rect, xRadius, yRadius);
}
public void SetOval (SKRect rect)
{
SkiaApi.sk_rrect_set_oval (Handle, ref rect);
}
public void SetNinePatch (SKRect rect, float leftRadius, float topRadius, float rightRadius, float bottomRadius)
{
SkiaApi.sk_rrect_set_nine_patch (Handle, ref rect, leftRadius, topRadius, rightRadius, bottomRadius);
}
public void SetRectRadii (SKRect rect, SKPoint[] radii)
{
if (radii == null)
throw new ArgumentNullException (nameof (radii));
if (radii.Length != 4)
throw new ArgumentException ("Radii must have a length of 4.", nameof (radii));
SkiaApi.sk_rrect_set_rect_radii (Handle, ref rect, radii);
}
public bool Contains (SKRect rect)
{
return SkiaApi.sk_rrect_contains (Handle, ref rect);
}
public SKPoint GetRadii (SKRoundRectCorner corner)
{
SkiaApi.sk_rrect_get_radii (Handle, corner, out var radii);
return radii;
}
public void Deflate (SKSize size)
{
Deflate (size.Width, size.Height);
}
public void Deflate (float dx, float dy)
{
SkiaApi.sk_rrect_inset (Handle, dx, dy);
}
public void Inflate (SKSize size)
{
Inflate (size.Width, size.Height);
}
public void Inflate (float dx, float dy)
{
SkiaApi.sk_rrect_outset (Handle, dx, dy);
}
public void Offset (SKPoint pos)
{
Offset (pos.X, pos.Y);
}
public void Offset (float dx, float dy)
{
SkiaApi.sk_rrect_offset (Handle, dx, dy);
}
public SKRoundRect Transform (SKMatrix matrix)
{
var destHandle = SkiaApi.sk_rrect_new ();
if (SkiaApi.sk_rrect_transform (Handle, ref matrix, destHandle)) {
return new SKRoundRect (destHandle, true);
}
return null;
}
}
}

Просмотреть файл

@ -64,6 +64,7 @@ using sk_matrix44_t = System.IntPtr;
using sk_color_t = System.UInt32;
using sk_pmcolor_t = System.UInt32;
using sk_vertices_t = System.IntPtr;
using sk_rrect_t = System.IntPtr;
namespace SkiaSharp
{
@ -235,6 +236,8 @@ namespace SkiaSharp
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_canvas_draw_rect(sk_canvas_t t, ref SKRect rect, sk_paint_t paint);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_canvas_draw_rrect(sk_canvas_t t, sk_rrect_t rect, sk_paint_t paint);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_canvas_draw_round_rect (sk_canvas_t t, ref SKRect rect, float rx, float ry, sk_paint_t paint);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_canvas_draw_oval(sk_canvas_t t, ref SKRect rect, sk_paint_t paint);
@ -295,7 +298,8 @@ namespace SkiaSharp
public extern static void sk_canvas_draw_named_destination_annotation(sk_canvas_t t, ref SKPoint point, sk_data_t value);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_canvas_draw_link_destination_annotation(sk_canvas_t t, ref SKRect rect, sk_data_t value);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_canvas_clip_rrect_with_operation(sk_canvas_t t, sk_rrect_t crect, SKClipOperation op, [MarshalAs(UnmanagedType.I1)] bool doAA);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_canvas_clip_rect_with_operation(sk_canvas_t t, ref SKRect crect, SKClipOperation op, [MarshalAs(UnmanagedType.I1)] bool doAA);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
@ -636,6 +640,10 @@ namespace SkiaSharp
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_path_add_rect_start(sk_path_t t, ref SKRect rect, SKPathDirection direction, uint startIndex);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_path_add_rrect(sk_path_t t, sk_rrect_t rect, SKPathDirection direction);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_path_add_rrect_start(sk_path_t t, sk_rrect_t rect, SKPathDirection direction, uint startIndex);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_path_add_oval(sk_path_t t, ref SKRect rect, SKPathDirection direction);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_path_add_arc(sk_path_t t, ref SKRect rect, float startAngle, float sweepAngle);
@ -1724,5 +1732,53 @@ namespace SkiaSharp
public extern static void sk_vertices_unref(sk_vertices_t cvertices);
[DllImport(SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static sk_vertices_t sk_vertices_make_copy(SKVertexMode vmode, int vertexCount, [In] SKPoint[] positions, [In] SKPoint[] texs, [In] SKColor[] colors, int indexCount, [In] UInt16[] indices);
// RRect
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static sk_rrect_t sk_rrect_new ();
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static sk_rrect_t sk_rrect_new_copy (sk_rrect_t rrect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_delete (sk_rrect_t rrect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static SKRoundRectType sk_rrect_get_type (sk_rrect_t rrect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_get_rect (sk_rrect_t rrect, out SKRect rect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_get_radii (sk_rrect_t rrect, SKRoundRectCorner corner, [Out] out SKPoint radii);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs (UnmanagedType.I1)]
public extern static bool sk_rrect_all_corners_circular (sk_rrect_t rrect, float tolerance);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static float sk_rrect_get_width (sk_rrect_t rrect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static float sk_rrect_get_height (sk_rrect_t rrect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_set_empty (sk_rrect_t rrect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_set_rect (sk_rrect_t rrect, [In] ref SKRect rect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_set_oval (sk_rrect_t rrect, [In] ref SKRect rect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_set_rect_xy (sk_rrect_t rrect, [In] ref SKRect rect, float xRad, float yRad);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_set_nine_patch (sk_rrect_t rrect, [In] ref SKRect rect, float leftRad, float topRad, float rightRad, float bottomRad);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_set_rect_radii (sk_rrect_t rrect, [In] ref SKRect rect, [In] SKPoint[] radii);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_inset (sk_rrect_t rrect, float dx, float dy);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_outset (sk_rrect_t rrect, float dx, float dy);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
public extern static void sk_rrect_offset (sk_rrect_t rrect, float dx, float dy);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs (UnmanagedType.I1)]
public extern static bool sk_rrect_contains (sk_rrect_t rrect, [In] ref SKRect rect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs (UnmanagedType.I1)]
public extern static bool sk_rrect_is_valid (sk_rrect_t rrect);
[DllImport (SKIA, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs (UnmanagedType.I1)]
public extern static bool sk_rrect_transform (sk_rrect_t rrect, [In] ref SKMatrix matrix, sk_rrect_t dest);
}
}

Просмотреть файл

@ -5,6 +5,11 @@ using System.Text;
namespace SkiaSharp
{
public static class Utils
{
internal const float NearlyZero = (1.0f / (1 << 12));
}
public static class StringUtilities
{
private static int GetUnicodeStringLength(SKTextEncoding encoding)
@ -75,4 +80,4 @@ namespace SkiaSharp
}
}
}
}
}

2
externals/skia поставляемый

@ -1 +1 @@
Subproject commit 5c4c24d136a63126308997ef999da4e991ecc001
Subproject commit ae78530211be44f493765603404fa0b9dd009eae

Просмотреть файл

@ -30,6 +30,25 @@ namespace SkiaSharp.Tests
}
}
[SkippableFact]
public void CanvasCanClipRoundRect()
{
using (var canvas = new SKNWayCanvas(100, 100))
{
canvas.ClipRoundRect(new SKRoundRect(new SKRect(10, 10, 50, 50), 5, 5));
}
}
[SkippableFact]
public void CanvasCanDrawRoundRect()
{
using (var canvas = new SKNWayCanvas(100, 100))
using (var paint = new SKPaint())
{
canvas.DrawRoundRect(new SKRoundRect(new SKRect(10, 10, 50, 50), 5, 5), paint);
}
}
[SkippableFact]
public void NWayCanvasCanBeConstructed()
{

Просмотреть файл

@ -81,6 +81,18 @@ namespace SkiaSharp.Tests
}
}
[SkippableFact]
public void PathContainsPointInRoundRect()
{
using (var path = new SKPath ()) {
var rrect = new SKRoundRect(SKRect.Create(10, 10, 100, 100), 5, 5);
path.AddRoundRect (rrect);
Assert.True (path.Contains (30, 30));
Assert.False (path.Contains (5, 30));
}
}
[SkippableFact]
public void GetLastPoint()
{
@ -183,7 +195,7 @@ namespace SkiaSharp.Tests
p.AddOval (r);
TestToFromSvgPath (p);
p.AddRoundedRect (r, 4, 4.5f);
p.AddRoundRect (r, 4, 4.5f);
TestToFromSvgPath (p);
}
}

Просмотреть файл

@ -0,0 +1,236 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace SkiaSharp.Tests
{
public class SKRoundRectTest : SKTest
{
[SkippableFact]
public void CanConstructEmpty()
{
var rrect = new SKRoundRect();
Assert.NotNull(rrect);
Assert.True(rrect.IsValid);
Assert.Equal(SKRoundRectType.Empty, rrect.Type);
Assert.Equal(0f, rrect.Width);
Assert.Equal(0f, rrect.Height);
Assert.Equal(SKRect.Empty, rrect.Rect);
}
[SkippableFact]
public void CanConstructRect()
{
var rect = SKRect.Create(10, 10, 100, 100);
var rrect = new SKRoundRect(rect);
Assert.NotNull(rrect);
Assert.True(rrect.IsValid);
Assert.Equal(SKRoundRectType.Rect, rrect.Type);
Assert.Equal(100f, rrect.Width);
Assert.Equal(100f, rrect.Height);
Assert.Equal(rect, rrect.Rect);
}
[SkippableFact]
public void CanConstructOval()
{
var rect = SKRect.Create(10, 10, 100, 100);
var rrect = new SKRoundRect();
rrect.SetOval(rect);
Assert.NotNull(rrect);
Assert.True(rrect.IsValid);
Assert.Equal(SKRoundRectType.Oval, rrect.Type);
Assert.Equal(100f, rrect.Width);
Assert.Equal(100f, rrect.Height);
Assert.Equal(rect, rrect.Rect);
}
[SkippableFact]
public void CanConstructSimple()
{
var rect = SKRect.Create(10, 10, 100, 100);
var rrect = new SKRoundRect(rect, 5, 5);
Assert.NotNull(rrect);
Assert.True(rrect.IsValid);
Assert.Equal(SKRoundRectType.Simple, rrect.Type);
Assert.Equal(100f, rrect.Width);
Assert.Equal(100f, rrect.Height);
Assert.Equal(rect, rrect.Rect);
}
[SkippableFact]
public void CanConstructNinePatch()
{
var rect = SKRect.Create(10, 10, 100, 100);
var rrect = new SKRoundRect();
rrect.SetNinePatch(rect, 5, 10, 5, 5);
Assert.NotNull(rrect);
Assert.True(rrect.IsValid);
Assert.Equal(SKRoundRectType.NinePatch, rrect.Type);
Assert.Equal(100f, rrect.Width);
Assert.Equal(100f, rrect.Height);
Assert.Equal(rect, rrect.Rect);
}
[SkippableFact]
public void CanNotConstructRectWithInvalidRadii()
{
var rect = SKRect.Create(10, 10, 100, 100);
var radii = new[]
{
new SKPoint(1, 2),
new SKPoint(3, 4)
};
var rrect = new SKRoundRect();
Assert.Throws<ArgumentException>(() => rrect.SetRectRadii(rect, radii));
}
[SkippableFact]
public void CanConstructRectWithRadii()
{
var rect = SKRect.Create(10, 10, 100, 100);
var radii = new[]
{
new SKPoint(1, 2),
new SKPoint(3, 4),
new SKPoint(5, 6),
new SKPoint(7, 8)
};
var rrect = new SKRoundRect();
rrect.SetRectRadii(rect, radii);
Assert.NotNull(rrect);
Assert.True(rrect.IsValid);
Assert.Equal(SKRoundRectType.Complex, rrect.Type);
Assert.Equal(100f, rrect.Width);
Assert.Equal(100f, rrect.Height);
Assert.Equal(rect, rrect.Rect);
Assert.Equal(radii[0], rrect.GetRadii(SKRoundRectCorner.UpperLeft));
Assert.Equal(radii[1], rrect.GetRadii(SKRoundRectCorner.UpperRight));
Assert.Equal(radii[2], rrect.GetRadii(SKRoundRectCorner.LowerRight));
Assert.Equal(radii[3], rrect.GetRadii(SKRoundRectCorner.LowerLeft));
}
[SkippableFact]
public void CanCopy()
{
var rect = SKRect.Create(10, 10, 100, 100);
var original = new SKRoundRect(rect, 5, 5);
var rrect = new SKRoundRect(original);
Assert.NotNull(rrect);
Assert.True(rrect.IsValid);
Assert.Equal(SKRoundRectType.Simple, rrect.Type);
Assert.Equal(100f, rrect.Width);
Assert.Equal(100f, rrect.Height);
Assert.Equal(rect, rrect.Rect);
}
[SkippableFact]
public void ContainsRect()
{
var rect = SKRect.Create(10, 10, 100, 100);
var rrect = new SKRoundRect(rect, 5, 5);
var contains = rrect.Contains(SKRect.Create(20, 20, 20, 20));
Assert.True(contains);
}
[SkippableFact]
public void CanGetRadii()
{
var rect = SKRect.Create(10, 10, 100, 100);
var rrect = new SKRoundRect(rect, 5, 7);
Assert.Equal(new SKPoint(5, 7), rrect.GetRadii(SKRoundRectCorner.UpperLeft));
Assert.Equal(new SKPoint(5, 7), rrect.GetRadii(SKRoundRectCorner.UpperRight));
Assert.Equal(new SKPoint(5, 7), rrect.GetRadii(SKRoundRectCorner.LowerRight));
Assert.Equal(new SKPoint(5, 7), rrect.GetRadii(SKRoundRectCorner.LowerLeft));
}
[SkippableFact]
public void CheckAllCornersCircular()
{
var rect = SKRect.Create(10, 10, 100, 100);
var rrect = new SKRoundRect(rect, 5, 5);
Assert.True(rrect.AllCornersCircular);
}
[SkippableFact]
public void CheckAllCornersCircularWithTolerance()
{
var rect = SKRect.Create(10, 10, 100, 100);
var rrect = new SKRoundRect(rect, 5, 7);
Assert.False(rrect.AllCornersCircular);
Assert.True(rrect.CheckAllCornersCircular(2f));
}
[SkippableFact]
public void CanInflate()
{
var rect = SKRect.Create(10, 10, 100, 100);
var inflated = SKRect.Inflate(rect, 2, 2);
var rrect = new SKRoundRect(rect, 5, 5);
rrect.Inflate(2, 2);
Assert.Equal(inflated, rrect.Rect);
}
[SkippableFact]
public void CanOffset()
{
var rect = SKRect.Create(10, 10, 100, 100);
var offset = rect;
offset.Offset(2, 2);
var rrect = new SKRoundRect(rect, 5, 5);
rrect.Offset(2, 2);
Assert.Equal(offset, rrect.Rect);
}
[SkippableFact]
public void CanTransform()
{
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.MakeTranslation(2, 2));
Assert.Equal(offset, transformed.Rect);
}
}
}