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

Keep clipping inside containers. #639

Merged
merged 5 commits into from
Apr 28, 2020
Merged

Conversation

PreferLinux
Copy link
Contributor

Containers need to maintain the clipping that exists outside them.

I have implemented this by storing the overall clip region outside the current container (graphics->previous_clip, NULL if not in a container or if no clipping outside) in addition to any clip region set (graphics->clip), and then intersecting them in cairo_SetGraphicsClip(), GdipBeginContainer2() and GdipGetVisibleClipBounds() (the three places that need the overall clip). previous_clip goes on the save stack on saving, in addition to clip.

Alternatively the intersection could be done when modifying the clip and when restoring it off the save stack (four places), but that would mean storing the resulting region as well as the other two, although the overall clip wouldn't need to be stored on the save stack. (GdipTranslateClip(), GdipGetClip() and GdipGetClipBounds() need the clip that was set.)

Also, I modified GdipResetClip() to call cairo_SetGraphicsClip() rather than cairo_ResetClip() when previous_clip exists, as it needs to keep that. Alternatively, it would be possible to modify cairo_ResetClip() to set the clip to previous_clip itself.

I have implemented this into GdipGetVisibleClipBounds(), as that should provide the overall clip bounds. And I changed GdipIsVisiblePoint() and GdipIsVisibleRect() to use that instead of the graphics->bounds (they should take clipping into account). I won't mention the insane check previously used in the latter of those two methods, but the replacement was taken from region.c – ideally I'd have added a declaration for it to region-private.h, but I didn't think gdip_intersects() was a descriptive enough name for that, and I didn't want to do a rename.

I guess I should write some tests too, so I'll try to get around to that some time soon. But I'll put this out there now for any comments.

@PreferLinux
Copy link
Contributor Author

I realised shortly after I posted this yesterday that GdipIsVisiblePoint() and GdipIsVisibleRect() should not be using the clip bounds, they should be using the clip itself... So I'll sort that out. I'll also change to the alternative I mentioned above, because that'll result in less intersecting of clip with previous_clip.

Store the overall clip, and calculate it when modifying the clip.

GdipIsVisiblePoint() and GdipIsVisibleRect() need to use the visible
clip, not just its bounds.
@filipnavara
Copy link
Contributor

filipnavara commented Apr 27, 2020

Sorry it is taking me so long to review this. I'm still going through the ASAN reports (after applying @akoeplinger's test patches). There are some leaks reported and I have to figure out whether they are false positives, pre-existing leaks, or something introduced by this PR (likely mix of all of this).

gdip_cairo_matrix_copy (graphics->clip_matrix, &pos_state->clip_matrix);

gdip_calculate_overall_clipping (graphics);
Copy link
Contributor

@filipnavara filipnavara Apr 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

graphics->overall_clip is leaked at this point. Couple of lines above you set graphics->previous_clip to NULL (and pos_state->previous_clip can be NULL too). This causes gdip_calculate_overall_clipping to enter this code path:

	if (!graphics->previous_clip) {
		graphics->overall_clip = graphics->clip;
	}

and never free the original overall_clip.

src/graphics.c Outdated Show resolved Hide resolved
Copy link
Contributor

@filipnavara filipnavara left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found one memory leak in the PR and one other preexisting one (#649). I wrote down a suggestion on how to fix it, otherwise LGTM.

Co-Authored-By: Filip Navara <[email protected]>
@PreferLinux
Copy link
Contributor Author

Thanks for picking that up. Your suggested fix looks good to me, so I've committed it.

@akoeplinger akoeplinger merged commit 87eba4c into mono:master Apr 28, 2020
@PreferLinux PreferLinux deleted the clipping-fixes branch April 28, 2020 20:28
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.

3 participants