Discussion:
DC clipping bug with empty regions?
(too old to reply)
Ian Britten
2009-05-06 16:12:33 UTC
Permalink
Hi all,
[ wxGTK 2.8.9, GTK 2.12.9 ]
Can someone confirm that what I'm seeing is a bug in WX (or GTK),
and not my mis-understanding of how DC clipping with regions is
supposed to behave?

In my code, I dynamically build up a wxRegion to clip my graphics
against, using various criteria, and a series of
finalRegion.Intersect(currentRegion)
calls. No problems so far, and the results are as expected.

With this region built, I then set it on the DC before drawing:
wxDCClipper clip(theDC, finalRegion);
and in most cases, this works fine.

The problem seems to be the case when the finalRegion ends up
being IsEmpty(), due to the individual clip regions being disjoint
and there being no intersection between them.
In this workflow, I'd expect the DC to draw _nothing_, since I'm
only interested in seeing what satisfies the final region, and the
region is empty. What actually happens though is that *everything*
draws, as if the clip region was simply ignored by the DC.

I was able to add a workaround in my code to achieve my desired
effect, but I'm not sure if I should have to do this.
I worked around it by adding:
if (finalRegion.IsEmpty() == true)
finalRegion = wxRegion(-1, -1, 1, 1);
just before setting finalRegion on the DC, so the clip region is
a 1x1 pixel, just off the screen.

So, can anyone clarify whether this is a bug or intended?
Many thanks for any info!
Ian
Vadim Zeitlin
2009-05-07 08:55:14 UTC
Permalink
On Wed, 06 May 2009 13:12:33 -0300 Ian Britten <***@caris.com> wrote:

IB> With this region built, I then set it on the DC before drawing:
IB> wxDCClipper clip(theDC, finalRegion);
IB> and in most cases, this works fine.
IB>
IB> The problem seems to be the case when the finalRegion ends up
IB> being IsEmpty(), due to the individual clip regions being disjoint
IB> and there being no intersection between them.
IB> In this workflow, I'd expect the DC to draw nothing, since I'm
IB> only interested in seeing what satisfies the final region, and the
IB> region is empty. What actually happens though is that everything
IB> draws, as if the clip region was simply ignored by the DC.

This is intentional: setting an empty clipping region resets any existing
clipping. I do agree that it would be logical to expect it behave like you
did and the current behaviour is unnecessary because we have
DestroyClippingRegion() which can do the same thing explicitly, but this is
how the things used to work and changing them now wouldn't be a good idea.

This definitely should be documented though so I'll add a note about it to
wxDC docs.

IB> I was able to add a workaround in my code to achieve my desired
IB> effect, but I'm not sure if I should have to do this.
IB> I worked around it by adding:
IB> if (finalRegion.IsEmpty() == true)
IB> finalRegion = wxRegion(-1, -1, 1, 1);
IB> just before setting finalRegion on the DC, so the clip region is
IB> a 1x1 pixel, just off the screen.

Wouldn't it be simpler (and more efficient) to simply skip drawing
entirely if you detect that everything is clipped anyhow?

Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
Ian Britten
2009-05-07 11:11:45 UTC
Permalink
Post by Vadim Zeitlin
IB> The problem seems to be the case when the finalRegion ends up
IB> being IsEmpty(), due to the individual clip regions being disjoint
IB> and there being no intersection between them.
IB> In this workflow, I'd expect the DC to draw nothing, since I'm
IB> only interested in seeing what satisfies the final region, and the
IB> region is empty. What actually happens though is that everything
IB> draws, as if the clip region was simply ignored by the DC.
This is intentional: setting an empty clipping region resets any existing
clipping. I do agree that it would be logical to expect it behave like you
did and the current behaviour is unnecessary because we have
DestroyClippingRegion() which can do the same thing explicitly, but this is
how the things used to work and changing them now wouldn't be a good idea.
That's what I had suspected - Thanks for confirming it!
Post by Vadim Zeitlin
This definitely should be documented though so I'll add a note about it to
wxDC docs.
Thanks - I was going to suggest that...
Post by Vadim Zeitlin
IB> I was able to add a workaround in my code to achieve my desired
IB> effect, but I'm not sure if I should have to do this.
IB> if (finalRegion.IsEmpty() == true)
IB> finalRegion = wxRegion(-1, -1, 1, 1);
IB> just before setting finalRegion on the DC, so the clip region is
IB> a 1x1 pixel, just off the screen.
Wouldn't it be simpler (and more efficient) to simply skip drawing
entirely if you detect that everything is clipped anyhow?
D'Oh! You're probably right. I had been too focused getting to the
root of this problematic edge-case that I probably didn't consider
that option.

Many thanks!
Ian

Loading...