New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix rendering of source clipped images with the MCU renderer #1305
Conversation
internal/backends/mcu/renderer.rs
Outdated
let geometry = clipped_src.scale(sx, sy).translate(offset).round(); | ||
let geometry = euclid::Rect::new(Default::default(), clipped_src.size) | ||
.scale(sx, sy) | ||
.translate(offset) | ||
.round(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could also be written differently, if you prefer: Create the rectangle from offset as origin and size directly calculated by taking clipped_src.size scaled with sx/sy. Maybe that's clearer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the part in draw_clipped_image and draw_image. It makes sense to have the source_clip limited to the actual size of the image.
However, the merging with the actual clip seems off.
There are 3 coordinate system to take care of:
- the logical one
- the physical one
- the image one
scaled_clip is transforming the current_state.clip which is in logical coordinate to the image coordinate.
But then you add a translation by the source_clip.origin that make sense because the image should actually be translated by that amount. But that is not in any of the coordinate system listed, this is a new one: the translated image. So clipped_src will then be in that referential too.
The geometry then is in physical coordinate. But it should match to the location of the clipped rect of the image to the physical screen. In particular, you are dropping the clipped part from the clip. (making it potentially rendering into area that should be clipped away)
I think one proper fix here is to translate t.rect.intersection(&source_clip)
by -source_clip.origin
to move the image coordinate into the translated image coordinate.
the actual_x and actual_y also need to be adjusted.
In other word, i think we should apply the transformation by source_clip.origin on the image coordinate
I really would love to see some rendering tests that render a small scene into a .png so we can do image comparison.
internal/backends/mcu/renderer.rs
Outdated
(self.current_state.clip.cast() * self.scale_factor).scale(1. / sx, 1. / sy); | ||
let scaled_clip = (self.current_state.clip.cast() * self.scale_factor) | ||
.scale(1. / sx, 1. / sy) | ||
.translate(euclid::Vector2D::<_, PhysicalPx>::new( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is that not source_clip.origin.to_vector()
?
(there is also the `euclid::vec2' helper function to simplify that kind of code.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's true. Modulo the type tag.
internal/backends/mcu/renderer.rs
Outdated
let geometry = euclid::Rect::new(Default::default(), clipped_src.size) | ||
.scale(sx, sy) | ||
.translate(offset) | ||
.round(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ignores clipped_src.origin and i think it is wrong if the image is clipped. You can try the x
button in the printer demo when scrolled partially out of the ListView. Does it still looks alright?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right, the scaled clip could cover the top-left of the Image
geometry and thus should adjust clipped_src.origin
(in image space through the intersection
call).
You're right, this approach is introducing a fourth coordinate system, and that's not helping to make the code easier to understand.
You're right, that's simpler and appears to work as well (and certainly won't suffer from the missing origin breaking the renderer's clip). I'll add comments to explain the steps (and will rename |
On second thought, I think translating Edit: Scratch that, Olivier's approach is the better one :) |
77aeb03
to
5fb3dd7
Compare
The slide puzzle makes use of the source-clip-* properties and that unveiled three issues: * For the scale factor from image space to physical pixel space (sx/sy), use the source clip size, as we're only drawing those pixels. That means that the call sites of draw_image_impl need to pass the correct original image size if there is no source clip. * Similarly, the scaled_clip is in image coordinates, but needs to be relative to the source-clip-x/y * The geometry for the target rectangle on screen must originate at (0, 0) so that the apllication of sx/sy only changes the size.
5fb3dd7
to
2dfe52f
Compare
The slide puzzle makes use of the source-clip-* properties and that unveiled three issues:
use the source clip size, as we're only drawing those
pixels. That means that the call sites of draw_image_impl need to pass the
correct original image size if there is no source clip.
must originate at (0, 0) so that the apllication of
sx/sy only changes the size.