diff options
| author | Alan Third | 2017-12-03 17:39:03 +0000 |
|---|---|---|
| committer | Alan Third | 2017-12-03 22:41:05 +0000 |
| commit | e4f2061ebc61168f23c0d9440221cbc99864deae (patch) | |
| tree | c9831522b68c63c5810b0164ec67fb3714c771fd | |
| parent | 1cdd0e8cd801aa1d6f04ab4d8e6097a46af8c951 (diff) | |
| download | emacs-e4f2061ebc61168f23c0d9440221cbc99864deae.tar.gz emacs-e4f2061ebc61168f23c0d9440221cbc99864deae.zip | |
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.
| -rw-r--r-- | configure.ac | 6 | ||||
| -rw-r--r-- | lisp/image.el | 5 | ||||
| -rw-r--r-- | src/nsimage.m | 116 | ||||
| -rw-r--r-- | src/nsterm.h | 3 |
4 files changed, 124 insertions, 6 deletions
diff --git a/configure.ac b/configure.ac index b773e3b7f0c..61455a4b0fa 100644 --- a/configure.ac +++ b/configure.ac | |||
| @@ -3424,7 +3424,9 @@ AC_SUBST(LIBXPM) | |||
| 3424 | ### Use -ljpeg if available, unless '--with-jpeg=no'. | 3424 | ### Use -ljpeg if available, unless '--with-jpeg=no'. |
| 3425 | HAVE_JPEG=no | 3425 | HAVE_JPEG=no |
| 3426 | LIBJPEG= | 3426 | LIBJPEG= |
| 3427 | if test "${with_jpeg}" != "no"; then | 3427 | if test "${NS_IMPL_COCOA}" = yes; then |
| 3428 | : # Cocoa provides its own jpeg support, so do nothing. | ||
| 3429 | elif test "${with_jpeg}" != "no"; then | ||
| 3428 | AC_CACHE_CHECK([for jpeglib 6b or later], | 3430 | AC_CACHE_CHECK([for jpeglib 6b or later], |
| 3429 | [emacs_cv_jpeglib], | 3431 | [emacs_cv_jpeglib], |
| 3430 | [OLD_LIBS=$LIBS | 3432 | [OLD_LIBS=$LIBS |
| @@ -3559,7 +3561,7 @@ HAVE_PNG=no | |||
| 3559 | LIBPNG= | 3561 | LIBPNG= |
| 3560 | PNG_CFLAGS= | 3562 | PNG_CFLAGS= |
| 3561 | if test "${NS_IMPL_COCOA}" = yes; then | 3563 | if test "${NS_IMPL_COCOA}" = yes; then |
| 3562 | : # Nothing to do | 3564 | : # Cocoa provides its own png support, so do nothing. |
| 3563 | elif test "${with_png}" != no; then | 3565 | elif test "${with_png}" != no; then |
| 3564 | # mingw32 loads the library dynamically. | 3566 | # mingw32 loads the library dynamically. |
| 3565 | if test "$opsys" = mingw32; then | 3567 | if test "$opsys" = mingw32; then |
diff --git a/lisp/image.el b/lisp/image.el index 32df508bc8d..ed32307ae24 100644 --- a/lisp/image.el +++ b/lisp/image.el | |||
| @@ -976,11 +976,12 @@ default is 20%." | |||
| 976 | image)) | 976 | image)) |
| 977 | 977 | ||
| 978 | (defun image--get-imagemagick-and-warn () | 978 | (defun image--get-imagemagick-and-warn () |
| 979 | (unless (fboundp 'imagemagick-types) | 979 | (unless (or (fboundp 'imagemagick-types) (featurep 'ns)) |
| 980 | (error "Can't rescale images without ImageMagick support")) | 980 | (error "Can't rescale images without ImageMagick support")) |
| 981 | (let ((image (image--get-image))) | 981 | (let ((image (image--get-image))) |
| 982 | (image-flush image) | 982 | (image-flush image) |
| 983 | (plist-put (cdr image) :type 'imagemagick) | 983 | (when (fboundp 'imagemagick-types) |
| 984 | (plist-put (cdr image) :type 'imagemagick)) | ||
| 984 | image)) | 985 | image)) |
| 985 | 986 | ||
| 986 | (defun image--change-size (factor) | 987 | (defun image--change-size (factor) |
diff --git a/src/nsimage.m b/src/nsimage.m index 9d45b063af1..52e3bae05f1 100644 --- a/src/nsimage.m +++ b/src/nsimage.m | |||
| @@ -76,8 +76,9 @@ ns_load_image (struct frame *f, struct image *img, | |||
| 76 | { | 76 | { |
| 77 | EmacsImage *eImg = nil; | 77 | EmacsImage *eImg = nil; |
| 78 | NSSize size; | 78 | NSSize size; |
| 79 | Lisp_Object lisp_index; | 79 | Lisp_Object lisp_index, lisp_rotation; |
| 80 | unsigned int index; | 80 | unsigned int index; |
| 81 | double rotation; | ||
| 81 | 82 | ||
| 82 | NSTRACE ("ns_load_image"); | 83 | NSTRACE ("ns_load_image"); |
| 83 | 84 | ||
| @@ -86,6 +87,9 @@ ns_load_image (struct frame *f, struct image *img, | |||
| 86 | lisp_index = Fplist_get (XCDR (img->spec), QCindex); | 87 | lisp_index = Fplist_get (XCDR (img->spec), QCindex); |
| 87 | index = INTEGERP (lisp_index) ? XFASTINT (lisp_index) : 0; | 88 | index = INTEGERP (lisp_index) ? XFASTINT (lisp_index) : 0; |
| 88 | 89 | ||
| 90 | lisp_rotation = Fplist_get (XCDR (img->spec), QCrotation); | ||
| 91 | rotation = NUMBERP (lisp_rotation) ? XFLOATINT (lisp_rotation) : 0; | ||
| 92 | |||
| 89 | if (STRINGP (spec_file)) | 93 | if (STRINGP (spec_file)) |
| 90 | { | 94 | { |
| 91 | eImg = [EmacsImage allocInitFromFile: spec_file]; | 95 | eImg = [EmacsImage allocInitFromFile: spec_file]; |
| @@ -113,6 +117,17 @@ ns_load_image (struct frame *f, struct image *img, | |||
| 113 | return 0; | 117 | return 0; |
| 114 | } | 118 | } |
| 115 | 119 | ||
| 120 | img->lisp_data = [eImg getMetadata]; | ||
| 121 | |||
| 122 | if (rotation != 0) | ||
| 123 | { | ||
| 124 | EmacsImage *temp = [eImg rotate:rotation]; | ||
| 125 | [eImg release]; | ||
| 126 | eImg = temp; | ||
| 127 | } | ||
| 128 | |||
| 129 | [eImg setSizeFromSpec:XCDR (img->spec)]; | ||
| 130 | |||
| 116 | size = [eImg size]; | 131 | size = [eImg size]; |
| 117 | img->width = size.width; | 132 | img->width = size.width; |
| 118 | img->height = size.height; | 133 | img->height = size.height; |
| @@ -120,7 +135,6 @@ ns_load_image (struct frame *f, struct image *img, | |||
| 120 | /* 4) set img->pixmap = emacsimage */ | 135 | /* 4) set img->pixmap = emacsimage */ |
| 121 | img->pixmap = eImg; | 136 | img->pixmap = eImg; |
| 122 | 137 | ||
| 123 | img->lisp_data = [eImg getMetadata]; | ||
| 124 | return 1; | 138 | return 1; |
| 125 | } | 139 | } |
| 126 | 140 | ||
| @@ -510,4 +524,102 @@ ns_set_alpha (void *img, int x, int y, unsigned char a) | |||
| 510 | return YES; | 524 | return YES; |
| 511 | } | 525 | } |
| 512 | 526 | ||
| 527 | - (void)setSizeFromSpec: (Lisp_Object) spec | ||
| 528 | { | ||
| 529 | NSSize size = [self size]; | ||
| 530 | Lisp_Object value; | ||
| 531 | double scale = 1, aspect = size.width / size.height; | ||
| 532 | double width = -1, height = -1, max_width = -1, max_height = -1; | ||
| 533 | |||
| 534 | value = Fplist_get (spec, QCscale); | ||
| 535 | if (NUMBERP (value)) | ||
| 536 | scale = XFLOATINT (value) ; | ||
| 537 | |||
| 538 | value = Fplist_get (spec, QCmax_width); | ||
| 539 | if (NUMBERP (value)) | ||
| 540 | max_width = XFLOATINT (value); | ||
| 541 | |||
| 542 | value = Fplist_get (spec, QCmax_height); | ||
| 543 | if (NUMBERP (value)) | ||
| 544 | max_height = XFLOATINT (value); | ||
| 545 | |||
| 546 | value = Fplist_get (spec, QCwidth); | ||
| 547 | if (NUMBERP (value)) | ||
| 548 | { | ||
| 549 | width = XFLOATINT (value) * scale; | ||
| 550 | /* :width overrides :max-width. */ | ||
| 551 | max_width = -1; | ||
| 552 | } | ||
| 553 | |||
| 554 | value = Fplist_get (spec, QCheight); | ||
| 555 | if (NUMBERP (value)) | ||
| 556 | { | ||
| 557 | height = XFLOATINT (value) * scale; | ||
| 558 | /* :height overrides :max-height. */ | ||
| 559 | max_height = -1; | ||
| 560 | } | ||
| 561 | |||
| 562 | if (width <= 0 && height <= 0) | ||
| 563 | { | ||
| 564 | width = size.width * scale; | ||
| 565 | height = size.height * scale; | ||
| 566 | } | ||
| 567 | else if (width > 0 && height <= 0) | ||
| 568 | height = width / aspect; | ||
| 569 | else if (height > 0 && width <= 0) | ||
| 570 | width = height * aspect; | ||
| 571 | |||
| 572 | if (max_width > 0 && width > max_width) | ||
| 573 | { | ||
| 574 | width = max_width; | ||
| 575 | height = max_width / aspect; | ||
| 576 | } | ||
| 577 | |||
| 578 | if (max_height > 0 && height > max_height) | ||
| 579 | { | ||
| 580 | height = max_height; | ||
| 581 | width = max_height * aspect; | ||
| 582 | } | ||
| 583 | |||
| 584 | [self setSize:NSMakeSize(width, height)]; | ||
| 585 | } | ||
| 586 | |||
| 587 | - (instancetype)rotate: (double)rotation | ||
| 588 | { | ||
| 589 | EmacsImage *new_image; | ||
| 590 | NSPoint new_origin; | ||
| 591 | NSSize new_size, size = [self size]; | ||
| 592 | NSRect rect = { NSZeroPoint, [self size] }; | ||
| 593 | |||
| 594 | /* Create a bezier path of the outline of the image and do the | ||
| 595 | * rotation on it. */ | ||
| 596 | NSBezierPath *bounds_path = [NSBezierPath bezierPathWithRect:rect]; | ||
| 597 | NSAffineTransform *transform = [NSAffineTransform transform]; | ||
| 598 | [transform rotateByDegrees: rotation * -1]; | ||
| 599 | [bounds_path transformUsingAffineTransform:transform]; | ||
| 600 | |||
| 601 | /* Now we can find out how large the rotated image needs to be. */ | ||
| 602 | new_size = [bounds_path bounds].size; | ||
| 603 | new_image = [[EmacsImage alloc] initWithSize:new_size]; | ||
| 604 | |||
| 605 | new_origin = NSMakePoint((new_size.width - size.width)/2, | ||
| 606 | (new_size.height - size.height)/2); | ||
| 607 | |||
| 608 | [new_image lockFocus]; | ||
| 609 | |||
| 610 | /* Create the final transform. */ | ||
| 611 | transform = [NSAffineTransform transform]; | ||
| 612 | [transform translateXBy:new_size.width/2 yBy:new_size.height/2]; | ||
| 613 | [transform rotateByDegrees: rotation * -1]; | ||
| 614 | [transform translateXBy:-new_size.width/2 yBy:-new_size.height/2]; | ||
| 615 | |||
| 616 | [transform concat]; | ||
| 617 | [self drawAtPoint:new_origin fromRect:NSZeroRect | ||
| 618 | operation:NSCompositingOperationCopy fraction:1]; | ||
| 619 | |||
| 620 | [new_image unlockFocus]; | ||
| 621 | |||
| 622 | return new_image; | ||
| 623 | } | ||
| 624 | |||
| 513 | @end | 625 | @end |
diff --git a/src/nsterm.h b/src/nsterm.h index de96e0dbcbf..c81bf5fb63d 100644 --- a/src/nsterm.h +++ b/src/nsterm.h | |||
| @@ -646,6 +646,8 @@ typedef id instancetype; | |||
| 646 | - (NSColor *)stippleMask; | 646 | - (NSColor *)stippleMask; |
| 647 | - (Lisp_Object)getMetadata; | 647 | - (Lisp_Object)getMetadata; |
| 648 | - (BOOL)setFrame: (unsigned int) index; | 648 | - (BOOL)setFrame: (unsigned int) index; |
| 649 | - (void)setSizeFromSpec: (Lisp_Object) spec; | ||
| 650 | - (instancetype)rotate: (double)rotation; | ||
| 649 | @end | 651 | @end |
| 650 | 652 | ||
| 651 | 653 | ||
| @@ -1306,6 +1308,7 @@ extern char gnustep_base_version[]; /* version tracking */ | |||
| 1306 | #define NSWindowStyleMaskUtilityWindow NSUtilityWindowMask | 1308 | #define NSWindowStyleMaskUtilityWindow NSUtilityWindowMask |
| 1307 | #define NSAlertStyleCritical NSCriticalAlertStyle | 1309 | #define NSAlertStyleCritical NSCriticalAlertStyle |
| 1308 | #define NSControlSizeRegular NSRegularControlSize | 1310 | #define NSControlSizeRegular NSRegularControlSize |
| 1311 | #define NSCompositingOperationCopy NSCompositeCopy | ||
| 1309 | 1312 | ||
| 1310 | /* And adds NSWindowStyleMask. */ | 1313 | /* And adds NSWindowStyleMask. */ |
| 1311 | #ifdef __OBJC__ | 1314 | #ifdef __OBJC__ |