Code

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