[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Add native image scaling
From: |
Alan Third |
Subject: |
[PATCH] Add native image scaling |
Date: |
Tue, 1 Jan 2019 21:47:19 +0000 |
User-agent: |
Mutt/1.10.1 (2018-07-13) |
* 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): Allow resizing if
native scaling is available.
* src/dispextern.h: Add XRender and image scaling stuff.
(struct image): Add XRender Pictures.
* src/image.c (x_create_bitmap_mask):
(image_create_x_image_and_pixmap): Handle XRender Picture.
(scale_image_size):
(compute_image_size): Make available when any form of scaling is
enabled.
(x_set_image_size): New function.
(lookup_image): Set image size.
(x_create_x_image_and_pixmap): Create XRender Picture when necessary.
(x_put_x_image): Handle the case where desired size != actual size.
(free_image): Free XRender Pictures.
(Fimage_scaling_p): New function.
(syms_of_image): Add image-scaling-p.
* src/nsimage.m (ns_load_image): Remove NS specific resizing.
([EmacsImage setSizeFromSpec:]): Remove method.
(ns_image_set_size): New function.
* src/nsterm.m (ns_draw_fringe_bitmap): Cocoa and GNUstep both have
the same compositing functions, so remove unnecessary difference.
* src/xterm.c (x_composite_image): New function.
(x_draw_image_foreground): Use new x_composite_image function.
---
This is a completely rewritten version that doesn't do anything
different with the image cache. I think this is pretty complete as it
is, excepting Windows support. I don't know how to add Windows support
to match the way it's done in NS and X, however if we can't resize the
images up-front, it should be possible to add some size info to the
image struct and do the resize on display.
I'm still unsure about image.el calling image-flush on every image
resize, but I have to assume it's in there for a reason.
configure.ac | 14 ++-
etc/NEWS | 6 +
lisp/image.el | 4 +-
src/Makefile.in | 3 +-
src/dispextern.h | 13 ++
src/image.c | 314 ++++++++++++++++++++++++++++++++---------------
src/nsimage.m | 68 +---------
src/nsterm.h | 2 +-
src/nsterm.m | 8 --
src/xterm.c | 58 +++++++--
10 files changed, 298 insertions(+), 192 deletions(-)
diff --git a/configure.ac b/configure.ac
index 91fa417308..0c59fe0619 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/etc/NEWS b/etc/NEWS
index 75e2c1bf98..69e14773a7 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1442,6 +1442,12 @@ that is non-nil, it will look for a file name handler
for the current
buffer's 'default-directory' and invoke that file name handler to make
the process. That way 'make-process' can start remote processes.
++++
+** Emacs now supports resizing images without ImageMagick on X window
+systems where the XRender extension is available, and on the NS port.
+The new function 'image-scaling-p' can be used to test whether any
+given frame supports resizing.
+
* Changes in Emacs 27.1 on Non-Free Operating Systems
diff --git a/lisp/image.el b/lisp/image.el
index 5727d8fbce..2e84e47b5c 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -982,8 +982,8 @@ image--get-image
image))
(defun image--get-imagemagick-and-warn ()
- (unless (or (fboundp 'imagemagick-types) (featurep 'ns))
- (error "Cannot rescale images without ImageMagick support"))
+ (unless (or (fboundp 'imagemagick-types) (image-scaling-p))
+ (error "Cannot rescale images on this terminal"))
(let ((image (image--get-image)))
(image-flush image)
(when (fboundp 'imagemagick-types)
diff --git a/src/Makefile.in b/src/Makefile.in
index e9831e9299..f409ed4db2 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 5774e3e951..b064875ac4 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -31,6 +31,9 @@ along with GNU Emacs. If not, see
<https://www.gnu.org/licenses/>. */
#include <X11/Intrinsic.h>
#endif /* USE_X_TOOLKIT */
+#ifdef HAVE_XRENDER
+#include <X11/extensions/Xrender.h>
+#endif
#else /* !HAVE_X_WINDOWS */
/* X-related stuff used by non-X gui code. */
@@ -2935,6 +2938,11 @@ struct redisplay_interface
#ifdef HAVE_WINDOW_SYSTEM
+#if defined (HAVE_X_WINDOWS) && defined (HAVE_XRENDER) \
+ || defined (HAVE_NS)
+#define HAVE_NATIVE_SCALING
+#endif
+
/* Structure describing an image. Specific image formats like XBM are
converted into this form, so that display only has to deal with
this type of image. */
@@ -2958,6 +2966,11 @@ struct image
and the latter is outdated. NULL means the X image has been
synchronized to Pixmap. */
XImagePtr ximg, mask_img;
+
+#ifdef HAVE_NATIVE_SCALING
+ /* Picture versions of pixmap and mask for compositing. */
+ Picture picture, mask_picture;
+#endif
#endif
/* Colors allocated for this image, if any. Allocated via xmalloc. */
diff --git a/src/image.c b/src/image.c
index 87e0c071ee..9c78755bbc 100644
--- a/src/image.c
+++ b/src/image.c
@@ -408,8 +408,13 @@ x_destroy_all_bitmaps (Display_Info *dpyinfo)
dpyinfo->bitmaps_last = 0;
}
+#ifdef HAVE_XRENDER
+static bool x_create_x_image_and_pixmap (struct frame *, int, int, int,
+ XImagePtr *, Pixmap *, Picture *);
+#else
static bool x_create_x_image_and_pixmap (struct frame *, int, int, int,
XImagePtr *, Pixmap *);
+#endif
static void x_destroy_x_image (XImagePtr ximg);
#ifdef HAVE_NTGUI
@@ -472,7 +477,11 @@ x_create_bitmap_mask (struct frame *f, ptrdiff_t id)
return;
}
- result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask);
+ result = x_create_x_image_and_pixmap (f, width, height, 1, &mask_img, &mask
+#ifdef HAVE_XRENDER
+ , NULL
+#endif
+ );
unblock_input ();
if (!result)
@@ -1011,6 +1020,13 @@ free_image (struct frame *f, struct image *img)
c->images[img->id] = NULL;
+#ifdef HAVE_XRENDER
+ if (img->picture)
+ XRenderFreePicture (FRAME_X_DISPLAY (f), img->picture);
+ if (img->mask_picture)
+ XRenderFreePicture (FRAME_X_DISPLAY (f), img->mask_picture);
+#endif
+
/* Windows NT redefines 'free', but in this file, we need to
avoid the redefinition. */
#ifdef WINDOWSNT
@@ -1747,6 +1763,147 @@ postprocess_image (struct frame *f, struct image *img)
}
}
+#if defined (HAVE_IMAGEMAGICK) || defined (HAVE_NATIVE_SCALING)
+/* 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;
+}
+
+#ifdef HAVE_NATIVE_SCALING
+static void
+x_set_image_size (struct frame *f, struct image *img)
+{
+#ifdef HAVE_IMAGEMAGICK
+ /* ImageMagick images are already the correct size. */
+ if (!imagemagick_image_p (img->spec))
+#endif
+ {
+ int width, height;
+
+ compute_image_size (img->width, img->height, img->spec, &width, &height);
+
+#ifdef HAVE_NS
+ ns_image_set_size (img->pixmap, width, height);
+ img->width = width;
+ img->height = height;
+#endif
+
+#ifdef HAVE_XRENDER
+ if (img->picture)
+ {
+ double xscale = (double) img->width/width;
+ double yscale = (double) img->height/height;
+
+ XTransform tmat = {{{XDoubleToFixed (xscale), XDoubleToFixed (0),
XDoubleToFixed (0)},
+ {XDoubleToFixed (0), XDoubleToFixed (yscale),
XDoubleToFixed (0)},
+ {XDoubleToFixed (0), XDoubleToFixed (0),
XDoubleToFixed (1)}}};
+
+ XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture,
FilterBest, 0, 0);
+ XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->picture, &tmat);
+
+ img->width = width;
+ img->height = height;
+ }
+#endif
+ }
+}
+#endif
+#endif /* HAVE_IMAGEMAGICK || HAVE_XRENDER || HAVE_NS */
+
/* Return the id of image with Lisp specification SPEC on frame F.
SPEC must be a valid Lisp image specification (see valid_image_p). */
@@ -1802,6 +1959,9 @@ lookup_image (struct frame *f, Lisp_Object spec)
`:background COLOR'. */
Lisp_Object ascent, margin, relief, bg;
int relief_bound;
+#ifdef HAVE_NATIVE_SCALING
+ x_set_image_size (f, img);
+#endif
ascent = image_spec_value (spec, QCascent, NULL);
if (FIXNUMP (ascent))
@@ -1975,13 +2135,21 @@ x_check_image_size (XImagePtr ximg, int width, int
height)
should indicate the bit depth of the image. */
static bool
+#ifdef HAVE_XRENDER
+x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
+ XImagePtr *ximg, Pixmap *pixmap, Picture *picture)
+#else
x_create_x_image_and_pixmap (struct frame *f, int width, int height, int depth,
XImagePtr *ximg, Pixmap *pixmap)
+#endif
{
#ifdef HAVE_X_WINDOWS
Display *display = FRAME_X_DISPLAY (f);
Drawable drawable = FRAME_X_DRAWABLE (f);
Screen *screen = FRAME_X_SCREEN (f);
+#ifdef HAVE_XRENDER
+ int event_basep, error_basep;
+#endif
eassert (input_blocked_p ());
@@ -2018,6 +2186,21 @@ x_create_x_image_and_pixmap (struct frame *f, int width,
int height, int depth,
return 0;
}
+#ifdef HAVE_XRENDER
+ if (picture && XRenderQueryExtension (display, &event_basep, &error_basep))
+ {
+ XRenderPictFormat *format;
+ XRenderPictureAttributes attr;
+
+ /* FIXME: Do we need to handle all possible bit depths? */
+ format = XRenderFindStandardFormat (display,
+ depth > 24 ? PictStandardARGB32
+ : depth > 8 ? PictStandardRGB24
+ : PictStandardA8);
+ *picture = XRenderCreatePicture (display, *pixmap, format, 0, &attr);
+ }
+#endif
+
return 1;
#endif /* HAVE_X_WINDOWS */
@@ -2163,7 +2346,8 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap
pixmap, int width, int he
eassert (input_blocked_p ());
gc = XCreateGC (FRAME_X_DISPLAY (f), pixmap, 0, NULL);
- XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0, width, height);
+ XPutImage (FRAME_X_DISPLAY (f), pixmap, gc, ximg, 0, 0, 0, 0,
+ ximg->width, ximg->height);
XFreeGC (FRAME_X_DISPLAY (f), gc);
#endif /* HAVE_X_WINDOWS */
@@ -2192,7 +2376,11 @@ image_create_x_image_and_pixmap (struct frame *f, struct
image *img,
eassert ((!mask_p ? img->pixmap : img->mask) == NO_PIXMAP);
return x_create_x_image_and_pixmap (f, width, height, depth, ximg,
- !mask_p ? &img->pixmap : &img->mask);
+ !mask_p ? &img->pixmap : &img->mask
+#ifdef HAVE_XRENDER
+ , !mask_p ? &img->picture :
&img->mask_picture
+#endif
+ );
}
/* Put X image XIMG into image IMG on frame F, as a mask if and only
@@ -8101,105 +8289,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 *);
@@ -9816,6 +9905,25 @@ DEFUN ("lookup-image", Flookup_image, Slookup_image, 1,
1, 0,
Initialization
***********************************************************************/
+DEFUN ("image-scaling-p", Fimage_scaling_p, Simage_scaling_p, 0, 1, 0,
+ doc: /* Test whether FRAME supports resizing images.
+Return t if FRAME supports native scaling, nil otherwise. */)
+ (Lisp_Object frame)
+{
+#ifdef HAVE_NS
+ return Qt;
+#elif defined (HAVE_X_WINDOWS) && defined (HAVE_XRENDER)
+ int event_basep, error_basep;
+
+ if (XRenderQueryExtension
+ (FRAME_X_DISPLAY (decode_window_system_frame (frame)),
+ &event_basep, &error_basep))
+ return Qt;
+#endif
+
+ return Qnil;
+}
+
DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 1, 1, 0,
doc: /* Initialize image library implementing image type TYPE.
Return non-nil if TYPE is a supported image type.
@@ -10058,6 +10166,8 @@ non-numeric, there is no explicit limit on the size of
images. */);
defsubr (&Slookup_image);
#endif
+ defsubr (&Simage_scaling_p);
+
DEFVAR_BOOL ("cross-disabled-images", cross_disabled_images,
doc: /* Non-nil means always draw a cross over disabled images.
Disabled images are those having a `:conversion disabled' property.
diff --git a/src/nsimage.m b/src/nsimage.m
index 7879c5891d..f16910de08 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;
@@ -151,6 +149,12 @@ Updated by Christian Limpach (address@hidden)
return [(id)img size].height;
}
+void
+ns_image_set_size (void *img, int width, int height)
+{
+ [(EmacsImage *)img setSize:NSMakeSize (width, height)];
+}
+
unsigned long
ns_get_pixel (void *img, int x, int y)
{
@@ -524,66 +528,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 089cbccbf0..78ce608554 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
@@ -1197,6 +1196,7 @@ extern bool ns_load_image (struct frame *f, struct image
*img,
Lisp_Object spec_file, Lisp_Object spec_data);
extern int ns_image_width (void *img);
extern int ns_image_height (void *img);
+extern void ns_image_set_size (void *img, int width, int height);
extern unsigned long ns_get_pixel (void *img, int x, int y);
extern void ns_put_pixel (void *img, int x, int y, unsigned long argb);
extern void ns_set_alpha (void *img, int x, int y, unsigned char a);
diff --git a/src/nsterm.m b/src/nsterm.m
index 016c044760..cbb2d2a5ce 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);
}
diff --git a/src/xterm.c b/src/xterm.c
index e9cebcebba..fbbf61d320 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -38,11 +38,6 @@ along with GNU Emacs. If not, see
<https://www.gnu.org/licenses/>. */
#include <X11/extensions/Xfixes.h>
#endif
-/* Using Xft implies that XRender is available. */
-#ifdef HAVE_XFT
-#include <X11/extensions/Xrender.h>
-#endif
-
#ifdef HAVE_XDBE
#include <X11/extensions/Xdbe.h>
#endif
@@ -2976,6 +2971,46 @@ 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
+ if (s->img->picture)
+ {
+ Picture destination;
+ XRenderPictFormat *default_format;
+ XRenderPictureAttributes attr;
+
+ /* FIXME: Should we do this each time or would it make sense to
+ store destination in the frame struct? */
+ default_format = XRenderFindVisualFormat (s->display,
+ DefaultVisual (s->display, 0));
+ destination = XRenderCreatePicture (s->display, dest,
+ default_format, 0, &attr);
+
+ /* FIXME: It may make sense to use PictOpSrc instead of
+ PictOpOver, as I don't know if we care about alpha values too
+ much here. */
+ XRenderComposite (s->display, PictOpOver,
+ s->img->picture, s->img->mask_picture, destination,
+ srcX, srcY,
+ srcX, srcY,
+ dstX, dstY,
+ width, height);
+
+ XRenderFreePicture (s->display, destination);
+ }
+ else
+#endif
+ XCopyArea (s->display, s->img->pixmap,
+ dest, s->gc,
+ srcX, srcY,
+ width, height, dstX, dstY);
+}
+
+
/* Draw foreground of image glyph string S. */
static void
@@ -3007,6 +3042,7 @@ x_draw_image_foreground (struct glyph_string *s)
trust on the shape extension to be available
(XShapeCombineRegion). So, compute the rectangle to draw
manually. */
+ /* FIXME: Do we need to do this when using XRender compositing? */
unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
| GCFunction);
XGCValues xgcv;
@@ -3024,10 +3060,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 +3073,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
--
2.19.1
--
Alan Third
- [PATCH] Add native image scaling,
Alan Third <=
- Re: [PATCH] Add native image scaling, Eli Zaretskii, 2019/01/02
- [PATCH v2] Add native image scaling (bug#33587), Alan Third, 2019/01/02
- Re: [PATCH v2] Add native image scaling (bug#33587), Eli Zaretskii, 2019/01/04
- Re: [PATCH v2] Add native image scaling (bug#33587), Alan Third, 2019/01/04
- Re: [PATCH v2] Add native image scaling (bug#33587), Eli Zaretskii, 2019/01/04
- Re: [PATCH v2] Add native image scaling (bug#33587), Alan Third, 2019/01/04
- Re: [PATCH v2] Add native image scaling (bug#33587), Alan Third, 2019/01/10
- Re: [PATCH v2] Add native image scaling (bug#33587), Eli Zaretskii, 2019/01/10
- Re: [PATCH v2] Add native image scaling (bug#33587), Paul Eggert, 2019/01/10
- Re: [PATCH v2] Add native image scaling (bug#33587), Eli Zaretskii, 2019/01/06