Enhancing AA-but-no-RENDER performance
- From: Owen Taylor <otaylor redhat com>
- To: fonts xfree86 org, gtk-devel-list gnome org, terra diku dk
- Subject: Enhancing AA-but-no-RENDER performance
- Date: 06 Mar 2003 15:03:28 -0500
Basic idea
==========
If you use, Xft + anti-aliasing without RENDER, it's no great
surprise that the performance is rather poor, especially on
a remote X server.
But the following observations occurred to me:
- Almost all rendering with Xft is actually on a solid
background.
- With GTK+, drawing is typically very controlled ... we
create a backing pixmap, fill it with a constant
color, then draw some lines, images and shapes on it.
So, it's not hard for GTK+ to _know_ that it is drawing
on a solid colored background.
Taking advantage of this requires hooking the part of
Xft that gets the background on to which to composite.
I did this by making it possible for a program to "hook"
the following operations in Xft:
- Get an XImage from a drawable
- Put the XImage back to a drawable
- Release an image that was retrieved earlier
Then, when GTK+ knows that an area is solid, rather than
getting it from the X server, it can
Xft details
===========
The full API added to Xft is:
====
typedef struct _XftDrawHooks XftDrawHooks;
struct _XftDrawHooks {
void *user_data;
void (*destroy) (XftDraw *draw,
void *user_data);
XImage * (*get_image) (XftDraw *draw,
void *user_data,
int x,
int y,
int width,
int height,
int *x_offset,
int *y_offset,
void **image_data);
void (*put_image) (XftDraw *draw,
void *user_data,
XImage *ximage,
void *image_data,
int src_x,
int src_y,
int dest_x,
int dest_y,
int width,
int height);
void (*destroy_image) (XftDraw *draw,
void *user_data,
XImage *ximage,
void *image_data);
};
typedef void (*XftDrawInstallHooksFunc) (XftDraw *draw,
XftDrawHooks *hooks,
void *user_data);
void
XftDrawInstallHooks (XftDraw *draw,
XftDrawInstallHooksFunc func,
void *user_data);
===
The extra indirection of providing a function to fill in
the hooks structure probably looks weird at first
glance, but my experience is that passing in the hook
structure (and thus making the hook structure size
part of the API/ABI) is something that you always regret
later when you decide you needed one more hook.
You could also have separate functions to set each hook
(XftDrawSetGetImageFunc()) but this would be really
cumbersome, especially as you would then need separate
user-data and destroy callbacks for each hook.
GTK+ details
============
The algorithm used for tracking solid regions is very simple:
- Whenever a rectangle is drawn that covers
the entire drawable, initialize
drawable->solid_region to that area.
- Whenever anything else is drawn, subtract
a bounding region for it from drawable->solid_region,
if drawable->solid_region exists.
It turns out that when I set things up in the right
fashion - putting the magic inside
_gdk_drawable_copy_to_image() - I got free optimization of
image-on-constant background without any extra code
changes.
Some timings
============
The benchmark here is the time (in seconds) it takes to layout
and draw:
20,000 10 digit strings "0123456789".
Render No-AA Nothing [A] [B] [C]
[1] Local 3.6 2.6 1.3 4.4 3.4 2.7
[2] Remote 3.5 2.2 1.2 19.1 4.7 3.8
20,000 20 digit strings "01234567890123456789".
Render No-AA Nothing [A] [B] [C]
[1] Local 6.3 4.5 2.1 7.2 5.9 4.3
[2] Remote 6.8 4.2 1.8 27.5 7.6 7.6
Render - Using RENDER
No-AA - Antialiasing off
Nothing - XftGlyphSpecCore a no-op
[A] - No RENDER, Standard Xft CVS
[B] - No RENDER, Xft CVS with attached patch
[C] - No RENDER, Xft CVS with attached patch and optimized
compositing code (will mail patch separately)
[A] and [B] also are with the GDK changes to track solid
colored regions, which has some overhead.
[1] 1.13ghz PIII, SuperSavage video (no accelerated render),
depth-24 color
[2] Machine in [1], remote displaying over 100mbit
network to a dual 733mhz PII, G400 (accelerated
render disabled as buggy, IIRC), depth-16 color
Notes:
*) For case [C] (and the 20 digit case in [B]),
the remote performance is bandwidth limited - using the figure
that the 10-digit string is 13x80 pixels, you can calculate
that it is pushing about 84Mbit/sec over a 100Mbit/sec link.
*) It's important to keep the parallelization for the
remote case in mind when looking at the numbers ... that's
why the remote numbers are _faster_ for the no-AA case,
for instance.
Possible improvements to Xft changes
====================================
- One thing that the current set of patches doesn't
do is optimize the case where only a partial area
needs to be composited. A common case for this
is where a string goes off the edge of the backing
pixmap.
GTK+ knows this (it knows the size of the pixmap)
but Xft will try to composite the full area, so
GTK+ currently has to create a larger image, and
let Xft composite on top of junk.
It probably makes sense to change the GetImage hook
to something like:
XImage * (*get_image) (XftDraw *draw,
void *user_data,
XRectangle *area_to_get,
XRectangle *area_gotten,
int *x_offset,
int *y_offset,
void **image_data);
Using XRectangle's to avoid a truly ridiculous
number of out parameters.
[ I decided to get some reaction on the current
patch before making this change, but I'm pretty
sure it makes sense ]
- An entirely different way of doing the Xft work would
have been to provide hooks at a higher level:
- Prep an area for compositing
- Composite a glyph
- Finish with compositing area
This would allow further optimizations in some cases ...
as an example ... with the patches above, GTK+ doesn't
use shared memory for compositing areas _larger_ than
256x64 pixels because shared memory allocation inside
GDK is done using a tile-based system with tiles of that
size. With a higher level set of hooks, it would be
possible break down a large area into several small areas.
Another you could do here is make the compositing operation
go faster by special-casing composite-on-solid background.
However, a high-level set of hooks puts a lot more burden
on the person doing the hooking ... they'd need to
duplicate all the compositing logic, so I think the
simpler XImage based approach is better.
Possible improvements to GTK+ changes
=====================================
- The bounding box calculations for X primitives
could/should be improved (especially arc, but
also lines)
- The patch is going to be buggy when rectangles
are drawn with tiles/stipples ... the code will
think that that creates a solid region when
it doesn't. (Should be straightforward to fix.)
- It probably isn't a good idea to turn on the solid
area tracking for every pixmap; rather it should
only be turned on only for the backing pixmaps.
This requires an additional gdk-internal API
addition.
- The solid area tracking needs to be turned off when
someone calls gdk_window_get_internal_paint_info(),
since they then can use X calls directly and
screw up the tracking.
- The totally-solid approach the current patch uses
now doesn't catch:
- selected text
- tree-views with the rules hint on
- prelighted buttons
Or anything where we have text on something
other than the window's background color.
I suspect the hit rate could be made almost 100%
by extending the current one-region approach to
two regions:
- The last rectangle that covered the entire
draw.
- The last solid rectangle (perhaps excluding
very small rectangles)
This would take some experimentation to find out
what the current hit rate is and how much it
would be improved by such a change.
Regards,
Owen
Index: Xft.h
===================================================================
RCS file: /cvs/xc/lib/Xft/Xft.h,v
retrieving revision 1.32
diff -u -p -r1.32 Xft.h
--- Xft.h 2003/02/25 21:57:53 1.32
+++ Xft.h 2003/03/06 17:00:43
@@ -287,6 +287,54 @@ void
XftDrawSetSubwindowMode (XftDraw *draw,
int mode);
+typedef struct _XftDrawHooks XftDrawHooks;
+
+struct _XftDrawHooks {
+ void *user_data;
+
+ void (*destroy) (XftDraw *draw,
+ void *user_data);
+ XImage * (*get_image) (XftDraw *draw,
+ void *user_data,
+ int x,
+ int y,
+ int width,
+ int height,
+ int *x_offset,
+ int *y_offset,
+ void **image_data);
+ void (*put_image) (XftDraw *draw,
+ void *user_data,
+ XImage *ximage,
+ void *image_data,
+ int src_x,
+ int src_y,
+ int dest_x,
+ int dest_y,
+ int width,
+ int height);
+ void (*destroy_image) (XftDraw *draw,
+ void *user_data,
+ XImage *ximage,
+ void *image_data);
+};
+
+typedef void (*XftDrawInstallHooksFunc) (XftDraw *draw,
+ XftDrawHooks *hooks,
+ void *user_data);
+
+/* To hook into the process of getting/putting the image data,
+ * call this function passing in a point to a function that
+ * actually fills in the XftDrawHooks. The extra indirection
+ * is to allow future expansion of XftDrawHooks.
+ */
+void
+XftDrawInstallHooks (XftDraw *draw,
+ XftDrawInstallHooksFunc func,
+ void *user_data);
+
+
+
/* xftextent.c */
void
Index: xftcore.c
===================================================================
RCS file: /cvs/xc/lib/Xft/xftcore.c,v
retrieving revision 1.13
diff -u -p -r1.13 xftcore.c
--- xftcore.c 2003/02/15 22:30:51 1.13
+++ xftcore.c 2003/03/06 17:00:43
@@ -932,6 +1175,124 @@ static int XftGetImageErrorHandler (Disp
return 0;
}
+static XImage *
+XftGetImage (XftDraw *draw,
+ int x,
+ int y,
+ int width,
+ int height,
+ int *x_offset,
+ int *y_offset,
+ void **image_data)
+{
+ Display *dpy = draw->dpy;
+ XImage *image;
+ XErrorHandler prev_error;
+ unsigned int depth;
+
+ *x_offset = 0;
+ *y_offset = 0;
+ *image_data = 0;
+
+ if (draw->hooks && draw->hooks->get_image) {
+ image = (*draw->hooks->get_image) (draw, draw->hooks->user_data,
+ x, y, width, height,
+ x_offset, y_offset, image_data);
+ if (!image)
+ return 0;
+ }
+ /*
+ * Try to get bits directly from the drawable; if that fails,
+ * use a temporary pixmap. When it does fail, assume it
+ * will probably fail for a while and keep using temporary
+ * pixmaps for a while to avoid double round trips.
+ */
+ else if (draw->core.use_pixmap == 0)
+ {
+ prev_error = XSetErrorHandler (XftGetImageErrorHandler);
+ image = XGetImage (dpy, draw->drawable,
+ x, y,
+ width, height, AllPlanes,
+ ZPixmap);
+ XSetErrorHandler (prev_error);
+ if (!image)
+ draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
+ }
+ else
+ {
+ draw->core.use_pixmap--;
+ image = 0;
+ }
+
+ if (!image && (depth = XftDrawDepth (draw)))
+ {
+ Pixmap pix;
+ GC gc;
+ XGCValues gcv;
+
+ pix = XCreatePixmap (dpy, draw->drawable,
+ width, height, depth);
+ gcv.graphics_exposures = False;
+ gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
+ XCopyArea (dpy, draw->drawable, pix, gc, x, y,
+ width, height, 0, 0);
+ XFreeGC (dpy, gc);
+ image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
+ ZPixmap);
+ XFreePixmap (dpy, pix);
+ }
+
+ if (image) {
+ image->red_mask = draw->visual->red_mask;
+ image->green_mask = draw->visual->green_mask;
+ image->blue_mask = draw->visual->blue_mask;
+ }
+
+ return image;
+
+}
+
+static void
+XftPutImage (XftDraw *draw,
+ XImage *image,
+ void *image_data,
+ int src_x,
+ int src_y,
+ int dest_x,
+ int dest_y,
+ int width,
+ int height)
+{
+ Display *dpy = draw->dpy;
+
+ if (draw->hooks && (*draw->hooks->put_image)) {
+ (*draw->hooks->put_image) (draw, draw->hooks->user_data,
+ image, image_data,
+ src_x, src_y,
+ dest_x, dest_y,
+ width, height);
+ return;
+ }
+
+ XPutImage (dpy, draw->drawable, draw->core.gc, image,
+ src_x, src_y,
+ dest_x, dest_y,
+ width, height);
+}
+
+static void
+XftDestroyImage (XftDraw *draw,
+ XImage *image,
+ void *image_data)
+{
+ if (draw->hooks && (*draw->hooks->destroy_image)) {
+ (*draw->hooks->destroy_image) (draw, draw->hooks->user_data, image, image_data);
+ return;
+ }
+
+ XDestroyImage (image);
+}
+
void
XftGlyphCore (XftDraw *draw,
_Xconst XftColor *color,
@@ -950,7 +1311,6 @@ XftGlyphCore (XftDraw *draw,
FcBool glyphs_loaded;
int nmissing;
int n;
- XErrorHandler prev_error;
/*
* Load missing glyphs
@@ -972,8 +1332,9 @@ XftGlyphCore (XftDraw *draw,
{
XGlyphInfo gi;
XImage *image;
- unsigned int depth;
+ void *image_data;
int ox, oy;
+ int x_offset, y_offset;
XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
XftGlyphExtents (dpy, public, glyphs, nglyphs, &gi);
@@ -981,50 +1342,10 @@ XftGlyphCore (XftDraw *draw,
goto bail1;
ox = x - gi.x;
oy = y - gi.y;
- /*
- * Try to get bits directly from the drawable; if that fails,
- * use a temporary pixmap. When it does fail, assume it
- * will probably fail for a while and keep using temporary
- * pixmaps for a while to avoid double round trips.
- */
- if (draw->core.use_pixmap == 0)
- {
- prev_error = XSetErrorHandler (XftGetImageErrorHandler);
- image = XGetImage (dpy, draw->drawable,
- ox, oy,
- gi.width, gi.height, AllPlanes,
- ZPixmap);
- XSetErrorHandler (prev_error);
- if (!image)
- draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
- }
- else
- {
- draw->core.use_pixmap--;
- image = 0;
- }
- if (!image && (depth = XftDrawDepth (draw)))
- {
- Pixmap pix;
- GC gc;
- XGCValues gcv;
- pix = XCreatePixmap (dpy, draw->drawable,
- gi.width, gi.height, depth);
- gcv.graphics_exposures = False;
- gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
- XCopyArea (dpy, draw->drawable, pix, gc, ox, oy,
- gi.width, gi.height, 0, 0);
- XFreeGC (dpy, gc);
- image = XGetImage (dpy, pix, 0, 0, gi.width, gi.height, AllPlanes,
- ZPixmap);
- XFreePixmap (dpy, pix);
- }
+ image = XftGetImage (draw, ox, oy, gi.width, gi.height, &x_offset, &y_offset, &image_data);
if (!image)
goto bail1;
- image->red_mask = draw->visual->red_mask;
- image->green_mask = draw->visual->green_mask;
- image->blue_mask = draw->visual->blue_mask;
if (image->byte_order != XftNativeByteOrder ())
XftSwapImage (image);
while (n--)
@@ -1034,16 +1355,15 @@ XftGlyphCore (XftDraw *draw,
xftg = _XftGlyphDefault (dpy, public);
if (xftg)
{
- (*smooth) (image, xftg, x - ox, y - oy, color);
+ (*smooth) (image, xftg, x_offset + x - ox, y_offset + y - oy, color);
x += xftg->metrics.xOff;
y += xftg->metrics.yOff;
}
}
if (image->byte_order != XftNativeByteOrder ())
XftSwapImage (image);
- XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, ox, oy,
- gi.width, gi.height);
- XDestroyImage (image);
+ XftPutImage (draw, image, image_data, x_offset, y_offset, ox, oy, gi.width, gi.height);
+ XftDestroyImage (draw, image, image_data);
}
else
{
@@ -1082,7 +1402,6 @@ XftGlyphSpecCore (XftDraw *draw,
FcBool glyphs_loaded;
int nmissing;
int i;
- XErrorHandler prev_error;
int x1, y1, x2, y2;
/*
@@ -1133,54 +1452,14 @@ XftGlyphSpecCore (XftDraw *draw,
_XftSmoothGlyphPossible (draw))
{
XImage *image;
- unsigned int depth;
+ int x_offset, y_offset;
+ void *image_data;
int width = x2 - x1, height = y2 - y1;
XftSmoothGlyph smooth = _XftSmoothGlyphFind (draw, public);
- /*
- * Try to get bits directly from the drawable; if that fails,
- * use a temporary pixmap. When it does fail, assume it
- * will probably fail for a while and keep using temporary
- * pixmaps for a while to avoid double round trips.
- */
- if (draw->core.use_pixmap == 0)
- {
- prev_error = XSetErrorHandler (XftGetImageErrorHandler);
- image = XGetImage (dpy, draw->drawable,
- x1, y1,
- width, height, AllPlanes,
- ZPixmap);
- XSetErrorHandler (prev_error);
- if (!image)
- draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
- }
- else
- {
- draw->core.use_pixmap--;
- image = 0;
- }
- if (!image && (depth = XftDrawDepth (draw)))
- {
- Pixmap pix;
- GC gc;
- XGCValues gcv;
-
- pix = XCreatePixmap (dpy, draw->drawable,
- width, height, depth);
- gcv.graphics_exposures = False;
- gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
- XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
- width, height, 0, 0);
- XFreeGC (dpy, gc);
- image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
- ZPixmap);
- XFreePixmap (dpy, pix);
- }
+ image = XftGetImage (draw, x1, y1, width, height, &x_offset, &y_offset, &image_data);
if (!image)
goto bail1;
- image->red_mask = draw->visual->red_mask;
- image->green_mask = draw->visual->green_mask;
- image->blue_mask = draw->visual->blue_mask;
if (image->byte_order != XftNativeByteOrder ())
XftSwapImage (image);
for (i = 0; i < nglyphs; i++)
@@ -1190,15 +1469,14 @@ XftGlyphSpecCore (XftDraw *draw,
xftg = _XftGlyphDefault (dpy, public);
if (xftg)
{
- (*smooth) (image, xftg, glyphs[i].x - x1,
- glyphs[i].y - y1, color);
+ (*smooth) (image, xftg, x_offset + glyphs[i].x - x1,
+ y_offset + glyphs[i].y - y1, color);
}
}
if (image->byte_order != XftNativeByteOrder ())
XftSwapImage (image);
- XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
- width, height);
- XDestroyImage (image);
+ XftPutImage (draw, image, image_data, x_offset, y_offset, x1, y1, width, height);
+ XftDestroyImage (draw, image, image_data);
}
else
{
@@ -1229,7 +1507,6 @@ XftGlyphFontSpecCore (XftDraw *draw,
FcBool glyphs_loaded;
int nmissing;
int i;
- XErrorHandler prev_error;
int x1, y1, x2, y2;
/*
@@ -1285,53 +1562,13 @@ XftGlyphFontSpecCore (XftDraw *draw,
_XftSmoothGlyphPossible (draw))
{
XImage *image;
- unsigned int depth;
+ void *image_data;
int width = x2 - x1, height = y2 - y1;
-
- /*
- * Try to get bits directly from the drawable; if that fails,
- * use a temporary pixmap. When it does fail, assume it
- * will probably fail for a while and keep using temporary
- * pixmaps for a while to avoid double round trips.
- */
- if (draw->core.use_pixmap == 0)
- {
- prev_error = XSetErrorHandler (XftGetImageErrorHandler);
- image = XGetImage (dpy, draw->drawable,
- x1, y1,
- width, height, AllPlanes,
- ZPixmap);
- XSetErrorHandler (prev_error);
- if (!image)
- draw->core.use_pixmap = XFT_ASSUME_PIXMAP;
- }
- else
- {
- draw->core.use_pixmap--;
- image = 0;
- }
- if (!image && (depth = XftDrawDepth (draw)))
- {
- Pixmap pix;
- GC gc;
- XGCValues gcv;
+ int x_offset, y_offset;
- pix = XCreatePixmap (dpy, draw->drawable,
- width, height, depth);
- gcv.graphics_exposures = False;
- gc = XCreateGC (dpy, pix, GCGraphicsExposures, &gcv);
- XCopyArea (dpy, draw->drawable, pix, gc, x1, y1,
- width, height, 0, 0);
- XFreeGC (dpy, gc);
- image = XGetImage (dpy, pix, 0, 0, width, height, AllPlanes,
- ZPixmap);
- XFreePixmap (dpy, pix);
- }
+ image = XftGetImage (draw, x1, y1, width, height, &x_offset, &y_offset, &image_data);
if (!image)
goto bail1;
- image->red_mask = draw->visual->red_mask;
- image->green_mask = draw->visual->green_mask;
- image->blue_mask = draw->visual->blue_mask;
if (image->byte_order != XftNativeByteOrder ())
XftSwapImage (image);
for (i = 0; i < nglyphs; i++)
@@ -1345,15 +1582,14 @@ XftGlyphFontSpecCore (XftDraw *draw,
xftg = _XftGlyphDefault (dpy, public);
if (xftg)
{
- (*smooth) (image, xftg, glyphs[i].x - x1,
- glyphs[i].y - y1, color);
+ (*smooth) (image, xftg, x_offset + glyphs[i].x - x1,
+ y_offset + glyphs[i].y - y1, color);
}
}
if (image->byte_order != XftNativeByteOrder ())
XftSwapImage (image);
- XPutImage (dpy, draw->drawable, draw->core.gc, image, 0, 0, x1, y1,
- width, height);
- XDestroyImage (image);
+ XftPutImage (draw, image, image_data, x_offset, y_offset, x1, y1, width, height);
+ XftDestroyImage (draw, image, image_data);
}
else
{
Index: xftdraw.c
===================================================================
RCS file: /cvs/xc/lib/Xft/xftdraw.c,v
retrieving revision 1.25
diff -u -p -r1.25 xftdraw.c
--- xftdraw.c 2002/10/11 17:53:02 1.25
+++ xftdraw.c 2003/03/06 17:00:43
@@ -155,6 +155,7 @@ XftDrawCreate (Display *dpy,
draw->core.use_pixmap = 0;
draw->clip_type = XftClipTypeNone;
draw->subwindow_mode = ClipByChildren;
+ draw->hooks = 0;
XftMemAlloc (XFT_MEM_DRAW, sizeof (XftDraw));
return draw;
}
@@ -280,6 +281,12 @@ XftDrawVisual (XftDraw *draw)
void
XftDrawDestroy (XftDraw *draw)
{
+ if (draw->hooks) {
+ if (draw->hooks->destroy)
+ (*draw->hooks->destroy) (draw, draw->hooks->user_data);
+
+ free (draw->hooks);
+ }
if (draw->render.pict)
XRenderFreePicture (draw->dpy, draw->render.pict);
if (draw->core.gc)
@@ -294,6 +301,7 @@ XftDrawDestroy (XftDraw *draw)
case XftClipTypeNone:
break;
}
+
XftMemFree (XFT_MEM_DRAW, sizeof (XftDraw));
free (draw);
}
@@ -990,4 +998,27 @@ XftDrawSetSubwindowMode (XftDraw *draw,
}
if (draw->core.gc)
XSetSubwindowMode (draw->dpy, draw->core.gc, mode);
+}
+
+void
+XftDrawInstallHooks (XftDraw *draw,
+ XftDrawInstallHooksFunc func,
+ void *user_data)
+{
+ XftDrawHooks *new_hooks;
+
+ new_hooks = calloc (sizeof (XftDrawHooks), 1);
+ if (!new_hooks)
+ return;
+
+ if (draw->hooks) {
+ if (draw->hooks->destroy)
+ (*draw->hooks->destroy) (draw, draw->hooks->user_data);
+
+ free (draw->hooks);
+ }
+
+ draw->hooks = new_hooks;
+
+ (*func) (draw, new_hooks, user_data);
}
Index: xftint.h
===================================================================
RCS file: /cvs/xc/lib/Xft/xftint.h,v
retrieving revision 1.37
diff -u -p -r1.37 xftint.h
--- xftint.h 2002/10/11 17:53:02 1.37
+++ xftint.h 2003/03/06 17:00:43
@@ -182,6 +182,7 @@ struct _XftDraw {
XftClipType clip_type;
XftClip clip;
int subwindow_mode;
+ XftDrawHooks *hooks;
struct {
Picture pict;
} render;
? x11/childinfo.c
? x11/childinfo.h
Index: x11/gdkdisplay-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdisplay-x11.c,v
retrieving revision 1.25
diff -u -p -r1.25 gdkdisplay-x11.c
--- x11/gdkdisplay-x11.c 9 Jan 2003 02:38:12 -0000 1.25
+++ x11/gdkdisplay-x11.c 6 Mar 2003 16:59:40 -0000
@@ -127,6 +127,7 @@ gdk_display_open (const gchar *display_n
display_x11 = GDK_DISPLAY_X11 (display);
display_x11->use_xft = -1;
+ display_x11->use_xshm = TRUE;
display_x11->xdisplay = xdisplay;
/* Set up handlers for Xlib internal connections */
Index: x11/gdkdrawable-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdrawable-x11.c,v
retrieving revision 1.25
diff -u -p -r1.25 gdkdrawable-x11.c
--- x11/gdkdrawable-x11.c 7 Nov 2002 22:27:22 -0000 1.25
+++ x11/gdkdrawable-x11.c 6 Mar 2003 16:59:40 -0000
@@ -24,6 +24,10 @@
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#undef GDK_DISABLE_DEPRECATED
+#include "gdkfont.h"
+#define GDK_DISABLE_DEPRECATED
+
#include "gdkx.h"
#include "gdkregion-generic.h"
@@ -149,6 +153,14 @@ static void gdk_drawable_impl_x11_class_
static void gdk_drawable_impl_x11_finalize (GObject *object);
+static GdkDrawable *get_impl_drawable (GdkDrawable *drawable);
+
+static void solid_colored_subtract (GdkDrawable *drawable,
+ gint x,
+ gint y,
+ gint width,
+ gint height);
+
static gpointer parent_class = NULL;
GType
@@ -218,8 +230,13 @@ gdk_drawable_impl_x11_class_init (GdkDra
static void
gdk_drawable_impl_x11_finalize (GObject *object)
{
+ GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (object);
+
gdk_drawable_set_colormap (GDK_DRAWABLE (object), NULL);
+ if (impl->solid_region)
+ gdk_region_destroy (impl->solid_region);
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -236,9 +253,124 @@ _gdk_x11_have_render (GdkDisplay *displa
&event_base, &error_base);
}
+static XImage *
+get_xft_image (XftDraw *draw,
+ void *user_data,
+ int x,
+ int y,
+ int width,
+ int height,
+ int *x_offset,
+ int *y_offset,
+ void **image_data)
+{
+ GdkDrawable *drawable = user_data;
+ GdkImage *image;
+
+ if (width <= GDK_SCRATCH_IMAGE_WIDTH && height <= GDK_SCRATCH_IMAGE_HEIGHT)
+ {
+ gint xs0, ys0;
+ gint xoff = 0, yoff = 0;
+ int depth = gdk_drawable_get_depth (drawable);
+
+ image = _gdk_image_get_scratch (gdk_drawable_get_screen (drawable),
+ width, height,
+ depth, &xs0, &ys0);
+
+ if (x < 0)
+ {
+ width += x;
+ xoff = -x;
+ x = 0;
+ }
+
+ if (y < 0)
+ {
+ height += y;
+ yoff = -y;
+ y = 0;
+ }
+
+
+ _gdk_drawable_copy_to_image (drawable, image,
+ x, y, xs0 + xoff, ys0 + yoff, width, height);
+
+ *x_offset = xs0;
+ *y_offset = ys0;
+ *image_data = g_object_ref (image);
+
+ return GDK_IMAGE_XIMAGE (image);
+ }
+ else
+ {
+ image = gdk_image_new (GDK_IMAGE_NORMAL,
+ gdk_drawable_get_visual (drawable),
+ width, height);
+
+ _gdk_drawable_copy_to_image (drawable, image,
+ x, y, 0, 0, width, height);
+
+ *x_offset = 0;
+ *y_offset = 0;
+ *image_data = image;
+
+ return GDK_IMAGE_XIMAGE (image);
+ }
+}
+
+static void
+put_xft_image (XftDraw *draw,
+ void *user_data,
+ XImage *ximage,
+ void *image_data,
+ int src_x,
+ int src_y,
+ int dest_x,
+ int dest_y,
+ int width,
+ int height)
+{
+ GdkVisual *visual = gdk_drawable_get_visual (user_data);
+ GdkDrawable *drawable = user_data;
+ GdkDrawable *impl = get_impl_drawable (drawable);
+
+ gdk_draw_image (drawable,
+ _gdk_x11_visual_get_scratch_gc (visual),
+ image_data,
+ src_x, src_y, dest_x, dest_y,
+ width, height);
+
+
+ if (GDK_DRAWABLE_IMPL_X11 (impl)->solid_region)
+ solid_colored_subtract (impl, dest_x, dest_y, width, height);
+}
+
+static void
+destroy_xft_image (XftDraw *draw,
+ void *user_data,
+ XImage *ximage,
+ void *image_data)
+{
+ g_object_unref (image_data);
+
+ return;
+}
+
+static void
+install_xft_draw_hooks (XftDraw *draw,
+ XftDrawHooks *hooks,
+ void *user_data)
+{
+ hooks->user_data = user_data = user_data;
+ hooks->get_image = get_xft_image;
+ hooks->put_image = put_xft_image;
+ hooks->destroy_image = destroy_xft_image;
+}
+
#ifdef HAVE_XFT2
static XftDraw *
-gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable)
+gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable,
+ gboolean warn)
{
GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
@@ -249,11 +381,12 @@ gdk_x11_drawable_get_xft_draw (GdkDrawab
if (!colormap)
{
- g_warning ("Using Xft rendering requires the drawable argument to\n"
- "have a specified colormap. All windows have a colormap,\n"
- "however, pixmaps only have colormap by default if they\n"
- "were created with a non-NULL window argument. Otherwise\n"
- "a colormap must be set on them with gdk_drawable_set_colormap");
+ if (warn)
+ g_warning ("Using Xft rendering requires the drawable argument to\n"
+ "have a specified colormap. All windows have a colormap,\n"
+ "however, pixmaps only have colormap by default if they\n"
+ "were created with a non-NULL window argument. Otherwise\n"
+ "a colormap must be set on them with gdk_drawable_set_colormap");
return NULL;
}
@@ -261,6 +394,7 @@ gdk_x11_drawable_get_xft_draw (GdkDrawab
impl->xft_draw = XftDrawCreate (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
GDK_VISUAL_XVISUAL (visual), GDK_COLORMAP_XCOLORMAP (colormap));
+ XftDrawInstallHooks (impl->xft_draw, install_xft_draw_hooks, impl->wrapper);
}
return impl->xft_draw;
@@ -269,7 +403,7 @@ gdk_x11_drawable_get_xft_draw (GdkDrawab
static Picture
gdk_x11_drawable_get_picture (GdkDrawable *drawable)
{
- XftDraw *draw = gdk_x11_drawable_get_xft_draw (drawable);
+ XftDraw *draw = gdk_x11_drawable_get_xft_draw (drawable, TRUE);
return draw ? XftDrawPicture (draw) : None;
}
@@ -279,7 +413,7 @@ gdk_x11_drawable_update_xft_clip (GdkDra
GdkGC *gc)
{
GdkGCX11 *gc_private = gc ? GDK_GC_X11 (gc) : NULL;
- XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable);
+ XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable, TRUE);
if (gc && gc_private->clip_region)
{
@@ -436,6 +570,104 @@ gdk_x11_set_colormap (GdkDrawable *drawa
*/
static void
+solid_colored_subtract (GdkDrawable *drawable,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+ GdkRegion *tmp_region;
+ GdkRectangle r;
+
+ r.x = x; r.y = y; r.width = width; r.height = height;
+ tmp_region = gdk_region_rectangle (&r);
+ gdk_region_subtract (impl->solid_region, tmp_region);
+ gdk_region_destroy (tmp_region);
+}
+
+static void
+solid_colored_subtract_points (GdkDrawable *drawable,
+ GdkPoint *points,
+ gint npoints,
+ gboolean filled)
+{
+ gint xmin = G_MININT, ymin = G_MININT;
+ gint xmax = G_MAXINT, ymax = G_MAXINT;
+ gint i;
+
+ for (i=0; i<npoints; i++)
+ {
+ xmin = MIN (xmin, points[i].x); ymin = MIN (ymin, points[i].y);
+ if (filled)
+ {
+ xmax = MAX (xmax, points[i].x); ymax = MAX (ymax, points[i].y);
+ }
+ else
+ {
+ xmax = MAX (xmax, points[i].x + 1); ymax = MAX (ymax, points[i].y + 1);
+ }
+ }
+
+ solid_colored_subtract (drawable, xmin, ymin, xmax - xmin, ymax - ymin);
+}
+
+static void
+solid_colored_subtract_line (GdkDrawable *drawable,
+ GdkGC *gc,
+ gint x1,
+ gint x2,
+ gint y1,
+ gint y2)
+{
+ GdkGCX11 *gc_x11 = GDK_GC_X11 (gc);
+ int lw = gc_x11->line_width;
+
+ gint xmin = MIN (x1, x2); gint ymin = MIN (y1, y2);
+ gint xmax = MAX (x1, x2); gint ymax = MAX (y1, y2);
+
+ if (lw == 0)
+ lw = 1;
+
+ /* Instead of computing the exact line bounds, we compute
+ * the exact bounds for a rectangle with X's rasterization
+ * rules, which should give the line bounding box + a bit
+ * of slop
+ */
+ solid_colored_subtract (drawable,
+ xmin - lw / 2, ymin - lw/2,
+ xmax + lw - lw / 2, ymax + lw - lw / 2);
+}
+
+static void
+solid_colored_subtract_polyline (GdkDrawable *drawable,
+ GdkGC *gc,
+ XPoint *points,
+ gint npoints)
+{
+ gint i;
+
+ for (i = 1; i < npoints; i++)
+ solid_colored_subtract_line (drawable, gc,
+ points[i - 1].x, points[i - 1].y,
+ points[i].x, points[i].y);
+}
+
+static void
+solid_colored_subtract_segments (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkSegment *segs,
+ gint nsegs)
+{
+ gint i;
+
+ for (i = 0; i < nsegs; i++)
+ solid_colored_subtract_line (drawable, gc,
+ segs[i].x1, segs[i].y1,
+ segs[i].x2, segs[i].y2);
+}
+
+static void
gdk_x11_draw_rectangle (GdkDrawable *drawable,
GdkGC *gc,
gboolean filled,
@@ -447,6 +679,46 @@ gdk_x11_draw_rectangle (GdkDrawable *dra
GdkDrawableImplX11 *impl;
impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+
+ if (impl->do_solid_colored)
+ {
+ int w, h;
+
+ gdk_drawable_get_size (impl->wrapper, &w, &h);
+
+ if (filled &&
+ x <= 0 && y <= 0 &&
+ x + width >= w && y + height >= h)
+ {
+ GdkGCX11 *gc_x11 = GDK_GC_X11 (gc);
+
+ GdkRectangle r;
+
+ r.x = 0; r.y = 0; r.width = w; r.height = h;
+
+ if (impl->solid_region)
+ gdk_region_destroy (impl->solid_region);
+
+ impl->solid_region = gdk_region_rectangle (&r);
+ impl->solid_pixel = gc_x11->fg_pixel;
+ }
+ else if (impl->solid_region)
+ {
+ if (filled)
+ {
+ GdkGCX11 *gc_x11 = GDK_GC_X11 (gc);
+
+ if (gc_x11->fg_pixel != impl->solid_pixel)
+ solid_colored_subtract (drawable, x, y, width, height);
+ }
+ else
+ {
+ /* We actually use the rectangle bounding box for lines */
+ solid_colored_subtract_line (drawable, gc, x, y, x + width, y + height);
+ }
+
+ }
+ }
if (filled)
XFillRectangle (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
@@ -471,6 +743,14 @@ gdk_x11_draw_arc (GdkDrawable *drawable,
impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+ if (impl->solid_region)
+ {
+ /* Could do a lot better */
+ if (filled)
+ solid_colored_subtract (drawable, x, y, width, height);
+ else
+ solid_colored_subtract_line (drawable, gc, x, y, x + width, y + height);
+ }
if (filled)
XFillArc (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
@@ -493,7 +773,6 @@ gdk_x11_draw_polygon (GdkDrawable *drawa
impl = GDK_DRAWABLE_IMPL_X11 (drawable);
-
if (!filled &&
(points[0].x != points[npoints-1].x || points[0].y != points[npoints-1].y))
{
@@ -508,6 +787,14 @@ gdk_x11_draw_polygon (GdkDrawable *drawa
tmp_points = g_new (XPoint, tmp_npoints);
}
+ if (impl->solid_region)
+ {
+ if (filled)
+ solid_colored_subtract_points (drawable, points, npoints, TRUE);
+ else
+ solid_colored_subtract_polyline (drawable, gc, tmp_points, tmp_npoints);
+ }
+
for (i=0; i<npoints; i++)
{
tmp_points[i].x = points[i].x;
@@ -544,6 +831,21 @@ gdk_x11_draw_text (GdkDrawable *drawable
impl = GDK_DRAWABLE_IMPL_X11 (drawable);
xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
+
+ if (impl->solid_region)
+ {
+ gint lbearing;
+ gint rbearing;
+ gint ascent;
+ gint descent;
+
+ gdk_text_extents (font, text, text_length,
+ &lbearing, &rbearing, NULL, &ascent, &descent);
+
+ solid_colored_subtract (drawable,
+ x + lbearing, y - ascent,
+ rbearing, descent);
+ }
if (font->type == GDK_FONT_FONT)
{
@@ -585,6 +887,21 @@ gdk_x11_draw_text_wc (GdkDrawable *dr
impl = GDK_DRAWABLE_IMPL_X11 (drawable);
xdisplay = GDK_SCREEN_XDISPLAY (impl->screen);
+ if (impl->solid_region)
+ {
+ gint lbearing;
+ gint rbearing;
+ gint ascent;
+ gint descent;
+
+ gdk_text_extents_wc (font, text, text_length,
+ &lbearing, &rbearing, NULL, &ascent, &descent);
+
+ solid_colored_subtract (drawable,
+ x + lbearing, y - ascent,
+ rbearing, descent);
+ }
+
if (font->type == GDK_FONT_FONT)
{
XFontStruct *xfont = (XFontStruct *) GDK_FONT_XFONT (font);
@@ -639,6 +956,9 @@ gdk_x11_draw_drawable (GdkDrawable *draw
impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+ if (impl->solid_region)
+ solid_colored_subtract (drawable, xdest, ydest, width, height);
+
if (GDK_IS_DRAWABLE_IMPL_X11 (src))
src_impl = GDK_DRAWABLE_IMPL_X11 (src);
else
@@ -679,6 +999,8 @@ gdk_x11_draw_points (GdkDrawable *drawab
impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+ if (impl->solid_region)
+ solid_colored_subtract_points (drawable, points, npoints, FALSE);
/* We special-case npoints == 1, because X will merge multiple
* consecutive XDrawPoint requests into a PolyPoint request
@@ -722,6 +1044,8 @@ gdk_x11_draw_segments (GdkDrawable *draw
impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+ if (impl->solid_region)
+ solid_colored_subtract_segments (drawable, gc, segs, nsegs);
/* We special-case nsegs == 1, because X will merge multiple
* consecutive XDrawLine requests into a PolySegment request
@@ -765,13 +1089,15 @@ gdk_x11_draw_lines (GdkDrawable *drawabl
GdkDrawableImplX11 *impl;
impl = GDK_DRAWABLE_IMPL_X11 (drawable);
-
for (i=0; i<npoints; i++)
{
tmp_points[i].x = points[i].x;
tmp_points[i].y = points[i].y;
}
+
+ if (impl->solid_region)
+ solid_colored_subtract_polyline (drawable, gc, tmp_points, npoints);
XDrawLines (GDK_SCREEN_XDISPLAY (impl->screen),
impl->xid,
@@ -804,7 +1130,7 @@ gdk_x11_draw_glyphs (GdkDrawable *d
_gdk_gc_x11_get_fg_xft_color (gc, &color);
gdk_x11_drawable_update_xft_clip (drawable, gc);
- draw = gdk_x11_drawable_get_xft_draw (drawable);
+ draw = gdk_x11_drawable_get_xft_draw (drawable, TRUE);
pango_xft_render (draw, &color, font, glyphs, x, y);
#else /* !HAVE_XFT2 */
@@ -844,6 +1170,9 @@ gdk_x11_draw_image (GdkDrawable
impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+ if (impl->solid_region)
+ solid_colored_subtract (drawable, xdest, ydest, width, height);
+
if (image->type == GDK_IMAGE_SHARED)
XShmPutImage (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid,
GDK_GC_GET_XGC (gc), GDK_IMAGE_XIMAGE (image),
@@ -863,7 +1192,8 @@ gdk_x11_get_depth (GdkDrawable *drawable
}
-static GdkDrawable * get_impl_drawable (GdkDrawable *drawable)
+static GdkDrawable *
+get_impl_drawable (GdkDrawable *drawable)
{
GdkDrawable *impl;
@@ -1429,12 +1759,16 @@ gdk_x11_draw_pixbuf (GdkDrawable *dr
gint x_dither,
gint y_dither)
{
+ GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
FormatType format_type;
XRenderPictFormat *format, *mask_format;
gint rowstride;
#ifdef USE_SHM
gboolean use_pixmaps = TRUE;
#endif /* USE_SHM */
+
+ if (impl->solid_region)
+ solid_colored_subtract (drawable, dest_x, dest_y, width, height);
format_type = select_format (gdk_drawable_get_display (drawable),
&format, &mask_format);
@@ -1444,7 +1778,7 @@ gdk_x11_draw_pixbuf (GdkDrawable *dr
(dither == GDK_RGB_DITHER_MAX && gdk_drawable_get_depth (drawable) != 24) ||
gdk_x11_drawable_get_picture (drawable) == None)
{
- GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper;
+ GdkDrawable *wrapper = impl->wrapper;
GDK_DRAWABLE_CLASS (parent_class)->draw_pixbuf (wrapper, gc, pixbuf,
src_x, src_y, dest_x, dest_y,
width, height,
Index: x11/gdkdrawable-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdrawable-x11.h,v
retrieving revision 1.9
diff -u -p -r1.9 gdkdrawable-x11.h
--- x11/gdkdrawable-x11.h 3 Oct 2002 21:17:07 -0000 1.9
+++ x11/gdkdrawable-x11.h 6 Mar 2003 16:59:40 -0000
@@ -69,7 +69,13 @@ struct _GdkDrawableImplX11
XftDraw *xft_draw;
#elif defined (HAVE_XFT)
Picture picture;
-#endif
+#endif
+
+ GdkRegion *solid_region;
+ guint solid_pixel;
+
+ guint do_solid_colored : 1;
+ guint solid_colored : 1;
};
struct _GdkDrawableImplX11Class
Index: x11/gdkgc-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkgc-x11.c,v
retrieving revision 1.26
diff -u -p -r1.26 gdkgc-x11.c
--- x11/gdkgc-x11.c 28 Nov 2002 00:33:05 -0000 1.26
+++ x11/gdkgc-x11.c 6 Mar 2003 16:59:40 -0000
@@ -159,6 +159,11 @@ _gdk_x11_gc_new (GdkDrawable *drawa
if (values_mask & GDK_GC_FOREGROUND)
private->fg_pixel = values->foreground.pixel;
+ if (values_mask & GDK_GC_LINE_WIDTH)
+ private->line_width = values->line_width;
+ else
+ private->line_width = 0;
+
xvalues.function = GXcopy;
xvalues.fill_style = FillSolid;
xvalues.arc_mode = ArcPieSlice;
@@ -400,6 +405,9 @@ gdk_x11_gc_set_values (GdkGC *
if (values_mask & GDK_GC_FOREGROUND)
x11_gc->fg_pixel = values->foreground.pixel;
+
+ if (values_mask & GDK_GC_LINE_WIDTH)
+ x11_gc->line_width = values->line_width;
gdk_x11_gc_values_to_xvalues (values, values_mask, &xvalues, &xvalues_mask);
Index: x11/gdkimage-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkimage-x11.c,v
retrieving revision 1.50
diff -u -p -r1.50 gdkimage-x11.c
--- x11/gdkimage-x11.c 22 Oct 2002 22:11:22 -0000 1.50
+++ x11/gdkimage-x11.c 6 Mar 2003 16:59:40 -0000
@@ -496,6 +496,31 @@ get_full_image (GdkDrawable *drawable
return image;
}
+static void
+fill_solid_image (GdkDrawable *drawable,
+ GdkImage *image,
+ guint pixel,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ XImage *ximage = GDK_IMAGE_XIMAGE (image);
+
+ int i;
+ guchar *base;
+
+ /* Now fill in the image
+ */
+ for (i = 0; i < width; i++)
+ XPutPixel (ximage, x + i, y, pixel);
+
+ base = (guchar *)image->mem + y * image->bpl + x * image->bpp;
+
+ for (i = 1; i < height; i++)
+ memcpy (base + i * image->bpl, base, width * image->bpp);
+}
+
GdkImage*
_gdk_x11_copy_to_image (GdkDrawable *drawable,
GdkImage *image,
@@ -512,6 +537,7 @@ _gdk_x11_copy_to_image (GdkDrawable *
GdkDisplay *display;
Display *xdisplay;
gboolean have_grab;
+ gboolean have_trap;
GdkRectangle req;
GdkRectangle window_rect;
Pixmap shm_pixmap = None;
@@ -529,6 +555,7 @@ _gdk_x11_copy_to_image (GdkDrawable *
return NULL;
have_grab = FALSE;
+ have_trap = FALSE;
#define UNGRAB() G_STMT_START { \
if (have_grab) { \
@@ -537,6 +564,25 @@ _gdk_x11_copy_to_image (GdkDrawable *
have_grab = FALSE; } \
} G_STMT_END
+ if (impl->solid_region)
+ {
+ GdkRectangle r;
+
+ r.x = src_x; r.y = src_y; r.width = width; r.height = height;
+
+ if (gdk_region_rect_in (impl->solid_region, &r) == GDK_OVERLAP_RECTANGLE_IN)
+ {
+ if (!image)
+ image = _gdk_image_new_for_depth (impl->screen, GDK_IMAGE_NORMAL,
+ visual, width, height,
+ gdk_drawable_get_depth (drawable));
+
+ fill_solid_image (drawable, image, impl->solid_pixel, dest_x, dest_y, width, height);
+
+ return image;
+ }
+ }
+
if (!image && !GDK_IS_WINDOW_IMPL_X11 (drawable))
return get_full_image (drawable, src_x, src_y, width, height);
@@ -628,7 +674,8 @@ _gdk_x11_copy_to_image (GdkDrawable *
goto out;
gdk_error_trap_push ();
-
+ have_trap = TRUE;
+
if (!image &&
req.x == src_x && req.y == src_y && req.width == width && req.height == height)
{
@@ -674,7 +721,8 @@ _gdk_x11_copy_to_image (GdkDrawable *
XFlush (xdisplay);
have_grab = FALSE;
}
-
+
+ if (have_trap)
gdk_error_trap_pop ();
if (success && !image)
Index: x11/gdkpixmap-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkpixmap-x11.c,v
retrieving revision 1.57
diff -u -p -r1.57 gdkpixmap-x11.c
--- x11/gdkpixmap-x11.c 9 Dec 2002 23:34:49 -0000 1.57
+++ x11/gdkpixmap-x11.c 6 Mar 2003 16:59:40 -0000
@@ -208,6 +208,8 @@ gdk_pixmap_new (GdkDrawable *drawable,
pix_impl->height = height;
GDK_PIXMAP_OBJECT (pixmap)->depth = depth;
+ draw_impl->do_solid_colored = TRUE;
+
if (depth == window_depth)
{
cmap = gdk_drawable_get_colormap (drawable);
Index: x11/gdkprivate-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkprivate-x11.h,v
retrieving revision 1.27
diff -u -p -r1.27 gdkprivate-x11.h
--- x11/gdkprivate-x11.h 24 Sep 2002 20:20:03 -0000 1.27
+++ x11/gdkprivate-x11.h 6 Mar 2003 16:59:40 -0000
@@ -71,6 +71,7 @@ struct _GdkGCX11
XRenderColor fg_picture_color;
#endif
gulong fg_pixel;
+ gint line_width;
};
struct _GdkGCX11Class
@@ -90,6 +91,9 @@ struct _GdkVisualPrivate
GdkVisual visual;
Visual *xvisual;
GdkScreen *screen;
+
+ GdkDrawable *scratch_pixmap;
+ GdkGC *scratch_gc;
};
void _gdk_xid_table_insert (GdkDisplay *display,
@@ -168,6 +172,9 @@ gboolean _gdk_x11_display_is_root_window
void _gdk_x11_events_init_screen (GdkScreen *screen);
void _gdk_x11_events_uninit_screen (GdkScreen *screen);
+
+GdkGC *_gdk_x11_visual_get_scratch_gc (GdkVisual *visual);
+
void _gdk_events_init (GdkDisplay *display);
void _gdk_windowing_window_init (GdkScreen *screen);
Index: x11/gdkvisual-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkvisual-x11.c,v
retrieving revision 1.34
diff -u -p -r1.34 gdkvisual-x11.c
--- x11/gdkvisual-x11.c 6 Feb 2003 19:18:19 -0000 1.34
+++ x11/gdkvisual-x11.c 6 Mar 2003 16:59:40 -0000
@@ -663,3 +663,19 @@ gdk_visual_get_screen (GdkVisual *visual
return ((GdkVisualPrivate*) visual)->screen;
}
+
+GdkGC *
+_gdk_x11_visual_get_scratch_gc (GdkVisual *visual)
+{
+ GdkVisualPrivate *private = (GdkVisualPrivate *) visual;
+
+ if (!private->scratch_gc)
+ {
+ private->scratch_pixmap = gdk_pixmap_new (gdk_screen_get_root_window (private->screen),
+ 1, 1, visual->depth);
+ private->scratch_gc = gdk_gc_new (private->scratch_pixmap);
+ }
+
+ return private->scratch_gc;
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]