xoreos  0.0.5
texturefont.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
25 #include <vector>
26 
27 #include "src/common/types.h"
28 #include "src/common/error.h"
29 #include "src/common/ustring.h"
30 #include "src/common/util.h"
31 #include "src/common/encoding.h"
32 
33 #include "src/aurora/language.h"
34 
36 
40 
42 
44 
45 namespace Graphics {
46 
47 namespace Aurora {
48 
50  if ((encoding == Common::kEncodingInvalid) || (encoding == Common::kEncodingASCII))
51  return (uint32) c;
52 
53  byte data[2] = { c, 0x00 };
54 
55  const Common::UString str = Common::readString(data, 2, encoding);
56  if (str.empty())
57  return 0;
58 
59  return *str.begin();
60 }
61 
62 
63 // TODO: Multibyte fonts?
64 TextureFont::TextureFont(const Common::UString &name) : _height(1.0f), _spaceR(0.0f), _spaceB(0.0f) {
65  _texture = TextureMan.get(name);
66 
67  load();
68 
69  _mesh = static_cast<Mesh::MeshFont *>(MeshMan.getMesh("defaultMeshFont"));
70  _material = new Shader::ShaderMaterial(ShaderMan.getShaderObject("default/text.frag", Shader::SHADER_FRAGMENT), "text");
71  Shader::ShaderSampler *sampler;
72  sampler = (Shader::ShaderSampler *)(_material->getVariableData("sampler_0_id"));
73  sampler->handle = _texture;
74  _renderable = new Shader::ShaderRenderable(SurfaceMan.getSurface("textSurface"), _material, _mesh);
75 }
76 
78  delete _renderable;
79  delete _material;
80 }
81 
82 float TextureFont::getWidth(uint32 c) const {
83  std::map<uint32, Char>::const_iterator cC = _chars.find(c);
84 
85  if (cC == _chars.end())
86  cC = _chars.find('m');
87  if (cC == _chars.end())
88  return _spaceR;
89 
90  return cC->second.width + _spaceR;
91 }
92 
93 float TextureFont::getHeight() const {
94  return _height;
95 }
96 
98  return _spaceB;
99 }
100 
102  TextureMan.set();
103 
104  float width = getWidth('m') - _spaceR;
105 
106  glBegin(GL_QUADS);
107  glVertex2f(0.0f , 0.0f);
108  glVertex2f(width, 0.0f);
109  glVertex2f(width, _height);
110  glVertex2f(0.0f , _height);
111  glEnd();
112 
113  glTranslatef(width + _spaceR, 0.0f, 0.0f);
114 }
115 
116 void TextureFont::draw(uint32 c) const {
117  std::map<uint32, Char>::const_iterator cC = _chars.find(c);
118 
119  if (cC == _chars.end()) {
120  drawMissing();
121  return;
122  }
123 
124  TextureMan.set(_texture);
125 
126  glBegin(GL_QUADS);
127  for (int i = 0; i < 4; i++) {
128  glTexCoord2f(cC->second.tX[i], cC->second.tY[i]);
129  glVertex2f (cC->second.vX[i], cC->second.vY[i]);
130  }
131  glEnd();
132 
133  glTranslatef(cC->second.width + _spaceR, 0.0f, 0.0f);
134 }
135 
136 void TextureFont::renderBind(const glm::mat4 &transform) const {
137  glUseProgram(_renderable->getProgram()->glid);
142  _mesh->renderBind();
143 
150  glBindBuffer(GL_ARRAY_BUFFER, _mesh->getVertexBuffer()->getVBO());
151 }
152 
153 void TextureFont::render(uint32 c, float &x, float &y, float *rgba) const {
154  std::map<uint32, Char>::const_iterator cC = _chars.find(c);
155 
156  if (cC == _chars.end()) {
157  //drawMissing();
158  return;
159  }
160 
161  float v_pos[12];
162  float v_uv[8];
163  float v_rgba[4*4];
164 
165  for (int i = 0; i < 4; ++i) {
166  v_uv[i*2] = cC->second.tX[i];
167  v_uv[i*2 +1] = cC->second.tY[i];
168  v_pos[i*3] = x + cC->second.vX[i];
169  v_pos[i*3 +1] = y + cC->second.vY[i];
170  v_pos[i*3 +2] = 0.0f;
171  v_rgba[i*4] = rgba[0];
172  v_rgba[i*4 +1] = rgba[1];
173  v_rgba[i*4 +2] = rgba[2];
174  v_rgba[i*4 +3] = rgba[3];
175  }
176  _mesh->render(v_pos, v_uv, v_rgba);
177  x += cC->second.width + _spaceR;
178 }
179 
181  _mesh->renderUnbind();
182 
185  glUseProgram(0);
186 }
187 
189  const Texture &texture = _texture.getTexture();
190  const TXI::Features &txiFeatures = texture.getTXI().getFeatures();
191 
192  // Number of characters
193  uint32 charCount = txiFeatures.numChars;
194  if (charCount == 0)
195  throw Common::Exception("Texture defines no characters");
196 
197  if ((charCount > 256) || (txiFeatures.fileRange > 1) || (txiFeatures.isDoubleByte))
198  throw Common::Exception("TODO: Multibyte texture font");
199 
200  // Character coordinates
201  const std::vector<TXI::Coords> &uls = txiFeatures.upperLeftCoords;
202  const std::vector<TXI::Coords> &lrs = txiFeatures.lowerRightCoords;
203  if ((uls.size() < charCount) || (lrs.size() < charCount))
204  throw Common::Exception("Texture defines not enough character coordinates");
205 
206  if ((texture.getWidth() == 0) || (texture.getHeight() == 0))
207  throw Common::Exception("Invalid texture dimensions (%dx%d)", texture.getWidth(), texture.getHeight());
208 
209  double textureRatio = ((double) texture.getWidth()) / ((double) texture.getHeight());
210 
211  // Get features
212  _height = txiFeatures.fontHeight * 100.0f;
213  _spaceR = txiFeatures.spacingR * 100.0f;
214  _spaceB = txiFeatures.spacingB * 100.0f;
215 
216  const Common::Encoding encoding = LangMan.getCurrentEncoding();
217 
218  // Build the character texture and vertex coordinates
219  for (uint32 i = 0; i < charCount; i++) {
220  if ((encoding != Common::kEncodingInvalid) && !Common::isValidCodepoint(encoding, i))
221  continue;
222 
223  std::pair<std::map<uint32, Char>::iterator,bool> result;
224 
225  result = _chars.insert(std::make_pair(convertToUTF32((byte) i, encoding), Char()));
226  if (!result.second)
227  continue;
228 
229  TXI::Coords ul = uls[i];
230  TXI::Coords lr = lrs[i];
231  Char &c = result.first->second;
232 
233  // Texture coordinates, directly out of the TXI
234  c.tX[0] = ul.x; c.tY[0] = lr.y;
235  c.tX[1] = lr.x; c.tY[1] = lr.y;
236  c.tX[2] = lr.x; c.tY[2] = ul.y;
237  c.tX[3] = ul.x; c.tY[3] = ul.y;
238 
239  double height = ABS(lr.y - ul.y);
240  double width = ABS(lr.x - ul.x);
241  double ratio = ((height != 0.0f) ? (width / height) : 0.0f) * textureRatio;
242 
243  // Vertex coordinates. Fixed height, width to fit the texture ratio
244  c.vX[0] = 0.00f; c.vY[0] = 0.00f;
245  c.vX[1] = _height * ratio; c.vY[1] = 0.00f;
246  c.vX[2] = _height * ratio; c.vY[2] = _height;
247  c.vX[3] = 0.00f; c.vY[3] = _height;
248 
249  c.width = c.vX[1] - c.vX[0];
250  }
251 }
252 
253 } // End of namespace Aurora
254 
255 } // End of namespace Graphics
void render(float *pos, float *uv, float *rgba)
Dynamic data prior to render call.
Definition: meshfont.cpp:96
T ABS(T x)
Definition: util.h:69
const TXI & getTXI() const
Return the TXI.
Definition: texture.cpp:96
A class holding an UTF-8 string.
Definition: ustring.h:48
#define TextureMan
Shortcut for accessing the texture manager.
Definition: textureman.h:127
VertexBuffer * getVertexBuffer()
Definition: mesh.cpp:39
#define SurfaceMan
Shortcut for accessing the shader manager.
Definition: surfaceman.h:74
void * getVariableData(uint32 index) const
std::vector< Coords > upperLeftCoords
Definition: txi.h:117
The Aurora texture manager.
static uint32 convertToUTF32(byte c, Common::Encoding encoding)
Definition: texturefont.cpp:49
virtual void renderUnbind() const
iterator begin() const
Definition: ustring.cpp:253
uint32 getHeight() const
Definition: texture.cpp:80
virtual void render(uint32 c, float &x, float &y, float *rgba) const
Shader::ShaderRenderable * _renderable
Definition: texturefont.h:90
void bindProgram(Shader::ShaderProgram *program)
float getHeight() const
Return the height of a character.
Definition: texturefont.cpp:93
Basic exceptions to throw.
Coordinates.
Definition: txi.h:50
Graphics::Aurora::TextureHandle handle
Definition: shader.h:176
Utility templates and functions.
void renderUnbind()
Definition: mesh.cpp:227
Types and functions related to language.
float getWidth(uint32 c) const
Return the width of a character.
Definition: texturefont.cpp:82
Utility functions for working with differing string encodings.
Encoding
Definition: encoding.h:37
bool empty() const
Is the string empty?
Definition: ustring.cpp:245
The global shader surface manager.
Low-level type definitions to handle fixed width types portably.
The global mesh manager.
Texture information.
StackException Exception
Definition: error.h:59
std::vector< Coords > lowerRightCoords
Definition: txi.h:118
Shader::ShaderMaterial * _material
Definition: texturefont.h:89
void bindProgram(Shader::ShaderProgram *program)
uint32 getWidth() const
Definition: texture.cpp:76
void renderBind()
Follows the steps of renderImmediate, but broken into different functions.
Definition: mesh.cpp:177
Unicode string handling.
#define MeshMan
Shortcut for accessing the shader manager.
Definition: meshman.h:74
Plain, unextended ASCII (7bit clean).
Definition: encoding.h:40
Shader sampler is used to bind a texture to a texture unit.
Definition: shader.h:174
uint32 _height
Definition: h263.cpp:54
#define LangMan
Shortcut for accessing the language manager.
Definition: language.h:275
A texture as used in the Aurora engines.
#define ShaderMan
Shortcut for accessing the shader manager.
Definition: shader.h:293
uint32_t uint32
Definition: types.h:204
Texture features.
Definition: txi.h:55
UString readString(SeekableReadStream &stream, Encoding encoding)
Read a string with the given encoding of a stream.
Definition: encoding.cpp:287
float getLineSpacing() const
Return the size of space between lines.
Definition: texturefont.cpp:97
const Features & getFeatures() const
Definition: txi.cpp:283
A texture font, as used by NWN and KotOR/KotOR2.
bool isValidCodepoint(Encoding encoding, uint32 cp)
Return whether the given codepoint is valid in this encoding.
Definition: encoding.cpp:393
virtual void renderBind(const glm::mat4 &transform) const
Bind the font for rendering.
uint8 byte
Definition: types.h:209
std::map< uint32, Char > _chars
Definition: texturefont.h:82
TextureFont(const Common::UString &name)
Definition: texturefont.cpp:64
void draw(uint32 c) const
Draw this character.