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, FontType ntype, int nw, int nh,
34 : chars(0), shadow_chars(0), type(ntype), w(nw), h(nh),
35 shadowsize(nshadowsize)
37 chars = new Surface(file, true);
47 char_count = (chars->h / h) * 16;
51 SDL_Surface* conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface());
52 int pixels = conv->w * conv->h;
53 SDL_LockSurface(conv);
54 for(int i = 0; i < pixels; ++i) {
55 Uint32 *p = (Uint32 *)conv->pixels + i;
56 *p = *p & conv->format->Amask;
58 SDL_UnlockSurface(conv);
59 SDL_SetAlpha(conv, SDL_SRCALPHA, 128);
60 shadow_chars = new Surface(conv, true);
61 SDL_FreeSurface(conv);
72 Font::get_text_width(const std::string& text) const
74 /** Let's calculate the size of the biggest paragraph */
75 std::string::size_type l, hl, ol;
80 l = text.find("\n", l+1);
81 if(l == std::string::npos)
89 for (uint i = 0; i < text.size(); i++)
90 if ((unsigned char) text[i] > 0xC2 && (unsigned char) text[i] < 0xC6)
91 hl--; // control characters are a WASTE.
97 Font::get_text_height(const std::string& text) const
99 /** Let's calculate height of the text */
100 std::string::size_type l, hh;
104 l = text.find("\n", l+1);
105 if(l == std::string::npos)
114 Font::get_height() const
120 Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment,
121 uint32_t drawing_effect, uint8_t alpha) const
123 /* Cut lines changes into seperate strings, needed to support center/right text
124 alignments with break lines.
125 Feel free to replace this hack with a more elegant solution
128 std::string::size_type l, i, y;
133 l = text.find("\n", i);
134 if(l == std::string::npos) {
139 temp[text.copy(temp, l - i, i)] = '\0';
141 // calculate X positions based on the alignment type
142 Vector pos = Vector(pos_);
143 if(alignment == CENTER_ALLIGN)
144 pos.x -= get_text_width(temp) / 2;
145 else if(alignment == RIGHT_ALLIGN)
146 pos.x -= get_text_width(temp);
148 draw_text(temp, pos + Vector(0,y), drawing_effect, alpha);
156 Font::draw_text(const std::string& text, const Vector& pos,
157 uint32_t drawing_effect, uint8_t alpha) const
160 draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize),
161 drawing_effect, alpha);
163 draw_chars(chars, text, pos, drawing_effect, alpha);
166 /** decoding of a byte stream to a single unicode character.
167 * This should be correct for well formed utf-8 sequences but doesn't check for
168 * all forms of illegal sequences.
169 * (see unicode standard section 3.10 table 3-5 and 3-6 for details)
171 uint32_t decode_utf8(const std::string& text, size_t& p)
174 uint32_t c = (unsigned char) text[p++];
181 throw std::runtime_error("Malformed utf-8 sequence");
182 uint32_t c2 = (unsigned char) text[p++];
185 throw std::runtime_error("Malformed utf-8 sequence");
186 return (c & 0x1F) << 6 | (c2 & 0x3F);
191 throw std::runtime_error("Malformed utf-8 sequence");
192 uint32_t c3 = (unsigned char) text[p++];
194 return (c & 0x0F) << 12 | (c2 & 0x3F) << 6 | (c3 & 0x3F);
199 throw std::runtime_error("Malformed utf-8 sequence");
200 uint32_t c4 = (unsigned char) text[p++];
202 return (c & 0x07) << 18 | (c2 & 0x3F) << 12 | (c3 & 0x3F) << 6
206 throw std::runtime_error("Malformed utf-8 sequence");
210 Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
211 uint32_t drawing_effect, uint8_t alpha) const
213 SurfaceImpl* impl = pchars->impl;
217 while(i < text.size()) {
218 uint32_t c = decode_utf8(text, i);
221 // a non-printable character?
232 font_index = c - first_char;
233 // we don't have the control chars 0x80-0xa0 in the font
238 std::cout << "Unsupported utf-8 character '" << c << "' found\n";
244 if(font_index < 0 || font_index >= (ssize_t) char_count) {
246 std::cout << "Unsupported utf-8 character found\n";
251 int source_x = (font_index % 16) * w;
252 int source_y = (font_index / 16) * h;
253 impl->draw_part(source_x, source_y, p.x, p.y, w, h, alpha, drawing_effect);