]> git.tdb.fi Git - libs/gl.git/blob - source/font.cpp
Remove an XXX because I no longer remember how to reproduce the issue
[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         cap_height(1),
20         x_height(0.5)
21 { }
22
23 // Avoid synthesizing ~RefPtr in files including font.h
24 Font::~Font()
25 { }
26
27 void Font::set_texture(const Texture2D &t)
28 {
29         texture = &t;
30         texture.keep();
31 }
32
33 const Texture2D &Font::get_texture() const
34 {
35         if(!texture)
36                 throw logic_error("No texture");
37         return *texture;
38 }
39
40 void Font::add_glyph(const Glyph &g)
41 {
42         insert_unique(glyphs, g.code, g);
43 }
44
45 void Font::set_kerning(unsigned l, unsigned r, float d)
46 {
47         kerning[KerningKey(l, r)] = d;
48 }
49
50 float Font::get_string_width(const string &str, StringCodec::Decoder &dec) const
51 {
52         float x = 0;
53
54         unsigned prev = 0;
55         for(string::const_iterator i=str.begin(); i!=str.end();)
56         {
57                 unsigned c = dec.decode_char(str, i);
58                 if(prev)
59                         x += get_glyph_advance(prev, c);
60                 prev = c;
61         }
62         x += get_glyph_advance(prev);
63
64         return x;
65 }
66
67 void Font::draw_string(const string &str, StringCodec::Decoder &dec, const Color &color) const
68 {
69         BindRestore bind_tex(get_texture());
70         Immediate imm((TEXCOORD2, COLOR4_UBYTE, VERTEX2));
71         imm.color(color);
72         build_string(str, dec, imm);
73 }
74
75 void Font::build_string(const string &str, StringCodec::Decoder &dec, PrimitiveBuilder &bld) const
76 {
77         MatrixStack::Push push_mtx(bld.matrix());
78
79         unsigned prev = 0;
80         for(string::const_iterator i=str.begin(); i!=str.end();)
81         {
82                 unsigned c = dec.decode_char(str, i);
83                 GlyphMap::const_iterator j = glyphs.find(c);
84                 if(j==glyphs.end())
85                         continue;
86
87                 if(prev)
88                         bld.matrix() *= Matrix::translation(get_glyph_advance(prev, c), 0, 0);
89
90                 create_glyph_quad(j->second, bld);
91                 prev = c;
92         }
93 }
94
95 void Font::create_glyph_quad(const Glyph &glyph, PrimitiveBuilder &bld) const
96 {
97         bld.begin(TRIANGLE_STRIP);
98         bld.texcoord(glyph.x1, glyph.y2);
99         bld.vertex(glyph.off_x, glyph.off_y+glyph.h);
100         bld.texcoord(glyph.x1, glyph.y1);
101         bld.vertex(glyph.off_x, glyph.off_y);
102         bld.texcoord(glyph.x2, glyph.y2);
103         bld.vertex(glyph.off_x+glyph.w, glyph.off_y+glyph.h);
104         bld.texcoord(glyph.x2, glyph.y1);
105         bld.vertex(glyph.off_x+glyph.w, glyph.off_y);
106         bld.end();
107 }
108
109 float Font::get_glyph_advance(unsigned code, unsigned next) const
110 {
111         GlyphMap::const_iterator i = glyphs.find(code);
112         if(i==glyphs.end())
113                 return 0;
114
115         float advance = i->second.advance;
116
117         if(next)
118         {
119                 KerningMap::const_iterator j = kerning.find(KerningKey(code, next));
120                 if(j!=kerning.end())
121                         advance += j->second;
122         }
123
124         return advance;
125 }
126
127
128 Font::Loader::Loader(Font &f):
129         DataFile::CollectionObjectLoader<Font>(f, 0)
130 {
131         init();
132 }
133
134 Font::Loader::Loader(Font &f, Collection &c):
135         DataFile::CollectionObjectLoader<Font>(f, &c)
136 {
137         init();
138 }
139
140 void Font::Loader::init()
141 {
142         add("native_size", &Font::native_size);
143         add("ascent",      &Font::ascent);
144         add("cap_height",  &Font::cap_height);
145         add("descent",     &Font::descent);
146         add("texture",     &Loader::texture);
147         add("texture",     &Loader::texture_ref);
148         add("glyph",       &Loader::glyph);
149         add("kerning",     &Loader::kerning);
150         add("x_height",    &Font::x_height);
151 }
152
153 void Font::Loader::glyph(unsigned c)
154 {
155         Glyph gl;
156         gl.code = c;
157         load_sub(gl);
158         obj.glyphs.insert(GlyphMap::value_type(c, gl));
159 }
160
161 void Font::Loader::kerning(unsigned l, unsigned r, float d)
162 {
163         obj.kerning[KerningKey(l, r)] = d;
164 }
165
166 void Font::Loader::texture()
167 {
168         RefPtr<Texture2D> tex = new Texture2D;
169         load_sub(*tex);
170         obj.texture = tex;
171 }
172
173 void Font::Loader::texture_ref(const string &name)
174 {
175         obj.texture = &get_collection().get<Texture2D>(name);
176         obj.texture.keep();
177 }
178
179
180 Font::Glyph::Loader::Loader(Glyph &g):
181         DataFile::ObjectLoader<Glyph>(g)
182 {
183         add("texcoords", &Loader::texcoords);
184         add("size",      &Glyph::w,     &Glyph::h);
185         add("offset",    &Glyph::off_x, &Glyph::off_y);
186         add("advance",   &Glyph::advance);
187 }
188
189 void Font::Glyph::Loader::texcoords(float x1_, float y1_, float x2_, float y2_)
190 {
191         obj.x1 = x1_;
192         obj.y1 = y1_;
193         obj.x2 = x2_;
194         obj.y2 = y2_;
195 }
196
197 } // namespace GL
198 } // namespace Msp