2 // Copyright (C) 2008 by Martin Moracek
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.
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
31 #include "gui/font/font.h"
34 #include "memory/mmgr.h"
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_
);
55 for(PageVector::iterator pos
= pages_
.begin();
56 pos
!= pages_
.end(); ++pos
) {
62 void Text::SetRect(uint width
, uint height
)
64 bounds_
.Set(width
, height
);
69 void Text::SetHAlign(HorizAlign align
)
76 void Text::SetVAlign(VertAlign align
)
83 void Text::SetFont(const std::string
& font
)
85 // fonts are shared resources
86 FontPtr fnt
= Font::Factory().CreateInstance(font
);
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
) {
113 void Text::SetScaleFactor(const Vector2f scale
)
115 if(scaleFactor_
!= scale
) {
116 scaleFactor_
= scale
;
121 void Text::SetTransform(const Matrix4x4f
* trans
)
125 for(GeometryBatch::iterator pos
= batch_
.begin();
126 pos
!= batch_
.end(); ++pos
) {
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
]);
149 delete pages_
[i
].indices
;
150 pages_
[i
].indices
= NULL
;
151 delete pages_
[i
].vars
;
152 pages_
[i
].vars
= NULL
;
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
));
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
;
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
);
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
;
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
;
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
;
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
;
216 pages_
[i
].indices
->vTo
= cur_verts
;
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)
239 while(i
< pages_
.size()) {
240 if(pages_
[i
].indices
) {
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
)
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();