1 /* gradient.c - renders gradients
3 * Raster graphics library
5 * Copyright (c) 1997-2000 Alfredo K. Kojima
6 * Copyright (c) 1998-2000 Dan Pascu
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library; if not, write to the Free
20 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
34 static RImage
*renderHGradient(unsigned width
, unsigned height
,
35 int r0
, int g0
, int b0
,
36 int rf
, int gf
, int bf
);
37 static RImage
*renderVGradient(unsigned width
, unsigned height
,
38 int r0
, int g0
, int b0
,
39 int rf
, int gf
, int bf
);
40 static RImage
*renderDGradient(unsigned width
, unsigned height
,
41 int r0
, int g0
, int b0
,
42 int rf
, int gf
, int bf
);
44 static RImage
*renderMHGradient(unsigned width
, unsigned height
,
45 RColor
**colors
, int count
);
46 static RImage
*renderMVGradient(unsigned width
, unsigned height
,
47 RColor
**colors
, int count
);
48 static RImage
*renderMDGradient(unsigned width
, unsigned height
,
49 RColor
**colors
, int count
);
52 RRenderMultiGradient(unsigned width
, unsigned height
, RColor
**colors
, int style
)
57 while (colors
[count
]!=NULL
) count
++;
61 case RHorizontalGradient
:
62 return renderMHGradient(width
, height
, colors
, count
);
63 case RVerticalGradient
:
64 return renderMVGradient(width
, height
, colors
, count
);
65 case RDiagonalGradient
:
66 return renderMDGradient(width
, height
, colors
, count
);
68 } else if (count
> 1) {
69 return RRenderGradient(width
, height
, colors
[0], colors
[1], style
);
70 } else if (count
> 0) {
71 return RRenderGradient(width
, height
, colors
[0], colors
[0], style
);
80 RRenderGradient(unsigned width
, unsigned height
, RColor
*from
, RColor
*to
,
84 case RHorizontalGradient
:
85 return renderHGradient(width
, height
, from
->red
, from
->green
,
86 from
->blue
, to
->red
, to
->green
, to
->blue
);
87 case RVerticalGradient
:
88 return renderVGradient(width
, height
, from
->red
, from
->green
,
89 from
->blue
, to
->red
, to
->green
, to
->blue
);
91 case RDiagonalGradient
:
92 return renderDGradient(width
, height
, from
->red
, from
->green
,
93 from
->blue
, to
->red
, to
->green
, to
->blue
);
101 *----------------------------------------------------------------------
103 * Renders a horizontal linear gradient of the specified size in the
104 * RImage format with a border of the specified type.
107 * A 24bit RImage with the gradient (no alpha channel).
111 *----------------------------------------------------------------------
114 renderHGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
,
115 int rf
, int gf
, int bf
)
118 unsigned long r
, g
, b
, dr
, dg
, db
;
122 image
= RCreateImage(width
, height
, False
);
132 dr
= ((rf
-r0
)<<16)/(int)width
;
133 dg
= ((gf
-g0
)<<16)/(int)width
;
134 db
= ((bf
-b0
)<<16)/(int)width
;
135 /* render the first line */
136 for (i
=0; i
<width
; i
++) {
137 *(ptr
++) = (unsigned char)(r
>>16);
138 *(ptr
++) = (unsigned char)(g
>>16);
139 *(ptr
++) = (unsigned char)(b
>>16);
145 /* copy the first line to the other lines */
146 for (i
=1; i
<height
; i
++) {
147 memcpy(&(image
->data
[i
*width
*3]), image
->data
, width
*3);
155 *----------------------------------------------------------------------
157 * Renders a vertical linear gradient of the specified size in the
158 * RImage format with a border of the specified type.
161 * A 24bit RImage with the gradient (no alpha channel).
165 *----------------------------------------------------------------------
168 renderVGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
,
169 int rf
, int gf
, int bf
)
172 unsigned long r
, g
, b
, dr
, dg
, db
;
176 unsigned char rr
, gg
, bb
;
178 image
= RCreateImage(width
, height
, False
);
182 iptr
= (unsigned int*)ptr
= image
->data
;
188 dr
= ((rf
-r0
)<<16)/(int)height
;
189 dg
= ((gf
-g0
)<<16)/(int)height
;
190 db
= ((bf
-b0
)<<16)/(int)height
;
192 for (i
=0; i
<height
; i
++) {
196 for (j
=0; j
<width
/8; j
++) {
197 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
198 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
199 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
200 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
201 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
202 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
203 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
204 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
207 case 7: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
208 case 6: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
209 case 5: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
210 case 4: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
211 case 3: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
212 case 2: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
213 case 1: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
224 *----------------------------------------------------------------------
226 * Renders a diagonal linear gradient of the specified size in the
227 * RImage format with a border of the specified type.
230 * A 24bit RImage with the gradient (no alpha channel).
234 *----------------------------------------------------------------------
239 renderDGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
,
240 int rf
, int gf
, int bf
)
248 return renderVGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
249 else if (height
== 1)
250 return renderHGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
252 image
= RCreateImage(width
, height
, False
);
257 tmp
= renderHGradient(2*width
-1, 1, r0
, g0
, b0
, rf
, gf
, bf
);
259 RDestroyImage(image
);
265 a
= ((float)(width
- 1))/((float)(height
- 1));
268 /* copy the first line to the other lines with corresponding offset */
269 for (j
=0, offset
=0.0; j
<width
*height
; j
+= width
) {
270 memcpy(&(image
->data
[j
]), &ptr
[3*(int)offset
], width
);
280 renderMHGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
283 unsigned long r
, g
, b
, dr
, dg
, db
;
291 image
= RCreateImage(width
, height
, False
);
301 width2
= width
/(count
-1);
307 r
= colors
[0]->red
<< 16;
308 g
= colors
[0]->green
<< 16;
309 b
= colors
[0]->blue
<< 16;
311 /* render the first line */
312 for (i
=1; i
<count
; i
++) {
313 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)width2
;
314 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)width2
;
315 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)width2
;
316 for (j
=0; j
<width2
; j
++) {
317 *ptr
++ = (unsigned char)(r
>>16);
318 *ptr
++ = (unsigned char)(g
>>16);
319 *ptr
++ = (unsigned char)(b
>>16);
325 r
= colors
[i
]->red
<< 16;
326 g
= colors
[i
]->green
<< 16;
327 b
= colors
[i
]->blue
<< 16;
329 for (j
=k
; j
<width
; j
++) {
330 *ptr
++ = (unsigned char)(r
>>16);
331 *ptr
++ = (unsigned char)(g
>>16);
332 *ptr
++ = (unsigned char)(b
>>16);
335 /* copy the first line to the other lines */
336 for (i
=1; i
<height
; i
++) {
337 memcpy(&(image
->data
[i
*width
*3]), image
->data
, width
*3);
346 renderMVGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
349 unsigned long r
, g
, b
, dr
, dg
, db
;
351 unsigned char *ptr
, *tmp
;
354 unsigned char rr
, gg
, bb
;
359 image
= RCreateImage(width
, height
, False
);
369 height2
= height
/(count
-1);
375 r
= colors
[0]->red
<< 16;
376 g
= colors
[0]->green
<< 16;
377 b
= colors
[0]->blue
<< 16;
379 for (i
=1; i
<count
; i
++) {
380 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)height2
;
381 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)height2
;
382 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)height2
;
384 for (j
=0; j
<height2
; j
++) {
389 for (x
=0; x
<width
/4; x
++) {
390 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
391 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
392 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
393 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
396 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
397 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
398 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
405 r
= colors
[i
]->red
<< 16;
406 g
= colors
[i
]->green
<< 16;
407 b
= colors
[i
]->blue
<< 16;
416 for (x
=0; x
<width
/4; x
++) {
417 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
418 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
419 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
420 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
423 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
424 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
425 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
429 for (j
=k
+1; j
<height
; j
++) {
430 memcpy(ptr
, tmp
, width
*3);
440 renderMDGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
450 return renderMVGradient(width
, height
, colors
, count
);
451 else if (height
== 1)
452 return renderMHGradient(width
, height
, colors
, count
);
454 image
= RCreateImage(width
, height
, False
);
465 tmp
= renderMHGradient(2*width
-1, 1, colors
, count
);
467 tmp
= renderHGradient(2*width
-1, 1, colors
[0]->red
<<8,
468 colors
[0]->green
<<8, colors
[0]->blue
<<8,
469 colors
[1]->red
<<8, colors
[1]->green
<<8,
473 RDestroyImage(image
);
478 a
= ((float)(width
- 1))/((float)(height
- 1));
481 /* copy the first line to the other lines with corresponding offset */
482 for (j
=0, offset
=0; j
<width
*height
; j
+= width
) {
483 memcpy(&(image
->data
[j
]), &ptr
[3*(int)offset
], width
);