unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Alan Third <alan@idiocy.org>
To: "Adam Sjøgren" <asjo@koldfront.dk>
Cc: 38109@debbugs.gnu.org
Subject: bug#38109: Updated Emacs to HEAD, consistently not scaling now
Date: Sun, 24 Nov 2019 17:26:12 +0000	[thread overview]
Message-ID: <20191124172612.GA5665@breton.holly.idiocy.org> (raw)
In-Reply-To: <87blt38no5.fsf@tullinup.koldfront.dk>

[-- Attachment #1: Type: text/plain, Size: 604 bytes --]

On Sat, Nov 23, 2019 at 01:02:50AM +0100, Adam Sjøgren wrote:
> 
> Note, though, how the RGB image looks different than the two others, it
> has a border added.

This is caused by the smoothing of the image. After a LOT of searching
around I found out we need to set the repeat value for the Picture to
pad so that when it’s applying the filter and looking outside the
image bounds it will look for the nearest real pixel rather than
inventing a transparent black one.

Patch attached.

> I have run Gnus in Emacs for around an hour now without any crashes,
> with this patch.

Thanks!
-- 
Alan Third

[-- Attachment #2: v4-0001-Fix-image-scaling-with-masks-bug-38109.patch --]
[-- Type: text/plain, Size: 10173 bytes --]

From 4efbc28e264e2045d4836492bd7fe388e42da055 Mon Sep 17 00:00:00 2001
From: Alan Third <alan@idiocy.org>
Date: Sat, 9 Nov 2019 17:04:25 +0000
Subject: [PATCH v4] Fix image scaling with masks (bug#38109)

* src/image.c (lookup_image): Move call to image_set_transform after
postprocess_image.
(image_create_x_image_and_pixmap_1): Use new function.
(image_set_transform): Apply the transform to the mask too.
(x_create_xrender_picture): New function.
(Create_Pixmap_From_Bitmap_Data):
(xpm_load): Use new function.
* src/xterm.c (x_composite_image): Use PictOpOver when there is a mask
so the transparency is honoured.
(x_draw_image_foreground_1): Use x_composite_image.
---
 src/image.c | 147 ++++++++++++++++++++++++++++++++++++----------------
 src/xterm.c |  11 ++--
 2 files changed, 106 insertions(+), 52 deletions(-)

diff --git a/src/image.c b/src/image.c
index 870f008b14..70d932f9ed 100644
--- a/src/image.c
+++ b/src/image.c
@@ -2244,6 +2244,14 @@ image_set_transform (struct frame *f, struct image *img)
       XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->picture, FilterBest,
 			       0, 0);
       XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->picture, &tmat);
+
+      if (img->mask_picture)
+        {
+          XRenderSetPictureFilter (FRAME_X_DISPLAY (f), img->mask_picture,
+                                   FilterBest, 0, 0);
+          XRenderSetPictureTransform (FRAME_X_DISPLAY (f), img->mask_picture,
+                                      &tmat);
+        }
     }
 # elif defined HAVE_NTGUI
   /* Store the transform matrix for application at draw time.  */
@@ -2313,10 +2321,6 @@ lookup_image (struct frame *f, Lisp_Object spec)
 	  Lisp_Object ascent, margin, relief, bg;
 	  int relief_bound;
 
-#ifdef HAVE_NATIVE_TRANSFORMS
-          image_set_transform (f, img);
-#endif
-
 	  ascent = image_spec_value (spec, QCascent, NULL);
 	  if (FIXNUMP (ascent))
 	    img->ascent = XFIXNUM (ascent);
@@ -2357,6 +2361,13 @@ lookup_image (struct frame *f, Lisp_Object spec)
 	     don't have the image yet.  */
 	  if (!EQ (builtin_lisp_symbol (img->type->type), Qpostscript))
 	    postprocess_image (f, img);
+
+          /* postprocess_image above may modify the image or the mask,
+             relying on the image's real width and height, so
+             image_set_transform must be called after it.  */
+#ifdef HAVE_NATIVE_TRANSFORMS
+          image_set_transform (f, img);
+#endif
 	}
 
       unblock_input ();
@@ -2527,6 +2538,61 @@ x_destroy_x_image (XImage *ximg)
     }
 }
 
+# if !defined USE_CAIRO && defined HAVE_XRENDER
+/* Create and return an XRender Picture for XRender transforms.  */
+static Picture
+x_create_xrender_picture (struct frame *f, Emacs_Pixmap pixmap, int depth)
+{
+  Picture p;
+  Display *display = FRAME_X_DISPLAY (f);
+  int event_basep, error_basep;
+
+  if (XRenderQueryExtension (display, &event_basep, &error_basep))
+    {
+      if (depth <= 0)
+	depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
+      if (depth == 32 || depth == 24 || depth == 8 || depth == 4 || depth == 1)
+        {
+          /* FIXME: Do we need to handle all possible bit depths?
+             XRenderFindStandardFormat supports PictStandardARGB32,
+             PictStandardRGB24, PictStandardA8, PictStandardA4,
+             PictStandardA1, and PictStandardNUM (what is this?!).
+
+             XRenderFindFormat may support more, but I don't
+             understand the documentation.  */
+          XRenderPictFormat *format;
+          format = XRenderFindStandardFormat (display,
+                                              depth == 32 ? PictStandardARGB32
+                                              : depth == 24 ? PictStandardRGB24
+                                              : depth == 8 ? PictStandardA8
+                                              : depth == 4 ? PictStandardA4
+                                              : PictStandardA1);
+
+          /* Set the Picture repeat to "pad".  This means when
+             operations look at pixels outside the image area they
+             will use the value of the nearest real pixel instead of
+             using a transparent black pixel.  */
+          XRenderPictureAttributes attr;
+          unsigned long attr_mask = CPRepeat;
+          attr.repeat = RepeatPad;
+
+          p = XRenderCreatePicture (display, pixmap, format, attr_mask, &attr);
+        }
+      else
+        {
+          image_error ("Specified image bit depth is not supported by XRender");
+          return 0;
+        }
+    }
+  else
+    {
+      /* XRender not supported on this display.  */
+      return 0;
+    }
+
+  return p;
+}
+# endif /* !defined USE_CAIRO && defined HAVE_XRENDER */
 #endif	/* HAVE_X_WINDOWS */
 
 /* Return true if XIMG's size WIDTH x HEIGHT doesn't break the
@@ -2579,36 +2645,8 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d
   if (!x_create_x_image_and_pixmap (f, width, height, depth, pimg, pixmap))
     return 0;
 # ifdef HAVE_XRENDER
-  Display *display = FRAME_X_DISPLAY (f);
-  int event_basep, error_basep;
-  if (picture && XRenderQueryExtension (display, &event_basep, &error_basep))
-    {
-      if (depth <= 0)
-	depth = DefaultDepthOfScreen (FRAME_X_SCREEN (f));
-      if (depth == 32 || depth == 24 || depth == 8)
-        {
-          XRenderPictFormat *format;
-          XRenderPictureAttributes attr;
-
-          /* FIXME: Do we need to handle all possible bit depths?
-             XRenderFindStandardFormat supports PictStandardARGB32,
-             PictStandardRGB24, PictStandardA8, PictStandardA4,
-             PictStandardA1, and PictStandardNUM (what is this?!).
-
-             XRenderFindFormat may support more, but I don't
-             understand the documentation.  */
-          format = XRenderFindStandardFormat (display,
-                                              depth == 32 ? PictStandardARGB32
-                                              : depth == 24 ? PictStandardRGB24
-                                              : PictStandardA8);
-          *picture = XRenderCreatePicture (display, *pixmap, format, 0, &attr);
-        }
-      else
-        {
-          image_error ("Specified image bit depth is not supported by XRender");
-          *picture = 0;
-        }
-    }
+  if (picture)
+    *picture = x_create_xrender_picture (f, *pixmap, depth);
 # endif
 
   return 1;
@@ -3387,6 +3425,11 @@ Create_Pixmap_From_Bitmap_Data (struct frame *f, struct image *img, char *data,
 				   img->width, img->height,
 				   fg, bg,
 				   DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
+# if !defined USE_CAIRO && defined HAVE_XRENDER
+  if (img->pixmap)
+    img->picture = x_create_xrender_picture (f, img->pixmap, 0);
+# endif
+
 #elif defined HAVE_NTGUI
   img->pixmap
     = w32_create_pixmap_from_bitmap_data (img->width, img->height, data);
@@ -4359,18 +4402,30 @@ xpm_load (struct frame *f, struct image *img)
 	  image_clear_image (f, img);
 	  rc = XpmNoMemory;
 	}
-      else if (img->mask_img)
-	{
-          img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
-				     img->mask_img->width,
-				     img->mask_img->height,
-				     img->mask_img->depth);
-	  if (img->mask == NO_PIXMAP)
-	    {
-	      image_clear_image (f, img);
-	      rc = XpmNoMemory;
-	    }
-	}
+      else
+        {
+# if !defined USE_CAIRO && defined HAVE_XRENDER
+          img->picture = x_create_xrender_picture (f, img->pixmap,
+                                                   img->ximg->depth);
+# endif
+          if (img->mask_img)
+            {
+              img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
+                                         img->mask_img->width,
+                                         img->mask_img->height,
+                                         img->mask_img->depth);
+              if (img->mask == NO_PIXMAP)
+                {
+                  image_clear_image (f, img);
+                  rc = XpmNoMemory;
+                }
+# if !defined USE_CAIRO && defined HAVE_XRENDER
+              else
+                img->mask_picture = x_create_xrender_picture
+                  (f, img->mask, img->mask_img->depth);
+# endif
+            }
+        }
     }
 #endif
 
diff --git a/src/xterm.c b/src/xterm.c
index d55bc3890d..9a6eda4488 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -3049,14 +3049,12 @@ x_composite_image (struct glyph_string *s, Pixmap dest,
       XRenderPictFormat *default_format;
       XRenderPictureAttributes attr;
 
-      /* FIXME: Should we do this each time or would it make sense to
-         store destination in the frame struct?  */
       default_format = XRenderFindVisualFormat (display,
                                                 DefaultVisual (display, 0));
       destination = XRenderCreatePicture (display, dest,
                                           default_format, 0, &attr);
 
-      XRenderComposite (display, PictOpSrc,
+      XRenderComposite (display, s->img->mask_picture ? PictOpOver : PictOpSrc,
                         s->img->picture, s->img->mask_picture, destination,
                         srcX, srcY,
                         srcX, srcY,
@@ -3315,6 +3313,7 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
 	     trust on the shape extension to be available
 	     (XShapeCombineRegion).  So, compute the rectangle to draw
 	     manually.  */
+          /* FIXME: Do we need to do this when using XRender compositing?  */
 	  unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
 				| GCFunction);
 	  XGCValues xgcv;
@@ -3325,9 +3324,9 @@ x_draw_image_foreground_1 (struct glyph_string *s, Pixmap pixmap)
 	  xgcv.function = GXcopy;
 	  XChangeGC (display, s->gc, mask, &xgcv);
 
-	  XCopyArea (display, s->img->pixmap, pixmap, s->gc,
-		     s->slice.x, s->slice.y,
-		     s->slice.width, s->slice.height, x, y);
+	  x_composite_image (s, pixmap,
+                             s->slice.x, s->slice.y,
+                             x, y, s->slice.width, s->slice.height);
 	  XSetClipMask (display, s->gc, None);
 	}
       else
-- 
2.21.0


  reply	other threads:[~2019-11-24 17:26 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-11-07 21:11 bug#38109: 27.0.50; xpm image scaling doesn't work Unknown
2019-11-07 21:30 ` bug#38109: Updated Emacs to HEAD, consistently not scaling now Unknown
2019-11-07 21:49   ` Lars Ingebrigtsen
2019-11-07 21:54     ` Unknown
2019-11-07 22:03       ` Lars Ingebrigtsen
2019-11-07 22:12         ` Unknown
2019-11-08 19:34           ` Alan Third
2019-11-08 19:38             ` Alan Third
2019-11-08 21:19               ` Unknown
2019-11-08 21:03             ` Unknown
2019-11-08 21:12               ` Lars Ingebrigtsen
2019-11-08 21:18                 ` Unknown
2019-11-08 21:19                   ` Lars Ingebrigtsen
2019-11-08 21:35                     ` Unknown
2019-11-08 23:03               ` Alan Third
2019-11-09 17:22                 ` Alan Third
2019-11-09 17:58                   ` Eli Zaretskii
2019-11-09 18:11                     ` Alan Third
2019-11-09 18:42                       ` Eli Zaretskii
2019-11-09 20:09                   ` Lars Ingebrigtsen
2019-11-09 21:56                   ` Unknown
2019-11-09 22:18                     ` Unknown
2019-11-09 23:13                       ` Unknown
2019-11-10 17:12                         ` Alan Third
2019-11-16 16:53                           ` Unknown
2019-11-17 17:22                             ` Alan Third
2019-11-17 18:23                               ` Unknown
2019-11-17 18:49                                 ` Unknown
2019-11-17 19:01                                   ` Alan Third
2019-11-09  6:33               ` Eli Zaretskii
2019-11-09 10:28                 ` Unknown
2019-11-09 10:37                   ` Eli Zaretskii
2019-11-08 21:11             ` Lars Ingebrigtsen
2019-11-08 23:06               ` Alan Third
2019-11-08  6:36     ` Eli Zaretskii
2019-11-08 21:04       ` Lars Ingebrigtsen
2019-11-09  6:31         ` Eli Zaretskii
2019-11-07 21:58 ` bug#38109: 27.0.50; xpm image scaling doesn't work Stephen Berman
2019-11-08  6:28 ` Eli Zaretskii
2019-11-08  8:17   ` Unknown
2019-11-08 21:46 ` bug#38109: Another data point Unknown
2019-11-08 22:02   ` Lars Ingebrigtsen
2019-11-23  0:02 ` bug#38109: Updated Emacs to HEAD, consistently not scaling now Unknown
2019-11-24 17:26   ` Alan Third [this message]
2019-11-24 17:52     ` Unknown
2019-11-26 20:36       ` Alan Third
2019-11-26 20:40         ` Unknown
     [not found]           ` <20191126212729.GC7891@breton.holly.idiocy.org>
2019-11-26 21:39             ` bug#38394: Fwd: Use different image filtering when zooming in vs zooming out Alan Third
2019-11-27 12:32               ` Lars Ingebrigtsen
2019-12-02 13:05                 ` Alan Third
2019-12-05 10:02                   ` Lars Ingebrigtsen
2020-08-02 17:52               ` Lars Ingebrigtsen
2020-08-02 20:35                 ` Alan Third
2020-08-03  6:10                   ` Lars Ingebrigtsen
2020-08-03  9:10                     ` Alan Third
2020-08-03 14:04                       ` Robert Pluim
2020-08-03 15:13                         ` Alan Third
2020-08-03 19:55                           ` Robert Pluim
2020-08-04  8:52                       ` Lars Ingebrigtsen
2020-08-04 19:51                         ` Alan Third
2020-08-05  8:47                           ` Lars Ingebrigtsen
2020-08-14  6:03               ` David Ponce
2020-08-14 20:20                 ` Alan Third
2020-08-14 21:14                   ` David Ponce
2020-08-14 23:10                     ` Alan Third
2020-08-15  7:04                       ` David Ponce
2019-11-29 21:27     ` bug#38109: Updated Emacs to HEAD, consistently not scaling now Alan Third

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191124172612.GA5665@breton.holly.idiocy.org \
    --to=alan@idiocy.org \
    --cc=38109@debbugs.gnu.org \
    --cc=asjo@koldfront.dk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).