news download themes documentation links










Font.cc

00001 // Font.cc
00002 // Copyright (c) 2002 Henrik Kinnunen (fluxgen@linuxmail.org)
00003 // 
00004 // Permission is hereby granted, free of charge, to any person obtaining a
00005 // copy of this software and associated documentation files (the "Software"),
00006 // to deal in the Software without restriction, including without limitation
00007 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
00008 // and/or sell copies of the Software, and to permit persons to whom the
00009 // Software is furnished to do so, subject to the following conditions:
00010 //
00011 // The above copyright notice and this permission notice shall be included in
00012 // all copies or substantial portions of the Software.
00013 //
00014 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00017 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00019 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00020 // DEALINGS IN THE SOFTWARE.
00021 
00022 //$Id: Font.cc,v 1.6 2003/12/01 19:57:01 fluxgen Exp $
00023 
00024 
00025 #include "Font.hh"
00026 #include "FontImp.hh"
00027 
00028 #ifdef    HAVE_CONFIG_H
00029 #include "config.h"
00030 #endif // HAVE_CONFIG_H
00031 
00032 // for antialias 
00033 #ifdef USE_XFT
00034 #include "XftFontImp.hh"
00035 #endif // USE_XFT
00036 
00037 // for multibyte support
00038 #ifdef USE_XMB
00039 #include "XmbFontImp.hh"
00040 #endif //USE_XMB
00041 
00042 // standard font system
00043 #include "XFontImp.hh"
00044 
00045 #include "GContext.hh"
00046 
00047 //use gnu extensions
00048 #ifndef _GNU_SOURCE
00049 #define _GNU_SOURCE
00050 #endif //_GNU_SOURCE
00051 
00052 #ifndef __USE_GNU
00053 #define __USE_GNU
00054 #endif //__USE_GNU
00055 
00056 #include <iostream> 
00057 #include <cstring>
00058 #include <cstdlib>
00059 #include <typeinfo>
00060 using namespace std;
00061 
00062 #ifdef HAVE_SETLOCALE
00063 #include <locale.h>
00064 #endif //HAVE_SETLOCALE
00065 
00066 namespace FbTk {
00067 
00068 bool Font::m_multibyte = false; 
00069 bool Font::m_utf8mode = false;
00070 
00071 Font::Font(const char *name, bool antialias):
00072     m_fontimp(0),
00073     m_antialias(false), m_rotated(false), m_shadow(false) {
00074     
00075     // MB_CUR_MAX returns the size of a char in the current locale
00076     if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte
00077         m_multibyte = true;
00078 
00079     char *s; // temporary string for enviroment variable
00080     // check for utf-8 mode
00081     if (((s = getenv("LC_ALL")) && *s) ||
00082         ((s = getenv("LC_CTYPE")) && *s) ||
00083         ((s = getenv("LANG")) && *s)) {
00084         if (strstr(s, "UTF-8"))
00085             m_utf8mode = true;
00086     }
00087 
00088     // create the right font implementation
00089     // antialias is prio 1
00090 #ifdef USE_XFT
00091     if (antialias) {
00092         m_fontimp.reset(new XftFontImp(0, m_utf8mode));
00093         m_antialias = true;
00094     }
00095 #endif //USE_XFT
00096     // if we didn't create a Xft font then create basic font
00097     if (m_fontimp.get() == 0) {
00098 #ifdef USE_XMB
00099         if (m_multibyte || m_utf8mode)
00100             m_fontimp.reset(new XmbFontImp(0, m_utf8mode));
00101         else // basic font implementation
00102 #endif // USE_XMB
00103             m_fontimp.reset(new XFontImp());
00104     }
00105     
00106     if (name != 0) {
00107         load(name);
00108     }
00109 
00110 }
00111 
00112 Font::~Font() {
00113 
00114 }
00115 
00116 void Font::setAntialias(bool flag) {
00117     bool loaded = m_fontimp->loaded();
00118 #ifdef USE_XFT
00119     if (flag && !isAntialias() && !m_rotated) {
00120         m_fontimp.reset(new XftFontImp(m_fontstr.c_str(), m_utf8mode));
00121     } else if (!flag && isAntialias()) 
00122 #endif // USE_XFT
00123     {
00124 #ifdef USE_XMB
00125             if (m_multibyte || m_utf8mode)
00126                 m_fontimp.reset(new XmbFontImp(m_fontstr.c_str(), m_utf8mode));
00127             else
00128 #endif // USE_XMB
00129                 m_fontimp.reset(new XFontImp(m_fontstr.c_str()));
00130     }
00131 
00132     if (m_fontimp->loaded() != loaded) { // if the new font failed to load, fall back to 'fixed'
00133         if (!m_fontimp->load("fixed")) // if that failes too, output warning
00134             cerr<<"Warning: can't load fallback font 'fixed'."<<endl;
00135     }
00136 
00137     m_antialias = flag;
00138 }
00139 
00140 bool Font::load(const std::string &name) {
00141     if (name.size() == 0)
00142         return false;
00143     // copy name so we can manipulate it
00144     std::string new_name = name;
00145 
00146     m_shadow = false;
00147 
00148     // find font option "shadow"    
00149     size_t start_pos = new_name.find_first_of(':');
00150     if (start_pos != std::string::npos) {        
00151         size_t shadow_pos = new_name.find("shadow", start_pos);
00152         if (shadow_pos != std::string::npos) {
00153             m_shadow = true;
00154             // erase "shadow" since it's not a valid option for the font
00155             new_name.erase(shadow_pos, 6);
00156             
00157             // is the option row empty?
00158             if (new_name.find_first_not_of("\t ,", start_pos + 1) == std::string::npos)
00159                 new_name.erase(start_pos); // erase the ':' and the rest of the line
00160             else {
00161                 // there might be some options left so we need to remove the ","
00162                 // before/after "shadow" option
00163                 size_t pos = new_name.find_last_not_of("\t ", shadow_pos);
00164                 if (pos != std::string::npos) {
00165                     if (new_name[pos] == ',')
00166                         new_name.erase(pos, 1);
00167                 
00168                 }
00169 
00170                 // ok, we removed the "," and "shadow" now we need to determine
00171                 // if we need to remove the ":" , so we search for anything except
00172                 // \t and space and if we dont find anything the ":" is removed
00173                 if (new_name.find_first_not_of("\t ", start_pos + 1) == std::string::npos)
00174                     new_name.erase(start_pos, 1);               
00175 
00176             }
00177 
00178         }
00179     }
00180 
00181     m_fontstr = name;
00182     return m_fontimp->load(new_name.c_str());
00183 }
00184 
00185 unsigned int Font::textWidth(const char * const text, unsigned int size) const {
00186     return m_fontimp->textWidth(text, size);
00187 }
00188 
00189 unsigned int Font::height() const {
00190     return m_fontimp->height();
00191 }
00192 
00193 int Font::ascent() const {
00194     return m_fontimp->ascent();
00195 }
00196 
00197 int Font::descent() const { 
00198     return m_fontimp->descent();
00199 }
00200 void Font::drawText(Drawable w, int screen, GC gc,
00201                     const char *text, size_t len, int x, int y, 
00202                     bool rotate) const {
00203     if (text == 0 || len == 0)
00204         return;
00205 
00206     // so we don't end up in a loop with m_shadow
00207     static bool first_run = true; 
00208 
00209     // draw shadow first
00210     if (first_run && m_shadow) {
00211         FbTk::GContext shadow_gc(w);
00212         shadow_gc.setForeground(FbTk::Color("black", screen));
00213         first_run = false; // so we don't end up in a loop
00214         drawText(w, screen, shadow_gc.gc(), text, len, x + 1, y + 1);
00215         first_run = true;
00216     }
00217 
00218     if (!rotate && isRotated()) {
00219         // if this was called with request to not rotated the text
00220         // we just forward it to the implementation that handles rotation
00221         // currently just XFontImp
00222         // Using dynamic_cast just temporarly until there's a better solution 
00223         // to put in FontImp
00224         try {
00225             XFontImp *font = dynamic_cast<XFontImp *>(m_fontimp.get());
00226             font->setRotate(false); // disable rotation temporarly
00227 
00228             font->drawText(w, screen, gc, text, len, x, y);
00229             font->setRotate(true); // enable rotation
00230         } catch (std::bad_cast &bc) {
00231             // draw normal...
00232             m_fontimp->drawText(w, screen, gc, text, len, x, y);
00233         }
00234 
00235     } else
00236         m_fontimp->drawText(w, screen, gc, text, len, x, y);        
00237 
00238 
00239 }   
00240 
00241 void Font::rotate(float angle) {
00242 #ifdef USE_XFT
00243     // if we are rotated and we are changing to horiz text 
00244     // and we were antialiased before we rotated then change to XftFontImp
00245     if (isRotated() && angle == 0 && isAntialias())
00246         m_fontimp.reset(new XftFontImp(m_fontstr.c_str(), m_utf8mode));
00247 #endif // USE_XFT
00248     // change to a font imp that handles rotated fonts (i.e just XFontImp at the moment)
00249     // if we're going to rotate this font
00250     if (angle != 0 && isAntialias() && !isRotated()) {
00251         m_fontimp.reset(new XFontImp(m_fontstr.c_str()));
00252         if (!m_fontimp->loaded()) // if it failed to load font, try default font fixed
00253             m_fontimp->load("fixed");
00254     }
00255 
00256     //Note: only XFontImp implements FontImp::rotate
00257     m_fontimp->rotate(angle);
00258 
00259     m_rotated = (angle == 0 ? false : true);
00260     m_angle = angle;
00261 }
00262 
00263 };

Fluxbox CVS-Jan-2003




      



Got comments about the page? Send them to webmaster.
If you have general Fluxbox related questions ask them on our irc channel or mailing lists.

Show Source








Designed by aLEczapKA