diff options
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/gdkpango.c | 47 | ||||
-rw-r--r-- | gdk/gdkpixbuf-drawable.c | 23 | ||||
-rw-r--r-- | gdk/gdkpixbuf-render.c | 91 |
3 files changed, 121 insertions, 40 deletions
diff --git a/gdk/gdkpango.c b/gdk/gdkpango.c index 53af8371d..2a10fcc8e 100644 --- a/gdk/gdkpango.c +++ b/gdk/gdkpango.c @@ -33,6 +33,7 @@ struct _GdkPangoContextInfo static void gdk_pango_get_item_properties (PangoItem *item, PangoUnderline *uline, + gint *rise, PangoAttrColor *fg_color, gboolean *fg_set, PangoAttrColor *bg_color, @@ -133,7 +134,6 @@ gdk_pango_context_set_colormap (PangoContext *context, } } - /** * gdk_draw_layout_line: * @drawable: the drawable on which to draw the line @@ -157,7 +157,8 @@ gdk_draw_layout_line (GdkDrawable *drawable, PangoRectangle ink_rect; PangoContext *context; gint x_off = 0; - + gint rise = 0; + g_return_if_fail (drawable != NULL); g_return_if_fail (gc != NULL); g_return_if_fail (line != NULL); @@ -173,12 +174,21 @@ gdk_draw_layout_line (GdkDrawable *drawable, PangoAttrColor fg_color, bg_color; gboolean fg_set, bg_set, shape_set; GdkGC *fg_gc; + gint risen_y; tmp_list = tmp_list->next; - - gdk_pango_get_item_properties (run->item, &uline, &fg_color, &fg_set, &bg_color, &bg_set, &shape_set, &ink_rect, + + gdk_pango_get_item_properties (run->item, &uline, + &rise, + &fg_color, &fg_set, + &bg_color, &bg_set, + &shape_set, + &ink_rect, &logical_rect); + /* we subtract the rise because X coordinates are upside down */ + risen_y = y - rise / PANGO_SCALE; + if (!shape_set) { if (uline == PANGO_UNDERLINE_NONE) @@ -195,7 +205,7 @@ gdk_draw_layout_line (GdkDrawable *drawable, gdk_draw_rectangle (drawable, bg_gc, TRUE, x + (x_off + logical_rect.x) / PANGO_SCALE, - y + overall_rect.y / PANGO_SCALE, + risen_y + overall_rect.y / PANGO_SCALE, logical_rect.width / PANGO_SCALE, overall_rect.height / PANGO_SCALE); @@ -209,7 +219,9 @@ gdk_draw_layout_line (GdkDrawable *drawable, if (!shape_set) gdk_draw_glyphs (drawable, fg_gc, run->item->analysis.font, - x + x_off / PANGO_SCALE, y, run->glyphs); + x + x_off / PANGO_SCALE, + risen_y, + run->glyphs); switch (uline) { @@ -217,18 +229,22 @@ gdk_draw_layout_line (GdkDrawable *drawable, break; case PANGO_UNDERLINE_DOUBLE: gdk_draw_line (drawable, fg_gc, - x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + 4, + x + (x_off + ink_rect.x) / PANGO_SCALE - 1, + risen_y + 4, x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + 4); /* Fall through */ case PANGO_UNDERLINE_SINGLE: gdk_draw_line (drawable, fg_gc, - x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + 2, + x + (x_off + ink_rect.x) / PANGO_SCALE - 1, + risen_y + 2, x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + 2); break; case PANGO_UNDERLINE_LOW: gdk_draw_line (drawable, fg_gc, - x + (x_off + ink_rect.x) / PANGO_SCALE - 1, y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2, - x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2); + x + (x_off + ink_rect.x) / PANGO_SCALE - 1, + risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2, + x + (x_off + ink_rect.x + ink_rect.width) / PANGO_SCALE, + risen_y + (ink_rect.y + ink_rect.height) / PANGO_SCALE + 2); break; } @@ -328,6 +344,7 @@ gdk_draw_layout (GdkDrawable *drawable, static void gdk_pango_get_item_properties (PangoItem *item, PangoUnderline *uline, + gint *rise, PangoAttrColor *fg_color, gboolean *fg_set, PangoAttrColor *bg_color, @@ -346,6 +363,9 @@ gdk_pango_get_item_properties (PangoItem *item, if (shape_set) *shape_set = FALSE; + + if (rise) + *rise = 0; while (tmp_list) { @@ -382,7 +402,12 @@ gdk_pango_get_item_properties (PangoItem *item, if (ink_rect) *ink_rect = ((PangoAttrShape *)attr)->ink_rect; break; - + + case PANGO_ATTR_RISE: + if (rise) + *rise = ((PangoAttrInt *)attr)->value; + break; + default: break; } diff --git a/gdk/gdkpixbuf-drawable.c b/gdk/gdkpixbuf-drawable.c index 07175a638..776ebe606 100644 --- a/gdk/gdkpixbuf-drawable.c +++ b/gdk/gdkpixbuf-drawable.c @@ -1195,14 +1195,12 @@ gdk_pixbuf_get_from_drawable (GdkPixbuf *dest, int src_width, src_height; GdkImage *image; int rowstride, bpp, alpha; - + /* General sanity checks */ g_return_val_if_fail (src != NULL, NULL); - if (GDK_IS_PIXMAP (src)) - g_return_val_if_fail (cmap != NULL, NULL); - else + if (GDK_IS_WINDOW (src)) /* FIXME: this is not perfect, since is_viewable() only tests * recursively up the Gdk parent window tree, but stops at * foreign windows or Gdk toplevels. I.e. if a window manager @@ -1219,6 +1217,17 @@ gdk_pixbuf_get_from_drawable (GdkPixbuf *dest, g_return_val_if_fail (dest->bits_per_sample == 8, NULL); } + if (cmap == NULL) + cmap = gdk_drawable_get_colormap (src); + + if (cmap == NULL) + { + g_warning ("%s: Source drawable has no colormap; either pass " + "in a colormap, or set the colormap on the drawable " + "with gdk_drawable_set_colormap()", G_STRLOC); + return NULL; + } + /* Coordinate sanity checks */ gdk_drawable_get_size (src, &src_width, &src_height); @@ -1233,7 +1242,7 @@ gdk_pixbuf_get_from_drawable (GdkPixbuf *dest, g_return_val_if_fail (dest_y + height <= dest->height, NULL); } - if (!GDK_IS_PIXMAP (src)) + if (GDK_IS_WINDOW (src)) { int ret; int src_xorigin, src_yorigin; @@ -1269,10 +1278,6 @@ gdk_pixbuf_get_from_drawable (GdkPixbuf *dest, } } - /* Get the colormap if needed */ - if (!GDK_IS_PIXMAP (src)) - cmap = gdk_window_get_colormap (src); - alpha = dest->has_alpha; rowstride = dest->rowstride; bpp = alpha ? 4 : 3; diff --git a/gdk/gdkpixbuf-render.c b/gdk/gdkpixbuf-render.c index 5ad39f760..9ef7bb6f6 100644 --- a/gdk/gdkpixbuf-render.c +++ b/gdk/gdkpixbuf-render.c @@ -246,6 +246,11 @@ gdk_pixbuf_render_to_drawable (GdkPixbuf *pixbuf, * the alpha channel of the image. If performance is crucial, consider handling * the alpha channel yourself (possibly by caching it in your application) and * using gdk_pixbuf_render_to_drawable() or GdkRGB directly instead. + * + * The #GDK_PIXBUF_ALPHA_FULL mode involves round trips to the X + * server, and may also be somewhat slow in its current implementation + * (though in the future it could be made significantly faster, in + * principle). **/ void gdk_pixbuf_render_to_drawable_alpha (GdkPixbuf *pixbuf, @@ -260,7 +265,8 @@ gdk_pixbuf_render_to_drawable_alpha (GdkPixbuf *pixbuf, { GdkBitmap *bitmap = NULL; GdkGC *gc; - + GdkPixbuf *composited = NULL; + g_return_if_fail (pixbuf != NULL); g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB); g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4); @@ -278,31 +284,76 @@ gdk_pixbuf_render_to_drawable_alpha (GdkPixbuf *pixbuf, if (pixbuf->has_alpha) { - /* Right now we only support GDK_PIXBUF_ALPHA_BILEVEL, so we - * unconditionally create the clipping mask. - */ - - bitmap = gdk_pixmap_new (NULL, width, height, 1); - gdk_pixbuf_render_threshold_alpha (pixbuf, bitmap, - src_x, src_y, - 0, 0, - width, height, - alpha_threshold); - - gdk_gc_set_clip_mask (gc, bitmap); - gdk_gc_set_clip_origin (gc, dest_x, dest_y); + if (alpha_mode == GDK_PIXBUF_ALPHA_BILEVEL) + { + bitmap = gdk_pixmap_new (NULL, width, height, 1); + gdk_pixbuf_render_threshold_alpha (pixbuf, bitmap, + src_x, src_y, + 0, 0, + width, height, + alpha_threshold); + + gdk_gc_set_clip_mask (gc, bitmap); + gdk_gc_set_clip_origin (gc, dest_x, dest_y); + } + else if (alpha_mode == GDK_PIXBUF_ALPHA_FULL) + { + GdkPixbuf *sub = NULL; + + composited = gdk_pixbuf_get_from_drawable (NULL, + drawable, + NULL, + dest_x, dest_y, + 0, 0, + width, height); + + if (src_x != 0 || src_y != 0) + { + sub = gdk_pixbuf_new_subpixbuf (pixbuf, src_x, src_y, + width, height); + } + + gdk_pixbuf_composite (sub ? sub : pixbuf, + composited, + 0, 0, + width, height, + 0, 0, + 1.0, 1.0, + GDK_INTERP_BILINEAR, + 255); + + if (sub) + g_object_unref (G_OBJECT (sub)); + } } - gdk_pixbuf_render_to_drawable (pixbuf, drawable, gc, - src_x, src_y, - dest_x, dest_y, - width, height, - dither, - x_dither, y_dither); + if (composited) + { + gdk_pixbuf_render_to_drawable (composited, + drawable, gc, + 0, 0, + dest_x, dest_y, + width, height, + dither, + x_dither, y_dither); + } + else + { + gdk_pixbuf_render_to_drawable (pixbuf, + drawable, gc, + src_x, src_y, + dest_x, dest_y, + width, height, + dither, + x_dither, y_dither); + } if (bitmap) gdk_bitmap_unref (bitmap); + if (composited) + g_object_unref (G_OBJECT (composited)); + gdk_gc_unref (gc); } |