From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Alan Third Newsgroups: gmane.emacs.devel Subject: Native image rotation Date: Sun, 24 Feb 2019 11:30:50 +0000 Message-ID: <20190224113050.GA67303@breton.holly.idiocy.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="vkogqOf2sHV7VnPd" Content-Transfer-Encoding: 8bit Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="110922"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Mutt/1.11.2 (2019-01-07) To: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Sun Feb 24 12:31:23 2019 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1gxs0B-000SgU-3K for ged-emacs-devel@m.gmane.org; Sun, 24 Feb 2019 12:31:23 +0100 Original-Received: from localhost ([127.0.0.1]:49248 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gxs0A-0000dG-3K for ged-emacs-devel@m.gmane.org; Sun, 24 Feb 2019 06:31:22 -0500 Original-Received: from eggs.gnu.org ([209.51.188.92]:49982) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gxrzx-0000cm-4D for emacs-devel@gnu.org; Sun, 24 Feb 2019 06:31:11 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gxrzu-00033P-2F for emacs-devel@gnu.org; Sun, 24 Feb 2019 06:31:09 -0500 Original-Received: from mail-wr1-x42e.google.com ([2a00:1450:4864:20::42e]:34107) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gxrzr-0002m2-BM for emacs-devel@gnu.org; Sun, 24 Feb 2019 06:31:04 -0500 Original-Received: by mail-wr1-x42e.google.com with SMTP id f14so6903800wrg.1 for ; Sun, 24 Feb 2019 03:30:55 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20161025; h=sender:date:from:to:subject:message-id:mime-version :content-disposition:content-transfer-encoding:user-agent; bh=kkdymX7k50CwwpoC6YFCA4HG+ymWtEoF4RWe4Cx4O/w=; b=esTsinbxqUSp5oa3lK/W6SSMaRucB247tLt5fbZEg8EZL+KRkEkqbQv84aWWgvdsxv 2MFG88mFRVpiAIAqROXSuzW2jdGCdgfys6s+G2ns4bPGVVRibJMl75t5vpNUZYleKJtV FlJGfFUF+Ngvg4Hc2OPAUVbZ45oJcmdsM99Som9wTyRM/96s9rgcXy35KKyHwaxABMRc bNsX1IZexJLNPCtUJ3WFwhhqBD82X6r+9u6n/DPyfvhBbGGZssxgwPWBRpR9bds32Plc etJRRH15jYmH+x7M0fHtTDRxMfa4rO3PU032JOVQP6fw9XzaF8bV0iQc3AxeXT4XbxS0 zjhw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:date:from:to:subject:message-id :mime-version:content-disposition:content-transfer-encoding :user-agent; bh=kkdymX7k50CwwpoC6YFCA4HG+ymWtEoF4RWe4Cx4O/w=; b=UYhe2/guIwpnuqKhqhAsfio8MxuNJPEQucguYr1Uzfeurd+z6TJynvvxxXONPt+ucQ tYbmZf46EpH9pn62kpbsRbAGONafE/YcXxhaYSl6MRr742hObdjd3gdKk6wp8yjVrwhA RqgDt1Q+sxMHsDNEa6mg70Oi8v6mJiX7pJ82US8XUIpt3Tz2tguSIWgZfDIcN6qgR9KW eM8OMyCQdUfA8Cu2E16KhtR30tI5CgwgKD4oi/DEuGSR+HiC0kfzTvOxrNY1d0G5aE/F D3JOslgFhUUliPDVtt4aLA5xM5OtnG+nwZY2K0NocofyxvNsIU2fMZp2HK+IeXhyYG8d hQaQ== X-Gm-Message-State: AHQUAub0Qmt8nmcUYFqnXpVwVnfHPGM+e2SFPQw9NRp69NvmPshxoY9I dYa+iXRr4sb5ftCEUzSG8gHt8Qwv X-Google-Smtp-Source: AHgI3IZHTYdcZODn66WIa6C3NK9Z1Aa0Z4JXaNv/Wp9Nw2IBgxTDH35vasmNKHCZ8chjOuGJoFcZ8g== X-Received: by 2002:a5d:6346:: with SMTP id b6mr9269724wrw.118.1551007854071; Sun, 24 Feb 2019 03:30:54 -0800 (PST) Original-Received: from breton.holly.idiocy.org (ip6-2001-08b0-03f8-8129-2116-b59c-3958-9dbd.holly.idiocy.org. [2001:8b0:3f8:8129:2116:b59c:3958:9dbd]) by smtp.gmail.com with ESMTPSA id m4sm7745537wmi.3.2019.02.24.03.30.52 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 24 Feb 2019 03:30:52 -0800 (PST) Content-Disposition: inline X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::42e X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:233561 Archived-At: --vkogqOf2sHV7VnPd Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit 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 --vkogqOf2sHV7VnPd Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0001-Add-native-image-rotation.patch" >From 1b1dbf1d77f40f09756c4d677dfdc4bf3e44952d Mon Sep 17 00:00:00 2001 From: Alan Third 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 . */ #include #endif /* HAVE_SYS_TYPES_H */ +#ifdef HAVE_NATIVE_SCALING +#include +#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 --vkogqOf2sHV7VnPd Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0002-Rename-image-scaling-to-image-transforms.patch" >From c9345f094179372b0b83c2b6bafaf9276fd59b29 Mon Sep 17 00:00:00 2001 From: Alan Third 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 . */ #include #endif /* HAVE_SYS_TYPES_H */ -#ifdef HAVE_NATIVE_SCALING +#ifdef HAVE_NATIVE_TRANSFORMS #include #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 --vkogqOf2sHV7VnPd--