emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 2755cf1 2/2: Support native image resizing on cairo


From: YAMAMOTO Mitsuharu
Subject: [Emacs-diffs] master 2755cf1 2/2: Support native image resizing on cairo
Date: Tue, 26 Mar 2019 22:13:42 -0400 (EDT)

branch: master
commit 2755cf1848b551436b9cc2eff6e4b882b10c07aa
Author: YAMAMOTO Mitsuharu <address@hidden>
Commit: YAMAMOTO Mitsuharu <address@hidden>

    Support native image resizing on cairo
    
    * src/xterm.c (x_cr_draw_image): Add arguments image_width and
    image_height and support scaling.  All callers changed.
    * src/image.c (Fimage_scaling_p): Return t when USE_CAIRO.
    (x_set_image_size) [USE_CAIRO]: Record the scaled dimensions
    in the image struct.
    * src/dispextern.h (HAVE_NATIVE_SCALING): Define when
    USE_CAIRO as well.
    
    * etc/NEWS: Update the announcement of native image scaling.
---
 etc/NEWS         |  6 +++---
 src/dispextern.h |  2 +-
 src/image.c      |  7 +++++--
 src/xterm.c      | 34 +++++++++++++++++++++++++---------
 4 files changed, 34 insertions(+), 15 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 71127ac..7486d6b 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1718,9 +1718,9 @@ the process.  That way 'make-process' can start remote 
processes.
 +++
 ** Emacs now supports resizing (scaling) of 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
-scaling.)
+systems, Cairo drawing or 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.
diff --git a/src/dispextern.h b/src/dispextern.h
index 4d96e51..1a53656 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -2938,7 +2938,7 @@ struct redisplay_interface
 
 #ifdef HAVE_WINDOW_SYSTEM
 
-# if defined HAVE_XRENDER || defined HAVE_NS || defined HAVE_NTGUI
+# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS || defined 
HAVE_NTGUI
 #  define HAVE_NATIVE_SCALING
 # endif
 
diff --git a/src/image.c b/src/image.c
index 16c5978..6e415ef 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1878,7 +1878,10 @@ x_set_image_size (struct frame *f, struct image *img)
   img->height = height;
 # endif
 
-# ifdef HAVE_XRENDER
+# ifdef USE_CAIRO
+  img->width = width;
+  img->height = height;
+# elif defined HAVE_XRENDER
   if (img->picture)
     {
       double xscale = img->width / (double) width;
@@ -9918,7 +9921,7 @@ DEFUN ("image-scaling-p", Fimage_scaling_p, 
Simage_scaling_p, 0, 1, 0,
 Return t if FRAME supports native scaling, nil otherwise.  */)
      (Lisp_Object frame)
 {
-#if defined (HAVE_NS) || defined (HAVE_NTGUI)
+#if defined (USE_CAIRO) || defined (HAVE_NS) || defined (HAVE_NTGUI)
   return Qt;
 #elif defined (HAVE_X_WINDOWS) && defined (HAVE_XRENDER)
   int event_basep, error_basep;
diff --git a/src/xterm.c b/src/xterm.c
index 33eb0f3..f90d671 100644
--- a/src/xterm.c
+++ b/src/xterm.c
@@ -480,13 +480,12 @@ x_cr_destroy_fringe_bitmap (int which)
 
 static void
 x_cr_draw_image (struct frame *f, GC gc, cairo_surface_t *image,
+                int image_width, int image_height,
                 int src_x, int src_y, int width, int height,
                 int dest_x, int dest_y, bool overlay_p)
 {
-  cairo_t *cr;
-  cairo_format_t format;
+  cairo_t *cr = x_begin_cr_clip (f, gc);
 
-  cr = x_begin_cr_clip (f, gc);
   if (overlay_p)
     cairo_rectangle (cr, dest_x, dest_y, width, height);
   else
@@ -495,18 +494,33 @@ x_cr_draw_image (struct frame *f, GC gc, cairo_surface_t 
*image,
       cairo_rectangle (cr, dest_x, dest_y, width, height);
       cairo_fill_preserve (cr);
     }
-  format = cairo_image_surface_get_format (image);
+
+  int orig_image_width = cairo_image_surface_get_width (image);
+  if (image_width == 0) image_width = orig_image_width;
+  int orig_image_height = cairo_image_surface_get_height (image);
+  if (image_height == 0) image_height = orig_image_height;
+
+  cairo_pattern_t *pattern = cairo_pattern_create_for_surface (image);
+  cairo_matrix_t matrix;
+  cairo_matrix_init_scale (&matrix, orig_image_width / (double) image_width,
+                          orig_image_height / (double) image_height);
+  cairo_matrix_translate (&matrix, src_x - dest_x, src_y - dest_y);
+  cairo_pattern_set_matrix (pattern, &matrix);
+
+  cairo_format_t format = cairo_image_surface_get_format (image);
   if (format != CAIRO_FORMAT_A8 && format != CAIRO_FORMAT_A1)
     {
-      cairo_set_source_surface (cr, image, dest_x - src_x, dest_y - src_y);
+      cairo_set_source (cr, pattern);
       cairo_fill (cr);
     }
   else
     {
       x_set_cr_source_with_gc_foreground (f, gc);
       cairo_clip (cr);
-      cairo_mask_surface (cr, image, dest_x - src_x, dest_y - src_y);
+      cairo_mask (cr, pattern);
     }
+  cairo_pattern_destroy (pattern);
+
   x_end_cr_clip (f);
 }
 
@@ -1430,7 +1444,7 @@ x_draw_fringe_bitmap (struct window *w, struct glyph_row 
*row, struct draw_fring
                                       : f->output_data.x->cursor_pixel)
                                    : face->foreground));
       XSetBackground (display, gc, face->background);
-      x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, p->dh,
+      x_cr_draw_image (f, gc, fringe_bmp[p->which], 0, 0, 0, p->dh,
                       p->wd, p->h, p->x, p->y, p->overlay_p);
       XSetForeground (display, gc, gcv.foreground);
       XSetBackground (display, gc, gcv.background);
@@ -3041,8 +3055,10 @@ x_draw_image_foreground (struct glyph_string *s)
   if (s->img->cr_data)
     {
       x_set_glyph_string_clipping (s);
-      x_cr_draw_image (s->f, s->gc, s->img->cr_data, s->slice.x, s->slice.y,
-                      s->slice.width, s->slice.height, x, y, true);
+      x_cr_draw_image (s->f, s->gc,
+                      s->img->cr_data, s->img->width, s->img->height,
+                      s->slice.x, s->slice.y, s->slice.width, s->slice.height,
+                      x, y, true);
       if (!s->img->mask)
        {
          /* When the image has a mask, we can expect that at



reply via email to

[Prev in Thread] Current Thread [Next in Thread]