4 * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
6 * This program 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.
11 * This program 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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "bcresources.h"
26 #include "bcsignals.h"
27 #include "bcsynchronous.h"
29 #include "bcwindowbase.h"
39 void BC_WindowBase::copy_area(int x1, int y1, int x2, int y2, int w, int h, BC_Pixmap *pixmap)
41 XCopyArea(top_level->display,
42 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
43 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
44 top_level->gc, x1, y1, w, h, x2, y2);
48 void BC_WindowBase::draw_box(int x, int y, int w, int h, BC_Pixmap *pixmap)
50 //if(x == 0) printf("BC_WindowBase::draw_box %d %d %d %d\n", x, y, w, h);
51 XFillRectangle(top_level->display,
52 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
53 top_level->gc, x, y, w, h);
57 void BC_WindowBase::draw_circle(int x, int y, int w, int h, BC_Pixmap *pixmap)
59 XDrawArc(top_level->display,
60 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
61 top_level->gc, x, y, (w - 1), (h - 2), 0 * 64, 360 * 64);
64 void BC_WindowBase::draw_arc(int x, int y, int w, int h,
65 int start_angle, int angle_length, BC_Pixmap *pixmap)
67 XDrawArc(top_level->display,
68 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
69 top_level->gc, x, y, (w - 1), (h - 2), start_angle * 64,
73 void BC_WindowBase::draw_disc(int x, int y, int w, int h, BC_Pixmap *pixmap)
75 XFillArc(top_level->display,
76 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
77 top_level->gc, x, y, (w - 1), (h - 2), 0 * 64, 360 * 64);
80 void BC_WindowBase::clear_box(int x, int y, int w, int h, BC_Pixmap *pixmap)
83 Pixmap xpixmap = pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap;
84 XFillRectangle(top_level->display, xpixmap, top_level->gc, x, y, w, h);
87 void BC_WindowBase::draw_text_line(int x, int y, const char *text, int len,
91 if( get_resources()->use_xft ) {
92 draw_xft_text(x, y, text, len, pixmap);
96 Pixmap xpixmap = pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap;
97 if( get_resources()->use_fontset ) {
98 XFontSet fontset = top_level->get_curr_fontset();
100 XmbDrawString(top_level->display, xpixmap, fontset,
101 top_level->gc, x, y, text, len);
106 //printf("BC_WindowBase::draw_text 3\n");
107 XDrawString(top_level->display, xpixmap, top_level->gc, x, y, text, len);
110 void BC_WindowBase::draw_text(int x, int y, const char *text, int length,
113 if( length < 0 ) length = strlen(text);
114 //int boldface = top_level->current_font & BOLDFACE;
115 int font = top_level->current_font & 0xff;
117 switch(top_level->current_font) {
118 case MEDIUM_7SEGMENT:
119 for(int i = 0; i < length; i++) {
120 VFrame *image, **img7seg = get_resources()->medium_7segment;
123 case '0': case '1': case '2': case '3': case '4':
124 case '5': case '6': case '7': case '8': case '9':
125 image = img7seg[ch-'0']; break;
126 case ':': image = img7seg[10]; break;
127 case '.': image = img7seg[11]; break;
128 case 'a': case 'b': case 'c':
129 case 'd': case 'e': case 'f': ch -= 'a'-'A';
130 case 'A': case 'B': case 'C': /* fallthru */
131 case 'D': case 'E': case 'F':
132 image = img7seg[12+ch-'A']; break;
134 case '-': image = img7seg[19]; break;
136 case ' ': image = img7seg[18]; break;
139 draw_vframe(image, x, y - image->get_h());
145 if(top_level->get_xft_struct(top_level->current_font)) {
146 draw_xft_text(x, y, text, length, pixmap);
150 for(int i = 0, j = 0; i <= length; i++) {
151 if(text[i] == '\n' || text[i] == 0) {
152 if(get_resources()->use_fontset && top_level->get_curr_fontset()) {
153 XmbDrawString(top_level->display,
154 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
155 top_level->get_curr_fontset(),
156 top_level->gc, x, y, &text[j], i-j);
159 XDrawString(top_level->display,
160 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
161 top_level->gc, x, y, &text[j], i-j);
164 y += get_text_height(font);
171 void BC_WindowBase::draw_utf8_text(int x, int y,
172 const char *text, int length, BC_Pixmap *pixmap)
174 if(length < 0) length = strlen(text);
176 if(top_level->get_xft_struct(top_level->current_font))
187 for(int i = 0, j = 0; i <= length; i++)
189 if(text[i] == '\n' || text[i] == 0)
191 if(get_resources()->use_fontset && top_level->get_curr_fontset())
193 XmbDrawString(top_level->display,
194 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
195 top_level->get_curr_fontset(),
204 XDrawString(top_level->display,
205 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
214 y += get_text_height(MEDIUMFONT);
219 void BC_WindowBase::draw_xft_text(int x, int y,
220 const char *text, int length, BC_Pixmap *pixmap, int is_utf8)
223 wchar_t wide_text[l];
224 length = BC_Resources::encode(
225 is_utf8 ? "UTF8" : BC_Resources::encoding, BC_Resources::wide_encoding,
226 (char*)text, length, (char*)wide_text, l*sizeof(wchar_t)) / sizeof(wchar_t);
227 draw_xft_text(x, y, wide_text, length, pixmap);
230 void BC_WindowBase::draw_xft_text(int x, int y,
231 const wchar_t *text, int length, BC_Pixmap *pixmap)
234 const wchar_t *wsp = text, *wep = wsp + length;
236 const wchar_t *wcp = wsp;
237 while( wcp < wep && *wcp != '\n' ) ++wcp;
240 draw_wtext(x, y, wsp, len, pixmap);
241 if( wcp >= wep ) break;
243 dy = get_text_height(top_level->current_font);
249 void BC_WindowBase::xft_draw_string(XftColor *xft_color, XftFont *xft_font,
250 int x, int y, const FcChar32 *fc, int len, BC_Pixmap *pixmap)
252 Pixmap draw_pixmap = 0;
253 XftDraw *xft_draw = (XftDraw *)
254 (pixmap ? pixmap->opaque_xft_draw : this->pixmap->opaque_xft_draw);
255 int src_x = x, src_y = y, src_w = 0, src_h = 0;
257 XGetGCValues(top_level->display, top_level->gc, GCFunction, &values);
258 if( values.function != GXcopy ) {
259 XSetFunction(top_level->display, top_level->gc, GXcopy);
261 XftTextExtents32(top_level->display, xft_font, fc, len, &info);
262 src_w = info.width; src_h = info.height;
263 draw_pixmap = XCreatePixmap(top_level->display, top_level->win,
264 src_w, src_h, top_level->default_depth);
265 int color = get_color(); set_color(0);
266 XFillRectangle(top_level->display, draw_pixmap, top_level->gc, 0, 0, src_w, src_h);
268 xft_draw = XftDrawCreate(top_level->display, draw_pixmap,
269 top_level->vis, top_level->cmap);
270 src_x = info.x; src_y = info.y;
272 XftDrawString32(xft_draw, xft_color, xft_font, src_x, src_y, fc, len);
273 if( values.function != GXcopy ) {
274 XSetFunction(top_level->display, top_level->gc, values.function);
275 Pixmap xpixmap = pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap;
276 XCopyArea(top_level->display, draw_pixmap, xpixmap,
277 top_level->gc, 0, 0, src_w, src_h, x, y);
278 XFreePixmap(top_level->display, draw_pixmap);
279 XftDrawDestroy(xft_draw);
283 int BC_WindowBase::get_single_text_width(int font, const wchar_t *text, int length)
286 length = wcslen(text);
287 if( !length ) return 0;
289 if( !get_resources()->use_xft ) {
290 if( !get_font_struct(font) ) return 0;
291 XChar2b xtext[length], *xp = xtext;
292 for( int i=0; i<length; ++i,++xp ) {
293 xp->byte1 = (unsigned char) (text[i] >> 8);
294 xp->byte2 = (unsigned char) (text[i] & 0xff);
296 return XTextWidth16(get_font_struct(font), xtext, length);
300 XftFont *basefont = top_level->get_xft_struct(font);
301 XftFont *curfont = 0, *altfont = 0;
302 const wchar_t *up = text, *ubp = up, *uep = ubp + length;
305 XftFont *xft_font = 0;
306 if( XftCharExists(top_level->display, basefont, *up) )
309 if( XftCharExists(top_level->display, altfont, *up))
312 XftFontClose(top_level->display, altfont);
317 FcPattern *pattern = BC_Resources::find_similar_font(*up, basefont->pattern);
320 FcPatternGetDouble(basefont->pattern, FC_PIXEL_SIZE, 0, &psize);
321 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, psize);
322 FcPatternDel(pattern, FC_SCALABLE);
323 xft_font = altfont = XftFontOpenPattern(top_level->display, pattern);
328 if( xft_font != curfont ) {
329 if( curfont && up > ubp ) {
331 XftTextExtents32(top_level->display, curfont,
332 (const FcChar32*)ubp, up-ubp, &extents);
335 ubp = up; curfont = xft_font;
340 if( curfont && up > ubp ) {
342 XftTextExtents32(top_level->display, curfont,
343 (const FcChar32*)ubp, up-ubp, &extents);
348 XftFontClose(top_level->display, altfont);
353 void BC_WindowBase::draw_wtext(int x, int y,
354 const wchar_t *text, int length, BC_Pixmap *pixmap)
357 length = wcslen(text);
358 if( !length ) return;
360 int font = top_level->current_font;
361 if( !get_resources()->use_xft ) {
362 if( !get_font_struct(font) ) return;
363 XChar2b xtext[length], *xp = xtext;
364 for( int i=0; i<length; ++i,++xp ) {
365 xp->byte1 = (unsigned char) (text[i] >> 8);
366 xp->byte2 = (unsigned char) (text[i] & 0xff);
368 XDrawString16(top_level->display,
369 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
370 top_level->gc, x, y, xtext, length);
376 color.red = (top_level->current_color & 0xff0000) >> 16;
377 color.red |= color.red << 8;
378 color.green = (top_level->current_color & 0xff00) >> 8;
379 color.green |= color.green << 8;
380 color.blue = (top_level->current_color & 0xff);
381 color.blue |= color.blue << 8;
382 color.alpha = 0xffff;
385 XftColorAllocValue(top_level->display, top_level->vis, top_level->cmap,
388 XftFont *basefont = top_level->get_xft_struct(font);
389 XftFont *curfont = 0, *altfont = 0;
390 const wchar_t *up = text, *ubp = up, *uep = ubp + length;
393 XftFont *xft_font = 0;
394 if( XftCharExists(top_level->display, basefont, *up) )
397 if( XftCharExists(top_level->display, altfont, *up))
400 XftFontClose(top_level->display, altfont);
405 FcPattern *pattern = BC_Resources::find_similar_font(*up, basefont->pattern);
408 FcPatternGetDouble(basefont->pattern, FC_PIXEL_SIZE, 0, &psize);
409 FcPatternAddDouble(pattern, FC_PIXEL_SIZE, psize);
410 FcPatternDel(pattern, FC_SCALABLE);
411 xft_font = altfont = XftFontOpenPattern(top_level->display, pattern);
416 if( xft_font != curfont ) {
417 if( curfont && up > ubp ) {
418 xft_draw_string(&xft_color, curfont, x, y,
419 (const FcChar32*)ubp, up-ubp, pixmap);
421 XftTextExtents32(top_level->display, curfont,
422 (const FcChar32*)ubp, up-ubp, &extents);
425 ubp = up; curfont = xft_font;
430 if( curfont && up > ubp ) {
431 xft_draw_string(&xft_color, curfont, x, y,
432 (const FcChar32*)ubp, up-ubp, pixmap);
436 XftFontClose(top_level->display, altfont);
438 XftColorFree(top_level->display, top_level->vis, top_level->cmap, &xft_color);
442 void BC_WindowBase::truncate_text(char *result, const char *text, int w)
444 int new_w = get_text_width(current_font, text);
448 const char* separator = "...";
449 int separator_w = get_text_width(current_font, separator);
453 strcpy(result, separator);
457 int text_len = strlen(text);
458 // widen middle gap until it fits
459 for(int i = text_len / 2; i > 0; i--)
461 strncpy(result, text, i);
463 strcat(result, separator);
464 strncat(result, text + text_len - i, i);
465 result[i + strlen(separator) + i] = 0;
466 new_w = get_text_width(current_font, result);
467 //printf("BC_WindowBase::truncate_text %d %d %d %s\n", __LINE__, new_w, w, result);
468 if(new_w < w) return;
472 strcpy(result, separator);
477 strcpy(result, text);
481 void BC_WindowBase::draw_center_text(int x, int y, const char *text, int length)
483 if(length < 0) length = strlen(text);
484 int w = get_text_width(current_font, text, length);
486 draw_text(x, y, text, length);
489 void BC_WindowBase::draw_line(int x1, int y1, int x2, int y2, BC_Pixmap *pixmap)
491 // Some X drivers can't draw 0 length lines
492 if(x1 == x2 && y1 == y2)
494 draw_pixel(x1, y1, pixmap);
498 XDrawLine(top_level->display,
499 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
508 void BC_WindowBase::draw_polygon(ArrayList<int> *x, ArrayList<int> *y, BC_Pixmap *pixmap)
510 int npoints = MIN(x->total, y->total);
511 XPoint *points = new XPoint[npoints];
513 for(int i = 0; i < npoints; i++)
515 points[i].x = x->values[i];
516 points[i].y = y->values[i];
519 XDrawLines(top_level->display,
520 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
529 void BC_WindowBase::fill_polygon(ArrayList<int> *x, ArrayList<int> *y, BC_Pixmap *pixmap)
531 int npoints = MIN(x->total, y->total);
532 XPoint *points = new XPoint[npoints];
534 for(int i = 0; i < npoints; i++)
536 points[i].x = x->values[i];
537 points[i].y = y->values[i];
540 XFillPolygon(top_level->display,
541 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
552 void BC_WindowBase::draw_rectangle(int x, int y, int w, int h)
554 XDrawRectangle(top_level->display,
555 pixmap->opaque_pixmap,
563 void BC_WindowBase::draw_3d_border(int x,
573 top_level->get_resources()->border_shadow2,
574 top_level->get_resources()->border_shadow1,
575 top_level->get_resources()->border_light1,
576 top_level->get_resources()->border_light2);
580 void BC_WindowBase::draw_3d_border(int x,
594 ux = x+w-1; uy = y+h-1;
597 draw_line(x, y, ux, y);
598 draw_line(x, y, x, uy);
600 draw_line(lx, ly, ux - 1, ly);
601 draw_line(lx, ly, lx, uy - 1);
604 draw_line(ux, ly, ux, uy);
605 draw_line(lx, uy, ux, uy);
607 draw_line(x + w, y, x + w, y + h);
608 draw_line(x, y + h, x + w, y + h);
611 void BC_WindowBase::draw_3d_box(int x,
627 ux = x+w-1; uy = y+h-1;
630 draw_box(x, y, w, h, pixmap);
633 draw_line(x, y, ux, y, pixmap);
634 draw_line(x, y, x, uy, pixmap);
636 draw_line(lx, ly, ux - 1, ly, pixmap);
637 draw_line(lx, ly, lx, uy - 1, pixmap);
640 draw_line(ux, ly, ux, uy, pixmap);
641 draw_line(lx, uy, ux, uy, pixmap);
643 draw_line(x + w, y, x + w, y + h, pixmap);
644 draw_line(x, y + h, x + w, y + h, pixmap);
647 void BC_WindowBase::draw_colored_box(int x, int y, int w, int h, int down, int highlighted)
652 draw_3d_box(x, y, w, h,
653 top_level->get_resources()->button_light,
654 top_level->get_resources()->button_highlighted,
655 top_level->get_resources()->button_highlighted,
656 top_level->get_resources()->button_shadow,
659 draw_3d_box(x, y, w, h,
660 top_level->get_resources()->button_light,
661 top_level->get_resources()->button_up,
662 top_level->get_resources()->button_up,
663 top_level->get_resources()->button_shadow,
668 // need highlighting for toggles
670 draw_3d_box(x, y, w, h,
671 top_level->get_resources()->button_shadow,
673 top_level->get_resources()->button_up,
674 top_level->get_resources()->button_up,
675 top_level->get_resources()->button_light);
677 draw_3d_box(x, y, w, h,
678 top_level->get_resources()->button_shadow,
680 top_level->get_resources()->button_down,
681 top_level->get_resources()->button_down,
682 top_level->get_resources()->button_light);
687 void BC_WindowBase::draw_border(char *text, int x, int y, int w, int h)
689 int left_indent = 20;
693 lx = x + 1; ly = y + 1;
694 ux = x + w - 1; uy = y + h - 1;
697 if(text && text[0] != 0)
700 set_font(MEDIUMFONT);
701 draw_text(x + left_indent, y + get_text_height(MEDIUMFONT) / 2, text);
704 set_color(top_level->get_resources()->button_shadow);
705 draw_line(x, y, x + left_indent - 5, y);
706 draw_line(x, y, x, uy);
707 draw_line(x + left_indent + 5 + get_text_width(MEDIUMFONT, text), y, ux, y);
708 draw_line(x, y, x, uy);
709 draw_line(ux, ly, ux, uy);
710 draw_line(lx, uy, ux, uy);
711 set_color(top_level->get_resources()->button_light);
712 draw_line(lx, ly, x + left_indent - 5 - 1, ly);
713 draw_line(lx, ly, lx, uy - 1);
714 draw_line(x + left_indent + 5 + get_text_width(MEDIUMFONT, text), ly, ux - 1, ly);
715 draw_line(lx, ly, lx, uy - 1);
716 draw_line(x + w, y, x + w, y + h);
717 draw_line(x, y + h, x + w, y + h);
720 void BC_WindowBase::draw_triangle_down_flat(int x, int y, int w, int h)
722 int x1, y1, x2, y2, x3;
725 x1 = x; x2 = x + w / 2; x3 = x + w - 1;
726 y1 = y; y2 = y + h - 1;
728 point[0].x = x2; point[0].y = y2; point[1].x = x3;
729 point[1].y = y1; point[2].x = x1; point[2].y = y1;
731 XFillPolygon(top_level->display,
732 pixmap->opaque_pixmap,
740 void BC_WindowBase::draw_triangle_up(int x, int y, int w, int h,
741 int light1, int light2, int middle, int shadow1, int shadow2)
743 int x1, y1, x2, y2, x3;
746 x1 = x; y1 = y; x2 = x + w / 2;
747 y2 = y + h - 1; x3 = x + w - 1;
750 point[0].x = x2; point[0].y = y1; point[1].x = x3;
751 point[1].y = y2; point[2].x = x1; point[2].y = y2;
754 XFillPolygon(top_level->display,
755 pixmap->opaque_pixmap,
762 // bottom and top right
764 draw_line(x3, y2-1, x1, y2-1);
765 draw_line(x2-1, y1, x3-1, y2);
767 draw_line(x3, y2, x1, y2);
768 draw_line(x2, y1, x3, y2);
772 draw_line(x2+1, y1, x1+1, y2);
774 draw_line(x2, y1, x1, y2);
777 void BC_WindowBase::draw_triangle_down(int x, int y, int w, int h,
778 int light1, int light2, int middle, int shadow1, int shadow2)
780 int x1, y1, x2, y2, x3;
783 x1 = x; x2 = x + w / 2; x3 = x + w - 1;
784 y1 = y; y2 = y + h - 1;
786 point[0].x = x2; point[0].y = y2; point[1].x = x3;
787 point[1].y = y1; point[2].x = x1; point[2].y = y1;
790 XFillPolygon(top_level->display,
791 pixmap->opaque_pixmap,
798 // top and bottom left
800 draw_line(x3-1, y1+1, x1+1, y1+1);
801 draw_line(x1+1, y1, x2+1, y2);
803 draw_line(x3, y1, x1, y1);
804 draw_line(x1, y1, x2, y2);
808 draw_line(x3-1, y1, x2-1, y2);
810 draw_line(x3, y1, x2, y2);
813 void BC_WindowBase::draw_triangle_left(int x, int y, int w, int h,
814 int light1, int light2, int middle, int shadow1, int shadow2)
816 int x1, y1, x2, y2, y3;
820 y1 = y; x1 = x; y2 = y + h / 2;
821 x2 = x + w - 1; y3 = y + h - 1;
823 point[0].x = x1; point[0].y = y2; point[1].x = x2;
824 point[1].y = y1; point[2].x = x2; point[2].y = y3;
827 XFillPolygon(top_level->display,
828 pixmap->opaque_pixmap,
835 // right and bottom right
837 draw_line(x2-1, y1, x2-1, y3-1);
838 draw_line(x2, y3-1, x1, y2-1);
840 draw_line(x2, y1, x2, y3);
841 draw_line(x2, y3, x1, y2);
845 draw_line(x1, y2, x2, y1);
847 draw_line(x1, y2+1, x2, y1+1);
850 void BC_WindowBase::draw_triangle_right(int x, int y, int w, int h,
851 int light1, int light2, int middle, int shadow1, int shadow2)
853 int x1, y1, x2, y2, y3;
856 y1 = y; y2 = y + h / 2; y3 = y + h - 1;
857 x1 = x; x2 = x + w - 1;
859 point[0].x = x1; point[0].y = y1; point[1].x = x2;
860 point[1].y = y2; point[2].x = x1; point[2].y = y3;
863 XFillPolygon(top_level->display,
864 pixmap->opaque_pixmap,
871 // left and top right
873 draw_line(x1+1, y3, x1+1, y1);
874 draw_line(x1, y1+1, x2, y2+1);
876 draw_line(x1, y3, x1, y1);
877 draw_line(x1, y1, x2, y2);
881 draw_line(x2, y2-1, x1, y3-1);
883 draw_line(x2, y2, x1, y3);
887 void BC_WindowBase::draw_check(int x, int y)
889 const int w = 15, h = 15;
890 draw_line(x + 3, y + h / 2 + 0, x + 6, y + h / 2 + 2);
891 draw_line(x + 3, y + h / 2 + 1, x + 6, y + h / 2 + 3);
892 draw_line(x + 6, y + h / 2 + 2, x + w - 4, y + h / 2 - 3);
893 draw_line(x + 3, y + h / 2 + 2, x + 6, y + h / 2 + 4);
894 draw_line(x + 6, y + h / 2 + 2, x + w - 4, y + h / 2 - 3);
895 draw_line(x + 6, y + h / 2 + 3, x + w - 4, y + h / 2 - 2);
896 draw_line(x + 6, y + h / 2 + 4, x + w - 4, y + h / 2 - 1);
899 void BC_WindowBase::draw_tiles(BC_Pixmap *tile, int origin_x, int origin_y, int x, int y, int w, int h)
904 draw_box(x, y, w, h);
908 XSetFillStyle(top_level->display, top_level->gc, FillTiled);
909 // Don't know how slow this is
910 XSetTile(top_level->display, top_level->gc, tile->get_pixmap());
911 XSetTSOrigin(top_level->display, top_level->gc, origin_x, origin_y);
912 draw_box(x, y, w, h);
913 XSetFillStyle(top_level->display, top_level->gc, FillSolid);
917 void BC_WindowBase::draw_top_tiles(BC_WindowBase *parent_window, int x, int y, int w, int h)
920 int origin_x, origin_y;
921 XTranslateCoordinates(top_level->display,
930 draw_tiles(parent_window->bg_pixmap,
939 void BC_WindowBase::draw_top_background(BC_WindowBase *parent_window,
948 XLockDisplay(top_level->display);
950 XTranslateCoordinates(top_level->display,
959 XCopyArea(top_level->display,
960 parent_window->pixmap->opaque_pixmap,
961 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
970 XUnlockDisplay(top_level->display);
973 void BC_WindowBase::draw_background(int x, int y, int w, int h)
977 draw_tiles(bg_pixmap, 0, 0, x, y, w, h);
981 clear_box(x, y, w, h);
985 void BC_WindowBase::draw_bitmap(BC_Bitmap *bitmap,
998 // Hide cursor if video enabled
999 update_video_cursor();
1001 //printf("BC_WindowBase::draw_bitmap 1\n");
1002 if(dest_w <= 0 || dest_h <= 0)
1004 // Use hardware scaling to canvas dimensions if proper color model.
1005 if(bitmap->get_color_model() == BC_YUV420P)
1012 dest_w = bitmap->get_w();
1013 dest_h = bitmap->get_h();
1017 if(src_w <= 0 || src_h <= 0)
1019 src_w = bitmap->get_w();
1020 src_h = bitmap->get_h();
1025 bitmap->write_drawable(win,
1040 bitmap->write_drawable(pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1050 //printf("BC_WindowBase::draw_bitmap 2\n");
1054 void BC_WindowBase::draw_pixel(int x, int y, BC_Pixmap *pixmap)
1056 XDrawPoint(top_level->display,
1057 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1064 void BC_WindowBase::draw_pixmap(BC_Pixmap *pixmap,
1073 pixmap->write_drawable(dst ? dst->opaque_pixmap : this->pixmap->opaque_pixmap,
1082 void BC_WindowBase::draw_vframe(VFrame *frame,
1093 if(dest_w <= 0) dest_w = frame->get_w() - src_x;
1094 if(dest_h <= 0) dest_h = frame->get_h() - src_y;
1095 if(src_w <= 0) src_w = frame->get_w() - src_x;
1096 if(src_h <= 0) src_h = frame->get_h() - src_y;
1097 CLAMP(src_x, 0, frame->get_w() - 1);
1098 CLAMP(src_y, 0, frame->get_h() - 1);
1099 if(src_x + src_w > frame->get_w()) src_w = frame->get_w() - src_x;
1100 if(src_y + src_h > frame->get_h()) src_h = frame->get_h() - src_y;
1102 if(!temp_bitmap) temp_bitmap = new BC_Bitmap(this,
1108 temp_bitmap->match_params(dest_w,
1113 temp_bitmap->read_frame(frame,
1123 draw_bitmap(temp_bitmap,
1136 void BC_WindowBase::draw_tooltip(const char *text)
1139 text = tooltip_text;
1140 if(tooltip_popup && text)
1142 int w = tooltip_popup->get_w(), h = tooltip_popup->get_h();
1143 tooltip_popup->set_color(get_resources()->tooltip_bg_color);
1144 tooltip_popup->draw_box(0, 0, w, h);
1145 tooltip_popup->set_color(BLACK);
1146 tooltip_popup->draw_rectangle(0, 0, w, h);
1147 tooltip_popup->set_font(MEDIUMFONT);
1148 tooltip_popup->draw_text(TOOLTIP_MARGIN,
1149 get_text_ascent(MEDIUMFONT) + TOOLTIP_MARGIN,
1154 void BC_WindowBase::slide_left(int distance)
1158 XCopyArea(top_level->display,
1159 pixmap->opaque_pixmap,
1160 pixmap->opaque_pixmap,
1171 void BC_WindowBase::slide_right(int distance)
1175 XCopyArea(top_level->display,
1176 pixmap->opaque_pixmap,
1177 pixmap->opaque_pixmap,
1188 void BC_WindowBase::slide_up(int distance)
1192 XCopyArea(top_level->display,
1193 pixmap->opaque_pixmap,
1194 pixmap->opaque_pixmap,
1202 set_color(bg_color);
1203 XFillRectangle(top_level->display,
1204 pixmap->opaque_pixmap,
1213 void BC_WindowBase::slide_down(int distance)
1217 XCopyArea(top_level->display,
1218 pixmap->opaque_pixmap,
1219 pixmap->opaque_pixmap,
1227 set_color(bg_color);
1228 XFillRectangle(top_level->display,
1229 pixmap->opaque_pixmap,
1238 // 3 segments in separate pixmaps. Obsolete.
1239 void BC_WindowBase::draw_3segment(int x,
1243 BC_Pixmap *left_image,
1244 BC_Pixmap *mid_image,
1245 BC_Pixmap *right_image,
1248 if(w <= 0 || h <= 0) return;
1249 int left_boundary = left_image->get_w_fixed();
1250 int right_boundary = w - right_image->get_w_fixed();
1251 for(int i = 0; i < w; )
1255 if(i < left_boundary)
1258 if(i < right_boundary)
1261 image = right_image;
1263 int output_w = image->get_w_fixed();
1265 if(i < left_boundary)
1267 if(i + output_w > left_boundary) output_w = left_boundary - i;
1270 if(i < right_boundary)
1272 if(i + output_w > right_boundary) output_w = right_boundary - i;
1275 if(i + output_w > w) output_w = w - i;
1277 image->write_drawable(pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1288 // 3 segments in separate vframes. Obsolete.
1289 void BC_WindowBase::draw_3segment(int x,
1295 VFrame *right_image,
1298 if(w <= 0 || h <= 0) return;
1299 int left_boundary = left_image->get_w_fixed();
1300 int right_boundary = w - right_image->get_w_fixed();
1303 for(int i = 0; i < w; )
1307 if(i < left_boundary)
1310 if(i < right_boundary)
1313 image = right_image;
1315 int output_w = image->get_w_fixed();
1317 if(i < left_boundary)
1319 if(i + output_w > left_boundary) output_w = left_boundary - i;
1322 if(i < right_boundary)
1324 if(i + output_w > right_boundary) output_w = right_boundary - i;
1327 if(i + output_w > w) output_w = w - i;
1341 if(output_w == 0) break;
1346 // Draw all 3 segments in a single vframe for a changing level
1351 // <------------------------------------------------------------>
1355 // <-------------------------------------------------------------------->
1357 // |-------------------|----------------------|------------------|
1360 void BC_WindowBase::draw_3segmenth(int x,
1375 void BC_WindowBase::draw_3segmenth(int x,
1383 if(total_w <= 0 || w <= 0 || h <= 0) return;
1384 int third_image = image->get_w() / 3;
1385 int half_image = image->get_w() / 2;
1386 //int left_boundary = third_image;
1387 //int right_boundary = total_w - third_image;
1389 int left_in_w = third_image;
1390 int left_out_x = total_x;
1391 int left_out_w = third_image;
1392 int right_in_x = image->get_w() - third_image;
1393 int right_in_w = third_image;
1394 int right_out_x = total_x + total_w - third_image;
1395 int right_out_w = third_image;
1396 int center_out_x = total_x + third_image;
1397 int center_out_w = total_w - third_image * 2;
1398 //int image_x, image_w;
1400 //printf("BC_WindowBase::draw_3segment 1 left_out_x=%d left_out_w=%d center_out_x=%d center_out_w=%d right_out_x=%d right_out_w=%d\n",
1401 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1405 left_in_w -= x - left_out_x;
1406 left_out_w -= x - left_out_x;
1407 left_in_x += x - left_out_x;
1408 left_out_x += x - left_out_x;
1411 if(left_out_x + left_out_w > x + w)
1413 left_in_w -= (left_out_x + left_out_w) - (x + w);
1414 left_out_w -= (left_out_x + left_out_w) - (x + w);
1419 right_in_w -= x - right_out_x;
1420 right_out_w -= x - right_out_x;
1421 right_in_x += x - right_out_x;
1422 right_out_x += x - right_out_x;
1425 if(right_out_x + right_out_w > x + w)
1427 right_in_w -= (right_out_x + right_out_w) - (x + w);
1428 right_out_w -= (right_out_x + right_out_w) - (x + w);
1431 if(center_out_x < x)
1433 center_out_w -= x - center_out_x;
1434 center_out_x += x - center_out_x;
1437 if(center_out_x + center_out_w > x + w)
1439 center_out_w -= (center_out_x + center_out_w) - (x + w);
1442 if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1447 temp_bitmap->match_params(image->get_w(),
1451 temp_bitmap->read_frame(image,
1458 //printf("BC_WindowBase::draw_3segment 2 left_out_x=%d left_out_w=%d center_out_x=%d center_out_w=%d right_out_x=%d right_out_w=%d\n",
1459 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1462 draw_bitmap(temp_bitmap,
1470 -1, // src width and height are meaningless in video_off mode
1477 draw_bitmap(temp_bitmap,
1485 -1, // src width and height are meaningless in video_off mode
1490 for(int pixel = center_out_x;
1491 pixel < center_out_x + center_out_w;
1492 pixel += half_image)
1494 int fragment_w = half_image;
1495 if(fragment_w + pixel > center_out_x + center_out_w)
1496 fragment_w = (center_out_x + center_out_w) - pixel;
1498 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1499 draw_bitmap(temp_bitmap,
1507 -1, // src width and height are meaningless in video_off mode
1520 void BC_WindowBase::draw_3segmenth(int x,
1528 if(w <= 0 || total_w <= 0) return;
1529 if(!src) printf("BC_WindowBase::draw_3segmenth src=0\n");
1530 int quarter_src = src->get_w() / 4;
1531 int half_src = src->get_w() / 2;
1532 //int left_boundary = quarter_src;
1533 //int right_boundary = total_w - quarter_src;
1535 int left_in_w = quarter_src;
1536 int left_out_x = total_x;
1537 int left_out_w = quarter_src;
1538 int right_in_x = src->get_w() - quarter_src;
1539 int right_in_w = quarter_src;
1540 int right_out_x = total_x + total_w - quarter_src;
1541 int right_out_w = quarter_src;
1542 int center_out_x = total_x + quarter_src;
1543 int center_out_w = total_w - quarter_src * 2;
1546 //printf("BC_WindowBase::draw_3segment 1 left_out_x=%d left_out_w=%d center_out_x=%d center_out_w=%d right_out_x=%d right_out_w=%d\n",
1547 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1551 left_in_w -= x - left_out_x;
1552 left_out_w -= x - left_out_x;
1553 left_in_x += x - left_out_x;
1554 left_out_x += x - left_out_x;
1557 if(left_out_x + left_out_w > x + w)
1559 left_in_w -= (left_out_x + left_out_w) - (x + w);
1560 left_out_w -= (left_out_x + left_out_w) - (x + w);
1565 right_in_w -= x - right_out_x;
1566 right_out_w -= x - right_out_x;
1567 right_in_x += x - right_out_x;
1568 right_out_x += x - right_out_x;
1571 if(right_out_x + right_out_w > x + w)
1573 right_in_w -= (right_out_x + right_out_w) - (x + w);
1574 right_out_w -= (right_out_x + right_out_w) - (x + w);
1577 if(center_out_x < x)
1579 center_out_w -= x - center_out_x;
1580 center_out_x += x - center_out_x;
1583 if(center_out_x + center_out_w > x + w)
1585 center_out_w -= (center_out_x + center_out_w) - (x + w);
1589 //printf("BC_WindowBase::draw_3segment 2 left_out_x=%d left_out_w=%d center_out_x=%d center_out_w=%d right_out_x=%d right_out_w=%d\n",
1590 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1615 for(int pixel = center_out_x;
1616 pixel < center_out_x + center_out_w;
1619 int fragment_w = half_src;
1620 if(fragment_w + pixel > center_out_x + center_out_w)
1621 fragment_w = (center_out_x + center_out_w) - pixel;
1623 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1637 void BC_WindowBase::draw_3segmenth(int x,
1644 int third_image = src->get_w() / 3;
1645 int half_output = w / 2;
1646 //int left_boundary = third_image;
1647 //int right_boundary = w - third_image;
1649 int left_in_w = third_image;
1651 int left_out_w = third_image;
1652 int right_in_x = src->get_w() - third_image;
1653 int right_in_w = third_image;
1654 int right_out_x = x + w - third_image;
1655 int right_out_w = third_image;
1656 //int image_x, image_w;
1658 //printf("BC_WindowBase::draw_3segment 1 left_out_x=%d left_out_w=%d center_out_x=%d center_out_w=%d right_out_x=%d right_out_w=%d\n",
1659 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1661 if(left_out_w > half_output)
1663 left_in_w -= left_out_w - half_output;
1664 left_out_w -= left_out_w - half_output;
1667 if(right_out_x < x + half_output)
1669 right_in_w -= x + half_output - right_out_x;
1670 right_out_w -= x + half_output - right_out_x;
1671 right_in_x += x + half_output - right_out_x;
1672 right_out_x += x + half_output - right_out_x;
1675 //printf("BC_WindowBase::draw_3segment 2 left_out_x=%d left_out_w=%d center_out_x=%d center_out_w=%d right_out_x=%d right_out_w=%d\n",
1676 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1701 for(int pixel = left_out_x + left_out_w;
1702 pixel < right_out_x;
1703 pixel += third_image)
1705 int fragment_w = third_image;
1706 if(fragment_w + pixel > right_out_x)
1707 fragment_w = right_out_x - pixel;
1709 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1728 void BC_WindowBase::draw_3segmentv(int x,
1735 int third_image = src->get_h() / 3;
1736 int half_output = h / 2;
1737 //int left_boundary = third_image;
1738 //int right_boundary = h - third_image;
1740 int left_in_h = third_image;
1742 int left_out_h = third_image;
1743 int right_in_y = src->get_h() - third_image;
1744 int right_in_h = third_image;
1745 int right_out_y = y + h - third_image;
1746 int right_out_h = third_image;
1747 //int image_y, image_h;
1750 if(left_out_h > half_output)
1752 left_in_h -= left_out_h - half_output;
1753 left_out_h -= left_out_h - half_output;
1756 if(right_out_y < y + half_output)
1758 right_in_h -= y + half_output - right_out_y;
1759 right_out_h -= y + half_output - right_out_y;
1760 right_in_y += y + half_output - right_out_y;
1761 right_out_y += y + half_output - right_out_y;
1765 if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1770 temp_bitmap->match_params(src->get_w(),
1774 temp_bitmap->read_frame(src,
1783 draw_bitmap(temp_bitmap,
1798 draw_bitmap(temp_bitmap,
1811 for(int pixel = left_out_y + left_out_h;
1812 pixel < right_out_y;
1813 pixel += third_image)
1815 int fragment_h = third_image;
1816 if(fragment_h + pixel > right_out_y)
1817 fragment_h = right_out_y - pixel;
1819 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1820 draw_bitmap(temp_bitmap,
1834 void BC_WindowBase::draw_3segmentv(int x,
1841 int third_image = src->get_h() / 3;
1842 int half_output = h / 2;
1843 //int left_boundary = third_image;
1844 //int right_boundary = h - third_image;
1846 int left_in_h = third_image;
1848 int left_out_h = third_image;
1849 int right_in_y = src->get_h() - third_image;
1850 int right_in_h = third_image;
1851 int right_out_y = y + h - third_image;
1852 int right_out_h = third_image;
1853 //int image_y, image_h;
1856 if(left_out_h > half_output)
1858 left_in_h -= left_out_h - half_output;
1859 left_out_h -= left_out_h - half_output;
1862 if(right_out_y < y + half_output)
1864 right_in_h -= y + half_output - right_out_y;
1865 right_out_h -= y + half_output - right_out_y;
1866 right_in_y += y + half_output - right_out_y;
1867 right_out_y += y + half_output - right_out_y;
1894 for(int pixel = left_out_y + left_out_h;
1895 pixel < right_out_y;
1896 pixel += third_image)
1898 int fragment_h = third_image;
1899 if(fragment_h + pixel > right_out_y)
1900 fragment_h = right_out_y - pixel;
1902 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1915 void BC_WindowBase::draw_9segment(int x,
1922 if(w <= 0 || h <= 0) return;
1924 int in_x_third = src->get_w() / 3;
1925 int in_y_third = src->get_h() / 3;
1926 int out_x_half = w / 2;
1927 int out_y_half = h / 2;
1933 int in_x2 = MIN(in_x_third, out_x_half);
1934 int in_y2 = MIN(in_y_third, out_y_half);
1938 int out_x3 = MAX(w - out_x_half, w - in_x_third);
1940 int in_x3 = src->get_w() - (out_x4 - out_x3);
1941 //int in_x4 = src->get_w();
1943 int out_y3 = MAX(h - out_y_half, h - in_y_third);
1945 int in_y3 = src->get_h() - (out_y4 - out_y3);
1946 //int in_y4 = src->get_h();
1960 for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
1964 int w = MIN(in_x3 - in_x2, out_x3 - i);
1993 for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
1997 int h = MIN(in_y3 - in_y2, out_y3 - i);
2010 // Segment 5 * n * n
2011 for(int i = out_y2; i < out_y3; i += in_y3 - in_y2 /* in_y_third */)
2015 int h = MIN(in_y3 - in_y2 /* in_y_third */, out_y3 - i);
2018 for(int j = out_x2; j < out_x3; j += in_x3 - in_x2 /* in_x_third */)
2020 int w = MIN(in_x3 - in_x2 /* in_x_third */, out_x3 - j);
2035 for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
2039 int h = MIN(in_y3 - in_y2, out_y3 - i);
2066 for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
2070 int w = MIN(in_x3 - in_y2, out_x3 - i);
2096 void BC_WindowBase::draw_9segment(int x,
2103 if(w <= 0 || h <= 0) return;
2105 int in_x_third = src->get_w() / 3;
2106 int in_y_third = src->get_h() / 3;
2107 int out_x_half = w / 2;
2108 int out_y_half = h / 2;
2114 int in_x2 = MIN(in_x_third, out_x_half);
2115 int in_y2 = MIN(in_y_third, out_y_half);
2119 int out_x3 = MAX(w - out_x_half, w - in_x_third);
2121 int in_x3 = src->get_w() - (out_x4 - out_x3);
2122 int in_x4 = src->get_w();
2124 int out_y3 = MAX(h - out_y_half, h - in_y_third);
2126 int in_y3 = src->get_h() - (out_y4 - out_y3);
2127 int in_y4 = src->get_h();
2129 //printf("PFCFrame::draw_9segment 1 %d %d %d %d\n", out_x1, out_x2, out_x3, out_x4);
2130 //printf("PFCFrame::draw_9segment 2 %d %d %d %d\n", in_x1, in_x2, in_x3, in_x4);
2131 //printf("PFCFrame::draw_9segment 2 %d %d %d %d\n", in_y1, in_y2, in_y3, in_y4);
2133 if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
2138 temp_bitmap->match_params(src->get_w(),
2142 temp_bitmap->read_frame(src,
2149 draw_bitmap(temp_bitmap,
2163 for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
2167 int w = MIN(in_x3 - in_x2, out_x3 - i);
2168 draw_bitmap(temp_bitmap,
2187 draw_bitmap(temp_bitmap,
2202 for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
2206 int h = MIN(in_y3 - in_y2, out_y3 - i);
2207 draw_bitmap(temp_bitmap,
2222 // Segment 5 * n * n
2223 for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
2227 int h = MIN(in_y3 - in_y2, out_y3 - i);
2230 for(int j = out_x2; j < out_x3; j += in_x3 - in_x2)
2232 int w = MIN(in_x3 - in_x2, out_x3 - j);
2234 draw_bitmap(temp_bitmap,
2250 for(int i = out_y2; i < out_y3; i += in_y_third)
2254 int h = MIN(in_y_third, out_y3 - i);
2255 draw_bitmap(temp_bitmap,
2273 draw_bitmap(temp_bitmap,
2287 for(int i = out_x2; i < out_x3; i += in_x_third)
2291 int w = MIN(in_x_third, out_x3 - i);
2292 draw_bitmap(temp_bitmap,
2309 draw_bitmap(temp_bitmap,