[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); |
---|
[2841] | 84 | |
---|
[580] | 85 | glMatrixMode(GL_PROJECTION); |
---|
| 86 | glPushMatrix(); |
---|
[2953] | 87 | glLoadIdentity(); |
---|
[2841] | 88 | |
---|
[580] | 89 | gluOrtho2D(0.0f, _screenWidth, _screenHeight, 0.0f); |
---|
[2841] | 90 | |
---|
[580] | 91 | glMatrixMode(GL_MODELVIEW); |
---|
[2953] | 92 | glPushMatrix(); |
---|
| 93 | glLoadIdentity(); |
---|
[580] | 94 | |
---|
| 95 | glEnable(GL_BLEND); |
---|
| 96 | glDisable(GL_DEPTH_TEST); |
---|
| 97 | } |
---|
| 98 | |
---|
[953] | 99 | void |
---|
[3463] | 100 | Fonts::end() |
---|
[580] | 101 | { |
---|
[835] | 102 | glBindTexture(GL_TEXTURE_2D, 0); |
---|
[580] | 103 | |
---|
[835] | 104 | glMatrixMode(GL_PROJECTION); |
---|
[2953] | 105 | glPopMatrix(); |
---|
[580] | 106 | |
---|
| 107 | glMatrixMode(GL_MODELVIEW); |
---|
[2953] | 108 | glPopMatrix(); |
---|
[580] | 109 | |
---|
[2953] | 110 | glPopAttrib(); |
---|
[580] | 111 | } |
---|
| 112 | |
---|
[953] | 113 | void |
---|
[3463] | 114 | Fonts::initializeFont(FontAttributes& attr) |
---|
[580] | 115 | { |
---|
[835] | 116 | attr._displayLists = glGenLists(256); |
---|
[580] | 117 | |
---|
[2841] | 118 | int index; |
---|
[835] | 119 | for (index = 0; index < 256; ++index) { |
---|
[3463] | 120 | FontAttributes::CharInfo& charInfo = attr._chars[index]; |
---|
[953] | 121 | glNewList(attr._displayLists + index, GL_COMPILE); |
---|
| 122 | if (charInfo._valid) { |
---|
| 123 | glBegin(GL_TRIANGLE_STRIP); |
---|
| 124 | |
---|
[1115] | 125 | glTexCoord2f(charInfo._left, charInfo._top); |
---|
[1113] | 126 | glVertex2i(0, 0); |
---|
[953] | 127 | |
---|
| 128 | glTexCoord2f(charInfo._left, charInfo._bottom); |
---|
[1115] | 129 | glVertex2i(0, (GLint)attr._fontHeight); |
---|
[953] | 130 | |
---|
| 131 | glTexCoord2f(charInfo._right, charInfo._top); |
---|
[1115] | 132 | glVertex2i((GLint)charInfo._width, 0); |
---|
[953] | 133 | |
---|
| 134 | glTexCoord2f(charInfo._right, charInfo._bottom); |
---|
[1115] | 135 | glVertex2i((GLint)charInfo._width, (GLint)attr._fontHeight); |
---|
[953] | 136 | |
---|
[1115] | 137 | glEnd(); |
---|
[580] | 138 | glTranslatef(charInfo._width, 0.0f, 0.0f); |
---|
[953] | 139 | } |
---|
| 140 | glEndList(); |
---|
[835] | 141 | } |
---|
[580] | 142 | } |
---|
| 143 | |
---|
[2841] | 144 | bool |
---|
[3463] | 145 | Fonts::loadFont(const char *fontName, const char *fontFileName, |
---|
| 146 | FontAttributes& sFont) |
---|
[580] | 147 | { |
---|
[2841] | 148 | bool bSuccess = false; |
---|
[1111] | 149 | |
---|
[3463] | 150 | std::string path = FilePath::getInstance()->getPath(fontFileName); |
---|
[2972] | 151 | if (path.empty()) { |
---|
[2841] | 152 | return false; |
---|
[1111] | 153 | } |
---|
[2972] | 154 | std::ifstream fsInput(path.c_str(), std::ios::binary); |
---|
[835] | 155 | if (fsInput) { |
---|
[2972] | 156 | sFont._fontName = fontName; |
---|
[1111] | 157 | |
---|
[580] | 158 | // make sure this file is the correct type by checking the header |
---|
| 159 | unsigned int uiFileId = 0; |
---|
| 160 | fsInput.read(reinterpret_cast<char*>(&uiFileId), sizeof(unsigned int)); |
---|
[929] | 161 | if (uiFileId == (unsigned int)c_nFileMagicHeader) { |
---|
[580] | 162 | // read general font/texture dimensions |
---|
[835] | 163 | fsInput.read(reinterpret_cast<char*>(&sFont._textureWidth), |
---|
[953] | 164 | sizeof(unsigned int)); |
---|
[835] | 165 | fsInput.read(reinterpret_cast<char*>(&sFont._textureHeight), |
---|
[953] | 166 | sizeof(unsigned int)); |
---|
[835] | 167 | fsInput.read(reinterpret_cast<char*>(&sFont._fontHeight), |
---|
[953] | 168 | sizeof(unsigned int)); |
---|
[580] | 169 | |
---|
[2877] | 170 | // read dimensions for each character in 256-char ASCII chart |
---|
[835] | 171 | for (int i = 0; i < 256; ++i) { |
---|
[580] | 172 | unsigned int uiSize = 0; |
---|
| 173 | |
---|
| 174 | // top |
---|
[835] | 175 | fsInput.read(reinterpret_cast<char*>(&uiSize), |
---|
[953] | 176 | sizeof(unsigned int)); |
---|
[580] | 177 | sFont._chars[i]._top = static_cast<float>(uiSize) / sFont._textureHeight; |
---|
| 178 | // left |
---|
| 179 | fsInput.read(reinterpret_cast<char*>(&uiSize), sizeof(unsigned int)); |
---|
| 180 | sFont._chars[i]._left = static_cast<float>(uiSize) / sFont._textureWidth; |
---|
| 181 | // bottom |
---|
| 182 | fsInput.read(reinterpret_cast<char*>(&uiSize), sizeof(unsigned int)); |
---|
| 183 | sFont._chars[i]._bottom = static_cast<float>(uiSize) / sFont._textureHeight; |
---|
| 184 | // right |
---|
| 185 | fsInput.read(reinterpret_cast<char*>(&uiSize), sizeof(unsigned int)); |
---|
| 186 | sFont._chars[i]._right = static_cast<float>(uiSize) / sFont._textureWidth; |
---|
| 187 | // enabled |
---|
| 188 | fsInput.read(reinterpret_cast<char*>(&uiSize), sizeof(unsigned int)); |
---|
| 189 | sFont._chars[i]._valid = (uiSize != 0); |
---|
| 190 | // width factor |
---|
| 191 | float fWidthFactor = 1.0f; |
---|
| 192 | fsInput.read(reinterpret_cast<char*>(&fWidthFactor), sizeof(float)); |
---|
| 193 | sFont._chars[i]._width = fWidthFactor * sFont._fontHeight; |
---|
| 194 | } |
---|
| 195 | } |
---|
| 196 | |
---|
| 197 | // allocate and read the texture map |
---|
[835] | 198 | if (!fsInput.eof() && !fsInput.fail()) { |
---|
[580] | 199 | unsigned int uiArea = sFont._textureWidth * sFont._textureHeight; |
---|
[2841] | 200 | unsigned char *pRawMap = new unsigned char[uiArea]; |
---|
| 201 | fsInput.read(reinterpret_cast<char *>(pRawMap), uiArea); |
---|
[580] | 202 | |
---|
[835] | 203 | // we've only read the luminance values, but we need a luminance + |
---|
| 204 | // alpha buffer, so we make a new buffer and duplicate the |
---|
| 205 | // luminance values |
---|
[2841] | 206 | unsigned char *pTexMap = new unsigned char[2 * uiArea]; |
---|
| 207 | unsigned char *pMap = pTexMap; |
---|
[835] | 208 | for (unsigned int i = 0; i < uiArea; ++i) { |
---|
[580] | 209 | *pMap++ = pRawMap[i]; |
---|
| 210 | *pMap++ = pRawMap[i]; |
---|
| 211 | } |
---|
| 212 | delete[] pRawMap; |
---|
| 213 | pRawMap = NULL; |
---|
| 214 | |
---|
| 215 | // make texture map out of new buffer |
---|
| 216 | glGenTextures(1, &sFont._fontTextureID); |
---|
| 217 | glBindTexture(GL_TEXTURE_2D, sFont._fontTextureID); |
---|
[835] | 218 | glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, |
---|
[953] | 219 | sFont._textureWidth, sFont._textureHeight, 0, |
---|
| 220 | GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pTexMap); |
---|
[580] | 221 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
---|
| 222 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
---|
| 223 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); |
---|
| 224 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); |
---|
| 225 | glBindTexture(GL_TEXTURE_2D, 0); |
---|
| 226 | |
---|
| 227 | delete[] pTexMap; |
---|
| 228 | pTexMap = NULL; |
---|
| 229 | |
---|
| 230 | bSuccess = true; |
---|
| 231 | } |
---|
| 232 | |
---|
[2953] | 233 | fsInput.close(); |
---|
[580] | 234 | } |
---|
| 235 | return bSuccess; |
---|
| 236 | } |
---|
| 237 | |
---|
[835] | 238 | void |
---|
[3463] | 239 | Fonts::resize(int width, int height) |
---|
[580] | 240 | { |
---|
[835] | 241 | _screenWidth = width; |
---|
| 242 | _screenHeight = height; |
---|
| 243 | } |
---|
| 244 | |
---|