Initial commit, includes Lua with broken Luabind as a backup for branching purposes
[terrastrategy.git] / src / gui / text.cpp
blobb6de4cfbddde3ff5e84fc1949f3aa1d74bd357b1
1 //
2 // Copyright (C) 2008 by Martin Moracek
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 /**
20 * @file text.cpp
22 * blahblah
25 #include <wctype.h>
26 #include <algorithm>
27 #include <vector>
29 #include <string.h>
31 #include "gui/font/font.h"
32 #include "gui/text.h"
34 #include "memory/mmgr.h"
36 namespace tre {
39 * Text class
41 Text::Text() : antialias_(false), bounds_(0.0f),
42 halign_(haLeft), valign_(vaTop), trans_(NULL), abuffers_(NULL)
44 abuffers_ = AttribBufferSet::Factory().CreateInstance();
46 DEBUG_ASSERT(abuffers_);
49 Text::~Text()
51 // clear buffers
52 delete abuffers_;
54 // clear pages
55 for(PageVector::iterator pos = pages_.begin();
56 pos != pages_.end(); ++pos) {
57 delete pos->indices;
58 delete pos->vars;
62 void Text::SetRect(uint width, uint height)
64 bounds_.Set(width, height);
66 RedrawText(false);
69 void Text::SetHAlign(HorizAlign align)
71 halign_ = align;
73 RedrawText(false);
76 void Text::SetVAlign(VertAlign align)
78 valign_ = align;
80 RedrawText(false);
83 void Text::SetFont(const std::string & font)
85 // fonts are shared resources
86 FontPtr fnt = Font::Factory().CreateInstance(font);
87 if(fnt == font_)
88 return;
90 font_ = fnt;
92 RedrawText(true);
95 void Text::SetEffect(const std::string & fx)
97 effect_ = Effect::Factory().CreateInstance(fx);
99 for(GeometryBatch::iterator pos = batch_.begin();
100 pos != batch_.end(); ++pos) {
101 pos->effect = effect_.get();
105 void Text::SetAntialias(bool on)
107 if(antialias_ != on) {
108 antialias_ = on;
109 RedrawText(true);
113 void Text::SetScaleFactor(const Vector2f scale)
115 if(scaleFactor_ != scale) {
116 scaleFactor_ = scale;
117 RedrawText(true);
121 void Text::SetTransform(const Matrix4x4f * trans)
123 trans_ = trans;
125 for(GeometryBatch::iterator pos = batch_.begin();
126 pos != batch_.end(); ++pos) {
127 pos->trans = trans_;
131 void Text::ResetPages(void)
133 uint quads = 0, cur_verts = 0;
134 std::vector<uint*> iptrs(pages_.size(), NULL);
135 float * verts, * cols, * tex;
137 const uint inds[] = {0, 1, 2, 0, 2, 3};
139 // first pass for reinitializing buffers
140 for(uint i = 0; i < pages_.size(); ++i) {
141 if(!pages_[i].prep.empty()) {
142 pages_[i].indices->Init(pages_[i].prep.size()
143 * sizeof(inds) / sizeof(uint));
144 iptrs[i] = pages_[i].indices->Lock();
145 quads += pages_[i].prep.size();
147 DEBUG_ASSERT(iptrs[i]);
148 } else {
149 delete pages_[i].indices;
150 pages_[i].indices = NULL;
151 delete pages_[i].vars;
152 pages_[i].vars = NULL;
155 if(quads) {
156 abuffers_->Init(atPosition, adFloat2, quads * 4);
157 abuffers_->Init(atColour, adFloat4, quads * 4);
158 abuffers_->Init(atTexCoord0, adFloat2, quads * 4);
159 verts = static_cast<float*>(abuffers_->Lock(atPosition));
160 cols = static_cast<float*>(abuffers_->Lock(atColour));
161 tex = static_cast<float*>(abuffers_->Lock(atTexCoord0));
162 DEBUG_ASSERT(verts);
163 DEBUG_ASSERT(cols);
164 DEBUG_ASSERT(tex);
167 // fill the buffers
168 for(uint i = 0, cur_inds = 0; i < pages_.size(); ++i, cur_inds = 0) {
169 pages_[i].indices->vFrom = cur_verts;
170 for(PagePrepQueue::iterator itr = pages_[i].prep.begin();
171 itr != pages_[i].prep.end(); ++itr) {
172 const GlyphInfo * gi = itr->first->glyph;
174 // index buffers
175 std::transform(inds, inds + sizeof(inds) / sizeof(uint),
176 iptrs[i] + cur_inds, std::bind1st(std::plus<uint>(), cur_verts));
177 cur_inds += sizeof(inds) / sizeof(uint);
179 // attrib buffers
180 verts[cur_verts * 2] = itr->second.x + gi->bearing_x;
181 verts[cur_verts * 2 + 1] = itr->second.y - gi->bearing_y
182 + static_cast<int>(gi->height);
183 memcpy(&cols[cur_verts * 4],
184 &itr->first->style->colour.x, sizeof(Vector4f));
185 tex[cur_verts * 2] = gi->texCoords.x;
186 tex[cur_verts * 2 + 1] = gi->texCoords.w;
187 ++cur_verts;
189 verts[cur_verts * 2] = itr->second.x + gi->bearing_x
190 + static_cast<int>(gi->width);
191 verts[cur_verts * 2 + 1] = itr->second.y - gi->bearing_y
192 + static_cast<int>(gi->height);
193 memcpy(&cols[cur_verts * 4],
194 &itr->first->style->colour.x, sizeof(Vector4f));
195 tex[cur_verts * 2] = gi->texCoords.z;
196 tex[cur_verts * 2 + 1] = gi->texCoords.w;
197 ++cur_verts;
199 verts[cur_verts * 2] = itr->second.x + gi->bearing_x
200 + static_cast<int>(gi->width);
201 verts[cur_verts * 2 + 1] = itr->second.y - gi->bearing_y;
202 memcpy(&cols[cur_verts * 4],
203 &itr->first->style->colour.x, sizeof(Vector4f));
204 tex[cur_verts * 2] = gi->texCoords.z;
205 tex[cur_verts * 2 + 1] = gi->texCoords.y;
206 ++cur_verts;
208 verts[cur_verts * 2] = itr->second.x + gi->bearing_x;
209 verts[cur_verts * 2 + 1] = itr->second.y - gi->bearing_y;
210 memcpy(&cols[cur_verts * 4],
211 &itr->first->style->colour.x, sizeof(Vector4f));
212 tex[cur_verts * 2] = gi->texCoords.x;
213 tex[cur_verts * 2 + 1] = gi->texCoords.y;
214 ++cur_verts;
216 pages_[i].indices->vTo = cur_verts;
219 if(quads) {
220 abuffers_->Unlock(atPosition);
221 abuffers_->Unlock(atColour);
222 abuffers_->Unlock(atTexCoord0);
225 // finish and close pages (and clean queues)
226 for(uint i = 0; i < pages_.size(); ++i) {
227 if(pages_[i].indices) {
228 pages_[i].indices->Unlock();
230 // let's assume we're not changing text mesh every frame
231 pages_[i].prep.clear();
232 pages_[i].prep.swap(pages_[i].prep);
236 DEBUG_ASSERT(batch_.size() >= pages_.size());
237 // remove empty pages (and batches)
238 uint i = 0;
239 while(i < pages_.size()) {
240 if(pages_[i].indices) {
241 ++i;
242 } else {
243 pages_.erase(pages_.begin() + i);
244 batch_.erase(batch_.begin() + i);
249 Text::MeshPage & Text::GetPageByTexture(const TexturePtr & texture)
251 DEBUG_ASSERT(batch_.size() == pages_.size());
253 for(PageVector::iterator pos = pages_.begin();
254 pos != pages_.end(); ++pos) {
255 // text materials contain exactly one texture, so we can afford this
256 if(pos->vars->samplers[0].second == texture)
257 return *pos;
259 // else
260 MeshPage page;
261 page.indices = IndexBuffer::Factory().CreateInstance();
262 page.vars = new EffectVars();
263 page.vars->SetTexture("fnt_Texture", texture);
264 pages_.push_back(page);
265 batch_.push_back(GeometryInfo(trans_, abuffers_, page.indices,
266 effect_.get(), page.vars));
268 return pages_.back();