
Quiero que mis listados acuñados no tengan texto copiable. He encontrado esto:
¿Es posible producir un PDF con texto que no se puede copiar?
Pero después de algunas horas de pruebas no puedo integrarlo con mi documento. Estoy usando un report
documento LaTeX simple y puedo compilarlo con XeTeX o LuaLaTeX.
Documento de ejemplo:
% 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}
Cómo me gustaría que se viera el texto copiado:
Chapter 1 Foo
1.1 Bar
This should be copyable.
And this again should be copyable.
Respuesta1
Primero, estoy totalmente de acuerdo con Jesse Knight:
- Quien hizo este requisito en tu facultad es un sádico.
Pero si usas LuaTeX puedes destruir el mapeo de glifo a Unicode en el archivo PDF creando una característica de fuente especial:
% 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}
Con este enfoque no puedes usar la misma fuente en la parte copiable y en la no copiable, por lo que si cargas cualquier fuente una vez con nocopy
y otra sin, solo se respetará la primera configuración.
Si no desea afectar el texto \texttt "normal" y el material textual, puede seleccionar una fuente especial para los bloques acuñados:
% 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}
Respuesta2
Solución
Quizás mi mayor truco hasta ahora...
main.tex
: compilar con --shell-escape
para permitir\write18
elogiar
\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
: es posible que tengas que chmod +x code.sh
permitir que se ejecute el script
echo \\def\\xstyle{$1} \\def\\xfile{$2} > code-config.tex
pdflatex -interaction=nonstopmode code.tex
convert -trim -density 300 code.pdf $2.png
code.tex
: dóndeconvert
esimagenmagia
\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}
... produciendo main.pdf
:
Notas:
- Siéntete libre de jugar
code.tex
para conseguir el estilo que te guste. - Es posible que descubra que tiene artefactos de alias en las imágenes del código, no hay mucho que podamos hacer
- Si tiene mucho código, el tamaño de su documento será grande
- No me pidas que haga funcionar esto en Windows
- Quien hizo este requisito en tu facultad es un sádico.
Respuesta3
Si estuviera en tu situación, seguiría estos 3 pasos:
- Exportar listado tipográfico acuñado a un PDF (independiente si cabe en la misma página o usar otra clase de documento si el listado abarca varias páginas),
- Ejecute Ghostscript para convertir texto en rutas vectoriales.
- Importe el pdf de ruta vectorial producido por ghostscript en la posición del entorno acuñado.
Aquí hay un ejemplo (independiente):
- Paso 1: digamos que tenemos cada código creado en un archivo independiente (puede haber otras formas de exportar código en línea a un pdf separado, no sé cómo)
% 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}
Ejecute su motor de látex favorito, yo usé >>lualatex --shell-escape minted.tex
. Producirá minted.pdf que se parece a:
- Ejecute el siguiente script usando el comando:
>>./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"
- Importe mintedpath.pdf en el lugar donde planeaba tener su código acuñado.*
Ventaja de esta solución: 1. no se rasterizará nada, 2. el tamaño del archivo será menor en comparación con la exportación e importación de formatos de imagen como jpeg, etc., 3. la calidad de impresión no se degradará,4. Como se solicitó en sus comentarios, esto también funciona para bloques de código largos que abarcan varias páginas, para eso use una clase de documento como un artículo en lugar de uno independiente, y configure la geometría de la página para que coincida con la de su informe. Ghostscript puede convertir un pdf que abarca páginas en un pdf de ruta vectorial equivalente que abarca varias páginas y que luego se puede importar como si estuviera agregando otro documento pdf en su código látex.
- Nota: Dependiendo del visor de PDF, es posible que aún puedas seleccionar estas rutas vectoriales, pero intenta pegarlas en un procesador de textos o editor para darte cuenta de que no copia ningún texto (porque no queda ningún texto en este punto).