source: trunk/packages/vizservers/nanovis/util/Fonts.cpp @ 4167

Last change on this file since 4167 was 4167, checked in by ldelgass, 7 years ago

Texture environment is not part of texture object stored state, so don't set
environment mode before loading textures, should be done at render time.

  • Property svn:eol-style set to native
File size: 7.3 KB
Line 
1/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2/*
3 *  Copyright (c) 2004-2013  HUBzero Foundation, LLC
4 */
5
6#include <stdarg.h>
7#include <string.h>
8
9#include <fstream>
10
11#include <GL/glew.h>
12
13#include "Fonts.h"
14#include "FilePath.h"
15
16using namespace nv::util;
17
18// constants
19const int c_nFileMagicHeader = 6666;
20
21Fonts::Fonts() :
22    _fontIndex(-1),
23    _screenWidth(512),
24    _screenHeight(512)
25{
26}
27
28Fonts::~Fonts()
29{
30    for (unsigned index = 0; index < _fonts.size(); ++index) {
31        glDeleteLists(_fonts[index]._displayLists, 256);
32        glDeleteTextures(1, &(_fonts[_fontIndex]. _fontTextureID));
33    }
34}
35
36void
37Fonts::setFont(const char *fontName)
38{
39    if (fontName != NULL) {
40        unsigned int i;
41        for (i = 0; i < _fonts.size(); ++i) {
42            if (strcmp(_fonts[i]._fontName.c_str(), fontName) == 0) {
43                _fontIndex = i;
44                break;
45            }
46        }
47    }
48}
49
50void
51Fonts::addFont(const char *fontName, const char *fontFileName)
52{
53    FontAttributes sFont;
54   
55    loadFont(fontName, fontFileName, sFont);
56    initializeFont(sFont);
57    _fonts.push_back(sFont);
58}
59
60void
61Fonts::draw(const char *pString, ...) const
62{
63    va_list vlArgs;
64    char szVargsBuffer[1024];
65
66    va_start(vlArgs, pString);
67    vsprintf(szVargsBuffer, pString, vlArgs);
68
69    if (_fontIndex != -1) {
70        int length = strlen(szVargsBuffer);
71
72        glListBase(_fonts[_fontIndex]._displayLists);
73        glCallLists(length, GL_UNSIGNED_BYTE,
74                    reinterpret_cast<const GLvoid*>(szVargsBuffer));
75    }
76}
77
78void
79Fonts::begin()
80{
81    glPushAttrib(GL_TRANSFORM_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT);
82    glEnable(GL_TEXTURE_2D);
83    glBindTexture(GL_TEXTURE_2D, _fonts[_fontIndex]._fontTextureID);
84    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
85
86    glMatrixMode(GL_PROJECTION);
87    glPushMatrix();
88    glLoadIdentity();
89
90    gluOrtho2D(0.0f, _screenWidth, _screenHeight, 0.0f);
91
92    glMatrixMode(GL_MODELVIEW);
93    glPushMatrix();
94    glLoadIdentity();
95
96    glEnable(GL_BLEND);
97    glDisable(GL_DEPTH_TEST);
98}
99
100void
101Fonts::end()
102{
103    glBindTexture(GL_TEXTURE_2D, 0);
104
105    glMatrixMode(GL_PROJECTION);
106    glPopMatrix();
107
108    glMatrixMode(GL_MODELVIEW);
109    glPopMatrix();
110
111    glPopAttrib();
112}
113
114void
115Fonts::initializeFont(FontAttributes& attr)
116{
117    attr._displayLists = glGenLists(256);
118
119    int index;
120    for (index = 0; index < 256; ++index) {
121        FontAttributes::CharInfo& charInfo = attr._chars[index];
122        glNewList(attr._displayLists + index, GL_COMPILE);
123        if (charInfo._valid) {
124            glBegin(GL_TRIANGLE_STRIP);
125           
126            glTexCoord2f(charInfo._left, charInfo._top);
127            glVertex2i(0, 0);
128           
129            glTexCoord2f(charInfo._left, charInfo._bottom);
130            glVertex2i(0, (GLint)attr._fontHeight);
131           
132            glTexCoord2f(charInfo._right, charInfo._top);
133            glVertex2i((GLint)charInfo._width, 0);
134           
135            glTexCoord2f(charInfo._right,  charInfo._bottom);
136            glVertex2i((GLint)charInfo._width, (GLint)attr._fontHeight);
137           
138            glEnd();
139            glTranslatef(charInfo._width, 0.0f, 0.0f);
140        }
141        glEndList();
142    }
143}
144
145bool
146Fonts::loadFont(const char *fontName, const char *fontFileName,
147                FontAttributes& sFont)
148{
149    bool bSuccess = false;
150
151    std::string path = FilePath::getInstance()->getPath(fontFileName);
152    if (path.empty()) {
153        return false;
154    }
155    std::ifstream fsInput(path.c_str(), std::ios::binary);
156    if (fsInput) {
157        sFont._fontName = fontName;
158
159        // make sure this file is the correct type by checking the header
160        unsigned int uiFileId = 0;
161        fsInput.read(reinterpret_cast<char*>(&uiFileId), sizeof(unsigned int));
162        if (uiFileId == (unsigned int)c_nFileMagicHeader) {
163            // read general font/texture dimensions
164            fsInput.read(reinterpret_cast<char*>(&sFont._textureWidth),
165                         sizeof(unsigned int));
166            fsInput.read(reinterpret_cast<char*>(&sFont._textureHeight),
167                         sizeof(unsigned int));
168            fsInput.read(reinterpret_cast<char*>(&sFont._fontHeight),
169                         sizeof(unsigned int));
170
171            // read dimensions for each character in 256-char ASCII chart
172            for (int i = 0; i < 256; ++i) {
173                unsigned int uiSize = 0;
174
175                // top
176                fsInput.read(reinterpret_cast<char*>(&uiSize),
177                             sizeof(unsigned int));
178                sFont._chars[i]._top = static_cast<float>(uiSize) / sFont._textureHeight;
179                // left
180                fsInput.read(reinterpret_cast<char*>(&uiSize), sizeof(unsigned int));
181                sFont._chars[i]._left = static_cast<float>(uiSize) / sFont._textureWidth;
182                // bottom
183                fsInput.read(reinterpret_cast<char*>(&uiSize), sizeof(unsigned int));
184                sFont._chars[i]._bottom = static_cast<float>(uiSize) / sFont._textureHeight;
185                // right
186                fsInput.read(reinterpret_cast<char*>(&uiSize), sizeof(unsigned int));
187                sFont._chars[i]._right = static_cast<float>(uiSize) / sFont._textureWidth;
188                // enabled
189                fsInput.read(reinterpret_cast<char*>(&uiSize), sizeof(unsigned int));
190                sFont._chars[i]._valid = (uiSize != 0);
191                // width factor
192                float fWidthFactor = 1.0f;
193                fsInput.read(reinterpret_cast<char*>(&fWidthFactor), sizeof(float));
194                sFont._chars[i]._width = fWidthFactor * sFont._fontHeight;
195            }
196        }
197
198        // allocate and read the texture map
199        if (!fsInput.eof() && !fsInput.fail()) {
200            unsigned int uiArea = sFont._textureWidth * sFont._textureHeight;
201            unsigned char *pRawMap = new unsigned char[uiArea];
202            fsInput.read(reinterpret_cast<char *>(pRawMap), uiArea);
203
204            // we've only read the luminance values, but we need a luminance +
205            // alpha buffer, so we make a new buffer and duplicate the
206            // luminance values
207            unsigned char *pTexMap = new unsigned char[2 * uiArea];
208            unsigned char *pMap = pTexMap;
209            for (unsigned int i = 0; i < uiArea; ++i) {
210                *pMap++ = pRawMap[i];
211                *pMap++ = pRawMap[i];
212            }
213            delete[] pRawMap;
214            pRawMap = NULL;
215
216            // make texture map out of new buffer
217            glGenTextures(1, &sFont._fontTextureID);
218            glBindTexture(GL_TEXTURE_2D, sFont._fontTextureID);
219            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
220            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
221            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
222            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
223            glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA,
224                         sFont._textureWidth, sFont._textureHeight, 0,
225                         GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pTexMap);
226            glBindTexture(GL_TEXTURE_2D, 0);
227
228            delete[] pTexMap;
229            pTexMap = NULL;
230
231            bSuccess = true;
232        }
233
234        fsInput.close();
235    }
236    return bSuccess;
237}
238
239void
240Fonts::resize(int width, int height)
241{
242    _screenWidth = width;
243    _screenHeight = height;
244}
245
Note: See TracBrowser for help on using the repository browser.