[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#69602: 29.1; Image :map should adjust with :scale and :rotation
From: |
Joseph Turner |
Subject: |
bug#69602: 29.1; Image :map should adjust with :scale and :rotation |
Date: |
Thu, 07 Mar 2024 05:53:11 -0800 |
Eli Zaretskii <eliz@gnu.org> writes:
>> From: Joseph Turner <joseph@breatheoutbreathe.in>
>> Cc: 69602@debbugs.gnu.org, stephen.berman@gmx.net, juri@linkov.net
>> Date: Thu, 07 Mar 2024 00:08:57 -0800
>>
>> Eli Zaretskii <eliz@gnu.org> writes:
> I hoped :map allows its value to be a form that is evaluated when the
> image is being processed, in which case that form could call
> image-compute-scaling-factor when it produces the coordinates.
Thanks! Would this require a change in C?
> If that doesn't work, then...
>
>> When creating an image, we set its :map property according to the return
>> value of `image-compute-scaling-factor'. Once the image is inserted into
>> the buffer, the user may run `image-increase-size' or `image-rotate',
>> which changes how the image is displayed but not its :map.
>>
>> Now, we need to rerun `image-compute-scaling-factor' and recompute :map.
What I said here is wrong. `image-compute-scaling-factor' is not
useful for recomputing :map, but `image--current-scaling' is.
>> However, there is no hook which runs after the user runs those commands,
>> so AFAICT there's no way for our code to know when to recompute :map.
>
> ...AFAIU, when an image is rescaled, we call
> image-transform-properties to produce the updated image properties.
There are two ways to rescale an image, `image-transform-properties'
(defined in image-mode.el; works only on file-backed images in
image-mode) and `image--change-size' (defined in image.el; works
on any image object in any mode).
For now, I'd like to focus on improving `image.el'.
> So I guess you'd like that function to recompute the coordinates in
> :map according to the transform?
>
> IOW, I don't understand why you think the problem can only be solved
> in C: AFAIK almost all of the machinery that performs image transforms
> is implemented in Lisp, and each time an image is rescaled, we
> basically re-process the image descriptor anew.
The attached patch adds two hooks in `image.el' which allow packages to
recompute an image's map after it's rescaled or rotated.
The following demonstrates `image-after-change-size-hooks':
(progn
(defun image--scale-map (map factor)
"Scale MAP by FACTOR, destructively modifying it."
(when (and factor (/= 1 factor))
(pcase-dolist (`(,`(,type . ,coords) ,_id ,_plist) map)
(pcase-exhaustive type
('rect
(setf (caar coords) (round (* (caar coords) factor)))
(setf (cdar coords) (round (* (cdar coords) factor)))
(setf (cadr coords) (round (* (cadr coords) factor)))
(setf (cddr coords) (round (* (cddr coords) factor))))
('circle
(setf (caar coords) (round (* (caar coords) factor)))
(setf (cdar coords) (round (* (cdar coords) factor)))
(setf (cdr coords) (round (* (cdr coords) factor))))
('poly
(dotimes (i (length coords))
(aset coords i
(round (* (aref coords i) factor))))))))
map)
(defun image-rescale-image-map ()
"Recalculate and set :map property of image at point.
Assumes that image has an :unscaled-map property."
(when-let* ((image (image--get-imagemagick-and-warn))
(unscaled-image (image--image-without-parameters image))
(unscaled-map (image-property image :unscaled-map))
(scale (image--current-scaling image unscaled-image)))
(setf (image-property image :map)
(image--scale-map (copy-tree unscaled-map t) scale))))
(with-current-buffer (get-buffer-create "*image-properties-test*")
(let* ((svg-string "<?xml version=\"1.0\" encoding=\"UTF-8\"
standalone=\"no\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\"\n
\"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n<!-- Generated by
graphviz version 2.43.0 (0)\n -->\n<!-- Title: orggraphview Pages: 1 -->\n<svg
width=\"128pt\" height=\"128pt\"\n viewBox=\"0.00 0.00 127.59 127.59\"
xmlns=\"http://www.w3.org/2000/svg\"
xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n<g id=\"graph0\" class=\"graph\"
transform=\"scale(1 1) rotate(0) translate(4
123.59)\">\n<title>orggraphview</title>\n<polygon fill=\"white\"
stroke=\"transparent\" points=\"-4,4 -4,-123.59 123.59,-123.59 123.59,4
-4,4\"/>\n<!-- a -->\n<g id=\"node1\" class=\"node\">\n<title>a</title>\n<g
id=\"a_node1\"><a xlink:href=\"1\" xlink:title=\"Hover me!\">\n<ellipse
fill=\"none\" stroke=\"black\" cx=\"59.79\" cy=\"-59.79\" rx=\"59.59\"
ry=\"59.59\"/>\n<text text-anchor=\"middle\" x=\"59.79\" y=\"-56.09\"
font-family=\"Times,serif\" font-size=\"14.00\" fill=\"#000000\">Hover
me!</text>\n</a>\n</g>\n</g>\n</g>\n</svg>\n")
(scale 0.75) ; Adjust initial image scale
(unscaled-map '(((circle (85 . 85) . 80) "1" (help-echo
"Surprise!"))))
(map (image--scale-map (copy-tree unscaled-map t) scale))
(image
(create-image svg-string 'svg t
:scale scale :map map :unscaled-map unscaled-map)))
(add-hook 'image-after-change-size-hooks #'image-rescale-image-map nil t)
(erase-buffer)
(insert-image image)
(goto-char (point-min))
(pop-to-buffer (current-buffer)))))
After applying the attached patch, evaluate the above form, press "i +"
and "i -" repeatedly to see the image and its map scale together.
Thanks!
Joseph
0001-Add-image-after-change-size-hooks-image-after-rotate.patch
Description: Text Data
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Joseph Turner, 2024/03/07
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Eli Zaretskii, 2024/03/07
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Joseph Turner, 2024/03/07
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Eli Zaretskii, 2024/03/07
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Joseph Turner, 2024/03/07
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Eli Zaretskii, 2024/03/07
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation,
Joseph Turner <=
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Joseph Turner, 2024/03/08
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Eli Zaretskii, 2024/03/08
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Joseph Turner, 2024/03/08
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Eli Zaretskii, 2024/03/08
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Joseph Turner, 2024/03/21
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Eli Zaretskii, 2024/03/21
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Joseph Turner, 2024/03/22
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Eli Zaretskii, 2024/03/23
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Joseph Turner, 2024/03/23
- bug#69602: 29.1; Image :map should adjust with :scale and :rotation, Eli Zaretskii, 2024/03/23