]> git.tdb.fi Git - libs/gl.git/blob - source/font.cpp
Reorder Font members
[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 <msp/datafile/collection.h>
9 #include "bindable.h"
10 #include "gl.h"
11 #include "font.h"
12 #include "immediate.h"
13 #include "primitivetype.h"
14 #include "texture2d.h"
15
16 using namespace std;
17
18 namespace Msp {
19 namespace GL {
20
21 Font::Font():
22         tex(0),
23         own_tex(false),
24         default_size(1),
25         ascent(1),
26         descent(0)
27 { }
28
29 Font::~Font()
30 {
31         if(own_tex)
32                 delete tex;
33 }
34
35 void Font::set_texture(const Texture2D &t)
36 {
37         if(own_tex)
38                 delete tex;
39
40         tex = &t;
41         own_tex = false;
42 }
43
44 const Texture2D &Font::get_texture() const
45 {
46         if(!tex)
47                 throw InvalidState("No texture");
48         return *tex;
49 }
50
51 void Font::add_glyph(unsigned code, float x1, float y1, float x2, float y2, float w, float h, float ox, float oy, float adv)
52 {
53         Glyph glyph;
54         glyph.code = code;
55         glyph.x1 = x1;
56         glyph.y1 = y1;
57         glyph.x2 = x2;
58         glyph.y2 = y2;
59         glyph.w = w;
60         glyph.h = h;
61         glyph.off_x = ox;
62         glyph.off_y = oy;
63         glyph.advance = adv;
64         glyphs.insert(GlyphMap::value_type(code, glyph));
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, Codecs::Decoder &dec) const
78 {
79         Immediate imm((TEXCOORD2, VERTEX2));
80         draw_string(str, dec, imm);
81 }
82
83 void Font::draw_string(const string &str, Codecs::Decoder &dec, PrimitiveBuilder &pbuilder) const
84 {
85         if(!tex)
86                 throw InvalidState("No texture");
87
88         Bind bind_tex(tex, true);
89
90         float x = 0;
91         unsigned count = 0;
92
93         pbuilder.begin(QUADS);
94         for(string::const_iterator i=str.begin(); i!=str.end();)
95         {
96                 GlyphMap::const_iterator j = glyphs.find(dec.decode_char(str, i));
97                 if(j==glyphs.end())
98                         continue;
99
100                 create_glyph_vertices(j->second, pbuilder, x);
101                 x += j->second.advance;
102                 count += 4;
103         }
104         pbuilder.end();
105 }
106
107 void Font::create_glyph_vertices(const Glyph &glyph, VertexBuilder &vbuilder, float x) const
108 {
109         vbuilder.texcoord(glyph.x1, glyph.y1);
110         vbuilder.vertex(x+glyph.off_x, glyph.off_y);
111         vbuilder.texcoord(glyph.x2, glyph.y1);
112         vbuilder.vertex(x+glyph.off_x+glyph.w, glyph.off_y);
113         vbuilder.texcoord(glyph.x2, glyph.y2);
114         vbuilder.vertex(x+glyph.off_x+glyph.w, glyph.off_y+glyph.h);
115         vbuilder.texcoord(glyph.x1, glyph.y2);
116         vbuilder.vertex(x+glyph.off_x, glyph.off_y+glyph.h);
117 }
118
119 float Font::get_glyph_advance(unsigned code) const
120 {
121         GlyphMap::const_iterator i = glyphs.find(code);
122         if(i==glyphs.end())
123                 return 0;
124
125         return i->second.advance;
126 }
127
128
129 Font::Loader::Loader(Font &f):
130         DataFile::CollectionObjectLoader<Font>(f, 0)
131 {
132         init();
133 }
134
135 Font::Loader::Loader(Font &f, Collection &c):
136         DataFile::CollectionObjectLoader<Font>(f, &c)
137 {
138         init();
139 }
140
141 void Font::Loader::init()
142 {
143         add("default_size",   &Font::default_size);
144         add("ascent",         &Font::ascent);
145         add("descent",        &Font::descent);
146         add("texture",        &Font::tex);
147         add("texture_inline", &Loader::texture_inline);
148         add("glyph",          &Loader::glyph);
149 }
150
151 void Font::Loader::glyph(unsigned c)
152 {
153         Glyph gl;
154         gl.code = c;
155         load_sub(gl);
156         obj.glyphs.insert(GlyphMap::value_type(c, gl));
157 }
158
159 void Font::Loader::texture_inline()
160 {
161         RefPtr<Texture2D> tex = new Texture2D;
162         load_sub(*tex);
163         obj.tex = tex.release();
164         obj.own_tex = true;
165 }
166
167
168 Font::Glyph::Loader::Loader(Glyph &g):
169         DataFile::ObjectLoader<Glyph>(g)
170 {
171         add("texcoords", &Loader::texcoords);
172         add("size",      &Glyph::w,     &Glyph::h);
173         add("offset",    &Glyph::off_x, &Glyph::off_y);
174         add("advance",   &Glyph::advance);
175 }
176
177 void Font::Glyph::Loader::texcoords(float x1, float y1, float x2, float y2)
178 {
179         obj.x1 = x1;
180         obj.y1 = y1;
181         obj.x2 = x2;
182         obj.y2 = y2;
183 }
184
185 } // namespace GL
186 } // namespace Msp