Объяснение

Объяснение

Я хотел бы объединить две мини-страницы в текст, сохранив межстрочный интервал. При использовании этой \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. Внутри этого мы можем видеть две \hboxes, соответствующие двум строкам абзаца. Между ними находится , \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

Здесь есть несколько интересных моментов:

  1. Второе \vboxсоответствует нашему \vtop;
  2. A \parskipбыл вставлен между абзацами; и
  3. \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- глубина последнего поля в вертикальном списке (то есть последняя строка текста).

Два последних предостережения.

  1. Это не работает с minipage, я не исследовал почему.
  2. enumerateдобавит пробел над ним обычно. Это подавляется minipagewhich 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}

введите описание изображения здесь

Связанный контент