2
* feComposite filter effect renderer
5
* Niko Kiirala <niko@kiirala.com>
7
* Copyright (C) 2007 authors
9
* Released under GNU GPL, read the file 'COPYING' for more information
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"
27
composite_over(unsigned char *r, unsigned char const *a, unsigned char const *b)
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]));
36
composite_in(unsigned char *r, unsigned char const *a, unsigned char const *b)
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]);
45
composite_out(unsigned char *r, unsigned char const *a, unsigned char const *b)
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]));
54
composite_atop(unsigned char *r, unsigned char const *a, unsigned char const *b)
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]));
63
composite_xor(unsigned char *r, unsigned char const *a, unsigned char const *b)
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]));
72
// This makes arithmetic compositing non re-entrant and non thread safe.
73
static int arith_k1, arith_k2, arith_k3, arith_k4;
75
composite_arithmetic(unsigned char *r, unsigned char const *a, unsigned char const *b)
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));
89
FilterComposite::FilterComposite() :
90
op(COMPOSITE_DEFAULT), k1(0), k2(0), k3(0), k4(0),
91
_input2(NR::NR_FILTER_SLOT_NOT_SET)
94
FilterPrimitive * FilterComposite::create() {
95
return new FilterComposite();
98
FilterComposite::~FilterComposite()
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;
108
// Bail out if either one of source images is missing
110
g_warning("Missing source image for feComposite (in=%d in2=%d)", _input, _input2);
114
out = new NRPixBlock;
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,
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,
129
nr_blit_pixblock_pixblock(in1, original_in1);
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,
137
nr_blit_pixblock_pixblock(in2, original_in2);
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.
146
pixops_mix<composite_in>(*out, *in1, *in2);
149
pixops_mix<composite_out>(*out, *in1, *in2);
152
pixops_mix<composite_atop>(*out, *in1, *in2);
155
pixops_mix<composite_xor>(*out, *in1, *in2);
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);
164
case COMPOSITE_DEFAULT:
167
pixops_mix<composite_over>(*out, *in1, *in2);
171
if (in1 != original_in1) {
172
nr_pixblock_release(in1);
175
if (in2 != original_in2) {
176
nr_pixblock_release(in2);
181
slot.set(_output, out);
186
void FilterComposite::set_input(int input) {
190
void FilterComposite::set_input(int input, int slot) {
191
if (input == 0) _input = slot;
192
if (input == 1) _input2 = slot;
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)
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");
225
c-file-style:"stroustrup"
226
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
231
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :