.\" 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.
.\"
.\" Internal macro names start with `pdfpic@`; internal registers and
.\" strings start with `pdfpic*`.
.
.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
.  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
..
.
.\" Get image dimensions.
.\"
.\" The following is a circus of portability and escaping constraints.
.\" See <https://savannah.gnu.org/bugs/?64061>.
.\"
.\" We therefore shut off roff's escape mechanism _twice_: once while
.\" defining the macro, and once while interpreting part of it, to
.\" preserve backslashes that we need in the constructed C string.
.\"
.\" We _still_ must escape the backslashes in the string appendments to
.\" keep them from being interpreted as commencing roff escape sequences
.\" when the string they populate is later interpolated.
.eo
.de pdfpic@get-image-dimensions
.  ds pdfpic*command pdfinfo \$1 2>/dev/null \"
.  eo
.  as pdfpic*command  | perl -ne 'print qq(. \\\\R\@pdfpic*width ${1}p@ \\\\R\@pdfpic*height ${2}p\@),qq(\\n) if m/Page\s+size:\s+([\d.]+)\sx\s([\d.]+)/si;'
.  ec
.  pso \*[pdfpic*command]
.  if !r pdfpic*width \{\
.    ds pdfpic*command ( identify \$1 2>/dev/null || file \$1 ) \"
.    eo
.    as pdfpic*command  | perl -ne 'print qq(. \\\\R\@pdfpic*width ${1}p@ \\\\R\@pdfpic*height ${2}p\@),qq(\\n) if m/(?:[,=A-Z]|JP2) (\d+)\s*x\s*(\d+)/';
.    ec
.    pso \*[pdfpic*command]
.  \}
.  rm pdfpic*command
..
.ec
.
.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
.
.  \" 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-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
.    \}
.
.    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]
.    pdfpic@cleanup
.    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
.  \}
.
.  pdfpic@get-image-dimensions \\$1
.  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:
