После того как логический шрифт выбран в контекст устройства, приложение может получить дополнительную информацию о подобранном физическом шрифте и его метриках.
Функция GetTextMetrics, позволяющая выполнить эту задачу, уже рассматривалась ранее.
Но можно использовать и другую функцию, прототип которой приведен ниже:
int GetTextFace(HDC hDC. int nCount. LPTSTR "IpFaceName);
Эта функция получает имя гарнитуры физического шрифта. Оно может отличаться от имени гарнитуры, которое было задано в структуре LOGFONT. Искомое имя в виде строки с завершающим нулевым символом записывается в символьный буфер с адресом IpFaceName. Длина буфера (количество символов) определяется параметром nCount. В случае успешного завершения функция возвращает количество символов, скопированных в буфер, включая и завершающий нулевой символ. В случае ошибки возвращается нулевое значение. Функцию GetTextFace можно вызвать, указав на месте третьего параметра значение NULL. В этом случае она просто вернет количество символов в имени гарнитуры.
Функция GetTextCharSet(HDC hDC) возвращает идентификатор набора символов для текущего шрифта, выбранного в контекст устройства.
Есть и другие функции для получения дополнительной информации о текущей реализации физического шрифта, к которым относятся GetFontLanguagelnfo, GetTextCharSetlnfo и GetOutlineTextMetrics. Они используются при нетривиальном форматировании текста, например при непосредственной работе с глифами.
Новый логический шрифт, созданный функцией CreateFont или CreateFontlndirect, не ассоциируется ни с каким физическим шрифтом, пока он не будет выбран в контекст устройства вызовом функции SelectObject. Процесс поиска и выбора нужного физического шрифта, реализуемый системой в ходе выполнения функции SelectObject, называется подстановкой или отображением шрифта (font mapping).
Процесс отображения логического шрифта довольно сложен. GDI сравнивает параметры, заданные в структуре LOGFONT, с параметрами различных шрифтов, доступных для графического устройства, выбирая наиболее подходящий шрифт. Для сравнения используются штрафные очки, которые имеют разные весовые коэффициенты. Выбирается тот шрифт, для которого штрафная сумма будет наименьшей.
Наиболее важным фактором при подборе физического шрифта является набор символов, который задается в поле IfCharSet При несовпадении этого атрибута очень велика вероятность, что символы будут выводиться совершенно неверными глифами. Следующее по важности поле — это IfOutPrecision. Этот показатель ограничивает рассматриваемые наборы символов определенными типами шрифтов. Затем оценивается поле IfFaceName, а после него— поле IfPitch And Family. Моноширинные шрифты сильно отличаются по внешнему виду от пропорциональных, поэтому этот атрибут также является важным при подстановке. После сравнения указанных полей GDI сравнивает высоту символов, заданную в поле IfHeight, а затем поля IfWidth, Ifltalic, IfUnderline, IfStrikeOut.
Область применения стандартных шрифтов обычно ограничивается простым выводом элементов пользовательского интерфейса. Для любых других целей приходится создавать собственные логические шрифты. В GDI для этого предусмотрены функции CreateFont, CreateFontlndirect и CreateFontlndirectEx.
В этом разделе не будет рассматриваться функция CreateFontlndirectEx, которая поддерживает использование шрифтов нового формата ОрепТуре фирмы Microsoft. При необходимости найти нужную информацию можно в MSDN.
Функция CreateFont использует для описания логического шрифта 14 параметров, поэтому она не слишком удобна в использовании. Вместо нее лучше пользоваться функцией CreateFontlndirect.
По умолчанию в контексте устройства выбран системный шрифт SYSTEM_FONT, основным и почти единственным преимуществом которого является то, что он всегда доступен для использования. Системный шрифт является растровым, содержит буквы переменной ширины, не имеющие засечек, и для него используется кодировка ANSI.
Однако в некоторых случаях может понадобиться шрифт с фиксированной шириной букв или шрифт в кодировке OEM1. Вы можете получить дескриптор одного из стандартных (встроенных) шрифтов при помощи функции GetStockObject, передав в качестве аргумента одно из значений.
Получив дескриптор встроенного шрифта, необходимо выбрать его в контекст устройства при помощи функции SelectObject После окончания работы с встроенным шрифтом его удаление не требуется.
К счастью, при выводе текста приложениям не приходится напрямую общаться с физическими шрифтами. С физическими шрифтами работают шрифтовые драйверы, находящиеся в системе на одном уровне с драйверами графических устройств. В программах же используются так называемые логические шрифты.
Логический шрифт представляет собой объект GDI, описывающий требования к шрифту со стороны приложения. GDI анализирует запрошенные параметры и подбирает наиболее подходящий шрифт из тех, которые зарегистрированы в системе.
Объект логического шрифта находится под управлением GDI вместе с другими логическими объектами. Приложения работают с логическими шрифтами только через их дескрипторы, имеющие тип HF0NT.
Отсчет всех размеров выполняется от так называемой базовой линии шрифта. На ней находится нижняя граница глифов большинства прописных букв. Все символы шрифта размещаются в прямоугольных ячейках.
Высота шрифта tmHeight складывается из надстрочного интервала и подстрочного интервала.
Надстрочный интервал tmAscent — это расстояние от базовой линии до верхней границы ячейки символа.
Подстрочный интервал tm Descent — это расстояние от базовой линии до нижней границы ячейки символа.
Внутренний зазор tmlnternalLeading определяет пространство для размещения диакритических знаков, таких как знак акцента или умляут.
Внешний зазор tmExternalLeading определяет минимальный интервал между соседними строками для многострочного текста.
В полиграфии размер шрифта измеряется в пунктах. Один пункт равен 0,01389 дюйма (1/71,99424). В компьютерной верстке пункт округляется до 1/72 дюйма. Еще один типографский термин «кегль» определяется как разность высоты шрифта и внутреннего зазора.
Для получения информации о шрифте, выбранном в контекст устройства, предназначена функция GetTextMetrics:
BOOL GetTextMetrics(HDC hdc. LPTEXTMETRIC Iptm);
Поле tmWeight определяет вес (жирность) шрифта. Эта величина может изменяться от 0 до 1000, но чаще всего она равна или 400 для нормального начертания шрифта, или 700 для полужирного начертания.
В поле tmOverhang содержится величина, на которую увеличивается ширина символов для синтезированных шрифтов, например для наклонных или жирных шрифтов, получаемых из нормального шрифта. Шрифты TrueType обычно не используют это поле, так как в них для каждого начертания создается свой шрифт.
Поля tmDigitizedAspectX и tmDigitizedAspectY прокомментированы в MSDN терминами горизонтальный аспект устройства (horizontal aspect of the device) и вертикальный аспект устройства (vertical aspect of the device) соответственно, для которых был создан текущий шрифт. По существу, они содержат те же значения, которые возвращает функция GetDeviceCaps с аргументами LOGPIXELSX и LOGPIXELSY, то есть «число пикселов на 1 логический дюйм по горизонтали» и «число пикселов на 1 логический дюйм по вертикали». При синтезе шрифтов имеют значение не абсолютные значения этих величин, а их соотношение tmDigitizedAspectY / tmDigitizedAspectX, называемое аспектным соотношением (aspect ratio).
Windows поддерживает две главные категории шрифтов: «шрифты GDI» и «шрифты устройства» {device fonts). Шрифты GDI хранятся в файлах, которые обычно расположены в одном из подкаталогов операционной системы. Шрифты устройства соответствуют конкретному устройству вывода. Например, большинство принтеров имеет набор встроенных шрифтов устройства. Шрифты GDI подразделяются на три типа:
растровые шрифты;
векторные шрифты;
шрифты типа TrueType.
В шрифтах растрового типа символы хранятся в виде растровых картинок — прямоугольных матриц из точек-пикселов. В этих шрифтах каждая точка символа описывается отдельно. Растровые шрифты удобны для вывода текста на экран, особенно при малой высоте букв. Однако для каждого размера шрифта и, возможно, для различных разрешений экрана необходимо хранить свой набор символов. Растровые шрифты плохо поддаются масштабированию, так как при увеличении символов просто дублируются строки или колонки пикселов, что, конечно, приводит к «зазубринам» в очертаниях глифов. Чаще всего растровые шрифты применяются для воспроизведения текстовых элементов интерфейса Windows.
В векторных шрифтах глиф описывается последовательностью линейных отрезков, которые затем рисуются с помощью пера. Векторные шрифты легко масштабируются в широких пределах. Однако они имеют более низкую скорость отображения, плохую четкость при маленьких размерах, а при большом увеличении символы выглядят очень бледными, потому что их контуры являются всего лишь тонкими линиями. В настоящее время они применяются в основном только для плоттеров. Векторные шрифты так же, как и растровые шрифты, хранятся в файлах с расширением .fon.
С появлением шрифтов типа TrueType в версии Windows 3.1 значительно повысились возможности и гибкость работы с текстами. TrueType — это технология контурных шрифтов, которая была разработана Apple Computer Inc. и Microsoft Corporation. Эта технология поддерживается многими производителями шрифтов. Отдельные символы шрифтов TrueType определяются контурами, состоящими из прямых линий и кривых. Таким образом, Windows может масштабировать символы, изменяя определяющие контуры координаты. При этом контуры глифов остаются плавными и при увеличении размеров символов. Шрифты TrueType могут быть использованы как для вывода на экран, так и для вывода на принтер, делая возможным режим отображения текста WYSIWYG (What-You-See-Is-What-You-Get).
Когда программе необходимо использовать шрифт TrueType определенного размера, Windows формирует растровое представление этого шрифта. Этот процесс называется растеризацией шрифта. Алгоритмы растеризации учитывают не только координаты точек соединения прямых и кривых каждого символа, не и некоторые дополнительные данные, содержащиеся в описании шрифта, чтобы скомпенсировать ошибки округления, которые могли бы привести к искажению формы символа. В результате достигается хорошее качество изображения глифов символов независимо от коэффициента масштабирования.
Любой шрифт, с которым имеет дело Windows, характеризуется несколькими
параметрами:
Гарнитура (typeface) — это совокупность нескольких начертаний шрифта, объединенных стилевыми и другими признаками. Самыми известными гарнитурами являются Arial, Times New Roman, Courier New.
Размер шрифта — это высота прямоугольника, в котором помещаются все символы шрифта.
Начертание — это специфические характеристики шрифта. В Windows доступны нормальное (normal) начертание, курсивное (italic), полужирное (bold), с подчеркиванием символа (underline), с перечеркиванием символа (strike out). Кроме того, эти виды начертаний могут комбинироваться в любом сочетании.
Фиксированная или переменная ширина символов. Шрифты первой группы называют моноширинными. В них все символы имеют одинаковую ширину. Шрифты второй группы называют пропорциональными. В них символ «i» занимает гораздо меньше места, чем символ «т». Пропорциональные шрифты более удобны для чтения и поэтому чаще используются в текстовых документах.
Глиф (glyph) — это графическая форма отдельного символа при его изображении на бумаге или экране дисплея. Различные гарнитуры шрифтов различаются прежде всего глифами символов.
В приведенном примере шрифты Arial и Times New Roman являются пропорциональными, а шрифт Courier New — моноширинным. Можно также отметить, что глифы шрифтов Times New Roman и Courier New имеют так называемые засечки, а глифы шрифта Arial таких засечек не имеют.
Работа с разными кодировками, особенно многобайтными, доставляет программисту немало сложностей, например, в случае преобразования символов из одной кодировки в другую. Для решения подобных проблем был предложен стандарт Unicode. В Консорциум Unicode, осуществляющий сопровождение данного стандарта, входят Apple, Hewlett-Packard, IBM, Microsoft, Sun и другие компании. В этом стандарте каждый символ кодируется двумя байтами, что обеспечивает возможность выражения до 65 536 символов. Стандарт Unicode позволяет представить большую часть символов практически всех языков мира.
Символы в стандарте Unicode группируются в логические зоны. Например, в первой зоне содержатся символы с кодами от 0x0000 до 0x007F, и младшие байты этих кодов повторяют таблицу ASCII. Самая большая зона содержит 29 902 иероглифов, используемых в Китае, Японии и Корее.
Windows поддерживает работу с символами как в традиционной ANSI-кодировке, так и в кодировке Unicode. Почти все функции Win32 API, получающие в качестве аргумента адрес строки, имеют ANSI- и Unicode-версии.
При соблюдении небольшого количества правил вы можете написать программу так, что она будет компилироваться как в ANSI-версии, так и в Unicode-версии.
Если в начале файла имеется директива #define UNICODE, то компилятор создает Unicode-версию, если такой директивы нет — ANSI-версию. Разумеется, в многофайловом проекте эта директива должна одновременно присутствовать или отсутствовать во всех файлах проекта.
Вот эти правила:
Для определения символов и строк вместо типа char используйте тип TCHAR, вместо типа char используйте тип LPTSTR, вместо типа const char — тип LPCTSTR.
Для определения строковых констант используйте макрос TEXT, то есть вместо нотации "abed" употребляйте нотацию TEXT("abcd").
В случае использования функций из С-библиотеки, работающих со строками, предусмотрите вызов нужной версии функции. Для этого нужно добавить в начале файла, но после директивы #define UNICODE, директивы условной компиляции, подобные следующим инструкциям:
#ifdef UNICODE
fdefine sprintf swprintf
fdefine sscanf swscanf
fdefine strcpy wesepy
fdefine strcat wescat
fdefine strlen wcslen fendif
Представление символов в компьютерах базируется на кодовых таблицах, в которых каждому отображаемому на экране символу соответствует некоторый целочисленный код. Кодовую таблицу называют также набором символов (character set). Одним из первых стандартов кодовых таблиц был стандарт представления символов ASCII1. В наборе символов ASCII каждому символу сопоставлен 7-битный двоичный код, поэтому общее количество символов равно 27 = = 128 символов.
Номера строк и столбцов даны в шестнадцатеричной нотации. Шестнадцатеричный код символа образуется в результате сцепления номера строки и номера столбца. Например, код буквы N равен 0х4Е, что соответствует двоичному коду 01001110 или десятичному коду 78.
Первые 32 символа в таблице (коды 0x00 — OxlF) соответствуют неотобража-емым управляющим кодам. К ним относятся «возврат каретки» (код OxOD)2, «перевод строки» (код ОхОА) и другие неотображаемые символы3. Затем следуют пробел (код 0x20), синтаксические и служебные знаки, знаки математических операций, цифры и буквы английского алфавита в верхнем и нижнем регистрах. Последний символ (код 0x7F) используется также как управляющий код.
Позже появились различные расширения таблицы ASCII с использованием 8-битной кодировки, позволяющей отображать 256 символов. Во всех расширениях первые 128 позиций повторяют стандарт ASCII.
Наиболее распространенной реализацией такой кодировки является расширенный набор символов IBM, предложенный производителями IBM PC в начале 80-х годов. В старшей половине кодовой таблицы эта кодировка содержит псевдографические символы, символы греческого алфавита и некоторые математические символы. Набор символов IBM растиражирован в миллионах микросхем ПЗУ, которые установлены в видеоадаптерах, принтерах и микросхемах BIOS. Для множества программ, работающих в текстовом режиме и написанных не для Microsoft Windows, используется эта кодировка, поскольку в них для вывода информации на экран используются символы псевдографики, имеющие коды от ОхВО до OxDF.
Известно несколько вариантов кодирования набора символов IBM, которые называются кодовыми страницами {code pages). Вариант, используемый в США и большинстве европейских стран, называется СР437 (code page 437). В России получила наибольшее распространение так называемая альтернативная кодировка ГОСТа. Она известна также под именем СР866 и отличается от СР437 тем, что некоторые символы во второй половине таблицы заменены на кириллицу, а псевдографические символы остались на своих местах.
С появлением операционной системы Microsoft Windows возникла необходимость разработки нового расширения таблицы ASCII, так как текстовый режим MS-DOS, а вместе с ним и символы псевдографики стали уже ненужной архаикой. Так появился набор символов ANSP, который, фактически, стал международным стандартом ISO2.