1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
use crate::streaming::basic_data_types::{parse_s_rgb8, parse_straight_s_rgba8};
use nom::number::complete::le_u8 as parse_u8;
use nom::IResult as NomResult;
use swf_types as swf;

#[allow(unused_variables)]
pub fn parse_color_stop(input: &[u8], with_alpha: bool) -> NomResult<&[u8], swf::ColorStop> {
  use nom::combinator::map;

  let (input, ratio) = parse_u8(input)?;
  let (input, color) = if with_alpha {
    parse_straight_s_rgba8(input)?
  } else {
    map(parse_s_rgb8, |c| swf::StraightSRgba8 {
      r: c.r,
      g: c.g,
      b: c.b,
      a: 255,
    })(input)?
  };

  Ok((input, swf::ColorStop { ratio, color }))
}

pub fn parse_gradient(input: &[u8], with_alpha: bool) -> NomResult<&[u8], swf::Gradient> {
  let (input, flags) = parse_u8(input)?;
  let spread_code = flags >> 6;
  let color_space_code = (flags & ((1 << 6) - 1)) >> 4;
  let color_count = flags & ((1 << 4) - 1);

  let spread = match spread_code {
    0 => swf::GradientSpread::Pad,
    1 => swf::GradientSpread::Reflect,
    2 => swf::GradientSpread::Repeat,
    _ => return Err(nom::Err::Error((input, nom::error::ErrorKind::Switch))),
  };

  let color_space = match color_space_code {
    0 => swf::ColorSpace::SRgb,
    1 => swf::ColorSpace::LinearRgb,
    _ => return Err(nom::Err::Error((input, nom::error::ErrorKind::Switch))),
  };

  let (input, colors) = nom::multi::count(|i| parse_color_stop(i, with_alpha), color_count as usize)(input)?;

  Ok((
    input,
    swf::Gradient {
      spread,
      color_space,
      colors,
    },
  ))
}

#[allow(unused_variables)]
pub fn parse_morph_color_stop(input: &[u8], with_alpha: bool) -> NomResult<&[u8], swf::MorphColorStop> {
  let (input, start) = parse_color_stop(input, with_alpha)?;
  let (input, end) = parse_color_stop(input, with_alpha)?;

  Ok((
    input,
    swf::MorphColorStop {
      ratio: start.ratio,
      color: start.color,
      morph_ratio: end.ratio,
      morph_color: end.color,
    },
  ))
}

#[allow(unused_variables)]
pub fn parse_morph_gradient(input: &[u8], with_alpha: bool) -> NomResult<&[u8], swf::MorphGradient> {
  let (input, flags) = parse_u8(input)?;
  let spread_code = flags >> 6;
  let color_space_code = (flags & ((1 << 6) - 1)) >> 4;
  let color_count = flags & ((1 << 4) - 1);

  let spread = match spread_code {
    0 => swf::GradientSpread::Pad,
    1 => swf::GradientSpread::Reflect,
    2 => swf::GradientSpread::Repeat,
    _ => return Err(nom::Err::Error((input, nom::error::ErrorKind::Switch))),
  };

  let color_space = match color_space_code {
    0 => swf::ColorSpace::SRgb,
    1 => swf::ColorSpace::LinearRgb,
    _ => return Err(nom::Err::Error((input, nom::error::ErrorKind::Switch))),
  };

  let (input, colors) = nom::multi::count(|i| parse_morph_color_stop(i, with_alpha), color_count as usize)(input)?;

  Ok((
    input,
    swf::MorphGradient {
      spread,
      color_space,
      colors,
    },
  ))
}