aboutsummaryrefslogtreecommitdiff
path: root/src/DrawUtil.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/DrawUtil.cc')
-rw-r--r--src/DrawUtil.cc369
1 files changed, 2 insertions, 367 deletions
diff --git a/src/DrawUtil.cc b/src/DrawUtil.cc
index 8c41bc2..868e4fa 100644
--- a/src/DrawUtil.cc
+++ b/src/DrawUtil.cc
@@ -19,7 +19,7 @@
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: DrawUtil.cc,v 1.8 2002/11/12 22:44:17 fluxgen Exp $ 22// $Id: DrawUtil.cc,v 1.9 2002/11/25 14:00:20 fluxgen Exp $
23 23
24#ifdef HAVE_CONFIG_H 24#ifdef HAVE_CONFIG_H
25#include "config.h" 25#include "config.h"
@@ -37,372 +37,7 @@
37 37
38using namespace std; 38using namespace std;
39 39
40namespace DrawUtil 40namespace DrawUtil {
41{
42 41
43// ----------------------------------------------------------------------
44// xvertext, Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma)
45// ----------------------------------------------------------------------
46//------- XRotLoadFont -------------------
47// Load the rotated version of a given font
48//----------------------------------------
49XRotFontStruct *XRotLoadFont(Display *dpy, char *fontname, float angle) {
50 char val;
51 XImage *I1, *I2;
52 Pixmap canvas;
53 Window root;
54 int screen;
55 GC font_gc;
56 char text[3];/*, errstr[300];*/
57 XFontStruct *fontstruct;
58 XRotFontStruct *rotfont;
59 int ichar, i, j, index, boxlen = 60, dir;
60 int vert_w, vert_h, vert_len, bit_w, bit_h, bit_len;
61 int min_char, max_char;
62 unsigned char *vertdata, *bitdata;
63 int ascent, descent, lbearing, rbearing;
64 int on = 1, off = 0;
65
66 /* make angle positive ... */
67 if (angle < 0) do angle += 360; while (angle < 0);
68
69 /* get nearest vertical or horizontal direction ... */
70 dir = (int)((angle+45.)/90.)%4;
71
72 /* useful macros ... */
73 screen = DefaultScreen(dpy);
74 root = DefaultRootWindow(dpy);
75
76 /* create the depth 1 canvas bitmap ... */
77 canvas = XCreatePixmap(dpy, root, boxlen, boxlen, 1);
78
79 /* create a GC ... */
80 font_gc = XCreateGC(dpy, canvas, 0, 0);
81 XSetBackground(dpy, font_gc, off);
82
83 /* load the font ... */
84 fontstruct = XLoadQueryFont(dpy, fontname);
85 if (fontstruct == 0 || fontstruct->per_char == 0) {
86 cerr<<"Fluxbox::DrawUtil: No font"<<endl;
87 return 0;
88 }
89
90 XSetFont(dpy, font_gc, fontstruct->fid);
91
92 /* allocate space for rotated font ... */
93 rotfont = (XRotFontStruct *)malloc((unsigned)sizeof(XRotFontStruct));
94
95 if (rotfont == 0) {
96 cerr<<"Fluxbox::DrawUtil: out of memory"<<endl;
97 return 0;
98 }
99
100 /* determine which characters are defined in font ... */
101 min_char = fontstruct->min_char_or_byte2;
102 max_char = fontstruct->max_char_or_byte2;
103
104 /* we only want printing characters ... */
105 if (min_char<32) min_char = 32;
106 if (max_char>126) max_char = 126;
107
108 /* some overall font data ... */
109 rotfont->name = StringUtil::strdup(fontname);
110 rotfont->dir = dir;
111 rotfont->min_char = min_char;
112 rotfont->max_char = max_char;
113 rotfont->max_ascent = fontstruct->max_bounds.ascent;
114 rotfont->max_descent = fontstruct->max_bounds.descent;
115 rotfont->height = rotfont->max_ascent+rotfont->max_descent;
116
117 /* remember xfontstruct for `normal' text ... */
118 if (dir == 0)
119 rotfont->xfontstruct = fontstruct;
120 else {
121 /* font needs rotation ... */
122 /* loop through each character ... */
123 for (ichar = min_char; ichar <= max_char; ichar++) {
124 index = ichar-fontstruct->min_char_or_byte2;
125
126 /* per char dimensions ... */
127 ascent = rotfont->per_char[ichar-32].ascent =
128 fontstruct->per_char[index].ascent;
129 descent = rotfont->per_char[ichar-32].descent =
130 fontstruct->per_char[index].descent;
131 lbearing = rotfont->per_char[ichar-32].lbearing =
132 fontstruct->per_char[index].lbearing;
133 rbearing = rotfont->per_char[ichar-32].rbearing =
134 fontstruct->per_char[index].rbearing;
135 rotfont->per_char[ichar-32].width =
136 fontstruct->per_char[index].width;
137
138 /* some space chars have zero body, but a bitmap can't have ... */
139 if (!ascent && !descent)
140 ascent = rotfont->per_char[ichar-32].ascent = 1;
141 if (!lbearing && !rbearing)
142 rbearing = rotfont->per_char[ichar-32].rbearing = 1;
143
144 /* glyph width and height when vertical ... */
145 vert_w = rbearing-lbearing;
146 vert_h = ascent+descent;
147
148 /* width in bytes ... */
149 vert_len = (vert_w-1)/8+1;
150
151 XSetForeground(dpy, font_gc, off);
152 XFillRectangle(dpy, canvas, font_gc, 0, 0, boxlen, boxlen);
153
154 /* draw the character centre top right on canvas ... */
155 sprintf(text, "%c", ichar);
156 XSetForeground(dpy, font_gc, on);
157 XDrawImageString(dpy, canvas, font_gc, boxlen/2 - lbearing,
158 boxlen/2 - descent, text, 1);
159
160 /* reserve memory for first XImage ... */
161 vertdata = (unsigned char *) malloc((unsigned)(vert_len*vert_h));
162
163 /* create the XImage ... */
164 I1 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap,
165 0, (char *)vertdata, vert_w, vert_h, 8, 0);
166
167 if (I1 == NULL) {
168 cerr<<"Fluxbox::DrawUtil: Cant create ximage."<<endl;
169 return NULL;
170 }
171
172 I1->byte_order = I1->bitmap_bit_order = MSBFirst;
173
174 /* extract character from canvas ... */
175 XGetSubImage(dpy, canvas, boxlen/2, boxlen/2-vert_h,
176 vert_w, vert_h, 1, XYPixmap, I1, 0, 0);
177 I1->format = XYBitmap;
178
179 /* width, height of rotated character ... */
180 if (dir == 2) {
181 bit_w = vert_w;
182 bit_h = vert_h;
183 } else {
184 bit_w = vert_h;
185 bit_h = vert_w;
186 }
187
188 /* width in bytes ... */
189 bit_len = (bit_w-1)/8 + 1;
190
191 rotfont->per_char[ichar-32].glyph.bit_w = bit_w;
192 rotfont->per_char[ichar-32].glyph.bit_h = bit_h;
193
194 /* reserve memory for the rotated image ... */
195 bitdata = (unsigned char *)calloc((unsigned)(bit_h*bit_len), 1);
196
197 /* create the image ... */
198 I2 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0,
199 (char *)bitdata, bit_w, bit_h, 8, 0);
200
201 if (I2 == NULL) {
202 cerr<<"Font::DrawUtil: Cant create ximage!"<<endl;
203 return 0;
204 }
205
206 I2->byte_order = I2->bitmap_bit_order = MSBFirst;
207
208 /* map vertical data to rotated character ... */
209 for (j = 0; j < bit_h; j++) {
210 for (i = 0; i < bit_w; i++) {
211 /* map bits ... */
212 if (dir == 1) {
213 val = vertdata[i*vert_len + (vert_w-j-1)/8] &
214 (128>>((vert_w-j-1)%8));
215 } else if (dir == 2) {
216 val = vertdata[(vert_h-j-1)*vert_len +
217 (vert_w-i-1)/8] & (128>>((vert_w-i-1)%8));
218 } else {
219 val = vertdata[(vert_h-i-1)*vert_len + j/8] &
220 (128>>(j%8));
221 }
222 if (val) {
223 bitdata[j*bit_len + i/8] = bitdata[j*bit_len + i/8] |
224 (128>>(i%8));
225 }
226 }
227 }
228
229 /* create this character's bitmap ... */
230 rotfont->per_char[ichar-32].glyph.bm =
231 XCreatePixmap(dpy, root, bit_w, bit_h, 1);
232
233 /* put the image into the bitmap ... */
234 XPutImage(dpy, rotfont->per_char[ichar-32].glyph.bm,
235 font_gc, I2, 0, 0, 0, 0, bit_w, bit_h);
236
237 /* free the image and data ... */
238 XDestroyImage(I1);
239 XDestroyImage(I2);
240 /* free((char *)bitdata); -- XDestroyImage does this
241 free((char *)vertdata);*/
242 }
243 XFreeFont(dpy, fontstruct);
244 }
245
246 /* free pixmap and GC ... */
247 XFreePixmap(dpy, canvas);
248 XFreeGC(dpy, font_gc);
249
250 return rotfont;
251}
252
253//------- XRotUnloadFont -----------------
254// Free the resources associated with a
255// rotated font
256//----------------------------------------
257void XRotUnloadFont(Display *dpy, XRotFontStruct *rotfont)
258{
259 int ichar;
260
261 if (rotfont->dir == 0)
262 XFreeFont(dpy, rotfont->xfontstruct);
263 else {
264 /* loop through each character, freeing its pixmap ... */
265 for (ichar = rotfont->min_char-32; ichar <= rotfont->max_char-32;
266 ichar++)
267 XFreePixmap(dpy, rotfont->per_char[ichar].glyph.bm);
268 }
269
270 free((char *)rotfont->name);
271 free((char *)rotfont);
272}
273
274//------- XRotTextWidth ------------------
275// Returns the width of a rotated string
276//----------------------------------------
277unsigned int XRotTextWidth(XRotFontStruct *rotfont, const char *str, int len)
278{
279 int i, width = 0, ichar;
280
281 if (str == NULL)
282 return 0;
283
284 if (rotfont->dir == 0)
285 width = XTextWidth(rotfont->xfontstruct, str, strlen(str));
286 else {
287 for (i = 0; i<len; i++) {
288 ichar = str[i]-32;
289
290 /* make sure it's a printing character ... */
291 if (ichar >= 0 && ichar<95)
292 width += rotfont->per_char[ichar].width;
293 }
294 }
295 return width;
296}
297
298
299//------- XRotDrawString -----------------
300// A front end to XRotDrawString : mimics XDrawString
301//----------------------------------------
302void XRotDrawString(Display *dpy, XRotFontStruct *rotfont, Drawable drawable,
303 GC gc, int x, int y, const char *str, int len)
304{
305 static GC my_gc = 0;
306 int i, xp, yp, dir, ichar;
307
308 if (str == NULL || len<1)
309 return;
310
311 dir = rotfont->dir;
312 if (my_gc == 0)
313 my_gc = XCreateGC(dpy, drawable, 0, 0);
314
315 XCopyGC(dpy, gc, GCForeground|GCBackground, my_gc);
316
317 /* a horizontal string is easy ... */
318 if (dir == 0) {
319 XSetFillStyle(dpy, my_gc, FillSolid);
320 XSetFont(dpy, my_gc, rotfont->xfontstruct->fid);
321 XDrawString(dpy, drawable, my_gc, x, y, str, len);
322 return;
323 }
324
325 /* vertical or upside down ... */
326
327 XSetFillStyle(dpy, my_gc, FillStippled);
328
329 /* loop through each character in string ... */
330 for (i = 0; i<len; i++) {
331 ichar = str[i]-32;
332
333 /* make sure it's a printing character ... */
334 if (ichar >= 0 && ichar<95) {
335 /* suitable offset ... */
336 if (dir == 1) {
337 xp = x-rotfont->per_char[ichar].ascent;
338 yp = y-rotfont->per_char[ichar].rbearing;
339 } else if (dir == 2) {
340 xp = x-rotfont->per_char[ichar].rbearing;
341 yp = y-rotfont->per_char[ichar].descent+1;
342 } else {
343 xp = x-rotfont->per_char[ichar].descent+1;
344 yp = y+rotfont->per_char[ichar].lbearing;
345 }
346
347 /* draw the glyph ... */
348 XSetStipple(dpy, my_gc, rotfont->per_char[ichar].glyph.bm);
349
350 XSetTSOrigin(dpy, my_gc, xp, yp);
351
352 XFillRectangle(dpy, drawable, my_gc, xp, yp,
353 rotfont->per_char[ichar].glyph.bit_w,
354 rotfont->per_char[ichar].glyph.bit_h);
355
356 /* advance position ... */
357 if (dir == 1)
358 y -= rotfont->per_char[ichar].width;
359 else if (dir == 2)
360 x -= rotfont->per_char[ichar].width;
361 else
362 y += rotfont->per_char[ichar].width;
363 }
364 }
365}
366
367void DrawRotString(Display *display, Window w, GC gc, XRotFontStruct *font,
368 unsigned int align, unsigned int text_w,
369 unsigned int size_w, unsigned int size_h,
370 unsigned int bevel_w, const char *text) {
371
372 assert(display);
373 assert(font);
374
375 if (!text || text_w<1 || size_w < 1)
376 return;
377
378 unsigned int l = text_w;
379 int dlen = strlen(text);
380 int dx = bevel_w * 2;
381
382 if (text_w > size_w) {
383 for (; dlen >= 0; dlen--) {
384 l = XRotTextWidth(font, text, dlen);
385
386 l += (dx * 4);
387
388 if (l < size_h)
389 break;
390 }
391 }
392
393 if (align == DrawUtil::Font::RIGHT)
394 size_h = l;
395 else if (align == DrawUtil::Font::CENTER)
396 size_h = (size_h + l) / 2;
397 else //LEFT
398 size_h -= (dx * 4);
399
400 // To get it in the "center" of the tab
401 size_w = (size_w + XRotTextWidth(font, "/", 1)) / 2;
402
403 //Draw title to m_tabwin
404 XClearWindow(display, w);
405 XRotDrawString(display, font, w, gc, size_w, size_h, text, dlen);
406}
407 42
408}; //end namespace DrawUtil 43}; //end namespace DrawUtil