test not only if header frei0r.h exists, also use an item
[mlt-frei0r-support.git] / shotcut / wm / Rotated.cpp
blobffcf6dc2d8e398efdfc968ba80483aa630b6938a
1 // Rotated text drawing with X.
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 "
12 /* xvertext, Copyright (c) 1992 Alan Richardson (mppa3@uk.ac.sussex.syma)
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.
24 // if not defined then portions not used by flwm are included:
25 #define FLWM 1
27 /* ********************************************************************** */
29 #include <FL/x.H>
30 #include <FL/fl_draw.H>
31 #include "Rotated.h"
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdio.h>
36 struct BitmapStruct {
37 int bit_w;
38 int bit_h;
39 Pixmap bm;
42 struct XRotCharStruct {
43 int ascent;
44 int descent;
45 int lbearing;
46 int rbearing;
47 int width;
48 BitmapStruct glyph;
51 struct XRotFontStruct {
52 int dir;
53 int height;
54 int max_ascent;
55 int max_descent;
56 int max_char;
57 int min_char;
58 XFontStruct* xfontstruct;
59 XRotCharStruct per_char[256];
62 /* *** Load the rotated version of a given font *** */
64 static XRotFontStruct*
65 XRotLoadFont(Display *dpy, XFontStruct* fontstruct, int dir)
67 char val;
68 XImage *I1, *I2;
69 Pixmap canvas;
70 Window root;
71 int screen;
72 GC font_gc;
73 char text[3];/*, errstr[300];*/
75 XRotFontStruct *rotfont;
76 int ichar, i, j, index, boxlen = 60;
77 int vert_w, vert_h, vert_len, bit_w, bit_h, bit_len;
78 int min_char, max_char;
79 unsigned char *vertdata, *bitdata;
80 int ascent, descent, lbearing, rbearing;
81 int on = 1, off = 0;
83 /* useful macros ... */
84 screen = DefaultScreen(dpy);
85 root = DefaultRootWindow(dpy);
87 /* create the depth 1 canvas bitmap ... */
88 canvas = XCreatePixmap(dpy, root, boxlen, boxlen, 1);
90 /* create a GC ... */
91 font_gc = XCreateGC(dpy, canvas, 0, 0);
92 XSetBackground(dpy, font_gc, off);
94 XSetFont(dpy, font_gc, fontstruct->fid);
96 /* allocate space for rotated font ... */
97 rotfont = (XRotFontStruct *)malloc((unsigned)sizeof(XRotFontStruct));
99 /* determine which characters are defined in font ... */
100 min_char = fontstruct->min_char_or_byte2;
101 if (min_char<0) min_char = 0;
102 rotfont->min_char = min_char;
103 max_char = fontstruct->max_char_or_byte2;
104 if (max_char>255) max_char = 255;
105 rotfont->max_char = max_char;
107 /* some overall font data ... */
108 rotfont->dir = dir;
109 rotfont->max_ascent = fontstruct->max_bounds.ascent;
110 rotfont->max_descent = fontstruct->max_bounds.descent;
111 rotfont->height = rotfont->max_ascent+rotfont->max_descent;
113 rotfont->xfontstruct = fontstruct;
114 /* remember xfontstruct for `normal' text ... */
115 if (dir != 0) {
116 /* font needs rotation ... */
117 /* loop through each character ... */
118 for (ichar = min_char; ichar <= max_char; ichar++) {
120 index = ichar-fontstruct->min_char_or_byte2;
122 /* per char dimensions ... */
123 ascent = rotfont->per_char[ichar].ascent =
124 fontstruct->per_char[index].ascent;
125 descent = rotfont->per_char[ichar].descent =
126 fontstruct->per_char[index].descent;
127 lbearing = rotfont->per_char[ichar].lbearing =
128 fontstruct->per_char[index].lbearing;
129 rbearing = rotfont->per_char[ichar].rbearing =
130 fontstruct->per_char[index].rbearing;
131 rotfont->per_char[ichar].width =
132 fontstruct->per_char[index].width;
134 /* some space chars have zero body, but a bitmap can't have ... */
135 if (!ascent && !descent)
136 ascent = rotfont->per_char[ichar].ascent = 1;
137 if (!lbearing && !rbearing)
138 rbearing = rotfont->per_char[ichar].rbearing = 1;
140 /* glyph width and height when vertical ... */
141 vert_w = rbearing-lbearing;
142 vert_h = ascent+descent;
144 /* width in bytes ... */
145 vert_len = (vert_w-1)/8+1;
147 XSetForeground(dpy, font_gc, off);
148 XFillRectangle(dpy, canvas, font_gc, 0, 0, boxlen, boxlen);
150 /* draw the character centre top right on canvas ... */
151 sprintf(text, "%c", ichar);
152 XSetForeground(dpy, font_gc, on);
153 XDrawImageString(dpy, canvas, font_gc, boxlen/2 - lbearing,
154 boxlen/2 - descent, text, 1);
156 /* reserve memory for first XImage ... */
157 vertdata = (unsigned char *) malloc((unsigned)(vert_len*vert_h));
159 /* create the XImage ... */
160 I1 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap,
161 0, (char *)vertdata, vert_w, vert_h, 8, 0);
163 // if (I1 == NULL) ... do something here
165 I1->byte_order = I1->bitmap_bit_order = MSBFirst;
167 /* extract character from canvas ... */
168 XGetSubImage(dpy, canvas, boxlen/2, boxlen/2-vert_h,
169 vert_w, vert_h, 1, XYPixmap, I1, 0, 0);
170 I1->format = XYBitmap;
172 /* width, height of rotated character ... */
173 if (dir == 2) {
174 bit_w = vert_w;
175 bit_h = vert_h;
176 } else {
177 bit_w = vert_h;
178 bit_h = vert_w;
181 /* width in bytes ... */
182 bit_len = (bit_w-1)/8 + 1;
184 rotfont->per_char[ichar].glyph.bit_w = bit_w;
185 rotfont->per_char[ichar].glyph.bit_h = bit_h;
187 /* reserve memory for the rotated image ... */
188 bitdata = (unsigned char *)calloc((unsigned)(bit_h*bit_len), 1);
190 /* create the image ... */
191 I2 = XCreateImage(dpy, DefaultVisual(dpy, screen), 1, XYBitmap, 0,
192 (char *)bitdata, bit_w, bit_h, 8, 0);
194 // if (I2 == NULL) ... error
196 I2->byte_order = I2->bitmap_bit_order = MSBFirst;
198 /* map vertical data to rotated character ... */
199 for (j = 0; j < bit_h; j++) {
200 for (i = 0; i < bit_w; i++) {
201 /* map bits ... */
202 if (dir == 1)
203 val = vertdata[i*vert_len + (vert_w-j-1)/8] &
204 (128>>((vert_w-j-1)%8));
206 else if (dir == 2)
207 val = vertdata[(vert_h-j-1)*vert_len + (vert_w-i-1)/8] &
208 (128>>((vert_w-i-1)%8));
210 else
211 val = vertdata[(vert_h-i-1)*vert_len + j/8] &
212 (128>>(j%8));
214 if (val)
215 bitdata[j*bit_len + i/8] = bitdata[j*bit_len + i/8] |
216 (128>>(i%8));
220 /* create this character's bitmap ... */
221 rotfont->per_char[ichar].glyph.bm =
222 XCreatePixmap(dpy, root, bit_w, bit_h, 1);
224 /* put the image into the bitmap ... */
225 XPutImage(dpy, rotfont->per_char[ichar].glyph.bm,
226 font_gc, I2, 0, 0, 0, 0, bit_w, bit_h);
228 /* free the image and data ... */
229 XDestroyImage(I1);
230 XDestroyImage(I2);
231 /* free((char *)bitdata); -- XDestroyImage does this
232 free((char *)vertdata);*/
237 for (ichar = 0; ichar < min_char; ichar++)
238 rotfont->per_char[ichar] = rotfont->per_char[(int)'?'];
239 for (ichar = max_char+1; ichar < 256; ichar++)
240 rotfont->per_char[ichar] = rotfont->per_char[(int)'?'];
242 /* free pixmap and GC ... */
243 XFreePixmap(dpy, canvas);
244 XFreeGC(dpy, font_gc);
246 return rotfont;
249 /* *** Free the resources associated with a rotated font *** */
251 static void XRotUnloadFont(Display *dpy, XRotFontStruct *rotfont)
253 int ichar;
255 if (rotfont->dir != 0) {
256 /* loop through each character, freeing its pixmap ... */
257 for (ichar = rotfont->min_char; ichar <= rotfont->max_char; ichar++)
258 XFreePixmap(dpy, rotfont->per_char[ichar].glyph.bm);
260 /* rotfont should never be referenced again ... */
261 free((char *)rotfont);
264 /* ---------------------------------------------------------------------- */
266 /* *** A front end to XRotPaintString : mimics XDrawString *** */
268 static void
269 XRotDrawString(Display *dpy, XRotFontStruct *rotfont, Drawable drawable,
270 GC gc, int x, int y, const char *str, int len)
272 int i, xp, yp, dir, ichar;
274 if (str == NULL || len<1) return;
276 dir = rotfont->dir;
278 /* a horizontal string is easy ... */
279 if (dir == 0) {
280 XSetFont(dpy, gc, rotfont->xfontstruct->fid);
281 XDrawString(dpy, drawable, gc, x, y, str, len);
282 return;
285 /* vertical or upside down ... */
287 XSetFillStyle(dpy, gc, FillStippled);
289 /* loop through each character in string ... */
290 for (i = 0; i<len; i++) {
291 ichar = ((unsigned char*)str)[i];
293 /* suitable offset ... */
294 if (dir == 1) {
295 xp = x-rotfont->per_char[ichar].ascent;
296 yp = y-rotfont->per_char[ichar].rbearing;
298 else if (dir == 2) {
299 xp = x-rotfont->per_char[ichar].rbearing;
300 yp = y-rotfont->per_char[ichar].descent+1;
302 else {
303 xp = x-rotfont->per_char[ichar].descent+1;
304 yp = y+rotfont->per_char[ichar].lbearing;
307 /* draw the glyph ... */
308 XSetStipple(dpy, gc, rotfont->per_char[ichar].glyph.bm);
310 XSetTSOrigin(dpy, gc, xp, yp);
312 XFillRectangle(dpy, drawable, gc, xp, yp,
313 rotfont->per_char[ichar].glyph.bit_w,
314 rotfont->per_char[ichar].glyph.bit_h);
316 /* advance position ... */
317 if (dir == 1)
318 y -= rotfont->per_char[ichar].width;
319 else if (dir == 2)
320 x -= rotfont->per_char[ichar].width;
321 else
322 y += rotfont->per_char[ichar].width;
324 XSetFillStyle(dpy, gc, FillSolid);
327 #ifndef FLWM
328 /* *** Return the width of a string *** */
330 static int XRotTextWidth(XRotFontStruct *rotfont, const char *str, int len)
332 int i, width = 0, ichar;
334 if (str == NULL) return 0;
336 if (rotfont->dir == 0)
337 width = XTextWidth(rotfont->xfontstruct, str, strlen(str));
339 else
340 for (i = 0; i<len; i++) {
341 width += rotfont->per_char[((unsigned char*)str)[i]].width;
344 return width;
346 #endif
348 /* ---------------------------------------------------------------------- */
350 // the public functions use the fltk global variables for font & gc:
352 static XRotFontStruct* font;
354 void draw_rotated(const char* text, int n, int x, int y, int angle) {
355 if (!text || !*text) return;
356 /* make angle positive ... */
357 if (angle < 0) do angle += 360; while (angle < 0);
358 /* get nearest vertical or horizontal direction ... */
359 int dir = ((angle+45)/90)%4;
361 if (font && font->xfontstruct == fl_xfont && font->dir == dir) {
363 } else {
364 if (font) XRotUnloadFont(fl_display, font);
365 font = XRotLoadFont(fl_display, fl_xfont, dir);
367 XRotDrawString(fl_display, font, fl_window, fl_gc, x, y, text, n);
370 #ifndef FLWM
371 void draw_rotated(const char* text, int x, int y, int angle) {
372 if (!text || !*text) return;
373 draw_rotated(text, strlen(text), x, y, angle);
375 #endif
377 static void draw_rot90(const char* str, int n, int x, int y) {
378 draw_rotated(str, n, y, -x, 90);
380 void draw_rotated90(
381 const char* str, // the (multi-line) string
382 int x, int y, int w, int h, // bounding box
383 Fl_Align align) {
384 if (!str || !*str) return;
385 if (w && h && !fl_not_clipped(x, y, w, h)) return;
386 if (align & FL_ALIGN_CLIP) fl_clip(x, y, w, h);
387 int a1 = align&(-16);
388 if (align & FL_ALIGN_LEFT) a1 |= FL_ALIGN_TOP;
389 if (align & FL_ALIGN_RIGHT) a1 |= FL_ALIGN_BOTTOM;
390 if (align & FL_ALIGN_TOP) a1 |= FL_ALIGN_RIGHT;
391 if (align & FL_ALIGN_BOTTOM) a1 |= FL_ALIGN_LEFT;
392 fl_draw(str, -(y+h), x, h, w, (Fl_Align)a1, draw_rot90);
393 if (align & FL_ALIGN_CLIP) fl_pop_clip();
396 #ifndef FLWM
397 static void draw_rot180(const char* str, int n, int x, int y) {
398 draw_rotated(str, n, -x, -y, 180);
400 void draw_rotated180(
401 const char* str, // the (multi-line) string
402 int x, int y, int w, int h, // bounding box
403 Fl_Align align) {
404 int a1 = align&(-16);
405 if (align & FL_ALIGN_LEFT) a1 |= FL_ALIGN_RIGHT;
406 if (align & FL_ALIGN_RIGHT) a1 |= FL_ALIGN_LEFT;
407 if (align & FL_ALIGN_TOP) a1 |= FL_ALIGN_BOTTOM;
408 if (align & FL_ALIGN_BOTTOM) a1 |= FL_ALIGN_TOP;
409 fl_draw(str, -(x+w), -(y+h), w, h, (Fl_Align)a1, draw_rot180);
412 static void draw_rot270(const char* str, int n, int x, int y) {
413 draw_rotated(str, n, -y, x, 270);
415 void draw_rotated270(
416 const char* str, // the (multi-line) string
417 int x, int y, int w, int h, // bounding box
418 Fl_Align align) {
419 int a1 = align&(-16);
420 if (align & FL_ALIGN_LEFT) a1 |= FL_ALIGN_BOTTOM;
421 if (align & FL_ALIGN_RIGHT) a1 |= FL_ALIGN_TOP;
422 if (align & FL_ALIGN_TOP) a1 |= FL_ALIGN_LEFT;
423 if (align & FL_ALIGN_BOTTOM) a1 |= FL_ALIGN_RIGHT;
424 fl_draw(str, y, -(x+w), h, w, (Fl_Align)a1, draw_rot270);
426 #endif