Skip to content

Commit

Permalink
rust: Fix flaw where rectangles could be drawn without changing the c…
Browse files Browse the repository at this point in the history
…ompositing mode from blend_with_matte. No known bugs.
  • Loading branch information
lilith committed Jan 25, 2025
1 parent 40abfa0 commit cee19fa
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 23 deletions.
6 changes: 6 additions & 0 deletions imageflow_core/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@ impl BitmapBgra {


pub fn fill_rect(&mut self, x1: u32, y1: u32, x2: u32, y2: u32, color: &s::Color) -> Result<()> {
if self.compositing_mode == BitmapCompositingMode::BlendWithMatte{
if (0,0,self.w,self.h) != (x1,y1,x2,y2){
return Err(nerror!(ErrorKind::InvalidArgument, "Cannot draw on a sub-rectangle of a bitmap in BlendWithMatte mode"));
}
}

let color_srgb_argb = color.clone().to_u32_bgra().unwrap();
unsafe {
crate::graphics::fill::flow_bitmap_bgra_fill_rect(self, x1,y1,x2,y2, color_srgb_argb)
Expand Down
50 changes: 32 additions & 18 deletions imageflow_core/src/graphics/bitmaps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,8 @@ impl BitmapBuffer{

pub struct BitmapWindowMut<'a, T>{
slice: &'a mut [T],
info: BitmapInfo
info: BitmapInfo,
is_sub_window: bool
}

// impl debug for Bitmap
Expand Down Expand Up @@ -340,6 +341,7 @@ impl<'a,T> BitmapWindowMut<'a, T> {
BitmapWindowMut{
info: self.info.clone(),
slice: self.slice,
is_sub_window: self.is_sub_window
}
}

Expand All @@ -348,14 +350,16 @@ impl<'a,T> BitmapWindowMut<'a, T> {
return None;// Err(nerror!(ErrorKind::InvalidArgument, "x1,y1,x2,y2 must be within window bounds"));
}
let offset = (x1 * self.info.channels() as u32) + (y1 * self.info.item_stride());
let (orig_w, orig_h) = (self.w(), self.h());
Some(BitmapWindowMut{
slice: &mut self.slice[offset as usize..],
info: BitmapInfo {
w: x2 - x1,
h: y2 - y1,
item_stride: self.info.item_stride(),
info: self.info.info.clone()
}
},
is_sub_window: (x1,y1,x2,y2) != (0,0,orig_w,orig_h)
})
}

Expand All @@ -375,7 +379,8 @@ impl<'a,T> BitmapWindowMut<'a, T> {
self.info.h = y;
Some(BitmapWindowMut{
slice: bottom,
info: info2
info: info2,
is_sub_window: true
})
}

Expand All @@ -384,10 +389,17 @@ impl<'a,T> BitmapWindowMut<'a, T> {
impl<'a> BitmapWindowMut<'a, u8> {

pub fn fill_rect(&mut self, x: u32, y: u32, x2: u32, y2: u32, color: &imageflow_types::Color) -> Result<(), FlowError>{


let color_srgb_argb = color.to_color_32()?;
self.fill_rectangle(color_srgb_argb, x, y, x2, y2)
self.fill_rectangle(color_srgb_argb, x, y, x2, y2).map_err(|e| e.at(here!()))
}
pub fn fill_rectangle(&mut self, color: imageflow_helpers::colors::Color32, x: u32, y: u32, x2: u32, y2: u32) -> Result<(), FlowError>{
if let BitmapCompositing::BlendWithMatte(_) = self.info().compose(){
if self.is_sub_window || (x,y,x2,y2) != (0,0,self.w(),self.h()){
return Err(nerror!(ErrorKind::InvalidArgument, "Cannot draw a rectangle on a sub-rectangle of a bitmap in BlendWithMatte mode"));
}
}
if y2 == y || x2 == x { return Ok(()); } // Don't fail on zero width rect
if y2 <= y || x2 <= x || x2 > self.w() || y2 > self.h(){
return Err(nerror!(ErrorKind::InvalidArgument, "Coordinates {},{} {},{} must be within image dimensions {}x{}", x, y, x2, y2, self.w(), self.h())); }
Expand All @@ -399,21 +411,21 @@ impl<'a> BitmapWindowMut<'a, u8> {

let mut top = self.window(x, y, x2, y2).unwrap();

if y2 > y + 2{
// Supposed to be a bit faster to memcpy than memset?
let mut rest = top.split_off(1).unwrap();
for top_lines in top.scanlines_bgra().unwrap(){
top_lines.row.fill(bgra);
}

for line in rest.scanlines(){
line.row.copy_from_slice(&top.slice_mut()[0..line.row.len()]);
}
}else{
// if y2 > y + 2{
// // Supposed to be a bit faster to memcpy than memset?
// let mut rest = top.split_off(1).unwrap();
// for top_lines in top.scanlines_bgra().unwrap(){
// top_lines.row.fill(bgra);
// }

// for line in rest.scanlines(){
// line.row.copy_from_slice(&top.slice_mut()[0..line.row.len()]);
// }
// }else{
for line in top.scanlines_bgra().unwrap(){
line.row.fill(bgra);
}
}
//}

Ok(())
}
Expand Down Expand Up @@ -444,7 +456,8 @@ impl Bitmap{
self.get_u8_slice().map(|s| {
BitmapWindowMut{
slice: &mut s[offset..],
info
info,
is_sub_window: false
}
})
}
Expand All @@ -456,7 +469,8 @@ impl Bitmap{
self.get_f32_slice().map(|s| {
BitmapWindowMut{
slice: &mut s[offset..],
info
info,
is_sub_window: false
}
})
}
Expand Down
16 changes: 11 additions & 5 deletions imageflow_core/tests/visuals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1761,6 +1761,9 @@ fn test_detect_whitespace_all_small_images(){

let mut bitmap = bitmaps.try_borrow_mut(bitmap_key).unwrap();

bitmap.set_compositing(BitmapCompositing::BlendWithSelf);


let mut b = unsafe { bitmap.get_window_u8().unwrap().to_bitmap_bgra().unwrap() };

for (x, y, size_w, size_h) in on_canvas{
Expand Down Expand Up @@ -1821,16 +1824,18 @@ fn test_detect_whitespace_basic(){

{
let mut bitmap = bitmaps.try_borrow_mut(bitmap_key_a).unwrap();

bitmap.set_compositing(BitmapCompositing::BlendWithSelf);
let mut window = bitmap.get_window_u8().unwrap();

window.fill_rect(1, 1, 9, 9, &red).unwrap();
// This works if .to_bitmap_bgra() is called first
// or if

window.fill_rect(1, 1, 9, 9, &red).unwrap();
let mut b = unsafe { window.to_bitmap_bgra().unwrap() };

let r = ::imageflow_core::graphics::whitespace::detect_content(&b, 1).unwrap();
assert_eq!(r.x1, 1);
assert_eq!(r.y1, 1);
assert_eq!(r.x2, 9);
assert_eq!(r.y2, 9);
assert_eq!((r.x1, r.y1, r.x2, r.y2), (1, 1, 9, 9));
}

let bitmap_key_b = bitmaps.create_bitmap_u8(
Expand All @@ -1846,6 +1851,7 @@ fn test_detect_whitespace_basic(){

{
let mut bitmap = bitmaps.try_borrow_mut(bitmap_key_b).unwrap();
bitmap.set_compositing(BitmapCompositing::BlendWithSelf);
let mut window = bitmap.get_window_u8().unwrap();
window.fill_rect(2, 3, 70, 70, &red).unwrap();
let mut b = unsafe { bitmap.get_window_u8().unwrap().to_bitmap_bgra().unwrap() };
Expand Down

0 comments on commit cee19fa

Please sign in to comment.