summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordonal.k.fellows@manchester.ac.uk <dkf>2012-06-12 08:29:27 (GMT)
committerdonal.k.fellows@manchester.ac.uk <dkf>2012-06-12 08:29:27 (GMT)
commite35b17d7fcc763b19e43339ca575f9336d4d6eca (patch)
tree152cc41513346198a20a352370b2d8b0fe9dd1d0
parentf932a6bf8e0df9f53c0125d0e94130ff1d544f9f (diff)
downloadtk-e35b17d7fcc763b19e43339ca575f9336d4d6eca.zip
tk-e35b17d7fcc763b19e43339ca575f9336d4d6eca.tar.gz
tk-e35b17d7fcc763b19e43339ca575f9336d4d6eca.tar.bz2
Fix text clipping when working with the Xft-based renderer.
-rw-r--r--ChangeLog8
-rw-r--r--generic/tkInt.h3
-rw-r--r--generic/ttk/ttkEntry.c13
-rw-r--r--generic/ttk/ttkLabel.c13
-rw-r--r--unix/tkUnixRFont.c28
5 files changed, 63 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 7ac76d5..c5bee52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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 b152a7a..a95adf8 100644
--- a/generic/tkInt.h
+++ b/generic/tkInt.h
@@ -1186,6 +1186,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 e5d0ef2..a3d0179 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 = textarea.x;
@@ -1230,6 +1231,9 @@ static void EntryDisplay(void *clientData, Drawable d)
rect.height = textarea.height;
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 df6a686..52782ea 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 134bb45..deecceb 100644
--- a/unix/tkUnixRFont.c
+++ b/unix/tkUnixRFont.c
@@ -33,6 +33,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:
@@ -712,6 +722,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
@@ -738,6 +750,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;
@@ -775,6 +790,9 @@ Tk_DrawChars(
if (nspec) {
XftDrawGlyphFontSpec(fontPtr->ftDraw, &fontPtr->color, specs, nspec);
}
+ if (tsdPtr->clipRegion != None) {
+ XftDrawSetClip(fontPtr->ftDraw, None);
+ }
doUnderlineStrikeout:
if (fontPtr->font.fa.underline != 0) {
@@ -789,3 +807,13 @@ Tk_DrawChars(
(unsigned) fontPtr->font.underlineHeight);
}
}
+
+void
+TkUnixSetXftClipRegion(
+ Region clipRegion) /* The clipping region to install. */
+{
+ ThreadSpecificData *tsdPtr = (ThreadSpecificData *)
+ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData));
+
+ tsdPtr->clipRegion = clipRegion;
+}