4 // Copyright (C) 2006 Matthias Braun <matze@braunis.de>
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 #include "lisp/parser.hpp"
27 #include "lisp/lisp.hpp"
30 #include "drawing_context.hpp"
33 Font::Font(const std::string& file, const std::string& shadowfile,
34 int w, int h, int shadowsize)
35 : chars(0), shadow_chars(0), w(w), h(h), shadowsize(shadowsize)
37 chars = new Surface(file);
38 shadow_chars = new Surface(shadowfile);
41 char_count = ((int) chars->get_height() / h) * 16;
51 Font::get_text_width(const std::string& text) const
53 /** Let's calculate the size of the biggest paragraph */
54 std::string::size_type l, hl, ol;
59 l = text.find("\n", l+1);
60 if(l == std::string::npos)
68 for (unsigned int i = 0; i < text.size(); i++)
69 if ((unsigned char) text[i] > 0xC2 && (unsigned char) text[i] < 0xC6)
70 hl--; // control characters are a WASTE.
76 Font::get_text_height(const std::string& text) const
78 /** Let's calculate height of the text */
79 std::string::size_type l, hh;
83 l = text.find("\n", l+1);
84 if(l == std::string::npos)
93 Font::get_height() const
99 Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment,
100 DrawingEffect drawing_effect, float alpha) const
102 /* Cut lines changes into seperate strings, needed to support center/right text
103 alignments with break lines.
104 Feel free to replace this hack with a more elegant solution
107 std::string::size_type l, i, y;
112 l = text.find("\n", i);
113 if(l == std::string::npos) {
118 if(l > sizeof(temp)-1)
121 temp[text.copy(temp, l - i, i)] = '\0';
123 // calculate X positions based on the alignment type
124 Vector pos = Vector(pos_);
125 if(alignment == CENTER_ALLIGN)
126 pos.x -= get_text_width(temp) / 2;
127 else if(alignment == RIGHT_ALLIGN)
128 pos.x -= get_text_width(temp);
130 draw_text(temp, pos + Vector(0,y), drawing_effect, alpha);
138 Font::draw_text(const std::string& text, const Vector& pos,
139 DrawingEffect drawing_effect, float alpha) const
142 draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize),
143 drawing_effect, alpha);
145 draw_chars(chars, text, pos, drawing_effect, alpha);
148 /** decoding of a byte stream to a single unicode character.
149 * This should be correct for well formed utf-8 sequences but doesn't check for
150 * all forms of illegal sequences.
151 * (see unicode standard section 3.10 table 3-5 and 3-6 for details)
153 uint32_t decode_utf8(const std::string& text, size_t& p)
156 uint32_t c = (unsigned char) text[p++];
163 throw std::runtime_error("Malformed utf-8 sequence");
164 uint32_t c2 = (unsigned char) text[p++];
167 throw std::runtime_error("Malformed utf-8 sequence");
168 return (c & 0x1F) << 6 | (c2 & 0x3F);
173 throw std::runtime_error("Malformed utf-8 sequence");
174 uint32_t c3 = (unsigned char) text[p++];
176 return (c & 0x0F) << 12 | (c2 & 0x3F) << 6 | (c3 & 0x3F);
181 throw std::runtime_error("Malformed utf-8 sequence");
182 uint32_t c4 = (unsigned char) text[p++];
184 return (c & 0x07) << 18 | (c2 & 0x3F) << 12 | (c3 & 0x3F) << 6
188 throw std::runtime_error("Malformed utf-8 sequence");
192 Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
193 DrawingEffect drawing_effect, float alpha) const
197 while(i < text.size()) {
198 uint32_t c = decode_utf8(text, i);
201 // a non-printable character?
212 font_index = c - first_char;
213 // we don't have the control chars 0x80-0xa0 in the font
217 log_debug << "Unsupported utf-8 character '" << c << "' found" << std::endl;
222 if(font_index < 0 || font_index >= (ssize_t) char_count) {
223 log_debug << "Unsupported utf-8 character found" << std::endl;
227 int source_x = (font_index % 16) * w;
228 int source_y = (font_index / 16) * h;
229 pchars->draw_part(source_x, source_y, p.x, p.y, w, h, alpha,