diff options
Diffstat (limited to '')
-rw-r--r-- | tmac/pdfpic.tmac | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/tmac/pdfpic.tmac b/tmac/pdfpic.tmac new file mode 100644 index 0000000..f81b66e --- /dev/null +++ b/tmac/pdfpic.tmac @@ -0,0 +1,287 @@ +.\" Define the PDFPIC macro. +.\" +.\" When used with output devices other than `pdf`, convert image to +.\" encapsulated PostScript and process it with PSPIC. +.\" +.\" Usage: +.\" +.\" .PDFPIC [-L|-R|-C|-I <indentation>] <file> [<width> [<height>]] +.\" +.\" Requires the poppler-utils package (for pdfinfo(1) and pdftops(1)). +.\" Requires running troff(1) in unsafe mode. +. +.do if d PDFPIC .nx +. +.do nr *groff_pdfpic_tmac_C \n[.cp] +.cp 0 +. +.\" Locate a directory to house temporary files. Check each argument +.\" in turn, confirming its existence, writability, and searchability. +.\" +.\" `pdfpic*temporary-directory` contains its name if one is found, and +.\" is empty otherwise. +.de pdfpic@get-temporary-directory +. ds pdfpic*temporary-directory \" empty +. while !'\\$1'' \{\ +. sy test -d \\$1 && test -w \\$1 && test -x \\$1 +. if \\n[systat]=0 .ds pdfpic*temporary-directory \\$1 +. ie '\\*[pdfpic*temporary-directory]'' .shift +. el .break +. \} +.. +. +.\" A user may wish to append an 'ab' to this macro using 'am'. That +.\" is why we don't 'return X' from here to return from two scopes. +.de pdfpic@error +. tm pdfpic.tmac:\\n[.F]:\\n[.c]: error: \\$* +.. +. +.de pdfpic@cleanup +. rm pdfpic*pspic-args +. rm pdfpic*file-extension +. rm pdfpic*file-name-base +. rm pdfpic*temporary-directory +. rm pdfpic*temporary-file +. rr pdfpic*do-conversion +. rr pdfpic*offset-mode +. rr pdfpic*indentation +. rr pdfpic*width +. rr pdfpic*height +. rr pdfpic*did-pdfinfo-work +. rr pdfpic*desired-width +. rr pdfpic*desired-height +.. +. +.de PDFPIC +. if !\\n[.U] \{\ +. pdfpic@error use of \\$0 requires GNU troff's unsafe mode \ +(-U option) +. return +. \} +. +. \" Dispose of junk from any previous early return. +. pdfpic@cleanup +. +. nr pdfpic*do-conversion 0 +. if !'\\*[.T]'pdf' .nr pdfpic*do-conversion 1 +. +. nr pdfpic*offset-mode 0 +. +. \" Preserve the trailing space in definitions of pdfpic*pspic-args. +. +. \" left-aligned? +. ie '\\$1'-L' \{\ +. nr pdfpic*offset-mode 1 +. if \\n[pdfpic*do-conversion] .ds pdfpic*pspic-args \\$1 \" +. shift +. \} +. el \{\ +. \" right-aligned? +. ie '\\$1'-R' \{\ +. nr pdfpic*offset-mode 2 +. if \\n[pdfpic*do-conversion] .ds pdfpic*pspic-args \\$1 \" +. shift +. \} +. el \{\ +. \" indented? +. ie '\\$1'-I' \{\ +. nr pdfpic*offset-mode 3 +. nr pdfpic*indentation (m;\\$2) +. if \\n[pdfpic*do-conversion] .ds pdfpic*pspic-args \\$1 \\$2 \" +. shift 2 +. \} +. el \{\ +. \" centered is the default +. ie '\\$1'-C' \{\ +. if \\n[pdfpic*do-conversion] .ds pdfpic*pspic-args \\$1 \" +. shift +. \} +. el .nr pdfpic*offset-mode 0 +. \} +. \} +. \} +. br +. +. ds pdfpic*file-extension \\$1\" +. substring pdfpic*file-extension -4 +. stringdown pdfpic*file-extension +. if !'\\*[pdfpic*file-extension]'.pdf' \{\ +. pdfpic@error '\\$1' lacks a '.pdf' extension; skipping +. return +. \} +. +. \" Ensure the file exists and is readable. +. \" +. \" This test is subject to a time-of-check-to-time-of-use (TOCTTOU) +. \" attack (or a simple race with a concurrent `rm` command, for +. \" instance). +. sy test -r \\$1 +. if \\n[systat]!=0 \{\ +. pdfpic@error '\\$1' does not exist or is not readable; skipping +. return +. \} +. +. \" if driver is not gropdf, convert image to .eps +. if \\n[pdfpic*do-conversion] \{\ +. ds pdfpic*file-name-base \\$1 +. substring pdfpic*file-name-base 0 -5 +. +. sy pdftops -eps \\$1 +. shift +. +. as pdfpic*pspic-args \\*[pdfpic*file-name-base].eps \\$* +. +. PSPIC \\*[pdfpic*pspic-args] +. return +. \} +. +. pdfpic@get-temporary-directory \\V[GROFF_TMPDIR] \\V[TMPDIR] +. +. if 'pdfpic*temporary-directory'' \{\ +. \" Figure out if we're on a Windows system (with a Unix shell). +. nr pdfpic*is-on-windows 0 +. +. sy expr $(uname -s) : "CYGWIN.*" > /dev/null +. if \\n[systat]=0 .nr pdfpic*is-on-windows 1 +. sy expr $(uname -s) : "MINGW.*" > /dev/null +. if \\n[systat]=0 .nr pdfpic*is-on-windows 1 +. +. if \\n[pdfpic*is-on-windows] \ +. pdfpic@get-temporary-directory \\V[TEMP] \\V[TMP] +. +. rr pdfpic*is-on-windows +. \} +. +. if '\\*[pdfpic*temporary-directory]'' \ +. pdfpic@get-temporary-directory /tmp +. +. if '\\*[pdfpic*temporary-directory]'' \{\ +. pdfpic@error cannot locate a usable temporary directory; \ +skipping '\\$1' +. return +. \} +. ds pdfpic*temporary-file \\*[pdfpic*temporary-directory]/pdfpic\n[$$] +. +. \" Get image dimensions. The `tr` command to strip null bytes is +. \" distasteful, but its necessity is imposed on us. See +. \" <https://gitlab.freedesktop.org/poppler/poppler/-/issues/776>. +. ec @ +. sy pdfinfo @$1 | \ +tr -d '\000' | \ +grep "Page *size" | \ +sed -e 's/Page *size: *\\([[:digit:].]*\\) *x *\\([[:digit:].]*\\).*$/\ +.nr pdfpic*width (p;\\1)\\n\ +.nr pdfpic*height (p;\\2)/' \ +> @*[pdfpic*temporary-file] +. ec +. if \\n[systat] \{\ +. pdfpic@error retrieval of '\\$1' image dimensions failed with \ +exit status \\n[systat]; skipping +. return +. \} +. so \\*[pdfpic*temporary-file] +. sy rm \\*[pdfpic*temporary-file] +. +. nr pdfpic*did-pdfinfo-work 1 +. if !r pdfpic*width .nr pdfpic*did-pdfinfo-work 0 +. if !r pdfpic*height .nr pdfpic*did-pdfinfo-work 0 +. if !\\n[pdfpic*did-pdfinfo-work] \{\ +. pdfpic@error retrieval of '\\$1' image dimensions failed; skipping +. return +. \} +. rr pdfpic*did-pdfinfo-work +. +. \" reject nonsense dimensions <= 0 (and avoid zero divide later) +. if !\\n[pdfpic*width] \{\ +. pdfpic@error '\\$1' reports image width of \\n[pdfpic*width]u; \ +skipping +. return +. \} +. if !\\n[pdfpic*height] \{\ +. pdfpic@error '\\$1' reports image height of \\n[pdfpic*height]u; \ +skipping +. return +. \} +. +. \" if we have a <width> parameter, use it as the final +. \" image width; otherwise we use the image's natural width +. \" or the current line length, whatever is smaller +. ie (\\n[.$] >= 2) \{\ +. nr pdfpic*desired-width (i;\\$2) +. if !\\n[pdfpic*desired-width] \{\ +. pdfpic@error rejecting desired image width of \ +\\n[pdfpic*desired-width]u; skipping '\\$1' +. return +. \} +. \} +. el \ +. nr pdfpic*desired-width ((\\n[.l] - \\n[.i]) <? \\n[pdfpic*width]) +. +. if (\\n[.$] >= 3) \{\ +. nr pdfpic*desired-height (i;\\$3) +. if !\\n[pdfpic*desired-height] \{\ +. pdfpic@error rejecting desired image height of \ +\\n[pdfpic*desired-height]u; skipping '\\$1' +. return +. \} +. \} +. \" We have no else clause; pdfpic*desired-height will get clobbered +. \" anyway. +. +. \" compute the final image height (with proper rounding), +. \" based on the image's aspect ratio +. nr pdfpic*desired-height (\\n[pdfpic*desired-width] * 1000 \ + + (\\n[pdfpic*width] / 2) \ + / \\n[pdfpic*width] * \\n[pdfpic*height] \ + + 500 / 1000) +. +. \" if we have a <height> parameter, use it as the final +. \" image height in case it is smaller than the height +. \" value we have just computed +. if ((\\n[.$] >= 3) & (\\n[pdfpic*desired-height] > (i;0\\$3))) \{\ +. nr pdfpic*desired-height (i;\\$3) +. \" recompute the final image width since we always +. \" keep the correct image aspect +. nr pdfpic*desired-width (\\n[pdfpic*desired-height] * 1000 \ + + (\\n[pdfpic*height] / 2) \ + / \\n[pdfpic*height] * \\n[pdfpic*width] \ + + 500 / 1000) +. \} +. +. \" reserve vertical space for image +. ne (\\n[pdfpic*desired-height]u + 1v) +. +. \" compute image offset w.r.t. the current left margin +. if (\\n[pdfpic*offset-mode] == 0) \ +. nr pdfpic*indentation \ + (\\n[.l] - \\n[.i] - \\n[pdfpic*desired-width] / 2) +. if (\\n[pdfpic*offset-mode] == 1) \ +. nr pdfpic*indentation 0 +. if (\\n[pdfpic*offset-mode] == 2) \ +. nr pdfpic*indentation \ + (\\n[.l] - \\n[.i] - \\n[pdfpic*desired-width]) +. +\h'\\n[pdfpic*indentation]u'\ +\X'pdf: pdfpic \\$1 -L \\n[pdfpic*desired-width]z \ +\\n[pdfpic*desired-height]z' +. if !r PDFPIC_NOSPACE \{\ +. nr PDFPIC_NOSPACE 0 +. if \B'\\V[GROFF_PDFPIC_NOSPACE]' \ +. nr PDFPIC_NOSPACE \\V[GROFF_PDFPIC_NOSPACE] +. \} +. if \\n[PDFPIC_NOSPACE]=0 \{\ +. br +. sp \\n[pdfpic*desired-height]u +. \} +. +. pdfpic@cleanup +.. +. +.cp \n[*groff_pdfpic_tmac_C] +.do rr *groff_pdfpic_tmac_C +. +.\" Local Variables: +.\" mode: nroff +.\" fill-column: 72 +.\" End: +.\" vim: set expandtab filetype=groff tabstop=2 textwidth=72: |