Skip to content

Commit

Permalink
LaTeX writer: new method for ensuring images don't overflow.
Browse files Browse the repository at this point in the history
Previously we relied on graphicx internals and made global
changes to Gin to force images to be resized if they exceed
textwidth.  This approach is brittle and caused problems
with `\includesvg` (see #9660).

The new approach uses a new macro `\pandocbounded` that is
now defined in the LaTeX template. (Thanks here to Falk Hanisch in
mrpiggi/svg#60.)

The LaTeX writer has been changed to enclose `\includegraphics`
and `\includesvg` commands in this macro when they don't explicitly
specify a width or height.

In addition, the writer now adds `keepaspectratio` to the
`\includegraphics` or `\includesvg` options if `height` is specified
without width, or vice versa. Previously, this was set in the preamble
as a global option.

Compatibility issues:

- If custom templates are used with the new LaTeX writer, they will have
  to be updated to include the new `\pandocbounded` macro, or an error
  will be raised because of the undefined macro.

- Documents that specify explicit dimensions for an image may render
  differently, if the dimensions are greater than the line width or
  page height. Previously pandoc would shrink these images to fit,
  but the new behavior takes the specified dimensions literally.
  In addition, pandoc previously always enforced `keepaspectratio`,
  even when width and height were both specified, so images with
  width and height specified that do not conform to their intrinsic
  aspect ratio will appear differently.

Closes #9660.
  • Loading branch information
jgm committed Jun 23, 2024
1 parent 965de61 commit 26b25a4
Show file tree
Hide file tree
Showing 8 changed files with 36 additions and 25 deletions.
18 changes: 10 additions & 8 deletions data/templates/default.latex
Original file line number Diff line number Diff line change
Expand Up @@ -302,15 +302,17 @@ $endif$
$if(graphics)$
\usepackage{graphicx}
\makeatletter
\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}
\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}
\makeatother
% Scale images if necessary, so that they will not overflow the page
% margins by default, and it is still possible to overwrite the defaults
% using explicit options in \includegraphics[width, height, ...]{}
\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}
\newsavebox\pandoc@box
\newcommand*\pandocbounded[1]{% scales image to fit in text height/width
\sbox\pandoc@box{#1}%
\Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%
\Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%
\ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both
\ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%
\else\usebox{\pandoc@box}%
\fi%
}
% Set default figure placement to htbp
\makeatletter
\def\fps@figure{htbp}
\makeatother
$endif$
Expand Down
10 changes: 8 additions & 2 deletions src/Text/Pandoc/Writers/LaTeX.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,9 @@ inlineToLaTeX (Image attr@(_,_,kvs) _ (source, _)) = do
[d <> "\\textheight"]
_ -> []
optList = showDim Width <> showDim Height <>
(case (dimension Height attr, dimension Width attr) of
(Just _, Just _) -> []
_ -> ["keepaspectratio"]) <>
maybe [] (\x -> ["page=" <> literal x]) (lookup "page" kvs) <>
maybe [] (\x -> ["trim=" <> literal x]) (lookup "trim" kvs) <>
maybe [] (const ["clip"]) (lookup "clip" kvs)
Expand All @@ -1100,8 +1103,11 @@ inlineToLaTeX (Image attr@(_,_,kvs) _ (source, _)) = do
inHeading <- gets stInHeading
return $
(if inHeading then "\\protect" else "") <>
(if isSVG then "\\includesvg" else "\\includegraphics") <>
options <> braces (literal source'')
(case dimension Width attr `mplus` dimension Height attr of
Just _ -> id
Nothing -> ("\\pandocbounded" <>) . braces)
((if isSVG then "\\includesvg" else "\\includegraphics") <>
options <> braces (literal source''))
inlineToLaTeX (Note contents) = do
setEmptyLine False
externalNotes <- gets stExternalNotes
Expand Down
2 changes: 1 addition & 1 deletion test/Tests/Writers/LaTeX.hs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ tests = [ testGroup "code blocks"
"\\begin{description}\n\\item[foo] ~ \n\\subsection{bar}\n\nbaz\n\\end{description}"
, "containing image" =:
header 1 (image "imgs/foo.jpg" "" (text "Alt text")) =?>
"\\section{\\texorpdfstring{\\protect\\includegraphics{imgs/foo.jpg}}{Alt text}}"
"\\section{\\texorpdfstring{\\protect\\pandocbounded{\\includegraphics[keepaspectratio]{imgs/foo.jpg}}}{Alt text}}"
]
, testGroup "inline code"
[ "struck out and highlighted" =:
Expand Down
2 changes: 1 addition & 1 deletion test/command/3450.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
% pandoc -fmarkdown-implicit_figures -t latex
![image](lalune.jpg){height=2em}
^D
\includegraphics[width=\linewidth,height=2em]{lalune.jpg}
\includegraphics[width=\linewidth,height=2em,keepaspectratio]{lalune.jpg}
```
2 changes: 1 addition & 1 deletion test/command/5476.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
^D
\begin{figure}
\centering
\includegraphics{test/lalune.jpg}
\pandocbounded{\includegraphics[keepaspectratio]{test/lalune.jpg}}
\caption[moon]{moon\footnotemark{}}
\end{figure}
\footnotetext{the moon}
Expand Down
2 changes: 1 addition & 1 deletion test/command/7181.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
^D
\begin{figure}
\centering
\includegraphics[page=13,trim=1cm,clip,width=4cm]{slides.pdf}
\pandocbounded{\includegraphics[keepaspectratio,page=13,trim=1cm,clip,width=4cm]{slides.pdf}}
\caption{Global frog population.}
\end{figure}
Expand Down
2 changes: 1 addition & 1 deletion test/command/9045.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
^D
\begin{figure}
\centering
\includegraphics{there.jpg}
\pandocbounded{\includegraphics[keepaspectratio]{there.jpg}}
\caption{hi}\label{foo}
\end{figure}
```
23 changes: 13 additions & 10 deletions test/writer.latex
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,17 @@
\usepackage{xcolor}
\usepackage{graphicx}
\makeatletter
\def\maxwidth{\ifdim\Gin@nat@width>\linewidth\linewidth\else\Gin@nat@width\fi}
\def\maxheight{\ifdim\Gin@nat@height>\textheight\textheight\else\Gin@nat@height\fi}
\makeatother
% Scale images if necessary, so that they will not overflow the page
% margins by default, and it is still possible to overwrite the defaults
% using explicit options in \includegraphics[width, height, ...]{}
\setkeys{Gin}{width=\maxwidth,height=\maxheight,keepaspectratio}
\newsavebox\pandoc@box
\newcommand*\pandocbounded[1]{% scales image to fit in text height/width
\sbox\pandoc@box{#1}%
\Gscale@div\@tempa{\textheight}{\dimexpr\ht\pandoc@box+\dp\pandoc@box\relax}%
\Gscale@div\@tempb{\linewidth}{\wd\pandoc@box}%
\ifdim\@tempb\p@<\@tempa\p@\let\@tempa\@tempb\fi% select the smaller of both
\ifdim\@tempa\p@<\p@\scalebox{\@tempa}{\usebox\pandoc@box}%
\else\usebox{\pandoc@box}%
\fi%
}
% Set default figure placement to htbp
\makeatletter
\def\fps@figure{htbp}
\makeatother
\ifLuaTeX
Expand Down Expand Up @@ -922,11 +924,12 @@ From ``Voyage dans la Lune'' by Georges Melies (1902):

\begin{figure}
\centering
\includegraphics{lalune.jpg}
\pandocbounded{\includegraphics[keepaspectratio]{lalune.jpg}}
\caption{lalune}
\end{figure}

Here is a movie \includegraphics{movie.jpg} icon.
Here is a movie \pandocbounded{\includegraphics[keepaspectratio]{movie.jpg}}
icon.

\begin{center}\rule{0.5\linewidth}{0.5pt}\end{center}

Expand Down

0 comments on commit 26b25a4

Please sign in to comment.