Convert SVG to PNG with embeded base64 fonts - node.js

I have a nodeJS backend with a service to convert SVG files to PNG.
I used to use phantomJS to do that, and never had any problem, but performance was really bad.
I'm looking for a performatic way of doing this.
Right now I'm using RSVG, and it works perfectly except for fonts.
Currently we embed our fonts inside SVG file using something like this:
<defs>
<style type="text/css">
#font-face {
font-family: 'BoomBoom';
src: url('data:application/x-font-ttf;base64,[base-encoded font here]');
}
</style>
</defs>
In browsers this works perfectly, but RSVG does not seems to work with embedded base64 fonts.
Does anyone have a suggestion?

Related

Problem with imported stylesheet in svg file after webpack processing

According to https://www.w3.org/TR/SVG/styling.html#StylingWithCSS, in order to configure svg to use styles defined in an external stylesheet, you can import them as follows:
<svg xmlns="http://www.w3.org/2000/svg">
<style>
#import url(mystyles.css);
</style>
<rect .../>
</svg>
This works fine in Chrome when the files exist in their original format, whether served from a web server or read from the local filesystem, but after building with webpack the resulting app's svg elements have no styling, so clearly the stylesheet isn't getting found.
All of the searches I've done turn up lots of info on what is more or less the reverse operation - referencing svg files from within css (e.g., to specify an svg image as the background for an element).
Does anyone know of a webpack plugin and/or configuration specifically for this case?

SVG image not displaying in mozilla firefox

I am using Angular7 and trying to load SVG image as an Object element. when I do ng serve and open the URL in firefox its not loading svg file. In chrome its working perfectly fine. and If I open the svg file directly(not through the angular application) in firefox it is loading.
I have tried viewbox and height & width and all but still same problem.
<object id="svg1" data="assets/12455_01.svg" type="image/svg+xml" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></object>
inside my svg root element I have viewbox as: viewBox="-36.52 -2607.7 2723 2621"
css file:
object{
width:100%;
height: 80vh;
}
I want to display the svg file provided in Object element when I load/run the application in all kinds of browsers.
I got it fixed myself, but not sure whether this is correct approach. I have set the path and type through ngOnInit like below and it got loaded successfully.
ngOnInit(){
let obj = document.getElementById("svg1");
obj.setAttribute('data', this.svgPath);
obj.setAttribute('type', "image/svg+xml");
}

SVG background-image not appearing on IE11

https://codepen.io/leftynaut/pen/PKwEqz
Any idea what I am doing wrong with my svg background image here to make them not show up on IE11?
(jQuery acting up on IE also, but my actual implementation with Angular is working fine)
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 400 400'><path fill='#000000' d='M192,32 C103.75,32 32,103.75 32,192 C32,280.25 103.75,352 192,352 C280.25,352 352,280.25 352,192 C352,103.75 280.25,32 192,32 Z M384,192 C384,298 298,384 192,384 C86,384 0,298 0,192 C0,86 86,0 192,0 L192,0 C298,0 384,86 384,192 Z'></path></svg>") no-repeat center;
I recently discovered that Internet Explorer is a bit picky with the format of the URL in background-image property. Specifically, you need to specify the charset differently and URL encode the SVG part:
background: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20400%20400%27%3E%3Cpath%20fill%3D%27%23000000%27%20d%3D%27M192%2C32%20C103.75%2C32%2032%2C103.75%2032%2C192%20C32%2C280.25%20103.75%2C352%20192%2C352%20C280.25%2C352%20352%2C280.25%20352%2C192%20C352%2C103.75%20280.25%2C32%20192%2C32%20Z%20M384%2C192%20C384%2C298%20298%2C384%20192%2C384%20C86%2C384%200%2C298%200%2C192%20C0%2C86%2086%2C0%20192%2C0%20L192%2C0%20C298%2C0%20384%2C86%20384%2C192%20Z%27%3E%3C%2Fpath%3E%3C%2Fsvg%3E") no-repeat center;
For the record, the full URL encoding is probably overkill. You really only need to do the < and > but I'm just being lazy and using a URL encoder instead of editing your code directly.
It is discussed in greater detail over in this question:
CSS: Using raw svg in the URL parameter of a background-image in IE
This CodePen shows the differences between implementations of inline SVG with the different charset, URL encode and Base64 encode: https://codepen.io/chriscoyier/pen/zEJtC

Possible to use SVG sprites without needing <svg> for each instance?

I'm attempting to move from font icons (icomoon.io) to SVG sprites. Is it possible to use SVG sprites without needing < svg > markup for each icon instance?
What I really liked about the font icons was that I didn't have to clutter my HTML with any additional elements to get the icon to display. I usually just targeted a simple class on whatever element I wanted the icon to display and then used pseudo selectors to display the icon, e.g.:
<h1 class="news">News</h1>
h1.user:before {
font-family: 'icons';
content: '\news';
}
That made a lot of sense to me, and all of my icons were easily managed almost completely in CSS. I rarely had to touch my HTML as long as my markup contained appropriate classes.
I've since switched my build system to Grunt and thought I'd give SVG sprites a try. Almost every1 article2 I3 can4 find5 on the subject says you need to add an additional SVG element to your markup wherever you want each instance to display, e.g.:
<h1>
<svg class="icon">
<use xlink:href="#icon-news">
</svg>
News
</h1>
That seems like a step backwards to me, at least in the management of markup. To me, an icon is usually presentation that should be separate from document structure. Are we doing it this way simply because of the state of SVG support in browsers?
Ideally, I'd love to be able to do something like this:
<h1 class="news">News</h1>
h1.news:before {
display: inline-block;
width: px;
height: px;
background: url(icons.svg#news) no-repeat;
}
This post seems to be closer to what I'm looking for, but I'm not sure of browser support and how to do it automatically in a build system like Grunt.
SVGs can be loaded as files exactly the same way as other images using <img> tags or CSS background, and can be used as sprites exactly the same way too. The only difference is that you have to specify the size you want it (because it's scalable, so the browser doesn't automatically know how big it is like it does with PNGs).
Depending on how you want to use the image, loading them this way may or may not be suitable as some SVG features aren't available, but it can be done.

How to specify font-family in SVG

I have this piece of SVG picture:
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;
font-family:'Arial;Sans';
-inkscape-font-specification:'Arial;Sans';font-stretch:normal;font-variant:normal"
x="11.764346"
y="192.01521"
id="text3607"
sodipodi:linespacing="125%"><tspan
sodipodi:role="line"
id="tspan3609"
x="11.764346"
y="192.01521">PCI-E</tspan></text>
which I edited on linux using inkscape. It used font "sans" which is not available on windows. I would like to specify a font-family that contains fonts available on all major operating systems, but whatever syntax I use it doesn't work. So far I tried:
font-family:'Arial' - works on windows
font-family:'Sans' - works on linux
font-family:'Sans,Arial' - broken
font-family:'Sans;Arial' - broken
What is correct syntax for this to work? I was rendering the picture in IE and Firefox, both seems to have same problems.
in order to change font-family in svg you should first import font in defs in svg like this:
<defs>
<style type="text/css">#import url('https://fonts.googleapis.com/css?family=Lato|Open+Sans|Oswald|Raleway|Roboto|Indie+Flower|Gamja+Flower');</style>
</defs>
then you can change font-family either using an inline style or by javascript
<text xmlns="http://www.w3.org/2000/svg" style="direction:rtl ;font-family:Gamja Flower" id="nametxt" class="text" transform="matrix(1 0 0 1 390 88.44)">text</text>
and for javascript:
svgTextNode.style.fontFamily=FontFamily
It seems that problem was I had it wrapped in quotes. Correct syntax (or at least it works to me):
font-family:Sans,Arial; (no quotes)
In case if we need to declare global style we could use the following syntax:
<svg width="100" height="100"
xmlns="http://www.w3.org/2000/svg">
<style>
text {
font-family:Roboto-Regular,Roboto;
}
</style>
...
</svg>
For security reason, embedded svg images have to be standalone images. You will need to make the svg 'standalone' by embedding all external assets (in our case is the font definition) into it.
To embedded the font inside svg file, follow these steps:
1. Generate the embedded font url as base64
Download the font file you want to use under .ttf extension.
We will need to have the embedded as data URI scheme.
Upload this font file to any online Data URI converter,
I'm using dopiaza.org data URI generator for simplicity (or you can use any File to Base64 converter tool, as long as you follow the same data-uri generated pattern).
Upload the font file to the converter. Ensure Use base64 encoding is checked. Since we're embedding font, so choose Explicitly specify mime type
and put the mime type is application/font-woff
Hit the Generate Data URI and let the tool do the job, it should present you the following data URI format:
data:<mime-type>;base64,<the_encoded_font_as_base64_content>
In our case using font as Mime-Type, it will be:
data:application/font-woff;base64,AAEAAAATAQAABAAwR0RFRv4pBjw....
2. Declare the embedded font inside our SVG file
Edit our SVG file that's using the font. Declare #font-face inside the tag. Put the generated data-uri URL above in the src: url("<generated_data_uri>")
<svg>
<defs>
<style>
#font-face {
font-family: Inter;
src: url("data:application/font-woff;base64,AAEAAAATAQAABAAwR0RFRv4pBjw....")
}
</style>
</defs>
<!-- The rest of your SVG content goes here -->
</svg>
In my case I was converting an SVG as a base64.
Using font-family="Arial, sans-serif;" was not working, but when I removed ";" semi-colon from last portion, voila! it worked.

Resources