core: Move palette_map from BitmapData to bitmap_data_operations
This commit is contained in:
parent
b1b0394101
commit
8a0cb4685e
|
@ -1173,22 +1173,10 @@ pub fn palette_map<'gc>(
|
|||
|
||||
if let Some(src_bitmap) = source_bitmap.as_bitmap_data_object() {
|
||||
if !src_bitmap.disposed() {
|
||||
// dealing with object aliasing...
|
||||
let src_bitmap_data_cell = src_bitmap.bitmap_data();
|
||||
let read;
|
||||
let source: Option<&BitmapData> =
|
||||
if GcCell::ptr_eq(src_bitmap_data_cell, bitmap_data.bitmap_data()) {
|
||||
None
|
||||
} else {
|
||||
read = src_bitmap_data_cell.read();
|
||||
Some(&read)
|
||||
};
|
||||
|
||||
bitmap_data
|
||||
.bitmap_data()
|
||||
.write(activation.context.gc_context)
|
||||
.palette_map(
|
||||
source,
|
||||
bitmap_data_operations::palette_map(
|
||||
&mut activation.context,
|
||||
bitmap_data.bitmap_data_wrapper(),
|
||||
src_bitmap.bitmap_data_wrapper(),
|
||||
(src_min_x, src_min_y, src_width, src_height),
|
||||
(dest_x, dest_y),
|
||||
(red_array, green_array, blue_array, alpha_array),
|
||||
|
|
|
@ -1135,11 +1135,11 @@ pub fn palette_map<'gc>(
|
|||
this: Option<Object<'gc>>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
if let Some(bitmap_data) = this.and_then(|this| this.as_bitmap_data()) {
|
||||
bitmap_data.read().check_valid(activation)?;
|
||||
if let Some(bitmap_data) = this.and_then(|this| this.as_bitmap_data_wrapper()) {
|
||||
bitmap_data.check_valid(activation)?;
|
||||
let source_bitmap = args
|
||||
.get_object(activation, 0, "sourceBitmapData")?
|
||||
.as_bitmap_data()
|
||||
.as_bitmap_data_wrapper()
|
||||
.unwrap();
|
||||
|
||||
let source_rect = args.get_object(activation, 1, "sourceRect")?;
|
||||
|
@ -1183,19 +1183,10 @@ pub fn palette_map<'gc>(
|
|||
let blue_array = get_channel(5, 0)?;
|
||||
let alpha_array = get_channel(6, 24)?;
|
||||
|
||||
let read;
|
||||
let source: Option<&BitmapData> = if GcCell::ptr_eq(source_bitmap, bitmap_data) {
|
||||
None
|
||||
} else {
|
||||
read = source_bitmap.read();
|
||||
read.check_valid(activation)?;
|
||||
Some(&read)
|
||||
};
|
||||
|
||||
bitmap_data
|
||||
.write(activation.context.gc_context)
|
||||
.palette_map(
|
||||
source,
|
||||
bitmap_data_operations::palette_map(
|
||||
&mut activation.context,
|
||||
bitmap_data,
|
||||
source_bitmap,
|
||||
(source_point.0, source_point.1, source_size.0, source_size.1),
|
||||
dest_point,
|
||||
(red_array, green_array, blue_array, alpha_array),
|
||||
|
|
|
@ -824,58 +824,6 @@ impl<'gc> BitmapData<'gc> {
|
|||
self.set_cpu_dirty(dirty_region);
|
||||
}
|
||||
|
||||
// Unlike `copy_channel` and `copy_pixels`, this function seems to
|
||||
// operate "in-place" if the source bitmap is the same object as `self`.
|
||||
// This means that we can't resolve this aliasing issue in Rust by a
|
||||
// simple clone in the caller. Instead, if the `source_bitmap` parameter
|
||||
// is `None`, it means that `self` should be used as source as well.
|
||||
pub fn palette_map(
|
||||
&mut self,
|
||||
source_bitmap: Option<&Self>,
|
||||
src_rect: (i32, i32, i32, i32),
|
||||
dest_point: (i32, i32),
|
||||
channel_arrays: ([u32; 256], [u32; 256], [u32; 256], [u32; 256]),
|
||||
) {
|
||||
let (src_min_x, src_min_y, src_width, src_height) = src_rect;
|
||||
let (dest_min_x, dest_min_y) = dest_point;
|
||||
|
||||
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
|
||||
.unwrap_or(self)
|
||||
.is_point_in_bounds(src_x, src_y)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let source_color = source_bitmap
|
||||
.unwrap_or(self)
|
||||
.get_pixel32_raw(src_x as u32, src_y as u32)
|
||||
.to_un_multiplied_alpha();
|
||||
|
||||
let r = channel_arrays.0[source_color.red() as usize];
|
||||
let g = channel_arrays.1[source_color.green() as usize];
|
||||
let b = channel_arrays.2[source_color.blue() as usize];
|
||||
let a = channel_arrays.3[source_color.alpha() as usize];
|
||||
|
||||
let sum = u32::wrapping_add(u32::wrapping_add(r, g), u32::wrapping_add(b, a));
|
||||
let mix_color = Color(sum as i32).to_premultiplied_alpha(true);
|
||||
|
||||
self.set_pixel32_raw(dest_x as u32, dest_y as u32, mix_color);
|
||||
}
|
||||
}
|
||||
let mut dirty_region = PixelRegion::encompassing_pixels_i32(
|
||||
((dest_min_x), (dest_min_y)),
|
||||
((dest_min_x + src_width), (dest_min_y + src_height)),
|
||||
);
|
||||
dirty_region.clamp(self.width, self.height);
|
||||
self.set_cpu_dirty(dirty_region);
|
||||
}
|
||||
|
||||
// Updates the data stored with our `BitmapHandle` if this `BitmapData`
|
||||
// is dirty
|
||||
pub fn update_dirty_texture(&mut self, renderer: &mut dyn RenderBackend) {
|
||||
|
|
|
@ -607,3 +607,68 @@ pub fn scroll<'gc>(
|
|||
let region = PixelRegion::for_whole_size(write.width(), write.height());
|
||||
write.set_cpu_dirty(region);
|
||||
}
|
||||
|
||||
pub fn palette_map<'gc>(
|
||||
context: &mut UpdateContext<'_, 'gc>,
|
||||
target: BitmapDataWrapper<'gc>,
|
||||
source_bitmap: BitmapDataWrapper<'gc>,
|
||||
src_rect: (i32, i32, i32, i32),
|
||||
dest_point: (i32, i32),
|
||||
channel_arrays: ([u32; 256], [u32; 256], [u32; 256], [u32; 256]),
|
||||
) {
|
||||
let (src_min_x, src_min_y, src_width, src_height) = src_rect;
|
||||
let (dest_min_x, dest_min_y) = dest_point;
|
||||
|
||||
let target = target.sync();
|
||||
let source_bitmap = source_bitmap.sync();
|
||||
|
||||
// Unlike `copy_channel` and `copy_pixels`, this function seems to
|
||||
// operate "in-place" if the source bitmap is the same object as the destination.
|
||||
let source_bitmap = if GcCell::ptr_eq(source_bitmap, target) {
|
||||
None
|
||||
} else {
|
||||
Some(source_bitmap.read())
|
||||
};
|
||||
|
||||
let mut write = target.write(context.gc_context);
|
||||
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let source_color = if let Some(source) = &source_bitmap {
|
||||
if !source.is_point_in_bounds(src_x, src_y) {
|
||||
continue;
|
||||
}
|
||||
source
|
||||
.get_pixel32_raw(src_x as u32, src_y as u32)
|
||||
.to_un_multiplied_alpha()
|
||||
} else {
|
||||
write
|
||||
.get_pixel32_raw(src_x as u32, src_y as u32)
|
||||
.to_un_multiplied_alpha()
|
||||
};
|
||||
|
||||
let r = channel_arrays.0[source_color.red() as usize];
|
||||
let g = channel_arrays.1[source_color.green() as usize];
|
||||
let b = channel_arrays.2[source_color.blue() as usize];
|
||||
let a = channel_arrays.3[source_color.alpha() as usize];
|
||||
|
||||
let sum = u32::wrapping_add(u32::wrapping_add(r, g), u32::wrapping_add(b, a));
|
||||
let mix_color = Color::from(sum as i32).to_premultiplied_alpha(true);
|
||||
|
||||
write.set_pixel32_raw(dest_x as u32, dest_y as u32, mix_color);
|
||||
}
|
||||
}
|
||||
let mut dirty_region = PixelRegion::encompassing_pixels_i32(
|
||||
((dest_min_x), (dest_min_y)),
|
||||
((dest_min_x + src_width), (dest_min_y + src_height)),
|
||||
);
|
||||
dirty_region.clamp(write.width(), write.height());
|
||||
write.set_cpu_dirty(dirty_region);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue