unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Mechanism to scale SVG images when default face height changes?
@ 2023-09-18 17:42 Jimmy Yuen Ho Wong
  2023-09-18 17:53 ` Eli Zaretskii
  2023-09-18 18:19 ` Alan Third
  0 siblings, 2 replies; 10+ messages in thread
From: Jimmy Yuen Ho Wong @ 2023-09-18 17:42 UTC (permalink / raw)
  To: Emacs-Devel devel

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

Hi everyone,

all-the-icons maintainer here. Recently I've converted all-the-icons from
using icon-fonts to SVGs. A few early testers of this branch have reported
that when they resize the default face, either by text-scale-mode, loading
a different theme or setting the default face size attributes manually, the
SVG icons inserted into the buffers do not scale accordingly.

In the SVG branch in all-the-icons, all the icons are inserted with a
`:width` and `:height` properties set on the image, and the face is applied
to the propertized string. i.e.

```elisp
ELISP> (all-the-icons-icon-for-file "test.js")
#("" 0 1
  (face all-the-icons-lpurple font-lock-face all-the-icons-lpurple
fontified t display
        (image :type svg :data "<svg viewBox=\"0 0 512 512\" width=\"512\"
height=\"512\"> <path d=\"...snip...\"></path></svg>" :scale 1
:transform-smoothing t :width 14 :height 14 :ascent center :margin 1)
        front-sticky nil rear-nonsticky t))
```

As far as I understand, simply adjusting the scale factor of the image will
suffice. The problem is, since Emacs doesn't do it by itself, I don't
really know how to do it in Elisp and be performant. Are there any hooks or
internal undocumented functions that I can use to scale all the images in
all of the frames when the default face size changes?

Thanks,

Jimmy Yuen Ho Wong

[-- Attachment #2: Type: text/html, Size: 1667 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Mechanism to scale SVG images when default face height changes?
  2023-09-18 17:42 Mechanism to scale SVG images when default face height changes? Jimmy Yuen Ho Wong
@ 2023-09-18 17:53 ` Eli Zaretskii
  2023-09-18 19:16   ` Jimmy Yuen Ho Wong
  2023-09-18 18:19 ` Alan Third
  1 sibling, 1 reply; 10+ messages in thread
From: Eli Zaretskii @ 2023-09-18 17:53 UTC (permalink / raw)
  To: Jimmy Yuen Ho Wong; +Cc: emacs-devel

> From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
> Date: Mon, 18 Sep 2023 18:42:33 +0100
> 
> As far as I understand, simply adjusting the scale factor of the image will suffice. The problem is,
> since Emacs doesn't do it by itself, I don't really know how to do it in Elisp and be performant. Are
> there any hooks or internal undocumented functions that I can use to scale all the images in all of the
> frames when the default face size changes?

Are you aware of the function image--change-size?



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Mechanism to scale SVG images when default face height changes?
  2023-09-18 17:42 Mechanism to scale SVG images when default face height changes? Jimmy Yuen Ho Wong
  2023-09-18 17:53 ` Eli Zaretskii
@ 2023-09-18 18:19 ` Alan Third
  2023-09-18 19:10   ` Jimmy Yuen Ho Wong
  1 sibling, 1 reply; 10+ messages in thread
From: Alan Third @ 2023-09-18 18:19 UTC (permalink / raw)
  To: Jimmy Yuen Ho Wong; +Cc: Emacs-Devel devel

On Mon, Sep 18, 2023 at 06:42:33PM +0100, Jimmy Yuen Ho Wong wrote:
> In the SVG branch in all-the-icons, all the icons are inserted with a
> `:width` and `:height` properties set on the image, and the face is applied
> to the propertized string. i.e.
> 
> ```elisp
> ELISP> (all-the-icons-icon-for-file "test.js")
> #("" 0 1
>   (face all-the-icons-lpurple font-lock-face all-the-icons-lpurple
> fontified t display
>         (image :type svg :data "<svg viewBox=\"0 0 512 512\" width=\"512\"
> height=\"512\"> <path d=\"...snip...\"></path></svg>" :scale 1
> :transform-smoothing t :width 14 :height 14 :ascent center :margin 1)
>         front-sticky nil rear-nonsticky t))
> ```

Do you need to set the size in pixels? If you set the size in em's
(from Emacs 28 up) then it will scale automatically.

-- 
Alan Third



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Mechanism to scale SVG images when default face height changes?
  2023-09-18 18:19 ` Alan Third
@ 2023-09-18 19:10   ` Jimmy Yuen Ho Wong
  2023-09-18 19:37     ` Alan Third
  0 siblings, 1 reply; 10+ messages in thread
From: Jimmy Yuen Ho Wong @ 2023-09-18 19:10 UTC (permalink / raw)
  To: Alan Third, Jimmy Yuen Ho Wong, Emacs-Devel devel

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

Ah, I was looking at
https://www.gnu.org/software/emacs/manual/html_node/elisp/Pixel-Specification.html,
this isn't documented but indeed it scales.

```elisp
#("" 0 1
  (face all-the-icons-lpurple font-lock-face all-the-icons-lpurple
fontified t display
        (image :type svg :data "<svg viewBox=\"0 0 512 512\" width=\"512\"
height=\"512\"> <path d=\"...snip...\"></path></svg>" :scale 1
:transform-smoothing t :width (1 . em) :ascent center :margin 1)
        front-sticky nil rear-nonsticky t))
```

But this doesn't seem to work, I suppose px is not a unit?

```elisp
#("" 0 1
  (face all-the-icons-lpurple font-lock-face all-the-icons-lpurple
fontified t display
        (image :type svg :data "<svg viewBox=\"0 0 512 512\" width=\"512\"
height=\"512\"> <path d=\"...snip...\"></path></svg>" :scale 1
:transform-smoothing t :width (- (1 . em) (1 . px)) :ascent center :margin
1)
        front-sticky nil rear-nonsticky t))
```

I like this approach a lot, but I do need pixel precision calculated on
demand because I need to add a 1px margin between icons. If I don't
subtract 2 px back from the dimensions, the icons will be wider than a
character.

Jimmy


On Mon, Sep 18, 2023 at 7:19 PM Alan Third <alan@idiocy.org> wrote:

> On Mon, Sep 18, 2023 at 06:42:33PM +0100, Jimmy Yuen Ho Wong wrote:
> > In the SVG branch in all-the-icons, all the icons are inserted with a
> > `:width` and `:height` properties set on the image, and the face is
> applied
> > to the propertized string. i.e.
> >
> > ```elisp
> > ELISP> (all-the-icons-icon-for-file "test.js")
> > #("" 0 1
> >   (face all-the-icons-lpurple font-lock-face all-the-icons-lpurple
> > fontified t display
> >         (image :type svg :data "<svg viewBox=\"0 0 512 512\"
> width=\"512\"
> > height=\"512\"> <path d=\"...snip...\"></path></svg>" :scale 1
> > :transform-smoothing t :width 14 :height 14 :ascent center :margin 1)
> >         front-sticky nil rear-nonsticky t))
> > ```
>
> Do you need to set the size in pixels? If you set the size in em's
> (from Emacs 28 up) then it will scale automatically.
>
> --
> Alan Third
>

[-- Attachment #2: Type: text/html, Size: 3109 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Mechanism to scale SVG images when default face height changes?
  2023-09-18 17:53 ` Eli Zaretskii
@ 2023-09-18 19:16   ` Jimmy Yuen Ho Wong
  0 siblings, 0 replies; 10+ messages in thread
From: Jimmy Yuen Ho Wong @ 2023-09-18 19:16 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: emacs-devel

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

Is there anything where I don't have to specify the position of every icon
in every frame?

Jimmy


On Mon, Sep 18, 2023 at 6:53 PM Eli Zaretskii <eliz@gnu.org> wrote:

> > From: Jimmy Yuen Ho Wong <wyuenho@gmail.com>
> > Date: Mon, 18 Sep 2023 18:42:33 +0100
> >
> > As far as I understand, simply adjusting the scale factor of the image
> will suffice. The problem is,
> > since Emacs doesn't do it by itself, I don't really know how to do it in
> Elisp and be performant. Are
> > there any hooks or internal undocumented functions that I can use to
> scale all the images in all of the
> > frames when the default face size changes?
>
> Are you aware of the function image--change-size?
>

[-- Attachment #2: Type: text/html, Size: 1219 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Mechanism to scale SVG images when default face height changes?
  2023-09-18 19:10   ` Jimmy Yuen Ho Wong
@ 2023-09-18 19:37     ` Alan Third
  2023-09-18 19:55       ` Jimmy Yuen Ho Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Alan Third @ 2023-09-18 19:37 UTC (permalink / raw)
  To: Jimmy Yuen Ho Wong; +Cc: Emacs-Devel devel

On Mon, Sep 18, 2023 at 08:10:59PM +0100, Jimmy Yuen Ho Wong wrote:
> Ah, I was looking at
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Pixel-Specification.html,
> this isn't documented but indeed it scales.

Ems are only available for images, afaik:

https://www.gnu.org/software/emacs/manual/html_node/elisp/Image-Descriptors.html

> But this doesn't seem to work, I suppose px is not a unit?
> 
> ```elisp
> #("" 0 1
>   (face all-the-icons-lpurple font-lock-face all-the-icons-lpurple
> fontified t display
>         (image :type svg :data "<svg viewBox=\"0 0 512 512\" width=\"512\"
> height=\"512\"> <path d=\"...snip...\"></path></svg>" :scale 1
> :transform-smoothing t :width (- (1 . em) (1 . px)) :ascent center :margin
> 1)
>         front-sticky nil rear-nonsticky t))
> ```

Hmm, yeah it only supports ems in that format, and it's not clever
enough to be able to do arithmetic on it. The conversion from ems to
pixels is done when the image is to be displayed.

> I like this approach a lot, but I do need pixel precision calculated on
> demand because I need to add a 1px margin between icons. If I don't
> subtract 2 px back from the dimensions, the icons will be wider than a
> character.

I suppose you could calculate the number of ems required by
doing something like...

      ((/ (- font-px-size 1) font-px-size) . 'em)

But while that would scale on demand, it wouldn't scale properly
because the calculation is done before the user changes the font size.

I can't think of any way round it, or even any practical way to extend
the current mechanism.

-- 
Alan Third



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Mechanism to scale SVG images when default face height changes?
  2023-09-18 19:37     ` Alan Third
@ 2023-09-18 19:55       ` Jimmy Yuen Ho Wong
  2023-09-18 20:53         ` Alan Third
  0 siblings, 1 reply; 10+ messages in thread
From: Jimmy Yuen Ho Wong @ 2023-09-18 19:55 UTC (permalink / raw)
  To: Alan Third, Jimmy Yuen Ho Wong, Emacs-Devel devel

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

On Mon, Sep 18, 2023 at 8:37 PM Alan Third <alan@idiocy.org> wrote:

> On Mon, Sep 18, 2023 at 08:10:59PM +0100, Jimmy Yuen Ho Wong wrote:
> > Ah, I was looking at
> >
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Pixel-Specification.html
> ,
> > this isn't documented but indeed it scales.
>
> Ems are only available for images, afaik:
>
>
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Image-Descriptors.html
>
> > But this doesn't seem to work, I suppose px is not a unit?
> >
> > ```elisp
> > #("" 0 1
> >   (face all-the-icons-lpurple font-lock-face all-the-icons-lpurple
> > fontified t display
> >         (image :type svg :data "<svg viewBox=\"0 0 512 512\"
> width=\"512\"
> > height=\"512\"> <path d=\"...snip...\"></path></svg>" :scale 1
> > :transform-smoothing t :width (- (1 . em) (1 . px)) :ascent center
> :margin
> > 1)
> >         front-sticky nil rear-nonsticky t))
> > ```
>
> Hmm, yeah it only supports ems in that format, and it's not clever
> enough to be able to do arithmetic on it. The conversion from ems to
> pixels is done when the image is to be displayed.
>
> > I like this approach a lot, but I do need pixel precision calculated on
> > demand because I need to add a 1px margin between icons. If I don't
> > subtract 2 px back from the dimensions, the icons will be wider than a
> > character.
>
> I suppose you could calculate the number of ems required by
> doing something like...
>
>       ((/ (- font-px-size 1) font-px-size) . 'em)
>
> But while that would scale on demand, it wouldn't scale properly
> because the calculation is done before the user changes the font size.
>
> I can't think of any way round it, or even any practical way to extend
> the current mechanism.
>
>
Sad face :(. I suppose what I'm really looking for is to extend the pixel
specification mini language to support something like CSS' calc()
<https://developer.mozilla.org/en-US/docs/Web/CSS/calc> function, where it
can do arithmetic on both relative and absolute units.

Is that possible? For my specific purpose, having `:margin` to support
floating point em will also suffice, but that doesn't seem to work at the
moment.


> --
> Alan Third
>

[-- Attachment #2: Type: text/html, Size: 3282 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Mechanism to scale SVG images when default face height changes?
  2023-09-18 19:55       ` Jimmy Yuen Ho Wong
@ 2023-09-18 20:53         ` Alan Third
  2023-09-18 21:04           ` Jimmy Yuen Ho Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Alan Third @ 2023-09-18 20:53 UTC (permalink / raw)
  To: Jimmy Yuen Ho Wong; +Cc: Emacs-Devel devel

On Mon, Sep 18, 2023 at 08:55:55PM +0100, Jimmy Yuen Ho Wong wrote:
> On Mon, Sep 18, 2023 at 8:37 PM Alan Third <alan@idiocy.org> wrote:
> 
> > On Mon, Sep 18, 2023 at 08:10:59PM +0100, Jimmy Yuen Ho Wong wrote:
> > > Ah, I was looking at
> > >
> > https://www.gnu.org/software/emacs/manual/html_node/elisp/Pixel-Specification.html
> > ,
<snip>
> >
> > I suppose you could calculate the number of ems required by
> > doing something like...
> >
> >       ((/ (- font-px-size 1) font-px-size) . 'em)
> >
> > But while that would scale on demand, it wouldn't scale properly
> > because the calculation is done before the user changes the font size.
> >
> > I can't think of any way round it, or even any practical way to extend
> > the current mechanism.
> >
> >
> Sad face :(. I suppose what I'm really looking for is to extend the pixel
> specification mini language to support something like CSS' calc()
> <https://developer.mozilla.org/en-US/docs/Web/CSS/calc> function, where it
> can do arithmetic on both relative and absolute units.
> 
> Is that possible?

I didn't actually know about the pixel specification language before
now. It seems to me like it would make sense to teach the image code
to understand it too and add ems to it, but since I know nothing about
it I can't say if that's practical or not.

> For my specific purpose, having `:margin` to support
> floating point em will also suffice, but that doesn't seem to work at the
> moment.

Indeed, this would actually be quite simple, but it won't help you now
as it won't be available until Emacs 30.

All I can suggest for compatibility with current versions of Emacs is
to wrap the SVG's within other SVGs. We do this internally in Emacs to
implement vector scaling and you could probably do something similar,
although I'm not sure exactly how much control you could get from it.

For example, you can do something like:

<svg xmlns:xlink="http://www.w3.org/1999/xlink"
 xmlns:xi="http://www.w3.org/2001/XInclude"
 width="1em" height="1em" preserveAspectRatio="none">
  <xi:include href="data:image/svg+xml;base64,<base64 encoded SVG data>">
  </xi:include>
</svg>

It should be possible to scale down the embedded image to leave a gap
around it, but I'd have to go and investigate how to do it.

I recommend base64 encoding the SVG data as shown above, because
directly embedding the SVG text can be problematic unless it's very
simple.
-- 
Alan Third



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Mechanism to scale SVG images when default face height changes?
  2023-09-18 20:53         ` Alan Third
@ 2023-09-18 21:04           ` Jimmy Yuen Ho Wong
  2023-09-20 19:12             ` Alan Third
  0 siblings, 1 reply; 10+ messages in thread
From: Jimmy Yuen Ho Wong @ 2023-09-18 21:04 UTC (permalink / raw)
  To: Alan Third, Jimmy Yuen Ho Wong, Emacs-Devel devel

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

On Mon, Sep 18, 2023 at 9:53 PM Alan Third <alan@idiocy.org> wrote:

> On Mon, Sep 18, 2023 at 08:55:55PM +0100, Jimmy Yuen Ho Wong wrote:
> > On Mon, Sep 18, 2023 at 8:37 PM Alan Third <alan@idiocy.org> wrote:
> >
> > > On Mon, Sep 18, 2023 at 08:10:59PM +0100, Jimmy Yuen Ho Wong wrote:
> > > > Ah, I was looking at
> > > >
> > >
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Pixel-Specification.html
> > > ,
> <snip>
> > >
> > > I suppose you could calculate the number of ems required by
> > > doing something like...
> > >
> > >       ((/ (- font-px-size 1) font-px-size) . 'em)
> > >
> > > But while that would scale on demand, it wouldn't scale properly
> > > because the calculation is done before the user changes the font size.
> > >
> > > I can't think of any way round it, or even any practical way to extend
> > > the current mechanism.
> > >
> > >
> > Sad face :(. I suppose what I'm really looking for is to extend the pixel
> > specification mini language to support something like CSS' calc()
> > <https://developer.mozilla.org/en-US/docs/Web/CSS/calc> function, where
> it
> > can do arithmetic on both relative and absolute units.
> >
> > Is that possible?
>
> I didn't actually know about the pixel specification language before
> now. It seems to me like it would make sense to teach the image code
> to understand it too and add ems to it, but since I know nothing about
> it I can't say if that's practical or not.
>
> > For my specific purpose, having `:margin` to support
> > floating point em will also suffice, but that doesn't seem to work at the
> > moment.
>
> Indeed, this would actually be quite simple, but it won't help you now
> as it won't be available until Emacs 30.
>
> All I can suggest for compatibility with current versions of Emacs is
> to wrap the SVG's within other SVGs. We do this internally in Emacs to
> implement vector scaling and you could probably do something similar,
> although I'm not sure exactly how much control you could get from it.
>
> For example, you can do something like:
>
> <svg xmlns:xlink="http://www.w3.org/1999/xlink"
>  xmlns:xi="http://www.w3.org/2001/XInclude"
>  width="1em" height="1em" preserveAspectRatio="none">
>   <xi:include href="data:image/svg+xml;base64,<base64 encoded SVG data>">
>   </xi:include>
> </svg>
>
> It should be possible to scale down the embedded image to leave a gap
> around it, but I'd have to go and investigate how to do it.
>
> I recommend base64 encoding the SVG data as shown above, because
> directly embedding the SVG text can be problematic unless it's very
> simple.
> --
> Alan Third
>

Thank you! I'll report back once I've played around with SVG wrappers.

Thanks

[-- Attachment #2: Type: text/html, Size: 4008 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Mechanism to scale SVG images when default face height changes?
  2023-09-18 21:04           ` Jimmy Yuen Ho Wong
@ 2023-09-20 19:12             ` Alan Third
  0 siblings, 0 replies; 10+ messages in thread
From: Alan Third @ 2023-09-20 19:12 UTC (permalink / raw)
  To: Jimmy Yuen Ho Wong; +Cc: Emacs-Devel devel

On Mon, Sep 18, 2023 at 10:04:17PM +0100, Jimmy Yuen Ho Wong wrote:
> 
> Thank you! I'll report back once I've played around with SVG wrappers.

Best of luck with it. If I can help you any more, please let me know.
-- 
Alan Third



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2023-09-20 19:12 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-09-18 17:42 Mechanism to scale SVG images when default face height changes? Jimmy Yuen Ho Wong
2023-09-18 17:53 ` Eli Zaretskii
2023-09-18 19:16   ` Jimmy Yuen Ho Wong
2023-09-18 18:19 ` Alan Third
2023-09-18 19:10   ` Jimmy Yuen Ho Wong
2023-09-18 19:37     ` Alan Third
2023-09-18 19:55       ` Jimmy Yuen Ho Wong
2023-09-18 20:53         ` Alan Third
2023-09-18 21:04           ` Jimmy Yuen Ho Wong
2023-09-20 19:12             ` Alan Third

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).