.\" 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:
|