~ubuntu-branches/ubuntu/utopic/inkscape/utopic-proposed

« back to all changes in this revision

Viewing changes to src/display/nr-filter-displacement-map.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alex Valavanis
  • Date: 2010-09-12 19:44:58 UTC
  • mfrom: (1.1.12 upstream) (45.1.3 maverick)
  • Revision ID: james.westby@ubuntu.com-20100912194458-4sjwmbl7dlsrk5dc
Tags: 0.48.0-1ubuntu1
* Merge with Debian unstable (LP: #628048, LP: #401567, LP: #456248, 
  LP: #463602, LP: #591986)
* debian/control: 
  - Ubuntu maintainers
  - Promote python-lxml, python-numpy, python-uniconvertor to Recommends.
  - Demote pstoedit to Suggests (universe package).
  - Suggests ttf-dejavu instead of ttf-bitstream-vera (LP: #513319)
* debian/rules:
  - Run intltool-update on build (Ubuntu-specific).
  - Add translation domain to .desktop files (Ubuntu-specific).
* debian/dirs:
  - Add usr/share/pixmaps.  Allow inkscape.xpm installation
* drop 50-poppler-API.dpatch (now upstream)
* drop 51-paste-in-unwritable-directory.dpatch (now upstream) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * feDisplacementMap filter primitive renderer
3
3
 *
4
4
 * Authors:
5
 
 *   Felipe Corrêa da Silva Sanches <felipe.sanches@gmail.com>
 
5
 *   Felipe Corrêa da Silva Sanches <juca@members.fsf.org>
6
6
 *
7
7
 * Copyright (C) 2007 authors
8
8
 *
43
43
 
44
44
static inline pixel_t pixelValue(NRPixBlock const* pb, int x, int y) {
45
45
    if ( x < pb->area.x0 || x >= pb->area.x1 || y < pb->area.y0 || y >= pb->area.y1 ) return pixel_t::blank(); // This assumes anything outside the defined range is (0,0,0,0)
46
 
    pixel_t const* data = reinterpret_cast<pixel_t const*>(NR_PIXBLOCK_PX(pb));
47
 
    int offset = (x-pb->area.x0) + (pb->area.x1-pb->area.x0)*(y-pb->area.y0);
48
 
    return data[offset];
 
46
    pixel_t const* rowData = reinterpret_cast<pixel_t const*>(NR_PIXBLOCK_PX(pb) + (y-pb->area.y0)*pb->rs);
 
47
    return rowData[x-pb->area.x0];
49
48
}
50
49
 
51
50
template<bool PREMULTIPLIED>
74
73
     * We might as well avoid premultiplication in this case, which still gives us a fully
75
74
     * transparent result, but with interpolated RGB parts. */
76
75
 
77
 
    /* First calculate interpolated alpha value. */
78
 
    unsigned ra = 0;
79
 
    if (!PREMULTIPLIED) {
80
 
        unsigned const y0 = sf*p00[3] + xf*(p01[3]-p00[3]); // range [0,a*sf]
81
 
        unsigned const y1 = sf*p10[3] + xf*(p11[3]-p10[3]);
82
 
        ra = sf*y0 + yf*(y1-y0); // range [0,a*sf*sf]
83
 
    }
84
 
 
85
76
    pixel_t r;
86
 
    if (ra == 0) {
87
 
        /* Either premultiplied or the interpolated alpha value is zero,
88
 
         * so do simple interpolation. */
 
77
    if (PREMULTIPLIED) {
 
78
        /* Premultiplied, so do simple interpolation. */
89
79
        for (unsigned i = 0; i != 4; ++i) {
90
80
            // y0,y1 have range [0,a*sf]
91
81
            unsigned const y0 = sf*p00[i] + xf*((unsigned int)p01[i]-(unsigned int)p00[i]);
95
85
            r[i] = (ri + sf2h)>>(2*sfl); // range [0,a]
96
86
        }
97
87
    } else {
98
 
        /* Do premultiplication ourselves. */
99
 
        for (unsigned i = 0; i != 3; ++i) {
100
 
            // Premultiplied versions.  Range [0,255*a].
101
 
            unsigned const c00 = p00[i]*p00[3];
102
 
            unsigned const c01 = p01[i]*p01[3];
103
 
            unsigned const c10 = p10[i]*p10[3];
104
 
            unsigned const c11 = p11[i]*p11[3];
105
 
 
106
 
            // Interpolation.
107
 
            unsigned const y0 = sf*c00 + xf*(c01-c00); // range [0,255*a*sf]
108
 
            unsigned const y1 = sf*c10 + xf*(c11-c10); // range [0,255*a*sf]
109
 
            unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*a*sf*sf]
110
 
            r[i] = (ri + ra/2) / ra;  // range [0,255]
 
88
        /* First calculate interpolated alpha value. */
 
89
        unsigned const y0 = sf*p00[3] + xf*((unsigned int)p01[3]-(unsigned int)p00[3]); // range [0,a*sf]
 
90
        unsigned const y1 = sf*p10[3] + xf*((unsigned int)p11[3]-(unsigned int)p10[3]);
 
91
        unsigned const ra = sf*y0 + yf*(y1-y0); // range [0,a*sf*sf]
 
92
 
 
93
        if (ra==0) {
 
94
            /* Fully transparent, so do simple interpolation. */
 
95
            for (unsigned i = 0; i != 3; ++i) {
 
96
                // y0,y1 have range [0,255*sf]
 
97
                unsigned const y0 = sf*p00[i] + xf*((unsigned int)p01[i]-(unsigned int)p00[i]);
 
98
                unsigned const y1 = sf*p10[i] + xf*((unsigned int)p11[i]-(unsigned int)p10[i]);
 
99
 
 
100
                unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*sf*sf]
 
101
                r[i] = (ri + sf2h)>>(2*sfl); // range [0,255]
 
102
            }
 
103
            r[3] = 0;
 
104
        } else {
 
105
            /* Do premultiplication ourselves. */
 
106
            for (unsigned i = 0; i != 3; ++i) {
 
107
                // Premultiplied versions.  Range [0,255*a].
 
108
                unsigned const c00 = p00[i]*p00[3];
 
109
                unsigned const c01 = p01[i]*p01[3];
 
110
                unsigned const c10 = p10[i]*p10[3];
 
111
                unsigned const c11 = p11[i]*p11[3];
 
112
 
 
113
                // Interpolation.
 
114
                unsigned const y0 = sf*c00 + xf*(c01-c00); // range [0,255*a*sf]
 
115
                unsigned const y1 = sf*c10 + xf*(c11-c10); // range [0,255*a*sf]
 
116
                unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*a*sf*sf]
 
117
                r[i] = (ri + ra/2) / ra;  // range [0,255]
 
118
            }
 
119
            r[3] = (ra + sf2h)>>(2*sfl); // range [0,a]
111
120
        }
112
 
        r[3] = (ra + sf2h)>>(2*sfl); // range [0,a]
113
121
    }
114
122
 
115
123
    return r;
117
125
 
118
126
template<bool MAP_PREMULTIPLIED, bool DATA_PREMULTIPLIED>
119
127
static void performDisplacement(NRPixBlock const* texture, NRPixBlock const* map, int Xchannel, int Ychannel, NRPixBlock* out, double scalex, double scaley) {
120
 
    pixel_t *out_data = reinterpret_cast<pixel_t*>(NR_PIXBLOCK_PX(out));
121
 
 
122
128
    bool Xneedsdemul = MAP_PREMULTIPLIED && Xchannel<3;
123
129
    bool Yneedsdemul = MAP_PREMULTIPLIED && Ychannel<3;
124
130
    if (!Xneedsdemul) scalex /= 255.0;
125
131
    if (!Yneedsdemul) scaley /= 255.0;
126
132
 
127
133
    for (int yout=out->area.y0; yout < out->area.y1; yout++){
 
134
        pixel_t const* mapRowData = reinterpret_cast<pixel_t const*>(NR_PIXBLOCK_PX(map) + (yout-map->area.y0)*map->rs);
 
135
        pixel_t* outRowData = reinterpret_cast<pixel_t*>(NR_PIXBLOCK_PX(out) + (yout-out->area.y0)*out->rs);
128
136
        for (int xout=out->area.x0; xout < out->area.x1; xout++){
129
 
            int xmap = xout;
130
 
            int ymap = yout;
 
137
            pixel_t const mapValue = mapRowData[xout-map->area.x0];
131
138
 
132
 
            pixel_t mapValue = pixelValue(map, xmap, ymap);
133
139
            double xtex = xout + (Xneedsdemul ? // Although the value of the pixel corresponds to the MIDDLE of the pixel, no +0.5 is needed because we're interpolating pixels anyway (so to get the actual pixel locations 0.5 would have to be subtracted again).
134
140
                (mapValue[3]==0?0:(scalex * (mapValue[Xchannel] - mapValue[3]*0.5) / mapValue[3])) :
135
141
                (scalex * (mapValue[Xchannel] - 127.5)));
137
143
                (mapValue[3]==0?0:(scaley * (mapValue[Ychannel] - mapValue[3]*0.5) / mapValue[3])) :
138
144
                (scaley * (mapValue[Ychannel] - 127.5)));
139
145
 
140
 
            out_data[(xout-out->area.x0) + (out->area.x1-out->area.x0)*(yout-out->area.y0)] = interpolatePixels<DATA_PREMULTIPLIED>(texture, xtex, ytex);
 
146
            outRowData[xout-out->area.x0] = interpolatePixels<DATA_PREMULTIPLIED>(texture, xtex, ytex);
141
147
        }
142
148
    }
143
149
}
152
158
        return 1;
153
159
    }
154
160
 
155
 
    //TODO: check whether do we really need this check:
156
 
    if (map->area.x1 <= map->area.x0 || map->area.y1 <=  map->area.y0) return 0; //nothing to do!
 
161
    NR::IRect area = units.get_pixblock_filterarea_paraller();
 
162
    int x0 = std::max(map->area.x0,area.min()[NR::X]);
 
163
    int y0 = std::max(map->area.y0,area.min()[NR::Y]);
 
164
    int x1 = std::min(map->area.x1,area.max()[NR::X]);
 
165
    int y1 = std::min(map->area.y1,area.max()[NR::Y]);
 
166
 
 
167
    //TODO: check whether we really need this check:
 
168
    if (x1 <= x0 || y1 <= y0) return 0; //nothing to do!
157
169
 
158
170
    if (texture->mode != NR_PIXBLOCK_MODE_R8G8B8A8N && texture->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
159
171
        g_warning("Source images without an alpha channel are not supported by feDisplacementMap at the moment.");
161
173
    }
162
174
 
163
175
    NRPixBlock *out = new NRPixBlock;
164
 
    
165
 
    out->area.x0 = map->area.x0;
166
 
    out->area.y0 = map->area.y0;
167
 
    out->area.x1 = map->area.x1;
168
 
    out->area.y1 = map->area.y1;
169
 
 
170
 
    nr_pixblock_setup_fast(out, texture->mode, out->area.x0, out->area.y0, out->area.x1, out->area.y1, true);
 
176
    nr_pixblock_setup_fast(out, texture->mode, x0, y0, x1, y1, true);
171
177
 
172
178
    // convert to a suitable format
173
179
    bool free_map_on_exit = false;