]> git.tdb.fi Git - libs/gltk.git/blob - source/text.cpp
Make the Text class interface more obvious by not using a reference to pointer
[libs/gltk.git] / source / text.cpp
1 #include <msp/gl/immediate.h>
2 #include <msp/gl/matrix.h>
3 #include "style.h"
4 #include "text.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GLtk {
10
11 Text::Text():
12         style(0)
13 { }
14
15 Text::Text(const Style &s, const string &t):
16         style(&s)
17 {
18         set(t);
19 }
20
21 void Text::set_style(const Style *s)
22 {
23         style = s;
24
25         float font_size=style->get_font()->get_default_size();
26         for(vector<Line>::iterator i=lines.begin(); i!=lines.end(); ++i)
27                 i->width=static_cast<unsigned>(style->get_font()->get_string_width(text.substr(i->start, i->length))*font_size);
28 }
29
30 unsigned Text::get_width() const
31 {
32         unsigned width=0;
33         for(vector<Line>::const_iterator i=lines.begin(); i!=lines.end(); ++i)
34                 width=max(width, i->width);
35         return width;
36 }
37
38 unsigned Text::get_height() const
39 {
40         const GL::Font *font=style->get_font();
41         float font_size=font->get_default_size();
42         unsigned line_height=static_cast<unsigned>((font->get_ascent()-font->get_descent())*font_size);
43         unsigned line_spacing=line_height*6/5;
44         return line_height+(lines.size()-1)*line_spacing;
45 }
46
47 void Text::set(const string &t)
48 {
49         text=t;
50         find_lines();
51 }
52
53 void Text::erase(unsigned pos, unsigned len)
54 {
55         text.erase(pos, len);
56
57         vector<Line>::iterator i;
58         for(i=lines.begin(); (i!=lines.end() && i->start+i->length<pos); ++i) ;
59
60         if(pos+len>i->start+i->length)
61                 find_lines();
62         else
63         {
64                 i->length-=len;
65
66                 for(++i; i!=lines.end(); ++i)
67                         i->start-=len;
68         }
69 }
70
71 void Text::insert(unsigned pos, const string &s)
72 {
73         text.insert(pos, s);
74
75         if(s.find('\n')!=string::npos)
76                 find_lines();
77         else
78         {
79                 vector<Line>::iterator i;
80                 for(i=lines.begin(); (i!=lines.end() && i->start+i->length<pos); ++i) ;
81
82                 i->length+=s.size();
83
84                 for(++i; i!=lines.end(); ++i)
85                         i->start+=s.size();
86         }
87 }
88
89 void Text::render(const Part &part, const Geometry &geom) const
90 {
91         if(lines.empty())
92                 return;
93
94         const GL::Font *font=style->get_font();
95         float font_size=font->get_default_size();
96         unsigned line_height=static_cast<unsigned>((font->get_ascent()-font->get_descent())*font_size);
97         unsigned line_spacing=font_size*6/5;
98         unsigned height=line_height+(lines.size()-1)*line_spacing;
99         int y_offset=static_cast<int>(-font->get_descent()*font_size);
100
101         const GL::Color &color=style->get_font_color();
102         GL::Immediate imm((GL::COLOR4_UBYTE, GL::TEXCOORD2, GL::VERTEX2));
103         imm.color(color.r, color.g, color.b);
104         for(unsigned i=0; i<lines.size(); ++i)
105         {
106                 const Line &line=lines[i];
107
108                 Geometry rgeom;
109                 rgeom.w=line.width;
110                 rgeom.h=height;
111                 rgeom.y=(lines.size()-1-i)*line_spacing+y_offset;
112                 part.get_alignment().apply(rgeom, geom, part.get_margin());
113
114                 GL::push_matrix();
115                 GL::translate(rgeom.x, rgeom.y, 0);
116                 GL::scale_uniform(font_size);
117
118                 font->draw_string(text.substr(line.start, line.length), imm);
119
120                 GL::pop_matrix();
121         }
122 }
123
124 Text &Text::operator=(const string &t)
125 {
126         set(t);
127         return *this;
128 }
129
130 void Text::find_lines()
131 {
132         lines.clear();
133         float font_size=style->get_font()->get_default_size();
134         string::size_type start=0;
135         while(1)
136         {
137                 string::size_type newline=text.find('\n', start);
138
139                 Line line;
140                 line.start=start;
141                 line.length=(newline==string::npos ? text.size() : newline)-start;
142                 line.width=static_cast<unsigned>(style->get_font()->get_string_width(text.substr(line.start, line.length))*font_size);
143                 lines.push_back(line);
144
145                 if(newline==string::npos)
146                         break;
147                 start=newline+1;
148         }
149 }
150
151 } // namespace GLtk
152 } // namespace Msp