如何使 DOT 正确处理 UTF-8 到 PostScript 并具有多个 graph/pages?
How can I make DOT correctly process UTF-8 to PostScript and have multiple graph/pages?
此点源
graph A
{
a;
}
graph B
{
"Enûma Eliš";
}
使用 dot -Tps
编译时生成此错误
Warning: UTF-8 input uses non-Latin1 characters which cannot be handled by this PostScript driver
我可以通过传递 -Tps:cairo
来解决 UTF-8 问题,但是输出中只有图 A——它被截断为一个页面。 -Tpdf
也是如此。我的安装中没有其他可用的 postscript 驱动程序。
我可以将图表拆分成单独的文件,然后将它们连接起来,但我宁愿不这样做。有没有办法进行正确的 UTF-8 处理和多页输出?
显然 dot
PS 驱动程序无法处理旧的 ISO8859-1 以外的其他编码。我觉得它也不能改变字体。
您可以做的一件事是 运行 过滤器来更改 dot
的 PostScript 输出。下面的 Perl 程序就是这样做的,它是对我的一些代码的改编。它将编码从 UTF-8 更改为修改后的 ISO 编码,用额外的字符替换未使用的字符。
当然,输出仍然取决于具有字符的字体。由于 dot
(我认为)只使用默认的 PostScript 字体,所以超出 "standard latin" 的任何内容都是不可能的...
它适用于 Ghostscript 或任何定义 AdobeGlyphList
.
的解释器
过滤器应该这样使用:
dot -Tps graph.dot | perl reenc.pl > output.ps
这里是:
#!/usr/bin/perl
use strict;
use warnings;
use open qw(:std :utf8);
my $ps = do { local $/; <STDIN> };
my %high;
my %in_use;
foreach my $char (split //, $ps) {
my $code = (unpack("C", $char))[0];
if ($code > 127) {
$high{$char} = $code;
if ($code < 256) {
$in_use{$code} = 1;
}
}
}
my %repl;
my $i = 128;
foreach my $char (keys %high) {
if ($in_use{$high{$char}}) {
$ps =~ s/$char/sprintf("\%03o", $high{$char})/ge;
next;
}
while ($in_use{$i}) { $i++; }
$repl{$i} = $high{$char};
$ps =~ s/$char/sprintf("\%03o", $i)/ge;
$i++;
}
my $psprocs = <<"EOPS";
/EncReplacements <<
@{[ join(" ", %repl) ]}
>> def
/RevList AdobeGlyphList length dict dup begin
AdobeGlyphList { exch def } forall
end def
% code -- (uniXXXX)
/uniX { 16 6 string cvrs dup length 7 exch sub exch
(uni0000) 7 string copy dup 4 2 roll putinterval } def
% font code -- glyphname
/unitoname { dup RevList exch known
{ RevList exch get }
{ uniX cvn } ifelse
exch /CharStrings get 1 index known not
{ pop /.notdef } if
} def
/chg-enc { dup length array copy EncReplacements
{ currentdict exch unitoname 2 index 3 1 roll put } forall
} def
EOPS
$ps =~ s{/Encoding EncodingVector def}{/Encoding EncodingVector chg-enc def};
$ps =~ s/(%%BeginProlog)/\n$psprocs/;
print $ps;
生成 PDF 或 SVG 也可以绕过编码问题。
dot -Tpdf chs.dot > chs.pdf
// or
dot -Tsvg chs.dot > chs.svg
此点源
graph A
{
a;
}
graph B
{
"Enûma Eliš";
}
使用 dot -Tps
编译时生成此错误
Warning: UTF-8 input uses non-Latin1 characters which cannot be handled by this PostScript driver
我可以通过传递 -Tps:cairo
来解决 UTF-8 问题,但是输出中只有图 A——它被截断为一个页面。 -Tpdf
也是如此。我的安装中没有其他可用的 postscript 驱动程序。
我可以将图表拆分成单独的文件,然后将它们连接起来,但我宁愿不这样做。有没有办法进行正确的 UTF-8 处理和多页输出?
显然 dot
PS 驱动程序无法处理旧的 ISO8859-1 以外的其他编码。我觉得它也不能改变字体。
您可以做的一件事是 运行 过滤器来更改 dot
的 PostScript 输出。下面的 Perl 程序就是这样做的,它是对我的一些代码的改编。它将编码从 UTF-8 更改为修改后的 ISO 编码,用额外的字符替换未使用的字符。
当然,输出仍然取决于具有字符的字体。由于 dot
(我认为)只使用默认的 PostScript 字体,所以超出 "standard latin" 的任何内容都是不可能的...
它适用于 Ghostscript 或任何定义 AdobeGlyphList
.
过滤器应该这样使用:
dot -Tps graph.dot | perl reenc.pl > output.ps
这里是:
#!/usr/bin/perl
use strict;
use warnings;
use open qw(:std :utf8);
my $ps = do { local $/; <STDIN> };
my %high;
my %in_use;
foreach my $char (split //, $ps) {
my $code = (unpack("C", $char))[0];
if ($code > 127) {
$high{$char} = $code;
if ($code < 256) {
$in_use{$code} = 1;
}
}
}
my %repl;
my $i = 128;
foreach my $char (keys %high) {
if ($in_use{$high{$char}}) {
$ps =~ s/$char/sprintf("\%03o", $high{$char})/ge;
next;
}
while ($in_use{$i}) { $i++; }
$repl{$i} = $high{$char};
$ps =~ s/$char/sprintf("\%03o", $i)/ge;
$i++;
}
my $psprocs = <<"EOPS";
/EncReplacements <<
@{[ join(" ", %repl) ]}
>> def
/RevList AdobeGlyphList length dict dup begin
AdobeGlyphList { exch def } forall
end def
% code -- (uniXXXX)
/uniX { 16 6 string cvrs dup length 7 exch sub exch
(uni0000) 7 string copy dup 4 2 roll putinterval } def
% font code -- glyphname
/unitoname { dup RevList exch known
{ RevList exch get }
{ uniX cvn } ifelse
exch /CharStrings get 1 index known not
{ pop /.notdef } if
} def
/chg-enc { dup length array copy EncReplacements
{ currentdict exch unitoname 2 index 3 1 roll put } forall
} def
EOPS
$ps =~ s{/Encoding EncodingVector def}{/Encoding EncodingVector chg-enc def};
$ps =~ s/(%%BeginProlog)/\n$psprocs/;
print $ps;
生成 PDF 或 SVG 也可以绕过编码问题。
dot -Tpdf chs.dot > chs.pdf
// or
dot -Tsvg chs.dot > chs.svg