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
;
175 unsigned char rr
, gg
, bb
;
177 image
= RCreateImage(width
, height
, False
);
187 dr
= ((rf
-r0
)<<16)/(int)height
;
188 dg
= ((gf
-g0
)<<16)/(int)height
;
189 db
= ((bf
-b0
)<<16)/(int)height
;
191 for (i
=0; i
<height
; i
++) {
195 for (j
=0; j
<width
/8; 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
;
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
;
206 case 7: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
207 case 6: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
208 case 5: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
209 case 4: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
210 case 3: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
211 case 2: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
212 case 1: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
223 *----------------------------------------------------------------------
225 * Renders a diagonal linear gradient of the specified size in the
226 * RImage format with a border of the specified type.
229 * A 24bit RImage with the gradient (no alpha channel).
233 *----------------------------------------------------------------------
238 renderDGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
,
239 int rf
, int gf
, int bf
)
247 return renderVGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
248 else if (height
== 1)
249 return renderHGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
251 image
= RCreateImage(width
, height
, False
);
256 tmp
= renderHGradient(2*width
-1, 1, r0
, g0
, b0
, rf
, gf
, bf
);
258 RDestroyImage(image
);
264 a
= ((float)(width
- 1))/((float)(height
- 1));
267 /* copy the first line to the other lines with corresponding offset */
268 for (j
=0, offset
=0.0; j
<width
*height
; j
+= width
) {
269 memcpy(&(image
->data
[j
]), &ptr
[3*(int)offset
], width
);
279 renderMHGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
282 unsigned long r
, g
, b
, dr
, dg
, db
;
290 image
= RCreateImage(width
, height
, False
);
300 width2
= width
/(count
-1);
306 r
= colors
[0]->red
<< 16;
307 g
= colors
[0]->green
<< 16;
308 b
= colors
[0]->blue
<< 16;
310 /* render the first line */
311 for (i
=1; i
<count
; i
++) {
312 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)width2
;
313 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)width2
;
314 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)width2
;
315 for (j
=0; j
<width2
; j
++) {
316 *ptr
++ = (unsigned char)(r
>>16);
317 *ptr
++ = (unsigned char)(g
>>16);
318 *ptr
++ = (unsigned char)(b
>>16);
324 r
= colors
[i
]->red
<< 16;
325 g
= colors
[i
]->green
<< 16;
326 b
= colors
[i
]->blue
<< 16;
328 for (j
=k
; j
<width
; j
++) {
329 *ptr
++ = (unsigned char)(r
>>16);
330 *ptr
++ = (unsigned char)(g
>>16);
331 *ptr
++ = (unsigned char)(b
>>16);
334 /* copy the first line to the other lines */
335 for (i
=1; i
<height
; i
++) {
336 memcpy(&(image
->data
[i
*width
*3]), image
->data
, width
*3);
345 renderMVGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
348 unsigned long r
, g
, b
, dr
, dg
, db
;
350 unsigned char *ptr
, *tmp
;
353 unsigned char rr
, gg
, bb
;
358 image
= RCreateImage(width
, height
, False
);
368 height2
= height
/(count
-1);
374 r
= colors
[0]->red
<< 16;
375 g
= colors
[0]->green
<< 16;
376 b
= colors
[0]->blue
<< 16;
378 for (i
=1; i
<count
; i
++) {
379 dr
= ((int)(colors
[i
]->red
- colors
[i
-1]->red
) <<16)/(int)height2
;
380 dg
= ((int)(colors
[i
]->green
- colors
[i
-1]->green
)<<16)/(int)height2
;
381 db
= ((int)(colors
[i
]->blue
- colors
[i
-1]->blue
) <<16)/(int)height2
;
383 for (j
=0; j
<height2
; j
++) {
388 for (x
=0; x
<width
/4; x
++) {
389 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
390 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
391 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
392 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
395 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
396 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
397 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
404 r
= colors
[i
]->red
<< 16;
405 g
= colors
[i
]->green
<< 16;
406 b
= colors
[i
]->blue
<< 16;
415 for (x
=0; x
<width
/4; x
++) {
416 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
417 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
418 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
419 *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
422 case 3: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
423 case 2: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
424 case 1: *ptr
++ = rr
; *ptr
++ = gg
; *ptr
++ = bb
;
428 for (j
=k
+1; j
<height
; j
++) {
429 memcpy(ptr
, tmp
, width
*3);
439 renderMDGradient(unsigned width
, unsigned height
, RColor
**colors
, int count
)
449 return renderMVGradient(width
, height
, colors
, count
);
450 else if (height
== 1)
451 return renderMHGradient(width
, height
, colors
, count
);
453 image
= RCreateImage(width
, height
, False
);
464 tmp
= renderMHGradient(2*width
-1, 1, colors
, count
);
466 tmp
= renderHGradient(2*width
-1, 1, colors
[0]->red
<<8,
467 colors
[0]->green
<<8, colors
[0]->blue
<<8,
468 colors
[1]->red
<<8, colors
[1]->green
<<8,
472 RDestroyImage(image
);
477 a
= ((float)(width
- 1))/((float)(height
- 1));
480 /* copy the first line to the other lines with corresponding offset */
481 for (j
=0, offset
=0; j
<width
*height
; j
+= width
) {
482 memcpy(&(image
->data
[j
]), &ptr
[3*(int)offset
], width
);
492 RImage
*RRenderInterwovenGradient(unsigned width
, unsigned height
,
493 RColor colors1
[2], int thickness1
,
494 RColor colors2
[2], int thickness2
)
497 unsigned long r1
, g1
, b1
, dr1
, dg1
, db1
;
498 unsigned long r2
, g2
, b2
, dr2
, dg2
, db2
;
501 unsigned char rr
, gg
, bb
;
503 image
= RCreateImage(width
, height
, False
);
509 r1
= colors1
[0].red
<<16;
510 g1
= colors1
[0].green
<<16;
511 b1
= colors1
[0].blue
<<16;
513 r2
= colors2
[0].red
<<16;
514 g2
= colors2
[0].green
<<16;
515 b2
= colors2
[0].blue
<<16;
517 dr1
= ((colors1
[1].red
-colors1
[0].red
)<<16)/(int)height
;
518 dg1
= ((colors1
[1].green
-colors1
[0].green
)<<16)/(int)height
;
519 db1
= ((colors1
[1].blue
-colors1
[0].blue
)<<16)/(int)height
;
521 dr2
= ((colors2
[1].red
-colors2
[0].red
)<<16)/(int)height
;
522 dg2
= ((colors2
[1].green
-colors2
[0].green
)<<16)/(int)height
;
523 db2
= ((colors2
[1].blue
-colors2
[0].blue
)<<16)/(int)height
;
525 for (i
=0,k
=0,l
=0,ll
=thickness1
; i
<height
; i
++) {
535 for (j
=0; j
<width
/8; j
++) {
536 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
537 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
538 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
539 *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
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
;
546 case 7: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
547 case 6: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
548 case 5: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
549 case 4: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
550 case 3: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
551 case 2: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;
552 case 1: *(ptr
++) = rr
; *(ptr
++) = gg
; *(ptr
++) = bb
;