1// SuperTux
2// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17#include "supertux/info_box_line.hpp"
18
19#include "supertux/textscroller_screen.hpp"
20#include "supertux/resources.hpp"
21#include "supertux/colorscheme.hpp"
22#include "video/drawing_context.hpp"
23#include "video/font.hpp"
24#include "video/surface.hpp"
25
26static const float ITEMS_SPACE = 4;
27
28namespace {
29
30FontPtr get_font_by_format_char(char format_char) {
31 switch (format_char)
32 {
33 case ' ':
34 return Resources::small_font;
35 case '-':
36 return Resources::big_font;
37 case '\t':
38 case '*':
39 case '#':
40 case '!':
41 return Resources::normal_font;
42 default:
43 return Resources::normal_font;
44 //log_warning << "Unknown format_char: '" << format_char << "'" << std::endl;
45 }
46}
47
48Color get_color_by_format_char(char format_char) {
49 switch (format_char)
50 {
51 case ' ':
52 return ColorScheme::Text::small_color;
53 case '-':
54 return ColorScheme::Text::heading_color;
55 case '*':
56 return ColorScheme::Text::reference_color;
57 case '\t':
58 case '#':
59 case '!':
60 return ColorScheme::Text::normal_color;
61 default:
62 return ColorScheme::Text::normal_color;
63 //log_warning << "Unknown format_char: '" << format_char << "'" << std::endl;
64 }
65}
66
67InfoBoxLine::LineType get_linetype_by_format_char(char format_char) {
68 switch (format_char)
69 {
70 case ' ':
71 return InfoBoxLine::SMALL;
72
73 case '\t':
74 return InfoBoxLine::NORMAL;
75 case '-':
76 return InfoBoxLine::HEADING;
77 case '*':
78 return InfoBoxLine::REFERENCE;
79 case '#':
80 return InfoBoxLine::NORMAL_LEFT;
81 case '!':
82 return InfoBoxLine::IMAGE;
83 default:
84 return InfoBoxLine::SMALL;
85 //log_warning << "Unknown format_char: '" << format_char << "'" << std::endl;
86 }
87}
88
89} // namespace
90
91InfoBoxLine::InfoBoxLine(char format_char, const std::string& text_) :
92 lineType(get_linetype_by_format_char(format_char)),
93 font(get_font_by_format_char(format_char)),
94 color(get_color_by_format_char(format_char)),
95 text(text_),
96 image()
97{
98 if (lineType == IMAGE)
99 {
100 image = Surface::from_file(text);
101 }
102}
103
104std::vector<std::unique_ptr<InfoBoxLine> >
105InfoBoxLine::split(const std::string& text, float width)
106{
107 std::vector<std::unique_ptr<InfoBoxLine> > lines;
108
109 std::string::size_type i = 0;
110 std::string::size_type l;
111 char format_char = '#';
112 while (i < text.size()) {
113 // take care of empty lines - represent them as blank lines of normal text
114 if (text[i] == '\n') {
115 lines.emplace_back(new InfoBoxLine('\t', ""));
116 i++;
117 continue;
118 }
119
120 // extract the format_char
121 if (is_valid_format_char(text[i]))
122 {
123 format_char = text[i];
124 i++;
125 }
126 else
127 {
128 format_char = '#';
129 }
130 if (i >= text.size()) break;
131
132 // extract one line
133 l = text.find('\n', i);
134 if (l == std::string::npos) l=text.size();
135 std::string s = text.substr(i, l-i);
136 i = l+1;
137
138 // if we are dealing with an image, just store the line
139 if (format_char == '!') {
140 lines.emplace_back(new InfoBoxLine(format_char, s));
141 continue;
142 }
143
144 // append wrapped parts of line into list
145 std::string overflow;
146 do {
147 FontPtr font = get_font_by_format_char(format_char);
148 std::string s2 = s;
149 if (font) s2 = font->wrap_to_width(s2, width, &overflow);
150 lines.emplace_back(new InfoBoxLine(format_char, s2));
151 s = overflow;
152 } while (s.length() > 0);
153 }
154
155 return lines;
156}
157
158void
159InfoBoxLine::draw(DrawingContext& context, const Rectf& bbox, int layer)
160{
161 Vector position = bbox.p1();
162 switch (lineType) {
163 case IMAGE:
164 context.color().draw_surface(image, Vector( (bbox.get_left() + bbox.get_right() - static_cast<float>(image->get_width())) / 2.0f, position.y), layer);
165 break;
166 case NORMAL_LEFT:
167 context.color().draw_text(font, text, Vector(position.x, position.y), ALIGN_LEFT, layer, color);
168 break;
169 default:
170 context.color().draw_text(font, text, Vector((bbox.get_left() + bbox.get_right()) / 2, position.y), ALIGN_CENTER, layer, color);
171 break;
172 }
173}
174
175float
176InfoBoxLine::get_height() const
177{
178 switch (lineType) {
179 case IMAGE:
180 return static_cast<float>(image->get_height()) + ITEMS_SPACE;
181 case NORMAL_LEFT:
182 return font->get_height() + ITEMS_SPACE;
183 default:
184 return font->get_height() + ITEMS_SPACE;
185 }
186}
187
188/* EOF */
189