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"
38 #include "workarounds.h"
40 void BC_WindowBase::copy_area(int x1, int y1, int x2, int y2, int w, int h, BC_Pixmap *pixmap)
42 XCopyArea(top_level->display,
43 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
44 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
45 top_level->gc, x1, y1, w, h, x2, y2);
49 void BC_WindowBase::draw_box(int x, int y, int w, int h, BC_Pixmap *pixmap)
51 //if(x == 0) printf("BC_WindowBase::draw_box %d %d %d %d\n", x, y, w, h);
52 XFillRectangle(top_level->display,
53 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
54 top_level->gc, x, y, w, h);
58 void BC_WindowBase::draw_circle(int x, int y, int w, int h, BC_Pixmap *pixmap)
60 XDrawArc(top_level->display,
61 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
62 top_level->gc, x, y, (w - 1), (h - 2), 0 * 64, 360 * 64);
65 void BC_WindowBase::draw_arc(int x, int y, int w, int h,
66 int start_angle, int angle_length, BC_Pixmap *pixmap)
68 XDrawArc(top_level->display,
69 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
70 top_level->gc, x, y, (w - 1), (h - 2), start_angle * 64,
74 void BC_WindowBase::draw_disc(int x, int y, int w, int h, BC_Pixmap *pixmap)
76 XFillArc(top_level->display,
77 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
78 top_level->gc, x, y, (w - 1), (h - 2), 0 * 64, 360 * 64);
81 void BC_WindowBase::clear_box(int x, int y, int w, int h, BC_Pixmap *pixmap)
84 Pixmap xpixmap = pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap;
85 XFillRectangle(top_level->display, xpixmap, top_level->gc, x, y, w, h);
88 void BC_WindowBase::draw_text_line(int x, int y, const char *text, int len,
92 if( get_resources()->use_xft ) {
93 draw_xft_text(x, y, text, len, pixmap);
97 Pixmap xpixmap = pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap;
98 if( get_resources()->use_fontset ) {
99 XFontSet fontset = top_level->get_curr_fontset();
101 XmbDrawString(top_level->display, xpixmap, fontset,
102 top_level->gc, x, y, text, len);
107 //printf("BC_WindowBase::draw_text 3\n");
108 XDrawString(top_level->display, xpixmap, top_level->gc, x, y, text, len);
111 void BC_WindowBase::draw_text(int x, int y, const char *text, int length,
114 if( length < 0 ) length = strlen(text);
115 //int boldface = top_level->current_font & BOLDFACE;
116 int font = top_level->current_font & 0xff;
118 switch(top_level->current_font) {
119 case MEDIUM_7SEGMENT:
120 for(int i = 0; i < length; i++) {
121 VFrame *image, **img7seg = get_resources()->medium_7segment;
124 case '0': case '1': case '2': case '3': case '4':
125 case '5': case '6': case '7': case '8': case '9':
126 image = img7seg[ch-'0']; break;
127 case ':': image = img7seg[10]; break;
128 case '.': image = img7seg[11]; break;
129 case 'a': case 'b': case 'c':
130 case 'd': case 'e': case 'f': ch -= 'a'-'A';
131 case 'A': case 'B': case 'C': /* fallthru */
132 case 'D': case 'E': case 'F':
133 image = img7seg[12+ch-'A']; break;
135 case '-': image = img7seg[19]; break;
137 case ' ': image = img7seg[18]; break;
140 draw_vframe(image, x, y - image->get_h());
146 if(top_level->get_xft_struct(top_level->current_font)) {
147 draw_xft_text(x, y, text, length, pixmap);
151 for(int i = 0, j = 0; i <= length; i++) {
152 if(text[i] == '\n' || text[i] == 0) {
153 if(get_resources()->use_fontset && top_level->get_curr_fontset()) {
154 XmbDrawString(top_level->display,
155 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
156 top_level->get_curr_fontset(),
157 top_level->gc, x, y, &text[j], i-j);
160 XDrawString(top_level->display,
161 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
162 top_level->gc, x, y, &text[j], i-j);
165 y += get_text_height(font);
172 void BC_WindowBase::draw_utf8_text(int x, int y,
173 const char *text, int length, BC_Pixmap *pixmap)
175 if(length < 0) length = strlen(text);
177 if(top_level->get_xft_struct(top_level->current_font))
188 for(int i = 0, j = 0; i <= length; i++)
190 if(text[i] == '\n' || text[i] == 0)
192 if(get_resources()->use_fontset && top_level->get_curr_fontset())
194 XmbDrawString(top_level->display,
195 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
196 top_level->get_curr_fontset(),
205 XDrawString(top_level->display,
206 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
215 y += get_text_height(MEDIUMFONT);
220 void BC_WindowBase::draw_xft_text(int x, int y,
221 const char *text, int length, BC_Pixmap *pixmap, int is_utf8)
224 wchar_t wide_text[l];
225 length = BC_Resources::encode(
226 is_utf8 ? "UTF8" : BC_Resources::encoding, BC_Resources::wide_encoding,
227 (char*)text, length, (char*)wide_text, l*sizeof(wchar_t)) / sizeof(wchar_t);
228 draw_xft_text(x, y, wide_text, length, pixmap);
231 void BC_WindowBase::draw_xft_text(int x, int y,
232 const wchar_t *text, int length, BC_Pixmap *pixmap)
235 const wchar_t *wsp = text, *wep = wsp + length;
236 int font = top_level->current_font;
238 const wchar_t *wcp = wsp;
239 while( wcp < wep && *wcp != '\n' ) ++wcp;
242 draw_single_text(1, font, x, y, wsp, len, pixmap);
243 if( wcp >= wep ) break;
245 dy = get_text_height(font);
251 void BC_WindowBase::xft_draw_string(XftColor *xft_color, XftFont *xft_font,
252 int x, int y, const FcChar32 *fc, int len, BC_Pixmap *pixmap)
254 Pixmap draw_pixmap = 0;
255 XftDraw *xft_draw = (XftDraw *)
256 (pixmap ? pixmap->opaque_xft_draw : this->pixmap->opaque_xft_draw);
257 int src_x = x, src_y = y, src_w = 0, src_h = 0;
259 XGetGCValues(top_level->display, top_level->gc, GCFunction, &values);
260 if( values.function != GXcopy ) {
261 XSetFunction(top_level->display, top_level->gc, GXcopy);
263 xftTextExtents32(top_level->display, xft_font, fc, len, &info);
264 src_w = info.width; src_h = info.height;
265 draw_pixmap = XCreatePixmap(top_level->display, top_level->win,
266 src_w, src_h, top_level->default_depth);
267 int color = get_color(); set_color(0);
268 XFillRectangle(top_level->display, draw_pixmap, top_level->gc, 0, 0, src_w, src_h);
270 xft_draw = xftDrawCreate(top_level->display, draw_pixmap,
271 top_level->vis, top_level->cmap);
272 src_x = info.x; src_y = info.y;
274 xftDrawString32(xft_draw, xft_color, xft_font, src_x, src_y, fc, len);
275 if( values.function != GXcopy ) {
276 XSetFunction(top_level->display, top_level->gc, values.function);
277 Pixmap xpixmap = pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap;
278 XCopyArea(top_level->display, draw_pixmap, xpixmap,
279 top_level->gc, 0, 0, src_w, src_h, x, y);
280 XFreePixmap(top_level->display, draw_pixmap);
281 xftDrawDestroy(xft_draw);
285 int BC_WindowBase::get_single_text_width(int font, const wchar_t *text, int length)
287 return draw_single_text(0, font, 0,0, text, length);
290 int BC_WindowBase::draw_single_text(int draw, int font,
291 int x, int y, const wchar_t *text, int length, BC_Pixmap *pixmap)
294 length = wcslen(text);
295 if( !length ) return 0;
297 if( !get_resources()->use_xft ) {
298 if( !get_font_struct(font) ) return 0;
299 XChar2b xtext[length], *xp = xtext;
300 for( int i=0; i<length; ++i,++xp ) {
301 xp->byte1 = (unsigned char) (text[i] >> 8);
302 xp->byte2 = (unsigned char) (text[i] & 0xff);
305 XDrawString16(top_level->display,
306 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
307 top_level->gc, x, y, xtext, length);
309 return XTextWidth16(get_font_struct(font), xtext, length);
316 color.red = (top_level->current_color & 0xff0000) >> 16;
317 color.red |= color.red << 8;
318 color.green = (top_level->current_color & 0xff00) >> 8;
319 color.green |= color.green << 8;
320 color.blue = (top_level->current_color & 0xff);
321 color.blue |= color.blue << 8;
322 color.alpha = 0xffff;
324 xftColorAllocValue(top_level->display, top_level->vis, top_level->cmap,
329 XftFont *basefont = top_level->get_xft_struct(font);
330 XftFont *curfont = 0, *altfont = 0;
331 const wchar_t *up = text, *ubp = up, *uep = ubp + length;
334 XftFont *xft_font = 0;
335 if( xftCharExists(top_level->display, basefont, *up) )
338 if( xftCharExists(top_level->display, altfont, *up))
341 xftFontClose(top_level->display, altfont);
346 FcPattern *pattern = BC_Resources::find_similar_font(*up, basefont->pattern);
349 fcPatternGetDouble(basefont->pattern, FC_PIXEL_SIZE, 0, &psize);
350 fcPatternAddDouble(pattern, FC_PIXEL_SIZE, psize);
351 fcPatternDel(pattern, FC_SCALABLE);
352 xft_font = altfont = xftFontOpenPattern(top_level->display, pattern);
357 if( xft_font != curfont ) {
358 if( curfont && up > ubp ) {
360 xft_draw_string(&xft_color, curfont, x, y,
361 (const FcChar32*)ubp, up-ubp, pixmap);
364 xftTextExtents32(top_level->display, curfont,
365 (const FcChar32*)ubp, up-ubp, &extents);
368 ubp = up; curfont = xft_font;
373 if( curfont && up > ubp ) {
375 xft_draw_string(&xft_color, curfont, x, y,
376 (const FcChar32*)ubp, up-ubp, pixmap);
379 xftTextExtents32(top_level->display, curfont,
380 (const FcChar32*)ubp, up-ubp, &extents);
385 xftFontClose(top_level->display, altfont);
387 xftColorFree(top_level->display, top_level->vis, top_level->cmap, &xft_color);
392 void BC_WindowBase::truncate_text(char *result, const char *text, int w)
394 int new_w = get_text_width(current_font, text);
398 const char* separator = "...";
399 int separator_w = get_text_width(current_font, separator);
403 strcpy(result, separator);
407 int text_len = strlen(text);
408 // widen middle gap until it fits
409 for(int i = text_len / 2; i > 0; i--)
411 strncpy(result, text, i);
413 strcat(result, separator);
414 strncat(result, text + text_len - i, i);
415 result[i + strlen(separator) + i] = 0;
416 new_w = get_text_width(current_font, result);
417 //printf("BC_WindowBase::truncate_text %d %d %d %s\n", __LINE__, new_w, w, result);
418 if(new_w < w) return;
422 strcpy(result, separator);
427 strcpy(result, text);
431 void BC_WindowBase::draw_center_text(int x, int y, const char *text, int length)
433 if(length < 0) length = strlen(text);
434 int w = get_text_width(current_font, text, length);
436 draw_text(x, y, text, length);
439 void BC_WindowBase::draw_line(int x1, int y1, int x2, int y2, BC_Pixmap *pixmap)
441 // Some X drivers can't draw 0 length lines
442 if(x1 == x2 && y1 == y2)
444 draw_pixel(x1, y1, pixmap);
448 XDrawLine(top_level->display,
449 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
458 void BC_WindowBase::draw_polygon(ArrayList<int> *x, ArrayList<int> *y, BC_Pixmap *pixmap)
460 int npoints = MIN(x->total, y->total);
461 XPoint *points = new XPoint[npoints];
463 for(int i = 0; i < npoints; i++)
465 points[i].x = x->values[i];
466 points[i].y = y->values[i];
469 XDrawLines(top_level->display,
470 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
479 void BC_WindowBase::fill_polygon(ArrayList<int> *x, ArrayList<int> *y, BC_Pixmap *pixmap)
481 int npoints = MIN(x->total, y->total);
482 XPoint *points = new XPoint[npoints];
484 for(int i = 0; i < npoints; i++)
486 points[i].x = x->values[i];
487 points[i].y = y->values[i];
490 XFillPolygon(top_level->display,
491 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
502 void BC_WindowBase::draw_rectangle(int x, int y, int w, int h)
504 XDrawRectangle(top_level->display,
505 pixmap->opaque_pixmap,
513 void BC_WindowBase::draw_3d_border(int x,
523 top_level->get_resources()->border_shadow2,
524 top_level->get_resources()->border_shadow1,
525 top_level->get_resources()->border_light1,
526 top_level->get_resources()->border_light2);
530 void BC_WindowBase::draw_3d_border(int x,
544 ux = x+w-1; uy = y+h-1;
547 draw_line(x, y, ux, y);
548 draw_line(x, y, x, uy);
550 draw_line(lx, ly, ux - 1, ly);
551 draw_line(lx, ly, lx, uy - 1);
554 draw_line(ux, ly, ux, uy);
555 draw_line(lx, uy, ux, uy);
557 draw_line(x + w, y, x + w, y + h);
558 draw_line(x, y + h, x + w, y + h);
561 void BC_WindowBase::draw_3d_box(int x,
577 ux = x+w-1; uy = y+h-1;
580 draw_box(x, y, w, h, pixmap);
583 draw_line(x, y, ux, y, pixmap);
584 draw_line(x, y, x, uy, pixmap);
586 draw_line(lx, ly, ux - 1, ly, pixmap);
587 draw_line(lx, ly, lx, uy - 1, pixmap);
590 draw_line(ux, ly, ux, uy, pixmap);
591 draw_line(lx, uy, ux, uy, pixmap);
593 draw_line(x + w, y, x + w, y + h, pixmap);
594 draw_line(x, y + h, x + w, y + h, pixmap);
597 void BC_WindowBase::draw_colored_box(int x, int y, int w, int h, int down, int highlighted)
602 draw_3d_box(x, y, w, h,
603 top_level->get_resources()->button_light,
604 top_level->get_resources()->button_highlighted,
605 top_level->get_resources()->button_highlighted,
606 top_level->get_resources()->button_shadow,
609 draw_3d_box(x, y, w, h,
610 top_level->get_resources()->button_light,
611 top_level->get_resources()->button_up,
612 top_level->get_resources()->button_up,
613 top_level->get_resources()->button_shadow,
618 // need highlighting for toggles
620 draw_3d_box(x, y, w, h,
621 top_level->get_resources()->button_shadow,
623 top_level->get_resources()->button_up,
624 top_level->get_resources()->button_up,
625 top_level->get_resources()->button_light);
627 draw_3d_box(x, y, w, h,
628 top_level->get_resources()->button_shadow,
630 top_level->get_resources()->button_down,
631 top_level->get_resources()->button_down,
632 top_level->get_resources()->button_light);
637 void BC_WindowBase::draw_border(char *text, int x, int y, int w, int h)
639 int left_indent = 20;
643 lx = x + 1; ly = y + 1;
644 ux = x + w - 1; uy = y + h - 1;
647 if(text && text[0] != 0)
650 set_font(MEDIUMFONT);
651 draw_text(x + left_indent, y + get_text_height(MEDIUMFONT) / 2, text);
654 set_color(top_level->get_resources()->button_shadow);
655 draw_line(x, y, x + left_indent - 5, y);
656 draw_line(x, y, x, uy);
657 draw_line(x + left_indent + 5 + get_text_width(MEDIUMFONT, text), y, ux, y);
658 draw_line(x, y, x, uy);
659 draw_line(ux, ly, ux, uy);
660 draw_line(lx, uy, ux, uy);
661 set_color(top_level->get_resources()->button_light);
662 draw_line(lx, ly, x + left_indent - 5 - 1, ly);
663 draw_line(lx, ly, lx, uy - 1);
664 draw_line(x + left_indent + 5 + get_text_width(MEDIUMFONT, text), ly, ux - 1, ly);
665 draw_line(lx, ly, lx, uy - 1);
666 draw_line(x + w, y, x + w, y + h);
667 draw_line(x, y + h, x + w, y + h);
670 void BC_WindowBase::draw_triangle_down_flat(int x, int y, int w, int h)
672 int x1, y1, x2, y2, x3;
675 x1 = x; x2 = x + w / 2; x3 = x + w - 1;
676 y1 = y; y2 = y + h - 1;
678 point[0].x = x2; point[0].y = y2; point[1].x = x3;
679 point[1].y = y1; point[2].x = x1; point[2].y = y1;
681 XFillPolygon(top_level->display,
682 pixmap->opaque_pixmap,
690 void BC_WindowBase::draw_triangle_up(int x, int y, int w, int h,
691 int light1, int light2, int middle, int shadow1, int shadow2)
693 int x1, y1, x2, y2, x3;
696 x1 = x; y1 = y; x2 = x + w / 2;
697 y2 = y + h - 1; x3 = x + w - 1;
700 point[0].x = x2; point[0].y = y1; point[1].x = x3;
701 point[1].y = y2; point[2].x = x1; point[2].y = y2;
704 XFillPolygon(top_level->display,
705 pixmap->opaque_pixmap,
712 // bottom and top right
714 draw_line(x3, y2-1, x1, y2-1);
715 draw_line(x2-1, y1, x3-1, y2);
717 draw_line(x3, y2, x1, y2);
718 draw_line(x2, y1, x3, y2);
722 draw_line(x2+1, y1, x1+1, y2);
724 draw_line(x2, y1, x1, y2);
727 void BC_WindowBase::draw_triangle_down(int x, int y, int w, int h,
728 int light1, int light2, int middle, int shadow1, int shadow2)
730 int x1, y1, x2, y2, x3;
733 x1 = x; x2 = x + w / 2; x3 = x + w - 1;
734 y1 = y; y2 = y + h - 1;
736 point[0].x = x2; point[0].y = y2; point[1].x = x3;
737 point[1].y = y1; point[2].x = x1; point[2].y = y1;
740 XFillPolygon(top_level->display,
741 pixmap->opaque_pixmap,
748 // top and bottom left
750 draw_line(x3-1, y1+1, x1+1, y1+1);
751 draw_line(x1+1, y1, x2+1, y2);
753 draw_line(x3, y1, x1, y1);
754 draw_line(x1, y1, x2, y2);
758 draw_line(x3-1, y1, x2-1, y2);
760 draw_line(x3, y1, x2, y2);
763 void BC_WindowBase::draw_triangle_left(int x, int y, int w, int h,
764 int light1, int light2, int middle, int shadow1, int shadow2)
766 int x1, y1, x2, y2, y3;
770 y1 = y; x1 = x; y2 = y + h / 2;
771 x2 = x + w - 1; y3 = y + h - 1;
773 point[0].x = x1; point[0].y = y2; point[1].x = x2;
774 point[1].y = y1; point[2].x = x2; point[2].y = y3;
777 XFillPolygon(top_level->display,
778 pixmap->opaque_pixmap,
785 // right and bottom right
787 draw_line(x2-1, y1, x2-1, y3-1);
788 draw_line(x2, y3-1, x1, y2-1);
790 draw_line(x2, y1, x2, y3);
791 draw_line(x2, y3, x1, y2);
795 draw_line(x1, y2, x2, y1);
797 draw_line(x1, y2+1, x2, y1+1);
800 void BC_WindowBase::draw_triangle_right(int x, int y, int w, int h,
801 int light1, int light2, int middle, int shadow1, int shadow2)
803 int x1, y1, x2, y2, y3;
806 y1 = y; y2 = y + h / 2; y3 = y + h - 1;
807 x1 = x; x2 = x + w - 1;
809 point[0].x = x1; point[0].y = y1; point[1].x = x2;
810 point[1].y = y2; point[2].x = x1; point[2].y = y3;
813 XFillPolygon(top_level->display,
814 pixmap->opaque_pixmap,
821 // left and top right
823 draw_line(x1+1, y3, x1+1, y1);
824 draw_line(x1, y1+1, x2, y2+1);
826 draw_line(x1, y3, x1, y1);
827 draw_line(x1, y1, x2, y2);
831 draw_line(x2, y2-1, x1, y3-1);
833 draw_line(x2, y2, x1, y3);
837 void BC_WindowBase::draw_check(int x, int y)
839 const int w = 15, h = 15;
840 draw_line(x + 3, y + h / 2 + 0, x + 6, y + h / 2 + 2);
841 draw_line(x + 3, y + h / 2 + 1, x + 6, y + h / 2 + 3);
842 draw_line(x + 6, y + h / 2 + 2, x + w - 4, y + h / 2 - 3);
843 draw_line(x + 3, y + h / 2 + 2, x + 6, y + h / 2 + 4);
844 draw_line(x + 6, y + h / 2 + 2, x + w - 4, y + h / 2 - 3);
845 draw_line(x + 6, y + h / 2 + 3, x + w - 4, y + h / 2 - 2);
846 draw_line(x + 6, y + h / 2 + 4, x + w - 4, y + h / 2 - 1);
849 void BC_WindowBase::draw_tiles(BC_Pixmap *tile, int origin_x, int origin_y, int x, int y, int w, int h)
854 draw_box(x, y, w, h);
858 XSetFillStyle(top_level->display, top_level->gc, FillTiled);
859 // Don't know how slow this is
860 XSetTile(top_level->display, top_level->gc, tile->get_pixmap());
861 XSetTSOrigin(top_level->display, top_level->gc, origin_x, origin_y);
862 draw_box(x, y, w, h);
863 XSetFillStyle(top_level->display, top_level->gc, FillSolid);
867 void BC_WindowBase::draw_top_tiles(BC_WindowBase *parent_window, int x, int y, int w, int h)
870 int origin_x, origin_y;
871 XTranslateCoordinates(top_level->display,
880 draw_tiles(parent_window->bg_pixmap,
889 void BC_WindowBase::draw_top_background(BC_WindowBase *parent_window,
898 XLockDisplay(top_level->display);
900 XTranslateCoordinates(top_level->display,
909 XCopyArea(top_level->display,
910 parent_window->pixmap->opaque_pixmap,
911 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
920 XUnlockDisplay(top_level->display);
923 void BC_WindowBase::draw_background(int x, int y, int w, int h)
927 draw_tiles(bg_pixmap, 0, 0, x, y, w, h);
931 clear_box(x, y, w, h);
935 void BC_WindowBase::draw_bitmap(BC_Bitmap *bitmap,
948 // Hide cursor if video enabled
949 update_video_cursor();
951 //printf("BC_WindowBase::draw_bitmap %d dest_y=%d\n", __LINE__, dest_y);
952 if(dest_w <= 0 || dest_h <= 0)
954 // Use hardware scaling to canvas dimensions if proper color model.
955 if(bitmap->get_color_model() == BC_YUV420P)
962 dest_w = bitmap->get_w();
963 dest_h = bitmap->get_h();
967 if(src_w <= 0 || src_h <= 0)
969 src_w = bitmap->get_w();
970 src_h = bitmap->get_h();
975 bitmap->write_drawable(win,
990 bitmap->write_drawable(pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1000 //printf("BC_WindowBase::draw_bitmap 2\n");
1004 void BC_WindowBase::draw_pixel(int x, int y, BC_Pixmap *pixmap)
1006 XDrawPoint(top_level->display,
1007 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1014 void BC_WindowBase::draw_pixmap(BC_Pixmap *pixmap,
1023 pixmap->write_drawable(dst ? dst->opaque_pixmap : this->pixmap->opaque_pixmap,
1032 void BC_WindowBase::draw_vframe(VFrame *frame,
1043 if(dest_w <= 0) dest_w = frame->get_w() - src_x;
1044 if(dest_h <= 0) dest_h = frame->get_h() - src_y;
1045 if(src_w <= 0) src_w = frame->get_w() - src_x;
1046 if(src_h <= 0) src_h = frame->get_h() - src_y;
1047 CLAMP(src_x, 0, frame->get_w() - 1);
1048 CLAMP(src_y, 0, frame->get_h() - 1);
1049 if(src_x + src_w > frame->get_w()) src_w = frame->get_w() - src_x;
1050 if(src_y + src_h > frame->get_h()) src_h = frame->get_h() - src_y;
1052 if(!temp_bitmap) temp_bitmap = new BC_Bitmap(this,
1058 temp_bitmap->match_params(dest_w,
1063 temp_bitmap->read_frame(frame,
1073 draw_bitmap(temp_bitmap,
1086 void BC_WindowBase::draw_tooltip(const char *text)
1089 text = tooltip_text;
1090 if(tooltip_popup && text)
1092 int w = tooltip_popup->get_w(), h = tooltip_popup->get_h();
1093 tooltip_popup->set_color(get_resources()->tooltip_bg_color);
1094 tooltip_popup->draw_box(0, 0, w, h);
1095 tooltip_popup->set_color(BLACK);
1096 tooltip_popup->draw_rectangle(0, 0, w, h);
1097 tooltip_popup->set_font(MEDIUMFONT);
1098 tooltip_popup->draw_text(TOOLTIP_MARGIN,
1099 get_text_ascent(MEDIUMFONT) + TOOLTIP_MARGIN,
1104 void BC_WindowBase::slide_left(int distance)
1108 XCopyArea(top_level->display,
1109 pixmap->opaque_pixmap,
1110 pixmap->opaque_pixmap,
1121 void BC_WindowBase::slide_right(int distance)
1125 XCopyArea(top_level->display,
1126 pixmap->opaque_pixmap,
1127 pixmap->opaque_pixmap,
1138 void BC_WindowBase::slide_up(int distance)
1142 XCopyArea(top_level->display,
1143 pixmap->opaque_pixmap,
1144 pixmap->opaque_pixmap,
1152 set_color(bg_color);
1153 XFillRectangle(top_level->display,
1154 pixmap->opaque_pixmap,
1163 void BC_WindowBase::slide_down(int distance)
1167 XCopyArea(top_level->display,
1168 pixmap->opaque_pixmap,
1169 pixmap->opaque_pixmap,
1177 set_color(bg_color);
1178 XFillRectangle(top_level->display,
1179 pixmap->opaque_pixmap,
1188 // 3 segments in separate pixmaps. Obsolete.
1189 void BC_WindowBase::draw_3segment(int x,
1193 BC_Pixmap *left_image,
1194 BC_Pixmap *mid_image,
1195 BC_Pixmap *right_image,
1198 if(w <= 0 || h <= 0) return;
1199 int left_boundary = left_image->get_w_fixed();
1200 int right_boundary = w - right_image->get_w_fixed();
1201 for(int i = 0; i < w; )
1205 if(i < left_boundary)
1208 if(i < right_boundary)
1211 image = right_image;
1213 int output_w = image->get_w_fixed();
1215 if(i < left_boundary)
1217 if(i + output_w > left_boundary) output_w = left_boundary - i;
1220 if(i < right_boundary)
1222 if(i + output_w > right_boundary) output_w = right_boundary - i;
1225 if(i + output_w > w) output_w = w - i;
1227 image->write_drawable(pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1238 // 3 segments in separate vframes. Obsolete.
1239 void BC_WindowBase::draw_3segment(int x,
1245 VFrame *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();
1253 for(int i = 0; i < w; )
1257 if(i < left_boundary)
1260 if(i < right_boundary)
1263 image = right_image;
1265 int output_w = image->get_w_fixed();
1267 if(i < left_boundary)
1269 if(i + output_w > left_boundary) output_w = left_boundary - i;
1272 if(i < right_boundary)
1274 if(i + output_w > right_boundary) output_w = right_boundary - i;
1277 if(i + output_w > w) output_w = w - i;
1291 if(output_w == 0) break;
1296 // Draw all 3 segments in a single vframe for a changing level
1301 // <------------------------------------------------------------>
1305 // <-------------------------------------------------------------------->
1307 // |-------------------|----------------------|------------------|
1310 void BC_WindowBase::draw_3segmenth(int x,
1325 void BC_WindowBase::draw_3segmenth(int x,
1333 if(total_w <= 0 || w <= 0 || h <= 0) return;
1334 int third_image = image->get_w() / 3;
1335 int half_image = image->get_w() / 2;
1336 //int left_boundary = third_image;
1337 //int right_boundary = total_w - third_image;
1339 int left_in_w = third_image;
1340 int left_out_x = total_x;
1341 int left_out_w = third_image;
1342 int right_in_x = image->get_w() - third_image;
1343 int right_in_w = third_image;
1344 int right_out_x = total_x + total_w - third_image;
1345 int right_out_w = third_image;
1346 int center_out_x = total_x + third_image;
1347 int center_out_w = total_w - third_image * 2;
1348 //int image_x, image_w;
1350 //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",
1351 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1355 left_in_w -= x - left_out_x;
1356 left_out_w -= x - left_out_x;
1357 left_in_x += x - left_out_x;
1358 left_out_x += x - left_out_x;
1361 if(left_out_x + left_out_w > x + w)
1363 left_in_w -= (left_out_x + left_out_w) - (x + w);
1364 left_out_w -= (left_out_x + left_out_w) - (x + w);
1369 right_in_w -= x - right_out_x;
1370 right_out_w -= x - right_out_x;
1371 right_in_x += x - right_out_x;
1372 right_out_x += x - right_out_x;
1375 if(right_out_x + right_out_w > x + w)
1377 right_in_w -= (right_out_x + right_out_w) - (x + w);
1378 right_out_w -= (right_out_x + right_out_w) - (x + w);
1381 if(center_out_x < x)
1383 center_out_w -= x - center_out_x;
1384 center_out_x += x - center_out_x;
1387 if(center_out_x + center_out_w > x + w)
1389 center_out_w -= (center_out_x + center_out_w) - (x + w);
1392 if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1397 temp_bitmap->match_params(image->get_w(),
1401 temp_bitmap->read_frame(image,
1408 //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",
1409 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1412 draw_bitmap(temp_bitmap,
1420 -1, // src width and height are meaningless in video_off mode
1427 draw_bitmap(temp_bitmap,
1435 -1, // src width and height are meaningless in video_off mode
1440 for(int pixel = center_out_x;
1441 pixel < center_out_x + center_out_w;
1442 pixel += half_image)
1444 int fragment_w = half_image;
1445 if(fragment_w + pixel > center_out_x + center_out_w)
1446 fragment_w = (center_out_x + center_out_w) - pixel;
1448 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1449 draw_bitmap(temp_bitmap,
1457 -1, // src width and height are meaningless in video_off mode
1470 void BC_WindowBase::draw_3segmenth(int x,
1478 if(w <= 0 || total_w <= 0) return;
1479 if(!src) printf("BC_WindowBase::draw_3segmenth src=0\n");
1480 int quarter_src = src->get_w() / 4;
1481 int half_src = src->get_w() / 2;
1482 //int left_boundary = quarter_src;
1483 //int right_boundary = total_w - quarter_src;
1485 int left_in_w = quarter_src;
1486 int left_out_x = total_x;
1487 int left_out_w = quarter_src;
1488 int right_in_x = src->get_w() - quarter_src;
1489 int right_in_w = quarter_src;
1490 int right_out_x = total_x + total_w - quarter_src;
1491 int right_out_w = quarter_src;
1492 int center_out_x = total_x + quarter_src;
1493 int center_out_w = total_w - quarter_src * 2;
1496 //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",
1497 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1501 left_in_w -= x - left_out_x;
1502 left_out_w -= x - left_out_x;
1503 left_in_x += x - left_out_x;
1504 left_out_x += x - left_out_x;
1507 if(left_out_x + left_out_w > x + w)
1509 left_in_w -= (left_out_x + left_out_w) - (x + w);
1510 left_out_w -= (left_out_x + left_out_w) - (x + w);
1515 right_in_w -= x - right_out_x;
1516 right_out_w -= x - right_out_x;
1517 right_in_x += x - right_out_x;
1518 right_out_x += x - right_out_x;
1521 if(right_out_x + right_out_w > x + w)
1523 right_in_w -= (right_out_x + right_out_w) - (x + w);
1524 right_out_w -= (right_out_x + right_out_w) - (x + w);
1527 if(center_out_x < x)
1529 center_out_w -= x - center_out_x;
1530 center_out_x += x - center_out_x;
1533 if(center_out_x + center_out_w > x + w)
1535 center_out_w -= (center_out_x + center_out_w) - (x + w);
1539 //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",
1540 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1565 for(int pixel = center_out_x;
1566 pixel < center_out_x + center_out_w;
1569 int fragment_w = half_src;
1570 if(fragment_w + pixel > center_out_x + center_out_w)
1571 fragment_w = (center_out_x + center_out_w) - pixel;
1573 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1587 void BC_WindowBase::draw_3segmenth(int x,
1594 int third_image = src->get_w() / 3;
1595 int half_output = w / 2;
1596 //int left_boundary = third_image;
1597 //int right_boundary = w - third_image;
1599 int left_in_w = third_image;
1601 int left_out_w = third_image;
1602 int right_in_x = src->get_w() - third_image;
1603 int right_in_w = third_image;
1604 int right_out_x = x + w - third_image;
1605 int right_out_w = third_image;
1606 //int image_x, image_w;
1608 //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",
1609 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1611 if(left_out_w > half_output)
1613 left_in_w -= left_out_w - half_output;
1614 left_out_w -= left_out_w - half_output;
1617 if(right_out_x < x + half_output)
1619 right_in_w -= x + half_output - right_out_x;
1620 right_out_w -= x + half_output - right_out_x;
1621 right_in_x += x + half_output - right_out_x;
1622 right_out_x += x + half_output - right_out_x;
1625 //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",
1626 // left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1651 for(int pixel = left_out_x + left_out_w;
1652 pixel < right_out_x;
1653 pixel += third_image)
1655 int fragment_w = third_image;
1656 if(fragment_w + pixel > right_out_x)
1657 fragment_w = right_out_x - pixel;
1659 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1678 void BC_WindowBase::draw_3segmentv(int x,
1685 int third_image = src->get_h() / 3;
1686 int half_output = h / 2;
1687 //int left_boundary = third_image;
1688 //int right_boundary = h - third_image;
1690 int left_in_h = third_image;
1692 int left_out_h = third_image;
1693 int right_in_y = src->get_h() - third_image;
1694 int right_in_h = third_image;
1695 int right_out_y = y + h - third_image;
1696 int right_out_h = third_image;
1697 //int image_y, image_h;
1700 if(left_out_h > half_output)
1702 left_in_h -= left_out_h - half_output;
1703 left_out_h -= left_out_h - half_output;
1706 if(right_out_y < y + half_output)
1708 right_in_h -= y + half_output - right_out_y;
1709 right_out_h -= y + half_output - right_out_y;
1710 right_in_y += y + half_output - right_out_y;
1711 right_out_y += y + half_output - right_out_y;
1715 if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1720 temp_bitmap->match_params(src->get_w(),
1724 temp_bitmap->read_frame(src,
1733 draw_bitmap(temp_bitmap,
1748 draw_bitmap(temp_bitmap,
1761 for(int pixel = left_out_y + left_out_h;
1762 pixel < right_out_y;
1763 pixel += third_image)
1765 int fragment_h = third_image;
1766 if(fragment_h + pixel > right_out_y)
1767 fragment_h = right_out_y - pixel;
1769 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1770 draw_bitmap(temp_bitmap,
1784 void BC_WindowBase::draw_3segmentv(int x,
1791 int third_image = src->get_h() / 3;
1792 int half_output = h / 2;
1793 //int left_boundary = third_image;
1794 //int right_boundary = h - third_image;
1796 int left_in_h = third_image;
1798 int left_out_h = third_image;
1799 int right_in_y = src->get_h() - third_image;
1800 int right_in_h = third_image;
1801 int right_out_y = y + h - third_image;
1802 int right_out_h = third_image;
1803 //int image_y, image_h;
1806 if(left_out_h > half_output)
1808 left_in_h -= left_out_h - half_output;
1809 left_out_h -= left_out_h - half_output;
1812 if(right_out_y < y + half_output)
1814 right_in_h -= y + half_output - right_out_y;
1815 right_out_h -= y + half_output - right_out_y;
1816 right_in_y += y + half_output - right_out_y;
1817 right_out_y += y + half_output - right_out_y;
1844 for(int pixel = left_out_y + left_out_h;
1845 pixel < right_out_y;
1846 pixel += third_image)
1848 int fragment_h = third_image;
1849 if(fragment_h + pixel > right_out_y)
1850 fragment_h = right_out_y - pixel;
1852 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1865 void BC_WindowBase::draw_9segment(int x,
1872 if(w <= 0 || h <= 0) return;
1874 int in_x_third = src->get_w() / 3;
1875 int in_y_third = src->get_h() / 3;
1876 int out_x_half = w / 2;
1877 int out_y_half = h / 2;
1883 int in_x2 = MIN(in_x_third, out_x_half);
1884 int in_y2 = MIN(in_y_third, out_y_half);
1888 int out_x3 = MAX(w - out_x_half, w - in_x_third);
1890 int in_x3 = src->get_w() - (out_x4 - out_x3);
1891 //int in_x4 = src->get_w();
1893 int out_y3 = MAX(h - out_y_half, h - in_y_third);
1895 int in_y3 = src->get_h() - (out_y4 - out_y3);
1896 //int in_y4 = src->get_h();
1910 for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
1914 int w = MIN(in_x3 - in_x2, out_x3 - i);
1943 for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
1947 int h = MIN(in_y3 - in_y2, out_y3 - i);
1960 // Segment 5 * n * n
1961 for(int i = out_y2; i < out_y3; i += in_y3 - in_y2 /* in_y_third */)
1965 int h = MIN(in_y3 - in_y2 /* in_y_third */, out_y3 - i);
1968 for(int j = out_x2; j < out_x3; j += in_x3 - in_x2 /* in_x_third */)
1970 int w = MIN(in_x3 - in_x2 /* in_x_third */, out_x3 - j);
1985 for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
1989 int h = MIN(in_y3 - in_y2, out_y3 - i);
2016 for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
2020 int w = MIN(in_x3 - in_y2, out_x3 - i);
2046 void BC_WindowBase::draw_9segment(int x,
2053 if(w <= 0 || h <= 0) return;
2055 int in_x_third = src->get_w() / 3;
2056 int in_y_third = src->get_h() / 3;
2057 int out_x_half = w / 2;
2058 int out_y_half = h / 2;
2064 int in_x2 = MIN(in_x_third, out_x_half);
2065 int in_y2 = MIN(in_y_third, out_y_half);
2069 int out_x3 = MAX(w - out_x_half, w - in_x_third);
2071 int in_x3 = src->get_w() - (out_x4 - out_x3);
2072 int in_x4 = src->get_w();
2074 int out_y3 = MAX(h - out_y_half, h - in_y_third);
2076 int in_y3 = src->get_h() - (out_y4 - out_y3);
2077 int in_y4 = src->get_h();
2079 //printf("PFCFrame::draw_9segment 1 %d %d %d %d\n", out_x1, out_x2, out_x3, out_x4);
2080 //printf("PFCFrame::draw_9segment 2 %d %d %d %d\n", in_x1, in_x2, in_x3, in_x4);
2081 //printf("PFCFrame::draw_9segment 2 %d %d %d %d\n", in_y1, in_y2, in_y3, in_y4);
2083 if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
2088 temp_bitmap->match_params(src->get_w(),
2092 temp_bitmap->read_frame(src,
2099 draw_bitmap(temp_bitmap,
2113 for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
2117 int w = MIN(in_x3 - in_x2, out_x3 - i);
2118 draw_bitmap(temp_bitmap,
2137 draw_bitmap(temp_bitmap,
2152 for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
2156 int h = MIN(in_y3 - in_y2, out_y3 - i);
2157 draw_bitmap(temp_bitmap,
2172 // Segment 5 * n * n
2173 for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
2177 int h = MIN(in_y3 - in_y2, out_y3 - i);
2180 for(int j = out_x2; j < out_x3; j += in_x3 - in_x2)
2182 int w = MIN(in_x3 - in_x2, out_x3 - j);
2184 draw_bitmap(temp_bitmap,
2200 for(int i = out_y2; i < out_y3; i += in_y_third)
2204 int h = MIN(in_y_third, out_y3 - i);
2205 draw_bitmap(temp_bitmap,
2223 draw_bitmap(temp_bitmap,
2237 for(int i = out_x2; i < out_x3; i += in_x_third)
2241 int w = MIN(in_x_third, out_x3 - i);
2242 draw_bitmap(temp_bitmap,
2259 draw_bitmap(temp_bitmap,