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}