swf_emitter/
gradient.rs

1use std::convert::TryFrom;
2use std::io;
3
4use swf_types as ast;
5
6use crate::basic_data_types::{emit_s_rgb8, emit_straight_s_rgba8};
7use crate::primitives::emit_u8;
8
9fn gradient_spread_to_code(value: ast::GradientSpread) -> u8 {
10  match value {
11    ast::GradientSpread::Pad => 0,
12    ast::GradientSpread::Reflect => 1,
13    ast::GradientSpread::Repeat => 2,
14  }
15}
16
17fn color_space_to_code(value: ast::ColorSpace) -> u8 {
18  match value {
19    ast::ColorSpace::LinearRgb => 1,
20    ast::ColorSpace::SRgb => 0,
21  }
22}
23
24pub(crate) fn emit_gradient<W: io::Write + ?Sized>(
25  writer: &mut W,
26  value: &ast::Gradient,
27  with_alpha: bool,
28) -> io::Result<()> {
29  assert!(value.colors.len() <= 0x0f);
30  #[allow(clippy::identity_op)]
31  let flags: u8 = 0
32    | ((u8::try_from(value.colors.len()).unwrap() & 0x0f) << 0)
33    | ((gradient_spread_to_code(value.spread) & 0b11) << 4)
34    | ((color_space_to_code(value.color_space) & 0b11) << 6);
35  emit_u8(writer, flags)?;
36
37  for color_stop in &value.colors {
38    emit_color_stop(writer, color_stop, with_alpha)?;
39  }
40
41  Ok(())
42}
43
44pub(crate) fn emit_color_stop<W: io::Write + ?Sized>(
45  writer: &mut W,
46  value: &ast::ColorStop,
47  with_alpha: bool,
48) -> io::Result<()> {
49  emit_u8(writer, value.ratio)?;
50  if with_alpha {
51    emit_straight_s_rgba8(writer, value.color)
52  } else {
53    assert!(value.color.a == u8::max_value());
54    emit_s_rgb8(
55      writer,
56      ast::SRgb8 {
57        r: value.color.r,
58        g: value.color.g,
59        b: value.color.b,
60      },
61    )
62  }
63}
64
65pub(crate) fn emit_morph_gradient<W: io::Write + ?Sized>(writer: &mut W, value: &ast::MorphGradient) -> io::Result<()> {
66  assert!(value.colors.len() <= 0x0f);
67  #[allow(clippy::identity_op)]
68  let flags: u8 = 0
69    | ((u8::try_from(value.colors.len()).unwrap() & 0x0f) << 0)
70    | ((gradient_spread_to_code(value.spread) & 0b11) << 4)
71    | ((color_space_to_code(value.color_space) & 0b11) << 6);
72  emit_u8(writer, flags)?;
73
74  for color_stop in &value.colors {
75    emit_morph_color_stop(writer, color_stop)?;
76  }
77
78  Ok(())
79}
80
81pub(crate) fn emit_morph_color_stop<W: io::Write + ?Sized>(
82  writer: &mut W,
83  value: &ast::MorphColorStop,
84) -> io::Result<()> {
85  emit_color_stop(
86    writer,
87    &ast::ColorStop {
88      ratio: value.ratio,
89      color: value.color,
90    },
91    true,
92  )?;
93  emit_color_stop(
94    writer,
95    &ast::ColorStop {
96      ratio: value.morph_ratio,
97      color: value.morph_color,
98    },
99    true,
100  )
101}