diff options
author | Owen Taylor <otaylor@redhat.com> | 2005-03-17 01:54:40 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2005-03-17 01:54:40 +0000 |
commit | 09d7eafb15099362c0ed611d775b1f2fe5f17f94 (patch) | |
tree | 288fc18e7d665e5e897409489e409c017efece2d /gdk | |
parent | eebd4f1c4bba4d1a2b9a5e0cfd9fd34f318ee84d (diff) | |
download | gtk+-09d7eafb15099362c0ed611d775b1f2fe5f17f94.tar.gz |
Switch set_cairo_target() virtual function to ref_cairo_surface()
2005-03-15 Owen Taylor <otaylor@redhat.com>
* gdk/gdkdrawable.h gdk/gdkdraw.c gdk/gdkpixmap.c gdk/gdkwindow.c
gdk/x11/gdkdrawable-x11.c gdk/x11/gdkpixmap-x11.c gdk/x11/gdkwindow-x11.c
gdk/gdkinternals.h: Switch set_cairo_target() virtual function to
ref_cairo_surface()
* gdk/gdkdrawable.h gdk/gdkdraw.h: Switch set_cairo_target() virtual
function to create_cairo_context()
* gdk/gdkwindow.c: Clear double buffer pixmaps with Cairo.
* gdk/x11/gdkwindow-x11.c: Keep all components in GdkWindowObject.bg_color,
not just the pixel.
* tests/testcairo.c: Update for create_cairo_context()
* gdk/gdkdraw.c (gdk_draw_trapezoids, gdk_draw_glyphs[_transformed]):
Reimplement in terms of Cairo, bypass the vtable entries.
* gdk/x11/gdkdrawable-x11.[ch] gdk/x11/gdkdisplay-x11.[ch]
gdk/x11/gdkgc-x11.c gdk/x11/gdkpango-x11.c
gdk/x11/gdkprivate-x11.h gdk/x11/Makefile.am: Remove
implementation of draw_trapezoids / draw_glyphs[_transformed].
* gdk/gdkpango.c: Switch GdkPangoRenderer to use Cairo
* gdk/gdkpango.c gdk/x11/gdkpango-x11.c: Move
gdk_pango_context_get_for_screen() into the backend independent code.
* gdk/x11/gdkdrawable-x11.[ch]: Remove Xft use, use RENDER directly
for drawing images.
* gdk/gdkdrawable.h gdk/x11/gdkdrawable-x11.c: Remove
gdk_draw_rectangle_alpha_libgtk_only.
* gdk/gdkpixbuf.h gdk/gdkpixbuf-render.c: Add
gdk_pixbuf_set_as_cairo_source()
* gdk/gdk.symbols: Update
* gtk/gtkcolorsel.c gtk/gtkhsv.c gtk/gtkiconview.c gtk/gtkruler.[ch]
gtk/gtk[hv]ruler.c: Convert to Cairo rendering.
* gtk/gtkstyle.c (gtk_default_draw_check, gtk_default_draw_focus,
gtk_default_draw_option): Switch to Cairo. Simplify the checkbutton,
radio button style for now to get something more scalable.
* gtk/gtksettings.c: #if 0 out the code to use PangoXft for hinting/
antialiasing/dpi settings.
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/gdk.symbols | 17 | ||||
-rw-r--r-- | gdk/gdkcolor.c | 18 | ||||
-rw-r--r-- | gdk/gdkcolor.h | 4 | ||||
-rw-r--r-- | gdk/gdkdraw.c | 401 | ||||
-rw-r--r-- | gdk/gdkdrawable.h | 14 | ||||
-rw-r--r-- | gdk/gdkinternals.h | 6 | ||||
-rw-r--r-- | gdk/gdkpango.c | 523 | ||||
-rw-r--r-- | gdk/gdkpixbuf-render.c | 108 | ||||
-rw-r--r-- | gdk/gdkpixbuf.h | 3 | ||||
-rw-r--r-- | gdk/gdkpixmap.c | 13 | ||||
-rw-r--r-- | gdk/gdkwindow.c | 110 | ||||
-rw-r--r-- | gdk/x11/Makefile.am | 1 | ||||
-rw-r--r-- | gdk/x11/gdkdisplay-x11.c | 1 | ||||
-rw-r--r-- | gdk/x11/gdkdisplay-x11.h | 1 | ||||
-rw-r--r-- | gdk/x11/gdkdrawable-x11.c | 450 | ||||
-rw-r--r-- | gdk/x11/gdkdrawable-x11.h | 14 | ||||
-rw-r--r-- | gdk/x11/gdkgc-x11.c | 371 | ||||
-rw-r--r-- | gdk/x11/gdkpango-x11.c | 174 | ||||
-rw-r--r-- | gdk/x11/gdkpixmap-x11.c | 10 | ||||
-rw-r--r-- | gdk/x11/gdkprivate-x11.h | 9 | ||||
-rw-r--r-- | gdk/x11/gdkwindow-x11.c | 18 |
21 files changed, 674 insertions, 1592 deletions
diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols index 2b7b7df049..07b1412042 100644 --- a/gdk/gdk.symbols +++ b/gdk/gdk.symbols @@ -301,6 +301,7 @@ gdk_color_equal gdk_color_free gdk_color_get_type G_GNUC_CONST gdk_color_hash +gdk_cairo_set_source_color gdk_colormap_alloc_color gdk_colormap_get_system gdk_colormap_get_visual @@ -497,7 +498,7 @@ gdk_drag_get_protocol #if IN_HEADER(__GDK_DRAWABLE_H__) #if IN_FILE(__GDK_DRAW_C__) -gdk_drawable_set_cairo_target +gdk_drawable_create_cairo_context gdk_drawable_copy_to_image gdk_drawable_get_clip_region gdk_drawable_get_colormap @@ -537,12 +538,6 @@ gdk_draw_trapezoids #endif #if IN_HEADER(__GDK_DRAWABLE_H__) -#if IN_FILE(__GDK_DRAWABLE_X11_C__) -gdk_draw_rectangle_alpha_libgtk_only -#endif -#endif - -#if IN_HEADER(__GDK_DRAWABLE_H__) #if IN_FILE(__GDK_PANGO_C__) gdk_draw_layout gdk_draw_layout_line @@ -818,6 +813,7 @@ gdk_net_wm_supports gdk_pango_attr_embossed_new gdk_pango_attr_stipple_new gdk_pango_context_get +gdk_pango_context_get_for_screen #ifndef GDK_DISABLE_DEPRECATED gdk_pango_context_set_colormap #endif @@ -833,12 +829,6 @@ gdk_pango_renderer_set_stipple #endif #endif -#if IN_HEADER(__GDK_PANGO_H__) -#if IN_FILE(__GDK_PANGO_X11_C__) -gdk_pango_context_get_for_screen -#endif -#endif - #if IN_HEADER(__GDK_PIXBUF_H__) #if IN_FILE(__GDK_PIXBUF_DRAWABLE_C__) gdk_pixbuf_get_from_drawable @@ -851,6 +841,7 @@ gdk_pixbuf_get_from_image gdk_pixbuf_render_pixmap_and_mask gdk_pixbuf_render_pixmap_and_mask_for_colormap gdk_pixbuf_render_threshold_alpha +gdk_pixbuf_set_as_cairo_source #ifndef GDK_DISABLE_DEPRECATED gdk_pixbuf_render_to_drawable gdk_pixbuf_render_to_drawable_alpha diff --git a/gdk/gdkcolor.c b/gdk/gdkcolor.c index d2a4a55cab..f33ff790c4 100644 --- a/gdk/gdkcolor.c +++ b/gdk/gdkcolor.c @@ -371,5 +371,23 @@ gdk_colormap_get_system (void) return gdk_screen_get_system_colormap (gdk_screen_get_default ()); } +/** + * gdk_cairo_set_source_color: + * @cr: a #cairo_t + * @color: a #GdkColor + * + * Convenience function to set the specified GdkColor as the + * source color of the given Cairo context. + **/ +void +gdk_cairo_set_source_color (cairo_t *cr, + GdkColor *color) +{ + cairo_set_rgb_color (cr, + color->red / 65535., + color->green / 65535., + color->blue / 65535.); +} + #define __GDK_COLOR_C__ #include "gdkaliasdef.c" diff --git a/gdk/gdkcolor.h b/gdk/gdkcolor.h index 8754c3cd9f..df4e2ffc8c 100644 --- a/gdk/gdkcolor.h +++ b/gdk/gdkcolor.h @@ -1,6 +1,7 @@ #ifndef __GDK_COLOR_H__ #define __GDK_COLOR_H__ +#include <cairo.h> #include <gdk/gdktypes.h> #ifdef __cplusplus @@ -111,6 +112,9 @@ gboolean gdk_color_equal (const GdkColor *colora, GType gdk_color_get_type (void) G_GNUC_CONST; +void gdk_cairo_set_source_color (cairo_t *cr, + GdkColor *color); + /* The following functions are deprecated */ #ifndef GDK_DISABLE_DEPRECATED void gdk_colors_store (GdkColormap *colormap, diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c index b8a653d433..c5bd2d8b62 100644 --- a/gdk/gdkdraw.c +++ b/gdk/gdkdraw.c @@ -26,6 +26,7 @@ #include <config.h> #include <math.h> +#include <pango/pangocairo.h> #include "gdkdrawable.h" #include "gdkinternals.h" #include "gdkwindow.h" @@ -59,10 +60,6 @@ static void gdk_drawable_real_draw_pixbuf (GdkDrawable *draw GdkRgbDither dither, gint x_dither, gint y_dither); -static void gdk_drawable_real_draw_trapezoids (GdkDrawable *drawable, - GdkGC *gc, - GdkTrapezoid *trapezoids, - gint n_trapezoids); static void gdk_drawable_class_init (GdkDrawableClass *klass); @@ -104,7 +101,6 @@ gdk_drawable_class_init (GdkDrawableClass *klass) klass->get_clip_region = gdk_drawable_real_get_visible_region; klass->get_visible_region = gdk_drawable_real_get_visible_region; klass->draw_pixbuf = gdk_drawable_real_draw_pixbuf; - klass->draw_trapezoids = gdk_drawable_real_draw_trapezoids; } /* Manipulation of drawables @@ -872,6 +868,43 @@ gdk_draw_lines (GdkDrawable *drawable, GDK_DRAWABLE_GET_CLASS (drawable)->draw_lines (drawable, gc, points, npoints); } +static void +real_draw_glyphs (GdkDrawable *drawable, + GdkGC *gc, + PangoMatrix *matrix, + PangoFont *font, + gdouble x, + gdouble y, + PangoGlyphString *glyphs) +{ + GdkColor color; + cairo_t *cr; + + cr = gdk_drawable_create_cairo_context (drawable); + + _gdk_windowing_gc_get_foreground (gc, &color); + gdk_cairo_set_source_color (cr, &color); + + if (matrix) + { + cairo_matrix_t *cairo_matrix; + + cairo_matrix = cairo_matrix_create (); + cairo_matrix_set_affine (cairo_matrix, + matrix->xx, matrix->yx, + matrix->xy, matrix->yy, + matrix->x0, matrix->y0); + + cairo_set_matrix (cr, cairo_matrix); + cairo_matrix_destroy (cairo_matrix); + } + + cairo_move_to (cr, x, y); + pango_cairo_show_glyph_string (cr, font, glyphs); + + cairo_destroy (cr); +} + /** * gdk_draw_glyphs: * @drawable: a #GdkDrawable @@ -901,9 +934,9 @@ gdk_draw_glyphs (GdkDrawable *drawable, { g_return_if_fail (GDK_IS_DRAWABLE (drawable)); g_return_if_fail (GDK_IS_GC (gc)); - - - GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs (drawable, gc, font, x, y, glyphs); + + real_draw_glyphs (drawable, gc, NULL, font, + x, y, glyphs); } /** @@ -941,9 +974,8 @@ gdk_draw_glyphs_transformed (GdkDrawable *drawable, g_return_if_fail (GDK_IS_DRAWABLE (drawable)); g_return_if_fail (GDK_IS_GC (gc)); - if (GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs_transformed) - GDK_DRAWABLE_GET_CLASS (drawable)->draw_glyphs_transformed (drawable, gc, matrix, - font, x, y, glyphs); + real_draw_glyphs (drawable, gc, matrix, font, + x / PANGO_SCALE, y / PANGO_SCALE, glyphs); } /** @@ -967,12 +999,31 @@ gdk_draw_trapezoids (GdkDrawable *drawable, GdkTrapezoid *trapezoids, gint n_trapezoids) { + GdkColor color; + cairo_t *cr; + int i; + g_return_if_fail (GDK_IS_DRAWABLE (drawable)); g_return_if_fail (GDK_IS_GC (gc)); g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL); - GDK_DRAWABLE_GET_CLASS (drawable)->draw_trapezoids (drawable, gc, - trapezoids, n_trapezoids); + cr = gdk_drawable_create_cairo_context (drawable); + + _gdk_windowing_gc_get_foreground (gc, &color); + gdk_cairo_set_source_color (cr, &color); + + for (i = 0; i < n_trapezoids; i++) + { + cairo_move_to (cr, trapezoids[i].x11, trapezoids[i].y1); + cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y1); + cairo_line_to (cr, trapezoids[i].x22, trapezoids[i].y2); + cairo_line_to (cr, trapezoids[i].x21, trapezoids[i].y2); + cairo_close_path (cr); + } + + cairo_fill (cr); + + cairo_destroy (cr); } /** @@ -1222,26 +1273,50 @@ gdk_drawable_real_get_visible_region (GdkDrawable *drawable) } /** - * gdk_drawable_set_cairo_target: + * _gdk_drawable_ref_cairo_surface: + * @drawable: a #GdkDrawable + * + * Obtains a #cairo_surface_t for the given drawable. If a + * #cairo_surface_t for the drawable already exists, it will be + * referenced, otherwise a new surface will be created. + * + * Return value: a newly referenced #cairo_surface_t that points + * to @drawable. Unref with cairo_surface_destroy() + **/ +cairo_surface_t * +_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable) +{ + g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL); + + return GDK_DRAWABLE_GET_CLASS (drawable)->ref_cairo_surface (drawable); +} + +/** + * gdk_drawable_create_cairo_context: * @drawable: a #GdkDrawable - * @cr: a cairo context * - * Sets the given drawable as the target surface for a Cairo context. - * Note that when @drawable is a window and gdk_window_begin_paint() - * has been called, the target surface will be set to the temporary - * backing pixmap, so you can only use the Cairo context until - * the matching call to gdk_window_end_paint(). + * Creates a Cairo context for drawing to @drawable. * + * Return value: A newly created Cairo context. Free with + * cairo_destroy() when you are done drawing. + * * Since: 2.10 **/ -void -gdk_drawable_set_cairo_target (GdkDrawable *drawable, - cairo_t *cr) +cairo_t * +gdk_drawable_create_cairo_context (GdkDrawable *drawable) { - g_return_if_fail (GDK_IS_DRAWABLE (drawable)); - g_return_if_fail (cr != NULL); + cairo_surface_t *surface; + cairo_t *cr; + + g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL); + + cr = cairo_create (); - return GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_target (drawable, cr); + surface = _gdk_drawable_ref_cairo_surface (drawable); + if (surface) + cairo_set_target_surface (cr, surface); + + return cr; } static void @@ -1633,280 +1708,6 @@ gdk_drawable_real_draw_pixbuf (GdkDrawable *drawable, /************************************************************************/ -/* Fallback rendering code for anti-aliased trapezoids. Note that this code - * is cut-and-pasted (with the substitution of GdkPixbuf for FT_Bitmap) between - * here and pangoft2-render.c. - */ -typedef struct { - double y; - double x1; - double x2; -} Position; - -static void -draw_simple_trap (GdkPixbuf *pixbuf, - int pixbuf_x, - int pixbuf_y, - Position *t, - Position *b) -{ - guchar *pixels = gdk_pixbuf_get_pixels (pixbuf); - int rowstride = gdk_pixbuf_get_rowstride (pixbuf); - int pixbuf_width = gdk_pixbuf_get_width (pixbuf); - int pixbuf_height = gdk_pixbuf_get_height (pixbuf); - int iy = floor (t->y); - int x1, x2, x; - double dy = b->y - t->y; - guchar *dest; - - if (iy < pixbuf_y || iy >= pixbuf_y + pixbuf_height) - return; - - if (t->x1 < b->x1) - x1 = floor (t->x1); - else - x1 = floor (b->x1); - - if (t->x2 > b->x2) - x2 = ceil (t->x2); - else - x2 = ceil (b->x2); - - x1 = CLAMP (x1, pixbuf_x, pixbuf_x + pixbuf_width); - x2 = CLAMP (x2, pixbuf_x, pixbuf_x + pixbuf_width); - - dest = pixels + (iy - pixbuf_y) * rowstride + (x1 - pixbuf_x) * 4; - - for (x = x1; x < x2; x++, dest += 4) - { - double top_left = MAX (t->x1, x); - double top_right = MIN (t->x2, x + 1); - double bottom_left = MAX (b->x1, x); - double bottom_right = MIN (b->x2, x + 1); - double c = 0.5 * dy * ((top_right - top_left) + (bottom_right - bottom_left)); - - /* When converting to [0,255], we round up. This is intended - * to prevent the problem of pixels that get divided into - * multiple slices not being fully black. - */ - int ic = c * 256; - - /* We already set the entire buffer to the destination color */ - dest[3] = MIN (dest[3] + ic, 255); - } -} - -static void -interpolate_position (Position *result, - Position *top, - Position *bottom, - double val, - double val1, - double val2) -{ - result->y = (top->y * (val2 - val) + bottom->y * (val - val1)) / (val2 - val1); - result->x1 = (top->x1 * (val2 - val) + bottom->x1 * (val - val1)) / (val2 - val1); - result->x2 = (top->x2 * (val2 - val) + bottom->x2 * (val - val1)) / (val2 - val1); -} - -/* This draws a trapezoid with the parallel sides aligned with - * the X axis. We do this by subdividing the trapezoid vertically - * into thin slices (themselves trapezoids) where two edge sides are each - * contained within a single pixel and then rasterizing each - * slice. There are frequently multiple slices within a single - * line so we have to accumulate to get the final result. - */ -static void -draw_trapezoid (GdkPixbuf *pixbuf, - int pixbuf_x, - int pixbuf_y, - GdkTrapezoid *trapezoid) -{ - Position pos; - Position t; - Position b; - gboolean done = FALSE; - - if (trapezoid->y1 == trapezoid->y2) - return; - - pos.y = t.y = trapezoid->y1; - pos.x1 = t.x1 = trapezoid->x11; - pos.x2 = t.x2 = trapezoid->x21; - b.y = trapezoid->y2; - b.x1 = trapezoid->x12; - b.x2 = trapezoid->x22; - - while (!done) - { - Position pos_next; - double y_next, x1_next, x2_next; - double ix1, ix2; - - /* The algorithm here is written to emphasize simplicity and - * numerical stability as opposed to speed. - * - * While the end result is slicing up the polygon vertically, - * conceptually we aren't walking in the X direction, rather we - * are walking along the edges. When we compute crossing of - * horizontal pixel boundaries, we use the X coordinate as the - * interpolating variable, when we compute crossing for vertical - * pixel boundaries, we use the Y coordinate. - * - * This allows us to handle almost exactly horizontal edges without - * running into difficulties. (Almost exactly horizontal edges - * come up frequently due to inexactness in computing, say, - * a 90 degree rotation transformation) - */ - - pos_next = b; - done = TRUE; - - /* Check for crossing vertical pixel boundaries */ - y_next = floor (pos.y) + 1; - if (y_next < pos_next.y) - { - interpolate_position (&pos_next, &t, &b, - y_next, t.y, b.y); - pos_next.y = y_next; - done = FALSE; - } - - /* Check left side for crossing horizontal pixel boundaries */ - ix1 = floor (pos.x1); - - if (b.x1 < t.x1) - { - if (ix1 == pos.x1) - x1_next = ix1 - 1; - else - x1_next = ix1; - - if (x1_next > pos_next.x1) - { - interpolate_position (&pos_next, &t, &b, - x1_next, t.x1, b.x1); - pos_next.x1 = x1_next; - done = FALSE; - } - } - else if (b.x1 > t.x1) - { - x1_next = ix1 + 1; - - if (x1_next < pos_next.x1) - { - interpolate_position (&pos_next, &t, &b, - x1_next, t.x1, b.x1); - pos_next.x1 = x1_next; - done = FALSE; - } - } - - /* Check right side for crossing horizontal pixel boundaries */ - ix2 = floor (pos.x2); - - if (b.x2 < t.x2) - { - if (ix2 == pos.x2) - x2_next = ix2 - 1; - else - x2_next = ix2; - - if (x2_next > pos_next.x2) - { - interpolate_position (&pos_next, &t, &b, - x2_next, t.x2, b.x2); - pos_next.x2 = x2_next; - done = FALSE; - } - } - else if (trapezoid->x22 > trapezoid->x21) - { - x2_next = ix2 + 1; - - if (x2_next < pos_next.x2) - { - interpolate_position (&pos_next, &t, &b, - x2_next, t.x2, b.x2); - pos_next.x2 = x2_next; - done = FALSE; - } - } - - draw_simple_trap (pixbuf, pixbuf_x, pixbuf_y, &pos, &pos_next); - pos = pos_next; - } -} - -static void -gdk_drawable_real_draw_trapezoids (GdkDrawable *drawable, - GdkGC *gc, - GdkTrapezoid *trapezoids, - gint n_trapezoids) -{ - GdkPixbuf *pixbuf; - double min_x, max_x, min_y, max_y; - int x, y, width, height; - GdkColor color; - int i; - - if (n_trapezoids == 0) - return; - - /* compute bounding box */ - - min_x = max_x = trapezoids[0].x11; - min_y = max_y = trapezoids[0].y1; - - for (i = 0; i < n_trapezoids; i++) - { - if (trapezoids[i].x11 < min_x) min_x = trapezoids[i].x11; - if (trapezoids[i].x21 > max_x) max_x = trapezoids[i].x21; - if (trapezoids[i].x12 < min_x) min_x = trapezoids[i].x12; - if (trapezoids[i].x22 > max_x) max_x = trapezoids[i].x22; - if (trapezoids[i].y1 < min_y) min_y = trapezoids[i].y1; - if (trapezoids[i].y2 > max_y) max_y = trapezoids[i].y2; - } - - /* allocate temporary pixbuf */ - - x = floor (min_x); - width = ceil (max_x) - x; - y = floor (min_y); - height = ceil (max_y) - y; - - if (width == 0 || height == 0) - return; - - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height); - if (!pixbuf) - return; - - /* Fill the pixbuf with the foreground color and alpha 0 */ - - _gdk_windowing_gc_get_foreground (gc, &color); - gdk_pixbuf_fill (pixbuf, - (((color.red & 0xff00) << 16) | - ((color.green & 0xff00) << 8) | - ((color.blue & 0xff00)))); - - /* draw the trapezoids into the alpha channel */ - - for (i = 0; i < n_trapezoids; i++) - draw_trapezoid (pixbuf, x, y, &trapezoids[i]); - - /* composite that onto the drawable */ - - gdk_draw_pixbuf (drawable, gc, pixbuf, - 0, 0, x, y, width, height, - GDK_RGB_DITHER_NORMAL, 0, 0); - - g_object_unref (pixbuf); -} - -/************************************************************************/ - /** * _gdk_drawable_get_scratch_gc: * @drawable: A #GdkDrawable diff --git a/gdk/gdkdrawable.h b/gdk/gdkdrawable.h index 612ce694fd..19344954f1 100644 --- a/gdk/gdkdrawable.h +++ b/gdk/gdkdrawable.h @@ -170,8 +170,7 @@ struct _GdkDrawableClass GdkTrapezoid *trapezoids, gint n_trapezoids); - void (*set_cairo_target) (GdkDrawable *drawable, - cairo_t *cr); + cairo_surface_t *(*ref_cairo_surface) (GdkDrawable *drawable); /* Padding for future expansion */ void (*_gdk_reserved4) (void); @@ -392,16 +391,7 @@ GdkImage *gdk_drawable_copy_to_image (GdkDrawable *drawable, GdkRegion *gdk_drawable_get_clip_region (GdkDrawable *drawable); GdkRegion *gdk_drawable_get_visible_region (GdkDrawable *drawable); -void gdk_drawable_set_cairo_target (GdkDrawable *drawable, - cairo_t *cr); - -gboolean gdk_draw_rectangle_alpha_libgtk_only (GdkDrawable *drawable, - gint x, - gint y, - gint width, - gint height, - GdkColor *color, - guint16 alpha); +cairo_t *gdk_drawable_create_cairo_context (GdkDrawable *drawable); #ifdef __cplusplus } diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index 19667da3b5..8aee134d02 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -210,6 +210,8 @@ GdkImage *_gdk_drawable_copy_to_image (GdkDrawable *drawable, gint width, gint height); +cairo_surface_t *_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable); + /* GC caching */ GdkGC *_gdk_drawable_get_scratch_gc (GdkDrawable *drawable, gboolean graphics_exposures); @@ -260,6 +262,10 @@ void _gdk_windowing_window_clear_area_e (GdkWindow *window, gint width, gint height); +void _gdk_windowing_set_surface_device_offset (cairo_surface_t *surface, + gint x_offset, + gint y_offset); + void _gdk_windowing_get_pointer (GdkDisplay *display, GdkScreen **screen, gint *x, diff --git a/gdk/gdkpango.c b/gdk/gdkpango.c index d317b0faab..c94f58d724 100644 --- a/gdk/gdkpango.c +++ b/gdk/gdkpango.c @@ -19,8 +19,10 @@ #include <config.h> #include <math.h> +#include <pango/pangocairo.h> #include "gdkcolor.h" #include "gdkgc.h" +#include "gdkinternals.h" #include "gdkpango.h" #include "gdkrgb.h" #include "gdkprivate.h" @@ -47,34 +49,17 @@ struct _GdkPangoRendererPrivate gboolean override_color_set[MAX_RENDER_PART + 1]; GdkBitmap *stipple[MAX_RENDER_PART + 1]; + cairo_surface_t *stipple_surface[MAX_RENDER_PART + 1]; gboolean embossed; - /* When switching between the normal and shadow copies when - * drawing shadows we can get unexpected recursion into the - * drawing functions; the 'in_emboss' flag guards against that. - */ - gboolean in_emboss; - /* Current target */ GdkDrawable *drawable; GdkGC *base_gc; - - /* Cached GC, derived from base_gc */ - GdkGC *gc; - PangoColor gc_color; - gboolean gc_color_set; - GdkBitmap *gc_stipple; - - /* we accumulate trapezoids for the same PangoRenderPart */ - GArray *trapezoids; - PangoRenderPart trapezoid_part; }; static PangoAttrType gdk_pango_attr_stipple_type; static PangoAttrType gdk_pango_attr_embossed_type; -static void flush_trapezoids (GdkPangoRenderer *gdk_renderer); - enum { PROP_0, PROP_SCREEN @@ -89,21 +74,19 @@ gdk_pango_renderer_finalize (GObject *object) GdkPangoRendererPrivate *priv = gdk_renderer->priv; int i; - if (priv->gc) - g_object_unref (priv->gc); - if (priv->gc_stipple) - g_object_unref (priv->gc_stipple); if (priv->base_gc) g_object_unref (priv->base_gc); if (priv->drawable) g_object_unref (priv->drawable); for (i = 0; i <= MAX_RENDER_PART; i++) + if (priv->stipple_surface[i]) + cairo_surface_destroy (priv->stipple_surface[i]); + + for (i = 0; i <= MAX_RENDER_PART; i++) if (priv->stipple[i]) g_object_unref (priv->stipple[i]); - g_array_free (priv->trapezoids, TRUE); - G_OBJECT_CLASS (gdk_pango_renderer_parent_class)->finalize (object); } @@ -130,154 +113,138 @@ gdk_pango_renderer_constructor (GType type, return object; } -/* Adjusts matrix and color for the renderer to draw the secondar +/* Adjusts matrix and color for the renderer to draw the secondary * "shadow" copy for embossed text */ static void -emboss_renderer (PangoRenderer *renderer, - PangoRenderPart part, - PangoMatrix **save_matrix, - PangoColor **save_color) +emboss_context (cairo_t *cr) { - GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv; - static const PangoColor white = { 0xffff, 0xffff, 0xffff }; - PangoMatrix tmp_matrix = PANGO_MATRIX_INIT; + cairo_matrix_t *tmp_matrix = cairo_matrix_create (); + double a, b, c, d, tx, ty; - priv->in_emboss = TRUE; - - *save_color = pango_renderer_get_color (renderer, part); - if (*save_color) - *save_color = pango_color_copy (*save_color); - - *save_matrix = renderer->matrix; - if (*save_matrix) - { - *save_matrix = pango_matrix_copy (*save_matrix); - tmp_matrix = **save_matrix; - } - /* The gymnastics here to adjust the matrix are because we want * to offset by +1,+1 in device-space, not in user-space, * so we can't just draw the layout at x + 1, y + 1 */ - tmp_matrix.x0 += 1; - tmp_matrix.y0 += 1; - - pango_renderer_set_matrix (renderer, &tmp_matrix); - pango_renderer_set_color (renderer, part, &white); + cairo_get_matrix (cr, tmp_matrix); + cairo_matrix_get_affine (tmp_matrix, &a, &b, &c, &d, &tx, &ty); + cairo_matrix_set_affine (tmp_matrix, a, b, c, d, tx + 1, ty + 1); + cairo_set_matrix (cr, tmp_matrix); + cairo_matrix_destroy (tmp_matrix); + + cairo_set_rgb_color (cr, 1.0, 1.0, 1.0); } -/* Restores from emboss_renderer() */ static void -unemboss_renderer (PangoRenderer *renderer, - PangoRenderPart part, - PangoMatrix **save_matrix, - PangoColor **save_color) +set_part_color (GdkPangoRenderer *gdk_renderer, + cairo_t *cr, + PangoRenderPart part) { - GdkPangoRendererPrivate *priv = GDK_PANGO_RENDERER(renderer)->priv; - pango_renderer_set_matrix (renderer, *save_matrix); - pango_renderer_set_color (renderer, part, *save_color); - - if (*save_matrix) - pango_matrix_free (*save_matrix); - if (*save_color) - pango_color_free (*save_color); - - priv->in_emboss = FALSE; + PangoColor *color = pango_renderer_get_color (PANGO_RENDERER (gdk_renderer), + part); + if (color) + { + cairo_set_rgb_color (cr, + color->red / 65535., + color->green / 65535., + color->blue / 65535.); + } + else + { + GdkColor gc_color; + + _gdk_windowing_gc_get_foreground (gdk_renderer->priv->base_gc, &gc_color); + gdk_cairo_set_source_color (cr, &gc_color); + } } -/* Gets the GC for drawing @part. This make involve copying the base GC - * for the renderer, in which case we keep a one-GC cache. */ -static GdkGC * -get_gc (GdkPangoRenderer *gdk_renderer, - PangoRenderPart part) +static cairo_surface_t * +get_stipple_surface (GdkPangoRenderer *gdk_renderer, + cairo_t *cr, + PangoRenderPart part) { - PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer); - PangoColor *color; - GdkBitmap *stipple; - GdkPangoRendererPrivate *priv = gdk_renderer->priv; + if (!gdk_renderer->priv->stipple_surface[part]) + { + cairo_t *tmp_cr; + cairo_surface_t *surface; + cairo_surface_t *alpha_surface; + gint width, height; - color = pango_renderer_get_color (renderer, part); + gdk_drawable_get_size (gdk_renderer->priv->stipple[part], + &width, &height); - if (part <= MAX_RENDER_PART) - stipple = priv->stipple[part]; - else - stipple = NULL; + alpha_surface = _gdk_drawable_ref_cairo_surface (gdk_renderer->priv->stipple[part]); - if (!color && !stipple) /* nothing override, use base_gc */ - return priv->base_gc; - else - { - gboolean new_stipple = FALSE; - gboolean new_color = FALSE; + surface = cairo_surface_create_similar (cairo_get_target_surface (cr), + CAIRO_FORMAT_ARGB32, + width, height); + + tmp_cr = cairo_create (); + cairo_set_target_surface (tmp_cr, surface); + + cairo_set_operator (tmp_cr, CAIRO_OPERATOR_SRC); + cairo_show_surface (tmp_cr, alpha_surface, width, height); - if (stipple != priv->gc_stipple) - new_stipple = TRUE; - - if ((priv->gc_color_set && !color) || - (!priv->gc_color_set && color) || - priv->gc_color.red != color->red || - priv->gc_color.green != color->green || - priv->gc_color.blue != color->blue) - new_color = TRUE; + set_part_color (gdk_renderer, tmp_cr, part); + cairo_set_operator (tmp_cr, CAIRO_OPERATOR_OVER); - if (!priv->gc) - { - priv->gc = gdk_gc_new (priv->drawable); - gdk_gc_copy (priv->gc, priv->base_gc); - } - else if (new_color && priv->gc_color_set && !color) - { - /* We have to recopy the original GC onto the cached GC - * to get the default color */ - new_stipple = TRUE; - gdk_gc_copy (priv->gc, priv->base_gc); - } - else if (new_stipple && priv->gc_stipple && !stipple) - { - /* Similarly, we need to make a new copy to restore to the - * default stipple state (the caller may have set a stipple - * on the GC, and even if not, gdk_gc_set_stipple (gc, NULL) - * doesn't work currently to restore to the default X stipple) */ - new_color = TRUE; - gdk_gc_copy (priv->gc, priv->base_gc); - } + cairo_rectangle (tmp_cr, 0, 0, width, height); + cairo_fill (tmp_cr); - if (new_color) - { - if (color) - { - GdkColor gdk_color; + cairo_destroy (tmp_cr); + cairo_surface_destroy (alpha_surface); + } +} - gdk_color.red = color->red; - gdk_color.green = color->green; - gdk_color.blue = color->blue; - - gdk_gc_set_rgb_fg_color (priv->gc, &gdk_color); +static cairo_t * +create_cairo_context (GdkPangoRenderer *gdk_renderer, + PangoRenderPart part) +{ + PangoRenderer *renderer = PANGO_RENDERER (gdk_renderer); + const PangoMatrix *matrix; + cairo_t *cr = gdk_drawable_create_cairo_context (gdk_renderer->priv->drawable); - priv->gc_color = *color; - priv->gc_color_set = TRUE; - } - else - priv->gc_color_set = FALSE; - } + if (gdk_renderer->priv->stipple[part]) + { + cairo_surface_t *surface = get_stipple_surface (gdk_renderer, cr, part); + cairo_pattern_t *pattern; - if (new_stipple) - { - if (priv->gc_stipple) - g_object_unref (priv->gc_stipple); + pattern = cairo_pattern_create_for_surface (surface); - if (stipple) - { - gdk_gc_set_stipple (priv->gc, stipple); - gdk_gc_set_fill (priv->gc, GDK_STIPPLED); - priv->gc_stipple = g_object_ref (stipple); - } - else - priv->gc_stipple = NULL; + if (gdk_renderer->priv->base_gc->ts_x_origin != 0 || + gdk_renderer->priv->base_gc->ts_y_origin != 0) + { + cairo_matrix_t *matrix = cairo_matrix_create (); + cairo_matrix_translate (matrix, + - gdk_renderer->priv->base_gc->ts_x_origin, + - gdk_renderer->priv->base_gc->ts_y_origin); + cairo_pattern_set_matrix (pattern, matrix); + cairo_matrix_destroy (matrix); } - return priv->gc; + cairo_set_pattern (cr, pattern); + cairo_pattern_destroy (pattern); } + else + { + set_part_color (gdk_renderer, cr, part); + } + + matrix = pango_renderer_get_matrix (renderer); + if (matrix) + { + cairo_matrix_t *cairo_matrix; + + cairo_matrix = cairo_matrix_create (); + cairo_matrix_set_affine (cairo_matrix, + matrix->xx, matrix->yx, + matrix->xy, matrix->yy, + matrix->x0, matrix->y0); + + cairo_set_matrix (cr, cairo_matrix); + cairo_matrix_destroy (cairo_matrix); + } + + return cr; } static void @@ -289,86 +256,104 @@ gdk_pango_renderer_draw_glyphs (PangoRenderer *renderer, { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); GdkPangoRendererPrivate *priv = gdk_renderer->priv; + cairo_t *cr; - flush_trapezoids (gdk_renderer); + cr = create_cairo_context (gdk_renderer, + PANGO_RENDER_PART_FOREGROUND); - if (!priv->in_emboss && priv->embossed) + if (priv->embossed) { - PangoMatrix *save_matrix; - PangoColor *save_color; - - emboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color); - gdk_draw_glyphs_transformed (priv->drawable, - get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND), - renderer->matrix, font, x, y, glyphs); - unemboss_renderer (renderer, PANGO_RENDER_PART_FOREGROUND, &save_matrix, &save_color); + cairo_save (cr); + emboss_context (cr); + cairo_move_to (cr, x / PANGO_SCALE, y / PANGO_SCALE); + pango_cairo_show_glyph_string (cr, font, glyphs); + cairo_restore (cr); } - - gdk_draw_glyphs_transformed (priv->drawable, - get_gc (gdk_renderer, PANGO_RENDER_PART_FOREGROUND), - renderer->matrix, font, x, y, glyphs); + + cairo_move_to (cr, x / PANGO_SCALE, y / PANGO_SCALE); + pango_cairo_show_glyph_string (cr, font, glyphs); + + cairo_destroy (cr); } -/* Outputs any pending trapezoids, we do this when the part or - * part color changes, when we are about to draw text, etc. */ -static void -flush_trapezoids (GdkPangoRenderer *gdk_renderer) -{ - GdkPangoRendererPrivate *priv = gdk_renderer->priv; - - if (!priv->trapezoids || priv->trapezoids->len == 0) - return; - - gdk_draw_trapezoids (priv->drawable, - get_gc (gdk_renderer, priv->trapezoid_part), - (GdkTrapezoid *)priv->trapezoids->data, - priv->trapezoids->len); - - g_array_set_size (priv->trapezoids, 0); -} +/* Draws an error underline that looks like one of: + * H E H + * /\ /\ /\ /\ /\ - + * A/ \ / \ / \ A/ \ / \ | + * \ \ / \ / /D \ \ / \ | + * \ \/ C \/ / \ \/ C \ | height = HEIGHT_SQUARES * square + * \ /\ F / \ F /\ \ | + * \ / \ / \ / \ \G | + * \ / \ / \ / \ / | + * \/ \/ \/ \/ - + * B B + * |----| + * unit_width = (HEIGHT_SQUARES - 1) * square + * + * The x, y, width, height passed in give the desired bounding box; + * x/width are adjusted to make the underline a integer number of units + * wide. + */ +#define HEIGHT_SQUARES 2.5 -/* Draws a single trapezoid ... we don't draw it immediately, but rather - * cache it to join together with other trapezoids that form part of the - * same logical shape */ static void -gdk_pango_renderer_draw_trapezoid (PangoRenderer *renderer, - PangoRenderPart part, - double y1, - double x11, - double x21, - double y2, - double x12, - double x22) +draw_error_underline (cairo_t *cr, + double x, + double y, + double width, + double height) { - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - GdkTrapezoid trap; + double square = height / HEIGHT_SQUARES; + double unit_width = (HEIGHT_SQUARES - 1) * square; + int width_units = (width + unit_width / 2) / unit_width; + double y_top, y_bottom; + int i; - if (!gdk_renderer->priv->trapezoids) - gdk_renderer->priv->trapezoids = g_array_new (FALSE, FALSE, - sizeof (GdkTrapezoid)); + x += (width - width_units * unit_width); + width = width_units * unit_width; + + y_top = y; + y_bottom = y + height; - if (gdk_renderer->priv->trapezoids->len > 0 && - gdk_renderer->priv->trapezoid_part != part) - flush_trapezoids (gdk_renderer); + /* Bottom of squiggle */ + cairo_move_to (cr, x - square / 2, y_top + square / 2); /* A */ + for (i = 0; i < width_units; i += 2) + { + double x_middle = x + (i + 1) * unit_width; + double x_right = x + (i + 2) * unit_width; + + cairo_line_to (cr, x_middle, y_bottom); /* B */ + + if (i + 1 == width_units) + /* Nothing */; + else if (i + 2 == width_units) + cairo_line_to (cr, x_right + square / 2, y_top + square / 2); /* D */ + else + cairo_line_to (cr, x_right, y_top + square); /* C */ + } - gdk_renderer->priv->trapezoid_part = part; - - trap.y1 = y1; - trap.x11 = x11; - trap.x21 = x21; - trap.y2 = y2; - trap.x12 = x12; - trap.x22 = x22; + /* Top of squiggle */ + for (i -= 2; i >= 0; i -= 2) + { + double x_left = x + i * unit_width; + double x_middle = x + (i + 1) * unit_width; + double x_right = x + (i + 2) * unit_width; + + if (i + 1 == width_units) + cairo_line_to (cr, x_middle + square / 2, y_bottom - square / 2); /* G */ + else { + if (i + 2 == width_units) + cairo_line_to (cr, x_right, y_top); /* E */ + cairo_line_to (cr, x_middle, y_bottom - square); /* F */ + } + + cairo_line_to (cr, x_left, y_top); /* H */ + } - g_array_append_val (gdk_renderer->priv->trapezoids, trap); + cairo_close_path (cr); + cairo_fill (cr); } -/* We can't handle embossing at the level of trapezoids, because when an - * underline is split into multiple trapezoids, the normal and shadow - * trapezoids will be drawn mixed together. Instead, we have to emboss - * and entire rectangle or error underline - */ - static void gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer, PangoRenderPart part, @@ -379,20 +364,28 @@ gdk_pango_renderer_draw_rectangle (PangoRenderer *renderer, { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); GdkPangoRendererPrivate *priv = gdk_renderer->priv; + cairo_t *cr; + + cr = create_cairo_context (gdk_renderer, part); - if (!priv->in_emboss && priv->embossed && part != PANGO_RENDER_PART_BACKGROUND) + if (priv->embossed && part != PANGO_RENDER_PART_BACKGROUND) { - PangoMatrix *save_matrix; - PangoColor *save_color; - - emboss_renderer (renderer, part, &save_matrix, &save_color); - PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part, - x, y, width, height); - unemboss_renderer (renderer, part, &save_matrix, &save_color); + cairo_save (cr); + emboss_context (cr); + cairo_rectangle (cr, + (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, + (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); + + cairo_fill (cr); + cairo_restore (cr); } - PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_rectangle (renderer, part, - x, y, width, height); + cairo_rectangle (cr, + (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, + (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); + cairo_fill (cr); + + cairo_destroy (cr); } static void @@ -404,20 +397,25 @@ gdk_pango_renderer_draw_error_underline (PangoRenderer *renderer, { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); GdkPangoRendererPrivate *priv = gdk_renderer->priv; - - if (!priv->in_emboss && priv->embossed) + cairo_t *cr; + + cr = create_cairo_context (gdk_renderer, PANGO_RENDER_PART_UNDERLINE); + + if (priv->embossed) { - PangoMatrix *save_matrix; - PangoColor *save_color; - - emboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color); - PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer, - x, y, width, height); - unemboss_renderer (renderer, PANGO_RENDER_PART_UNDERLINE, &save_matrix, &save_color); + cairo_save (cr); + emboss_context (cr); + draw_error_underline (cr, + (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, + (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); + cairo_restore (cr); } - PANGO_RENDERER_CLASS (gdk_pango_renderer_parent_class)->draw_error_underline (renderer, - x, y, width, height); + draw_error_underline (cr, + (double)x / PANGO_SCALE, (double)y / PANGO_SCALE, + (double)width / PANGO_SCALE, (double)height / PANGO_SCALE); + + cairo_destroy (cr); } static void @@ -426,11 +424,14 @@ gdk_pango_renderer_part_changed (PangoRenderer *renderer, { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - if (part == gdk_renderer->priv->trapezoid_part) - flush_trapezoids (gdk_renderer); + if (gdk_renderer->priv->stipple_surface[part]) + { + cairo_surface_destroy (gdk_renderer->priv->stipple_surface[part]); + gdk_renderer->priv->stipple_surface[part] = NULL; + } } -static void +void gdk_pango_renderer_begin (PangoRenderer *renderer) { GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); @@ -443,14 +444,6 @@ gdk_pango_renderer_begin (PangoRenderer *renderer) } static void -gdk_pango_renderer_end (PangoRenderer *renderer) -{ - GdkPangoRenderer *gdk_renderer = GDK_PANGO_RENDERER (renderer); - - flush_trapezoids (gdk_renderer); -} - -static void gdk_pango_renderer_prepare_run (PangoRenderer *renderer, PangoLayoutRun *run) { @@ -555,12 +548,10 @@ gdk_pango_renderer_class_init (GdkPangoRendererClass *klass) PangoRendererClass *renderer_class = PANGO_RENDERER_CLASS (klass); renderer_class->draw_glyphs = gdk_pango_renderer_draw_glyphs; - renderer_class->draw_trapezoid = gdk_pango_renderer_draw_trapezoid; renderer_class->draw_rectangle = gdk_pango_renderer_draw_rectangle; renderer_class->draw_error_underline = gdk_pango_renderer_draw_error_underline; renderer_class->part_changed = gdk_pango_renderer_part_changed; renderer_class->begin = gdk_pango_renderer_begin; - renderer_class->end = gdk_pango_renderer_end; renderer_class->prepare_run = gdk_pango_renderer_prepare_run; object_class->finalize = gdk_pango_renderer_finalize; @@ -671,8 +662,6 @@ gdk_pango_renderer_set_drawable (GdkPangoRenderer *gdk_renderer, priv = gdk_renderer->priv; - flush_trapezoids (gdk_renderer); - if (priv->drawable != drawable) { if (priv->drawable) @@ -707,8 +696,6 @@ gdk_pango_renderer_set_gc (GdkPangoRenderer *gdk_renderer, priv = gdk_renderer->priv; - flush_trapezoids (gdk_renderer); - if (priv->base_gc != gc) { if (priv->base_gc) @@ -716,20 +703,6 @@ gdk_pango_renderer_set_gc (GdkPangoRenderer *gdk_renderer, priv->base_gc = gc; if (priv->base_gc) g_object_ref (priv->base_gc); - - if (priv->gc) - { - g_object_unref (priv->gc); - priv->gc = NULL; - } - - priv->gc_color_set = FALSE; - - if (priv->gc_stipple) - { - g_object_unref (priv->gc_stipple); - priv->gc_stipple = NULL; - } } } @@ -1419,5 +1392,33 @@ gdk_pango_context_get (void) return gdk_pango_context_get_for_screen (gdk_screen_get_default ()); } +/** + * gdk_pango_context_get_for_screen: + * @screen: the #GdkScreen for which the context is to be created. + * + * Creates a #PangoContext for @screen. + * + * The context must be freed when you're finished with it. + * + * When using GTK+, normally you should use gtk_widget_get_pango_context() + * instead of this function, to get the appropriate context for + * the widget you intend to render text onto. + * + * Return value: a new #PangoContext for @screen + * + * Since: 2.2 + **/ +PangoContext * +gdk_pango_context_get_for_screen (GdkScreen *screen) +{ + PangoFontMap *fontmap; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + fontmap = pango_cairo_font_map_get_default (); + + return pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap)); +} + #define __GDK_PANGO_C__ #include "gdkaliasdef.c" diff --git a/gdk/gdkpixbuf-render.c b/gdk/gdkpixbuf-render.c index e4fe24bf8a..52c54c5a02 100644 --- a/gdk/gdkpixbuf-render.c +++ b/gdk/gdkpixbuf-render.c @@ -329,5 +329,113 @@ gdk_pixbuf_render_pixmap_and_mask_for_colormap (GdkPixbuf *pixbuf, } } +/** + * gdk_pixbuf_set_as_cairo_source: + * @pixbuf: a #GdkPixbuf + * @cr: a #Cairo context + * + * Sets the given pixbuf as the source pattern for the Cairo context. + * The pattern has an extend mode of %CAIRO_EXTEND_NONE and is aligned + * so that the origin of @pixbuf is at the current point. + **/ +void +gdk_pixbuf_set_as_cairo_source (GdkPixbuf *pixbuf, + cairo_t *cr) +{ + gint width = gdk_pixbuf_get_width (pixbuf); + gint height = gdk_pixbuf_get_height (pixbuf); + guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf); + int gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf); + int n_channels = gdk_pixbuf_get_n_channels (pixbuf); + guchar *cairo_pixels; + cairo_format_t format; + cairo_surface_t *surface; + cairo_pattern_t *pattern; + static const cairo_user_data_key_t key; + cairo_matrix_t *matrix; + double x, y; + int j; + + if (n_channels == 3) + format = CAIRO_FORMAT_RGB24; + else + format = CAIRO_FORMAT_ARGB32; + + cairo_pixels = g_malloc (4 * width * height); + surface = cairo_image_surface_create_for_data ((char *)cairo_pixels, format, + width, height, 4 * width); + cairo_surface_set_user_data (surface, &key, + cairo_pixels, (cairo_destroy_func_t)g_free); + + for (j = height; j; j--) + { + guchar *p = gdk_pixels; + guchar *q = cairo_pixels; + + if (n_channels == 3) + { + guchar *end = p + 3 * width; + + while (p < end) + { +#if G_BYTE_ORDER == GDK_LSB_FIRST + q[0] = p[2]; + q[1] = p[1]; + q[2] = p[2]; +#else + q[0] = p[0]; + q[1] = p[1]; + q[2] = p[2]; +#endif + p += 3; + q += 4; + } + } + else + { + guchar *end = p + 4 * width; + guint t1,t2,t3; + +#define MULT(d,c,a,t) G_STMT_START { t = c * a; d = ((t >> 8) + t) >> 8; } G_STMT_END + + while (p < end) + { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + MULT(q[0], p[2], p[3], t1); + MULT(q[1], p[1], p[3], t2); + MULT(q[2], p[0], p[3], t3); + q[3] = p[3]; +#else + q[0] = p[3]; + MULT(q[1], p[0], p[3], t1); + MULT(q[2], p[1], p[3], t2); + MULT(q[3], p[2], p[3], t3); +#endif + + p += 4; + q += 4; + } + +#undef MULT + } + + gdk_pixels += gdk_rowstride; + cairo_pixels += 4 * width; + } + + pattern = cairo_pattern_create_for_surface (surface); + cairo_surface_destroy (surface); + + cairo_current_point (cr, &x, &y); + matrix = cairo_matrix_create (); + cairo_matrix_translate (matrix, -x, -y); + cairo_pattern_set_matrix (pattern, matrix); + cairo_matrix_destroy (matrix); + + cairo_set_pattern (cr, pattern); + cairo_pattern_destroy (pattern); +} + #define __GDK_PIXBUF_RENDER_C__ #include "gdkaliasdef.c" + diff --git a/gdk/gdkpixbuf.h b/gdk/gdkpixbuf.h index 39c33d240d..26d72d04a8 100644 --- a/gdk/gdkpixbuf.h +++ b/gdk/gdkpixbuf.h @@ -81,6 +81,9 @@ GdkPixbuf *gdk_pixbuf_get_from_image (GdkPixbuf *dest, int width, int height); +void gdk_pixbuf_set_as_cairo_source (GdkPixbuf *pixbuf, + cairo_t *cr); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/gdk/gdkpixmap.c b/gdk/gdkpixmap.c index f4c0d05ebd..06021e60c8 100644 --- a/gdk/gdkpixmap.c +++ b/gdk/gdkpixmap.c @@ -144,8 +144,7 @@ static GdkImage* gdk_pixmap_copy_to_image (GdkDrawable *drawable, gint width, gint height); -static void gdk_pixmap_set_cairo_target (GdkDrawable *drawable, - cairo_t *cr); +static cairo_surface_t *gdk_pixmap_ref_cairo_surface (GdkDrawable *drawable); static GdkVisual* gdk_pixmap_real_get_visual (GdkDrawable *drawable); static gint gdk_pixmap_real_get_depth (GdkDrawable *drawable); @@ -227,7 +226,7 @@ gdk_pixmap_class_init (GdkPixmapObjectClass *klass) drawable_class->get_colormap = gdk_pixmap_real_get_colormap; drawable_class->get_visual = gdk_pixmap_real_get_visual; drawable_class->_copy_to_image = gdk_pixmap_copy_to_image; - drawable_class->set_cairo_target = gdk_pixmap_set_cairo_target; + drawable_class->ref_cairo_surface = gdk_pixmap_ref_cairo_surface; } static void @@ -521,12 +520,10 @@ gdk_pixmap_copy_to_image (GdkDrawable *drawable, width, height); } -static void -gdk_pixmap_set_cairo_target (GdkDrawable *drawable, - cairo_t *cr) +static cairo_surface_t * +gdk_pixmap_ref_cairo_surface (GdkDrawable *drawable) { - gdk_drawable_set_cairo_target (((GdkPixmapObject*)drawable)->impl, - cr); + return _gdk_drawable_ref_cairo_surface (((GdkPixmapObject*)drawable)->impl); } static GdkBitmap * diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index e509f3b376..1d36a80703 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -44,6 +44,7 @@ struct _GdkWindowPaint GdkPixmap *pixmap; gint x_offset; gint y_offset; + cairo_surface_t *surface; }; static GdkGC *gdk_window_create_gc (GdkDrawable *drawable, @@ -157,8 +158,7 @@ static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable, gint width, gint height); -static void gdk_window_set_cairo_target (GdkDrawable *drawable, - cairo_t *cr); +static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable); static void gdk_window_real_get_size (GdkDrawable *drawable, gint *width, @@ -266,7 +266,7 @@ gdk_window_class_init (GdkWindowObjectClass *klass) drawable_class->get_colormap = gdk_window_real_get_colormap; drawable_class->get_visual = gdk_window_real_get_visual; drawable_class->_copy_to_image = gdk_window_copy_to_image; - drawable_class->set_cairo_target = gdk_window_set_cairo_target; + drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface; drawable_class->get_clip_region = gdk_window_get_clip_region; drawable_class->get_visible_region = gdk_window_get_visible_region; drawable_class->get_composite_drawable = gdk_window_get_composite_drawable; @@ -973,6 +973,10 @@ gdk_window_begin_paint_region (GdkWindow *window, gdk_pixmap_new (window, MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1); + paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap); + _gdk_windowing_set_surface_device_offset (paint->surface, + - paint->x_offset, - paint->y_offset); + for (list = private->paint_stack; list != NULL; list = list->next) { GdkWindowPaint *tmp_paint = list->data; @@ -1047,7 +1051,8 @@ gdk_window_end_paint (GdkWindow *window) /* Reset clip region of the cached GdkGC */ gdk_gc_set_clip_region (tmp_gc, NULL); - + + cairo_surface_destroy (paint->surface); g_object_unref (paint->pixmap); gdk_region_destroy (paint->region); g_free (paint); @@ -1720,42 +1725,60 @@ gdk_window_draw_glyphs_transformed (GdkDrawable *drawable, RESTORE_GC (gc); } -static GdkGC * -gdk_window_get_bg_gc (GdkWindow *window, - GdkWindowPaint *paint) +static void +gdk_window_set_bg_pattern (GdkWindow *window, + cairo_t *cr, + int x_offset, + int y_offset) { GdkWindowObject *private = (GdkWindowObject *)window; - guint gc_mask = 0; - GdkGCValues gc_values; - if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent) { - GdkWindowPaint tmp_paint = *paint; - tmp_paint.x_offset += private->x; - tmp_paint.y_offset += private->y; - - return gdk_window_get_bg_gc (GDK_WINDOW (private->parent), &tmp_paint); + gdk_window_set_bg_pattern (GDK_WINDOW (private->parent), cr, + private->x, private->y); } else if (private->bg_pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG && private->bg_pixmap != GDK_NO_BG) { - gc_values.fill = GDK_TILED; - gc_values.tile = private->bg_pixmap; - - gc_mask = GDK_GC_FILL | GDK_GC_TILE; + cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap); + cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface); + cairo_surface_destroy (surface); - return gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask); + if (x_offset != 0 || y_offset) + { + cairo_matrix_t *matrix = cairo_matrix_create (); + cairo_matrix_translate (matrix, x_offset, y_offset); + cairo_pattern_set_matrix (pattern, matrix); + cairo_matrix_destroy (matrix); + } + + cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); + cairo_set_pattern (cr, pattern); + cairo_pattern_destroy (pattern); } else { - GdkGC *gc = _gdk_drawable_get_scratch_gc (paint->pixmap, FALSE); - - gdk_gc_set_foreground (gc, &(private->bg_color)); + gdk_cairo_set_source_color (cr, &private->bg_color); + } +} - return g_object_ref (gc); +static void +region_path (cairo_t *cr, + GdkRegion *region) +{ + GdkRectangle *rectangles; + int n_rectangles, i; + + gdk_region_get_rectangles (region, &rectangles, &n_rectangles); + for (i = 0; i < n_rectangles; i++) + { + cairo_rectangle (cr, + rectangles[i].x, rectangles[i].y, + rectangles[i].width, rectangles[i].height); } + g_free (rectangles); } static void @@ -1767,20 +1790,27 @@ gdk_window_clear_backing_rect (GdkWindow *window, { GdkWindowObject *private = (GdkWindowObject *)window; GdkWindowPaint *paint = private->paint_stack->data; - GdkGC *tmp_gc; + cairo_t *cr; if (GDK_WINDOW_DESTROYED (window)) return; - tmp_gc = gdk_window_get_bg_gc (window, paint); - gdk_gc_set_clip_region (tmp_gc, paint->region); - - gdk_draw_rectangle (window, tmp_gc, TRUE, - x, y, width, height); + cr = cairo_create (); + cairo_set_target_surface (cr, paint->surface); - gdk_gc_set_clip_region (tmp_gc, NULL); - - g_object_unref (tmp_gc); + gdk_window_set_bg_pattern (window, cr, 0, 0); + + cairo_save (cr); + + cairo_rectangle (cr, x, y, width, height); + cairo_clip (cr); + + region_path (cr, paint->region); + cairo_fill (cr); + + cairo_restore (cr); + + cairo_destroy (cr); } /** @@ -2095,11 +2125,11 @@ gdk_window_copy_to_image (GdkDrawable *drawable, width, height); } -static void -gdk_window_set_cairo_target (GdkDrawable *drawable, - cairo_t *cr) +static cairo_surface_t * +gdk_window_ref_cairo_surface (GdkDrawable *drawable) { GdkWindowObject *private = (GdkWindowObject*) drawable; + cairo_surface_t *surface; gint x_offset, y_offset; gdk_window_get_offsets (GDK_WINDOW (drawable), &x_offset, &y_offset); @@ -2107,12 +2137,14 @@ gdk_window_set_cairo_target (GdkDrawable *drawable, if (private->paint_stack) { GdkWindowPaint *paint = private->paint_stack->data; - gdk_drawable_set_cairo_target (paint->pixmap, cr); + + surface = paint->surface; + cairo_surface_reference (surface); } else - gdk_drawable_set_cairo_target (private->impl, cr); + surface = _gdk_drawable_ref_cairo_surface (private->impl); - cairo_translate (cr, - x_offset, - y_offset); + return surface; } /* Code for dirty-region queueing diff --git a/gdk/x11/Makefile.am b/gdk/x11/Makefile.am index d7c529431c..13a05aaf5a 100644 --- a/gdk/x11/Makefile.am +++ b/gdk/x11/Makefile.am @@ -39,7 +39,6 @@ libgdk_x11_la_SOURCES = \ gdkinput.c \ gdkkeys-x11.c \ gdkmain-x11.c \ - gdkpango-x11.c \ gdkpixmap-x11.c \ gdkpixmap-x11.h \ gdkproperty-x11.c \ diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index c06603073b..b73f0ea7e1 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -208,7 +208,6 @@ gdk_display_open (const gchar *display_name) display_x11->leader_window_title_set = FALSE; display_x11->have_render = GDK_UNKNOWN; - display_x11->have_render_with_trapezoids = GDK_UNKNOWN; #ifdef HAVE_XFIXES if (XFixesQueryExtension (display_x11->xdisplay, diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h index 9392657736..198bf6a727 100644 --- a/gdk/x11/gdkdisplay-x11.h +++ b/gdk/x11/gdkdisplay-x11.h @@ -78,7 +78,6 @@ struct _GdkDisplayX11 gboolean use_xshm; gboolean have_shm_pixmaps; GdkTristate have_render; - GdkTristate have_render_with_trapezoids; gboolean have_xfixes; gint xfixes_event_base; diff --git a/gdk/x11/gdkdrawable-x11.c b/gdk/x11/gdkdrawable-x11.c index 1af5cc836d..0c49e87e43 100644 --- a/gdk/x11/gdkdrawable-x11.c +++ b/gdk/x11/gdkdrawable-x11.c @@ -109,20 +109,6 @@ static void gdk_x11_draw_lines (GdkDrawable *drawable, GdkPoint *points, gint npoints); -static void gdk_x11_draw_glyphs (GdkDrawable *drawable, - GdkGC *gc, - PangoFont *font, - gint x, - gint y, - PangoGlyphString *glyphs); -static void gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable, - GdkGC *gc, - PangoMatrix *matrix, - PangoFont *font, - gint x, - gint y, - PangoGlyphString *glyphs); - static void gdk_x11_draw_image (GdkDrawable *drawable, GdkGC *gc, GdkImage *image, @@ -145,13 +131,7 @@ static void gdk_x11_draw_pixbuf (GdkDrawable *drawable, gint x_dither, gint y_dither); -static void gdk_x11_draw_trapezoids (GdkDrawable *drawable, - GdkGC *gc, - GdkTrapezoid *trapezoids, - gint n_trapezoids); - -static void gdk_x11_set_cairo_target (GdkDrawable *drawable, - cairo_t *cr); +static cairo_surface_t *gdk_x11_ref_cairo_surface (GdkDrawable *drawable); static void gdk_x11_set_colormap (GdkDrawable *drawable, GdkColormap *colormap); @@ -166,6 +146,7 @@ static void gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass); static void gdk_drawable_impl_x11_finalize (GObject *object); static gpointer parent_class = NULL; +static const cairo_user_data_key_t gdk_x11_cairo_key; GType _gdk_drawable_impl_x11_get_type (void) @@ -215,13 +196,10 @@ gdk_drawable_impl_x11_class_init (GdkDrawableImplX11Class *klass) drawable_class->draw_points = gdk_x11_draw_points; drawable_class->draw_segments = gdk_x11_draw_segments; drawable_class->draw_lines = gdk_x11_draw_lines; - drawable_class->draw_glyphs = gdk_x11_draw_glyphs; - drawable_class->draw_glyphs_transformed = gdk_x11_draw_glyphs_transformed; drawable_class->draw_image = gdk_x11_draw_image; drawable_class->draw_pixbuf = gdk_x11_draw_pixbuf; - drawable_class->draw_trapezoids = gdk_x11_draw_trapezoids; - drawable_class->set_cairo_target = gdk_x11_set_cairo_target; + drawable_class->ref_cairo_surface = gdk_x11_ref_cairo_surface; drawable_class->set_colormap = gdk_x11_set_colormap; drawable_class->get_colormap = gdk_x11_get_colormap; @@ -241,6 +219,32 @@ gdk_drawable_impl_x11_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +/** + * _gdk_x11_drawable_finish: + * @drawable: a #GdkDrawableImplX11. + * + * Performs necessary cleanup prior to freeing a pixmap or + * destroying a window. + **/ +void +_gdk_x11_drawable_finish (GdkDrawable *drawable) +{ + GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable); + + if (impl->picture) + { + XRenderFreePicture (GDK_SCREEN_XDISPLAY (impl->screen), + impl->picture); + impl->picture = None; + } + + if (impl->cairo_surface) + { + cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key, + NULL, NULL); + } +} + static void try_pixmap (Display *xdisplay, int screen, @@ -329,94 +333,25 @@ _gdk_x11_have_render (GdkDisplay *display) return x11display->have_render == GDK_YES; } -gboolean -_gdk_x11_have_render_with_trapezoids (GdkDisplay *display) -{ - Display *xdisplay = GDK_DISPLAY_XDISPLAY (display); - GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display); - - if (x11display->have_render_with_trapezoids == GDK_UNKNOWN) - { - x11display->have_render_with_trapezoids = GDK_NO; - if (_gdk_x11_have_render (display)) - { - /* - * Require protocol >= 0.4 for CompositeTrapezoids support. - */ - int major_version, minor_version; - -#define XRENDER_TETRAPEZOIDS_MAJOR 0 -#define XRENDER_TETRAPEZOIDS_MINOR 4 - - if (XRenderQueryVersion (xdisplay, &major_version, - &minor_version)) - { - if ((major_version == XRENDER_TETRAPEZOIDS_MAJOR) && - (minor_version >= XRENDER_TETRAPEZOIDS_MINOR)) - x11display->have_render_with_trapezoids = GDK_YES; - } - } - } - - return x11display->have_render_with_trapezoids == GDK_YES; -} - -static XftDraw * -gdk_x11_drawable_get_xft_draw (GdkDrawable *drawable) -{ - GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable); - - if (impl->xft_draw == NULL) - { - GdkColormap *colormap = gdk_drawable_get_colormap (drawable); - - if (colormap) - { - GdkVisual *visual; - - visual = gdk_colormap_get_visual (colormap); - - impl->xft_draw = XftDrawCreate (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid, - GDK_VISUAL_XVISUAL (visual), GDK_COLORMAP_XCOLORMAP (colormap)); - } - else if (gdk_drawable_get_depth (drawable) == 1) - { - impl->xft_draw = XftDrawCreateBitmap (GDK_SCREEN_XDISPLAY (impl->screen), impl->xid); - } - else - { - 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; - } - } - - return impl->xft_draw; -} - static Picture gdk_x11_drawable_get_picture (GdkDrawable *drawable) { - XftDraw *draw = gdk_x11_drawable_get_xft_draw (drawable); - - return draw ? XftDrawPicture (draw) : None; + return None; } static void -gdk_x11_drawable_update_xft_clip (GdkDrawable *drawable, - GdkGC *gc) +gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable, + GdkGC *gc) { + GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable); + Display *xdisplay = GDK_SCREEN_XDISPLAY (impl->screen); GdkGCX11 *gc_private = gc ? GDK_GC_X11 (gc) : NULL; - XftDraw *xft_draw = gdk_x11_drawable_get_xft_draw (drawable); + Picture picture = gdk_x11_drawable_get_picture (drawable); if (gc && gc_private->clip_region) { GdkRegionBox *boxes = gc_private->clip_region->rects; gint n_boxes = gc_private->clip_region->numRects; -#if 0 /* Until XftDrawSetClipRectangles is there */ XRectangle *rects = g_new (XRectangle, n_boxes); int i; @@ -427,32 +362,18 @@ gdk_x11_drawable_update_xft_clip (GdkDrawable *drawable, rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x; rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y; } - XftDrawSetClipRectangles (xft_draw, 0, 0, rects, n_boxes); - - g_free (rects); -#else - Region xregion = XCreateRegion (); - int i; - - for (i=0; i < n_boxes; i++) - { - XRectangle rect; - - rect.x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT); - rect.y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT); - rect.width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rect.x; - rect.height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rect.y; - - XUnionRectWithRegion (&rect, xregion, xregion); - } - XftDrawSetClip (xft_draw, xregion); - XDestroyRegion (xregion); -#endif + XRenderSetPictureClipRectangles (xdisplay, picture, + 0, 0, rects, n_boxes); + + g_free (rects); } else { - XftDrawSetClip (xft_draw, NULL); + XRenderPictureAttributes pa; + pa.clip_mask = None; + XRenderChangePicture (xdisplay, picture, + CPClipMask, &pa); } } @@ -839,45 +760,6 @@ gdk_x11_draw_lines (GdkDrawable *drawable, } static void -gdk_x11_draw_glyphs (GdkDrawable *drawable, - GdkGC *gc, - PangoFont *font, - gint x, - gint y, - PangoGlyphString *glyphs) -{ - gdk_x11_draw_glyphs_transformed (drawable, gc, NULL, - font, - x * PANGO_SCALE, - y * PANGO_SCALE, - glyphs); -} - -static void -gdk_x11_draw_glyphs_transformed (GdkDrawable *drawable, - GdkGC *gc, - PangoMatrix *matrix, - PangoFont *font, - gint x, - gint y, - PangoGlyphString *glyphs) -{ - GdkDrawableImplX11 *impl; - PangoRenderer *renderer; - - impl = GDK_DRAWABLE_IMPL_X11 (drawable); - - g_return_if_fail (PANGO_XFT_IS_FONT (font)); - - renderer = _gdk_x11_renderer_get (drawable, gc); - if (matrix) - pango_renderer_set_matrix (renderer, matrix); - pango_renderer_draw_glyphs (renderer, font, glyphs, x, y); - if (matrix) - pango_renderer_set_matrix (renderer, NULL); -} - -static void gdk_x11_draw_image (GdkDrawable *drawable, GdkGC *gc, GdkImage *image, @@ -1501,7 +1383,7 @@ gdk_x11_draw_pixbuf (GdkDrawable *drawable, return; } - gdk_x11_drawable_update_xft_clip (drawable, gc); + gdk_x11_drawable_update_picture_clip (drawable, gc); rowstride = gdk_pixbuf_get_rowstride (pixbuf); @@ -1526,239 +1408,65 @@ gdk_x11_draw_pixbuf (GdkDrawable *drawable, } static void -gdk_x11_draw_trapezoids (GdkDrawable *drawable, - GdkGC *gc, - GdkTrapezoid *trapezoids, - gint n_trapezoids) +gdk_x11_cairo_surface_destroy (void *data) { - GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; - GdkDisplay *display = gdk_screen_get_display (screen); - XTrapezoid *xtrapezoids; - gint i; + GdkDrawableImplX11 *impl = data; - if (!_gdk_x11_have_render_with_trapezoids (display)) - { - GdkDrawable *wrapper = GDK_DRAWABLE_IMPL_X11 (drawable)->wrapper; - GDK_DRAWABLE_CLASS (parent_class)->draw_trapezoids (wrapper, gc, - trapezoids, n_trapezoids); - return; - } - - xtrapezoids = g_new (XTrapezoid, n_trapezoids); - - for (i = 0; i < n_trapezoids; i++) - { - xtrapezoids[i].top = XDoubleToFixed (trapezoids[i].y1); - xtrapezoids[i].bottom = XDoubleToFixed (trapezoids[i].y2); - xtrapezoids[i].left.p1.x = XDoubleToFixed (trapezoids[i].x11); - xtrapezoids[i].left.p1.y = XDoubleToFixed (trapezoids[i].y1); - xtrapezoids[i].left.p2.x = XDoubleToFixed (trapezoids[i].x12); - xtrapezoids[i].left.p2.y = XDoubleToFixed (trapezoids[i].y2); - xtrapezoids[i].right.p1.x = XDoubleToFixed (trapezoids[i].x21); - xtrapezoids[i].right.p1.y = XDoubleToFixed (trapezoids[i].y1); - xtrapezoids[i].right.p2.x = XDoubleToFixed (trapezoids[i].x22); - xtrapezoids[i].right.p2.y = XDoubleToFixed (trapezoids[i].y2); - } - - _gdk_x11_drawable_draw_xtrapezoids (drawable, gc, - xtrapezoids, n_trapezoids); - - g_free (xtrapezoids); + impl->cairo_surface = NULL; } static cairo_surface_t * -gdk_x11_drawable_get_cairo_surface (GdkDrawable *drawable) +gdk_x11_ref_cairo_surface (GdkDrawable *drawable) { GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable); - GdkColormap *colormap; - GdkVisual *visual; if (GDK_IS_WINDOW_IMPL_X11 (drawable) && GDK_WINDOW_DESTROYED (impl->wrapper)) return NULL; - colormap = gdk_drawable_get_colormap (drawable); - if (!colormap) - { - g_warning ("Using Cairo 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; - } - - visual = gdk_colormap_get_visual (colormap); - if (!impl->cairo_surface) { - impl->cairo_surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen), - impl->xid, - GDK_VISUAL_XVISUAL (visual), - CAIRO_FORMAT_RGB24, - GDK_COLORMAP_XCOLORMAP (colormap)); - } - - return impl->cairo_surface; -} - -static void -gdk_x11_set_cairo_target (GdkDrawable *drawable, - cairo_t *cr) -{ - cairo_surface_t *surface = gdk_x11_drawable_get_cairo_surface (drawable); - if (surface) - cairo_set_target_surface (cr, surface); -} - -/** - * gdk_draw_rectangle_alpha_libgtk_only: - * @drawable: The #GdkDrawable to draw on - * @x: the x coordinate of the left edge of the rectangle. - * @y: the y coordinate of the top edge of the rectangle. - * @width: the width of the rectangle. - * @height: the height of the rectangle. - * @color: The color - * @alpha: The alpha value. - * - * Tries to draw a filled alpha blended rectangle using the window - * system's native routines. This is not public API and must not be - * used by applications. - * - * Return value: TRUE if the rectangle could be drawn, FALSE - * otherwise. - **/ -gboolean -gdk_draw_rectangle_alpha_libgtk_only (GdkDrawable *drawable, - gint x, - gint y, - gint width, - gint height, - GdkColor *color, - guint16 alpha) -{ - Display *xdisplay; - XRenderColor render_color; - Picture pict; - int x_offset, y_offset; - GdkDrawable *real_drawable, *impl; - - g_return_val_if_fail (color != NULL, FALSE); - - if (!GDK_IS_WINDOW (drawable)) - return FALSE; + GdkVisual *visual = NULL; - if (!_gdk_x11_have_render (gdk_drawable_get_display (drawable))) - return FALSE; - - gdk_window_get_internal_paint_info (GDK_WINDOW (drawable), - &real_drawable, - &x_offset, &y_offset); - - impl = ((GdkWindowObject *)real_drawable)->impl; - - pict = gdk_x11_drawable_get_picture (impl); - - if (pict == None) - return FALSE; - - xdisplay = GDK_DISPLAY_XDISPLAY (gdk_drawable_get_display (drawable)); - - render_color.alpha = alpha; - render_color.red = (guint32)color->red * render_color.alpha / 0xffff; - render_color.green = (guint32)color->green * render_color.alpha / 0xffff; - render_color.blue = (guint32)color->blue * render_color.alpha / 0xffff; - - XRenderFillRectangle (xdisplay, - PictOpOver, pict, &render_color, - x - x_offset, y - y_offset, - width, height); - return TRUE; -} - -void -_gdk_x11_drawable_draw_xtrapezoids (GdkDrawable *drawable, - GdkGC *gc, - XTrapezoid *xtrapezoids, - int n_trapezoids) -{ - GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; - GdkDisplay *display = gdk_screen_get_display (screen); - GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display); - - XftDraw *draw; - - if (!_gdk_x11_have_render_with_trapezoids (display)) - { - /* This is the case of drawing the borders of the unknown glyph box - * without render on the display, we need to feed it back to - * fallback code. Not efficient, but doesn't matter. - */ - GdkTrapezoid *trapezoids = g_new (GdkTrapezoid, n_trapezoids); - int i; - - for (i = 0; i < n_trapezoids; i++) + visual = gdk_drawable_get_visual (drawable); + + if (GDK_IS_WINDOW (drawable)) + impl->cairo_surface = cairo_xlib_surface_create_for_window_with_visual (GDK_SCREEN_XDISPLAY (impl->screen), + impl->xid, + GDK_VISUAL_XVISUAL (visual)); + else if (visual) + impl->cairo_surface = cairo_xlib_surface_create_for_pixmap_with_visual (GDK_SCREEN_XDISPLAY (impl->screen), + impl->xid, + GDK_VISUAL_XVISUAL (visual)); + else if (gdk_drawable_get_depth (drawable) == 1) + impl->cairo_surface = cairo_xlib_surface_create_for_pixmap (GDK_SCREEN_XDISPLAY (impl->screen), + impl->xid, + CAIRO_FORMAT_A1); + else { - trapezoids[i].y1 = XFixedToDouble (xtrapezoids[i].top); - trapezoids[i].y2 = XFixedToDouble (xtrapezoids[i].bottom); - trapezoids[i].x11 = XFixedToDouble (xtrapezoids[i].left.p1.x); - trapezoids[i].x12 = XFixedToDouble (xtrapezoids[i].left.p2.x); - trapezoids[i].x21 = XFixedToDouble (xtrapezoids[i].right.p1.x); - trapezoids[i].x22 = XFixedToDouble (xtrapezoids[i].right.p2.x); + g_warning ("Using Cairo 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; } - gdk_x11_draw_trapezoids (drawable, gc, trapezoids, n_trapezoids); - g_free (trapezoids); - - return; + cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key, + drawable, gdk_x11_cairo_surface_destroy); } + else + cairo_surface_reference (impl->cairo_surface); - gdk_x11_drawable_update_xft_clip (drawable, gc); - draw = gdk_x11_drawable_get_xft_draw (drawable); - - if (!x11display->mask_format) - x11display->mask_format = XRenderFindStandardFormat (x11display->xdisplay, - PictStandardA8); - - XRenderCompositeTrapezoids (x11display->xdisplay, PictOpOver, - _gdk_x11_gc_get_fg_picture (gc), - XftDrawPicture (draw), - x11display->mask_format, - - gc->ts_x_origin, - gc->ts_y_origin, - xtrapezoids, n_trapezoids); + return impl->cairo_surface; } void -_gdk_x11_drawable_draw_xft_glyphs (GdkDrawable *drawable, - GdkGC *gc, - XftFont *xft_font, - XftGlyphSpec *glyphs, - gint n_glyphs) +_gdk_windowing_set_surface_device_offset (cairo_surface_t *surface, + gint x_offset, + gint y_offset) { - GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; - GdkDisplay *display = gdk_screen_get_display (screen); - GdkDisplayX11 *x11display = GDK_DISPLAY_X11 (display); - XftDraw *draw; - - gdk_x11_drawable_update_xft_clip (drawable, gc); - draw = gdk_x11_drawable_get_xft_draw (drawable); - - if (_gdk_x11_have_render (display)) - { - XftGlyphSpecRender (x11display->xdisplay, PictOpOver, - _gdk_x11_gc_get_fg_picture (gc), - xft_font, - XftDrawPicture (draw), - - gc->ts_x_origin, - gc->ts_y_origin, - glyphs, n_glyphs); - } - else - { - XftColor color; - - _gdk_gc_x11_get_fg_xft_color (gc, &color); - XftDrawGlyphSpec (draw, &color, xft_font, glyphs, n_glyphs); - } + cairo_xlib_surface_set_device_offset (surface, x_offset, y_offset); } #define __GDK_DRAWABLE_X11_C__ diff --git a/gdk/x11/gdkdrawable-x11.h b/gdk/x11/gdkdrawable-x11.h index 1de1e50c3e..4b3d13c69d 100644 --- a/gdk/x11/gdkdrawable-x11.h +++ b/gdk/x11/gdkdrawable-x11.h @@ -32,7 +32,7 @@ #include <gdk/gdkdrawable.h> #include <X11/Xlib.h> -#include <X11/Xft/Xft.h> +#include <X11/extensions/Xrender.h> #ifdef __cplusplus extern "C" { @@ -70,7 +70,7 @@ struct _GdkDrawableImplX11 Window xid; GdkScreen *screen; - XftDraw *xft_draw; + Picture picture; cairo_surface_t *cairo_surface; }; @@ -92,15 +92,7 @@ void _gdk_x11_convert_to_format (guchar *src_buf, gint height); /* Note that the following take GdkDrawableImplX11, not the wrapper drawable */ -void _gdk_x11_drawable_draw_xtrapezoids (GdkDrawable *drawable, - GdkGC *gc, - XTrapezoid *xtrapezoids, - int n_trapezoids); -void _gdk_x11_drawable_draw_xft_glyphs (GdkDrawable *drawable, - GdkGC *gc, - XftFont *xft_font, - XftGlyphSpec *glyphs, - gint n_glyphs); +void _gdk_x11_drawable_finish (GdkDrawable *drawable); #ifdef __cplusplus } diff --git a/gdk/x11/gdkgc-x11.c b/gdk/x11/gdkgc-x11.c index c01128de60..806e96fe76 100644 --- a/gdk/x11/gdkgc-x11.c +++ b/gdk/x11/gdkgc-x11.c @@ -110,9 +110,6 @@ gdk_gc_x11_finalize (GObject *object) if (x11_gc->clip_region) gdk_region_destroy (x11_gc->clip_region); - if (x11_gc->fg_picture != None) - XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture); - if (x11_gc->stipple) g_object_unref (x11_gc->stipple); if (x11_gc->tile) @@ -396,18 +393,6 @@ gdk_x11_gc_get_values (GdkGC *gc, } static void -clear_fg_picture (GdkGC *gc) -{ - GdkGCX11 *x11_gc = GDK_GC_X11 (gc); - - if (x11_gc->fg_picture != None) - { - XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), x11_gc->fg_picture); - x11_gc->fg_picture = None; - } -} - -static void gdk_x11_gc_set_values (GdkGC *gc, GdkGCValues *values, GdkGCValuesMask values_mask) @@ -447,28 +432,19 @@ gdk_x11_gc_set_values (GdkGC *gc, if (values_mask & GDK_GC_BACKGROUND) { if (x11_gc->bg_pixel != values->background.pixel) - { - x11_gc->bg_pixel = values->background.pixel; - if (x11_gc->fill == GDK_OPAQUE_STIPPLED) - clear_fg_picture (gc); - } + x11_gc->bg_pixel = values->background.pixel; } if (values_mask & GDK_GC_FILL) { if (x11_gc->fill != values->fill) - { - clear_fg_picture (gc); - x11_gc->fill = values->fill; - } + x11_gc->fill = values->fill; } if (values_mask & GDK_GC_STIPPLE) { if (x11_gc->stipple != values->stipple) { - if (x11_gc->fill == GDK_STIPPLED || x11_gc->fill == GDK_OPAQUE_STIPPLED) - clear_fg_picture (gc); if (x11_gc->stipple) g_object_unref (x11_gc->stipple); x11_gc->stipple = values->stipple; @@ -481,8 +457,6 @@ gdk_x11_gc_set_values (GdkGC *gc, { if (x11_gc->tile != values->tile) { - if (x11_gc->fill == GDK_TILED) - clear_fg_picture (gc); if (x11_gc->tile) g_object_unref (x11_gc->tile); x11_gc->tile = values->tile; @@ -882,8 +856,6 @@ gdk_gc_copy (GdkGC *dst_gc, GdkGC *src_gc) x11_dst_gc->tile = x11_src_gc->tile; if (x11_dst_gc->tile) g_object_ref (x11_dst_gc->tile); - - clear_fg_picture (dst_gc); } /** @@ -943,345 +915,6 @@ gdk_x11_gc_get_xgc (GdkGC *gc) return gc_x11->xgc; } -/* Various bits of the below are roughly cribbed from XFree86 - * lib/Xft/xftdraw.c, Copyright 2000, Keith Packard - */ - -static XRenderPictFormat * -foreground_format (GdkGC *gc) -{ - XRenderPictFormat pf; - - pf.type = PictTypeDirect; - pf.depth = 32; - pf.direct.redMask = 0xff; - pf.direct.greenMask = 0xff; - pf.direct.blueMask = 0xff; - pf.direct.alphaMask = 0xff; - - return XRenderFindFormat (GDK_GC_XDISPLAY (gc), - (PictFormatType | - PictFormatDepth | - PictFormatRedMask | - PictFormatGreenMask | - PictFormatBlueMask | - PictFormatAlphaMask), - &pf, - 0); -} - -static Picture -make_fg_tile_picture (GdkGC *gc) -{ - GdkGCX11 *x11_gc = GDK_GC_X11 (gc); - GdkVisual *visual = gdk_drawable_get_visual (x11_gc->tile); - XRenderPictFormat *format = NULL; - - if (visual) - { - format = XRenderFindVisualFormat (GDK_GC_XDISPLAY (gc), - GDK_VISUAL_XVISUAL (visual)); - } - else if (x11_gc->depth == 1) - { - format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc), - PictStandardA1); - } - - if (format) - { - XRenderPictureAttributes pa; - pa.repeat = True; - - return XRenderCreatePicture (GDK_GC_XDISPLAY (gc), - GDK_PIXMAP_XID (x11_gc->tile), - format, - CPRepeat, &pa); - } - - return None; -} - -static Picture -make_stipple_picture (GdkGC *gc) -{ - GdkGCX11 *x11_gc = GDK_GC_X11 (gc); - XRenderPictFormat *format = NULL; - XRenderPictureAttributes pa; - - format = XRenderFindStandardFormat (GDK_GC_XDISPLAY (gc), - PictStandardA1); - - pa.repeat = True; - return XRenderCreatePicture (GDK_GC_XDISPLAY (gc), - GDK_PIXMAP_XID (x11_gc->stipple), - format, - CPRepeat, &pa); -} - -static Picture -make_color_picture (GdkGC *gc, - XRenderColor *color) -{ - GdkGCX11 *x11_gc = GDK_GC_X11 (gc); - XRenderPictureAttributes pa; - XRenderPictFormat *pix_format = foreground_format (gc); - Pixmap pix; - Picture picture; - - if (!pix_format) - return None; - - pix = XCreatePixmap (GDK_GC_XDISPLAY (gc), - GDK_SCREEN_XROOTWIN (x11_gc->screen), - 1, 1, pix_format->depth); - pa.repeat = True; - picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc), - pix, - pix_format, - CPRepeat, &pa); - XFreePixmap (GDK_GC_XDISPLAY (gc), pix); - - XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, - picture, color, - 0, 0, 1, 1); - - return picture; -} - -static void -get_bg_color (GdkGC *gc, - XRenderColor *render_color) -{ - GdkGCX11 *x11_gc = GDK_GC_X11 (gc); - GdkColormap *cmap; - - cmap = gdk_gc_get_colormap (gc); - - if (cmap) - { - GdkColor color; - - gdk_colormap_query_color (cmap, x11_gc->bg_pixel, &color); - - render_color->alpha = 0xffff; - render_color->red = color.red; - render_color->green = color.green; - render_color->blue = color.blue; - } - else /* Not worth warning, just use black */ - { - render_color->alpha = 0xffff; - render_color->red = 0; - render_color->green = 0; - render_color->blue = 0; - } -} - -/** - * _gdk_x11_gc_get_fg_picture: - * @gc: a #GdkGC - * - * Gets a Xrender Picture object suitable for being the source - * drawable for drawing with the foreground the graphics context. - * - * Return value: a Picture, owned by the GC; this cannot be - * used over subsequent modification of the GC. - **/ -Picture -_gdk_x11_gc_get_fg_picture (GdkGC *gc) -{ - GdkGCX11 *x11_gc; - gboolean new = FALSE; - XftColor xftcolor; - GdkFill fill; - int width, height; - - g_return_val_if_fail (GDK_IS_GC_X11 (gc), None); - - if (!_gdk_x11_have_render (GDK_GC_DISPLAY (gc))) - return None; - - x11_gc = GDK_GC_X11 (gc); - - fill = GDK_SOLID; - width = 1; - height = 1; - - switch (x11_gc->fill) - { - case GDK_SOLID: - break; - case GDK_TILED: - if (x11_gc->tile) - { - if (!x11_gc->fg_picture) - x11_gc->fg_picture = make_fg_tile_picture (gc); - - if (x11_gc->fg_picture != None) - return x11_gc->fg_picture; - } - break; - case GDK_STIPPLED: - case GDK_OPAQUE_STIPPLED: - if (x11_gc->stipple) - { - gdk_drawable_get_size (x11_gc->stipple, &width, &height); - fill = x11_gc->fill; - } - break; - } - - if (x11_gc->fg_picture == None) - { - XRenderPictureAttributes pa; - XRenderPictFormat *pix_format = foreground_format (gc); - Pixmap pix; - - if (!pix_format) - return None; - - pix = XCreatePixmap (GDK_GC_XDISPLAY (gc), - GDK_SCREEN_XROOTWIN (x11_gc->screen), - width, height, pix_format->depth); - pa.repeat = True; - x11_gc->fg_picture = XRenderCreatePicture (GDK_GC_XDISPLAY (gc), - pix, - pix_format, - CPRepeat, &pa); - XFreePixmap (GDK_GC_XDISPLAY (gc), pix); - - new = TRUE; - } - - _gdk_gc_x11_get_fg_xft_color (gc, &xftcolor); - - if (x11_gc->fg_picture_color.alpha != 0xffff || - x11_gc->fg_picture_color.red != xftcolor.color.red || - x11_gc->fg_picture_color.green != xftcolor.color.green || - x11_gc->fg_picture_color.blue != xftcolor.color.blue) - { - x11_gc->fg_picture_color.alpha = 0xffff; - x11_gc->fg_picture_color.red = xftcolor.color.red; - x11_gc->fg_picture_color.green = xftcolor.color.green; - x11_gc->fg_picture_color.blue = xftcolor.color.blue; - - new = TRUE; - } - - switch (fill) - { - case GDK_SOLID: - XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, - x11_gc->fg_picture, &x11_gc->fg_picture_color, - 0, 0, width, height); - break; - case GDK_STIPPLED: - { - Picture stipple_picture = make_stipple_picture (gc); - - XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, - x11_gc->fg_picture, &x11_gc->fg_picture_color, - 0, 0, width, height); - XRenderComposite (GDK_GC_XDISPLAY (gc), - PictOpInReverse, - stipple_picture, None, x11_gc->fg_picture, - 0, 0, 0, 0, 0, 0, width, height); - - XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture); - } - break; - case GDK_OPAQUE_STIPPLED: - { - XRenderColor bg_color; - - Picture stipple_picture = make_stipple_picture (gc); - Picture fg_picture = make_color_picture (gc, &x11_gc->fg_picture_color); - - get_bg_color (gc, &bg_color); - - XRenderFillRectangle (GDK_GC_XDISPLAY (gc), PictOpSrc, - x11_gc->fg_picture, &bg_color, - 0, 0, width, height); - XRenderComposite (GDK_GC_XDISPLAY (gc), - PictOpOver, - fg_picture, stipple_picture, x11_gc->fg_picture, - 0, 0, 0, 0, 0, 0, width, height); - - XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), stipple_picture); - XRenderFreePicture (GDK_GC_XDISPLAY (x11_gc), fg_picture); - } - break; - case GDK_TILED: - g_assert_not_reached (); /* handled above */ - break; - } - - return x11_gc->fg_picture; -} - -/** - * _gdk_gc_x11_get_fg_xft_color: - * @gc: a #GdkGC - * @xftcolor: location to store the color - * - * Gets the foreground color of the GC as a XftColor. - **/ -void -_gdk_gc_x11_get_fg_xft_color (GdkGC *gc, - XftColor *xftcolor) -{ - GdkGCX11 *x11_gc; - GdkColormap *cmap; - GdkColor color; - - g_return_if_fail (GDK_IS_GC_X11 (gc)); - - x11_gc = GDK_GC_X11 (gc); - - cmap = gdk_gc_get_colormap (gc); - - xftcolor->pixel = x11_gc->fg_pixel; - - if (cmap) - { - gdk_colormap_query_color (cmap, xftcolor->pixel, &color); - xftcolor->color.alpha = 0xffff; - xftcolor->color.red = color.red; - xftcolor->color.green = color.green; - xftcolor->color.blue = color.blue; - } - else if (x11_gc->depth == 1) - { - /* Drawing with Xft on a bitmap is a bit bizzare; it - * takes alpha >= 0x8000 to mean 'set to 1' and - * alpha < 0x8000 to mean 'set to 0'. - */ - if (xftcolor->pixel) - { - xftcolor->color.red = 0xffff; - xftcolor->color.green = 0xffff; - xftcolor->color.blue = 0xffff; - xftcolor->color.alpha = 0xffff; - } - else - { - xftcolor->color.red = 0; - xftcolor->color.green = 0; - xftcolor->color.blue = 0; - xftcolor->color.alpha = 0; - } - } - else - { - g_warning ("Using Xft rendering requires the GC argument to have a\n" - "specified colormap. If the GC was created for a drawable\n" - "with a colormap, the colormap will be set on the GC\n" - "automatically. Otherwise, a colormap must be set on it with" - "gdk_gc_set_colormap"); - } -} - void _gdk_windowing_gc_get_foreground (GdkGC *gc, GdkColor *color) diff --git a/gdk/x11/gdkpango-x11.c b/gdk/x11/gdkpango-x11.c deleted file mode 100644 index 9db3f3567a..0000000000 --- a/gdk/x11/gdkpango-x11.c +++ /dev/null @@ -1,174 +0,0 @@ -/* GDK - The GIMP Drawing Kit - * Copyright (C) 2000 Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include <config.h> -#include <stdlib.h> - -#include "gdkx.h" -#include "gdkdisplay-x11.h" -#include "gdkpango.h" -#include <pango/pangoxft.h> -#include <pango/pangoxft-render.h> -#include "gdkalias.h" - -#include <math.h> - -typedef struct _GdkX11Renderer GdkX11Renderer; -typedef struct _GdkX11RendererClass GdkX11RendererClass; - -#define GDK_TYPE_X11_RENDERER (_gdk_x11_renderer_get_type()) -#define GDK_X11_RENDERER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_X11_RENDERER, GdkX11Renderer)) -#define GDK_IS_X11_RENDERER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_X11_RENDERER)) -#define GDK_X11_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_X11_RENDERER, GdkX11RendererClass)) -#define GDK_IS_X11_RENDERER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_X11_RENDERER)) -#define GDK_X11_RENDERER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_X11_RENDERER, GdkX11RendererClass)) - -#define MAX_RENDER_PART PANGO_RENDER_PART_STRIKETHROUGH - -struct _GdkX11Renderer -{ - PangoXftRenderer parent_instance; - - XRenderPictFormat *mask_format; - - GdkDrawable *drawable; - GdkGC *gc; -}; - -struct _GdkX11RendererClass -{ - PangoXftRendererClass parent_class; -}; - -G_DEFINE_TYPE (GdkX11Renderer, _gdk_x11_renderer, PANGO_TYPE_XFT_RENDERER) - -static void -gdk_x11_renderer_finalize (GObject *object) -{ - G_OBJECT_CLASS (_gdk_x11_renderer_parent_class)->finalize (object); -} - -static void -gdk_x11_renderer_composite_trapezoids (PangoXftRenderer *xftrenderer, - PangoRenderPart part, - XTrapezoid *trapezoids, - int n_trapezoids) -{ - /* Because we only use this renderer for "draw_glyphs()" calls, we - * won't hit this code path much. However, it is hit for drawing - * the "unknown glyph" hex squares. We can safely ignore the part, - */ - GdkX11Renderer *x11_renderer = GDK_X11_RENDERER (xftrenderer); - - _gdk_x11_drawable_draw_xtrapezoids (x11_renderer->drawable, - x11_renderer->gc, - trapezoids, n_trapezoids); - -} - -static void -gdk_x11_renderer_composite_glyphs (PangoXftRenderer *xftrenderer, - XftFont *xft_font, - XftGlyphSpec *glyphs, - gint n_glyphs) -{ - GdkX11Renderer *x11_renderer = GDK_X11_RENDERER (xftrenderer); - - _gdk_x11_drawable_draw_xft_glyphs (x11_renderer->drawable, - x11_renderer->gc, - xft_font, glyphs, n_glyphs); -} - -static void -_gdk_x11_renderer_init (GdkX11Renderer *renderer) -{ -} - -static void -_gdk_x11_renderer_class_init (GdkX11RendererClass *klass) -{ - PangoXftRendererClass *xftrenderer_class = PANGO_XFT_RENDERER_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - xftrenderer_class->composite_glyphs = gdk_x11_renderer_composite_glyphs; - xftrenderer_class->composite_trapezoids = gdk_x11_renderer_composite_trapezoids; - - object_class->finalize = gdk_x11_renderer_finalize; -} - -PangoRenderer * -_gdk_x11_renderer_get (GdkDrawable *drawable, - GdkGC *gc) -{ - GdkScreen *screen = GDK_DRAWABLE_IMPL_X11 (drawable)->screen; - GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen); - GdkX11Renderer *x11_renderer; - - if (!screen_x11->renderer) - { - screen_x11->renderer = g_object_new (GDK_TYPE_X11_RENDERER, - "display", GDK_SCREEN_XDISPLAY (screen), - "screen", GDK_SCREEN_XNUMBER (screen), - NULL); - } - - x11_renderer = GDK_X11_RENDERER (screen_x11->renderer); - - x11_renderer->drawable = drawable; - x11_renderer->gc = gc; - - return screen_x11->renderer; -} - -/** - * gdk_pango_context_get_for_screen: - * @screen: the #GdkScreen for which the context is to be created. - * - * Creates a #PangoContext for @screen. - * - * The context must be freed when you're finished with it. - * - * When using GTK+, normally you should use gtk_widget_get_pango_context() - * instead of this function, to get the appropriate context for - * the widget you intend to render text onto. - * - * Return value: a new #PangoContext for @screen - * - * Since: 2.2 - **/ -PangoContext * -gdk_pango_context_get_for_screen (GdkScreen *screen) -{ - PangoContext *context; - - g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); - - if (screen->closed) - return NULL; - - context = pango_xft_get_context (GDK_SCREEN_XDISPLAY (screen), - GDK_SCREEN_X11 (screen)->screen_num); - - g_object_set_data (G_OBJECT (context), "gdk-pango-screen", screen); - - return context; -} - -#define __GDK_PANGO_X11_C__ -#include "gdkaliasdef.c" diff --git a/gdk/x11/gdkpixmap-x11.c b/gdk/x11/gdkpixmap-x11.c index 6181bccb5d..501c4c3edd 100644 --- a/gdk/x11/gdkpixmap-x11.c +++ b/gdk/x11/gdkpixmap-x11.c @@ -132,14 +132,8 @@ gdk_pixmap_impl_x11_finalize (GObject *object) { GdkDrawableImplX11 *draw_impl = GDK_DRAWABLE_IMPL_X11 (impl); - if (draw_impl->xft_draw) - XftDrawDestroy (draw_impl->xft_draw); - - if (draw_impl->cairo_surface) - { - cairo_surface_destroy (draw_impl->cairo_surface); - draw_impl->cairo_surface = NULL; - } + + _gdk_x11_drawable_finish (GDK_DRAWABLE (draw_impl)); if (!impl->is_foreign) XFreePixmap (GDK_DISPLAY_XDISPLAY (display), GDK_PIXMAP_XID (wrapper)); diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h index 3152375d96..8554beb762 100644 --- a/gdk/x11/gdkprivate-x11.h +++ b/gdk/x11/gdkprivate-x11.h @@ -41,8 +41,6 @@ #include <config.h> -#include <X11/extensions/Xrender.h> - #define GDK_TYPE_GC_X11 (_gdk_gc_x11_get_type ()) #define GDK_GC_X11(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_GC_X11, GdkGCX11)) #define GDK_GC_X11_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_GC_X11, GdkGCX11Class)) @@ -70,8 +68,6 @@ struct _GdkGCX11 GdkBitmap *stipple; GdkPixmap *tile; - Picture fg_picture; - XRenderColor fg_picture_color; gulong fg_pixel; gulong bg_pixel; }; @@ -109,11 +105,6 @@ gint _gdk_send_xevent (GdkDisplay *display, GType _gdk_gc_x11_get_type (void); gboolean _gdk_x11_have_render (GdkDisplay *display); -gboolean _gdk_x11_have_render_with_trapezoids (GdkDisplay *display); - -Picture _gdk_x11_gc_get_fg_picture (GdkGC *gc); -void _gdk_gc_x11_get_fg_xft_color (GdkGC *gc, - XftColor *xftcolor); GdkGC *_gdk_x11_gc_new (GdkDrawable *drawable, GdkGCValues *values, diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index ac0883b658..bd86efdb83 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -842,6 +842,7 @@ gdk_window_new (GdkWindow *parent, } private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num); + private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0; xattributes.background_pixel = private->bg_color.pixel; private->bg_pixmap = NULL; @@ -1128,7 +1129,6 @@ _gdk_windowing_window_destroy (GdkWindow *window, { GdkWindowObject *private = (GdkWindowObject *)window; GdkToplevelX11 *toplevel; - GdkDrawableImplX11 *draw_impl; g_return_if_fail (GDK_IS_WINDOW (window)); @@ -1141,19 +1141,7 @@ _gdk_windowing_window_destroy (GdkWindow *window, if (toplevel) gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel); - draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl); - - if (draw_impl->xft_draw) - { - XftDrawDestroy (draw_impl->xft_draw); - draw_impl->xft_draw = NULL; - } - - if (draw_impl->cairo_surface) - { - cairo_surface_destroy (draw_impl->cairo_surface); - draw_impl->cairo_surface = NULL; - } + _gdk_x11_drawable_finish (private->impl); if (!recursing && !foreign_destroy) { @@ -2773,6 +2761,7 @@ gdk_window_set_background (GdkWindow *window, const GdkColor *color) { GdkWindowObject *private = (GdkWindowObject *)window; + GdkColormap *colormap = gdk_drawable_get_colormap (window); g_return_if_fail (window != NULL); g_return_if_fail (GDK_IS_WINDOW (window)); @@ -2782,6 +2771,7 @@ gdk_window_set_background (GdkWindow *window, GDK_WINDOW_XID (window), color->pixel); private->bg_color = *color; + gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color); if (private->bg_pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG && |