1
use std::cmp::min;
2

            
3
use cssparser::Parser;
4
use markup5ever::{expanded_name, local_name, namespace_url, ns};
5

            
6
use crate::document::AcquiredNodes;
7
use crate::drawing_ctx::DrawingCtx;
8
use crate::element::{set_attribute, ElementData, ElementTrait};
9
use crate::error::*;
10
use crate::node::{CascadedValues, Node, NodeBorrow};
11
use crate::parse_identifiers;
12
use crate::parsers::{NumberList, Parse, ParseValue};
13
use crate::properties::ColorInterpolationFilters;
14
use crate::rect::IRect;
15
use crate::session::Session;
16
use crate::surface_utils::{
17
    iterators::Pixels, shared_surface::ExclusiveImageSurface, ImageSurfaceDataExt, Pixel,
18
};
19
use crate::util::clamp;
20
use crate::xml::Attributes;
21

            
22
use super::bounds::BoundsBuilder;
23
use super::context::{FilterContext, FilterOutput};
24
use super::{
25
    FilterEffect, FilterError, FilterResolveError, Input, Primitive, PrimitiveParams,
26
    ResolvedPrimitive,
27
};
28

            
29
/// The `feComponentTransfer` filter primitive.
30
16
#[derive(Default)]
31
pub struct FeComponentTransfer {
32
16
    base: Primitive,
33
16
    params: ComponentTransfer,
34
}
35

            
36
/// Resolved `feComponentTransfer` primitive for rendering.
37
76
#[derive(Clone, Default)]
38
pub struct ComponentTransfer {
39
38
    pub in1: Input,
40
38
    pub functions: Functions,
41
38
    pub color_interpolation_filters: ColorInterpolationFilters,
42
}
43

            
44
impl ElementTrait for FeComponentTransfer {
45
16
    fn set_attributes(&mut self, attrs: &Attributes, session: &Session) {
46
16
        self.params.in1 = self.base.parse_one_input(attrs, session);
47
16
    }
48
}
49

            
50
/// Component transfer function types.
51
98
#[derive(Clone, Debug, PartialEq)]
52
pub enum FunctionType {
53
    Identity,
54
    Table,
55
    Discrete,
56
    Linear,
57
    Gamma,
58
}
59

            
60
impl Parse for FunctionType {
61
45
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
62
90
        Ok(parse_identifiers!(
63
            parser,
64
            "identity" => FunctionType::Identity,
65
            "table" => FunctionType::Table,
66
            "discrete" => FunctionType::Discrete,
67
            "linear" => FunctionType::Linear,
68
            "gamma" => FunctionType::Gamma,
69
        )?)
70
45
    }
71
}
72

            
73
/// The compute function parameters.
74
struct FunctionParameters {
75
    table_values: Vec<f64>,
76
    slope: f64,
77
    intercept: f64,
78
    amplitude: f64,
79
    exponent: f64,
80
    offset: f64,
81
}
82

            
83
88
#[derive(Clone, Debug, Default, PartialEq)]
84
pub struct Functions {
85
44
    pub r: FeFuncR,
86
44
    pub g: FeFuncG,
87
44
    pub b: FeFuncB,
88
44
    pub a: FeFuncA,
89
}
90

            
91
/// The compute function type.
92
type Function = fn(&FunctionParameters, f64) -> f64;
93

            
94
/// The identity component transfer function.
95
1392000
fn identity(_: &FunctionParameters, value: f64) -> f64 {
96
    value
97
1392000
}
98

            
99
/// The table component transfer function.
100
909191
fn table(params: &FunctionParameters, value: f64) -> f64 {
101
909191
    let n = params.table_values.len() - 1;
102
909191
    let k = (value * (n as f64)).floor() as usize;
103

            
104
909191
    let k = min(k, n); // Just in case.
105

            
106
909191
    if k == n {
107
159990
        return params.table_values[k];
108
    }
109

            
110
749201
    let vk = params.table_values[k];
111
749201
    let vk1 = params.table_values[k + 1];
112
749201
    let k = k as f64;
113
749201
    let n = n as f64;
114

            
115
749201
    vk + (value - k / n) * n * (vk1 - vk)
116
909191
}
117

            
118
/// The discrete component transfer function.
119
fn discrete(params: &FunctionParameters, value: f64) -> f64 {
120
    let n = params.table_values.len();
121
    let k = (value * (n as f64)).floor() as usize;
122

            
123
    params.table_values[min(k, n - 1)]
124
}
125

            
126
/// The linear component transfer function.
127
1214674
fn linear(params: &FunctionParameters, value: f64) -> f64 {
128
1214674
    params.slope * value + params.intercept
129
1214674
}
130

            
131
/// The gamma component transfer function.
132
42225
fn gamma(params: &FunctionParameters, value: f64) -> f64 {
133
42225
    params.amplitude * value.powf(params.exponent) + params.offset
134
42225
}
135

            
136
/// Common values for `feFuncX` elements
137
///
138
/// The elements `feFuncR`, `feFuncG`, `feFuncB`, `feFuncA` all have the same parameters; this structure
139
/// contains them.  Later we define newtypes on this struct as [`FeFuncR`], etc.
140
196
#[derive(Clone, Debug, PartialEq)]
141
pub struct FeFuncCommon {
142
98
    pub function_type: FunctionType,
143
98
    pub table_values: Vec<f64>,
144
98
    pub slope: f64,
145
98
    pub intercept: f64,
146
98
    pub amplitude: f64,
147
98
    pub exponent: f64,
148
98
    pub offset: f64,
149
}
150

            
151
impl Default for FeFuncCommon {
152
    #[inline]
153
204
    fn default() -> Self {
154
204
        Self {
155
204
            function_type: FunctionType::Identity,
156
204
            table_values: Vec::new(),
157
            slope: 1.0,
158
            intercept: 0.0,
159
            amplitude: 1.0,
160
            exponent: 1.0,
161
            offset: 0.0,
162
        }
163
204
    }
164
}
165

            
166
// All FeFunc* elements are defined here; they just delegate their attributes
167
// to the FeFuncCommon inside.
168
macro_rules! impl_func {
169
    ($(#[$attr:meta])*
170
     $name:ident
171
    ) => {
172
572
        #[derive(Clone, Debug, Default, PartialEq)]
173
286
        pub struct $name(pub FeFuncCommon);
174

            
175
        impl ElementTrait for $name {
176
45
            fn set_attributes(&mut self, attrs: &Attributes, session: &Session) {
177
45
                self.0.set_attributes(attrs, session);
178
45
            }
179
        }
180
    };
181
}
182

            
183
impl_func!(
184
    /// The `feFuncR` element.
185
    FeFuncR
186
);
187

            
188
impl_func!(
189
    /// The `feFuncG` element.
190
    FeFuncG
191
);
192

            
193
impl_func!(
194
    /// The `feFuncB` element.
195
    FeFuncB
196
);
197

            
198
impl_func!(
199
    /// The `feFuncA` element.
200
    FeFuncA
201
);
202

            
203
impl FeFuncCommon {
204
45
    fn set_attributes(&mut self, attrs: &Attributes, session: &Session) {
205
153
        for (attr, value) in attrs.iter() {
206
108
            match attr.expanded() {
207
                expanded_name!("", "type") => {
208
45
                    set_attribute(&mut self.function_type, attr.parse(value), session)
209
                }
210
                expanded_name!("", "tableValues") => {
211
                    // #691: Limit list to 256 to mitigate malicious SVGs
212
13
                    let mut number_list = NumberList::<0, 256>(Vec::new());
213
13
                    set_attribute(&mut number_list, attr.parse(value), session);
214
13
                    self.table_values = number_list.0;
215
13
                }
216
                expanded_name!("", "slope") => {
217
16
                    set_attribute(&mut self.slope, attr.parse(value), session)
218
                }
219
                expanded_name!("", "intercept") => {
220
13
                    set_attribute(&mut self.intercept, attr.parse(value), session)
221
                }
222
                expanded_name!("", "amplitude") => {
223
7
                    set_attribute(&mut self.amplitude, attr.parse(value), session)
224
                }
225
                expanded_name!("", "exponent") => {
226
7
                    set_attribute(&mut self.exponent, attr.parse(value), session)
227
                }
228
                expanded_name!("", "offset") => {
229
7
                    set_attribute(&mut self.offset, attr.parse(value), session)
230
                }
231

            
232
                _ => (),
233
            }
234
108
        }
235

            
236
        // The table function type with empty table_values is considered
237
        // an identity function.
238
45
        match self.function_type {
239
            FunctionType::Table | FunctionType::Discrete => {
240
2
                if self.table_values.is_empty() {
241
2
                    self.function_type = FunctionType::Identity;
242
                }
243
            }
244
            _ => (),
245
        }
246
45
    }
247

            
248
72
    fn function_parameters(&self) -> FunctionParameters {
249
72
        FunctionParameters {
250
72
            table_values: self.table_values.clone(),
251
72
            slope: self.slope,
252
72
            intercept: self.intercept,
253
72
            amplitude: self.amplitude,
254
72
            exponent: self.exponent,
255
72
            offset: self.offset,
256
        }
257
72
    }
258

            
259
72
    fn function(&self) -> Function {
260
72
        match self.function_type {
261
32
            FunctionType::Identity => identity,
262
14
            FunctionType::Table => table,
263
            FunctionType::Discrete => discrete,
264
20
            FunctionType::Linear => linear,
265
6
            FunctionType::Gamma => gamma,
266
        }
267
72
    }
268
}
269

            
270
macro_rules! func_or_default {
271
    ($func_node:ident, $func_type:ident) => {
272
        match $func_node {
273
            Some(ref f) => match &*f.borrow_element_data() {
274
                ElementData::$func_type(e) => (**e).clone(),
275
                _ => unreachable!(),
276
            },
277
            _ => $func_type::default(),
278
        }
279
    };
280
}
281

            
282
macro_rules! get_func_x_node {
283
    ($func_node:ident, $func_type:ident) => {
284
        $func_node
285
            .children()
286
            .rev()
287
274
            .filter(|c| c.is_element())
288
126
            .find(|c| matches!(*c.borrow_element_data(), ElementData::$func_type(_)))
289
    };
290
}
291

            
292
impl ComponentTransfer {
293
18
    pub fn render(
294
        &self,
295
        bounds_builder: BoundsBuilder,
296
        ctx: &FilterContext,
297
        acquired_nodes: &mut AcquiredNodes<'_>,
298
        draw_ctx: &mut DrawingCtx,
299
    ) -> Result<FilterOutput, FilterError> {
300
36
        let input_1 = ctx.get_input(
301
            acquired_nodes,
302
            draw_ctx,
303
18
            &self.in1,
304
18
            self.color_interpolation_filters,
305
        )?;
306
18
        let bounds: IRect = bounds_builder
307
            .add_input(&input_1)
308
            .compute(ctx)
309
            .clipped
310
            .into();
311

            
312
        // Create the output surface.
313
18
        let mut surface = ExclusiveImageSurface::new(
314
18
            ctx.source_graphic().width(),
315
18
            ctx.source_graphic().height(),
316
18
            input_1.surface().surface_type(),
317
        )?;
318

            
319
54
        fn compute_func(func: &FeFuncCommon) -> impl Fn(u8, f64, f64) -> u8 {
320
54
            let compute = func.function();
321
54
            let params = func.function_parameters();
322

            
323
2463472
            move |value, alpha, new_alpha| {
324
2463418
                let value = f64::from(value) / 255f64;
325

            
326
2463418
                let unpremultiplied = if alpha == 0f64 { 0f64 } else { value / alpha };
327

            
328
2463418
                let new_value = compute(&params, unpremultiplied);
329
2463418
                let new_value = clamp(new_value, 0f64, 1f64);
330

            
331
2463418
                ((new_value * new_alpha * 255f64) + 0.5) as u8
332
2463418
            }
333
54
        }
334

            
335
18
        let compute_r = compute_func(&self.functions.r.0);
336
18
        let compute_g = compute_func(&self.functions.g.0);
337
18
        let compute_b = compute_func(&self.functions.b.0);
338

            
339
        // Alpha gets special handling since everything else depends on it.
340
18
        let compute_a = self.functions.a.0.function();
341
18
        let params_a = self.functions.a.0.function_parameters();
342
906752
        let compute_a = |alpha| compute_a(&params_a, alpha);
343

            
344
        // Do the actual processing.
345
36
        surface.modify(&mut |data, stride| {
346
952323
            for (x, y, pixel) in Pixels::within(input_1.surface(), bounds) {
347
952305
                let alpha = f64::from(pixel.a) / 255f64;
348
952305
                let new_alpha = compute_a(alpha);
349

            
350
952305
                let output_pixel = Pixel {
351
952305
                    r: compute_r(pixel.r, alpha, new_alpha),
352
952305
                    g: compute_g(pixel.g, alpha, new_alpha),
353
952305
                    b: compute_b(pixel.b, alpha, new_alpha),
354
952305
                    a: ((new_alpha * 255f64) + 0.5) as u8,
355
                };
356

            
357
952305
                data.set_pixel(stride, output_pixel, x, y);
358
            }
359
18
        });
360

            
361
18
        Ok(FilterOutput {
362
18
            surface: surface.share()?,
363
18
            bounds,
364
        })
365
18
    }
366
}
367

            
368
impl FilterEffect for FeComponentTransfer {
369
14
    fn resolve(
370
        &self,
371
        _acquired_nodes: &mut AcquiredNodes<'_>,
372
        node: &Node,
373
    ) -> Result<Vec<ResolvedPrimitive>, FilterResolveError> {
374
14
        let cascaded = CascadedValues::new_from_node(node);
375
14
        let values = cascaded.get();
376

            
377
14
        let mut params = self.params.clone();
378
14
        params.functions = get_functions(node)?;
379
14
        params.color_interpolation_filters = values.color_interpolation_filters();
380

            
381
14
        Ok(vec![ResolvedPrimitive {
382
14
            primitive: self.base.clone(),
383
14
            params: PrimitiveParams::ComponentTransfer(params),
384
        }])
385
14
    }
386
}
387

            
388
/// Takes a feComponentTransfer and walks its children to produce the feFuncX arguments.
389
15
fn get_functions(node: &Node) -> Result<Functions, FilterResolveError> {
390
15
    let func_r_node = get_func_x_node!(node, FeFuncR);
391
15
    let func_g_node = get_func_x_node!(node, FeFuncG);
392
15
    let func_b_node = get_func_x_node!(node, FeFuncB);
393
15
    let func_a_node = get_func_x_node!(node, FeFuncA);
394

            
395
15
    let r = func_or_default!(func_r_node, FeFuncR);
396
15
    let g = func_or_default!(func_g_node, FeFuncG);
397
15
    let b = func_or_default!(func_b_node, FeFuncB);
398
15
    let a = func_or_default!(func_a_node, FeFuncA);
399

            
400
15
    Ok(Functions { r, g, b, a })
401
15
}
402

            
403
#[cfg(test)]
404
mod tests {
405
    use super::*;
406
    use crate::document::Document;
407

            
408
    #[test]
409
2
    fn extracts_functions() {
410
1
        let document = Document::load_from_bytes(
411
            br#"<?xml version="1.0" encoding="UTF-8"?>
412
<svg xmlns="http://www.w3.org/2000/svg">
413
  <filter id="filter">
414
    <feComponentTransfer id="component_transfer">
415
      <!-- no feFuncR so it should get the defaults -->
416

            
417
      <feFuncG type="table" tableValues="0.0 1.0 2.0"/>
418

            
419
      <feFuncB type="table"/>
420
      <!-- duplicate this to test that last-one-wins -->
421
      <feFuncB type="discrete" tableValues="0.0, 1.0" slope="1.0" intercept="2.0" amplitude="3.0" exponent="4.0" offset="5.0"/>
422

            
423
      <!-- no feFuncA so it should get the defaults -->
424
    </feComponentTransfer>
425
  </filter>
426
</svg>
427
"#
428
        );
429

            
430
1
        let component_transfer = document.lookup_internal_node("component_transfer").unwrap();
431
1
        let functions = get_functions(&component_transfer).unwrap();
432

            
433
2
        assert_eq!(
434
            functions,
435
1
            Functions {
436
1
                r: FeFuncR::default(),
437

            
438
1
                g: FeFuncG(FeFuncCommon {
439
1
                    function_type: FunctionType::Table,
440
1
                    table_values: vec![0.0, 1.0, 2.0],
441
1
                    ..FeFuncCommon::default()
442
                }),
443

            
444
1
                b: FeFuncB(FeFuncCommon {
445
1
                    function_type: FunctionType::Discrete,
446
1
                    table_values: vec![0.0, 1.0],
447
                    slope: 1.0,
448
                    intercept: 2.0,
449
                    amplitude: 3.0,
450
                    exponent: 4.0,
451
                    offset: 5.0,
452
1
                    ..FeFuncCommon::default()
453
                }),
454

            
455
1
                a: FeFuncA::default(),
456
            }
457
        );
458
2
    }
459
}