From 17cd772470e5867a435c8475e35b6cbba1a63737 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 16 Jul 2023 12:58:32 +0000 Subject: Bug [f9eddb541a] (TkSetRegion(), XSetClipRectangles): Patch 1 from Christopher Chavez - Introduce a convenience function TkpCopyRegion(dst, src). --- generic/tkInt.h | 2 ++ macosx/tkMacOSXRegion.c | 24 ++++++++++++++++++++++++ unix/tkUnix.c | 26 ++++++++++++++++++++++++++ win/tkWinRegion.c | 24 ++++++++++++++++++++++++ 4 files changed, 76 insertions(+) diff --git a/generic/tkInt.h b/generic/tkInt.h index 7568585..e31bc1b 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -1337,6 +1337,8 @@ MODULE_SCOPE Status TkParseColor (Display * display, MODULE_SCOPE void TkUnixSetXftClipRegion(TkRegion clipRegion); #endif +MODULE_SCOPE void TkpCopyRegion(TkRegion dst, TkRegion src); + #if !defined(__cplusplus) && !defined(c_plusplus) # define c_class class #endif diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c index fbb41cb..e03cb2e 100644 --- a/macosx/tkMacOSXRegion.c +++ b/macosx/tkMacOSXRegion.c @@ -478,6 +478,30 @@ XOffsetRegion( /* *---------------------------------------------------------------------- * + * TkpCopyRegion -- + * + * Makes the destination region a copy of the source region. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpCopyRegion( + TkRegion dst, + TkRegion src) +{ + ChkErr(HIShapeSetWithShape, (HIMutableShapeRef)dst, (HIShapeRef)src); +} + +/* + *---------------------------------------------------------------------- + * * TkMacOSXHIShapeCreateEmpty, TkMacOSXHIShapeCreateMutableWithRect, * TkMacOSXHIShapeSetWithShape, * TkMacOSHIShapeDifferenceWithRect, TkMacOSHIShapeUnionWithRect, diff --git a/unix/tkUnix.c b/unix/tkUnix.c index ed024d1..8ec4254 100644 --- a/unix/tkUnix.c +++ b/unix/tkUnix.c @@ -116,6 +116,32 @@ Tk_UpdatePointer( /* *---------------------------------------------------------------------- * + * TkpCopyRegion -- + * + * Makes the destination region a copy of the source region. + * Currently unused on X11. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpCopyRegion( + TkRegion dst, + TkRegion src) +{ + /* XUnionRegion() in Xlib is optimized to detect copying */ + XUnionRegion(src, src, dst); +} + +/* + *---------------------------------------------------------------------- + * * TkpBuildRegionFromAlphaData -- * * Set up a rectangle of the given region based on the supplied alpha diff --git a/win/tkWinRegion.c b/win/tkWinRegion.c index a2f6fd7..9e9d80a 100644 --- a/win/tkWinRegion.c +++ b/win/tkWinRegion.c @@ -285,6 +285,30 @@ TkSubtractRegion( } /* + *---------------------------------------------------------------------- + * + * TkpCopyRegion -- + * + * Makes the destination region a copy of the source region. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpCopyRegion( + TkRegion dst, + TkRegion src) +{ + CombineRgn((HRGN)dst, (HRGN)src, NULL, RGN_COPY); +} + +/* * Local Variables: * mode: c * c-basic-offset: 4 -- cgit v0.12 From 32e85c199e36f68c80a08a50c6610a3990c54499 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 16 Jul 2023 13:01:02 +0000 Subject: Bug [f9eddb541a] (TkSetRegion(), XSetClipRectangles): Patch 2 from Christopher Chavez - For safety, have AllocClipMask() initialize the TkpClipMask. --- xlib/xgc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xlib/xgc.c b/xlib/xgc.c index 786a6fd..1f13406 100644 --- a/xlib/xgc.c +++ b/xlib/xgc.c @@ -50,6 +50,8 @@ static TkpClipMask *AllocClipMask(GC gc) { clip_mask = (TkpClipMask *)ckalloc(sizeof(TkpClipMask)); gc->clip_mask = (Pixmap) clip_mask; } + clip_mask->type = TKP_CLIP_PIXMAP; + clip_mask->value.pixmap = None; return clip_mask; } -- cgit v0.12 From c0213377420fc585acd517b8a519901101aba1db Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 16 Jul 2023 13:03:38 +0000 Subject: Bug [f9eddb541a] (TkSetRegion(), XSetClipRectangles): Patch 3 from Christopher Chavez - Stylistic adjustment to FreeClipMask() to make the next change clearer. --- xlib/xgc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/xlib/xgc.c b/xlib/xgc.c index 1f13406..8d8b6dc 100644 --- a/xlib/xgc.c +++ b/xlib/xgc.c @@ -72,10 +72,12 @@ static TkpClipMask *AllocClipMask(GC gc) { */ static void FreeClipMask(GC gc) { - if (gc->clip_mask != None) { - ckfree((char *)gc->clip_mask); - gc->clip_mask = None; + TkpClipMask * clip_mask = (TkpClipMask*)gc->clip_mask; + if (clip_mask == NULL) { + return; } + ckfree(clip_mask); + gc->clip_mask = None; } /* -- cgit v0.12 From dd8254af9cebde60bfd0d6d0aebaef9b0585d049 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 16 Jul 2023 13:19:29 +0000 Subject: Bug [f9eddb541a] (TkSetRegion(), XSetClipRectangles): Patch 4 from Christopher Chavez - TkSetRegion() copies the provided region to a dedicated region for the TkpClipMask. --- xlib/xgc.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/xlib/xgc.c b/xlib/xgc.c index 8d8b6dc..fafde25 100644 --- a/xlib/xgc.c +++ b/xlib/xgc.c @@ -49,6 +49,8 @@ static TkpClipMask *AllocClipMask(GC gc) { if (clip_mask == NULL) { clip_mask = (TkpClipMask *)ckalloc(sizeof(TkpClipMask)); gc->clip_mask = (Pixmap) clip_mask; + } else if (clip_mask->type == TKP_CLIP_REGION) { + TkDestroyRegion(clip_mask->value.region); } clip_mask->type = TKP_CLIP_PIXMAP; clip_mask->value.pixmap = None; @@ -76,6 +78,9 @@ static void FreeClipMask(GC gc) { if (clip_mask == NULL) { return; } + if (clip_mask->type == TKP_CLIP_REGION) { + TkDestroyRegion(clip_mask->value.region); + } ckfree(clip_mask); gc->clip_mask = None; } @@ -431,8 +436,8 @@ XSetClipOrigin( * * Sets the clipping region/pixmap for a GC. * - * Note that unlike the Xlib equivalent, it is not safe to delete the - * region after setting it into the GC (except on Mac OS X). The only + * Like the Xlib equivalent, it is safe to delete the + * region after setting it into the GC. The only * uses of TkSetRegion are currently in DisplayFrame and in * ImgPhotoDisplay, which use the GC immediately. * @@ -460,6 +465,8 @@ TkSetRegion( clip_mask->type = TKP_CLIP_REGION; clip_mask->value.region = r; + clip_mask->value.region = TkCreateRegion(); + TkpCopyRegion(clip_mask->value.region, r); } return Success; } -- cgit v0.12 From ef6562fba1ee7d08f5cfec0030c94b5364ba90d6 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 16 Jul 2023 13:20:26 +0000 Subject: Remove obsolete comment (TkSetRegion is used elsewhere, namely in Ttk). --- xlib/xgc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/xlib/xgc.c b/xlib/xgc.c index fafde25..ba186b4 100644 --- a/xlib/xgc.c +++ b/xlib/xgc.c @@ -437,9 +437,7 @@ XSetClipOrigin( * Sets the clipping region/pixmap for a GC. * * Like the Xlib equivalent, it is safe to delete the - * region after setting it into the GC. The only - * uses of TkSetRegion are currently in DisplayFrame and in - * ImgPhotoDisplay, which use the GC immediately. + * region after setting it into the GC. * * Results: * None. -- cgit v0.12 From 81da7830cb098eaccd1d444a8bd5defa37a25b84 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 16 Jul 2023 13:28:34 +0000 Subject: Bug [f9eddb541a] (TkSetRegion(), XSetClipRectangles): Patch 5 from Christopher Chavez - Implement XSetClipRectangles() on Windows by relocating the existing Aqua implementation --- generic/tkInt.decls | 10 ++++------ generic/tkIntXlibDecls.h | 10 +++++++--- generic/tkStubInit.c | 2 +- macosx/tkMacOSXXStubs.c | 24 ------------------------ xlib/xgc.c | 27 ++++++++++++++++++++++++++- 5 files changed, 38 insertions(+), 35 deletions(-) diff --git a/generic/tkInt.decls b/generic/tkInt.decls index 7f68cf1..8106b83 100644 --- a/generic/tkInt.decls +++ b/generic/tkInt.decls @@ -1335,12 +1335,10 @@ declare 80 win { Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height) } -# This slot is reserved for use by the clipping rectangle patch: -# declare 81 win { -# XSetClipRectangles(Display *display, GC gc, int clip_x_origin, -# int clip_y_origin, XRectangle rectangles[], int n, int ordering) -# } - +declare 81 win { + int XSetClipRectangles(Display *display, GC gc, int clip_x_origin, + int clip_y_origin, XRectangle rectangles[], int n, int ordering) +} declare 82 win { Status XParseColor(Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr) diff --git a/generic/tkIntXlibDecls.h b/generic/tkIntXlibDecls.h index 9d4200a..1040c4f 100644 --- a/generic/tkIntXlibDecls.h +++ b/generic/tkIntXlibDecls.h @@ -275,7 +275,10 @@ EXTERN int TkPutImage(unsigned long *colors, int ncolors, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); -/* Slot 81 is reserved */ ++/* 81 */ +EXTERN int XSetClipRectangles(Display * display, GC gc, + int clip_x_origin, int clip_y_origin, + XRectangle rectangles[], int n, int ordering); /* 82 */ EXTERN Status XParseColor(Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr); @@ -879,7 +882,7 @@ typedef struct TkIntXlibStubs { Bool (*xFilterEvent) (XEvent *x, Window w); /* 78 */ int (*xmbLookupString) (XIC xi, XKeyPressedEvent *xk, char *c, int i, KeySym *k, Status *s); /* 79 */ int (*tkPutImage) (unsigned long *colors, int ncolors, Display *display, Drawable d, GC gc, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); /* 80 */ - void (*reserved81)(void); + int (*xSetClipRectangles) (Display* display, GC gc, int clip_x_origin, int clip_y_origin, XRectangle rectangles[], int n, int ordering); /* 81 */ Status (*xParseColor) (Display *display, Colormap map, _Xconst char *spec, XColor *colorPtr); /* 82 */ GC (*xCreateGC) (Display *display, Drawable d, unsigned long valuemask, XGCValues *values); /* 83 */ int (*xFreeGC) (Display *display, GC gc); /* 84 */ @@ -1296,7 +1299,8 @@ extern const TkIntXlibStubs *tkIntXlibStubsPtr; (tkIntXlibStubsPtr->xmbLookupString) /* 79 */ #define TkPutImage \ (tkIntXlibStubsPtr->tkPutImage) /* 80 */ -/* Slot 81 is reserved */ +#define XSetClipRectangles \ + (tkIntXlibStubsPtr->xSetClipRectangles) /* 81 */ #define XParseColor \ (tkIntXlibStubsPtr->xParseColor) /* 82 */ #define XCreateGC \ diff --git a/generic/tkStubInit.c b/generic/tkStubInit.c index 47742c1..8b12e05 100644 --- a/generic/tkStubInit.c +++ b/generic/tkStubInit.c @@ -770,7 +770,7 @@ static const TkIntXlibStubs tkIntXlibStubs = { XFilterEvent, /* 78 */ XmbLookupString, /* 79 */ TkPutImage, /* 80 */ - 0, /* 81 */ + XSetClipRectangles, /* 81 */ XParseColor, /* 82 */ XCreateGC, /* 83 */ XFreeGC, /* 84 */ diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index 1973f5d..dbf4e09 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -721,30 +721,6 @@ XSync( return 0; } -int -XSetClipRectangles( - Display *d, - GC gc, - int clip_x_origin, - int clip_y_origin, - XRectangle* rectangles, - int n, - TCL_UNUSED(int)) -{ - TkRegion clipRgn = TkCreateRegion(); - - while (n--) { - XRectangle rect = *rectangles; - - rect.x += clip_x_origin; - rect.y += clip_y_origin; - TkUnionRectWithRegion(&rect, clipRgn, clipRgn); - rectangles++; - } - TkSetRegion(d, gc, clipRgn); - TkDestroyRegion(clipRgn); - return 1; -} /* *---------------------------------------------------------------------- * diff --git a/xlib/xgc.c b/xlib/xgc.c index ba186b4..1a5dd81 100644 --- a/xlib/xgc.c +++ b/xlib/xgc.c @@ -432,7 +432,7 @@ XSetClipOrigin( /* *---------------------------------------------------------------------- * - * TkSetRegion, XSetClipMask -- + * TkSetRegion, XSetClipMask, XSetClipRectangles -- * * Sets the clipping region/pixmap for a GC. * @@ -488,6 +488,31 @@ XSetClipMask( return Success; } +int +XSetClipRectangles( + Display* d, + GC gc, + int clip_x_origin, + int clip_y_origin, + XRectangle* rectangles, + int n, + TCL_UNUSED(int)) +{ + TkRegion clipRgn = TkCreateRegion(); + + while (n--) { + XRectangle rect = *rectangles; + + rect.x += clip_x_origin; + rect.y += clip_y_origin; + TkUnionRectWithRegion(&rect, clipRgn, clipRgn); + rectangles++; + } + TkSetRegion(d, gc, clipRgn); + TkDestroyRegion(clipRgn); + return 1; +} + /* * Some additional dummy functions (hopefully implemented soon). */ -- cgit v0.12 From 27f929b144bffb44ff31e2fc34627df4c268f890 Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 16 Jul 2023 13:31:17 +0000 Subject: Bug [f9eddb541a] (TkSetRegion(), XSetClipRectangles): Patch 6 from Christopher Chavez - Optimize XSetClipRectangles() by letting it set clip_mask->value.region directly, rather than creating a temporary region and relying on TkSetRegion() to copy it. --- xlib/xgc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/xlib/xgc.c b/xlib/xgc.c index 1a5dd81..d897bed 100644 --- a/xlib/xgc.c +++ b/xlib/xgc.c @@ -490,7 +490,7 @@ XSetClipMask( int XSetClipRectangles( - Display* d, + TCL_UNUSED(Display*), GC gc, int clip_x_origin, int clip_y_origin, @@ -499,6 +499,9 @@ XSetClipRectangles( TCL_UNUSED(int)) { TkRegion clipRgn = TkCreateRegion(); + TkpClipMask * clip_mask = AllocClipMask(gc); + clip_mask->type = TKP_CLIP_REGION; + clip_mask->value.region = clipRgn; while (n--) { XRectangle rect = *rectangles; @@ -508,8 +511,6 @@ XSetClipRectangles( TkUnionRectWithRegion(&rect, clipRgn, clipRgn); rectangles++; } - TkSetRegion(d, gc, clipRgn); - TkDestroyRegion(clipRgn); return 1; } -- cgit v0.12 From 9c2230bdc2d8b9a52ae6be01d063e2195509410c Mon Sep 17 00:00:00 2001 From: fvogel Date: Sun, 16 Jul 2023 13:36:49 +0000 Subject: Fix typo when applying patches. --- generic/tkIntXlibDecls.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generic/tkIntXlibDecls.h b/generic/tkIntXlibDecls.h index 1040c4f..365e92f 100644 --- a/generic/tkIntXlibDecls.h +++ b/generic/tkIntXlibDecls.h @@ -275,7 +275,7 @@ EXTERN int TkPutImage(unsigned long *colors, int ncolors, XImage *image, int src_x, int src_y, int dest_x, int dest_y, unsigned int width, unsigned int height); -+/* 81 */ +/* 81 */ EXTERN int XSetClipRectangles(Display * display, GC gc, int clip_x_origin, int clip_y_origin, XRectangle rectangles[], int n, int ordering); -- cgit v0.12 From 94d10731a6770689abcdba4f46d445746e002502 Mon Sep 17 00:00:00 2001 From: fvogel Date: Mon, 17 Jul 2023 19:49:57 +0000 Subject: Add an example of XSetClipRectangles() use, for non-Ttk labelframe widgets with overflowing text. From Christopher Chavez. --- generic/tkFrame.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/generic/tkFrame.c b/generic/tkFrame.c index 30602b2..4d69c16 100644 --- a/generic/tkFrame.c +++ b/generic/tkFrame.c @@ -1416,7 +1416,7 @@ DisplayFrame( Tk_Window tkwin = framePtr->tkwin; int bdX1, bdY1, bdX2, bdY2, hlWidth; Pixmap pixmap; - TkRegion clipRegion = NULL; + Bool useClipping = False; framePtr->flags &= ~REDRAW_PENDING; if ((framePtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { @@ -1551,11 +1551,9 @@ DisplayFrame( if ((labelframePtr->labelBox.width < labelframePtr->labelReqWidth) || (labelframePtr->labelBox.height < labelframePtr->labelReqHeight)) { - clipRegion = TkCreateRegion(); - TkUnionRectWithRegion(&labelframePtr->labelBox, clipRegion, - clipRegion); - TkSetRegion(framePtr->display, labelframePtr->textGC, - clipRegion); + useClipping = True; + XSetClipRectangles(framePtr->display, labelframePtr->textGC, 0, 0, + &labelframePtr->labelBox, 1, Unsorted); } Tk_DrawTextLayout(framePtr->display, pixmap, @@ -1563,9 +1561,8 @@ DisplayFrame( labelframePtr->labelTextX + LABELSPACING, labelframePtr->labelTextY + LABELSPACING, 0, -1); - if (clipRegion != NULL) { + if (useClipping) { XSetClipMask(framePtr->display, labelframePtr->textGC, None); - TkDestroyRegion(clipRegion); } } else { /* -- cgit v0.12