Php 如何将文本转换为SVG路径?
我在ttf文件中有一个字体,希望生成SVG,将文本转换为路径。我不需要图像(所以使用imagettftext或ImageMagick字体渲染功能是不够的),我需要可以放大和缩小的形状,我想丢失有关所用字体的信息,不想在SVG文件中引用它(所以这里不能使用字体面声明)。有可能吗?一种解决方法是使用inkscape(将SVG文档保存到Php 如何将文本转换为SVG路径?,php,text,svg,truetype,Php,Text,Svg,Truetype,我在ttf文件中有一个字体,希望生成SVG,将文本转换为路径。我不需要图像(所以使用imagettftext或ImageMagick字体渲染功能是不够的),我需要可以放大和缩小的形状,我想丢失有关所用字体的信息,不想在SVG文件中引用它(所以这里不能使用字体面声明)。有可能吗?一种解决方法是使用inkscape(将SVG文档保存到file.SVG后,通过左右执行)。在inkscape 0.49+中,只需传递--导出到svg和--将文本导出到路径,如下所示: $ inkscape file_tex
file.SVG
后,通过左右执行)。在inkscape 0.49+中,只需传递--导出到svg
和--将文本导出到路径
,如下所示:
$ inkscape file_text.svg --export-text-to-path --export-plain-svg file_shapes.svg
在inkscape<0.49中,您可以手动编写inkscape脚本(注意,这需要一个X服务器):
如果可以获得svgfont,那么就有了所有信息,可以使用glyph路径进行渲染(将所有需要的glyph路径数据复制粘贴到任意数量的路径元素,并应用翻转y变换并将其缩放到所需的大小)。Batik有一个名为的工具,它可以为您提供svgfont输出。例如,还有其他的
不确定是否有任何纯命令行工具可以直接生成这样的svg,但Inkscape解决方案应该完全满足您的需要。我创建了自己的类来处理svg字体文件并将文本转换为字形。使用的示例:
include "SVGFont.php";
$svgFont = new SVGFont();
$svgFont->load("/path/to/font.svg");
$result = $svgFont->textToPaths("Simple text", 20);
示例结果:
<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>
我的班级代码:
<?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;
}
}
glyphs=array();
$z=新的XMLReader;
$z->open($filename);
//移动到第一个节点
而($z->read()){
$name=$z->name;
如果($z->nodeType==XMLReader::ELEMENT){
如果($name='font'){
$this->id=$z->getAttribute('id');
$this->horizAdvX=$z->getAttribute('horiz-adv-x');
}
如果($name=='font-face'){
$this->unitsPerEm=$z->getAttribute('units-per-em');
$this->ascent=$z->getAttribute('ascent');
$this->descent=$z->getAttribute('descent');
}
如果($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(空($this->glyphs[$unicode]->horizAdvX)){
$this->glyphs[$unicode]->horizAdvX=$this->horizAdvX;
}
$this->glyphs[$unicode]->d=$z->getAttribute('d');
}
}
}
}
/**
*函数接受UTF-8编码的字符串和大小,返回表示该字符串的SVG路径的xml。
*@param string$text UTF-8编码文本
*@param int$asize请求文本的大小
*@用于转换为SVG路径的文本的返回字符串xml
*/
公共函数textToPaths($text,$asize){
$lines=分解(“\n”,$text);
$result=“”;
$horizAdvY=0;
foreach($text形式的行){
$text=$this->utf8ToUnicode($text);
$size=((浮动)$asize)/$this->unitsPerEm;
$result.=”;
$horizAdvX=0;
对于($i=0;$iglyphs[$letter]->horizAdvX;
}
$result.=”;
$horizAdvY+=$this->上升+$this->下降;
}
返回$result;
}
}
我刚刚在您的基础上编写了一个PHP库,用于处理字体数据(来自SVG文件)并对其进行任何类型的转换。您可以从GitHub尝试一下:
用法示例:
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();
$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)
SVG数据操作示例:
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();
$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)
运行Inkscape。输入您的文本。单击菜单>路径>对象到路径 单击另存为。。。并选择纯SVG格式。在方形SVG 3.28中 选择文本,然后进入菜单:形状>形状到路径 文本将转换,每个字形现在是给定字体/字体的可编辑矢量形状
David Spector的Inkscape答案是我最近使用的答案我为SVG字体处理附加了PHP类。您可以在这里看到示例输出:这不支持连字,是吗?@CorySimmons:我不需要支持连字。如果一个连字在svg文件中是单独的字符,它应该可以工作。这一次我不是一个字体专家:)谢谢这是完美的作品,inkscape可以免费下载。我有一个字体的问题,它在Figma中不起作用,我不得不这样做。对任何感兴趣的人来说,字体都是legothick:)我认为这个库比公认的答案更有效。一些获得者会很好。。。比如获取创建的分组路径的宽度和高度。我知道这对于SVG来说没有多大意义,但是类似于php库的getBBox。。。那太好了。