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 | |
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.
35 files changed, 1484 insertions, 2467 deletions
@@ -1,3 +1,54 @@ +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. + 2005-03-16 Matthias Clasen <mclasen@redhat.com> * demos/gtk-demo/editable_cells.c: Also demonstrate diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index e05d594e5d..483b0c0c39 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,54 @@ +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. + 2005-03-16 Matthias Clasen <mclasen@redhat.com> * demos/gtk-demo/editable_cells.c: Also demonstrate diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index e05d594e5d..483b0c0c39 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,54 @@ +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. + 2005-03-16 Matthias Clasen <mclasen@redhat.com> * demos/gtk-demo/editable_cells.c: Also demonstrate 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 && diff --git a/gtk/gtkcolorsel.c b/gtk/gtkcolorsel.c index 7baea1367f..7c6375bd97 100644 --- a/gtk/gtkcolorsel.c +++ b/gtk/gtkcolorsel.c @@ -165,7 +165,8 @@ static void gtk_color_selection_show_all (GtkWidget *widget static void gtk_color_selection_set_palette_color (GtkColorSelection *colorsel, gint index, GdkColor *color); -static GdkGC *get_focus_gc (GtkWidget *drawing_area, +static void set_focus_line_attributes (GtkWidget *drawing_area, + cairo_t *cr, gint *focus_width); static void default_noscreen_change_palette_func (const GdkColor *colors, gint n_colors); @@ -216,7 +217,7 @@ static const guchar dropper_mask[] = { #define SAMPLE_HEIGHT 28 static void color_sample_draw_sample (GtkColorSelection *colorsel, int which); -static void color_sample_draw_samples (GtkColorSelection *colorsel); +static void color_sample_update_samples (GtkColorSelection *colorsel); static void set_color_internal (GtkColorSelection *colorsel, @@ -377,11 +378,9 @@ static void color_sample_draw_sample (GtkColorSelection *colorsel, int which) { GtkWidget *da; - gint x, y, i, wid, heig, f, n, goff; - guchar c[3 * 2], cc[3 * 4], *cp = c; - gdouble o; - guchar *buf; + gint x, y, wid, heig, goff; ColorSelectionPrivate *priv; + cairo_t *cr; g_return_if_fail (colorsel != NULL); priv = colorsel->private_data; @@ -389,81 +388,74 @@ color_sample_draw_sample (GtkColorSelection *colorsel, int which) g_return_if_fail (priv->sample_area != NULL); if (!GTK_WIDGET_DRAWABLE (priv->sample_area)) return; - + if (which == 0) { da = priv->old_sample; - for (n = 0, i = COLORSEL_RED; n < 3; n++, i++) - c[n] = (guchar) (UNSCALE (priv->old_color[i]) >> 8); goff = 0; } else { da = priv->cur_sample; - for (n = 0, i = COLORSEL_RED; n < 3; n++, i++) - c[n] = (guchar) (UNSCALE (priv->color[i]) >> 8); goff = priv->old_sample->allocation.width % 32; } + + cr = gdk_drawable_create_cairo_context (da->window); wid = da->allocation.width; heig = da->allocation.height; + + /* Below needs tweaking for non-power-of-two */ +#define CHECK_SIZE 16 - buf = g_new (guchar, 3 * wid * heig); - -#if 0 - i = COLORSEL_RED; - for (n = 0; n < 3; n++) + if (priv->has_opacity) { - c[n] = (guchar) (255.0 * priv->old_color[i]); - c[n + 3] = (guchar) (255.0 * priv->color[i++]); + /* Draw checks in background */ + + cairo_set_rgb_color (cr, 0.5, 0.5, 0.5); + cairo_rectangle (cr, 0, 0, wid, heig); + cairo_fill (cr); + + cairo_set_rgb_color (cr, 0.75, 0.75, 0.75); + for (x = goff & -CHECK_SIZE; x < goff + wid; x += CHECK_SIZE) + for (y = 0; y < heig; y += CHECK_SIZE) + if ((x / CHECK_SIZE + y / CHECK_SIZE) % 2 == 0) + cairo_rectangle (cr, x - goff, y, CHECK_SIZE, CHECK_SIZE); + cairo_fill (cr); } -#endif - - if (priv->has_opacity) + + if (which == 0) { - o = (which) ? priv->color[COLORSEL_OPACITY] : priv->old_color[COLORSEL_OPACITY]; - - for (n = 0; n < 3; n++) - { - cc[n] = (guchar) ((1.0 - o) * 192 + (o * (gdouble) c[n])); - cc[n + 3] = (guchar) ((1.0 - o) * 128 + (o * (gdouble) c[n])); - } - cp = cc; + cairo_set_rgb_color (cr, + priv->old_color[COLORSEL_RED], + priv->old_color[COLORSEL_GREEN], + priv->old_color[COLORSEL_BLUE]); + if (priv->has_opacity) + cairo_set_alpha (cr, priv->old_color[COLORSEL_OPACITY]); } - - i = 0; - for (y = 0; y < heig; y++) + else { - for (x = 0; x < wid; x++) - { - if (priv->has_opacity) - f = 3 * ((((goff + x) % 32) < 16) ^ ((y % 32) < 16)); - else - f = 0; - - for (n = 0; n < 3; n++) - buf[i++] = cp[n + f]; - } + cairo_set_rgb_color (cr, + priv->color[COLORSEL_RED], + priv->color[COLORSEL_GREEN], + priv->color[COLORSEL_BLUE]); + if (priv->has_opacity) + cairo_set_alpha (cr, priv->color[COLORSEL_OPACITY]); } - - gdk_draw_rgb_image (da->window, - da->style->black_gc, - 0, 0, - wid, heig, - GDK_RGB_DITHER_NORMAL, - buf, - 3*wid); - - - g_free (buf); + + cairo_rectangle (cr, 0, 0, wid, heig); + cairo_fill (cr); + + cairo_destroy (cr); } static void -color_sample_draw_samples (GtkColorSelection *colorsel) +color_sample_update_samples (GtkColorSelection *colorsel) { - color_sample_draw_sample (colorsel, 0); - color_sample_draw_sample (colorsel, 1); + ColorSelectionPrivate *priv = colorsel->private_data; + gtk_widget_queue_draw (priv->old_sample); + gtk_widget_queue_draw (priv->cur_sample); } static gboolean @@ -614,31 +606,42 @@ palette_paint (GtkWidget *drawing_area, GdkRectangle *area, gpointer data) { + cairo_t *cr; + gint focus_width; + if (drawing_area->window == NULL) return; - gdk_draw_rectangle (drawing_area->window, - drawing_area->style->bg_gc[GTK_STATE_NORMAL], - TRUE, - area->x, area->y, area->width, area->height); + cr = gdk_drawable_create_cairo_context (drawing_area->window); + + gdk_cairo_set_source_color (cr, &drawing_area->style->bg[GTK_STATE_NORMAL]); + cairo_rectangle (cr, + area->x, area->y, area->width, area->height); + cairo_fill (cr); if (GTK_WIDGET_HAS_FOCUS (drawing_area)) { - gint focus_width; - GdkGC *gc = get_focus_gc (drawing_area, &focus_width); - gdk_draw_rectangle (drawing_area->window, - gc, FALSE, focus_width / 2, focus_width / 2, - drawing_area->allocation.width - focus_width, - drawing_area->allocation.height - focus_width); - g_object_unref (gc); + set_focus_line_attributes (drawing_area, cr, &focus_width); + g_print ("%g %g %g %g\n", + focus_width / 2., focus_width / 2., + (double)drawing_area->allocation.width - focus_width, + (double)drawing_area->allocation.height - focus_width); + + cairo_rectangle (cr, + focus_width / 2., focus_width / 2., + drawing_area->allocation.width - focus_width, + drawing_area->allocation.height - focus_width); + cairo_stroke (cr); } + + cairo_destroy (cr); } -static GdkGC * -get_focus_gc (GtkWidget *drawing_area, - gint *focus_width) +static void +set_focus_line_attributes (GtkWidget *drawing_area, + cairo_t *cr, + gint *focus_width) { - GdkGC *gc = gdk_gc_new (drawing_area->window); gdouble color[4]; gint8 *dash_list; @@ -648,22 +651,42 @@ get_focus_gc (GtkWidget *drawing_area, NULL); palette_get_color (drawing_area, color); - + if (INTENSITY (color[0], color[1], color[2]) > 0.5) - gdk_gc_copy (gc, drawing_area->style->black_gc); + cairo_set_rgb_color (cr, 0., 0., 0.); else - gdk_gc_copy (gc, drawing_area->style->white_gc); + cairo_set_rgb_color (cr, 1., 1., 1.); - gdk_gc_set_line_attributes (gc, *focus_width, - dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID, - GDK_CAP_BUTT, GDK_JOIN_MITER); + cairo_set_line_width (cr, *focus_width); if (dash_list[0]) - gdk_gc_set_dashes (gc, 0, dash_list, strlen ((char *)dash_list)); + { + gint n_dashes = strlen (dash_list); + gdouble *dashes = g_new (gdouble, n_dashes); + gdouble total_length = 0; + gdouble dash_offset; + gint i; + + for (i = 0; i < n_dashes; i++) + { + dashes[i] = dash_list[i]; + total_length += dash_list[i]; + } + + /* The dash offset here aligns the pattern to integer pixels + * by starting the dash at the right side of the left border + * Negative dash offsets in cairo don't work + * (https://bugs.freedesktop.org/show_bug.cgi?id=2729) + */ + dash_offset = - *focus_width / 2.; + while (dash_offset < 0) + dash_offset += total_length; + + cairo_set_dash (cr, dashes, n_dashes, dash_offset); + g_free (dashes); + } g_free (dash_list); - - return gc; } static void @@ -1649,7 +1672,7 @@ update_color (GtkColorSelection *colorsel) gchar *ptr; priv->changing = TRUE; - color_sample_draw_samples (colorsel); + color_sample_update_samples (colorsel); gtk_hsv_set_color (GTK_HSV (priv->triangle_colorsel), priv->color[COLORSEL_HUE], @@ -2208,7 +2231,7 @@ gtk_color_selection_set_has_opacity_control (GtkColorSelection *colorsel, gtk_widget_hide (priv->opacity_label); gtk_widget_hide (priv->opacity_entry); } - color_sample_draw_samples (colorsel); + color_sample_update_samples (colorsel); g_object_notify (G_OBJECT (colorsel), "has_opacity_control"); } @@ -2448,7 +2471,7 @@ gtk_color_selection_set_previous_color (GtkColorSelection *colorsel, &priv->old_color[COLORSEL_HUE], &priv->old_color[COLORSEL_SATURATION], &priv->old_color[COLORSEL_VALUE]); - color_sample_draw_samples (colorsel); + color_sample_update_samples (colorsel); priv->default_set = TRUE; priv->changing = FALSE; } @@ -2472,7 +2495,7 @@ gtk_color_selection_set_previous_alpha (GtkColorSelection *colorsel, priv = colorsel->private_data; priv->changing = TRUE; priv->old_color[COLORSEL_OPACITY] = SCALE (alpha); - color_sample_draw_samples (colorsel); + color_sample_update_samples (colorsel); priv->default_alpha_set = TRUE; priv->changing = FALSE; } diff --git a/gtk/gtkhruler.c b/gtk/gtkhruler.c index 4f13d80d99..b4997c8957 100644 --- a/gtk/gtkhruler.c +++ b/gtk/gtkhruler.c @@ -135,7 +135,7 @@ static void gtk_hruler_draw_ticks (GtkRuler *ruler) { GtkWidget *widget; - GdkGC *gc, *bg_gc; + cairo_t *cr; gint i; gint width, height; gint xthickness; @@ -159,9 +159,6 @@ gtk_hruler_draw_ticks (GtkRuler *ruler) widget = GTK_WIDGET (ruler); - gc = widget->style->fg_gc[GTK_STATE_NORMAL]; - bg_gc = widget->style->bg_gc[GTK_STATE_NORMAL]; - xthickness = widget->style->xthickness; ythickness = widget->style->ythickness; @@ -179,13 +176,15 @@ gtk_hruler_draw_ticks (GtkRuler *ruler) NULL, widget, "hruler", 0, 0, widget->allocation.width, widget->allocation.height); - - - gdk_draw_line (ruler->backing_store, gc, - xthickness, - height + ythickness, - widget->allocation.width - xthickness, - height + ythickness); + + cr = gdk_drawable_create_cairo_context (ruler->backing_store); + gdk_cairo_set_source_color (cr, &widget->style->fg[widget->state]); + + cairo_rectangle (cr, + xthickness, + height + ythickness, + widget->allocation.width - 2 * xthickness, + 1); upper = ruler->upper / ruler->metric->pixels_per_unit; lower = ruler->lower / ruler->metric->pixels_per_unit; @@ -242,9 +241,9 @@ gtk_hruler_draw_ticks (GtkRuler *ruler) { pos = ROUND ((cur - lower) * increment); - gdk_draw_line (ruler->backing_store, gc, - pos, height + ythickness, - pos, height - length + ythickness); + cairo_rectangle (cr, + pos, height + ythickness - length, + 1, length); /* draw label */ if (i == 0) @@ -267,15 +266,16 @@ gtk_hruler_draw_ticks (GtkRuler *ruler) } } + cairo_fill (cr); + cairo_destroy (cr); + g_object_unref (layout); } static void gtk_hruler_draw_pos (GtkRuler *ruler) { - GtkWidget *widget; - GdkGC *gc; - int i; + GtkWidget *widget = GTK_WIDGET (ruler); gint x, y; gint width, height; gint bs_width, bs_height; @@ -285,24 +285,23 @@ gtk_hruler_draw_pos (GtkRuler *ruler) if (GTK_WIDGET_DRAWABLE (ruler)) { - widget = GTK_WIDGET (ruler); - - gc = widget->style->fg_gc[GTK_STATE_NORMAL]; xthickness = widget->style->xthickness; ythickness = widget->style->ythickness; width = widget->allocation.width; height = widget->allocation.height - ythickness * 2; - bs_width = height / 2; + bs_width = height / 2 + 2; bs_width |= 1; /* make sure it's odd */ bs_height = bs_width / 2 + 1; if ((bs_width > 0) && (bs_height > 0)) { + cairo_t *cr = gdk_drawable_create_cairo_context (widget->window); + /* If a backing store exists, restore the ruler */ - if (ruler->backing_store && ruler->non_gr_exp_gc) - gdk_draw_drawable (ruler->widget.window, - ruler->non_gr_exp_gc, + if (ruler->backing_store) + gdk_draw_drawable (widget->window, + widget->style->black_gc, ruler->backing_store, ruler->xsrc, ruler->ysrc, ruler->xsrc, ruler->ysrc, @@ -313,11 +312,14 @@ gtk_hruler_draw_pos (GtkRuler *ruler) x = ROUND ((ruler->position - ruler->lower) * increment) + (xthickness - bs_width) / 2 - 1; y = (height + bs_height) / 2 + ythickness; - for (i = 0; i < bs_height; i++) - gdk_draw_line (widget->window, gc, - x + i, y + i, - x + bs_width - 1 - i, y + i); + gdk_cairo_set_source_color (cr, &widget->style->fg[widget->state]); + + cairo_move_to (cr, x, y); + cairo_line_to (cr, x + bs_width / 2., y + bs_height); + cairo_line_to (cr, x + bs_width, y); + cairo_fill (cr); + cairo_destroy (cr); ruler->xsrc = x; ruler->ysrc = y; diff --git a/gtk/gtkhsv.c b/gtk/gtkhsv.c index cb73ecd8fc..cc8203d660 100644 --- a/gtk/gtkhsv.c +++ b/gtk/gtkhsv.c @@ -917,10 +917,30 @@ gtk_hsv_motion (GtkWidget *widget, /* Redrawing */ +void +set_source_surface (cairo_t *cr, + cairo_surface_t *surface) +{ + cairo_pattern_t *pattern; + cairo_matrix_t *matrix; + double x, y; + + pattern = cairo_pattern_create_for_surface (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); +} + /* Paints the hue ring */ static void paint_ring (GtkHSV *hsv, - GdkDrawable *drawable, + cairo_t *cr, gint x, gint y, gint width, @@ -932,13 +952,12 @@ paint_ring (GtkHSV *hsv, gdouble dx, dy, dist; gdouble center; gdouble inner, outer; - guchar *buf, *p; + guint32 *buf, *p; gdouble angle; gdouble hue; gdouble r, g, b; - GdkBitmap *mask; - GdkGC *gc; - GdkColor color; + cairo_surface_t *source; + cairo_t *source_cr; gint focus_width; gint focus_pad; @@ -954,13 +973,13 @@ paint_ring (GtkHSV *hsv, outer = priv->size / 2.0; inner = outer - priv->ring_width; - /* Paint the ring */ + /* Create an image initialized with the ring colors */ - buf = g_new (guchar, width * height * 3); + buf = g_new (guint32, width * height); for (yy = 0; yy < height; yy++) { - p = buf + yy * width * 3; + p = buf + yy * width; dy = -(yy + y - center); @@ -972,8 +991,6 @@ paint_ring (GtkHSV *hsv, if (dist < ((inner-1) * (inner-1)) || dist > ((outer+1) * (outer+1))) { *p++ = 0; - *p++ = 0; - *p++ = 0; continue; } @@ -988,54 +1005,21 @@ paint_ring (GtkHSV *hsv, b = 1.0; hsv_to_rgb (&r, &g, &b); - *p++ = floor (r * 255 + 0.5); - *p++ = floor (g * 255 + 0.5); - *p++ = floor (b * 255 + 0.5); + *p++ = (((int)floor (r * 255 + 0.5) << 16) | + ((int)floor (g * 255 + 0.5) << 8) | + (int)floor (b * 255 + 0.5)); } } - - /* Create clipping mask */ - - mask = gdk_pixmap_new (widget->window, width, height, 1); - gc = gdk_gc_new (mask); - - color.pixel = 0; - gdk_gc_set_foreground (gc, &color); - gdk_draw_rectangle (mask, gc, TRUE, - 0, 0, width, height); - - - color.pixel = 1; - gdk_gc_set_foreground (gc, &color); - gdk_draw_arc (mask, gc, TRUE, - focus_width + focus_pad - x, - focus_width + focus_pad - y, - priv->size - 1, priv->size - 1, - 0, 360 * 64); - - color.pixel = 0; - gdk_gc_set_foreground (gc, &color); - gdk_draw_arc (mask, gc, TRUE, - focus_width + focus_pad - x + priv->ring_width - 1, - focus_width + focus_pad - y + priv->ring_width - 1, - priv->size - 2 * priv->ring_width + 1, priv->size - 2 * priv->ring_width + 1, - 0, 360 * 64); - - g_object_unref (gc); - - gdk_gc_set_clip_mask (priv->gc, mask); - gdk_gc_set_clip_origin (priv->gc, 0, 0); - - /* Draw ring */ - - gdk_draw_rgb_image_dithalign (drawable, priv->gc, 0, 0, width, height, - GDK_RGB_DITHER_MAX, - buf, - width * 3, - x, y); - - /* Draw value marker */ + source = cairo_image_surface_create_for_data ((char *)buf, + CAIRO_FORMAT_RGB24, + width, height, 4 * width); + + /* Now draw the value marker onto the source image, so that it + * will get properly clipped at the edges of the ring + */ + source_cr = cairo_create (); + cairo_set_target_surface (source_cr, source); r = priv->h; g = 1.0; @@ -1043,31 +1027,36 @@ paint_ring (GtkHSV *hsv, hsv_to_rgb (&r, &g, &b); if (INTENSITY (r, g, b) > 0.5) - { - color.red = 0x0000; - color.green = 0x0000; - color.blue = 0x0000; - } + cairo_set_rgb_color (source_cr, 0., 0., 0.); else - { - color.red = 0xffff; - color.green = 0xffff; - color.blue = 0xffff; - } + cairo_set_rgb_color (source_cr, 1., 1., 1.); - gdk_gc_set_rgb_fg_color (priv->gc, &color); - - gdk_draw_line (drawable, priv->gc, - -x + center, -y + center, + cairo_move_to (source_cr, -x + center, - y + center); + cairo_line_to (source_cr, -x + center + cos (priv->h * 2.0 * G_PI) * center, -y + center - sin (priv->h * 2.0 * G_PI) * center); + cairo_stroke (source_cr); + cairo_destroy (source_cr); + + /* Draw the ring using the source image */ + + cairo_save (cr); + + cairo_move_to (cr, x, y); + set_source_surface (cr, source); + cairo_surface_destroy (source); + + cairo_set_line_width (cr, priv->ring_width); + cairo_new_path (cr); + cairo_arc (cr, + center, center, + priv->size / 2. - priv->ring_width / 2., + 0, 2 * M_PI); + cairo_stroke (cr); - gdk_gc_set_clip_mask (priv->gc, NULL); - g_object_unref (mask); + cairo_restore (cr); g_free (buf); - - /* Draw ring outline */ } /* Converts an HSV triplet to an integer RGB triplet */ @@ -1092,10 +1081,15 @@ get_color (gdouble h, ? ((a) + ((b) - (a)) * ((i) - (v1)) / ((v2) - (v1))) \ : (a)) +/* Number of pixels we extend out from the edges when creating + * color source to avoid artifacts + */ +#define PAD 3 + /* Paints the HSV triangle */ static void paint_triangle (GtkHSV *hsv, - GdkDrawable *drawable, + cairo_t *cr, gint x, gint y, gint width, @@ -1108,13 +1102,12 @@ paint_triangle (GtkHSV *hsv, gint x2, y2, r2, g2, b2; /* Second vertex */ gint x3, y3, r3, g3, b3; /* Third vertex */ gint t; - guchar *buf, *p; + guint32 *buf, *p; gint xl, xr, rl, rr, gl, gr, bl, br; /* Scanline data */ gint xx, yy; - GdkBitmap *mask; - GdkGC *gc; - GdkColor color; - GdkPoint points[3]; + gint x_interp, y_interp; + gint x_start, x_end; + cairo_surface_t *source; gdouble r, g, b; gchar *detail; @@ -1165,42 +1158,37 @@ paint_triangle (GtkHSV *hsv, /* Shade the triangle */ - buf = g_new (guchar, width * height * 3); + buf = g_new (guint32, width * height); for (yy = 0; yy < height; yy++) { - p = buf + yy * width * 3; + p = buf + yy * width; - if (yy + y < y1 || yy + y > y3) - for (xx = 0; xx < width; xx++) - { - *p++ = 0; - *p++ = 0; - *p++ = 0; - } - else { - if (yy + y < y2) + if (yy + y >= y1 - PAD && yy + y < y3 + PAD) { + y_interp = CLAMP (yy + y, y1, y3); + + if (y_interp < y2) { - xl = LERP (x1, x2, y1, y2, yy + y); + xl = LERP (x1, x2, y1, y2, y_interp); - rl = LERP (r1, r2, y1, y2, yy + y); - gl = LERP (g1, g2, y1, y2, yy + y); - bl = LERP (b1, b2, y1, y2, yy + y); + rl = LERP (r1, r2, y1, y2, y_interp); + gl = LERP (g1, g2, y1, y2, y_interp); + bl = LERP (b1, b2, y1, y2, y_interp); } else { - xl = LERP (x2, x3, y2, y3, yy + y); + xl = LERP (x2, x3, y2, y3, y_interp); - rl = LERP (r2, r3, y2, y3, yy + y); - gl = LERP (g2, g3, y2, y3, yy + y); - bl = LERP (b2, b3, y2, y3, yy + y); + rl = LERP (r2, r3, y2, y3, y_interp); + gl = LERP (g2, g3, y2, y3, y_interp); + bl = LERP (b2, b3, y2, y3, y_interp); } - xr = LERP (x1, x3, y1, y3, yy + y); + xr = LERP (x1, x3, y1, y3, y_interp); - rr = LERP (r1, r3, y1, y3, yy + y); - gr = LERP (g1, g3, y1, y3, yy + y); - br = LERP (b1, b3, y1, y3, yy + y); + rr = LERP (r1, r3, y1, y3, y_interp); + gr = LERP (g1, g3, y1, y3, y_interp); + br = LERP (b1, b3, y1, y3, y_interp); if (xl > xr) { @@ -1209,69 +1197,45 @@ paint_triangle (GtkHSV *hsv, SWAP (gl, gr, t); SWAP (bl, br, t); } - - for (xx = 0; xx < width; xx++) + + x_start = MAX (xl - PAD, x); + x_end = MIN (xr + PAD, x + width); + + p += (x_start - x); + + for (xx = x_start; xx < x_end; xx++) { - if (xx + x < xl || xx + x > xr) - { - *p++ = 0; - *p++ = 0; - *p++ = 0; - } - else - { - *p++ = LERP (rl, rr, xl, xr, xx + x); - *p++ = LERP (gl, gr, xl, xr, xx + x); - *p++ = LERP (bl, br, xl, xr, xx + x); - } + x_interp = CLAMP (xx, xl, xr); + + *p++ = ((LERP (rl, rr, xl, xr, x_interp) << 16) | + (LERP (gl, gr, xl, xr, x_interp) << 8) | + LERP (bl, br, xl, xr, x_interp)); } } } - - /* Create clipping mask */ - - mask = gdk_pixmap_new (widget->window, width, height, 1); - gc = gdk_gc_new (mask); - - color.pixel = 0; - gdk_gc_set_foreground (gc, &color); - gdk_draw_rectangle (mask, gc, TRUE, - 0, 0, width, height); + source = cairo_image_surface_create_for_data ((char *)buf, + CAIRO_FORMAT_RGB24, + width, height, 4 * width); - color.pixel = 1; - gdk_gc_set_foreground (gc, &color); - - points[0].x = x1 - x; - points[0].y = y1 - y; - points[1].x = x2 - x; - points[1].y = y2 - y; - points[2].x = x3 - x; - points[2].y = y3 - y; - gdk_draw_polygon (mask, gc, TRUE, points, 3); - - g_object_unref (gc); - - gdk_gc_set_clip_mask (priv->gc, mask); - gdk_gc_set_clip_origin (priv->gc, 0, 0); - - /* Draw triangle */ - - gdk_draw_rgb_image_dithalign (drawable, priv->gc, 0, 0, width, height, - GDK_RGB_DITHER_MAX, - buf, - width * 3, - x, y); + /* Draw a triangle with the image as a source */ + + cairo_move_to (cr, x, y); + set_source_surface (cr, source); + cairo_surface_destroy (source); - gdk_gc_set_clip_mask (priv->gc, NULL); - g_object_unref (mask); + cairo_move_to (cr, x1, y1); + cairo_line_to (cr, x2, y2); + cairo_line_to (cr, x3, y3); + cairo_close_path (cr); + cairo_fill (cr); g_free (buf); /* Draw value marker */ - xx = floor (sx + (vx - sx) * priv->v + (hx - vx) * priv->s * priv->v + 0.5) - x; - yy = floor (sy + (vy - sy) * priv->v + (hy - vy) * priv->s * priv->v + 0.5) - y; + xx = floor (sx + (vx - sx) * priv->v + (hx - vx) * priv->s * priv->v + 0.5); + yy = floor (sy + (vy - sy) * priv->v + (hy - vy) * priv->s * priv->v + 0.5); r = priv->h; g = priv->s; @@ -1281,33 +1245,21 @@ paint_triangle (GtkHSV *hsv, if (INTENSITY (r, g, b) > 0.5) { detail = "colorwheel_light"; - color.red = 0x0000; - color.green = 0x0000; - color.blue = 0x0000; + cairo_set_rgb_color (cr, 0., 0., 0.); } else { detail = "colorwheel_dark"; - color.red = 0xffff; - color.green = 0xffff; - color.blue = 0xffff; + cairo_set_rgb_color (cr, 1., 1., 1.); } - gdk_gc_set_rgb_fg_color (priv->gc, &color); - -#define OUTER_RADIUS 4 -#define INNER_RADIUS 3 +#define RADIUS 4 #define FOCUS_RADIUS 6 - - gdk_draw_arc (drawable, priv->gc, FALSE, - xx - OUTER_RADIUS, yy - OUTER_RADIUS, - OUTER_RADIUS * 2, OUTER_RADIUS * 2, - 0, 360 * 64); - gdk_draw_arc (drawable, priv->gc, FALSE, - xx - INNER_RADIUS, yy - INNER_RADIUS, - INNER_RADIUS * 2, INNER_RADIUS * 2, - 0, 360 * 64); + cairo_new_path (cr); + cairo_arc (cr, xx, yy, RADIUS, 0, 2 * M_PI); + cairo_stroke (cr); + /* Draw focus outline */ if (GTK_WIDGET_HAS_FOCUS (hsv) && @@ -1321,11 +1273,11 @@ paint_triangle (GtkHSV *hsv, "focus-padding", &focus_pad, NULL); - gtk_paint_focus (widget->style, drawable, + gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget), NULL, widget, detail, - xx - FOCUS_RADIUS - focus_width - focus_pad, - yy - FOCUS_RADIUS - focus_width - focus_pad, + widget->allocation.x + xx - FOCUS_RADIUS - focus_width - focus_pad, + widget->allocation.y + yy - FOCUS_RADIUS - focus_width - focus_pad, 2 * (FOCUS_RADIUS + focus_width + focus_pad), 2 * (FOCUS_RADIUS + focus_width + focus_pad)); } @@ -1335,14 +1287,14 @@ paint_triangle (GtkHSV *hsv, /* Paints the contents of the HSV color selector */ static void paint (GtkHSV *hsv, - GdkDrawable *drawable, + cairo_t *cr, gint x, gint y, gint width, gint height) { - paint_ring (hsv, drawable, x, y, width, height); - paint_triangle (hsv, drawable, x, y, width, height); + paint_ring (hsv, cr, x, y, width, height); + paint_triangle (hsv, cr, x, y, width, height); } /* Expose_event handler for the HSV color selector */ @@ -1353,14 +1305,14 @@ gtk_hsv_expose (GtkWidget *widget, GtkHSV *hsv; HSVPrivate *priv; GdkRectangle rect, dest; - GdkPixmap *pixmap; + cairo_t *cr; hsv = GTK_HSV (widget); priv = hsv->priv; if (!(GTK_WIDGET_DRAWABLE (widget) && event->window == widget->window)) return FALSE; - + rect.x = widget->allocation.x; rect.y = widget->allocation.y; rect.width = widget->allocation.width; @@ -1369,29 +1321,14 @@ gtk_hsv_expose (GtkWidget *widget, if (!gdk_rectangle_intersect (&event->area, &rect, &dest)) return FALSE; - pixmap = gdk_pixmap_new (widget->window, dest.width, dest.height, - gtk_widget_get_visual (widget)->depth); - - rect = dest; - rect.x = 0; - rect.y = 0; - - gdk_draw_rectangle (pixmap, - widget->style->bg_gc[GTK_WIDGET_STATE (widget)], - TRUE, - 0, 0, dest.width, dest.height); - paint (hsv, pixmap, - dest.x - widget->allocation.x, dest.y - widget->allocation.y, + cr = gdk_drawable_create_cairo_context (widget->window); + + cairo_translate (cr, widget->allocation.x, widget->allocation.y); + paint (hsv, cr, + dest.x - widget->allocation.x, + dest.y - widget->allocation.y, dest.width, dest.height); - gdk_draw_drawable (widget->window, - priv->gc, - pixmap, - 0, 0, - dest.x, - dest.y, - event->area.width, event->area.height); - if (GTK_WIDGET_HAS_FOCUS (hsv) && priv->focus_on_ring) gtk_paint_focus (widget->style, widget->window, GTK_WIDGET_STATE (widget), @@ -1401,8 +1338,6 @@ gtk_hsv_expose (GtkWidget *widget, widget->allocation.width, widget->allocation.height); - g_object_unref (pixmap); - return FALSE; } diff --git a/gtk/gtkiconview.c b/gtk/gtkiconview.c index 8fc55ca328..c36301f399 100644 --- a/gtk/gtkiconview.c +++ b/gtk/gtkiconview.c @@ -202,9 +202,11 @@ static void gtk_icon_view_adjustment_changed (GtkAdjustment *ad GtkIconView *icon_view); static void gtk_icon_view_layout (GtkIconView *icon_view); static void gtk_icon_view_paint_item (GtkIconView *icon_view, + cairo_t *cr, GtkIconViewItem *item, GdkRectangle *area); static void gtk_icon_view_paint_rubberband (GtkIconView *icon_view, + cairo_t *cr, GdkRectangle *area); static void gtk_icon_view_queue_draw_item (GtkIconView *icon_view, GtkIconViewItem *item); @@ -989,12 +991,16 @@ gtk_icon_view_expose (GtkWidget *widget, { GtkIconView *icon_view; GList *icons; + cairo_t *cr; icon_view = GTK_ICON_VIEW (widget); if (expose->window != icon_view->priv->bin_window) return FALSE; + cr = gdk_drawable_create_cairo_context (icon_view->priv->bin_window); + cairo_set_line_width (cr, 1.); + for (icons = icon_view->priv->items; icons; icons = icons->next) { GtkIconViewItem *item = icons->data; GdkRectangle item_rectangle; @@ -1008,23 +1014,21 @@ gtk_icon_view_expose (GtkWidget *widget, continue; #ifdef DEBUG_ICON_VIEW - gdk_draw_rectangle (icon_view->priv->bin_window, - GTK_WIDGET (icon_view)->style->black_gc, - FALSE, - item->x, item->y, - item->width, item->height); - gdk_draw_rectangle (icon_view->priv->bin_window, - GTK_WIDGET (icon_view)->style->black_gc, - FALSE, - item->pixbuf_x, item->pixbuf_y, - item->pixbuf_width, item->pixbuf_height); - gdk_draw_rectangle (icon_view->priv->bin_window, - GTK_WIDGET (icon_view)->style->black_gc, - FALSE, - item->layout_x, item->layout_y, - item->layout_width, item->layout_height); + cairo_rectangle (cr, + item->x + 0.5, item->y + 0.5, + item->width - 1, item->height - 1); + cairo_rectangle (cr, + item->x + 0.5, item->y + 0.5, + item->width - 1, item->height- 1); + cairo_rectangle (cr, + item->pixbuf_x + 0.5, item->pixbuf_y + 0.5, + item->pixbuf_width - 1, item->pixbuf_height- 1); + cairo_rectangle (cr, + item->layout_x + 0.5, item->layout_y + 0.5, + item->layout_width - 1, item->layout_height - 1); + cairo_stroke (cr); #endif - gtk_icon_view_paint_item (icon_view, item, &expose->area); + gtk_icon_view_paint_item (icon_view, cr, item, &expose->area); } @@ -1038,11 +1042,13 @@ gtk_icon_view_expose (GtkWidget *widget, &n_rectangles); while (n_rectangles--) - gtk_icon_view_paint_rubberband (icon_view, &rectangles[n_rectangles]); + gtk_icon_view_paint_rubberband (icon_view, cr, &rectangles[n_rectangles]); g_free (rectangles); } + cairo_destroy (cr); + return TRUE; } @@ -1995,6 +2001,7 @@ create_colorized_pixbuf (GdkPixbuf *src, GdkColor *new_color) static void gtk_icon_view_paint_item (GtkIconView *icon_view, + cairo_t *cr, GtkIconViewItem *item, GdkRectangle *area) { @@ -2027,14 +2034,15 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, } else pixbuf = tmp; + + cairo_move_to (cr, item->pixbuf_x, item->pixbuf_y); + gdk_pixbuf_set_as_cairo_source (pixbuf, cr); + g_object_unref (pixbuf); - gdk_draw_pixbuf (icon_view->priv->bin_window, NULL, pixbuf, - 0, 0, + cairo_rectangle (cr, item->pixbuf_x, item->pixbuf_y, - item->pixbuf_width, item->pixbuf_height, - GDK_RGB_DITHER_NORMAL, item->pixbuf_width, item->pixbuf_height); - g_object_unref (pixbuf); + cairo_fill (cr); } if (icon_view->priv->text_column != -1 || @@ -2042,13 +2050,13 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, { if (item->selected) { - gdk_draw_rectangle (icon_view->priv->bin_window, - GTK_WIDGET (icon_view)->style->base_gc[state], - TRUE, - item->layout_x - ICON_TEXT_PADDING, - item->layout_y - ICON_TEXT_PADDING, - item->layout_width + 2 * ICON_TEXT_PADDING, - item->layout_height + 2 * ICON_TEXT_PADDING); + gdk_cairo_set_source_color (cr, >K_WIDGET (icon_view)->style->base[state]); + cairo_rectangle (cr, + item->layout_x - ICON_TEXT_PADDING, + item->layout_y - ICON_TEXT_PADDING, + item->layout_width + 2 * ICON_TEXT_PADDING, + item->layout_height + 2 * ICON_TEXT_PADDING); + cairo_fill (cr); } gtk_icon_view_update_item_text (icon_view, item); @@ -2077,26 +2085,14 @@ gtk_icon_view_paint_item (GtkIconView *icon_view, } } -static guint32 -gtk_gdk_color_to_rgb (const GdkColor *color) -{ - guint32 result; - result = (0xff0000 | (color->red & 0xff00)); - result <<= 8; - result |= ((color->green & 0xff00) | (color->blue >> 8)); - return result; -} - static void gtk_icon_view_paint_rubberband (GtkIconView *icon_view, + cairo_t *cr, GdkRectangle *area) { GdkRectangle rect; - GdkPixbuf *pixbuf; - GdkGC *gc; GdkRectangle rubber_rect; GdkColor *fill_color_gdk; - guint fill_color; guchar fill_color_alpha; rubber_rect.x = MIN (icon_view->priv->rubberband_x1, icon_view->priv->rubberband_x2); @@ -2112,38 +2108,25 @@ gtk_icon_view_paint_rubberband (GtkIconView *icon_view, "selection_box_alpha", &fill_color_alpha, NULL); - if (!fill_color_gdk) { + if (!fill_color_gdk) fill_color_gdk = gdk_color_copy (>K_WIDGET (icon_view)->style->base[GTK_STATE_SELECTED]); - } - fill_color = gtk_gdk_color_to_rgb (fill_color_gdk) << 8 | fill_color_alpha; + gdk_cairo_set_source_color (cr, fill_color_gdk); + cairo_set_alpha (cr, fill_color_alpha / 255.); - if (!gdk_draw_rectangle_alpha_libgtk_only (icon_view->priv->bin_window, - rect.x, rect.y, rect.width, rect.height, - fill_color_gdk, - fill_color_alpha << 8 | fill_color_alpha)) - { - pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, rect.width, rect.height); - gdk_pixbuf_fill (pixbuf, fill_color); - - gdk_draw_pixbuf (icon_view->priv->bin_window, NULL, pixbuf, - 0, 0, - rect.x,rect.y, - rect.width, rect.height, - GDK_RGB_DITHER_NONE, - 0, 0); - g_object_unref (pixbuf); - } + cairo_save (cr); + cairo_rectangle (cr, rect.x, rect.y, rect.width, rect.height); + cairo_clip (cr); + cairo_fill (cr); + + cairo_set_alpha (cr, 1.0); + cairo_rectangle (cr, + rubber_rect.x + 0.5, rubber_rect.y + 0.5, + rubber_rect.width - 1, rubber_rect.height - 1); + cairo_stroke (cr); + cairo_restore (cr); - gc = gdk_gc_new (icon_view->priv->bin_window); - gdk_gc_set_rgb_fg_color (gc, fill_color_gdk); - gdk_gc_set_clip_rectangle (gc, &rect); - gdk_draw_rectangle (icon_view->priv->bin_window, - gc, FALSE, - rubber_rect.x, rubber_rect.y, - rubber_rect.width - 1, rubber_rect.height - 1); gdk_color_free (fill_color_gdk); - g_object_unref (gc); } static void diff --git a/gtk/gtkruler.c b/gtk/gtkruler.c index 8f8c02edfc..6c1370104a 100644 --- a/gtk/gtkruler.c +++ b/gtk/gtkruler.c @@ -159,7 +159,6 @@ static void gtk_ruler_init (GtkRuler *ruler) { ruler->backing_store = NULL; - ruler->non_gr_exp_gc = NULL; ruler->xsrc = 0; ruler->ysrc = 0; ruler->slider_size = 0; @@ -391,8 +390,6 @@ gtk_ruler_unrealize (GtkWidget *widget) if (ruler->backing_store) g_object_unref (ruler->backing_store); - if (ruler->non_gr_exp_gc) - g_object_unref (ruler->non_gr_exp_gc); ruler->backing_store = NULL; ruler->non_gr_exp_gc = NULL; diff --git a/gtk/gtkruler.h b/gtk/gtkruler.h index a27c698663..e0512ecb8b 100644 --- a/gtk/gtkruler.h +++ b/gtk/gtkruler.h @@ -67,7 +67,7 @@ struct _GtkRuler GtkWidget widget; GdkPixmap *backing_store; - GdkGC *non_gr_exp_gc; + GdkGC *non_gr_exp_gc; /* unused */ GtkRulerMetric *metric; gint xsrc, ysrc; gint slider_size; diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index f74f5cc265..badf30abd1 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -45,7 +45,7 @@ struct _GtkSettingsPropertyValue GtkSettingsSource source; }; -#ifdef GDK_WINDOWING_X11 +#if 0 #include <pango/pangoxft.h> #include <gdk/x11/gdkx.h> #endif @@ -133,7 +133,7 @@ gtk_settings_get_type (void) return settings_type; } -#ifdef GDK_WINDOWING_X11 +#if 0 static void gtk_default_substitute (FcPattern *pattern, gpointer data) @@ -478,7 +478,7 @@ gtk_settings_get_for_screen (GdkScreen *screen) settings->screen = screen; g_object_set_data (G_OBJECT (screen), "gtk-settings", settings); -#ifdef GDK_WINDOWING_X11 +#if 0 /* Set the default substitution function for the Pango fontmap. */ pango_xft_set_default_substitute (GDK_SCREEN_XDISPLAY (screen), @@ -615,7 +615,7 @@ gtk_settings_notify (GObject *object, case PROP_DOUBLE_CLICK_DISTANCE: settings_update_double_click (settings); break; -#ifdef GDK_WINDOWING_X11 +#if 0 case PROP_XFT_ANTIALIAS: case PROP_XFT_HINTING: case PROP_XFT_HINTSTYLE: diff --git a/gtk/gtkstyle.c b/gtk/gtkstyle.c index c641b1f85a..8f9adc4d3a 100644 --- a/gtk/gtkstyle.c +++ b/gtk/gtkstyle.c @@ -325,128 +325,6 @@ static GdkFont *gtk_style_get_font_internal (GtkStyle *style); static const GtkRequisition default_option_indicator_size = { 7, 13 }; static const GtkBorder default_option_indicator_spacing = { 7, 5, 2, 2 }; -#define INDICATOR_PART_SIZE 13 - -typedef enum { - CHECK_AA, - CHECK_BASE, - CHECK_BLACK, - CHECK_DARK, - CHECK_LIGHT, - CHECK_MID, - CHECK_TEXT, - CHECK_INCONSISTENT_TEXT, - RADIO_BASE, - RADIO_BLACK, - RADIO_DARK, - RADIO_LIGHT, - RADIO_MID, - RADIO_TEXT, - RADIO_INCONSISTENT_AA, - RADIO_INCONSISTENT_TEXT -} IndicatorPart; - -/* - * Extracted from check-13.png, width=13, height=13 - */ -static const guchar check_black_bits[] = { - 0x00,0x00,0xfe,0x0f,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02, - 0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x00,0x00,0x00,0x00}; -static const guchar check_dark_bits[] = { - 0xff,0x1f,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01, - 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x00,0x00}; -static const guchar check_mid_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00, - 0x08,0x00,0x08,0x00,0x08,0x00,0x08,0xfc,0x0f,0x00,0x00,0x00,0x00}; -static const guchar check_light_bits[] = { - 0x00,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00, - 0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0xfe,0x1f,0x00,0x00}; -static const guchar check_text_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x03,0x80,0x01,0x80,0x00,0x58, - 0x00,0x60,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -static const guchar check_aa_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x58,0x00,0xa0, - 0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -static const guchar check_base_bits[] = { - 0x00,0x00,0x00,0x00,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc, - 0x07,0xfc,0x07,0xfc,0x07,0xfc,0x07,0x00,0x00,0x00,0x00,0x00,0x00}; - -/* - * Extracted from check-13-inconsistent.png, width=13, height=13 - */ -static const guchar check_inconsistent_text_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x03,0xf8, - 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -#if 0 -/* - * check_inconsistent_aa_bits is currently not used, since it is all zeros. - */ -static const guchar check_inconsistent_aa_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -#endif - -/* - * Extracted from radio-13.png, width=13, height=13 - */ -static const guchar radio_black_bits[] = { - 0x00,0x00,0xf0,0x01,0x0c,0x02,0x04,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02, - 0x00,0x02,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x08}; -static const guchar radio_dark_bits[] = { - 0xf0,0x00,0x0c,0x02,0x02,0x04,0x02,0x04,0x01,0x08,0x01,0x08,0x01,0x08,0x01, - 0x08,0x00,0x08,0x02,0x04,0x0c,0x06,0xf0,0x01,0x00,0x00,0x00,0x00}; -static const guchar radio_mid_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -static const guchar radio_light_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x10,0x00, - 0x10,0x00,0x10,0x00,0x08,0x00,0x08,0x00,0x06,0xe0,0x01,0x00,0x00}; -static const guchar radio_text_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x00,0xf0,0x01,0xf0,0x01,0xf0, - 0x01,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -#if 0 -/* - * radio_aa_bits is currently not used, since it is all zeros. - */ -static const guchar radio_aa_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -#endif -static const guchar radio_base_bits[] = { - 0x00,0x00,0x00,0x00,0xf0,0x01,0xf8,0x03,0xfc,0x07,0xfc,0x07,0xfc,0x07,0xfc, - 0x07,0xfc,0x07,0xf8,0x03,0xf0,0x01,0x00,0x00,0x00,0x00,0x00,0x00}; - -/* - * Extracted from radio-13.png, width=13, height=13 - */ -static const guchar radio_inconsistent_text_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x03,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -static const guchar radio_inconsistent_aa_bits[] = { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x03,0x00,0x00,0xf8, - 0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - -static struct { - const guchar *bits; - GList *bmap_list; /* list of GdkBitmap */ -} indicator_parts[] = { - { check_aa_bits, NULL }, - { check_base_bits, NULL }, - { check_black_bits, NULL }, - { check_dark_bits, NULL }, - { check_light_bits, NULL }, - { check_mid_bits, NULL }, - { check_text_bits, NULL }, - { check_inconsistent_text_bits, NULL }, - { radio_base_bits, NULL }, - { radio_black_bits, NULL }, - { radio_dark_bits, NULL }, - { radio_light_bits, NULL }, - { radio_mid_bits, NULL }, - { radio_text_bits, NULL }, - { radio_inconsistent_aa_bits, NULL }, - { radio_inconsistent_text_bits, NULL }, -}; #define GTK_GRAY 0xdcdc, 0xdada, 0xd5d5 #define GTK_DARK_GRAY 0xc4c4, 0xc2c2, 0xbdbd #define GTK_LIGHT_GRAY 0xeeee, 0xebeb, 0xe7e7 @@ -2263,57 +2141,6 @@ sanitize_size (GdkWindow *window, gdk_drawable_get_size (window, NULL, height); } -static GdkBitmap * -get_indicator_for_screen (GdkDrawable *drawable, - IndicatorPart part) - -{ - GdkScreen *screen = gdk_drawable_get_screen (drawable); - GdkBitmap *bitmap; - GList *tmp_list; - - tmp_list = indicator_parts[part].bmap_list; - while (tmp_list) - { - bitmap = tmp_list->data; - - if (gdk_drawable_get_screen (bitmap) == screen) - return bitmap; - - tmp_list = tmp_list->next; - } - - bitmap = gdk_bitmap_create_from_data (drawable, - (gchar *)indicator_parts[part].bits, - INDICATOR_PART_SIZE, INDICATOR_PART_SIZE); - indicator_parts[part].bmap_list = g_list_prepend (indicator_parts[part].bmap_list, bitmap); - - return bitmap; -} - -static void -draw_part (GdkDrawable *drawable, - GdkGC *gc, - GdkRectangle *area, - gint x, - gint y, - IndicatorPart part) -{ - if (area) - gdk_gc_set_clip_rectangle (gc, area); - - gdk_gc_set_ts_origin (gc, x, y); - gdk_gc_set_stipple (gc, get_indicator_for_screen (drawable, part)); - gdk_gc_set_fill (gc, GDK_STIPPLED); - - gdk_draw_rectangle (drawable, gc, TRUE, x, y, INDICATOR_PART_SIZE, INDICATOR_PART_SIZE); - - gdk_gc_set_fill (gc, GDK_SOLID); - - if (area) - gdk_gc_set_clip_rectangle (gc, NULL); -} - static void gtk_default_draw_hline (GtkStyle *style, GdkWindow *window, @@ -3065,7 +2892,7 @@ gtk_default_draw_polygon (GtkStyle *style, static void draw_arrow (GdkWindow *window, - GdkGC *gc, + GdkColor *color, GdkRectangle *area, GtkArrowType arrow_type, gint x, @@ -3073,34 +2900,49 @@ draw_arrow (GdkWindow *window, gint width, gint height) { - gint i, j; - + cairo_t *cr = gdk_drawable_create_cairo_context (window); + gdk_cairo_set_source_color (cr, color); + if (area) - gdk_gc_set_clip_rectangle (gc, area); - + { + cairo_save (cr); + cairo_rectangle (cr, area->x, area->y, area->width, area->height); + cairo_clip (cr); + cairo_new_path (cr); + } + if (arrow_type == GTK_ARROW_DOWN) { - for (i = 0, j = 0; i < height; i++, j++) - gdk_draw_line (window, gc, x + j, y + i, x + width - j - 1, y + i); + cairo_move_to (cr, x, y); + cairo_line_to (cr, x + width, y); + cairo_line_to (cr, x + width / 2., y + height); } else if (arrow_type == GTK_ARROW_UP) { - for (i = height - 1, j = 0; i >= 0; i--, j++) - gdk_draw_line (window, gc, x + j, y + i, x + width - j - 1, y + i); + cairo_move_to (cr, x, y + height); + cairo_line_to (cr, x + width / 2., y); + cairo_line_to (cr, x + width, y + height); } else if (arrow_type == GTK_ARROW_LEFT) { - for (i = width - 1, j = 0; i >= 0; i--, j++) - gdk_draw_line (window, gc, x + i, y + j, x + i, y + height - j - 1); + cairo_move_to (cr, x + width, y); + cairo_line_to (cr, x + width, y + height); + cairo_line_to (cr, x, y + height / 2.); } else if (arrow_type == GTK_ARROW_RIGHT) { - for (i = 0, j = 0; i < width; i++, j++) - gdk_draw_line (window, gc, x + i, y + j, x + i, y + height - j - 1); + cairo_move_to (cr, x, y); + cairo_line_to (cr, x + width, y + height / 2.); + cairo_line_to (cr, x, y + height); } + cairo_close_path (cr); + cairo_fill (cr); + if (area) - gdk_gc_set_clip_rectangle (gc, NULL); + cairo_restore (cr); + + cairo_destroy (cr); } static void @@ -3200,9 +3042,9 @@ gtk_default_draw_arrow (GtkStyle *style, y++; if (state == GTK_STATE_INSENSITIVE) - draw_arrow (window, style->white_gc, area, arrow_type, + draw_arrow (window, &style->white, area, arrow_type, x + 1, y + 1, width, height); - draw_arrow (window, style->fg_gc[state], area, arrow_type, + draw_arrow (window, &style->fg[state], area, arrow_type, x, y, width, height); } @@ -3760,21 +3602,6 @@ gtk_default_draw_flat_box (GtkStyle *style, g_object_unref (freeme); } -static GdkGC * -create_aa_gc (GdkWindow *window, GtkStyle *style, GtkStateType state_type) -{ - GdkColor aa_color; - GdkGC *gc = gdk_gc_new (window); - - aa_color.red = (style->fg[state_type].red + style->bg[state_type].red) / 2; - aa_color.green = (style->fg[state_type].green + style->bg[state_type].green) / 2; - aa_color.blue = (style->fg[state_type].blue + style->bg[state_type].blue) / 2; - - gdk_gc_set_rgb_fg_color (gc, &aa_color); - - return gc; -} - static void gtk_default_draw_check (GtkStyle *style, GdkWindow *window, @@ -3788,92 +3615,121 @@ gtk_default_draw_check (GtkStyle *style, gint width, gint height) { - if (detail && strcmp (detail, "cellcheck") == 0) - { - if (area) - gdk_gc_set_clip_rectangle (widget->style->base_gc[state_type], area); - gdk_draw_rectangle (window, - widget->style->base_gc[state_type], - TRUE, - x, y, - width, height); - if (area) - { - gdk_gc_set_clip_rectangle (widget->style->base_gc[state_type], NULL); - gdk_gc_set_clip_rectangle (widget->style->text_gc[state_type], area); - } - gdk_draw_rectangle (window, - widget->style->text_gc[state_type], - FALSE, - x, y, - width, height); - if (area) - gdk_gc_set_clip_rectangle (widget->style->text_gc[state_type], NULL); - - x -= (1 + INDICATOR_PART_SIZE - width) / 2; - y -= (((1 + INDICATOR_PART_SIZE - height) / 2) - 1); - if (shadow_type == GTK_SHADOW_IN) - { - draw_part (window, style->text_gc[state_type], area, x, y, CHECK_TEXT); - draw_part (window, style->text_aa_gc[state_type], area, x, y, CHECK_AA); - } - else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */ - { - draw_part (window, style->text_gc[state_type], area, x, y, CHECK_INCONSISTENT_TEXT); - } - } - else + cairo_t *cr = gdk_drawable_create_cairo_context (window); + enum { BUTTON, MENU, CELL } type = BUTTON; + int exterior_size; + int interior_size; + int pad; + + if (detail) { - GdkGC *free_me = NULL; + if (strcmp (detail, "cellcheck") == 0) + type = CELL; + else if (strcmp (detail, "check") == 0) + type = MENU; + } - GdkGC *base_gc; - GdkGC *text_gc; - GdkGC *aa_gc; + if (area) + { + cairo_save (cr); + cairo_rectangle (cr, area->x, area->y, area->width, area->height); + cairo_clip (cr); + cairo_new_path (cr); + } + + exterior_size = MIN (width, height); + if (exterior_size % 2 == 0) /* Ensure odd */ + exterior_size -= -1; - x -= (1 + INDICATOR_PART_SIZE - width) / 2; - y -= (1 + INDICATOR_PART_SIZE - height) / 2; + pad = style->xthickness + MAX (1, (exterior_size - 2 * style->xthickness) / 9); + interior_size = MAX (1, exterior_size - 2 * pad); - if (detail && strcmp (detail, "check") == 0) /* Menu item */ - { - text_gc = style->fg_gc[state_type]; - base_gc = style->bg_gc[state_type]; - aa_gc = free_me = create_aa_gc (window, style, state_type); - } + if (interior_size < 7) + { + interior_size = 7; + pad = MAX (0, (exterior_size - interior_size) / 2); + } + + x -= (1 + exterior_size - width) / 2; + y -= (1 + exterior_size - height) / 2; + + switch (type) + { + case BUTTON: + case CELL: + if (type == BUTTON) + gdk_cairo_set_source_color (cr, &style->fg[state_type]); else - { - if (state_type == GTK_STATE_ACTIVE) - { - text_gc = style->fg_gc[state_type]; - base_gc = style->bg_gc[state_type]; - aa_gc = free_me = create_aa_gc (window, style, state_type); - } - else - { - text_gc = style->text_gc[state_type]; - base_gc = style->base_gc[state_type]; - aa_gc = style->text_aa_gc[state_type]; - } + gdk_cairo_set_source_color (cr, &style->text[state_type]); + + cairo_set_line_width (cr, 1.0); + cairo_rectangle (cr, x + 0.5, y + 0.5, exterior_size - 1, exterior_size - 1); + cairo_stroke (cr); - draw_part (window, base_gc, area, x, y, CHECK_BASE); - draw_part (window, style->black_gc, area, x, y, CHECK_BLACK); - draw_part (window, style->dark_gc[state_type], area, x, y, CHECK_DARK); - draw_part (window, style->mid_gc[state_type], area, x, y, CHECK_MID); - draw_part (window, style->light_gc[state_type], area, x, y, CHECK_LIGHT); - } + gdk_cairo_set_source_color (cr, &style->base[state_type]); + cairo_rectangle (cr, x + 1, y + 1, exterior_size - 2, exterior_size - 2); + cairo_fill (cr); + break; - if (shadow_type == GTK_SHADOW_IN) - { - draw_part (window, text_gc, area, x, y, CHECK_TEXT); - draw_part (window, aa_gc, area, x, y, CHECK_AA); - } - else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */ - { - draw_part (window, text_gc, area, x, y, CHECK_INCONSISTENT_TEXT); - } + case MENU: + break; + } + + switch (type) + { + case BUTTON: + case CELL: + gdk_cairo_set_source_color (cr, &style->text[state_type]); + break; + case MENU: + gdk_cairo_set_source_color (cr, &style->fg[state_type]); + break; + } - if (free_me) - g_object_unref (free_me); + if (shadow_type == GTK_SHADOW_IN) + { + cairo_translate (cr, + x + pad, y + pad); + + cairo_scale (cr, interior_size / 7., interior_size / 7.); + + cairo_move_to (cr, 7.0, 0.0); + cairo_line_to (cr, 7.5, 1.0); + cairo_curve_to (cr, 5.3, 2.0, + 4.3, 4.0, + 3.5, 7.0); + cairo_curve_to (cr, 3.0, 5.7, + 1.3, 4.7, + 0.0, 4.7); + cairo_line_to (cr, 0.2, 3.5); + cairo_curve_to (cr, 1.1, 3.5, + 2.3, 4.3, + 3.0, 5.0); + cairo_curve_to (cr, 1.0, 3.9, + 2.4, 4.1, + 3.2, 4.9); + cairo_curve_to (cr, 3.5, 3.1, + 5.2, 2.0, + 7.0, 0.0); + + cairo_fill (cr); } + else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */ + { + int line_thickness = MAX (1, (3 + interior_size * 2) / 7); + + cairo_rectangle (cr, + x + pad, + y + pad + (1 + interior_size - line_thickness) / 2, + interior_size, + line_thickness); + cairo_fill (cr); + } + + if (area) + cairo_restore (cr); + + cairo_destroy (cr); } static void @@ -3889,96 +3745,118 @@ gtk_default_draw_option (GtkStyle *style, gint width, gint height) { - if (detail && strcmp (detail, "cellradio") == 0) - { - if (area) - gdk_gc_set_clip_rectangle (widget->style->fg_gc[state_type], area); - gdk_draw_arc (window, - widget->style->fg_gc[state_type], - FALSE, - x, y, - width, - height, - 0, 360*64); - - if (shadow_type == GTK_SHADOW_IN) - { - gdk_draw_arc (window, - widget->style->fg_gc[state_type], - TRUE, - x + 2, - y + 2, - width - 4, - height - 4, - 0, 360*64); - } - else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */ - { - draw_part (window, widget->style->fg_gc[state_type], - area, x, y, CHECK_INCONSISTENT_TEXT); - } - if (area) - gdk_gc_set_clip_rectangle (widget->style->fg_gc[state_type], NULL); + cairo_t *cr = gdk_drawable_create_cairo_context (window); + enum { BUTTON, MENU, CELL } type = BUTTON; + int exterior_size; + + if (detail) + { + if (strcmp (detail, "radio") == 0) + type = CELL; + else if (strcmp (detail, "option") == 0) + type = MENU; } - else + + if (area) + { + cairo_save (cr); + cairo_rectangle (cr, area->x, area->y, area->width, area->height); + cairo_clip (cr); + cairo_new_path (cr); + } + + exterior_size = MIN (width, height); + if (exterior_size % 2 == 0) /* Ensure odd */ + exterior_size -= -1; + + x -= (1 + exterior_size - width) / 2; + y -= (1 + exterior_size - height) / 2; + + switch (type) { - GdkGC *free_me = NULL; + case BUTTON: + case CELL: + gdk_cairo_set_source_color (cr, &style->base[state_type]); - GdkGC *base_gc; - GdkGC *text_gc; - GdkGC *aa_gc; + cairo_arc (cr, + x + exterior_size / 2., + y + exterior_size / 2., + (exterior_size - 1) / 2., + 0, 2 * M_PI); + + cairo_save (cr); + cairo_fill (cr); + cairo_restore (cr); + + if (type == BUTTON) + gdk_cairo_set_source_color (cr, &style->fg[state_type]); + else + gdk_cairo_set_source_color (cr, &style->text[state_type]); + + cairo_set_line_width (cr, 1.); + cairo_stroke (cr); + break; - x -= (1 + INDICATOR_PART_SIZE - width) / 2; - y -= (1 + INDICATOR_PART_SIZE - height) / 2; + case MENU: + break; + } + + switch (type) + { + case BUTTON: + gdk_cairo_set_source_color (cr, &style->text[state_type]); + break; + case CELL: + break; + case MENU: + gdk_cairo_set_source_color (cr, &style->fg[state_type]); + break; + } - if (detail && strcmp (detail, "option") == 0) /* Menu item */ + if (shadow_type == GTK_SHADOW_IN) + { + int pad = style->xthickness + MAX (1, 2 * (exterior_size - 2 * style->xthickness) / 9); + int interior_size = MAX (1, exterior_size - 2 * pad); + + if (interior_size < 5) { - text_gc = style->fg_gc[state_type]; - base_gc = style->bg_gc[state_type]; - aa_gc = free_me = create_aa_gc (window, style, state_type); + interior_size = 7; + pad = MAX (0, (exterior_size - interior_size) / 2); } - else - { - if (state_type == GTK_STATE_ACTIVE) - { - text_gc = style->fg_gc[state_type]; - base_gc = style->bg_gc[state_type]; - aa_gc = free_me = create_aa_gc (window, style, state_type); - } - else - { - text_gc = style->text_gc[state_type]; - base_gc = style->base_gc[state_type]; - aa_gc = style->text_aa_gc[state_type]; - } - draw_part (window, base_gc, area, x, y, RADIO_BASE); - draw_part (window, style->black_gc, area, x, y, RADIO_BLACK); - draw_part (window, style->dark_gc[state_type], area, x, y, RADIO_DARK); - draw_part (window, style->mid_gc[state_type], area, x, y, RADIO_MID); - draw_part (window, style->light_gc[state_type], area, x, y, RADIO_LIGHT); - } + cairo_arc (cr, + x + pad + interior_size / 2., + y + pad + interior_size / 2., + interior_size / 2., + 0, 2 * M_PI); + cairo_fill (cr); + } + else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */ + { + int pad = style->xthickness + MAX (1, (exterior_size - 2 * style->xthickness) / 9); + int interior_size = MAX (1, exterior_size - 2 * pad); + int line_thickness; - if (shadow_type == GTK_SHADOW_IN) + if (interior_size < 7) { - draw_part (window, text_gc, area, x, y, RADIO_TEXT); - } - else if (shadow_type == GTK_SHADOW_ETCHED_IN) /* inconsistent */ - { - if (detail && strcmp (detail, "option") == 0) /* Menu item */ - { - draw_part (window, text_gc, area, x, y, CHECK_INCONSISTENT_TEXT); - } - else - { - draw_part (window, text_gc, area, x, y, RADIO_INCONSISTENT_TEXT); - draw_part (window, aa_gc, area, x, y, RADIO_INCONSISTENT_AA); - } + interior_size = 7; + pad = MAX (0, (exterior_size - interior_size) / 2); } - if (free_me) - g_object_unref (free_me); + line_thickness = MAX (1, (3 + interior_size * 2) / 7); + + cairo_rectangle (cr, + x + pad, + y + pad + (interior_size - line_thickness) / 2., + interior_size, + line_thickness); + cairo_fill (cr); } + + if (area) + cairo_restore (cr); + + cairo_destroy (cr); } static void @@ -4010,21 +3888,21 @@ gtk_default_draw_tab (GtkStyle *style, if (state_type == GTK_STATE_INSENSITIVE) { - draw_arrow (window, style->white_gc, area, + draw_arrow (window, &style->white, area, GTK_ARROW_UP, x + 1, y + 1, indicator_size.width, arrow_height); - draw_arrow (window, style->white_gc, area, + draw_arrow (window, &style->white, area, GTK_ARROW_DOWN, x + 1, y + arrow_height + ARROW_SPACE + 1, indicator_size.width, arrow_height); } - draw_arrow (window, style->fg_gc[state_type], area, + draw_arrow (window, &style->fg[state_type], area, GTK_ARROW_UP, x, y, indicator_size.width, arrow_height); - draw_arrow (window, style->fg_gc[state_type], area, + draw_arrow (window, &style->fg[state_type], area, GTK_ARROW_DOWN, x, y + arrow_height + ARROW_SPACE, indicator_size.width, arrow_height); } @@ -4653,12 +4531,10 @@ gtk_default_draw_focus (GtkStyle *style, gint width, gint height) { - GdkPoint points[5]; - GdkGC *gc; + cairo_t *cr; gboolean free_dash_list = FALSE; gint line_width = 1; gint8 *dash_list = "\1\1"; - gint dash_len; if (widget) { @@ -4670,22 +4546,6 @@ gtk_default_draw_focus (GtkStyle *style, free_dash_list = TRUE; } - sanitize_size (window, &width, &height); - - if (detail && !strcmp (detail, "colorwheel_light")) - gc = style->black_gc; - else if (detail && !strcmp (detail, "colorwheel_dark")) - gc = style->white_gc; - else - gc = style->fg_gc[state_type]; - - gdk_gc_set_line_attributes (gc, line_width, - dash_list[0] ? GDK_LINE_ON_OFF_DASH : GDK_LINE_SOLID, - GDK_CAP_BUTT, GDK_JOIN_MITER); - - if (area) - gdk_gc_set_clip_rectangle (gc, area); - if (detail && !strcmp (detail, "add-mode")) { if (free_dash_list) @@ -4695,88 +4555,61 @@ gtk_default_draw_focus (GtkStyle *style, free_dash_list = FALSE; } - points[0].x = x + line_width / 2; - points[0].y = y + line_width / 2; - points[1].x = x + width - line_width + line_width / 2; - points[1].y = y + line_width / 2; - points[2].x = x + width - line_width + line_width / 2; - points[2].y = y + height - line_width + line_width / 2; - points[3].x = x + line_width / 2; - points[3].y = y + height - line_width + line_width / 2; - points[4] = points[0]; + sanitize_size (window, &width, &height); - if (!dash_list[0]) - { - gdk_draw_lines (window, gc, points, 5); - } + cr = gdk_drawable_create_cairo_context (window); + + if (detail && !strcmp (detail, "colorwheel_light")) + cairo_set_rgb_color (cr, 0., 0., 0.); + else if (detail && !strcmp (detail, "colorwheel_dark")) + cairo_set_rgb_color (cr, 1., 1., 1.); else + gdk_cairo_set_source_color (cr, &style->fg[state_type]); + + cairo_set_line_width (cr, line_width); + + if (dash_list[0]) { - /* We go through all the pain below because the X rasterization - * rules don't really work right for dashed lines if you - * want continuity in segments that go between top/right - * and left/bottom. For instance, a top left corner - * with a 1-1 dash is drawn as: - * - * X X X - * X - * - * X - * - * This is because pixels on the top and left boundaries - * of polygons are drawn, but not on the bottom and right. - * So, if you have a line going up that turns the corner - * and goes right, there is a one pixel shift in the pattern. - * - * So, to fix this, we drawn the top and right in one call, - * then the left and bottom in another call, fixing up - * the dash offset for the second call ourselves to get - * continuity at the upper left. - * - * It's not perfect since we really should have a join at - * the upper left and lower right instead of two intersecting - * lines but that's only really apparent for no-dashes, - * which (for this reason) are done as one polygon and - * don't to through this code path. - */ - - dash_len = strlen (dash_list); - - if (dash_list[0]) - gdk_gc_set_dashes (gc, 0, dash_list, dash_len); - - gdk_draw_lines (window, gc, points, 3); - - /* We draw this line one farther over than it is "supposed" to - * because of another rasterization problem ... if two 1 pixel - * unjoined lines meet at the lower right, there will be a missing - * pixel. - */ - points[2].x += 1; - - if (dash_list[0]) + gint n_dashes = strlen (dash_list); + gdouble *dashes = g_new (gdouble, n_dashes); + gdouble total_length = 0; + gdouble dash_offset; + gint i; + + for (i = 0; i < n_dashes; i++) { - gint dash_pixels = 0; - gint i; - - /* Adjust the dash offset for the bottom and left so we - * match up at the upper left. - */ - for (i = 0; i < dash_len; i++) - dash_pixels += dash_list[i]; - - if (dash_len % 2 == 1) - dash_pixels *= 2; - - gdk_gc_set_dashes (gc, dash_pixels - (width + height - 2 * line_width) % dash_pixels, dash_list, dash_len); + dashes[i] = dash_list[i]; + total_length += dash_list[i]; } + + /* The dash offset here aligns the pattern to integer pixels + * by starting the dash at the right side of the left border + * Negative dash offsets in cairo don't work + * (https://bugs.freedesktop.org/show_bug.cgi?id=2729) + */ + dash_offset = - line_width / 2.; + while (dash_offset < 0) + dash_offset += total_length; - gdk_draw_lines (window, gc, points + 2, 3); + cairo_set_dash (cr, dashes, n_dashes, dash_offset); + g_free (dashes); } - gdk_gc_set_line_attributes (gc, 0, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_MITER); - if (area) - gdk_gc_set_clip_rectangle (gc, NULL); + { + cairo_rectangle (cr, + area->x, area->y, area->width, area->height); + cairo_clip (cr); + cairo_new_path (cr); + } + + cairo_rectangle (cr, + x + line_width / 2., + y + line_width / 2., + width - line_width, + height - line_width); + cairo_stroke (cr); + cairo_destroy (cr); if (free_dash_list) g_free (dash_list); diff --git a/gtk/gtkvruler.c b/gtk/gtkvruler.c index 996092041e..f967df5b40 100644 --- a/gtk/gtkvruler.c +++ b/gtk/gtkvruler.c @@ -136,7 +136,7 @@ static void gtk_vruler_draw_ticks (GtkRuler *ruler) { GtkWidget *widget; - GdkGC *gc, *bg_gc; + cairo_t *cr; gint i, j; gint width, height; gint xthickness; @@ -160,9 +160,6 @@ gtk_vruler_draw_ticks (GtkRuler *ruler) widget = GTK_WIDGET (ruler); - gc = widget->style->fg_gc[GTK_STATE_NORMAL]; - bg_gc = widget->style->bg_gc[GTK_STATE_NORMAL]; - xthickness = widget->style->xthickness; ythickness = widget->style->ythickness; @@ -181,12 +178,15 @@ gtk_vruler_draw_ticks (GtkRuler *ruler) 0, 0, widget->allocation.width, widget->allocation.height); - gdk_draw_line (ruler->backing_store, gc, - height + xthickness, - ythickness, - height + xthickness, - widget->allocation.height - ythickness); - + cr = gdk_drawable_create_cairo_context (ruler->backing_store); + gdk_cairo_set_source_color (cr, &widget->style->fg[widget->state]); + + cairo_rectangle (cr, + height + xthickness, + ythickness, + 1, + widget->allocation.height - 2 * ythickness); + upper = ruler->upper / ruler->metric->pixels_per_unit; lower = ruler->lower / ruler->metric->pixels_per_unit; @@ -242,9 +242,9 @@ gtk_vruler_draw_ticks (GtkRuler *ruler) { pos = ROUND ((cur - lower) * increment); - gdk_draw_line (ruler->backing_store, gc, - height + xthickness - length, pos, - height + xthickness, pos); + cairo_rectangle (cr, + height + xthickness - length, pos, + length, 1); /* draw label */ if (i == 0) @@ -272,6 +272,9 @@ gtk_vruler_draw_ticks (GtkRuler *ruler) } } + cairo_fill (cr); + cairo_destroy (cr); + g_object_unref (layout); } @@ -279,9 +282,7 @@ gtk_vruler_draw_ticks (GtkRuler *ruler) static void gtk_vruler_draw_pos (GtkRuler *ruler) { - GtkWidget *widget; - GdkGC *gc; - int i; + GtkWidget *widget = GTK_WIDGET (ruler); gint x, y; gint width, height; gint bs_width, bs_height; @@ -291,24 +292,23 @@ gtk_vruler_draw_pos (GtkRuler *ruler) if (GTK_WIDGET_DRAWABLE (ruler)) { - widget = GTK_WIDGET (ruler); - - gc = widget->style->fg_gc[GTK_STATE_NORMAL]; xthickness = widget->style->xthickness; ythickness = widget->style->ythickness; width = widget->allocation.width - xthickness * 2; height = widget->allocation.height; - bs_height = width / 2; + bs_height = width / 2 + 2; bs_height |= 1; /* make sure it's odd */ bs_width = bs_height / 2 + 1; if ((bs_width > 0) && (bs_height > 0)) { + cairo_t *cr = gdk_drawable_create_cairo_context (widget->window); + /* If a backing store exists, restore the ruler */ - if (ruler->backing_store && ruler->non_gr_exp_gc) - gdk_draw_drawable (ruler->widget.window, - ruler->non_gr_exp_gc, + if (ruler->backing_store) + gdk_draw_drawable (widget->window, + widget->style->black_gc, ruler->backing_store, ruler->xsrc, ruler->ysrc, ruler->xsrc, ruler->ysrc, @@ -318,11 +318,15 @@ gtk_vruler_draw_pos (GtkRuler *ruler) x = (width + bs_width) / 2 + xthickness; y = ROUND ((ruler->position - ruler->lower) * increment) + (ythickness - bs_height) / 2 - 1; + + gdk_cairo_set_source_color (cr, &widget->style->fg[widget->state]); + + cairo_move_to (cr, x, y); + cairo_line_to (cr, x + bs_width, y + bs_height / 2.); + cairo_line_to (cr, x, y + bs_height); + cairo_fill (cr); - for (i = 0; i < bs_width; i++) - gdk_draw_line (widget->window, gc, - x + i, y + i, - x + i, y + bs_height - 1 - i); + cairo_destroy (cr); ruler->xsrc = x; ruler->ysrc = y; diff --git a/tests/testcairo.c b/tests/testcairo.c index 9759adf0d3..2e6eb7264e 100644 --- a/tests/testcairo.c +++ b/tests/testcairo.c @@ -205,8 +205,7 @@ on_expose_event (GtkWidget *widget, { cairo_t *cr; - cr = cairo_create (); - gdk_drawable_set_cairo_target (GDK_DRAWABLE (widget->window), cr); + cr = gdk_drawable_create_cairo_context (widget->window); draw (cr, widget->allocation.width, widget->allocation.height); diff --git a/tests/testgtkrc b/tests/testgtkrc index f15d2531e0..dbe3acfa74 100644 --- a/tests/testgtkrc +++ b/tests/testgtkrc @@ -122,6 +122,12 @@ style 'button_list' = 'button' } widget "main window.*GtkScrolledWindow.*GtkButton*" style "button_list" +style "checkbutton" { +# GtkCheckButton::indicator-size = 27 +} + +class "GtkCheckButton" style "checkbutton" + class "GtkScrollbar" style "red-bar" |