00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "XFontImp.hh"
00025 #include "App.hh"
00026 #include "GContext.hh"
00027 #include "FbPixmap.hh"
00028
00029 #include <X11/Xutil.h>
00030
00031 #include <iostream>
00032 #include <new>
00033 #include <cstdio>
00034 using namespace std;
00035
00036 namespace FbTk {
00037
00038 XFontImp::XFontImp(const char *fontname):m_rotfont(0), m_fontstruct(0),
00039 m_angle(0), m_rotate(true) {
00040 if (fontname != 0)
00041 load(fontname);
00042 }
00043
00044 XFontImp::~XFontImp() {
00045 if (m_fontstruct != 0)
00046 XFreeFont(App::instance()->display(), m_fontstruct);
00047 if (m_rotfont != 0)
00048 freeRotFont();
00049 }
00050
00051 int XFontImp::ascent() const {
00052 if (m_fontstruct == 0)
00053 return 0;
00054 if (m_rotfont != 0)
00055 return m_rotfont->max_ascent;
00056
00057 return m_fontstruct->ascent;
00058 }
00059
00060 bool XFontImp::load(const std::string &fontname) {
00061 XFontStruct *font = XLoadQueryFont(App::instance()->display(), fontname.c_str());
00062 if (font == 0)
00063 return false;
00064 if (m_fontstruct != 0)
00065 XFreeFont(App::instance()->display(), m_fontstruct);
00066
00067 m_fontstruct = font;
00068
00069 if (m_rotfont != 0) {
00070 freeRotFont();
00071 rotate(m_angle);
00072 }
00073
00074 return true;
00075 }
00076
00077 void XFontImp::drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const {
00078 if (m_fontstruct == 0)
00079 return;
00080
00081 if (m_rotfont != 0 && m_rotate) {
00082 drawRotText(w, screen, gc, text, len, x, y);
00083 return;
00084 }
00085
00086 Display *disp = App::instance()->display();
00087 XSetFont(disp, gc, m_fontstruct->fid);
00088 XDrawString(disp, w, gc, x, y, text, len);
00089 }
00090
00091 unsigned int XFontImp::textWidth(const char * const text, unsigned int size) const {
00092 if (text == 0)
00093 return 0;
00094 if (m_fontstruct == 0)
00095 return 0;
00096
00097 if (m_rotfont != 0)
00098 return rotTextWidth(text, size);
00099
00100 return XTextWidth(m_fontstruct, text, size);
00101 }
00102
00103 unsigned int XFontImp::height() const {
00104 if (m_fontstruct == 0)
00105 return 0;
00106
00107 return m_fontstruct->ascent + m_fontstruct->descent;
00108 }
00109
00110 void XFontImp::rotate(float angle) {
00111
00112 if (m_fontstruct == 0 || m_fontstruct->per_char == 0)
00113 return;
00114
00115 if (m_rotfont != 0)
00116 freeRotFont();
00117
00118
00119 if (angle == 0) {
00120 m_angle = 0;
00121 return;
00122 }
00123
00124
00125 while (angle < 0)
00126 angle += 360;
00127
00128 m_angle = angle;
00129
00130
00131 Display *dpy = App::instance()->display();
00132 Window rootwin = DefaultRootWindow(dpy);
00133 int screen = DefaultScreen(dpy);
00134
00135 char text[3];
00136 int ichar, i, j, index, boxlen = 60;
00137 int vert_w, vert_h, vert_len, bit_w, bit_h, bit_len;
00138 int min_char, max_char;
00139 unsigned char *vertdata, *bitdata;
00140 int ascent, descent, lbearing, rbearing;
00141
00142
00143 int dir = (int)((angle+45.0)/90.0)%4;
00144
00145 if (dir == 0)
00146 return;
00147
00148
00149 FbTk::FbPixmap canvas(rootwin, boxlen, boxlen, 1);
00150
00151
00152 FbTk::GContext font_gc(canvas);
00153 font_gc.setBackground(None);
00154 font_gc.setFont(m_fontstruct->fid);
00155
00156
00157 m_rotfont = new(nothrow) XRotFontStruct;
00158
00159 if (m_rotfont == 0) {
00160 cerr<<"RotFont: out of memory"<<endl;
00161 return;
00162 }
00163
00164
00165 min_char = m_fontstruct->min_char_or_byte2;
00166 max_char = m_fontstruct->max_char_or_byte2;
00167
00168
00169 if (min_char<32)
00170 min_char = 32;
00171 if (max_char>126)
00172 max_char = 126;
00173
00174
00175 m_rotfont->dir = dir;
00176 m_rotfont->min_char = min_char;
00177 m_rotfont->max_char = max_char;
00178 m_rotfont->max_ascent = m_fontstruct->max_bounds.ascent;
00179 m_rotfont->max_descent = m_fontstruct->max_bounds.descent;
00180 m_rotfont->height = m_rotfont->max_ascent + m_rotfont->max_descent;
00181
00182
00183
00184 for (ichar = min_char; ichar <= max_char; ichar++) {
00185 index = ichar - m_fontstruct->min_char_or_byte2;
00186
00187
00188 ascent = m_rotfont->per_char[ichar-32].ascent = m_fontstruct->per_char[index].ascent;
00189 descent = m_rotfont->per_char[ichar-32].descent = m_fontstruct->per_char[index].descent;
00190 lbearing = m_rotfont->per_char[ichar-32].lbearing = m_fontstruct->per_char[index].lbearing;
00191 rbearing = m_rotfont->per_char[ichar-32].rbearing = m_fontstruct->per_char[index].rbearing;
00192 m_rotfont->per_char[ichar-32].width = m_fontstruct->per_char[index].width;
00193
00194
00195 if (!ascent && !descent)
00196 ascent = m_rotfont->per_char[ichar-32].ascent = 1;
00197 if (!lbearing && !rbearing)
00198 rbearing = m_rotfont->per_char[ichar-32].rbearing = 1;
00199
00200
00201 vert_w = rbearing - lbearing;
00202 vert_h = ascent + descent;
00203
00204
00205 vert_len = (vert_w-1)/8+1;
00206
00207 font_gc.setForeground(None);
00208 canvas.fillRectangle(font_gc.gc(),
00209 0, 0,
00210 boxlen, boxlen);
00211
00212 sprintf(text, "%c", ichar);
00213 font_gc.setForeground(1);
00214 XDrawImageString(dpy, canvas.drawable(), font_gc.gc(),
00215 boxlen/2 - lbearing,
00216 boxlen/2 - descent, text, 1);
00217
00218
00219 vertdata = new unsigned char[vert_len * vert_h];
00220
00221 XImage *I1 = XCreateImage(dpy, DefaultVisual(dpy, screen),
00222 1, XYBitmap,
00223 0, (char *)vertdata,
00224 vert_w, vert_h, 8, 0);
00225
00226 if (I1 == None) {
00227 cerr<<"RotFont: Cant create ximage."<<endl;
00228 delete m_rotfont;
00229 m_rotfont = 0;
00230 return;
00231 }
00232
00233 I1->byte_order = I1->bitmap_bit_order = MSBFirst;
00234
00235
00236 XGetSubImage(dpy, canvas.drawable(),
00237 boxlen/2, boxlen/2 - vert_h,
00238 vert_w, vert_h, 1, XYPixmap, I1, 0, 0);
00239
00240 I1->format = XYBitmap;
00241
00242
00243 if (dir == 2) {
00244 bit_w = vert_w;
00245 bit_h = vert_h;
00246 } else {
00247 bit_w = vert_h;
00248 bit_h = vert_w;
00249 }
00250
00251
00252 bit_len = (bit_w-1)/8 + 1;
00253
00254 m_rotfont->per_char[ichar-32].glyph.bit_w = bit_w;
00255 m_rotfont->per_char[ichar-32].glyph.bit_h = bit_h;
00256
00257
00258 bitdata = (unsigned char *)calloc((unsigned)(bit_h * bit_len), 1);
00259
00260
00261 XImage *I2 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0,
00262 (char *)bitdata, bit_w, bit_h, 8, 0);
00263
00264 if (I2 == None) {
00265 cerr<<"XFontImp: Cant create ximage!"<<endl;
00266 delete m_rotfont;
00267 m_rotfont = 0;
00268 return;
00269 }
00270
00271 I2->byte_order = I2->bitmap_bit_order = MSBFirst;
00272
00273
00274 for (j = 0; j < bit_h; j++) {
00275 for (i = 0; i < bit_w; i++) {
00276 char val = 0;
00277 if (dir == 1) {
00278 val = vertdata[i*vert_len + (vert_w-j-1)/8] &
00279 (128>>((vert_w-j-1)%8));
00280 } else if (dir == 2) {
00281 val = vertdata[(vert_h-j-1)*vert_len +
00282 (vert_w-i-1)/8] & (128>>((vert_w-i-1)%8));
00283 } else {
00284 val = vertdata[(vert_h-i-1)*vert_len + j/8] &
00285 (128>>(j%8));
00286 }
00287 if (val) {
00288 bitdata[j*bit_len + i/8] = bitdata[j*bit_len + i/8] |
00289 (128>>(i%8));
00290 }
00291 }
00292 }
00293
00294
00295 m_rotfont->per_char[ichar-32].glyph.bm =
00296 XCreatePixmap(dpy, rootwin, bit_w, bit_h, 1);
00297
00298
00299 XPutImage(dpy, m_rotfont->per_char[ichar-32].glyph.bm,
00300 font_gc.gc(), I2, 0, 0, 0, 0, bit_w, bit_h);
00301
00302
00303 XDestroyImage(I1);
00304 XDestroyImage(I2);
00305 }
00306
00307 }
00308
00309 void XFontImp::freeRotFont() {
00310 if (m_rotfont == 0)
00311 return;
00312
00313 for (int ichar = m_rotfont->min_char - 32;
00314 ichar <= m_rotfont->max_char - 32; ++ichar) {
00315 XFreePixmap(App::instance()->display(), m_rotfont->per_char[ichar].glyph.bm);
00316 }
00317
00318 delete m_rotfont;
00319 m_rotfont = 0;
00320 }
00321
00322 void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const {
00323
00324 Display *dpy = App::instance()->display();
00325 static GC my_gc = 0;
00326 int xp, yp, dir, ichar;
00327
00328 if (text == NULL || len<1)
00329 return;
00330
00331 dir = m_rotfont->dir;
00332 if (my_gc == 0)
00333 my_gc = XCreateGC(dpy, w, 0, 0);
00334
00335 XCopyGC(dpy, gc, GCForeground|GCBackground, my_gc);
00336
00337
00338
00339 XSetFillStyle(dpy, my_gc, FillStippled);
00340
00341
00342 for (size_t i = 0; i<len; i++) {
00343 ichar = text[i]-32;
00344
00345
00346 if (ichar >= 0 && ichar<95) {
00347
00348 if (dir == 1) {
00349 xp = x-m_rotfont->per_char[ichar].ascent;
00350 yp = y-m_rotfont->per_char[ichar].rbearing;
00351 } else if (dir == 2) {
00352 xp = x-m_rotfont->per_char[ichar].rbearing;
00353 yp = y-m_rotfont->per_char[ichar].descent+1;
00354 } else {
00355 xp = x-m_rotfont->per_char[ichar].descent+1;
00356 yp = y+m_rotfont->per_char[ichar].lbearing;
00357 }
00358
00359
00360 XSetStipple(dpy, my_gc, m_rotfont->per_char[ichar].glyph.bm);
00361
00362 XSetTSOrigin(dpy, my_gc, xp, yp);
00363
00364 XFillRectangle(dpy, w, my_gc, xp, yp,
00365 m_rotfont->per_char[ichar].glyph.bit_w,
00366 m_rotfont->per_char[ichar].glyph.bit_h);
00367
00368
00369 if (dir == 1)
00370 y -= m_rotfont->per_char[ichar].width;
00371 else if (dir == 2)
00372 x -= m_rotfont->per_char[ichar].width;
00373 else
00374 y += m_rotfont->per_char[ichar].width;
00375 }
00376 }
00377 }
00378
00379
00380 unsigned int XFontImp::rotTextWidth(const char * const text, unsigned int size) const {
00381
00382 if (text == 0)
00383 return 0;
00384
00385 unsigned int width = 0;
00386 for (size_t i = 0; i<size; i++) {
00387 int ichar = text[i] - 32;
00388
00389 if (ichar >= 0 && ichar < 95)
00390 width += m_rotfont->per_char[ichar].width;
00391 }
00392
00393 return width;
00394 }
00395
00396 };