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 网站上的折线图进行了测试,并在每个 texttspan 元素上明确设置 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,只是用您的测试文本替换了标题。)