core: Move threshold from BitmapData to bitmap_data_operations
This commit is contained in:
parent
f476968693
commit
4510eb305b
|
@ -1299,7 +1299,7 @@ pub fn threshold<'gc>(
|
||||||
.unwrap_or(&Value::Undefined)
|
.unwrap_or(&Value::Undefined)
|
||||||
.coerce_to_u32(activation)?;
|
.coerce_to_u32(activation)?;
|
||||||
|
|
||||||
let colour = args.get(5).unwrap_or(&0.into()).coerce_to_u32(activation)?;
|
let colour = args.get(5).unwrap_or(&0.into()).coerce_to_i32(activation)?;
|
||||||
|
|
||||||
let mask = args
|
let mask = args
|
||||||
.get(6)
|
.get(6)
|
||||||
|
@ -1313,24 +1313,10 @@ pub fn threshold<'gc>(
|
||||||
|
|
||||||
if let Some(src_bitmap) = source_bitmap.as_bitmap_data_object() {
|
if let Some(src_bitmap) = source_bitmap.as_bitmap_data_object() {
|
||||||
if !src_bitmap.disposed() {
|
if !src_bitmap.disposed() {
|
||||||
// dealing with object aliasing...
|
let modified_count = bitmap_data_operations::threshold(
|
||||||
let src_bitmap_clone: BitmapData; // only initialized if source is the same object as self
|
&mut activation.context,
|
||||||
let src_bitmap_data_cell = src_bitmap.bitmap_data();
|
bitmap_data.bitmap_data_wrapper(),
|
||||||
let src_bitmap_gc_ref; // only initialized if source is a different object than self
|
src_bitmap.bitmap_data_wrapper(),
|
||||||
let source_bitmap_ref = // holds the reference to either of the ones above
|
|
||||||
if GcCell::ptr_eq(src_bitmap.bitmap_data(), bitmap_data.bitmap_data()) {
|
|
||||||
src_bitmap_clone = src_bitmap_data_cell.read().clone();
|
|
||||||
&src_bitmap_clone
|
|
||||||
} else {
|
|
||||||
src_bitmap_gc_ref = src_bitmap_data_cell.read();
|
|
||||||
&src_bitmap_gc_ref
|
|
||||||
};
|
|
||||||
|
|
||||||
let modified_count = bitmap_data
|
|
||||||
.bitmap_data()
|
|
||||||
.write(activation.context.gc_context)
|
|
||||||
.threshold(
|
|
||||||
source_bitmap_ref,
|
|
||||||
(src_min_x, src_min_y, src_width, src_height),
|
(src_min_x, src_min_y, src_width, src_height),
|
||||||
(dest_x, dest_y),
|
(dest_x, dest_y),
|
||||||
operation,
|
operation,
|
||||||
|
|
|
@ -1275,8 +1275,8 @@ pub fn threshold<'gc>(
|
||||||
this: Option<Object<'gc>>,
|
this: Option<Object<'gc>>,
|
||||||
args: &[Value<'gc>],
|
args: &[Value<'gc>],
|
||||||
) -> Result<Value<'gc>, Error<'gc>> {
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
if let Some(bitmap_data) = this.and_then(|this| this.as_bitmap_data()) {
|
if let Some(bitmap_data) = this.and_then(|this| this.as_bitmap_data_wrapper()) {
|
||||||
if !bitmap_data.read().disposed() {
|
if !bitmap_data.disposed() {
|
||||||
let src_bitmap = args.get_object(activation, 0, "sourceBitmapData")?;
|
let src_bitmap = args.get_object(activation, 0, "sourceBitmapData")?;
|
||||||
let source_rect = args.get_object(activation, 1, "sourceRect")?;
|
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, "dstPoint")?;
|
||||||
|
@ -1290,7 +1290,7 @@ pub fn threshold<'gc>(
|
||||||
);
|
);
|
||||||
let operation = args.try_get_string(activation, 3)?;
|
let operation = args.try_get_string(activation, 3)?;
|
||||||
let threshold = args.get_u32(activation, 4)?;
|
let threshold = args.get_u32(activation, 4)?;
|
||||||
let color = args.get_u32(activation, 5)?;
|
let color = args.get_i32(activation, 5)?;
|
||||||
let mask = args.get_u32(activation, 6)?;
|
let mask = args.get_u32(activation, 6)?;
|
||||||
let copy_source = args.get_bool(7);
|
let copy_source = args.get_bool(7);
|
||||||
|
|
||||||
|
@ -1322,24 +1322,13 @@ pub fn threshold<'gc>(
|
||||||
.get_public_property("height", activation)?
|
.get_public_property("height", activation)?
|
||||||
.coerce_to_i32(activation)?;
|
.coerce_to_i32(activation)?;
|
||||||
|
|
||||||
if let Some(src_bitmap) = src_bitmap.as_bitmap_data() {
|
if let Some(src_bitmap) = src_bitmap.as_bitmap_data_wrapper() {
|
||||||
src_bitmap.read().check_valid(activation)?;
|
src_bitmap.check_valid(activation)?;
|
||||||
// dealing with object aliasing...
|
|
||||||
let src_bitmap_clone: BitmapData; // only initialized if source is the same object as self
|
return Ok(bitmap_data_operations::threshold(
|
||||||
let src_bitmap_data_cell = src_bitmap;
|
&mut activation.context,
|
||||||
let src_bitmap_gc_ref; // only initialized if source is a different object than self
|
bitmap_data,
|
||||||
let source_bitmap_ref = // holds the reference to either of the ones above
|
src_bitmap,
|
||||||
if GcCell::ptr_eq(src_bitmap, bitmap_data) {
|
|
||||||
src_bitmap_clone = src_bitmap_data_cell.read().clone();
|
|
||||||
&src_bitmap_clone
|
|
||||||
} else {
|
|
||||||
src_bitmap_gc_ref = src_bitmap_data_cell.read();
|
|
||||||
&src_bitmap_gc_ref
|
|
||||||
};
|
|
||||||
return Ok(bitmap_data
|
|
||||||
.write(activation.context.gc_context)
|
|
||||||
.threshold(
|
|
||||||
source_bitmap_ref,
|
|
||||||
(src_min_x, src_min_y, src_width, src_height),
|
(src_min_x, src_min_y, src_width, src_height),
|
||||||
dest_point,
|
dest_point,
|
||||||
operation,
|
operation,
|
||||||
|
|
|
@ -920,77 +920,6 @@ impl<'gc> BitmapData<'gc> {
|
||||||
self.set_cpu_dirty(PixelRegion::for_whole_size(self.width, self.height));
|
self.set_cpu_dirty(PixelRegion::for_whole_size(self.width, self.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This implements the threshold operation generically over the test operation performed for each pixel
|
|
||||||
/// Returns the number of pixels modified
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
|
||||||
pub fn threshold(
|
|
||||||
&mut self,
|
|
||||||
source_bitmap: &Self,
|
|
||||||
src_rect: (i32, i32, i32, i32),
|
|
||||||
dest_point: (i32, i32),
|
|
||||||
operation: ThresholdOperation,
|
|
||||||
threshold: u32,
|
|
||||||
colour: u32,
|
|
||||||
mask: u32,
|
|
||||||
copy_source: bool,
|
|
||||||
) -> u32 {
|
|
||||||
// Pre-compute the masked threshold
|
|
||||||
let masked_threshold = threshold & mask;
|
|
||||||
|
|
||||||
// Extract coords
|
|
||||||
let (src_min_x, src_min_y, src_width, src_height) = src_rect;
|
|
||||||
let (dest_min_x, dest_min_y) = dest_point;
|
|
||||||
|
|
||||||
// The number of modified pixels
|
|
||||||
// This doesn't seem to include pixels changed due to copy_source
|
|
||||||
let mut modified_count = 0;
|
|
||||||
let mut dirty_area: Option<PixelRegion> = None;
|
|
||||||
|
|
||||||
// Check each pixel
|
|
||||||
for src_y in src_min_y..(src_min_y + src_height) {
|
|
||||||
for src_x in src_min_x..(src_min_x + src_width) {
|
|
||||||
let dest_x = src_x - src_min_x + dest_min_x;
|
|
||||||
let dest_y = src_y - src_min_y + dest_min_y;
|
|
||||||
|
|
||||||
if !self.is_point_in_bounds(dest_x, dest_y)
|
|
||||||
|| !source_bitmap.is_point_in_bounds(src_x, src_y)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract source colour
|
|
||||||
let source_color = source_bitmap
|
|
||||||
.get_pixel32_raw(src_x as u32, src_y as u32)
|
|
||||||
.to_un_multiplied_alpha();
|
|
||||||
|
|
||||||
// If the test, as defined by the operation pass then set to input colour
|
|
||||||
if operation.matches(source_color.0 as u32 & mask, masked_threshold) {
|
|
||||||
modified_count += 1;
|
|
||||||
self.set_pixel32_raw(dest_x as u32, dest_y as u32, Color(colour as _));
|
|
||||||
} else {
|
|
||||||
// If the test fails, but copy_source is true then take the colour from the source
|
|
||||||
if copy_source {
|
|
||||||
let new_color = source_bitmap
|
|
||||||
.get_pixel32_raw(dest_x as u32, dest_y as u32)
|
|
||||||
.to_un_multiplied_alpha();
|
|
||||||
|
|
||||||
self.set_pixel32_raw(dest_x as u32, dest_y as u32, new_color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(dirty_area) = &mut dirty_area {
|
|
||||||
dirty_area.encompass(dest_x as u32, dest_y as u32);
|
|
||||||
} else {
|
|
||||||
dirty_area = Some(PixelRegion::for_pixel(dest_x as u32, dest_y as u32));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(dirty_area) = dirty_area {
|
|
||||||
self.set_cpu_dirty(dirty_area);
|
|
||||||
}
|
|
||||||
|
|
||||||
modified_count
|
|
||||||
}
|
|
||||||
|
|
||||||
// Updates the data stored with our `BitmapHandle` if this `BitmapData`
|
// Updates the data stored with our `BitmapHandle` if this `BitmapData`
|
||||||
// is dirty
|
// is dirty
|
||||||
pub fn update_dirty_texture(&mut self, renderer: &mut dyn RenderBackend) {
|
pub fn update_dirty_texture(&mut self, renderer: &mut dyn RenderBackend) {
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::bitmap::bitmap_data::{BitmapData, BitmapDataWrapper, ChannelOptions, Color, LehmerRng};
|
use crate::bitmap::bitmap_data::{
|
||||||
|
BitmapData, BitmapDataWrapper, ChannelOptions, Color, LehmerRng, ThresholdOperation,
|
||||||
|
};
|
||||||
use crate::bitmap::turbulence::Turbulence;
|
use crate::bitmap::turbulence::Turbulence;
|
||||||
use crate::context::UpdateContext;
|
use crate::context::UpdateContext;
|
||||||
use gc_arena::GcCell;
|
use gc_arena::GcCell;
|
||||||
|
@ -463,3 +465,92 @@ pub fn color_transform<'gc>(
|
||||||
(x_max - 1, y_max - 1),
|
(x_max - 1, y_max - 1),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn threshold<'gc>(
|
||||||
|
context: &mut UpdateContext<'_, 'gc>,
|
||||||
|
target: BitmapDataWrapper<'gc>,
|
||||||
|
source_bitmap: BitmapDataWrapper<'gc>,
|
||||||
|
src_rect: (i32, i32, i32, i32),
|
||||||
|
dest_point: (i32, i32),
|
||||||
|
operation: ThresholdOperation,
|
||||||
|
threshold: u32,
|
||||||
|
colour: i32,
|
||||||
|
mask: u32,
|
||||||
|
copy_source: bool,
|
||||||
|
) -> u32 {
|
||||||
|
// Pre-compute the masked threshold
|
||||||
|
let masked_threshold = threshold & mask;
|
||||||
|
|
||||||
|
// Extract coords
|
||||||
|
let (src_min_x, src_min_y, src_width, src_height) = src_rect;
|
||||||
|
let (dest_min_x, dest_min_y) = dest_point;
|
||||||
|
|
||||||
|
// The number of modified pixels
|
||||||
|
// This doesn't seem to include pixels changed due to copy_source
|
||||||
|
let mut modified_count = 0;
|
||||||
|
let mut dirty_area: Option<PixelRegion> = None;
|
||||||
|
|
||||||
|
let target = target.sync();
|
||||||
|
let source_bitmap = source_bitmap.sync();
|
||||||
|
|
||||||
|
// dealing with object aliasing...
|
||||||
|
let src_bitmap_clone: BitmapData; // only initialized if source is the same object as self
|
||||||
|
let src_bitmap_data_cell = source_bitmap;
|
||||||
|
let src_bitmap_gc_ref; // only initialized if source is a different object than self
|
||||||
|
let source_bitmap_ref = // holds the reference to either of the ones above
|
||||||
|
if GcCell::ptr_eq(source_bitmap, target) {
|
||||||
|
src_bitmap_clone = src_bitmap_data_cell.read().clone();
|
||||||
|
&src_bitmap_clone
|
||||||
|
} else {
|
||||||
|
src_bitmap_gc_ref = src_bitmap_data_cell.read();
|
||||||
|
&src_bitmap_gc_ref
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut write = target.write(context.gc_context);
|
||||||
|
|
||||||
|
// Check each pixel
|
||||||
|
for src_y in src_min_y..(src_min_y + src_height) {
|
||||||
|
for src_x in src_min_x..(src_min_x + src_width) {
|
||||||
|
let dest_x = src_x - src_min_x + dest_min_x;
|
||||||
|
let dest_y = src_y - src_min_y + dest_min_y;
|
||||||
|
|
||||||
|
if !write.is_point_in_bounds(dest_x, dest_y)
|
||||||
|
|| !source_bitmap_ref.is_point_in_bounds(src_x, src_y)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract source colour
|
||||||
|
let source_color = source_bitmap_ref
|
||||||
|
.get_pixel32_raw(src_x as u32, src_y as u32)
|
||||||
|
.to_un_multiplied_alpha();
|
||||||
|
|
||||||
|
// If the test, as defined by the operation pass then set to input colour
|
||||||
|
if operation.matches(i32::from(source_color) as u32 & mask, masked_threshold) {
|
||||||
|
modified_count += 1;
|
||||||
|
write.set_pixel32_raw(dest_x as u32, dest_y as u32, Color::from(colour));
|
||||||
|
} else {
|
||||||
|
// If the test fails, but copy_source is true then take the colour from the source
|
||||||
|
if copy_source {
|
||||||
|
let new_color = source_bitmap_ref
|
||||||
|
.get_pixel32_raw(dest_x as u32, dest_y as u32)
|
||||||
|
.to_un_multiplied_alpha();
|
||||||
|
|
||||||
|
write.set_pixel32_raw(dest_x as u32, dest_y as u32, new_color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(dirty_area) = &mut dirty_area {
|
||||||
|
dirty_area.encompass(dest_x as u32, dest_y as u32);
|
||||||
|
} else {
|
||||||
|
dirty_area = Some(PixelRegion::for_pixel(dest_x as u32, dest_y as u32));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(dirty_area) = dirty_area {
|
||||||
|
write.set_cpu_dirty(dirty_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
modified_count
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue