1 module skia.SKRoundRect;
2 
3 import skia.Definitions;
4 import skia.MathTypes;
5 import skia.SKObject;
6 import skia.SkiaApi;
7 import skia.SKMatrix;
8 import skia.Exceptions;
9 import skia.Util;
10 
11 class SKRoundRect : SKObject, ISKSkipObjectRegistration {
12 	this(void* handle, bool owns) {
13 		super(handle, owns);
14 	}
15 
16 	this() {
17 		this(SkiaApi.sk_rrect_new(), true);
18 		if (Handle is null) {
19 			throw new InvalidOperationException("Unable to create a new SKRoundRect instance.");
20 		}
21 		SetEmpty();
22 	}
23 
24 	this(SKRect rect) {
25 		this(SkiaApi.sk_rrect_new(), true);
26 		if (Handle is null) {
27 			throw new InvalidOperationException("Unable to create a new SKRoundRect instance.");
28 		}
29 		SetRect(rect);
30 	}
31 
32 	this(SKRect rect, float radius) {
33 		this(rect, radius, radius);
34 	}
35 
36 	this(SKRect rect, float xRadius, float yRadius) {
37 		this(SkiaApi.sk_rrect_new(), true);
38 		if (Handle is null) {
39 			throw new InvalidOperationException("Unable to create a new SKRoundRect instance.");
40 		}
41 		SetRect(rect, xRadius, yRadius);
42 	}
43 
44 	this(SKRoundRect rrect) {
45 		this(SkiaApi.sk_rrect_new_copy(cast(sk_rrect_t*) rrect.Handle), true);
46 	}
47 
48 	// 	protected override void Dispose (bool disposing)
49 	//   {
50 	//     return super.Dispose (disposing);
51 	//   }
52 
53 	protected override void DisposeNative() {
54 		return SkiaApi.sk_rrect_delete(cast(sk_rrect_t*) Handle);
55 	}
56 
57 	SKRect Rect() {
58 
59 		SKRect rect;
60 		SkiaApi.sk_rrect_get_rect(cast(sk_rrect_t*) Handle, &rect);
61 		return rect;
62 	}
63 
64 	// SKPoint[] Radii()
65 	// {
66 	//   return new[] {
67 	// 	GetRadii(SKRoundRectCorner.UpperLeft),
68 	// 	GetRadii(SKRoundRectCorner.UpperRight),
69 	// 	GetRadii(SKRoundRectCorner.LowerRight),
70 	// 	GetRadii(SKRoundRectCorner.LowerLeft),
71 	// };
72 	// } 
73 
74 	SKRoundRectType Type() {
75 		return SkiaApi.sk_rrect_get_type(cast(sk_rrect_t*) Handle);
76 	}
77 
78 	float Width() {
79 		return SkiaApi.sk_rrect_get_width(cast(sk_rrect_t*) Handle);
80 	}
81 
82 	float Height() {
83 		return SkiaApi.sk_rrect_get_height(cast(sk_rrect_t*) Handle);
84 	}
85 
86 	bool IsValid() {
87 		return SkiaApi.sk_rrect_is_valid(cast(sk_rrect_t*) Handle);
88 	}
89 
90 	bool AllCornersCircular() {
91 		return CheckAllCornersCircular(Utils.NearlyZero);
92 	}
93 
94 	bool CheckAllCornersCircular(float tolerance) {
95 		auto ul = GetRadii(SKRoundRectCorner.UpperLeft);
96 		auto ur = GetRadii(SKRoundRectCorner.UpperRight);
97 		auto lr = GetRadii(SKRoundRectCorner.LowerRight);
98 		auto ll = GetRadii(SKRoundRectCorner.LowerLeft);
99 
100 		return Utils.NearlyEqual(ul.X, ul.Y, tolerance)
101 			&& Utils.NearlyEqual(ur.X, ur.Y, tolerance)
102 			&& Utils.NearlyEqual(lr.X, lr.Y, tolerance) && Utils.NearlyEqual(ll.X, ll.Y, tolerance);
103 	}
104 
105 	void SetEmpty() {
106 		SkiaApi.sk_rrect_set_empty(cast(sk_rrect_t*) Handle);
107 	}
108 
109 	void SetRect(SKRect rect) {
110 		SkiaApi.sk_rrect_set_rect(cast(sk_rrect_t*) Handle, &rect);
111 	}
112 
113 	void SetRect(SKRect rect, float xRadius, float yRadius) {
114 		SkiaApi.sk_rrect_set_rect_xy(cast(sk_rrect_t*) Handle, &rect, xRadius, yRadius);
115 	}
116 
117 	void SetOval(SKRect rect) {
118 		SkiaApi.sk_rrect_set_oval(cast(sk_rrect_t*) Handle, &rect);
119 	}
120 
121 	void SetNinePatch(SKRect rect, float leftRadius, float topRadius,
122 			float rightRadius, float bottomRadius) {
123 		SkiaApi.sk_rrect_set_nine_patch(cast(sk_rrect_t*) Handle, &rect,
124 				leftRadius, topRadius, rightRadius, bottomRadius);
125 	}
126 
127 	void SetRectRadii(SKRect rect, SKPoint[] radii) {
128 		if (radii is null)
129 			throw new ArgumentNullException(radii.stringof);
130 		if (radii.length != 4)
131 			throw new ArgumentException("Radii must have a length of 4.", radii.stringof);
132 
133 		SKPoint* r = radii.ptr;
134 		SkiaApi.sk_rrect_set_rect_radii(cast(sk_rrect_t*) Handle, &rect, r);
135 	}
136 
137 	bool Contains(SKRect rect) {
138 		return SkiaApi.sk_rrect_contains(cast(sk_rrect_t*) Handle, &rect);
139 	}
140 
141 	SKPoint GetRadii(SKRoundRectCorner corner) {
142 		SKPoint radii;
143 		SkiaApi.sk_rrect_get_radii(cast(sk_rrect_t*) Handle, corner, &radii);
144 		return radii;
145 	}
146 
147 	void Deflate(SKSize size) {
148 		Deflate(size.Width, size.Height);
149 	}
150 
151 	void Deflate(float dx, float dy) {
152 		SkiaApi.sk_rrect_inset(cast(sk_rrect_t*) Handle, dx, dy);
153 	}
154 
155 	void Inflate(SKSize size) {
156 		Inflate(size.Width, size.Height);
157 	}
158 
159 	void Inflate(float dx, float dy) {
160 		SkiaApi.sk_rrect_outset(cast(sk_rrect_t*) Handle, dx, dy);
161 	}
162 
163 	void Offset(SKPoint pos) {
164 		Offset(pos.X, pos.Y);
165 	}
166 
167 	void Offset(float dx, float dy) {
168 		SkiaApi.sk_rrect_offset(cast(sk_rrect_t*) Handle, dx, dy);
169 	}
170 
171 	bool TryTransform(SKMatrix matrix, out SKRoundRect transformed) {
172 		auto destHandle = SkiaApi.sk_rrect_new();
173 		if (SkiaApi.sk_rrect_transform(cast(sk_rrect_t*) Handle, &matrix, destHandle)) {
174 			transformed = new SKRoundRect(destHandle, true);
175 			return true;
176 		}
177 		SkiaApi.sk_rrect_delete(destHandle);
178 		transformed = null;
179 		return false;
180 	}
181 
182 	SKRoundRect Transform(SKMatrix matrix) {
183 		SKRoundRect transformed;
184 		if (TryTransform(matrix, transformed)) {
185 			return transformed;
186 		}
187 		return null;
188 	}
189 }