aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/XFontImp.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk/XFontImp.cc')
-rw-r--r--src/FbTk/XFontImp.cc180
1 files changed, 74 insertions, 106 deletions
diff --git a/src/FbTk/XFontImp.cc b/src/FbTk/XFontImp.cc
index eeb0830..1bf54a7 100644
--- a/src/FbTk/XFontImp.cc
+++ b/src/FbTk/XFontImp.cc
@@ -40,8 +40,10 @@ using namespace std;
40 40
41namespace FbTk { 41namespace FbTk {
42 42
43XFontImp::XFontImp(const char *fontname):m_rotfont(0), m_fontstruct(0), 43XFontImp::XFontImp(const char *fontname):m_fontstruct(0) {
44 m_angle(0), m_rotate(true) { 44 for (int i = ROT0; i <= ROT270; ++i)
45 m_rotfonts[i] = 0;
46
45 if (fontname != 0) 47 if (fontname != 0)
46 load(fontname); 48 load(fontname);
47} 49}
@@ -49,20 +51,21 @@ XFontImp::XFontImp(const char *fontname):m_rotfont(0), m_fontstruct(0),
49XFontImp::~XFontImp() { 51XFontImp::~XFontImp() {
50 if (m_fontstruct != 0) 52 if (m_fontstruct != 0)
51 XFreeFont(App::instance()->display(), m_fontstruct); 53 XFreeFont(App::instance()->display(), m_fontstruct);
52 if (m_rotfont != 0) 54
53 freeRotFont(); 55 for (int i = ROT0; i <= ROT270; ++i)
56 if (m_rotfonts[i] != 0)
57 freeRotFont(m_rotfonts[i]);
54} 58}
55 59
56int XFontImp::ascent() const { 60int XFontImp::ascent() const {
57 if (m_fontstruct == 0) 61 if (m_fontstruct == 0)
58 return 0; 62 return 0;
59 if (m_rotfont != 0)
60 return m_rotfont->max_ascent;
61 63
62 return m_fontstruct->ascent; 64 return m_fontstruct->ascent;
63} 65}
64 66
65bool XFontImp::load(const std::string &fontname) { 67bool XFontImp::load(const std::string &fontname) {
68
66 XFontStruct *font = XLoadQueryFont(App::instance()->display(), fontname.c_str()); 69 XFontStruct *font = XLoadQueryFont(App::instance()->display(), fontname.c_str());
67 if (font == 0) 70 if (font == 0)
68 return false; 71 return false;
@@ -71,10 +74,9 @@ bool XFontImp::load(const std::string &fontname) {
71 74
72 m_fontstruct = font; //set new font 75 m_fontstruct = font; //set new font
73 76
74 if (m_rotfont != 0) { 77 for (int i = ROT0; i <= ROT270; ++i)
75 freeRotFont(); // free old rotated font 78 if (m_rotfonts[i] != 0)
76 rotate(m_angle); // allocate new rotated font and rotate it to old angle 79 freeRotFont(m_rotfonts[i]);
77 }
78 80
79 return true; 81 return true;
80} 82}
@@ -84,8 +86,8 @@ void XFontImp::drawText(const FbDrawable &w, int screen, GC gc, const char *text
84 return; 86 return;
85 87
86 // use roated font functions? 88 // use roated font functions?
87 if (m_rotfont != 0 && m_rotate) { 89 if (orient != ROT0 && m_rotfonts[orient] != 0) {
88 drawRotText(w.drawable(), screen, gc, text, len, x, y); 90 drawRotText(w.drawable(), screen, gc, text, len, x, y, orient);
89 return; 91 return;
90 } 92 }
91 93
@@ -97,10 +99,6 @@ unsigned int XFontImp::textWidth(const char * const text, unsigned int size) con
97 if (text == 0 || m_fontstruct == 0) 99 if (text == 0 || m_fontstruct == 0)
98 return 0; 100 return 0;
99 101
100 // check rotated font?
101 if (m_rotfont != 0)
102 return rotTextWidth(text, size);
103
104 return XTextWidth(m_fontstruct, text, size); 102 return XTextWidth(m_fontstruct, text, size);
105} 103}
106 104
@@ -111,28 +109,13 @@ unsigned int XFontImp::height() const {
111 return m_fontstruct->ascent + m_fontstruct->descent; 109 return m_fontstruct->ascent + m_fontstruct->descent;
112} 110}
113 111
114void XFontImp::rotate(int angle) { 112void XFontImp::rotate(FbTk::Orientation orient) {
115 //we must have a font loaded before we rotate 113 //we must have a font loaded before we rotate
116 if (m_fontstruct == 0 || m_fontstruct->per_char == 0) 114 if (m_fontstruct == 0 || m_fontstruct->per_char == 0 || orient == ROT0)
117 return; 115 return;
118 116
119 if (m_rotfont != 0)
120 freeRotFont();
121
122 // no need for rotating, use regular font
123 if (angle == 0) {
124 m_angle = 0;
125 return;
126 }
127
128 _FB_USES_NLS; 117 _FB_USES_NLS;
129 118
130 //get positive angle
131 while (angle < 0)
132 angle += 360;
133
134 m_angle = angle;
135
136 // X system default vars 119 // X system default vars
137 Display *dpy = App::instance()->display(); 120 Display *dpy = App::instance()->display();
138 Window rootwin = DefaultRootWindow(dpy); 121 Window rootwin = DefaultRootWindow(dpy);
@@ -145,12 +128,6 @@ void XFontImp::rotate(int angle) {
145 unsigned char *vertdata, *bitdata; 128 unsigned char *vertdata, *bitdata;
146 int ascent, descent, lbearing, rbearing; 129 int ascent, descent, lbearing, rbearing;
147 130
148 // get nearest vertical or horizontal direction
149 int dir = (int)((angle+45.0)/90.0)%4;
150
151 if (dir == 0) // no rotation
152 return;
153
154 // create the depth 1 canvas bitmap 131 // create the depth 1 canvas bitmap
155 FbTk::FbPixmap canvas(rootwin, boxlen, boxlen, 1); 132 FbTk::FbPixmap canvas(rootwin, boxlen, boxlen, 1);
156 133
@@ -160,9 +137,10 @@ void XFontImp::rotate(int angle) {
160 font_gc.setFont(m_fontstruct->fid); 137 font_gc.setFont(m_fontstruct->fid);
161 138
162 // allocate space for rotated font 139 // allocate space for rotated font
163 m_rotfont = new(nothrow) XRotFontStruct; 140 m_rotfonts[orient] = new(nothrow) XRotFontStruct;
141 XRotFontStruct *rotfont = m_rotfonts[orient];
164 142
165 if (m_rotfont == 0) { 143 if (rotfont == 0) {
166 cerr<<"RotFont: "<<_FBTKTEXT(Error, OutOfMemory, "Out of memory", "Something couldn't allocate memory")<<endl; 144 cerr<<"RotFont: "<<_FBTKTEXT(Error, OutOfMemory, "Out of memory", "Something couldn't allocate memory")<<endl;
167 return; 145 return;
168 } 146 }
@@ -178,12 +156,11 @@ void XFontImp::rotate(int angle) {
178 max_char = 126; 156 max_char = 126;
179 157
180 /* some overall font data ... */ 158 /* some overall font data ... */
181 m_rotfont->dir = dir; 159 rotfont->min_char = min_char;
182 m_rotfont->min_char = min_char; 160 rotfont->max_char = max_char;
183 m_rotfont->max_char = max_char; 161 rotfont->max_ascent = m_fontstruct->max_bounds.ascent;
184 m_rotfont->max_ascent = m_fontstruct->max_bounds.ascent; 162 rotfont->max_descent = m_fontstruct->max_bounds.descent;
185 m_rotfont->max_descent = m_fontstruct->max_bounds.descent; 163 rotfont->height = rotfont->max_ascent + rotfont->max_descent;
186 m_rotfont->height = m_rotfont->max_ascent + m_rotfont->max_descent;
187 164
188 // font needs rotation 165 // font needs rotation
189 // loop through each character 166 // loop through each character
@@ -191,17 +168,17 @@ void XFontImp::rotate(int angle) {
191 index = ichar - m_fontstruct->min_char_or_byte2; 168 index = ichar - m_fontstruct->min_char_or_byte2;
192 169
193 // per char dimensions ... 170 // per char dimensions ...
194 ascent = m_rotfont->per_char[ichar-32].ascent = m_fontstruct->per_char[index].ascent; 171 ascent = rotfont->per_char[ichar-32].ascent = m_fontstruct->per_char[index].ascent;
195 descent = m_rotfont->per_char[ichar-32].descent = m_fontstruct->per_char[index].descent; 172 descent = rotfont->per_char[ichar-32].descent = m_fontstruct->per_char[index].descent;
196 lbearing = m_rotfont->per_char[ichar-32].lbearing = m_fontstruct->per_char[index].lbearing; 173 lbearing = rotfont->per_char[ichar-32].lbearing = m_fontstruct->per_char[index].lbearing;
197 rbearing = m_rotfont->per_char[ichar-32].rbearing = m_fontstruct->per_char[index].rbearing; 174 rbearing = rotfont->per_char[ichar-32].rbearing = m_fontstruct->per_char[index].rbearing;
198 m_rotfont->per_char[ichar-32].width = m_fontstruct->per_char[index].width; 175 rotfont->per_char[ichar-32].width = m_fontstruct->per_char[index].width;
199 176
200 // some space chars have zero body, but a bitmap can't have 177 // some space chars have zero body, but a bitmap can't have
201 if (!ascent && !descent) 178 if (!ascent && !descent)
202 ascent = m_rotfont->per_char[ichar-32].ascent = 1; 179 ascent = rotfont->per_char[ichar-32].ascent = 1;
203 if (!lbearing && !rbearing) 180 if (!lbearing && !rbearing)
204 rbearing = m_rotfont->per_char[ichar-32].rbearing = 1; 181 rbearing = rotfont->per_char[ichar-32].rbearing = 1;
205 182
206 // glyph width and height when vertical 183 // glyph width and height when vertical
207 vert_w = rbearing - lbearing; 184 vert_w = rbearing - lbearing;
@@ -235,8 +212,8 @@ void XFontImp::rotate(int angle) {
235 "XCreateImage failed for some reason") 212 "XCreateImage failed for some reason")
236 << "." << endl; 213 << "." << endl;
237 free(vertdata); 214 free(vertdata);
238 delete m_rotfont; 215 delete rotfont;
239 m_rotfont = 0; 216 m_rotfonts[orient] = 0;
240 return; 217 return;
241 } 218 }
242 219
@@ -250,7 +227,7 @@ void XFontImp::rotate(int angle) {
250 I1->format = XYBitmap; 227 I1->format = XYBitmap;
251 228
252 // width, height of rotated character 229 // width, height of rotated character
253 if (dir == 2) { 230 if (orient == ROT180) {
254 bit_w = vert_w; 231 bit_w = vert_w;
255 bit_h = vert_h; 232 bit_h = vert_h;
256 } else { 233 } else {
@@ -261,8 +238,8 @@ void XFontImp::rotate(int angle) {
261 // width in bytes 238 // width in bytes
262 bit_len = (bit_w-1)/8 + 1; 239 bit_len = (bit_w-1)/8 + 1;
263 240
264 m_rotfont->per_char[ichar-32].glyph.bit_w = bit_w; 241 rotfont->per_char[ichar-32].glyph.bit_w = bit_w;
265 m_rotfont->per_char[ichar-32].glyph.bit_h = bit_h; 242 rotfont->per_char[ichar-32].glyph.bit_h = bit_h;
266 243
267 // reserve memory for the rotated image 244 // reserve memory for the rotated image
268 bitdata = (unsigned char *)calloc((unsigned)(bit_h * bit_len), 1); 245 bitdata = (unsigned char *)calloc((unsigned)(bit_h * bit_len), 1);
@@ -277,8 +254,8 @@ void XFontImp::rotate(int angle) {
277 "XCreateImage failed for some reason") 254 "XCreateImage failed for some reason")
278 << "." << endl; 255 << "." << endl;
279 free(bitdata); 256 free(bitdata);
280 delete m_rotfont; 257 delete rotfont;
281 m_rotfont = 0; 258 m_rotfonts[orient] = 0;
282 return; 259 return;
283 } 260 }
284 261
@@ -288,10 +265,10 @@ void XFontImp::rotate(int angle) {
288 for (j = 0; j < bit_h; j++) { 265 for (j = 0; j < bit_h; j++) {
289 for (i = 0; i < bit_w; i++) { 266 for (i = 0; i < bit_w; i++) {
290 char val = 0; 267 char val = 0;
291 if (dir == 1) { 268 if (orient == ROT270) {
292 val = vertdata[i*vert_len + (vert_w-j-1)/8] & 269 val = vertdata[i*vert_len + (vert_w-j-1)/8] &
293 (128>>((vert_w-j-1)%8)); 270 (128>>((vert_w-j-1)%8));
294 } else if (dir == 2) { 271 } else if (orient == ROT180) {
295 val = vertdata[(vert_h-j-1)*vert_len + 272 val = vertdata[(vert_h-j-1)*vert_len +
296 (vert_w-i-1)/8] & (128>>((vert_w-i-1)%8)); 273 (vert_w-i-1)/8] & (128>>((vert_w-i-1)%8));
297 } else { 274 } else {
@@ -306,11 +283,11 @@ void XFontImp::rotate(int angle) {
306 } 283 }
307 284
308 // create this character's bitmap 285 // create this character's bitmap
309 m_rotfont->per_char[ichar-32].glyph.bm = 286 rotfont->per_char[ichar-32].glyph.bm =
310 XCreatePixmap(dpy, rootwin, bit_w, bit_h, 1); 287 XCreatePixmap(dpy, rootwin, bit_w, bit_h, 1);
311 288
312 // put the image into the bitmap 289 // put the image into the bitmap
313 XPutImage(dpy, m_rotfont->per_char[ichar-32].glyph.bm, 290 XPutImage(dpy, rotfont->per_char[ichar-32].glyph.bm,
314 font_gc.gc(), I2, 0, 0, 0, 0, bit_w, bit_h); 291 font_gc.gc(), I2, 0, 0, 0, 0, bit_w, bit_h);
315 292
316 // free the image and data 293 // free the image and data
@@ -320,29 +297,28 @@ void XFontImp::rotate(int angle) {
320 297
321} 298}
322 299
323void XFontImp::freeRotFont() { 300void XFontImp::freeRotFont(XRotFontStruct *rotfont) {
324 if (m_rotfont == 0)
325 return;
326 // loop through each character and free its pixmap 301 // loop through each character and free its pixmap
327 for (int ichar = m_rotfont->min_char - 32; 302 for (int ichar = rotfont->min_char - 32;
328 ichar <= m_rotfont->max_char - 32; ++ichar) { 303 ichar <= rotfont->max_char - 32; ++ichar) {
329 XFreePixmap(App::instance()->display(), m_rotfont->per_char[ichar].glyph.bm); 304 XFreePixmap(App::instance()->display(), rotfont->per_char[ichar].glyph.bm);
330 } 305 }
331 306
332 delete m_rotfont; 307 delete rotfont;
333 m_rotfont = 0; 308 rotfont = 0;
334} 309}
335 310
336void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const { 311void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y, FbTk::Orientation orient) const {
337 312
338 Display *dpy = App::instance()->display(); 313 Display *dpy = App::instance()->display();
339 static GC my_gc = 0; 314 static GC my_gc = 0;
340 int xp, yp, dir, ichar; 315 int xp, yp, ichar;
316
317 XRotFontStruct *rotfont = m_rotfonts[orient];
341 318
342 if (text == NULL || len<1) 319 if (text == NULL || len<1)
343 return; 320 return;
344 321
345 dir = m_rotfont->dir;
346 if (my_gc == 0) 322 if (my_gc == 0)
347 my_gc = XCreateGC(dpy, w, 0, 0); 323 my_gc = XCreateGC(dpy, w, 0, 0);
348 324
@@ -359,52 +335,44 @@ void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size
359 // make sure it's a printing character 335 // make sure it's a printing character
360 if (ichar >= 0 && ichar<95) { 336 if (ichar >= 0 && ichar<95) {
361 // suitable offset 337 // suitable offset
362 if (dir == 1) { 338 if (orient == ROT270) {
363 xp = x-m_rotfont->per_char[ichar].ascent; 339 xp = x-rotfont->per_char[ichar].ascent;
364 yp = y-m_rotfont->per_char[ichar].rbearing; 340 yp = y-rotfont->per_char[ichar].rbearing;
365 } else if (dir == 2) { 341 } else if (orient == ROT180) {
366 xp = x-m_rotfont->per_char[ichar].rbearing; 342 xp = x-rotfont->per_char[ichar].rbearing;
367 yp = y-m_rotfont->per_char[ichar].descent+1; 343 yp = y-rotfont->per_char[ichar].descent+1;
368 } else { 344 } else { // ROT90
369 xp = x-m_rotfont->per_char[ichar].descent+1; 345 xp = x-rotfont->per_char[ichar].descent;
370 yp = y+m_rotfont->per_char[ichar].lbearing; 346 yp = y+rotfont->per_char[ichar].lbearing;
371 } 347 }
372 348
373 // draw the glyph 349 // draw the glyph
374 XSetStipple(dpy, my_gc, m_rotfont->per_char[ichar].glyph.bm); 350 XSetStipple(dpy, my_gc, rotfont->per_char[ichar].glyph.bm);
375 351
376 XSetTSOrigin(dpy, my_gc, xp, yp); 352 XSetTSOrigin(dpy, my_gc, xp, yp);
377 353
378 XFillRectangle(dpy, w, my_gc, xp, yp, 354 XFillRectangle(dpy, w, my_gc, xp, yp,
379 m_rotfont->per_char[ichar].glyph.bit_w, 355 rotfont->per_char[ichar].glyph.bit_w,
380 m_rotfont->per_char[ichar].glyph.bit_h); 356 rotfont->per_char[ichar].glyph.bit_h);
381 357
382 // advance position 358 // advance position
383 if (dir == 1) 359 if (orient == ROT270)
384 y -= m_rotfont->per_char[ichar].width; 360 y -= rotfont->per_char[ichar].width;
385 else if (dir == 2) 361 else if (orient == ROT180)
386 x -= m_rotfont->per_char[ichar].width; 362 x -= rotfont->per_char[ichar].width;
387 else 363 else
388 y += m_rotfont->per_char[ichar].width; 364 y += rotfont->per_char[ichar].width;
389 } 365 }
390 } 366 }
391} 367}
392 368
393 369
394unsigned int XFontImp::rotTextWidth(const char * const text, unsigned int size) const { 370bool XFontImp::validOrientation(FbTk::Orientation orient) {
395 371 if (orient == ROT0 || m_rotfonts[orient])
396 if (text == 0) 372 return true;
397 return 0;
398
399 unsigned int width = 0;
400 for (size_t i = 0; i<size; i++) {
401 int ichar = text[i] - 32;
402 // make sure it's a printing character
403 if (ichar >= 0 && ichar < 95)
404 width += m_rotfont->per_char[ichar].width;
405 }
406 373
407 return width; 374 rotate(orient);
375 return m_rotfonts[orient] != 0;
408} 376}
409 377
410}; 378};