swf: Clean up LineStyle
* Remove LineStyle::color, instead using fill_style with FillStyle::Color to indicate solid color. * Store `flags` in the struct instead of separate bools/values. * Add getters/setters for ease of use. * Add builder-style methods for setting LineStyle properties. * Fix misnamed ALLOW_CLOSE flag to NO_CLOSE.
This commit is contained in:
parent
99d8a5bff3
commit
146b8adc68
|
@ -291,21 +291,20 @@ fn line_style<'gc>(
|
|||
Some(v) if v == b"bevel" => LineJoinStyle::Bevel,
|
||||
_ => LineJoinStyle::Round,
|
||||
};
|
||||
let line_style = LineStyle::new()
|
||||
.with_width(width)
|
||||
.with_color(color)
|
||||
.with_start_cap(cap_style)
|
||||
.with_end_cap(cap_style)
|
||||
.with_join_style(join_style)
|
||||
.with_allow_scale_x(allow_scale_x)
|
||||
.with_allow_scale_y(allow_scale_y)
|
||||
.with_is_pixel_hinted(is_pixel_hinted)
|
||||
.with_allow_close(false);
|
||||
movie_clip
|
||||
.as_drawing(activation.context.gc_context)
|
||||
.unwrap()
|
||||
.set_line_style(Some(LineStyle {
|
||||
width,
|
||||
color,
|
||||
start_cap: cap_style,
|
||||
end_cap: cap_style,
|
||||
join_style,
|
||||
fill_style: None,
|
||||
allow_scale_x,
|
||||
allow_scale_y,
|
||||
is_pixel_hinted,
|
||||
allow_close: false,
|
||||
}));
|
||||
.set_line_style(Some(line_style));
|
||||
} else {
|
||||
movie_clip
|
||||
.as_drawing(activation.context.gc_context)
|
||||
|
|
|
@ -248,18 +248,16 @@ fn line_style<'gc>(
|
|||
let join_style = joints_to_join_style(activation, joints, miter_limit)?;
|
||||
let (allow_scale_x, allow_scale_y) = scale_mode_to_allow_scale_bits(&scale_mode)?;
|
||||
|
||||
let line_style = LineStyle {
|
||||
width,
|
||||
color,
|
||||
start_cap: caps,
|
||||
end_cap: caps,
|
||||
join_style,
|
||||
fill_style: None,
|
||||
allow_scale_x,
|
||||
allow_scale_y,
|
||||
is_pixel_hinted,
|
||||
allow_close: true,
|
||||
};
|
||||
let line_style = LineStyle::new()
|
||||
.with_width(width)
|
||||
.with_color(color)
|
||||
.with_start_cap(caps)
|
||||
.with_end_cap(caps)
|
||||
.with_join_style(join_style)
|
||||
.with_allow_scale_x(allow_scale_x)
|
||||
.with_allow_scale_y(allow_scale_y)
|
||||
.with_is_pixel_hinted(is_pixel_hinted)
|
||||
.with_allow_close(false);
|
||||
|
||||
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
|
||||
draw.set_line_style(Some(line_style));
|
||||
|
|
|
@ -705,10 +705,11 @@ impl<'gc> EditText<'gc> {
|
|||
let background_color = write.background_color;
|
||||
|
||||
if write.has_border {
|
||||
write.drawing.set_line_style(Some(swf::LineStyle::new_v1(
|
||||
Twips::new(1),
|
||||
swf::Color::from_rgb(border_color, 0xFF),
|
||||
)));
|
||||
write.drawing.set_line_style(Some(
|
||||
swf::LineStyle::new()
|
||||
.with_width(Twips::new(1))
|
||||
.with_color(swf::Color::from_rgb(border_color, 0xFF)),
|
||||
));
|
||||
} else {
|
||||
write.drawing.set_line_style(None);
|
||||
}
|
||||
|
|
|
@ -204,17 +204,11 @@ impl MorphShapeStatic {
|
|||
.line_styles
|
||||
.iter()
|
||||
.zip(self.end.line_styles.iter())
|
||||
.map(|(start, end)| LineStyle {
|
||||
width: lerp_twips(start.width, end.width, a, b),
|
||||
color: lerp_color(&start.color, &end.color, a, b),
|
||||
start_cap: start.start_cap,
|
||||
end_cap: start.end_cap,
|
||||
join_style: start.join_style,
|
||||
fill_style: None,
|
||||
allow_scale_x: start.allow_scale_x,
|
||||
allow_scale_y: start.allow_scale_y,
|
||||
is_pixel_hinted: start.is_pixel_hinted,
|
||||
allow_close: start.allow_close,
|
||||
.map(|(start, end)| {
|
||||
start
|
||||
.clone()
|
||||
.with_width(lerp_twips(start.width(), end.width(), a, b))
|
||||
.with_fill_style(lerp_fill(start.fill_style(), end.fill_style(), a, b))
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -177,7 +177,7 @@ impl Drawing {
|
|||
// Add command to current line.
|
||||
let stroke_width = if let Some(line) = &mut self.current_line {
|
||||
line.commands.push(command.clone());
|
||||
line.style.width
|
||||
line.style.width()
|
||||
} else {
|
||||
Twips::ZERO
|
||||
};
|
||||
|
@ -310,7 +310,7 @@ impl Drawing {
|
|||
DrawingPath::Line(line) => {
|
||||
if shape_utils::draw_command_stroke_hit_test(
|
||||
&line.commands,
|
||||
line.style.width,
|
||||
line.style.width(),
|
||||
point,
|
||||
local_matrix,
|
||||
) {
|
||||
|
@ -330,7 +330,7 @@ impl Drawing {
|
|||
for line in &self.pending_lines {
|
||||
if shape_utils::draw_command_stroke_hit_test(
|
||||
&line.commands,
|
||||
line.style.width,
|
||||
line.style.width(),
|
||||
point,
|
||||
local_matrix,
|
||||
) {
|
||||
|
@ -341,7 +341,7 @@ impl Drawing {
|
|||
if let Some(line) = &self.current_line {
|
||||
if shape_utils::draw_command_stroke_hit_test(
|
||||
&line.commands,
|
||||
line.style.width,
|
||||
line.style.width(),
|
||||
point,
|
||||
local_matrix,
|
||||
) {
|
||||
|
@ -362,7 +362,7 @@ impl Drawing {
|
|||
y: self.fill_start.1,
|
||||
},
|
||||
],
|
||||
line.style.width,
|
||||
line.style.width(),
|
||||
point,
|
||||
local_matrix,
|
||||
)
|
||||
|
|
|
@ -145,10 +145,11 @@ impl<'a, 'gc> LayoutContext<'a, 'gc> {
|
|||
let mut line_drawing = Drawing::new();
|
||||
let mut has_underline: bool = false;
|
||||
|
||||
line_drawing.set_line_style(Some(swf::LineStyle::new_v1(
|
||||
Twips::new(1),
|
||||
swf::Color::from_rgb(0, 255),
|
||||
)));
|
||||
line_drawing.set_line_style(Some(
|
||||
swf::LineStyle::new()
|
||||
.with_width(Twips::new(1))
|
||||
.with_color(swf::Color::from_rgb(0, 255)),
|
||||
));
|
||||
|
||||
if let Some(linelist) = self.boxes.get(self.current_line..) {
|
||||
for linebox in linelist {
|
||||
|
|
|
@ -761,7 +761,7 @@ pub fn shape_hit_test(
|
|||
stroke_width = if i > 0 {
|
||||
// Flash renders strokes with a 1px minimum width.
|
||||
if let Some(line_style) = line_styles.get(i as usize - 1) {
|
||||
let width = line_style.width.get() as f64;
|
||||
let width = line_style.width().get() as f64;
|
||||
let scaled_width = 0.5 * width.max(min_width);
|
||||
Some((scaled_width, scaled_width * scaled_width))
|
||||
} else {
|
||||
|
|
|
@ -1219,20 +1219,22 @@ fn swf_shape_to_svg(
|
|||
// strokes end up rendering very faintly if we use the actual width of 1 twip.
|
||||
// Therefore, we clamp the stroke width to 1 pixel (20 twips). This won't be 100% accurate
|
||||
// if the shape is scaled, but it looks much closer to the Flash Player.
|
||||
let stroke_width = std::cmp::max(style.width.get(), 20);
|
||||
let stroke_width = std::cmp::max(style.width().get(), 20);
|
||||
let color = if let FillStyle::Color(color) = style.fill_style() {
|
||||
color.clone()
|
||||
} else {
|
||||
Color::from_rgba(0)
|
||||
};
|
||||
let mut svg_path = SvgPath::new()
|
||||
.set("fill", "none")
|
||||
.set(
|
||||
"stroke",
|
||||
format!(
|
||||
"rgba({},{},{},{})",
|
||||
style.color.r, style.color.g, style.color.b, style.color.a
|
||||
),
|
||||
format!("rgba({},{},{},{})", color.r, color.g, color.b, color.a),
|
||||
)
|
||||
.set("stroke-width", stroke_width)
|
||||
.set(
|
||||
"stroke-linecap",
|
||||
match style.start_cap {
|
||||
match style.start_cap() {
|
||||
LineCapStyle::Round => "round",
|
||||
LineCapStyle::Square => "square",
|
||||
LineCapStyle::None => "butt",
|
||||
|
@ -1240,14 +1242,14 @@ fn swf_shape_to_svg(
|
|||
)
|
||||
.set(
|
||||
"stroke-linejoin",
|
||||
match style.join_style {
|
||||
match style.join_style() {
|
||||
LineJoinStyle::Round => "round",
|
||||
LineJoinStyle::Bevel => "bevel",
|
||||
LineJoinStyle::Miter(_) => "miter",
|
||||
},
|
||||
);
|
||||
|
||||
if let LineJoinStyle::Miter(miter_limit) = style.join_style {
|
||||
if let LineJoinStyle::Miter(miter_limit) = style.join_style() {
|
||||
svg_path = svg_path.set("stroke-miterlimit", miter_limit.to_f32());
|
||||
}
|
||||
|
||||
|
@ -1480,23 +1482,25 @@ fn swf_shape_to_canvas_commands(
|
|||
// strokes end up rendering very faintly if we use the actual width of 1 twip.
|
||||
// Therefore, we clamp the stroke width to 1 pixel (20 twips). This won't be 100% accurate
|
||||
// if the shape is scaled, but it looks much closer to the Flash Player.
|
||||
let line_width = std::cmp::max(style.width.get(), 20);
|
||||
let line_width = std::cmp::max(style.width().get(), 20);
|
||||
let color = if let FillStyle::Color(color) = style.fill_style() {
|
||||
color.clone()
|
||||
} else {
|
||||
Color::from_rgba(0)
|
||||
};
|
||||
let stroke_style = CanvasColor(
|
||||
format!(
|
||||
"rgba({},{},{},{})",
|
||||
style.color.r, style.color.g, style.color.b, style.color.a
|
||||
),
|
||||
style.color.r,
|
||||
style.color.g,
|
||||
style.color.b,
|
||||
style.color.a,
|
||||
format!("rgba({},{},{},{})", color.r, color.g, color.b, color.a),
|
||||
color.r,
|
||||
color.g,
|
||||
color.b,
|
||||
color.a,
|
||||
);
|
||||
let line_cap = match style.start_cap {
|
||||
let line_cap = match style.start_cap() {
|
||||
LineCapStyle::Round => "round",
|
||||
LineCapStyle::Square => "square",
|
||||
LineCapStyle::None => "butt",
|
||||
};
|
||||
let (line_join, miter_limit) = match style.join_style {
|
||||
let (line_join, miter_limit) = match style.join_style() {
|
||||
LineJoinStyle::Round => ("round", 999_999.0),
|
||||
LineJoinStyle::Bevel => ("bevel", 999_999.0),
|
||||
LineJoinStyle::Miter(ml) => ("miter", ml.to_f32()),
|
||||
|
|
|
@ -205,30 +205,31 @@ impl ShapeTessellator {
|
|||
commands,
|
||||
is_closed,
|
||||
} => {
|
||||
let mut buffers_builder = BuffersBuilder::new(
|
||||
&mut lyon_mesh,
|
||||
RuffleVertexCtor {
|
||||
color: style.color.clone(),
|
||||
},
|
||||
);
|
||||
let color = if let swf::FillStyle::Color(color) = &style.fill_style() {
|
||||
color.clone()
|
||||
} else {
|
||||
swf::Color::from_rgba(0)
|
||||
};
|
||||
let mut buffers_builder =
|
||||
BuffersBuilder::new(&mut lyon_mesh, RuffleVertexCtor { color });
|
||||
|
||||
// TODO(Herschel): 0 width indicates "hairline".
|
||||
let width = (style.width.to_pixels() as f32).max(1.0);
|
||||
let width = (style.width().to_pixels() as f32).max(1.0);
|
||||
|
||||
let mut options = StrokeOptions::default()
|
||||
.with_line_width(width)
|
||||
.with_start_cap(match style.start_cap {
|
||||
.with_start_cap(match style.start_cap() {
|
||||
swf::LineCapStyle::None => tessellation::LineCap::Butt,
|
||||
swf::LineCapStyle::Round => tessellation::LineCap::Round,
|
||||
swf::LineCapStyle::Square => tessellation::LineCap::Square,
|
||||
})
|
||||
.with_end_cap(match style.end_cap {
|
||||
.with_end_cap(match style.end_cap() {
|
||||
swf::LineCapStyle::None => tessellation::LineCap::Butt,
|
||||
swf::LineCapStyle::Round => tessellation::LineCap::Round,
|
||||
swf::LineCapStyle::Square => tessellation::LineCap::Square,
|
||||
});
|
||||
|
||||
let line_join = match style.join_style {
|
||||
let line_join = match style.join_style() {
|
||||
swf::LineJoinStyle::Round => tessellation::LineJoin::Round,
|
||||
swf::LineJoinStyle::Bevel => tessellation::LineJoin::Bevel,
|
||||
swf::LineJoinStyle::Miter(limit) => {
|
||||
|
|
164
swf/src/read.rs
164
swf/src/read.rs
|
@ -1354,78 +1354,53 @@ impl<'a> Reader<'a> {
|
|||
let end_color = self.read_rgba()?;
|
||||
|
||||
Ok((
|
||||
LineStyle::new_v1(start_width, start_color),
|
||||
LineStyle::new_v1(end_width, end_color),
|
||||
LineStyle::new()
|
||||
.with_width(start_width)
|
||||
.with_color(start_color),
|
||||
LineStyle::new().with_width(end_width).with_color(end_color),
|
||||
))
|
||||
} else {
|
||||
// MorphLineStyle2 in DefineMorphShape2.
|
||||
let flags = LineStyleFlag::from_bits_truncate(self.read_u16()?);
|
||||
let is_pixel_hinted = flags.contains(LineStyleFlag::PIXEL_HINTING);
|
||||
let allow_scale_y = !flags.contains(LineStyleFlag::NO_V_SCALE);
|
||||
let allow_scale_x = !flags.contains(LineStyleFlag::NO_H_SCALE);
|
||||
let has_fill = flags.contains(LineStyleFlag::HAS_FILL);
|
||||
let join_style = match flags & LineStyleFlag::JOIN_STYLE {
|
||||
LineStyleFlag::ROUND => LineJoinStyle::Round,
|
||||
LineStyleFlag::BEVEL => LineJoinStyle::Bevel,
|
||||
LineStyleFlag::MITER => LineJoinStyle::Miter(self.read_fixed8()?),
|
||||
_ => return Err(Error::invalid_data("Invalid line cap type.")),
|
||||
let mut flags = LineStyleFlag::from_bits_truncate(self.read_u16()?);
|
||||
// Verify valid cap and join styles.
|
||||
if flags.contains(LineStyleFlag::JOIN_STYLE) {
|
||||
log::warn!("Invalid line join style");
|
||||
flags -= LineStyleFlag::JOIN_STYLE;
|
||||
}
|
||||
if flags.contains(LineStyleFlag::START_CAP_STYLE) {
|
||||
log::warn!("Invalid line start cap style");
|
||||
flags -= LineStyleFlag::START_CAP_STYLE;
|
||||
}
|
||||
if flags.contains(LineStyleFlag::END_CAP_STYLE) {
|
||||
log::warn!("Invalid line end cap style");
|
||||
flags -= LineStyleFlag::END_CAP_STYLE;
|
||||
}
|
||||
let miter_limit = if flags & LineStyleFlag::JOIN_STYLE == LineStyleFlag::MITER {
|
||||
self.read_fixed8()?
|
||||
} else {
|
||||
Fixed8::ZERO
|
||||
};
|
||||
let start_cap =
|
||||
LineCapStyle::from_u8(((flags & LineStyleFlag::START_CAP_STYLE).bits() >> 6) as u8)
|
||||
.ok_or_else(|| Error::invalid_data("Invalid line cap type."))?;
|
||||
let end_cap =
|
||||
LineCapStyle::from_u8(((flags & LineStyleFlag::END_CAP_STYLE).bits() >> 8) as u8)
|
||||
.ok_or_else(|| Error::invalid_data("Invalid line cap type."))?;
|
||||
let allow_close = !flags.contains(LineStyleFlag::ALLOW_CLOSE);
|
||||
|
||||
let (start_color, end_color) = if !has_fill {
|
||||
(self.read_rgba()?, self.read_rgba()?)
|
||||
let (start_fill_style, end_fill_style) = if flags.contains(LineStyleFlag::HAS_FILL) {
|
||||
let (start, end) = self.read_morph_fill_style()?;
|
||||
(start, end)
|
||||
} else {
|
||||
(
|
||||
Color {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0,
|
||||
},
|
||||
Color {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0,
|
||||
},
|
||||
FillStyle::Color(self.read_rgba()?),
|
||||
FillStyle::Color(self.read_rgba()?),
|
||||
)
|
||||
};
|
||||
let (start_fill_style, end_fill_style) = if has_fill {
|
||||
let (start, end) = self.read_morph_fill_style()?;
|
||||
(Some(start), Some(end))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
Ok((
|
||||
LineStyle {
|
||||
width: start_width,
|
||||
color: start_color,
|
||||
start_cap,
|
||||
end_cap,
|
||||
join_style,
|
||||
allow_scale_x,
|
||||
allow_scale_y,
|
||||
is_pixel_hinted,
|
||||
allow_close,
|
||||
fill_style: start_fill_style,
|
||||
flags,
|
||||
miter_limit,
|
||||
},
|
||||
LineStyle {
|
||||
width: end_width,
|
||||
color: end_color,
|
||||
start_cap,
|
||||
end_cap,
|
||||
join_style,
|
||||
allow_scale_x,
|
||||
allow_scale_y,
|
||||
is_pixel_hinted,
|
||||
allow_close,
|
||||
fill_style: end_fill_style,
|
||||
flags,
|
||||
miter_limit,
|
||||
},
|
||||
))
|
||||
}
|
||||
|
@ -1682,54 +1657,39 @@ impl<'a> Reader<'a> {
|
|||
} else {
|
||||
self.read_rgb()?
|
||||
};
|
||||
Ok(LineStyle::new_v1(width, color))
|
||||
Ok(LineStyle::new().with_width(width).with_color(color))
|
||||
} else {
|
||||
// LineStyle2 in DefineShape4
|
||||
let flags = LineStyleFlag::from_bits_truncate(self.read_u16()?);
|
||||
let is_pixel_hinted = flags.contains(LineStyleFlag::PIXEL_HINTING);
|
||||
let allow_scale_y = !flags.contains(LineStyleFlag::NO_V_SCALE);
|
||||
let allow_scale_x = !flags.contains(LineStyleFlag::NO_H_SCALE);
|
||||
let has_fill = flags.contains(LineStyleFlag::HAS_FILL);
|
||||
let join_style = match flags & LineStyleFlag::JOIN_STYLE {
|
||||
LineStyleFlag::ROUND => LineJoinStyle::Round,
|
||||
LineStyleFlag::BEVEL => LineJoinStyle::Bevel,
|
||||
LineStyleFlag::MITER => LineJoinStyle::Miter(self.read_fixed8()?),
|
||||
_ => return Err(Error::invalid_data("Invalid line cap type.")),
|
||||
};
|
||||
let start_cap =
|
||||
LineCapStyle::from_u8(((flags & LineStyleFlag::START_CAP_STYLE).bits() >> 6) as u8)
|
||||
.ok_or_else(|| Error::invalid_data("Invalid line cap type."))?;
|
||||
let end_cap =
|
||||
LineCapStyle::from_u8(((flags & LineStyleFlag::END_CAP_STYLE).bits() >> 8) as u8)
|
||||
.ok_or_else(|| Error::invalid_data("Invalid line cap type."))?;
|
||||
let allow_close = !flags.contains(LineStyleFlag::ALLOW_CLOSE);
|
||||
|
||||
let color = if !has_fill {
|
||||
self.read_rgba()?
|
||||
} else {
|
||||
Color {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0,
|
||||
let mut flags = LineStyleFlag::from_bits_truncate(self.read_u16()?);
|
||||
// Verify valid cap and join styles.
|
||||
if flags.contains(LineStyleFlag::JOIN_STYLE) {
|
||||
log::warn!("Invalid line join style");
|
||||
flags -= LineStyleFlag::JOIN_STYLE;
|
||||
}
|
||||
};
|
||||
let fill_style = if has_fill {
|
||||
Some(self.read_fill_style(shape_version)?)
|
||||
if flags.contains(LineStyleFlag::START_CAP_STYLE) {
|
||||
log::warn!("Invalid line start cap style");
|
||||
flags -= LineStyleFlag::START_CAP_STYLE;
|
||||
}
|
||||
if flags.contains(LineStyleFlag::END_CAP_STYLE) {
|
||||
log::warn!("Invalid line end cap style");
|
||||
flags -= LineStyleFlag::END_CAP_STYLE;
|
||||
}
|
||||
let miter_limit = if flags & LineStyleFlag::JOIN_STYLE == LineStyleFlag::MITER {
|
||||
self.read_fixed8()?
|
||||
} else {
|
||||
None
|
||||
Fixed8::ZERO
|
||||
};
|
||||
|
||||
let fill_style = if flags.contains(LineStyleFlag::HAS_FILL) {
|
||||
self.read_fill_style(shape_version)?
|
||||
} else {
|
||||
FillStyle::Color(self.read_rgba()?)
|
||||
};
|
||||
Ok(LineStyle {
|
||||
width,
|
||||
color,
|
||||
start_cap,
|
||||
end_cap,
|
||||
join_style,
|
||||
fill_style,
|
||||
allow_scale_x,
|
||||
allow_scale_y,
|
||||
is_pixel_hinted,
|
||||
allow_close,
|
||||
flags,
|
||||
miter_limit,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -2995,15 +2955,9 @@ pub mod tests {
|
|||
#[test]
|
||||
fn read_line_style() {
|
||||
// DefineShape1 and 2 read RGB colors.
|
||||
let line_style = LineStyle::new_v1(
|
||||
Twips::from_pixels(0.0),
|
||||
Color {
|
||||
r: 255,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 255,
|
||||
},
|
||||
);
|
||||
let line_style = LineStyle::new()
|
||||
.with_width(Twips::from_pixels(0.0))
|
||||
.with_color(Color::from_rgba(0xffff0000));
|
||||
assert_eq!(
|
||||
reader(&[0, 0, 255, 0, 0]).read_line_style(2).unwrap(),
|
||||
line_style
|
||||
|
|
|
@ -737,15 +737,9 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
],
|
||||
})],
|
||||
line_styles: vec![LineStyle::new_v1(
|
||||
Twips::from_pixels(10.0),
|
||||
Color {
|
||||
r: 0,
|
||||
g: 255,
|
||||
b: 0,
|
||||
a: 255,
|
||||
},
|
||||
)],
|
||||
line_styles: vec![LineStyle::new()
|
||||
.with_width(Twips::from_pixels(10.0))
|
||||
.with_color(Color::from_rgba(0xff00ff00))],
|
||||
shape: vec![
|
||||
ShapeRecord::StyleChange(Box::new(StyleChangeData {
|
||||
move_to: Some((Twips::from_pixels(20.0), Twips::from_pixels(20.0))),
|
||||
|
@ -840,15 +834,9 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
],
|
||||
})],
|
||||
line_styles: vec![LineStyle::new_v1(
|
||||
Twips::from_pixels(2.0),
|
||||
Color {
|
||||
r: 255,
|
||||
g: 255,
|
||||
b: 0,
|
||||
a: 255,
|
||||
},
|
||||
)],
|
||||
line_styles: vec![LineStyle::new()
|
||||
.with_width(Twips::from_pixels(2.0))
|
||||
.with_color(Color::from_rgba(0xffffff00))],
|
||||
shape: vec![
|
||||
ShapeRecord::StyleChange(Box::new(StyleChangeData {
|
||||
move_to: Some((Twips::from_pixels(20.0), Twips::from_pixels(60.0))),
|
||||
|
@ -969,23 +957,9 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
focal_point: Fixed8::from_f64(0.97265625),
|
||||
}],
|
||||
line_styles: vec![LineStyle {
|
||||
width: Twips::from_pixels(10.0),
|
||||
color: Color {
|
||||
r: 0,
|
||||
g: 255,
|
||||
b: 0,
|
||||
a: 255,
|
||||
},
|
||||
start_cap: LineCapStyle::Round,
|
||||
end_cap: LineCapStyle::Round,
|
||||
join_style: LineJoinStyle::Round,
|
||||
fill_style: None,
|
||||
allow_scale_x: true,
|
||||
allow_scale_y: true,
|
||||
is_pixel_hinted: false,
|
||||
allow_close: true,
|
||||
}],
|
||||
line_styles: vec![LineStyle::new()
|
||||
.with_width(Twips::from_pixels(10.0))
|
||||
.with_color(Color::from_rgba(0xff00ff00))],
|
||||
shape: vec![
|
||||
ShapeRecord::StyleChange(Box::new(StyleChangeData {
|
||||
move_to: Some((Twips::from_pixels(20.0), Twips::from_pixels(20.0))),
|
||||
|
@ -1092,23 +1066,9 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
focal_point: Fixed8::from_f64(-0.9921875),
|
||||
}],
|
||||
line_styles: vec![LineStyle {
|
||||
width: Twips::from_pixels(2.0),
|
||||
color: Color {
|
||||
r: 255,
|
||||
g: 255,
|
||||
b: 0,
|
||||
a: 255,
|
||||
},
|
||||
start_cap: LineCapStyle::Round,
|
||||
end_cap: LineCapStyle::Round,
|
||||
join_style: LineJoinStyle::Round,
|
||||
fill_style: None,
|
||||
allow_scale_x: true,
|
||||
allow_scale_y: true,
|
||||
is_pixel_hinted: false,
|
||||
allow_close: true,
|
||||
}],
|
||||
line_styles: vec![LineStyle::new()
|
||||
.with_width(Twips::from_pixels(2.0))
|
||||
.with_color(Color::from_rgba(0xffffff00))],
|
||||
shape: vec![
|
||||
ShapeRecord::StyleChange(Box::new(StyleChangeData {
|
||||
move_to: Some((Twips::from_pixels(26.0), Twips::from_pixels(147.35))),
|
||||
|
@ -1217,23 +1177,9 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
],
|
||||
})],
|
||||
line_styles: vec![LineStyle {
|
||||
width: Twips::from_pixels(0.0),
|
||||
color: Color {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0,
|
||||
},
|
||||
start_cap: LineCapStyle::Round,
|
||||
end_cap: LineCapStyle::Round,
|
||||
join_style: LineJoinStyle::Round,
|
||||
fill_style: None,
|
||||
allow_scale_x: true,
|
||||
allow_scale_y: true,
|
||||
is_pixel_hinted: false,
|
||||
allow_close: true,
|
||||
}],
|
||||
line_styles: vec![LineStyle::new()
|
||||
.with_width(Twips::ZERO)
|
||||
.with_color(Color::from_rgba(0x00000000))],
|
||||
shape: vec![
|
||||
ShapeRecord::StyleChange(Box::new(StyleChangeData {
|
||||
move_to: None,
|
||||
|
@ -1305,23 +1251,9 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
],
|
||||
})],
|
||||
line_styles: vec![LineStyle {
|
||||
width: Twips::from_pixels(0.0),
|
||||
color: Color {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0,
|
||||
},
|
||||
start_cap: LineCapStyle::Round,
|
||||
end_cap: LineCapStyle::Round,
|
||||
join_style: LineJoinStyle::Round,
|
||||
fill_style: None,
|
||||
allow_scale_x: true,
|
||||
allow_scale_y: true,
|
||||
is_pixel_hinted: false,
|
||||
allow_close: true,
|
||||
}],
|
||||
line_styles: vec![LineStyle::new()
|
||||
.with_width(Twips::from_pixels(0.0))
|
||||
.with_color(Color::from_rgba(0x00000000))],
|
||||
shape: vec![
|
||||
ShapeRecord::StraightEdge {
|
||||
delta_x: Twips::from_pixels(200.0),
|
||||
|
@ -1641,35 +1573,23 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
],
|
||||
line_styles: vec![
|
||||
LineStyle {
|
||||
width: Twips::from_pixels(20.0),
|
||||
color: Color {
|
||||
LineStyle::new()
|
||||
.with_width(Twips::from_pixels(20.0))
|
||||
.with_color(Color {
|
||||
r: 0,
|
||||
g: 153,
|
||||
b: 0,
|
||||
a: 255,
|
||||
},
|
||||
start_cap: LineCapStyle::None,
|
||||
end_cap: LineCapStyle::None,
|
||||
join_style: LineJoinStyle::Bevel,
|
||||
fill_style: None,
|
||||
allow_scale_x: false,
|
||||
allow_scale_y: false,
|
||||
is_pixel_hinted: true,
|
||||
allow_close: true,
|
||||
},
|
||||
LineStyle {
|
||||
width: Twips::from_pixels(20.0),
|
||||
color: Color {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0,
|
||||
},
|
||||
start_cap: LineCapStyle::Round,
|
||||
end_cap: LineCapStyle::Round,
|
||||
join_style: LineJoinStyle::Round,
|
||||
fill_style: Some(FillStyle::LinearGradient(Gradient {
|
||||
})
|
||||
.with_allow_scale_x(false)
|
||||
.with_allow_scale_y(false)
|
||||
.with_is_pixel_hinted(true)
|
||||
.with_join_style(LineJoinStyle::Bevel)
|
||||
.with_start_cap(LineCapStyle::None)
|
||||
.with_end_cap(LineCapStyle::None),
|
||||
LineStyle::new()
|
||||
.with_width(Twips::from_pixels(20.0))
|
||||
.with_fill_style(FillStyle::LinearGradient(Gradient {
|
||||
matrix: Matrix {
|
||||
tx: Twips::from_pixels(50.0),
|
||||
ty: Twips::from_pixels(50.0),
|
||||
|
@ -1700,29 +1620,20 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
},
|
||||
],
|
||||
})),
|
||||
allow_scale_x: true,
|
||||
allow_scale_y: false,
|
||||
is_pixel_hinted: true,
|
||||
allow_close: true,
|
||||
},
|
||||
LineStyle {
|
||||
width: Twips::from_pixels(20.0),
|
||||
color: Color {
|
||||
}))
|
||||
.with_allow_scale_y(false)
|
||||
.with_is_pixel_hinted(true),
|
||||
LineStyle::new()
|
||||
.with_width(Twips::from_pixels(20.0))
|
||||
.with_color(Color {
|
||||
r: 0,
|
||||
g: 153,
|
||||
b: 0,
|
||||
a: 255,
|
||||
},
|
||||
start_cap: LineCapStyle::Round,
|
||||
end_cap: LineCapStyle::Round,
|
||||
join_style: LineJoinStyle::Miter(Fixed8::from_f32(56.0)),
|
||||
fill_style: None,
|
||||
allow_scale_x: true,
|
||||
allow_scale_y: false,
|
||||
is_pixel_hinted: true,
|
||||
allow_close: true,
|
||||
},
|
||||
})
|
||||
.with_join_style(LineJoinStyle::Miter(Fixed8::from_f32(56.0)))
|
||||
.with_allow_scale_y(false)
|
||||
.with_is_pixel_hinted(true),
|
||||
],
|
||||
},
|
||||
shape: vec![
|
||||
|
@ -2572,18 +2483,9 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
has_scaling_strokes: true,
|
||||
styles: ShapeStyles {
|
||||
fill_styles: vec![],
|
||||
line_styles: vec![LineStyle {
|
||||
width: Twips::from_pixels(40.0),
|
||||
color: Color {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
a: 0,
|
||||
},
|
||||
start_cap: LineCapStyle::Round,
|
||||
end_cap: LineCapStyle::Round,
|
||||
join_style: LineJoinStyle::Round,
|
||||
fill_style: Some(FillStyle::Bitmap {
|
||||
line_styles: vec![LineStyle::new()
|
||||
.with_width(Twips::from_pixels(40.0))
|
||||
.with_fill_style(FillStyle::Bitmap {
|
||||
id: 1,
|
||||
matrix: Matrix {
|
||||
a: Fixed16::from_f32(20.0),
|
||||
|
@ -2594,12 +2496,7 @@ pub fn tag_tests() -> Vec<TagTestData> {
|
|||
},
|
||||
is_smoothed: false,
|
||||
is_repeating: true,
|
||||
}),
|
||||
allow_scale_x: true,
|
||||
allow_scale_y: true,
|
||||
is_pixel_hinted: false,
|
||||
allow_close: true,
|
||||
}],
|
||||
})],
|
||||
},
|
||||
shape: vec![
|
||||
ShapeRecord::StyleChange(Box::new(StyleChangeData {
|
||||
|
|
190
swf/src/types.rs
190
swf/src/types.rs
|
@ -1116,31 +1116,153 @@ pub struct GradientRecord {
|
|||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct LineStyle {
|
||||
pub width: Twips,
|
||||
pub color: Color,
|
||||
pub start_cap: LineCapStyle,
|
||||
pub end_cap: LineCapStyle,
|
||||
pub join_style: LineJoinStyle,
|
||||
pub fill_style: Option<FillStyle>,
|
||||
pub allow_scale_x: bool,
|
||||
pub allow_scale_y: bool,
|
||||
pub is_pixel_hinted: bool,
|
||||
pub allow_close: bool,
|
||||
pub(crate) width: Twips,
|
||||
pub(crate) fill_style: FillStyle,
|
||||
pub(crate) flags: LineStyleFlag,
|
||||
pub(crate) miter_limit: Fixed8,
|
||||
}
|
||||
|
||||
impl LineStyle {
|
||||
pub const fn new_v1(width: Twips, color: Color) -> LineStyle {
|
||||
LineStyle {
|
||||
width,
|
||||
color,
|
||||
start_cap: LineCapStyle::Round,
|
||||
end_cap: LineCapStyle::Round,
|
||||
join_style: LineJoinStyle::Round,
|
||||
fill_style: None,
|
||||
allow_scale_x: false,
|
||||
allow_scale_y: false,
|
||||
is_pixel_hinted: false,
|
||||
allow_close: true,
|
||||
#[inline]
|
||||
pub fn new() -> LineStyle {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn allow_close(&self) -> bool {
|
||||
!self.flags.contains(LineStyleFlag::NO_CLOSE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_allow_close(mut self, val: bool) -> Self {
|
||||
self.flags.set(LineStyleFlag::NO_CLOSE, !val);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn allow_scale_x(&self) -> bool {
|
||||
!self.flags.contains(LineStyleFlag::NO_H_SCALE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_allow_scale_x(mut self, val: bool) -> Self {
|
||||
self.flags.set(LineStyleFlag::NO_H_SCALE, !val);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn allow_scale_y(&self) -> bool {
|
||||
!self.flags.contains(LineStyleFlag::NO_V_SCALE)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_allow_scale_y(mut self, val: bool) -> Self {
|
||||
self.flags.set(LineStyleFlag::NO_V_SCALE, !val);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_pixel_hinted(&self) -> bool {
|
||||
self.flags.contains(LineStyleFlag::PIXEL_HINTING)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_is_pixel_hinted(mut self, val: bool) -> Self {
|
||||
self.flags.set(LineStyleFlag::PIXEL_HINTING, val);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn start_cap(&self) -> LineCapStyle {
|
||||
let cap = (self.flags & LineStyleFlag::START_CAP_STYLE).bits() >> 6;
|
||||
LineCapStyle::from_u8(cap as u8).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_start_cap(mut self, val: LineCapStyle) -> Self {
|
||||
self.flags -= LineStyleFlag::START_CAP_STYLE;
|
||||
self.flags |= LineStyleFlag::from_bits_truncate((val as u16) << 6);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn end_cap(&self) -> LineCapStyle {
|
||||
let cap = (self.flags & LineStyleFlag::END_CAP_STYLE).bits() >> 8;
|
||||
LineCapStyle::from_u8(cap as u8).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_end_cap(mut self, val: LineCapStyle) -> Self {
|
||||
self.flags -= LineStyleFlag::END_CAP_STYLE;
|
||||
self.flags |= LineStyleFlag::from_bits_truncate((val as u16) << 8);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn join_style(&self) -> LineJoinStyle {
|
||||
match self.flags & LineStyleFlag::JOIN_STYLE {
|
||||
LineStyleFlag::ROUND => LineJoinStyle::Round,
|
||||
LineStyleFlag::BEVEL => LineJoinStyle::Bevel,
|
||||
LineStyleFlag::MITER => LineJoinStyle::Miter(self.miter_limit),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_join_style(mut self, val: LineJoinStyle) -> Self {
|
||||
self.flags -= LineStyleFlag::JOIN_STYLE;
|
||||
self.flags |= match val {
|
||||
LineJoinStyle::Round => LineStyleFlag::ROUND,
|
||||
LineJoinStyle::Bevel => LineStyleFlag::BEVEL,
|
||||
LineJoinStyle::Miter(miter_limit) => {
|
||||
self.miter_limit = miter_limit;
|
||||
LineStyleFlag::MITER
|
||||
}
|
||||
};
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn fill_style(&self) -> &FillStyle {
|
||||
&self.fill_style
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_fill_style(mut self, val: FillStyle) -> Self {
|
||||
self.flags
|
||||
.set(LineStyleFlag::HAS_FILL, !matches!(val, FillStyle::Color(_)));
|
||||
self.fill_style = val;
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_color(mut self, val: Color) -> Self {
|
||||
self.flags.remove(LineStyleFlag::HAS_FILL);
|
||||
self.fill_style = FillStyle::Color(val);
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn width(&self) -> Twips {
|
||||
self.width
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with_width(mut self, val: Twips) -> Self {
|
||||
self.width = val;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LineStyle {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
// Hairline black stroke.
|
||||
Self {
|
||||
width: Twips::ZERO,
|
||||
fill_style: FillStyle::Color(Color::from_rgb(0, 255)),
|
||||
flags: Default::default(),
|
||||
miter_limit: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1157,7 +1279,7 @@ bitflags! {
|
|||
|
||||
// Second byte.
|
||||
const END_CAP_STYLE = 0b11 << 8;
|
||||
const ALLOW_CLOSE = 1 << 10;
|
||||
const NO_CLOSE = 1 << 10;
|
||||
|
||||
// JOIN_STYLE mask values.
|
||||
const ROUND = 0b00 << 4;
|
||||
|
@ -1166,6 +1288,13 @@ bitflags! {
|
|||
}
|
||||
}
|
||||
|
||||
impl Default for LineStyleFlag {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
LineStyleFlag::empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, FromPrimitive)]
|
||||
pub enum LineCapStyle {
|
||||
Round = 0,
|
||||
|
@ -1174,11 +1303,19 @@ pub enum LineCapStyle {
|
|||
}
|
||||
|
||||
impl LineCapStyle {
|
||||
#[inline]
|
||||
pub fn from_u8(n: u8) -> Option<Self> {
|
||||
num_traits::FromPrimitive::from_u8(n)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LineCapStyle {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::Round
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum LineJoinStyle {
|
||||
Round,
|
||||
|
@ -1186,6 +1323,13 @@ pub enum LineJoinStyle {
|
|||
Miter(Fixed8),
|
||||
}
|
||||
|
||||
impl Default for LineJoinStyle {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::Round
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, FromPrimitive)]
|
||||
pub enum AudioCompression {
|
||||
UncompressedUnknownEndian = 0,
|
||||
|
|
109
swf/src/write.rs
109
swf/src/write.rs
|
@ -1205,17 +1205,19 @@ impl<W: Write> Writer<W> {
|
|||
// TODO(Herschel): Handle overflow.
|
||||
self.write_u16(start.width.get() as u16)?;
|
||||
self.write_u16(end.width.get() as u16)?;
|
||||
self.write_rgba(&start.color)?;
|
||||
self.write_rgba(&end.color)?;
|
||||
match (&start.fill_style, &end.fill_style) {
|
||||
(FillStyle::Color(start), FillStyle::Color(end)) => {
|
||||
self.write_rgba(start)?;
|
||||
self.write_rgba(end)?;
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::invalid_data(
|
||||
"Complex line styles can only be used in DefineMorphShape2 tags",
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if start.start_cap != end.start_cap
|
||||
|| start.join_style != end.join_style
|
||||
|| start.allow_scale_x != end.allow_scale_x
|
||||
|| start.allow_scale_y != end.allow_scale_y
|
||||
|| start.is_pixel_hinted != end.is_pixel_hinted
|
||||
|| start.allow_close != end.allow_close
|
||||
|| start.end_cap != end.end_cap
|
||||
{
|
||||
if start.flags != end.flags {
|
||||
return Err(Error::invalid_data(
|
||||
"Morph start and end line styles must have the same join parameters.",
|
||||
));
|
||||
|
@ -1226,41 +1228,21 @@ impl<W: Write> Writer<W> {
|
|||
self.write_u16(end.width.get() as u16)?;
|
||||
|
||||
// MorphLineStyle2
|
||||
let mut bits = self.bits();
|
||||
bits.write_ubits(2, start.start_cap as u32)?;
|
||||
bits.write_ubits(
|
||||
2,
|
||||
match start.join_style {
|
||||
LineJoinStyle::Round => 0,
|
||||
LineJoinStyle::Bevel => 1,
|
||||
LineJoinStyle::Miter(_) => 2,
|
||||
},
|
||||
)?;
|
||||
bits.write_bit(start.fill_style.is_some())?;
|
||||
bits.write_bit(!start.allow_scale_x)?;
|
||||
bits.write_bit(!start.allow_scale_y)?;
|
||||
bits.write_bit(start.is_pixel_hinted)?;
|
||||
bits.write_ubits(5, 0)?;
|
||||
bits.write_bit(!start.allow_close)?;
|
||||
bits.write_ubits(2, start.end_cap as u32)?;
|
||||
drop(bits);
|
||||
if let LineJoinStyle::Miter(miter_factor) = start.join_style {
|
||||
self.write_u16(start.flags.bits())?;
|
||||
if let LineJoinStyle::Miter(miter_factor) = start.join_style() {
|
||||
self.write_fixed8(miter_factor)?;
|
||||
}
|
||||
if start.flags.contains(LineStyleFlag::HAS_FILL) {
|
||||
self.write_morph_fill_style(&start.fill_style, &end.fill_style)?;
|
||||
} else {
|
||||
match (&start.fill_style, &end.fill_style) {
|
||||
(&None, &None) => {
|
||||
self.write_rgba(&start.color)?;
|
||||
self.write_rgba(&end.color)?;
|
||||
(FillStyle::Color(start), FillStyle::Color(end)) => {
|
||||
self.write_rgba(start)?;
|
||||
self.write_rgba(end)?;
|
||||
}
|
||||
|
||||
(&Some(ref start_fill), &Some(ref end_fill)) => {
|
||||
self.write_morph_fill_style(start_fill, end_fill)?
|
||||
}
|
||||
|
||||
_ => {
|
||||
return Err(Error::invalid_data(
|
||||
"Morph start and end line styles must both have fill styles.",
|
||||
))
|
||||
return Err(Error::invalid_data("Unexpected line fill style fill type"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1584,34 +1566,31 @@ impl<W: Write> Writer<W> {
|
|||
self.write_u16(line_style.width.get() as u16)?;
|
||||
if shape_version >= 4 {
|
||||
// LineStyle2
|
||||
let mut flags = LineStyleFlag::empty();
|
||||
flags.set(LineStyleFlag::PIXEL_HINTING, line_style.is_pixel_hinted);
|
||||
flags.set(LineStyleFlag::NO_V_SCALE, !line_style.allow_scale_y);
|
||||
flags.set(LineStyleFlag::NO_H_SCALE, !line_style.allow_scale_x);
|
||||
flags.set(LineStyleFlag::HAS_FILL, line_style.fill_style.is_some());
|
||||
flags |= match line_style.join_style {
|
||||
LineJoinStyle::Round => LineStyleFlag::ROUND,
|
||||
LineJoinStyle::Bevel => LineStyleFlag::BEVEL,
|
||||
LineJoinStyle::Miter(_) => LineStyleFlag::MITER,
|
||||
};
|
||||
let mut flags = flags.bits();
|
||||
flags |= (line_style.start_cap as u16) << 6;
|
||||
flags |= (line_style.end_cap as u16) << 8;
|
||||
self.write_u16(flags)?;
|
||||
|
||||
if let LineJoinStyle::Miter(miter_factor) = line_style.join_style {
|
||||
self.write_u16(line_style.flags.bits())?;
|
||||
if let LineJoinStyle::Miter(miter_factor) = line_style.join_style() {
|
||||
self.write_fixed8(miter_factor)?;
|
||||
}
|
||||
match line_style.fill_style {
|
||||
None => self.write_rgba(&line_style.color)?,
|
||||
Some(ref fill) => self.write_fill_style(fill, shape_version)?,
|
||||
}
|
||||
} else if shape_version >= 3 {
|
||||
// LineStyle1 with RGBA
|
||||
self.write_rgba(&line_style.color)?;
|
||||
if line_style.flags.contains(LineStyleFlag::HAS_FILL) {
|
||||
self.write_fill_style(&line_style.fill_style, shape_version)?;
|
||||
} else if let FillStyle::Color(color) = &line_style.fill_style {
|
||||
self.write_rgba(color)?;
|
||||
} else {
|
||||
// LineStyle1 with RGB
|
||||
self.write_rgb(&line_style.color)?;
|
||||
return Err(Error::invalid_data("Unexpected line style fill type"));
|
||||
}
|
||||
} else {
|
||||
// LineStyle1
|
||||
let color = if let FillStyle::Color(color) = &line_style.fill_style {
|
||||
color
|
||||
} else {
|
||||
return Err(Error::invalid_data(
|
||||
"Complex line styles can only be used in DefineShape4 tags",
|
||||
));
|
||||
};
|
||||
if shape_version >= 3 {
|
||||
self.write_rgba(color)?
|
||||
} else {
|
||||
self.write_rgb(color)?
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue