% File: thumbpdf.sty % Project: thumbpdf % Version: 2018/09/07 v3.17 % Author: Heiko Oberdiek % % Function: Inclusion of thumbnails % % Copyright: Copyright (C) 1999-2018 Heiko Oberdiek. % % This work may be distributed and/or modified under % the conditions of the LaTeX Project Public License, % either version 1.3 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.3 or later is part of all distributions % of LaTeX version 2003/12/01 or later. % % This work has the LPPL maintenance status "maintained". % % This Current Maintainer of this work is Heiko Oberdiek. % % See file `readme.txt' for a list of files that % belong to this project. % % Requirement: * pdftex mode: % * pdfTeX (plain or latex formats) % * thumbnail data file: `.tpt' % * pdfmark mode: % * Ghostscript 6.0, versions below do not work. % Eventually Adobe Distiller can work, but I % cannot test this. % * thumbnail data file: `.tpm' % * Both thumbnail data files are generated by the % perl script `thumbpdf(.pl)'. % % Use: * LaTeX2e: \usepackage{thumbpdf} % Options: pdftex, % pdfmark, dvips, ps2pdf % vtex, vtexpdfmark % * plain: \input thumbpdf.sty % A driver can be defined previously: % \def\ThumbpdfDriver{pdfmark} % * It is not necessary to set driver `pdftex', `vtex', % or `vtexpdfmark', because pdfTeX and VTeX are % detected at run time. So package `thumbpdf' % chooses the correct driver and ignores other % specified drivers. % % History: 1999/02/14 v1.0: first public release % 1999/02/23 v1.1: bug in plain-\@thumbwarning removed. % 1999/03/01 v1.2: \DefLastObj no longer needed. % 1999/03/12 v1.3: Copyright: LPPL % 1999/05/05 v1.4: added \the before \inputlineno. % sharing RGB objects. % 1999/06/13 v1.5 % 1999/07/27 v1.6: Bug of handling with \pdfpageattr % fixed. The same bug is in hyperref % versions below 6.64 (option % pagetransition). % Warning added, if there are missing % thumbnails. % 1999/08/08 v1.7: Bug in \@ThumbPageAttr fixed % (introduced in version 1.6). % 1999/09/09 v1.8: \PackageWarning does not work at % the beginning of \shipout, because % \protect has been set to \noexpand % (mysterious LaTeX behaviour?). % 1999/09/16 v1.9 % 2000/01/11 v1.10: Revised. % 2000/01/19 v1.11 % 2000/02/11 v1.12: \jobname.tnd supported, % \DeclareThumbs added. % 2000/02/22 v2.0: pdfmark support, extra thumbnails are % scanned in file `.tno'. % 2000/02/28 v2.1: support of `thumbpdf.cfg'. % 2000/03/07 v2.2 % 2000/03/22 v2.3 % 2000/04/10 v2.4 % 2000/07/29 v2.5 % 2000/09/27 v2.6 % 2000/10/27 v2.7 % 2001/01/12 v2.8 % 2001/03/29 v2.9 % 2001/04/02 v2.10 % 2001/04/26 v2.11 % 2002/01/11 v3.0: Support for VTeX's PostScript mode added. % 2002/05/26 v3.1 % 2002/05/26 v3.2 % 2003/03/19 v3.3 % 2003/06/06 v3.4 % 2004/10/24 v3.5: LPPL 1.3. % 2004/11/19 v3.6 % 2004/11/19 v3.7 % 2005/07/06 v3.8 % 2007/11/07 v3.9 % 2008/04/16 v3.10 % 2010/07/07 v3.11: Warning if \pdfobjcompresslevel>0. % 2011/08/09 v3.12: Support for LuaTeX added. % 2011/08/10 v3.13: Version date fixed. % 2012/04/09 v3.14: Fix for plain TeX compatibility % (offending \RequirePackage). % 2012/04/18 v3.15 % 2014/07/15 v3.16 % 2018/09/07 v3.17 Abort not just warn on terminal if pdfcompression is enabled. % (David Carlisle as suggested by Karl Berry) % https://github.com/ho-tex/thumbpdf % % \THB@ is the prefix for internal command names. % % Prevent that the package is loaded twice (for plain formats). \expandafter\ifx\csname THB@name\endcsname\relax \expandafter\gdef\csname THB@name\endcsname{thumbpdf} \else \expandafter\endinput \fi % Package identification in the log file \begingroup \def\x[#1]{\endgroup\immediate\write-1{Package: thumbpdf #1}}% \ifx\ProvidesPackage\UnDeFiNeD \else \ifx\ProvidesPackage\relax \else \def\x{\endgroup\ProvidesPackage{thumbpdf}}% \fi \fi \x[2018/09/07 v3.17 Inclusion of thumbnails (HO)]% % Dummy for \thisthumb and \DeclareThumbs. It is overwritten, % if the checks succeed and the whole package is loaded. \def\thisthumb#1{} \def\DeclareThumbs#1{} % Check part, keep help macros local: \begingroup % For use of `@' in command names. \catcode`\@=11 % Now we define utils of the LaTeX kernel, if they aren't. \expandafter\ifx\csname @firstoftwo\endcsname\relax \long\def\@firstoftwo#1#2{#1}% \long\def\@secondoftwo#1#2{#2}% \fi \expandafter\ifx\csname @ifundefined\endcsname\relax \def\@ifundefined#1{% \expandafter\ifx\csname#1\endcsname\relax \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi }% \fi % If a check fails, a warning is produced and the package exits. \@ifundefined{PackageWarningNoLine}{% \def\PackageWarningNoLine#1#2{% \immediate\write16{}% \immediate\write16{Package #1 Warning: #2.}% \immediate\write16{}% }% }{} \long\def\@ReturnAfterFi#1\fi{\fi#1} \long\def\@ReturnAfterElseFi#1\else#2\fi{\fi#1} \def\THB@WarnEnd#1{% \PackageWarningNoLine{thumbpdf}{#1}% \endgroup \endinput } % \csname-Trick because of \outer definition of \newread. % \globaldefs=-1 in order to make the allocation of \newread local. \@ifundefined{IfFileExists}{% \edef\x{\the\globaldefs}% \globaldefs-1\relax \csname newread\endcsname\THB@TempRead \globaldefs\x\relax \def\IfFileExists#1{% \openin\THB@TempRead=#1\relax \ifeof\THB@TempRead \closein\THB@TempRead \expandafter\@secondoftwo \else \closein\THB@TempRead \expandafter\@firstoftwo \fi }% }{} % Load .cfg file if it exists \IfFileExists{thumbpdf.cfg}{% \@ifundefined{@@input}{% \input thumbpdf.cfg\relax }{% \input{thumbpdf.cfg}% }% }{} % LaTeX2e options \def\THB@pdftex{pdftex} \def\THB@pdfmark{pdfmark} \def\THB@vtex{vtex} \@ifundefined{ThumbpdfDriver}{\let\ThumbpdfDriver\empty}{} \@ifundefined{DeclareOption}{}{% \DeclareOption{pdftex}{\let\ThumbpdfDriver\THB@pdftex}% \DeclareOption{pdfmark}{\let\ThumbpdfDriver\THB@pdfmark}% \DeclareOption{dvips}{\let\ThumbpdfDriver\THB@pdfmark}% \DeclareOption{ps2pdf}{\let\ThumbpdfDriver\THB@pdfmark}% \DeclareOption{vtex}{\let\ThumbpdfDriver\THB@vtex}% \DeclareOption{vtexpdfmark}{\let\ThumbpdfDriver\THB@vtex}% \ProcessOptions\relax } \edef\x{\ThumbpdfDriver} \expandafter\lowercase\expandafter{% \expandafter\gdef\expandafter\ThumbpdfDriver\expandafter{\x}% } \def\x{dvips}\ifx\ThumbpdfDriver\x \global\let\ThumbpdfDriver\THB@pdfmark \fi \def\x{ps2pdf}\ifx\ThumbpdfDriver\x \global\let\ThumbpdfDriver\THB@pdfmark \fi \def\x{vtexpdfmark}\ifx\ThumbpdfDriver\x \global\let\ThumbpdfDriver\THB@vtex \fi % Check: Called by pdfTeX or VTeX? Driver correct? \ifcase\@ifundefined{pdfoutput}0\pdfoutput\relax \@ReturnAfterElseFi{% \ifcase0\@ifundefined{OpMode}1{\ifnum\OpMode=2 \else 1\fi} % \global\let\ThumbpdfDriver\THB@vtex \else \@ReturnAfterFi{% \ifx\ThumbpdfDriver\THB@pdfmark \else \@ReturnAfterFi{% \ifx\ThumbpdfDriver\empty \@ReturnAfterElseFi{% \THB@WarnEnd{% Missing driver name% }% }% \else \@ReturnAfterFi{% \ifx\ThumbpdfDriver\THB@pdftex \@ReturnAfterElseFi{% \THB@WarnEnd{% You need pdfTeX in PDF mode for driver `pdftex'% }% }% \else \@ReturnAfterFi{% \ifx\ThumbpdfDriver\THB@vtex \@ReturnAfterElseFi{% \THB@WarnEnd{% You need VTeX in PS mode for driver `vtex'% }% }% \else \@ReturnAfterFi{% \THB@WarnEnd{% Driver `\ThumbpdfDriver' not supported% }% }% \fi }% \fi }% \fi }% \fi }% \fi }% \else \global\let\ThumbpdfDriver\THB@pdftex \fi % Check \pdfobjcompresslevel \expandafter\ifx\csname pdfobjcompresslevel\endcsname\relax \else \ifnum\pdfobjcompresslevel>0 % \wlog{THUMBPDF: Compressed PDF objects of PDF 1.5 are not supported}% \endgroup\expandafter\expandafter\expandafter\endinput \fi \fi % Check: Does data file exists? \edef\THB@datafile{% \jobname.tp\ifx\ThumbpdfDriver\THB@pdftex t\else m\fi }% \IfFileExists{\THB@datafile}{}{% \THB@WarnEnd{Thumbnail data file `\THB@datafile' not found}% }% % Some macros need \PackageWarning \expandafter\ifx\csname PackageWarning\endcsname\relax \gdef\PackageWarning#1#2{% \immediate\write16{}% \immediate\write16{% Package `#1' warning: #2 on input line \the\inputlineno.% }% \immediate\write16{}% }% \fi % definition of \DeclareThumbs \gdef\DeclareThumbs#1{% \begingroup % check LaTeX's \if@filesw \expandafter\ifx\csname if@filesw\expandafter\endcsname \csname iffalse\endcsname \else \csname newwrite\endcsname\THB@thumbopt \immediate\openout\THB@thumbopt=\jobname.tno % Definition of \thumb that also works with plain format. \def\thumb##1##{\THB@thumb{##1}}% \def\THB@thumb##1##2{% \immediate\write\THB@thumbopt{% \string\thumb##1{##2}% }% }% \let\protect\string % process data #1% % end of file \immediate\write\THB@thumbopt{\string\endinput}% \fi \endgroup \global\let\DeclareThumbs\THB@DeclareThumbs } \def\THB@DeclareThumbs#1{% \PackageWarning{\THB@name}{Too many \string\DeclareThumbs}% } % pdfmark part \ifx\ThumbpdfDriver\THB@pdfmark % the header file includes already the regular thumbnails. \special{header=\THB@datafile}% \begingroup \def\DefThisThumb#1{% \global\expandafter\let\csname thumb#1\endcsname\empty }% % ignore PostScript comment char \catcode`\%=9 \@ifundefined{@@input}{\input\THB@datafile\relax} {\input{\THB@datafile}} \endgroup % definition of \thisthumb \gdef\thisthumb#1{% \expandafter\ifx\csname thumb#1\endcsname\relax \PackageWarning{\THB@name}{Thumbnail `#1' undefined}% \else \special{ps:{THB\string_#1} thisTHB}% \fi }% % end of pdfmark part \endgroup\expandafter\endinput \fi % vtex part \ifx\ThumbpdfDriver\THB@vtex % the header file includes already the regular thumbnails. \ifnum\@ifundefined{VTeXversion}0\VTeXversion<753 % \ifcase\@ifundefined{gexmode}1\gexmode % without GeX \immediate\special{header=\THB@datafile}% \else % with GeX \begingroup \edef\x{\the\globaldefs}% \globaldefs-1\relax \csname newread\endcsname\THB@TempRead \globaldefs\x\relax \openin\THB@TempRead=\THB@datafile\relax \def\x{% \catcode`\%=12 % \catcode`\|=0 % \catcode`\{=12 % \catcode`\}=12 % \catcode`\ =12 % \catcode`\\=12 % \catcode`\_=12 % \let\par\empty \loop \ifcase\ifeof\THB@TempRead 1 \else 0 \fi \read\THB@TempRead to \THB@line \immediate\special{!=\THB@line}% \repeat \closein\THB@TempRead \endgroup }% \x \fi \else \immediate\special{headercopy=\THB@datafile}% \fi \begingroup \def\DefThisThumb#1{% \global\expandafter\let\csname thumb#1\endcsname\empty }% % ignore PostScript comment char \catcode`\%=9 \@ifundefined{@@input}{\input\THB@datafile\relax} {\input{\THB@datafile}} \endgroup % definition of \thisthumb \gdef\thisthumb#1{% \expandafter\ifx\csname thumb#1\endcsname\relax \PackageWarning{\THB@name}{Thumbnail `#1' undefined}% \else \special{!={THB\string_#1} thisTHB}% \fi }% % end of vtex part \endgroup\expandafter\endinput \fi % pdftex part \global\let\THB@datafile\THB@datafile \endgroup \expandafter\chardef\csname THB@AtCode\endcsname=\the\catcode`\@ \catcode`\@=11 % The thumbnails are numbered with the output pages: % `thb1.png' means the thumbnail of the first output page, % `thb28.png' the thumbnail of the 28th written page, % regardless of the page number. % Therefore we need a new counter that is incremented with each % page that is written to the pdf file. \newcount\c@thumb \c@thumb 0\relax \newif\ifTHB@thisthumb \def\thisthumb#1{% \global\THB@thisthumbtrue \THB@AddPageAttr{#1}% } % Now we enhance \shipout in order to % * increment the output page counter (\c@thumb), % * check if a thumbnail exists, % * add/remove the thumbnail entry to the pdf page attributes. \let\THBorg@shipout\shipout \def\shipout{\THB@AddThumb\THBorg@shipout} \def\THB@AddThumb{% \begingroup \global\advance\c@thumb by 1\relax \ifTHB@thisthumb \global\THB@thisthumbfalse % reset switch \else \THB@AddPageAttr{\the\c@thumb}% \fi \endgroup } \def\THB@AddPageAttr#1{% % Remove previous /Thumb entry. \expandafter\THB@RemoveThumbAttr\the\pdfpageattr^^J/Thumb{} 0 R\END % Check, if thumb exists. \expandafter\ifx\csname thumb#1\endcsname\relax % \PackageWarning cannot be used, because \protect=\noexpand. \immediate\write16{}% \immediate\write16{Package \THB@name\space Warning: % Thumbnail `#1' undefined % on input line \the\inputlineno.% }% \immediate\write16{}% \else \begingroup \edef\x{\endgroup \global\pdfpageattr{% \the\pdfpageattr ^^J/Thumb \csname thumb#1\endcsname\space 0 R% }% }% \x \fi } \def\THB@RemoveThumbAttr#1^^J/Thumb#2#3 0 R#4\END{% \ifx\\#2\\% \global\pdfpageattr{#1}% \else \THB@RemoveThumbAttr#1#4\END \fi } \begingroup\expandafter\expandafter\expandafter\endgroup \expandafter\ifx\csname RequirePackage\endcsname\relax \input ifluatex.sty\relax \else \RequirePackage{ifluatex}[2010/03/01]% \fi \ifluatex \def\THB@InitLua{% \catcode39=12 % ' \catcode40=12 % ( \catcode41=12 % ) \catcode43=12 % + \catcode45=12 % - \catcode46=12 % . \catcode60=12 % < \catcode95=12 % _ \escapechar=-1 % \edef\\{\string\\}% \edef\%{\string\%}% \escapechar=92 % \newlinechar=13 % \catcode13=12 % \endlinechar=13 % }% \ifnum\luatexversion<36 % \def\THB@directlua#{\directlua0}% \else \let\THB@directlua\directlua \fi \begingroup \THB@InitLua % \THB@directlua{% thumbpdf = {} thumbpdf.callback = callback.find('process_input_buffer') % if thumbpdf.callback then % texio.write_nl('log', 'Package thumbpdf Info: Callback saved.') % texio.write_nl('log', '') % end function thumbpdf.process_input_buffer(buffer) return string.gsub(buffer, '[\\100-\\255]', function (s) local num = string.byte(s) if num < 128 then return s else return unicode.utf8.char(num + 1114112) end end ) end thumbpdf.id, thumbpdf.error = callback.register('process_input_buffer', thumbpdf.process_input_buffer) if thumbpdf.id == nil then tex.print(string.format( '\\\\endgroup\\\\begingroup% \\\\PackageError{thumbpdf}% {\%s:\\\\MessageBreak \%s}\\\\@ehc', 'Setting process_input_buffer failed', string.gsub(thumbpdf.error, '\\.$', ''))) % else % texio.write_nl('log', % 'Package thumbpdf Info: Setting process_input_buffer.') % texio.write_nl('log', '') end }% \endgroup% \fi % Many commands and catcode changes are only necessary to read % the data file, so we do this in a group. \begingroup % These commands are used in `.tpt' \def\DefThumb#1{% \expandafter\xdef\csname thumb#1\endcsname{\the\pdflastobj}% }% \def\DefRGB#1{% \expandafter\edef\csname thumbRGB#1\endcsname{\the\pdflastobj}% }% \def\UseRGB#1{\csname thumbRGB#1\endcsname}% % Now the catcodes to read `.tpt' follows: \def\SetCatcodeRange#1#2{% \c@thumb=#1 \loop \catcode\c@thumb=12 \ifnum\c@thumb<#2 \advance\c@thumb by 1 \repeat } \SetCatcodeRange{0}{12}% % ^^M \SetCatcodeRange{14}{31}% % space \SetCatcodeRange{33}{36}% ! " # $ % percent \SetCatcodeRange{38}{63}% & ' ( ) * + , - . / 0-9 : ; < = > ? % @ A-Z \catcode`\[=12 % backslash \catcode`\]=12 % ^ \SetCatcodeRange{95}{96}% _ ' % a-z { \catcode`\|=12 % } \SetCatcodeRange{126}{255}% ~ 127 8-bit % commands for special characters used in `.tpt'. \edef\~{\space}% in stream data to avoid `\ ' at line end. \let\ \~% \edef\+{\string^}% \begingroup \lccode`1=`\\ \lccode`2=`\^^M \lccode`3=`\{ \lccode`4=`\} \lccode`5=`\% \lowercase{\endgroup \def\\{1}% \def\/{2}% \def\{{3}% \def\}{4}% \def\%{5}% } % no white space by line ends \endlinechar=-1 % process data file and include the thumbnails % in the current pdf file \expandafter\ifx\csname @@input\endcsname\relax \input\THB@datafile\relax \else \input{\THB@datafile}% \fi \endgroup \ifluatex \begingroup \THB@InitLua % \THB@directlua{% thumbpdf.id, thumbpdf.error = callback.register('process_input_buffer', thumbpdf.callback) if thumbpdf.id == nil then tex.print(string.format( '\\\\endgroup\\\\begingroup% \\\\PackageError{thumbpdf}% {\%s:\\\\MessageBreak \%s}\\\\@ehc', 'Restoring process_input_buffer failed', string.gsub(thumbpdf.error, '\\.$', ''))) % else % texio.write_nl('log', 'Package thumbpdf Info: Callback restored.') % texio.write_nl('log', '') end }% \endgroup \fi % restore catcode of `@'. \catcode`\@=\THB@AtCode\relax \endinput