| 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. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 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/shadow/ComposedTreeTraversal.h" | 28 #include "core/dom/shadow/ComposedTreeTraversal.h" |
| 29 #include "core/html/HTMLOListElement.h" | 29 #include "core/html/HTMLOListElement.h" |
| 30 #include "core/layout/LayoutListMarker.h" | 30 #include "core/layout/LayoutListMarker.h" |
| 31 #include "core/layout/LayoutView.h" | 31 #include "core/layout/LayoutView.h" |
| 32 #include "core/layout/TextAutosizer.h" | |
| 33 #include "wtf/StdLibExtras.h" | 32 #include "wtf/StdLibExtras.h" |
| 34 #include "wtf/text/StringBuilder.h" | 33 #include "wtf/text/StringBuilder.h" |
| 35 | 34 |
| 36 namespace blink { | 35 namespace blink { |
| 37 | 36 |
| 38 using namespace HTMLNames; | 37 using namespace HTMLNames; |
| 39 | 38 |
| 40 LayoutListItem::LayoutListItem(Element* element) | 39 LayoutListItem::LayoutListItem(Element* element) |
| 41 : LayoutBlockFlow(element) | 40 : LayoutBlockFlow(element) |
| 42 , m_marker(nullptr) | 41 , m_marker(nullptr) |
| 43 , m_hasExplicitValue(false) | 42 , m_hasExplicitValue(false) |
| 44 , m_isValueUpToDate(false) | 43 , m_isValueUpToDate(false) |
| 45 , m_notInList(false) | 44 , m_notInList(false) |
| 46 { | 45 { |
| 47 setInline(false); | 46 setInline(false); |
| 47 |
| 48 setConsumesSubtreeChangeNotification(); |
| 49 registerSubtreeChangeListenerOnDescendants(true); |
| 48 } | 50 } |
| 49 | 51 |
| 50 void LayoutListItem::styleDidChange(StyleDifference diff, const ComputedStyle* o
ldStyle) | 52 void LayoutListItem::styleDidChange(StyleDifference diff, const ComputedStyle* o
ldStyle) |
| 51 { | 53 { |
| 52 LayoutBlockFlow::styleDidChange(diff, oldStyle); | 54 LayoutBlockFlow::styleDidChange(diff, oldStyle); |
| 53 | 55 |
| 54 if (style()->listStyleType() != NoneListStyle | 56 if (style()->listStyleType() != NoneListStyle |
| 55 || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurr
ed())) { | 57 || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurr
ed())) { |
| 56 if (!m_marker) | 58 if (!m_marker) |
| 57 m_marker = LayoutListMarker::createAnonymous(this); | 59 m_marker = LayoutListMarker::createAnonymous(this); |
| 58 m_marker->listItemStyleDidChange(); | 60 m_marker->listItemStyleDidChange(); |
| 61 notifyOfSubtreeChange(); |
| 59 } else if (m_marker) { | 62 } else if (m_marker) { |
| 60 m_marker->destroy(); | 63 m_marker->destroy(); |
| 61 m_marker = nullptr; | 64 m_marker = nullptr; |
| 62 } | 65 } |
| 63 } | 66 } |
| 64 | 67 |
| 65 void LayoutListItem::willBeDestroyed() | 68 void LayoutListItem::willBeDestroyed() |
| 66 { | 69 { |
| 67 if (m_marker) { | 70 if (m_marker) { |
| 68 m_marker->destroy(); | 71 m_marker->destroy(); |
| 69 m_marker = nullptr; | 72 m_marker = nullptr; |
| 70 } | 73 } |
| 71 LayoutBlockFlow::willBeDestroyed(); | 74 LayoutBlockFlow::willBeDestroyed(); |
| 72 } | 75 } |
| 73 | 76 |
| 74 void LayoutListItem::insertedIntoTree() | 77 void LayoutListItem::insertedIntoTree() |
| 75 { | 78 { |
| 76 LayoutBlockFlow::insertedIntoTree(); | 79 LayoutBlockFlow::insertedIntoTree(); |
| 77 | 80 |
| 78 updateListMarkerNumbers(); | 81 updateListMarkerNumbers(); |
| 79 } | 82 } |
| 80 | 83 |
| 81 void LayoutListItem::willBeRemovedFromTree() | 84 void LayoutListItem::willBeRemovedFromTree() |
| 82 { | 85 { |
| 83 LayoutBlockFlow::willBeRemovedFromTree(); | 86 LayoutBlockFlow::willBeRemovedFromTree(); |
| 84 | 87 |
| 85 updateListMarkerNumbers(); | 88 updateListMarkerNumbers(); |
| 86 } | 89 } |
| 87 | 90 |
| 91 void LayoutListItem::subtreeDidChange() |
| 92 { |
| 93 if (!m_marker) |
| 94 return; |
| 95 |
| 96 if (!updateMarkerLocation()) |
| 97 return; |
| 98 |
| 99 // If the marker is inside we need to redo the preferred width calculations |
| 100 // as the size of the item now includes the size of the list marker. |
| 101 if (m_marker->isInside()) |
| 102 setPreferredLogicalWidthsDirty(); |
| 103 } |
| 104 |
| 88 static bool isList(const Node& node) | 105 static bool isList(const Node& node) |
| 89 { | 106 { |
| 90 return isHTMLUListElement(node) || isHTMLOListElement(node); | 107 return isHTMLUListElement(node) || isHTMLOListElement(node); |
| 91 } | 108 } |
| 92 | 109 |
| 93 // Returns the enclosing list with respect to the DOM order. | 110 // Returns the enclosing list with respect to the DOM order. |
| 94 static Node* enclosingList(const LayoutListItem* listItem) | 111 static Node* enclosingList(const LayoutListItem* listItem) |
| 95 { | 112 { |
| 96 Node* listItemNode = listItem->node(); | 113 Node* listItemNode = listItem->node(); |
| 97 if (!listItemNode) | 114 if (!listItemNode) |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 } | 275 } |
| 259 | 276 |
| 260 static LayoutObject* firstNonMarkerChild(LayoutObject* parent) | 277 static LayoutObject* firstNonMarkerChild(LayoutObject* parent) |
| 261 { | 278 { |
| 262 LayoutObject* result = parent->slowFirstChild(); | 279 LayoutObject* result = parent->slowFirstChild(); |
| 263 while (result && result->isListMarker()) | 280 while (result && result->isListMarker()) |
| 264 result = result->nextSibling(); | 281 result = result->nextSibling(); |
| 265 return result; | 282 return result; |
| 266 } | 283 } |
| 267 | 284 |
| 268 void LayoutListItem::updateMarkerLocationAndInvalidateWidth() | |
| 269 { | |
| 270 ASSERT(m_marker); | |
| 271 | |
| 272 // FIXME: We should not modify the structure of the layout tree | |
| 273 // during layout. crbug.com/370461 | |
| 274 DeprecatedDisableModifyLayoutTreeStructureAsserts disabler; | |
| 275 LayoutState* layoutState = view()->layoutState(); | |
| 276 LayoutFlowThread* currentFlowThread = nullptr; | |
| 277 if (layoutState) { | |
| 278 // 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 | |
| 280 // than the flow thread code will suffer, though, so just reset the curr
ent flow thread | |
| 281 // temporarily. | |
| 282 // FIXME: get rid of this hack, including the flow thread setter in Layo
utState, as part of | |
| 283 // fixing crbug.com/370461 | |
| 284 currentFlowThread = layoutState->flowThread(); | |
| 285 layoutState->setFlowThread(nullptr); | |
| 286 } | |
| 287 if (updateMarkerLocation()) { | |
| 288 // 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. | |
| 290 if (m_marker->isInside()) | |
| 291 containingBlock()->updateLogicalWidth(); | |
| 292 } | |
| 293 if (layoutState) | |
| 294 layoutState->setFlowThread(currentFlowThread); | |
| 295 } | |
| 296 | |
| 297 bool LayoutListItem::updateMarkerLocation() | 285 bool LayoutListItem::updateMarkerLocation() |
| 298 { | 286 { |
| 299 ASSERT(m_marker); | 287 ASSERT(m_marker); |
| 288 |
| 300 LayoutObject* markerParent = m_marker->parent(); | 289 LayoutObject* markerParent = m_marker->parent(); |
| 301 LayoutObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker); | 290 LayoutObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker); |
| 302 if (!lineBoxParent) { | 291 if (!lineBoxParent) { |
| 303 // If the marker is currently contained inside an anonymous box, then we | 292 // 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 | 293 // 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. | 294 // found). It's ok to just leave the marker where it is in this case. |
| 306 if (markerParent && markerParent->isAnonymousBlock()) | 295 if (markerParent && markerParent->isAnonymousBlock()) |
| 307 lineBoxParent = markerParent; | 296 lineBoxParent = markerParent; |
| 308 else | 297 else |
| 309 lineBoxParent = this; | 298 lineBoxParent = this; |
| 310 } | 299 } |
| 311 | 300 |
| 312 if (markerParent != lineBoxParent) { | 301 if (markerParent != lineBoxParent) { |
| 313 m_marker->remove(); | 302 m_marker->remove(); |
| 314 lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent)); | 303 lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent)); |
| 315 m_marker->updateMarginsAndContent(); | 304 m_marker->updateMarginsAndContent(); |
| 316 // If markerParent is an anonymous block with no children, destroy it. | 305 // If markerParent is an anonymous block with no children, destroy it. |
| 317 if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(m
arkerParent)->firstChild() && !toLayoutBlock(markerParent)->continuation()) | 306 if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(m
arkerParent)->firstChild() && !toLayoutBlock(markerParent)->continuation()) |
| 318 markerParent->destroy(); | 307 markerParent->destroy(); |
| 319 return true; | 308 return true; |
| 320 } | 309 } |
| 321 | 310 |
| 322 return false; | 311 return false; |
| 323 } | 312 } |
| 324 | 313 |
| 325 void LayoutListItem::layout() | |
| 326 { | |
| 327 ASSERT(needsLayout()); | |
| 328 | |
| 329 if (m_marker) { | |
| 330 // The marker must be autosized before calling | |
| 331 // updateMarkerLocationAndInvalidateWidth. It cannot be done in the | |
| 332 // parent's beginLayout because it is not yet in the layout tree. | |
| 333 if (TextAutosizer* textAutosizer = document().textAutosizer()) | |
| 334 textAutosizer->inflateListItem(this, m_marker); | |
| 335 | |
| 336 updateMarkerLocationAndInvalidateWidth(); | |
| 337 } | |
| 338 | |
| 339 LayoutBlockFlow::layout(); | |
| 340 } | |
| 341 | |
| 342 void LayoutListItem::addOverflowFromChildren() | 314 void LayoutListItem::addOverflowFromChildren() |
| 343 { | 315 { |
| 344 LayoutBlockFlow::addOverflowFromChildren(); | 316 LayoutBlockFlow::addOverflowFromChildren(); |
| 345 positionListMarker(); | 317 positionListMarker(); |
| 346 } | 318 } |
| 347 | 319 |
| 348 void LayoutListItem::positionListMarker() | 320 void LayoutListItem::positionListMarker() |
| 349 { | 321 { |
| 350 if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_ma
rker->inlineBoxWrapper()) { | 322 if (m_marker && m_marker->parent() && m_marker->parent()->isBox() && !m_mark
er->isInside() && m_marker->inlineBoxWrapper()) { |
| 351 LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft(); | 323 LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft(); |
| 352 LayoutUnit blockOffset = 0; | 324 LayoutUnit blockOffset = 0; |
| 353 LayoutUnit lineOffset = 0; | 325 LayoutUnit lineOffset = 0; |
| 354 for (LayoutBox* o = m_marker->parentBox(); o != this; o = o->parentBox()
) { | 326 for (LayoutBox* o = m_marker->parentBox(); o != this; o = o->parentBox()
) { |
| 355 blockOffset += o->logicalTop(); | 327 blockOffset += o->logicalTop(); |
| 356 lineOffset += o->logicalLeft(); | 328 lineOffset += o->logicalLeft(); |
| 357 } | 329 } |
| 358 | 330 |
| 359 bool adjustOverflow = false; | 331 bool adjustOverflow = false; |
| 360 LayoutUnit markerLogicalLeft; | 332 LayoutUnit markerLogicalLeft; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 482 if (!m_hasExplicitValue) | 454 if (!m_hasExplicitValue) |
| 483 return; | 455 return; |
| 484 m_hasExplicitValue = false; | 456 m_hasExplicitValue = false; |
| 485 m_isValueUpToDate = false; | 457 m_isValueUpToDate = false; |
| 486 explicitValueChanged(); | 458 explicitValueChanged(); |
| 487 } | 459 } |
| 488 | 460 |
| 489 void LayoutListItem::setNotInList(bool notInList) | 461 void LayoutListItem::setNotInList(bool notInList) |
| 490 { | 462 { |
| 491 m_notInList = notInList; | 463 m_notInList = notInList; |
| 492 if (m_marker) | |
| 493 updateMarkerLocation(); | |
| 494 } | 464 } |
| 495 | 465 |
| 496 static LayoutListItem* previousOrNextItem(bool isListReversed, Node* list, Layou
tListItem* item) | 466 static LayoutListItem* previousOrNextItem(bool isListReversed, Node* list, Layou
tListItem* item) |
| 497 { | 467 { |
| 498 return isListReversed ? previousListItem(list, item) : nextListItem(list, it
em); | 468 return isListReversed ? previousListItem(list, item) : nextListItem(list, it
em); |
| 499 } | 469 } |
| 500 | 470 |
| 501 void LayoutListItem::updateListMarkerNumbers() | 471 void LayoutListItem::updateListMarkerNumbers() |
| 502 { | 472 { |
| 503 // If distribution recalc is needed, updateListMarkerNumber will be re-invok
ed | 473 // 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. | 498 // assume that all the following ones have too. |
| 529 // This gives us the opportunity to stop here and avoid | 499 // This gives us the opportunity to stop here and avoid |
| 530 // marking the same nodes again. | 500 // marking the same nodes again. |
| 531 break; | 501 break; |
| 532 } | 502 } |
| 533 item->updateValue(); | 503 item->updateValue(); |
| 534 } | 504 } |
| 535 } | 505 } |
| 536 | 506 |
| 537 } // namespace blink | 507 } // namespace blink |
| OLD | NEW |