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