Closed Bug 215567 Opened 21 years ago Closed 20 years ago

Absolute positioned element doesn't paint correctly when 'clip' changes

Categories

(Core :: Web Painting, defect, P2)

x86
All
defect

Tracking

()

RESOLVED FIXED

People

(Reporter: cmattar, Assigned: roc)

Details

(Keywords: regression, testcase)

Attachments

(2 files, 1 obsolete file)

Open the testcase.
After the image has loaded, the clip-property of the image is changed by
Javascript, but the now visible area isn't completely painted.
Attached file Testcase
It seems the bug only appears when doing a Shift-Reload of the testcase.
Bug also occurs in trunk build 2003-08-04-05 and with Mozilla 1.4 on Linux.
It does NOT seem to occur with Mozilla 1.3.1 on Linux
Keywords: regression, testcase
OS: Windows XP → All
Attached patch fix (obsolete) — Splinter Review
This turned out to be a subtle one. 'auto' clip values were being stored as
zero in the mClip rect, and in the testcase both the old and new rects have
'auto' as the top and bottom values. Thus the old and new mClip both appeared
to be zero height and so old mClip == new mClip since they're both empty! thus
we failed to compute the right change hint.

I think the right solution is to change mClip to be something other than
nsRect, so we never accidentally treat 0 values are indicating an empty rect.
Comment on attachment 142730 [details] [diff] [review]
fix

This is a simple review, I think.
Attachment #142730 - Flags: superreview?(bzbarsky)
Attachment #142730 - Flags: review?(bzbarsky)
Comment on attachment 142730 [details] [diff] [review]
fix

>Index: content/shared/public/nsStyleStruct.h
>+  nsClipRect       mClip;       // [reset] offsets from upper-left border edge;
>+  // not an nsRect because 0 values don't always mean zero (see mClipFlags),
>+  // so IsEmpty(), == etc don't do the right thing

I'd put the comment before the var.  r+sr=bzbarsky with that.

On the other hand, wouldn't it be simpler to use 0 for auto top and left while
using NS_UNCONSTRAINEDSIZE or something for auto right and bottom?  That should
also solve the problem (and the values are more meaningful too), no?
Attachment #142730 - Flags: superreview?(bzbarsky)
Attachment #142730 - Flags: superreview+
Attachment #142730 - Flags: review?(bzbarsky)
Attachment #142730 - Flags: review+
> That should also solve the problem (and the values are more meaningful too),
> no?

You mean use NS_UNCONSTRAINEDSIZE for auto width/height and then keep mClip as
an nsRect?

I guess that would work. The important property is that if the actual clip rect
changes, then mClip != other.mClip or mClipFlags != other.mClipFlags. Proving
that that's so is actually a little subtle. You have the underlying style rect
Shape = (Z U {auto})^4, and two functions, f : Shape x nsSize -> nsRect
interpreting the style for a particular frame's size and g : Shape -> nsRect
storing the style in mClip, and you have to show that for all size, shape,
shape', f(shape, size).nsRect::operator!=(f(shape', size)) implies
g(shape).nsRect::operator!=(g(shape')) or flags(shape) != flags(shape') where
flags : Shape -> {auto, nonauto}^4.

That's fairly easy to prove if you start by assuming
g(shape).nsRect::operator==(g(shape')) and flags(shape) == flags(shape') and
show f(shape, size).nsRect::operator==(f(shape', size)).

Suppose g(shape).IsEmpty(). Then g(shape').IsEmpty(). Also, (shape.bottom !=
auto && shape.bottom <= shape.top (or 0 if shape.top is auto)) || (shape.right
!= auto && shape.right <= shape.left (or 0 if shape.left is auto)). If
(shape.bottom != auto && shape.bottom <= shape.top (or 0 if shape.top is auto)),
then f(shape, size).height <= 0. Likewise on the other hand f(shape, size).width
<= 0. Then f(shape, size).IsEmpty(). Similarly f(shape', size).IsEmpty(). We're
done.

Now suppose !g(shape).IsEmpty(). Then !g(shape').IsEmpty() && g(shape).x ==
g(shape').x && g(shape).y == g(shape').y && g(shape).width == g(shape').width &&
g(shape').height == g(shape').height. Clearly shape == shape' and therefore
f(shape, size) == f(shape', size).

And people wonder why program verification never got off the ground :-).

Note that we'll still need mClipFlags, or at least two bits of it, with this
approach, to distinguish auto from 0 in top and left, which I presume we need to
do so computed style values are returned correctly.
> Note that we'll still need mClipFlags, or at least two bits of it, with this
> approach, to distinguish auto from 0 in top and left

And to distinguish auto right/bottom from people actually setting a huge value
there....

Anyway, whichever approach you prefer is fine with me, really.  I guess the
approach you took in your patch is a lot easier to prove correct... ;)
don't we bound CSS values somehow? I notice that the CSS spec doesn't restrict
min/max values on integers :-(
We have a bug somewhere that a large positive pixel width in a CSS sheet will
overflow to a negative number of twips (since it will be positive at parse time,
hence will not get dropped, but the number of twips is bigger).

So no, we don't bound.
Presumably because, as you pointed out, the spec does not.
Attached patch fix #2Splinter Review
Okay, I think NS_MAXSIZE is the right way to go. It has the advantage that if
you change from one genuinely empty rect to another, we don't generate any
style change hint. And the patch is trivial.
Attachment #142730 - Attachment is obsolete: true
Attachment #142805 - Flags: superreview?(bzbarsky)
Attachment #142805 - Flags: review?(bzbarsky)
Comment on attachment 142805 [details] [diff] [review]
fix #2

r+sr=bzbarsky
Attachment #142805 - Flags: superreview?(bzbarsky)
Attachment #142805 - Flags: superreview+
Attachment #142805 - Flags: review?(bzbarsky)
Attachment #142805 - Flags: review+
Checked in. Thanks bz!
Status: NEW → RESOLVED
Closed: 20 years ago
Resolution: --- → FIXED
Component: Layout: View Rendering → Layout: Web Painting
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: