288 lines
8.3 KiB
Plaintext
288 lines
8.3 KiB
Plaintext
.\" 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:
|