Changeset 228682 in webkit
- Timestamp:
- Feb 19, 2018 7:16:45 AM (6 years ago)
- Location:
- releases/WebKitGTK/webkit-2.20/Source/WebCore
- Files:
-
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
releases/WebKitGTK/webkit-2.20/Source/WebCore/ChangeLog
r228681 r228682 1 2018-02-09 Zalan Bujtas <zalan@apple.com> 2 3 [RenderTreeBuilder] Move multicolumn spanner mutation logic to RenderTreeBuilder 4 https://bugs.webkit.org/show_bug.cgi?id=182627 5 <rdar://problem/37367284> 6 7 Reviewed by Antti Koivisto. 8 9 Move spanner triggered mutation logic to RenderTreeBuilder. 10 11 No change in functionality. 12 13 * rendering/RenderFragmentedFlow.h: 14 * rendering/RenderMultiColumnFlow.cpp: 15 (WebCore::RenderMultiColumnFlow::isColumnSpanningDescendant const): 16 (WebCore::findSetRendering): Deleted. 17 (WebCore::isValidColumnSpanner): Deleted. 18 (WebCore::spannerPlacehoderCandidate): Deleted. 19 (WebCore::RenderMultiColumnFlow::processPossibleSpannerDescendant): Deleted. 20 (WebCore::RenderMultiColumnFlow::fragmentedFlowDescendantInserted): Deleted. 21 * rendering/RenderMultiColumnFlow.h: 22 * rendering/RenderObject.cpp: 23 (WebCore::RenderObject::insertedIntoTree): 24 * rendering/updating/RenderTreeBuilder.cpp: 25 (WebCore::RenderTreeBuilder::multiColumnDescendantInserted): 26 * rendering/updating/RenderTreeBuilder.h: 27 * rendering/updating/RenderTreeBuilderMultiColumn.cpp: 28 (WebCore::findSetRendering): 29 (WebCore::spannerPlacehoderCandidate): 30 (WebCore::isValidColumnSpanner): 31 (WebCore::RenderTreeBuilder::MultiColumn::multiColumnDescendantInserted): 32 (WebCore::RenderTreeBuilder::MultiColumn::processPossibleSpannerDescendant): 33 * rendering/updating/RenderTreeBuilderMultiColumn.h: 34 1 35 2018-02-09 Javier Fernandez <jfernandez@igalia.com> 2 36 -
releases/WebKitGTK/webkit-2.20/Source/WebCore/rendering/RenderFragmentedFlow.h
r227903 r228682 87 87 virtual bool singleFragmentHasUniformLogicalHeight() const { return true; } 88 88 89 // Called when a descendant of the flow thread has been inserted.90 virtual void fragmentedFlowDescendantInserted(RenderObject&) { }91 89 // Called when a sibling or descendant of the flow thread is about to be removed. 92 90 virtual void fragmentedFlowRelativeWillBeRemoved(RenderObject&) { } -
releases/WebKitGTK/webkit-2.20/Source/WebCore/rendering/RenderMultiColumnFlow.cpp
r227977 r228682 41 41 WTF_MAKE_ISO_ALLOCATED_IMPL(RenderMultiColumnFlow); 42 42 43 bool RenderMultiColumnFlow::gShiftingSpanner = false;44 45 43 RenderMultiColumnFlow::RenderMultiColumnFlow(Document& document, RenderStyle&& style) 46 44 : RenderFragmentedFlow(document, WTFMove(style)) … … 136 134 } 137 135 138 static RenderMultiColumnSet* findSetRendering(const RenderMultiColumnFlow& fragmentedFlow, const RenderObject& renderer) 139 { 140 // Find the set inside which the specified renderer would be rendered. 141 for (auto* multicolSet = fragmentedFlow.firstMultiColumnSet(); multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) { 142 if (multicolSet->containsRendererInFragmentedFlow(renderer)) 143 return multicolSet; 144 } 145 return nullptr; 136 bool RenderMultiColumnFlow::isColumnSpanningDescendant(const RenderBox& descendantBox) const 137 { 138 return descendantBox.style().columnSpan() == ColumnSpanAll; 146 139 } 147 140 … … 168 161 } 169 162 170 bool RenderMultiColumnFlow::isColumnSpanningDescendant(const RenderBox& descendantBox) const171 {172 return descendantBox.style().columnSpan() == ColumnSpanAll;173 }174 175 static bool isValidColumnSpanner(const RenderMultiColumnFlow& fragmentedFlow, const RenderObject& descendant)176 {177 // We assume that we're inside the flow thread. This function is not to be called otherwise.178 ASSERT(descendant.isDescendantOf(&fragmentedFlow));179 // First make sure that the renderer itself has the right properties for becoming a spanner.180 if (!is<RenderBox>(descendant))181 return false;182 183 auto& descendantBox = downcast<RenderBox>(descendant);184 if (descendantBox.isFloatingOrOutOfFlowPositioned())185 return false;186 187 if (!fragmentedFlow.isColumnSpanningDescendant(descendantBox))188 return false;189 190 auto* parent = descendantBox.parent();191 if (!is<RenderBlockFlow>(*parent) || parent->childrenInline()) {192 // Needs to be block-level.193 return false;194 }195 196 // We need to have the flow thread as the containing block. A spanner cannot break out of the flow thread.197 auto* enclosingFragmentedFlow = descendantBox.enclosingFragmentedFlow();198 if (enclosingFragmentedFlow != &fragmentedFlow)199 return false;200 201 // This looks like a spanner, but if we're inside something unbreakable, it's not to be treated as one.202 for (auto* ancestor = descendantBox.containingBlock(); ancestor; ancestor = ancestor->containingBlock()) {203 if (is<RenderView>(*ancestor))204 return false;205 if (is<RenderFragmentedFlow>(*ancestor)) {206 // Don't allow any intervening non-multicol fragmentation contexts. The spec doesn't say207 // anything about disallowing this, but it's just going to be too complicated to208 // implement (not to mention specify behavior).209 return ancestor == &fragmentedFlow;210 }211 // This ancestor (descendent of the fragmentedFlow) will create columns later. The spanner belongs to it.212 if (is<RenderBlockFlow>(*ancestor) && downcast<RenderBlockFlow>(*ancestor).willCreateColumns())213 return false;214 ASSERT(ancestor->style().columnSpan() != ColumnSpanAll || !isValidColumnSpanner(fragmentedFlow, *ancestor));215 if (ancestor->isUnsplittableForPagination())216 return false;217 }218 ASSERT_NOT_REACHED();219 return false;220 }221 222 static RenderObject* spannerPlacehoderCandidate(const RenderObject& renderer, const RenderMultiColumnFlow& stayWithin)223 {224 // Spanner candidate is a next sibling/ancestor's next child within the flow thread and225 // it is in the same inflow/out-of-flow layout context.226 if (renderer.isOutOfFlowPositioned())227 return nullptr;228 229 ASSERT(renderer.isDescendantOf(&stayWithin));230 auto* current = &renderer;231 while (true) {232 // Skip to the first in-flow sibling.233 auto* nextSibling = current->nextSibling();234 while (nextSibling && nextSibling->isOutOfFlowPositioned())235 nextSibling = nextSibling->nextSibling();236 if (nextSibling)237 return nextSibling;238 // No sibling candidate, jump to the parent and check its siblings.239 current = current->parent();240 if (!current || current == &stayWithin || current->isOutOfFlowPositioned())241 return nullptr;242 }243 return nullptr;244 }245 246 RenderObject* RenderMultiColumnFlow::processPossibleSpannerDescendant(RenderObject*& subtreeRoot, RenderObject& descendant)247 {248 RenderBlockFlow* multicolContainer = multiColumnBlockFlow();249 RenderObject* nextRendererInFragmentedFlow = spannerPlacehoderCandidate(descendant, *this);250 RenderObject* insertBeforeMulticolChild = nullptr;251 RenderObject* nextDescendant = &descendant;252 253 if (isValidColumnSpanner(*this, descendant)) {254 // This is a spanner (column-span:all). Such renderers are moved from where they would255 // otherwise occur in the render tree to becoming a direct child of the multicol container,256 // so that they live among the column sets. This simplifies the layout implementation, and257 // basically just relies on regular block layout done by the RenderBlockFlow that258 // establishes the multicol container.259 RenderBlockFlow* container = downcast<RenderBlockFlow>(descendant.parent());260 RenderMultiColumnSet* setToSplit = nullptr;261 if (nextRendererInFragmentedFlow) {262 setToSplit = findSetRendering(*this, descendant);263 if (setToSplit) {264 setToSplit->setNeedsLayout();265 insertBeforeMulticolChild = setToSplit->nextSibling();266 }267 }268 // Moving a spanner's renderer so that it becomes a sibling of the column sets requires us269 // to insert an anonymous placeholder in the tree where the spanner's renderer otherwise270 // would have been. This is needed for a two reasons: We need a way of separating inline271 // content before and after the spanner, so that it becomes separate line boxes. Secondly,272 // this placeholder serves as a break point for column sets, so that, when encountered, we273 // end flowing one column set and move to the next one.274 auto newPlaceholder = RenderMultiColumnSpannerPlaceholder::createAnonymous(*this, downcast<RenderBox>(descendant), container->style());275 auto& placeholder = *newPlaceholder;276 RenderTreeBuilder::current()->insertChild(*container, WTFMove(newPlaceholder), descendant.nextSibling());277 auto takenDescendant = container->takeChild(*RenderTreeBuilder::current(), descendant);278 279 // This is a guard to stop an ancestor flow thread from processing the spanner.280 gShiftingSpanner = true;281 RenderTreeBuilder::current()->insertChildToRenderBlock(*multicolContainer, WTFMove(takenDescendant), insertBeforeMulticolChild);282 gShiftingSpanner = false;283 284 // The spanner has now been moved out from the flow thread, but we don't want to285 // examine its children anyway. They are all part of the spanner and shouldn't trigger286 // creation of column sets or anything like that. Continue at its original position in287 // the tree, i.e. where the placeholder was just put.288 if (subtreeRoot == &descendant)289 subtreeRoot = &placeholder;290 nextDescendant = &placeholder;291 } else {292 // This is regular multicol content, i.e. not part of a spanner.293 if (is<RenderMultiColumnSpannerPlaceholder>(nextRendererInFragmentedFlow)) {294 // Inserted right before a spanner. Is there a set for us there?295 RenderMultiColumnSpannerPlaceholder& placeholder = downcast<RenderMultiColumnSpannerPlaceholder>(*nextRendererInFragmentedFlow);296 if (RenderObject* previous = placeholder.spanner()->previousSibling()) {297 if (is<RenderMultiColumnSet>(*previous))298 return nextDescendant; // There's already a set there. Nothing to do.299 }300 insertBeforeMulticolChild = placeholder.spanner();301 } else if (RenderMultiColumnSet* lastSet = lastMultiColumnSet()) {302 // This child is not an immediate predecessor of a spanner, which means that if this303 // child precedes a spanner at all, there has to be a column set created for us there304 // already. If it doesn't precede any spanner at all, on the other hand, we need a305 // column set at the end of the multicol container. We don't really check here if the306 // child inserted precedes any spanner or not (as that's an expensive operation). Just307 // make sure we have a column set at the end. It's no big deal if it remains unused.308 if (!lastSet->nextSibling())309 return nextDescendant;310 }311 }312 // Need to create a new column set when there's no set already created. We also always insert313 // another column set after a spanner. Even if it turns out that there are no renderers314 // following the spanner, there may be bottom margins there, which take up space.315 auto newSet = createMultiColumnSet(RenderStyle::createAnonymousStyleWithDisplay(multicolContainer->style(), BLOCK));316 newSet->initializeStyle();317 auto& set = *newSet;318 RenderTreeBuilder::current()->insertChildToRenderBlock(*multicolContainer, WTFMove(newSet), insertBeforeMulticolChild);319 invalidateFragments();320 321 // We cannot handle immediate column set siblings at the moment (and there's no need for322 // it, either). There has to be at least one spanner separating them.323 ASSERT_UNUSED(set, !previousColumnSetOrSpannerSiblingOf(&set) || !previousColumnSetOrSpannerSiblingOf(&set)->isRenderMultiColumnSet());324 ASSERT(!nextColumnSetOrSpannerSiblingOf(&set) || !nextColumnSetOrSpannerSiblingOf(&set)->isRenderMultiColumnSet());325 326 return nextDescendant;327 }328 329 163 RenderPtr<RenderMultiColumnSet> RenderMultiColumnFlow::createMultiColumnSet(RenderStyle&& style) 330 164 { 331 165 return createRenderer<RenderMultiColumnSet>(*this, WTFMove(style)); 332 }333 334 void RenderMultiColumnFlow::fragmentedFlowDescendantInserted(RenderObject& newDescendant)335 {336 if (gShiftingSpanner || newDescendant.isInFlowRenderFragmentedFlow())337 return;338 339 auto* subtreeRoot = &newDescendant;340 auto* descendant = subtreeRoot;341 while (descendant) {342 // Skip nested multicolumn flows.343 if (is<RenderMultiColumnFlow>(*descendant)) {344 descendant = descendant->nextSibling();345 continue;346 }347 if (is<RenderMultiColumnSpannerPlaceholder>(*descendant)) {348 // A spanner's placeholder has been inserted. The actual spanner renderer is moved from349 // where it would otherwise occur (if it weren't a spanner) to becoming a sibling of the350 // column sets.351 RenderMultiColumnSpannerPlaceholder& placeholder = downcast<RenderMultiColumnSpannerPlaceholder>(*descendant);352 ASSERT(!spannerMap().get(placeholder.spanner()));353 spannerMap().add(placeholder.spanner(), makeWeakPtr(downcast<RenderMultiColumnSpannerPlaceholder>(descendant)));354 ASSERT(!placeholder.firstChild()); // There should be no children here, but if there are, we ought to skip them.355 } else356 descendant = processPossibleSpannerDescendant(subtreeRoot, *descendant);357 if (descendant)358 descendant = descendant->nextInPreOrder(subtreeRoot);359 }360 166 } 361 167 -
releases/WebKitGTK/webkit-2.20/Source/WebCore/rendering/RenderMultiColumnFlow.h
r227903 r228682 101 101 virtual bool isColumnSpanningDescendant(const RenderBox&) const; 102 102 103 protected:104 103 virtual RenderPtr<RenderMultiColumnSet> createMultiColumnSet(RenderStyle&&); 105 104 … … 109 108 void addFragmentToThread(RenderFragmentContainer*) override; 110 109 void willBeRemovedFromTree() override; 111 void fragmentedFlowDescendantInserted(RenderObject&) override;112 110 void fragmentedFlowRelativeWillBeRemoved(RenderObject&) override; 113 111 void fragmentedFlowDescendantBoxLaidOut(RenderBox*) override; … … 122 120 123 121 void handleSpannerRemoval(RenderObject& spanner); 124 RenderObject* processPossibleSpannerDescendant(RenderObject*& subtreeRoot, RenderObject& descendant);125 122 126 123 private: … … 142 139 bool m_progressionIsInline; 143 140 bool m_progressionIsReversed; 144 145 static bool gShiftingSpanner;146 141 }; 147 142 -
releases/WebKitGTK/webkit-2.20/Source/WebCore/rendering/RenderObject.cpp
r228655 r228682 1460 1460 parent()->dirtyLinesFromChangedChild(*this); 1461 1461 1462 if (RenderFragmentedFlow* fragmentedFlow = enclosingFragmentedFlow()) 1463 fragmentedFlow->fragmentedFlowDescendantInserted(*this); 1462 auto* fragmentedFlow = enclosingFragmentedFlow(); 1463 if (is<RenderMultiColumnFlow>(fragmentedFlow)) 1464 RenderTreeBuilder::current()->multiColumnDescendantInserted(downcast<RenderMultiColumnFlow>(*fragmentedFlow), *this); 1464 1465 } 1465 1466 -
releases/WebKitGTK/webkit-2.20/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp
r228668 r228682 353 353 } 354 354 355 void RenderTreeBuilder::multiColumnDescendantInserted(RenderMultiColumnFlow& flow, RenderObject& newDescendant) 356 { 357 multiColumnBuilder().multiColumnDescendantInserted(flow, newDescendant); 358 } 359 355 360 static bool isAnonymousAndSafeToDelete(RenderElement& element) 356 361 { -
releases/WebKitGTK/webkit-2.20/Source/WebCore/rendering/updating/RenderTreeBuilder.h
r228665 r228682 80 80 RenderObject* resolveMovedChildForMultiColumnFlow(RenderFragmentedFlow& enclosingFragmentedFlow, RenderObject* beforeChild); 81 81 void removeFromParentAndDestroyCleaningUpAnonymousWrappers(RenderObject& child); 82 void multiColumnDescendantInserted(RenderMultiColumnFlow&, RenderObject& newDescendant); 82 83 83 84 private: -
releases/WebKitGTK/webkit-2.20/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.cpp
r228668 r228682 35 35 namespace WebCore { 36 36 37 static RenderMultiColumnSet* findSetRendering(const RenderMultiColumnFlow& fragmentedFlow, const RenderObject& renderer) 38 { 39 // Find the set inside which the specified renderer would be rendered. 40 for (auto* multicolSet = fragmentedFlow.firstMultiColumnSet(); multicolSet; multicolSet = multicolSet->nextSiblingMultiColumnSet()) { 41 if (multicolSet->containsRendererInFragmentedFlow(renderer)) 42 return multicolSet; 43 } 44 return nullptr; 45 } 46 47 static RenderObject* spannerPlacehoderCandidate(const RenderObject& renderer, const RenderMultiColumnFlow& stayWithin) 48 { 49 // Spanner candidate is a next sibling/ancestor's next child within the flow thread and 50 // it is in the same inflow/out-of-flow layout context. 51 if (renderer.isOutOfFlowPositioned()) 52 return nullptr; 53 54 ASSERT(renderer.isDescendantOf(&stayWithin)); 55 auto* current = &renderer; 56 while (true) { 57 // Skip to the first in-flow sibling. 58 auto* nextSibling = current->nextSibling(); 59 while (nextSibling && nextSibling->isOutOfFlowPositioned()) 60 nextSibling = nextSibling->nextSibling(); 61 if (nextSibling) 62 return nextSibling; 63 // No sibling candidate, jump to the parent and check its siblings. 64 current = current->parent(); 65 if (!current || current == &stayWithin || current->isOutOfFlowPositioned()) 66 return nullptr; 67 } 68 return nullptr; 69 } 70 71 static bool isValidColumnSpanner(const RenderMultiColumnFlow& fragmentedFlow, const RenderObject& descendant) 72 { 73 // We assume that we're inside the flow thread. This function is not to be called otherwise. 74 ASSERT(descendant.isDescendantOf(&fragmentedFlow)); 75 // First make sure that the renderer itself has the right properties for becoming a spanner. 76 if (!is<RenderBox>(descendant)) 77 return false; 78 79 auto& descendantBox = downcast<RenderBox>(descendant); 80 if (descendantBox.isFloatingOrOutOfFlowPositioned()) 81 return false; 82 83 if (!fragmentedFlow.isColumnSpanningDescendant(descendantBox)) 84 return false; 85 86 auto* parent = descendantBox.parent(); 87 if (!is<RenderBlockFlow>(*parent) || parent->childrenInline()) { 88 // Needs to be block-level. 89 return false; 90 } 91 92 // We need to have the flow thread as the containing block. A spanner cannot break out of the flow thread. 93 auto* enclosingFragmentedFlow = descendantBox.enclosingFragmentedFlow(); 94 if (enclosingFragmentedFlow != &fragmentedFlow) 95 return false; 96 97 // This looks like a spanner, but if we're inside something unbreakable, it's not to be treated as one. 98 for (auto* ancestor = descendantBox.containingBlock(); ancestor; ancestor = ancestor->containingBlock()) { 99 if (is<RenderView>(*ancestor)) 100 return false; 101 if (is<RenderFragmentedFlow>(*ancestor)) { 102 // Don't allow any intervening non-multicol fragmentation contexts. The spec doesn't say 103 // anything about disallowing this, but it's just going to be too complicated to 104 // implement (not to mention specify behavior). 105 return ancestor == &fragmentedFlow; 106 } 107 // This ancestor (descendent of the fragmentedFlow) will create columns later. The spanner belongs to it. 108 if (is<RenderBlockFlow>(*ancestor) && downcast<RenderBlockFlow>(*ancestor).willCreateColumns()) 109 return false; 110 ASSERT(ancestor->style().columnSpan() != ColumnSpanAll || !isValidColumnSpanner(fragmentedFlow, *ancestor)); 111 if (ancestor->isUnsplittableForPagination()) 112 return false; 113 } 114 ASSERT_NOT_REACHED(); 115 return false; 116 } 117 37 118 RenderTreeBuilder::MultiColumn::MultiColumn(RenderTreeBuilder& builder) 38 119 : m_builder(builder) … … 172 253 } 173 254 174 } 255 static bool gShiftingSpanner = false; 256 257 void RenderTreeBuilder::MultiColumn::multiColumnDescendantInserted(RenderMultiColumnFlow& flow, RenderObject& newDescendant) 258 { 259 if (gShiftingSpanner || newDescendant.isInFlowRenderFragmentedFlow()) 260 return; 261 262 auto* subtreeRoot = &newDescendant; 263 auto* descendant = subtreeRoot; 264 while (descendant) { 265 // Skip nested multicolumn flows. 266 if (is<RenderMultiColumnFlow>(*descendant)) { 267 descendant = descendant->nextSibling(); 268 continue; 269 } 270 if (is<RenderMultiColumnSpannerPlaceholder>(*descendant)) { 271 // A spanner's placeholder has been inserted. The actual spanner renderer is moved from 272 // where it would otherwise occur (if it weren't a spanner) to becoming a sibling of the 273 // column sets. 274 RenderMultiColumnSpannerPlaceholder& placeholder = downcast<RenderMultiColumnSpannerPlaceholder>(*descendant); 275 ASSERT(!flow.spannerMap().get(placeholder.spanner())); 276 flow.spannerMap().add(placeholder.spanner(), makeWeakPtr(downcast<RenderMultiColumnSpannerPlaceholder>(descendant))); 277 ASSERT(!placeholder.firstChild()); // There should be no children here, but if there are, we ought to skip them. 278 } else 279 descendant = processPossibleSpannerDescendant(flow, subtreeRoot, *descendant); 280 if (descendant) 281 descendant = descendant->nextInPreOrder(subtreeRoot); 282 } 283 } 284 285 RenderObject* RenderTreeBuilder::MultiColumn::processPossibleSpannerDescendant(RenderMultiColumnFlow& flow, RenderObject*& subtreeRoot, RenderObject& descendant) 286 { 287 RenderBlockFlow* multicolContainer = flow.multiColumnBlockFlow(); 288 RenderObject* nextRendererInFragmentedFlow = spannerPlacehoderCandidate(descendant, flow); 289 RenderObject* insertBeforeMulticolChild = nullptr; 290 RenderObject* nextDescendant = &descendant; 291 292 if (isValidColumnSpanner(flow, descendant)) { 293 // This is a spanner (column-span:all). Such renderers are moved from where they would 294 // otherwise occur in the render tree to becoming a direct child of the multicol container, 295 // so that they live among the column sets. This simplifies the layout implementation, and 296 // basically just relies on regular block layout done by the RenderBlockFlow that 297 // establishes the multicol container. 298 RenderBlockFlow* container = downcast<RenderBlockFlow>(descendant.parent()); 299 RenderMultiColumnSet* setToSplit = nullptr; 300 if (nextRendererInFragmentedFlow) { 301 setToSplit = findSetRendering(flow, descendant); 302 if (setToSplit) { 303 setToSplit->setNeedsLayout(); 304 insertBeforeMulticolChild = setToSplit->nextSibling(); 305 } 306 } 307 // Moving a spanner's renderer so that it becomes a sibling of the column sets requires us 308 // to insert an anonymous placeholder in the tree where the spanner's renderer otherwise 309 // would have been. This is needed for a two reasons: We need a way of separating inline 310 // content before and after the spanner, so that it becomes separate line boxes. Secondly, 311 // this placeholder serves as a break point for column sets, so that, when encountered, we 312 // end flowing one column set and move to the next one. 313 auto newPlaceholder = RenderMultiColumnSpannerPlaceholder::createAnonymous(flow, downcast<RenderBox>(descendant), container->style()); 314 auto& placeholder = *newPlaceholder; 315 m_builder.insertChild(*container, WTFMove(newPlaceholder), descendant.nextSibling()); 316 auto takenDescendant = container->takeChild(m_builder, descendant); 317 318 // This is a guard to stop an ancestor flow thread from processing the spanner. 319 gShiftingSpanner = true; 320 m_builder.insertChildToRenderBlock(*multicolContainer, WTFMove(takenDescendant), insertBeforeMulticolChild); 321 gShiftingSpanner = false; 322 323 // The spanner has now been moved out from the flow thread, but we don't want to 324 // examine its children anyway. They are all part of the spanner and shouldn't trigger 325 // creation of column sets or anything like that. Continue at its original position in 326 // the tree, i.e. where the placeholder was just put. 327 if (subtreeRoot == &descendant) 328 subtreeRoot = &placeholder; 329 nextDescendant = &placeholder; 330 } else { 331 // This is regular multicol content, i.e. not part of a spanner. 332 if (is<RenderMultiColumnSpannerPlaceholder>(nextRendererInFragmentedFlow)) { 333 // Inserted right before a spanner. Is there a set for us there? 334 RenderMultiColumnSpannerPlaceholder& placeholder = downcast<RenderMultiColumnSpannerPlaceholder>(*nextRendererInFragmentedFlow); 335 if (RenderObject* previous = placeholder.spanner()->previousSibling()) { 336 if (is<RenderMultiColumnSet>(*previous)) 337 return nextDescendant; // There's already a set there. Nothing to do. 338 } 339 insertBeforeMulticolChild = placeholder.spanner(); 340 } else if (RenderMultiColumnSet* lastSet = flow.lastMultiColumnSet()) { 341 // This child is not an immediate predecessor of a spanner, which means that if this 342 // child precedes a spanner at all, there has to be a column set created for us there 343 // already. If it doesn't precede any spanner at all, on the other hand, we need a 344 // column set at the end of the multicol container. We don't really check here if the 345 // child inserted precedes any spanner or not (as that's an expensive operation). Just 346 // make sure we have a column set at the end. It's no big deal if it remains unused. 347 if (!lastSet->nextSibling()) 348 return nextDescendant; 349 } 350 } 351 // Need to create a new column set when there's no set already created. We also always insert 352 // another column set after a spanner. Even if it turns out that there are no renderers 353 // following the spanner, there may be bottom margins there, which take up space. 354 auto newSet = flow.createMultiColumnSet(RenderStyle::createAnonymousStyleWithDisplay(multicolContainer->style(), BLOCK)); 355 newSet->initializeStyle(); 356 auto& set = *newSet; 357 m_builder.insertChildToRenderBlock(*multicolContainer, WTFMove(newSet), insertBeforeMulticolChild); 358 flow.invalidateFragments(); 359 360 // We cannot handle immediate column set siblings at the moment (and there's no need for 361 // it, either). There has to be at least one spanner separating them. 362 ASSERT_UNUSED(set, !RenderMultiColumnFlow::previousColumnSetOrSpannerSiblingOf(&set) 363 || !RenderMultiColumnFlow::previousColumnSetOrSpannerSiblingOf(&set)->isRenderMultiColumnSet()); 364 ASSERT(!RenderMultiColumnFlow::nextColumnSetOrSpannerSiblingOf(&set) 365 || !RenderMultiColumnFlow::nextColumnSetOrSpannerSiblingOf(&set)->isRenderMultiColumnSet()); 366 367 return nextDescendant; 368 } 369 370 } -
releases/WebKitGTK/webkit-2.20/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.h
r227903 r228682 41 41 // location in the tree. 42 42 RenderObject* resolveMovedChild(RenderFragmentedFlow& enclosingFragmentedFlow, RenderObject* beforeChild); 43 void multiColumnDescendantInserted(RenderMultiColumnFlow&, RenderObject& newDescendant); 43 44 44 45 private: 45 46 void createFragmentedFlow(RenderBlockFlow&); 46 47 void destroyFragmentedFlow(RenderBlockFlow&); 48 RenderObject* processPossibleSpannerDescendant(RenderMultiColumnFlow&, RenderObject*& subtreeRoot, RenderObject& descendant); 47 49 48 50 RenderTreeBuilder& m_builder;
Note: See TracChangeset
for help on using the changeset viewer.