00001 /* 00002 libwt - Vassilis Virvilis Toolkit - a widget library 00003 Copyright (C) 2006 Vassilis Virvilis <vasvir2@fastmail.fm> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Lesser General Public 00007 License as published by the Free Software Foundation; either 00008 version 2.1 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Lesser General Public License for more details. 00014 00015 You should have received a copy of the GNU Lesser General Public 00016 License along with this library; if not, write to the 00017 Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, SA. 00019 */ 00020 00021 #include<boost/tokenizer.hpp> 00022 #include <boost/lexical_cast.hpp> 00023 00024 #include <wt/font.h> 00025 #include <wt/builtin_font.h> 00026 #include <wt/trace.h> 00027 00028 #define DEFAULT_POINTSIZE 18 00029 #define DEFAULT_RENDERING Blended 00030 #define DEFAULT_ENCODING ASCII 00031 #define DEFAULT_BACKGROUNDCOLOR "black" 00032 #define DEFAULT_FOREGROUNDCOLOR "white" 00033 00034 namespace Wt { 00035 00036 Font::Map Font::map; 00037 00038 Font* Font::default_font = 0; 00039 00040 void Font::Deleter::operator()(TTF_Font* f) { 00041 if (f) 00042 TTF_CloseFont(f); 00043 } 00044 00045 Font::Ptr Font::open_default_font(int ptsize) { 00046 if (!default_font) { 00047 SDL_RWops *rwop = SDL_RWFromConstMem(BultinFontData, 00048 BultinFontDataSize); 00049 return Ptr(TTF_OpenFontRW(rwop, true, ptsize), Deleter()); 00050 } 00051 return default_font->ttf_font; 00052 } 00053 00054 Font::Ptr Font::open_font(const std::string& filename, 00055 int ptsize, int style, int index) { 00056 Ptr f(TTF_OpenFontIndex(filename.c_str(), ptsize, index), Deleter()); 00057 if (!f) 00058 f = open_default_font(ptsize); 00059 00060 if (f) 00061 TTF_SetFontStyle(f.get(), style); 00062 return f; 00063 } 00064 00065 Font::Font(const std::string& filename, int ptsize, int style, int index) : 00066 ttf_font(open_font(filename, defaultFontSize(ptsize), style, index)), 00067 filename_(filename), 00068 ptsize_(defaultFontSize(ptsize)), 00069 index_(index), 00070 rendering_(DEFAULT_RENDERING), 00071 encoding_(DEFAULT_ENCODING), 00072 bg_color_(DEFAULT_BACKGROUNDCOLOR), 00073 fg_color_(DEFAULT_FOREGROUNDCOLOR) { 00074 trace("font", "Creating font %p (%p) (%s)\n", this, ttf_font.get(), filename_.c_str()); 00075 trace("font") << "Adding to Font::Map " << *this << 00076 " use count: " << ttf_font.use_count() << std::endl; 00077 map[this->description()] = *this; 00078 } 00079 00080 Font::Font() : 00081 ttf_font(open_default_font(defaultFontSize())), 00082 filename_("*"), 00083 ptsize_(defaultFontSize()), 00084 index_(0), 00085 rendering_(DEFAULT_RENDERING), 00086 encoding_(DEFAULT_ENCODING), 00087 bg_color_(DEFAULT_BACKGROUNDCOLOR), 00088 fg_color_(DEFAULT_FOREGROUNDCOLOR) { 00089 trace("font", "Creating font %p (%p) (default)\n", this, ttf_font.get()); 00090 trace("font") << "Adding to Font::Map " << *this << 00091 " use count: " << ttf_font.use_count() << std::endl; 00092 } 00093 00094 Font::Font(const std::string& desc) { 00095 Map::iterator it = map.find(desc); 00096 trace("font", "Looking in Font::Map for '%s'\n", desc.c_str()); 00097 00098 // if it is in cache return it 00099 if (it != map.end()) { 00100 *this = it->second; 00101 trace("font") << "Found in Font::Map " << *this << 00102 " use count: " << ttf_font.use_count() << std::endl; 00103 return; 00104 } 00105 00106 // let's parse the description and load it in cache 00107 boost::char_separator<char> sep(", "); 00108 typedef boost::tokenizer<boost::char_separator<char> > Tokenizer; 00109 Tokenizer tokens(desc, sep); 00110 Tokenizer::iterator token = tokens.begin(); 00111 00112 std::string filename; 00113 if (token != tokens.end()) { 00114 filename = *token; 00115 ++token; 00116 } 00117 00118 int point_size = 0; 00119 if (token != tokens.end()) { 00120 point_size = boost::lexical_cast<int>(*token); 00121 ++token; 00122 } 00123 00124 int st = Normal; 00125 if (token != tokens.end()) { 00126 std::string flags = *token; 00127 for (std::string::iterator ct = flags.begin(), 00128 ctend = flags.end(); ct != ctend; ++ct) { 00129 switch (*ct) { 00130 case 'b': 00131 st |= Bold; 00132 break; 00133 case 'i': 00134 st |= Italic; 00135 break; 00136 case 'u': 00137 st |= Underline; 00138 break; 00139 default: 00140 Warn("Unknown specifier '%c' in font " 00141 "attibute desctrition '%s'\n", *ct, flags.c_str()); 00142 break; 00143 } 00144 } 00145 } 00146 00147 trace("font", "Parsing font description as '%s, %d, %d'\n", 00148 filename.c_str(), point_size, st); 00149 00150 *this = Font(filename, point_size, st); 00151 trace("font") << "Added to Font::Map " << *this << 00152 " use count: " << ttf_font.use_count() << std::endl; 00153 } 00154 00155 void Font::detach() { 00156 //avoid detaching if we are the only client for this font 00157 if (!ttf_font.unique()) { 00158 ttf_font = open_font(filename_, pointSize(), style(), index_); 00159 } 00160 } 00161 00162 TTF_Font *Font::deconst() const { 00163 //SDL breakage 00164 return const_cast<TTF_Font *> 00165 (static_cast<const TTF_Font *>(*this)); 00166 } 00167 00168 void Font::init() { 00169 TTF_Init(); 00170 default_font = new Font(); 00171 map[default_font->description()] = *default_font; 00172 } 00173 00174 void Font::quit() { 00175 map.clear(); 00176 delete default_font; 00177 TTF_Quit(); 00178 } 00179 00180 int Font::defaultFontSize(int ptsize) { 00181 return (ptsize) ? ptsize : DEFAULT_POINTSIZE; 00182 } 00183 00184 Font& Font::defaultFont() { 00185 return *default_font; 00186 } 00187 00188 std::string Font::description() const { 00189 std::string desc = filename_ + ", "; 00190 desc += boost::lexical_cast<std::string>(pointSize()) + ", "; 00191 00192 int st = style(); 00193 desc += (st & Bold) ? "b" : ""; 00194 desc += (st & Italic) ? "i" : ""; 00195 desc += (st & Underline) ? "u" : ""; 00196 return desc; 00197 } 00198 00199 std::string Font::family() const { 00200 const char *font_family = TTF_FontFaceFamilyName(deconst()); 00201 if (!font_family) 00202 font_family = "*"; 00203 return font_family; 00204 } 00205 00206 void Font::setFont(std::string& filename) { 00207 ttf_font = open_font(filename, pointSize(), style(), index_); 00208 filename_ = filename; 00209 } 00210 00211 int Font::pointSize() const { 00212 return ptsize_; 00213 } 00214 00215 void Font::setPointSize(int ptsize) { 00216 ttf_font = open_font(filename_, ptsize, style(), index_); 00217 ptsize_ = ptsize; 00218 } 00219 00220 bool Font::style() const { 00221 return TTF_GetFontStyle(deconst()); 00222 } 00223 00224 bool Font::styleFlag(int flag) const { 00225 return style() & flag; 00226 } 00227 00228 void Font::setStyleFlag(int flag, bool enable) { 00229 int s = style(); 00230 00231 if (enable && (flag & s)) 00232 return; 00233 00234 if (!enable && !(~flag & s)) 00235 return; 00236 00237 detach(); 00238 00239 if (enable) 00240 TTF_SetFontStyle(*this, flag | s); 00241 else 00242 TTF_SetFontStyle(*this, ~flag & s); 00243 } 00244 00245 bool Font::bold() const { 00246 return styleFlag(TTF_STYLE_BOLD); 00247 } 00248 00249 void Font::setBold(bool enable) { 00250 setStyleFlag(TTF_STYLE_BOLD, enable); 00251 } 00252 00253 bool Font::italic() const { 00254 return styleFlag(TTF_STYLE_ITALIC); 00255 } 00256 00257 void Font::setItalic(bool enable) { 00258 setStyleFlag(TTF_STYLE_ITALIC, enable); 00259 } 00260 00261 bool Font::underline() const { 00262 return styleFlag(TTF_STYLE_UNDERLINE); 00263 00264 } 00265 00266 void Font::setUnderline(bool enable) { 00267 setStyleFlag(TTF_STYLE_UNDERLINE, enable); 00268 } 00269 00270 void Font::setRendering(int rendering) { 00271 detach(); 00272 rendering_ = rendering; 00273 } 00274 00275 int Font::rendering() const { 00276 return rendering_; 00277 } 00278 00279 void Font::setEncoding(int encoding) { 00280 detach(); 00281 encoding_ = encoding; 00282 } 00283 00284 int Font::encoding() const { 00285 return encoding_; 00286 } 00287 00288 void Font::setBackgroundColor(const Color& bg_color) { 00289 detach(); 00290 bg_color_ = bg_color; 00291 } 00292 00293 const Color& Font::backgroundColor() const { 00294 return bg_color_; 00295 } 00296 00297 void Font::setForegroundColor(const Color& fg_color) { 00298 detach(); 00299 fg_color_ = fg_color; 00300 } 00301 00302 const Color& Font::foregroundColor() const { 00303 return fg_color_; 00304 } 00305 00306 Size Font::size(const std::string& text) const { 00307 int w = 0, h = 0; 00308 if (encoding_ == ASCII) { 00309 TTF_SizeText(deconst(), text.c_str(), &w, &h); 00310 } else if (encoding_ == UTF8) { 00311 TTF_SizeUTF8(deconst(), text.c_str(), &w, &h); 00312 } 00313 return Size(w, h); 00314 } 00315 00316 Size Font::size(const Uint16 *text) const { 00317 int w, h; 00318 TTF_SizeUNICODE(deconst(), text, &w, &h); 00319 return Size(w, h); 00320 } 00321 00322 Pixmap Font::blitText(const std::string& text) const { 00323 SDL_Surface *s = 0; 00324 switch (rendering_) { 00325 case Solid: 00326 if (encoding_ == ASCII) { 00327 s = TTF_RenderText_Solid(deconst(), text.c_str(), fg_color_); 00328 } else if (encoding_ == UTF8) { 00329 s = TTF_RenderUTF8_Solid(deconst(), text.c_str(), fg_color_); 00330 } 00331 break; 00332 case Shaded: 00333 if (encoding_ == ASCII) { 00334 s = TTF_RenderText_Shaded(deconst(), 00335 text.c_str(), fg_color_, bg_color_); 00336 } else if (encoding_ == UTF8) { 00337 s = TTF_RenderUTF8_Shaded(deconst(), text.c_str(),fg_color_, bg_color_); 00338 } 00339 break; 00340 case Blended: 00341 if (encoding_ == ASCII) { 00342 s = TTF_RenderText_Blended(deconst(), text.c_str(), fg_color_); 00343 } else if (encoding_ == UTF8) { 00344 s = TTF_RenderUTF8_Blended(deconst(), text.c_str(), fg_color_); 00345 } 00346 break; 00347 default: 00348 break; 00349 } 00350 00351 return Pixmap(s); 00352 } 00353 00354 Pixmap Font::blitText(const Uint16 *text) const { 00355 SDL_Surface *s = 0; 00356 switch (rendering_) { 00357 case Solid: 00358 s = TTF_RenderUNICODE_Solid(deconst(), text, fg_color_); 00359 break; 00360 case Shaded: 00361 s = TTF_RenderUNICODE_Shaded(deconst(), text, fg_color_, bg_color_); 00362 break; 00363 case Blended: 00364 s = TTF_RenderUNICODE_Blended(deconst(), text, fg_color_); 00365 break; 00366 default: 00367 break; 00368 } 00369 00370 return Pixmap(s); 00371 } 00372 00373 int Font::ascent() const { 00374 return TTF_FontAscent(deconst()); 00375 } 00376 00377 int Font::descent() const { 00378 return TTF_FontDescent(deconst()); 00379 } 00380 00381 int Font::height() const { 00382 return TTF_FontHeight(deconst()); 00383 } 00384 00385 int Font::lineSpacing() const { 00386 return TTF_FontLineSkip(deconst()); 00387 } 00388 00389 int Font::leading() const { 00390 return lineSpacing() - height(); 00391 } 00392 00393 int Font::faces() const { 00394 return TTF_FontFaces(deconst()); 00395 } 00396 00397 std::string Font::faceStyleName() const { 00398 const char *face_style_name = TTF_FontFaceStyleName(deconst()); 00399 if (!face_style_name) 00400 face_style_name = "*"; 00401 return face_style_name; 00402 } 00403 00404 bool Font::monoSpace() const { 00405 return TTF_FontFaceIsFixedWidth(deconst()) > 0; 00406 } 00407 00408 int Font::leftBearing(Uint16 ch) const { 00409 int minx; 00410 TTF_GlyphMetrics(deconst(), ch, &minx, 0, 0, 0, 0); 00411 return minx; 00412 } 00413 00414 int Font::rightBearing(Uint16 ch) const { 00415 int maxx, advance; 00416 TTF_GlyphMetrics(deconst(), ch, 0, &maxx, 0, 0, &advance); 00417 return advance - maxx; 00418 } 00419 00420 int Font::width(Uint16 ch) const { 00421 int minx, maxx; 00422 TTF_GlyphMetrics(deconst(), ch, &minx, &maxx, 0, 0, 0); 00423 return maxx - minx; 00424 } 00425 00426 Size Font::size(const Uint16 ch) const { 00427 int minx, maxx, miny, maxy; 00428 TTF_GlyphMetrics(deconst(), ch, &minx, &maxx, &miny, &maxy, 0); 00429 return Size(maxx - minx, maxy - miny); 00430 } 00431 00432 Rect Font::boundingRect(const Uint16 ch) const { 00433 int minx, maxx, miny, maxy; 00434 TTF_GlyphMetrics(deconst(), ch, &minx, &maxx, &miny, &maxy, 0); 00435 return Rect(minx, miny, maxx - minx + 1, maxy - miny + 1); 00436 } 00437 00438 Rect Font::boundingRect(const std::string& str, int len) const { 00439 const std::string s = (len == -1) ? str : str.substr(0, len); 00440 return Rect(Point(0, 0), size(str)); 00441 } 00442 00443 std::ostream& operator<<(std::ostream& s, const Font& f) { 00444 s << f.description(); 00445 return s; 00446 } 00447 00448 }
This document is licensed under the terms of the GNU Free Documentation License and may be freely distributed under the conditions given by this license.