[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: NSView patch
From: |
Nicola Pero |
Subject: |
Re: NSView patch |
Date: |
Mon, 23 Feb 2009 17:37:39 +0100 |
I would say that the algorithm followed by GUI must be incorrect in
the case
of overlapping siblings - while a normal floating
point mismatch in computing areas that need drawing could result in
some
areas being redrawn unnecessarily, I fail to
see how it could cause a major part of a view to be drawn *above*
the views
above it, as in the screenshot ... unless there
is an error in the drawing logic. But possibly making it correct for
overlapping siblings might make it too expensive
in the normal case of nested views ? (that's what the Apple
documentation
suggests)
because of the floating point mismatch, whole views are not set as not
needing display after drawing
I completely agree with this. I had a look and you are completely
right. :-)
You can't even see the problem by using NSStringFromRect(), because
it prints coordinates using %g, which does not print enough significant
digits (shall we fix that ?). ;-)
But if you hack NSStringFromRect() to use %f, you can see that the
coordinate
conversions in the GUI introduces floating point errors ... at least
in the case of
DBModeler (couldn't find another example).
In my experiment, the conversion error occurred for a view with frame --
x=281.721222, y=148.529358, width=150.000000, height=70.000000
when the frame was converted into the view's own coordinate system, it
became
x=0.000000, y=0.000000, width=149.99969, height=70.000000
So, the GUI started trying to redraw the entire view; it took the
view's frame,
and converted it into the view's coordinate system to get the area to
redraw.
Because of the rounding error, the area to redraw ended up being
smaller,
by 0.00031 pixels, than the bounds. So the area was redrawn, but the
view was still not marked as fully redrawn because of the area redrawn
was smaller than the bounds. :-(
Now this is definitely a performance issue since the view will keep
getting
redrawn due to the rounding error; but it shouldn't generate any invalid
display. ;-)
I'm not sure how you fix this; I'm not too keen on forcing different
floating
point values to be considered equal ;-) ... either the coordinate
conversion
should be improved, or some more robust logic could be used ... trying
to reduce the number of conversions and the effect of rounding
errors. Maybe
we could always redraw an area that is slightly larger than the
frame ? Or
we could use the bounds instead of taking the frame and converting ?
unfortunately for our unsuspecting view, subviews which were at some
odd coordinate were left as needing display, when their super views
noticed that they were still marked as needing display and redisplayed
only those. (in case a view calls -setNeedsDisplay: on something while
in drawRect:)
Yes. This is where there seems to be an error in the logic in the
current code - ie,
support for overlapping sibling views is missing. If a view is
redrawn, all views
that above it must always be redrawn too. ;-)
So, if view A is still marked as needing redisplay, and view B is on top
of it, both A and B must be redrawn, even if B is not marked as needing
redisplay. The current code in the GUI doesn't do that; it iterates
over the
subviews, and redraws the ones marked for redisplay, but doesn't redraw
any other one, without considering that if we support overlapping
sibling views,
it also needs to redraw all the other views that are on top of the
ones being
redrawn. ;-)
In the standard situation where there are no overlapping views, adding
support
for overlapping sibling views in that way would mean a lot of
pointless redrawing
though - because if view A is redrawn, then all views following it in
the list of subviews
would be redrawn even if they are not actually overlapping A. In
other words,
any time anything changes in a window, everything needs to be
redrawn. :-(
Presumably the code could try to only redraw views that are over
(according
to the list of views) *and* that overlap the ones that needed to be
redrawn.
I'm not sure how to do that computation efficiently though ... I
suppose for
every view that is redrawn, you also iterate over all the views above it
looking for ones that overlap, and redraw these as well. That sounds
potentially
expensive (N^2) if there are a lot of subviews ... :-(
Thanks
- NSView patch, Matt Rice, 2009/02/22
- Re: NSView patch, Matt Rice, 2009/02/22
- Re: NSView patch, Richard Frith-Macdonald, 2009/02/23
- Re: NSView patch, Matt Rice, 2009/02/23
- Fwd: NSView patch, Richard Frith-Macdonald, 2009/02/23
- Re: NSView patch, Nicola Pero, 2009/02/23
- Re: NSView patch, Matt Rice, 2009/02/23
- Re: NSView patch,
Nicola Pero <=
- Re: NSView patch, Matt Rice, 2009/02/23
- Re: Fwd: NSView patch, Fred Kiefer, 2009/02/23
- Re: Fwd: NSView patch, Matt Rice, 2009/02/23
- Re: Fwd: NSView patch, Fred Kiefer, 2009/02/23
- Re: Fwd: NSView patch, Matt Rice, 2009/02/24
- Re: Fwd: NSView patch, Fred Kiefer, 2009/02/26