%2C%20%D1%81%D0%BE%D0%B4%D0%B5%D1%80%D0%B6%D0%B0%D1%89%D0%B8%D0%B9%D1%81%D1%8F%20%D0%B2%20%D0%BC%D0%B0%D0%BA%D1%80%D0%BE%D1%81%D0%B5.png)
Допустим, у нас есть большой объем текста, который нужно набрать, содержащийся в одном макросе, назовем его\myverylongtext
\newcommand{\myverylongtext}{
This is some really long text: \blindtext[4].
And it continues even more: \blindtext[1].
}
Для простоты предположим, что в нет команды sectioning/newpage \myverylongtext
, но в нем могут быть команды переноса строк и несколько абзацев (команды переноса абзацев?). Также предположим, что размер шрифта и интерлиньяж остаются неизменными, хотя все остальные команды набора LaTeX (\textbf и т. д.) разрешены в тексте и должны вступить в силу.
Можно ли определить эффективный* макрос, который (при обнаружении) получает следующий фрагмент текста указанного размера? Например:
\newcommand{\getnextchunk}[4]{
% #1 is name of macro (in our case \myverylongtext)
% #2 width of text box
% #3 height of text box in lines
% #4 draftmode: optional boolean argument that, when set, instead of typesetting contents returns the actual height (in lines), and width (in length units) of the chunk. (useful in making dynamic layout decisions)
% returns/typesets a box of shape width * height
}
Новые вызовы этого макроса \getnextchunk
должны получать следующий фрагмент текста, как если бы текст, содержащийся в нем, \myverylongtext
был перенесен из предыдущего фрагмента в этот фрагмент.
* Это \myverylongtext
может быть очень длинным, и таких фрагментов может быть много, поэтому нужна эффективность. Вы не можете набирать оставшуюся часть \myverylongtext
несколько раз. Одно из моих видений решения такой проблемы заключается в том, что блок размером 0 заполняется итеративно, пока не вырастет до указанной метрики: ширина (в измерении длины), высота (в строках) и требуемое выравнивание; хотя мне не хватает понимания низкоуровневого tex/luatex/expl3, чтобы написать его самому.
Кроме того, либо команды выравнивания, такие как raggedright/raggedleft/full-justified, указанные в , \myverylongtext
должны волшебным образом вступить в силу, либо мы можем установить ограничение, что у нас не будет таких команд в \myverylongtext
&, вместо этого передав их в качестве четвертого аргумента \getnextchunk
(я думаю, последний вариант предпочтительнее и сделает код/использование проще и/или чище).
Другой способ визуализировать проблему — представить, что у нас есть несколько прямоугольных текстовых полей (разной ширины и высоты), которые последовательно перетекают друг в друга по мере того, как мы сталкиваемся с ними в нашем документе (не беспокойтесь о размещении этих текстовых полей, *tex уже имеет несколько элегантных решений для этого). Кроме того, мы не знаем, когда и сколько таких текстовых полей будет встречаться в документе заранее. По моему мнению, за годы использования *tex решение только этой одной проблемы откроет массу возможностей и сделает tex непобедимым (по сравнению с InDesign и т. д.) по ценности как типографский инструмент для макетов, ориентированных на дизайн. Такие инструменты, как InDesign и Affinity Publisher, позволяют связывать текстовые поля, которые в конечном итоге перетекают друг в друга как поток, и являются чем-то незаменимым для типографской системы, которая предполагает обслуживать современную выразительную типографику и множество дизайнов. Это может открыть *tex как наборщика для гораздо более широкого сообщества наборщиков/дизайнеров.
решение1
Мое решение не совсем то, что вам нужно, но вся информация управляется в одном месте. Надеюсь, что не составит проблемы принять три прохода по параметрам.
Данные должны выглядеть так:
% lines width
\declchunk 5 10cm ;
\declchunk 6 12cm ;
\declchunk 12 13cm ;
\declchunk 9 10cm ;
\declchunk 9 10cm ;
\declchunk 9 10cm ;
\declchunk 7 8cm ;
\declchunk 5 10cm ;
\formatchunks \myverylongtext
\setbox101 = \getnextchunk
\setbox102 = \getnextchunk \rebox 102:{\raggedright}
\setbox103 = \getnextchunk
\setbox104 = \getnextchunk \rebox 104:{\raggedleft}
\setbox105 = \getnextchunk
% you can place these boxes everywhere. the following code is only for testing:
box 101: \par \box101 \bigskip
box 102: \par \box102 \bigskip
box 103: \par \box103 \bigskip
box 104: \par \box104 \bigskip
box 105: \par \box105 \bigskip
\bye
Во-первых, мы dcelare размеры всех блоков (по количеству строк для высоты и по размерам для ширины). Во-вторых, мы форматируем заданный текст. Наконец, мы можем получить фрагменты данных и сохранить их, например, в блоках. Они выравниваются по блокам по умолчанию. Если нам нужно сделать другую настройку, то мы можем повторно скомпоновать эти блоки. Наш пример показывает, что второй блок имеет рваные края справа, а четвертый блок имеет рваные края слева. Более того, вы можете сделать
\vbox to<dimension>{\unvbox103} \vtop to12mm{\unvbox105} etc.
например, потому что между линиями существует растяжимость и сжимаемость.
Реализация: мы получаем все \parshape
параметры по списку \declchunk
s, затем форматируем текст, используя эти параметры (только один раз) в \vbox\allchunks
и затем делаем \vsplit
когда \getnextcunk
вызывается. Наконец, мы можем сделать небольшую переупаковку, если пользователю нужно несколько иное выравнивание блока формы.
Моя реализация работает только с простым TeX и классическим TeX. Нам не нужно никаких расширений TeX и (конечно) нам не нужен LaTeX:).
\newcount\tmpnum
\newcount\shapenum
\newcount\globpar
\newbox\allchunks
\newif\ifrepeat
\splittopskip=\baselineskip
\def\formatchunks#1{\setbox\allchunks=\vbox{%
\def\par{\ifhmode\shapepar\fi}
\def\shapepar{\prevgraf=\globpar
\parshape\shapenum\shapelist \endgraf
\globpar=\prevgraf
\ifnum\prevgraf>\shapenum \let\par=\endgraf \fi}
\dimen0=\baselineskip \baselineskip=\dimen0 plus2pt minus2pt
\widowpenalty=0 \clubpenalty=0 \brokenpenalty=0
\penalty0 #1\vfil}
\setbox0=\vsplit\allchunks to0pt % \splittopskip added
\expandafter \renewsize \sizelist \relax
}
\def\shapelist{} \def\sizelist{}
\splittopskip=\baselineskip
\def\shapelist{} \def\sizelist{}
\def\declchunk #1 #2;{\edef\sizelist{\sizelist#1\space}
\tmpnum=0
\loop \advance\tmpnum by1 \advance\shapenum by1
\edef\shapelist{\shapelist 0pt#2}%
\ifnum\tmpnum<#1 \repeat
}
\def\getnextchunk{\vsplit\allchunks to\size
\ifx\sizelist\empty \def\size{\baselineskip}%
\else \expandafter \renewsize \sizelist \relax \fi
}
\def\renewsize #1 #2\relax{%
\def\size{#1\baselineskip}\def\sizelist{#2}%
}
\def\rebox#1:#2{\setbox#1=\vbox{%
\setbox0=\hbox{}%
\repeattrue
\def\raggedright{\rightskip=0pt plus1fill minus1em \relax}%
\def\raggedleft{\leftskip=0pt plus1fill minus1em \relax}%
\hsize=\wd#1
\unvbox#1
\loop
\setbox2=\lastbox
\ifvoid2 \repeatfalse
\else \setbox0=\hbox{\hbox{\unhbox2}\penalty-10000 \unhbox0 }
\unskip\unskip\unpenalty
\fi
\ifrepeat \repeat
\null
#2\noindent \hfil \unhbox0 \par
}}
\def\myverylongtext{%
Lorem ipsum dolor sit amet, consectetuer
...
purus eget enim. Nunc vitae tortor. Proin tempus nibh sit amet nisl.
Vivamus quis tortor vitae risus porta vehicula.
}