Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(11)

Side by Side Diff: third_party/WebKit/Source/core/dom/Text.cpp

Issue 2450093005: Support display: contents for elements, first-line and first-letter pseudos. (Closed)
Patch Set: Rebased Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698