summaryrefslogtreecommitdiffstats
path: root/macosx/tkMacOSXRegion.c
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/tkMacOSXRegion.c')
-rw-r--r--macosx/tkMacOSXRegion.c466
1 files changed, 437 insertions, 29 deletions
diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c
index 4920958..39ba614 100644
--- a/macosx/tkMacOSXRegion.c
+++ b/macosx/tkMacOSXRegion.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tkMacOSXRegion.c,v 1.2.2.6 2007/06/29 03:22:02 das Exp $
+ * RCS: @(#) $Id: tkMacOSXRegion.c,v 1.2.2.7 2007/11/09 06:26:56 das Exp $
*/
#include "tkMacOSXPrivate.h"
@@ -36,7 +36,7 @@
TkRegion
TkCreateRegion(void)
{
- return (TkRegion) NewRgn();
+ return (TkRegion) HIShapeCreateMutable();
}
/*
@@ -60,7 +60,9 @@ void
TkDestroyRegion(
TkRegion r)
{
- DisposeRgn((RgnHandle) r);
+ if (r) {
+ CFRelease(r);
+ }
}
/*
@@ -86,7 +88,8 @@ TkIntersectRegion(
TkRegion srb,
TkRegion dr_return)
{
- SectRgn((RgnHandle) sra, (RgnHandle) srb, (RgnHandle) dr_return);
+ ChkErr(HIShapeIntersect, (HIShapeRef) sra, (HIShapeRef) srb,
+ (HIMutableShapeRef) dr_return);
}
/*
@@ -112,7 +115,8 @@ TkSubtractRegion(
TkRegion srb,
TkRegion dr_return)
{
- DiffRgn((RgnHandle) sra, (RgnHandle) srb, (RgnHandle) dr_return);
+ ChkErr(HIShapeDifference, (HIShapeRef) sra, (HIShapeRef) srb,
+ (HIMutableShapeRef) dr_return);
}
/*
@@ -139,12 +143,19 @@ TkUnionRectWithRegion(
TkRegion src_region,
TkRegion dest_region_return)
{
- TkMacOSXCheckTmpQdRgnEmpty();
- SetRectRgn(tkMacOSXtmpQdRgn, rectangle->x, rectangle->y,
- rectangle->x + rectangle->width, rectangle->y + rectangle->height);
- UnionRgn((RgnHandle) src_region, tkMacOSXtmpQdRgn,
- (RgnHandle) dest_region_return);
- SetEmptyRgn(tkMacOSXtmpQdRgn);
+ const CGRect r = CGRectMake(rectangle->x, rectangle->y,
+ rectangle->width, rectangle->height);
+
+ if (src_region == dest_region_return) {
+ ChkErr(TkMacOSHIShapeUnionWithRect,
+ (HIMutableShapeRef) dest_region_return, &r);
+ } else {
+ HIShapeRef rectRgn = HIShapeCreateWithRect(&r);
+
+ ChkErr(TkMacOSHIShapeUnion, rectRgn, (HIShapeRef) src_region,
+ (HIMutableShapeRef) dest_region_return);
+ CFRelease(rectRgn);
+ }
}
/*
@@ -156,7 +167,8 @@ TkUnionRectWithRegion(
* XRectInRegion. See X window documentation for more details.
*
* Results:
- * Returns one of: RectangleOut, RectangleIn, RectanglePart.
+ * Returns RectanglePart or RectangleOut. Note that this is not a
+ * complete implementation since it doesn't test for RectangleIn.
*
* Side effects:
* None.
@@ -173,18 +185,40 @@ TkRectInRegion(
unsigned int height)
{
int result;
+ const CGRect r = CGRectMake(x, y, width, height);
- TkMacOSXCheckTmpQdRgnEmpty();
- SetRectRgn(tkMacOSXtmpQdRgn, x, y, x + width, y + height);
- SectRgn((RgnHandle) region, tkMacOSXtmpQdRgn, tkMacOSXtmpQdRgn);
- if (EmptyRgn(tkMacOSXtmpQdRgn)) {
- result = RectangleOut;
- } else if (EqualRgn((RgnHandle) region, tkMacOSXtmpQdRgn)) {
- result = RectangleIn;
- } else {
- result = RectanglePart;
- }
- SetEmptyRgn(tkMacOSXtmpQdRgn);
+ TK_IF_MAC_OS_X_API (4, HIShapeIntersectsRect,
+ result = HIShapeIntersectsRect((HIShapeRef) region, &r) ?
+ RectanglePart : RectangleOut;
+ ) TK_ELSE_MAC_OS_X (4,
+ HIShapeRef rectRgn = HIShapeCreateWithRect(&r);
+ HIShapeRef sectRgn = HIShapeCreateIntersection((HIShapeRef) region,
+ rectRgn);
+
+#if 1
+ result = !HIShapeIsEmpty(sectRgn) ? RectanglePart : RectangleOut;
+#else
+ /*
+ * More expensive full implementation that tests for RectangleIn,
+ * unused by Tk at present.
+ */
+
+ if (!HIShapeIsEmpty(sectRgn)) {
+ HIShapeRef diffRgn = HIShapeCreateDifference(rectRgn, sectRgn);
+
+ if (HIShapeIsEmpty(diffRgn)) {
+ result = RectangleIn;
+ } else {
+ result = RectanglePart;
+ }
+ CFRelease(diffRgn);
+ } else {
+ result = RectangleOut;
+ }
+#endif
+ CFRelease(sectRgn);
+ CFRelease(rectRgn);
+ ) TK_ENDIF
return result;
}
@@ -210,11 +244,385 @@ TkClipBox(
TkRegion r,
XRectangle* rect_return)
{
- Rect rect;
+ CGRect rect;
+
+ HIShapeGetBounds((HIShapeRef) r, &rect);
+ rect_return->x = rect.origin.x;
+ rect_return->y = rect.origin.y;
+ rect_return->width = rect.size.width;
+ rect_return->height = rect.size.height;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpBuildRegionFromAlphaData --
+ *
+ * Set up a rectangle of the given region based on the supplied
+ * alpha data.
+ *
+ * Results:
+ * None
+ *
+ * Side effects:
+ * The region is updated, with extra pixels added to it.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpBuildRegionFromAlphaData(
+ TkRegion region, /* Region to update. */
+ unsigned int x, /* Where in region to update. */
+ unsigned int y, /* Where in region to update. */
+ unsigned int width, /* Size of rectangle to update. */
+ unsigned int height, /* Size of rectangle to update. */
+ unsigned char *dataPtr, /* Data to read from. */
+ unsigned int pixelStride, /* num bytes from one piece of alpha
+ * data to the next in the line. */
+ unsigned int lineStride) /* num bytes from one line of alpha
+ * data to the next line. */
+{
+ unsigned char *lineDataPtr;
+ unsigned int x1, y1, end;
+ XRectangle rect;
- GetRegionBounds((RgnHandle) r,&rect);
- rect_return->x = rect.left;
- rect_return->y = rect.top;
- rect_return->width = rect.right-rect.left;
- rect_return->height = rect.bottom-rect.top;
+ for (y1 = 0; y1 < height; y1++) {
+ lineDataPtr = dataPtr;
+ for (x1 = 0; x1 < width; x1 = end) {
+ /* search for first non-transparent pixel */
+ while ((x1 < width) && !*lineDataPtr) {
+ x1++;
+ lineDataPtr += pixelStride;
+ }
+ end = x1;
+ /* search for first transparent pixel */
+ while ((end < width) && *lineDataPtr) {
+ end++;
+ lineDataPtr += pixelStride;
+ }
+ if (end > x1) {
+ rect.x = x + x1;
+ rect.y = y + y1;
+ rect.width = end - x1;
+ rect.height = 1;
+ TkUnionRectWithRegion(&rect, region, region);
+ }
+ }
+ dataPtr += lineStride;
+ }
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpRetainRegion --
+ *
+ * Increases reference count of region.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpRetainRegion(
+ TkRegion r)
+{
+ CFRetain(r);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkpReleaseRegion --
+ *
+ * Decreases reference count of region.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * May free memory.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkpReleaseRegion(
+ TkRegion r)
+{
+ CFRelease(r);
+}
+#if 0
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXEmtpyRegion --
+ *
+ * Set region to emtpy.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXEmtpyRegion(
+ TkRegion r)
+{
+ ChkErr(HIShapeSetEmpty, (HIMutableShapeRef) r);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXIsEmptyRegion --
+ *
+ * Return native region for given tk region.
+ *
+ * Results:
+ * 1 if empty, 0 otherwise.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+TkMacOSXIsEmptyRegion(
+ TkRegion r)
+{
+ return HIShapeIsEmpty((HIMutableShapeRef) r) ? 1 : 0;
+}
+#endif
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXGetNativeRegion --
+ *
+ * Return native region for given tk region.
+ *
+ * Results:
+ * Native region, CFRelease when done.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+HIShapeRef
+TkMacOSXGetNativeRegion(
+ TkRegion r)
+{
+ return (HIShapeRef) CFRetain(r);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXSetWithNativeRegion --
+ *
+ * Set region to the native region.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXSetWithNativeRegion(
+ TkRegion r,
+ HIShapeRef rgn)
+{
+ ChkErr(TkMacOSXHIShapeSetWithShape, (HIMutableShapeRef) r, rgn);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXOffsetRegion --
+ *
+ * Offsets region by given distances.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+TkMacOSXOffsetRegion(
+ TkRegion r,
+ short dx,
+ short dy)
+{
+ ChkErr(HIShapeOffset, (HIMutableShapeRef) r, dx, dy);
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * TkMacOSXHIShapeCreateEmpty, TkMacOSXHIShapeCreateMutableWithRect,
+ * TkMacOSXHIShapeSetWithShape, TkMacOSXHIShapeSetWithRect,
+ * TkMacOSHIShapeDifferenceWithRect, TkMacOSHIShapeUnionWithRect,
+ * TkMacOSHIShapeUnion --
+ *
+ * Wrapper functions for missing/buggy HIShape API
+ *
+ *----------------------------------------------------------------------
+ */
+
+HIShapeRef
+TkMacOSXHIShapeCreateEmpty(void)
+{
+ HIShapeRef result;
+
+ TK_IF_MAC_OS_X_API (4, HIShapeCreateEmpty,
+ result = HIShapeCreateEmpty();
+ ) TK_ELSE_MAC_OS_X (4,
+ static HIShapeRef emptyRgn = NULL;
+
+ if (!emptyRgn) {
+ HIMutableShapeRef rgn = HIShapeCreateMutable();
+
+ emptyRgn = HIShapeCreateCopy(rgn);
+ CFRelease(rgn);
+ }
+ result = HIShapeCreateCopy(emptyRgn);
+ ) TK_ENDIF
+
+ return result;
+}
+
+HIMutableShapeRef
+TkMacOSXHIShapeCreateMutableWithRect(
+ const CGRect *inRect)
+{
+ HIMutableShapeRef result;
+
+ TK_IF_MAC_OS_X_API (5, HIShapeCreateMutableWithRect,
+ result = HIShapeCreateMutableWithRect(inRect);
+ ) TK_ELSE_MAC_OS_X (5,
+ HIShapeRef rgn = HIShapeCreateWithRect(inRect);
+
+ result = HIShapeCreateMutableCopy(rgn);
+ CFRelease(rgn);
+ ) TK_ENDIF
+
+ return result;
+}
+
+OSStatus
+TkMacOSXHIShapeSetWithShape(
+ HIMutableShapeRef inDestShape,
+ HIShapeRef inSrcShape)
+{
+ OSStatus result;
+
+ TK_IF_MAC_OS_X_API (5, HIShapeSetWithShape,
+ result = HIShapeSetWithShape(inDestShape, inSrcShape);
+ ) TK_ELSE_MAC_OS_X (5,
+ result = HIShapeSetEmpty(inDestShape);
+ if (result == noErr) {
+ result = HIShapeDifference(inSrcShape, inDestShape, inDestShape);
+ }
+ ) TK_ENDIF
+
+ return result;
+}
+
+#if 0
+OSStatus
+TkMacOSXHIShapeSetWithRect(
+ HIMutableShapeRef inShape,
+ const CGRect *inRect)
+{
+ OSStatus result;
+ HIShapeRef rgn = HIShapeCreateWithRect(inRect);
+
+ result = TkMacOSXHIShapeSetWithShape(inShape, rgn);
+ CFRelease(rgn);
+
+ return result;
+}
+#endif
+
+OSStatus
+TkMacOSHIShapeDifferenceWithRect(
+ HIMutableShapeRef inShape,
+ const CGRect *inRect)
+{
+ OSStatus result;
+ HIShapeRef rgn = HIShapeCreateWithRect(inRect);
+
+ result = HIShapeDifference(inShape, rgn, inShape);
+ CFRelease(rgn);
+
+ return result;
+}
+
+OSStatus
+TkMacOSHIShapeUnionWithRect(
+ HIMutableShapeRef inShape,
+ const CGRect *inRect)
+{
+ OSStatus result;
+
+ TK_IF_MAC_OS_X_API (5, HIShapeUnionWithRect,
+ result = HIShapeUnionWithRect(inShape, inRect);
+ ) TK_ELSE_MAC_OS_X (5,
+ HIShapeRef rgn = HIShapeCreateWithRect(inRect);
+
+ result = TkMacOSHIShapeUnion(rgn, inShape, inShape);
+ CFRelease(rgn);
+ ) TK_ENDIF
+
+ return result;
+}
+
+OSStatus
+TkMacOSHIShapeUnion(
+ HIShapeRef inShape1,
+ HIShapeRef inShape2,
+ HIMutableShapeRef outResult)
+{
+ OSStatus result;
+
+ TK_IF_HI_TOOLBOX (4,
+ result = HIShapeUnion(inShape1, inShape2, outResult);
+ ) TK_ELSE_HI_TOOLBOX (4,
+ /* Workaround HIShapeUnion bug in 10.3 and earlier */
+ HIShapeRef rgn = HIShapeCreateCopy(outResult);
+
+ result = HIShapeUnion(inShape1, inShape2, (HIMutableShapeRef) rgn);
+ if (result == noErr) {
+ result = HIShapeSetEmpty(outResult);
+ if (result == noErr) {
+ result = HIShapeDifference(rgn, outResult, outResult);
+ }
+ }
+ CFRelease(rgn);
+ ) TK_ENDIF
+
+ return result;
}