summaryrefslogtreecommitdiffstats
path: root/src/display/nr-filter-flood.cpp
blob: 2a0996d45ddff6260079ab3405e58fd9d8ca85b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * feFlood filter primitive renderer
 *
 * Authors:
 *   Felipe Corrêa da Silva Sanches <juca@members.fsf.org>
 *   Tavmjong Bah <tavmjong@free.fr> (use primitive filter region)
 *
 * Copyright (C) 2007, 2011 authors
 *
 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
 */

#ifdef HAVE_CONFIG_H
# include "config.h"  // only include where actually required!
#endif

#include "display/cairo-utils.h"
#include "display/nr-filter-flood.h"
#include "display/nr-filter-slot.h"
#include "svg/svg-icc-color.h"
#include "svg/svg-color.h"
#include "color.h"

namespace Inkscape {
namespace Filters {

FilterFlood::FilterFlood()
= default;

FilterPrimitive * FilterFlood::create() {
    return new FilterFlood();
}

FilterFlood::~FilterFlood()
= default;

void FilterFlood::render_cairo(FilterSlot &slot)
{
    cairo_surface_t *input = slot.getcairo(_input);

    double r = SP_RGBA32_R_F(color);
    double g = SP_RGBA32_G_F(color);
    double b = SP_RGBA32_B_F(color);
    double a = opacity;

    if (icc) {
        guchar ru, gu, bu;
        icc_color_to_sRGB(icc, &ru, &gu, &bu);
        r = SP_COLOR_U_TO_F(ru);
        g = SP_COLOR_U_TO_F(gu);
        b = SP_COLOR_U_TO_F(bu);
    }

    cairo_surface_t *out = ink_cairo_surface_create_same_size(input, CAIRO_CONTENT_COLOR_ALPHA);

    SPColorInterpolation ci_fp  = SP_CSS_COLOR_INTERPOLATION_AUTO;
    if( _style ) {
        ci_fp = (SPColorInterpolation)_style->color_interpolation_filters.computed;

        // Flood color is always defined in terms of sRGB, preconvert to linearRGB
        // if color_interpolation_filters set to linearRGB (for efficiency assuming
        // next filter primitive has same value of cif).
        if( ci_fp == SP_CSS_COLOR_INTERPOLATION_LINEARRGB ) {
            r = srgb_to_linear( r );
            g = srgb_to_linear( g );
            b = srgb_to_linear( b );
        }
    }
    set_cairo_surface_ci(out, ci_fp );

    // Get filter primitive area in user units
    Geom::Rect fp = filter_primitive_area( slot.get_units() );

    // Convert to Cairo units
    Geom::Rect fp_cairo = fp * slot.get_units().get_matrix_user2pb();

    // Get area in slot (tile to fill)
    Geom::Rect sa = slot.get_slot_area();

    // Get overlap
    Geom::OptRect optoverlap = intersect( fp_cairo, sa );
    if( optoverlap ) {

        Geom::Rect overlap = *optoverlap;

        double dx = fp_cairo.min()[Geom::X] - sa.min()[Geom::X];
        double dy = fp_cairo.min()[Geom::Y] - sa.min()[Geom::Y];
        if( dx < 0.0 ) dx = 0.0;
        if( dy < 0.0 ) dy = 0.0;

        cairo_t *ct = cairo_create(out);
        cairo_set_source_rgba(ct, r, g, b, a);
        cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
        cairo_rectangle(ct, dx, dy, overlap.width(), overlap.height() );
        cairo_fill(ct);
        cairo_destroy(ct);
    }

    slot.set(_output, out);
    cairo_surface_destroy(out);
}

bool FilterFlood::can_handle_affine(Geom::Affine const &)
{
    // flood is a per-pixel primitive and is immutable under transformations
    return true;
}

void FilterFlood::set_color(guint32 c) {
    color = c;
}

void FilterFlood::set_opacity(double o) {
    opacity = o;
}

void FilterFlood::set_icc(SVGICCColor *icc_color) {
    icc = icc_color;
}
double FilterFlood::complexity(Geom::Affine const &)
{
    // flood is actually less expensive than normal rendering,
    // but when flood is processed, the object has already been rendered
    return 1.0;
}

} /* namespace Filters */
} /* namespace Inkscape */

/*
  Local Variables:
  mode:c++
  c-file-style:"stroustrup"
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
  indent-tabs-mode:nil
  fill-column:99
  End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :