From: Yuuki Harano Date: Fri, 5 Jul 2019 13:37:18 +0000 (+0900) Subject: Add Stipple support for PGTK X-Git-Tag: emacs-29.0.90~3844 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=85441c96d74f82ca368b950aa0f5334297bf4fa0;p=emacs.git Add Stipple support for PGTK * ../src/pgtkterm.c (create_background_surface_by_face) (create_background_surface, x_draw_glyph_string_background) (x_draw_glyph_string_bg_rect, x_draw_image_glyph_string) (x_draw_stretch_glyph_string, pgtk_draw_fringe_bitmap): handle stipple * ../src/image.c (image_create_bitmap_from_file, ) (syms_of_image): Add pgtk support * ../lisp/faces.el (face-valid-attribute-values): add pgtk support stipple 対応。 stipple がまともに動いてなかったので修正。 --- diff --git a/lisp/faces.el b/lisp/faces.el index 5e525e79531..ee4a95eb574 100644 --- a/lisp/faces.el +++ b/lisp/faces.el @@ -1151,13 +1151,14 @@ an integer value." (:height 'integerp) (:stipple - (and (memq (window-system frame) '(x ns)) ; No stipple on w32 - (mapcar #'list + (and (memq (window-system frame) '(x ns pgtk)) ; No stipple on w32 + (mapcar (lambda (f) + (cons (file-name-base f) f)) (apply #'nconc (mapcar (lambda (dir) (and (file-readable-p dir) (file-directory-p dir) - (directory-files dir))) + (directory-files dir 'full))) x-bitmap-file-path))))) (:inherit (cons '("none" . nil) diff --git a/src/image.c b/src/image.c index 9beb35c484b..0242b502581 100644 --- a/src/image.c +++ b/src/image.c @@ -507,12 +507,14 @@ image_create_bitmap_from_file (struct frame *f, Lisp_Object file) #endif #ifdef HAVE_PGTK - GError *err; + GError *err = NULL; ptrdiff_t id; void * bitmap = gdk_pixbuf_new_from_file(SSDATA(file), &err); - if (!bitmap) + if (!bitmap) { + g_error_free(err); return -1; + } id = image_allocate_bitmap_record(f); @@ -10698,7 +10700,7 @@ non-numeric, there is no explicit limit on the size of images. */); DEFSYM (Qxbm, "xbm"); add_image_type (Qxbm); -#if defined (HAVE_XPM) || defined (HAVE_NS) +#if defined (HAVE_XPM) || defined (HAVE_NS) || defined (USE_CAIRO) DEFSYM (Qxpm, "xpm"); add_image_type (Qxpm); #endif diff --git a/src/pgtkterm.c b/src/pgtkterm.c index 3e3c73ce503..fb2520614f2 100644 --- a/src/pgtkterm.c +++ b/src/pgtkterm.c @@ -984,6 +984,66 @@ x_clear_glyph_string_rect (struct glyph_string *s, int x, int y, int w, int h) } +static cairo_surface_t * +create_background_surface_by_face (struct frame *f, struct face *face, int x, int y, int width, int height) +{ + cairo_surface_t *surface = cairo_surface_create_similar (FRAME_CR_SURFACE (f), + CAIRO_CONTENT_COLOR, + width, + height); + + { + cairo_t *cr = cairo_create (surface); + + double r = ((face->background >> 16) & 0xff) / 255.0; + double g = ((face->background >> 8) & 0xff) / 255.0; + double b = ((face->background >> 0) & 0xff) / 255.0; + cairo_set_source_rgb (cr, r, g, b); + cairo_paint (cr); + + cairo_destroy (cr); + } + + if (face->stipple != 0) { + GdkPixbuf *pixbuf = FRAME_DISPLAY_INFO (f)->bitmaps[face->stipple - 1].img; + GdkPixbuf *pb = gdk_pixbuf_add_alpha (pixbuf, TRUE, 255, 255, 255); + cairo_surface_t *mask = cairo_surface_create_similar_image (FRAME_CR_SURFACE (f), + CAIRO_FORMAT_A1, + width, + height); + + { + cairo_t *cr = cairo_create (mask); + gdk_cairo_set_source_pixbuf (cr, pb, 0, 0); + cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + cairo_destroy (cr); + } + + { + cairo_t *cr = cairo_create (surface); + double r = ((face->foreground >> 16) & 0xff) / 255.0; + double g = ((face->foreground >> 8) & 0xff) / 255.0; + double b = ((face->foreground >> 0) & 0xff) / 255.0; + cairo_set_source_rgb (cr, r, g, b); + cairo_mask_surface (cr, mask, 0, 0); + cairo_destroy (cr); + } + + cairo_surface_destroy (mask); + g_object_unref (pb); + } + + return surface; +} + +static cairo_surface_t * +create_background_surface (struct glyph_string *s, int x, int y, int width, int height) +{ + return create_background_surface_by_face (s->f, s->face, x, y, width, height); +} + /* Draw the background of glyph_string S. If S->background_filled_p is non-zero don't draw it. FORCE_P non-zero means draw the background even if it wouldn't be drawn normally. This is used @@ -1007,20 +1067,28 @@ x_draw_glyph_string_background (struct glyph_string *s, bool force_p) PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->font_not_found_p); PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", s->extends_to_end_of_line_p); PGTK_TRACE("x_draw_glyph_string_background: 2. %d.", force_p); -#if 0 + if (s->stippled_p) { /* Fill background with a stipple pattern. */ - XSetFillStyle (s->display, s->gc, FillOpaqueStippled); - x_fill_rectangle (s->f, s->gc, s->x, - s->y + box_line_width, - s->background_width, - s->height - 2 * box_line_width); - XSetFillStyle (s->display, s->gc, FillSolid); + + cairo_surface_t *bg = create_background_surface (s, + s->x, s->y + box_line_width, + s->background_width, s->height - 2 * box_line_width); + + cairo_t *cr = pgtk_begin_cr_clip (s->f); + cairo_set_source_surface (cr, bg, s->x, s->y + box_line_width); + cairo_rectangle (cr, + s->x, s->y + box_line_width, + s->background_width, s->height - 2 * box_line_width); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); + + cairo_surface_destroy (bg); + s->background_filled_p = true; } else -#endif if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width /* When xdisp.c ignores FONT_HEIGHT, we cannot trust font dimensions, since the actual glyphs might be @@ -1821,16 +1889,21 @@ x_draw_image_relief (struct glyph_string *s) static void x_draw_glyph_string_bg_rect (struct glyph_string *s, int x, int y, int w, int h) { -#if 0 if (s->stippled_p) { /* Fill background with a stipple pattern. */ - XSetFillStyle (s->display, s->gc, FillOpaqueStippled); - x_fill_rectangle (s->f, s->gc, x, y, w, h); - XSetFillStyle (s->display, s->gc, FillSolid); + + cairo_surface_t *bg = create_background_surface (s, x, y, w, h); + + cairo_t *cr = pgtk_begin_cr_clip (s->f); + cairo_set_source_surface (cr, bg, x, y); + cairo_rectangle (cr, x, y, w, h); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); + + cairo_surface_destroy (bg); } else -#endif x_clear_glyph_string_rect (s, x, y, w, h); } @@ -1881,7 +1954,6 @@ x_draw_image_glyph_string (struct glyph_string *s) int box_line_hwidth = eabs (s->face->box_line_width); int box_line_vwidth = max (s->face->box_line_width, 0); int height; - cairo_surface_t *surface = NULL; height = s->height; if (s->slice.y == 0) @@ -1903,43 +1975,15 @@ x_draw_image_glyph_string (struct glyph_string *s) { if (s->img->mask) { - /* Create a pixmap as large as the glyph string. Fill it - with the background color. Copy the image to it, using - its mask. Copy the temporary pixmap to the display. */ - - /* Create a pixmap as large as the glyph string. */ - surface = cairo_surface_create_similar(FRAME_CR_SURFACE(s->f), CAIRO_CONTENT_COLOR_ALPHA, - s->background_width, - s->height); + cairo_surface_t *bg = create_background_surface (s, s->x, s->y, s->background_width, s->height); - /* Don't clip in the following because we're working on the - pixmap. */ - // XSetClipMask (s->display, s->gc, None); + cairo_t *cr = pgtk_begin_cr_clip (s->f); + cairo_set_source_surface (cr, bg, s->x, s->y); + cairo_rectangle (cr, s->x, s->y, s->background_width, s->height); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); - /* Fill the pixmap with the background color/stipple. */ -#if 0 - if (s->stippled_p) - { - /* Fill background with a stipple pattern. */ - XSetFillStyle (s->display, s->gc, FillOpaqueStippled); - XSetTSOrigin (s->display, s->gc, - s->x, - s->y); - XFillRectangle (s->display, pixmap, s->gc, - 0, 0, s->background_width, s->height); - XSetFillStyle (s->display, s->gc, FillSolid); - XSetTSOrigin (s->display, s->gc, 0, 0); - } - else -#endif - { - cairo_t *cr = cairo_create(surface); - int red = (s->xgcv.background >> 16) & 0xff; - int green = (s->xgcv.background >> 8) & 0xff; - int blue = (s->xgcv.background >> 0) & 0xff; - cairo_set_source_rgb (cr, red / 255.0, green / 255.0, blue / 255.0); - cairo_rectangle(cr, 0, 0, s->background_width, s->height); - cairo_fill(cr); - cairo_destroy(cr); - } + cairo_surface_destroy (bg); } else { @@ -1957,7 +2001,15 @@ x_draw_image_glyph_string (struct glyph_string *s) if (s->slice.y == 0) y += box_line_vwidth; - x_draw_glyph_string_bg_rect (s, x, y, width, height); + cairo_surface_t *bg = create_background_surface (s, x, y, width, height); + + cairo_t *cr = pgtk_begin_cr_clip (s->f); + cairo_set_source_surface (cr, bg, x, y); + cairo_rectangle (cr, x, y, width, height); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); + + cairo_surface_destroy (bg); } s->background_filled_p = true; @@ -1978,18 +2030,6 @@ x_draw_image_glyph_string (struct glyph_string *s) cairo_fill (cr); pgtk_end_cr_clip (s->f); } - else - if (surface != NULL) - { - cairo_t *cr = pgtk_begin_cr_clip(s->f); - - x_draw_image_foreground_1 (s, surface); - x_set_glyph_string_clipping (s, cr); - - cairo_set_source_surface(cr, surface, 0, 0); - cairo_rectangle(cr, s->x, s->y, s->background_width, s->height); - pgtk_end_cr_clip(s->f); - } else x_draw_image_foreground (s); @@ -1998,9 +2038,6 @@ x_draw_image_glyph_string (struct glyph_string *s) || s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) x_draw_image_relief (s); - - if (surface != NULL) - cairo_surface_destroy(surface); } /* Draw stretch glyph string S. */ @@ -2071,16 +2108,18 @@ x_draw_stretch_glyph_string (struct glyph_string *s) get_glyph_string_clip_rect (s, &r); x_set_clip_rectangles (s->f, cr, &r, 1); -#if 0 if (s->face->stipple) { /* Fill background with a stipple pattern. */ - XSetFillStyle (s->display, gc, FillOpaqueStippled); - x_fill_rectangle (s->f, gc, x, y, w, h); - XSetFillStyle (s->display, gc, FillSolid); + cairo_surface_t *bg = create_background_surface (s, x, y, w, h); + cairo_t *cr = pgtk_begin_cr_clip (s->f); + cairo_set_source_surface (cr, bg, x, y); + cairo_rectangle (cr, x, y, w, h); + cairo_fill (cr); + pgtk_end_cr_clip (s->f); + cairo_surface_destroy (bg); } else -#endif { pgtk_fill_rectangle(s->f, color, x, y, w, h); } @@ -3195,15 +3234,19 @@ pgtk_draw_fringe_bitmap (struct window *w, struct glyph_row *row, struct draw_fr for something displayed in the text (e.g. face `region' on mono-displays, the fill style may have been changed to FillSolid in x_draw_glyph_string_background. */ -#if 0 - if (face->stipple) - XSetFillStyle (display, face->gc, FillOpaqueStippled); - else -#endif + if (face->stipple) { + cairo_surface_t *bg = create_background_surface_by_face(f, face, p->bx, p->by, p->nx, p->ny); + cairo_t *cr = pgtk_begin_cr_clip (f); + cairo_set_source_surface (cr, bg, p->bx, p->by); + cairo_rectangle (cr, p->bx, p->by, p->nx, p->ny); + cairo_fill (cr); + pgtk_end_cr_clip (f); + cairo_surface_destroy (bg); + } else { pgtk_set_cr_source_with_color(f, face->background); - - cairo_rectangle(cr, p->bx, p->by, p->nx, p->ny); - cairo_fill(cr); + cairo_rectangle(cr, p->bx, p->by, p->nx, p->ny); + cairo_fill(cr); + } } PGTK_TRACE("which: %d, max_fringe_bmp: %d.", p->which, max_fringe_bmp);