How to Convert Text to Svg Paths

How to convert text to SVG paths?

I have created my own class to process SVG font file and to turn text into glyphs. Example of using:

include "SVGFont.php";
$svgFont = new SVGFont();
$svgFont->load("/path/to/font.svg");
$result = $svgFont->textToPaths("Simple text", 20);

Example result:

<g transform="scale(0.009765625) translate(0, 0)"><path transform="translate(0,0) rotate(180) scale(-1, 1)" d="M92 471l183 16q13 -110 60.5 -180.5t147.5 -114t225 -43.5q111 0 196 33t126.5 90.5t41.5 125.5q0 69 -40 120.5t-132 86.5q-59 23 -261 71.5t-283 91.5q-105 55 -156.5 136.5t-51.5 182.5q0 111 63 207.5t184 146.5t269 50q163 0 287.5 -52.5t191.5 -154.5t72 -231 l-186 -14q-15 139 -101.5 210t-255.5 71q-176 0 -256.5 -64.5t-80.5 -155.5q0 -79 57 -130q56 -51 292.5 -104.5t324.5 -93.5q128 -59 189 -149.5t61 -208.5q0 -117 -67 -220.5t-192.5 -161t-282.5 -57.5q-199 0 -333.5 58t-211 174.5t-80.5 263.5z" /><path transform="translate(1366,0) rotate(180) scale(-1, 1)" d="M136 0v1062h180v-1062h-180zM136 1259v207h180v-207h-180z" /><path transform="translate(1821,0) rotate(180) scale(-1, 1)" d="M135 0v1062h161v-149q50 78 133 125.5t189 47.5q118 0 193.5 -49t106.5 -137q126 186 328 186q158 0 243 -87.5t85 -269.5v-729h-179v669q0 108 -17.5 155.5t-63.5 76.5t-108 29q-112 0 -186 -74.5t-74 -238.5v-617h-180v690q0 120 -44 180t-144 60q-76 0 -140.5 -40 t-93.5 -117t-29 -222v-551h-180z" /><path transform="translate(3527,0) rotate(180) scale(-1, 1)" d="M135 -407v1469h164v-138q58 81 131 121.5t177 40.5q136 0 240 -70t157 -197.5t53 -279.5q0 -163 -58.5 -293.5t-170 -200t-234.5 -69.5q-90 0 -161.5 38t-117.5 96v-517h-180zM298 525q0 -205 83 -303t201 -98q120 0 205.5 101.5t85.5 314.5q0 203 -83.5 304t-199.5 101 q-115 0 -203.5 -107.5t-88.5 -312.5z" /><path transform="translate(4666,0) rotate(180) scale(-1, 1)" d="M131 0v1466h180v-1466h-180z" /><path transform="translate(5121,0) rotate(180) scale(-1, 1)" d="M75 522q0 268 138 416t358 148q213 0 348 -145t135 -408q0 -16 -1 -48h-792q10 -175 99 -268t222 -93q99 0 169 52t111 166l186 -23q-44 -163 -163 -253t-304 -90q-233 0 -369.5 143.5t-136.5 402.5zM271 633h593q-12 134 -68 201q-86 104 -223 104q-124 0 -208.5 -83 t-93.5 -222z" /><path transform="translate(6260,0) rotate(180) scale(-1, 1)" d="" /><path transform="translate(6829,0) rotate(180) scale(-1, 1)" d="M36 922v140h132v263l179 108v-371h181v-140h-181v-621q0 -77 9.5 -99t31 -35t61.5 -13q30 0 79 7l26 -159q-76 -16 -136 -16q-98 0 -152 31t-76 81.5t-22 212.5v611h-132z" /><path transform="translate(7398,0) rotate(180) scale(-1, 1)" d="M75 522q0 268 138 416t358 148q213 0 348 -145t135 -408q0 -16 -1 -48h-792q10 -175 99 -268t222 -93q99 0 169 52t111 166l186 -23q-44 -163 -163 -253t-304 -90q-233 0 -369.5 143.5t-136.5 402.5zM271 633h593q-12 134 -68 201q-86 104 -223 104q-124 0 -208.5 -83 t-93.5 -222z" /><path transform="translate(8537,0) rotate(180) scale(-1, 1)" d="M15 0l388 552l-359 510h225l163 -249q46 -71 74 -119q44 66 81 117l179 251h215l-367 -500l395 -562h-221l-218 330l-58 89l-279 -419h-218z" /><path transform="translate(9561,0) rotate(180) scale(-1, 1)" d="M36 922v140h132v263l179 108v-371h181v-140h-181v-621q0 -77 9.5 -99t31 -35t61.5 -13q30 0 79 7l26 -159q-76 -16 -136 -16q-98 0 -152 31t-76 81.5t-22 212.5v611h-132z" /></g>

Code for my class:

<?php

/**
* This class represents SVG pa
* @author Łukasz Ledóchowski lukasz@ledochowski.pl
* @version 0.1
*/
class SVGFont {

protected $id = '';
protected $horizAdvX = 0;
protected $unitsPerEm = 0;
protected $ascent = 0;
protected $descent = 0;
protected $glyphs = array();

/**
* Function takes UTF-8 encoded string and returns unicode number for every character.
* Copied somewhere from internet, thanks.
*/
function utf8ToUnicode( $str ) {
$unicode = array();
$values = array();
$lookingFor = 1;

for ($i = 0; $i < strlen( $str ); $i++ ) {
$thisValue = ord( $str[ $i ] );
if ( $thisValue < 128 ) $unicode[] = $thisValue;
else {
if ( count( $values ) == 0 ) $lookingFor = ( $thisValue < 224 ) ? 2 : 3;
$values[] = $thisValue;
if ( count( $values ) == $lookingFor ) {
$number = ( $lookingFor == 3 ) ?
( ( $values[0] % 16 ) * 4096 ) + ( ( $values[1] % 64 ) * 64 ) + ( $values[2] % 64 ):
( ( $values[0] % 32 ) * 64 ) + ( $values[1] % 64 );

$unicode[] = $number;
$values = array();
$lookingFor = 1;
}
}
}

return $unicode;
}

/**
* Function takes path to SVG font (local path) and processes its xml
* to get path representation of every character and additional
* font parameters
*/
public function load($filename) {
$this->glyphs = array();
$z = new XMLReader;
$z->open($filename);

// move to the first <product /> node
while ($z->read()) {
$name = $z->name;

if ($z->nodeType == XMLReader::ELEMENT) {
if ($name == 'font') {
$this->id = $z->getAttribute('id');
$this->horizAdvX = $z->getAttribute('horiz-adv-x');
}

if ($name == 'font-face') {
$this->unitsPerEm = $z->getAttribute('units-per-em');
$this->ascent = $z->getAttribute('ascent');
$this->descent = $z->getAttribute('descent');
}

if ($name == 'glyph') {
$unicode = $z->getAttribute('unicode');
$unicode = $this->utf8ToUnicode($unicode);
$unicode = $unicode[0];

$this->glyphs[$unicode] = new stdClass();
$this->glyphs[$unicode]->horizAdvX = $z->getAttribute('horiz-adv-x');
if (empty($this->glyphs[$unicode]->horizAdvX)) {
$this->glyphs[$unicode]->horizAdvX = $this->horizAdvX;
}
$this->glyphs[$unicode]->d = $z->getAttribute('d');
}
}
}

}

/**
* Function takes UTF-8 encoded string and size, returns xml for SVG paths representing this string.
* @param string $text UTF-8 encoded text
* @param int $asize size of requested text
* @return string xml for text converted into SVG paths
*/
public function textToPaths($text, $asize) {
$lines = explode("\n", $text);
$result = "";
$horizAdvY = 0;
foreach($lines as $text) {
$text = $this->utf8ToUnicode($text);
$size = ((float)$asize) / $this->unitsPerEm;
$result .= "<g transform=\"scale({$size}) translate(0, {$horizAdvY})\">";
$horizAdvX = 0;
for($i = 0; $i < count($text); $i++) {
$letter = $text[$i];
$result .= "<path transform=\"translate({$horizAdvX},{$horizAdvY}) rotate(180) scale(-1, 1)\" d=\"{$this->glyphs[$letter]->d}\" />";
$horizAdvX += $this->glyphs[$letter]->horizAdvX;
}
$result .= "</g>";
$horizAdvY += $this->ascent + $this->descent;
}

return $result;
}
}

How to convert SVG text to SVG paths?

For now, I’m find only one lib where it's possible to do: inkscape with --export-text-to-path param.

Inkscape work in few threads, and can be runned from java. Convertions are slow, and size of exported files depends of version of inkscape.

Add text to SVG path dynamically

Here's some sample code that takes a label path and adds a <text> element after it with whatever text you choose.

let label1 = document.querySelector("#label1");

addLabelText(label1, "Something");



function addLabelText(bgPath, labelText)
{
let bbox = bgPath.getBBox();
let x = bbox.x + bbox.width / 2;
let y = bbox.y + bbox.height / 2;

// Create a <text> element
let textElem = document.createElementNS(bgPath.namespaceURI, "text");
textElem.setAttribute("x", x);
textElem.setAttribute("y", y);
// Centre text horizontally at x,y
textElem.setAttribute("text-anchor", "middle");
// Give it a class that will determine the text size, colour, etc
textElem.classList.add("label-text");
// Set the text
textElem.textContent = labelText;
// Add this text element directly after the label background path
bgPath.after(textElem);
}
.st37 {
fill: linen;
}

.label-text {
font-size: 10px;
fill: rebeccapurple;
transform: translate(0, 3px); /* adjust vertical position to centre text */
}
<svg viewbox="387 390 74 20">
<g>
<path id="label1" class="st37" d="M452,408h-56c-4.42,0-8-3.58-8-8l0,0c0-4.42,3.58-8,8-8h56c4.42,0,8,3.58,8,8l0,0 C460,404.42,456.42,408,452,408z" />
</g>
</svg>

How change font text to SVG path

Yes this is possible with https://github.com/tdewolff/canvas (I'm the principal author). You can see an example at https://github.com/tdewolff/canvas/blob/master/examples/preview/main.go#L89 (result at https://github.com/tdewolff/canvas/blob/master/examples/preview/out.png) where I load a font and convert a piece of text to a vector path.

The following should work in your case (not tested) using tdewolff/canvas:

fontFamily := canvas.NewFontFamily("Lato")
if err := fontFamily.LoadFontFile("Lato-Bold.ttf", canvas.FontBold); err != nil {
panic(err)
}

face := fontFamily.Face(14.0, canvas.Black, canvas.FontBold, canvas.FontNormal)
path, err := face.ToPath("Change me to svg path")
if err != nil {
panic(err)
}

tpl := `<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" height="400" width="800">
<path d="%s" />
</svg>`
fmt.Printf(tpl, path.ToSVG())


Related Topics



Leave a reply



Submit