font.cpp

Go to the documentation of this file.
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 }

Generated Fri Jul 28 19:23:00 2006.
Copyright © 1998-2003 by the respective authors.

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.