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