如何使 pdf 轮廓在 LuaTeX 中正常工作?

如何使 pdf 轮廓在 LuaTeX 中正常工作?

cwebmac.tex 版本 3.67 --- 2006 年 7 月

以下 Lua 代码使用 将字符串从 UTF-8 转换为 UTF-16BE tex.write,它将打印出 catcode 12 的所有内容,除了空格,这是必需的。我们将代码添加到 的顶部cwebmac.tex

% from navigator.tex
\catcode`\%=12
\directlua{
  local function to8 (...)
    local arg, str = {...}, ""
    for i, num in ipairs(arg) do
      tex.write(string.char(92) .. string.format("%03o", num))
    end
  end
  function toutf16(str)
    tex.write(string.char(92) .. "376" .. string.char(92) .. "377")
    for c in string.utfvalues(str) do
      if c < 0x10000 then
        to8(c / 256, c % 256)
      else
        c = c - 0x10000
        local a, b = c / 1024 + 0xD800, c % 1024 + 0xDC00
        to8(a / 256, a % 256, b / 256, b % 256)
      end
    end
  end
}
\catcode`\%=14

另外,通过如下编辑来使用新toutf16功能:cwebmac.tex

--- /usr/share/texlive/texmf-dist/tex/plain/cweb/cwebmac.tex
+++ /usr/local/cwebmac.tex
@@ -474,7 +474,7 @@
     \pdfoutline goto name {NOS} count -\secno {\outsecname}
     \def\X##1:##2\X{\Xpdf##1:##2\X \firstsecno##1.%
       {\toksF={}\makeoutlinetoks##2\outlinedone\outlinedone}%
-      \pdfoutline goto num \the\toksA \expandafter{\the\toksE}}
+      \pdfoutline goto num \the\toksA {\directlua{toutf16("\luaescapestring{\the\toksE}")}}}
   \else\ifpdf
     \special{pdf: outline -1 << /Title (\outsecname)
       /Dest [ @thispage /FitH @ypos ] >>}
@@ -491,7 +491,7 @@
   \expandafter\xdef\csname#1\endcsname{\the\countA}}
 \def\writebookmarkline#1#2#3#4#5{{%
   \let\(=\let \let\)=\let \let\[=\let \let\]=\let \let\/=\let
-  \pdfoutline goto num #3 count -\expnumber{chunk#2.#3} {#5}}}
+  \pdfoutline goto num #3 count -\expnumber{chunk#2.#3} {\directlua{toutf16("\luaescapestring{#5}")}}}}
 \def\con{\par\vfill\eject % finish the section names
 % \ifodd\pageno\else\titletrue\null\vfill\eject\fi % for duplex printers
   \rightskip 0pt \hyphenpenalty 50 \tolerance 200

在大多数情况下,书签是正确的(顺便问一下,\expandafter第一次更改是为了什么?)。但在这个大纲中

在此处输入图片描述

(和之前有多余的反斜杠)。为什么会出现它们?我是否使用了正确的方法来编码 PDF 轮廓?

通过在单独的文件中使用上述 lua 块和以下代码,我们表明该toutf16函数可以正常工作(即,它不会产生反斜杠):

% ...
\pdfdest num 1 fit
\pdfoutline goto num 1 count 0 {\directlua{toutf16("\luaescapestring{Если файл дан, пробовать открыть *(++argv); continue если неудача}")}}

\bye

相反,当我们通过将其添加到 的顶部来\special{pdf:tounicode UTF8-UCS2}完成所有操作时,一切都顺利进行:dvipdfmxcwebmac.tex

\let\oldshipout\shipout
\def\shipout{\global\let\shipout\oldshipout\afterassignment\myboat\setbox255=}
\def\myboat{\aftergroup\myship}
\def\myship{\setbox255=\vbox{\special{pdf:tounicode UTF8-UCS2}\unvbox255}\shipout\box255}
\let\pdf+

编辑有关详细信息和更好的解决方案,请参阅线。

答案1

toutf16函数应该改为:

\directlua{
  function toutf16(str)
    tex.write(string.char(92) .. "376" .. string.char(92) .. "377")
    for c in string.utfvalues(str) do
      if c < 0x10000 then
        tex.write(string.char(92) .. string.format("%03o", c / 256) ..
                  string.char(92) .. string.format("%03o", c % 256))
      else
        c = c - 0x10000
        local c1 = c / 1024 + 0xD800
        local c2 = c % 1024 + 0xDC00
        tex.write(string.char(92) .. string.format("%03o", c1 / 256) ..
                  string.char(92) .. string.format("%03o", c1 % 256) ..
                  string.char(92) .. string.format("%03o", c2 / 256) ..
                  string.char(92) .. string.format("%03o", c2 % 256))
      end
    end
  end
}

另外,cwebmac.tex必须改为如下:

...
\pdfoutline goto name {NOS} count -\secno {\directlua{toutf16("\outsecname")}}
...
\pdfoutline goto num \the\toksA {\directlua{toutf16(string.gsub([[\the\toksE]],string.char(92),""))}}}
...
\pdfoutline goto num #3 count -\expnumber{chunk#2.#3} {\directlua{toutf16(string.gsub([[#5]],string.char(92),""))}}}}
...

此外, 中还有两个错误cwebmac.tex,在 pdf 模式下使用时会出现。以下是针对这两个错误的修复。

1)这会在每个部分编号后添加额外的空间:

--- /usr/share/texlive/texmf-dist/tex/plain/cweb/cwebmac.tex
+++ cwebmac.tex
@@ -278,7 +278,7 @@
   \sfcode`;=1500 \pretolerance 200 \hyphenpenalty 50 \exhyphenpenalty 50
   \noindent{\let\*=\lapstar\bf\secstar.\quad}%
   \ifpdftex\smash{\raise\baselineskip\hbox to0pt{%
-     \let\*=\empty\pdfdest num \secstar fith}}
+     \let\*=\empty\pdfdest num \secstar fith}}%
   \else\ifpdf\smash{\raise\baselineskip\hbox to0pt{%
      \let\*=\empty\special{%
        pdf: dest (\romannumeral\secstar) [ @thispage /FitH @ypos ]}}}\fi\fi}

2)这将删除所有书签,如果\nosecs使用:

--- /usr/share/texlive/texmf-dist/tex/plain/cweb/cwebmac.tex
+++ cwebmac.tex
@@ -457,6 +457,7 @@
 \def\fin{\par\vfill\eject % this is done when we are ending the index
   \ifpagesaved\null\vfill\eject\fi % output a null index column
   \if L\lr\else\null\vfill\eject\fi % finish the current page
+  \ifpdftex \makebookmarks \fi
   \parfillskip 0pt plus 1fil
   \def\grouptitle{NAMES OF THE SECTIONS}
   \let\topsecno=\nullsec
@@ -470,7 +471,7 @@
   \def\Us{\note{Used in sections}} % crossref for uses of a section
   \def\I{\par\hangindent 2em}\let\*=*
   \ifacro \def\outsecname{Names of the sections} \let\Xpdf\X
-  \ifpdftex \makebookmarks \pdfdest name {NOS} fitb
+  \ifpdftex \pdfdest name {NOS} fitb
     \pdfoutline goto name {NOS} count -\secno {\outsecname}
     \def\X##1:##2\X{\Xpdf##1:##2\X \firstsecno##1.%
       {\toksF={}\makeoutlinetoks##2\outlinedone\outlinedone}%

相关内容