Skip to content
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

Merged
merged 1 commit into from Jun 2, 2022

Conversation

tronical
Copy link
Member

@tronical tronical commented Jun 1, 2022

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.

@tronical tronical requested a review from ogoffart June 1, 2022 13:50
Comment on lines 530 to 545
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();

Copy link
Member Author

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?

Copy link
Member

@ogoffart ogoffart left a 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.

(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(
Copy link
Member

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.)

Copy link
Member Author

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.

Comment on lines 535 to 544
let geometry = euclid::Rect::new(Default::default(), clipped_src.size)
.scale(sx, sy)
.translate(offset)
.round();
Copy link
Member

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?

Copy link
Member Author

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).

@tronical
Copy link
Member Author

tronical commented Jun 1, 2022

But that is not in any of the coordinate system listed, this is a new one: the translated image.

You're right, this approach is introducing a fourth coordinate system, and that's not helping to make the code easier to understand.

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.

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 r ;)

@tronical
Copy link
Member Author

tronical commented Jun 1, 2022

But that is not in any of the coordinate system listed, this is a new one: the translated image.

On second thought, I think translating scaled_clip by source_clip.origin is better than translating t.rect.intersection(&source_clip) by -source_clip.origin. The former keeps everything in original image space, the latter introduces a translated image space.

Edit: Scratch that, Olivier's approach is the better one :)

@tronical tronical force-pushed the simon/mcu-clipped-source-image-fix branch from 77aeb03 to 5fb3dd7 Compare June 2, 2022 08:39
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.
@tronical tronical force-pushed the simon/mcu-clipped-source-image-fix branch from 5fb3dd7 to 2dfe52f Compare June 2, 2022 08:41
@tronical tronical merged commit 44f7bc1 into master Jun 2, 2022
@tronical tronical deleted the simon/mcu-clipped-source-image-fix branch June 2, 2022 13:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants