diff options
Diffstat (limited to 'src/nsimage.m')
-rw-r--r-- | src/nsimage.m | 150 |
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 |