Reviewed by kocienda
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 19 Oct 2004 23:04:29 +0000 (23:04 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 19 Oct 2004 23:04:29 +0000 (23:04 +0000)
More cleanup of block layout.  Eliminates the separate step for tables that dont fit on a line with a float
and consolidates it with clearing.

Also patch dom_textimpl.cpp to reduce further the # of RenderTexts created.

        * khtml/rendering/render_block.cpp:
        (khtml::getInlineRun):
        (khtml::RenderBlock::layoutBlock):
        (khtml::RenderBlock::adjustFloatingBlock):
        (khtml::RenderBlock::collapseMargins):
        (khtml::RenderBlock::clearFloatsIfNeeded):
        (khtml::RenderBlock::estimateVerticalPosition):
        (khtml::RenderBlock::layoutBlockChildren):
        (khtml::RenderBlock::markAllDescendantsWithFloatsForLayout):
        (khtml::RenderBlock::getClearDelta):
        (khtml::RenderBlock::calcBlockMinMaxWidth):
        * khtml/rendering/render_block.h:
        * khtml/rendering/render_frames.cpp:
        (RenderFrameSet::layout):
        * khtml/xml/dom_textimpl.cpp:
        (TextImpl::rendererIsNeeded):

        Fix for 3841060, regression with * in frames.  Reviewed by kocienda.

* layout-tests/fast/frames/002-expected.txt: Added.
        * layout-tests/fast/frames/002.html: Added.

 2004-10-19  Darin Adler  <darin@apple.com>

        Reviewed by Maciej.

        - follow-on to my fix yesterday, which broke a layout test because I rolled out a fix that Maciej had done

        * khtml/html/htmltokenizer.cpp: (khtml::HTMLTokenizer::write): Need to check the actual queue of external
        scripts being loaded here. If the current code being run is the external script itself, then we don't want
        to defer parsing. But loadingExtScript has to stay true until after the script runs. The old code would
        assume that any time we're running a script there's no need to look at loadingExtScript, but that was also
        wrong since there can be a script loading in that case too. Layout tests check for both problems.

        * layout-tests/fast/tokenizer/external-script-document-write-expected.txt: Added.
        * layout-tests/fast/tokenizer/external-script-document-write.html: Added.
        * layout-tests/fast/tokenizer/resources/external-script-document-write.js: Added.

        * layout-tests/fast/tokenizer/004.html: Fixed line endings (were CR, should be LF).

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@7861 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/fast/frames/002-expected.txt [new file with mode: 0644]
LayoutTests/fast/frames/002.html [new file with mode: 0644]
WebCore/ChangeLog-2005-08-23
WebCore/khtml/rendering/render_block.cpp
WebCore/khtml/rendering/render_block.h
WebCore/khtml/rendering/render_frames.cpp
WebCore/khtml/xml/dom_textimpl.cpp

diff --git a/LayoutTests/fast/frames/002-expected.txt b/LayoutTests/fast/frames/002-expected.txt
new file mode 100644 (file)
index 0000000..737eeab
--- /dev/null
@@ -0,0 +1,15 @@
+layer at (0,0) size 800x600
+  RenderCanvas at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderFrameSet {FRAMESET} at (0,0) size 800x600
+      RenderFrame {FRAME} at (0,0) size 398x600
+        layer at (0,0) size 381x596
+          RenderCanvas at (0,0) size 381x596
+      RenderFrameSet {FRAMESET} at (402,0) size 398x600
+        RenderFrame {FRAME} at (0,0) size 398x298
+          layer at (0,0) size 381x294
+            RenderCanvas at (0,0) size 381x294
+        RenderFrame {FRAME} at (0,302) size 398x298
+          layer at (0,0) size 381x294
+            RenderCanvas at (0,0) size 381x294
diff --git a/LayoutTests/fast/frames/002.html b/LayoutTests/fast/frames/002.html
new file mode 100644 (file)
index 0000000..56d43b4
--- /dev/null
@@ -0,0 +1,15 @@
+<html>
+<head>
+<title>frame test</title>
+</head>
+<frameset cols="50%,*">
+  <frame src="about:blank" name="frame1">
+  <frameset rows="50%,*">
+    <frame src="about:blank" name="frame2">
+    <frame src="about:blank" name="frame3">
+  </frameset>
+  <noframes>
+  Please see by the browser corresponding to the frame.
+  </noframes>
+</frameset>
+</html>
index 3d6df53811997234fa6b980089480699cf0fb958..1401070db1086b9418d5641c5ae7b23087945748 100644 (file)
@@ -1,3 +1,34 @@
+2004-10-19  David Hyatt  <hyatt@apple.com>
+
+        Reviewed by kocienda
+
+       More cleanup of block layout.  Eliminates the separate step for tables that dont fit on a line with a float
+       and consolidates it with clearing.
+
+       Also patch dom_textimpl.cpp to reduce further the # of RenderTexts created.
+       
+        * khtml/rendering/render_block.cpp:
+        (khtml::getInlineRun):
+        (khtml::RenderBlock::layoutBlock):
+        (khtml::RenderBlock::adjustFloatingBlock):
+        (khtml::RenderBlock::collapseMargins):
+        (khtml::RenderBlock::clearFloatsIfNeeded):
+        (khtml::RenderBlock::estimateVerticalPosition):
+        (khtml::RenderBlock::layoutBlockChildren):
+        (khtml::RenderBlock::markAllDescendantsWithFloatsForLayout):
+        (khtml::RenderBlock::getClearDelta):
+        (khtml::RenderBlock::calcBlockMinMaxWidth):
+        * khtml/rendering/render_block.h:
+        * khtml/rendering/render_frames.cpp:
+        (RenderFrameSet::layout):
+        * khtml/xml/dom_textimpl.cpp:
+        (TextImpl::rendererIsNeeded):
+
+        Fix for 3841060, regression with * in frames.  Reviewed by kocienda.
+       
+       * layout-tests/fast/frames/002-expected.txt: Added.
+        * layout-tests/fast/frames/002.html: Added.
+
  2004-10-19  Darin Adler  <darin@apple.com>
 
         Reviewed by Maciej.
index 0f8614718e921ebcbf5f9a201a29607b019422dc..0b5740173a72bbd24ed251a32b97a92f9b3771d9 100644 (file)
@@ -237,22 +237,15 @@ static void getInlineRun(RenderObject* start, RenderObject* stop,
 
     if (!curr)
         return; // No more inline children to be found.
-
-    inlineRunStart = inlineRunEnd = curr;
-
-    bool sawInline = curr->isInline();
     
-    curr = curr->nextSibling();
     while (curr && (curr->isInline() || curr->isFloatingOrPositioned()) && (curr != stop)) {
-        inlineRunEnd = curr;
-        if (curr->isInline())
-            sawInline = true;
+        if (curr->isInline()) {
+            if (!inlineRunStart)
+                inlineRunStart = curr;
+            inlineRunEnd = curr;
+        }
         curr = curr->nextSibling();
     }
-    
-    // Need to really see an inline in order to do any work.
-    if (!sawInline)
-        inlineRunStart = inlineRunEnd = 0;
 }
 
 void RenderBlock::makeChildrenNonInline(RenderObject *insertionPoint)
@@ -458,9 +451,9 @@ void RenderBlock::layoutBlock(bool relayoutChildren)
    
     QRect repaintRect;
     if (childrenInline())
-        repaintRect = layoutInlineChildren( relayoutChildren );
+        repaintRect = layoutInlineChildren(relayoutChildren);
     else
-        layoutBlockChildren( relayoutChildren );
+        layoutBlockChildren(relayoutChildren);
 
     // Expand our intrinsic height to encompass floats.
     int toAdd = borderBottom() + paddingBottom();
@@ -565,7 +558,7 @@ void RenderBlock::adjustFloatingBlock(const MarginInfo& marginInfo)
     // Note also that the previous flow may collapse its margin into the top of
     // our block.  If this is the case, then we do not add the margin in to our
     // height when computing the position of the float.   This condition can be tested
-    // for by simply checking the boolean |addPreviousMargins| variable.  See
+    // for by simply calling canCollapseWithTop.  See
     // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
     // an example of this scenario.
     int marginOffset = marginInfo.canCollapseWithTop() ? 0 : marginInfo.margin();
@@ -805,7 +798,7 @@ void RenderBlock::collapseMargins(RenderObject* child, MarginInfo& marginInfo, i
             // So go ahead and mark the item as dirty.
             child->setChildNeedsLayout(true);
 
-        if (child->containsFloats() || containsFloats())
+        if (!child->avoidsFloats() && child->containsFloats())
             child->markAllDescendantsWithFloatsForLayout();
 
         // Our guess was wrong. Make the child lay itself out again.
@@ -852,22 +845,20 @@ void RenderBlock::clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInf
             // change (because it has more available line width).
             // So go ahead and mark the item as dirty.
             child->setChildNeedsLayout(true);
-        if (child->containsFloats())
+        if (!child->avoidsFloats() && child->containsFloats())
             child->markAllDescendantsWithFloatsForLayout();
         child->layoutIfNeeded();
     }
 }
 
-int RenderBlock::estimateVerticalPosition(RenderObject* child, const MarginInfo& marginInfo, RenderObject* prevBlock)
+int RenderBlock::estimateVerticalPosition(RenderObject* child, const MarginInfo& marginInfo)
 {
-    // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we trigger a pathological
+    // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
     // relayout if there are intruding floats.
     int yPosEstimate = m_height;
     if (!marginInfo.canCollapseWithTop()) {
-        if (prevBlock)
-            yPosEstimate += kMax(prevBlock->collapsedMarginBottom(), child->marginTop());
-        else
-            yPosEstimate += child->marginTop();
+        int childMarginTop = child->selfNeedsLayout() ? child->marginTop() : child->collapsedMarginTop();
+        yPosEstimate += kMax(marginInfo.margin(), childMarginTop);
     }
     return yPosEstimate;
 }
@@ -942,29 +933,6 @@ void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
     }
 }
 
-bool RenderBlock::adjustChildIfOverhangingFloatsExist(RenderObject* child, MarginInfo& marginInfo, int& yPosEstimate)
-{
-    bool shouldCollapse = true;
-    int fb = floatBottom();
-    if (fb > m_height) {
-        if (child->avoidsFloats()) {
-            if (style()->width().isFixed() && child->minWidth() > lineWidth(m_height)) {
-                m_height = yPosEstimate = fb;
-                marginInfo.setAtTopOfBlock(false);
-                shouldCollapse = false;
-            }
-        }
-        else // If a float is going to intrude into our space then mark the child as needing layout so that lines inside the child can
-             // properly adjust to flow around the float.
-            child->setChildNeedsLayout(true);
-    }
-
-    if (fb > yPosEstimate && !child->avoidsFloats())
-        child->setChildNeedsLayout(true);
-        
-    return shouldCollapse;
-}
-
 void RenderBlock::handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo)
 {
      // If our last flow was a self-collapsing block that cleared a float, then we don't
@@ -998,9 +966,6 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren)
 
     m_height = m_overflowHeight = top;
 
-    // Track our previous normal flow block.
-    RenderObject* prevBlock = 0;
-
     // The margin struct caches all our current margin collapsing state.  The compact struct caches state when we encounter compacts,
     MarginInfo marginInfo(this, top, bottom);
     CompactInfo compactInfo;
@@ -1042,12 +1007,17 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren)
 
         // Try to guess our correct y position.  In most cases this guess will
         // be correct.  Only if we're wrong (when we compute the real y position)
-        // will we have to relayout.
-        int yPosEstimate = estimateVerticalPosition(child, marginInfo, prevBlock);
+        // will we have to potentially relayout.
+        int yPosEstimate = estimateVerticalPosition(child, marginInfo);
         
-        // Sometimes an element will be shoved down away from a previous sibling, e.g., when
-        // clearing to pass beyond a float.  In this case, you don't need to collapse.
-        bool shouldCollapseChild = adjustChildIfOverhangingFloatsExist(child, marginInfo, yPosEstimate);
+        // If an element might be affected by the presence of floats, then always mark it for
+        // layout.
+        bool affectedByFloats = !child->avoidsFloats() || (child->style()->width().isPercent() && child->usesLineWidth());
+        if (affectedByFloats) {
+            int fb = floatBottom();
+            if (fb > m_height || fb > yPosEstimate)
+                child->setChildNeedsLayout(true);
+        }
 
         // Cache our old position so that we can dirty the proper repaint rects if the child moves.
         int oldChildX = child->xPos();
@@ -1059,10 +1029,7 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren)
 
         // Now determine the correct ypos based off examination of collapsing margin
         // values.
-        if (shouldCollapseChild)
-            collapseMargins(child, marginInfo, yPosEstimate);
-        else
-            marginInfo.setSelfCollapsingBlockClearedFloat(false);
+        collapseMargins(child, marginInfo, yPosEstimate);
 
         // Now check for clear.
         clearFloatsIfNeeded(child, marginInfo, oldTopPosMargin, oldTopNegMargin);
@@ -1085,9 +1052,6 @@ void RenderBlock::layoutBlockChildren(bool relayoutChildren)
         if (m_height + overflowDelta > m_overflowHeight)
             m_overflowHeight = m_height + overflowDelta;
 
-        // Track the previous block so that we can check its collapsed bottom margin in the next loop iteration.
-        prevBlock = child;
-
         if (child->hasOverhangingFloats() && !child->hasOverflowClip())
             // need to add the child's floats to our floating objects list, but not in the case where
             // overflow is auto/scroll
@@ -2277,7 +2241,7 @@ bool RenderBlock::containsFloat(RenderObject* o)
 
 void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderObject* floatToRemove)
 {
-    setNeedsLayout(true);
+    setChildNeedsLayout(true);
 
     if (floatToRemove)
         removeFloatingObject(floatToRemove);
@@ -2294,12 +2258,11 @@ void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderObject* floatToRem
 
 int RenderBlock::getClearDelta(RenderObject *child)
 {
-    //kdDebug( 6040 ) << "checkClear oldheight=" << m_height << endl;
+    bool clearSet = child->style()->clear() != CNONE;
     int bottom = 0;
-    switch(child->style()->clear())
-    {
+    switch (child->style()->clear()) {
         case CNONE:
-            return 0;
+            break;
         case CLEFT:
             bottom = leftBottom();
             break;
@@ -2311,7 +2274,11 @@ int RenderBlock::getClearDelta(RenderObject *child)
             break;
     }
 
-    return QMAX(0, bottom-(child->yPos()));
+    // We also clear floats if we are too big to sit on the same line as a float (and wish to avoid floats by default).
+    int result = clearSet ? kMax(0, bottom - child->yPos()) : 0;
+    if (!result && child->avoidsFloats() && child->style()->width().isFixed() && child->minWidth() > lineWidth(child->yPos()))
+        result = kMax(0, floatBottom() - child->yPos());
+    return result;
 }
 
 bool RenderBlock::isPointInScrollbar(int _x, int _y, int _tx, int _ty)
@@ -2905,8 +2872,7 @@ void RenderBlock::calcBlockMinMaxWidth()
     bool nowrap = style()->whiteSpace() == NOWRAP;
 
     RenderObject *child = firstChild();
-    RenderObject* prevFloat = 0;
-    int floatWidths = 0;
+    int floatLeftWidth = 0, floatRightWidth = 0;
     while (child) {
         // Positioned children don't affect the min/max width
         if (child->isPositioned()) {
@@ -2914,11 +2880,16 @@ void RenderBlock::calcBlockMinMaxWidth()
             continue;
         }
 
-        if (prevFloat && (!child->isFloating() || 
-                          (prevFloat->style()->floating() == FLEFT && (child->style()->clear() & CLEFT)) ||
-                          (prevFloat->style()->floating() == FRIGHT && (child->style()->clear() & CRIGHT)))) {
-            m_maxWidth = kMax(floatWidths, m_maxWidth);
-            floatWidths = 0;
+        if (child->isFloating() || child->avoidsFloats()) {
+            int floatTotalWidth = floatLeftWidth + floatRightWidth;
+            if (child->style()->clear() & CLEFT) {
+                m_maxWidth = kMax(floatTotalWidth, m_maxWidth);
+                floatLeftWidth = 0;
+            }
+            if (child->style()->clear() & CRIGHT) {
+                m_maxWidth = kMax(floatTotalWidth, m_maxWidth);
+                floatRightWidth = 0;
+            }
         }
 
         Length ml = child->style()->marginLeft();
@@ -2936,29 +2907,47 @@ void RenderBlock::calcBlockMinMaxWidth()
         // Percentage margins are computed as a percentage of the width we calculated in
         // the calcWidth call above.  In this case we use the actual cached margin values on
         // the RenderObject itself.
-        int margin = 0;
+        int margin = 0, marginLeft = 0, marginRight = 0;
         if (ml.type == Fixed)
-            margin += ml.value;
+            marginLeft += ml.value;
         else if (ml.type == Percent)
-            margin += child->marginLeft();
-
+            marginLeft += child->marginLeft();
+        marginLeft = kMax(0, marginLeft);
         if (mr.type == Fixed)
-            margin += mr.value;
+            marginRight += mr.value;
         else if (mr.type == Percent)
-            margin += child->marginRight();
-        
-        if (margin < 0) margin = 0;
+            marginRight += child->marginRight();
+        marginRight = kMax(0, marginRight);
+        margin = marginLeft + marginRight;
 
         int w = child->minWidth() + margin;
         if (m_minWidth < w) m_minWidth = w;
+        
         // IE ignores tables for calculation of nowrap. Makes some sense.
         if (nowrap && !child->isTable() && m_maxWidth < w)
             m_maxWidth = w;
 
         w = child->maxWidth() + margin;
 
-        if (child->isFloating())
-            floatWidths += w;
+        if (!child->isFloating()) {
+            if (child->avoidsFloats()) {
+                // Determine a left and right max value based off whether or not the floats can fit in the
+                // margins of the object.
+                int maxLeft = kMax(floatLeftWidth, marginLeft);
+                int maxRight = kMax(floatRightWidth, marginRight);
+                w = child->maxWidth() + maxLeft + maxRight;
+            }
+            else
+                m_maxWidth = kMax(floatLeftWidth + floatRightWidth, m_maxWidth);
+            floatLeftWidth = floatRightWidth = 0;
+        }
+        
+        if (child->isFloating()) {
+            if (style()->floating() == FLEFT)
+                floatLeftWidth += w;
+            else
+                floatRightWidth += w;
+        }
         else if (m_maxWidth < w)
             m_maxWidth = w;
 
@@ -2984,12 +2973,10 @@ void RenderBlock::calcBlockMinMaxWidth()
                 m_maxWidth = BLOCK_MAX_WIDTH;
         }
         
-        if (child->isFloating())
-            prevFloat = child;
         child = child->nextSibling();
     }
     
-    m_maxWidth = kMax(floatWidths, m_maxWidth);
+    m_maxWidth = kMax(floatLeftWidth + floatRightWidth, m_maxWidth);
 }
 
 short RenderBlock::lineHeight(bool b, bool isRootLineBox) const
index 67875f5daae6d841b0317bae283205ee5c79ff6d..e2b71be25989483fef5c765f1681a849811b141a 100644 (file)
@@ -104,9 +104,9 @@ public:
     virtual void setStyle(RenderStyle* _style);
 
     virtual void layout();
-    virtual void layoutBlock( bool relayoutChildren );
-    void layoutBlockChildren( bool relayoutChildren );
-    QRect layoutInlineChildren( bool relayoutChildren );
+    virtual void layoutBlock(bool relayoutChildren);
+    void layoutBlockChildren(bool relayoutChildren);
+    QRect layoutInlineChildren(bool relayoutChildren);
 
     void layoutPositionedObjects( bool relayoutChildren );
     void insertPositionedObject(RenderObject *o);
@@ -383,11 +383,10 @@ protected:
     void collapseMargins(RenderObject* child, MarginInfo& marginInfo, int yPosEstimate);
     void clearFloatsIfNeeded(RenderObject* child, MarginInfo& marginInfo, int oldTopPosMargin, int oldTopNegMargin);
     void insertCompactIfNeeded(RenderObject* child, CompactInfo& compactInfo);
-    int estimateVerticalPosition(RenderObject* child, const MarginInfo& info, RenderObject* prevBlock);
+    int estimateVerticalPosition(RenderObject* child, const MarginInfo& info);
     void determineHorizontalPosition(RenderObject* child);
     void handleBottomOfBlock(int top, int bottom, MarginInfo& marginInfo);
     void setCollapsedBottomMargin(const MarginInfo& marginInfo);
-    bool adjustChildIfOverhangingFloatsExist(RenderObject* child, MarginInfo& marginInfo, int& yPosEstimate);
     // End helper functions and structs used by layoutBlockChildren.
 
 protected:
index c23ca0b9836af98e5f9554d5b4ae6a6e489dd847..9563312da6929203815b53cb2eb32ce41b704685 100644 (file)
@@ -172,10 +172,12 @@ void RenderFrameSet::layout( )
             }
 
             int currPercent = totalPercent;
+            int percentLen = (countRelative && currPercent < 100) ? currPercent * remainingLen[k] / 100 : remainingLen[k];
             for(int i = 0; i < gridLen; i++)
                 if (grid[i].isPercent() && grid[i].value >= 0 && currPercent) {
-                    gridLayout[i] = grid[i].value * remainingLen[k] / currPercent;
+                    gridLayout[i] = grid[i].value * percentLen / currPercent;
                     remainingLen[k] -= gridLayout[i];
+                    percentLen -= gridLayout[i];
                     currPercent -= grid[i].value;
                 }
 
index fdadf66d8801e7fed0dd583e98f89aee763c5cee..801a73d65de5e4ac2ec9421b98869bf3566d3ce0 100644 (file)
@@ -439,6 +439,8 @@ bool TextImpl::rendererIsNeeded(RenderStyle *style)
             return false;
         
         RenderObject *first = par->firstChild();
+        while (first && first->isFloatingOrPositioned())
+            first = first->nextSibling();
         RenderObject *next = nextRenderer();
         if (!first || next == first)
             // Whitespace at the start of a block just goes away.  Don't even