4

When using the spacing environment from the setspace package, it appears that rubber lengths in \abovedisplayskip and \belowdisplayskip are being ignored.

\documentclass{article}
\usepackage[nopar]{lipsum}
\usepackage{setspace}

\flushbottom
\begin{document}
%\begin{spacing}{1.0}
\setlength{\abovedisplayskip}{12pt plus 1000pt}%
\setlength{\belowdisplayskip}{12pt plus 1000pt}%
\lipsum[1]
\par
\lipsum[2]
%
\[a^2+b^2=c^2\]
%
\lipsum[3]
\par
\lipsum[4]
%
\[
\begin{array}{c}a\\b\\c\\d\\e\\f\\g\\h\\i\end{array}
\]
%\end{spacing}
\end{document}

My MWE is designed such that the second fomula with the very tall array forces an unpleasant page break. Due to the big rubber lengths in \abovedisplayskip and \belowdisplayskip, lots of space is introduced around the first formula instead of spreading the paragraphs. This behavior is as expected. (Side question: Why does it not work, when I set the lengths before \begin{document}?)

enter image description here

However, when I add the two commented out lines that begin and end the spacing environment, then for some reason the rubber lenghts are ignored. When I output the value of the length, the rubber is there, but the space just doesnt't want to stretch.

enter image description here

This happens irrespective of the stretch value passed to the spacing environment. (A spread of 1.0 is obviously nonsensical and just for illustration). What can I do to correct this behavior?

3
  • While looking for the source of the setspace package, I stubled over this issue that seems related to my problem. Adding \setdisplayskipstretch{} as suggested there, indeed restores the stretching behavior before and after display math. However, this also disables the automatic stretching of space around equations together with the line spreading, which then has to be done manually. Hence, this is only a partial solution.
    – ranguwud
    Commented Jan 8, 2020 at 19:34
  • If I remember correctly, each lipsum paragraph ends with \par, and a paragraph break before a display environment wreaks havoc with the vertical spacing. That may not be the problem with your actual project, but it would cause the results of a test to be unreliable. Commented Jan 9, 2020 at 1:30
  • Interesting, I didn't know that. The MWE is now updated to use the nopar option of the lipsum package to get rid of the \par. The problem persists without change, however.
    – ranguwud
    Commented Jan 9, 2020 at 8:02

1 Answer 1

5

As to why, the answer is easy: the setspace package does

\everydisplay\expandafter{%
  \the\everydisplay
  \abovedisplayskip \displayskipstretch\abovedisplayskip
  \belowdisplayskip \displayskipstretch\belowdisplayskip
  \abovedisplayshortskip \displayskipstretch\abovedisplayshortskip
  \belowdisplayshortskip \displayskipstretch\belowdisplayshortskip
}

which means that stretch and shrink components are killed, if \displayskipstretch has a numeric value. Without \begin{spacing}{1.0}, the eventual expansion of \displayskipstretch is empty, so the killing doesn't happen.

We need to remove the faulty bits and reconstruct \everydisplay. The following assumes that stretch and shrink components are finite.

\documentclass{article}
\usepackage[nopar]{lipsum}
\usepackage{setspace}

\newcommand{\addstretchshrink}[1]{%
  \if\relax\displayskipstretch\relax
    % there is no factor, don't add plus and minus
  \else
    plus \displayskipstretch\gluestretch#1
    minus \displayskipstretch\glueshrink#1
  \fi
}
\def\fix#1\abovedisplayskip#2\displayskipstretch\belowdisplayshortskip#3\fix{%
  \everydisplay{#1#3
    \abovedisplayskip = \displayskipstretch\abovedisplayskip \addstretchshrink\abovedisplayskip
    \belowdisplayskip = \displayskipstretch\belowdisplayskip \addstretchshrink\belowdisplayskip
    \abovedisplayshortskip = \displayskipstretch\abovedisplayshortskip \addstretchshrink\abovedisplayshortskip
    \belowdisplayshortskip = \displayskipstretch\belowdisplayshortskip \addstretchshrink\belowdisplayshortskip
  }%
}
\expandafter\fix\the\everydisplay\fix

\flushbottom

\begin{document}
\begin{spacing}{1.0}
\setlength{\abovedisplayskip}{12pt plus 1000pt}%
\setlength{\belowdisplayskip}{12pt plus 1000pt}%
\lipsum[1]
\par
\lipsum[2]
%
\[a^2+b^2=c^2\]
%
\lipsum[3]
\par
\lipsum[4]
%
\[
\begin{array}{c}a\\b\\c\\d\\e\\f\\g\\h\\i\end{array}
\]
\end{spacing}
\end{document}
2
  • Yes, this totally makes sense. I didn't know about \gluestretch and \glueshrink before, that was the missing part for me. Do I get it right, that your \fix basically cuts out the relevant part of \everydisplay between #1 and #3, then re-inserts #1 and #3 but discards everything in between?
    – ranguwud
    Commented Jan 9, 2020 at 12:31
  • @ranguwud Yes, that's necessary otherwise those settings would cancel stretch and shrink. There's room for improvement, though.
    – egreg
    Commented Jan 9, 2020 at 12:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .