diff options
Diffstat (limited to 'macosx/tkMacOSXRegion.c')
-rw-r--r-- | macosx/tkMacOSXRegion.c | 466 |
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; } |