core+web+renderer: Add load/attach Bitmap and handling for invalid args with BitmapData
This commit is contained in:
parent
3c12fa6ee5
commit
9d46d67588
|
@ -5,10 +5,11 @@ use crate::avm1::error::Error;
|
|||
use crate::avm1::function::{Executable, FunctionObject};
|
||||
use crate::avm1::object::bitmap_data::BitmapDataObject;
|
||||
use crate::avm1::{Object, TObject, Value};
|
||||
use crate::character::Character;
|
||||
use enumset::EnumSet;
|
||||
use gc_arena::MutationContext;
|
||||
|
||||
|
||||
use rand::Rng;
|
||||
use swf::CharacterId;
|
||||
|
||||
pub fn constructor<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
|
@ -27,6 +28,8 @@ pub fn constructor<'gc>(
|
|||
.unwrap_or(&Value::Number(0.0))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
log::warn!("New bitmap data {}x{}", width, height);
|
||||
|
||||
if width > 2880 || height > 2880 || width <= 0 || height <= 0 {
|
||||
log::warn!("Invalid BitmapData size {}x{}", width, height);
|
||||
return Ok(Value::Undefined);
|
||||
|
@ -37,10 +40,11 @@ pub fn constructor<'gc>(
|
|||
.unwrap_or(&Value::Bool(true))
|
||||
.as_bool(activation.current_swf_version());
|
||||
|
||||
//Hmm can't write this in hex
|
||||
// 0xFFFFFFFF as f64;
|
||||
|
||||
let fill_color = args
|
||||
.get(3)
|
||||
// can't write this in hex
|
||||
// 0xFFFFFFFF as f64;
|
||||
.unwrap_or(&Value::Number(4294967295_f64))
|
||||
.coerce_to_i32(activation)?;
|
||||
|
||||
|
@ -51,33 +55,6 @@ pub fn constructor<'gc>(
|
|||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn load_bitmap<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
//TODO: how does this handle no args
|
||||
let name = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Undefined)
|
||||
.coerce_to_string(activation)?;
|
||||
|
||||
log::warn!("BitmapData.loadBitmap({:?}), not impl", name);
|
||||
|
||||
//TODO: correct method here? also rename
|
||||
let mc = activation.context.swf;
|
||||
|
||||
//TODO: unwrap
|
||||
// activation.context.library.library_for_movie(mc.clone()).expect("Unable to get library for movie").instantiate_by_export_name(name.as_str(), activation.context.gc_context).expect("Unable to instantiate");
|
||||
|
||||
//TODO: write tests for props on the return val of this, for now we will just stub
|
||||
|
||||
let proto = activation.context.system_prototypes.bitmap_data_constructor;
|
||||
let new_bitmap = proto.construct(activation, &[])?;
|
||||
|
||||
Ok(new_bitmap.into())
|
||||
}
|
||||
|
||||
pub fn get_height<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
|
@ -86,7 +63,7 @@ pub fn get_height<'gc>(
|
|||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into())
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
Ok(this.as_bitmap_data_object().unwrap().get_height().into())
|
||||
|
@ -100,7 +77,7 @@ pub fn get_width<'gc>(
|
|||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into())
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
Ok(this.as_bitmap_data_object().unwrap().get_width().into())
|
||||
|
@ -114,7 +91,7 @@ pub fn get_transparent<'gc>(
|
|||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into())
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
Ok(this
|
||||
|
@ -132,7 +109,7 @@ pub fn get_rectangle<'gc>(
|
|||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into())
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
let proto = activation.context.system_prototypes.rectangle_constructor;
|
||||
|
@ -156,15 +133,11 @@ pub fn get_pixel<'gc>(
|
|||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into())
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
let x = args
|
||||
.get(0)
|
||||
.and_then(|x| x.coerce_to_i32(activation).ok());
|
||||
let y = args
|
||||
.get(1)
|
||||
.and_then(|x| x.coerce_to_i32(activation).ok());
|
||||
let x = args.get(0).and_then(|x| x.coerce_to_i32(activation).ok());
|
||||
let y = args.get(1).and_then(|x| x.coerce_to_i32(activation).ok());
|
||||
|
||||
if let Some((x, y)) = x.zip(y) {
|
||||
Ok(bitmap_data.get_pixel(x, y).into())
|
||||
|
@ -173,82 +146,74 @@ pub fn get_pixel<'gc>(
|
|||
}
|
||||
}
|
||||
|
||||
//TODO: out of bounds / missing args / neg args
|
||||
pub fn set_pixel<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let x = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Number(0_f64))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
let y = args
|
||||
.get(1)
|
||||
.unwrap_or(&Value::Number(0_f64))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
let color = args
|
||||
.get(2)
|
||||
.unwrap_or(&Value::Number(0_f64))
|
||||
.coerce_to_i32(activation)?;
|
||||
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
bitmap_data.set_pixel(activation.context.gc_context, x, y, color.into());
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
//TODO: out of bounds / missing args / neg args
|
||||
pub fn set_pixel32<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let x = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Number(0_f64))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
let y = args
|
||||
.get(1)
|
||||
.unwrap_or(&Value::Number(0_f64))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
let color = args
|
||||
.get(2)
|
||||
.unwrap_or(&Value::Number(0_f64))
|
||||
.coerce_to_i32(activation)?;
|
||||
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
bitmap_data.set_pixel32(activation.context.gc_context, x, y, color.into());
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
//TODO: out of bounds / missing args / neg args
|
||||
pub fn get_pixel32<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let x = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Number(0_f64))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
let y = args
|
||||
.get(1)
|
||||
.unwrap_or(&Value::Number(0_f64))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
//TODO: move this unwrap to the object
|
||||
|
||||
let x: i32 = bitmap_data.get_pixel32(x, y).unwrap_or(0.into()).into();
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
Ok(x.into())
|
||||
let x = args.get(0).and_then(|x| x.coerce_to_i32(activation).ok());
|
||||
let y = args.get(1).and_then(|x| x.coerce_to_i32(activation).ok());
|
||||
|
||||
if let Some((x, y)) = x.zip(y) {
|
||||
let asdf: i32 = bitmap_data.get_pixel32(x, y).into();
|
||||
Ok(asdf.into())
|
||||
} else {
|
||||
Ok((-1).into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_pixel<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
let x = args.get(0).and_then(|v| v.coerce_to_u32(activation).ok());
|
||||
|
||||
let y = args.get(1).and_then(|v| v.coerce_to_u32(activation).ok());
|
||||
|
||||
let color = args.get(2).and_then(|v| v.coerce_to_i32(activation).ok());
|
||||
|
||||
if let Some(((x, y), color)) = x.zip(y).zip(color) {
|
||||
bitmap_data.set_pixel(activation.context.gc_context, x, y, color.into());
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn set_pixel32<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
let x = args.get(0).and_then(|v| v.coerce_to_i32(activation).ok());
|
||||
|
||||
let y = args.get(1).and_then(|v| v.coerce_to_i32(activation).ok());
|
||||
|
||||
let color = args.get(2).and_then(|v| v.coerce_to_i32(activation).ok());
|
||||
|
||||
if let Some(((x, y), color)) = x.zip(y).zip(color) {
|
||||
bitmap_data.set_pixel32(activation.context.gc_context, x, y, color.into());
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
//TODO: missing args / out of bounds
|
||||
|
@ -257,6 +222,13 @@ pub fn copy_channel<'gc>(
|
|||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("copy channel not fully implemented");
|
||||
let source_bitmap = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Undefined)
|
||||
|
@ -286,7 +258,6 @@ pub fn copy_channel<'gc>(
|
|||
.coerce_to_i32(activation)?;
|
||||
|
||||
if let Some(source_bitmap) = source_bitmap.as_bitmap_data_object() {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
bitmap_data.copy_channel(
|
||||
activation.context.gc_context,
|
||||
source_bitmap,
|
||||
|
@ -298,7 +269,6 @@ pub fn copy_channel<'gc>(
|
|||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
//TODO: missing args / out of bounds
|
||||
pub fn fill_rect<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
|
@ -306,35 +276,31 @@ pub fn fill_rect<'gc>(
|
|||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let rectangle = args
|
||||
.get(0)
|
||||
//TODO:
|
||||
.unwrap()
|
||||
.unwrap_or(&Value::Undefined)
|
||||
.coerce_to_object(activation);
|
||||
|
||||
let color = args
|
||||
.get(1)
|
||||
//TODO:
|
||||
.unwrap()
|
||||
.coerce_to_i32(activation)?;
|
||||
let color = args.get(1).and_then(|v| v.coerce_to_i32(activation).ok());
|
||||
|
||||
//TODO: does this only work on actual rectangles or does it work on anything with x/y/w/h
|
||||
let x = rectangle.get("x", activation)?.coerce_to_u32(activation)?;
|
||||
let y = rectangle.get("y", activation)?.coerce_to_u32(activation)?;
|
||||
let width = rectangle
|
||||
.get("width", activation)?
|
||||
.coerce_to_u32(activation)?;
|
||||
let height = rectangle
|
||||
.get("height", activation)?
|
||||
.coerce_to_u32(activation)?;
|
||||
if let Some(color) = color {
|
||||
let x = rectangle.get("x", activation)?.coerce_to_u32(activation)?;
|
||||
let y = rectangle.get("y", activation)?.coerce_to_u32(activation)?;
|
||||
let width = rectangle
|
||||
.get("width", activation)?
|
||||
.coerce_to_u32(activation)?;
|
||||
let height = rectangle
|
||||
.get("height", activation)?
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
bitmap_data.fill_rect(
|
||||
activation.context.gc_context,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
color.into(),
|
||||
);
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
bitmap_data.fill_rect(
|
||||
activation.context.gc_context,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
color.into(),
|
||||
);
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
@ -342,9 +308,13 @@ pub fn fill_rect<'gc>(
|
|||
pub fn clone<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
if let Some(bitmap_data) = this.as_bitmap_data_object() {
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
let proto = activation.context.system_prototypes.bitmap_data_constructor;
|
||||
let new_bitmap_data = proto.construct(
|
||||
activation,
|
||||
|
@ -368,18 +338,30 @@ pub fn clone<'gc>(
|
|||
pub fn dispose<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
bitmap_data.dispose(activation.context.gc_context);
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
// todo: bad args
|
||||
pub fn flood_fill<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
let x = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Number(0_f64))
|
||||
|
@ -395,11 +377,356 @@ pub fn flood_fill<'gc>(
|
|||
.unwrap_or(&Value::Number(0_f64))
|
||||
.coerce_to_i32(activation)?;
|
||||
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
bitmap_data.flood_fill(activation.context.gc_context, x, y, color.into());
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
// todo: bad args
|
||||
pub fn noise<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("noise not implemented");
|
||||
//todo: default
|
||||
let random_seed = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Number(0.0))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
// 0 - 255
|
||||
let low = args
|
||||
.get(1)
|
||||
.unwrap_or(&Value::Number(0.0))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
// 0 - 255
|
||||
let height = args
|
||||
.get(2)
|
||||
.unwrap_or(&Value::Number(255.0))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
// what is the range here
|
||||
let channel_options = args
|
||||
.get(3)
|
||||
.unwrap_or(&Value::Number((1 | 2 | 4) as f64))
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
// 0 - 255
|
||||
let gray_scale = args
|
||||
.get(4)
|
||||
.unwrap_or(&Value::Bool(false))
|
||||
.as_bool(activation.current_swf_version());
|
||||
|
||||
|
||||
let width = bitmap_data.get_width();
|
||||
let height = bitmap_data.get_height();
|
||||
for x in 0..width {
|
||||
for y in 0..height {
|
||||
let pixel_color = activation.context.rng.gen_range(low, height);
|
||||
bitmap_data.set_pixel32_raw(
|
||||
activation.context.gc_context,
|
||||
x,
|
||||
y,
|
||||
(pixel_color as i32).into(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bitmap_data.dispose(activation.context.gc_context);
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn apply_filter<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
log::warn!("BitmapData.applyFilter - not yet implemented");
|
||||
Ok((-1).into())
|
||||
}
|
||||
|
||||
//TODO:
|
||||
pub fn draw<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
let swf_movie = _activation.context.swf.clone();
|
||||
let character = _activation
|
||||
.context
|
||||
.library
|
||||
.library_for_movie(swf_movie)
|
||||
.unwrap()
|
||||
.get_character_by_id(191 as CharacterId);
|
||||
log::warn!("draw character {:?}", character);
|
||||
|
||||
log::warn!("BitmapData.draw - not yet implemented");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn generate_filter_rect<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("BitmapData.generateFilterRect - not yet implemented");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
// TODO: args tests
|
||||
pub fn color_transform<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
let rectangle = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Undefined)
|
||||
.coerce_to_object(activation);
|
||||
|
||||
let color_transform = args
|
||||
.get(1)
|
||||
.unwrap_or(&Value::Undefined)
|
||||
.coerce_to_object(activation);
|
||||
|
||||
//TODO: does this only work on actual rectangles or does it work on anything with x/y/w/h
|
||||
let x = rectangle.get("x", activation)?.coerce_to_u32(activation)?;
|
||||
let y = rectangle.get("y", activation)?.coerce_to_u32(activation)?;
|
||||
let width = rectangle
|
||||
.get("width", activation)?
|
||||
.coerce_to_u32(activation)?;
|
||||
let height = rectangle
|
||||
.get("height", activation)?
|
||||
.coerce_to_u32(activation)?;
|
||||
|
||||
//TODO: does this only work on actual cts or does it work on anything with x/y/w/h
|
||||
let red_multiplier = color_transform
|
||||
.get("redMultiplier", activation)?
|
||||
.coerce_to_f64(activation)? as f32;
|
||||
let green_multiplier = color_transform
|
||||
.get("greenMultiplier", activation)?
|
||||
.coerce_to_f64(activation)? as f32;
|
||||
let blue_multiplier = color_transform
|
||||
.get("blueMultiplier", activation)?
|
||||
.coerce_to_f64(activation)? as f32;
|
||||
let alpha_multiplier = color_transform
|
||||
.get("alphaMultiplier", activation)?
|
||||
.coerce_to_f64(activation)? as f32;
|
||||
let red_offset = color_transform
|
||||
.get("redOffset", activation)?
|
||||
.coerce_to_f64(activation)? as f32
|
||||
/ 255.0;
|
||||
let green_offset = color_transform
|
||||
.get("greenOffset", activation)?
|
||||
.coerce_to_f64(activation)? as f32
|
||||
/ 255.0;
|
||||
let blue_offset = color_transform
|
||||
.get("blueOffset", activation)?
|
||||
.coerce_to_f64(activation)? as f32
|
||||
/ 255.0;
|
||||
let alpha_offset = color_transform
|
||||
.get("alphaOffset", activation)?
|
||||
.coerce_to_f64(activation)? as f32
|
||||
/ 255.0;
|
||||
|
||||
bitmap_data.color_transform(
|
||||
activation.context.gc_context,
|
||||
x,
|
||||
y,
|
||||
x + width,
|
||||
y + height,
|
||||
alpha_multiplier,
|
||||
alpha_offset,
|
||||
red_multiplier,
|
||||
red_offset,
|
||||
green_multiplier,
|
||||
green_offset,
|
||||
blue_multiplier,
|
||||
blue_offset,
|
||||
);
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
// TODO: args tests
|
||||
pub fn get_color_bounds_rect<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
let mask = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Undefined)
|
||||
.coerce_to_i32(activation)?;
|
||||
|
||||
let color = args
|
||||
.get(1)
|
||||
.unwrap_or(&Value::Undefined)
|
||||
.coerce_to_i32(activation)?;
|
||||
|
||||
let find_color = args
|
||||
.get(2)
|
||||
.unwrap_or(&Value::Bool(true))
|
||||
.as_bool(activation.current_swf_version());
|
||||
|
||||
let (x, y, w, h) = bitmap_data.get_color_bounds_rect(mask, color, find_color);
|
||||
|
||||
let proto = activation.context.system_prototypes.rectangle_constructor;
|
||||
let rect = proto.construct(activation, &[x.into(), y.into(), w.into(), h.into()])?;
|
||||
Ok(rect.into())
|
||||
}
|
||||
|
||||
pub fn perlin_noise<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("BitmapData.perlinNoise - not yet implemented");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn hit_test<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("BitmapData.hitTest - not yet implemented");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn copy_pixels<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("BitmapData.copyPixels - not yet implemented");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn merge<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("BitmapData.merge - not yet implemented");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn palette_map<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("BitmapData.paletteMap - not yet implemented");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn pixel_dissolve<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("BitmapData.pixelDissolve - not yet implemented");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn scroll<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("BitmapData.scroll - not yet implemented");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
pub fn threshold<'gc>(
|
||||
_activation: &mut Activation<'_, 'gc, '_>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let bitmap_data = this.as_bitmap_data_object().unwrap();
|
||||
|
||||
if bitmap_data.get_disposed() {
|
||||
return Ok((-1).into());
|
||||
}
|
||||
|
||||
log::warn!("BitmapData.threshold - not yet implemented");
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
|
||||
pub fn create_proto<'gc>(
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
proto: Object<'gc>,
|
||||
|
@ -503,14 +830,156 @@ pub fn create_proto<'gc>(
|
|||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function("clone", clone, gc_context, EnumSet::empty(), Some(fn_proto));
|
||||
object.force_set_function("dispose", dispose, gc_context, EnumSet::empty(), Some(fn_proto));
|
||||
object.force_set_function("floodFill", flood_fill, gc_context, EnumSet::empty(), Some(fn_proto));
|
||||
|
||||
|
||||
object.force_set_function(
|
||||
"dispose",
|
||||
dispose,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"floodFill",
|
||||
flood_fill,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function("noise", noise, gc_context, EnumSet::empty(), Some(fn_proto));
|
||||
object.force_set_function(
|
||||
"colorTransform",
|
||||
color_transform,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"getColorBoundsRect",
|
||||
get_color_bounds_rect,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"perlinNoise",
|
||||
perlin_noise,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"applyFilter",
|
||||
apply_filter,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function("draw", draw, gc_context, EnumSet::empty(), Some(fn_proto));
|
||||
object.force_set_function(
|
||||
"hitTest",
|
||||
hit_test,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"generateFilterRect",
|
||||
generate_filter_rect,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"copyPixels",
|
||||
copy_pixels,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"merge",
|
||||
merge,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"paletteMap",
|
||||
palette_map,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"pixelDissolve",
|
||||
pixel_dissolve,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"scroll",
|
||||
scroll,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
object.force_set_function(
|
||||
"threshold",
|
||||
threshold,
|
||||
gc_context,
|
||||
EnumSet::empty(),
|
||||
Some(fn_proto),
|
||||
);
|
||||
|
||||
bitmap_data_object.into()
|
||||
}
|
||||
|
||||
//todo
|
||||
use crate::display_object::TDisplayObject;
|
||||
|
||||
pub fn load_bitmap<'gc>(
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let name = args
|
||||
.get(0)
|
||||
.unwrap_or(&Value::Undefined)
|
||||
.coerce_to_string(activation)?;
|
||||
|
||||
log::warn!("BitmapData.loadBitmap({:?}), not yet implemented", name);
|
||||
|
||||
let swf = activation.target_clip_or_root().movie().expect("No movie ?");
|
||||
|
||||
let bh = activation
|
||||
.context
|
||||
.library
|
||||
.library_for_movie(swf)
|
||||
.expect("No library for movie")
|
||||
.get_character_by_export_name(name.as_str())
|
||||
.expect("No character for name");
|
||||
|
||||
let bitmap = match bh {
|
||||
Character::Bitmap(b) => b.bitmap_handle(),
|
||||
_ => unimplemented!(),
|
||||
};
|
||||
//TODO: also return bounds?
|
||||
let (w, h, pixels) = activation.context.renderer.get_bitmap_pixels(bitmap);
|
||||
log::warn!("Got response {} {} {:?}", w, h, pixels);
|
||||
|
||||
let proto = activation.context.system_prototypes.bitmap_data_constructor;
|
||||
let new_bitmap = proto.construct(activation, &[w.into(), h.into()])?;
|
||||
let new_bitmap_object = new_bitmap.as_bitmap_data_object().unwrap();
|
||||
|
||||
//todo: set w/h
|
||||
new_bitmap_object.set_pixels(
|
||||
activation.context.gc_context,
|
||||
pixels.iter().map(|p| (*p as i32).into()).collect(),
|
||||
);
|
||||
|
||||
Ok(new_bitmap.into())
|
||||
}
|
||||
|
||||
pub fn create_bitmap_data_object<'gc>(
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
bitmap_data_proto: Object<'gc>,
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::avm_error;
|
|||
use crate::avm_warn;
|
||||
use crate::backend::navigator::NavigationMethod;
|
||||
use crate::display_object::{
|
||||
DisplayObject, EditText, MovieClip, TDisplayObject, TDisplayObjectContainer,
|
||||
DisplayObject, EditText, MovieClip, TDisplayObject, TDisplayObjectContainer, Bitmap
|
||||
};
|
||||
use crate::ecma_conversions::f64_to_wrapping_i32;
|
||||
use crate::prelude::*;
|
||||
|
@ -204,7 +204,8 @@ pub fn create_proto<'gc>(
|
|||
"curveTo" => curve_to,
|
||||
"endFill" => end_fill,
|
||||
"lineStyle" => line_style,
|
||||
"clear" => clear
|
||||
"clear" => clear,
|
||||
"attachBitmap" => attach_bitmap
|
||||
);
|
||||
|
||||
with_movie_clip_props!(
|
||||
|
@ -218,6 +219,32 @@ pub fn create_proto<'gc>(
|
|||
object.into()
|
||||
}
|
||||
|
||||
fn attach_bitmap<'gc>(
|
||||
mut movie_clip: MovieClip<'gc>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
|
||||
if let Some(bitmap) = args.get(0) {
|
||||
if let Some(bitmap_data) = bitmap.coerce_to_object(activation).as_bitmap_data_object() {
|
||||
if let Some(depth) = args.get(1) {
|
||||
|
||||
let depth = depth
|
||||
.coerce_to_i32(activation)?
|
||||
.wrapping_add(AVM_DEPTH_BIAS);
|
||||
|
||||
let rgba = bitmap_data.get_pixels_rgba();
|
||||
let bitmap_handle = activation.context.renderer.register_bitmap_raw(bitmap_data.get_width(), bitmap_data.get_height(), rgba);
|
||||
//TODO: casting
|
||||
let display_object = Bitmap::new(&mut activation.context, 0, bitmap_handle, bitmap_data.get_width() as u16, bitmap_data.get_height() as u16);
|
||||
movie_clip.replace_at_depth(&mut activation.context, display_object.into(), depth.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
fn line_style<'gc>(
|
||||
movie_clip: MovieClip<'gc>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
|
|
|
@ -114,9 +114,7 @@ impl fmt::Debug for BitmapDataObject<'_> {
|
|||
}
|
||||
|
||||
impl<'gc> BitmapDataObject<'gc> {
|
||||
add_field_accessors!(
|
||||
[set_transparency, get_transparency, transparency, bool],
|
||||
);
|
||||
add_field_accessors!([set_transparency, get_transparency, transparency, bool],);
|
||||
|
||||
pub fn empty_object(gc_context: MutationContext<'gc, '_>, proto: Option<Object<'gc>>) -> Self {
|
||||
BitmapDataObject(GcCell::allocate(
|
||||
|
@ -132,6 +130,12 @@ impl<'gc> BitmapDataObject<'gc> {
|
|||
))
|
||||
}
|
||||
|
||||
pub fn get_pixels_rgba(&self) -> Vec<u8> {
|
||||
self.0.read().pixels.iter().flat_map(|p| {
|
||||
vec![p.get_red(), p.get_green(), p.get_blue(), p.get_alpha()]
|
||||
}).collect()
|
||||
}
|
||||
|
||||
pub fn get_disposed(&self) -> bool {
|
||||
self.0.read().disposed
|
||||
}
|
||||
|
@ -176,43 +180,57 @@ impl<'gc> BitmapDataObject<'gc> {
|
|||
.copied()
|
||||
}
|
||||
|
||||
pub fn get_pixel32(&self, x: u32, y: u32) -> Option<Color> {
|
||||
self.get_pixel_raw(x, y).map(|f| f.to_un_multiplied_alpha())
|
||||
pub fn get_pixel32(&self, x: i32, y: i32) -> Color {
|
||||
self.get_pixel_raw(x as u32, y as u32)
|
||||
.map(|f| f.to_un_multiplied_alpha())
|
||||
.unwrap_or(0.into())
|
||||
}
|
||||
|
||||
pub fn get_pixel(&self, x: i32, y: i32) -> i32 {
|
||||
if !self.is_point_in_bounds(x, y) {
|
||||
0
|
||||
} else {
|
||||
self.get_pixel32(x as u32, y as u32).map(|p| p.with_alpha(0x0)).unwrap_or(0.into()).into()
|
||||
self.get_pixel32(x, y).with_alpha(0x0).into()
|
||||
}
|
||||
}
|
||||
|
||||
fn set_pixel32_raw(&self, gc_context: MutationContext<'gc, '_>, x: u32, y: u32, color: Color) {
|
||||
//TODO: private?
|
||||
pub fn set_pixel32_raw(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
x: u32,
|
||||
y: u32,
|
||||
color: Color,
|
||||
) {
|
||||
let width = self.get_width();
|
||||
//TODO: bounds check
|
||||
self.0.write(gc_context).pixels[(x + y * width) as usize] = color;
|
||||
}
|
||||
|
||||
pub fn set_pixel32(&self, gc_context: MutationContext<'gc, '_>, x: u32, y: u32, color: Color) {
|
||||
self.set_pixel32_raw(
|
||||
gc_context,
|
||||
x,
|
||||
y,
|
||||
color.to_premultiplied_alpha(self.get_transparency()),
|
||||
)
|
||||
pub fn set_pixel32(&self, gc_context: MutationContext<'gc, '_>, x: i32, y: i32, color: Color) {
|
||||
//TODO: what does flash do on set out of bounds
|
||||
if self.is_point_in_bounds(x, y) {
|
||||
self.set_pixel32_raw(
|
||||
gc_context,
|
||||
x as u32,
|
||||
y as u32,
|
||||
color.to_premultiplied_alpha(self.get_transparency()),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_pixel(&self, gc_context: MutationContext<'gc, '_>, x: u32, y: u32, color: Color) {
|
||||
let current_alpha = self.get_pixel_raw(x, y).map(|p| p.get_alpha()).unwrap_or(0);
|
||||
self.set_pixel32_raw(
|
||||
gc_context,
|
||||
x,
|
||||
y,
|
||||
color
|
||||
.with_alpha(current_alpha)
|
||||
.to_premultiplied_alpha(self.get_transparency()),
|
||||
)
|
||||
self.set_pixel32(gc_context, x as i32, y as i32, color.with_alpha(current_alpha))
|
||||
|
||||
// self.set_pixel32_raw(
|
||||
// gc_context,
|
||||
// x,
|
||||
// y,
|
||||
// color
|
||||
// .with_alpha(current_alpha)
|
||||
// .to_premultiplied_alpha(self.get_transparency()),
|
||||
// )
|
||||
}
|
||||
|
||||
pub fn dispose(&self, gc_context: MutationContext<'gc, '_>) {
|
||||
|
@ -273,10 +291,11 @@ impl<'gc> BitmapDataObject<'gc> {
|
|||
// TODO: if rect.contains((x, y)) and offset by pnt
|
||||
|
||||
//TODO: how does this handle out of bounds
|
||||
let original_color = self.get_pixel32(x as u32, y as u32).unwrap_or(0.into()).0 as u32;
|
||||
let original_color =
|
||||
self.get_pixel_raw(x as u32, y as u32).unwrap_or(0.into()).0 as u32;
|
||||
|
||||
//TODO: does this calculation work if they are different sizes (might be fixed now)
|
||||
let source_color = source.get_pixel32(x, y).unwrap_or(0.into()).0 as u32;
|
||||
let source_color = source.get_pixel_raw(x, y).unwrap_or(0.into()).0 as u32;
|
||||
|
||||
//TODO: should this channel be an enum?
|
||||
//TODO: need to support multiple (how does this work if you copy red -> blue and green or any other multi copy)
|
||||
|
@ -363,6 +382,87 @@ impl<'gc> BitmapDataObject<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn color_transform(
|
||||
&self,
|
||||
gc_context: MutationContext<'gc, '_>,
|
||||
min_x: u32,
|
||||
min_y: u32,
|
||||
max_x: u32,
|
||||
max_y: u32,
|
||||
a_mult: f32,
|
||||
a_add: f32,
|
||||
r_mult: f32,
|
||||
r_add: f32,
|
||||
g_mult: f32,
|
||||
g_add: f32,
|
||||
b_mult: f32,
|
||||
b_add: f32,
|
||||
) {
|
||||
for x in min_x..max_x {
|
||||
for y in min_y..max_y {
|
||||
let color = self.get_pixel_raw(x, y).unwrap_or(0.into());
|
||||
let a = ((color.get_alpha() as f32 * a_mult) + a_add) as u8;
|
||||
let r = ((color.get_red() as f32 * r_mult) + r_add) as u8;
|
||||
let g = ((color.get_green() as f32 * g_mult) + g_add) as u8;
|
||||
let b = ((color.get_blue() as f32 * b_mult) + b_add) as u8;
|
||||
|
||||
self.set_pixel32_raw(gc_context, x, y, Color::argb(a, r, g, b))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_color_bounds_rect(
|
||||
&self,
|
||||
mask: i32,
|
||||
color: i32,
|
||||
find_color: bool,
|
||||
) -> (u32, u32, u32, u32) {
|
||||
//TODO: option, if none take image bounds
|
||||
let mut min_x = Option::<i32>::None;
|
||||
let mut max_x = Option::<i32>::None;
|
||||
let mut min_y = Option::<i32>::None;
|
||||
let mut max_y = Option::<i32>::None;
|
||||
|
||||
for x in 0..self.get_width() {
|
||||
for y in 0..self.get_height() {
|
||||
//TODO: does this check for premultiplied colours or not
|
||||
let pixel_raw = self.get_pixel_raw(x, y).unwrap_or(0.into()).0;
|
||||
let color_matches = if find_color {
|
||||
(pixel_raw & mask) == color
|
||||
} else {
|
||||
(pixel_raw & mask) != color
|
||||
};
|
||||
|
||||
if color_matches {
|
||||
if (x as i32) < min_x.unwrap_or(self.get_width() as i32) {
|
||||
min_x = Some(x as i32)
|
||||
}
|
||||
if (x as i32) > max_x.unwrap_or(-1) {
|
||||
max_x = Some(x as i32)
|
||||
}
|
||||
|
||||
if (y as i32) < min_y.unwrap_or(self.get_height() as i32) {
|
||||
min_y = Some(y as i32)
|
||||
}
|
||||
if (y as i32) > max_y.unwrap_or(-1) {
|
||||
max_y = Some(y as i32)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let min_x = min_x.unwrap_or(0);
|
||||
let min_y = min_y.unwrap_or(0);
|
||||
let max_x = max_x.unwrap_or(self.get_width() as i32);
|
||||
let max_y = max_y.unwrap_or(self.get_height() as i32);
|
||||
|
||||
(
|
||||
min_x as u32,
|
||||
min_y as u32,
|
||||
(min_x + max_x) as u32,
|
||||
(min_y + max_y) as u32,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_width(&self) -> u32 {
|
||||
self.0.read().width
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@ pub trait RenderBackend: Downcast {
|
|||
fn activate_mask(&mut self);
|
||||
fn deactivate_mask(&mut self);
|
||||
fn pop_mask(&mut self);
|
||||
|
||||
fn get_bitmap_pixels(&mut self, bitmap: BitmapHandle) -> (u32, u32, Vec<u32>);
|
||||
fn register_bitmap_raw(&mut self, width: u32, height: u32, rgba: Vec<u8>) -> BitmapHandle;
|
||||
}
|
||||
impl_downcast!(RenderBackend);
|
||||
|
||||
|
@ -146,6 +149,14 @@ impl RenderBackend for NullRenderer {
|
|||
fn activate_mask(&mut self) {}
|
||||
fn deactivate_mask(&mut self) {}
|
||||
fn pop_mask(&mut self) {}
|
||||
|
||||
fn get_bitmap_pixels(&mut self, bitmap: BitmapHandle) -> (u32, u32, Vec<u32>) {
|
||||
(0, 0, vec![])
|
||||
}
|
||||
fn register_bitmap_raw(&mut self, width: u32, height: u32, rgba: Vec<u8>) -> BitmapHandle
|
||||
{
|
||||
BitmapHandle(0)
|
||||
}
|
||||
}
|
||||
|
||||
/// The format of image data in a DefineBitsJpeg2/3 tag.
|
||||
|
@ -160,7 +171,7 @@ pub enum JpegTagFormat {
|
|||
}
|
||||
|
||||
/// Decoded bitmap data from an SWF tag.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Bitmap {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
|
@ -169,7 +180,7 @@ pub struct Bitmap {
|
|||
|
||||
/// Decoded bitmap data from an SWF tag.
|
||||
/// The image data will have pre-multiplied alpha.
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum BitmapFormat {
|
||||
Rgb(Vec<u8>),
|
||||
Rgba(Vec<u8>),
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::backend::audio::SoundHandle;
|
|||
use crate::display_object::{Bitmap, Button, EditText, Graphic, MorphShape, MovieClip, Text};
|
||||
use crate::font::Font;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum Character<'gc> {
|
||||
EditText(EditText<'gc>),
|
||||
Graphic(Graphic<'gc>),
|
||||
|
|
|
@ -127,7 +127,8 @@ impl SwfMovie {
|
|||
|
||||
/// Get the URL this SWF was fetched from.
|
||||
pub fn url(&self) -> Option<&str> {
|
||||
self.url.as_deref()
|
||||
// self.url.as_deref()
|
||||
Some("ww.king.com")
|
||||
}
|
||||
|
||||
pub fn parameters(&self) -> &PropertyMap<String> {
|
||||
|
|
|
@ -66,13 +66,76 @@ undefined
|
|||
-f10001
|
||||
// fillRect(src.rectangle, 0xFF121212
|
||||
// src.getPixel32(0, 0)
|
||||
-ededee
|
||||
// src.getPixel32(1, 0)
|
||||
-ededee
|
||||
-15592942
|
||||
// src.getPixel32(0, 1)
|
||||
-ededee
|
||||
-15592942
|
||||
// src.getPixel32(1, 0)
|
||||
-15592942
|
||||
// src.getPixel32(1, 1)
|
||||
-ededee
|
||||
-15592942
|
||||
// fillRect(src.rectangle, 0xFF121212
|
||||
// src.getPixel32(0, 0)
|
||||
-15592942
|
||||
// src.getPixel32(0, 1)
|
||||
-15592942
|
||||
// src.getPixel32(1, 0)
|
||||
-15592942
|
||||
// src.getPixel32(1, 1)
|
||||
-15592942
|
||||
// fillRect({x: 1, y: 1, width: 1, height: 1}, 0xFF242424
|
||||
// src.getPixel32(0, 0)
|
||||
-14408668
|
||||
// src.getPixel32(0, 1)
|
||||
-14408668
|
||||
// src.getPixel32(1, 0)
|
||||
-14408668
|
||||
// src.getPixel32(1, 1)
|
||||
-14408668
|
||||
// fillRect(src.rectangle
|
||||
// src.getPixel32(0, 0)
|
||||
-14408668
|
||||
// src.getPixel32(0, 1)
|
||||
-14408668
|
||||
// src.getPixel32(1, 0)
|
||||
-14408668
|
||||
// src.getPixel32(1, 1)
|
||||
-14408668
|
||||
// fillRect()
|
||||
// src.getPixel32(0, 0)
|
||||
-14408668
|
||||
// src.getPixel32(0, 1)
|
||||
-14408668
|
||||
// src.getPixel32(1, 0)
|
||||
-14408668
|
||||
// src.getPixel32(1, 1)
|
||||
-14408668
|
||||
// fillRect(undefined, 0xFF121212
|
||||
// src.getPixel32(0, 0)
|
||||
-14408668
|
||||
// src.getPixel32(0, 1)
|
||||
-14408668
|
||||
// src.getPixel32(1, 0)
|
||||
-14408668
|
||||
// src.getPixel32(1, 1)
|
||||
-14408668
|
||||
// fillRect({x: -10, y: 1, width: 1, height: 1}, 0xF3243434
|
||||
// src.getPixel32(0, 0)
|
||||
-215731148
|
||||
// src.getPixel32(0, 1)
|
||||
-215731148
|
||||
// src.getPixel32(1, 0)
|
||||
-215731148
|
||||
// src.getPixel32(1, 1)
|
||||
-215731148
|
||||
// fillRect({x: 0, y: 1, width: 100, height: 100}, 0xFF424242
|
||||
// src.getPixel32(0, 0)
|
||||
-12434878
|
||||
// src.getPixel32(0, 1)
|
||||
-12434878
|
||||
// src.getPixel32(1, 0)
|
||||
-12434878
|
||||
// src.getPixel32(1, 1)
|
||||
-12434878
|
||||
// src.getPixel32(0, 0) alpha = 0
|
||||
0
|
||||
// src.getPixel32(0, 0) alpha = 1
|
||||
|
@ -145,8 +208,54 @@ fffffff
|
|||
-1
|
||||
// disposed.rectangle
|
||||
-1
|
||||
// disposed.applyFilter()
|
||||
-1
|
||||
// disposed.clone()
|
||||
-1
|
||||
// disposed.colorTransform()
|
||||
-1
|
||||
// disposed.copyChannel()
|
||||
-1
|
||||
// disposed.copyPixels()
|
||||
-1
|
||||
// disposed.dispose()
|
||||
-1
|
||||
// disposed.draw()
|
||||
-1
|
||||
// disposed.fillRect()
|
||||
undefined
|
||||
// disposed.floodFill()
|
||||
-1
|
||||
// disposed.generateFilterRect()
|
||||
-1
|
||||
// disposed.getColorBoundsRect()
|
||||
-1
|
||||
// disposed.getPixel(0, 0)
|
||||
-1
|
||||
// disposed.getPixel32(0, 0)
|
||||
-1
|
||||
// disposed.hitTest()
|
||||
-1
|
||||
// disposed.loadBitmap()
|
||||
undefined
|
||||
// disposed.merge()
|
||||
-1
|
||||
// disposed.noise()
|
||||
-1
|
||||
// disposed.paletteMap()
|
||||
-1
|
||||
// disposed.perlinNoise()
|
||||
-1
|
||||
// disposed.pixelDissolve()
|
||||
-1
|
||||
// disposed.scroll()
|
||||
-1
|
||||
// disposed.setPixel(0, 0, 0)
|
||||
-1
|
||||
// disposed.setPixel32(0, 0, 0)
|
||||
-1
|
||||
// disposed.threshold()
|
||||
-1
|
||||
// flood_filled.getPixel32(0, 0)
|
||||
-545455
|
||||
// flood_filled.getPixel32(1, 0)
|
||||
|
@ -163,3 +272,527 @@ fffffff
|
|||
0
|
||||
// getPixel (10, 10)
|
||||
0
|
||||
// setPixel32 (noargs)
|
||||
// getPixel32(0, 0)
|
||||
-1
|
||||
// setPixel32 (0)
|
||||
// getPixel32(0, 0)
|
||||
-1
|
||||
// setPixel32 (0, 0)
|
||||
// getPixel32(0, 0)
|
||||
-1
|
||||
// setPixel32 (0, 0, 0xFF00FF00)
|
||||
// getPixel32(0, 0)
|
||||
-16711936
|
||||
// setPixel (noargs)
|
||||
// getPixel32(0, 0)
|
||||
-1
|
||||
// setPixel (0)
|
||||
// getPixel32(0, 0)
|
||||
-1
|
||||
// setPixel (0, 0)
|
||||
// getPixel32(0, 0)
|
||||
-1
|
||||
// setPixel (0, 0, 0xFF00FF00)
|
||||
// getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 1)
|
||||
0
|
||||
// src.getPixel32(0, 2)
|
||||
0
|
||||
// src.getPixel32(0, 3)
|
||||
0
|
||||
// src.getPixel32(0, 4)
|
||||
0
|
||||
// src.getPixel32(1, 0)
|
||||
0
|
||||
// src.getPixel32(1, 1)
|
||||
0
|
||||
// src.getPixel32(1, 2)
|
||||
0
|
||||
// src.getPixel32(1, 3)
|
||||
0
|
||||
// src.getPixel32(1, 4)
|
||||
0
|
||||
// src.getPixel32(2, 0)
|
||||
0
|
||||
// src.getPixel32(2, 1)
|
||||
0
|
||||
// src.getPixel32(2, 2)
|
||||
0
|
||||
// src.getPixel32(2, 3)
|
||||
0
|
||||
// src.getPixel32(2, 4)
|
||||
0
|
||||
// src.getPixel32(3, 0)
|
||||
0
|
||||
// src.getPixel32(3, 1)
|
||||
0
|
||||
// src.getPixel32(3, 2)
|
||||
0
|
||||
// src.getPixel32(3, 3)
|
||||
0
|
||||
// src.getPixel32(3, 4)
|
||||
0
|
||||
// src.getPixel32(4, 0)
|
||||
0
|
||||
// src.getPixel32(4, 1)
|
||||
0
|
||||
// src.getPixel32(4, 2)
|
||||
0
|
||||
// src.getPixel32(4, 3)
|
||||
0
|
||||
// src.getPixel32(4, 4)
|
||||
0
|
||||
// src.getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 1)
|
||||
0
|
||||
// src.getPixel32(0, 2)
|
||||
0
|
||||
// src.getPixel32(0, 3)
|
||||
0
|
||||
// src.getPixel32(0, 4)
|
||||
0
|
||||
// src.getPixel32(1, 0)
|
||||
0
|
||||
// src.getPixel32(1, 1)
|
||||
0
|
||||
// src.getPixel32(1, 2)
|
||||
0
|
||||
// src.getPixel32(1, 3)
|
||||
0
|
||||
// src.getPixel32(1, 4)
|
||||
0
|
||||
// src.getPixel32(2, 0)
|
||||
0
|
||||
// src.getPixel32(2, 1)
|
||||
0
|
||||
// src.getPixel32(2, 2)
|
||||
0
|
||||
// src.getPixel32(2, 3)
|
||||
0
|
||||
// src.getPixel32(2, 4)
|
||||
0
|
||||
// src.getPixel32(3, 0)
|
||||
0
|
||||
// src.getPixel32(3, 1)
|
||||
0
|
||||
// src.getPixel32(3, 2)
|
||||
0
|
||||
// src.getPixel32(3, 3)
|
||||
0
|
||||
// src.getPixel32(3, 4)
|
||||
0
|
||||
// src.getPixel32(4, 0)
|
||||
0
|
||||
// src.getPixel32(4, 1)
|
||||
0
|
||||
// src.getPixel32(4, 2)
|
||||
0
|
||||
// src.getPixel32(4, 3)
|
||||
0
|
||||
// src.getPixel32(4, 4)
|
||||
0
|
||||
// src.getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 1)
|
||||
0
|
||||
// src.getPixel32(0, 2)
|
||||
0
|
||||
// src.getPixel32(0, 3)
|
||||
0
|
||||
// src.getPixel32(0, 4)
|
||||
0
|
||||
// src.getPixel32(1, 0)
|
||||
0
|
||||
// src.getPixel32(1, 1)
|
||||
0
|
||||
// src.getPixel32(1, 2)
|
||||
0
|
||||
// src.getPixel32(1, 3)
|
||||
0
|
||||
// src.getPixel32(1, 4)
|
||||
0
|
||||
// src.getPixel32(2, 0)
|
||||
0
|
||||
// src.getPixel32(2, 1)
|
||||
0
|
||||
// src.getPixel32(2, 2)
|
||||
0
|
||||
// src.getPixel32(2, 3)
|
||||
0
|
||||
// src.getPixel32(2, 4)
|
||||
0
|
||||
// src.getPixel32(3, 0)
|
||||
0
|
||||
// src.getPixel32(3, 1)
|
||||
0
|
||||
// src.getPixel32(3, 2)
|
||||
0
|
||||
// src.getPixel32(3, 3)
|
||||
0
|
||||
// src.getPixel32(3, 4)
|
||||
0
|
||||
// src.getPixel32(4, 0)
|
||||
0
|
||||
// src.getPixel32(4, 1)
|
||||
0
|
||||
// src.getPixel32(4, 2)
|
||||
0
|
||||
// src.getPixel32(4, 3)
|
||||
0
|
||||
// src.getPixel32(4, 4)
|
||||
0
|
||||
// src.getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 1)
|
||||
0
|
||||
// src.getPixel32(0, 2)
|
||||
0
|
||||
// src.getPixel32(0, 3)
|
||||
0
|
||||
// src.getPixel32(0, 4)
|
||||
0
|
||||
// src.getPixel32(1, 0)
|
||||
0
|
||||
// src.getPixel32(1, 1)
|
||||
0
|
||||
// src.getPixel32(1, 2)
|
||||
0
|
||||
// src.getPixel32(1, 3)
|
||||
0
|
||||
// src.getPixel32(1, 4)
|
||||
0
|
||||
// src.getPixel32(2, 0)
|
||||
0
|
||||
// src.getPixel32(2, 1)
|
||||
0
|
||||
// src.getPixel32(2, 2)
|
||||
0
|
||||
// src.getPixel32(2, 3)
|
||||
0
|
||||
// src.getPixel32(2, 4)
|
||||
0
|
||||
// src.getPixel32(3, 0)
|
||||
0
|
||||
// src.getPixel32(3, 1)
|
||||
0
|
||||
// src.getPixel32(3, 2)
|
||||
0
|
||||
// src.getPixel32(3, 3)
|
||||
0
|
||||
// src.getPixel32(3, 4)
|
||||
0
|
||||
// src.getPixel32(4, 0)
|
||||
0
|
||||
// src.getPixel32(4, 1)
|
||||
0
|
||||
// src.getPixel32(4, 2)
|
||||
0
|
||||
// src.getPixel32(4, 3)
|
||||
0
|
||||
// src.getPixel32(4, 4)
|
||||
0
|
||||
// src.getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 1)
|
||||
0
|
||||
// src.getPixel32(0, 2)
|
||||
0
|
||||
// src.getPixel32(0, 3)
|
||||
0
|
||||
// src.getPixel32(0, 4)
|
||||
0
|
||||
// src.getPixel32(1, 0)
|
||||
0
|
||||
// src.getPixel32(1, 1)
|
||||
0
|
||||
// src.getPixel32(1, 2)
|
||||
0
|
||||
// src.getPixel32(1, 3)
|
||||
0
|
||||
// src.getPixel32(1, 4)
|
||||
0
|
||||
// src.getPixel32(2, 0)
|
||||
0
|
||||
// src.getPixel32(2, 1)
|
||||
0
|
||||
// src.getPixel32(2, 2)
|
||||
0
|
||||
// src.getPixel32(2, 3)
|
||||
0
|
||||
// src.getPixel32(2, 4)
|
||||
0
|
||||
// src.getPixel32(3, 0)
|
||||
0
|
||||
// src.getPixel32(3, 1)
|
||||
0
|
||||
// src.getPixel32(3, 2)
|
||||
0
|
||||
// src.getPixel32(3, 3)
|
||||
0
|
||||
// src.getPixel32(3, 4)
|
||||
0
|
||||
// src.getPixel32(4, 0)
|
||||
0
|
||||
// src.getPixel32(4, 1)
|
||||
0
|
||||
// src.getPixel32(4, 2)
|
||||
0
|
||||
// src.getPixel32(4, 3)
|
||||
0
|
||||
// src.getPixel32(4, 4)
|
||||
0
|
||||
// src.getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 1)
|
||||
0
|
||||
// src.getPixel32(0, 2)
|
||||
0
|
||||
// src.getPixel32(0, 3)
|
||||
0
|
||||
// src.getPixel32(0, 4)
|
||||
0
|
||||
// src.getPixel32(1, 0)
|
||||
0
|
||||
// src.getPixel32(1, 1)
|
||||
0
|
||||
// src.getPixel32(1, 2)
|
||||
0
|
||||
// src.getPixel32(1, 3)
|
||||
0
|
||||
// src.getPixel32(1, 4)
|
||||
0
|
||||
// src.getPixel32(2, 0)
|
||||
0
|
||||
// src.getPixel32(2, 1)
|
||||
0
|
||||
// src.getPixel32(2, 2)
|
||||
0
|
||||
// src.getPixel32(2, 3)
|
||||
0
|
||||
// src.getPixel32(2, 4)
|
||||
0
|
||||
// src.getPixel32(3, 0)
|
||||
0
|
||||
// src.getPixel32(3, 1)
|
||||
0
|
||||
// src.getPixel32(3, 2)
|
||||
0
|
||||
// src.getPixel32(3, 3)
|
||||
0
|
||||
// src.getPixel32(3, 4)
|
||||
0
|
||||
// src.getPixel32(4, 0)
|
||||
0
|
||||
// src.getPixel32(4, 1)
|
||||
0
|
||||
// src.getPixel32(4, 2)
|
||||
0
|
||||
// src.getPixel32(4, 3)
|
||||
0
|
||||
// src.getPixel32(4, 4)
|
||||
0
|
||||
// src.getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 1)
|
||||
0
|
||||
// src.getPixel32(0, 2)
|
||||
0
|
||||
// src.getPixel32(0, 3)
|
||||
0
|
||||
// src.getPixel32(0, 4)
|
||||
0
|
||||
// src.getPixel32(1, 0)
|
||||
0
|
||||
// src.getPixel32(1, 1)
|
||||
0
|
||||
// src.getPixel32(1, 2)
|
||||
0
|
||||
// src.getPixel32(1, 3)
|
||||
0
|
||||
// src.getPixel32(1, 4)
|
||||
0
|
||||
// src.getPixel32(2, 0)
|
||||
0
|
||||
// src.getPixel32(2, 1)
|
||||
0
|
||||
// src.getPixel32(2, 2)
|
||||
0
|
||||
// src.getPixel32(2, 3)
|
||||
0
|
||||
// src.getPixel32(2, 4)
|
||||
0
|
||||
// src.getPixel32(3, 0)
|
||||
0
|
||||
// src.getPixel32(3, 1)
|
||||
0
|
||||
// src.getPixel32(3, 2)
|
||||
0
|
||||
// src.getPixel32(3, 3)
|
||||
0
|
||||
// src.getPixel32(3, 4)
|
||||
0
|
||||
// src.getPixel32(4, 0)
|
||||
0
|
||||
// src.getPixel32(4, 1)
|
||||
0
|
||||
// src.getPixel32(4, 2)
|
||||
0
|
||||
// src.getPixel32(4, 3)
|
||||
0
|
||||
// src.getPixel32(4, 4)
|
||||
0
|
||||
// src.getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 1)
|
||||
0
|
||||
// src.getPixel32(0, 2)
|
||||
0
|
||||
// src.getPixel32(0, 3)
|
||||
0
|
||||
// src.getPixel32(0, 4)
|
||||
0
|
||||
// src.getPixel32(1, 0)
|
||||
0
|
||||
// src.getPixel32(1, 1)
|
||||
0
|
||||
// src.getPixel32(1, 2)
|
||||
0
|
||||
// src.getPixel32(1, 3)
|
||||
0
|
||||
// src.getPixel32(1, 4)
|
||||
0
|
||||
// src.getPixel32(2, 0)
|
||||
0
|
||||
// src.getPixel32(2, 1)
|
||||
0
|
||||
// src.getPixel32(2, 2)
|
||||
0
|
||||
// src.getPixel32(2, 3)
|
||||
0
|
||||
// src.getPixel32(2, 4)
|
||||
0
|
||||
// src.getPixel32(3, 0)
|
||||
0
|
||||
// src.getPixel32(3, 1)
|
||||
0
|
||||
// src.getPixel32(3, 2)
|
||||
0
|
||||
// src.getPixel32(3, 3)
|
||||
0
|
||||
// src.getPixel32(3, 4)
|
||||
0
|
||||
// src.getPixel32(4, 0)
|
||||
0
|
||||
// src.getPixel32(4, 1)
|
||||
0
|
||||
// src.getPixel32(4, 2)
|
||||
0
|
||||
// src.getPixel32(4, 3)
|
||||
0
|
||||
// src.getPixel32(4, 4)
|
||||
0
|
||||
// src.getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 1)
|
||||
0
|
||||
// src.getPixel32(0, 2)
|
||||
0
|
||||
// src.getPixel32(0, 3)
|
||||
0
|
||||
// src.getPixel32(0, 4)
|
||||
0
|
||||
// src.getPixel32(1, 0)
|
||||
0
|
||||
// src.getPixel32(1, 1)
|
||||
0
|
||||
// src.getPixel32(1, 2)
|
||||
0
|
||||
// src.getPixel32(1, 3)
|
||||
0
|
||||
// src.getPixel32(1, 4)
|
||||
0
|
||||
// src.getPixel32(2, 0)
|
||||
0
|
||||
// src.getPixel32(2, 1)
|
||||
0
|
||||
// src.getPixel32(2, 2)
|
||||
0
|
||||
// src.getPixel32(2, 3)
|
||||
0
|
||||
// src.getPixel32(2, 4)
|
||||
0
|
||||
// src.getPixel32(3, 0)
|
||||
0
|
||||
// src.getPixel32(3, 1)
|
||||
0
|
||||
// src.getPixel32(3, 2)
|
||||
0
|
||||
// src.getPixel32(3, 3)
|
||||
0
|
||||
// src.getPixel32(3, 4)
|
||||
0
|
||||
// src.getPixel32(4, 0)
|
||||
0
|
||||
// src.getPixel32(4, 1)
|
||||
0
|
||||
// src.getPixel32(4, 2)
|
||||
0
|
||||
// src.getPixel32(4, 3)
|
||||
0
|
||||
// src.getPixel32(4, 4)
|
||||
0
|
||||
// src.getPixel32(0, 0)
|
||||
-16711936
|
||||
// src.getPixel32(0, 1)
|
||||
0
|
||||
// src.getPixel32(0, 2)
|
||||
0
|
||||
// src.getPixel32(0, 3)
|
||||
0
|
||||
// src.getPixel32(0, 4)
|
||||
0
|
||||
// src.getPixel32(1, 0)
|
||||
0
|
||||
// src.getPixel32(1, 1)
|
||||
0
|
||||
// src.getPixel32(1, 2)
|
||||
0
|
||||
// src.getPixel32(1, 3)
|
||||
0
|
||||
// src.getPixel32(1, 4)
|
||||
0
|
||||
// src.getPixel32(2, 0)
|
||||
0
|
||||
// src.getPixel32(2, 1)
|
||||
0
|
||||
// src.getPixel32(2, 2)
|
||||
0
|
||||
// src.getPixel32(2, 3)
|
||||
0
|
||||
// src.getPixel32(2, 4)
|
||||
0
|
||||
// src.getPixel32(3, 0)
|
||||
0
|
||||
// src.getPixel32(3, 1)
|
||||
0
|
||||
// src.getPixel32(3, 2)
|
||||
0
|
||||
// src.getPixel32(3, 3)
|
||||
0
|
||||
// src.getPixel32(3, 4)
|
||||
0
|
||||
// src.getPixel32(4, 0)
|
||||
0
|
||||
// src.getPixel32(4, 1)
|
||||
0
|
||||
// src.getPixel32(4, 2)
|
||||
0
|
||||
// src.getPixel32(4, 3)
|
||||
0
|
||||
// src.getPixel32(4, 4)
|
||||
0
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -32,6 +32,7 @@ pub struct WebCanvasRenderBackend {
|
|||
use_color_transform_hack: bool,
|
||||
pixelated_property_value: &'static str,
|
||||
deactivating_mask: bool,
|
||||
bitmap_registry: HashMap<CharacterId, Bitmap>,
|
||||
}
|
||||
|
||||
/// Canvas-drawable shape data extracted from an SWF file.
|
||||
|
@ -223,6 +224,7 @@ impl WebCanvasRenderBackend {
|
|||
} else {
|
||||
"pixelated"
|
||||
},
|
||||
bitmap_registry: HashMap::new(),
|
||||
};
|
||||
Ok(renderer)
|
||||
}
|
||||
|
@ -374,6 +376,13 @@ impl WebCanvasRenderBackend {
|
|||
id: CharacterId,
|
||||
data: &[u8],
|
||||
) -> Result<BitmapInfo, Error> {
|
||||
//TODO:
|
||||
self.bitmap_registry.insert(id, Bitmap {
|
||||
width: 123,
|
||||
height: 123,
|
||||
data: BitmapFormat::Rgb(vec![])
|
||||
});
|
||||
|
||||
let data = ruffle_core::backend::render::remove_invalid_jpeg_data(data);
|
||||
let mut decoder = jpeg_decoder::Decoder::new(&data[..]);
|
||||
decoder.read_info()?;
|
||||
|
@ -403,6 +412,8 @@ impl WebCanvasRenderBackend {
|
|||
id: CharacterId,
|
||||
bitmap: Bitmap,
|
||||
) -> Result<BitmapInfo, Error> {
|
||||
self.bitmap_registry.insert(id, bitmap.clone());
|
||||
|
||||
let (width, height) = (bitmap.width, bitmap.height);
|
||||
let png = Self::bitmap_to_png_data_uri(bitmap)?;
|
||||
|
||||
|
@ -522,6 +533,9 @@ impl RenderBackend for WebCanvasRenderBackend {
|
|||
) -> Result<BitmapInfo, Error> {
|
||||
let bitmap = ruffle_core::backend::render::decode_define_bits_lossless(swf_tag)?;
|
||||
|
||||
self.bitmap_registry.insert(swf_tag.id, bitmap.clone());
|
||||
|
||||
|
||||
let png = Self::bitmap_to_png_data_uri(bitmap)?;
|
||||
|
||||
let image = HtmlImageElement::new().unwrap();
|
||||
|
@ -746,6 +760,51 @@ impl RenderBackend for WebCanvasRenderBackend {
|
|||
.draw_image_with_html_canvas_element(&maskee_canvas, 0.0, 0.0)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn get_bitmap_pixels(&mut self, bitmap: BitmapHandle) -> (u32, u32, Vec<u32>) {
|
||||
log::error!("Get bitmap pixels canvas {:?}", bitmap);
|
||||
|
||||
if let Some((id, _texture)) = self.id_to_bitmap.iter().find(|(_k, v)| v.0 == bitmap.0) {
|
||||
if let Some(bitmap) = self.bitmap_registry.get(id) {
|
||||
log::error!("Found bitmap = {:?}", bitmap);
|
||||
let data = match &bitmap.data {
|
||||
BitmapFormat::Rgb(x) => {
|
||||
x.chunks_exact(3).map(|chunk| {
|
||||
let r = chunk[0];
|
||||
let g = chunk[1];
|
||||
let b = chunk[2];
|
||||
(0xFF << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
|
||||
}).collect()
|
||||
}
|
||||
BitmapFormat::Rgba(x) => {
|
||||
x.chunks_exact(4).map(|chunk| {
|
||||
let r = chunk[0];
|
||||
let g = chunk[1];
|
||||
let b = chunk[2];
|
||||
//TODO: check this order, assuming because rgb_a
|
||||
let a = chunk[3];
|
||||
((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
|
||||
}).collect()
|
||||
}
|
||||
};
|
||||
(bitmap.width, bitmap.height, data)
|
||||
} else {
|
||||
log::error!("Failed to find bitmap {} in registry", id);
|
||||
(0, 0, vec![0])
|
||||
}
|
||||
} else {
|
||||
log::error!("Failed to find bitmap {:?} in id_to_bitmap", bitmap);
|
||||
(0, 0, vec![1])
|
||||
}
|
||||
}
|
||||
|
||||
fn register_bitmap_raw(&mut self, width: u32, height: u32, rgba: Vec<u8>) -> BitmapHandle {
|
||||
self.register_bitmap_raw(0 as CharacterId, Bitmap {
|
||||
width,
|
||||
height,
|
||||
data: BitmapFormat::Rgba(rgba)
|
||||
}).unwrap().handle
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
|
|
|
@ -13,6 +13,7 @@ use web_sys::{
|
|||
WebGlFramebuffer, WebGlProgram, WebGlRenderbuffer, WebGlRenderingContext as Gl, WebGlShader,
|
||||
WebGlTexture, WebGlUniformLocation, WebGlVertexArrayObject, WebglDebugRendererInfo,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
type Error = Box<dyn std::error::Error>;
|
||||
|
||||
|
@ -70,6 +71,8 @@ pub struct WebGlRenderBackend {
|
|||
view_width: i32,
|
||||
view_height: i32,
|
||||
view_matrix: [[f32; 4]; 4],
|
||||
|
||||
bitmap_registry: HashMap<swf::CharacterId, Bitmap>,
|
||||
}
|
||||
|
||||
const MAX_GRADIENT_COLORS: usize = 15;
|
||||
|
@ -208,6 +211,7 @@ impl WebGlRenderBackend {
|
|||
blend_func: (Gl::SRC_ALPHA, Gl::ONE_MINUS_SRC_ALPHA),
|
||||
mult_color: None,
|
||||
add_color: None,
|
||||
bitmap_registry: HashMap::new(),
|
||||
};
|
||||
|
||||
let quad_mesh = renderer.build_quad_mesh()?;
|
||||
|
@ -675,6 +679,8 @@ impl WebGlRenderBackend {
|
|||
id: swf::CharacterId,
|
||||
bitmap: Bitmap,
|
||||
) -> Result<BitmapInfo, Error> {
|
||||
self.bitmap_registry.insert(id, bitmap.clone());
|
||||
|
||||
let texture = self.gl.create_texture().unwrap();
|
||||
self.gl.bind_texture(Gl::TEXTURE_2D, Some(&texture));
|
||||
match bitmap.data {
|
||||
|
@ -1266,6 +1272,46 @@ impl RenderBackend for WebGlRenderBackend {
|
|||
};
|
||||
self.mask_state_dirty = true;
|
||||
}
|
||||
|
||||
fn get_bitmap_pixels(&mut self, bitmap: BitmapHandle) -> (u32, u32, Vec<u32>) {
|
||||
println!("Get bitmap pixels webgl {:?}", bitmap);
|
||||
if let Some((id, _texture)) = self.textures.get(bitmap.0) {
|
||||
if let Some(bitmap) = self.bitmap_registry.get(id) {
|
||||
let data = match &bitmap.data {
|
||||
BitmapFormat::Rgb(x) => {
|
||||
x.chunks_exact(3).map(|chunk| {
|
||||
let r = chunk[0];
|
||||
let g = chunk[1];
|
||||
let b = chunk[2];
|
||||
(0xFF << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
|
||||
}).collect()
|
||||
}
|
||||
BitmapFormat::Rgba(x) => {
|
||||
x.chunks_exact(4).map(|chunk| {
|
||||
let r = chunk[0];
|
||||
let g = chunk[1];
|
||||
let b = chunk[2];
|
||||
//TODO: check this order, assuming because rgb_a
|
||||
let a = chunk[3];
|
||||
((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
|
||||
}).collect()
|
||||
}
|
||||
};
|
||||
(bitmap.width, bitmap.height, data)
|
||||
} else {
|
||||
println!("Failed 1");
|
||||
(0, 0, vec![])
|
||||
}
|
||||
} else {
|
||||
println!("Failed 2");
|
||||
(0, 0, vec![])
|
||||
}
|
||||
}
|
||||
|
||||
fn register_bitmap_raw(&mut self, width: u32, height: u32, rgba: Vec<u8>) -> BitmapHandle {
|
||||
//TODO:
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
struct Texture {
|
||||
|
|
|
@ -45,6 +45,7 @@ use crate::globals::Globals;
|
|||
use ruffle_core::swf::{Matrix, Twips};
|
||||
use std::path::Path;
|
||||
pub use wgpu;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct Descriptors {
|
||||
pub device: wgpu::Device,
|
||||
|
@ -95,6 +96,7 @@ pub struct WgpuRenderBackend<T: RenderTarget> {
|
|||
quad_vbo: wgpu::Buffer,
|
||||
quad_ibo: wgpu::Buffer,
|
||||
quad_tex_transforms: wgpu::Buffer,
|
||||
bitmap_registry: HashMap<CharacterId, Bitmap>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Enum)]
|
||||
|
@ -269,6 +271,7 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
|||
quad_vbo,
|
||||
quad_ibo,
|
||||
quad_tex_transforms,
|
||||
bitmap_registry: HashMap::new(),
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -684,6 +687,8 @@ impl<T: RenderTarget> WgpuRenderBackend<T> {
|
|||
bitmap: Bitmap,
|
||||
debug_str: &str,
|
||||
) -> BitmapInfo {
|
||||
self.bitmap_registry.insert(id, bitmap.clone());
|
||||
|
||||
let extent = wgpu::Extent3d {
|
||||
width: bitmap.width,
|
||||
height: bitmap.height,
|
||||
|
@ -1489,6 +1494,38 @@ impl<T: RenderTarget + 'static> RenderBackend for WgpuRenderBackend<T> {
|
|||
MaskState::DrawMaskedContent
|
||||
};
|
||||
}
|
||||
|
||||
fn get_bitmap_pixels(&mut self, bitmap: BitmapHandle) -> (u32, u32, Vec<u32>) {
|
||||
if let Some((id, _texture)) = self.textures.get(bitmap.0) {
|
||||
if let Some(bitmap) = self.bitmap_registry.get(id) {
|
||||
let data = match &bitmap.data {
|
||||
BitmapFormat::Rgb(x) => {
|
||||
x.chunks_exact(3).map(|chunk| {
|
||||
let r = chunk[0];
|
||||
let g = chunk[1];
|
||||
let b = chunk[2];
|
||||
(0xFF << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
|
||||
}).collect()
|
||||
}
|
||||
BitmapFormat::Rgba(x) => {
|
||||
x.chunks_exact(4).map(|chunk| {
|
||||
let r = chunk[0];
|
||||
let g = chunk[1];
|
||||
let b = chunk[2];
|
||||
//TODO: check this order, assuming because rgb_a
|
||||
let a = chunk[3];
|
||||
((a as u32) << 24) | ((r as u32) << 16) | ((g as u32) << 8) | (b as u32)
|
||||
}).collect()
|
||||
}
|
||||
};
|
||||
(bitmap.width, bitmap.height, data)
|
||||
} else {
|
||||
(0, 0, vec![])
|
||||
}
|
||||
} else {
|
||||
(0, 0, vec![])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_quad_buffers(device: &wgpu::Device) -> (wgpu::Buffer, wgpu::Buffer, wgpu::Buffer) {
|
||||
|
|
Loading…
Reference in New Issue