~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Kees Cook, Ted Gould
  • Date: 2008-02-10 14:20:16 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20080210142016-vcnb2zqyhszu0xvb
Tags: 0.46~pre1-0ubuntu1
[ Kees Cook ]
* debian/control:
  - add libgtkspell-dev build-dep to gain GtkSpell features (LP: #183547).
  - update Standards version (no changes needed).
  - add Vcs and Homepage fields.
  - switch to new python-lxml dep.
* debian/{control,rules}: switch from dpatch to quilt for more sanity.
* debian/patches/20_fix_glib_and_gxx43_ftbfs.patch:
  - merged against upstream fixes.
  - added additional fixes for newly written code.
* debian/rules: enable parallel building.

[ Ted Gould ]
* Updating POTFILES.in to make it so things build correctly.
* debian/control:
  - add ImageMagick++ and libboost-dev to build-deps

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * SVG feBlend renderer
 
3
 *
 
4
 * "This filter composites two objects together using commonly used
 
5
 * imaging software blending modes. It performs a pixel-wise combination
 
6
 * of two input images." 
 
7
 * http://www.w3.org/TR/SVG11/filters.html#feBlend
 
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
 */
 
16
 
 
17
#include "display/nr-filter-blend.h"
 
18
#include "display/nr-filter-pixops.h"
 
19
#include "display/nr-filter-primitive.h"
 
20
#include "display/nr-filter-slot.h"
 
21
#include "display/nr-filter-types.h"
 
22
#include "display/nr-filter-units.h"
 
23
#include "libnr/nr-pixblock.h"
 
24
#include "libnr/nr-matrix.h"
 
25
#include "libnr/nr-blit.h"
 
26
#include "libnr/nr-pixops.h"
 
27
 
 
28
namespace NR {
 
29
 
 
30
/*
 
31
 * From http://www.w3.org/TR/SVG11/filters.html#feBlend
 
32
 *
 
33
 * For all feBlend modes, the result opacity is computed as follows:
 
34
 * qr = 1 - (1-qa)*(1-qb)
 
35
 *
 
36
 * For the compositing formulas below, the following definitions apply:
 
37
 * cr = Result color (RGB) - premultiplied
 
38
 * qa = Opacity value at a given pixel for image A
 
39
 * qb = Opacity value at a given pixel for image B
 
40
 * ca = Color (RGB) at a given pixel for image A - premultiplied
 
41
 * cb = Color (RGB) at a given pixel for image B - premultiplied
 
42
 */
 
43
 
 
44
/*
 
45
 * These blending equations given in SVG standard are for color values
 
46
 * in the range 0..1. As these values are stored as unsigned char values,
 
47
 * they need some reworking. An unsigned char value can be thought as
 
48
 * 0.8 fixed point representation of color value. This is how I've
 
49
 * ended up with these equations here.
 
50
 */
 
51
 
 
52
// Set alpha / opacity. This line is same for all the blending modes,
 
53
// so let's save some copy-pasting.
 
54
#define SET_ALPHA r[3] = NR_NORMALIZE_21((255 * 255) - (255 - a[3]) * (255 - b[3]))
 
55
 
 
56
// cr = (1 - qa) * cb + ca
 
57
inline void
 
58
blend_normal(unsigned char *r, unsigned char const *a, unsigned char const *b)
 
59
{
 
60
    r[0] = NR_NORMALIZE_21((255 - a[3]) * b[0]) + a[0];
 
61
    r[1] = NR_NORMALIZE_21((255 - a[3]) * b[1]) + a[1];
 
62
    r[2] = NR_NORMALIZE_21((255 - a[3]) * b[2]) + a[2];
 
63
    SET_ALPHA;
 
64
}
 
65
 
 
66
// cr = (1-qa)*cb + (1-qb)*ca + ca*cb
 
67
inline void
 
68
blend_multiply(unsigned char *r, unsigned char const *a, unsigned char const *b)
 
69
{
 
70
    r[0] = NR_NORMALIZE_21((255 - a[3]) * b[0] + (255 - b[3]) * a[0]
 
71
                           + a[0] * b[0]);
 
72
    r[1] = NR_NORMALIZE_21((255 - a[3]) * b[1] + (255 - b[3]) * a[1]
 
73
                           + a[1] * b[1]);
 
74
    r[2] = NR_NORMALIZE_21((255 - a[3]) * b[2] + (255 - b[3]) * a[2]
 
75
                           + a[2] * b[2]);
 
76
    SET_ALPHA;
 
77
}
 
78
 
 
79
// cr = cb + ca - ca * cb
 
80
inline void
 
81
blend_screen(unsigned char *r, unsigned char const *a, unsigned char const *b)
 
82
{
 
83
    r[0] = NR_NORMALIZE_21(b[0] * 255 + a[0] * 255 - a[0] * b[0]);
 
84
    r[1] = NR_NORMALIZE_21(b[1] * 255 + a[1] * 255 - a[1] * b[1]);
 
85
    r[2] = NR_NORMALIZE_21(b[2] * 255 + a[2] * 255 - a[2] * b[2]);
 
86
    SET_ALPHA;
 
87
}
 
88
 
 
89
// cr = Min ((1 - qa) * cb + ca, (1 - qb) * ca + cb)
 
90
inline void
 
91
blend_darken(unsigned char *r, unsigned char const *a, unsigned char const *b)
 
92
{
 
93
    r[0] = std::min(NR_NORMALIZE_21((255 - a[3]) * b[0]) + a[0],
 
94
                    NR_NORMALIZE_21((255 - b[3]) * a[0]) + b[0]);
 
95
    r[1] = std::min(NR_NORMALIZE_21((255 - a[3]) * b[1]) + a[1],
 
96
                    NR_NORMALIZE_21((255 - b[3]) * a[1]) + b[1]);
 
97
    r[2] = std::min(NR_NORMALIZE_21((255 - a[3]) * b[2]) + a[2],
 
98
                    NR_NORMALIZE_21((255 - b[3]) * a[2]) + b[2]);
 
99
    SET_ALPHA;
 
100
}
 
101
 
 
102
// cr = Max ((1 - qa) * cb + ca, (1 - qb) * ca + cb)
 
103
inline void
 
104
blend_lighten(unsigned char *r, unsigned char const *a, unsigned char const *b)
 
105
{
 
106
    r[0] = std::max(NR_NORMALIZE_21((255 - a[3]) * b[0]) + a[0],
 
107
                    NR_NORMALIZE_21((255 - b[3]) * a[0]) + b[0]);
 
108
    r[1] = std::max(NR_NORMALIZE_21((255 - a[3]) * b[1]) + a[1],
 
109
                    NR_NORMALIZE_21((255 - b[3]) * a[1]) + b[1]);
 
110
    r[2] = std::max(NR_NORMALIZE_21((255 - a[3]) * b[2]) + a[2],
 
111
                    NR_NORMALIZE_21((255 - b[3]) * a[2]) + b[2]);
 
112
    SET_ALPHA;
 
113
}
 
114
 
 
115
FilterBlend::FilterBlend() 
 
116
    : _blend_mode(BLEND_NORMAL),
 
117
      _input2(NR_FILTER_SLOT_NOT_SET)
 
118
{}
 
119
 
 
120
FilterPrimitive * FilterBlend::create() {
 
121
    return new FilterBlend();
 
122
}
 
123
 
 
124
FilterBlend::~FilterBlend()
 
125
{}
 
126
 
 
127
int FilterBlend::render(FilterSlot &slot, FilterUnits const & /*units*/) {
 
128
    NRPixBlock *in1 = slot.get(_input);
 
129
    NRPixBlock *in2 = slot.get(_input2);
 
130
    NRPixBlock *original_in1 = in1;
 
131
    NRPixBlock *original_in2 = in2;
 
132
    NRPixBlock *out;
 
133
 
 
134
    // Bail out if either one of source images is missing
 
135
    if (!in1 || !in2) {
 
136
        g_warning("Missing source image for feBlend (in=%d in2=%d)", _input, _input2);
 
137
        return 1;
 
138
    }
 
139
 
 
140
    out = new NRPixBlock;
 
141
    NRRectL out_area;
 
142
    nr_rect_l_union(&out_area, &in1->area, &in2->area);
 
143
    nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8P,
 
144
                           out_area.x0, out_area.y0, out_area.x1, out_area.y1,
 
145
                           true);
 
146
 
 
147
    // Blending modes are defined for premultiplied RGBA values,
 
148
    // thus convert them to that format before blending
 
149
    if (in1->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
 
150
        in1 = new NRPixBlock;
 
151
        nr_pixblock_setup_fast(in1, NR_PIXBLOCK_MODE_R8G8B8A8P,
 
152
                               original_in1->area.x0, original_in1->area.y0,
 
153
                               original_in1->area.x1, original_in1->area.y1,
 
154
                               false);
 
155
        nr_blit_pixblock_pixblock(in1, original_in1);
 
156
    }
 
157
    if (in2->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
 
158
        in2 = new NRPixBlock;
 
159
        nr_pixblock_setup_fast(in2, NR_PIXBLOCK_MODE_R8G8B8A8P,
 
160
                               original_in2->area.x0, original_in2->area.y0,
 
161
                               original_in2->area.x1, original_in2->area.y1,
 
162
                               false);
 
163
        nr_blit_pixblock_pixblock(in2, original_in2);
 
164
    }
 
165
 
 
166
    /* pixops_mix is defined in display/nr-filter-pixops.h
 
167
     * It mixes the two input images with the function given as template
 
168
     * and places the result in output image.
 
169
     */
 
170
    switch (_blend_mode) {
 
171
        case BLEND_MULTIPLY:
 
172
            pixops_mix<blend_multiply>(*out, *in1, *in2);
 
173
            break;
 
174
        case BLEND_SCREEN:
 
175
            pixops_mix<blend_screen>(*out, *in1, *in2);
 
176
            break;
 
177
        case BLEND_DARKEN:
 
178
            pixops_mix<blend_darken>(*out, *in1, *in2);
 
179
            break;
 
180
        case BLEND_LIGHTEN:
 
181
            pixops_mix<blend_lighten>(*out, *in1, *in2);
 
182
            break;
 
183
        case BLEND_NORMAL:
 
184
        default:
 
185
            pixops_mix<blend_normal>(*out, *in1, *in2);
 
186
            break;
 
187
    }
 
188
 
 
189
    if (in1 != original_in1) {
 
190
        nr_pixblock_release(in1);
 
191
        delete in1;
 
192
    }
 
193
    if (in2 != original_in2) {
 
194
        nr_pixblock_release(in2);
 
195
        delete in2;
 
196
    }
 
197
 
 
198
    out->empty = FALSE;
 
199
    slot.set(_output, out);
 
200
 
 
201
    return 0;
 
202
}
 
203
 
 
204
void FilterBlend::set_input(int slot) {
 
205
    _input = slot;
 
206
}
 
207
 
 
208
void FilterBlend::set_input(int input, int slot) {
 
209
    if (input == 0) _input = slot;
 
210
    if (input == 1) _input2 = slot;
 
211
}
 
212
 
 
213
void FilterBlend::set_mode(FilterBlendMode mode) {
 
214
    if (mode == BLEND_NORMAL || mode == BLEND_MULTIPLY ||
 
215
        mode == BLEND_SCREEN || mode == BLEND_DARKEN ||
 
216
        mode == BLEND_LIGHTEN)
 
217
    {
 
218
        _blend_mode = mode;
 
219
    }
 
220
}
 
221
 
 
222
} /* namespace NR */
 
223
 
 
224
/*
 
225
  Local Variables:
 
226
  mode:c++
 
227
  c-file-style:"stroustrup"
 
228
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
229
  indent-tabs-mode:nil
 
230
  fill-column:99
 
231
  End:
 
232
*/
 
233
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :