diff options
Diffstat (limited to 'src/FbTk/XFontImp.cc')
-rw-r--r-- | src/FbTk/XFontImp.cc | 180 |
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 | ||
41 | namespace FbTk { | 41 | namespace FbTk { |
42 | 42 | ||
43 | XFontImp::XFontImp(const char *fontname):m_rotfont(0), m_fontstruct(0), | 43 | XFontImp::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), | |||
49 | XFontImp::~XFontImp() { | 51 | XFontImp::~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 | ||
56 | int XFontImp::ascent() const { | 60 | int 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 | ||
65 | bool XFontImp::load(const std::string &fontname) { | 67 | bool 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 | ||
114 | void XFontImp::rotate(int angle) { | 112 | void 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 | ||
323 | void XFontImp::freeRotFont() { | 300 | void 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 | ||
336 | void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const { | 311 | void 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 | ||
394 | unsigned int XFontImp::rotTextWidth(const char * const text, unsigned int size) const { | 370 | bool 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 | }; |