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, 2007, 2008, 2009 Apple Inc. All rights
reserved. | 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights |
| 5 * reserved. |
5 * | 6 * |
6 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
7 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
8 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
9 * 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. |
10 * | 11 * |
11 * 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, |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 * Library General Public License for more details. | 15 * Library General Public License for more details. |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 result.append(toText(n)->data()); | 185 result.append(toText(n)->data()); |
185 } | 186 } |
186 DCHECK_EQ(result.length(), resultLength); | 187 DCHECK_EQ(result.length(), resultLength); |
187 | 188 |
188 return result.toString(); | 189 return result.toString(); |
189 } | 190 } |
190 | 191 |
191 Text* Text::replaceWholeText(const String& newText) { | 192 Text* Text::replaceWholeText(const String& newText) { |
192 // Remove all adjacent text nodes, and replace the contents of this one. | 193 // Remove all adjacent text nodes, and replace the contents of this one. |
193 | 194 |
194 // Protect startText and endText against mutation event handlers removing the
last ref | 195 // Protect startText and endText against mutation event handlers removing the |
| 196 // last ref |
195 Text* startText = const_cast<Text*>(earliestLogicallyAdjacentTextNode(this)); | 197 Text* startText = const_cast<Text*>(earliestLogicallyAdjacentTextNode(this)); |
196 Text* endText = const_cast<Text*>(latestLogicallyAdjacentTextNode(this)); | 198 Text* endText = const_cast<Text*>(latestLogicallyAdjacentTextNode(this)); |
197 | 199 |
198 ContainerNode* parent = | 200 ContainerNode* parent = parentNode(); // Protect against mutation handlers |
199 parentNode(); // Protect against mutation handlers moving this node durin
g traversal | 201 // moving this node during traversal |
200 for (Node* n = startText; | 202 for (Node* n = startText; |
201 n && n != this && n->isTextNode() && n->parentNode() == parent;) { | 203 n && n != this && n->isTextNode() && n->parentNode() == parent;) { |
202 Node* nodeToRemove = n; | 204 Node* nodeToRemove = n; |
203 n = nodeToRemove->nextSibling(); | 205 n = nodeToRemove->nextSibling(); |
204 parent->removeChild(nodeToRemove, IGNORE_EXCEPTION); | 206 parent->removeChild(nodeToRemove, IGNORE_EXCEPTION); |
205 } | 207 } |
206 | 208 |
207 if (this != endText) { | 209 if (this != endText) { |
208 Node* onePastEndText = endText->nextSibling(); | 210 Node* onePastEndText = endText->nextSibling(); |
209 for (Node* n = nextSibling(); n && n != onePastEndText && n->isTextNode() && | 211 for (Node* n = nextSibling(); n && n != onePastEndText && n->isTextNode() && |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 return false; | 274 return false; |
273 | 275 |
274 // pre-wrap in SVG never makes layoutObject. | 276 // pre-wrap in SVG never makes layoutObject. |
275 if (style.whiteSpace() == PRE_WRAP && parent.isSVG()) | 277 if (style.whiteSpace() == PRE_WRAP && parent.isSVG()) |
276 return false; | 278 return false; |
277 | 279 |
278 // pre/pre-wrap/pre-line always make layoutObjects. | 280 // pre/pre-wrap/pre-line always make layoutObjects. |
279 if (style.preserveNewline()) | 281 if (style.preserveNewline()) |
280 return true; | 282 return true; |
281 | 283 |
282 // childNeedsDistributionRecalc() here is rare, only happens JS calling surrou
ndContents() etc. from DOMNodeInsertedIntoDocument etc. | 284 // childNeedsDistributionRecalc() here is rare, only happens JS calling |
| 285 // surroundContents() etc. from DOMNodeInsertedIntoDocument etc. |
283 if (document().childNeedsDistributionRecalc()) | 286 if (document().childNeedsDistributionRecalc()) |
284 return true; | 287 return true; |
285 | 288 |
286 const LayoutObject* prev = | 289 const LayoutObject* prev = |
287 LayoutTreeBuilderTraversal::previousSiblingLayoutObject(*this); | 290 LayoutTreeBuilderTraversal::previousSiblingLayoutObject(*this); |
288 if (prev && prev->isBR()) // <span><br/> <br/></span> | 291 if (prev && prev->isBR()) // <span><br/> <br/></span> |
289 return false; | 292 return false; |
290 | 293 |
291 if (parent.isLayoutInline()) { | 294 if (parent.isLayoutInline()) { |
292 // <span><div/> <div/></span> | 295 // <span><div/> <div/></span> |
293 if (prev && !prev->isInline() && !prev->isOutOfFlowPositioned()) | 296 if (prev && !prev->isInline() && !prev->isOutOfFlowPositioned()) |
294 return false; | 297 return false; |
295 } else { | 298 } else { |
296 if (parent.isLayoutBlock() && !parent.childrenInline() && | 299 if (parent.isLayoutBlock() && !parent.childrenInline() && |
297 (!prev || !prev->isInline())) | 300 (!prev || !prev->isInline())) |
298 return false; | 301 return false; |
299 | 302 |
300 // Avoiding creation of a layoutObject for the text node is a non-essential
memory optimization. | 303 // Avoiding creation of a layoutObject for the text node is a non-essential |
301 // So to avoid blowing up on very wide DOMs, we limit the number of siblings
to visit. | 304 // memory optimization. So to avoid blowing up on very wide DOMs, we limit |
| 305 // the number of siblings to visit. |
302 unsigned maxSiblingsToVisit = 50; | 306 unsigned maxSiblingsToVisit = 50; |
303 | 307 |
304 LayoutObject* first = parent.slowFirstChild(); | 308 LayoutObject* first = parent.slowFirstChild(); |
305 while (first && first->isFloatingOrOutOfFlowPositioned() && | 309 while (first && first->isFloatingOrOutOfFlowPositioned() && |
306 maxSiblingsToVisit--) | 310 maxSiblingsToVisit--) |
307 first = first->nextSibling(); | 311 first = first->nextSibling(); |
308 if (!first || first == layoutObject() || | 312 if (!first || first == layoutObject() || |
309 LayoutTreeBuilderTraversal::nextSiblingLayoutObject(*this) == first) { | 313 LayoutTreeBuilderTraversal::nextSiblingLayoutObject(*this) == first) { |
310 // If we're adding children to this flow our previous siblings are not in
the layout tree yet so we | 314 // If we're adding children to this flow our previous siblings are not in |
311 // cannot know if we will be the first child in the line and collapse away
. We have to assume we need a layout object. | 315 // the layout tree yet so we cannot know if we will be the first child in |
| 316 // the line and collapse away. We have to assume we need a layout object. |
312 Node* firstChildNode = | 317 Node* firstChildNode = |
313 parent.node() ? LayoutTreeBuilderTraversal::firstChild(*parent.node()) | 318 parent.node() ? LayoutTreeBuilderTraversal::firstChild(*parent.node()) |
314 : nullptr; | 319 : nullptr; |
315 if (first && first == layoutObject() && firstChildNode && | 320 if (first && first == layoutObject() && firstChildNode && |
316 !firstChildNode->layoutObject()) | 321 !firstChildNode->layoutObject()) |
317 return true; | 322 return true; |
318 | 323 |
319 // Whitespace at the start of a block just goes away. Don't even | 324 // Whitespace at the start of a block just goes away. Don't even |
320 // make a layout object for this text. | 325 // make a layout object for this text. |
321 return !firstChildNode; | 326 return !firstChildNode; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
360 if (LayoutObject* parentLayoutObject = layoutParent->layoutObject()) { | 365 if (LayoutObject* parentLayoutObject = layoutParent->layoutObject()) { |
361 if (textLayoutObjectIsNeeded(*parentLayoutObject->style(), | 366 if (textLayoutObjectIsNeeded(*parentLayoutObject->style(), |
362 *parentLayoutObject)) | 367 *parentLayoutObject)) |
363 layoutObjectIsNeeded = true; | 368 layoutObjectIsNeeded = true; |
364 } | 369 } |
365 } | 370 } |
366 | 371 |
367 if (layoutObjectIsNeeded == !!layoutObject()) | 372 if (layoutObjectIsNeeded == !!layoutObject()) |
368 return; | 373 return; |
369 | 374 |
370 // The following is almost the same as Node::reattachLayoutTree() except that
we create a layoutObject only if needed. | 375 // The following is almost the same as Node::reattachLayoutTree() except that |
371 // Not calling reattachLayoutTree() to avoid repeated calls to Text::textLayou
tObjectIsNeeded(). | 376 // we create a layoutObject only if needed. Not calling reattachLayoutTree() |
| 377 // to avoid repeated calls to Text::textLayoutObjectIsNeeded(). |
372 AttachContext reattachContext(context); | 378 AttachContext reattachContext(context); |
373 reattachContext.performingReattach = true; | 379 reattachContext.performingReattach = true; |
374 | 380 |
375 if (getStyleChangeType() < NeedsReattachStyleChange) | 381 if (getStyleChangeType() < NeedsReattachStyleChange) |
376 detachLayoutTree(reattachContext); | 382 detachLayoutTree(reattachContext); |
377 if (layoutObjectIsNeeded) | 383 if (layoutObjectIsNeeded) |
378 LayoutTreeBuilderForText(*this, layoutParent->layoutObject()) | 384 LayoutTreeBuilderForText(*this, layoutParent->layoutObject()) |
379 .createLayoutObject(); | 385 .createLayoutObject(); |
380 CharacterData::attachLayoutTree(reattachContext); | 386 CharacterData::attachLayoutTree(reattachContext); |
381 } | 387 } |
382 | 388 |
383 void Text::recalcTextStyle(StyleRecalcChange change, Text* nextTextSibling) { | 389 void Text::recalcTextStyle(StyleRecalcChange change, Text* nextTextSibling) { |
384 if (LayoutTextItem layoutItem = LayoutTextItem(this->layoutObject())) { | 390 if (LayoutTextItem layoutItem = LayoutTextItem(this->layoutObject())) { |
385 if (change != NoChange || needsStyleRecalc()) | 391 if (change != NoChange || needsStyleRecalc()) |
386 layoutItem.setStyle(document().ensureStyleResolver().styleForText(this)); | 392 layoutItem.setStyle(document().ensureStyleResolver().styleForText(this)); |
387 if (needsStyleRecalc()) | 393 if (needsStyleRecalc()) |
388 layoutItem.setText(dataImpl()); | 394 layoutItem.setText(dataImpl()); |
389 clearNeedsStyleRecalc(); | 395 clearNeedsStyleRecalc(); |
390 } else if (needsStyleRecalc() || needsWhitespaceLayoutObject()) { | 396 } else if (needsStyleRecalc() || needsWhitespaceLayoutObject()) { |
391 reattachLayoutTree(); | 397 reattachLayoutTree(); |
392 if (this->layoutObject()) | 398 if (this->layoutObject()) |
393 reattachWhitespaceSiblingsIfNeeded(nextTextSibling); | 399 reattachWhitespaceSiblingsIfNeeded(nextTextSibling); |
394 } | 400 } |
395 } | 401 } |
396 | 402 |
397 // If a whitespace node had no layoutObject and goes through a recalcStyle it ma
y | 403 // If a whitespace node had no layoutObject and goes through a recalcStyle it |
398 // need to create one if the parent style now has white-space: pre. | 404 // may need to create one if the parent style now has white-space: pre. |
399 bool Text::needsWhitespaceLayoutObject() { | 405 bool Text::needsWhitespaceLayoutObject() { |
400 DCHECK(!layoutObject()); | 406 DCHECK(!layoutObject()); |
401 if (const ComputedStyle* style = parentComputedStyle()) | 407 if (const ComputedStyle* style = parentComputedStyle()) |
402 return style->preserveNewline(); | 408 return style->preserveNewline(); |
403 return false; | 409 return false; |
404 } | 410 } |
405 | 411 |
406 // Passing both |textNode| and its layout object because repeated calls to | 412 // Passing both |textNode| and its layout object because repeated calls to |
407 // |Node::layoutObject()| are discouraged. | 413 // |Node::layoutObject()| are discouraged. |
408 static bool shouldUpdateLayoutByReattaching(const Text& textNode, | 414 static bool shouldUpdateLayoutByReattaching(const Text& textNode, |
(...skipping 27 matching lines...) Expand all Loading... |
436 | 442 |
437 Text* Text::cloneWithData(const String& data) { | 443 Text* Text::cloneWithData(const String& data) { |
438 return create(document(), data); | 444 return create(document(), data); |
439 } | 445 } |
440 | 446 |
441 DEFINE_TRACE(Text) { | 447 DEFINE_TRACE(Text) { |
442 CharacterData::trace(visitor); | 448 CharacterData::trace(visitor); |
443 } | 449 } |
444 | 450 |
445 } // namespace blink | 451 } // namespace blink |
OLD | NEW |