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 |