0

I want to dynamically create an svg that I can use in an <img/> tag. This in itself is easy; create an svg, set the header and echo the generated parts in their correct place.

The problem is, I want to be able to embed fonts in the svg. I've tried using the @font-face rule in the css of the svg, but that didn't work (MDN says that it only works on Android and Safari).

Is there any cross-browser way to do this?

Solutions I've Considered:

Possible Solution #01:

The solution:

In my main file, create an svg file which uses the @font-face css rule, and then use exec() to use inkscape to convert that svg into another svg, which converts all letters into paths. I then could use echo file_get_contents($inkscape_file) with the correct headers to output it as a svg which can be used with an <img/> tag.

The problem with this:

This creates 2 additional files, so seems very inefficient. Furthermore, since each user will end up generating several images, the space it takes up would grow phenomenally.

Possible Solution #02:

The solution:

Make a template in illustrator, then save it as svg, and tick the embed all glyphs option. Then replace the text & the styles with the options from the PHP script. Use the correct header and output this.

The problem with this:

This severely limits the amount of fonts that can be used, as it is limited to only those which I create a template for. My desired behaviour was to add the option for users to upload their own fonts and use them. This solution does not allow for that.

Additional information that may be of some relevance:

  1. My development server runs fedora, and the production server uses redhat.
  2. The @font-face rule I am currently using is as follows:

    @font-face { font-family: Potato; src: url("/fonts/potato.otf"); }

Sanjuktha
  • 1,065
  • 3
  • 13
  • 26
M. Salman Khan
  • 608
  • 1
  • 6
  • 16

1 Answers1

0

You can't load any external resources declared in the svg from the <img> tag.

The only solutions would be some crappy ways to append the glyphs or the fonts into the svg file itself.
Actually there is a not so crappy way to do it as you found in this answer by lèse-majesté.

The best way is then still IMO to not use an <img> tag to display the svg documents, but rather use an <iframe> or an <object> tag, with the @font-face declared inside the svg file, or even directly include an inline version into the document. These methods do allow the loading of external resources such as fonts.

Then you just have to save the fonts on your server or just an url to the font in the @font-face declaration.

Community
  • 1
  • 1
Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • 1
    Hiya, thanks for answering. I accidentally stumbled across a thread on the graphic design SE, which said to encode the font using base64. (`src: url("data:application/font-woff;charset=utf-8;base64,");`) This worked fine, and it works with the `` tag, but I was wondering if you knew *why* this worked? – M. Salman Khan Dec 29 '15 at 13:55
  • yes, because you actually do append the font as a base64 encoded dataURI version into the svg, no external resources are being loaded there, good idea too :-) Didn't though of this for fonts :-) Could you point me to the post on graphic-design ? This answerer deserves a few upvotes. – Kaiido Dec 29 '15 at 14:20
  • I see, thanks! :) Also, [here is that answer.](http://graphicdesign.stackexchange.com/a/5167) – M. Salman Khan Dec 29 '15 at 17:01
  • @Xhaerithius thanks for the link, added it to an edit. Also, you will still have to parse the svg on our server before sending it to client, so I still do think that if you can just display the svgs in something else than the `` tag it would be easier, if not better. – Kaiido Dec 29 '15 at 17:12
  • The problem is, the image that is generated will be used on a different site (deviantART), which only allows for `` tags. But thanks for the suggestions, I'm sure others who find this thread will find them useful =) – M. Salman Khan Dec 30 '15 at 02:09
  • @Xhaerithius, I though dA [removed the support for svg files](http://mlp-vectorclub.deviantart.com/journal/Recent-dA-updates-and-SVG-files-539084613) (I'm not into dA myself) Then wouldn't a rasterized version has more compatibility? – Kaiido Dec 30 '15 at 03:06
  • they only removed the ability to upload svg files to sta.sh (private storage for users). Svg images with external sources inside ` ` tags still work fine :) – M. Salman Khan Dec 30 '15 at 05:40
  • Then @lèse-majesté 's solution is the best for you, but one other caveat of this method, is that the fonts won't be cached by client's bowser... – Kaiido Dec 30 '15 at 06:18
  • // hypothetical question \\ If it wasn't being used through the img tag, and it was being used on my own site, could I not store the encoded font in a cookie on the user's computer? Would that not have a similar effect to caching it? (Though I presume nothing will have exactly the same speed as if the browser itself cached it...) – M. Salman Khan Dec 31 '15 at 02:06
  • No, unfortunately that won't (if you do display it in img tag). You are embedding the font directly into the svg file, so whenever a user will download one of those svg files, he will have to redownload the fonts. But the browser should cache the svg file with the font embedded. It's just that if you do display 4 svgs, all using `font1.otf`, then the user would have to download 4 times the font, without caching, since the browser won't ever know it is downloading `font1.otf` since it is only downloading `fileX.svg`. – Kaiido Dec 31 '15 at 02:32
  • Storing the fonts on user computer is not an option either, since it would become an external resource, unreachable in the img tag. Using iframe or object or inline svg however, the font will be cached with `file1.svg` and only the svg markup of the 3 other will be downloaded. – Kaiido Dec 31 '15 at 02:32
  • Hmmm but if I set the encoded as a cookie, will it not download the first time, but then for the second time, echo the cookie if it is set? Sorry if this is a silly question. I can't tell if I'm forgetting something important because of my tiredness. :s – M. Salman Khan Dec 31 '15 at 02:44
  • No, **you can't load any external resources declared in an `` tag**. Your cookie will just be an external resource, for the content of the `` tag. Also, for the browser be able to cache anything, your files need to have a name and an origin. Here it has none of it. One possible solution for caching, and rendering into an img tag, would be to first use an ``, an ` – Kaiido Dec 31 '15 at 03:28
  • But seriously, it's easier to just use an iframe and CSS to make it behave as an img. – Kaiido Dec 31 '15 at 03:29
  • I see. Thanks for the info. As for using a DOM parser, will that not increase the time it takes to load by a lot? (I think in my current situation, I'll stick to what I have now, but I still wish to understand the alternatives) – M. Salman Khan Jan 01 '16 at 14:08
  • It will then depends on user's computer's capacities. But normally, a DOMParser is not so slow, but the serialization can be a little bit cumbersome, but we're talking about <100ms operations for very large files. – Kaiido Jan 01 '16 at 14:36