вернуться в оглавление предыдущая глава предыдущий параграф следующий параграф следующая глава


Визуализация текстовых символов


Формирование образа символа на разных платформах, к сожалению, осуществляется по разному. Воспользуемся функциями библиотеки 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");

}