summaryrefslogtreecommitdiffstats
path: root/tmac/pdfpic.tmac
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--tmac/pdfpic.tmac287
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: