Come convertire il text in routes SVG?

Ho un font nel file ttf e voglio generare SVG con il text trasformato in tracciati. Non ho bisogno di immagini (quindi usare le funzionalità di rendering dei font di imagettftext o Image Magick non è sufficiente), ho bisogno di una forma, che possa essere scalata in alto e in basso e voglio perdere informazioni sul font usato e non voglio farvi riferimento in File SVG (quindi le dichiarazioni di font-face non possono essere utilizzate qui). È ansible?

Ho creato la mia class per elaborare il file di font SVG e trasformare il text in glifi. Esempio di utilizzo:

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

Esempio di risultato:

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

Codice per la mia class:

 <?php /** * This class represents SVG pa * @author Łukasz Ledóchowski [email protected] * @version 0.1 */ class SVGFont { protected $id = ''; protected $horizAdvX = 0; protected $unitsPerEm = 0; protected $ascent = 0; protected $descent = 0; protected $glyphs = arrays(); /** * Function takes UTF-8 encoded string and returns unicode number for every character. * Copied somewhere from internet, thanks. */ function utf8ToUnicode( $str ) { $unicode = arrays(); $values = arrays(); $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 = arrays(); $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 = arrays(); $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; } } 

Una soluzione alternativa è usare inkscape (eseguirlo tramite exec o così dopo aver salvato il documento SVG in file.svg ). In inkscape 0.49+, puoi semplicemente passare --export-to-svg e --export-text-to-path , in questo modo:

 $ inkscape file_text.svg --export-text-to-path --export-plain-svg file_shapes.svg 

In inkscape <0.49, puoi scrivere manualmente inkscape (nota che questo richiede un server X):

 $ inkscape --with-gui --verb EditSelectAll --verb ObjectToPath --verb FileSave \ --verb FileQuit file.svg 

Ho appena scritto una libreria PHP basata sul tuo che manipola i dati dei font (dal file SVG) e fa qualsiasi tipo di trasformazione su di esso. Puoi provarlo dal GitHub:

https://github.com/kartsims/easysvg

Esempio di utilizzo:

 require 'easySVG.php'; $svg = new EasySVG(); $svg->setFont("paris-bold-webfont.svg", 100, "#000000"); $svg->addText("Simple text display"); $svg->addAttribute("width", "800px"); $svg->addAttribute("height", "100px"); echo $svg->asXML(); 

Esempio di manipolazione dei dati SVG:

 $def = 'YOUR SVG DEFINITION HERE'; $easySVG = new EasySVG(); // rotate by 40° $rotated_def = $easySVG->defRotate($def, 40) // rotate by 40° with center at (200,100) $rotated_def2 = $easySVG->defRotate($def, 40, 200, 100) // scale transform : width*4 $scaled_def = $easySVG->defScale($def, 4) 

Se riesci a get uno svgfont, allora hai tutte le informazioni lì per renderlo usando i routes dei glifi (copia-incolla tutti i dati del path glifi necessari ad un numero qualsiasi di elementi del path e applica una trasformazione flip-y e ridimensionala a qualunque size necessarie). Batik ha uno strumento chiamato ttf2svg , che ti dà l'output di svgfont. Ce ne sono anche altri, fontforge per esempio.

Non sono sicuro che ci siano degli strumenti da row di command che possano generare direttamente uno svg come questo, ma la soluzione Inkscape dovrebbe fare esattamente quello che vuoi.

Se sei su un Mac, ho scoperto che l'apertura di un file SVG in iVinci Express con un object di text lo convertirà automaticamente in un path. Ho creato il mio SVG in Inkscape, che era una T maiuscola in Times New Roman (strumento di selezione text standard). Android SVG lib non poteva gestirlo mostrando un Roboto T, così ho aperto in iVinci Express, salvato da lì e convertito automaticamente in un path. Ho eliminato parte della posta indesiderata aggiunta e ho impostato la viewbox (Android ne ha bisogno) e tutto è andato bene.

iVinci Express è gratuito su Mac Store.