Визуализация текстовых символов
Формирование образа символа на разных платформах, к сожалению, осуществляется по разному. Воспользуемся функциями библиотеки GLUT. GLUT поддерживает оба способа визуализации символов: растровый и векторный.
В векторном или штриховом способе формирования образа шрифтов каждый из символов представляется в виде набора отрезков линий. Символы сформированные таким образом легко масштабируются и вращаются. Для
создания векторного образа символа используется функция
void glutStrokeCharacter(void *font, int character);
Первый аргумент определяет тип шрифта (например, GLUT_STROKE_ROMAN), а второй ASCII код символа (от 32 до 128). Интересно, что после отображения символа начало координат оказывается в нижнем правом углу
описанного прямоугольника, что обеспечивает отображение следующего символа рядом.
В растровом способе образ символа формируется в небольшом двумерном массиве, который будет визуализироваться с помощью функции glBitmap. Растровые символы не могут масштабироваться и вращаться, но зато
быстрее формируются и отображаются. Для создания растрового образа символа используется функция с аналогичным прототипом
void glutBitmapCharacter(void *font, int character);
Набор растровых шрифтов гораздо больше (GLUT_BITMAP_9_BY_15, GLUT_BITMAP_TIMES_ROMAN_10, GLUT_BITMAP_HELVETICA_12). Формировать каждый символ заново нерационально. Ппоэтому, независимо от способа представления
символов используются дисплейные списки. Для каждого символа формируется дисплейный список. При необходимости отобразить символ вызывается список с соответствующим номером. Инкапсулируем этот процесс
в классе.
// Класс для формирования дисплейного списка символов и отображения их на экране
class GLUTFont
{
private:
// Базовое значение списка
int m_base;
public:
// Формирование списка
Create(void* font);
// Отображение строки
void Write(double x, double y, const char* str);
// Преобразование значения и отображение строки
void Write(double x, double y, double data);
};
// Формирование списка
GLUTFont::Create(void* font)
{
// Удалить старые списки
glDeleteLists(m_base, 256);
// Получить номер первого списка
m_base = glGenLists(256);
for(int i=0; i<256; i++)
{
// Создать список для одного символа
glNewList(m_base+i, GL_COMPILE);
glutBitmapCharacter(font,i);
glEndList();
}
}
// Отображение строки
void GLUTFont::Write(double x, double y, const char* str)
{
// Сохраняет текущее состояние
glPushAttrib(GL_LIST_BIT);
// Установка положения вывода растра символа
glRasterPos2d(x, y);
//Восстанавливается базовый номер начала элементов списка картинок текстовых символов
glListBase(m_base);
//Отображает заданное количество символов заданного размера из заданного массива
glCallLists(strlen(str), GL_UNSIGNED_BYTE, str);
//Восстановление текущего атрибута
glPopAttrib();
}
// Преобразование значения и отображение строки
void GLUTFont::Write(double x, double y, double data)
{
// Преобразование в string
std::stringstream sstr;
sstr<<data;
// Вывод текста
Write(x, y, sstr.str().c_str());
}
GLUTFont fnt;
Инициализацию списка можно осуществить заранее, например в функции main или специальной функции Init:
void Init(void)
{
fnt.Create(GLUT_BITMAP_HELVETICA_12);
}
void Draw(void)
{
//Рисование горизонтальной оси
...
fnt.Write(47.,-5.,"X,mm");
//Рисование вертикальной оси
...
fnt.Write(5., 47.,"Y,mm");
}
|