]> git.tdb.fi Git - libs/gl.git/blob - source/font.cpp
Change Font::add_glyph to take a glyph struct
[libs/gl.git] / source / font.cpp
1 #include <msp/core/maputils.h>
2 #include <msp/datafile/collection.h>
3 #include "bindable.h"
4 #include "gl.h"
5 #include "font.h"
6 #include "immediate.h"
7 #include "primitivetype.h"
8 #include "texture2d.h"
9
10 using namespace std;
11
12 namespace Msp {
13 namespace GL {
14
15 Font::Font():
16         native_size(1),
17         ascent(1),
18         descent(0)
19 { }
20
21 void Font::set_texture(const Texture2D &t)
22 {
23         texture = &t;
24         texture.keep();
25 }
26
27 const Texture2D &Font::get_texture() const
28 {
29         if(!texture)
30                 throw logic_error("No texture");
31         return *texture;
32 }
33
34 void Font::add_glyph(const Glyph &g)
35 {
36         insert_unique(glyphs, g.code, g);
37 }
38
39 float Font::get_string_width(const string &str, StringCodec::Decoder &dec) const
40 {
41         float x = 0;
42
43         for(string::const_iterator i=str.begin(); i!=str.end();)
44                 x += get_glyph_advance(dec.decode_char(str, i));
45
46         return x;
47 }
48
49 void Font::draw_string(const string &str, StringCodec::Decoder &dec, const Color &color) const
50 {
51         Bind bind_tex(get_texture(), true);
52         Immediate imm((TEXCOORD2, COLOR4_UBYTE, VERTEX2));
53         imm.color(color);
54         build_string(str, dec, imm);
55 }
56
57 void Font::build_string(const string &str, StringCodec::Decoder &dec, PrimitiveBuilder &bld) const
58 {
59         MatrixStack::Push push_mtx(bld.matrix());
60
61         bld.begin(QUADS);
62         for(string::const_iterator i=str.begin(); i!=str.end();)
63         {
64                 GlyphMap::const_iterator j = glyphs.find(dec.decode_char(str, i));
65                 if(j==glyphs.end())
66                         continue;
67
68                 create_glyph_vertices(j->second, bld);
69                 bld.matrix() *= Matrix::translation(j->second.advance, 0, 0);
70         }
71         bld.end();
72 }
73
74 void Font::create_glyph_vertices(const Glyph &glyph, VertexBuilder &bld) const
75 {
76         bld.texcoord(glyph.x1, glyph.y1);
77         bld.vertex(glyph.off_x, glyph.off_y);
78         bld.texcoord(glyph.x2, glyph.y1);
79         bld.vertex(glyph.off_x+glyph.w, glyph.off_y);
80         bld.texcoord(glyph.x2, glyph.y2);
81         bld.vertex(glyph.off_x+glyph.w, glyph.off_y+glyph.h);
82         bld.texcoord(glyph.x1, glyph.y2);
83         bld.vertex(glyph.off_x, glyph.off_y+glyph.h);
84 }
85
86 float Font::get_glyph_advance(unsigned code) const
87 {
88         GlyphMap::const_iterator i = glyphs.find(code);
89         if(i==glyphs.end())
90                 return 0;
91
92         return i->second.advance;
93 }
94
95
96 Font::Loader::Loader(Font &f):
97         DataFile::CollectionObjectLoader<Font>(f, 0)
98 {
99         init();
100 }
101
102 Font::Loader::Loader(Font &f, Collection &c):
103         DataFile::CollectionObjectLoader<Font>(f, &c)
104 {
105         init();
106 }
107
108 void Font::Loader::init()
109 {
110         add("native_size", &Font::native_size);
111         add("ascent",      &Font::ascent);
112         add("descent",     &Font::descent);
113         add("texture",     &Loader::texture);
114         add("texture",     &Loader::texture_ref);
115         add("glyph",       &Loader::glyph);
116 }
117
118 void Font::Loader::glyph(unsigned c)
119 {
120         Glyph gl;
121         gl.code = c;
122         load_sub(gl);
123         obj.glyphs.insert(GlyphMap::value_type(c, gl));
124 }
125
126 void Font::Loader::texture()
127 {
128         RefPtr<Texture2D> tex = new Texture2D;
129         load_sub(*tex);
130         obj.texture = tex;
131 }
132
133 void Font::Loader::texture_ref(const string &name)
134 {
135         obj.texture = &get_collection().get<Texture2D>(name);
136         obj.texture.keep();
137 }
138
139
140 Font::Glyph::Loader::Loader(Glyph &g):
141         DataFile::ObjectLoader<Glyph>(g)
142 {
143         add("texcoords", &Loader::texcoords);
144         add("size",      &Glyph::w,     &Glyph::h);
145         add("offset",    &Glyph::off_x, &Glyph::off_y);
146         add("advance",   &Glyph::advance);
147 }
148
149 void Font::Glyph::Loader::texcoords(float x1, float y1, float x2, float y2)
150 {
151         obj.x1 = x1;
152         obj.y1 = y1;
153         obj.x2 = x2;
154         obj.y2 = y2;
155 }
156
157 } // namespace GL
158 } // namespace Msp