Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /** | 1 /** |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * Copyright (C) 2003, 2004, 2005, 2006, 2010 Apple Inc. All rights reserved. | 4 * Copyright (C) 2003, 2004, 2005, 2006, 2010 Apple Inc. All rights reserved. |
| 5 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) | 5 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) |
| 6 * | 6 * |
| 7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
| 11 * | 11 * |
| 12 * This library is distributed in the hope that it will be useful, | 12 * This library is distributed in the hope that it will be useful, |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 * Library General Public License for more details. | 15 * Library General Public License for more details. |
| 16 * | 16 * |
| 17 * You should have received a copy of the GNU Library General Public License | 17 * You should have received a copy of the GNU Library General Public License |
| 18 * along with this library; see the file COPYING.LIB. If not, write to | 18 * along with this library; see the file COPYING.LIB. If not, write to |
| 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 20 * Boston, MA 02110-1301, USA. | 20 * Boston, MA 02110-1301, USA. |
| 21 * | 21 * |
| 22 */ | 22 */ |
| 23 | 23 |
| 24 #include "config.h" | 24 #include "config.h" |
| 25 #include "core/layout/LayoutListItem.h" | 25 #include "core/layout/LayoutListItem.h" |
| 26 | 26 |
| 27 #include "core/HTMLNames.h" | 27 #include "core/HTMLNames.h" |
| 28 #include "core/dom/MarkerPseudoElement.h" | |
| 28 #include "core/dom/shadow/ComposedTreeTraversal.h" | 29 #include "core/dom/shadow/ComposedTreeTraversal.h" |
| 29 #include "core/html/HTMLOListElement.h" | 30 #include "core/html/HTMLOListElement.h" |
| 30 #include "core/layout/LayoutListMarker.h" | 31 #include "core/layout/LayoutListMarker.h" |
| 31 #include "core/layout/LayoutView.h" | 32 #include "core/layout/LayoutView.h" |
| 32 #include "core/layout/TextAutosizer.h" | 33 #include "core/layout/TextAutosizer.h" |
| 33 #include "wtf/StdLibExtras.h" | 34 #include "wtf/StdLibExtras.h" |
| 35 #include "wtf/TemporaryChange.h" | |
| 34 #include "wtf/text/StringBuilder.h" | 36 #include "wtf/text/StringBuilder.h" |
| 35 | 37 |
| 36 namespace blink { | 38 namespace blink { |
| 37 | 39 |
| 38 using namespace HTMLNames; | 40 using namespace HTMLNames; |
| 39 | 41 |
| 40 LayoutListItem::LayoutListItem(Element* element) | 42 LayoutListItem::LayoutListItem(Element* element) |
| 41 : LayoutBlockFlow(element) | 43 : LayoutBlockFlow(element) |
| 42 , m_marker(nullptr) | 44 , m_marker(nullptr) |
| 45 , m_inSubtreeChanged(false) | |
| 43 , m_hasExplicitValue(false) | 46 , m_hasExplicitValue(false) |
| 44 , m_isValueUpToDate(false) | 47 , m_isValueUpToDate(false) |
| 45 , m_notInList(false) | 48 , m_notInList(false) |
| 46 { | 49 { |
| 47 setInline(false); | 50 setInline(false); |
| 48 } | 51 } |
| 49 | 52 |
| 50 void LayoutListItem::styleDidChange(StyleDifference diff, const ComputedStyle* o ldStyle) | 53 void LayoutListItem::styleDidChange(StyleDifference diff, const ComputedStyle* o ldStyle) |
| 51 { | 54 { |
| 52 LayoutBlockFlow::styleDidChange(diff, oldStyle); | 55 LayoutBlockFlow::styleDidChange(diff, oldStyle); |
| 53 | 56 |
| 57 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) | |
| 58 return; | |
| 59 | |
| 54 if (style()->listStyleType() != NoneListStyle | 60 if (style()->listStyleType() != NoneListStyle |
| 55 || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurr ed())) { | 61 || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurr ed())) { |
| 56 if (!m_marker) | 62 if (!m_marker) |
| 57 m_marker = LayoutListMarker::createAnonymous(this); | 63 m_marker = LayoutListMarker::createAnonymous(this); |
| 58 m_marker->listItemStyleDidChange(); | 64 m_marker->listItemStyleDidChange(); |
| 59 } else if (m_marker) { | 65 } else if (m_marker) { |
| 60 m_marker->destroy(); | 66 m_marker->destroy(); |
| 61 m_marker = nullptr; | 67 m_marker = nullptr; |
| 62 } | 68 } |
| 63 } | 69 } |
| 64 | 70 |
| 65 void LayoutListItem::willBeDestroyed() | 71 void LayoutListItem::willBeDestroyed() |
| 66 { | 72 { |
| 67 if (m_marker) { | 73 if (m_marker) { |
| 68 m_marker->destroy(); | 74 m_marker->destroy(); |
| 69 m_marker = nullptr; | 75 m_marker = nullptr; |
| 70 } | 76 } |
| 71 LayoutBlockFlow::willBeDestroyed(); | 77 LayoutBlockFlow::willBeDestroyed(); |
| 72 } | 78 } |
| 73 | 79 |
| 74 void LayoutListItem::insertedIntoTree() | 80 void LayoutListItem::insertedIntoTree() |
| 75 { | 81 { |
| 76 LayoutBlockFlow::insertedIntoTree(); | 82 LayoutBlockFlow::insertedIntoTree(); |
| 77 | |
| 78 updateListMarkerNumbers(); | 83 updateListMarkerNumbers(); |
| 79 } | 84 } |
| 80 | 85 |
| 81 void LayoutListItem::willBeRemovedFromTree() | 86 void LayoutListItem::willBeRemovedFromTree() |
| 82 { | 87 { |
| 83 LayoutBlockFlow::willBeRemovedFromTree(); | 88 LayoutBlockFlow::willBeRemovedFromTree(); |
| 89 updateListMarkerNumbers(); | |
| 90 } | |
| 84 | 91 |
| 85 updateListMarkerNumbers(); | 92 void LayoutListItem::subtreeChangedNotification() |
| 93 { | |
| 94 if (!document().lifecycle().isActive()) | |
| 95 return; | |
| 96 | |
| 97 if (m_inSubtreeChanged) | |
| 98 return; | |
| 99 | |
| 100 TemporaryChange<bool> changed(m_inSubtreeChanged, true); | |
| 101 | |
|
esprehn
2015/04/20 16:04:08
This is an example why you can't do this, it's ver
dsinclair
2015/04/21 20:23:10
Done.
| |
| 102 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) | |
|
esprehn
2015/04/20 16:04:08
You can't do synchronous subtree notifications lik
dsinclair
2015/04/21 20:23:10
Done.
| |
| 103 toMarkerPseudoElement(element)->attachListMarkerLayoutObject(); | |
| 104 | |
| 105 LayoutBlockFlow::subtreeChangedNotification(); | |
| 106 } | |
| 107 | |
| 108 void LayoutListItem::addChild(LayoutObject* newChild, LayoutObject* beforeChild) | |
| 109 { | |
| 110 LayoutBlockFlow::addChild(newChild, beforeChild); | |
| 111 | |
| 112 if (!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) | |
| 113 return; | |
| 114 | |
| 115 newChild->setNotifyAncestorsOfSubtreeChangeRecursive(true); | |
| 116 | |
| 117 // If we've inserted a new child we, possibly, have to move the list marker | |
| 118 // into that child. Nothing to do if it's the marker we're inserting. | |
| 119 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) { | |
| 120 if (newChild != element->layoutObject()) | |
| 121 toMarkerPseudoElement(element)->attachListMarkerLayoutObject(); | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 void LayoutListItem::removeChild(LayoutObject* child) | |
| 126 { | |
| 127 LayoutBlockFlow::removeChild(child); | |
| 128 | |
| 129 if (!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) | |
| 130 return; | |
| 131 | |
| 132 child->setNotifyAncestorsOfSubtreeChangeRecursive(false); | |
| 133 | |
| 134 // If we've removed a child we, possibly, have to move the list marker | |
| 135 // into a new parent. Don't try to update the marker when it's the | |
| 136 // marker that was removed. | |
| 137 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) { | |
| 138 if (child != element->layoutObject()) | |
| 139 toMarkerPseudoElement(element)->attachListMarkerLayoutObject(); | |
| 140 } | |
| 86 } | 141 } |
| 87 | 142 |
| 88 static bool isList(const Node& node) | 143 static bool isList(const Node& node) |
| 89 { | 144 { |
| 90 return isHTMLUListElement(node) || isHTMLOListElement(node); | 145 return isHTMLUListElement(node) || isHTMLOListElement(node); |
| 91 } | 146 } |
| 92 | 147 |
| 93 // Returns the enclosing list with respect to the DOM order. | 148 // Returns the enclosing list with respect to the DOM order. |
| 94 static Node* enclosingList(const LayoutListItem* listItem) | 149 static Node* enclosingList(const LayoutListItem* listItem) |
| 95 { | 150 { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 122 ASSERT(!current->document().childNeedsDistributionRecalc()); | 177 ASSERT(!current->document().childNeedsDistributionRecalc()); |
| 123 current = LayoutTreeBuilderTraversal::next(*current, listNode); | 178 current = LayoutTreeBuilderTraversal::next(*current, listNode); |
| 124 | 179 |
| 125 while (current) { | 180 while (current) { |
| 126 if (isList(*current)) { | 181 if (isList(*current)) { |
| 127 // We've found a nested, independent list: nothing to do here. | 182 // We've found a nested, independent list: nothing to do here. |
| 128 current = LayoutTreeBuilderTraversal::nextSkippingChildren(*current, listNode); | 183 current = LayoutTreeBuilderTraversal::nextSkippingChildren(*current, listNode); |
| 129 continue; | 184 continue; |
| 130 } | 185 } |
| 131 | 186 |
| 132 LayoutObject* renderer = current->layoutObject(); | 187 LayoutObject* layoutObject = current->layoutObject(); |
| 133 if (renderer && renderer->isListItem()) | 188 if (layoutObject && layoutObject->isListItem()) |
| 134 return toLayoutListItem(renderer); | 189 return toLayoutListItem(layoutObject); |
| 135 | 190 |
| 136 // FIXME: Can this be optimized to skip the children of the elements wit hout a renderer? | 191 // FIXME: Can this be optimized to skip the children of the elements wit hout a layoutObject? |
| 137 current = LayoutTreeBuilderTraversal::next(*current, listNode); | 192 current = LayoutTreeBuilderTraversal::next(*current, listNode); |
| 138 } | 193 } |
| 139 | 194 |
| 140 return 0; | 195 return 0; |
| 141 } | 196 } |
| 142 | 197 |
| 143 // Returns the previous list item with respect to the DOM order. | 198 // Returns the previous list item with respect to the DOM order. |
| 144 static LayoutListItem* previousListItem(const Node* listNode, const LayoutListIt em* item) | 199 static LayoutListItem* previousListItem(const Node* listNode, const LayoutListIt em* item) |
| 145 { | 200 { |
| 146 Node* current = item->node(); | 201 Node* current = item->node(); |
| 147 ASSERT(current); | 202 ASSERT(current); |
| 148 ASSERT(!current->document().childNeedsDistributionRecalc()); | 203 ASSERT(!current->document().childNeedsDistributionRecalc()); |
| 149 for (current = LayoutTreeBuilderTraversal::previous(*current, listNode); cur rent && current != listNode; current = LayoutTreeBuilderTraversal::previous(*cur rent, listNode)) { | 204 for (current = LayoutTreeBuilderTraversal::previous(*current, listNode); |
| 150 LayoutObject* renderer = current->layoutObject(); | 205 current && current != listNode; |
| 151 if (!renderer || (renderer && !renderer->isListItem())) | 206 current = LayoutTreeBuilderTraversal::previous(*current, listNode)) { |
| 207 | |
| 208 LayoutObject* layoutObject = current->layoutObject(); | |
| 209 if (!layoutObject || (layoutObject && !layoutObject->isListItem())) | |
| 152 continue; | 210 continue; |
| 153 Node* otherList = enclosingList(toLayoutListItem(renderer)); | 211 Node* otherList = enclosingList(toLayoutListItem(layoutObject)); |
| 154 // This item is part of our current list, so it's what we're looking for . | 212 // This item is part of our current list, so it's what we're looking for . |
| 155 if (listNode == otherList) | 213 if (listNode == otherList) |
| 156 return toLayoutListItem(renderer); | 214 return toLayoutListItem(layoutObject); |
| 157 // We found ourself inside another list; lets skip the rest of it. | 215 // We found ourself inside another list; lets skip the rest of it. |
| 158 // Use nextIncludingPseudo() here because the other list itself may actu ally | 216 // Use nextIncludingPseudo() here because the other list itself may actu ally |
| 159 // be a list item itself. We need to examine it, so we do this to counte ract | 217 // be a list item itself. We need to examine it, so we do this to counte ract |
| 160 // the previousIncludingPseudo() that will be done by the loop. | 218 // the previousIncludingPseudo() that will be done by the loop. |
| 161 if (otherList) | 219 if (otherList) |
| 162 current = LayoutTreeBuilderTraversal::next(*otherList, listNode); | 220 current = LayoutTreeBuilderTraversal::next(*otherList, listNode); |
| 163 } | 221 } |
| 164 return 0; | 222 return 0; |
| 165 } | 223 } |
| 166 | 224 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 206 } | 264 } |
| 207 | 265 |
| 208 void LayoutListItem::updateValueNow() const | 266 void LayoutListItem::updateValueNow() const |
| 209 { | 267 { |
| 210 m_value = calcValue(); | 268 m_value = calcValue(); |
| 211 m_isValueUpToDate = true; | 269 m_isValueUpToDate = true; |
| 212 } | 270 } |
| 213 | 271 |
| 214 bool LayoutListItem::isEmpty() const | 272 bool LayoutListItem::isEmpty() const |
| 215 { | 273 { |
| 274 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { | |
| 275 PseudoElement* element = toElement(node())->pseudoElement(MARKER); | |
| 276 return !(element && lastChild() != element->layoutObject()); | |
| 277 } | |
| 216 return lastChild() == m_marker; | 278 return lastChild() == m_marker; |
| 217 } | 279 } |
| 218 | 280 |
| 219 static LayoutObject* getParentOfFirstLineBox(LayoutBlockFlow* curr, LayoutObject * marker) | |
| 220 { | |
| 221 LayoutObject* firstChild = curr->firstChild(); | |
| 222 if (!firstChild) | |
| 223 return 0; | |
| 224 | |
| 225 bool inQuirksMode = curr->document().inQuirksMode(); | |
| 226 for (LayoutObject* currChild = firstChild; currChild; currChild = currChild- >nextSibling()) { | |
| 227 if (currChild == marker) | |
| 228 continue; | |
| 229 | |
| 230 if (currChild->isInline() && (!currChild->isLayoutInline() || curr->gene ratesLineBoxesForInlineChild(currChild))) | |
| 231 return curr; | |
| 232 | |
| 233 if (currChild->isFloating() || currChild->isOutOfFlowPositioned()) | |
| 234 continue; | |
| 235 | |
| 236 if (!currChild->isLayoutBlockFlow() || (currChild->isBox() && toLayoutBo x(currChild)->isWritingModeRoot())) | |
| 237 break; | |
| 238 | |
| 239 if (curr->isListItem() && inQuirksMode && currChild->node() | |
| 240 && (isHTMLUListElement(*currChild->node()) || isHTMLOListElement(*cu rrChild->node()))) | |
| 241 break; | |
| 242 | |
| 243 LayoutObject* lineBox = getParentOfFirstLineBox(toLayoutBlockFlow(currCh ild), marker); | |
| 244 if (lineBox) | |
| 245 return lineBox; | |
| 246 } | |
| 247 | |
| 248 return 0; | |
| 249 } | |
| 250 | |
| 251 void LayoutListItem::updateValue() | 281 void LayoutListItem::updateValue() |
| 252 { | 282 { |
| 253 if (!m_hasExplicitValue) { | 283 if (m_hasExplicitValue) |
| 254 m_isValueUpToDate = false; | 284 return; |
| 255 if (m_marker) | 285 |
| 256 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( LayoutInvalidationReason::ListValueChange); | 286 m_isValueUpToDate = false; |
| 287 | |
| 288 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { | |
| 289 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) | |
| 290 element->layoutObject()->setNeedsLayoutAndPrefWidthsRecalcAndFullPai ntInvalidation(LayoutInvalidationReason::ListValueChange); | |
| 291 } else if (m_marker) { | |
| 292 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(Layo utInvalidationReason::ListValueChange); | |
| 257 } | 293 } |
| 258 } | 294 } |
| 259 | 295 |
| 260 static LayoutObject* firstNonMarkerChild(LayoutObject* parent) | |
| 261 { | |
| 262 LayoutObject* result = parent->slowFirstChild(); | |
| 263 while (result && result->isListMarker()) | |
| 264 result = result->nextSibling(); | |
| 265 return result; | |
| 266 } | |
| 267 | |
| 268 void LayoutListItem::updateMarkerLocationAndInvalidateWidth() | 296 void LayoutListItem::updateMarkerLocationAndInvalidateWidth() |
| 269 { | 297 { |
| 298 ASSERT(!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()); | |
| 270 ASSERT(m_marker); | 299 ASSERT(m_marker); |
| 271 | 300 |
| 272 // FIXME: We should not modify the structure of the render tree | 301 // FIXME: We should not modify the structure of the render tree |
| 273 // during layout. crbug.com/370461 | 302 // during layout. crbug.com/370461 |
| 274 DeprecatedDisableModifyRenderTreeStructureAsserts disabler; | 303 DeprecatedDisableModifyRenderTreeStructureAsserts disabler; |
| 275 LayoutState* layoutState = view()->layoutState(); | 304 LayoutState* layoutState = view()->layoutState(); |
| 276 LayoutFlowThread* currentFlowThread = nullptr; | 305 LayoutFlowThread* currentFlowThread = nullptr; |
| 277 if (layoutState) { | 306 if (layoutState) { |
| 278 // We're about to modify the layout tree structure (during layout!), and any code using | 307 // We're about to modify the layout tree structure (during layout!), and any code using |
| 279 // LayoutState might get utterly confused by that. There's no evidence t hat anything other | 308 // LayoutState might get utterly confused by that. There's no evidence t hat anything other |
| 280 // than the flow thread code will suffer, though, so just reset the curr ent flow thread | 309 // than the flow thread code will suffer, though, so just reset the curr ent flow thread |
| 281 // temporarily. | 310 // temporarily. |
| 282 // FIXME: get rid of this hack, including the flow thread setter in Layo utState, as part of | 311 // FIXME: get rid of this hack, including the flow thread setter in Layo utState, as part of |
| 283 // fixing crbug.com/370461 | 312 // fixing crbug.com/370461 |
| 284 currentFlowThread = layoutState->flowThread(); | 313 currentFlowThread = layoutState->flowThread(); |
| 285 layoutState->setFlowThread(nullptr); | 314 layoutState->setFlowThread(nullptr); |
| 286 } | 315 } |
| 287 if (updateMarkerLocation()) { | 316 if (updateMarkerLocation()) { |
| 288 // If the marker is inside we need to redo the preferred width calculati ons | 317 // If the marker is inside we need to redo the preferred width calculati ons |
| 289 // as the size of the item now includes the size of the list marker. | 318 // as the size of the item now includes the size of the list marker. |
| 290 if (m_marker->isInside()) | 319 if (m_marker->isInside()) |
| 291 containingBlock()->updateLogicalWidth(); | 320 containingBlock()->updateLogicalWidth(); |
| 292 } | 321 } |
| 293 if (layoutState) | 322 if (layoutState) |
| 294 layoutState->setFlowThread(currentFlowThread); | 323 layoutState->setFlowThread(currentFlowThread); |
| 295 } | 324 } |
| 296 | 325 |
| 297 bool LayoutListItem::updateMarkerLocation() | 326 bool LayoutListItem::updateMarkerLocation() |
| 298 { | 327 { |
| 328 ASSERT(!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()); | |
| 299 ASSERT(m_marker); | 329 ASSERT(m_marker); |
| 330 | |
| 300 LayoutObject* markerParent = m_marker->parent(); | 331 LayoutObject* markerParent = m_marker->parent(); |
| 301 LayoutObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker); | 332 LayoutObject* lineBoxParent = MarkerPseudoElement::getParentOfFirstLineBox(t his, m_marker); |
| 302 if (!lineBoxParent) { | 333 if (!lineBoxParent) { |
| 303 // If the marker is currently contained inside an anonymous box, then we | 334 // If the marker is currently contained inside an anonymous box, then we |
| 304 // are the only item in that anonymous box (since no line box parent was | 335 // are the only item in that anonymous box (since no line box parent was |
| 305 // found). It's ok to just leave the marker where it is in this case. | 336 // found). It's ok to just leave the marker where it is in this case. |
| 306 if (markerParent && markerParent->isAnonymousBlock()) | 337 if (markerParent && markerParent->isAnonymousBlock()) |
| 307 lineBoxParent = markerParent; | 338 lineBoxParent = markerParent; |
| 308 else | 339 else |
| 309 lineBoxParent = this; | 340 lineBoxParent = this; |
| 310 } | 341 } |
| 311 | 342 |
| 312 if (markerParent != lineBoxParent) { | 343 if (markerParent != lineBoxParent) { |
| 313 m_marker->remove(); | 344 m_marker->remove(); |
| 314 lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent)); | 345 lineBoxParent->addChild(m_marker, MarkerPseudoElement::firstNonMarkerChi ld(lineBoxParent)); |
| 315 m_marker->updateMarginsAndContent(); | 346 m_marker->updateMarginsAndContent(); |
| 316 // If markerParent is an anonymous block with no children, destroy it. | 347 // If markerParent is an anonymous block with no children, destroy it. |
| 317 if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(m arkerParent)->firstChild() && !toLayoutBlock(markerParent)->continuation()) | 348 if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(m arkerParent)->firstChild() |
| 349 && !toLayoutBlock(markerParent)->continuation()) | |
| 318 markerParent->destroy(); | 350 markerParent->destroy(); |
| 319 return true; | 351 return true; |
| 320 } | 352 } |
| 321 | 353 |
| 322 return false; | 354 return false; |
| 323 } | 355 } |
| 324 | 356 |
| 325 void LayoutListItem::layout() | 357 void LayoutListItem::layout() |
| 326 { | 358 { |
| 327 ASSERT(needsLayout()); | 359 ASSERT(needsLayout()); |
| 328 | 360 |
| 329 if (m_marker) { | 361 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
| 362 PseudoElement* element = toElement(node())->pseudoElement(MARKER); | |
| 363 if (element && element->layoutObject()) { | |
| 364 ASSERT(element->layoutObject()->isListMarker()); | |
| 365 LayoutListMarker* marker = toLayoutListMarker(element->layoutObject( )); | |
| 366 | |
| 367 marker->updateMarginsAndContent(); | |
| 368 } | |
| 369 | |
| 370 } else if (m_marker) { | |
| 330 // The marker must be autosized before calling | 371 // The marker must be autosized before calling |
| 331 // updateMarkerLocationAndInvalidateWidth. It cannot be done in the | 372 // updateMarkerLocationAndInvalidateWidth. It cannot be done in the |
| 332 // parent's beginLayout because it is not yet in the render tree. | 373 // parent's beginLayout because it is not yet in the render tree. |
| 333 if (TextAutosizer* textAutosizer = document().textAutosizer()) | 374 if (TextAutosizer* textAutosizer = document().textAutosizer()) |
| 334 textAutosizer->inflateListItem(this, m_marker); | 375 textAutosizer->inflateListItem(this, m_marker); |
| 335 | 376 |
| 336 updateMarkerLocationAndInvalidateWidth(); | 377 updateMarkerLocationAndInvalidateWidth(); |
| 337 } | 378 } |
| 338 | 379 |
| 339 LayoutBlockFlow::layout(); | 380 LayoutBlockFlow::layout(); |
| 340 } | 381 } |
| 341 | 382 |
| 342 void LayoutListItem::addOverflowFromChildren() | 383 void LayoutListItem::addOverflowFromChildren() |
| 343 { | 384 { |
| 344 LayoutBlockFlow::addOverflowFromChildren(); | 385 LayoutBlockFlow::addOverflowFromChildren(); |
| 345 positionListMarker(); | 386 |
| 387 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { | |
| 388 MarkerPseudoElement* markerElement = toMarkerPseudoElement(toElement(nod e())->pseudoElement(MARKER)); | |
| 389 if (markerElement && markerElement->layoutObject()) { | |
| 390 ASSERT(markerElement->layoutObject()->isListMarker()); | |
| 391 positionListMarker(toLayoutListMarker(markerElement->layoutObject()) ); | |
| 392 } | |
| 393 } else { | |
| 394 positionListMarker(m_marker); | |
| 395 } | |
| 346 } | 396 } |
| 347 | 397 |
| 348 void LayoutListItem::positionListMarker() | 398 void LayoutListItem::positionListMarker(LayoutListMarker* marker) |
| 349 { | 399 { |
| 350 if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_ma rker->inlineBoxWrapper()) { | 400 if (!marker) |
| 351 LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft(); | 401 return; |
| 402 | |
| 403 ASSERT(marker->parent()); | |
| 404 if (marker->parent()->isBox() && !marker->isInside() && marker->inlineBoxWra pper()) { | |
| 405 LayoutUnit markerOldLogicalLeft = marker->logicalLeft(); | |
| 352 LayoutUnit blockOffset = 0; | 406 LayoutUnit blockOffset = 0; |
| 353 LayoutUnit lineOffset = 0; | 407 LayoutUnit lineOffset = 0; |
| 354 for (LayoutBox* o = m_marker->parentBox(); o != this; o = o->parentBox() ) { | 408 for (LayoutBox* o = marker->parentBox(); o != this; o = o->parentBox()) { |
| 355 blockOffset += o->logicalTop(); | 409 blockOffset += o->logicalTop(); |
| 356 lineOffset += o->logicalLeft(); | 410 lineOffset += o->logicalLeft(); |
| 357 } | 411 } |
| 358 | 412 |
| 359 bool adjustOverflow = false; | 413 bool adjustOverflow = false; |
| 360 LayoutUnit markerLogicalLeft; | 414 LayoutUnit markerLogicalLeft; |
| 361 RootInlineBox& root = m_marker->inlineBoxWrapper()->root(); | 415 RootInlineBox& root = marker->inlineBoxWrapper()->root(); |
| 362 bool hitSelfPaintingLayer = false; | 416 bool hitSelfPaintingLayer = false; |
| 363 | 417 |
| 364 LayoutUnit lineTop = root.lineTop(); | 418 LayoutUnit lineTop = root.lineTop(); |
| 365 LayoutUnit lineBottom = root.lineBottom(); | 419 LayoutUnit lineBottom = root.lineBottom(); |
| 366 | 420 |
| 367 // FIXME: Need to account for relative positioning in the layout overflo w. | 421 // FIXME: Need to account for relative positioning in the layout overflo w. |
| 368 if (style()->isLeftToRightDirection()) { | 422 if (style()->isLeftToRightDirection()) { |
| 369 LayoutUnit leftLineOffset = logicalLeftOffsetForLine(blockOffset, lo gicalLeftOffsetForLine(blockOffset, false), false); | 423 LayoutUnit leftLineOffset = logicalLeftOffsetForLine(blockOffset, lo gicalLeftOffsetForLine(blockOffset, false), false); |
| 370 markerLogicalLeft = leftLineOffset - lineOffset - paddingStart() - b orderStart() + m_marker->marginStart(); | 424 markerLogicalLeft = leftLineOffset - lineOffset - paddingStart() - b orderStart() + marker->marginStart(); |
| 371 m_marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLog icalLeft - markerOldLogicalLeft).toFloat()); | 425 marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLogic alLeft - markerOldLogicalLeft).toFloat()); |
| 372 for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); bo x; box = box->parent()) { | 426 for (InlineFlowBox* box = marker->inlineBoxWrapper()->parent(); box; box = box->parent()) { |
| 373 LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOver flowRect(lineTop, lineBottom); | 427 LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOver flowRect(lineTop, lineBottom); |
| 374 LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOver flowRect(lineTop, lineBottom); | 428 LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOver flowRect(lineTop, lineBottom); |
| 375 if (markerLogicalLeft < newLogicalVisualOverflowRect.x() && !hit SelfPaintingLayer) { | 429 if (markerLogicalLeft < newLogicalVisualOverflowRect.x() && !hit SelfPaintingLayer) { |
| 376 newLogicalVisualOverflowRect.setWidth(newLogicalVisualOverfl owRect.maxX() - markerLogicalLeft); | 430 newLogicalVisualOverflowRect.setWidth(newLogicalVisualOverfl owRect.maxX() - markerLogicalLeft); |
| 377 newLogicalVisualOverflowRect.setX(markerLogicalLeft); | 431 newLogicalVisualOverflowRect.setX(markerLogicalLeft); |
| 378 if (box == root) | 432 if (box == root) |
| 379 adjustOverflow = true; | 433 adjustOverflow = true; |
| 380 } | 434 } |
| 381 if (markerLogicalLeft < newLogicalLayoutOverflowRect.x()) { | 435 if (markerLogicalLeft < newLogicalLayoutOverflowRect.x()) { |
| 382 newLogicalLayoutOverflowRect.setWidth(newLogicalLayoutOverfl owRect.maxX() - markerLogicalLeft); | 436 newLogicalLayoutOverflowRect.setWidth(newLogicalLayoutOverfl owRect.maxX() - markerLogicalLeft); |
| 383 newLogicalLayoutOverflowRect.setX(markerLogicalLeft); | 437 newLogicalLayoutOverflowRect.setX(markerLogicalLeft); |
| 384 if (box == root) | 438 if (box == root) |
| 385 adjustOverflow = true; | 439 adjustOverflow = true; |
| 386 } | 440 } |
| 387 box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, n ewLogicalVisualOverflowRect, lineTop, lineBottom); | 441 box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, n ewLogicalVisualOverflowRect, lineTop, lineBottom); |
| 388 if (box->boxModelObject()->hasSelfPaintingLayer()) | 442 if (box->boxModelObject()->hasSelfPaintingLayer()) |
| 389 hitSelfPaintingLayer = true; | 443 hitSelfPaintingLayer = true; |
| 390 } | 444 } |
| 391 } else { | 445 } else { |
| 392 LayoutUnit rightLineOffset = logicalRightOffsetForLine(blockOffset, logicalRightOffsetForLine(blockOffset, false), false); | 446 LayoutUnit rightLineOffset = logicalRightOffsetForLine(blockOffset, logicalRightOffsetForLine(blockOffset, false), false); |
| 393 markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + m_marker->marginEnd(); | 447 markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + marker->marginEnd(); |
| 394 m_marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLog icalLeft - markerOldLogicalLeft).toFloat()); | 448 marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLogic alLeft - markerOldLogicalLeft).toFloat()); |
| 395 for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); bo x; box = box->parent()) { | 449 for (InlineFlowBox* box = marker->inlineBoxWrapper()->parent(); box; box = box->parent()) { |
| 396 LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOver flowRect(lineTop, lineBottom); | 450 LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOver flowRect(lineTop, lineBottom); |
| 397 LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOver flowRect(lineTop, lineBottom); | 451 LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOver flowRect(lineTop, lineBottom); |
| 398 if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalVis ualOverflowRect.maxX() && !hitSelfPaintingLayer) { | 452 if (markerLogicalLeft + marker->logicalWidth() > newLogicalVisua lOverflowRect.maxX() && !hitSelfPaintingLayer) { |
| 399 newLogicalVisualOverflowRect.setWidth(markerLogicalLeft + m_ marker->logicalWidth() - newLogicalVisualOverflowRect.x()); | 453 newLogicalVisualOverflowRect.setWidth(markerLogicalLeft + ma rker->logicalWidth() - newLogicalVisualOverflowRect.x()); |
| 400 if (box == root) | 454 if (box == root) |
| 401 adjustOverflow = true; | 455 adjustOverflow = true; |
| 402 } | 456 } |
| 403 if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalLay outOverflowRect.maxX()) { | 457 if (markerLogicalLeft + marker->logicalWidth() > newLogicalLayou tOverflowRect.maxX()) { |
| 404 newLogicalLayoutOverflowRect.setWidth(markerLogicalLeft + m_ marker->logicalWidth() - newLogicalLayoutOverflowRect.x()); | 458 newLogicalLayoutOverflowRect.setWidth(markerLogicalLeft + ma rker->logicalWidth() - newLogicalLayoutOverflowRect.x()); |
| 405 if (box == root) | 459 if (box == root) |
| 406 adjustOverflow = true; | 460 adjustOverflow = true; |
| 407 } | 461 } |
| 408 box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, n ewLogicalVisualOverflowRect, lineTop, lineBottom); | 462 box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, n ewLogicalVisualOverflowRect, lineTop, lineBottom); |
| 409 | 463 |
| 410 if (box->boxModelObject()->hasSelfPaintingLayer()) | 464 if (box->boxModelObject()->hasSelfPaintingLayer()) |
| 411 hitSelfPaintingLayer = true; | 465 hitSelfPaintingLayer = true; |
| 412 } | 466 } |
| 413 } | 467 } |
| 414 | 468 |
| 415 if (adjustOverflow) { | 469 if (adjustOverflow) { |
| 416 LayoutRect markerRect(LayoutPoint(markerLogicalLeft + lineOffset, bl ockOffset), m_marker->size()); | 470 LayoutRect markerRect(LayoutPoint(markerLogicalLeft + lineOffset, bl ockOffset), marker->size()); |
| 417 if (!style()->isHorizontalWritingMode()) | 471 if (!style()->isHorizontalWritingMode()) |
| 418 markerRect = markerRect.transposedRect(); | 472 markerRect = markerRect.transposedRect(); |
| 419 LayoutBox* o = m_marker; | 473 LayoutBox* o = marker; |
| 420 bool propagateVisualOverflow = true; | 474 bool propagateVisualOverflow = true; |
| 421 bool propagateLayoutOverflow = true; | 475 bool propagateLayoutOverflow = true; |
| 422 do { | 476 do { |
| 423 o = o->parentBox(); | 477 o = o->parentBox(); |
| 424 if (o->isLayoutBlock()) { | 478 if (o->isLayoutBlock()) { |
| 425 if (propagateVisualOverflow) | 479 if (propagateVisualOverflow) |
| 426 toLayoutBlock(o)->addContentsVisualOverflow(markerRect); | 480 toLayoutBlock(o)->addContentsVisualOverflow(markerRect); |
| 427 if (propagateLayoutOverflow) | 481 if (propagateLayoutOverflow) |
| 428 toLayoutBlock(o)->addLayoutOverflow(markerRect); | 482 toLayoutBlock(o)->addLayoutOverflow(markerRect); |
| 429 } | 483 } |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 442 void LayoutListItem::paint(const PaintInfo& paintInfo, const LayoutPoint& paintO ffset) | 496 void LayoutListItem::paint(const PaintInfo& paintInfo, const LayoutPoint& paintO ffset) |
| 443 { | 497 { |
| 444 if (!logicalHeight() && hasOverflowClip()) | 498 if (!logicalHeight() && hasOverflowClip()) |
| 445 return; | 499 return; |
| 446 | 500 |
| 447 LayoutBlockFlow::paint(paintInfo, paintOffset); | 501 LayoutBlockFlow::paint(paintInfo, paintOffset); |
| 448 } | 502 } |
| 449 | 503 |
| 450 const String& LayoutListItem::markerText() const | 504 const String& LayoutListItem::markerText() const |
| 451 { | 505 { |
| 452 if (m_marker) | 506 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
| 507 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) { | |
| 508 if (element->layoutObject()) { | |
| 509 ASSERT(element->layoutObject()->isListMarker()); | |
| 510 return toLayoutListMarker(element->layoutObject())->text(); | |
| 511 } | |
| 512 } | |
| 513 } else if (m_marker) { | |
| 453 return m_marker->text(); | 514 return m_marker->text(); |
| 515 } | |
| 454 return nullAtom.string(); | 516 return nullAtom.string(); |
| 455 } | 517 } |
| 456 | 518 |
| 457 void LayoutListItem::explicitValueChanged() | 519 void LayoutListItem::explicitValueChanged() |
| 458 { | 520 { |
| 459 if (m_marker) | 521 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
| 522 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) | |
| 523 element->layoutObject()->setNeedsLayoutAndPrefWidthsRecalcAndFullPai ntInvalidation(LayoutInvalidationReason::ListValueChange); | |
| 524 } else if (m_marker) { | |
| 460 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(Layo utInvalidationReason::ListValueChange); | 525 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(Layo utInvalidationReason::ListValueChange); |
| 526 } | |
| 527 | |
| 461 Node* listNode = enclosingList(this); | 528 Node* listNode = enclosingList(this); |
| 462 for (LayoutListItem* item = this; item; item = nextListItem(listNode, item)) | 529 for (LayoutListItem* item = this; item; item = nextListItem(listNode, item)) |
| 463 item->updateValue(); | 530 item->updateValue(); |
| 464 } | 531 } |
| 465 | 532 |
| 466 void LayoutListItem::setExplicitValue(int value) | 533 void LayoutListItem::setExplicitValue(int value) |
| 467 { | 534 { |
| 468 ASSERT(node()); | 535 ASSERT(node()); |
| 469 | 536 |
| 470 if (m_hasExplicitValue && m_explicitValue == value) | 537 if (m_hasExplicitValue && m_explicitValue == value) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 482 if (!m_hasExplicitValue) | 549 if (!m_hasExplicitValue) |
| 483 return; | 550 return; |
| 484 m_hasExplicitValue = false; | 551 m_hasExplicitValue = false; |
| 485 m_isValueUpToDate = false; | 552 m_isValueUpToDate = false; |
| 486 explicitValueChanged(); | 553 explicitValueChanged(); |
| 487 } | 554 } |
| 488 | 555 |
| 489 void LayoutListItem::setNotInList(bool notInList) | 556 void LayoutListItem::setNotInList(bool notInList) |
| 490 { | 557 { |
| 491 m_notInList = notInList; | 558 m_notInList = notInList; |
| 492 if (m_marker) | 559 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
| 560 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) { | |
| 561 ASSERT(element->layoutObject()); | |
| 562 ASSERT(element->layoutObject()->isListMarker()); | |
| 563 toLayoutListMarker(element->layoutObject())->updateMarginsAndContent (); | |
| 564 } | |
| 565 } else if (m_marker) { | |
| 493 updateMarkerLocation(); | 566 updateMarkerLocation(); |
| 567 } | |
| 494 } | 568 } |
| 495 | 569 |
| 496 static LayoutListItem* previousOrNextItem(bool isListReversed, Node* list, Layou tListItem* item) | 570 static LayoutListItem* previousOrNextItem(bool isListReversed, Node* list, Layou tListItem* item) |
| 497 { | 571 { |
| 498 return isListReversed ? previousListItem(list, item) : nextListItem(list, it em); | 572 return isListReversed ? previousListItem(list, item) : nextListItem(list, it em); |
| 499 } | 573 } |
| 500 | 574 |
| 501 void LayoutListItem::updateListMarkerNumbers() | 575 void LayoutListItem::updateListMarkerNumbers() |
| 502 { | 576 { |
| 503 // If distribution recalc is needed, updateListMarkerNumber will be re-invok ed | 577 // If distribution recalc is needed, updateListMarkerNumber will be re-invok ed |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 528 // assume that all the following ones have too. | 602 // assume that all the following ones have too. |
| 529 // This gives us the opportunity to stop here and avoid | 603 // This gives us the opportunity to stop here and avoid |
| 530 // marking the same nodes again. | 604 // marking the same nodes again. |
| 531 break; | 605 break; |
| 532 } | 606 } |
| 533 item->updateValue(); | 607 item->updateValue(); |
| 534 } | 608 } |
| 535 } | 609 } |
| 536 | 610 |
| 537 } // namespace blink | 611 } // namespace blink |
| OLD | NEW |