From 0772898b83115f2e10b32b4e5919b17ed9b1f28d Mon Sep 17 00:00:00 2001 From: Daiki Ueno Date: Wed, 24 Aug 2011 17:05:41 +0900 Subject: [PATCH] Improve icon rendering. --- eek/eek-gtk-renderer.c | 57 ++++---------------- eek/eek-renderer.c | 116 ++++++++++++++++++++++++++--------------- eek/eek-renderer.h | 92 ++++++++++++++++---------------- 3 files changed, 132 insertions(+), 133 deletions(-) diff --git a/eek/eek-gtk-renderer.c b/eek/eek-gtk-renderer.c index c88e685e..86b9c9bc 100644 --- a/eek/eek-gtk-renderer.c +++ b/eek/eek-gtk-renderer.c @@ -51,64 +51,27 @@ pixbuf_to_cairo_surface (GdkPixbuf *pixbuf) return surface; } -static void -eek_gtk_renderer_real_render_key_icon (EekRenderer *self, - cairo_t *cr, - EekKey *key, - gdouble scale, - gboolean rotate) +static cairo_surface_t * +eek_gtk_renderer_real_get_icon_surface (EekRenderer *self, + const gchar *icon_name, + gint size) { - EekBounds bounds; - EekSymbol *symbol; - const gchar *icon_name; GdkPixbuf *pixbuf; - cairo_surface_t *surface; GError *error; - gint width, height; - - symbol = eek_key_get_symbol_with_fallback (key, 0, 0); - g_return_if_fail (symbol); - - icon_name = eek_symbol_get_icon_name (symbol); - g_return_if_fail (icon_name); - - eek_element_get_bounds (EEK_ELEMENT(key), &bounds); - bounds.width *= scale; - bounds.height *= scale; + cairo_surface_t *surface; error = NULL; pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), icon_name, - MIN(bounds.width, bounds.height), + size, 0, &error); - g_return_if_fail (pixbuf); + if (pixbuf == NULL) + return NULL; - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - - if (bounds.height * width / bounds.width <= height) - scale = width / bounds.width; - else if (bounds.width * height / bounds.height <= width) - scale = height / bounds.height; - else { - if (bounds.width * height < bounds.height * width) - scale = bounds.width / width; - else - scale = bounds.height / height; - } - - cairo_save (cr); - cairo_translate (cr, - (bounds.width - width * scale) / 2, - (bounds.height - height * scale) / 2); - - eek_renderer_apply_transformation_for_key (self, cr, key, scale, rotate); surface = pixbuf_to_cairo_surface (pixbuf); g_object_unref (pixbuf); - cairo_set_source_surface (cr, surface, 0.0, 0.0); - cairo_paint (cr); - cairo_restore (cr); + return surface; } static void @@ -116,7 +79,7 @@ eek_gtk_renderer_class_init (EekGtkRendererClass *klass) { EekRendererClass *renderer_class = EEK_RENDERER_CLASS (klass); - renderer_class->render_key_icon = eek_gtk_renderer_real_render_key_icon; + renderer_class->get_icon_surface = eek_gtk_renderer_real_get_icon_surface; } static void diff --git a/eek/eek-renderer.c b/eek/eek-renderer.c index c7592167..7bad2102 100644 --- a/eek/eek-renderer.c +++ b/eek/eek-renderer.c @@ -440,8 +440,15 @@ render_key (EekRenderer *self, gulong oref; EekSymbol *symbol; GHashTable *outline_surface_cache; + PangoLayout *layout; + PangoRectangle extents = { 0, }; + EekColor foreground; + /* render outline */ eek_element_get_bounds (EEK_ELEMENT(key), &bounds); + bounds.width *= priv->scale; + bounds.height *= priv->scale; + oref = eek_key_get_oref (key); if (oref == 0) return; @@ -458,8 +465,8 @@ render_key (EekRenderer *self, outline_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - bounds.width * priv->scale, - bounds.height * priv->scale); + bounds.width, + bounds.height); cr = cairo_create (outline_surface); /* blank background */ @@ -481,36 +488,66 @@ render_key (EekRenderer *self, cairo_set_source_surface (cr, outline_surface, 0.0, 0.0); cairo_paint (cr); + /* render icon (if any) */ symbol = eek_key_get_symbol_with_fallback (key, 0, 0); - if (EEK_RENDERER_GET_CLASS(self)->render_key_icon && - symbol && eek_symbol_get_icon_name (symbol)) { - eek_renderer_render_key_icon (self, cr, key, 1.0, 0); - } else { - PangoLayout *layout; - PangoRectangle extents = { 0, }; - EekColor foreground; + if (!symbol) + return; - layout = pango_cairo_create_layout (cr); - eek_renderer_render_key_label (self, layout, key); - pango_layout_get_extents (layout, NULL, &extents); + if (eek_symbol_get_icon_name (symbol)) { + cairo_surface_t *icon_surface = + eek_renderer_get_icon_surface (self, + eek_symbol_get_icon_name (symbol), + MIN(bounds.width, bounds.height)); + if (icon_surface) { + gint width = cairo_image_surface_get_width (icon_surface); + gint height = cairo_image_surface_get_height (icon_surface); + gdouble scale; - cairo_save (cr); - cairo_move_to - (cr, - (bounds.width * priv->scale - extents.width / PANGO_SCALE) / 2, - (bounds.height * priv->scale - extents.height / PANGO_SCALE) / 2); + if (height * bounds.width / width <= bounds.height) + scale = bounds.width / width; + else if (width * bounds.height / height <= bounds.width) + scale = bounds.height / height; + else { + if (width * bounds.height < height * bounds.width) + scale = width / bounds.width; + else + scale = height / bounds.height; + } - eek_renderer_get_foreground_color (self, EEK_ELEMENT(key), &foreground); - cairo_set_source_rgba (cr, - foreground.red, - foreground.green, - foreground.blue, - foreground.alpha); - - pango_cairo_show_layout (cr, layout); - cairo_restore (cr); - g_object_unref (layout); + cairo_save (cr); + cairo_translate (cr, + (bounds.width - width * scale) / 2, + (bounds.height - height * scale) / 2); + cairo_rectangle (cr, 0, 0, width, height); + cairo_clip (cr); + cairo_set_source_surface (cr, icon_surface, 0.0, 0.0); + cairo_paint (cr); + cairo_restore (cr); + return; + } } + + /* render label */ + layout = pango_cairo_create_layout (cr); + eek_renderer_render_key_label (self, layout, key); + pango_layout_get_extents (layout, NULL, &extents); + + cairo_save (cr); + cairo_move_to + (cr, + (bounds.width - extents.width / PANGO_SCALE) / 2, + (bounds.height - extents.height / PANGO_SCALE) / 2); + + eek_renderer_get_foreground_color (self, EEK_ELEMENT(key), &foreground); + cairo_set_source_rgba (cr, + foreground.red, + foreground.green, + foreground.blue, + foreground.alpha); + + pango_cairo_show_layout (cr, layout); + cairo_restore (cr); + g_object_unref (layout); } void @@ -1040,22 +1077,19 @@ eek_renderer_render_key_outline (EekRenderer *renderer, rotate); } -void -eek_renderer_render_key_icon (EekRenderer *renderer, - cairo_t *cr, - EekKey *key, - gdouble scale, - gboolean rotate) +cairo_surface_t * +eek_renderer_get_icon_surface (EekRenderer *renderer, + const gchar *icon_name, + gint size) { - g_return_if_fail (EEK_IS_RENDERER(renderer)); - g_return_if_fail (EEK_IS_KEY(key)); - g_return_if_fail (scale >= 0.0); + EekRendererClass *klass; - EEK_RENDERER_GET_CLASS(renderer)->render_key_icon (renderer, - cr, - key, - scale, - rotate); + g_return_val_if_fail (EEK_IS_RENDERER(renderer), NULL); + + klass = EEK_RENDERER_GET_CLASS(renderer); + if (klass->get_icon_surface) + return klass->get_icon_surface (renderer, icon_name, size); + return NULL; } void diff --git a/eek/eek-renderer.h b/eek/eek-renderer.h index 2f4d0930..86d10042 100644 --- a/eek/eek-renderer.h +++ b/eek/eek-renderer.h @@ -51,109 +51,111 @@ struct _EekRendererClass { GObjectClass parent_class; - void (* render_key_label) (EekRenderer *self, - PangoLayout *layout, - EekKey *key); + void (* render_key_label) (EekRenderer *self, + PangoLayout *layout, + EekKey *key); - void (* render_key_outline) (EekRenderer *self, - cairo_t *cr, - EekKey *key, - gdouble scale, - gboolean rotate); + void (* render_key_outline) (EekRenderer *self, + cairo_t *cr, + EekKey *key, + gdouble scale, + gboolean rotate); - void (* render_key) (EekRenderer *self, - cairo_t *cr, - EekKey *key, - gdouble scale, - gboolean rotate); + void (* render_key) (EekRenderer *self, + cairo_t *cr, + EekKey *key, + gdouble scale, + gboolean rotate); - void (* render_keyboard) (EekRenderer *self, - cairo_t *cr); + void (* render_keyboard) (EekRenderer *self, + cairo_t *cr); - void (* render_key_icon) (EekRenderer *self, - cairo_t *cr, - EekKey *key, - gdouble scale, - gboolean rotate); + cairo_surface_t *(* get_icon_surface) (EekRenderer *self, + const gchar *icon_name, + gint size); /*< private >*/ /* padding */ gpointer pdummy[23]; }; -GType eek_renderer_get_type (void) G_GNUC_CONST; -EekRenderer *eek_renderer_new (EekKeyboard *keyboard, +GType eek_renderer_get_type (void) G_GNUC_CONST; +EekRenderer *eek_renderer_new (EekKeyboard *keyboard, PangoContext *pcontext); -void eek_renderer_set_allocation_size (EekRenderer *renderer, +void eek_renderer_set_allocation_size + (EekRenderer *renderer, gdouble width, gdouble height); -void eek_renderer_get_size (EekRenderer *renderer, +void eek_renderer_get_size (EekRenderer *renderer, gdouble *width, gdouble *height); -void eek_renderer_get_key_bounds (EekRenderer *renderer, +void eek_renderer_get_key_bounds (EekRenderer *renderer, EekKey *key, EekBounds *bounds, gboolean rotate); -gdouble eek_renderer_get_scale (EekRenderer *renderer); +gdouble eek_renderer_get_scale (EekRenderer *renderer); -PangoLayout *eek_renderer_create_pango_layout (EekRenderer *renderer); -void eek_renderer_render_key_label (EekRenderer *renderer, +PangoLayout *eek_renderer_create_pango_layout + (EekRenderer *renderer); +void eek_renderer_render_key_label (EekRenderer *renderer, PangoLayout *layout, EekKey *key); -void eek_renderer_render_key_outline (EekRenderer *renderer, +void eek_renderer_render_key_outline + (EekRenderer *renderer, cairo_t *cr, EekKey *key, gdouble scale, gboolean rotate); -void eek_renderer_render_key (EekRenderer *renderer, +void eek_renderer_render_key (EekRenderer *renderer, cairo_t *cr, EekKey *key, gdouble scale, gboolean rotate); -void eek_renderer_render_key_icon (EekRenderer *renderer, - cairo_t *cr, - EekKey *key, - gdouble scale, - gboolean rotate); +cairo_surface_t *eek_renderer_get_icon_surface (EekRenderer *renderer, + const gchar *icon_name, + gint size); -void eek_renderer_render_keyboard (EekRenderer *renderer, +void eek_renderer_render_keyboard (EekRenderer *renderer, cairo_t *cr); -void eek_renderer_set_default_foreground_color +void eek_renderer_set_default_foreground_color (EekRenderer *renderer, const EekColor *color); -void eek_renderer_set_default_background_color +void eek_renderer_set_default_background_color (EekRenderer *renderer, const EekColor *color); -void eek_renderer_get_foreground_color (EekRenderer *renderer, +void eek_renderer_get_foreground_color + (EekRenderer *renderer, EekElement *element, EekColor *color); -void eek_renderer_get_background_color (EekRenderer *renderer, +void eek_renderer_get_background_color + (EekRenderer *renderer, EekElement *element, EekColor *color); -void eek_renderer_get_background_gradient +void eek_renderer_get_background_gradient (EekRenderer *renderer, EekElement *element, EekGradientType *type, EekColor *start, EekColor *end); -void eek_renderer_set_border_width (EekRenderer *renderer, +void eek_renderer_set_border_width (EekRenderer *renderer, gdouble border_width); -EekKey *eek_renderer_find_key_by_position (EekRenderer *renderer, +EekKey *eek_renderer_find_key_by_position + (EekRenderer *renderer, gdouble x, gdouble y); -void eek_renderer_apply_transformation_for_key +void eek_renderer_apply_transformation_for_key (EekRenderer *renderer, cairo_t *cr, EekKey *key, gdouble scale, gboolean rotate); -void eek_renderer_set_theme (EekRenderer *renderer, +void eek_renderer_set_theme (EekRenderer *renderer, EekTheme *theme); G_END_DECLS