From e0c6872cf40896c7be36b11dcc744620f10adf1d Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Mon, 2 Sep 2019 13:46:59 +0900
Subject: Initial commit

---
 macros/latex/contrib/pdfoverlay/pdfoverlay.dtx | 647 +++++++++++++++++++++++++
 1 file changed, 647 insertions(+)
 create mode 100644 macros/latex/contrib/pdfoverlay/pdfoverlay.dtx

(limited to 'macros/latex/contrib/pdfoverlay/pdfoverlay.dtx')

diff --git a/macros/latex/contrib/pdfoverlay/pdfoverlay.dtx b/macros/latex/contrib/pdfoverlay/pdfoverlay.dtx
new file mode 100644
index 0000000000..15425f7ed5
--- /dev/null
+++ b/macros/latex/contrib/pdfoverlay/pdfoverlay.dtx
@@ -0,0 +1,647 @@
+% \iffalse meta-comment
+%
+% Copyright (c) 2018 David Purton <dcpurton@marshwiggle.net>
+%
+% This work may be distributed and/or modified under the conditions of
+% the LaTeX Project Public License, either version 1.3c of this license
+% or (at your option) any later version. The latest version of this
+% license is in
+%    http://www.latex-project.org/lppl.txt
+% and version 1.3c or later is part of all distributions of LaTeX
+% version 2005/12/01 or later.
+%
+%<*driver>
+\documentclass[a4paper]{l3doc}
+\begin{document}
+\DocInput{\jobname.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \changes{v1.0}{2018/05/08}{First public release}
+%
+% \title{The \pkg{pdfoverlay} package}
+% \author{David Purton\thanks{Email: \url{dcpurton@marshwiggle.net}}}
+% \date{2018/05/08 v1.0}
+%
+% \maketitle
+%
+% \begin{abstract}
+%   This \pkg{pdfoverlay} package provides a simple interface to overlay text
+%   on to an existing PDF. The text to be overlayed is typeset and positioned
+%   normally as you would any other \LaTeX{} document. Some or all of the pages
+%   of the PDF can be included and not all pages of the PDF need have overlayed
+%   text. It's also possible to include text between pages of the PDF.
+% \end{abstract}
+%
+% \tableofcontents
+%
+% \begin{documentation}
+%
+% \section{Introduction}
+%
+% It's often desirable to take an exisiting PDF and easily add annotations or
+% text overlaying the PDF. This might arise if you wish to add comments to a
+% PDF, fill in a PDF form, or add text to a PDF where space has been left for
+% notes.
+%
+% This package provides a simple interface to do this without having to resort
+% to inserting one page at a time. Some or all of the pages of the PDF can be
+% included and not all pages of the PDF need have overlayed text. It's also
+% possible to include text between pages of the PDF.
+%
+% Another advantage of this package is that the overlayed text can be set as
+% normal flowing from one page to another or with manual page breaks if you
+% wish. It's also possible to use any standard method to position text at
+% arbitrary places on a given page.
+%
+% \section{Acknowlegements}
+%
+% This package is particularly indebted to the \pkg{pdfpages} package to count
+% the number of pages in the PDF file, the \pkg{eso-pic} package to output
+% pages from the PDF file in the document background, and the \pkg{everypage}
+% package to ensure that PDF pages are inserted at every page in the document.
+%
+% \section{Bug Reports and Feature Requests}
+%
+% Bug reports and feature requests can be made at the \pkg{pdfoverlay} package
+% GitHub respoitory. See \url{https://github.com/dcpurton/pdfoverlay}.
+%
+% \section{Documentation}
+%
+% \subsection{Basic Usage}
+%
+% At it's simplest, the only thing required is to specify the PDF to overlay
+% with text and then begin typing your document. The pages of the PDF will be
+% inserted as you go automatically. If your text takes up more pages than the
+% PDF then any remaining text is inserted on blank pages.
+% \begin{verbatim}
+%   \documentclass{article}
+%   \usepackage{pdfoverlay}
+%   \pdfoverlaySetPDF{filename.pdf}
+%   \begin{document}
+%   ...
+%   \end{document}
+% \end{verbatim}
+% The PDF will be centered on and scaled to fit the document page size while
+% keeping a fixed aspect ratio.
+%
+% \subsection{Main Interface}
+%
+% \begin{function}{\pdfoverlaySetPDF, \pdfoverlay_set_pdf:n}
+%   \begin{syntax}
+%     \cs{pdfoverlaySetPDF} \Arg{PDF filename}
+%   \end{syntax}
+%   Specify the \meta{PDF filename} to overlay text on to. This function must
+%   be called first. It can be used either in the preamble or at any point in
+%   the document body. It is possible to call this more than once to include
+%   multiple PDF files. If the specified \meta{PDF filename} cannot be found an
+%   error is generated.
+% \end{function}
+%
+% \begin{function}{\pdfoverlaySetGraphicsOptions,
+%                  \pdfoverlay_set_graphics_options:n}
+%   \begin{syntax}
+%     \cs{pdfoverlaySetGraphicsOptions} \Arg{Options}
+%   \end{syntax}
+%   Set the \meta{Options} to be passed to \cs{includegraphics} when each page
+%   of the PDF is output. See the \pkg{graphicx} package documentation for
+%   valid options. \textbf{Note} that it is not necessary to specify the
+%   \texttt{page} option as this is appended automatically in the right format.
+%   The default options are: \texttt{keepaspectratio,
+%   width=}\cs{paperwidth}\texttt{, height=}\cs{paperheight}.
+% \end{function}
+%
+% \begin{function}{\pdfoverlayIncludeToPage, \pdfoverlay_include_to_page:n}
+%   \begin{syntax}
+%     \cs{pdfoverlayIncludeToPage} \Arg{page number}
+%   \end{syntax}
+%   Output all pages in the PDF file up until the specified \meta{page number}.
+%   If the specified \meta{page number} does not evaluate to an integer or does
+%   not exist in the PDF an error is generated.
+% \end{function}
+%
+% \begin{function}{\pdfoverlayIncludeToLastPage, \pdfoverlay_include_to_last_page:}
+%   \begin{syntax}
+%     \cs{pdfoverlayIncludeToLastPage}
+%   \end{syntax}
+%   Output all remaining pages in the PDF file.
+% \end{function}
+%
+% \begin{function}{\pdfoverlaySkipToPage, \pdfoverlay_skip_to_page:n}
+%   \begin{syntax}
+%     \cs{pdfoverlaySkipToPage} \Arg{page number}
+%   \end{syntax}
+%   Skip to the specified \meta{page number}. This can be before or after the
+%   current page in the PDF file. If the specified \meta{page number} does not
+%   evaluate to an integer or does not exist in the PDF an error is generated.
+% \end{function}
+%
+% \begin{function}{\pdfoverlayPauseOutput, \pdfoverlay_pause_output:}
+%   \begin{syntax}
+%     \cs{pdfoverlayPauseOutput}
+%   \end{syntax}
+%   Pause outputting pages from the PDF file. Any subsequent text will by
+%   output on blank pages.
+% \end{function}
+%
+% \begin{function}{\pdfoverlayResumeOutput, \pdfoverlay_resume_output:}
+%   \begin{syntax}
+%     \cs{pdfoverlayResumeOutput}
+%   \end{syntax}
+%   Resume outputting pages from the PDF file.
+% \end{function}
+%
+% \end{documentation}
+%
+% \begin{implementation}
+%
+% \section{Implementation}
+%
+%    \begin{macrocode}
+%<*package>
+%<@@=pdfoverlay>
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\RequirePackage{xparse}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\ProvidesExplPackage{pdfoverlay}{2018/05/08}{1.0}
+  {Overlay text on an existing PDF document (DCP)}
+%    \end{macrocode}
+%
+% \noindent The \pkg{everypage} and \pkg{pdfpages} packages are required.
+%
+%    \begin{macrocode}
+\RequirePackage{everypage,pdfpages}
+%    \end{macrocode}
+%
+% \noindent Call \cs{@@_output_pdf_page:} on every page using the
+% \pkg{everypage} package.
+%    \begin{macrocode}
+\AddEverypageHook { \@@_output_pdf_page: }
+%    \end{macrocode}
+%
+% \noindent Add \cs{null} to the end of the document if an action is pending.
+% This is required to ensure that the last requested page from the PDF file is
+% output even if there isn't any other content on the page.
+%    \begin{macrocode}
+\AtEndDocument {
+  \bool_if:NT \g_@@_action_pending_bool
+    {
+      \null
+    }
+}
+%    \end{macrocode}
+%
+% \subsection{Messages}
+%
+% Error message when specified PDF file cannot be found. \\
+% |#|1: PDF file name
+%    \begin{macrocode}
+\msg_new:nnnn { pdfoverlay } { file-not-found }
+  { PDF~file~`#1'~not~found. }
+  { Unable~to~find~the~file~`#1'. \\
+    Check~that~the~file~exists~and~you~have~spelt~it~correctly. }
+%    \end{macrocode}
+%
+% \noindent Error message when no PDF file has been set.
+%    \begin{macrocode}
+\msg_new:nnnn { pdfoverlay } { file-not-set }
+  { PDF~file~not~set. }
+  { You~have~not~specified~a~PDF~file. \\
+    Set~a~PDF~file~using~\pdfoverlaySetPDF. }
+%    \end{macrocode}
+%
+% \noindent Error message when the requested page number cannot be found in the
+% PDF file. \\
+% |#1|: PDF file name \\
+% |#2|: Requested page number \\
+% |#3|: Total number of pages in PDF
+%    \begin{macrocode}
+\msg_new:nnnn { pdfoverlay } { page-not-found }
+  { Page~not~found~in~PDF. }
+  { PDF~file~`#1'~does~not~contain~page~#2. \\
+    Specify~a~page~between~1~and~#3. }
+%    \end{macrocode}
+%
+% \noindent Error message when the requested page number to include to is less
+% than the current page number being output from the PDF file. \\
+% |#1|: Requested page number \\
+% |#2|: Current page number in PDF \\
+% |#3|: Total number of pages in PDF
+%    \begin{macrocode}
+\msg_new:nnnn { pdfoverlay } { page-too-low }
+  { Requested~page~less~than~current~page~in~PDF. }
+  { You~have~requested~to~include~to~page~#1, \\
+    but~the~current~page~is~already~at~page~#2. \\
+    Specify~a~page~between~#2~and~#3. }
+%    \end{macrocode}
+%
+% \subsection{Private Variables and Helper Functions}
+%
+% \begin{macro}{\g_@@_pdf_file_name_str}
+%   Store the PDF file name.
+%    \begin{macrocode}
+\str_new:N \g_@@_pdf_file_name_str
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_page_count_int}
+%   Store the total number of pages in the PDF file.
+%    \begin{macrocode}
+\int_new:N \g_@@_page_count_int
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_page_int}
+%   Keep track of the current page in the PDF file.
+%    \begin{macrocode}
+\int_new:N \g_@@_page_int
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_output_active_bool}
+%   Flag to store whether to output pages from the PDF file or not.
+%    \begin{macrocode}
+\bool_new:N \g_@@_output_active_bool
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_action_pending_bool}
+%   Flag to store whether an action (\cs{pdfoverlay_include_to_page:n} or
+%   \cs{pdfoverlay_set_page:n}) is pending. If an action is pending, these
+%   functions will start a new page.
+%    \begin{macrocode}
+\bool_new:N \g_@@_action_pending_bool
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\g_@@_graphics_options_clist}
+%   Hold the options passed to \cs{includegraphics} when including a page from
+%   the PDF. The default options scale the PDF page to fit the document page
+%   while keeping the original PDF page aspect ratio.
+%    \begin{macrocode}
+\clist_new:N \g_@@_graphics_options_clist
+\clist_set:Nn \g_@@_graphics_options_clist
+  {
+    keepaspectratio ,
+    width  = \paperwidth ,
+    height = \paperheight ,
+    page = \int_use:N \g_@@_page_int
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_output_pdf_page:}
+%   Main function to output the current page of the PDF file. This is called
+%   before every page is shipped using the \pkg{everypage} package.
+%    \begin{macrocode}
+\cs_new:Nn \@@_output_pdf_page:
+  {
+%    \end{macrocode}
+%   Check if we are currently outputting pages, a PDF file has been set, and
+%   the requested page exists in the PDF file.
+%    \begin{macrocode}
+    \bool_lazy_all:nT
+      {
+        { \bool_if_p:N \g_@@_output_active_bool }
+        { \bool_not_p:n
+            { \str_if_empty_p:N \g_@@_pdf_file_name_str } }
+        { \int_compare_p:n
+            { \c_zero <= \g_@@_page_int
+              < \g_@@_page_count_int } }
+      }
+      {
+%    \end{macrocode}
+%   Place requested page from the PDF file in the background of the
+%   document page with the specified format.
+%    \begin{macrocode}
+        \AddToShipoutPictureBG*
+          {
+            \@@_format_pdf_page:
+          }
+%    \end{macrocode}
+%   Increment the current page counter.
+%    \begin{macrocode}
+        \int_gincr:N \g_@@_page_int
+%    \end{macrocode}
+%   Set action pending flag to false.
+%    \begin{macrocode}
+        \bool_gset_false:N \g_@@_action_pending_bool
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\@@_format_pdf_page:}
+%   Format the PDF page in the centre of the document page with options from
+%   \cs{g_@@_graphics_options_clist}. Although marked as private, this function
+%   could be redifined to position the PDF page at a different location on the
+%   document page. See the \pkg{eso-pic} package documentation for hints on how
+%   to position the PDF page.
+%    \begin{macrocode}
+\cs_new:Nn \@@_format_pdf_page:
+  {
+    \AtPageCenter
+      {
+        \makebox (0, 0)
+          {
+            \use:x
+              {
+                \exp_not:N \includegraphics
+                  [ \clist_use:Nn \g_@@_graphics_options_clist { , } ]
+                  { \g_@@_pdf_file_name_str }
+              }
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}[pTF]{\@@_check_page:n}
+%   Check if a PDF file has been set and the requested page is valid. If not,
+%   generate suitable error messages.
+%    \begin{macrocode}
+\prg_new_conditional:Npnn \@@_if_page_exists:n #1 { p, T, F, TF }
+  {
+    \str_if_empty:NTF \g_@@_pdf_file_name_str
+      {
+        \msg_error:nn { pdfoverlay } { file-not-set }
+        \prg_return_false:
+      }
+      {
+        \int_compare:nTF
+          {
+            \c_one <= #1 <= \g_@@_page_count_int
+          }
+          {
+            \prg_return_true:
+          }
+          {
+            \msg_error:nnxxx { pdfoverlay } { page-not-found }
+              { \str_use:N \g_@@_pdf_file_name_str }
+              { \int_eval:n { #1 } }
+              { \int_use:N \g_@@_page_count_int }
+            \prg_return_false:
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%
+% \subsection{Public Expl3 Functions}
+%
+% \begin{macro}{\pdfoverlay_set_pdf:n}
+%   Specify a PDF file to overlay text on to.
+%    \begin{macrocode}
+\cs_new:Npn \pdfoverlay_set_pdf:n #1
+  {
+%    \end{macrocode}
+%   Test if the file exists and generate a suitable error if it doesn't.
+%    \begin{macrocode}
+    \file_if_exist:nTF { #1 }
+      {
+        \str_gset:Nn \g_@@_pdf_file_name_str { #1 }
+%    \end{macrocode}
+%   Use the \pkg{pdfpages} package to find the number of pages in the PDF file.
+%    \begin{macrocode}
+        \edef \AM@currentdocname { #1 }
+        \AM@getpagecount
+%    \end{macrocode}
+%   Initialise variables.
+%    \begin{macrocode}
+        \int_gset_eq:NN \g_@@_page_count_int \AM@pagecount
+        \int_gset_eq:NN \g_@@_page_int \c_zero
+        \bool_gset_true:N \g_@@_output_active_bool
+        \bool_gset_false:N \g_@@_action_pending_bool
+      }
+      {
+        \msg_error:nnn { pdfoverlay } { file-not-found } { #1 }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlay_set_graphics_options:n}
+% Set the options as a comma separated list to be passed to
+% \cs{includegraphics} when outputting each page from the PDF file. The
+% \texttt{page} option is appended automatically in the
+% correct format.
+%    \begin{macrocode}
+\cs_new:Nn \pdfoverlay_set_graphics_options:n
+  {
+    \clist_gset:Nn \g_@@_graphics_options_clist { #1 }
+    \clist_gput_right:Nn \g_@@_graphics_options_clist
+      {
+        page = \int_use:N \g_@@_page_int
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlay_include_to_page:n}
+%   Output all pages in the PDF file up until the specified page. Since the
+%   actual PDF page is inserted by \cs{__pdfoverlay_output_pdf_page:} using the
+%   \pkg{everypage} package before the page is shipped, we just insert the
+%   required number of blank pages into the document.
+%    \begin{macrocode}
+\cs_new:Npn \pdfoverlay_include_to_page:n #1
+  {
+%    \end{macrocode}
+%   Check if a PDF file is set and the requested page exists.
+%    \begin{macrocode}
+    \@@_if_page_exists:nT { #1 }
+      {
+%    \end{macrocode}
+%   Check if the requested page is greater than the current page.
+%    \begin{macrocode}
+        \int_compare:nTF
+          {
+              #1 >= \g_@@_page_int + 1
+          }
+          {
+%    \end{macrocode}
+%   Check if an action is pending and start a new page if so.
+%    \begin{macrocode}
+            \bool_lazy_all:nT
+              {
+                { \bool_if_p:n { \g_@@_action_pending_bool } }
+                { \int_compare_p:n { \g_@@_page_int <
+                                     \g_@@_page_count_int - 1 } }
+                { \int_compare_p:n { #1 != \g_@@_page_int + 1 } }
+              }
+              {
+                \null
+                \clearpage
+              }
+%    \end{macrocode}
+% Loop until the specified page, inserting blank pages.
+%    \begin{macrocode}
+              \int_while_do:nNnn { \g_@@_page_int } < { #1 - 1 }
+                {
+                  \null
+                  \clearpage
+                }
+%    \end{macrocode}
+% Set the action pending flag, so final page is output even if no text is
+% overlayed on it.
+%    \begin{macrocode}
+              \bool_gset_true:N \g_@@_action_pending_bool
+          }
+          {
+            \msg_error:nnxxx { pdfoverlay } { page-too-low }
+              { \int_eval:n { #1 } }
+              { \int_eval:n { \g_@@_page_int + 1 } }
+              { \int_use:N \g_@@_page_count_int }
+          }
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlay_include_to_last_page:}
+%   Output all remaining pages in the PDF file.
+%    \begin{macrocode}
+\cs_new:Nn \pdfoverlay_include_to_last_page:
+  {
+      \pdfoverlay_include_to_page:n { \g_@@_page_count_int }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlay_skip_to_page:n}
+%   Skip to the specified page number in the PDF file.
+%    \begin{macrocode}
+\cs_new:Npn \pdfoverlay_skip_to_page:n #1
+  { 
+    \@@_if_page_exists:nT { #1 }
+      {
+%    \end{macrocode}
+%   Check if an action is pending and start a new page if so.
+%    \begin{macrocode}
+        \bool_if:nT { \g_@@_action_pending_bool }
+          {
+            \null
+            \clearpage
+          }
+%    \end{macrocode}
+% Set the page numer for the next page to be output.
+%    \begin{macrocode}
+        \int_gset:Nn \g_@@_page_int { #1 - 1 }
+%    \end{macrocode}
+% Set the action pending flag, so final page is output even if no text is
+% overlayed on it.
+%    \begin{macrocode}
+        \bool_gset_true:N \g_@@_action_pending_bool
+      }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlay_pause_output:}
+%   Pause outputting pages from the PDF file.
+%    \begin{macrocode}
+\cs_new:Nn \pdfoverlay_pause_output:
+  {
+    \bool_gset_false:N \g_@@_output_active_bool
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlay_resume_output:}
+%   Resume outputting pages from the PDF file.
+%    \begin{macrocode}
+\cs_new:Nn \pdfoverlay_resume_output:
+  {
+    \bool_gset_true:N \g_@@_output_active_bool
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \subsection{Public \LaTeX{} Interface}
+%
+% \begin{macro}{\pdfoverlaySetPDF}
+%   Specify a PDF file to overlay text on to.
+%    \begin{macrocode}
+\NewDocumentCommand \pdfoverlaySetPDF { m }
+  {
+    \pdfoverlay_set_pdf:n { #1 }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlaySetGraphicsOptions}
+%   Set the options as a comma separated list to be passed to
+%   \cs{includegraphics} when outputting each page from the PDF file. The
+%   \texttt{page} option is appended automatically in the right format.
+%    \begin{macrocode}
+\NewDocumentCommand \pdfoverlaySetGraphicsOptions { m }
+  {
+    \pdfoverlay_set_graphics_options:n { #1 }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlayIncludeToPage}
+%   Output all pages in the PDF file up until the specified page.
+%    \begin{macrocode}
+\NewDocumentCommand \pdfoverlayIncludeToPage { m }
+  {
+    \pdfoverlay_include_to_page:n { #1 }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlayIncludeToLastPage}
+%   Output all remaining pages in the PDF file.
+%    \begin{macrocode}
+\NewDocumentCommand \pdfoverlayIncludeToLastPage { }
+  {
+    \pdfoverlay_include_to_last_page:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlaySkipToPage}
+%   Skip ahead to the specified page number in the PDF file.
+%    \begin{macrocode}
+\NewDocumentCommand \pdfoverlaySkipToPage { m }
+  {
+    \pdfoverlay_skip_to_page:n { #1 }
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlayPauseOutput}
+%   Pause outputting pages from the PDF file.
+%    \begin{macrocode}
+\NewDocumentCommand \pdfoverlayPauseOutput { }
+  {
+    \pdfoverlay_pause_output:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\pdfoverlayResumeOutput}
+%   Resume outputting pages from the PDF file.
+%    \begin{macrocode}
+\NewDocumentCommand \pdfoverlayResumeOutput { }
+  {
+    \pdfoverlay_resume_output:
+  }
+%    \end{macrocode}
+% \end{macro}
+%
+%    \begin{macrocode}
+%</package>
+%    \end{macrocode}
+%
+% \end{implementation}
+%
+% \PrintChanges
+%
+% \PrintIndex
-- 
cgit v1.2.3

