7164bab70a1cb5f53dcbd438aace39c575c9d09b
[goodguy/cinelerra.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 "bccolors.h"
32 #include "bctrace.h"
33 #include "cursors.h"
34 #include "fonts.h"
35 #include "vframe.h"
36 #include <string.h>
37 #include <wchar.h>
38 #include <ft2build.h>
39 #include "workarounds.h"
40
41 void BC_WindowBase::copy_area(int x1, int y1, int x2, int y2, int w, int h, BC_Pixmap *pixmap)
42 { BT
43         XCopyArea(top_level->display,
44                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
45                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
46                 top_level->gc, x1, y1, w, h, x2, y2);
47 }
48
49
50 void BC_WindowBase::draw_box(int x, int y, int w, int h, BC_Pixmap *pixmap)
51 { BT
52 //if(x == 0) printf("BC_WindowBase::draw_box %d %d %d %d\n", x, y, w, h);
53         XFillRectangle(top_level->display,
54                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
55                 top_level->gc, x, y, w, h);
56 }
57
58
59 void BC_WindowBase::draw_circle(int x, int y, int w, int h, BC_Pixmap *pixmap)
60 { BT
61         XDrawArc(top_level->display,
62                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
63                 top_level->gc, x, y, (w - 1), (h - 2), 0 * 64, 360 * 64);
64 }
65
66 void BC_WindowBase::draw_arc(int x, int y, int w, int h,
67         int start_angle, int angle_length, BC_Pixmap *pixmap)
68 { BT
69         XDrawArc(top_level->display,
70                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
71                 top_level->gc, x, y, (w - 1), (h - 2), start_angle * 64,
72                 angle_length * 64);
73 }
74
75 void BC_WindowBase::draw_disc(int x, int y, int w, int h, BC_Pixmap *pixmap)
76 { BT
77         XFillArc(top_level->display,
78                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
79                 top_level->gc, x, y, (w - 1), (h - 2), 0 * 64, 360 * 64);
80 }
81
82 void BC_WindowBase::clear_box(int x, int y, int w, int h, BC_Pixmap *pixmap)
83 { BT
84         set_color(bg_color);
85         Pixmap xpixmap = pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap;
86         XFillRectangle(top_level->display, xpixmap, top_level->gc, x, y, w, h);
87 }
88
89 void BC_WindowBase::draw_text_line(int x, int y, const char *text, int len,
90         BC_Pixmap *pixmap)
91 {
92 #ifdef HAVE_XFT
93         if( get_resources()->use_xft ) {
94                 draw_xft_text(x, y, text, len, pixmap);
95                 return;
96         }
97 #endif
98  BT
99         Pixmap xpixmap = pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap;
100         if( get_resources()->use_fontset ) {
101                 XFontSet fontset = top_level->get_curr_fontset();
102                 if( fontset ) {
103                         XmbDrawString(top_level->display, xpixmap, fontset,
104                                 top_level->gc, x, y, text, len);
105                         return;
106                 }
107
108         }
109 //printf("BC_WindowBase::draw_text 3\n");
110         XDrawString(top_level->display, xpixmap, top_level->gc, x, y, text, len);
111 }
112
113 void BC_WindowBase::draw_text(int x, int y, const char *text, int length,
114         BC_Pixmap *pixmap)
115 {
116         if( length < 0 ) length = strlen(text);
117         //int boldface = top_level->current_font & BOLDFACE;
118         int font = top_level->current_font & 0xff;
119
120         switch(top_level->current_font) {
121         case MEDIUM_7SEGMENT:
122                 for(int i = 0; i < length; i++) {
123                         VFrame *image, **img7seg = get_resources()->medium_7segment;
124                         int ch = text[i];
125                         switch( ch ) {
126                         case '0': case '1': case '2': case '3': case '4':
127                         case '5': case '6': case '7': case '8': case '9':
128                                   image = img7seg[ch-'0'];  break;
129                         case ':': image = img7seg[10];      break;
130                         case '.': image = img7seg[11];      break;
131                         case 'a': case 'b': case 'c':
132                         case 'd': case 'e': case 'f':  ch -= 'a'-'A';
133                         case 'A': case 'B': case 'C':  /* fallthru */
134                         case 'D': case 'E': case 'F':
135                                 image = img7seg[12+ch-'A']; break;
136                                 break;
137                         case '-': image = img7seg[19];      break;
138                         default:
139                         case ' ': image = img7seg[18];      break;
140                         }
141
142                         draw_vframe(image, x, y - image->get_h());
143                         x += image->get_w();
144                 }
145                 break;
146
147         default: {
148                 if(top_level->get_xft_struct(top_level->current_font)) {
149                         draw_xft_text(x, y, text, length, pixmap);
150                         return;
151                 }
152  BT
153                 for(int i = 0, j = 0; i <= length; i++) {
154                         if(text[i] == '\n' || text[i] == 0) {
155                                 if(get_resources()->use_fontset && top_level->get_curr_fontset()) {
156                                         XmbDrawString(top_level->display,
157                                                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
158                                                 top_level->get_curr_fontset(),
159                                                 top_level->gc, x, y, &text[j], i-j);
160                                 }
161                                 else {
162                                         XDrawString(top_level->display,
163                                                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
164                                                 top_level->gc, x, y, &text[j], i-j);
165                                 }
166                                 j = i + 1;
167                                 y += get_text_height(font);
168                         }
169                 }
170                 break; }
171         }
172 }
173
174 void BC_WindowBase::draw_utf8_text(int x, int y,
175         const char *text, int length, BC_Pixmap *pixmap)
176 {
177         if(length < 0) length = strlen(text);
178
179         if(top_level->get_xft_struct(top_level->current_font))
180         {
181                 draw_xft_text(x, y, text, length, pixmap, 1);
182                 return;
183         }
184  BT
185         for(int i = 0, j = 0; i <= length; i++)
186         {
187                 if(text[i] == '\n' || text[i] == 0)
188                 {
189                         if(get_resources()->use_fontset && top_level->get_curr_fontset())
190                         {
191                                 XmbDrawString(top_level->display,
192                                         pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
193                                         top_level->get_curr_fontset(), top_level->gc,
194                                         x, y, &text[j], i - j);
195                         }
196                         else
197                         {
198                                 XDrawString(top_level->display,
199                                         pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
200                                         top_level->gc,
201                                         x, y, &text[j], i - j);
202                         }
203
204                         j = i + 1;
205                         y += get_text_height(MEDIUMFONT);
206                 }
207         }
208 }
209
210 void BC_WindowBase::draw_xft_text(int x, int y,
211         const char *text, int length, BC_Pixmap *pixmap, int is_utf8)
212 {
213         int l = length + 1;
214         wchar_t wide_text[l];
215         length = BC_Resources::encode(
216                 is_utf8 ? "UTF8" : BC_Resources::encoding, BC_Resources::wide_encoding,
217                 (char*)text, length, (char*)wide_text, l*sizeof(wchar_t)) / sizeof(wchar_t);
218         draw_xft_text(x, y, wide_text, length, pixmap);
219 }
220
221 void BC_WindowBase::draw_xft_text(int x, int y,
222         const wchar_t *text, int length, BC_Pixmap *pixmap)
223 {
224         int dy = -1;
225         const wchar_t *wsp = text, *wep = wsp + length;
226         int font = top_level->current_font;
227         while( wsp < wep ) {
228                 const wchar_t *wcp = wsp;
229                 while( wcp < wep && *wcp != '\n' ) ++wcp;
230                 int len = wcp - wsp;
231                 if( len > 0 )
232                         draw_single_text(1, font, x, y, wsp, len, pixmap);
233                 if( wcp >= wep ) break;
234                 if( dy < 0 )
235                         dy = get_text_height(font);
236                 y += dy;
237                 wsp = wcp + 1;
238         }
239 }
240
241 void BC_WindowBase::xft_draw_string(XftColor *xft_color, XftFont *xft_font,
242                 int x, int y, const FcChar32 *fc, int len, BC_Pixmap *pixmap)
243 { BT
244         Pixmap draw_pixmap = 0;
245         XftDraw *xft_draw = (XftDraw *)
246                 (pixmap ? pixmap->opaque_xft_draw : this->pixmap->opaque_xft_draw);
247         int src_x = x, src_y = y, src_w = 0, src_h = 0;
248         XGCValues values;
249         XGetGCValues(top_level->display, top_level->gc, GCFunction, &values);
250         if( values.function != GXcopy ) {
251                 XSetFunction(top_level->display, top_level->gc, GXcopy);
252                 XGlyphInfo info;
253                 xftTextExtents32(top_level->display, xft_font, fc, len, &info);
254                 src_w = info.width;  src_h = info.height;
255                 draw_pixmap = XCreatePixmap(top_level->display, top_level->win,
256                         src_w, src_h, top_level->default_depth);
257                 int color = get_color(); set_color(0);
258                 XFillRectangle(top_level->display, draw_pixmap, top_level->gc, 0, 0, src_w, src_h);
259                 set_color(color);
260                 xft_draw = xftDrawCreate(top_level->display, draw_pixmap,
261                            top_level->vis, top_level->cmap);
262                 src_x = info.x;  src_y = info.y;
263         }
264         xftDrawString32(xft_draw, xft_color, xft_font, src_x, src_y, fc, len);
265         if( values.function != GXcopy ) {
266                 XSetFunction(top_level->display, top_level->gc, values.function);
267                 Pixmap xpixmap = pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap;
268                 XCopyArea(top_level->display, draw_pixmap, xpixmap,
269                         top_level->gc, 0, 0, src_w, src_h, x, y);
270                 XFreePixmap(top_level->display, draw_pixmap);
271                 xftDrawDestroy(xft_draw);
272         }
273 }
274
275 int BC_WindowBase::get_single_text_width(int font, const wchar_t *text, int length)
276 {
277         return draw_single_text(0, font, 0,0, text, length);
278 }
279
280 int BC_WindowBase::draw_single_text(int draw, int font,
281         int x, int y, const wchar_t *text, int length, BC_Pixmap *pixmap)
282 {
283         if( length < 0 )
284                 length = wcslen(text);
285         if( !length ) return 0;
286
287         if( !get_resources()->use_xft ) {
288  BT
289                 if( !get_font_struct(font) ) return 0;
290                 XChar2b xtext[length], *xp = xtext;
291                 for( int i=0; i<length; ++i,++xp ) {
292                         xp->byte1 = (unsigned char) (text[i] >> 8);
293                         xp->byte2 = (unsigned char) (text[i] & 0xff);
294                 }
295                 if( draw ) {
296                         XDrawString16(top_level->display,
297                                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
298                                 top_level->gc, x, y, xtext, length);
299                 }
300                 return XTextWidth16(get_font_struct(font), xtext, length);
301         }
302
303 #ifdef HAVE_XFT
304         XftColor xft_color;
305         if( draw ) {
306                 XRenderColor color;
307                 color.red = (top_level->current_color & 0xff0000) >> 16;
308                 color.red |= color.red << 8;
309                 color.green = (top_level->current_color & 0xff00) >> 8;
310                 color.green |= color.green << 8;
311                 color.blue = (top_level->current_color & 0xff);
312                 color.blue |= color.blue << 8;
313                 color.alpha = 0xffff;
314
315                 xftColorAllocValue(top_level->display, top_level->vis, top_level->cmap,
316                         &color, &xft_color);
317         }
318
319         int x0 = x;
320         XftFont *basefont = top_level->get_xft_struct(font);
321         XftFont *curfont = 0, *altfont = 0;
322         const wchar_t *up = text, *ubp = up, *uep = ubp + length;
323
324         while( up < uep ) {
325                 XftFont *xft_font = 0;
326                 if( xftCharExists(top_level->display, basefont, *up) )
327                         xft_font = basefont;
328                 else if( altfont ) {
329                         if( xftCharExists(top_level->display, altfont, *up))
330                                 xft_font = altfont;
331                         else {
332                                 xftFontClose(top_level->display, altfont);
333                                 altfont = 0;
334                         }
335                 }
336                 if( !xft_font ) {
337                         FcPattern *pattern = BC_Resources::find_similar_font(*up, basefont->pattern);
338                         if( pattern != 0 ) {
339                                 double psize = 0;
340                                 fcPatternGetDouble(basefont->pattern, FC_PIXEL_SIZE, 0, &psize);
341                                 fcPatternAddDouble(pattern, FC_PIXEL_SIZE, psize);
342                                 fcPatternDel(pattern, FC_SCALABLE);
343                                 xft_font = altfont = xftFontOpenPattern(top_level->display, pattern);
344                         }
345                 }
346                 if( !xft_font )
347                         xft_font = basefont;
348                 if( xft_font != curfont ) {
349                         if( curfont && up > ubp ) {
350                                 if( draw ) {
351                                         xft_draw_string(&xft_color, curfont, x, y,
352                                                 (const FcChar32*)ubp, up-ubp, pixmap);
353                                 }
354                                 XGlyphInfo extents;
355                                 xftTextExtents32(top_level->display, curfont,
356                                         (const FcChar32*)ubp, up-ubp, &extents);
357                                 x += extents.xOff;
358                         }
359                         ubp = up;  curfont = xft_font;
360                 }
361                 ++up;
362         }
363
364         if( curfont && up > ubp ) {
365                 if( draw ) {
366                         xft_draw_string(&xft_color, curfont, x, y,
367                                 (const FcChar32*)ubp, up-ubp, pixmap);
368                 }
369                 XGlyphInfo extents;
370                 xftTextExtents32(top_level->display, curfont,
371                         (const FcChar32*)ubp, up-ubp, &extents);
372                 x += extents.xOff;
373         }
374
375         if( altfont )
376                 xftFontClose(top_level->display, altfont);
377
378         xftColorFree(top_level->display, top_level->vis, top_level->cmap, &xft_color);
379 #endif
380         return x - x0;
381 }
382
383 void BC_WindowBase::truncate_text(char *result, const char *text, int w)
384 {
385         int new_w = get_text_width(current_font, text);
386
387         if( new_w > w ) {
388                 const char* separator = "...";
389                 int separator_w = get_text_width(current_font, separator);
390 // can't fit
391                 if( separator_w >= w ) {
392                         strcpy(result, separator);
393                         return;
394                 }
395
396                 int text_len = strlen(text);
397 // widen middle gap until it fits
398                 for( int i=text_len/2; i>0; --i ) {
399                         strncpy(result, text, i);
400                         result[i] = 0;
401                         strcat(result, separator);
402                         strncat(result, text + text_len - i, i);
403                         result[i + strlen(separator) + i] = 0;
404                         new_w = get_text_width(current_font, result);
405 //printf("BC_WindowBase::truncate_text %d %d %d %s\n", __LINE__, new_w, w, result);
406                         if(new_w < w) return;
407                 }
408
409 // Didn't fit
410                 strcpy(result, separator);
411                 return;
412         }
413
414         strcpy(result, text);
415 }
416
417 void BC_WindowBase::draw_center_text(int x, int y, const char *text, int length)
418 {
419         if(length < 0) length = strlen(text);
420         int w = get_text_width(current_font, text, length);
421         x -= w / 2;
422         draw_text(x, y, text, length);
423 }
424
425 void BC_WindowBase::draw_line(int x1, int y1, int x2, int y2, BC_Pixmap *pixmap)
426 { BT
427 // Some X drivers can't draw 0 length lines
428         if( x1 == x2 && y1 == y2 ) {
429                 draw_pixel(x1, y1, pixmap);
430         }
431         else {
432                 XDrawLine(top_level->display,
433                         pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
434                         top_level->gc, x1, y1, x2, y2);
435         }
436 }
437
438 void BC_WindowBase::draw_polygon(ArrayList<int> *x, ArrayList<int> *y, BC_Pixmap *pixmap)
439 { BT
440         int npoints = MIN(x->total, y->total);
441         XPoint *points = new XPoint[npoints];
442
443         for( int i=0; i<npoints; ++i ) {
444                 points[i].x = x->values[i];
445                 points[i].y = y->values[i];
446         }
447
448         XDrawLines(top_level->display,
449                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
450                 top_level->gc, points, npoints, CoordModeOrigin);
451
452         delete [] points;
453 }
454
455 void BC_WindowBase::fill_polygon(ArrayList<int> *x, ArrayList<int> *y, BC_Pixmap *pixmap)
456 { BT
457         int npoints = MIN(x->total, y->total);
458         XPoint *points = new XPoint[npoints];
459
460         for( int i=0; i<npoints; ++i ) {
461                 points[i].x = x->values[i];
462                 points[i].y = y->values[i];
463         }
464
465         XFillPolygon(top_level->display,
466                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
467                 top_level->gc, points, npoints, Nonconvex, CoordModeOrigin);
468
469         delete [] points;
470 }
471
472
473 void BC_WindowBase::draw_rectangle(int x, int y, int w, int h)
474 { BT
475         XDrawRectangle(top_level->display,
476                 pixmap->opaque_pixmap, top_level->gc,
477                 x, y, w - 1, h - 1);
478 }
479
480 void BC_WindowBase::draw_3d_border(int x, int y, int w, int h, int is_down)
481 {
482         draw_3d_border(x, y, w, h,
483                 top_level->get_resources()->border_shadow2,
484                 top_level->get_resources()->border_shadow1,
485                 top_level->get_resources()->border_light1,
486                 top_level->get_resources()->border_light2);
487 }
488
489
490 void BC_WindowBase::draw_3d_border(int x, int y, int w, int h,
491         int light1, int light2, int shadow1, int shadow2)
492 {
493         int lx, ly, ux, uy;
494
495         h--; w--;
496
497         lx = x+1;  ly = y+1;
498         ux = x+w-1;  uy = y+h-1;
499
500         set_color(light1);
501         draw_line(x, y, ux, y);
502         draw_line(x, y, x, uy);
503         set_color(light2);
504         draw_line(lx, ly, ux - 1, ly);
505         draw_line(lx, ly, lx, uy - 1);
506
507         set_color(shadow1);
508         draw_line(ux, ly, ux, uy);
509         draw_line(lx, uy, ux, uy);
510         set_color(shadow2);
511         draw_line(x + w, y, x + w, y + h);
512         draw_line(x, y + h, x + w, y + h);
513 }
514
515 void BC_WindowBase::draw_3d_box(int x, int y, int w, int h,
516         int light1, int light2, int middle, int shadow1, int shadow2,
517         BC_Pixmap *pixmap)
518 {
519         int lx, ly, ux, uy;
520
521         h--; w--;
522
523         lx = x+1;  ly = y+1;
524         ux = x+w-1;  uy = y+h-1;
525
526         set_color(middle);
527         draw_box(x, y, w, h, pixmap);
528
529         set_color(light1);
530         draw_line(x, y, ux, y, pixmap);
531         draw_line(x, y, x, uy, pixmap);
532         set_color(light2);
533         draw_line(lx, ly, ux - 1, ly, pixmap);
534         draw_line(lx, ly, lx, uy - 1, pixmap);
535
536         set_color(shadow1);
537         draw_line(ux, ly, ux, uy, pixmap);
538         draw_line(lx, uy, ux, uy, pixmap);
539         set_color(shadow2);
540         draw_line(x + w, y, x + w, y + h, pixmap);
541         draw_line(x, y + h, x + w, y + h, pixmap);
542 }
543
544 void BC_WindowBase::draw_colored_box(int x, int y, int w, int h, int down, int highlighted)
545 {
546         if(!down)
547         {
548                 if(highlighted)
549                         draw_3d_box(x, y, w, h,
550                                 top_level->get_resources()->button_light,
551                                 top_level->get_resources()->button_highlighted,
552                                 top_level->get_resources()->button_highlighted,
553                                 top_level->get_resources()->button_shadow,
554                                 BLACK);
555                 else
556                         draw_3d_box(x, y, w, h,
557                                 top_level->get_resources()->button_light,
558                                 top_level->get_resources()->button_up,
559                                 top_level->get_resources()->button_up,
560                                 top_level->get_resources()->button_shadow,
561                                 BLACK);
562         }
563         else
564         {
565 // need highlighting for toggles
566                 if(highlighted)
567                         draw_3d_box(x, y, w, h,
568                                 top_level->get_resources()->button_shadow,
569                                 BLACK,
570                                 top_level->get_resources()->button_up,
571                                 top_level->get_resources()->button_up,
572                                 top_level->get_resources()->button_light);
573                 else
574                         draw_3d_box(x, y, w, h,
575                                 top_level->get_resources()->button_shadow,
576                                 BLACK,
577                                 top_level->get_resources()->button_down,
578                                 top_level->get_resources()->button_down,
579                                 top_level->get_resources()->button_light);
580         }
581 }
582
583
584 void BC_WindowBase::draw_border(char *text, int x, int y, int w, int h)
585 {
586         int left_indent = xS(20);
587         int lx, ly, ux, uy;
588
589         h--; w--;
590         lx = x + 1;  ly = y + 1;
591         ux = x + w - 1;  uy = y + h - 1;
592
593         set_opaque();
594         if(text && text[0] != 0)
595         {
596                 set_color(BLACK);
597                 set_font(MEDIUMFONT);
598                 draw_text(x + left_indent, y + get_text_height(MEDIUMFONT) / 2, text);
599         }
600
601         set_color(top_level->get_resources()->button_shadow);
602         draw_line(x, y, x + left_indent - xS(5), y);
603         draw_line(x, y, x, uy);
604         draw_line(x + left_indent + xS(5) + get_text_width(MEDIUMFONT, text), y, ux, y);
605         draw_line(x, y, x, uy);
606         draw_line(ux, ly, ux, uy);
607         draw_line(lx, uy, ux, uy);
608         set_color(top_level->get_resources()->button_light);
609         draw_line(lx, ly, x + left_indent - xS(5) - 1, ly);
610         draw_line(lx, ly, lx, uy - 1);
611         draw_line(x + left_indent + xS(5) + get_text_width(MEDIUMFONT, text), ly, ux - 1, ly);
612         draw_line(lx, ly, lx, uy - 1);
613         draw_line(x + w, y, x + w, y + h);
614         draw_line(x, y + h, x + w, y + h);
615 }
616
617 void BC_WindowBase::draw_triangle_down_flat(int x, int y, int w, int h)
618 { BT
619         int x1, y1, x2, y2, x3;
620         XPoint point[3];
621
622         x1 = x+1; x2 = x + w/2; x3 = x+w-1;
623         y1 = y; y2 = y+h-1;
624
625         point[0].x = x2; point[0].y = y2;
626         point[1].x = x3; point[1].y = y1;
627         point[2].x = x1; point[2].y = y1;
628
629         XFillPolygon(top_level->display, pixmap->opaque_pixmap, top_level->gc,
630                 (XPoint *)point, 3, Nonconvex, CoordModeOrigin);
631         draw_line(x1,y1, x3,y1);
632 }
633
634 void BC_WindowBase::draw_triangle_up(int x, int y, int w, int h,
635         int light1, int light2, int middle, int shadow1, int shadow2)
636 { BT
637         int x1, y1, x2, y2, x3;
638         XPoint point[3];
639
640         x1 = x; y1 = y; x2 = x + w / 2;
641         y2 = y + h - 1; x3 = x + w - 1;
642
643 // middle
644         point[0].x = x2; point[0].y = y1; point[1].x = x3;
645         point[1].y = y2; point[2].x = x1; point[2].y = y2;
646
647         set_color(middle);
648         XFillPolygon(top_level->display, pixmap->opaque_pixmap, top_level->gc,
649                 (XPoint *)point, 3, Nonconvex, CoordModeOrigin);
650
651 // bottom and top right
652         set_color(shadow1);
653         draw_line(x3, y2-1, x1, y2-1);
654         draw_line(x2-1, y1, x3-1, y2);
655         set_color(shadow2);
656         draw_line(x3, y2, x1, y2);
657         draw_line(x2, y1, x3, y2);
658
659 // top left
660         set_color(light2);
661         draw_line(x2+1, y1, x1+1, y2);
662         set_color(light1);
663         draw_line(x2, y1, x1, y2);
664 }
665
666 void BC_WindowBase::draw_triangle_down(int x, int y, int w, int h,
667         int light1, int light2, int middle, int shadow1, int shadow2)
668 {
669         int x1, y1, x2, y2, x3;
670         XPoint point[3];
671
672         x1 = x; x2 = x + w / 2; x3 = x + w - 1;
673         y1 = y; y2 = y + h - 1;
674
675         point[0].x = x2; point[0].y = y2; point[1].x = x3;
676         point[1].y = y1; point[2].x = x1; point[2].y = y1;
677
678         set_color(middle);
679         XFillPolygon(top_level->display,
680                 pixmap->opaque_pixmap,
681                 top_level->gc,
682                 (XPoint *)point,
683                 3,
684                 Nonconvex,
685                 CoordModeOrigin);
686
687 // top and bottom left
688         set_color(light2);
689         draw_line(x3-1, y1+1, x1+1, y1+1);
690         draw_line(x1+1, y1, x2+1, y2);
691         set_color(light1);
692         draw_line(x3, y1, x1, y1);
693         draw_line(x1, y1, x2, y2);
694
695 // bottom right
696         set_color(shadow1);
697         draw_line(x3-1, y1, x2-1, y2);
698         set_color(shadow2);
699         draw_line(x3, y1, x2, y2);
700 }
701
702 void BC_WindowBase::draw_triangle_left(int x, int y, int w, int h,
703         int light1, int light2, int middle, int shadow1, int shadow2)
704 { BT
705         int x1, y1, x2, y2, y3;
706         XPoint point[3];
707
708         // draw back arrow
709         y1 = y; x1 = x; y2 = y + h / 2;
710         x2 = x + w - 1; y3 = y + h - 1;
711
712         point[0].x = x1; point[0].y = y2; point[1].x = x2;
713         point[1].y = y1; point[2].x = x2; point[2].y = y3;
714
715         set_color(middle);
716         XFillPolygon(top_level->display,
717                 pixmap->opaque_pixmap,
718                 top_level->gc,
719                 (XPoint *)point,
720                 3,
721                 Nonconvex,
722                 CoordModeOrigin);
723
724 // right and bottom right
725         set_color(shadow1);
726         draw_line(x2-1, y1, x2-1, y3-1);
727         draw_line(x2, y3-1, x1, y2-1);
728         set_color(shadow2);
729         draw_line(x2, y1, x2, y3);
730         draw_line(x2, y3, x1, y2);
731
732 // top left
733         set_color(light1);
734         draw_line(x1, y2, x2, y1);
735         set_color(light2);
736         draw_line(x1, y2+1, x2, y1+1);
737 }
738
739 void BC_WindowBase::draw_triangle_right(int x, int y, int w, int h,
740         int light1, int light2, int middle, int shadow1, int shadow2)
741 { BT
742         int x1, y1, x2, y2, y3;
743         XPoint point[3];
744
745         y1 = y; y2 = y + h / 2; y3 = y + h - 1;
746         x1 = x; x2 = x + w - 1;
747
748         point[0].x = x1; point[0].y = y1; point[1].x = x2;
749         point[1].y = y2; point[2].x = x1; point[2].y = y3;
750
751         set_color(middle);
752         XFillPolygon(top_level->display,
753                 pixmap->opaque_pixmap,
754                 top_level->gc,
755                 (XPoint *)point,
756                 3,
757                 Nonconvex,
758                 CoordModeOrigin);
759
760 // left and top right
761         set_color(light2);
762         draw_line(x1+1, y3, x1+1, y1);
763         draw_line(x1, y1+1, x2, y2+1);
764         set_color(light1);
765         draw_line(x1, y3, x1, y1);
766         draw_line(x1, y1, x2, y2);
767
768 // bottom right
769         set_color(shadow1);
770         draw_line(x2, y2-1, x1, y3-1);
771         set_color(shadow2);
772         draw_line(x2, y2, x1, y3);
773 }
774
775
776 void BC_WindowBase::draw_check(int x, int y)
777 {
778         int xs3 = xS(3), xs4 = xS(4), xs6 = xS(6);
779         int ys1 = yS(1), ys2 = yS(2), ys3 = yS(3), ys4 = yS(4);
780         const int w = xS(15), h = yS(15), yh2 = y + h/2;
781         draw_line(x + xs3, yh2 + 0,   x + xs6,     yh2 + ys2);
782         draw_line(x + xs3, yh2 + ys1, x + xs6,     yh2 + ys3);
783         draw_line(x + xs6, yh2 + ys2, x + w - xs4, yh2 - ys3);
784         draw_line(x + xs3, yh2 + ys2, x + xs6,     yh2 + ys4);
785         draw_line(x + xs6, yh2 + ys2, x + w - xs4, yh2 - ys3);
786         draw_line(x + xs6, yh2 + ys3, x + w - xs4, yh2 - ys2);
787         draw_line(x + xs6, yh2 + ys4, x + w - xs4, yh2 - ys1);
788 }
789
790 void BC_WindowBase::draw_tiles(BC_Pixmap *tile, int origin_x, int origin_y, int x, int y, int w, int h)
791 { BT
792         if( !tile ) {
793                 set_color(bg_color);
794                 draw_box(x, y, w, h);
795         }
796         else {
797                 XSetFillStyle(top_level->display, top_level->gc, FillTiled);
798 // Don't know how slow this is
799                 XSetTile(top_level->display, top_level->gc, tile->get_pixmap());
800                 XSetTSOrigin(top_level->display, top_level->gc, origin_x, origin_y);
801                 draw_box(x, y, w, h);
802                 XSetFillStyle(top_level->display, top_level->gc, FillSolid);
803         }
804 }
805
806 void BC_WindowBase::draw_top_tiles(BC_WindowBase *parent_window, int x, int y, int w, int h)
807 { BT
808         Window tempwin;
809         int origin_x, origin_y;
810         XTranslateCoordinates(top_level->display,
811                 parent_window->win, win,
812                 0, 0, &origin_x, &origin_y, &tempwin);
813         draw_tiles(parent_window->bg_pixmap,
814                 origin_x, origin_y,
815                 x, y, w, h);
816 }
817
818 void BC_WindowBase::draw_top_background(BC_WindowBase *parent_window,
819         int x, int y, int w, int h, BC_Pixmap *pixmap)
820 { BT
821         Window tempwin;
822         int top_x, top_y;
823         XLockDisplay(top_level->display);
824
825         XTranslateCoordinates(top_level->display,
826                 win, parent_window->win,
827                 x, y, &top_x, &top_y, &tempwin);
828
829         XCopyArea(top_level->display,
830                 parent_window->pixmap->opaque_pixmap,
831                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
832                 top_level->gc, top_x, top_y, w, h, x, y);
833
834         XUnlockDisplay(top_level->display);
835 }
836
837 void BC_WindowBase::draw_background(int x, int y, int w, int h)
838 {
839         if( bg_pixmap ) {
840                 draw_tiles(bg_pixmap, 0, 0, x, y, w, h);
841         }
842         else {
843                 clear_box(x, y, w, h);
844         }
845 }
846
847 void BC_WindowBase::draw_bitmap(BC_Bitmap *bitmap, int dont_wait,
848         int dest_x, int dest_y, int dest_w, int dest_h,
849         int src_x, int src_y, int src_w, int src_h,
850         BC_Pixmap *pixmap)
851 { BT
852 // Hide cursor if video enabled
853         update_video_cursor();
854
855 //printf("BC_WindowBase::draw_bitmap %d dest_y=%d\n", __LINE__, dest_y);
856         if( dest_w <= 0 || dest_h <= 0 ) {
857 // Use hardware scaling to canvas dimensions if proper color model.
858                 if( bitmap->get_color_model() == BC_YUV420P ) {
859                         dest_w = w;
860                         dest_h = h;
861                 }
862                 else {
863                         dest_w = bitmap->get_w();
864                         dest_h = bitmap->get_h();
865                 }
866         }
867
868         if( src_w <= 0 || src_h <= 0 ) {
869                 src_w = bitmap->get_w();
870                 src_h = bitmap->get_h();
871         }
872
873         if( video_on ) {
874                 bitmap->write_drawable(win,
875                         top_level->gc, src_x, src_y, src_w, src_h,
876                         dest_x, dest_y, dest_w, dest_h, dont_wait);
877                 top_level->flush();
878         }
879         else {
880                 bitmap->write_drawable(pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
881                         top_level->gc, dest_x, dest_y, src_x, src_y, dest_w, dest_h, dont_wait);
882         }
883 //printf("BC_WindowBase::draw_bitmap 2\n");
884 }
885
886
887 void BC_WindowBase::draw_pixel(int x, int y, BC_Pixmap *pixmap)
888 { BT
889         XDrawPoint(top_level->display,
890                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
891                 top_level->gc, x, y);
892 }
893
894
895 void BC_WindowBase::draw_pixmap(BC_Pixmap *pixmap,
896         int dest_x, int dest_y, int dest_w, int dest_h,
897         int src_x, int src_y, BC_Pixmap *dst)
898 { BT
899         pixmap->write_drawable(dst ? dst->opaque_pixmap : this->pixmap->opaque_pixmap,
900                         dest_x, dest_y, dest_w, dest_h, src_x, src_y);
901 }
902
903 void BC_WindowBase::draw_vframe(VFrame *frame,
904         int dest_x, int dest_y, int dest_w, int dest_h,
905         int src_x, int src_y, int src_w, int src_h,
906         BC_Pixmap *pixmap)
907 {
908         if(dest_w <= 0) dest_w = frame->get_w() - src_x;
909         if(dest_h <= 0) dest_h = frame->get_h() - src_y;
910         if(src_w <= 0) src_w = frame->get_w() - src_x;
911         if(src_h <= 0) src_h = frame->get_h() - src_y;
912         CLAMP(src_x, 0, frame->get_w() - 1);
913         CLAMP(src_y, 0, frame->get_h() - 1);
914         if(src_x + src_w > frame->get_w()) src_w = frame->get_w() - src_x;
915         if(src_y + src_h > frame->get_h()) src_h = frame->get_h() - src_y;
916
917         if( !temp_bitmap )
918                 temp_bitmap = new BC_Bitmap(this, dest_w, dest_h, get_color_model(), 0);
919         temp_bitmap->match_params(dest_w, dest_h, get_color_model(), 0);
920
921         temp_bitmap->read_frame(frame,
922                 src_x, src_y, src_w, src_h,
923                 0, 0, dest_w, dest_h, bg_color);
924
925         draw_bitmap(temp_bitmap, 0,
926                 dest_x, dest_y, dest_w, dest_h,
927                 0, 0, -1, -1, pixmap);
928 }
929
930 void BC_WindowBase::draw_tooltip(const char *text)
931 {
932         if( !text )
933                 text = tooltip_text;
934         if(tooltip_popup && text)
935         {
936                 int w = tooltip_popup->get_w(), h = tooltip_popup->get_h();
937                 tooltip_popup->set_color(get_resources()->tooltip_bg_color);
938                 tooltip_popup->draw_box(0, 0, w, h);
939                 tooltip_popup->set_color(BLACK);
940                 tooltip_popup->draw_rectangle(0, 0, w, h);
941                 tooltip_popup->set_font(MEDIUMFONT);
942                 tooltip_popup->draw_text(TOOLTIP_MARGIN,
943                         get_text_ascent(MEDIUMFONT) + TOOLTIP_MARGIN,
944                         text);
945         }
946 }
947
948 void BC_WindowBase::slide_left(int distance)
949 { BT
950         if(distance < w)
951         {
952                 XCopyArea(top_level->display,
953                         pixmap->opaque_pixmap,
954                         pixmap->opaque_pixmap,
955                         top_level->gc,
956                         distance,
957                         0,
958                         w - distance,
959                         h,
960                         0,
961                         0);
962         }
963 }
964
965 void BC_WindowBase::slide_right(int distance)
966 { BT
967         if(distance < w)
968         {
969                 XCopyArea(top_level->display,
970                         pixmap->opaque_pixmap, pixmap->opaque_pixmap, top_level->gc,
971                         0, 0, w - distance, h, distance, 0);
972         }
973 }
974
975 void BC_WindowBase::slide_up(int distance)
976 { BT
977         if(distance < h)
978         {
979                 XCopyArea(top_level->display,
980                         pixmap->opaque_pixmap, pixmap->opaque_pixmap, top_level->gc,
981                         0, distance, w, h - distance, 0, 0);
982                 set_color(bg_color);
983                 XFillRectangle(top_level->display, pixmap->opaque_pixmap, top_level->gc,
984                         0, h - distance, w, distance);
985         }
986 }
987
988 void BC_WindowBase::slide_down(int distance)
989 { BT
990         if(distance < h)
991         {
992                 XCopyArea(top_level->display,
993                         pixmap->opaque_pixmap, pixmap->opaque_pixmap, top_level->gc,
994                         0, 0, w, h - distance, 0, distance);
995                 set_color(bg_color);
996                 XFillRectangle(top_level->display,
997                         pixmap->opaque_pixmap, top_level->gc,
998                         0, 0, w, distance);
999         }
1000 }
1001
1002 // 3 segments in separate pixmaps.  Obsolete.
1003 void BC_WindowBase::draw_3segment(int x, int y, int w, int h,
1004         BC_Pixmap *left_image, BC_Pixmap *mid_image,
1005         BC_Pixmap *right_image, BC_Pixmap *pixmap)
1006 {
1007         if(w <= 0 || h <= 0) return;
1008         int left_boundary = left_image->get_w_fixed();
1009         int right_boundary = w - right_image->get_w_fixed();
1010         for(int i = 0; i < w; )
1011         {
1012                 BC_Pixmap *image;
1013
1014                 if(i < left_boundary)
1015                         image = left_image;
1016                 else
1017                 if(i < right_boundary)
1018                         image = mid_image;
1019                 else
1020                         image = right_image;
1021
1022                 int output_w = image->get_w_fixed();
1023
1024                 if(i < left_boundary)
1025                 {
1026                         if(i + output_w > left_boundary) output_w = left_boundary - i;
1027                 }
1028                 else
1029                 if(i < right_boundary)
1030                 {
1031                         if(i + output_w > right_boundary) output_w = right_boundary - i;
1032                 }
1033                 else
1034                         if(i + output_w > w) output_w = w - i;
1035
1036                 image->write_drawable(pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1037                                 x + i, y, output_w, h, 0, 0);
1038                 i += output_w;
1039         }
1040 }
1041 // 3 segments in separate vframes.  Obsolete.
1042 void BC_WindowBase::draw_3segment(int x, int y, int w, int h,
1043         VFrame *left_image, VFrame *mid_image,
1044         VFrame *right_image, BC_Pixmap *pixmap)
1045 {
1046         if(w <= 0 || h <= 0) return;
1047         int left_boundary = left_image->get_w_fixed();
1048         int right_boundary = w - right_image->get_w_fixed();
1049
1050
1051         for(int i = 0; i < w; )
1052         {
1053                 VFrame *image;
1054
1055                 if(i < left_boundary)
1056                         image = left_image;
1057                 else
1058                 if(i < right_boundary)
1059                         image = mid_image;
1060                 else
1061                         image = right_image;
1062
1063                 int output_w = image->get_w_fixed();
1064
1065                 if(i < left_boundary)
1066                 {
1067                         if(i + output_w > left_boundary) output_w = left_boundary - i;
1068                 }
1069                 else
1070                 if(i < right_boundary)
1071                 {
1072                         if(i + output_w > right_boundary) output_w = right_boundary - i;
1073                 }
1074                 else
1075                         if(i + output_w > w) output_w = w - i;
1076
1077                 if(image)
1078                         draw_vframe(image, x + i, y, output_w, h,
1079                                         0, 0, 0, 0, pixmap);
1080
1081                 if(output_w == 0) break;
1082                 i += output_w;
1083         }
1084 }
1085
1086 // Draw all 3 segments in a single vframe for a changing level
1087
1088 // total_x
1089 // <------>
1090 // total_w
1091 //         <------------------------------------------------------------>
1092 // x
1093 // |
1094 // w
1095 // <-------------------------------------------------------------------->
1096 // output
1097 //         |-------------------|----------------------|------------------|
1098
1099
1100 void BC_WindowBase::draw_3segmenth(int x, int y, int w,
1101                 VFrame *image, BC_Pixmap *pixmap)
1102 {
1103         draw_3segmenth(x, y, w, x, w, image, pixmap);
1104 }
1105
1106 void BC_WindowBase::draw_3segmenth(int x, int y, int w,
1107                 int total_x, int total_w, VFrame *image,
1108                 BC_Pixmap *pixmap)
1109 {
1110         if(total_w <= 0 || w <= 0 || h <= 0) return;
1111         int third_image = image->get_w() / 3;
1112         int half_image = image->get_w() / 2;
1113         //int left_boundary = third_image;
1114         //int right_boundary = total_w - third_image;
1115         int left_in_x = 0;
1116         int left_in_w = third_image;
1117         int left_out_x = total_x;
1118         int left_out_w = third_image;
1119         int right_in_x = image->get_w() - third_image;
1120         int right_in_w = third_image;
1121         int right_out_x = total_x + total_w - third_image;
1122         int right_out_w = third_image;
1123         int center_out_x = total_x + third_image;
1124         int center_out_w = total_w - third_image * 2;
1125         //int image_x, image_w;
1126
1127 //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",
1128 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1129
1130         if(left_out_x < x)
1131         {
1132                 left_in_w -= x - left_out_x;
1133                 left_out_w -= x - left_out_x;
1134                 left_in_x += x - left_out_x;
1135                 left_out_x += x - left_out_x;
1136         }
1137
1138         if(left_out_x + left_out_w > x + w)
1139         {
1140                 left_in_w -= (left_out_x + left_out_w) - (x + w);
1141                 left_out_w -= (left_out_x + left_out_w) - (x + w);
1142         }
1143
1144         if(right_out_x < x)
1145         {
1146                 right_in_w -= x - right_out_x;
1147                 right_out_w -= x - right_out_x;
1148                 right_in_x += x - right_out_x;
1149                 right_out_x += x - right_out_x;
1150         }
1151
1152         if(right_out_x + right_out_w > x + w)
1153         {
1154                 right_in_w -= (right_out_x + right_out_w) - (x + w);
1155                 right_out_w -= (right_out_x + right_out_w) - (x + w);
1156         }
1157
1158         if(center_out_x < x)
1159         {
1160                 center_out_w -= x - center_out_x;
1161                 center_out_x += x - center_out_x;
1162         }
1163
1164         if(center_out_x + center_out_w > x + w)
1165         {
1166                 center_out_w -= (center_out_x + center_out_w) - (x + w);
1167         }
1168
1169         if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1170                 image->get_w(), image->get_h(),
1171                 get_color_model(), 0);
1172         temp_bitmap->match_params(image->get_w(), image->get_h(),
1173                 get_color_model(), 0);
1174         temp_bitmap->read_frame(image,
1175                 0, 0, image->get_w(), image->get_h(), bg_color);
1176 // src width and height are meaningless in video_off mode
1177 //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",
1178 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1179         if(left_out_w > 0) {
1180                 draw_bitmap(temp_bitmap, 0,
1181                         left_out_x, y, left_out_w, image->get_h(),
1182                         left_in_x, 0, -1, -1, pixmap);
1183         }
1184
1185         if(right_out_w > 0) {
1186                 draw_bitmap(temp_bitmap, 0,
1187                         right_out_x, y, right_out_w, image->get_h(),
1188                         right_in_x, 0, -1, -1, pixmap);
1189         }
1190
1191         for( int pixel = center_out_x;
1192                  pixel < center_out_x + center_out_w;
1193                  pixel += half_image ) {
1194                 int fragment_w = half_image;
1195                 if(fragment_w + pixel > center_out_x + center_out_w)
1196                         fragment_w = (center_out_x + center_out_w) - pixel;
1197
1198 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1199                 draw_bitmap(temp_bitmap, 0,
1200                         pixel, y, fragment_w, image->get_h(),
1201                         third_image, 0, -1, -1, pixmap);
1202         }
1203
1204 }
1205
1206 void BC_WindowBase::draw_3segmenth(int x, int y, int w, int total_x, int total_w,
1207                 BC_Pixmap *src, BC_Pixmap *dst)
1208 {
1209         if(w <= 0 || total_w <= 0) return;
1210         if(!src) printf("BC_WindowBase::draw_3segmenth src=0\n");
1211         int quarter_src = src->get_w() / 4;
1212         int half_src = src->get_w() / 2;
1213         //int left_boundary = quarter_src;
1214         //int right_boundary = total_w - quarter_src;
1215         int left_in_x = 0;
1216         int left_in_w = quarter_src;
1217         int left_out_x = total_x;
1218         int left_out_w = quarter_src;
1219         int right_in_x = src->get_w() - quarter_src;
1220         int right_in_w = quarter_src;
1221         int right_out_x = total_x + total_w - quarter_src;
1222         int right_out_w = quarter_src;
1223         int center_out_x = total_x + quarter_src;
1224         int center_out_w = total_w - quarter_src * 2;
1225         //int src_x, src_w;
1226
1227 //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",
1228 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1229
1230         if(left_out_x < x)
1231         {
1232                 left_in_w -= x - left_out_x;
1233                 left_out_w -= x - left_out_x;
1234                 left_in_x += x - left_out_x;
1235                 left_out_x += x - left_out_x;
1236         }
1237
1238         if(left_out_x + left_out_w > x + w)
1239         {
1240                 left_in_w -= (left_out_x + left_out_w) - (x + w);
1241                 left_out_w -= (left_out_x + left_out_w) - (x + w);
1242         }
1243
1244         if(right_out_x < x)
1245         {
1246                 right_in_w -= x - right_out_x;
1247                 right_out_w -= x - right_out_x;
1248                 right_in_x += x - right_out_x;
1249                 right_out_x += x - right_out_x;
1250         }
1251
1252         if(right_out_x + right_out_w > x + w)
1253         {
1254                 right_in_w -= (right_out_x + right_out_w) - (x + w);
1255                 right_out_w -= (right_out_x + right_out_w) - (x + w);
1256         }
1257
1258         if(center_out_x < x)
1259         {
1260                 center_out_w -= x - center_out_x;
1261                 center_out_x += x - center_out_x;
1262         }
1263
1264         if(center_out_x + center_out_w > x + w)
1265         {
1266                 center_out_w -= (center_out_x + center_out_w) - (x + w);
1267         }
1268
1269
1270 //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",
1271 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1272         if(left_out_w > 0)
1273                 draw_pixmap(src, left_out_x, y, left_out_w, src->get_h(), left_in_x, 0, dst);
1274
1275         if(right_out_w > 0)
1276                 draw_pixmap(src, right_out_x, y, right_out_w, src->get_h(), right_in_x, 0, dst);
1277
1278         for( int pixel = center_out_x; pixel < center_out_x + center_out_w; pixel += half_src) {
1279                 int fragment_w = half_src;
1280                 if(fragment_w + pixel > center_out_x + center_out_w)
1281                         fragment_w = (center_out_x + center_out_w) - pixel;
1282 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1283                 draw_pixmap(src, pixel, y, fragment_w, src->get_h(), quarter_src, 0, dst);
1284         }
1285
1286 }
1287
1288
1289 void BC_WindowBase::draw_3segmenth(int x, int y, int w, BC_Pixmap *src, BC_Pixmap *dst)
1290 {
1291         if(w <= 0) return;
1292         int third_image = src->get_w() / 3;
1293         int half_output = w / 2;
1294         //int left_boundary = third_image;
1295         //int right_boundary = w - third_image;
1296         int left_in_x = 0;
1297         int left_in_w = third_image;
1298         int left_out_x = x;
1299         int left_out_w = third_image;
1300         int right_in_x = src->get_w() - third_image;
1301         int right_in_w = third_image;
1302         int right_out_x = x + w - third_image;
1303         int right_out_w = third_image;
1304         //int image_x, image_w;
1305
1306 //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",
1307 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1308
1309         if(left_out_w > half_output)
1310         {
1311                 left_in_w -= left_out_w - half_output;
1312                 left_out_w -= left_out_w - half_output;
1313         }
1314
1315         if(right_out_x < x + half_output)
1316         {
1317                 right_in_w -= x + half_output - right_out_x;
1318                 right_out_w -= x + half_output - right_out_x;
1319                 right_in_x += x + half_output - right_out_x;
1320                 right_out_x += x + half_output - right_out_x;
1321         }
1322
1323 //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",
1324 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1325         if(left_out_w > 0)
1326                 draw_pixmap(src, left_out_x, y, left_out_w, src->get_h(), left_in_x, 0, dst);
1327
1328         if(right_out_w > 0)
1329                 draw_pixmap(src, right_out_x, y, right_out_w, src->get_h(), right_in_x, 0, dst);
1330
1331         for(int pixel = left_out_x + left_out_w; pixel < right_out_x; pixel += third_image) {
1332                 int fragment_w = third_image;
1333                 if(fragment_w + pixel > right_out_x)
1334                         fragment_w = right_out_x - pixel;
1335
1336 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1337                 draw_pixmap(src, pixel, y, fragment_w, src->get_h(), third_image, 0, dst);
1338         }
1339
1340 }
1341
1342 void BC_WindowBase::draw_3segmentv(int x, int y, int h, VFrame *src, BC_Pixmap *dst)
1343 {
1344         if(h <= 0) return;
1345         int third_image = src->get_h() / 3;
1346         int half_output = h / 2;
1347         //int left_boundary = third_image;
1348         //int right_boundary = h - third_image;
1349         int left_in_y = 0;
1350         int left_in_h = third_image;
1351         int left_out_y = y;
1352         int left_out_h = third_image;
1353         int right_in_y = src->get_h() - third_image;
1354         int right_in_h = third_image;
1355         int right_out_y = y + h - third_image;
1356         int right_out_h = third_image;
1357         //int image_y, image_h;
1358
1359
1360         if(left_out_h > half_output)
1361         {
1362                 left_in_h -= left_out_h - half_output;
1363                 left_out_h -= left_out_h - half_output;
1364         }
1365
1366         if(right_out_y < y + half_output)
1367         {
1368                 right_in_h -= y + half_output - right_out_y;
1369                 right_out_h -= y + half_output - right_out_y;
1370                 right_in_y += y + half_output - right_out_y;
1371                 right_out_y += y + half_output - right_out_y;
1372         }
1373
1374
1375         if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1376                 src->get_w(),
1377                 src->get_h(),
1378                 get_color_model(),
1379                 0);
1380         temp_bitmap->match_params(src->get_w(),
1381                 src->get_h(),
1382                 get_color_model(),
1383                 0);
1384         temp_bitmap->read_frame(src,
1385                 0, 0, src->get_w(), src->get_h(), bg_color);
1386
1387
1388         if(left_out_h > 0)
1389         {
1390                 draw_bitmap(temp_bitmap, 0, x, left_out_y,
1391                         src->get_w(), left_out_h, 0, left_in_y,
1392                         -1, -1, dst);
1393         }
1394
1395         if(right_out_h > 0)
1396         {
1397                 draw_bitmap(temp_bitmap, 0, x, right_out_y,
1398                         src->get_w(), right_out_h, 0, right_in_y,
1399                         -1, -1, dst);
1400         }
1401
1402         for(int pixel = left_out_y + left_out_h;
1403                 pixel < right_out_y;
1404                 pixel += third_image)
1405         {
1406                 int fragment_h = third_image;
1407                 if(fragment_h + pixel > right_out_y)
1408                         fragment_h = right_out_y - pixel;
1409
1410 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1411                 draw_bitmap(temp_bitmap, 0, x, pixel,
1412                         src->get_w(), fragment_h, 0, third_image,
1413                         -1, -1, dst);
1414         }
1415 }
1416
1417 void BC_WindowBase::draw_3segmentv(int x,
1418                 int y,
1419                 int h,
1420                 BC_Pixmap *src,
1421                 BC_Pixmap *dst)
1422 {
1423         if(h <= 0) return;
1424         int third_image = src->get_h() / 3;
1425         int half_output = h / 2;
1426         //int left_boundary = third_image;
1427         //int right_boundary = h - third_image;
1428         int left_in_y = 0;
1429         int left_in_h = third_image;
1430         int left_out_y = y;
1431         int left_out_h = third_image;
1432         int right_in_y = src->get_h() - third_image;
1433         int right_in_h = third_image;
1434         int right_out_y = y + h - third_image;
1435         int right_out_h = third_image;
1436         //int image_y, image_h;
1437
1438
1439         if(left_out_h > half_output)
1440         {
1441                 left_in_h -= left_out_h - half_output;
1442                 left_out_h -= left_out_h - half_output;
1443         }
1444
1445         if(right_out_y < y + half_output)
1446         {
1447                 right_in_h -= y + half_output - right_out_y;
1448                 right_out_h -= y + half_output - right_out_y;
1449                 right_in_y += y + half_output - right_out_y;
1450                 right_out_y += y + half_output - right_out_y;
1451         }
1452
1453         if(left_out_h > 0)
1454                 draw_pixmap(src, x, left_out_y, src->get_w(), left_out_h,
1455                         0, left_in_y, dst);
1456
1457         if(right_out_h > 0)
1458                 draw_pixmap(src, x, right_out_y, src->get_w(), right_out_h,
1459                         0, right_in_y, dst);
1460
1461         for(int pixel = left_out_y + left_out_h; pixel < right_out_y; pixel += third_image) {
1462                 int fragment_h = third_image;
1463                 if(fragment_h + pixel > right_out_y)
1464                         fragment_h = right_out_y - pixel;
1465
1466 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1467                 draw_pixmap(src, x, pixel, src->get_w(), fragment_h,
1468                         0, third_image, dst);
1469         }
1470 }
1471
1472
1473 void BC_WindowBase::draw_9segment(int x, int y, int w, int h,
1474                 BC_Pixmap *src, BC_Pixmap *dst)
1475 {
1476         if(w <= 0 || h <= 0) return;
1477
1478         int in_x_third = src->get_w() / 3;
1479         int in_y_third = src->get_h() / 3;
1480         int out_x_half = w / 2;
1481         int out_y_half = h / 2;
1482
1483         int in_x1 = 0;
1484         int in_y1 = 0;
1485         int out_x1 = 0;
1486         int out_y1 = 0;
1487         int in_x2 = MIN(in_x_third, out_x_half);
1488         int in_y2 = MIN(in_y_third, out_y_half);
1489         int out_x2 = in_x2;
1490         int out_y2 = in_y2;
1491
1492         int out_x3 = MAX(w - out_x_half, w - in_x_third);
1493         int out_x4 = w;
1494         int in_x3 = src->get_w() - (out_x4 - out_x3);
1495         //int in_x4 = src->get_w();
1496
1497         int out_y3 = MAX(h - out_y_half, h - in_y_third);
1498         int out_y4 = h;
1499         int in_y3 = src->get_h() - (out_y4 - out_y3);
1500         //int in_y4 = src->get_h();
1501
1502 // Segment 1
1503         draw_pixmap(src, x + out_x1, y + out_y1, out_x2 - out_x1, out_y2 - out_y1,
1504                 in_x1, in_y1, dst);
1505
1506 // Segment 2 * n
1507         for(int i = out_x2; i < out_x3; i += in_x3 - in_x2) {
1508                 if(out_x3 - i > 0) {
1509                         int w = MIN(in_x3 - in_x2, out_x3 - i);
1510                         draw_pixmap(src, x + i, y + out_y1, w, out_y2 - out_y1,
1511                                 in_x2, in_y1, dst);
1512                 }
1513         }
1514
1515 // Segment 3
1516         draw_pixmap(src, x + out_x3, y + out_y1, out_x4 - out_x3, out_y2 - out_y1,
1517                 in_x3, in_y1, dst);
1518
1519 // Segment 4 * n
1520         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
1521         {
1522                 if(out_y3 - i > 0)
1523                 {
1524                         int h = MIN(in_y3 - in_y2, out_y3 - i);
1525                         draw_pixmap(src, x + out_x1, y + i, out_x2 - out_x1, h,
1526                                 in_x1, in_y2, dst);
1527                 }
1528         }
1529
1530 // Segment 5 * n * n
1531         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2 /* in_y_third */)
1532         {
1533                 if(out_y3 - i > 0)
1534                 {
1535                         int h = MIN(in_y3 - in_y2 /* in_y_third */, out_y3 - i);
1536
1537
1538                         for(int j = out_x2; j < out_x3; j += in_x3 - in_x2 /* in_x_third */)
1539                         {
1540                                 int w = MIN(in_x3 - in_x2 /* in_x_third */, out_x3 - j);
1541                                 if(out_x3 - j > 0)
1542                                         draw_pixmap(src, x + j, y + i, w, h,
1543                                                 in_x2, in_y2, dst);
1544                         }
1545                 }
1546         }
1547
1548 // Segment 6 * n
1549         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
1550         {
1551                 if(out_y3 - i > 0)
1552                 {
1553                         int h = MIN(in_y3 - in_y2, out_y3 - i);
1554                         draw_pixmap(src, x + out_x3, y + i, out_x4 - out_x3, h,
1555                                 in_x3, in_y2, dst);
1556                 }
1557         }
1558
1559 // Segment 7
1560         draw_pixmap(src, x + out_x1, y + out_y3, out_x2 - out_x1, out_y4 - out_y3,
1561                 in_x1, in_y3, dst);
1562
1563 // Segment 8 * n
1564         for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
1565         {
1566                 if(out_x3 - i > 0)
1567                 {
1568                         int w = MIN(in_x3 - in_y2, out_x3 - i);
1569                         draw_pixmap(src, x + i, y + out_y3, w, out_y4 - out_y3,
1570                                 in_x2, in_y3, dst);
1571                 }
1572         }
1573
1574 // Segment 9
1575         draw_pixmap(src, x + out_x3, y + out_y3, out_x4 - out_x3, out_y4 - out_y3,
1576                 in_x3, in_y3, dst);
1577 }
1578
1579
1580 void BC_WindowBase::draw_9segment(int x, int y, int w, int h,
1581                 VFrame *src, BC_Pixmap *dst)
1582 {
1583         if(w <= 0 || h <= 0) return;
1584
1585         int in_x_third = src->get_w() / 3;
1586         int in_y_third = src->get_h() / 3;
1587         int out_x_half = w / 2;
1588         int out_y_half = h / 2;
1589
1590         int in_x1 = 0;
1591         int in_y1 = 0;
1592         int out_x1 = 0;
1593         int out_y1 = 0;
1594         int in_x2 = MIN(in_x_third, out_x_half);
1595         int in_y2 = MIN(in_y_third, out_y_half);
1596         int out_x2 = in_x2;
1597         int out_y2 = in_y2;
1598
1599         int out_x3 = MAX(w - out_x_half, w - in_x_third);
1600         int out_x4 = w;
1601         int in_x3 = src->get_w() - (out_x4 - out_x3);
1602         int in_x4 = src->get_w();
1603
1604         int out_y3 = MAX(h - out_y_half, h - in_y_third);
1605         int out_y4 = h;
1606         int in_y3 = src->get_h() - (out_y4 - out_y3);
1607         int in_y4 = src->get_h();
1608
1609 //printf("PFCFrame::draw_9segment 1 %d %d %d %d\n", out_x1, out_x2, out_x3, out_x4);
1610 //printf("PFCFrame::draw_9segment 2 %d %d %d %d\n", in_x1, in_x2, in_x3, in_x4);
1611 //printf("PFCFrame::draw_9segment 2 %d %d %d %d\n", in_y1, in_y2, in_y3, in_y4);
1612
1613         if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1614                 src->get_w(),
1615                 src->get_h(),
1616                 get_color_model(),
1617                 0);
1618         temp_bitmap->match_params(src->get_w(),
1619                 src->get_h(),
1620                 get_color_model(),
1621                 0);
1622         temp_bitmap->read_frame(src,
1623                 0, 0, src->get_w(), src->get_h(), bg_color);
1624
1625 // Segment 1
1626         draw_bitmap(temp_bitmap, 0,
1627                 x + out_x1, y + out_y1, out_x2 - out_x1, out_y2 - out_y1,
1628                 in_x1, in_y1, in_x2 - in_x1, in_y2 - in_y1,
1629                 dst);
1630
1631 // Segment 2 * n
1632         for( int i = out_x2; i < out_x3; i += in_x3 - in_x2 ) {
1633                 if( out_x3 - i > 0 ) {
1634                         int w = MIN(in_x3 - in_x2, out_x3 - i);
1635                         draw_bitmap(temp_bitmap, 0,
1636                                 x + i, y + out_y1, w, out_y2 - out_y1,
1637                                 in_x2, in_y1, w, in_y2 - in_y1,
1638                                 dst);
1639                 }
1640         }
1641
1642 // Segment 3
1643         draw_bitmap(temp_bitmap, 0,
1644                 x + out_x3, y + out_y1, out_x4 - out_x3, out_y2 - out_y1,
1645                 in_x3, in_y1, in_x4 - in_x3, in_y2 - in_y1,
1646                 dst);
1647
1648 // Segment 4 * n
1649         for( int i = out_y2; i < out_y3; i += in_y3 - in_y2 ) {
1650                 if( out_y3 - i > 0 ) {
1651                         int h = MIN(in_y3 - in_y2, out_y3 - i);
1652                         draw_bitmap(temp_bitmap, 0,
1653                                 x + out_x1, y + i, out_x2 - out_x1, h,
1654                                 in_x1, in_y2, in_x2 - in_x1, h,
1655                                 dst);
1656                 }
1657         }
1658
1659 // Segment 5 * n * n
1660         for( int i = out_y2; i < out_y3; i += in_y3 - in_y2 ) {
1661                 if( out_y3 - i > 0 ) {
1662                         int h = MIN(in_y3 - in_y2, out_y3 - i);
1663
1664                         for( int j = out_x2; j < out_x3; j += in_x3 - in_x2 ) {
1665                                 int w = MIN(in_x3 - in_x2, out_x3 - j);
1666                                 if(out_x3 - j > 0)
1667                                         draw_bitmap(temp_bitmap, 0,
1668                                                 x + j, y + i, w, h,
1669                                                 in_x2, in_y2, w, h,
1670                                                 dst);
1671                         }
1672                 }
1673         }
1674
1675 // Segment 6 * n
1676         for( int i = out_y2; i < out_y3; i += in_y_third ) {
1677                 if( out_y3 - i > 0 ) {
1678                         int h = MIN(in_y_third, out_y3 - i);
1679                         draw_bitmap(temp_bitmap, 0,
1680                                 x + out_x3, y + i, out_x4 - out_x3, h,
1681                                 in_x3, in_y2, in_x4 - in_x3, h,
1682                                 dst);
1683                 }
1684         }
1685
1686 // Segment 7
1687         draw_bitmap(temp_bitmap, 0,
1688                 x + out_x1, y + out_y3, out_x2 - out_x1, out_y4 - out_y3,
1689                 in_x1, in_y3, in_x2 - in_x1, in_y4 - in_y3,
1690                 dst);
1691
1692 // Segment 8 * n
1693         for( int i = out_x2; i < out_x3; i += in_x_third ) {
1694                 if( out_x3 - i > 0 ) {
1695                         int w = MIN(in_x_third, out_x3 - i);
1696                         draw_bitmap(temp_bitmap, 0,
1697                                 x + i, y + out_y3, w, out_y4 - out_y3,
1698                                 in_x2, in_y3, w, in_y4 - in_y3,
1699                                 dst);
1700                 }
1701         }
1702
1703 // Segment 9
1704         draw_bitmap(temp_bitmap, 0,
1705                 x + out_x3, y + out_y3, out_x4 - out_x3, out_y4 - out_y3,
1706                 in_x3, in_y3, in_x4 - in_x3, in_y4 - in_y3,
1707                 dst);
1708 }
1709