1 module skia.SKRegion;
2 
3 import skia.Definitions;
4 import skia.SKObject;
5 import skia.SkiaApi;
6 import skia.SKPath;
7 import skia.MathTypes;
8 import skia.Exceptions;
9 
10 class SKRegion : SKObject, ISKSkipObjectRegistration {
11 	this(void* handle, bool owns) {
12 		super(handle, owns);
13 	}
14 
15 	this() {
16 		this(SkiaApi.sk_region_new(), true);
17 	}
18 
19 	this(SKRegion region) {
20 		this();
21 		SetRegion(region);
22 	}
23 
24 	this(SKRectI rect) {
25 		this();
26 		SetRect(rect);
27 	}
28 
29 	this(SKPath path) {
30 		this();
31 		SetPath(path);
32 	}
33 
34 	// 	protected override void Dispose (bool disposing)	
35 	//   {
36 	// 		return super.Dispose (disposing);
37 	// 	}
38 
39 	protected override void DisposeNative() {
40 		return SkiaApi.sk_region_delete(cast(sk_region_t*) Handle);
41 	}
42 
43 	// properties
44 
45 	bool IsEmpty() {
46 		return SkiaApi.sk_region_is_empty(cast(sk_region_t*) Handle);
47 	}
48 
49 	bool IsRect() {
50 		return SkiaApi.sk_region_is_rect(cast(sk_region_t*) Handle);
51 	}
52 
53 	bool IsComplex() {
54 		return SkiaApi.sk_region_is_complex(cast(sk_region_t*) Handle);
55 	}
56 
57 	SKRectI Bounds() {
58 
59 		SKRectI rect;
60 		SkiaApi.sk_region_get_bounds(cast(sk_region_t*) Handle, &rect);
61 		return rect;
62 
63 	}
64 
65 	// GetBoundaryPath
66 
67 	SKPath GetBoundaryPath() {
68 		auto path = new SKPath();
69 		if (!SkiaApi.sk_region_get_boundary_path(cast(sk_region_t*) Handle,
70 				cast(sk_path_t*) path.Handle)) {
71 			path.Dispose();
72 			path = null;
73 		}
74 		return path;
75 	}
76 
77 	// Contains
78 
79 	bool Contains(SKPath path) {
80 		if (path is null)
81 			throw new ArgumentNullException(path.stringof);
82 
83 		auto pathRegion = new SKRegion(path);
84 		scope (exit) {
85 			pathRegion.Dispose();
86 		}
87 
88 		return Contains(pathRegion);
89 	}
90 
91 	bool Contains(SKRegion src) {
92 		if (src is null)
93 			throw new ArgumentNullException(src.stringof);
94 
95 		return SkiaApi.sk_region_contains(cast(sk_region_t*) Handle, cast(sk_region_t*) src.Handle);
96 	}
97 
98 	bool Contains(SKPointI xy) {
99 		return SkiaApi.sk_region_contains_point(cast(sk_region_t*) Handle, xy.X, xy.Y);
100 	}
101 
102 	bool Contains(int x, int y) {
103 		return SkiaApi.sk_region_contains_point(cast(sk_region_t*) Handle, x, y);
104 	}
105 
106 	bool Contains(SKRectI rect) {
107 		return SkiaApi.sk_region_contains_rect(cast(sk_region_t*) Handle, &rect);
108 	}
109 
110 	// QuickContains
111 
112 	bool QuickContains(SKRectI rect) {
113 		return SkiaApi.sk_region_quick_contains(cast(sk_region_t*) Handle, &rect);
114 	}
115 
116 	// QuickReject
117 
118 	bool QuickReject(SKRectI rect) {
119 		return SkiaApi.sk_region_quick_reject_rect(cast(sk_region_t*) Handle, &rect);
120 	}
121 
122 	bool QuickReject(SKRegion region) {
123 		if (region is null)
124 			throw new ArgumentNullException(region.stringof);
125 
126 		return SkiaApi.sk_region_quick_reject(cast(sk_region_t*) Handle,
127 				cast(sk_region_t*) region.Handle);
128 	}
129 
130 	bool QuickReject(SKPath path) {
131 		if (path is null)
132 			throw new ArgumentNullException(path.stringof);
133 
134 		auto pathRegion = new SKRegion(path);
135 		scope (exit) {
136 			pathRegion.Dispose();
137 		}
138 
139 		return QuickReject(pathRegion);
140 	}
141 
142 	// Intersects
143 
144 	bool Intersects(SKPath path) {
145 		if (path is null)
146 			throw new ArgumentNullException(path.stringof);
147 
148 		auto pathRegion = new SKRegion(path);
149 		scope (exit) {
150 			pathRegion.Dispose();
151 		}
152 
153 		return Intersects(pathRegion);
154 	}
155 
156 	bool Intersects(SKRegion region) {
157 		if (region is null)
158 			throw new ArgumentNullException(region.stringof);
159 
160 		return SkiaApi.sk_region_intersects(cast(sk_region_t*) Handle,
161 				cast(sk_region_t*) region.Handle);
162 	}
163 
164 	bool Intersects(SKRectI rect) {
165 		return SkiaApi.sk_region_intersects_rect(cast(sk_region_t*) Handle, &rect);
166 	}
167 
168 	// Set*
169 
170 	void SetEmpty() {
171 		SkiaApi.sk_region_set_empty(cast(sk_region_t*) Handle);
172 	}
173 
174 	bool SetRegion(SKRegion region) {
175 		if (region is null)
176 			throw new ArgumentNullException(region.stringof);
177 
178 		return SkiaApi.sk_region_set_region(cast(sk_region_t*) Handle,
179 				cast(sk_region_t*) region.Handle);
180 	}
181 
182 	bool SetRect(SKRectI rect) {
183 		return SkiaApi.sk_region_set_rect(cast(sk_region_t*) Handle, &rect);
184 	}
185 
186 	bool SetRects(SKRectI[] rects) {
187 		if (rects is null)
188 			throw new ArgumentNullException(rects.stringof);
189 
190 		SKRectI* r = rects.ptr;
191 		return SkiaApi.sk_region_set_rects(cast(sk_region_t*) Handle, r, cast(int) rects.length);
192 	}
193 
194 	bool SetPath(SKPath path, SKRegion clip) {
195 		if (path is null)
196 			throw new ArgumentNullException(path.stringof);
197 		if (clip is null)
198 			throw new ArgumentNullException(clip.stringof);
199 
200 		return SkiaApi.sk_region_set_path(cast(sk_region_t*) Handle,
201 				cast(sk_path_t*) path.Handle, cast(sk_region_t*) clip.Handle);
202 	}
203 
204 	bool SetPath(SKPath path) {
205 		if (path is null)
206 			throw new ArgumentNullException(path.stringof);
207 
208 		auto clip = new SKRegion();
209 		scope (exit) {
210 			clip.Dispose();
211 		}
212 
213 		auto rect = SKRectI.Ceiling(path.Bounds);
214 		if (!rect.IsEmpty)
215 			clip.SetRect(rect);
216 
217 		return SkiaApi.sk_region_set_path(cast(sk_region_t*) Handle,
218 				cast(sk_path_t*) path.Handle, cast(sk_region_t*) clip.Handle);
219 	}
220 
221 	// Translate
222 
223 	void Translate(int x, int y) {
224 		return SkiaApi.sk_region_translate(cast(sk_region_t*) Handle, x, y);
225 	}
226 
227 	// Op
228 
229 	bool Op(SKRectI rect, SKRegionOperation op) {
230 		return SkiaApi.sk_region_op_rect(cast(sk_region_t*) Handle, &rect, op);
231 	}
232 
233 	bool Op(int left, int top, int right, int bottom, SKRegionOperation op) {
234 		return Op(SKRectI(left, top, right, bottom), op);
235 	}
236 
237 	bool Op(SKRegion region, SKRegionOperation op) {
238 		return SkiaApi.sk_region_op(cast(sk_region_t*) Handle,
239 				cast(sk_region_t*) region.Handle, op);
240 	}
241 
242 	bool Op(SKPath path, SKRegionOperation op) {
243 		auto pathRegion = new SKRegion(path);
244 		scope (exit) {
245 			pathRegion.Dispose();
246 		}
247 
248 		return Op(pathRegion, op);
249 	}
250 
251 	// Iterators
252 
253 	RectIterator CreateRectIterator() {
254 		return new RectIterator(this);
255 	}
256 
257 	ClipIterator CreateClipIterator(SKRectI clip) {
258 		return new ClipIterator(this, clip);
259 	}
260 
261 	SpanIterator CreateSpanIterator(int y, int left, int right) {
262 		return new SpanIterator(this, y, left, right);
263 	}
264 
265 	// classes
266 
267 	class RectIterator : SKObject, ISKSkipObjectRegistration {
268 		private const SKRegion region;
269 
270 		this(SKRegion region) {
271 			super(SkiaApi.sk_region_iterator_new(cast(sk_region_t*) region.Handle), true);
272 			this.region = region;
273 		}
274 
275 		protected override void DisposeNative() {
276 			return SkiaApi.sk_region_iterator_delete(cast(sk_region_iterator_t*) Handle);
277 		}
278 
279 		bool Next(out SKRectI rect) {
280 			if (SkiaApi.sk_region_iterator_done(cast(sk_region_iterator_t*) Handle)) {
281 				rect = SKRectI.Empty;
282 				return false;
283 			}
284 
285 			SKRectI* r = ▭
286 			SkiaApi.sk_region_iterator_rect(cast(sk_region_iterator_t*) Handle, r);
287 
288 			SkiaApi.sk_region_iterator_next(cast(sk_region_iterator_t*) Handle);
289 
290 			return true;
291 		}
292 	}
293 
294 	class ClipIterator : SKObject, ISKSkipObjectRegistration {
295 		private const SKRegion region;
296 		private const SKRectI clip;
297 
298 		this(SKRegion region, SKRectI clip) {
299 			super(SkiaApi.sk_region_cliperator_new(cast(sk_region_t*) region.Handle, &clip), true);
300 			this.region = region;
301 			this.clip = clip;
302 		}
303 
304 		protected override void DisposeNative() {
305 			return SkiaApi.sk_region_cliperator_delete(cast(sk_region_cliperator_t*) Handle);
306 		}
307 
308 		bool Next(out SKRectI rect) {
309 			if (SkiaApi.sk_region_cliperator_done(cast(sk_region_cliperator_t*) Handle)) {
310 				rect = SKRectI.Empty;
311 				return false;
312 			}
313 
314 			SKRectI* r = ▭
315 			SkiaApi.sk_region_iterator_rect(cast(sk_region_iterator_t*) Handle, r);
316 
317 			SkiaApi.sk_region_cliperator_next(cast(sk_region_cliperator_t*) Handle);
318 
319 			return true;
320 		}
321 	}
322 
323 	class SpanIterator : SKObject, ISKSkipObjectRegistration {
324 		this(SKRegion region, int y, int left, int right) {
325 			super(SkiaApi.sk_region_spanerator_new(cast(sk_region_t*) region.Handle,
326 					y, left, right), true);
327 		}
328 
329 		protected override void DisposeNative() {
330 			return SkiaApi.sk_region_spanerator_delete(cast(sk_region_spanerator_t*) Handle);
331 		}
332 
333 		bool Next(out int left, out int right) {
334 			int l;
335 			int r;
336 			if (SkiaApi.sk_region_spanerator_next(cast(sk_region_spanerator_t*) Handle, &l, &r)) {
337 				left = l;
338 				right = r;
339 				return true;
340 			}
341 
342 			left = 0;
343 			right = 0;
344 			return false;
345 		}
346 	}
347 }