1 /*
2 * This file is part of the XForms library package.
3 *
4 * XForms is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation; either version 2.1, or
7 * (at your option) any later version.
8 *
9 * XForms is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with XForms. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18
19 /**
20 * \file fldraw.c
21 *
22 * This file is part of the XForms library package.
23 * Copyright (c) 1996-2002 T.C. Zhao and Mark Overmars
24 * All rights reserved.
25 *
26 * High level drawing routines. Uses the routines defined in xdraw.c
27 */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include "include/forms.h"
34 #include "flinternal.h"
35
36
37 #define FLI_SHADOW_COL FL_RIGHT_BCOL
38
39
40 static void fl_foldertab_box( int,
41 FL_Coord,
42 FL_Coord,
43 FL_Coord,
44 FL_Coord,
45 FL_COLOR,
46 int );
47
48
49 /*******************************************************************
50 * Rectangle routines
51 ****************************************************************{**/
52
53 /***************************************
54 * Make an arbitary rectangle have positive width and height
55 ***************************************/
56
57 void
fli_canonicalize_rect(FL_Coord * x,FL_Coord * y,FL_Coord * w,FL_Coord * h)58 fli_canonicalize_rect( FL_Coord * x,
59 FL_Coord * y,
60 FL_Coord * w,
61 FL_Coord * h )
62 {
63 if ( *w < 0 )
64 {
65 *w = -*w;
66 *x -= *w;
67 }
68
69 if ( *h < 0 )
70 {
71 *h = -*h;
72 *y -= *h;
73 }
74 }
75
76
77 /***************************************
78 * Draw a filled rectangle with a black boundary. Also compensates
79 * for the inconsistency in Xlib
80 ***************************************/
81
82 int flrectboundcolor = FL_BLACK;
83
84 void
fl_rectbound(FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,FL_COLOR col)85 fl_rectbound( FL_Coord x,
86 FL_Coord y,
87 FL_Coord w,
88 FL_Coord h,
89 FL_COLOR col )
90 {
91 fli_canonicalize_rect( &x, &y, &w, &h );
92
93 /* 0 width has special meaning in Xlib */
94
95 if ( h < 2 )
96 h = 2;
97 if ( w < 2 )
98 w = 2;
99
100 fl_rectangle( 1, x + 1, y + 1, w - 1, h - 1, col );
101 fl_rectangle( 0, x, y, w, h, flrectboundcolor );
102 }
103
104
105 /****** End of rectangle routines ***********************}***/
106
107
108 #define MAX_RADIUS 18
109
110 static double offset[ ] = { 0.0, 0.07612, 0.29289, 0.61732, 1.0 };
111
112 #define RN ( sizeof offset / sizeof *offset )
113
114
115 /***************************************
116 ***************************************/
117
118 static void
compute_round_corners(FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,FL_POINT * point)119 compute_round_corners( FL_Coord x,
120 FL_Coord y,
121 FL_Coord w,
122 FL_Coord h,
123 FL_POINT * point )
124 {
125 size_t i;
126 double rs = 0.45 * FL_min( w, h );
127 static double old_rs = -1;
128 static FL_Coord o[ RN ];
129
130 if ( rs > MAX_RADIUS )
131 rs = MAX_RADIUS;
132 if ( rs < 0 )
133 rs = 0;
134
135 if ( rs != old_rs )
136 {
137 for ( i = 0; i < RN; i++ )
138 o[ i ] = FL_crnd( offset[ i ] * rs );
139 old_rs = rs;
140 }
141
142 for ( i = 0; i < RN; i++, point++ )
143 {
144 point->x = x + o[ RN - i - 1 ];
145 point->y = y + o[ i ];
146 }
147
148 for ( i = 0; i < RN; i++, point++ )
149 {
150 point->x = x + o[ i ];
151 point->y = y + h - 1 - o[ RN - i - 1 ];
152 }
153
154 for ( i = 0; i < RN; i++, point++ )
155 {
156 point->x = x + w - 1 - o[ RN - i - 1 ];
157 point->y = y + h - 1 - o[ i ];
158 }
159
160 for ( i = 0; i < RN; i++, point++ )
161 {
162 point->x = x + w - 1 - o[ i ];
163 point->y = y + o[ RN - i - 1 ];
164 }
165 }
166
167
168 /***************************************
169 ***************************************/
170
171 void
fl_roundrectangle(int fill,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,FL_COLOR col)172 fl_roundrectangle( int fill,
173 FL_Coord x,
174 FL_Coord y,
175 FL_Coord w,
176 FL_Coord h,
177 FL_COLOR col )
178 {
179 FL_POINT point[ 4 * RN + 1 ]; /* need one extra for closing of polygon! */
180
181 compute_round_corners( x, y, w, h, point );
182 fl_polygon( fill, point, 4 * RN, col );
183 }
184
185
186 #define SHRINK( x, y, w, h, d ) \
187 do { x += ( d ); \
188 y += ( d ); \
189 w -= 2 * ( d ); \
190 h -= 2 * ( d ); \
191 } while ( 0 )
192
193
194 /***************************************
195 ***************************************/
196
197 static void
fl_rounded3dbox(int style,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,FL_COLOR col,int bw)198 fl_rounded3dbox( int style,
199 FL_Coord x,
200 FL_Coord y,
201 FL_Coord w,
202 FL_Coord h,
203 FL_COLOR col,
204 int bw )
205 {
206 FL_POINT point[ 4 * RN + 1 ]; /* on extra for closing of curve */
207 int lw = FL_abs( bw );
208 int n = 4 * RN,
209 olw;
210
211 SHRINK( x, y, w, h, ( int ) ( lw / 2 ) );
212
213 compute_round_corners( x, y, w, h, point );
214 fl_polyf( point, n, col );
215
216 olw = fl_get_linewidth( );
217 fl_linewidth( lw );
218
219 /* draw the shadow */
220
221 if ( style == FL_ROUNDED3D_UPBOX )
222 {
223 fl_lines( point, 2 * RN, FL_LEFT_BCOL );
224 fl_lines( point + 2 * RN - 3, RN + 1, FL_BOTTOM_BCOL );
225 fl_lines( point + 3 * RN - 4, RN + 2, FL_RIGHT_BCOL );
226 point[ n ] = point[ 0 ];
227 fl_lines( point + n - 3, 4, FL_TOP_BCOL );
228 }
229 else
230 {
231 fl_lines( point, 2 * RN, FL_BOTTOM_BCOL );
232 fl_lines( point + 2 * RN - 3, RN + 1, FL_TOP_BCOL );
233 fl_lines( point + 3 * RN - 4, RN + 2, FL_LEFT_BCOL );
234 point[ n ] = point[ 0 ];
235 fl_lines( point + n - 3, 4, FL_BOTTOM_BCOL );
236 }
237
238 fl_linewidth( olw );
239
240 if ( bw > 0 && fli_dithered( fl_vmode ) )
241 {
242 compute_round_corners( x, y, w, h, point );
243 fl_polyl( point, n, FL_BLACK );
244 }
245 }
246
247
248 /***************************************
249 ***************************************/
250
251 static void
fl_oval3dbox(int style,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,FL_COLOR col,int bw)252 fl_oval3dbox( int style,
253 FL_Coord x,
254 FL_Coord y,
255 FL_Coord w,
256 FL_Coord h,
257 FL_COLOR col,
258 int bw )
259 {
260 int absbw = FL_abs( bw ),
261 olw = fl_get_linewidth( );
262 int extra = 1 + ( absbw > 3 );
263 int xx,
264 yy,
265 ww,
266 hh;
267
268 SHRINK( x, y, w, h, ( int ) ( absbw / 2 ) );
269 fl_pieslice( 1, x, y, w, h, 0, 3600, col );
270
271 xx = x + extra;
272 yy = y + extra;
273 ww = w - 2 * extra;
274 hh = h - 2 * extra;
275
276 fl_linewidth( absbw );
277
278 if ( style == FL_OVAL3D_UPBOX )
279 {
280 fl_pieslice( 0, x, y, w, h, 450, 2250, FL_TOP_BCOL );
281 fl_pieslice( 0, x, y, w, h, 0, 450, FL_BOTTOM_BCOL );
282 fl_pieslice( 0, x, y, w, h, 2250, 3600, FL_BOTTOM_BCOL );
283 }
284 else if ( style == FL_OVAL3D_FRAMEBOX )
285 {
286 fl_linewidth( 0 );
287
288 fl_pieslice( 0, x, y, w, h, 450, 2250, FL_BOTTOM_BCOL );
289 fl_pieslice( 0, xx, yy, ww, hh, 450, 2250, FL_LEFT_BCOL );
290
291 fl_pieslice( 0, xx, yy, ww, hh, 0, 450, FL_BOTTOM_BCOL );
292 fl_pieslice( 0, x, y, w, h, 0, 450, FL_LEFT_BCOL );
293
294 fl_pieslice( 0, xx, yy, ww, hh, 2250, 3600, FL_BOTTOM_BCOL );
295 fl_pieslice( 0, x, y, w, h, 2250, 3600, FL_LEFT_BCOL );
296 }
297 else if ( style == FL_OVAL3D_EMBOSSEDBOX )
298 {
299 fl_linewidth( 0 );
300
301 fl_pieslice( 0, x, y, w, h, 450, 2250, FL_LEFT_BCOL );
302 fl_pieslice( 0, xx, yy, ww, hh, 450, 2250, FL_BOTTOM_BCOL );
303
304 fl_pieslice( 0, xx, yy, ww, hh, 0, 450, FL_LEFT_BCOL );
305 fl_pieslice( 0, x, y, w, h, 0, 450, FL_BOTTOM_BCOL );
306
307 fl_pieslice( 0, xx, yy, ww, hh, 2250, 3600, FL_LEFT_BCOL );
308 fl_pieslice( 0, x, y, w, h, 2250, 3600, FL_BOTTOM_BCOL );
309 }
310 else
311 {
312 fl_pieslice( 0, x, y, w, h, 450, 2250, FL_BOTTOM_BCOL );
313 fl_pieslice( 0, x, y, w, h, 0, 450, FL_TOP_BCOL );
314 fl_pieslice( 0, x, y, w, h, 2250, 3600, FL_TOP_BCOL );
315 }
316
317 fl_linewidth( olw );
318
319 if ( fli_dithered( fl_vmode ) )
320 fl_pieslice( 0, x, y, w, h, 0, 3600, FL_BLACK );
321 }
322
323
324 #define SET_POINT( v, xp, yp ) \
325 do { ( v )->x = xp; \
326 ( v )->y = yp; \
327 } while ( 0 )
328
329
330 /***************************************
331 * Draw a rectangular box. TODO: need to change primitive box
332 * drawing using frame
333 ***************************************/
334
335 void
fl_draw_box(int style,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,FL_COLOR c,int bw_in)336 fl_draw_box( int style,
337 FL_Coord x,
338 FL_Coord y,
339 FL_Coord w,
340 FL_Coord h,
341 FL_COLOR c,
342 int bw_in )
343 {
344 FL_POINT vert[ 5 ]; /* need one extra for closing of polygon! */
345 int B,
346 dp = fli_dithered( fl_vmode ),
347 bw = bw_in;
348 FL_Coord cx,
349 cy,
350 cw,
351 ch;
352
353 if ( c == FL_NoColor )
354 c = FL_COL1;
355
356 if ( style == FL_NO_BOX )
357 return;
358
359 if ( ! ( B = ( bw > 0 ) ) )
360 bw = - bw;
361
362 if ( bw == 0 )
363 style = FL_FLAT_BOX;
364
365 /* We must guarantee width of rectangle is larger than 0 */
366
367 if ( w - 2 * bw <= 0 )
368 bw = w / 2 - 1;
369 if ( h - 2 * bw <= 0 )
370 bw = h / 2 - 1;
371
372 if ( w <= 0 || h <= 0 )
373 return;
374
375 switch ( style )
376 {
377 case FL_UP_BOX:
378 fl_rectf( x + bw + B, y + bw + B, w - 2 * bw - 2 * B,
379 h - 2 * bw - 2 * B, c );
380 fl_rectf( x + B, y + B, w - 1 - B, bw, FL_TOP_BCOL );
381 fl_rectf( x + B, y + h - bw - B, w - 1 - B, bw, FL_BOTTOM_BCOL );
382
383 SET_POINT( vert, x + w - B - bw, y + bw + B );
384 SET_POINT( vert + 1, x + w - B - bw, y + h - B - bw );
385 SET_POINT( vert + 2, x + w - B, y + h - B );
386 SET_POINT( vert + 3, x + w - B, y + B );
387 fl_polyf( vert, 4, FL_RIGHT_BCOL );
388
389 /* left trapzoidal */
390
391 SET_POINT( vert, x + B, y + B );
392 SET_POINT( vert + 1, x + B, y + h - B );
393 SET_POINT( vert + 2, x + bw + B, y + h - bw - B );
394 SET_POINT( vert + 3, x + bw + B, y + bw + B );
395
396 fl_polyf( vert, 4, FL_LEFT_BCOL );
397
398 if ( B || fli_dithered( fl_vmode ) )
399 fl_rect( x, y, w - 1, h - 1, FL_RIGHT_BCOL );
400
401 /* special hack for B&W */
402
403 if ( fli_dithered( fl_vmode ) )
404 {
405 if ( bw > 2 )
406 {
407 SET_POINT( vert, x + B, y + B );
408 SET_POINT( vert + 1, x + B + bw - 1, y + bw );
409 SET_POINT( vert + 2, x + w - bw, y + bw );
410
411 fl_lines( vert, 3, FL_BLACK );
412 fl_simple_line( x + B + bw - 1, y + B + bw, x + B + bw - 1,
413 y + h - bw, FL_BLACK );
414 }
415 else
416 fl_rect( x, y, w - 1, h - 1, FL_BLACK );
417 }
418 break;
419
420 case FL_DOWN_BOX:
421 fl_rectf( x + bw, y + bw, w - 2 * bw, h - 2 * bw, c );
422 fl_rectf( x, y + h - bw, w, bw - dp, FL_TOP_BCOL );
423 fl_rectf( x, y, w, bw, FL_BOTTOM_BCOL );
424
425 /* right trapzoid */
426
427 SET_POINT( vert, x + w - bw, y + bw );
428 SET_POINT( vert + 1, x + w - bw, y + h - bw );
429 SET_POINT( vert + 2, x + w - dp, y + h );
430 SET_POINT( vert + 3, x + w - dp, y );
431
432 fl_polyf( vert, 4, FL_LEFT_BCOL );
433
434 /* left trapzoid */
435
436 SET_POINT( vert, x, y );
437 SET_POINT( vert + 1, x, y + h - 1 );
438 SET_POINT( vert + 2, x + bw, y + h - bw );
439 SET_POINT( vert + 3, x + bw, y + bw );
440
441 fl_polyf( vert, 4, FL_RIGHT_BCOL );
442
443 /* special hack for B&W */
444
445 if ( fli_dithered( fl_vmode ) )
446 {
447 SET_POINT( vert, x + B, y + h - 1 );
448 SET_POINT( vert + 1, x + w - 1, y + h - 1 );
449 SET_POINT( vert + 2, x + w - 1, y + B );
450 fl_lines( vert, 3, FL_BLACK );
451 }
452 break;
453
454 case FL_FLAT_BOX:
455 fl_rectf( x, y, w, h, c );
456 break;
457
458 case FL_BORDER_BOX:
459 fl_rectbound( x, y, w - 1, h - 1, c );
460 break;
461
462 case FL_FRAME_BOX:
463 B = bw > 2 ? bw - 2 : 1;
464 fl_draw_box( FL_DOWN_BOX, x, y, w, h, c, 1 );
465 x += B + 1;
466 y += B + 1;
467 w -= 2 * ( B + 1 );
468 h -= 2 * ( B + 1 );
469 fl_draw_frame( FL_UP_FRAME, x, y, w, h, c, -1 );
470 break;
471
472 case FL_EMBOSSED_BOX:
473 B = bw > 2 ? bw - 2 : 1;
474 fl_draw_box( FL_UP_BOX, x, y, w, h, c, -1 );
475 x += B + 1;
476 y += B + 1;
477 w -= 2 * ( B + 1 );
478 h -= 2 * ( B + 1 );
479 fl_draw_frame( FL_DOWN_FRAME, x, y, w, h, c, 1 );
480 break;
481
482 case FL_ROUNDED_BOX:
483 fl_roundrectf( x + 1, y + 1, w - 1, h - 1, c );
484 fl_roundrect( x, y, w, h, FL_BLACK );
485 break;
486
487 case FL_ROUNDED3D_UPBOX:
488 case FL_ROUNDED3D_DOWNBOX:
489 fl_rounded3dbox( style, x, y, w, h, c, bw );
490 break;
491
492 case FL_SHADOW_BOX:
493 bw++;
494 fl_rectf( x + bw, y + h - bw, w - bw, bw, FLI_SHADOW_COL );
495 fl_rectf( x + w - bw, y + bw, bw, h - bw, FLI_SHADOW_COL );
496 fl_rectbound( x, y, w - bw, h - bw, c );
497 break;
498
499 case FL_RSHADOW_BOX:
500 if ( w > 70 && h > 70 )
501 bw++;
502
503 if ( fl_get_clipping( 1, &cx, &cy, &cw, &ch )
504 && ( cw <= 0 || ch <= 0 ) )
505 break;
506
507 /* Draw the shadow, raw it several times with clipping */
508
509 fl_roundrectf( x + bw, y + bw, w - bw, h - bw, FLI_SHADOW_COL );
510
511 /* Draw the box */
512
513 fli_set_additional_clipping( x, y, w, h );
514 fl_roundrectf( x + 1, y + 1, w - 1 - bw, h - 1 - bw, c );
515 fl_roundrect( x, y, w - bw, h - bw, FL_BLACK );
516 fl_set_clipping( cx, cy, cw, ch );
517 break;
518
519 case FL_RFLAT_BOX:
520 fl_roundrectf( x, y, w, h, c );
521 break;
522
523 case FL_OVAL_BOX:
524 fl_oval( 1, x + 1, y + 1, w - 1, h - 1, c );
525 fl_oval( 0, x + 1, y + 1, w - 2, h - 2, FL_BLACK );
526 break;
527
528 case FL_OVAL3D_UPBOX:
529 case FL_OVAL3D_DOWNBOX:
530 case FL_OVAL3D_FRAMEBOX:
531 case FL_OVAL3D_EMBOSSEDBOX:
532 fl_oval3dbox( style, x, y, w, h, c, bw_in );
533 break;
534
535 case FL_TOPTAB_UPBOX:
536 case FL_SELECTED_TOPTAB_UPBOX:
537 case FL_BOTTOMTAB_UPBOX:
538 case FL_SELECTED_BOTTOMTAB_UPBOX:
539 fl_foldertab_box( style, x, y, w, h, c, bw_in );
540 break;
541
542 default:
543 if ( style & FLI_BROKEN_BOX )
544 fl_foldertab_box( style, x, y, w, h, c, bw_in );
545 else
546 M_err( "fl_draw_box", "Unkonwn boxtype: %d", style );
547 break;
548 }
549 }
550
551
552 /***************************************
553 * 0
554 * 1 3
555 * 2
556 * Draws a box rotated by 45 degrees
557 ***************************************/
558
559 void
fli_draw_checkbox(int type,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,FL_COLOR col,int bw)560 fli_draw_checkbox( int type,
561 FL_Coord x,
562 FL_Coord y,
563 FL_Coord w,
564 FL_Coord h,
565 FL_COLOR col,
566 int bw )
567 {
568 int halfw = w / 2,
569 halfh = h / 2;
570 FL_POINT allp[ 9 ];;
571
572 w = 2 * halfw;
573 h = 2 * halfh;
574
575 /* Generate all points */
576
577 SET_POINT( allp, x + halfw, y );
578 SET_POINT( allp + 1, x, y + halfh );
579 SET_POINT( allp + 2, x + halfw, y + h );
580 SET_POINT( allp + 3, x + w, y + halfh );
581 SET_POINT( allp + 4, x + halfw, y + bw );
582 SET_POINT( allp + 5, x + bw, y + halfh );
583 SET_POINT( allp + 6, x + halfw, y + h - bw );
584 SET_POINT( allp + 7, x + w - bw, y + halfh );
585 SET_POINT( allp + 8, x + halfw, y + halfh ); /* center */
586
587 /* Draw the borders for up and down boxes (plus the interior, it will
588 be overdrawn in the next step) */
589
590 if ( type == FL_UP_BOX || type == FL_DOWN_BOX )
591 {
592 FL_POINT xp[ 4 ]; /* need one extra for closing of polygons! */
593
594 xp[ 2 ] = allp[ 8 ];
595
596 xp[ 0 ] = allp[ 0 ];
597 xp[ 1 ] = allp[ 1 ];
598 fl_polyf( xp, 3, type == FL_UP_BOX ? FL_LEFT_BCOL : FL_RIGHT_BCOL );
599
600 xp[ 0 ] = allp[ 1 ];
601 xp[ 1 ] = allp[ 2 ];
602 fl_polyf( xp, 3, type == FL_UP_BOX ? FL_BOTTOM_BCOL : FL_TOP_BCOL );
603
604 xp[ 0 ] = allp[ 2 ];
605 xp[ 1 ] = allp[ 3 ];
606 fl_polyf( xp, 3, type == FL_UP_BOX ? FL_RIGHT_BCOL : FL_LEFT_BCOL );
607
608 xp[ 0 ] = allp[ 3 ];
609 xp[ 1 ] = allp[ 0 ];
610 fl_polyf( xp, 3, type == FL_UP_BOX ? FL_TOP_BCOL : FL_BOTTOM_BCOL );
611 }
612
613 /* Draw the interior */
614
615 fl_polyf( allp + 4, 4, col );
616
617 /* Special hack for B&W, add a border */
618
619 if ( fli_dithered( fl_vmode ) )
620 fl_polyl( allp, 4, FL_BLACK );
621 }
622
623
624 /***************************************
625 * Draws a frame around a box. The frame is drawn that it is just
626 * outside of the box without any gap. A flat box with the same
627 * size as that frame just fit the inside the of the frame.
628 ***************************************/
629
630 void
fl_draw_frame(int style,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,FL_COLOR c,int bw)631 fl_draw_frame( int style,
632 FL_Coord x,
633 FL_Coord y,
634 FL_Coord w,
635 FL_Coord h,
636 FL_COLOR c,
637 int bw )
638 {
639 FL_POINT vert[ 5 ]; /* need one extra for closing of polygon! */
640 int B,
641 dp = fli_dithered( fl_vmode );
642
643 if ( w <= 0 || h <= 0 )
644 return;
645
646 if ( ! ( B = ( bw > 0 ) ) )
647 bw = - bw;
648
649 switch ( style )
650 {
651 case FL_UP_FRAME:
652 /* Must guarante that width of rectangle > 0 */
653
654 if ( ( w - 2 * bw ) <= 0 )
655 bw = w / 2;
656 if ( ( h - 2 * bw ) <= 0 )
657 bw = h / 2;
658
659 x -= bw + B;
660 y -= bw + B;
661 w += 2 * ( bw + B );
662 h += 2 * ( bw + B );
663
664 fl_rectf( x + B, y + B, w - 1 - B, bw, FL_TOP_BCOL );
665 fl_rectf( x + B, y + h - bw - B, w - 1 - B, bw, FL_BOTTOM_BCOL );
666
667 SET_POINT( vert, x + w - B - bw, y + bw + B );
668 SET_POINT( vert + 1, x + w - B - bw, y + h - B - bw );
669 SET_POINT( vert + 2, x + w - B, y + h - B );
670 SET_POINT( vert + 3, x + w - B, y + B );
671
672 fl_polyf( vert, 4, FL_RIGHT_BCOL );
673
674 /* Left trapzoidal */
675
676 SET_POINT( vert, x + B, y + B );
677 SET_POINT( vert + 1, x + B, y + h - B );
678 SET_POINT( vert + 2, x + bw + B, y + h - bw - B );
679 SET_POINT( vert + 3, x + bw + B, y + bw + B );
680
681 fl_polyf( vert, 4, FL_LEFT_BCOL );
682
683 if ( B || fli_dithered( fl_vmode ) )
684 fl_rect( x, y, w - 1, h - 1, FL_BLACK );
685
686 /* Special hack for B&W */
687
688 if ( dp )
689 {
690 if ( bw > 2 )
691 {
692 SET_POINT( vert, x + B, y + B );
693 SET_POINT( vert + 1, x + B + bw - 1, y + bw );
694 SET_POINT( vert + 2, x + w - bw, y + bw );
695
696 fl_lines( vert, 3, FL_BLACK );
697 fl_simple_line( x + B + bw - 1, y + B + bw,
698 x + B + bw - 1, y + h - bw, FL_BLACK );
699 }
700 else
701 fl_rect( x, y, w - 1, h - 1, FL_BLACK );
702 }
703 break;
704
705 case FL_DOWN_FRAME:
706 x -= bw;
707 y -= bw;
708 w += 2 * bw;
709 h += 2 * bw;
710
711 /* Top and bottom section */
712
713 fl_rectf( x, y, w, bw, FL_BOTTOM_BCOL ); /* top */
714 fl_rectf (x, y + h - bw, w, bw - dp, FL_TOP_BCOL); /* bottom */
715
716 /* Right trapzoid */
717
718 SET_POINT( vert, x + w - bw, y + bw );
719 SET_POINT( vert + 1, x + w - bw, y + h - bw );
720 SET_POINT( vert + 2, x + w - dp, y + h );
721 SET_POINT( vert + 3, x + w - dp, y );
722
723 fl_polyf( vert, 4, FL_LEFT_BCOL );
724
725 /* Left trapzoid */
726
727 SET_POINT( vert, x, y );
728 SET_POINT( vert + 1, x, y + h - 1 );
729 SET_POINT( vert + 2, x + bw, y + h - bw );
730 SET_POINT( vert + 3, x + bw, y + bw );
731
732 fl_polyf( vert, 4, FL_RIGHT_BCOL );
733
734 /* Special hack for B&W */
735
736 if ( dp )
737 {
738 SET_POINT( vert, x + B, y + h - 1 );
739 SET_POINT( vert + 1, x + w - 1, y + h - 1 );
740 SET_POINT( vert + 2, x + w - 1, y + B );
741 fl_lines( vert, 3, FL_BLACK );
742 }
743 break;
744
745 case FL_SHADOW_FRAME:
746 if ( w > 70 && h > 70 )
747 {
748 if ( ( bw += ( w + h ) / 140 ) > 5 )
749 bw = 5;
750 }
751
752 fl_rectf( x + bw, y + h, w, bw, FLI_SHADOW_COL );
753 fl_rectf( x + w, y + bw, bw, h, FLI_SHADOW_COL );
754 fl_rect( x - 1, y - 1, w + 1, h + 1, FL_BLACK );
755 break;
756
757 case FL_BORDER_FRAME:
758 fl_rect( x - 1, y - 1, w + 1, h + 1, c );
759 break;
760
761 case FL_EMBOSSED_FRAME:
762 B = bw > 2 ? ( bw - 2 ) : 1;
763 fl_draw_frame( FL_UP_FRAME, x, y, w, h, 0, -1 );
764 fl_draw_frame( FL_DOWN_FRAME, x + B, y + B, w - 2 * B, h - 2 * B,
765 0, 1 );
766 break;
767
768 case FL_ENGRAVED_FRAME:
769 B = bw > 2 ? bw - 2 : 1;
770 fl_draw_frame( FL_DOWN_FRAME, x, y, w, h, 0, 1 );
771 fl_draw_frame( FL_UP_FRAME, x + B, y + B,
772 w - 2 * B, h - 2 * B, 0, -1 );
773 break;
774
775 case FL_ROUNDED_FRAME:
776 fl_roundrect( x - 1, y - 1, w + 2, h + 2, c );
777 break;
778
779 case FL_OVAL_FRAME:
780 fl_oval( 0, x - 1, y - 1, w + 2, h + 2, c );
781 break;
782 }
783 }
784
785
786 /********* Some convience functions, sort of GL in X ******{*****/
787
788 #define MAX_BUF_POINT 128
789 static FL_POINT xpbuf[ MAX_BUF_POINT ];
790 static int npt;
791 static FL_COLOR pcol;
792
793
794 /***************************************
795 ***************************************/
796
797 void
fli_add_vertex(FL_Coord x,FL_Coord y)798 fli_add_vertex( FL_Coord x,
799 FL_Coord y )
800 {
801 if ( npt >= MAX_BUF_POINT )
802 {
803 M_err( "fli_add_vertex", "Vertices Out of bounds" );
804 return;
805 }
806
807 xpbuf[ npt ].x = x;
808 xpbuf[ npt++ ].y = y;
809 }
810
811
812 /***************************************
813 ***************************************/
814
815 void
fli_add_float_vertex(float x,float y)816 fli_add_float_vertex( float x,
817 float y )
818 {
819 if ( npt >= MAX_BUF_POINT )
820 {
821 M_err( "fli_add_float_vertex", "Vertices Out of bounds" );
822 return;
823 }
824
825 xpbuf[ npt ].x = FL_nint( x );
826 xpbuf[ npt++ ].y = FL_nint( y );
827 }
828
829
830 /***************************************
831 ***************************************/
832
833 void
fli_reset_vertex(void)834 fli_reset_vertex( void )
835 {
836 npt = 0;
837 pcol = flx->color;
838 }
839
840
841 /***************************************
842 ***************************************/
843
844 void
fli_endline(void)845 fli_endline( void )
846 {
847 if ( npt >= MAX_BUF_POINT )
848 {
849 M_err( "fli_endline", "Vertices Out of bounds" );
850 return;
851 }
852
853 fl_lines( xpbuf, npt, flx->color );
854 }
855
856
857 /***************************************
858 ***************************************/
859
860 void
fli_endclosedline(void)861 fli_endclosedline( void )
862 {
863 if ( npt + 1 >= MAX_BUF_POINT )
864 {
865 M_err( "fli_endclosedline", "Vertices Out of bounds" );
866 return;
867 }
868
869 fl_polyl( xpbuf, npt, pcol );
870 }
871
872
873 /***************************************
874 ***************************************/
875
876 void
fli_endpolygon(void)877 fli_endpolygon( void )
878 {
879 if ( npt + 1 >= MAX_BUF_POINT )
880 {
881 M_err( "fli_endpolygon", "Vertices Out of bounds" );
882 return;
883 }
884
885 fl_polyf( xpbuf, npt, flx->color );
886 }
887
888
889 static int Tabfolder_Corner = 3;
890
891
892 /***************************************
893 ***************************************/
894
895 int
fl_set_default_tabfolder_corner(int n)896 fl_set_default_tabfolder_corner( int n )
897 {
898 int old = Tabfolder_Corner;
899
900 Tabfolder_Corner = FL_abs( n );
901 if ( Tabfolder_Corner > 10 )
902 Tabfolder_Corner = 10;
903
904 return old;
905 }
906
907
908 /***************************************
909 ***************************************/
910
911 static void
fl_foldertab_box(int style,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,FL_COLOR c,int bw)912 fl_foldertab_box( int style,
913 FL_Coord x,
914 FL_Coord y,
915 FL_Coord w,
916 FL_Coord h,
917 FL_COLOR c,
918 int bw )
919 {
920 int ctr,
921 right,
922 bott;
923 FL_POINT vert[ 9 ]; /* need one extra for closing of polygon! */
924 int border = ( bw > 0 );
925 int absbw = FL_abs( bw ),
926 i;
927 int C = Tabfolder_Corner;
928 int isbroken = style & FLI_BROKEN_BOX;
929
930 style &= ~ FLI_BROKEN_BOX;
931
932 /* for foldertab box, actual h is pre-enlarged by absbw pixels so the
933 label is draw centered. Here we recover the pixels */
934
935 if ( style == FL_BOTTOMTAB_UPBOX || style == FL_SELECTED_BOTTOMTAB_UPBOX )
936 h += absbw;
937 else
938 h -= absbw;
939
940 /* We must try to guarantee the width of the rectangle is larger than 0 */
941
942 if ( w - 2 * absbw <= 0 )
943 absbw = FL_abs( w / 2 - 1 );
944
945 if ( h - 2 * absbw <= 0 )
946 absbw = FL_abs( h / 2 - 1 );
947
948 ctr = absbw / 2;
949 SHRINK( x, y, w, h, ctr );
950
951 right = x + w - 1;
952 bott = y + h - 1;
953
954 switch ( style )
955 {
956 case FL_TOPTAB_UPBOX:
957 SET_POINT( vert, x, y + h - ( ctr == 0 ) );
958 SET_POINT( vert + 1, x, y + C - 1 );
959 SET_POINT( vert + 2, x + C - 1, y );
960 SET_POINT( vert + 3, right - C, y );
961 SET_POINT( vert + 4, x + C - 1, y );
962 SET_POINT( vert + 5, right - C + 1, y );
963 SET_POINT( vert + 6, right, y + C - 1 );
964 SET_POINT( vert + 7, right, y + h - ( ctr == 0 ) );
965
966 fl_polyf( vert, 8, c );
967
968 fl_set_linewidth( absbw );
969 fl_lines( vert, 3, FL_LEFT_BCOL );
970 fl_lines( vert + 3, 2, FL_TOP_BCOL );
971 if ( ! isbroken )
972 fl_lines( vert + 5, 3, FL_BOTTOM_BCOL );
973 else
974 {
975 int yc = ( h - ( ctr == 0 ) ) / 2,
976 yc2 = yc / 2,
977 yc4 = yc / 4;
978
979 fl_line( right, y, right, y + 4, FL_INACTIVE_COL );
980 fl_line( right, y + 4, right - 3, y + yc4, FL_INACTIVE_COL );
981 fl_line( right - 3, y + yc4, right - 2, y + yc2,
982 FL_INACTIVE_COL );
983 fl_line( right - 2, y + yc2, right, y + yc, FL_INACTIVE_COL );
984 fl_line( right, y + yc, right, y + yc + 2, FL_INACTIVE_COL );
985 fl_line( right, y + yc + 2, right + 1, y + yc + yc4,
986 FL_INACTIVE_COL );
987 fl_line( right + 1, y + yc + yc4, right - 2, y + yc + yc,
988 FL_INACTIVE_COL );
989 }
990
991 fl_set_linewidth( 0 );
992
993 if ( border || fli_dithered( fl_vmode ) )
994 {
995 for ( i = 0; i < 8; i++ )
996 {
997 if ( vert[ i ].x > x + w / 2 )
998 vert[ i ].x += ctr;
999 else
1000 vert[ i ].x -= ctr + 1;
1001
1002 if ( vert[ i ].y < y + h / 2 )
1003 vert[ i ].y -= ctr + 1;
1004 }
1005
1006 fl_lines( vert, 8, FL_RIGHT_BCOL );
1007 }
1008 break;
1009
1010 case FL_SELECTED_TOPTAB_UPBOX:
1011 SET_POINT( vert, x, bott + absbw + 3 );
1012 SET_POINT( vert + 1, x, y + C - 1 );
1013 SET_POINT( vert + 2, x + C - 1, y );
1014 SET_POINT( vert + 3, right - C, y );
1015 SET_POINT( vert + 4, x + C - 1, y );
1016 SET_POINT( vert + 5, right - C + 1, y );
1017 SET_POINT( vert + 6, right, y + C - 1 );
1018 SET_POINT( vert + 7, right, bott + absbw + 3 );
1019
1020 fl_polyf( vert, 8, c );
1021
1022 fl_set_linewidth( absbw );
1023 fl_lines( vert, 3, FL_LEFT_BCOL );
1024 fl_lines( vert + 3, 2, FL_TOP_BCOL );
1025 fl_lines( vert + 5, 3, FL_BOTTOM_BCOL );
1026 fl_set_linewidth( 0 );
1027
1028 if ( border || fli_dithered( fl_vmode ) )
1029 {
1030 for ( i = 0; i < 8; i++ )
1031 {
1032 if ( vert[ i ].x > x + w / 2 )
1033 vert[ i ].x += ctr;
1034 else
1035 vert[ i ].x -= ctr + 1;
1036
1037 if ( vert[ i ].y < y + h / 2 )
1038 vert[ i ].y -= ctr + 1;
1039 }
1040
1041 vert[ 0 ].y -= absbw + 1;
1042 vert[ 7 ].y -= absbw + 1;
1043 fl_lines( vert, 8, FL_RIGHT_BCOL );
1044 }
1045 break;
1046
1047 case FL_BOTTOMTAB_UPBOX:
1048 SET_POINT( vert, x, y + ( ctr == 0 ) );
1049 SET_POINT( vert + 1, x, bott - C + 1 );
1050 SET_POINT( vert + 2, x + C - 1, bott );
1051 SET_POINT( vert + 3, x + C - 1, bott );
1052 SET_POINT( vert + 4, right - C, bott );
1053 SET_POINT( vert + 5, right - C, bott );
1054 SET_POINT( vert + 6, right, bott - C );
1055 SET_POINT( vert + 7, right, y + ( ctr == 0 ) );
1056
1057 fl_polyf( vert, 8, c );
1058
1059 fl_linewidth( absbw );
1060 fl_lines( vert, 3, FL_TOP_BCOL );
1061 fl_lines( vert + 3, 2, FL_BOTTOM_BCOL );
1062 fl_lines( vert + 5, 3, FL_RIGHT_BCOL );
1063 fl_linewidth( 0 );
1064
1065 if ( border || fli_dithered( fl_vmode ) )
1066 {
1067 for ( i = 0; i < 8; i++ )
1068 {
1069 if ( vert[ i ].x > x + w / 2 )
1070 vert[ i ].x += ctr;
1071 else
1072 vert[ i ].x -= ctr + 1;
1073 if ( vert[ i ].y > y + h / 2 )
1074 vert[ i ].y += ctr;
1075 }
1076
1077 fl_lines( vert, 8, FL_RIGHT_BCOL );
1078 }
1079 break;
1080
1081 case FL_SELECTED_BOTTOMTAB_UPBOX:
1082 SET_POINT( vert, x, y - absbw - 1 );
1083 SET_POINT( vert + 1, x, bott - C + 1 );
1084 SET_POINT( vert + 2, x + C - 1, bott );
1085 SET_POINT( vert + 3, x + C - 1, bott );
1086 SET_POINT( vert + 4, right - C, bott );
1087 SET_POINT( vert + 5, right - C, bott );
1088 SET_POINT( vert + 6, right, bott - C + 1 );
1089 SET_POINT( vert + 7, right, y - absbw - 1 );
1090
1091 fl_polyf( vert, 8, c );
1092
1093 fl_linewidth( absbw );
1094 fl_lines( vert, 3, FL_TOP_BCOL );
1095 fl_lines( vert + 3, 2, FL_BOTTOM_BCOL );
1096 fl_lines( vert + 5, 3, FL_RIGHT_BCOL );
1097 fl_linewidth( 0 );
1098
1099 if ( border || fli_dithered( fl_vmode ) )
1100 {
1101 for ( i = 0; i < 8; i++ )
1102 {
1103 if ( vert[ i ].x > x + w / 2 )
1104 vert[ i ].x += ctr;
1105 else
1106 vert[ i ].x -= ctr + 1;
1107 if ( vert[ i ].y > y + h / 2 )
1108 vert[ i ].y += ctr;
1109 }
1110
1111 fl_lines( vert, 8, FL_RIGHT_BCOL );
1112 }
1113 break;
1114 }
1115 }
1116
1117
1118 /***************************************
1119 * draw triangluar box
1120 ***************************************/
1121
1122 void
fli_draw_tbox(int style,FL_Coord x,FL_Coord y,FL_Coord w,FL_Coord h,FL_COLOR c,int bw_in)1123 fli_draw_tbox( int style,
1124 FL_Coord x,
1125 FL_Coord y,
1126 FL_Coord w,
1127 FL_Coord h,
1128 FL_COLOR c,
1129 int bw_in )
1130 {
1131 FL_POINT vert[ 4 ]; /* need one extra for closing of polygon! */
1132 int dp = fli_dithered( fl_vmode ),
1133 bw = bw_in;
1134 int xc = x + w / 2,
1135 yc = y + h / 2;
1136 int halfbw = bw / 2;
1137
1138 if ( c == FL_NoColor )
1139 c = FL_COL1;
1140
1141 if ( bw < 0 )
1142 bw = -bw;
1143
1144 if ( bw == 0 && style != FL_NO_BOX )
1145 style = FL_FLAT_BOX;
1146
1147 switch ( style )
1148 {
1149 case FLI_TRIANGLE_UPBOX8:
1150 SET_POINT( vert, xc, y + bw );
1151 SET_POINT( vert + 1, x + bw, y + h - bw );
1152 SET_POINT( vert + 2, x + w - bw, y + h - bw );
1153 fl_polyf( vert, 3, c );
1154
1155 fl_linewidth( bw );
1156 SHRINK( x, y, w, h, halfbw );
1157 xc = x + w / 2;
1158 fl_line( xc, y, x, y + h - 1, FL_LEFT_BCOL );
1159 fl_line( x, y + h - 1, x + w - 1, y + h - 1, FL_BOTTOM_BCOL );
1160 fl_line( xc, y, x + w - 1, y + h - 1, FL_BOTTOM_BCOL );
1161 fl_linewidth( 0 );
1162 break;
1163
1164 case FLI_TRIANGLE_DOWNBOX8:
1165 SET_POINT( vert, xc, y + bw );
1166 SET_POINT( vert + 1, x + bw, y + h - bw );
1167 SET_POINT( vert + 2, x + w - bw, y + h - bw );
1168
1169 fl_polyf( vert, 3, c );
1170
1171 fl_linewidth( bw );
1172 SHRINK( x, y, w, h, halfbw );
1173 xc = x + w / 2;
1174 fl_line( xc, y, x, y + h - 1, FL_BOTTOM_BCOL );
1175 fl_line( x, y + h - 1, x + w - 1, y + h - 1, FL_TOP_BCOL );
1176 fl_line( xc, y, x + w - 1, y + h - 1, FL_LEFT_BCOL );
1177 fl_linewidth( 0 );
1178 break;
1179
1180 case FLI_TRIANGLE_UPBOX2:
1181 SET_POINT( vert, xc, y + h - bw );
1182 SET_POINT( vert + 1, x + bw, y + bw );
1183 SET_POINT( vert + 2, x + w - bw, y + bw );
1184
1185 fl_polyf( vert, 3, c );
1186
1187 fl_linewidth( bw );
1188 SHRINK( x, y, w, h, halfbw );
1189 xc = x + w / 2;
1190 fl_line( xc, y + h - 1, x, y, FL_LEFT_BCOL );
1191 fl_line( x, y, x + w - 1, y, FL_TOP_BCOL );
1192 fl_line( x + w - 1, y, xc, y + h - 1, FL_RIGHT_BCOL );
1193 fl_linewidth( 0 );
1194 break;
1195
1196 case FLI_TRIANGLE_DOWNBOX2:
1197 SET_POINT( vert, xc, y + h - bw );
1198 SET_POINT( vert + 1, x + bw, y + bw );
1199 SET_POINT( vert + 2, x + w - bw, y + bw );
1200
1201 fl_polyf( vert, 3, c );
1202
1203 fl_linewidth( bw );
1204 SHRINK( x, y, w, h, halfbw );
1205 xc = x + w / 2;
1206 fl_line( xc, y + h - 1, x, y, FL_BOTTOM_BCOL );
1207 fl_line( x, y, x + w - 1, y, FL_BOTTOM_BCOL );
1208 fl_line( x + w - 1, y, xc, y + h - 1, FL_TOP_BCOL );
1209 fl_linewidth( 0 );
1210 break;
1211
1212 case FLI_TRIANGLE_UPBOX4:
1213 SET_POINT( vert, x + bw, yc );
1214 SET_POINT( vert + 1, x + w - bw, y + bw );
1215 SET_POINT( vert + 2, x + w - bw, y + h - bw );
1216
1217 fl_polyf( vert, 3, c );
1218
1219 fl_linewidth( bw );
1220 SHRINK( x, y, w, h, halfbw );
1221 yc = y + h / 2;
1222 fl_line( x, yc, x + w - 1, y, FL_TOP_BCOL );
1223 fl_line( x + w - 1, y, x + w - 1, y + h - 1, FL_RIGHT_BCOL );
1224 fl_line( x + w - 1, y + h - 1, x, yc, FL_BOTTOM_BCOL );
1225 fl_linewidth( 0 );
1226 break;
1227
1228 case FLI_TRIANGLE_DOWNBOX4:
1229 SET_POINT( vert, x + bw, yc );
1230 SET_POINT( vert + 1, x + w - bw, y + bw );
1231 SET_POINT( vert + 2, x + w - bw, y + h - bw );
1232
1233 fl_polyf( vert, 3, c );
1234
1235 fl_linewidth( bw );
1236 SHRINK( x, y, w, h, halfbw );
1237 yc = y + h / 2;
1238 fl_line( x, yc, x + w - 1, y, FL_BOTTOM_BCOL );
1239 fl_line( x + w - 1, y, x + w - 1, y + h - 1, FL_LEFT_BCOL );
1240 fl_line( x + w - 1, y + h - 1, x, yc, FL_LEFT_BCOL );
1241 fl_linewidth( 0 );
1242 break;
1243
1244 case FLI_TRIANGLE_UPBOX6:
1245 SET_POINT( vert, x + bw, y + bw );
1246 SET_POINT( vert + 1, x + w - bw, yc );
1247 SET_POINT( vert + 2, x + bw, y + h - bw );
1248
1249 fl_polyf( vert, 3, c );
1250
1251 fl_linewidth( bw );
1252 SHRINK( x, y, w, h, halfbw );
1253 yc = y + h / 2;
1254 fl_line( x, y, x + w - 1, yc, FL_RIGHT_BCOL );
1255 fl_line( x + w - 1, yc, x, y + h - 1, FL_BOTTOM_BCOL );
1256 fl_line( x, y + h - 1, x, y, FL_LEFT_BCOL );
1257 fl_linewidth( 0 );
1258 break;
1259
1260 case FLI_TRIANGLE_DOWNBOX6:
1261 SET_POINT( vert, x + bw, y + bw );
1262 SET_POINT( vert + 1, x + w - bw, yc );
1263 SET_POINT( vert + 2, x + bw, y + h - bw );
1264
1265 fl_polyf( vert, 3, c );
1266
1267 fl_linewidth( bw );
1268 SHRINK( x, y, w, h, halfbw );
1269 yc = y + h / 2;
1270 fl_line( x, y, x + w - 1, yc, FL_LEFT_BCOL );
1271 fl_line( x + w - 1, yc, x, y + h - 1, FL_TOP_BCOL );
1272 fl_line( x, y + h - 1, x, y, FL_RIGHT_BCOL );
1273 fl_linewidth( 0 );
1274 break;
1275 }
1276
1277 /* handle black and white */
1278
1279 if ( dp )
1280 fl_polyl( vert, 3, FL_BLACK );
1281 }
1282
1283
1284 /***************************************
1285 ***************************************/
1286
1287 int
fli_boxtype2frametype(int btype)1288 fli_boxtype2frametype( int btype )
1289 {
1290 if ( btype <= FL_EMBOSSED_BOX )
1291 return btype;
1292 else if ( btype == FL_FLAT_BOX )
1293 return FL_NO_FRAME;
1294
1295 return FL_DOWN_FRAME;
1296 }
1297
1298
1299 /*
1300 * Local variables:
1301 * tab-width: 4
1302 * indent-tabs-mode: nil
1303 * End:
1304 */
1305