summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/media9/pdfbase.sty
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/media9/pdfbase.sty
Initial commit
Diffstat (limited to 'macros/latex/contrib/media9/pdfbase.sty')
-rw-r--r--macros/latex/contrib/media9/pdfbase.sty1412
1 files changed, 1412 insertions, 0 deletions
diff --git a/macros/latex/contrib/media9/pdfbase.sty b/macros/latex/contrib/media9/pdfbase.sty
new file mode 100644
index 0000000000..37cbd103ff
--- /dev/null
+++ b/macros/latex/contrib/media9/pdfbase.sty
@@ -0,0 +1,1412 @@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% pdfbase.sty
+%
+% driver independent access to low-level pdf features
+%
+% Copyright 2015--\today, Alexander Grahn
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%
+% This package implements commands for the creation of PDF Objects,
+% Form XObjects, Image XObjects, annotations, links, marked content (BDC/EMC)
+% and for manipulating the PDF catalog.
+%
+% Supported workflows:
+%
+% pdflatex, lualatex
+% latex-->dvips-->ps2pdf or Distiller
+% latex-->dvipdfmx
+% xelatex
+%
+% Package options:
+%
+% xetex
+% dvipdfmx
+% dvisvgm (basic support: \pbs_literal:nn, \pbs_pdfannot:nnnn,
+% \pbs_pdfxform:nnnnn\pbs_pdfrefxform:n)
+% bigfiles (for embedding large files as stream objects; only relevant for
+% dvips mode, ignored otherwise)
+%
+% Commands defined:
+%
+% \pbs_pdfobj:nnn
+% #1: predefined PDF object ID to be used for the current obj; may be empty
+% #2: type of object ( generic | dict | array | stream | fstream )
+% #3: if #2==
+% `generic', then single basic object, such as 3.141, (foo), true, /Name
+% `dict', then PDF key-value dictionary
+% `stream', then
+% {stream attributes as PDF key-value dictionary}{content string}
+% `fstream', then
+% {stream attributes as PDF key-value dictionary}{file name}
+%
+% if #3 && #1 are both empty, an object reference will be reserved for later
+% use as #1
+%
+% \pbs_pdflastobj:
+% inserts object ID of PDF object created/processed during most recent call
+% of \pbs_pdfobj:nnn
+%
+% --------
+%
+% \pbs_pdfannot:nnnn
+% #1: width, #2: height, #3: depth, #4: dictionary (key-value)
+%
+% \pbs_pdflastann:
+% inserts object ID of PDF object created during most recent call of
+% \pbs_pdfannot:nnnn
+%
+% --------
+%
+% \pbs_appendtofields:n
+% #1 object ID of PDF annotation; annotations of /Subtype/Widget
+% should be appended to the /Fields array of the global /AcroForm dictionary
+%
+% --------
+%
+% \pbs_pdflink:nn
+% #1: dictionary (key-value), #2: text
+%
+% --------
+%
+% \pbs_pdfdest:nnnn
+% #1: name, #2: fit | fitb | fitbh | fith | fitbv | fitv | xyz | fitr
+% #3: zoom, #4: text
+%
+% --------
+%
+% \pbs_pdfxform:nnnnn
+% #1: add pgf/tikz resources (transparency, shading)? (1|0) %dvipdfmx/xetex
+% #2: used as PDF annotation appearance? (1|0) %dvips/pdftex
+% #3: additional resources %all BUT dvips
+% #4: additional dictionary entries
+% #5: savebox number
+% creates PDF Form XObject from savebox content
+%
+% \pbs_pdflastxform:
+% inserts object ID of PDF Form XObject created during most recent call of
+% \pbs_pdfxform:nnnnn
+%
+% \pbs_pdfrefxform:n
+% #1: xform object ID
+% inserts the PDF Form XObject into the current content stream, that is,
+% typsets the PDF Form XObject
+%
+% --------
+%
+% \pbs_pdfximage:n
+% #1: bitmap image file name
+% creates PDF Image XObject from /bitmap/ file for use as bitmap resource
+% in 3D context
+%
+% \pbs_pdflastximage:
+% inserts object ID of PDF Image XObject created during most recent call of
+% \pbs_pdfximage:n
+%
+% --------
+%
+% \pbs_literal:nn
+% #1: keyword (empty) | direct | page
+% #2: raw PDF/Postscript code
+% implements \pdfliteral{...}, \pdfliteral direct {...},
+% \pdfliteral page {...} from pdfTeX, and
+% \special{" ...} and \special{ps: ...} from dvips
+%
+% --------
+%
+% \pbs_pdfcatalog:n
+% #1: dictionary (key-value)
+%
+% --------
+%
+% marked content BDC/EMC operators
+% \pbs_pdfbdc:nn ...
+% ... \pbs_pdfemc:
+% #1: tag, #2: properties dictionary obj ID
+%
+% --------
+%
+% alternative \AtEndDvi
+% \pbs_at_end_dvi:n
+% #1: \specials or \write to be inserted on the very last page
+%
+% --------
+%
+% \pbs_add_form_font: (pdfLaTeX, LuaLaTeX)
+% adds current font as a resource to the global /AcroForm dict, allowing
+% the font to be used in PDF Forms (theoretically, see
+% https://acrobat.uservoice.com/forums/590923-acrobat-for-windows-and-mac/
+% suggestions/33077827-bug-in-text-field-forms-embedded-opentype-font )
+%
+% \pbs_last_form_font: (pdfLaTeX, LuaLaTeX)
+% expands to current font's resource name; to be used in the /DA (...)
+% entry of the Form dictionary
+%
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+% This work may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License.
+%
+% The latest version of this license is in
+%
+% http://mirrors.ctan.org/macros/latex/base/lppl.txt
+%
+% This work has the LPPL maintenance status `maintained'.
+%
+% The Current Maintainer of this work is A. Grahn.
+
+%process non-detectable driver options for passing to expl3
+\RequirePackage{xkeyval}
+\DeclareOptionX{dvipdfmx}{%
+ \PassOptionsToPackage{driver=dvipdfmx}{expl3}
+}
+\DeclareOptionX{dvisvgm}{%
+ \PassOptionsToPackage{driver=dvisvgm}{expl3}
+}
+\DeclareOptionX*{}\ProcessOptionsX*\relax %allow anything as an option
+
+\RequirePackage{expl3}
+\RequirePackage{l3keys2e}
+
+\def\g@pbs@date@tl{2019/07/11}
+\def\g@pbs@version@tl{0.33}
+
+\ProvidesExplPackage{pdfbase}{\g@pbs@date@tl}{\g@pbs@version@tl}
+{driver independent access to low-level PDF features}
+
+\msg_set:nnnn{pdfbase}{support~outdated}{
+ Support~package~`#1'~too~old.
+}{
+ Get~an~up~to~date~version~of~`#1'.\\
+ Aborting.
+}
+\@ifpackagelater{expl3}{2019/05/09}{}{
+ \msg_error:nnn{pdfbase}{support~outdated}{expl3.sty}
+ \tex_endinput:D
+}
+
+\int_new:N\g_pbs_page_int %abs. page counter
+
+%creating global definitions
+\cs_new:Npn\pbs@newkey#1#2{\tl_gset:cx{#1}{#2}}
+
+\msg_set:nnn{pdfbase}{rerun}{Rerun~to~get~internal~references~right!}
+
+%LaTeX2e wrapper
+\cs_new_nopar:Npn\pbs@seq@push@cx#1#2{
+ \seq_if_exist:cF{#1}{\seq_new:c{#1}}
+ \seq_gput_right:cx{#1}{#2}
+}
+
+%wrong image file type for Image XObject generation
+\msg_gset:nnn{pdfbase}{wrong~image~resource}{
+ Image~resource~file\\~~'#1'\\has~wrong~type.\\\\
+ Driver~#2~only~accepts~files~of~type\\#3\\
+ as~image~resources.
+}
+
+%pdfTeX version check
+\sys_if_engine_pdftex:T{
+ \int_compare:nT{\pdftexversion<130}{
+ \msg_interrupt:nnn{pdfbase~error}{pdfTeX,~version~>=~1.30~required.}{}
+ }
+}
+
+% page (bop, eop) hooks
+\cs_new_protected:Nn\pbs_bop_action:n{\seq_gput_right:Nn\g_pbs_bop_seq{#1}}
+\cs_new_protected:Nn\pbs_eop_action:n{\seq_gput_right:Nn\g_pbs_eop_seq{#1}}
+\seq_new:N\g_pbs_bop_seq
+\seq_new:N\g_pbs_eop_seq
+
+% own AtEndDvi implementation
+\cs_new_protected:Nn\pbs_at_end_dvi:n{\seq_gput_right:Nn\g_pbs_eod_seq{#1}}
+\seq_new:N\g_pbs_eod_seq
+\pbs@newkey{pbs@last@page}{0}
+
+% AtEndDvi check
+\AtBeginDocument{
+ \iow_now:Nx\@mainaux{
+ \token_to_str:N\providecommand\token_to_str:N\pbs@newkey[2]{}
+ }
+ \iow_now:Nx\@mainaux{
+ \token_to_str:N\providecommand\token_to_str:N\pbs@seq@push@cx[2]{}
+ }
+ \iow_now:Nx\@mainaux{
+ \token_to_str:N\providecommand\token_to_str:N\pbs@at@end@dvi@check{}
+ }
+ \iow_now:Nx\@mainaux{\token_to_str:N\pbs@at@end@dvi@check}
+ \cs_new_protected:Npn\pbs@at@end@dvi@check{
+ \bool_if:nT{
+ !\tl_if_exist:NTF\pbs@last@page{
+ \int_compare_p:n{\pbs@last@page=\g_pbs_page_int}
+ }{
+ \c_false_bool
+ }
+ }{
+ \cs_if_exist:NF\g_pbs_rerunwarned_tl{
+ \tl_new:N\g_pbs_rerunwarned_tl
+ \msg_warning:nn{pdfbase}{rerun}
+ }
+ }
+ }
+}
+
+%%%%%%%%%%%%%%%%%
+%package options
+%%%%%%%%%%%%%%%%%
+%unknown package option error message
+\msg_gset:nnnn{pdfbase}{unknown~package~option}{Unknown~package~option~`#1'.}{
+ Package option~'#1'~is~unknown;\\
+ perhaps~it~is~spelled~incorrectly.
+}
+
+\bool_new:N\g_pbs_pkgbigfiles_bool
+\bool_new:N\g_pbs_dvipdfmx_bool
+\bool_new:N\g_pbs_dvisvgm_bool
+\bool_new:N\g_pbs_lscape_bool %if we are inside landscape env
+\AtBeginDocument{
+ \cs_if_exist:NT\landscape{%
+ \tl_put_right:Nn\landscape{\bool_gset_true:N\g_pbs_lscape_bool}
+ \tl_put_left:Nn\endlandscape{\bool_gset_false:N\g_pbs_lscape_bool}
+ }
+}
+
+\keys_define:nn{pdfbase}{
+ xetex .code:n = {}, %dummy, we use engine test instead
+
+ dvipdfmx .choice:,
+ dvipdfmx / true .code:n = {
+ \bool_gset_true:N\g_pbs_dvipdfmx_bool
+ \bool_gset_false:N\g_pbs_dvisvgm_bool
+ },
+ dvipdfmx / false .code:n = {\bool_gset_false:N\g_pbs_dvipdfmx_bool},
+ dvipdfmx .default:n = {true},
+
+ dvisvgm .choice:,
+ dvisvgm / true .code:n = {
+ \bool_gset_true:N\g_pbs_dvisvgm_bool
+ \bool_gset_false:N\g_pbs_dvipdfmx_bool
+ },
+ dvisvgm / false .code:n = {\bool_gset_false:N\g_pbs_dvisvgm_bool},
+ dvisvgm .default:n = {true},
+
+ bigfiles .bool_gset:N = \g_pbs_pkgbigfiles_bool,
+
+ unknown .code:n = {
+ \msg_error:nnx{pdfbase}{unknown~package~option}{\l_keys_key_tl}
+ }
+}
+\ProcessKeysOptions{pdfbase}
+
+\sys_if_output_pdf:T{
+ \bool_gset_false:N\g_pbs_dvipdfmx_bool
+ \bool_gset_false:N\g_pbs_dvisvgm_bool
+}
+
+\sys_if_engine_xetex:T{
+ \bool_if:NF\g_pbs_dvisvgm_bool{\bool_gset_true:N\g_pbs_dvipdfmx_bool}
+}
+
+\cs_new_nopar:Nn\pbs_insert_properties_entry:{}
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%commands for creating PDF objects, annots etc.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\sys_if_output_pdf:TF{
+ %in LuaTeX-0.95.0, pdfTeX primitives got new names
+ \bool_lazy_and:nnT{
+ \sys_if_engine_luatex_p:
+ }{
+ !\int_compare_p:n{\luatexversion<95}
+ }{
+ \cs_set_protected:Npn\pdfnames{\pdfextension~names~}
+ \cs_set_protected:Npn\pdfobj{\pdfextension~obj~}
+ \cs_set_protected:Npn\pdfrefobj{\pdfextension~refobj~}
+ \cs_set_protected:Npn\pdfannot{\pdfextension~annot~}
+ \cs_set_protected:Npn\pdfstartlink{\pdfextension~startlink~}
+ \cs_set_protected:Npn\pdfendlink{\pdfextension~endlink\relax}
+ \cs_set_protected:Npn\pdfdest{\pdfextension~dest~}
+ \cs_set_protected:Npn\pdfliteral{\pdfextension~literal~}
+ \cs_set_protected:Npn\pdfcatalog{\pdfextension~catalog~}
+ \cs_set:Npn\pdflastlink{\numexpr\pdffeedback~lastlink\relax}
+ \cs_set:Npn\pdflastobj{\numexpr\pdffeedback~lastobj\relax}
+ \cs_set:Npn\pdflastannot{\numexpr\pdffeedback~lastannot\relax}
+ \cs_set:Npn\pdfpageref{\numexpr\pdffeedback~pageref\relax}
+ \cs_set:Npx\pdfpageresources{\pdfvariable~pageresources}
+ \cs_set_eq:NN\pdfximage\saveimageresource
+ \cs_set_eq:NN\pdfrefximage\useimageresource
+ \cs_set_eq:NN\pdflastximage\lastsavedimageresourceindex
+ \cs_set_eq:NN\pdflastximagepages\lastsavedimageresourcepages
+ \cs_set_eq:NN\pdfxform\saveboxresource
+ \cs_set_eq:NN\pdfrefxform\useboxresource
+ \cs_set_eq:NN\pdflastxform\lastsavedboxresourceindex
+ \cs_set:Npn\pdffontobjnum{\pdffeedback~fontobjnum}
+ }
+
+ %helper func to remove `0 R' part from pdf obj reference
+ \cs_new_nopar:Nn\pbs_reftonum:n{\_pbs_reftonum:f{#1}}
+ \cs_new_nopar:Nn\_pbs_reftonum:n{\exp_after:wN\_pbs_reftonum:w#1}
+ \cs_generate_variant:Nn\_pbs_reftonum:n{f}
+ \cs_new_nopar:Npn\_pbs_reftonum:w #1~0~R{#1}
+
+ %literal PDF code into content stream, no saving of graphics state
+ \cs_new_protected_nopar:Nn\pbs_literal:nn{ % #1: empty (`'), `direct' or `page'
+ \str_case:nnF{#1}{ % #2: raw PDF
+ % `direct' inserts raw pdf code without translating origin (0,0) to
+ % current position: origin is lower left page corner
+ {direct}{\pdfliteral~direct~{#2}}
+ % same as above, but closing text object if necessary
+ {page}{\pdfliteral~page~{#2}}
+ }{
+ % closing text object if necessary and setting current
+ % location's coordinates to (0,0)
+ \pdfliteral{#2}
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfobj:nnn{
+ \tl_clear:N\l_pbs_usenum_tl
+ \tl_if_blank:oF{#1}{
+ \tl_set:Nx\l_pbs_usenum_tl{useobjnum~\pbs_reftonum:n{#1}}
+ }
+ \bool_if:nTF{\tl_if_blank_p:o{#1}&&\tl_if_blank_p:o{#3}}{
+ \pdfobj~reserveobjnum
+ }{
+ \str_case:nn{#2}{
+ {generic}{\immediate\pdfobj~\l_pbs_usenum_tl~{#3}}
+ {dict}{\immediate\pdfobj~\l_pbs_usenum_tl~{<<#3>>}}
+ {array}{\immediate\pdfobj~\l_pbs_usenum_tl~{[#3]}}
+ {stream}{\immediate\pdfobj~\l_pbs_usenum_tl~stream~
+ attr{\use_i:nn#3}~{\use_ii:nn#3}
+ }
+ {fstream}{\immediate\pdfobj~\l_pbs_usenum_tl~stream~
+ attr{\use_i:nn#3}~file~{\use_ii:nn#3}
+ }
+ }
+ }
+ \tl_gset:Nx\g_pbs_pdflastobj_tl{\the\pdflastobj\space 0~R}
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfannot:nnnn{
+ \immediate\pdfannot~width~#1~height~#2~depth~#3 {
+ \cs_if_exist_use:N\ocgbase_insert_oc:~#4}
+ \tl_gset:Nx\g_pbs_pdflastann_tl{\the\pdflastannot\space 0~R}
+ }
+
+ \cs_new_protected:Nn\pbs_pdflink:nn{
+ \leavevmode
+ \immediate\pdfstartlink~user~{
+ \cs_if_exist_use:N\ocgbase_insert_oc:~#1}#2\pdfendlink
+ }
+
+ \cs_new_protected:Nn\pbs_pdfdest:nnnn{
+ \leavevmode
+ \str_case:nnTF{#2}{
+ {fit}{}
+ {fitb}{}
+ {fitbv}{}
+ {fitv}{}
+ }{
+ \pdfdest~name~{#1}~#2~#4
+ }{
+ \group_begin:
+ \hbox_set:Nn\l_tmpa_box{#4}
+ \str_case:nnTF{#2}{
+ {fitbh}{\tl_set:Nn\l_pbs_fittype_tl{#2}}
+ {fith}{\tl_set:Nn\l_pbs_fittype_tl{#2}}
+ {xyz}{\tl_set:Nn\l_pbs_fittype_tl{#2~zoom~\int_eval:n{#3*1000}}}
+ }{
+ \box_move_up:nn{\box_ht:N\l_tmpa_box}{\hbox:n{
+ \pdfdest~name~{#1}~\l_pbs_fittype_tl
+ }}#4
+ }{
+ \pdfdest~name~{#1}~fitr~
+ width~\box_wd:N\l_tmpa_box~
+ height~\box_ht:N\l_tmpa_box~
+ depth~\box_dp:N\l_tmpa_box
+ \box_use:N\l_tmpa_box
+ }
+ \box_clear:N\l_tmpa_box
+ \group_end:
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfxform:nnnnn{ % #1 not used
+ %additional resources
+ \tl_set:Nx\l_tmpa_tl{\the\pdfpageresources~#3}\tl_trim_spaces:N\l_tmpa_tl
+ %additional dict entries
+ \tl_set:Nx\l_tmpb_tl{#4}
+ \tl_trim_spaces:N\l_tmpb_tl
+ \int_compare:nT{#2>\c_zero_int}{\immediate}
+ \pdfxform~
+ \str_if_eq:eeF{\l_tmpb_tl}{}{attr~{\l_tmpb_tl}~}
+ \str_if_eq:eeF{\l_tmpa_tl}{}{resources~{\l_tmpa_tl}~}#5
+ \tl_gset:Nx\g_pbs_pdflastxform_tl{\the\pdflastxform\space 0~R}
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfrefxform:n{% #1: xform obj ID
+ \hbox_overlap_right:n{\smash{\pdfrefxform\pbs_reftonum:n{#1}}}
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfximage:n{
+ \filename@parse{#1}
+ \tl_set:Nx\l_pbs_ext_tl{\tl_lower_case:n{\filename@ext}}
+ \bool_if:nTF{
+ \str_if_eq_p:Vn\l_pbs_ext_tl{png}
+ ||\str_if_eq_p:Vn\l_pbs_ext_tl{jpg}
+ ||\str_if_eq_p:Vn\l_pbs_ext_tl{jpeg}
+ ||\str_if_eq_p:Vn\l_pbs_ext_tl{jbig2}
+ ||\str_if_eq_p:Vn\l_pbs_ext_tl{jb2}
+ }{
+ \immediate\pdfximage{#1}
+ \tl_gset:Nx\g_pbs_pdflastximage_tl{\the\pdflastximage\space 0~R}
+ }{
+ \msg_error:nnnnn{pdfbase}{wrong~image~resource}{#1}{pdftex}{
+ png,~jpeg~and~jbig2
+ }
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfcatalog:n{\pdfcatalog{#1}}
+
+ \int_new:N\g_pbs_oc_int %object ID for marked content Properties
+
+ \cs_new_protected_nopar:Nn\pbs_zap_properties:{ %strip /Properties dict from
+ \group_begin: %/pdfpageresources
+ \tl_set:Nx\l_pbs_temp_tl{\group_end:
+ \global\pdfpageresources{
+ \exp_after:wN\_pbs_zap_properties:w\the\pdfpageresources/Properties<<>>.
+ }
+ }\l_pbs_temp_tl
+ }
+ \cs_new_nopar:Npn\_pbs_zap_properties:w#1/Properties<<#2>>#3{
+ \bool_if:nTF{\tl_if_empty_p:n{#2}&&\str_if_eq_p:nn{#3}{.}}{#1}{
+ #1\_pbs_zap_properties:w#3
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfbdc:nn{
+ \pdfliteral~page~{#1/rm@oc\int_use:N\g_pbs_oc_int\space BDC}
+ %decide whether the current property is to be written to the page
+ %resources or to the xobject resources, depending on whether marked content
+ %is written to a page stream or to an xobject stream (for compatibility with
+ %`xsavebox' package)
+ \bool_if:nTF{
+ \cs_if_exist:NTF\xsb_count_props:{
+ \int_compare_p:n{\xsb_count_props:>\c_zero_int}
+ }{
+ \c_false_bool
+ }
+ }{
+ \xsb_addto_props:n{/rm@oc\int_use:N\g_pbs_oc_int\space#2}
+ }{
+ \iow_shipout_x:Nx\@mainaux{\token_to_str:N\pbs@seq@push@cx{
+ pbs@props@\exp_not:N\int_use:N\g_pbs_page_int
+ }{/rm@oc\int_use:N\g_pbs_oc_int\space#2}}
+ }
+ \int_gincr:N\g_pbs_oc_int
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfemc:{\pdfliteral~page~{EMC}}
+
+ %inserts /Properties <<...>> entry into page resources
+ \cs_gset:Nn\pbs_insert_properties_entry:{
+ \pbs_zap_properties: %purge those from previous page
+ \tl_set:Nx\l_tmpa_tl{\seq_if_exist:cT{pbs@props@\int_use:N\g_pbs_page_int}{
+ \seq_use:cn{pbs@props@\int_use:N\g_pbs_page_int}{~}}}
+ \tl_trim_spaces:N\l_tmpa_tl
+ \str_if_eq:eeF{\l_tmpa_tl}{}{
+ \group_begin:
+ \tl_set:Nx\l_pbs_temp_tl{\group_end:
+ \global\pdfpageresources{
+ \the\pdfpageresources
+ /Properties<<\seq_if_exist:cT{pbs@props@\int_use:N\g_pbs_page_int}{
+ \seq_use:cn{pbs@props@\int_use:N\g_pbs_page_int}{~}
+ }>>
+ }
+ }\l_pbs_temp_tl
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_add_form_font:{
+ \cs_if_exist:cF{pbs_form_font_\pdffontobjnum\font}{
+ \tl_new:c{pbs_form_font_\pdffontobjnum\font}
+ \tl_gput_right:Nx\g_pbs_form_fonts_tl{
+ ~/FormFont\pdffontobjnum\font\space\pdffontobjnum\font\space 0~R
+ }
+ }
+ \tl_gset:Nx\g_pbs_last_form_font_tl{/FormFont\pdffontobjnum\font}
+ }
+ \cs_new_nopar:Nn\pbs_last_form_font:{\g_pbs_last_form_font_tl}
+}{
+ %pgf + transparency related settings
+ \bool_new:N\g_pbs_pgfloaded_bool
+ \bool_gset_false:N\g_pbs_pgfloaded_bool
+ \AtBeginDocument{
+ \@ifpackageloaded{pgf}{\bool_gset_true:N\g_pbs_pgfloaded_bool}{}
+ }
+ \int_new:N\g_pbs_obj_int %object ID
+ \bool_if:NTF\g_pbs_dvipdfmx_bool{ %dvipdfmx/XeTeX
+ \AtBeginDocument{
+ % suppress any annotation growth through (x)dvipdfmx option/config var `g'
+ \special{dvipdfmx:config~g~0}
+ % suppress link destination renaming (as in original dvipdfm
+ \special{dvipdfmx:config~C~0x10} % and in pre-2014 dvipdfmx)
+ }
+
+ %literal PDF code into content stream; open text objects are always closed
+ \cs_new_protected_nopar:Nn\pbs_literal:nn{ % #1: empty (`'), `direct' or `page'
+ \str_if_eq:nnTF{#1}{}{ % #2: raw PDF
+ % set current location's coordinates to (0,0), while saving graphics
+ % state before and re-instating after insertion (this is different from
+ % \pdfliteral{...}
+ \special{pdf:content~#2}
+ }{
+ % `direct' works the same as `page': no origin translation,
+ % no gs saving, but closing open text objects
+ \special{pdf:code~#2}
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfobj:nnn{
+ \tl_if_blank:oTF{#1}{
+ \tl_set:Nx\l_pbs_usenum_tl{@pbs@obj\int_use:N\g_pbs_obj_int}
+ \int_gincr:N\g_pbs_obj_int
+ }{
+ \tl_set:Nx\l_pbs_usenum_tl{#1}
+ }
+ \tl_if_blank:oF{#3}{
+ \str_case:nn{#2}{
+ {generic}{\special{pdf:obj~\l_pbs_usenum_tl\space #3}}
+ {dict}{\special{pdf:obj~\l_pbs_usenum_tl\space<<#3>>}}
+ {array}{\special{pdf:obj~\l_pbs_usenum_tl\space[#3]}}
+ {stream}{\special{pdf:stream~\l_pbs_usenum_tl\space
+ (\use_ii:nn#3)<<\use_i:nn#3>>
+ }}
+ {fstream}{
+ \message{<\use_ii:nn#3>}
+ \special{pdf:fstream~\l_pbs_usenum_tl\space
+ (\use_ii:nn#3)<<\use_i:nn#3>>
+ }
+ }
+ }
+ }
+ \tl_gset_eq:NN\g_pbs_pdflastobj_tl\l_pbs_usenum_tl
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfannot:nnnn{
+ \special{pdf:ann~@pbs@obj\int_use:N\g_pbs_obj_int\space
+ width~\dim_eval:n{#1}~height~\dim_eval:n{#2}~depth~\dim_eval:n{#3}~
+ <<\cs_if_exist_use:N\ocgbase_insert_oc:~#4>>
+ }
+ \tl_gset:Nx\g_pbs_pdflastann_tl{@pbs@obj\int_use:N\g_pbs_obj_int}
+ \int_gincr:N\g_pbs_obj_int
+ }
+
+ \cs_new_protected:Nn\pbs_pdflink:nn{
+ \leavevmode
+ \special{pdf:bann~<<\cs_if_exist_use:N\ocgbase_insert_oc:~#1>>}#2
+ \special{pdf:eann}
+ }
+
+ \cs_new_protected:Nn\pbs_pdfdest:nnnn{
+ \leavevmode
+ \str_case:nnTF{#2}{
+ {fit}{\tl_set:Nn\l_pbs_fittype_tl{/Fit}}
+ {fitb}{\tl_set:Nn\l_pbs_fittype_tl{/FitB}}
+ {fitbv}{\tl_set:Nn\l_pbs_fittype_tl{/FitBV~@xpos}}
+ {fitv}{\tl_set:Nn\l_pbs_fittype_tl{/FitV~@xpos}}
+ }{
+ \special{pdf:~dest~(#1)~[~@thispage~\l_pbs_fittype_tl]}#4
+ }{
+ \group_begin:
+ \hbox_set:Nn\l_tmpa_box{#4}
+ \str_case:nnTF{#2}{
+ {fitbh}{\tl_set:Nn\l_pbs_fittype_tl{/FitBH~@ypos}}
+ {fith}{\tl_set:Nn\l_pbs_fittype_tl{/FitH~@ypos}}
+ {xyz}{\tl_set:Nn\l_pbs_fittype_tl{/XYZ~@xpos~@ypos~#3}}
+ }{
+ \box_move_up:nn{\box_ht:N\l_tmpa_box}{\hbox:n{
+ \special{pdf:~dest~(#1)~[~@thispage~\l_pbs_fittype_tl]}
+ }}#4
+ }{ % FitR
+ \box_move_down:nn{\box_dp:N\l_tmpa_box}{\hbox:n{
+ \pbs_pdfobj:nnn{}{generic}{@xpos}
+ \tl_gset_eq:NN\g_pbs_llx_tl\g_pbs_pdflastobj_tl
+ \pbs_pdfobj:nnn{}{generic}{@ypos}
+ \tl_gset_eq:NN\g_pbs_lly_tl\g_pbs_pdflastobj_tl
+ }}
+ \box_use:N\l_tmpa_box
+ \box_move_up:nn{\box_ht:N\l_tmpa_box}{\hbox:n{
+ \special{pdf:~dest~(#1)~[@thispage~
+ /FitR~
+ \g_pbs_llx_tl\space\g_pbs_lly_tl\space @xpos~@ypos
+ ]}
+ }}
+ }
+ \box_clear:N\l_tmpa_box
+ \group_end:
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfxform:nnnnn{ % #2 not used
+ \begin{picture}(0,0)
+ \put(0,0){
+ \special{pdf:bxobj~@pbs@obj\int_use:N\g_pbs_obj_int\space
+ width~\dim_eval:n{\box_wd:N#5}~
+ height~\space\dim_eval:n{\box_ht:N#5}~
+ depth~\space \dim_eval:n{\box_dp:N#5}
+ }
+ \box_use:N#5
+ \tl_clear:N\l_tmpa_tl{}
+ %transparency et al. for PGF
+ \bool_if:nT{\int_compare_p:n{#1>\c_zero_int} && \g_pbs_pgfloaded_bool}{
+ \ifpgf@sys@pdf@extgs@exists
+ \tl_set:Nn\l_tmpa_tl{/ExtGState~@pgfextgs}
+ \fi
+ \ifpgf@sys@pdf@patterns@exists
+ \tl_put_right:Nn\l_tmpa_tl{/Pattern~@pgfpatterns}
+ \fi
+ \ifpgf@sys@pdf@colorspaces@exists
+ \tl_put_right:Nn\l_tmpa_tl{/ColorSpace~@pgfcolorspaces}
+ \fi
+ }
+ %additional resources
+ \tl_put_right:Nx\l_tmpa_tl{~#3}\tl_trim_spaces:N\l_tmpa_tl
+ \str_if_eq:eeF{\l_tmpa_tl}{}{
+ \special{pdf:put~@resources~<<\l_tmpa_tl>>}
+ }
+ %additional dict entries
+ \tl_set:Nx\l_tmpa_tl{#4}
+ \tl_trim_spaces:N\l_tmpa_tl
+ \special{pdf:exobj %close form xobject
+ \str_if_eq:eeF{\l_tmpa_tl}{}{<<\l_tmpa_tl>>}
+ }
+ }
+ \end{picture}
+ \tl_gset:Nx\g_pbs_pdflastxform_tl{@pbs@obj\int_use:N\g_pbs_obj_int}
+ \int_gincr:N\g_pbs_obj_int
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfrefxform:n{\special{pdf:uxobj~#1}}% #1: xform obj ID
+
+ \cs_new_protected_nopar:Nn\pbs_pdfximage:n{
+ \filename@parse{#1}
+ \tl_set:Nx\l_pbs_ext_tl{\tl_lower_case:n{\filename@ext}}
+ \bool_if:nTF{
+ \str_if_eq_p:Vn\l_pbs_ext_tl{png}
+ ||\str_if_eq_p:Vn\l_pbs_ext_tl{jpg}
+ ||\str_if_eq_p:Vn\l_pbs_ext_tl{jpeg}
+ }{
+ \special{pdf:image~@pbs@obj\int_use:N\g_pbs_obj_int\space
+ %move initial display off the page
+ matrix~0.000001~0~0~0.000001~-1000000~-1000000~(#1)}
+ \tl_gset:Nx\g_pbs_pdflastximage_tl{@pbs@obj\int_use:N\g_pbs_obj_int}
+ \int_gincr:N\g_pbs_obj_int
+ }{
+ \msg_error:nnnnn{pdfbase}{wrong~image~resource}{#1}{dvipdfmx/xetex}{
+ png~and~jpeg
+ }
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfcatalog:n{\special{pdf:put~@catalog~<<#1>>}}
+
+ \int_new:N\g_pbs_oc_int %object ID
+ \cs_new_protected_nopar:Nn\pbs_pdfbdc:nn{
+ \special{pdf:code~#1/rm@oc\int_use:N\g_pbs_oc_int\space BDC}
+ \special{pdf:put~@resources~<<
+ /Properties~<</rm@oc\int_use:N\g_pbs_oc_int\space#2>>>>}
+ \int_gincr:N\g_pbs_oc_int
+ }
+ \cs_new_nopar:Nn\pbs_pdfemc:{\special{pdf:code~EMC}}
+ }{
+ \bool_if:NTF\g_pbs_dvisvgm_bool{
+ \tl_gset:Nx\g_pbs_hash_tl{\token_to_str:N#}
+ %insert literal Postscript code
+ \cs_new_protected_nopar:Nn\pbs_literal:nn{ % #1: empty (`'), `direct' or `page'
+ \str_if_eq:nnTF{#1}{}{ % #2: raw Postscript
+ % set current location's coordinates to (0,0) and set unit vectors to
+ % 1bp right and 1bp upwards; graphics state is saved before and
+ % re-instated after insertion
+ \special{"~#2}
+ }{
+ % `direct' does the same as `page': no origin translation,
+ % no gs saving
+ \special{ps::~#2}
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfannot:nnnn{
+ \special{dvisvgm:raw~{?nl}<path~d=}
+ \group_begin:\dim_set:Nn\unitlength{1pt}
+ \begin{picture}(0,0)% mark annotation rectangle
+ \put(0,-\dim_to_decimal:n{#3}){% ll
+ \special{dvisvgm:raw~'M{?x}~{?y}}
+ }
+ \put(\dim_to_decimal:n{#1},-\dim_to_decimal:n{#3}){% lr
+ \special{dvisvgm:raw~{?nl}L{?x}~{?y}}
+ }
+ \put(\dim_to_decimal:n{#1},\dim_to_decimal:n{#2}){% ur
+ \special{dvisvgm:raw~{?nl}L{?x}~{?y}}
+ }
+ \put(0,\dim_to_decimal:n{#2}){% ul
+ \special{dvisvgm:raw~{?nl}L{?x}~{?y}~Z'}
+ }
+ \end{picture}
+ \group_end:
+ \special{dvisvgm:raw~{?nl}opacity='0'~#4~class='annot'/>}
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfxform:nnnnn{
+ \makebox[\c_zero_dim][l]{
+ \raisebox{\c_zero_dim}[\c_zero_dim][\c_zero_dim]{
+ \special{dvisvgm:raw~{?nl}<defs>{?nl}
+ <
+ g~transform='translate(-{?x},-{?y})'~#4~
+ id='pbs@obj\int_use:N\g_pbs_obj_int'~class='xform'
+ >
+ }
+ \box_use_drop:N#5
+ \special{dvisvgm:raw~{?nl}</g>{?nl}</defs>}
+ }
+ }
+ \tl_gset:Nx\g_pbs_pdflastxform_tl{\g_pbs_hash_tl pbs@obj\int_use:N\g_pbs_obj_int}
+ \int_gincr:N\g_pbs_obj_int
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfrefxform:n{
+ \special{dvisvgm:raw~{?nl}<use~x='{?x}'~y='{?y}'~xlink:href='#1'/>}
+ }
+ }{
+ %dvips
+ \bool_new:N\g_pbs_powerdot_bool %to cope with some powerdot oddity
+ \@ifclassloaded{powerdot}{\bool_gset_true:N\g_pbs_powerdot_bool}{}
+
+ \sys_if_engine_pdftex:TF{
+ \cs_new_nopar:Nn\pbs_filesize:n{\pdffilesize{#1}}
+ \cs_new_nopar:Nn\pbs_filedump:nnn{\pdffiledump~offset~#1~length~#2~{#3}}
+ }{
+ \sys_if_engine_luatex:T{
+ \RequirePackage{pdftexcmds}
+ \cs_new_nopar:Nn\pbs_filesize:n{\pdf@filesize{#1}}
+ \cs_new_nopar:Nn\pbs_filedump:nnn{\pdf@filedump{#1}{#2}{#3}}
+ }
+ }
+
+ \AtBeginDocument{
+ \@ifpackageloaded{hyperref}{}{
+ %define `?pdfmark' operator as in file pdfmark.def from package `hyperref'
+ \special{!~
+ systemdict~/pdfmark~known
+ {
+ userdict~/?pdfmark~systemdict~/exec~get~put
+ }{
+ userdict~/?pdfmark~systemdict~/pop~get~put~
+ userdict~/pdfmark~systemdict~/cleartomark~get~put
+ }
+ ifelse
+ }
+ }
+ \special{!~
+ %keeping track of xform nesting level
+ true~setglobal~globaldict~/pbs@xform@level~0~put~false~setglobal
+ %back-transforms user coords to page coords (bigpoints with reference
+ %point [0,0] in the bottom-left page corner)
+ % user_x user_y pbs@user2page --> page_x page_y
+ /pbs@user2page~{
+ 0~begin~% make everything local in here
+ /y~exch~def~/x~exch~def~
+ matrix~currentmatrix~
+ matrix~defaultmatrix~
+ matrix~invertmatrix~
+ matrix~concatmatrix~cvx~exec~
+ /ty~exch~def~/tx~exch~def~
+ /d~exch~def~/c~exch~def~
+ /b~exch~def~/a~exch~def~
+ x~a~mul~y~c~mul~add~tx~add~
+ x~b~mul~y~d~mul~add~ty~add~
+ end
+ }~def~
+ /pbs@user2page~load~0~1~dict~put % insert dict at index 0;
+ } % dict is allocated only once
+ }
+ \cs_new:Nn\pbs_special:n{\special{ps:~SDict~begin~#1~end}}
+
+ \bool_if:NT\g_pbs_pkgbigfiles_bool{
+ \special{psfile=\jobname.pbsdat}
+ %open auxiliary file \jobname.pbsdat for writing hex encoded streams of
+ %the files to be embedded. This file is inserted into PS during dvips.
+ \iow_new:N\g_pbs_mstreams_stream
+ \iow_open:Nn\g_pbs_mstreams_stream{\jobname.pbsdat}
+ \iow_now:Nn\g_pbs_mstreams_stream{
+ /M9D~1~dict~def~M9D~begin
+ /o{mark/_objdef}bind~def/O{/type/stream/OBJ~pdfmark}bind~def
+ /m~systemdict/mark~get~def
+ /P{/ASCIIHexDecode~filter/PUT~pdfmark}bind~def
+ /PP{/PUT~pdfmark}bind~def
+ /C{/CLOSE~pdfmark}bind~def~end
+ }
+ }
+
+ %insert literal Postscript code
+ \cs_new_protected_nopar:Nn\pbs_literal:nn{ % #1: empty (`'), `direct' or `page'
+ \str_if_eq:nnTF{#1}{}{ % #2: raw Postscript
+ % set current location's coordinates to (0,0) and set unit vectors to
+ % 1bp right and 1bp upwards; graphics state is saved before and
+ % re-instated after insertion
+ \special{"~#2}
+ }{
+ % `direct' does the same as `page': no origin translation,
+ % no gs saving
+ \special{ps::~#2}
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfobj:nnn{
+ \tl_clear:N\l_pbs_usenum_tl
+ \tl_if_blank:oTF{#1}{
+ \tl_set:Nx\l_pbs_usenum_tl{{pbs@obj\int_use:N\g_pbs_obj_int}}
+ \int_gincr:N\g_pbs_obj_int
+ }{
+ \tl_set:Nx\l_pbs_usenum_tl{#1}
+ }
+ \str_if_eq:nnT{#2}{generic}{
+ \msg_interrupt:nnn{pdfbase~error}{
+ generic~object~creation~not~supported~by~PDFmarks
+ }{}
+ }
+ \tl_if_blank:oF{#3}{
+ \bool_if:nTF{
+ \g_pbs_pkgbigfiles_bool &&
+ \str_if_eq_p:nn{#2}{fstream}
+ }{
+ \iow_now:Nx\g_pbs_mstreams_stream{
+ M9D~begin~o\l_pbs_usenum_tl O
+ }
+ }{
+ \pbs_special:n{mark~/_objdef~\l_pbs_usenum_tl\space/type
+ \str_case:nn{#2}{
+ {generic}{}
+ {dict}{/dict}
+ {array}{/array}
+ {stream}{/stream}
+ {fstream}{/stream}
+ }~
+ /OBJ~pdfmark
+ }
+ }
+ \str_case:nn{#2}{
+ {generic}{}
+ {dict}{\pbs_special:n{mark~\l_pbs_usenum_tl~<<#3>>/PUT~pdfmark}}
+ {array}{
+ \pbs_special:n{mark~\l_pbs_usenum_tl~0~[#3]/PUTINTERVAL~pdfmark}
+ }
+ {stream}{\special{ps::[nobreak]~SDict~begin~
+ mark~\l_pbs_usenum_tl~(\use_ii:nn#3)/PUT~pdfmark~
+ mark~\l_pbs_usenum_tl~<<\use_i:nn#3>>/PUT~pdfmark~end
+ }}
+ {fstream}{
+ \tl_set:Nn\l_pbs_offset_tl{0}
+ \tl_set:Nx\l_pbs_fsize_tl{\pbs_filesize:n{\use_ii:nn#3}}
+ \message{<\use_ii:nn#3}
+ %embed file in chunks of 32768 Bytes into PS as chunks of
+ %65536 Bytes of HEX code
+ \bool_while_do:nn{
+ \int_compare_p:n{\l_pbs_offset_tl<\l_pbs_fsize_tl}
+ }{
+ \bool_if:NTF\g_pbs_pkgbigfiles_bool{
+ \iow_now:Nx\g_pbs_mstreams_stream{
+ m\l_pbs_usenum_tl
+ (\pbs_filedump:nnn{\l_pbs_offset_tl}{32767}{
+ \use_ii:nn#3
+ })P
+ }
+ }{
+ \pbs_special:n{
+ mark~
+ \l_pbs_usenum_tl~
+ (\pbs_filedump:nnn{\l_pbs_offset_tl}{32767}{
+ \use_ii:nn#3
+ })~
+ /ASCIIHexDecode~filter~/PUT~
+ pdfmark
+ }
+ }
+ \tl_set:Nx\l_pbs_offset_tl{\int_eval:n{\l_pbs_offset_tl+32767}}
+ \message{.}
+ }
+ \bool_if:NTF\g_pbs_pkgbigfiles_bool{
+ \iow_now:Nx\g_pbs_mstreams_stream{
+ m\l_pbs_usenum_tl<<\use_i:nn#3>>PP~
+ m\l_pbs_usenum_tl~C~end
+ }
+ }{
+ \pbs_special:n{
+ mark~\l_pbs_usenum_tl~<<\use_i:nn#3>>~/PUT~pdfmark~
+ mark~\l_pbs_usenum_tl~/CLOSE~pdfmark
+ }
+ }
+ \message{>}
+ }
+ }
+ }
+ \tl_gset_eq:NN\g_pbs_pdflastobj_tl\l_pbs_usenum_tl
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfannot:nnnn{
+ \group_begin:
+ \dim_set:Nn\unitlength{1pt}
+ \begin{picture}(0,0)% mark annotation rectangle
+ \put(0,-\dim_to_decimal:n{#3}){
+ \pbs_special:n{currentpoint~/pbs@lly~exch~def~/pbs@llx~exch~def}
+ }
+ \put(\dim_to_decimal:n{#1},\dim_to_decimal:n{#2}){
+ \pbs_special:n{currentpoint~/pbs@ury~exch~def~/pbs@urx~exch~def}
+ }
+ \end{picture}
+ \group_end:
+ \str_if_eq:eeF{#4}{}{
+ \pbs_special:n{
+ mark~
+ /_objdef~{pbs@obj\int_use:N\g_pbs_obj_int}
+ /Rect~[pbs@llx~pbs@lly~pbs@urx~pbs@ury]
+ \cs_if_exist_use:N\ocgbase_insert_oc:~#4
+ /ANN~pdfmark
+ }
+ \tl_gset:Nx\g_pbs_pdflastann_tl{{pbs@obj\int_use:N\g_pbs_obj_int}}
+ \int_gincr:N\g_pbs_obj_int
+ }
+ }
+
+ \cs_new_protected:Nn\pbs_pdflink:nn{
+ \leavevmode
+ \cs_if_exist:NTF\pdfmark{
+ \pdfmark[#2]{pdfmark=/ANN,Raw={
+ \cs_if_exist_use:N\ocgbase_insert_oc:~#1}}
+ }{
+ \hbox_set:Nn\l_tmpb_box{#2}
+ \pbs_pdfannot:nnnn{
+ \dim_use:N\box_wd:N\l_tmpb_box}{
+ \dim_use:N\box_ht:N\l_tmpb_box}{
+ \dim_use:N\box_dp:N\l_tmpb_box
+ }{#1}
+ \box_use_drop:N\l_tmpb_box
+ }
+ }
+
+ \cs_new_protected:Nn\pbs_pdfdest:nnnn{
+ \leavevmode
+ \group_begin:
+ %write destination page number to aux
+ \iow_shipout_x:Nx\@mainaux{
+ \token_to_str:N\pbs@newkey{pbs@#1@destpage}{
+ \exp_not:N\int_use:N\exp_not:N\g_pbs_page_int}
+ }
+ \cs_if_exist:cF{pbs@#1@destpage}{
+ \tl_set:cn{pbs@#1@destpage}{0}
+ \cs_if_exist:NF\g_pbs_rerunwarned_tl{
+ \tl_new:N\g_pbs_rerunwarned_tl
+ \msg_warning:nn{pdfbase}{rerun}
+ }
+ }
+ \str_case:nnTF{#2}{
+ {fit}{\tl_set:Nn\l_pbs_fittype_tl{/Fit}}
+ {fitb}{\tl_set:Nn\l_pbs_fittype_tl{/FitB}}
+ }{
+ \pbs_special:n{
+ mark~/Dest~(#1)~cvn~/Page~\tl_use:c{pbs@#1@destpage}~/View~[
+ \l_pbs_fittype_tl
+ ]~/DEST~pdfmark
+ }
+ #4
+ }{
+ \hbox_set:Nn\l_tmpa_box{#4}
+ %mark anchor/view rect, insert text, insert destination
+ \str_case:nnTF{#2}{
+ {fitbh}{\tl_set:Nn\l_pbs_fittype_tl{/FitBH}}
+ {fith}{\tl_set:Nn\l_pbs_fittype_tl{/FitH}}
+ }{
+ \box_move_up:nn{\box_ht:N\l_tmpa_box}{\hbox:n{
+ \pbs_special:n{
+ currentpoint~pbs@user2page~/pbs@top~exch~def~pop~
+ mark~/Dest~(#1)~cvn~/Page~\tl_use:c{pbs@#1@destpage}~/View~[
+ \l_pbs_fittype_tl\space pbs@top
+ ]~/DEST~pdfmark
+ }
+ }}
+ #4
+ }{
+ \str_case:nnTF{#2}{
+ {fitbv}{\tl_set:Nn\l_pbs_fittype_tl{/FitBV}}
+ {fitv}{\tl_set:Nn\l_pbs_fittype_tl{/FitV}}
+ }{
+ \pbs_special:n{
+ currentpoint~pbs@user2page~pop~/pbs@left~exch~def~
+ mark~/Dest~(#1)~cvn~/Page~\tl_use:c{pbs@#1@destpage}~/View~[
+ \l_pbs_fittype_tl\space pbs@left
+ ]~/DEST~pdfmark
+ }
+ #4
+ }{
+ \str_case:nn{#2}{
+ {xyz}{
+ \box_move_up:nn{\box_ht:N\l_tmpa_box}{\hbox:n{
+ \pbs_special:n{
+ currentpoint~pbs@user2page~
+ /pbs@top~exch~def~/pbs@left~exch~def~
+ mark~/Dest~(#1)~cvn~/Page~\tl_use:c{pbs@#1@destpage}~
+ /View~[
+ /XYZ~pbs@left~pbs@top~#3
+ ]~/DEST~pdfmark
+ }
+ }}
+ #4
+ }
+ {fitr}{
+ \box_move_down:nn{\box_dp:N\l_tmpa_box}{\hbox:n{
+ \pbs_special:n{
+ currentpoint~pbs@user2page~
+ /pbs@lly~exch~def~/pbs@llx~exch~def
+ }
+ }}
+ \box_use:N\l_tmpa_box
+ \box_move_up:nn{\box_ht:N\l_tmpa_box}{\hbox:n{
+ \pbs_special:n{
+ currentpoint~pbs@user2page~
+ /pbs@ury~exch~def~/pbs@urx~exch~def~
+ mark~/Dest~(#1)~cvn~/Page~\tl_use:c{pbs@#1@destpage}~
+ /View~[
+ /FitR~pbs@llx~pbs@lly~pbs@urx~pbs@ury
+ ]~/DEST~pdfmark
+ }
+ }}
+ }
+ }
+ }
+ }
+ \box_clear:N\l_tmpa_box
+ }
+ \group_end:
+ }
+
+ \msg_set:nnn{pdfbase}{content~too~large}{
+ Line~\msg_line_number: :\\
+ Content~exceeds~paper~size~(width~and/or~height)\\
+ of~the~document~and~may~be~clipped~in~the~final\\
+ output.
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfxform:nnnnn{ % #1, #3 not used (resources are
+ %this allows nesting \pbs_pdfxform:nnnnn{...} % managed by pdfmarks)
+ \pbs_special:n{
+ gsave~
+ pbs@xform@level~0~eq~{/pbs@ctm@0~matrix~currentmatrix~def}~if~
+ pbs@ctm@0~setmatrix~
+ true~setglobal~
+ globaldict~/pbs@xform@level~pbs@xform@level~1~add~put~
+ false~setglobal
+ }
+ %rescale box to fit within the papersize while distilling
+ \tl_gset:cx{scale_{pbs@obj\int_use:N\g_pbs_obj_int}}{\fp_eval:n{min(1.0,
+ \dim_ratio:nn{\paperwidth}{\box_wd:N#5},
+ \dim_ratio:nn{\paperheight}{\box_ht:N#5+\box_dp:N#5}
+ )}}
+ \box_scale:Nnn#5{
+ \tl_use:c{scale_{pbs@obj\int_use:N\g_pbs_obj_int}}
+ }{
+ \tl_use:c{scale_{pbs@obj\int_use:N\g_pbs_obj_int}}
+ }
+ \group_begin:
+ %mark bbox of box#5
+ \dim_set:Nn\unitlength{1pt}
+ \begin{picture}(0,0)
+ \put(0,-\dim_to_decimal:n{\box_dp:N#5}){
+ \pbs_special:n{
+ currentpoint~/pbs@lly~exch~def~/pbs@llx~exch~def
+ }
+ }
+ \put(
+ \dim_to_decimal:n{\box_wd:N#5},
+ \dim_to_decimal:n{\box_ht:N#5}
+ ){
+ \pbs_special:n{
+ currentpoint~/pbs@ury~exch~def~/pbs@urx~exch~def
+ }
+ }
+ \end{picture}
+ \group_end:
+ %additional dict entries
+ \tl_set:Nx\l_tmpa_tl{#4} \tl_trim_spaces:N\l_tmpa_tl
+ \pbs_special:n{
+ gsave~
+ currentpoint~/pbs@cury~exch~def~/pbs@curx~exch~def~
+ %translate graphics to upper left page corner
+ \bool_if:nF{\g_pbs_powerdot_bool||\g_pbs_lscape_bool}{
+ {
+ pbs@llx~neg~pbs@ury~neg~translate~
+ Resolution~neg~VResolution~neg~translate %one inch left, one inch up
+ }?pdfmark~
+ }
+ %distill graphics to XObject
+ gsave~pbs@curx~pbs@cury~translate~ %move origin (0,0) to the current
+ mark~ %position
+ /_objdef~{pbs@obj\int_use:N\g_pbs_obj_int}
+ /BBox~[
+ pbs@llx~pbs@curx~sub~pbs@lly~pbs@cury~sub~
+ pbs@urx~pbs@curx~sub~pbs@ury~pbs@cury~sub
+ ]
+ %insert additional dict entries (the Distiller way)
+ \str_if_eq:eeF{\l_tmpa_tl}{}{
+ product~(Distiller)~search~{pop~pop~pop~\l_tmpa_tl}{pop}ifelse
+ }
+ /BP~pdfmark~grestore~
+ \int_compare:nT{#2>\c_zero_int}{
+ %operations needed if used as annotation appearance
+ {
+ isls{%landscape mode (powerdot, geometry /w landscape option)
+ /pbs@dxdy~{
+ pbs@urx~pbs@llx~sub~abs~
+ pbs@ury~pbs@lly~sub~abs~div
+ }~bind~def
+ /pbs@dydx~{1~pbs@dxdy~div}~bind~def
+ /pbs@cx~{pbs@urx~pbs@llx~add~2~div}~bind~def
+ /pbs@cy~{pbs@ury~pbs@lly~add~2~div}~bind~def
+ %graphics needs to be rescaled for some reason ...
+ [pbs@dxdy~0~0~pbs@dydx~1~pbs@dxdy~sub~pbs@cx~mul~
+ 1~pbs@dydx~sub~pbs@cy~mul]~concat
+ %... rotated by 270 degrees ...
+ [0~-1~1~0~pbs@cx~pbs@cy~sub~pbs@cx~pbs@cy~add]~concat
+ %... and flipped around vertical axis
+ [-1~0~0~1~pbs@llx~pbs@urx~add~0]~concat
+ }{%flip around horizontal axis in portrait mode
+ [1~0~0~-1~0~pbs@lly~pbs@ury~add]~concat
+ }ifelse
+ }?pdfmark
+ }
+ }
+ \begin{picture}(0,0)\put(0,0){\box_use:N#5}\end{picture}
+ \pbs_special:n{~mark~/EP~pdfmark~grestore}
+ %insert additional dict entries (the Ghostscript way)
+ \str_if_eq:eeF{\l_tmpa_tl}{}{
+ \pbs_special:n{
+ product~(Ghostscript)~search~{
+ pop~pop~pop~
+ mark~{pbs@obj\int_use:N\g_pbs_obj_int}~<<\l_tmpa_tl>>~/PUT~pdfmark
+ }{pop}ifelse
+ }
+ }
+ \tl_gset:Nx\g_pbs_pdflastxform_tl{{pbs@obj\int_use:N\g_pbs_obj_int}}
+ \int_gincr:N\g_pbs_obj_int
+ \int_compare:nT{#2>\c_zero_int}{
+ %Form XObjects for use as annotation appearances require that
+ %dvips generated PostScript to be further processed with ps2pdf
+ %must not have the exaggerated dpi resolution resulting from dvips
+ %option `-Ppdf'.
+ \tl_if_exist:NF\g_pbs_dpiwarned_tl{
+ \tl_new:N\g_pbs_dpiwarned_tl
+ \pbs_at_end_dvi:n{
+ \special{ps::[nobreak]~SDict~begin~\pbs_dpiwarning:\space end}
+ }
+ }
+ }
+ \pbs_special:n{
+ true~setglobal~
+ globaldict~/pbs@xform@level~pbs@xform@level~1~sub~put~
+ false~setglobal~
+ grestore
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfrefxform:n{% #1: xform obj ID
+ %The /SP pdfmark for placement of Form XObjects works reliably only
+ %since gs-9.14. As gs-9.14 had some other TeX-related issues, we
+ %require 9.15.
+ \tl_if_exist:NF\g_pbs_gsoldwarned_tl{
+ \tl_new:N\g_pbs_gsoldwarned_tl
+ \pbs_at_end_dvi:n{
+ \special{ps::[nobreak]~SDict~begin~\pbs_gsoldwarning:\space end}
+ }
+ }
+ \pbs_special:n{
+ gsave~currentpoint~translate~1~\tl_use:c{scale_#1}~div~dup~scale~
+ mark~#1~/SP~pdfmark~grestore
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfximage:n{
+ \filename@parse{#1}
+ \tl_set:Nx\l_pbs_ext_tl{\tl_lower_case:n{\filename@ext}}
+ \bool_if:nTF{
+ \str_if_eq_p:Vn\l_pbs_ext_tl{ps}
+ ||\str_if_eq_p:Vn\l_pbs_ext_tl{eps}
+ }{
+ \pbs_special:n{
+ mark~/_objdef~{pbs@obj\int_use:N\g_pbs_obj_int}~/NI~pdfmark
+ }
+ \special{psfile=#1~hsize=0~vsize=0}
+ \pbs_special:n{
+ {
+ 0~0~1~[1~0~0~1~0~0]~{}~image~%empty dummy, in case #1 is not
+ }?pdfmark %a valid raster image file
+ }
+ \tl_gset:Nx\g_pbs_pdflastximage_tl{{pbs@obj\int_use:N\g_pbs_obj_int}}
+ \int_gincr:N\g_pbs_obj_int
+ }{
+ \msg_error:nnxxx{pdfbase}{wrong~image~resource}{#1}{dvips}{
+ Postscript~(ps/eps)~with~bitmapped~content
+ }
+ }
+ }
+
+ \cs_new_protected_nopar:Nn\pbs_pdfcatalog:n{
+ \pbs_special:n{~mark~{Catalog}~<<#1>>~/PUT~pdfmark}
+ }
+
+ %marked content BDC/EMC operators
+ %require Ghostscript v. >= 9.15
+ \cs_new_protected_nopar:Nn\pbs_pdfbdc:nn{
+ \pbs_special:n{~mark~#1~#2~/BDC~pdfmark}
+ \tl_if_exist:NF\g_pbs_gsoldwarned_tl{
+ \tl_new:N\g_pbs_gsoldwarned_tl
+ \pbs_at_end_dvi:n{
+ \special{ps::[nobreak]~SDict~begin~\pbs_gsoldwarning:\space end}
+ }
+ }
+ }
+ \cs_new_nopar:Nn\pbs_pdfemc:{\pbs_special:n{~mark~/EMC~pdfmark}}
+ }
+ }
+}
+
+\cs_new_nopar:Nn\pbs_pdflastobj:{\g_pbs_pdflastobj_tl}
+\cs_new_nopar:Nn\pbs_pdflastann:{\g_pbs_pdflastann_tl}
+\cs_new_nopar:Nn\pbs_pdflastxform:{\g_pbs_pdflastxform_tl}
+\cs_new_nopar:Nn\pbs_pdflastximage:{\g_pbs_pdflastximage_tl}
+
+%adding AcroForm dict to PDF Catalog
+\tl_new:N\g_pbs_fields_tl %takes object IDs of Fields (aka annots with
+\tl_new:N\g_pbs_form_fonts_tl %name tree of font resources used in text fields
+\pbs_at_end_dvi:n{
+ \tl_if_empty:NF\g_pbs_fields_tl{
+ \pbs_pdfobj:nnn{}{array}{\g_pbs_fields_tl}
+ \pbs_pdfcatalog:n{
+ /AcroForm~<<
+ /Fields~\pbs_pdflastobj:/NeedAppearances~false~
+ \tl_if_empty:NF\g_pbs_form_fonts_tl{
+ /DR~<</Font~<<\g_pbs_form_fonts_tl>> >>
+ }
+ >>
+ }
+ }
+}
+\cs_new_protected_nopar:Nn\pbs_appendtofields:n{
+ \tl_gput_left:Nx\g_pbs_fields_tl{#1\space}
+}
+
+%modify output routine for output box insertions
+\bool_new:N\l_pbs_is_vertical_bool
+\cs_set_eq:NN\pbs_outputpage_orig:\@outputpage
+\cs_set_nopar:Npn\@outputpage{
+ \int_gincr:N\g_pbs_page_int
+ \iow_now:Nx\@mainaux{
+ \token_to_str:N\pbs@newkey{pbs@last@page}{\int_use:N\g_pbs_page_int}
+ }
+ \box_if_vertical:cTF{@outputbox}{
+ \bool_set_true:N\l_pbs_is_vertical_bool
+ }{
+ \bool_set_false:N\l_pbs_is_vertical_bool
+ }
+ \hbox_set:Nn\@outputbox{
+ %begin of page
+ \hbox_overlap_right:n{\seq_map_inline:Nn\g_pbs_bop_seq{##1}}
+ \box_use_drop:N\@outputbox
+ %end of page
+ \hbox_overlap_right:n{\seq_map_inline:Nn\g_pbs_eop_seq{##1}}
+ }
+ \bool_if:NT\l_pbs_is_vertical_bool{
+ \vbox_set:Nn\@outputbox{\box_use_drop:N\@outputbox}
+ }
+ \pbs_outputpage_orig:
+}
+
+\RequirePackage{atbegshi}
+\AtBeginDocument{
+ \bool_new:N\g_pbs_ocgbase_loaded_bool
+ \@ifpackageloaded{ocgbase}{
+ \bool_gset_true:N\g_pbs_ocgbase_loaded_bool
+ }{}
+ \AtBeginShipout{
+ \AtBeginShipoutAddToBoxForeground{
+ %insert /Properties into current page's resources
+ \pbs_insert_properties_entry:
+ %end of dvi (last page)
+ \int_compare:nT{\pbs@last@page=\g_pbs_page_int}{
+ \seq_map_variable:NNn\g_pbs_eod_seq\l_tmpa_tl{\l_tmpa_tl}
+ }
+ }
+ \AtBeginShipoutUpperLeft{
+ % workaround for curious AR bug (pdf annot or link placed on
+ % OCG remains active when OCG is hidden)
+ % see https://forums.adobe.com/message/5787612#5787612
+ % This can be fixed by placing a dumb (non-interactive) Widget dummy
+ % somewhere on the page.
+ \bool_if:NT\g_pbs_ocgbase_loaded_bool{
+ \skip_horizontal:n{1bp}
+ \box_move_down:nn{1bp}{\vbox:n{
+ \pbs_pdfannot:nnnn{3bp}{\c_zero_dim}{3bp}{
+ /Ff~65537/FT/Btn/Subtype/Widget
+ /T~(pbs@ARFix@\int_use:N\g_pbs_page_int)
+ }
+ }}
+ }
+ }
+ }
+}
+
+\group_begin:
+\char_set_catcode_active:N\+\let+\space
+\cs_new_nopar:Nx\pbs_gsoldwarning:{
+ {product~(Ghostscript)~search~{pop~pop~pop~true}{pop~false}ifelse~
+ revision~915~lt~and~{
+ (\token_to_str:N\n
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\token_to_str:N\n
+ @@++++++++++++Warning:+Ghostscript+too+old!++++++++++++@@\token_to_str:N\n
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\token_to_str:N\n
+ @@+++++++++++++++++++++++++++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@+Ghostscript+version+>=+9.15.+required!++++++++++++++@@\token_to_str:N\n
+ @@+++++++++++++++++++++++++++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@+Various+advanced+PDF+features+such+as+Layers+(OCGs)+@@\token_to_str:N\n
+ @@+and+animations+may+not+work.++++++++++++++++++++++++@@\token_to_str:N\n
+ @@+++++++++++++++++++++++++++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@+Get+current+version+from++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@+http://www.ghostscript.com/download+++++++++++++++++@@\token_to_str:N\n
+ @@+++++++++++++++++++++++++++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\token_to_str:N\n)
+ print}~if}~?pdfmark
+}
+
+\cs_new_nopar:Nx\pbs_dpiwarning:{
+ {Resolution~1200~gt~VResolution~1200~gt~or~product~(Ghostscript)~
+ search~{pop~pop~pop~true}{pop~false}ifelse~and~{
+ (\token_to_str:N\n
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\token_to_str:N\n
+ @@+++++Warning:+DVI+resolution+greater+than+1200+dpi!+++++@@\token_to_str:N\n
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\token_to_str:N\n
+ @@++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@+PDF+Annotation+appearances+(buttons,+animation+frames)+@@\token_to_str:N\n
+ @@+may+be+poorly+scaled,+clipped+or+invisible.++++++++++++@@\token_to_str:N\n
+ @@++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@+Dvips+should+be+called+either+without+option+`-Ppdf':++@@\token_to_str:N\n
+ @@++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@+++dvips+\jobname\token_to_str:N\n
+ @@++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@+or+with+a+different+resolution+setting,+e.g.:++++++++++@@\token_to_str:N\n
+ @@++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@+++dvips+-Ppdf+-D1200+\jobname\token_to_str:N\n
+ @@++++++++++++++++++++++++++++++++++++++++++++++++++++++++@@\token_to_str:N\n
+ @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\token_to_str:N\n)
+ print}~if}~?pdfmark
+}
+\group_end: