~ubuntu-branches/debian/experimental/inkscape/experimental

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-09-09 23:29:02 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080909232902-c50iujhk1w79u8e7
Tags: 0.46-2.1
* Non-maintainer upload.
* Add upstream patch fixing a crash in the open dialog
  in the zh_CN.utf8 locale. Closes: #487623.
  Thanks to Luca Bruno for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * feDiffuseLighting renderer
 
3
 *
 
4
 * Authors:
 
5
 *   Niko Kiirala <niko@kiirala.com>
 
6
 *   Jean-Rene Reinhard <jr@komite.net>
 
7
 *
 
8
 * Copyright (C) 2007 authors
 
9
 *
 
10
 * Released under GNU GPL, read the file 'COPYING' for more information
 
11
 */
 
12
 
 
13
#include <glib/gmessages.h>
 
14
 
 
15
#include "display/nr-3dutils.h"
 
16
#include "display/nr-arena-item.h"
 
17
#include "display/nr-filter-diffuselighting.h"
 
18
#include "display/nr-filter-getalpha.h"
 
19
#include "display/nr-filter-slot.h"
 
20
#include "display/nr-filter-units.h"
 
21
#include "display/nr-filter-utils.h"
 
22
#include "display/nr-light.h"
 
23
#include "libnr/nr-blit.h"
 
24
#include "libnr/nr-pixblock.h"
 
25
#include "libnr/nr-matrix.h"
 
26
#include "libnr/nr-rect-l.h"
 
27
#include "color.h"
 
28
 
 
29
namespace NR {
 
30
 
 
31
FilterDiffuseLighting::FilterDiffuseLighting() 
 
32
{
 
33
    light_type = NO_LIGHT;
 
34
    diffuseConstant = 1;
 
35
    surfaceScale = 1;
 
36
    lighting_color = 0xffffffff;
 
37
}
 
38
 
 
39
FilterPrimitive * FilterDiffuseLighting::create() {
 
40
    return new FilterDiffuseLighting();
 
41
}
 
42
 
 
43
FilterDiffuseLighting::~FilterDiffuseLighting()
 
44
{}
 
45
 
 
46
#define COMPUTE_INTER(inter, N, L, kd) \
 
47
do {\
 
48
    (inter) = (kd) * scalar_product((N), (L)); \
 
49
    if ((inter) < 0) (inter) = 0; \
 
50
}while(0)
 
51
 
 
52
 
 
53
int FilterDiffuseLighting::render(FilterSlot &slot, FilterUnits const &units) {
 
54
    NRPixBlock *in = slot.get(_input);
 
55
    if (!in) {
 
56
        g_warning("Missing source image for feDiffuseLighting (in=%d)", _input);
 
57
        return 1;
 
58
    }
 
59
 
 
60
    NRPixBlock *out = new NRPixBlock;
 
61
 
 
62
    int w = in->area.x1 - in->area.x0;
 
63
    int h = in->area.y1 - in->area.y0;
 
64
    int x0 = in->area.x0;
 
65
    int y0 = in->area.y0;
 
66
    int i, j;
 
67
    //As long as FilterRes and kernel unit is not supported we hardcode the
 
68
    //default value
 
69
    int dx = 1; //TODO setup
 
70
    int dy = 1; //TODO setup
 
71
    //surface scale
 
72
    Matrix trans = units.get_matrix_primitiveunits2pb();
 
73
    gdouble ss = surfaceScale * trans[0];
 
74
    gdouble kd = diffuseConstant; //diffuse lighting constant
 
75
 
 
76
    Fvector L, N, LC;
 
77
    gdouble inter;
 
78
 
 
79
    nr_pixblock_setup_fast(out, in->mode,
 
80
            in->area.x0, in->area.y0, in->area.x1, in->area.y1,
 
81
            true);
 
82
    unsigned char *data_i = NR_PIXBLOCK_PX (in);
 
83
    unsigned char *data_o = NR_PIXBLOCK_PX (out);
 
84
    //No light, nothing to do
 
85
    switch (light_type) {
 
86
        case DISTANT_LIGHT:  
 
87
            //the light vector is constant
 
88
            {
 
89
            DistantLight *dl = new DistantLight(light.distant, lighting_color);
 
90
            dl->light_vector(L);
 
91
            dl->light_components(LC);
 
92
            //finish the work
 
93
            for (i = 0, j = 0; i < w*h; i++) {
 
94
                compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
 
95
                COMPUTE_INTER(inter, N, L, kd);
 
96
 
 
97
                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
 
98
                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
 
99
                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
 
100
                data_o[j++] = 255;
 
101
            }
 
102
            out->empty = FALSE;
 
103
            delete dl;
 
104
            }
 
105
            break;
 
106
        case POINT_LIGHT:
 
107
            {
 
108
            PointLight *pl = new PointLight(light.point, lighting_color, trans);
 
109
            pl->light_components(LC);
 
110
        //TODO we need a reference to the filter to determine primitiveUnits
 
111
        //if objectBoundingBox is used, use a different matrix for light_vector
 
112
        // UPDATE: trans is now correct matrix from primitiveUnits to
 
113
        // pixblock coordinates
 
114
            //finish the work
 
115
            for (i = 0, j = 0; i < w*h; i++) {
 
116
                compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
 
117
                pl->light_vector(L,
 
118
                        i % w + x0,
 
119
                        i / w + y0,
 
120
                        ss * (double) data_i[4*i+3]/ 255);
 
121
                COMPUTE_INTER(inter, N, L, kd);
 
122
 
 
123
                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
 
124
                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
 
125
                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
 
126
                data_o[j++] = 255;
 
127
            }
 
128
            out->empty = FALSE;
 
129
            delete pl;
 
130
            }
 
131
            break;
 
132
        case SPOT_LIGHT:
 
133
            {
 
134
            SpotLight *sl = new SpotLight(light.spot, lighting_color, trans);
 
135
        //TODO we need a reference to the filter to determine primitiveUnits
 
136
        //if objectBoundingBox is used, use a different matrix for light_vector
 
137
        // UPDATE: trans is now correct matrix from primitiveUnits to
 
138
        // pixblock coordinates
 
139
            //finish the work
 
140
            for (i = 0, j = 0; i < w*h; i++) {
 
141
                compute_surface_normal(N, ss, in, i / w, i % w, dx, dy);
 
142
                sl->light_vector(L,
 
143
                    i % w + x0,
 
144
                    i / w + y0,
 
145
                    ss * (double) data_i[4*i+3]/ 255);
 
146
                sl->light_components(LC, L);
 
147
                COMPUTE_INTER(inter, N, L, kd);
 
148
                
 
149
                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_RED]);
 
150
                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_GREEN]);
 
151
                data_o[j++] = CLAMP_D_TO_U8(inter * LC[LIGHT_BLUE]);
 
152
                data_o[j++] = 255;
 
153
            }
 
154
            out->empty = FALSE;
 
155
            delete sl;
 
156
            }
 
157
            break;
 
158
        //else unknown light source, doing nothing
 
159
        case NO_LIGHT:
 
160
        default:
 
161
            {
 
162
            if (light_type != NO_LIGHT)
 
163
                g_warning("unknown light source %d", light_type);
 
164
            for (i = 0; i < w*h; i++) {
 
165
                data_o[4*i+3] = 255;
 
166
            }
 
167
            out->empty = false;
 
168
            }
 
169
    }
 
170
        
 
171
    //finishing
 
172
    slot.set(_output, out);
 
173
    //nr_pixblock_release(in);
 
174
    //delete in;
 
175
    return 0;
 
176
}
 
177
 
 
178
FilterTraits FilterDiffuseLighting::get_input_traits() {
 
179
    return TRAIT_PARALLER;
 
180
}
 
181
 
 
182
} /* namespace NR */
 
183
 
 
184
/*
 
185
  Local Variables:
 
186
  mode:c++
 
187
  c-file-style:"stroustrup"
 
188
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
189
  indent-tabs-mode:nil
 
190
  fill-column:99
 
191
  End:
 
192
*/
 
193
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :