]> git.tdb.fi Git - libs/gl.git/blob - source/render/text.cpp
cb7f998e9bb2a38d4102024fc4648e8461b38f0c
[libs/gl.git] / source / render / text.cpp
1 #include "meshbuilder.h"
2 #include "program.h"
3 #include "renderer.h"
4 #include "technique.h"
5 #include "text.h"
6 #include "texture2d.h"
7
8 using namespace std;
9
10 namespace Msp {
11 namespace GL {
12
13 Text::Text(const Font &f, const Technique *tech, Tag tex_slot):
14         ObjectInstance(object),
15         font(f),
16         mesh((TEXCOORD2, VERTEX2)),
17         horz_align(0.0f),
18         vert_offset(0.0f),
19         width(0.0f)
20 {
21         object.set_mesh(&mesh);
22         if(tech)
23                 set_technique(tech, tex_slot);
24 }
25
26 void Text::set_technique(const Technique *tech, Tag tex_slot)
27 {
28         if(tech)
29         {
30                 if(!tex_slot.id && tech->has_method(Tag()))
31                         if(const Program *shprog = tech->get_method(Tag()).get_shader_program())
32                         {
33                                 if(shprog->get_uniform_location(Tag("font_tex"))>=0)
34                                         tex_slot = "font_tex";
35                                 else if(shprog->get_uniform_location(Tag("color_tex"))>=0)
36                                         tex_slot = "color_tex";
37                                 else if(shprog->get_uniform_location(Tag("diffuse_map"))>=0)
38                                         tex_slot = "diffuse_map";
39                                 else if(shprog->get_uniform_location(Tag("base_color_map"))>=0)
40                                         tex_slot = "base_color_map";
41                         }
42
43                 object.set_technique(tech);
44                 texture_slot = tex_slot;
45         }
46         else
47         {
48                 object.set_technique(0);
49                 texture_slot = Tag();
50         }
51 }
52
53 void Text::set_text(const string &text, StringCodec::Decoder &dec)
54 {
55         clear();
56         width = font.get_string_width(text, dec);
57         MeshBuilder bld(mesh);
58         bld.transform(Matrix::translation(Vector3(-horz_align*width, vert_offset, 0.0f)));
59         font.build_string(text, dec, bld);
60 }
61
62 void Text::clear()
63 {
64         mesh.clear();
65         width = 0;
66 }
67
68 void Text::set_alignment(HorizontalAlign ha, VerticalAlign va)
69 {
70         float h;
71         switch(ha)
72         {
73         case LEFT: h = 0.0f; break;
74         case CENTER: h = 0.5f; break;
75         case RIGHT: h = 1.0f; break;
76         default: throw invalid_argument("Text::set_alignment");
77         }
78
79         float v;
80         switch(va)
81         {
82         case DESCENT: v = -font.get_descent(); break;
83         case BASELINE: v = 0.0f; break;
84         case MIDLINE: v = font.get_cap_height()/2; break;
85         case ASCENT: v = font.get_ascent(); break;
86         default: throw invalid_argument("Text::set_alignment");
87         }
88
89         set_alignment(h, v);
90 }
91
92 void Text::set_alignment(float h, float v)
93 {
94         if(h==horz_align && -v==vert_offset)
95                 return;
96
97         float horz_adjust = (horz_align-h)*width;
98         float vert_adjust = -v-vert_offset;
99         horz_align = h;
100         vert_offset = -v;
101
102         unsigned pos_offset = mesh.get_vertices().get_format().offset(VERTEX2);
103         unsigned n_vertices = mesh.get_n_vertices();
104         for(unsigned i=0; i<n_vertices; ++i)
105         {
106                 float *pos = reinterpret_cast<float *>(mesh.modify_vertex(i)+pos_offset);
107                 pos[0] += horz_adjust;
108                 pos[1] += vert_adjust;
109         }
110 }
111
112 void Text::setup_render(Renderer &renderer, Tag tag) const
113 {
114         ObjectInstance::setup_render(renderer, tag);
115         renderer.set_texture(texture_slot, &font.get_texture());
116 }
117
118 } // namespace GL
119 } // namespace Msp