1 /* gradient.c - renders gradients
3 * Raster graphics library
5 * Copyright (c) 1997-2003 Alfredo K. Kojima
6 * Copyright (c) 1998-2003 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.
33 static RImage
*renderHGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
, int rf
, int gf
, int bf
);
34 static RImage
*renderVGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
, int rf
, int gf
, int bf
);
35 static RImage
*renderDGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
, int rf
, int gf
, int bf
);
37 static RImage
*renderMHGradient(unsigned width
, unsigned height
, RColor
** colors
, int count
);
38 static RImage
*renderMVGradient(unsigned width
, unsigned height
, RColor
** colors
, int count
);
39 static RImage
*renderMDGradient(unsigned width
, unsigned height
, RColor
** colors
, int count
);
41 RImage
*RRenderMultiGradient(unsigned width
, unsigned height
, RColor
** colors
, int style
)
46 while (colors
[count
] != NULL
)
51 case RHorizontalGradient
:
52 return renderMHGradient(width
, height
, colors
, count
);
53 case RVerticalGradient
:
54 return renderMVGradient(width
, height
, colors
, count
);
55 case RDiagonalGradient
:
56 return renderMDGradient(width
, height
, colors
, count
);
58 } else if (count
> 1) {
59 return RRenderGradient(width
, height
, colors
[0], colors
[1], style
);
60 } else if (count
> 0) {
61 return RRenderGradient(width
, height
, colors
[0], colors
[0], style
);
67 RImage
*RRenderGradient(unsigned width
, unsigned height
, RColor
* from
, RColor
* to
, int style
)
70 case RHorizontalGradient
:
71 return renderHGradient(width
, height
, from
->red
, from
->green
,
72 from
->blue
, to
->red
, to
->green
, to
->blue
);
73 case RVerticalGradient
:
74 return renderVGradient(width
, height
, from
->red
, from
->green
,
75 from
->blue
, to
->red
, to
->green
, to
->blue
);
77 case RDiagonalGradient
:
78 return renderDGradient(width
, height
, from
->red
, from
->green
,
79 from
->blue
, to
->red
, to
->green
, to
->blue
);
86 *----------------------------------------------------------------------
88 * Renders a horizontal linear gradient of the specified size in the
89 * RImage format with a border of the specified type.
92 * A 24bit RImage with the gradient (no alpha channel).
96 *----------------------------------------------------------------------
98 static RImage
*renderHGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
, int rf
, int gf
, int bf
)
101 long r
, g
, b
, dr
, dg
, db
;
102 unsigned lineSize
= width
* 3;
106 image
= RCreateImage(width
, height
, False
);
116 dr
= ((rf
- r0
) << 16) / (int)width
;
117 dg
= ((gf
- g0
) << 16) / (int)width
;
118 db
= ((bf
- b0
) << 16) / (int)width
;
119 /* render the first line */
120 for (i
= 0; i
< width
; i
++) {
121 *(ptr
++) = (unsigned char)(r
>> 16);
122 *(ptr
++) = (unsigned char)(g
>> 16);
123 *(ptr
++) = (unsigned char)(b
>> 16);
129 /* copy the first line to the other lines */
130 for (i
= 1; i
< height
; i
++) {
131 memcpy(&(image
->data
[i
* lineSize
]), image
->data
, lineSize
);
137 *----------------------------------------------------------------------
139 * Renders a vertical linear gradient of the specified size in the
140 * RImage format with a border of the specified type.
143 * A 24bit RImage with the gradient (no alpha channel).
147 *----------------------------------------------------------------------
149 static RImage
*renderVGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
, int rf
, int gf
, int bf
)
152 long r
, g
, b
, dr
, dg
, db
;
155 unsigned char rr
, gg
, bb
;
157 image
= RCreateImage(width
, height
, False
);
167 dr
= ((rf
- r0
) << 16) / (int)height
;
168 dg
= ((gf
- g0
) << 16) / (int)height
;
169 db
= ((bf
- b0
) << 16) / (int)height
;
171 for (i
= 0; i
< height
; i
++) {
175 for (j
= 0; j
< width
/ 8; j
++) {
239 *----------------------------------------------------------------------
241 * Renders a diagonal linear gradient of the specified size in the
242 * RImage format with a border of the specified type.
245 * A 24bit RImage with the gradient (no alpha channel).
249 *----------------------------------------------------------------------
252 static RImage
*renderDGradient(unsigned width
, unsigned height
, int r0
, int g0
, int b0
, int rf
, int gf
, int bf
)
260 return renderVGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
261 else if (height
== 1)
262 return renderHGradient(width
, height
, r0
, g0
, b0
, rf
, gf
, bf
);
264 image
= RCreateImage(width
, height
, False
);
269 tmp
= renderHGradient(2 * width
- 1, 1, r0
, g0
, b0
, rf
, gf
, bf
);
271 RReleaseImage(image
);
277 a
= ((float)(width
- 1)) / ((float)(height
- 1));
280 /* copy the first line to the other lines with corresponding offset */
281 for (j
= 0, offset
= 0.0; j
< width
* height
; j
+= width
) {
282 memcpy(&(image
->data
[j
]), &ptr
[3 * (int)offset
], width
);
290 static RImage
*renderMHGradient(unsigned width
, unsigned height
, RColor
** colors
, int count
)
293 long r
, g
, b
, dr
, dg
, db
;
294 unsigned lineSize
= width
* 3;
301 image
= RCreateImage(width
, height
, False
);
311 width2
= width
/ (count
- 1);
317 r
= colors
[0]->red
<< 16;
318 g
= colors
[0]->green
<< 16;
319 b
= colors
[0]->blue
<< 16;
321 /* render the first line */
322 for (i
= 1; i
< count
; i
++) {
323 dr
= ((int)(colors
[i
]->red
- colors
[i
- 1]->red
) << 16) / (int)width2
;
324 dg
= ((int)(colors
[i
]->green
- colors
[i
- 1]->green
) << 16) / (int)width2
;
325 db
= ((int)(colors
[i
]->blue
- colors
[i
- 1]->blue
) << 16) / (int)width2
;
326 for (j
= 0; j
< width2
; j
++) {
327 *ptr
++ = (unsigned char)(r
>> 16);
328 *ptr
++ = (unsigned char)(g
>> 16);
329 *ptr
++ = (unsigned char)(b
>> 16);
335 r
= colors
[i
]->red
<< 16;
336 g
= colors
[i
]->green
<< 16;
337 b
= colors
[i
]->blue
<< 16;
339 for (j
= k
; j
< width
; j
++) {
340 *ptr
++ = (unsigned char)(r
>> 16);
341 *ptr
++ = (unsigned char)(g
>> 16);
342 *ptr
++ = (unsigned char)(b
>> 16);
345 /* copy the first line to the other lines */
346 for (i
= 1; i
< height
; i
++) {
347 memcpy(&(image
->data
[i
* lineSize
]), image
->data
, lineSize
);
352 static RImage
*renderMVGradient(unsigned width
, unsigned height
, RColor
** colors
, int count
)
355 long r
, g
, b
, dr
, dg
, db
;
356 unsigned lineSize
= width
* 3;
358 unsigned char *ptr
, *tmp
;
361 unsigned char rr
, gg
, bb
;
365 image
= RCreateImage(width
, height
, False
);
375 height2
= height
/ (count
- 1);
381 r
= colors
[0]->red
<< 16;
382 g
= colors
[0]->green
<< 16;
383 b
= colors
[0]->blue
<< 16;
385 for (i
= 1; i
< count
; i
++) {
386 dr
= ((int)(colors
[i
]->red
- colors
[i
- 1]->red
) << 16) / (int)height2
;
387 dg
= ((int)(colors
[i
]->green
- colors
[i
- 1]->green
) << 16) / (int)height2
;
388 db
= ((int)(colors
[i
]->blue
- colors
[i
- 1]->blue
) << 16) / (int)height2
;
390 for (j
= 0; j
< height2
; j
++) {
395 for (x
= 0; x
< width
/ 4; x
++) {
428 r
= colors
[i
]->red
<< 16;
429 g
= colors
[i
]->green
<< 16;
430 b
= colors
[i
]->blue
<< 16;
439 for (x
= 0; x
< width
/ 4; x
++) {
470 for (j
= k
+ 1; j
< height
; j
++) {
471 memcpy(ptr
, tmp
, lineSize
);
479 static RImage
*renderMDGradient(unsigned width
, unsigned height
, RColor
** colors
, int count
)
489 return renderMVGradient(width
, height
, colors
, count
);
490 else if (height
== 1)
491 return renderMHGradient(width
, height
, colors
, count
);
493 image
= RCreateImage(width
, height
, False
);
504 tmp
= renderMHGradient(2 * width
- 1, 1, colors
, count
);
506 tmp
= renderHGradient(2 * width
- 1, 1, colors
[0]->red
<< 8,
507 colors
[0]->green
<< 8, colors
[0]->blue
<< 8,
508 colors
[1]->red
<< 8, colors
[1]->green
<< 8, colors
[1]->blue
<< 8);
511 RReleaseImage(image
);
516 a
= ((float)(width
- 1)) / ((float)(height
- 1));
519 /* copy the first line to the other lines with corresponding offset */
520 for (j
= 0, offset
= 0; j
< width
* height
; j
+= width
) {
521 memcpy(&(image
->data
[j
]), &ptr
[3 * (int)offset
], width
);
528 RImage
*RRenderInterwovenGradient(unsigned width
, unsigned height
,
529 RColor colors1
[2], int thickness1
, RColor colors2
[2], int thickness2
)
532 long r1
, g1
, b1
, dr1
, dg1
, db1
;
533 long r2
, g2
, b2
, dr2
, dg2
, db2
;
536 unsigned char rr
, gg
, bb
;
538 image
= RCreateImage(width
, height
, False
);
544 r1
= colors1
[0].red
<< 16;
545 g1
= colors1
[0].green
<< 16;
546 b1
= colors1
[0].blue
<< 16;
548 r2
= colors2
[0].red
<< 16;
549 g2
= colors2
[0].green
<< 16;
550 b2
= colors2
[0].blue
<< 16;
552 dr1
= ((colors1
[1].red
- colors1
[0].red
) << 16) / (int)height
;
553 dg1
= ((colors1
[1].green
- colors1
[0].green
) << 16) / (int)height
;
554 db1
= ((colors1
[1].blue
- colors1
[0].blue
) << 16) / (int)height
;
556 dr2
= ((colors2
[1].red
- colors2
[0].red
) << 16) / (int)height
;
557 dg2
= ((colors2
[1].green
- colors2
[0].green
) << 16) / (int)height
;
558 db2
= ((colors2
[1].blue
- colors2
[0].blue
) << 16) / (int)height
;
560 for (i
= 0, k
= 0, l
= 0, ll
= thickness1
; i
< height
; i
++) {
570 for (j
= 0; j
< width
/ 8; j
++) {