Skip to content

Commit

Permalink
StretchDIBits now stretches
Browse files Browse the repository at this point in the history
When doing a stretching bit copy, we don't clip the src rectangle to match the
dst, we instead transform coordinates to fit within the bounds.

Part of #43.
  • Loading branch information
evmar committed Oct 9, 2024
1 parent 388c86f commit 366ace6
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 43 deletions.
77 changes: 34 additions & 43 deletions win32/src/winapi/gdi32/bitmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,31 +346,6 @@ pub fn CreateCompatibleBitmap(machine: &mut Machine, hdc: HDC, cx: u32, cy: u32)
.add(Object::Bitmap(Bitmap::RGBA32(Rc::new(bitmap))))
}

fn copy_bitmap(
mem: Mem,
dst_bitmap: &BitmapRGBA32,
dst_rect: &RECT,
src_bitmap: &BitmapRGBA32,
src_rect: &RECT,
) {
let src_copy_rect = src_rect.clip(&src_bitmap.to_rect());
let dst_copy_rect = dst_rect.clip(&dst_bitmap.to_rect());

let copy_rect =
dst_copy_rect.clip(&src_copy_rect.add(dst_rect.origin().sub(src_rect.origin())));

let dst_to_src = src_rect.origin().sub(dst_rect.origin());

src_bitmap.pixels.with_slice(mem, |src| {
fill_pixels(mem, &*dst_bitmap, &copy_rect, |p, _| {
let p = p.add(dst_to_src);
let mut pixel = src[(p.y * src_bitmap.width as i32 + p.x) as usize];
pixel[3] = 0xFF;
pixel
});
});
}

#[win32_derive::dllexport]
pub fn SetDIBitsToDevice(
machine: &mut Machine,
Expand Down Expand Up @@ -416,14 +391,22 @@ pub fn SetDIBitsToDevice(
bottom: yDst + h,
};

copy_bitmap(
machine.emu.memory.mem(),
&*dst_bitmap,
&dst_rect,
&src_bitmap,
&src_rect,
);
// Clip copy region to the relevant bitmap bounds.
let src_copy_rect = src_rect.clip(&src_bitmap.to_rect());
let dst_copy_rect = dst_rect.clip(&dst_bitmap.to_rect());
let copy_rect =
dst_copy_rect.clip(&src_copy_rect.add(dst_rect.origin().sub(src_rect.origin())));
let dst_to_src = src_rect.origin().sub(dst_rect.origin());

let mem = machine.mem();
src_bitmap.pixels.with_slice(mem, |src| {
fill_pixels(mem, &*dst_bitmap, &copy_rect, |p, _| {
let p = p.add(dst_to_src);
let mut pixel = src[(p.y * src_bitmap.width as i32 + p.x) as usize];
pixel[3] = 0xFF;
pixel
});
});
target.flush(machine);

cLines
Expand All @@ -446,10 +429,6 @@ pub fn StretchDIBits(
iUsage: u32,
rop: Result<RasterOp, u32>,
) -> i32 {
if wSrc != wDst || hSrc != hDst {
log::warn!("TODO: StretchDIBits doesn't stretch");
}

match rop.unwrap() {
RasterOp::SRCCOPY => {}
_ => todo!(),
Expand Down Expand Up @@ -478,13 +457,25 @@ pub fn StretchDIBits(
bottom: yDst + hDst,
};

copy_bitmap(
machine.emu.memory.mem(),
&*dst_bitmap,
&dst_rect,
&src_bitmap,
&src_rect,
);
// TODO: do we need to clip src or dst rect?

let copy_rect = dst_rect;

let mem = machine.mem();
src_bitmap.pixels.with_slice(mem, |src| {
fill_pixels(mem, &*dst_bitmap, &dst_rect, |p, _| {
// Translate p from dst to src space.
// Because we're stretching, we scale to src space rather than clipping.
let p = p
.sub(dst_rect.origin())
.mul(src_rect.size())
.div(dst_rect.size())
.add(src_rect.origin());
let mut pixel = src[(p.y * src_bitmap.width as i32 + p.x) as usize];
pixel[3] = 0xFF;
pixel
});
});

target.flush(machine);

Expand Down
22 changes: 22 additions & 0 deletions win32/src/winapi/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,13 @@ impl RECT {
}
}

pub fn size(&self) -> POINT {
POINT {
x: self.right - self.left,
y: self.bottom - self.top,
}
}

pub fn contains(&self, point: POINT) -> bool {
point.x >= self.left && point.x < self.right && point.y >= self.top && point.y < self.bottom
}
Expand Down Expand Up @@ -85,12 +92,27 @@ impl POINT {
y: self.y + delta.y,
}
}

pub fn sub(&self, delta: POINT) -> POINT {
POINT {
x: self.x - delta.x,
y: self.y - delta.y,
}
}

pub fn mul(&self, o: POINT) -> POINT {
POINT {
x: self.x * o.x,
y: self.y * o.y,
}
}

pub fn div(&self, o: POINT) -> POINT {
POINT {
x: self.x / o.x,
y: self.y / o.y,
}
}
}

impl<'a> super::stack_args::FromStack<'a> for POINT {
Expand Down

0 comments on commit 366ace6

Please sign in to comment.