пятница, 30 марта 2018 г.

GOSTdown: автоматическая вёрстка документации по ГОСТам

Введение

В данном посте описаны решения, которые легли в основу GOSTdown — набора шаблонов и скриптов для автоматической вёрстки. GOSTdown предназначен для тех, кому приходится писать и оформлять научно-технические отчёты (НТО) или программы по Единой системе программной документации (ЕСПД). Такие документы нередко имеют крупный размер, создаются долго и несколькими людьми, и перед сдачей проверяются на соответствие ГОСТам. Традиционно для создания таких документов используется Microsoft Word. Исполнители привыкли делать в Word, заказчики привыкли принимать в Word. Заказчиков мы обсуждать не будем, а поговорим об исполнителях и их проблемах.

Проблема

При создании документации нередко требуются следующие вещи:
  • Нумерация глав и разделов, генерация оглавления
  • Вставка и нумерация формул, таблиц и рисунков
  • Нумерация и форматирование многоуровневых списков
  • Ссылки на главы, разделы, формулы, таблицы и рисунки
  • Ведение перечня использованных источников, генерация списка литературы и ссылок на него в тексте
  • Автоматический подсчёт и вставка в текст количества страниц, таблиц, рисунков, приложений
  • Вставка текста из других документов и оформление его под стиль
  • Протоколирование изменений, внесённых разными людьми
  • Слияние изменений, сделанных разными людьми в своих копиях документа
Само собой, подразумевается отсутствие ручной работы. Никакой перенумерации ссылок или сравнения двух документов «на глаз». Никакого выставления отступов и промежутков индивидуально для абзаца. Рутинные задачи должен делать компьютер.

Строго говоря, Word имеет средства для всех вышеперечисленных задач. Да, для всех. С параллельным редактированием и слиянием изменений Word в одиночку не справится, но установка сервера Sharepoint решит и этот вопрос.

Допустим, существуют люди, которые используют Word и его возможности, и у них всё получается. Им будет неинтересно читать дальше. Этот пост может представлять интерес для людей, у которых:
  • Какие-то заголовки упорно не появляются в оглавлении, а другие, которые в нём не нужны — упорно появляются
  • Текст документа пестрит сообщениями [ошибка! источник ссылки не найден] или ненадёжными прямыми номерами, вставленными отчаявшимися коллегами
  • Постоянно ломается форматирование многоуровневых списков
  • Съезжает форматирование при вставке пункта списка из буфера обмена, вне зависимости от способа вставки
  • Отслеживание изменений невозможно, потому что от «Отформатировано: русский» рябит в глазах
  • Нет Sharepoint, а если он и появится, никто не научится им пользоваться
  • При сохранении doc-файла в .docx работа Word необъяснимо и фатально замедляется
  • Любая попытка привести в порядок зоопарк стилей в 100-страничном документе делает всё только хуже
  • Есть необходимость редактировать основной текст документа в iOS или Android, и при этом не портить оформление при сохранении.

Решение

Решение заключается в том, чтобы редактировать документ в формате, основанном на тексте (plain text), а для чтения, печати и сдачи осуществлять преобразование текста в docx-файл, оформленный по всем правилам.

Исходный текстовый формат позволит легко отслеживать и сливать изменения (в идеале — с применением git или иной системы контроля версий). Автоматизированная процедура преобразования в docx пронумерует всё необходимое, расставит номера ссылок и применит стили оформления.

Пример исходного текста в Markdown:

Результат в PDF, сохранённом из docx:

Полный пример документа см. в репозитории. Там же находится руководство пользователя (README.md). Примеры результатов см. в архиве артефактов репозитория.

Остальное — технические детали, в которых всё самое интересное.

Выбор исходного формата и конвертера

С конвертером всё просто: он фактически единственный и называется Pandoc. Он обладает уникальным движком преобразования латеховских формул в формулы Word 2010.

Pandoc — универсальный инструмент для преобразования более чем 20 форматов друг в друга. Но схема его работы такова, что любые преобразования идут через внутреннее промежуточное представление документа в самом Pandoc. Модель внутреннего представления не содержит всех возможностей всех исходных форматов (и наоборот, содержит возможности, которые присутствуют не во всех исходных форматах). Это фактически приводит к выбору формата для нашей задачи. Есть только один формат, на 100% соответствующий внутреннему представлению Pandoc: Markdown. Точнее, Pandoc’s Markdown (формат Markdown сам по себе существует во многих вариациях).

Формулы в Pandoc’s Markdown вводятся в формате LaTeX. Для библиографии доступны разные варианты, включая BibTeX. Это привычно многим сотрудникам научных организаций, которые занимаются написанием статей.

Иллюстрации в Markdown вставляются в виде внешних файлов в форматах PNG, JPEG и EMF (последний — для графиков и векторных рисунков).

Ссылками в Pandoc занимаются т.н. фильтры: pandoc-citeproc (для библиографических ссылок) и pandoc-crossref (для всего остального). Эти фильтры — отдельные программы, запускаемые из Pandoc и работающие с документом в его внутреннем представлении.

Библиография

Существует два ГОСТа: 7.1-2003 (Библиографическая запись. Библиографическое
описание) и 7.0.5-2008 (Библиографическая ссылка). При создании списка
литературы в программной и научно-технической документации формально требуется применять ГОСТ 7.1. Но реально его никто не применяет из-за нелепых требований:
  • вставлять пометку «[Текст]» в ссылки на любые тексты (т.е. практически во все ссылки);
  • повторять имя первого автора дважды (включая случай, если автор всего один);
  • писать полный список авторов после названия (до трёх включительно), а если их четыре и более, то упоминать только первого «и др».
ГОСТ 7.0.5 обходится без этих требований, поэтому его более охотно используют
вместо 7.1 — ту его часть, которая называется «затекстовые ссылки», про
которые, впрочем, сказано, что «Совокупность затекстовых библиографических
ссылок не является библиографическим списком».

В пакете pandoc-citeproc, используемом в Pandoc, есть стилевой файл в формате CSL 1.0.1, основанный на ГОСТ 7.0.5 с отдельными элементами ГОСТ 7.1.

В целом, правила ГОСТов (как 7.1, так и 7.0.5) настолько сложны, что автоматизировать библиографию по всем правилам невозможно. Вышеупомянутый формат CSL 1.0.1, задуманный как универсальный окончательный формат для формирования всей библиографии на свете, разумеется, не подходит в полной мере для этих ГОСТов.

В частности, в ГОСТе есть разумное требование: английские ссылки должны быть с английскими вспомогательными словами (Vol., No., pp., ed. и прочие), а русские — с русскими. В CSL 1.0.1 такой опции не предусмотрено. Опция появилась в расширении CSL-M, которое не поддерживается в pandoc-citeproc. Это препятствие удалось частично преодолеть ценой установки вспомогательного поля «note» в русскоязычных статьях и дополнительных изменений в CSL-файле.

Шаблон

Pandoc работает с основным текстом документа. Такие вещи, как титульный лист и колонтитулы, легко создаются пользователями в Word в режиме WYSIWYG, тогда как их создание в Pandoc затруднено или невозможно. Для разрешения этого противоречия в GOSTdown существует файл-шаблон в формате docx, который содержит следующее:
  1. Формат колонтитулов (Pandoc «подхватывает» этот формат при генерации документа с основным текстом)
  2. Перечень стилей, которые впоследствии использует Pandoc при генерации docx-файла
  3. Собственно неосновное содержимое документа, т.е. небольшая часть содержимого, которая не генерируется из Markdown.

Постобработка

Напомним, Pandoc преобразует файл основного текста в формате Markdown в аналогичный файл в формате docx. Сразу после получения этого файла возникает задача вставки его в нужное место шаблона (после титульного листа). Этим занимается скрипт постобработки. И не только этим: файл, сгенерированный Pandoc, хотя и содержит необходимые стили, всё же не является готовым продуктом. Для получения готового продукта необходимо следующее:
  1. Установка стилей нумерации и отступы для списков и вложенных списков (Pandoc в настоящий момент не обладает механизмом шаблонизации списков)
  2. Исправление выравнивания номеров формул (нумерованные формулы pandoc-crossref генерирует как таблицы из двух колонок)
  3. Исправление горизонтального выравнивания ячеек таблиц, в которых есть только формула и больше ничего (Word в таком случае берёт настройки выравнивания из формулы, а не из ячейки, а Pandoc не заботится о том, чтобы выравнивание в формуле совпадало с оным в ячейке.)
  4. Установка стилей таблиц (Pandoc не умеет этого делать)
  5. Установка стилей ненумерованных заголовков (они отличаются от стилей нумерованных, а Pandoc присваивает всем заголовкам одного уровня один стиль).
  6. Разные другие мелочи по части форматирования
  7. Вставление оглавления средствами Word
  8. Подсчёт количества страниц, рисунков, таблиц, приложений, литературных источников, и вставка этих чисел в необходимое место документа.
  9. Сохранение полученного документа не только в docx, но и в PDF.
Всё это делается с помощью Word COM. Фактически, любая инсталляция Word на Windows открывает возможности для программного управления содержимым документа так же, как пользователь делал бы это вручную в программе. Широко известно применение этой технологии в макросах (VBA), но макросы не очень удобны тем, что сами хранятся в документе. Менее известен следующий факт: с COM-объектами без труда можно работать в скриптах Powershell. Это и реализовано в GOSTdown, см. скрипт для запуска Pandoc и постобработки.

Вопросы и ответы

1. Где рамочки с боковыми ячейками для подписей?

В представленном примере Описания программы имеются рамки на листе утверждения и титульном листе. В основной части ГОСТ разрешает рамку не наносить. В НТО рамки не требуются нигде.

2. Всё это точно по ГОСТу?

ГОСТы соблюдены в разумных пределах. В редких случаях требования ГОСТов проигнорированы в угоду эстетической составляющей. Например, ГОСТ рекомендует форматировать списки следующим образом:
Также см. выше ремарку о библиографии.

3. Почему шрифты не Arial и Times New Roman, а какие-то другие?

Требований по гарнитуре нет в ГОСТах (за исключением ГОСТов на стандарты и на конструкторскую документацию). В представленных шаблонах используются общедоступные гарнитуры фирмы «Паратайп»: PT Serif (с засечками), PT Sans (без засечек) и PT Mono (моноширинный) Объяснение, почему паратайповские шрифты идеально подходят для документов на русском языке, см. здесь.

4. Почему docx-файлы такие большие?

Из-за вышеупомянутых шрифтов, встроенных в файл. Можно отключить встраивание шрифтов (за него отвечает опция -embedfonts), и тогда файлы станут адекватного размера, но если на компьютере вашего коллеги или заказчика не установлены шрифты PT Serif, PT Sans и PT Mono, то при открытии документа в Word шрифты заменятся на шрифты по умолчанию, и документ в итоге будет выглядеть не так, как было задумано.

5. Почему не LaTeX?

Государственные заказчики не возьмут LaTeX-файл, т.к. не знают, что это такое. В принципе, если заказчику не нужен исходник и достаточно PDF-файла, то можно использовать и LaTeX.
Pandoc умеет генерировать docx-файлы из LaTeX, но генерация осуществляется с потерями из-за разницы в идеологиях LaTeX и Word в области стилей. Теоретически возможен вариант генерации и LaTeX и docx-файлов из одного исходника в Markdown с помощью Pandoc, но в реальности такое средство пока не создано.

6. Почему не Google Docs? Там даже формулы появились

Да, и даже доступны дополнения (Add-ons) для нумерации и библиографии. В Google Docs удобные средства совместной работы, но ограниченные средства форматирования. Нет стилей (кроме небольшого исходного набора). Проблематична вставка векторных рисунков. Нет поддержки офлайновой работы. (На самом деле есть, но тогда перестаёт решаться проблема слияния изменений.)

7. Почему не LibreOffice?

Во-первых, потому, что в LibreOffice/OpenOffice крайне плохо обстоит дело с отображением формул. Позвольте не называть остальные 17 причин.

8. Как преобразовать имеющийся docx в Markdown?

Конечно же, с помощью Pandoc (он ведь преобразует в любую сторону). Конечно, информация о стилях исходного документа при этом потеряется. Возможно, после конвертации потребуется ручная правка. Дополнительные проблемы могут возникнуть с формулами: Pandoc распознаёт в docx-файлах только формулы, набранные средствами Word 2010 (не MS Equation и не MathType). Известен трюк с участием LibreOffice для пересохранения формул MS Equation в Word 2010. Для более позднего MathType он, кажется, не работает.

9. Чем редактировать Markdown?

Любым текстовым редактором, начиная с notepad.exe. Например, для Windows есть Notepad++, для Linux — Emacs, для всех десктопных ОС — Visual Studio Code. Все они бесплатные.
Преимущество текстового представления в том, что вносить правки в текст можно хоть со смартфона в самолёте (и если настроен GitLab CI, вы сразу получаете готовый документ).

10. Что такое Gitlab CI и как мне получить docx, редактируя файл не на Windows?

См. соответствующий раздел руководства. Машина с Windows (удалённая) всё же понадобится, см. раздел «Системные требования».

11. Чем редактировать Markdown так, чтобы сразу видеть результат?

Это сложнее. Вам потребуется или вышеупомянутый Visual Studio Code, или Atom. Потребуется также установить расширение Markdown Preview Enhanced (MPE). Альтернативное расширение — Markdown Preview Plus (MPP), только для Atom. Эти расширения используют Pandoc для того, чтобы делать из вашего Markdown-файла HTML-файл для предпросмотра. Прочие средства редактирования Markdown, в т.ч. онлайновые, рассчитаны на другие диалекты Markdown и не будут отображать Pandoc’s Markdown в полной мере.

Пользовательские настройки для MPE в VS Code таковы:
{
    "markdown-preview-enhanced.usePandocParser": true,
    "markdown-preview-enhanced.pandocArguments":
       "--filter=pandoc-crossref, --filter=pandoc-citeproc"
}
При нажатии Ctrl+k v включается предпросмотр, который, хоть и не совпадает в точности с будущим docx-файлом, аккуратно отображает все формулы, таблицы, блоки кода и изображения (кроме EMF).


12. Таблицы неудобно редактировать в виде текста, что делать?

В Visual Studio Code и Atom существуют многочисленные расширения для упрощения работы с Markdown, в т.ч. с таблицами. Таблицы самого сложного вида (с многоабзацевыми ячейками) они, к сожалению, не поддерживают. Такие таблицы поддерживает Emacs и его table-mode.

13. Мне нужны вещи, которые есть в Word, но отсутствуют в Markdown, что делать?

Если речь идёт об относительно небольшом фрагменте документа, не укладывающимся в формат (например, сложная таблица с объединёнными ячейками), то пользователь может держать этот фрагмент в отдельном docx-файле, редактируя его в Word. Вставка фрагмента в основной текст может делаться скриптом, аналогично тому, как сейчас сам основной текст вставляется в шаблон на место %MAINTEXT%.

Благодарности

В создании GOSTdown принимала активное участие Алёна Водолагина (ИПА РАН), также помощь оказывал Даниил Аксим (ИПА РАН). Разумеется, GOSTdown не был бы возможен без замечательного ПО: Pandoc, pandoc-citeproc и pandoc-crossref (автор последнего — Николай Якимов, МАИ). Ну и Microsoft помогла своими Word COM и Powershell, чего уж там.

понедельник, 29 января 2018 г.

Три жалобы

О компьютерных вещах, в которых я не очень глубоко разбираюсь, но которые мне не нравятся, в особенности их насильственное внедрение. Поделать ничего с ними нельзя, остаётся жаловаться в блог.

Часть первая. HTTPS

Стало сложно найти сайт на простом HTTP. Веб массово переходит на HTTPS, браузеры предпочитают защищённое соединение обычному. HTTP становится изгоем, сайты на нём вскоре будут считаться небезопасными, особенно те, на которых есть пользовательский ввод (даже форма поиска). Не за горами запрет на HTTP, как бы дико это не звучало.

Какие аргументы звучат в пользу HTTPS? Якобы этот протокол гарантирует:
  1. Защиту от прослушивания
  2. Защиту от подмены канала
  3. Защиту от модификации данных
Мне кажется, что ничего этого нет и не будет.

Прослушивание канала

Протокол защищает канал связи от прослушивания — при условии, что злоумышленник сидит исключительно на канале связи. В реальности злоумышленник не щёлкает клювом на канале, а проникает непосредственно на машину пользователя или на сервер. На машине пользователя он инсталлирует кейлоггер, крадущий пароли и номера карт при их вводе с клавиатуры. Если с кейлоггером не получилось, можно украсть ключи, которые позволят прослушать канал и получить пароли и номера карт из него. Ну а если искомые данные у пользователя хранятся в файлах, то вообще никаких усилий не потребуется.

Не инсталлируете сомнительные программы, чтобы оградить себя от хакеров? Правильно делаете, но средства взлома бывают и в известных программах, в том числе в программах с открытыми исходниками; когда их обнаруживают, случается скандал. В программах с закрытыми исходниками средства взлома обнаружить сложнее, поэтому с ними скандалы возникают реже. Злой умысел разработчиков или случайность — неважно, вы скачали программу и тем самым подарили свою машину хакерам. Пользуетесь антивирусом? Антивирусы ловят только то, что уже известно. Если вы оказались в первой волне заражения, антивирус не спасёт.

Не инсталлируете программы, пользуетесь только браузером? В браузерах есть уязвимости, позволяющие выполнить программный код на вашем устройстве. Уязвимости находятся каждый год, их исправляют, потом находятся новые. В движках или в библиотеках типа libpng, неважно. Вы можете зайти на сайт злоумышленника, он особым образом вызовет переполнение буфера в вашем браузере, исполнит программный код по установке руткита и будет дальше делать на вашей машине всё что хочет.

Аналогичные уязвимости есть в серверных программах, которым злоумышленник может послать специально сформированный запрос и получить в итоге контроль над сервером.

Более того, злоумышленник может не озадачиваться полным контролем над сервером. Ему достаточно пропихнуть в веб-страницу свой код — после чего все данные, введённые пользователем на странице, отправятся из браузера прямиком на сервер злоумышленника. Сегодняшняя новость: «Мошенники смогли разместить на YouTube рекламу с кодом для майнинга криптовалюты». Мошеннический Javascript на сервисе Google, каково?

Особого упоминания заслуживает Heartbleed — ошибка в реализации OpenSSL, которая, фактически, сводила на нет защищённость SSH, HTTPS и всего такого. С марта 2012 по апрель 2014 хакеры могли беспрепятственно красть ключи от любых защищённых соединений.

Помимо программ есть операционные системы, также полные дыр.

Наконец, есть уязвимости в аппаратной части. В конце 2017 г. мир узнал, что почти все процессоры с 1995 года имеют уязвимости Meltdown и Spectre, позволяющие программам читать память ядра и других программ. То есть, читать пароли и ключи прямо из оперативной памяти. На мобильных устройствах тоже. Выходят заплатки для операционных систем, программ и микрокода, но их эффективность ограничена. Ошибки в процессорах не исправить.

Ещё одна декабрьская новость: найден способ захватывать контроль над выключенными компьютерами. Поток таких новостей никогда не иссякнет. Серверы и машины пользователей никогда не будут защищены от проникновений. Следовательно, HTTPS никогда не станет гарантией защиты соединения.

Подмена канала

Ленивый злоумышленник даже не станет взламывать ваш канал или красть ваши данные вышеперечисленными способами. Он просто подделает канал, и вы ему дадите все данные добровольно. По защищённому соединению. Простейший способ — заманить вас на легально заведённый адрес, напоминающий настоящий по доменному имени, дизайну и степени надёжности. Критерием надёжности сайта с защищённым соединением является сертификат. Сертификаты продаются удостоверяющими центрами (CA), гарантирующими добропорядочность сайтов. В 2016 г. появился бесплатный центр Let’s Encrypt.

Считаете, что CA помогут браузеру надёжно отличить мошенников от честных людей? Нет такого. Центры подвержены коррупции и бардаку, как и всё в мире. Платный центр Symantec недавно потерял репутацию настолько, что Google планирует отказаться от признания его сертификатов. На молодой и бесплатный Let’s Encrypt тоже поступают жалобы.

Real and fake side-by-side
Обычный PayPal (слева) и подставной (справа). Это реальный мошеннический сайт, которому Let’s Encrypt выдал сертификат. Пользователь видит успокаивающий зелёный значок, а на мелочи не обращает внимания. Источник.

Если мошеннику не удалось получить сертификат, это не повод отчаиваться: на существующих CA свет клином не сошёлся, он может создать собственный CA. Изначально браузер не будет доверять этому CA (и сайту злоумышленника). Благонадёжные CA подтверждены корневыми сертификатами, хранящимися в браузере и операционной системе. Как вы уже догадались, уязвимости, позволяющие мошенникам установить свои корневые сертификаты в систему, обнаруживаются регулярно.

Если хакер проник на вашу машину или на ваш роутер (роутеры — потрясающее решето), ему не потребуется доменное имя-приманка. Подмена DNS-сервера позволит ему поставить свой сайт вместо настоящего. Ведётся деятельность по внедрению шифрования и в DNS, что немного усложнит задачу хакеру, но в принципе ничего особо не изменит, как и HTTPS.

Модификация данных

Протокол защищает канал связи от модификации — при условии, что злоумышленник, опять же, не лезет на сервер или машину пользователя. В действительности, конечно, он это делает.
Допустим, злодей хочет показать вам рекламу. При HTTP можно быть купить у провайдера пакет рекламы, вставляемой в страницы, а HTTPS сделал это невозможным, ну и что? Показ рекламы с тем же успехом можно купить у сайта напрямую или через всякие агентства по рекламе в вебе. На десктопе рекламой блещет скайп, на мобильных устройствах рекламу содержит каждое второе бесплатное приложение.
Ещё одна иллюстрация — AdBlock, превратившийся из блокировщика рекламы в её менеджера, не говоря уже о сайтах, которые детектируют AdBlock, издеваются над пользователем и всё равно показывают ему рекламу. Словом, вам покажут всю рекламу, которая вам полагается: так работает бизнес. Если вы хотите уменьшить количество рекламы в жизни, то заниматься надо не игрой в шпионов по HTTPS, а гораздо более скучной вещью — законами.


HTTPS-сайты в своей первозданной чистоте. Тщательно запланированные и реализованные. Ни единого пикселя непрошеной рекламы от провайдера.

Что плохо в HTTPS?

  • Соединение устанавливается дольше, чем в HTTP. Шифрование/дешифрование создаёт дополнительную нагрузку на процессор.
  • Пользовательские проблемы из-за навязанной технологии. Например: на гаджете открыт сайт по HTTPS через сотовую сеть, гаджет подключается к публичному вай-фаю, пользователь совершает переход внутри сайта (т.е. обращается к тому же сайту, но к другой странице), провайдер публичного вай-фая перенаправляет пользователя на свою страницу авторизации, гаджет считает это попыткой хакерской атаки и жалуется на неправильный сертификат, страницу не показывает, пользователь во фрустрации.
  • Сложность легального анализа трафика для сбора данных и блокировки контента. Считаете, что тайна любого трафика священна и провайдер не должен его видеть вообще? Ну, заметьте, что средства анализа трафика и блокировки добровольно-принудительно внедрились во все крупные сайты с согласия хозяев. Наверняка не за горами легальное прослушивание HTTPS-трафика на стороне провайдера (изобретут официальные сертификаты для прослушивания, если ещё не). Технологии шифрования, как и в случае с рекламой, ничего принципиально не поменяли и не поменяют. Для перемен нужны законы.
  • Забота для вебмастера добывать сертификат для сайта. Самоподписанные сертификаты объявлены браузерами практически вне закона. Приличные сертификаты нужно покупать. Или получить сертификат в Let’s Encrypt и нервно ожидать момента, когда эта организация начнёт наглеть и играть в хотелки с вебмастерами; или же навыдаёт кучу сертификатов мошенническим сайтам и лишится доверия браузеров. Да и с платным центром сертификации это тоже может произойти, см. выше про Symantec.
HTTPS уместен в онлайн-платежах и на сайтах, где есть вход по паролю. Внедрение HTTPS во все сайты без оглядки на реалии приведёт к дальнейшему развитию технологий легального и преступного взлома и в итоге к ослаблению безопасности тех сайтов, где защита действительно нужна.

Часть вторая. Сглаженные шрифты

Большая часть шрифтов в наши дни — векторные: TrueType от Microsoft, Type 1 от Apple, OpenType от Microsoft и Apple вместе, METAFONT от Дональда Кнута. Глифы векторных шрифтов состоят из кривых (2, 3, 2+3 и произвольного порядка соответственно). Считается, что векторные шрифты должны быть в равной степени применимы для экрана и для печати (чего на самом деле не бывает).

С печатью более-менее всё хорошо. Лазерные принтеры растеризуют чёрные векторные глифы бинарным способом, без полутонировния. При большой плотности точек, которую имеют принтеры (600-1200 DPI), ступенчатость линий не является проблемой.

С экраном в основном всё плохо. Если при плотности пикселей ~96 PPI растеризовать кривые «как есть», получается неприятная глазу ступенчатая картинка. Алгоритмы удаления ступенчатости не дают объективно хорошего результата, это не точная наука. Существуют дисплеи высокой плотности (200-400 PPI), на которых проблема ступенчатости стоит менее остро. Но, во-первых, эти дисплеи мало распространены (преимущественно на мониторах Apple и топовых мобильных устройствах), и во-вторых, бороться со ступенчатостью нужно и на этих дисплеях тоже, особенно для прямых косых линий и для любой анимации с текстом.

Я не буду касаться рендеринга текста в PDF. Он, как правило, плох, но PDF — формат в первую очередь для печати, а не для экрана, так что грешно придираться.

Я не буду касаться рендеринга крупного текста (заголовков и пр). В конце концов, крупный текст состоит преимущественно из массивов одноцветных пикселей, и бахрома по краям не мешает его читать. Да его и не так много.

Но вот обычный текст, небольшого размера, в браузере и текстовых редакторах. Текст, который приходится читать с экрана в большом количестве. В нём, за редкими исключениями, что-то не так.

В большинстве глифов (если это не курсив или иной шрифт с украшениями) есть строгие вертикальные и горизонтальные линии. Это во всех отношениях хорошо, это упрощает чтение. Казалось бы, это должно упрощать и сглаживание. В том смысле, что вертикальные и горизонтальные линии вообще не нужно сглаживать! Они прекрасно отображаются прямоугольной сеткой пикселей на экране. Сглаживать нужно лишь косые и кривые линии.

Но, вот беда, глиф стоит в строке так, что его вертикальный край не попадает точно между пикселями. В такой ситуации можно пойти по одному из трёх путей:

1. Применить «сглаживание», несмотря ни на что

Получится как-то так:



Обратите внимание, как повезло букве f, она попала ровно по пикселям. Буквам l, i, t, h повезло меньше, хотя исходные толщины их вертикальных черт такие же, как у f. Очевидно, сглаживание не работает. Невозможно развидеть то, что вертикальные черты глифов, кроме l, размыты по краям и занимают большую, чем l, ширину.

2. Применить субпиксельное сглаживание (ClearType)

Эта технология использует физические свойства жидкокристаллических дисплеев и увеличивает разрешение растеризации чёрных глифов в три раза по горизонтали, а по вертикали не увеличивает. (По этой причине ClearType не используется на смартфонах и планшетах, каковые устройства должны работать одинаково при различных поворотах экрана.)

Диалог с шестью вариантами ClearType в Windows.


Увеличенный фрагмент второго варианта. Цветные квадраты в размене одного пикселя служат для управления яркостью трёх светодиодов, составляющих пиксель.

При растеризации серых точек (при сглаживании) применение ClearType порождает малозаметные цветные артефакты на границах.

Для отображения белых глифов на чёрном фоне алгоритм субпиксельного сглаживания возможен, хотя и несколько отличается и, кажется, отсутствует на практике.

К сожалению, субпиксельное сглаживание всегда сглаживает линии, даже вертикальные. То есть, несмотря на втрое большее горизонтальное разрешение, ему присущи недостатки обычного сглаживания. Посмотрите на ножки буквы m, они все различаются. Вертикальные черты в h и i, T и L — все различаются.

3. Применить хинтинг

Хинтинг — это специальные инструкции по подгонке глифов под пиксельную сетку в мелких кеглях. Пропорции при этом немного страдают, но читабельность повышается значительно. Иллюстрация из Википедии (хинтинг + сглаживание):


Возможно совмещение хинтинга и ClearType. Впрочем, хинтинг сам по себе колоссально улучшает читаемость шрифта с экрана. Хороший хинтинг требует усилий от разработчика шрифта: требуется подгонять под сетку каждый глиф в отдельности, и независимо на разных экранных размерах. Хинтинг присутствует в малом количестве шрифтов. В современных движках рендеринга есть опция авто-хинтинга, с менее впечатляющим результатом.

Хинтинг бывает и без сглаживания, что не делает его хуже. Вот примеры отличного хинтинга:

Хинтинг в PT Sans без сглаживания.


Хинтинг в PT Serif без сглаживания.


Example of bi-level rendering, with detail area.
Какой-то шрифт от Microsoft без сглаживания. (Источник)

Как видно, отсутствие полутонов не уменьшает читательность текста на расстоянии. И это наводит на мысль, что можно...

4. Не использовать векторный шрифт

Пиксельные бинарные шрифты маргинальны и элитны — одновременно. Нет ничего лучше пиксельного шрифта для отображения некрупного кегля на обычном мониторе. Но пиксели не масштабируются и плохо выглядят на печати, поэтому операционные системы и программы подсовывают пользователям в первую очередь векторные шрифты. Современные браузеры и офисные программы не позволяют использовать пиксельные шрифты. Все программы на Java, включая среды разработки (NetBeans, продукты JetBrains и пр.) не позволяют использовать пиксельные шрифты. Остаются эмуляторы терминалов, Emacs, DrRacket и прочие аутсайдеры.

Пиксельные шрифты продолжают развиваться, несмотря на то, что пик их славы прошёл в 1980-е. Наиболее хорошо развиваются моноширинные пиксельные шрифты, по причине их востребованности программистами, коим не нужно масштабирование и печать. Вот блестящий Terminus, созданный в 2010 г.:



Подытожим: среди сложившегося бардака остаётся выбирать для офисных программ векторные шрифты с хинтингом (сглаживание и субпиксели по желанию), а для кода — пиксельные шрифты. Такое стремление к комфорту требует усилий и значительно сужает выбор. В браузере, как правило, пользователи вынуждены пользоваться теми шрифтами, которые пришлись по вкусу дизайнеру, и ничего не сделать.

Пользователи экранов с 200+ PPI взирают на все эти проблемы с лёгким недоумением.


Часть третья. Нейросети

Искусственные компьютерные нейросети возникли в начале 1950-х, и до поры до времени влачили своё существование на задворках прикладной математики. Была красивая идея, что вот есть мозг, в нём есть нейроны, как мозг работает — непонятно, а мы сделаем компьютерную модель с нейронами, как она работает — непонятно, вот мы и получили компьютерный мозг. Это одна из таких вещей, которые должны решать задачи, традиционно сложные для компьютера, но лёгкие для человека. То есть задачи искусственного интеллекта.

Красивая идея не давала особо заметных результатов, но энтузиасты копали тему, сочиняли различные усложнения, доказывали теоремы, в общем, дело как-то двигалось, в основном в академической среде.

Внезапно в начале 2000-х появились графические ускорители (GPU) с их особой архитектурой, существенно превосходящей архитектуру CPU для задач типа вычисления освещённости при рендеринге 3D-картинки. Пришло осознание, что GPU можно использовать не только для 3D. В 2007 году возникла Nvidia CUDA, позволяющая писать программы для GPU практически на обычном Си. За год до этого был предложен особый вид нейросетей под названием «deep learning». Он оказался лучше, чем другие виды нейросетей.

CUDA позволила применить «deep learning» на реальных задачах, для которых мощности традиционных CPU не хватало. Нейросети начали захватывать мир, и к настоящему моменту захватили.

Из каждого утюга слышны новости об успехах нейросетей. Использовать технологии машинного обучения, отличающиеся от deep leaning, стало неприлично. Для нейросетей есть современные средства на Питоне. Вся движуха AI сегодня в нейросетях, а более строгие математические методы считаются вчерашним днём и нишевыми инструментами. Школьники создают нейросети для определения жанра музыки. Геологи создают нейросети для поиска месторождений.

Откуда этот ажиотаж, зачем?

Нейросеть не может победить другие алгоритмы

Точнее, может — если эти алгоритмы такие же глупые, как она. Генетические алгоритмы, например. Но не о них речь. Нейросети уместны там, где не придумано алгоритмов, использующих специфику задачи. Нейросети не используют специфику задачи и поэтому могут решить любую задачу. В этом сила нейросетей и одновременно их слабость. Никакую задачу нейросети не могут решить хорошо и математически доказуемо.

Нейросеть — это абстрактная модель, под которую можно подогнать любые данные. Размер модели (и, соответственно, её дискриминирующие свойства) можно настраивать путём добавления нейронов или целых слоёв. Нейросеть «обучается» аппроксимировать некоторую функцию, которая, якобы, имеет какое-то отношение к требуемому результату (на самом деле не имеет, т.к. никакие свойства предметной области не находят прямого отражения в получившейся функции).

Заметим, что нейросеть — не единственный подход такого рода. Можно назвать битовые отпечатки, байесовские классификаторы, SVM, Монте-Карло + цепи Маркова, кластерный анализ. Эти вещи в принципе не хуже нейросетей и друг друга.

На этот счёт есть известная теорема об отсутствии бесплатных завтраков (No free lunch). Вкратце: все методы оптимизации в среднем одинаково (не)эффективны. То есть, метод, одинаково подходящий для любых задач оптимизации, подходит для всех задач одинаково плохо — хуже, чем методы, предназначенные для конкретной задачи и неприменимые к другим.

Оговоримся, что в некоторых случаях специфика задачи всё же используется, например свёрточные (convolutional) нейронные сети в большей степени заточены под обработку изображений. Также в ряде алгоритмов исходные данные подвергаются специально придуманному препроцессингу перед передачей их в нейросеть. С каждым таким шагом алгоритм становится дальше от нейросетей и ближе к задаче. В пределе этой деятельности нейросеть окажется не нужна, см. рус. народ. сказку «Каша из топора».

Машинное обучение на нейросетях вырвалось вперёд по сравнению с другими глупыми методами по одной основной причине: те самые GPU. Оказалось, что нейросетевые вычисления хорошо параллелятся и позволяют максимально эффективно использовать вычислительные ресурсы. Победа нейросетей — это победа видеокарт.

Это, кстати, видно и по общему положению дел в области. Львиная доля публикаций на тему нейросетевых алгоритмов сводится к описанию эксперимента вида «мы взяли фреймворк, настроили какие-то параметры, достали где-то обучающее и тестовое множества, и что-то получилось». Фактически, наука превратилась в игры с инструментами. Почему люди считают это стоящим занятием? Потому что конфигурирование и запуск фреймворков — большая работа, есть над чем потрудиться и испытать гордость за хорошо сделанное дело. В поддержке популярности нейросетей есть и экономическая подоплёка: продажи GPU, продажи обучающих и тестовых множеств, продажи обученных моделей.

Польза нейросетей дико преувеличивается

Большая часть задач решается более адекватными средствами: хоть линейная регрессия, хоть байес, хоть алгоритм Дейкстры для поиска кратчайшего пути. Нейросеть, как правило, на таких задачах с треском проваливается. Если можно применить математически обоснованный метод, его нужно применять, и он будет выгоднее нейросети. Использование нейросети равнозначно печальному признанию в том, что приличного алгоритма придумать не получилось.

В задачах с динамикой процессов нейросети бесполезны в принципе. Нейросеть не знает, что такое время и динамическая модель.

Генерация или дорисовывание красивых бесполезных картинок давно делалось и без нейросетей методами математической статистики.

Нейросеть распознала кота на картинке не хуже человека? Прекрасно, но картинка-то была похожа на обучающее множество. На картинке, не похожей на обучающее множество, нейросеть ошибётся, а человек подумает и выдаст правильный ответ.

С распознаванием речи всё то же самое.

Нейросеть без всякого обучения выиграла в шахматы или го? Серьёзно, кому нужны программы, играющие в шахматы или го, пусть даже лучше всех в мире? По-моему, это не про интеллект вообще.

Увлечение нейросетями проникло даже в астрономию. Нейросеть нашла экзопланету! Нейросеть ищет резонансы в движении астероидов! Конечно, без нейросетей всё это делалось и делается куда лучше. Просто мода.

Нейросети разорительны

IBM вложила миллиард долларов в нейросетевой компьютер Watson, который якобы научился выдавать диагнозы онкобольным и назначать курс лечения. Оказалось, что врачи лучше справляются с этой работой. Кроме онкологии, Watson отличился интересной трактовкой песен Боба Дилана и ещё несколькими вещами.

Кстати, идея о том, что нейросеть на компьютере может каким-то образом симулировать мозг, абсолютно несостоятельна. Мозг — это не нейросеть. Это неизвестно что. Наука, кажется, до сих пор открывала лишь то, чем мозг не является. В III веке до н.э. люди изобрели гидравлику и предположили, что мозг — это гидравлическое устройство. В XVI-XVII веках с развитием механизмов появились фантазии на тему мозга как механизма. Электричество, телеграф, первые вычислительные машины — всё находило место в гипотезах о происхождении мысли. Теперь вот нейросети в тренде. А мозг всё так же непостижим.

Швейцарский профессор Генри Маркрам в 2013 г. получил от Евросоюза 1.3 миллиарда долларов на проект, посвящённый симуляции могза человека (!) на компьютере. В 2015 г. профессора выгнали из проекта за шарлатанство и распил. Сам проект закрывать не стали, неудобно. Профессор успел симулировать часть неокортекса крысы объёмом 0.3 мм3. Ещё одним выдающимся проектом является симуляция нервной системы червя-нематоды.

После AI Winter, нагрянувшей в середине 1970-х, человечество разочаровалось в Лиспе и экспертных системах. Придёт ли вторая зима, после которой упадёт популярность Питона и нейросетей на GPU?