Changeset 41203 in webkit


Ignore:
Timestamp:
Feb 24, 2009 5:21:03 PM (15 years ago)
Author:
hyatt@apple.com
Message:

WebCore:

2009-02-23 David Hyatt <hyatt@apple.com>

Reviewed by Eric Seidel

https://bugs.webkit.org/show_bug.cgi?id=23740, painting order wrong for normal flow elements with overflow: hidden


This patch reworks the painting of overflow. There is now the concept of a "self-painting layer." All
layers are considered to be self-painting except for overflow layers that are normal flow (and that don't have
reflections or masks).


If an overflow layer is not self-painting, then it ends up painted by its parent just like any other normal flow object.
The only difference is that the clip has to be pushed and popped when painting the object's children.


The lightweight clipping scheme used for controls has been extended to cover overflow now in this simplified case. With
the code consolidated into reusable push/pop functions, all of the renderers that use overflow have been patched to
use the new functions.


Hit testing has also been patched to check the overflow clip rect first before recurring into children.


Scrollbar paint has been moved into RenderBlock for now, since none of the table objects support scrollbars
yet, and scrollbar hit testing was already there anyway. Now the two code paths are more symmetrical.


Masks are now treated like normal flow layers (just like reflections).

A couple of test cases have been added to fast/overflow to test the stacking order.

  • rendering/InlineFlowBox.cpp: (WebCore::InlineFlowBox::nodeAtPoint): (WebCore::InlineFlowBox::paint):
  • rendering/RenderBlock.cpp: (WebCore::RenderBlock::repaintOverhangingFloats): (WebCore::RenderBlock::paint): (WebCore::RenderBlock::paintChildren): (WebCore::RenderBlock::paintObject): (WebCore::RenderBlock::paintFloats): (WebCore::RenderBlock::insertFloatingObject): (WebCore::RenderBlock::floatRect): (WebCore::RenderBlock::lowestPosition): (WebCore::RenderBlock::rightmostPosition): (WebCore::RenderBlock::leftmostPosition): (WebCore::RenderBlock::addOverhangingFloats): (WebCore::RenderBlock::nodeAtPoint): (WebCore::RenderBlock::hitTestContents):
  • rendering/RenderBox.cpp: (WebCore::RenderBox::nodeAtPoint): (WebCore::RenderBox::pushContentsClip): (WebCore::RenderBox::popContentsClip):
  • rendering/RenderBox.h: (WebCore::RenderBox::paintObject):
  • rendering/RenderBoxModelObject.cpp: (WebCore::RenderBoxModelObject::hasSelfPaintingLayer):
  • rendering/RenderBoxModelObject.h:
  • rendering/RenderLayer.cpp: (WebCore::RenderLayer::paintLayer): (WebCore::RenderLayer::hitTestLayer): (WebCore::RenderLayer::shouldBeNormalFlowOnly): (WebCore::RenderLayer::isSelfPaintingLayer):
  • rendering/RenderLayer.h:
  • rendering/RenderTable.cpp: (WebCore::RenderTable::paint): (WebCore::RenderTable::paintObject): (WebCore::RenderTable::nodeAtPoint):
  • rendering/RenderTable.h:
  • rendering/RenderTableCell.cpp: (WebCore::RenderTableCell::paint):
  • rendering/RenderTableRow.cpp: (WebCore::RenderTableRow::nodeAtPoint): (WebCore::RenderTableRow::paint):
  • rendering/RenderTableRow.h:
  • rendering/RenderTableSection.cpp: (WebCore::RenderTableSection::paint): (WebCore::RenderTableSection::paintObject): (WebCore::RenderTableSection::nodeAtPoint):
  • rendering/RenderTableSection.h:
  • rendering/RenderTreeAsText.cpp: (WebCore::write): (WebCore::writeLayers):

LayoutTests:

2009-02-24 David Hyatt <hyatt@apple.com>

Reviewed by Eric Seidel

https://bugs.webkit.org/show_bug.cgi?id=23740, painting order wrong for normal flow elements with overflow: hidden


This patch reworks the painting of overflow. There is now the concept of a "self-painting layer." All
layers are considered to be self-painting except for overflow layers that are normal flow (and that don't have
reflections or masks).


If an overflow layer is not self-painting, then it ends up painted by its parent just like any other normal flow object.
The only difference is that the clip has to be pushed and popped when painting the object's children.


The lightweight clipping scheme used for controls has been extended to cover overflow now in this simplified case. With
the code consolidated into reusable push/pop functions, all of the renderers that use overflow have been patched to
use the new functions.


Hit testing has also been patched to check the overflow clip rect first before recurring into children.


Scrollbar paint has been moved into RenderBlock for now, since none of the table objects support scrollbars
yet, and scrollbar hit testing was already there anyway. Now the two code paths are more symmetrical.


Masks are now treated like normal flow layers (just like reflections).


A couple of test cases have been added to fast/overflow to test the stacking order.

  • fast/overflow/overflow-float-stacking.html: Added.
  • fast/overflow/overflow-stacking.html: Added.
  • platform/mac/fast/overflow/overflow-float-stacking-expected.checksum: Added.
  • platform/mac/fast/overflow/overflow-float-stacking-expected.png: Added.
  • platform/mac/fast/overflow/overflow-float-stacking-expected.txt: Added.
  • platform/mac/fast/overflow/overflow-stacking-expected.checksum: Added.
  • platform/mac/fast/overflow/overflow-stacking-expected.png: Added.
  • platform/mac/fast/overflow/overflow-stacking-expected.txt: Added.
Location:
trunk
Files:
8 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r41201 r41203  
     12009-02-24  David Hyatt  <hyatt@apple.com>
     2
     3        Reviewed by Eric Seidel
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=23740, painting order wrong for normal flow elements with overflow: hidden
     6       
     7        This patch reworks the painting of overflow.  There is now the concept of a "self-painting layer."  All
     8        layers are considered to be self-painting except for overflow layers that are normal flow (and that don't have
     9        reflections or masks).
     10       
     11        If an overflow layer is not self-painting, then it ends up painted by its parent just like any other normal flow object.
     12        The only difference is that the clip has to be pushed and popped when painting the object's children.
     13       
     14        The lightweight clipping scheme used for controls has been extended to cover overflow now in this simplified case.  With
     15        the code consolidated into reusable push/pop functions, all of the renderers that use overflow have been patched to
     16        use the new functions.
     17       
     18        Hit testing has also been patched to check the overflow clip rect first before recurring into children.
     19       
     20        Scrollbar paint has been moved into RenderBlock for now, since none of the table objects support scrollbars
     21        yet, and scrollbar hit testing was already there anyway.  Now the two code paths are more symmetrical.
     22       
     23        Masks are now treated like normal flow layers (just like reflections).
     24       
     25        A couple of test cases have been added to fast/overflow to test the stacking order.
     26
     27        * fast/overflow/overflow-float-stacking.html: Added.
     28        * fast/overflow/overflow-stacking.html: Added.
     29        * platform/mac/fast/overflow/overflow-float-stacking-expected.checksum: Added.
     30        * platform/mac/fast/overflow/overflow-float-stacking-expected.png: Added.
     31        * platform/mac/fast/overflow/overflow-float-stacking-expected.txt: Added.
     32        * platform/mac/fast/overflow/overflow-stacking-expected.checksum: Added.
     33        * platform/mac/fast/overflow/overflow-stacking-expected.png: Added.
     34        * platform/mac/fast/overflow/overflow-stacking-expected.txt: Added.
     35
    1362009-02-24  Simon Fraser  <simon.fraser@apple.com>
    237
  • trunk/WebCore/ChangeLog

    r41202 r41203  
     12009-02-23  David Hyatt  <hyatt@apple.com>
     2
     3        Reviewed by Eric Seidel
     4
     5        https://bugs.webkit.org/show_bug.cgi?id=23740, painting order wrong for normal flow elements with overflow: hidden
     6       
     7        This patch reworks the painting of overflow.  There is now the concept of a "self-painting layer."  All
     8        layers are considered to be self-painting except for overflow layers that are normal flow (and that don't have
     9        reflections or masks).
     10       
     11        If an overflow layer is not self-painting, then it ends up painted by its parent just like any other normal flow object.
     12        The only difference is that the clip has to be pushed and popped when painting the object's children.
     13       
     14        The lightweight clipping scheme used for controls has been extended to cover overflow now in this simplified case.  With
     15        the code consolidated into reusable push/pop functions, all of the renderers that use overflow have been patched to
     16        use the new functions.
     17       
     18        Hit testing has also been patched to check the overflow clip rect first before recurring into children.
     19       
     20        Scrollbar paint has been moved into RenderBlock for now, since none of the table objects support scrollbars
     21        yet, and scrollbar hit testing was already there anyway.  Now the two code paths are more symmetrical.
     22       
     23        Masks are now treated like normal flow layers (just like reflections).
     24
     25        A couple of test cases have been added to fast/overflow to test the stacking order.
     26
     27        * rendering/InlineFlowBox.cpp:
     28        (WebCore::InlineFlowBox::nodeAtPoint):
     29        (WebCore::InlineFlowBox::paint):
     30        * rendering/RenderBlock.cpp:
     31        (WebCore::RenderBlock::repaintOverhangingFloats):
     32        (WebCore::RenderBlock::paint):
     33        (WebCore::RenderBlock::paintChildren):
     34        (WebCore::RenderBlock::paintObject):
     35        (WebCore::RenderBlock::paintFloats):
     36        (WebCore::RenderBlock::insertFloatingObject):
     37        (WebCore::RenderBlock::floatRect):
     38        (WebCore::RenderBlock::lowestPosition):
     39        (WebCore::RenderBlock::rightmostPosition):
     40        (WebCore::RenderBlock::leftmostPosition):
     41        (WebCore::RenderBlock::addOverhangingFloats):
     42        (WebCore::RenderBlock::nodeAtPoint):
     43        (WebCore::RenderBlock::hitTestContents):
     44        * rendering/RenderBox.cpp:
     45        (WebCore::RenderBox::nodeAtPoint):
     46        (WebCore::RenderBox::pushContentsClip):
     47        (WebCore::RenderBox::popContentsClip):
     48        * rendering/RenderBox.h:
     49        (WebCore::RenderBox::paintObject):
     50        * rendering/RenderBoxModelObject.cpp:
     51        (WebCore::RenderBoxModelObject::hasSelfPaintingLayer):
     52        * rendering/RenderBoxModelObject.h:
     53        * rendering/RenderLayer.cpp:
     54        (WebCore::RenderLayer::paintLayer):
     55        (WebCore::RenderLayer::hitTestLayer):
     56        (WebCore::RenderLayer::shouldBeNormalFlowOnly):
     57        (WebCore::RenderLayer::isSelfPaintingLayer):
     58        * rendering/RenderLayer.h:
     59        * rendering/RenderTable.cpp:
     60        (WebCore::RenderTable::paint):
     61        (WebCore::RenderTable::paintObject):
     62        (WebCore::RenderTable::nodeAtPoint):
     63        * rendering/RenderTable.h:
     64        * rendering/RenderTableCell.cpp:
     65        (WebCore::RenderTableCell::paint):
     66        * rendering/RenderTableRow.cpp:
     67        (WebCore::RenderTableRow::nodeAtPoint):
     68        (WebCore::RenderTableRow::paint):
     69        * rendering/RenderTableRow.h:
     70        * rendering/RenderTableSection.cpp:
     71        (WebCore::RenderTableSection::paint):
     72        (WebCore::RenderTableSection::paintObject):
     73        (WebCore::RenderTableSection::nodeAtPoint):
     74        * rendering/RenderTableSection.h:
     75        * rendering/RenderTreeAsText.cpp:
     76        (WebCore::write):
     77        (WebCore::writeLayers):
     78
    1792009-02-24  David Levin  <levin@chromium.org>
    280
  • trunk/WebCore/rendering/InlineFlowBox.cpp

    r41152 r41203  
    554554    // Check children first.
    555555    for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
    556         if (!curr->renderer()->hasLayer() && curr->nodeAtPoint(request, result, x, y, tx, ty)) {
     556        if ((curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) && curr->nodeAtPoint(request, result, x, y, tx, ty)) {
    557557            renderer()->updateHitTestResult(result, IntPoint(x - tx, y - ty));
    558558            return true;
     
    594594            if (renderer()->style()->visibility() == VISIBLE && renderer()->hasOutline() && !isRootInlineBox()) {
    595595                RenderInline* inlineFlow = toRenderInline(renderer());
    596                 if ((inlineFlow->continuation() || inlineFlow->isInlineContinuation()) && !renderer()->hasLayer()) {
     596                if ((inlineFlow->continuation() || inlineFlow->isInlineContinuation()) && !boxModelObject()->hasSelfPaintingLayer()) {
    597597                    // Add ourselves to the containing block of the entire continuation so that it can
    598598                    // paint us atomically.
     
    625625    if (paintPhase != PaintPhaseSelfOutline) {
    626626        for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
    627             if (!curr->renderer()->hasLayer())
     627            if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
    628628                curr->paint(childInfo, tx, ty);
    629629        }
  • trunk/WebCore/rendering/RenderBlock.cpp

    r41191 r41203  
    15481548            // is our responsibility to paint (m_shouldPaint is set). When paintAllDescendants is true, the latter
    15491549            // condition is replaced with being a descendant of us.
    1550             if (r->m_bottom > height() && (paintAllDescendants && r->m_renderer->isDescendantOf(this) || r->m_shouldPaint) && !r->m_renderer->hasLayer()) {               
     1550            if (r->m_bottom > height() && (paintAllDescendants && r->m_renderer->isDescendantOf(this) || r->m_shouldPaint) && !r->m_renderer->hasSelfPaintingLayer()) {               
    15511551                r->m_renderer->repaint();
    15521552                r->m_renderer->repaintOverhangingFloats();
     
    15751575    }
    15761576
    1577     bool useControlClip = phase != PaintPhaseBlockBackground && phase != PaintPhaseSelfOutline && phase != PaintPhaseMask && hasControlClip();
    1578 
    1579     // Push a clip.
    1580     if (useControlClip) {
    1581         if (phase == PaintPhaseOutline)
    1582             paintInfo.phase = PaintPhaseChildOutlines;
    1583         else if (phase == PaintPhaseChildBlockBackground) {
    1584             paintInfo.phase = PaintPhaseBlockBackground;
    1585             paintObject(paintInfo, tx, ty);
    1586             paintInfo.phase = PaintPhaseChildBlockBackgrounds;
    1587         }
    1588         IntRect clipRect(controlClipRect(tx, ty));
    1589         if (clipRect.isEmpty())
    1590             return;
    1591         paintInfo.context->save();
    1592         paintInfo.context->clip(clipRect);
    1593     }
    1594 
     1577    bool pushedClip = pushContentsClip(paintInfo, tx, ty);
    15951578    paintObject(paintInfo, tx, ty);
    1596    
    1597     // Pop the clip.
    1598     if (useControlClip) {
    1599         paintInfo.context->restore();
    1600         if (phase == PaintPhaseOutline) {
    1601             paintInfo.phase = PaintPhaseSelfOutline;
    1602             paintObject(paintInfo, tx, ty);
    1603             paintInfo.phase = phase;
    1604         } else if (phase == PaintPhaseChildBlockBackground)
    1605             paintInfo.phase = phase;
    1606     }
     1579    if (pushedClip)
     1580        popContentsClip(paintInfo, phase, tx, ty);
     1581
     1582    // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
     1583    // z-index.  We paint after we painted the background/border, so that the scrollbars will
     1584    // sit above the background/border.
     1585    if (hasOverflowClip() && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground))
     1586        layer()->paintOverflowControls(paintInfo.context, tx, ty, paintInfo.rect);
    16071587}
    16081588
     
    17281708        }
    17291709
    1730         if (!child->hasLayer() && !child->isFloating())
     1710        if (!child->hasSelfPaintingLayer() && !child->isFloating())
    17311711            child->paint(info, tx, ty);
    17321712
     
    18161796        if (inlineContinuation() && inlineContinuation()->hasOutline() && inlineContinuation()->style()->visibility() == VISIBLE) {
    18171797            RenderInline* inlineRenderer = toRenderInline(inlineContinuation()->node()->renderer());
    1818             if (!inlineRenderer->hasLayer())
     1798            if (!inlineRenderer->hasSelfPaintingLayer())
    18191799                containingBlock()->addContinuationWithOutline(inlineRenderer);
    18201800            else if (!inlineRenderer->firstLineBox())
     
    18431823    for (; (r = it.current()); ++it) {
    18441824        // Only paint the object if our m_shouldPaint flag is set.
    1845         if (r->m_shouldPaint && !r->m_renderer->hasLayer()) {
     1825        if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
    18461826            PaintInfo currentPaintInfo(paintInfo);
    18471827            currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
     
    23772357    newObj->m_bottom = -1;
    23782358    newObj->m_width = o->width() + o->marginLeft() + o->marginRight();
    2379     newObj->m_shouldPaint = !o->hasLayer(); // If a layer exists, the float will paint itself.  Otherwise someone else will.
     2359    newObj->m_shouldPaint = !o->hasSelfPaintingLayer(); // If a layer exists, the float will paint itself.  Otherwise someone else will.
    23802360    newObj->m_isDescendant = true;
    23812361    newObj->m_renderer = o;
     
    26732653    DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
    26742654    for (; (r = it.current()); ++it) {
    2675         if (r->m_shouldPaint && !r->m_renderer->hasLayer()) {
     2655        if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
    26762656            IntRect childRect = r->m_renderer->overflowRect(false);
    26772657            childRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
     
    27422722        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
    27432723        for ( ; (r = it.current()); ++it ) {
    2744             if (r->m_shouldPaint || r->m_renderer->hasLayer()) {
     2724            if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
    27452725                int lp = r->m_top + r->m_renderer->marginTop() + r->m_renderer->lowestPosition(false);
    27462726                bottom = max(bottom, lp + relativeOffset);
     
    28182798        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
    28192799        for ( ; (r = it.current()); ++it ) {
    2820             if (r->m_shouldPaint || r->m_renderer->hasLayer()) {
     2800            if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
    28212801                int rp = r->m_left + r->m_renderer->marginLeft() + r->m_renderer->rightmostPosition(false);
    28222802                right = max(right, rp + relativeOffset);
     
    28992879        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
    29002880        for ( ; (r = it.current()); ++it ) {
    2901             if (r->m_shouldPaint || r->m_renderer->hasLayer()) {
     2881            if (r->m_shouldPaint || r->m_renderer->hasSelfPaintingLayer()) {
    29022882                int lp = r->m_left + r->m_renderer->marginLeft() + r->m_renderer->leftmostPosition(false);
    29032883                left = min(left, lp + relativeOffset);
     
    30953075                m_floatingObjects->append(floatingObj);
    30963076            }
    3097         } else if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasLayer() && r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingLayer() == child->enclosingLayer())
     3077        } else if (makeChildPaintOtherFloats && !r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer() &&
     3078                   r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingLayer() == child->enclosingLayer())
    30983079            // The float is not overhanging from this block, so if it is a descendant of the child, the child should
    30993080            // paint it (the other case is that it is intruding into the child), unless it has its own layer or enclosing
     
    31033084            r->m_shouldPaint = true;
    31043085
    3105         if (r->m_shouldPaint && !r->m_renderer->hasLayer()) {
     3086        if (r->m_shouldPaint && !r->m_renderer->hasSelfPaintingLayer()) {
    31063087            IntRect floatOverflowRect = r->m_renderer->overflowRect(false);
    31073088            floatOverflowRect.move(r->m_left + r->m_renderer->marginLeft(), r->m_top + r->m_renderer->marginTop());
     
    32653246    }
    32663247
    3267     if (isPointInOverflowControl(result, _x, _y, tx, ty)) {
    3268         if (hitTestAction == HitTestBlockBackground) {
    3269             updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
    3270             return true;
    3271         }
    3272         return false;
    3273     }
    3274 
    3275      // If we have lightweight control clipping, then we can't have any spillout.
    3276     if (!hasControlClip() || controlClipRect(tx, ty).contains(_x, _y)) {
     3248    if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, _x, _y, tx, ty)) {
     3249        updateHitTestResult(result, IntPoint(_x - tx, _y - ty));
     3250        return true;
     3251    }
     3252
     3253    // If we have clipping, then we can't have any spillout.
     3254    bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
     3255    bool useClip = (hasControlClip() || useOverflowClip);
     3256    bool checkChildren = !useClip || (hasControlClip() ? controlClipRect(tx, ty).contains(_x, _y) : overflowClipRect(tx, ty).contains(_x, _y));
     3257    if (checkChildren) {
    32773258        // Hit test descendants first.
    32783259        int scrolledX = tx;
     
    32993280            DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
    33003281            for (it.toLast(); (o = it.current()); --it) {
    3301                 if (o->m_shouldPaint && !o->m_renderer->hasLayer()) {
     3282                if (o->m_shouldPaint && !o->m_renderer->hasSelfPaintingLayer()) {
    33023283                    int xoffset = scrolledX + o->m_left + o->m_renderer->marginLeft() - o->m_renderer->x();
    33033284                    int yoffset =  scrolledY + o->m_top + o->m_renderer->marginTop() - o->m_renderer->y();
     
    33703351        if (hitTestAction == HitTestChildBlockBackgrounds)
    33713352            childHitTest = HitTestChildBlockBackground;
    3372         for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
    3373             // FIXME: We have to skip over inline flows, since they can show up inside RenderTables at the moment (a demoted inline <form> for example).  If we ever implement a
    3374             // table-specific hit-test method (which we should do for performance reasons anyway), then we can remove this check.
    3375             if (!child->hasLayer() && !child->isFloating() && !child->isRenderInline() && child->nodeAtPoint(request, result, x, y, tx, ty, childHitTest)) {
     3353        for (RenderBox* child = lastChildBox(); child; child = child->previousSiblingBox()) {
     3354            if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, x, y, tx, ty, childHitTest)) {
    33763355                updateHitTestResult(result, IntPoint(x - tx, y - ty));
    33773356                return true;
  • trunk/WebCore/rendering/RenderBox.cpp

    r41018 r41203  
    556556    // Check kids first.
    557557    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
    558         // FIXME: We have to skip over inline flows, since they can show up inside table rows
    559         // at the moment (a demoted inline <form> for example). If we ever implement a
    560         // table-specific hit-test method (which we should do for performance reasons anyway),
    561         // then we can remove this check.
    562         if (!child->hasLayer() && !child->isRenderInline() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
     558        ASSERT(!child->hasLayer());
     559        if (!child->hasLayer() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
    563560            updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
    564561            return true;
     
    852849
    853850#endif
     851
     852bool RenderBox::pushContentsClip(PaintInfo& paintInfo, int tx, int ty)
     853{
     854    if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseMask)
     855        return false;
     856       
     857    bool isControlClip = hasControlClip();
     858    bool isOverflowClip = hasOverflowClip() && !layer()->isSelfPaintingLayer();
     859   
     860    if (!isControlClip && !isOverflowClip)
     861        return false;
     862   
     863    if (paintInfo.phase == PaintPhaseOutline)
     864        paintInfo.phase = PaintPhaseChildOutlines;
     865    else if (paintInfo.phase == PaintPhaseChildBlockBackground) {
     866        paintInfo.phase = PaintPhaseBlockBackground;
     867        paintObject(paintInfo, tx, ty);
     868        paintInfo.phase = PaintPhaseChildBlockBackgrounds;
     869    }
     870    IntRect clipRect(isControlClip ? controlClipRect(tx, ty) : overflowClipRect(tx, ty));
     871    paintInfo.context->save();
     872    paintInfo.context->clip(clipRect);
     873    return true;
     874}
     875
     876void RenderBox::popContentsClip(PaintInfo& paintInfo, PaintPhase originalPhase, int tx, int ty)
     877{
     878    ASSERT(hasControlClip() || (hasOverflowClip() && !layer()->isSelfPaintingLayer()));
     879
     880    paintInfo.context->restore();
     881    if (originalPhase == PaintPhaseOutline) {
     882        paintInfo.phase = PaintPhaseSelfOutline;
     883        paintObject(paintInfo, tx, ty);
     884        paintInfo.phase = originalPhase;
     885    } else if (originalPhase == PaintPhaseChildBlockBackground)
     886        paintInfo.phase = originalPhase;
     887}
    854888
    855889IntRect RenderBox::overflowClipRect(int tx, int ty)
  • trunk/WebCore/rendering/RenderBox.h

    r41188 r41203  
    251251    virtual bool hasControlClip() const { return false; }
    252252    virtual IntRect controlClipRect(int /*tx*/, int /*ty*/) const { return IntRect(); }
    253 
     253    bool pushContentsClip(PaintInfo&, int tx, int ty);
     254    void popContentsClip(PaintInfo&, PaintPhase originalPhase, int tx, int ty);
     255
     256    virtual void paintObject(PaintInfo&, int /*tx*/, int /*ty*/) { ASSERT_NOT_REACHED(); }
    254257    virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
    255258    virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
  • trunk/WebCore/rendering/RenderBoxModelObject.cpp

    r40990 r41203  
    5959        m_layer->clearClipRects();
    6060    RenderObject::destroy();
     61}
     62
     63bool RenderBoxModelObject::hasSelfPaintingLayer() const
     64{
     65    return m_layer && m_layer->isSelfPaintingLayer();
    6166}
    6267
  • trunk/WebCore/rendering/RenderBoxModelObject.h

    r40990 r41203  
    5858    virtual void updateBoxModelInfoFromStyle();
    5959
     60    bool hasSelfPaintingLayer() const;
    6061    RenderLayer* layer() const { return m_layer; }
    6162    virtual bool requiresLayer() const { return isRoot() || isPositioned() || isRelPositioned() || isTransparent() || hasOverflowClip() || hasTransform() || hasMask() || hasReflection(); }
  • trunk/WebCore/rendering/RenderLayer.cpp

    r41154 r41203  
    19391939        renderer()->paint(paintInfo, tx, ty);
    19401940
    1941         // Our scrollbar widgets paint exactly when we tell them to, so that they work properly with
    1942         // z-index.  We paint after we painted the background/border, so that the scrollbars will
    1943         // sit above the background/border.
    1944         paintOverflowControls(p, x, y, damageRect);
    1945        
    19461941        // Restore the clip.
    19471942        restoreClip(p, paintDirtyRect, damageRect);
     
    19881983    // Paint any child layers that have overflow.
    19891984    if (m_normalFlowList)
    1990         for (Vector<RenderLayer*>::iterator it = m_normalFlowList->begin(); it != m_normalFlowList->end(); ++it)
    1991             it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
    1992    
     1985        for (Vector<RenderLayer*>::iterator it = m_normalFlowList->begin(); it != m_normalFlowList->end(); ++it) {
     1986            if (it[0]->isSelfPaintingLayer())
     1987                it[0]->paintLayer(rootLayer, p, paintDirtyRect, haveTransparency, paintRestriction, paintingRoot, false, temporaryClipRects);
     1988        }
     1989
    19931990    // Now walk the sorted list of children with positive z-indices.
    19941991    if (m_posZOrderList)
     
    21212118    if (m_normalFlowList) {
    21222119        for (int i = m_normalFlowList->size() - 1; i >= 0; --i) {
    2123             insideLayer = m_normalFlowList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
     2120            if (m_normalFlowList->at(i)->isSelfPaintingLayer())
     2121                insideLayer = m_normalFlowList->at(i)->hitTestLayer(rootLayer, request, result, hitTestRect, hitTestPoint);
    21242122            if (insideLayer)
    21252123                return insideLayer;
     
    27432741bool RenderLayer::shouldBeNormalFlowOnly() const
    27442742{
    2745     return (renderer()->hasOverflowClip() || renderer()->hasReflection()) &&
     2743    return (renderer()->hasOverflowClip() || renderer()->hasReflection() || renderer()->hasMask()) &&
    27462744           !renderer()->isPositioned() &&
    27472745           !renderer()->isRelPositioned() &&
    27482746           !renderer()->hasTransform() &&
    27492747           !isTransparent();
     2748}
     2749
     2750bool RenderLayer::isSelfPaintingLayer() const
     2751{
     2752    return !isNormalFlowOnly() || renderer()->hasReflection() || renderer()->hasMask() || renderer()->isTableRow();
    27502753}
    27512754
  • trunk/WebCore/rendering/RenderLayer.h

    r41154 r41203  
    219219
    220220    bool isNormalFlowOnly() const { return m_isNormalFlowOnly; }
     221    bool isSelfPaintingLayer() const;
    221222
    222223    bool requiresSlowRepaints() const;
     
    458459    void computeScrollDimensions(bool* needHBar = 0, bool* needVBar = 0);
    459460
    460     bool shouldBeNormalFlowOnly() const;
     461    bool shouldBeNormalFlowOnly() const; 
    461462
    462463    virtual void valueChanged(Scrollbar*);
  • trunk/WebCore/rendering/RenderTable.cpp

    r40947 r41203  
    451451        return;
    452452
     453    bool pushedClip = pushContentsClip(paintInfo, tx, ty);   
     454    paintObject(paintInfo, tx, ty);
     455    if (pushedClip)
     456        popContentsClip(paintInfo, paintPhase, tx, ty);
     457}
     458
     459void RenderTable::paintObject(PaintInfo& paintInfo, int tx, int ty)
     460{
     461    PaintPhase paintPhase = paintInfo.phase;
    453462    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style()->visibility() == VISIBLE)
    454463        paintBoxDecorations(paintInfo, tx, ty);
     
    462471    if (paintPhase == PaintPhaseBlockBackground)
    463472        return;
    464 
     473   
    465474    // We don't paint our own background, but we do let the kids paint their backgrounds.
    466475    if (paintPhase == PaintPhaseChildBlockBackgrounds)
    467476        paintPhase = PaintPhaseChildBlockBackground;
     477
    468478    PaintInfo info(paintInfo);
    469479    info.phase = paintPhase;
     
    471481
    472482    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
    473         if (!child->hasLayer() && (child->isTableSection() || child == m_caption))
     483        if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption))
    474484            child->paint(info, tx, ty);
    475485    }
    476 
     486   
    477487    if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
    478488        // Collect all the unique border styles that we want to paint in a sorted list.  Once we
     
    11361146}
    11371147
    1138 }
     1148bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int xPos, int yPos, int tx, int ty, HitTestAction action)
     1149{
     1150    tx += x();
     1151    ty += y();
     1152
     1153    // Check kids first.
     1154    if (!hasOverflowClip() || overflowClipRect(tx, ty).contains(xPos, yPos)) {
     1155        for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
     1156            if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child == m_caption) &&
     1157                child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
     1158                updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
     1159                return true;
     1160            }
     1161        }
     1162    }
     1163
     1164    // Check our bounds next.
     1165    if (visibleToHitTesting() && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && IntRect(tx, ty, width(), height()).contains(xPos, yPos)) {
     1166        updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
     1167        return true;
     1168    }
     1169
     1170    return false;
     1171}
     1172
     1173}
  • trunk/WebCore/rendering/RenderTable.h

    r40947 r41203  
    7676
    7777    virtual void paint(PaintInfo&, int tx, int ty);
     78    virtual void paintObject(PaintInfo&, int tx, int ty);
    7879    virtual void paintBoxDecorations(PaintInfo&, int tx, int ty);
    7980    virtual void paintMask(PaintInfo& paintInfo, int tx, int ty);
    8081    virtual void layout();
    8182    virtual void calcPrefWidths();
    82 
     83    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, int xPos, int yPos, int tx, int ty, HitTestAction);
     84   
    8385    virtual int firstLineBoxBaseline() const;
    8486
  • trunk/WebCore/rendering/RenderTableCell.cpp

    r40916 r41203  
    650650void RenderTableCell::paint(PaintInfo& paintInfo, int tx, int ty)
    651651{
    652     tx += x();
    653     ty += y();
    654 
    655     // check if we need to do anything at all...
    656     int os = 2 * maximalOutlineSize(paintInfo.phase);
    657 
    658652    if (paintInfo.phase == PaintPhaseCollapsedTableBorders && style()->visibility() == VISIBLE) {
    659         if (ty - table()->outerBorderTop() >= paintInfo.rect.bottom() + os ||
    660                 ty + height() + table()->outerBorderBottom() <= paintInfo.rect.y() - os)
    661             return;
    662         paintCollapsedBorder(paintInfo.context, tx, ty, width(), height());
    663     } else {
    664         if (ty + overflowTop(false) >= paintInfo.rect.bottom() + os || ty + overflowHeight(false) <= paintInfo.rect.y() - os)
    665             return;
    666         RenderBlock::paintObject(paintInfo, tx, ty);
    667     }
     653        tx += x();
     654        ty += y();
     655        int os = 2 * maximalOutlineSize(paintInfo.phase);
     656        if (ty - table()->outerBorderTop() < paintInfo.rect.bottom() + os &&
     657            ty + height() + table()->outerBorderBottom() > paintInfo.rect.y() - os)
     658            paintCollapsedBorder(paintInfo.context, tx, ty, width(), height());
     659        return;
     660    }
     661   
     662    RenderBlock::paint(paintInfo, tx, ty);
    668663}
    669664
  • trunk/WebCore/rendering/RenderTableRow.cpp

    r40871 r41203  
    184184        // table-specific hit-test method (which we should do for performance reasons anyway),
    185185        // then we can remove this check.
    186         if (!child->hasLayer() && !child->isRenderInline() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
     186        if (child->isTableCell() && !toRenderBox(child)->hasSelfPaintingLayer() && child->nodeAtPoint(request, result, x, y, tx, ty, action)) {
    187187            updateHitTestResult(result, IntPoint(x - tx, y - ty));
    188188            return true;
     
    195195void RenderTableRow::paint(PaintInfo& paintInfo, int tx, int ty)
    196196{
    197     ASSERT(hasLayer());
     197    ASSERT(hasSelfPaintingLayer());
    198198    if (!layer())
    199199        return;
    200 
    201200    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
    202201        if (child->isTableCell()) {
     
    206205                cell->paintBackgroundsBehindCell(paintInfo, tx, ty, this);
    207206            }
    208             if (!child->hasLayer())
     207            if (!toRenderBox(child)->hasSelfPaintingLayer())
    209208                child->paint(paintInfo, tx, ty);
    210209        }
  • trunk/WebCore/rendering/RenderTableRow.h

    r40875 r41203  
    6161
    6262    virtual void paint(PaintInfo&, int tx, int ty);
     63
    6364    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
    6465
  • trunk/WebCore/rendering/RenderTableSection.cpp

    r40980 r41203  
    940940    ty += y();
    941941
     942    PaintPhase phase = paintInfo.phase;
     943    bool pushedClip = pushContentsClip(paintInfo, tx, ty);
     944    paintObject(paintInfo, tx, ty);
     945    if (pushedClip)
     946        popContentsClip(paintInfo, phase, tx, ty);
     947}
     948
     949void RenderTableSection::paintObject(PaintInfo& paintInfo, int tx, int ty)
     950{
    942951    // Check which rows and cols are visible and only paint these.
    943952    // FIXME: Could use a binary search here.
     953    unsigned totalRows = m_gridRows;
     954    unsigned totalCols = table()->columns().size();
     955
    944956    PaintPhase paintPhase = paintInfo.phase;
    945957    int x = paintInfo.rect.x();
     
    10281040                    // Paint the row next, but only if it doesn't have a layer.  If a row has a layer, it will be responsible for
    10291041                    // painting the row background for the cell.
    1030                     if (!row->hasLayer())
     1042                    if (!row->hasSelfPaintingLayer())
    10311043                        cell->paintBackgroundsBehindCell(paintInfo, tx, ty, row);
    10321044                }
    10331045
    1034                 if ((!cell->hasLayer() && !row->hasLayer()) || paintInfo.phase == PaintPhaseCollapsedTableBorders)
     1046                if ((!cell->hasSelfPaintingLayer() && !row->hasSelfPaintingLayer()) || paintInfo.phase == PaintPhaseCollapsedTableBorders)
    10351047                    cell->paint(paintInfo, tx, ty);
    10361048            }
     
    11251137    ty += y();
    11261138
     1139    if (hasOverflowClip() && !overflowClipRect(tx, ty).contains(xPos, yPos))
     1140        return false;
     1141
    11271142    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
    11281143        // FIXME: We have to skip over inline flows, since they can show up inside table rows
     
    11301145        // table-specific hit-test method (which we should do for performance reasons anyway),
    11311146        // then we can remove this check.
    1132         if (!child->hasLayer() && !child->isRenderInline() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
     1147        if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && child->nodeAtPoint(request, result, xPos, yPos, tx, ty, action)) {
    11331148            updateHitTestResult(result, IntPoint(xPos - tx, yPos - ty));
    11341149            return true;
  • trunk/WebCore/rendering/RenderTableSection.h

    r40875 r41203  
    108108
    109109    virtual void paint(PaintInfo&, int tx, int ty);
     110    virtual void paintObject(PaintInfo&, int tx, int ty);
     111
    110112    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
    111113
  • trunk/WebCore/rendering/RenderTreeAsText.cpp

    r41154 r41203  
    473473        write(ts, *l, layerBounds, damageRect, clipRectToApply, outlineRect, negList && negList->size() > 0, indent);
    474474
    475     Vector<RenderLayer*>* overflowList = l->normalFlowList();
    476     if (overflowList) {
    477         for (unsigned i = 0; i != overflowList->size(); ++i)
    478             writeLayers(ts, rootLayer, overflowList->at(i), paintDirtyRect, indent);
     475    Vector<RenderLayer*>* normalFlowList = l->normalFlowList();
     476    if (normalFlowList) {
     477        for (unsigned i = 0; i != normalFlowList->size(); ++i)
     478            writeLayers(ts, rootLayer, normalFlowList->at(i), paintDirtyRect, indent);
    479479    }
    480480
Note: See TracChangeset for help on using the changeset viewer.