summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
Diffstat (limited to 'gdk')
-rw-r--r--gdk/gdkpango.c47
-rw-r--r--gdk/gdkpixbuf-drawable.c23
-rw-r--r--gdk/gdkpixbuf-render.c91
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);
}