unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Native image rotation
@ 2019-02-24 11:30 Alan Third
  2019-02-24 16:14 ` Eli Zaretskii
  0 siblings, 1 reply; 30+ messages in thread
From: Alan Third @ 2019-02-24 11:30 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 445 bytes --]

I’ve attached a couple of patches. The second renames image scaling to
image transforms, as it covers more than just scaling.

It should be trivial to add cropping now. I can’t think of anything
else we might want to support.

Again I’ve not handled Windows, but hopefully it’s quite
straight‐forward.

The image rotation code is very explicit in what it’s doing and could
be optimized, but I’m not sure it matters.
-- 
Alan Third

[-- Attachment #2: 0001-Add-native-image-rotation.patch --]
[-- Type: text/plain, Size: 17135 bytes --]

From 1b1dbf1d77f40f09756c4d677dfdc4bf3e44952d Mon Sep 17 00:00:00 2001
From: Alan Third <alan@idiocy.org>
Date: Sat, 23 Feb 2019 20:56:48 +0000
Subject: [PATCH 1/2] Add native image rotation

* src/dispextern.h (INIT_MATRIX, COPY_MATRIX, MULT_MATRICES): New
macros for matrix manipulation.
* src/image.c (x_set_image_rotation):
(x_set_transform): New functions.
(x_set_image_size): Use transform matrix for resizing under X and NS.
(lookup_image): Use the new transform functions.
* src/nsimage.m (ns_load_image): Remove rotation code.
(ns_image_set_transform): New function.
([EmacsImage dealloc]): Release the saved transform.
([EmacsImage rotate:]): Remove unneeded method.
([EmacsImage setTransform:]): New method.
* src/nsterm.h (EmacsImage): Add transform property and update method
definitions.
* src/nsterm.m (ns_dumpglyphs_image): Use the transform to draw the
image correctly.
* src/xterm.c (x_composite_image): Clear under an image before
compositing it.
* doc/lispref/display.texi (Image Descriptors): Add :rotation.
(ImageMagick Images): Remove :rotation.
---
 doc/lispref/display.texi |   6 +-
 etc/NEWS                 |   2 +-
 src/dispextern.h         |  18 +++++
 src/image.c              | 149 +++++++++++++++++++++++++++++++++------
 src/nsimage.m            |  64 +++++------------
 src/nsterm.h             |   5 +-
 src/nsterm.m             |  41 +++++++----
 src/xterm.c              |   5 ++
 8 files changed, 204 insertions(+), 86 deletions(-)

diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index 95379b342b..b0f1fd2676 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -5157,6 +5157,9 @@ Image Descriptors
 specified, the height/width will be adjusted by the specified scaling
 factor.
 
+@item :rotation @var{angle}
+Specifies a rotation angle in degrees.
+
 @item :index @var{frame}
 @xref{Multi-Frame Images}.
 
@@ -5450,9 +5453,6 @@ ImageMagick Images
 image data, as found in @code{image-format-suffixes}.  This is used
 when the image does not have an associated file name, to provide a
 hint to ImageMagick to help it detect the image type.
-
-@item :rotation @var{angle}
-Specifies a rotation angle in degrees.
 @end table
 
 @node SVG Images
diff --git a/etc/NEWS b/etc/NEWS
index 0cafbaae96..3a50a51637 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1569,7 +1569,7 @@ 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 (scaling) of images without ImageMagick.
+** Emacs now supports resizing and rotating images without ImageMagick.
 All modern systems are supported by this feature.  (On GNU and Unix
 systems, the XRender extension to X11 is required for this to be
 available; the configure script will test for it and, if found, enable
diff --git a/src/dispextern.h b/src/dispextern.h
index 894753669d..d45bc03d09 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2940,6 +2940,24 @@ struct redisplay_interface
 
 # if defined HAVE_XRENDER || defined HAVE_NS || defined HAVE_NTGUI
 #  define HAVE_NATIVE_SCALING
+
+#  define INIT_MATRIX(m)                          \
+  for (int i = 0 ; i < 3 ; i++)                   \
+    for (int j = 0 ; j < 3 ; j++)                 \
+      m[i][j] = (i == j) ? 1 : 0;
+
+#  define COPY_MATRIX(a, b)                       \
+  for (int i = 0 ; i < 3 ; i++)                   \
+    for (int j = 0 ; j < 3 ; j++)                 \
+      b[i][j] = a[i][j];
+
+#  define MULT_MATRICES(a, b, result)             \
+  for (int i = 0 ; i < 3 ; i++)                   \
+    for (int j = 0 ; j < 3 ; j++) {               \
+      double sum = 0;                             \
+      for (int k = 0 ; k < 3 ; k++)               \
+        sum += a[k][j] * b[i][k];                 \
+      result[i][j] = sum;}
 # endif
 
 /* Structure describing an image.  Specific image formats like XBM are
diff --git a/src/image.c b/src/image.c
index 642bf67152..f48db69a24 100644
--- a/src/image.c
+++ b/src/image.c
@@ -56,6 +56,10 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <sys/types.h>
 #endif /* HAVE_SYS_TYPES_H */
 
+#ifdef HAVE_NATIVE_SCALING
+#include <math.h>
+#endif
+
 #ifdef HAVE_WINDOW_SYSTEM
 #include TERM_HEADER
 #endif /* HAVE_WINDOW_SYSTEM */
@@ -1863,43 +1867,111 @@ compute_image_size (size_t width, size_t height,
 #endif /* HAVE_IMAGEMAGICK || HAVE_NATIVE_SCALING */
 
 static void
-x_set_image_size (struct frame *f, struct image *img)
+x_set_image_rotation (struct image *img, double tm[3][3])
 {
 #ifdef HAVE_NATIVE_SCALING
 # ifdef HAVE_IMAGEMAGICK
-  /* ImageMagick images are already the correct size.  */
+  /* ImageMagick images are already rotated.  */
   if (EQ (image_spec_value (img->spec, QCtype, NULL), Qimagemagick))
     return;
 # endif
 
+# ifdef HAVE_XRENDER
+  if (!img->picture)
+    return;
+# endif
+
+  Lisp_Object value;
+  double rotation = 0;
+  double t[3][3], rot[3][3], tmp[3][3], tmp2[3][3];
   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);
+  value = image_spec_value (img->spec, QCrotation, NULL);
+  if (NUMBERP (value))
+    rotation = M_PI * XFLOATINT (value) / 180; /* radians */
+
+  if (rotation == 0)
+    return;
+
+  if (rotation > 3 * M_PI && rotation <= M_PI)
+    {
+      width = fabs (img->height * cos (rotation))
+        + fabs (img->width * sin (rotation));
+      height = fabs (img->height * sin (rotation))
+        + fabs (img->width * cos (rotation));
+    }
+  else
+    {
+      width = fabs (img->height * sin (rotation))
+        + fabs (img->width * cos (rotation));
+      height = fabs (img->height * cos (rotation))
+        + fabs (img->width * sin (rotation));
+    }
+
+  /* Translate so (0, 0) is in the centre of the image.  */
+  INIT_MATRIX (t);
+  t[2][0] = img->width/2;
+  t[2][1] = img->height/2;
+
+  MULT_MATRICES (tm, t, tmp);
+
+  /* Rotate.  */
+  INIT_MATRIX (rot);
+  rot[0][0] = cos (rotation);
+  rot[1][0] = sin (rotation);
+  rot[0][1] = - sin (rotation);
+  rot[1][1] = cos (rotation);
+
+  MULT_MATRICES (tmp, rot, tmp2);
+
+  /* Translate back.  */
+  INIT_MATRIX (t);
+  t[2][0] = - width/2;
+  t[2][1] = - height/2;
+
+  MULT_MATRICES (tmp2, t, tm);
+
   img->width = width;
   img->height = height;
+#endif
+}
+
+static void
+x_set_image_size (struct image *img, double tm[3][3])
+{
+#ifdef HAVE_NATIVE_SCALING
+# ifdef HAVE_IMAGEMAGICK
+  /* ImageMagick images are already the correct size.  */
+  if (EQ (image_spec_value (img->spec, QCtype, NULL), Qimagemagick))
+    return;
 # endif
 
 # ifdef HAVE_XRENDER
-  if (img->picture)
-    {
-      double xscale = img->width / (double) width;
-      double yscale = img->height / (double) height;
+  if (!img->picture)
+    return;
+# endif
 
-      XTransform tmat
-	= {{{XDoubleToFixed (xscale), XDoubleToFixed (0), XDoubleToFixed (0)},
-	    {XDoubleToFixed (0), XDoubleToFixed (yscale), XDoubleToFixed (0)},
-	    {XDoubleToFixed (0), XDoubleToFixed (0), XDoubleToFixed (1)}}};
+  double rm[3][3], tmp[3][3];
+  double xscale, yscale;
+  int width, height;
 
-      XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture, FilterBest,
-			       0, 0);
-      XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->picture, &tmat);
+  compute_image_size (img->width, img->height, img->spec, &width, &height);
 
-      img->width = width;
-      img->height = height;
-    }
+  xscale = img->width / (double) width;
+  yscale = img->height / (double) height;
+
+# if defined (HAVE_NS) || defined (HAVE_XRENDER)
+  INIT_MATRIX (rm);
+  rm[0][0] = xscale;
+  rm[1][1] = yscale;
+
+  MULT_MATRICES (tm, rm, tmp);
+  COPY_MATRIX (tmp, tm);
+
+  img->width = width;
+  img->height = height;
 # endif
+
 # ifdef HAVE_NTGUI
   /* Under HAVE_NTGUI, we will scale the image on the fly, when we
      draw it.  See w32term.c:x_draw_image_foreground.  */
@@ -1909,6 +1981,35 @@ x_set_image_size (struct frame *f, struct image *img)
 #endif
 }
 
+static void
+x_set_transform (struct frame *f, struct image *img, double matrix[3][3])
+{
+#ifdef HAVE_NATIVE_SCALING
+# if defined (HAVE_NS)
+  /* Under NS the transform is applied to the drawing surface at
+     drawing time, so store it for later.  */
+  ns_image_set_transform (img->pixmap, matrix);
+# elif defined (HAVE_XRENDER)
+  if (img->picture)
+    {
+      XTransform tmat
+	= {{{XDoubleToFixed (matrix[0][0]),
+             XDoubleToFixed (matrix[1][0]),
+             XDoubleToFixed (matrix[2][0])},
+	    {XDoubleToFixed (matrix[0][1]),
+             XDoubleToFixed (matrix[1][1]),
+             XDoubleToFixed (matrix[2][1])},
+	    {XDoubleToFixed (matrix[0][2]),
+             XDoubleToFixed (matrix[1][2]),
+             XDoubleToFixed (matrix[2][2])}}};
+
+      XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture, FilterBest,
+			       0, 0);
+      XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->picture, &tmat);
+    }
+# endif
+#endif
+}
 
 /* Return the id of image with Lisp specification SPEC on frame F.
    SPEC must be a valid Lisp image specification (see valid_image_p).  */
@@ -1964,7 +2065,15 @@ lookup_image (struct frame *f, Lisp_Object spec)
 	     `:background COLOR'.  */
 	  Lisp_Object ascent, margin, relief, bg;
 	  int relief_bound;
-          x_set_image_size (f, img);
+
+#ifdef HAVE_NATIVE_SCALING
+          double transform_matrix[3][3];
+
+          INIT_MATRIX (transform_matrix);
+          x_set_image_rotation (img, transform_matrix);
+          x_set_image_size (img, transform_matrix);
+          x_set_transform (f, img, transform_matrix);
+#endif
 
 	  ascent = image_spec_value (spec, QCascent, NULL);
 	  if (FIXNUMP (ascent))
diff --git a/src/nsimage.m b/src/nsimage.m
index f16910de08..3a5dd24185 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -76,9 +76,8 @@ Updated by Christian Limpach (chris@nice.ch)
 {
   EmacsImage *eImg = nil;
   NSSize size;
-  Lisp_Object lisp_index, lisp_rotation;
+  Lisp_Object lisp_index;
   unsigned int index;
-  double rotation;
 
   NSTRACE ("ns_load_image");
 
@@ -87,9 +86,6 @@ Updated by Christian Limpach (chris@nice.ch)
   lisp_index = Fplist_get (XCDR (img->spec), QCindex);
   index = FIXNUMP (lisp_index) ? XFIXNAT (lisp_index) : 0;
 
-  lisp_rotation = Fplist_get (XCDR (img->spec), QCrotation);
-  rotation = NUMBERP (lisp_rotation) ? XFLOATINT (lisp_rotation) : 0;
-
   if (STRINGP (spec_file))
     {
       eImg = [EmacsImage allocInitFromFile: spec_file];
@@ -119,13 +115,6 @@ Updated by Christian Limpach (chris@nice.ch)
 
   img->lisp_data = [eImg getMetadata];
 
-  if (rotation != 0)
-    {
-      EmacsImage *temp = [eImg rotate:rotation];
-      [eImg release];
-      eImg = temp;
-    }
-
   size = [eImg size];
   img->width = size.width;
   img->height = size.height;
@@ -155,6 +144,12 @@ Updated by Christian Limpach (chris@nice.ch)
   [(EmacsImage *)img setSize:NSMakeSize (width, height)];
 }
 
+void
+ns_image_set_transform (void *img, double m[3][3])
+{
+  [(EmacsImage *)img setTransform:m];
+}
+
 unsigned long
 ns_get_pixel (void *img, int x, int y)
 {
@@ -225,6 +220,7 @@ - (void)dealloc
 {
   [stippleMask release];
   [bmRep release];
+  [transform release];
   [super dealloc];
 }
 
@@ -528,42 +524,16 @@ - (BOOL)setFrame: (unsigned int) index
   return YES;
 }
 
-- (instancetype)rotate: (double)rotation
+- (void)setTransform: (double[3][3]) m
 {
-  EmacsImage *new_image;
-  NSPoint new_origin;
-  NSSize new_size, size = [self size];
-  NSRect rect = { NSZeroPoint, [self size] };
-
-  /* Create a bezier path of the outline of the image and do the
-   * rotation on it.  */
-  NSBezierPath *bounds_path = [NSBezierPath bezierPathWithRect:rect];
-  NSAffineTransform *transform = [NSAffineTransform transform];
-  [transform rotateByDegrees: rotation * -1];
-  [bounds_path transformUsingAffineTransform:transform];
-
-  /* Now we can find out how large the rotated image needs to be.  */
-  new_size = [bounds_path bounds].size;
-  new_image = [[EmacsImage alloc] initWithSize:new_size];
-
-  new_origin = NSMakePoint((new_size.width - size.width)/2,
-                           (new_size.height - size.height)/2);
-
-  [new_image lockFocus];
-
-  /* Create the final transform.  */
-  transform = [NSAffineTransform transform];
-  [transform translateXBy:new_size.width/2 yBy:new_size.height/2];
-  [transform rotateByDegrees: rotation * -1];
-  [transform translateXBy:-new_size.width/2 yBy:-new_size.height/2];
-
-  [transform concat];
-  [self drawAtPoint:new_origin fromRect:NSZeroRect
-          operation:NSCompositingOperationCopy fraction:1];
-
-  [new_image unlockFocus];
-
-  return new_image;
+  transform = [[NSAffineTransform transform] retain];
+  NSAffineTransformStruct tm
+    = { m[0][0], m[0][1], m[1][0], m[1][1], m[2][0], m[2][1]};
+  [transform setTransformStruct:tm];
+
+  /* Because the transform is applied to the drawing surface, and not
+     the image itself, we need to invert it.  */
+  [transform invert];
 }
 
 @end
diff --git a/src/nsterm.h b/src/nsterm.h
index 78ce608554..2541b672bb 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -632,6 +632,8 @@ typedef id instancetype;
   unsigned char *pixmapData[5]; /* shortcut to access pixel data */
   NSColor *stippleMask;
   unsigned long xbm_fg;
+@public
+  NSAffineTransform *transform;
 }
 + (instancetype)allocInitFromFile: (Lisp_Object)file;
 - (void)dealloc;
@@ -648,7 +650,7 @@ typedef id instancetype;
 - (NSColor *)stippleMask;
 - (Lisp_Object)getMetadata;
 - (BOOL)setFrame: (unsigned int) index;
-- (instancetype)rotate: (double)rotation;
+- (void)setTransform: (double[3][3]) m;
 @end
 
 
@@ -1197,6 +1199,7 @@ extern bool ns_load_image (struct frame *f, struct image *img,
 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 void ns_image_set_transform (void *img, double m[3][3]);
 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 2bf3e00786..3f227f525a 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -3868,21 +3868,34 @@ Function modeled after x_draw_glyph_string_box ().
   /* Draw the image... do we need to draw placeholder if img == nil?  */
   if (img != nil)
     {
-#ifdef NS_IMPL_COCOA
+      /* The idea here is that the clipped area is set in the normal
+         view coordinate system, then we transform the coordinate
+         system so that when we draw the image it is rotated, resized
+         or whatever as required.  This is kind of backwards, but
+         there's no way to apply the transform to the image without
+         creating a whole new bitmap.  */
       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);
-      [img drawInRect: dr
-             fromRect: ir
-             operation: NSCompositingOperationSourceOver
-              fraction: 1.0
-           respectFlipped: YES
-                hints: nil];
-#else
-      [img compositeToPoint: NSMakePoint (x, y + s->slice.height)
-                  operation: NSCompositingOperationSourceOver];
-#endif
+      NSRect ir = NSMakeRect (0, 0, [img size].width, [img size].height);
+
+      NSAffineTransform *setOrigin = [NSAffineTransform transform];
+
+      [[NSGraphicsContext currentContext] saveGraphicsState];
+
+      /* Because of the transforms it's far too difficult to work out
+         what portion of the original, untransformed, image will be
+         drawn, so the clipping area will ensure we draw only the
+         correct bit.  */
+      NSRectClip (dr);
+
+      [setOrigin translateXBy:x - s->slice.x yBy:y - s->slice.y];
+      [setOrigin concat];
+      [img->transform concat];
+
+      [img drawInRect:ir fromRect:ir
+            operation:NSCompositingOperationSourceOver
+             fraction:1.0 respectFlipped:YES hints:nil];
+
+      [[NSGraphicsContext currentContext] restoreGraphicsState];
     }
 
   if (s->hl == DRAW_CURSOR)
diff --git a/src/xterm.c b/src/xterm.c
index d8eb45a00c..a81efac5c8 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -2984,6 +2984,11 @@ x_composite_image (struct glyph_string *s, Pixmap dest,
       XRenderPictFormat *default_format;
       XRenderPictureAttributes attr;
 
+      /* A rotated image has no background in the "new" sections of
+         the image, so XRenderComposite makes them transparent with
+         PictOpOver.  Fill in the background before compositing.  */
+      x_clear_area (s->f, dstX, dstY, width, height);
+
       /* FIXME: Should we do this each time or would it make sense to
          store destination in the frame struct?  */
       default_format = XRenderFindVisualFormat (s->display,
-- 
2.20.1


[-- Attachment #3: 0002-Rename-image-scaling-to-image-transforms.patch --]
[-- Type: text/plain, Size: 7415 bytes --]

From c9345f094179372b0b83c2b6bafaf9276fd59b29 Mon Sep 17 00:00:00 2001
From: Alan Third <alan@idiocy.org>
Date: Sun, 24 Feb 2019 11:16:42 +0000
Subject: [PATCH 2/2] Rename image scaling to image transforms

* src/dispextern.h (HAVE_NATIVE_SCALING, HAVE_NATIVE_TRANSFORMS):
Rename and change all relevant locations.
* src/image.c (Fimage_scaling_p, Fimage_transforms_p): Rename and
update all callers.
---
 doc/lispref/display.texi | 15 ++++++++-------
 etc/NEWS                 |  4 ++--
 lisp/image.el            |  2 +-
 src/dispextern.h         |  4 ++--
 src/image.c              | 30 ++++++++++++++++--------------
 5 files changed, 29 insertions(+), 26 deletions(-)

diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi
index b0f1fd2676..801ab9595a 100644
--- a/doc/lispref/display.texi
+++ b/doc/lispref/display.texi
@@ -5302,14 +5302,15 @@ Image Descriptors
 (@pxref{Input Focus}).
 @end defun
 
-@defun image-scaling-p &optional frame
-This function returns @code{t} if @var{frame} supports image scaling.
-@var{frame} @code{nil} or omitted means to use the selected frame
-(@pxref{Input Focus}).
+@defun image-transforms-p &optional frame
+This function returns @code{t} if @var{frame} supports image scaling
+and rotation.  @var{frame} @code{nil} or omitted means to use the
+selected frame (@pxref{Input Focus}).
 
-If image scaling is not supported, @code{:width}, @code{:height},
-@code{:scale}, @code{:max-width} and @code{:max-height} will only be
-usable through ImageMagick, if available (@pxref{ImageMagick Images}).
+If image transforms are not supported, @code{:rotation},
+@code{:width}, @code{:height}, @code{:scale}, @code{:max-width} and
+@code{:max-height} will only be usable through ImageMagick, if
+available (@pxref{ImageMagick Images}).
 @end defun
 
 @node XBM Images
diff --git a/etc/NEWS b/etc/NEWS
index 3a50a51637..4cc0ccaf07 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1575,8 +1575,8 @@ systems, the XRender extension to X11 is required for this to be
 available; the configure script will test for it and, if found, enable
 scaling.)
 
-The new function 'image-scaling-p' can be used to test whether any
-given frame supports resizing.
+The new function 'image-transforms-p' can be used to test whether any
+given frame supports this capability.
 
 +++
 ** (locale-info 'paper) now returns the paper size on systems that support it.
diff --git a/lisp/image.el b/lisp/image.el
index 3aa3b0aa24..42e906b3ad 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -989,7 +989,7 @@ image--get-image
     image))
 
 (defun image--get-imagemagick-and-warn ()
-  (unless (or (fboundp 'imagemagick-types) (image-scaling-p))
+  (unless (or (fboundp 'imagemagick-types) (image-transforms-p))
     (error "Cannot rescale images on this terminal"))
   (let ((image (image--get-image)))
     (image-flush image)
diff --git a/src/dispextern.h b/src/dispextern.h
index d45bc03d09..0eb7776056 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2939,7 +2939,7 @@ struct redisplay_interface
 #ifdef HAVE_WINDOW_SYSTEM
 
 # if defined HAVE_XRENDER || defined HAVE_NS || defined HAVE_NTGUI
-#  define HAVE_NATIVE_SCALING
+#  define HAVE_NATIVE_TRANSFORMS
 
 #  define INIT_MATRIX(m)                          \
   for (int i = 0 ; i < 3 ; i++)                   \
@@ -2984,7 +2984,7 @@ struct image
      synchronized to Pixmap.  */
   XImagePtr ximg, mask_img;
 
-# ifdef HAVE_NATIVE_SCALING
+# ifdef HAVE_NATIVE_TRANSFORMS
   /* Picture versions of pixmap and mask for compositing.  */
   Picture picture, mask_picture;
 # endif
diff --git a/src/image.c b/src/image.c
index f48db69a24..dcc8cd06b6 100644
--- a/src/image.c
+++ b/src/image.c
@@ -56,7 +56,7 @@ along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.  */
 #include <sys/types.h>
 #endif /* HAVE_SYS_TYPES_H */
 
-#ifdef HAVE_NATIVE_SCALING
+#ifdef HAVE_NATIVE_TRANSFORMS
 #include <math.h>
 #endif
 
@@ -1765,7 +1765,7 @@ postprocess_image (struct frame *f, struct image *img)
     }
 }
 
-#if defined (HAVE_IMAGEMAGICK) || defined (HAVE_NATIVE_SCALING)
+#if defined (HAVE_IMAGEMAGICK) || defined (HAVE_NATIVE_TRANSFORMS)
 /* Scale an image size by returning SIZE / DIVISOR * MULTIPLIER,
    safely rounded and clipped to int range.  */
 
@@ -1864,12 +1864,12 @@ compute_image_size (size_t width, size_t height,
   *d_width = desired_width;
   *d_height = desired_height;
 }
-#endif /* HAVE_IMAGEMAGICK || HAVE_NATIVE_SCALING */
+#endif /* HAVE_IMAGEMAGICK || HAVE_NATIVE_TRANSFORMS */
 
 static void
 x_set_image_rotation (struct image *img, double tm[3][3])
 {
-#ifdef HAVE_NATIVE_SCALING
+#ifdef HAVE_NATIVE_TRANSFORMS
 # ifdef HAVE_IMAGEMAGICK
   /* ImageMagick images are already rotated.  */
   if (EQ (image_spec_value (img->spec, QCtype, NULL), Qimagemagick))
@@ -1939,7 +1939,7 @@ x_set_image_rotation (struct image *img, double tm[3][3])
 static void
 x_set_image_size (struct image *img, double tm[3][3])
 {
-#ifdef HAVE_NATIVE_SCALING
+#ifdef HAVE_NATIVE_TRANSFORMS
 # ifdef HAVE_IMAGEMAGICK
   /* ImageMagick images are already the correct size.  */
   if (EQ (image_spec_value (img->spec, QCtype, NULL), Qimagemagick))
@@ -1951,16 +1951,17 @@ x_set_image_size (struct image *img, double tm[3][3])
     return;
 # endif
 
-  double rm[3][3], tmp[3][3];
-  double xscale, yscale;
   int width, height;
 
   compute_image_size (img->width, img->height, img->spec, &width, &height);
 
+# if defined (HAVE_NS) || defined (HAVE_XRENDER)
+  double rm[3][3], tmp[3][3];
+  double xscale, yscale;
+
   xscale = img->width / (double) width;
   yscale = img->height / (double) height;
 
-# if defined (HAVE_NS) || defined (HAVE_XRENDER)
   INIT_MATRIX (rm);
   rm[0][0] = xscale;
   rm[1][1] = yscale;
@@ -1984,7 +1985,8 @@ x_set_image_size (struct image *img, double tm[3][3])
 static void
 x_set_transform (struct frame *f, struct image *img, double matrix[3][3])
 {
-#ifdef HAVE_NATIVE_SCALING
+  /* TODO: Add MS Windows support.  */
+#ifdef HAVE_NATIVE_TRANSFORMS
 # if defined (HAVE_NS)
   /* Under NS the transform is applied to the drawing surface at
      drawing time, so store it for later.  */
@@ -2066,7 +2068,7 @@ lookup_image (struct frame *f, Lisp_Object spec)
 	  Lisp_Object ascent, margin, relief, bg;
 	  int relief_bound;
 
-#ifdef HAVE_NATIVE_SCALING
+#ifdef HAVE_NATIVE_TRANSFORMS
           double transform_matrix[3][3];
 
           INIT_MATRIX (transform_matrix);
@@ -10025,9 +10027,9 @@ 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.  */)
+DEFUN ("image-transforms-p", Fimage_transforms_p, Simage_transforms_p, 0, 1, 0,
+       doc: /* Test whether FRAME supports image transformation.
+Return t if FRAME supports native transforms, nil otherwise.  */)
      (Lisp_Object frame)
 {
 #if defined (HAVE_NS) || defined (HAVE_NTGUI)
@@ -10288,7 +10290,7 @@ non-numeric, there is no explicit limit on the size of images.  */);
   defsubr (&Slookup_image);
 #endif
 
-  defsubr (&Simage_scaling_p);
+  defsubr (&Simage_transforms_p);
 
   DEFVAR_BOOL ("cross-disabled-images", cross_disabled_images,
     doc: /* Non-nil means always draw a cross over disabled images.
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 30+ messages in thread
* Re: Native image rotation
@ 2019-02-25 12:48 Evgeny Zajcev
  2019-02-25 15:43 ` Clément Pit-Claudel
  0 siblings, 1 reply; 30+ messages in thread
From: Evgeny Zajcev @ 2019-02-25 12:48 UTC (permalink / raw)
  To: cpitclaudel; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 427 bytes --]

> I've used rotated images to display a spinning 'busy' indicator in the modeline
> in the past.  The corresponding package currently ships with a set of
> pre-rotated images, but generating them in Emacs would be more convenient.


I used runtime svg generation for similar task, to display video notes (and
its progression) inside Emacs.

It worked pretty nice, see the demo -
http://lgarc.narod.ru/pics/IMG_3498.MOV

-- 
lg

[-- Attachment #2: Type: text/html, Size: 693 bytes --]

^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2019-06-06 12:57 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-24 11:30 Native image rotation Alan Third
2019-02-24 16:14 ` Eli Zaretskii
2019-02-24 17:34   ` Clément Pit-Claudel
2019-02-24 17:49     ` Eli Zaretskii
2019-02-24 18:06       ` Clément Pit-Claudel
2019-02-24 18:28         ` Eli Zaretskii
2019-02-24 18:51           ` Stefan Monnier
2019-02-24 19:13             ` Eli Zaretskii
2019-02-24 19:23               ` Eli Zaretskii
2019-02-24 20:08                 ` Stefan Monnier
2019-02-24 23:00                   ` Alan Third
2019-02-25  3:32                   ` Eli Zaretskii
2019-02-24 23:22   ` Alan Third
2019-02-25  3:36     ` Eli Zaretskii
2019-02-25  5:11       ` Van L
2019-02-25 13:47       ` Stefan Monnier
2019-02-25 19:21       ` Alan Third
2019-02-26 17:01         ` Daniel Pittman
2019-03-02 13:29         ` Alan Third
2019-05-19 20:29           ` Basil L. Contovounesios
2019-05-20 18:18             ` Alan Third
2019-05-21 20:11               ` Alan Third
2019-06-02 18:11                 ` Alan Third
2019-06-02 18:24                   ` Lars Ingebrigtsen
2019-06-05 21:39                     ` Alan Third
2019-06-06  9:03                       ` Andy Moreton
2019-06-06 12:57                         ` Eli Zaretskii
2019-05-22  6:45             ` Eli Zaretskii
  -- strict thread matches above, loose matches on Subject: below --
2019-02-25 12:48 Evgeny Zajcev
2019-02-25 15:43 ` Clément Pit-Claudel

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).