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.

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.

Closes #9660.
  • Loading branch information
jgm committed Apr 18, 2024
1 parent 3d90234 commit 72ce03d
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 24 deletions.
18 changes: 10 additions & 8 deletions data/templates/default.latex
Original file line number Diff line number Diff line change
Expand Up @@ -299,15 +299,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
7 changes: 5 additions & 2 deletions src/Text/Pandoc/Writers/LaTeX.hs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,8 +1094,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{imgs/foo.jpg}}}{Alt text}}"
]
, testGroup "inline code"
[ "struck out and highlighted" =:
Expand Down
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{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[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{there.jpg}}
\caption{hi}\label{foo}
\end{figure}
```
22 changes: 12 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 @@ -925,11 +927,11 @@ From ``Voyage dans la Lune'' by Georges Melies (1902):

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

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

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

Expand Down

6 comments on commit 72ce03d

@estedeahora
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a question about this change. Wouldn't this create an issue with figures in two-column texts? I think this could eliminate the possibility of switching between page-width and text-width figures. I'm thinking about the discussion on this in #9268. Personally, losing the possibility of page-wide figures (in two-column texts) seems to me to be a problem.

@jgm
Copy link
Owner Author

@jgm jgm commented on 72ce03d May 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't thought about this. Can you try it? (If you don't want to build from source, there are binary nightlies you can download from the Actions tab.) Perhaps there's a workaround?
Perhaps @mrpiggi who suggested this approach could comment.

@jgm
Copy link
Owner Author

@jgm jgm commented on 72ce03d May 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that using \textwidth instead of \linewidth would preserve the ability to have full-width figures.

@jgm
Copy link
Owner Author

@jgm jgm commented on 72ce03d May 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note also that when an explicit image size is specified, \pandocbounded is not used. So you could always just specify an explicit size for full-width images.

@estedeahora
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't thought about this. Can you try it? (If you don't want to build from source, there are binary nightlies you can download from the Actions tab.) Perhaps there's a workaround? Perhaps @mrpiggi who suggested this approach could comment.

I will try to test it. I'm not very good at latex, but I think I can experiment with the codes I used before and see what the result is. I don't think I'll be able to do it for a few days, if that's ok (I see this commit is going fast).

@mrpiggi
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The usage of \linewidth comes right from the code-snippet posted at mrpiggi/svg#60 (comment) which was the base for \pandocbounded. It could be changed to \textwidth but this will give probably unintended result when used in a indented environment like quote or similar. IMHO it would be better to stick to \linewdith especially for two-column layout as this is often tedious and typesetting images over multiple columns needs manual intervention almost always with LaTeX.

Please sign in to comment.