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) |
43 , m_hasExplicitValue(false) | 45 , m_hasExplicitValue(false) |
44 , m_isValueUpToDate(false) | 46 , m_isValueUpToDate(false) |
45 , m_notInList(false) | 47 , m_notInList(false) |
46 { | 48 { |
47 setInline(false); | 49 setInline(false); |
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 |
56 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) | |
57 return; | |
58 | |
54 if (style()->listStyleType() != NoneListStyle | 59 if (style()->listStyleType() != NoneListStyle |
55 || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurr ed())) { | 60 || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurr ed())) { |
56 if (!m_marker) | 61 if (!m_marker) |
57 m_marker = LayoutListMarker::createAnonymous(this); | 62 m_marker = LayoutListMarker::createAnonymous(this); |
58 m_marker->listItemStyleDidChange(); | 63 m_marker->listItemStyleDidChange(); |
59 } else if (m_marker) { | 64 } else if (m_marker) { |
60 m_marker->destroy(); | 65 m_marker->destroy(); |
61 m_marker = nullptr; | 66 m_marker = nullptr; |
62 } | 67 } |
63 } | 68 } |
64 | 69 |
65 void LayoutListItem::willBeDestroyed() | 70 void LayoutListItem::willBeDestroyed() |
66 { | 71 { |
67 if (m_marker) { | 72 if (m_marker) { |
68 m_marker->destroy(); | 73 m_marker->destroy(); |
69 m_marker = nullptr; | 74 m_marker = nullptr; |
70 } | 75 } |
71 LayoutBlockFlow::willBeDestroyed(); | 76 LayoutBlockFlow::willBeDestroyed(); |
72 } | 77 } |
73 | 78 |
74 void LayoutListItem::insertedIntoTree() | 79 void LayoutListItem::insertedIntoTree() |
75 { | 80 { |
76 LayoutBlockFlow::insertedIntoTree(); | 81 LayoutBlockFlow::insertedIntoTree(); |
77 | |
78 updateListMarkerNumbers(); | 82 updateListMarkerNumbers(); |
79 } | 83 } |
80 | 84 |
81 void LayoutListItem::willBeRemovedFromTree() | 85 void LayoutListItem::willBeRemovedFromTree() |
82 { | 86 { |
83 LayoutBlockFlow::willBeRemovedFromTree(); | 87 LayoutBlockFlow::willBeRemovedFromTree(); |
88 updateListMarkerNumbers(); | |
89 } | |
84 | 90 |
85 updateListMarkerNumbers(); | 91 // FIXME: This causes subtree modifications, which will set the flags and we'll |
92 // end up doing the check a second time next frame .... | |
93 void LayoutListItem::handleSubtreeModifications() | |
94 { | |
95 if (documentBeingDestroyed()) | |
96 return; | |
97 | |
98 if (!notifyAncestorsOfSubtreeChange()) | |
esprehn
2015/04/22 07:45:46
The tree walk should handle this for you, not the
dsinclair
2015/04/22 20:00:39
Done.
| |
99 return; | |
100 | |
101 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) | |
esprehn
2015/04/22 07:45:46
Having the layout tree reach back into the DOM lik
dsinclair
2015/04/22 20:00:39
I'm not sure how to fix this one? The PseudoElemen
| |
102 toMarkerPseudoElement(element)->attachListMarkerLayoutObject(); | |
103 | |
104 LayoutBlockFlow::handleSubtreeModifications(); | |
esprehn
2015/04/22 07:45:46
tree walk should be external to the notification c
dsinclair
2015/04/22 20:00:39
Done.
| |
86 } | 105 } |
87 | 106 |
88 static bool isList(const Node& node) | 107 static bool isList(const Node& node) |
89 { | 108 { |
90 return isHTMLUListElement(node) || isHTMLOListElement(node); | 109 return isHTMLUListElement(node) || isHTMLOListElement(node); |
91 } | 110 } |
92 | 111 |
93 // Returns the enclosing list with respect to the DOM order. | 112 // Returns the enclosing list with respect to the DOM order. |
94 static Node* enclosingList(const LayoutListItem* listItem) | 113 static Node* enclosingList(const LayoutListItem* listItem) |
95 { | 114 { |
(...skipping 26 matching lines...) Expand all Loading... | |
122 ASSERT(!current->document().childNeedsDistributionRecalc()); | 141 ASSERT(!current->document().childNeedsDistributionRecalc()); |
123 current = LayoutTreeBuilderTraversal::next(*current, listNode); | 142 current = LayoutTreeBuilderTraversal::next(*current, listNode); |
124 | 143 |
125 while (current) { | 144 while (current) { |
126 if (isList(*current)) { | 145 if (isList(*current)) { |
127 // We've found a nested, independent list: nothing to do here. | 146 // We've found a nested, independent list: nothing to do here. |
128 current = LayoutTreeBuilderTraversal::nextSkippingChildren(*current, listNode); | 147 current = LayoutTreeBuilderTraversal::nextSkippingChildren(*current, listNode); |
129 continue; | 148 continue; |
130 } | 149 } |
131 | 150 |
132 LayoutObject* renderer = current->layoutObject(); | 151 LayoutObject* layoutObject = current->layoutObject(); |
133 if (renderer && renderer->isListItem()) | 152 if (layoutObject && layoutObject->isListItem()) |
134 return toLayoutListItem(renderer); | 153 return toLayoutListItem(layoutObject); |
135 | 154 |
136 // FIXME: Can this be optimized to skip the children of the elements wit hout a renderer? | 155 // FIXME: Can this be optimized to skip the children of the elements wit hout a layoutObject? |
137 current = LayoutTreeBuilderTraversal::next(*current, listNode); | 156 current = LayoutTreeBuilderTraversal::next(*current, listNode); |
138 } | 157 } |
139 | 158 |
140 return 0; | 159 return 0; |
141 } | 160 } |
142 | 161 |
143 // Returns the previous list item with respect to the DOM order. | 162 // Returns the previous list item with respect to the DOM order. |
144 static LayoutListItem* previousListItem(const Node* listNode, const LayoutListIt em* item) | 163 static LayoutListItem* previousListItem(const Node* listNode, const LayoutListIt em* item) |
145 { | 164 { |
146 Node* current = item->node(); | 165 Node* current = item->node(); |
147 ASSERT(current); | 166 ASSERT(current); |
148 ASSERT(!current->document().childNeedsDistributionRecalc()); | 167 ASSERT(!current->document().childNeedsDistributionRecalc()); |
149 for (current = LayoutTreeBuilderTraversal::previous(*current, listNode); cur rent && current != listNode; current = LayoutTreeBuilderTraversal::previous(*cur rent, listNode)) { | 168 for (current = LayoutTreeBuilderTraversal::previous(*current, listNode); |
150 LayoutObject* renderer = current->layoutObject(); | 169 current && current != listNode; |
151 if (!renderer || (renderer && !renderer->isListItem())) | 170 current = LayoutTreeBuilderTraversal::previous(*current, listNode)) { |
171 | |
172 LayoutObject* layoutObject = current->layoutObject(); | |
173 if (!layoutObject || (layoutObject && !layoutObject->isListItem())) | |
152 continue; | 174 continue; |
153 Node* otherList = enclosingList(toLayoutListItem(renderer)); | 175 Node* otherList = enclosingList(toLayoutListItem(layoutObject)); |
esprehn
2015/04/22 07:45:46
I'm really not sure all this is a code improvement
dsinclair
2015/04/22 20:00:39
Ack.
| |
154 // This item is part of our current list, so it's what we're looking for . | 176 // This item is part of our current list, so it's what we're looking for . |
155 if (listNode == otherList) | 177 if (listNode == otherList) |
156 return toLayoutListItem(renderer); | 178 return toLayoutListItem(layoutObject); |
157 // We found ourself inside another list; lets skip the rest of it. | 179 // We found ourself inside another list; lets skip the rest of it. |
158 // Use nextIncludingPseudo() here because the other list itself may actu ally | 180 // 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 | 181 // 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. | 182 // the previousIncludingPseudo() that will be done by the loop. |
161 if (otherList) | 183 if (otherList) |
162 current = LayoutTreeBuilderTraversal::next(*otherList, listNode); | 184 current = LayoutTreeBuilderTraversal::next(*otherList, listNode); |
163 } | 185 } |
164 return 0; | 186 return 0; |
165 } | 187 } |
166 | 188 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
206 } | 228 } |
207 | 229 |
208 void LayoutListItem::updateValueNow() const | 230 void LayoutListItem::updateValueNow() const |
209 { | 231 { |
210 m_value = calcValue(); | 232 m_value = calcValue(); |
211 m_isValueUpToDate = true; | 233 m_isValueUpToDate = true; |
212 } | 234 } |
213 | 235 |
214 bool LayoutListItem::isEmpty() const | 236 bool LayoutListItem::isEmpty() const |
215 { | 237 { |
238 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { | |
239 PseudoElement* element = toElement(node())->pseudoElement(MARKER); | |
240 return !(element && lastChild() != element->layoutObject()); | |
esprehn
2015/04/22 07:45:46
Run demorgans.
dsinclair
2015/04/22 20:00:39
Done.
| |
241 } | |
216 return lastChild() == m_marker; | 242 return lastChild() == m_marker; |
217 } | 243 } |
218 | 244 |
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() | 245 void LayoutListItem::updateValue() |
252 { | 246 { |
253 if (!m_hasExplicitValue) { | 247 if (m_hasExplicitValue) |
254 m_isValueUpToDate = false; | 248 return; |
255 if (m_marker) | 249 |
256 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( LayoutInvalidationReason::ListValueChange); | 250 m_isValueUpToDate = false; |
251 | |
252 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { | |
253 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) | |
254 element->layoutObject()->setNeedsLayoutAndPrefWidthsRecalcAndFullPai ntInvalidation(LayoutInvalidationReason::ListValueChange); | |
255 } else if (m_marker) { | |
256 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(Layo utInvalidationReason::ListValueChange); | |
257 } | 257 } |
258 } | 258 } |
259 | 259 |
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() | 260 void LayoutListItem::updateMarkerLocationAndInvalidateWidth() |
269 { | 261 { |
262 ASSERT(!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()); | |
270 ASSERT(m_marker); | 263 ASSERT(m_marker); |
271 | 264 |
272 // FIXME: We should not modify the structure of the render tree | 265 // FIXME: We should not modify the structure of the render tree |
273 // during layout. crbug.com/370461 | 266 // during layout. crbug.com/370461 |
274 DeprecatedDisableModifyRenderTreeStructureAsserts disabler; | 267 DeprecatedDisableModifyRenderTreeStructureAsserts disabler; |
275 LayoutState* layoutState = view()->layoutState(); | 268 LayoutState* layoutState = view()->layoutState(); |
276 LayoutFlowThread* currentFlowThread = nullptr; | 269 LayoutFlowThread* currentFlowThread = nullptr; |
277 if (layoutState) { | 270 if (layoutState) { |
278 // We're about to modify the layout tree structure (during layout!), and any code using | 271 // 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 | 272 // 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 | 273 // than the flow thread code will suffer, though, so just reset the curr ent flow thread |
281 // temporarily. | 274 // temporarily. |
282 // FIXME: get rid of this hack, including the flow thread setter in Layo utState, as part of | 275 // FIXME: get rid of this hack, including the flow thread setter in Layo utState, as part of |
283 // fixing crbug.com/370461 | 276 // fixing crbug.com/370461 |
284 currentFlowThread = layoutState->flowThread(); | 277 currentFlowThread = layoutState->flowThread(); |
285 layoutState->setFlowThread(nullptr); | 278 layoutState->setFlowThread(nullptr); |
286 } | 279 } |
287 if (updateMarkerLocation()) { | 280 if (updateMarkerLocation()) { |
288 // If the marker is inside we need to redo the preferred width calculati ons | 281 // 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. | 282 // as the size of the item now includes the size of the list marker. |
290 if (m_marker->isInside()) | 283 if (m_marker->isInside()) |
291 containingBlock()->updateLogicalWidth(); | 284 containingBlock()->updateLogicalWidth(); |
292 } | 285 } |
293 if (layoutState) | 286 if (layoutState) |
294 layoutState->setFlowThread(currentFlowThread); | 287 layoutState->setFlowThread(currentFlowThread); |
295 } | 288 } |
296 | 289 |
297 bool LayoutListItem::updateMarkerLocation() | 290 bool LayoutListItem::updateMarkerLocation() |
298 { | 291 { |
292 ASSERT(!RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()); | |
299 ASSERT(m_marker); | 293 ASSERT(m_marker); |
294 | |
300 LayoutObject* markerParent = m_marker->parent(); | 295 LayoutObject* markerParent = m_marker->parent(); |
301 LayoutObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker); | 296 LayoutObject* lineBoxParent = MarkerPseudoElement::parentOfFirstLineBox(this , m_marker); |
302 if (!lineBoxParent) { | 297 if (!lineBoxParent) { |
303 // If the marker is currently contained inside an anonymous box, then we | 298 // 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 | 299 // 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. | 300 // found). It's ok to just leave the marker where it is in this case. |
306 if (markerParent && markerParent->isAnonymousBlock()) | 301 if (markerParent && markerParent->isAnonymousBlock()) |
307 lineBoxParent = markerParent; | 302 lineBoxParent = markerParent; |
308 else | 303 else |
309 lineBoxParent = this; | 304 lineBoxParent = this; |
310 } | 305 } |
311 | 306 |
312 if (markerParent != lineBoxParent) { | 307 if (markerParent != lineBoxParent) { |
313 m_marker->remove(); | 308 m_marker->remove(); |
314 lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent)); | 309 lineBoxParent->addChild(m_marker, MarkerPseudoElement::firstNonMarkerChi ld(lineBoxParent)); |
315 m_marker->updateMarginsAndContent(); | 310 m_marker->updateMarginsAndContent(); |
316 // If markerParent is an anonymous block with no children, destroy it. | 311 // If markerParent is an anonymous block with no children, destroy it. |
317 if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(m arkerParent)->firstChild() && !toLayoutBlock(markerParent)->continuation()) | 312 if (markerParent && markerParent->isAnonymousBlock() && !toLayoutBlock(m arkerParent)->firstChild() |
313 && !toLayoutBlock(markerParent)->continuation()) | |
318 markerParent->destroy(); | 314 markerParent->destroy(); |
319 return true; | 315 return true; |
320 } | 316 } |
321 | 317 |
322 return false; | 318 return false; |
323 } | 319 } |
324 | 320 |
325 void LayoutListItem::layout() | 321 void LayoutListItem::layout() |
326 { | 322 { |
327 ASSERT(needsLayout()); | 323 ASSERT(needsLayout()); |
328 | 324 |
329 if (m_marker) { | 325 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
326 PseudoElement* element = toElement(node())->pseudoElement(MARKER); | |
esprehn
2015/04/22 07:45:46
I think you just want to keep m_marker, going out
dsinclair
2015/04/22 20:00:39
Done.
| |
327 if (element && element->layoutObject()) { | |
esprehn
2015/04/22 07:45:46
How does the element exist but not have a layoutOb
dsinclair
2015/04/22 20:00:39
Done.
| |
328 ASSERT(element->layoutObject()->isListMarker()); | |
329 LayoutListMarker* marker = toLayoutListMarker(element->layoutObject( )); | |
330 | |
331 marker->updateMarginsAndContent(); | |
332 } | |
333 | |
334 } else if (m_marker) { | |
330 // The marker must be autosized before calling | 335 // The marker must be autosized before calling |
331 // updateMarkerLocationAndInvalidateWidth. It cannot be done in the | 336 // updateMarkerLocationAndInvalidateWidth. It cannot be done in the |
332 // parent's beginLayout because it is not yet in the render tree. | 337 // parent's beginLayout because it is not yet in the render tree. |
333 if (TextAutosizer* textAutosizer = document().textAutosizer()) | 338 if (TextAutosizer* textAutosizer = document().textAutosizer()) |
334 textAutosizer->inflateListItem(this, m_marker); | 339 textAutosizer->inflateListItem(this, m_marker); |
335 | 340 |
336 updateMarkerLocationAndInvalidateWidth(); | 341 updateMarkerLocationAndInvalidateWidth(); |
337 } | 342 } |
338 | 343 |
339 LayoutBlockFlow::layout(); | 344 LayoutBlockFlow::layout(); |
340 } | 345 } |
341 | 346 |
342 void LayoutListItem::addOverflowFromChildren() | 347 void LayoutListItem::addOverflowFromChildren() |
343 { | 348 { |
344 LayoutBlockFlow::addOverflowFromChildren(); | 349 LayoutBlockFlow::addOverflowFromChildren(); |
345 positionListMarker(); | 350 |
351 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { | |
352 MarkerPseudoElement* markerElement = toMarkerPseudoElement(toElement(nod e())->pseudoElement(MARKER)); | |
esprehn
2015/04/22 07:45:46
I really think you want to keep m_marker and not d
dsinclair
2015/04/22 20:00:39
Done.
| |
353 if (markerElement && markerElement->layoutObject()) { | |
354 ASSERT(markerElement->layoutObject()->isListMarker()); | |
355 positionListMarker(toLayoutListMarker(markerElement->layoutObject()) ); | |
356 } | |
357 } else { | |
358 positionListMarker(m_marker); | |
359 } | |
346 } | 360 } |
347 | 361 |
348 void LayoutListItem::positionListMarker() | 362 void LayoutListItem::positionListMarker(LayoutListMarker* marker) |
349 { | 363 { |
350 if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_ma rker->inlineBoxWrapper()) { | 364 if (!marker) |
351 LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft(); | 365 return; |
366 | |
367 ASSERT(marker->parent()); | |
368 if (marker->parent()->isBox() && !marker->isInside() && marker->inlineBoxWra pper()) { | |
369 LayoutUnit markerOldLogicalLeft = marker->logicalLeft(); | |
352 LayoutUnit blockOffset = 0; | 370 LayoutUnit blockOffset = 0; |
353 LayoutUnit lineOffset = 0; | 371 LayoutUnit lineOffset = 0; |
354 for (LayoutBox* o = m_marker->parentBox(); o != this; o = o->parentBox() ) { | 372 for (LayoutBox* o = marker->parentBox(); o != this; o = o->parentBox()) { |
355 blockOffset += o->logicalTop(); | 373 blockOffset += o->logicalTop(); |
356 lineOffset += o->logicalLeft(); | 374 lineOffset += o->logicalLeft(); |
357 } | 375 } |
358 | 376 |
359 bool adjustOverflow = false; | 377 bool adjustOverflow = false; |
360 LayoutUnit markerLogicalLeft; | 378 LayoutUnit markerLogicalLeft; |
361 RootInlineBox& root = m_marker->inlineBoxWrapper()->root(); | 379 RootInlineBox& root = marker->inlineBoxWrapper()->root(); |
362 bool hitSelfPaintingLayer = false; | 380 bool hitSelfPaintingLayer = false; |
363 | 381 |
364 LayoutUnit lineTop = root.lineTop(); | 382 LayoutUnit lineTop = root.lineTop(); |
365 LayoutUnit lineBottom = root.lineBottom(); | 383 LayoutUnit lineBottom = root.lineBottom(); |
366 | 384 |
367 // FIXME: Need to account for relative positioning in the layout overflo w. | 385 // FIXME: Need to account for relative positioning in the layout overflo w. |
368 if (style()->isLeftToRightDirection()) { | 386 if (style()->isLeftToRightDirection()) { |
369 LayoutUnit leftLineOffset = logicalLeftOffsetForLine(blockOffset, lo gicalLeftOffsetForLine(blockOffset, false), false); | 387 LayoutUnit leftLineOffset = logicalLeftOffsetForLine(blockOffset, lo gicalLeftOffsetForLine(blockOffset, false), false); |
370 markerLogicalLeft = leftLineOffset - lineOffset - paddingStart() - b orderStart() + m_marker->marginStart(); | 388 markerLogicalLeft = leftLineOffset - lineOffset - paddingStart() - b orderStart() + marker->marginStart(); |
371 m_marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLog icalLeft - markerOldLogicalLeft).toFloat()); | 389 marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLogic alLeft - markerOldLogicalLeft).toFloat()); |
372 for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); bo x; box = box->parent()) { | 390 for (InlineFlowBox* box = marker->inlineBoxWrapper()->parent(); box; box = box->parent()) { |
373 LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOver flowRect(lineTop, lineBottom); | 391 LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOver flowRect(lineTop, lineBottom); |
374 LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOver flowRect(lineTop, lineBottom); | 392 LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOver flowRect(lineTop, lineBottom); |
375 if (markerLogicalLeft < newLogicalVisualOverflowRect.x() && !hit SelfPaintingLayer) { | 393 if (markerLogicalLeft < newLogicalVisualOverflowRect.x() && !hit SelfPaintingLayer) { |
376 newLogicalVisualOverflowRect.setWidth(newLogicalVisualOverfl owRect.maxX() - markerLogicalLeft); | 394 newLogicalVisualOverflowRect.setWidth(newLogicalVisualOverfl owRect.maxX() - markerLogicalLeft); |
377 newLogicalVisualOverflowRect.setX(markerLogicalLeft); | 395 newLogicalVisualOverflowRect.setX(markerLogicalLeft); |
378 if (box == root) | 396 if (box == root) |
379 adjustOverflow = true; | 397 adjustOverflow = true; |
380 } | 398 } |
381 if (markerLogicalLeft < newLogicalLayoutOverflowRect.x()) { | 399 if (markerLogicalLeft < newLogicalLayoutOverflowRect.x()) { |
382 newLogicalLayoutOverflowRect.setWidth(newLogicalLayoutOverfl owRect.maxX() - markerLogicalLeft); | 400 newLogicalLayoutOverflowRect.setWidth(newLogicalLayoutOverfl owRect.maxX() - markerLogicalLeft); |
383 newLogicalLayoutOverflowRect.setX(markerLogicalLeft); | 401 newLogicalLayoutOverflowRect.setX(markerLogicalLeft); |
384 if (box == root) | 402 if (box == root) |
385 adjustOverflow = true; | 403 adjustOverflow = true; |
386 } | 404 } |
387 box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, n ewLogicalVisualOverflowRect, lineTop, lineBottom); | 405 box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, n ewLogicalVisualOverflowRect, lineTop, lineBottom); |
388 if (box->boxModelObject()->hasSelfPaintingLayer()) | 406 if (box->boxModelObject()->hasSelfPaintingLayer()) |
389 hitSelfPaintingLayer = true; | 407 hitSelfPaintingLayer = true; |
390 } | 408 } |
391 } else { | 409 } else { |
392 LayoutUnit rightLineOffset = logicalRightOffsetForLine(blockOffset, logicalRightOffsetForLine(blockOffset, false), false); | 410 LayoutUnit rightLineOffset = logicalRightOffsetForLine(blockOffset, logicalRightOffsetForLine(blockOffset, false), false); |
393 markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + m_marker->marginEnd(); | 411 markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + marker->marginEnd(); |
394 m_marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLog icalLeft - markerOldLogicalLeft).toFloat()); | 412 marker->inlineBoxWrapper()->adjustLineDirectionPosition((markerLogic alLeft - markerOldLogicalLeft).toFloat()); |
395 for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); bo x; box = box->parent()) { | 413 for (InlineFlowBox* box = marker->inlineBoxWrapper()->parent(); box; box = box->parent()) { |
396 LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOver flowRect(lineTop, lineBottom); | 414 LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOver flowRect(lineTop, lineBottom); |
397 LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOver flowRect(lineTop, lineBottom); | 415 LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOver flowRect(lineTop, lineBottom); |
398 if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalVis ualOverflowRect.maxX() && !hitSelfPaintingLayer) { | 416 if (markerLogicalLeft + marker->logicalWidth() > newLogicalVisua lOverflowRect.maxX() && !hitSelfPaintingLayer) { |
399 newLogicalVisualOverflowRect.setWidth(markerLogicalLeft + m_ marker->logicalWidth() - newLogicalVisualOverflowRect.x()); | 417 newLogicalVisualOverflowRect.setWidth(markerLogicalLeft + ma rker->logicalWidth() - newLogicalVisualOverflowRect.x()); |
400 if (box == root) | 418 if (box == root) |
401 adjustOverflow = true; | 419 adjustOverflow = true; |
402 } | 420 } |
403 if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalLay outOverflowRect.maxX()) { | 421 if (markerLogicalLeft + marker->logicalWidth() > newLogicalLayou tOverflowRect.maxX()) { |
404 newLogicalLayoutOverflowRect.setWidth(markerLogicalLeft + m_ marker->logicalWidth() - newLogicalLayoutOverflowRect.x()); | 422 newLogicalLayoutOverflowRect.setWidth(markerLogicalLeft + ma rker->logicalWidth() - newLogicalLayoutOverflowRect.x()); |
405 if (box == root) | 423 if (box == root) |
406 adjustOverflow = true; | 424 adjustOverflow = true; |
407 } | 425 } |
408 box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, n ewLogicalVisualOverflowRect, lineTop, lineBottom); | 426 box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, n ewLogicalVisualOverflowRect, lineTop, lineBottom); |
409 | 427 |
410 if (box->boxModelObject()->hasSelfPaintingLayer()) | 428 if (box->boxModelObject()->hasSelfPaintingLayer()) |
411 hitSelfPaintingLayer = true; | 429 hitSelfPaintingLayer = true; |
412 } | 430 } |
413 } | 431 } |
414 | 432 |
415 if (adjustOverflow) { | 433 if (adjustOverflow) { |
416 LayoutRect markerRect(LayoutPoint(markerLogicalLeft + lineOffset, bl ockOffset), m_marker->size()); | 434 LayoutRect markerRect(LayoutPoint(markerLogicalLeft + lineOffset, bl ockOffset), marker->size()); |
417 if (!style()->isHorizontalWritingMode()) | 435 if (!style()->isHorizontalWritingMode()) |
418 markerRect = markerRect.transposedRect(); | 436 markerRect = markerRect.transposedRect(); |
419 LayoutBox* o = m_marker; | 437 LayoutBox* o = marker; |
420 bool propagateVisualOverflow = true; | 438 bool propagateVisualOverflow = true; |
421 bool propagateLayoutOverflow = true; | 439 bool propagateLayoutOverflow = true; |
422 do { | 440 do { |
423 o = o->parentBox(); | 441 o = o->parentBox(); |
424 if (o->isLayoutBlock()) { | 442 if (o->isLayoutBlock()) { |
425 if (propagateVisualOverflow) | 443 if (propagateVisualOverflow) |
426 toLayoutBlock(o)->addContentsVisualOverflow(markerRect); | 444 toLayoutBlock(o)->addContentsVisualOverflow(markerRect); |
427 if (propagateLayoutOverflow) | 445 if (propagateLayoutOverflow) |
428 toLayoutBlock(o)->addLayoutOverflow(markerRect); | 446 toLayoutBlock(o)->addLayoutOverflow(markerRect); |
429 } | 447 } |
(...skipping 12 matching lines...) Expand all Loading... | |
442 void LayoutListItem::paint(const PaintInfo& paintInfo, const LayoutPoint& paintO ffset) | 460 void LayoutListItem::paint(const PaintInfo& paintInfo, const LayoutPoint& paintO ffset) |
443 { | 461 { |
444 if (!logicalHeight() && hasOverflowClip()) | 462 if (!logicalHeight() && hasOverflowClip()) |
445 return; | 463 return; |
446 | 464 |
447 LayoutBlockFlow::paint(paintInfo, paintOffset); | 465 LayoutBlockFlow::paint(paintInfo, paintOffset); |
448 } | 466 } |
449 | 467 |
450 const String& LayoutListItem::markerText() const | 468 const String& LayoutListItem::markerText() const |
451 { | 469 { |
452 if (m_marker) | 470 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
471 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) { | |
472 if (element->layoutObject()) { | |
473 ASSERT(element->layoutObject()->isListMarker()); | |
474 return toLayoutListMarker(element->layoutObject())->text(); | |
esprehn
2015/04/22 07:45:45
ditto.
dsinclair
2015/04/22 20:00:39
Done.
| |
475 } | |
476 } | |
477 } else if (m_marker) { | |
453 return m_marker->text(); | 478 return m_marker->text(); |
479 } | |
454 return nullAtom.string(); | 480 return nullAtom.string(); |
455 } | 481 } |
456 | 482 |
457 void LayoutListItem::explicitValueChanged() | 483 void LayoutListItem::explicitValueChanged() |
458 { | 484 { |
459 if (m_marker) | 485 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
486 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) | |
487 element->layoutObject()->setNeedsLayoutAndPrefWidthsRecalcAndFullPai ntInvalidation(LayoutInvalidationReason::ListValueChange); | |
esprehn
2015/04/22 07:45:46
same.
dsinclair
2015/04/22 20:00:39
Done.
| |
488 } else if (m_marker) { | |
460 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(Layo utInvalidationReason::ListValueChange); | 489 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(Layo utInvalidationReason::ListValueChange); |
490 } | |
491 | |
461 Node* listNode = enclosingList(this); | 492 Node* listNode = enclosingList(this); |
462 for (LayoutListItem* item = this; item; item = nextListItem(listNode, item)) | 493 for (LayoutListItem* item = this; item; item = nextListItem(listNode, item)) |
463 item->updateValue(); | 494 item->updateValue(); |
464 } | 495 } |
465 | 496 |
466 void LayoutListItem::setExplicitValue(int value) | 497 void LayoutListItem::setExplicitValue(int value) |
467 { | 498 { |
468 ASSERT(node()); | 499 ASSERT(node()); |
469 | 500 |
470 if (m_hasExplicitValue && m_explicitValue == value) | 501 if (m_hasExplicitValue && m_explicitValue == value) |
(...skipping 11 matching lines...) Expand all Loading... | |
482 if (!m_hasExplicitValue) | 513 if (!m_hasExplicitValue) |
483 return; | 514 return; |
484 m_hasExplicitValue = false; | 515 m_hasExplicitValue = false; |
485 m_isValueUpToDate = false; | 516 m_isValueUpToDate = false; |
486 explicitValueChanged(); | 517 explicitValueChanged(); |
487 } | 518 } |
488 | 519 |
489 void LayoutListItem::setNotInList(bool notInList) | 520 void LayoutListItem::setNotInList(bool notInList) |
490 { | 521 { |
491 m_notInList = notInList; | 522 m_notInList = notInList; |
492 if (m_marker) | 523 if (RuntimeEnabledFeatures::listMarkerPseudoElementEnabled()) { |
524 if (PseudoElement* element = toElement(node())->pseudoElement(MARKER)) { | |
525 ASSERT(element->layoutObject()); | |
526 ASSERT(element->layoutObject()->isListMarker()); | |
527 toLayoutListMarker(element->layoutObject())->updateMarginsAndContent (); | |
esprehn
2015/04/22 07:45:46
ditto
dsinclair
2015/04/22 20:00:39
Done.
| |
528 } | |
529 } else if (m_marker) { | |
493 updateMarkerLocation(); | 530 updateMarkerLocation(); |
531 } | |
494 } | 532 } |
495 | 533 |
496 static LayoutListItem* previousOrNextItem(bool isListReversed, Node* list, Layou tListItem* item) | 534 static LayoutListItem* previousOrNextItem(bool isListReversed, Node* list, Layou tListItem* item) |
497 { | 535 { |
498 return isListReversed ? previousListItem(list, item) : nextListItem(list, it em); | 536 return isListReversed ? previousListItem(list, item) : nextListItem(list, it em); |
499 } | 537 } |
500 | 538 |
501 void LayoutListItem::updateListMarkerNumbers() | 539 void LayoutListItem::updateListMarkerNumbers() |
502 { | 540 { |
503 // If distribution recalc is needed, updateListMarkerNumber will be re-invok ed | 541 // 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. | 566 // assume that all the following ones have too. |
529 // This gives us the opportunity to stop here and avoid | 567 // This gives us the opportunity to stop here and avoid |
530 // marking the same nodes again. | 568 // marking the same nodes again. |
531 break; | 569 break; |
532 } | 570 } |
533 item->updateValue(); | 571 item->updateValue(); |
534 } | 572 } |
535 } | 573 } |
536 | 574 |
537 } // namespace blink | 575 } // namespace blink |
OLD | NEW |