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