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 long r
, g
, b
, dr
, dg
, db
;
119 unsigned lineSize
= width
*3;
123 image
= RCreateImage(width
, height
, False
);
133 dr
= ((rf
-r0
)<<16)/(int)width
;
134 dg
= ((gf
-g0
)<<16)/(int)width
;
135 db
= ((bf
-b0
)<<16)/(int)width
;
136 /* render the first line */
137 for (i
=0; i
<width
; i
++) {
138 *(ptr
++) = (unsigned char)(r
>>16);
139 *(ptr
++) = (unsigned char)(g
>>16);
140 *(ptr
++) = (unsigned char)(b
>>16);
146 /* copy the first line to the other lines */
147 for (i
=1; i
<height
; i
++) {
148 memcpy(&(image
->data
[i
*lineSize
]), image
->data
, lineSize
);
156 *----------------------------------------------------------------------
158 * Renders a vertical linear gradient of the specified size in the
159 * RImage format with a border of the specified type.
162 * A 24bit RImage with the gradient (no alpha channel).
166 *----------------------------------------------------------------------
169 renderVGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
,
170 int rf
, int gf
, int bf
)
173 long r
, g
, b
, dr
, dg
, db
;
176 unsigned char rr
, gg
, bb
;
178 image
= RCreateImage(width
, height
, False
);
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 RReleaseImage(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 long r
, g
, b
, dr
, dg
, db
;
284 unsigned lineSize
= width
*3;
292 image
= RCreateImage(width
, height
, False
);
302 width2
= width
/(count
-1);
308 r
= colors
[0]->red
<< 16;
309 g
= colors
[0]->green
<< 16;
310 b
= colors
[0]->blue
<< 16;
312 /* render the first line */
313 for (i
=1; i
<count
; i
++) {
314 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)width2
;
315 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)width2
;
316 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)width2
;
317 for (j
=0; j
<width2
; j
++) {
318 *ptr
++ = (unsigned char)(r
>>16);
319 *ptr
++ = (unsigned char)(g
>>16);
320 *ptr
++ = (unsigned char)(b
>>16);
326 r
= colors
[i
]->red
<< 16;
327 g
= colors
[i
]->green
<< 16;
328 b
= colors
[i
]->blue
<< 16;
330 for (j
=k
; j
<width
; j
++) {
331 *ptr
++ = (unsigned char)(r
>>16);
332 *ptr
++ = (unsigned char)(g
>>16);
333 *ptr
++ = (unsigned char)(b
>>16);
336 /* copy the first line to the other lines */
337 for (i
=1; i
<height
; i
++) {
338 memcpy(&(image
->data
[i
*lineSize
]), image
->data
, lineSize
);
347 renderMVGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
350 long r
, g
, b
, dr
, dg
, db
;
351 unsigned lineSize
= width
*3;
353 unsigned char *ptr
, *tmp
;
356 unsigned char rr
, gg
, bb
;
361 image
= RCreateImage(width
, height
, False
);
371 height2
= height
/(count
-1);
377 r
= colors
[0]->red
<< 16;
378 g
= colors
[0]->green
<< 16;
379 b
= colors
[0]->blue
<< 16;
381 for (i
=1; i
<count
; i
++) {
382 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)height2
;
383 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)height2
;
384 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)height2
;
386 for (j
=0; j
<height2
; j
++) {
391 for (x
=0; x
<width
/4; x
++) {
392 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
393 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
394 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
395 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
398 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
399 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
400 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
407 r
= colors
[i
]->red
<< 16;
408 g
= colors
[i
]->green
<< 16;
409 b
= colors
[i
]->blue
<< 16;
418 for (x
=0; x
<width
/4; x
++) {
419 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
420 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
421 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
422 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
425 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
426 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
427 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
431 for (j
=k
+1; j
<height
; j
++) {
432 memcpy(ptr
, tmp
, lineSize
);
442 renderMDGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
452 return renderMVGradient(width
, height
, colors
, count
);
453 else if (height
== 1)
454 return renderMHGradient(width
, height
, colors
, count
);
456 image
= RCreateImage(width
, height
, False
);
467 tmp
= renderMHGradient(2*width
-1, 1, colors
, count
);
469 tmp
= renderHGradient(2*width
-1, 1, colors
[0]->red
<<8,
470 colors
[0]->green
<<8, colors
[0]->blue
<<8,
471 colors
[1]->red
<<8, colors
[1]->green
<<8,
475 RReleaseImage(image
);
480 a
= ((float)(width
- 1))/((float)(height
- 1));
483 /* copy the first line to the other lines with corresponding offset */
484 for (j
=0, offset
=0; j
<width
*height
; j
+= width
) {
485 memcpy(&(image
->data
[j
]), &ptr
[3*(int)offset
], width
);
496 RRenderInterwovenGradient(unsigned width
, unsigned height
,
497 RColor colors1
[2], int thickness1
,
498 RColor colors2
[2], int thickness2
)
501 long r1
, g1
, b1
, dr1
, dg1
, db1
;
502 long r2
, g2
, b2
, dr2
, dg2
, db2
;
505 unsigned char rr
, gg
, bb
;
507 image
= RCreateImage(width
, height
, False
);
513 r1
= colors1
[0].red
<<16;
514 g1
= colors1
[0].green
<<16;
515 b1
= colors1
[0].blue
<<16;
517 r2
= colors2
[0].red
<<16;
518 g2
= colors2
[0].green
<<16;
519 b2
= colors2
[0].blue
<<16;
521 dr1
= ((colors1
[1].red
-colors1
[0].red
)<<16)/(int)height
;
522 dg1
= ((colors1
[1].green
-colors1
[0].green
)<<16)/(int)height
;
523 db1
= ((colors1
[1].blue
-colors1
[0].blue
)<<16)/(int)height
;
525 dr2
= ((colors2
[1].red
-colors2
[0].red
)<<16)/(int)height
;
526 dg2
= ((colors2
[1].green
-colors2
[0].green
)<<16)/(int)height
;
527 db2
= ((colors2
[1].blue
-colors2
[0].blue
)<<16)/(int)height
;
529 for (i
=0,k
=0,l
=0,ll
=thickness1
; i
<height
; i
++) {
539 for (j
=0; j
<width
/8; j
++) {
540 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
541 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
542 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
543 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
544 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
545 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
546 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
547 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
550 case 7: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
551 case 6: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
552 case 5: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
553 case 4: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
554 case 3: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
555 case 2: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
556 case 1: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;