Chromium Code Reviews| 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 | 4 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights |
| 5 * reserved. | 5 * reserved. |
| 6 * | 6 * |
| 7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
| 8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
| 9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
| 10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
| (...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 parent.isLayoutTableCol() || parent.isFrameSet() || | 247 parent.isLayoutTableCol() || parent.isFrameSet() || |
| 248 parent.isFlexibleBox() || parent.isLayoutGrid() || parent.isSVGRoot() || | 248 parent.isFlexibleBox() || parent.isLayoutGrid() || parent.isSVGRoot() || |
| 249 parent.isSVGContainer() || parent.isSVGImage() || parent.isSVGShape()) { | 249 parent.isSVGContainer() || parent.isSVGImage() || parent.isSVGShape()) { |
| 250 return false; | 250 return false; |
| 251 } | 251 } |
| 252 return true; | 252 return true; |
| 253 } | 253 } |
| 254 | 254 |
| 255 bool Text::textLayoutObjectIsNeeded(const ComputedStyle& style, | 255 bool Text::textLayoutObjectIsNeeded(const ComputedStyle& style, |
| 256 const LayoutObject& parent) const { | 256 const LayoutObject& parent) const { |
| 257 const LayoutObject* prev = nullptr; | |
| 258 bool lookedForPrev = false; | |
| 259 | |
| 257 if (!parent.canHaveChildren()) | 260 if (!parent.canHaveChildren()) |
| 258 return false; | 261 return false; |
| 259 | 262 |
| 260 if (isEditingText()) | 263 if (isEditingText()) |
| 261 return true; | 264 return true; |
| 262 | 265 |
| 263 if (!length()) | 266 if (!length()) |
| 264 return false; | 267 return false; |
| 265 | 268 |
| 266 if (style.display() == EDisplay::None) | 269 if (style.display() == EDisplay::None) |
| 267 return false; | 270 return false; |
| 268 | 271 |
| 269 if (!containsOnlyWhitespace()) | 272 if (!containsOnlyWhitespace()) |
| 270 return true; | 273 return true; |
| 271 | 274 |
| 275 // We may have multiple text layout object siblings as part of a layout tree | |
| 276 // affected by display: contents. In the case we have something like: | |
| 277 // | |
| 278 // <div>Foo<div style="display: contents"> </div>Bar</div> | |
| 279 // | |
| 280 // We can't just bail out and don't create a text layout object for the | |
| 281 // whitespace text node inside the display: contents element. | |
| 282 // | |
| 283 // We can check whether our style parent or our previous light-tree sibling | |
| 284 // has display contents to to avoid doing the previous layout object lookup | |
|
rune
2017/01/27 13:09:23
double "to"
| |
| 285 // more than necessary. | |
| 286 if (style.display() == EDisplay::Contents || | |
| 287 (previousSibling() && previousSibling()->isElementNode() && | |
| 288 toElement(previousSibling())->hasDisplayContentsStyle())) { | |
| 289 prev = LayoutTreeBuilderTraversal::previousSiblingLayoutObject(*this); | |
| 290 lookedForPrev = true; | |
| 291 if (prev && prev->node() && prev->node()->isTextNode()) | |
|
rune
2017/01/27 13:09:23
Not strictly true if the previous sibling is also
emilio
2017/01/27 22:13:15
Right, I guess we could avoid creating it if the p
| |
| 292 return true; | |
| 293 } | |
| 294 | |
| 272 if (!canHaveWhitespaceChildren(parent)) | 295 if (!canHaveWhitespaceChildren(parent)) |
| 273 return false; | 296 return false; |
| 274 | 297 |
| 275 // pre-wrap in SVG never makes layoutObject. | 298 // pre-wrap in SVG never makes layoutObject. |
| 276 if (style.whiteSpace() == EWhiteSpace::kPreWrap && parent.isSVG()) | 299 if (style.whiteSpace() == EWhiteSpace::kPreWrap && parent.isSVG()) |
| 277 return false; | 300 return false; |
| 278 | 301 |
| 279 // pre/pre-wrap/pre-line always make layoutObjects. | 302 // pre/pre-wrap/pre-line always make layoutObjects. |
| 280 if (style.preserveNewline()) | 303 if (style.preserveNewline()) |
| 281 return true; | 304 return true; |
| 282 | 305 |
| 283 // childNeedsDistributionRecalc() here is rare, only happens JS calling | 306 // childNeedsDistributionRecalc() here is rare, only happens JS calling |
| 284 // surroundContents() etc. from DOMNodeInsertedIntoDocument etc. | 307 // surroundContents() etc. from DOMNodeInsertedIntoDocument etc. |
| 285 if (document().childNeedsDistributionRecalc()) | 308 if (document().childNeedsDistributionRecalc()) |
| 286 return true; | 309 return true; |
| 287 | 310 |
| 288 // Avoiding creation of a layoutObject for the text node is a non-essential | 311 // Avoiding creation of a layoutObject for the text node is a non-essential |
| 289 // memory optimization. So to avoid blowing up on very wide DOMs, we limit | 312 // memory optimization. So to avoid blowing up on very wide DOMs, we limit |
| 290 // the number of siblings to visit. | 313 // the number of siblings to visit. |
| 291 unsigned maxSiblingsToVisit = 50; | 314 unsigned maxSiblingsToVisit = 50; |
| 292 | 315 |
| 293 const LayoutObject* prev = | 316 if (!lookedForPrev) { |
| 294 LayoutTreeBuilderTraversal::previousSiblingLayoutObject( | 317 lookedForPrev = true; |
| 295 *this, maxSiblingsToVisit); | 318 prev = LayoutTreeBuilderTraversal::previousSiblingLayoutObject( |
| 319 *this, maxSiblingsToVisit); | |
| 320 } | |
| 321 | |
| 296 if (prev && prev->isBR()) // <span><br/> <br/></span> | 322 if (prev && prev->isBR()) // <span><br/> <br/></span> |
| 297 return false; | 323 return false; |
| 298 | 324 |
| 299 if (parent.isLayoutInline()) { | 325 if (parent.isLayoutInline()) { |
| 300 // <span><div/> <div/></span> | 326 // <span><div/> <div/></span> |
| 301 if (prev && !prev->isInline() && !prev->isOutOfFlowPositioned()) | 327 if (prev && !prev->isInline() && !prev->isOutOfFlowPositioned()) |
| 302 return false; | 328 return false; |
| 303 } else { | 329 } else { |
| 304 if (parent.isLayoutBlock() && !parent.childrenInline() && | 330 if (parent.isLayoutBlock() && !parent.childrenInline() && |
| 305 (!prev || !prev->isInline())) | 331 (!prev || !prev->isInline())) |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 342 if (isSVGText(this)) | 368 if (isSVGText(this)) |
| 343 return new LayoutSVGInlineText(this, dataImpl()); | 369 return new LayoutSVGInlineText(this, dataImpl()); |
| 344 | 370 |
| 345 if (style.hasTextCombine()) | 371 if (style.hasTextCombine()) |
| 346 return new LayoutTextCombine(this, dataImpl()); | 372 return new LayoutTextCombine(this, dataImpl()); |
| 347 | 373 |
| 348 return new LayoutText(this, dataImpl()); | 374 return new LayoutText(this, dataImpl()); |
| 349 } | 375 } |
| 350 | 376 |
| 351 void Text::attachLayoutTree(const AttachContext& context) { | 377 void Text::attachLayoutTree(const AttachContext& context) { |
| 352 if (ContainerNode* layoutParent = LayoutTreeBuilderTraversal::parent(*this)) { | 378 ContainerNode* styleParent = LayoutTreeBuilderTraversal::parent(*this); |
| 353 if (LayoutObject* parentLayoutObject = layoutParent->layoutObject()) { | 379 LayoutObject* parentLayoutObject = |
| 354 if (textLayoutObjectIsNeeded(*parentLayoutObject->style(), | 380 LayoutTreeBuilderTraversal::parentLayoutObject(*this); |
| 355 *parentLayoutObject)) | 381 |
| 356 LayoutTreeBuilderForText(*this, parentLayoutObject) | 382 if (styleParent && parentLayoutObject) { |
| 357 .createLayoutObject(); | 383 DCHECK(styleParent->computedStyle()); |
| 384 if (textLayoutObjectIsNeeded(*styleParent->computedStyle(), | |
| 385 *parentLayoutObject)) { | |
| 386 LayoutTreeBuilderForText(*this, parentLayoutObject, | |
| 387 styleParent->mutableComputedStyle()) | |
|
rune
2017/01/27 13:09:23
Using mutableComputedStyle() here looks worrying,
emilio
2017/01/27 22:13:15
Yes, I agree, though this was pre-existing (the pr
| |
| 388 .createLayoutObject(); | |
| 358 } | 389 } |
| 359 } | 390 } |
| 360 CharacterData::attachLayoutTree(context); | 391 CharacterData::attachLayoutTree(context); |
| 361 } | 392 } |
| 362 | 393 |
| 363 void Text::reattachLayoutTreeIfNeeded(const AttachContext& context) { | 394 void Text::reattachLayoutTreeIfNeeded(const AttachContext& context) { |
| 364 bool layoutObjectIsNeeded = false; | 395 bool layoutObjectIsNeeded = false; |
| 365 ContainerNode* layoutParent = LayoutTreeBuilderTraversal::parent(*this); | 396 ContainerNode* styleParent = LayoutTreeBuilderTraversal::parent(*this); |
| 366 if (layoutParent) { | 397 LayoutObject* parentLayoutObject = |
| 367 if (LayoutObject* parentLayoutObject = layoutParent->layoutObject()) { | 398 LayoutTreeBuilderTraversal::parentLayoutObject(*this); |
| 368 if (textLayoutObjectIsNeeded(*parentLayoutObject->style(), | 399 if (styleParent && parentLayoutObject) { |
| 369 *parentLayoutObject)) | 400 DCHECK(styleParent->computedStyle()); |
| 370 layoutObjectIsNeeded = true; | 401 layoutObjectIsNeeded = textLayoutObjectIsNeeded( |
| 371 } | 402 *styleParent->computedStyle(), *parentLayoutObject); |
| 372 } | 403 } |
| 373 | 404 |
| 374 if (layoutObjectIsNeeded == !!layoutObject()) | 405 if (layoutObjectIsNeeded == !!layoutObject()) |
| 375 return; | 406 return; |
| 376 | 407 |
| 377 // The following is almost the same as Node::reattachLayoutTree() except that | 408 // The following is almost the same as Node::reattachLayoutTree() except that |
| 378 // we create a layoutObject only if needed. Not calling reattachLayoutTree() | 409 // we create a layoutObject only if needed. Not calling reattachLayoutTree() |
| 379 // to avoid repeated calls to Text::textLayoutObjectIsNeeded(). | 410 // to avoid repeated calls to Text::textLayoutObjectIsNeeded(). |
| 380 AttachContext reattachContext(context); | 411 AttachContext reattachContext(context); |
| 381 reattachContext.performingReattach = true; | 412 reattachContext.performingReattach = true; |
| 382 | 413 |
| 383 if (getStyleChangeType() < NeedsReattachStyleChange) | 414 if (getStyleChangeType() < NeedsReattachStyleChange) |
| 384 detachLayoutTree(reattachContext); | 415 detachLayoutTree(reattachContext); |
| 385 if (layoutObjectIsNeeded) | 416 if (layoutObjectIsNeeded) { |
| 386 LayoutTreeBuilderForText(*this, layoutParent->layoutObject()) | 417 LayoutTreeBuilderForText(*this, parentLayoutObject, |
| 418 styleParent->mutableComputedStyle()) | |
| 387 .createLayoutObject(); | 419 .createLayoutObject(); |
| 420 } | |
| 388 CharacterData::attachLayoutTree(reattachContext); | 421 CharacterData::attachLayoutTree(reattachContext); |
| 389 } | 422 } |
| 390 | 423 |
| 391 void Text::recalcTextStyle(StyleRecalcChange change, Text* nextTextSibling) { | 424 void Text::recalcTextStyle(StyleRecalcChange change, Text* nextTextSibling) { |
| 392 if (LayoutTextItem layoutItem = LayoutTextItem(this->layoutObject())) { | 425 if (LayoutTextItem layoutItem = LayoutTextItem(this->layoutObject())) { |
| 393 if (change != NoChange || needsStyleRecalc()) | 426 if (change != NoChange || needsStyleRecalc()) |
| 394 layoutItem.setStyle(document().ensureStyleResolver().styleForText(this)); | 427 layoutItem.setStyle(document().ensureStyleResolver().styleForText(this)); |
| 395 if (needsStyleRecalc()) | 428 if (needsStyleRecalc()) |
| 396 layoutItem.setText(dataImpl()); | 429 layoutItem.setText(dataImpl()); |
| 397 clearNeedsStyleRecalc(); | 430 clearNeedsStyleRecalc(); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 449 | 482 |
| 450 Text* Text::cloneWithData(const String& data) { | 483 Text* Text::cloneWithData(const String& data) { |
| 451 return create(document(), data); | 484 return create(document(), data); |
| 452 } | 485 } |
| 453 | 486 |
| 454 DEFINE_TRACE(Text) { | 487 DEFINE_TRACE(Text) { |
| 455 CharacterData::trace(visitor); | 488 CharacterData::trace(visitor); |
| 456 } | 489 } |
| 457 | 490 |
| 458 } // namespace blink | 491 } // namespace blink |
| OLD | NEW |