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