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