tcpdf 中的 SVG 渲染器是否不支持 00FF 以上的 UTF-8 字符?
Does the SVG renderer in tcpdf not support UTF-8 characters above 00FF?
我正在尝试将来自前端 javascript 的 highcharts SVG 输出的希腊文和拉丁文字符的公式打印到后端 php 的 TCPDF 中。
这是 SVG 文件的相关部分:
β(ϴᶜ)m-¹ sr-¹
当呈现为 pdf 时,打印如下:
?(??)m-1 sr-1
我也将这些字符呈现为 pdf 页面上的文本,效果很好。
初始化代码如下:
parent::__construct('P', 'mm','Letter', true, 'UTF-8', false, true);
我正在使用自定义 TTF 字体:
$this->documentFont = \TCPDF_FONTS::addTTFfont($ttfFont, 'TrueTypeUnicode',
'', 96);
调用打印单元格的代码,正确呈现 00FF 以上的扩展 UTF-8 字符集:
$this->WriteHTMLCell($x, $y, $this->text);
这是渲染 highcharts SVG 的调用,无法正确渲染 00FF 以上的字符:
$this->ImageSVG('@'.$image, $x, $y, $width, $height);
为了变通,我在 UTF-8 的 00FF 子集中发现了与我需要的字符相似的字符:
ß(Øc)m-¹ sr-¹
它并不完美,但作为一种变通方法,它会起作用,直到我弄清楚为什么 SVG 渲染不能正确打印 00FF 以上的 unicode 字符。
我尝试在 00FF 以上的 unicode 范围内向 Highchart 轴添加字符。这就是我发现这似乎是 SVG 渲染器将打印的上限的原因。
我还尝试确保在 PDF 渲染器的前端和后端使用相同的字体。 PDF 渲染器中使用的自定义 TTF 字体与我指定用于前端、CSS 和 HighCharts 配置的字体相同。
正如我在下面的代码中所示,我还尝试使用 unescape();
包围来自 HighCharts 的 SVG 渲染器
HighCharts 渲染:
/**
* inserts a highchart line chart into the HTML document at specified point
* @param {HTMLElement} chartContainer where this chart is rendered to
* @param {object} chartConfig config object with chart options.
* @param {array} seriesData two dimensional array to plot
* @param {string} seriesName name of series being plotted
* @return {Highcharts} highcharts object to be inserted - allows later referencing
*/
function addChart(chartContainer, chartConfig, seriesData, seriesName)
{
return new Highcharts.Chart({
chart: {
animation: false,
type: 'line',
renderTo: chartContainer,
zoomType: 'y'
},
title: {
text: chartConfig.title
},
xAxis: {
title: {
text: 'DUT DATA - ' + chartConfig.uom
},
gridLineDashStyle: 'solid',
gridLineWidth: 2,
minorTicks: true,
minorGridLineDashStyle: 'longdash',
startOnTick: true,
endOnTick: true,
max: chartConfig.xMax,
min: chartConfig.xMin
},
yAxis: {
title: {
text: 'Residuals'
},
gridLineDashStyle: 'solid',
gridLineWidth: 2,
minorTicks: true,
minorGridLineDashStyle: 'longdash',
tickWidth: 2,
lineWidth: 1,
max: chartConfig.yMax,
min: chartConfig.yMin
},
plotOptions: {
line: {
animation: false
}
},
series: [{
name: seriesName,
point: {
events: {
click: function () {
console.log('Category: ' + this.category + ', value: ' + this.y);
}
}
},
animation: false,
showInLegend: true,
data: seriesData
}],
exporting: {
enabled: true
},
credits: {
enabled: false
}
});
}
SVG 创建:
chart[i].svgData = unescape(chart[i].getSVG());
我希望 TCPDF SVG 渲染器打印整个 UTF-8 范围。 SVG 渲染器似乎无法渲染 00FF 以上的字符。
SVG 解析器启动时要做的第一件事就是初始化 SVG 样式。这样做时,它将 font-family
设置为 Helvetica。因此,您需要确保在 SVG 中明确使用自定义字体。
我用 Highcharts 网站上的折线图进行了测试,并在每个 text
和 tspan
元素上明确设置 font-family
属性似乎可以解决问题。不可否认,这是一个相当生硬的解决方案,但您可以对其进行调整以使其更有针对性。我在下面附上了一张截图。 (Highcharts 有时会在 style
属性中包含不同的字体系列,但 font-family
属性为我们提供了一种简单的方法来覆盖它,而无需解析和更新 style
属性字符串。)
<?php
$svgdom = new DOMDocument();
//My extract from Highcharts did not include the XML declaration, so I add it.
//TCPDF might assume it's UTF-8, so this may not be needed.
//[Edit: Checked, TCPDF does, but we're working on it before that stage I figure
//it's best to include the xml declaration if it's not already there.]
$svgdom->loadXML('<?xml version="1.0" encoding="utf-8" ?>'.$image);
$xpath = new DOMXPath($svgdom);
$textitems = $xpath->query('//*[local-name() = "text" or local-name() = "tspan"]');
foreach($textitems as $element) {
$element->setAttribute('font-family', $font);
}
$image = $svgdom->saveXML();
(我在下面的示例中使用了 Dejavusans,只是用您的测试文本替换了标题。)
我正在尝试将来自前端 javascript 的 highcharts SVG 输出的希腊文和拉丁文字符的公式打印到后端 php 的 TCPDF 中。
这是 SVG 文件的相关部分:
β(ϴᶜ)m-¹ sr-¹
当呈现为 pdf 时,打印如下:
?(??)m-1 sr-1
我也将这些字符呈现为 pdf 页面上的文本,效果很好。
初始化代码如下:
parent::__construct('P', 'mm','Letter', true, 'UTF-8', false, true);
我正在使用自定义 TTF 字体:
$this->documentFont = \TCPDF_FONTS::addTTFfont($ttfFont, 'TrueTypeUnicode',
'', 96);
调用打印单元格的代码,正确呈现 00FF 以上的扩展 UTF-8 字符集:
$this->WriteHTMLCell($x, $y, $this->text);
这是渲染 highcharts SVG 的调用,无法正确渲染 00FF 以上的字符:
$this->ImageSVG('@'.$image, $x, $y, $width, $height);
为了变通,我在 UTF-8 的 00FF 子集中发现了与我需要的字符相似的字符:
ß(Øc)m-¹ sr-¹
它并不完美,但作为一种变通方法,它会起作用,直到我弄清楚为什么 SVG 渲染不能正确打印 00FF 以上的 unicode 字符。
我尝试在 00FF 以上的 unicode 范围内向 Highchart 轴添加字符。这就是我发现这似乎是 SVG 渲染器将打印的上限的原因。
我还尝试确保在 PDF 渲染器的前端和后端使用相同的字体。 PDF 渲染器中使用的自定义 TTF 字体与我指定用于前端、CSS 和 HighCharts 配置的字体相同。
正如我在下面的代码中所示,我还尝试使用 unescape();
包围来自 HighCharts 的 SVG 渲染器HighCharts 渲染:
/**
* inserts a highchart line chart into the HTML document at specified point
* @param {HTMLElement} chartContainer where this chart is rendered to
* @param {object} chartConfig config object with chart options.
* @param {array} seriesData two dimensional array to plot
* @param {string} seriesName name of series being plotted
* @return {Highcharts} highcharts object to be inserted - allows later referencing
*/
function addChart(chartContainer, chartConfig, seriesData, seriesName)
{
return new Highcharts.Chart({
chart: {
animation: false,
type: 'line',
renderTo: chartContainer,
zoomType: 'y'
},
title: {
text: chartConfig.title
},
xAxis: {
title: {
text: 'DUT DATA - ' + chartConfig.uom
},
gridLineDashStyle: 'solid',
gridLineWidth: 2,
minorTicks: true,
minorGridLineDashStyle: 'longdash',
startOnTick: true,
endOnTick: true,
max: chartConfig.xMax,
min: chartConfig.xMin
},
yAxis: {
title: {
text: 'Residuals'
},
gridLineDashStyle: 'solid',
gridLineWidth: 2,
minorTicks: true,
minorGridLineDashStyle: 'longdash',
tickWidth: 2,
lineWidth: 1,
max: chartConfig.yMax,
min: chartConfig.yMin
},
plotOptions: {
line: {
animation: false
}
},
series: [{
name: seriesName,
point: {
events: {
click: function () {
console.log('Category: ' + this.category + ', value: ' + this.y);
}
}
},
animation: false,
showInLegend: true,
data: seriesData
}],
exporting: {
enabled: true
},
credits: {
enabled: false
}
});
}
SVG 创建:
chart[i].svgData = unescape(chart[i].getSVG());
我希望 TCPDF SVG 渲染器打印整个 UTF-8 范围。 SVG 渲染器似乎无法渲染 00FF 以上的字符。
SVG 解析器启动时要做的第一件事就是初始化 SVG 样式。这样做时,它将 font-family
设置为 Helvetica。因此,您需要确保在 SVG 中明确使用自定义字体。
我用 Highcharts 网站上的折线图进行了测试,并在每个 text
和 tspan
元素上明确设置 font-family
属性似乎可以解决问题。不可否认,这是一个相当生硬的解决方案,但您可以对其进行调整以使其更有针对性。我在下面附上了一张截图。 (Highcharts 有时会在 style
属性中包含不同的字体系列,但 font-family
属性为我们提供了一种简单的方法来覆盖它,而无需解析和更新 style
属性字符串。)
<?php
$svgdom = new DOMDocument();
//My extract from Highcharts did not include the XML declaration, so I add it.
//TCPDF might assume it's UTF-8, so this may not be needed.
//[Edit: Checked, TCPDF does, but we're working on it before that stage I figure
//it's best to include the xml declaration if it's not already there.]
$svgdom->loadXML('<?xml version="1.0" encoding="utf-8" ?>'.$image);
$xpath = new DOMXPath($svgdom);
$textitems = $xpath->query('//*[local-name() = "text" or local-name() = "tspan"]');
foreach($textitems as $element) {
$element->setAttribute('font-family', $font);
}
$image = $svgdom->saveXML();
(我在下面的示例中使用了 Dejavusans,只是用您的测试文本替换了标题。)