--- /dev/null
+#include "meshbuilder.h"
+#include "text.h"
+#include "texture2d.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+Text::Text(const Font &f, const Technique *tech):
+ font(f),
+ mesh((TEXCOORD2, VERTEX2)),
+ horz_align(0.0f),
+ vert_offset(0.0f),
+ width(0.0f)
+{
+ object.set_mesh(&mesh);
+ if(tech)
+ set_technique(tech);
+}
+
+void Text::set_technique(const Technique *tech)
+{
+ if(tech)
+ {
+ technique = *tech;
+ technique.replace_texture("diffuse_map", font.get_texture());
+ object.set_technique(&technique);
+ }
+ else
+ object.set_technique(0);
+}
+
+void Text::set_text(const string &text, StringCodec::Decoder &dec)
+{
+ clear();
+ width = font.get_string_width(text, dec);
+ MeshBuilder bld(mesh);
+ bld.transform(Matrix::translation(Vector3(-horz_align*width, vert_offset, 0.0f)));
+ font.build_string(text, dec, bld);
+}
+
+void Text::clear()
+{
+ mesh.clear();
+ width = 0;
+}
+
+void Text::set_alignment(HorizontalAlign ha, VerticalAlign va)
+{
+ float h;
+ switch(ha)
+ {
+ case LEFT: h = 0.0f; break;
+ case CENTER: h = 0.5f; break;
+ case RIGHT: h = 1.0f; break;
+ default: throw invalid_argument("Text::set_alignment");
+ }
+
+ float v;
+ switch(va)
+ {
+ case DESCENT: v = -font.get_descent(); break;
+ case BASELINE: v = 0.0f; break;
+ case MIDLINE: v = font.get_cap_height()/2; break;
+ case ASCENT: v = font.get_ascent(); break;
+ default: throw invalid_argument("Text::set_alignment");
+ }
+
+ set_alignment(h, v);
+}
+
+void Text::set_alignment(float h, float v)
+{
+ if(h==horz_align && -v==vert_offset)
+ return;
+
+ float horz_adjust = (horz_align-h)*width;
+ float vert_adjust = -v-vert_offset;
+ horz_align = h;
+ vert_offset = -v;
+
+ unsigned pos_offset = mesh.get_vertices().get_format().offset(VERTEX2);
+ unsigned n_vertices = mesh.get_n_vertices();
+ for(unsigned i=0; i<n_vertices; ++i)
+ {
+ float *pos = mesh.modify_vertex(i)+pos_offset;
+ pos[0] += horz_adjust;
+ pos[1] += vert_adjust;
+ }
+}
+
+void Text::render(Renderer &renderer, const Tag &tag) const
+{
+ object.render(renderer, tag);
+}
+
+} // namespace GL
+} // namespace Msp