diff dwt/graphics/Region.d @ 45:d8635bb48c7c

Merge with SWT 3.5
author Jacob Carlborg <doob@me.com>
date Mon, 01 Dec 2008 17:07:00 +0100
parents 642f460a0908
children cfa563df4fdd
line wrap: on
line diff
--- a/dwt/graphics/Region.d	Tue Oct 21 15:20:04 2008 +0200
+++ b/dwt/graphics/Region.d	Mon Dec 01 17:07:00 2008 +0100
@@ -1,5 +1,5 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -9,7 +9,7 @@
  *     IBM Corporation - initial API and implementation
  *     
  * Port to the D programming language:
- *     Jacob Carlborg <jacob.carlborg@gmail.com>
+ *     Jacob Carlborg <doob@me.com>
  *******************************************************************************/
 module dwt.graphics.Region;
 
@@ -17,10 +17,13 @@
 import dwt.DWT;
 import dwt.DWTError;
 import dwt.DWTException;
+import dwt.internal.C;
 import dwt.internal.cocoa.NSAffineTransform;
+import dwt.internal.cocoa.NSAutoreleasePool;
 import dwt.internal.cocoa.NSBezierPath;
 import dwt.internal.cocoa.NSPoint;
 import dwt.internal.cocoa.NSRect;
+import dwt.internal.cocoa.NSThread;
 import dwt.internal.cocoa.OS;
 
 import tango.text.convert.Format;
@@ -43,6 +46,9 @@
  * method to release the operating system resources managed by each instance
  * when those instances are no longer required.
  * </p>
+ * 
+ * @see <a href="http://www.eclipse.org/swt/examples.php">DWT Example: GraphicsExample</a>
+ * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
  */
 public final class Region : Resource {
 
@@ -92,9 +98,15 @@
  */
 public this(Device device) {
     super(device);
-    handle = OS.NewRgn();
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
+    try {
+        handle = OS.NewRgn();
     if (handle is null) DWT.error(DWT.ERROR_NO_HANDLES);
     init_();
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 this(Device device, QuickdrawTypes.RgnHandle handle) {
@@ -102,6 +114,78 @@
     this.handle = handle;
 }
 
+public static Region cocoa_new(Device device, int handle) {
+    return new Region(device, handle);
+}
+
+static int /*long*/ polyToRgn(int[] poly, int length) {
+    short[] r = new short[4];
+    int /*long*/ polyRgn = OS.NewRgn(), rectRgn = OS.NewRgn();
+    int minY = poly[1], maxY = poly[1];
+    for (int y = 3; y < length; y += 2) {
+        if (poly[y] < minY) minY = poly[y];
+        if (poly[y] > maxY) maxY = poly[y];
+    }
+    int[] inter = new int[length + 1];
+    for (int y = minY; y <= maxY; y++) {
+        int count = 0;
+        int x1 = poly[0], y1 = poly[1];
+        for (int p = 2; p < length; p += 2) {
+            int x2 = poly[p], y2 = poly[p + 1];
+            if (y1 !is y2 && ((y1 <= y && y < y2) || (y2 <= y && y < y1))) {
+                inter[count++] = (int)((((y - y1) / (float)(y2 - y1)) * (x2 - x1)) + x1 + 0.5f);
+            }
+            x1 = x2;
+            y1 = y2;
+        }
+        int x2 = poly[0], y2 = poly[1];         
+        if (y1 !is y2 && ((y1 <= y && y < y2) || (y2 <= y && y < y1))) {
+            inter[count++] = (int)((((y - y1) / (float)(y2 - y1)) * (x2 - x1)) + x1 + 0.5f);
+        }
+        for (int gap=count/2; gap>0; gap/=2) {
+            for (int i=gap; i<count; i++) {
+                for (int j=i-gap; j>=0; j-=gap) {
+                    if ((inter[j] - inter[j + gap]) <= 0)
+                        break;
+                    int temp = inter[j];
+                    inter[j] = inter[j + gap];
+                    inter[j + gap] = temp;
+                }
+            }
+        }
+        for (int i = 0; i < count; i += 2) {
+            OS.SetRect(r, (short)inter[i], (short)y, (short)(inter[i + 1]),(short)(y + 1));
+            OS.RectRgn(rectRgn, r);
+            OS.UnionRgn(polyRgn, rectRgn, polyRgn);
+        }
+    }
+    OS.DisposeRgn(rectRgn);
+    return polyRgn;
+}
+
+static int /*long*/ polyRgn(int[] pointArray, int count) {
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
+    try {
+        int /*long*/ polyRgn;
+        if (C.PTR_SIZEOF is 4) {
+            polyRgn = OS.NewRgn();
+            OS.OpenRgn();
+            OS.MoveTo((short)pointArray[0], (short)pointArray[1]);
+            for (int i = 1; i < count / 2; i++) {
+                OS.LineTo((short)pointArray[2 * i], (short)pointArray[2 * i + 1]);
+            }
+            OS.LineTo((short)pointArray[0], (short)pointArray[1]);
+            OS.CloseRgn(polyRgn);
+        } else {
+            polyRgn = polyToRgn(pointArray, count);
+        }
+        return polyRgn;
+    } finally {
+        if (pool !is null) pool.release();
+    }
+}
+
 /**
  * Adds the given polygon to the collection of polygons
  * the receiver maintains to describe its area.
@@ -121,21 +205,26 @@
 public void add (int[] pointArray) {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (pointArray is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    add(pointArray, pointArray.length);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
+    try {
+        add(pointArray, pointArray.length);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
     
 void add(int[] pointArray, int count) {
     if (count <= 2) return;
-    QuickdrawTypes.RgnHandle polyRgn = OS.NewRgn();
-    OS.OpenRgn();
-    OS.MoveTo(cast(short)pointArray[0], cast(short)pointArray[1]);
-    for (int i = 1; i < count / 2; i++) {
-        OS.LineTo(cast(short)pointArray[2 * i], cast(short)pointArray[2 * i + 1]);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
+    try {
+        int /*long*/ polyRgn = polyRgn(pointArray, count);
+        OS.UnionRgn(handle, polyRgn, handle);
+        OS.DisposeRgn(polyRgn);
+    } finally {
+        if (pool !is null) pool.release();
     }
-    OS.LineTo(cast(short)pointArray[0], cast(short)pointArray[1]);
-    OS.CloseRgn(polyRgn);
-    OS.UnionRgn(handle, polyRgn, handle);
-    OS.DisposeRgn(polyRgn);
 }
 
 /**
@@ -156,7 +245,13 @@
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (rect is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (rect.width < 0 || rect.height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    add (rect.x, rect.y, rect.width, rect.height);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
+    try {
+        add (rect.x, rect.y, rect.width, rect.height);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -180,12 +275,18 @@
 public void add(int x, int y, int width, int height) {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (width < 0 || height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    QuickdrawTypes.RgnHandle rectRgn = OS.NewRgn();
-    Rect r;
-    OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
-    OS.RectRgn(rectRgn, &r);
-    OS.UnionRgn(handle, rectRgn, handle);
-    OS.DisposeRgn(rectRgn);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
+    try {
+        QuickdrawTypes.RgnHandle rectRgn = OS.NewRgn();
+        Rect r;
+        OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
+        OS.RectRgn(rectRgn, &r);
+        OS.UnionRgn(handle, rectRgn, handle);
+        OS.DisposeRgn(rectRgn);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -207,7 +308,13 @@
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (region is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (region.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    OS.UnionRgn(handle, region.handle, handle);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
+    try {
+        OS.UnionRgn(handle, region.handle, handle);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -225,8 +332,14 @@
  */
 public bool contains(int x, int y) {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
-    QuickdrawTypes.Point point = {cast(short)x, cast(short)y};
-    return OS.PtInRgn(point, handle);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
+    try {
+        QuickdrawTypes.Point point = {cast(short)x, cast(short)y};
+        return OS.PtInRgn(point, handle);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -264,29 +377,30 @@
     if (message is OS.kQDRegionToRectsMsgParse) {
         Rect rect;
         OS.memmove(&rect, r, rect.sizeof);
-        NSPoint point = NSPoint(); 
-        QuickdrawTypes.RgnHandle polyRgn = OS.NewRgn();
-        OS.OpenRgn();
+        int i = 0;
+        NSPoint point = NSPoint();
+        int[] points = new int[10];
         point.x = rect.left;
         point.y = rect.top;
         point = transform.transformPoint(point);
         short startX, startY;
-        OS.MoveTo(startX = cast(short)point.x, startY = cast(short)point.y);
-        point.x = rect.right;
+        points[i++] = startX = (short)point.x;
+        points[i++] = startY = (short)point.y;
         point.y = rect.top;
         point = transform.transformPoint(point);
-        OS.LineTo(cast(short)Math.round(point.x), cast(short)point.y);
-        point.x = rect.right;
+        points[i++] = (short)Math.round(point.x);
+        points[i++] = (short)point.y;
         point.y = rect.bottom;
         point = transform.transformPoint(point);
-        OS.LineTo(cast(short)Math.round(point.x), cast(short)Math.round(point.y));
-        point.x = rect.left;
+        points[i++] = (short)Math.round(point.x);
+        points[i++] = (short)Math.round(point.y);
         point.y = rect.bottom;
         point = transform.transformPoint(point);
-        OS.LineTo(cast(short)point.x, cast(short)Math.round(point.y));
-        OS.LineTo(startX, startY);
-        OS.CloseRgn(polyRgn);
-        OS.UnionRgn(cast(QuickdrawTypes.RgnHandle) newRgn, polyRgn, cast(QuickdrawTypes.RgnHandle) newRgn);
+        points[i++] = (short)point.x;
+        points[i++] = (short)Math.round(point.y);
+        points[i++] = startX;
+        points[i++] = startY;
+        int /*long*/ polyRgn = polyRgn(points, points.length);
         OS.DisposeRgn(polyRgn);
     }
     return null;
@@ -331,11 +445,18 @@
  */
 public Rectangle getBounds() {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
+    NSAutoreleasePool pool = null;
     Rect bounds;
+
+    if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
+    try {
     OS.GetRegionBounds(handle, &bounds);
     int width = bounds.right - bounds.left;
     int height = bounds.bottom - bounds.left;
     return new Rectangle(bounds.left, bounds.top, width, height);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 NSBezierPath getPath() {
@@ -348,28 +469,24 @@
 
 static NSPoint pt = NSPoint();
 static Rect rect;
-extern(C) private static OSStatus* regionToRects(ushort message, QuickdrawTypes.RgnHandle rgn, Rect* r, void* path) {
+extern(C) private static OSStatus* regionToRects(ushort message, QuickdrawTypes.RgnHandle rgn, Rect* r, objc.id path) {
     if (message is OS.kQDRegionToRectsMsgParse) {
         OS.memmove(&rect, r, rect.sizeof);
         pt.x = rect.left;
         pt.y = rect.top;
-        OS.objc_msgSend(cast(objc.id) path, OS.sel_moveToPoint_1, pt);
+        OS.objc_msgSend(path, OS.sel_moveToPoint_, pt);
         pt.x = rect.right;
-        OS.objc_msgSend(cast(objc.id) path, OS.sel_lineToPoint_1, pt);
+        OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
         pt.x = rect.right;
         pt.y = rect.bottom;
-        OS.objc_msgSend(cast(objc.id) path, OS.sel_lineToPoint_1, pt);
+        OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
         pt.x = rect.left;
-        OS.objc_msgSend(cast(objc.id) path, OS.sel_lineToPoint_1, pt);
-        OS.objc_msgSend(cast(objc.id) path, OS.sel_closePath);
+        OS.objc_msgSend(path, OS.sel_lineToPoint_, pt);
+        OS.objc_msgSend(path, OS.sel_closePath);
     }
     return null;
 }
 
-public static Region carbon_new(Device device, QuickdrawTypes.RgnHandle handle) {
-    return new Region(device, handle);
-}
-
 /**
  * Returns an integer hash code for the receiver. Any two 
  * objects that return <code>true</code> when passed to 
@@ -429,12 +546,18 @@
 public void intersect(int x, int y, int width, int height) {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (width < 0 || height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    QuickdrawTypes.RgnHandle rectRgn = OS.NewRgn();
-    Rect r;
-    OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
-    OS.RectRgn(rectRgn, &r);
-    OS.SectRgn(handle, rectRgn, handle);
-    OS.DisposeRgn(rectRgn);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
+    try {
+        QuickdrawTypes.RgnHandle rectRgn = OS.NewRgn();
+        Rect r;
+        OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
+        OS.RectRgn(rectRgn, &r);
+        OS.SectRgn(handle, rectRgn, handle);
+        OS.DisposeRgn(rectRgn);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -458,7 +581,13 @@
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (region is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (region.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    OS.SectRgn(handle, region.handle, handle);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
+    try {
+        OS.SectRgn(handle, region.handle, handle);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -480,9 +609,15 @@
  */
 public bool intersects (int x, int y, int width, int height) {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
-    Rect r;
-    OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
-    return OS.RectInRgn(&rect, handle);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
+    try {
+        Rect r;
+        OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
+        return OS.RectInRgn(&rect, handle);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -534,7 +669,13 @@
  */
 public bool isEmpty() {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
-    return OS.EmptyRgn(handle);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
+    try {
+        return OS.EmptyRgn(handle);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -556,16 +697,15 @@
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (pointArray is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (pointArray.length < 2) return;
-    QuickdrawTypes.RgnHandle polyRgn = OS.NewRgn();
-    OS.OpenRgn();
-    OS.MoveTo(cast(short)pointArray[0], cast(short)pointArray[1]);
-    for (int i = 1; i < pointArray.length / 2; i++) {
-        OS.LineTo(cast(short)pointArray[2 * i], cast(short)pointArray[2 * i + 1]);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
+    try {
+        int /*long*/ polyRgn = polyRgn(pointArray, pointArray.length);
+        OS.DiffRgn(handle, polyRgn, handle);
+        OS.DisposeRgn(polyRgn);
+    } finally {
+        if (pool !is null) pool.release();
     }
-    OS.LineTo(cast(short)pointArray[0], cast(short)pointArray[1]);
-    OS.CloseRgn(polyRgn);
-    OS.DiffRgn(handle, polyRgn, handle);
-    OS.DisposeRgn(polyRgn);
 }
 
 /**
@@ -611,12 +751,18 @@
 public void subtract(int x, int y, int width, int height) {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (width < 0 || height < 0) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    QuickdrawTypes.RgnHandle rectRgn = OS.NewRgn();
-    Rect r;
-    OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
-    OS.RectRgn(rectRgn, &r);
-    OS.DiffRgn(handle, rectRgn, handle);
-    OS.DisposeRgn(rectRgn);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
+    try {
+        int /*long*/ rectRgn = OS.NewRgn();
+        Rect r;
+        OS.SetRect(&r, cast(short)x, cast(short)y, cast(short)(x + width),cast(short)(y + height));
+        OS.RectRgn(rectRgn, &r);
+        OS.DiffRgn(handle, rectRgn, handle);
+        OS.DisposeRgn(rectRgn);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -640,7 +786,13 @@
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (region is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
     if (region.isDisposed()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
-    OS.DiffRgn(handle, region.handle, handle);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
+    try {
+        OS.DiffRgn(handle, region.handle, handle);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -658,7 +810,13 @@
  */
 public void translate (int x, int y) {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
-    OS.OffsetRgn (handle, cast(short)x, cast(short)y);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = cast(NSAutoreleasePool) (new NSAutoreleasePool()).alloc().init();
+    try {
+        OS.OffsetRgn (handle, cast(short)x, cast(short)y);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**
@@ -679,7 +837,13 @@
 public void translate (Point pt) {
     if (isDisposed()) DWT.error(DWT.ERROR_GRAPHIC_DISPOSED);
     if (pt is null) DWT.error(DWT.ERROR_NULL_ARGUMENT);
-    translate (pt.x, pt.y);
+    NSAutoreleasePool pool = null;
+    if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
+    try {
+        translate (pt.x, pt.y);
+    } finally {
+        if (pool !is null) pool.release();
+    }
 }
 
 /**