~ubuntu-branches/debian/experimental/inkscape/experimental

« back to all changes in this revision

Viewing changes to src/display/nr-filter-composite.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-09-09 23:29:02 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080909232902-c50iujhk1w79u8e7
Tags: 0.46-2.1
* Non-maintainer upload.
* Add upstream patch fixing a crash in the open dialog
  in the zh_CN.utf8 locale. Closes: #487623.
  Thanks to Luca Bruno for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * feComposite 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
 */
 
11
 
 
12
#include <cmath>
 
13
 
 
14
#include "isnan.h"
 
15
#include "sp-fecomposite.h"
 
16
#include "display/nr-filter-composite.h"
 
17
#include "display/nr-filter-pixops.h"
 
18
#include "display/nr-filter-slot.h"
 
19
#include "display/nr-filter-units.h"
 
20
#include "display/nr-filter-utils.h"
 
21
#include "libnr/nr-blit.h"
 
22
#include "libnr/nr-pixblock.h"
 
23
#include "libnr/nr-pixops.h"
 
24
#include "libnr/nr-matrix.h"
 
25
 
 
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
}
 
34
 
 
35
inline void
 
36
composite_in(unsigned char *r, unsigned char const *a, unsigned char const *b)
 
37
{
 
38
    r[0] = NR_NORMALIZE_21(a[0] * b[3]);
 
39
    r[1] = NR_NORMALIZE_21(a[1] * b[3]);
 
40
    r[2] = NR_NORMALIZE_21(a[2] * b[3]);
 
41
    r[3] = NR_NORMALIZE_21(a[3] * b[3]);
 
42
}
 
43
 
 
44
inline void
 
45
composite_out(unsigned char *r, unsigned char const *a, unsigned char const *b)
 
46
{
 
47
    r[0] = NR_NORMALIZE_21(a[0] * (255 - b[3]));
 
48
    r[1] = NR_NORMALIZE_21(a[1] * (255 - b[3]));
 
49
    r[2] = NR_NORMALIZE_21(a[2] * (255 - b[3]));
 
50
    r[3] = NR_NORMALIZE_21(a[3] * (255 - b[3]));
 
51
}
 
52
 
 
53
inline void
 
54
composite_atop(unsigned char *r, unsigned char const *a, unsigned char const *b)
 
55
{
 
56
    r[0] = NR_NORMALIZE_21(a[0] * b[3] + b[0] * (255 - a[3]));
 
57
    r[1] = NR_NORMALIZE_21(a[1] * b[3] + b[1] * (255 - a[3]));
 
58
    r[2] = NR_NORMALIZE_21(a[2] * b[3] + b[2] * (255 - a[3]));
 
59
    r[3] = b[3];
 
60
}
 
61
 
 
62
inline void
 
63
composite_xor(unsigned char *r, unsigned char const *a, unsigned char const *b)
 
64
{
 
65
    r[0] = NR_NORMALIZE_21(a[0] * (255 - b[3]) + b[0] * (255 - a[3]));
 
66
    r[1] = NR_NORMALIZE_21(a[1] * (255 - b[3]) + b[1] * (255 - a[3]));
 
67
    r[2] = NR_NORMALIZE_21(a[2] * (255 - b[3]) + b[2] * (255 - a[3]));
 
68
    r[3] = NR_NORMALIZE_21(a[3] * (255 - b[3]) + b[3] * (255 - a[3]));
 
69
}
 
70
 
 
71
// BUGBUG / TODO
 
72
// This makes arithmetic compositing non re-entrant and non thread safe.
 
73
static int arith_k1, arith_k2, arith_k3, arith_k4;
 
74
inline void
 
75
composite_arithmetic(unsigned char *r, unsigned char const *a, unsigned char const *b)
 
76
{
 
77
    r[0] = NR_NORMALIZE_31(NR::clamp3(arith_k1 * a[0] * b[0]
 
78
                 + arith_k2 * a[0] + arith_k3 * b[0] + arith_k4));
 
79
    r[1] = NR_NORMALIZE_31(NR::clamp3(arith_k1 * a[1] * b[1]
 
80
                 + arith_k2 * a[1] + arith_k3 * b[1] + arith_k4));
 
81
    r[2] = NR_NORMALIZE_31(NR::clamp3(arith_k1 * a[2] * b[2]
 
82
                 + arith_k2 * a[2] + arith_k3 * b[2] + arith_k4));
 
83
    r[3] = NR_NORMALIZE_31(NR::clamp3(arith_k1 * a[3] * b[3]
 
84
                 + arith_k2 * a[3] + arith_k3 * b[3] + arith_k4));
 
85
}
 
86
 
 
87
namespace NR {
 
88
 
 
89
FilterComposite::FilterComposite() :
 
90
    op(COMPOSITE_DEFAULT), k1(0), k2(0), k3(0), k4(0),
 
91
    _input2(NR::NR_FILTER_SLOT_NOT_SET)
 
92
{}
 
93
 
 
94
FilterPrimitive * FilterComposite::create() {
 
95
    return new FilterComposite();
 
96
}
 
97
 
 
98
FilterComposite::~FilterComposite()
 
99
{}
 
100
 
 
101
int FilterComposite::render(FilterSlot &slot, FilterUnits const &/*units*/) {
 
102
    NRPixBlock *in1 = slot.get(_input);
 
103
    NRPixBlock *in2 = slot.get(_input2);
 
104
    NRPixBlock *original_in1 = in1;
 
105
    NRPixBlock *original_in2 = in2;
 
106
    NRPixBlock *out;
 
107
 
 
108
    // Bail out if either one of source images is missing
 
109
    if (!in1 || !in2) {
 
110
        g_warning("Missing source image for feComposite (in=%d in2=%d)", _input, _input2);
 
111
        return 1;
 
112
    }
 
113
 
 
114
    out = new NRPixBlock;
 
115
    NRRectL out_area;
 
116
    nr_rect_l_union(&out_area, &in1->area, &in2->area);
 
117
    nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8P,
 
118
                           out_area.x0, out_area.y0, out_area.x1, out_area.y1,
 
119
                           true);
 
120
 
 
121
    // Blending modes are defined for premultiplied RGBA values,
 
122
    // thus convert them to that format before blending
 
123
    if (in1->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
 
124
        in1 = new NRPixBlock;
 
125
        nr_pixblock_setup_fast(in1, NR_PIXBLOCK_MODE_R8G8B8A8P,
 
126
                               original_in1->area.x0, original_in1->area.y0,
 
127
                               original_in1->area.x1, original_in1->area.y1,
 
128
                               false);
 
129
        nr_blit_pixblock_pixblock(in1, original_in1);
 
130
    }
 
131
    if (in2->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
 
132
        in2 = new NRPixBlock;
 
133
        nr_pixblock_setup_fast(in2, NR_PIXBLOCK_MODE_R8G8B8A8P,
 
134
                               original_in2->area.x0, original_in2->area.y0,
 
135
                               original_in2->area.x1, original_in2->area.y1,
 
136
                               false);
 
137
        nr_blit_pixblock_pixblock(in2, original_in2);
 
138
    }
 
139
 
 
140
    /* pixops_mix is defined in display/nr-filter-pixops.h
 
141
     * It mixes the two input images with the function given as template
 
142
     * and places the result in output image.
 
143
     */
 
144
    switch (op) {
 
145
        case COMPOSITE_IN:
 
146
            pixops_mix<composite_in>(*out, *in1, *in2);
 
147
            break;
 
148
        case COMPOSITE_OUT:
 
149
            pixops_mix<composite_out>(*out, *in1, *in2);
 
150
            break;
 
151
        case COMPOSITE_ATOP:
 
152
            pixops_mix<composite_atop>(*out, *in1, *in2);
 
153
            break;
 
154
        case COMPOSITE_XOR:
 
155
            pixops_mix<composite_xor>(*out, *in1, *in2);
 
156
            break;
 
157
        case COMPOSITE_ARITHMETIC:
 
158
            arith_k1 = (int)(k1 * 255);
 
159
            arith_k2 = (int)(k2 * 255 * 255);
 
160
            arith_k3 = (int)(k3 * 255 * 255);
 
161
            arith_k4 = (int)(k4 * 255 * 255 * 255);
 
162
            pixops_mix<composite_arithmetic>(*out, *in1, *in2);
 
163
            break;
 
164
        case COMPOSITE_DEFAULT:
 
165
        case COMPOSITE_OVER:
 
166
        default:
 
167
            pixops_mix<composite_over>(*out, *in1, *in2);
 
168
            break;
 
169
    }
 
170
 
 
171
    if (in1 != original_in1) {
 
172
        nr_pixblock_release(in1);
 
173
        delete in1;
 
174
    }
 
175
    if (in2 != original_in2) {
 
176
        nr_pixblock_release(in2);
 
177
        delete in2;
 
178
    }
 
179
 
 
180
    out->empty = FALSE;
 
181
    slot.set(_output, out);
 
182
 
 
183
    return 0;
 
184
}
 
185
 
 
186
void FilterComposite::set_input(int input) {
 
187
    _input = input;
 
188
}
 
189
 
 
190
void FilterComposite::set_input(int input, int slot) {
 
191
    if (input == 0) _input = slot;
 
192
    if (input == 1) _input2 = slot;
 
193
}
 
194
 
 
195
void FilterComposite::set_operator(FeCompositeOperator op) {
 
196
    if (op == COMPOSITE_DEFAULT) {
 
197
        this->op = COMPOSITE_OVER;
 
198
    } else if (op == COMPOSITE_OVER ||
 
199
               op == COMPOSITE_IN ||
 
200
               op == COMPOSITE_OUT ||
 
201
               op == COMPOSITE_ATOP ||
 
202
               op == COMPOSITE_XOR ||
 
203
               op == COMPOSITE_ARITHMETIC)
 
204
    {
 
205
        this->op = op;
 
206
    }
 
207
}
 
208
 
 
209
void FilterComposite::set_arithmetic(double k1, double k2, double k3, double k4) {
 
210
    if (!isFinite(k1) || !isFinite(k2) || !isFinite(k3) || !isFinite(k4)) {
 
211
        g_warning("Non-finite parameter for feComposite arithmetic operator");
 
212
        return;
 
213
    }
 
214
    this->k1 = k1;
 
215
    this->k2 = k2;
 
216
    this->k3 = k3;
 
217
    this->k4 = k4;
 
218
}
 
219
 
 
220
} /* namespace NR */
 
221
 
 
222
/*
 
223
  Local Variables:
 
224
  mode:c++
 
225
  c-file-style:"stroustrup"
 
226
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
227
  indent-tabs-mode:nil
 
228
  fill-column:99
 
229
  End:
 
230
*/
 
231
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :