From af0779178e38f2d52acbb75f00f8c90d78dae03d Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 3 Jun 2024 16:34:51 +0800 Subject: [PATCH] Maintain relationship between tool bar image and default font width * doc/lispref/display.texi (Image Descriptors): Document new value of QCscale. * lisp/cus-start.el (standard) : New definition. * lisp/image.el (image-scaling-factor): Move to C. (create-image): Provide `default' as the default scaling factor. (image--default-smoothing): Accept non-integer scaling factors. (image-compute-scaling-factor): Document that this function is no longer invoked by Emacs. * lisp/tool-bar.el (tool-bar--image-expression): Disable transform smoothing for tool-bar icons. * src/dispextern.h (clear_image_cache): New definition. * src/frame.c (gui_set_font): Clear such image cache entries as derive their scales from the default font width. * src/image.c (clear_image_cache): Export function. (compute_image_size): Implement `default' by reading Vimage_scaling_factor and/or computing a scale factor from the frame's column width, as the case may be. New argument F. All callers changed. (syms_of_image) : Move from image.el. (cherry picked from commit 56376585134d627f96c71b7b063ec51548d3ad3f) --- doc/lispref/display.texi | 10 +++++++ lisp/cus-start.el | 4 +++ lisp/image.el | 24 +++++---------- lisp/tool-bar.el | 3 +- src/dispextern.h | 1 + src/frame.c | 4 +++ src/image.c | 63 ++++++++++++++++++++++++++++++++++------ 7 files changed, 82 insertions(+), 27 deletions(-) diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index abd4ade5931..ce95f2c2056 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi @@ -5971,6 +5971,16 @@ values. If both @code{:scale} and @code{:height}/@code{:width} are specified, the height/width will be adjusted by the specified scaling factor. +@vindex image-scaling-factor +Alternatively, the symbol @code{default} may be specified, indicating +that the image should be scaled according as the value of the +@code{image-scaling-factor} variable, which by default scales the image +in proportion to the average widths (@pxref{Low-Level Font}) of the +default faces of frames on which it happens to be displayed, if such +widths should exceed @code{10} pixels. If no other value is provided, +@code{create-image} will specify this value in image specifications it +creates. + @item :rotation @var{angle} Specifies a rotation angle in degrees. Only multiples of 90 degrees are supported, unless the image type is @code{imagemagick}. Positive diff --git a/lisp/cus-start.el b/lisp/cus-start.el index b5fb5f009bd..b90b35dc8c5 100644 --- a/lisp/cus-start.el +++ b/lisp/cus-start.el @@ -358,6 +358,10 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of ;; fringe.c (overflow-newline-into-fringe fringe boolean) ;; image.c + (image-scaling-factor image + (choice number + (const :tag "Automatically compute" auto)) + "26.1") (imagemagick-render-type image integer "24.1") ;; indent.c (indent-tabs-mode indent boolean) diff --git a/lisp/image.el b/lisp/image.el index e973dff32c7..654a15ef2b4 100644 --- a/lisp/image.el +++ b/lisp/image.el @@ -136,18 +136,6 @@ Subdirectories are not automatically included in the search." :type '(repeat (choice directory variable)) :initialize #'custom-initialize-delay) -(defcustom image-scaling-factor 'auto - "When displaying images, apply this scaling factor before displaying. -This is not supported for all image types, and is mostly useful -when you have a high-resolution monitor. -The value is either a floating point number (where numbers higher -than 1 means to increase the size and lower means to shrink the -size), or the symbol `auto', which will compute a scaling factor -based on the font pixel size." - :type '(choice number - (const :tag "Automatically compute" auto)) - :version "26.1") - (defcustom image-transform-smoothing #'image--default-smoothing "Whether to do smoothing when applying transforms to images. Common transforms are rescaling and rotation. @@ -548,9 +536,7 @@ Images should not be larger than specified by `max-image-size'." file-or-data) (and (not (plist-get props :scale)) ;; Add default scaling. - (list :scale - (image-compute-scaling-factor - image-scaling-factor))) + (list :scale 'default)) props))) ;; Add default smoothing. (unless (plist-member props :transform-smoothing) @@ -579,7 +565,7 @@ Images should not be larger than specified by `max-image-size'." (rotation (plist-get props :rotation))) (cond ;; We always smooth when scaling down and small upwards scaling. - ((and scaling (< scaling 2)) + ((and scaling (numberp scaling) (< scaling 2)) t) ;; Smooth when doing non-90-degree rotation ((and rotation @@ -619,7 +605,11 @@ properties specific to certain image types." (defun image-compute-scaling-factor (&optional scaling) "Compute the scaling factor based on SCALING. If a number, use that. If it's `auto', compute the factor. -If nil, use the `image-scaling-factor' variable." +If nil, use the `image-scaling-factor' variable. + +This function is provided for the benefit of Lisp code that +must compute this factor; it does not affect Emacs's scaling +of images." (unless scaling (setq scaling image-scaling-factor)) (cond diff --git a/lisp/tool-bar.el b/lisp/tool-bar.el index 01c65c42324..1beb6dd819f 100644 --- a/lisp/tool-bar.el +++ b/lisp/tool-bar.el @@ -220,7 +220,8 @@ To define items in any other map, use `tool-bar-local-item'." (let* ((fg (face-attribute 'tool-bar :foreground)) (bg (face-attribute 'tool-bar :background)) (colors (nconc (if (eq fg 'unspecified) nil (list :foreground fg)) - (if (eq bg 'unspecified) nil (list :background bg)))) + (if (eq bg 'unspecified) nil (list :background bg)) + '(:transform-smoothing nil))) (xpm-spec (list :type 'xpm :file (concat icon ".xpm"))) (xpm-lo-spec (list :type 'xpm :file (concat "low-color/" icon ".xpm"))) diff --git a/src/dispextern.h b/src/dispextern.h index 93cbde6583d..28e59700469 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -3621,6 +3621,7 @@ extern void update_redisplay_ticks (int, struct window *); #ifdef HAVE_WINDOW_SYSTEM +extern void clear_image_cache (struct frame *, Lisp_Object); extern ptrdiff_t image_bitmap_pixmap (struct frame *, ptrdiff_t); extern void image_reference_bitmap (struct frame *, ptrdiff_t); extern ptrdiff_t image_create_bitmap_from_data (struct frame *, char *, diff --git a/src/frame.c b/src/frame.c index 80aa4a4a2e8..25620217680 100644 --- a/src/frame.c +++ b/src/frame.c @@ -4811,6 +4811,10 @@ gui_set_font (struct frame *f, Lisp_Object arg, Lisp_Object oldval) /* Recalculate toolbar height. */ f->n_tool_bar_rows = 0; + /* Clean F's image cache of images whose values derive from the font + width. */ + clear_image_cache (f, Qauto); + /* Ensure we redraw it. */ clear_current_matrices (f); diff --git a/src/image.c b/src/image.c index 321073a4fd9..879531d5264 100644 --- a/src/image.c +++ b/src/image.c @@ -2327,7 +2327,7 @@ free_image_cache (struct frame *f) If image-cache-eviction-delay is non-nil, this frees images in the cache which weren't displayed for at least that many seconds. */ -static void +void clear_image_cache (struct frame *f, Lisp_Object filter) { struct image_cache *c = FRAME_IMAGE_CACHE (f); @@ -2670,17 +2670,49 @@ image_get_dimension (struct image *img, Lisp_Object symbol) return -1; } -/* Compute the desired size of an image with native size WIDTH x HEIGHT. - Use IMG to deduce the size. Store the desired size into - *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */ +/* Compute the desired size of an image with native size WIDTH x HEIGHT, + which is to be displayed on F. Use IMG to deduce the size. Store + the desired size into *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the + native size is OK. */ + static void -compute_image_size (double width, double height, +compute_image_size (struct frame *f, double width, double height, struct image *img, int *d_width, int *d_height) { double scale = 1; Lisp_Object value = image_spec_value (img->spec, QCscale, NULL); - if (NUMBERP (value)) + + if (EQ (value, Qdefault)) + { + Lisp_Object sval = Vimage_scaling_factor; + + /* Compute the scale from factors specified by the value of + Vimage_scaling_factor. */ + + invalid_value: + if (EQ (sval, Qauto)) + { + /* This is a tag with which callers of `clear_image_cache' can + refer to this image and its likenesses. */ + img->dependencies = Fcons (Qauto, img->dependencies); + scale = (FRAME_COLUMN_WIDTH (f) > 10 + ? (FRAME_COLUMN_WIDTH (f) / 10.0f) : 1); + } + else if (NUMBERP (sval)) + scale = XFLOATINT (sval); + else + { + image_error ("Invalid `image-scaling-factor': %s", + Vimage_scaling_factor); + + /* If Vimage_scaling_factor is set to an invalid value, treat + it as though it were the default. */ + sval = Qauto; + goto invalid_value; + } + } + else if (NUMBERP (value)) { double dval = XFLOATINT (value); if (0 <= dval) @@ -3009,7 +3041,8 @@ image_set_transform (struct frame *f, struct image *img) } else #endif - compute_image_size (img->width, img->height, img, &width, &height); + compute_image_size (f, img->width, img->height, img, &width, + &height); /* Determine rotation. */ double rotation = 0.0; @@ -11161,7 +11194,7 @@ imagemagick_load_image (struct frame *f, struct image *img, } #ifndef DONT_CREATE_TRANSFORMED_IMAGEMAGICK_IMAGE - compute_image_size (MagickGetImageWidth (image_wand), + compute_image_size (f, MagickGetImageWidth (image_wand), MagickGetImageHeight (image_wand), img, &desired_width, &desired_height); #else @@ -12134,7 +12167,7 @@ svg_load_image (struct frame *f, struct image *img, char *contents, #endif #ifdef HAVE_NATIVE_TRANSFORMS - compute_image_size (viewbox_width, viewbox_height, img, + compute_image_size (f, viewbox_width, viewbox_height, img, &width, &height); width = scale_image_size (width, 1, FRAME_SCALE_FACTOR (f)); @@ -12877,6 +12910,7 @@ non-numeric, there is no explicit limit on the size of images. */); DEFSYM (Qcount, "count"); DEFSYM (Qextension_data, "extension-data"); DEFSYM (Qdelay, "delay"); + DEFSYM (Qauto, "auto"); /* Keywords. */ DEFSYM (QCascent, ":ascent"); @@ -13089,6 +13123,17 @@ The value can also be nil, meaning the cache is never cleared. The function `clear-image-cache' disregards this variable. */); Vimage_cache_eviction_delay = make_fixnum (300); + + DEFVAR_LISP ("image-scaling-factor", Vimage_scaling_factor, + doc: /* When displaying images, apply this scaling factor before displaying. +This is not supported for all image types, and is mostly useful +when you have a high-resolution monitor. +The value is either a floating point number (where numbers higher +than 1 means to increase the size and lower means to shrink the +size), or the symbol `auto', which will compute a scaling factor +based on the font pixel size. */); + Vimage_scaling_factor = Qauto; + #ifdef HAVE_IMAGEMAGICK DEFVAR_INT ("imagemagick-render-type", imagemagick_render_type, doc: /* Integer indicating which ImageMagick rendering method to use. -- 2.39.2