~ubuntu-branches/ubuntu/jaunty/flwm/jaunty

1 by Tommi Virtanen
Import upstream version 1.00
1
// Rotated text drawing with X.
2
3
// Original code:
4
// Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma) */
5
//
6
// Modifications for fltk:
7
// Copyright (c) 1997 Bill Spitzak (spitzak@d2.com)
8
// Modifications are to draw using the current fl_font.  All fonts
9
// used are cached in local structures.  This can get real expensive,
10
// use "
11
12
/* xvertext, Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma)
13
 *
14
 * Permission to use, copy, modify, and distribute this software and its
15
 * documentation for any purpose and without fee is hereby granted, provided
16
 * that the above copyright notice appear in all copies and that both the
17
 * copyright notice and this permission notice appear in supporting
18
 * documentation.  All work developed as a consequence of the use of
19
 * this program should duly acknowledge such use. No representations are
20
 * made about the suitability of this software for any purpose.  It is
21
 * provided "as is" without express or implied warranty.
22
 */
23
24
// if not defined then portions not used by flwm are included:
25
#define FLWM 1
26
27
/* ********************************************************************** */
28
29
#include <FL/x.H>
1.1.1 by Bill Allombert
Import upstream version 1.01
30
#if FL_MAJOR_VERSION < 2
31
# define XWindow Window
32
#endif
1 by Tommi Virtanen
Import upstream version 1.00
33
#include <FL/fl_draw.H>
34
#include "Rotated.H"
35
#include <stdlib.h>
36
#include <string.h>
37
#include <stdio.h>
38
39
struct BitmapStruct {
40
  int			 bit_w;
41
  int			 bit_h;
42
  Pixmap bm;
43
};
44
45
struct XRotCharStruct {
46
  int			 ascent;
47
  int			 descent;
48
  int			 lbearing;
49
  int			 rbearing;
50
  int			 width;
51
  BitmapStruct	 glyph;
52
};
53
54
struct XRotFontStruct {
55
  int			 dir;
56
  int			 height;
57
  int			 max_ascent;
58
  int			 max_descent;
59
  int			 max_char;
60
  int			 min_char;
61
  XFontStruct*		 xfontstruct;
62
  XRotCharStruct	 per_char[256];
63
};
64
65
/* *** Load the rotated version of a given font *** */
66
 
67
static XRotFontStruct*
68
XRotLoadFont(Display *dpy, XFontStruct* fontstruct, int dir)
69
{
70
  char val;
71
  XImage *I1, *I2;
72
  Pixmap canvas;
1.1.1 by Bill Allombert
Import upstream version 1.01
73
  XWindow root;
1 by Tommi Virtanen
Import upstream version 1.00
74
  int screen;
75
  GC font_gc;
76
  char text[3];/*, errstr[300];*/
77
  
78
  XRotFontStruct *rotfont;
79
  int ichar, i, j, index, boxlen = 60;
80
  int vert_w, vert_h, vert_len, bit_w, bit_h, bit_len;
81
  int min_char, max_char;
82
  unsigned char *vertdata, *bitdata;
83
  int ascent, descent, lbearing, rbearing;
84
  int on = 1, off = 0;
85
86
  /* useful macros ... */
87
  screen = DefaultScreen(dpy);
88
  root = DefaultRootWindow(dpy);
89
90
  /* create the depth 1 canvas bitmap ... */
91
  canvas = XCreatePixmap(dpy, root, boxlen, boxlen, 1);
92
 
93
  /* create a GC ... */
94
  font_gc = XCreateGC(dpy, canvas, 0, 0);
95
  XSetBackground(dpy, font_gc, off);
96
97
  XSetFont(dpy, font_gc, fontstruct->fid);
98
99
  /* allocate space for rotated font ... */
100
  rotfont = (XRotFontStruct *)malloc((unsigned)sizeof(XRotFontStruct));
101
   
102
  /* determine which characters are defined in font ... */
103
  min_char = fontstruct->min_char_or_byte2; 
104
  if (min_char<0)  min_char = 0;
105
  rotfont->min_char = min_char;
106
  max_char = fontstruct->max_char_or_byte2;
107
  if (max_char>255) max_char = 255;
108
  rotfont->max_char = max_char;
109
     
110
  /* some overall font data ... */
111
  rotfont->dir = dir;
112
  rotfont->max_ascent = fontstruct->max_bounds.ascent;
113
  rotfont->max_descent = fontstruct->max_bounds.descent;   
114
  rotfont->height = rotfont->max_ascent+rotfont->max_descent;
115
116
  rotfont->xfontstruct = fontstruct;
117
  /* remember xfontstruct for `normal' text ... */
118
  if (dir != 0) {
119
    /* font needs rotation ... */
120
    /* loop through each character ... */
121
    for (ichar = min_char; ichar <= max_char; ichar++) {
122
123
      index = ichar-fontstruct->min_char_or_byte2;
2.1.1 by Bill Allombert
* NMU (playing at home the Debcamp BSP).
124
1.1.1 by Bill Allombert
Import upstream version 1.01
125
      XCharStruct* charstruct;
126
      if (fontstruct->per_char)
127
	charstruct = fontstruct->per_char+index;
128
      else
2.1.1 by Bill Allombert
* NMU (playing at home the Debcamp BSP).
129
	charstruct = &fontstruct->min_bounds;
130
1 by Tommi Virtanen
Import upstream version 1.00
131
      /* per char dimensions ... */
1.1.1 by Bill Allombert
Import upstream version 1.01
132
      ascent =   rotfont->per_char[ichar].ascent   = charstruct->ascent;
133
      descent =  rotfont->per_char[ichar].descent  = charstruct->descent;
134
      lbearing = rotfont->per_char[ichar].lbearing = charstruct->lbearing;
135
      rbearing = rotfont->per_char[ichar].rbearing = charstruct->rbearing;
136
                 rotfont->per_char[ichar].width    = charstruct->width;
1 by Tommi Virtanen
Import upstream version 1.00
137
138
      /* some space chars have zero body, but a bitmap can't have ... */
139
      if (!ascent && !descent)   
140
	ascent =   rotfont->per_char[ichar].ascent =   1;
141
      if (!lbearing && !rbearing) 
142
	rbearing = rotfont->per_char[ichar].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) ... do something here
168
  
169
      I1->byte_order = I1->bitmap_bit_order = MSBFirst;
170
   
171
      /* extract character from canvas ... */
172
      XGetSubImage(dpy, canvas, boxlen/2, boxlen/2-vert_h,
173
		   vert_w, vert_h, 1, XYPixmap, I1, 0, 0);
174
      I1->format = XYBitmap; 
175
 
176
      /* width, height of rotated character ... */
177
      if (dir == 2) { 
178
	bit_w = vert_w;
179
	bit_h = vert_h; 
180
      } else {
181
	bit_w = vert_h;
182
	bit_h = vert_w; 
183
      }
184
185
      /* width in bytes ... */
186
      bit_len = (bit_w-1)/8 + 1;
187
188
      rotfont->per_char[ichar].glyph.bit_w = bit_w;
189
      rotfont->per_char[ichar].glyph.bit_h = bit_h;
190
191
      /* reserve memory for the rotated image ... */
192
      bitdata = (unsigned char *)calloc((unsigned)(bit_h*bit_len), 1);
193
194
      /* create the image ... */
195
      I2 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0,
196
			(char *)bitdata, bit_w, bit_h, 8, 0); 
197
 
198
//    if (I2 == NULL) ... error
199
200
      I2->byte_order = I2->bitmap_bit_order = MSBFirst;
201
 
202
      /* map vertical data to rotated character ... */
203
      for (j = 0; j < bit_h; j++) {
204
	for (i = 0; i < bit_w; i++) {
205
	  /* map bits ... */
206
	  if (dir == 1)
207
	    val = vertdata[i*vert_len + (vert_w-j-1)/8] &
208
	      (128>>((vert_w-j-1)%8));
209
   
210
	  else if (dir == 2)
211
	    val = vertdata[(vert_h-j-1)*vert_len + (vert_w-i-1)/8] &
212
	      (128>>((vert_w-i-1)%8));
213
                    
214
	  else 
215
	    val = vertdata[(vert_h-i-1)*vert_len + j/8] & 
216
	      (128>>(j%8));
217
        
218
	  if (val) 
219
	    bitdata[j*bit_len + i/8] = bitdata[j*bit_len + i/8] |
220
	      (128>>(i%8));
221
	}
222
      }
223
   
224
      /* create this character's bitmap ... */
225
      rotfont->per_char[ichar].glyph.bm = 
226
	XCreatePixmap(dpy, root, bit_w, bit_h, 1);
227
     
228
      /* put the image into the bitmap ... */
229
      XPutImage(dpy, rotfont->per_char[ichar].glyph.bm, 
230
		font_gc, I2, 0, 0, 0, 0, bit_w, bit_h);
231
  
232
      /* free the image and data ... */
233
      XDestroyImage(I1);
234
      XDestroyImage(I2);
235
      /*      free((char *)bitdata);  -- XDestroyImage does this
236
	      free((char *)vertdata);*/
237
    }
238
239
  }
240
  
241
  for (ichar = 0; ichar < min_char; ichar++)
1.1.1 by Bill Allombert
Import upstream version 1.01
242
    rotfont->per_char[ichar] = rotfont->per_char[int('?')];
1 by Tommi Virtanen
Import upstream version 1.00
243
  for (ichar = max_char+1; ichar < 256; ichar++)
1.1.1 by Bill Allombert
Import upstream version 1.01
244
    rotfont->per_char[ichar] = rotfont->per_char[int('?')];
1 by Tommi Virtanen
Import upstream version 1.00
245
246
  /* free pixmap and GC ... */
247
  XFreePixmap(dpy, canvas);
248
  XFreeGC(dpy, font_gc);
249
250
  return rotfont;
251
}
252
253
/* *** Free the resources associated with a rotated font *** */
254
255
static void XRotUnloadFont(Display *dpy, XRotFontStruct *rotfont)
256
{
257
  int ichar;
258
259
  if (rotfont->dir != 0) {
260
    /* loop through each character, freeing its pixmap ... */
261
    for (ichar = rotfont->min_char; ichar <= rotfont->max_char; ichar++)
262
      XFreePixmap(dpy, rotfont->per_char[ichar].glyph.bm);
263
  }
264
  /* rotfont should never be referenced again ... */
265
  free((char *)rotfont);
266
}
267
268
/* ---------------------------------------------------------------------- */
269
270
/* *** A front end to XRotPaintString : mimics XDrawString *** */
271
272
static void
273
XRotDrawString(Display *dpy, XRotFontStruct *rotfont, Drawable drawable,
274
	       GC gc, int x, int y, const char *str, int len)
275
{            
276
  int i, xp, yp, dir, ichar;
277
278
  if (str == NULL || len<1) return;
279
280
  dir = rotfont->dir;
281
282
  /* a horizontal string is easy ... */
283
  if (dir == 0) {
284
    XSetFont(dpy, gc, rotfont->xfontstruct->fid);
285
    XDrawString(dpy, drawable, gc, x, y, str, len);
286
    return;
287
  }
288
289
  /* vertical or upside down ... */
290
291
  XSetFillStyle(dpy, gc, FillStippled);
292
293
  /* loop through each character in string ... */
294
  for (i = 0; i<len; i++) {
295
    ichar = ((unsigned char*)str)[i];
296
297
    /* suitable offset ... */
298
    if (dir == 1) {
299
      xp = x-rotfont->per_char[ichar].ascent;
300
      yp = y-rotfont->per_char[ichar].rbearing; 
301
    }
302
    else if (dir == 2) {
303
      xp = x-rotfont->per_char[ichar].rbearing;
304
      yp = y-rotfont->per_char[ichar].descent+1; 
305
    }
306
    else {
307
      xp = x-rotfont->per_char[ichar].descent+1;  
308
      yp = y+rotfont->per_char[ichar].lbearing; 
309
    }
310
                   
311
    /* draw the glyph ... */
312
    XSetStipple(dpy, gc, rotfont->per_char[ichar].glyph.bm);
313
314
    XSetTSOrigin(dpy, gc, xp, yp);
315
316
    XFillRectangle(dpy, drawable, gc, xp, yp,
317
		   rotfont->per_char[ichar].glyph.bit_w,
318
		   rotfont->per_char[ichar].glyph.bit_h);
319
320
    /* advance position ... */
321
    if (dir == 1)
322
      y -= rotfont->per_char[ichar].width;
323
    else if (dir == 2)
324
      x -= rotfont->per_char[ichar].width;
325
    else 
326
      y += rotfont->per_char[ichar].width;
327
  }
328
  XSetFillStyle(dpy, gc, FillSolid);
329
}
330
331
#ifndef FLWM
332
/* *** Return the width of a string *** */
333
334
static int XRotTextWidth(XRotFontStruct *rotfont, const char *str, int len)
335
{
336
  int i, width = 0, ichar;
337
338
  if (str == NULL) return 0;
339
340
  if (rotfont->dir == 0)
341
    width = XTextWidth(rotfont->xfontstruct, str, strlen(str));
342
343
  else
344
    for (i = 0; i<len; i++) {
345
      width += rotfont->per_char[((unsigned char*)str)[i]].width;
346
    }
347
348
  return width;
349
}
350
#endif
351
352
/* ---------------------------------------------------------------------- */
353
354
// the public functions use the fltk global variables for font & gc:
355
356
static XRotFontStruct* font;
357
1.1.1 by Bill Allombert
Import upstream version 1.01
358
static void setrotfont(int angle) {
1 by Tommi Virtanen
Import upstream version 1.00
359
  /* make angle positive ... */
360
  if (angle < 0) do angle += 360; while (angle < 0);
361
  /* get nearest vertical or horizontal direction ... */
362
  int dir = ((angle+45)/90)%4;
1.1.1 by Bill Allombert
Import upstream version 1.01
363
  if (font) {
364
    if (font->xfontstruct == fl_xfont && font->dir == dir) return;
365
    XRotUnloadFont(fl_display, font);
366
  }
367
  font = XRotLoadFont(fl_display, fl_xfont, dir);
368
}
1 by Tommi Virtanen
Import upstream version 1.00
369
1.1.1 by Bill Allombert
Import upstream version 1.01
370
void draw_rotated(const char* text, int n, int x, int y, int angle) {
371
  if (!text || !*text) return;
372
  setrotfont(angle);
1 by Tommi Virtanen
Import upstream version 1.00
373
  XRotDrawString(fl_display, font, fl_window, fl_gc, x, y, text, n);
374
}
375
1.1.1 by Bill Allombert
Import upstream version 1.01
376
#if !defined(FLWM) || FL_MAJOR_VERSION>=2
1 by Tommi Virtanen
Import upstream version 1.00
377
void draw_rotated(const char* text, int x, int y, int angle) {
378
  if (!text || !*text) return;
379
  draw_rotated(text, strlen(text), x, y, angle);
380
}
381
#endif
382
383
static void draw_rot90(const char* str, int n, int x, int y) {
384
  draw_rotated(str, n, y, -x, 90);
385
}
386
void draw_rotated90(
387
  const char* str, 	// the (multi-line) string
388
  int x, int y, int w, int h, 	// bounding box
389
  Fl_Align align) {
390
  if (!str || !*str) return;
391
  if (w && h && !fl_not_clipped(x, y, w, h)) return;
392
  if (align & FL_ALIGN_CLIP) fl_clip(x, y, w, h);
1.1.1 by Bill Allombert
Import upstream version 1.01
393
#if FL_MAJOR_VERSION>1
394
  setrotfont(90);
395
  int a = font->xfontstruct->ascent;
396
  int d = font->xfontstruct->descent;
397
  XRotDrawString(fl_display, font, fl_window, fl_gc,
398
		 x+(w+a-d+1)/2, y+h, str, strlen(str));
399
#else
1 by Tommi Virtanen
Import upstream version 1.00
400
  int a1 = align&(-16);
401
  if (align & FL_ALIGN_LEFT) a1 |= FL_ALIGN_TOP;
402
  if (align & FL_ALIGN_RIGHT) a1 |= FL_ALIGN_BOTTOM;
403
  if (align & FL_ALIGN_TOP) a1 |= FL_ALIGN_RIGHT;
404
  if (align & FL_ALIGN_BOTTOM) a1 |= FL_ALIGN_LEFT;
405
  fl_draw(str, -(y+h), x, h, w, (Fl_Align)a1, draw_rot90);
1.1.1 by Bill Allombert
Import upstream version 1.01
406
#endif
1 by Tommi Virtanen
Import upstream version 1.00
407
  if (align & FL_ALIGN_CLIP) fl_pop_clip();
408
}
409
410
#ifndef FLWM
411
static void draw_rot180(const char* str, int n, int x, int y) {
412
  draw_rotated(str, n, -x, -y, 180);
413
}
414
void draw_rotated180(
415
  const char* str, 	// the (multi-line) string
416
  int x, int y, int w, int h, 	// bounding box
417
  Fl_Align align) {
418
  int a1 = align&(-16);
419
  if (align & FL_ALIGN_LEFT) a1 |= FL_ALIGN_RIGHT;
420
  if (align & FL_ALIGN_RIGHT) a1 |= FL_ALIGN_LEFT;
421
  if (align & FL_ALIGN_TOP) a1 |= FL_ALIGN_BOTTOM;
422
  if (align & FL_ALIGN_BOTTOM) a1 |= FL_ALIGN_TOP;
423
  fl_draw(str, -(x+w), -(y+h), w, h, (Fl_Align)a1, draw_rot180);
424
}
425
426
static void draw_rot270(const char* str, int n, int x, int y) {
427
  draw_rotated(str, n, -y, x, 270);
428
}
429
void draw_rotated270(
430
  const char* str, 	// the (multi-line) string
431
  int x, int y, int w, int h, 	// bounding box
432
  Fl_Align align) {
433
  int a1 = align&(-16);
434
  if (align & FL_ALIGN_LEFT) a1 |= FL_ALIGN_BOTTOM;
435
  if (align & FL_ALIGN_RIGHT) a1 |= FL_ALIGN_TOP;
436
  if (align & FL_ALIGN_TOP) a1 |= FL_ALIGN_LEFT;
437
  if (align & FL_ALIGN_BOTTOM) a1 |= FL_ALIGN_RIGHT;
438
  fl_draw(str, y, -(x+w), h, w, (Fl_Align)a1, draw_rot270);
439
}
440
#endif
441