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/rendering/RenderListItem.h" | 25 #include "core/layout/LayoutListItem.h" |
26 | 26 |
27 #include "core/HTMLNames.h" | 27 #include "core/HTMLNames.h" |
28 #include "core/dom/NodeRenderingTraversal.h" | 28 #include "core/dom/NodeRenderingTraversal.h" |
29 #include "core/html/HTMLOListElement.h" | 29 #include "core/html/HTMLOListElement.h" |
| 30 #include "core/layout/LayoutListMarker.h" |
30 #include "core/layout/TextAutosizer.h" | 31 #include "core/layout/TextAutosizer.h" |
31 #include "core/rendering/RenderListMarker.h" | |
32 #include "core/rendering/RenderView.h" | 32 #include "core/rendering/RenderView.h" |
33 #include "wtf/StdLibExtras.h" | 33 #include "wtf/StdLibExtras.h" |
34 #include "wtf/text/StringBuilder.h" | 34 #include "wtf/text/StringBuilder.h" |
35 | 35 |
36 namespace blink { | 36 namespace blink { |
37 | 37 |
38 using namespace HTMLNames; | 38 using namespace HTMLNames; |
39 | 39 |
40 RenderListItem::RenderListItem(Element* element) | 40 LayoutListItem::LayoutListItem(Element* element) |
41 : RenderBlockFlow(element) | 41 : RenderBlockFlow(element) |
42 , m_marker(nullptr) | 42 , m_marker(nullptr) |
43 , m_hasExplicitValue(false) | 43 , m_hasExplicitValue(false) |
44 , m_isValueUpToDate(false) | 44 , m_isValueUpToDate(false) |
45 , m_notInList(false) | 45 , m_notInList(false) |
46 { | 46 { |
47 setInline(false); | 47 setInline(false); |
48 } | 48 } |
49 | 49 |
50 void RenderListItem::styleDidChange(StyleDifference diff, const LayoutStyle* old
Style) | 50 void LayoutListItem::styleDidChange(StyleDifference diff, const LayoutStyle* old
Style) |
51 { | 51 { |
52 RenderBlockFlow::styleDidChange(diff, oldStyle); | 52 RenderBlockFlow::styleDidChange(diff, oldStyle); |
53 | 53 |
54 if (style()->listStyleType() != NoneListStyle | 54 if (style()->listStyleType() != NoneListStyle |
55 || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurr
ed())) { | 55 || (style()->listStyleImage() && !style()->listStyleImage()->errorOccurr
ed())) { |
56 if (!m_marker) | 56 if (!m_marker) |
57 m_marker = RenderListMarker::createAnonymous(this); | 57 m_marker = LayoutListMarker::createAnonymous(this); |
58 m_marker->listItemStyleDidChange(); | 58 m_marker->listItemStyleDidChange(); |
59 } else if (m_marker) { | 59 } else if (m_marker) { |
60 m_marker->destroy(); | 60 m_marker->destroy(); |
61 m_marker = nullptr; | 61 m_marker = nullptr; |
62 } | 62 } |
63 } | 63 } |
64 | 64 |
65 void RenderListItem::willBeDestroyed() | 65 void LayoutListItem::willBeDestroyed() |
66 { | 66 { |
67 if (m_marker) { | 67 if (m_marker) { |
68 m_marker->destroy(); | 68 m_marker->destroy(); |
69 m_marker = nullptr; | 69 m_marker = nullptr; |
70 } | 70 } |
71 RenderBlockFlow::willBeDestroyed(); | 71 RenderBlockFlow::willBeDestroyed(); |
72 } | 72 } |
73 | 73 |
74 void RenderListItem::insertedIntoTree() | 74 void LayoutListItem::insertedIntoTree() |
75 { | 75 { |
76 RenderBlockFlow::insertedIntoTree(); | 76 RenderBlockFlow::insertedIntoTree(); |
77 | 77 |
78 updateListMarkerNumbers(); | 78 updateListMarkerNumbers(); |
79 } | 79 } |
80 | 80 |
81 void RenderListItem::willBeRemovedFromTree() | 81 void LayoutListItem::willBeRemovedFromTree() |
82 { | 82 { |
83 RenderBlockFlow::willBeRemovedFromTree(); | 83 RenderBlockFlow::willBeRemovedFromTree(); |
84 | 84 |
85 updateListMarkerNumbers(); | 85 updateListMarkerNumbers(); |
86 } | 86 } |
87 | 87 |
88 static bool isList(const Node& node) | 88 static bool isList(const Node& node) |
89 { | 89 { |
90 return isHTMLUListElement(node) || isHTMLOListElement(node); | 90 return isHTMLUListElement(node) || isHTMLOListElement(node); |
91 } | 91 } |
92 | 92 |
93 // Returns the enclosing list with respect to the DOM order. | 93 // Returns the enclosing list with respect to the DOM order. |
94 static Node* enclosingList(const RenderListItem* listItem) | 94 static Node* enclosingList(const LayoutListItem* listItem) |
95 { | 95 { |
96 Node* listItemNode = listItem->node(); | 96 Node* listItemNode = listItem->node(); |
97 if (!listItemNode) | 97 if (!listItemNode) |
98 return nullptr; | 98 return nullptr; |
99 Node* firstNode = nullptr; | 99 Node* firstNode = nullptr; |
100 // We use parentNode because the enclosing list could be a ShadowRoot that's
not Element. | 100 // We use parentNode because the enclosing list could be a ShadowRoot that's
not Element. |
101 for (Node* parent = NodeRenderingTraversal::parent(*listItemNode); parent; p
arent = NodeRenderingTraversal::parent(*parent)) { | 101 for (Node* parent = NodeRenderingTraversal::parent(*listItemNode); parent; p
arent = NodeRenderingTraversal::parent(*parent)) { |
102 if (isList(*parent)) | 102 if (isList(*parent)) |
103 return parent; | 103 return parent; |
104 if (!firstNode) | 104 if (!firstNode) |
105 firstNode = parent; | 105 firstNode = parent; |
106 } | 106 } |
107 | 107 |
108 // If there's no actual <ul> or <ol> list element, then the first found | 108 // If there's no actual <ul> or <ol> list element, then the first found |
109 // node acts as our list for purposes of determining what other list items | 109 // node acts as our list for purposes of determining what other list items |
110 // should be numbered as part of the same list. | 110 // should be numbered as part of the same list. |
111 return firstNode; | 111 return firstNode; |
112 } | 112 } |
113 | 113 |
114 // Returns the next list item with respect to the DOM order. | 114 // Returns the next list item with respect to the DOM order. |
115 static RenderListItem* nextListItem(const Node* listNode, const RenderListItem*
item = 0) | 115 static LayoutListItem* nextListItem(const Node* listNode, const LayoutListItem*
item = 0) |
116 { | 116 { |
117 if (!listNode) | 117 if (!listNode) |
118 return 0; | 118 return 0; |
119 | 119 |
120 const Node* current = item ? item->node() : listNode; | 120 const Node* current = item ? item->node() : listNode; |
121 ASSERT(current); | 121 ASSERT(current); |
122 ASSERT(!current->document().childNeedsDistributionRecalc()); | 122 ASSERT(!current->document().childNeedsDistributionRecalc()); |
123 current = NodeRenderingTraversal::next(*current, listNode); | 123 current = NodeRenderingTraversal::next(*current, listNode); |
124 | 124 |
125 while (current) { | 125 while (current) { |
126 if (isList(*current)) { | 126 if (isList(*current)) { |
127 // We've found a nested, independent list: nothing to do here. | 127 // We've found a nested, independent list: nothing to do here. |
128 current = NodeRenderingTraversal::nextSkippingChildren(*current, lis
tNode); | 128 current = NodeRenderingTraversal::nextSkippingChildren(*current, lis
tNode); |
129 continue; | 129 continue; |
130 } | 130 } |
131 | 131 |
132 LayoutObject* renderer = current->renderer(); | 132 LayoutObject* renderer = current->renderer(); |
133 if (renderer && renderer->isListItem()) | 133 if (renderer && renderer->isListItem()) |
134 return toRenderListItem(renderer); | 134 return toLayoutListItem(renderer); |
135 | 135 |
136 // FIXME: Can this be optimized to skip the children of the elements wit
hout a renderer? | 136 // FIXME: Can this be optimized to skip the children of the elements wit
hout a renderer? |
137 current = NodeRenderingTraversal::next(*current, listNode); | 137 current = NodeRenderingTraversal::next(*current, listNode); |
138 } | 138 } |
139 | 139 |
140 return 0; | 140 return 0; |
141 } | 141 } |
142 | 142 |
143 // Returns the previous list item with respect to the DOM order. | 143 // Returns the previous list item with respect to the DOM order. |
144 static RenderListItem* previousListItem(const Node* listNode, const RenderListIt
em* item) | 144 static LayoutListItem* previousListItem(const Node* listNode, const LayoutListIt
em* item) |
145 { | 145 { |
146 Node* current = item->node(); | 146 Node* current = item->node(); |
147 ASSERT(current); | 147 ASSERT(current); |
148 ASSERT(!current->document().childNeedsDistributionRecalc()); | 148 ASSERT(!current->document().childNeedsDistributionRecalc()); |
149 for (current = NodeRenderingTraversal::previous(*current, listNode); current
&& current != listNode; current = NodeRenderingTraversal::previous(*current, li
stNode)) { | 149 for (current = NodeRenderingTraversal::previous(*current, listNode); current
&& current != listNode; current = NodeRenderingTraversal::previous(*current, li
stNode)) { |
150 LayoutObject* renderer = current->renderer(); | 150 LayoutObject* renderer = current->renderer(); |
151 if (!renderer || (renderer && !renderer->isListItem())) | 151 if (!renderer || (renderer && !renderer->isListItem())) |
152 continue; | 152 continue; |
153 Node* otherList = enclosingList(toRenderListItem(renderer)); | 153 Node* otherList = enclosingList(toLayoutListItem(renderer)); |
154 // This item is part of our current list, so it's what we're looking for
. | 154 // This item is part of our current list, so it's what we're looking for
. |
155 if (listNode == otherList) | 155 if (listNode == otherList) |
156 return toRenderListItem(renderer); | 156 return toLayoutListItem(renderer); |
157 // We found ourself inside another list; lets skip the rest of it. | 157 // We found ourself inside another list; lets skip the rest of it. |
158 // Use nextIncludingPseudo() here because the other list itself may actu
ally | 158 // 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 | 159 // 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. | 160 // the previousIncludingPseudo() that will be done by the loop. |
161 if (otherList) | 161 if (otherList) |
162 current = NodeRenderingTraversal::next(*otherList, listNode); | 162 current = NodeRenderingTraversal::next(*otherList, listNode); |
163 } | 163 } |
164 return 0; | 164 return 0; |
165 } | 165 } |
166 | 166 |
167 void RenderListItem::updateItemValuesForOrderedList(const HTMLOListElement* list
Node) | 167 void LayoutListItem::updateItemValuesForOrderedList(const HTMLOListElement* list
Node) |
168 { | 168 { |
169 ASSERT(listNode); | 169 ASSERT(listNode); |
170 | 170 |
171 for (RenderListItem* listItem = nextListItem(listNode); listItem; listItem =
nextListItem(listNode, listItem)) | 171 for (LayoutListItem* listItem = nextListItem(listNode); listItem; listItem =
nextListItem(listNode, listItem)) |
172 listItem->updateValue(); | 172 listItem->updateValue(); |
173 } | 173 } |
174 | 174 |
175 unsigned RenderListItem::itemCountForOrderedList(const HTMLOListElement* listNod
e) | 175 unsigned LayoutListItem::itemCountForOrderedList(const HTMLOListElement* listNod
e) |
176 { | 176 { |
177 ASSERT(listNode); | 177 ASSERT(listNode); |
178 | 178 |
179 unsigned itemCount = 0; | 179 unsigned itemCount = 0; |
180 for (RenderListItem* listItem = nextListItem(listNode); listItem; listItem =
nextListItem(listNode, listItem)) | 180 for (LayoutListItem* listItem = nextListItem(listNode); listItem; listItem =
nextListItem(listNode, listItem)) |
181 itemCount++; | 181 itemCount++; |
182 | 182 |
183 return itemCount; | 183 return itemCount; |
184 } | 184 } |
185 | 185 |
186 inline int RenderListItem::calcValue() const | 186 inline int LayoutListItem::calcValue() const |
187 { | 187 { |
188 if (m_hasExplicitValue) | 188 if (m_hasExplicitValue) |
189 return m_explicitValue; | 189 return m_explicitValue; |
190 | 190 |
191 Node* list = enclosingList(this); | 191 Node* list = enclosingList(this); |
192 HTMLOListElement* oListElement = isHTMLOListElement(list) ? toHTMLOListEleme
nt(list) : 0; | 192 HTMLOListElement* oListElement = isHTMLOListElement(list) ? toHTMLOListEleme
nt(list) : 0; |
193 int valueStep = 1; | 193 int valueStep = 1; |
194 if (oListElement && oListElement->isReversed()) | 194 if (oListElement && oListElement->isReversed()) |
195 valueStep = -1; | 195 valueStep = -1; |
196 | 196 |
197 // FIXME: This recurses to a possible depth of the length of the list. | 197 // FIXME: This recurses to a possible depth of the length of the list. |
198 // That's not good -- we need to change this to an iterative algorithm. | 198 // That's not good -- we need to change this to an iterative algorithm. |
199 if (RenderListItem* previousItem = previousListItem(list, this)) | 199 if (LayoutListItem* previousItem = previousListItem(list, this)) |
200 return previousItem->value() + valueStep; | 200 return previousItem->value() + valueStep; |
201 | 201 |
202 if (oListElement) | 202 if (oListElement) |
203 return oListElement->start(); | 203 return oListElement->start(); |
204 | 204 |
205 return 1; | 205 return 1; |
206 } | 206 } |
207 | 207 |
208 void RenderListItem::updateValueNow() const | 208 void LayoutListItem::updateValueNow() const |
209 { | 209 { |
210 m_value = calcValue(); | 210 m_value = calcValue(); |
211 m_isValueUpToDate = true; | 211 m_isValueUpToDate = true; |
212 } | 212 } |
213 | 213 |
214 bool RenderListItem::isEmpty() const | 214 bool LayoutListItem::isEmpty() const |
215 { | 215 { |
216 return lastChild() == m_marker; | 216 return lastChild() == m_marker; |
217 } | 217 } |
218 | 218 |
219 static LayoutObject* getParentOfFirstLineBox(RenderBlockFlow* curr, LayoutObject
* marker) | 219 static LayoutObject* getParentOfFirstLineBox(RenderBlockFlow* curr, LayoutObject
* marker) |
220 { | 220 { |
221 LayoutObject* firstChild = curr->firstChild(); | 221 LayoutObject* firstChild = curr->firstChild(); |
222 if (!firstChild) | 222 if (!firstChild) |
223 return 0; | 223 return 0; |
224 | 224 |
225 bool inQuirksMode = curr->document().inQuirksMode(); | 225 bool inQuirksMode = curr->document().inQuirksMode(); |
226 for (LayoutObject* currChild = firstChild; currChild; currChild = currChild-
>nextSibling()) { | 226 for (LayoutObject* currChild = firstChild; currChild; currChild = currChild-
>nextSibling()) { |
227 if (currChild == marker) | 227 if (currChild == marker) |
228 continue; | 228 continue; |
229 | 229 |
230 if (currChild->isInline() && (!currChild->isRenderInline() || curr->gene
ratesLineBoxesForInlineChild(currChild))) | 230 if (currChild->isInline() && (!currChild->isRenderInline() || curr->gene
ratesLineBoxesForInlineChild(currChild))) |
231 return curr; | 231 return curr; |
232 | 232 |
233 if (currChild->isFloating() || currChild->isOutOfFlowPositioned()) | 233 if (currChild->isFloating() || currChild->isOutOfFlowPositioned()) |
234 continue; | 234 continue; |
235 | 235 |
236 if (!currChild->isRenderBlockFlow() || (currChild->isBox() && toRenderBo
x(currChild)->isWritingModeRoot())) | 236 if (!currChild->isRenderBlockFlow() || (currChild->isBox() && toRenderBo
x(currChild)->isWritingModeRoot())) |
237 break; | 237 break; |
238 | 238 |
239 if (curr->isListItem() && inQuirksMode && currChild->node() && | 239 if (curr->isListItem() && inQuirksMode && currChild->node() |
240 (isHTMLUListElement(*currChild->node()) || isHTMLOListElement(*currC
hild->node()))) | 240 && (isHTMLUListElement(*currChild->node()) || isHTMLOListElement(*cu
rrChild->node()))) |
241 break; | 241 break; |
242 | 242 |
243 LayoutObject* lineBox = getParentOfFirstLineBox(toRenderBlockFlow(currCh
ild), marker); | 243 LayoutObject* lineBox = getParentOfFirstLineBox(toRenderBlockFlow(currCh
ild), marker); |
244 if (lineBox) | 244 if (lineBox) |
245 return lineBox; | 245 return lineBox; |
246 } | 246 } |
247 | 247 |
248 return 0; | 248 return 0; |
249 } | 249 } |
250 | 250 |
251 void RenderListItem::updateValue() | 251 void LayoutListItem::updateValue() |
252 { | 252 { |
253 if (!m_hasExplicitValue) { | 253 if (!m_hasExplicitValue) { |
254 m_isValueUpToDate = false; | 254 m_isValueUpToDate = false; |
255 if (m_marker) | 255 if (m_marker) |
256 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
); | 256 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(
); |
257 } | 257 } |
258 } | 258 } |
259 | 259 |
260 static LayoutObject* firstNonMarkerChild(LayoutObject* parent) | 260 static LayoutObject* firstNonMarkerChild(LayoutObject* parent) |
261 { | 261 { |
262 LayoutObject* result = parent->slowFirstChild(); | 262 LayoutObject* result = parent->slowFirstChild(); |
263 while (result && result->isListMarker()) | 263 while (result && result->isListMarker()) |
264 result = result->nextSibling(); | 264 result = result->nextSibling(); |
265 return result; | 265 return result; |
266 } | 266 } |
267 | 267 |
268 void RenderListItem::updateMarkerLocationAndInvalidateWidth() | 268 void LayoutListItem::updateMarkerLocationAndInvalidateWidth() |
269 { | 269 { |
270 ASSERT(m_marker); | 270 ASSERT(m_marker); |
271 | 271 |
272 // FIXME: We should not modify the structure of the render tree | 272 // FIXME: We should not modify the structure of the render tree |
273 // during layout. crbug.com/370461 | 273 // during layout. crbug.com/370461 |
274 DeprecatedDisableModifyRenderTreeStructureAsserts disabler; | 274 DeprecatedDisableModifyRenderTreeStructureAsserts disabler; |
275 if (updateMarkerLocation()) { | 275 if (updateMarkerLocation()) { |
276 // If the marker is inside we need to redo the preferred width calculati
ons | 276 // If the marker is inside we need to redo the preferred width calculati
ons |
277 // as the size of the item now includes the size of the list marker. | 277 // as the size of the item now includes the size of the list marker. |
278 if (m_marker->isInside()) | 278 if (m_marker->isInside()) |
279 containingBlock()->updateLogicalWidth(); | 279 containingBlock()->updateLogicalWidth(); |
280 } | 280 } |
281 } | 281 } |
282 | 282 |
283 bool RenderListItem::updateMarkerLocation() | 283 bool LayoutListItem::updateMarkerLocation() |
284 { | 284 { |
285 ASSERT(m_marker); | 285 ASSERT(m_marker); |
286 LayoutObject* markerParent = m_marker->parent(); | 286 LayoutObject* markerParent = m_marker->parent(); |
287 LayoutObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker); | 287 LayoutObject* lineBoxParent = getParentOfFirstLineBox(this, m_marker); |
288 if (!lineBoxParent) { | 288 if (!lineBoxParent) { |
289 // If the marker is currently contained inside an anonymous box, then we | 289 // If the marker is currently contained inside an anonymous box, then we |
290 // are the only item in that anonymous box (since no line box parent was | 290 // are the only item in that anonymous box (since no line box parent was |
291 // found). It's ok to just leave the marker where it is in this case. | 291 // found). It's ok to just leave the marker where it is in this case. |
292 if (markerParent && markerParent->isAnonymousBlock()) | 292 if (markerParent && markerParent->isAnonymousBlock()) |
293 lineBoxParent = markerParent; | 293 lineBoxParent = markerParent; |
294 else | 294 else |
295 lineBoxParent = this; | 295 lineBoxParent = this; |
296 } | 296 } |
297 | 297 |
298 if (markerParent != lineBoxParent) { | 298 if (markerParent != lineBoxParent) { |
299 m_marker->remove(); | 299 m_marker->remove(); |
300 lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent)); | 300 lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent)); |
301 m_marker->updateMarginsAndContent(); | 301 m_marker->updateMarginsAndContent(); |
302 // If markerParent is an anonymous block with no children, destroy it. | 302 // If markerParent is an anonymous block with no children, destroy it. |
303 if (markerParent && markerParent->isAnonymousBlock() && !toRenderBlock(m
arkerParent)->firstChild() && !toRenderBlock(markerParent)->continuation()) | 303 if (markerParent && markerParent->isAnonymousBlock() && !toRenderBlock(m
arkerParent)->firstChild() && !toRenderBlock(markerParent)->continuation()) |
304 markerParent->destroy(); | 304 markerParent->destroy(); |
305 return true; | 305 return true; |
306 } | 306 } |
307 | 307 |
308 return false; | 308 return false; |
309 } | 309 } |
310 | 310 |
311 void RenderListItem::layout() | 311 void LayoutListItem::layout() |
312 { | 312 { |
313 ASSERT(needsLayout()); | 313 ASSERT(needsLayout()); |
314 | 314 |
315 if (m_marker) { | 315 if (m_marker) { |
316 // The marker must be autosized before calling | 316 // The marker must be autosized before calling |
317 // updateMarkerLocationAndInvalidateWidth. It cannot be done in the | 317 // updateMarkerLocationAndInvalidateWidth. It cannot be done in the |
318 // parent's beginLayout because it is not yet in the render tree. | 318 // parent's beginLayout because it is not yet in the render tree. |
319 if (TextAutosizer* textAutosizer = document().textAutosizer()) | 319 if (TextAutosizer* textAutosizer = document().textAutosizer()) |
320 textAutosizer->inflateListItem(this, m_marker); | 320 textAutosizer->inflateListItem(this, m_marker); |
321 | 321 |
322 updateMarkerLocationAndInvalidateWidth(); | 322 updateMarkerLocationAndInvalidateWidth(); |
323 } | 323 } |
324 | 324 |
325 RenderBlockFlow::layout(); | 325 RenderBlockFlow::layout(); |
326 } | 326 } |
327 | 327 |
328 void RenderListItem::addOverflowFromChildren() | 328 void LayoutListItem::addOverflowFromChildren() |
329 { | 329 { |
330 RenderBlockFlow::addOverflowFromChildren(); | 330 RenderBlockFlow::addOverflowFromChildren(); |
331 positionListMarker(); | 331 positionListMarker(); |
332 } | 332 } |
333 | 333 |
334 void RenderListItem::positionListMarker() | 334 void LayoutListItem::positionListMarker() |
335 { | 335 { |
336 if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_ma
rker->inlineBoxWrapper()) { | 336 if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_ma
rker->inlineBoxWrapper()) { |
337 LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft(); | 337 LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft(); |
338 LayoutUnit blockOffset = 0; | 338 LayoutUnit blockOffset = 0; |
339 LayoutUnit lineOffset = 0; | 339 LayoutUnit lineOffset = 0; |
340 for (RenderBox* o = m_marker->parentBox(); o != this; o = o->parentBox()
) { | 340 for (RenderBox* o = m_marker->parentBox(); o != this; o = o->parentBox()
) { |
341 blockOffset += o->logicalTop(); | 341 blockOffset += o->logicalTop(); |
342 lineOffset += o->logicalLeft(); | 342 lineOffset += o->logicalLeft(); |
343 } | 343 } |
344 | 344 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 propagateVisualOverflow = false; | 418 propagateVisualOverflow = false; |
419 } | 419 } |
420 if (o->hasSelfPaintingLayer()) | 420 if (o->hasSelfPaintingLayer()) |
421 propagateVisualOverflow = false; | 421 propagateVisualOverflow = false; |
422 markerRect.moveBy(-o->location()); | 422 markerRect.moveBy(-o->location()); |
423 } while (o != this && propagateVisualOverflow && propagateLayoutOver
flow); | 423 } while (o != this && propagateVisualOverflow && propagateLayoutOver
flow); |
424 } | 424 } |
425 } | 425 } |
426 } | 426 } |
427 | 427 |
428 void RenderListItem::paint(const PaintInfo& paintInfo, const LayoutPoint& paintO
ffset) | 428 void LayoutListItem::paint(const PaintInfo& paintInfo, const LayoutPoint& paintO
ffset) |
429 { | 429 { |
430 if (!logicalHeight() && hasOverflowClip()) | 430 if (!logicalHeight() && hasOverflowClip()) |
431 return; | 431 return; |
432 | 432 |
433 RenderBlockFlow::paint(paintInfo, paintOffset); | 433 RenderBlockFlow::paint(paintInfo, paintOffset); |
434 } | 434 } |
435 | 435 |
436 const String& RenderListItem::markerText() const | 436 const String& LayoutListItem::markerText() const |
437 { | 437 { |
438 if (m_marker) | 438 if (m_marker) |
439 return m_marker->text(); | 439 return m_marker->text(); |
440 return nullAtom.string(); | 440 return nullAtom.string(); |
441 } | 441 } |
442 | 442 |
443 void RenderListItem::explicitValueChanged() | 443 void LayoutListItem::explicitValueChanged() |
444 { | 444 { |
445 if (m_marker) | 445 if (m_marker) |
446 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); | 446 m_marker->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); |
447 Node* listNode = enclosingList(this); | 447 Node* listNode = enclosingList(this); |
448 for (RenderListItem* item = this; item; item = nextListItem(listNode, item)) | 448 for (LayoutListItem* item = this; item; item = nextListItem(listNode, item)) |
449 item->updateValue(); | 449 item->updateValue(); |
450 } | 450 } |
451 | 451 |
452 void RenderListItem::setExplicitValue(int value) | 452 void LayoutListItem::setExplicitValue(int value) |
453 { | 453 { |
454 ASSERT(node()); | 454 ASSERT(node()); |
455 | 455 |
456 if (m_hasExplicitValue && m_explicitValue == value) | 456 if (m_hasExplicitValue && m_explicitValue == value) |
457 return; | 457 return; |
458 m_explicitValue = value; | 458 m_explicitValue = value; |
459 m_value = value; | 459 m_value = value; |
460 m_hasExplicitValue = true; | 460 m_hasExplicitValue = true; |
461 explicitValueChanged(); | 461 explicitValueChanged(); |
462 } | 462 } |
463 | 463 |
464 void RenderListItem::clearExplicitValue() | 464 void LayoutListItem::clearExplicitValue() |
465 { | 465 { |
466 ASSERT(node()); | 466 ASSERT(node()); |
467 | 467 |
468 if (!m_hasExplicitValue) | 468 if (!m_hasExplicitValue) |
469 return; | 469 return; |
470 m_hasExplicitValue = false; | 470 m_hasExplicitValue = false; |
471 m_isValueUpToDate = false; | 471 m_isValueUpToDate = false; |
472 explicitValueChanged(); | 472 explicitValueChanged(); |
473 } | 473 } |
474 | 474 |
475 void RenderListItem::setNotInList(bool notInList) | 475 void LayoutListItem::setNotInList(bool notInList) |
476 { | 476 { |
477 m_notInList = notInList; | 477 m_notInList = notInList; |
478 if (m_marker) | 478 if (m_marker) |
479 updateMarkerLocation(); | 479 updateMarkerLocation(); |
480 } | 480 } |
481 | 481 |
482 static RenderListItem* previousOrNextItem(bool isListReversed, Node* list, Rende
rListItem* item) | 482 static LayoutListItem* previousOrNextItem(bool isListReversed, Node* list, Layou
tListItem* item) |
483 { | 483 { |
484 return isListReversed ? previousListItem(list, item) : nextListItem(list, it
em); | 484 return isListReversed ? previousListItem(list, item) : nextListItem(list, it
em); |
485 } | 485 } |
486 | 486 |
487 void RenderListItem::updateListMarkerNumbers() | 487 void LayoutListItem::updateListMarkerNumbers() |
488 { | 488 { |
489 // If distribution recalc is needed, updateListMarkerNumber will be re-invok
ed | 489 // If distribution recalc is needed, updateListMarkerNumber will be re-invok
ed |
490 // after distribution is calculated. | 490 // after distribution is calculated. |
491 if (node()->document().childNeedsDistributionRecalc()) | 491 if (node()->document().childNeedsDistributionRecalc()) |
492 return; | 492 return; |
493 | 493 |
494 Node* listNode = enclosingList(this); | 494 Node* listNode = enclosingList(this); |
495 ASSERT(listNode); | 495 ASSERT(listNode); |
496 | 496 |
497 bool isListReversed = false; | 497 bool isListReversed = false; |
498 HTMLOListElement* oListElement = isHTMLOListElement(listNode) ? toHTMLOListE
lement(listNode) : 0; | 498 HTMLOListElement* oListElement = isHTMLOListElement(listNode) ? toHTMLOListE
lement(listNode) : 0; |
499 if (oListElement) { | 499 if (oListElement) { |
500 oListElement->itemCountChanged(); | 500 oListElement->itemCountChanged(); |
501 isListReversed = oListElement->isReversed(); | 501 isListReversed = oListElement->isReversed(); |
502 } | 502 } |
503 | 503 |
504 // FIXME: The n^2 protection below doesn't help if the elements were inserte
d after the | 504 // FIXME: The n^2 protection below doesn't help if the elements were inserte
d after the |
505 // the list had already been displayed. | 505 // the list had already been displayed. |
506 | 506 |
507 // Avoid an O(n^2) walk over the children below when they're all known to be
attaching. | 507 // Avoid an O(n^2) walk over the children below when they're all known to be
attaching. |
508 if (listNode->needsAttach()) | 508 if (listNode->needsAttach()) |
509 return; | 509 return; |
510 | 510 |
511 for (RenderListItem* item = previousOrNextItem(isListReversed, listNode, thi
s); item; item = previousOrNextItem(isListReversed, listNode, item)) { | 511 for (LayoutListItem* item = previousOrNextItem(isListReversed, listNode, thi
s); item; item = previousOrNextItem(isListReversed, listNode, item)) { |
512 if (!item->m_isValueUpToDate) { | 512 if (!item->m_isValueUpToDate) { |
513 // If an item has been marked for update before, we can safely | 513 // If an item has been marked for update before, we can safely |
514 // assume that all the following ones have too. | 514 // assume that all the following ones have too. |
515 // This gives us the opportunity to stop here and avoid | 515 // This gives us the opportunity to stop here and avoid |
516 // marking the same nodes again. | 516 // marking the same nodes again. |
517 break; | 517 break; |
518 } | 518 } |
519 item->updateValue(); | 519 item->updateValue(); |
520 } | 520 } |
521 } | 521 } |
522 | 522 |
523 } // namespace blink | 523 } // namespace blink |
OLD | NEW |