blob: 28a50c7d1222f04874dc03b8236bc317e4c239ea [file] [log] [blame]
DRC2ff39b82011-07-28 08:38:59 +00001//
2// "$Id: fl_plastic.cxx 7903 2010-11-28 21:06:39Z matt $"
3//
4// "Plastic" drawing routines for the Fast Light Tool Kit (FLTK).
5//
6// These box types provide a cross between Aqua and KDE buttons; kindof
7// like translucent plastic buttons...
8//
9// Copyright 2001-2010 by Michael Sweet.
10//
11// This library is free software; you can redistribute it and/or
12// modify it under the terms of the GNU Library General Public
13// License as published by the Free Software Foundation; either
14// version 2 of the License, or (at your option) any later version.
15//
16// This library is distributed in the hope that it will be useful,
17// but WITHOUT ANY WARRANTY; without even the implied warranty of
18// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19// Library General Public License for more details.
20//
21// You should have received a copy of the GNU Library General Public
22// License along with this library; if not, write to the Free Software
23// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
24// USA.
25//
26// Please report all bugs and problems on the following page:
27//
28// http://www.fltk.org/str.php
29//
30
31// Box drawing code for an obscure box type.
32// These box types are in separate files so they are not linked
33// in if not used.
34
35#include <FL/Fl.H>
36#include <FL/fl_draw.H>
37#include "flstring.h"
38
39//
40// Uncomment the following line to restore the old plastic box type
41// appearance.
42//
43
44//#define USE_OLD_PLASTIC_BOX
45#define USE_OLD_PLASTIC_COLOR
46
47extern uchar *fl_gray_ramp();
48
49inline Fl_Color shade_color(uchar gc, Fl_Color bc) {
50#ifdef USE_OLD_PLASTIC_COLOR
51 return fl_color_average((Fl_Color)gc, bc, 0.75f);
52#else
53 unsigned grgb = Fl::get_color((Fl_Color)gc),
54 brgb = Fl::get_color(bc);
55 int red, green, blue, gray;
56
57
58 gray = ((grgb >> 24) & 255);
59 red = gray * ((brgb >> 24) & 255) / 255 + gray * gray / 510;
60 gray = ((grgb >> 16) & 255);
61 green = gray * ((brgb >> 16) & 255) / 255 + gray * gray / 510;
62 gray = ((grgb >> 8) & 255);
63 blue = gray * ((brgb >> 8) & 255) / 255 + gray * gray / 510;
64
65 if (red > 255)
66 red = 255;
67
68 if (green > 255)
69 green = 255;
70
71 if (blue > 255)
72 blue = 255;
73
74 if (Fl::draw_box_active())
75 return fl_rgb_color(red, green, blue);
76 else
77 return fl_color_average(FL_GRAY, fl_rgb_color(red, green, blue), 0.75f);
78#endif // USE_OLD_PLASTIC_COLOR
79}
80
81
82static void frame_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) {
83 uchar *g = fl_gray_ramp();
84 int b = strlen(c) / 4 + 1;
85
86 for (x += b, y += b, w -= 2 * b, h -= 2 * b; b > 1; b --)
87 {
88 // Draw lines around the perimeter of the button, 4 colors per
89 // circuit.
90 fl_color(shade_color(g[(int)*c++], bc));
91 fl_line(x, y + h + b, x + w - 1, y + h + b, x + w + b - 1, y + h);
92 fl_color(shade_color(g[(int)*c++], bc));
93 fl_line(x + w + b - 1, y + h, x + w + b - 1, y, x + w - 1, y - b);
94 fl_color(shade_color(g[(int)*c++], bc));
95 fl_line(x + w - 1, y - b, x, y - b, x - b, y);
96 fl_color(shade_color(g[(int)*c++], bc));
97 fl_line(x - b, y, x - b, y + h, x, y + h + b);
98 }
99}
100
101
102static void frame_round(int x, int y, int w, int h, const char *c, Fl_Color bc) {
103 uchar *g = fl_gray_ramp();
104 int b = strlen(c) / 4 + 1;
105
106 if (w==h) {
107 for (; b > 1; b --, x ++, y ++, w -= 2, h -= 2)
108 {
109 fl_color(shade_color(g[(int)*c++], bc));
110 fl_arc(x, y, w, h, 45.0, 135.0);
111 fl_color(shade_color(g[(int)*c++], bc));
112 fl_arc(x, y, w, h, 315.0, 405.0);
113 fl_color(shade_color(g[(int)*c++], bc));
114 fl_arc(x, y, w, h, 225.0, 315.0);
115 fl_color(shade_color(g[(int)*c++], bc));
116 fl_arc(x, y, w, h, 135.0, 225.0);
117 }
118 } else if (w>h) {
119 int d = h/2;
120 for (; b > 1; d--, b --, x ++, y ++, w -= 2, h -= 2)
121 {
122 fl_color(shade_color(g[(int)*c++], bc));
123 fl_arc(x, y, h, h, 90.0, 135.0);
124 fl_xyline(x+d, y, x+w-d);
125 fl_arc(x+w-h, y, h, h, 45.0, 90.0);
126 fl_color(shade_color(g[(int)*c++], bc));
127 fl_arc(x+w-h, y, h, h, 315.0, 405.0);
128 fl_color(shade_color(g[(int)*c++], bc));
129 fl_arc(x+w-h, y, h, h, 270.0, 315.0);
130 fl_xyline(x+d, y+h-1, x+w-d);
131 fl_arc(x, y, h, h, 225.0, 270.0);
132 fl_color(shade_color(g[(int)*c++], bc));
133 fl_arc(x, y, h, h, 135.0, 225.0);
134 }
135 } else if (w<h) {
136 int d = w/2;
137 for (; b > 1; d--, b --, x ++, y ++, w -= 2, h -= 2)
138 {
139 fl_color(shade_color(g[(int)*c++], bc));
140 fl_arc(x, y, w, w, 45.0, 135.0);
141 fl_color(shade_color(g[(int)*c++], bc));
142 fl_arc(x, y, w, w, 0.0, 45.0);
143 fl_yxline(x+w-1, y+d, y+h-d);
144 fl_arc(x, y+h-w, w, w, 315.0, 360.0);
145 fl_color(shade_color(g[(int)*c++], bc));
146 fl_arc(x, y+h-w, w, w, 225.0, 315.0);
147 fl_color(shade_color(g[(int)*c++], bc));
148 fl_arc(x, y+h-w, w, w, 180.0, 225.0);
149 fl_yxline(x, y+d, y+h-d);
150 fl_arc(x, y, w, w, 135.0, 180.0);
151 }
152 }
153}
154
155
156static void shade_rect(int x, int y, int w, int h, const char *c, Fl_Color bc) {
157 uchar *g = fl_gray_ramp();
158 int i, j;
159 int clen = strlen(c) - 1;
160 int chalf = clen / 2;
161 int cstep = 1;
162
163 if (h < (w * 2)) {
164 // Horizontal shading...
165 if (clen >= h) cstep = 2;
166
167 for (i = 0, j = 0; j < chalf; i ++, j += cstep) {
168 // Draw the top line and points...
169 fl_color(shade_color(g[(int)c[i]], bc));
170 fl_xyline(x + 1, y + i, x + w - 2);
171
172 fl_color(shade_color(g[c[i] - 2], bc));
173 fl_point(x, y + i + 1);
174 fl_point(x + w - 1, y + i + 1);
175
176 // Draw the bottom line and points...
177 fl_color(shade_color(g[(int)c[clen - i]], bc));
178 fl_xyline(x + 1, y + h - i, x + w - 2);
179
180 fl_color(shade_color(g[c[clen - i] - 2], bc));
181 fl_point(x, y + h - i);
182 fl_point(x + w - 1, y + h - i);
183 }
184
185 // Draw the interior and sides...
186 i = chalf / cstep;
187
188 fl_color(shade_color(g[(int)c[chalf]], bc));
189 fl_rectf(x + 1, y + i, w - 2, h - 2 * i + 1);
190
191 fl_color(shade_color(g[c[chalf] - 2], bc));
192 fl_yxline(x, y + i, y + h - i);
193 fl_yxline(x + w - 1, y + i, y + h - i);
194 } else {
195 // Vertical shading...
196 if (clen >= w) cstep = 2;
197
198 for (i = 0, j = 0; j < chalf; i ++, j += cstep) {
199 // Draw the left line and points...
200 fl_color(shade_color(g[(int)c[i]], bc));
201 fl_yxline(x + i, y + 1, y + h - 1);
202
203 fl_color(shade_color(g[c[i] - 2], bc));
204 fl_point(x + i + 1, y);
205 fl_point(x + i + 1, y + h);
206
207 // Draw the right line and points...
208 fl_color(shade_color(g[(int)c[clen - i]], bc));
209 fl_yxline(x + w - 1 - i, y + 1, y + h - 1);
210
211 fl_color(shade_color(g[c[clen - i] - 2], bc));
212 fl_point(x + w - 2 - i, y);
213 fl_point(x + w - 2 - i, y + h);
214 }
215
216 // Draw the interior, top, and bottom...
217 i = chalf / cstep;
218
219 fl_color(shade_color(g[(int)c[chalf]], bc));
220 fl_rectf(x + i, y + 1, w - 2 * i, h - 1);
221
222 fl_color(shade_color(g[c[chalf] - 2], bc));
223 fl_xyline(x + i, y, x + w - i);
224 fl_xyline(x + i, y + h, x + w - i);
225 }
226}
227
228static void shade_round(int x, int y, int w, int h, const char *c, Fl_Color bc) {
229 uchar *g = fl_gray_ramp();
230 int i;
231 int clen = strlen(c) - 1;
232 int chalf = clen / 2;
233
234 if (w>h) {
235 int d = h/2;
236 const int na = 8;
237 for (i=0; i<chalf; i++, d--, x++, y++, w-=2, h-=2)
238 {
239 fl_color(shade_color(g[(int)c[i]], bc));
240 fl_pie(x, y, h, h, 90.0, 135.0+i*na);
241 fl_xyline(x+d, y, x+w-d);
242 fl_pie(x+w-h, y, h, h, 45.0+i*na, 90.0);
243 fl_color(shade_color(g[(int)c[i] - 2], bc));
244 fl_pie(x+w-h, y, h, h, 315.0+i*na, 405.0+i*na);
245 fl_color(shade_color(g[(int)c[clen - i]], bc));
246 fl_pie(x+w-h, y, h, h, 270.0, 315.0+i*na);
247 fl_xyline(x+d, y+h-1, x+w-d);
248 fl_pie(x, y, h, h, 225.0+i*na, 270.0);
249 fl_color(shade_color(g[c[(int)clen - i] - 2], bc));
250 fl_pie(x, y, h, h, 135.0+i*na, 225.0+i*na);
251 }
252 fl_color(shade_color(g[(int)c[chalf]], bc));
253 fl_rectf(x+d, y, w-h+1, h+1);
254 fl_pie(x, y, h, h, 90.0, 270.0);
255 fl_pie(x+w-h, y, h, h, 270.0, 90.0);
256 } else {
257 int d = w/2;
258 const int na = 8;
259 for (i=0; i<chalf; i++, d--, x++, y++, w-=2, h-=2)
260 {
261 fl_color(shade_color(g[(int)c[i]], bc));
262 fl_pie(x, y, w, w, 45.0+i*na, 135.0+i*na);
263 fl_color(shade_color(g[c[i] - 2], bc));
264 fl_pie(x, y, w, w, 0.0, 45.0+i*na);
265 fl_yxline(x+w-1, y+d, y+h-d);
266 fl_pie(x, y+h-w, w, w, 315.0+i*na, 360.0);
267 fl_color(shade_color(g[(int)c[clen - i]], bc));
268 fl_pie(x, y+h-w, w, w, 225.0+i*na, 315.0+i*na);
269 fl_color(shade_color(g[c[clen - i] - 2], bc));
270 fl_pie(x, y+h-w, w, w, 180.0, 225.0+i*na);
271 fl_yxline(x, y+d, y+h-d);
272 fl_pie(x, y, w, w, 135.0+i*na, 180.0);
273 }
274 fl_color(shade_color(g[(int)c[chalf]], bc));
275 fl_rectf(x, y+d, w+1, h-w+1);
276 fl_pie(x, y, w, w, 0.0, 180.0);
277 fl_pie(x, y+h-w, w, w, 180.0, 360.0);
278 }
279}
280
281
282static void up_frame(int x, int y, int w, int h, Fl_Color c) {
283 frame_rect(x, y, w, h - 1, "KLDIIJLM", c);
284}
285
286
287static void narrow_thin_box(int x, int y, int w, int h, Fl_Color c) {
288 if (h<=0 || w<=0) return;
289 uchar *g = fl_gray_ramp();
290 fl_color(shade_color(g['R'], c));
291 fl_rectf(x+1, y+1, w-2, h-2);
292 fl_color(shade_color(g['I'], c));
293 if (w > 1) {
294 fl_xyline(x+1, y, x+w-2);
295 fl_xyline(x+1, y+h-1, x+w-2);
296 }
297 if (h > 1) {
298 fl_yxline(x, y+1, y+h-2);
299 fl_yxline(x+w-1, y+1, y+h-2);
300 }
301}
302
303
304static void thin_up_box(int x, int y, int w, int h, Fl_Color c) {
305#ifdef USE_OLD_PLASTIC_BOX
306 shade_rect(x + 2, y + 2, w - 4, h - 5, "RVQNOPQRSTUVWVQ", c);
307 up_frame(x, y, w, h, c);
308#else
309 if (w > 4 && h > 4) {
310 shade_rect(x + 1, y + 1, w - 2, h - 3, "RQOQSUWQ", c);
311 frame_rect(x, y, w, h - 1, "IJLM", c);
312 } else {
313 narrow_thin_box(x, y, w, h, c);
314 }
315#endif // USE_OLD_PLASTIC_BOX
316}
317
318
319static void up_box(int x, int y, int w, int h, Fl_Color c) {
320#ifdef USE_OLD_PLASTIC_BOX
321 shade_rect(x + 2, y + 2, w - 4, h - 5, "RVQNOPQRSTUVWVQ", c);
322 up_frame(x, y, w, h, c);
323#else
324 if (w > 8 && h > 8) {
325 shade_rect(x + 1, y + 1, w - 2, h - 3, "RVQNOPQRSTUVWVQ", c);
326 frame_rect(x, y, w, h - 1, "IJLM", c);
327 } else {
328 thin_up_box(x, y, w, h, c);
329 }
330#endif // USE_OLD_PLASTIC_BOX
331}
332
333
334static void up_round(int x, int y, int w, int h, Fl_Color c) {
335 shade_round(x, y, w, h, "RVQNOPQRSTUVWVQ", c);
336 frame_round(x, y, w, h, "IJLM", c);
337}
338
339
340static void down_frame(int x, int y, int w, int h, Fl_Color c) {
341 frame_rect(x, y, w, h - 1, "LLLLTTRR", c);
342}
343
344
345static void down_box(int x, int y, int w, int h, Fl_Color c) {
346 if (w > 6 && h > 6) {
347 shade_rect(x + 2, y + 2, w - 4, h - 5, "STUVWWWVT", c);
348 down_frame(x, y, w, h, c);
349 }
350 else {
351 narrow_thin_box(x, y, w, h, c);
352 }
353}
354
355
356static void down_round(int x, int y, int w, int h, Fl_Color c) {
357 shade_round(x, y, w, h, "STUVWWWVT", c);
358 frame_round(x, y, w, h, "IJLM", c);
359}
360
361
362extern void fl_internal_boxtype(Fl_Boxtype, Fl_Box_Draw_F*);
363
364
365Fl_Boxtype fl_define_FL_PLASTIC_UP_BOX() {
366 fl_internal_boxtype(_FL_PLASTIC_UP_BOX, up_box);
367 fl_internal_boxtype(_FL_PLASTIC_DOWN_BOX, down_box);
368 fl_internal_boxtype(_FL_PLASTIC_UP_FRAME, up_frame);
369 fl_internal_boxtype(_FL_PLASTIC_DOWN_FRAME, down_frame);
370 fl_internal_boxtype(_FL_PLASTIC_THIN_UP_BOX, thin_up_box);
371 fl_internal_boxtype(_FL_PLASTIC_THIN_DOWN_BOX, down_box);
372 fl_internal_boxtype(_FL_PLASTIC_ROUND_UP_BOX, up_round);
373 fl_internal_boxtype(_FL_PLASTIC_ROUND_DOWN_BOX, down_round);
374
375 return _FL_PLASTIC_UP_BOX;
376}
377
378
379//
380// End of "$Id: fl_plastic.cxx 7903 2010-11-28 21:06:39Z matt $".
381//