gamma yuva hist fix, theme change without exit
[goodguy/history.git] / cinelerra-5.0 / guicast / bcwindowdraw.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  */
21
22 #include "bcbitmap.h"
23 #include "bcpixmap.h"
24 #include "bcpopup.h"
25 #include "bcresources.h"
26 #include "bcsignals.h"
27 #include "bcsynchronous.h"
28 #include "bctimer.h"
29 #include "bcwindowbase.h"
30 #include "clip.h"
31 #include "colors.h"
32 #include "cursors.h"
33 #include "fonts.h"
34 #include "vframe.h"
35 #include <string.h>
36 #include <wchar.h>
37 #include <ft2build.h>
38
39 void BC_WindowBase::copy_area(int x1, int y1, int x2, int y2, int w, int h, BC_Pixmap *pixmap)
40 {
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);
45 }
46
47
48 void BC_WindowBase::draw_box(int x, int y, int w, int h, BC_Pixmap *pixmap)
49 {
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);
54 }
55
56
57 void BC_WindowBase::draw_circle(int x, int y, int w, int h, BC_Pixmap *pixmap)
58 {
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);
62 }
63
64 void BC_WindowBase::draw_arc(int x, int y, int w, int h,
65         int start_angle, int angle_length, BC_Pixmap *pixmap)
66 {
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,
70                 angle_length * 64);
71 }
72
73 void BC_WindowBase::draw_disc(int x, int y, int w, int h, BC_Pixmap *pixmap)
74 {
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);
78 }
79
80 void BC_WindowBase::clear_box(int x, int y, int w, int h, BC_Pixmap *pixmap)
81 {
82         set_color(bg_color);
83         Pixmap xpixmap = pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap;
84         XFillRectangle(top_level->display, xpixmap, top_level->gc, x, y, w, h);
85 }
86
87 void BC_WindowBase::draw_text_line(int x, int y, const char *text, int len,
88         BC_Pixmap *pixmap)
89 {
90 #ifdef HAVE_XFT
91         if( get_resources()->use_xft ) {
92                 draw_xft_text(x, y, text, len, pixmap);
93                 return;
94         }
95 #endif
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();
99                 if( fontset ) {
100                         XmbDrawString(top_level->display, xpixmap, fontset,
101                                 top_level->gc, x, y, text, len);
102                         return;
103                 }
104
105         }
106 //printf("BC_WindowBase::draw_text 3\n");
107         XDrawString(top_level->display, xpixmap, top_level->gc, x, y, text, len);
108 }
109
110 void BC_WindowBase::draw_text(int x, int y, const char *text, int length,
111         BC_Pixmap *pixmap)
112 {
113         if( length < 0 ) length = strlen(text);
114         //int boldface = top_level->current_font & BOLDFACE;
115         int font = top_level->current_font & 0xff;
116
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;
121                         int ch = text[i];
122                         switch( ch ) {
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;
133                                 break;
134                         case '-': image = img7seg[19];      break;
135                         default:
136                         case ' ': image = img7seg[18];      break;
137                         }
138
139                         draw_vframe(image, x, y - image->get_h());
140                         x += image->get_w();
141                 }
142                 break;
143
144         default: {
145                         if(top_level->get_xft_struct(top_level->current_font)) {
146                                 draw_xft_text(x, y, text, length, pixmap);
147                                 return;
148                         }
149
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);
157                                         }
158                                         else {
159                                                 XDrawString(top_level->display,
160                                                         pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
161                                                         top_level->gc, x, y, &text[j], i-j);
162                                         }
163                                         j = i;
164                                         y += get_text_height(font);
165                                 }
166                         }
167                 }
168                 break;
169         }
170 }
171
172 void BC_WindowBase::draw_utf8_text(int x, int y,
173         const char *text, int length, BC_Pixmap *pixmap)
174 {
175         if(length < 0) length = strlen(text);
176
177         if(top_level->get_xft_struct(top_level->current_font))
178         {
179                 draw_xft_text(x,
180                         y,
181                         text,
182                         length,
183                         pixmap,
184                         1);
185                 return;
186         }
187
188         for(int i = 0, j = 0; i <= length; i++)
189         {
190                 if(text[i] == '\n' || text[i] == 0)
191                 {
192                         if(get_resources()->use_fontset && top_level->get_curr_fontset())
193                         {
194                                 XmbDrawString(top_level->display,
195                                         pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
196                                         top_level->get_curr_fontset(),
197                                         top_level->gc,
198                                         x,
199                                         y,
200                                         &text[j],
201                                         i - j);
202                         }
203                         else
204                         {
205                                 XDrawString(top_level->display,
206                                         pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
207                                         top_level->gc,
208                                         x,
209                                         y,
210                                         &text[j],
211                                         i - j);
212                         }
213
214                         j = i + 1;
215                         y += get_text_height(MEDIUMFONT);
216                 }
217         }
218 }
219
220 void BC_WindowBase::draw_xft_text(int x, int y, 
221         const char *text, int length, BC_Pixmap *pixmap, int is_utf8)
222 {
223         int l = length + 1;
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);
229 }
230
231 void BC_WindowBase::draw_xft_text(int x, int y,
232         const wchar_t *text, int length, BC_Pixmap *pixmap)
233 {
234         int dy = -1;
235         const wchar_t *wsp = text, *wep = wsp + length;
236         while( wsp < wep ) {
237                 const wchar_t *wcp = wsp;
238                 while( wcp < wep && *wcp != '\n' ) ++wcp;
239                 int len = wcp - wsp;
240                 if( len > 0 )
241                         draw_wtext(x, y, wsp, len, pixmap);
242                 if( wcp >= wep ) break;
243                 if( dy < 0 )
244                         dy = get_text_height(top_level->current_font);
245                 y += dy;
246                 wsp = wcp + 1;
247         }
248 }
249
250 int BC_WindowBase::wcharpos(const wchar_t *text, XftFont *font, int length,
251                 int *charpos)
252 {
253         XGlyphInfo extents;
254
255         if(charpos)
256         {
257                 int bpos = charpos[-1];
258
259                 for(int i = 0; i < length; i++)
260                 {
261                         XftTextExtents32(top_level->display,
262                                 font,
263                                 (const FcChar32*)text,
264                                 i + 1,
265                                 &extents);
266                         charpos[i] = extents.xOff + bpos;
267                 }
268                 return charpos[length - 1] - bpos;
269         }
270         else
271         {
272                 XftTextExtents32(top_level->display,
273                         font,
274                         (const FcChar32*)text,
275                         length,
276                         &extents);
277                 return extents.xOff;
278         }
279 }
280
281 void BC_WindowBase::draw_wtext(int x, int y,
282         const wchar_t *text, int length, BC_Pixmap *pixmap, int *charpos)
283 {
284         if( !get_resources()->use_xft ) {
285                 if( !get_font_struct(current_font) ) return;
286                 XChar2b xtext[length], *xp = xtext;
287                 for( int i=0; i<length; ++i,++xp ) {
288                         xp->byte1 = (unsigned char) (text[i] >> 8);
289                         xp->byte2 = (unsigned char) (text[i] & 0xff);
290                 }
291                 XDrawString16(top_level->display,
292                         pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
293                         top_level->gc, x, y, xtext, length);
294                 return;
295         }
296         XRenderColor color;
297         XftColor xft_color;
298         const wchar_t *up, *ubp;
299         int l, *cp;
300         FcPattern *newpat;
301         XftFont *curfont, *nextfont, *altfont, *basefont;
302
303         if(length < 0)
304                 length = wcslen(text);
305
306         if(charpos)
307                 charpos[0] = 0;
308         if(!length)
309                 return;
310
311         color.red = (top_level->current_color & 0xff0000) >> 16;
312         color.red |= color.red << 8;
313         color.green = (top_level->current_color & 0xff00) >> 8;
314         color.green |= color.green << 8;
315         color.blue = (top_level->current_color & 0xff);
316         color.blue |= color.blue << 8;
317         color.alpha = 0xffff;
318
319         XftColorAllocValue(top_level->display,
320                 top_level->vis,
321                 top_level->cmap,
322                 &color,
323                 &xft_color);
324
325         basefont = top_level->get_xft_struct(top_level->current_font);
326
327         curfont = nextfont = basefont;
328         altfont = 0;
329         cp = 0;
330         ubp = text;
331
332         for(up = text; up < &text[length]; up++)
333         {
334                 if(XftCharExists(top_level->display, basefont, *up))
335                         nextfont = basefont;
336                 else if(altfont && XftCharExists(top_level->display, altfont, *up))
337                         nextfont = altfont;
338                 else
339                 {
340                         if(altfont)
341                                 XftFontClose(top_level->display, altfont);
342
343                         if( (newpat = BC_Resources::find_similar_font(*up, basefont->pattern)) != 0 ) {
344                                 double psize;
345
346                                 FcPatternGetDouble(basefont->pattern, FC_PIXEL_SIZE,
347                                         0, &psize);
348                                 FcPatternAddDouble(newpat, FC_PIXEL_SIZE, psize);
349                                 FcPatternDel(newpat, FC_SCALABLE);
350                                 altfont = XftFontOpenPattern(top_level->display,
351                                         newpat);
352                                 if(altfont)
353                                 nextfont = altfont;
354                         }
355                         else
356                         {
357                                 altfont = 0;
358                                 nextfont = basefont;
359                         }
360                 }
361                 if(nextfont != curfont)
362                 {
363                         l = up - ubp;
364                         XftDrawString32((XftDraw*)(pixmap ? pixmap->opaque_xft_draw : this->pixmap->opaque_xft_draw),
365                                 &xft_color,
366                                 curfont,
367                                 x,
368                                 y,
369                                 (const FcChar32*)ubp,
370                                 l);
371
372                         if(charpos)
373                                 cp = &charpos[ubp - text + 1];
374
375                         x += wcharpos(ubp, curfont, l, cp);
376                         ubp = up;
377                         curfont = nextfont;
378                 }
379         }
380
381         if(up > ubp)
382         {
383                 XftDrawString32((XftDraw*)(pixmap ? pixmap->opaque_xft_draw : this->pixmap->opaque_xft_draw),
384                         &xft_color,
385                         curfont,
386                         x,
387                         y,
388                         (const FcChar32*)ubp,
389                         up - ubp);
390                 if(charpos)
391                         wcharpos(ubp, curfont, up - ubp, &charpos[ubp - text + 1]);
392         }
393
394         if(altfont)
395                 XftFontClose(top_level->display, altfont);
396
397         XftColorFree(top_level->display,
398                 top_level->vis,
399                 top_level->cmap,
400                 &xft_color);
401 }
402
403 void BC_WindowBase::truncate_text(char *result, const char *text, int w)
404 {
405         int new_w = get_text_width(current_font, text);
406
407         if(new_w > w)
408         {
409                 const char* separator = "...";
410                 int separator_w = get_text_width(current_font, separator);
411 // can't fit
412                 if(separator_w >= w)
413                 {
414                         strcpy(result, separator);
415                         return;
416                 }
417
418                 int text_len = strlen(text);
419 // widen middle gap until it fits
420                 for(int i = text_len / 2; i > 0; i--)
421                 {
422                         strncpy(result, text, i);
423                         result[i] = 0;
424                         strcat(result, separator);
425                         strncat(result, text + text_len - i, i);
426                         result[i + strlen(separator) + i] = 0;
427                         new_w = get_text_width(current_font, result);
428 //printf("BC_WindowBase::truncate_text %d %d %d %s\n", __LINE__, new_w, w, result);
429                         if(new_w < w) return;
430                 }
431
432 // Didn't fit
433                 strcpy(result, separator);
434                 return;
435         }
436         else
437         {
438                 strcpy(result, text);
439         }
440 }
441
442 void BC_WindowBase::draw_center_text(int x, int y, const char *text, int length)
443 {
444         if(length < 0) length = strlen(text);
445         int w = get_text_width(current_font, text, length);
446         x -= w / 2;
447         draw_text(x, y, text, length);
448 }
449
450 void BC_WindowBase::draw_line(int x1, int y1, int x2, int y2, BC_Pixmap *pixmap)
451 {
452 // Some X drivers can't draw 0 length lines
453         if(x1 == x2 && y1 == y2)
454         {
455                 draw_pixel(x1, y1, pixmap);
456         }
457         else
458         {
459                 XDrawLine(top_level->display,
460                         pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
461                         top_level->gc,
462                         x1,
463                         y1,
464                         x2,
465                         y2);
466         }
467 }
468
469 void BC_WindowBase::draw_polygon(ArrayList<int> *x, ArrayList<int> *y, BC_Pixmap *pixmap)
470 {
471         int npoints = MIN(x->total, y->total);
472         XPoint *points = new XPoint[npoints];
473
474         for(int i = 0; i < npoints; i++)
475         {
476                 points[i].x = x->values[i];
477                 points[i].y = y->values[i];
478         }
479
480         XDrawLines(top_level->display,
481         pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
482         top_level->gc,
483         points,
484         npoints,
485         CoordModeOrigin);
486
487         delete [] points;
488 }
489
490 void BC_WindowBase::fill_polygon(ArrayList<int> *x, ArrayList<int> *y, BC_Pixmap *pixmap)
491 {
492         int npoints = MIN(x->total, y->total);
493         XPoint *points = new XPoint[npoints];
494
495         for(int i = 0; i < npoints; i++)
496         {
497                 points[i].x = x->values[i];
498                 points[i].y = y->values[i];
499         }
500
501         XFillPolygon(top_level->display,
502         pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
503         top_level->gc,
504         points,
505         npoints,
506                 Nonconvex,
507         CoordModeOrigin);
508
509         delete [] points;
510 }
511
512
513 void BC_WindowBase::draw_rectangle(int x, int y, int w, int h)
514 {
515         XDrawRectangle(top_level->display,
516                 pixmap->opaque_pixmap,
517                 top_level->gc,
518                 x,
519                 y,
520                 w - 1,
521                 h - 1);
522 }
523
524 void BC_WindowBase::draw_3d_border(int x,
525         int y,
526         int w,
527         int h,
528         int is_down)
529 {
530         draw_3d_border(x,
531                 y,
532                 w,
533                 h,
534                 top_level->get_resources()->border_shadow2,
535                 top_level->get_resources()->border_shadow1,
536                 top_level->get_resources()->border_light1,
537                 top_level->get_resources()->border_light2);
538 }
539
540
541 void BC_WindowBase::draw_3d_border(int x,
542         int y,
543         int w,
544         int h,
545         int light1,
546         int light2,
547         int shadow1,
548         int shadow2)
549 {
550         int lx, ly, ux, uy;
551
552         h--; w--;
553
554         lx = x+1;  ly = y+1;
555         ux = x+w-1;  uy = y+h-1;
556
557         set_color(light1);
558         draw_line(x, y, ux, y);
559         draw_line(x, y, x, uy);
560         set_color(light2);
561         draw_line(lx, ly, ux - 1, ly);
562         draw_line(lx, ly, lx, uy - 1);
563
564         set_color(shadow1);
565         draw_line(ux, ly, ux, uy);
566         draw_line(lx, uy, ux, uy);
567         set_color(shadow2);
568         draw_line(x + w, y, x + w, y + h);
569         draw_line(x, y + h, x + w, y + h);
570 }
571
572 void BC_WindowBase::draw_3d_box(int x,
573         int y,
574         int w,
575         int h,
576         int light1,
577         int light2,
578         int middle,
579         int shadow1,
580         int shadow2,
581         BC_Pixmap *pixmap)
582 {
583         int lx, ly, ux, uy;
584
585         h--; w--;
586
587         lx = x+1;  ly = y+1;
588         ux = x+w-1;  uy = y+h-1;
589
590         set_color(middle);
591         draw_box(x, y, w, h, pixmap);
592
593         set_color(light1);
594         draw_line(x, y, ux, y, pixmap);
595         draw_line(x, y, x, uy, pixmap);
596         set_color(light2);
597         draw_line(lx, ly, ux - 1, ly, pixmap);
598         draw_line(lx, ly, lx, uy - 1, pixmap);
599
600         set_color(shadow1);
601         draw_line(ux, ly, ux, uy, pixmap);
602         draw_line(lx, uy, ux, uy, pixmap);
603         set_color(shadow2);
604         draw_line(x + w, y, x + w, y + h, pixmap);
605         draw_line(x, y + h, x + w, y + h, pixmap);
606 }
607
608 void BC_WindowBase::draw_colored_box(int x, int y, int w, int h, int down, int highlighted)
609 {
610         if(!down)
611         {
612                 if(highlighted)
613                         draw_3d_box(x, y, w, h,
614                                 top_level->get_resources()->button_light,
615                                 top_level->get_resources()->button_highlighted,
616                                 top_level->get_resources()->button_highlighted,
617                                 top_level->get_resources()->button_shadow,
618                                 BLACK);
619                 else
620                         draw_3d_box(x, y, w, h,
621                                 top_level->get_resources()->button_light,
622                                 top_level->get_resources()->button_up,
623                                 top_level->get_resources()->button_up,
624                                 top_level->get_resources()->button_shadow,
625                                 BLACK);
626         }
627         else
628         {
629 // need highlighting for toggles
630                 if(highlighted)
631                         draw_3d_box(x, y, w, h,
632                                 top_level->get_resources()->button_shadow,
633                                 BLACK,
634                                 top_level->get_resources()->button_up,
635                                 top_level->get_resources()->button_up,
636                                 top_level->get_resources()->button_light);
637                 else
638                         draw_3d_box(x, y, w, h,
639                                 top_level->get_resources()->button_shadow,
640                                 BLACK,
641                                 top_level->get_resources()->button_down,
642                                 top_level->get_resources()->button_down,
643                                 top_level->get_resources()->button_light);
644         }
645 }
646
647
648 void BC_WindowBase::draw_border(char *text, int x, int y, int w, int h)
649 {
650         int left_indent = 20;
651         int lx, ly, ux, uy;
652
653         h--; w--;
654         lx = x + 1;  ly = y + 1;
655         ux = x + w - 1;  uy = y + h - 1;
656
657         set_opaque();
658         if(text && text[0] != 0)
659         {
660                 set_color(BLACK);
661                 set_font(MEDIUMFONT);
662                 draw_text(x + left_indent, y + get_text_height(MEDIUMFONT) / 2, text);
663         }
664
665         set_color(top_level->get_resources()->button_shadow);
666         draw_line(x, y, x + left_indent - 5, y);
667         draw_line(x, y, x, uy);
668         draw_line(x + left_indent + 5 + get_text_width(MEDIUMFONT, text), y, ux, y);
669         draw_line(x, y, x, uy);
670         draw_line(ux, ly, ux, uy);
671         draw_line(lx, uy, ux, uy);
672         set_color(top_level->get_resources()->button_light);
673         draw_line(lx, ly, x + left_indent - 5 - 1, ly);
674         draw_line(lx, ly, lx, uy - 1);
675         draw_line(x + left_indent + 5 + get_text_width(MEDIUMFONT, text), ly, ux - 1, ly);
676         draw_line(lx, ly, lx, uy - 1);
677         draw_line(x + w, y, x + w, y + h);
678         draw_line(x, y + h, x + w, y + h);
679 }
680
681 void BC_WindowBase::draw_triangle_down_flat(int x, int y, int w, int h)
682 {
683         int x1, y1, x2, y2, x3;
684         XPoint point[3];
685
686         x1 = x; x2 = x + w / 2; x3 = x + w - 1;
687         y1 = y; y2 = y + h - 1;
688
689         point[0].x = x2; point[0].y = y2; point[1].x = x3;
690         point[1].y = y1; point[2].x = x1; point[2].y = y1;
691
692         XFillPolygon(top_level->display,
693                 pixmap->opaque_pixmap,
694                 top_level->gc,
695                 (XPoint *)point,
696                 3,
697                 Nonconvex,
698                 CoordModeOrigin);
699 }
700
701 void BC_WindowBase::draw_triangle_up(int x, int y, int w, int h,
702         int light1, int light2, int middle, int shadow1, int shadow2)
703 {
704         int x1, y1, x2, y2, x3;
705         XPoint point[3];
706
707         x1 = x; y1 = y; x2 = x + w / 2;
708         y2 = y + h - 1; x3 = x + w - 1;
709
710 // middle
711         point[0].x = x2; point[0].y = y1; point[1].x = x3;
712         point[1].y = y2; point[2].x = x1; point[2].y = y2;
713
714         set_color(middle);
715         XFillPolygon(top_level->display,
716                 pixmap->opaque_pixmap,
717                 top_level->gc,
718                 (XPoint *)point,
719                 3,
720                 Nonconvex,
721                 CoordModeOrigin);
722
723 // bottom and top right
724         set_color(shadow1);
725         draw_line(x3, y2-1, x1, y2-1);
726         draw_line(x2-1, y1, x3-1, y2);
727         set_color(shadow2);
728         draw_line(x3, y2, x1, y2);
729         draw_line(x2, y1, x3, y2);
730
731 // top left
732         set_color(light2);
733         draw_line(x2+1, y1, x1+1, y2);
734         set_color(light1);
735         draw_line(x2, y1, x1, y2);
736 }
737
738 void BC_WindowBase::draw_triangle_down(int x, int y, int w, int h,
739         int light1, int light2, int middle, int shadow1, int shadow2)
740 {
741         int x1, y1, x2, y2, x3;
742         XPoint point[3];
743
744         x1 = x; x2 = x + w / 2; x3 = x + w - 1;
745         y1 = y; y2 = y + h - 1;
746
747         point[0].x = x2; point[0].y = y2; point[1].x = x3;
748         point[1].y = y1; point[2].x = x1; point[2].y = y1;
749
750         set_color(middle);
751         XFillPolygon(top_level->display,
752                 pixmap->opaque_pixmap,
753                 top_level->gc,
754                 (XPoint *)point,
755                 3,
756                 Nonconvex,
757                 CoordModeOrigin);
758
759 // top and bottom left
760         set_color(light2);
761         draw_line(x3-1, y1+1, x1+1, y1+1);
762         draw_line(x1+1, y1, x2+1, y2);
763         set_color(light1);
764         draw_line(x3, y1, x1, y1);
765         draw_line(x1, y1, x2, y2);
766
767 // bottom right
768         set_color(shadow1);
769         draw_line(x3-1, y1, x2-1, y2);
770         set_color(shadow2);
771         draw_line(x3, y1, x2, y2);
772 }
773
774 void BC_WindowBase::draw_triangle_left(int x, int y, int w, int h,
775         int light1, int light2, int middle, int shadow1, int shadow2)
776 {
777         int x1, y1, x2, y2, y3;
778         XPoint point[3];
779
780         // draw back arrow
781         y1 = y; x1 = x; y2 = y + h / 2;
782         x2 = x + w - 1; y3 = y + h - 1;
783
784         point[0].x = x1; point[0].y = y2; point[1].x = x2;
785         point[1].y = y1; point[2].x = x2; point[2].y = y3;
786
787         set_color(middle);
788         XFillPolygon(top_level->display,
789                 pixmap->opaque_pixmap,
790                 top_level->gc,
791                 (XPoint *)point,
792                 3,
793                 Nonconvex,
794                 CoordModeOrigin);
795
796 // right and bottom right
797         set_color(shadow1);
798         draw_line(x2-1, y1, x2-1, y3-1);
799         draw_line(x2, y3-1, x1, y2-1);
800         set_color(shadow2);
801         draw_line(x2, y1, x2, y3);
802         draw_line(x2, y3, x1, y2);
803
804 // top left
805         set_color(light1);
806         draw_line(x1, y2, x2, y1);
807         set_color(light2);
808         draw_line(x1, y2+1, x2, y1+1);
809 }
810
811 void BC_WindowBase::draw_triangle_right(int x, int y, int w, int h,
812         int light1, int light2, int middle, int shadow1, int shadow2)
813 {
814         int x1, y1, x2, y2, y3;
815         XPoint point[3];
816
817         y1 = y; y2 = y + h / 2; y3 = y + h - 1;
818         x1 = x; x2 = x + w - 1;
819
820         point[0].x = x1; point[0].y = y1; point[1].x = x2;
821         point[1].y = y2; point[2].x = x1; point[2].y = y3;
822
823         set_color(middle);
824         XFillPolygon(top_level->display,
825                 pixmap->opaque_pixmap,
826                 top_level->gc,
827                 (XPoint *)point,
828                 3,
829                 Nonconvex,
830                 CoordModeOrigin);
831
832 // left and top right
833         set_color(light2);
834         draw_line(x1+1, y3, x1+1, y1);
835         draw_line(x1, y1+1, x2, y2+1);
836         set_color(light1);
837         draw_line(x1, y3, x1, y1);
838         draw_line(x1, y1, x2, y2);
839
840 // bottom right
841         set_color(shadow1);
842         draw_line(x2, y2-1, x1, y3-1);
843         set_color(shadow2);
844         draw_line(x2, y2, x1, y3);
845 }
846
847
848 void BC_WindowBase::draw_check(int x, int y)
849 {
850         const int w = 15, h = 15;
851         draw_line(x + 3, y + h / 2 + 0, x + 6, y + h / 2 + 2);
852         draw_line(x + 3, y + h / 2 + 1, x + 6, y + h / 2 + 3);
853         draw_line(x + 6, y + h / 2 + 2, x + w - 4, y + h / 2 - 3);
854         draw_line(x + 3, y + h / 2 + 2, x + 6, y + h / 2 + 4);
855         draw_line(x + 6, y + h / 2 + 2, x + w - 4, y + h / 2 - 3);
856         draw_line(x + 6, y + h / 2 + 3, x + w - 4, y + h / 2 - 2);
857         draw_line(x + 6, y + h / 2 + 4, x + w - 4, y + h / 2 - 1);
858 }
859
860 void BC_WindowBase::draw_tiles(BC_Pixmap *tile, int origin_x, int origin_y, int x, int y, int w, int h)
861 {
862         if(!tile)
863         {
864                 set_color(bg_color);
865                 draw_box(x, y, w, h);
866         }
867         else
868         {
869                 XSetFillStyle(top_level->display, top_level->gc, FillTiled);
870 // Don't know how slow this is
871                 XSetTile(top_level->display, top_level->gc, tile->get_pixmap());
872                 XSetTSOrigin(top_level->display, top_level->gc, origin_x, origin_y);
873                 draw_box(x, y, w, h);
874                 XSetFillStyle(top_level->display, top_level->gc, FillSolid);
875         }
876 }
877
878 void BC_WindowBase::draw_top_tiles(BC_WindowBase *parent_window, int x, int y, int w, int h)
879 {
880         Window tempwin;
881         int origin_x, origin_y;
882         XTranslateCoordinates(top_level->display,
883                         parent_window->win,
884                         win,
885                         0,
886                         0,
887                         &origin_x,
888                         &origin_y,
889                         &tempwin);
890
891         draw_tiles(parent_window->bg_pixmap,
892                 origin_x,
893                 origin_y,
894                 x,
895                 y,
896                 w,
897                 h);
898 }
899
900 void BC_WindowBase::draw_top_background(BC_WindowBase *parent_window,
901         int x,
902         int y,
903         int w,
904         int h,
905         BC_Pixmap *pixmap)
906 {
907         Window tempwin;
908         int top_x, top_y;
909         XLockDisplay(top_level->display);
910
911         XTranslateCoordinates(top_level->display,
912                         win,
913                         parent_window->win,
914                         x,
915                         y,
916                         &top_x,
917                         &top_y,
918                         &tempwin);
919
920         XCopyArea(top_level->display,
921                 parent_window->pixmap->opaque_pixmap,
922                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
923                 top_level->gc,
924                 top_x,
925                 top_y,
926                 w,
927                 h,
928                 x,
929                 y);
930
931         XUnlockDisplay(top_level->display);
932 }
933
934 void BC_WindowBase::draw_background(int x, int y, int w, int h)
935 {
936         if(bg_pixmap)
937         {
938                 draw_tiles(bg_pixmap, 0, 0, x, y, w, h);
939         }
940         else
941         {
942                 clear_box(x, y, w, h);
943         }
944 }
945
946 void BC_WindowBase::draw_bitmap(BC_Bitmap *bitmap,
947         int dont_wait,
948         int dest_x,
949         int dest_y,
950         int dest_w,
951         int dest_h,
952         int src_x,
953         int src_y,
954         int src_w,
955         int src_h,
956         BC_Pixmap *pixmap)
957 {
958
959 // Hide cursor if video enabled
960         update_video_cursor();
961
962 //printf("BC_WindowBase::draw_bitmap 1\n");
963         if(dest_w <= 0 || dest_h <= 0)
964         {
965 // Use hardware scaling to canvas dimensions if proper color model.
966                 if(bitmap->get_color_model() == BC_YUV420P)
967                 {
968                         dest_w = w;
969                         dest_h = h;
970                 }
971                 else
972                 {
973                         dest_w = bitmap->get_w();
974                         dest_h = bitmap->get_h();
975                 }
976         }
977
978         if(src_w <= 0 || src_h <= 0)
979         {
980                 src_w = bitmap->get_w();
981                 src_h = bitmap->get_h();
982         }
983
984         if(video_on)
985         {
986                 bitmap->write_drawable(win,
987                         top_level->gc,
988                         src_x,
989                         src_y,
990                         src_w,
991                         src_h,
992                         dest_x,
993                         dest_y,
994                         dest_w,
995                         dest_h,
996                         dont_wait);
997                 top_level->flush();
998         }
999         else
1000         {
1001                 bitmap->write_drawable(pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1002                         top_level->gc,
1003                         dest_x,
1004                         dest_y,
1005                         src_x,
1006                         src_y,
1007                         dest_w,
1008                         dest_h,
1009                         dont_wait);
1010         }
1011 //printf("BC_WindowBase::draw_bitmap 2\n");
1012 }
1013
1014
1015 void BC_WindowBase::draw_pixel(int x, int y, BC_Pixmap *pixmap)
1016 {
1017         XDrawPoint(top_level->display,
1018                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1019                 top_level->gc,
1020                 x,
1021                 y);
1022 }
1023
1024
1025 void BC_WindowBase::draw_pixmap(BC_Pixmap *pixmap,
1026         int dest_x,
1027         int dest_y,
1028         int dest_w,
1029         int dest_h,
1030         int src_x,
1031         int src_y,
1032         BC_Pixmap *dst)
1033 {
1034         pixmap->write_drawable(dst ? dst->opaque_pixmap : this->pixmap->opaque_pixmap,
1035                         dest_x,
1036                         dest_y,
1037                         dest_w,
1038                         dest_h,
1039                         src_x,
1040                         src_y);
1041 }
1042
1043 void BC_WindowBase::draw_vframe(VFrame *frame,
1044                 int dest_x,
1045                 int dest_y,
1046                 int dest_w,
1047                 int dest_h,
1048                 int src_x,
1049                 int src_y,
1050                 int src_w,
1051                 int src_h,
1052                 BC_Pixmap *pixmap)
1053 {
1054         if(dest_w <= 0) dest_w = frame->get_w() - src_x;
1055         if(dest_h <= 0) dest_h = frame->get_h() - src_y;
1056         if(src_w <= 0) src_w = frame->get_w() - src_x;
1057         if(src_h <= 0) src_h = frame->get_h() - src_y;
1058         CLAMP(src_x, 0, frame->get_w() - 1);
1059         CLAMP(src_y, 0, frame->get_h() - 1);
1060         if(src_x + src_w > frame->get_w()) src_w = frame->get_w() - src_x;
1061         if(src_y + src_h > frame->get_h()) src_h = frame->get_h() - src_y;
1062
1063         if(!temp_bitmap) temp_bitmap = new BC_Bitmap(this,
1064                 dest_w,
1065                 dest_h,
1066                 get_color_model(),
1067                 0);
1068
1069         temp_bitmap->match_params(dest_w,
1070                 dest_h,
1071                 get_color_model(),
1072                 0);
1073
1074         temp_bitmap->read_frame(frame,
1075                 src_x,
1076                 src_y,
1077                 src_w,
1078                 src_h,
1079                 0,
1080                 0,
1081                 dest_w,
1082                 dest_h);
1083
1084         draw_bitmap(temp_bitmap,
1085                 0,
1086                 dest_x,
1087                 dest_y,
1088                 dest_w,
1089                 dest_h,
1090                 0,
1091                 0,
1092                 -1,
1093                 -1,
1094                 pixmap);
1095 }
1096
1097 void BC_WindowBase::draw_tooltip()
1098 {
1099         if(tooltip_popup && tooltip_text)
1100         {
1101                 int w = tooltip_popup->get_w(), h = tooltip_popup->get_h();
1102                 tooltip_popup->set_color(get_resources()->tooltip_bg_color);
1103                 tooltip_popup->draw_box(0, 0, w, h);
1104                 tooltip_popup->set_color(BLACK);
1105                 tooltip_popup->draw_rectangle(0, 0, w, h);
1106                 tooltip_popup->set_font(MEDIUMFONT);
1107                 tooltip_popup->draw_text(TOOLTIP_MARGIN,
1108                         get_text_ascent(MEDIUMFONT) + TOOLTIP_MARGIN,
1109                         tooltip_text);
1110         }
1111 }
1112
1113 void BC_WindowBase::slide_left(int distance)
1114 {
1115         if(distance < w)
1116         {
1117                 XCopyArea(top_level->display,
1118                         pixmap->opaque_pixmap,
1119                         pixmap->opaque_pixmap,
1120                         top_level->gc,
1121                         distance,
1122                         0,
1123                         w - distance,
1124                         h,
1125                         0,
1126                         0);
1127         }
1128 }
1129
1130 void BC_WindowBase::slide_right(int distance)
1131 {
1132         if(distance < w)
1133         {
1134                 XCopyArea(top_level->display,
1135                         pixmap->opaque_pixmap,
1136                         pixmap->opaque_pixmap,
1137                         top_level->gc,
1138                         0,
1139                         0,
1140                         w - distance,
1141                         h,
1142                         distance,
1143                         0);
1144         }
1145 }
1146
1147 void BC_WindowBase::slide_up(int distance)
1148 {
1149         if(distance < h)
1150         {
1151                 XCopyArea(top_level->display,
1152                         pixmap->opaque_pixmap,
1153                         pixmap->opaque_pixmap,
1154                         top_level->gc,
1155                         0,
1156                         distance,
1157                         w,
1158                         h - distance,
1159                         0,
1160                         0);
1161                 set_color(bg_color);
1162                 XFillRectangle(top_level->display,
1163                         pixmap->opaque_pixmap,
1164                         top_level->gc,
1165                         0,
1166                         h - distance,
1167                         w,
1168                         distance);
1169         }
1170 }
1171
1172 void BC_WindowBase::slide_down(int distance)
1173 {
1174         if(distance < h)
1175         {
1176                 XCopyArea(top_level->display,
1177                         pixmap->opaque_pixmap,
1178                         pixmap->opaque_pixmap,
1179                         top_level->gc,
1180                         0,
1181                         0,
1182                         w,
1183                         h - distance,
1184                         0,
1185                         distance);
1186                 set_color(bg_color);
1187                 XFillRectangle(top_level->display,
1188                         pixmap->opaque_pixmap,
1189                         top_level->gc,
1190                         0,
1191                         0,
1192                         w,
1193                         distance);
1194         }
1195 }
1196
1197 // 3 segments in separate pixmaps.  Obsolete.
1198 void BC_WindowBase::draw_3segment(int x,
1199         int y,
1200         int w,
1201         int h,
1202         BC_Pixmap *left_image,
1203         BC_Pixmap *mid_image,
1204         BC_Pixmap *right_image,
1205         BC_Pixmap *pixmap)
1206 {
1207         if(w <= 0 || h <= 0) return;
1208         int left_boundary = left_image->get_w_fixed();
1209         int right_boundary = w - right_image->get_w_fixed();
1210         for(int i = 0; i < w; )
1211         {
1212                 BC_Pixmap *image;
1213
1214                 if(i < left_boundary)
1215                         image = left_image;
1216                 else
1217                 if(i < right_boundary)
1218                         image = mid_image;
1219                 else
1220                         image = right_image;
1221
1222                 int output_w = image->get_w_fixed();
1223
1224                 if(i < left_boundary)
1225                 {
1226                         if(i + output_w > left_boundary) output_w = left_boundary - i;
1227                 }
1228                 else
1229                 if(i < right_boundary)
1230                 {
1231                         if(i + output_w > right_boundary) output_w = right_boundary - i;
1232                 }
1233                 else
1234                         if(i + output_w > w) output_w = w - i;
1235
1236                 image->write_drawable(pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1237                                 x + i,
1238                                 y,
1239                                 output_w,
1240                                 h,
1241                                 0,
1242                                 0);
1243
1244                 i += output_w;
1245         }
1246 }
1247 // 3 segments in separate vframes.  Obsolete.
1248 void BC_WindowBase::draw_3segment(int x,
1249         int y,
1250         int w,
1251         int h,
1252         VFrame *left_image,
1253         VFrame *mid_image,
1254         VFrame *right_image,
1255         BC_Pixmap *pixmap)
1256 {
1257         if(w <= 0 || h <= 0) return;
1258         int left_boundary = left_image->get_w_fixed();
1259         int right_boundary = w - right_image->get_w_fixed();
1260
1261
1262         for(int i = 0; i < w; )
1263         {
1264                 VFrame *image;
1265
1266                 if(i < left_boundary)
1267                         image = left_image;
1268                 else
1269                 if(i < right_boundary)
1270                         image = mid_image;
1271                 else
1272                         image = right_image;
1273
1274                 int output_w = image->get_w_fixed();
1275
1276                 if(i < left_boundary)
1277                 {
1278                         if(i + output_w > left_boundary) output_w = left_boundary - i;
1279                 }
1280                 else
1281                 if(i < right_boundary)
1282                 {
1283                         if(i + output_w > right_boundary) output_w = right_boundary - i;
1284                 }
1285                 else
1286                         if(i + output_w > w) output_w = w - i;
1287
1288                 if(image)
1289                         draw_vframe(image,
1290                                         x + i,
1291                                         y,
1292                                         output_w,
1293                                         h,
1294                                         0,
1295                                         0,
1296                                         0,
1297                                         0,
1298                                         pixmap);
1299
1300                 if(output_w == 0) break;
1301                 i += output_w;
1302         }
1303 }
1304
1305 // Draw all 3 segments in a single vframe for a changing level
1306
1307 // total_x
1308 // <------>
1309 // total_w
1310 //         <------------------------------------------------------------>
1311 // x
1312 // |
1313 // w
1314 // <-------------------------------------------------------------------->
1315 // output
1316 //         |-------------------|----------------------|------------------|
1317
1318
1319 void BC_WindowBase::draw_3segmenth(int x,
1320                 int y,
1321                 int w,
1322                 VFrame *image,
1323                 BC_Pixmap *pixmap)
1324 {
1325         draw_3segmenth(x,
1326                 y,
1327                 w,
1328                 x,
1329                 w,
1330                 image,
1331                 pixmap);
1332 }
1333
1334 void BC_WindowBase::draw_3segmenth(int x,
1335                 int y,
1336                 int w,
1337                 int total_x,
1338                 int total_w,
1339                 VFrame *image,
1340                 BC_Pixmap *pixmap)
1341 {
1342         if(total_w <= 0 || w <= 0 || h <= 0) return;
1343         int third_image = image->get_w() / 3;
1344         int half_image = image->get_w() / 2;
1345         //int left_boundary = third_image;
1346         //int right_boundary = total_w - third_image;
1347         int left_in_x = 0;
1348         int left_in_w = third_image;
1349         int left_out_x = total_x;
1350         int left_out_w = third_image;
1351         int right_in_x = image->get_w() - third_image;
1352         int right_in_w = third_image;
1353         int right_out_x = total_x + total_w - third_image;
1354         int right_out_w = third_image;
1355         int center_out_x = total_x + third_image;
1356         int center_out_w = total_w - third_image * 2;
1357         //int image_x, image_w;
1358
1359 //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",
1360 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1361
1362         if(left_out_x < x)
1363         {
1364                 left_in_w -= x - left_out_x;
1365                 left_out_w -= x - left_out_x;
1366                 left_in_x += x - left_out_x;
1367                 left_out_x += x - left_out_x;
1368         }
1369
1370         if(left_out_x + left_out_w > x + w)
1371         {
1372                 left_in_w -= (left_out_x + left_out_w) - (x + w);
1373                 left_out_w -= (left_out_x + left_out_w) - (x + w);
1374         }
1375
1376         if(right_out_x < x)
1377         {
1378                 right_in_w -= x - right_out_x;
1379                 right_out_w -= x - right_out_x;
1380                 right_in_x += x - right_out_x;
1381                 right_out_x += x - right_out_x;
1382         }
1383
1384         if(right_out_x + right_out_w > x + w)
1385         {
1386                 right_in_w -= (right_out_x + right_out_w) - (x + w);
1387                 right_out_w -= (right_out_x + right_out_w) - (x + w);
1388         }
1389
1390         if(center_out_x < x)
1391         {
1392                 center_out_w -= x - center_out_x;
1393                 center_out_x += x - center_out_x;
1394         }
1395
1396         if(center_out_x + center_out_w > x + w)
1397         {
1398                 center_out_w -= (center_out_x + center_out_w) - (x + w);
1399         }
1400
1401         if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1402                 image->get_w(),
1403                 image->get_h(),
1404                 get_color_model(),
1405                 0);
1406         temp_bitmap->match_params(image->get_w(),
1407                 image->get_h(),
1408                 get_color_model(),
1409                 0);
1410         temp_bitmap->read_frame(image,
1411                 0,
1412                 0,
1413                 image->get_w(),
1414                 image->get_h());
1415
1416
1417 //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",
1418 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1419         if(left_out_w > 0)
1420         {
1421                 draw_bitmap(temp_bitmap,
1422                         0,
1423                         left_out_x,
1424                         y,
1425                         left_out_w,
1426                         image->get_h(),
1427                         left_in_x,
1428                         0,
1429                         -1,   // src width and height are meaningless in video_off mode
1430                         -1,
1431                         pixmap);
1432         }
1433
1434         if(right_out_w > 0)
1435         {
1436                 draw_bitmap(temp_bitmap,
1437                         0,
1438                         right_out_x,
1439                         y,
1440                         right_out_w,
1441                         image->get_h(),
1442                         right_in_x,
1443                         0,
1444                         -1,   // src width and height are meaningless in video_off mode
1445                         -1,
1446                         pixmap);
1447         }
1448
1449         for(int pixel = center_out_x;
1450                 pixel < center_out_x + center_out_w;
1451                 pixel += half_image)
1452         {
1453                 int fragment_w = half_image;
1454                 if(fragment_w + pixel > center_out_x + center_out_w)
1455                         fragment_w = (center_out_x + center_out_w) - pixel;
1456
1457 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1458                 draw_bitmap(temp_bitmap,
1459                         0,
1460                         pixel,
1461                         y,
1462                         fragment_w,
1463                         image->get_h(),
1464                         third_image,
1465                         0,
1466                         -1,   // src width and height are meaningless in video_off mode
1467                         -1,
1468                         pixmap);
1469         }
1470
1471 }
1472
1473
1474
1475
1476
1477
1478
1479 void BC_WindowBase::draw_3segmenth(int x,
1480                 int y,
1481                 int w,
1482                 int total_x,
1483                 int total_w,
1484                 BC_Pixmap *src,
1485                 BC_Pixmap *dst)
1486 {
1487         if(w <= 0 || total_w <= 0) return;
1488         if(!src) printf("BC_WindowBase::draw_3segmenth src=0\n");
1489         int quarter_src = src->get_w() / 4;
1490         int half_src = src->get_w() / 2;
1491         //int left_boundary = quarter_src;
1492         //int right_boundary = total_w - quarter_src;
1493         int left_in_x = 0;
1494         int left_in_w = quarter_src;
1495         int left_out_x = total_x;
1496         int left_out_w = quarter_src;
1497         int right_in_x = src->get_w() - quarter_src;
1498         int right_in_w = quarter_src;
1499         int right_out_x = total_x + total_w - quarter_src;
1500         int right_out_w = quarter_src;
1501         int center_out_x = total_x + quarter_src;
1502         int center_out_w = total_w - quarter_src * 2;
1503         //int src_x, src_w;
1504
1505 //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",
1506 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1507
1508         if(left_out_x < x)
1509         {
1510                 left_in_w -= x - left_out_x;
1511                 left_out_w -= x - left_out_x;
1512                 left_in_x += x - left_out_x;
1513                 left_out_x += x - left_out_x;
1514         }
1515
1516         if(left_out_x + left_out_w > x + w)
1517         {
1518                 left_in_w -= (left_out_x + left_out_w) - (x + w);
1519                 left_out_w -= (left_out_x + left_out_w) - (x + w);
1520         }
1521
1522         if(right_out_x < x)
1523         {
1524                 right_in_w -= x - right_out_x;
1525                 right_out_w -= x - right_out_x;
1526                 right_in_x += x - right_out_x;
1527                 right_out_x += x - right_out_x;
1528         }
1529
1530         if(right_out_x + right_out_w > x + w)
1531         {
1532                 right_in_w -= (right_out_x + right_out_w) - (x + w);
1533                 right_out_w -= (right_out_x + right_out_w) - (x + w);
1534         }
1535
1536         if(center_out_x < x)
1537         {
1538                 center_out_w -= x - center_out_x;
1539                 center_out_x += x - center_out_x;
1540         }
1541
1542         if(center_out_x + center_out_w > x + w)
1543         {
1544                 center_out_w -= (center_out_x + center_out_w) - (x + w);
1545         }
1546
1547
1548 //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",
1549 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1550         if(left_out_w > 0)
1551         {
1552                 draw_pixmap(src,
1553                         left_out_x,
1554                         y,
1555                         left_out_w,
1556                         src->get_h(),
1557                         left_in_x,
1558                         0,
1559                         dst);
1560         }
1561
1562         if(right_out_w > 0)
1563         {
1564                 draw_pixmap(src,
1565                         right_out_x,
1566                         y,
1567                         right_out_w,
1568                         src->get_h(),
1569                         right_in_x,
1570                         0,
1571                         dst);
1572         }
1573
1574         for(int pixel = center_out_x;
1575                 pixel < center_out_x + center_out_w;
1576                 pixel += half_src)
1577         {
1578                 int fragment_w = half_src;
1579                 if(fragment_w + pixel > center_out_x + center_out_w)
1580                         fragment_w = (center_out_x + center_out_w) - pixel;
1581
1582 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1583                 draw_pixmap(src,
1584                         pixel,
1585                         y,
1586                         fragment_w,
1587                         src->get_h(),
1588                         quarter_src,
1589                         0,
1590                         dst);
1591         }
1592
1593 }
1594
1595
1596 void BC_WindowBase::draw_3segmenth(int x,
1597                 int y,
1598                 int w,
1599                 BC_Pixmap *src,
1600                 BC_Pixmap *dst)
1601 {
1602         if(w <= 0) return;
1603         int third_image = src->get_w() / 3;
1604         int half_output = w / 2;
1605         //int left_boundary = third_image;
1606         //int right_boundary = w - third_image;
1607         int left_in_x = 0;
1608         int left_in_w = third_image;
1609         int left_out_x = x;
1610         int left_out_w = third_image;
1611         int right_in_x = src->get_w() - third_image;
1612         int right_in_w = third_image;
1613         int right_out_x = x + w - third_image;
1614         int right_out_w = third_image;
1615         //int image_x, image_w;
1616
1617 //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",
1618 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1619
1620         if(left_out_w > half_output)
1621         {
1622                 left_in_w -= left_out_w - half_output;
1623                 left_out_w -= left_out_w - half_output;
1624         }
1625
1626         if(right_out_x < x + half_output)
1627         {
1628                 right_in_w -= x + half_output - right_out_x;
1629                 right_out_w -= x + half_output - right_out_x;
1630                 right_in_x += x + half_output - right_out_x;
1631                 right_out_x += x + half_output - right_out_x;
1632         }
1633
1634 //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",
1635 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1636         if(left_out_w > 0)
1637         {
1638                 draw_pixmap(src,
1639                         left_out_x,
1640                         y,
1641                         left_out_w,
1642                         src->get_h(),
1643                         left_in_x,
1644                         0,
1645                         dst);
1646         }
1647
1648         if(right_out_w > 0)
1649         {
1650                 draw_pixmap(src,
1651                         right_out_x,
1652                         y,
1653                         right_out_w,
1654                         src->get_h(),
1655                         right_in_x,
1656                         0,
1657                         dst);
1658         }
1659
1660         for(int pixel = left_out_x + left_out_w;
1661                 pixel < right_out_x;
1662                 pixel += third_image)
1663         {
1664                 int fragment_w = third_image;
1665                 if(fragment_w + pixel > right_out_x)
1666                         fragment_w = right_out_x - pixel;
1667
1668 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1669                 draw_pixmap(src,
1670                         pixel,
1671                         y,
1672                         fragment_w,
1673                         src->get_h(),
1674                         third_image,
1675                         0,
1676                         dst);
1677         }
1678
1679 }
1680
1681
1682
1683
1684
1685
1686
1687 void BC_WindowBase::draw_3segmentv(int x,
1688                 int y,
1689                 int h,
1690                 VFrame *src,
1691                 BC_Pixmap *dst)
1692 {
1693         if(h <= 0) return;
1694         int third_image = src->get_h() / 3;
1695         int half_output = h / 2;
1696         //int left_boundary = third_image;
1697         //int right_boundary = h - third_image;
1698         int left_in_y = 0;
1699         int left_in_h = third_image;
1700         int left_out_y = y;
1701         int left_out_h = third_image;
1702         int right_in_y = src->get_h() - third_image;
1703         int right_in_h = third_image;
1704         int right_out_y = y + h - third_image;
1705         int right_out_h = third_image;
1706         //int image_y, image_h;
1707
1708
1709         if(left_out_h > half_output)
1710         {
1711                 left_in_h -= left_out_h - half_output;
1712                 left_out_h -= left_out_h - half_output;
1713         }
1714
1715         if(right_out_y < y + half_output)
1716         {
1717                 right_in_h -= y + half_output - right_out_y;
1718                 right_out_h -= y + half_output - right_out_y;
1719                 right_in_y += y + half_output - right_out_y;
1720                 right_out_y += y + half_output - right_out_y;
1721         }
1722
1723
1724         if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1725                 src->get_w(),
1726                 src->get_h(),
1727                 get_color_model(),
1728                 0);
1729         temp_bitmap->match_params(src->get_w(),
1730                 src->get_h(),
1731                 get_color_model(),
1732                 0);
1733         temp_bitmap->read_frame(src,
1734                 0,
1735                 0,
1736                 src->get_w(),
1737                 src->get_h());
1738
1739
1740         if(left_out_h > 0)
1741         {
1742                 draw_bitmap(temp_bitmap,
1743                         0,
1744                         x,
1745                         left_out_y,
1746                         src->get_w(),
1747                         left_out_h,
1748                         0,
1749                         left_in_y,
1750                         -1,
1751                         -1,
1752                         dst);
1753         }
1754
1755         if(right_out_h > 0)
1756         {
1757                 draw_bitmap(temp_bitmap,
1758                         0,
1759                         x,
1760                         right_out_y,
1761                         src->get_w(),
1762                         right_out_h,
1763                         0,
1764                         right_in_y,
1765                         -1,
1766                         -1,
1767                         dst);
1768         }
1769
1770         for(int pixel = left_out_y + left_out_h;
1771                 pixel < right_out_y;
1772                 pixel += third_image)
1773         {
1774                 int fragment_h = third_image;
1775                 if(fragment_h + pixel > right_out_y)
1776                         fragment_h = right_out_y - pixel;
1777
1778 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1779                 draw_bitmap(temp_bitmap,
1780                         0,
1781                         x,
1782                         pixel,
1783                         src->get_w(),
1784                         fragment_h,
1785                         0,
1786                         third_image,
1787                         -1,
1788                         -1,
1789                         dst);
1790         }
1791 }
1792
1793 void BC_WindowBase::draw_3segmentv(int x,
1794                 int y,
1795                 int h,
1796                 BC_Pixmap *src,
1797                 BC_Pixmap *dst)
1798 {
1799         if(h <= 0) return;
1800         int third_image = src->get_h() / 3;
1801         int half_output = h / 2;
1802         //int left_boundary = third_image;
1803         //int right_boundary = h - third_image;
1804         int left_in_y = 0;
1805         int left_in_h = third_image;
1806         int left_out_y = y;
1807         int left_out_h = third_image;
1808         int right_in_y = src->get_h() - third_image;
1809         int right_in_h = third_image;
1810         int right_out_y = y + h - third_image;
1811         int right_out_h = third_image;
1812         //int image_y, image_h;
1813
1814
1815         if(left_out_h > half_output)
1816         {
1817                 left_in_h -= left_out_h - half_output;
1818                 left_out_h -= left_out_h - half_output;
1819         }
1820
1821         if(right_out_y < y + half_output)
1822         {
1823                 right_in_h -= y + half_output - right_out_y;
1824                 right_out_h -= y + half_output - right_out_y;
1825                 right_in_y += y + half_output - right_out_y;
1826                 right_out_y += y + half_output - right_out_y;
1827         }
1828
1829         if(left_out_h > 0)
1830         {
1831                 draw_pixmap(src,
1832                         x,
1833                         left_out_y,
1834                         src->get_w(),
1835                         left_out_h,
1836                         0,
1837                         left_in_y,
1838                         dst);
1839         }
1840
1841         if(right_out_h > 0)
1842         {
1843                 draw_pixmap(src,
1844                         x,
1845                         right_out_y,
1846                         src->get_w(),
1847                         right_out_h,
1848                         0,
1849                         right_in_y,
1850                         dst);
1851         }
1852
1853         for(int pixel = left_out_y + left_out_h;
1854                 pixel < right_out_y;
1855                 pixel += third_image)
1856         {
1857                 int fragment_h = third_image;
1858                 if(fragment_h + pixel > right_out_y)
1859                         fragment_h = right_out_y - pixel;
1860
1861 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1862                 draw_pixmap(src,
1863                         x,
1864                         pixel,
1865                         src->get_w(),
1866                         fragment_h,
1867                         0,
1868                         third_image,
1869                         dst);
1870         }
1871 }
1872
1873
1874 void BC_WindowBase::draw_9segment(int x,
1875                 int y,
1876                 int w,
1877                 int h,
1878                 BC_Pixmap *src,
1879                 BC_Pixmap *dst)
1880 {
1881         if(w <= 0 || h <= 0) return;
1882
1883         int in_x_third = src->get_w() / 3;
1884         int in_y_third = src->get_h() / 3;
1885         int out_x_half = w / 2;
1886         int out_y_half = h / 2;
1887
1888         int in_x1 = 0;
1889         int in_y1 = 0;
1890         int out_x1 = 0;
1891         int out_y1 = 0;
1892         int in_x2 = MIN(in_x_third, out_x_half);
1893         int in_y2 = MIN(in_y_third, out_y_half);
1894         int out_x2 = in_x2;
1895         int out_y2 = in_y2;
1896
1897         int out_x3 = MAX(w - out_x_half, w - in_x_third);
1898         int out_x4 = w;
1899         int in_x3 = src->get_w() - (out_x4 - out_x3);
1900         //int in_x4 = src->get_w();
1901
1902         int out_y3 = MAX(h - out_y_half, h - in_y_third);
1903         int out_y4 = h;
1904         int in_y3 = src->get_h() - (out_y4 - out_y3);
1905         //int in_y4 = src->get_h();
1906
1907 // Segment 1
1908         draw_pixmap(src,
1909                 x + out_x1,
1910                 y + out_y1,
1911                 out_x2 - out_x1,
1912                 out_y2 - out_y1,
1913                 in_x1,
1914                 in_y1,
1915                 dst);
1916
1917
1918 // Segment 2 * n
1919         for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
1920         {
1921                 if(out_x3 - i > 0)
1922                 {
1923                         int w = MIN(in_x3 - in_x2, out_x3 - i);
1924                         draw_pixmap(src,
1925                                 x + i,
1926                                 y + out_y1,
1927                                 w,
1928                                 out_y2 - out_y1,
1929                                 in_x2,
1930                                 in_y1,
1931                                 dst);
1932                 }
1933         }
1934
1935
1936
1937
1938
1939 // Segment 3
1940         draw_pixmap(src,
1941                 x + out_x3,
1942                 y + out_y1,
1943                 out_x4 - out_x3,
1944                 out_y2 - out_y1,
1945                 in_x3,
1946                 in_y1,
1947                 dst);
1948
1949
1950
1951 // Segment 4 * n
1952         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
1953         {
1954                 if(out_y3 - i > 0)
1955                 {
1956                         int h = MIN(in_y3 - in_y2, out_y3 - i);
1957                         draw_pixmap(src,
1958                                 x + out_x1,
1959                                 y + i,
1960                                 out_x2 - out_x1,
1961                                 h,
1962                                 in_x1,
1963                                 in_y2,
1964                                 dst);
1965                 }
1966         }
1967
1968
1969 // Segment 5 * n * n
1970         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2 /* in_y_third */)
1971         {
1972                 if(out_y3 - i > 0)
1973                 {
1974                         int h = MIN(in_y3 - in_y2 /* in_y_third */, out_y3 - i);
1975
1976
1977                         for(int j = out_x2; j < out_x3; j += in_x3 - in_x2 /* in_x_third */)
1978                         {
1979                                 int w = MIN(in_x3 - in_x2 /* in_x_third */, out_x3 - j);
1980                                 if(out_x3 - j > 0)
1981                                         draw_pixmap(src,
1982                                                 x + j,
1983                                                 y + i,
1984                                                 w,
1985                                                 h,
1986                                                 in_x2,
1987                                                 in_y2,
1988                                                 dst);
1989                         }
1990                 }
1991         }
1992
1993 // Segment 6 * n
1994         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
1995         {
1996                 if(out_y3 - i > 0)
1997                 {
1998                         int h = MIN(in_y3 - in_y2, out_y3 - i);
1999                         draw_pixmap(src,
2000                                 x + out_x3,
2001                                 y + i,
2002                                 out_x4 - out_x3,
2003                                 h,
2004                                 in_x3,
2005                                 in_y2,
2006                                 dst);
2007                 }
2008         }
2009
2010
2011
2012
2013 // Segment 7
2014         draw_pixmap(src,
2015                 x + out_x1,
2016                 y + out_y3,
2017                 out_x2 - out_x1,
2018                 out_y4 - out_y3,
2019                 in_x1,
2020                 in_y3,
2021                 dst);
2022
2023
2024 // Segment 8 * n
2025         for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
2026         {
2027                 if(out_x3 - i > 0)
2028                 {
2029                         int w = MIN(in_x3 - in_y2, out_x3 - i);
2030                         draw_pixmap(src,
2031                                 x + i,
2032                                 y + out_y3,
2033                                 w,
2034                                 out_y4 - out_y3,
2035                                 in_x2,
2036                                 in_y3,
2037                                 dst);
2038                 }
2039         }
2040
2041
2042
2043 // Segment 9
2044         draw_pixmap(src,
2045                 x + out_x3,
2046                 y + out_y3,
2047                 out_x4 - out_x3,
2048                 out_y4 - out_y3,
2049                 in_x3,
2050                 in_y3,
2051                 dst);
2052 }
2053
2054
2055 void BC_WindowBase::draw_9segment(int x,
2056                 int y,
2057                 int w,
2058                 int h,
2059                 VFrame *src,
2060                 BC_Pixmap *dst)
2061 {
2062         if(w <= 0 || h <= 0) return;
2063
2064         int in_x_third = src->get_w() / 3;
2065         int in_y_third = src->get_h() / 3;
2066         int out_x_half = w / 2;
2067         int out_y_half = h / 2;
2068
2069         int in_x1 = 0;
2070         int in_y1 = 0;
2071         int out_x1 = 0;
2072         int out_y1 = 0;
2073         int in_x2 = MIN(in_x_third, out_x_half);
2074         int in_y2 = MIN(in_y_third, out_y_half);
2075         int out_x2 = in_x2;
2076         int out_y2 = in_y2;
2077
2078         int out_x3 = MAX(w - out_x_half, w - in_x_third);
2079         int out_x4 = w;
2080         int in_x3 = src->get_w() - (out_x4 - out_x3);
2081         int in_x4 = src->get_w();
2082
2083         int out_y3 = MAX(h - out_y_half, h - in_y_third);
2084         int out_y4 = h;
2085         int in_y3 = src->get_h() - (out_y4 - out_y3);
2086         int in_y4 = src->get_h();
2087
2088 //printf("PFCFrame::draw_9segment 1 %d %d %d %d\n", out_x1, out_x2, out_x3, out_x4);
2089 //printf("PFCFrame::draw_9segment 2 %d %d %d %d\n", in_x1, in_x2, in_x3, in_x4);
2090 //printf("PFCFrame::draw_9segment 2 %d %d %d %d\n", in_y1, in_y2, in_y3, in_y4);
2091
2092         if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
2093                 src->get_w(),
2094                 src->get_h(),
2095                 get_color_model(),
2096                 0);
2097         temp_bitmap->match_params(src->get_w(),
2098                 src->get_h(),
2099                 get_color_model(),
2100                 0);
2101         temp_bitmap->read_frame(src,
2102                 0,
2103                 0,
2104                 src->get_w(),
2105                 src->get_h());
2106
2107 // Segment 1
2108         draw_bitmap(temp_bitmap,
2109                 0,
2110                 x + out_x1,
2111                 y + out_y1,
2112                 out_x2 - out_x1,
2113                 out_y2 - out_y1,
2114                 in_x1,
2115                 in_y1,
2116                 in_x2 - in_x1,
2117                 in_y2 - in_y1,
2118                 dst);
2119
2120
2121 // Segment 2 * n
2122         for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
2123         {
2124                 if(out_x3 - i > 0)
2125                 {
2126                         int w = MIN(in_x3 - in_x2, out_x3 - i);
2127                         draw_bitmap(temp_bitmap,
2128                                 0,
2129                                 x + i,
2130                                 y + out_y1,
2131                                 w,
2132                                 out_y2 - out_y1,
2133                                 in_x2,
2134                                 in_y1,
2135                                 w,
2136                                 in_y2 - in_y1,
2137                                 dst);
2138                 }
2139         }
2140
2141
2142
2143
2144
2145 // Segment 3
2146         draw_bitmap(temp_bitmap,
2147                 0,
2148                 x + out_x3,
2149                 y + out_y1,
2150                 out_x4 - out_x3,
2151                 out_y2 - out_y1,
2152                 in_x3,
2153                 in_y1,
2154                 in_x4 - in_x3,
2155                 in_y2 - in_y1,
2156                 dst);
2157
2158
2159
2160 // Segment 4 * n
2161         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
2162         {
2163                 if(out_y3 - i > 0)
2164                 {
2165                         int h = MIN(in_y3 - in_y2, out_y3 - i);
2166                         draw_bitmap(temp_bitmap,
2167                                 0,
2168                                 x + out_x1,
2169                                 y + i,
2170                                 out_x2 - out_x1,
2171                                 h,
2172                                 in_x1,
2173                                 in_y2,
2174                                 in_x2 - in_x1,
2175                                 h,
2176                                 dst);
2177                 }
2178         }
2179
2180
2181 // Segment 5 * n * n
2182         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
2183         {
2184                 if(out_y3 - i > 0)
2185                 {
2186                         int h = MIN(in_y3 - in_y2, out_y3 - i);
2187
2188
2189                         for(int j = out_x2; j < out_x3; j += in_x3 - in_x2)
2190                         {
2191                                 int w = MIN(in_x3 - in_x2, out_x3 - j);
2192                                 if(out_x3 - j > 0)
2193                                         draw_bitmap(temp_bitmap,
2194                                                 0,
2195                                                 x + j,
2196                                                 y + i,
2197                                                 w,
2198                                                 h,
2199                                                 in_x2,
2200                                                 in_y2,
2201                                                 w,
2202                                                 h,
2203                                                 dst);
2204                         }
2205                 }
2206         }
2207
2208 // Segment 6 * n
2209         for(int i = out_y2; i < out_y3; i += in_y_third)
2210         {
2211                 if(out_y3 - i > 0)
2212                 {
2213                         int h = MIN(in_y_third, out_y3 - i);
2214                         draw_bitmap(temp_bitmap,
2215                                 0,
2216                                 x + out_x3,
2217                                 y + i,
2218                                 out_x4 - out_x3,
2219                                 h,
2220                                 in_x3,
2221                                 in_y2,
2222                                 in_x4 - in_x3,
2223                                 h,
2224                                 dst);
2225                 }
2226         }
2227
2228
2229
2230
2231 // Segment 7
2232         draw_bitmap(temp_bitmap,
2233                 0,
2234                 x + out_x1,
2235                 y + out_y3,
2236                 out_x2 - out_x1,
2237                 out_y4 - out_y3,
2238                 in_x1,
2239                 in_y3,
2240                 in_x2 - in_x1,
2241                 in_y4 - in_y3,
2242                 dst);
2243
2244
2245 // Segment 8 * n
2246         for(int i = out_x2; i < out_x3; i += in_x_third)
2247         {
2248                 if(out_x3 - i > 0)
2249                 {
2250                         int w = MIN(in_x_third, out_x3 - i);
2251                         draw_bitmap(temp_bitmap,
2252                                 0,
2253                                 x + i,
2254                                 y + out_y3,
2255                                 w,
2256                                 out_y4 - out_y3,
2257                                 in_x2,
2258                                 in_y3,
2259                                 w,
2260                                 in_y4 - in_y3,
2261                                 dst);
2262                 }
2263         }
2264
2265
2266
2267 // Segment 9
2268         draw_bitmap(temp_bitmap,
2269                 0,
2270                 x + out_x3,
2271                 y + out_y3,
2272                 out_x4 - out_x3,
2273                 out_y4 - out_y3,
2274                 in_x3,
2275                 in_y3,
2276                 in_x4 - in_x3,
2277                 in_y4 - in_y3,
2278                 dst);
2279 }
2280
2281
2282
2283
2284
2285
2286
2287
2288