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