1 /*
2 * Copyright (C) 2000-2019 the xine project
3 *
4 * This file is part of xine, a unix video player.
5 *
6 * xine is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * xine is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 *
20 */
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <X11/Xlib.h>
28 #include <errno.h>
29
30 #include "_xitk.h"
31
32 #include "utils.h"
33
34 int xitk_x_error = 0;
35
36 /*
37 * Get a pixel color from rgb values.
38 */
xitk_get_pixel_color_from_rgb(ImlibData * im,int r,int g,int b)39 unsigned int xitk_get_pixel_color_from_rgb(ImlibData *im, int r, int g, int b) {
40 XColor xcolor;
41 unsigned int pixcol;
42
43 ABORT_IF_NULL(im);
44
45 xcolor.flags = DoRed | DoBlue | DoGreen;
46
47 xcolor.red = r<<8;
48 xcolor.green = g<<8;
49 xcolor.blue = b<<8;
50
51 XLOCK (im->x.x_lock_display, im->x.disp);
52 XAllocColor(im->x.disp, Imlib_get_colormap(im), &xcolor);
53 XUNLOCK (im->x.x_unlock_display, im->x.disp);
54
55 pixcol = xcolor.pixel;
56
57 return pixcol;
58 }
59
60 /*
61 * Some default pixel colors.
62 */
xitk_get_pixel_color_black(ImlibData * im)63 unsigned int xitk_get_pixel_color_black(ImlibData *im) {
64 int user_color = xitk_get_black_color();
65 if(user_color >= 0)
66 return (unsigned int) user_color;
67 return xitk_get_pixel_color_from_rgb(im, 0, 0, 0);
68 }
xitk_get_pixel_color_white(ImlibData * im)69 unsigned int xitk_get_pixel_color_white(ImlibData *im) {
70 int user_color = xitk_get_white_color();
71 if(user_color >= 0)
72 return (unsigned int) user_color;
73 return xitk_get_pixel_color_from_rgb(im, 255, 255, 255);
74 }
xitk_get_pixel_color_lightgray(ImlibData * im)75 unsigned int xitk_get_pixel_color_lightgray(ImlibData *im) {
76 int user_color = xitk_get_focus_color();
77 if(user_color >= 0)
78 return (unsigned int) user_color;
79 return xitk_get_pixel_color_from_rgb(im, 224, 224, 224);
80 }
xitk_get_pixel_color_gray(ImlibData * im)81 unsigned int xitk_get_pixel_color_gray(ImlibData *im) {
82 int user_color = xitk_get_background_color();
83 if(user_color >= 0)
84 return (unsigned int) user_color;
85 return xitk_get_pixel_color_from_rgb(im, 190, 190, 190);
86 }
xitk_get_pixel_color_darkgray(ImlibData * im)87 unsigned int xitk_get_pixel_color_darkgray(ImlibData *im) {
88 int user_color = xitk_get_select_color();
89 if(user_color >= 0)
90 return (unsigned int) user_color;
91 return xitk_get_pixel_color_from_rgb(im, 128, 128, 128);
92 }
xitk_get_pixel_color_warning_foreground(ImlibData * im)93 unsigned int xitk_get_pixel_color_warning_foreground(ImlibData *im) {
94 int user_color = xitk_get_warning_foreground();
95 if(user_color >= 0)
96 return (unsigned int) user_color;
97 return xitk_get_pixel_color_black(im);
98 }
xitk_get_pixel_color_warning_background(ImlibData * im)99 unsigned int xitk_get_pixel_color_warning_background(ImlibData *im) {
100 int user_color = xitk_get_warning_background();
101 if(user_color >= 0)
102 return (unsigned int) user_color;
103 return xitk_get_pixel_color_from_rgb(im, 255, 255, 0);
104 }
105
_xitk_pix_font_find_char(xitk_pix_font_t * pf,xitk_point_t * found,int this_char)106 static int _xitk_pix_font_find_char (xitk_pix_font_t *pf, xitk_point_t *found, int this_char) {
107 int range, n = 0;
108
109 for (range = 0; pf->unicode_ranges[range].first > 0; range++) {
110 if ((this_char >= pf->unicode_ranges[range].first) && (this_char <= pf->unicode_ranges[range].last))
111 break;
112 n += pf->unicode_ranges[range].last - pf->unicode_ranges[range].first + 1;
113 }
114
115 if (pf->unicode_ranges[range].first <= 0) {
116 *found = pf->unknown;
117 return 0;
118 }
119
120 n += this_char - pf->unicode_ranges[range].first;
121 found->x = (n % pf->chars_per_row) * pf->char_width;
122 found->y = (n / pf->chars_per_row) * pf->char_height;
123 return 1;
124 }
125
xitk_image_set_pix_font(xitk_image_t * image,const char * format)126 void xitk_image_set_pix_font (xitk_image_t *image, const char *format) {
127 xitk_pix_font_t *pf;
128 int range, total;
129
130 if (!image || !format)
131 return;
132 if (image->pix_font)
133 return;
134 image->pix_font = pf = malloc (sizeof (*pf));
135 if (!pf)
136 return;
137
138 pf->width = image->width;
139 pf->height = image->height;
140
141 range = 0;
142 total = 0;
143 do {
144 const uint8_t *p = (const uint8_t *)format;
145 int v;
146 uint8_t z;
147 if (!p)
148 break;
149 while (1) {
150 while (*p && (*p != '('))
151 p++;
152 if (!(*p))
153 break;
154 p++;
155 if ((*p ^ '0') < 10)
156 break;
157 }
158 if (!(*p))
159 break;
160
161 v = 0;
162 while ((z = (*p ^ '0')) < 10)
163 v = v * 10u + z, p++;
164 if (v <= 0)
165 break;
166 pf->chars_per_row = v;
167 if (*p != '!')
168 break;
169 p++;
170
171 while (1) {
172 pf->unicode_ranges[range].last = 0;
173 v = 0;
174 while ((z = (*p ^ '0')) < 10)
175 v = v * 10u + z, p++;
176 pf->unicode_ranges[range].first = v;
177 if (*p != '-')
178 break;
179 p++;
180 v = 0;
181 while ((z = (*p ^ '0')) < 10)
182 v = v * 10u + z, p++;
183 pf->unicode_ranges[range].last = v;
184 if (pf->unicode_ranges[range].last < pf->unicode_ranges[range].first)
185 pf->unicode_ranges[range].last = pf->unicode_ranges[range].first;
186 total += pf->unicode_ranges[range].last - pf->unicode_ranges[range].first + 1;
187 range++;
188 if (range >= XITK_MAX_UNICODE_RANGES)
189 break;
190 if (*p != '!')
191 break;
192 p++;
193 }
194 } while (0);
195
196 if (range == 0) {
197 pf->chars_per_row = 32;
198 pf->unicode_ranges[0].first = 32;
199 pf->unicode_ranges[0].last = 127;
200 total = 127 - 32 + 1;
201 range = 1;
202 }
203
204 pf->char_width = pf->width / pf->chars_per_row;
205 pf->chars_total = total;
206 total = (total + pf->chars_per_row - 1) / pf->chars_per_row;
207 pf->char_height = pf->height / total;
208 pf->unicode_ranges[range].first = 0;
209 pf->unicode_ranges[range].last = 0;
210
211 pf->unknown.x = 0;
212 pf->unknown.y = 0;
213 _xitk_pix_font_find_char (pf, &pf->unknown, 127);
214 _xitk_pix_font_find_char (pf, &pf->space, ' ');
215 _xitk_pix_font_find_char (pf, &pf->asterisk, '*');
216 }
217
_xitk_image_destroy_pix_font(xitk_pix_font_t ** pix_font)218 static void _xitk_image_destroy_pix_font (xitk_pix_font_t **pix_font) {
219 free (*pix_font);
220 *pix_font = NULL;
221 }
222
223 /*
224 *
225 */
xitk_image_free_image(ImlibData * im,xitk_image_t ** src)226 void xitk_image_free_image(ImlibData *im, xitk_image_t **src) {
227
228 ABORT_IF_NULL(im);
229 ABORT_IF_NULL(*src);
230
231 if((*src)->mask)
232 xitk_image_destroy_xitk_pixmap((*src)->mask);
233
234 if((*src)->image)
235 xitk_image_destroy_xitk_pixmap((*src)->image);
236
237 _xitk_image_destroy_pix_font (&(*src)->pix_font);
238
239 XITK_FREE((*src));
240 *src = NULL;
241 }
242
243 /*
244 *
245 */
xitk_image_create_pixmap(ImlibData * im,int width,int height)246 Pixmap xitk_image_create_pixmap(ImlibData *im, int width, int height) {
247 Pixmap p;
248
249 ABORT_IF_NULL(im);
250 ABORT_IF_NOT_COND(width > 0);
251 ABORT_IF_NOT_COND(height > 0);
252
253 XLOCK (im->x.x_lock_display, im->x.disp);
254 p = XCreatePixmap(im->x.disp, im->x.base_window, width, height, im->x.depth);
255 XUNLOCK (im->x.x_unlock_display, im->x.disp);
256
257 return p;
258 }
259
260 /*
261 *
262 */
xitk_image_xitk_pixmap_destroyer(xitk_pixmap_t * xpix)263 static void xitk_image_xitk_pixmap_destroyer(xitk_pixmap_t *xpix) {
264 ABORT_IF_NULL(xpix);
265
266 XLOCK (xpix->imlibdata->x.x_lock_display, xpix->imlibdata->x.disp);
267
268 if(xpix->pixmap != None)
269 XFreePixmap(xpix->imlibdata->x.disp, xpix->pixmap);
270
271 XFreeGC(xpix->imlibdata->x.disp, xpix->gc);
272 XSync(xpix->imlibdata->x.disp, False);
273
274 #ifdef HAVE_SHM
275 if(xpix->shm) {
276 XShmSegmentInfo *shminfo = xpix->shminfo;
277
278 XShmDetach(xpix->imlibdata->x.disp, shminfo);
279
280 if(xpix->xim)
281 XDestroyImage(xpix->xim);
282
283 if(shmdt(shminfo->shmaddr) < 0)
284 XITK_WARNING("shmdt() failed: '%s'\n", strerror(errno));
285
286 if(shmctl(shminfo->shmid, IPC_RMID, 0) < 0)
287 XITK_WARNING("shmctl() failed: '%s'\n", strerror(errno));
288
289
290 free(shminfo);
291 }
292 #endif
293
294 XUNLOCK (xpix->imlibdata->x.x_unlock_display, xpix->imlibdata->x.disp);
295
296 XITK_FREE(xpix);
297 }
298
299 /*
300 *
301 */
xitk_image_create_xitk_pixmap_with_depth(ImlibData * im,int width,int height,int depth)302 xitk_pixmap_t *xitk_image_create_xitk_pixmap_with_depth(ImlibData *im, int width, int height, int depth) {
303 xitk_pixmap_t *xpix;
304 #ifdef HAVE_SHM
305 XShmSegmentInfo *shminfo;
306 #endif
307
308 ABORT_IF_NULL(im);
309 ABORT_IF_NOT_COND(width > 0);
310 ABORT_IF_NOT_COND(height > 0);
311
312 xpix = (xitk_pixmap_t *) xitk_xmalloc(sizeof(xitk_pixmap_t));
313 xpix->imlibdata = im;
314 xpix->destroy = xitk_image_xitk_pixmap_destroyer;
315 xpix->width = width;
316 xpix->height = height;
317 xpix->xim = NULL;
318 xpix->shm = 0;
319
320 XLOCK (im->x.x_lock_display, im->x.disp);
321
322 #ifdef HAVE_SHM
323 if(xitk_is_use_xshm() == 2) {
324 XImage *xim;
325
326 shminfo = (XShmSegmentInfo *) xitk_xmalloc(sizeof(XShmSegmentInfo));
327
328 xitk_x_error = 0;
329 xitk_install_x_error_handler();
330
331 xim = XShmCreateImage(im->x.disp, im->x.visual, depth, ZPixmap, NULL, shminfo, width, height);
332 if(!xim) {
333 XITK_WARNING("XShmCreateImage() failed.\n");
334 free(shminfo);
335 xitk_uninstall_x_error_handler();
336 goto __noxshm_pixmap;
337 }
338
339 shminfo->shmid = shmget(IPC_PRIVATE, xim->bytes_per_line * xim->height, IPC_CREAT | 0777);
340 if(shminfo->shmid < 0) {
341 XITK_WARNING("shmget() failed.\n");
342 XDestroyImage(xim);
343 free(shminfo);
344 xitk_uninstall_x_error_handler();
345 goto __noxshm_pixmap;
346 }
347
348 shminfo->shmaddr = xim->data = shmat(shminfo->shmid, 0, 0);
349 if(xim->data == (char *) -1) {
350 XITK_WARNING("shmmat() failed.\n");
351 XDestroyImage(xim);
352 shmctl(shminfo->shmid, IPC_RMID, 0);
353 free(shminfo);
354 xitk_uninstall_x_error_handler();
355 goto __noxshm_pixmap;
356 }
357
358 shminfo->readOnly = False;
359 XShmAttach(im->x.disp, shminfo);
360 XSync(im->x.disp, False);
361
362 if(xitk_x_error) {
363 XITK_WARNING("XShmAttach() failed.\n");
364 XDestroyImage(xim);
365 shmdt(shminfo->shmaddr);
366 shmctl(shminfo->shmid, IPC_RMID, 0);
367 free(shminfo);
368 xitk_uninstall_x_error_handler();
369 goto __noxshm_pixmap;
370 }
371
372 xpix->xim = xim;
373 xpix->pixmap = XShmCreatePixmap(im->x.disp, im->x.base_window,
374 shminfo->shmaddr, shminfo, width, height, depth);
375
376 if(!xpix->pixmap) {
377 XITK_WARNING("XShmCreatePixmap() failed.\n");
378 XShmDetach(xpix->imlibdata->x.disp, xpix->shminfo);
379 XDestroyImage(xim);
380 shmdt(shminfo->shmaddr);
381 shmctl(shminfo->shmid, IPC_RMID, 0);
382 free(shminfo);
383 xitk_uninstall_x_error_handler();
384 goto __noxshm_pixmap;
385 }
386 else {
387 xpix->shm = 1;
388 xpix->shminfo = shminfo;
389 xpix->gcv.graphics_exposures = False;
390 xpix->gc = XCreateGC(im->x.disp, xpix->pixmap, GCGraphicsExposures, &xpix->gcv);
391 xitk_uninstall_x_error_handler();
392 }
393 }
394 else
395 #endif
396 {
397 #ifdef HAVE_SHM /* Just to make GCC happy */
398 __noxshm_pixmap:
399 #endif
400 xpix->shm = 0;
401 #ifdef HAVE_SHM
402 xpix->shminfo = NULL;
403 #endif
404 xpix->pixmap = XCreatePixmap(im->x.disp, im->x.base_window, width, height, depth);
405
406 xpix->gcv.graphics_exposures = False;
407 xpix->gc = XCreateGC(im->x.disp, xpix->pixmap, GCGraphicsExposures, &xpix->gcv);
408 }
409 XUNLOCK (im->x.x_unlock_display, im->x.disp);
410
411 return xpix;
412 }
413
xitk_image_create_xitk_pixmap(ImlibData * im,int width,int height)414 xitk_pixmap_t *xitk_image_create_xitk_pixmap(ImlibData *im, int width, int height) {
415 return xitk_image_create_xitk_pixmap_with_depth(im, width, height, im->x.depth);
416 }
xitk_image_create_xitk_mask_pixmap(ImlibData * im,int width,int height)417 xitk_pixmap_t *xitk_image_create_xitk_mask_pixmap(ImlibData *im, int width, int height) {
418 return xitk_image_create_xitk_pixmap_with_depth(im, width, height, 1);
419 }
420
xitk_image_destroy_xitk_pixmap(xitk_pixmap_t * p)421 void xitk_image_destroy_xitk_pixmap(xitk_pixmap_t *p) {
422 ABORT_IF_NULL(p);
423 p->destroy(p);
424 }
425
426 #if 0
427 /*
428 *
429 */
430 Pixmap xitk_image_create_mask_pixmap(ImlibData *im, int width, int height) {
431 Pixmap p;
432
433 ABORT_IF_NULL(im);
434 ABORT_IF_NOT_COND(width > 0);
435 ABORT_IF_NOT_COND(height > 0);
436
437 XLOCK (im->x.x_lock_display, im->x.disp);
438 p = XCreatePixmap(im->x.disp, im->x.base_window, width, height, 1);
439 XUNLOCK (im->x.x_unlock_display, im->x.disp);
440
441 return p;
442 }
443 #endif
444
445 /*
446 *
447 */
xitk_image_change_image(ImlibData * im,xitk_image_t * src,xitk_image_t * dest,int width,int height)448 void xitk_image_change_image(ImlibData *im,
449 xitk_image_t *src, xitk_image_t *dest, int width, int height) {
450 ABORT_IF_NULL(im);
451 ABORT_IF_NULL(src);
452 ABORT_IF_NULL(dest);
453 ABORT_IF_NOT_COND(width > 0);
454 ABORT_IF_NOT_COND(height > 0);
455
456 if(dest->mask)
457 xitk_image_destroy_xitk_pixmap(dest->mask);
458
459 if(src->mask) {
460 xitk_image_destroy_xitk_pixmap(src->mask);
461
462 dest->mask = xitk_image_create_xitk_pixmap(im, width, height);
463
464 XLOCK (im->x.x_lock_display, im->x.disp);
465 XCopyArea(im->x.disp, src->mask->pixmap, dest->mask->pixmap, dest->mask->gc,
466 0, 0, width, height, 0, 0);
467 XUNLOCK (im->x.x_unlock_display, im->x.disp);
468
469 }
470 else
471 dest->mask = NULL;
472
473 if(dest->image)
474 xitk_image_destroy_xitk_pixmap(dest->image);
475
476 dest->image = xitk_image_create_xitk_pixmap(im, width, height);
477
478 XLOCK (im->x.x_lock_display, im->x.disp);
479 XCopyArea(im->x.disp, src->image->pixmap, dest->image->pixmap, dest->image->gc,
480 0, 0, width, height, 0, 0);
481 XUNLOCK (im->x.x_unlock_display, im->x.disp);
482
483 dest->width = width;
484 dest->height = height;
485 }
486
487 /*
488 *
489 */
xitk_image_create_image(ImlibData * im,int width,int height)490 xitk_image_t *xitk_image_create_image(ImlibData *im, int width, int height) {
491 xitk_image_t *i;
492
493 ABORT_IF_NULL(im);
494 ABORT_IF_NOT_COND(width > 0);
495 ABORT_IF_NOT_COND(height > 0);
496
497 i = (xitk_image_t *) xitk_xmalloc(sizeof(xitk_image_t));
498 i->mask = NULL;
499 i->image = xitk_image_create_xitk_pixmap(im, width, height);
500 i->width = width;
501 i->height = height;
502
503 return i;
504 }
505
506 /*
507 *
508 */
xitk_image_create_image_with_colors_from_string(ImlibData * im,const char * fontname,int width,int align,const char * str,unsigned int foreground,unsigned int background)509 xitk_image_t *xitk_image_create_image_with_colors_from_string(ImlibData *im,
510 const char *fontname,
511 int width, int align, const char *str,
512 unsigned int foreground,
513 unsigned int background) {
514 xitk_image_t *image;
515 xitk_font_t *fs;
516 GC gc;
517 int length, height, lbearing, rbearing, ascent, descent, linel, linew, wlinew, lastws;
518 int maxw = 0;
519 const char *p;
520 char *bp;
521 char *lines[256];
522 int numlines = 0;
523 char buf[BUFSIZ]; /* Could be allocated dynamically for bigger texts */
524
525 int add_line_spc = 2;
526
527 ABORT_IF_NULL(im);
528 ABORT_IF_NULL(fontname);
529 ABORT_IF_NULL(str);
530 ABORT_IF_NOT_COND(width > 0);
531
532 XLOCK (im->x.x_lock_display, im->x.disp);
533 gc = XCreateGC(im->x.disp, im->x.base_window, None, None);
534 XUNLOCK (im->x.x_unlock_display, im->x.disp);
535
536 /* Creating an image from an empty string would cause an abort with failed */
537 /* condition "width > 0". So we substitute some spaces (one single space */
538 /* may not be enough!). Should only happen in case of error. */
539 if(!*str)
540 str = " ";
541
542 fs = xitk_font_load_font(im->x.disp, fontname);
543 xitk_font_set_font(fs, gc);
544 xitk_font_string_extent(fs, str, NULL, NULL, NULL, &ascent, &descent);
545 height = ascent + descent;
546
547 p = str;
548 bp = buf;
549 wlinew = linew = lastws = linel = 0;
550
551 /*
552 * Create string image using exactly the ink width
553 * without left and right spacing measures
554 */
555
556 while((*p!='\0') && (bp + linel) < (buf + BUFSIZ - TABULATION_SIZE - 2)) {
557
558 switch(*p) {
559
560 case '\t':
561 {
562 int a;
563
564 if((linel == 0) || (bp[linel - 1] != ' ')) {
565 lastws = linel;
566 wlinew = linew; /* width if wrapped */
567 }
568
569 a = TABULATION_SIZE - (linel % TABULATION_SIZE);
570
571 while(a--)
572 bp[linel++] = ' ';
573 }
574 break;
575
576 case '\a':
577 case '\b':
578 case '\f':
579 case '\r':
580 case '\v':
581 break; /* Ignore those */
582
583 case '\n':
584 lines[numlines++] = bp;
585 bp = bp + linel + 1;
586
587 wlinew = lastws = linel = 0;
588
589 if(linew > maxw)
590 maxw = linew;
591 break;
592
593 case ' ':
594 if((linel == 0) || (bp[linel-1] != ' ')) {
595 lastws = linel;
596 wlinew = linew; /* width if wrapped */
597 }
598
599 /* fall through */
600 default:
601 bp[linel++] = *p;
602
603 if(!lastws)
604 wlinew = linew;
605 break;
606 }
607
608 bp[linel] = '\0'; /* terminate the string for reading with xitk_font_string_extent or strlen */
609
610 xitk_font_string_extent(fs, bp, &lbearing, &rbearing, NULL, NULL, NULL);
611 if((linew = rbearing - lbearing) > width) {
612
613 if(lastws == 0) { /* if we haven't found a whitespace */
614 bp[linel] = bp[linel-1]; /* Move that last character down */
615 bp[linel-1] = 0;
616 lines[numlines++] = bp;
617 bp += linel;
618 linel = 1;
619 bp[linel] = 0;
620 }
621 else {
622 char *nextword = (bp + lastws);
623 int wordlen;
624
625 while(*nextword == ' ')
626 nextword++;
627
628 wordlen = (bp + linel) - nextword;
629 bp[lastws] = '\0';
630 lines[numlines++] = bp;
631 bp = bp + lastws + 1;
632
633 if(bp != nextword)
634 memmove(bp, nextword, wordlen + 1);
635
636 linel = wordlen;
637 lastws = 0;
638 }
639
640 if(wlinew > maxw)
641 maxw = wlinew;
642
643 xitk_font_string_extent(fs, bp, &lbearing, &rbearing, NULL, NULL, NULL);
644 linew = rbearing - lbearing;
645 }
646
647 p++;
648 }
649
650 if(linel) { /* In case last chars aren't stored */
651 lines[numlines++] = bp;
652
653 if(linew > maxw)
654 maxw = linew;
655 }
656
657 /* If default resp. left aligned, we may shrink the image */
658 if((align == ALIGN_DEFAULT) || (align == ALIGN_LEFT))
659 width = MIN(maxw, width);
660
661 image = xitk_image_create_image(im, width, (height + add_line_spc) * numlines - add_line_spc);
662 draw_flat_with_color(im, image->image, image->width, image->height, background);
663
664 { /* Draw string in image */
665 int i, y, x = 0;
666
667 XLOCK (im->x.x_lock_display, im->x.disp);
668 XSetForeground(im->x.disp, gc, foreground);
669 XUNLOCK (im->x.x_unlock_display, im->x.disp);
670
671 for(y = ascent, i = 0; i < numlines; i++, y += (height + add_line_spc)) {
672 xitk_font_string_extent(fs, lines[i], &lbearing, &rbearing, NULL, NULL, NULL);
673 length = rbearing - lbearing;
674
675 if((align == ALIGN_DEFAULT) || (align == ALIGN_LEFT))
676 x = 0;
677 else if(align == ALIGN_CENTER)
678 x = (width - length) >> 1;
679 else if(align == ALIGN_RIGHT)
680 x = (width - length);
681
682 xitk_font_draw_string(fs, image->image->pixmap, gc,
683 (x - lbearing), y, lines[i], strlen(lines[i]));
684 /* ^^^^^^^^ Adjust to start of ink */
685 }
686 }
687
688 xitk_font_unload_font(fs);
689
690 XLOCK (im->x.x_lock_display, im->x.disp);
691 XFreeGC(im->x.disp, gc);
692 XUNLOCK (im->x.x_unlock_display, im->x.disp);
693
694 return image;
695 }
xitk_image_create_image_from_string(ImlibData * im,const char * fontname,int width,int align,const char * str)696 xitk_image_t *xitk_image_create_image_from_string(ImlibData *im,
697 const char *fontname,
698 int width, int align, const char *str) {
699
700 return xitk_image_create_image_with_colors_from_string(im,fontname, width, align, str,
701 xitk_get_pixel_color_black(im),
702 xitk_get_pixel_color_gray(im));
703 }
704 /*
705 *
706 */
xitk_image_add_mask(ImlibData * im,xitk_image_t * dest)707 void xitk_image_add_mask(ImlibData *im, xitk_image_t *dest) {
708 ABORT_IF_NULL(im);
709 ABORT_IF_NULL(dest);
710
711 if(dest->mask)
712 xitk_image_destroy_xitk_pixmap(dest->mask);
713
714 dest->mask = xitk_image_create_xitk_mask_pixmap(im, dest->width, dest->height);
715
716 XLOCK (im->x.x_lock_display, im->x.disp);
717 XSetForeground(im->x.disp, dest->mask->gc, 1);
718 XFillRectangle(im->x.disp, dest->mask->pixmap, dest->mask->gc, 0, 0, dest->width, dest->height);
719 XUNLOCK (im->x.x_unlock_display, im->x.disp);
720 }
721
menu_draw_arrow_branch(ImlibData * im,xitk_image_t * p)722 void menu_draw_arrow_branch(ImlibData *im, xitk_image_t *p) {
723 int w;
724 int h;
725 XPoint points[4];
726 int i;
727 int x1, x2, x3;
728 int y1, y2, y3;
729
730 ABORT_IF_NULL(im);
731 ABORT_IF_NULL(p);
732
733 w = p->width / 3;
734 h = p->height;
735
736 x1 = (w - 5);
737 y1 = (h / 2);
738
739 x2 = (w - 10);
740 y2 = ((h / 2) + 5);
741
742 x3 = (w - 10);
743 y3 = ((h / 2) - 5);
744
745 XLOCK (im->x.x_lock_display, im->x.disp);
746 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
747 XUNLOCK (im->x.x_unlock_display, im->x.disp);
748
749 for(i = 0; i < 3; i++) {
750
751 if(i == 2) {
752 x1++; x2++; x3++;
753 y1++; y2++; y3++;
754 }
755
756 points[0].x = x1;
757 points[0].y = y1;
758 points[1].x = x2;
759 points[1].y = y2;
760 points[2].x = x3;
761 points[2].y = y3;
762 points[3].x = x1;
763 points[3].y = y1;
764
765 XLOCK (im->x.x_lock_display, im->x.disp);
766 XFillPolygon(im->x.disp, p->image->pixmap, p->image->gc,
767 &points[0], 4, Convex, CoordModeOrigin);
768 XUNLOCK (im->x.x_unlock_display, im->x.disp);
769
770 x1 += w;
771 x2 += w;
772 x3 += w;
773 }
774
775 }
776
777 /*
778 *
779 */
_draw_arrow(ImlibData * im,xitk_image_t * p,int direction)780 static void _draw_arrow(ImlibData *im, xitk_image_t *p, int direction) {
781 int w;
782 int h;
783 XSegment *segments;
784 int nsegments;
785 int i, s;
786 int x1, x2, dx;
787 int y1, y2, dy;
788
789 ABORT_IF_NULL(im);
790 ABORT_IF_NULL(p);
791
792 w = p->width / 3;
793 h = p->height;
794
795 /*
796 * XFillPolygon doesn't yield equally shaped arbitrary sized small triangles
797 * because of its filling algorithm (see also fill-rule in XCreateGC(3X11)
798 * as for which pixels are drawn on the boundary).
799 * So we handcraft them using XDrawSegments applying Bresenham's algorithm.
800 */
801
802 /* Coords of the enclosing rectangle for the triangle: */
803 /* Pay attention to integer precision loss and calculate */
804 /* carefully to obtain symmetrical and centered shapes. */
805 x1 = ((w - 1) / 2) - (w / 4);
806 x2 = ((w - 1) / 2) + (w / 4);
807 y1 = ((h - 1) / 2) - (h / 4);
808 y2 = ((h - 1) / 2) + (h / 4);
809
810 dx = (x2 - x1 + 1);
811 dy = (y2 - y1 + 1);
812
813 if(direction == DIRECTION_UP || direction == DIRECTION_DOWN) {
814 int y, iy, dd;
815
816 nsegments = dy;
817 segments = (XSegment *) calloc(nsegments, sizeof(XSegment));
818
819 if(direction == DIRECTION_DOWN) {
820 y = y1; iy = 1;
821 }
822 else {
823 y = y2; iy = -1;
824 }
825 dx = (dx + 1) / 2;
826 dd = 0;
827 for(s = 0; s < nsegments; s++) {
828 segments[s].y1 = y; segments[s].x1 = x1;
829 segments[s].y2 = y; segments[s].x2 = x2;
830 y += iy;
831 if(dy >= dx) {
832 if((dd += dx) >= dy) {
833 x1++; x2--;
834 dd -= dy;
835 }
836 }
837 else {
838 do {
839 x1++; x2--;
840 } while((dd += dy) < dx);
841 dd -= dx;
842 }
843 }
844 }
845 else if(direction == DIRECTION_LEFT || direction == DIRECTION_RIGHT) {
846 int x, ix, dd;
847
848 nsegments = dx;
849 segments = (XSegment *) calloc(nsegments, sizeof(XSegment));
850
851 if(direction == DIRECTION_RIGHT) {
852 x = x1; ix = 1;
853 }
854 else {
855 x = x2; ix = -1;
856 }
857 dy = (dy + 1) / 2;
858 dd = 0;
859 for(s = 0; s < nsegments; s++) {
860 segments[s].x1 = x; segments[s].y1 = y1;
861 segments[s].x2 = x; segments[s].y2 = y2;
862 x += ix;
863 if(dx >= dy) {
864 if((dd += dy) >= dx) {
865 y1++; y2--;
866 dd -= dx;
867 }
868 }
869 else {
870 do {
871 y1++; y2--;
872 } while((dd += dx) < dy);
873 dd -= dy;
874 }
875 }
876 }
877 else {
878 XITK_WARNING("direction '%d' is unhandled.\n", direction);
879 return;
880 }
881
882 XLOCK (im->x.x_lock_display, im->x.disp);
883 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
884 XUNLOCK (im->x.x_unlock_display, im->x.disp);
885
886 for(i = 0; i < 3; i++) {
887
888 if(i == 2) {
889 for(s = 0; s < nsegments; s++) {
890 segments[s].x1++; segments[s].y1++;
891 segments[s].x2++; segments[s].y2++;
892 }
893 }
894
895 XLOCK (im->x.x_lock_display, im->x.disp);
896 XDrawSegments(im->x.disp, p->image->pixmap, p->image->gc,
897 &segments[0], nsegments);
898 XUNLOCK (im->x.x_unlock_display, im->x.disp);
899
900 for(s = 0; s < nsegments; s++) {
901 segments[s].x1 += w;
902 segments[s].x2 += w;
903 }
904 }
905
906 free(segments);
907 }
908
909 /*
910 *
911 */
draw_arrow_up(ImlibData * im,xitk_image_t * p)912 void draw_arrow_up(ImlibData *im, xitk_image_t *p) {
913 _draw_arrow(im, p, DIRECTION_UP);
914 }
draw_arrow_down(ImlibData * im,xitk_image_t * p)915 void draw_arrow_down(ImlibData *im, xitk_image_t *p) {
916 _draw_arrow(im, p, DIRECTION_DOWN);
917 }
draw_arrow_left(ImlibData * im,xitk_image_t * p)918 void draw_arrow_left(ImlibData *im, xitk_image_t *p) {
919 _draw_arrow(im, p, DIRECTION_LEFT);
920 }
draw_arrow_right(ImlibData * im,xitk_image_t * p)921 void draw_arrow_right(ImlibData *im, xitk_image_t *p) {
922 _draw_arrow(im, p, DIRECTION_RIGHT);
923 }
924
925 /*
926 *
927 */
_draw_rectangular_box(ImlibData * im,xitk_pixmap_t * p,int x,int y,int excstart,int excstop,int width,int height,int relief)928 static void _draw_rectangular_box(ImlibData *im, xitk_pixmap_t *p,
929 int x, int y, int excstart, int excstop,
930 int width, int height, int relief) {
931 ABORT_IF_NULL(im);
932 ABORT_IF_NULL(p);
933
934 XLOCK (im->x.x_lock_display, im->x.disp);
935 if(relief == DRAW_OUTTER)
936 XSetForeground(im->x.disp, p->gc, xitk_get_pixel_color_white(im));
937 else if(relief == DRAW_INNER)
938 XSetForeground(im->x.disp, p->gc, xitk_get_pixel_color_black(im));
939
940 XDrawLine(im->x.disp, p->pixmap, p->gc, x, y, (x + excstart), y);
941 XDrawLine(im->x.disp, p->pixmap, p->gc, (x + excstop), y, (x + width - 1), y);
942 XDrawLine(im->x.disp, p->pixmap, p->gc, x, y, x, (y + height));
943 XUNLOCK (im->x.x_unlock_display, im->x.disp);
944
945 XLOCK (im->x.x_lock_display, im->x.disp);
946 if(relief == DRAW_OUTTER)
947 XSetForeground(im->x.disp, p->gc, xitk_get_pixel_color_black(im));
948 else if(relief == DRAW_INNER)
949 XSetForeground(im->x.disp, p->gc, xitk_get_pixel_color_white(im));
950
951 XDrawLine(im->x.disp, p->pixmap, p->gc, (x + width), y, (x + width), (y + height));
952 XDrawLine(im->x.disp, p->pixmap, p->gc, (x + 1), (y + height), (x + width), (y + height));
953 XUNLOCK (im->x.x_unlock_display, im->x.disp);
954 }
955
956 /*
957 *
958 */
_draw_rectangular_box_light(ImlibData * im,xitk_pixmap_t * p,int x,int y,int excstart,int excstop,int width,int height,int relief)959 static void _draw_rectangular_box_light(ImlibData *im, xitk_pixmap_t *p,
960 int x, int y, int excstart, int excstop,
961 int width, int height, int relief) {
962 ABORT_IF_NULL(im);
963 ABORT_IF_NULL(p);
964
965 XLOCK (im->x.x_lock_display, im->x.disp);
966 if(relief == DRAW_OUTTER)
967 XSetForeground(im->x.disp, p->gc, xitk_get_pixel_color_white(im));
968 else if(relief == DRAW_INNER)
969 XSetForeground(im->x.disp, p->gc, xitk_get_pixel_color_darkgray(im));
970
971 XDrawLine(im->x.disp, p->pixmap, p->gc, x, y, (x + excstart), y);
972 XDrawLine(im->x.disp, p->pixmap, p->gc, (x + excstop), y, (x + width - 1), y);
973 XDrawLine(im->x.disp, p->pixmap, p->gc, x, y, x, (y + height));
974 XUNLOCK (im->x.x_unlock_display, im->x.disp);
975
976 XLOCK (im->x.x_lock_display, im->x.disp);
977 if(relief == DRAW_OUTTER)
978 XSetForeground(im->x.disp, p->gc, xitk_get_pixel_color_darkgray(im));
979 else if(relief == DRAW_INNER)
980 XSetForeground(im->x.disp, p->gc, xitk_get_pixel_color_white(im));
981
982 XDrawLine(im->x.disp, p->pixmap, p->gc, (x + width), y, (x + width), (y + height));
983 XDrawLine(im->x.disp, p->pixmap, p->gc, (x + 1), (y + height), (x + width), (y + height));
984 XUNLOCK (im->x.x_unlock_display, im->x.disp);
985 }
986
987 /*
988 *
989 */
_draw_rectangular_box_with_colors(ImlibData * im,xitk_pixmap_t * p,int x,int y,int width,int height,unsigned int lcolor,unsigned int dcolor,int relief)990 static void _draw_rectangular_box_with_colors(ImlibData *im, xitk_pixmap_t *p,
991 int x, int y, int width, int height,
992 unsigned int lcolor, unsigned int dcolor,
993 int relief) {
994 ABORT_IF_NULL(im);
995 ABORT_IF_NULL(p);
996
997 XLOCK (im->x.x_lock_display, im->x.disp);
998 if(relief == DRAW_OUTTER)
999 XSetForeground(im->x.disp, p->gc, lcolor);
1000 else if(relief == DRAW_INNER)
1001 XSetForeground(im->x.disp, p->gc, dcolor);
1002
1003 XDrawLine(im->x.disp, p->pixmap, p->gc, x, y, (x + width - 1), y);
1004 XDrawLine(im->x.disp, p->pixmap, p->gc, x, y, x, (y + height));
1005 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1006
1007 XLOCK (im->x.x_lock_display, im->x.disp);
1008 if(relief == DRAW_OUTTER)
1009 XSetForeground(im->x.disp, p->gc, dcolor);
1010 else if(relief == DRAW_INNER)
1011 XSetForeground(im->x.disp, p->gc, lcolor);
1012
1013 XDrawLine(im->x.disp, p->pixmap, p->gc, (x + width), y, (x + width), (y + height));
1014 XDrawLine(im->x.disp, p->pixmap, p->gc, (x + 1), (y + height), (x + width), (y + height));
1015 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1016 }
1017
1018 /*
1019 *
1020 */
draw_rectangular_inner_box(ImlibData * im,xitk_pixmap_t * p,int x,int y,int width,int height)1021 void draw_rectangular_inner_box(ImlibData *im, xitk_pixmap_t *p,
1022 int x, int y, int width, int height) {
1023 _draw_rectangular_box(im, p, x, y, 0, 0, width, height, DRAW_INNER);
1024 }
draw_rectangular_outter_box(ImlibData * im,xitk_pixmap_t * p,int x,int y,int width,int height)1025 void draw_rectangular_outter_box(ImlibData *im, xitk_pixmap_t *p,
1026 int x, int y, int width, int height) {
1027 _draw_rectangular_box(im, p, x, y, 0, 0, width, height, DRAW_OUTTER);
1028 }
draw_rectangular_inner_box_light(ImlibData * im,xitk_pixmap_t * p,int x,int y,int width,int height)1029 void draw_rectangular_inner_box_light(ImlibData *im, xitk_pixmap_t *p,
1030 int x, int y, int width, int height) {
1031 _draw_rectangular_box_light(im, p, x, y, 0, 0, width, height, DRAW_INNER);
1032 }
draw_rectangular_outter_box_light(ImlibData * im,xitk_pixmap_t * p,int x,int y,int width,int height)1033 void draw_rectangular_outter_box_light(ImlibData *im, xitk_pixmap_t *p,
1034 int x, int y, int width, int height) {
1035 _draw_rectangular_box_light(im, p, x, y, 0, 0, width, height, DRAW_OUTTER);
1036 }
1037
_draw_check_round(ImlibData * im,xitk_image_t * p,int x,int y,int d,int checked)1038 static void _draw_check_round(ImlibData *im, xitk_image_t *p, int x, int y, int d, int checked) {
1039 XLOCK (im->x.x_lock_display, im->x.disp);
1040 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
1041 XFillArc(im->x.disp, p->image->pixmap, p->image->gc, x, y, d, d, (30 * 64), (180 * 64));
1042 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1043
1044 XLOCK (im->x.x_lock_display, im->x.disp);
1045 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_darkgray(im));
1046 XFillArc(im->x.disp, p->image->pixmap, p->image->gc, x, y, d, d, (210 * 64), (180 * 64));
1047 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1048
1049 XLOCK (im->x.x_lock_display, im->x.disp);
1050 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_white(im));
1051 XFillArc(im->x.disp, p->image->pixmap, p->image->gc, x + 2, y + 2, d - 4, d - 4, (0 * 64), (360 * 64));
1052 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1053
1054 if(checked) {
1055 XLOCK (im->x.x_lock_display, im->x.disp);
1056 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
1057 XFillArc(im->x.disp, p->image->pixmap, p->image->gc, x + 4, y + 4, d - 8, d - 8, (0 * 64), (360 * 64));
1058 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1059 }
1060 }
_draw_check_check(ImlibData * im,xitk_image_t * p,int x,int y,int d,int checked)1061 static void _draw_check_check(ImlibData *im, xitk_image_t *p, int x, int y, int d, int checked) {
1062 /* background */
1063 XLOCK (im->x.x_lock_display, im->x.disp);
1064 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_lightgray(im));
1065 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, x, y, d, d);
1066 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1067 /* */
1068 XLOCK (im->x.x_lock_display, im->x.disp);
1069 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
1070 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, x, y, x + d, y);
1071 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, x, y, x, y + d);
1072 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1073
1074 XLOCK (im->x.x_lock_display, im->x.disp);
1075 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_darkgray(im));
1076 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, x, y + d, x + d, y + d);
1077 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, x + d, y, x + d, y + d);
1078 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1079
1080 if(checked) {
1081 XLOCK (im->x.x_lock_display, im->x.disp);
1082 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
1083 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, x + (d / 5), (y + ((d / 3) * 2)) - 2, x + (d / 2), y + d - 2);
1084 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, x + (d / 5)+1, (y + ((d / 3) * 2)) - 2, x + (d / 2) + 1, y + d - 2);
1085 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, x + (d / 2), y + d - 2, x + d - 2, y+1);
1086 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, x + (d / 2) + 1, y + d - 2, x + d - 1, y+1);
1087 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1088 }
1089
1090 }
1091
draw_check_three_state_round_style(ImlibData * im,xitk_image_t * p,int x,int y,int d,int w,int checked)1092 static void draw_check_three_state_round_style(ImlibData *im, xitk_image_t *p, int x, int y, int d, int w, int checked) {
1093 int i;
1094
1095 ABORT_IF_NULL(im);
1096 ABORT_IF_NULL(p);
1097
1098 for(i = 0; i < 3; i++) {
1099 if(i == 2) {
1100 x++;
1101 y++;
1102 }
1103
1104 _draw_check_round(im, p, x, y, d, checked);
1105 x += w;
1106 }
1107 }
1108
draw_check_three_state_check_style(ImlibData * im,xitk_image_t * p,int x,int y,int d,int w,int checked)1109 static void draw_check_three_state_check_style(ImlibData *im, xitk_image_t *p, int x, int y, int d, int w, int checked) {
1110 int i;
1111
1112 ABORT_IF_NULL(im);
1113 ABORT_IF_NULL(p);
1114
1115 for(i = 0; i < 3; i++) {
1116 if(i == 2) {
1117 x++;
1118 y++;
1119 }
1120
1121 _draw_check_check(im, p, x, y, d, checked);
1122 x += w;
1123 }
1124 }
1125
menu_draw_check(ImlibData * im,xitk_image_t * p,int checked)1126 void menu_draw_check(ImlibData *im, xitk_image_t *p, int checked) {
1127 int style = xitk_get_checkstyle_feature();
1128
1129 ABORT_IF_NULL(im);
1130 ABORT_IF_NULL(p);
1131
1132 switch(style) {
1133
1134 case CHECK_STYLE_CHECK:
1135 draw_check_three_state_check_style(im, p, 4, 4, p->height - 8, p->width / 3, checked);
1136 break;
1137
1138 case CHECK_STYLE_ROUND:
1139 draw_check_three_state_round_style(im, p, 4, 4, p->height - 8, p->width / 3, checked);
1140 break;
1141
1142 case CHECK_STYLE_OLD:
1143 default:
1144 {
1145 int relief = (checked) ? DRAW_INNER : DRAW_OUTTER;
1146 int nrelief = (checked) ? DRAW_OUTTER : DRAW_INNER;
1147 int w, h;
1148
1149 w = p->width / 3;
1150 h = p->height - 12;
1151 _draw_rectangular_box(im, p->image, 4, 6, 0, 0, 12, h, relief);
1152 _draw_rectangular_box(im, p->image, w + 4, 6, 0, 0, 12, h, relief);
1153 _draw_rectangular_box(im, p->image, (w * 2) + 4 + 1, 6 + 1, 0, 0, 12, h, nrelief);
1154 }
1155 break;
1156 }
1157 }
1158
1159 /*
1160 *
1161 */
_draw_three_state(ImlibData * im,xitk_image_t * p,int style)1162 static void _draw_three_state(ImlibData *im, xitk_image_t *p, int style) {
1163 int w;
1164 int h;
1165
1166 ABORT_IF_NULL(im);
1167 ABORT_IF_NULL(p);
1168
1169 w = p->width / 3;
1170 h = p->height;
1171
1172 XLOCK (im->x.x_lock_display, im->x.disp);
1173 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_gray(im));
1174 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, 0, 0, w , h);
1175 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_lightgray(im));
1176 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, w, 0, (w * 2) , h);
1177 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1178
1179 XLOCK (im->x.x_lock_display, im->x.disp);
1180 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_white(im));
1181 if(style == STYLE_BEVEL) {
1182 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 0, 0, w, 0);
1183 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 0, 0, 0, (h - 1));
1184 }
1185 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w, 0, (w * 2), 0);
1186 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w, 0, w, (h - 1));
1187 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1188
1189 XLOCK (im->x.x_lock_display, im->x.disp);
1190 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_darkgray(im));
1191 if(style == STYLE_BEVEL) {
1192 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w - 2), 2, (w - 2), (h - 3));
1193 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 2, (h - 2), w-2, (h - 2));
1194 }
1195 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 2*w - 2, 2, 2*w - 2, h - 3);
1196 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w+2, h - 2, 2*w - 2, h - 2);
1197 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w * 2, 0, w * 3, 0);
1198 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w * 2, 0, w * 2, h - 1);
1199 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1200
1201 XLOCK (im->x.x_lock_display, im->x.disp);
1202 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, w * 2 , 0, (w - 1), (h - 1));
1203
1204 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
1205 if(style == STYLE_BEVEL) {
1206 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w - 1), 0, (w - 1), (h - 1));
1207 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 0, (h - 1), w-1, (h - 1));
1208 }
1209 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2)+1, 1, (w * 3)-1, 1);
1210 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2)+1, 1, (w * 2)+1, (h - 2));
1211 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2) - 1, 0, (w * 2) - 1, h);
1212 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w, (h - 1), (w * 2)-1, (h - 1));
1213 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1214
1215 XLOCK (im->x.x_lock_display, im->x.disp);
1216 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_white(im));
1217 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 3) - 1, 1, (w * 3) - 1, (h - 1));
1218 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2) + 1, (h - 1), (w * 3), (h - 1));
1219 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1220 }
1221
1222 /*
1223 *
1224 */
_draw_two_state(ImlibData * im,xitk_image_t * p,int style)1225 static void _draw_two_state(ImlibData *im, xitk_image_t *p, int style) {
1226 int w;
1227 int h;
1228
1229 ABORT_IF_NULL(im);
1230 ABORT_IF_NULL(p);
1231
1232 w = p->width / 2;
1233 h = p->height;
1234
1235 XLOCK (im->x.x_lock_display, im->x.disp);
1236 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_gray(im));
1237 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, 0, 0, w - 1, h - 1);
1238 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_lightgray(im));
1239 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, w, 0, (w * 2) - 1 , h - 1);
1240 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1241
1242 XLOCK (im->x.x_lock_display, im->x.disp);
1243 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
1244 if(style == STYLE_BEVEL) {
1245 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 0, 0, w, 0);
1246 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 0, 0, 0, (h - 1));
1247 }
1248 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w, 0, (w * 2), 0);
1249 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w, 0, w, (h - 1));
1250 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1251
1252 XLOCK (im->x.x_lock_display, im->x.disp);
1253 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_white(im));
1254 if(style == STYLE_BEVEL) {
1255 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w - 1), 0 , (w - 1), (h - 1));
1256 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 0 ,(h - 1), w , (h - 1));
1257 }
1258 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2) - 1, 0, (w * 2) - 1, h);
1259 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w, (h - 1),(w * 2), (h - 1));
1260 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1261 }
1262
1263 /*
1264 *
1265 */
_draw_relief(ImlibData * im,xitk_pixmap_t * p,int w,int h,int relief,int light)1266 static void _draw_relief(ImlibData *im, xitk_pixmap_t *p, int w, int h, int relief, int light) {
1267 ABORT_IF_NULL(im);
1268 ABORT_IF_NULL(p);
1269
1270 XLOCK (im->x.x_lock_display, im->x.disp);
1271 XSetForeground(im->x.disp, p->gc, xitk_get_pixel_color_gray(im));
1272 XFillRectangle(im->x.disp, p->pixmap, p->gc, 0, 0, w , h);
1273 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1274
1275 if(relief != DRAW_FLATTER) {
1276
1277 _draw_rectangular_box_with_colors(im, p, 0, 0, w-1, h-1,
1278 xitk_get_pixel_color_white(im),
1279 ((light)
1280 ? xitk_get_pixel_color_darkgray(im)
1281 : xitk_get_pixel_color_black(im)),
1282 relief);
1283 }
1284
1285 }
1286
draw_checkbox_check(ImlibData * im,xitk_image_t * p)1287 void draw_checkbox_check(ImlibData *im, xitk_image_t *p) {
1288 int style = xitk_get_checkstyle_feature();
1289
1290 XLOCK (im->x.x_lock_display, im->x.disp);
1291 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_gray(im));
1292 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, 0, 0, p->width, p->height);
1293 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1294
1295 switch(style) {
1296
1297 case CHECK_STYLE_CHECK:
1298 {
1299 int w;
1300
1301 w = p->width / 3;
1302 _draw_check_check(im, p, 0, 0, p->height, 0);
1303 _draw_check_check(im, p, w, 0, p->height, 0);
1304 _draw_check_check(im, p, w * 2, 0, p->height, 1);
1305 }
1306 break;
1307
1308 case CHECK_STYLE_ROUND:
1309 {
1310 int w;
1311
1312 w = p->width / 3;
1313 _draw_check_round(im, p, 0, 0, p->height, 0);
1314 _draw_check_round(im, p, w, 0, p->height, 0);
1315 _draw_check_round(im, p, w * 2, 0, p->height, 1);
1316 }
1317 break;
1318
1319 case CHECK_STYLE_OLD:
1320 default:
1321 _draw_three_state(im, p, STYLE_BEVEL);
1322 break;
1323 }
1324 }
1325
1326 /*
1327 *
1328 */
draw_flat_three_state(ImlibData * im,xitk_image_t * p)1329 void draw_flat_three_state(ImlibData *im, xitk_image_t *p) {
1330 _draw_three_state(im, p, STYLE_FLAT);
1331 }
1332
1333 /*
1334 *
1335 */
draw_bevel_three_state(ImlibData * im,xitk_image_t * p)1336 void draw_bevel_three_state(ImlibData *im, xitk_image_t *p) {
1337 _draw_three_state(im, p, STYLE_BEVEL);
1338 }
1339
1340 /*
1341 *
1342 */
draw_bevel_two_state(ImlibData * im,xitk_image_t * p)1343 void draw_bevel_two_state(ImlibData *im, xitk_image_t *p) {
1344 _draw_two_state(im, p, STYLE_BEVEL);
1345 }
1346
1347 /*
1348 *
1349 */
_draw_paddle_three_state(ImlibData * im,xitk_image_t * p,int direction)1350 static void _draw_paddle_three_state(ImlibData *im, xitk_image_t *p, int direction) {
1351 int w;
1352 int h;
1353
1354 ABORT_IF_NULL(im);
1355 ABORT_IF_NULL(p);
1356
1357 w = p->width / 3;
1358 h = p->height;
1359
1360 XLOCK (im->x.x_lock_display, im->x.disp);
1361 /* Draw mask */
1362 XSetForeground(im->x.disp, p->mask->gc, 0);
1363 /* Top */
1364 XDrawLine(im->x.disp, p->mask->pixmap, p->mask->gc, 0, 0, (w - 1), 0);
1365 XDrawLine(im->x.disp, p->mask->pixmap, p->mask->gc, 0, 1, (w - 1), 1);
1366 /* Bottom */
1367 XDrawLine(im->x.disp, p->mask->pixmap, p->mask->gc, 0, (h - 1), (w - 1), (h - 1));
1368 XDrawLine(im->x.disp, p->mask->pixmap, p->mask->gc, 0, (h - 1) - 1, (w - 1), (h - 1) - 1);
1369 /* Left */
1370 XDrawLine(im->x.disp, p->mask->pixmap, p->mask->gc, 0, 0, 0, (h - 1));
1371 XDrawLine(im->x.disp, p->mask->pixmap, p->mask->gc, 1, 0, 1, (h - 1));
1372 /* Right */
1373 XDrawLine(im->x.disp, p->mask->pixmap, p->mask->gc, (w - 1), 0, (w - 1), (h - 1));
1374 XDrawLine(im->x.disp, p->mask->pixmap, p->mask->gc, (w - 1) - 1, 0, (w - 1) - 1, (h - 1));
1375 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1376
1377 XLOCK (im->x.x_lock_display, im->x.disp);
1378 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_gray(im));
1379 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, 2, 2, w - 4, (h - 1) - 2);
1380
1381 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_lightgray(im));
1382 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, w + 2, 2, (w * 2) - 4, (h - 1) - 2);
1383
1384 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_darkgray(im));
1385 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, (w * 2) + 2, 2, ((w * 3) - 1) - 4, (h - 1) - 2);
1386 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1387
1388 _draw_rectangular_box_with_colors(im, p->image, 2, 2, (w-1)-4, (h-1)-4,
1389 xitk_get_pixel_color_white(im),
1390 xitk_get_pixel_color_black(im),
1391 DRAW_OUTTER);
1392 _draw_rectangular_box_with_colors(im, p->image, w+2, 2, (w-1)-4, (h-1)-4,
1393 xitk_get_pixel_color_white(im),
1394 xitk_get_pixel_color_black(im),
1395 DRAW_OUTTER);
1396 _draw_rectangular_box_with_colors(im, p->image, (w*2)+2, 2, (w-1)-4, (h-1)-4,
1397 xitk_get_pixel_color_white(im),
1398 xitk_get_pixel_color_black(im),
1399 DRAW_INNER);
1400
1401 { /* Enlightening paddle */
1402 int xx, yy, ww, hh;
1403 int i, offset = 0;
1404
1405 if(direction == DIRECTION_UP) {
1406 xx = 4; yy = ((h-1)>>1); ww = (w-1) - 8; hh = 1;
1407 }
1408 else if(direction == DIRECTION_LEFT) {
1409 xx = ((w-1)>>1); yy = 4; ww = 1; hh = (h-1) - 8;
1410 }
1411 else {
1412 XITK_WARNING("direction '%d' is unhandled.\n",direction);
1413 return;
1414 }
1415
1416 for(i = 0; i < 3; i++, offset += w) {
1417 if(i == 2) { xx++; yy++; }
1418 draw_rectangular_outter_box(im, p->image, xx + offset, yy, ww, hh);
1419 }
1420 }
1421
1422 }
1423
1424 /*
1425 *
1426 */
draw_paddle_three_state_vertical(ImlibData * im,xitk_image_t * p)1427 void draw_paddle_three_state_vertical(ImlibData *im, xitk_image_t *p) {
1428 _draw_paddle_three_state(im, p, DIRECTION_UP);
1429 }
draw_paddle_three_state_horizontal(ImlibData * im,xitk_image_t * p)1430 void draw_paddle_three_state_horizontal(ImlibData *im, xitk_image_t *p) {
1431 _draw_paddle_three_state(im, p, DIRECTION_LEFT);
1432 }
1433
1434 /*
1435 *
1436 */
draw_inner(ImlibData * im,xitk_pixmap_t * p,int w,int h)1437 void draw_inner(ImlibData *im, xitk_pixmap_t *p, int w, int h) {
1438 _draw_relief(im, p, w, h, DRAW_INNER, 0);
1439 }
draw_inner_light(ImlibData * im,xitk_pixmap_t * p,int w,int h)1440 void draw_inner_light(ImlibData *im, xitk_pixmap_t *p, int w, int h) {
1441 _draw_relief(im, p, w, h, DRAW_INNER, 1);
1442 }
1443
1444 /*
1445 *
1446 */
draw_outter(ImlibData * im,xitk_pixmap_t * p,int w,int h)1447 void draw_outter(ImlibData *im, xitk_pixmap_t *p, int w, int h) {
1448 _draw_relief(im, p, w, h, DRAW_OUTTER, 0);
1449 }
draw_outter_light(ImlibData * im,xitk_pixmap_t * p,int w,int h)1450 void draw_outter_light(ImlibData *im, xitk_pixmap_t *p, int w, int h) {
1451 _draw_relief(im, p, w, h, DRAW_OUTTER, 1);
1452 }
1453
1454 /*
1455 *
1456 */
draw_flat(ImlibData * im,xitk_pixmap_t * p,int w,int h)1457 void draw_flat(ImlibData *im, xitk_pixmap_t *p, int w, int h) {
1458 _draw_relief(im, p, w, h, DRAW_FLATTER, 1);
1459 }
1460
1461 /*
1462 *
1463 */
draw_flat_with_color(ImlibData * im,xitk_pixmap_t * p,int w,int h,unsigned int color)1464 void draw_flat_with_color(ImlibData *im, xitk_pixmap_t *p, int w, int h, unsigned int color) {
1465 ABORT_IF_NULL(im);
1466 ABORT_IF_NULL(p);
1467
1468 XLOCK (im->x.x_lock_display, im->x.disp);
1469 XSetForeground(im->x.disp, p->gc, color);
1470 XFillRectangle(im->x.disp, p->pixmap, p->gc, 0, 0, w , h);
1471 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1472 }
1473
1474 /*
1475 * Draw a frame outline with embedded title.
1476 */
_draw_frame(ImlibData * im,xitk_pixmap_t * p,const char * title,const char * fontname,int style,int x,int y,int w,int h)1477 static void _draw_frame(ImlibData *im, xitk_pixmap_t *p,
1478 const char *title, const char *fontname,
1479 int style, int x, int y, int w, int h) {
1480 xitk_font_t *fs = NULL;
1481 int sty[2];
1482 int yoff = 0, xstart = 0, xstop = 0;
1483 int ascent = 0, descent = 0, lbearing = 0, rbearing = 0;
1484 int titlelen = 0;
1485 const char *titlebuf = NULL;
1486 char buf[BUFSIZ];
1487
1488 ABORT_IF_NULL(im);
1489 ABORT_IF_NULL(p);
1490
1491 if(title) {
1492 int maxinkwidth = (w - 12);
1493
1494 titlelen = strlen(title);
1495 titlebuf = title;
1496
1497 fs = xitk_font_load_font(im->x.disp, (fontname ? fontname : DEFAULT_FONT_12));
1498 xitk_font_set_font(fs, p->gc);
1499 xitk_font_text_extent(fs, title, titlelen, &lbearing, &rbearing, NULL, &ascent, &descent);
1500
1501 /* Limit title to frame width */
1502 if((rbearing - lbearing) > maxinkwidth) {
1503 char dots[] = "...";
1504 int dotslen = strlen(dots);
1505 int dotsrbearing;
1506 int titlewidth;
1507
1508 /* Cut title, append dots */
1509 xitk_font_text_extent(fs, dots, dotslen, NULL, &dotsrbearing, NULL, NULL, NULL);
1510 do {
1511 titlelen--;
1512 xitk_font_text_extent(fs, title, titlelen, NULL, NULL, &titlewidth, NULL, NULL);
1513 rbearing = titlewidth + dotsrbearing;
1514 } while((rbearing - lbearing) > maxinkwidth);
1515 { /* Cut possible incomplete multibyte character at the end */
1516 int titlewidth1;
1517 while((titlelen > 0) &&
1518 (xitk_font_text_extent(fs, title, (titlelen - 1), NULL, NULL, &titlewidth1, NULL, NULL),
1519 titlewidth1 == titlewidth))
1520 titlelen--;
1521 }
1522 if(titlelen > (sizeof(buf) - dotslen - 1)) /* Should never happen, */
1523 titlelen = (sizeof(buf) - dotslen - 1); /* just to be sure ... */
1524 strlcpy(buf, title, titlelen);
1525 strcat(buf, dots);
1526 titlelen += dotslen;
1527 titlebuf = buf;
1528 }
1529 }
1530
1531 sty[0] = (style == DRAW_INNER) ? DRAW_INNER : DRAW_OUTTER;
1532 sty[1] = (style == DRAW_INNER) ? DRAW_OUTTER : DRAW_INNER;
1533
1534 /* Dont draw frame box under frame title */
1535 if(title) {
1536 yoff = (ascent >> 1) + 1; /* Roughly v-center outline to ascent part of glyphs */
1537 xstart = 4 - 1;
1538 xstop = (rbearing - lbearing) + 8;
1539 }
1540
1541 _draw_rectangular_box_light(im, p, x, (y + yoff),
1542 xstart, xstop,
1543 w, (h - yoff), sty[0]);
1544
1545 if(title)
1546 xstart--, xstop--;
1547
1548 _draw_rectangular_box_light(im, p, (x + 1), ((y + yoff) + 1),
1549 xstart, xstop,
1550 (w - 2), ((h - yoff) - 2), sty[1]);
1551
1552 if(title) {
1553 XLOCK (im->x.x_lock_display, im->x.disp);
1554 XSetForeground(im->x.disp, p->gc, xitk_get_pixel_color_black(im));
1555 xitk_font_draw_string(fs, p->pixmap, p->gc, (x - lbearing + 6), (y + ascent), titlebuf, titlelen);
1556 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1557
1558 xitk_font_unload_font(fs);
1559 }
1560
1561 }
1562
1563 /*
1564 *
1565 */
draw_inner_frame(ImlibData * im,xitk_pixmap_t * p,const char * title,const char * fontname,int x,int y,int w,int h)1566 void draw_inner_frame(ImlibData *im, xitk_pixmap_t *p,
1567 const char *title, const char *fontname,
1568 int x, int y, int w, int h) {
1569 _draw_frame(im, p, title, fontname, DRAW_INNER, x, y, w, h);
1570 }
draw_outter_frame(ImlibData * im,xitk_pixmap_t * p,const char * title,const char * fontname,int x,int y,int w,int h)1571 void draw_outter_frame(ImlibData *im, xitk_pixmap_t *p,
1572 const char *title, const char *fontname,
1573 int x, int y, int w, int h) {
1574 _draw_frame(im, p, title, fontname, DRAW_OUTTER, x, y, w, h);
1575 }
1576
1577 /*
1578 *
1579 */
draw_tab(ImlibData * im,xitk_image_t * p)1580 void draw_tab(ImlibData *im, xitk_image_t *p) {
1581 int w, h;
1582
1583 ABORT_IF_NULL(im);
1584 ABORT_IF_NULL(p);
1585
1586 w = p->width / 3;
1587 h = p->height;
1588
1589 XLOCK (im->x.x_lock_display, im->x.disp);
1590 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_gray(im));
1591 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, 0, 0, (w * 3), h);
1592 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_lightgray(im));
1593 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, 0, 3, (w - 1), h);
1594 XFillRectangle(im->x.disp, p->image->pixmap, p->image->gc, w, 0, (w - 1), h);
1595 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1596
1597 XLOCK (im->x.x_lock_display, im->x.disp);
1598 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_white(im));
1599 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 0, 3, w, 3);
1600 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 0, 3, 0, h);
1601 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w, 0, (w * 2) - 1, 0);
1602 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w, 0, w, h);
1603 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1604
1605 XLOCK (im->x.x_lock_display, im->x.disp);
1606 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2) + 3, 0, (w * 3) - 1, 0);
1607 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2), 3, (w * 2), (h - 1));
1608 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2), 3, (w * 2) + 3, 0);
1609 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1610
1611 XLOCK (im->x.x_lock_display, im->x.disp);
1612 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
1613 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w - 1), 3, (w - 1), h);
1614 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2) - 1, 0, (w * 2) - 1, h);
1615 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 3) - 1, 0, (w * 3) - 1, h);
1616 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1617
1618 XLOCK (im->x.x_lock_display, im->x.disp);
1619 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_white(im));
1620 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 0, (h - 1), (w * 2) - 1, (h - 1));
1621 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1622 }
1623
1624 /*
1625 *
1626 */
draw_paddle_rotate(ImlibData * im,xitk_image_t * p)1627 void draw_paddle_rotate(ImlibData *im, xitk_image_t *p) {
1628 int w;
1629 int h;
1630 unsigned int ccolor, fcolor, ncolor;
1631
1632 ABORT_IF_NULL(im);
1633 ABORT_IF_NULL(p);
1634
1635 w = p->width/3;
1636 h = p->height;
1637 ncolor = xitk_get_pixel_color_darkgray(im);
1638 fcolor = xitk_get_pixel_color_warning_background(im);
1639 ccolor = xitk_get_pixel_color_lightgray(im);
1640
1641 {
1642 int x, i;
1643 unsigned int bg_colors[3] = { ncolor, fcolor, ccolor };
1644
1645 XLOCK (im->x.x_lock_display, im->x.disp);
1646 XSetForeground(im->x.disp, p->mask->gc, 0);
1647 XFillRectangle(im->x.disp, p->mask->pixmap, p->mask->gc, 0, 0, w * 3 , h);
1648 XSetForeground(im->x.disp, p->mask->gc, 1);
1649 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1650
1651 for(x = 0, i = 0; i < 3; i++) {
1652 XLOCK (im->x.x_lock_display, im->x.disp);
1653 XSetForeground(im->x.disp, p->mask->gc, 1);
1654 XFillArc(im->x.disp, p->mask->pixmap, p->mask->gc, x, 0, w-1, h-1, (0 * 64), (360 * 64));
1655 XDrawArc(im->x.disp, p->mask->pixmap, p->mask->gc, x, 0, w-1, h-1, (0 * 64), (360 * 64));
1656 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1657
1658 XLOCK (im->x.x_lock_display, im->x.disp);
1659 XSetForeground(im->x.disp, p->image->gc, bg_colors[i]);
1660 XFillArc(im->x.disp, p->image->pixmap, p->image->gc, x, 0, w-1, h-1, (0 * 64), (360 * 64));
1661 XDrawArc(im->x.disp, p->image->pixmap, p->image->gc, x, 0, w-1, h-1, (0 * 64), (360 * 64));
1662 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
1663 XDrawArc(im->x.disp, p->image->pixmap, p->image->gc, x, 0, w-1, h-1, (0 * 64), (360 * 64));
1664 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1665
1666 x += w;
1667 }
1668 }
1669 }
1670
1671 /*
1672 *
1673 */
draw_rotate_button(ImlibData * im,xitk_image_t * p)1674 void draw_rotate_button(ImlibData *im, xitk_image_t *p) {
1675 int w;
1676 int h;
1677
1678 ABORT_IF_NULL(im);
1679 ABORT_IF_NULL(p);
1680
1681 w = p->width;
1682 h = p->height;
1683
1684 XLOCK (im->x.x_lock_display, im->x.disp);
1685
1686 /* Draw mask */
1687 XSetForeground(im->x.disp, p->mask->gc, 0);
1688 XFillRectangle(im->x.disp, p->mask->pixmap, p->mask->gc, 0, 0, w , h);
1689
1690 XSetForeground(im->x.disp, p->mask->gc, 1);
1691 XFillArc(im->x.disp, p->mask->pixmap, p->mask->gc, 0, 0, w-1, h-1, (0 * 64), (360 * 64));
1692 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1693
1694 /* */
1695 XLOCK (im->x.x_lock_display, im->x.disp);
1696 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_gray(im));
1697 XFillArc(im->x.disp, p->image->pixmap, p->image->gc, 0, 0, w-1, h-1, (0 * 64), (360 * 64));
1698
1699 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_white(im));
1700 // XDrawArc(im->x.disp, p->image, p->image->gc, 0, 0, w-1, h-1, (30 * 64), (180 * 64));
1701 XDrawArc(im->x.disp, p->image->pixmap, p->image->gc, 1, 1, w-2, h-2, (30 * 64), (180 * 64));
1702 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1703
1704 XLOCK (im->x.x_lock_display, im->x.disp);
1705 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_darkgray(im));
1706 // XDrawArc(im->x.disp, p->image, p->image->gc, 0, 0, w-1, h-1, (210 * 64), (180 * 64));
1707 XDrawArc(im->x.disp, p->image->pixmap, p->image->gc, 1, 1, w-3, h-3, (210 * 64), (180 * 64));
1708 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1709 }
1710
1711 /*
1712 *
1713 */
draw_button_plus(ImlibData * im,xitk_image_t * p)1714 void draw_button_plus(ImlibData *im, xitk_image_t *p) {
1715 int w, h;
1716
1717 ABORT_IF_NULL(im);
1718 ABORT_IF_NULL(p);
1719
1720 draw_button_minus(im, p);
1721
1722 w = p->width / 3;
1723 h = p->height;
1724
1725 XLOCK (im->x.x_lock_display, im->x.disp);
1726 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
1727
1728 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w >> 1) - 1, 2, (w >> 1) - 1, h - 4);
1729 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w + (w >> 1) - 1, 2, w + (w >> 1) - 1, h - 4);
1730 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2) + (w >> 1), 3, (w * 2) + (w >> 1), h - 3);
1731
1732 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1733 }
1734
1735 /*
1736 *
1737 */
draw_button_minus(ImlibData * im,xitk_image_t * p)1738 void draw_button_minus(ImlibData *im, xitk_image_t *p) {
1739 int w, h;
1740
1741 ABORT_IF_NULL(im);
1742 ABORT_IF_NULL(p);
1743
1744 w = p->width / 3;
1745 h = p->height;
1746
1747 XLOCK (im->x.x_lock_display, im->x.disp);
1748 XSetForeground(im->x.disp, p->image->gc, xitk_get_pixel_color_black(im));
1749
1750 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, 2, (h >> 1) - 1, w - 4, (h >> 1) - 1);
1751 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, w + 2, (h >> 1) - 1, (w * 2) - 4, (h >> 1) - 1);
1752 XDrawLine(im->x.disp, p->image->pixmap, p->image->gc, (w * 2) + 3, h >> 1, (w * 3) - 3, h >> 1);
1753
1754 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1755 }
1756
1757 /*
1758 *
1759 */
xitk_image_load_image(ImlibData * im,const char * image)1760 xitk_image_t *xitk_image_load_image(ImlibData *im, const char *image) {
1761 ImlibImage *img = NULL;
1762 xitk_image_t *i;
1763
1764 ABORT_IF_NULL(im);
1765
1766 if(image == NULL) {
1767 XITK_WARNING("image name is NULL\n");
1768 return NULL;
1769 }
1770
1771 XLOCK (im->x.x_lock_display, im->x.disp);
1772 if(!(img = Imlib_load_image(im, (char *)image))) {
1773 XITK_WARNING("%s(): couldn't find image %s\n", __FUNCTION__, image);
1774 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1775 return NULL;
1776 }
1777
1778 Imlib_render (im, img, img->rgb_width, img->rgb_height);
1779 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1780
1781 i = (xitk_image_t *) xitk_xmalloc(sizeof(xitk_image_t));
1782 i->image = xitk_image_create_xitk_pixmap(im, img->rgb_width, img->rgb_height);
1783 i->pix_font = NULL;
1784 XLOCK (im->x.x_lock_display, im->x.disp);
1785 i->image->pixmap = Imlib_copy_image(im, img);
1786 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1787
1788 if(img->shape_mask) {
1789 i->mask = xitk_image_create_xitk_mask_pixmap(im, img->rgb_width, img->rgb_height);
1790 XLOCK (im->x.x_lock_display, im->x.disp);
1791 i->mask->pixmap = Imlib_copy_mask(im, img);
1792 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1793 }
1794 else {
1795 i->mask = NULL;
1796 }
1797
1798 i->width = img->rgb_width;
1799 i->height = img->rgb_height;
1800
1801 XLOCK (im->x.x_lock_display, im->x.disp);
1802 Imlib_destroy_image(im, img);
1803 XUNLOCK (im->x.x_unlock_display, im->x.disp);
1804
1805 return i;
1806 }
1807
1808 /*
1809 * ********************************************************************************
1810 * Widget specific part
1811 * ********************************************************************************
1812 */
1813
1814 /*
1815 *
1816 */
notify_destroy(xitk_widget_t * w)1817 static void notify_destroy(xitk_widget_t *w) {
1818 image_private_data_t *private_data;
1819
1820 if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_IMAGE)) {
1821 private_data = (image_private_data_t *) w->private_data;
1822
1823 if(!private_data->skin_element_name)
1824 xitk_image_free_image(private_data->imlibdata, &(private_data->skin));
1825
1826 XITK_FREE(private_data->skin_element_name);
1827 XITK_FREE(private_data);
1828 }
1829 }
1830
1831 /*
1832 *
1833 */
notify_inside(xitk_widget_t * w,int x,int y)1834 static int notify_inside(xitk_widget_t *w, int x, int y) {
1835 return 0;
1836 }
1837
1838 /*
1839 *
1840 */
get_skin(xitk_widget_t * w,int sk)1841 static xitk_image_t *get_skin(xitk_widget_t *w, int sk) {
1842 image_private_data_t *private_data;
1843
1844 if(w && ((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_IMAGE)) {
1845 private_data = (image_private_data_t *) w->private_data;
1846 if(sk == BACKGROUND_SKIN && private_data->skin) {
1847 return private_data->skin;
1848 }
1849 }
1850
1851 return NULL;
1852 }
1853
1854 /*
1855 *
1856 */
paint_image(xitk_widget_t * w)1857 static void paint_image (xitk_widget_t *w) {
1858 image_private_data_t *private_data;
1859 xitk_image_t *skin;
1860 GC lgc;
1861
1862 if(w && (((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_IMAGE) && w->visible == 1)) {
1863 private_data = (image_private_data_t *) w->private_data;
1864
1865 skin = private_data->skin;
1866
1867 XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
1868 lgc = XCreateGC(private_data->imlibdata->x.disp, w->wl->win, None, None);
1869 XCopyGC(private_data->imlibdata->x.disp, w->wl->gc, (1 << GCLastBit) - 1, lgc);
1870 XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
1871
1872 if (skin->mask) {
1873 XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
1874 XSetClipOrigin(private_data->imlibdata->x.disp, lgc, w->x, w->y);
1875 XSetClipMask(private_data->imlibdata->x.disp, lgc, skin->mask->pixmap);
1876 XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
1877 }
1878
1879 XLOCK (private_data->imlibdata->x.x_lock_display, private_data->imlibdata->x.disp);
1880 XCopyArea (private_data->imlibdata->x.disp, skin->image->pixmap, w->wl->win, lgc, 0, 0,
1881 skin->width, skin->height, w->x, w->y);
1882
1883 XFreeGC(private_data->imlibdata->x.disp, lgc);
1884 XUNLOCK (private_data->imlibdata->x.x_unlock_display, private_data->imlibdata->x.disp);
1885 }
1886
1887 }
1888
1889 /*
1890 *
1891 */
notify_change_skin(xitk_widget_t * w,xitk_skin_config_t * skonfig)1892 static void notify_change_skin(xitk_widget_t *w, xitk_skin_config_t *skonfig) {
1893 image_private_data_t *private_data;
1894
1895 if(w && (((w->type & WIDGET_TYPE_MASK) == WIDGET_TYPE_IMAGE) && w->visible == 1)) {
1896 private_data = (image_private_data_t *) w->private_data;
1897
1898 if(private_data->skin_element_name) {
1899
1900 xitk_skin_lock(skonfig);
1901
1902 private_data->skin = xitk_skin_get_image(skonfig,
1903 xitk_skin_get_skin_filename(skonfig, private_data->skin_element_name));
1904
1905 w->x = xitk_skin_get_coord_x(skonfig, private_data->skin_element_name);
1906 w->y = xitk_skin_get_coord_y(skonfig, private_data->skin_element_name);
1907 w->width = private_data->skin->width;
1908 w->height = private_data->skin->height;
1909
1910 xitk_skin_unlock(skonfig);
1911
1912 xitk_set_widget_pos(w, w->x, w->y);
1913 }
1914 }
1915 }
1916
notify_event(xitk_widget_t * w,widget_event_t * event,widget_event_result_t * result)1917 static int notify_event(xitk_widget_t *w, widget_event_t *event, widget_event_result_t *result) {
1918 int retval = 0;
1919
1920 switch(event->type) {
1921 case WIDGET_EVENT_PAINT:
1922 paint_image(w);
1923 break;
1924 case WIDGET_EVENT_INSIDE:
1925 result->value = notify_inside(w, event->x, event->y);
1926 retval = 1;
1927 break;
1928 case WIDGET_EVENT_CHANGE_SKIN:
1929 notify_change_skin(w, event->skonfig);
1930 break;
1931 case WIDGET_EVENT_DESTROY:
1932 notify_destroy(w);
1933 break;
1934 case WIDGET_EVENT_GET_SKIN:
1935 if(result) {
1936 result->image = get_skin(w, event->skin_layer);
1937 retval = 1;
1938 }
1939 break;
1940 }
1941
1942 return retval;
1943 }
1944
1945 /*
1946 *
1947 */
_xitk_image_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_image_widget_t * im,int x,int y,const char * skin_element_name,xitk_image_t * skin)1948 static xitk_widget_t *_xitk_image_create (xitk_widget_list_t *wl,
1949 xitk_skin_config_t *skonfig,
1950 xitk_image_widget_t *im,
1951 int x, int y,
1952 const char *skin_element_name,
1953 xitk_image_t *skin) {
1954 xitk_widget_t *mywidget;
1955 image_private_data_t *private_data;
1956
1957 mywidget = (xitk_widget_t *) xitk_xmalloc (sizeof(xitk_widget_t));
1958
1959 private_data = (image_private_data_t *) xitk_xmalloc (sizeof (image_private_data_t));
1960
1961 private_data->imlibdata = im->imlibdata;
1962 private_data->skin_element_name = (skin_element_name == NULL) ? NULL : strdup(im->skin_element_name);
1963
1964 private_data->bWidget = mywidget;
1965 private_data->skin = skin;
1966
1967 mywidget->private_data = private_data;
1968
1969 mywidget->wl = wl;
1970
1971 mywidget->enable = 0;
1972 mywidget->running = 1;
1973 mywidget->visible = 0;
1974 mywidget->have_focus = FOCUS_LOST;
1975 mywidget->imlibdata = private_data->imlibdata;
1976 mywidget->x = x;
1977 mywidget->y = y;
1978 mywidget->width = private_data->skin->width;
1979 mywidget->height = private_data->skin->height;
1980 mywidget->type = WIDGET_TYPE_IMAGE;
1981 mywidget->event = notify_event;
1982 mywidget->tips_timeout = 0;
1983 mywidget->tips_string = NULL;
1984
1985 return mywidget;
1986 }
1987
xitk_image_create(xitk_widget_list_t * wl,xitk_skin_config_t * skonfig,xitk_image_widget_t * im)1988 xitk_widget_t *xitk_image_create (xitk_widget_list_t *wl,
1989 xitk_skin_config_t *skonfig, xitk_image_widget_t *im) {
1990
1991 XITK_CHECK_CONSTITENCY(im);
1992
1993 return _xitk_image_create(wl, skonfig, im,
1994 (xitk_skin_get_coord_x(skonfig, im->skin_element_name)),
1995 (xitk_skin_get_coord_y(skonfig, im->skin_element_name)),
1996 im->skin_element_name,
1997 (xitk_skin_get_image(skonfig,
1998 xitk_skin_get_skin_filename(skonfig, im->skin_element_name))));
1999 }
2000
2001 /*
2002 *
2003 */
xitk_noskin_image_create(xitk_widget_list_t * wl,xitk_image_widget_t * im,xitk_image_t * image,int x,int y)2004 xitk_widget_t *xitk_noskin_image_create (xitk_widget_list_t *wl,
2005 xitk_image_widget_t *im,
2006 xitk_image_t *image, int x, int y) {
2007 XITK_CHECK_CONSTITENCY(im);
2008
2009 return _xitk_image_create(wl, NULL, im, x, y, NULL, image);
2010 }
2011