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);
153 *----------------------------------------------------------------------
155 * Renders a vertical linear gradient of the specified size in the
156 * RImage format with a border of the specified type.
159 * A 24bit RImage with the gradient (no alpha channel).
163 *----------------------------------------------------------------------
166 renderVGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
,
167 int rf
, int gf
, int bf
)
170 unsigned long r
, g
, b
, dr
, dg
, db
;
174 unsigned char rr
, gg
, bb
;
176 image
= RCreateImage(width
, height
, False
);
180 iptr
= (unsigned int*)ptr
= image
->data
;
186 dr
= ((rf
-r0
)<<16)/(int)height
;
187 dg
= ((gf
-g0
)<<16)/(int)height
;
188 db
= ((bf
-b0
)<<16)/(int)height
;
191 for (i
=0; i
<height
; i
++) {
195 for (j
=0; j
<width
/4; j
++) {
196 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
197 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
198 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
199 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
202 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
203 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
204 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
215 *----------------------------------------------------------------------
217 * Renders a diagonal linear gradient of the specified size in the
218 * RImage format with a border of the specified type.
221 * A 24bit RImage with the gradient (no alpha channel).
225 *----------------------------------------------------------------------
230 renderDGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
,
231 int rf
, int gf
, int bf
)
238 return renderVGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
239 else if (height
== 1)
240 return renderHGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
242 image
= RCreateImage(width
, height
, False
);
247 tmp
= renderHGradient(2*width
-1, 1, r0
, g0
, b0
, rf
, gf
, bf
);
249 RDestroyImage(image
);
253 a
= (((width
- 1)<<16) / (height
- 1))*3;
256 /* copy the first line to the other lines with corresponding offset */
257 for (i
=0, j
=0, offset
= 0; i
<height
; i
++, j
+= width
) {
259 memcpy(&(image
->data
[j
]), &(tmp
->data
[(offset
>>16)]), width
);
267 renderMHGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
270 unsigned long r
, g
, b
, dr
, dg
, db
;
278 image
= RCreateImage(width
, height
, False
);
288 width2
= width
/(count
-1);
294 r
= colors
[0]->red
<< 16;
295 g
= colors
[0]->green
<< 16;
296 b
= colors
[0]->blue
<< 16;
298 /* render the first line */
299 for (i
=1; i
<count
; i
++) {
300 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)width2
;
301 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)width2
;
302 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)width2
;
303 for (j
=0; j
<width2
; j
++) {
304 *ptr
++ = (unsigned char)(r
>>16);
305 *ptr
++ = (unsigned char)(g
>>16);
306 *ptr
++ = (unsigned char)(b
>>16);
312 r
= colors
[i
]->red
<< 16;
313 g
= colors
[i
]->green
<< 16;
314 b
= colors
[i
]->blue
<< 16;
316 for (j
=k
; j
<width
; j
++) {
317 *ptr
++ = (unsigned char)(r
>>16);
318 *ptr
++ = (unsigned char)(g
>>16);
319 *ptr
++ = (unsigned char)(b
>>16);
322 /* copy the first line to the other lines */
323 for (i
=1; i
<height
; i
++) {
324 memcpy(&(image
->data
[i
*width
*3]), image
->data
, width
*3);
333 renderMVGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
336 unsigned long r
, g
, b
, dr
, dg
, db
;
338 unsigned char *ptr
, *tmp
;
341 unsigned char rr
, gg
, bb
;
346 image
= RCreateImage(width
, height
, False
);
356 height2
= height
/(count
-1);
362 r
= colors
[0]->red
<< 16;
363 g
= colors
[0]->green
<< 16;
364 b
= colors
[0]->blue
<< 16;
366 for (i
=1; i
<count
; i
++) {
367 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)height2
;
368 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)height2
;
369 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)height2
;
371 for (j
=0; j
<height2
; j
++) {
376 for (x
=0; x
<width
/4; x
++) {
377 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
378 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
379 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
380 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
383 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
384 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
385 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
392 r
= colors
[i
]->red
<< 16;
393 g
= colors
[i
]->green
<< 16;
394 b
= colors
[i
]->blue
<< 16;
403 for (x
=0; x
<width
/4; x
++) {
404 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
405 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
406 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
407 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
410 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
411 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
412 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
416 for (j
=k
+1; j
<height
; j
++) {
417 memcpy(ptr
, tmp
, width
*3);
427 renderMDGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
436 return renderMVGradient(width
, height
, colors
, count
);
437 else if (height
== 1)
438 return renderMHGradient(width
, height
, colors
, count
);
440 image
= RCreateImage(width
, height
, False
);
451 tmp
= renderMHGradient(2*width
-1, 1, colors
, count
);
453 tmp
= renderHGradient(2*width
-1, 1, colors
[0]->red
<<8,
454 colors
[0]->green
<<8, colors
[0]->blue
<<8,
455 colors
[1]->red
<<8, colors
[1]->green
<<8,
459 RDestroyImage(image
);
463 a
= ((float)(width
- 1))/((float)(height
- 1));
465 /* copy the first line to the other lines with corresponding offset */
466 for (i
=0; i
<height
; i
++) {
467 offset
= (int)(a
*i
+0.5)*3;
468 memcpy(&(image
->data
[i
*width
*3]), &(tmp
->data
[offset
]), width
*3);