comparison dwt/graphics/Region.d @ 34:5123b17c98ef

Ported dwt.events.*, dwt.graphics.GC, Region, dwt.internal.image.*
author Jacob Carlborg <doob@me.com> <jacob.carlborg@gmail.com>
date Sun, 14 Sep 2008 01:45:57 +0200
parents a9ab4c738ed8
children db5a898b2119
comparison
equal deleted inserted replaced
33:965ac0a77267 34:5123b17c98ef
5 * which accompanies this distribution, and is available at 5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html 6 * http://www.eclipse.org/legal/epl-v10.html
7 * 7 *
8 * Contributors: 8 * Contributors:
9 * IBM Corporation - initial API and implementation 9 * IBM Corporation - initial API and implementation
10 *
11 * Port to the D programming language:
12 * Jacob Carlborg <jacob.carlborg@gmail.com>
10 *******************************************************************************/ 13 *******************************************************************************/
11 module dwt.graphics.Region; 14 module dwt.graphics.Region;
12
13 import dwt.dwthelper.utils;
14 15
15 16
16 import dwt.DWT; 17 import dwt.DWT;
17 import dwt.DWTError; 18 import dwt.DWTError;
18 import dwt.DWTException; 19 import dwt.DWTException;
19 import dwt.internal.Callback;
20 import dwt.internal.cocoa.NSAffineTransform; 20 import dwt.internal.cocoa.NSAffineTransform;
21 import dwt.internal.cocoa.NSBezierPath; 21 import dwt.internal.cocoa.NSBezierPath;
22 import dwt.internal.cocoa.NSPoint; 22 import dwt.internal.cocoa.NSPoint;
23 import dwt.internal.cocoa.NSRect; 23 import dwt.internal.cocoa.NSRect;
24 import dwt.internal.cocoa.OS; 24 import dwt.internal.cocoa.OS;
25
26 import tango.text.convert.Format;
27
28 import dwt.dwthelper.utils;
29 import dwt.graphics.Device;
30 import dwt.graphics.Point;
31 import dwt.graphics.Rectangle;
32 import dwt.graphics.Resource;
33 import dwt.internal.c.qd.Quickdraw;
34 import dwt.internal.c.qd.QuickdrawTypes;
25 35
26 /** 36 /**
27 * Instances of this class represent areas of an x-y coordinate 37 * Instances of this class represent areas of an x-y coordinate
28 * system that are aggregates of the areas covered by a number 38 * system that are aggregates of the areas covered by a number
29 * of polygons. 39 * of polygons.
42 * public API. It is marked public only so that it can be shared 52 * public API. It is marked public only so that it can be shared
43 * within the packages provided by DWT. It is not available on all 53 * within the packages provided by DWT. It is not available on all
44 * platforms and should never be accessed from application code. 54 * platforms and should never be accessed from application code.
45 * </p> 55 * </p>
46 */ 56 */
47 public int handle; 57 public RgnHandle handle;
48 58
49 /** 59 /**
50 * Constructs a new empty region. 60 * Constructs a new empty region.
51 * 61 *
52 * @exception DWTError <ul> 62 * @exception DWTError <ul>
77 * @since 3.0 87 * @since 3.0
78 */ 88 */
79 public this(Device device) { 89 public this(Device device) {
80 super(device); 90 super(device);
81 handle = OS.NewRgn(); 91 handle = OS.NewRgn();
82 if (handle is 0) DWT.error(DWT.ERROR_NO_HANDLES); 92 if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES);
83 init(); 93 init();
84 } 94 }
85 95
86 this(Device device, int handle) { 96 this(Device device, RgnHandle handle) {
87 super(device); 97 super(device);
88 this.handle = handle; 98 this.handle = handle;
89 } 99 }
90 100
91 /** 101 /**
110 add(pointArray, pointArray.length); 120 add(pointArray, pointArray.length);
111 } 121 }
112 122
113 void add(int[] pointArray, int count) { 123 void add(int[] pointArray, int count) {
114 if (count <= 2) return; 124 if (count <= 2) return;
115 int polyRgn = OS.NewRgn(); 125 RgnHandle polyRgn = OS.NewRgn();
116 OS.OpenRgn(); 126 OS.OpenRgn();
117 OS.MoveTo(cast(short)pointArray[0], cast(short)pointArray[1]); 127 OS.MoveTo(cast(short)pointArray[0], cast(short)pointArray[1]);
118 for (int i = 1; i < count / 2; i++) { 128 for (int i = 1; i < count / 2; i++) {
119 OS.LineTo(cast(short)pointArray[2 * i], cast(short)pointArray[2 * i + 1]); 129 OS.LineTo(cast(short)pointArray[2 * i], cast(short)pointArray[2 * i + 1]);
120 } 130 }
164 * @since 3.1 174 * @since 3.1
165 */ 175 */
166 public void add(int x, int y, int width, int height) { 176 public void add(int x, int y, int width, int height) {
167 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 177 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
168 if (width < 0 || height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); 178 if (width < 0 || height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
169 int rectRgn = OS.NewRgn(); 179 RgnHandle rectRgn = OS.NewRgn();
170 short[] r = new short[4]; 180 Rect r;
171 OS.SetRect(r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height)); 181 OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
172 OS.RectRgn(rectRgn, r); 182 OS.RectRgn(rectRgn, &r);
173 OS.UnionRgn(handle, rectRgn, handle); 183 OS.UnionRgn(handle, rectRgn, handle);
174 OS.DisposeRgn(rectRgn); 184 OS.DisposeRgn(rectRgn);
175 } 185 }
176 186
177 /** 187 /**
209 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li> 219 * <li>ERROR_GRAPHIC_DISPOSED - if the receiver has been disposed</li>
210 * </ul> 220 * </ul>
211 */ 221 */
212 public bool contains(int x, int y) { 222 public bool contains(int x, int y) {
213 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 223 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
214 short[] point = new short[]{cast(short)x, cast(short)y}; 224 Point point = Point(cast(short)x, cast(short)y);
215 return OS.PtInRgn(point, handle); 225 return OS.PtInRgn(point, handle);
216 } 226 }
217 227
218 /** 228 /**
219 * Returns <code>true</code> if the given point is inside the 229 * Returns <code>true</code> if the given point is inside the
235 return contains(pt.x, pt.y); 245 return contains(pt.x, pt.y);
236 } 246 }
237 247
238 NSAffineTransform transform; 248 NSAffineTransform transform;
239 void convertRgn(NSAffineTransform transform) { 249 void convertRgn(NSAffineTransform transform) {
240 int newRgn = OS.NewRgn(); 250 RgnHandle newRgn = OS.NewRgn();
241 Callback callback = new Callback(this, "convertRgn", 4); 251 RegionToRectsUPP proc = &convertRgn;
242 int proc = callback.getAddress();
243 if (proc is 0) DWT.error(DWT.ERROR_NO_MORE_CALLBACKS);
244 this.transform = transform; 252 this.transform = transform;
245 OS.QDRegionToRects(handle, OS.kQDParseRegionFromTopLeft, proc, newRgn); 253 OS.QDRegionToRects(handle, OS.kQDParseRegionFromTopLeft, proc, newRgn);
246 this.transform = null; 254 this.transform = null;
247 callback.dispose();
248 OS.CopyRgn(newRgn, handle); 255 OS.CopyRgn(newRgn, handle);
249 OS.DisposeRgn(newRgn); 256 OS.DisposeRgn(newRgn);
250 } 257 }
251 258
252 int convertRgn(int message, int rgn, int r, int newRgn) { 259 extern(C) private static OSStatus* convertRgn(ushort message, RgnHandle rgn, Rect* r, void* newRgn) {
253 if (message is OS.kQDRegionToRectsMsgParse) { 260 if (message is OS.kQDRegionToRectsMsgParse) {
254 short[] rect = new short[4]; 261 Rect rect;
255 OS.memmove(rect, r, rect.length * 2); 262 OS.memmove(&rect, r, rect.sizeof);
256 NSPoint point = new NSPoint(); 263 NSPoint point = NSPoint();
257 int polyRgn = OS.NewRgn(); 264 RgnHandle polyRgn = OS.NewRgn();
258 OS.OpenRgn(); 265 OS.OpenRgn();
259 point.x = rect[1]; 266 point.x = rect.left;
260 point.y = rect[0]; 267 point.y = rect.top;
261 point = transform.transformPoint(point); 268 point = transform.transformPoint(point);
262 short startX, startY; 269 short startX, startY;
263 OS.MoveTo(startX = cast(short)point.x, startY = cast(short)point.y); 270 OS.MoveTo(startX = cast(short)point.x, startY = cast(short)point.y);
264 point.x = rect[3]; 271 point.x = rect.right;
265 point.y = rect[0]; 272 point.y = rect.top;
266 point = transform.transformPoint(point); 273 point = transform.transformPoint(point);
267 OS.LineTo(cast(short)Math.round(point.x), cast(short)point.y); 274 OS.LineTo(cast(short)Math.round(point.x), cast(short)point.y);
268 point.x = rect[3]; 275 point.x = rect.right;
269 point.y = rect[2]; 276 point.y = rect.bottom;
270 point = transform.transformPoint(point); 277 point = transform.transformPoint(point);
271 OS.LineTo(cast(short)Math.round(point.x), cast(short)Math.round(point.y)); 278 OS.LineTo(cast(short)Math.round(point.x), cast(short)Math.round(point.y));
272 point.x = rect[1]; 279 point.x = rect.left;
273 point.y = rect[2]; 280 point.y = rect.bottom;
274 point = transform.transformPoint(point); 281 point = transform.transformPoint(point);
275 OS.LineTo(cast(short)point.x, cast(short)Math.round(point.y)); 282 OS.LineTo(cast(short)point.x, cast(short)Math.round(point.y));
276 OS.LineTo(startX, startY); 283 OS.LineTo(startX, startY);
277 OS.CloseRgn(polyRgn); 284 OS.CloseRgn(polyRgn);
278 OS.UnionRgn(newRgn, polyRgn, newRgn); 285 OS.UnionRgn(newRgn, polyRgn, newRgn);
279 OS.DisposeRgn(polyRgn); 286 OS.DisposeRgn(polyRgn);
280 } 287 }
281 return 0; 288 return null;
282 } 289 }
283 290
284 void destroy() { 291 void destroy() {
285 OS.DisposeRgn(handle); 292 OS.DisposeRgn(handle);
286 handle = 0; 293 handle = 0;
294 * @param object the object to compare with this object 301 * @param object the object to compare with this object
295 * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise 302 * @return <code>true</code> if the object is the same as this object and <code>false</code> otherwise
296 * 303 *
297 * @see #hashCode 304 * @see #hashCode
298 */ 305 */
299 public bool equals(Object object) { 306 public int opEquals(Object object) {
300 if (this is object) return true; 307 if (this is object) return true;
301 if (!( null !is cast(Region)object )) return false; 308 if (!( null !is cast(Region)object )) return false;
302 Region region = cast(Region)object; 309 Region region = cast(Region)object;
303 return handle is region.handle; 310 return handle is region.handle;
304 } 311 }
305 312
313 alias opEquals equals;
314
306 /** 315 /**
307 * Returns a rectangle which represents the rectangular 316 * Returns a rectangle which represents the rectangular
308 * union of the collection of polygons the receiver 317 * union of the collection of polygons the receiver
309 * maintains to describe its area. 318 * maintains to describe its area.
310 * 319 *
316 * 325 *
317 * @see Rectangle#union 326 * @see Rectangle#union
318 */ 327 */
319 public Rectangle getBounds() { 328 public Rectangle getBounds() {
320 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 329 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
321 short[] bounds = new short[4]; 330 Rect bounds;
322 OS.GetRegionBounds(handle, bounds); 331 OS.GetRegionBounds(handle, &bounds);
323 int width = bounds[3] - bounds[1]; 332 int width = bounds.right - bounds.left;
324 int height = bounds[2] - bounds[0]; 333 int height = bounds.bottom - bounds.left;
325 return new Rectangle(bounds[1], bounds[0], width, height); 334 return new Rectangle(bounds.left, bounds.top, width, height);
326 } 335 }
327 336
328 NSBezierPath getPath() { 337 NSBezierPath getPath() {
329 Callback callback = new Callback(this, "regionToRects", 4);
330 if (callback.getAddress() is 0) DWT.error(DWT.ERROR_NO_MORE_CALLBACKS);
331 NSBezierPath path = NSBezierPath.bezierPath(); 338 NSBezierPath path = NSBezierPath.bezierPath();
332 path.retain(); 339 path.retain();
333 OS.QDRegionToRects(handle, OS.kQDParseRegionFromTopLeft, callback.getAddress(), path.id); 340 OS.QDRegionToRects(handle, OS.kQDParseRegionFromTopLeft, &regionToRects, path.id_);
334 callback.dispose(); 341 if (path.isEmpty()) path.appendBezierPathWithRect(NSRect());
335 if (path.isEmpty()) path.appendBezierPathWithRect(new NSRect());
336 return path; 342 return path;
337 } 343 }
338 344
339 NSPoint pt = new NSPoint(); 345 NSPoint pt = NSPoint();
340 short[] rect = new short[4]; 346 Rect rect;
341 int regionToRects(int message, int rgn, int r, int path) { 347 extern(C) private static OSStatus* regionToRects(ushort message, RgnHandle rgn, Rect* r, void* path) {
342 if (message is OS.kQDRegionToRectsMsgParse) { 348 if (message is OS.kQDRegionToRectsMsgParse) {
343 OS.memmove(rect, r, rect.length * 2); 349 OS.memmove(rect, r, rect.sizeof);
344 pt.x = rect[1]; 350 pt.x = rect.left;
345 pt.y = rect[0]; 351 pt.y = rect.top;
346 OS.objc_msgSend(path, OS.sel_moveToPoint_1, pt); 352 OS.objc_msgSend(path, OS.sel_moveToPoint_1, pt);
347 pt.x = rect[3]; 353 pt.x = rect.right;
348 OS.objc_msgSend(path, OS.sel_lineToPoint_1, pt); 354 OS.objc_msgSend(path, OS.sel_lineToPoint_1, pt);
349 pt.x = rect[3]; 355 pt.x = rect.right;
350 pt.y = rect[2]; 356 pt.y = rect.bottom;
351 OS.objc_msgSend(path, OS.sel_lineToPoint_1, pt); 357 OS.objc_msgSend(path, OS.sel_lineToPoint_1, pt);
352 pt.x = rect[1]; 358 pt.x = rect.left;
353 OS.objc_msgSend(path, OS.sel_lineToPoint_1, pt); 359 OS.objc_msgSend(path, OS.sel_lineToPoint_1, pt);
354 OS.objc_msgSend(path, OS.sel_closePath); 360 OS.objc_msgSend(path, OS.sel_closePath);
355 } 361 }
356 return 0; 362 return null;
357 } 363 }
358 364
359 public static Region carbon_new(Device device, int handle) { 365 public static Region carbon_new(Device device, RgnHandle handle) {
360 return new Region(device, handle); 366 return new Region(device, handle);
361 } 367 }
362 368
363 /** 369 /**
364 * Returns an integer hash code for the receiver. Any two 370 * Returns an integer hash code for the receiver. Any two
368 * 374 *
369 * @return the receiver's hash 375 * @return the receiver's hash
370 * 376 *
371 * @see #equals 377 * @see #equals
372 */ 378 */
373 public int hashCode() { 379 public hash_t toHash() {
374 return handle; 380 return handle;
375 } 381 }
382
383 alias toHash hashCode;
376 384
377 /** 385 /**
378 * Intersects the given rectangle to the collection of polygons 386 * Intersects the given rectangle to the collection of polygons
379 * the receiver maintains to describe its area. 387 * the receiver maintains to describe its area.
380 * 388 *
415 * @since 3.1 423 * @since 3.1
416 */ 424 */
417 public void intersect(int x, int y, int width, int height) { 425 public void intersect(int x, int y, int width, int height) {
418 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 426 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
419 if (width < 0 || height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); 427 if (width < 0 || height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
420 int rectRgn = OS.NewRgn(); 428 RgnHandle rectRgn = OS.NewRgn();
421 short[] r = new short[4]; 429 Rect r;
422 OS.SetRect(r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height)); 430 OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
423 OS.RectRgn(rectRgn, r); 431 OS.RectRgn(rectRgn, &r);
424 OS.SectRgn(handle, rectRgn, handle); 432 OS.SectRgn(handle, rectRgn, handle);
425 OS.DisposeRgn(rectRgn); 433 OS.DisposeRgn(rectRgn);
426 } 434 }
427 435
428 /** 436 /**
466 * 474 *
467 * @see Rectangle#intersects(Rectangle) 475 * @see Rectangle#intersects(Rectangle)
468 */ 476 */
469 public bool intersects (int x, int y, int width, int height) { 477 public bool intersects (int x, int y, int width, int height) {
470 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 478 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
471 short[] r = new short[4]; 479 Rect r;
472 OS.SetRect(r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height)); 480 OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
473 return OS.RectInRgn(rect, handle); 481 return OS.RectInRgn(&rect, handle);
474 } 482 }
475 483
476 /** 484 /**
477 * Returns <code>true</code> if the given rectangle intersects 485 * Returns <code>true</code> if the given rectangle intersects
478 * with any of the polygons the receiver maintains to describe 486 * with any of the polygons the receiver maintains to describe
504 * invoke any other method using the region. 512 * invoke any other method using the region.
505 * 513 *
506 * @return <code>true</code> when the region is disposed, and <code>false</code> otherwise 514 * @return <code>true</code> when the region is disposed, and <code>false</code> otherwise
507 */ 515 */
508 public bool isDisposed() { 516 public bool isDisposed() {
509 return handle is 0; 517 return handle is null;
510 } 518 }
511 519
512 /** 520 /**
513 * Returns <code>true</code> if the receiver does not cover any 521 * Returns <code>true</code> if the receiver does not cover any
514 * area in the (x, y) coordinate plane, and <code>false</code> if 522 * area in the (x, y) coordinate plane, and <code>false</code> if
542 */ 550 */
543 public void subtract (int[] pointArray) { 551 public void subtract (int[] pointArray) {
544 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 552 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
545 if (pointArray is null) DWT.error(DWT.ERROR_NULL_ARGUMENT); 553 if (pointArray is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
546 if (pointArray.length < 2) return; 554 if (pointArray.length < 2) return;
547 int polyRgn = OS.NewRgn(); 555 RgnHandle polyRgn = OS.NewRgn();
548 OS.OpenRgn(); 556 OS.OpenRgn();
549 OS.MoveTo(cast(short)pointArray[0], cast(short)pointArray[1]); 557 OS.MoveTo(cast(short)pointArray[0], cast(short)pointArray[1]);
550 for (int i = 1; i < pointArray.length / 2; i++) { 558 for (int i = 1; i < pointArray.length / 2; i++) {
551 OS.LineTo(cast(short)pointArray[2 * i], cast(short)pointArray[2 * i + 1]); 559 OS.LineTo(cast(short)pointArray[2 * i], cast(short)pointArray[2 * i + 1]);
552 } 560 }
597 * @since 3.1 605 * @since 3.1
598 */ 606 */
599 public void subtract(int x, int y, int width, int height) { 607 public void subtract(int x, int y, int width, int height) {
600 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED); 608 if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
601 if (width < 0 || height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT); 609 if (width < 0 || height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
602 int rectRgn = OS.NewRgn(); 610 RgnHandle rectRgn = OS.NewRgn();
603 short[] r = new short[4]; 611 Rect r;
604 OS.SetRect(r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height)); 612 OS.SetRect(r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
605 OS.RectRgn(rectRgn, r); 613 OS.RectRgn(rectRgn, &r);
606 OS.DiffRgn(handle, rectRgn, handle); 614 OS.DiffRgn(handle, rectRgn, handle);
607 OS.DisposeRgn(rectRgn); 615 OS.DisposeRgn(rectRgn);
608 } 616 }
609 617
610 /** 618 /**
676 * 684 *
677 * @return a string representation of the receiver 685 * @return a string representation of the receiver
678 */ 686 */
679 public String toString () { 687 public String toString () {
680 if (isDisposed()) return "Region {*DISPOSED*}"; 688 if (isDisposed()) return "Region {*DISPOSED*}";
681 return "Region {" + handle + "}"; 689 return Format("Region {{}{}" , handle , "}");
682 } 690 }
683 } 691 }