% \iffalse meta-comment % %% File: pdfcomment.dtx (C) Copyright 2026 Ulrike Fischer, 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 % % https://www.latex-project.org/lppl.txt % % % The pdfcomment is developed at % % https://github.com/LaTeX-Package-Repositories/pdfcomment % %<*driver> \DocumentMetadata{tagging=on,pdfstandard=ua-2} \documentclass{l3in2edoc} \EnableCrossrefs \CodelineIndex \begin{document} \DocInput{pdfcomment.dtx} \end{document} % % % \fi % % \title{The \textsf{pdfcomment} package} % \author{Ulrike Fischer, \LaTeX{} Project\thanks{Initial implementation done by Josef Kleber}} % \date{v3.0a 2026-06-12} % % \maketitle % % \section{Implementation} % % \begin{macrocode} %<*package> % \end{macrocode} % \begin{macrocode} \ProvidesExplPackage {pdfcomment} {2026-06-12} {3.0a} {PDF annotations and comments} \IfPDFManagementActiveF{\RequirePackageWithOptions{pdfcomment-2018-11-01}} \IfPDFManagementActiveF{\endinput} \RequirePackage{hyperref} % \end{macrocode} %\subsection{Variables} % Default values. The commands use \texttt{goptd}. % \begin{macrocode} \gdef\pc@goptd@subject{} \gdef\pc@goptd@color{0~0~1} \gdef\pc@goptd@author{} \gdef\pc@goptd@deadline{} \gdef\pc@goptd@icon{Comment} \gdef\pc@goptd@open{false} \gdef\pc@goptd@hspace{0pt} \gdef\pc@goptd@voffset{0pt} \gdef\pc@goptd@hoffset{0pt} \gdef\pc@goptd@width{0pt} \gdef\pc@goptd@height{0pt} \gdef\pc@goptd@depth{0pt} \gdef\pc@goptd@opacity{1.0} \gdef\pc@goptd@markup{Highlight} \gdef\pc@goptd@font{Helv} \gdef\pc@goptd@fontsize{12bp} \gdef\pc@goptd@fontcolor{0.0~0.0~0.0} \gdef\pc@goptd@justification{0} \gdef\pc@goptd@borderstyle{S} \gdef\pc@goptd@linewidth{1bp} \gdef\pc@goptd@dashstyle{3~3} \gdef\pc@goptd@bse{S} \gdef\pc@goptd@bsei{1} \gdef\pc@goptd@type{freetext} \gdef\pc@goptd@lineend{/OpenArrow} \gdef\pc@goptd@linebegin{/None} \gdef\pc@goptd@icolor{1~1~0} \gdef\pc@goptd@line{50~50~300~600} \gdef\pc@goptd@caption{inline} \gdef\pc@goptd@captionhoffset{0pt} \gdef\pc@goptd@captionvoffset{0pt} \gdef\pc@goptd@linesep{0.5cm} \gdef\pc@goptd@disable{false} \gdef\pc@goptd@id{} \gdef\pc@goptd@date{\c_sys_timestamp_str} \gdef\pc@goptd@timezone{+00'00'} \gdef\pc@hyenc@fontcolor{0.0~0.0~0.0} % \end{macrocode} % Variables for local command options % \begin{macrocode} \def\pc@lopt@subject{} \def\pc@lopt@color{} \def\pc@lopt@author{} \def\pc@lopt@deadline{} \def\pc@lopt@icon{} \def\pc@lopt@open{} \def\pc@lopt@hspace{} \def\pc@lopt@voffset{} \def\pc@lopt@hoffset{} \def\pc@lopt@width{} \def\pc@lopt@height{} \def\pc@lopt@depth{} \def\pc@lopt@opacity{} \def\pc@lopt@font{} \def\pc@lopt@fontsize{} \def\pc@lopt@fontcolor{} \def\pc@lopt@justification{} \def\pc@lopt@borderstyle{} \def\pc@lopt@linewidth{} \def\pc@lopt@dashstyle{} \def\pc@lopt@bse{} \def\pc@lopt@bsei{} \def\pc@lopt@type{} \def\pc@lopt@lineend{} \def\pc@lopt@linebegin{} \def\pc@lopt@icolor{} \def\pc@lopt@line{} \def\pc@lopt@caption{} \def\pc@lopt@captionhoffset{} \def\pc@lopt@captionvoffset{} \def\pc@lopt@linesep{} \def\pc@lopt@mathstyle{} \def\pc@lopt@disable{} \def\pc@lopt@id{} \def\pc@lopt@date{} \def\pc@lopt@replyto{} \def\pc@lopt@timezone{} \def\pc@lopt@subtype{/Text} % \end{macrocode} % This can probably go at some time. % \begin{macrocode} \gdef\pc@lopt@c{} \gdef\pc@lopt@ic{} \gdef\pc@lopt@cdate{} \gdef\pc@lopt@l{} \gdef\pc@lopt@le{} \gdef\pc@lopt@cap{} \gdef\pc@lopt@cp{} \gdef\pc@lopt@co{} % \end{macrocode} % Booleans % \begin{macrocode} \newif\ifpc@gopt@final\pc@gopt@finalfalse \newif\ifpc@lopt@disable\pc@lopt@disablefalse \bool_new:N \@@_lopt_printSOfinal_bool \newif\ifpc@annot@samepage\pc@annot@samepagetrue \newif\ifpc@annot@secondpage\pc@annot@secondpagefalse \newif\ifpc@ignorespaces\pc@ignorespacesfalse \newif\ifpc@firstcolumn\pc@firstcolumntrue \newif\ifpc@Sfirstcolumn\pc@Sfirstcolumntrue \newif\ifpc@Efirstcolumn\pc@Efirstcolumntrue % \end{macrocode} % A few counter % \begin{macrocode} \newcounter{pc@count@i} \newcounter{pc@count@ii} \newcounter{pc@count@iii} \newcounter{pc@count@iv} % \end{macrocode} % Temporary boxes. TODO change names % \begin{macrocode} \newbox\pc@mathannot@box% \newbox\pc@nullbox% % \end{macrocode} % Temporary lengths. % \begin{macrocode} \newlength{\pc@dima} \newlength{\pc@dimb} % \end{macrocode} % Other lengths. % \begin{macrocode} \newlength{\pc@Sposx}% \newlength{\pc@Sposy}% \newlength{\pc@Eposx}% \newlength{\pc@Eposy}% \newlength{\pc@column}% \newlength{\pc@box@width}% \newlength{\pc@box@height}% \newlength{\pc@box@depth}% % \end{macrocode} % Variables to hold the coordinate of the QuadPoints % \begin{macrocode} \newcommand{\pc@x@one}{}% \newcommand{\pc@x@two}{}% \newcommand{\pc@x@three}{}% \newcommand{\pc@x@four}{}% \newcommand{\pc@y@one}{}% \newcommand{\pc@y@two}{}% \newcommand{\pc@y@three}{}% \newcommand{\pc@y@four}{}% % \newcommand{\pc@x@left@text}{}% \newcommand{\pc@x@right@text}{}% \newcommand{\pc@y@top@text}{}% \newcommand{\pc@y@bottom@text}{}% % \gdef\pc@version{}% \gdef\pc@collect@PDFOBJID{}% % \newcommand{\pc@raggedleftmarginnote}{\centering}% \newcommand{\pc@raggedrightmarginnote}{\centering}% % \end{macrocode} % % \subsection{List of pdfcomments} % \begin{macrocode} \newcommand{\lpcname}{List~of~pdfcomments}% \gdef\pc@lpc@format{\pc@lopt@author\ -~ \pc@lopt@subject}% \gdef\pc@lopt@liststyle{AuthorSubject}% % % \end{macrocode} % % \subsection{Key definitions} % \begin{macrocode} \keys_define:nn{pdfcomment} { avatar.code:n = { \cs_if_exist_use:cF { pc@avatar@#1 } { \PackageWarning{pdfcomment}{Unknown~avatar~ #1\MessageBreak% skip~assignment}% } } } \keys_define:nn{pdfcomment} { style.code:n = { \cs_if_exist_use:cF { pc@style@#1 } { \PackageWarning{pdfcomment}{Unknown~style~ #1\MessageBreak% skip~assignment}% } } } \keys_define:nn{pdfcomment} { ,subject .tl_set:N = \pc@lopt@subject ,subject .initial:o = \pc@goptd@subject } \keys_define:nn{pdfcomment} { ,color .code:n = { \tl_if_blank:eTF {#1} {\tl_set:Nn\pc@lopt@color{}} { \HyColor@XZeroOneThreeFour{#1}{\pc@lopt@color}{pdfcomment}{color} \tl_set:Ne \pc@lopt@color {[\pc@lopt@color]} } } ,color .initial:o = \pc@goptd@color } \keys_define:nn{pdfcomment} { ,author .tl_set:N = \pc@lopt@author ,author .initial:o = \pc@goptd@author } \keys_define:nn{pdfcomment} { ,deadline .tl_set:N = \pc@lopt@deadline ,deadline .initial:o = \pc@goptd@deadline } \keys_define:nn{pdfcomment} { ,icon.code:n = {\tl_set:Nn \pc@lopt@icon {/#1}} ,icon.initial:o = \pc@goptd@icon } \keys_define:nn{pdfcomment} { ,open .choice: ,open/true .code:n = \tl_set:Nn \pc@lopt@open{true} ,open/false.code:n = \tl_set:Nn \pc@lopt@open{false} ,open.default:n = true ,open.initial:o = \pc@goptd@open } \keys_define:nn{pdfcomment} { ,hspace .tl_set:N = \pc@lopt@hspace ,hspace .value_required:n = true ,hspace .initial:o =\pc@goptd@hspace } \keys_define:nn{pdfcomment} { ,voffset .tl_set:N = \pc@lopt@voffset ,voffset .value_required:n = true ,voffset .initial:o = \pc@goptd@voffset } \keys_define:nn{pdfcomment} { ,hoffset .tl_set:N = \pc@lopt@hoffset ,hoffset .value_required:n = true ,hoffset .initial:o =\pc@goptd@hoffset } \keys_define:nn{pdfcomment} { ,width .tl_set:N = \pc@lopt@width ,width .value_required:n = true ,width .initial:o =\pc@goptd@width } \keys_define:nn{pdfcomment} { ,height .tl_set:N = \pc@lopt@height ,height .value_required:n = true ,height .initial:o =\pc@goptd@height } \keys_define:nn{pdfcomment} { ,depth .tl_set:N = \pc@lopt@depth ,depth .value_required:n = true ,depth .initial:o = \pc@goptd@depth } \keys_define:nn{pdfcomment} { ,opacity .tl_set:N = \pc@lopt@opacity ,opacity .value_required:n = true, ,opacity .initial:o = \pc@goptd@opacity } \keys_define:nn{pdfcomment} { ,markup .choices:nn = {Highlight,Underline,Squiggly,StrikeOut} { \tl_set:Nn\pc@lopt@subtype{/#1} } ,markup .initial:o = \pc@goptd@markup } \keys_define:nn{pdfcomment} { ,font .tl_set:N = \pc@lopt@font ,font .value_required:n = true ,font .initial:o = \pc@goptd@font } \keys_define:nn{pdfcomment} { ,fontsize .code:n = \tl_set:Nn \pc@lopt@fontsize {\pc@pttobp{#1}} ,fontsize .value_required:n = true ,fontsize .initial:o = \pc@goptd@fontsize } \keys_define:nn{pdfcomment} { ,fontcolor .code:n = { \tl_if_blank:eTF {#1} {\tl_set:Nn\pc@lopt@fontcolor{}} { \HyColor@XZeroOneThreeFour{#1}{\pc@hyenc@fontcolor}{pdfcomment}{color} } } ,fontcolor .value_required:n = true ,fontcolor .initial:o = \pc@goptd@fontcolor } \keys_define:nn{pdfcomment} { ,justification .choices:nn = {left,center,right} {\tl_set:Ne\pc@lopt@justification{\int_eval:n{\l_keys_choice_int-1}}}, ,justification .value_required:n = true, ,justification .initial:n = left %!!!default command can not used } \keys_define:nn{pdfcomment} { ,borderstyle .choice: ,borderstyle/solid .code:n = \tl_set:Nn \pc@lopt@borderstyle {S} ,borderstyle/dashed.code:n = \tl_set:Nn \pc@lopt@borderstyle {D} ,borderstyle .initial:n = solid %default command can not used } \keys_define:nn{pdfcomment} { ,dashstyle .tl_set:N = \pc@lopt@dashstyle ,dashstyle .value_required:n = true ,dashstyle .initial:o = \pc@goptd@dashstyle } \keys_define:nn{pdfcomment} { ,linewidth .code:n = {\tl_set:Nn\pc@lopt@linewidth {\pc@pttobp{#1}}} ,linewidth .value_required:n = true ,linewidth .initial:o = \pc@goptd@linewidth } \keys_define:nn{pdfcomment} { ,bse .choice: ,bse/none .code:n = {\tl_set:Nn\pc@lopt@bse{S}} ,bse/cloudy.code:n = {\tl_set:Nn\pc@lopt@bse{C}} ,bse .initial:n = none } \keys_define:nn{pdfcomment} { ,bsei .tl_set:N = \pc@lopt@bsei ,bsei .value_required:n = true ,bsei .initial:o = \pc@goptd@bsei } \keys_define:nn{pdfcomment} { ,type.choice: ,type/freetext .code:n = \tl_set:Nn\pc@lopt@type{} ,type/callout .code:n = \tl_set:Nn\pc@lopt@type{/FreeTextCallout} ,type/typewriter .code:n = \tl_set:Nn\pc@lopt@type{/FreeTextTypewriter} ,type/line .code:n = \tl_set:Nn\pc@lopt@type{/Line}\tl_set:Nn\pc@lopt@subtype{/Line} ,type/polyline .code:n = \tl_set:Nn\pc@lopt@type{/PolyLine}\tl_set:Nn\pc@lopt@subtype{/PolyLine} ,type/polygon .code:n = \tl_set:Nn\pc@lopt@type{/Polygon}\tl_set:Nn\pc@lopt@subtype{/Polygon} ,type .initial:n = freetext } \keys_define:nn{pdfcomment} { ,lineend .tl_set:N = \pc@lopt@lineend ,lineend .value_required:n = true ,lineend .initial:o = \pc@goptd@lineend } \keys_define:nn{pdfcomment} { ,linebegin .tl_set:N = \pc@lopt@linebegin ,linebegin .value_required:n = true ,linebegin .initial:o = \pc@goptd@linebegin } \keys_define:nn{pdfcomment} { ,icolor .code:n = { \tl_if_blank:eTF {#1} {\tl_set:Nn\pc@lopt@icolor{}} { \HyColor@XZeroOneThreeFour{#1}{\pc@lopt@icolor}{pdfcomment}{color} \tl_set:Ne \pc@lopt@icolor {[\pc@lopt@icolor]} } } ,icolor .value_required:n = true ,icolor .initial:o = \pc@goptd@icolor } \keys_define:nn{pdfcomment} { ,caption .choice: ,caption/none .code:n = \tl_set:Nn \pc@lopt@caption{none} ,caption/inline.code:n = \tl_set:Nn \pc@lopt@caption{Inline} ,caption/top .code:n = \tl_set:Nn \pc@lopt@caption{Top} ,caption .initial:n = inline } \keys_define:nn{pdfcomment} { ,line .tl_set:N = \pc@lopt@line ,line .value_required:n = true ,line .initial:o = \pc@goptd@line } \keys_define:nn{pdfcomment} { ,captionhoffset .code:n = \tl_set:Nn\pc@lopt@captionhoffset{\pc@pttobp{#1}} ,captionhoffset .value_required:n=true ,captionhoffset .initial:o =\pc@goptd@captionhoffset } \keys_define:nn{pdfcomment} { ,captionvoffset .code:n = \tl_set:Nn\pc@lopt@captionvoffset{\pc@pttobp{#1}} ,captionvoffset .value_required:n = true, ,captionvoffset .initial:o = \pc@goptd@captionvoffset } \keys_define:nn{pdfcomment} { ,linesep .code:n = \tl_set:Nn\pc@lopt@linesep{\pc@pttobp{#1}} ,linesep .value_required:n = true ,linesep .initial:o = \pc@goptd@linesep } \keys_define:nn{pdfcomment} { disable .legacy_if_set:n={pc@lopt@disable} } \keys_define:nn{pdfcomment} { ,id .tl_set:N = \pc@lopt@id ,id .value_required:n = true ,id .initial:o = \pc@goptd@id } \keys_define:nn{pdfcomment} { ,date .code:n = { \tl_if_blank:nTF{#1} {\tl_set:Nn\pc@lopt@date{}} {\tl_set:Nn\pc@lopt@date{(#1)}} } ,date .value_required:n = true ,date .initial:o = \pc@goptd@date } \keys_define:nn{pdfcomment} { ,timezone .tl_set:N = \pc@lopt@timezone ,timezone .value_required:n = true ,timezone .initial:o = \pc@goptd@timezone } \keys_define:nn{pdfcomment} { ,printSOfinal.bool_set:N = \@@_lopt_printSOfinal_bool ,printSOfinal.initial:n = true } \keys_define:nn{pdfcomment} { ,dvipdfmx .code:n = {\PackageWarning{pdfcomment}{The~option~'dvipdfmx'~is~ignored}} ,version .code:n = {\PackageWarning{pdfcomment}{The~option~'version'~is~ignored}} } \keys_define:nn{pdfcomment} { ,final .legacy_if_gset:n = pc@gopt@final ,final .usage:n = preamble ,draft .legacy_if_gset_inverse:n = pc@gopt@final ,draft .usage:n = preamble } \keys_define:nn{pdfcomment} { ,mathstyle .tl_set:N = \pc@lopt@mathstyle ,mathstyle .groups:n = {pdfmarkupcomment,pdftooltip} } \keys_define:nn{pdfcomment} { ,replyto .tl_set:N = \pc@lopt@replyto ,replyto .groups:n = {pdfreply} } \keys_define:nn{pdfcomment} { local.code:n = {\PackageWarning{pdfcomment}{The~option~'local'~is~ignored}} } \keys_define:nn{pdfcomment} { ,liststyle .code:n = {\setliststyle{#1}} ,liststyle .groups:n = {listofpdfcomments} } \keys_define:nn{pdfcomment} { ,heading .tl_set:N = \pc@lopt@liststyle ,heading .groups:n = {listofpdfcomments} } \ProcessKeyOptions[pdfcomment]\relax% % \RequirePackage{etoolbox}% \RequirePackage{zref-savepos}[2007/04/22]% \zref@require@unique% \RequirePackage{refcount}% \RequirePackage{ifthen}% \RequirePackage{marginnote}% \RequirePackage{soulpos}% %\RequirePackage{hyperref} % % Using the options draft, final in \pdfcommentsetup makes absolutely no sense! % Therefore, they are switched off at "\AtBeginDocument" % and a warning is issued by xkeyval.sty, if used. % \end{macrocode} % % \subsection{Tagging Socket(s)} % \begin{macrocode} \NewStructureName{pdfcomment/annot} \AssignStructureRole{pdfcomment/annot}{Annot} \NewTaggingSocket{pdfcomment/annotbox}{2} \NewTaggingSocketPlug{pdfcomment/annotbox}{default} { \tag_mc_end_push: \tag_struct_begin:n {tag=\UseStructureName{pdfcomment/annot}} \pdfdict_put:nne {#1}{StructParent}{ \tag_struct_parent_int: } #2 \exp_args:Nee \tag_struct_insert_annot:nn {\pdfannot_ref_last:}{ \tag_struct_parent_int: } \tag_struct_end: \tag_mc_begin_pop:n{} } \AssignTaggingSocketPlug{pdfcomment/annotbox}{default} % \end{macrocode} % % \subsection{Tagging support for marginnote} % % From https://github.com/latex3/tagging-project/issues/165 % \begin{macrocode} \long\def\@mn@@marginnote[#1]#2[#3]{% \endgroup \UseTaggingSocket{marginpar/begin}%<----------- \ifhmode \@mn@@@marginnote[{#1}]{#2}[{#3}]% \@esphack \else \@mn@@@marginnote[{#1}]{#2}[{#3}]% \fi \UseTaggingSocket{marginpar/end}%<---------- } \renewcommand*{\mn@parboxrestore}{% \UseTaggingSocket{para/restore}%<----------- \@tempskipa\parskip \@parboxrestore \parskip\@tempskipa } \renewcommand{\mn@zbox}[1]{% \bgroup \setbox\@tempboxa\vbox{#1\RawParEnd}%<--------- avoid para end \ht\@tempboxa\ht\strutbox \dp\@tempboxa\dp\strutbox \wd\@tempboxa\z@ \box\@tempboxa \egroup }% \renewcommand{\mn@vadjust}[1]{% \mn@zbox{\kern-\parskip \tagpdfparaOff\leavevmode\tagpdfparaOn%<------------- avoid para begin structure \vadjust{#1}% \kern\parskip }% } % \end{macrocode} % % \subsection{Standard building blocks} % \subsubsection{Annotation keys} % The keys generally allowed in annotations % \begin{macrocode} %<@@=pdfcomment> \pdfdict_new:n {l_@@_core_dict} % \end{macrocode} % Type: automatic\\ % Subtype: % \begin{macrocode} \pdfdict_put:nnn {l_@@_core_dict} {Subtype}{\pc@lopt@subtype} % \end{macrocode} % Rect: automatic\\ % Contents: % \begin{macrocode} \pdfdict_put:nnn {l_@@_core_dict} {Contents}{\pc@pdfenc@contents} % \end{macrocode} % P: ignored. TODO?\\ % NM: ignored. TODO? \\ % M: date % \begin{macrocode} \pdfdict_put:nnn {l_@@_core_dict} {M} {\pc@lopt@date} % \end{macrocode} % F: annotflags. TODO: currently fix. Check needed options % \begin{macrocode} \pdfdict_put:nnn {l_@@_core_dict} {F} {4} % \end{macrocode} % AP, AS: appearance. TODO!\\ % Border: ignored. See BS. TODO?\\ % C: color % \begin{macrocode} \pdfdict_put:nnn {l_@@_core_dict} {C} {\pc@lopt@color} % \end{macrocode} % StructParent: Through tagging code.\\ % OC: ignored. TODO?\\ % AF: ignored. TODO?\\ % ca: ignored. TODO?\\ % CA: opacity, in PDF 2.0 only for non-markup annotations. Fix when AP are fixed. % \begin{macrocode} \pdfdict_put:nnn {l_@@_core_dict} {CA} {\pc@lopt@opacity} % \end{macrocode} % BM: blend mode, ignored. TODO?\\ % Lang: (pdf 2.0) TODO % \subsubsection{Markup annotation keys} % With the exception of the tooltip all annotation types currently supported % are markup annotations. % \begin{macrocode} \pdfdict_new:n {l_@@_markup_dict} % \end{macrocode} % T: the title/author of a markup. % \begin{macrocode} \pdfdict_put:nnn {l_@@_markup_dict} {T} {\pc@pdfenc@author} % \end{macrocode} % Popup: ignored. TODO?\\ % RC: ignored. TODO?\\ % CreationDate: % \begin{macrocode} \pdfdict_put:nnn {l_@@_markup_dict} {CreationDate}{\pc@lopt@date} % \end{macrocode} % IRT: object reference for replyto. Done in the replyto command. TODO add a general key?\\ % Subj: % \begin{macrocode} \pdfdict_put:nnn {l_@@_markup_dict} {Subj} {\pc@pdfenc@subject} % \end{macrocode} % RT: currently ignored. Needs an IRT entry. TODO?\\ % IT: Intent. Currently ignored. TODO? % % \subsection{Keys of text annotations} % \begin{macrocode} \pdfdict_new:n {l_@@_text_dict} \pdfdict_set_eq:nn {l_@@_text_dict} {l_@@_core_dict} % \end{macrocode} % Open: a boolean flag % \begin{macrocode} \pdfdict_put:nnn {l_@@_text_dict} {Open} {\pc@lopt@open} % \end{macrocode} % Name: The name of the icon. Standard names are % Comment, Key, Note, Help, NewParagraph, Paragraph, Insert % \begin{macrocode} \pdfdict_put:nnn {l_@@_text_dict} {Name} {\pc@lopt@icon} % \end{macrocode} % State, StateModel: currently ignored. Related to Annotation states. % % \subsubsection{Keys for freetext annotations} % \begin{macrocode} \pdfdict_new:n {l_@@_freetext_dict} \pdfdict_set_eq:nn {l_@@_freetext_dict}{l_@@_core_dict} % \end{macrocode} % DA: font settings. TODO: check if defaults are ok nowadays... % Check color model. % \begin{macrocode} \pdfdict_put:nnn {l_@@_freetext_dict} {DA} {(/\pc@lopt@font\space \pc@lopt@fontsize\space Tf\space\pc@hyenc@fontcolor \space rg)} % \end{macrocode} % Q: justification, integer, 0, 1 or 2 % \begin{macrocode} \pdfdict_put:nnn {l_@@_freetext_dict} {Q} {\pc@lopt@justification} % \end{macrocode} % RC: currently ignored. TODO?\\ % DS: currently ignored. TODO?\\ % CL: callout (needs IT=FreeTextCallout): % \begin{macrocode} \pdfdict_put:nnn {l_@@_freetext_dict} {CL} {[\pc@lopt@line]} % \end{macrocode} % IT: intent. One of FreeText, FreeTextTypeWriter, FreeTextCallout % \begin{macrocode} \pdfdict_put:nnn {l_@@_freetext_dict} {IT} {\pc@lopt@type} % \end{macrocode} % BE: % \begin{macrocode} \pdfdict_put:nnn {l_@@_freetext_dict} {BE} {<>} % \end{macrocode} % RD: currently ignored. TODO?\\ % BS: % \begin{macrocode} \pdfdict_put:nnn {l_@@_freetext_dict} {BS} {<>} % \end{macrocode} % LE % \begin{macrocode} \pdfdict_put:nnn {l_@@_freetext_dict} {LE} {\pc@lopt@lineend} % \end{macrocode} % In a FreeTextTypewriter color and line are currently removed. TODO: check if that is needed. % \begin{macrocode} \cs_new_protected:Npn \@@_dict_update_freetext: { \str_if_eq:eeT {\pc@lopt@type}{/FreeTextTypewriter} {% \tl_set:Nn\pc@lopt@linewidth{0} \tl_set:Nn\pc@lopt@color{} }% } % \end{macrocode} % % \subsection{Keys for square and circle annotations} % \begin{macrocode} \pdfdict_new:n {l_@@_geometric_dict} \pdfdict_set_eq:nn {l_@@_geometric_dict}{l_@@_core_dict} \pdfdict_put:nnn {l_@@_geometric_dict} {BE} {<>} \pdfdict_put:nnn {l_@@_geometric_dict} {BS} {<>} \pdfdict_put:nnn {l_@@_geometric_dict} {IC} {\pc@lopt@icolor} % \end{macrocode} % % \subsection{Keys for line annotations} % The command covers Line, Polygon and PolyLine, so some settings have to be updated % in the command. % \begin{macrocode} \pdfdict_new:n {l_@@_line_dict} \pdfdict_set_eq:nn {l_@@_line_dict}{l_@@_core_dict} % \end{macrocode} % L: see below in update command. % \begin{macrocode} \pdfdict_put:nnn {l_@@_line_dict} {L} {[\pc@lopt@line]} % \end{macrocode} % BS: % \begin{macrocode} \pdfdict_put:nnn {l_@@_line_dict} {BS} {<>} % \end{macrocode} % LE: line endings. % \begin{macrocode} \pdfdict_put:nnn {l_@@_line_dict} {LE} {[\pc@lopt@linebegin\space\pc@lopt@lineend]} % \end{macrocode} % IC: internal color % \begin{macrocode} \pdfdict_put:nnn {l_@@_line_dict} {IC} {\pc@lopt@icolor} % \end{macrocode} % LL, LLE, LLO: currently ignored. TODO?\\ % Cap, CP: see below in update command. \\ % IT: currently ignored. Either /LineArrow or /LineDimension. TODO?\\ % Measure: currently ignored. TODO?\\ % CO: see below in update command. % \begin{macrocode} \cs_new_protected:Npn \@@_dict_update_line: { \str_if_eq:eeTF{\pc@lopt@caption}{none} { \pdfdict_put:nnn {l_@@_line_dict} {Cap}{false} } { \pdfdict_put:nnn {l_@@_line_dict} {Cap}{true} \pdfdict_put:nnn {l_@@_line_dict} {CP} {/\pc@lopt@caption} \pdfdict_put:nnn {l_@@_line_dict} {CO} {[\pc@lopt@captionhoffset\space \pc@lopt@captionvoffset]} } } % \end{macrocode} % % \subsection{Keys for Polygon and PolyLine annotations} % % \begin{macrocode} \pdfdict_new:n{l_@@_poly_dict} \pdfdict_set_eq:nn {l_@@_poly_dict}{l_@@_core_dict} % \end{macrocode} % Vertices: % \begin{macrocode} \pdfdict_put:nnn {l_@@_poly_dict} {Vertices} {[\pc@lopt@line]} % \end{macrocode} % LE (meaning full only for polyline) % \begin{macrocode} \pdfdict_put:nnn {l_@@_poly_dict} {LE} {[\pc@lopt@linebegin\space\pc@lopt@lineend]} % \end{macrocode} % BS: % \begin{macrocode} \pdfdict_put:nnn {l_@@_poly_dict} {BS} {<>} % \end{macrocode} % IC: internal color % \begin{macrocode} \pdfdict_put:nnn {l_@@_poly_dict} {IC} {\pc@lopt@icolor} % \end{macrocode} % BE (meaningful only for polygon) % \begin{macrocode} \pdfdict_put:nnn {l_@@_poly_dict} {BE} {<>} % \end{macrocode} % IT, Measure, Path: currently ignored. TODO? % % \subsection{Keys for tool tips} % Note: tooltips are form fields! % \begin{macrocode} \pdfdict_new:n {l_@@_tooltip_dict} \pdfdict_set_eq:nn {l_@@_tooltip_dict}{l_@@_core_dict} % \end{macrocode} % This is are field keys, not widget keys! % \begin{macrocode} \pdfdict_put:nnn {l_@@_tooltip_dict} {TU}{\pc@pdfenc@contents} \pdfdict_put:nnn {l_@@_tooltip_dict} {T} {(tooltip \thezref@unique)} \pdfdict_put:nnn {l_@@_tooltip_dict} {FT}{/Btn} \pdfdict_put:nnn {l_@@_tooltip_dict} {Ff}{65536} % \end{macrocode} % Widget keys. % H: TODO: allow more options? % \begin{macrocode} \pdfdict_put:nnn {l_@@_tooltip_dict} {H}{/N} % \end{macrocode} % We set a different flag value here. % \begin{macrocode} \pdfdict_put:nnn {l_@@_tooltip_dict} {F}{768} \pdfdict_put:nnn {l_@@_tooltip_dict} {BS}{<>} % \end{macrocode} % % \subsection{Keys for text markup annotions} % Highlight, Underline, Squiggly, StrikeOut: % \begin{macrocode} \pdfdict_new:n {l_@@_textmarkup_dict} \pdfdict_set_eq:nn {l_@@_textmarkup_dict}{l_@@_core_dict} \pdfdict_put:nnn {l_@@_textmarkup_dict} {QuadPoints} {[\pc@annot@quadpoints]} % \end{macrocode} % % \subsection{Collecting references} % This is used for the \cs{pdfreply} command. TODO: check code % \begin{macrocode} \cs_new_protected:Npn \@@_collect_objid: { \tl_if_empty:eF{\pc@lopt@id} { \tl_put_right:Ne\pc@collect@PDFOBJID{,\pdfannot_ref_last:} } } \cs_new_protected:Npn \@@_save_objid: { \tl_if_empty:eF{\pc@lopt@id} { \pc@save@PDFOBJID{\pc@lopt@id} } } % \end{macrocode} % % \subsection{\cs{pdfcomment}} % \begin{macrocode} \newcommand{\pdfcomment}[2][] { \ifhmode\unskip\fi \ifvmode\leavevmode\fi % \end{macrocode} % TODO Check if the command needs to be set globally! % \begin{macrocode} \group_begin: \gdef\pc@collect@PDFOBJID{S} \keys_set:nn{pdfcomment}{#1} \def\pc@lopt@subtype{/Text} \def\pc@lopt@comment{#2} % \end{macrocode} % Encode Contents, Author and Subject to pdf encodings % and transform color input to pdf color % % \begin{macrocode} \pc@encode@PDF{#2} % \end{macrocode} % % \begin{macrocode} \ifpc@gopt@final\else \ifpc@lopt@disable\else \hspace*{0pt} % \end{macrocode} % This creates the list entry % \begin{macrocode} \pc@create@lpc % \end{macrocode} % Typeset the text annotation in a box of size zero. % \begin{macrocode} \vbox% {\tagpdfparaOff \hsize=0pt \noindent \vspace{\pc@lopt@voffset} \hbox to 0pt { \vsize=0pt \hskip\pc@lopt@hoffset \UseTaggingSocket{pdfcomment/annotbox} {l_@@_text_dict} { \pdfannot_box:nnne {\normalbaselineskip} {\normalbaselineskip} {0pt} { \pdfdict_use:n {l_@@_text_dict} \pdfdict_use:n {l_@@_markup_dict} } } % \end{macrocode} % TODO: check % \begin{macrocode} \@@_collect_objid: \@@_save_objid: \hss% }% }% \hspace{\pc@lopt@hspace} \fi \fi \group_end: }% % \end{macrocode} % % \subsection{\cs{pdfmargincomment}} % This is a text annotation moved into the margin. % The \cs{marginnote} command is patched above. % % \begin{macrocode} \newcommand{\pdfmargincomment}[2][] { \ifhmode\unskip\fi \ifvmode\leavevmode\fi \group_begin: \gdef\pc@collect@PDFOBJID{S} \keys_set:nn{pdfcomment}{#1} \def\pc@lopt@subtype{/Text} \def\pc@lopt@comment{#2} % \end{macrocode} % Encode Contents, Author and Subject % and transform color input to pdf color % \begin{macrocode} \pc@encode@PDF{#2} \ifpc@gopt@final\else \ifpc@lopt@disable\else \hspace*{0pt} \pc@create@lpc % \end{macrocode} % Center marginnotes: % \begin{macrocode} \renewcommand{\raggedleftmarginnote}{\pc@raggedleftmarginnote} \renewcommand{\raggedrightmarginnote}{\pc@raggedrightmarginnote} % \end{macrocode} % Typeset the annotation in a \cs{marginnote}: % \begin{macrocode} \marginnote { \vbox {\tagpdfparaOff \hsize=0pt \noindent \vspace{\pc@lopt@voffset} \hbox to 0pt { \vsize=0pt \hskip\pc@lopt@hoffset \UseTaggingSocket{pdfcomment/annotbox} {l_@@_text_dict} { \pdfannot_box:nnne {\normalbaselineskip} {\normalbaselineskip} {0pt} { \pdfdict_use:n {l_@@_text_dict} \pdfdict_use:n {l_@@_markup_dict} } } \@@_collect_objid: \@@_save_objid: \hss } } \hspace{\pc@lopt@hspace} } \fi \fi \group_end: } % \end{macrocode} % \subsection{pdffreetextcomment} % % \begin{macrocode} \newcommand{\pdffreetextcomment}[2][] { \ifhmode\unskip\fi \ifvmode\leavevmode\fi \group_begin: \gdef\pc@collect@PDFOBJID{S} \keys_set:nn{pdfcomment}{#1} \def\pc@lopt@subtype{/FreeText} \def\pc@lopt@comment{#2} \@@_dict_update_freetext: % \end{macrocode} % Encode Contents, Author and Subject and colors: % \begin{macrocode} \pc@encode@PDF{#2} \ifpc@gopt@final\else \ifpc@lopt@disable\else \hspace*{0pt} % \end{macrocode} % typeset freetext annotation % \begin{macrocode} \vbox to 0pt { \tagpdfparaOff \hsize=0pt \noindent% \vskip-\pc@lopt@voffset \hbox to 0pt { \vsize=0pt \hskip\pc@lopt@hoffset \pc@create@lpc \UseTaggingSocket{pdfcomment/annotbox} {l_@@_freetext_dict} { \pdfannot_box:nnne {\dim_eval:n{\pc@lopt@width+0pt}} {\dim_eval:n{\pc@lopt@height+0pt}} {\dim_eval:n{\pc@lopt@depth+0pt}} { \pdfdict_use:n {l_@@_freetext_dict} \pdfdict_use:n {l_@@_markup_dict} } } \@@_collect_objid: \@@_save_objid: \hss } \vss } \fi \fi \group_end: } % \end{macrocode} % % \subsection{\cs{pdfsquarecomment}} % \begin{macrocode} \newcommand{\pdfsquarecomment}[2][] { \ifhmode\unskip\fi \ifvmode\leavevmode\fi \group_begin: \gdef\pc@collect@PDFOBJID{S} \keys_set:nn{pdfcomment}{#1} \def\pc@lopt@subtype{/Square} \def\pc@lopt@comment{#2} % \end{macrocode} % Encode Contents, Author and Subject and color % \begin{macrocode} \pc@encode@PDF{#2} \ifpc@gopt@final\else \ifpc@lopt@disable\else \hspace*{0pt} % \end{macrocode} % typeset square annotation % \begin{macrocode} \vbox to 0pt { \tagpdfparaOff \hsize=0pt \noindent \vskip-\pc@lopt@voffset \hbox to 0pt { \vsize=0pt \hskip\pc@lopt@hoffset \pc@create@lpc \UseTaggingSocket{pdfcomment/annotbox} {l_@@_geometric_dict} { \pdfannot_box:nnne {\dim_eval:n{\pc@lopt@width+0pt}} {\dim_eval:n{\pc@lopt@height+0pt}} {\dim_eval:n{\pc@lopt@depth+0pt}} { \pdfdict_use:n {l_@@_geometric_dict} \pdfdict_use:n {l_@@_markup_dict} } } \@@_collect_objid: \@@_save_objid: \hss } \vss } \fi \fi \group_end: } % \end{macrocode} % \subsection{\cs{pdfcirclecomment}} % \begin{macrocode} \newcommand{\pdfcirclecomment}[2][] { \ifhmode\unskip\fi \ifvmode\leavevmode\fi \group_begin: \gdef\pc@collect@PDFOBJID{S} \keys_set:nn{pdfcomment}{#1} \def\pc@lopt@subtype{/Circle} \def\pc@lopt@comment{#2} % \end{macrocode} % Encode Contents, Author and Subject and color % \begin{macrocode} \pc@encode@PDF{#2} \ifpc@gopt@final\else \ifpc@lopt@disable\else \hspace*{0pt}% % \end{macrocode} % typeset circle annotation % \begin{macrocode} \vbox to 0pt { \tagpdfparaOff \hsize=0pt \noindent \vskip-\pc@lopt@voffset \hbox to 0pt { \vsize=0pt \hskip\pc@lopt@hoffset \pc@create@lpc \UseTaggingSocket{pdfcomment/annotbox} {l_@@_geometric_dict} { \pdfannot_box:nnne {\dim_eval:n{\pc@lopt@width+0pt}} {\dim_eval:n{\pc@lopt@height+0pt}} {\dim_eval:n{\pc@lopt@depth+0pt}} { \pdfdict_use:n {l_@@_geometric_dict} \pdfdict_use:n {l_@@_markup_dict} } } \@@_collect_objid: \@@_save_objid: \hss } \vss } \fi \fi \group_end: }% % \end{macrocode} % % \subsection{\cs{pdflinecomment}} % \begin{macrocode} \newcommand{\pdflinecomment}[2][] { \ifhmode\unskip\fi \ifvmode\leavevmode\fi \group_begin: \gdef\pc@collect@PDFOBJID{S} \keys_set:nn{pdfcomment}{#1} \def\pc@lopt@comment{#2} \pc@encode@PDF{#2} \ifpc@gopt@final\else \ifpc@lopt@disable\else \hspace*{0pt} \pc@create@lpc \vbox to 0pt { \tagpdfparaOff \hsize=0pt \noindent \hbox to 0pt { \vsize=0pt \tl_if_eq:NnTF\pc@lopt@subtype{/Line} { \@@_dict_update_line: \UseTaggingSocket{pdfcomment/annotbox} {l_@@_line_dict} { \pdfannot_box:nnne {\dim_eval:n{\pc@lopt@width+0pt}} {\dim_eval:n{\pc@lopt@height+0pt}} {\dim_eval:n{\pc@lopt@depth+0pt}} { \pdfdict_use:n {l_@@_line_dict} \pdfdict_use:n {l_@@_markup_dict} } } } { \UseTaggingSocket{pdfcomment/annotbox} {l_@@_poly_dict} { \pdfannot_box:nnne {\dim_eval:n{\pc@lopt@width+0pt}} {\dim_eval:n{\pc@lopt@height+0pt}} {\dim_eval:n{\pc@lopt@depth+0pt}} { \pdfdict_use:n {l_@@_poly_dict} \pdfdict_use:n {l_@@_markup_dict} } } } \@@_collect_objid: \@@_save_objid: \hss } \vss } \fi \fi \group_end: } % \end{macrocode} % % \subsection{\cs{pdfmarkupcomment}} % TODO: We need to get rid of soul with luatex. % \begin{macrocode} \newcommand{\pdfmarkupcomment}[3][] %#1 option, #2 text, #3 comment { \leavevmode \group_begin: \gdef\pc@collect@PDFOBJID{S} \keys_set:nn{pdfcomment}{#1} \def\pc@lopt@comment{#3} \ifmmode% \zsavepos{pdfcomment:\thezref@unique} \zref@refused{pdfcomment:\thezref@unique} \setlength{\pc@Sposx}{\zposx{pdfcomment:\thezref@unique}sp} \setlength{\pc@Sposy}{\zposy{pdfcomment:\thezref@unique}sp} \stepcounter{zref@unique}% \setlength{\pc@Eposx}{\zposx{pdfcomment:\thezref@unique}sp} \setlength{\pc@Eposy}{\zposy{pdfcomment:\thezref@unique}sp} \ifpc@gopt@final\else \ifpc@lopt@disable\else \setbox\pc@nullbox= \hbox{\SuspendTagging{}\pc@encode@PDF{#3}$\pc@lopt@mathstyle#2$} \setbox\pc@mathannot@box=\hbox to\wd\pc@nullbox { \vrule height\ht\pc@nullbox~depth\dp\pc@nullbox~width\z@ \hfill \pc@annot@calc@pos@math \edef\pc@annot@quadpoints { \pc@x@one\space\pc@y@one\space\pc@x@two\space\pc@y@two\space \pc@x@three\space\pc@y@three\space\pc@x@four\space\pc@y@four } \UseTaggingSocket {pdfcomment/annotbox} {l_@@_textmarkup_dict} { \pdfannot_box:nnne {0pt} {0pt} {0pt} { \pdfdict_use:n {l_@@_textmarkup_dict} \pdfdict_use:n {l_@@_markup_dict} } } } \@@_collect_objid: \wd\pc@mathannot@box\z@ \ht\pc@mathannot@box\z@ \dp\pc@mathannot@box\z@ \box\pc@mathannot@box \nobreak% \fi \fi \ifpc@gopt@final \str_if_eq:eeTF{\pc@lopt@subtype}{/StrikeOut} { \bool_if:NTF\@@_lopt_printSOfinal_bool {#2\pc@ignorespacesfalse} {\pc@ignorespacestrue} } { #2\pc@ignorespacesfalse } \else \ifpc@lopt@disable \str_if_eq:eeTF{\pc@lopt@subtype}{/StrikeOut} { \bool_if:NTF\@@_lopt_printSOfinal_bool {#2\pc@ignorespacesfalse} {\pc@ignorespacestrue} } { #2\pc@ignorespacesfalse } \else #2\pc@ignorespacesfalse \fi \fi \zsavepos{pdfcomment:\thezref@unique} \zref@refused{pdfcomment:\thezref@unique} \stepcounter{zref@unique} \else \pc@encode@PDF{#3} \settoheight{\pc@box@height}{#2} \str_if_eq:eeTF {\pc@lopt@subtype} {/Underline} { \settodepth{\pc@box@depth}{Tq} } { \settodepth{\pc@box@depth}{#2} } \def\SOUL@preamble { \def\ulp@skern{0pt} \def\ulp@ekern{0pt} \def\ulp@sgap{0pt} \def\ulp@egap{0pt} \def\ulp@pos{\z@} % \end{macrocode} % Here the annotation is created: % \begin{macrocode} \def\ulp@draw{\pc@soul@markup} \ulp@preamble } \let\SOUL@postamble\ulp@postamble \let\SOUL@everyspace\ulp@everyspace % \end{macrocode} % For tagging we need a fake space: % \begin{macrocode} \def\SOUL@everyspace##1 { \ulp@stepput\@ne ##1\use:c{pdffakespace}\space \ulp@stepput\@ne } \let\SOUL@everyhyphen\ulp@everyhyphen \let\SOUL@everyexhyphen\ulp@everyexhyphen \let\SOUL@everysyllable\@empty \def\SOUL@everytoken{\the\SOUL@token} \ifpc@gopt@final \str_if_eq:eeTF {\pc@lopt@subtype} {/StrikeOut} { \bool_if:NTF\@@_lopt_printSOfinal_bool {\SuspendTagging{}\SOUL@{#2}\ResumeTagging{}\pc@ignorespacesfalse} {\pc@ignorespacestrue} } { #2\pc@ignorespacesfalse } \else \ifpc@lopt@disable \str_if_eq:eeTF {\pc@lopt@subtype} {/StrikeOut} { \bool_if:NTF\@@_lopt_printSOfinal_bool {#2\pc@ignorespacesfalse} {\pc@ignorespacestrue} } { #2\global\pc@ignorespacesfalse } \else \SuspendTagging{}\SOUL@{#2}\ResumeTagging{} \pc@ignorespacesfalse \fi \fi \fi \ifpc@gopt@final\else \ifpc@lopt@disable\else \pc@create@lpc \fi \fi \@@_save_objid: \ifpc@ignorespaces \ignorespaces \fi \group_end: }% % \end{macrocode} % \subsection{pdfsidelinecomment} % This is a Line annotation. % \begin{macrocode} \newenvironment{pdfsidelinecomment}[2][] { \ifhmode\unskip\fi \ifvmode\leavevmode\fi \gdef\pc@collect@PDFOBJID{S} \keys_set:nn{pdfcomment}{#1} \def\pc@lopt@subtype{/Line} \def\pc@lopt@comment{#2} \@@_dict_update_line: % \end{macrocode} % Encode Contents, Author and Subject % and transform color input to pdf color % \begin{macrocode} \pc@encode@PDF{#2} \zsavepos{pdfcomment:slc:\thepc@count@iv} \zref@refused{pdfcomment:slc:\thepc@count@iv} \setlength{\pc@Sposx}{\zposx{pdfcomment:slc:\thepc@count@iv}sp} \setlength{\pc@Sposy}{\zposy{pdfcomment:slc:\thepc@count@iv}sp} \stepcounter{pc@count@iv} \setlength{\pc@Eposx}{\zposx{pdfcomment:slc:\thepc@count@iv}sp} \setlength{\pc@Eposy}{\zposy{pdfcomment:slc:\thepc@count@iv}sp} \settoheight{\pc@box@height}{Tq} \settoheight{\pc@box@depth}{Tq} \stepcounter{pc@count@i} \label{pdfcomment:pageS:\thepc@count@i} \refused{pdfcomment:pageS:\thepc@count@i} \def\pc@pS{\getpagerefnumber{pdfcomment:pageS:\thepc@count@i}} \def\pc@pE{\getpagerefnumber{pdfcomment:pageE:\thepc@count@i}} \str_if_eq:eeTF {\pc@pS}{\pc@pE} {\pc@annot@samepagetrue} {\pc@annot@samepagefalse} \pc@firstcolumntrue \pc@calc@textblockpos \setlength{\pc@column}{\pc@x@right@text bp} \addtolength{\pc@column}{3pt} \ifnum\pc@Sposx<\pc@column \pc@Sfirstcolumntrue \else \pc@Sfirstcolumnfalse \fi \ifnum\pc@Eposx<\pc@column \pc@Efirstcolumntrue \else \pc@Efirstcolumnfalse \fi \ifpc@annot@samepage\else \ifpc@gopt@final\else \ifpc@lopt@disable\else % 1st part of annotation on 1st page \if@twocolumn \ifpc@Sfirstcolumn \PackageError{pdfcomment} { \string\pdfsidelinecomment\space supports~only~one\MessageBreak column~or~ page~ break~ in~ twocolumn~ mode!!\MessageBreak Your~ comment~ is~ too~ long! } \else % start in second column \pc@annot@secondpagefalse \pc@calc@sidelinepos \renewcommand{\pc@y@two}{\pc@y@bottom@text} \def\pc@lopt@line{\pc@x@two\space\pc@y@one\space\pc@x@two\space\pc@y@two} \pdfdict_put:nne {l_@@_line_dict} {LE} {[\pc@lopt@linebegin\space/None]} \marginnote{\pc@create@lpc\pc@create@annot@sideline} \fi \else \pc@annot@secondpagefalse \pc@calc@sidelinepos \renewcommand{\pc@y@two}{\pc@y@bottom@text} \def\pc@lopt@line{\pc@x@two\space\pc@y@one\space\pc@x@two\space\pc@y@two} \pdfdict_put:nne {l_@@_line_dict} {LE} {[\pc@lopt@linebegin\space/None]} \marginnote{\pc@create@lpc\pc@create@annot@sideline} \def\pc@lopt@line{\pc@x@one\space\pc@y@two\space\pc@x@one\space\pc@y@one} \pdfdict_put:nne {l_@@_line_dict} {LE} {[/None\space \pc@lopt@linebegin]} \marginnote{\pc@create@annot@sideline} \fi \fi \fi \fi } { \zsavepos{pdfcomment:slc:\thepc@count@iv} \zref@refused{pdfcomment:slc:\thepc@count@iv} \label{pdfcomment:pageE:\thepc@count@i} \refused{pdfcomment:pageE:\thepc@count@i} \stepcounter{pc@count@iv} \ifpc@gopt@final\else \ifpc@lopt@disable\else \ifpc@annot@samepage % annot complete on one page \if@twocolumn \ifpc@Sfirstcolumn \ifpc@Efirstcolumn % complete in first column \pc@firstcolumntrue \pc@calc@sidelinepos \def\pc@lopt@line{\pc@x@one\space\pc@y@two\space\pc@x@one\space\pc@y@one} \pdfdict_put:nne {l_@@_line_dict} {LE} {[\pc@lopt@lineend\space \pc@lopt@linebegin]} \marginnote{\pc@create@lpc\pc@create@annot@sideline} \else % column break \pc@firstcolumntrue \pc@calc@sidelinepos \renewcommand{\pc@y@two}{\pc@y@bottom@text} \def\pc@lopt@line{\pc@x@one\space\pc@y@two\space\pc@x@one\space\pc@y@one} \pdfdict_put:nne {l_@@_line_dict} {LE} {[/None\space \pc@lopt@linebegin]} \marginnote{\pc@create@lpc\pc@create@annot@sideline} \pc@firstcolumnfalse \pc@calc@sidelinepos \renewcommand{\pc@y@one}{\pc@y@top@text} \def\pc@lopt@line{\pc@x@two\space\pc@y@one\space\pc@x@two\space\pc@y@two} \pdfdict_put:nne {l_@@_line_dict} {LE} {[/None\space \pc@lopt@lineend]} \marginnote{\pc@create@annot@sideline} \fi \else \ifpc@Efirstcolumn % not possible \else % complete in seconds column \pc@firstcolumnfalse \pc@calc@sidelinepos \def\pc@lopt@line{\pc@x@two\space\pc@y@one\space\pc@x@two\space\pc@y@two} \pdfdict_put:nne {l_@@_line_dict} {LE} {[\pc@lopt@linebegin\space \pc@lopt@lineend]} \marginnote{\pc@create@lpc\pc@create@annot@sideline} \fi \fi \else \pc@calc@sidelinepos \def\pc@lopt@line{\pc@x@two\space\pc@y@one\space\pc@x@two\space\pc@y@two} \pdfdict_put:nne {l_@@_line_dict} {LE} {[\pc@lopt@linebegin\space\pc@lopt@lineend]} \marginnote{\pc@create@lpc\pc@create@annot@sideline} \def\pc@lopt@line{\pc@x@one\space\pc@y@two\space\pc@x@one\space\pc@y@one} \pdfdict_put:nne {l_@@_line_dict} {LE} {[\pc@lopt@lineend\space\pc@lopt@linebegin]} \marginnote{\pc@create@annot@sideline} \fi \else % 2nd part of annotation on 2nd page \if@twocolumn \ifpc@Efirstcolumn % end in first column \pc@firstcolumntrue \pc@annot@secondpagetrue \pc@calc@sidelinepos \renewcommand{\pc@y@one}{\pc@y@top@text} \def\pc@lopt@line{\pc@x@one\space\pc@y@two\space\pc@x@one\space\pc@y@one} \pdfdict_put:nne {l_@@_line_dict} {LE} {[\pc@lopt@lineend\space/None]} \marginnote{\pc@create@annot@sideline} \else \PackageError{pdfcomment} { \string\pdfsidelinecomment\space supports~ only~ one\MessageBreak column~ or~ page~ break~ in~ twocolumn~ mode!\MessageBreak Your~ comment~ is~ too~ long! } \fi \else \pc@annot@secondpagetrue \pc@calc@sidelinepos \renewcommand{\pc@y@one}{\pc@y@top@text} \def\pc@lopt@line{\pc@x@two\space\pc@y@one\space\pc@x@two\space\pc@y@two} \pdfdict_put:nne {l_@@_line_dict} {LE} {[/None\space\pc@lopt@lineend]} \marginnote{\pc@create@annot@sideline} \def\pc@lopt@line{\pc@x@one\space\pc@y@two\space\pc@x@one\space\pc@y@one} \pdfdict_put:nne {l_@@_line_dict} {LE} {[\pc@lopt@lineend\space/None]} \marginnote{\pc@create@annot@sideline} \fi \fi \fi \fi \@@_save_objid: } % \end{macrocode} % The helper command with the annotation: % \begin{macro}[int]{\pc@create@annot@sideline} % \begin{macrocode} \newcommand{\pc@create@annot@sideline} { \ifpc@gopt@final\else % typeset line annotation (see: PDF Reference) \vbox to 0pt {\tagpdfparaOff \hsize=0pt \noindent \hbox to 0pt { \vsize=0pt \UseTaggingSocket{pdfcomment/annotbox} {l_@@_line_dict} { \pdfannot_box:nnne {\dim_eval:n{\pc@lopt@width+0pt}} {\dim_eval:n{\pc@lopt@height+0pt}} {\dim_eval:n{\pc@lopt@depth+0pt}} { \pdfdict_use:n {l_@@_line_dict} \pdfdict_use:n {l_@@_markup_dict} } } \hss } \vss } \ifpc@annot@samepage \@@_collect_objid: \else \ifpc@annot@secondpage \@@_collect_objid: \else \fi \fi \fi } % \end{macrocode} % \end{macro} % % \subsection{\cs{pdfreply}} % % \begin{macrocode} \newcommand{\pdfreply}[2][] { \ifhmode\unskip\fi \ifvmode\leavevmode\fi \group_begin: \gdef\pc@collect@PDFOBJID{S} \keys_set:nn{pdfcomment}{#1} \def\pc@lopt@subtype{/Text} \def\pc@lopt@comment{#2} % \end{macrocode} % Encode Contents, Author and Subject % and transform color input to pdf color % \begin{macrocode} \pc@encode@PDF{#2} \ifpc@gopt@final\else \ifpc@lopt@disable\else \hspace*{0pt}% %\pc@create@lpc% ???????? % typeset text annotation (see: PDF Reference) % \end{macrocode} % TODO: check logic % \begin{macrocode} \xdef\pc@zref@PDFOBJID{\pc@get@PDFOBJID{\pc@lopt@replyto}} \clist_map_inline:Nn \pc@zref@PDFOBJID { \str_if_eq:eeTF{##1}{A} { \xdef\pc@collect@PDFOBJID{\pc@collect@PDFOBJID,A} } { \str_if_eq:eeF{##1}{S} { \pdfdict_put:nnn {l_@@_text_dict} {IRT}{##1} \vbox {\tagpdfparaOff \hsize=0pt \noindent \vspace{\pc@lopt@voffset} \hbox to 0pt { \vsize=0pt \hskip\pc@lopt@hoffset \UseTaggingSocket{pdfcomment/annotbox} {l_@@_text_dict} { \pdfannot_box:nnne {0pt} {\normalbaselineskip} {0pt} { \pdfdict_use:n{l_@@_text_dict} \pdfdict_use:n {l_@@_markup_dict} } } \@@_collect_objid: \hss } } } } } \@@_save_objid: \fi \fi \group_end: } % \end{macrocode} % % \subsection{\cs{pdftooltip}} % \begin{macro}[no-user-doc]{\pdftooltip} % \begin{macrocode} \newcommand{\pdftooltip}[3][] { \leavevmode \group_begin: \gdef\pc@collect@PDFOBJID{S} \keys_set:nn{pdfcomment}{#1} \def\pc@lopt@subtype{/Widget} \def\pc@lopt@comment{#3} \ifmmode \setbox\pc@nullbox=\hbox{\SuspendTagging{}\pc@encode@PDF{#3}} \setbox\pc@nullbox=\hbox{\SuspendTagging{}$\pc@lopt@mathstyle#2$} \else \pc@encode@PDF{#3} \setbox\pc@nullbox=\hbox{\SuspendTagging{}#2} \fi \ifpc@lopt@disable #2 \else \AssignStructureRole{pdfcomment/annot}{Form} \UseTaggingSocket{pdfcomment/annotbox} {l_@@_tooltip_dict} { \pdfannot_box:nnne {\wd\pc@nullbox} {\ht\pc@nullbox} {\dp\pc@nullbox} { \pdfdict_use:n{l_@@_tooltip_dict} } } #2 \fi \stepcounter{zref@unique} \group_end: } % \end{macrocode} % \end{macro} % % \subsection{\cs{pdfsquaretooltip}} % \begin{macro}[no-user-doc]{\pdfsquaretooltip} % \begin{macrocode} \newbox\pc@tmp@box \NewDocumentCommand\pdfsquaretooltip{O{}mm} { \leavevmode \sbox\pc@tmp@box{#2}% \kern0pt\pdfsquarecomment [liststyle=, linewidth=0pt, opacity=0, color=,icolor=, width=\wd\pc@tmp@box, height=\ht\pc@tmp@box, depth=\dp\pc@tmp@box,#1] {#3} \usebox\pc@tmp@box } % \end{macrocode} % \end{macro} % % \subsection{Setup commands} % % \begin{macro}[no-user-doc]{\pdfcommentsetup} % \begin{macrocode} \newcommand{\pdfcommentsetup}[2][] { \keys_set:nn{pdfcomment}{#1,#2} } % \end{macrocode} % \end{macro} % % Define predefined set of options (Avatar) % % \begin{macro}[no-user-doc]{\defineavatar} % \begin{macrocode} \newcommand{\defineavatar}[2] { \cs_if_exist:cTF {pc@avatar@#1} { \cs_set:cpn {pc@avatar@#1}{\keys_set:nn{pdfcomment}{#2}} } { \cs_new:cpn {pc@avatar@#1}{\keys_set:nn{pdfcomment}{#2}} } } % % \end{macrocode} % \end{macro} % % Define predefined set of options (Style) % % \begin{macro}[no-user-doc]{\definestyle} % \begin{macrocode} \newcommand{\definestyle}[2] { \cs_if_exist:cTF {pc@style@#1} { \cs_set:cpn {pc@style@#1}{\keys_set:nn{pdfcomment}{#2}} } { \cs_new:cpn {pc@style@#1}{\keys_set:nn{pdfcomment}{#2}} } } % \end{macrocode} % \end{macro} % % \subsection{List of pdf comments} % % The format of the list entries: % \begin{macrocode} \newcommand\l@lpcsec{\@dottedtocline{1}{0em}{0em}}% % \end{macrocode} % % Define predefined set of liststyles: % % \begin{macro}[no-user-doc]{\defineliststyle} % \begin{macrocode} \newcommand{\defineliststyle}[2] { \cs_if_exist:cTF {@@_set_list_style_#1:} { \cs_set_protected:cpn {@@_set_list_style_#1:} { \cs_set:Npn \pc@lpc@format {#2} } % Warning? } { \cs_new_protected:cpn {@@_set_list_style_#1:} { \cs_set:Npn \pc@lpc@format {#2} } } } % \end{macrocode} % \end{macro} % % Setting the list style: % \begin{macro}[no-user-doc]{\setliststyle} % \begin{macrocode} \newcommand{\setliststyle}[1] { \cs_if_exist_use:cF { @@_set_list_style_#1: } { \setliststyle{AuthorSubject} \PackageWarning{pdfcomment} { Unknown~liststyle~#1\MessageBreak in~command~setliststyle\MessageBreak Using~liststyle~AuthorSubject~instead! } } } % \end{macrocode} % \end{macro} % % The predefined styles. The empty style suppresses the list entry. % \begin{macrocode} \cs_new_protected:cpn {__pc_set_list_style_:} { \cs_set_eq:N \pc@lpc@format \prg_do_nothing: } \defineliststyle {} {} \defineliststyle {AuthorSubject} {\pc@lopt@author\ -\ \pc@lopt@subject} \defineliststyle {AuthorSubjectDeadline} {\pc@lopt@author\ -\ \pc@lopt@subject\ (\pc@lopt@deadline)} \defineliststyle {SubjectAuthorComment} {\pc@lopt@subject\ (\pc@lopt@author) :\ \pc@lopt@comment} \defineliststyle {SubjectAuthorCommentDeadline} {\pc@lopt@subject\ (\pc@lopt@author) :\ \pc@lopt@comment\ (\pc@lopt@deadline)} \defineliststyle {AuthorComment} {\pc@lopt@author :\ \pc@lopt@comment} \defineliststyle {AuthorCommentDeadline} {\pc@lopt@author :\ \pc@lopt@comment\ (\pc@lopt@deadline)} \defineliststyle {SubjectComment} {\pc@lopt@subject :\ \pc@lopt@comment} \defineliststyle {SubjectCommentDeadline} {\pc@lopt@subject :\ \pc@lopt@comment\ (\pc@lopt@deadline)} \defineliststyle {Comment} {\pc@lopt@comment} \defineliststyle {CommentDeadline} {\pc@lopt@comment\ (\pc@lopt@deadline)} % \end{macrocode} % % The list of pdf comments % \begin{macrocode} \newcommand{\listofpdfcomments}[1][] { \keys_set_groups:nnn {pdfcomment}{listofpdfcomments}{#1} \ifpc@gopt@final\else \@ifundefined{chapter}% { \section*{\lpcname\@mkboth{\lpcname}{\lpcname}} \addcontentsline{toc}{section}{\lpcname{}} } { \chapter*{\lpcname\@mkboth{\lpcname}{\lpcname}} \addcontentsline{toc}{chapter}{\lpcname{}} } \@starttoc{lpc} \fi } % \end{macrocode} % The command that creates the list entries in the annotations: % \begin{macro}[int]{\pc@create@lpc} % \begin{macrocode} \newcommand{\pc@create@lpc}% { \cs_if_eq:NNF\pc@lpc@format\prg_do_nothing: { \MakeLinkTarget[pdfcomment]{} \addcontentsline{lpc}{lpcsec}{\protect\numberline{}\pc@lpc@format} } } % \end{macrocode} % \end{macro} % % \subsection{Helper code} % These properties are used for the reply command: % \begin{macrocode} \zref@newlist{pdfcomment} \zref@newprop{PCPDFOBJID}[]{\pc@collect@PDFOBJID} \zref@addprop{pdfcomment}{PCPDFOBJID} \newcommand*{\pc@save@PDFOBJID}[1] { \zref@labelbylist{#1}{pdfcomment} } \newcommand*{\pc@get@PDFOBJID}[1] { \zref@extract{#1}{PCPDFOBJID} } % \end{macrocode} % % % The command that encodes the text in PDF format. % % \begin{macrocode} \newcommand{\pc@encode@PDF}[1] { \tl_if_empty:oTF {\pc@lopt@deadline} { \pdfstringdef\pc@pdfenc@contents{#1} } { \pdfstringdef\pc@pdfenc@contents{#1\textCR(\pc@lopt@deadline)} } \tl_gset:Ne\pc@pdfenc@contents {(\pc@pdfenc@contents)} \pdfstringdef\pc@pdfenc@author {\pc@lopt@author} \tl_gset:Ne\pc@pdfenc@author {(\pc@pdfenc@author)} \pdfstringdef\pc@pdfenc@subject {\pc@lopt@subject} \tl_gset:Ne\pc@pdfenc@subject {(\pc@pdfenc@subject)} } % \end{macrocode} % \begin{macrocode} \cs_set_eq:NN\pc@pttobp\dim_to_decimal_in_bp:n \newcommand{\pc@annot@calc@pos@math} { \renewcommand{\pc@x@one} {\pc@pttobp{\pc@Sposx}} \renewcommand{\pc@x@two} {\pc@pttobp{\dimexpr \pc@Sposx + \wd\pc@nullbox\relax}} \renewcommand{\pc@x@three} {\pc@pttobp{\pc@Sposx}} \renewcommand{\pc@x@four} {\pc@pttobp{\dimexpr \pc@Sposx + \wd\pc@nullbox\relax}} \renewcommand{\pc@y@one} {\pc@pttobp{\dimexpr \pc@Sposy + \ht\pc@nullbox + 1pt\relax}} \renewcommand{\pc@y@two} {\pc@pttobp{\dimexpr \pc@Sposy + \ht\pc@nullbox + 1pt\relax}} \renewcommand{\pc@y@three} {\pc@pttobp{\dimexpr \pc@Sposy - \dp\pc@nullbox - 1pt\relax}} \renewcommand{\pc@y@four} {\pc@pttobp{\dimexpr \pc@Sposy - \dp\pc@nullbox - 1pt\relax}} \setlength{\pc@dima}{\dimexpr \pc@Sposy - \dp\pc@nullbox - 1pt\relax} \setlength{\pc@dimb}{\dimexpr \pc@Eposy - \dp\pc@nullbox - 1pt\relax} } \newcommand{\pc@annot@complete} { \renewcommand{\pc@x@one}{\pc@pttobp{\pc@Sposx}} \renewcommand{\pc@x@two}{\pc@pttobp{\pc@Eposx}} \renewcommand{\pc@x@three}{\pc@pttobp{\pc@Sposx}} \renewcommand{\pc@x@four}{\pc@pttobp{\pc@Eposx}} \renewcommand{\pc@y@one} {\pc@pttobp{\dimexpr \pc@Sposy + \pc@box@height + 1pt\relax}} \renewcommand{\pc@y@two} {\pc@pttobp{\dimexpr \pc@Eposy + \pc@box@height + 1pt\relax}} \renewcommand{\pc@y@three} {\pc@pttobp{\dimexpr \pc@Sposy - \pc@box@depth - 1pt\relax}} \renewcommand{\pc@y@four} {\pc@pttobp{\dimexpr \pc@Eposy - \pc@box@depth - 1pt\relax}} \def\pc@annot@quadpoints { \pc@x@one\space\pc@y@one\space \pc@x@two\space\pc@y@two\space \pc@x@three\space\pc@y@three\space \pc@x@four\space\pc@y@four } \UseTaggingSocket{pdfcomment/annotbox} {l_@@_textmarkup_dict} { \pdfannot_box:nnne {0pt} {0pt} {0pt} { \pdfdict_use:n {l_@@_textmarkup_dict} \pdfdict_use:n {l_@@_markup_dict} }% } \@@_collect_objid: } \newcommand*{\pc@soul@markup} { \stepcounter{pc@count@iii} \zsavepos{pdfcomment_soul_markup:\thepc@count@iii} \zref@refused{pdfcomment_soul_markup:\thepc@count@iii} \setlength{\pc@Sposx}{\zposx{pdfcomment_soul_markup:\thepc@count@iii}sp} \setlength{\pc@Sposy}{\zposy{pdfcomment_soul_markup:\thepc@count@iii}sp} \str_if_eq:eeT {\pc@lopt@subtype}{/StrikeOut} { \addtolength{\pc@Sposy}{1pt} } \setlength{\pc@Eposx}{\pc@Sposx} \addtolength{\pc@Eposx}{\ulwidth} \setlength{\pc@Eposy}{\pc@Sposy} \pc@annot@complete } \newcommand{\pc@calc@textblockpos} { \if@twoside \stepcounter{pc@count@ii} \label{pdfcomment:ts:page:\thepc@count@ii} \refused{pdfcomment:ts:page:\thepc@count@ii} \ifodd\getpagerefnumber{pdfcomment:ts:page:\thepc@count@ii} \if@twocolumn \ifpc@firstcolumn \renewcommand{\pc@x@left@text} {\pc@pttobp{ 1in + \hoffset + \oddsidemargin}} \renewcommand{\pc@x@right@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin + \columnwidth}}% \else \renewcommand{\pc@x@left@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin + \textwidth - \columnwidth}} \renewcommand{\pc@x@right@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin + \textwidth}} \fi \else \renewcommand{\pc@x@left@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin}} \renewcommand{\pc@x@right@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin + \textwidth}} \fi \else \if@twocolumn% \ifpc@firstcolumn% \renewcommand{\pc@x@left@text} {\pc@pttobp{1in + \hoffset + \evensidemargin}} \renewcommand{\pc@x@right@text} {\pc@pttobp{1in + \hoffset + \evensidemargin + \columnwidth}} \else \renewcommand{\pc@x@left@text} {\pc@pttobp{1in + \hoffset + \evensidemargin + \textwidth - \columnwidth}} \renewcommand{\pc@x@right@text} {\pc@pttobp{1in + \hoffset + \evensidemargin + \textwidth}} \fi \else \renewcommand{\pc@x@left@text} {\pc@pttobp{1in + \hoffset + \evensidemargin}} \renewcommand{\pc@x@right@text} {\pc@pttobp{1in\relax + \hoffset + \evensidemargin + \textwidth}} \fi \fi \else \if@twocolumn \ifpc@firstcolumn \renewcommand{\pc@x@left@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin}} \renewcommand{\pc@x@right@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin + \columnwidth}} \else \renewcommand{\pc@x@left@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin + \textwidth - \columnwidth}} \renewcommand{\pc@x@right@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin + \textwidth}} \fi \else \renewcommand{\pc@x@left@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin}} \renewcommand{\pc@x@right@text} {\pc@pttobp{1in + \hoffset + \oddsidemargin + \textwidth}} \fi \fi \renewcommand{\pc@y@top@text} {\pc@pttobp{\paperheight - 1in - \voffset - \topmargin - \headheight - \headsep}} \renewcommand{\pc@y@bottom@text} { \pc@pttobp {\paperheight - 1in - \voffset - \topmargin - \headheight - \headsep - \textheight } } } \newcommand{\pc@calc@sidelinepos} { \if@twoside \stepcounter{pc@count@ii} \label{pdfcomment:ts:page:\thepc@count@ii} \refused{pdfcomment:ts:page:\thepc@count@ii} \ifodd\getpagerefnumber{pdfcomment:ts:page:\thepc@count@ii} \renewcommand{\pc@x@one} {\pc@pttobp{ 1in + \hoffset + \oddsidemargin - \pc@lopt@linesep bp }} \renewcommand{\pc@x@two} {\pc@pttobp{ 1in + \hoffset + \oddsidemargin + \textwidth + \pc@lopt@linesep bp }} \else \renewcommand{\pc@x@one} {\pc@pttobp{ 1in + \hoffset + \evensidemargin - \pc@lopt@linesep bp }} \renewcommand{\pc@x@two} {\pc@pttobp{ 1in + \hoffset + \evensidemargin + \textwidth + \pc@lopt@linesep bp }} \fi \else \renewcommand{\pc@x@one} {\pc@pttobp{ 1in + \hoffset + \oddsidemargin - \pc@lopt@linesep bp }} \renewcommand{\pc@x@two} {\pc@pttobp{ 1in + \hoffset + \oddsidemargin + \textwidth + \pc@lopt@linesep bp }} \fi \renewcommand{\pc@y@one}{\pc@pttobp{ \pc@Sposy + \pc@box@height + 1pt}} \renewcommand{\pc@y@two}{\pc@pttobp{ \pc@Eposy - \pc@box@depth - 1pt}} \renewcommand{\pc@y@top@text} {\pc@pttobp{ \paperheight - 1in - \voffset - \topmargin - \headheight - \headsep}} \renewcommand{\pc@y@bottom@text} {\pc@pttobp{ \paperheight - 1in - \voffset - \topmargin - \headheight - \headsep - \textheight}} } % \end{macrocode} % \begin{macrocode} % % \end{macrocode}