1 // $Id: font.cpp 2298 2005-03-30 12:01:02Z matzebraun $
4 // Copyright (C) 2004 Tobias Glaesser <tobi.web@gmx.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
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 temp[text.copy(temp, l - i, i)] = '\0';
120 // calculate X positions based on the alignment type
121 Vector pos = Vector(pos_);
122 if(alignment == CENTER_ALLIGN)
123 pos.x -= get_text_width(temp) / 2;
124 else if(alignment == RIGHT_ALLIGN)
125 pos.x -= get_text_width(temp);
127 draw_text(temp, pos + Vector(0,y), drawing_effect, alpha);
135 Font::draw_text(const std::string& text, const Vector& pos,
136 DrawingEffect drawing_effect, float alpha) const
139 draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize),
140 drawing_effect, alpha);
142 draw_chars(chars, text, pos, drawing_effect, alpha);
145 /** decoding of a byte stream to a single unicode character.
146 * This should be correct for well formed utf-8 sequences but doesn't check for
147 * all forms of illegal sequences.
148 * (see unicode standard section 3.10 table 3-5 and 3-6 for details)
150 uint32_t decode_utf8(const std::string& text, size_t& p)
153 uint32_t c = (unsigned char) text[p++];
160 throw std::runtime_error("Malformed utf-8 sequence");
161 uint32_t c2 = (unsigned char) text[p++];
164 throw std::runtime_error("Malformed utf-8 sequence");
165 return (c & 0x1F) << 6 | (c2 & 0x3F);
170 throw std::runtime_error("Malformed utf-8 sequence");
171 uint32_t c3 = (unsigned char) text[p++];
173 return (c & 0x0F) << 12 | (c2 & 0x3F) << 6 | (c3 & 0x3F);
178 throw std::runtime_error("Malformed utf-8 sequence");
179 uint32_t c4 = (unsigned char) text[p++];
181 return (c & 0x07) << 18 | (c2 & 0x3F) << 12 | (c3 & 0x3F) << 6
185 throw std::runtime_error("Malformed utf-8 sequence");
189 Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
190 DrawingEffect drawing_effect, float alpha) const
194 while(i < text.size()) {
195 uint32_t c = decode_utf8(text, i);
198 // a non-printable character?
209 font_index = c - first_char;
210 // we don't have the control chars 0x80-0xa0 in the font
214 msg_debug << "Unsupported utf-8 character '" << c << "' found" << std::endl;
219 if(font_index < 0 || font_index >= (ssize_t) char_count) {
220 msg_debug << "Unsupported utf-8 character found" << std::endl;
224 int source_x = (font_index % 16) * w;
225 int source_y = (font_index / 16) * h;
226 pchars->draw_part(source_x, source_y, p.x, p.y, w, h, alpha,