Subject: Re: bug#70093: Remove unnecessary `image-tests--map-equal'

From: David Ponce <[email-masked]>
Date: Mon, 3 Mar 2025 16:00:37 +0100

On 2025-03-02 20:37, Joseph Turner wrote:
> David Ponce <[email-masked]> writes:
> 
>> On 2025-03-02 05:52, Joseph Turner wrote:
>>> Stefan Kangas <[email-masked]> writes:
>>>
>>>> Eli Zaretskii <[email-masked]> writes:
>>>>
>>>>>> Was this patch installed?
>>>>>
>>>>> No.
>>>>>
>>>>>> Should it be?
>>>>>
>>>>> I'm not sure, and I said so in the discussion.
>>>>
>>>> Now I see that there were some issues with the patch reported by David
>>>> Ponce, but I see no followup to his last message from Joseph.
>>>>
>>>> Joseph, do you still consider this patch a good idea?
>>> Yes.  The stricter tests which I propose in the patch all pass on my
>>> machine.  David, are you able to reproduce this issue with emacs -Q?
>>> Thank you!
>>> Joseph
>>
>> Here here are the results of running image map tests with emacs -Q
> 
> [...]
> 
> Thank you!  In this case, I suppose we should not apply this patch until
> we figure out why the generated image map varies on some machines.
> 
> Joseph

Hello,

I am still trying to understand why the the rotated-map and
flipped-map cases in `image--compute-map-and-original-map' test fails
for me.

I wrote the function `svg-draw-image-map' (see below) to draw in SVG
an image map, in order to help visualize image maps (maybe a such
function could be useful to "kind of debug" image maps?).

I also adapted the code from `image--compute-map-and-original-map'
to be evaluated in the *scratch* buffer, in order to show computed
and reference image maps.

And, for me this reveals that the reference maps `flipped-map' and
`rotated-map' are not as expected, contrary to the corresponding
result of `image--compute-map' which looks as expected.  This explains
why these test case are failing for me.  But I still can't explain
why the same test cases passes for you?

Maybe could you try the code below to see if it help clarify this?

Thanks!

;; Please eval in the *scratch* buffer:

(require 'svg)

;;; Drawing image map.
;;
(defun svg-draw-image-map (svg map color)
   "In SVG, draw image MAP with COLOR."
   (pcase-dolist (`(,area _ _) map)
     (pcase-exhaustive area
       ;; Rectangle hot spot.
       (`(rect . ((,x0 . ,y0) . (,x1 . ,y1)))
        (svg-rectangle svg x0 y0 (- x1 x0) (- y1 y0)
                       :stroke-width 1
                       :stroke color
                       :fill "transparent")
        )
       ;; Circle hot spot.
       (`(circle . ((,x . ,y) . ,r))
        (svg-circle svg x y r
                    :stroke-width 1
                    :stroke color
                    :fill "transparent")
        )
       ;; Polygon hot spot.
       (`(poly . ,coords)
        (let ((i 0) (n (length coords)) points)
          ;; Convert the vector of coords [x0 y0 ...] to a list of
          ;; points ((x0 . y0) ...)
          (while (< i n)
            (let ((x (aref coords i))
                  (y (aref coords (setq i (1+ i)))))
              (push (cons x y) points))
            (setq i (1+ i)))
          (svg-polyline svg points
                        :stroke-width 1
                        :stroke color
                        :fill "transparent"))
        ))))

(let* ((svg-string "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><svg width=\"125pt\" height=\"116pt\" viewBox=\"0.00 0.00 125.00 116.00\" xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><g transform=\"scale(1 1) rotate(0) translate(4 112)\"><polygon fill=\"white\" stroke=\"transparent\" points=\"-4,4 -4,-112 121,-112 121,4 -4,4\"/><a xlink:href=\"a\"><ellipse fill=\"none\" stroke=\"black\" cx=\"27\" cy=\"-90\" rx=\"18\" ry=\"18\"/><text text-anchor=\"middle\" x=\"27\" y=\"-86.3\" fill=\"#000000\">A</text></a><a xlink:href=\"b\"><polygon fill=\"none\" stroke=\"black\" points=\"54,-36 0,-36 0,0 54,0 54,-36\"/><text text-anchor=\"middle\" x=\"27\" y=\"-14.3\" fill=\"#000000\">B</text></a><a xlink:href=\"c\"><ellipse fill=\"none\" stroke=\"black\" cx=\"90\" cy=\"-90\" rx=\"27\" ry=\"18\"/><text text-anchor=\"middle\" x=\"90\" y=\"-86.3\" fill=\"#000000\">C</text></a></g></svg>")
        (original-map
         '(((circle (41 . 29) . 24) "a" (help-echo "A"))
           ((rect (5 . 101) 77 . 149) "b" (help-echo "B"))
           ((poly . [161 29 160 22 154 15 146 10 136 7 125 5 114 7 104 10 96 15 91 22 89 29 91 37 96 43 104 49 114 52 125 53 136 52 146 49 154 43 160 37]) "c" (help-echo "C"))))
        (scaled-map
         '(((circle (82 . 58) . 48) "a" (help-echo "A"))
           ((rect (10 . 202) 154 . 298) "b" (help-echo "B"))
           ((poly . [322 58 320 44 308 30 292 20 272 14 250 10 228 14 208 20 192 30 182 44 178 58 182 74 192 86 208 98 228 104 250 106 272 104 292 98 308 86 320 74]) "c" (help-echo "C"))))
        (flipped-map
         '(((circle (125 . 29) . 24) "a" (help-echo "A"))
           ((rect (89 . 101) 161 . 149) "b" (help-echo "B"))
           ((poly . [5 29 6 22 12 15 20 10 30 7 41 5 52 7 62 10 70 15 75 22 77 29 75 37 70 43 62 49 52 52 41 53 30 52 20 49 12 43 6 37]) "c" (help-echo "C"))))
        (rotated-map
         '(((circle (126 . 41) . 24) "a" (help-echo "A"))
           ((rect (6 . 5) 54 . 77) "b" (help-echo "B"))
           ((poly . [126 161 133 160 140 154 145 146 148 136 150 125 148 114 145 104 140 96 133 91 126 89 118 91 112 96 106 104 103 114 102 125 103 136 106 146 112 154 118 160]) "c" (help-echo "C"))))
        (scaled-rotated-flipped-map
         '(((circle (58 . 82) . 48) "a" (help-echo "A"))
           ((rect (202 . 10) 298 . 154) "b" (help-echo "B"))
           ((poly . [58 322 44 320 30 308 20 292 14 272 10 250 14 228 20 208 30 192 44 182 58 178 74 182 86 192 98 208 104 228 106 250 104 272 98 292 86 308 74 320]) "c" (help-echo "C"))))
        (image (create-image svg-string 'svg t :map scaled-rotated-flipped-map
                             :scale 2 :rotation 90 :flip t))
        )
   ;; Test that `image--compute-original-map' correctly generates
   ;; original-map when creating an already transformed image.
   '(should (image-tests--map-equal (image-property image :original-map)
                                    original-map))
   (or (equal (image-property image :original-map) original-map)
       (error "original-map not as expected"))

   (insert "\nScaled map computed(red) ref(grey)\n")
   (setf (image-property image :flip) nil)
   (setf (image-property image :rotation) 0)
   (setf (image-property image :scale) 2)
   (pcase-let* ((`(,w . ,h) (image-size image t))
                (svg (svg-create w h)))
     (svg-draw-image-map svg (image--compute-map image) "red")
     (svg-draw-image-map svg scaled-map "grey")
     (insert-image (svg-image svg :scale 1)))
   '(should (image-tests--map-equal (image--compute-map image)
                                    scaled-map))

   (insert "\nRotated map computed(red) ref(grey)\n")
   (setf (image-property image :scale) 1)
   (setf (image-property image :rotation) 90)
   (pcase-let* ((`(,w . ,h) (image-size image t))
                (svg (svg-create w h)))
     (svg-draw-image-map svg (image--compute-map image) "red")
     (svg-draw-image-map svg rotated-map "grey")
     (insert-image (svg-image svg :scale 1)))
   '(should (image-tests--map-equal (image--compute-map image)
                                    rotated-map))

   (insert "\nFlipped map computed(red) ref(grey)\n")
   (setf (image-property image :rotation) 0)
   (setf (image-property image :flip) t)
   (pcase-let* ((`(,w . ,h) (image-size image t))
                (svg (svg-create w h)))
     (svg-draw-image-map svg (image--compute-map image) "red")
     (svg-draw-image-map svg rotated-map "grey")
     (insert-image (svg-image svg :scale 1)))
   '(should (image-tests--map-equal (image--compute-map image)
                                    flipped-map))
     
   (insert "\nScaled Rotated Flipped map computed(red) ref(grey)\n")
   (setf (image-property image :scale) 2)
   (setf (image-property image :rotation) 90)
   (pcase-let* ((`(,w . ,h) (image-size image t))
                (svg (svg-create w h)))
     (svg-draw-image-map svg (image--compute-map image) "red")
     (svg-draw-image-map svg scaled-rotated-flipped-map "grey")
     (insert-image (svg-image svg :scale 1)))
   '(should (image-tests--map-equal (image--compute-map image)
                                    scaled-rotated-flipped-map))

   (insert "\n")
   )