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