皇家贝蒂斯vs赫塔菲:LaTeX 技巧942:在 LaTeX 中實現縮印效果

巴萨vs赫塔菲全场录像 www.vsttod.com.cn 近日大概重拾了一點對 LaTeX 的興趣,遇見這樣一個問題:如何在 LaTeX 中實現縮印效果(即,將兩頁或更多頁排版在一頁紙上),并且實現水印效果的頁碼?

縮印

以樸素的辦法實現縮印效果并不困難。例如,可以先以 LaTeX 正常輸出文檔,再以 pdfpages 宏包將生成的文檔載入進來排版。不過,這樣的做法擴展性太差,并且需要至少編譯兩份文檔——一份是原始文檔,一份是縮印框架文檔。

更有技巧的辦法,需要深入到 TeX 構建頁面輸出的過程中去?;舊俠此?,我們需要讓 TeX 按往常一樣去構建頁面,但是在 TeX 準備將頁面輸出(shipout)時我們需要插入一個鉤子。這個鉤子做兩件事情:

  • 打斷輸出過程;

  • 將整個頁面內容保存在一個盒子中備用。

我們將保存在盒子里的頁面稱為邏輯頁面(logic pages)。而后,當保存的頁面足夠多時,或沒有更多頁面需要保存時,將這些盒子的內容成比例縮小并列印在頁面上。我們將最終輸出的頁面稱之為物理頁面。

pgfpages 就是這樣做的。它是 PGF 宏集的一部分,因而使用 texdoc pgf 可以看到它的文檔(Section 89)。

首先我們從一個簡單的例子開始:

\documentclass{article}
\usepackage{pgfpages}
\pgfpagesuselayout{2 on 1}[a4paper, landscape, border shrink = 5mm]
\begin{document}
This text is shown on the left.
\clearpage
This text is shown on the right.
\end{document}

這里,\pgfpagesuselayout 命令是實現縮印效果的核心命令。參數 2 on 1 的含義不言自明。其后的可選參數:a4paper 表示物理頁的尺寸是標準 A4 紙;landscape 表示要將物理頁橫過來——畢竟是二合一縮印,這很合理;border shink = 5mm 表示被縮印的邏輯頁會被繼續縮小,并在每個邏輯頁的上下左右四周保留寬度為 5mm 的邊框。

類似地,你也可以縮印 beamer 幻燈片。不過,由于 beamer 幻燈片的邏輯頁本就是橫著的,所以此處不需要在加 landscape 參數了。

相應的,4 on 1 需要加,6 on 1 和 8 on 1 不需要加,以及 16 on 1 又需要加?!?2 on 1 是不存在的……

\documentclass{beamer}
\usepackage{pgfpages}
\pgfpagesuselayout{2 on 1}[a4paper, border shrink=5mm]
\begin{document}
\begin{frame}
This text is shown at the top.
\end{frame}
\begin{frame}
This text is shown at the bottom.
\end{frame}
\end{document}

頁碼

在當前問題中,TeX 默認的頁碼機制實際上是作用在各個邏輯頁上的。但顯然,我們可能會想要為物理頁編上頁碼。這里有兩個問題需要解決:

  • 物理頁的頁碼如何確定?

  • 縮印排版,有效內容字體很小且密集,如何保證物理頁頁碼可見且不影響有效內容的閱讀?

對于第一個問題,有兩種思路。

一是讀取邏輯頁頁碼 page 計數器,然后按 x on 1 的比例做除法,得出物理頁的頁碼。不過,這種方式是有前提的。具體來說,它要求 TeX 的邏輯頁頁碼功能不在縮印的情況下失效,并且它要求 TeX 能正確計算整數除法(向上取整)。總得來說,這是一種快而臟的解法,不推薦。

如果十年以后,你以快而臟的方式做什么事的時候,能想象我在你的肩后看著,然后對自己說:「Dijkstra 不會希望這樣的?!鼓敲炊暈依此?,這就和永生一樣了。
—— Edsger Wybe Dijkstra

另一種思路則更加直接。既然頁碼本質是由計數器實現的,這一計數器隨頁面輸出而自增,而 pgfpages 影響的正是 TeX 頁面輸出的邏輯,那么 pgfpages 內必然有什么地方可以下鉤子來自增該計數器。

\newcommand\pgfshipoutphysicalpage{%
  \ifnum\[email protected]>0\relax%
    \[email protected]%
    \[email protected]%
    \[email protected]%
    \global\pgfphysicalpageemptytrue%
    \global\[email protected]%
  \fi%
}

通過翻閱 pgfpages.sty 的源碼,我們不難發現有以上代碼和物理頁輸出有關??梢運?,PGF 宏集的代碼風格相當好,一眼就能看明白代碼在做什么。顯然,\[email protected] 是在輸出物理頁,而它之前的 \[email protected] 就是將邏輯頁構建成物理頁的過程了。因此,我們需要在 \[email protected] 當中下鉤子;此時我們又要用到老朋友 etoolbox 當中的 \patchcmd 了。

\newcounter{physicalpage}
\makeatletter
\patchcmd{\[email protected]}{%
  \[email protected]
}{%
  \[email protected]
  \stepcounter{physicalpage}%
}{}{}
\makeatother

第二個問題可能有多種解決思路。我偏好于在頁面中央以水印的形式加一個大大的頁碼。四年多以前,我利用 TikZ 實現了水印功能。TikZ 也是 PGF 宏集的一部分,用在這里正好。于是,我們的代碼變為

% require packages: pgfpages, etoolbox, xcolor, tikz
\newcommand{\boxedcontent}[5]{\parbox[b][\paperheight]{\paperwidth}{%
  \vfill%
  \centering%
  \tikz[remember picture, overlay]%
    \node [rotate = #1, scale = #2] at (#3)%
      {\textcolor{#4}{#5}};
  \vfill}}

\newcounter{physicalpage}
\makeatletter
\patchcmd{\[email protected]}{%
  \[email protected]
}{%
  \[email protected]
  \stepcounter{physicalpage}%
  \setbox0\vbox{\makebox[0pt][c]{\boxedcontent{0}{30}{current page.center}{gray!80!cyan!30}{\arabic{physicalpage}}}}%
  \[email protected]
  \pgflowlevel{\pgftransformshift{\pgfpoint{0\pgfphysicalwidth}{0\pgfphysicalheight}}}%
  \[email protected]%
  \[email protected]
}{}{}
\makeatother

實際效果

將以上代碼綜合起來,我做了一個簡單的 demo。

new_1.png

選自:https://liam.page/2019/01/25/reduced-print-in-LaTeX/ 

分享到:
未經允許不得轉載:LaTeX 技巧942:在 LaTeX 中實現縮印效果
已有 條意見

    最新文章

    加載中...
      本站提供專業LaTeX排版、咨詢、定制服務,請點擊下圖咨詢詳情


      全國首個精品的LaTeX視頻教程,大牛帶著你入門,讓LaTeX學習不再糾結,請點擊下圖咨詢詳情

      熱門評論

        聯系我們

        交流QQ群:91940767
        本站QQ號:343083553
        郵箱聯系[email protected]
        淘寶店鋪latexstudio.taobao.com 提供排版,模板定制,培訓,圖片處理,視頻教程等LaTeX服務。


        如果您投稿或者希望加入我們團隊,請發送您的簡歷到[email protected]。

        科技藝術的完美融合,專業精致的排版體驗

        聯系我們聯系我們