1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2026-01-31 04:41:23 -08:00

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.
This commit is contained in:
YAMAMOTO Mitsuharu 2019-05-30 17:16:41 +09:00
parent ceca1740ea
commit cc71a82fc7
3 changed files with 81 additions and 4 deletions

View file

@ -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 ();

View file

@ -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),

View file

@ -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