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
)
239 return renderVGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
240 else if (height
== 1)
241 return renderHGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
243 image
= RCreateImage(width
, height
, False
);
248 tmp
= renderHGradient(2*width
-1, 1, r0
, g0
, b0
, rf
, gf
, bf
);
250 RDestroyImage(image
);
257 a
= ((float)(width
- 1))/((float)(height
- 1));
259 /* copy the first line to the other lines with corresponding offset */
260 for (i
=0, j
=0, offset
=0; i
<height
; i
++, j
+= width
) {
261 offset
= (int)(a
*i
+0.5)*3;
262 memcpy(&(image
->data
[j
]), &ptr
[offset
], width
);
271 renderMHGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
274 unsigned long r
, g
, b
, dr
, dg
, db
;
282 image
= RCreateImage(width
, height
, False
);
292 width2
= width
/(count
-1);
298 r
= colors
[0]->red
<< 16;
299 g
= colors
[0]->green
<< 16;
300 b
= colors
[0]->blue
<< 16;
302 /* render the first line */
303 for (i
=1; i
<count
; i
++) {
304 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)width2
;
305 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)width2
;
306 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)width2
;
307 for (j
=0; j
<width2
; j
++) {
308 *ptr
++ = (unsigned char)(r
>>16);
309 *ptr
++ = (unsigned char)(g
>>16);
310 *ptr
++ = (unsigned char)(b
>>16);
316 r
= colors
[i
]->red
<< 16;
317 g
= colors
[i
]->green
<< 16;
318 b
= colors
[i
]->blue
<< 16;
320 for (j
=k
; j
<width
; j
++) {
321 *ptr
++ = (unsigned char)(r
>>16);
322 *ptr
++ = (unsigned char)(g
>>16);
323 *ptr
++ = (unsigned char)(b
>>16);
326 /* copy the first line to the other lines */
327 for (i
=1; i
<height
; i
++) {
328 memcpy(&(image
->data
[i
*width
*3]), image
->data
, width
*3);
337 renderMVGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
340 unsigned long r
, g
, b
, dr
, dg
, db
;
342 unsigned char *ptr
, *tmp
;
345 unsigned char rr
, gg
, bb
;
350 image
= RCreateImage(width
, height
, False
);
360 height2
= height
/(count
-1);
366 r
= colors
[0]->red
<< 16;
367 g
= colors
[0]->green
<< 16;
368 b
= colors
[0]->blue
<< 16;
370 for (i
=1; i
<count
; i
++) {
371 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)height2
;
372 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)height2
;
373 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)height2
;
375 for (j
=0; j
<height2
; j
++) {
380 for (x
=0; x
<width
/4; x
++) {
381 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
382 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
383 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
384 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
387 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
388 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
389 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
396 r
= colors
[i
]->red
<< 16;
397 g
= colors
[i
]->green
<< 16;
398 b
= colors
[i
]->blue
<< 16;
407 for (x
=0; x
<width
/4; x
++) {
408 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
409 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
410 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
411 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
414 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
415 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
416 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
420 for (j
=k
+1; j
<height
; j
++) {
421 memcpy(ptr
, tmp
, width
*3);
431 renderMDGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
441 return renderMVGradient(width
, height
, colors
, count
);
442 else if (height
== 1)
443 return renderMHGradient(width
, height
, colors
, count
);
445 image
= RCreateImage(width
, height
, False
);
456 tmp
= renderMHGradient(2*width
-1, 1, colors
, count
);
458 tmp
= renderHGradient(2*width
-1, 1, colors
[0]->red
<<8,
459 colors
[0]->green
<<8, colors
[0]->blue
<<8,
460 colors
[1]->red
<<8, colors
[1]->green
<<8,
464 RDestroyImage(image
);
470 a
= ((float)(width
- 1))/((float)(height
- 1));
472 /* copy the first line to the other lines with corresponding offset */
473 for (i
=0, j
=0, offset
=0; i
<height
; i
++, j
+= width
) {
474 offset
= (int)(a
*i
+0.5)*3;
475 memcpy(&(image
->data
[j
]), &ptr
[offset
], width
);