Use cairo (if available) for anti-aliased rendering of the analogue clock face. (May be disabled at build time.) Signed-off-by: Darren Salt Index: configure.in.in =================================================================== --- configure.in.in (revision 22251) +++ configure.in.in (working copy) @@ -93,10 +93,21 @@ XDT_CHECK_LIBX11_REQUIRE XDT_CHECK_LIBSM +dnl ***************************************** +dnl *** Early check for optional packages *** +dnl ***************************************** +XDT_CHECK_OPTIONAL_PACKAGE([CAIRO], [cairo], [1.0.0], [cairo], + [anti-aliased vector rendering library]) +if test "x$CAIRO_FOUND" = xyes; then + GTK_MIN_VERSION=2.8.0 +else + GTK_MIN_VERSION=2.6.0 +fi + dnl *********************************** dnl *** Check for required packages *** dnl *********************************** -XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [2.6.0]) +XDT_CHECK_PACKAGE([GTK], [gtk+-2.0], [$GTK_MIN_VERSION]) XDT_CHECK_PACKAGE([LIBXFCE4UTIL], [libxfce4util-1.0], [4.3.90.2]) dnl *********************************** Index: libxfcegui4/xfce_clock.c =================================================================== --- libxfcegui4/xfce_clock.c (revision 22251) +++ libxfcegui4/xfce_clock.c (working copy) @@ -44,6 +44,9 @@ #include #include +#ifdef HAVE_CAIRO +#include +#endif /* HAVE_CAIRO */ #include "xfce_clock.h" @@ -844,23 +847,54 @@ clock->pointer_width = MAX (clock->radius / 5, 3); } +#ifndef HAVE_CAIRO + +#define CAIRO_ARG(x) /* nothing */ +#define CAIRO_ARG_GC /* nothing */ + +#else /* HAVE_CAIRO */ + +#define CAIRO_ARG(x) (x), +#define CAIRO_ARG_GC cairo_t *cgc, + static void -draw_ticks (GtkWidget * widget, GdkGC * gc, gint xc, gint yc) +set_cairo_colour (cairo_t *cgc, GdkGC *gc) { + GdkGCValues gcv; + GdkColor colour; + gdk_gc_get_values (gc, &gcv); + gdk_colormap_query_color (gdk_gc_get_colormap (gc), gcv.foreground.pixel, + &colour); + gdk_cairo_set_source_color (cgc, &colour); +} +#endif /* HAVE_CAIRO */ + +static void +draw_ticks (GtkWidget * widget, CAIRO_ARG_GC GdkGC * gc, gint xc, gint yc) +{ XfceClock *clock; gint i; gdouble theta; gdouble s, c; gdouble demi, quarter; +#ifndef HAVE_CAIRO GdkPoint points[5]; +#endif /* ! HAVE_CAIRO */ g_return_if_fail (widget != NULL); g_return_if_fail (XFCE_IS_CLOCK (widget)); + g_return_if_fail (gc != NULL); +#ifdef HAVE_CAIRO + g_return_if_fail (cgc != NULL); + set_cairo_colour (cgc, gc); + cairo_new_path (cgc); +#endif /* HAVE_CAIRO */ + clock = XFCE_CLOCK (widget); - demi = clock->pointer_width / 2; - quarter = clock->pointer_width / 4; + demi = clock->pointer_width / 2.0; + quarter = clock->pointer_width / 4.0; if (clock->pointer_width / 4 > 0) { @@ -870,6 +904,7 @@ s = sin (theta); c = cos (theta); +#ifndef HAVE_CAIRO points[0].x = xc + s * (clock->radius - demi) - quarter; points[0].y = yc + c * (clock->radius - demi) - quarter; points[1].x = xc + s * (clock->radius - demi) - quarter; @@ -882,42 +917,70 @@ points[4].y = yc + c * (clock->radius - demi) - quarter; gdk_draw_polygon (widget->window, gc, TRUE, points, 5); +#else /* HAVE_CAIRO */ + cairo_rectangle (cgc, + xc + s * (clock->radius - demi) - quarter, + yc + c * (clock->radius - demi) - quarter, + demi, demi); +#endif /* HAVE_CAIRO */ } } else { +#ifdef HAVE_CAIRO + cairo_set_line_width (cgc, 0.75); +#endif /* HAVE_CAIRO */ for (i = 0; i < 12; i++) { theta = (i * M_PI / 6.); s = sin (theta); c = cos (theta); +#ifndef HAVE_CAIRO gdk_draw_line (widget->window, gc, xc + s * (clock->radius - 1), yc + c * (clock->radius - 1), xc + s * (clock->radius + 1), yc + c * (clock->radius + 1)); +#else /* HAVE_CAIRO */ + cairo_move_to (cgc, xc + s * (clock->radius - 2), yc + c * (clock->radius - 2)); + cairo_line_to (cgc, xc + s * (clock->radius + 1), yc + c * (clock->radius + 1)); + cairo_close_path (cgc); +#endif /* HAVE_CAIRO */ } } + +#ifdef HAVE_CAIRO + cairo_stroke (cgc); + cairo_set_line_width (cgc, 1); +#endif /* HAVE_CAIRO */ } static void -draw_sec_pointer (GtkWidget * widget, GdkGC * gc, gint xc, gint yc) +draw_sec_pointer (GtkWidget * widget, CAIRO_ARG_GC GdkGC * gc, gint xc, gint yc) { XfceClock *clock; +#ifndef HAVE_CAIRO GdkPoint points[6]; +#endif /* ! HAVE_CAIRO */ gdouble s, c; gdouble width; g_return_if_fail (widget != NULL); g_return_if_fail (XFCE_IS_CLOCK (widget)); g_return_if_fail (gc != NULL); +#ifdef HAVE_CAIRO + g_return_if_fail (cgc != NULL); + set_cairo_colour (cgc, gc); +#endif /* HAVE_CAIRO */ + clock = XFCE_CLOCK (widget); s = sin (clock->sec_angle); c = cos (clock->sec_angle); width = (gdouble) MAX (clock->pointer_width / 3, 1); +#ifndef HAVE_CAIRO points[0].x = xc + s * width; points[0].y = yc + c * width; points[1].x = xc + c * clock->radius + s * 0.5; @@ -932,26 +995,46 @@ points[5].y = yc + c * width; gdk_draw_polygon (widget->window, gc, TRUE, points, 6); +#else /* HAVE_CAIRO */ + cairo_new_path (cgc); + cairo_move_to (cgc, xc + s * width, yc + c * width); + cairo_line_to (cgc, xc + c * clock->radius + s * 0.5, + yc - s * clock->radius + c * 0.5); + cairo_line_to (cgc, xc + c * clock->radius - s * 0.5, + yc - s * clock->radius - c * 0.5); + cairo_line_to (cgc, xc - s * width, yc - c * width); + cairo_line_to (cgc, xc - c * width, yc + s * width); + cairo_close_path (cgc); + cairo_fill (cgc); +#endif /* HAVE_CAIRO */ } static void -draw_min_pointer (GtkWidget * widget, GdkGC * gc, gint xc, gint yc) +draw_min_pointer (GtkWidget * widget, CAIRO_ARG_GC GdkGC * gc, gint xc, gint yc) { XfceClock *clock; +#ifndef HAVE_CAIRO GdkPoint points[6]; +#endif /* ! HAVE_CAIRO */ gdouble s, c; gdouble width; g_return_if_fail (widget != NULL); g_return_if_fail (XFCE_IS_CLOCK (widget)); g_return_if_fail (gc != NULL); +#ifdef HAVE_CAIRO + g_return_if_fail (cgc != NULL); + set_cairo_colour (cgc, gc); +#endif /* HAVE_CAIRO */ + clock = XFCE_CLOCK (widget); s = sin (clock->min_angle); c = cos (clock->min_angle); width = (gdouble) MAX (clock->pointer_width / 2, 1); +#ifndef HAVE_CAIRO points[0].x = xc + s * width; points[0].y = yc + c * width; points[1].x = xc + 3.0 * c * clock->radius / 4.0 + s * 0.5; @@ -966,26 +1049,46 @@ points[5].y = yc + c * width; gdk_draw_polygon (widget->window, gc, TRUE, points, 6); +#else /* HAVE_CAIRO */ + cairo_new_path (cgc); + cairo_move_to (cgc, xc + s * width, yc + c * width); + cairo_line_to (cgc, xc + 3.0 * c * clock->radius / 4.0 + s * 0.5, + yc - 3.0 * s * clock->radius / 4.0 + c * 0.5); + cairo_line_to (cgc, xc + 3.0 * c * clock->radius / 4.0 - s * 0.5, + yc - 3.0 * s * clock->radius / 4.0 - c * 0.5); + cairo_line_to (cgc, xc - s * width, yc - c * width); + cairo_line_to (cgc, xc - c * width, yc + s * width); + cairo_close_path (cgc); + cairo_fill (cgc); +#endif /* HAVE_CAIRO */ } static void -draw_hrs_pointer (GtkWidget * widget, GdkGC * gc, gint xc, gint yc) +draw_hrs_pointer (GtkWidget * widget, CAIRO_ARG_GC GdkGC * gc, gint xc, gint yc) { XfceClock *clock; +#ifndef HAVE_CAIRO GdkPoint points[6]; +#endif /* ! HAVE_CAIRO */ gdouble s, c; gdouble width; g_return_if_fail (widget != NULL); g_return_if_fail (XFCE_IS_CLOCK (widget)); g_return_if_fail (gc != NULL); +#ifdef HAVE_CAIRO + g_return_if_fail (cgc != NULL); + set_cairo_colour (cgc, gc); +#endif /* HAVE_CAIRO */ + clock = XFCE_CLOCK (widget); s = sin (clock->hrs_angle); c = cos (clock->hrs_angle); width = (gdouble) MAX (clock->pointer_width / 2, 1); +#ifndef HAVE_CAIRO points[0].x = xc + s * width; points[0].y = yc + c * width; points[1].x = xc + 2.0 * c * clock->radius / 5.0 + s * 0.5; @@ -1000,6 +1103,16 @@ points[5].y = yc + c * width; gdk_draw_polygon (widget->window, gc, TRUE, points, 6); +#else /* HAVE_CAIRO */ + cairo_new_path (cgc); + cairo_move_to (cgc, xc + s * width, yc + c * width); + cairo_line_to (cgc, xc + 2.0 * c * clock->radius / 5.0 + s * 0.5, yc - 2.0 * s * clock->radius / 5.0 + c * 0.5); + cairo_line_to (cgc, xc + 2.0 * c * clock->radius / 5.0 - s * 0.5, yc - 2.0 * s * clock->radius / 5.0 - c * 0.5); + cairo_line_to (cgc, xc - s * width, yc - c * width); + cairo_line_to (cgc, xc - c * width, yc + s * width); + cairo_close_path (cgc); + cairo_fill (cgc); +#endif /* HAVE_CAIRO */ } @@ -1107,6 +1220,9 @@ xfce_clock_draw_analog (GtkWidget * widget, GdkRectangle * area) { XfceClock *clock; +#ifdef HAVE_CAIRO + cairo_t *cgc; +#endif /* HAVE_CAIRO */ gint xc, yc; @@ -1118,6 +1234,7 @@ xc = widget->allocation.width / 2 + 1; yc = widget->allocation.height / 2 + 1; +#ifndef HAVE_CAIRO if (area) { gdk_gc_set_clip_rectangle (widget->style->light_gc[widget->state], @@ -1136,36 +1253,58 @@ gdk_window_clear_area (widget->window, 0, 0, widget->allocation.width, widget->allocation.height); } +#else /* HAVE_CAIRO */ + cgc = gdk_cairo_create (widget->window); + g_return_if_fail (cgc != NULL); + set_cairo_colour (cgc, widget->style->bg_gc[widget->state]); + cairo_new_path (cgc); + + if (area) + { + cairo_rectangle (cgc, area->x, area->y, area->width, area->height); + } + else + { + cairo_rectangle (cgc, 0, 0, widget->allocation.width, + widget->allocation.height); + cairo_clip (cgc); + } + cairo_fill (cgc); +#endif /* HAVE_CAIRO */ + /* * Here we decide arbitrary that if the clock widget is smaller than * 20 pixels, we don't draw the shadow. */ if (MIN (xc, yc) >= 20) { - draw_ticks (widget, widget->style->dark_gc[widget->state], xc, yc); - draw_hrs_pointer (widget, widget->style->dark_gc[widget->state], xc, - yc); - draw_min_pointer (widget, widget->style->dark_gc[widget->state], xc, - yc); + draw_ticks (widget, CAIRO_ARG (cgc) + widget->style->dark_gc[widget->state], xc, yc); + draw_hrs_pointer (widget, CAIRO_ARG (cgc) + widget->style->dark_gc[widget->state], xc, yc); + draw_min_pointer (widget, CAIRO_ARG (cgc) + widget->style->dark_gc[widget->state], xc, yc); if (clock->display_secs) { - draw_sec_pointer (widget, widget->style->dark_gc[widget->state], - xc, yc); + draw_sec_pointer (widget, CAIRO_ARG (cgc) + widget->style->dark_gc[widget->state], xc, yc); } } - draw_ticks (widget, widget->style->text_gc[widget->state], xc - 1, - yc - 1); - draw_hrs_pointer (widget, widget->style->text_gc[widget->state], xc - 1, - yc - 1); - draw_min_pointer (widget, widget->style->text_gc[widget->state], xc - 1, - yc - 1); + draw_ticks (widget, CAIRO_ARG (cgc) + widget->style->text_gc[widget->state], xc - 1, yc - 1); + draw_hrs_pointer (widget, CAIRO_ARG (cgc) + widget->style->text_gc[widget->state], xc - 1, yc - 1); + draw_min_pointer (widget, CAIRO_ARG (cgc) + widget->style->text_gc[widget->state], xc - 1, yc - 1); if (clock->display_secs) { - draw_sec_pointer (widget, widget->style->text_gc[widget->state], + draw_sec_pointer (widget, CAIRO_ARG (cgc) + widget->style->text_gc[widget->state], xc - 1, yc - 1); } +#ifndef HAVE_CAIRO if (area) { gdk_gc_set_clip_rectangle (widget->style->light_gc[widget->state], @@ -1177,6 +1316,9 @@ gdk_gc_set_clip_rectangle (widget->style->black_gc, NULL); gdk_gc_set_clip_rectangle (widget->style->bg_gc[widget->state], NULL); } +#else /* HAVE_CAIRO */ + cairo_destroy (cgc); +#endif /* HAVE_CAIRO */ } static void