From 1bd9f824968fa1bc20c04e0387102d7f4f7204ba Mon Sep 17 00:00:00 2001 From: iwannabethedev Date: Tue, 9 May 2023 05:52:01 +0200 Subject: [PATCH] core: Implements `BitmapData.pixelDissolve()` for AVM2. The changes have automated tests for them. The implementation has not been implemented or tested for AVM1 yet. --- .../avm2/globals/flash/display/BitmapData.as | 4 + .../avm2/globals/flash/display/bitmap_data.rs | 89 +- core/src/bitmap/operations.rs | 242 ++++ .../avm2/bitmapdata_pixeldissolve/output.txt | 1037 +++++++++++++++++ .../avm2/bitmapdata_pixeldissolve/test.as | 255 ++++ .../avm2/bitmapdata_pixeldissolve/test.swf | Bin 0 -> 2766 bytes .../avm2/bitmapdata_pixeldissolve/test.toml | 1 + .../expected.png | Bin 0 -> 9684 bytes .../bitmapdata_pixeldissolve_image/output.txt | 0 .../bitmapdata_pixeldissolve_image/test.as | 121 ++ .../bitmapdata_pixeldissolve_image/test.swf | Bin 0 -> 2074 bytes .../bitmapdata_pixeldissolve_image/test.toml | 7 + 12 files changed, 1751 insertions(+), 5 deletions(-) create mode 100644 tests/tests/swfs/avm2/bitmapdata_pixeldissolve/output.txt create mode 100644 tests/tests/swfs/avm2/bitmapdata_pixeldissolve/test.as create mode 100644 tests/tests/swfs/avm2/bitmapdata_pixeldissolve/test.swf create mode 100644 tests/tests/swfs/avm2/bitmapdata_pixeldissolve/test.toml create mode 100644 tests/tests/swfs/avm2/bitmapdata_pixeldissolve_image/expected.png create mode 100644 tests/tests/swfs/avm2/bitmapdata_pixeldissolve_image/output.txt create mode 100644 tests/tests/swfs/avm2/bitmapdata_pixeldissolve_image/test.as create mode 100644 tests/tests/swfs/avm2/bitmapdata_pixeldissolve_image/test.swf create mode 100644 tests/tests/swfs/avm2/bitmapdata_pixeldissolve_image/test.toml diff --git a/core/src/avm2/globals/flash/display/BitmapData.as b/core/src/avm2/globals/flash/display/BitmapData.as index 513dbbc24..d491eb441 100644 --- a/core/src/avm2/globals/flash/display/BitmapData.as +++ b/core/src/avm2/globals/flash/display/BitmapData.as @@ -61,6 +61,10 @@ package flash.display { sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, operation:String, threshold:uint, color:uint = 0, mask:uint = 0xFFFFFFFF, copySource:Boolean = false ):uint; public native function compare(otherBitmapData:BitmapData):Object; + public native function pixelDissolve( + sourceBitmapData:BitmapData, sourceRect:Rectangle, destPoint:Point, randomSeed:int = 0, numPixels:int = 0, + fillColor:uint = 0 + ):int; public function generateFilterRect(sourceRect:Rectangle, filter:BitmapFilter):Rectangle { stub_method("flash.display.BitmapData", "generateFilterRect"); diff --git a/core/src/avm2/globals/flash/display/bitmap_data.rs b/core/src/avm2/globals/flash/display/bitmap_data.rs index aa310eedf..4314663d5 100644 --- a/core/src/avm2/globals/flash/display/bitmap_data.rs +++ b/core/src/avm2/globals/flash/display/bitmap_data.rs @@ -1,7 +1,7 @@ //! `flash.display.BitmapData` builtin/prototype use crate::avm2::activation::Activation; -use crate::avm2::error::{argument_error, make_error_2008}; +use crate::avm2::error::{argument_error, make_error_2008, range_error}; use crate::avm2::filters::FilterAvm2Ext; use crate::avm2::object::{BitmapDataObject, ByteArrayObject, Object, TObject, VectorObject}; use crate::avm2::value::Value; @@ -1050,7 +1050,7 @@ pub fn apply_filter<'gc>( source_rect.width().to_pixels().ceil() as u32, source_rect.height().to_pixels().ceil() as u32, ); - let dest_point = args.get_object(activation, 2, "dstPoint")?; + let dest_point = args.get_object(activation, 2, "destPoint")?; let dest_point = ( dest_point .get_public_property("x", activation)? @@ -1123,7 +1123,7 @@ pub fn palette_map<'gc>( source_rect.width().to_pixels().ceil() as i32, source_rect.height().to_pixels().ceil() as i32, ); - let dest_point = args.get_object(activation, 2, "dstPoint")?; + let dest_point = args.get_object(activation, 2, "destPoint")?; let dest_point = ( dest_point .get_public_property("x", activation)? @@ -1239,7 +1239,7 @@ pub fn threshold<'gc>( if !bitmap_data.disposed() { let src_bitmap = args.get_object(activation, 0, "sourceBitmapData")?; let source_rect = args.get_object(activation, 1, "sourceRect")?; - let dest_point = args.get_object(activation, 2, "dstPoint")?; + let dest_point = args.get_object(activation, 2, "destPoint")?; let dest_point = ( dest_point .get_public_property("x", activation)? @@ -1336,11 +1336,15 @@ pub fn compare<'gc>( { other_bitmap_data } else { - // The documentation says that -1 should be returned here, but -2 is actually returned. + // The documentation for AVM1 says that -1 should be returned here, + // but -2 is actually returned. + // TODO: Has this been tested for AVM2? return Ok(BITMAP_DISPOSED.into()); }; other_bitmap_data.check_valid(activation)?; + // TODO: Given the above check with `other_bitmap_data.check_valid`, this branch will + // presumably never get executed. if other_bitmap_data.disposed() { return Ok(BITMAP_DISPOSED.into()); } @@ -1369,3 +1373,78 @@ pub fn compare<'gc>( None => Ok(EQUIVALENT.into()), } } + +/// Implements `BitmapData.pixelDissolve`. +pub fn pixel_dissolve<'gc>( + activation: &mut Activation<'_, 'gc>, + this: Option>, + args: &[Value<'gc>], +) -> Result, Error<'gc>> { + if let Some(bitmap_data) = this.and_then(|t| t.as_bitmap_data()) { + bitmap_data.check_valid(activation)?; + + let src_bitmap_data = args.get_object(activation, 0, "sourceBitmapData")?; + + let source_rect = args.get_object(activation, 1, "sourceRect")?; + + // TODO: `BitmapData.pixelDissolve() might be called frequently. Is this performant, + // and if not, is there a faster alternative? + let src_min_x = source_rect + .get_public_property("x", activation)? + .coerce_to_i32(activation)?; + let src_min_y = source_rect + .get_public_property("y", activation)? + .coerce_to_i32(activation)?; + let src_width = source_rect + .get_public_property("width", activation)? + .coerce_to_i32(activation)?; + let src_height = source_rect + .get_public_property("height", activation)? + .coerce_to_i32(activation)?; + + let dest_point = args.get_object(activation, 2, "destPoint")?; + let dest_point = ( + dest_point + .get_public_property("x", activation)? + .coerce_to_i32(activation)?, + dest_point + .get_public_property("y", activation)? + .coerce_to_i32(activation)?, + ); + + let random_seed = args.get_i32(activation, 3)?; + + let num_pixels = args.get_i32(activation, 4)?; + if num_pixels < 0 { + return Err(Error::AvmError(range_error( + activation, + &format!("Parameter numPixels must be a non-negative number; got {num_pixels}."), + 2027, + )?)); + } + + let fill_color = args.get_i32(activation, 5)?; + + // Apparently, if this check fails, a type error for `null` is given. + if let Some(src_bitmap_data) = src_bitmap_data.as_bitmap_data() { + src_bitmap_data.check_valid(activation)?; + + return Ok(operations::pixel_dissolve( + activation.context.gc_context, + bitmap_data, + src_bitmap_data, + (src_min_x, src_min_y, src_width, src_height), + dest_point, + random_seed, + num_pixels, + fill_color, + ) + .into()); + } + } + + // TODO: Should it always return `Ok(Value::Undefined)` in this case? + // Can this even be tested for? + + Ok(Value::Undefined) +} diff --git a/core/src/bitmap/operations.rs b/core/src/bitmap/operations.rs index bbfd09fac..6b9832c35 100644 --- a/core/src/bitmap/operations.rs +++ b/core/src/bitmap/operations.rs @@ -14,6 +14,7 @@ use ruffle_render::filters::Filter; use ruffle_render::matrix::Matrix; use ruffle_render::quality::StageQuality; use ruffle_render::transform::Transform; +use std::cell::{Ref, RefMut}; use swf::{BlendMode, ColorTransform, Fixed8, Rectangle, Twips}; /// AVM1 and AVM2 have a shared set of operations they can perform on BitmapDatas. @@ -1616,3 +1617,244 @@ pub fn set_pixels_from_byte_array<'gc>( Ok(()) } + +/// Returns at least 2. Always returns an even number. +fn get_feistel_block_size(sequence_length: u32) -> u32 { + let sequence_length = sequence_length.max(2); + + // For the given sequence length, figure out the number of bits required to + // represent all indices for the sequence. After that, round up to + // the nearest even number of bits. + // For instance, for a sequence of length 9, 4 bits are required, + // and 4 is even, so the result is 4. + // For a sequence of length 8, 3 bits are required, but 3 is not + // even, so round up to 4. + + let mut bit_number: u32 = 0; + let mut num = sequence_length - 1; + + while num > 0 { + num /= 2; + bit_number += 1; + } + + bit_number + (bit_number % 2) +} + +/// Meant to be a bijective function that takes a raw index and gives the corresponding +/// Feistel index. +/// +/// # Arguments +/// +/// * `raw_permutation_index` - Must obey '0 <= permutation_raw_index < permutation_length`. +/// * `feistel_block_size` - See `get_feistel_block_size()`. +fn pixel_dissolve_raw_to_feistel_index(raw_permutation_index: u32, feistel_block_size: u32) -> u32 { + // Discussion on Feistel networks: + // https://github.com/ruffle-rs/ruffle/issues/10962 + + // For the simple balanced variant of a Feistel network, an even number of + // bits for the block size is required (unbalanced Feistel networks + // also exists, but are presumably more complex). + + // Applying a single round of Feistel. + + let feistel_halfpiece_size = feistel_block_size / 2; + + let halfpiece1 = raw_permutation_index >> feistel_halfpiece_size; + let halfpiece2 = raw_permutation_index & ((1 << feistel_halfpiece_size) - 1); + + // Apply some function to make the output appear more random. + // TODO: Apply some decent but fast PRNG? Or at least some better and less non-random-looking + // function? Can also take `feistel_block_size` as an argument. + // This specific function was gotten by trial-and-error on what might make the output look + // random. + fn f(num: u32) -> u32 { + num * num + 1 + } + let result_before_xor = (f(halfpiece2)) % (1 << feistel_halfpiece_size); + + let new_halfpiece1 = halfpiece2; + let new_halfpiece2 = halfpiece1 ^ result_before_xor; + + (new_halfpiece2 << feistel_halfpiece_size) | new_halfpiece1 +} + +#[allow(clippy::too_many_arguments)] +pub fn pixel_dissolve<'gc>( + mc: MutationContext<'gc, '_>, + target: BitmapDataWrapper<'gc>, + source_bitmap: BitmapDataWrapper<'gc>, + src_rect: (i32, i32, i32, i32), + dest_point: (i32, i32), + random_seed: i32, + num_pixels: i32, + fill_color: i32, +) -> i32 { + // TODO: What should happen in AVM1 when `num_pixels` is negative? + + // Apparently, + // "numPixels:int (default = 0) — The default is 1/30 of the source area (width x height). " + // is wrong. + + // TODO: Ensure that the AVM1 version returns -1 (probably in the AVM1 interface layer) + // when: + // "Calls to any method or property of a BitmapData object fail if the BitmapData object is + // invalid (for example, if it has height == 0 and width == 0), + // and upon failing those properties and methods that return Number values return -1. ". + + // Extract points and areas. + + let (src_min_x, src_min_y, src_width, src_height) = src_rect; + + let src_width = src_width.max(0); + let src_height = src_height.max(0); + + if src_width == 0 || src_height == 0 { + return 0; + } + + let (dest_min_x, dest_min_y) = dest_point; + + let transparency = target.transparency(); + + let mut source_region = + PixelRegion::for_whole_size(source_bitmap.width(), source_bitmap.height()); + let mut dest_region = PixelRegion::for_whole_size(target.width(), target.height()); + dest_region.clamp_with_intersection( + (dest_min_x, dest_min_y), + (src_min_x, src_min_y), + (src_width, src_height), + &mut source_region, + ); + + if dest_region.width() == 0 || dest_region.height() == 0 { + return 0; + } + + let write_offset = (dest_region.x_min, dest_region.y_min); + let read_offset = (source_region.x_min, source_region.y_min); + + fn write_pixel( + write: &mut RefMut, + different_source_than_target: &Option>, + fill_color: i32, + transparency: bool, + base_point: (u32, u32), + read_offset: (u32, u32), + write_offset: (u32, u32), + ) { + let read_point = (read_offset.0 + base_point.0, read_offset.1 + base_point.1); + let write_point = (write_offset.0 + base_point.0, write_offset.1 + base_point.1); + + match different_source_than_target { + None => { + write.set_pixel32_raw( + write_point.0, + write_point.1, + Color::from(fill_color).to_premultiplied_alpha(transparency), + ); + } + Some(different_source) => { + write.set_pixel32_raw( + write_point.0, + write_point.1, + different_source.get_pixel32_raw(read_point.0, read_point.1), + ); + } + } + } + + let different_source_than_target = if source_bitmap.ptr_eq(target) { + None + } else { + Some(source_bitmap.read_area(source_region)) + }; + + let final_pixel_sequence_length = dest_region.width() * dest_region.height(); + + let num_pixels = num_pixels.min(final_pixel_sequence_length as i32); + + // TODO: Should this be `target.sync()`? Or something else? + let target = target.sync(); + + let mut write = target.write(mc); + + // For compliance with the official Flash Player, we always write the pixel at (0, 0). + write_pixel( + &mut write, + &different_source_than_target, + fill_color, + transparency, + (0, 0), + read_offset, + write_offset, + ); + + let feistel_block_size: u32 = get_feistel_block_size(final_pixel_sequence_length); + let permutation_length = 1 << feistel_block_size; + // Raw permutation index. + let mut raw_perm_index = (random_seed % (permutation_length as i32)) as u32; + + for _ in 0..num_pixels { + // Feistel permutation index. + let mut feistel_perm_index = 0; + + // Safety mechanism, in case there is a bug in the implementation. + let mut loop_counter = 0; + + // Find a valid index to write to. + // Since the pixel at (0, 0) is always written, we always skip `feistel_perm_index == 0`. + while (feistel_perm_index == 0 || feistel_perm_index >= final_pixel_sequence_length) + && final_pixel_sequence_length != 1 + { + raw_perm_index = (raw_perm_index + 1) % permutation_length; + + feistel_perm_index = + pixel_dissolve_raw_to_feistel_index(raw_perm_index, feistel_block_size); + + loop_counter += 1; + + if loop_counter > permutation_length + 2 { + // TODO: Is this the correct way to panic or error? + panic!( + "operations::pixel_dissolve() failed:\n\ + Using Feistel network permutations:\n\ + `raw_perm_index`: {raw_perm_index}\n\ + `feistel_perm_index`: {feistel_perm_index}\n\ + `permutation_length`: {permutation_length}\n\ + `final_pixel_sequence_length`: {final_pixel_sequence_length}\n\ + `src_rect`: {}, {}, {}, {}\n\ + `dest_region`: {}, {}, {}, {}\n\ + `dest_point`: {}, {}.", + src_min_x, + src_min_y, + src_width, + src_height, + dest_region.x_min, + dest_region.y_min, + dest_region.x_max, + dest_region.y_max, + dest_point.0, + dest_point.1 + ); + } + } + + let base_point = ( + feistel_perm_index % dest_region.width(), + feistel_perm_index / dest_region.width(), + ); + + write_pixel( + &mut write, + &different_source_than_target, + fill_color, + transparency, + base_point, + read_offset, + write_offset, + ); + } + + raw_perm_index as i32 +} diff --git a/tests/tests/swfs/avm2/bitmapdata_pixeldissolve/output.txt b/tests/tests/swfs/avm2/bitmapdata_pixeldissolve/output.txt new file mode 100644 index 000000000..bbd67ac6a --- /dev/null +++ b/tests/tests/swfs/avm2/bitmapdata_pixeldissolve/output.txt @@ -0,0 +1,1037 @@ +------------------------------------------ +Basic test. + +Dissolving for 100 rounds, with data: width: 10, height: 10, sourceRect: [own], destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 25 +(25) Overwritten pixel count: 26 +(26) Overwritten pixel count: 27 +(27) Overwritten pixel count: 28 +(28) Overwritten pixel count: 29 +(29) Overwritten pixel count: 30 +(30) Overwritten pixel count: 31 +(31) Overwritten pixel count: 32 +(32) Overwritten pixel count: 33 +(33) Overwritten pixel count: 34 +(34) Overwritten pixel count: 35 +(35) Overwritten pixel count: 36 +(36) Overwritten pixel count: 37 +(37) Overwritten pixel count: 38 +(38) Overwritten pixel count: 39 +(39) Overwritten pixel count: 40 +(40) Overwritten pixel count: 41 +(41) Overwritten pixel count: 42 +(42) Overwritten pixel count: 43 +(43) Overwritten pixel count: 44 +(44) Overwritten pixel count: 45 +(45) Overwritten pixel count: 46 +(46) Overwritten pixel count: 47 +(47) Overwritten pixel count: 48 +(48) Overwritten pixel count: 49 +(49) Overwritten pixel count: 50 +(50) Overwritten pixel count: 51 +(51) Overwritten pixel count: 52 +(52) Overwritten pixel count: 53 +(53) Overwritten pixel count: 54 +(54) Overwritten pixel count: 55 +(55) Overwritten pixel count: 56 +(56) Overwritten pixel count: 57 +(57) Overwritten pixel count: 58 +(58) Overwritten pixel count: 59 +(59) Overwritten pixel count: 60 +(60) Overwritten pixel count: 61 +(61) Overwritten pixel count: 62 +(62) Overwritten pixel count: 63 +(63) Overwritten pixel count: 64 +(64) Overwritten pixel count: 65 +(65) Overwritten pixel count: 66 +(66) Overwritten pixel count: 67 +(67) Overwritten pixel count: 68 +(68) Overwritten pixel count: 69 +(69) Overwritten pixel count: 70 +(70) Overwritten pixel count: 71 +(71) Overwritten pixel count: 72 +(72) Overwritten pixel count: 73 +(73) Overwritten pixel count: 74 +(74) Overwritten pixel count: 75 +(75) Overwritten pixel count: 76 +(76) Overwritten pixel count: 77 +(77) Overwritten pixel count: 78 +(78) Overwritten pixel count: 79 +(79) Overwritten pixel count: 80 +(80) Overwritten pixel count: 81 +(81) Overwritten pixel count: 82 +(82) Overwritten pixel count: 83 +(83) Overwritten pixel count: 84 +(84) Overwritten pixel count: 85 +(85) Overwritten pixel count: 86 +(86) Overwritten pixel count: 87 +(87) Overwritten pixel count: 88 +(88) Overwritten pixel count: 89 +(89) Overwritten pixel count: 90 +(90) Overwritten pixel count: 91 +(91) Overwritten pixel count: 92 +(92) Overwritten pixel count: 93 +(93) Overwritten pixel count: 94 +(94) Overwritten pixel count: 95 +(95) Overwritten pixel count: 96 +(96) Overwritten pixel count: 97 +(97) Overwritten pixel count: 98 +(98) Overwritten pixel count: 99 +(99) Overwritten pixel count: 100 +(100) Overwritten pixel count: 100 + + + +------------------------------------------ +`numPixels`. + +Dissolving for 4 rounds, with data: width: 10, height: 10, sourceRect: [own], destPoint: (x=0, y=0), numPixels: 0 +(1) Overwritten pixel count: 1 +(2) Overwritten pixel count: 1 +(3) Overwritten pixel count: 1 +(4) Overwritten pixel count: 1 + +Dissolving for 4 rounds, with data: width: 10, height: 10, sourceRect: [own], destPoint: (x=0, y=0), numPixels: -1 +Negative `numPixels` should error. +Dissolving for 35 rounds, with data: width: 10, height: 10, sourceRect: [own], destPoint: (x=0, y=0), numPixels: 3 +(1) Overwritten pixel count: 4 +(2) Overwritten pixel count: 7 +(3) Overwritten pixel count: 10 +(4) Overwritten pixel count: 13 +(5) Overwritten pixel count: 16 +(6) Overwritten pixel count: 19 +(7) Overwritten pixel count: 22 +(8) Overwritten pixel count: 25 +(9) Overwritten pixel count: 28 +(10) Overwritten pixel count: 31 +(11) Overwritten pixel count: 34 +(12) Overwritten pixel count: 37 +(13) Overwritten pixel count: 40 +(14) Overwritten pixel count: 43 +(15) Overwritten pixel count: 46 +(16) Overwritten pixel count: 49 +(17) Overwritten pixel count: 52 +(18) Overwritten pixel count: 55 +(19) Overwritten pixel count: 58 +(20) Overwritten pixel count: 61 +(21) Overwritten pixel count: 64 +(22) Overwritten pixel count: 67 +(23) Overwritten pixel count: 70 +(24) Overwritten pixel count: 73 +(25) Overwritten pixel count: 76 +(26) Overwritten pixel count: 79 +(27) Overwritten pixel count: 82 +(28) Overwritten pixel count: 85 +(29) Overwritten pixel count: 88 +(30) Overwritten pixel count: 91 +(31) Overwritten pixel count: 94 +(32) Overwritten pixel count: 97 +(33) Overwritten pixel count: 100 +(34) Overwritten pixel count: 100 +(35) Overwritten pixel count: 100 + + + +------------------------------------------ +Dimensions. + +Dissolving for 61 rounds, with data: width: 150, height: 2, sourceRect: [own], destPoint: (x=0, y=0), numPixels: 5 +(1) Overwritten pixel count: 6 +(2) Overwritten pixel count: 11 +(3) Overwritten pixel count: 16 +(4) Overwritten pixel count: 21 +(5) Overwritten pixel count: 26 +(6) Overwritten pixel count: 31 +(7) Overwritten pixel count: 36 +(8) Overwritten pixel count: 41 +(9) Overwritten pixel count: 46 +(10) Overwritten pixel count: 51 +(11) Overwritten pixel count: 56 +(12) Overwritten pixel count: 61 +(13) Overwritten pixel count: 66 +(14) Overwritten pixel count: 71 +(15) Overwritten pixel count: 76 +(16) Overwritten pixel count: 81 +(17) Overwritten pixel count: 86 +(18) Overwritten pixel count: 91 +(19) Overwritten pixel count: 96 +(20) Overwritten pixel count: 101 +(21) Overwritten pixel count: 106 +(22) Overwritten pixel count: 111 +(23) Overwritten pixel count: 116 +(24) Overwritten pixel count: 121 +(25) Overwritten pixel count: 126 +(26) Overwritten pixel count: 131 +(27) Overwritten pixel count: 136 +(28) Overwritten pixel count: 141 +(29) Overwritten pixel count: 146 +(30) Overwritten pixel count: 151 +(31) Overwritten pixel count: 156 +(32) Overwritten pixel count: 161 +(33) Overwritten pixel count: 166 +(34) Overwritten pixel count: 171 +(35) Overwritten pixel count: 176 +(36) Overwritten pixel count: 181 +(37) Overwritten pixel count: 186 +(38) Overwritten pixel count: 191 +(39) Overwritten pixel count: 196 +(40) Overwritten pixel count: 201 +(41) Overwritten pixel count: 206 +(42) Overwritten pixel count: 211 +(43) Overwritten pixel count: 216 +(44) Overwritten pixel count: 221 +(45) Overwritten pixel count: 226 +(46) Overwritten pixel count: 231 +(47) Overwritten pixel count: 236 +(48) Overwritten pixel count: 241 +(49) Overwritten pixel count: 246 +(50) Overwritten pixel count: 251 +(51) Overwritten pixel count: 256 +(52) Overwritten pixel count: 261 +(53) Overwritten pixel count: 266 +(54) Overwritten pixel count: 271 +(55) Overwritten pixel count: 276 +(56) Overwritten pixel count: 281 +(57) Overwritten pixel count: 286 +(58) Overwritten pixel count: 291 +(59) Overwritten pixel count: 296 +(60) Overwritten pixel count: 300 +(61) Overwritten pixel count: 300 + +Dissolving for 61 rounds, with data: width: 2, height: 150, sourceRect: [own], destPoint: (x=0, y=0), numPixels: 5 +(1) Overwritten pixel count: 6 +(2) Overwritten pixel count: 11 +(3) Overwritten pixel count: 16 +(4) Overwritten pixel count: 21 +(5) Overwritten pixel count: 26 +(6) Overwritten pixel count: 31 +(7) Overwritten pixel count: 36 +(8) Overwritten pixel count: 41 +(9) Overwritten pixel count: 46 +(10) Overwritten pixel count: 51 +(11) Overwritten pixel count: 56 +(12) Overwritten pixel count: 61 +(13) Overwritten pixel count: 66 +(14) Overwritten pixel count: 71 +(15) Overwritten pixel count: 76 +(16) Overwritten pixel count: 81 +(17) Overwritten pixel count: 86 +(18) Overwritten pixel count: 91 +(19) Overwritten pixel count: 96 +(20) Overwritten pixel count: 101 +(21) Overwritten pixel count: 106 +(22) Overwritten pixel count: 111 +(23) Overwritten pixel count: 116 +(24) Overwritten pixel count: 121 +(25) Overwritten pixel count: 126 +(26) Overwritten pixel count: 131 +(27) Overwritten pixel count: 136 +(28) Overwritten pixel count: 141 +(29) Overwritten pixel count: 146 +(30) Overwritten pixel count: 151 +(31) Overwritten pixel count: 156 +(32) Overwritten pixel count: 161 +(33) Overwritten pixel count: 166 +(34) Overwritten pixel count: 171 +(35) Overwritten pixel count: 176 +(36) Overwritten pixel count: 181 +(37) Overwritten pixel count: 186 +(38) Overwritten pixel count: 191 +(39) Overwritten pixel count: 196 +(40) Overwritten pixel count: 201 +(41) Overwritten pixel count: 206 +(42) Overwritten pixel count: 211 +(43) Overwritten pixel count: 216 +(44) Overwritten pixel count: 221 +(45) Overwritten pixel count: 226 +(46) Overwritten pixel count: 231 +(47) Overwritten pixel count: 236 +(48) Overwritten pixel count: 241 +(49) Overwritten pixel count: 246 +(50) Overwritten pixel count: 251 +(51) Overwritten pixel count: 256 +(52) Overwritten pixel count: 261 +(53) Overwritten pixel count: 266 +(54) Overwritten pixel count: 271 +(55) Overwritten pixel count: 276 +(56) Overwritten pixel count: 281 +(57) Overwritten pixel count: 286 +(58) Overwritten pixel count: 291 +(59) Overwritten pixel count: 296 +(60) Overwritten pixel count: 300 +(61) Overwritten pixel count: 300 + +Dissolving for 66 rounds, with data: width: 8, height: 8, sourceRect: [own], destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 25 +(25) Overwritten pixel count: 26 +(26) Overwritten pixel count: 27 +(27) Overwritten pixel count: 28 +(28) Overwritten pixel count: 29 +(29) Overwritten pixel count: 30 +(30) Overwritten pixel count: 31 +(31) Overwritten pixel count: 32 +(32) Overwritten pixel count: 33 +(33) Overwritten pixel count: 34 +(34) Overwritten pixel count: 35 +(35) Overwritten pixel count: 36 +(36) Overwritten pixel count: 37 +(37) Overwritten pixel count: 38 +(38) Overwritten pixel count: 39 +(39) Overwritten pixel count: 40 +(40) Overwritten pixel count: 41 +(41) Overwritten pixel count: 42 +(42) Overwritten pixel count: 43 +(43) Overwritten pixel count: 44 +(44) Overwritten pixel count: 45 +(45) Overwritten pixel count: 46 +(46) Overwritten pixel count: 47 +(47) Overwritten pixel count: 48 +(48) Overwritten pixel count: 49 +(49) Overwritten pixel count: 50 +(50) Overwritten pixel count: 51 +(51) Overwritten pixel count: 52 +(52) Overwritten pixel count: 53 +(53) Overwritten pixel count: 54 +(54) Overwritten pixel count: 55 +(55) Overwritten pixel count: 56 +(56) Overwritten pixel count: 57 +(57) Overwritten pixel count: 58 +(58) Overwritten pixel count: 59 +(59) Overwritten pixel count: 60 +(60) Overwritten pixel count: 61 +(61) Overwritten pixel count: 62 +(62) Overwritten pixel count: 63 +(63) Overwritten pixel count: 64 +(64) Overwritten pixel count: 64 +(65) Overwritten pixel count: 64 +(66) Overwritten pixel count: 64 + +Dissolving for 66 rounds, with data: width: 7, height: 9, sourceRect: [own], destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 25 +(25) Overwritten pixel count: 26 +(26) Overwritten pixel count: 27 +(27) Overwritten pixel count: 28 +(28) Overwritten pixel count: 29 +(29) Overwritten pixel count: 30 +(30) Overwritten pixel count: 31 +(31) Overwritten pixel count: 32 +(32) Overwritten pixel count: 33 +(33) Overwritten pixel count: 34 +(34) Overwritten pixel count: 35 +(35) Overwritten pixel count: 36 +(36) Overwritten pixel count: 37 +(37) Overwritten pixel count: 38 +(38) Overwritten pixel count: 39 +(39) Overwritten pixel count: 40 +(40) Overwritten pixel count: 41 +(41) Overwritten pixel count: 42 +(42) Overwritten pixel count: 43 +(43) Overwritten pixel count: 44 +(44) Overwritten pixel count: 45 +(45) Overwritten pixel count: 46 +(46) Overwritten pixel count: 47 +(47) Overwritten pixel count: 48 +(48) Overwritten pixel count: 49 +(49) Overwritten pixel count: 50 +(50) Overwritten pixel count: 51 +(51) Overwritten pixel count: 52 +(52) Overwritten pixel count: 53 +(53) Overwritten pixel count: 54 +(54) Overwritten pixel count: 55 +(55) Overwritten pixel count: 56 +(56) Overwritten pixel count: 57 +(57) Overwritten pixel count: 58 +(58) Overwritten pixel count: 59 +(59) Overwritten pixel count: 60 +(60) Overwritten pixel count: 61 +(61) Overwritten pixel count: 62 +(62) Overwritten pixel count: 63 +(63) Overwritten pixel count: 63 +(64) Overwritten pixel count: 63 +(65) Overwritten pixel count: 63 +(66) Overwritten pixel count: 63 + +Dissolving for 66 rounds, with data: width: 5, height: 13, sourceRect: [own], destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 25 +(25) Overwritten pixel count: 26 +(26) Overwritten pixel count: 27 +(27) Overwritten pixel count: 28 +(28) Overwritten pixel count: 29 +(29) Overwritten pixel count: 30 +(30) Overwritten pixel count: 31 +(31) Overwritten pixel count: 32 +(32) Overwritten pixel count: 33 +(33) Overwritten pixel count: 34 +(34) Overwritten pixel count: 35 +(35) Overwritten pixel count: 36 +(36) Overwritten pixel count: 37 +(37) Overwritten pixel count: 38 +(38) Overwritten pixel count: 39 +(39) Overwritten pixel count: 40 +(40) Overwritten pixel count: 41 +(41) Overwritten pixel count: 42 +(42) Overwritten pixel count: 43 +(43) Overwritten pixel count: 44 +(44) Overwritten pixel count: 45 +(45) Overwritten pixel count: 46 +(46) Overwritten pixel count: 47 +(47) Overwritten pixel count: 48 +(48) Overwritten pixel count: 49 +(49) Overwritten pixel count: 50 +(50) Overwritten pixel count: 51 +(51) Overwritten pixel count: 52 +(52) Overwritten pixel count: 53 +(53) Overwritten pixel count: 54 +(54) Overwritten pixel count: 55 +(55) Overwritten pixel count: 56 +(56) Overwritten pixel count: 57 +(57) Overwritten pixel count: 58 +(58) Overwritten pixel count: 59 +(59) Overwritten pixel count: 60 +(60) Overwritten pixel count: 61 +(61) Overwritten pixel count: 62 +(62) Overwritten pixel count: 63 +(63) Overwritten pixel count: 64 +(64) Overwritten pixel count: 65 +(65) Overwritten pixel count: 65 +(66) Overwritten pixel count: 65 + + + +------------------------------------------ +`sourceRect`. + +Dissolving for 101 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=10, h=10), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 25 +(25) Overwritten pixel count: 26 +(26) Overwritten pixel count: 27 +(27) Overwritten pixel count: 28 +(28) Overwritten pixel count: 29 +(29) Overwritten pixel count: 30 +(30) Overwritten pixel count: 31 +(31) Overwritten pixel count: 32 +(32) Overwritten pixel count: 33 +(33) Overwritten pixel count: 34 +(34) Overwritten pixel count: 35 +(35) Overwritten pixel count: 36 +(36) Overwritten pixel count: 37 +(37) Overwritten pixel count: 38 +(38) Overwritten pixel count: 39 +(39) Overwritten pixel count: 40 +(40) Overwritten pixel count: 41 +(41) Overwritten pixel count: 42 +(42) Overwritten pixel count: 43 +(43) Overwritten pixel count: 44 +(44) Overwritten pixel count: 45 +(45) Overwritten pixel count: 46 +(46) Overwritten pixel count: 47 +(47) Overwritten pixel count: 48 +(48) Overwritten pixel count: 49 +(49) Overwritten pixel count: 50 +(50) Overwritten pixel count: 51 +(51) Overwritten pixel count: 52 +(52) Overwritten pixel count: 53 +(53) Overwritten pixel count: 54 +(54) Overwritten pixel count: 55 +(55) Overwritten pixel count: 56 +(56) Overwritten pixel count: 57 +(57) Overwritten pixel count: 58 +(58) Overwritten pixel count: 59 +(59) Overwritten pixel count: 60 +(60) Overwritten pixel count: 61 +(61) Overwritten pixel count: 62 +(62) Overwritten pixel count: 63 +(63) Overwritten pixel count: 64 +(64) Overwritten pixel count: 65 +(65) Overwritten pixel count: 66 +(66) Overwritten pixel count: 67 +(67) Overwritten pixel count: 68 +(68) Overwritten pixel count: 69 +(69) Overwritten pixel count: 70 +(70) Overwritten pixel count: 71 +(71) Overwritten pixel count: 72 +(72) Overwritten pixel count: 73 +(73) Overwritten pixel count: 74 +(74) Overwritten pixel count: 75 +(75) Overwritten pixel count: 76 +(76) Overwritten pixel count: 77 +(77) Overwritten pixel count: 78 +(78) Overwritten pixel count: 79 +(79) Overwritten pixel count: 80 +(80) Overwritten pixel count: 81 +(81) Overwritten pixel count: 82 +(82) Overwritten pixel count: 83 +(83) Overwritten pixel count: 84 +(84) Overwritten pixel count: 85 +(85) Overwritten pixel count: 86 +(86) Overwritten pixel count: 87 +(87) Overwritten pixel count: 88 +(88) Overwritten pixel count: 89 +(89) Overwritten pixel count: 90 +(90) Overwritten pixel count: 91 +(91) Overwritten pixel count: 92 +(92) Overwritten pixel count: 93 +(93) Overwritten pixel count: 94 +(94) Overwritten pixel count: 95 +(95) Overwritten pixel count: 96 +(96) Overwritten pixel count: 97 +(97) Overwritten pixel count: 98 +(98) Overwritten pixel count: 99 +(99) Overwritten pixel count: 100 +(100) Overwritten pixel count: 100 +(101) Overwritten pixel count: 100 + +Dissolving for 20 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=4, h=4), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 16 +(17) Overwritten pixel count: 16 +(18) Overwritten pixel count: 16 +(19) Overwritten pixel count: 16 +(20) Overwritten pixel count: 16 + +Dissolving for 35 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=8, h=4), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 25 +(25) Overwritten pixel count: 26 +(26) Overwritten pixel count: 27 +(27) Overwritten pixel count: 28 +(28) Overwritten pixel count: 29 +(29) Overwritten pixel count: 30 +(30) Overwritten pixel count: 31 +(31) Overwritten pixel count: 32 +(32) Overwritten pixel count: 32 +(33) Overwritten pixel count: 32 +(34) Overwritten pixel count: 32 +(35) Overwritten pixel count: 32 + +Dissolving for 35 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=4, h=8), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 25 +(25) Overwritten pixel count: 26 +(26) Overwritten pixel count: 27 +(27) Overwritten pixel count: 28 +(28) Overwritten pixel count: 29 +(29) Overwritten pixel count: 30 +(30) Overwritten pixel count: 31 +(31) Overwritten pixel count: 32 +(32) Overwritten pixel count: 32 +(33) Overwritten pixel count: 32 +(34) Overwritten pixel count: 32 +(35) Overwritten pixel count: 32 + +Dissolving for 27 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=3, h=8), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 24 +(25) Overwritten pixel count: 24 +(26) Overwritten pixel count: 24 +(27) Overwritten pixel count: 24 + +Dissolving for 31 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=4, h=7), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 25 +(25) Overwritten pixel count: 26 +(26) Overwritten pixel count: 27 +(27) Overwritten pixel count: 28 +(28) Overwritten pixel count: 28 +(29) Overwritten pixel count: 28 +(30) Overwritten pixel count: 28 +(31) Overwritten pixel count: 28 + +Dissolving for 24 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=3, h=7), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 21 +(22) Overwritten pixel count: 21 +(23) Overwritten pixel count: 21 +(24) Overwritten pixel count: 21 + +Dissolving for 30 rounds, with data: width: 10, height: 10, sourceRect: (x=1, y=3, w=4, h=8), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 25 +(25) Overwritten pixel count: 26 +(26) Overwritten pixel count: 27 +(27) Overwritten pixel count: 28 +(28) Overwritten pixel count: 28 +(29) Overwritten pixel count: 28 +(30) Overwritten pixel count: 28 + +Dissolving for 4 rounds, with data: width: 10, height: 10, sourceRect: (x=14, y=3, w=4, h=8), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 0 +(2) Overwritten pixel count: 0 +(3) Overwritten pixel count: 0 +(4) Overwritten pixel count: 0 + +Dissolving for 4 rounds, with data: width: 10, height: 10, sourceRect: (x=3, y=14, w=4, h=8), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 0 +(2) Overwritten pixel count: 0 +(3) Overwritten pixel count: 0 +(4) Overwritten pixel count: 0 + +Dissolving for 25 rounds, with data: width: 10, height: 10, sourceRect: (x=-1, y=3, w=4, h=8), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 21 +(22) Overwritten pixel count: 21 +(23) Overwritten pixel count: 21 +(24) Overwritten pixel count: 21 +(25) Overwritten pixel count: 21 + +Dissolving for 25 rounds, with data: width: 10, height: 10, sourceRect: (x=-1, y=-1, w=4, h=8), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 21 +(22) Overwritten pixel count: 21 +(23) Overwritten pixel count: 21 +(24) Overwritten pixel count: 21 +(25) Overwritten pixel count: 21 + +Dissolving for 30 rounds, with data: width: 10, height: 10, sourceRect: (x=2, y=-1, w=4, h=8), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 19 +(19) Overwritten pixel count: 20 +(20) Overwritten pixel count: 21 +(21) Overwritten pixel count: 22 +(22) Overwritten pixel count: 23 +(23) Overwritten pixel count: 24 +(24) Overwritten pixel count: 25 +(25) Overwritten pixel count: 26 +(26) Overwritten pixel count: 27 +(27) Overwritten pixel count: 28 +(28) Overwritten pixel count: 28 +(29) Overwritten pixel count: 28 +(30) Overwritten pixel count: 28 + +Dissolving for 2 rounds, with data: width: 10, height: 10, sourceRect: (x=1, y=2, w=-1, h=-3), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 0 +(2) Overwritten pixel count: 0 + +Dissolving for 2 rounds, with data: width: 10, height: 10, sourceRect: (x=1, y=2, w=-1, h=3), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 0 +(2) Overwritten pixel count: 0 + +Dissolving for 2 rounds, with data: width: 10, height: 10, sourceRect: (x=1, y=2, w=1, h=-3), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 0 +(2) Overwritten pixel count: 0 + +Dissolving for 2 rounds, with data: width: 10, height: 10, sourceRect: (x=1, y=2, w=0, h=1), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 0 +(2) Overwritten pixel count: 0 + +Dissolving for 2 rounds, with data: width: 10, height: 10, sourceRect: (x=1, y=2, w=1, h=0), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 0 +(2) Overwritten pixel count: 0 + +Dissolving for 2 rounds, with data: width: 10, height: 10, sourceRect: (x=1, y=2, w=0, h=0), destPoint: (x=0, y=0), numPixels: 1 +(1) Overwritten pixel count: 0 +(2) Overwritten pixel count: 0 + +Dissolving for 20 rounds, with data: width: 10, height: 10, sourceRect: null, destPoint: (x=0, y=0), numPixels: 1 +`null` `sourceRect` should error: TypeError: Error #2007: Parameter sourceRect must be non-null. + + +------------------------------------------ +`destPoint`. + +Dissolving for 18 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=3, h=7), destPoint: (x=3, y=5), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 15 +(16) Overwritten pixel count: 15 +(17) Overwritten pixel count: 15 +(18) Overwritten pixel count: 15 + +Dissolving for 15 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=3, h=7), destPoint: (x=-1, y=-1), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 12 +(13) Overwritten pixel count: 12 +(14) Overwritten pixel count: 12 +(15) Overwritten pixel count: 12 + +Dissolving for 3 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=3, h=7), destPoint: (x=-10, y=-10), numPixels: 1 +(1) Overwritten pixel count: 0 +(2) Overwritten pixel count: 0 +(3) Overwritten pixel count: 0 + +Dissolving for 3 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=3, h=7), destPoint: (x=-2, y=10), numPixels: 1 +(1) Overwritten pixel count: 0 +(2) Overwritten pixel count: 0 +(3) Overwritten pixel count: 0 + +Dissolving for 21 rounds, with data: width: 10, height: 10, sourceRect: (x=0, y=0, w=3, h=7), destPoint: (x=5, y=4), numPixels: 1 +(1) Overwritten pixel count: 2 +(2) Overwritten pixel count: 3 +(3) Overwritten pixel count: 4 +(4) Overwritten pixel count: 5 +(5) Overwritten pixel count: 6 +(6) Overwritten pixel count: 7 +(7) Overwritten pixel count: 8 +(8) Overwritten pixel count: 9 +(9) Overwritten pixel count: 10 +(10) Overwritten pixel count: 11 +(11) Overwritten pixel count: 12 +(12) Overwritten pixel count: 13 +(13) Overwritten pixel count: 14 +(14) Overwritten pixel count: 15 +(15) Overwritten pixel count: 16 +(16) Overwritten pixel count: 17 +(17) Overwritten pixel count: 18 +(18) Overwritten pixel count: 18 +(19) Overwritten pixel count: 18 +(20) Overwritten pixel count: 18 +(21) Overwritten pixel count: 18 + + + +------------------------------------------ +Default parameters. + +(0) Overwritten pixel count: 1 + + +------------------------------------------ +`null` `sourceBitmapData`. + +`sourceBitmapData` being `null` should result in error: TypeError: Error #2007: Parameter sourceBitmapData must be non-null. + + +------------------------------------------ +`null` `sourceBitmapData`. + +`sourceBitmapData` being the wrong type should result in error: TypeError: Error #2007: Parameter sourceBitmapData must be non-null. + + +------------------------------------------ +Invalid other bitmap. + +`sourceBitmapData` being disposed() should result in error: ArgumentError: Error #2015: Invalid BitmapData. diff --git a/tests/tests/swfs/avm2/bitmapdata_pixeldissolve/test.as b/tests/tests/swfs/avm2/bitmapdata_pixeldissolve/test.as new file mode 100644 index 000000000..41514e571 --- /dev/null +++ b/tests/tests/swfs/avm2/bitmapdata_pixeldissolve/test.as @@ -0,0 +1,255 @@ + +package +{ + import flash.display.Sprite; + import flash.display.BitmapData; + import flash.display.Bitmap; + import flash.geom.Point; + import flash.geom.Rectangle; + import flash.utils.Timer; + import flash.events.TimerEvent; + + public class test extends Sprite { + + private function countTraceBitmap(bitmap: BitmapData, round: uint, fillColor: uint = 0xFFFF0000): void { + + var count: int = 0; + + var x: int = 0; + while (x < bitmap.width) + { + var y: int = 0; + while (y < bitmap.height) + { + if (bitmap.getPixel32(x, y) == fillColor) { + count += 1; + } + + y += 1; + } + + x += 1; + } + + trace("(" + round + ") Overwritten pixel count: " + count); + } + + private function dissolveOnce(bitmap: BitmapData, rectangle: Rectangle, destPoint: Point, rand: Number, numPixels: Number): Number { + var red:uint = 0xFFFF0000; + var newRand: Number = bitmap.pixelDissolve(bitmap, rectangle, destPoint, rand, numPixels, red); + return newRand; + } + + private function dissolveRounds( + rounds: uint, + width: uint, height: uint, + useBitmapDataOwnRectangle: Boolean, + sourceRect: Rectangle, + destPoint: Point, + numPixels: int + ): void { + + rounds = Math.max(1, rounds); + + var sourceRectString: String = useBitmapDataOwnRectangle ? "sourceRect: [own]" : "sourceRect: " + sourceRect; + + trace("Dissolving for " + rounds + " rounds, with data: width: " + width + ", height: " + height + ", " + sourceRectString + ", destPoint: " + destPoint + ", numPixels: " + numPixels); + + var bmd2:BitmapData = new BitmapData(width, height, false, 0xFFCCCCCC); + + var round:int; + var randNum: Number = 0; + for (round = 1; round <= rounds; round++) + { + randNum = dissolveOnce(bmd2, useBitmapDataOwnRectangle ? bmd2.rect : sourceRect, destPoint, randNum, numPixels); + countTraceBitmap(bmd2, round); + } + + trace(""); + } + + private function dissolveRounds_1( + rounds: uint, + width: uint, height: uint, + numPixels: int + ): void { + dissolveRounds(rounds, width, height, true, null, new Point(0, 0), numPixels); + } + + private function dissolveRounds_2( + rounds: uint, + width: uint, height: uint, + sourceRect: Rectangle, + numPixels: int + ): void { + dissolveRounds(rounds, width, height, false, sourceRect, new Point(0, 0), numPixels); + } + + private function dissolveRounds_3( + rounds: uint, + width: uint, height: uint, + sourceRect: Rectangle, + destPoint: Point, + numPixels: int + ): void { + dissolveRounds(rounds, width, height, false, sourceRect, destPoint, numPixels); + } + + public function test() { + + trace("------------------------------------------"); + trace("Basic test."); + trace(""); + dissolveRounds_1(100, 10, 10, 1); + + trace(""); + trace(""); + trace("------------------------------------------"); + trace("`numPixels`."); + trace(""); + dissolveRounds_1(4, 10, 10, 0); + try { + dissolveRounds_1(4, 10, 10, -1); + } + catch (e:Error) { + trace("Negative `numPixels` should error."); + } + dissolveRounds_1(35, 10, 10, 3); + + trace(""); + trace(""); + trace("------------------------------------------"); + trace("Dimensions."); + trace(""); + // WARNING: Apparently, `width` or `height` being 1 means that nothing is written, + // not even the pixel at (0, 0). This seems like a bug in Flash Player and will + // not necessarily be emulated. So, do not test for it here. + dissolveRounds_1(61, 150, 2, 5); + dissolveRounds_1(61, 2, 150, 5); + dissolveRounds_1(66, 8, 8, 1); + dissolveRounds_1(66, 7, 9, 1); // 7*9 = 8*8 - 1. + dissolveRounds_1(66, 5, 13, 1); // 5*13 = 8*8 + 1. + + trace(""); + trace(""); + trace("------------------------------------------"); + trace("`sourceRect`."); + trace(""); + dissolveRounds_2(101, 10, 10, new Rectangle(0, 0, 10, 10), 1); + dissolveRounds_2(20, 10, 10, new Rectangle(0, 0, 4, 4), 1); + dissolveRounds_2(35, 10, 10, new Rectangle(0, 0, 8, 4), 1); + dissolveRounds_2(35, 10, 10, new Rectangle(0, 0, 4, 8), 1); + dissolveRounds_2(27, 10, 10, new Rectangle(0, 0, 3, 8), 1); + dissolveRounds_2(31, 10, 10, new Rectangle(0, 0, 4, 7), 1); + dissolveRounds_2(24, 10, 10, new Rectangle(0, 0, 3, 7), 1); + dissolveRounds_2(30, 10, 10, new Rectangle(1, 3, 4, 8), 1); + dissolveRounds_2(4, 10, 10, new Rectangle(14, 3, 4, 8), 1); + dissolveRounds_2(4, 10, 10, new Rectangle(3, 14, 4, 8), 1); + dissolveRounds_2(25, 10, 10, new Rectangle(-1, 3, 4, 8), 1); + dissolveRounds_2(25, 10, 10, new Rectangle(-1, -1, 4, 8), 1); + dissolveRounds_2(30, 10, 10, new Rectangle(2, -1, 4, 8), 1); + dissolveRounds_2(2, 10, 10, new Rectangle(1, 2, -1, -3), 1); + dissolveRounds_2(2, 10, 10, new Rectangle(1, 2, -1, 3), 1); + dissolveRounds_2(2, 10, 10, new Rectangle(1, 2, 1, -3), 1); + dissolveRounds_2(2, 10, 10, new Rectangle(1, 2, 0, 1), 1); + dissolveRounds_2(2, 10, 10, new Rectangle(1, 2, 1, 0), 1); + dissolveRounds_2(2, 10, 10, new Rectangle(1, 2, 0, 0), 1); + // Note: Apparently, Flash Player seems to round width and height + // in really peculiar ways when the x- and y-coordinates have + // fractional components. Therefore, the tests involving + // fractional parts are commented out. + //dissolveRounds_2(18, 10, 10, new Rectangle(0.5, 0.5, 3, 3), 1); + //dissolveRounds_2(18, 10, 10, new Rectangle(0.5, 0.5, 3, 4), 1); + //dissolveRounds_2(27, 10, 10, new Rectangle(0.5, 0.5, 3, 5), 1); + //dissolveRounds_2(18, 10, 10, new Rectangle(0.5, 0.5, 4, 3), 1); + //dissolveRounds_2(18, 10, 10, new Rectangle(0.5, 0.5, 4, 4), 1); + //dissolveRounds_2(14, 10, 10, new Rectangle(0.4, 1, 3, 4), 1); + //dissolveRounds_2(14, 10, 10, new Rectangle(0.6, 1, 3, 4), 1); + //dissolveRounds_2(14, 10, 10, new Rectangle(1, 1, 3.4, 4), 1); + //dissolveRounds_2(14, 10, 10, new Rectangle(1, 1, 3.5, 4), 1); + //dissolveRounds_2(18, 10, 10, new Rectangle(1, 1, 3.6, 4), 1); + //dissolveRounds_2(18, 10, 10, new Rectangle(0.4, 1, 3.4, 4), 1); + //dissolveRounds_2(18, 10, 10, new Rectangle(0.5, 1, 3.4, 4), 1); + //dissolveRounds_2(14, 10, 10, new Rectangle(0.6, 1, 3.4, 4), 1); + //dissolveRounds_2(18, 10, 10, new Rectangle(0.4, 1, 3.5, 4), 1); + //dissolveRounds_2(18, 10, 10, new Rectangle(0.5, 1, 3.5, 4), 1); + //dissolveRounds_2(14, 10, 10, new Rectangle(0.6, 1, 3.5, 4), 1); + //dissolveRounds_2(18, 10, 10, new Rectangle(0.4, 1, 3.6, 4), 1); + //dissolveRounds_2(18, 10, 10, new Rectangle(0.5, 1, 3.6, 4), 1); + //dissolveRounds_2(14, 10, 10, new Rectangle(0.6, 1, 3.6, 4), 1); + try { + dissolveRounds_2(20, 10, 10, null, 1); + } + catch (e: Error) { + trace("`null` `sourceRect` should error: " + e); + } + + trace(""); + trace(""); + trace("------------------------------------------"); + trace("`destPoint`."); + trace(""); + dissolveRounds_3(18, 10, 10, new Rectangle(0, 0, 3, 7), new Point(3, 5), 1); + // This would result in a 1x6 resulting area. And Flash Player's pixelDissolve() + // cannot handle a size where at least one of the dimensions is 1. + //dissolveRounds_3(8, 10, 10, new Rectangle(0, 0, 3, 7), new Point(-2, -1), 1); + dissolveRounds_3(15, 10, 10, new Rectangle(0, 0, 3, 7), new Point(-1, -1), 1); + dissolveRounds_3(3, 10, 10, new Rectangle(0, 0, 3, 7), new Point(-10, -10), 1); + dissolveRounds_3(3, 10, 10, new Rectangle(0, 0, 3, 7), new Point(-2, 10), 1); + dissolveRounds_3(21, 10, 10, new Rectangle(0, 0, 3, 7), new Point(5, 4),1); + + trace(""); + trace(""); + trace("------------------------------------------"); + trace("Default parameters."); + trace(""); + var bmd:BitmapData = new BitmapData(10, 10, false, 0xFFCCCCCC); + // Omitting `numPixels` and `fillColor`. + // Apparently, "numPixels:int (default = 0) — The default is 1/30 of the source area (width x height). " is wrong. + bmd.pixelDissolve(bmd, bmd.rect, new Point(0, 0)); + countTraceBitmap(bmd, 0, 0xFF000000); + + trace(""); + trace(""); + trace("------------------------------------------"); + trace("`null` `sourceBitmapData`."); + trace(""); + var bmd2:BitmapData = new BitmapData(10, 10, false, 0xFFCCCCCC); + try { + bmd2.pixelDissolve(null, bmd2.rect, new Point(0, 0)); + } + catch (e: Error) { + trace("`sourceBitmapData` being `null` should result in error: " + e); + } + + trace(""); + trace(""); + trace("------------------------------------------"); + trace("`null` `sourceBitmapData`."); + trace(""); + var bmd3:BitmapData = new BitmapData(10, 10, false, 0xFFCCCCCC); + try { + bmd3.pixelDissolve(5 as BitmapData, bmd3.rect, new Point(0, 0)); + } + catch (e: Error) { + trace("`sourceBitmapData` being the wrong type should result in error: " + e); + } + + trace(""); + trace(""); + trace("------------------------------------------"); + trace("Invalid other bitmap."); + trace(""); + var bmd4:BitmapData = new BitmapData(10, 10, false, 0xFFCCCCCC); + var bmd5:BitmapData = new BitmapData(10, 10, false, 0xFFCFFCCC); + bmd5.dispose(); + try { + bmd4.pixelDissolve(bmd5, bmd4.rect, new Point(0, 0)); + } + catch (e: Error) { + trace("`sourceBitmapData` being disposed() should result in error: " + e); + } + } + } +} + diff --git a/tests/tests/swfs/avm2/bitmapdata_pixeldissolve/test.swf b/tests/tests/swfs/avm2/bitmapdata_pixeldissolve/test.swf new file mode 100644 index 0000000000000000000000000000000000000000..7d96c8df2ce8a7067ac99ba1ba69ac9ce86eab57 GIT binary patch literal 2766 zcmV;<3NiIVS5qeN6952s0gYH|a2r<@zIR_&TFJIz$FiJ9v$5B4oXCAAT^y46otQ&Ol*W9wR5Tz%VdS z9@BvtyoFMxJZjEe$y!-X3i9mHx#v5N@1FZujaLx&GD7WNKq!FG^p0MH(1TsCV1y?0 zR62HXIxel`vUwv0qvL~1rdf=I!{u^0R2~f#^u_SV`1p7@5)DVA!{9M&T*;ft%5dK3 zADpxkOlw9`&lJr}AurK{idra{#|H=NSyRbI(qc)^+9^}Xu$I+wTHZ9mBcTyUluE|Z z1wE&jlS;9e%_J3?F1#{qEESTM%gVAgoX#r7(nQ#Cq%mg3%xaTUMJ2hUN%5?Du;eQ5gy3vrVl3y$-i`t}?pTBF)&e<^8Gf+%z@|Q16|U#a)}?C^!Dxw(60FHWOs2W){YpK0GK>;yW+Y;0`YE3yCy@NmA%&yT`3 zL1^xNfA~?*o)b;YFwrwRAKHNsMeLyug+S%0<8LZv#AH#OA88!%qvZ0{rC zr9w^%D|uL7;CtCD6vIWmu&67!TqeI5Hp*!uY$&;6Rx@t9jfR92Lr^njPAT#_?YKLg z$!1R#vIU(_!q~(s_=>ownHMrET6Q!lENPj=C6g~_QsxqG>Pk|>2X_xiv&))Z)-$H5 z<)tEZmF(!4w3ikE4w+@>WXv|+Nuy5MHM!+NCe>!|zECP-6tl_|v4%`5roxpndDE?H zNfXvCtGQwGm=_9Q<8%d>=1V!7mBH#-isZHOMXr>jg+* zUMXsu-#Xw+)7Q9Im0HP;vxHkl>iozzN?8yz`1&PI<#Ts-zO{!afbJxl=m7tjI1h=lPF#!Hws!t5Yy z7h!f1W;bE>5^f*iB*F|5<{)842#yjwN|>XBIY#iU1Wyv?1YxEKK27lLggH<63xppa z{5uGLk??bb!Gui^=6*uv39ArRC2Z1-5QA7=AjJ15#sbF+yju`GZug#5uG`-eAUq*t zhv?}%vbx{v>Ff6gIBMw}qr(7Cb+L1t4*COvJ@RzM?4dt^(47oT@45@$eGfdB;CUxJ z_rh}@Jnu^3yEXVu<9(7_Kt%9OA&gPS6k;&$nnEmQc1|G| zD#k*ilirN}R((RzL7$h|4X`0L_7Fgi;(>$K4o&p8?Us zf(URRdiewEc$Y9}9SCDHDOiJRYuB!;oK4Cll#;|csFK?eVg;{Te3MT5usv;Y9q&hn z*RdCa@Gv0ySP=aj2tN-ZAb^m`v2{G)ia~qa6YKbZc-%UY@TR>oUW>Oe=8M)bmFpx3 z1&6Ns;CD&zkjhuCUQN2JF__cgwMsBpfr$-Qu2+Jgit4Ha!xdGi1S1ud)Mgq>2-mI; zhMBVhw<;vv)^Qn?k{)YP#zs=~jnfXFsH$$L0^L>J>GoC8$AQMLimIS`R1)vtX}}b9 z65~E*$eL8eXCYV>*Zj{ycc*~~V|Vp5bd_`SZt)0oVTN{fKboN(0O4Uk1lSqtjw$+qMrp3;AXA6Xo5kNb29LDhPxqy z;DWt31{p5ZGF+k=KzJAs{VWJS2O_{d{yS` z1jtTM+#GJ$L*2Ivp=x9;axXgc(xJ%V9JUMyJxP=7bum_{D)-ybtnFTIq+MxfS3s+k ze>Z5S?DFqvpbu8%;{#7%nUQ%r!zu=Y%urL!@Ln*SlwI&wo8d$Dn8@z>_+fj@%Wd`X zRouw^K1Y3osx=mmQgzy<@qWkQ1CU0eGf9YagHY|P2uD8N!w*>>1aM~)$jO`oeh5Ij z2lYr-Gx*^akds|bFdZUHy8Mm_=HCLu;{0iOhrX|Sd6f1G)KY8%Kp z;8QIiZjStP3y5UwM1H0P#Bd`t7W=a;AiXXc;8y^&cY;*k8ehXcseVH6<_Y;a-Bxjp z$zuC1r03+D&QAN5qkfyJwO#ogs?ONE@)^hBSt!@JZJpr;Vr3rgFyIgnhOF;_SI3RK zHslS*>pAdZZ{+p5{JP`y{hN8c2?wH4@dx15eWP4FZ2pGV^Ug$GaMT}CwKnM=QT2>H z=^r}|KfxMK2sHcV`vY#BH85ryPrAKv3&&mTkaZ1LDJ-Kf8~4HZr%tvP9rY!u)++yu zs%P!WKX)8{vAr^5{gPH?Br00V{>oW=W^?g>P1C)7%i{mmsqnI+{*J0OHovE8jm;k% zhd*v-!&Ic-m!(#Uz|GYj%rc0#_3h6p0hjjSI6OR z+c|O8YfVPZe&OeM>+h5(AMZs&)<3Aq(INeACH#g%nA;@$Pg-$y3*mp`8U7*s7=99W z`#(p%Ouj+7{f~RT?GL| z*+R0feKVtadY11y-sgS4_rHf@=J?&$eO~8vUFUt>H}~&~;Tau9dTx3E0Kf>>)ieeG z$W{m+Us`H{#pG-C4ghe_C&1JaZ;bE-x_i1|ur6pI-rpS!MEhYe0D#}%aEi0fP*p*u)gOF@K}{`#4FeCb?F6eGqgV;FvT!YbBBAy+I7lhvQdmg)g~l!A zdC7W?yK=0HbR&hp595xsv2>K%9A~G~1TUNduI*e+yA;o}74LF`RZ|}~fB6mYu-cQL~8Is;&3*N3= z&)?3!ZMJfY&ilfN+3H5Gm%**aKlk;4%YzQ@2}Oxc)h^kptpez807XYNQvABhg<2CO zZ2A?Lxb(nVlR+OEw?DktEQ%UW<^9mkJ6aM<2YPJ?|0<7-eHQXstKIp%%#gp$mY*_IA+zj3_Cq!~#w3 zu)aWA{jU*p&*Av7myJu0)x?&;0KW0QD=oS}3Y5Nj!U>C|y35S3PK7I)tn&p3Q6wbX z(d*U`zcgeBf0CjTon{mKHR$sO4@7|V%9i-V{flQx9Q4L=8|kA0=*8|QdWz@WPYz&G z_>|}+@lLn+rs3V=c@xH`Km{w@PWgGCtepx9);`&ULQUEV$_B0H(tUlj7nFvpvwT;% zp-!GD<>&kE2LtXL(&6?`G}1W|yu~HF171E++Ah1DK$U2I7CUKXZi`!G?DcU!xlpz& zQM*vFt?gSNJ(5C&dI5?m! zZSu2Ir@d|lT)6EWTN@|W)zd+PUtgy$`)Y%{LXzYx#%)G+?qJ%jW-my4*)Olz_G45u zdCo-T(}NyZWN!6O?AEO{x!Fmc%$b43N|Y(YEFAV>2*lQ|wOZ{OKQEDeQCQ_`A3s-c za6Yg*_$6kHMNwKjX7Xi8djHJKl;hdHV)%f+B*^{qqePgcLGn`{(Ll31-u*fEBKdlv zmicn6D{4G0%v;Q*+Ev&bbv*Vw!Oj=oSF}-a-F*-?J_d?nIn_MSee%?LcVk0^tkX$kfBp* z;3;m7xs_t?$tteshC}s_SZy@c^df6c9Ki(6WJ|V83+Ns7IJ75z1oe3y)>&MO$>L>} z2%Qf(FhBCr&Pr#*mNm{YsUq$a(6)R_=n9k3N%(?SpVUp;oMzEg@T*&MCI@;$#hEon zWlDVDiZ2s8lOp>r>VDLbxG`p`?eesbH9_0ZN6%;B6IzWDwQ}zr!z(u~~hQ(U352nU8g^6#S&iUKvIk1N+ zIEkmfvSU_FMNHP18^t}9jpz|!#W#TJ=Eusj%Nv%G!etg8-Pmk2fpN5o+-#rVui~sL z@@v0)`u>_cJj!1@R4Fb0^*EaKfnK%GSP*-WPAQW699M#q(ENo-N=tU=^ZfM#hJzzo z0sMuIW5$CIWzy~A9^!0i`1RSM2E2|A9YTnkVe(v)xB&*(39^*|8YmRAMkBK=R>-NuFpW&ouyeB*YRiFO!9p2BYI#u~K-LlQojD5W$MczH z+oLviqWye>3MA zk$&`Skkp)v&&Jr|ltc8ro$U&kB?7^=+of5XxLq&;hCjm-4&{(Z2lGWV1`0qLZg z4E9lc31ju3le_gClUW<$IxlXzp*>-V%ffKJuJG9F)ri6Ehb`uYc?a&bZ8NNu3m3}K zB;NKp@I|rY<6ZqKIyJxNnPo2+-m5}9a?hO-sT52a9{)nm)qM$;-4zjSn!@Y zxlvIWTbJZ?XUv`HB=l#mDCx8L+&8+N11l;3@2({|j+#DulM)+fRvJO4?mX74@}=jh z?YF=kr4JwX*i{TRs_L6MSd|x8FFeT+bLsJKdhr1|(NL6StN z*5Ww^ecIsxG)mb#H`yqSA}KA7kt4h35WpA$LbGn1xxj9F?ZuFhzLVwlx-_c*`?Y)o zBP{ql!vKABDvg=fsISO`atpah1aFnH_)`^T1oLndqpHBz8yr@F$J9kI;N^#` z=zR6BpR;op=bU7>3dkHRXo63qPDp%IQe$S;>T$K%He6fIslSkOa`6PY357kNEk*mh zKg}%lCQtY0Ta_1E9%WzC)_MUi4Yoe+)R=5Tlg|(%0`;0dkC|IpNx2MK$n%pHX7VrdW56fxsNUjZpN3M! zb}gA&ciMgm@Jxqiwz+B<#CIHT@_Qt*LVkE&H>ik1pL_Ej*5!oy1{YaqiUyf>NTJ}^ zUXCzisP^6lO7ubm?GOWN5I_0EgLh|pUp`mu(sdEC5b^GOaNpy|<*@bJpRQ+KGMeRi zFgP&I|VYIn^;yHWb76W^0=$wcG+233E) zhtbW2`8^x2N-Zhw)dFr!fIA;tkkJt&YxcRxz)Mk&@sPc7N~Q*vES>3VSp6lG?(Aot zxAU{ry3eIt6BjDp@D#yaV~499YRB0_1&eE#z8SvHzdZGl^ZFYdnk@T^$yR?6hF!wGA^4hcwO$#6uPjg(!()JG|oIod^j zs+g|4jEla9Yia_qH#c8_zCEnS-aCtX$`P~O4f$4NITYBov+Uq8TJdJo*tP=E)f>!W zSD#m#JX~^cbNi85_&wjs@IpnOMXi9z!tO^V^!C{|1N-c*%HH z;;%thXQ7oXU!|-n-c!mWE9;$xT%IsmY3M~w>RfdKhTN$La%pbfJz}F=@$uu{H4yKM zwCxBG@2A_47<7qcd4;i-l)@@mFmsC9TOXw@DV7(~{g&}1=67!!#hYcR(vIX#-@y6y zUQLe#yTo9GH7fd;n~;swuINMNcPcHz;<|;TEasm-w^3{V+QXnj-q3430 z-l*SPAAuVqxg+}W-7k4m;}!-Q0V(72otBaU_U)gKN~SVD$vc+6Hw9OjN=s?5O0^Ju z8G0eYUTEvV!%0>j7-rVJVS7W9N0gqesZZk`t|22qFZh|tG=u8pTPz9eVlM>?B36eK zT}MB@eOwY$Cnj*wCg{3`1p`AgIZMXLKFTvp1>z513s)tNN3@7q>TC+|#jD=OMXXBi ze90+!9LWZ4`;4oPi9#%uFo8zx#0Gh8nI^Ms-Clf*N%A+ODfmZ2QkhGdhk`|ebil<7QgMyB@Vd%Y=?naa>wul(^{$G7#Z z<`ZSI3Fflc^qC`}4nkmCLylL>!Y-&h^TVQ@$!yibMez4Qtc;$VU29PfFQ&5OTqd)< zzSa6lC$2S)liIo*66@ow)^-D*=0tQc&kO4g>jej6AH8hx*HGPOT@bWJv-rgTQR zLUy#Q=~7v!3GeLACD}^G(zw$aX7|YQxS~&`J2LH*IxxSlEHzUFOzae2jp<)D%&SYY zq`TTl6|-P3QO*1I!Li5eno}QibUAk9-b--bDrp~IOmYz%=Un{=TaRaHsVF>k#o&|G z>p0*02ZdBrsvb}2TsC_@K8ioeo$O5xjR<3bGhKUf{p&}*O~@B@&9=9Pj!{&FWHcLS zpZ{86yD+lW_7-~NS}w?%VIfJ+LB>~VRSi?{l5Q_k0FB5>BQyIy&lVU zS)6h#6}w0VnYW+YatgdM%d*LUYltdSTD1K#o(sn4JQZ=wHAL1_R4{qSu}EcNK%4R? z^9L@3b+laIL3`Nr5NMnC&>lQRWH7h6F)=y7$-jH+wkN}-;LnW8idw?wHg;2P>r4l& zy*1ROr*@<2JJFv-OL13$$6x)BAkw<){Hnp?^MTpSo|M)s)`LQQQu$(OP@5woYt2l? z?ycsV4??0hb%g_(;`Qn>1@-RgUt(8xH_MDXirji7aezat%H~dFPmptMu$n;L+o_r2 z{-Z}tA6vF|=~bBacK5kFf)~d&>LWj?^d>Y1`vftEEqn^Ti<2p@l`Ew88NLaNQ&HLr z;ikPQJOAzEmdX+S(<2r2Ei#1bcqCRs!w{~a@#6+gxOb-o$HR1AsPZ(~o1E4X5BFjA zptVf5WZGT8rMV(X46q5`Vfy4c-7Y1%@ z1aN$`8kySTdFs^e5NaTpfsVqmx-lEL4N^}9k4qhI6<<>D=*?zeQSr3(*u3VI)k5BJ zAa$l!$>Wyg34Brav;6Z;jV6tU%zDJ^UsdIMj*RCgJ<9hs*n4hx#@_0a;v0lu(PbfB z=B&(Ume!&}_sm3^)T7rv9^1>hZ_j^I{V@xt0=r=tb@dF*w}{bU>&+HAIWaaGa>?t< zV0ud5Fzq)Ub+JctJ;*oigdKl6U)URV+o0PS2lAv`!BKF$#p%DJknjzCCZZubd4D2T zY+|`#n=9CaowJH6pnqt@dRsmi(A{hHm0Dh&@+E!Z(}kslh4zs>SkLSt&Gqx1B^XUR zBf^^!ZY<%Ah^4-sBGL^ffk3%Ape6ip?u0ic0DzK;pF0BSjK%{U(2iJF82@5zJwFhO zg7I6(=u7FlYoO0#bpt%nCIM$mkpa#~1r)!EGQE$b=7|PEC7=>gAT2+v4}@Qt9;oDr!YCSRYJaC7j9~od@pyMd zNl9N{UkP7n2{%tiNw9)~f}|8g5&{7c5FjsqS3JTG=Rn=6pW ziEwc9#>4pe3G=`o`QhC4^?%a4dVN=cpogR%!d((9Ati~!N&f2Lh1c>SkbF<*FFm|W z2``o;jnQ6i-kwObmJiw$FYqe`3i;FD-P_ZJR1OL$iFQHb2v9FVRPgUY>cI64e|iul zaKz%=NnQl8e}}|lF~5oRyWEH~q;h^ugy8;@_jl+YwUfXEl)k>ArW?|mm>ygc#!rl| zh;l<>QHrET3807$l{6YnH^}-`uk!T_n zfm{Mh;6X}b&`6Xl5`=-sq6rkzD3AkE4hljkAQj~0zzR|dvY1~e3_P)fu0*)}niY`> zMWB+Fh9Zy%X#_}GS`G<<%F19s2zjU+NDhg_D1hZrD2P0QM1?{sYP)&j5QOE#;t-B# zNq1LA(gaa(MKwb>j2|K)^_#`e1%by99ANxZ65CmMlw^E7pHBfP#N zrUWEeWkBXHf|D=f$3GmA?K=9kQ5snwaX(jpdxcaUcQO5t`&-bHCjd|H$>X6!=@{e+&Ficm2P~MgQA{2klDuFUXg0ouRP=ln|~$ z)DEY0Gy&g;znM>SZxAeW?z&c90009k@k0hkN#i6KY4C7;Et)ARmIHzZ(?t^t2o^E8 zrkbhW;QSEm48({t>H`<#ba92p;S-^)t<)|+53>C5msuWMrF5s9E!09>Tn_M4yzU4b zt4YY+rmw#NUwFcvY>;<`3ZYd08m10(;~fE97pp`Yv9Y6B?+5}ogoi1Q0@UQxXjD7( zJIR>wYBT^f4m^PJH#5~y03~c%oL3NF6k#WM>^Y^EQAjlr%K8IFz!M$6GZ4+Ton)$= z1V=Tw5HY5)hWl8h@XS;O!ubD!{$%*;90;6$6%%*WOj#Gm(Y8A%Kv}|K#Gwd~_}4P~ z_rj4x`dMPB&13{6(5aJS^`>QQCz*Q|gCc;oCX)g0qeRsfWl5%3_LT)9Dt!QYO^12q z(EjwaTD>x9`V#Gyw-K>1VS1gCu_TGJ!Y^3$5)(hjv9e5p2fWI>!{JRV;|2B8;QhIy zD?a;vL7fIV#2#8X5xy5fn(GjrZr=AZSNnF76vmNb<;4Ty+GL)?zTVkeJlQO`(xNY5!MdQ`5aNsHj-UZBX^JCc=WII*`Irb)PBEjPf|1gY+qs@ z{s8?u%`R8pN<)W2RxDG82^ug*6OIMK5yXrKsCJS8h+CiLxAAw={`_wc!g$}5X^|uX z@GQo1$1=b2R9vN%__tX0ql5+;`IGM-B$1F+%KwDwZ`JS@W&d3n{zx%a2FXcOq9E*Y wlA`~se1G&KjK7=y%P#+Efq#)GP-OJk4D-dnakwbq?BhSMS-HnUV3Q{JruB$KG55C(H48E zSron2{fD&d$TG45IR8KYl`85ta#O3X(QL({o7wVFdKerJFs@F%L~41I?%N54ElA{rEncf4lPE{m}m}TlyQ!;rH2I`JNEsUQ^ec230j1P69A{;X6&W={l>f z)@Ydas_JbRp6Y3hrbWHkS(Z}JJh^824XwGT`5NBDTQYRhzZ;sQNTkApRM1VYX=z(A zP1hIJOiRzOe1JFCVLNBQDy%!EE=M^GO?uR7)Tk>kK*6PTUwq=2wl7C;tJG%9)&N56%QYeXS)!UKYEhuSkbwYVooeoVv$NQ zR%zLFb_K{D^`Ee9ohpfC*VVSd69|1)O4An(-eOI6YP3*y8ftlYN-Y(OH`H3ow0zU< z@96c+GPKvHN~aO}#SX&b+DFjS1qUuS)28l7XV3%Nr>+JSt+F7; z`G5)L*L=97T*;#Ls=pR%^NK%(W#PTIsL+Dr)PK?mIp1kKwz;F7-V?WVq%)?gzu{{V z^|Oz)_Sh0b%yuGhig_xqGmdLgFWtF}mvIaOh#noh-s6T+mu0HUaxESnA2ys`Sy^>f zd}l?chH0DZgsiMltI0PVkDn^ul%f_(QIpcg_CEP`V^SSG>+S0BV2A(kV4Q1Lz$kZ> zas9?5U%FAuh%}8M+l!iiwS?3@Hrw(5D}8D5I_>I5;0H2 z0ufar7Ku1X#1avwh2eCgCyRZV`T-q;C_hOt`y*TSy?pAyy4ZYzv|k zY6IKp18wk7JAJ4PF%3z>@R2wR&pEiWr@0Vi2G7nd;@J;CR!fTBS zPSu1r8XxrS)P#zFb3s4ga72*hnLV6FBMbosi5mgf?C$Qa5v#@(q@blZr=YPPK2mW- zmU6*`YGU{Gn@WPu1s4H|J-hm^}MUFV|N&X}TSc5yo=M#T|2AxNP6f4MY;7D*3XSY)g zJ`zGCL?)z$6wOE^Vv&ePLI%hOC>Wvm4#)Cg4Fz-_bOH1n=mO{>=+mH!pcByNL6<;h zHQfcBfF1|E0(uN|8T10hZGs~3V1)$gLD8892*rcqLG77QHk+i_f>JGDWN~@E(gWuK zBG^p9ulxp31g(GI&Hg^aVUeLd()58}fc;tr{&kr3Lt=z~12PWrRVl=Wh-3JdLwvwF z5r2u|;6w1lg0H|B4<5oOKjXL4jYRMmd{1D`2VaFz2%f?y2Foy#X97edgJBWGmZlu-=&3T*XHnFU0d&&4 z5wKL4!hE3yvn2Sw3qGygm~oXvjY$QyE?ZAfZO1V zRXGK1Gr-c*wzlP~ycl@_32bjSRUh~{)CKFY*p8-t2ka(T8Ct5^r@W_JRz{Wgm-+;_ zN`@4=ug{3UxFud+385E4@;i6jXP zBa%XAQ7nbdp?C_NM{)|ihZ1m0qhuOoQA$D=P>+NzqO^oYQAR>C2Oo#&og%!+Ns6kM zj7!DpxG`R=UN$Zlt2rZAtWFpc#p;+b77pJ)=fmF`yQ^im0ONh^Ys3C4pgW-aA1_^B ES;6@80ssI2 literal 0 HcmV?d00001 diff --git a/tests/tests/swfs/avm2/bitmapdata_pixeldissolve_image/test.toml b/tests/tests/swfs/avm2/bitmapdata_pixeldissolve_image/test.toml new file mode 100644 index 000000000..d8a3f915a --- /dev/null +++ b/tests/tests/swfs/avm2/bitmapdata_pixeldissolve_image/test.toml @@ -0,0 +1,7 @@ +num_frames = 1 + +[image_comparison] +tolerance = 1 + +[player_options] +with_renderer = { optional = false, sample_count = 1 }