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 }