Code

Warning cleanup
[inkscape.git] / src / display / nr-filter-pixops.h
1 #ifndef __NR_FILTER_PIXOPS_H__
2 #define __NR_FILTER_PIXOPS_H__
4 #include "libnr/nr-pixblock.h"
6 /*
7  * Per-pixel image manipulation functions.
8  * These can be used by all filter primitives, which combine two images on
9  * per-pixel basis. These are at least feBlend, feComposite and feMerge.
10  *
11  * Authors:
12  *   Niko Kiirala <niko@kiirala.com>
13  *
14  * Copyright (C) 2007 authors
15  *
16  * Released under GNU GPL, read the file 'COPYING' for more information
17  */
19 namespace Inkscape {
20 namespace Filters {
22 /**
23  * Mixes the two input images using the function given as template.
24  * The result is placed in out.
25  * The mixing function should have the following type:
26  * void mix(unsigned char *result, unsigned char const *in1,
27  *          unsigned char const *in2);
28  * Each of the parameters for mix-function is a pointer to four bytes of data,
29  * giving the RGBA values for that pixel. The mix function must only access
30  * the four bytes beginning at a pointer given as parameter.
31  */
32 /*
33  * The implementation is in a header file because of the template. It has to
34  * be in the same compilation unit as the code using it. Otherwise, linking
35  * the program will not succeed.
36  */
37 template <void(*blend)(unsigned char *cr, unsigned char const *ca, unsigned char const *cb)>
38 void pixops_mix(NRPixBlock &out, NRPixBlock &in1, NRPixBlock &in2) {
39     unsigned char *in1_data = NR_PIXBLOCK_PX(&in1);
40     unsigned char *in2_data = NR_PIXBLOCK_PX(&in2);
41     unsigned char *out_data = NR_PIXBLOCK_PX(&out);
42     unsigned char zero_rgba[4] = {0, 0, 0, 0};
44     if (in1.area.y0 < in2.area.y0) {
45         // in1 begins before in2 on y-axis
46         for (int y = in1.area.y0 ; y < in2.area.y0 ; y++) {
47             int out_line = (y - out.area.y0) * out.rs;
48             int in_line = (y - in1.area.y0) * in1.rs;
49             for (int x = in1.area.x0 ; x < in1.area.x1 ; x++) {
50                 blend(out_data + out_line + 4 * (x - out.area.x0),
51                       in1_data + in_line + 4 * (x - in1.area.x0),
52                       zero_rgba);
53             }
54         }
55     } else if (in1.area.y0 > in2.area.y0) {
56         // in2 begins before in1 on y-axis
57         for (int y = in2.area.y0 ; y < in1.area.y0 ; y++) {
58             int out_line = (y - out.area.y0) * out.rs;
59             int in_line = (y - in2.area.y0) * in2.rs;
60             for (int x = in2.area.x0 ; x < in2.area.x1 ; x++) {
61                 blend(out_data + out_line + 4 * (x - out.area.x0),
62                       zero_rgba,
63                       in2_data + in_line + 4 * (x - in2.area.x0));
64             }
65         }
66     }
68     for (int y = std::max(in1.area.y0, in2.area.y0) ;
69          y < std::min(in1.area.y1, in2.area.y1) ; ++y) {
70         int out_line = (y - out.area.y0) * out.rs;
71         int in1_line = (y - in1.area.y0) * in1.rs;
72         int in2_line = (y - in2.area.y0) * in2.rs;
74         if (in1.area.x0 < in2.area.x0) {
75             // in1 begins before in2 on x-axis
76             for (int x = in1.area.x0 ; x < in2.area.x0 ; ++x) {
77                 blend(out_data + out_line + 4 * (x - out.area.x0),
78                       in1_data + in1_line + 4 * (x - in1.area.x0),
79                       zero_rgba);
80             }
81         } else if (in1.area.x0 > in2.area.x0) {
82             // in2 begins before in1 on x-axis
83             for (int x = in2.area.x0 ; x < in1.area.x0 ; ++x) {
84                 blend(out_data + out_line + 4 * (x - out.area.x0),
85                       zero_rgba,
86                       in2_data + in2_line + 4 * (x - in2.area.x0));
87             }
88         }
90         for (int x = std::max(in1.area.x0, in2.area.x0) ;
91              x < std::min(in1.area.x1, in2.area.x1) ; ++x) {
92             blend(out_data + out_line + 4 * (x - out.area.x0),
93                   in1_data + in1_line + 4 * (x - in1.area.x0),
94                   in2_data + in2_line + 4 * (x - in2.area.x0));
95         }
97         if (in1.area.x1 > in2.area.x1) {
98             // in1 ends after in2 on x-axis
99             for (int x = in2.area.x1 ; x < in1.area.x1 ; ++x) {
100                 blend(out_data + out_line + 4 * (x - out.area.x0),
101                       in1_data + in1_line + 4 * (x - in1.area.x0),
102                       zero_rgba);
103             }
104         } else if (in1.area.x1 < in2.area.x1) {
105             // in2 ends after in1 on x-axis
106             for (int x = in1.area.x1 ; x < in2.area.x1 ; ++x) {
107                 blend(out_data + out_line + 4 * (x - out.area.x0),
108                       zero_rgba,
109                       in2_data + in2_line + 4 * (x - in2.area.x0));
110             }
111         }
112     }
114     if (in1.area.y1 > in2.area.y1) {
115         // in1 ends after in2 on y-axis
116         for (int y = in2.area.y1 ; y < in1.area.y1 ; y++) {
117             int out_line = (y - out.area.y0) * out.rs;
118             int in_line = (y - in1.area.y0) * in1.rs;
119             for (int x = in1.area.x0 ; x < in1.area.x1 ; x++) {
120                 blend(out_data + out_line + 4 * (x - out.area.x0),
121                       in1_data + in_line + 4 * (x - in1.area.x0),
122                       zero_rgba);
123             }
124         }
125     } else if (in1.area.y1 < in2.area.y1) {
126         // in2 ends after in1 on y-axis
127         for (int y = in1.area.y1 ; y < in2.area.y1 ; y++) {
128             int out_line = (y - out.area.y0) * out.rs;
129             int in_line = (y - in2.area.y0) * in2.rs;
130             for (int x = in2.area.x0 ; x < in2.area.x1 ; x++) {
131                 blend(out_data + out_line + 4 * (x - out.area.x0),
132                       zero_rgba,
133                       in2_data + in_line + 4 * (x - in2.area.x0));
134             }
135         }
136     }
139 } /* namespace Filters */
140 } /* namespace Inkscape */
142 #endif // __NR_FILTER_PIXOPS_H_
143 /*
144   Local Variables:
145   mode:c++
146   c-file-style:"stroustrup"
147   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
148   indent-tabs-mode:nil
149   fill-column:99
150   End:
151 */
152 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :