svg-tag-mode icon indicating copy to clipboard operation
svg-tag-mode copied to clipboard

Wrong sizes on high resolution screens

Open tarsius opened this issue 4 years ago • 44 comments

The math seems to be off on high resolution screens, 3840x2160 in my case. I believe I have also tried this on a 2560x1440 screen without any issues, but it has been a while since I had that hooked up, so I am not quite sure anymore.

20210226-00:44:00

Emacs does some weird calling for high resolutions. Again, I don't remember any details but for my moody package I got the create-image to stop calling by some unknown number by telling it to scale by 1 instead, using (create-image ... :scale 1).

Note that it's not just the font size that is off, there also appear some pixels to be missing at the bottom of images.

tarsius avatar Feb 25 '21 23:02 tarsius

Thanks for the report. For the weird calling for high resolution, do you know if this is related to the difference between actual scrren resolution vs system resolution? Also, on your screenshot, what is the font size of text?

rougier avatar Feb 27 '21 11:02 rougier

Just added :scale 1 to the svg image but since I cannot reproduce the bug, it's hard to tell if it has any effect. I also tried changing my system resolution (OSX) and it's still working as expected. What are the values (window-font-width) and (window-font-height)?

rougier avatar Feb 27 '21 11:02 rougier

do you know if this is related to the difference between actual scrren resolution vs system resolution?

I don't know. I am using the monitors native resolution.

Just added :scale 1 to the svg image but since I cannot reproduce the bug, it's hard to tell if it has any effect.

I already tried that. It doesn't seem to do anything.

The only documentation I could find about this is in create-image's doc-string:

If the property `:scale' is not given and the
display has a high resolution (more exactly, when the average width of a
character in the default font is more than 10 pixels), the image is
automatically scaled up in proportion to the default font.
(list (window-font-width)
      (window-font-height))
=> (13 27)

tarsius avatar Mar 01 '21 18:03 tarsius

Could you evaluate

(let* ((w (window-font-width))
       (h (window-font-height))
       (svg (svg-create w h)))
  (svg-rectangle svg 0 0 w h :stroke "black" :fill "none")
  (svg-text svg "A"
            :x           0
            :y           (- h 4)
            :font-family "Roboto Mono Emacs Regular"
            :font-size   14
            :fill        "black")
  (insert-image (svg-image svg :scale 1 :ascent 'center)))

Replacing the font-family and font size with yours. After evaluating the SVG and type "A" just next to the svg image in order to compare SVG text size vs emacs text size?

rougier avatar Mar 01 '21 21:03 rougier

Replacing the font-family and font size with yours.

How does one determine the font size? (face-attribute 'default :height) returns 158, which isn't in the same ballpark as 14.

tarsius avatar Mar 01 '21 21:03 tarsius

Anyway, I think the value is 16, because I have set Emacs.font: Source Code Pro-16 in .Xresources. With that evaluating the above code inserts something invisible that has the correct proportions (i.e. the visual effect is the same as just inserting a plain old space).

tarsius avatar Mar 01 '21 21:03 tarsius

The size is expressed in 1/10th of point hence 158 is 16. If you can't seen the letter, you can :y 0 instead of :y (- h 4)

rougier avatar Mar 01 '21 22:03 rougier

I've figured it out but it will be a few days until I get around to a pull-request.

tarsius avatar Mar 02 '21 15:03 tarsius

If I can contribute to this: I seem to be seeing the same problem on a high-resolution screen, with X set to 144 DPI. Using the test code above, I need to bump the font-size up to 19 to look approximately the same size as a normally-typed A, while my actual font size is 8 (which is not nearly as tiny as it would seem, thanks to the high DPI).

I also note that if I omit the font-size line in the code above, then it does draw as the correct size.

jamesnvc avatar Apr 29 '21 17:04 jamesnvc

You mean font-size in the svg-textpart?

rougier avatar Apr 30 '21 08:04 rougier

You mean font-size in the svg-textpart?

Yessir

jamesnvc avatar Apr 30 '21 11:04 jamesnvc

Hi,

Just tried on windows 10. My screen is hidpi and I can barely see the text within the box

deb75 avatar May 21 '21 15:05 deb75

We're trying to debug it. Can you try code at https://github.com/rougier/svg-tag-mode/pull/14#issuecomment-841776885 (and post in the same thread)?

rougier avatar May 21 '21 15:05 rougier

I'm having the same issue, here's how it looks in org-mode: image

And with the snippet (which I tweaked) you asked to evaluate, in elisp-mode : image

~~With the same snippet, but in emacs-lisp-mode, it does insert something, but it looks to be the wrong size and it's either white-on-white or too small to be seen:~~ Ok, SVGs are only displayed when the major-mode is a text-mode.

I'm on Windows, with Emacs 27.2 a resolution of 2560x1440 and no scaling. Also, I must point out that my emacs configuration is pretty empty at the moment, so it is unlikely it's caused by a conflict with another package or configuration

fstamour avatar Sep 07 '21 14:09 fstamour

Sorry for late answer. Can you try to remove the :scale 1.0 in the svg-image ?

rougier avatar Sep 20 '21 08:09 rougier

Also, can you have a look at https://github.com/rougier/svg-tag-mode/pull/14#issuecomment-899490532 (maybe best to continue discussion on this PR actually)

rougier avatar Sep 20 '21 08:09 rougier

Here, I did some test (I didn't look at the PR yet).

(save-excursion
  (forward-paragraph)
  (progn ;; Delete til end of file
    (delete-region (point) (point-max)))
  (cl-loop
   for font-family in (list "Roboto Mono Emacs Regular" "Roboto Mono" (face-attribute 'default :family)) do
   (cl-loop
    for font-size in (list 14 (face-attribute 'default :height)) do
    (let* ((canvas-scale 8.0)
	   (w (* canvas-scale (window-font-width)))
	   (h (* canvas-scale (window-font-height)))
	   (svg (svg-create w h)))
      (svg-rectangle svg 0 0 w h :stroke "black" :fill "none")
      (svg-text svg "A"
		:x           0
		:y           (- h 4)
		:font-family "Roboto Mono Emacs Regular"
		:font-size   font-size
		:fill        "black")
      (insert "\n")
      (insert "A")
      (insert-image (svg-image svg :scale 1 :ascent 'center))
      (insert-image (svg-image svg :ascent 'center))
      (insert "\t" font-family " - " (format "%s" font-size))))))
(face-attribute 'default :family) ;; => "Courier New"
(face-attribute 'default :height) ;; => 98

image

fstamour avatar Sep 29 '21 13:09 fstamour

Ok, @rougier I took a look at the comment you linked and I added the code next to what I tried, it work very well:

image

The whole shebang
(save-excursion
  (forward-paragraph)
  (progn ;; Delete til end of file
    (delete-region (point) (point-max)))
  (cl-loop
   for font-family in (list ;; "Roboto Mono Emacs Regular"
		       "Roboto Mono"
		       (face-attribute 'default :family))
   do
   (cl-loop
    for font-size in (list 14
			   (face-attribute 'default :height)
			   (elt (query-font (font-at (point-min))) 3))
    do
    (let* ((canvas-scale (+ 0.5 (/ font-size 14)))
	   (w (* canvas-scale (window-font-width)))
	   (h (* canvas-scale (window-font-height)))
	   (svg (svg-create w h)))
      (svg-rectangle svg 0 0 w h :stroke "black" :fill "none")
      (svg-text svg "A"
		:x           0
		:y           (- h 4)
		:font-family "Roboto Mono Emacs Regular"
		:font-size   font-size
		:fill        "black")
      (insert "\n")
      (insert "A")
      (insert-image (svg-image svg :scale 1 :ascent 'center))
      (insert-image (svg-image svg :ascent 'center))
      (insert "\t" font-family " - " (format "%s" font-size) " ")
      (let* ((text "Hello guys!")
	     (font       (query-font (font-at (point-min))))
	     (font-size  (elt font 2))
	     (family     (face-attribute 'default :family))
	     (descent    (elt font 4))
	     (ascent     (elt font 5))
	     (svg-height (+ ascent descent))
	     (char-width (elt font 7))
	     (svg-width  (* char-width (length text)))
	     (svg        (svg-create svg-width svg-height)))
	(svg-rectangle svg 0 0 svg-width svg-height :stroke "black" :fill "none")
	(svg-text svg text
		  :fill "red"
		  :stroke-width 0
		  :font-family family
		  :font-weight "300"
		  :font-size font-size
		  :x 0
		  :y descent)
	(insert-image (svg-image svg :ascent 'center)))
      ))))
(face-attribute 'default :family) ;; => "Courier New"
(face-attribute 'default :height) ;; => 98
(font-at (point)) ;; =>  #<font-object "-outline-Fira Mono-normal-normal-normal-mono-13-*-*-*-c-*-iso8859-1">

fstamour avatar Sep 29 '21 13:09 fstamour

Thanks for these tests. The last version seems better but the baseline seems a bit off.

rougier avatar Oct 04 '21 09:10 rougier

Hello,

I come back to this thread because I still have this issue.

My configuration is emacs master from a couple of weeks on windows 11 and on a hidpi screen (3000x2000). The default display zoom is 250%.

Here is an org file without ``svg-tag-mode` :

emacs1

Then Alt X svg-tag-mode gives :

emacs2

The svg are sensibly bigger than the text.

I digged a little in svg-tag-make, looking for a scale option as an example, but did not find anything useful.

Because images are svg, I am quite convinced that there should exist an easy way to rescale images. For example, if you are a math-preview user, there is an option to make the svg bigger or smaller.

I would love to use svg-tag-mode more extensively. How could I fix this issue ?

Regards

EDIT : it happens only with a hidpi screen with a zoom applied. With another screen, svg sizes are correct

deb75 avatar Apr 03 '22 12:04 deb75

Any hints ?

deb75 avatar Apr 05 '22 20:04 deb75

Where does the zoom comes from exactly ? From outside emacs?

rougier avatar Apr 08 '22 17:04 rougier

Yes, this is a zoom applied by windows 11.

By tweaking some parameters in svg-lib functions, I managed to get something better, not yet usable though. It seems that the scale parameter is ignored.

This issue definitely comes from the screen zoom. With another computer (same emacs config) and another screen, which does not need zooming, the text and its svg counter part are equivalent in size and appearance.

I do not remember the tweaks but I will let you know as soon as I have time.

Regards

deb75 avatar Apr 09 '22 12:04 deb75

It might be possible to retrieve the magnification factor from inside emacs but I'm not sure how. Maybe through DPI computation. See also https://emacs.stackexchange.com/questions/28390/quickly-adjusting-text-to-dpi-changes

rougier avatar Apr 11 '22 08:04 rougier

Yes, but then, how to use it ? as an argument to svg-tag-make ?

I will try do debug that soon.

Regards

deb75 avatar Apr 13 '22 08:04 deb75

Not sure how to use it, but most probably you can use the zoom factor for char-height and char-width.

rougier avatar Apr 21 '22 13:04 rougier

Hi,

I was able to correct my issue by manually modifying the font-size and height parameters which are given to svg-lib-tag function.

This is only a workaround. I plan to uncomment the scale parameter in svg-lib-tag and define a default scale value which will manually adjust the font size (character width and height) and the svg height.

Regards

deb75 avatar Jun 19 '22 14:06 deb75

Yes, but the idea is to have all of these calculations to be automated. It seems to be a reccuring problem though. Each time we solve one case, a new one pops out... Best would be to understand the origin of the problem or to find a parameter we could use.

rougier avatar Jun 21 '22 08:06 rougier

I finally got it working by modifying the svg-lib-tag function :

(defun svg-lib-tag (label &optional style &rest args)
  "Create an image displaying LABEL in a rounded box using given STYLE
and style elements ARGS."

  (let* ((default svg-lib-style-default)
         (style (if style (apply #'svg-lib-style nil style) default))
         (style (if args  (apply #'svg-lib-style style args) style))

         (foreground  (plist-get style :foreground))
         (background  (plist-get style :background))

         (crop-left   (plist-get style :crop-left))
         (crop-right  (plist-get style :crop-right))

         (alignment   (plist-get style :alignment))
         (stroke      (plist-get style :stroke))
         (width       (plist-get style :width))
         (height      (plist-get style :height))
         (radius      (plist-get style :radius))
         ;; (scale       (plist-get style :scale))
         (margin      (plist-get style :margin))
         (padding     (plist-get style :padding))
         (font-size   (plist-get style :font-size))
         (font-family (plist-get style :font-family))
         (font-weight (plist-get style :font-weight))

         (txt-char-width  (plist-get style :txt-char-width))
         (txt-char-height (plist-get style :txt-char-height))

         (txt-char-height (if line-spacing
                              (+ txt-char-height line-spacing)
                          txt-char-height))
         (font-info       (font-info (format "%s-%d" font-family font-size)))
         (font-size       (aref font-info 2)) ;; redefine font-size
         (ascent          (aref font-info 8))
         (tag-char-width  (aref font-info 11))
         ;; (tag-char-height (aref font-info 3))
         (tag-width       (* width (* (+ (length label) padding) txt-char-width)))
         (tag-height      (* txt-char-height height))

         (svg-width       (+ tag-width (* margin txt-char-width width)))
         (svg-height      tag-height)

         (tag-x  (* (- svg-width tag-width)  alignment))
         (text-x (+ tag-x (/ (- tag-width (* (length label) tag-char-width)) 2)))
         (text-y ascent)

         (tag-x      (if crop-left  (- tag-x     txt-char-width) tag-x))
         (tag-width  (if crop-left  (+ tag-width txt-char-width) tag-width))
         (text-x     (if crop-left  (- text-x (/ stroke 2)) text-x))
         (tag-width  (if crop-right (+ tag-width txt-char-width) tag-width))
         (text-x     (if crop-right (+ text-x (/ stroke 2)) text-x))

         (svg (svg-create svg-width svg-height)))

    (if (>= stroke 0.25)
        (svg-rectangle svg tag-x 0 tag-width tag-height
                           :fill foreground :rx radius))
    (svg-rectangle svg (+ tag-x (/ stroke 2.0)) (/ stroke 2.0)
                       (- tag-width stroke) (- tag-height stroke)
                       :fill background :rx (- radius (/ stroke 2.0)))
    (svg-text svg label
              :font-family font-family :font-weight font-weight  :font-size font-size
              :fill foreground :x text-x :y  text-y)
    (svg-lib--image svg :ascent 'center)))

where I introduced txt-char-width and txt-char-height. Those appears to be badly set by respectively window-font-width and window-font-height functions.

I also uncommented the width parameter which acts like the height one.

Then, to get a svg with correct size appearance, I have to call svg-lib-tag as follows :

(svg-lib-tag "TODO" nil :height 0.5 :width 0.5 :font-size 8

Regards

deb75 avatar Aug 03 '22 00:08 deb75

The 0.5 is because of your desktop magnification?

rougier avatar Aug 08 '22 15:08 rougier