| 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 |