Попытка улучшить алгоритмы растеризации шрифтов, пользуясь исключительно общедоступной информацией.
В первый раз я столкнулся с этой статьей в 2008 году. С тех пор я неоднократно задумывался о переводе (так как лучшего материала по теме не найти), и вдруг ссылка на оригинал всплыла на Хабре в обсуждении топика «Сглаживание шрифтов, анти-алиасинг, и субпиксельный рендеринг». Это стало решающим фактором (раз на материал ссылаются, значит, он кому-то нужен), и работа была, наконец, закончена.
Некоторые используемые термины не имеют общепринятых русских аналогов. Я буду переводить anti-aliasing как сглаживание (так считает википедия, и я склонен с ней согласиться), hinting как хинтинг (хинтование, на мой взгляд, не слишком благозвучное и совсем не распространенное слово), а rendering как растеризацию (в применении к шрифтам этот термин кажется мне более уместным, чем калька с английского; «отрисовка» же, на мой взгляд, слишком общее понятие).
Тем, кто ранее не интересовался темой экранной типографики, перед чтением статьи будет полезно сходить по приведенным выше ссылкам, и разобраться, что значат все эти термины.
Статья опубликована в 2007 году, и последняя версия Windows, упоминающаяся в ней — Vista. Тем не менее, большая часть статьи актуальна и по сей день: в Windows 7 механизмы растеризации шрифтов недалеко ушли от Vista, а тенденция к переводу интерфейсов на веб платформу добавила к различиям растеризации в разных ОС ещё и различия растеризации в разных браузерах. Так что, на мой взгляд, приведенные в статье идеи не теряют акутальность до сих пор.
Тексты на скриншотах я не переводил: с одной стороны, у меня не было технической возможности подготовить корректные изображения, с другой — тексты на них никоим образом не влияют на смысл статьи.
Я традиционно стараюсь переводить единицы в метрические, кроме общепринятых в российской IT-индустрии, таких как DPI. Кроме того, я перевожу имена, но оставляю английские названия компаний и их продуктов.
Буду благодарен за любые дополнения или коррекции перевода. Об очевидных ошибках и опечатках пишите, пожалуйста, личные сообщения — не будем засорять комментарии. Спасибо.
Джоэл Спольски в своей статье «Сглаживание шрифтов и субпиксельная отрисовка» [1] (та же статья в более раннем переводе на Хабре, прим. перев.) сравнивает методы растеризации текста в продуктах Microsoft и Apple, и делает предположение, почему пользователи Windows не любят Safari. Он объясняет это тем, что текст в Safari выглядит чрезмерно размытым. Я хочу пойти дальше и обобщить собственный опыт по этому вопросу. Я не эксперт в цифровой типографике, тем не менее, мне есть что сказать. Как минимум, некоторые из моих идей могут пригодиться сообществу GNU/Linux.
Джеф Этвуд в своем посте «Растеризация шрифтов: придерживаемся сетки пикселей» [5] пишет:
Я бы ответил на это так: до тех пор, пока Microsoft придерживается своей политики агрессивного хинтинга, мониторов с разрешением больше 100 DPI просто не появится. Стараниями Microsoft нам просто не вырваться из порочного круга.
Джеф не одобряет метод растеризации, применяющийся в продуктах Apple. Мне он тоже не слишком симпатичен. Но, может быть, миссия Apple — приблизить эпоху 200 DPI мониторов? Ладно, моя планка ещё выше, я хочу 300 DPI. По моим ощущениям, даже 200 DPI недостаточно, чтобы полностью отказаться от хинтинга. Тем не менее, в этой статье я попробую осветить и стратегию Apple в том числе. Статья может показаться вам длинной и скучной, но я чувствую необходимость тщательно и детально проанализировать сложившуюся ситуацию.
Чтобы добавить немного интриги, я загляну вперед и покажу вам несколько примеров.
Выглядит размытым? Но обратите внимание на размер текста. И имейте в виду, что он остается прекрасно читаемым, гладким и в то же время чётким. И в то же время, форма знаков полностью сохранена (используется гарнитура «Arial»).
Хорошо, как насчет этого примера?
Выглядит слишком тяжелым? Нет проблем, мы можем сделать его светлее.
И ещё пара примеров:
Это шрифт Georgia. Обратите внимание, форма знаков в обоих случаях идеально сохранена, просто во втором примере текст умышленно сделан более «тяжелым».
Но это была просто демонстрация, вот основная идея этой статьи: мы можем отказаться от привязки к пиксельной сетке по горизонтали! С этого момента вы можете использовать точность позиционирования текста по горизонтали в 1/256 пикселя! Вы можете сдвигать текст по горизонтали на любое дробное значение, при этом сохраняя прекрасный внешний вид текста! Эта «мелочь» на самом деле много значит. Как насчет этого:
Звучит как что-то невозможное? Хорошо, вот ещё один пример.
Посмотрите внимательно. Вы не заметили ничего странного? Каждая строка смещена вправо на одну десятую пикселя, так что в результате к 30-й строке смещение плавно накапливается, и составляет уже три пикселя. Я думаю, вы представляете себе, как бы выглядел этот пример, если бы мы использовали классическую привязку к сетке пикселей.
Если не представляете, вот пример:
Самое удивительное, что здесь нет ничего фантастически сложного! Даже патентовать нечего. Вся информация, которую я использовал, доступна публично и/или логически выводится из того, что мы знаем о применяющихся в настоящее время алгоритмах растеризации шрифтов. Вам всего лишь потребуется здравый смысл и немного инженерного чутья. Итак, поехали. Вы можете скачать демонстрационную программу со всеми исходниками в конце этой статьи, и поиграться с ней, но для начала, пожалуйста, проявите немного терпения, чтобы дочитать эту довольно длинную историю до конца.
Я начну с довольно жесткого заявления. Microsoft сыграли злую шутку со всем остальным миром. Способ растеризации шрифтов в Windows XP представляет собой безвкусицу с полным отсутствием инженерной культуры. Текст в XP выглядит чётко и привлекательно, но при этом совершенно неправильно.
Небольшой тест. Представим, что у нас есть одна строка текста, набранная гарнитурой Times New Roman, и отпечатанная в высоком разрешении (допустим, ровно в 1000 DPI). Эта строка занимает на бумаге 87% некоторого заданного расстояния (предположим, 12,7 см). Теперь нам нужно получить пропорциональное изображение в низком разрешении, допустим, в 100 DPI так, чтобы наши 12,7 см соответствовали ровно 500 пикселям. Есть ли в Windows способ отобразить текст, занимающий ровно 87% от 500 пикселей? Нет! Это очевидно из приведенных ниже скриншотов. Они сняты с Windows XP, «Свойства экрана -> Параметры -> Дополнительно -> Общие -> Масштаб (количество точек на дюйм) -> Особые параметры...».
Они (Microsoft. прим. перев.) пожертвовали честью инженеров ради денег, что привело к отсутствию технического прогресса (в повышении разрешения мониторов, прим. перев.) в течении многих лет. Они используют черезмерно агрессивный хинтинг, который не только искажает форму знаков, но и накапливает значительную ошибку (в координате по горизонтали, прим. перев.) на протяжении всей строки. В результате шрифты нельзя считать свободно масштабируемыми, они только выглядят масштабируемыми, но на самом деле это не так. Этот факт повлиял на индустрию компьютерных мониторов. Вы можете себе представить Windows XP на мониторе с разрешением в 600 DPI? Скажем, 8000x6000 пикселей? Я не могу, и не только из-за растровых пиктограмм, но преимущественно из-за ужасного масштабирования текста. Если вы измените разрешение в свойствах экрана, некоторые диалоговые окна в программах неизбежно будут отображаться некоректно. Соответственно, в чем мотивация выпускать мониторы с высоким разрешением?
Вы можете возразить, что проектировщики ПО должны учитывать различные размеры шрифта. Я бы согласился с вами, если бы не одна маленькая деталь. Создание стопроцентно корректных диалоговых окон чудовищно утомительно. В Windows Vista свободное масштабирование реализовано значительно лучше, но ситуация уже сложилась, и пройдет много времени, прежде чем она исправится. Другими словами, мы не можем свободно масштабировать диалоговые окна.
Некоторое время назад я работал на компанию Johnson&Johnson (привет Димитрису Аграфиотису и другим коллегам) и мне приходилось проектировать сложные диалоговые окна для платформы .Net WinForms. По умолчанию для любого статического или редактируемого текста применялось что-то вроде «Tahoma, 10pt». Но мне постоянно приходилось беспокоиться по поводу некоторого дополнительного свободного места в конце каждой строки текста, потому что после смены разрешения текст регулярно не вписывался в отведенное пространство, и формами совершенно невозможно было пользоваться. Так что если вы беспокоитесь о пропорциональном масштабировании, вам приходится оформлять ваши формы ужасным образом, оставляя большое количество свободного места «про запас». Другой способ заключается в том, чтобы жестко привязать размер текста к пикселям. То есть, использовать что-то вроде «Tahoma 14px» (обратите внимание, px, а не pt. прим. перев.). Это многое значит. Это значит, что ваше ПО не сможет использоваться на высоких разрешениях. Неважно, насколько хорошо Windows Vista поддерживает масштабирование текста: все равно беда уже случилась. Есть огромное количество ПО, которое полагается на фиксированное разрешение и это не дает производителям мониторов разрабатывать экраны высокого разрешения. Нет никакой мотивации! Вам не стоит обвинять меня и многих других разработчиков и проектировщиков ПО. Обвиняйте Microsoft за их брутальный хинтинг, который приводит к непредсказуемому наползанию текста на графические элементы.
Да, в Windows Vista с применением WPF всё становится свободно масштабируемым. Это хорошая новость. Плохая новость в том, что всё равно нельзя использовать высокие разрешения. Проблемы подробно описаны Лонгом Ценгом и Джимом Мэтьюсом:
Long Zheng, Windows Vista DPI scaling: my Vista is bigger than your Vista.
www.istartedsomething.com/20061211/vista-dpi-scaling
Jim Mathies, XP Style DPI Scaling.
www.mathies.com/weblog/?p=908
В Microsoft Word, который построен по принципу WYSIWYG, важно сохранять корректность разметки на любом разрешении. Это значит, что разметка должна быть свободно масштабируемой, и она действительно масштабируема. Но позвольте мне провести небольшое расследование. Ниже приведен текст так, как он выглядит в Microsoft Word из пакета Office 2003. Нет смысла читать этот текст, просто взгляните на него.
И сравните с тем, как он выглядит в Adobe Acrobat Reader:
Вы сможете лучше ощутить разницу, если скачаете оба изображения, и будете переключаться между ними в какой-нибудь программе, поддерживающей слайдшоу (я использую приятный и бесплатный IrfanView). Текст в Adobe Acrobat смотрится равномернее, к тому же, он гораздо ближе к тому, что мы видим на принтере. Текст в MS Word смотрится более чётким, но в целом он уродливее. Почему? Из-за кривого кернинга. Выглядит так, будто бы они вообще отказываются от кернинга на низких разрешениях (а 96 DPI это очень мало). Привязка глифов к пикселям в конечном итоге приводит к случайно разбросанным пробелам, которые выглядят просто ужасно. Есть только один способ заставить текст выглядеть лучше — использовать горизонтальное субпиксельное позиционирование. Это физический закон, близко связанный с теоремой Котельникова (в англоязычной литературе — теорема Найквиста — Шеннона или теорема отсчётов), которая гласит:
В нашем случае под спектром сигнала мы имеем в виду частоту дискретизации. На практике это значит, что вы не можете корректно отобразить набор вертикальных линий, одновременно четко и с равными интервалами до тех пор, пока интервалы кратны пикселям. Либо расстояние между линиями будет прыгать, либо некоторые линии будут выглядеть размытыми. Другого выбора нет, и точка.
Пьер Арнауд продемонстрировал это ещё более понятным образом:
Да, становятся. Именно это и происходит в Microsoft Word.
Таким образом, Microsoft не допускает субпиксельное позиционирование, а Adobe допускает. Это значит, что одни и те же глифы на разных позициях могут давать разное фактическое отображение на экране. Это чётко заметно в слове «institutions», помеченном красным прямоугольником в примерах выше.
Взгляните на Adobe'овские глифы «i», «n», «s», «t». Есть как минимум две разные версии их отображения в разных позициях. Именно поэтому текст у Adobe смотрится более равномерным, но при этом более размытым.
Теперь, если вы наберете то же самое слово «institutions» в WordPad, результат будет другим (и будет смотреться куда лучше). Так почему же он так плохо выглядит в MS Word? Только из-за визуальной неточности в позиционировании. Функция TextOut(), которая, по-видимому, используется в WordPad, не заботится об этом, но MS Word вынужден (чтобы сохранять корректность разметки при масштабировании, прим. перев.). Я не уверен на все сто, но могу предположить, что разработчики MS Word расчитывают смещение глифов на высоких разрешениях с нехинтованными глифами. Есть только один способ сделать это, используя документированный Win32 API — вызвать GetGlyphOutline() с очень сильно увеличенной аффинной матрицей таким образом, чтобы получившийся глиф умещался в прямоугольник 1024x1024 или около того. Непосредственное использование этого приема дает точно такой же результат, как и TextOut(). Он смотрится хорошо, но накапливает ощутимую ошибку на протяжении строки текста (больше, чем размер одного символа на протяжении только одного слова!).
В случае же с диалоговыми окнами, как мне кажется, они решили допустимым не сохранять точную ширину текста. Почему? Потому что иначе подписи, меню, диалоговые окна и тому подобное не выглядели бы так заманчиво. Была бы та же самая проблема со случайно разбросанным кернингом, что явно навредило бы продажам их ПО. Итак, симпатичный и чёткий текст в диалоговых окнах способствует бизнесу, но накапливает значительную неточность в ширине текста, что приводит к невозможности изменения размера диалоговых окон, а это, в свою очередь, вынуждает производителей выпускать мониторы с 96 DPI — в результате мы имеем порочный круг, который в конце концов превратился в большую профанацию.
С чисто инженерной точки зрения должен быть разумный компромисс между чёткостью текста и функциональностью. Проблема в том, что Microsoft сконцентрировалась на гламурном оформлении, при этом полностью игнорируя функциональную часть. Парадокс: на разрешении в 300 DPI вам вообще не нужен хинтинг, к тому же, текст становится свободно масштабируемым (а при разрешении 600 DPI и выше вам даже не нужно сглаживание), но вы не можете использовать ваше ПО на 300 DPI, потому что оно рассчитано в лучшем случае на 100 DPI! Вот цена, которую весь мир платит за гламурное оформление. Эта цена слишком высока, просто невероятно высока.
Несмотря на это, ещё 5 (пять!) лет назад было технически возможно иметь свободно масштабируемые формы и диалоговые окна. Все, что нам было нужно — допустить определенную степень размытия, очень незначительную, не настолько высокую, как в Mac OS X. Скорее, как в продукции Adobe. Пользователи Windows не любят Safari за слишком размытый вывод. Я частично согласен с ними, за исключением слепого отрицания любых других способов растеризации, кроме использующегося в Windows. Это просто безрассудный фанатизм. Это всё равно, что сказать «мне плевать на разрешение, пусть Windows выглядит так, как я привык, даже ценой в 96 DPI навсегда, даже если для этого потребуется остановить технический прогресс». Можно ли считать такой взгляд разумным?
Я не агитирую в пользу Apple, так как от растеризации Apple я тоже не в восторге. На мой взгляд, она действительно выглядит черезмерно размытой. Похоже, они используют что-то вроде алгоритма автохинтинга, который размывает горизонтальные штрихи, но по сути не дает никаких преимуществ. Фактически, их хинтинг тоже выглядит кривым, особенно для шрифтов без засечек, как будто бы они специально сдвинули чёткий текст на 0,2..0,5 пикселя. Именно поэтому пользователи Windows так не любят Safari. Но при этом многие из них с удовольствием используют Adobe Acrobat Reader и остаются довольны. Всё потому, что в нём текст выглядит приемлимо (не идеально, но приемлимо для фанатов Windows). При этом он остается свободно масштабируемым! Попробуйте просто загрузить любой документ и плавно увеличивать-уменьшать его. Разметка текста остается корректной, и при этом кернинг тоже. Так что я бы назвал способ рендеринга Adobe наилучшим, потому что их компромисс выглядит очень близко к оптимальному.
Джеф Этвуд [5] однозначно высказывается в пользу строгой привязки к пиксельной сетке. У меня свое мнение. Я согласен считаться с пиксельной сеткой, но только по оси Y. По X предпочтительнее использовать субпиксельное позиционирование. При этом мы жертвуем резкостью (но совсем незначительно), зато обретаем полную свободу.
Ирония в том, что у Microsoft уже есть субпиксельное позиционирование в хинтинге глифов. Самое смешное: это чётко видно на страницах Джефа с тем шрифтом, который он использует.
Посмотрите внимательно: слово «common», выделенное красным, а также буква «m».
Видите, три вертикальных штриха «m» отличаются друг от друга! Несмотря на это, в оригинальном тексте они смотрятся вполне чётко и привлекательно. Что это значит? Многое. Это значит, что с ClearType возможно использовать позиционирование с точностью до 1/3 пикселя. В таком случае, зачем они прикрепляют глифы к пикселям?! Этого я не понимаю. Точности в 1/3 пикселя было бы достаточно для точного кернинга и одновременно чёткого текста! Хорошо, если я вас ещё не убедил, продемонстрирую в деталях. Я взял скриншот строки текста из Microsoft Word. Он выглядел так:
Затем, с помощью несложных программных манипуляций я преобразовал цвета к битовой карте, допускающей три значения каждого цвета:
А затем я произвел «альфа-смешивание» этой карты в модели цветов RGB, воспринимая каждый цветовой канал как отдельный серый пиксель. Я проделал это 12 раз со смещением в 1 серый пиксель, получая смещение на 1/3 пикселя в RGB. Посмотрите, что получилось:
Но это же и есть субпиксельное позиционирование! Вы можете легко убедиться в этом: за 12 линий накопились 4 лишних пикселя, при этом чёткость символов не пострадала. Хорошо, строки слегка отличаются, но вам придется очень близко рассматривать их, чтобы это заметить (замечу, у меня зрение — единица, и я не ношу очки). Поверьте мне, это очень низкая цена за свободу точного субпиксельного позиционирования! Так что это работает. Это вполне возможно. Почему вы не используете субпиксельное позиционирование, дорогая Microsoft, ответьте! Ответа нет.
Кстати, а есть ли субпиксельное позиционирование в Windows Vista? Похоже что нет. Во всяком случае, я не смог найти ни одного примера, где один и тот же глиф растеризовался бы в различные наборы пикселей в разных позициях. Вы видите, они слегка увеличили размер шрифта по умолчанию (для 96 DPI), но, что более заметно, они увеличили межсимвольные интервалы таким образом, чтобы некорректное позиционирование меньше бросалось в глаза. Это хорошо, но как насчет более аккуратных форм символов? Вынужден признать: ситуация с цифровой типографикой не слишком улучшилась после выхода Vista. И вряд ли мы можем расчитывать, что в ближайшее время она изменится.
Ещё один большой вопрос заключается в названии «Microsoft ClearType Font Collection». Почему они называют её коллекцией шрифтов ClearType? Эта технология жёстко привязана к конкретным шрифтам? Тогда, опять же, эта технология производит впечатление очень узкоспециализированного локального решения, таким образом, она не может быть успешно применена к абсолютно любому шрифту. Ниже я продемонстрирую, как с применением автохинтера FreeType можно получить честный, универсальный и независимый от шрифта способ растеризации. Всё, что вам нужно, это векторные кривые глифов. Больше ничего.
Джеф, среди всего прочего, ссылается на документацию к FontFocus [4]. При всем уважении, я вынужден не согласиться с ней.
Они выравнивают штрихи по пикселям, игнорируя при этом вертикальный хинтинг. Вы видите, символы «T», «W», «C» и «g» сильно размыты. Кроме того, «W» выглядит тяжелее остальных.
На мой взгляд, это выглядит довольно небрежно. Подразумевается, что это Times New Roman. Похоже? Нет, больше похоже на примитивный растровый шрифт. Так в чем же смысл? Не проще ли один раз сохранить шрифт как растровый и использовать на низких разрешениях его? Какой смысл в сглаживании, если мы можем себе позволить искажать форму знаков? Кроме того, похоже что в тексте есть «пятна», будто бы он написан чернилами на мягкой салфетке: большая часть штрихов правильные, но кое-где они смазаны. В любом случае, проблема та же: либо вы отказываетесь от корректной разметки, либо получаете кривой кернинг.
Здесь я хочу снова упомянуть Safari. Не могу сказать с полной уверенностью, но, похоже, Mac OS тоже не использует субпиксельный кернинг, что в итоге приводит к проблемам, о которых я писал выше, критикуя подход Microsoft. Способ Safari гораздо ближе к получению корректной разметки с сохранением правильного позиционирования знаков, но выглядит это так, будто они тоже жестко привязывают символы к пикселям, и не важно, насколько размытым получается результат. Так в чем же их политика? Специально использовать растеризацию, которая (на низких разрешениях — прим. перев.) дает весьма размытый текст, только для того, чтобы люди покупали экраны с более высоким разрешением? Нечестная игра!
Ниже вы увидите, как добиться приятного и корректного отображения текста, и, что самое интересное, в результате весьма простых манипуляций. Я использовал библиотеку FreeType [10] и функцию GetGlyphOutline() из Win32 API. Другими словами, такая схема растеризации возможна как в Windows, так и в Linux, ну и, конечно же, в Mac OS, в которой FreeType тоже прекрасно компилируется. Кроме того, я выяснил, что автохинтер FreeType работает вполне корректно, если использовать его так, как я это делал (в обычных условиях результат его работы нельзя назвать приемлимым). Но для начала я расскажу о ситуации в мире Linux.
Продолжение...
От переводчика
В первый раз я столкнулся с этой статьей в 2008 году. С тех пор я неоднократно задумывался о переводе (так как лучшего материала по теме не найти), и вдруг ссылка на оригинал всплыла на Хабре в обсуждении топика «Сглаживание шрифтов, анти-алиасинг, и субпиксельный рендеринг». Это стало решающим фактором (раз на материал ссылаются, значит, он кому-то нужен), и работа была, наконец, закончена.
Некоторые используемые термины не имеют общепринятых русских аналогов. Я буду переводить anti-aliasing как сглаживание (так считает википедия, и я склонен с ней согласиться), hinting как хинтинг (хинтование, на мой взгляд, не слишком благозвучное и совсем не распространенное слово), а rendering как растеризацию (в применении к шрифтам этот термин кажется мне более уместным, чем калька с английского; «отрисовка» же, на мой взгляд, слишком общее понятие).
Тем, кто ранее не интересовался темой экранной типографики, перед чтением статьи будет полезно сходить по приведенным выше ссылкам, и разобраться, что значат все эти термины.
Статья опубликована в 2007 году, и последняя версия Windows, упоминающаяся в ней — Vista. Тем не менее, большая часть статьи актуальна и по сей день: в Windows 7 механизмы растеризации шрифтов недалеко ушли от Vista, а тенденция к переводу интерфейсов на веб платформу добавила к различиям растеризации в разных ОС ещё и различия растеризации в разных браузерах. Так что, на мой взгляд, приведенные в статье идеи не теряют акутальность до сих пор.
Тексты на скриншотах я не переводил: с одной стороны, у меня не было технической возможности подготовить корректные изображения, с другой — тексты на них никоим образом не влияют на смысл статьи.
Я традиционно стараюсь переводить единицы в метрические, кроме общепринятых в российской IT-индустрии, таких как DPI. Кроме того, я перевожу имена, но оставляю английские названия компаний и их продуктов.
Буду благодарен за любые дополнения или коррекции перевода. Об очевидных ошибках и опечатках пишите, пожалуйста, личные сообщения — не будем засорять комментарии. Спасибо.
Вступление
Джоэл Спольски в своей статье «Сглаживание шрифтов и субпиксельная отрисовка» [1] (та же статья в более раннем переводе на Хабре, прим. перев.) сравнивает методы растеризации текста в продуктах Microsoft и Apple, и делает предположение, почему пользователи Windows не любят Safari. Он объясняет это тем, что текст в Safari выглядит чрезмерно размытым. Я хочу пойти дальше и обобщить собственный опыт по этому вопросу. Я не эксперт в цифровой типографике, тем не менее, мне есть что сказать. Как минимум, некоторые из моих идей могут пригодиться сообществу GNU/Linux.
Джеф Этвуд в своем посте «Растеризация шрифтов: придерживаемся сетки пикселей» [5] пишет:
«Я не понимаю, почему Apple приносят настоящее в жертву будущему. Почему мы не можем пользоваться хинтингом на низких разрещениях, при этом соблюдая точность растеризации на высоких? Привязка шрифтов к сетке пикселей скорее всего будет неактуальной, когда каждый сможет наслаждаться великолепной картинкой на экране своего монитора разрешением в 200 DPI. Но до тех пор, пока это прекрасное время не настало, привязка к сетке пикселей однозначно делает текст значительно более читаемым для тех, кто живет в настоящем»
Я бы ответил на это так: до тех пор, пока Microsoft придерживается своей политики агрессивного хинтинга, мониторов с разрешением больше 100 DPI просто не появится. Стараниями Microsoft нам просто не вырваться из порочного круга.
Джеф не одобряет метод растеризации, применяющийся в продуктах Apple. Мне он тоже не слишком симпатичен. Но, может быть, миссия Apple — приблизить эпоху 200 DPI мониторов? Ладно, моя планка ещё выше, я хочу 300 DPI. По моим ощущениям, даже 200 DPI недостаточно, чтобы полностью отказаться от хинтинга. Тем не менее, в этой статье я попробую осветить и стратегию Apple в том числе. Статья может показаться вам длинной и скучной, но я чувствую необходимость тщательно и детально проанализировать сложившуюся ситуацию.
Чтобы добавить немного интриги, я загляну вперед и покажу вам несколько примеров.
Выглядит размытым? Но обратите внимание на размер текста. И имейте в виду, что он остается прекрасно читаемым, гладким и в то же время чётким. И в то же время, форма знаков полностью сохранена (используется гарнитура «Arial»).
Хорошо, как насчет этого примера?
Выглядит слишком тяжелым? Нет проблем, мы можем сделать его светлее.
И ещё пара примеров:
Это шрифт Georgia. Обратите внимание, форма знаков в обоих случаях идеально сохранена, просто во втором примере текст умышленно сделан более «тяжелым».
Но это была просто демонстрация, вот основная идея этой статьи: мы можем отказаться от привязки к пиксельной сетке по горизонтали! С этого момента вы можете использовать точность позиционирования текста по горизонтали в 1/256 пикселя! Вы можете сдвигать текст по горизонтали на любое дробное значение, при этом сохраняя прекрасный внешний вид текста! Эта «мелочь» на самом деле много значит. Как насчет этого:
- Вы можете применять кернинг с субпиксельным разрешением, не заботясь о внесении дополнительного размытия.
- Вы можете свободно масштабировать текст так, как вам захочется, со стопроцентной гарантией сохранения пропорций и отсутствия выпадения текста за границы графических элементов.
- Вы можете быть уверены в том, что расчетная ширина текста всегда будет соответствовать изображению на экране и на бумаге.
- Вы можете применять интересные векторные эффекты, такие как «искусственный полужирный» или «искусственный курсив», не рискуя получить при этом размытый текст.
Звучит как что-то невозможное? Хорошо, вот ещё один пример.
Посмотрите внимательно. Вы не заметили ничего странного? Каждая строка смещена вправо на одну десятую пикселя, так что в результате к 30-й строке смещение плавно накапливается, и составляет уже три пикселя. Я думаю, вы представляете себе, как бы выглядел этот пример, если бы мы использовали классическую привязку к сетке пикселей.
Если не представляете, вот пример:
Самое удивительное, что здесь нет ничего фантастически сложного! Даже патентовать нечего. Вся информация, которую я использовал, доступна публично и/или логически выводится из того, что мы знаем о применяющихся в настоящее время алгоритмах растеризации шрифтов. Вам всего лишь потребуется здравый смысл и немного инженерного чутья. Итак, поехали. Вы можете скачать демонстрационную программу со всеми исходниками в конце этой статьи, и поиграться с ней, но для начала, пожалуйста, проявите немного терпения, чтобы дочитать эту довольно длинную историю до конца.
Microsoft, Apple, Adobe и FontFocus
Я начну с довольно жесткого заявления. Microsoft сыграли злую шутку со всем остальным миром. Способ растеризации шрифтов в Windows XP представляет собой безвкусицу с полным отсутствием инженерной культуры. Текст в XP выглядит чётко и привлекательно, но при этом совершенно неправильно.
Небольшой тест. Представим, что у нас есть одна строка текста, набранная гарнитурой Times New Roman, и отпечатанная в высоком разрешении (допустим, ровно в 1000 DPI). Эта строка занимает на бумаге 87% некоторого заданного расстояния (предположим, 12,7 см). Теперь нам нужно получить пропорциональное изображение в низком разрешении, допустим, в 100 DPI так, чтобы наши 12,7 см соответствовали ровно 500 пикселям. Есть ли в Windows способ отобразить текст, занимающий ровно 87% от 500 пикселей? Нет! Это очевидно из приведенных ниже скриншотов. Они сняты с Windows XP, «Свойства экрана -> Параметры -> Дополнительно -> Общие -> Масштаб (количество точек на дюйм) -> Особые параметры...».
Они (Microsoft. прим. перев.) пожертвовали честью инженеров ради денег, что привело к отсутствию технического прогресса (в повышении разрешения мониторов, прим. перев.) в течении многих лет. Они используют черезмерно агрессивный хинтинг, который не только искажает форму знаков, но и накапливает значительную ошибку (в координате по горизонтали, прим. перев.) на протяжении всей строки. В результате шрифты нельзя считать свободно масштабируемыми, они только выглядят масштабируемыми, но на самом деле это не так. Этот факт повлиял на индустрию компьютерных мониторов. Вы можете себе представить Windows XP на мониторе с разрешением в 600 DPI? Скажем, 8000x6000 пикселей? Я не могу, и не только из-за растровых пиктограмм, но преимущественно из-за ужасного масштабирования текста. Если вы измените разрешение в свойствах экрана, некоторые диалоговые окна в программах неизбежно будут отображаться некоректно. Соответственно, в чем мотивация выпускать мониторы с высоким разрешением?
Вы можете возразить, что проектировщики ПО должны учитывать различные размеры шрифта. Я бы согласился с вами, если бы не одна маленькая деталь. Создание стопроцентно корректных диалоговых окон чудовищно утомительно. В Windows Vista свободное масштабирование реализовано значительно лучше, но ситуация уже сложилась, и пройдет много времени, прежде чем она исправится. Другими словами, мы не можем свободно масштабировать диалоговые окна.
Некоторое время назад я работал на компанию Johnson&Johnson (привет Димитрису Аграфиотису и другим коллегам) и мне приходилось проектировать сложные диалоговые окна для платформы .Net WinForms. По умолчанию для любого статического или редактируемого текста применялось что-то вроде «Tahoma, 10pt». Но мне постоянно приходилось беспокоиться по поводу некоторого дополнительного свободного места в конце каждой строки текста, потому что после смены разрешения текст регулярно не вписывался в отведенное пространство, и формами совершенно невозможно было пользоваться. Так что если вы беспокоитесь о пропорциональном масштабировании, вам приходится оформлять ваши формы ужасным образом, оставляя большое количество свободного места «про запас». Другой способ заключается в том, чтобы жестко привязать размер текста к пикселям. То есть, использовать что-то вроде «Tahoma 14px» (обратите внимание, px, а не pt. прим. перев.). Это многое значит. Это значит, что ваше ПО не сможет использоваться на высоких разрешениях. Неважно, насколько хорошо Windows Vista поддерживает масштабирование текста: все равно беда уже случилась. Есть огромное количество ПО, которое полагается на фиксированное разрешение и это не дает производителям мониторов разрабатывать экраны высокого разрешения. Нет никакой мотивации! Вам не стоит обвинять меня и многих других разработчиков и проектировщиков ПО. Обвиняйте Microsoft за их брутальный хинтинг, который приводит к непредсказуемому наползанию текста на графические элементы.
Да, в Windows Vista с применением WPF всё становится свободно масштабируемым. Это хорошая новость. Плохая новость в том, что всё равно нельзя использовать высокие разрешения. Проблемы подробно описаны Лонгом Ценгом и Джимом Мэтьюсом:
Long Zheng, Windows Vista DPI scaling: my Vista is bigger than your Vista.
www.istartedsomething.com/20061211/vista-dpi-scaling
Jim Mathies, XP Style DPI Scaling.
www.mathies.com/weblog/?p=908
Microsoft и Adobe: субпиксельное позиционирование и кернинг
В Microsoft Word, который построен по принципу WYSIWYG, важно сохранять корректность разметки на любом разрешении. Это значит, что разметка должна быть свободно масштабируемой, и она действительно масштабируема. Но позвольте мне провести небольшое расследование. Ниже приведен текст так, как он выглядит в Microsoft Word из пакета Office 2003. Нет смысла читать этот текст, просто взгляните на него.
И сравните с тем, как он выглядит в Adobe Acrobat Reader:
Вы сможете лучше ощутить разницу, если скачаете оба изображения, и будете переключаться между ними в какой-нибудь программе, поддерживающей слайдшоу (я использую приятный и бесплатный IrfanView). Текст в Adobe Acrobat смотрится равномернее, к тому же, он гораздо ближе к тому, что мы видим на принтере. Текст в MS Word смотрится более чётким, но в целом он уродливее. Почему? Из-за кривого кернинга. Выглядит так, будто бы они вообще отказываются от кернинга на низких разрешениях (а 96 DPI это очень мало). Привязка глифов к пикселям в конечном итоге приводит к случайно разбросанным пробелам, которые выглядят просто ужасно. Есть только один способ заставить текст выглядеть лучше — использовать горизонтальное субпиксельное позиционирование. Это физический закон, близко связанный с теоремой Котельникова (в англоязычной литературе — теорема Найквиста — Шеннона или теорема отсчётов), которая гласит:
Если аналоговый сигнал имеет ограниченный спектр, то он может быть восстановлен однозначно и без потерь по своим дискретным отсчётам, взятым с частотой строго большей удвоенной максимальной частоты спектра.
В нашем случае под спектром сигнала мы имеем в виду частоту дискретизации. На практике это значит, что вы не можете корректно отобразить набор вертикальных линий, одновременно четко и с равными интервалами до тех пор, пока интервалы кратны пикселям. Либо расстояние между линиями будет прыгать, либо некоторые линии будут выглядеть размытыми. Другого выбора нет, и точка.
Пьер Арнауд продемонстрировал это ещё более понятным образом:
Положим, вам нужно вывести глиф для символа «i», который будет шириной точно в 2.4 пикселя. Если вы используете хинтинг, скорее всего, вы получите на выходе изображение шириной в 2 пикселя. Положим, пробел у нас равен четырем пикселям.
Теперь представьте себе, что вам нужно вывести «iiiiiiiiii» (глиф «i» 10 раз). Это даст нам слово, которое занимает на экране 20 пикселей, но типографская позиция должна сдвинуться на 24 пикселя. Вам придется добавить 4 пикселя к последующему пробелу, фактически удвоив его размер. Это будет смотреться на экране довольно странно. Еще хуже будет, если глиф «i» реально занимает 2.6 пикселя, и хинтер решит растянуть его до 3 пикселей. В этом случае вы займете 30 пикселей на экране, хотя типографская позиция должна была сместиться на 26 пикселей. В этом случае, вы получите ошибку в -4 пикселя, и компенсация этой ошибки полностью съест последующий пробел.
Другая попытка могла бы заключаться в том, чтобы позиционировать глифы «i», округляя их типографские позиции. В результате применения такого подхода мы получили бы следующие координаты по оси x (в случае с шириной глифа в 2.4 пикселя):
x = 0 ----> 0 ошибка = 0 ширина = 2 x = 2.4 --> 2 ошибка = -0.4 ширина = 3 x = 4.8 --> 5 ошибка = +0.2 ширина = 2 x = 7.2 --> 7 ошибка = -0.2 ширина = 3 x = 9.6 --> 10 ошибка = +0.4 ширина = 2
Результат будет ужасен:
.*.*..*.*..* ............ .*.*..*.*..* .*.*..*.*..* .*.*..*.*..* .*.*..*.*..*
Вы поняли идею… Интервалы между глифами «i» становятся переменными.
Да, становятся. Именно это и происходит в Microsoft Word.
Таким образом, Microsoft не допускает субпиксельное позиционирование, а Adobe допускает. Это значит, что одни и те же глифы на разных позициях могут давать разное фактическое отображение на экране. Это чётко заметно в слове «institutions», помеченном красным прямоугольником в примерах выше.
Взгляните на Adobe'овские глифы «i», «n», «s», «t». Есть как минимум две разные версии их отображения в разных позициях. Именно поэтому текст у Adobe смотрится более равномерным, но при этом более размытым.
Теперь, если вы наберете то же самое слово «institutions» в WordPad, результат будет другим (и будет смотреться куда лучше). Так почему же он так плохо выглядит в MS Word? Только из-за визуальной неточности в позиционировании. Функция TextOut(), которая, по-видимому, используется в WordPad, не заботится об этом, но MS Word вынужден (чтобы сохранять корректность разметки при масштабировании, прим. перев.). Я не уверен на все сто, но могу предположить, что разработчики MS Word расчитывают смещение глифов на высоких разрешениях с нехинтованными глифами. Есть только один способ сделать это, используя документированный Win32 API — вызвать GetGlyphOutline() с очень сильно увеличенной аффинной матрицей таким образом, чтобы получившийся глиф умещался в прямоугольник 1024x1024 или около того. Непосредственное использование этого приема дает точно такой же результат, как и TextOut(). Он смотрится хорошо, но накапливает ощутимую ошибку на протяжении строки текста (больше, чем размер одного символа на протяжении только одного слова!).
В случае же с диалоговыми окнами, как мне кажется, они решили допустимым не сохранять точную ширину текста. Почему? Потому что иначе подписи, меню, диалоговые окна и тому подобное не выглядели бы так заманчиво. Была бы та же самая проблема со случайно разбросанным кернингом, что явно навредило бы продажам их ПО. Итак, симпатичный и чёткий текст в диалоговых окнах способствует бизнесу, но накапливает значительную неточность в ширине текста, что приводит к невозможности изменения размера диалоговых окон, а это, в свою очередь, вынуждает производителей выпускать мониторы с 96 DPI — в результате мы имеем порочный круг, который в конце концов превратился в большую профанацию.
С чисто инженерной точки зрения должен быть разумный компромисс между чёткостью текста и функциональностью. Проблема в том, что Microsoft сконцентрировалась на гламурном оформлении, при этом полностью игнорируя функциональную часть. Парадокс: на разрешении в 300 DPI вам вообще не нужен хинтинг, к тому же, текст становится свободно масштабируемым (а при разрешении 600 DPI и выше вам даже не нужно сглаживание), но вы не можете использовать ваше ПО на 300 DPI, потому что оно рассчитано в лучшем случае на 100 DPI! Вот цена, которую весь мир платит за гламурное оформление. Эта цена слишком высока, просто невероятно высока.
Несмотря на это, ещё 5 (пять!) лет назад было технически возможно иметь свободно масштабируемые формы и диалоговые окна. Все, что нам было нужно — допустить определенную степень размытия, очень незначительную, не настолько высокую, как в Mac OS X. Скорее, как в продукции Adobe. Пользователи Windows не любят Safari за слишком размытый вывод. Я частично согласен с ними, за исключением слепого отрицания любых других способов растеризации, кроме использующегося в Windows. Это просто безрассудный фанатизм. Это всё равно, что сказать «мне плевать на разрешение, пусть Windows выглядит так, как я привык, даже ценой в 96 DPI навсегда, даже если для этого потребуется остановить технический прогресс». Можно ли считать такой взгляд разумным?
Я не агитирую в пользу Apple, так как от растеризации Apple я тоже не в восторге. На мой взгляд, она действительно выглядит черезмерно размытой. Похоже, они используют что-то вроде алгоритма автохинтинга, который размывает горизонтальные штрихи, но по сути не дает никаких преимуществ. Фактически, их хинтинг тоже выглядит кривым, особенно для шрифтов без засечек, как будто бы они специально сдвинули чёткий текст на 0,2..0,5 пикселя. Именно поэтому пользователи Windows так не любят Safari. Но при этом многие из них с удовольствием используют Adobe Acrobat Reader и остаются довольны. Всё потому, что в нём текст выглядит приемлимо (не идеально, но приемлимо для фанатов Windows). При этом он остается свободно масштабируемым! Попробуйте просто загрузить любой документ и плавно увеличивать-уменьшать его. Разметка текста остается корректной, и при этом кернинг тоже. Так что я бы назвал способ рендеринга Adobe наилучшим, потому что их компромисс выглядит очень близко к оптимальному.
Субпиксельное позиционирование с помощью ClearType: возможно ли?
Джеф Этвуд [5] однозначно высказывается в пользу строгой привязки к пиксельной сетке. У меня свое мнение. Я согласен считаться с пиксельной сеткой, но только по оси Y. По X предпочтительнее использовать субпиксельное позиционирование. При этом мы жертвуем резкостью (но совсем незначительно), зато обретаем полную свободу.
Ирония в том, что у Microsoft уже есть субпиксельное позиционирование в хинтинге глифов. Самое смешное: это чётко видно на страницах Джефа с тем шрифтом, который он использует.
Посмотрите внимательно: слово «common», выделенное красным, а также буква «m».
Видите, три вертикальных штриха «m» отличаются друг от друга! Несмотря на это, в оригинальном тексте они смотрятся вполне чётко и привлекательно. Что это значит? Многое. Это значит, что с ClearType возможно использовать позиционирование с точностью до 1/3 пикселя. В таком случае, зачем они прикрепляют глифы к пикселям?! Этого я не понимаю. Точности в 1/3 пикселя было бы достаточно для точного кернинга и одновременно чёткого текста! Хорошо, если я вас ещё не убедил, продемонстрирую в деталях. Я взял скриншот строки текста из Microsoft Word. Он выглядел так:
Затем, с помощью несложных программных манипуляций я преобразовал цвета к битовой карте, допускающей три значения каждого цвета:
А затем я произвел «альфа-смешивание» этой карты в модели цветов RGB, воспринимая каждый цветовой канал как отдельный серый пиксель. Я проделал это 12 раз со смещением в 1 серый пиксель, получая смещение на 1/3 пикселя в RGB. Посмотрите, что получилось:
Но это же и есть субпиксельное позиционирование! Вы можете легко убедиться в этом: за 12 линий накопились 4 лишних пикселя, при этом чёткость символов не пострадала. Хорошо, строки слегка отличаются, но вам придется очень близко рассматривать их, чтобы это заметить (замечу, у меня зрение — единица, и я не ношу очки). Поверьте мне, это очень низкая цена за свободу точного субпиксельного позиционирования! Так что это работает. Это вполне возможно. Почему вы не используете субпиксельное позиционирование, дорогая Microsoft, ответьте! Ответа нет.
Кстати, а есть ли субпиксельное позиционирование в Windows Vista? Похоже что нет. Во всяком случае, я не смог найти ни одного примера, где один и тот же глиф растеризовался бы в различные наборы пикселей в разных позициях. Вы видите, они слегка увеличили размер шрифта по умолчанию (для 96 DPI), но, что более заметно, они увеличили межсимвольные интервалы таким образом, чтобы некорректное позиционирование меньше бросалось в глаза. Это хорошо, но как насчет более аккуратных форм символов? Вынужден признать: ситуация с цифровой типографикой не слишком улучшилась после выхода Vista. И вряд ли мы можем расчитывать, что в ближайшее время она изменится.
Ещё один большой вопрос заключается в названии «Microsoft ClearType Font Collection». Почему они называют её коллекцией шрифтов ClearType? Эта технология жёстко привязана к конкретным шрифтам? Тогда, опять же, эта технология производит впечатление очень узкоспециализированного локального решения, таким образом, она не может быть успешно применена к абсолютно любому шрифту. Ниже я продемонстрирую, как с применением автохинтера FreeType можно получить честный, универсальный и независимый от шрифта способ растеризации. Всё, что вам нужно, это векторные кривые глифов. Больше ничего.
Способ, которым FontFocus выполняет выравнивание по сетке пикселей
Джеф, среди всего прочего, ссылается на документацию к FontFocus [4]. При всем уважении, я вынужден не согласиться с ней.
Они выравнивают штрихи по пикселям, игнорируя при этом вертикальный хинтинг. Вы видите, символы «T», «W», «C» и «g» сильно размыты. Кроме того, «W» выглядит тяжелее остальных.
На мой взгляд, это выглядит довольно небрежно. Подразумевается, что это Times New Roman. Похоже? Нет, больше похоже на примитивный растровый шрифт. Так в чем же смысл? Не проще ли один раз сохранить шрифт как растровый и использовать на низких разрешениях его? Какой смысл в сглаживании, если мы можем себе позволить искажать форму знаков? Кроме того, похоже что в тексте есть «пятна», будто бы он написан чернилами на мягкой салфетке: большая часть штрихов правильные, но кое-где они смазаны. В любом случае, проблема та же: либо вы отказываетесь от корректной разметки, либо получаете кривой кернинг.
Здесь я хочу снова упомянуть Safari. Не могу сказать с полной уверенностью, но, похоже, Mac OS тоже не использует субпиксельный кернинг, что в итоге приводит к проблемам, о которых я писал выше, критикуя подход Microsoft. Способ Safari гораздо ближе к получению корректной разметки с сохранением правильного позиционирования знаков, но выглядит это так, будто они тоже жестко привязывают символы к пикселям, и не важно, насколько размытым получается результат. Так в чем же их политика? Специально использовать растеризацию, которая (на низких разрешениях — прим. перев.) дает весьма размытый текст, только для того, чтобы люди покупали экраны с более высоким разрешением? Нечестная игра!
Ниже вы увидите, как добиться приятного и корректного отображения текста, и, что самое интересное, в результате весьма простых манипуляций. Я использовал библиотеку FreeType [10] и функцию GetGlyphOutline() из Win32 API. Другими словами, такая схема растеризации возможна как в Windows, так и в Linux, ну и, конечно же, в Mac OS, в которой FreeType тоже прекрасно компилируется. Кроме того, я выяснил, что автохинтер FreeType работает вполне корректно, если использовать его так, как я это делал (в обычных условиях результат его работы нельзя назвать приемлимым). Но для начала я расскажу о ситуации в мире Linux.
Продолжение...