1 /* gradient.c - renders gradients
3 * Raster graphics library
5 * Copyright (c) 1997-2000 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 static RImage
*renderHGradient(unsigned width
, unsigned height
,
34 int r0
, int g0
, int b0
,
35 int rf
, int gf
, int bf
);
36 static RImage
*renderVGradient(unsigned width
, unsigned height
,
37 int r0
, int g0
, int b0
,
38 int rf
, int gf
, int bf
);
39 static RImage
*renderDGradient(unsigned width
, unsigned height
,
40 int r0
, int g0
, int b0
,
41 int rf
, int gf
, int bf
);
43 static RImage
*renderMHGradient(unsigned width
, unsigned height
,
44 RColor
**colors
, int count
);
45 static RImage
*renderMVGradient(unsigned width
, unsigned height
,
46 RColor
**colors
, int count
);
47 static RImage
*renderMDGradient(unsigned width
, unsigned height
,
48 RColor
**colors
, int count
);
51 RRenderMultiGradient(unsigned width
, unsigned height
, RColor
**colors
, int style
)
56 while (colors
[count
]!=NULL
) count
++;
60 case RHorizontalGradient
:
61 return renderMHGradient(width
, height
, colors
, count
);
62 case RVerticalGradient
:
63 return renderMVGradient(width
, height
, colors
, count
);
64 case RDiagonalGradient
:
65 return renderMDGradient(width
, height
, colors
, count
);
67 } else if (count
> 1) {
68 return RRenderGradient(width
, height
, colors
[0], colors
[1], style
);
69 } else if (count
> 0) {
70 return RRenderGradient(width
, height
, colors
[0], colors
[0], style
);
79 RRenderGradient(unsigned width
, unsigned height
, RColor
*from
, RColor
*to
,
83 case RHorizontalGradient
:
84 return renderHGradient(width
, height
, from
->red
, from
->green
,
85 from
->blue
, to
->red
, to
->green
, to
->blue
);
86 case RVerticalGradient
:
87 return renderVGradient(width
, height
, from
->red
, from
->green
,
88 from
->blue
, to
->red
, to
->green
, to
->blue
);
90 case RDiagonalGradient
:
91 return renderDGradient(width
, height
, from
->red
, from
->green
,
92 from
->blue
, to
->red
, to
->green
, to
->blue
);
100 *----------------------------------------------------------------------
102 * Renders a horizontal linear gradient of the specified size in the
103 * RImage format with a border of the specified type.
106 * A 24bit RImage with the gradient (no alpha channel).
110 *----------------------------------------------------------------------
113 renderHGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
,
114 int rf
, int gf
, int bf
)
117 unsigned long r
, g
, b
, dr
, dg
, db
;
121 image
= RCreateImage(width
, height
, False
);
131 dr
= ((rf
-r0
)<<16)/(int)width
;
132 dg
= ((gf
-g0
)<<16)/(int)width
;
133 db
= ((bf
-b0
)<<16)/(int)width
;
134 /* render the first line */
135 for (i
=0; i
<width
; i
++) {
136 *(ptr
++) = (unsigned char)(r
>>16);
137 *(ptr
++) = (unsigned char)(g
>>16);
138 *(ptr
++) = (unsigned char)(b
>>16);
144 /* copy the first line to the other lines */
145 for (i
=1; i
<height
; i
++) {
146 memcpy(&(image
->data
[i
*width
*3]), image
->data
, width
*3);
152 *----------------------------------------------------------------------
154 * Renders a vertical linear gradient of the specified size in the
155 * RImage format with a border of the specified type.
158 * A 24bit RImage with the gradient (no alpha channel).
162 *----------------------------------------------------------------------
165 renderVGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
,
166 int rf
, int gf
, int bf
)
169 unsigned long r
, g
, b
, dr
, dg
, db
;
173 unsigned char rr
, gg
, bb
;
175 image
= RCreateImage(width
, height
, False
);
179 iptr
= (unsigned int*)ptr
= image
->data
;
185 dr
= ((rf
-r0
)<<16)/(int)height
;
186 dg
= ((gf
-g0
)<<16)/(int)height
;
187 db
= ((bf
-b0
)<<16)/(int)height
;
190 for (i
=0; i
<height
; i
++) {
194 for (j
=0; j
<width
/4; j
++) {
195 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
196 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
197 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
198 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
201 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
202 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
203 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
214 *----------------------------------------------------------------------
216 * Renders a diagonal linear gradient of the specified size in the
217 * RImage format with a border of the specified type.
220 * A 24bit RImage with the gradient (no alpha channel).
224 *----------------------------------------------------------------------
229 renderDGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
,
230 int rf
, int gf
, int bf
)
237 return renderVGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
238 else if (height
== 1)
239 return renderHGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
241 image
= RCreateImage(width
, height
, False
);
246 tmp
= renderHGradient(2*width
-1, 1, r0
, g0
, b0
, rf
, gf
, bf
);
248 RDestroyImage(image
);
252 a
= (((width
- 1)<<16) / ((height
- 1)<<16)) * 3;
255 /* copy the first line to the other lines with corresponding offset */
256 for (i
=0, j
=0, offset
= 0; i
<height
; i
++, j
+= width
) {
258 memcpy(&(image
->data
[j
]), &(tmp
->data
[(offset
>>16)]), width
);
266 renderMHGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
269 unsigned long r
, g
, b
, dr
, dg
, db
;
277 image
= RCreateImage(width
, height
, False
);
287 width2
= width
/(count
-1);
293 r
= colors
[0]->red
<< 16;
294 g
= colors
[0]->green
<< 16;
295 b
= colors
[0]->blue
<< 16;
297 /* render the first line */
298 for (i
=1; i
<count
; i
++) {
299 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)width2
;
300 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)width2
;
301 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)width2
;
302 for (j
=0; j
<width2
; j
++) {
303 *ptr
++ = (unsigned char)(r
>>16);
304 *ptr
++ = (unsigned char)(g
>>16);
305 *ptr
++ = (unsigned char)(b
>>16);
311 r
= colors
[i
]->red
<< 16;
312 g
= colors
[i
]->green
<< 16;
313 b
= colors
[i
]->blue
<< 16;
315 for (j
=k
; j
<width
; j
++) {
316 *ptr
++ = (unsigned char)(r
>>16);
317 *ptr
++ = (unsigned char)(g
>>16);
318 *ptr
++ = (unsigned char)(b
>>16);
321 /* copy the first line to the other lines */
322 for (i
=1; i
<height
; i
++) {
323 memcpy(&(image
->data
[i
*width
*3]), image
->data
, width
*3);
332 renderMVGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
335 unsigned long r
, g
, b
, dr
, dg
, db
;
337 unsigned char *ptr
, *tmp
;
340 unsigned char rr
, gg
, bb
;
345 image
= RCreateImage(width
, height
, False
);
355 height2
= height
/(count
-1);
361 r
= colors
[0]->red
<< 16;
362 g
= colors
[0]->green
<< 16;
363 b
= colors
[0]->blue
<< 16;
365 for (i
=1; i
<count
; i
++) {
366 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)height2
;
367 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)height2
;
368 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)height2
;
370 for (j
=0; j
<height2
; j
++) {
375 for (x
=0; x
<width
/4; x
++) {
376 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
377 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
378 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
379 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
382 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
383 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
384 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
391 r
= colors
[i
]->red
<< 16;
392 g
= colors
[i
]->green
<< 16;
393 b
= colors
[i
]->blue
<< 16;
401 for (x
=0; x
<width
/4; x
++) {
402 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
403 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
404 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
405 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
408 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
409 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
410 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
413 for (j
=k
+1; j
<width
; j
++) {
414 memcpy(ptr
, tmp
, width
*3);
423 renderMDGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
432 return renderMVGradient(width
, height
, colors
, count
);
433 else if (height
== 1)
434 return renderMHGradient(width
, height
, colors
, count
);
436 image
= RCreateImage(width
, height
, False
);
447 tmp
= renderMHGradient(2*width
-1, 1, colors
, count
);
449 tmp
= renderHGradient(2*width
-1, 1, colors
[0]->red
<<8,
450 colors
[0]->green
<<8, colors
[0]->blue
<<8,
451 colors
[1]->red
<<8, colors
[1]->green
<<8,
455 RDestroyImage(image
);
459 a
= ((float)(width
- 1))/((float)(height
- 1));
461 /* copy the first line to the other lines with corresponding offset */
462 for (i
=0; i
<height
; i
++) {
463 offset
= (int)(a
*i
+0.5)*3;
464 memcpy(&(image
->data
[i
*width
*3]), &(tmp
->data
[offset
]), width
*3);