Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
nr-filter-displacement-map.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * feDisplacementMap filter primitive renderer
4 *
5 * Authors:
6 * Felipe CorrĂȘa da Silva Sanches <juca@members.fsf.org>
7 *
8 * Copyright (C) 2007 authors
9 *
10 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
11 */
12
14#include "display/cairo-utils.h"
18
19namespace Inkscape {
20namespace Filters {
21
22struct Displace
23{
24 Displace(cairo_surface_t *texture, cairo_surface_t *map,
25 unsigned xch, unsigned ych, double scalex, double scaley)
26 : _texture(texture)
27 , _map(map)
28 , _xch(xch)
29 , _ych(ych)
30 , _scalex(scalex / 255.0)
31 , _scaley(scaley / 255.0)
32 {
33 }
34
35 guint32 operator()(int x, int y)
36 {
37 guint32 mappx = _map.pixelAt(x, y);
38 guint32 a = (mappx & 0xff000000) >> 24;
39 guint32 xpx = 0, ypx = 0;
40 double xtex = x, ytex = y;
41
42 guint32 xshift = _xch * 8, yshift = _ych * 8;
43 xpx = (mappx & (0xff << xshift)) >> xshift;
44 ypx = (mappx & (0xff << yshift)) >> yshift;
45 if (a) {
46 if (_xch != 3) xpx = unpremul_alpha(xpx, a);
47 if (_ych != 3) ypx = unpremul_alpha(ypx, a);
48 }
49 xtex += _scalex * (xpx - 127.5);
50 ytex += _scaley * (ypx - 127.5);
51
52 if (xtex >= 0 && xtex < _texture._w - 1 &&
53 ytex >= 0 && ytex < _texture._h - 1)
54 {
55 return _texture.pixelAt(xtex, ytex);
56 } else {
57 return 0;
58 }
59 }
60
61private:
62 SurfaceSynth _texture;
63 SurfaceSynth _map;
64 unsigned _xch, _ych;
65 double _scalex, _scaley;
66};
67
69{
70 cairo_surface_t *texture = slot.getcairo(_input);
71 cairo_surface_t *map = slot.getcairo(_input2);
73 // color_interpolation_filters for out same as texture. See spec.
74 copy_cairo_surface_ci(texture, out);
75
76 // We may need to transform map surface to correct color interpolation space. The map surface
77 // might be used as input to another primitive but it is likely that all the primitives in a given
78 // filter use the same color interpolation space so we don't copy the map before converting.
80
82
83 int device_scale = slot.get_device_scale();
84 double scalex = scale * trans.expansionX() * device_scale;
85 double scaley = scale * trans.expansionY() * device_scale;
86
87 ink_cairo_surface_synthesize(out, Displace(texture, map, Xchannel, Ychannel, scalex, scaley));
88
89 slot.set(_output, out);
90 cairo_surface_destroy(out);
91}
92
94{
95 _input = slot;
96}
97
99{
100 scale = s;
101}
102
103void FilterDisplacementMap::set_input(int input, int slot)
104{
105 if (input == 0) _input = slot;
106 if (input == 1) _input2 = slot;
107}
108
110{
112 g_warning("Selected an invalid channel value. (%d)", channel);
113 return;
114 }
115
116 // channel numbering:
117 // a = 3, r = 2, g = 1, b = 0
118 // this way we can get the component value using:
119 // component = (color & (ch*8)) >> (ch*8)
120 unsigned ch;
121 switch (channel) {
123 ch = 3;
124 break;
126 ch = 2;
127 break;
129 ch = 1;
130 break;
132 ch = 0;
133 break;
134 default:
135 return;
136 }
137
138 if (s == 0) Xchannel = ch;
139 if (s == 1) Ychannel = ch;
140}
141
143{
144 //I assume scale is in user coordinates (?!?)
145 //FIXME: trans should be multiplied by some primitiveunits2user, shouldn't it?
146
147 double scalex = scale / 2. * (std::fabs(trans[0]) + std::fabs(trans[1]));
148 double scaley = scale / 2. * (std::fabs(trans[2]) + std::fabs(trans[3]));
149
150 //FIXME: no +2 should be there!... (noticeable only for big scales at big zoom factor)
151 area.expandBy(scalex + 2, scaley + 2);
152}
153
155{
156 return 3.0;
157}
158
159} // namespace Filters
160} // namespace Inkscape
161
162/*
163 Local Variables:
164 mode:c++
165 c-file-style:"stroustrup"
166 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
167 indent-tabs-mode:nil
168 fill-column:99
169 End:
170*/
171// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
Cairo software blending templates.
void ink_cairo_surface_synthesize(cairo_surface_t *out, cairo_rectangle_t const &out_area, Synth &&synth)
Synthesize surface pixels based on their position.
void copy_cairo_surface_ci(cairo_surface_t *in, cairo_surface_t *out)
cairo_surface_t * ink_cairo_surface_create_identical(cairo_surface_t *s)
Create a surface that differs only in pixel content.
void set_cairo_surface_ci(cairo_surface_t *surface, SPColorInterpolation ci)
Set the color_interpolation_value for a Cairo surface.
Cairo integration helpers.
G_GNUC_CONST guint32 unpremul_alpha(const guint32 color, const guint32 alpha)
3x3 matrix representing an affine transformation.
Definition affine.h:70
Coord expansionX() const
Calculates the amount of x-scaling imparted by the Affine.
Definition affine.cpp:64
Coord expansionY() const
Calculates the amount of y-scaling imparted by the Affine.
Definition affine.cpp:71
Axis aligned, non-empty, generic rectangle.
void expandBy(C amount)
Expand the rectangle in both directions by the specified amount.
void area_enlarge(Geom::IntRect &area, Geom::Affine const &trans) const override
void render_cairo(FilterSlot &slot) const override
void set_channel_selector(int s, FilterDisplacementMapChannelSelector channel)
double complexity(Geom::Affine const &ctm) const override
void set_input(int slot) override
Sets the input slot number 'slot' to be used as input in rendering filter primitive 'primitive' For f...
cairo_surface_t * getcairo(int slot)
Returns the pixblock in specified slot.
void set(int slot, cairo_surface_t *s)
Sets or re-sets the pixblock associated with given slot.
int get_device_scale() const
Gets the device scale; for high DPI monitors.
FilterUnits const & get_units() const
Geom::Affine get_matrix_primitiveunits2pb() const
Gets the primitiveUnits to pixblock coordinates transformation matrix.
FilterDisplacementMapChannelSelector
@ DISPLACEMENTMAP_CHANNEL_RED
@ DISPLACEMENTMAP_CHANNEL_BLUE
@ DISPLACEMENTMAP_CHANNEL_GREEN
@ DISPLACEMENTMAP_CHANNEL_ALPHA
unsigned int guint32
struct _cairo_surface cairo_surface_t
Helper class to stream background task notifications as a series of messages.
TODO: insert short description here.