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 setConsumesSubtreeChangeNotification(); | |
48 setAncestorNeedsSubtreeChangeNotification(true); | |
49 setNeedsSubtreeChangeNotification(); | |
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 setNeedsSubtreeChangeNotification(); | |
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 containingBlock()->setPreferredLogicalWidthsDirty(); | |
ojan
2015/04/30 02:56:45
I'm not 100% sure, but I think you want to setPref
dsinclair
2015/04/30 17:52:29
Done. This was copied from the original code which
| |
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 render 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 render 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()->isBox() && !m_marker->isInside() && m_ma rker->inlineBoxWrapper()) { |
351 LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft(); | 323 LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft(); |
(...skipping 130 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) | 464 setNeedsSubtreeChangeNotification(); |
ojan
2015/04/30 02:56:45
Since we set this in the constructor, do we need t
dsinclair
2015/04/30 17:52:30
Good catch. Done.
| |
493 updateMarkerLocation(); | |
494 } | 465 } |
495 | 466 |
496 static LayoutListItem* previousOrNextItem(bool isListReversed, Node* list, Layou tListItem* item) | 467 static LayoutListItem* previousOrNextItem(bool isListReversed, Node* list, Layou tListItem* item) |
497 { | 468 { |
498 return isListReversed ? previousListItem(list, item) : nextListItem(list, it em); | 469 return isListReversed ? previousListItem(list, item) : nextListItem(list, it em); |
499 } | 470 } |
500 | 471 |
501 void LayoutListItem::updateListMarkerNumbers() | 472 void LayoutListItem::updateListMarkerNumbers() |
502 { | 473 { |
503 // If distribution recalc is needed, updateListMarkerNumber will be re-invok ed | 474 // 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. | 499 // assume that all the following ones have too. |
529 // This gives us the opportunity to stop here and avoid | 500 // This gives us the opportunity to stop here and avoid |
530 // marking the same nodes again. | 501 // marking the same nodes again. |
531 break; | 502 break; |
532 } | 503 } |
533 item->updateValue(); | 504 item->updateValue(); |
534 } | 505 } |
535 } | 506 } |
536 | 507 |
537 } // namespace blink | 508 } // namespace blink |
OLD | NEW |