fast drag/drop rework, modify labels in mwin->cwin locks, mods to cut/paste, marks...
[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; 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; point[1].x = x3;
638         point[1].y = y1; point[2].x = x1; point[2].y = y1;
639
640         XFillPolygon(top_level->display,
641                 pixmap->opaque_pixmap,
642                 top_level->gc,
643                 (XPoint *)point,
644                 3,
645                 Nonconvex,
646                 CoordModeOrigin);
647 }
648
649 void BC_WindowBase::draw_triangle_up(int x, int y, int w, int h,
650         int light1, int light2, int middle, int shadow1, int shadow2)
651 { BT
652         int x1, y1, x2, y2, x3;
653         XPoint point[3];
654
655         x1 = x; y1 = y; x2 = x + w / 2;
656         y2 = y + h - 1; x3 = x + w - 1;
657
658 // middle
659         point[0].x = x2; point[0].y = y1; point[1].x = x3;
660         point[1].y = y2; point[2].x = x1; point[2].y = y2;
661
662         set_color(middle);
663         XFillPolygon(top_level->display,
664                 pixmap->opaque_pixmap,
665                 top_level->gc,
666                 (XPoint *)point,
667                 3,
668                 Nonconvex,
669                 CoordModeOrigin);
670
671 // bottom and top right
672         set_color(shadow1);
673         draw_line(x3, y2-1, x1, y2-1);
674         draw_line(x2-1, y1, x3-1, y2);
675         set_color(shadow2);
676         draw_line(x3, y2, x1, y2);
677         draw_line(x2, y1, x3, y2);
678
679 // top left
680         set_color(light2);
681         draw_line(x2+1, y1, x1+1, y2);
682         set_color(light1);
683         draw_line(x2, y1, x1, y2);
684 }
685
686 void BC_WindowBase::draw_triangle_down(int x, int y, int w, int h,
687         int light1, int light2, int middle, int shadow1, int shadow2)
688 {
689         int x1, y1, x2, y2, x3;
690         XPoint point[3];
691
692         x1 = x; x2 = x + w / 2; x3 = x + w - 1;
693         y1 = y; y2 = y + h - 1;
694
695         point[0].x = x2; point[0].y = y2; point[1].x = x3;
696         point[1].y = y1; point[2].x = x1; point[2].y = y1;
697
698         set_color(middle);
699         XFillPolygon(top_level->display,
700                 pixmap->opaque_pixmap,
701                 top_level->gc,
702                 (XPoint *)point,
703                 3,
704                 Nonconvex,
705                 CoordModeOrigin);
706
707 // top and bottom left
708         set_color(light2);
709         draw_line(x3-1, y1+1, x1+1, y1+1);
710         draw_line(x1+1, y1, x2+1, y2);
711         set_color(light1);
712         draw_line(x3, y1, x1, y1);
713         draw_line(x1, y1, x2, y2);
714
715 // bottom right
716         set_color(shadow1);
717         draw_line(x3-1, y1, x2-1, y2);
718         set_color(shadow2);
719         draw_line(x3, y1, x2, y2);
720 }
721
722 void BC_WindowBase::draw_triangle_left(int x, int y, int w, int h,
723         int light1, int light2, int middle, int shadow1, int shadow2)
724 { BT
725         int x1, y1, x2, y2, y3;
726         XPoint point[3];
727
728         // draw back arrow
729         y1 = y; x1 = x; y2 = y + h / 2;
730         x2 = x + w - 1; y3 = y + h - 1;
731
732         point[0].x = x1; point[0].y = y2; point[1].x = x2;
733         point[1].y = y1; point[2].x = x2; point[2].y = y3;
734
735         set_color(middle);
736         XFillPolygon(top_level->display,
737                 pixmap->opaque_pixmap,
738                 top_level->gc,
739                 (XPoint *)point,
740                 3,
741                 Nonconvex,
742                 CoordModeOrigin);
743
744 // right and bottom right
745         set_color(shadow1);
746         draw_line(x2-1, y1, x2-1, y3-1);
747         draw_line(x2, y3-1, x1, y2-1);
748         set_color(shadow2);
749         draw_line(x2, y1, x2, y3);
750         draw_line(x2, y3, x1, y2);
751
752 // top left
753         set_color(light1);
754         draw_line(x1, y2, x2, y1);
755         set_color(light2);
756         draw_line(x1, y2+1, x2, y1+1);
757 }
758
759 void BC_WindowBase::draw_triangle_right(int x, int y, int w, int h,
760         int light1, int light2, int middle, int shadow1, int shadow2)
761 { BT
762         int x1, y1, x2, y2, y3;
763         XPoint point[3];
764
765         y1 = y; y2 = y + h / 2; y3 = y + h - 1;
766         x1 = x; x2 = x + w - 1;
767
768         point[0].x = x1; point[0].y = y1; point[1].x = x2;
769         point[1].y = y2; point[2].x = x1; point[2].y = y3;
770
771         set_color(middle);
772         XFillPolygon(top_level->display,
773                 pixmap->opaque_pixmap,
774                 top_level->gc,
775                 (XPoint *)point,
776                 3,
777                 Nonconvex,
778                 CoordModeOrigin);
779
780 // left and top right
781         set_color(light2);
782         draw_line(x1+1, y3, x1+1, y1);
783         draw_line(x1, y1+1, x2, y2+1);
784         set_color(light1);
785         draw_line(x1, y3, x1, y1);
786         draw_line(x1, y1, x2, y2);
787
788 // bottom right
789         set_color(shadow1);
790         draw_line(x2, y2-1, x1, y3-1);
791         set_color(shadow2);
792         draw_line(x2, y2, x1, y3);
793 }
794
795
796 void BC_WindowBase::draw_check(int x, int y)
797 {
798         const int w = 15, h = 15;
799         draw_line(x + 3, y + h / 2 + 0, x + 6, y + h / 2 + 2);
800         draw_line(x + 3, y + h / 2 + 1, x + 6, y + h / 2 + 3);
801         draw_line(x + 6, y + h / 2 + 2, x + w - 4, y + h / 2 - 3);
802         draw_line(x + 3, y + h / 2 + 2, x + 6, y + h / 2 + 4);
803         draw_line(x + 6, y + h / 2 + 2, x + w - 4, y + h / 2 - 3);
804         draw_line(x + 6, y + h / 2 + 3, x + w - 4, y + h / 2 - 2);
805         draw_line(x + 6, y + h / 2 + 4, x + w - 4, y + h / 2 - 1);
806 }
807
808 void BC_WindowBase::draw_tiles(BC_Pixmap *tile, int origin_x, int origin_y, int x, int y, int w, int h)
809 { BT
810         if( !tile ) {
811                 set_color(bg_color);
812                 draw_box(x, y, w, h);
813         }
814         else {
815                 XSetFillStyle(top_level->display, top_level->gc, FillTiled);
816 // Don't know how slow this is
817                 XSetTile(top_level->display, top_level->gc, tile->get_pixmap());
818                 XSetTSOrigin(top_level->display, top_level->gc, origin_x, origin_y);
819                 draw_box(x, y, w, h);
820                 XSetFillStyle(top_level->display, top_level->gc, FillSolid);
821         }
822 }
823
824 void BC_WindowBase::draw_top_tiles(BC_WindowBase *parent_window, int x, int y, int w, int h)
825 { BT
826         Window tempwin;
827         int origin_x, origin_y;
828         XTranslateCoordinates(top_level->display,
829                 parent_window->win, win,
830                 0, 0, &origin_x, &origin_y, &tempwin);
831         draw_tiles(parent_window->bg_pixmap,
832                 origin_x, origin_y,
833                 x, y, w, h);
834 }
835
836 void BC_WindowBase::draw_top_background(BC_WindowBase *parent_window,
837         int x, int y, int w, int h, BC_Pixmap *pixmap)
838 { BT
839         Window tempwin;
840         int top_x, top_y;
841         XLockDisplay(top_level->display);
842
843         XTranslateCoordinates(top_level->display,
844                 win, parent_window->win,
845                 x, y, &top_x, &top_y, &tempwin);
846
847         XCopyArea(top_level->display,
848                 parent_window->pixmap->opaque_pixmap,
849                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
850                 top_level->gc, top_x, top_y, w, h, x, y);
851
852         XUnlockDisplay(top_level->display);
853 }
854
855 void BC_WindowBase::draw_background(int x, int y, int w, int h)
856 {
857         if( bg_pixmap ) {
858                 draw_tiles(bg_pixmap, 0, 0, x, y, w, h);
859         }
860         else {
861                 clear_box(x, y, w, h);
862         }
863 }
864
865 void BC_WindowBase::draw_bitmap(BC_Bitmap *bitmap, int dont_wait,
866         int dest_x, int dest_y, int dest_w, int dest_h,
867         int src_x, int src_y, int src_w, int src_h,
868         BC_Pixmap *pixmap)
869 { BT
870 // Hide cursor if video enabled
871         update_video_cursor();
872
873 //printf("BC_WindowBase::draw_bitmap %d dest_y=%d\n", __LINE__, dest_y);
874         if( dest_w <= 0 || dest_h <= 0 ) {
875 // Use hardware scaling to canvas dimensions if proper color model.
876                 if( bitmap->get_color_model() == BC_YUV420P ) {
877                         dest_w = w;
878                         dest_h = h;
879                 }
880                 else {
881                         dest_w = bitmap->get_w();
882                         dest_h = bitmap->get_h();
883                 }
884         }
885
886         if( src_w <= 0 || src_h <= 0 ) {
887                 src_w = bitmap->get_w();
888                 src_h = bitmap->get_h();
889         }
890
891         if( video_on ) {
892                 bitmap->write_drawable(win,
893                         top_level->gc, src_x, src_y, src_w, src_h,
894                         dest_x, dest_y, dest_w, dest_h, dont_wait);
895                 top_level->flush();
896         }
897         else {
898                 bitmap->write_drawable(pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
899                         top_level->gc, dest_x, dest_y, src_x, src_y, dest_w, dest_h, dont_wait);
900         }
901 //printf("BC_WindowBase::draw_bitmap 2\n");
902 }
903
904
905 void BC_WindowBase::draw_pixel(int x, int y, BC_Pixmap *pixmap)
906 { BT
907         XDrawPoint(top_level->display,
908                 pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
909                 top_level->gc, x, y);
910 }
911
912
913 void BC_WindowBase::draw_pixmap(BC_Pixmap *pixmap,
914         int dest_x, int dest_y, int dest_w, int dest_h,
915         int src_x, int src_y, BC_Pixmap *dst)
916 { BT
917         pixmap->write_drawable(dst ? dst->opaque_pixmap : this->pixmap->opaque_pixmap,
918                         dest_x, dest_y, dest_w, dest_h, src_x, src_y);
919 }
920
921 void BC_WindowBase::draw_vframe(VFrame *frame,
922         int dest_x, int dest_y, int dest_w, int dest_h,
923         int src_x, int src_y, int src_w, int src_h,
924         BC_Pixmap *pixmap)
925 {
926         if(dest_w <= 0) dest_w = frame->get_w() - src_x;
927         if(dest_h <= 0) dest_h = frame->get_h() - src_y;
928         if(src_w <= 0) src_w = frame->get_w() - src_x;
929         if(src_h <= 0) src_h = frame->get_h() - src_y;
930         CLAMP(src_x, 0, frame->get_w() - 1);
931         CLAMP(src_y, 0, frame->get_h() - 1);
932         if(src_x + src_w > frame->get_w()) src_w = frame->get_w() - src_x;
933         if(src_y + src_h > frame->get_h()) src_h = frame->get_h() - src_y;
934
935         if( !temp_bitmap )
936                 temp_bitmap = new BC_Bitmap(this, dest_w, dest_h, get_color_model(), 0);
937         temp_bitmap->match_params(dest_w, dest_h, get_color_model(), 0);
938
939         temp_bitmap->read_frame(frame,
940                 src_x, src_y, src_w, src_h,
941                 0, 0, dest_w, dest_h, bg_color);
942
943         draw_bitmap(temp_bitmap, 0,
944                 dest_x, dest_y, dest_w, dest_h,
945                 0, 0, -1, -1, pixmap);
946 }
947
948 void BC_WindowBase::draw_tooltip(const char *text)
949 {
950         if( !text )
951                 text = tooltip_text;
952         if(tooltip_popup && text)
953         {
954                 int w = tooltip_popup->get_w(), h = tooltip_popup->get_h();
955                 tooltip_popup->set_color(get_resources()->tooltip_bg_color);
956                 tooltip_popup->draw_box(0, 0, w, h);
957                 tooltip_popup->set_color(BLACK);
958                 tooltip_popup->draw_rectangle(0, 0, w, h);
959                 tooltip_popup->set_font(MEDIUMFONT);
960                 tooltip_popup->draw_text(TOOLTIP_MARGIN,
961                         get_text_ascent(MEDIUMFONT) + TOOLTIP_MARGIN,
962                         text);
963         }
964 }
965
966 void BC_WindowBase::slide_left(int distance)
967 { BT
968         if(distance < w)
969         {
970                 XCopyArea(top_level->display,
971                         pixmap->opaque_pixmap,
972                         pixmap->opaque_pixmap,
973                         top_level->gc,
974                         distance,
975                         0,
976                         w - distance,
977                         h,
978                         0,
979                         0);
980         }
981 }
982
983 void BC_WindowBase::slide_right(int distance)
984 { BT
985         if(distance < w)
986         {
987                 XCopyArea(top_level->display,
988                         pixmap->opaque_pixmap,
989                         pixmap->opaque_pixmap,
990                         top_level->gc,
991                         0,
992                         0,
993                         w - distance,
994                         h,
995                         distance,
996                         0);
997         }
998 }
999
1000 void BC_WindowBase::slide_up(int distance)
1001 { BT
1002         if(distance < h)
1003         {
1004                 XCopyArea(top_level->display,
1005                         pixmap->opaque_pixmap,
1006                         pixmap->opaque_pixmap,
1007                         top_level->gc,
1008                         0,
1009                         distance,
1010                         w,
1011                         h - distance,
1012                         0,
1013                         0);
1014                 set_color(bg_color);
1015                 XFillRectangle(top_level->display,
1016                         pixmap->opaque_pixmap,
1017                         top_level->gc,
1018                         0,
1019                         h - distance,
1020                         w,
1021                         distance);
1022         }
1023 }
1024
1025 void BC_WindowBase::slide_down(int distance)
1026 { BT
1027         if(distance < h)
1028         {
1029                 XCopyArea(top_level->display,
1030                         pixmap->opaque_pixmap,
1031                         pixmap->opaque_pixmap,
1032                         top_level->gc,
1033                         0,
1034                         0,
1035                         w,
1036                         h - distance,
1037                         0,
1038                         distance);
1039                 set_color(bg_color);
1040                 XFillRectangle(top_level->display,
1041                         pixmap->opaque_pixmap,
1042                         top_level->gc,
1043                         0,
1044                         0,
1045                         w,
1046                         distance);
1047         }
1048 }
1049
1050 // 3 segments in separate pixmaps.  Obsolete.
1051 void BC_WindowBase::draw_3segment(int x,
1052         int y,
1053         int w,
1054         int h,
1055         BC_Pixmap *left_image,
1056         BC_Pixmap *mid_image,
1057         BC_Pixmap *right_image,
1058         BC_Pixmap *pixmap)
1059 {
1060         if(w <= 0 || h <= 0) return;
1061         int left_boundary = left_image->get_w_fixed();
1062         int right_boundary = w - right_image->get_w_fixed();
1063         for(int i = 0; i < w; )
1064         {
1065                 BC_Pixmap *image;
1066
1067                 if(i < left_boundary)
1068                         image = left_image;
1069                 else
1070                 if(i < right_boundary)
1071                         image = mid_image;
1072                 else
1073                         image = right_image;
1074
1075                 int output_w = image->get_w_fixed();
1076
1077                 if(i < left_boundary)
1078                 {
1079                         if(i + output_w > left_boundary) output_w = left_boundary - i;
1080                 }
1081                 else
1082                 if(i < right_boundary)
1083                 {
1084                         if(i + output_w > right_boundary) output_w = right_boundary - i;
1085                 }
1086                 else
1087                         if(i + output_w > w) output_w = w - i;
1088
1089                 image->write_drawable(pixmap ? pixmap->opaque_pixmap : this->pixmap->opaque_pixmap,
1090                                 x + i,
1091                                 y,
1092                                 output_w,
1093                                 h,
1094                                 0,
1095                                 0);
1096
1097                 i += output_w;
1098         }
1099 }
1100 // 3 segments in separate vframes.  Obsolete.
1101 void BC_WindowBase::draw_3segment(int x,
1102         int y,
1103         int w,
1104         int h,
1105         VFrame *left_image,
1106         VFrame *mid_image,
1107         VFrame *right_image,
1108         BC_Pixmap *pixmap)
1109 {
1110         if(w <= 0 || h <= 0) return;
1111         int left_boundary = left_image->get_w_fixed();
1112         int right_boundary = w - right_image->get_w_fixed();
1113
1114
1115         for(int i = 0; i < w; )
1116         {
1117                 VFrame *image;
1118
1119                 if(i < left_boundary)
1120                         image = left_image;
1121                 else
1122                 if(i < right_boundary)
1123                         image = mid_image;
1124                 else
1125                         image = right_image;
1126
1127                 int output_w = image->get_w_fixed();
1128
1129                 if(i < left_boundary)
1130                 {
1131                         if(i + output_w > left_boundary) output_w = left_boundary - i;
1132                 }
1133                 else
1134                 if(i < right_boundary)
1135                 {
1136                         if(i + output_w > right_boundary) output_w = right_boundary - i;
1137                 }
1138                 else
1139                         if(i + output_w > w) output_w = w - i;
1140
1141                 if(image)
1142                         draw_vframe(image,
1143                                         x + i,
1144                                         y,
1145                                         output_w,
1146                                         h,
1147                                         0,
1148                                         0,
1149                                         0,
1150                                         0,
1151                                         pixmap);
1152
1153                 if(output_w == 0) break;
1154                 i += output_w;
1155         }
1156 }
1157
1158 // Draw all 3 segments in a single vframe for a changing level
1159
1160 // total_x
1161 // <------>
1162 // total_w
1163 //         <------------------------------------------------------------>
1164 // x
1165 // |
1166 // w
1167 // <-------------------------------------------------------------------->
1168 // output
1169 //         |-------------------|----------------------|------------------|
1170
1171
1172 void BC_WindowBase::draw_3segmenth(int x,
1173                 int y,
1174                 int w,
1175                 VFrame *image,
1176                 BC_Pixmap *pixmap)
1177 {
1178         draw_3segmenth(x,
1179                 y,
1180                 w,
1181                 x,
1182                 w,
1183                 image,
1184                 pixmap);
1185 }
1186
1187 void BC_WindowBase::draw_3segmenth(int x, int y, int w,
1188                 int total_x, int total_w, VFrame *image,
1189                 BC_Pixmap *pixmap)
1190 {
1191         if(total_w <= 0 || w <= 0 || h <= 0) return;
1192         int third_image = image->get_w() / 3;
1193         int half_image = image->get_w() / 2;
1194         //int left_boundary = third_image;
1195         //int right_boundary = total_w - third_image;
1196         int left_in_x = 0;
1197         int left_in_w = third_image;
1198         int left_out_x = total_x;
1199         int left_out_w = third_image;
1200         int right_in_x = image->get_w() - third_image;
1201         int right_in_w = third_image;
1202         int right_out_x = total_x + total_w - third_image;
1203         int right_out_w = third_image;
1204         int center_out_x = total_x + third_image;
1205         int center_out_w = total_w - third_image * 2;
1206         //int image_x, image_w;
1207
1208 //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",
1209 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1210
1211         if(left_out_x < x)
1212         {
1213                 left_in_w -= x - left_out_x;
1214                 left_out_w -= x - left_out_x;
1215                 left_in_x += x - left_out_x;
1216                 left_out_x += x - left_out_x;
1217         }
1218
1219         if(left_out_x + left_out_w > x + w)
1220         {
1221                 left_in_w -= (left_out_x + left_out_w) - (x + w);
1222                 left_out_w -= (left_out_x + left_out_w) - (x + w);
1223         }
1224
1225         if(right_out_x < x)
1226         {
1227                 right_in_w -= x - right_out_x;
1228                 right_out_w -= x - right_out_x;
1229                 right_in_x += x - right_out_x;
1230                 right_out_x += x - right_out_x;
1231         }
1232
1233         if(right_out_x + right_out_w > x + w)
1234         {
1235                 right_in_w -= (right_out_x + right_out_w) - (x + w);
1236                 right_out_w -= (right_out_x + right_out_w) - (x + w);
1237         }
1238
1239         if(center_out_x < x)
1240         {
1241                 center_out_w -= x - center_out_x;
1242                 center_out_x += x - center_out_x;
1243         }
1244
1245         if(center_out_x + center_out_w > x + w)
1246         {
1247                 center_out_w -= (center_out_x + center_out_w) - (x + w);
1248         }
1249
1250         if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1251                 image->get_w(), image->get_h(),
1252                 get_color_model(), 0);
1253         temp_bitmap->match_params(image->get_w(), image->get_h(),
1254                 get_color_model(), 0);
1255         temp_bitmap->read_frame(image,
1256                 0, 0, image->get_w(), image->get_h(), bg_color);
1257 // src width and height are meaningless in video_off mode
1258 //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",
1259 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1260         if(left_out_w > 0) {
1261                 draw_bitmap(temp_bitmap, 0,
1262                         left_out_x, y, left_out_w, image->get_h(),
1263                         left_in_x, 0, -1, -1, pixmap);
1264         }
1265
1266         if(right_out_w > 0) {
1267                 draw_bitmap(temp_bitmap, 0,
1268                         right_out_x, y, right_out_w, image->get_h(),
1269                         right_in_x, 0, -1, -1, pixmap);
1270         }
1271
1272         for( int pixel = center_out_x;
1273                  pixel < center_out_x + center_out_w;
1274                  pixel += half_image ) {
1275                 int fragment_w = half_image;
1276                 if(fragment_w + pixel > center_out_x + center_out_w)
1277                         fragment_w = (center_out_x + center_out_w) - pixel;
1278
1279 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1280                 draw_bitmap(temp_bitmap, 0,
1281                         pixel, y, fragment_w, image->get_h(),
1282                         third_image, 0, -1, -1, pixmap);
1283         }
1284
1285 }
1286
1287 void BC_WindowBase::draw_3segmenth(int x, int y, int w, int total_x, int total_w,
1288                 BC_Pixmap *src, BC_Pixmap *dst)
1289 {
1290         if(w <= 0 || total_w <= 0) return;
1291         if(!src) printf("BC_WindowBase::draw_3segmenth src=0\n");
1292         int quarter_src = src->get_w() / 4;
1293         int half_src = src->get_w() / 2;
1294         //int left_boundary = quarter_src;
1295         //int right_boundary = total_w - quarter_src;
1296         int left_in_x = 0;
1297         int left_in_w = quarter_src;
1298         int left_out_x = total_x;
1299         int left_out_w = quarter_src;
1300         int right_in_x = src->get_w() - quarter_src;
1301         int right_in_w = quarter_src;
1302         int right_out_x = total_x + total_w - quarter_src;
1303         int right_out_w = quarter_src;
1304         int center_out_x = total_x + quarter_src;
1305         int center_out_w = total_w - quarter_src * 2;
1306         //int src_x, src_w;
1307
1308 //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",
1309 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1310
1311         if(left_out_x < x)
1312         {
1313                 left_in_w -= x - left_out_x;
1314                 left_out_w -= x - left_out_x;
1315                 left_in_x += x - left_out_x;
1316                 left_out_x += x - left_out_x;
1317         }
1318
1319         if(left_out_x + left_out_w > x + w)
1320         {
1321                 left_in_w -= (left_out_x + left_out_w) - (x + w);
1322                 left_out_w -= (left_out_x + left_out_w) - (x + w);
1323         }
1324
1325         if(right_out_x < x)
1326         {
1327                 right_in_w -= x - right_out_x;
1328                 right_out_w -= x - right_out_x;
1329                 right_in_x += x - right_out_x;
1330                 right_out_x += x - right_out_x;
1331         }
1332
1333         if(right_out_x + right_out_w > x + w)
1334         {
1335                 right_in_w -= (right_out_x + right_out_w) - (x + w);
1336                 right_out_w -= (right_out_x + right_out_w) - (x + w);
1337         }
1338
1339         if(center_out_x < x)
1340         {
1341                 center_out_w -= x - center_out_x;
1342                 center_out_x += x - center_out_x;
1343         }
1344
1345         if(center_out_x + center_out_w > x + w)
1346         {
1347                 center_out_w -= (center_out_x + center_out_w) - (x + w);
1348         }
1349
1350
1351 //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",
1352 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1353         if(left_out_w > 0)
1354         {
1355                 draw_pixmap(src,
1356                         left_out_x,
1357                         y,
1358                         left_out_w,
1359                         src->get_h(),
1360                         left_in_x,
1361                         0,
1362                         dst);
1363         }
1364
1365         if(right_out_w > 0)
1366         {
1367                 draw_pixmap(src,
1368                         right_out_x,
1369                         y,
1370                         right_out_w,
1371                         src->get_h(),
1372                         right_in_x,
1373                         0,
1374                         dst);
1375         }
1376
1377         for(int pixel = center_out_x;
1378                 pixel < center_out_x + center_out_w;
1379                 pixel += half_src)
1380         {
1381                 int fragment_w = half_src;
1382                 if(fragment_w + pixel > center_out_x + center_out_w)
1383                         fragment_w = (center_out_x + center_out_w) - pixel;
1384
1385 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1386                 draw_pixmap(src,
1387                         pixel,
1388                         y,
1389                         fragment_w,
1390                         src->get_h(),
1391                         quarter_src,
1392                         0,
1393                         dst);
1394         }
1395
1396 }
1397
1398
1399 void BC_WindowBase::draw_3segmenth(int x,
1400                 int y,
1401                 int w,
1402                 BC_Pixmap *src,
1403                 BC_Pixmap *dst)
1404 {
1405         if(w <= 0) return;
1406         int third_image = src->get_w() / 3;
1407         int half_output = w / 2;
1408         //int left_boundary = third_image;
1409         //int right_boundary = w - third_image;
1410         int left_in_x = 0;
1411         int left_in_w = third_image;
1412         int left_out_x = x;
1413         int left_out_w = third_image;
1414         int right_in_x = src->get_w() - third_image;
1415         int right_in_w = third_image;
1416         int right_out_x = x + w - third_image;
1417         int right_out_w = third_image;
1418         //int image_x, image_w;
1419
1420 //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",
1421 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1422
1423         if(left_out_w > half_output)
1424         {
1425                 left_in_w -= left_out_w - half_output;
1426                 left_out_w -= left_out_w - half_output;
1427         }
1428
1429         if(right_out_x < x + half_output)
1430         {
1431                 right_in_w -= x + half_output - right_out_x;
1432                 right_out_w -= x + half_output - right_out_x;
1433                 right_in_x += x + half_output - right_out_x;
1434                 right_out_x += x + half_output - right_out_x;
1435         }
1436
1437 //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",
1438 //      left_out_x, left_out_w, center_out_x, center_out_w, right_out_x, right_out_w);
1439         if(left_out_w > 0)
1440         {
1441                 draw_pixmap(src,
1442                         left_out_x,
1443                         y,
1444                         left_out_w,
1445                         src->get_h(),
1446                         left_in_x,
1447                         0,
1448                         dst);
1449         }
1450
1451         if(right_out_w > 0)
1452         {
1453                 draw_pixmap(src,
1454                         right_out_x,
1455                         y,
1456                         right_out_w,
1457                         src->get_h(),
1458                         right_in_x,
1459                         0,
1460                         dst);
1461         }
1462
1463         for(int pixel = left_out_x + left_out_w;
1464                 pixel < right_out_x;
1465                 pixel += third_image)
1466         {
1467                 int fragment_w = third_image;
1468                 if(fragment_w + pixel > right_out_x)
1469                         fragment_w = right_out_x - pixel;
1470
1471 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1472                 draw_pixmap(src,
1473                         pixel,
1474                         y,
1475                         fragment_w,
1476                         src->get_h(),
1477                         third_image,
1478                         0,
1479                         dst);
1480         }
1481
1482 }
1483
1484
1485
1486
1487
1488
1489
1490 void BC_WindowBase::draw_3segmentv(int x,
1491                 int y,
1492                 int h,
1493                 VFrame *src,
1494                 BC_Pixmap *dst)
1495 {
1496         if(h <= 0) return;
1497         int third_image = src->get_h() / 3;
1498         int half_output = h / 2;
1499         //int left_boundary = third_image;
1500         //int right_boundary = h - third_image;
1501         int left_in_y = 0;
1502         int left_in_h = third_image;
1503         int left_out_y = y;
1504         int left_out_h = third_image;
1505         int right_in_y = src->get_h() - third_image;
1506         int right_in_h = third_image;
1507         int right_out_y = y + h - third_image;
1508         int right_out_h = third_image;
1509         //int image_y, image_h;
1510
1511
1512         if(left_out_h > half_output)
1513         {
1514                 left_in_h -= left_out_h - half_output;
1515                 left_out_h -= left_out_h - half_output;
1516         }
1517
1518         if(right_out_y < y + half_output)
1519         {
1520                 right_in_h -= y + half_output - right_out_y;
1521                 right_out_h -= y + half_output - right_out_y;
1522                 right_in_y += y + half_output - right_out_y;
1523                 right_out_y += y + half_output - right_out_y;
1524         }
1525
1526
1527         if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1528                 src->get_w(),
1529                 src->get_h(),
1530                 get_color_model(),
1531                 0);
1532         temp_bitmap->match_params(src->get_w(),
1533                 src->get_h(),
1534                 get_color_model(),
1535                 0);
1536         temp_bitmap->read_frame(src,
1537                 0, 0, src->get_w(), src->get_h(), bg_color);
1538
1539
1540         if(left_out_h > 0)
1541         {
1542                 draw_bitmap(temp_bitmap,
1543                         0,
1544                         x,
1545                         left_out_y,
1546                         src->get_w(),
1547                         left_out_h,
1548                         0,
1549                         left_in_y,
1550                         -1,
1551                         -1,
1552                         dst);
1553         }
1554
1555         if(right_out_h > 0)
1556         {
1557                 draw_bitmap(temp_bitmap,
1558                         0,
1559                         x,
1560                         right_out_y,
1561                         src->get_w(),
1562                         right_out_h,
1563                         0,
1564                         right_in_y,
1565                         -1,
1566                         -1,
1567                         dst);
1568         }
1569
1570         for(int pixel = left_out_y + left_out_h;
1571                 pixel < right_out_y;
1572                 pixel += third_image)
1573         {
1574                 int fragment_h = third_image;
1575                 if(fragment_h + pixel > right_out_y)
1576                         fragment_h = right_out_y - pixel;
1577
1578 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1579                 draw_bitmap(temp_bitmap,
1580                         0,
1581                         x,
1582                         pixel,
1583                         src->get_w(),
1584                         fragment_h,
1585                         0,
1586                         third_image,
1587                         -1,
1588                         -1,
1589                         dst);
1590         }
1591 }
1592
1593 void BC_WindowBase::draw_3segmentv(int x,
1594                 int y,
1595                 int h,
1596                 BC_Pixmap *src,
1597                 BC_Pixmap *dst)
1598 {
1599         if(h <= 0) return;
1600         int third_image = src->get_h() / 3;
1601         int half_output = h / 2;
1602         //int left_boundary = third_image;
1603         //int right_boundary = h - third_image;
1604         int left_in_y = 0;
1605         int left_in_h = third_image;
1606         int left_out_y = y;
1607         int left_out_h = third_image;
1608         int right_in_y = src->get_h() - third_image;
1609         int right_in_h = third_image;
1610         int right_out_y = y + h - third_image;
1611         int right_out_h = third_image;
1612         //int image_y, image_h;
1613
1614
1615         if(left_out_h > half_output)
1616         {
1617                 left_in_h -= left_out_h - half_output;
1618                 left_out_h -= left_out_h - half_output;
1619         }
1620
1621         if(right_out_y < y + half_output)
1622         {
1623                 right_in_h -= y + half_output - right_out_y;
1624                 right_out_h -= y + half_output - right_out_y;
1625                 right_in_y += y + half_output - right_out_y;
1626                 right_out_y += y + half_output - right_out_y;
1627         }
1628
1629         if(left_out_h > 0)
1630         {
1631                 draw_pixmap(src,
1632                         x,
1633                         left_out_y,
1634                         src->get_w(),
1635                         left_out_h,
1636                         0,
1637                         left_in_y,
1638                         dst);
1639         }
1640
1641         if(right_out_h > 0)
1642         {
1643                 draw_pixmap(src,
1644                         x,
1645                         right_out_y,
1646                         src->get_w(),
1647                         right_out_h,
1648                         0,
1649                         right_in_y,
1650                         dst);
1651         }
1652
1653         for(int pixel = left_out_y + left_out_h;
1654                 pixel < right_out_y;
1655                 pixel += third_image)
1656         {
1657                 int fragment_h = third_image;
1658                 if(fragment_h + pixel > right_out_y)
1659                         fragment_h = right_out_y - pixel;
1660
1661 //printf("BC_WindowBase::draw_3segment 2 pixel=%d fragment_w=%d\n", pixel, fragment_w);
1662                 draw_pixmap(src,
1663                         x,
1664                         pixel,
1665                         src->get_w(),
1666                         fragment_h,
1667                         0,
1668                         third_image,
1669                         dst);
1670         }
1671 }
1672
1673
1674 void BC_WindowBase::draw_9segment(int x,
1675                 int y,
1676                 int w,
1677                 int h,
1678                 BC_Pixmap *src,
1679                 BC_Pixmap *dst)
1680 {
1681         if(w <= 0 || h <= 0) return;
1682
1683         int in_x_third = src->get_w() / 3;
1684         int in_y_third = src->get_h() / 3;
1685         int out_x_half = w / 2;
1686         int out_y_half = h / 2;
1687
1688         int in_x1 = 0;
1689         int in_y1 = 0;
1690         int out_x1 = 0;
1691         int out_y1 = 0;
1692         int in_x2 = MIN(in_x_third, out_x_half);
1693         int in_y2 = MIN(in_y_third, out_y_half);
1694         int out_x2 = in_x2;
1695         int out_y2 = in_y2;
1696
1697         int out_x3 = MAX(w - out_x_half, w - in_x_third);
1698         int out_x4 = w;
1699         int in_x3 = src->get_w() - (out_x4 - out_x3);
1700         //int in_x4 = src->get_w();
1701
1702         int out_y3 = MAX(h - out_y_half, h - in_y_third);
1703         int out_y4 = h;
1704         int in_y3 = src->get_h() - (out_y4 - out_y3);
1705         //int in_y4 = src->get_h();
1706
1707 // Segment 1
1708         draw_pixmap(src,
1709                 x + out_x1,
1710                 y + out_y1,
1711                 out_x2 - out_x1,
1712                 out_y2 - out_y1,
1713                 in_x1,
1714                 in_y1,
1715                 dst);
1716
1717
1718 // Segment 2 * n
1719         for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
1720         {
1721                 if(out_x3 - i > 0)
1722                 {
1723                         int w = MIN(in_x3 - in_x2, out_x3 - i);
1724                         draw_pixmap(src,
1725                                 x + i,
1726                                 y + out_y1,
1727                                 w,
1728                                 out_y2 - out_y1,
1729                                 in_x2,
1730                                 in_y1,
1731                                 dst);
1732                 }
1733         }
1734
1735
1736
1737
1738
1739 // Segment 3
1740         draw_pixmap(src,
1741                 x + out_x3,
1742                 y + out_y1,
1743                 out_x4 - out_x3,
1744                 out_y2 - out_y1,
1745                 in_x3,
1746                 in_y1,
1747                 dst);
1748
1749
1750
1751 // Segment 4 * n
1752         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
1753         {
1754                 if(out_y3 - i > 0)
1755                 {
1756                         int h = MIN(in_y3 - in_y2, out_y3 - i);
1757                         draw_pixmap(src,
1758                                 x + out_x1,
1759                                 y + i,
1760                                 out_x2 - out_x1,
1761                                 h,
1762                                 in_x1,
1763                                 in_y2,
1764                                 dst);
1765                 }
1766         }
1767
1768
1769 // Segment 5 * n * n
1770         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2 /* in_y_third */)
1771         {
1772                 if(out_y3 - i > 0)
1773                 {
1774                         int h = MIN(in_y3 - in_y2 /* in_y_third */, out_y3 - i);
1775
1776
1777                         for(int j = out_x2; j < out_x3; j += in_x3 - in_x2 /* in_x_third */)
1778                         {
1779                                 int w = MIN(in_x3 - in_x2 /* in_x_third */, out_x3 - j);
1780                                 if(out_x3 - j > 0)
1781                                         draw_pixmap(src,
1782                                                 x + j,
1783                                                 y + i,
1784                                                 w,
1785                                                 h,
1786                                                 in_x2,
1787                                                 in_y2,
1788                                                 dst);
1789                         }
1790                 }
1791         }
1792
1793 // Segment 6 * n
1794         for(int i = out_y2; i < out_y3; i += in_y3 - in_y2)
1795         {
1796                 if(out_y3 - i > 0)
1797                 {
1798                         int h = MIN(in_y3 - in_y2, out_y3 - i);
1799                         draw_pixmap(src,
1800                                 x + out_x3,
1801                                 y + i,
1802                                 out_x4 - out_x3,
1803                                 h,
1804                                 in_x3,
1805                                 in_y2,
1806                                 dst);
1807                 }
1808         }
1809
1810
1811
1812
1813 // Segment 7
1814         draw_pixmap(src,
1815                 x + out_x1,
1816                 y + out_y3,
1817                 out_x2 - out_x1,
1818                 out_y4 - out_y3,
1819                 in_x1,
1820                 in_y3,
1821                 dst);
1822
1823
1824 // Segment 8 * n
1825         for(int i = out_x2; i < out_x3; i += in_x3 - in_x2)
1826         {
1827                 if(out_x3 - i > 0)
1828                 {
1829                         int w = MIN(in_x3 - in_y2, out_x3 - i);
1830                         draw_pixmap(src,
1831                                 x + i,
1832                                 y + out_y3,
1833                                 w,
1834                                 out_y4 - out_y3,
1835                                 in_x2,
1836                                 in_y3,
1837                                 dst);
1838                 }
1839         }
1840
1841
1842
1843 // Segment 9
1844         draw_pixmap(src,
1845                 x + out_x3,
1846                 y + out_y3,
1847                 out_x4 - out_x3,
1848                 out_y4 - out_y3,
1849                 in_x3,
1850                 in_y3,
1851                 dst);
1852 }
1853
1854
1855 void BC_WindowBase::draw_9segment(int x, int y, int w, int h,
1856                 VFrame *src, BC_Pixmap *dst)
1857 {
1858         if(w <= 0 || h <= 0) return;
1859
1860         int in_x_third = src->get_w() / 3;
1861         int in_y_third = src->get_h() / 3;
1862         int out_x_half = w / 2;
1863         int out_y_half = h / 2;
1864
1865         int in_x1 = 0;
1866         int in_y1 = 0;
1867         int out_x1 = 0;
1868         int out_y1 = 0;
1869         int in_x2 = MIN(in_x_third, out_x_half);
1870         int in_y2 = MIN(in_y_third, out_y_half);
1871         int out_x2 = in_x2;
1872         int out_y2 = in_y2;
1873
1874         int out_x3 = MAX(w - out_x_half, w - in_x_third);
1875         int out_x4 = w;
1876         int in_x3 = src->get_w() - (out_x4 - out_x3);
1877         int in_x4 = src->get_w();
1878
1879         int out_y3 = MAX(h - out_y_half, h - in_y_third);
1880         int out_y4 = h;
1881         int in_y3 = src->get_h() - (out_y4 - out_y3);
1882         int in_y4 = src->get_h();
1883
1884 //printf("PFCFrame::draw_9segment 1 %d %d %d %d\n", out_x1, out_x2, out_x3, out_x4);
1885 //printf("PFCFrame::draw_9segment 2 %d %d %d %d\n", in_x1, in_x2, in_x3, in_x4);
1886 //printf("PFCFrame::draw_9segment 2 %d %d %d %d\n", in_y1, in_y2, in_y3, in_y4);
1887
1888         if(!temp_bitmap) temp_bitmap = new BC_Bitmap(top_level,
1889                 src->get_w(),
1890                 src->get_h(),
1891                 get_color_model(),
1892                 0);
1893         temp_bitmap->match_params(src->get_w(),
1894                 src->get_h(),
1895                 get_color_model(),
1896                 0);
1897         temp_bitmap->read_frame(src,
1898                 0, 0, src->get_w(), src->get_h(), bg_color);
1899
1900 // Segment 1
1901         draw_bitmap(temp_bitmap, 0,
1902                 x + out_x1, y + out_y1, out_x2 - out_x1, out_y2 - out_y1,
1903                 in_x1, in_y1, in_x2 - in_x1, in_y2 - in_y1,
1904                 dst);
1905
1906 // Segment 2 * n
1907         for( int i = out_x2; i < out_x3; i += in_x3 - in_x2 ) {
1908                 if( out_x3 - i > 0 ) {
1909                         int w = MIN(in_x3 - in_x2, out_x3 - i);
1910                         draw_bitmap(temp_bitmap, 0,
1911                                 x + i, y + out_y1, w, out_y2 - out_y1,
1912                                 in_x2, in_y1, w, in_y2 - in_y1,
1913                                 dst);
1914                 }
1915         }
1916
1917 // Segment 3
1918         draw_bitmap(temp_bitmap, 0,
1919                 x + out_x3, y + out_y1, out_x4 - out_x3, out_y2 - out_y1,
1920                 in_x3, in_y1, in_x4 - in_x3, in_y2 - in_y1,
1921                 dst);
1922
1923 // Segment 4 * n
1924         for( int i = out_y2; i < out_y3; i += in_y3 - in_y2 ) {
1925                 if( out_y3 - i > 0 ) {
1926                         int h = MIN(in_y3 - in_y2, out_y3 - i);
1927                         draw_bitmap(temp_bitmap, 0,
1928                                 x + out_x1, y + i, out_x2 - out_x1, h,
1929                                 in_x1, in_y2, in_x2 - in_x1, h,
1930                                 dst);
1931                 }
1932         }
1933
1934 // Segment 5 * n * n
1935         for( int i = out_y2; i < out_y3; i += in_y3 - in_y2 ) {
1936                 if( out_y3 - i > 0 ) {
1937                         int h = MIN(in_y3 - in_y2, out_y3 - i);
1938
1939                         for( int j = out_x2; j < out_x3; j += in_x3 - in_x2 ) {
1940                                 int w = MIN(in_x3 - in_x2, out_x3 - j);
1941                                 if(out_x3 - j > 0)
1942                                         draw_bitmap(temp_bitmap, 0,
1943                                                 x + j, y + i, w, h,
1944                                                 in_x2, in_y2, w, h,
1945                                                 dst);
1946                         }
1947                 }
1948         }
1949
1950 // Segment 6 * n
1951         for( int i = out_y2; i < out_y3; i += in_y_third ) {
1952                 if( out_y3 - i > 0 ) {
1953                         int h = MIN(in_y_third, out_y3 - i);
1954                         draw_bitmap(temp_bitmap, 0,
1955                                 x + out_x3, y + i, out_x4 - out_x3, h,
1956                                 in_x3, in_y2, in_x4 - in_x3, h,
1957                                 dst);
1958                 }
1959         }
1960
1961 // Segment 7
1962         draw_bitmap(temp_bitmap, 0,
1963                 x + out_x1, y + out_y3, out_x2 - out_x1, out_y4 - out_y3,
1964                 in_x1, in_y3, in_x2 - in_x1, in_y4 - in_y3,
1965                 dst);
1966
1967 // Segment 8 * n
1968         for( int i = out_x2; i < out_x3; i += in_x_third ) {
1969                 if( out_x3 - i > 0 ) {
1970                         int w = MIN(in_x_third, out_x3 - i);
1971                         draw_bitmap(temp_bitmap, 0,
1972                                 x + i, y + out_y3, w, out_y4 - out_y3,
1973                                 in_x2, in_y3, w, in_y4 - in_y3,
1974                                 dst);
1975                 }
1976         }
1977
1978 // Segment 9
1979         draw_bitmap(temp_bitmap, 0,
1980                 x + out_x3, y + out_y3, out_x4 - out_x3, out_y4 - out_y3,
1981                 in_x3, in_y3, in_x4 - in_x3, in_y4 - in_y3,
1982                 dst);
1983 }
1984