emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master e4f2061: Add image resizing and rotation to NS port


From: Alan Third
Subject: [Emacs-diffs] master e4f2061: Add image resizing and rotation to NS port
Date: Sun, 3 Dec 2017 17:44:42 -0500 (EST)

branch: master
commit e4f2061ebc61168f23c0d9440221cbc99864deae
Author: Alan Third <address@hidden>
Commit: Alan Third <address@hidden>

    Add image resizing and rotation to NS port
    
    * lisp/image.el (image--get-imagemagick-and-warn): Bypass imagemagick
    check when using NS.
    * src/nsimage.m (ns_load_image): Add rotation and resizing
    functionality. Move the getMetaData call to before the resize/rotation
    so it returns correct metadata.
    (EmacsImage::setSizeFromSpec, EmacsImage::rotate): New functions.
    * src/nsterm.h (EmacsImage): Add new function prototypes.
    (NSCompositingOperationCopy): Add define to older equivalent for
    GNUstep and pre-10.12 macOS.
    * configure.ac: Don't use libjpeg on Cocoa.
---
 configure.ac  |   6 ++-
 lisp/image.el |   5 ++-
 src/nsimage.m | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/nsterm.h  |   3 ++
 4 files changed, 124 insertions(+), 6 deletions(-)

diff --git a/configure.ac b/configure.ac
index b773e3b..61455a4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3424,7 +3424,9 @@ AC_SUBST(LIBXPM)
 ### Use -ljpeg if available, unless '--with-jpeg=no'.
 HAVE_JPEG=no
 LIBJPEG=
-if test "${with_jpeg}" != "no"; then
+if test "${NS_IMPL_COCOA}" = yes; then
+  : # Cocoa provides its own jpeg support, so do nothing.
+elif test "${with_jpeg}" != "no"; then
   AC_CACHE_CHECK([for jpeglib 6b or later],
     [emacs_cv_jpeglib],
     [OLD_LIBS=$LIBS
@@ -3559,7 +3561,7 @@ HAVE_PNG=no
 LIBPNG=
 PNG_CFLAGS=
 if test "${NS_IMPL_COCOA}" = yes; then
-  : # Nothing to do
+  : # Cocoa provides its own png support, so do nothing.
 elif test "${with_png}" != no; then
   # mingw32 loads the library dynamically.
   if test "$opsys" = mingw32; then
diff --git a/lisp/image.el b/lisp/image.el
index 32df508..ed32307 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -976,11 +976,12 @@ default is 20%."
     image))
 
 (defun image--get-imagemagick-and-warn ()
-  (unless (fboundp 'imagemagick-types)
+  (unless (or (fboundp 'imagemagick-types) (featurep 'ns))
     (error "Can't rescale images without ImageMagick support"))
   (let ((image (image--get-image)))
     (image-flush image)
-    (plist-put (cdr image) :type 'imagemagick)
+    (when (fboundp 'imagemagick-types)
+      (plist-put (cdr image) :type 'imagemagick))
     image))
 
 (defun image--change-size (factor)
diff --git a/src/nsimage.m b/src/nsimage.m
index 9d45b06..52e3bae 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -76,8 +76,9 @@ ns_load_image (struct frame *f, struct image *img,
 {
   EmacsImage *eImg = nil;
   NSSize size;
-  Lisp_Object lisp_index;
+  Lisp_Object lisp_index, lisp_rotation;
   unsigned int index;
+  double rotation;
 
   NSTRACE ("ns_load_image");
 
@@ -86,6 +87,9 @@ ns_load_image (struct frame *f, struct image *img,
   lisp_index = Fplist_get (XCDR (img->spec), QCindex);
   index = INTEGERP (lisp_index) ? XFASTINT (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];
@@ -113,6 +117,17 @@ ns_load_image (struct frame *f, struct image *img,
       return 0;
     }
 
+  img->lisp_data = [eImg getMetadata];
+
+  if (rotation != 0)
+    {
+      EmacsImage *temp = [eImg rotate:rotation];
+      [eImg release];
+      eImg = temp;
+    }
+
+  [eImg setSizeFromSpec:XCDR (img->spec)];
+
   size = [eImg size];
   img->width = size.width;
   img->height = size.height;
@@ -120,7 +135,6 @@ ns_load_image (struct frame *f, struct image *img,
   /* 4) set img->pixmap = emacsimage */
   img->pixmap = eImg;
 
-  img->lisp_data = [eImg getMetadata];
   return 1;
 }
 
@@ -510,4 +524,102 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
   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;
+  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;
+}
+
 @end
diff --git a/src/nsterm.h b/src/nsterm.h
index de96e0d..c81bf5f 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -646,6 +646,8 @@ typedef id instancetype;
 - (NSColor *)stippleMask;
 - (Lisp_Object)getMetadata;
 - (BOOL)setFrame: (unsigned int) index;
+- (void)setSizeFromSpec: (Lisp_Object) spec;
+- (instancetype)rotate: (double)rotation;
 @end
 
 
@@ -1306,6 +1308,7 @@ extern char gnustep_base_version[];  /* version tracking 
*/
 #define NSWindowStyleMaskUtilityWindow     NSUtilityWindowMask
 #define NSAlertStyleCritical               NSCriticalAlertStyle
 #define NSControlSizeRegular               NSRegularControlSize
+#define NSCompositingOperationCopy         NSCompositeCopy
 
 /* And adds NSWindowStyleMask. */
 #ifdef __OBJC__



reply via email to

[Prev in Thread] Current Thread [Next in Thread]