Code

Super duper mega (fun!) commit: replaced encoding=utf-8 with fileencoding=utf-8 in...
[inkscape.git] / src / display / nr-filter-merge.cpp
1 /*
2  * feMerge filter effect renderer
3  *
4  * Authors:
5  *   Niko Kiirala <niko@kiirala.com>
6  *
7  * Copyright (C) 2007 authors
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #include <cmath>
13 #include <vector>
15 #include "2geom/isnan.h"
16 #include "filters/merge.h"
17 #include "display/nr-filter-merge.h"
18 #include "display/nr-filter-pixops.h"
19 #include "display/nr-filter-slot.h"
20 #include "display/nr-filter-units.h"
21 #include "display/nr-filter-utils.h"
22 #include "libnr/nr-blit.h"
23 #include "libnr/nr-pixblock.h"
24 #include "libnr/nr-pixops.h"
26 inline void
27 composite_over(unsigned char *r, unsigned char const *a, unsigned char const *b)
28 {
29     r[0] = a[0] + NR_NORMALIZE_21(b[0] * (255 - a[3]));
30     r[1] = a[1] + NR_NORMALIZE_21(b[1] * (255 - a[3]));
31     r[2] = a[2] + NR_NORMALIZE_21(b[2] * (255 - a[3]));
32     r[3] = a[3] + NR_NORMALIZE_21(b[3] * (255 - a[3]));
33 }
35 namespace Inkscape {
36 namespace Filters {
38 FilterMerge::FilterMerge() :
39     _input_image(1, NR_FILTER_SLOT_NOT_SET)
40 {}
42 FilterPrimitive * FilterMerge::create() {
43     return new FilterMerge();
44 }
46 FilterMerge::~FilterMerge()
47 {}
49 int FilterMerge::render(FilterSlot &slot, FilterUnits const &/*units*/) {
50     NRPixBlock *in[_input_image.size()];
51     NRPixBlock *original_in[_input_image.size()];
53     for (unsigned int i = 0 ; i < _input_image.size() ; i++) {
54         in[i] = slot.get(_input_image[i]);
55         original_in[i] = in[i];
56     }
58     NRPixBlock *out;
60     // Bail out if one of source images is missing
61     for (unsigned int i = 0 ; i < _input_image.size() ; i++) {
62         bool missing = false;
63         if (!in[i]) {
64             g_warning("Missing source image for feMerge (number=%d slot=%d)", i, _input_image[i]);
65             missing = true;
66         }
67         if (missing) return 1;
68     }
70     out = new NRPixBlock;
71     NRRectL out_area = in[0]->area;
72     for (unsigned int i = 1 ; i < _input_image.size() ; i++) {
73         nr_rect_l_union(&out_area, &out_area, &in[i]->area);
74     }
75     nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8P,
76                            out_area.x0, out_area.y0, out_area.x1, out_area.y1,
77                            true);
79     // Merge is defined for premultiplied RGBA values, thus convert them to
80     // that format before blending
81     for (unsigned int i = 0 ; i < _input_image.size() ; i++) {
82         if (in[i]->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
83             in[i] = new NRPixBlock;
84             nr_pixblock_setup_fast(in[i], NR_PIXBLOCK_MODE_R8G8B8A8P,
85                                    original_in[i]->area.x0,
86                                    original_in[i]->area.y0,
87                                    original_in[i]->area.x1,
88                                    original_in[i]->area.y1,
89                                    false);
90             nr_blit_pixblock_pixblock(in[i], original_in[i]);
91         }
92     }
94     /* pixops_mix is defined in display/nr-filter-pixops.h
95      * It mixes the two input images with the function given as template
96      * and places the result in output image.
97      */
98     for (unsigned int i = 0 ; i < _input_image.size() ; i++) {
99         pixops_mix<composite_over>(*out, *in[i], *out);
100     }
102     for (unsigned int i = 0 ; i < _input_image.size() ; i++) {
103         if (in[i] != original_in[i]) {
104             nr_pixblock_release(in[i]);
105             delete in[i];
106         }
107     }
109     out->empty = FALSE;
110     slot.set(_output, out);
112     return 0;
115 void FilterMerge::set_input(int slot) {
116     _input_image[0] = slot;
119 void FilterMerge::set_input(int input, int slot) {
120     if (input < 0) return;
122     if (static_cast<int>(_input_image.size()) > input) {
123         _input_image[input] = slot;
124     } else {
125         for (int i = static_cast<int>(_input_image.size()) ; i < input ; i++) {
126             _input_image.push_back(NR_FILTER_SLOT_NOT_SET);
127         }
128         _input_image.push_back(slot);
129     }
132 } /* namespace Filters */
133 } /* namespace Inkscape */
135 /*
136   Local Variables:
137   mode:c++
138   c-file-style:"stroustrup"
139   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
140   indent-tabs-mode:nil
141   fill-column:99
142   End:
143 */
144 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :