summaryrefslogtreecommitdiff
path: root/src/nsimage.m
diff options
context:
space:
mode:
Diffstat (limited to 'src/nsimage.m')
-rw-r--r--src/nsimage.m150
1 files changed, 131 insertions, 19 deletions
diff --git a/src/nsimage.m b/src/nsimage.m
index f3eba5e37b2..7879c5891d6 100644
--- a/src/nsimage.m
+++ b/src/nsimage.m
@@ -26,7 +26,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
*/
/* This should be the first include, as it may set up #defines affecting
- interpretation of even the system includes. */
+ interpretation of even the system includes. */
#include <config.h>
#include "lisp.h"
@@ -41,7 +41,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
C interface. This allows easy calling from C files. We could just
compile everything as Objective-C, but that might mean slower
- compilation and possible difficulties on some platforms..
+ compilation and possible difficulties on some platforms.
========================================================================== */
@@ -76,15 +76,19 @@ 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");
eassert (valid_image_p (img->spec));
lisp_index = Fplist_get (XCDR (img->spec), QCindex);
- index = INTEGERP (lisp_index) ? XFASTINT (lisp_index) : 0;
+ 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))
{
@@ -109,10 +113,21 @@ ns_load_image (struct frame *f, struct image *img,
if (![eImg setFrame: index])
{
add_to_log ("Unable to set index %d for image %s",
- make_number (index), img->spec);
+ make_fixnum (index), img->spec);
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;
}
@@ -212,7 +226,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
/* Create image from monochrome bitmap. If both FG and BG are 0
- (black), set the background to white and make it transparent. */
+ (black), set the background to white and make it transparent. */
- (instancetype)initFromXBM: (unsigned char *)bits width: (int)w height: (int)h
fg: (unsigned long)fg bg: (unsigned long)bg
{
@@ -237,7 +251,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
}
{
- /* pull bits out to set the (bytewise) alpha mask */
+ /* Pull bits out to set the (bytewise) alpha mask. */
int i, j, k;
unsigned char *s = bits;
unsigned char *rr = planes[0];
@@ -348,7 +362,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
}
-/* attempt to pull out pixmap data from a BitmapImageRep; returns NO if fails */
+/* Attempt to pull out pixmap data from a BitmapImageRep; returns NO if fails. */
- (void) setPixmapData
{
NSEnumerator *reps;
@@ -372,15 +386,15 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
}
-/* note; this and next work only for image created with initForXPMWithDepth,
- initFromSkipXBM, or where setPixmapData was called successfully */
+/* Note: this and next work only for image created with initForXPMWithDepth,
+ initFromSkipXBM, or where setPixmapData was called successfully. */
/* return ARGB */
- (unsigned long) getPixelAtX: (int)x Y: (int)y
{
if (bmRep == nil)
return 0;
- /* this method is faster but won't work for bitmaps */
+ /* This method is faster but won't work for bitmaps. */
if (pixmapData[0] != NULL)
{
int loc = x + y * [self size].width;
@@ -443,7 +457,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
}
}
-/* returns a pattern color, which is cached here */
+/* Returns a pattern color, which is cached here. */
- (NSColor *)stippleMask
{
if (stippleMask == nil)
@@ -451,7 +465,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
return stippleMask;
}
-/* Find the first NSBitmapImageRep which has multiple frames. */
+/* Find the first NSBitmapImageRep which has multiple frames. */
- (NSBitmapImageRep *)getAnimatedBitmapImageRep
{
for (NSImageRep * r in [self representations])
@@ -467,7 +481,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
}
/* If the image has multiple frames, get a count of them and the
- animation delay, if available. */
+ animation delay, if available. */
- (Lisp_Object)getMetadata
{
Lisp_Object metadata = Qnil;
@@ -481,14 +495,14 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
floatValue];
if (frames > 1)
- metadata = Fcons (Qcount, Fcons (make_number (frames), metadata));
+ metadata = Fcons (Qcount, Fcons (make_fixnum (frames), metadata));
if (delay > 0)
metadata = Fcons (Qdelay, Fcons (make_float (delay), metadata));
}
return metadata;
}
-/* Attempt to set the animation frame to be displayed. */
+/* Attempt to set the animation frame to be displayed. */
- (BOOL)setFrame: (unsigned int) index
{
NSBitmapImageRep * bm = [self getAnimatedBitmapImageRep];
@@ -497,7 +511,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
{
int frames = [[bm valueForProperty:NSImageFrameCount] intValue];
- /* If index is invalid, give up. */
+ /* If index is invalid, give up. */
if (index < 0 || index > frames)
return NO;
@@ -506,8 +520,106 @@ ns_set_alpha (void *img, int x, int y, unsigned char a)
}
/* Setting the frame has succeeded, or the image doesn't have
- multiple frames. */
+ multiple frames. */
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