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 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
245 | 245 |
246 if (parent.isTable() || parent.isTableRow() || parent.isTableSection() || | 246 if (parent.isTable() || parent.isTableRow() || parent.isTableSection() || |
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 static inline bool emptyOrEndsWithWhitespace(const WTF::String& string) { | |
256 unsigned len = string.length(); | |
257 return !len || isASCIISpace(string[len - 1]); | |
258 } | |
259 | |
255 bool Text::textLayoutObjectIsNeeded(const ComputedStyle& style, | 260 bool Text::textLayoutObjectIsNeeded(const ComputedStyle& style, |
256 const LayoutObject& parent) const { | 261 const LayoutObject& parent) const { |
257 DCHECK(!document().childNeedsDistributionRecalc()); | 262 DCHECK(!document().childNeedsDistributionRecalc()); |
258 | 263 |
259 if (!parent.canHaveChildren()) | 264 if (!parent.canHaveChildren()) |
260 return false; | 265 return false; |
261 | 266 |
262 if (isEditingText()) | 267 if (isEditingText()) |
263 return true; | 268 return true; |
264 | 269 |
(...skipping 13 matching lines...) Expand all Loading... | |
278 if (style.whiteSpace() == EWhiteSpace::kPreWrap && parent.isSVG()) | 283 if (style.whiteSpace() == EWhiteSpace::kPreWrap && parent.isSVG()) |
279 return false; | 284 return false; |
280 | 285 |
281 // pre/pre-wrap/pre-line always make layoutObjects. | 286 // pre/pre-wrap/pre-line always make layoutObjects. |
282 if (style.preserveNewline()) | 287 if (style.preserveNewline()) |
283 return true; | 288 return true; |
284 | 289 |
285 // Avoiding creation of a layoutObject for the text node is a non-essential | 290 // Avoiding creation of a layoutObject for the text node is a non-essential |
286 // memory optimization. So to avoid blowing up on very wide DOMs, we limit | 291 // memory optimization. So to avoid blowing up on very wide DOMs, we limit |
287 // the number of siblings to visit. | 292 // the number of siblings to visit. |
288 unsigned maxSiblingsToVisit = 50; | 293 uint32_t maxSiblingsToVisit = 50; |
rune
2017/02/27 10:38:06
Looks unnecessary to have a size-specific (32-bit)
| |
289 | 294 bool ranOutOfSiblings = false; |
290 const LayoutObject* prev = | 295 const LayoutObject* prev = |
291 LayoutTreeBuilderTraversal::previousSiblingLayoutObject( | 296 LayoutTreeBuilderTraversal::previousSiblingLayoutObject( |
292 *this, maxSiblingsToVisit); | 297 *this, maxSiblingsToVisit, &ranOutOfSiblings); |
rune
2017/02/27 10:38:06
Can't you send maxSiblingsToVisit as a non-const r
emilio
2017/02/27 12:09:32
That's right. I can, but that'd be somewhat annoyi
| |
293 if (prev && prev->isBR()) // <span><br/> <br/></span> | 298 |
299 while (prev && prev->isFloatingOrOutOfFlowPositioned() && | |
300 --maxSiblingsToVisit) { | |
301 prev = prev->previousSibling(); | |
302 } | |
303 | |
304 // If we give up due to too many siblings, just create a layout object. | |
305 if (ranOutOfSiblings || !maxSiblingsToVisit) | |
306 return true; | |
307 | |
308 // Collapse whitespace away if we find previous whitespace. | |
309 if (prev && prev->isText() && | |
310 emptyOrEndsWithWhitespace(toLayoutText(prev)->text())) { | |
rune
2017/02/27 10:38:06
Is checking the previous layout object for white-s
emilio
2017/02/27 12:09:32
Not totally sure about this, but it's likely. Actu
| |
311 return false; | |
312 } | |
313 | |
314 // Whitespace after a non-inline is useless. | |
315 if (prev && !prev->isInline()) | |
294 return false; | 316 return false; |
295 | 317 |
296 if (parent.isLayoutInline()) { | 318 // So it is after a <br> |
297 // <span><div/> <div/></span> | 319 if (prev && prev->isBR()) |
298 if (prev && !prev->isInline() && !prev->isOutOfFlowPositioned()) | 320 return false; |
299 return false; | |
300 } else { | |
301 if (parent.isLayoutBlock() && !parent.childrenInline() && | |
302 (!prev || !prev->isInline())) | |
303 return false; | |
304 | 321 |
305 LayoutObject* first = parent.slowFirstChild(); | 322 // It may matter if we're in an inline and we haven't proven otherwise though. |
306 for (; first && first->isFloatingOrOutOfFlowPositioned() && | 323 if (parent.isLayoutInline()) |
307 maxSiblingsToVisit; | 324 return true; |
308 first = first->nextSibling(), --maxSiblingsToVisit) { | |
309 } | |
310 if (!first || first == layoutObject() || | |
311 LayoutTreeBuilderTraversal::nextSiblingLayoutObject( | |
312 *this, maxSiblingsToVisit) == first) { | |
313 // If we're adding children to this flow our previous siblings are not in | |
314 // the layout tree yet so we cannot know if we will be the first child in | |
315 // the line and collapse away. We have to assume we need a layout object. | |
316 Node* firstChildNode = | |
317 parent.node() ? LayoutTreeBuilderTraversal::firstChild(*parent.node()) | |
318 : nullptr; | |
319 if (first && first == layoutObject() && firstChildNode && | |
320 !firstChildNode->layoutObject()) | |
321 return true; | |
322 | 325 |
323 // Whitespace at the start of a block just goes away. Don't even | 326 // Whitespace at the start of a block just goes away. |
324 // make a layout object for this text. | 327 return !!prev; |
rune
2017/02/27 10:38:06
We still re-attach right-to-left? That means we'll
emilio
2017/02/27 12:09:32
Yes, I believe that's right. I don't think it matt
| |
325 return !firstChildNode; | |
326 } | |
327 } | |
328 return true; | |
329 } | 328 } |
330 | 329 |
331 static bool isSVGText(Text* text) { | 330 static bool isSVGText(Text* text) { |
332 Node* parentOrShadowHostNode = text->parentOrShadowHostNode(); | 331 Node* parentOrShadowHostNode = text->parentOrShadowHostNode(); |
333 DCHECK(parentOrShadowHostNode); | 332 DCHECK(parentOrShadowHostNode); |
334 return parentOrShadowHostNode->isSVGElement() && | 333 return parentOrShadowHostNode->isSVGElement() && |
335 !isSVGForeignObjectElement(*parentOrShadowHostNode); | 334 !isSVGForeignObjectElement(*parentOrShadowHostNode); |
336 } | 335 } |
337 | 336 |
338 LayoutText* Text::createTextLayoutObject(const ComputedStyle& style) { | 337 LayoutText* Text::createTextLayoutObject(const ComputedStyle& style) { |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 | 466 |
468 Text* Text::cloneWithData(const String& data) { | 467 Text* Text::cloneWithData(const String& data) { |
469 return create(document(), data); | 468 return create(document(), data); |
470 } | 469 } |
471 | 470 |
472 DEFINE_TRACE(Text) { | 471 DEFINE_TRACE(Text) { |
473 CharacterData::trace(visitor); | 472 CharacterData::trace(visitor); |
474 } | 473 } |
475 | 474 |
476 } // namespace blink | 475 } // namespace blink |
OLD | NEW |