diff options
| author | Lars Ingebrigtsen | 2017-07-15 02:45:19 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2017-07-15 02:48:17 +0200 |
| commit | ae56c9674b4668ded392c66d46aa22db902ddd71 (patch) | |
| tree | 3472b1e2c5877ee37a0b4813f60bc2b2b5515d47 | |
| parent | 89c5d59280edaf89b959597a39d848b54c36975a (diff) | |
| download | emacs-ae56c9674b4668ded392c66d46aa22db902ddd71.tar.gz emacs-ae56c9674b4668ded392c66d46aa22db902ddd71.zip | |
Make combinations of :width/:max-height image specs work reliably
* doc/lispref/display.texi (ImageMagick Images): Document
:width/:max-height combinations (etc) (bug #25583).
* src/image.c (compute_image_size): Handle :width/:max-height
(etc) combinations consistently (by letting "max" win and
preserve ratio).
* test/manual/image-size-tests.el (image-size-tests): Add
tests for :width/:max-height (etc) combinations.
| -rw-r--r-- | doc/lispref/display.texi | 11 | ||||
| -rw-r--r-- | etc/NEWS | 8 | ||||
| -rw-r--r-- | src/image.c | 97 | ||||
| -rw-r--r-- | test/manual/image-size-tests.el | 10 |
4 files changed, 72 insertions, 54 deletions
diff --git a/doc/lispref/display.texi b/doc/lispref/display.texi index 005d31af05a..98940cbc996 100644 --- a/doc/lispref/display.texi +++ b/doc/lispref/display.texi | |||
| @@ -5305,6 +5305,17 @@ and if @code{:height} is set it will have precedence over | |||
| 5305 | wish. @code{:max-width} and @code{:max-height} will always preserve | 5305 | wish. @code{:max-width} and @code{:max-height} will always preserve |
| 5306 | the aspect ratio. | 5306 | the aspect ratio. |
| 5307 | 5307 | ||
| 5308 | If both @code{:width} and @code{:max-height} has been set (but | ||
| 5309 | @code{:height} has not been set), then @code{:max-height} will have | ||
| 5310 | precedence. The same is the case for the opposite combination: The | ||
| 5311 | ``max'' keyword has precedence. That is, if you have a 200x100 image | ||
| 5312 | and specify that @code{:width} should be 400 and @code{:max-height} | ||
| 5313 | should be 150, you'll end up with an image that is 300x150: Preserving | ||
| 5314 | the aspect ratio and not exceeding the ``max'' setting. This | ||
| 5315 | combination of parameters is a useful way of saying ``display this | ||
| 5316 | image as large as possible, but no larger than the available display | ||
| 5317 | area''. | ||
| 5318 | |||
| 5308 | @item :scale @var{scale} | 5319 | @item :scale @var{scale} |
| 5309 | This should be a number, where values higher than 1 means to increase | 5320 | This should be a number, where values higher than 1 means to increase |
| 5310 | the size, and lower means to decrease the size. For instance, a value | 5321 | the size, and lower means to decrease the size. For instance, a value |
| @@ -763,6 +763,14 @@ Ido mode is active. | |||
| 763 | in question). | 763 | in question). |
| 764 | 764 | ||
| 765 | +++ | 765 | +++ |
| 766 | *** It's now possible to specify aspect-ratio preserving combinations | ||
| 767 | of :width/:max-height and :height/:max-width keywords. In either | ||
| 768 | case, the "max" keywords win. (Previously some combinations would, | ||
| 769 | depending on the aspect ratio of the image, just be ignored and in | ||
| 770 | other instances this would lead to the aspect ratio not being | ||
| 771 | preserved.) | ||
| 772 | |||
| 773 | +++ | ||
| 766 | *** Images inserted with 'insert-image' and related functions get a | 774 | *** Images inserted with 'insert-image' and related functions get a |
| 767 | keymap put into the text properties (or overlays) that span the | 775 | keymap put into the text properties (or overlays) that span the |
| 768 | image. This keymap binds keystrokes for manipulating size and | 776 | image. This keymap binds keystrokes for manipulating size and |
diff --git a/src/image.c b/src/image.c index 1426e309445..69a529e8c35 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -8086,83 +8086,76 @@ compute_image_size (size_t width, size_t height, | |||
| 8086 | int *d_width, int *d_height) | 8086 | int *d_width, int *d_height) |
| 8087 | { | 8087 | { |
| 8088 | Lisp_Object value; | 8088 | Lisp_Object value; |
| 8089 | int desired_width, desired_height; | 8089 | int desired_width = -1, desired_height = -1, max_width = -1, max_height = -1; |
| 8090 | double scale = 1; | 8090 | double scale = 1; |
| 8091 | 8091 | ||
| 8092 | value = image_spec_value (spec, QCscale, NULL); | 8092 | value = image_spec_value (spec, QCscale, NULL); |
| 8093 | if (NUMBERP (value)) | 8093 | if (NUMBERP (value)) |
| 8094 | scale = XFLOATINT (value); | 8094 | scale = XFLOATINT (value); |
| 8095 | 8095 | ||
| 8096 | value = image_spec_value (spec, QCmax_width, NULL); | ||
| 8097 | if (NATNUMP (value)) | ||
| 8098 | max_width = min (XFASTINT (value), INT_MAX); | ||
| 8099 | |||
| 8100 | value = image_spec_value (spec, QCmax_height, NULL); | ||
| 8101 | if (NATNUMP (value)) | ||
| 8102 | max_height = min (XFASTINT (value), INT_MAX); | ||
| 8103 | |||
| 8096 | /* If width and/or height is set in the display spec assume we want | 8104 | /* If width and/or height is set in the display spec assume we want |
| 8097 | to scale to those values. If either h or w is unspecified, the | 8105 | to scale to those values. If either h or w is unspecified, the |
| 8098 | unspecified should be calculated from the specified to preserve | 8106 | unspecified should be calculated from the specified to preserve |
| 8099 | aspect ratio. */ | 8107 | aspect ratio. */ |
| 8100 | value = image_spec_value (spec, QCwidth, NULL); | 8108 | value = image_spec_value (spec, QCwidth, NULL); |
| 8101 | desired_width = NATNUMP (value) ? | 8109 | if (NATNUMP (value)) |
| 8102 | min (XFASTINT (value) * scale, INT_MAX) : -1; | ||
| 8103 | value = image_spec_value (spec, QCheight, NULL); | ||
| 8104 | desired_height = NATNUMP (value) ? | ||
| 8105 | min (XFASTINT (value) * scale, INT_MAX) : -1; | ||
| 8106 | |||
| 8107 | width = width * scale; | ||
| 8108 | height = height * scale; | ||
| 8109 | |||
| 8110 | if (desired_width == -1) | ||
| 8111 | { | 8110 | { |
| 8112 | value = image_spec_value (spec, QCmax_width, NULL); | 8111 | desired_width = min (XFASTINT (value) * scale, INT_MAX); |
| 8113 | if (NATNUMP (value)) | 8112 | /* :width overrides :max-width. */ |
| 8114 | { | 8113 | max_width = -1; |
| 8115 | int max_width = min (XFASTINT (value), INT_MAX); | ||
| 8116 | if (max_width < width) | ||
| 8117 | { | ||
| 8118 | /* The image is wider than :max-width. */ | ||
| 8119 | desired_width = max_width; | ||
| 8120 | if (desired_height == -1) | ||
| 8121 | { | ||
| 8122 | desired_height = scale_image_size (desired_width, | ||
| 8123 | width, height); | ||
| 8124 | value = image_spec_value (spec, QCmax_height, NULL); | ||
| 8125 | if (NATNUMP (value)) | ||
| 8126 | { | ||
| 8127 | int max_height = min (XFASTINT (value), INT_MAX); | ||
| 8128 | if (max_height < desired_height) | ||
| 8129 | { | ||
| 8130 | desired_height = max_height; | ||
| 8131 | desired_width = scale_image_size (desired_height, | ||
| 8132 | height, width); | ||
| 8133 | } | ||
| 8134 | } | ||
| 8135 | } | ||
| 8136 | } | ||
| 8137 | } | ||
| 8138 | } | 8114 | } |
| 8139 | 8115 | ||
| 8140 | if (desired_height == -1) | 8116 | value = image_spec_value (spec, QCheight, NULL); |
| 8117 | if (NATNUMP (value)) | ||
| 8141 | { | 8118 | { |
| 8142 | value = image_spec_value (spec, QCmax_height, NULL); | 8119 | desired_height = min (XFASTINT (value) * scale, INT_MAX); |
| 8143 | if (NATNUMP (value)) | 8120 | /* :height overrides :max-height. */ |
| 8144 | { | 8121 | max_height = -1; |
| 8145 | int max_height = min (XFASTINT (value), INT_MAX); | ||
| 8146 | if (max_height < height) | ||
| 8147 | desired_height = max_height; | ||
| 8148 | } | ||
| 8149 | } | 8122 | } |
| 8150 | 8123 | ||
| 8124 | /* If we have both width/height set explicitly, we skip past all the | ||
| 8125 | aspect ratio-preserving computations below. */ | ||
| 8126 | if (desired_width != -1 && desired_height != -1) | ||
| 8127 | goto out; | ||
| 8128 | |||
| 8129 | width = width * scale; | ||
| 8130 | height = height * scale; | ||
| 8131 | |||
| 8151 | if (desired_width != -1 && desired_height == -1) | 8132 | if (desired_width != -1 && desired_height == -1) |
| 8152 | /* w known, calculate h. */ | 8133 | /* Width known, calculate height. */ |
| 8153 | desired_height = scale_image_size (desired_width, width, height); | 8134 | desired_height = scale_image_size (desired_width, width, height); |
| 8154 | 8135 | else if (desired_width == -1 && desired_height != -1) | |
| 8155 | if (desired_width == -1 && desired_height != -1) | 8136 | /* Height known, calculate width. */ |
| 8156 | /* h known, calculate w. */ | ||
| 8157 | desired_width = scale_image_size (desired_height, height, width); | 8137 | desired_width = scale_image_size (desired_height, height, width); |
| 8158 | 8138 | else | |
| 8159 | /* We have no width/height settings, so just apply the scale. */ | ||
| 8160 | if (desired_width == -1 && desired_height == -1) | ||
| 8161 | { | 8139 | { |
| 8162 | desired_width = width; | 8140 | desired_width = width; |
| 8163 | desired_height = height; | 8141 | desired_height = height; |
| 8164 | } | 8142 | } |
| 8165 | 8143 | ||
| 8144 | if (max_width != -1 && desired_width > max_width) | ||
| 8145 | { | ||
| 8146 | /* The image is wider than :max-width. */ | ||
| 8147 | desired_width = max_width; | ||
| 8148 | desired_height = scale_image_size (desired_width, width, height); | ||
| 8149 | } | ||
| 8150 | |||
| 8151 | if (max_height != -1 && desired_height > max_height) | ||
| 8152 | { | ||
| 8153 | /* The image is higher than :max-height. */ | ||
| 8154 | desired_height = max_height; | ||
| 8155 | desired_width = scale_image_size (desired_height, height, width); | ||
| 8156 | } | ||
| 8157 | |||
| 8158 | out: | ||
| 8166 | *d_width = desired_width; | 8159 | *d_width = desired_width; |
| 8167 | *d_height = desired_height; | 8160 | *d_height = desired_height; |
| 8168 | } | 8161 | } |
diff --git a/test/manual/image-size-tests.el b/test/manual/image-size-tests.el index 577c7658791..6721e348e12 100644 --- a/test/manual/image-size-tests.el +++ b/test/manual/image-size-tests.el | |||
| @@ -25,8 +25,8 @@ | |||
| 25 | (defmacro im-should (image width height &rest props) | 25 | (defmacro im-should (image width height &rest props) |
| 26 | `(let ((im (im-image ,image ,@props))) | 26 | `(let ((im (im-image ,image ,@props))) |
| 27 | (unless (im-compare im ,width ,height) | 27 | (unless (im-compare im ,width ,height) |
| 28 | (error "%s didn't succeed; size is %s" | 28 | (error "%s %s didn't succeed; size is %s" |
| 29 | ',props (image-size im t))))) | 29 | ',image ',props (image-size im t))))) |
| 30 | 30 | ||
| 31 | (defun im-image (type &rest props) | 31 | (defun im-image (type &rest props) |
| 32 | (let ((image-scaling-factor 1)) | 32 | (let ((image-scaling-factor 1)) |
| @@ -67,6 +67,9 @@ | |||
| 67 | ;; Both max-width/height. | 67 | ;; Both max-width/height. |
| 68 | (im-should :w 100 50 :max-width 100 :max-height 75) | 68 | (im-should :w 100 50 :max-width 100 :max-height 75) |
| 69 | (im-should :w 50 25 :max-width 100 :max-height 25) | 69 | (im-should :w 50 25 :max-width 100 :max-height 25) |
| 70 | ;; :width and :max-height (max-height wins). | ||
| 71 | (im-should :w 400 200 :width 400 :max-height 200) | ||
| 72 | (im-should :w 400 200 :width 500 :max-height 200) | ||
| 70 | 73 | ||
| 71 | ;; Test the image that's taller than it is wide. | 74 | ;; Test the image that's taller than it is wide. |
| 72 | (im-should :h 100 200) | 75 | (im-should :h 100 200) |
| @@ -87,6 +90,9 @@ | |||
| 87 | ;; Both max-width/height. | 90 | ;; Both max-width/height. |
| 88 | (im-should :h 50 100 :max-width 75 :max-height 100) | 91 | (im-should :h 50 100 :max-width 75 :max-height 100) |
| 89 | (im-should :h 25 50 :max-width 25 :max-height 100) | 92 | (im-should :h 25 50 :max-width 25 :max-height 100) |
| 93 | ;; :hieght and :max-width (max-width wins). | ||
| 94 | (im-should :h 200 400 :height 400 :max-width 200) | ||
| 95 | (im-should :h 200 400 :height 500 :max-width 200) | ||
| 90 | ) | 96 | ) |
| 91 | 97 | ||
| 92 | ;;; image-size-tests.el ends here | 98 | ;;; image-size-tests.el ends here |