>From 8644aace35436d4e92f5c998003072b4b345f8ab Mon Sep 17 00:00:00 2001 From: Alan Third Date: Mon, 10 Dec 2018 19:43:08 +0000 Subject: [PATCH] Add native image scaling * configure.ac: Test for XRender outside of xft checks. * src/Makefile.in (XRENDER_LIBS): List XRender libs separately from xft libs. * lisp/image.el (image--get-imagemagick-and-warn): Remove ImageMagick checks and on't flush the image cache as often. * src/image.c (get_cache_spec): (calc_image_spec): New function. (Fimage_flush): Use the modified image spec. (image_ascent): (Fimage_size): Replace struct image with struct image_spec. (make_image): Remove members that are image independent. (scale_image_size): (compute_image_size): Make available when image resizing of any sort is available. (lookup_image): Use new cache_spec for lookups and remove image independent code. * src/dispextern.h (struct image_spec): New struct. (struct it): (struct glyph): Replace an image_id with struct image_spec. (struct glyph_string): Add struct image_spec. (struct image): Remove members that are image independent. (calc_image_spec): New function. (image_ascent): Replace struct image with struct image_spec. * src/dispnew.c (buffer_posn_from_coords): (mode_line_string): (marginal_area_string): Replace struct image. * src/nsimage.m (ns_load_image): ([EmacsImage setSizeFromSpec:]): Remove NS specific image resizing. * src/nsterm.m (ns_draw_fringe_bitmap): Remove GNUstep specific code. (ns_dumpglyphs_image): Composite image according to sizes in new image_prop struct. * src/w32term.c (x_draw_image_foreground): (x_draw_image_relief): (w32_draw_image_foreground_1): Replace struct image with struct image_spec. * src/xdisp.c (handle_single_display_spec): (push_it): (pop_it): (dump_glyph): (push_prefix_prop): (calc_pixel_width_or_height): (fill_image_glyph_string): (produce_image_glyph): (get_window_cursor_type): Replace struct image with struct image_spec. (note_mouse_highlight): Use the image spec stored in the glyph struct rather than the one attached to the image struct. * src/xterm.c (x_composite_image): New function. (x_draw_image_foreground): Replace struct image with struct image_spec and use new x_composite_image function. (x_draw_image_relief): (x_draw_image_foreground_1): (x_draw_image_glyph_string): Replace struct image with struct image_spec. --- configure.ac | 14 +- lisp/image.el | 3 - src/Makefile.in | 3 +- src/dispextern.h | 48 +++--- src/dispnew.c | 32 +--- src/image.c | 374 +++++++++++++++++++++++++++++------------------ src/nsimage.m | 62 -------- src/nsterm.h | 1 - src/nsterm.m | 36 ++--- src/w32term.c | 6 +- src/xdisp.c | 86 ++++++----- src/xterm.c | 108 +++++++++----- 12 files changed, 417 insertions(+), 356 deletions(-) diff --git a/configure.ac b/configure.ac index 8b34c3b658..2b22e2cbc2 100644 --- a/configure.ac +++ b/configure.ac @@ -3241,6 +3241,17 @@ AC_DEFUN CFLAGS=$late_CFLAGS fi +# Check for XRender +HAVE_XRENDER=no +if test "${HAVE_X11}" = "yes"; then + AC_CHECK_LIB(Xrender, XRenderQueryExtension, HAVE_XRENDER=yes) + if test $HAVE_XRENDER = yes; then + XRENDER_LIBS="-lXrender" + AC_SUBST(XRENDER_LIBS) + AC_DEFINE([HAVE_XRENDER], 1, [Define to 1 if XRender is available.]) + fi +fi + ### Start of font-backend (under any platform) section. # (nothing here yet -- this is a placeholder) ### End of font-backend (under any platform) section. @@ -3263,15 +3274,12 @@ AC_DEFUN EMACS_CHECK_MODULES([XFT], [xft >= 0.13.0], [], [HAVE_XFT=no]) ## Because xterm.c uses XRenderQueryExtension when XFT is ## enabled, we also need to link to -lXrender. - HAVE_XRENDER=no - AC_CHECK_LIB(Xrender, XRenderQueryExtension, HAVE_XRENDER=yes) if test "$HAVE_XFT" != no && test "$HAVE_XRENDER" != no; then OLD_CPPFLAGS="$CPPFLAGS" OLD_CFLAGS="$CFLAGS" OLD_LIBS="$LIBS" CPPFLAGS="$CPPFLAGS $XFT_CFLAGS" CFLAGS="$CFLAGS $XFT_CFLAGS" - XFT_LIBS="-lXrender $XFT_LIBS" LIBS="$XFT_LIBS $LIBS" AC_CHECK_HEADER(X11/Xft/Xft.h, AC_CHECK_LIB(Xft, XftFontOpen, HAVE_XFT=yes, , $XFT_LIBS) , , diff --git a/lisp/image.el b/lisp/image.el index 74a23046e9..4843c2de1f 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -982,10 +982,7 @@ image--get-image image)) (defun image--get-imagemagick-and-warn () - (unless (or (fboundp 'imagemagick-types) (featurep 'ns)) - (error "Cannot rescale images without ImageMagick support")) (let ((image (image--get-image))) - (image-flush image) (when (fboundp 'imagemagick-types) (plist-put (cdr image) :type 'imagemagick)) image)) diff --git a/src/Makefile.in b/src/Makefile.in index 6b2e54a160..809a484413 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -127,7 +127,8 @@ LIBIMAGE= address@hidden@ address@hidden@ -LIBX_EXTRA=-lX11 $(XCB_LIBS) $(XFT_LIBS) address@hidden@ +LIBX_EXTRA=-lX11 $(XCB_LIBS) $(XFT_LIBS) $(XRENDER_LIBS) FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ diff --git a/src/dispextern.h b/src/dispextern.h index 4cd017603d..877948ee97 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -172,6 +172,30 @@ extern bool trace_redisplay_p EXTERNALLY_VISIBLE; +/* Struct for use by display functions. Contains the desired size of + the image, derived from the display properties. */ + +struct image_spec +{ + ptrdiff_t image_id; + int width; + int height; + + /* Relief to draw around the image. */ + int relief; + + /* Optional margins around the image. This includes the relief. */ + int hmargin, vmargin; + + /* Percent of image height used as ascent. A value of + CENTERED_IMAGE_ASCENT means draw the image centered on the + line. */ + int ascent; +#define DEFAULT_IMAGE_ASCENT 50 +#define CENTERED_IMAGE_ASCENT -1 +}; + + /*********************************************************************** Text positions ***********************************************************************/ @@ -505,7 +529,7 @@ struct glyph } cmp; /* Image ID for image glyphs (type == IMAGE_GLYPH). */ - int img_id; + struct image_spec image; #ifdef HAVE_XWIDGETS /* Xwidget reference (type == XWIDGET_GLYPH). */ @@ -1361,6 +1385,7 @@ struct glyph_string /* Image, if any. */ struct image *img; + struct image_spec image; /* Xwidget. */ struct xwidget *xwidget; @@ -2373,7 +2398,7 @@ struct it struct { Lisp_Object object; struct it_slice slice; - ptrdiff_t image_id; + struct image_spec image; } image; /* method == GET_FROM_STRETCH */ struct { @@ -2509,7 +2534,7 @@ struct it enum glyphless_display_method glyphless_method; /* If what == IT_IMAGE, the id of the image to display. */ - ptrdiff_t image_id; + struct image_spec image; /* If what == IT_XWIDGET. */ struct xwidget *xwidget; @@ -3001,13 +3026,6 @@ struct image #define BOT_CORNER 2 #define RIGHT_CORNER 3 - /* Percent of image height used as ascent. A value of - CENTERED_IMAGE_ASCENT means draw the image centered on the - line. */ - int ascent; -#define DEFAULT_IMAGE_ASCENT 50 -#define CENTERED_IMAGE_ASCENT -1 - /* Lisp specification of this image. */ Lisp_Object spec; @@ -3016,12 +3034,6 @@ struct image Used to allow fine-grained cache flushing. */ Lisp_Object dependencies; - /* Relief to draw around the image. */ - int relief; - - /* Optional margins around the image. This includes the relief. */ - int hmargin, vmargin; - /* Reference to the type of the image. */ struct image_type *type; @@ -3042,7 +3054,6 @@ struct image struct image *next, *prev; }; - /* Cache of images. Each frame has a cache. X frames with the same x_display_info share their caches. */ @@ -3358,6 +3369,7 @@ void clear_image_caches (Lisp_Object); void mark_image_cache (struct image_cache *); bool valid_image_p (Lisp_Object); void prepare_image_for_display (struct frame *, struct image *); +struct image_spec calc_image_spec (struct frame *f, Lisp_Object spec); ptrdiff_t lookup_image (struct frame *, Lisp_Object); #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) @@ -3373,7 +3385,7 @@ RGB_PIXEL_COLOR image_background (struct image *, struct frame *, int image_background_transparent (struct image *, struct frame *, XImagePtr_or_DC mask); -int image_ascent (struct image *, struct face *, struct glyph_slice *); +int image_ascent (struct image_spec, struct face *, struct glyph_slice *); #endif diff --git a/src/dispnew.c b/src/dispnew.c index b628c694e8..4f374928eb 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -5117,9 +5117,6 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p struct text_pos startp; Lisp_Object string; struct glyph_row *row; -#ifdef HAVE_WINDOW_SYSTEM - struct image *img = 0; -#endif int x0, x1, to_x, it_vpos; void *itdata = NULL; @@ -5213,17 +5210,8 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p } #ifdef HAVE_WINDOW_SYSTEM - if (it.what == IT_IMAGE) - { - /* Note that this ignores images that are fringe bitmaps, - because their image ID is zero, and so IMAGE_OPT_FROM_ID will - return NULL. This is okay, since fringe bitmaps are not - displayed in the text area, and so are never the object we - are interested in. */ - img = IMAGE_OPT_FROM_ID (it.f, it.image_id); - if (img && !NILP (img->spec)) - *object = img->spec; - } + if (it.what == IT_IMAGE && !NILP (it.object)) + *object = it.object; #endif /* IT's vpos counts from the glyph row that includes the window's @@ -5239,14 +5227,14 @@ buffer_posn_from_coords (struct window *w, int *x, int *y, struct display_pos *p { struct glyph *glyph = row->glyphs[TEXT_AREA] + it.hpos; #ifdef HAVE_WINDOW_SYSTEM - if (img) + if (it.what == IT_IMAGE) { *dy -= row->ascent - glyph->ascent; *dx += glyph->slice.img.x; *dy += glyph->slice.img.y; /* Image slices positions are still relative to the entire image */ - *width = img->width; - *height = img->height; + *width = it.image.width; + *height = it.image.height; } else #endif @@ -5317,10 +5305,7 @@ mode_line_string (struct window *w, enum window_part part, #ifdef HAVE_WINDOW_SYSTEM if (glyph->type == IMAGE_GLYPH) { - struct image *img; - img = IMAGE_OPT_FROM_ID (WINDOW_XFRAME (w), glyph->u.img_id); - if (img != NULL) - *object = img->spec; + *object = glyph->object; y0 -= row->ascent - glyph->ascent; } #endif @@ -5404,10 +5389,7 @@ marginal_area_string (struct window *w, enum window_part part, #ifdef HAVE_WINDOW_SYSTEM if (glyph->type == IMAGE_GLYPH) { - struct image *img; - img = IMAGE_OPT_FROM_ID (WINDOW_XFRAME (w), glyph->u.img_id); - if (img != NULL) - *object = img->spec; + *object = glyph->object; y0 -= row->ascent - glyph->ascent; x0 += glyph->slice.img.x; y0 += glyph->slice.img.y; diff --git a/src/image.c b/src/image.c index 218626f771..7900d3a2bc 100644 --- a/src/image.c +++ b/src/image.c @@ -901,11 +901,14 @@ or omitted means use the selected frame. */) size = Qnil; if (valid_image_p (spec)) { + struct image_spec image; + int width, height; struct frame *f = decode_window_system_frame (frame); - ptrdiff_t id = lookup_image (f, spec); - struct image *img = IMAGE_FROM_ID (f, id); - int width = img->width + 2 * img->hmargin; - int height = img->height + 2 * img->vmargin; + + image = calc_image_spec (f, spec); + + width = image.width + 2 * image.hmargin; + height = image.height + 2 * image.vmargin; if (NILP (pixels)) size = Fcons (make_float ((double) width / FRAME_COLUMN_WIDTH (f)), @@ -984,7 +987,6 @@ make_image (Lisp_Object spec, EMACS_UINT hash) eassert (img->type != NULL); img->spec = spec; img->lisp_data = Qnil; - img->ascent = DEFAULT_IMAGE_ASCENT; img->hash = hash; img->corners[BOT_CORNER] = -1; /* Full image */ return img; @@ -1082,19 +1084,19 @@ prepare_image_for_display (struct frame *f, struct image *img) drawn in face FACE. */ int -image_ascent (struct image *img, struct face *face, struct glyph_slice *slice) +image_ascent (struct image_spec img, struct face *face, struct glyph_slice *slice) { int height; int ascent; - if (slice->height == img->height) - height = img->height + img->vmargin; + if (slice->height == img.height) + height = img.height + img.vmargin; else if (slice->y == 0) - height = slice->height + img->vmargin; + height = slice->height + img.vmargin; else height = slice->height; - if (img->ascent == CENTERED_IMAGE_ASCENT) + if (img.ascent == CENTERED_IMAGE_ASCENT) { if (face->font) { @@ -1116,7 +1118,7 @@ image_ascent (struct image *img, struct face *face, struct glyph_slice *slice) ascent = height / 2; } else - ascent = height * (img->ascent / 100.0); + ascent = height * (img.ascent / 100.0); return ascent; } @@ -1453,6 +1455,46 @@ make_image_cache (void) return c; } +/* Filter the SPEC so it can be used to look up images in the cache + without worrying about whether they are the same size, etc. */ + +static Lisp_Object +get_cache_spec (Lisp_Object spec) +{ + Lisp_Object cache_spec, tail; + + /* If type is imagemagick then the image will already be resized and + rotated, etc., so just return the full spec. + + FIXME: I think we still want to strip out the likes of margin, as + that is not part of the image. */ + if (EQ (image_spec_value (spec, QCtype, NULL), Qimagemagick)) + return spec; + + cache_spec = Qnil; + + for (tail = XCDR (spec); + CONSP (tail) && CONSP (XCDR (tail)); + tail = XCDR (XCDR (tail))) + { + Lisp_Object property = XCAR (tail); + Lisp_Object value = XCAR (XCDR (tail)); + + /* FIXME: Surely there's a better way to do this? */ + if (!EQ (property, QCwidth) + && !EQ (property, QCheight) + && !EQ (property, QCmax_width) + && !EQ (property, QCmax_height) + && !EQ (property, QCscale) + && !EQ (property, QCmargin) + && !EQ (property, QCascent) + && !EQ (property, QCrelief)) + cache_spec = Fcons (property, Fcons (value, cache_spec)); + } + cache_spec = Fcons (XCAR (spec), cache_spec); + + return cache_spec; +} /* Find an image matching SPEC in the cache, and return it. If no image is found, return NULL. */ @@ -1661,6 +1703,8 @@ FRAME t means refresh the image on all frames. */) if (!valid_image_p (spec)) error ("Invalid image specification"); + spec = get_cache_spec (spec); + if (EQ (frame, Qt)) { Lisp_Object tail; @@ -1747,6 +1791,176 @@ postprocess_image (struct frame *f, struct image *img) } } +#if defined (HAVE_IMAGEMAGICK) || defined (HAVE_XRENDER) || defined (HAVE_NS) +/* Scale an image size by returning SIZE / DIVISOR * MULTIPLIER, + safely rounded and clipped to int range. */ + +static int +scale_image_size (int size, size_t divisor, size_t multiplier) +{ + if (divisor != 0) + { + double s = size; + double scaled = s * multiplier / divisor + 0.5; + if (scaled < INT_MAX) + return scaled; + } + return INT_MAX; +} + +/* Compute the desired size of an image with native size WIDTH x HEIGHT. + Use SPEC to deduce the size. Store the desired size into + *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */ +static void +compute_image_size (size_t width, size_t height, + Lisp_Object spec, + int *d_width, int *d_height) +{ + Lisp_Object value; + int desired_width = -1, desired_height = -1, max_width = -1, max_height = -1; + double scale = 1; + + value = image_spec_value (spec, QCscale, NULL); + if (NUMBERP (value)) + scale = XFLOATINT (value); + + value = image_spec_value (spec, QCmax_width, NULL); + if (FIXNATP (value)) + max_width = min (XFIXNAT (value), INT_MAX); + + value = image_spec_value (spec, QCmax_height, NULL); + if (FIXNATP (value)) + max_height = min (XFIXNAT (value), INT_MAX); + + /* If width and/or height is set in the display spec assume we want + to scale to those values. If either h or w is unspecified, the + unspecified should be calculated from the specified to preserve + aspect ratio. */ + value = image_spec_value (spec, QCwidth, NULL); + if (FIXNATP (value)) + { + desired_width = min (XFIXNAT (value) * scale, INT_MAX); + /* :width overrides :max-width. */ + max_width = -1; + } + + value = image_spec_value (spec, QCheight, NULL); + if (FIXNATP (value)) + { + desired_height = min (XFIXNAT (value) * scale, INT_MAX); + /* :height overrides :max-height. */ + max_height = -1; + } + + /* If we have both width/height set explicitly, we skip past all the + aspect ratio-preserving computations below. */ + if (desired_width != -1 && desired_height != -1) + goto out; + + width = width * scale; + height = height * scale; + + if (desired_width != -1) + /* Width known, calculate height. */ + desired_height = scale_image_size (desired_width, width, height); + else if (desired_height != -1) + /* Height known, calculate width. */ + desired_width = scale_image_size (desired_height, height, width); + else + { + desired_width = width; + desired_height = height; + } + + if (max_width != -1 && desired_width > max_width) + { + /* The image is wider than :max-width. */ + desired_width = max_width; + desired_height = scale_image_size (desired_width, width, height); + } + + if (max_height != -1 && desired_height > max_height) + { + /* The image is higher than :max-height. */ + desired_height = max_height; + desired_width = scale_image_size (desired_height, height, width); + } + + out: + *d_width = desired_width; + *d_height = desired_height; +} +#endif /* HAVE_IMAGEMAGICK || HAVE_XRENDER || HAVE_NS */ + +struct image_spec +calc_image_spec (struct frame *f, Lisp_Object spec) +{ + struct image_spec img_spec; + struct image *img; + + Lisp_Object ascent, margin, relief; + int relief_bound; + + img_spec.image_id = lookup_image (f, spec); + img = IMAGE_OPT_FROM_ID (f, img_spec.image_id); + +#if defined (HAVE_XRENDER) || defined (HAVE_NS) + if (!EQ (image_spec_value (spec, QCtype, NULL), Qimagemagick)) + { + int width, height; + + compute_image_size (img->width, img->height, spec, &width, &height); + + /* Set the final sizes. We always maintain the aspect ratio. */ + img_spec.width = width; + img_spec.height = height; + } + else +#endif + { + /* We don't have built-in image resizing or we're using + ImageMagick which does its own transforms. */ + img_spec.width = img->width; + img_spec.height = img->height; + } + + /* Handle type independent image attributes + `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF'. */ + ascent = image_spec_value (spec, QCascent, NULL); + if (FIXNUMP (ascent)) + img_spec.ascent = XFIXNAT (ascent); + else if (EQ (ascent, Qcenter)) + img_spec.ascent = CENTERED_IMAGE_ASCENT; + else + img_spec.ascent = DEFAULT_IMAGE_ASCENT; + + margin = image_spec_value (spec, QCmargin, NULL); + if (FIXNUMP (margin)) + img_spec.vmargin = img_spec.hmargin = XFIXNAT (margin); + else if (CONSP (margin)) + { + img_spec.hmargin = XFIXNAT (XCAR (margin)); + img_spec.vmargin = XFIXNAT (XCDR (margin)); + } + else + { + img_spec.hmargin = 0; + img_spec.vmargin = 0; + } + + relief = image_spec_value (spec, QCrelief, NULL); + relief_bound = INT_MAX - max (img_spec.hmargin, img_spec.vmargin); + if (RANGED_FIXNUMP (- relief_bound, relief, relief_bound)) + { + img_spec.relief = XFIXNUM (relief); + img_spec.hmargin += eabs (img_spec.relief); + img_spec.vmargin += eabs (img_spec.relief); + } + else + img_spec.relief = 0; + + return img_spec; +} /* Return the id of image with Lisp specification SPEC on frame F. SPEC must be a valid Lisp image specification (see valid_image_p). */ @@ -1756,15 +1970,18 @@ lookup_image (struct frame *f, Lisp_Object spec) { struct image *img; EMACS_UINT hash; + Lisp_Object cache_spec; /* F must be a window-system frame, and SPEC must be a valid image specification. */ eassert (FRAME_WINDOW_P (f)); eassert (valid_image_p (spec)); + cache_spec = get_cache_spec (spec); + /* Look up SPEC in the hash table of the image cache. */ - hash = sxhash (spec, 0); - img = search_image_cache (f, spec, hash); + hash = sxhash (cache_spec, 0); + img = search_image_cache (f, cache_spec, hash); if (img && img->load_failed_p) { free_image (f, img); @@ -1775,7 +1992,7 @@ lookup_image (struct frame *f, Lisp_Object spec) if (img == NULL) { block_input (); - img = make_image (spec, hash); + img = make_image (cache_spec, hash); cache_image (f, img); img->load_failed_p = ! img->type->load (f, img); img->frame_foreground = FRAME_FOREGROUND_PIXEL (f); @@ -1797,35 +2014,9 @@ lookup_image (struct frame *f, Lisp_Object spec) } else { - /* Handle image type independent image attributes - `:ascent ASCENT', `:margin MARGIN', `:relief RELIEF', + /* Handle image type independent image attribute `:background COLOR'. */ - Lisp_Object ascent, margin, relief, bg; - int relief_bound; - - ascent = image_spec_value (spec, QCascent, NULL); - if (FIXNUMP (ascent)) - img->ascent = XFIXNAT (ascent); - else if (EQ (ascent, Qcenter)) - img->ascent = CENTERED_IMAGE_ASCENT; - - margin = image_spec_value (spec, QCmargin, NULL); - if (FIXNUMP (margin)) - img->vmargin = img->hmargin = XFIXNAT (margin); - else if (CONSP (margin)) - { - img->hmargin = XFIXNAT (XCAR (margin)); - img->vmargin = XFIXNAT (XCDR (margin)); - } - - relief = image_spec_value (spec, QCrelief, NULL); - relief_bound = INT_MAX - max (img->hmargin, img->vmargin); - if (RANGED_FIXNUMP (- relief_bound, relief, relief_bound)) - { - img->relief = XFIXNUM (relief); - img->hmargin += eabs (img->relief); - img->vmargin += eabs (img->relief); - } + Lisp_Object bg; if (! img->background_valid) { @@ -8101,105 +8292,6 @@ gif_load (struct frame *f, struct image *img) ImageMagick ***********************************************************************/ -/* Scale an image size by returning SIZE / DIVISOR * MULTIPLIER, - safely rounded and clipped to int range. */ - -static int -scale_image_size (int size, size_t divisor, size_t multiplier) -{ - if (divisor != 0) - { - double s = size; - double scaled = s * multiplier / divisor + 0.5; - if (scaled < INT_MAX) - return scaled; - } - return INT_MAX; -} - -/* Compute the desired size of an image with native size WIDTH x HEIGHT. - Use SPEC to deduce the size. Store the desired size into - *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */ -static void -compute_image_size (size_t width, size_t height, - Lisp_Object spec, - int *d_width, int *d_height) -{ - Lisp_Object value; - int desired_width = -1, desired_height = -1, max_width = -1, max_height = -1; - double scale = 1; - - value = image_spec_value (spec, QCscale, NULL); - if (NUMBERP (value)) - scale = XFLOATINT (value); - - value = image_spec_value (spec, QCmax_width, NULL); - if (FIXNATP (value)) - max_width = min (XFIXNAT (value), INT_MAX); - - value = image_spec_value (spec, QCmax_height, NULL); - if (FIXNATP (value)) - max_height = min (XFIXNAT (value), INT_MAX); - - /* If width and/or height is set in the display spec assume we want - to scale to those values. If either h or w is unspecified, the - unspecified should be calculated from the specified to preserve - aspect ratio. */ - value = image_spec_value (spec, QCwidth, NULL); - if (FIXNATP (value)) - { - desired_width = min (XFIXNAT (value) * scale, INT_MAX); - /* :width overrides :max-width. */ - max_width = -1; - } - - value = image_spec_value (spec, QCheight, NULL); - if (FIXNATP (value)) - { - desired_height = min (XFIXNAT (value) * scale, INT_MAX); - /* :height overrides :max-height. */ - max_height = -1; - } - - /* If we have both width/height set explicitly, we skip past all the - aspect ratio-preserving computations below. */ - if (desired_width != -1 && desired_height != -1) - goto out; - - width = width * scale; - height = height * scale; - - if (desired_width != -1) - /* Width known, calculate height. */ - desired_height = scale_image_size (desired_width, width, height); - else if (desired_height != -1) - /* Height known, calculate width. */ - desired_width = scale_image_size (desired_height, height, width); - else - { - desired_width = width; - desired_height = height; - } - - if (max_width != -1 && desired_width > max_width) - { - /* The image is wider than :max-width. */ - desired_width = max_width; - desired_height = scale_image_size (desired_width, width, height); - } - - if (max_height != -1 && desired_height > max_height) - { - /* The image is higher than :max-height. */ - desired_height = max_height; - desired_width = scale_image_size (desired_height, height, width); - } - - out: - *d_width = desired_width; - *d_height = desired_height; -} - static bool imagemagick_image_p (Lisp_Object); static bool imagemagick_load (struct frame *, struct image *); static void imagemagick_clear_image (struct frame *, struct image *); diff --git a/src/nsimage.m b/src/nsimage.m index 0ae1b88edd..71da0201d1 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -126,8 +126,6 @@ Updated by Christian Limpach (address@hidden) eImg = temp; } - [eImg setSizeFromSpec:XCDR (img->spec)]; - size = [eImg size]; img->width = size.width; img->height = size.height; @@ -524,66 +522,6 @@ - (BOOL)setFrame: (unsigned int) index return YES; } -- (void)setSizeFromSpec: (Lisp_Object) spec -{ - NSSize size = [self size]; - Lisp_Object value; - double scale = 1, aspect = size.width / size.height; - double width = -1, height = -1, max_width = -1, max_height = -1; - - value = Fplist_get (spec, QCscale); - if (NUMBERP (value)) - scale = XFLOATINT (value) ; - - value = Fplist_get (spec, QCmax_width); - if (NUMBERP (value)) - max_width = XFLOATINT (value); - - value = Fplist_get (spec, QCmax_height); - if (NUMBERP (value)) - max_height = XFLOATINT (value); - - value = Fplist_get (spec, QCwidth); - if (NUMBERP (value)) - { - width = XFLOATINT (value) * scale; - /* :width overrides :max-width. */ - max_width = -1; - } - - value = Fplist_get (spec, QCheight); - if (NUMBERP (value)) - { - height = XFLOATINT (value) * scale; - /* :height overrides :max-height. */ - max_height = -1; - } - - if (width <= 0 && height <= 0) - { - width = size.width * scale; - height = size.height * scale; - } - else if (width > 0 && height <= 0) - height = width / aspect; - else if (height > 0 && width <= 0) - width = height * aspect; - - if (max_width > 0 && width > max_width) - { - width = max_width; - height = max_width / aspect; - } - - if (max_height > 0 && height > max_height) - { - height = max_height; - width = max_height * aspect; - } - - [self setSize:NSMakeSize(width, height)]; -} - - (instancetype)rotate: (double)rotation { EmacsImage *new_image; diff --git a/src/nsterm.h b/src/nsterm.h index 23460abc65..f64d78bd2b 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -648,7 +648,6 @@ typedef id instancetype; - (NSColor *)stippleMask; - (Lisp_Object)getMetadata; - (BOOL)setFrame: (unsigned int) index; -- (void)setSizeFromSpec: (Lisp_Object) spec; - (instancetype)rotate: (double)rotation; @end diff --git a/src/nsterm.m b/src/nsterm.m index 6c285f0abb..0a2a184830 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -3121,7 +3121,6 @@ so some key presses (TAB) are swallowed by the system. */ [img setXBMColor: bm_color]; } -#ifdef NS_IMPL_COCOA // Note: For periodic images, the full image height is "h + hd". // By using the height h, a suitable part of the image is used. NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h); @@ -3134,13 +3133,6 @@ so some key presses (TAB) are swallowed by the system. */ fraction: 1.0 respectFlipped: YES hints: nil]; -#else - { - NSPoint pt = imageRect.origin; - pt.y += p->h; - [img compositeToPoint: pt operation: NSCompositingOperationSourceOver]; - } -#endif } ns_reset_clipping (f); } @@ -3821,13 +3813,15 @@ Function modeled after x_draw_glyph_string_box (). { EmacsImage *img = s->img->pixmap; int box_line_vwidth = max (s->face->box_line_width, 0); - int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice); + int x = s->x, y = s->ybase - image_ascent (s->image, s->face, &s->slice); int bg_x, bg_y, bg_height; int th; char raised_p; NSRect br; struct face *face; NSColor *tdCol; + double xscale = (double)s->img->width/s->image.width; + double yscale = (double)s->img->height/s->image.height; NSTRACE ("ns_dumpglyphs_image"); @@ -3841,8 +3835,8 @@ Function modeled after x_draw_glyph_string_box (). /* other terms have this, but was causing problems w/tabbar mode */ /* - 2 * box_line_vwidth; */ - if (s->slice.x == 0) x += s->img->hmargin; - if (s->slice.y == 0) y += s->img->vmargin; + if (s->slice.x == 0) x += s->image.hmargin; + if (s->slice.y == 0) y += s->image.vmargin; /* Draw BG: if we need larger area than image itself cleared, do that, otherwise, since we composite the image under NS (instead of mucking @@ -3859,7 +3853,7 @@ Function modeled after x_draw_glyph_string_box (). [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f) set]; - if (bg_height > s->slice.height || s->img->hmargin || s->img->vmargin + if (bg_height > s->slice.height || s->image.hmargin || s->image.vmargin || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width) { br = NSMakeRect (bg_x, bg_y, s->background_width, bg_height); @@ -3877,9 +3871,9 @@ Function modeled after x_draw_glyph_string_box (). { #ifdef NS_IMPL_COCOA NSRect dr = NSMakeRect (x, y, s->slice.width, s->slice.height); - NSRect ir = NSMakeRect (s->slice.x, - s->img->height - s->slice.y - s->slice.height, - s->slice.width, s->slice.height); + NSRect ir = NSMakeRect (s->slice.x * xscale, + (s->image.height - s->slice.y - s->slice.height) * yscale, + s->slice.width * xscale , s->slice.height * yscale); [img drawInRect: dr fromRect: ir operation: NSCompositingOperationSourceOver @@ -3914,7 +3908,7 @@ Function modeled after x_draw_glyph_string_box (). ns_draw_text_decoration (s, face, tdCol, br.size.width, br.origin.x); /* Draw relief, if requested */ - if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN) + if (s->image.relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN) { if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED) { @@ -3924,8 +3918,8 @@ Function modeled after x_draw_glyph_string_box (). } else { - th = abs (s->img->relief); - raised_p = (s->img->relief > 0); + th = abs (s->image.relief); + raised_p = (s->image.relief > 0); } r.origin.x = x - th; @@ -3934,9 +3928,9 @@ Function modeled after x_draw_glyph_string_box (). r.size.height = s->slice.height + 2*th-1; ns_draw_relief (r, th, raised_p, s->slice.y == 0, - s->slice.y + s->slice.height == s->img->height, + s->slice.y + s->slice.height == s->image.height, s->slice.x == 0, - s->slice.x + s->slice.width == s->img->width, s); + s->slice.x + s->slice.width == s->image.width, s); } /* If there is no mask, the background won't be seen, @@ -3944,7 +3938,7 @@ Function modeled after x_draw_glyph_string_box (). Do this for all images, getting transparency right is not reliable. */ if (s->hl == DRAW_CURSOR) { - int thickness = abs (s->img->relief); + int thickness = abs (s->image.relief); if (thickness == 0) thickness = 1; ns_draw_box (br, thickness, FRAME_CURSOR_COLOR (s->f), 1, 1); } diff --git a/src/w32term.c b/src/w32term.c index 8d189ae32c..eb231b57f7 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -1850,7 +1850,7 @@ static void x_draw_image_foreground (struct glyph_string *s) { int x = s->x; - int y = s->ybase - image_ascent (s->img, s->face, &s->slice); + int y = s->ybase - image_ascent (s->image, s->face, &s->slice); /* If first glyph of S has a left box line, start drawing it to the right of that line. */ @@ -1943,7 +1943,7 @@ x_draw_image_relief (struct glyph_string *s) int extra_x, extra_y; RECT r; int x = s->x; - int y = s->ybase - image_ascent (s->img, s->face, &s->slice); + int y = s->ybase - image_ascent (s->image, s->face, &s->slice); /* If first glyph of S has a left box line, start drawing it to the right of that line. */ @@ -2015,7 +2015,7 @@ w32_draw_image_foreground_1 (struct glyph_string *s, HBITMAP pixmap) HDC hdc = CreateCompatibleDC (s->hdc); HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap); int x = 0; - int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice); + int y = s->ybase - s->y - image_ascent (s->image, s->face, &s->slice); /* If first glyph of S has a left box line, start drawing it to the right of that line. */ diff --git a/src/xdisp.c b/src/xdisp.c index 4201bdc4a7..6d17f64b7d 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -5197,7 +5197,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, it->area = TEXT_AREA; it->what = IT_IMAGE; - it->image_id = -1; /* no image */ + it->image.image_id = -1; /* no image */ it->position = start_pos; it->object = NILP (object) ? it->w->contents : object; it->method = GET_FROM_IMAGE; @@ -5356,7 +5356,7 @@ handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object, else { it->what = IT_IMAGE; - it->image_id = lookup_image (it->f, value); + it->image = calc_image_spec (it->f, value); it->position = start_pos; it->object = NILP (object) ? it->w->contents : object; it->method = GET_FROM_IMAGE; @@ -6103,7 +6103,7 @@ push_it (struct it *it, struct text_pos *position) { case GET_FROM_IMAGE: p->u.image.object = it->object; - p->u.image.image_id = it->image_id; + p->u.image.image = it->image; p->u.image.slice = it->slice; break; case GET_FROM_STRETCH: @@ -6209,7 +6209,7 @@ pop_it (struct it *it) switch (it->method) { case GET_FROM_IMAGE: - it->image_id = p->u.image.image_id; + it->image = p->u.image.image; it->object = p->u.image.object; it->slice = p->u.image.slice; break; @@ -19446,7 +19446,7 @@ dump_glyph (struct glyph_row *row, struct glyph *glyph, int area) ? '0' : '-'))), glyph->pixel_width, - (unsigned int) glyph->u.img_id, + (unsigned int) glyph->u.image.image_id, '.', glyph->face_id, glyph->left_box_line_p, @@ -20775,7 +20775,7 @@ push_prefix_prop (struct it *it, Lisp_Object prop) else if (IMAGEP (prop)) { it->what = IT_IMAGE; - it->image_id = lookup_image (it->f, prop); + it->image = calc_image_spec (it->f, prop); it->method = GET_FROM_IMAGE; } #endif /* HAVE_WINDOW_SYSTEM */ @@ -25596,12 +25596,8 @@ calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop, /* '(image PROPS...)': width or height of the specified image. */ if (FRAME_WINDOW_P (it->f) && valid_image_p (prop)) - { - ptrdiff_t id = lookup_image (it->f, prop); - struct image *img = IMAGE_FROM_ID (it->f, id); + return OK_PIXELS (width_p ? it->image.width : it->image.height); - return OK_PIXELS (width_p ? img->width : img->height); - } /* '(xwidget PROPS...)': dimensions of the specified xwidget. */ if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop)) { @@ -26104,7 +26100,8 @@ static void fill_image_glyph_string (struct glyph_string *s) { eassert (s->first_glyph->type == IMAGE_GLYPH); - s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id); + s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.image.image_id); + s->image = s->first_glyph->u.image; eassert (s->img); s->slice = s->first_glyph->slice.img; s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id); @@ -27247,7 +27244,7 @@ produce_image_glyph (struct it *it) /* Make sure X resources of the face is loaded. */ prepare_face_for_display (it->f, face); - if (it->image_id < 0) + if (it->image.image_id < 0) { /* Fringe bitmap. */ it->ascent = it->phys_ascent = 0; @@ -27257,60 +27254,60 @@ produce_image_glyph (struct it *it) return; } - img = IMAGE_FROM_ID (it->f, it->image_id); + img = IMAGE_FROM_ID (it->f, it->image.image_id); /* Make sure X resources of the image is loaded. */ prepare_image_for_display (it->f, img); slice.x = slice.y = 0; - slice.width = img->width; - slice.height = img->height; + slice.width = it->image.width; + slice.height = it->image.height; if (FIXNUMP (it->slice.x)) slice.x = XFIXNUM (it->slice.x); else if (FLOATP (it->slice.x)) - slice.x = XFLOAT_DATA (it->slice.x) * img->width; + slice.x = XFLOAT_DATA (it->slice.x) * it->image.width; if (FIXNUMP (it->slice.y)) slice.y = XFIXNUM (it->slice.y); else if (FLOATP (it->slice.y)) - slice.y = XFLOAT_DATA (it->slice.y) * img->height; + slice.y = XFLOAT_DATA (it->slice.y) * it->image.height; if (FIXNUMP (it->slice.width)) slice.width = XFIXNUM (it->slice.width); else if (FLOATP (it->slice.width)) - slice.width = XFLOAT_DATA (it->slice.width) * img->width; + slice.width = XFLOAT_DATA (it->slice.width) * it->image.width; if (FIXNUMP (it->slice.height)) slice.height = XFIXNUM (it->slice.height); else if (FLOATP (it->slice.height)) - slice.height = XFLOAT_DATA (it->slice.height) * img->height; + slice.height = XFLOAT_DATA (it->slice.height) * it->image.height; - if (slice.x >= img->width) - slice.x = img->width; - if (slice.y >= img->height) - slice.y = img->height; - if (slice.x + slice.width >= img->width) - slice.width = img->width - slice.x; - if (slice.y + slice.height > img->height) - slice.height = img->height - slice.y; + if (slice.x >= it->image.width) + slice.x = it->image.width; + if (slice.y >= it->image.height) + slice.y = it->image.height; + if (slice.x + slice.width >= it->image.width) + slice.width = it->image.width - slice.x; + if (slice.y + slice.height > it->image.height) + slice.height = it->image.height - slice.y; if (slice.width == 0 || slice.height == 0) return; - it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice); + it->ascent = it->phys_ascent = glyph_ascent = image_ascent (it->image, face, &slice); it->descent = slice.height - glyph_ascent; if (slice.y == 0) - it->descent += img->vmargin; - if (slice.y + slice.height == img->height) - it->descent += img->vmargin; + it->descent += it->image.vmargin; + if (slice.y + slice.height == it->image.height) + it->descent += it->image.vmargin; it->phys_descent = it->descent; it->pixel_width = slice.width; if (slice.x == 0) - it->pixel_width += img->hmargin; - if (slice.x + slice.width == img->width) - it->pixel_width += img->hmargin; + it->pixel_width += it->image.hmargin; + if (slice.x + slice.width == it->image.width) + it->pixel_width += it->image.hmargin; /* It's quite possible for images to have an ascent greater than their height, so don't get confused in that case. */ @@ -27325,13 +27322,13 @@ produce_image_glyph (struct it *it) { if (slice.y == 0) it->ascent += face->box_line_width; - if (slice.y + slice.height == img->height) + if (slice.y + slice.height == it->image.height) it->descent += face->box_line_width; } if (it->start_of_box_run_p && slice.x == 0) it->pixel_width += eabs (face->box_line_width); - if (it->end_of_box_run_p && slice.x + slice.width == img->width) + if (it->end_of_box_run_p && slice.x + slice.width == it->image.width) it->pixel_width += eabs (face->box_line_width); } @@ -27388,7 +27385,7 @@ produce_image_glyph (struct it *it) glyph->padding_p = false; glyph->glyph_not_available_p = false; glyph->face_id = it->face_id; - glyph->u.img_id = img->id; + glyph->u.image = it->image; glyph->slice.img = slice; glyph->font_type = FONT_TYPE_UNKNOWN; if (it->bidi_p) @@ -29326,15 +29323,15 @@ get_window_cursor_type (struct window *w, struct glyph *glyph, int *width, /* Using a block cursor on large images can be very annoying. So use a hollow cursor for "large" images. If image is not transparent (no mask), also use hollow cursor. */ - struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id); + struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.image.image_id); if (img != NULL && IMAGEP (img->spec)) { /* Arbitrarily, interpret "Large" as >32x32 and >NxN where N = size of default frame font size. This should cover most of the "tiny" icons people may use. */ if (!img->mask - || img->width > max (32, WINDOW_FRAME_COLUMN_WIDTH (w)) - || img->height > max (32, WINDOW_FRAME_LINE_HEIGHT (w))) + || glyph->u.image.width > max (32, WINDOW_FRAME_COLUMN_WIDTH (w)) + || glyph->u.image.height > max (32, WINDOW_FRAME_LINE_HEIGHT (w))) cursor_type = HOLLOW_BOX_CURSOR; } } @@ -31482,11 +31479,10 @@ note_mouse_highlight (struct frame *f, int x, int y) /* Look for :pointer property on image. */ if (glyph != NULL && glyph->type == IMAGE_GLYPH) { - struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id); - if (img != NULL && IMAGEP (img->spec)) + if (IMAGEP (glyph->object)) { Lisp_Object image_map, hotspot; - if ((image_map = Fplist_get (XCDR (img->spec), QCmap), + if ((image_map = Fplist_get (XCDR (glyph->object), QCmap), !NILP (image_map)) && (hotspot = find_hot_spot (image_map, glyph->slice.img.x + dx, @@ -31517,7 +31513,7 @@ note_mouse_highlight (struct frame *f, int x, int y) } } if (NILP (pointer)) - pointer = Fplist_get (XCDR (img->spec), QCpointer); + pointer = Fplist_get (XCDR (glyph->object), QCpointer); } } #endif /* HAVE_WINDOW_SYSTEM */ diff --git a/src/xterm.c b/src/xterm.c index 943f4c3b3d..6a94916d4e 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -38,11 +38,6 @@ along with GNU Emacs. If not, see . */ #include #endif -/* Using Xft implies that XRender is available. */ -#ifdef HAVE_XFT -#include -#endif - #ifdef HAVE_XDBE #include #endif @@ -136,6 +131,10 @@ along with GNU Emacs. If not, see . */ #include #endif +#ifdef HAVE_XRENDER +#include +#endif + /* Default to using XIM if available. */ #ifdef USE_XIM bool use_xim = true; @@ -2976,13 +2975,60 @@ x_draw_glyph_string_box (struct glyph_string *s) } +static void +x_composite_image (struct glyph_string *s, Pixmap dest, + int srcX, int srcY, int dstX, int dstY, + int width, int height) +{ +#ifdef HAVE_XRENDER + Picture source, destination; + XRenderPictFormat *default_format, *source_format; + XRenderPictureAttributes source_attr, dest_attr; + double xscale = (double) s->img->width/s->image.width; + double yscale = (double) s->img->height/s->image.height; + + XTransform tmat = {{{XDoubleToFixed (xscale), XDoubleToFixed (0), XDoubleToFixed (0)}, + {XDoubleToFixed (0), XDoubleToFixed (yscale), XDoubleToFixed (0)}, + {XDoubleToFixed (0), XDoubleToFixed (0), XDoubleToFixed (1)}}}; + + default_format = XRenderFindVisualFormat (s->display, DefaultVisual (s->display, 0)); + /* FIXME: I doubt this is always correct. There must be a way of + working out the format of the pixmap. */ + source_format = XRenderFindStandardFormat (s->display, PictStandardRGB24); + + source = XRenderCreatePicture (s->display, s->img->pixmap, source_format, + 0, &source_attr); + destination = XRenderCreatePicture (s->display, dest, default_format, 0, &dest_attr); + + XRenderSetPictureFilter (s->display, source, FilterBest, 0, 0); + XRenderSetPictureTransform (s->display, source, &tmat); + + /* FIXME: XRenderComposite supports masks, so can we just use the + mask in s->img->mask here? */ + XRenderComposite (s->display, PictOpOver, source, None, destination, + srcX*xscale, srcY*yscale, + 0, 0, + dstX, dstY, + width, height); + + XRenderFreePicture (s->display, source); + XRenderFreePicture (s->display, destination); +#else + XCopyArea (s->display, s->img->pixmap, + dest, s->gc, + srcX, srcY + width, height, dstX, dstY); +#endif +} + + /* Draw foreground of image glyph string S. */ static void x_draw_image_foreground (struct glyph_string *s) { int x = s->x; - int y = s->ybase - image_ascent (s->img, s->face, &s->slice); + int y = s->ybase - image_ascent (s->image, s->face, &s->slice); /* If first glyph of S has a left box line, start drawing it to the right of that line. */ @@ -2994,9 +3040,9 @@ x_draw_image_foreground (struct glyph_string *s) /* If there is a margin around the image, adjust x- and y-position by that margin. */ if (s->slice.x == 0) - x += s->img->hmargin; + x += s->image.hmargin; if (s->slice.y == 0) - y += s->img->vmargin; + y += s->image.vmargin; if (s->img->pixmap) { @@ -3024,10 +3070,8 @@ x_draw_image_foreground (struct glyph_string *s) image_rect.width = s->slice.width; image_rect.height = s->slice.height; if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) - XCopyArea (s->display, s->img->pixmap, - FRAME_X_DRAWABLE (s->f), s->gc, - s->slice.x + r.x - x, s->slice.y + r.y - y, - r.width, r.height, r.x, r.y); + x_composite_image (s, FRAME_X_DRAWABLE (s->f), s->slice.x + r.x - x, s->slice.y + r.y - y, + r.x, r.y, r.width, r.height); } else { @@ -3039,10 +3083,8 @@ x_draw_image_foreground (struct glyph_string *s) image_rect.width = s->slice.width; image_rect.height = s->slice.height; if (x_intersect_rectangles (&clip_rect, &image_rect, &r)) - XCopyArea (s->display, s->img->pixmap, - FRAME_X_DRAWABLE (s->f), s->gc, - s->slice.x + r.x - x, s->slice.y + r.y - y, - r.width, r.height, r.x, r.y); + x_composite_image (s, FRAME_X_DRAWABLE (s->f), s->slice.x + r.x - x, s->slice.y + r.y - y, + r.x, r.y, r.width, r.height); /* When the image has a mask, we can expect that at least part of a mouse highlight or a block cursor will @@ -3052,7 +3094,7 @@ x_draw_image_foreground (struct glyph_string *s) nothing here for mouse-face. */ if (s->hl == DRAW_CURSOR) { - int relief = eabs (s->img->relief); + int relief = eabs (s->image.relief); x_draw_rectangle (s->f, s->gc, x - relief, y - relief, s->slice.width + relief*2 - 1, @@ -3077,7 +3119,7 @@ x_draw_image_relief (struct glyph_string *s) int extra_x, extra_y; XRectangle r; int x = s->x; - int y = s->ybase - image_ascent (s->img, s->face, &s->slice); + int y = s->ybase - image_ascent (s->image, s->face, &s->slice); /* If first glyph of S has a left box line, start drawing it to the right of that line. */ @@ -3089,9 +3131,9 @@ x_draw_image_relief (struct glyph_string *s) /* If there is a margin around the image, adjust x- and y-position by that margin. */ if (s->slice.x == 0) - x += s->img->hmargin; + x += s->image.hmargin; if (s->slice.y == 0) - y += s->img->vmargin; + y += s->image.vmargin; if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED) @@ -3101,8 +3143,8 @@ x_draw_image_relief (struct glyph_string *s) } else { - thick = eabs (s->img->relief); - raised_p = s->img->relief > 0; + thick = eabs (s->image.relief); + raised_p = s->image.relief > 0; } x1 = x + s->slice.width - 1; @@ -3128,9 +3170,9 @@ x_draw_image_relief (struct glyph_string *s) x -= thick + extra_x, left_p = true; if (s->slice.y == 0) y -= thick + extra_y, top_p = true; - if (s->slice.x + s->slice.width == s->img->width) + if (s->slice.x + s->slice.width == s->image.width) x1 += thick + extra_x, right_p = true; - if (s->slice.y + s->slice.height == s->img->height) + if (s->slice.y + s->slice.height == s->image.height) y1 += thick + extra_y, bot_p = true; x_setup_relief_colors (s); @@ -3146,7 +3188,7 @@ static void x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap) { int x = 0; - int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice); + int y = s->ybase - s->y - image_ascent (s->image, s->face, &s->slice); /* If first glyph of S has a left box line, start drawing it to the right of that line. */ @@ -3158,9 +3200,9 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap) /* If there is a margin around the image, adjust x- and y-position by that margin. */ if (s->slice.x == 0) - x += s->img->hmargin; + x += s->image.hmargin; if (s->slice.y == 0) - y += s->img->vmargin; + y += s->image.vmargin; if (s->img->pixmap) { @@ -3200,7 +3242,7 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap) nothing here for mouse-face. */ if (s->hl == DRAW_CURSOR) { - int r = eabs (s->img->relief); + int r = eabs (s->image.relief); x_draw_rectangle (s->f, s->gc, x - r, y - r, s->slice.width + r*2 - 1, s->slice.height + r*2 - 1); @@ -3265,8 +3307,8 @@ x_draw_image_glyph_string (struct glyph_string *s) flickering. */ s->stippled_p = s->face->stipple != 0; if (height > s->slice.height - || s->img->hmargin - || s->img->vmargin + || s->image.hmargin + || s->image.vmargin || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width) @@ -3338,8 +3380,8 @@ x_draw_image_glyph_string (struct glyph_string *s) { cairo_t *cr = x_begin_cr_clip (s->f, s->gc); - int x = s->x + s->img->hmargin; - int y = s->y + s->img->vmargin; + int x = s->x + s->image.hmargin; + int y = s->y + s->image.vmargin; int width = s->background_width; cairo_set_source_surface (cr, s->img->cr_data, @@ -3363,7 +3405,7 @@ x_draw_image_glyph_string (struct glyph_string *s) x_draw_image_foreground (s); /* If we must draw a relief around the image, do it. */ - if (s->img->relief + if (s->image.relief || s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN) x_draw_image_relief (s); -- 2.19.1