Changeset 31116 in webkit


Ignore:
Timestamp:
Mar 17, 2008 9:04:34 PM (16 years ago)
Author:
mitz@apple.com
Message:

WebCore:

2008-03-17 Dan Bernstein <mitz@apple.com>

Reviewed by Dave Hyatt.

  • allow incremental relayout of blocks that contain floats

Tests: fast/repaint/line-flow-with-floats-[1-9].html

  • rendering/RenderBlock.cpp: (WebCore::RenderBlock::clearFloatsIfNeeded): Cleaned up by moving most of the function body out of an if statement which was replaced with an early return. (WebCore::RenderBlock::insertFloatingObject): Cleaned up by moving most of the function body out of an if statement and moving the ASSERT, which is a crash in release builds, to the beginning. Made this function set the m_isDescendant flag of floating objects it creates. (WebCore::RenderBlock::removeFloatingObject): Added a call to markLinesDirtyInVerticalRange() when removing a float from a block with inline children. (WebCore::RenderBlock::markLinesDirtyInVerticalRange): Added. Marks the lines in the given range as dirty. (WebCore::RenderBlock::clearFloats): Added code to detect changes to the geometry of floats intruding into this block from other blocks and mark any lines whose available width has changed as a result as dirty.
  • rendering/RenderBlock.h: (WebCore::RenderBlock::FloatWithRect::FloatWithRect): Added a structure to cache a float with its position and size. (WebCore::RenderBlock::FloatingObject::FloatingObject): Added an m_isDescendant flag, used by clearFloats() to distinguish between floats entering the block from outside and floats internal to the block.
  • rendering/RootInlineBox.h: (WebCore::RootInlineBox::floats): Added. (WebCore::RootInlineBox::floatsPtr): Added. (WebCore::RootInlineBox::Overflow::Overflow): Added a data member to hold the floats originating on the line.
  • rendering/bidi.cpp: (WebCore::RenderBlock::layoutInlineChildren): Made the existence of floats not force a full layout. Changed to cache the geometry of floats in the block and detect changes to it. If a float's size or position changes, all lines from that point on are treated as dirty. An exception is a change in the dimensions of a float on an otherwise-clean line, which only dirties lines potentially affected by the change (see determineStartPosition()). Added code to update each RootInlineBox's set of floats as lines are laid out. Added code to shift floats belonging to clean lines in the end along with the lines. (WebCore::RenderBlock::determineStartPosition): Made this function look for changes to floats' dimensions and mark lines as dirty accordingly. Also look for new floats and if found, cause a full layout. Added code to re-add floats belonging to clean lines. (WebCore::RenderBlock::matchedEndLine): Added checking that the clean lines in the end can be shifted vertically as needed, i.e. that the available width along the way is uniform.

LayoutTests:

2008-03-17 Dan Bernstein <mitz@apple.com>

Reviewed by Dave Hyatt.

  • test incremental relayout of blocks that contain floats
  • fast/repaint/line-flow-with-floats-1.html: Added.
  • fast/repaint/line-flow-with-floats-2.html: Added.
  • fast/repaint/line-flow-with-floats-3.html: Added.
  • fast/repaint/line-flow-with-floats-4.html: Added.
  • fast/repaint/line-flow-with-floats-5.html: Added.
  • fast/repaint/line-flow-with-floats-6.html: Added.
  • fast/repaint/line-flow-with-floats-7.html: Added.
  • fast/repaint/line-flow-with-floats-8.html: Added.
  • fast/repaint/line-flow-with-floats-9.html: Added.
  • fast/repaint/resources/line-flow-with-floats.html: Added.
  • fast/repaint/resources/line-flow-with-floats.js: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-1-expected.checksum: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-1-expected.png: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-1-expected.txt: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-2-expected.checksum: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-2-expected.png: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-2-expected.txt: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-3-expected.checksum: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-3-expected.png: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-3-expected.txt: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-4-expected.checksum: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-4-expected.png: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-4-expected.txt: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-5-expected.checksum: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-5-expected.png: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-5-expected.txt: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-6-expected.checksum: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-6-expected.png: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-6-expected.txt: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-7-expected.checksum: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-7-expected.png: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-7-expected.txt: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-8-expected.checksum: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-8-expected.png: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-8-expected.txt: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-9-expected.checksum: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-9-expected.png: Added.
  • platform/mac/fast/repaint/line-flow-with-floats-9-expected.txt: Added.
Location:
trunk
Files:
38 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r31112 r31116  
     12008-03-17  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Dave Hyatt.
     4
     5        - test incremental relayout of blocks that contain floats
     6
     7        * fast/repaint/line-flow-with-floats-1.html: Added.
     8        * fast/repaint/line-flow-with-floats-2.html: Added.
     9        * fast/repaint/line-flow-with-floats-3.html: Added.
     10        * fast/repaint/line-flow-with-floats-4.html: Added.
     11        * fast/repaint/line-flow-with-floats-5.html: Added.
     12        * fast/repaint/line-flow-with-floats-6.html: Added.
     13        * fast/repaint/line-flow-with-floats-7.html: Added.
     14        * fast/repaint/line-flow-with-floats-8.html: Added.
     15        * fast/repaint/line-flow-with-floats-9.html: Added.
     16        * fast/repaint/resources/line-flow-with-floats.html: Added.
     17        * fast/repaint/resources/line-flow-with-floats.js: Added.
     18        * platform/mac/fast/repaint/line-flow-with-floats-1-expected.checksum: Added.
     19        * platform/mac/fast/repaint/line-flow-with-floats-1-expected.png: Added.
     20        * platform/mac/fast/repaint/line-flow-with-floats-1-expected.txt: Added.
     21        * platform/mac/fast/repaint/line-flow-with-floats-2-expected.checksum: Added.
     22        * platform/mac/fast/repaint/line-flow-with-floats-2-expected.png: Added.
     23        * platform/mac/fast/repaint/line-flow-with-floats-2-expected.txt: Added.
     24        * platform/mac/fast/repaint/line-flow-with-floats-3-expected.checksum: Added.
     25        * platform/mac/fast/repaint/line-flow-with-floats-3-expected.png: Added.
     26        * platform/mac/fast/repaint/line-flow-with-floats-3-expected.txt: Added.
     27        * platform/mac/fast/repaint/line-flow-with-floats-4-expected.checksum: Added.
     28        * platform/mac/fast/repaint/line-flow-with-floats-4-expected.png: Added.
     29        * platform/mac/fast/repaint/line-flow-with-floats-4-expected.txt: Added.
     30        * platform/mac/fast/repaint/line-flow-with-floats-5-expected.checksum: Added.
     31        * platform/mac/fast/repaint/line-flow-with-floats-5-expected.png: Added.
     32        * platform/mac/fast/repaint/line-flow-with-floats-5-expected.txt: Added.
     33        * platform/mac/fast/repaint/line-flow-with-floats-6-expected.checksum: Added.
     34        * platform/mac/fast/repaint/line-flow-with-floats-6-expected.png: Added.
     35        * platform/mac/fast/repaint/line-flow-with-floats-6-expected.txt: Added.
     36        * platform/mac/fast/repaint/line-flow-with-floats-7-expected.checksum: Added.
     37        * platform/mac/fast/repaint/line-flow-with-floats-7-expected.png: Added.
     38        * platform/mac/fast/repaint/line-flow-with-floats-7-expected.txt: Added.
     39        * platform/mac/fast/repaint/line-flow-with-floats-8-expected.checksum: Added.
     40        * platform/mac/fast/repaint/line-flow-with-floats-8-expected.png: Added.
     41        * platform/mac/fast/repaint/line-flow-with-floats-8-expected.txt: Added.
     42        * platform/mac/fast/repaint/line-flow-with-floats-9-expected.checksum: Added.
     43        * platform/mac/fast/repaint/line-flow-with-floats-9-expected.png: Added.
     44        * platform/mac/fast/repaint/line-flow-with-floats-9-expected.txt: Added.
     45
    1462008-03-17  Eric Seidel  <eric@webkit.org>
    247
  • trunk/WebCore/ChangeLog

    r31112 r31116  
     12008-03-17  Dan Bernstein  <mitz@apple.com>
     2
     3        Reviewed by Dave Hyatt.
     4
     5        - allow incremental relayout of blocks that contain floats
     6
     7        Tests: fast/repaint/line-flow-with-floats-[1-9].html
     8
     9        * rendering/RenderBlock.cpp:
     10        (WebCore::RenderBlock::clearFloatsIfNeeded): Cleaned up by moving most
     11        of the function body out of an if statement which was replaced with an
     12        early return.
     13        (WebCore::RenderBlock::insertFloatingObject): Cleaned up by moving most
     14        of the function body out of an if statement and moving the ASSERT, which
     15        is a crash in release builds, to the beginning. Made this function set
     16        the m_isDescendant flag of floating objects it creates.
     17        (WebCore::RenderBlock::removeFloatingObject): Added a call to
     18        markLinesDirtyInVerticalRange() when removing a float from a block with
     19        inline children.
     20        (WebCore::RenderBlock::markLinesDirtyInVerticalRange): Added. Marks the
     21        lines in the given range as dirty.
     22        (WebCore::RenderBlock::clearFloats): Added code to detect changes to
     23        the geometry of floats intruding into this block from other blocks and
     24        mark any lines whose available width has changed as a result as dirty.
     25
     26        * rendering/RenderBlock.h:
     27        (WebCore::RenderBlock::FloatWithRect::FloatWithRect): Added a structure
     28        to cache a float with its position and size.
     29        (WebCore::RenderBlock::FloatingObject::FloatingObject): Added an
     30        m_isDescendant flag, used by clearFloats() to distinguish between floats
     31        entering the block from outside and floats internal to the block.
     32
     33        * rendering/RootInlineBox.h:
     34        (WebCore::RootInlineBox::floats): Added.
     35        (WebCore::RootInlineBox::floatsPtr): Added.
     36        (WebCore::RootInlineBox::Overflow::Overflow): Added a data member to
     37        hold the floats originating on the line.
     38
     39        * rendering/bidi.cpp:
     40        (WebCore::RenderBlock::layoutInlineChildren): Made the existence of
     41        floats not force a full layout. Changed to cache the geometry of floats
     42        in the block and detect changes to it. If a float's size or position
     43        changes, all lines from that point on are treated as dirty. An exception
     44        is a change in the dimensions of a float on an otherwise-clean line,
     45        which only dirties lines potentially affected by the change (see
     46        determineStartPosition()). Added code to update each RootInlineBox's
     47        set of floats as lines are laid out. Added code to shift floats
     48        belonging to clean lines in the end along with the lines.
     49        (WebCore::RenderBlock::determineStartPosition): Made this function look
     50        for changes to floats' dimensions and mark lines as dirty accordingly.
     51        Also look for new floats and if found, cause a full layout. Added code
     52        to re-add floats belonging to clean lines.
     53        (WebCore::RenderBlock::matchedEndLine): Added checking that the clean
     54        lines in the end can be shifted vertically as needed, i.e. that the
     55        available width along the way is uniform.
     56
    1572008-03-17  Eric Seidel  <eric@webkit.org>
    258
  • trunk/WebCore/rendering/RenderBlock.cpp

    r31065 r31116  
    33 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
    44 *           (C) 2007 David Smith (catfish.man@gmail.com)
    5  * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
     5 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
    66 *
    77 * This library is free software; you can redistribute it and/or
     
    979979{
    980980    int heightIncrease = getClearDelta(child);
    981     if (heightIncrease) {
    982         // The child needs to be lowered.  Move the child so that it just clears the float.
    983         view()->addLayoutDelta(IntSize(0, -heightIncrease));
    984         child->setPos(child->xPos(), child->yPos() + heightIncrease);
    985 
    986         if (child->isSelfCollapsingBlock()) {
    987             // For self-collapsing blocks that clear, they can still collapse their
    988             // margins with following siblings.  Reset the current margins to represent
    989             // the self-collapsing block's margins only.
    990             marginInfo.setPosMargin(max(child->maxTopMargin(true), child->maxBottomMargin(true)));
    991             marginInfo.setNegMargin(max(child->maxTopMargin(false), child->maxBottomMargin(false)));
    992            
    993             // Adjust our height such that we are ready to be collapsed with subsequent siblings.
    994             m_height = child->yPos() - max(0, marginInfo.margin());
    995            
    996             // Set a flag that we cleared a float so that we know both to increase the height of the block
    997             // to compensate for the clear and to avoid collapsing our margins with the parent block's
    998             // bottom margin.
    999             marginInfo.setSelfCollapsingBlockClearedFloat(true);
    1000         } else
    1001             // Increase our height by the amount we had to clear.
    1002             m_height += heightIncrease;
    1003        
    1004         if (marginInfo.canCollapseWithTop()) {
    1005             // We can no longer collapse with the top of the block since a clear
    1006             // occurred.  The empty blocks collapse into the cleared block.
    1007             // FIXME: This isn't quite correct.  Need clarification for what to do
    1008             // if the height the cleared block is offset by is smaller than the
    1009             // margins involved.
    1010             setMaxTopMargins(oldTopPosMargin, oldTopNegMargin);
    1011             marginInfo.setAtTopOfBlock(false);
    1012         }
    1013 
    1014         // If our value of clear caused us to be repositioned vertically to be
    1015         // underneath a float, we might have to do another layout to take into account
    1016         // the extra space we now have available.
    1017         if (child->shrinkToAvoidFloats())
    1018             // The child's width depends on the line width.
    1019             // When the child shifts to clear an item, its width can
    1020             // change (because it has more available line width).
    1021             // So go ahead and mark the item as dirty.
    1022             child->setChildNeedsLayout(true, false);
    1023         if (!child->avoidsFloats() && child->containsFloats())
    1024             child->markAllDescendantsWithFloatsForLayout();
    1025         child->layoutIfNeeded();
    1026     }
     981    if (!heightIncrease)
     982        return;
     983
     984    // The child needs to be lowered.  Move the child so that it just clears the float.
     985    view()->addLayoutDelta(IntSize(0, -heightIncrease));
     986    child->setPos(child->xPos(), child->yPos() + heightIncrease);
     987
     988    if (child->isSelfCollapsingBlock()) {
     989        // For self-collapsing blocks that clear, they can still collapse their
     990        // margins with following siblings.  Reset the current margins to represent
     991        // the self-collapsing block's margins only.
     992        marginInfo.setPosMargin(max(child->maxTopMargin(true), child->maxBottomMargin(true)));
     993        marginInfo.setNegMargin(max(child->maxTopMargin(false), child->maxBottomMargin(false)));
     994       
     995        // Adjust our height such that we are ready to be collapsed with subsequent siblings.
     996        m_height = child->yPos() - max(0, marginInfo.margin());
     997       
     998        // Set a flag that we cleared a float so that we know both to increase the height of the block
     999        // to compensate for the clear and to avoid collapsing our margins with the parent block's
     1000        // bottom margin.
     1001        marginInfo.setSelfCollapsingBlockClearedFloat(true);
     1002    } else
     1003        // Increase our height by the amount we had to clear.
     1004        m_height += heightIncrease;
     1005   
     1006    if (marginInfo.canCollapseWithTop()) {
     1007        // We can no longer collapse with the top of the block since a clear
     1008        // occurred.  The empty blocks collapse into the cleared block.
     1009        // FIXME: This isn't quite correct.  Need clarification for what to do
     1010        // if the height the cleared block is offset by is smaller than the
     1011        // margins involved.
     1012        setMaxTopMargins(oldTopPosMargin, oldTopNegMargin);
     1013        marginInfo.setAtTopOfBlock(false);
     1014    }
     1015
     1016    // If our value of clear caused us to be repositioned vertically to be
     1017    // underneath a float, we might have to do another layout to take into account
     1018    // the extra space we now have available.
     1019    if (child->shrinkToAvoidFloats())
     1020        // The child's width depends on the line width.
     1021        // When the child shifts to clear an item, its width can
     1022        // change (because it has more available line width).
     1023        // So go ahead and mark the item as dirty.
     1024        child->setChildNeedsLayout(true, false);
     1025    if (!child->avoidsFloats() && child->containsFloats())
     1026        child->markAllDescendantsWithFloatsForLayout();
     1027    child->layoutIfNeeded();
    10271028}
    10281029
     
    21142115void RenderBlock::insertFloatingObject(RenderObject *o)
    21152116{
     2117    ASSERT(o->isFloating());
     2118
    21162119    // Create the list of special objects if we don't aleady have one
    21172120    if (!m_floatingObjects) {
    21182121        m_floatingObjects = new DeprecatedPtrList<FloatingObject>;
    21192122        m_floatingObjects->setAutoDelete(true);
    2120     }
    2121     else {
     2123    } else {
    21222124        // Don't insert the object again if it's already in the list
    21232125        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
     
    21312133    // Create the special object entry & append it to the list
    21322134
    2133     FloatingObject *newObj;
    2134     if (o->isFloating()) {
    2135         // floating object
    2136         o->layoutIfNeeded();
    2137 
    2138         if(o->style()->floating() == FLEFT)
    2139             newObj = new FloatingObject(FloatingObject::FloatLeft);
    2140         else
    2141             newObj = new FloatingObject(FloatingObject::FloatRight);
    2142 
    2143         newObj->startY = -1;
    2144         newObj->endY = -1;
    2145         newObj->width = o->width() + o->marginLeft() + o->marginRight();
    2146         newObj->noPaint = o->hasLayer(); // If a layer exists, the float will paint itself.  Otherwise someone else will.
    2147     }
    2148     else {
    2149         // We should never get here, as insertFloatingObject() should only ever be called with floating
    2150         // objects.
    2151         ASSERT(false);
    2152         newObj = 0; // keep gcc's uninitialized variable warnings happy
    2153     }
    2154 
     2135    o->layoutIfNeeded();
     2136
     2137    FloatingObject* newObj = new FloatingObject(o->style()->floating() == FLEFT ? FloatingObject::FloatLeft : FloatingObject::FloatRight);
     2138
     2139    newObj->startY = -1;
     2140    newObj->endY = -1;
     2141    newObj->width = o->width() + o->marginLeft() + o->marginRight();
     2142    newObj->noPaint = o->hasLayer(); // If a layer exists, the float will paint itself.  Otherwise someone else will.
     2143    newObj->m_isDescendant = true;
    21552144    newObj->node = o;
    21562145
     
    21632152        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
    21642153        while (it.current()) {
    2165             if (it.current()->node == o)
     2154            if (it.current()->node == o) {
     2155                if (childrenInline())
     2156                    markLinesDirtyInVerticalRange(0, it.current()->endY);
    21662157                m_floatingObjects->removeRef(it.current());
     2158            }
    21672159            ++it;
    21682160        }
     
    21702162}
    21712163
    2172 void RenderBlock::positionNewFloats()
     2164bool RenderBlock::positionNewFloats()
    21732165{
    21742166    if (!m_floatingObjects)
    2175         return;
     2167        return false;
    21762168   
    21772169    FloatingObject* f = m_floatingObjects->last();
     
    21792171    // If all floats have already been positioned, then we have no work to do.
    21802172    if (!f || f->startY != -1)
    2181         return;
     2173        return false;
    21822174
    21832175    // Move backwards through our floating object list until we find a float that has
     
    22542246        f = m_floatingObjects->next();
    22552247    }
     2248    return true;
    22562249}
    22572250
     
    26082601}
    26092602
    2610 void
    2611 RenderBlock::clearFloats()
    2612 {
    2613     if (m_floatingObjects)
    2614         m_floatingObjects->clear();
    2615 
     2603void RenderBlock::markLinesDirtyInVerticalRange(int top, int bottom)
     2604{
     2605    if (top >= bottom)
     2606        return;
     2607
     2608    RootInlineBox* lowestDirtyLine = lastRootBox();
     2609    RootInlineBox* afterLowest = lowestDirtyLine;
     2610    while (lowestDirtyLine && lowestDirtyLine->blockHeight() >= bottom) {
     2611        afterLowest = lowestDirtyLine;
     2612        lowestDirtyLine = lowestDirtyLine->prevRootBox();
     2613    }
     2614
     2615    while (afterLowest && afterLowest->blockHeight() > top) {
     2616        afterLowest->markDirty();
     2617        afterLowest = afterLowest->prevRootBox();
     2618    }
     2619}
     2620
     2621void RenderBlock::clearFloats()
     2622{
    26162623    // Inline blocks are covered by the isReplaced() check in the avoidFloats method.
    2617     if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrPositioned() || isTableCell())
     2624    if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrPositioned() || isTableCell()) {
     2625        if (m_floatingObjects)
     2626            m_floatingObjects->clear();
    26182627        return;
    2619    
     2628    }
     2629
     2630    typedef HashMap<RenderObject*, FloatingObject*> RendererToFloatInfoMap;
     2631    RendererToFloatInfoMap floatMap;
     2632
     2633    if (m_floatingObjects) {
     2634        if (childrenInline()) {
     2635            m_floatingObjects->first();
     2636            while (FloatingObject* f = m_floatingObjects->take())
     2637                floatMap.add(f->node, f);
     2638        } else
     2639            m_floatingObjects->clear();
     2640    }
     2641
    26202642    // Attempt to locate a previous sibling with overhanging floats.  We skip any elements that are
    26212643    // out of flow (like floating/positioned elements), and we also skip over any objects that may have shifted
     
    26422664        xoffset += prev->borderLeft() + prev->paddingLeft();
    26432665    }
    2644     //kdDebug() << "RenderBlock::clearFloats found previous "<< (void *)this << " prev=" << (void *)prev<< endl;
    26452666
    26462667    // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.
    26472668    if (!prev->isRenderBlock()) return;
    26482669    RenderBlock* block = static_cast<RenderBlock *>(prev);
    2649     if (!block->m_floatingObjects) return;
    2650     if (block->floatBottom() > offset)
     2670
     2671    if (block->m_floatingObjects && block->floatBottom() > offset)
    26512672        addIntrudingFloats(block, xoffset, offset);
     2673
     2674    if (childrenInline()) {
     2675        int changeTop = INT_MAX;
     2676        int changeBottom = INT_MIN;
     2677        if (m_floatingObjects) {
     2678            for (FloatingObject* f = m_floatingObjects->first(); f; f = m_floatingObjects->next()) {
     2679                FloatingObject* oldFloatingObject = floatMap.get(f->node);
     2680                if (oldFloatingObject) {
     2681                    if (f->width != oldFloatingObject->width || f->left != oldFloatingObject->left) {
     2682                        changeTop = 0;
     2683                        changeBottom = max(changeBottom, max(f->endY, oldFloatingObject->endY));
     2684                    } else if (f->endY != oldFloatingObject->endY) {
     2685                        changeTop = min(changeTop, min(f->endY, oldFloatingObject->endY));
     2686                        changeBottom = max(changeBottom, max(f->endY, oldFloatingObject->endY));
     2687                    }
     2688
     2689                    floatMap.remove(f->node);
     2690                    delete oldFloatingObject;
     2691                } else {
     2692                    changeTop = 0;
     2693                    changeBottom = max(changeBottom, f->endY);
     2694                }
     2695            }
     2696        }
     2697
     2698        RendererToFloatInfoMap::iterator end = floatMap.end();
     2699        for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) {
     2700            FloatingObject* floatingObject = (*it).second;
     2701            if (!floatingObject->m_isDescendant) {
     2702                changeTop = 0;
     2703                changeBottom = max(changeBottom, floatingObject->endY);
     2704            }
     2705        }
     2706        deleteAllValues(floatMap);
     2707
     2708        markLinesDirtyInVerticalRange(changeTop, changeBottom);
     2709    }
    26522710}
    26532711
  • trunk/WebCore/rendering/RenderBlock.h

    r30963 r31116  
    55 *           (C) 1999 Antti Koivisto (koivisto@kde.org)
    66 *           (C) 2007 David Smith (catfish.man@gmail.com)
    7  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Computer, Inc.
     7 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
    88 *
    99 * This library is free software; you can redistribute it and/or
     
    127127
    128128    // the implementation of the following functions is in bidi.cpp
     129    struct FloatWithRect {
     130        FloatWithRect(RenderObject* f)
     131            : object(f)
     132            , rect(IntRect(f->xPos() - f->marginLeft(), f->yPos() - f->marginTop(), f->width() + f->marginLeft() + f->marginRight(), f->height() + f->marginTop() + f->marginBottom()))
     133        {
     134        }
     135
     136        RenderObject* object;
     137        IntRect rect;
     138    };
     139
    129140    void bidiReorderLine(BidiState&, const BidiIterator& end);
    130     RootInlineBox* determineStartPosition(bool fullLayout, BidiState&);
     141    RootInlineBox* determineStartPosition(bool& fullLayout, BidiState&, Vector<FloatWithRect>& floats, unsigned& numCleanFloats);
    131142    RootInlineBox* determineEndPosition(RootInlineBox* startBox, BidiIterator& cleanLineStart,
    132143                                        BidiStatus& cleanLineBidiStatus,
     
    162173
    163174    // called from lineWidth, to position the floats added in the last line.
    164     void positionNewFloats();
     175    bool positionNewFloats();
    165176    void clearFloats();
    166177    int getClearDelta(RenderObject* child);
     
    299310    void adjustForBorderFit(int x, int& left, int& right) const; // Helper function for borderFitAdjust
    300311
     312    void markLinesDirtyInVerticalRange(int top, int bottom);
     313
    301314protected:
    302315    void newLine();
     
    327340            , m_type(type)
    328341            , noPaint(false)
     342            , m_isDescendant(false)
    329343        {
    330344        }
     
    339353        unsigned m_type : 1; // Type (left or right aligned)
    340354        bool noPaint : 1;
     355        bool m_isDescendant : 1;
    341356    };
    342357
     
    447462    ListHashSet<RenderObject*>* m_positionedObjects;
    448463         
    449      // Allocated only when some of these fields have non-default values
    450      struct MaxMargin {
    451          MaxMargin(const RenderBlock* o)
    452              : m_topPos(topPosDefault(o))
    453              , m_topNeg(topNegDefault(o))
    454              , m_bottomPos(bottomPosDefault(o))
    455              , m_bottomNeg(bottomNegDefault(o))
    456              {
    457              }
    458          static int topPosDefault(const RenderBlock* o) { return o->marginTop() > 0 ? o->marginTop() : 0; }
    459          static int topNegDefault(const RenderBlock* o) { return o->marginTop() < 0 ? -o->marginTop() : 0; }
    460          static int bottomPosDefault(const RenderBlock* o) { return o->marginBottom() > 0 ? o->marginBottom() : 0; }
    461          static int bottomNegDefault(const RenderBlock* o) { return o->marginBottom() < 0 ? -o->marginBottom() : 0; }
    462          
    463          int m_topPos;
    464          int m_topNeg;
    465          int m_bottomPos;
    466          int m_bottomNeg;
     464    // Allocated only when some of these fields have non-default values
     465    struct MaxMargin {
     466        MaxMargin(const RenderBlock* o)
     467            : m_topPos(topPosDefault(o))
     468            , m_topNeg(topNegDefault(o))
     469            , m_bottomPos(bottomPosDefault(o))
     470            , m_bottomNeg(bottomNegDefault(o))
     471        {
     472        }
     473
     474        static int topPosDefault(const RenderBlock* o) { return o->marginTop() > 0 ? o->marginTop() : 0; }
     475        static int topNegDefault(const RenderBlock* o) { return o->marginTop() < 0 ? -o->marginTop() : 0; }
     476        static int bottomPosDefault(const RenderBlock* o) { return o->marginBottom() > 0 ? o->marginBottom() : 0; }
     477        static int bottomNegDefault(const RenderBlock* o) { return o->marginBottom() < 0 ? -o->marginBottom() : 0; }
     478
     479        int m_topPos;
     480        int m_topNeg;
     481        int m_bottomPos;
     482        int m_bottomNeg;
    467483     };
    468484
  • trunk/WebCore/rendering/RootInlineBox.h

    r26384 r31116  
    22 * This file is part of the line box implementation for KDE.
    33 *
    4  * Copyright (C) 2003, 2006 Apple Computer, Inc.
     4 * Copyright (C) 2003, 2006, 2007, 2008 Apple Inc. All rights reserved.
    55 *
    66 * This library is free software; you can redistribute it and/or
     
    119119
    120120    InlineBox* closestLeafChildForXPos(int x, bool onlyEditableLeaves = false);
     121
     122    Vector<RenderObject*>& floats()
     123    {
     124        ASSERT(!isDirty());
     125        if (!m_overflow)
     126            m_overflow = new (m_object->renderArena()) Overflow(this);
     127        return m_overflow->floats;
     128    }
     129
     130    Vector<RenderObject*>* floatsPtr() { ASSERT(!isDirty()); return m_overflow ? &m_overflow->floats : 0; }
    121131
    122132protected:
     
    134144            , m_selectionTop(box->m_y)
    135145            , m_selectionBottom(box->m_y + box->m_height)
    136             {
    137             }
     146        {
     147        }
     148
    138149        void destroy(RenderArena*);
    139150        void* operator new(size_t, RenderArena*) throw();
     
    146157        int m_selectionTop;
    147158        int m_selectionBottom;
     159        // Floats hanging off the line are pushed into this vector during layout. It is only
     160        // good for as long as the line has not been marked dirty.
     161        Vector<RenderObject*> floats;
    148162    private:
    149163        void* operator new(size_t) throw();
  • trunk/WebCore/rendering/bidi.cpp

    r31011 r31116  
    762762    // FIXME: Handle resize eventually!
    763763    // FIXME: Do something better when floats are present.
    764     bool fullLayout = !firstLineBox() || !firstChild() || selfNeedsLayout() || relayoutChildren || containsFloats();
     764    bool fullLayout = !firstLineBox() || !firstChild() || selfNeedsLayout() || relayoutChildren;
    765765    if (fullLayout)
    766766        deleteLineBoxes();
     
    781781        bool endOfInline = false;
    782782        RenderObject* o = bidiFirst(this, 0, false);
    783         bool hasFloat = false;
     783        Vector<FloatWithRect> floats;
    784784        int containerWidth = max(0, containingBlockWidth());
    785785        while (o) {
     
    797797                else {
    798798                    if (o->isFloating())
    799                         hasFloat = true;
     799                        floats.append(FloatWithRect(o));
    800800                    else if (fullLayout || o->needsLayout()) // Replaced elements
    801801                        o->dirtyLineBoxes(fullLayout);
     802
    802803                    o->layoutIfNeeded();
    803804                }
    804             }
    805             else if (o->isText() || (o->isInlineFlow() && !endOfInline)) {
     805            } else if (o->isText() || (o->isInlineFlow() && !endOfInline)) {
    806806                if (fullLayout || o->selfNeedsLayout())
    807807                    o->dirtyLineBoxes(fullLayout);
     
    815815        }
    816816
    817         if (hasFloat)
    818             fullLayout = true; // FIXME: Will need to find a way to optimize floats some day.
     817        // We want to skip ahead to the first dirty line
     818        BidiState start;
     819        unsigned floatIndex;
     820        RootInlineBox* startLine = determineStartPosition(fullLayout, start, floats, floatIndex);
    819821
    820822        if (fullLayout && !selfNeedsLayout()) {
     
    832834        }
    833835
     836        FloatingObject* lastFloat = m_floatingObjects ? m_floatingObjects->last() : 0;
     837
    834838        if (!smidpoints)
    835839            smidpoints = new Vector<BidiIterator>();
     
    837841        sNumMidpoints = 0;
    838842        sCurrMidpoint = 0;
    839 
    840         // We want to skip ahead to the first dirty line
    841         BidiState start;
    842         RootInlineBox* startLine = determineStartPosition(fullLayout, start);
    843843
    844844        // We also find the first clean line and extract these lines.  We will add them back
     
    867867        BidiIterator end = start.position();
    868868
     869        if (!fullLayout && end.atEnd() && lastRootBox() && lastRootBox()->firstChild()->object()->isBR() && lastRootBox()->object()->firstChild()->style()->clear() != CNONE) {
     870            m_clearStatus = lastRootBox()->object()->firstChild()->style()->clear();
     871            newLine();
     872        }
     873
    869874        bool endLineMatched = false;
     875
    870876        while (!end.atEnd()) {
    871877            // FIXME: Is this check necessary before the first iteration or can it be moved to the end?
     
    932938            }
    933939
     940            if (m_floatingObjects) {
     941                if (lastFloat) {
     942                    for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) {
     943                    }
     944                    m_floatingObjects->next();
     945                } else
     946                    m_floatingObjects->first();
     947                for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next()) {
     948                    lastRootBox()->floats().append(f->node);
     949                    ASSERT(f->node == floats[floatIndex].object);
     950                    // If a float's geometry has changed, give up on syncing with clean lines.
     951                    if (floats[floatIndex].rect != IntRect(f->left, f->startY, f->width, f->endY - f->startY))
     952                        endLine = 0;
     953                    floatIndex++;
     954                }
     955                lastFloat = m_floatingObjects->last();
     956            }
     957
    934958            sNumMidpoints = 0;
    935959            sCurrMidpoint = 0;
     
    940964            if (endLineMatched) {
    941965                // Attach all the remaining lines, and then adjust their y-positions as needed.
    942                 for (RootInlineBox* line = endLine; line; line = line->nextRootBox())
     966                int delta = m_height - endLineYPos;
     967                for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) {
    943968                    line->attachLine();
    944 
    945                 // Now apply the offset to each line if needed.
    946                 int delta = m_height - endLineYPos;
    947                 if (delta) {
    948                     for (RootInlineBox* line = endLine; line; line = line->nextRootBox()) {
     969                    if (delta) {
    949970                        repaintTop = min(repaintTop, line->topOverflow() + min(delta, 0));
    950971                        repaintBottom = max(repaintBottom, line->bottomOverflow() + max(delta, 0));
    951972                        line->adjustPosition(0, delta);
     973                    }
     974                    if (Vector<RenderObject*>* cleanLineFloats = line->floatsPtr()) {
     975                        Vector<RenderObject*>::iterator end = cleanLineFloats->end();
     976                        for (Vector<RenderObject*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
     977                            int floatTop = (*f)->yPos() - (*f)->marginTop();
     978                            insertFloatingObject(*f);
     979                            m_height = floatTop + delta;
     980                            positionNewFloats();
     981                        }
    952982                    }
    953983                }
     
    966996            }
    967997        }
     998        if (m_floatingObjects) {
     999            // In case we have a float on the last line, it might not be positioned up to now.
     1000            // This has to be done before adding in the bottom border/padding, or the float will
     1001            // include the padding incorrectly. -dwh
     1002            if (positionNewFloats() && lastRootBox()) {
     1003                if (lastFloat) {
     1004                    for (FloatingObject* f = m_floatingObjects->last(); f != lastFloat; f = m_floatingObjects->prev()) {
     1005                    }
     1006                    m_floatingObjects->next();
     1007                } else
     1008                    m_floatingObjects->first();
     1009                for (FloatingObject* f = m_floatingObjects->current(); f; f = m_floatingObjects->next())
     1010                    lastRootBox()->floats().append(f->node);
     1011                lastFloat = m_floatingObjects->last();
     1012            }
     1013        }
     1014
    9681015    }
    9691016
    9701017    sNumMidpoints = 0;
    9711018    sCurrMidpoint = 0;
    972 
    973     // in case we have a float on the last line, it might not be positioned up to now.
    974     // This has to be done before adding in the bottom border/padding, or the float will
    975     // include the padding incorrectly. -dwh
    976     positionNewFloats();
    9771019
    9781020    // Now add in the bottom border/padding.
     
    9941036}
    9951037
    996 RootInlineBox* RenderBlock::determineStartPosition(bool fullLayout, BidiState& start)
     1038RootInlineBox* RenderBlock::determineStartPosition(bool& fullLayout, BidiState& start, Vector<FloatWithRect>& floats, unsigned& numCleanFloats)
    9971039{
    9981040    RootInlineBox* curr = 0;
    9991041    RootInlineBox* last = 0;
     1042
     1043    bool dirtiedByFloat = false;
     1044    if (!fullLayout) {
     1045        size_t floatIndex = 0;
     1046        for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) {
     1047            if (Vector<RenderObject*>* cleanLineFloats = curr->floatsPtr()) {
     1048                Vector<RenderObject*>::iterator end = cleanLineFloats->end();
     1049                for (Vector<RenderObject*>::iterator o = cleanLineFloats->begin(); o != end; ++o) {
     1050                    RenderObject* f = *o;
     1051                    IntSize newSize(f->width() + f->marginLeft() +f->marginRight(), f->height() + f->marginTop() + f->marginBottom());
     1052                    ASSERT(floatIndex < floats.size());
     1053                    if (floats[floatIndex].object != f) {
     1054                        // A new float has been inserted before this line or before its last known float.
     1055                        // Just do a full layout.
     1056                        fullLayout = true;
     1057                        break;
     1058                    }
     1059                    if (floats[floatIndex].rect.size() != newSize) {
     1060                        int floatTop = f->yPos() - f->marginTop();
     1061                        ASSERT(floatTop == floats[floatIndex].rect.y());
     1062                        curr->markDirty();
     1063                        markLinesDirtyInVerticalRange(curr->blockHeight(), floatTop + max(floats[floatIndex].rect.height(), newSize.height()));
     1064                        floats[floatIndex].rect.setSize(newSize);
     1065                        dirtiedByFloat = true;
     1066                    }
     1067                    floatIndex++;
     1068                }
     1069            }
     1070            if (dirtiedByFloat || fullLayout)
     1071                break;
     1072        }
     1073        // Check if a new float has been inserted after the last known float.
     1074        if (!curr && floatIndex < floats.size())
     1075            fullLayout = true;
     1076    }
    10001077
    10011078    if (fullLayout) {
     
    10121089        }
    10131090    } else {
    1014         for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) { }
    10151091        if (curr) {
    10161092            // We have a dirty line.
    10171093            if (RootInlineBox* prevRootBox = curr->prevRootBox()) {
    10181094                // We have a previous line.
    1019                 if (!prevRootBox->endsWithBreak() || prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= static_cast<RenderText*>(prevRootBox->lineBreakObj())->textLength())
     1095                if (!dirtiedByFloat && (!prevRootBox->endsWithBreak() || prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= static_cast<RenderText*>(prevRootBox->lineBreakObj())->textLength()))
    10201096                    // The previous line didn't break cleanly or broke at a newline
    10211097                    // that has been deleted, so treat it as dirty too.
     
    10311107        // If we have no dirty lines, then last is just the last root box.
    10321108        last = curr ? curr->prevRootBox() : lastRootBox();
     1109    }
     1110
     1111    numCleanFloats = 0;
     1112    if (!floats.isEmpty()) {
     1113        int savedHeight = m_height;
     1114        // Restore floats from clean lines.
     1115        RootInlineBox* line = firstRootBox();
     1116        while (line != curr) {
     1117            if (Vector<RenderObject*>* cleanLineFloats = line->floatsPtr()) {
     1118                Vector<RenderObject*>::iterator end = cleanLineFloats->end();
     1119                for (Vector<RenderObject*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
     1120                    insertFloatingObject(*f);
     1121                    m_height = (*f)->yPos() - (*f)->marginTop();
     1122                    positionNewFloats();
     1123                    ASSERT(floats[numCleanFloats].object == *f);
     1124                    numCleanFloats++;
     1125                }
     1126            }
     1127            line = line->nextRootBox();
     1128        }
     1129        m_height = savedHeight;
    10331130    }
    10341131
     
    10491146    #endif
    10501147            ;
     1148
    10511149        BidiContext* context = new BidiContext(ltr ? 0 : 1, ltr ? LeftToRight : RightToLeft, style()->unicodeBidi() == Override);
    10521150
     
    10941192bool RenderBlock::matchedEndLine(const BidiState& start, const BidiIterator& endLineStart, const BidiStatus& endLineStatus, RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop)
    10951193{
    1096     if (start.position() == endLineStart)
    1097         return start.status() == endLineStatus;
     1194    if (start.position() == endLineStart) {
     1195        if (start.status() != endLineStatus)
     1196            return false;
     1197
     1198        int delta = m_height - endYPos;
     1199        if (!delta || !m_floatingObjects)
     1200            return true;
     1201
     1202        // See if any floats end in the range along which we want to shift the lines vertically.
     1203        int top = min(m_height, endYPos);
     1204
     1205        RootInlineBox* lastLine = endLine;
     1206        while (RootInlineBox* nextLine = lastLine->nextRootBox())
     1207            lastLine = nextLine;
     1208
     1209        int bottom = lastLine->blockHeight() + abs(delta);
     1210
     1211        for (FloatingObject* f = m_floatingObjects->first(); f; f = m_floatingObjects->next()) {
     1212            if (f->endY >= top && f->endY < bottom)
     1213                return false;
     1214        }
     1215
     1216        return true;
     1217    }
    10981218
    10991219    // The first clean line doesn't match, but we can check a handful of following lines to try
     
    11111231            if (result)
    11121232                endYPos = line->blockHeight();
     1233
     1234            int delta = m_height - endYPos;
     1235            if (delta && m_floatingObjects) {
     1236                // See if any floats end in the range along which we want to shift the lines vertically.
     1237                int top = min(m_height, endYPos);
     1238
     1239                RootInlineBox* lastLine = endLine;
     1240                while (RootInlineBox* nextLine = lastLine->nextRootBox())
     1241                    lastLine = nextLine;
     1242
     1243                int bottom = lastLine->blockHeight() + abs(delta);
     1244
     1245                for (FloatingObject* f = m_floatingObjects->first(); f; f = m_floatingObjects->next()) {
     1246                    if (f->endY >= top && f->endY < bottom)
     1247                        return false;
     1248                }
     1249            }
    11131250
    11141251            // Now delete the lines that we failed to sync.
Note: See TracChangeset for help on using the changeset viewer.