Changeset 92610 in webkit
- Timestamp:
- Aug 8, 2011 11:09:19 AM (13 years ago)
- Location:
- trunk
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/PerformanceTests/ChangeLog
r92444 r92610 1 2011-08-08 Alexandru Chiculita <achicu@adobe.com> 2 3 Optimize floating elements lookup 4 https://bugs.webkit.org/show_bug.cgi?id=65668 5 6 Reviewed by David Hyatt. 7 8 * Layout/floats.html: Added the nested divs, so that we can test the propagation impact of the floats tree. 9 1 10 2011-08-04 Alexandru Chiculita <achicu@adobe.com> 2 11 -
trunk/PerformanceTests/Layout/floats.html
r92444 r92610 31 31 } 32 32 33 function createSet(width, height )33 function createSet(width, height, nested) 34 34 { 35 35 var container = createElement("div", document.body, "container"); … … 37 37 for (var x = 0; x < width; ++x) 38 38 createElement("div", container, "float", "float" + x + "_" + y); 39 40 var nestedContainer = container; 41 for ( ; nested > 0; --nested) 42 nestedContainer = createElement("div", nestedContainer, "nested", "nested" + x + "_" + nested); 43 39 44 createElement("div", container, "float-end", "end" + x) 40 45 } … … 48 53 } 49 54 50 function test(width, height )55 function test(width, height, nested) 51 56 { 57 nested = nested || 0; 58 52 59 document.getElementById("test_panel").style.display = "none"; 53 60 document.getElementById("framerate_panel").style.display = "block"; 54 61 55 createSet(width, height );62 createSet(width, height, nested); 56 63 var updates = 0; 57 64 var startTime = new Date(); … … 92 99 <button onclick="test(50, 100)">50 by 100</button> 93 100 <button onclick="test(100, 100)">100 by 100</button> 101 <p>Nested divs:</p> 102 <button onclick="test(2, 100, 100)">2 by 100, 100 nested</button> 103 <button onclick="test(20, 100, 100)">20 by 100, 100 nested</button> 104 <button onclick="test(50, 100, 100)">50 by 100, 100 nested</button> 105 <button onclick="test(100, 100, 100)">100 by 100, 100 nested</button> 94 106 </div> 95 107 </body> -
trunk/Source/WebCore/ChangeLog
r92607 r92610 1 2011-08-08 Alexandru Chiculita <achicu@adobe.com> 2 3 Optimize floating elements lookup 4 https://bugs.webkit.org/show_bug.cgi?id=65668 5 6 Added an interval tree in the FloatingObjects structure. Also added new mechanisms to make 7 sure the tree is updated correctly when a float is repositioned. 8 9 Changed the PODIntervalTree to support giving a search adapter that can be implemented by the 10 client. I'm not adding a different bug for that because PODIntervalTree is not used anywhere else 11 and would be hard to test that the change is not breaking anything. 12 13 Reviewed by David Hyatt. 14 15 No new tests, just a refactor on the floating objects data structure. 16 17 * WebCore.xcodeproj/project.pbxproj: 18 * platform/PODIntervalTree.h: 19 (WebCore::PODIntervalSearchAdapter::PODIntervalSearchAdapter): 20 (WebCore::PODIntervalSearchAdapter::lowValue): 21 (WebCore::PODIntervalSearchAdapter::highValue): 22 (WebCore::PODIntervalSearchAdapter::collectIfNeeded): 23 (WebCore::PODIntervalTree::PODIntervalTree): 24 (WebCore::PODIntervalTree::allOverlaps): 25 (WebCore::PODIntervalTree::allOverlapsWithAdapter): 26 (WebCore::PODIntervalTree::searchForOverlapsFrom): 27 * platform/PODRedBlackTree.h: 28 (WebCore::PODRedBlackTree::PODRedBlackTree): 29 (WebCore::PODRedBlackTree::clear): 30 (WebCore::PODRedBlackTree::isInitialized): 31 (WebCore::PODRedBlackTree::initIfNeeded): 32 (WebCore::PODRedBlackTree::add): 33 (WebCore::PODRedBlackTree::remove): 34 (WebCore::PODRedBlackTree::contains): 35 (WebCore::PODRedBlackTree::visitInorder): 36 (WebCore::PODRedBlackTree::size): 37 (WebCore::PODRedBlackTree::checkInvariants): 38 (WebCore::PODRedBlackTree::dump): 39 * rendering/RenderBlock.cpp: 40 (WebCore::RenderBlock::styleDidChange): 41 (WebCore::RenderBlock::addOverflowFromFloats): 42 (WebCore::RenderBlock::repaintOverhangingFloats): 43 (WebCore::RenderBlock::paintFloats): 44 (WebCore::RenderBlock::selectionGaps): 45 (WebCore::RenderBlock::insertFloatingObject): 46 (WebCore::RenderBlock::removeFloatingObject): 47 (WebCore::RenderBlock::removeFloatingObjectsBelow): 48 (WebCore::RenderBlock::positionNewFloats): 49 (WebCore::::collectIfNeeded): 50 (WebCore::RenderBlock::logicalLeftOffsetForLine): 51 (WebCore::RenderBlock::logicalRightOffsetForLine): 52 (WebCore::RenderBlock::nextFloatLogicalBottomBelow): 53 (WebCore::RenderBlock::lowestFloatLogicalBottom): 54 (WebCore::RenderBlock::addPositionedFloats): 55 (WebCore::RenderBlock::clearFloats): 56 (WebCore::RenderBlock::addOverhangingFloats): 57 (WebCore::RenderBlock::hasOverhangingFloat): 58 (WebCore::RenderBlock::addIntrudingFloats): 59 (WebCore::RenderBlock::markSiblingsWithFloatsForLayout): 60 (WebCore::RenderBlock::hitTestFloats): 61 (WebCore::RenderBlock::adjustForBorderFit): 62 (WebCore::RenderBlock::FloatingObjects::clear): 63 (WebCore::RenderBlock::FloatingObjects::intervalForFloatingObject): 64 (WebCore::RenderBlock::FloatingObjects::addPlacedObject): 65 (WebCore::RenderBlock::FloatingObjects::removePlacedObject): 66 (WebCore::RenderBlock::FloatingObjects::add): 67 (WebCore::RenderBlock::FloatingObjects::remove): 68 (WebCore::RenderBlock::FloatingObjects::computePlacedFloatsTree): 69 (WebCore::::string): 70 * rendering/RenderBlock.h: 71 (WebCore::RenderBlock::FloatingObject::FloatingObject): 72 (WebCore::RenderBlock::FloatingObject::setX): 73 (WebCore::RenderBlock::FloatingObject::setY): 74 (WebCore::RenderBlock::FloatingObject::setWidth): 75 (WebCore::RenderBlock::FloatingObject::setHeight): 76 (WebCore::RenderBlock::FloatingObject::setFrameRect): 77 (WebCore::RenderBlock::FloatingObject::isInPlacedTree): 78 (WebCore::RenderBlock::FloatingObject::setIsInPlacedTree): 79 (WebCore::RenderBlock::FloatIntervalSearchAdapter::FloatIntervalSearchAdapter): 80 (WebCore::RenderBlock::FloatIntervalSearchAdapter::lowValue): 81 (WebCore::RenderBlock::FloatIntervalSearchAdapter::highValue): 82 (WebCore::RenderBlock::FloatingObjects::FloatingObjects): 83 (WebCore::RenderBlock::FloatingObjects::setHorizontalWritingMode): 84 (WebCore::RenderBlock::FloatingObjects::set): 85 (WebCore::RenderBlock::FloatingObjects::placedFloatsTree): 86 (WebCore::RenderBlock::FloatingObjects::computePlacedFloatsTreeIfNeeded): 87 * rendering/RenderBlockLineLayout.cpp: 88 (WebCore::RenderBlock::layoutRunsAndFloatsInRange): 89 (WebCore::RenderBlock::linkToEndLineIfNeeded): 90 (WebCore::RenderBlock::matchedEndLine): 91 (WebCore::RenderBlock::positionNewFloatOnLine): 92 1 93 2011-08-08 Alexei Svitkine <asvitkine@chromium.org> 2 94 -
trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj
r92592 r92610 1337 1337 508CCA4F13CF106B003151F3 /* RenderFlowThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 508CCA4D13CF106B003151F3 /* RenderFlowThread.h */; }; 1338 1338 508CCA5013CF106B003151F3 /* RenderFlowThread.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 508CCA4E13CF106B003151F3 /* RenderFlowThread.cpp */; }; 1339 5097C5A313EABA7E002DE4AF /* PODArena.h in Headers */ = {isa = PBXBuildFile; fileRef = 5097C59F13EABA7E002DE4AF /* PODArena.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1340 5097C5A413EABA7E002DE4AF /* PODInterval.h in Headers */ = {isa = PBXBuildFile; fileRef = 5097C5A013EABA7E002DE4AF /* PODInterval.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1341 5097C5A513EABA7E002DE4AF /* PODIntervalTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 5097C5A113EABA7E002DE4AF /* PODIntervalTree.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1342 5097C5A613EABA7E002DE4AF /* PODRedBlackTree.h in Headers */ = {isa = PBXBuildFile; fileRef = 5097C5A213EABA7E002DE4AF /* PODRedBlackTree.h */; settings = {ATTRIBUTES = (Private, ); }; }; 1339 1343 50E566D6139E38C500214433 /* CSSWrapShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 501BAAB11395114B00F7ACEB /* CSSWrapShapes.cpp */; }; 1340 1344 510184690B08602A004A825F /* CachedPage.h in Headers */ = {isa = PBXBuildFile; fileRef = 510184670B08602A004A825F /* CachedPage.h */; settings = {ATTRIBUTES = (Private, ); }; }; … … 7938 7942 508CCA4D13CF106B003151F3 /* RenderFlowThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderFlowThread.h; sourceTree = "<group>"; }; 7939 7943 508CCA4E13CF106B003151F3 /* RenderFlowThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderFlowThread.cpp; sourceTree = "<group>"; }; 7944 5097C59F13EABA7E002DE4AF /* PODArena.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PODArena.h; sourceTree = "<group>"; }; 7945 5097C5A013EABA7E002DE4AF /* PODInterval.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PODInterval.h; sourceTree = "<group>"; }; 7946 5097C5A113EABA7E002DE4AF /* PODIntervalTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PODIntervalTree.h; sourceTree = "<group>"; }; 7947 5097C5A213EABA7E002DE4AF /* PODRedBlackTree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PODRedBlackTree.h; sourceTree = "<group>"; }; 7940 7948 510184670B08602A004A825F /* CachedPage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CachedPage.h; sourceTree = "<group>"; }; 7941 7949 510184680B08602A004A825F /* CachedPage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CachedPage.cpp; sourceTree = "<group>"; }; … … 19009 19017 isa = PBXGroup; 19010 19018 children = ( 19019 5097C59F13EABA7E002DE4AF /* PODArena.h */, 19020 5097C5A013EABA7E002DE4AF /* PODInterval.h */, 19021 5097C5A113EABA7E002DE4AF /* PODIntervalTree.h */, 19022 5097C5A213EABA7E002DE4AF /* PODRedBlackTree.h */, 19011 19023 49E912A40EFAC8E6009D0CAF /* animation */, 19012 19024 FD31604012B026A300C1A359 /* audio */, … … 23355 23367 977E2E0F12F0FC9C00C13379 /* XSSAuditor.h in Headers */, 23356 23368 FD537353137B651800008DCE /* ZeroPole.h in Headers */, 23369 5097C5A313EABA7E002DE4AF /* PODArena.h in Headers */, 23370 5097C5A413EABA7E002DE4AF /* PODInterval.h in Headers */, 23371 5097C5A513EABA7E002DE4AF /* PODIntervalTree.h in Headers */, 23372 5097C5A613EABA7E002DE4AF /* PODRedBlackTree.h in Headers */, 23357 23373 ); 23358 23374 runOnlyForDeploymentPostprocessing = 0; -
trunk/Source/WebCore/platform/PODIntervalTree.h
r92363 r92610 41 41 #endif 42 42 43 template <class T, class UserData = void*> 44 class PODIntervalSearchAdapter { 45 public: 46 typedef PODInterval<T, UserData> IntervalType; 47 48 PODIntervalSearchAdapter(Vector<IntervalType>& result, const T& lowValue, const T& highValue) 49 : m_result(result) 50 , m_lowValue(lowValue) 51 , m_highValue(highValue) 52 { 53 } 54 55 const T& lowValue() const { return m_lowValue; } 56 const T& highValue() const { return m_highValue; } 57 void collectIfNeeded(const IntervalType& data) const 58 { 59 if (data.overlaps(m_lowValue, m_highValue)) 60 m_result.append(data); 61 } 62 63 private: 64 Vector<IntervalType>& m_result; 65 T m_lowValue; 66 T m_highValue; 67 }; 68 43 69 // An interval tree, which is a form of augmented red-black tree. It 44 70 // supports efficient (O(lg n)) insertion, removal and querying of … … 51 77 // this tree. 52 78 typedef PODInterval<T, UserData> IntervalType; 53 79 typedef PODIntervalSearchAdapter<T, UserData> IntervalSearchAdapterType; 80 81 PODIntervalTree(UninitializedTreeEnum unitializedTree) 82 : PODRedBlackTree<IntervalType>(unitializedTree) 83 { 84 init(); 85 } 86 54 87 PODIntervalTree() 55 88 : PODRedBlackTree<IntervalType>() … … 81 114 // Explicit dereference of "this" required because of 82 115 // inheritance rules in template classes. 83 searchForOverlapsFrom(this->root(), interval, result); 116 IntervalSearchAdapterType adapter(result, interval.low(), interval.high()); 117 searchForOverlapsFrom<IntervalSearchAdapterType>(this->root(), adapter); 118 } 119 120 template <class AdapterType> 121 void allOverlapsWithAdapter(AdapterType& adapter) const 122 { 123 // Explicit dereference of "this" required because of 124 // inheritance rules in template classes. 125 searchForOverlapsFrom<AdapterType>(this->root(), adapter); 84 126 } 85 127 … … 113 155 // interval to the result vector. The intervals are sorted by 114 156 // increasing low endpoint. 115 void searchForOverlapsFrom(IntervalNode* node, const IntervalType& interval, Vector<IntervalType>& res) const 157 template <class AdapterType> 158 void searchForOverlapsFrom(IntervalNode* node, AdapterType& adapter) const 116 159 { 117 160 if (!node) … … 126 169 // This is phrased this way to avoid the need for operator 127 170 // <= on type T. 128 && !(left->data().maxHigh() < interval.low()))129 searchForOverlapsFrom (left, interval, res);171 && !(left->data().maxHigh() < adapter.lowValue())) 172 searchForOverlapsFrom<AdapterType>(left, adapter); 130 173 131 174 // Check for overlap with current node. 132 if (node->data().overlaps(interval)) 133 res.append(node->data()); 175 adapter.collectIfNeeded(node->data()); 134 176 135 177 // See whether we need to traverse the right subtree. 136 178 // This is phrased this way to avoid the need for operator <= 137 179 // on type T. 138 if (!( interval.high() < node->data().low()))139 searchForOverlapsFrom (node->right(), interval, res);180 if (!(adapter.highValue() < node->data().low())) 181 searchForOverlapsFrom<AdapterType>(node->right(), adapter); 140 182 } 141 183 -
trunk/Source/WebCore/platform/PODRedBlackTree.h
r92363 r92610 91 91 #endif 92 92 93 enum UninitializedTreeEnum { 94 UninitializedTree 95 }; 96 93 97 template<class T> 94 98 class PODRedBlackTree { … … 102 106 }; 103 107 108 // Constructs a new red-black tree without allocating an arena. 109 // isInitialized will return false in this case. initIfNeeded can be used 110 // to init the structure. This constructor is usefull for creating 111 // lazy initialized tree. 112 PODRedBlackTree(UninitializedTreeEnum) 113 : m_root(0) 114 , m_needsFullOrderingComparisons(false) 115 #ifndef NDEBUG 116 , m_verboseDebugging(false) 117 #endif 118 { 119 } 120 104 121 // Constructs a new red-black tree, allocating temporary objects 105 122 // from a newly constructed PODArena. … … 128 145 virtual ~PODRedBlackTree() { } 129 146 147 // Clearing will delete the contents of the tree. After this call 148 // isInitialized will return false. 149 void clear() 150 { 151 m_arena = 0; 152 m_root = 0; 153 } 154 155 bool isInitialized() const 156 { 157 return m_arena; 158 } 159 160 void initIfNeeded() 161 { 162 if (!m_arena) 163 m_arena = PODArena::create(); 164 } 165 130 166 void add(const T& data) 131 167 { 168 ASSERT(isInitialized()); 132 169 Node* node = m_arena->allocateObject<Node, T>(data); 133 170 insertNode(node); … … 137 174 bool remove(const T& data) 138 175 { 176 ASSERT(isInitialized()); 139 177 Node* node = treeSearch(data); 140 178 if (node) { … … 145 183 } 146 184 147 bool contains(const T& data) const { return treeSearch(data); } 185 bool contains(const T& data) const 186 { 187 ASSERT(isInitialized()); 188 return treeSearch(data); 189 } 148 190 149 191 void visitInorder(Visitor* visitor) const 150 192 { 193 ASSERT(isInitialized()); 151 194 if (!m_root) 152 195 return; … … 156 199 int size() const 157 200 { 201 ASSERT(isInitialized()); 158 202 Counter counter; 159 203 visitInorder(&counter); … … 169 213 virtual bool checkInvariants() const 170 214 { 215 ASSERT(isInitialized()); 171 216 int blackCount; 172 217 return checkInvariantsFromNode(m_root, &blackCount); … … 178 223 void dump() const 179 224 { 180 dumpFromNode(m_root, 0); 225 if (m_arena) 226 dumpFromNode(m_root, 0); 181 227 } 182 228 -
trunk/Source/WebCore/rendering/RenderBlock.cpp
r92438 r92610 275 275 if (diff == StyleDifferenceLayout && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) { 276 276 RenderBlock* parentBlock = this; 277 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();277 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 278 278 FloatingObjectSetIterator end = floatingObjectSet.end(); 279 279 … … 1437 1437 return; 1438 1438 1439 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();1439 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1440 1440 FloatingObjectSetIterator end = floatingObjectSet.end(); 1441 1441 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 2295 2295 // in this block. Better yet would be to push extra state for the containers of other floats. 2296 2296 LayoutStateDisabler layoutStateDisabler(view()); 2297 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();2297 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2298 2298 FloatingObjectSetIterator end = floatingObjectSet.end(); 2299 2299 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 2628 2628 return; 2629 2629 2630 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();2630 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2631 2631 FloatingObjectSetIterator end = floatingObjectSet.end(); 2632 2632 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 2880 2880 clipOutPositionedObjects(paintInfo, IntPoint(cb->x(), cb->y()), cb->m_positionedObjects.get()); // FIXME: Not right for flipped writing modes. 2881 2881 if (m_floatingObjects) { 2882 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();2882 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2883 2883 FloatingObjectSetIterator end = floatingObjectSet.end(); 2884 2884 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 3191 3191 // Create the list of special objects if we don't aleady have one 3192 3192 if (!m_floatingObjects) 3193 m_floatingObjects = adoptPtr(new FloatingObjects );3193 m_floatingObjects = adoptPtr(new FloatingObjects(isHorizontalWritingMode())); 3194 3194 else { 3195 3195 // Don't insert the object again if it's already in the list 3196 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();3196 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3197 3197 FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o); 3198 3198 if (it != floatingObjectSet.end()) … … 3225 3225 newObj->m_renderer = o; 3226 3226 3227 m_floatingObjects->increaseObjectsCount(newObj->type()); 3228 m_floatingObjects->set().add(newObj); 3227 m_floatingObjects->add(newObj); 3229 3228 3230 3229 return newObj; … … 3234 3233 { 3235 3234 if (m_floatingObjects) { 3236 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();3237 FloatingObjectSet ::iterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o);3235 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3236 FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o); 3238 3237 if (it != floatingObjectSet.end()) { 3239 3238 FloatingObject* r = *it; … … 3260 3259 markLinesDirtyInBlockRange(0, logicalBottom); 3261 3260 } 3262 m_floatingObjects->decreaseObjectsCount(r->type()); 3263 floatingObjectSet.remove(it); 3261 m_floatingObjects->remove(r); 3264 3262 ASSERT(!r->m_originatingLine); 3265 3263 delete r; … … 3273 3271 return; 3274 3272 3275 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();3273 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3276 3274 FloatingObject* curr = floatingObjectSet.last(); 3277 3275 while (curr != lastFloat && (!curr->isPlaced() || logicalTopForFloat(curr) >= logicalOffset)) { 3278 m_floatingObjects->decreaseObjectsCount(curr->type()); 3279 floatingObjectSet.removeLast(); 3276 m_floatingObjects->remove(curr); 3280 3277 ASSERT(!curr->m_originatingLine); 3281 3278 delete curr; … … 3289 3286 return false; 3290 3287 3291 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();3288 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3292 3289 if (floatingObjectSet.isEmpty()) 3293 3290 return false; … … 3404 3401 setLogicalHeightForFloat(floatingObject, logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox)); 3405 3402 3406 floatingObject->setIsPlaced();3403 m_floatingObjects->addPlacedObject(floatingObject); 3407 3404 3408 3405 // If the child moved, we have to repaint it. … … 3506 3503 #endif 3507 3504 3508 // FIXME: The logicalLeftOffsetForLine/logicalRightOffsetForLine functions are very slow if there are many floats 3509 // present. We need to add a structure to floating objects to represent "lines" of floats. Then instead of checking 3510 // each float individually, we'd just walk backwards through the "lines" and stop when we hit a line that is fully above 3511 // the vertical offset that we'd like to check. Computing the "lines" would be rather complicated, but could replace the left 3512 // objects and right objects count hack that is currently used here. 3505 template <RenderBlock::FloatingObject::Type FloatTypeValue> 3506 inline void RenderBlock::FloatIntervalSearchAdapter<FloatTypeValue>::collectIfNeeded(const IntervalType& interval) const 3507 { 3508 const FloatingObject* r = interval.data(); 3509 if (r->type() == FloatTypeValue && interval.low() <= m_value && m_value < interval.high()) { 3510 // All the objects returned from the tree should be already placed. 3511 ASSERT(r->isPlaced() && m_renderer->logicalTopForFloat(r) <= m_value && m_renderer->logicalBottomForFloat(r) > m_value); 3512 3513 if (FloatTypeValue == FloatingObject::FloatLeft 3514 && m_renderer->logicalRightForFloat(r) > m_offset) { 3515 m_offset = m_renderer->logicalRightForFloat(r); 3516 if (m_heightRemaining) 3517 *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_value; 3518 } 3519 3520 if (FloatTypeValue == FloatingObject::FloatRight 3521 && m_renderer->logicalLeftForFloat(r) < m_offset) { 3522 m_offset = m_renderer->logicalLeftForFloat(r); 3523 if (m_heightRemaining) 3524 *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_value; 3525 } 3526 } 3527 } 3528 3513 3529 LayoutUnit RenderBlock::logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining) const 3514 3530 { … … 3518 3534 *heightRemaining = 1; 3519 3535 3520 // We know the list is non-empty, since we have "left" objects to search for. 3521 // Therefore we can assume that begin != end, and that we can do at least one 3522 // decrement. 3523 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3524 FloatingObjectSetIterator begin = floatingObjectSet.begin(); 3525 FloatingObjectSetIterator it = floatingObjectSet.end(); 3526 do { 3527 --it; 3528 FloatingObject* r = *it; 3529 if (r->isPlaced() && logicalTopForFloat(r) <= logicalTop && logicalBottomForFloat(r) > logicalTop 3530 && r->type() == FloatingObject::FloatLeft 3531 && logicalRightForFloat(r) > left) { 3532 left = max(left, logicalRightForFloat(r)); 3533 if (heightRemaining) 3534 *heightRemaining = logicalBottomForFloat(r) - logicalTop; 3535 } 3536 } while (it != begin); 3536 FloatIntervalSearchAdapter<FloatingObject::FloatLeft> adapter(this, logicalTop, left, heightRemaining); 3537 m_floatingObjects->placedFloatsTree().allOverlapsWithAdapter(adapter); 3537 3538 } 3538 3539 … … 3554 3555 if (heightRemaining) 3555 3556 *heightRemaining = 1; 3556 3557 // We know the list is non-empty, since we have "right" objects to search for. 3558 // Therefore we can assume that begin != end, and that we can do at least one 3559 // decrement. 3560 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3561 FloatingObjectSetIterator begin = floatingObjectSet.begin(); 3562 FloatingObjectSetIterator it = floatingObjectSet.end(); 3563 do { 3564 --it; 3565 FloatingObject* r = *it; 3566 if (r->isPlaced() && logicalTopForFloat(r) <= logicalTop && logicalBottomForFloat(r) > logicalTop 3567 && r->type() == FloatingObject::FloatRight 3568 && logicalLeftForFloat(r) < right) { 3569 right = min(right, logicalLeftForFloat(r)); 3570 if (heightRemaining) 3571 *heightRemaining = logicalBottomForFloat(r) - logicalTop; 3572 } 3573 } while (it != begin); 3557 3558 FloatIntervalSearchAdapter<FloatingObject::FloatRight> adapter(this, logicalTop, right, heightRemaining); 3559 m_floatingObjects->placedFloatsTree().allOverlapsWithAdapter(adapter); 3574 3560 } 3575 3561 … … 3596 3582 3597 3583 int bottom = INT_MAX; 3598 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();3584 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3599 3585 FloatingObjectSetIterator end = floatingObjectSet.end(); 3600 3586 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 3613 3599 return 0; 3614 3600 int lowestFloatBottom = 0; 3615 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();3601 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3616 3602 FloatingObjectSetIterator end = floatingObjectSet.end(); 3617 3603 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 3661 3647 setLogicalTopForFloat(floatingObject, logicalTopForChild(positionedObject) - marginBeforeForChild(positionedObject)); 3662 3648 setLogicalHeightForFloat(floatingObject, logicalHeightForChild(positionedObject) + marginBeforeForChild(positionedObject) + marginAfterForChild(positionedObject)); 3663 floatingObject->setIsPlaced(true); 3649 3650 m_floatingObjects->addPlacedObject(floatingObject); 3664 3651 3665 3652 m_hasPositionedFloats = true; … … 3669 3656 void RenderBlock::clearFloats(BlockLayoutPass layoutPass) 3670 3657 { 3658 if (m_floatingObjects) 3659 m_floatingObjects->setHorizontalWritingMode(isHorizontalWritingMode()); 3660 3671 3661 // Clear our positioned floats boolean. 3672 3662 m_hasPositionedFloats = false; … … 3687 3677 3688 3678 if (m_floatingObjects) { 3689 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();3679 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3690 3680 if (childrenInline()) { 3691 FloatingObjectSet ::iterator end = floatingObjectSet.end();3692 for (FloatingObjectSet ::iterator it = floatingObjectSet.begin(); it != end; ++it) {3681 FloatingObjectSetIterator end = floatingObjectSet.end(); 3682 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { 3693 3683 FloatingObject* f = *it; 3694 3684 floatMap.add(f->m_renderer, f); … … 3742 3732 int changeLogicalBottom = numeric_limits<int>::min(); 3743 3733 if (m_floatingObjects) { 3744 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();3734 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3745 3735 FloatingObjectSetIterator end = floatingObjectSet.end(); 3746 3736 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 3824 3814 // We create the floating object list lazily. 3825 3815 if (!m_floatingObjects) 3826 m_floatingObjects = adoptPtr(new FloatingObjects); 3827 3828 m_floatingObjects->increaseObjectsCount(floatingObj->type()); 3829 m_floatingObjects->set().add(floatingObj); 3816 m_floatingObjects = adoptPtr(new FloatingObjects(isHorizontalWritingMode())); 3817 3818 m_floatingObjects->add(floatingObj); 3830 3819 } 3831 3820 } else { … … 3854 3843 return false; 3855 3844 3856 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();3845 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3857 3846 FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(renderer); 3858 3847 if (it == floatingObjectSet.end()) … … 3870 3859 logicalLeftOffset += (isHorizontalWritingMode() ? marginLeft() : marginTop()); 3871 3860 3872 FloatingObjectSet& prevSet = prev->m_floatingObjects->set();3861 const FloatingObjectSet& prevSet = prev->m_floatingObjects->set(); 3873 3862 FloatingObjectSetIterator prevEnd = prevSet.end(); 3874 3863 for (FloatingObjectSetIterator prevIt = prevSet.begin(); prevIt != prevEnd; ++prevIt) { … … 3898 3887 // We create the floating object list lazily. 3899 3888 if (!m_floatingObjects) 3900 m_floatingObjects = adoptPtr(new FloatingObjects); 3901 m_floatingObjects->increaseObjectsCount(floatingObj->type()); 3902 m_floatingObjects->set().add(floatingObj); 3889 m_floatingObjects = adoptPtr(new FloatingObjects(isHorizontalWritingMode())); 3890 m_floatingObjects->add(floatingObj); 3903 3891 } 3904 3892 } … … 3941 3929 void RenderBlock::markSiblingsWithFloatsForLayout() 3942 3930 { 3943 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();3931 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 3944 3932 FloatingObjectSetIterator end = floatingObjectSet.end(); 3945 3933 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 4093 4081 } 4094 4082 4095 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();4083 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 4096 4084 FloatingObjectSetIterator begin = floatingObjectSet.begin(); 4097 4085 for (FloatingObjectSetIterator it = floatingObjectSet.end(); it != begin;) { … … 5700 5688 5701 5689 if (m_floatingObjects) { 5702 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();5690 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 5703 5691 FloatingObjectSetIterator end = floatingObjectSet.end(); 5704 5692 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 6444 6432 { 6445 6433 m_set.clear(); 6434 m_placedFloatsTree.clear(); 6446 6435 m_leftObjectsCount = 0; 6447 6436 m_rightObjectsCount = 0; … … 6469 6458 } 6470 6459 6460 inline RenderBlock::FloatingObjectInterval RenderBlock::FloatingObjects::intervalForFloatingObject(FloatingObject* floatingObject) 6461 { 6462 if (m_horizontalWritingMode) 6463 return RenderBlock::FloatingObjectInterval(floatingObject->y(), floatingObject->maxY(), floatingObject); 6464 return RenderBlock::FloatingObjectInterval(floatingObject->x(), floatingObject->maxX(), floatingObject); 6465 } 6466 6467 void RenderBlock::FloatingObjects::addPlacedObject(FloatingObject* floatingObject) 6468 { 6469 ASSERT(!floatingObject->isInPlacedTree()); 6470 6471 floatingObject->setIsPlaced(true); 6472 if (m_placedFloatsTree.isInitialized()) 6473 m_placedFloatsTree.add(intervalForFloatingObject(floatingObject)); 6474 6475 #ifndef NDEBUG 6476 floatingObject->setIsInPlacedTree(true); 6477 #endif 6478 } 6479 6480 void RenderBlock::FloatingObjects::removePlacedObject(FloatingObject* floatingObject) 6481 { 6482 ASSERT(floatingObject->isPlaced() && floatingObject->isInPlacedTree()); 6483 6484 if (m_placedFloatsTree.isInitialized()) { 6485 bool removed = m_placedFloatsTree.remove(intervalForFloatingObject(floatingObject)); 6486 ASSERT_UNUSED(removed, removed); 6487 } 6488 6489 floatingObject->setIsPlaced(false); 6490 #ifndef NDEBUG 6491 floatingObject->setIsInPlacedTree(false); 6492 #endif 6493 } 6494 6495 inline void RenderBlock::FloatingObjects::add(FloatingObject* floatingObject) 6496 { 6497 increaseObjectsCount(floatingObject->type()); 6498 m_set.add(floatingObject); 6499 if (floatingObject->isPlaced()) 6500 addPlacedObject(floatingObject); 6501 } 6502 6503 inline void RenderBlock::FloatingObjects::remove(FloatingObject* floatingObject) 6504 { 6505 decreaseObjectsCount(floatingObject->type()); 6506 m_set.remove(floatingObject); 6507 ASSERT(floatingObject->isPlaced() || !floatingObject->isInPlacedTree()); 6508 if (floatingObject->isPlaced()) 6509 removePlacedObject(floatingObject); 6510 } 6511 6512 void RenderBlock::FloatingObjects::computePlacedFloatsTree() 6513 { 6514 ASSERT(!m_placedFloatsTree.isInitialized()); 6515 if (m_set.isEmpty()) 6516 return; 6517 m_placedFloatsTree.initIfNeeded(); 6518 FloatingObjectSetIterator it = m_set.begin(); 6519 FloatingObjectSetIterator end = m_set.end(); 6520 for (; it != end; ++it) { 6521 FloatingObject* floatingObject = *it; 6522 if (floatingObject->isPlaced()) 6523 m_placedFloatsTree.add(intervalForFloatingObject(floatingObject)); 6524 } 6525 } 6526 6471 6527 TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags) 6472 6528 { … … 6503 6559 } 6504 6560 6561 // These helpers are only used by the PODIntervalTree for debugging purposes. 6562 String ValueToString<int>::string(const int value) 6563 { 6564 return String::number(value); 6565 } 6566 6567 String ValueToString<RenderBlock::FloatingObject*>::string(const RenderBlock::FloatingObject* floatingObject) 6568 { 6569 return String::format("%p (%dx%d %dx%d)", floatingObject, floatingObject->x(), floatingObject->y(), floatingObject->maxX(), floatingObject->maxY()); 6570 } 6571 6505 6572 #endif 6506 6573 -
trunk/Source/WebCore/rendering/RenderBlock.h
r92438 r92610 25 25 26 26 #include "GapRects.h" 27 #include "PODIntervalTree.h" 27 28 #include "RenderBox.h" 28 29 #include "RenderLineBoxList.h" … … 68 69 public: 69 70 friend class LineLayoutState; 71 #ifndef NDEBUG 72 // Used by the PODIntervalTree for debugging the FloatingObject. 73 template <class> friend struct ValueToString; 74 #endif 75 70 76 RenderBlock(Node*); 71 77 virtual ~RenderBlock(); … … 423 429 , m_isDescendant(false) 424 430 , m_isPlaced(false) 431 #ifndef NDEBUG 432 , m_isInPlacedTree(false) 433 #endif 425 434 { 426 435 ASSERT(type != NoFloat); … … 442 451 , m_isDescendant(false) 443 452 , m_isPlaced(true) 453 #ifndef NDEBUG 454 , m_isInPlacedTree(false) 455 #endif 444 456 { 445 457 } … … 458 470 int height() const { return m_frameRect.height(); } 459 471 460 void setX(int x) { m_frameRect.setX(x); }461 void setY(int y) { m_frameRect.setY(y); }462 void setWidth(int width) { m_frameRect.setWidth(width); }463 void setHeight(int height) { m_frameRect.setHeight(height); }472 void setX(int x) { ASSERT(!isInPlacedTree()); m_frameRect.setX(x); } 473 void setY(int y) { ASSERT(!isInPlacedTree()); m_frameRect.setY(y); } 474 void setWidth(int width) { ASSERT(!isInPlacedTree()); m_frameRect.setWidth(width); } 475 void setHeight(int height) { ASSERT(!isInPlacedTree()); m_frameRect.setHeight(height); } 464 476 465 477 const IntRect& frameRect() const { ASSERT(isPlaced()); return m_frameRect; } 466 void setFrameRect(const IntRect& frameRect) { m_frameRect = frameRect; } 478 void setFrameRect(const IntRect& frameRect) { ASSERT(!isInPlacedTree()); m_frameRect = frameRect; } 479 480 #ifndef NDEBUG 481 bool isInPlacedTree() const { return m_isInPlacedTree; } 482 void setIsInPlacedTree(bool value) { m_isInPlacedTree = value; } 483 #endif 467 484 468 485 RenderBox* m_renderer; … … 474 491 bool m_isDescendant : 1; 475 492 bool m_isPlaced : 1; 493 #ifndef NDEBUG 494 bool m_isInPlacedTree : 1; 495 #endif 476 496 }; 477 497 … … 800 820 typedef ListHashSet<FloatingObject*, 4, FloatingObjectHashFunctions> FloatingObjectSet; 801 821 typedef FloatingObjectSet::const_iterator FloatingObjectSetIterator; 822 typedef PODInterval<LayoutUnit, FloatingObject*> FloatingObjectInterval; 823 typedef PODIntervalTree<LayoutUnit, FloatingObject*> FloatingObjectTree; 824 825 template <FloatingObject::Type FloatTypeValue> 826 class FloatIntervalSearchAdapter { 827 public: 828 typedef FloatingObjectInterval IntervalType; 829 830 FloatIntervalSearchAdapter(const RenderBlock* renderer, LayoutUnit value, LayoutUnit& offset, LayoutUnit* heightRemaining) 831 : m_renderer(renderer) 832 , m_value(value) 833 , m_offset(offset) 834 , m_heightRemaining(heightRemaining) 835 { 836 } 837 838 inline LayoutUnit lowValue() const { return m_value; } 839 inline LayoutUnit highValue() const { return m_value; } 840 void collectIfNeeded(const IntervalType&) const; 841 842 private: 843 const RenderBlock* m_renderer; 844 LayoutUnit m_value; 845 LayoutUnit& m_offset; 846 LayoutUnit* m_heightRemaining; 847 }; 848 802 849 class FloatingObjects { 803 850 public: 804 FloatingObjects() 805 : m_leftObjectsCount(0) 851 FloatingObjects(bool horizontalWritingMode) 852 : m_placedFloatsTree(UninitializedTree) 853 , m_leftObjectsCount(0) 806 854 , m_rightObjectsCount(0) 807 855 , m_positionedObjectsCount(0) 856 , m_horizontalWritingMode(horizontalWritingMode) 808 857 { 809 858 } 810 859 811 860 void clear(); 812 void increaseObjectsCount(FloatingObject::Type); 813 void decreaseObjectsCount(FloatingObject::Type); 861 void add(FloatingObject*); 862 void remove(FloatingObject*); 863 void addPlacedObject(FloatingObject*); 864 void removePlacedObject(FloatingObject*); 865 void setHorizontalWritingMode(bool b = true) { m_horizontalWritingMode = b; } 866 814 867 bool hasLeftObjects() const { return m_leftObjectsCount > 0; } 815 868 bool hasRightObjects() const { return m_rightObjectsCount > 0; } 816 869 bool hasPositionedObjects() const { return m_positionedObjectsCount > 0; } 817 FloatingObjectSet& set() { return m_set; } 818 870 const FloatingObjectSet& set() const { return m_set; } 871 const FloatingObjectTree& placedFloatsTree() 872 { 873 computePlacedFloatsTreeIfNeeded(); 874 return m_placedFloatsTree; 875 } 819 876 private: 877 void computePlacedFloatsTree(); 878 inline void computePlacedFloatsTreeIfNeeded() 879 { 880 if (!m_placedFloatsTree.isInitialized()) 881 computePlacedFloatsTree(); 882 } 883 void increaseObjectsCount(FloatingObject::Type); 884 void decreaseObjectsCount(FloatingObject::Type); 885 FloatingObjectInterval intervalForFloatingObject(FloatingObject*); 886 820 887 FloatingObjectSet m_set; 888 FloatingObjectTree m_placedFloatsTree; 821 889 unsigned m_leftObjectsCount; 822 890 unsigned m_rightObjectsCount; 823 891 unsigned m_positionedObjectsCount; 892 bool m_horizontalWritingMode; 824 893 }; 825 894 OwnPtr<FloatingObjects> m_floatingObjects; … … 896 965 void toRenderBlock(const RenderBlock*); 897 966 967 #ifndef NDEBUG 968 // These structures are used by PODIntervalTree for debugging purposes. 969 template <> struct ValueToString<int> { 970 static String string(const int value); 971 }; 972 template<> struct ValueToString<RenderBlock::FloatingObject*> { 973 static String string(const RenderBlock::FloatingObject*); 974 }; 975 #endif 976 898 977 } // namespace WebCore 899 978 -
trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp
r92207 r92610 1092 1092 1093 1093 if (m_floatingObjects && lastRootBox()) { 1094 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();1094 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1095 1095 FloatingObjectSetIterator it = floatingObjectSet.begin(); 1096 1096 FloatingObjectSetIterator end = floatingObjectSet.end(); … … 1173 1173 } 1174 1174 1175 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();1175 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1176 1176 FloatingObjectSetIterator it = floatingObjectSet.begin(); 1177 1177 FloatingObjectSetIterator end = floatingObjectSet.end(); … … 1492 1492 int logicalBottom = lastLine->blockLogicalHeight() + abs(delta); 1493 1493 1494 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();1494 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1495 1495 FloatingObjectSetIterator end = floatingObjectSet.end(); 1496 1496 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 1529 1529 int logicalBottom = lastLine->blockLogicalHeight() + abs(delta); 1530 1530 1531 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();1531 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 1532 1532 FloatingObjectSetIterator end = floatingObjectSet.end(); 1533 1533 for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) { … … 2551 2551 return true; 2552 2552 2553 FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();2553 const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set(); 2554 2554 ASSERT(floatingObjectSet.last() == newFloat); 2555 2555 … … 2576 2576 toRenderBlock(o)->setChildNeedsLayout(true, false); 2577 2577 o->layoutIfNeeded(); 2578 m_floatingObjects->removePlacedObject(f); 2578 2579 setLogicalTopForFloat(f, logicalTopForFloat(f) + f->m_paginationStrut); 2580 m_floatingObjects->addPlacedObject(f); 2579 2581 } 2580 2582 }
Note: See TracChangeset
for help on using the changeset viewer.