From ff5439d00ba53d3e4b82d79f78ce65524f3684fd Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Sat, 15 May 2021 03:01:02 +0000 Subject: CTAN sync 202105150301 --- .../contrib/pdfmanagement-testphase/CHANGELOG.md | 18 + .../contrib/pdfmanagement-testphase/README.md | 2 +- .../contrib/pdfmanagement-testphase/color-ltx.sty | 2 +- .../pdfmanagement-testphase/hyperref-generic.dtx | 157 +- .../pdfmanagement-testphase/hyperref-generic.pdf | Bin 892975 -> 947436 bytes .../hyperxmp-patches-tmp-ltx.sty | 14 +- .../l3backend-testphase.dtx | 58 +- .../l3backend-testphase.pdf | Bin 567916 -> 588344 bytes .../contrib/pdfmanagement-testphase/l3pdfannot.dtx | 56 +- .../contrib/pdfmanagement-testphase/l3pdfannot.pdf | Bin 566379 -> 573518 bytes .../contrib/pdfmanagement-testphase/l3pdfdict.dtx | 4 +- .../contrib/pdfmanagement-testphase/l3pdfdict.pdf | Bin 523372 -> 526914 bytes .../l3pdffield-checkbox.dtx | 433 +++++ .../l3pdffield-checkbox.pdf | Bin 0 -> 438103 bytes .../l3pdffield-radiobutton.pdf | Bin 0 -> 296047 bytes .../l3pdffield-textfield.dtx | 508 ++++++ .../l3pdffield-textfield.pdf | Bin 0 -> 419934 bytes .../contrib/pdfmanagement-testphase/l3pdffield.dtx | 1921 +++++++++++++------- .../contrib/pdfmanagement-testphase/l3pdffield.pdf | Bin 555926 -> 619765 bytes .../contrib/pdfmanagement-testphase/l3pdffile.dtx | 18 +- .../contrib/pdfmanagement-testphase/l3pdffile.pdf | Bin 547260 -> 551626 bytes .../pdfmanagement-testphase/l3pdfmanagement.dtx | 82 +- .../pdfmanagement-testphase/l3pdfmanagement.pdf | Bin 649325 -> 658596 bytes .../contrib/pdfmanagement-testphase/l3pdfmeta.dtx | 4 +- .../contrib/pdfmanagement-testphase/l3pdfmeta.pdf | Bin 656637 -> 661637 bytes .../contrib/pdfmanagement-testphase/l3pdftools.dtx | 10 +- .../contrib/pdfmanagement-testphase/l3pdftools.pdf | Bin 515149 -> 517767 bytes .../contrib/pdfmanagement-testphase/l3pdfxform.dtx | 4 +- .../contrib/pdfmanagement-testphase/l3pdfxform.pdf | Bin 434789 -> 435558 bytes .../contrib/pdfmanagement-testphase/ltdocinit.dtx | 4 +- .../contrib/pdfmanagement-testphase/ltdocinit.pdf | Bin 550068 -> 552201 bytes .../pdfmanagement-testphase/pdflscape-ltx.sty | 2 +- .../pdfmanagement-firstaid.dtx | 26 +- .../pdfmanagement-firstaid.pdf | Bin 419958 -> 421911 bytes .../pdfmanagement-testphase.dtx | 6 +- .../pdfmanagement-testphase.ins | 2 + .../pdfmanagement-testphase.pdf | Bin 444675 -> 446163 bytes .../pdfmanagement-testphase/transparent-ltx.sty | 2 +- .../xcolor-patches-tmp-ltx.sty | 54 +- 39 files changed, 2567 insertions(+), 820 deletions(-) create mode 100644 macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx create mode 100644 macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf create mode 100644 macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf create mode 100644 macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx create mode 100644 macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf (limited to 'macros/latex/contrib/pdfmanagement-testphase') diff --git a/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md b/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md index 2f09d1fbf8..d114f50eed 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md +++ b/macros/latex/contrib/pdfmanagement-testphase/CHANGELOG.md @@ -5,6 +5,24 @@ first release 0.95a, 2021-02-23 will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), this project uses date-based 'snapshot' version identifiers. +## [2021-05-14 +### Fixed + - xcolor patch for [ps] type used in pstricks + - value of citecolor wasn't expanded (errored with tcolorbox) + - \url, \href, \hrefurl, \hrefrun and \hrefpdf leaves now vmode + - handling of pdfauthor, pdftitle and pdfsubject in hyperxmp patch + +### Changes + - the module for formfield and checkboxes has been in part rewritten to + better fit to the new module for textfield. + Keys and documentation has been extended. + +### Added + - generic command hooks have been added to \url, \href, \hrefurl, + \hrefrun and \hrefpdf. Their use require a latex 2021-06-01. + - dictionaries widget/AA, widget/AP, widget/MK and widget/BS in l3pdfannot. + - a module for textfields + ## [2021-03-17] ### Fixed diff --git a/macros/latex/contrib/pdfmanagement-testphase/README.md b/macros/latex/contrib/pdfmanagement-testphase/README.md index 40ae909e00..49840245c6 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/README.md +++ b/macros/latex/contrib/pdfmanagement-testphase/README.md @@ -1,6 +1,6 @@ # LaTeX PDF management testphase bundle -Version: 0.95c, 2021-03-17 +Version: 0.95d, 2021-05-14 This package is used during a test phase to load the new PDF management code of LaTeX. diff --git a/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty index 15754414a1..d8a6c9c408 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty +++ b/macros/latex/contrib/pdfmanagement-testphase/color-ltx.sty @@ -22,7 +22,7 @@ %% This file has the LPPL maintenance status "maintained". %% \NeedsTeXFormat{LaTeX2e}[1995/12/01] -\ProvidesPackage{color-ltx}[2021-03-17 v0.95c +\ProvidesPackage{color-ltx}[2021-05-14 v0.95d Standard LaTeX Color (patched for l3color, part of pdfmanagement-testphase, original version 2021/03/07 v1.2e) (DPC)] \edef\Gin@codes{% \catcode`\noexpand\^^A\the\catcode`\^^A\relax diff --git a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx index 8c60439dd3..30266d866c 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.dtx @@ -86,7 +86,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -325,7 +325,8 @@ % \subsection{Options} % All \cs{href} commands and \cs{url} have an option argument for keyval syntax. % It accepts the following keys. Not all keys make sense for all keys, but they don't -% error, they are silently ignored. +% error, they are silently ignored. The optional argument can currently not be used together +% with the \cs{urldef} command. % % \begin{tabular}{llp{6cm}} % key & applicable commands & note\\\hline @@ -634,7 +635,7 @@ % The key is ignored with this driver. Instead the wanted standard should be declared % in \cs{DeclareDocumentMetadata}: % \begin{verbatim} -% \DeclareDocumentMetadata{standard=A-2b} +% \DeclareDocumentMetadata{pdfstandard=A-2b} % \end{verbatim} % Currently |A-1b|, |A-2b|, |A-3b| can be set. % The support for various requirements is still incomplete, but the parts that @@ -921,7 +922,7 @@ %<@@=hyp> % \end{macrocode} % \begin{macrocode} -\ProvidesFile{hgeneric-testphase.def}[2021-03-17 v0.95c % +\ProvidesFile{hgeneric-testphase.def}[2021-05-14 v0.95d % generic Hyperref driver for the LaTeX PDF management testphase bundle] \RequirePackage{etoolbox} %why? @@ -1241,10 +1242,12 @@ ,href / format .code:n = { \cs_set_eq:NN \@@_href_url_format #1 } } - +\hook_new_pair:nn{cmd/href/before}{cmd/href/after} \DeclareRobustCommand*{\href}[1][]{% - \begingroup + \mode_leave_vertical: + \hook_use:n{cmd/href/before} + \group_begin: \keys_set:nn { hyp / href } {#1} \let\protect\@unexpandable@protect \bool_if:NTF \l_@@_href_url_encode_bool @@ -1257,12 +1260,27 @@ \@ifnextchar\bgroup\Hy@href{\hyper@normalise\href@}% } +\begingroup + \catcode`\$=6 % + \catcode`\#=12 % + \gdef\href@$1{\expandafter\href@split$1##\\}% + \gdef\href@split$1#$2#$3\\$4{% + \hyper@@@@link{$1}{$2}{$4}%<---@@-docstrip doubling! + \endgroup + \hook_use:n{cmd/href/after} + }% +\endgroup -\DeclareRobustCommand*{\hrefurl}[1][]{ - \group_begin: - \keys_set:nn { hyp / href } {#1} - \let\protect\@unexpandable@protect - \bool_if:NTF \l_@@_href_url_encode_bool +\hook_new_pair:nn{cmd/hrefurl/before}{cmd/hrefurl/after} + +\DeclareRobustCommand*{\hrefurl}[1][] + { + \mode_leave_vertical: + \hook_use:n{cmd/href/before} + \group_begin: + \keys_set:nn { hyp / href } {#1} + \let\protect\@unexpandable@protect + \bool_if:NTF \l_@@_href_url_encode_bool { \tl_set:Nn \l__hyp_text_enc_uri_print_tl {utf8/URI} } @@ -1275,12 +1293,15 @@ { \exp_args:Nno\hyper@linkurl{#2}{\l_@@_href_url_protocol_tl#1} \group_end: + \hook_use:n{cmd/href/after} } - +\hook_new_pair:nn{cmd/hrefpdf/before}{cmd/hrefpdf/after} \DeclareRobustCommand*{\hrefpdf}[1][] { - \begingroup + \mode_leave_vertical: + \hook_use:n{cmd/hrefpdf/before} + \group_begin: \keys_set:nn { hyp / href } {#1} \let\protect\@unexpandable@protect \hyper@normalise\@@_href_pdf_aux:nn @@ -1288,11 +1309,16 @@ \cs_new_protected:Npn \@@_href_pdf_aux:nn #1 #2 { - \exp_args:Nnno\hyper@linkfile{#2}{#1}{\l_@@_href_pdf_destination_tl}\endgroup + \exp_args:Nnno\hyper@linkfile{#2}{#1}{\l_@@_href_pdf_destination_tl} + \group_end: + \hook_use:n{cmd/hrefpdf/after} } +\hook_new_pair:nn{cmd/hrefrun/before}{cmd/hrefrun/after} \DeclareRobustCommand*{\hrefrun}[1][] { + \mode_leave_vertical: + \hook_use:n{cmd/hrefrun/before} \group_begin: \keys_set:nn { hyp / href } {#1} \let\protect\@unexpandable@protect @@ -1303,10 +1329,16 @@ { \exp_args:Nnno\hyper@linklaunch{#2}{#1}{\l_@@_href_run_parameter_tl} \group_end: + \hook_use:n{cmd/hrefrun/after} } + +\hook_new_pair:nn{cmd/url/before}{cmd/url/after} + \DeclareRobustCommand*{\url}[1][] { + \mode_leave_vertical: + \hook_use:n{cmd/url/before} \group_begin: \keys_set:nn {hyp / href } {#1} \let\protect \@unexpandable@protect @@ -1326,9 +1358,23 @@ \hyper@linkurl{\@@_href_url_format {#1}} {\l_@@_href_url_protocol_tl#1} \group_end: + \hook_use:n{cmd/url/after} } +% \end{macrocode} +% the \cs{urldef} command doesn't like the optional argument, so we overwrite +% locally the \cs{url} command here: +% \begin{macrocode} + +\def\urldef#1#2{\begingroup\def\url{\hyper@normalise\url@}\setbox\z@\hbox\bgroup + \def\Url@HyperHook##1\endgroup{\Url@def{#1}{#2}}% + % Because hyperref breaks \urldef and does not define its own (Grrrr!)... + \def\url@##1{\egroup\endgroup\DeclareRobustCommand#1{#2{##1}}}% + #2} +% \end{macrocode} +% make the new commands compatible with \cs{pdfstringdef}: +% \begin{macrocode} \NewExpandableDocumentCommand\@@_secondoftwowithopt:wnn {omm}{#3} \pdfstringdefDisableCommands{\let\hrefurl\@@_secondoftwowithopt:wnn} \pdfstringdefDisableCommands{\let\hrefpdf\@@_secondoftwowithopt:wnn} @@ -1356,9 +1402,9 @@ \color_set:nn {hyp/color/citeborder}{hyp/color/cite!60!white} \keys_define:nn { hyp / setup } { - ,citecolor .code:n = {\@@_color_set:nn {hyp/color/cite}{#1}} + ,citecolor .code:n = {\@@_color_set:ne {hyp/color/cite}{#1}} ,citebordercolor - .code:n = {\@@_color_set:nn {hyp/color/citeborder}{#1}} + .code:n = {\@@_color_set:ne {hyp/color/citeborder}{#1}} } \hook_gput_code:nnn { hyp/link/cite }{hyp/cite} { @@ -2277,17 +2323,16 @@ % \section{Link decorations} % \subsection{Functions to export and select colors} % We support two input syntax: color expressions and model with values. -% \begin{function}{\@@_color_export:nnN,\@@_colormodel_export:nnnN} +% \begin{function}{\@@_color_export:nnN} % \begin{syntax} -% \cs{@@_color_export:nnN} \Arg{color} \Arg{export format} \meta{tlvar}\\ -% \cs{@@_colormodel_export:nnnN} \Arg{color model}\Arg{value} \Arg{export format} \meta{tlvar} +% \cs{@@_color_export:nnN} \Arg{color} \Arg{export format} \meta{tlvar} % \end{syntax} % This exports a color as space separated numbers as needed in in |/C|. % \Arg{color} should have either the format |[model]{value}| or be a color expression. % For examples: |[rgb]{1,0,.5}| or |red!50!blue|. The export format is either % |space-sep-cmyk| or |space-sep-rgb|. % \end{function} -% \begin{macro}{\@@_color_export:nnN,\@@_colormodel_export:nnnN} +% \begin{macro}{\@@_color_export:nnN,\@@_color_export_aux:wnnN} % Color keys need to parse color expressions. Two input types are supported: % |color=[rgb]{1,0,.5}| and |color=red!50!blue|. The colors are exported % to PDF syntax (space separated numbers). @@ -2296,14 +2341,14 @@ { \tl_if_head_eq_charcode:nNTF {#1}[ %] { - \@@_colormodel_export:wnnN #1 {#2} #3 + \@@_color_export_aux:wnnN #1 {#2} #3 } { \color_export:nnN {#1} {#2} #3 } } -\cs_new_protected:Npn \@@_colormodel_export:wnnN [#1] #2 #3 #4 +\cs_new_protected:Npn \@@_color_export_aux:wnnN [#1] #2 #3 #4 { \color_export:nnnN {#1}{#2}{#3}#4 } @@ -2320,7 +2365,7 @@ % \Arg{color} should have either the format |[model]{value}| or be a color expression. % For examples: |[rgb]{1,0,.5}| or |red!50!blue| % \end{function} -% \begin{macro}{\@@_color_select:n,\@@_colormodel_select_aux:wn} +% \begin{macro}{\@@_color_select:n,\@@_color_select_aux:wn} % Color keys need to parse color expressions. Two input types are supported: % |color=[rgb]{1,0,.5}| and |color=red!50!blue|. % \begin{macrocode} @@ -2328,14 +2373,14 @@ { \tl_if_head_eq_charcode:nNTF {#1}[ %] { - \@@_colormodel_select_aux:wn #1 + \@@_color_select_aux:wn #1 } { \color_select:n {#1} } } -\cs_new_protected:Npn \@@_colormodel_select_aux:wn [#1] #2 +\cs_new_protected:Npn \@@_color_select_aux:wn [#1] #2 { \color_select:nn {#1}{#2} } @@ -2352,7 +2397,7 @@ % \Arg{color} should have either the format |[model]{value}| or be a color expression. % For examples: |[rgb]{1,0,.5}| or |red!50!blue| % \end{function} -% \begin{macro}{\@@_color_set:nn,\@@_colormodel_set_aux:nwn} +% \begin{macro}{\@@_color_set:nn,\@@_color_set_aux:nwn} % Color keys need to parse color expressions. Two input types are supported: % |color=[rgb]{1,0,.5}| and |color=red!50!blue|. % \begin{macrocode} @@ -2360,14 +2405,14 @@ { \tl_if_head_eq_charcode:nNTF {#2}[ %] { - \@@_colormodel_set_aux:nwn { #1 } #2 + \@@_color_set_aux:nwn { #1 } #2 } { \color_set:nn {#1} {#2} } } -\cs_new_protected:Npn \@@_colormodel_set_aux:nwn #1 [#2] #3 +\cs_new_protected:Npn \@@_color_set_aux:nwn #1 [#2] #3 { \color_set:nnn {#1}{#2}{#3} } @@ -2621,17 +2666,17 @@ % \begin{macrocode} \cs_new_protected:Npn \@@_ocg_init: { - \pdf_object_new:nn { l_@@_ocg_view_dict_obj } { dict } - \pdf_object_new:nn { l_@@_ocg_print_dict_obj } { dict } - \pdf_object_new:nn { l_@@_ocg_config_dict_obj } { dict } - \pdf_object_new:nn { l_@@_ocg_ref_array_obj } { array } - \pdf_object_write:nx { l_@@_ocg_ref_array_obj } + \pdf_object_new:nn { @@/OCG/View } { dict } + \pdf_object_new:nn { @@/OCG/Print } { dict } + \pdf_object_new:nn { @@/OCG/config } { dict } + \pdf_object_new:nn { @@/OCG/refarray } { array } + \pdf_object_write:nx { @@/OCG/refarray } { - \pdf_object_ref:n { l_@@_ocg_view_dict_obj } + \pdf_object_ref:n { @@/OCG/View } \c_space_tl - \pdf_object_ref:n { l_@@_ocg_print_dict_obj } + \pdf_object_ref:n { @@/OCG/Print } } - \pdf_object_write:nn { l_@@_ocg_view_dict_obj } + \pdf_object_write:nn { @@/OCG/View } { /Type/OCG /Name(View) @@ -2641,7 +2686,7 @@ /View <>~ >> } - \pdf_object_write:nn { l_@@_ocg_print_dict_obj } + \pdf_object_write:nn { @@/OCG/Print } { /Type/OCG /Name(Print) @@ -2651,30 +2696,30 @@ /View <>~ >> } - \pdfmanagement_add:nnx { Catalog / OCProperties }{OCGs }{ \pdf_object_ref:n {l_@@_ocg_view_dict_obj} } - \pdfmanagement_add:nnx { Catalog / OCProperties }{OCGs }{ \pdf_object_ref:n {l_@@_ocg_print_dict_obj} } - \pdf_object_write:nx { l_@@_ocg_config_dict_obj } + \pdfmanagement_add:nnx { Catalog / OCProperties }{OCGs }{ \pdf_object_ref:n {@@/OCG/View} } + \pdfmanagement_add:nnx { Catalog / OCProperties }{OCGs }{ \pdf_object_ref:n {@@/OCG/Print} } + \pdf_object_write:nx { @@/OCG/config } { - /OFF[\pdf_object_ref:n { l_@@_ocg_print_dict_obj }] + /OFF[\pdf_object_ref:n { @@/OCG/Print }] /AS[ << /Event/View - /OCGs\c_space_tl \pdf_object_ref:n { l_@@_ocg_ref_array_obj } + /OCGs\c_space_tl \pdf_object_ref:n { @@/OCG/refarray } /Category[/View] >> << /Event/Print - /OCGs\c_space_tl \pdf_object_ref:n { l_@@_ocg_ref_array_obj } + /OCGs\c_space_tl \pdf_object_ref:n { @@/OCG/refarray } /Category[/Print] >> << /Event/Export - /OCGs\c_space_tl \pdf_object_ref:n { l_@@_ocg_ref_array_obj } + /OCGs\c_space_tl \pdf_object_ref:n { @@/OCG/refarray } /Category[/Print] >> ] } - \pdfmanagement_add:nnx { Catalog / OCProperties }{ D }{ \pdf_object_ref:n { l_@@_ocg_config_dict_obj} } + \pdfmanagement_add:nnx { Catalog / OCProperties }{ D }{ \pdf_object_ref:n { @@/OCG/config} } \cs_gset:Npn \@@_ocg_init: {} } % \end{macrocode} @@ -2704,10 +2749,10 @@ \hbox_set_end: \mbox { - \pdf_bdcobject:nn {OC}{l_@@_ocg_print_dict_obj} + \pdf_bdcobject:nn {OC}{@@/OCG/Print} \hbox_overlap_right:n { \box_use:N \l_@@_tmpa_box } \pdf_emc: - \pdf_bdcobject:nn {OC}{l_@@_ocg_view_dict_obj} + \pdf_bdcobject:nn {OC}{@@/OCG/View} \group_begin: \color_select:n { hyp/color/#1 } \box_use_drop:N \l_@@_tmpa_box @@ -4187,9 +4232,9 @@ } } \pdfmanagement_add:nnx {Catalog / AcroForm/DR/Font } - {ZaDb} {\pdf_object_ref:n {l_@@_font_zapfdingbats_obj} } + {ZaDb} {\pdf_object_ref:n {@@/Font/ZaDb} } \pdfmanagement_add:nnx {Catalog / AcroForm/DR/Font } - {Helv} {\pdf_object_ref:n {l_@@_font_helvetica_obj} } + {Helv} {\pdf_object_ref:n {@@/Font/Helv} } \pdfmanagement_add:nnx {Catalog /AcroForm} {DA}{(/Helv~10~Tf~0~g)} \pdfmeta_standard_verify:nTF {form_no_NeedAppearance} @@ -4601,10 +4646,10 @@ \ExplSyntaxOn \def\Hy@FormObjects { - \pdf_object_new:nn {l_@@_encoding_pdfdoc_obj } { dict } - \pdf_object_new:nn {l_@@_font_zapfdingbats_obj } { dict } - \pdf_object_new:nn {l_@@_font_helvetica_obj } { dict } - \pdf_object_write:nx {l_@@_encoding_pdfdoc_obj } + \pdf_object_new:nn {@@/Encoding/pdfdoc } { dict } + \pdf_object_new:nn {@@/Font/ZaDb } { dict } + \pdf_object_new:nn {@@/Font/Helv } { dict } + \pdf_object_write:nx {@@/Encoding/pdfdoc } { /Type/Encoding /Differences[ @@ -4646,20 +4691,20 @@ /uacute/ucircumflex/udieresis/yacute/thorn/ydieresis ] } - \pdf_object_write:nn {l_@@_font_zapfdingbats_obj } + \pdf_object_write:nn {@@/Font/ZaDb } { /Type/Font /Subtype/Type1 /Name/ZaDb /BaseFont/ZapfDingbats } - \pdf_object_write:nx {l_@@_font_helvetica_obj } + \pdf_object_write:nx {@@/Font/Helv } { /Type/Font /Subtype/Type1 /Name/Helv /BaseFont/Helvetica - /Encoding~\pdf_object_ref:n { l_@@_encoding_pdfdoc_obj } + /Encoding~\pdf_object_ref:n { @@/Encoding/pdfdoc } } \global\let\Hy@FormObjects\relax } diff --git a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf index ddb0c9b2b9..fb13e4b8e6 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf and b/macros/latex/contrib/pdfmanagement-testphase/hyperref-generic.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty index b38a47f09c..ab8723947e 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty +++ b/macros/latex/contrib/pdfmanagement-testphase/hyperxmp-patches-tmp-ltx.sty @@ -19,7 +19,7 @@ % % for those people who are interested. \NeedsTeXFormat{LaTeX2e}[2020/10/01] -\ProvidesExplPackage{hyperxmp-patches-tmp-ltx}{2021-03-17}{0.95c} +\ProvidesExplPackage{hyperxmp-patches-tmp-ltx}{2021-05-14}{0.95d} {Store hyperref metadata in XMP format / temporay patches to test pdfresource management ... UF} \cs_if_exist:NT \pdfmanagement_add:nnn @@ -103,8 +103,8 @@ ,pdfcontacturl ,pdfdate %hyperref, needs probably special handling - ,pdftitle - ,pdfsubject + % ,pdftitle %see below + % ,pdfsubject %see below ,pdfkeywords ,pdfproducer } @@ -115,9 +115,15 @@ % pdfauthor, this is only a work around for simple author % TODO needs improvement + \exp_args:NNe \pdfstringdef\@pdfauthor{\GetDocumentProperties{hyperref/pdfauthor}} \cs_set_eq:NN\hyxmp@pdfauthor\@pdfauthor - + \exp_args:NNe + \pdfstringdef\@pdfsubject{\GetDocumentProperties{hyperref/pdfsubject}} + \cs_set_eq:NN\hyxmp@pdfsubject\@pdfsubject + \exp_args:NNe + \pdfstringdef\@pdftitle{\GetDocumentProperties{hyperref/pdftitle}} + \cs_set_eq:NN\hyxmp@pdftitle\@pdftitle % pdflang, \tl_if_exist:cF{@pdflang}{\tl_new:c{@pdflang}} \tl_set:cx {@pdflang}{\GetDocumentProperties{document/lang}} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx index 1b1e1b1b91..497491f3b7 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.dtx @@ -45,7 +45,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % @@ -56,27 +56,27 @@ % \begin{macrocode} %\ProvidesExplFile %<*dvipdfmx> - {l3backend-testphase-dvipdfmx.def}{2021-03-17}{} + {l3backend-testphase-dvipdfmx.def}{2021-05-14}{} {LaTeX~PDF~management~testphase~bundle~backend~support: dvipdfmx} % %<*dvips> - {l3backend-testphase-dvips.def}{2021-03-17}{} + {l3backend-testphase-dvips.def}{2021-05-14}{} {LaTeX~PDF~management~testphase~bundle~backend~support: dvips} % %<*dvisvgm> - {l3backend-testphase-dvisvgm.def}{2021-03-17}{} + {l3backend-testphase-dvisvgm.def}{2021-05-14}{} {LaTeX~PDF~management~testphase~bundle~backend~support: dvisvgm} % %<*luatex> - {l3backend-testphase-luatex.def}{2021-03-17}{} + {l3backend-testphase-luatex.def}{2021-05-14}{} {LaTeX~PDF~management~testphase~bundle~backend~support: PDF output (LuaTeX)} % %<*pdftex> - {l3backend-testphase-pdftex.def}{2021-03-17}{} + {l3backend-testphase-pdftex.def}{2021-05-14}{} {LaTeX~PDF~management~testphase~bundle~backend~support: PDF output (pdfTeX)} % %<*xdvipdfmx> - {l3backend-testphase-xetex.def}{2021-03-17}{} + {l3backend-testphase-xetex.def}{2021-05-14}{} {LaTeX~PDF~management~testphase~bundle~backend~support: XeTeX} % % \end{macrocode} @@ -590,14 +590,14 @@ %create the backend objects: \clist_map_inline:Nn \c_@@_backend_PageResources_clist { - \@@_backend_object_new:nn {Page/Resources/#1} {dict} + \@@_backend_object_new:nn {@@/Page/Resources/#1} {dict} \cs_if_exist:NT \tex_directlua:D { \tex_directlua:D { - ltx.@@.object["Page/Resources/#1"] + ltx.@@.object["@@/Page/Resources/#1"] = - "\@@_backend_object_ref:n{Page/Resources/#1}" + "\@@_backend_object_ref:n{@@/Page/Resources/#1}" } } } @@ -631,7 +631,7 @@ { \__kernel_pdfdict_name:n { g_@@_Core/Page/Resources/##1} } { \@@_backend_object_write:nx - { Page/Resources/##1 } + { @@/Page/Resources/##1 } { \pdfdict_use:n { g_@@_Core/Page/Resources/##1} } } } @@ -651,8 +651,8 @@ % \clist_map_inline:Nn \c_@@_backend_PageResources_clist { - \@@_backend_object_new:nn { Page/Resources/#1 } { dict } - \hook_gput_code:nnn{shipout/firstpage}{pdf}{\@@_backend_object_write:nn { Page/Resources/#1 } {}} + \@@_backend_object_new:nn { @@/Page/Resources/#1 } { dict } + \hook_gput_code:nnn{shipout/firstpage}{pdf}{\@@_backend_object_write:nn { @@/Page/Resources/#1 } {}} } \cs_new_protected:Npn \@@_backend_PageResources:n #1 { @@ -667,7 +667,7 @@ %objects are not filled with \pdf_object_write as this is not additive! \@@_backend:x { - put~\@@_backend_object_ref:n {Page/Resources/#1}<> + put~\@@_backend_object_ref:n {@@/Page/Resources/#1}<> } } @@ -847,7 +847,7 @@ \__kernel_backend_literal:x { pdf:put~@resources~ - <> + <> } } } @@ -1042,7 +1042,7 @@ \prop_if_empty:cF { \__kernel_pdfdict_name:n { g_@@_Core/Page/Resources/#1} } { - \pdfdict_item:ne { #1 }{ \pdf_object_ref:n {Page/Resources/#1}} + \pdfdict_item:ne { #1 }{ \pdf_object_ref:n {@@/Page/Resources/#1}} } } @@ -1243,22 +1243,22 @@ \prop_if_empty:cF { \__kernel_pdfdict_name:n { g_@@_Core/Page/Resources/ExtGState } } { - /ExtGState~ \pdf_object_ref:n { Page/Resources/ExtGState } + /ExtGState~ \pdf_object_ref:n { @@/Page/Resources/ExtGState } } \prop_if_empty:cF { \__kernel_pdfdict_name:n { g_@@_Core/Page/Resources/Pattern } } { - /Pattern~ \pdf_object_ref:n { Page/Resources/Pattern } + /Pattern~ \pdf_object_ref:n { @@/Page/Resources/Pattern } } \prop_if_empty:cF { \__kernel_pdfdict_name:n { g_@@_Core/Page/Resources/Shading } } { - /Shading~ \pdf_object_ref:n { Page/Resources/Shading } + /Shading~ \pdf_object_ref:n { @@/Page/Resources/Shading } } \prop_if_empty:cF { \__kernel_pdfdict_name:n { g_@@_Core/Page/Resources/ColorSpace } } { - /ColorSpace~ \pdf_object_ref:n { Page/Resources/ColorSpace } + /ColorSpace~ \pdf_object_ref:n { @@/Page/Resources/ColorSpace } } } \l_@@_backend_tmpa_box @@ -1323,22 +1323,22 @@ \prop_if_empty:cF { \__kernel_pdfdict_name:n { g_@@_Core/Page/Resources/ExtGState } } { - /ExtGState~ \pdf_object_ref:n { Page/Resources/ExtGState } + /ExtGState~ \pdf_object_ref:n { @@/Page/Resources/ExtGState } } \prop_if_empty:cF { \__kernel_pdfdict_name:n { g_@@_Core/Page/Resources/Pattern } } { - /Pattern~ \pdf_object_ref:n { Page/Resources/Pattern } + /Pattern~ \pdf_object_ref:n { @@/Page/Resources/Pattern } } \prop_if_empty:cF { \__kernel_pdfdict_name:n { g_@@_Core/Page/Resources/Shading } } { - /Shading~ \pdf_object_ref:n { Page/Resources/Shading } + /Shading~ \pdf_object_ref:n { @@/Page/Resources/Shading } } \prop_if_empty:cF { \__kernel_pdfdict_name:n { g_@@_Core/Page/Resources/ColorSpace } } { - /ColorSpace~ \pdf_object_ref:n { Page/Resources/ColorSpace } + /ColorSpace~ \pdf_object_ref:n { @@/Page/Resources/ColorSpace } } } \l_@@_backend_tmpa_box @@ -1414,21 +1414,21 @@ { put~ @resources ~ << - /ExtGState~ \pdf_object_ref:n { Page/Resources/ExtGState } + /ExtGState~ \pdf_object_ref:n { @@/Page/Resources/ExtGState } >> } \@@_backend:x { put~ @resources ~ << - /Pattern~ \pdf_object_ref:n { Page/Resources/Pattern } + /Pattern~ \pdf_object_ref:n { @@/Page/Resources/Pattern } >> } \@@_backend:x { put~ @resources ~ << - /Shading~ \pdf_object_ref:n { Page/Resources/Shading } + /Shading~ \pdf_object_ref:n { @@/Page/Resources/Shading } >> } \@@_backend:x @@ -1436,7 +1436,7 @@ put~ @resources ~ << /ColorSpace~ - \pdf_object_ref:n { Page/Resources/ColorSpace } + \pdf_object_ref:n { @@/Page/Resources/ColorSpace } >> } \exp_args:Nx @@ -1582,7 +1582,7 @@ local function @@_backend_PageResources_gpush (page) end for i,name in ipairs(ResourceList) do if ltx.@@.Page.Resources[name] then - token = token .. "/"..name.." "..ltx.pdf.object_ref("Page/Resources/"..name) + token = token .. "/"..name.." "..ltx.pdf.object_ref("@@/Page/Resources/"..name) end end return token diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf index 6e5e8afd77..6e8a0d0155 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf and b/macros/latex/contrib/pdfmanagement-testphase/l3backend-testphase.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx index 256e3e6dc9..c8eddc0806 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.dtx @@ -52,7 +52,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -354,9 +354,9 @@ % /F flag in an annotation. % It can be used for example like this: % \begin{verbatim} -% \pdfannot_dict_put:nnn {link/URI} {F} -% { \bitset_to_arabic:N \l_pdfannot_F_bitset } % \bitset_set_true:Nn \l_pdfannot_F_bitset {Print} +% \pdfannot_dict_put:nnx {link/URI} {F} +% { \bitset_to_arabic:N \l_pdfannot_F_bitset } % \end{verbatim} % The known keys for the bitset are |Invisible|, |Hidden|, % |Print|, |NoZoom|, |NoRotate|, |NoView|, |ReadOnly|, |Locked|, |ToggleNoView|, @@ -382,6 +382,11 @@ % is prefilled with \texttt{/Subtype/Widget}). % The hooks \texttt{pdfannot/widget/before} and \texttt{pdfannot/widget/after} % are executed before and after the widget. +% The widget has four subdirectories, |widget/AA|, |widget/AP|, |widget/MK| and +% |widget/BS| +% which can be filled with \cs{pdfannot_dict_put:nnn} and will be used if not +% empty. +% % \end{function} % \end{documentation} % @@ -392,7 +397,7 @@ % \begin{macrocode} %<@@=pdfannot> %<*header> -\ProvidesExplPackage{l3pdfannot}{2021-03-17}{0.95c} +\ProvidesExplPackage{l3pdfannot}{2021-05-14}{0.95d} {PDF-annotations} \RequirePackage{l3pdfdict} % @@ -463,21 +468,56 @@ % the subtype setting (the /Type is added by the backend). % \begin{macrocode} \pdfdict_new:n { l_@@/widget } + \pdfdict_new:n { l_@@/widget/AA } + \pdfdict_new:n { l_@@/widget/AP } + \pdfdict_new:n { l_@@/widget/MK } + \pdfdict_new:n { l_@@/widget/BS } \pdfdict_put:nnn { l_@@/widget }{ Subtype }{ /Widget } \hook_new_pair:nn {pdfannot/widget/before} {pdfannot/widget/after} - \hook_new_pair:nn - {pdfannot/widget/begin} - {pdfannot/widget/end} \cs_new_protected:Npn \pdfannot_widget_box:nnn #1 #2 #3 { \hook_use:n { pdfannot/widget/before } + \group_begin: + \pdfmeta_standard_verify:nT + {annot_widget_no_AA} + { + \pdfdict_if_empty:nF { l_@@/widget/AA } + { + \pdf_object_unnamed_write:nx {dict}{\pdfdict_use:n{l_@@/widget/AA}} + \pdfdict_put:nnx { l_@@/widget } + {AA} + {\pdf_object_ref_last:} + } + } + \pdfdict_if_empty:nF { l_@@/widget/AP } + { + \pdf_object_unnamed_write:nx {dict}{\pdfdict_use:n{l_@@/widget/AP}} + \pdfdict_put:nnx { l_@@/widget } + {AP} + {\pdf_object_ref_last:} + } + \pdfdict_if_empty:nF { l_@@/widget/MK } + { + \pdf_object_unnamed_write:nx {dict}{\pdfdict_use:n{l_@@/widget/MK}} + \pdfdict_put:nnx { l_@@/widget } + {MK} + {\pdf_object_ref_last:} + } + \pdfdict_if_empty:nF { l_@@/widget/BS } + { + \pdf_object_unnamed_write:nx {dict}{\pdfdict_use:n{l_@@/widget/BS}} + \pdfdict_put:nnx { l_@@/widget } + {BS} + {\pdf_object_ref_last:} + } \pdfannot_box:nnnx {#1}{#2}{#3} { \pdfdict_use:n { l_@@/widget} } - \hook_use:n { pdfannot/widget/after } + \hook_use:n { pdfannot/widget/end } + \group_end: \bool_gset_false:N\g_@@_use_lastlink_bool } % \end{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf index 3e647106b5..8025552014 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf and b/macros/latex/contrib/pdfmanagement-testphase/l3pdfannot.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx index 25a3599445..b23ff4508f 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.dtx @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -212,7 +212,7 @@ % \begin{macrocode} %<@@=pdfdict> %<*header> -\ProvidesExplPackage{l3pdfdict}{2021-03-17}{0.95c} +\ProvidesExplPackage{l3pdfdict}{2021-05-14}{0.95d} {Tools for PDF dictionaries (LaTeX PDF management testphase bundle)} % % \end{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf index 970086e088..bb3eb95d68 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf and b/macros/latex/contrib/pdfmanagement-testphase/l3pdfdict.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx new file mode 100644 index 0000000000..681a8d7059 --- /dev/null +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.dtx @@ -0,0 +1,433 @@ +% \iffalse meta-comment +% +%% File: l3pdfpdffield-checkbox.dtx +% +% Copyright (C) 2021 The LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% http://www.latex-project.org/lppl.txt +% +% This file is part of the "LaTeX PDF management testphase bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/latex3/pdfresources +% +% for those people who are interested. +% +%<*driver> +\RequirePackage{pdfmanagement-testphase} +\DeclareDocumentMetadata{} +\makeatletter +\declare@file@substitution{doc.sty}{doc-v3beta.sty} +\makeatother +\documentclass[full]{l3doc} +\usepackage{array,booktabs} +\usepackage{l3pdffield-testphase,bearwear} +\hypersetup{pdfauthor=The LaTeX Project, + pdftitle=l3pdffield (LaTeX PDF management testphase bundle)} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% \fi +% \NewDocElement[ +% idxgroup=checkbox keys, +% idxtype = {checkbox key}, +% printtype= \textit{checkbox key} +% ]{Checkboxkey}{checkboxkey} +% \providecommand\hook[1]{\texttt{#1}} +% \ExplSyntaxOn +% \pdffield_appearance:nn {pdffield/bear/Yes} +% { +% \tikz\bear\bearwear[shirt=red,body~deco={\node[font=\tiny\bfseries,white]~at~(beartummy){Yes};}]; +% } +% \pdffield_appearance:nn {pdffield/bear/Off} +% { +% \tikz\bear\bearwear[body~deco={\node[font=\tiny\bfseries,white]~at~(beartummy){Off};}]; +% } +% \ExplSyntaxOff +% \title{^^A +% The \pkg{l3pdffield-checkbox} module\\ Commands to create checkbox form fields ^^A +% \\ \LaTeX{} PDF management testphase bundle +% } +% +% \author{^^A +% The \LaTeX{} Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Version 0.95d, released 2021-05-14} +% +% \maketitle +% \begin{documentation} +% \section{\pkg{l3pdffield-checkbox} Introduction} +% This is the documentation for checkbox fields, for general information about form fields +% check the documentation l3pdffield. +% +% +% +% Please keep in mind +% \begin{itemize} +% \item Not every PDF viewer supports checkboxes. +% \item The handling can depend on settings in the PDF viewer. In adobe reader for +% example I had to disable an option to avoid that it tries to create an appearance +% itself +% \item Standards like pdf/A disable features of form fields too +% (as you typically can't change the PDF). +% \end{itemize} +% \section{Checkboxes} +% Click me: +% \ExplSyntaxOn +% \pdffield_checkbox:n{name=bear,appearance=pdffield/bear,width=23pt,height=30pt,depth=10pt} +% \ExplSyntaxOff +% +% \bigskip +% \subsection{Commands} +% \begin{function}{\pdffield_checkbox:n} +% \begin{syntax} +% \cs{pdffield_checkbox:n}\Arg{key val list} +% \end{syntax} +% This creates a checkbox to check and uncheck. The list of allowed keys is described below. +% The \meta{key val list} should at least set the name, without it the default name +% |checkbox| is used. Checkboxes with the same +% name belong to the same field and are checked and unchecked together. The default appearance +% is a quadratic frame with a \cs{texttimes} in it for the checked case. +% The default appearance is setup at the first use and will use the font family +% active at that time. +% \end{function} +% +% +% \subsection{Keys} +% +% The new checkbox command accept all field and annot keys from l3pdffield. +% A few keys are disabled or are forced to specific values. +% The |appearance| keys have a more checkbox specific +% behaviour, other keys have other defaults than with the basic commands. +% Additionally there +% are a small number of keys specific to a checkbox. +% +% +% Disabled keys are +% \begin{itemize} +% \item |V|, |DV|, |AS|: use |checked| instead. +% \item |FT| is overwritten. +% \item For checkboxes only the field flags |ReadOnly|, |Required| and |NoExport| make sense. +% |Radio|, |Pushbotton| are set automatically automatically by the code +% as this is required for a checkbox. +% \end{itemize} +% +% \begin{function}{preset-checkbox} +% \begin{syntax} +% |preset-checkbox| = \Arg{key-val-list} +% \end{syntax} +% This allows to set default keys for a checkbox. +% \end{function} +% +% \begin{function}{name,T} +% \begin{syntax} +% |name| = \meta{partial name}\\ +% |T| = \meta{partial name} +% \end{syntax} +% This sets like the |T| key for fields the partial name of the field. The value +% shouldn't contain a period, be not empty and sensibly consist of simple chars. +% Additionally the value is used to create the field ID. +% This means that checkboxes with the same partial name are annotations +% with the same field as parent and are checked and unchecked together---this +% what is typically expected. +% The field ID is then internal and can not be used to +% attach another annotation. +% For explicit control of the field ID use the |fieldID| key. +% \end{function} +% +% \begin{function}{fieldID} +% \begin{syntax} +% |fieldID| = \meta{field ID}\\ +% \end{syntax} +% \emph{For experts only!} +% This allows to give the checkbox field a specific ID. This is only useful +% in the context of a larger fieldset or if you want to attach another annotation +% to the field with \cs{pdffield_annot:n}. If used wrongly you can +% easily create invalid fieldset. It allows you to create to fields with the +% same partial name, but if you want to see both +% you need to ensure that their full names are +% different---for example by adding some parent fields. +% \end{function} +% +% \begin{function}{parent} +% \begin{syntax} +% |parent| = \meta{field ID}\\ +% \end{syntax} +% This is only needed if the field should be part +% of a larger fieldset. The value should be a field ID of a field created previously +% with \cs{pdffield_field:nn}. +% \end{function} +% +% \begin{function}{altname,TU} +% \begin{syntax} +% |altname| = \meta{string}\\ +% |TU| = \meta{string}\\ +% \end{syntax} +% This is sets an alternative name for user interaction. +% This name can only be set at the first checkbox instance, when the field is initialized. +% \end{function} +% +% \begin{function}{mappingname,TM} +% \begin{syntax} +% |mappingname| = \meta{string}\\ +% |TM| = \meta{string}\\ +% \end{syntax} +% This is sets an alternative name for export. +% This name can only be set at the first checkbox instance, when the field is initialized. +% \end{function} +% +% \begin{function}{width,height,depth} +% \begin{syntax} +% |width| = \meta{dim expression}\\ +% |height| = \meta{dim expression}\\ +% |depth| = \meta{dim expression} +% \end{syntax} +% These keys allow to set the dimensions of checkbox instance. +% The value should be a dimension expression. By default +% |width| and |height| use \cs{normalbaselineskip}, the |depth| is zero. +% \end{function} +% +% \begin{function}{AP/N,appearance,AP/R,rollover-appearance,AP/D,down-appearance} +% \begin{syntax} +% |AP/N| = \meta{partial appearance name}\\ +% |appearance| = \meta{partial appearance name}\\ +% |AP/R| = \meta{partial appearance name}\\ +% |rollover-appearance| = \meta{partial appearance name}\\ +% |AP/D| = \meta{partial appearance name}\\ +% |down-appearance| = \meta{partial appearance name} +% \end{syntax} +% This keys sets the normal appearance, the rollover appearance (when the +% mouse hovers over the checkbox) and the down appearance (when the +% mouse clicks). They take as value a +% \meta{partial appearance name} and expects that \emph{two} form Xobjects +% \meta{partial appearance name}|/Yes| and \meta{partial appearance name}|/Off| +% has been created. The initial value is |pdffield/checkbox/default| +% for the normal appearance and shows a \cs{texttimes}. +% The other appearance are not set by default. +% \end{function} +% \begin{function}{checked} +% \begin{syntax} +% |checked| = |true|\verb"|"|false| +% \end{syntax} +% This is a boolean key which allows to set if the +% checkbox should be initially checked or not. It sets the |/V| and |/DV| key of the field +% and the |/AS| key of the annotation instance. It is possible to use different +% values for different instances, if one wants to confuse the user. +% \end{function} +% +% +% \subsection{Using with hyperref} +% The \cs{CheckBox} command from hyperref also prints a label, something that the +% command here doesn't do. A redefinition like the following should allow \cs{CheckBox} +% to use the commands of this module. Be aware that the behaviour will not be identical! +% Not every setting and key from \pkg{hyperref} has been copied. +% +% \begin{verbatim} +% \ExplSyntaxOn\makeatletter +% \def\@CheckBox[#1]#2{\LayoutCheckField{#2}{\pdffield_checkbox:n {name=#2,#1}}} +% \ExplSyntaxOff\makeatother +% \end{verbatim} +% +% \subsection{Some background} +% For some general background about fieldsets, fields and field annotations, please +% check \pkg{l3pdffield}. Here are only some remarks about the special case of +% checkboxes. +% +% A checkbox consist of a field along with one or more field annotations. +% The annotations can appear on more than one page or locations and if one instance +% is checked all other instances follows and are checked too. +% +% A checkbox has two different looks: checked and unchecked. The hyperref +% implementation uses symbolic names for the two states and adds some +% values with the /MK key and lets the PDF viewer +% create a look from them. But this doesn't work reliably and is one of the reasons +% why a reimplementation is needed. Also newer PDF versions +% deprecate the /NeedAppearances setting and require that such a look, +% an \enquote{appearance}, is given as form XObjects. +% So the code forces the use of two appearances. +% +% \end{documentation} +% +% \begin{implementation} +% \section{\pkg{l3pdffield-checkbox} Implementation} +% \begin{macrocode} +%<*package> +%<@@=pdffield> +% \end{macrocode} +% \subsection{Variables} +% \begin{macrocode} +% \end{macrocode} +% \subsection{Messages} +% \begin{macrocode} +% \end{macrocode} +% \subsection{Appearances} +% The default appearances are a cross (\cs{texttimes}), +% Every appearance should have two versions and follow the naming +% module/\meta{name}/Yes and module/\meta{name}/Off. +% \begin{macro}{@@/checkbox/default_appearances:} +% This defines the standard appearance. It is setup at the first +% use of a checkbox, and will adapt to the font family in use then. +% \begin{macrocode} +\cs_new_protected:cn {@@/checkbox/default_appearances:} + { + \pdffield_appearance:nn {pdffield/checkbox/default/Yes} + { + \normalsize + \fboxsep 0pt + \framebox + [ \dim_eval:n { \box_ht:N\strutbox+\box_dp:N\strutbox } ] + { \texttimes \strut } + } + \pdffield_appearance:nn {pdffield/checkbox/default/Off} + { + \normalsize + \fboxsep 0pt + \framebox + [ \dim_eval:n { \box_ht:N\strutbox+\box_dp:N\strutbox } ] + { \phantom{\texttimes} \strut } + } + \cs_gset_eq:cN {@@/checkbox/default_appearances:} \prg_do_nothing: + } +% \end{macrocode} +% \end{macro} +% +%\subsection{Creating the field} +% A field should be created if the name doesn't exist +% \begin{macrocode} +\cs_new_protected:Npn \@@_checkbox_field:n #1 %name + { + \pdf_object_if_exist:nF {@@/field/@@/checkbox/#1} + { + \@@_field:n { @@/checkbox/#1 } + } + \keys_set:nn {pdffield}{parent=@@/checkbox/#1} + } +\cs_generate_variant:Nn \@@_checkbox_field:n {V} +% \end{macrocode} +% \subsection{Assembling the checkbox} + +% \begin{macro}{\@@_checkbox:n} +% \begin{macrocode} +\cs_new_protected:Npn \@@_checkbox:n #1 + { + \group_begin: + \use:c {@@/checkbox/default_appearances:} + \cs_set_eq:NN\@@_appearance_handler:nnn \@@_checkbox_appearance_handler:nnn +% \end{macrocode} +% Setting up the defaults. +% \begin{macrocode} + \keys_set:nn {pdffield} + { + fieldID=, + name=checkbox, + appearance = pdffield/checkbox/default, + checked=false, + width = \normalbaselineskip, + height = \normalbaselineskip, + } +% \end{macrocode} +% Value keys should be undefined. +% \begin{macrocode} + \@@_key_disable:nnn{checkbox}{V}{checked} + \@@_key_disable:nnn{checkbox}{DV}{checked} + \@@_key_disable:nnn{checkbox}{AS}{checked} + \keys_set:nn { pdffield }{@@/preset/checkbox,#1} + \keys_set:nn { pdffield } + { + ,unsetFf={Radio,Pushbutton} + ,FT= Btn + } + \tl_if_empty:NT\l_@@_fieldID_tl + { + \pdfdict_get:nnN {l_@@/field}{T}\l_@@_fieldID_tl + \tl_put_left:Nn \l_@@_fieldID_tl {@@/checkbox/} + } + \@@_checkbox_field:V\l_@@_fieldID_tl + \@@_annot: + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Keys} +% Most keys are inherited simply the ones from the generic field and annot keys. +% A key to decide if the box is initially checked or not. +% We stay in the same family so that we can build a style. +% \begin{macrocode} +\keys_define:nn { pdffield } + { + ,checked .choice: + ,checked / false .code:n = + { + \pdfdict_put:nnx { l_@@/field }{V} { /Off } + \pdfdict_put:nnx { l_@@/field }{DV}{ /Off } + \pdfannot_dict_put:nnn {widget}{AS}{ /Off } + } + ,checked / true .code:n = + { + \pdfdict_put:nnx { l_@@/field }{V} { /Yes } + \pdfdict_put:nnx { l_@@/field }{DV}{ /Yes } + \pdfannot_dict_put:nnn {widget}{AS}{ /Yes } + } + ,checked .default:n = {true} + ,checked .groups:n = {checkbox} + } +% \end{macrocode} +% And a key to set a dedicated field ID +% \begin{macrocode} +\keys_define:nn { pdffield } + { + fieldID .tl_set:N = \l_@@_fieldID_tl + } +% \end{macrocode} +% \begin{macro}{\@@_checkbox_appearance_handler:nnn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_checkbox_appearance_handler:nnn #1 #2 #3 %name, type, text + { + \pdfxform_if_exist:nTF { #1/Yes } + { + \pdf_object_if_exist:nF {@@/checkbox/AP/#1} + { + \pdf_object_new:nn {@@/checkbox/AP/#1}{dict} + \pdf_object_write:nx + {@@/checkbox/AP/#1} + { + /Yes ~ \pdfxform_ref:n { #1/Yes} + /Off ~ \pdfxform_ref:n { #1/Off} + } + } + \pdfannot_dict_put:nnx {widget/AP}{#2}{\pdf_object_ref:n{@@/checkbox/AP/#1}} + } + { + \msg_error:nnnn{pdffield}{appearance-missing}{#1}{#3} + } + } + +% \end{macrocode} +% +% \end{macro} +% +% \subsection{user commands} +% \begin{macro}{\pdffield_checkbox:n} +% \begin{macrocode} +\cs_set_eq:NN \pdffield_checkbox:n \@@_checkbox:n +% +% \end{macrocode} +% \end{macro} +%\end{implementation} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf new file mode 100644 index 0000000000..e4b957a528 Binary files /dev/null and b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-checkbox.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf new file mode 100644 index 0000000000..5328b6e77e Binary files /dev/null and b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-radiobutton.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx new file mode 100644 index 0000000000..a8ea21042f --- /dev/null +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.dtx @@ -0,0 +1,508 @@ +% \iffalse meta-comment +% +%% File: l3pdfpdffield-textfield.dtx +% +% Copyright (C) 2021 The LaTeX Project +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file +% +% http://www.latex-project.org/lppl.txt +% +% This file is part of the "LaTeX PDF management testphase bundle" (The Work in LPPL) +% and all files in that bundle must be distributed together. +% +% ----------------------------------------------------------------------- +% +% The development version of the bundle can be found at +% +% https://github.com/latex3/pdfresources +% +% for those people who are interested. +% +%<*driver> +\RequirePackage{pdfmanagement-testphase} +\DeclareDocumentMetadata{} +\makeatletter +\declare@file@substitution{doc.sty}{doc-v3beta.sty} +\makeatother +\documentclass[full]{l3doc} +\usepackage{array,booktabs} +\usepackage{l3pdffield-testphase} +\hypersetup{pdfauthor=The LaTeX Project, + pdftitle=l3pdffield (LaTeX PDF management testphase bundle)} +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +% +% \fi +% \providecommand\hook[1]{\texttt{#1}} +% \title{^^A +% The \pkg{l3pdffield-textfield} module\\ Commands to create textfield form fields ^^A +% \\ \LaTeX{} PDF management testphase bundle +% } +% +% \author{^^A +% The \LaTeX{} Project\thanks +% {^^A +% E-mail: +% \href{mailto:latex-team@latex-project.org} +% {latex-team@latex-project.org}^^A +% }^^A +% } +% +% \date{Version 0.95c, released 2021-03-17} +% +% \maketitle +% \begin{documentation} +% \section{\pkg{l3pdffield-textfield} Introduction} +% \ExplSyntaxOn +% Enter~your~name:\quad \pdffield_textfield:n{name=name,fontcolor=[RGB]{00,33,99},width=5cm} +% \ExplSyntaxOff +% +% This is the documentation for textfield fields, for general information about form fields +% check the documentation l3pdffield. +% +% Textfields allows the user to input text which is then rendered by the PDF viewer and +% often can also be saved together with the PDF. +% +% Currently the package doesn't initialize the font |/Helv| +% used by default in the fields (It works also without it, but this isn't fully compliant.) +% I don't want to setup the same font twice and haven't yet decided how +% to organize the collaboration with hyperref. So for now you should load hyperref +% and issue the \cs{Form} command. +% +% Please keep in mind +% \begin{itemize} +% \item Not every PDF viewer supports textfields. +% \item The font and the exact position of the chars depends on the PDF viewer. +% \item The handling can depend on settings in the PDF viewer. In adobe reader for +% example I had to disable an option to avoid that it tries to create an appearance +% itself +% \item Standards like pdf/A disable features of form fields too +% (as you typically can't change the PDF). +% \end{itemize} +% +% \subsection{About fonts} +% +% The font color and font size can be changed with the keys |fontcolor| and +% |fontsize| described below. This works quite reliably (but e.g. +% the PDF viewer of my browser insists to show the font in blue while editing). +% +% Much more difficult is the font family: +% a typical wish for textfields is that a font matching the document font is used +% in the fields. But how can that be done? +% Obviously it is not possible like with a checkbox to prepare and include appearances +% with the right look, the PDF reader has to render the text dynamically. + +% The PDF reference mentions only one way to pass a font setting to the text field: +% The |DA| key can contain a font operator and the fontname used should be added +% along with a object reference of the font to the form resources +% in the |AcroForm/DR/Font| dictionary. The question is: what does a PDF renderer +% make with this data? Clearly the main resources to render +% the text can not be to rely on an embedded font and a PDF font operator as both +% is not enough +% to guarantee a sensible text support: a font operator is normally used in +% the page stream along with glyph indices and positioning instructions, not +% with unicode input, and typically a font is only partially embedded. +% This means the PDF viewers and editors actually have to use external +% resources--system fonts, or fonts that come along with the viewer and libraries +% to handle font shaping. +% +% Hyperref may add a reference the type1 font helvetica to the DA key, but +% PDF viewers use actually Arial. And if one doesn't add a font with +% |DA| and |DR/Font| the text field works nevertheless. +% +% This doesn't mean that the DA/DR info is ignored altogether. +% Adobe Reader and Pro seems to use it to choose a fitting fallback font: +% \begin{itemize} +% \item One can change the font by simply using the font name (the examples use +% the |font| key of this module). One get courier with |font=courier|, +% times with |font=times|, +% comic sans with |font=ComicSansMS|, DejaVu with |font=DejaVuSans|. The fonts +% don't need to be used in the document or added as resources in the DR/Font dictionary. +% Some fonts work better than other: comic sans is quite unproblematic, +% but DejaVu seems to trigger a font search first and so is slower (perhaps the. +% \item If one fill and then save such a PDF at least adobe adds +% the missing font resources to the PDF. +% \end{itemize} +% +% This lazy font setting doesn't work with other PDF viewers. +% In other test I had better results by actually embedding a few glyphs +% of the font and then adding the font +% as resource to the DR/Font dictionary. Sadly this requires lualatex, only there is +% possible to retrieve the internal font name and font object number for a larger set +% of fonts---with pdflatex it works only for fonts not using a virtual font, and xelatex +% has no access at all. The code for lualatex looked like this (the font one wants +% to use should be active) +% \begin{verbatim} +% \pdffield_textfield:n {name=text,font=F\pdffeedback~fontname\font} +% \pdfmanagement_add:nxx{Catalog/AcroForm/DR/Font} +% {F\pdffeedback~fontname\font} +% {\pdffeedback~fontobjnum\font \c_space_tl 0 \c_space_tl R} +% \end{verbatim} +% +% \subsection{Vertical alignment} +% There is no way to set a reference point for the baseline. +% Alignment must achieved by +% fiddling with the height and depth of the field. The defaults (which uses as +% height the fontsize, and a bit depth) works okay in adobe reader with arial. +% If the font is set to courier, the text jumps up and one has to decrease the height +% by around 30\%. For a multiline field which should be top aligned you should +% increase the depth by the wanted amount \emph{and} the height by around 2pt. +% +% The geometry of the fields is seen by TeX, and so can influence the line spacing. +% If needed you should hide the height with \cs{raisebox} or \cs{smash}. +% +% \section{Textfields} +% Input a value: +% \ExplSyntaxOn +% \pdffield_textfield:n{name=test,width=4cm,height=0.7\baselineskip,depth=0.3\baselineskip} +% \ExplSyntaxOff +% +% \bigskip +% \subsection{Commands} +% \begin{function}{\pdffield_textfield:n} +% \begin{syntax} +% \cs{pdffield_textfield:n}\Arg{key val list} +% \end{syntax} +% This creates a textfield. The list of allowed keys is described below. +% The \meta{key val list} should at least set the name, without it the default name +% |textfield| is used. Textfields with the same +% name belong to the same field and are filled together. The default appearance +% is a light gray background. +% The default appearance is setup at the first use. +% \end{function} +% +% +% \subsection{Keys} +% +% The new textfield command accept all field and annot keys from l3pdffield, +% please check the documentation there. The list here mentions only a few +% central keys, and the keys which are either specific for textfields, or have +% changed functionality. +% +% Disabled keys are +% \begin{itemize} +% \item |FT| is overwritten. +% \item |DA| is overwritten. +% Locally use |fontcolor|, |fontsize| and |font| instead. +% Globally you can set the |DA| key in the catalog with for example +% \begin{verbatim} +% \pdfmanagement_add:nnn{Catalog/AcroForm}{DA}{(/Helv~10~Tf~1~1~0~rg)} +% \end{verbatim} +% \item For textfields only the field flags |ReadOnly|, |Required| |NoExport| +% |Multiline|, |Password|, |FileSelect|, |DoNotSpellCheck|, |DoNotScroll| and |Comb| +% make sense. +% If |Comb| is set, |Multiline|, |Password| and |FileSelect| are unset, |MaxLen| is +% set to 10 if it hasn't been set previously. +% \end{itemize} +% +% \begin{function}{preset-textfield} +% \begin{syntax} +% |preset-textfield| = \Arg{key-val-list} +% \end{syntax} +% This allows to set default keys for a textfield. +% \end{function} +% +% \begin{function}{name,T} +% \begin{syntax} +% |name| = \meta{partial name}\\ +% |T| = \meta{partial name} +% \end{syntax} +% This sets like the |T| key for fields the partial name of the field. The value +% shouldn't contain a period, be not empty and sensibly consist of simple chars. +% Additionally the value is used to create the field ID. +% This means that textfield with the same partial name are annotations +% with the same field as parent and are filled together---this +% what is typically expected. +% The field ID is then internal and can not be used to +% attach another annotation. +% For explicit control of the field ID use the |fieldID| key. +% \end{function} +% +% \begin{function}{fieldID} +% \begin{syntax} +% |fieldID| = \meta{field ID}\\ +% \end{syntax} +% \emph{For experts only!} +% This allows to give the textfield a specific ID. This is only useful +% in the context of a larger fieldset or if you want to attach another annotation +% to the field with \cs{pdffield_annot:n}. If used wrongly you can +% easily create an invalid fieldset. It allows you to create to fields with the +% same partial name, but if you want to see both +% you need to ensure that their full names are +% different---for example by adding some parent fields. +% \end{function} +% +% \begin{function}{parent} +% \begin{syntax} +% |parent| = \meta{field ID}\\ +% \end{syntax} +% This is only needed if the field should be part +% of a larger fieldset. The value should be a field ID of a field created previously +% with \cs{pdffield_field:nn}. +% \end{function} +% +% \begin{function}{altname,TU} +% \begin{syntax} +% |altname| = \meta{string}\\ +% |TU| = \meta{string}\\ +% \end{syntax} +% This is sets an alternative name for user interaction. +% This name can only be set at the first textfield instance, when the field is initialized. +% \end{function} +% +% \begin{function}{mappingname,TM} +% \begin{syntax} +% |mappingname| = \meta{string}\\ +% |TM| = \meta{string}\\ +% \end{syntax} +% This is sets an alternative name for export. +% This name can only be set at the first textfield instance, when the field is initialized. +% \end{function} +% +% \begin{function}{width,height,depth} +% \begin{syntax} +% |width| = \meta{dim expression}\\ +% |height| = \meta{dim expression}\\ +% |depth| = \meta{dim expression} +% \end{syntax} +% These keys allow to set the dimensions of textfield instance. +% The value should be a dimension expression. By default +% |width| is 3cm, the |height| uses the fontsize (\cs{f@size} in pt), +% the |depth| is 0.3\cs{f@size}. +% \end{function} +% +% \begin{function}{appearance,rollover-appearance,down-appearance} +% \begin{syntax} +% |appearance| = \meta{name}\\ +% |rollover-appearance| = \meta{name}\\ +% |down-appearance| = \meta{name} +% \end{syntax} +% This keys sets the normal appearance, the rollover appearance (when the +% mouse hovers over the textfield) and the down appearance (when the +% mouse clicks). They expect the name of an existing form Xobject as value. +% The initial value is |pdffield/textfield/default| +% for the normal appearance and shows a light gray background. +% The other appearance are not set by default (and it is quite unclear if they +% make sense for a textfield). +% \end{function} +% +% \begin{function}{fontcolor} +% \begin{syntax} +% |fontcolor| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values}\\ +% \end{syntax} +% This is sets the color of font in the textfield. Internally currently RGB is used. +% The colors used in +% \meta{color expression} must be known to the \pkg{l3color} commands. +% The initial color is black. It is a \emph{field} setting, that means instances +% share the color. +% \end{function} +% +% \begin{function}{fontsize} +% \begin{syntax} +% |fontsize| = \meta{dim expression} +% \end{syntax} +% This is sets the size of the font in the textfield. +% The default value is the current font size (\cs{f@size} in pt). +% It is a \emph{field} setting, that means instances +% share the size. +% \end{function} +% +% \begin{function}{font} +% \begin{syntax} +% |font| = \meta{symbolic font name} +% \end{syntax} +% This is sets the font in the textfield. See the discussion at the begin of +% the documentation about some background. The default value is |Helv| and this +% name is setup if you load hyperref and issue the \cs{Form} command. +% The default value is the current font size (\cs{f@size} in pt). +% It is a \emph{field} setting, that means instances +% share the font. +% \end{function} +% +% \subsection{Using with hyperref} +% The \cs{TextField} command from hyperref also prints a label, something that the +% command here doesn't do. A redefinition like the following should allow \cs{TextField} +% to use the commands of this module. Be aware that the behaviour will not be identical! +% Not every setting and key from \pkg{hyperref} has been copied. +% +% \begin{verbatim} +% \ExplSyntaxOn\makeatletter +% \def\@TextField[#1]#2{\LayoutTextField{#2}{\pdffield_textfield:n {name=#2,#1}}} +% \ExplSyntaxOff\makeatother +% \end{verbatim} +% +% +% \end{documentation} +% +% \begin{implementation} +% \section{\pkg{l3pdffield-textfield} Implementation} +% \begin{macrocode} +%<*package> +%<@@=pdffield> +% \end{macrocode} +% \subsection{Variables} +% \begin{macrocode} +\tl_new:N \l_@@_DA_fontcolor_tl +\dim_new:N \l_@@_DA_fontsize_dim +\tl_new:N \l_@@_DA_fontname_tl +% \end{macrocode} +% \subsection{Messages} +% \begin{macrocode} +% \end{macrocode} +% \subsection{Appearances} +% The default appearances are a cross (\cs{texttimes}), +% Every appearance should have two versions and follow the naming +% module/\meta{name}/Yes and module/\meta{name}/Off. +% \begin{macro}{@@/textfield/default_appearances:} +% This defines the standard appearance. It is setup at the first +% use of a textfield. +% \begin{macrocode} +\cs_new_protected:cn {@@/textfield/default_appearance:} + { + \pdffield_appearance:nn {pdffield/textfield/default} + { + { \color_select:n{black!5!white}\rule{\paperwidth}{\paperheight} } + } + \cs_gset_eq:cN {@@/textfield/default_appearance:} \prg_do_nothing: + } +% \end{macrocode} +% \end{macro} +% +%\subsection{Creating the field} +% A field should be created if the name doesn't exist +% \begin{macrocode} +\cs_new_protected:Npn \@@_textfield_field:n #1 %name + { + \pdf_object_if_exist:nF {@@/field/@@/textfield/#1} + { + \@@_field:n { @@/textfield/#1 } + } + \keys_set:nn {pdffield}{parent=@@/textfield/#1} + } +\cs_generate_variant:Nn \@@_textfield_field:n {V} +% \end{macrocode} +% \subsection{Assembling the textfield} + +% \begin{macro}{\@@_textfield:n} +% \begin{macrocode} +\cs_new_protected:Npn \@@_textfield:n #1 + { + \group_begin: + \cs_set_eq:NN\@@_value_handler:nN \@@_textfield_value_handler:nN + \use:c {@@/textfield/default_appearance:} +% \end{macrocode} +% Setting up the defaults. +% \begin{macrocode} + \keys_set:nn {pdffield} + { + ,fieldID= + ,name=textfield + ,appearance = pdffield/textfield/default + ,width = 3cm + ,fontsize= \f@size pt + ,height = \f@size pt, + depth = \fp_eval:n {0.3*\f@size} pt, + % font defaults!! + } +% \end{macrocode} +% \begin{macrocode} + \keys_set:nn { pdffield }{@@/preset/textfield,#1} + \int_compare:nNnT {\bitset_item:Nn \l_@@_Ff_bitset {Comb}}={1} + { + % warning if set? + \keys_set:nn { pdffield } + { + ,unsetFf={FileSelect,Multiline,Password} + } + \pdfdict_get:nnN {l_@@/field}{MaxLen}\l_@@_tmpa_tl + \quark_if_no_value:NT \l_@@_tmpa_tl + { + \keys_set:nn { pdffield} + { + MaxLen = 10 %variable + } + % warning + } + } + \keys_set:nn { pdffield } + { + ,FT= Tx + ,AS= + ,DA= + { + \pdf_name_from_unicode_e:n{\l_@@_DA_fontname_tl} + \c_space_tl + \dim_to_decimal_in_bp:n{\l_@@_DA_fontsize_dim} + \c_space_tl + Tf + \c_space_tl + \l_@@_DA_fontcolor_tl + \c_space_tl + %\l_@@_text_DAextra_tl + } + } + \tl_if_empty:NT\l_@@_fieldID_tl + { + \pdfdict_get:nnN {l_@@/field}{T}\l_@@_fieldID_tl + \tl_put_left:Nn \l_@@_fieldID_tl {@@/textfield/} + } + + \@@_textfield_field:V\l_@@_fieldID_tl + \@@_annot: + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \subsection{Keys} +% Most keys are inherited simply the ones from the generic field and annot keys. +% A key to decide if the box is initially checked or not. +% We stay in the same family so that we can build a style. +% \begin{macrocode} +\keys_define:nn {pdffield} + { + ,fontcolor .code:n = + { + \@@_color_set:nn {@@/tmp}{#1} + \color_export:nnN{@@/tmp}{space-sep-rgb}\l_@@_DA_fontcolor_tl + \tl_put_right:Nn \l_@@_DA_fontcolor_tl{~rg} + } + ,fontcolor .initial:n = black, + ,fontcolor .groups:n = {textfield} + ,font .tl_set:N = \l_@@_DA_fontname_tl + ,font .initial:n = {Helv} + ,font .groups:n = {textfield} + ,fontsize .dim_set:N = \l_@@_DA_fontsize_dim + ,fontsize .initial:n = {10bp} + ,fontsize .groups:n = {textfield} + } +% \end{macrocode} +% And a key to set a dedicated field ID +% \begin{macrocode} +\keys_define:nn { pdffield } + { + fieldID .tl_set:N = \l_@@_fieldID_tl + } +% \end{macrocode} +% +% \subsection{Handler} +% \begin{macrocode} +\cs_new_protected:Npn \@@_textfield_value_handler:nN #1#2 + { + \pdf_string_from_unicode:nnN {utf8/string}{#1}#2 + } +% \end{macrocode} +% +% \subsection{user commands} +% \begin{macro}{\pdffield_textfield:n} +% \begin{macrocode} +\cs_set_eq:NN \pdffield_textfield:n \@@_textfield:n +% +% \end{macrocode} +% \end{macro} +%\end{implementation} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf new file mode 100644 index 0000000000..69a2e13b7d Binary files /dev/null and b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield-textfield.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx index dc3fcc3df6..e1e5f8bae1 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.dtx @@ -1,6 +1,6 @@ % \iffalse meta-comment % -%% File: l3pdfpdffield-checkbox.dtx +%% File: l3pdffield.dtx % % Copyright (C) 2021 The LaTeX Project % @@ -28,9 +28,9 @@ \makeatletter \declare@file@substitution{doc.sty}{doc-v3beta.sty} \makeatother -\documentclass[full]{l3doc} -\usepackage{array,booktabs} -\usepackage{l3pdffield-testphase,bearwear} +\documentclass{l3doc} +\usepackage{array,booktabs,caption} +\usepackage{l3pdffield-testphase,tikz} \hypersetup{pdfauthor=The LaTeX Project, pdftitle=l3pdffield (LaTeX PDF management testphase bundle)} \begin{document} @@ -43,17 +43,22 @@ % idxtype = {checkbox key}, % printtype= \textit{checkbox key} % ]{Checkboxkey}{checkboxkey} +% \NewDocElement[ +% idxgroup=field keys, +% idxtype = {field key}, +% printtype= \textit{field key} +% ]{Fieldkey}{fieldkey} +% \NewDocElement[ +% idxgroup=setup keys, +% idxtype = {setup key}, +% printtype= \textit{setup key} +% ]{Fieldsetupkey}{fieldsetupkey} +% \NewDocElement[ +% idxgroup=annot keys, +% idxtype = {annot key}, +% printtype= \textit{annot key} +% ]{Annotkey}{annotkey}% % \providecommand\hook[1]{\texttt{#1}} -% \ExplSyntaxOn -% \pdffield_store_appearance:nn {bear/Yes} -% { -% \tikz\bear\bearwear[shirt=red,body~deco={\node[font=\tiny\bfseries,white]~at~(beartummy){Yes};}]; -% } -% \pdffield_store_appearance:nn {bear/Off} -% { -% \tikz\bear\bearwear[body~deco={\node[font=\tiny\bfseries,white]~at~(beartummy){Off};}]; -% } -% \ExplSyntaxOff % \title{^^A % The \pkg{l3pdffield} module\\ Commands to create form fields ^^A % \\ \LaTeX{} PDF management testphase bundle @@ -68,36 +73,50 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} % \section{\pkg{l3pdffield} Introduction} -% The implementation of form fields in hyperref has some bugs, see for example -% \url{https://github.com/latex3/hyperref/issues/94}. This package is a first step +% The implementation of form fields in hyperref has some bugs\footnote{see for example +% \url{https://github.com/latex3/hyperref/issues/94}}. This package is a first step % towards the goal to review and improve the code of form fields. % % Like the \pkg{pdfmanagement-testphase} package itself it is a temporary package: -% the definite home of the code is not yet decided. +% the definite home of the code is not yet decided, and during the development +% changes in the interfaces are possible. % -% It handles for now \emph{only} checkboxes, other form fields like pushbutton, -% radio buttons or text fields will follow later. As currently no fonts are used, -% it doesn't relies on the hyperref code -% to initialize the form, but it can be used with hyperref. +% The package itself is currently loaded with +% \begin{verbatim} +% \usepackage{l3pdffield-testphase} +% \end{verbatim} % -% The code requires the new PDF management. The code makes use of -% \pkg{l3pdfxform} to create the Xobjects. This code doesn't support yet the -% the dvips backend. +% The code is splitted into various submodules. \texttt{l3pdffield} +% contains the basic commands to create a form field. The code related to field types +% like checkboxes are in \texttt{l3pdffield-\emph{type}}, for example +% \texttt{l3pdffield-checkbox}. Currently only checkboxes have been implemented, +% other form fields like pushbutton, +% radio buttons or text fields will follow later. +% The code doesn't rely on to initialize the form, +% but it can be used with hyperref. % +% The code requires the new PDF management. The code makes use of +% \pkg{l3pdfxform} to create the form Xobjects of the appearances. +% This code doesn't support yet the the dvips backend. % +% The code targets PDF~2.0. This doesn't mean that it won't work in older +% PDF versions, but it tries to implement requirements needed or recommended +% for 2.0; most importantly appearances are used by default everywhere and it +% deprecates |/NeedAppearances|. % % Please keep in mind % \begin{itemize} -% \item Not every PDF viewer supports checkboxes. +% \item Not every PDF viewer supports form fields or all types and features. % \item The handling can depend on settings in the PDF viewer. In adobe reader for % example I had to disable an option to avoid that it tries to create an appearance -% itself -% \item Standards like pdf/A disable form fields too (as you typically can't change the PDF). +% itself. +% \item Standards like pdf/A disable some features of form fields like javascript actions +% (as you typically can't change the PDF). % \end{itemize} % % If \pkg{hyperref} is loaded before @@ -115,258 +134,636 @@ % \begin{document} % \Form % \end{verbatim} -% \section{Step 1: Checkboxes} -% Click me: -% \ExplSyntaxOn\pdffield_checkbox:n{name=bear,appearance=bear,width=23pt,height=30pt,depth=10pt}\ExplSyntaxOff % -% \bigskip -% \subsection{Commands} -% \begin{function}{\pdffield_checkbox:n} +% \section{Some background} +% +% A document can contain a arbitrary number of fields which can be organized in trees. +% The leaf fields in such a tree, the \emph{terminal fields}, typically have +% widget annotations as kids which are then the actual, visual instances of the field, +% and allow to interact with the field. I will call such a +% tree a \emph{fieldset}, nodes \emph{fields} and the widget annotation +% \emph{field annotations}. +% +% If a field has only one child annotation the content of the field dictionary and the +% widget annotation dictionary can be merged---some examples in the PDF reference +% show such merged dictionaries---but the code here keeps them separate, at the end +% this is clearer. +% +% A simple example would look like this +% +% \begin{tikzpicture}[level 2/.style={level distance=7mm}, +% level 1/.style={sibling distance=25mm}, +% level 2/.style={sibling distance=15mm}] +% \node[draw] {week} +% child {node[draw] {mon} +% child {node[draw,dashed] {annot}} +% } +% child {node[draw] {tue} +% child {node[draw,dashed] {annot}} +% } +% child {node[draw] {wen} +% child {node[draw,dashed] {annot}} +% child {node[draw,dashed] {annot}} +% } +% ; +% \end{tikzpicture} +% +% In many cases a fieldset consists of only one field along with its field annotation(s), +% but larger sets can be needed to build more complex interactions with javascript code. +% For example a datepicker can be built as a fieldset with various fields to represent +% the month and year choice and to select days. +% +% Fields in a fieldset should have a name, for example |wen| or |week| in the example +% above. This name is the \emph{partial name} of the field, the \emph{full name} +% is than built from it by adding the names of the parents separated by periods. +% In the example above the partial name is \texttt{mon} and the full name +% \texttt{week.mon}. +% Partial names shouldn't contain periods. If two fields have the same name they will +% work in unison: if you enter text in one field, the text appears also in the other, such +% fields must have the same type and the same value and default value entry. +% If a field has no name it is considered to be a simple widget annotation and so +% only another representation of its parent. +% +% +% All terminal fields should also have a type, e.g. \texttt{Btn} for a button field, +% or \texttt{Tx} for a textfield. The type can be set for the parent and then inherited. +% The fields in a fieldset can have different types. +% +% \subsection{The look of a field: Appearances and other settings} +% +% The look of widget annotation of a field can be set with various keys. The keys developed over +% time and some of them superseed older ones. There is for example the simple +% |/Border|, the more sophisticated |/BS| (\enquote{border style dictionary}), +% the \enquote{dynamic appearance dictionary} |MK|, with lots of keys, +% and the appearance dictionary |/AP| which +% may define as many as three separate appearances: +% the normal appearance (required), the rollover appearance and the down appearance. +% Such an appearance can be a simple form XObjects% +% \footnote{Such form XObjects are small pictures stored in the PDF which +% can be referenced in various part of the PDF. They can be +% created with the commands of the \pkg{l3pdfxform} package.}% +% , but in some cases the annotation can have different \emph{appearance states}: +% a checkbox +% for example can be checked or unchecked, in this case the appearances +% are dictionaries which +% maps state names like |/Yes| and |/Off| to form XObjects. +% +% The annotations cover a rectangular area on +% the page and form XObjects appearances are squeezed into this rectangle. +% So for the best result +% both should have the same ratio of width and height. Simple plain backgrounds can +% also be created in large size and reused for various annotations. +% Form XObjects used as appearances can not be rotated, if needed one has to +% create a new appearance. +% +% +% In PDF 2.0 widget annotations must have at least a normal |/AP| appearance +% (unless the size of the annotation is zero) and the keys \enquote{\itshape C, IC, Border, +% BS, BE, BM, CA, ca, H, DA, Q, +% DS, LE, LL, LLE, and Sy shall be ignored}. But it is quite unclear if +% PDF Viewer honor this, and if this make sense e.g. for text fields which require +% a DA entry. It is also not clear how appearances and the entries of the MK dictionary +% are related in a form field. Tests with some PDF viewers +% are needed here. +% +% +% \section{Commands} +% \begin{function}{\pdffield_field:nn,\pdffield_field:Vn} % \begin{syntax} -% \cs{pdffield_checkbox:n}\Arg{key val list} +% \cs{pdffield_field:nn}\Arg{key val list}\Arg{field ID} % \end{syntax} -% This creates a checkbox to check and uncheck. The list of allowed keys is described below. -% Typically the \meta{key val list} should at least set the name. Checkboxes with the same -% name belong to the same field and are checked and unchecked together. The default appearance -% is a quadratic frame with a \cs{texttimes} in it for the checked case. +% This creates a new field. \meta{field ID} will be used to create and +% reference the needed objects but it is not the direct object name, so +% |pdf_object_ref:n| can not be used to access (and there will not +% clash with object names). It is recommended to start +% the name with a module prefix to avoid name clashes, so e.g. |mymodule/field/1| or +% |mymodule/field/week|. +% +% The list of handled keys is described below. +% Typically the \meta{key val list} should at least set the name |T|, fields that +% are kids in a fieldset must set the |parent| key, this should point to a field +% declared before. +% +% The command is meant as a basic command to build more complex variants like +% checkbox or textfields. For this reason it doesn't check if +% the combination of values and flags are sensible, and it uses as key names the +% names from the PDF reference. +% If you create a button field (Btn) and set MaxLen (which is only known for text +% fields), it will not complain. +% +% Root fields (fields without parent) are added automatically to the +% Catalog/AcroForm dictionary with +% +% +% \begin{verbatim} +% \pdfmanagement_add:nnx{Catalog/AcroForm}{Fields}{} +% \end{verbatim} +% % \end{function} % -%\begin{function}{\pdffield_setup:nn} +% \begin{function}{\pdffield_annot:n,\pdffield_annot:V} % \begin{syntax} -% \cs{pdffield_setup:nn}\Arg{field type}\Arg{key val list} +% \cs{pdffield_field:nn}\Arg{key val list} % \end{syntax} -% This allows to setup up values for following fields. \Arg{field type} -% should be a field, currently the only allowed value is |checkbox|. +% This creates a new field annotation. +% It is a widget annotation box created with \cs{pdfannot_widget_box:nnn}, and +% it is possible to add values to its dictionary +% by using |\pdfannot_dict_put:nnn {widget}...|. +% But to correctly setup the parent/kid relationship some additional wrapper code is needed. +% The command also setup dictionaries to fill the |AP|, |MK| and |AA| dictionaries. % \end{function} % -%\begin{function}{\pdffield_store_appearance:nn} +% \begin{function}{\pdffield_appearance:nn} % \begin{syntax} -% \cs{pdffield_store_appearance:nn}\Arg{name/state}\Arg{content} +% \cs{pdffield_appearance:nn}\Arg{name}\Arg{content} % \end{syntax} -% This is a small wrapper around \cs{pdfxform_new:nn} and store appearances for the fields. -% \meta{state} should be for checkboxes either |Yes| or |Off| (and typically -% you should define both). \meta{name} is the name -% that is used in the |appearance| key, |checkbox/default| is predefined and so can't be used. -% \meta{content} is arbitrary content. The dimensions should fit to the planed size of the -% checkbox.% +% This is a small wrapper around \cs{pdfxform_new:nnn} (which could be used too) +% to create an appearance. To avoid name clashes \meta{name} should start with +% a module part, e.g. |mymodule/appearance/cross|. % \end{function} -% \subsection{Keys} % -% The new checkbox commands accepts following keys: +% \begin{function}{\pdffield_setup:n} +% \begin{syntax} +% \cs{pdffield_setup:n}\Arg{key-val} +% \end{syntax} +% This command allows to preset some field settings. +% \end{function} +% It knows currently two keys: % -% \DescribeCheckboxkey{name} This sets the (internal) name of the field. It shouldn't contain -% a period, be not empty and sensibly consist of simple chars. Checkboxes instances -% with the same name belong to the same field and are checked and unchecked together. +% \begin{function}{create-style} +% \begin{syntax} +% |create-style| = \Arg{name}\Arg{key-val} +% \end{syntax} +% This defines a style which can then be used with the |style| key. +% \Arg{key-val} can be an arbitrary collection of the keys of the module. +% \end{function} % -% \DescribeCheckboxkey{altname} This sets an alternative name for user interaction. -% This name can only be set at the first checkbox instance, when the field is initialized. -% \DescribeCheckboxkey{mappingname} This sets an alternative name for export. -% This name can only be set at the first checkbox instance, when the field is initialized. +% \begin{function}{preset-checkbox} +% \begin{syntax} +% |preset-checkbox|=\Arg{key-val} +% \end{syntax} +% This allows to set default keys for a checkbox. +% \end{function} + +% \section{Field Keys} +% +% Table~\ref{tab:fieldkeys} summarize the keys which can be used. +% A number of keys have two names, the second is normally the name used by hyperref. +% Where is makes sense an empty value \enquote{unsets} a key. +% +% \begin{table} +% \caption{Keys for fields}\label{tab:fieldkeys} +% \centering +% \begin{tabular}{>{\ttfamily}lllll} +% \toprule +% key & value & required & inheritable &remark\\\midrule +% parent & field ID & for non-root fields & \\ +% style & style name & & defined with |create-style| \\ +% T, name & string & mostly & \\ +% TU, altname & string & & \\ +% TM, mappingname & string & & \\ +% FT & name & terminal fields & yes \\ +% setFf, & list of flags & & yes\\ +% setfieldflags\\ +% unsetFf, & list of flags & & yes \\ +% unsetfieldflags \\ +% V & various & & yes \\ +% DV & various & & yes \\ +% MaxLen & integer & with Comb & yes & only textfields\\ +% Lock & object name & & & signature field\\ +% SV & object name & & & signature field\\ +% Opt & object name & & & buttons and choice fields\\ +% TI & integer & & & list fields\\ +% I & object name& & & list fields\\ +% AA/K, keystroke & javascript \\ +% AA/F, format & javascript\\ +% AA/V, validate & javascript\\ +% AA/C, calculate & javascript\\ +% DA & string & yes & yes & variable text \\ +% Q & 0, 1 or 2 & & yes &variable text \\ +% DS & & & & (ignored) \\ +% RV & & & & (ignored) \\\bottomrule +% \end{tabular} +% \end{table} +% +% \begin{function}{parent} +% \begin{syntax} +% |parent| = \meta{field ID}\\ +% \end{syntax} +% This declares the parent of the field. It is required if +% the field is not the root of the fieldset. The value is the field ID +% of the parent, the parent should have been already declared. +% It will add the reference to the parent field to the |/Parent| key, and also +% add reference of the kid as |/Kid| in the parent field. +% \end{function} % -% \DescribeCheckboxkey{width} -% \DescribeCheckboxkey{height} -% \DescribeCheckboxkey{depth} These keys allow to set the dimensions of checkbox instance. -% The value should be a command that expands to a dimension expression. By default -% |width| and |height| use \cs{normalbaselineskip}, the |depth| is zero. -% -% \DescribeCheckboxkey{appearance} This key sets the normal appearance. It takes as value a -% \meta{name} and expects that the two appearances \meta{name}|/Yes| and \meta{name}|/Off| -% has been created with the command described below. The initial value is |checkbox/default| -% and shows a \cs{texttimes}. -% -% \DescribeCheckboxkey{rollover-appearance} This key sets the rollover appearance (when the -% mouse hovers over the checkbox). It takes as value a -% \meta{name} and expects that the two appearances \meta{name}|/Yes| and \meta{name}|/Off| -% has been created with the command described below. Initially this is not set. -% An empty value removes the entry. -% -% \DescribeCheckboxkey{down-appearance} This key sets the down appearance (when the -% mouse clicks). It takes as value a -% \meta{name} and expects that the two appearances \meta{name}|/Yes| and \meta{name}|/Off| -% has been created with the command described below. Initially this is not set. -% An empty value removes the entry. -% -% \DescribeCheckboxkey{checked} This is a boolean key which allows to set if the -% checkbox should be initially checked or not. It sets the |/V| and |/DV| key of the field -% and the |/AS| key of the annotation instance. It is possible to use different -% values for different instances, if one wants to confuse the user. -% -% \DescribeCheckboxkey{setfieldflags} -% \DescribeCheckboxkey{unsetfieldflags} -% These keys allow to set or unset the field flags. They expect a comma lists of -% flag names. Allowed names |ReadOnly|, |Required|, +% \begin{function}{name,T} +% \begin{syntax} +% |name| = \meta{partial name}\\ +% |T| = \meta{partial name} +% \end{syntax} +% This sets the partial name of the field. It shouldn't contain +% a period, be not empty and sensibly consist of simple ascii chars. +% It is normally required, see above. The value is passed through \cs{pdf_string_from_unicode:nnN}. +% \end{function} +% +% \begin{function}{altname,TU} +% \begin{syntax} +% |altname| = \meta{string}\\ +% |TU| = \meta{string}\\ +% \end{syntax} +% This sets an alternative name for user interaction. +% Unlike the name field it can use unicode or periods. +% The value is passed through \cs{pdf_string_from_unicode:nnN} +% \end{function} +% +% \begin{function}{mappingname,TM} +% \begin{syntax} +% |mappingname| = \meta{string}\\ +% |TM| = \meta{string}\\ +% \end{syntax} +% This sets an alternative name for the export. +% The value is passed through \cs{pdf_string_from_unicode:nnN} +% \end{function} +% +% \begin{function}{mappingname,TM} +% \begin{syntax} +% |FT| = |Btn|\verb"|"|Tx|\verb"|"|Ch|\verb"|"|Sig| +% \end{syntax} +% This sets the type of the field, the value should be one of +% \texttt{Btn} (button), \texttt{Tx} (text), \texttt{Ch} (choice), \texttt{Sig} (signature). +% The value is of relevance only for terminal fields, but it can be set in a parent +% and then inherited. +% \end{function} +% +% \begin{function}{setfieldflags,setFf,unsetfieldflags,unsetFf} +% \begin{syntax} +% |setfieldflags| = \meta{comma list of flags}\\ +% |setFf| = \meta{comma list of flags}\\ +% |unsetfieldflags| = |all| \verb"|" \meta{comma list of flags}\\ +% |unsetFf| = |all| \verb"|" \meta{comma list of flags} +% \end{syntax} +% These keys accept a list of flag names and then sets or unsets them, the resulting value +% is then used with the \texttt{/Ff} key. Depending +% on the field type some flags must be set or unset, other are optional or are ignored. +% The flag name can be given in PDF spelling (\texttt{RadiosInUnison}), +% in lowercase (\texttt{radiosinunison}), and as number. |unsetFf| and its +% alias |unsetfieldflags| know the special value |all| which clears all the fields. +% +% The list of flags are: +% |ReadOnly|, |Required|, % |NoExport|, |Multiline|, |Password|, |NoToggleToOff|, |Radio|, |Pushbotton|, % |Combo|, |Edit|, |Sort|, |FileSelect|, |MultiSelect|, |DoNotSpellCheck|, % |DoNotScroll|, |Comb|, |RadiosInUnison|, |RichText|, |CommitOnSelChange|. % -% From these |Radio|, |Pushbotton| are set automatically automatically by the code -% as this is required for a checkbox. Not every one from the rest makes sense for -% checkboxes but the same key will be used for other fields too. -% Check the PDF reference to decide which one to set or unset. -% -% \begin{checkboxkey}{keystroke,format,validate,calculate} -% These keys add the |/K, |/F, |/V|, |/C| key to the |/AA| dictionary of the field object. -% Their value should be javascript code. The |/AA| dictionary is suppressed -% if a pdf/A standard is set. These keys are probably not of much used with a checkbox. -% \end{checkboxkey} -% -% \vspace{2\baselineskip} -% \begin{checkboxkey}{onfocus,onblur,onmousedown,onmouseup,onenter,onexit} -% These keys adds the |/F, |/Bl, |/D|, |/U|, |E| and |X| key to the |/AA| dictionary -% of the widget annotation (the checkbox instance) object. -% Their value should be javascript code. The |/AA| dictionary -% is suppressed if a pdf/A standard is set. +% \end{function} % -% For example -% \begin{verbatim} -% onenter={app.alert('Hello');} -% \end{verbatim} -% \end{checkboxkey} +% \begin{function}{V} +% \begin{syntax} +% |V| = \meta{various} +% \end{syntax} +% This sets the value of the field. Its +% format varies depending on the field type, so typically +% commands for the various type will have to preprocess and sanitize it. +% The value given here is x-expanded and then added to the dictionary! +% See the descriptions of individual field types for further information. +% (Pushbuttons for example don't have a value). +% \end{function} % -% \subsection{Using with hyperref} -% The \cs{CheckBox} command from hyperref also prints a label, something that the -% command here don't do. A redefinition like the following should allow to \cs{CheckBox} -% to use the commands of this module. Be aware that the behaviour will not be identical! -% Not every setting and key from \pkg{hyperref} has been copied. +% \begin{function}{DV} +% \begin{syntax} +% |DV| = \meta{various} +% \end{syntax} +% The default value, to which the field reverts +% when a reset-form action is executed. The format of this value is the +% same as that of \texttt{DV}. +% \end{function} % -% \begin{verbatim} -% \ExplSyntaxOn\makeatletter -% \def\@CheckBox[#1]#2{\LayoutCheckField{#2}{\pdffield_checkbox:n {name=#2,#1}}} -% \ExplSyntaxOff\makeatother -% \end{verbatim} +% \begin{function}{MaxLen} +% \begin{syntax} +% |MaxLen| = \meta{integer} +% \end{syntax} +% Only relevant for textfields. +% The value is an integer and describes the maximum length of the field’s text in characters. +% Required if the |Comb| flag is used. +% \end{function} % -% \subsection{Some background} -% Form fields consist of a field object and number of instances of the field: -% A checkbox can appear on more than one page or location and if one instance -% is checked all other instances follows and are checked too. -% -% All instances are in this case widget annotations and are referenced in the Kid array of the field -% object\footnote{Fields can actually build a tree: between the root field and -% widget annotations there can be more fields. The last one before the widget is -% the \emph{terminal} field, but unless a sensible -% use case comes up, I will assume that the widget annotations are direct children of -% the root and that the root field is the terminal field.}. -% This means that the code has to collect all the children and write -% out the field object at the end of the document. -% -% If a field has only one children the content of the field dictionary and the -% widget annotation dictionary can be merged---some examples in the PDF reference -% show such merged dictionaries---but the code here keeps them separate, at the end -% this is clearer. +% \begin{function}{Lock} +% \begin{syntax} +% |MaxLen| = \meta{object name} +% \end{syntax} +% Only relevant for signature fields. The value is an object name +% which should point to a dictionary that specifies a set of form fields +% that shall be locked when this signature field is signed. The exact format of +% the dictionary is described in the PDF reference. +% \end{function} % -% All the root field objects must be referenced in the AcroForm dictionary in the -% Fields entry. This can be done with +% \begin{function}{SV} +% \begin{syntax} +% |SV| = \meta{object name} +% \end{syntax} +% Only relevant for signature fields. The value is an object name +% which should point to a seed value dictionary. The exact format of +% the dictionary is described in the PDF reference. +% \end{function} % -% \begin{verbatim} -% \pdfmanagement_add:nnx{Catalog/AcroForm}{Fields}{} -% \end{verbatim} +% \begin{function}{Opt} +% \begin{syntax} +% |Opt| = \meta{object name} +% \end{syntax} +% Only relevant for checkboxes, radiobuttons and choice fields. +% The value is an object name +% which should point to a array. The exact format of +% the array is described in the PDF reference. +% \end{function} % -% A checkbox has two different looks: checked and unchecked. The current hyperref -% implementation uses symbolic names for the two states and and adds some -% values with the /MK key and lets the PDF viewer -% create a look from them. But this doesn't work reliably. Also newer PDF versions -% deprecate the /NeedAppearances setting and require that such a look, -% an \enquote{appearance}, is given as form XObjects: -% such form XObjects are like small pictures stored in the PDF and can be referenced -% in various part of the PDF. They can be created with the commands of -% the \pkg{l3pdfxform} package. -% -% The checkbox instances---the widget annotations---cover a rectangular area on -% the page, the XObjects are squeezed into this rectangle. So for the best result -% both should have the same ratio of width and height. -% XObjects used as appearances can not be rotated, if needed one has to -% create a new appearance. +% \begin{function}{TI} +% \begin{syntax} +% |TI| = \meta{integer} +% \end{syntax} +% Only relevant for scrollable list boxes. +% The value is an integer, the top index (the index in the Opt array +% of the first option visible in the list). Default value: 0 +% \end{function} % -% \subsubsection{The field dictionary} +% \begin{function}{I} +% \begin{syntax} +% |I| = \meta{object name} +% \end{syntax} +% For choice fields that allow +% multiple selection (MultiSelect flag set). The value is an object name +% which should point to a array. The exact format of +% the array is described in the PDF reference +% (I have no idea what exactly should be added there, perhaps some future test will make +% it more understandable.) +% \end{function} % -% The field dictionary shall or can have the following entries +% The following four keys are used to add javascript (\enquote{ECMAScript}) code. +% The values are currently only passed through \cs{pdf_string_from_unicode:nnN}, +% but this perhaps will have to change. The keys will be ignored if a pdfstandard +% is used that prohibits such actions. +% +% \begin{function}{AA/K,keystroke} +% \begin{syntax} +% |AA/K| = \meta{string (ECMAScript)}\\ +% |keystroke| = \meta{string (ECMAScript)} +% \end{syntax} +% This adds a keystroke action to the +% additional action dictionary. The value is passed through +% \cs{pdf_string_from_unicode:nnN}. The action is meant for text and choice fields. +% It is quite unclear if such an action +% make sense for non-terminal fields. +% \end{function} +% +% \begin{function}{AA/F,format} +% \begin{syntax} +% |AA/F| = \meta{string (ECMAScript)}\\ +% |format| = \meta{string (ECMAScript)} +% \end{syntax} +% This adds a format action to the +% additional action dictionary. The value is passed through +% \cs{pdf_string_from_unicode:nnN}. The action is meant for text and choice fields. +% It is quite unclear if such an action +% make sense for non-terminal fields. +% \end{function} % -% \begin{description} -% \item[FT] required for terminal fields (here for the root field), -% the value is always \texttt{Btn}, so this entry is set by the code. -% \item[Parents] currently irrelevant as we don't have a field hierarchy. -% \item[Kids] an array. Contains references to the children, in our case to -% the widget annotations. The array is build by the code. +% \begin{function}{AA/V,validate} +% \begin{syntax} +% |AA/V| = \meta{string (ECMAScript)}\\ +% |validate| = \meta{string (ECMAScript)} +% \end{syntax} +% This adds a validate action to the +% additional action dictionary. The value is passed through +% \cs{pdf_string_from_unicode:nnN}. It is quite unclear if such an action +% make sense for non-terminal fields. +% \end{function} +% +% \begin{function}{AA/C,calculate} +% \begin{syntax} +% |AA/C| = \meta{string (ECMAScript)}\\ +% |calculate| = \meta{string (ECMAScript)} +% \end{syntax} +% This adds a calculate action to the +% additional action dictionary. The value is passed through +% \cs{pdf_string_from_unicode:nnN}. It is quite unclear if such an action +% make sense for non-terminal fields. +% \end{function} % -% \item[T] required, the name, a (unique) text string without a period. -% This field is a mandatory argument which must be given by the user. -% The value should be passed through a suitable string conversion and checked -% if it contains a period (which is not allowed). +% \begin{function}{DA} +% \begin{syntax} +% |DA| = \meta{string} +% \end{syntax} +% This contains instructions for the text in text fields. +% It is stored expanded and parentheses are added around the value. +% \end{function} % -% \item[TU,TM] optional, alternative names for user messages (TU) and export (TM). -% As these fields are optional they should be set by some key-val option. +% \begin{function}{Q,align} +% \begin{syntax} +% |Q| = |left|\verb"|"|center|\verb"|"|right|\\ +% |align| = |left|\verb"|"|center|\verb"|"|right| +% \end{syntax} +% The justification of the text. +% \end{function} % -% \item[Ff] A bitset, two flags must be unset for a checkbox (Radio and Pushbotton), -% for the rest we need a keyval interface. +% \begin{function}{DS,RV} +% These two keys are currently not implemented +% as it is unclear if there are of any use. +% \end{function} % -% \item[V] describes the initial value, for checkboxes is should be either |/Yes| -% or |/Off|. The initial value will be |/Yes|, keys are need to set both the local -% and the default value. +% \section{Annot keys} +% +% Table~\ref{tab:annotkeys} summarize the keys which can be used. +% A number of keys have alias names which are mentioned in the descriptions. +% +% \begin{table} +% \caption{Keys for field annotations}\label{tab:annotkeys} +% \centering +% \begin{tabular}{>{\ttfamily}lllll} +% \toprule +% key & value & required &remark\\\midrule +% parent & field ID & yes \\ +% width & dim expression & (yes) & default is 0pt \\ +% height & dim expression & (yes) & default is 0pt \\ +% depth & dim expression & (yes) & default is 0pt \\ +% AP/N & appearance name & yes (in PDF 2.0) \\ +% AP/R & appearance name & yes (in PDF 2.0) \\ +% AP/D & appearance name & yes (in PDF 2.0) \\ +% AS & name & yes (in PDF 2.0) \\ +% setF & list of flags \\ +% unsetF & list of flags \\ +% AA/* & javascript & *= F, Bl, D, U, E, \\ +% & & X, PO, PC,PV, PI\\ +% MK/* & various & *= R, BC, BG, CA, RC, \\ +% & & AC, I, RI, IX, IF, TP\\ \bottomrule +% +% \end{tabular} +% \end{table} +% +% \begin{function}{width,height,depth} +% \begin{syntax} +% |width| = \meta{dim expression}\\ +% |height| = \meta{dim expression}\\ +% |depth| = \meta{dim expression} +% \end{syntax} +% These keys allow to set the dimensions of the annotation. +% The value should be a command that expands to a dimension expression. By default +% all values are zero. +% \end{function} +% +% \begin{function}{parent} +% \begin{syntax} +% |parent| = \meta{field ID}\\ +% \end{syntax} +% This sets the parent. The value should be field ID of +% an already declared field. +% \end{function} +% +% \begin{function}{AP/N,AP/R,AP/D} +% \begin{syntax} +% |AP/N| = \meta{appearance name}\\ +% |AP/R| = \meta{appearance name}\\ +% |AP/D| = \meta{appearance name} +% \end{syntax} +% This keys set the normal, rollover and down appearance. Alias names are +% |appearance|, |rollover-appearance| and |down-appearance|. +% The value is by default a simple name of an appearance/form Xobject but +% modules like \pkg{l3pdffield-checkbox} change this to allow to add appearances for +% various states. +% \end{function} % -% \item[DV] optional, the default value after a reset. Should like |V| be either -% |/Yes| or |/Off|. +% \begin{function}{AS} +% \begin{syntax} +% |AS| = \meta{appearance state name} +% \end{syntax} +% This key sets the default appearance state. +% The value is a name without the starting slash +% (it is passed through |\pdf_name_from_unicode_e:n|), +% for checkbox for example |Yes|. If used it should typically have the same value +% as the V and DV key of the field. +% \end{function} % -% \item[AA] An action dictionary. For this we need a special command to setup such -% dictionaries, so that they then can be used in various places. +%\begin{function}{setannotflags,setF,unsetannotflags,unsetF} +% \begin{syntax} +% |setannotflags| = \meta{comma list of flags}\\ +% |setF| = \meta{comma list of flags}\\ +% |unsetannotflags| = |all| \verb"|" \meta{comma list of flags}\\ +% |unsetF| = |all| \verb"|" \meta{comma list of flags} +% \end{syntax} +% These keys allow to set or unset the annot flags. They expect a comma lists of +% flag names. Allowed names |Invisible|, |Hidden|, +% |Print|, |NoZoom|,|NoRotate|, |NoView|, |ReadOnly|, |Locked|, |ToggleNoView|, +% |LockedContents|, or the lowercase variants or numbers. +% \end{function} % -% \end{description} +% \begin{function}{AA/*} +% \begin{syntax} +% |AA/*| = \meta{string (ECMAScript)} +% \end{syntax} +% * should be one of |F|, |Bl|, |D|, |U|, |E|, |X|, |PO|, |PC|, |PV|, |PI|. +% Alias names for the first six keys are +% |onfocus|, |onblur|, |onmousedown|, |onmouseup|, |onenter|, |onexit|. +% These keys adds then the respective key to the |/AA| dictionary +% of the field annotation object. +% Their value should be javascript code. The |/AA| dictionary +% is suppressed if a pdf/A standard is set. +% +% For example +% \begin{verbatim} +% onenter={app.alert('Hello');} +% \end{verbatim} +% \end{function} % -% \subsubsection{The widget annotation dictionary} +% The following keys add values to the \emph{dynamic appearance dictionary} +% |MK| directory. This is only relevant for +% annotations with dynamic content, like e.g. textfields. +% The settings can also affect checkboxes and radio buttons if the (deprecated) +% |NeedAppearances| is set to true. +% +% The |MK| dictionary can also be added by using |\pdfannot_dict_put:nnn{Widget}{MK}{...}| +% but the two methods should not be mixed. +% +% \begin{function}{MK/R,rotate} +% \begin{syntax} +% |MK/R| = |0| \verb"|" |90| \verb"|" |180| \verb"|" |270|\\ +% |rotate| = |0| \verb"|" |90| \verb"|" |180| \verb"|" |270| +% \end{syntax} +% These rotates the content of the annotation. +% \end{function} % -% \begin{description} -% \item[Type] Value: |/Annot|, set automatically -% \item[Subtype] Value: |/Widget| this is added automatically. -% We use an internal dictionary which is locally copied over the one from l3pdfannot. -% It can be filled with keyval options. -% \item[Parent] The reference to the field, automatically added. -% \item[Rect] the size, calculated from the box size -% \item[Contents] a text string, not really needed but an optional key should allow to -% set it, -% \item[AP] the appearance dictionary. It should look like this -% |/AP <>>>|. I need to test if it makes sense here to -% have a |/R| and |/D| entry too. The objects refer to suitable xforms. -% \item[AS] should be either |/Yes| or |/Off|, and sensibly by default be -% the same as the V entry in the field dictionary. If they differ the AS entry wins. +% \begin{function}{MK/BC,bordercolor} +% \begin{syntax} +% |MK/BC| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values}\\ +% |bordercolor| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values} +% \end{syntax} +% These colors the border. Internally currently RGB is used. +% The colors used in +% \meta{color expression} must be known to the \pkg{l3color} commands. +% \end{function} % -% \item[A] Action, this must be checked. -% \item[AA] additional actions. This must be checked too. +% \begin{function}{MK/BG,backgroundcolor} +% \begin{syntax} +% |MK/BG| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values}\\ +% |backgroundcolor| = \meta{color expression} \verb"|" [\meta{model}]\Arg{values} +% \end{syntax} +% These colors the background. Internally currently RGB is used. +% The colors used in +% \meta{color expression} must be known to the \pkg{l3color} commands. +% \end{function} % -% \item[Border, C, OC, AF, BM, Lang, P, NM, M, F, BS, H]: These are not specifically -% needed for checkbox. An interface to add something to the used annot dictionary -% is needed (or already there), but probably no special key-val support for now. +% \begin{function}{MK/CA,caption} +% \begin{syntax} +% |MK/CA| = \meta{string}\\ +% |caption| = \meta{string} +% \end{syntax} +% This sets a text for the caption. \meta{string} is passed through \cs{pdf_string_from_unicode:nnN} +% and parentheses are added automatically. The font used seems to depend on +% the whims of the PDF reader: At least for checkboxes adobe reader quite insists to +% always use a symbol font and not a text font. It also shows always +% only one symbol, regardless how much one put in the string. +% hyperref uses the key names |checkboxsymbol| and +% |radiosymbol| for this setting. +% \end{function} % -% \item[MK] this is what hyperref uses to set the appearance, but I -% explicitly leave it out and use |AP|. +% The remaining key are useful for buttons only, currently no special syntax support +% is implemented. They will be handled when the code for push buttons is developed and +% tested. +% \begin{function}{MK/*} +% \begin{syntax} +% |MK/*| = \meta{various} +% \end{syntax} +% These keys adds the various entries in the \emph{dynamic appearance dictionary}. +% * should be one of |RC|, |AC|, |I|, |RI|, |IX|, |IF|, |TP|. +% The |MK| dictionary can also be added by using |\pdfannot_dict_put:nnn{Widget}{MK}{...}| +% but the two methods should not be mixed. +% \end{function} % -% \item[Q] (alignment), used by hyperref but not relevant as we don't have variable -% text here. -% \end{description} % \end{documentation} % % \begin{implementation} -% \section{\pkg{l3pdffield-checkbox} Implementation} +% \section{\pkg{l3pdffield} Implementation} % \begin{macrocode} %<*package> %<@@=pdffield> \NeedsTeXFormat{LaTeX2e} -\ProvidesExplPackage{l3pdffield-testphase}{2021-03-17}{0.95c}% - {form field checkboxes} +\ProvidesExplPackage{l3pdffield-testphase}{2021-05-14}{0.95d}% + {form fields} % \end{macrocode} % \subsection{hyperref specific command} % hyperref sets NeedAppearances by default. As this is deprecated we disable this. % \begin{macrocode} \csname HyField@NeedAppearancesfalse\endcsname % suppress NeedAppearances -% values from hyperref: -%\def\DefaultOptionsofCheckBox{print} -%\def\DefaultHeightofCheckBox{\normalbaselineskip} -%\def\DefaultWidthofCheckBox{\normalbaselineskip} % \end{macrocode} +% % \subsection{local variables} +% % \begin{macrocode} -\str_new:N \l_@@_field_name_str \str_new:N \l_@@_tmpa_str -\str_new:N \l_@@_name_tmpa_str -\tl_new:N \l_@@_keys_tmpa_tl +\tl_new:N \l_@@_tmpa_tl +\tl_new:N \l_@@_tmpa_keys_tl +\cs_new_protected:Npn \@@_tmpa:n #1 {} +\cs_new_protected:Npn \@@_tmpa:nn #1 #2 {} +\tl_new:N \l_@@_currentparent_tl +\tl_new:N \l_@@_fieldID_tl % \end{macrocode} % % \subsection{messages} @@ -383,15 +780,40 @@ } \msg_new:nnn {pdffield}{appearance-missing} { - The~appearance~`#1`~is~missing~for~the~#2~appearance. + The~appearance~definition~`#1`~is~missing~for~the~#2~appearance. + } +\msg_new:nnn {pdffield}{not-implemented} + { + Support~for~'/#1'~is~not~implemented\\ + The~key~is~ignored. + } +\msg_new:nnn {pdffield}{key-disabled} + { + key~`#2`~is~disabled~and~ignored~in~the~`#1`~command.\\ + Use~key~`#3`~instead. } -\msg_new:nnn {pdffield}{field-keys-ignored} +\msg_new:nnn {pdffield}{parent-field-missing} { - The~field~`#1`~is~already~initialized\\ - The~field~keys~`#2`~are~ignored. + The~parent~field~'#1'~doesn't~exist\\ + Create~it~with~\tl_to_str:n{\pdffield_field:nn} } % \end{macrocode} +% An auxiliary command to disable some keys +% \begin{macro}{\@@_key_disable:nnn} +% \begin{macrocode} +\cs_new_protected:Npn \@@_key_disable:nnn #1#2#3 + { + \keys_define:nn {pdffield} + { + #2 .code:n = + { + \msg_warning:nnnnn {pdffield}{key-disabled}{#1}{#2}{#3} + } + } + } +% \end{macrocode} +% \end{macro} % \subsection{bitsets} % A bitset for the field flag Ff % and an internal copy of the annot bitset. @@ -417,7 +839,27 @@ Comb = 25,%Tx, requires MaxLen in dict RadiosInUnison = 26,%Btn Radio RichText = 26,%Tx - CommitOnSelChange = 27 + CommitOnSelChange = 27, + readonly = 1, + required = 2, + noexport = 3, + multiline = 13,%Tx + password = 14, + notoggletooff = 15,%Btn, radio button + radio = 16,%Btn: Radio: 15=1, 16=0 + pushbutton = 17,%Btn: Checkbox: 15=0, 16=0 + %Btn: Pushbutton: 16=1 + combo = 18,%Ch: Combo=1 List=0 + edit = 19,%Ch, Combo=1 -> + edit field + sort = 20,%Ch, not relevant for view... + fileselect = 21,%Tx + multiselect = 22,%Ch + donotspellcheck = 23,%Tx, Ch (if Combo + Edit set) + donotscroll = 24,%Tx + comb = 25,%Tx, requires MaxLen in dict + radiosinunison = 26,%Btn Radio + richtext = 26,%Tx + commitonselchange = 27 } \bitset_new:Nn \l_@@_F_bitset @@ -431,102 +873,107 @@ ReadOnly = 7, Locked = 8, ToggleNoView = 9, - LockedContents = 10 + LockedContents = 10, + invisible = 1, + hidden = 2, + print = 3, + nozoom = 4, + norotate = 5, + noview = 6, + readonly = 7, + locked = 8, + togglenoview = 9, + lockedcontents = 10 } % \end{macrocode} % \subsection{The field dictionary} -% The field dictionary is the main object. It references the -% actual widget annotations as kids. It is created at the first -% checkbox with a specific name. +% The field dictionary is the main object. % To be able to set values from the outside it will use a % dictionary which can be filled by key-val. % \begin{macrocode} -\pdfdict_new:n {l_@@/checkbox/field} -\pdfdict_put:nnn {l_@@/checkbox/field}{FT}{/Btn} +\pdfdict_new:n {l_@@/field} +\pdfdict_new:n {l_@@/field/AA} +\bool_new:N \l_@@_root_field_bool % \end{macrocode} -% We need to check if the name contains a dot. But we will do this in an external command -% to avoid to have it twice. Here we assume that the name is already converted and safe. -% -% We also assume that values that can be changed by the user are set outside -% in the dictionary. -% If the field object already exists nothing is done. -% \begin{macro}{\@@_checkbox_field_add:n} +% \begin{macro}{\@@_field:n} % \begin{syntax} -% \cs{@@_checkbox_field_add:n}\Arg{name} +% \cs{@@_field:n}\Arg{field ID} % \end{syntax} -% \meta{name} should be a PDF text string without period. It identifies the -% field. % \begin{macrocode} -\cs_new_protected:Npn \@@_checkbox_field_new:n #1 +\cs_new_protected:Npn \@@_field:n #1 { - \group_begin: - \pdf_object_new:nn {@@_checkbox/field/#1} {dict} - \pdf_object_new:nn {@@_checkbox/field/#1/Kids} {array} - \seq_new:c {g_@@_checkbox/field/#1/Kids_seq} - \hook_gput_code:nnn {shipout/lastpage}{pdffield} %xetex needs this ... - { - \pdf_object_write:nx {@@_checkbox/field/#1/Kids} - { - \seq_use:cn{g_@@_checkbox/field/#1/Kids_seq}{~} - } - } - \pdfdict_put:nnn {l_@@/checkbox/field}{T}{(#1)} - % V,DV are names describing the appearance. With checkboxes - % the values /Yes and /Off are used. - % this values are taken from the outside - \pdfdict_put:nnx {l_@@/checkbox/field} - {Kids} - { - \pdf_object_ref:n {@@_checkbox/field/#1/Kids} - } - \bitset_set_false:Nn \l_@@_Ff_bitset {Radio} - \bitset_set_false:Nn \l_@@_Ff_bitset {Pushbutton} - \pdfdict_put:nnx {l_@@/checkbox/field} - {Ff} - {\bitset_to_arabic:N \l_@@_Ff_bitset } - \pdfdict_if_empty:nF{l_@@/checkbox/field/AA} - { - \pdfmeta_standard_verify:nT - {annot_widget_no_AA} - { - \pdfdict_put:nnx - {l_@@/checkbox/field} - {AA} - {<<\pdfdict_use:n {l_@@/checkbox/field/AA}>>} - } - } - \pdf_object_write:nx {@@_checkbox/field/#1} { \pdfdict_use:n {l_@@/checkbox/field} } - \pdfmanagement_add:nnx - { Catalog / AcroForm } - { Fields } - {\pdf_object_ref:n {@@_checkbox/field/#1} } - \group_end: + \pdf_object_new:nn {@@/field/#1} {dict} + \pdf_object_new:nn {@@/field/Kids/#1} {array} + \tl_if_empty:NTF \l_@@_currentparent_tl + { + \pdfmanagement_add:nnx + { Catalog / AcroForm } + { Fields } + {\pdf_object_ref:n {@@/field/#1} } + } + { + \exp_args:Ne + \pdf_object_if_exist:nTF {@@/field/\l_@@_currentparent_tl} + { + \pdfdict_put:nnx { l_@@/field }{Parent} + {\exp_args:Ne \pdf_object_ref:n{@@/field/\l_@@_currentparent_tl}} + \seq_gput_right:cx {g_@@_field/Kids/\l_@@_currentparent_tl _seq} + { \exp_args:Ne \pdf_object_ref:n{@@/field/#1}} + } + { + \msg_error:nnx {pdffield}{parent-field-missing}{\l_@@_currentparent_tl} + } + } + \seq_new:c {g_@@_field/Kids/#1_seq} + \pdfdict_put:nnx {l_@@/field} + {Kids} + { + \pdf_object_ref:n {@@/field/Kids/#1} + } + \pdfdict_put:nnx {l_@@/field} + {Ff} + {\bitset_to_arabic:N \l_@@_Ff_bitset } + \pdfdict_if_empty:nF{l_@@/field/AA} + { + \pdfmeta_standard_verify:nT + {annot_widget_no_AA} + { + \pdf_object_unnamed_write:nx {dict}{\pdfdict_use:n {l_@@/field/AA}} + \pdfdict_put:nnx + {l_@@/field} + {AA} + {\pdf_object_ref_last:} + } + } + \hook_gput_code:nnn {shipout/lastpage}{pdffield} %xetex needs this ... + { + \pdf_object_write:nx {@@/field/Kids/#1} + { + \seq_use:cn{g_@@_field/Kids/#1_seq}{~} + } + } + \pdf_object_write:nx {@@/field/#1} { \pdfdict_use:n {l_@@/field} } + } +\cs_new_protected:Npn \pdffield_field:nn #1 #2 + { + \group_begin: + \keys_set:nn { pdffield } {#1} + \@@_field:n {#2} + \group_end: } - % \end{macrocode} % \end{macro} +% % \subsection{The annot dictionary} % We assume that the annotation should really occupy space on the page and % leave vertical mode. -% We also assume that keys like AP, AS are added before through keys to -% the dictionary. -% We use a local dictionary which is copied into |l__pdfannot/widget| in the code. -% \begin{macrocode} -\pdfdict_new:n {l_@@/checkbox/annot} -\pdfdict_put:nnn {l_@@/checkbox/annot}{Subtype}{/Widget} -% \end{macrocode} % -% \begin{macro}{\@@_checkbox_annot_add:nnnn} +% \begin{macro}{\@@_annot:} +% The command doesn't add grouping, so should only be used inside a group. +% % \begin{macrocode} -\cs_new_protected:Npn \@@_checkbox_annot_add:nnnn #1 #2 #3 #4 %name, wd, ht, dp, +\cs_new_protected:Npn \@@_annot: { - \group_begin: -% \end{macrocode} -% Copy the internal dictionary to the pdfannot dictionary. This -% perhaps need a function in l3pdfannot, -% as it actually uses an internal name of another module. -% \begin{macrocode} - \pdfdict_put:nnx {l_@@/checkbox/annot}{AP}{<<\pdfdict_use:n{l_@@/checkbox/annot/AP}>>} \pdfmeta_standard_verify:nF {annot_flags} { @@ -535,428 +982,656 @@ \bitset_set_false:Nn \l_@@_F_bitset {Invisible} \bitset_set_false:Nn \l_@@_F_bitset {NoView} } - \pdfdict_if_empty:nF{l_@@/checkbox/annot/AA} + \pdfannot_dict_put:nnx {widget}{F}{ \bitset_to_arabic:N \l_@@_F_bitset } + \tl_if_empty:NF \l_@@_currentparent_tl { - \pdfmeta_standard_verify:nT - {annot_widget_no_AA} - { - \pdfdict_put:nnx - {l_@@/checkbox/annot} - {AA} - {<<\pdfdict_use:n {l_@@/checkbox/annot/AA}>>} - } - } - \pdfdict_put:nnx {l_@@/checkbox/annot}{F}{ \bitset_to_arabic:N \l_@@_F_bitset } - \pdfdict_set_eq:nn {l__pdfannot/widget}{l_@@/checkbox/annot} - \pdfannot_dict_put:nnx {widget}{Parent}{\pdf_object_ref:n{@@_checkbox/field/#1}} + \exp_args:Ne + \pdf_object_if_exist:nTF { @@/field/\l_@@_currentparent_tl } + { + \pdfannot_dict_put:nnx {widget}{Parent} + { + \exp_args:Ne + \pdf_object_ref:n{@@/field/\l_@@_currentparent_tl} + } + } + { + \msg_error:nnx { pdffield }{parent-field-missing}{\l_@@_currentparent_tl} + } + } \mode_leave_vertical: \hbox_to_wd:nn - { #2 } + { \l_@@_annot_wd_dim } { - \rule [-#4]{0pt}{\dim_eval:n{#3+#4} } + \rule [-\l_@@_annot_dp_dim]{0pt}{\dim_eval:n{\l_@@_annot_ht_dim+\l_@@_annot_dp_dim} } \pdfannot_widget_box:nnn - { #2 } - { #3 } - { #4 } + { \l_@@_annot_wd_dim } + { \l_@@_annot_ht_dim } + { \l_@@_annot_dp_dim } \hfill } - \seq_gput_right:cx {g_@@_checkbox/field/#1/Kids_seq}{ \pdfannot_box_ref_last:} - \group_end: - } - -% \end{macrocode} -% \end{macro} -% \subsection{Appearances} -% We don't try to force a size or content here. -% The default appearances are a cross (\cs{texttimes}), -% Every appearance should have two versions and follow the naming -% checkbox/\meta{name}/Yes and checkbox/\meta{name}/Off. -% TODO check if one delay the creation to a sensible place -% (and don't forget that the appearance key sets an initial -% value) -% \begin{macro}{\pdffield_store_appearance:nn,\@@_store_default_appearances:} -% \begin{macrocode} -\cs_new_protected:Npn \pdffield_store_appearance:nn #1 #2 - { - \pdfxform_new:nnn {@@_#1}{}{#2} + \tl_if_empty:NF \l_@@_currentparent_tl + { + \seq_if_exist:cTF {g_@@_field/Kids/\l_@@_currentparent_tl _seq} + { + \seq_gput_right:cx + {g_@@_field/Kids/\l_@@_currentparent_tl _seq} + { \pdfannot_box_ref_last:} + } + { + \msg_error:nnx { pdffield}{parent-field-missing}{\l_@@_currentparent_tl} + } + } } - -\cs_new_protected:Nn \@@_store_default_appearances: - { - \pdffield_store_appearance:nn {checkbox/default/Yes} - { - \normalsize - \fboxsep 0pt - \framebox - [ \dim_eval:n { \box_ht:N\strutbox+\box_dp:N\strutbox } ] - { \texttimes \strut } - } - \pdffield_store_appearance:nn {checkbox/default/Off} - { - \normalsize - \fboxsep 0pt - \framebox - [ \dim_eval:n { \box_ht:N\strutbox+\box_dp:N\strutbox } ] - { \phantom{\texttimes} \strut } - } - } - -\@@_store_default_appearances: -% \end{macrocode} -% \end{macro} -% We define a dictionary for the AP content, so that we can add R and D too -% \begin{macrocode} -\pdfdict_new:n {l_@@/checkbox/annot/AP} -% \end{macrocode} -% -% \subsection{Assembling the checkbox} -% \begin{macro}{\@@_checkbox_add:n} -% \begin{macrocode} - -\cs_new_protected:Npn \@@_checkbox_add:n #1 +\cs_new_protected:Npn \pdffield_annot:n #1 { \group_begin: - \keys_set_filter:nnnN {pdffield / checkbox }{field}{#1}\l_@@_keys_tmpa_tl - \str_if_empty:NT \l_@@_field_name_str - { - \msg_error:nn {pdffield}{empty-name} - } - \exp_args:Nx - \pdf_object_if_exist:nTF {@@_checkbox/field/\l_@@_field_name_str} - { - \tl_if_empty:NF \l_@@_keys_tmpa_tl - { - \msg_warning:nnxx - {pdffield} - {field-keys-ignored} - {\l_@@_field_name_str} - {\l_@@_keys_tmpa_tl} - } - } - { - \keys_set:nV { pdffield/checkbox } \l_@@_keys_tmpa_tl - \exp_args:No - \@@_checkbox_field_new:n {\l_@@_field_name_str} - } - \exp_args:No - \@@_checkbox_annot_add:nnnn - {\l_@@_field_name_str} - {\l_@@_annot_wd_tl } - {\l_@@_annot_ht_tl } - {\l_@@_annot_dp_tl } + \keys_set:nn { pdffield } {#1} + \@@_annot: \group_end: } % \end{macrocode} % \end{macro} -% \subsection{Keys} -% The size of the checkbox % +% \subsection{auxiliary command for color keys} % \begin{macrocode} -\tl_new:N \l_@@_annot_ht_tl -\tl_new:N \l_@@_annot_wd_tl -\tl_new:N \l_@@_annot_dp_tl +\cs_new_protected:Npn \@@_color_set:nn #1 #2 + { + \tl_if_head_eq_charcode:nNTF {#2}[ %] + { + \@@_color_set_aux:nwn { #1 } #2 + } + { + \color_set:nn {#1} {#2} + } + } -\keys_define:nn { pdffield / checkbox } +\cs_new_protected:Npn \@@_color_set_aux:nwn #1 [#2] #3 { - ,width .tl_set:N = \l_@@_annot_wd_tl - ,height .tl_set:N = \l_@@_annot_ht_tl - ,depth .tl_set:N = \l_@@_annot_dp_tl - ,width .initial:n = \normalbaselineskip - ,height .initial:n = \normalbaselineskip - ,depth .initial:n = 0pt + \color_set:nnn {#1}{#2}{#3} } + % \end{macrocode} +% \subsection{Field keys} % The names. The main name should not be empty, it is added to the dictionary % when the field is created. A new name means a new field. % The other names can only be set when the field is created, % so we put them in the field group. % \begin{macrocode} -\keys_define:nn { pdffield / checkbox } +\cs_new_protected:Npn \@@_value_handler:nN #1#2 + { + \tl_set:Nn #2 {#1} + } +\keys_define:nn { pdffield } { - ,name .code:n = + ,parent .tl_set:N = \l_@@_currentparent_tl + ,parent .groups:n = {field,annot} + ,T .code:n = { - \pdf_string_from_unicode:nnN {utf8/string-raw}{#1}\l_@@_field_name_str - \str_if_in:NnT \l_@@_field_name_str {.} + \pdf_string_from_unicode:nnN {utf8/string-raw}{#1}\l_@@_tmpa_str + \str_if_in:NnT \l_@@_tmpa_str {.} { - \msg_error:nnx {pdffield}{no-period}{\l_@@_field_name_str} + \msg_error:nnx {pdffield}{no-period}{\l_@@_tmpa_str} } - \str_if_empty:NT\l_@@_field_name_str + \str_if_empty:NTF\l_@@_tmpa_str { - \msg_error:nn {pdffield}{empty-name} + \msg_warning:nn {pdffield}{empty-name} + \pdfdict_remove:nn { l_@@/field }{T} + } + { + \pdfdict_put:nnx { l_@@/field }{T}{(\l_@@_tmpa_str)} } } + ,T .value_required:n = true + ,T .groups:n = {field} + ,name .meta:n = {T={#1}} ,name .value_required:n = true - ,name .initial:n = checkbox - ,altname .code:n = + ,name .groups:n = {field} + ,TU .groups:n = {field} + ,TU .code:n = { - \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_name_tmpa_str - \pdfdict_put:nnx { l_@@/checkbox/field }{TU}{\l_@@_name_tmpa_str} + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{TU} + } + { + \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str + \pdfdict_put:nnx { l_@@/field }{TU}{\l_@@_tmpa_str} + } } + ,TU .groups:n = {field} + ,altname .meta:n = {TU={#1}} ,altname .groups:n = {field} - ,mappingname .code:n = + ,TM .code:n = { - \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_name_tmpa_str - \pdfdict_put:nnx { l_@@/checkbox/field }{TM}{\l_@@_name_tmpa_str} + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{TM} + } + { + \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str + \pdfdict_put:nnx { l_@@/field }{TM}{\l_@@_tmpa_str} + } } + ,TM .groups:n = {field} + ,mappingname .meta:n = {TM={#1}} ,mappingname .groups:n = {field} - } -% \end{macrocode} - -% A key to decide if the Box is initially checked or not -% \begin{macrocode} -\keys_define:nn { pdffield / checkbox } - { - ,checked .choice: - ,checked / false .code:n = + ,FT .choices:nn = + { Btn, Tx, Ch, Sig } + { + \pdfdict_put:nnn { l_@@/field }{FT}{ /#1 } + } + ,FT .groups:n = {field} + ,V .code:n = { - \pdfdict_put:nnn {l_@@/checkbox/field}{V}{/Off} - \pdfdict_put:nnn {l_@@/checkbox/annot}{AS}{/Off} - \pdfdict_put:nnn {l_@@/checkbox/field}{DV}{/Off} + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{V} + } + { + \@@_value_handler:nN{#1}\l_@@_tmpa_str + \pdfdict_put:nnx { l_@@/field }{V}{ \l_@@_tmpa_str } + } } - ,checked / true .code:n = + ,V .groups:n = {field} + ,DV .code:n = { - \pdfdict_put:nnn {l_@@/checkbox/field}{V}{/Yes} - \pdfdict_put:nnn {l_@@/checkbox/annot}{AS}{/Yes} - \pdfdict_put:nnn {l_@@/checkbox/field}{DV}{/Yes} + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{DV} + } + { + \@@_value_handler:nN{#1}\l_@@_tmpa_str + \pdfdict_put:nnx { l_@@/field }{DV}{ \l_@@_tmpa_str } + } } - ,checked .default:n = {true} - ,checked .initial:n = {false} - } + ,DV .groups:n = {field} + ,MaxLen .code:n = + { + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{MaxLen} + } + { + \pdfdict_put:nnx { l_@@/field }{MaxLen}{ #1 } + } + } + ,MaxLen .groups:n = {field} + ,Lock .code:n = + { + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{Lock} + } + { + \pdfdict_put:nnx { l_@@/field }{Lock}{ \pdf_object_ref:n{#1} } + } + } + ,Lock .groups:n = {field} + ,SV .code:n = + { + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{SV} + } + { + \pdfdict_put:nnx { l_@@/field }{SV}{ \pdf_object_ref:n{#1} } + } + } + ,SV .groups:n = {field} + ,Opt .code:n = + { + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{Opt} + } + { + \pdfdict_put:nnx { l_@@/field }{Opt}{ \pdf_object_ref:n{#1} } + } + } + ,Opt .groups:n = {field} + ,TI .code:n = + { + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{TI} + } + { + \pdfdict_put:nnx { l_@@/field }{TI}{ #1 } + } + } + ,TI .groups:n = {field} + ,I .code:n = + { + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{I} + } + { + \pdfdict_put:nnx { l_@@/field }{I}{ \pdf_object_ref:n{#1} } + } + } + ,I .groups:n = {field} + } % \end{macrocode} -% Flags. We don't add lots of individual keys but mapped the key names directly + +% Flags. We don't add lots of individual keys but map the key names directly % \begin{macrocode} -\keys_define:nn { pdffield / checkbox } +\keys_define:nn { pdffield } { - ,setfieldflags .code:n = + ,setFf .code:n = { \clist_map_inline:nn {#1} { \bitset_set_true:Nn \l_@@_Ff_bitset {##1} } } + ,setFf .groups:n = {field} + ,setfieldflags .meta:n = + {setFf={#1}} ,setfieldflags .groups:n = {field} - ,unsetfieldflags .code:n = + ,unsetFf .multichoice: + ,unsetFf / all .code:n = { \bitset_clear:N \l_@@_Ff_bitset} + ,unsetFf / unknown .code:n = { - \clist_map_inline:nn {#1} - { - \bitset_set_false:Nn \l_@@_Ff_bitset {##1} - } + \bitset_set_false:Nn \l_@@_Ff_bitset {#1} } + ,unsetFf .groups:n = {field} + ,unsetfieldflags .meta:n = {unsetFf={#1}} ,unsetfieldflags .groups:n = {field} - ,setannotflags .code:n = + } + +% \end{macrocode} +% +% Keys for the AA dictionary. They all trigger a javascript option. +% K=keystroke, F=format, V=validate, C=calculate +% \begin{macrocode} +\cs_set_protected:Npn \@@_tmpa:n #1 % + { + \keys_define:nn { pdffield } { - \clist_map_inline:nn {#1} + AA/#1 .code:n = { - \bitset_set_true:Nn \l_@@_F_bitset {##1} - } + \pdf_string_from_unicode:nnN {utf8/string-raw}{##1}\l_@@_tmpa_str + \str_if_empty:NTF \l_@@_tmpa_str + { + \pdfdict_remove:nn {l_@@/field/AA}{#1} + } + { + \pdfdict_put:nnx {l_@@/field/AA} + {#1} + {<>} + } + }, + AA/#1 .groups:n = {field} } - ,unsetannotflags .code:n = + } + +\clist_map_inline:nn {K,F,V,C}{\@@_tmpa:n{#1}} + +\cs_set_protected:Npn \@@_tmpa:nn #1 #2 + { + \keys_define:nn { pdffield } { - \clist_map_inline:nn {#1} - { - \bitset_set_false:Nn \l_@@_F_bitset {##1} - } + #1 .meta:nn = + { pdffield }{AA/#2={##1}}, + #1 .groups:n = {field} } } +\@@_tmpa:nn {keystroke}{K} +\@@_tmpa:nn {format} {F} +\@@_tmpa:nn {validate} {V} +\@@_tmpa:nn {calculate}{C} + + +% \end{macrocode} +% +% \begin{macrocode} +\keys_define:nn { pdffield } + { + DA .code:n = + { + \tl_if_empty:nTF {#1} + { + \pdfdict_remove:nn { l_@@/field }{DA} + } + { + \pdfdict_put:nnx { l_@@/field }{DA}{ (#1) } + } + } + ,DA .groups:n = {field} + ,Q .choices:nn = {left,center,right} + { + \pdfdict_put:nnx { l_@@/field }{Q}{ \int_eval:n{\l_keys_choice_int-1} } + } + ,Q / .code:n = { \pdfdict_remove:nn { l_@@/field }{Q} } + ,Q .groups:n = {field} + ,align .meta:n={Q=#1} + ,DS .code:n = + { + \msg_warning:nnn {pdffield}{not-implemented}{DS} + } + ,DS .groups:n = {field} + ,RV .code:n = + { + \msg_warning:nnn {pdffield}{not-implemented}{RV} + } + ,RV .groups:n = {field} + } +% \end{macrocode} +% +% \subsection{Annotation keys} +% The size of the field annotation +% +% \begin{macrocode} +\dim_new:N \l_@@_annot_ht_dim +\dim_new:N \l_@@_annot_wd_dim +\dim_new:N \l_@@_annot_dp_dim -\keys_define:nn { pdffield / checkbox } +\keys_define:nn { pdffield } { - appearance .code:n = %value is a name of an appearance + ,width .dim_set:N = \l_@@_annot_wd_dim + ,height .dim_set:N = \l_@@_annot_ht_dim + ,depth .dim_set:N = \l_@@_annot_dp_dim + ,width .initial:n = 0pt + ,height .initial:n = 0pt + ,depth .initial:n = 0pt + } +% \end{macrocode} +% +% \begin{macrocode} +\keys_define:nn { pdffield } + { + %parent is defined in field + ,AS .code:n = + { + \tl_if_empty:nTF {#1} + { + \pdfannot_dict_remove:nn { widget }{AS} + } + { + \pdfannot_dict_put:nnx {widget}{AS}{\pdf_name_from_unicode_e:n{#1}} + } + } + ,AS .groups:n = annot + } +\cs_new_protected:Npn \@@_appearance_handler:nnn #1#2#3 + { + \pdfxform_if_exist:nTF { #1 } + { + \pdfannot_dict_put:nnx {widget/AP}{#2} + { + \pdfxform_ref:n {#1} + } + } + { + \msg_error:nnnn{pdffield}{appearance-missing}{#1}{#3} + } + } +\keys_define:nn { pdffield } + { + AP/N .code:n = { - \pdfxform_if_exist:nTF { @@_#1/Yes } + \tl_if_empty:nTF {#1} { - \pdfdict_put:nnn {l_@@/checkbox/annot/AP} - {N} - { - << - /Yes ~ \pdfxform_ref:n { @@_#1/Yes} - /Off ~ \pdfxform_ref:n { @@_#1/Off} - >> - } + \pdfannot_dict_remove:nn { widget/AP }{N} } { - \msg_error:nnnn{pdffield}{appearance-missing}{#1}{normal} + \@@_appearance_handler:nnn {#1}{N}{normal} } - }, - appearance .initial:n = checkbox/default, + } + ,AP/N .groups:n = annot + ,appearance .meta:n = {AP/N={#1}} } - -\keys_define:nn { pdffield / checkbox } +\keys_define:nn { pdffield } { - rollover-appearance .code:n = %value is a name of an appearance + AP/R .code:n = { + \tl_if_empty:nTF {#1} + { + \pdfannot_dict_remove:nn { widget/AP }{R} + } + { + \@@_appearance_handler:nnn {#1}{R}{rollover} + } + } + ,AP/R .groups:n = annot + ,rollover-appearance .meta:n = {AP/R={#1}} + } +\keys_define:nn { pdffield } + { + AP/D .code:n = + { + \tl_if_empty:nTF {#1} + { + \pdfannot_dict_remove:nn { widget/AP }{D} + } + { + \@@_appearance_handler:nnn {#1}{D}{rollover} + } + } + ,AP/D .groups:n = annot + ,down-appearance .meta:n = {AP/D={#1}} + } + +\keys_define:nn { pdffield } + { + MK/R .choices:nn = {0,90,180,270} + { + \pdfannot_dict_put:nnx {widget/MK}{R}{#1} + } + ,MK/R / .code:n = + { + \pdfannot_dict_remove:nn { widget/MK }{R} + } + ,MK/R .groups:n = annot + ,rotate .meta:n = {MK/R=#1} + } + +\keys_define:nn { pdffield } + { + MK/BC .code:n = + { \tl_if_empty:nTF {#1} - { - \pdfdict_remove:nn {l_@@/checkbox/annot/AP} {R} - } - { - \pdfxform_if_exist:nTF { @@_#1/Yes } - { - \pdfdict_put:nnn {l_@@/checkbox/annot/AP} - {R} - { - << - /Yes ~ \pdfxform_ref:n { @@_#1/Yes} - /Off ~ \pdfxform_ref:n { @@_#1/Off} - >> - } - } - { - \msg_warning:nnnn{pdffield}{appearance-missing}{#1}{rollover} - } + { + \pdfannot_dict_remove:nn { widget/MK }{BC} + } + { + \@@_color_set:nn {@@/tmp}{#1} + \color_export:nnN{@@/tmp}{space-sep-rgb}\l_@@_tmpa_tl + \pdfannot_dict_put:nnx {widget/MK}{BC}{[\l_@@_tmpa_tl]} + } + } + ,MK/BC .groups:n = annot + ,bordercolor .meta:n = {MK/BC=#1} + } - } - }, +\keys_define:nn { pdffield } + { + MK/BG .code:n = + { + \tl_if_empty:nTF {#1} + { + \pdfannot_dict_remove:nn { widget/MK }{BG} + } + { + \@@_color_set:nn {@@/tmp}{#1} + \color_export:nnN{@@/tmp}{space-sep-rgb}\l_@@_tmpa_tl + \pdfannot_dict_put:nnx {widget/MK}{BG}{[\l_@@_tmpa_tl]} + } + } + ,MK/BG .groups:n = annot + ,bordercolor .meta:n = {MK/BG=#1} } -\keys_define:nn { pdffield / checkbox } + +\keys_define:nn { pdffield } { - down-appearance .code:n = %value is a name of an appearance - { + MK/CA .code:n = + { \tl_if_empty:nTF {#1} - { - \pdfdict_remove:nn {l_@@/checkbox/annot/AP} {D} - } - { - \pdfxform_if_exist:nTF { @@_#1/Yes } + { + \pdfannot_dict_remove:nn { widget/MK }{CA} + } + { + \pdf_string_from_unicode:nnN {utf8/string}{#1}\l_@@_tmpa_str + \pdfannot_dict_put:nnx {widget/MK}{CA}{\l_@@_tmpa_str} + } + } + ,MK/CA .groups:n = annot + ,caption .meta:n = {MK/CA=#1} + } + +\cs_set_protected:Npn \@@_tmpa:n #1 + { + \keys_define:nn { pdffield } + { + MK/#1 .code:n = + { + \tl_if_empty:nTF {##1} { - \pdfdict_put:nnn {l_@@/checkbox/annot/AP} - {D} - { - << - /Yes ~ \pdfxform_ref:n { @@_#1/Yes} - /Off ~ \pdfxform_ref:n { @@_#1/Off} - >> - } + \pdfannot_dict_remove:nn { widget/AP }{#1} } { - \msg_warning:nnnn{pdffield}{appearance-missing}{#1}{down} + \pdfannot_dict_put:nnx {widget/MK}{#1}{##1} } - } - }, + } + ,MK/#1 .groups:n = annot + } + } + +\clist_map_inline:nn {RC,AC,I,RI,IX,IF,TP} + { \@@_tmpa:n {#1} } +% \end{macrocode} +% Flags. +% \begin{macrocode} +\keys_define:nn { pdffield } + { + ,setF .code:n = + { + \clist_map_inline:nn {#1} + { + \bitset_set_true:Nn \l_@@_F_bitset {##1} + } + } + ,setF .groups:n = annot + ,setannotflags .meta:nn = + { pdffield }{setF={#1}} + ,setannotflags .groups:n = annot + ,unsetF .multichoice: + ,unsetF / all .code:n = { \bitset_clear:N \l_@@_F_bitset} + ,unsetF / unknown .code:n = + { + \bitset_set_false:Nn \l_@@_F_bitset {#1} + } + ,unsetF .groups:n = annot + ,unsetannotflags .meta:nn = + { pdffield }{unsetF= {#1} } + ,unsetannotflags .groups:n = annot } + % \end{macrocode} % -% Keys for the AA dictionary. They all trigger javascript option. -% \begin{macro}{\@@_define_AAaction_key:nnn} +% Keys for the AA dictionary. They all trigger a javascript option. +% Fo = onfocus, Bl = onblur, D = onmousedown, U = onmouseup, +% E = onenter, X = onexit, PO = pageopen, PC = pageclose, +% PV = pagevisible, PI = pageinvisible % \begin{macrocode} -\pdfdict_new:n {l_@@/checkbox/annot/AA} -\pdfdict_new:n {l_@@/checkbox/field/AA} - -\cs_new_protected:Npn \@@_define_AAaction_key:nnn #1 #2 #3 %#1 key, #2 pdf, #3 dict +\cs_set_protected:Npn \@@_tmpa:n #1 % { - \keys_define:nn { pdffield / checkbox } + \keys_define:nn { pdffield } { - #1 .code:n = + AA/#1 .code:n = { - \pdf_string_from_unicode:nnN {utf8/string}{##1}\l_@@_tmpa_str + \pdf_string_from_unicode:nnN {utf8/string-raw}{##1}\l_@@_tmpa_str \str_if_empty:NTF \l_@@_tmpa_str { - \pdfdict_remove:nn {l_@@/checkbox/#3/AA}{#2} + \pdfannot_dict_remove:nn {widget/AA}{#1} } { - \pdfdict_put:nnx {l_@@/checkbox/#3/AA} - {#2} - {<>} + \pdfannot_dict_put:nnx {widget/AA} + {#1} + {<>} } }, - #1 .groups:n = {#3} + ,AA/#1 .groups:n = annot + } + } + +\clist_map_inline:nn {Fo,Bl,D,U,E,X,PO,PC,PV,PI}{\@@_tmpa:n{#1}} + +\cs_set_protected:Npn \@@_tmpa:nn #1 #2 + { + \keys_define:nn { pdffield } + { + #1 .meta:nn = + { pdffield }{AA/#2={##1}}, + #1 .groups:n = {annot} } } -\@@_define_AAaction_key:nnn {keystroke}{K}{field} -\@@_define_AAaction_key:nnn {format} {F}{field} -\@@_define_AAaction_key:nnn {validate} {V}{field} -\@@_define_AAaction_key:nnn {calculate}{C}{field} -\@@_define_AAaction_key:nnn {onfocus} {Fo}{annot} -\@@_define_AAaction_key:nnn {onblur} {Bl}{annot} -\@@_define_AAaction_key:nnn {onmousedown}{D}{annot} -\@@_define_AAaction_key:nnn {onmouseup}{U}{annot} -\@@_define_AAaction_key:nnn {onenter} {E}{annot} -\@@_define_AAaction_key:nnn {onexit} {X}{annot} +\@@_tmpa:nn {onfocus} {Fo} +\@@_tmpa:nn {onblur} {Bl} +\@@_tmpa:nn {onmousedown}{D} +\@@_tmpa:nn {onmouseup}{U} +\@@_tmpa:nn {onenter} {E} +\@@_tmpa:nn {onexit} {X} +% \end{macrocode} +% \subsection{Appearances} +% \begin{macro}{\pdffield_appearance:nn} +% \begin{macrocode} +\cs_new_protected:Npn \pdffield_appearance:nn #1 #2 + { + \pdfxform_new:nnn {#1}{}{#2} + } + +\cs_set_eq:NN \pdffield_store_appearance:nn\pdffield_appearance:nn % \end{macrocode} % \end{macro} -% \subsection{user commands} -% \begin{macro}{\pdffield_checkbox:n,\pdffield_setup:nn} +% \subsection{Setup command} +% % \begin{macrocode} -\cs_set_eq:NN \pdffield_checkbox:n \@@_checkbox_add:n +\keys_define:nn { pdffield / setup } + { + ,create-style .code:n = { \@@_style_create:nn #1 } + ,preset-checkbox .code:n = + { + \keys_define:nn { pdffield } + { + @@/preset/checkbox .meta:n = {#1}, + } + } + ,preset-textfield .code:n = + { + \keys_define:nn { pdffield } + { + @@/preset/textfield .meta:n = {#1}, + } + } + } +\keys_set:nn{ pdffield / setup }{preset-checkbox={}} +\keys_set:nn{ pdffield / setup }{preset-textfield={}} -\cs_new_protected:Npn \pdffield_setup:nn #1 #2 - { - \keys_set:nn {pdffield / #1 } {#2} - } +\cs_new_protected:Npn \@@_style_create:nn #1#2 + { + \keys_define:nn { pdffield } + { + @@/style/#1 .meta:n = {#2}, + } + } + + +\cs_new_protected:Npn \pdffield_setup:n #1 + { + \keys_set:nn{ pdffield / setup }{#1} + } + +\keys_define:nn { pdffield } + { + style .code:n = {\keys_set:nn {pdffield}{@@/style/#1={#1}}} + } +% \end{macrocode} +% \begin{macrocode} % % \end{macrocode} -% \end{macro} %\end{implementation} - -\endinput% -%%%% -% -%Field dict -%Ft : /Btn /Tx /Ch /Sig -%Parent : OR -%Kids: array, other fields or annot/widget -%T: partial fieldname (test string) -%TU: alternate description (test string) -%TM: mapping name -%Q integer (variable text field) -%Ff: flags ->pdffield/checkbox/field -%V: value % not pushbutton -%DV: default value % not pushbutton -%AA: Action dict ... -> see below -%Opt: array of strings, connected to kids -% or for choices, choices -%TI integer (lists) -%I array Ch (complicated ...) -% -%/DA ( 0 0 1 rg /Ti 12 Tf ) %text field -%/MaxLen %text field -% -%Lock dict (Sig) -%SV dict (Sig) -% -% -% -% -%Connected widget: -%/AS default appearance from AP ( here/Yes or /Off) -%% Appearance -%%checkbox -%/AP <>>> -%/C / Border /BS -% -%/OC ? -%/Structparens? -%/F flags -% -% -%AA: Submit: -% /S /SubmitForm -% /F file /URI (/F ( ftp : / / www . beatles . com / Movies / AbbeyRoad . mov ) -% /Fields array -% -% /S /ImportData -% /F file -% -% /S /ResetData -% /Fields array -% -% /S /JavaScript -% /JS text string or stream -% %\pdf_flag_new:nn {annot/field/submit} %name is wrong ... -% { -% Include/Exclude = 0, -% IncludeNoValueFields = 1, -% ExportFormat = 2, -% GetMethod = 3, % if ExportFormat=0 -> =0 to -% SubmitCoordinates = 4, % if ExportFormat=0 -> =0 to -% XFDF = 5, -% IncludeAppendSaves = 6, -% IncludeAnnotations = 7, -% SubmitPDF = 8, -% CanonicalFormat = 9, -% ExclNonUserAnnots = 10, -% ExclFKey = 11, -% EmbedForm = 12 -% } -% source: %adapted from https://chat.stackexchange.com/transcript/message/54421537#54421537 +% +% \PrintIndex diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf index 0c96ffee00..903cd42c0a 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf and b/macros/latex/contrib/pdfmanagement-testphase/l3pdffield.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx index e8810f81ff..cf2176e439 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.dtx @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -262,7 +262,8 @@ % \end{syntax} % This commands embeds the file \meta{source filename} in the PDF, % and creates a |/Filespec| dictionary object named \meta{object name}. -% The object name must be unique. +% The object name must be unique, it should start with the module name, so +% e.g. \texttt{module/name}. % The command uses the content of the local % dictionaries |l_pdffile|, |l_pdffile/Params| and |l_pdffile/Filespec| % to setup the dictionary entries of the stream object and the @@ -360,12 +361,12 @@ % \l_tmpa_str % \pdfdict_put:nnx {l_pdffile/Filespec} {Desc}{\l_tmpa_str} % %embeds testinput.txt and calls it grüße.txt -% \pdffile_embed_file:nnn {testinput.txt}{grüße.txt}{file:example1} +% \pdffile_embed_file:nnn {testinput.txt}{grüße.txt}{mymodule/example1} % %reference it in the panel % \pdfmanagement_add:nnx % {Catalog/Names} % {EmbeddedFiles} -% {\pdf_object_ref:n{file:example1}} +% {\pdf_object_ref:n{mymodule/example1}} % \group_end: % \end{verbatim} % \end{documentation} @@ -376,7 +377,7 @@ % % \begin{macrocode} %<*header> -\ProvidesExplPackage{l3pdffile}{2021-03-17}{0.95c} +\ProvidesExplPackage{l3pdffile}{2021-05-14}{0.95d} {embedding and referencing files in PDF---LaTeX PDF management testphase bundle} \RequirePackage{l3pdftools} %temporarly!! % @@ -456,6 +457,7 @@ ,.tex = text/plain %or application/x-tex, not in iana.org list ,.txt = text/plain ,.sty = text/plain + ,.xml = text/xml } % \end{macrocode} % \begin{variable} @@ -618,7 +620,6 @@ \msg_error:nn {pdffile}{target-name-missing} } { - \pdf_object_new:nn { #1 } {dict} \group_begin: \@@_filename_convert_to_print:nN { #2 } \l_@@_tmpa_str \pdfdict_put:nnx {l_pdffile/Filespec}{F} { \l_@@_tmpa_str } @@ -638,7 +639,7 @@ %#1 {source filename} %#2 {target filename} -%#3 { filespec object name } (will internally get a prefix!) +%#3 { filespec object name } (will internally get a prefix! ??) \cs_new_protected:Npn \pdffile_embed_file:nnn #1 #2 #3 { % if #1 empty => only filespec % if #2 empty => = #1 @@ -681,6 +682,7 @@ } \tl_if_blank:nTF { #2 } { + \pdf_object_new:nn { #3 } {dict} \exp_args:Nnnx \@@_filespec_write:nnn %#1 dict, #2 target file name, #3 object ref @@ -689,6 +691,7 @@ {\l_@@_embed_ref_tl} } { + \pdf_object_new:nn { #3 } {dict} \exp_args:Nnnx \@@_filespec_write:nnn %#1 dict, #2 target file name, #3 object ref @@ -722,6 +725,7 @@ { #1 } \l_@@_automimetype_tl \tl_set:Nx \l_@@_embed_ref_tl { \pdf_object_ref_last: } + \pdf_object_new:nn { #3 } {dict} \exp_args:Nnxx \@@_filespec_write:nnn %#1 dict, #2 target file name, #3 object ref diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf index f93e47b28d..b9b9a92b26 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf and b/macros/latex/contrib/pdfmanagement-testphase/l3pdffile.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx index e22600ea5b..9383c03290 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.dtx @@ -61,7 +61,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -517,9 +517,9 @@ % The value is an object reference. It is sensible to declare the object % first. E.g. % \begin{verbatim} -% \pdf_object_new:nn {pkg@intent}{dict} -% \pdf_object_write:nn {pkg@intent}{...} -% \pdfmanagement_add:nnx {Catalog} {OutputIntents}{\pdf_object_ref:n {pkg@intent}} +% \pdf_object_new:nn {module/intent}{dict} +% \pdf_object_write:nn {module/intent}{...} +% \pdfmanagement_add:nnx {Catalog} {OutputIntents}{\pdf_object_ref:n {module/intent}} % \end{verbatim} % % or @@ -557,7 +557,7 @@ %<@@=pdfmanagement> %<*header> % -\ProvidesExplPackage{l3pdfmanagement}{2021-03-17}{0.95c} +\ProvidesExplPackage{l3pdfmanagement}{2021-05-14}{0.95d} {Management of core PDF dictionaries (LaTeX PDF management testphase bundle)} % % \end{macrocode} @@ -1115,15 +1115,15 @@ \prop_if_empty:cF { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/AA } } { - \__pdf_backend_object_new:nn { g_@@_/Catalog/AA_obj } { dict } + \__pdf_backend_object_new:nn { @@/Catalog/AA } { dict } \__pdf_backend_object_write:nx - { g_@@_/Catalog/AA_obj } + { @@/Catalog/AA } { \pdfdict_use:n { g__pdf_Core/Catalog/AA } } \exp_args:Nnx \__pdf_backend_catalog_gput:nn {AA} { - \__pdf_backend_object_ref:n { g_@@_/Catalog/AA_obj } + \__pdf_backend_object_ref:n { @@/Catalog/AA } } } } @@ -1145,67 +1145,67 @@ { \seq_if_empty:cF { g_@@_/Catalog/AcroForm/Fields_seq } { - \__pdf_backend_object_new:nn { g_@@_/Catalog/AcroForm/Fields_obj } { array } + \__pdf_backend_object_new:nn { @@/Catalog/AcroForm/Fields } { array } \__pdf_backend_object_write:nx - { g_@@_/Catalog/AcroForm/Fields_obj } + { @@/Catalog/AcroForm/Fields } { \seq_use:cn { g_@@_/Catalog/AcroForm/Fields_seq } {~} } \exp_args:Nnnx \prop_gput:cnn %we have to use \prop here to avoid the handler ... { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/AcroForm } } { Fields } - { \__pdf_backend_object_ref:n { g_@@_/Catalog/AcroForm/Fields_obj } } + { \__pdf_backend_object_ref:n { @@/Catalog/AcroForm/Fields } } } \seq_if_empty:cF { g_@@_/Catalog/AcroForm/CO_seq } { - \__pdf_backend_object_new:nn { g_@@_/Catalog/AcroForm/CO_obj } { array } + \__pdf_backend_object_new:nn { @@/Catalog/AcroForm/CO } { array } \exp_args:Nnx \__pdf_backend_object_write:nn - { g_@@_/Catalog/AcroForm/CO_obj } + { @@/Catalog/AcroForm/CO } { \seq_use:cn { g_@@_/Catalog/AcroForm/CO_seq } {~} } \exp_args:Nnnx \prop_gput:cnn %we have to use \prop here to avoid the handler ... { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/AcroForm } } { CO } - { \__pdf_backend_object_ref:n { g_@@_/Catalog/AcroForm/CO_obj } } + { \__pdf_backend_object_ref:n { @@/Catalog/AcroForm/CO } } } \prop_if_empty:cF { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/AcroForm/DR/Font}} { - \__pdf_backend_object_new:nn { g_@@_/Catalog/AcroForm/DR/Font_obj } {dict} + \__pdf_backend_object_new:nn { @@/Catalog/AcroForm/DR/Font } {dict} \exp_args:Nnx \__pdf_backend_object_write:nn - { g_@@_/Catalog/AcroForm/DR/Font_obj } + { @@/Catalog/AcroForm/DR/Font } { \pdfdict_use:n { g__pdf_Core/Catalog/AcroForm/DR/Font } } \exp_args:Nnnx \prop_gput:cnn %we have to use \prop here to avoid the handler ... { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/AcroForm/DR } } { Font } - { \__pdf_backend_object_ref:n { g_@@_/Catalog/AcroForm/DR/Font_obj } } + { \__pdf_backend_object_ref:n { @@/Catalog/AcroForm/DR/Font } } } \prop_if_empty:cF { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/AcroForm/DR}} { - \__pdf_backend_object_new:nn { g_@@_/Catalog/AcroForm/DR_obj } {dict} + \__pdf_backend_object_new:nn { @@/Catalog/AcroForm/DR } {dict} \exp_args:Nnx \__pdf_backend_object_write:nn - { g_@@_/Catalog/AcroForm/DR_obj } + { @@/Catalog/AcroForm/DR } { \pdfdict_use:n { g__pdf_Core/Catalog/AcroForm/DR } } \exp_args:Nnnx \prop_gput:cnn %we have to use \prop here to avoid the handler ... { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/AcroForm } } { DR } - { \__pdf_backend_object_ref:n { g_@@_/Catalog/AcroForm/DR_obj } } + { \__pdf_backend_object_ref:n { @@/Catalog/AcroForm/DR } } } \prop_if_empty:cF { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/AcroForm} } { - \__pdf_backend_object_new:nn { g_@@_/Catalog/AcroForm_obj } {dict} + \__pdf_backend_object_new:nn { @@/Catalog/AcroForm } {dict} \exp_args:Nnx \__pdf_backend_object_write:nn - { g_@@_/Catalog/AcroForm_obj } + { @@/Catalog/AcroForm } { \pdfdict_use:n { g__pdf_Core/Catalog/AcroForm } } \exp_args:Nnnx \@@_handler_gput:nnn { Catalog } { AcroForm } - { \__pdf_backend_object_ref:n { g_@@_/Catalog/AcroForm_obj } } + { \__pdf_backend_object_ref:n { @@/Catalog/AcroForm } } } } @@ -1221,16 +1221,16 @@ \seq_if_empty:cF { g_@@_/Catalog/AF_seq } { - \__pdf_backend_object_new:nn { g_@@_/Catalog/AF_obj } { array } + \__pdf_backend_object_new:nn { @@/Catalog/AF } { array } \exp_args:Nnx \__pdf_backend_object_write:nn - { g_@@_/Catalog/AF_obj } + { @@/Catalog/AF } { \seq_use:cn { g_@@_/Catalog/AF_seq } {~} } \exp_args:Nnx \__pdf_backend_catalog_gput:nn {AF} { - \__pdf_backend_object_ref:n {g_@@_/Catalog/AF_obj} + \__pdf_backend_object_ref:n {@@/Catalog/AF} } } } @@ -1245,16 +1245,16 @@ \prop_if_empty:cF { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/MarkInfo } } { - \__pdf_backend_object_new:nn { g_@@_/Catalog/MarkInfo_obj } { dict } + \__pdf_backend_object_new:nn { @@/Catalog/MarkInfo } { dict } \exp_args:Nnx \__pdf_backend_object_write:nn - { g_@@_/Catalog/MarkInfo_obj } + { @@/Catalog/MarkInfo } { \pdfdict_use:n { g__pdf_Core/Catalog/MarkInfo } } \exp_args:Nnx \__pdf_backend_catalog_gput:nn {MarkInfo} { - \__pdf_backend_object_ref:n {g_@@_/Catalog/MarkInfo_obj} + \__pdf_backend_object_ref:n {@@/Catalog/MarkInfo} } } } @@ -1286,10 +1286,10 @@ > { 0 } { - \__pdf_backend_object_new:nn { g_@@_/Catalog/OCProperties_obj } { dict } + \__pdf_backend_object_new:nn { @@/Catalog/OCProperties } { dict } \seq_gpop_left:cN { g_@@_/Catalog/OCProperties/Configs_seq} \l_tmpa_tl \exp_args:Nnx - \__pdf_backend_object_write:nn {g_@@_/Catalog/OCProperties_obj} + \__pdf_backend_object_write:nn {@@/Catalog/OCProperties} { /OCGs~[ \seq_use:cn { g_@@_/Catalog/OCProperties/OCGs_seq } {~} ] /D~\l_tmpa_tl~ @@ -1302,7 +1302,7 @@ \exp_args:Nnx \__pdf_backend_catalog_gput:nn { OCProperties } - { \__pdf_backend_object_ref:n {g_@@_/Catalog/OCProperties_obj} } + { \__pdf_backend_object_ref:n {@@/Catalog/OCProperties} } } } % \end{macrocode} @@ -1317,16 +1317,16 @@ \seq_if_empty:cF { g_@@_/Catalog/OutputIntents_seq } { - \__pdf_backend_object_new:nn { g_@@_/Catalog/OutputIntents_obj } { array } + \__pdf_backend_object_new:nn { @@/Catalog/OutputIntents } { array } \exp_args:Nnx \__pdf_backend_object_write:nn - { g_@@_/Catalog/OutputIntents_obj } + { @@/Catalog/OutputIntents } { \seq_use:cn { g_@@_/Catalog/OutputIntents_seq } {~} } \exp_args:Nnx \__pdf_backend_catalog_gput:nn {OutputIntents} { - \__pdf_backend_object_ref:n {g_@@_/Catalog/OutputIntents_obj} + \__pdf_backend_object_ref:n {@@/Catalog/OutputIntents} } } } @@ -1342,16 +1342,16 @@ \seq_if_empty:cF { g_@@_/Catalog/Requirements_seq } { - \__pdf_backend_object_new:nn { g_@@_/Catalog/Requirements_obj } { array } + \__pdf_backend_object_new:nn { @@/Catalog/Requirements } { array } \exp_args:Nnx \__pdf_backend_object_write:nn - { g_@@_/Catalog/Requirements_obj } + { @@/Catalog/Requirements } { \seq_use:cn { g_@@_/Catalog/Requirements_seq } {~} } \exp_args:Nnx \__pdf_backend_catalog_gput:nn {Requirements} { - \__pdf_backend_object_ref:n { g_@@_/Catalog/Requirements_obj } + \__pdf_backend_object_ref:n { @@/Catalog/Requirements } } } } @@ -1367,16 +1367,16 @@ \prop_if_empty:cF { \__kernel_pdfdict_name:n { g__pdf_Core/Catalog/ViewerPreferences } } { - \__pdf_backend_object_new:nn { g_@@_/Catalog/ViewerPreferences_obj } { dict } + \__pdf_backend_object_new:nn { @@/Catalog/ViewerPreferences } { dict } \exp_args:Nnx \__pdf_backend_object_write:nn - { g_@@_/Catalog/ViewerPreferences_obj } + { @@/Catalog/ViewerPreferences } { \pdfdict_use:n { g__pdf_Core/Catalog/ViewerPreferences } } \exp_args:Nnx \__pdf_backend_catalog_gput:nn {ViewerPreferences} { - \__pdf_backend_object_ref:n {g_@@_/Catalog/ViewerPreferences_obj} + \__pdf_backend_object_ref:n {@@/Catalog/ViewerPreferences} } } } diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf index 92e9fe605e..b35c3a3a4d 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf and b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmanagement.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx index 2b48f0646c..44ea8a9191 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.dtx @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -340,7 +340,7 @@ % \begin{macrocode} %<@@=pdfmeta> %<*header> -\ProvidesExplPackage{l3pdfmeta}{2021-03-17}{0.95c} +\ProvidesExplPackage{l3pdfmeta}{2021-05-14}{0.95d} {PDF-Standards---LaTeX PDF management testphase bundle} % % \end{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf index f41e8f553f..7b8fdcea93 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf and b/macros/latex/contrib/pdfmanagement-testphase/l3pdfmeta.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx index 60d60d184e..76368fc475 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.dtx @@ -53,7 +53,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -198,9 +198,9 @@ % It should be on the same page as the bdc-command. % % \begin{verbatim} -% \pdf_object_new:nn {objA}{dict} -% \pdf_object_write:nn {objA}{/Type/Artifact} -% \pdf_bdc:nn {Span}{objA} +% \pdf_object_new:nn {module/objA}{dict} +% \pdf_object_write:nn {module/objA}{/Type/Artifact} +% \pdf_bdc:nn {Span}{module/objA} % text % \pdf_emc: % \end{verbatim} @@ -215,7 +215,7 @@ % % \begin{macrocode} %<*header> -\ProvidesExplPackage{l3pdftools}{2021-03-17}{0.95c} +\ProvidesExplPackage{l3pdftools}{2021-05-14}{0.95d} {candidate commands for l3pdf---LaTeX PDF management testphase bundle} % % \end{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf index ed1f4381e4..4df0731176 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf and b/macros/latex/contrib/pdfmanagement-testphase/l3pdftools.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx index f0fcda4aab..25465bdcb0 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.dtx @@ -52,7 +52,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -133,7 +133,7 @@ % \begin{macrocode} %<@@=pdf> %<*header> -\ProvidesExplPackage{l3pdfxform}{2021-03-17}{0.95c} +\ProvidesExplPackage{l3pdfxform}{2021-05-14}{0.95d} {command to create xforms (beta)---LaTeX PDF management testphase bundle} % % \end{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf index 8b0acbedcf..8ff3c6f2d5 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf and b/macros/latex/contrib/pdfmanagement-testphase/l3pdfxform.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx index fec2da64ba..4d6974eefe 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.dtx @@ -51,7 +51,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -164,7 +164,7 @@ % \begin{macrocode} %<@@=pdfmanagement> %<*header> -\ProvidesExplPackage{ltdocinit}{2021-03-17}{0.95c} +\ProvidesExplPackage{ltdocinit}{2021-05-14}{0.95d} {Initialize document metadata} % % \end{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf index 81e648525e..a7138a39fc 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf and b/macros/latex/contrib/pdfmanagement-testphase/ltdocinit.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty index d43c363fe5..43ac3a7ce9 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty +++ b/macros/latex/contrib/pdfmanagement-testphase/pdflscape-ltx.sty @@ -22,7 +22,7 @@ %% This work consists of the main source file pdflscape-ltx.sty %% \NeedsTeXFormat{LaTeX2e} -\ProvidesExplPackage{pdflscape-ltx}{2021-03-17}{0.95c} +\ProvidesExplPackage{pdflscape-ltx}{2021-05-14}{0.95d} {Display of landscape pages in PDF - adaption of pdflscape to the PDFmanagement bundle (testphase)} \RequirePackage{lscape} diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx index 54fb0ffa10..647fd55f93 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.dtx @@ -51,7 +51,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -67,7 +67,7 @@ % |firstaidoff={name1,name2,...}|. % \begin{macrocode} %<*package> -\ProvidesExplPackage{pdfmanagement-firstaid}{2021-03-17}{0.95c} +\ProvidesExplPackage{pdfmanagement-firstaid}{2021-05-14}{0.95d} {LaTeX PDF management testphase bundle / firstaid-patches} %<@@=pdfmanagement> @@ -192,9 +192,9 @@ %objects are already created ... \def\pgf@sys@pdf@possible@resources { - /ColorSpace~\pdf_object_ref:n {Page/Resources/ColorSpace} - /Pattern ~\pdf_object_ref:n {Page/Resources/Pattern} - /ExtGState ~\pdf_object_ref:n {Page/Resources/ExtGState} + /ColorSpace~\pdf_object_ref:n {__pdf/Page/Resources/ColorSpace} + /Pattern ~\pdf_object_ref:n {__pdf/Page/Resources/Pattern} + /ExtGState ~\pdf_object_ref:n {__pdf/Page/Resources/ExtGState} } \let\pgf@sys@pdf@check@resources=\relax% %not sure if needed, but perhaps the lists are used somewhere else ... @@ -227,24 +227,22 @@ } \cs_generate_variant:Nn \tl_trim_spaces:n{V} -\cs_generate_variant:Nn \__pdf_backend_PageResources_gput:nnn {nex} +\cs_generate_variant:Nn \pdfmanagement_add:nnn {nex} \cs_new:Npn \@@_patch_pgfextgs:w #1/#2<<#3>>#4\q_stop { \tl_set:Nx\l_tmpa_tl{#2} - \__pdf_backend_PageResources_gput:nex - {ExtGState}{\tl_trim_spaces:V\l_tmpa_tl}{<<#3 #4>>} + \pdfmanagement_add:nex + {Page/Resources/ExtGState}{\tl_trim_spaces:V\l_tmpa_tl}{<<#3 #4>>} } \cs_new:Npn \@@_patch_pgfpatterns:w #1/#2\space#3\q_stop { - \exp_args:Nnxx - \__pdf_backend_PageResources_gput:nnn - {Pattern}{\tl_trim_spaces:n{#2}}{#3} + \pdfmanagement_add:nex + {Page/Resources/Pattern}{\tl_trim_spaces:n{#2}}{#3} } \cs_new:Npn \@@_patch_pgfcolorspaces:w #1/#2[#3]#4\q_stop { - \exp_args:Nne - \__pdf_backend_PageResources_gput:nnn - {ColorSpace}{\tl_trim_spaces:n{#2}}{[#3]} + \pdfmanagement_add:nex + {Page/Resources/ColorSpace}{\tl_trim_spaces:n{#2}}{[#3]} } % \end{macrocode} diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf index d702eae143..41b232b735 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf and b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-firstaid.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx index 8cee17982e..82dc047ada 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx +++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.dtx @@ -51,7 +51,7 @@ % }^^A % } % -% \date{Version 0.95c, released 2021-03-17} +% \date{Version 0.95d, released 2021-05-14} % % \maketitle % \begin{documentation} @@ -384,7 +384,7 @@ % \begin{macrocode} %<@@=pdf> %<*package> -\ProvidesExplPackage{pdfmanagement-testphase}{2021-03-17}{0.95c} +\ProvidesExplPackage{pdfmanagement-testphase}{2021-05-14}{0.95d} {LaTeX PDF management testphase bundle} \providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} \IfFormatAtLeastTF{2020-10-01}{}{ @@ -411,7 +411,7 @@ % to allow to set it in the document. % \begin{macrocode} %<*header> -\ProvidesExplFile{pdfmanagement-testphase.ltx}{2021-03-17}{0.95c} +\ProvidesExplFile{pdfmanagement-testphase.ltx}{2021-05-14}{0.95d} {PDF~management~code~(testphase)} % %<*package> diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.ins b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.ins index 87ac62f1b0..97db2f066e 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.ins +++ b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.ins @@ -128,6 +128,8 @@ and all files in that bundle must be distributed together. \file{l3pdffield-testphase.sty} {% \from{l3pdffield.dtx}{package} + \from{l3pdffield-checkbox.dtx}{package} + \from{l3pdffield-textfield.dtx}{package} }% } diff --git a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf index cc1239e23a..2d1700dd49 100644 Binary files a/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf and b/macros/latex/contrib/pdfmanagement-testphase/pdfmanagement-testphase.pdf differ diff --git a/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty index 8d5abb7e2a..4b4030c4b2 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty +++ b/macros/latex/contrib/pdfmanagement-testphase/transparent-ltx.sty @@ -3,7 +3,7 @@ %% a replacement for transparent sty from Heiko Oberdiek %% \NeedsTeXFormat{LaTeX2e}[2020/10/01] -\ProvidesExplPackage{transparent-ltx}{2021-03-17}{0.95c} +\ProvidesExplPackage{transparent-ltx}{2021-05-14}{0.95d} {Transparency with color stacks (replacement for transparent.sty from Heiko Oberdiek)}% \RequirePackage{l3opacity} diff --git a/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty b/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty index aec0fbb632..76aee08fef 100644 --- a/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty +++ b/macros/latex/contrib/pdfmanagement-testphase/xcolor-patches-tmp-ltx.sty @@ -1,26 +1,44 @@ %% LaTeX2e file `xcolor-patches.sty' %% -\ProvidesPackage{xcolor-patches-tmp-ltx}[2021-03-17 v0.95c patch xcolor for l3color] +\ProvidesPackage{xcolor-patches-tmp-ltx}[2021-05-14 v0.95d patch xcolor for l3color] \@ifundefined{color_set:nn}{\RequirePackage{l3color}}{} \ExplSyntaxOn -\cs_gset_protected:Npn \@expl@xcolor@set@@nnn #1 #2 #3 +% #1 is the color name +% #2: model or models +% #3: value: either numbers or a color name +% #4 is the type: named or ps +\cs_gset_protected:Npn \@expl@xcolor@set@@nnnn #1 #2 #3 #4 { - \cs_if_exist:cTF { __color_parse_model_ #2 :w } - { - \color_set:nnn {#1}{#2}{#3} - } - { - \tl_if_eq:nnTF{#2}{named} - { - \color_set:nn{#1}{#3} - } - { - %this is for multi models, it will break if there is model - %l3 doesn't know, but the case is rare, so accept it for now. - \color_set:nnn{#1}{#2}{#3} - } - } + \str_case:nnF {#4} + { + % we ignore the ps type for now. + {ps}{} + {named} + { + \cs_if_exist:cT { __color_parse_model_ #2 :w } + { + \color_set:nnn {#1}{#2}{#3} + } + } + } + { + \cs_if_exist:cTF { __color_parse_model_ #2 :w } + { + \color_set:nnn {#1}{#2}{#3} + } + { + \tl_if_eq:nnTF{#2}{named}%this the model not the type! + { + \color_set:nn{#1}{#3} + } + { + %this is for multi models, it will break if there is model + %l3 doesn't know, but the case is rare, so accept it for now. + \color_set:nnn{#1}{#2}{#3} + } + } + } } \cs_generate_variant:Nn \color_set:nn {ne} \cs_new_protected:Npn \@expl@xcolor@set@@ne #1 #2 @@ -58,7 +76,7 @@ %\pretocmd{\XC@definec@lor}{\@expl@color@set@@nnn{#2}{#4}{#5}}{}{\fail} \def\XC@definec@lor[#1]#2[#3]#4#5% - {\@expl@xcolor@set@@nnn{#2}{#4}{#5}% + {\@expl@xcolor@set@@nnnn{#2}{#4}{#5}{#1}% \begingroup \XC@sdef\@@cls{#1}\XC@edef\@@nam{#2}\edef\colornameprefix{#3}% \XC@logdef\@@nam -- cgit v1.2.3