swf_parser/complete/
gradient.rs

1use crate::streaming::basic_data_types::{parse_s_rgb8, parse_straight_s_rgba8};
2use nom::number::complete::le_u8 as parse_u8;
3use nom::IResult as NomResult;
4use swf_types as swf;
5
6#[allow(unused_variables)]
7pub fn parse_color_stop(input: &[u8], with_alpha: bool) -> NomResult<&[u8], swf::ColorStop> {
8  use nom::combinator::map;
9
10  let (input, ratio) = parse_u8(input)?;
11  let (input, color) = if with_alpha {
12    parse_straight_s_rgba8(input)?
13  } else {
14    map(parse_s_rgb8, |c| swf::StraightSRgba8 {
15      r: c.r,
16      g: c.g,
17      b: c.b,
18      a: 255,
19    })(input)?
20  };
21
22  Ok((input, swf::ColorStop { ratio, color }))
23}
24
25pub fn parse_gradient(input: &[u8], with_alpha: bool) -> NomResult<&[u8], swf::Gradient> {
26  let (input, flags) = parse_u8(input)?;
27  let spread_code = flags >> 6;
28  let color_space_code = (flags & ((1 << 6) - 1)) >> 4;
29  let color_count = flags & ((1 << 4) - 1);
30
31  let spread = match spread_code {
32    0 => swf::GradientSpread::Pad,
33    1 => swf::GradientSpread::Reflect,
34    2 => swf::GradientSpread::Repeat,
35    _ => return Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Switch))),
36  };
37
38  let color_space = match color_space_code {
39    0 => swf::ColorSpace::SRgb,
40    1 => swf::ColorSpace::LinearRgb,
41    _ => return Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Switch))),
42  };
43
44  let (input, colors) = nom::multi::count(|i| parse_color_stop(i, with_alpha), color_count as usize)(input)?;
45
46  Ok((
47    input,
48    swf::Gradient {
49      spread,
50      color_space,
51      colors,
52    },
53  ))
54}
55
56#[allow(unused_variables)]
57pub fn parse_morph_color_stop(input: &[u8], with_alpha: bool) -> NomResult<&[u8], swf::MorphColorStop> {
58  let (input, start) = parse_color_stop(input, with_alpha)?;
59  let (input, end) = parse_color_stop(input, with_alpha)?;
60
61  Ok((
62    input,
63    swf::MorphColorStop {
64      ratio: start.ratio,
65      color: start.color,
66      morph_ratio: end.ratio,
67      morph_color: end.color,
68    },
69  ))
70}
71
72#[allow(unused_variables)]
73pub fn parse_morph_gradient(input: &[u8], with_alpha: bool) -> NomResult<&[u8], swf::MorphGradient> {
74  let (input, flags) = parse_u8(input)?;
75  let spread_code = flags >> 6;
76  let color_space_code = (flags & ((1 << 6) - 1)) >> 4;
77  let color_count = flags & ((1 << 4) - 1);
78
79  let spread = match spread_code {
80    0 => swf::GradientSpread::Pad,
81    1 => swf::GradientSpread::Reflect,
82    2 => swf::GradientSpread::Repeat,
83    _ => return Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Switch))),
84  };
85
86  let color_space = match color_space_code {
87    0 => swf::ColorSpace::SRgb,
88    1 => swf::ColorSpace::LinearRgb,
89    _ => return Err(nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Switch))),
90  };
91
92  let (input, colors) = nom::multi::count(|i| parse_morph_color_stop(i, with_alpha), color_count as usize)(input)?;
93
94  Ok((
95    input,
96    swf::MorphGradient {
97      spread,
98      color_space,
99      colors,
100    },
101  ))
102}