From: YAMAMOTO Mitsuharu Date: Thu, 30 May 2019 08:16:41 +0000 (+0900) Subject: Add stipple support on cairo X-Git-Tag: emacs-27.0.90~2757 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=cc71a82fc705a73fa3ef6cda3ec6bee1cb654d7e;p=emacs.git Add stipple support on cairo * src/xterm.h (struct x_bitmap_record) [USE_CAIRO]: Remove unused member img. Add member stipple. (x_bitmap_stipple) [USE_CAIRO]: Add extern. * src/image.c (x_bitmap_stipple) [HAVE_X_WINDOWS && USE_CAIRO]: New function. (image_create_bitmap_from_data, image_create_bitmap_from_file) (x_create_bitmap_from_xpm_data) [HAVE_X_WINDOWS && USE_CAIRO]: Initialize stipple member of struct x_bitmap_record. (free_bitmap_record) [HAVE_X_WINDOWS && USE_CAIRO]: Destroy stipple member. * src/xterm.c (x_fill_rectangle) [USE_CAIRO]: Inspect gc and draw stipple if necessary. Use x_bitmap_stipple. --- diff --git a/src/image.c b/src/image.c index c5d97e05743..a2e4aa98bf9 100644 --- a/src/image.c +++ b/src/image.c @@ -291,6 +291,41 @@ x_bitmap_width (struct frame *f, ptrdiff_t id) { return FRAME_DISPLAY_INFO (f)->bitmaps[id - 1].width; } + +#ifdef USE_CAIRO +cairo_pattern_t * +x_bitmap_stipple (struct frame *f, Pixmap pixmap) +{ + Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f); + + for (ptrdiff_t i = 0; i < dpyinfo->bitmaps_last; i++) + { + struct x_bitmap_record *bm = dpyinfo->bitmaps + i; + + if (bm->refcount && bm->pixmap == pixmap && bm->depth == 1) + { + if (bm->stipple == NULL) + { + cairo_surface_t *surface + = cairo_xlib_surface_create_for_bitmap (FRAME_X_DISPLAY (f), + pixmap, + FRAME_X_SCREEN (f), + bm->width, bm->height); + cairo_pattern_t *pattern + = cairo_pattern_create_for_surface (surface); + cairo_surface_destroy (surface); + cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); + bm->stipple = pattern; + } + + return bm->stipple; + } + } + + return NULL; +} + +#endif /* USE_CAIRO */ #endif #if defined (HAVE_X_WINDOWS) || defined (HAVE_NTGUI) @@ -389,6 +424,9 @@ image_create_bitmap_from_data (struct frame *f, char *bits, dpyinfo->bitmaps[id - 1].pixmap = bitmap; dpyinfo->bitmaps[id - 1].have_mask = false; dpyinfo->bitmaps[id - 1].depth = 1; +#ifdef USE_CAIRO + dpyinfo->bitmaps[id - 1].stipple = NULL; +#endif /* USE_CAIRO */ #endif /* HAVE_X_WINDOWS */ #ifdef HAVE_NTGUI @@ -470,6 +508,9 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) dpyinfo->bitmaps[id - 1].depth = 1; dpyinfo->bitmaps[id - 1].height = height; dpyinfo->bitmaps[id - 1].width = width; +#ifdef USE_CAIRO + dpyinfo->bitmaps[id - 1].stipple = NULL; +#endif /* USE_CAIRO */ return id; #endif /* HAVE_X_WINDOWS */ @@ -484,6 +525,10 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm) XFreePixmap (dpyinfo->display, bm->pixmap); if (bm->have_mask) XFreePixmap (dpyinfo->display, bm->mask); +#ifdef USE_CAIRO + if (bm->stipple) + cairo_pattern_destroy (bm->stipple); +#endif /* USE_CAIRO */ #endif /* HAVE_X_WINDOWS */ #ifdef HAVE_NTGUI @@ -3843,6 +3888,9 @@ x_create_bitmap_from_xpm_data (struct frame *f, const char **bits) dpyinfo->bitmaps[id - 1].width = attrs.width; dpyinfo->bitmaps[id - 1].depth = attrs.depth; dpyinfo->bitmaps[id - 1].refcount = 1; +#ifdef USE_CAIRO + dpyinfo->bitmaps[id - 1].stipple = NULL; +#endif /* USE_CAIRO */ #ifdef ALLOC_XPM_COLORS xpm_free_color_cache (); diff --git a/src/xterm.c b/src/xterm.c index 03458cb03f6..e9551475f7d 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -698,12 +698,39 @@ static void x_fill_rectangle (struct frame *f, GC gc, int x, int y, int width, int height) { #ifdef USE_CAIRO + Display *dpy = FRAME_X_DISPLAY (f); cairo_t *cr; + XGCValues xgcv; cr = x_begin_cr_clip (f, gc); - x_set_cr_source_with_gc_foreground (f, gc); - cairo_rectangle (cr, x, y, width, height); - cairo_fill (cr); + XGetGCValues (dpy, gc, GCFillStyle | GCStipple, &xgcv); + if (xgcv.fill_style == FillSolid + /* Invalid resource ID (one or more of the three most + significant bits set to 1) is obtained if the GCStipple + component has never been explicitly set. It should be + regarded as Pixmap of unspecified size filled with ones. */ + || (xgcv.stipple & ((Pixmap) 7 << (sizeof (Pixmap) * CHAR_BIT - 3)))) + { + x_set_cr_source_with_gc_foreground (f, gc); + cairo_rectangle (cr, x, y, width, height); + cairo_fill (cr); + } + else + { + eassert (xgcv.fill_style == FillOpaqueStippled); + eassert (xgcv.stipple != None); + x_set_cr_source_with_gc_background (f, gc); + cairo_rectangle (cr, x, y, width, height); + cairo_fill_preserve (cr); + + cairo_pattern_t *pattern = x_bitmap_stipple (f, xgcv.stipple); + if (pattern) + { + x_set_cr_source_with_gc_foreground (f, gc); + cairo_clip (cr); + cairo_mask (cr, pattern); + } + } x_end_cr_clip (f); #else XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f), diff --git a/src/xterm.h b/src/xterm.h index ce1443c381c..2bd2c0105f6 100644 --- a/src/xterm.h +++ b/src/xterm.h @@ -130,7 +130,7 @@ struct xim_inst_t struct x_bitmap_record { #ifdef USE_CAIRO - void *img; + cairo_pattern_t *stipple; #endif Pixmap pixmap; bool have_mask; @@ -151,6 +151,8 @@ struct x_gc_ext_data /* Clipping rectangles. */ XRectangle clip_rects[MAX_CLIP_RECTS]; }; + +extern cairo_pattern_t *x_bitmap_stipple (struct frame *, Pixmap); #endif