From c1b720f018f8942a361cf9ad68bf308161effa8d Mon Sep 17 00:00:00 2001 From: Viktor Odintsev <zakhams@gmail.com> Date: Mon, 3 Jul 2017 15:25:22 +0300 Subject: [PATCH] Implement cairo drawing --- src/frame.c | 41 ++++++------ src/mypixmap.c | 171 ++++++++++++++++++++++++++++--------------------- src/mypixmap.h | 3 + 3 files changed, 123 insertions(+), 92 deletions(-) diff --git a/src/frame.c b/src/frame.c index ca0d51158..19e571291 100644 --- a/src/frame.c +++ b/src/frame.c @@ -385,9 +385,8 @@ static void frameCreateTitlePixmap (Client * c, int state, int left, int right, xfwmPixmap * title_pm, xfwmPixmap * top_pm) { ScreenInfo *screen_info; - GdkPixmap *gpixmap; - GdkGCValues values; - GdkGC *gc; + cairo_surface_t *surface; + cairo_t *cr; PangoLayout *layout; PangoRectangle logical_rect; int width, x, hoffset, w1, w2, w3, w4, w5, temp; @@ -536,9 +535,9 @@ frameCreateTitlePixmap (Client * c, int state, int left, int right, xfwmPixmap * xfwmPixmapCreate (screen_info, top_pm, width, top_height); xfwmPixmapCreate (screen_info, title_pm, width, frameTop (c)); - gpixmap = gdk_pixmap_foreign_new (title_pm->pixmap); - gdk_drawable_set_colormap (gpixmap, gdk_screen_get_system_colormap (screen_info->gscr)); - gc = gdk_gc_new (gpixmap); + + surface = xfwmPixmapCreateSurface (title_pm, FALSE); + cr = cairo_create (surface); if (w1 > 0) { @@ -553,25 +552,31 @@ frameCreateTitlePixmap (Client * c, int state, int left, int right, xfwmPixmap * { frameFillTitlePixmap (c, state, TITLE_3, x, w3, top_height, title_pm, top_pm); title_x = hoffset + x; + cairo_translate (cr, title_x, title_y); if (screen_info->params->title_shadow[state]) { - gdk_gc_get_values (screen_info->title_shadow_colors[state].gc, &values); - gdk_gc_set_values (gc, &values, GDK_GC_FOREGROUND); + gdk_cairo_set_source_rgba (cr, &screen_info->title_shadow_colors[state]); if (screen_info->params->title_shadow[state] == TITLE_SHADOW_UNDER) { - gdk_draw_layout (gpixmap, gc, title_x + 1, title_y + 1, layout); + cairo_translate (cr, 1, 1); + pango_cairo_show_layout (cr, layout); + cairo_translate (cr, -1, -1); } else { - gdk_draw_layout (gpixmap, gc, title_x - 1, title_y, layout); - gdk_draw_layout (gpixmap, gc, title_x, title_y - 1, layout); - gdk_draw_layout (gpixmap, gc, title_x + 1, title_y, layout); - gdk_draw_layout (gpixmap, gc, title_x, title_y + 1, layout); + cairo_translate (cr, -1, 0); + pango_cairo_show_layout (cr, layout); + cairo_translate (cr, 1, -1); + pango_cairo_show_layout (cr, layout); + cairo_translate (cr, 1, 1); + pango_cairo_show_layout (cr, layout); + cairo_translate (cr, -1, 1); + pango_cairo_show_layout (cr, layout); + cairo_translate (cr, 0, -1); } } - gdk_gc_get_values (screen_info->title_colors[state].gc, &values); - gdk_gc_set_values (gc, &values, GDK_GC_FOREGROUND); - gdk_draw_layout (gpixmap, gc, title_x, title_y, layout); + gdk_cairo_set_source_rgba (cr, &screen_info->title_colors[state]); + pango_cairo_show_layout (cr, layout); x = x + w3; } @@ -586,8 +591,8 @@ frameCreateTitlePixmap (Client * c, int state, int left, int right, xfwmPixmap * { frameFillTitlePixmap (c, state, TITLE_5, x, w5, top_height, title_pm, top_pm); } - g_object_unref (G_OBJECT (gc)); - g_object_unref (G_OBJECT (gpixmap)); + cairo_destroy (cr); + cairo_surface_destroy (surface); g_object_unref (G_OBJECT (layout)); } diff --git a/src/mypixmap.c b/src/mypixmap.c index 0c516726f..7d84e6fb1 100644 --- a/src/mypixmap.c +++ b/src/mypixmap.c @@ -42,6 +42,7 @@ #include <glib/gstdio.h> #include <gdk/gdk.h> #include <gdk/gdkx.h> +#include <cairo/cairo-xlib.h> #include <libxfce4util/libxfce4util.h> #include <stdlib.h> #include <stdio.h> @@ -794,27 +795,21 @@ xfwmPixmapCompose (GdkPixbuf *pixbuf, const gchar * dir, const gchar * file) static gboolean xfwmPixmapDrawFromGdkPixbuf (xfwmPixmap * pm, GdkPixbuf *pixbuf) { - GdkPixmap *dest_pixmap; - GdkPixmap *dest_bitmap; - GdkVisual *gvisual; - GdkColormap *cmap; + cairo_surface_t *dest_pixmap; + cairo_surface_t *dest_bitmap; + cairo_t *cr; gint width, height; gint dest_x, dest_y; - gint alpha_threshold; + guchar *pixels; + gint dpx; + gboolean status, start_status; + gint x, y, start; g_return_val_if_fail (pm != NULL, FALSE); g_return_val_if_fail (pm->pixmap != None, FALSE); g_return_val_if_fail (pm->mask != None, FALSE); - dest_pixmap = gdk_xid_table_lookup (pm->pixmap); - if (dest_pixmap) - { - g_object_ref (G_OBJECT (dest_pixmap)); - } - else - { - dest_pixmap = gdk_pixmap_foreign_new (pm->pixmap); - } + dest_pixmap = xfwmPixmapCreateSurface (pm, FALSE); if (!dest_pixmap) { @@ -822,31 +817,12 @@ xfwmPixmapDrawFromGdkPixbuf (xfwmPixmap * pm, GdkPixbuf *pixbuf) return FALSE; } - dest_bitmap = gdk_xid_table_lookup (pm->mask); - if (dest_bitmap) - { - g_object_ref (G_OBJECT (dest_bitmap)); - } - else - { - dest_bitmap = gdk_pixmap_foreign_new (pm->mask); - } + dest_bitmap = xfwmPixmapCreateSurface (pm, TRUE); if (!dest_bitmap) { g_warning ("Cannot get bitmap"); - g_object_unref (dest_pixmap); - return FALSE; - } - - gvisual = gdk_screen_get_system_visual (pm->screen_info->gscr); - cmap = gdk_x11_colormap_foreign_new (gvisual, pm->screen_info->cmap); - - if (!cmap) - { - g_warning ("Cannot create colormap"); - g_object_unref (dest_pixmap); - g_object_unref (dest_bitmap); + cairo_surface_destroy (dest_pixmap); return FALSE; } @@ -855,18 +831,63 @@ xfwmPixmapDrawFromGdkPixbuf (xfwmPixmap * pm, GdkPixbuf *pixbuf) dest_x = (pm->width - width) / 2; dest_y = (pm->height - height) / 2; - gdk_drawable_set_colormap (GDK_DRAWABLE (dest_pixmap), cmap); - gdk_draw_pixbuf (GDK_DRAWABLE (dest_pixmap), NULL, pixbuf, 0, 0, dest_x, dest_y, - width, height, GDK_RGB_DITHER_NONE, 0, 0); + cr = cairo_create (dest_pixmap); + gdk_cairo_set_source_pixbuf (cr, pixbuf, dest_x, dest_y); + cairo_paint (cr); + cairo_destroy (cr); + + cr = cairo_create (dest_bitmap); + if (gdk_pixbuf_get_has_alpha (pixbuf) && width > 0) + { + /* draw alpha with threshold as gdk_pixbuf_render_threshold_alpha did before */ + + pixels = gdk_pixbuf_get_pixels (pixbuf); + dpx = gdk_pixbuf_get_rowstride (pixbuf) / gdk_pixbuf_get_width (pixbuf); - alpha_threshold = (gdk_pixbuf_get_has_alpha (pixbuf) ? 0xFF : 0); - gdk_pixbuf_render_threshold_alpha (pixbuf, dest_bitmap, - 0, 0, dest_x, dest_y, - width, height, alpha_threshold); + cairo_translate (cr, dest_x, dest_y); + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_rectangle (cr, 0, 0, width, height); + cairo_fill (cr); - g_object_unref (cmap); - g_object_unref (dest_pixmap); - g_object_unref (dest_bitmap); + for (y = 0; y < height; y++) + { + start_status = FALSE; + start = 0; + for (x = 0; x < width; x++) + { + status = pixels[(y * width + x + 1) * dpx - 1] == 0xff; + if (status != start_status) + { + if (!status) + { + /* draw line from previous start point to current point */ + cairo_rectangle (cr, start, y, x - start, 1); + } + start_status = status; + start = x; + } + } + if (start_status) + { + /* draw finishing line */ + cairo_rectangle (cr, start, y, width - start, 1); + } + } + + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_set_source_rgba (cr, 0, 0, 0, 1); + cairo_fill (cr); + } + else + { + cairo_set_source_rgba (cr, 0, 0, 0, 1); + cairo_rectangle (cr, dest_x, dest_y, width, height); + cairo_fill (cr); + } + cairo_destroy (cr); + + cairo_surface_destroy (dest_pixmap); + cairo_surface_destroy (dest_bitmap); return TRUE; } @@ -875,9 +896,8 @@ gboolean xfwmPixmapRenderGdkPixbuf (xfwmPixmap * pm, GdkPixbuf *pixbuf) { GdkPixbuf *src; - GdkPixmap *destw; - GdkVisual *gvisual; - GdkColormap *cmap; + cairo_surface_t *surface; + cairo_t *cr; gint width, height; gint dest_x, dest_y; @@ -885,32 +905,14 @@ xfwmPixmapRenderGdkPixbuf (xfwmPixmap * pm, GdkPixbuf *pixbuf) g_return_val_if_fail (pm->pixmap != None, FALSE); g_return_val_if_fail (pm->mask != None, FALSE); - destw = gdk_xid_table_lookup (pm->pixmap); - if (destw) - { - g_object_ref (G_OBJECT (destw)); - } - else - { - destw = gdk_pixmap_foreign_new (pm->pixmap); - } + surface = xfwmPixmapCreateSurface (pm, FALSE); - if (!destw) + if (!surface) { g_warning ("Cannot get pixmap"); return FALSE; } - gvisual = gdk_screen_get_system_visual (pm->screen_info->gscr); - cmap = gdk_x11_colormap_foreign_new (gvisual, pm->screen_info->cmap); - - if (!cmap) - { - g_warning ("Cannot create colormap"); - g_object_unref (destw); - return FALSE; - } - width = MIN (gdk_pixbuf_get_width (pixbuf), pm->width); height = MIN (gdk_pixbuf_get_height (pixbuf), pm->height); @@ -918,16 +920,16 @@ xfwmPixmapRenderGdkPixbuf (xfwmPixmap * pm, GdkPixbuf *pixbuf) dest_x = (pm->width - width + 1) / 2; dest_y = (pm->height - height + 1) / 2; - src = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE (destw), cmap, - dest_x, dest_y, 0, 0, width, height); + src = gdk_pixbuf_get_from_surface (surface, dest_x, dest_y, width, height); gdk_pixbuf_composite (pixbuf, src, 0, 0, width, height, 0, 0, 1.0, 1.0, GDK_INTERP_BILINEAR, 0xFF); - gdk_draw_pixbuf (GDK_DRAWABLE (destw), NULL, src, 0, 0, dest_x, dest_y, - width, height, GDK_RGB_DITHER_NONE, 0, 0); + cr = cairo_create (surface); + gdk_cairo_set_source_pixbuf (cr, pixbuf, dest_x, dest_y); + cairo_paint (cr); - g_object_unref (cmap); g_object_unref (src); - g_object_unref (destw); + cairo_destroy (cr); + cairo_surface_destroy (surface); return TRUE; } @@ -1124,3 +1126,24 @@ xfwmPixmapDuplicate (xfwmPixmap * src, xfwmPixmap * dst) xfwmPixmapCreate (src->screen_info, dst, src->width, src->height); xfwmPixmapFill (src, dst, 0, 0, src->width, src->height); } + +cairo_surface_t * +xfwmPixmapCreateSurface (xfwmPixmap *pm, gboolean bitmap) +{ + g_return_val_if_fail (pm != NULL, NULL); + + if (bitmap) + { + return cairo_xlib_surface_create_for_bitmap (pm->screen_info->display_info->dpy, + pm->mask, + pm->screen_info->xscreen, + pm->width, pm->height); + } + else + { + return cairo_xlib_surface_create (pm->screen_info->display_info->dpy, + pm->pixmap, + pm->screen_info->visual, + pm->width, pm->height); + } +} diff --git a/src/mypixmap.h b/src/mypixmap.h index 19302bc93..1b05cface 100644 --- a/src/mypixmap.h +++ b/src/mypixmap.h @@ -26,6 +26,7 @@ #endif #include <glib.h> +#include <cairo/cairo.h> #include "screen.h" #ifdef HAVE_RENDER @@ -78,4 +79,6 @@ void xfwmPixmapFill (xfwmPixmap *, gint); void xfwmPixmapDuplicate (xfwmPixmap *, xfwmPixmap *); +cairo_surface_t *xfwmPixmapCreateSurface (xfwmPixmap *, + gboolean); #endif /* INC_MYPIXMAP_H */ -- GitLab