Алгоритм TeX для переноса строк: как оценивать набор абзаца

Алгоритм TeX для переноса строк оценивает абзац целиком: он сравнивает возможные границы строк и выбирает последовательность, которая даёт наиболее ровный набор с учётом переносов и растяжения пробелов. Поэтому последняя строка может влиять на решение о предыдущих. Этот принцип полезен и без TeX: он помогает найти причину рыхлой строки и исправить исходные условия, а не маскировать дефект ручными пробелами.
Откуда появился подход TeX
В конце 1970-х математик и программист Дональд Кнут занялся TeX после того, как увидел неудовлетворительное качество набора корректур нового издания своей книги. Задача была шире, чем аккуратно напечатать формулы: авторский текст должен был одинаково собираться на разных системах, а решения по строкам не должны зависеть от случайностей построчного набора. История TeX описана в материалах TeX Users Group; важен сам поворот к алгоритму, который принимает решение на уровне абзаца, а не только ближайшего слова.
В 1981 году Кнут и Майкл Пласс подробно представили алгоритм разбиения абзацев на строки. В статье Breaking Paragraphs into Lines (DOI: DOI 10.1002/spe.4380111102) авторы описали модель из трёх элементов — коробок, клея и штрафов — и динамический поиск последовательности границ. Это не обещание идеального абзаца при любом тексте: система выбирает лучшее решение среди разрешённых правил и доступных вариантов переноса.
Что означают коробки, клей и штрафы
Коробка (box) — неделимый фрагмент с известной шириной: обычно слово, знак или формула. Клей (glue) — пробел, который в наборе может растягиваться или сжиматься в заданных пределах. Штраф (penalty) задаёт цену или запрет на разрыв в определённом месте. В совокупности модель описывает не только то, где физически заканчивается строка, но и сколько типографической «цены» стоит каждый вариант.
Например, в фразе «макет для музейной этикетки» программа может поставить границу после нескольких разных слов. В одном варианте появится почти пустая последняя строка, в другом — между словами первой строки придётся сильно растянуть пробелы, а третий использует допустимый перенос слова. Алгоритм сравнит суммарную стоимость таких решений с учётом следующих строк и выберет вариант с меньшим штрафом. Числа здесь не нужно угадывать дизайнеру: важнее понять, какие ограничения заложены в документе и шрифте.
«Клей» не означает, что все пробелы автоматически станут одинаковыми. У пробела есть естественная ширина и допустимое изменение; если строку невозможно заполнить аккуратно, чрезмерное растяжение становится видимым дефектом. Для выравнивания по левому краю задача иная: край справа остаётся неровным намеренно, поэтому нельзя диагностировать его по критерию полного заполнения строки.
Почему TeX смотрит на весь абзац
Построчный, или жадный, способ кладёт в текущую строку максимум слов, которые помещаются, и сразу фиксирует разрыв. Он может не заметить, что решение создаёт неудачную следующую строку. Подход TeX рассматривает допустимые разрывы в абзаце и накапливает стоимость пути от начала до конца. Если чуть более свободная первая строка заметно улучшает несколько последующих, общий вариант может оказаться предпочтительнее.
У метода есть практичная граница: «лучший» здесь означает лучший по формализованной функции качества, а не по любому культурному или смысловому критерию. Алгоритм сам по себе не знает, что имя и фамилию желательно оставить вместе, что перенос внутри названия бренда нежелателен или что в конкретной колонке дизайнер хочет особый ритм. Такие ограничения добавляют правилами, неразрывными пробелами, запретами на перенос или ручной редактурой.
Это отличает оценку абзаца от косметического выравнивания одной строки. Если слова в строке раздвинуты чрезмерно, причина часто расположена выше по цепочке: узкая колонка, длинное слово без подходящей точки переноса, неподходящая гарнитура или слишком жёсткие ограничения. Увеличение межсловного интервала в одном месте обычно переносит проблему в соседние строки.
Как применить эту логику при проверке макета
Проверку удобно вести как короткий эксперимент: менять по одному условию и сравнивать весь абзац после каждого изменения. Возьмите текст, который реально будет опубликован, а не набор случайных слов. Для книжной страницы подойдёт абзац с короткими служебными словами и длинными терминами; для этикетки — название, сорт, состав и одна фраза пояснения. Подставьте шрифт, ширину колонки и кегль из финального макета.
Шаг 1. Отметьте видимые симптомы
Как проверить узкую подпись на практике
Представьте карточку товара с узкой колонкой характеристик. В одном варианте строка распадается на три коротких фрагмента, в другом длинное название переносится с дефисом, а в третьем подпись становится на одну строку выше после небольшого увеличения блока. Сначала спросите, какая версия читается быстрее и сохраняет связь между названием и значением. Затем сравните цену каждого решения: дополнительная высота, заметный дефис или большие промежутки между словами. Такой протокол переводит разговор о «красивом наборе» в проверяемый выбор.
Проверяйте также реальный набор символов, а не только латинский Lorem ipsum. В русской подписи могут быть длинные слова, тире, единицы измерения и фамилии; в пользовательской гарнитуре различаются ширины букв и пары. Если строка стала неровной только после подстановки авторского шрифта, откройте отдельный образец с теми же словами и сравните силуэт строки. Проблема может быть в ограниченном составе символов или контуре конкретной буквы, а не в алгоритме переносов.
Обведите строки с необычно широкими пробелами, одинокими короткими словами, переносами рядом друг с другом и неудачным последним рядом. Не записывайте сразу «плохой шрифт»: один и тот же шрифт может выглядеть хорошо в широкой колонке и плохо в узкой. Зафиксируйте кегль, ширину блока, выравнивание, межстрочный интервал и включён ли автоматический перенос.
Шаг 2. Проверьте разрешённые места разрыва
Посмотрите, где программа вообще имеет право завершить строку. Если переносы отключены, длинные русские слова и составные термины оставляют мало допустимых вариантов. Если текст импортирован из PDF или веб-страницы, в нём могли остаться жёсткие переводы строки, неразрывные пробелы или дефисы из старой версии. Сначала удалите случайную разметку и настройте словарь переноса, затем оценивайте распределение пробелов.
Шаг 3. Сравните целый абзац
Сделайте три копии блока: исходный шрифт, соседняя по характеру гарнитура и тот же шрифт при немного изменённой ширине. Сравнивайте не отдельную строку, а все строки и финальную строку вместе. Если дефект исчезает после небольшого расширения блока, узкое ограничение, вероятно, важнее метрик шрифта. Если проблема остаётся только у одного начертания, проверьте ширину конкретных букв и межбуквенные пары.
Шаг 4. Внесите самое дешёвое исправление
Сначала исправляйте исходный текст и структуру: уберите лишний ручной перенос, разрешите допустимые переносы, переформулируйте слишком длинную подпись или увеличьте полезную ширину. Затем проверяйте кегль, гарнитуру, трекинг и настройки выравнивания. Ручной разрыв оставляйте для редакционно обоснованного решения, которое проверено при изменении текста и размера блока.
Если вы работаете в TeX
В документах на TeX или LaTeX результат зависит от языка, загруженных правил переноса, ширины абзаца, доступной гибкости пробелов и настроек штрафов. Параметр \tracingparagraphs=1 записывает в журнал сведения о рассмотрении абзаца и помогает понять, какие разрывы участвовали в выборе. Это диагностический след, а не визуальная оценка: откройте также PDF и проверьте строки глазами.
Для поиска проблемы попробуйте воспроизводимый фрагмент: один абзац, тот же шрифт, размеры и языковые настройки. Удалите из теста плавающие изображения и сложные макросы, если они не связаны с дефектом. Меняйте по одной переменной. При необходимости можно сравнить исходный результат с меньшей шириной колонки или другими разрешёнными переносами, но не делайте глобальное ослабление требований к пробелам ради одной строки.
Чек-лист перед сдачей абзаца
- Проверить весь абзац при финальной ширине и кегле, а не отдельную проблемную строку.
- Убедиться, что язык и словарь переноса соответствуют тексту.
- Найти случайные ручные разрывы, дефисы и неразрывные пробелы после импорта.
- Сравнить пробелы, переносы и последнюю строку вместе.
- Менять по одному параметру и сохранять исходный вариант для сравнения.
- Повторно проверить абзац после любой правки текста или ширины блока.
Частые ошибки
Первая ошибка — пытаться лечить рыхлую строку уменьшением пробелов вручную. Это может дать слипшийся набор и нарушить другие строки. Вторая — оценивать только заполненность правого края, не учитывая читаемость переносов и смысловые группы. Третья — считать, что TeX всегда принимает решение, которое лучше видит человек: алгоритм умеет сравнивать заданные критерии, но не заменяет редактора.
Ещё одна ошибка — переносить настройки одного движка в другой как универсальный рецепт. Вёрсточные программы и браузеры могут использовать разные алгоритмы и правила языка, а одинаковое значение ширины не гарантирует одинакового результата. Наконец, не стоит делать вывод о качестве шрифта по одному узкому блоку: проверьте несколько реальных текстов и размеров, иначе случайная длина слов станет мнимой проблемой гарнитуры.
Часто задаваемые вопросы
Алгоритм TeX переносит текст по одному слову?
Нет. Он рассматривает допустимые границы строк в контексте всего абзаца и сопоставляет стоимость вариантов. Поэтому выбор одной границы может зависеть от того, как распределятся слова в последующих строках.
Почему после включения переносов пробелы стали ровнее?
Переносы добавляют допустимые места для окончания строки. У алгоритма появляется больше способов заполнить строку без чрезмерного растяжения пробелов. Результат зависит от корректного языка и набора правил переноса.
Можно ли применить алгоритм TeX в обычном графическом редакторе?
Не обязательно сам алгоритм. Практический переносимый навык — оценивать весь абзац и проверять ограничения, влияющие на него: ширину, шрифт, переносы и запреты. Конкретный редактор может использовать собственные правила композиции строк.
Что делать, если строка всё равно выглядит плохо?
Сначала проверьте ширину блока, доступные переносы и наличие жёстких разрывов. Затем сравните соседнюю гарнитуру или кегль и перечитайте весь абзац. Если нужно изменить формулировку или вручную переставить разрыв, проверьте, не станет ли проблема заметна после редакторской правки.
Для чего нужен параметр \tracingparagraphs?
В TeX он включает запись диагностических сведений о ходе разбора абзацев в журнал компиляции. По нему можно изучить варианты разрывов и их оценки, но сам журнал не показывает, насколько удачно выглядит готовая полоса: PDF всё равно нужно проверить визуально.
Подходит ли подход TeX для короткой подписи?
Да, но короткая подпись часто даёт меньше допустимых мест разрыва, поэтому у алгоритма меньше выбора. Для узкого блока особенно полезно заранее подобрать короткую формулировку, увеличить ширину или выбрать более компактное начертание.
Итог
Алгоритм TeX важен не как универсальная команда «сделать красиво», а как способ мыслить абзацем целиком: перечислить возможные разрывы, учесть гибкость пробелов и сравнить последствия. При проверке собственного макета эта логика помогает найти первопричину неровного набора. Если вы создаёте рукописную гарнитуру, соберите её в Fontgenerator и испытайте на коротких и длинных реальных фразах — переносы покажут не только свойства программы, но и то, как ширины букв работают в строке.
Источники
Дональд Кнут и Майкл Пласс, “Breaking Paragraphs into Lines”, Software: Practice and Experience, 1981: DOI 10.1002/spe.4380111102. История TeX, TeX Users Group: история TeX в TeX Users Group. Техническая документация по TeX доступна через архив CTAN: архив CTAN.