diff options
Diffstat (limited to 'carbon/tkMacOSXRegion.c')
-rw-r--r-- | carbon/tkMacOSXRegion.c | 644 |
1 files changed, 644 insertions, 0 deletions
diff --git a/carbon/tkMacOSXRegion.c b/carbon/tkMacOSXRegion.c new file mode 100644 index 0000000..e2faab0 --- /dev/null +++ b/carbon/tkMacOSXRegion.c @@ -0,0 +1,644 @@ +/* + * tkMacOSXRegion.c -- + * + * Implements X window calls for manipulating regions + * + * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen <das@users.sourceforge.net> + * + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. + */ + +#include "tkMacOSXPrivate.h" + + +/* + *---------------------------------------------------------------------- + * + * TkCreateRegion -- + * + * Implements the equivelent of the X window function XCreateRegion. See + * Xwindow documentation for more details. + * + * Results: + * Returns an allocated region handle. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkRegion +TkCreateRegion(void) +{ + return (TkRegion) HIShapeCreateMutable(); +} + +/* + *---------------------------------------------------------------------- + * + * TkDestroyRegion -- + * + * Implements the equivelent of the X window function XDestroyRegion. See + * Xwindow documentation for more details. + * + * Results: + * None. + * + * Side effects: + * Memory is freed. + * + *---------------------------------------------------------------------- + */ + +void +TkDestroyRegion( + TkRegion r) +{ + if (r) { + CFRelease(r); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkIntersectRegion -- + * + * Implements the equivalent of the X window function XIntersectRegion. + * See Xwindow documentation for more details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkIntersectRegion( + TkRegion sra, + TkRegion srb, + TkRegion dr_return) +{ + ChkErr(HIShapeIntersect, (HIShapeRef) sra, (HIShapeRef) srb, + (HIMutableShapeRef) dr_return); +} + +/* + *---------------------------------------------------------------------- + * + * TkSubtractRegion -- + * + * Implements the equivalent of the X window function XSubtractRegion. + * See X window documentation for more details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkSubtractRegion( + TkRegion sra, + TkRegion srb, + TkRegion dr_return) +{ + ChkErr(HIShapeDifference, (HIShapeRef) sra, (HIShapeRef) srb, + (HIMutableShapeRef) dr_return); +} + +/* + *---------------------------------------------------------------------- + * + * TkUnionRectWithRegion -- + * + * Implements the equivelent of the X window function + * XUnionRectWithRegion. See Xwindow documentation for more details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkUnionRectWithRegion( + XRectangle* rectangle, + TkRegion src_region, + TkRegion dest_region_return) +{ + 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); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkRectInRegion -- + * + * Implements the equivelent of the X window function XRectInRegion. See + * Xwindow documentation for more details. + * + * Results: + * Returns RectanglePart or RectangleOut. Note that this is not a + * complete implementation since it doesn't test for RectangleIn. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkRectInRegion( + TkRegion region, + int x, + int y, + unsigned int width, + unsigned int height) +{ + int result; + const CGRect r = CGRectMake(x, y, width, height); + + 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; +} + +/* + *---------------------------------------------------------------------- + * + * TkClipBox -- + * + * Implements the equivelent of the X window function XClipBox. See + * Xwindow documentation for more details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkClipBox( + TkRegion r, + XRectangle* rect_return) +{ + 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; + + 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; +} + +/* + * Local Variables: + * mode: c + * c-basic-offset: 4 + * fill-column: 78 + * coding: utf-8 + * End: + */ |