+void Text::find_lines()
+{
+ lines.clear();
+ float font_size = (style ? style->get_font_size() : 1);
+ string::size_type start = 0;
+ while(1)
+ {
+ string::size_type newline = text.find('\n', start);
+
+ Line line;
+ line.start = start;
+ line.length = (newline==string::npos ? text.size() : newline)-start;
+ line.width = line.length;
+ if(style)
+ {
+ string str = text.substr(line.start, line.length);
+ line.width = static_cast<unsigned>(style->get_font().get_string_width(str)*font_size);
+ }
+ lines.push_back(line);
+
+ if(newline==string::npos)
+ break;
+ start = newline+1;
+ }
+}
+
+template<typename T>
+void Text::process_lines(const Part &part, const Geometry &parent, unsigned first_row, void (Text::*func)(unsigned, const Geometry &, T &) const, T &data) const
+{
+ if(!style)
+ return;
+
+ const GL::Font &font = style->get_font();
+ float font_size = style->get_font_size();
+ unsigned line_height = static_cast<unsigned>((font.get_ascent()-font.get_descent())*font_size);
+ unsigned line_spacing = static_cast<unsigned>(font_size*6/5);
+ unsigned height = line_height+(lines.size()-1)*line_spacing;
+ int y_offset = static_cast<int>(-font.get_descent()*font_size);
+
+ const Sides &margin = part.get_margin();
+ unsigned fit_height = parent.h-margin.top-margin.bottom+line_spacing-line_height;
+ unsigned n_lines = min<unsigned>(lines.size(), max(fit_height/line_spacing, 1U));
+ first_row = min<unsigned>(first_row, lines.size()-n_lines);
+
+ for(unsigned i=0; i<n_lines; ++i)
+ {
+ const Line &line = lines[first_row+i];
+
+ Geometry rgeom;
+ rgeom.w = line.width;
+ rgeom.h = height;
+ rgeom.y = (n_lines-1-i)*line_spacing+y_offset;
+ part.get_alignment().apply(rgeom, parent, part.get_margin());
+
+ (this->*func)(first_row+i, rgeom, data);
+ }
+}
+
+void Text::build_line(unsigned i, const Geometry &rgeom, RenderData &data) const
+{
+ const Line &line = lines[i];
+
+ GL::MatrixStack::Push _pushm(data.bld->matrix());
+ data.bld->matrix() *= GL::Matrix::translation(rgeom.x, rgeom.y, 0);
+ data.bld->matrix() *= GL::Matrix::scaling(style->get_font_size());
+
+ style->get_font().build_string(text.substr(line.start, line.length), *data.bld);
+}
+
+void Text::coords_to_geom_line(unsigned i, const Geometry &rgeom, CoordsToGeomData &data) const
+{
+ if(i==data.row)
+ {
+ float w = style->get_font().get_string_width(text.substr(lines[i].start, data.col));
+ data.result = rgeom;
+ data.result.x += static_cast<unsigned>(w*style->get_font_size());
+ }
+}
+