aboutsummaryrefslogtreecommitdiff
path: root/src/XFontImp.cc
diff options
context:
space:
mode:
authorfluxgen <fluxgen>2002-11-25 14:07:21 (GMT)
committerfluxgen <fluxgen>2002-11-25 14:07:21 (GMT)
commit99c92a637392a988382559d0b162aed68ab83ba8 (patch)
treed353aa10684ed0814327a64e9aef041510e08a41 /src/XFontImp.cc
parent1fc16d3d3d8a62a9697f4a42044b695707fe5d50 (diff)
downloadfluxbox_pavel-99c92a637392a988382559d0b162aed68ab83ba8.zip
fluxbox_pavel-99c92a637392a988382559d0b162aed68ab83ba8.tar.bz2
fixed rotated text on vertical tab in XFontImp and a rotate function in FontImp interface
Diffstat (limited to 'src/XFontImp.cc')
-rw-r--r--src/XFontImp.cc314
1 files changed, 312 insertions, 2 deletions
diff --git a/src/XFontImp.cc b/src/XFontImp.cc
index 9a57cc7..a263466 100644
--- a/src/XFontImp.cc
+++ b/src/XFontImp.cc
@@ -19,15 +19,18 @@
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE. 20// DEALINGS IN THE SOFTWARE.
21 21
22// $Id: XFontImp.cc,v 1.1 2002/10/13 22:22:14 fluxgen Exp $ 22// $Id: XFontImp.cc,v 1.2 2002/11/25 14:07:21 fluxgen Exp $
23 23
24#include "XFontImp.hh" 24#include "XFontImp.hh"
25#include "BaseDisplay.hh" 25#include "BaseDisplay.hh"
26 26
27#include <X11/Xutil.h>
28
27#include <iostream> 29#include <iostream>
28using namespace std; 30using namespace std;
29 31
30XFontImp::XFontImp(const char *fontname):m_fontstruct(0) { 32XFontImp::XFontImp(const char *fontname):m_rotfont(0), m_fontstruct(0),
33m_angle(0) {
31 if (fontname != 0) 34 if (fontname != 0)
32 load(fontname); 35 load(fontname);
33} 36}
@@ -35,6 +38,17 @@ XFontImp::XFontImp(const char *fontname):m_fontstruct(0) {
35XFontImp::~XFontImp() { 38XFontImp::~XFontImp() {
36 if (m_fontstruct != 0) 39 if (m_fontstruct != 0)
37 XFreeFont(BaseDisplay::getXDisplay(), m_fontstruct); 40 XFreeFont(BaseDisplay::getXDisplay(), m_fontstruct);
41 if (m_rotfont != 0)
42 freeRotFont();
43}
44
45int XFontImp::ascent() const {
46 if (m_fontstruct == 0)
47 return 0;
48 if (m_rotfont != 0)
49 return m_rotfont->max_ascent;
50
51 return m_fontstruct->ascent;
38} 52}
39 53
40bool XFontImp::load(const std::string &fontname) { 54bool XFontImp::load(const std::string &fontname) {
@@ -51,14 +65,26 @@ bool XFontImp::load(const std::string &fontname) {
51void XFontImp::drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const { 65void XFontImp::drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const {
52 if (m_fontstruct == 0) 66 if (m_fontstruct == 0)
53 return; 67 return;
68 // use roated font functions?
69 if (m_rotfont != 0) {
70 drawRotText(w, screen, gc, text, len, x, y);
71 return;
72 }
73
54 Display *disp = BaseDisplay::getXDisplay(); 74 Display *disp = BaseDisplay::getXDisplay();
55 XSetFont(disp, gc, m_fontstruct->fid); 75 XSetFont(disp, gc, m_fontstruct->fid);
56 XDrawString(disp, w, gc, x, y, text, len); 76 XDrawString(disp, w, gc, x, y, text, len);
57} 77}
58 78
59unsigned int XFontImp::textWidth(const char * const text, unsigned int size) const { 79unsigned int XFontImp::textWidth(const char * const text, unsigned int size) const {
80 if (text == 0)
81 return 0;
60 if (m_fontstruct == 0) 82 if (m_fontstruct == 0)
61 return 0; 83 return 0;
84 // check rotated font?
85 if (m_rotfont != 0)
86 return rotTextWidth(text, size);
87
62 return XTextWidth(m_fontstruct, text, size); 88 return XTextWidth(m_fontstruct, text, size);
63} 89}
64 90
@@ -68,3 +94,287 @@ unsigned int XFontImp::height() const {
68 94
69 return m_fontstruct->ascent + m_fontstruct->descent; 95 return m_fontstruct->ascent + m_fontstruct->descent;
70} 96}
97
98void XFontImp::rotate(float angle) {
99 //we must have a font loaded before we rotate
100 if (m_fontstruct == 0)
101 return;
102 if (m_rotfont != 0)
103 freeRotFont();
104 // no need for rotating, use regular font
105 if (angle == 0)
106 return;
107
108 //get positive angle
109 while (angle < 0)
110 angle += 360;
111
112 char val;
113 XImage *I1, *I2;
114 // X system default vars
115 Display *dpy = BaseDisplay::instance()->getXDisplay();
116 Window rootwin = DefaultRootWindow(dpy);
117 int screen = DefaultScreen(dpy);
118
119 GC font_gc;
120 char text[3];
121 int ichar, i, j, index, boxlen = 60;
122 int vert_w, vert_h, vert_len, bit_w, bit_h, bit_len;
123 int min_char, max_char;
124 unsigned char *vertdata, *bitdata;
125 int ascent, descent, lbearing, rbearing;
126
127 // get nearest vertical or horizontal direction
128 int dir = (int)((angle+45.0)/90.0)%4;
129
130 if (dir == 0) // no rotation
131 return;
132
133 // create the depth 1 canvas bitmap
134 Pixmap canvas = XCreatePixmap(dpy, rootwin, boxlen, boxlen, 1);
135
136 // create graphic context for our canvas
137 font_gc = XCreateGC(dpy, canvas, 0, 0);
138
139 XSetBackground(dpy, font_gc, None);
140
141 XSetFont(dpy, font_gc, m_fontstruct->fid);
142
143 // allocate space for rotated font
144 m_rotfont = new(nothrow) XRotFontStruct;
145
146 if (m_rotfont == 0) {
147 cerr<<"RotFont: out of memory"<<endl;
148 return;
149 }
150
151 // determine which characters are defined in font
152 min_char = m_fontstruct->min_char_or_byte2;
153 max_char = m_fontstruct->max_char_or_byte2;
154
155 // we only want printable chars
156 if (min_char<32)
157 min_char = 32;
158 if (max_char>126)
159 max_char = 126;
160
161 /* some overall font data ... */
162 m_rotfont->dir = dir;
163 m_rotfont->min_char = min_char;
164 m_rotfont->max_char = max_char;
165 m_rotfont->max_ascent = m_fontstruct->max_bounds.ascent;
166 m_rotfont->max_descent = m_fontstruct->max_bounds.descent;
167 m_rotfont->height = m_rotfont->max_ascent + m_rotfont->max_descent;
168
169 // font needs rotation
170 // loop through each character
171 for (ichar = min_char; ichar <= max_char; ichar++) {
172 index = ichar - m_fontstruct->min_char_or_byte2;
173
174 // per char dimensions ...
175 ascent = m_rotfont->per_char[ichar-32].ascent = m_fontstruct->per_char[index].ascent;
176 descent = m_rotfont->per_char[ichar-32].descent = m_fontstruct->per_char[index].descent;
177 lbearing = m_rotfont->per_char[ichar-32].lbearing = m_fontstruct->per_char[index].lbearing;
178 rbearing = m_rotfont->per_char[ichar-32].rbearing = m_fontstruct->per_char[index].rbearing;
179 m_rotfont->per_char[ichar-32].width = m_fontstruct->per_char[index].width;
180
181 // some space chars have zero body, but a bitmap can't have
182 if (!ascent && !descent)
183 ascent = m_rotfont->per_char[ichar-32].ascent = 1;
184 if (!lbearing && !rbearing)
185 rbearing = m_rotfont->per_char[ichar-32].rbearing = 1;
186
187 // glyph width and height when vertical
188 vert_w = rbearing - lbearing;
189 vert_h = ascent + descent;
190
191 // width in bytes
192 vert_len = (vert_w-1)/8+1;
193
194 XSetForeground(dpy, font_gc, None);
195 XFillRectangle(dpy, canvas, font_gc, 0, 0, boxlen, boxlen);
196
197 // draw the character centre top right on canvas
198 sprintf(text, "%c", ichar);
199 XSetForeground(dpy, font_gc, 1);
200 XDrawImageString(dpy, canvas, font_gc, boxlen/2 - lbearing,
201 boxlen/2 - descent, text, 1);
202
203 // reserve memory for first XImage
204 vertdata = (unsigned char *) malloc((unsigned)(vert_len*vert_h));
205
206 /* create the XImage ... */
207 I1 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap,
208 0, (char *)vertdata, vert_w, vert_h, 8, 0);
209
210 if (I1 == None) {
211 cerr<<"RotFont: Cant create ximage."<<endl;
212 delete m_rotfont;
213 m_rotfont = 0;
214 return;
215 }
216
217 I1->byte_order = I1->bitmap_bit_order = MSBFirst;
218
219 /* extract character from canvas ... */
220 XGetSubImage(dpy, canvas, boxlen/2, boxlen/2 - vert_h,
221 vert_w, vert_h, 1, XYPixmap, I1, 0, 0);
222 I1->format = XYBitmap;
223
224 /* width, height of rotated character ... */
225 if (dir == 2) {
226 bit_w = vert_w;
227 bit_h = vert_h;
228 } else {
229 bit_w = vert_h;
230 bit_h = vert_w;
231 }
232
233 /* width in bytes ... */
234 bit_len = (bit_w-1)/8 + 1;
235
236 m_rotfont->per_char[ichar-32].glyph.bit_w = bit_w;
237 m_rotfont->per_char[ichar-32].glyph.bit_h = bit_h;
238
239 /* reserve memory for the rotated image ... */
240 bitdata = (unsigned char *)calloc((unsigned)(bit_h * bit_len), 1);
241
242 /* create the image ... */
243 I2 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0,
244 (char *)bitdata, bit_w, bit_h, 8, 0);
245
246 if (I2 == None) {
247 cerr<<"XFontImp: Cant create ximage!"<<endl;
248 delete m_rotfont;
249 m_rotfont = 0;
250 return;
251 }
252
253 I2->byte_order = I2->bitmap_bit_order = MSBFirst;
254
255 /* map vertical data to rotated character ... */
256 for (j = 0; j < bit_h; j++) {
257 for (i = 0; i < bit_w; i++) {
258 /* map bits ... */
259 if (dir == 1) {
260 val = vertdata[i*vert_len + (vert_w-j-1)/8] &
261 (128>>((vert_w-j-1)%8));
262 } else if (dir == 2) {
263 val = vertdata[(vert_h-j-1)*vert_len +
264 (vert_w-i-1)/8] & (128>>((vert_w-i-1)%8));
265 } else {
266 val = vertdata[(vert_h-i-1)*vert_len + j/8] &
267 (128>>(j%8));
268 }
269 if (val) {
270 bitdata[j*bit_len + i/8] = bitdata[j*bit_len + i/8] |
271 (128>>(i%8));
272 }
273 }
274 }
275
276 // create this character's bitmap
277 m_rotfont->per_char[ichar-32].glyph.bm =
278 XCreatePixmap(dpy, rootwin, bit_w, bit_h, 1);
279
280 // put the image into the bitmap
281 XPutImage(dpy, m_rotfont->per_char[ichar-32].glyph.bm,
282 font_gc, I2, 0, 0, 0, 0, bit_w, bit_h);
283
284 // free the image and data
285 XDestroyImage(I1);
286 XDestroyImage(I2);
287 }
288
289 /* free pixmap and GC ... */
290 XFreePixmap(dpy, canvas);
291 XFreeGC(dpy, font_gc);
292
293}
294
295void XFontImp::freeRotFont() {
296 if (m_rotfont == 0)
297 return;
298 // loop through each character and free its pixmap
299 for (int ichar = m_rotfont->min_char - 32;
300 ichar <= m_rotfont->max_char - 32; ++ichar) {
301 XFreePixmap(BaseDisplay::instance()->getXDisplay(), m_rotfont->per_char[ichar].glyph.bm);
302 }
303
304 delete m_rotfont;
305 m_rotfont = 0;
306}
307
308void XFontImp::drawRotText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y) const {
309
310 Display *dpy = BaseDisplay::instance()->getXDisplay();
311 static GC my_gc = 0;
312 int xp, yp, dir, ichar;
313
314 if (text == NULL || len<1)
315 return;
316
317 dir = m_rotfont->dir;
318 if (my_gc == 0)
319 my_gc = XCreateGC(dpy, w, 0, 0);
320
321 XCopyGC(dpy, gc, GCForeground|GCBackground, my_gc);
322
323 // vertical or upside down
324
325 XSetFillStyle(dpy, my_gc, FillStippled);
326
327 // loop through each character in texting
328 for (size_t i = 0; i<len; i++) {
329 ichar = text[i]-32;
330
331 // make sure it's a printing character
332 if (ichar >= 0 && ichar<95) {
333 // suitable offset
334 if (dir == 1) {
335 xp = x-m_rotfont->per_char[ichar].ascent;
336 yp = y-m_rotfont->per_char[ichar].rbearing;
337 } else if (dir == 2) {
338 xp = x-m_rotfont->per_char[ichar].rbearing;
339 yp = y-m_rotfont->per_char[ichar].descent+1;
340 } else {
341 xp = x-m_rotfont->per_char[ichar].descent+1;
342 yp = y+m_rotfont->per_char[ichar].lbearing;
343 }
344
345 // draw the glyph
346 XSetStipple(dpy, my_gc, m_rotfont->per_char[ichar].glyph.bm);
347
348 XSetTSOrigin(dpy, my_gc, xp, yp);
349
350 XFillRectangle(dpy, w, my_gc, xp, yp,
351 m_rotfont->per_char[ichar].glyph.bit_w,
352 m_rotfont->per_char[ichar].glyph.bit_h);
353
354 // advance position
355 if (dir == 1)
356 y -= m_rotfont->per_char[ichar].width;
357 else if (dir == 2)
358 x -= m_rotfont->per_char[ichar].width;
359 else
360 y += m_rotfont->per_char[ichar].width;
361 }
362 }
363}
364
365
366unsigned int XFontImp::rotTextWidth(const char * const text, unsigned int size) const {
367
368 if (text == 0)
369 return 0;
370
371 unsigned int width = 0;
372 for (size_t i = 0; i<size; i++) {
373 int ichar = text[i] - 32;
374 // make sure it's a printing character
375 if (ichar >= 0 && ichar < 95)
376 width += m_rotfont->per_char[ichar].width;
377 }
378
379 return width;
380}