From 32e0f5d0a5abc4f2b6c7341f19b854b5945c3ebd Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Tue, 21 Sep 2021 03:02:01 +0000 Subject: CTAN sync 202109210302 --- macros/luatex/generic/pdfextra/pdfextra.opm | 1728 +++++++++++++++++++++++++++ 1 file changed, 1728 insertions(+) create mode 100644 macros/luatex/generic/pdfextra/pdfextra.opm (limited to 'macros/luatex/generic/pdfextra/pdfextra.opm') diff --git a/macros/luatex/generic/pdfextra/pdfextra.opm b/macros/luatex/generic/pdfextra/pdfextra.opm new file mode 100644 index 0000000000..bccf096484 --- /dev/null +++ b/macros/luatex/generic/pdfextra/pdfextra.opm @@ -0,0 +1,1728 @@ +% vim: tw=80 +\_def\_pdfextra_version{0.2} +\_codedecl \RM {Extra PDF features (v\_pdfextra_version)} +\_namespace{pdfextra} + + \_doc + \sec Package initialization + + We ensure that hyperlinking is active. Our fallback \`\_linkcolor` must + exist. We also use it for `\hyperlinks` if the user didn't enable + `\hyperlinks` yet (we don't want to override user setting). + \_cod + +\_ifdefined\_ilinkcolor\_else + \_ifdefined\_linkcolor + \_ea\_let\_ea\_linkcolor \_ifdefined\Blue\Blue\_else\_empty\_fi + \_else + \_let\_linkcolor\linkcolor + \_fi +\_fi + +\_ifx\_dest\_destactive\_else + \_hyperlinks\_linkcolor\_linkcolor +\_fi + + \_doc + We are in the \OpTeX/ package namespace. A couple of shortcuts are defined + here: \`\.isdefined`, \`\.trycs`, \`\.cs` \`\.slet`, \`\.slet`, \`\.sdef` and + \`\.sxdef`. They all hard code the package name, because we already have too + many levels of indirection. + \_cod + +\_def\.isdefined#1{\_isdefined{_pdfextra_#1}} +\_def\.trycs#1{\_trycs{_pdfextra_#1}} +\_def\.cs#1{\_cs{_pdfextra_#1}} +\_def\.slet#1#2{\_slet{_pdfextra_#1}{_pdfextra_#2}} +\_def\.sdef#1{\_sdef{_pdfextra_#1}} +\_def\.sxdef#1{\_sxdef{_pdfextra_#1}} + + \_doc + \sec Helper macros + The macros here are just helpers for the macros to follow. They are not + useful generally, but proved useful in the expandable context of writing to + PDF files. + + Already the first one limits the use to \LuaTeX/ (but who needs other engines + anyways :). \`\.emptyor` checks whether the first argument is empty, if not it expands the + second argument which can use the text from the first argument with + \`\.nonempty`. \`\.attrorempty` builds upon the first + one and is really useful for PDF dictionaries, when we don't want to write an + attribute without a value (a default specified by standard will be used instead). + \_cod + +\_def\.emptyor#1#2{% + \_immediateassignment\_edef\.nonempty{#1}% + \_ifx\.nonempty\_empty\_else #2\_fi +} +\_def\.attrorempty#1#2{\.emptyor{#2}{/#1 \.nonempty}} + + \_doc + There is a dillema for handling colors. While typesetting it is possible to + use greyscale, CMYK or RGB colors. But there are contexts where it is + possible to only use RGB colors. We want to provide the user with two + possibilities of specifying colors: + + \begitems + * RGB color using PDF triplet (e.g. `1 0 0`), + * \OpTeX/ color using control sequence (e.g. `\Blue`) + \enditems + + Both are handled by \`\.colortorgbdef`, which + defines to the corresponding PDF RGB triplet. The indirection with + defining a macro is because we want to use the processed color within + expansion only contexts where grouping is not possible. + \_cod + +\_def\.colortorgbdef#1#2{\_bgroup + \_def\_setrgbcolor##1{##1}% + \_def\_setcmykcolor##1{\_cmyktorgb ##1 ;}% + \_def\_setgreycolor##1{##1 ##1 ##1}% + \_xdef#1{#2}% + \_egroup +} + + \_doc + \`\.xaddto``\macro`{} is a natural extension of \OpTeX's `\addto` that + expands and is global.\nl + \`\.tmp` is used throught the package for temporary values. + \_cod + +\_def\.xaddto#1#2{\_edef\.tmp{#2}% + \_global\_ea\_addto\_ea#1\_ea{\.tmp}% +} + + \_doc + This package defines a few commands in the form + `\macro[][]{}`. To make it possible to omit + the `[]` \`\.secondoptdef` is defined. + + `\.secondoptdef\{}` + defines `\macro` with first mandatory argument in brackets (saved to + \`\.name`). Second optional argument in brackets is scanned using helper + macro defined with `\optdef` and is saved to `\_opt` token list). Additional + can be specified as with `\optdef` (numbered from `#1`). + \_cod + +\_def\.secondoptdef#1{% + \_def#1[##1]{\_def\.name{##1}\.cs{sopt:\_string#1}}% + \_ea\_optdef\_csname _pdfextra_sopt:\_string#1\_endcsname[]% +} + + \_doc + When processing comma separated lists sometimes it is needed to ignore the + remaining text. For this we use \`\.untilend` macro which ignores everything + up to dummy \`\.end`. This is analogous to \OpTeX/'s `\_finbody` used for the + same purpose. Sometimes `\.end` is used as sentinel and compared in `\ifx` + tests, hence we define it to a unique value. + \_cod + +\_def\.untilend#1\.end{} +\_def\.end{_pdfextra_end} + + \_doc + For various uses it is necessary to know the number of page where something + happens. This has to be handled asynchronously with `\write`. Here we use + \OpTeX/ specific `.ref` file and associated macros, but this could be + replaced as long as the same interface is exposed. + + \`\.setpageof` writes \`\.Xpageof` to the `.ref` file. In the next + \TeX/ run `\.Xpageof` finds out the page number (`\gpageno`) from \OpTeX/'s + `\_currpage` and saves it so that \`\.pageof` can retrieve it. In the + first run we can't be sure of the page where the content will end up. As a + rough estimate we take the current page~-- this actually works well for + slides where page breaks are manual. + + When `.ref` file is read along with the defintion of `\.Xpageof` this package + has not been loaded yet. Hence we can't use namespaced variants of + `\.isdefined`, etc. + \_cod + +\_refdecl{% + \_def\.Xpageof#1{\_isdefined{_pdfextra_pageof:#1}\_iffalse + \_sxdef{_pdfextra_pageof:#1}{\_ea\_ignoresecond\_currpage}\_fi + }% +} + +\_def\.setpageof#1{\_openref \_ewref\.Xpageof{{#1}}} + +\_def\.pageof#1{% + \.trycs{pageof:#1}{% + \_the\_numexpr\_gpageno+1\_relax % best effort = current page num + }% +} + + \_doc + \label[files] + \sec Handling of files + + Handling of files is a big topic of this package. Files are everywhere~-- + files containing multimedia, JavaScript script files, attachments, externally + referred files\dots Therefore a more sophisticated mechanism for handling + files is needed. The mechanism introduced in this section handles all three + cases of a {\em file specification}: + + \begitems + * files embedded in the PDF (\"e", embedded file), + * files determined by path (\"x", external file), + * files determined by URL (\"u", url file). + \enditems + + Although ideally all three would be interchangible this is not always the + case, because e.g. some media files must be embedded and linking to external + resources does not work with embedded files. + + In most cases there are two many names and other associated values involved: + \begitems + * Some kind of a \"friendly" name. This one is sometimes shown by PDF viewers. + * The real name of the file. Also shown but in different contexts. + * The path or URL used to determine the file. + * MIME type of the file. + \enditems + + For example when talking about \OpTeX/'s documentation we might have a + friendly name of \"opdoc", file name of \"`optex-doc.pdf`", URL of + \"\url{http://petr.olsak.net/ftp/olsak/optex/optex-doc.pdf}" and MIME type of + \"application/pdf". Different subset of them is required in different + contexts, but the user should only have to specify the friendly name (by + which they will refer to the file) and the path/URL of the file. The rest + will be deduced. The friendly name is used as a handle and {\em is usable} + in all places where file specification is required (although it may not + produce conforming output, see above). + + In this two step process~-- definition and (re)use~-- we introduce a command + for defining files: \`\filedef``/ []{}`. The + macro itself does general definitions and dispatches the type dependant work + to other macros in the form `_filedef:`. + \_cod + +\_def\.filedef/#1#2[#3]#4{% + \.sxdef{filename:#3}{(\.filename{#4})}% + \_edef\.tmp{\.exttomime{\.fileext{#4}}}% + \_ifx\.tmp\_empty + \_opwarning{MIME type of '#4' unknown, using '\.defaultmimetype'}% + \_edef\.tmp{\.defaultmimetype}% + \_fi + \.sxdef{filemime:#3}{\.tmp}% + \.cs{filedef:#1}{#3}{#4}% +} +\_nspublic \filedef ; + + \_doc + Types \"e", \"x", \"u" are predefined, anything else would essentialy be a + variant of these. + + External file (\"x") is determined only by path. + \_cod + +\.sdef{filedef:x}#1#2{% + \.slet{filespec:#1}{filename:#1}% +} + + \_doc + URL file (\"u") is determined by URL. Using all sorts of characters is + allowed by using `\_detokenize`. This time it is necessary to create full + {\em file specification}~-- a dictionary, where the \"file system" is URL. + \_cod + +\.sdef{filedef:u}#1#2{% + \.sdef{filespec:#1}{<>}% +} + + \_doc + Embedded files (\"e") are the most interesting ones. For further use (e.g. + for displaying the embedded files as attachments) MIME type is required. It + is saved in the stream as a `\Subtype`, encoded as a PDF name (e.g. + `/video#2Fmp4`). The embedded file stream must be wrapped in a full {\em file + specification}, which has the `/EF` (\"embedded file") entry. Also the + friendly name is used for some purpose by PDF viewers, so it set in `/Desc` + (description). + \_cod + +\.sdef{filedef:e}#1#2{% + \_edef\.tmp{\.cs{filemime:#1}}% + \_isfile{#2}\_iffalse + \_opwarning{file '#2' not found}% + \_fi + \_pdfobj stream + attr{/Type /EmbeddedFile /Subtype \_ea\.mimetoname\_ea[\.tmp]} + file {#2}% + \_pdfrefobj\_pdflastobj + \.sxdef{filestream:#1}{\_the\_pdflastobj\_space 0 R}% + \_pdfobj {<>% + >>}% + \_pdfrefobj\_pdflastobj + \.sxdef{filespec:#1}{\_the\_pdflastobj\_space 0 R}% +} + + \_doc + Now the less interesting part~-- determining the file names from paths and + determining MIME types. The file name is the part after the last \"`/`" (if + any). The file extension is the part after last \"`.`" (if any). + \_cod + +\_def\.filename#1{\_ea\.filenameA#1/\.end} +\_def\.filenameA#1/#2{\_ifx\.end#2#1\_else\_afterfi{\.filenameA#2}\_fi} + +\_def\.fileext#1{\_ea\.fileextA#1.\.end} +\_def\.fileextA#1.#2{\_ifx\.end#2#1\_else\_afterfi{\.fileextA#2}\_fi} + + \_doc + MIME type is determined from file extension (e.g. `mp4` is \"video/mp4"). For + mapping of file extensions to MIME types we abuse \TeX/'s hash table which + gets populated with \"known MIME types". This necessarily means that the + database is incomplete. Users can define their own additional mappings, or + they can contribute generally useful ones to this package. + + The default MIME type (used for unknown file extensions) is + \"application/octet-stream"~-- binary data. + + The uninteresting MIME type database itself is at the very end (\ref[mime]). + \_cod + +\_def\.mimetoname[#1/#2]{/#1\_csstring\#2F#2} + +\_def\.defaultmimetype{application/octet-stream} +\_def\.exttomime#1{\.trycs{mimetype:#1}{}} + + \_doc + Here we define an \OpTeX/ style \"is-macro" that checks whether the file has + already been defined~-- \`\.isfiledefined``{}\iftrue` (or `\iffalse`). + The case where the file has not + been defined using `\filedef` can be handled in a lot of ways. As a default + we interpret as path and try to embed it. Because the path from + is used as the \"friendly name" the file will be embedded only once even when + requested more times. + \_cod + +\_def\.isfiledefined#1#2{\.isdefined{filespec:#1}\_iftrue\_else + \_afterfi{\.fileundefined{#1}}\_fi#2% +} + +\_def\.fileundefined#1{\_isfile{#1}\_iftrue\.filedef/e[#1]{#1}\_else + \_opwarning{file '#1' not found, ignored}\_ea\_unless\_fi +} + +% strict requirement of preceeding `\filedef` can be set like this: +%\_def\.fileundefined#1{\_opwarning{file '#1' is not defined, ignored}\_unless} + + \_doc + \label[actions] + \sec PDF actions + + The core of interactivity in PDF are actions. They are all initialy handled + by \`\pdfaction``[]`. is a comma separated list of + `:`. Leading spaces in the elements of the list are ignored + using undelimited-delimited argument pair trick. + + An invocation could look like this: + + \begtt + \pdfaction[ + js:{app.alert("Yay JavaScript, going to page 5");}, + ilink:pg:5, + transition:Wipe, + ] + \endtt + + This is why we have to be very careful when loading the contents between `[]` + to arguments. In particular, we can't split immediatly using `[#1:#2]`, + because this would discard the braces guarding the comma in the JavaScript + code. However we also need to find out the {\em type} of action which is + taken as a type of the first action (`js` in this case). + \`\.pdfactiontype``[]` does this~-- we don't mind that there the + braces are lost. + + `\pdfaction` processes the list, to create a chain of actions using `/Next` + field. The handling of each action type is up to macro + `\_pdfextra_action`, which receives `[:]`. Because of + this a single type handler can handle multiple different actions, as is the + case with `\.ilinkaction` which is the fallback for unknown action types. + \_cod + +\_def\.pdfaction[#1#2]{\.pdfactionA#1#2,\.stop\.end} +\_def\.pdfactionA#1,#2#3\.end{% + <<% + \.pdfactionB[#1]% + % next action + \_ifx\.stop#3\_else\_space + /Next \_afterfi{\.pdfactionA#2#3\.end} % intentional space + \_fi + >> +} +\_def\.pdfactionB[#1:#2]{\.trycs{#1action}{\_ea\.ilinkaction}[#1:#2]} +\_nspublic \pdfaction ; + +\_def\.pdfactiontype[#1:#2]{#1} + + \_doc + \label[actions-additional] + \secc Additional actions + Some PDF objects, like pages and some annotations, can also have \"additional + actions". These are actions which will be executed when an event happens~-- + like page getting opened for `/O` action in page's additonal actions or `/PO` + in annotation's additional actions. For constructing these additional actions + we define a helper macro \`\.pdfaactions`. The use is as something follows: + \begtt \catcode`<=13 \adef|{\csstring<} + /AA || \.pdfaactions{ {O} {} {C} {} } >> + \endtt + To produce something this: + \begtt \catcode`<=13 \adef|{\csstring<} + /AA || /O ||>> /C ||>> >> + \endtt + \_cod + +\_def\.pdfaactions#1{<<\.pdfaactionsA #1\.end\.end>>} +\_def\.pdfaactionsA#1#2{\_ifx\.end#1\_else /#1 \_ea\.pdfaction\_ea[#2]\_ea\.pdfaactionsA\_fi} + + \_doc + \label[actions-link] + \secc Link annotations + The main use of actions~-- annotations of `/Subtype /Link`. Annotation of + this type creates an active rectangular area on the page that executes a PDF + action (or chain of them in the general case). + \`\hlink``[]` is macro that typesets and makes area + occupied by it active according to . All action types are + supported, the mechanism is completely generic. + + The `\pdfstartlink`/`\pdfendlink` primitives are used to denote the part of + the page where appears as active. \LuaTeX/ will then handle even the + situations where gets broken across multiple lines (by creating + multiple rectangular annotations to cover all `\hbox`es). + \_cod + +\_def\.hlink[#1]#2{\_bgroup\_def\#{\_csstring\#}% + \_edef\.type{\.pdfactiontype[#1]}% + \_quitvmode\_pdfstartlink \.linkdimens + attr{\_pdfborder{\.type}}% + user{/Subtype /Link /A \.pdfaction[#1]}\_relax + \_localcolor\.linkcolor{\.type}#2\_pdfendlink\_egroup +} + +\_nspublic \hlink ; + + \_doc + Use `\hlink` as the backing command for OpTeX's \"higher level" linking + commands (`\ilink` and `\ulink`). + + The lower level ones (`\xlink` and its predecessor `\link` actually have + completely different semantics with regards to color, so we keep them as they + are. + \_cod + +\_protected\_def\_ilink[#1]#2{\.hlink[#1]{#2}} +\_protected\_def\_ulink[#1]#2{{\_escapechar=-1 \_ea}\_expanded + {\_noexpand\.hlink[url:\_detokenize{#1}]}{#2}} + +\_public \link \ilink \ulink ; + +%\_protected\_def\_link[#1]#2#3{\_hlink[#1]{#3}} +%\_protected\_def\_xlink#1#2#3#4{\_hlink[#1:#2]{#4}} + + \_doc + Two customizations of `\hlinks` are possible: + \begitems + * Dimensions of rectangular areas created by + `\pdfstartlink`/`\pdfendlink`. This is done using \`\.linkdimens` + (analogous to \OpTeX's `\linkdimens`). Dimensions that are unset are taken + from the respective `\hbox`es. \`\lininglinks` sets the dimensions for + running text~-- it covers all space of a line using `\baselineskip`. + \`\nolininglinks` sets no dimensions, this is useful for buttons, that may + have larger height/depth than a line. + * The color is determined from the type of link (that is, the first action in + ) by checking `\_linkcolor` (compatible with \OpTeX/). + As a fallback `\_ilinkcolor` is used (set by \OpTeX's `\hyperlinks`) for all links + except for URLs, where `\_elinkcolor` is used instead. If even these + fallback colors are not defined (`\hyperlinks` isn't used), then the most + generic `\_linkcolor` will be taken or no color will be set. + \enditems + \_cod + +\_def\.lininglinks{% + \_def\.linkdimens{height.75\_baselineskip depth.25\_baselineskip}% +} +\_def\.nolininglinks{\_def\.linkdimens{}} +\.lininglinks + +\_nspublic \lininglinks \nolininglinks ; + +\_def\.linkcolor#1{\_trycs{_#1linkcolor}{\_trycs{_ilinkcolor}{\_trycs{_linkcolor}{}}}} + + % \_urllinkcolor = \_elinkcolor with fallbacks +\_def\_urllinkcolor{\.linkcolor{e}} + + \_doc + \secc Open action + The document itself has one action defined in the document catalog. It is + called `/OpenAction`. We allow the user to set it using the familiar + syntax with the command \`\openaction``[]`. + + Internally we could directly set it by appending to the catalog + using the primitive `\pdfcatalog`, but \LuaTeX/ (pdf\TeX/ really) allows + setting the action with special syntax. This has the benefit that it is not + allowed to set the action more than once. + \_cod + +\_def\.openaction[#1]{\_pdfcatalog{} openaction user{\.pdfaction[#1]}\_relax} +\_nspublic \openaction ; + + \_doc + \label[actions-jump] + \secc Jump actions + + These are the most typical actions. Even \LuaTeX/ itself handles them, + although we don't use the possibility for maintaining generality. There are a + few types of jump actions: + \begitems + * `/GoTo` actions are the classic internal links to named destinations in the + PDF file (created by `\pdfdest` primitive or \OpTeX/'s `\dest`). The + destination names include also the type of internal link (e.g. + `ref:section1`). They are handled by \`\.ilinkaction``[:]`. + * `/URI` actions which are in most cases used as \"goto URL" actions. These + are not that useful directly, because special characters should be handled + before this actions is used (like with `\url`). The low level use is + \`\.urlaction``[url:]`. + * \"Goto remote" actions, which can jump to a destination in another PDF file~-- + either determined by name, or by page number. The external files are + expected to be defined by `\filedef` (but not the embedded variant). The + use is either \`\.extrefaction``[extref::]` for + links to named destination or \`\.extpgrefaction``[extpgref::]` + for page destinations. Customization is possible with \`\.extrefextra`, by + default opening in a new windows is requested. + \enditems + \_cod + +\_def\.ilinkaction[#1:#2]{/S /GoTo /D (#1:#2)} + +\_def\.urlaction[#1:#2]{/S /URI /URI (#2)} + +\_def\.extrefaction[#1:#2:#3]{/S /GoToR + /F \.cs{filespec:#2} + /D (#3) + \.extrefextra +} +\_def\.extpgrefaction[#1:#2:#3]{/S /GoToR + /F \.cs{filespec:#2} + /D [\_the\_numexpr#3-1\_relax\_space /Fit] + \.extrefextra +} + +\_def\.extrefextra{/NewWindow true} + + + \_doc + Transition action is not really a jump action in of itself, but is only + useful when chained after jump actions, so we define it here. Transitions + (as page attributes) are handled more thoroughly in section~\ref[transitions]. + + The use would look something like:\nl + \`\.transitionaction`% + `[transition:::]`, where all fields + omitted from right take the default values. + \_cod + +\_def\.transitionaction[#1:#2]{/S /Trans \.attrorempty{Trans}{\.maketrans[#2]}} + + \_doc + \secc Named actions + + User can request arbitrary \"named" action with + \`\.namedaction``[named:]`. See user documentation for details. + \_cod + +\_def\.namedaction[#1:#2]{/S /Named /N /#2} + + \_doc + \secc JavaScript actions + + JavaScript actions have two forms, either \`\.jsaction``[js:]` or + `\.jsaction``[js: