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"
32 Font::Font(const std::string& file, const std::string& shadowfile,
33 int w, int h, int shadowsize)
34 : chars(0), shadow_chars(0), w(w), h(h), shadowsize(shadowsize)
36 chars = new Surface(file);
37 shadow_chars = new Surface(shadowfile);
40 char_count = ((int) chars->get_height() / h) * 16;
50 Font::get_text_width(const std::string& text) const
52 /** Let's calculate the size of the biggest paragraph */
53 std::string::size_type l, hl, ol;
58 l = text.find("\n", l+1);
59 if(l == std::string::npos)
67 for (uint i = 0; i < text.size(); i++)
68 if ((unsigned char) text[i] > 0xC2 && (unsigned char) text[i] < 0xC6)
69 hl--; // control characters are a WASTE.
75 Font::get_text_height(const std::string& text) const
77 /** Let's calculate height of the text */
78 std::string::size_type l, hh;
82 l = text.find("\n", l+1);
83 if(l == std::string::npos)
92 Font::get_height() const
98 Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment,
99 DrawingEffect drawing_effect, float alpha) const
101 /* Cut lines changes into seperate strings, needed to support center/right text
102 alignments with break lines.
103 Feel free to replace this hack with a more elegant solution
106 std::string::size_type l, i, y;
111 l = text.find("\n", i);
112 if(l == std::string::npos) {
117 temp[text.copy(temp, l - i, i)] = '\0';
119 // calculate X positions based on the alignment type
120 Vector pos = Vector(pos_);
121 if(alignment == CENTER_ALLIGN)
122 pos.x -= get_text_width(temp) / 2;
123 else if(alignment == RIGHT_ALLIGN)
124 pos.x -= get_text_width(temp);
126 draw_text(temp, pos + Vector(0,y), drawing_effect, alpha);
134 Font::draw_text(const std::string& text, const Vector& pos,
135 DrawingEffect drawing_effect, float alpha) const
138 draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize),
139 drawing_effect, alpha);
141 draw_chars(chars, text, pos, drawing_effect, alpha);
144 /** decoding of a byte stream to a single unicode character.
145 * This should be correct for well formed utf-8 sequences but doesn't check for
146 * all forms of illegal sequences.
147 * (see unicode standard section 3.10 table 3-5 and 3-6 for details)
149 uint32_t decode_utf8(const std::string& text, size_t& p)
152 uint32_t c = (unsigned char) text[p++];
159 throw std::runtime_error("Malformed utf-8 sequence");
160 uint32_t c2 = (unsigned char) text[p++];
163 throw std::runtime_error("Malformed utf-8 sequence");
164 return (c & 0x1F) << 6 | (c2 & 0x3F);
169 throw std::runtime_error("Malformed utf-8 sequence");
170 uint32_t c3 = (unsigned char) text[p++];
172 return (c & 0x0F) << 12 | (c2 & 0x3F) << 6 | (c3 & 0x3F);
177 throw std::runtime_error("Malformed utf-8 sequence");
178 uint32_t c4 = (unsigned char) text[p++];
180 return (c & 0x07) << 18 | (c2 & 0x3F) << 12 | (c3 & 0x3F) << 6
184 throw std::runtime_error("Malformed utf-8 sequence");
188 Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
189 DrawingEffect drawing_effect, float alpha) const
193 while(i < text.size()) {
194 uint32_t c = decode_utf8(text, i);
197 // a non-printable character?
208 font_index = c - first_char;
209 // we don't have the control chars 0x80-0xa0 in the font
214 std::cout << "Unsupported utf-8 character '" << c << "' found\n";
220 if(font_index < 0 || font_index >= (ssize_t) char_count) {
222 std::cout << "Unsupported utf-8 character found\n";
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,