11

I have the following glyph path:

<glyph glyph-name="right-nav-workflow" unicode="&#xe8c1;" d="M251 101c0 65 0 131 0 196 26 0 52 0 78 0 0 27 0 54 0 81-29 7-52 23-67 50-11 20-14 41-10 64 8 45 48 79 92 81 49 1 88-29 102-79 2 0 4 0 6 0 20 0 40 0 60 0 5 0 8 1 11 5 32 32 64 64 96 96 2 1 3 3 4 4 42-42 84-84 127-127-1 0-2-2-4-4-32-32-65-65-98-98-2-2-4-6-4-10 0-21 0-43 0-64 30-8 53-24 67-52 12-21 15-44 9-68-11-46-55-78-102-75-48 3-88 42-92 91-4 48 28 91 78 104 0 1 1 3 1 4 0 21 0 42 0 62 0 3-2 5-3 7-28 28-55 55-83 83-1 1-3 3-5 3-22 0-45 0-68 0-5-19-13-36-27-50-14-14-31-23-50-27 0-27 0-53 0-81 26 0 52 0 78 0 0-65 0-130 0-196-65 0-131 0-196 0z m157 156c-40 0-79 0-118 0 0-39 0-78 0-117 40 0 79 0 118 0 0 39 0 78 0 117z m275-58c0 33-26 59-59 59-32 0-59-26-59-59 0-33 27-59 60-59 32 0 58 26 58 59z m-334 216c33 0 59 27 59 59 0 33-26 59-59 59-33 0-59-26-59-59 0-33 26-59 59-59z m275-11c23 23 46 46 69 69-23 23-47 46-69 68-23-22-46-46-69-69 23-22 46-45 69-68z" horiz-adv-x="1000" />

How can I convert this into SVG? I tried to save it in a text file with svg extension but seems is not working.

Pavel Chuchuva
  • 22,633
  • 10
  • 99
  • 115
VAAA
  • 14,531
  • 28
  • 130
  • 253

3 Answers3

16

Take the raw drawing data, put it in a path element, remove the glyph specific attributes, add an appropriate viewBox. Now you have something that works as an inline SVG. If you want to save it as a standalone SVG, then you need to add a name space declaration.

<svg height="400px" width="400px" viewBox="0 0 1000 1000">
  <path transform="scale(1,-1) translate(0,-650)" fill="none" stroke="red" stroke-width="1" d="M251 101c0 65 0 131 0 196 26 0 52 0 78 0 0 27 0 54 0 81-29 7-52 23-67 50-11 20-14 41-10 64 8 45 48 79 92 81 49 1 88-29 102-79 2 0 4 0 6 0 20 0 40 0 60 0 5 0 8 1 11 5 32 32 64 64 96 96 2 1 3 3 4 4 42-42 84-84 127-127-1 0-2-2-4-4-32-32-65-65-98-98-2-2-4-6-4-10 0-21 0-43 0-64 30-8 53-24 67-52 12-21 15-44 9-68-11-46-55-78-102-75-48 3-88 42-92 91-4 48 28 91 78 104 0 1 1 3 1 4 0 21 0 42 0 62 0 3-2 5-3 7-28 28-55 55-83 83-1 1-3 3-5 3-22 0-45 0-68 0-5-19-13-36-27-50-14-14-31-23-50-27 0-27 0-53 0-81 26 0 52 0 78 0 0-65 0-130 0-196-65 0-131 0-196 0z m157 156c-40 0-79 0-118 0 0-39 0-78 0-117 40 0 79 0 118 0 0 39 0 78 0 117z m275-58c0 33-26 59-59 59-32 0-59-26-59-59 0-33 27-59 60-59 32 0 58 26 58 59z m-334 216c33 0 59 27 59 59 0 33-26 59-59 59-33 0-59-26-59-59 0-33 26-59 59-59z m275-11c23 23 46 46 69 69-23 23-47 46-69 68-23-22-46-46-69-69 23-22 46-45 69-68z"/>
  
</svg>

Update - Robert points out that the SVG Fonts spec has a y axis (0 on the bottom) that's inverted from the SVG norm (0 is the top) -> so you also need to flip the drawing along the x axis by using a scale (1,-1).

Michael Mullany
  • 30,283
  • 6
  • 81
  • 105
0

Michael Mullany's solution won't preserve colors (e.g. in empjis).

One solution I found: Print an internet page containing the glyph to a PDF, import the PDF into inkscape, use "TEXT AS VECTORS", crop the glyph, and then save as SVG

Berry Tsakala
  • 15,313
  • 12
  • 57
  • 80
0

1. Search for SVG repository

Especially, when you're dealing with icons.
Most icon libraries (e.g fontAwesome, Material UI etc.) also provide single SVG files or spritesheets.

2. Convert SVG fonts with an icon generator service

Although svg fonts are kind of deprecated - not supported by Firefox or Chromium – icon generators like icomoon or fontello can still use them as an import format.

  1. import icons
  2. select glyphs
  3. export single svgsicomoon app

3. Convert with javaScript

The following conversion function works like this:

  1. parse font metrics in like asccender <font-face> element – we'll need this for shifting the glyph path vertically
  2. parse the <glyph> pathdata – I'm using getPathData polyfill
  3. Flip Y coordinates via custom scaleAndShiftPathData() helper and shift all glyphs vertically by the ascent attribute value

let svgFont2Svg = parseSVGFont(svgFont);
document.body.append(svgFont2Svg)


function parseSVGFont(svgFont) {
  let isSVGFont = svgFont.querySelector("font") ? true : false;

  if (isSVGFont) {
    let ns = "http://www.w3.org/2000/svg";
    // get font metrics
    let fontFace = svgFont.querySelector("font-face");
    let unitsPerEm = +fontFace.getAttribute("units-per-em");
    let ascent = +fontFace.getAttribute("ascent");
    let descent = fontFace.getAttribute("descent")
      ? Math.abs(+fontFace.getAttribute("descent"))
      : 0;
    let glyphs = svgFont.querySelectorAll("glyph");
    let fontWrap = document.createElement("div");

    glyphs.forEach((glyph, i) => {
      let d = glyph.getAttribute("d");
      if (d) {
        // create glyph svg
        let glyphName = glyph.getAttribute("glyph-name");
        let glyphSvg = document.createElementNS(ns, "svg");
        let width = glyph.getAttribute("horiz-adv-x")
          ? +glyph.getAttribute("horiz-adv-x")
          : unitsPerEm;
        // glyphSvg.setAttribute('viewBox', [0, 0, width, unitsPerEm+(descent)].join(' '));
        glyphSvg.setAttribute(
          "viewBox",
          [0, 0, width, unitsPerEm - descent].join(" ")
        );
        glyphSvg.setAttribute("xmlns", ns);
        glyphSvg.id = glyphName;
        let path = document.createElementNS(ns, "path");
        path.setAttribute('d', d)
        let pathData = path.getPathData({normalize:true});
        
        // flip cartesian to svg coordinate system
        pathData = scaleAndShiftPathData(pathData, 1, -1, 0, ascent);

        //shift by ascender height
        offsetY = descent;
        //pathData = shiftPathData(pathData, 0, ascent);
        path.setPathData(pathData);
        glyphSvg.appendChild(path);
        fontWrap.appendChild(glyphSvg);
      }
    });
    return fontWrap;
  }
}


/**
 * scale pathData
 */
function scaleAndShiftPathData(pathData, scaleX=1, scaleY=1, shiftX=0, shiftY=0) {
  let pathDataScaled = [];
  pathData.forEach((com) => {
    let [type, values] = [com.type, com.values];
    let typeL = type.toLowerCase();
    let valuesL = values.length;
    let valsScaled = [];

    switch (typeL) {
      case "z":
        pathDataScaled.push(com);
        break;

      default:
        if (valuesL) {
          valsScaled = [];
          for (let i = 0; i < values.length; i += 2) {
            let x = values[i] * scaleX + shiftX;
            let y = values[i + 1] * scaleY + shiftY;
            valsScaled.push(x, y);
          }
          pathDataScaled.push({ type: type, values: valsScaled });
        }
    }
  });
  return pathDataScaled;
}
svg{
  height:10em;
  width:auto;
  overflow: visible;
  border:1px solid #ccc;
}
<!-- svg font -->
<svg style="display:none" id="svgFont" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
<defs>
<font id="Poppins-Medium" horiz-adv-x="0" >
  <font-face 
    font-family="Poppins Medium"
    font-weight="500"
    font-stretch="normal"
    units-per-em="1000"
    panose-1="0 0 6 0 0 0 0 0 0 0"
    ascent="800"
    descent="-200"
    cap-height="696"
    bbox="0 -6 736 704"
    underline-thickness="50"
    underline-position="-150"
    unicode-range="U+0020-0047"
  />
<missing-glyph horiz-adv-x="500" 
d="M0 700h500v-700h-500v700zM420 650h-340l170 -255zM50 95l170 255l-170 255v-510zM450 95v510l-170 -255zM420 50l-170 255l-170 -255h340z" />
    <glyph glyph-name=".notdef" horiz-adv-x="500" 
d="M0 700h500v-700h-500v700zM420 650h-340l170 -255zM50 95l170 255l-170 255v-510zM450 95v510l-170 -255zM420 50l-170 255l-170 -255h340z" />
    <glyph glyph-name=".null" 
 />
    <glyph glyph-name="nonmarkingreturn" horiz-adv-x="333" 
 />
    <glyph glyph-name="NULL" 
 />
    <glyph glyph-name="space" unicode=" " horiz-adv-x="260" 
 />
    <glyph glyph-name="A" unicode="A" horiz-adv-x="697" 
d="M494 142h-291l-50 -142h-119l249 696h132l249 -696h-120zM462 235l-113 323l-114 -323h227z" />
    <glyph glyph-name="B" unicode="B" horiz-adv-x="630" 
d="M542 298q39 -49 39 -111q0 -53 -27.5 -95.5t-79.5 -67t-121 -24.5h-278v695h265q71 0 122 -24t77 -64.5t26 -90.5q0 -60 -32 -100t-86 -59q56 -10 95 -59zM189 403h141q56 0 87.5 25.5t31.5 73.5q0 47 -31.5 73.5t-87.5 26.5h-141v-199zM434 121q33 28 33 78q0 51 -35 81
t-93 30h-150v-217h154q58 0 91 28z" />
    <glyph glyph-name="C" unicode="C" horiz-adv-x="773" 
d="M84.5 532q47.5 81 129 126.5t178.5 45.5q111 0 197.5 -54.5t125.5 -154.5h-137q-27 55 -75 82t-111 27q-69 0 -123 -31t-84.5 -89t-30.5 -135t30.5 -135t84.5 -89.5t123 -31.5q63 0 111 27t75 82h137q-39 -100 -125.5 -154t-197.5 -54q-98 0 -179 45.5t-128.5 126.5
t-47.5 183t47.5 183z" />
    <glyph glyph-name="D" unicode="D" horiz-adv-x="709" 
d="M496.5 652.5q83.5 -42.5 129 -122t45.5 -185.5t-45.5 -184t-129 -119.5t-194.5 -41.5h-227v695h227q111 0 194.5 -42.5zM489 159q65 66 65 186q0 121 -65 189t-187 68h-113v-509h113q122 0 187 66z" />
    <glyph glyph-name="E" unicode="E" horiz-adv-x="524" 
d="M189 603v-204h240v-93h-240v-213h270v-93h-384v696h384v-93h-270z" />
    <glyph glyph-name="F" unicode="F" horiz-adv-x="515" 
d="M484 695v-93h-295v-205h230v-93h-230v-304h-114v695h409z" />
    <glyph glyph-name="G" unicode="G" horiz-adv-x="773" 
d="M578 495q-27 52 -75 78.5t-111 26.5q-69 0 -123 -31t-84.5 -88t-30.5 -132t30.5 -132.5t84.5 -88.5t123 -31q93 0 151 52t71 141h-261v91h383v-89q-11 -81 -57.5 -149t-121 -108.5t-165.5 -40.5q-98 0 -179 45.5t-128.5 126.5t-47.5 183t47.5 183t129 126.5t178.5 45.5
q111 0 197.5 -54.5t125.5 -154.5h-137z" />
  </font>
</defs></svg>

<h3>Icomoon output</h3>
<!-- Generated by IcoMoon.io -->
<svg  xmlns="http://www.w3.org/2000/svg" width="25" height="32" viewBox="0 0 25 32">
<title>C</title>
<path d="M2.704 8.576q1.52-2.592 4.128-4.048t5.712-1.456q3.552 0 6.32 1.744t4.016 4.944h-4.384q-0.864-1.76-2.4-2.624t-3.552-0.864q-2.208 0-3.936 0.992t-2.704 2.848-0.976 4.32 0.976 4.32 2.704 2.864 3.936 1.008q2.016 0 3.552-0.864t2.4-2.624h4.384q-1.248 3.2-4.016 4.928t-6.32 1.728q-3.136 0-5.728-1.456t-4.112-4.048-1.52-5.856 1.52-5.856z"></path>
</svg>

<h3>Custom output</h3>

<script src="https://cdn.jsdelivr.net/npm/path-data-polyfill@latest/path-data-polyfill.min.js"></script>

As a side note: Opentype SVG fonts ≠ SVG fonts

As mentioned SVG fonts are barely used anywhere due to lacking browser support.

Opentype SVG fonts are commonly used for rich colored Emojis - for instance "Noto Color" as they support a variety of styling options like predefined color, gradients etc.

Both formats are often confused – the deprecated SVG fonts can't be used like Opentype SVG fonts.

A lot of font converters (like transfonter) still support a SVG output – this won't be an Opentype SVG font.

If you need to extract glyphs from these you might use a free tool like "OpenType SVG Font Editor" (Windows only)

herrstrietzel
  • 11,541
  • 2
  • 12
  • 34