core: Migrate clip drawing commands to exposing the internal `Drawing` to mutation

This commit is contained in:
David Wendt 2021-02-26 21:09:27 -05:00 committed by Mike Welsh
parent 1a6f401f1f
commit e8b6d1a52a
5 changed files with 197 additions and 213 deletions

View File

@ -336,9 +336,10 @@ fn line_style<'gc>(
Some("bevel") => LineJoinStyle::Bevel,
_ => LineJoinStyle::Round,
};
movie_clip.set_line_style(
&mut activation.context,
Some(LineStyle {
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.set_line_style(Some(LineStyle {
width,
color,
start_cap: cap_style,
@ -349,10 +350,12 @@ fn line_style<'gc>(
allow_scale_y,
is_pixel_hinted,
allow_close: false,
}),
);
}));
} else {
movie_clip.set_line_style(&mut activation.context, None);
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.set_line_style(None);
}
Ok(Value::Undefined)
}
@ -371,12 +374,15 @@ fn begin_fill<'gc>(
} as f32
/ 100.0
* 255.0;
movie_clip.set_fill_style(
&mut activation.context,
Some(FillStyle::Color(Color::from_rgb(rgb, alpha as u8))),
);
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.set_fill_style(Some(FillStyle::Color(Color::from_rgb(rgb, alpha as u8))));
} else {
movie_clip.set_fill_style(&mut activation.context, None);
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.set_fill_style(None);
}
Ok(Value::Undefined)
}
@ -461,9 +467,15 @@ fn begin_gradient_fill<'gc>(
return Ok(Value::Undefined);
}
};
movie_clip.set_fill_style(&mut activation.context, Some(style));
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.set_fill_style(Some(style));
} else {
movie_clip.set_fill_style(&mut activation.context, None);
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.set_fill_style(None);
}
Ok(Value::Undefined)
}
@ -476,13 +488,13 @@ fn move_to<'gc>(
if let (Some(x), Some(y)) = (args.get(0), args.get(1)) {
let x = x.coerce_to_f64(activation)?;
let y = y.coerce_to_f64(activation)?;
movie_clip.draw_command(
&mut activation.context,
DrawCommand::MoveTo {
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.draw_command(DrawCommand::MoveTo {
x: Twips::from_pixels(x),
y: Twips::from_pixels(y),
},
);
});
}
Ok(Value::Undefined)
}
@ -495,13 +507,13 @@ fn line_to<'gc>(
if let (Some(x), Some(y)) = (args.get(0), args.get(1)) {
let x = x.coerce_to_f64(activation)?;
let y = y.coerce_to_f64(activation)?;
movie_clip.draw_command(
&mut activation.context,
DrawCommand::LineTo {
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.draw_command(DrawCommand::LineTo {
x: Twips::from_pixels(x),
y: Twips::from_pixels(y),
},
);
});
}
Ok(Value::Undefined)
}
@ -518,15 +530,15 @@ fn curve_to<'gc>(
let y1 = y1.coerce_to_f64(activation)?;
let x2 = x2.coerce_to_f64(activation)?;
let y2 = y2.coerce_to_f64(activation)?;
movie_clip.draw_command(
&mut activation.context,
DrawCommand::CurveTo {
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.draw_command(DrawCommand::CurveTo {
x1: Twips::from_pixels(x1),
y1: Twips::from_pixels(y1),
x2: Twips::from_pixels(x2),
y2: Twips::from_pixels(y2),
},
);
});
}
Ok(Value::Undefined)
}
@ -536,7 +548,10 @@ fn end_fill<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
movie_clip.set_fill_style(&mut activation.context, None);
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.set_fill_style(None);
Ok(Value::Undefined)
}
@ -545,7 +560,10 @@ fn clear<'gc>(
activation: &mut Activation<'_, 'gc, '_>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
movie_clip.clear(&mut activation.context);
movie_clip
.as_drawing(activation.context.gc_context)
.unwrap()
.clear();
Ok(Value::Undefined)
}

View File

@ -47,9 +47,7 @@ pub fn begin_fill<'gc>(
this: Option<Object<'gc>>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error> {
if let Some(this) = this {
if let Some(dobj) = this.as_display_object() {
if let Some(mc) = dobj.as_movie_clip() {
if let Some(this) = this.and_then(|t| t.as_display_object()) {
let color = args
.get(0)
.cloned()
@ -61,11 +59,8 @@ pub fn begin_fill<'gc>(
.unwrap_or_else(|| 1.0.into())
.coerce_to_number(activation)?;
mc.set_fill_style(
&mut activation.context,
Some(FillStyle::Color(color_from_args(color, alpha))),
);
}
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
draw.set_fill_style(Some(FillStyle::Color(color_from_args(color, alpha))));
}
}
@ -78,11 +73,9 @@ pub fn clear<'gc>(
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error> {
if let Some(this) = this {
if let Some(dobj) = this.as_display_object() {
if let Some(mc) = dobj.as_movie_clip() {
mc.clear(&mut activation.context)
}
if let Some(this) = this.and_then(|t| t.as_display_object()) {
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
draw.clear()
}
}
@ -95,9 +88,7 @@ pub fn curve_to<'gc>(
this: Option<Object<'gc>>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error> {
if let Some(this) = this {
if let Some(dobj) = this.as_display_object() {
if let Some(mc) = dobj.as_movie_clip() {
if let Some(this) = this.and_then(|t| t.as_display_object()) {
let x1 = Twips::from_pixels(
args.get(0)
.cloned()
@ -123,11 +114,8 @@ pub fn curve_to<'gc>(
.coerce_to_number(activation)?,
);
mc.draw_command(
&mut activation.context,
DrawCommand::CurveTo { x1, y1, x2, y2 },
);
}
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
draw.draw_command(DrawCommand::CurveTo { x1, y1, x2, y2 });
}
}
@ -140,11 +128,9 @@ pub fn end_fill<'gc>(
this: Option<Object<'gc>>,
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error> {
if let Some(this) = this {
if let Some(dobj) = this.as_display_object() {
if let Some(mc) = dobj.as_movie_clip() {
mc.set_fill_style(&mut activation.context, None);
}
if let Some(this) = this.and_then(|t| t.as_display_object()) {
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
draw.set_fill_style(None);
}
}
@ -200,16 +186,17 @@ pub fn line_style<'gc>(
this: Option<Object<'gc>>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error> {
if let Some(this) = this {
if let Some(dobj) = this.as_display_object() {
if let Some(mc) = dobj.as_movie_clip() {
if let Some(this) = this.and_then(|t| t.as_display_object()) {
let thickness = args
.get(0)
.cloned()
.unwrap_or_else(|| f64::NAN.into())
.coerce_to_number(activation)?;
if thickness.is_nan() {
mc.set_line_style(&mut activation.context, None);
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
draw.set_line_style(None);
}
} else {
let color = args
.get(1)
@ -231,8 +218,7 @@ pub fn line_style<'gc>(
.cloned()
.unwrap_or_else(|| "normal".into())
.coerce_to_string(activation)?;
let caps =
caps_to_cap_style(activation, args.get(5).cloned().unwrap_or(Value::Null))?;
let caps = caps_to_cap_style(activation, args.get(5).cloned().unwrap_or(Value::Null))?;
let joints = args.get(6).cloned().unwrap_or(Value::Null);
let miter_limit = args
.get(7)
@ -243,8 +229,7 @@ pub fn line_style<'gc>(
let width = Twips::from_pixels(thickness.min(255.0).max(0.0));
let color = color_from_args(color, alpha);
let join_style = joints_to_join_style(activation, joints, miter_limit as f32)?;
let (allow_scale_x, allow_scale_y) =
scale_mode_to_allow_scale_bits(&scale_mode)?;
let (allow_scale_x, allow_scale_y) = scale_mode_to_allow_scale_bits(&scale_mode)?;
let line_style = LineStyle {
width,
@ -259,8 +244,8 @@ pub fn line_style<'gc>(
allow_close: true,
};
mc.set_line_style(&mut activation.context, Some(line_style));
}
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
draw.set_line_style(Some(line_style));
}
}
}
@ -274,9 +259,7 @@ pub fn line_to<'gc>(
this: Option<Object<'gc>>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error> {
if let Some(this) = this {
if let Some(dobj) = this.as_display_object() {
if let Some(mc) = dobj.as_movie_clip() {
if let Some(this) = this.and_then(|t| t.as_display_object()) {
let x = Twips::from_pixels(
args.get(0)
.cloned()
@ -290,8 +273,8 @@ pub fn line_to<'gc>(
.coerce_to_number(activation)?,
);
mc.draw_command(&mut activation.context, DrawCommand::LineTo { x, y });
}
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
draw.draw_command(DrawCommand::LineTo { x, y });
}
}
@ -304,9 +287,7 @@ pub fn move_to<'gc>(
this: Option<Object<'gc>>,
args: &[Value<'gc>],
) -> Result<Value<'gc>, Error> {
if let Some(this) = this {
if let Some(dobj) = this.as_display_object() {
if let Some(mc) = dobj.as_movie_clip() {
if let Some(this) = this.and_then(|t| t.as_display_object()) {
let x = Twips::from_pixels(
args.get(0)
.cloned()
@ -320,8 +301,8 @@ pub fn move_to<'gc>(
.coerce_to_number(activation)?,
);
mc.draw_command(&mut activation.context, DrawCommand::MoveTo { x, y });
}
if let Some(mut draw) = this.as_drawing(activation.context.gc_context) {
draw.draw_command(DrawCommand::MoveTo { x, y });
}
}

View File

@ -3,6 +3,7 @@ use crate::avm1::{
};
use crate::avm2::{Avm2, Event as Avm2Event, TObject as Avm2TObject, Value as Avm2Value};
use crate::context::{RenderContext, UpdateContext};
use crate::drawing::Drawing;
use crate::player::NEWEST_PLAYER_VERSION;
use crate::prelude::*;
use crate::tag_utils::SwfMovie;
@ -991,6 +992,9 @@ pub trait TDisplayObject<'gc>:
fn as_video(self) -> Option<Video<'gc>> {
None
}
fn as_drawing(&self, _gc_context: MutationContext<'gc, '_>) -> Option<RefMut<'_, Drawing>> {
None
}
fn apply_place_object(
&self,

View File

@ -26,18 +26,17 @@ use crate::drawing::Drawing;
use crate::events::{ButtonKeyCode, ClipEvent, ClipEventResult};
use crate::font::Font;
use crate::prelude::*;
use crate::shape_utils::DrawCommand;
use crate::tag_utils::{self, DecodeResult, SwfMovie, SwfSlice, SwfStream};
use crate::types::{Degrees, Percent};
use crate::vminterface::{AvmObject, AvmType, Instantiator};
use gc_arena::{Collect, Gc, GcCell, MutationContext};
use smallvec::SmallVec;
use std::cell::{Ref, RefCell};
use std::cell::{Ref, RefCell, RefMut};
use std::collections::HashMap;
use std::convert::TryFrom;
use std::sync::Arc;
use swf::extensions::ReadSwfExt;
use swf::{FillStyle, FrameLabelData, LineStyle, Tag};
use swf::{FrameLabelData, Tag};
type FrameNumber = u16;
@ -1013,34 +1012,6 @@ impl<'gc> MovieClip<'gc> {
actions.into_iter()
}
pub fn set_fill_style(
self,
context: &mut UpdateContext<'_, 'gc, '_>,
style: Option<FillStyle>,
) {
let mut mc = self.0.write(context.gc_context);
mc.drawing.set_fill_style(style);
}
pub fn clear(self, context: &mut UpdateContext<'_, 'gc, '_>) {
let mut mc = self.0.write(context.gc_context);
mc.drawing.clear();
}
pub fn set_line_style(
self,
context: &mut UpdateContext<'_, 'gc, '_>,
style: Option<LineStyle>,
) {
let mut mc = self.0.write(context.gc_context);
mc.drawing.set_line_style(style);
}
pub fn draw_command(self, context: &mut UpdateContext<'_, 'gc, '_>, command: DrawCommand) {
let mut mc = self.0.write(context.gc_context);
mc.drawing.draw_command(command);
}
pub fn run_clip_event(
self,
context: &mut crate::context::UpdateContext<'_, 'gc, '_>,
@ -1936,6 +1907,10 @@ impl<'gc> TDisplayObject<'gc> for MovieClip<'gc> {
Some(self.into())
}
fn as_drawing(&self, gc_context: MutationContext<'gc, '_>) -> Option<RefMut<'_, Drawing>> {
Some(RefMut::map(self.0.write(gc_context), |s| &mut s.drawing))
}
fn post_instantiation(
&self,
context: &mut UpdateContext<'_, 'gc, '_>,

View File

@ -20,6 +20,12 @@ pub struct Drawing {
cursor: (Twips, Twips),
}
impl Default for Drawing {
fn default() -> Self {
Self::new()
}
}
impl Drawing {
pub fn new() -> Self {
Self {