
Я хотел бы объединить две мини-страницы в текст, сохранив межстрочный интервал. При использовании этой \begin{minipage}[t]
опции пространство над мини-страницами правильное (зеленый круг). Но, к сожалению, пространство под ними слишком короткое (красный круг). Как мне настроить его на "нормальный пропуск базовой линии"?
МВЭ:
\documentclass[a4paper,DIV=15,oneside,12pt]{scrartcl}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{blindtext}
\usepackage{setspace}
\usepackage{enumitem}
\parskip 0pt
\parindent 0pt
\begin{document}
\pagestyle{empty}
\onehalfspacing
\blindtext\par
\begin{minipage}[t]{0.6\textwidth}
\blindtext
\end{minipage}\hfill
%Minipage 2
\begin{minipage}[t]{0.37\textwidth}
%\centering\rule{3cm}{2cm}
\begin{enumerate}[leftmargin=*,label=\alph{*}),itemsep=0pt,partopsep=0pt,topsep=0pt, parsep=0pt]
\item Test 1
\item Test 2
\end{enumerate}
\end{minipage}\par
\blindtext
\end{document}
решение1
Объяснение вашей проблемы довольно сложное. Если хотите, можете просто перейти к решению ниже.
Объяснение
Когда TeX набирает абзацы, он ведет себя примерно следующим образом: сначала он разбивает абзац на строки (используя сложный алгоритм с рядом параметров). Эти строки помещаются в горизонтальный блок (или \hbox
), а блоки размещаются в главном вертикальном списке. Главный вертикальный список содержит весь материал, из которого создаются страницы.
TeX пытается убедиться, что последовательные горизонтальные блоки в вертикальном списке расположены так, что базовые линии каждого блока находятся на \baselineskip
расстоянии друг от друга. Мы можем использовать TeX, чтобы увидеть это в действии.
Вот простой TeX (компилируйте с помощью tex
или pdftex
)
\showboxdepth=1
\showboxbreadth=10000
\tracingonline=1
\setbox0=\vbox{
First line\hfil\break
Second line
}
\showbox0
\end
При компиляции он выводит содержимое внутреннего \vbox
абзаца, разбитого на две строки. Параметры \boxshow...
управляют тем, как TeX выводит содержимое блока. Вот вывод.
> \box0=
\vbox(18.94444+0.0)x469.75499
.\hbox(6.94444+0.0)x469.75499, glue set 409.81047fil []
.\penalty 300
.\glue(\baselineskip) 5.05556
.\hbox(6.94444+0.0)x469.75499, glue set 420.31046fil []
Сначала это может быть немного сложно читать, но это говорит нам, что это , \box0
который \vbox
имеет высоту 18.94444pt, глубину 0pt и ширину 469.75499pt. То есть, (height+depth)xwidth
. Внутри этого мы можем видеть две \hbox
es, соответствующие двум строкам абзаца. Между ними находится , \glue
который соответствует \baselineskip
. Обратите внимание, что глубина верхнего блока плюс клей плюс высота нижнего блока составляет 12pt, что составляет \baselineskip
.
Теперь TeX также не хочет, чтобы последовательные блоки располагались слишком близко друг к другу, чтобы предотвратить их перекрытие. Чтобы предотвратить это, TeX вставит некоторое пространство между блоками, когда они расположены слишком близко друг к другу. Точный алгоритм здесь не важен, но ключ в том, что мы можем отключить это поведение с помощью \nointerlineskip
.
Теперь вы можете задаться вопросом, как два текстовых блока могут быть слишком близко друг к другу. Это может произойти, если у вас есть блок с глубиноймнаверху коробки высотойнтакой чтом+н> \baselineskip
.
Так какое отношение все это имеет к твоему вопросу? Ну, в TeX есть три типа вертикальных блоков, \vbox
, \vtop
, и \vcenter
. Давайте проигнорируем, \vcenter
так как это немного странно. \vbox
и\vtop
отличаются тем, где они размещают своиориентир— это точка, которая соответствует их базовой линии. A \vbox
устанавливает свою точку отсчета как точку отсчета последнего блока в списке (т. е. обычно базовую линию последней строки абзаца в блоке). Напротив, a устанавливает \vtop
свою точку отсчета как точку отсчета первого блока в списке (т. е. базовую линию верхней строки абзаца).
Мы можем видеть это в действии.
\noindent
\vbox{
\hsize=1in
Top line\hfill\break
Bottom line
}
\vtop{
\hsize=1in
Top line\hfill\break
Bottom line
}
\end
Вы можете видеть, как нижняя линия левого поля совпадает с верхней линией правого поля.
Мы можем распечатать то, как выглядят эти две коробки, как мы делали раньше.
Левое поле:
\vbox(18.94444+0.0)x72.26999
.\hbox(6.94444+1.94444)x72.26999, glue set 16.4366fill []
.\penalty 300
.\glue(\baselineskip) 3.11111
.\hbox(6.94444+0.0)x72.26999, glue set 20.18652fil []
Правое поле:
\vbox(6.94444+12.0)x72.26999
.\hbox(6.94444+1.94444)x72.26999, glue set 16.4366fill []
.\penalty 300
.\glue(\baselineskip) 3.11111
.\hbox(6.94444+0.0)x72.26999, glue set 20.18652fil []
Основное различие заключается в высоте и глубине этих двух полей (верхняя строка каждого списка).
Это приводит к сложной проблеме. Что произойдет, если мы используем a, \vtop
а следующая строка на странице — это просто обычная строка из абзаца? Давайте посмотрим.
\parindent=0pt
\leavevmode
\vtop{
\hsize=1in
Top line\hfill\break
g Bottom line
}
Next line
\end
Я подавил отступы и начал вторую строку с a, g
потому что он опускается ниже базовой линии. Давайте посмотрим на созданные блоки. (Я обернул все в a \vbox
и использовал \showbox
для просмотра вывода. Таким образом, ниже есть дополнительный внешний vbox. Я увеличил \showboxdepth
на 1, чтобы увидеть следующий внутренний блок.)
\vbox(28.83333+0.0)x469.75499
.\vbox(6.94444+13.94444)x72.26999
..\hbox(6.94444+1.94444)x72.26999, glue set 36.4366fill []
..\penalty 300
..\glue(\baselineskip) 3.11111
..\hbox(6.94444+1.94444)x72.26999, glue set 11.85318fil []
.\glue(\parskip) 0.0 plus 1.0
.\glue(\lineskip) 1.0
.\hbox(6.94444+0.0)x469.75499, glue set 429.75491fil
..\hbox(0.0+0.0)x0.0
..\tenrm N
..\tenrm e
..\tenrm x
..\tenrm t
..\glue 3.33333 plus 1.66666 minus 1.11111
..\tenrm l
..\tenrm i
..\tenrm n
..\tenrm e
..\penalty 10000
..\glue(\parfillskip) 0.0 plus 1.0fil
..\glue(\rightskip) 0.0
Здесь есть несколько интересных моментов:
- Второе
\vbox
соответствует нашему\vtop
; - A
\parskip
был вставлен между абзацами; и \baselineskip
Между\vtop
и следующим\hbox
, содержащим , было вставлено No.Next line
Вместо этого стоит\lineskip
. Это\lineskip
происходит из-за того, что глубина\vtop
и высота следующего\hbox
больше, чем\baselineskip
. Если бы TeX попытался\baselineskip
разделить их базовые линии, они бы перекрывались.
Может быть, теперь вы видите проблему с вашим собственным кодом. minipage
С [t]
опцией создается \vtop
. Таким образом, TeX не обеспечивает, чтобы базовая линия нижней строки в minipage
была \baselineskip
вдали от базовой линии следующей строки. Вместо этого он вставляет, \lineskip
что почти не дает достаточно места.
Вы можете подумать, что решение — переключить на minipage
, [b]
но тогда у вас будет аналогичная ситуация со строкой выше.
Решение
Обычный метод решения этой проблемы — поместить a \strut
в последнюю строку в \vtop
, отключить межстрочный пропуск (т. е. запретить \lineskip
склеивание) и поместить a \strut
в первую строку следующего абзаца.
A \strut
вставляет поле (а именно \box\strutbox
), имеющее высоту + глубину, которая обычно равна \baselineskip
. Однако в вашем случае это не сработает. Причина в том, \onehalfspacing
что изменяет , \baselineskip
но не затрагивает \box\strutbox
.
Итак, нам нужно закончить более длинный блок соответствующей \vskip
длиной, отключить пропуск между строками и использовать \strut
. Так какова же соответствующая длина? Ну, мы хотим \baselineskip
= (высота \box\strutbox
) + (глубина последнего блока в \vbox
) + (наш явный \vskip
).
Мы можем вычислить это, установив временный \skip
регистр (я выбрал 0
) равным \baselineskip
- \ht\strutbox
- \prevdepth
где \prevdepth
- глубина последнего поля в вертикальном списке (то есть последняя строка текста).
Два последних предостережения.
- Это не работает с
minipage
, я не исследовал почему. enumerate
добавит пробел над ним обычно. Это подавляетсяminipage
which executes\@setminipage
. Я понимаю, как это\@setminipage
работает, но я не понимаю, как предотвратить это поведение, просто используяenumitem
параметры . Поэтому вместо этого этот код выполняет\@setminipage
.
Вот полный код.
\documentclass[a4paper,DIV=15,oneside,12pt]{scrartcl}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{blindtext}
\usepackage{setspace}
\usepackage{enumitem}
\parskip 0pt
\parindent 0pt
\begin{document}
\pagestyle{empty}
\onehalfspacing
\blindtext\par
\noindent
\parbox[t]{0.6\textwidth}{
\blindtext
\skip0=\baselineskip
\advance\skip0 by-\prevdepth
\advance\skip0 by-\ht\strutbox\relax
\vskip\skip0
}\hfill
\parbox[t]{0.37\textwidth}{
\csname @setminipage\endcsname
\begin{enumerate}[leftmargin=*,label=\alph{*}),itemsep=0pt,partopsep=0pt,topsep=0pt, parsep=0pt]
\item Test 1
\item Test 2
\end{enumerate}
}
\par
\nointerlineskip
\strut\blindtext
\end{document}