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. |
5 * All rights 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
50 }; | 51 }; |
51 | 52 |
52 static_assert(sizeof(LayoutInline) == sizeof(SameSizeAsLayoutInline), | 53 static_assert(sizeof(LayoutInline) == sizeof(SameSizeAsLayoutInline), |
53 "LayoutInline should stay small"); | 54 "LayoutInline should stay small"); |
54 | 55 |
55 LayoutInline::LayoutInline(Element* element) : LayoutBoxModelObject(element) { | 56 LayoutInline::LayoutInline(Element* element) : LayoutBoxModelObject(element) { |
56 setChildrenInline(true); | 57 setChildrenInline(true); |
57 } | 58 } |
58 | 59 |
59 void LayoutInline::willBeDestroyed() { | 60 void LayoutInline::willBeDestroyed() { |
60 // Make sure to destroy anonymous children first while they are still connecte d to the rest of the tree, so that they will | 61 // Make sure to destroy anonymous children first while they are still |
61 // properly dirty line boxes that they are removed from. Effects that do :bef ore/:after only on hover could crash otherwise. | 62 // connected to the rest of the tree, so that they will properly dirty line |
63 // boxes that they are removed from. Effects that do :before/:after only on | |
64 // hover could crash otherwise. | |
62 children()->destroyLeftoverChildren(); | 65 children()->destroyLeftoverChildren(); |
63 | 66 |
64 // Destroy our continuation before anything other than anonymous children. | 67 // Destroy our continuation before anything other than anonymous children. |
65 // The reason we don't destroy it before anonymous children is that they may | 68 // The reason we don't destroy it before anonymous children is that they may |
66 // have continuations of their own that are anonymous children of our continua tion. | 69 // have continuations of their own that are anonymous children of our |
70 // continuation. | |
67 LayoutBoxModelObject* continuation = this->continuation(); | 71 LayoutBoxModelObject* continuation = this->continuation(); |
68 if (continuation) { | 72 if (continuation) { |
69 continuation->destroy(); | 73 continuation->destroy(); |
70 setContinuation(nullptr); | 74 setContinuation(nullptr); |
71 } | 75 } |
72 | 76 |
73 if (!documentBeingDestroyed()) { | 77 if (!documentBeingDestroyed()) { |
74 if (firstLineBox()) { | 78 if (firstLineBox()) { |
75 // We can't wait for LayoutBoxModelObject::destroy to clear the selection, | 79 // We can't wait for LayoutBoxModelObject::destroy to clear the selection, |
76 // because by then we will have nuked the line boxes. | 80 // because by then we will have nuked the line boxes. |
(...skipping 24 matching lines...) Expand all Loading... | |
101 LayoutInline* LayoutInline::inlineElementContinuation() const { | 105 LayoutInline* LayoutInline::inlineElementContinuation() const { |
102 LayoutBoxModelObject* continuation = this->continuation(); | 106 LayoutBoxModelObject* continuation = this->continuation(); |
103 if (!continuation || continuation->isInline()) | 107 if (!continuation || continuation->isInline()) |
104 return toLayoutInline(continuation); | 108 return toLayoutInline(continuation); |
105 return toLayoutBlockFlow(continuation)->inlineElementContinuation(); | 109 return toLayoutBlockFlow(continuation)->inlineElementContinuation(); |
106 } | 110 } |
107 | 111 |
108 void LayoutInline::updateFromStyle() { | 112 void LayoutInline::updateFromStyle() { |
109 LayoutBoxModelObject::updateFromStyle(); | 113 LayoutBoxModelObject::updateFromStyle(); |
110 | 114 |
111 // FIXME: Is this still needed. Was needed for run-ins, since run-in is consid ered a block display type. | 115 // FIXME: Is this still needed. Was needed for run-ins, since run-in is |
116 // considered a block display type. | |
112 setInline(true); | 117 setInline(true); |
113 | 118 |
114 // FIXME: Support transforms and reflections on inline flows someday. | 119 // FIXME: Support transforms and reflections on inline flows someday. |
115 setHasTransformRelatedProperty(false); | 120 setHasTransformRelatedProperty(false); |
116 setHasReflection(false); | 121 setHasReflection(false); |
117 } | 122 } |
118 | 123 |
119 static LayoutObject* inFlowPositionedInlineAncestor(LayoutObject* p) { | 124 static LayoutObject* inFlowPositionedInlineAncestor(LayoutObject* p) { |
120 while (p && p->isLayoutInline()) { | 125 while (p && p->isLayoutInline()) { |
121 if (p->isInFlowPositioned()) | 126 if (p->isInFlowPositioned()) |
122 return p; | 127 return p; |
123 p = p->parent(); | 128 p = p->parent(); |
124 } | 129 } |
125 return nullptr; | 130 return nullptr; |
126 } | 131 } |
127 | 132 |
128 static void updateInFlowPositionOfAnonymousBlockContinuations( | 133 static void updateInFlowPositionOfAnonymousBlockContinuations( |
129 LayoutObject* block, | 134 LayoutObject* block, |
130 const ComputedStyle& newStyle, | 135 const ComputedStyle& newStyle, |
131 const ComputedStyle& oldStyle, | 136 const ComputedStyle& oldStyle, |
132 LayoutObject* containingBlockOfEndOfContinuation) { | 137 LayoutObject* containingBlockOfEndOfContinuation) { |
133 for (; block && block != containingBlockOfEndOfContinuation && | 138 for (; block && block != containingBlockOfEndOfContinuation && |
134 block->isAnonymousBlock(); | 139 block->isAnonymousBlock(); |
135 block = block->nextSibling()) { | 140 block = block->nextSibling()) { |
136 LayoutBlockFlow* blockFlow = toLayoutBlockFlow(block); | 141 LayoutBlockFlow* blockFlow = toLayoutBlockFlow(block); |
137 if (!blockFlow->isAnonymousBlockContinuation()) | 142 if (!blockFlow->isAnonymousBlockContinuation()) |
138 continue; | 143 continue; |
139 | 144 |
140 // If we are no longer in-flow positioned but our descendant block(s) still have an in-flow positioned ancestor then | 145 // If we are no longer in-flow positioned but our descendant block(s) still |
141 // their containing anonymous block should keep its in-flow positioning. | 146 // have an in-flow positioned ancestor then their containing anonymous block |
147 // should keep its in-flow positioning. | |
142 if (oldStyle.hasInFlowPosition() && | 148 if (oldStyle.hasInFlowPosition() && |
143 inFlowPositionedInlineAncestor(blockFlow->inlineElementContinuation())) | 149 inFlowPositionedInlineAncestor(blockFlow->inlineElementContinuation())) |
144 continue; | 150 continue; |
145 | 151 |
146 RefPtr<ComputedStyle> newBlockStyle = | 152 RefPtr<ComputedStyle> newBlockStyle = |
147 ComputedStyle::clone(block->styleRef()); | 153 ComputedStyle::clone(block->styleRef()); |
148 newBlockStyle->setPosition(newStyle.position()); | 154 newBlockStyle->setPosition(newStyle.position()); |
149 block->setStyle(newBlockStyle); | 155 block->setStyle(newBlockStyle); |
150 } | 156 } |
151 } | 157 } |
152 | 158 |
153 void LayoutInline::styleDidChange(StyleDifference diff, | 159 void LayoutInline::styleDidChange(StyleDifference diff, |
154 const ComputedStyle* oldStyle) { | 160 const ComputedStyle* oldStyle) { |
155 LayoutBoxModelObject::styleDidChange(diff, oldStyle); | 161 LayoutBoxModelObject::styleDidChange(diff, oldStyle); |
156 | 162 |
157 // Ensure that all of the split inlines pick up the new style. We | 163 // Ensure that all of the split inlines pick up the new style. We only do this |
158 // only do this if we're an inline, since we don't want to propagate | 164 // if we're an inline, since we don't want to propagate a block's style to the |
159 // a block's style to the other inlines. | 165 // other inlines. e.g., <font>foo <h4>goo</h4> moo</font>. The <font> inlines |
160 // e.g., <font>foo <h4>goo</h4> moo</font>. The <font> inlines before | 166 // before and after the block share the same style, but the block doesn't need |
161 // and after the block share the same style, but the block doesn't | 167 // to pass its style on to anyone else. |
162 // need to pass its style on to anyone else. | |
163 const ComputedStyle& newStyle = styleRef(); | 168 const ComputedStyle& newStyle = styleRef(); |
164 LayoutInline* continuation = inlineElementContinuation(); | 169 LayoutInline* continuation = inlineElementContinuation(); |
165 LayoutInline* endOfContinuation = nullptr; | 170 LayoutInline* endOfContinuation = nullptr; |
166 for (LayoutInline* currCont = continuation; currCont; | 171 for (LayoutInline* currCont = continuation; currCont; |
167 currCont = currCont->inlineElementContinuation()) { | 172 currCont = currCont->inlineElementContinuation()) { |
168 LayoutBoxModelObject* nextCont = currCont->continuation(); | 173 LayoutBoxModelObject* nextCont = currCont->continuation(); |
169 currCont->setContinuation(nullptr); | 174 currCont->setContinuation(nullptr); |
170 currCont->setStyle(mutableStyle()); | 175 currCont->setStyle(mutableStyle()); |
171 currCont->setContinuation(nextCont); | 176 currCont->setContinuation(nextCont); |
172 endOfContinuation = currCont; | 177 endOfContinuation = currCont; |
173 } | 178 } |
174 | 179 |
175 if (continuation && oldStyle) { | 180 if (continuation && oldStyle) { |
176 ASSERT(endOfContinuation); | 181 ASSERT(endOfContinuation); |
177 LayoutObject* block = containingBlock()->nextSibling(); | 182 LayoutObject* block = containingBlock()->nextSibling(); |
178 // If an inline's in-flow positioning has changed then any descendant blocks will need to change their styles accordingly. | 183 // If an inline's in-flow positioning has changed then any descendant blocks |
184 // will need to change their styles accordingly. | |
179 if (block && block->isAnonymousBlock() && | 185 if (block && block->isAnonymousBlock() && |
180 newStyle.position() != oldStyle->position() && | 186 newStyle.position() != oldStyle->position() && |
181 (newStyle.hasInFlowPosition() || oldStyle->hasInFlowPosition())) | 187 (newStyle.hasInFlowPosition() || oldStyle->hasInFlowPosition())) |
182 updateInFlowPositionOfAnonymousBlockContinuations( | 188 updateInFlowPositionOfAnonymousBlockContinuations( |
183 block, newStyle, *oldStyle, endOfContinuation->containingBlock()); | 189 block, newStyle, *oldStyle, endOfContinuation->containingBlock()); |
184 } | 190 } |
185 | 191 |
186 if (!alwaysCreateLineBoxes()) { | 192 if (!alwaysCreateLineBoxes()) { |
187 bool alwaysCreateLineBoxesNew = | 193 bool alwaysCreateLineBoxesNew = |
188 hasSelfPaintingLayer() || hasBoxDecorationBackground() || | 194 hasSelfPaintingLayer() || hasBoxDecorationBackground() || |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
221 const SimpleFontData* font = style.font().primaryFont(); | 227 const SimpleFontData* font = style.font().primaryFont(); |
222 const SimpleFontData* parentFont = parentStyle.font().primaryFont(); | 228 const SimpleFontData* parentFont = parentStyle.font().primaryFont(); |
223 | 229 |
224 return (font && parentFont && | 230 return (font && parentFont && |
225 !font->getFontMetrics().hasIdenticalAscentDescentAndLineGap( | 231 !font->getFontMetrics().hasIdenticalAscentDescentAndLineGap( |
226 parentFont->getFontMetrics())) || | 232 parentFont->getFontMetrics())) || |
227 parentStyle.lineHeight() != style.lineHeight(); | 233 parentStyle.lineHeight() != style.lineHeight(); |
228 } | 234 } |
229 | 235 |
230 void LayoutInline::updateAlwaysCreateLineBoxes(bool fullLayout) { | 236 void LayoutInline::updateAlwaysCreateLineBoxes(bool fullLayout) { |
231 // Once we have been tainted once, just assume it will happen again. This way effects like hover highlighting that change the | 237 // Once we have been tainted once, just assume it will happen again. This way |
232 // background color will only cause a layout on the first rollover. | 238 // effects like hover highlighting that change the background color will only |
239 // cause a layout on the first rollover. | |
233 if (alwaysCreateLineBoxes()) | 240 if (alwaysCreateLineBoxes()) |
234 return; | 241 return; |
235 | 242 |
236 const ComputedStyle& parentStyle = parent()->styleRef(); | 243 const ComputedStyle& parentStyle = parent()->styleRef(); |
237 LayoutInline* parentLayoutInline = | 244 LayoutInline* parentLayoutInline = |
238 parent()->isLayoutInline() ? toLayoutInline(parent()) : 0; | 245 parent()->isLayoutInline() ? toLayoutInline(parent()) : 0; |
239 bool checkFonts = document().inNoQuirksMode(); | 246 bool checkFonts = document().inNoQuirksMode(); |
240 bool alwaysCreateLineBoxesNew = | 247 bool alwaysCreateLineBoxesNew = |
241 (parentLayoutInline && parentLayoutInline->alwaysCreateLineBoxes()) || | 248 (parentLayoutInline && parentLayoutInline->alwaysCreateLineBoxes()) || |
242 (parentLayoutInline && | 249 (parentLayoutInline && |
(...skipping 22 matching lines...) Expand all Loading... | |
265 setAlwaysCreateLineBoxes(); | 272 setAlwaysCreateLineBoxes(); |
266 } | 273 } |
267 } | 274 } |
268 | 275 |
269 LayoutRect LayoutInline::localCaretRect(InlineBox* inlineBox, | 276 LayoutRect LayoutInline::localCaretRect(InlineBox* inlineBox, |
270 int, | 277 int, |
271 LayoutUnit* extraWidthToEndOfLine) { | 278 LayoutUnit* extraWidthToEndOfLine) { |
272 if (firstChild()) { | 279 if (firstChild()) { |
273 // This condition is possible if the LayoutInline is at an editing boundary, | 280 // This condition is possible if the LayoutInline is at an editing boundary, |
274 // i.e. the VisiblePosition is: | 281 // i.e. the VisiblePosition is: |
275 // <LayoutInline editingBoundary=true>|<LayoutText> </LayoutText></LayoutI nline> | 282 // <LayoutInline editingBoundary=true>|<LayoutText> |
283 // </LayoutText></LayoutInline> | |
276 // FIXME: need to figure out how to make this return a valid rect, note that | 284 // FIXME: need to figure out how to make this return a valid rect, note that |
277 // there are no line boxes created in the above case. | 285 // there are no line boxes created in the above case. |
278 return LayoutRect(); | 286 return LayoutRect(); |
279 } | 287 } |
280 | 288 |
281 DCHECK(!inlineBox); | 289 DCHECK(!inlineBox); |
282 | 290 |
283 if (extraWidthToEndOfLine) | 291 if (extraWidthToEndOfLine) |
284 *extraWidthToEndOfLine = LayoutUnit(); | 292 *extraWidthToEndOfLine = LayoutUnit(); |
285 | 293 |
286 LayoutRect caretRect = | 294 LayoutRect caretRect = |
287 localCaretRectForEmptyElement(borderAndPaddingWidth(), LayoutUnit()); | 295 localCaretRectForEmptyElement(borderAndPaddingWidth(), LayoutUnit()); |
288 | 296 |
289 if (InlineBox* firstBox = firstLineBox()) { | 297 if (InlineBox* firstBox = firstLineBox()) { |
290 // FIXME: the call to roundedLayoutPoint() below is temporary and should be removed once | 298 // FIXME: the call to roundedLayoutPoint() below is temporary and should be |
pdr.
2016/10/07 02:49:40
I think this comment can be removed now.
eae
2016/10/07 16:38:13
Yay!
| |
291 // the transition to LayoutUnit-based types is complete (crbug.com/321237) | 299 // removed once the transition to LayoutUnit-based types is complete |
300 // (crbug.com/321237). | |
292 caretRect.moveBy(firstBox->topLeft()); | 301 caretRect.moveBy(firstBox->topLeft()); |
293 } | 302 } |
294 | 303 |
295 return caretRect; | 304 return caretRect; |
296 } | 305 } |
297 | 306 |
298 void LayoutInline::addChild(LayoutObject* newChild, LayoutObject* beforeChild) { | 307 void LayoutInline::addChild(LayoutObject* newChild, LayoutObject* beforeChild) { |
299 // Any table-part dom child of an inline element has anonymous wrappers in the layout tree | 308 // Any table-part dom child of an inline element has anonymous wrappers in the |
300 // so we need to climb up to the enclosing anonymous table wrapper and add the new child before that. | 309 // layout tree so we need to climb up to the enclosing anonymous table wrapper |
301 // TODO(rhogan): If newChild is a table part we want to insert it into the sam e table as beforeChild. | 310 // and add the new child before that. |
311 // TODO(rhogan): If newChild is a table part we want to insert it into the | |
312 // same table as beforeChild. | |
302 while (beforeChild && beforeChild->isTablePart()) | 313 while (beforeChild && beforeChild->isTablePart()) |
303 beforeChild = beforeChild->parent(); | 314 beforeChild = beforeChild->parent(); |
304 if (continuation()) | 315 if (continuation()) |
305 return addChildToContinuation(newChild, beforeChild); | 316 return addChildToContinuation(newChild, beforeChild); |
306 return addChildIgnoringContinuation(newChild, beforeChild); | 317 return addChildIgnoringContinuation(newChild, beforeChild); |
307 } | 318 } |
308 | 319 |
309 static LayoutBoxModelObject* nextContinuation(LayoutObject* layoutObject) { | 320 static LayoutBoxModelObject* nextContinuation(LayoutObject* layoutObject) { |
310 if (layoutObject->isInline() && !layoutObject->isAtomicInlineLevel()) | 321 if (layoutObject->isInline() && !layoutObject->isAtomicInlineLevel()) |
311 return toLayoutInline(layoutObject)->continuation(); | 322 return toLayoutInline(layoutObject)->continuation(); |
(...skipping 20 matching lines...) Expand all Loading... | |
332 curr = nextContinuation(curr); | 343 curr = nextContinuation(curr); |
333 } | 344 } |
334 | 345 |
335 if (!beforeChild && !last->slowFirstChild()) | 346 if (!beforeChild && !last->slowFirstChild()) |
336 return nextToLast; | 347 return nextToLast; |
337 return last; | 348 return last; |
338 } | 349 } |
339 | 350 |
340 void LayoutInline::addChildIgnoringContinuation(LayoutObject* newChild, | 351 void LayoutInline::addChildIgnoringContinuation(LayoutObject* newChild, |
341 LayoutObject* beforeChild) { | 352 LayoutObject* beforeChild) { |
342 // Make sure we don't append things after :after-generated content if we have it. | 353 // Make sure we don't append things after :after-generated content if we have |
354 // it. | |
343 if (!beforeChild && isAfterContent(lastChild())) | 355 if (!beforeChild && isAfterContent(lastChild())) |
344 beforeChild = lastChild(); | 356 beforeChild = lastChild(); |
345 | 357 |
346 if (!newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned() && | 358 if (!newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned() && |
347 !newChild->isTablePart()) { | 359 !newChild->isTablePart()) { |
348 // We are placing a block inside an inline. We have to perform a split of th is | 360 // We are placing a block inside an inline. We have to perform a split of |
349 // inline into continuations. This involves creating an anonymous block box to hold | 361 // this inline into continuations. This involves creating an anonymous |
350 // |newChild|. We then make that block box a continuation of this inline. We take all of | 362 // block box to hold |newChild|. We then make that block box a continuation |
351 // the children after |beforeChild| and put them in a clone of this object. | 363 // of this inline. We take all of the children after |beforeChild| and put |
364 // them in a clone of this object. | |
352 RefPtr<ComputedStyle> newStyle = | 365 RefPtr<ComputedStyle> newStyle = |
353 ComputedStyle::createAnonymousStyleWithDisplay( | 366 ComputedStyle::createAnonymousStyleWithDisplay( |
354 containingBlock()->styleRef(), EDisplay::Block); | 367 containingBlock()->styleRef(), EDisplay::Block); |
355 | 368 |
356 // If inside an inline affected by in-flow positioning the block needs to be affected by it too. | 369 // If inside an inline affected by in-flow positioning the block needs to be |
357 // Giving the block a layer like this allows it to collect the x/y offsets f rom inline parents later. | 370 // affected by it too. Giving the block a layer like this allows it to |
371 // collect the x/y offsets from inline parents later. | |
358 if (LayoutObject* positionedAncestor = inFlowPositionedInlineAncestor(this)) | 372 if (LayoutObject* positionedAncestor = inFlowPositionedInlineAncestor(this)) |
359 newStyle->setPosition(positionedAncestor->style()->position()); | 373 newStyle->setPosition(positionedAncestor->style()->position()); |
360 | 374 |
361 LayoutBlockFlow* newBox = LayoutBlockFlow::createAnonymous(&document()); | 375 LayoutBlockFlow* newBox = LayoutBlockFlow::createAnonymous(&document()); |
362 newBox->setStyle(newStyle.release()); | 376 newBox->setStyle(newStyle.release()); |
363 LayoutBoxModelObject* oldContinuation = continuation(); | 377 LayoutBoxModelObject* oldContinuation = continuation(); |
364 setContinuation(newBox); | 378 setContinuation(newBox); |
365 | 379 |
366 splitFlow(beforeChild, newBox, newChild, oldContinuation); | 380 splitFlow(beforeChild, newBox, newChild, oldContinuation); |
367 return; | 381 return; |
(...skipping 25 matching lines...) Expand all Loading... | |
393 } | 407 } |
394 | 408 |
395 void LayoutInline::splitInlines(LayoutBlockFlow* fromBlock, | 409 void LayoutInline::splitInlines(LayoutBlockFlow* fromBlock, |
396 LayoutBlockFlow* toBlock, | 410 LayoutBlockFlow* toBlock, |
397 LayoutBlockFlow* middleBlock, | 411 LayoutBlockFlow* middleBlock, |
398 LayoutObject* beforeChild, | 412 LayoutObject* beforeChild, |
399 LayoutBoxModelObject* oldCont) { | 413 LayoutBoxModelObject* oldCont) { |
400 ASSERT(isDescendantOf(fromBlock)); | 414 ASSERT(isDescendantOf(fromBlock)); |
401 | 415 |
402 // If we're splitting the inline containing the fullscreened element, | 416 // If we're splitting the inline containing the fullscreened element, |
403 // |beforeChild| may be the layoutObject for the fullscreened element. However , | 417 // |beforeChild| may be the layoutObject for the fullscreened element. |
404 // that layoutObject is wrapped in a LayoutFullScreen, so |this| is not its | 418 // However, that layoutObject is wrapped in a LayoutFullScreen, so |this| is |
405 // parent. Since the splitting logic expects |this| to be the parent, set | 419 // not its parent. Since the splitting logic expects |this| to be the parent, |
406 // |beforeChild| to be the LayoutFullScreen. | 420 // set |beforeChild| to be the LayoutFullScreen. |
407 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(document())) { | 421 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(document())) { |
408 const Element* fullScreenElement = fullscreen->currentFullScreenElement(); | 422 const Element* fullScreenElement = fullscreen->currentFullScreenElement(); |
409 if (fullScreenElement && beforeChild && | 423 if (fullScreenElement && beforeChild && |
410 beforeChild->node() == fullScreenElement) | 424 beforeChild->node() == fullScreenElement) |
411 beforeChild = fullscreen->fullScreenLayoutObject(); | 425 beforeChild = fullscreen->fullScreenLayoutObject(); |
412 } | 426 } |
413 | 427 |
414 // FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the depth at which we're willing to clone. | 428 // FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the |
415 // There will eventually be a better approach to this problem that will let us nest to a much | 429 // depth at which we're willing to clone. |
416 // greater depth (see bugzilla bug 13430) but for now we have a limit. This * will* result in | 430 // There will eventually be a better approach to this problem that will let us |
417 // incorrect rendering, but the alternative is to hang forever. | 431 // nest to a much greater depth (see bugzilla bug 13430) but for now we have a |
432 // limit. This *will* result in incorrect rendering, but the alternative is to | |
433 // hang forever. | |
418 const unsigned cMaxSplitDepth = 200; | 434 const unsigned cMaxSplitDepth = 200; |
419 Vector<LayoutInline*> inlinesToClone; | 435 Vector<LayoutInline*> inlinesToClone; |
420 LayoutInline* topMostInline = this; | 436 LayoutInline* topMostInline = this; |
421 for (LayoutObject* o = this; o != fromBlock; o = o->parent()) { | 437 for (LayoutObject* o = this; o != fromBlock; o = o->parent()) { |
422 topMostInline = toLayoutInline(o); | 438 topMostInline = toLayoutInline(o); |
423 if (inlinesToClone.size() < cMaxSplitDepth) | 439 if (inlinesToClone.size() < cMaxSplitDepth) |
424 inlinesToClone.append(topMostInline); | 440 inlinesToClone.append(topMostInline); |
425 // Keep walking up the chain to ensure |topMostInline| is a child of |fromBl ock|, | 441 // Keep walking up the chain to ensure |topMostInline| is a child of |
426 // to avoid assertion failure when |fromBlock|'s children are moved to |toBl ock| below. | 442 // |fromBlock|, to avoid assertion failure when |fromBlock|'s children are |
443 // moved to |toBlock| below. | |
427 } | 444 } |
428 | 445 |
429 // Create a new clone of the top-most inline in |inlinesToClone|. | 446 // Create a new clone of the top-most inline in |inlinesToClone|. |
430 LayoutInline* topMostInlineToClone = inlinesToClone.last(); | 447 LayoutInline* topMostInlineToClone = inlinesToClone.last(); |
431 LayoutInline* cloneInline = topMostInlineToClone->clone(); | 448 LayoutInline* cloneInline = topMostInlineToClone->clone(); |
432 | 449 |
433 // Now we are at the block level. We need to put the clone into the |toBlock|. | 450 // Now we are at the block level. We need to put the clone into the |toBlock|. |
434 toBlock->children()->appendChildNode(toBlock, cloneInline); | 451 toBlock->children()->appendChildNode(toBlock, cloneInline); |
435 | 452 |
436 // Now take all the children after |topMostInline| and remove them from the |f romBlock| | 453 // Now take all the children after |topMostInline| and remove them from the |
437 // and put them into the toBlock. | 454 // |fromBlock| and put them into the toBlock. |
438 fromBlock->moveChildrenTo(toBlock, topMostInline->nextSibling(), nullptr, | 455 fromBlock->moveChildrenTo(toBlock, topMostInline->nextSibling(), nullptr, |
439 true); | 456 true); |
440 | 457 |
441 LayoutInline* currentParent = topMostInlineToClone; | 458 LayoutInline* currentParent = topMostInlineToClone; |
442 LayoutInline* cloneInlineParent = cloneInline; | 459 LayoutInline* cloneInlineParent = cloneInline; |
443 | 460 |
444 // Clone the inlines from top to down to ensure any new object will be added i nto a rooted tree. | 461 // Clone the inlines from top to down to ensure any new object will be added |
445 // Note that we have already cloned the top-most one, so the loop begins from size - 2 (except if | 462 // into a rooted tree. |
446 // we have reached |cMaxDepth| in which case we sacrifice correct rendering fo r performance). | 463 // Note that we have already cloned the top-most one, so the loop begins from |
464 // size - 2 (except if we have reached |cMaxDepth| in which case we sacrifice | |
465 // correct rendering for performance). | |
447 for (int i = static_cast<int>(inlinesToClone.size()) - 2; i >= 0; --i) { | 466 for (int i = static_cast<int>(inlinesToClone.size()) - 2; i >= 0; --i) { |
448 // Hook the clone up as a continuation of |currentInline|. | 467 // Hook the clone up as a continuation of |currentInline|. |
449 LayoutBoxModelObject* oldCont = currentParent->continuation(); | 468 LayoutBoxModelObject* oldCont = currentParent->continuation(); |
450 currentParent->setContinuation(cloneInline); | 469 currentParent->setContinuation(cloneInline); |
451 cloneInline->setContinuation(oldCont); | 470 cloneInline->setContinuation(oldCont); |
452 | 471 |
453 // Create a new clone. | 472 // Create a new clone. |
454 LayoutInline* current = inlinesToClone[i]; | 473 LayoutInline* current = inlinesToClone[i]; |
455 cloneInline = current->clone(); | 474 cloneInline = current->clone(); |
456 | 475 |
457 // Insert our |cloneInline| as the first child of |cloneInlineParent|. | 476 // Insert our |cloneInline| as the first child of |cloneInlineParent|. |
458 cloneInlineParent->addChildIgnoringContinuation(cloneInline, nullptr); | 477 cloneInlineParent->addChildIgnoringContinuation(cloneInline, nullptr); |
459 | 478 |
460 // Now we need to take all of the children starting from the first child | 479 // Now we need to take all of the children starting from the first child |
461 // *after* |current| and append them all to the |cloneInlineParent|. | 480 // *after* |current| and append them all to the |cloneInlineParent|. |
462 currentParent->moveChildrenToIgnoringContinuation(cloneInlineParent, | 481 currentParent->moveChildrenToIgnoringContinuation(cloneInlineParent, |
463 current->nextSibling()); | 482 current->nextSibling()); |
464 | 483 |
465 currentParent = current; | 484 currentParent = current; |
466 cloneInlineParent = cloneInline; | 485 cloneInlineParent = cloneInline; |
467 } | 486 } |
468 | 487 |
469 // The last inline to clone is |this|, and the current |cloneInline| is cloned from |this|. | 488 // The last inline to clone is |this|, and the current |cloneInline| is cloned |
489 // from |this|. | |
470 ASSERT(this == inlinesToClone.first()); | 490 ASSERT(this == inlinesToClone.first()); |
471 | 491 |
472 // Hook |cloneInline| up as the continuation of the middle block. | 492 // Hook |cloneInline| up as the continuation of the middle block. |
473 cloneInline->setContinuation(oldCont); | 493 cloneInline->setContinuation(oldCont); |
474 middleBlock->setContinuation(cloneInline); | 494 middleBlock->setContinuation(cloneInline); |
475 | 495 |
476 // Now take all of the children from |beforeChild| to the end and remove | 496 // Now take all of the children from |beforeChild| to the end and remove |
477 // them from |this| and place them in the clone. | 497 // them from |this| and place them in the clone. |
478 moveChildrenToIgnoringContinuation(cloneInline, beforeChild); | 498 moveChildrenToIgnoringContinuation(cloneInline, beforeChild); |
479 } | 499 } |
480 | 500 |
481 void LayoutInline::splitFlow(LayoutObject* beforeChild, | 501 void LayoutInline::splitFlow(LayoutObject* beforeChild, |
482 LayoutBlockFlow* newBlockBox, | 502 LayoutBlockFlow* newBlockBox, |
483 LayoutObject* newChild, | 503 LayoutObject* newChild, |
484 LayoutBoxModelObject* oldCont) { | 504 LayoutBoxModelObject* oldCont) { |
485 LayoutBlockFlow* block = toLayoutBlockFlow(containingBlock()); | 505 LayoutBlockFlow* block = toLayoutBlockFlow(containingBlock()); |
486 LayoutBlockFlow* pre = nullptr; | 506 LayoutBlockFlow* pre = nullptr; |
487 | 507 |
488 // Delete our line boxes before we do the inline split into continuations. | 508 // Delete our line boxes before we do the inline split into continuations. |
489 block->deleteLineBoxTree(); | 509 block->deleteLineBoxTree(); |
490 | 510 |
491 bool reusedAnonymousBlock = false; | 511 bool reusedAnonymousBlock = false; |
492 if (block->isAnonymousBlock()) { | 512 if (block->isAnonymousBlock()) { |
493 LayoutBlock* outerContainingBlock = block->containingBlock(); | 513 LayoutBlock* outerContainingBlock = block->containingBlock(); |
494 if (outerContainingBlock && outerContainingBlock->isLayoutBlockFlow() && | 514 if (outerContainingBlock && outerContainingBlock->isLayoutBlockFlow() && |
495 !outerContainingBlock->createsAnonymousWrapper()) { | 515 !outerContainingBlock->createsAnonymousWrapper()) { |
496 // We can reuse this block and make it the preBlock of the next continuati on. | 516 // We can reuse this block and make it the preBlock of the next |
517 // continuation. | |
497 block->removePositionedObjects(nullptr); | 518 block->removePositionedObjects(nullptr); |
498 block->removeFloatingObjects(); | 519 block->removeFloatingObjects(); |
499 pre = block; | 520 pre = block; |
500 block = toLayoutBlockFlow(outerContainingBlock); | 521 block = toLayoutBlockFlow(outerContainingBlock); |
501 reusedAnonymousBlock = true; | 522 reusedAnonymousBlock = true; |
502 } | 523 } |
503 } | 524 } |
525 | |
526 // No anonymous block available for use. Make one. | |
504 if (!reusedAnonymousBlock) | 527 if (!reusedAnonymousBlock) |
505 pre = toLayoutBlockFlow( | 528 pre = toLayoutBlockFlow(block->createAnonymousBlock()); |
506 block | |
507 ->createAnonymousBlock()); // No anonymous block available for use. Make one. | |
508 | 529 |
509 LayoutBlockFlow* post = toLayoutBlockFlow(pre->createAnonymousBlock()); | 530 LayoutBlockFlow* post = toLayoutBlockFlow(pre->createAnonymousBlock()); |
510 | 531 |
511 LayoutObject* boxFirst = | 532 LayoutObject* boxFirst = |
512 !reusedAnonymousBlock ? block->firstChild() : pre->nextSibling(); | 533 !reusedAnonymousBlock ? block->firstChild() : pre->nextSibling(); |
513 if (!reusedAnonymousBlock) | 534 if (!reusedAnonymousBlock) |
514 block->children()->insertChildNode(block, pre, boxFirst); | 535 block->children()->insertChildNode(block, pre, boxFirst); |
515 block->children()->insertChildNode(block, newBlockBox, boxFirst); | 536 block->children()->insertChildNode(block, newBlockBox, boxFirst); |
516 block->children()->insertChildNode(block, post, boxFirst); | 537 block->children()->insertChildNode(block, post, boxFirst); |
517 block->setChildrenInline(false); | 538 block->setChildrenInline(false); |
518 | 539 |
519 if (!reusedAnonymousBlock) { | 540 if (!reusedAnonymousBlock) { |
520 LayoutObject* o = boxFirst; | 541 LayoutObject* o = boxFirst; |
521 while (o) { | 542 while (o) { |
522 LayoutObject* no = o; | 543 LayoutObject* no = o; |
523 o = no->nextSibling(); | 544 o = no->nextSibling(); |
524 pre->children()->appendChildNode( | 545 pre->children()->appendChildNode( |
525 pre, block->children()->removeChildNode(block, no)); | 546 pre, block->children()->removeChildNode(block, no)); |
526 no->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 547 no->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
527 LayoutInvalidationReason::AnonymousBlockChange); | 548 LayoutInvalidationReason::AnonymousBlockChange); |
528 } | 549 } |
529 } | 550 } |
530 | 551 |
531 splitInlines(pre, post, newBlockBox, beforeChild, oldCont); | 552 splitInlines(pre, post, newBlockBox, beforeChild, oldCont); |
532 | 553 |
533 // We already know the newBlockBox isn't going to contain inline kids, so avoi d wasting | 554 // We already know the newBlockBox isn't going to contain inline kids, so |
534 // time in makeChildrenNonInline by just setting this explicitly up front. | 555 // avoid wasting time in makeChildrenNonInline by just setting this explicitly |
556 // up front. | |
535 newBlockBox->setChildrenInline(false); | 557 newBlockBox->setChildrenInline(false); |
536 | 558 |
537 newBlockBox->addChild(newChild); | 559 newBlockBox->addChild(newChild); |
538 | 560 |
539 // Always just do a full layout in order to ensure that line boxes (especially wrappers for images) | 561 // Always just do a full layout in order to ensure that line boxes (especially |
540 // get deleted properly. Because objects moves from the pre block into the po st block, we want to | 562 // wrappers for images) get deleted properly. Because objects moves from the |
541 // make new line boxes instead of leaving the old line boxes around. | 563 // pre block into the post block, we want to make new line boxes instead of |
564 // leaving the old line boxes around. | |
542 pre->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 565 pre->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
543 LayoutInvalidationReason::AnonymousBlockChange); | 566 LayoutInvalidationReason::AnonymousBlockChange); |
544 block->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 567 block->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
545 LayoutInvalidationReason::AnonymousBlockChange); | 568 LayoutInvalidationReason::AnonymousBlockChange); |
546 post->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 569 post->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
547 LayoutInvalidationReason::AnonymousBlockChange); | 570 LayoutInvalidationReason::AnonymousBlockChange); |
548 } | 571 } |
549 | 572 |
550 void LayoutInline::addChildToContinuation(LayoutObject* newChild, | 573 void LayoutInline::addChildToContinuation(LayoutObject* newChild, |
551 LayoutObject* beforeChild) { | 574 LayoutObject* beforeChild) { |
552 // A continuation always consists of two potential candidates: an inline or an anonymous | 575 // A continuation always consists of two potential candidates: an inline or an |
553 // block box holding block children. | 576 // anonymous block box holding block children. |
554 LayoutBoxModelObject* flow = continuationBefore(beforeChild); | 577 LayoutBoxModelObject* flow = continuationBefore(beforeChild); |
555 ASSERT(!beforeChild || beforeChild->parent()->isAnonymousBlock() || | 578 ASSERT(!beforeChild || beforeChild->parent()->isAnonymousBlock() || |
556 beforeChild->parent()->isLayoutInline()); | 579 beforeChild->parent()->isLayoutInline()); |
557 LayoutBoxModelObject* beforeChildParent = nullptr; | 580 LayoutBoxModelObject* beforeChildParent = nullptr; |
558 if (beforeChild) { | 581 if (beforeChild) { |
559 beforeChildParent = toLayoutBoxModelObject(beforeChild->parent()); | 582 beforeChildParent = toLayoutBoxModelObject(beforeChild->parent()); |
560 } else { | 583 } else { |
561 LayoutBoxModelObject* cont = nextContinuation(flow); | 584 LayoutBoxModelObject* cont = nextContinuation(flow); |
562 if (cont) | 585 if (cont) |
563 beforeChildParent = cont; | 586 beforeChildParent = cont; |
564 else | 587 else |
565 beforeChildParent = flow; | 588 beforeChildParent = flow; |
566 } | 589 } |
567 | 590 |
568 // TODO(rhogan): Should we treat out-of-flows and floats as through they're in line below? | 591 // TODO(rhogan): Should we treat out-of-flows and floats as through they're |
592 // inline below? | |
569 if (newChild->isFloatingOrOutOfFlowPositioned()) | 593 if (newChild->isFloatingOrOutOfFlowPositioned()) |
570 return beforeChildParent->addChildIgnoringContinuation(newChild, | 594 return beforeChildParent->addChildIgnoringContinuation(newChild, |
571 beforeChild); | 595 beforeChild); |
572 | 596 |
573 // A table part will be wrapped by an inline anonymous table when it is added to the layout | 597 // A table part will be wrapped by an inline anonymous table when it is added |
574 // tree, so treat it as inline when deciding where to add it. | 598 // to the layout tree, so treat it as inline when deciding where to add it. |
575 bool childInline = newChild->isInline() || newChild->isTablePart(); | 599 bool childInline = newChild->isInline() || newChild->isTablePart(); |
576 bool bcpInline = beforeChildParent->isInline(); | 600 bool bcpInline = beforeChildParent->isInline(); |
577 bool flowInline = flow->isInline(); | 601 bool flowInline = flow->isInline(); |
578 | 602 |
579 if (flow == beforeChildParent) | 603 if (flow == beforeChildParent) |
580 return flow->addChildIgnoringContinuation(newChild, beforeChild); | 604 return flow->addChildIgnoringContinuation(newChild, beforeChild); |
581 | 605 |
582 // The goal here is to match up if we can, so that we can coalesce and create the | 606 // The goal here is to match up if we can, so that we can coalesce and create |
583 // minimal # of continuations needed for the inline. | 607 // the minimal # of continuations needed for the inline. |
584 if (childInline == bcpInline || (beforeChild && beforeChild->isInline())) | 608 if (childInline == bcpInline || (beforeChild && beforeChild->isInline())) |
585 return beforeChildParent->addChildIgnoringContinuation(newChild, | 609 return beforeChildParent->addChildIgnoringContinuation(newChild, |
586 beforeChild); | 610 beforeChild); |
587 if (flowInline == childInline) | 611 if (flowInline == childInline) { |
588 return flow->addChildIgnoringContinuation(newChild, | 612 // Just treat like an append. |
589 0); // Just treat like an append. | 613 return flow->addChildIgnoringContinuation(newChild, 0); |
614 } | |
590 return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); | 615 return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); |
591 } | 616 } |
592 | 617 |
593 void LayoutInline::paint(const PaintInfo& paintInfo, | 618 void LayoutInline::paint(const PaintInfo& paintInfo, |
594 const LayoutPoint& paintOffset) const { | 619 const LayoutPoint& paintOffset) const { |
595 InlinePainter(*this).paint(paintInfo, paintOffset); | 620 InlinePainter(*this).paint(paintInfo, paintOffset); |
596 } | 621 } |
597 | 622 |
598 template <typename GeneratorContext> | 623 template <typename GeneratorContext> |
599 void LayoutInline::generateLineBoxRects(GeneratorContext& yield) const { | 624 void LayoutInline::generateLineBoxRects(GeneratorContext& yield) const { |
(...skipping 11 matching lines...) Expand all Loading... | |
611 const LayoutInline* container) const { | 636 const LayoutInline* container) const { |
612 if (!culledInlineFirstLineBox()) | 637 if (!culledInlineFirstLineBox()) |
613 return; | 638 return; |
614 | 639 |
615 bool isHorizontal = style()->isHorizontalWritingMode(); | 640 bool isHorizontal = style()->isHorizontalWritingMode(); |
616 | 641 |
617 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { | 642 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { |
618 if (curr->isFloatingOrOutOfFlowPositioned()) | 643 if (curr->isFloatingOrOutOfFlowPositioned()) |
619 continue; | 644 continue; |
620 | 645 |
621 // We want to get the margin box in the inline direction, and then use our f ont ascent/descent in the block | 646 // We want to get the margin box in the inline direction, and then use our |
622 // direction (aligned to the root box's baseline). | 647 // font ascent/descent in the block direction (aligned to the root box's |
648 // baseline). | |
623 if (curr->isBox()) { | 649 if (curr->isBox()) { |
624 LayoutBox* currBox = toLayoutBox(curr); | 650 LayoutBox* currBox = toLayoutBox(curr); |
625 if (currBox->inlineBoxWrapper()) { | 651 if (currBox->inlineBoxWrapper()) { |
626 RootInlineBox& rootBox = currBox->inlineBoxWrapper()->root(); | 652 RootInlineBox& rootBox = currBox->inlineBoxWrapper()->root(); |
627 LayoutUnit logicalTop = | 653 LayoutUnit logicalTop = |
628 rootBox.logicalTop() + (rootBox.getLineLayoutItem() | 654 rootBox.logicalTop() + (rootBox.getLineLayoutItem() |
629 .style(rootBox.isFirstLineStyle()) | 655 .style(rootBox.isFirstLineStyle()) |
630 ->font() | 656 ->font() |
631 .getFontMetrics() | 657 .getFontMetrics() |
632 .ascent() - | 658 .ascent() - |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
940 // If there are continuations, test them first because our containing block | 966 // If there are continuations, test them first because our containing block |
941 // will not check them. | 967 // will not check them. |
942 LayoutBoxModelObject* continuation = this->continuation(); | 968 LayoutBoxModelObject* continuation = this->continuation(); |
943 while (continuation) { | 969 while (continuation) { |
944 if (continuation->isInline() || continuation->slowFirstChild()) | 970 if (continuation->isInline() || continuation->slowFirstChild()) |
945 return continuation->positionForPoint(point); | 971 return continuation->positionForPoint(point); |
946 continuation = toLayoutBlockFlow(continuation)->inlineElementContinuation(); | 972 continuation = toLayoutBlockFlow(continuation)->inlineElementContinuation(); |
947 } | 973 } |
948 | 974 |
949 if (firstLineBoxIncludingCulling()) { | 975 if (firstLineBoxIncludingCulling()) { |
950 // This inline actually has a line box. We must have clicked in the border/ padding of one of these boxes. We | 976 // This inline actually has a line box. We must have clicked in the |
977 // border/padding of one of these boxes. We | |
951 // should try to find a result by asking our containing block. | 978 // should try to find a result by asking our containing block. |
952 return containingBlock()->positionForPoint(point); | 979 return containingBlock()->positionForPoint(point); |
953 } | 980 } |
954 | 981 |
955 return LayoutBoxModelObject::positionForPoint(point); | 982 return LayoutBoxModelObject::positionForPoint(point); |
956 } | 983 } |
957 | 984 |
958 namespace { | 985 namespace { |
959 | 986 |
960 class LinesBoundingBoxGeneratorContext { | 987 class LinesBoundingBoxGeneratorContext { |
(...skipping 12 matching lines...) Expand all Loading... | |
973 if (!alwaysCreateLineBoxes()) { | 1000 if (!alwaysCreateLineBoxes()) { |
974 ASSERT(!firstLineBox()); | 1001 ASSERT(!firstLineBox()); |
975 FloatRect floatResult; | 1002 FloatRect floatResult; |
976 LinesBoundingBoxGeneratorContext context(floatResult); | 1003 LinesBoundingBoxGeneratorContext context(floatResult); |
977 generateCulledLineBoxRects(context, this); | 1004 generateCulledLineBoxRects(context, this); |
978 return enclosingLayoutRect(floatResult); | 1005 return enclosingLayoutRect(floatResult); |
979 } | 1006 } |
980 | 1007 |
981 LayoutRect result; | 1008 LayoutRect result; |
982 | 1009 |
983 // See <rdar://problem/5289721>, for an unknown reason the linked list here is sometimes inconsistent, first is non-zero and last is zero. We have been | 1010 // See <rdar://problem/5289721>, for an unknown reason the linked list here is |
984 // unable to reproduce this at all (and consequently unable to figure ot why t his is happening). The assert will hopefully catch the problem in debug | 1011 // sometimes inconsistent, first is non-zero and last is zero. We have been |
985 // builds and help us someday figure out why. We also put in a redundant chec k of lastLineBox() to avoid the crash for now. | 1012 // unable to reproduce this at all (and consequently unable to figure ot why |
1013 // this is happening). The assert will hopefully catch the problem in debug | |
1014 // builds and help us someday figure out why. We also put in a redundant | |
1015 // check of lastLineBox() to avoid the crash for now. | |
986 ASSERT(!firstLineBox() == | 1016 ASSERT(!firstLineBox() == |
987 !lastLineBox()); // Either both are null or both exist. | 1017 !lastLineBox()); // Either both are null or both exist. |
988 if (firstLineBox() && lastLineBox()) { | 1018 if (firstLineBox() && lastLineBox()) { |
989 // Return the width of the minimal left side and the maximal right side. | 1019 // Return the width of the minimal left side and the maximal right side. |
990 LayoutUnit logicalLeftSide; | 1020 LayoutUnit logicalLeftSide; |
991 LayoutUnit logicalRightSide; | 1021 LayoutUnit logicalRightSide; |
992 for (InlineFlowBox* curr = firstLineBox(); curr; | 1022 for (InlineFlowBox* curr = firstLineBox(); curr; |
993 curr = curr->nextLineBox()) { | 1023 curr = curr->nextLineBox()) { |
994 if (curr == firstLineBox() || curr->logicalLeft() < logicalLeftSide) | 1024 if (curr == firstLineBox() || curr->logicalLeft() < logicalLeftSide) |
995 logicalLeftSide = curr->logicalLeft(); | 1025 logicalLeftSide = curr->logicalLeft(); |
(...skipping 13 matching lines...) Expand all Loading... | |
1009 } | 1039 } |
1010 | 1040 |
1011 return result; | 1041 return result; |
1012 } | 1042 } |
1013 | 1043 |
1014 InlineBox* LayoutInline::culledInlineFirstLineBox() const { | 1044 InlineBox* LayoutInline::culledInlineFirstLineBox() const { |
1015 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { | 1045 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { |
1016 if (curr->isFloatingOrOutOfFlowPositioned()) | 1046 if (curr->isFloatingOrOutOfFlowPositioned()) |
1017 continue; | 1047 continue; |
1018 | 1048 |
1019 // We want to get the margin box in the inline direction, and then use our f ont ascent/descent in the block | 1049 // We want to get the margin box in the inline direction, and then use our |
1020 // direction (aligned to the root box's baseline). | 1050 // font ascent/descent in the block direction (aligned to the root box's |
1051 // baseline). | |
1021 if (curr->isBox()) | 1052 if (curr->isBox()) |
1022 return toLayoutBox(curr)->inlineBoxWrapper(); | 1053 return toLayoutBox(curr)->inlineBoxWrapper(); |
1023 if (curr->isLayoutInline()) { | 1054 if (curr->isLayoutInline()) { |
1024 LayoutInline* currInline = toLayoutInline(curr); | 1055 LayoutInline* currInline = toLayoutInline(curr); |
1025 InlineBox* result = currInline->firstLineBoxIncludingCulling(); | 1056 InlineBox* result = currInline->firstLineBoxIncludingCulling(); |
1026 if (result) | 1057 if (result) |
1027 return result; | 1058 return result; |
1028 } else if (curr->isText()) { | 1059 } else if (curr->isText()) { |
1029 LayoutText* currText = toLayoutText(curr); | 1060 LayoutText* currText = toLayoutText(curr); |
1030 if (currText->firstTextBox()) | 1061 if (currText->firstTextBox()) |
1031 return currText->firstTextBox(); | 1062 return currText->firstTextBox(); |
1032 } | 1063 } |
1033 } | 1064 } |
1034 return nullptr; | 1065 return nullptr; |
1035 } | 1066 } |
1036 | 1067 |
1037 InlineBox* LayoutInline::culledInlineLastLineBox() const { | 1068 InlineBox* LayoutInline::culledInlineLastLineBox() const { |
1038 for (LayoutObject* curr = lastChild(); curr; curr = curr->previousSibling()) { | 1069 for (LayoutObject* curr = lastChild(); curr; curr = curr->previousSibling()) { |
1039 if (curr->isFloatingOrOutOfFlowPositioned()) | 1070 if (curr->isFloatingOrOutOfFlowPositioned()) |
1040 continue; | 1071 continue; |
1041 | 1072 |
1042 // We want to get the margin box in the inline direction, and then use our f ont ascent/descent in the block | 1073 // We want to get the margin box in the inline direction, and then use our |
1043 // direction (aligned to the root box's baseline). | 1074 // font ascent/descent in the block direction (aligned to the root box's |
1075 // baseline). | |
1044 if (curr->isBox()) | 1076 if (curr->isBox()) |
1045 return toLayoutBox(curr)->inlineBoxWrapper(); | 1077 return toLayoutBox(curr)->inlineBoxWrapper(); |
1046 if (curr->isLayoutInline()) { | 1078 if (curr->isLayoutInline()) { |
1047 LayoutInline* currInline = toLayoutInline(curr); | 1079 LayoutInline* currInline = toLayoutInline(curr); |
1048 InlineBox* result = currInline->lastLineBoxIncludingCulling(); | 1080 InlineBox* result = currInline->lastLineBoxIncludingCulling(); |
1049 if (result) | 1081 if (result) |
1050 return result; | 1082 return result; |
1051 } else if (curr->isText()) { | 1083 } else if (curr->isText()) { |
1052 LayoutText* currText = toLayoutText(curr); | 1084 LayoutText* currText = toLayoutText(curr); |
1053 if (currText->lastTextBox()) | 1085 if (currText->lastTextBox()) |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1172 | 1204 |
1173 return visualOverflowRect(); | 1205 return visualOverflowRect(); |
1174 } | 1206 } |
1175 | 1207 |
1176 LayoutRect LayoutInline::visualOverflowRect() const { | 1208 LayoutRect LayoutInline::visualOverflowRect() const { |
1177 LayoutRect overflowRect = linesVisualOverflowBoundingBox(); | 1209 LayoutRect overflowRect = linesVisualOverflowBoundingBox(); |
1178 LayoutUnit outlineOutset(style()->outlineOutsetExtent()); | 1210 LayoutUnit outlineOutset(style()->outlineOutsetExtent()); |
1179 if (outlineOutset) { | 1211 if (outlineOutset) { |
1180 Vector<LayoutRect> rects; | 1212 Vector<LayoutRect> rects; |
1181 if (document().inNoQuirksMode()) { | 1213 if (document().inNoQuirksMode()) { |
1182 // We have already included outline extents of line boxes in linesVisualOv erflowBoundingBox(), | 1214 // We have already included outline extents of line boxes in |
1183 // so the following just add outline rects for children and continuations. | 1215 // linesVisualOverflowBoundingBox(), so the following just add outline |
1216 // rects for children and continuations. | |
1184 addOutlineRectsForChildrenAndContinuations( | 1217 addOutlineRectsForChildrenAndContinuations( |
1185 rects, LayoutPoint(), outlineRectsShouldIncludeBlockVisualOverflow()); | 1218 rects, LayoutPoint(), outlineRectsShouldIncludeBlockVisualOverflow()); |
1186 } else { | 1219 } else { |
1187 // In non-standard mode, because the difference in LayoutBlock::minLineHei ghtForReplacedObject(), | 1220 // In non-standard mode, because the difference in |
1188 // linesVisualOverflowBoundingBox() may not cover outline rects of lines c ontaining replaced objects. | 1221 // LayoutBlock::minLineHeightForReplacedObject(), |
1222 // linesVisualOverflowBoundingBox() may not cover outline rects of lines | |
1223 // containing replaced objects. | |
1189 addOutlineRects(rects, LayoutPoint(), | 1224 addOutlineRects(rects, LayoutPoint(), |
1190 outlineRectsShouldIncludeBlockVisualOverflow()); | 1225 outlineRectsShouldIncludeBlockVisualOverflow()); |
1191 } | 1226 } |
1192 if (!rects.isEmpty()) { | 1227 if (!rects.isEmpty()) { |
1193 LayoutRect outlineRect = unionRectEvenIfEmpty(rects); | 1228 LayoutRect outlineRect = unionRectEvenIfEmpty(rects); |
1194 outlineRect.inflate(outlineOutset); | 1229 outlineRect.inflate(outlineOutset); |
1195 overflowRect.unite(outlineRect); | 1230 overflowRect.unite(outlineRect); |
1196 } | 1231 } |
1197 } | 1232 } |
1198 return overflowRect; | 1233 return overflowRect; |
1199 } | 1234 } |
1200 | 1235 |
1201 bool LayoutInline::mapToVisualRectInAncestorSpace( | 1236 bool LayoutInline::mapToVisualRectInAncestorSpace( |
1202 const LayoutBoxModelObject* ancestor, | 1237 const LayoutBoxModelObject* ancestor, |
1203 LayoutRect& rect, | 1238 LayoutRect& rect, |
1204 VisualRectFlags visualRectFlags) const { | 1239 VisualRectFlags visualRectFlags) const { |
1205 if (ancestor == this) | 1240 if (ancestor == this) |
1206 return true; | 1241 return true; |
1207 | 1242 |
1208 LayoutObject* container = this->container(); | 1243 LayoutObject* container = this->container(); |
1209 ASSERT(container == parent()); | 1244 ASSERT(container == parent()); |
1210 if (!container) | 1245 if (!container) |
1211 return true; | 1246 return true; |
1212 | 1247 |
1213 if (style()->hasInFlowPosition() && layer()) { | 1248 if (style()->hasInFlowPosition() && layer()) { |
1214 // Apply the in-flow position offset when invalidating a rectangle. The laye r | 1249 // Apply the in-flow position offset when invalidating a rectangle. The |
1215 // is translated, but the layout box isn't, so we need to do this to get the | 1250 // layer is translated, but the layout box isn't, so we need to do this to |
1216 // right dirty rect. Since this is called from LayoutObject::setStyle, the r elative position | 1251 // get the right dirty rect. Since this is called from LayoutObject:: |
1217 // flag on the LayoutObject has been cleared, so use the one on the style(). | 1252 // setStyle, the relative position flag on the LayoutObject has been |
1253 // cleared, so use the one on the style(). | |
1218 rect.move(layer()->offsetForInFlowPosition()); | 1254 rect.move(layer()->offsetForInFlowPosition()); |
1219 } | 1255 } |
1220 | 1256 |
1221 LayoutBox* containerBox = | 1257 LayoutBox* containerBox = |
1222 container->isBox() ? toLayoutBox(container) : nullptr; | 1258 container->isBox() ? toLayoutBox(container) : nullptr; |
1223 if (containerBox && | 1259 if (containerBox && |
1224 !containerBox->mapScrollingContentsRectToBoxSpace( | 1260 !containerBox->mapScrollingContentsRectToBoxSpace( |
1225 rect, container == ancestor ? ApplyNonScrollOverflowClip | 1261 rect, container == ancestor ? ApplyNonScrollOverflowClip |
1226 : ApplyOverflowClip, | 1262 : ApplyOverflowClip, |
1227 visualRectFlags)) | 1263 visualRectFlags)) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1269 | 1305 |
1270 void LayoutInline::updateHitTestResult(HitTestResult& result, | 1306 void LayoutInline::updateHitTestResult(HitTestResult& result, |
1271 const LayoutPoint& point) { | 1307 const LayoutPoint& point) { |
1272 if (result.innerNode()) | 1308 if (result.innerNode()) |
1273 return; | 1309 return; |
1274 | 1310 |
1275 Node* n = node(); | 1311 Node* n = node(); |
1276 LayoutPoint localPoint(point); | 1312 LayoutPoint localPoint(point); |
1277 if (n) { | 1313 if (n) { |
1278 if (isInlineElementContinuation()) { | 1314 if (isInlineElementContinuation()) { |
1279 // We're in the continuation of a split inline. Adjust our local point to be in the coordinate space | 1315 // We're in the continuation of a split inline. Adjust our local point to |
1280 // of the principal layoutObject's containing block. This will end up bei ng the innerNode. | 1316 // be in the coordinate space of the principal layoutObject's containing |
1317 // block. This will end up being the innerNode. | |
1281 LayoutBlock* firstBlock = n->layoutObject()->containingBlock(); | 1318 LayoutBlock* firstBlock = n->layoutObject()->containingBlock(); |
1282 | 1319 |
1283 // Get our containing block. | 1320 // Get our containing block. |
1284 LayoutBox* block = containingBlock(); | 1321 LayoutBox* block = containingBlock(); |
1285 localPoint.moveBy(block->location() - firstBlock->locationOffset()); | 1322 localPoint.moveBy(block->location() - firstBlock->locationOffset()); |
1286 } | 1323 } |
1287 | 1324 |
1288 result.setNodeAndPosition(n, localPoint); | 1325 result.setNodeAndPosition(n, localPoint); |
1289 } | 1326 } |
1290 } | 1327 } |
1291 | 1328 |
1292 void LayoutInline::dirtyLineBoxes(bool fullLayout) { | 1329 void LayoutInline::dirtyLineBoxes(bool fullLayout) { |
1293 if (fullLayout) { | 1330 if (fullLayout) { |
1294 m_lineBoxes.deleteLineBoxes(); | 1331 m_lineBoxes.deleteLineBoxes(); |
1295 return; | 1332 return; |
1296 } | 1333 } |
1297 | 1334 |
1298 if (!alwaysCreateLineBoxes()) { | 1335 if (!alwaysCreateLineBoxes()) { |
1299 // We have to grovel into our children in order to dirty the appropriate lin es. | 1336 // We have to grovel into our children in order to dirty the appropriate |
1337 // lines. | |
1300 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { | 1338 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { |
1301 if (curr->isFloatingOrOutOfFlowPositioned()) | 1339 if (curr->isFloatingOrOutOfFlowPositioned()) |
1302 continue; | 1340 continue; |
1303 if (curr->isBox() && !curr->needsLayout()) { | 1341 if (curr->isBox() && !curr->needsLayout()) { |
1304 LayoutBox* currBox = toLayoutBox(curr); | 1342 LayoutBox* currBox = toLayoutBox(curr); |
1305 if (currBox->inlineBoxWrapper()) | 1343 if (currBox->inlineBoxWrapper()) |
1306 currBox->inlineBoxWrapper()->root().markDirty(); | 1344 currBox->inlineBoxWrapper()->root().markDirty(); |
1307 } else if (!curr->selfNeedsLayout()) { | 1345 } else if (!curr->selfNeedsLayout()) { |
1308 if (curr->isLayoutInline()) { | 1346 if (curr->isLayoutInline()) { |
1309 LayoutInline* currInline = toLayoutInline(curr); | 1347 LayoutInline* currInline = toLayoutInline(curr); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1361 } | 1399 } |
1362 | 1400 |
1363 LayoutSize LayoutInline::offsetForInFlowPositionedInline( | 1401 LayoutSize LayoutInline::offsetForInFlowPositionedInline( |
1364 const LayoutBox& child) const { | 1402 const LayoutBox& child) const { |
1365 // FIXME: This function isn't right with mixed writing modes. | 1403 // FIXME: This function isn't right with mixed writing modes. |
1366 | 1404 |
1367 ASSERT(isInFlowPositioned()); | 1405 ASSERT(isInFlowPositioned()); |
1368 if (!isInFlowPositioned()) | 1406 if (!isInFlowPositioned()) |
1369 return LayoutSize(); | 1407 return LayoutSize(); |
1370 | 1408 |
1371 // When we have an enclosing relpositioned inline, we need to add in the offse t of the first line | 1409 // When we have an enclosing relpositioned inline, we need to add in the |
1372 // box from the rest of the content, but only in the cases where we know we're positioned | 1410 // offset of the first line box from the rest of the content, but only in the |
1373 // relative to the inline itself. | 1411 // cases where we know we're positioned relative to the inline itself. |
1374 | 1412 |
1375 LayoutSize logicalOffset; | 1413 LayoutSize logicalOffset; |
1376 LayoutUnit inlinePosition; | 1414 LayoutUnit inlinePosition; |
1377 LayoutUnit blockPosition; | 1415 LayoutUnit blockPosition; |
1378 if (firstLineBox()) { | 1416 if (firstLineBox()) { |
1379 inlinePosition = firstLineBox()->logicalLeft(); | 1417 inlinePosition = firstLineBox()->logicalLeft(); |
1380 blockPosition = firstLineBox()->logicalTop(); | 1418 blockPosition = firstLineBox()->logicalTop(); |
1381 } else { | 1419 } else { |
1382 inlinePosition = layer()->staticInlinePosition(); | 1420 inlinePosition = layer()->staticInlinePosition(); |
1383 blockPosition = layer()->staticBlockPosition(); | 1421 blockPosition = layer()->staticBlockPosition(); |
1384 } | 1422 } |
1385 | 1423 |
1386 // Per http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width an absolu te positioned box | 1424 // Per http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width an |
1387 // with a static position should locate itself as though it is a normal flow b ox in relation to | 1425 // absolute positioned box with a static position should locate itself as |
1388 // its containing block. If this relative-positioned inline has a negative off set we need to | 1426 // though it is a normal flow box in relation to its containing block. If this |
1389 // compensate for it so that we align the positioned object with the edge of i ts containing block. | 1427 // relative-positioned inline has a negative offset we need to compensate for |
1428 // it so that we align the positioned object with the edge of its containing | |
1429 // block. | |
1390 if (child.style()->hasStaticInlinePosition( | 1430 if (child.style()->hasStaticInlinePosition( |
1391 style()->isHorizontalWritingMode())) | 1431 style()->isHorizontalWritingMode())) |
1392 logicalOffset.setWidth( | 1432 logicalOffset.setWidth( |
1393 std::max(LayoutUnit(), -offsetForInFlowPosition().width())); | 1433 std::max(LayoutUnit(), -offsetForInFlowPosition().width())); |
1394 else | 1434 else |
1395 logicalOffset.setWidth(inlinePosition); | 1435 logicalOffset.setWidth(inlinePosition); |
1396 | 1436 |
1397 if (!child.style()->hasStaticBlockPosition( | 1437 if (!child.style()->hasStaticBlockPosition( |
1398 style()->isHorizontalWritingMode())) | 1438 style()->isHorizontalWritingMode())) |
1399 logicalOffset.setHeight(blockPosition); | 1439 logicalOffset.setHeight(blockPosition); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1516 paintInvalidator.invalidateDisplayItemClient(*box, invalidationReason); | 1556 paintInvalidator.invalidateDisplayItemClient(*box, invalidationReason); |
1517 } | 1557 } |
1518 | 1558 |
1519 // TODO(lunalu): Not to just dump 0, 0 as the x and y here | 1559 // TODO(lunalu): Not to just dump 0, 0 as the x and y here |
1520 LayoutRect LayoutInline::debugRect() const { | 1560 LayoutRect LayoutInline::debugRect() const { |
1521 IntRect linesBox = enclosingIntRect(linesBoundingBox()); | 1561 IntRect linesBox = enclosingIntRect(linesBoundingBox()); |
1522 return LayoutRect(IntRect(0, 0, linesBox.width(), linesBox.height())); | 1562 return LayoutRect(IntRect(0, 0, linesBox.width(), linesBox.height())); |
1523 } | 1563 } |
1524 | 1564 |
1525 } // namespace blink | 1565 } // namespace blink |
OLD | NEW |