00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
00033 #ifdef USE_XFT
00034 #include "XftFontImp.hh"
00035 #endif // USE_XFT
00036
00037
00038 #ifdef USE_XMB
00039 #include "XmbFontImp.hh"
00040 #endif //USE_XMB
00041
00042
00043 #include "XFontImp.hh"
00044
00045 #include "GContext.hh"
00046
00047
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
00076 if (MB_CUR_MAX > 1)
00077 m_multibyte = true;
00078
00079 char *s;
00080
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
00089
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
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
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) {
00133 if (!m_fontimp->load("fixed"))
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
00144 std::string new_name = name;
00145
00146 m_shadow = false;
00147
00148
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
00155 new_name.erase(shadow_pos, 6);
00156
00157
00158 if (new_name.find_first_not_of("\t ,", start_pos + 1) == std::string::npos)
00159 new_name.erase(start_pos);
00160 else {
00161
00162
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
00171
00172
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
00207 static bool first_run = true;
00208
00209
00210 if (first_run && m_shadow) {
00211 FbTk::GContext shadow_gc(w);
00212 shadow_gc.setForeground(FbTk::Color("black", screen));
00213 first_run = false;
00214 drawText(w, screen, shadow_gc.gc(), text, len, x + 1, y + 1);
00215 first_run = true;
00216 }
00217
00218 if (!rotate && isRotated()) {
00219
00220
00221
00222
00223
00224 try {
00225 XFontImp *font = dynamic_cast<XFontImp *>(m_fontimp.get());
00226 font->setRotate(false);
00227
00228 font->drawText(w, screen, gc, text, len, x, y);
00229 font->setRotate(true);
00230 } catch (std::bad_cast &bc) {
00231
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
00244
00245 if (isRotated() && angle == 0 && isAntialias())
00246 m_fontimp.reset(new XftFontImp(m_fontstr.c_str(), m_utf8mode));
00247 #endif // USE_XFT
00248
00249
00250 if (angle != 0 && isAntialias() && !isRotated()) {
00251 m_fontimp.reset(new XFontImp(m_fontstr.c_str()));
00252 if (!m_fontimp->loaded())
00253 m_fontimp->load("fixed");
00254 }
00255
00256
00257 m_fontimp->rotate(angle);
00258
00259 m_rotated = (angle == 0 ? false : true);
00260 m_angle = angle;
00261 }
00262
00263 };