]> git.tdb.fi Git - libs/gl.git/blob - source/font.cpp
Add Id tags and copyright notices to files
[libs/gl.git] / source / font.cpp
1 /* $Id$
2
3 This file is part of libmspgl
4 Copyright © 2007  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <GL/gl.h>
9 #include "font.h"
10 #include "texture2d.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace GL {
16
17 Font::Font():
18         tex(0),
19         own_tex(false),
20         default_size(1),
21         ascent(1),
22         descent(0),
23         varray((TEXCOORD2, VERTEX2))
24 { }
25
26 Font::~Font()
27 {
28         if(own_tex)
29                 delete tex;
30 }
31
32 void Font::set_texture(const Texture2D &t)
33 {
34         tex=&t;
35 }
36
37 void Font::add_glyph(unsigned code, float x1, float y1, float x2, float y2, float w, float h, float ox, float oy, float adv)
38 {
39         Glyph glyph;
40         glyph.code=code;
41         glyph.x1=x1;
42         glyph.y1=y1;
43         glyph.x2=x2;
44         glyph.y2=y2;
45         glyph.w=w;
46         glyph.h=h;
47         glyph.off_x=ox;
48         glyph.off_y=oy;
49         glyph.advance=adv;
50         glyph.index=glyphs.size();
51         glyphs.insert(GlyphMap::value_type(code, glyph));
52
53         RefPtr<VertexArrayBuilder> va_builder=varray.modify();
54         create_glyph_vertices(glyph, *va_builder);
55 }
56
57 float Font::get_string_width(const string &str) const
58 {
59         float x=0;
60
61         for(string::const_iterator i=str.begin(); i!=str.end(); ++i)
62                 x+=get_glyph_advance(static_cast<unsigned char>(*i));
63
64         return x;
65 }
66
67 float Font::get_string_width(const string &str, Codecs::Decoder &dec) const
68 {
69         float x=0;
70
71         for(string::const_iterator i=str.begin(); i!=str.end();)
72                 x+=get_glyph_advance(dec.decode_char(str, i));
73
74         return x;
75 }
76
77 void Font::draw_string(const string &str) const
78 {
79         prepare_render();
80
81         for(string::const_iterator i=str.begin(); i!=str.end(); ++i)
82                 draw_glyph(static_cast<unsigned char>(*i));
83
84         glPopMatrix();
85 }
86
87 void Font::draw_string(const string &str, Codecs::Decoder &dec) const
88 {
89         prepare_render();
90
91         for(string::const_iterator i=str.begin(); i!=str.end();)
92                 draw_glyph(dec.decode_char(str, i));
93
94         glPopMatrix();
95 }
96
97 void Font::create_glyph_vertices()
98 {
99         varray.clear();
100         RefPtr<VertexArrayBuilder> va_builder=varray.modify();
101
102         unsigned n=0;
103         for(GlyphMap::iterator i=glyphs.begin(); i!=glyphs.end(); ++i, ++n)
104         {
105                 i->second.index=n;
106                 create_glyph_vertices(i->second, *va_builder);
107         }
108 }
109
110 void Font::create_glyph_vertices(const Glyph &glyph, VertexArrayBuilder &va_builder)
111 {
112         va_builder.texcoord(glyph.x1, glyph.y1);
113         va_builder.vertex(glyph.off_x, glyph.off_y);
114         va_builder.texcoord(glyph.x2, glyph.y1);
115         va_builder.vertex(glyph.off_x+glyph.w, glyph.off_y);
116         va_builder.texcoord(glyph.x2, glyph.y2);
117         va_builder.vertex(glyph.off_x+glyph.w, glyph.off_y+glyph.h);
118         va_builder.texcoord(glyph.x1, glyph.y2);
119         va_builder.vertex(glyph.off_x, glyph.off_y+glyph.h);
120 }
121
122 void Font::prepare_render() const
123 {
124         tex->bind();
125         varray.apply();
126         glPushMatrix();
127 }
128
129 void Font::draw_glyph(unsigned code) const
130 {
131         GlyphMap::const_iterator i=glyphs.find(code);
132         if(i==glyphs.end())
133                 return;
134
135         glDrawArrays(GL_QUADS, i->second.index*4, 4);
136
137         glTranslatef(i->second.advance, 0, 0);
138 }
139
140 float Font::get_glyph_advance(unsigned code) const
141 {
142         GlyphMap::const_iterator i=glyphs.find(code);
143         if(i==glyphs.end())
144                 return 0;
145
146         return i->second.advance;
147 }
148
149
150 Font::Loader::Loader(Font &f):
151         font(f)
152 {
153         add("default_size", &Font::default_size);
154         add("ascent",  &Font::ascent);
155         add("descent", &Font::descent);
156         add("texture", &Loader::texture);
157         add("glyph",   &Loader::glyph);
158 }
159
160 Font::Loader::~Loader()
161 {
162         font.create_glyph_vertices();
163 }
164
165 void Font::Loader::texture(const string &t)
166 {
167         Texture2D *tex=new Texture2D;
168         tex->parameter(GL_GENERATE_MIPMAP, 1);
169         font.tex=tex;
170         tex->image(t);
171         font.own_tex=true;
172 }
173
174 void Font::Loader::glyph(unsigned c)
175 {
176         Glyph gl;
177         gl.code=c;
178         load_sub(gl);
179         font.glyphs.insert(GlyphMap::value_type(c, gl));
180 }
181
182
183 Font::Glyph::Loader::Loader(Glyph &g):
184         glyph(g)
185 {
186         add("texcoords", &Loader::texcoords);
187         add("size",      &Glyph::w,     &Glyph::h);
188         add("offset",    &Glyph::off_x, &Glyph::off_y);
189         add("advance",   &Glyph::advance);
190 }
191
192 void Font::Glyph::Loader::texcoords(float x1, float y1, float x2, float y2)
193 {
194         glyph.x1=x1;
195         glyph.y1=y1;
196         glyph.x2=x2;
197         glyph.y2=y2;
198 }
199
200 } // namespace GL
201 } // namespace Msp