Php SVG中未对齐的文本 问题:

Php SVG中未对齐的文本 问题:,php,svg,gd,kerning,Php,Svg,Gd,Kerning,如何将PHP(5.2.17)中GD库的内核与SVG(1.1)适当匹配 问题 PNG和SVG文件文本不相同。克宁似乎已经停止了 处境 我有一个web应用程序,它从一些文本和位置数据创建SVG文件和图像文件(PNG) 目前,这两种实现都“起作用”,就像所有东西都在被创建一样。SVG文件工作正常,PNG工作正常。我遇到的问题是文本没有对齐。内核似乎已经关闭了 PNG将成为我们的基线(我们试图复制的内容) 我想要什么 我想让“行”中的“l”与第二行的最后一个“l”对齐。 我试过的 我已经确保SVG和

如何将PHP(5.2.17)中GD库的内核与SVG(1.1)适当匹配

问题 PNG和SVG文件文本不相同。克宁似乎已经停止了

处境 我有一个web应用程序,它从一些文本和位置数据创建SVG文件和图像文件(PNG)

目前,这两种实现都“起作用”,就像所有东西都在被创建一样。SVG文件工作正常,PNG工作正常。我遇到的问题是文本没有对齐。内核似乎已经关闭了

PNG将成为我们的基线(我们试图复制的内容)

我想要什么 我想让“行”中的“l”与第二行的最后一个“l”对齐。

我试过的
  • 我已经确保SVG和PNG文件使用相同的字体
  • 我已经用SVG对字体进行了base64编码,以确保它是相同的字体
  • 我牺牲了一只山羊
额外的
  • PHP将被提升到5.3,在我尝试过的所有PHP5.3服务器上,我都有相同的输出
  • SVG版本也可以更改
  • SVG可以使用分组和视图框。我只是还没有完全掌握它们
演示

$svg .= "fill='rgb(0,0,0)'>{$line2['text']}</text>";
$line2['width'] = $line2['width'] + 2;
$svg .= "fill='#000' textLength='{$line2['width']}px'>$line2['text']}</text>";

来源
好的,这里有很多来源。我尽量简化它;然而,剩下的东西是必要的(至少是为了让每个人都能实际访问它)


EOT;
//第1行
$svg.=“\r\n\t{$line1['text']}”;
//第2行
$svg.=“\r\n\t{$line2['text']}”;
//关闭SVG
$svg.=“\r\n”;
$file=fopen('text_align.svg','w');
fwrite($file,$svg);
fclose($文件);
if(设置($\u GET['download'])和&!空($\u GET['download']))
{
如果($_GET['download']=='SVG')
{
$file='text_align.svg';
$header=“内容类型:图像/svg+xml”;
}
elseif($\u GET['download']=='IMAGE')
{
$file='text_align.png';
$header=“内容类型:图像/png”;
}
if(isset($header))
{
页眉($页眉);
标题('Content-Disposition:attachment;filename=“.”.$file.'”);
回显文件\u获取\u内容($file);
}
}
其他的
{
?>   
下载图片:


下载SVG:
更新/进展 更新1

$svg .= "fill='rgb(0,0,0)'>{$line2['text']}</text>";
$line2['width'] = $line2['width'] + 2;
$svg .= "fill='#000' textLength='{$line2['width']}px'>$line2['text']}</text>";
我不确定这是否与服务器上生成的映像和客户端上呈现的文本有关。我当前正在运行Windows构建,但如果必须,我将抛出一个CentOS VM,并在VM上测试映像,以及在VM内的浏览器中测试映像的外观

更新2

$svg .= "fill='rgb(0,0,0)'>{$line2['text']}</text>";
$line2['width'] = $line2['width'] + 2;
$svg .= "fill='#000' textLength='{$line2['width']}px'>$line2['text']}</text>";
我已经尝试了各种嵌入字体的方法。到目前为止,结果都是一样的。我将尝试一种转换,看看是否有效

更新3

$svg .= "fill='rgb(0,0,0)'>{$line2['text']}</text>";
$line2['width'] = $line2['width'] + 2;
$svg .= "fill='#000' textLength='{$line2['width']}px'>$line2['text']}</text>";
好的!取得了一些进展!我发现SVG工作组委员会的人建议从SVG文档中删除doctype。我这样做了,现在我得到了一些不同的结果。我不确定它们有多好,但我现在肯定看到了不同的东西。这是一个加号

更新4
我已经尝试过明确设置每个字符之间的间距(而不仅仅是句子),但仍然没有骰子。这似乎抵消了一切。而且看起来更难看。虽然该函数运行良好,对图像有用(可能是分析验证码?)

下面是代码,如果有人感兴趣:

/**
* Function: Returns the space between letters, and the width of letters.
*           The first index is set to 0, as that is where it starts
*           Since spaces don't register (no pixels), strlen may not work.
* $image to analyze vertical gaps (from imagecreatetruecolor)
*/
function get_letter_dimensions($image)
{
   $bg           = imagecolorallocatealpha($image, 0, 0, 0, 127);
   $height       = imagesy($image) - 1; // was causing issues without
   $width        = imagesx($image);
   $bottom       = 0;
   $right        = 0;
   $letter_space = array(0=>0); // This holds the pixels between the letters
   $letter_width = array(0=>0); // This holds the width of the letters
   $y            = 0;
   $spacing      = 0;
   $lettering    = 0;
   $data         = array();

   for ($x = 0 ; $x < $width ; $x++) 
   {
      while((imagecolorat($image, $x, $y) == $bg) && ($y < ($height))) $y++;

      if($y == $height) 
      {
         if($lettering) $letter_width[] = $lettering;
         $lettering = 0;
         $spacing++;
      }
      else
      {
         if($spacing) $letter_space[] = $spacing;
         $spacing = 0;
         $lettering++;
      }
      $y = 0;
   }

   foreach($letter_space as $k=>$val) $data[$k] = $val + $letter_width[$k];

   return $data;      
}
/**
*函数:返回字母之间的空格和字母的宽度。
*第一个索引设置为0,因为它是从0开始的
*由于空格不注册(没有像素),strlen可能无法工作。
*$image用于分析垂直间距(来自ImageCreateTureColor)
*/
函数获取字母尺寸($image)
{
$bg=imagecolorallocatealpha($image,0,0,0127);
$height=imagesy($image)-1;//正在导致没有
$width=imagesx($image);
$bottom=0;
$right=0;
$letter_space=array(0=>0);//它保存字母之间的像素
$letter_width=array(0=>0);//它保存字母的宽度
$y=0;
$间距=0;
$letting=0;
$data=array();
对于($x=0;$x<$width;$x++)
{
而((imagecolorat($image,$x,$y)=$bg)和($y<($height)))$y++;
如果($y==$height)
{
如果($lettering)$letter_width[]=$lettering;
$letting=0;
$spating++;
}
其他的
{
如果($spating)$letter_space[]=$spating;
$间距=0;
$lettering++;
}
$y=0;
}
foreach($k=>$val的字母空间)$data[$k]=$val+$letter_宽度[$k];
返回$data;
}
更新5

$svg .= "fill='rgb(0,0,0)'>{$line2['text']}</text>";
$line2['width'] = $line2['width'] + 2;
$svg .= "fill='#000' textLength='{$line2['width']}px'>$line2['text']}</text>";
名为“textLength”的强大属性对我有一些帮助!我还没有让它完全工作,但它肯定是一个显著的改进。我仍然存在一些缩放问题。我不确定它是否可以接受,但是,它非常接近

更新6

下面是我发现textLength元素的作用:

所以,正如你所看到的,第二行“line up last L”看起来非常完美,就排队而言,没有textLength。然而,第一行“一行中有多个单词”看起来很糟糕。一切都很遥远。但是,有了textLength,它似乎更适合

更新7

$svg .= "fill='rgb(0,0,0)'>{$line2['text']}</text>";
$line2['width'] = $line2['width'] + 2;
$svg .= "fill='#000' textLength='{$line2['width']}px'>$line2['text']}</text>";
我想我解决了这个问题。我没有只做“textLength”并将其设置为提供的长度,而是将其调整了2px,并且排列得很好。微小的差异可能仅仅是因为服务器上的像素宽度与SVG放置的粒度不同。我不知道是否还有其他方法可以改变它