禁用从铸造清单复制文本

禁用从铸造清单复制文本

我希望我的铸造清单不包含可复制的文本。我发现了这一点:

是否可以生成包含不可复制文本的 PDF?

但经过几个小时的尝试,我无法将其与我的文档集成。我使用的是一个简单的 LaTeXreport文档,可以使用 XeTeX 或 LuaLaTeX 构建它。

示例文档:

% lualatex -shell-escape minted.tex

\begin{filecontents*}{test.rb}
# this should not be copyable
def hello
  "world"
end
\end{filecontents*}

\documentclass[12pt,twoside,openright,a4paper]{report}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage[dvipsnames]{xcolor}
\usepackage{minted}
\setmainfont{Times New Roman}
\definecolor{bg}{rgb}{0.95,0.95,0.95}
\begin{document}
\chapter{Foo}
\section{Bar}
This should be copyable.
\inputminted[linenos, numbersep=5pt, tabsize=2, bgcolor=bg]{ruby}{test.rb}
And this again should be copyable.
\end{document}

文档

我希望复制的文本看起来像:

Chapter 1 Foo
1.1 Bar
This should be copyable.

And this again should be copyable.

答案1

首先,我完全同意 Jesse Knight 的观点:

  • 你们学院提出这个要求的人是个虐待狂

但是如果您使用 LuaTeX,您可以通过创建特殊的字体功能来破坏 PDF 文件中的字形到 unicode 映射:

% lualatex -shell-escape minted.tex

\begin{filecontents*}{test.rb}
# this should not be copyable
def hello
  "world"
end
\end{filecontents*}

\documentclass[12pt,twoside,openright,a4paper]{report}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage[dvipsnames]{xcolor}
\usepackage{minted}
\setmainfont{Times New Roman}
\usepackage{luacode}
\begin{luacode*}
  local function nocopy(tfmdata)
    for _, c in next, tfmdata.characters do
      c.tounicode = nil
    end
  end
  fonts.handlers.otf.features.register {
    name        = "nocopy",
    description = "disallow copying for this font",
    manipulators = {
        base = nocopy,
        node = nocopy,
        plug = nocopy,
    }
  }
\end{luacode*}
\setmonofont[RawFeature=nocopy]{Latin Modern Mono}
\definecolor{bg}{rgb}{0.95,0.95,0.95}
\begin{document}
\chapter{Foo}
\section{Bar}
This should be copyable.
\inputminted[linenos, numbersep=5pt, tabsize=2, bgcolor=bg]{ruby}{test.rb}
And this again should be copyable.
\end{document}

使用这种方法,您不能在可复制和不可复制的部分使用相同的字体,因此如果您一次加载带有任何字体nocopy和一次不带有任何字体,则只会遵守第一个设置。

如果您不想影响“常规” \texttt 文本和逐字材料,您可以为铸造块选择特殊字体:

% lualatex -shell-escape minted.tex

\begin{filecontents*}{test.rb}
# this should not be copyable
def hello
  "world"
end
\end{filecontents*}

\documentclass[12pt,twoside,openright,a4paper]{report}
\usepackage[T1]{fontenc}
\usepackage{fontspec}
\usepackage[dvipsnames]{xcolor}
\usepackage{minted}
\setmainfont{Times New Roman}
\usepackage{luacode}
\begin{luacode*}
  local function nocopy(tfmdata)
    for _, c in next, tfmdata.characters do
      c.tounicode = nil
    end
  end
  fonts.handlers.otf.features.register {
    name        = "nocopy",
    description = "disallow copying for this font",
    manipulators = {
        base = nocopy,
        node = nocopy,
        plug = nocopy,
    }
  }
\end{luacode*}
\newfontfamily\nocopyfont[RawFeature=nocopy]{Courier New}
\renewcommand\myFont{\nocopyfont}
\fvset{fontfamily=myFont}
\definecolor{bg}{rgb}{0.95,0.95,0.95}
\begin{document}
\chapter{Foo}
\section{Bar}
This should be copyable.
\inputminted[linenos, numbersep=5pt, tabsize=2, bgcolor=bg]{ruby}{test.rb}
And this again should be copyable (\texttt{This too}).
{
\tracingall\nocopyfont
}
\end{document}

答案2

解决方案

也许是我迄今为止最大的一次黑客攻击...

main.tex:编译以--shell-escape允许\write18表彰

\documentclass[12pt,twoside,openright,a4paper]{report}
\usepackage{graphicx}
\newcommand{\nocopycode}[2]{%
  \immediate\write18{./code.sh #1 #2}
  \\[\textfloatsep]
  \includegraphics[width=\linewidth]{{#2}.png}%
  \\[\textfloatsep]
}
\usepackage{listings}
\begin{document}
\chapter{Foo}
\section{Bar}
This should be copyable.
\nocopycode{ruby}{hello.rb}
And this again should be copyable.
\end{document}

code.sh:你可能必须chmod +x code.sh允许脚本执行

echo \\def\\xstyle{$1} \\def\\xfile{$2} > code-config.tex
pdflatex -interaction=nonstopmode code.tex
convert -trim -density 300 code.pdf $2.png

code.texconvert哪里图像魔法

\documentclass{article}
\usepackage{listings}
\usepackage{xcolor}
\lstset{
  basicstyle=\ttfamily,
  backgroundcolor=\color{lightgray},
}
\input{code-config.tex}
\begin{document}
  \pagenumbering{gobble}
  \lstinputlisting[language={\xstyle}]{\xfile}
\end{document}

... 生产main.pdf

输出

笔记:

  • 随意尝试,code.tex获得你喜欢的造型
  • 您可能会发现代码图像中存在混叠伪影,我们无能为力
  • 如果你有很多代码,你的文档大小将会很大
  • 不要让我在 Windows 上实现这个功能
  • 你们学院提出这个要求的人是个虐待狂

答案3

如果我处于你的情况,我会遵循以下 3 个步骤:

  1. 将排版好的列表导出为 pdf(如果适合同一页则为独立文件,如果列表跨越多页则使用另一个文档类),
  2. 运行 ghostscript 将文本转换为矢量路径,
  3. 在minted环境的位置导入ghostscript生成的矢量路径pdf。

这是一个示例(独立):

  1. 步骤 1:假设我们在一个独立文件中拥有所有铸造的代码(可能还有其他方法可以将内联代码导出到单独的 pdf,但我不知道如何操作)
% minted.tex
\documentclass{standalone}
\usepackage{minted}
\begin{document}
\begin{minipage}[t]{0.5\textwidth}
\begin{minted}{bash}
echo "Hello, world!"
\end{minted}
\end{minipage}
\end{document}

运行你最喜欢的 latex 引擎,我使用了>>lualatex --shell-escape minted.tex。它将生成如下内容的 minted.pdf: 可复制的文本

  1. 使用命令运行以下脚本:>>./fonttopath.sh minted.pdf mintedpath.pdf
% fonttopath.sh
#!/bin/sh
if [ "x$1" = "x" -o "x$2" = "x" ]; then
        echo Usage: `basename "$0"` "<input.pdf>" "<output.pdf>" >&2
        exit 1
fi
gs -o "$2" -sDEVICE=pdfwrite -dNOCACHE -dNoOutputFonts -dNOSUBSTDEVICECOLORS -c 60000000 setvmthreshold -f "$1"
  1. 在您计划保存铸造代码的位置导入 mintedpath.pdf。*

此解决方案的优点:1. 不会对任何内容进行栅格化;2. 与导出和导入 jpeg 等图像格式相比,文件大小会更小;3. 打印质量不会下降;4. 根据您的评论要求,这也适用于跨多页的长代码块,为此使用 documentclass 如 article 而不是 standalone,并将页面的几何形状设置为与您的报告相匹配。 Ghostscript 可以将跨页的 pdf 转换为跨多页的等效矢量路径 pdf,然后可以将其导入,就像您在 latex 代码中添加另一个 pdf 文档一样。

  • 注意:根据 pdf 查看器的不同,您可能仍然可以选择这些矢量路径,但尝试将它们粘贴到文字处理器或编辑器中,您会发现它不会复制任何文本(因为此时没有剩余文本)。

相关内容