Code

Use is_straight_curve() instead of three separate dynamic casts
[inkscape.git] / src / display / nr-filter-component-transfer.cpp
1 /*
2  * feComponentTransfer filter primitive renderer
3  *
4  * Authors:
5  *   Felipe CorrĂȘa da Silva Sanches <felipe.sanches@gmail.com>
6  *
7  * Copyright (C) 2007 authors
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
12 #include "display/nr-filter-component-transfer.h"
13 #include "display/nr-filter-units.h"
14 #include "display/nr-filter-utils.h"
15 #include "libnr/nr-pixblock.h"
16 #include "libnr/nr-blit.h"
17 #include <math.h>
19 namespace NR {
21 FilterComponentTransfer::FilterComponentTransfer()
22 {
23 }
25 FilterPrimitive * FilterComponentTransfer::create() {
26     return new FilterComponentTransfer();
27 }
29 FilterComponentTransfer::~FilterComponentTransfer()
30 {}
32 int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units*/) {
33     NRPixBlock *in = slot.get(_input);
35     if (!in) {
36         g_warning("Missing source image for feComponentTransfer (in=%d)", _input);
37         return 1;
38     }
40     int x0=in->area.x0;
41     int x1=in->area.x1;
42     int y0=in->area.y0;
43     int y1=in->area.y1;
45     NRPixBlock *out = new NRPixBlock;
46     nr_pixblock_setup_fast(out, NR_PIXBLOCK_MODE_R8G8B8A8N, x0, y0, x1, y1, true);
48     // this primitive is defined for non-premultiplied RGBA values,
49     // thus convert them to that format before blending
50     bool free_in_on_exit = false;
51     if (in->mode != NR_PIXBLOCK_MODE_R8G8B8A8N) {
52         NRPixBlock *original_in = in;
53         in = new NRPixBlock;
54         nr_pixblock_setup_fast(in, NR_PIXBLOCK_MODE_R8G8B8A8N,
55                                original_in->area.x0, original_in->area.y0,
56                                original_in->area.x1, original_in->area.y1,
57                                false);
58         nr_blit_pixblock_pixblock(in, original_in);
59         free_in_on_exit = true;
60     }
62     unsigned char *in_data = NR_PIXBLOCK_PX(in);
63     unsigned char *out_data = NR_PIXBLOCK_PX(out);
65     (void)in_data;
66     (void)out_data;
68     int size = 4 * (y1-y0) * (x1-x0);
69     int i;
71     for (int color=0;color<4;color++){
72         int _vsize = tableValues[color].size();
73         std::vector<gdouble> _tableValues = tableValues[color];
74         double _intercept = intercept[color];
75         double _slope = slope[color];
76         double _amplitude = amplitude[color];
77         double _exponent = exponent[color];
78         double _offset = offset[color];        
79         switch(type[color]){
80             case COMPONENTTRANSFER_TYPE_IDENTITY:
81                 for(i=color;i<size;i+=4){
82                     out_data[i]=in_data[i];
83                 }
84                 break;
85             case COMPONENTTRANSFER_TYPE_TABLE:
86                 if (_vsize==0){
87                     for(i=color;i<size;i+=4){
88                         out_data[i]=in_data[i];
89                     }
90                 } else {
91                     for(i=color;i<size;i+=4){
92                         int k = (int)(((_vsize-1) * (double)in_data[i])/256);
93                         double dx = ((_vsize-1) * (double)in_data[i])/256 - k;
94                         out_data[i] = CLAMP_D_TO_U8(256 * (_tableValues[k] + dx * (_tableValues[k+1] - _tableValues[k]) ));
95                     }
96                 }
97                 break;
98             case COMPONENTTRANSFER_TYPE_DISCRETE:
99                 if (_vsize==0){
100                     for(i=color;i<size;i+=4){
101                         out_data[i] = in_data[i];
102                     }
103                 } else {
104                     for(i=color;i<size;i+=4){
105                         out_data[i] = CLAMP_D_TO_U8(256 * _tableValues[(int)((_vsize-1)*(double)in_data[i]/256)] );
106                     }
107                 }
108                 break;
109             case COMPONENTTRANSFER_TYPE_LINEAR:
110                 for(i=color;i<size;i+=4){
111                     out_data[i] = CLAMP_D_TO_U8(256 * (_slope * (double)in_data[i]/256 + _intercept));
112                 }
113                 break;
114             case COMPONENTTRANSFER_TYPE_GAMMA:
115                 for(i=color;i<size;i+=4){
116                     out_data[i] = CLAMP_D_TO_U8(256 * (_amplitude * pow((double)in_data[i]/256, _exponent) + _offset));
117                 }
118                 break;
119             case COMPONENTTRANSFER_TYPE_ERROR:
120                 //TODO: report an error here
121                 break;
122         }
123     }
125     if (free_in_on_exit) {
126         nr_pixblock_release(in);
127         delete in;
128     }
130     out->empty = FALSE;
131     slot.set(_output, out);
132     return 0;
135 void FilterComponentTransfer::area_enlarge(NRRectL &/*area*/, Matrix const &/*trans*/)
139 } /* namespace NR */
141 /*
142   Local Variables:
143   mode:c++
144   c-file-style:"stroustrup"
145   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
146   indent-tabs-mode:nil
147   fill-column:99
148   End:
149 */
150 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :