Skip to content

Commit e214dd5

Browse files
adrian17relrelb
authored andcommitted
avm2: Implement BitmapData.scroll/copyPixels, stub lock()
1 parent 17f090d commit e214dd5

File tree

1 file changed

+115
-2
lines changed

1 file changed

+115
-2
lines changed

core/src/avm2/globals/flash/display/bitmapdata.rs

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use crate::avm2::activation::Activation;
44
use crate::avm2::class::{Class, ClassAttributes};
55
use crate::avm2::method::{Method, NativeMethodImpl};
6-
use crate::avm2::names::{Namespace, QName};
6+
use crate::avm2::names::{Multiname, Namespace, QName};
77
use crate::avm2::object::{bitmapdata_allocator, Object, TObject};
88
use crate::avm2::value::Value;
99
use crate::avm2::Error;
@@ -159,6 +159,104 @@ pub fn transparent<'gc>(
159159
Ok(Value::Undefined)
160160
}
161161

162+
/// Implements `BitmapData.scroll`.
163+
pub fn scroll<'gc>(
164+
activation: &mut Activation<'_, 'gc, '_>,
165+
this: Option<Object<'gc>>,
166+
args: &[Value<'gc>],
167+
) -> Result<Value<'gc>, Error> {
168+
if let Some(bitmap_data) = this.and_then(|t| t.as_bitmap_data()) {
169+
let x = args
170+
.get(0)
171+
.unwrap_or(&Value::Undefined)
172+
.coerce_to_i32(activation)?;
173+
let y = args
174+
.get(1)
175+
.unwrap_or(&Value::Undefined)
176+
.coerce_to_i32(activation)?;
177+
178+
bitmap_data
179+
.write(activation.context.gc_context)
180+
.scroll(x, y);
181+
}
182+
183+
Ok(Value::Undefined)
184+
}
185+
186+
/// Implements `BitmapData.copyPixels`.
187+
pub fn copy_pixels<'gc>(
188+
activation: &mut Activation<'_, 'gc, '_>,
189+
this: Option<Object<'gc>>,
190+
args: &[Value<'gc>],
191+
) -> Result<Value<'gc>, Error> {
192+
if let Some(bitmap_data) = this.and_then(|t| t.as_bitmap_data()) {
193+
let source_bitmap = args
194+
.get(0)
195+
.unwrap_or(&Value::Undefined)
196+
.coerce_to_object(activation)?;
197+
198+
let source_rect = args
199+
.get(1)
200+
.unwrap_or(&Value::Undefined)
201+
.coerce_to_object(activation)?;
202+
203+
let src_min_x = source_rect
204+
.get_property(&Multiname::public("x"), activation)?
205+
.coerce_to_i32(activation)?;
206+
let src_min_y = source_rect
207+
.get_property(&Multiname::public("y"), activation)?
208+
.coerce_to_i32(activation)?;
209+
let src_width = source_rect
210+
.get_property(&Multiname::public("width"), activation)?
211+
.coerce_to_i32(activation)?;
212+
let src_height = source_rect
213+
.get_property(&Multiname::public("height"), activation)?
214+
.coerce_to_i32(activation)?;
215+
216+
let dest_point = args
217+
.get(2)
218+
.unwrap_or(&Value::Undefined)
219+
.coerce_to_object(activation)?;
220+
221+
let dest_x = dest_point
222+
.get_property(&Multiname::public("x"), activation)?
223+
.coerce_to_i32(activation)?;
224+
let dest_y = dest_point
225+
.get_property(&Multiname::public("y"), activation)?
226+
.coerce_to_i32(activation)?;
227+
228+
if let Some(src_bitmap) = source_bitmap.as_bitmap_data() {
229+
// dealing with object aliasing...
230+
let src_bitmap_clone: BitmapData; // only initialized if source is the same object as self
231+
let src_bitmap_data_cell = src_bitmap;
232+
let src_bitmap_gc_ref; // only initialized if source is a different object than self
233+
let source_bitmap_ref = // holds the reference to either of the ones above
234+
if GcCell::ptr_eq(src_bitmap, bitmap_data) {
235+
src_bitmap_clone = src_bitmap_data_cell.read().clone();
236+
&src_bitmap_clone
237+
} else {
238+
src_bitmap_gc_ref = src_bitmap_data_cell.read();
239+
&src_bitmap_gc_ref
240+
};
241+
242+
if args.len() >= 4 {
243+
log::warn!("BitmapData.copyPixels - alpha not implemented");
244+
}
245+
246+
bitmap_data
247+
.write(activation.context.gc_context)
248+
.copy_pixels(
249+
source_bitmap_ref,
250+
(src_min_x, src_min_y, src_width, src_height),
251+
(dest_x, dest_y),
252+
None,
253+
);
254+
}
255+
}
256+
257+
Ok(Value::Undefined)
258+
}
259+
162260
/// Implements `BitmapData.getPixel`.
163261
pub fn get_pixel<'gc>(
164262
activation: &mut Activation<'_, 'gc, '_>,
@@ -180,6 +278,15 @@ pub fn get_pixel<'gc>(
180278
Ok(Value::Undefined)
181279
}
182280

281+
pub fn lock<'gc>(
282+
_activation: &mut Activation<'_, 'gc, '_>,
283+
_this: Option<Object<'gc>>,
284+
_args: &[Value<'gc>],
285+
) -> Result<Value<'gc>, Error> {
286+
log::warn!("BitmapData.lock - not yet implemented");
287+
Ok(Value::Undefined)
288+
}
289+
183290
/// Construct `BitmapData`'s class.
184291
pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>> {
185292
let class = Class::new(
@@ -208,7 +315,13 @@ pub fn create_class<'gc>(mc: MutationContext<'gc, '_>) -> GcCell<'gc, Class<'gc>
208315
];
209316
write.define_public_builtin_instance_properties(mc, PUBLIC_INSTANCE_PROPERTIES);
210317

211-
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[("getPixel", get_pixel)];
318+
const PUBLIC_INSTANCE_METHODS: &[(&str, NativeMethodImpl)] = &[
319+
("getPixel", get_pixel),
320+
("scroll", scroll),
321+
("lock", lock),
322+
("unlock", lock), // sic, it's a noop (TODO)
323+
("copyPixels", copy_pixels),
324+
];
212325
write.define_public_builtin_instance_methods(mc, PUBLIC_INSTANCE_METHODS);
213326

214327
class

0 commit comments

Comments
 (0)