1 /* Copyright (C) 2000-2012 by George Williams */
2 /*
3  * Redistribution and use in source and binary forms, with or without
4  * modification, are permitted provided that the following conditions are met:
5 
6  * Redistributions of source code must retain the above copyright notice, this
7  * list of conditions and the following disclaimer.
8 
9  * Redistributions in binary form must reproduce the above copyright notice,
10  * this list of conditions and the following disclaimer in the documentation
11  * and/or other materials provided with the distribution.
12 
13  * The name of the author may not be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15 
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <fontforge-config.h>
29 
30 #include "gdraw.h"
31 #include "ggadget.h"
32 #include "ggadgetP.h"
33 
34 #include <math.h>
35 
FigureBorderCols(GBox * design,Color * cols)36 static void FigureBorderCols(GBox *design, Color *cols) {
37     if ( design->border_type==bt_box || design->border_type==bt_double ) {
38 	cols[0] = design->border_brightest;
39 	cols[1] = design->border_brighter;
40 	cols[2] = design->border_darkest;
41 	cols[3] = design->border_darker;
42     } else if ( design->border_type==bt_raised || design->border_type==bt_embossed ) {
43 	if ( design->flags&box_generate_colors ) {
44 	    int r = COLOR_RED(design->border_brightest), g=COLOR_GREEN(design->border_brightest), b = COLOR_BLUE(design->border_brightest);
45 	    cols[0] = design->border_brightest;
46 	    cols[1] = COLOR_CREATE(15*r/16,15*g/16,15*b/16);
47 	    cols[2] = COLOR_CREATE(7*r/16,7*g/16,7*b/16);
48 	    cols[3] = COLOR_CREATE(r/2,g/2,b/2);
49 	} else {
50 	    cols[0] = design->border_brightest;
51 	    cols[1] = design->border_brighter;
52 	    cols[2] = design->border_darkest;
53 	    cols[3] = design->border_darker;
54 	}
55     } else if ( design->border_type==bt_lowered || design->border_type==bt_engraved ) {
56 	if ( design->flags&box_generate_colors ) {
57 	    int r = COLOR_RED(design->border_brightest), g=COLOR_GREEN(design->border_brightest), b = COLOR_BLUE(design->border_brightest);
58 	    cols[2] = design->border_brightest;
59 	    cols[3] = COLOR_CREATE(15*r/16,15*g/16,15*b/16);
60 	    cols[0] = COLOR_CREATE(7*r/16,7*g/16,7*b/16);
61 	    cols[1] = COLOR_CREATE(r/2,g/2,b/2);
62 	} else {
63 	    cols[2] = design->border_brightest;
64 	    cols[3] = design->border_brighter;
65 	    cols[0] = design->border_darkest;
66 	    cols[1] = design->border_darker;
67 	}
68     }
69 }
70 
DrawLeftTrap(GWindow gw,GRect * pos,int inset,int width,Color col)71 static void DrawLeftTrap(GWindow gw,GRect *pos,int inset,int width,Color col) {
72     GPoint pts[5];
73 
74     --width;
75     if ( width==0 ) {
76 	GDrawDrawLine(gw,pos->x+inset,pos->y+inset,pos->x+inset,pos->y+pos->height-1-inset,col);
77     } else {
78 	pts[0].x = pos->x+inset;
79 		pts[0].y = pos->y+inset;
80 	pts[1].x = pos->x+inset+width;
81 		pts[1].y = pos->y+inset+width;
82 	pts[2].x = pts[1].x;
83 		pts[2].y = pos->y+pos->height-1-(inset+width);
84 	pts[3].x = pts[0].x;
85 		pts[3].y = pos->y+pos->height-1-inset;
86 	pts[4] = pts[0];
87 	GDrawFillPoly(gw,pts,5,col);
88     }
89 }
90 
DrawULTrap(GWindow gw,GRect * pos,int inset,int width,Color col)91 static void DrawULTrap(GWindow gw,GRect *pos,int inset,int width,Color col) {
92     GPoint pts[5];
93     /* for drawing a diamond shape */
94 
95     --width;
96     if ( width==0 ) {
97 	GDrawDrawLine(gw,pos->x+inset,pos->y+pos->height/2,pos->x+pos->width/2,pos->y+inset,col);
98     } else {
99 	pts[0].x = pos->x+inset;
100 		pts[0].y = pos->y+pos->height/2;
101 	pts[1].x = pos->x+inset+width;
102 		pts[1].y = pts[0].y;
103 	pts[2].x = pos->x+pos->width/2;
104 		pts[2].y = pos->y+inset+width;
105 	pts[3].x = pts[2].x;
106 		pts[3].y = pos->y+inset;
107 	pts[4] = pts[0];
108 	GDrawFillPoly(gw,pts,5,col);
109     }
110 }
111 
DrawTopTrap(GWindow gw,GRect * pos,int inset,int width,Color col)112 static void DrawTopTrap(GWindow gw,GRect *pos,int inset,int width,Color col) {
113     GPoint pts[5];
114 
115     --width;
116     if ( width==0 ) {
117 	GDrawDrawLine(gw,pos->x+inset,pos->y+inset,pos->x+pos->width-1-inset,pos->y+inset,col);
118     } else {
119 	pts[0].x = pos->x+inset;
120 		pts[0].y = pos->y+inset;
121 	pts[1].x = pos->x+inset+width;
122 		pts[1].y = pos->y+inset+width;
123 	pts[2].x = pos->x+pos->width-1-(inset+width);
124 		pts[2].y = pts[1].y;
125 	pts[3].x = pos->x+pos->width-1-inset;
126 		pts[3].y = pts[0].y;
127 	pts[4] = pts[0];
128 	GDrawFillPoly(gw,pts,5,col);
129     }
130 }
131 
DrawURTrap(GWindow gw,GRect * pos,int inset,int width,Color col)132 static void DrawURTrap(GWindow gw,GRect *pos,int inset,int width,Color col) {
133     GPoint pts[5];
134 
135     --width;
136     if ( width==0 ) {
137 	GDrawDrawLine(gw,pos->x+pos->width-1-inset,pos->y+pos->height/2,pos->x+pos->width/2,pos->y+inset,col);
138     } else {
139 	pts[0].x = pos->x+pos->width-1-inset;
140 		pts[0].y = pos->y+pos->height/2;
141 	pts[1].x = pts[0].x-width;
142 		pts[1].y = pts[0].y;
143 	pts[2].x = pos->x+pos->width/2;
144 		pts[2].y = pos->y+inset+width;
145 	pts[3].x = pts[2].x;
146 		pts[3].y = pts[2].y-width;
147 	pts[4] = pts[0];
148 	GDrawFillPoly(gw,pts,5,col);
149     }
150 }
151 
DrawRightTrap(GWindow gw,GRect * pos,int inset,int width,Color col)152 static void DrawRightTrap(GWindow gw,GRect *pos,int inset,int width,Color col) {
153     GPoint pts[5];
154 
155     --width;
156     if ( width==0 ) {
157 	GDrawDrawLine(gw,pos->x+pos->width-1-inset,pos->y+inset,pos->x+pos->width-1-inset,pos->y+pos->height-1-inset,col);
158     } else {
159 	pts[0].x = pos->x+pos->width-1-inset;
160 		pts[0].y = pos->y+inset;
161 	pts[1].x = pos->x+pos->width-1-(inset+width);
162 		pts[1].y = pos->y+inset+width;
163 	pts[2].x = pts[1].x;
164 		pts[2].y = pos->y+pos->height-1-(inset+width);
165 	pts[3].x = pts[0].x;
166 		pts[3].y = pos->y+pos->height-1-inset;
167 	pts[4] = pts[0];
168 	GDrawFillPoly(gw,pts,5,col);
169     }
170 }
171 
DrawLRTrap(GWindow gw,GRect * pos,int inset,int width,Color col)172 static void DrawLRTrap(GWindow gw,GRect *pos,int inset,int width,Color col) {
173     GPoint pts[5];
174 
175     --width;
176     if ( width==0 ) {
177 	GDrawDrawLine(gw,pos->x+pos->width-1-inset,pos->y+pos->height/2,pos->x+pos->width/2,pos->y+pos->height-1-inset,col);
178     } else {
179 	pts[0].x = pos->x+pos->width-1-inset;
180 		pts[0].y = pos->y+pos->height/2;
181 	pts[1].x = pts[0].x-width;
182 		pts[1].y = pts[0].y;
183 	pts[2].x = pos->x+pos->width/2;
184 		pts[2].y = pos->y+pos->height-1-inset-width;
185 	pts[3].x = pts[2].x;
186 		pts[3].y = pts[2].y+width;
187 	pts[4] = pts[0];
188 	GDrawFillPoly(gw,pts,5,col);
189     }
190 }
191 
DrawBottomTrap(GWindow gw,GRect * pos,int inset,int width,Color col)192 static void DrawBottomTrap(GWindow gw,GRect *pos,int inset,int width,Color col) {
193     GPoint pts[5];
194 
195     --width;
196     if ( width==0 ) {
197 	GDrawDrawLine(gw,pos->x+inset,pos->y+pos->height-1-inset,pos->x+pos->width-1-inset,pos->y+pos->height-1-inset,col);
198     } else {
199 	pts[0].x = pos->x+inset;
200 		pts[0].y = pos->y+pos->height-1-inset;
201 	pts[1].x = pos->x+inset+width;
202 		pts[1].y = pos->y+pos->height-1-(inset+width);
203 	pts[2].x = pos->x+pos->width-1-(inset+width);
204 		pts[2].y = pts[1].y;
205 	pts[3].x = pos->x+pos->width-1-inset;
206 		pts[3].y = pts[0].y;
207 	pts[4] = pts[0];
208 	GDrawFillPoly(gw,pts,5,col);
209     }
210 }
211 
DrawLLTrap(GWindow gw,GRect * pos,int inset,int width,Color col)212 static void DrawLLTrap(GWindow gw,GRect *pos,int inset,int width,Color col) {
213     GPoint pts[5];
214 
215     --width;
216     if ( width==0 ) {
217 	GDrawDrawLine(gw,pos->x+inset,pos->y+pos->height/2,pos->x+pos->width/2,pos->y+pos->height-1-inset,col);
218     } else {
219 	pts[0].x = pos->x+inset;
220 		pts[0].y = pos->y+pos->height/2;
221 	pts[1].x = pts[0].x+width;
222 		pts[1].y = pts[0].y;
223 	pts[2].x = pos->x+pos->width/2;
224 		pts[2].y = pos->y+pos->height-1-inset-width;
225 	pts[3].x = pts[2].x;
226 		pts[3].y = pts[2].y+width;
227 	pts[4] = pts[0];
228 	GDrawFillPoly(gw,pts,5,col);
229     }
230 }
231 
GetULRect(GRect * res,GRect * rect,int inset,int radius)232 static void GetULRect(GRect *res, GRect *rect,int inset,int radius) {
233     res->x = rect->x+inset; res->y = rect->y+inset;
234     res->width = res->height = 2*(radius-inset);
235 }
236 
DrawULArc(GWindow gw,GRect * rect,int inset,int radius,Color col)237 static void DrawULArc(GWindow gw, GRect *rect,int inset,int radius, Color col) {
238     GRect r;
239     if ( inset>=radius )
240 return;
241     GetULRect(&r,rect,inset,radius);
242     GDrawDrawArc(gw,&r,90*64,90*64,col);
243 }
244 
DrawULArcs(GWindow gw,GRect * rect,int inset,int radius,Color col1,Color col2)245 static void DrawULArcs(GWindow gw, GRect *rect,int inset,int radius, Color col1, Color col2) {
246     GRect r;
247     if ( inset>=radius )
248 return;
249     GetULRect(&r,rect,inset,radius);
250     if ( col1==col2 )
251 	GDrawDrawArc(gw,&r,90*64,90*64,col2);
252     else {
253 	GDrawDrawArc(gw,&r,135*64,45*64,col1);
254 	GDrawDrawArc(gw,&r,90*64,45*64,col2);
255     }
256 }
257 
GetURRect(GRect * res,GRect * rect,int inset,int radius)258 static void GetURRect(GRect *res, GRect *rect,int inset,int radius) {
259     res->width = res->height = 2*(radius-inset);
260     res->x = rect->x+rect->width-1-inset-res->width; res->y = rect->y+inset;
261 }
262 
DrawURArc(GWindow gw,GRect * rect,int inset,int radius,Color col)263 static void DrawURArc(GWindow gw, GRect *rect,int inset,int radius, Color col) {
264     GRect r;
265     if ( inset>=radius )
266 return;
267     GetURRect(&r,rect,inset,radius);
268     GDrawDrawArc(gw,&r,0*64,90*64,col);
269 }
270 
DrawURArcs(GWindow gw,GRect * rect,int inset,int radius,Color col1,Color col2)271 static void DrawURArcs(GWindow gw, GRect *rect,int inset,int radius, Color col1, Color col2) {
272     GRect r;
273     if ( inset>=radius )
274 return;
275     GetURRect(&r,rect,inset,radius);
276     if ( col1==col2 )
277 	GDrawDrawArc(gw,&r,0*64,90*64,col2);
278     else {
279 	GDrawDrawArc(gw,&r,45*64,45*64,col1);
280 	GDrawDrawArc(gw,&r,0*64,45*64,col2);
281     }
282 }
283 
GetLRRect(GRect * res,GRect * rect,int inset,int radius)284 static void GetLRRect(GRect *res, GRect *rect,int inset,int radius) {
285     res->width = res->height = 2*(radius-inset);
286     res->x = rect->x+rect->width-1-inset-res->width;
287     res->y = rect->y+rect->height-1-inset-res->height;
288 }
289 
DrawLRArc(GWindow gw,GRect * rect,int inset,int radius,Color col)290 static void DrawLRArc(GWindow gw, GRect *rect,int inset,int radius, Color col) {
291     GRect r;
292     if ( inset>=radius )
293 return;
294     GetLRRect(&r,rect,inset,radius);
295     GDrawDrawArc(gw,&r,-90*64,90*64,col);
296 }
297 
DrawLRArcs(GWindow gw,GRect * rect,int inset,int radius,Color col1,Color col2)298 static void DrawLRArcs(GWindow gw, GRect *rect,int inset,int radius, Color col1, Color col2) {
299     GRect r;
300     if ( inset>=radius )
301 return;
302     GetLRRect(&r,rect,inset,radius);
303     if ( col1==col2 )
304 	GDrawDrawArc(gw,&r,-90*64,90*64,col2);
305     else {
306 	GDrawDrawArc(gw,&r,-45*64,45*64,col1);
307 	GDrawDrawArc(gw,&r,-90*64,45*64,col2);
308     }
309 }
310 
GetLLRect(GRect * res,GRect * rect,int inset,int radius)311 static void GetLLRect(GRect *res, GRect *rect,int inset,int radius) {
312     res->width = res->height = 2*(radius-inset);
313     res->x = rect->x+inset;
314     res->y = rect->y+rect->height-1-inset-res->height;
315 }
316 
DrawLLArc(GWindow gw,GRect * rect,int inset,int radius,Color col)317 static void DrawLLArc(GWindow gw, GRect *rect,int inset,int radius, Color col) {
318     GRect r;
319     if ( inset>=radius )
320 return;
321     GetLLRect(&r,rect,inset,radius);
322     GDrawDrawArc(gw,&r,-180*64,90*64,col);
323 }
324 
DrawLLArcs(GWindow gw,GRect * rect,int inset,int radius,Color col1,Color col2)325 static void DrawLLArcs(GWindow gw, GRect *rect,int inset,int radius, Color col1, Color col2) {
326     GRect r;
327     if ( inset>=radius )
328 return;
329     GetLLRect(&r,rect,inset,radius);
330     if ( col1==col2 )
331 	GDrawDrawArc(gw,&r,-180*64,90*64,col2);
332     else {
333 	GDrawDrawArc(gw,&r,-135*64,45*64,col1);
334 	GDrawDrawArc(gw,&r,-180*64,45*64,col2);
335     }
336 }
337 
DrawRoundRect(GWindow gw,GRect * pos,int inset,int radius,Color col)338 static void DrawRoundRect(GWindow gw, GRect *pos,int inset,int radius,
339 	Color col) {
340     int off;
341     if ( inset<radius ) {
342 	off = radius;
343 	DrawULArc(gw,pos,inset,radius,col);
344 	DrawURArc(gw,pos,inset,radius,col);
345 	DrawLRArc(gw,pos,inset,radius,col);
346 	DrawLLArc(gw,pos,inset,radius,col);
347     } else
348 	off = inset;
349     GDrawDrawLine(gw,pos->x+inset,pos->y+off,pos->x+inset,pos->y+pos->height-1-off,col);
350     GDrawDrawLine(gw,pos->x+off,pos->y+inset,pos->x+pos->width-1-off,pos->y+inset,col);
351     GDrawDrawLine(gw,pos->x+pos->width-1-inset,pos->y+off,pos->x+pos->width-1-inset,pos->y+pos->height-1-off,col);
352     GDrawDrawLine(gw,pos->x+off,pos->y+pos->height-1-inset,pos->x+pos->width-1-off,pos->y+pos->height-1-inset,col);
353 }
354 
DrawRoundTab(GWindow gw,GRect * pos,int inset,int radius,Color col1,Color col2,Color col3,Color col4,int active)355 static void DrawRoundTab(GWindow gw, GRect *pos,int inset,int radius,
356 	Color col1, Color col2, Color col3, Color col4, int active) {
357     int off;
358     if ( inset<radius ) {
359 	off = radius;
360 	DrawULArc(gw,pos,inset,radius,col1);
361 	DrawURArc(gw,pos,inset,radius,col3);
362     } else
363 	off = inset;
364     GDrawDrawLine(gw,pos->x+inset,pos->y+off,pos->x+inset,pos->y+pos->height-1,col1);
365     GDrawDrawLine(gw,pos->x+off,pos->y+inset,pos->x+pos->width-1-off,pos->y+inset,col2);
366     GDrawDrawLine(gw,pos->x+pos->width-1-inset,pos->y+off,pos->x+pos->width-1-inset,pos->y+pos->height-1,col3);
367     if ( !active )
368 	GDrawDrawLine(gw,pos->x,pos->y+pos->height-1,pos->x+pos->width-1,pos->y+pos->height-1,col4);
369 }
370 
DrawRoundRects(GWindow gw,GRect * pos,int inset,int radius,Color col1,Color col2,Color col3,Color col4)371 static void DrawRoundRects(GWindow gw, GRect *pos,int inset,int radius,
372 	Color col1, Color col2, Color col3, Color col4) {
373     int off;
374     if ( inset<radius ) {
375 	off = radius;
376 	DrawULArcs(gw,pos,inset,radius,col1,col2);
377 	DrawURArcs(gw,pos,inset,radius,col2,col3);
378 	DrawLRArcs(gw,pos,inset,radius,col3,col4);
379 	DrawLLArcs(gw,pos,inset,radius,col4,col1);
380     } else
381 	off = inset;
382     GDrawDrawLine(gw,pos->x+inset,pos->y+off,pos->x+inset,pos->y+pos->height-1-off,col1);
383     GDrawDrawLine(gw,pos->x+off,pos->y+inset,pos->x+pos->width-1-off,pos->y+inset,col2);
384     GDrawDrawLine(gw,pos->x+pos->width-1-inset,pos->y+off,pos->x+pos->width-1-inset,pos->y+pos->height-1-off,col3);
385     GDrawDrawLine(gw,pos->x+off,pos->y+pos->height-1-inset,pos->x+pos->width-1-off,pos->y+pos->height-1-inset,col4);
386 }
387 
GBoxRectBorder(GWindow gw,GRect * pos,GBox * design,enum gadget_state state,int is_def)388 static int GBoxRectBorder(GWindow gw,GRect *pos,GBox *design,
389 	enum gadget_state state, int is_def) {
390     int bw = GDrawPointsToPixels(gw,design->border_width);
391     int inset = 0;
392     GRect cur;
393     int scale = GDrawPointsToPixels(gw,1);
394     enum border_type bt = design->border_type;
395     Color cols[4];
396     Color fg = state==gs_disabled?design->disabled_foreground:
397 		    design->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(gw)):
398 		    design->main_foreground;
399 	Color color_inner = design->border_inner == COLOR_DEFAULT ? fg : design->border_inner;
400 	Color color_outer = design->border_outer == COLOR_DEFAULT ? fg : design->border_outer;
401 
402     FigureBorderCols(design,cols);
403     if ( is_def && (design->flags & box_draw_default) && bt!=bt_none ) {
404 	DrawLeftTrap(gw,pos,inset,scale,cols[2]);
405 	DrawTopTrap(gw,pos,inset,scale,cols[3]);
406 	DrawRightTrap(gw,pos,inset,scale,cols[0]);
407 	DrawBottomTrap(gw,pos,inset,scale,cols[1]);
408 	inset = scale + GDrawPointsToPixels(gw,2);
409     }
410 
411     if ( (design->flags & (box_foreground_border_outer|box_foreground_shadow_outer)) ) {
412 	GDrawSetLineWidth(gw,scale);
413 	cur = *pos;
414 	cur.x += inset; cur.y += inset; cur.width -= 2*inset; cur.height -= 2*inset;
415 	if ( scale>1 ) {
416 	    cur.x += scale/2; cur.y += scale/2;
417 	    cur.width -= scale; cur.height -= scale;
418 	}
419 	--cur.width; --cur.height;
420 	if ( design->flags&box_foreground_border_outer )
421 	    GDrawDrawRect(gw,&cur,color_outer);
422 	else {
423 	    GDrawDrawLine(gw,cur.x+scale,cur.y+cur.height,cur.x+cur.width,cur.y+cur.height,fg);
424 	    GDrawDrawLine(gw,cur.x+cur.width,cur.y+scale,cur.x+cur.width,cur.y+cur.height,fg);
425 	}
426 	inset += scale;
427     }
428 
429     if ( bt==bt_double && bw<3 )
430 	bt = bt_box;
431     if (( bt==bt_engraved || bt==bt_embossed ) && bw<2 )
432 	bt = bt_box;
433 
434     if ( bw!=0 ) switch ( bt ) {
435       case bt_none:
436       break;
437       case bt_box: case bt_raised: case bt_lowered:
438 	DrawLeftTrap(gw,pos,inset,bw,cols[0]);
439 	DrawTopTrap(gw,pos,inset,bw,cols[1]);
440 	DrawRightTrap(gw,pos,inset,bw,cols[2]);
441 	DrawBottomTrap(gw,pos,inset,bw,cols[3]);
442       break;
443       case bt_engraved: case bt_embossed:
444 	bw &= ~1;
445 	DrawLeftTrap(gw,pos,inset,bw/2,cols[0]);
446 	DrawTopTrap(gw,pos,inset,bw/2,cols[1]);
447 	DrawRightTrap(gw,pos,inset,bw/2,cols[2]);
448 	DrawBottomTrap(gw,pos,inset,bw/2,cols[3]);
449 
450 	inset += bw/2;
451 	DrawLeftTrap(gw,pos,inset,bw/2,cols[2]);
452 	DrawTopTrap(gw,pos,inset,bw/2,cols[3]);
453 	DrawRightTrap(gw,pos,inset,bw/2,cols[0]);
454 	DrawBottomTrap(gw,pos,inset,bw/2,cols[1]);
455 	inset -= bw/2;
456       break;
457       case bt_double: {
458 	int width = (bw+1)/3;
459 	DrawLeftTrap(gw,pos,inset,width,cols[0]);
460 	DrawTopTrap(gw,pos,inset,width,cols[1]);
461 	DrawRightTrap(gw,pos,inset,width,cols[2]);
462 	DrawBottomTrap(gw,pos,inset,width,cols[3]);
463 
464 	inset += bw-width;
465 	DrawLeftTrap(gw,pos,inset,width,cols[0]);
466 	DrawTopTrap(gw,pos,inset,width,cols[1]);
467 	DrawRightTrap(gw,pos,inset,width,cols[2]);
468 	DrawBottomTrap(gw,pos,inset,width,cols[3]);
469 	inset -= bw-width;
470       } break;
471     }
472     inset += bw;
473 
474     if ( (design->flags & box_foreground_border_inner) ||
475 	    ((design->flags & box_active_border_inner) && state==gs_active)) {
476 	GDrawSetLineWidth(gw,scale);
477 	cur = *pos;
478 	cur.x += inset; cur.y += inset;
479 	cur.width -= 2*inset; cur.height -= 2*inset;
480 	if ( scale>1 ) {
481 	    cur.x += scale/2; cur.y += scale/2;
482 	    cur.width -= scale; cur.height -= scale;
483 	}
484 	--cur.width; --cur.height;
485 	GDrawDrawRect(gw,&cur,
486 		state == gs_active && (design->flags & box_active_border_inner) ?
487 			design->active_border : color_inner);
488 	inset += scale;
489     }
490 return( inset );
491 }
492 
GBoxDrawHLine(GWindow gw,GRect * pos,GBox * design)493 int GBoxDrawHLine(GWindow gw,GRect *pos,GBox *design) {
494     int bw = GDrawPointsToPixels(gw,design->border_width);
495     int x,y,xend;
496     int scale = GDrawPointsToPixels(gw,1);
497     enum border_type bt = design->border_type;
498     Color cols[4];
499     Color fg = design->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(gw)):
500 		    design->main_foreground;
501 	Color color_inner = design->border_inner == COLOR_DEFAULT ? fg : design->border_inner;
502 	Color color_outer = design->border_outer == COLOR_DEFAULT ? fg : design->border_outer;
503     int bp = GBoxBorderWidth(gw,design);
504 
505     FigureBorderCols(design,cols);
506 
507     x = pos->x; xend = x+pos->width -1;
508     y = pos->y + (pos->height-bp)/2;
509 
510     if ( (design->flags & box_foreground_border_outer) ) {
511 	GDrawSetLineWidth(gw,scale);
512 	GDrawDrawLine(gw,x,y+scale/2,xend,y+scale/2,color_outer);
513 	y += scale;
514     }
515 
516     if ( bt==bt_double && bw<3 )
517 	bt = bt_box;
518     if (( bt==bt_engraved || bt==bt_embossed ) && bw<2 )
519 	bt = bt_box;
520 
521     if ( bw!=0 ) switch ( bt ) {
522       case bt_none:
523       break;
524       case bt_box: case bt_raised: case bt_lowered:
525 	GDrawSetLineWidth(gw,bw);
526 	GDrawDrawLine(gw,x,y+bw/2,xend,y+bw/2,cols[1]);
527       break;
528       case bt_engraved: case bt_embossed:
529 	bw &= ~1;
530 	GDrawSetLineWidth(gw,bw/2);
531 	GDrawDrawLine(gw,x,y+bw/4,xend,y+bw/4,cols[1]);
532 	y += bw/2;
533 	GDrawDrawLine(gw,x,y+bw/4,xend,y+bw/4,cols[3]);
534 	y -= bw/2;
535       break;
536       case bt_double: {
537 	int width = (bw+1)/3;
538 	GDrawSetLineWidth(gw,width);
539 	GDrawDrawLine(gw,x,y+width/2,xend,y+width/2,cols[1]);
540 	y += bw-width;
541 	GDrawDrawLine(gw,x,y+width/2,xend,y+width/2,cols[1]);
542 	y -= bw-width;
543       } break;
544     }
545     y += bw;
546 
547     if ( design->flags & box_foreground_border_inner ) {
548 	GDrawSetLineWidth(gw,scale);
549 	GDrawDrawLine(gw,x,y+scale/2,xend,y+scale/2,color_inner);
550 	y += scale;
551     }
552 return( y );
553 }
554 
GBoxDrawVLine(GWindow gw,GRect * pos,GBox * design)555 int GBoxDrawVLine(GWindow gw,GRect *pos,GBox *design) {
556     int bw = GDrawPointsToPixels(gw,design->border_width);
557     int x,y,yend;
558     int scale = GDrawPointsToPixels(gw,1);
559     enum border_type bt = design->border_type;
560     Color cols[4];
561     Color fg = design->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(gw)):
562 		    design->main_foreground;
563 	Color color_inner = design->border_inner == COLOR_DEFAULT ? fg : design->border_inner;
564 	Color color_outer = design->border_outer == COLOR_DEFAULT ? fg : design->border_outer;
565     int bp = GBoxBorderWidth(gw,design);
566 
567     FigureBorderCols(design,cols);
568 
569     x = pos->x + (pos->width-bp)/2;
570     y = pos->y; yend = y+pos->height -1;
571 
572     if ( (design->flags & box_foreground_border_outer) ) {
573 	GDrawSetLineWidth(gw,scale);
574 	GDrawDrawLine(gw,x+scale/2,y,x+scale/2,yend,color_outer);
575 	x += scale;
576     }
577 
578     if ( bt==bt_double && bw<3 )
579 	bt = bt_box;
580     if (( bt==bt_engraved || bt==bt_embossed ) && bw<2 )
581 	bt = bt_box;
582 
583     if ( bw!=0 ) switch ( bt ) {
584       case bt_none:
585       break;
586       case bt_box: case bt_raised: case bt_lowered:
587 	GDrawSetLineWidth(gw,bw);
588 	GDrawDrawLine(gw,x+bw/2,y,x+bw/2,yend,cols[0]);
589       break;
590       case bt_engraved: case bt_embossed:
591 	bw &= ~1;
592 	GDrawSetLineWidth(gw,bw/2);
593 	GDrawDrawLine(gw,x+bw/4,y,x+bw/4,yend,cols[0]);
594 	x += bw/2;
595 	GDrawDrawLine(gw,x+bw/4,y,x+bw/4,yend,cols[2]);
596 	x -= bw/2;
597       break;
598       case bt_double: {
599 	int width = (bw+1)/3;
600 	GDrawSetLineWidth(gw,width);
601 	GDrawDrawLine(gw,x+width/2,y,x+width/2,yend,cols[0]);
602 	x += bw-width;
603 	GDrawDrawLine(gw,x+width/2,y,x+width/2,yend,cols[0]);
604 	x -= bw-width;
605       } break;
606     }
607     x += bw;
608 
609     if ( design->flags & box_foreground_border_inner ) {
610 	GDrawSetLineWidth(gw,scale);
611 	GDrawDrawLine(gw,x+scale/2,y,x+scale/2,yend,color_inner);
612 	x += scale;
613     }
614 return( x );
615 }
616 
GBoxRoundRectBorder(GWindow gw,GRect * pos,GBox * design,enum gadget_state state,int is_def)617 static int GBoxRoundRectBorder(GWindow gw,GRect *pos,GBox *design,
618 	enum gadget_state state, int is_def) {
619     int bw = GDrawPointsToPixels(gw,design->border_width);
620     int inset = 0;
621     int scale = GDrawPointsToPixels(gw,1);
622     enum border_type bt = design->border_type;
623     Color cols[4];
624     int rr = GDrawPointsToPixels(gw,design->rr_radius);
625     Color fg = state==gs_disabled?design->disabled_foreground:
626 		    design->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(gw)):
627 		    design->main_foreground;
628 	Color color_inner = design->border_inner == COLOR_DEFAULT ? fg : design->border_inner;
629 	Color color_outer = design->border_outer == COLOR_DEFAULT ? fg : design->border_outer;
630 
631     if ( rr==0 )
632 	rr = pos->width/2;
633     if ( is_def && (design->flags & box_draw_default) )
634 	rr += scale + GDrawPointsToPixels(gw,2);
635     if ( rr>pos->width/2 )
636 	rr = pos->width/2;
637     if ( rr>pos->height/2 )
638 	rr = pos->height/2;
639     if ( !(scale&1)) --scale;
640     if ( scale==0 ) scale = 1;
641 
642     FigureBorderCols(design,cols);
643     if ( is_def && (design->flags & box_draw_default) && bt!=bt_none ) {
644 	GDrawSetLineWidth(gw,scale);
645 	DrawRoundRects(gw,pos,inset+scale/2,rr,cols[2],cols[3],cols[0],cols[1]);
646 	inset += scale + GDrawPointsToPixels(gw,2);
647     }
648 
649     if ( design->flags & (box_foreground_border_outer|box_foreground_shadow_outer) ) {
650 	GDrawSetLineWidth(gw,scale);
651 	if ( design->flags&box_foreground_border_outer )
652 	    DrawRoundRect(gw,pos,scale/2,rr,color_outer);
653 	else {
654 	    GDrawDrawLine(gw,pos->x+scale+rr,pos->y+pos->height,pos->x+pos->width,pos->y+pos->height,fg);
655 	    GDrawDrawLine(gw,pos->x+pos->width,pos->y+scale+rr,pos->x+pos->width,pos->y+pos->height,fg);
656 	}
657 	inset += scale;
658     }
659 
660     if ( bt==bt_double && bw<3 )
661 	bt = bt_box;
662     if (( bt==bt_engraved || bt==bt_embossed ) && bw<2 )
663 	bt = bt_box;
664 
665     if ( bw!=0 ) switch ( bt ) {
666       case bt_none:
667       break;
668       case bt_box: case bt_raised: case bt_lowered:
669 	if ( !(bw&1) ) --bw;
670 	GDrawSetLineWidth(gw,bw);
671 	DrawRoundRects(gw,pos,inset+bw/2,rr,cols[0],cols[1],cols[2],cols[3]);
672       break;
673       case bt_engraved: case bt_embossed:
674 	bw &= ~1;
675 	if ( !(bw&2 ) )
676 	    bw -= 2;
677 	if ( bw<=0 )
678 	    bw = 2;
679 	GDrawSetLineWidth(gw,bw/2);
680 	DrawRoundRects(gw,pos,inset+bw/4,rr,cols[0],cols[1],cols[2],cols[3]);
681 	DrawRoundRects(gw,pos,inset+bw/2+bw/4,rr,cols[2],cols[3],cols[0],cols[1]);
682       break;
683       case bt_double: {
684 	int width = (bw+1)/3;
685 	if ( !(width&1) ) {
686 	    if ( 2*(width+1) < bw )
687 		++width;
688 	    else
689 		--width;
690 	}
691 	GDrawSetLineWidth(gw,width);
692 	DrawRoundRects(gw,pos,inset+width/2,rr,cols[0],cols[1],cols[2],cols[3]);
693 	DrawRoundRects(gw,pos,inset+bw-(width+1)/2,rr,cols[0],cols[1],cols[2],cols[3]);
694       } break;
695     }
696     inset += bw;
697 
698     if ( (design->flags & box_foreground_border_inner) ||
699 	    ((design->flags & box_active_border_inner) && state==gs_active)) {
700 	GDrawSetLineWidth(gw,scale);
701 	DrawRoundRect(gw,pos,inset+scale/2,rr,
702 		state == gs_active && (design->flags & box_active_border_inner) ?
703 			design->active_border : color_inner);
704 	inset += scale;
705     }
706 return( inset );
707 }
708 
GBoxElipseBorder(GWindow gw,GRect * pos,GBox * design,enum gadget_state state,int is_def)709 static int GBoxElipseBorder(GWindow gw,GRect *pos,GBox *design,
710 	enum gadget_state state, int is_def) {
711     int bw = GDrawPointsToPixels(gw,design->border_width);
712     int inset = 0;
713     GRect cur;
714     int scale = GDrawPointsToPixels(gw,1);
715     enum border_type bt = design->border_type;
716     Color cols[4];
717     Color fg = state==gs_disabled?design->disabled_foreground:
718 		    design->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(gw)):
719 		    design->main_foreground;
720 	Color color_inner = design->border_inner == COLOR_DEFAULT ? fg : design->border_inner;
721 	Color color_outer = design->border_outer == COLOR_DEFAULT ? fg : design->border_outer;
722 
723     if ( !(scale&1)) --scale;
724     if ( scale==0 ) scale = 1;
725 
726     FigureBorderCols(design,cols);
727     if ( is_def && (design->flags & box_draw_default) && bt!=bt_none ) {
728 	int temp = scale;
729 	if ( !(temp&1) ) --temp;
730 	GDrawSetLineWidth(gw,temp);
731 	cur = *pos;
732 	cur.x += inset+temp/2; cur.y += inset+temp/2;
733 	cur.width -= 2*(inset+temp/2)+1; cur.height -= 2*(inset+temp/2)+1;
734 	GDrawDrawArc(gw,&cur,90*64,90*64,cols[2]);
735 	GDrawDrawArc(gw,&cur,0*64,90*64,cols[3]);
736 	GDrawDrawArc(gw,&cur,-90*64,90*64,cols[0]);
737 	GDrawDrawArc(gw,&cur,-180*64,90*64,cols[1]);
738 	inset += scale + GDrawPointsToPixels(gw,2);
739     }
740 
741     if ( design->flags & box_foreground_border_outer ) {
742 	GDrawSetLineWidth(gw,scale);
743 	cur = *pos;
744 	if ( scale>1 ) {
745 	    cur.x += scale/2; cur.y += scale/2;
746 	    cur.width -= scale; cur.height -= scale;
747 	}
748 	--cur.width; --cur.height;
749 	GDrawDrawElipse(gw,&cur,color_outer);
750 	inset += scale;
751     }
752 
753     if ( bt==bt_double && bw<3 )
754 	bt = bt_box;
755     if (( bt==bt_engraved || bt==bt_embossed ) && bw<2 )
756 	bt = bt_box;
757     FigureBorderCols(design,cols);
758 
759     if ( bw!=0 ) switch ( bt ) {
760       case bt_none:
761       break;
762       case bt_box: case bt_raised: case bt_lowered:
763 	if ( !(bw&1) ) --bw;
764 	GDrawSetLineWidth(gw,bw);
765 	cur = *pos;
766 	cur.x += inset+bw/2; cur.y += inset+bw/2;
767 	cur.width -= 2*(inset+bw/2)+1; cur.height -= 2*(inset+bw/2)+1;
768 	GDrawDrawArc(gw,&cur,90*64,90*64,cols[0]);
769 	GDrawDrawArc(gw,&cur,0*64,90*64,cols[1]);
770 	GDrawDrawArc(gw,&cur,-90*64,90*64,cols[2]);
771 	GDrawDrawArc(gw,&cur,-180*64,90*64,cols[3]);
772       break;
773       case bt_engraved: case bt_embossed:
774 	bw &= ~1;
775 	if ( !(bw&2 ) )
776 	    bw -= 2;
777 	if ( bw<=0 )
778 	    bw = 2;
779 	GDrawSetLineWidth(gw,bw/2);
780 	cur = *pos;
781 	cur.x += inset+bw/4; cur.y += inset+bw/4;
782 	cur.width -= 2*(inset+bw/4)+1; cur.height -= 2*(inset+bw/4)+1;
783 	GDrawDrawArc(gw,&cur,90*64,90*64,cols[0]);
784 	GDrawDrawArc(gw,&cur,0*64,90*64,cols[1]);
785 	GDrawDrawArc(gw,&cur,-90*64,90*64,cols[2]);
786 	GDrawDrawArc(gw,&cur,-180*64,90*64,cols[3]);
787 	cur.x += bw/2; cur.y += bw/2;
788 	cur.width -= bw; cur.height -= bw;
789 	GDrawDrawArc(gw,&cur,90*64,90*64,cols[2]);
790 	GDrawDrawArc(gw,&cur,0*64,90*64,cols[3]);
791 	GDrawDrawArc(gw,&cur,-90*64,90*64,cols[0]);
792 	GDrawDrawArc(gw,&cur,-180*64,90*64,cols[1]);
793 	GDrawSetLineWidth(gw,scale);
794       break;
795       case bt_double: {
796 	int width = (bw+1)/3;
797 	if ( !(width&1) ) {
798 	    if ( 2*(width+1) < bw )
799 		++width;
800 	    else
801 		--width;
802 	}
803 	GDrawSetLineWidth(gw,width);
804 	cur = *pos;
805 	cur.x += inset+width/2; cur.y += inset+width/2;
806 	cur.width -= 2*(inset+width/2)+1; cur.height -= 2*(inset+width/2)+1;
807 	GDrawDrawArc(gw,&cur,90*64,90*64,cols[0]);
808 	GDrawDrawArc(gw,&cur,0*64,90*64,cols[1]);
809 	GDrawDrawArc(gw,&cur,-90*64,90*64,cols[2]);
810 	GDrawDrawArc(gw,&cur,-180*64,90*64,cols[3]);
811 	cur = *pos;
812 	cur.x += inset+bw-(width+1)/2; cur.y += inset+bw-(width+1)/2;
813 	cur.width -= 2*(inset+bw-(width+1)/2)+1; cur.height -= 2*(inset+bw-(width+1)/2)+1;
814 	GDrawDrawArc(gw,&cur,90*64,90*64,cols[0]);
815 	GDrawDrawArc(gw,&cur,0*64,90*64,cols[1]);
816 	GDrawDrawArc(gw,&cur,-90*64,90*64,cols[2]);
817 	GDrawDrawArc(gw,&cur,-180*64,90*64,cols[3]);
818 	GDrawSetLineWidth(gw,scale);
819       } break;
820     }
821     inset += bw;
822 
823     if ( (design->flags & box_foreground_border_inner) ||
824 	    ((design->flags & box_active_border_inner) && state==gs_active)) {
825 	GDrawSetLineWidth(gw,scale);
826 	cur = *pos;
827 	cur.x += inset; cur.y += inset;
828 	cur.width -= 2*inset; cur.height -= 2*inset;
829 	if ( scale>1 ) {
830 	    cur.x += scale/2; cur.y += scale/2;
831 	    cur.width -= scale; cur.height -= scale;
832 	}
833 	--cur.width; --cur.height;
834 	GDrawDrawElipse(gw,&cur,
835 		state == gs_active && (design->flags & box_active_border_inner) ?
836 			design->active_border : color_inner);
837 	inset += scale;
838     }
839 return( inset );
840 }
841 
GBoxDiamondBorder(GWindow gw,GRect * pos,GBox * design,enum gadget_state state,int is_def)842 static int GBoxDiamondBorder(GWindow gw,GRect *pos,GBox *design,
843 	enum gadget_state state, int is_def) {
844     int bw = GDrawPointsToPixels(gw,design->border_width);
845     int inset = 0;
846     int scale = GDrawPointsToPixels(gw,1);
847     enum border_type bt = design->border_type;
848     Color cols[4];
849     Color fg = state==gs_disabled?design->disabled_foreground:
850 		    design->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(gw)):
851 		    design->main_foreground;
852 	Color color_inner = design->border_inner == COLOR_DEFAULT ? fg : design->border_inner;
853 	Color color_outer = design->border_outer == COLOR_DEFAULT ? fg : design->border_outer;
854 
855     FigureBorderCols(design,cols);
856     if ( is_def && (design->flags & box_draw_default) && bt!=bt_none ) {
857 	DrawULTrap(gw,pos,inset,scale,cols[2]);
858 	DrawURTrap(gw,pos,inset,scale,cols[3]);
859 	DrawLRTrap(gw,pos,inset,scale,cols[0]);
860 	DrawLLTrap(gw,pos,inset,scale,cols[1]);
861 	inset += scale + GDrawPointsToPixels(gw,2);
862     }
863 
864     if ( design->flags & box_foreground_border_outer ) {
865 	GPoint pts[5];
866 	GDrawSetLineWidth(gw,scale);
867 	pts[0].x = pos->x+scale/2; pts[0].y = pos->y+pos->height/2;
868 	pts[1].x = pos->x+pos->width/2; pts[1].y = pos->y+scale/2;
869 	pts[2].x = pos->x+pos->width-1-scale/2; pts[2].y = pts[0].y;
870 	pts[3].x = pts[1].x; pts[3].y = pos->y+pos->height-1-scale/2;
871 	pts[4] = pts[0];
872 	GDrawDrawPoly(gw,pts,5,color_outer);
873 	inset += scale;
874     }
875 
876     if ( bt==bt_double && bw<3 )
877 	bt = bt_box;
878     if (( bt==bt_engraved || bt==bt_embossed ) && bw<2 )
879 	bt = bt_box;
880     FigureBorderCols(design,cols);
881 
882     if ( bw!=0 ) switch ( bt ) {
883       case bt_none:
884       break;
885       case bt_box: case bt_raised: case bt_lowered:
886 	DrawULTrap(gw,pos,inset,bw,cols[0]);
887 	DrawURTrap(gw,pos,inset,bw,cols[1]);
888 	DrawLRTrap(gw,pos,inset,bw,cols[2]);
889 	DrawLLTrap(gw,pos,inset,bw,cols[3]);
890       break;
891       case bt_engraved: case bt_embossed:
892 	bw &= ~1;
893 	DrawULTrap(gw,pos,inset,bw/2,cols[0]);
894 	DrawURTrap(gw,pos,inset,bw/2,cols[1]);
895 	DrawLRTrap(gw,pos,inset,bw/2,cols[2]);
896 	DrawLLTrap(gw,pos,inset,bw/2,cols[3]);
897 
898 	inset += bw/2;
899 	DrawULTrap(gw,pos,inset,bw/2,cols[2]);
900 	DrawURTrap(gw,pos,inset,bw/2,cols[3]);
901 	DrawLRTrap(gw,pos,inset,bw/2,cols[0]);
902 	DrawLLTrap(gw,pos,inset,bw/2,cols[1]);
903 	inset -= bw/2;
904       break;
905       case bt_double: {
906 	int width = (bw+1)/3;
907 	DrawULTrap(gw,pos,inset,width,cols[0]);
908 	DrawURTrap(gw,pos,inset,width,cols[1]);
909 	DrawLRTrap(gw,pos,inset,width,cols[2]);
910 	DrawLLTrap(gw,pos,inset,width,cols[3]);
911 
912 	inset += bw-width;
913 	DrawULTrap(gw,pos,inset,width,cols[0]);
914 	DrawURTrap(gw,pos,inset,width,cols[1]);
915 	DrawLRTrap(gw,pos,inset,width,cols[2]);
916 	DrawLLTrap(gw,pos,inset,width,cols[3]);
917 	inset -= bw-width;
918       } break;
919     }
920     inset += bw;
921 
922     if ( (design->flags & box_foreground_border_inner) ||
923 	    ((design->flags & box_active_border_inner) && state==gs_active)) {
924 	GPoint pts[5];
925 	GDrawSetLineWidth(gw,scale);
926 	pts[0].x = pos->x+inset+scale/2; pts[0].y = pos->y+pos->height/2;
927 	pts[1].x = pos->x+pos->width/2; pts[1].y = pos->y+inset+scale/2;
928 	pts[2].x = pos->x+pos->width-1-inset-scale/2; pts[2].y = pts[0].y;
929 	pts[3].x = pts[1].x; pts[3].y = pos->y+pos->height-1-inset-scale/2;
930 	pts[4] = pts[0];
931 	GDrawDrawPoly(gw,pts,5,
932 		state == gs_active && (design->flags & box_active_border_inner) ?
933 			design->active_border : color_inner);
934 	inset += scale;
935     }
936 return( inset );
937 }
938 
GBoxDrawBorder(GWindow gw,GRect * pos,GBox * design,enum gadget_state state,int is_default)939 int GBoxDrawBorder(GWindow gw,GRect *pos,GBox *design,enum gadget_state state,
940 	int is_default) {
941     int ret = 0;
942 
943     if ( state == gs_disabled )
944 	GDrawSetStippled(gw,1,0,0);
945     switch ( design->border_shape ) {
946       case bs_rect:
947 	ret = GBoxRectBorder(gw,pos,design,state,is_default);
948       break;
949       case bs_roundrect:
950 	ret = GBoxRoundRectBorder(gw,pos,design,state,is_default);
951       break;
952       case bs_elipse:
953 	ret = GBoxElipseBorder(gw,pos,design,state,is_default);
954       break;
955       case bs_diamond:
956 	ret = GBoxDiamondBorder(gw,pos,design,state,is_default);
957       break;
958     }
959     if ( state == gs_disabled )
960 	GDrawSetStippled(gw,0,0,0);
961 return( ret );
962 }
963 
BoxGradientRect(GWindow gw,GRect * r,Color start,Color end)964 static void BoxGradientRect(GWindow gw, GRect *r, Color start, Color end)
965 {
966     int xend = r->x + r->width - 1;
967     int i;
968 
969     int rstart = COLOR_RED(start);
970     int gstart = COLOR_GREEN(start);
971     int bstart = COLOR_BLUE(start);
972     int rdiff = COLOR_RED(end) - rstart;
973     int gdiff = COLOR_GREEN(end) - gstart;
974     int bdiff = COLOR_BLUE(end) - bstart;
975 
976     if (r->height <= 0)
977 return;
978 
979     for (i = 0; i < r->height; i++)
980 	GDrawDrawLine(gw, r->x, r->y + i, xend, r->y + i, COLOR_CREATE(
981 		rstart + rdiff * i / r->height,
982 		gstart + gdiff * i / r->height,
983 		bstart + bdiff * i / r->height ));
984 }
985 
BoxGradientElipse(GWindow gw,GRect * r,Color start,Color end)986 static void BoxGradientElipse(GWindow gw, GRect *r, Color start, Color end)
987 {
988     /*
989      * Ellipse borders are 1 unit wider and 1 unit higher than the passed GRect.
990      * With corrected values the gradient-fill will fit its corresponding border.
991      */
992     int correctedwidth = r->width + 1;
993     int correctedheight = r->height + 1;
994 
995     int xend = r->x + correctedwidth - 1;
996     int yend = r->y + correctedheight - 1;
997     int i, xoff;
998 
999     double a = (double)correctedwidth / 2.0;
1000     double b = (double)correctedheight / 2.0;
1001     double precalc = (a * a) / (b * b);
1002 
1003     int rstart = COLOR_RED(start);
1004     int gstart = COLOR_GREEN(start);
1005     int bstart = COLOR_BLUE(start);
1006     int rdiff = COLOR_RED(end) - rstart;
1007     int gdiff = COLOR_GREEN(end) - gstart;
1008     int bdiff = COLOR_BLUE(end) - bstart;
1009 
1010     if (correctedheight <= 0)
1011 return;
1012 
1013     for (i = 0; i < (correctedheight + 1) / 2; ++i) {
1014 	xoff = lrint(a - sqrt(precalc * (double)(i * (correctedheight - i)) ));
1015 
1016 	GDrawDrawLine(gw, r->x + xoff, r->y + i, xend - xoff, r->y + i, COLOR_CREATE(
1017 		rstart + rdiff * i / correctedheight,
1018 		gstart + gdiff * i / correctedheight,
1019 		bstart + bdiff * i / correctedheight ));
1020 
1021 	GDrawDrawLine(gw, r->x + xoff, yend - i, xend - xoff, yend - i, COLOR_CREATE(
1022 		rstart + rdiff * (correctedheight - i) / correctedheight,
1023 		gstart + gdiff * (correctedheight - i) / correctedheight,
1024 		bstart + bdiff * (correctedheight - i) / correctedheight ));
1025     }
1026 }
1027 
BoxGradientRoundRect(GWindow gw,GRect * r,int rr,Color start,Color end)1028 static void BoxGradientRoundRect(GWindow gw, GRect *r, int rr, Color start, Color end)
1029 {
1030     int radius = rr <= (r->height+1)/2 ? (rr > 0 ? rr : 0) : (r->height+1)/2;
1031     int xend = r->x + r->width - 1;
1032     int yend = r->y + r->height - 1;
1033     int precalc = radius * 2 - 1;
1034     int i, xoff;
1035 
1036     int rstart = COLOR_RED(start);
1037     int gstart = COLOR_GREEN(start);
1038     int bstart = COLOR_BLUE(start);
1039     int rdiff = COLOR_RED(end) - rstart;
1040     int gdiff = COLOR_GREEN(end) - gstart;
1041     int bdiff = COLOR_BLUE(end) - bstart;
1042 
1043     if (r->height <= 0)
1044 return;
1045 
1046     for (i = 0; i < radius; i++) {
1047 	xoff = radius - lrint(sqrt( (double)(i * (precalc - i)) ));
1048 
1049 	GDrawDrawLine(gw, r->x + xoff, r->y + i, xend - xoff, r->y + i, COLOR_CREATE(
1050 		rstart + rdiff * i / r->height,
1051 		gstart + gdiff * i / r->height,
1052 		bstart + bdiff * i / r->height ));
1053 
1054 	GDrawDrawLine(gw, r->x + xoff, yend - i, xend - xoff, yend - i, COLOR_CREATE(
1055 		rstart + rdiff * (r->height - i) / r->height,
1056 		gstart + gdiff * (r->height - i) / r->height,
1057 		bstart + bdiff * (r->height - i) / r->height ));
1058     }
1059 
1060     for (i = radius; i < r->height - radius; i++)
1061 	GDrawDrawLine(gw, r->x, r->y + i, xend, r->y + i, COLOR_CREATE(
1062 		rstart + rdiff * i / r->height,
1063 		gstart + gdiff * i / r->height,
1064 		bstart + bdiff * i / r->height ));
1065 }
1066 
GBoxDrawBackground(GWindow gw,GRect * pos,GBox * design,enum gadget_state state,int is_default)1067 void GBoxDrawBackground(GWindow gw,GRect *pos,GBox *design,
1068 	enum gadget_state state, int is_default) {
1069     Color gbg = GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(gw));
1070     Color mbg = design->main_background==COLOR_DEFAULT?gbg:design->main_background;
1071     Color dbg = design->disabled_background==COLOR_DEFAULT?gbg:design->disabled_background;
1072     Color pbg = design->depressed_background==COLOR_DEFAULT?gbg:design->depressed_background;
1073     Color ibg;
1074     int def_off = is_default && (design->flags & box_draw_default) ?
1075 	    GDrawPointsToPixels(gw,1) + GDrawPointsToPixels(gw,2): 0;
1076 
1077     if ( state == gs_disabled ) {
1078 	ibg=dbg;
1079 	GDrawSetStippled(gw,1,0,0);
1080     } else if ( state == gs_pressedactive && (design->flags & box_do_depressed_background ))
1081 	ibg=pbg;
1082     else
1083 	ibg=mbg;
1084 
1085     if ( design->border_shape==bs_rect && (def_off==0 || mbg==ibg) && !(design->flags & box_gradient_bg)) {
1086 	GDrawFillRect(gw,pos,ibg);
1087     } else {
1088 	/* GDrawFillRect(gw,pos,mbg); */
1089 	if ( design->border_shape==bs_rect ) {
1090 	    GRect cur;
1091 	    cur = *pos;
1092 	    cur.x += def_off; cur.y += def_off; cur.width -= 2*def_off; cur.height -= 2*def_off;
1093 	    if ( design->flags & box_gradient_bg )
1094 		BoxGradientRect(gw,&cur,ibg,design->gradient_bg_end);
1095 	    else
1096 		GDrawFillRect(gw,&cur,ibg);
1097 	} else if ( design->border_shape==bs_elipse ) {
1098 	    GRect cur;
1099 	    cur = *pos; --cur.width; --cur.height;
1100 	    if ( def_off ) {
1101 		cur.x += def_off; cur.y += def_off; cur.width -= 2*def_off; cur.height -= 2*def_off;
1102 	    }
1103 	    if ( design->flags & box_gradient_bg )
1104 		BoxGradientElipse(gw,&cur,ibg,design->gradient_bg_end);
1105 	    else
1106 		GDrawFillElipse(gw,&cur,ibg);
1107 	} else if ( design->border_shape==bs_diamond ) {
1108 	    GPoint pts[5];
1109 	    pts[0].x = pos->x+pos->width/2;	    pts[0].y = pos->y+def_off;
1110 	    pts[1].x = pos->x+pos->width-1-def_off; pts[1].y = pos->y+pos->height/2;
1111 	    pts[2].x = pts[0].x;		    pts[2].y = pos->y+pos->height-1-def_off;
1112 	    pts[3].x = pos->x+def_off;		    pts[3].y = pts[1].y;
1113 	    pts[4] = pts[0];
1114 	    GDrawFillPoly(gw,pts,5,ibg);
1115 	} else {
1116 	    int rr = GDrawPointsToPixels(gw,design->rr_radius);
1117 
1118 	    if ( rr==0 )
1119 		rr = pos->width/2-def_off;
1120 	    if ( rr>pos->width/2-def_off )
1121 		rr = pos->width/2-def_off;
1122 	    if ( rr>pos->height/2-def_off )
1123 		rr = pos->height/2-def_off;
1124 
1125 	    if ( design->flags & box_gradient_bg )
1126 		BoxGradientRoundRect(gw,pos,rr,ibg,design->gradient_bg_end);
1127 	    else
1128 		GDrawFillRoundRect(gw,pos,rr,ibg);
1129 	}
1130     }
1131     if ( state == gs_disabled )
1132 	GDrawSetStippled(gw,0,0,0);
1133 }
1134 
GBoxBorderWidth(GWindow gw,GBox * box)1135 int GBoxBorderWidth(GWindow gw, GBox *box) {
1136     int scale = GDrawPointsToPixels(gw,1);
1137     int bp = GDrawPointsToPixels(gw,box->border_width)+
1138 	     GDrawPointsToPixels(gw,box->padding)+
1139 	     ((box->flags & (box_foreground_border_outer|box_foreground_shadow_outer))?scale:0)+
1140 	     ((box->flags &
1141 		 (box_foreground_border_inner|box_active_border_inner))?scale:0);
1142 return( bp );
1143 }
1144 
GBoxExtraSpace(GGadget * g)1145 int GBoxExtraSpace(GGadget *g) {
1146     if ( g->state==gs_invisible || !(g->box->flags & box_draw_default) ||
1147 	    !GGadgetIsDefault(g))
1148 return( 0 );
1149 
1150 return( GDrawPointsToPixels(g->base,1) + GDrawPointsToPixels(g->base,2) );
1151 }
1152 
1153 /* Does not include the padding */
GBoxDrawnWidth(GWindow gw,GBox * box)1154 int GBoxDrawnWidth(GWindow gw, GBox *box) {
1155     int scale = GDrawPointsToPixels(gw,1);
1156     int bp = GDrawPointsToPixels(gw,box->border_width)+
1157 	     ((box->flags & (box_foreground_border_outer|box_foreground_shadow_outer))?scale:0)+
1158 	     ((box->flags &
1159 		 (box_foreground_border_inner|box_active_border_inner))?scale:0);
1160 return( bp );
1161 }
1162 
GBoxDrawTabBackground(GWindow pixmap,GRect * rect,int radius,Color color)1163 static void GBoxDrawTabBackground(GWindow pixmap, GRect *rect, int radius, Color color)
1164 {
1165     GRect older, r = *rect;
1166 
1167     GDrawPushClip(pixmap,rect,&older);
1168     GDrawSetLineWidth(pixmap,1);
1169     r.height*=2;
1170     if (2*radius>=r.height) r.height=2*radius+1;
1171     GDrawFillRoundRect(pixmap, &r, radius, color);
1172     GDrawPopClip(pixmap,&older);
1173 }
1174 
GBoxDrawTabOutline(GWindow pixmap,GGadget * g,int x,int y,int width,int rowh,int active)1175 void GBoxDrawTabOutline(GWindow pixmap, GGadget *g, int x, int y,
1176 	int width, int rowh, int active ) {
1177     GRect r;
1178     GBox *design = g->box;
1179     int bp = GBoxBorderWidth(pixmap,design);
1180     int dw = GBoxDrawnWidth(pixmap,design);
1181     int rr = GDrawPointsToPixels(pixmap,design->rr_radius);
1182     int scale = GDrawPointsToPixels(pixmap,1);
1183     int bw = GDrawPointsToPixels(pixmap,design->border_width);
1184     int inset = 0;
1185     enum border_type bt = design->border_type;
1186     Color cols[4];
1187 
1188     Color fg = g->state==gs_disabled?design->disabled_foreground:
1189 		    design->main_foreground==COLOR_DEFAULT?GDrawGetDefaultForeground(GDrawGetDisplayOfWindow(pixmap)):
1190 		    design->main_foreground;
1191 
1192     Color color_inner = design->border_inner == COLOR_DEFAULT ? fg : design->border_inner;
1193     Color color_outer = design->border_outer == COLOR_DEFAULT ? fg : design->border_outer;
1194 
1195     Color gbg = GDrawGetDefaultBackground(GDrawGetDisplayOfWindow(pixmap));
1196     Color mbg = design->main_background==COLOR_DEFAULT?gbg:design->main_background;
1197     Color dbg = design->disabled_background==COLOR_DEFAULT?gbg:design->disabled_background;
1198     Color pbg = design->depressed_background==COLOR_DEFAULT?gbg:design->depressed_background;
1199     Color ibg;
1200 
1201     r.x = x; r.y = y; r.width = width; r.height = rowh;
1202 
1203     if ( rr==0 )
1204         rr = GDrawPointsToPixels(pixmap,3);
1205 
1206     if ( !(scale&1)) --scale;
1207     if ( scale==0 ) scale = 1;
1208 
1209     FigureBorderCols(design,cols);
1210 
1211     if ( active ) {
1212         r.x -= bp; r.y -= bp; r.width += 2*bp; r.height += dw+bp;
1213     }
1214 
1215     if ( g->state == gs_disabled ) {
1216         ibg=dbg;
1217         GDrawSetStippled(pixmap,1,0,0);
1218     } else if ( !active && (design->flags & box_do_depressed_background ))
1219         ibg=pbg;
1220     else
1221         ibg=mbg;
1222 
1223     GBoxDrawTabBackground(pixmap,&r,rr,ibg);
1224     if ( g->state == gs_disabled )
1225         GDrawSetStippled(pixmap,0,0,0);
1226 
1227     if ( design->flags & (box_foreground_border_outer|box_foreground_shadow_outer) ) {
1228 	GDrawSetLineWidth(pixmap,scale);
1229 	if ( design->flags&box_foreground_border_outer )
1230 	    DrawRoundTab(pixmap,&r,scale/2,rr,color_outer,color_outer,color_outer,color_outer,active);
1231 	else
1232 	    GDrawDrawLine(pixmap,r.x+r.width-1,r.y+rr,r.x+r.width-1,r.y+r.height-1,fg);
1233 	inset += scale;
1234     }
1235 
1236     if ( bt==bt_double && bw<3 )
1237 	bt = bt_box;
1238     if (( bt==bt_engraved || bt==bt_embossed ) && bw<2 )
1239 	bt = bt_box;
1240 
1241     if ( bw!=0 ) switch ( bt ) {
1242       case bt_none:
1243       break;
1244       case bt_box: case bt_raised: case bt_lowered:
1245 	if ( !(bw&1) ) --bw;
1246 	GDrawSetLineWidth(pixmap,bw);
1247 	DrawRoundTab(pixmap,&r,inset+bw/2,rr,cols[0],cols[1],cols[2],cols[3],active);
1248       break;
1249       case bt_engraved: case bt_embossed:
1250 	bw &= ~1;
1251 	if ( !(bw&2 ) )
1252 	    bw -= 2;
1253 	if ( bw<=0 )
1254 	    bw = 2;
1255 	GDrawSetLineWidth(pixmap,bw/2);
1256 	DrawRoundTab(pixmap,&r,inset+bw/4,rr,cols[0],cols[1],cols[2],cols[3],active);
1257 	DrawRoundTab(pixmap,&r,inset+bw/2+bw/4,rr,cols[2],cols[3],cols[0],cols[1],active);
1258       break;
1259       case bt_double: {
1260 	int width = (bw+1)/3;
1261 	if ( !(width&1) ) {
1262 	    if ( 2*(width+1) < bw )
1263 		++width;
1264 	    else
1265 		--width;
1266 	}
1267 	GDrawSetLineWidth(pixmap,width);
1268 	DrawRoundTab(pixmap,&r,inset+width/2,rr,cols[0],cols[1],cols[2],cols[3],active);
1269 	DrawRoundTab(pixmap,&r,inset+bw-(width+1)/2,rr,cols[0],cols[1],cols[2],cols[3],active);
1270       } break;
1271     }
1272     inset += bw;
1273 
1274     if ( (design->flags & box_foreground_border_inner) ) {
1275 	GDrawSetLineWidth(pixmap,scale);
1276 	DrawRoundTab(pixmap,&r,inset+scale/2,rr,color_inner,color_inner,color_inner,color_inner,active);
1277 	inset += scale;
1278     }
1279 }
1280