unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Joseph Turner <joseph@ushin.org>
To: Stephen Berman <stephen.berman@gmx.net>
Cc: Juri Linkov <juri@linkov.net>,
	Emacs Devel Mailing List <emacs-devel@gnu.org>
Subject: Re: Retain image properties after image-mode commands
Date: Tue, 05 Mar 2024 23:51:51 -0800	[thread overview]
Message-ID: <87r0gng41l.fsf@ushin.org> (raw)
In-Reply-To: <87wmqg8v12.fsf@gmx.net>

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

Stephen Berman <stephen.berman@gmx.net> writes:

> On Tue, 05 Mar 2024 18:34:07 +0200 Juri Linkov <juri@linkov.net> wrote:
>
>>> Then zoom in on the image: Interactively run `image-transform-set-scale'
>>> by pressing "s s" then type the number 2 and press RET.
>>
>> Instead of "s s" you can use "i +" that works correctly.
>> Thus "s s 2 RET" is equivalent to "2 0 i +".

Good point!

> When I do this, the region in which the tooltip is activated does not
> increase: with the enlarged image the tooltip only appears when the
> mouse hovers over part of the upper left section of the large circle,
> and the adjacent region outside of the circumference of the circle
> (i.e., exactly the region occupied by the original circle AFAICT).

My experience matches Steve's; neither `image-increase-size' nor
`image-transform-set-scale' scales the image map with the image.

The attached patch attempts to scale the :map image property whenever
the :scale property changes.  After applying it, run this snippet:

(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")
        (map '(((circle (85 . 85) . 80) "1" (help-echo "Surprise!"))))
        (inhibit-read-only t))
    (erase-buffer)
    (insert-image (create-image svg-string 'svg t :map map) svg-string)
    (goto-char (point-min))
    (pop-to-buffer (current-buffer))))

Press "i +".  Now the tooltip and image should line up correctly.

The patch doesn't quite work correctly. Since image map coordinates must
be integers, they are scaled then rounded in the patch. However, if you
repeatedly increase and decrease the image size ("i +", then "+" & "-"),
eventually the image map drifts from the rendered image.

An untested potential solution is to add another image property
:unscaled-map, containing an image map which corresponds to the image
with :scale 1.  Then each time the image is scaled, we calculate the new
:map based on the :unscaled-map, avoiding the drift.

The :unscaled-map solution may even be able to handle image rotation...

Thoughts?

Thanks!

Joseph


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Scale-image-map-property-according-to-image-scale.patch --]
[-- Type: text/x-diff, Size: 1863 bytes --]

From a3bf934ad872999d0e63f0757429621b4e4b082c Mon Sep 17 00:00:00 2001
From: Joseph Turner <joseph@breatheoutbreathe.in>
Date: Wed, 6 Mar 2024 00:16:24 -0800
Subject: [PATCH] Scale image :map property according to image :scale

* lisp/image.el (image--scale-map): Add function to scale an image map.
(image--change-size): Use image--scale-map internally.
---
 lisp/image.el | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/lisp/image.el b/lisp/image.el
index 2ebce59a98c..48c38a0c9ec 100644
--- a/lisp/image.el
+++ b/lisp/image.el
@@ -1269,7 +1269,28 @@ image--change-size
          (new-image (image--image-without-parameters image))
          (scale (image--current-scaling image new-image)))
     (setcdr image (cdr new-image))
-    (plist-put (cdr image) :scale (* scale factor))))
+    (plist-put (cdr image) :scale (* scale factor))
+    (setf (image-property new-image :map)
+          (image--scale-map (image-property new-image :map) factor))))
+
+(defun image--scale-map (map factor)
+  "Scale MAP by FACTOR, destructively modifying it."
+  (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--image-without-parameters (image)
   (cons (pop image)
-- 
2.41.0


  reply	other threads:[~2024-03-06  7:51 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-03-04  6:07 Retain image properties after image-mode commands Joseph Turner
2024-03-05 16:34 ` Juri Linkov
2024-03-05 17:10   ` Stephen Berman
2024-03-06  7:51     ` Joseph Turner [this message]
2024-03-08  7:33       ` Joseph Turner

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=87r0gng41l.fsf@ushin.org \
    --to=joseph@ushin.org \
    --cc=emacs-devel@gnu.org \
    --cc=juri@linkov.net \
    --cc=stephen.berman@gmx.net \
    /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).