diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2012-06-12 08:34:40 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2012-06-12 08:34:40 (GMT) |
commit | 314b8aca482e318b8a62ae829671b364631f681e (patch) | |
tree | a423d46e9f550b20ab44f59a5e28af4ced782956 | |
parent | 94bf2a20e147c3a37f07c2a51348e3a072c4c248 (diff) | |
parent | fde697af64aae8450b540fb7eeb4f0f19aa3f005 (diff) | |
download | tk-314b8aca482e318b8a62ae829671b364631f681e.zip tk-314b8aca482e318b8a62ae829671b364631f681e.tar.gz tk-314b8aca482e318b8a62ae829671b364631f681e.tar.bz2 |
Fix text clipping when working with the Xft-based renderer.
-rw-r--r-- | ChangeLog | 8 | ||||
-rw-r--r-- | generic/tkInt.h | 3 | ||||
-rw-r--r-- | generic/ttk/ttkEntry.c | 13 | ||||
-rw-r--r-- | generic/ttk/ttkLabel.c | 13 | ||||
-rw-r--r-- | unix/tkUnixRFont.c | 39 |
5 files changed, 74 insertions, 2 deletions
@@ -1,3 +1,11 @@ +2012-06-12 Donal K. Fellows <dkf@users.sf.net> + + * unix/tkUnixRFont.c (Tk_DrawChars, TkUnixSetXftClipRegion): Add some + * generic/ttk/ttkEntry.c (EntryDisplay): special magic to make the + * generic/ttk/ttkLabel.c (TextDraw): text clipping work right with the + Xft-based renderer (which doesn't use the standard Tk GC except to + supply the color). + 2012-06-11 Donal K. Fellows <dkf@users.sf.net> * generic/ttk/ttkLabel.c (TextDraw): [Bug 3294450]: Get the clipping diff --git a/generic/tkInt.h b/generic/tkInt.h index 57157da..bc0e0a3 100644 --- a/generic/tkInt.h +++ b/generic/tkInt.h @@ -1218,6 +1218,9 @@ MODULE_SCOPE Status TkParseColor (Display * display, Colormap map, const char* spec, XColor * colorPtr); #endif +#ifdef HAVE_XFT +MODULE_SCOPE void TkUnixSetXftClipRegion(Region clipRegion); +#endif /* * Unsupported commands. diff --git a/generic/ttk/ttkEntry.c b/generic/ttk/ttkEntry.c index 98c8079..6eccf51 100644 --- a/generic/ttk/ttkEntry.c +++ b/generic/ttk/ttkEntry.c @@ -1221,7 +1221,8 @@ static void EntryDisplay(void *clientData, Drawable d) } } - /* Initialize the clip region: + /* Initialize the clip region. Note that Xft does _not_ derive its + * clipping area from the GC, so we have to supply that by other means. */ rect.x = entryPtr->entry.layoutX; @@ -1230,6 +1231,9 @@ static void EntryDisplay(void *clientData, Drawable d) rect.height = entryPtr->entry.layoutHeight; clipRegion = TkCreateRegion(); TkUnionRectWithRegion(&rect, clipRegion, clipRegion); +#ifdef HAVE_XFT + TkUnixSetXftClipRegion(clipRegion); +#endif /* Draw cursor: */ @@ -1272,6 +1276,13 @@ static void EntryDisplay(void *clientData, Drawable d) selFirst, selLast); Tk_FreeGC(Tk_Display(tkwin), gc); } + + /* Drop the region. Note that we have to manually remove the reference to + * it from the Xft guts (if they're being used). + */ +#ifdef HAVE_XFT + TkUnixSetXftClipRegion(None); +#endif TkDestroyRegion(clipRegion); } diff --git a/generic/ttk/ttkLabel.c b/generic/ttk/ttkLabel.c index 6abc847..17433dc 100644 --- a/generic/ttk/ttkLabel.c +++ b/generic/ttk/ttkLabel.c @@ -131,6 +131,7 @@ static void TextDraw(TextElement *text, Tk_Window tkwin, Drawable d, Ttk_Box b) XGCValues gcValues; GC gc1, gc2; Tk_Anchor anchor = TK_ANCHOR_CENTER; + TkRegion clipRegion = NULL; gcValues.font = Tk_FontId(text->tkfont); gcValues.foreground = color->pixel; @@ -148,9 +149,9 @@ static void TextDraw(TextElement *text, Tk_Window tkwin, Drawable d, Ttk_Box b) * Clip text if it's too wide: */ if (b.width < text->width) { - TkRegion clipRegion = TkCreateRegion(); XRectangle rect; + clipRegion = TkCreateRegion(); rect.x = b.x; rect.y = b.y; rect.width = b.width + (text->embossed ? 1 : 0); @@ -158,7 +159,11 @@ static void TextDraw(TextElement *text, Tk_Window tkwin, Drawable d, Ttk_Box b) TkUnionRectWithRegion(&rect, clipRegion, clipRegion); TkSetRegion(Tk_Display(tkwin), gc1, clipRegion); TkSetRegion(Tk_Display(tkwin), gc2, clipRegion); +#ifdef HAVE_XFT + TkUnixSetXftClipRegion(clipRegion); +#else TkDestroyRegion(clipRegion); +#endif } if (text->embossed) { @@ -180,6 +185,12 @@ static void TextDraw(TextElement *text, Tk_Window tkwin, Drawable d, Ttk_Box b) Tk_FreeGC(Tk_Display(tkwin), gc1); Tk_FreeGC(Tk_Display(tkwin), gc2); +#ifdef HAVE_XFT + if (clipRegion != NULL) { + TkUnixSetXftClipRegion(None); + TkDestroyRegion(clipRegion); + } +#endif } static void TextElementSize( diff --git a/unix/tkUnixRFont.c b/unix/tkUnixRFont.c index bad52d9..a8f5289 100644 --- a/unix/tkUnixRFont.c +++ b/unix/tkUnixRFont.c @@ -35,6 +35,16 @@ typedef struct { XftDraw *ftDraw; XftColor color; } UnixFtFont; + +/* + * Used to describe the current clipping box. Can't be passed normally because + * the information isn't retrievable from the GC. + */ + +typedef struct ThreadSpecificData { + Region clipRegion; /* The clipping region, or None. */ +} ThreadSpecificData; +static Tcl_ThreadDataKey dataKey; /* * Package initialization: @@ -754,6 +764,8 @@ Tk_DrawChars( int clen, nspec, xStart = x; XftGlyphFontSpec specs[NUM_SPEC]; XGlyphInfo metrics; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); if (fontPtr->ftDraw == 0) { #if DEBUG_FONTSEL @@ -780,6 +792,9 @@ Tk_DrawChars( fontPtr->color.color.alpha = 0xffff; fontPtr->color.pixel = values.foreground; } + if (tsdPtr->clipRegion != None) { + XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion); + } nspec = 0; while (numBytes > 0 && x <= maxCoord && y <= maxCoord) { XftFont *ftFont; @@ -819,6 +834,9 @@ Tk_DrawChars( } doUnderlineStrikeout: + if (tsdPtr->clipRegion != None) { + XftDrawSetClip(fontPtr->ftDraw, None); + } if (fontPtr->font.fa.underline != 0) { XFillRectangle(display, drawable, gc, xStart, y + fontPtr->font.underlinePos, (unsigned) (x - xStart), @@ -876,6 +894,8 @@ TkDrawAngledChars( XGCValues values; XColor xcolor; int xStart = x, yStart = y; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); #ifdef XFT_HAS_FIXED_ROTATED_PLACEMENT int clen, nglyph; FT_UInt glyphs[NUM_SPEC]; @@ -909,6 +929,9 @@ TkDrawAngledChars( fontPtr->color.color.alpha = 0xffff; fontPtr->color.pixel = values.foreground; } + if (tsdPtr->clipRegion != None) { + XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion); + } nglyph = 0; currentFtFont = NULL; @@ -995,6 +1018,9 @@ TkDrawAngledChars( fontPtr->color.color.alpha = 0xffff; fontPtr->color.pixel = values.foreground; } + if (tsdPtr->clipRegion != None) { + XftDrawSetClip(fontPtr->ftDraw, tsdPtr->clipRegion); + } nspec = 0; while (numBytes > 0 && x <= maxCoord && x >= minCoord && y <= maxCoord && y >= minCoord) { @@ -1037,6 +1063,9 @@ TkDrawAngledChars( #endif /* XFT_HAS_FIXED_ROTATED_PLACEMENT */ doUnderlineStrikeout: + if (tsdPtr->clipRegion != None) { + XftDrawSetClip(fontPtr->ftDraw, None); + } if (fontPtr->font.fa.underline || fontPtr->font.fa.overstrike) { XPoint points[5]; double width = (x - xStart) * cosA + (yStart - y) * sinA; @@ -1093,6 +1122,16 @@ TkDrawAngledChars( } } +void +TkUnixSetXftClipRegion( + Region clipRegion) /* The clipping region to install. */ +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + tsdPtr->clipRegion = clipRegion; +} + /* * Local Variables: * c-basic-offset: 4 |