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.h"
27 #include "lisp/lisp.h"
30 #include "drawing_context.h"
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 last_char = first_char + (chars->h / h) * 16;
48 if(last_char > 127 && last_char < 160) // we have left out some control chars at 128-159
53 SDL_Surface* conv = SDL_DisplayFormatAlpha(chars->impl->get_sdl_surface());
54 int pixels = conv->w * conv->h;
55 SDL_LockSurface(conv);
56 for(int i = 0; i < pixels; ++i) {
57 Uint32 *p = (Uint32 *)conv->pixels + i;
58 *p = *p & conv->format->Amask;
60 SDL_UnlockSurface(conv);
61 SDL_SetAlpha(conv, SDL_SRCALPHA, 128);
62 shadow_chars = new Surface(conv, true);
63 SDL_FreeSurface(conv);
74 Font::get_text_width(const std::string& text) const
76 /** Let's calculate the size of the biggest paragraph */
77 std::string::size_type l, hl, ol;
82 l = text.find("\n", l+1);
83 if(l == std::string::npos)
91 for (uint i = 0; i < text.size(); i++)
92 if ((unsigned char) text[i] > 0xC2 && (unsigned char) text[i] < 0xC6)
93 hl--; // control characters are a WASTE.
99 Font::get_text_height(const std::string& text) const
101 /** Let's calculate height of the text */
102 std::string::size_type l, hh;
106 l = text.find("\n", l+1);
107 if(l == std::string::npos)
116 Font::get_height() const
122 Font::draw(const std::string& text, const Vector& pos_, FontAlignment alignment,
123 uint32_t drawing_effect, uint8_t alpha) const
125 /* Cut lines changes into seperate strings, needed to support center/right text
126 alignments with break lines.
127 Feel free to replace this hack with a more elegant solution
130 std::string::size_type l, i, y;
135 l = text.find("\n", i);
136 if(l == std::string::npos) {
141 temp[text.copy(temp, l - i, i)] = '\0';
143 // calculate X positions based on the alignment type
144 Vector pos = Vector(pos_);
145 if(alignment == CENTER_ALLIGN)
146 pos.x -= get_text_width(temp) / 2;
147 else if(alignment == RIGHT_ALLIGN)
148 pos.x -= get_text_width(temp);
150 draw_text(temp, pos + Vector(0,y), drawing_effect, alpha);
158 Font::draw_text(const std::string& text, const Vector& pos,
159 uint32_t drawing_effect, uint8_t alpha) const
162 draw_chars(shadow_chars, text, pos + Vector(shadowsize, shadowsize),
163 drawing_effect, alpha);
165 draw_chars(chars, text, pos, drawing_effect, alpha);
169 Font::draw_chars(Surface* pchars, const std::string& text, const Vector& pos,
170 uint32_t drawing_effect, uint8_t alpha) const
172 SurfaceImpl* impl = pchars->impl;
176 for(size_t i = 0; i < text.size(); ++i) {
177 int c = (unsigned char) text[i];
179 if(c > 127 && c < 160) // correct for the 32 controlchars at 128-159
181 if (c > 0xC2 && text.size() == i+1) // string ends with control char
183 std::cerr << "String \"" << text << "\" is malformed.\n";
187 d = (unsigned char) text[i+1];
189 if (c == 0xC3 && d < 160) // first-byte identifier of U0080 ("C1 Control Characters and Latin-1 Supplement")
190 { // iso-8859-1 equiv character is capital A with tilde above, signified as "C3 83" in utf-8
194 else if (c == 0xC3 && d >= 160) // U0080 pt. 2
199 else if (c == 0xC4 && d < 160)
204 else if (c == 0xC4 && d >= 160)
209 else if (c == 0xC5 && d < 160) // first-byte identifier of U0100 ("Latin Extended-A")
210 { // iso-8859-1 equiv character is capital A with ring above, signified as "C3 85" in utf-8
214 else if (c == 0xC5 && d >= 160) // first-byte identifier of U0100 ("Latin Extended-A")
215 { // iso-8859-1 equiv character is capital A with ring above, signified as "C3 85" in utf-8
219 // insert more clauses here once somebody will need them
221 // a non-printable character?
227 if(c == ' ' || c < first_char || c > last_char) {
235 int index = c - first_char;
236 int source_x = (index % 16) * w;
237 int source_y = (index / 16) * h;
239 impl->draw_part(source_x, source_y, p.x, p.y, w, h, alpha, drawing_effect);