avm2: Implement Bitmap.pixelSnapping
This commit is contained in:
parent
289f73c85f
commit
4410d666ed
|
@ -6,12 +6,14 @@ use crate::avm2::globals::flash::display::display_object::initialize_for_allocat
|
|||
use crate::avm2::object::{BitmapDataObject, ClassObject, Object, TObject};
|
||||
use crate::avm2::value::Value;
|
||||
use crate::avm2::Error;
|
||||
use ruffle_render::bitmap::PixelSnapping;
|
||||
use ruffle_wstr::WStr;
|
||||
|
||||
use crate::avm2::error::make_error_2008;
|
||||
use crate::avm2::parameters::ParametersExt;
|
||||
use crate::bitmap::bitmap_data::BitmapDataWrapper;
|
||||
use crate::character::Character;
|
||||
use crate::display_object::{Bitmap, TDisplayObject};
|
||||
use crate::{avm2_stub_getter, avm2_stub_setter};
|
||||
|
||||
pub fn bitmap_allocator<'gc>(
|
||||
class: ClassObject<'gc>,
|
||||
|
@ -79,8 +81,9 @@ pub fn init<'gc>(
|
|||
let bitmap_data = args
|
||||
.try_get_object(activation, 0)
|
||||
.and_then(|o| o.as_bitmap_data());
|
||||
//TODO: Pixel snapping is not supported
|
||||
let _pixel_snapping = args.get_string(activation, 1);
|
||||
let Some(pixel_snapping) = PixelSnapping::from_wstr(&args.get_string(activation, 1)?) else {
|
||||
return Err(make_error_2008(activation, "pixelSnapping"));
|
||||
};
|
||||
let smoothing = args.get_bool(2);
|
||||
|
||||
if let Some(bitmap) = this.as_display_object().and_then(|dobj| dobj.as_bitmap()) {
|
||||
|
@ -88,6 +91,7 @@ pub fn init<'gc>(
|
|||
bitmap.set_bitmap_data(&mut activation.context, bitmap_data);
|
||||
}
|
||||
bitmap.set_smoothing(activation.context.gc_context, smoothing);
|
||||
bitmap.set_pixel_snapping(activation.context.gc_context, pixel_snapping);
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
|
@ -138,21 +142,29 @@ pub fn set_bitmap_data<'gc>(
|
|||
|
||||
/// Stub `Bitmap.pixelSnapping`'s getter
|
||||
pub fn get_pixel_snapping<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
_activation: &mut Activation<'_, 'gc>,
|
||||
this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
avm2_stub_getter!(activation, "flash.display.Bitmap", "pixelSnapping");
|
||||
Ok("auto".into())
|
||||
if let Some(bitmap) = this.as_display_object().and_then(|dobj| dobj.as_bitmap()) {
|
||||
let value: &WStr = bitmap.pixel_snapping().into();
|
||||
return Ok(Value::String(value.into()));
|
||||
}
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
/// Stub `Bitmap.pixelSnapping`'s setter
|
||||
pub fn set_pixel_snapping<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
_args: &[Value<'gc>],
|
||||
this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
avm2_stub_setter!(activation, "flash.display.Bitmap", "pixelSnapping");
|
||||
if let Some(bitmap) = this.as_display_object().and_then(|dobj| dobj.as_bitmap()) {
|
||||
let Some(value) = PixelSnapping::from_wstr(&args.get_string(activation, 0)?) else {
|
||||
return Err(make_error_2008(activation, "pixelSnapping"));
|
||||
};
|
||||
bitmap.set_pixel_snapping(activation.context.gc_context, value);
|
||||
}
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
|
|
|
@ -174,6 +174,14 @@ impl<'gc> Bitmap<'gc> {
|
|||
self.0.read().height as u16
|
||||
}
|
||||
|
||||
pub fn pixel_snapping(self) -> PixelSnapping {
|
||||
self.0.read().pixel_snapping
|
||||
}
|
||||
|
||||
pub fn set_pixel_snapping(self, mc: MutationContext<'gc, '_>, value: PixelSnapping) {
|
||||
self.0.write(mc).pixel_snapping = value;
|
||||
}
|
||||
|
||||
pub fn bitmap_data_wrapper(self) -> BitmapDataWrapper<'gc> {
|
||||
self.0.read().bitmap_data
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ use std::fmt::Debug;
|
|||
use std::sync::Arc;
|
||||
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
use ruffle_wstr::WStr;
|
||||
use swf::{Rectangle, Twips};
|
||||
|
||||
use crate::backend::RenderBackend;
|
||||
|
@ -67,7 +68,29 @@ pub enum PixelSnapping {
|
|||
Never,
|
||||
}
|
||||
|
||||
impl From<PixelSnapping> for &'static WStr {
|
||||
fn from(value: PixelSnapping) -> &'static WStr {
|
||||
match value {
|
||||
PixelSnapping::Always => WStr::from_units(b"always"),
|
||||
PixelSnapping::Auto => WStr::from_units(b"auto"),
|
||||
PixelSnapping::Never => WStr::from_units(b"never"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PixelSnapping {
|
||||
pub fn from_wstr(str: &WStr) -> Option<Self> {
|
||||
if str == b"always" {
|
||||
Some(PixelSnapping::Always)
|
||||
} else if str == b"auto" {
|
||||
Some(PixelSnapping::Auto)
|
||||
} else if str == b"never" {
|
||||
Some(PixelSnapping::Never)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn apply(&self, matrix: &mut Matrix) {
|
||||
match self {
|
||||
PixelSnapping::Always => {
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package {
|
||||
|
||||
import flash.display.MovieClip;
|
||||
import flash.display.Bitmap;
|
||||
import flash.display.PixelSnapping;
|
||||
|
||||
|
||||
public class Test extends MovieClip {
|
||||
|
||||
|
||||
public function Test() {
|
||||
addTest(PixelSnapping.NEVER, 1.0);
|
||||
addTest(PixelSnapping.ALWAYS, 1.0);
|
||||
addTest(PixelSnapping.AUTO, 1.0);
|
||||
|
||||
addTest(PixelSnapping.NEVER, 0.99);
|
||||
addTest(PixelSnapping.ALWAYS, 0.99);
|
||||
addTest(PixelSnapping.AUTO, 0.99);
|
||||
|
||||
addTest(PixelSnapping.NEVER, 1.01);
|
||||
addTest(PixelSnapping.ALWAYS, 1.01);
|
||||
addTest(PixelSnapping.AUTO, 1.01);
|
||||
|
||||
addTest(PixelSnapping.NEVER, 2.0);
|
||||
addTest(PixelSnapping.ALWAYS, 2.0);
|
||||
addTest(PixelSnapping.AUTO, 2.0);
|
||||
|
||||
addTest(PixelSnapping.NEVER, 2.5);
|
||||
addTest(PixelSnapping.ALWAYS, 2.5);
|
||||
addTest(PixelSnapping.AUTO, 2.5);
|
||||
|
||||
try {
|
||||
var bitmap = new Bitmap(new TestImage());
|
||||
bitmap.pixelSnapping = "test";
|
||||
} catch (err) {
|
||||
trace(err);
|
||||
}
|
||||
|
||||
try {
|
||||
var bitmap = new Bitmap(new TestImage(), "test");
|
||||
} catch (err) {
|
||||
trace(err);
|
||||
}
|
||||
}
|
||||
|
||||
function addTest(snapping: String, scale: Number) {
|
||||
var bitmap = new Bitmap(new TestImage());
|
||||
bitmap.pixelSnapping = snapping;
|
||||
bitmap.x = (numChildren % 3 * 100) + 10.5;
|
||||
bitmap.y = (Math.floor(numChildren / 3) * 100) + 10.5;
|
||||
bitmap.width *= scale;
|
||||
bitmap.height *= scale;
|
||||
addChild(bitmap);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
|
@ -0,0 +1,2 @@
|
|||
ArgumentError: Error #2008: Parameter pixelSnapping must be one of the accepted values.
|
||||
ArgumentError: Error #2008: Parameter pixelSnapping must be one of the accepted values.
|
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
Binary file not shown.
|
@ -0,0 +1,8 @@
|
|||
num_frames = 1
|
||||
ignore = true # big differences across rendering backends :(
|
||||
|
||||
[image_comparison]
|
||||
tolerance = 0
|
||||
|
||||
[player_options]
|
||||
with_renderer = { optional = false, sample_count = 1 }
|
Loading…
Reference in New Issue