50 votes

Comment convertir du texte en chemins SVG ?

J'ai une police dans un fichier ttf et je souhaite générer du SVG avec du texte transformé en chemins. Je n'ai pas besoin d'image (donc l'utilisation des capacités de rendu de police imagettftext ou Image Magick n'est pas suffisante), j'ai besoin d'une forme, qui peut être agrandie et réduite et je veux perdre des informations sur la police utilisée et je ne veux pas la référencer dans SVG (donc les déclarations font-face ne peuvent pas être utilisées ici). Est-il possible?

42voto

LukLed Points 18010

J'ai créé ma propre classe pour traiter le fichier de police SVG et transformer le texte en glyphes. Exemple d'utilisation :

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

Exemple de résultat :

 <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 pour ma classe :

 <?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;
    }
}

11voto

kartsims Points 86

Je viens d'écrire une bibliothèque PHP basée sur la vôtre qui manipule les données de police (à partir d'un fichier SVG) et effectue toute sorte de transformation dessus. Vous pouvez l'essayer depuis le GitHub :

https://github.com/kartsims/easysvg

Exemple d'utilisation :

 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();

Exemple de manipulation de données 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)

5voto

David Spector Points 20

Exécutez Inkscape. Entrez votre texte. Cliquez sur Menu > Chemin > Objet vers chemin.

Cliquez sur Enregistrer sous... et choisissez le format SVG simple.

3voto

jimmont Points 317

dans Boxy SVG 3.28 Sélectionnez le texte puis allez dans le menu : Forme > Forme vers chemin

le texte sera converti et chaque glyphe est maintenant une forme vectorielle modifiable à partir de la police de caractères/police donnée

La réponse Inkscape de David Spector est celle que j'utilise plus récemment

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X