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 | |
291 // the transition to LayoutUnit-based types is complete (crbug.com/321237) | |
292 caretRect.moveBy(firstBox->topLeft()); | 298 caretRect.moveBy(firstBox->topLeft()); |
293 } | |
294 | 299 |
295 return caretRect; | 300 return caretRect; |
296 } | 301 } |
297 | 302 |
298 void LayoutInline::addChild(LayoutObject* newChild, LayoutObject* beforeChild) { | 303 void LayoutInline::addChild(LayoutObject* newChild, LayoutObject* beforeChild) { |
299 // Any table-part dom child of an inline element has anonymous wrappers in the
layout tree | 304 // 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. | 305 // 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. | 306 // and add the new child before that. |
| 307 // TODO(rhogan): If newChild is a table part we want to insert it into the |
| 308 // same table as beforeChild. |
302 while (beforeChild && beforeChild->isTablePart()) | 309 while (beforeChild && beforeChild->isTablePart()) |
303 beforeChild = beforeChild->parent(); | 310 beforeChild = beforeChild->parent(); |
304 if (continuation()) | 311 if (continuation()) |
305 return addChildToContinuation(newChild, beforeChild); | 312 return addChildToContinuation(newChild, beforeChild); |
306 return addChildIgnoringContinuation(newChild, beforeChild); | 313 return addChildIgnoringContinuation(newChild, beforeChild); |
307 } | 314 } |
308 | 315 |
309 static LayoutBoxModelObject* nextContinuation(LayoutObject* layoutObject) { | 316 static LayoutBoxModelObject* nextContinuation(LayoutObject* layoutObject) { |
310 if (layoutObject->isInline() && !layoutObject->isAtomicInlineLevel()) | 317 if (layoutObject->isInline() && !layoutObject->isAtomicInlineLevel()) |
311 return toLayoutInline(layoutObject)->continuation(); | 318 return toLayoutInline(layoutObject)->continuation(); |
(...skipping 20 matching lines...) Expand all Loading... |
332 curr = nextContinuation(curr); | 339 curr = nextContinuation(curr); |
333 } | 340 } |
334 | 341 |
335 if (!beforeChild && !last->slowFirstChild()) | 342 if (!beforeChild && !last->slowFirstChild()) |
336 return nextToLast; | 343 return nextToLast; |
337 return last; | 344 return last; |
338 } | 345 } |
339 | 346 |
340 void LayoutInline::addChildIgnoringContinuation(LayoutObject* newChild, | 347 void LayoutInline::addChildIgnoringContinuation(LayoutObject* newChild, |
341 LayoutObject* beforeChild) { | 348 LayoutObject* beforeChild) { |
342 // Make sure we don't append things after :after-generated content if we have
it. | 349 // Make sure we don't append things after :after-generated content if we have |
| 350 // it. |
343 if (!beforeChild && isAfterContent(lastChild())) | 351 if (!beforeChild && isAfterContent(lastChild())) |
344 beforeChild = lastChild(); | 352 beforeChild = lastChild(); |
345 | 353 |
346 if (!newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned() && | 354 if (!newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned() && |
347 !newChild->isTablePart()) { | 355 !newChild->isTablePart()) { |
348 // We are placing a block inside an inline. We have to perform a split of th
is | 356 // 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 | 357 // 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 | 358 // 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. | 359 // of this inline. We take all of the children after |beforeChild| and put |
| 360 // them in a clone of this object. |
352 RefPtr<ComputedStyle> newStyle = | 361 RefPtr<ComputedStyle> newStyle = |
353 ComputedStyle::createAnonymousStyleWithDisplay( | 362 ComputedStyle::createAnonymousStyleWithDisplay( |
354 containingBlock()->styleRef(), EDisplay::Block); | 363 containingBlock()->styleRef(), EDisplay::Block); |
355 | 364 |
356 // If inside an inline affected by in-flow positioning the block needs to be
affected by it too. | 365 // 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. | 366 // affected by it too. Giving the block a layer like this allows it to |
| 367 // collect the x/y offsets from inline parents later. |
358 if (LayoutObject* positionedAncestor = inFlowPositionedInlineAncestor(this)) | 368 if (LayoutObject* positionedAncestor = inFlowPositionedInlineAncestor(this)) |
359 newStyle->setPosition(positionedAncestor->style()->position()); | 369 newStyle->setPosition(positionedAncestor->style()->position()); |
360 | 370 |
361 LayoutBlockFlow* newBox = LayoutBlockFlow::createAnonymous(&document()); | 371 LayoutBlockFlow* newBox = LayoutBlockFlow::createAnonymous(&document()); |
362 newBox->setStyle(newStyle.release()); | 372 newBox->setStyle(newStyle.release()); |
363 LayoutBoxModelObject* oldContinuation = continuation(); | 373 LayoutBoxModelObject* oldContinuation = continuation(); |
364 setContinuation(newBox); | 374 setContinuation(newBox); |
365 | 375 |
366 splitFlow(beforeChild, newBox, newChild, oldContinuation); | 376 splitFlow(beforeChild, newBox, newChild, oldContinuation); |
367 return; | 377 return; |
(...skipping 25 matching lines...) Expand all Loading... |
393 } | 403 } |
394 | 404 |
395 void LayoutInline::splitInlines(LayoutBlockFlow* fromBlock, | 405 void LayoutInline::splitInlines(LayoutBlockFlow* fromBlock, |
396 LayoutBlockFlow* toBlock, | 406 LayoutBlockFlow* toBlock, |
397 LayoutBlockFlow* middleBlock, | 407 LayoutBlockFlow* middleBlock, |
398 LayoutObject* beforeChild, | 408 LayoutObject* beforeChild, |
399 LayoutBoxModelObject* oldCont) { | 409 LayoutBoxModelObject* oldCont) { |
400 ASSERT(isDescendantOf(fromBlock)); | 410 ASSERT(isDescendantOf(fromBlock)); |
401 | 411 |
402 // If we're splitting the inline containing the fullscreened element, | 412 // If we're splitting the inline containing the fullscreened element, |
403 // |beforeChild| may be the layoutObject for the fullscreened element. However
, | 413 // |beforeChild| may be the layoutObject for the fullscreened element. |
404 // that layoutObject is wrapped in a LayoutFullScreen, so |this| is not its | 414 // However, that layoutObject is wrapped in a LayoutFullScreen, so |this| is |
405 // parent. Since the splitting logic expects |this| to be the parent, set | 415 // not its parent. Since the splitting logic expects |this| to be the parent, |
406 // |beforeChild| to be the LayoutFullScreen. | 416 // set |beforeChild| to be the LayoutFullScreen. |
407 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(document())) { | 417 if (Fullscreen* fullscreen = Fullscreen::fromIfExists(document())) { |
408 const Element* fullScreenElement = fullscreen->currentFullScreenElement(); | 418 const Element* fullScreenElement = fullscreen->currentFullScreenElement(); |
409 if (fullScreenElement && beforeChild && | 419 if (fullScreenElement && beforeChild && |
410 beforeChild->node() == fullScreenElement) | 420 beforeChild->node() == fullScreenElement) |
411 beforeChild = fullscreen->fullScreenLayoutObject(); | 421 beforeChild = fullscreen->fullScreenLayoutObject(); |
412 } | 422 } |
413 | 423 |
414 // FIXME: Because splitting is O(n^2) as tags nest pathologically, we cap the
depth at which we're willing to clone. | 424 // 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 | 425 // 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 | 426 // There will eventually be a better approach to this problem that will let us |
417 // incorrect rendering, but the alternative is to hang forever. | 427 // nest to a much greater depth (see bugzilla bug 13430) but for now we have a |
| 428 // limit. This *will* result in incorrect rendering, but the alternative is to |
| 429 // hang forever. |
418 const unsigned cMaxSplitDepth = 200; | 430 const unsigned cMaxSplitDepth = 200; |
419 Vector<LayoutInline*> inlinesToClone; | 431 Vector<LayoutInline*> inlinesToClone; |
420 LayoutInline* topMostInline = this; | 432 LayoutInline* topMostInline = this; |
421 for (LayoutObject* o = this; o != fromBlock; o = o->parent()) { | 433 for (LayoutObject* o = this; o != fromBlock; o = o->parent()) { |
422 topMostInline = toLayoutInline(o); | 434 topMostInline = toLayoutInline(o); |
423 if (inlinesToClone.size() < cMaxSplitDepth) | 435 if (inlinesToClone.size() < cMaxSplitDepth) |
424 inlinesToClone.append(topMostInline); | 436 inlinesToClone.append(topMostInline); |
425 // Keep walking up the chain to ensure |topMostInline| is a child of |fromBl
ock|, | 437 // 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. | 438 // |fromBlock|, to avoid assertion failure when |fromBlock|'s children are |
| 439 // moved to |toBlock| below. |
427 } | 440 } |
428 | 441 |
429 // Create a new clone of the top-most inline in |inlinesToClone|. | 442 // Create a new clone of the top-most inline in |inlinesToClone|. |
430 LayoutInline* topMostInlineToClone = inlinesToClone.last(); | 443 LayoutInline* topMostInlineToClone = inlinesToClone.last(); |
431 LayoutInline* cloneInline = topMostInlineToClone->clone(); | 444 LayoutInline* cloneInline = topMostInlineToClone->clone(); |
432 | 445 |
433 // Now we are at the block level. We need to put the clone into the |toBlock|. | 446 // Now we are at the block level. We need to put the clone into the |toBlock|. |
434 toBlock->children()->appendChildNode(toBlock, cloneInline); | 447 toBlock->children()->appendChildNode(toBlock, cloneInline); |
435 | 448 |
436 // Now take all the children after |topMostInline| and remove them from the |f
romBlock| | 449 // Now take all the children after |topMostInline| and remove them from the |
437 // and put them into the toBlock. | 450 // |fromBlock| and put them into the toBlock. |
438 fromBlock->moveChildrenTo(toBlock, topMostInline->nextSibling(), nullptr, | 451 fromBlock->moveChildrenTo(toBlock, topMostInline->nextSibling(), nullptr, |
439 true); | 452 true); |
440 | 453 |
441 LayoutInline* currentParent = topMostInlineToClone; | 454 LayoutInline* currentParent = topMostInlineToClone; |
442 LayoutInline* cloneInlineParent = cloneInline; | 455 LayoutInline* cloneInlineParent = cloneInline; |
443 | 456 |
444 // Clone the inlines from top to down to ensure any new object will be added i
nto a rooted tree. | 457 // 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 | 458 // into a rooted tree. |
446 // we have reached |cMaxDepth| in which case we sacrifice correct rendering fo
r performance). | 459 // Note that we have already cloned the top-most one, so the loop begins from |
| 460 // size - 2 (except if we have reached |cMaxDepth| in which case we sacrifice |
| 461 // correct rendering for performance). |
447 for (int i = static_cast<int>(inlinesToClone.size()) - 2; i >= 0; --i) { | 462 for (int i = static_cast<int>(inlinesToClone.size()) - 2; i >= 0; --i) { |
448 // Hook the clone up as a continuation of |currentInline|. | 463 // Hook the clone up as a continuation of |currentInline|. |
449 LayoutBoxModelObject* oldCont = currentParent->continuation(); | 464 LayoutBoxModelObject* oldCont = currentParent->continuation(); |
450 currentParent->setContinuation(cloneInline); | 465 currentParent->setContinuation(cloneInline); |
451 cloneInline->setContinuation(oldCont); | 466 cloneInline->setContinuation(oldCont); |
452 | 467 |
453 // Create a new clone. | 468 // Create a new clone. |
454 LayoutInline* current = inlinesToClone[i]; | 469 LayoutInline* current = inlinesToClone[i]; |
455 cloneInline = current->clone(); | 470 cloneInline = current->clone(); |
456 | 471 |
457 // Insert our |cloneInline| as the first child of |cloneInlineParent|. | 472 // Insert our |cloneInline| as the first child of |cloneInlineParent|. |
458 cloneInlineParent->addChildIgnoringContinuation(cloneInline, nullptr); | 473 cloneInlineParent->addChildIgnoringContinuation(cloneInline, nullptr); |
459 | 474 |
460 // Now we need to take all of the children starting from the first child | 475 // Now we need to take all of the children starting from the first child |
461 // *after* |current| and append them all to the |cloneInlineParent|. | 476 // *after* |current| and append them all to the |cloneInlineParent|. |
462 currentParent->moveChildrenToIgnoringContinuation(cloneInlineParent, | 477 currentParent->moveChildrenToIgnoringContinuation(cloneInlineParent, |
463 current->nextSibling()); | 478 current->nextSibling()); |
464 | 479 |
465 currentParent = current; | 480 currentParent = current; |
466 cloneInlineParent = cloneInline; | 481 cloneInlineParent = cloneInline; |
467 } | 482 } |
468 | 483 |
469 // The last inline to clone is |this|, and the current |cloneInline| is cloned
from |this|. | 484 // The last inline to clone is |this|, and the current |cloneInline| is cloned |
| 485 // from |this|. |
470 ASSERT(this == inlinesToClone.first()); | 486 ASSERT(this == inlinesToClone.first()); |
471 | 487 |
472 // Hook |cloneInline| up as the continuation of the middle block. | 488 // Hook |cloneInline| up as the continuation of the middle block. |
473 cloneInline->setContinuation(oldCont); | 489 cloneInline->setContinuation(oldCont); |
474 middleBlock->setContinuation(cloneInline); | 490 middleBlock->setContinuation(cloneInline); |
475 | 491 |
476 // Now take all of the children from |beforeChild| to the end and remove | 492 // Now take all of the children from |beforeChild| to the end and remove |
477 // them from |this| and place them in the clone. | 493 // them from |this| and place them in the clone. |
478 moveChildrenToIgnoringContinuation(cloneInline, beforeChild); | 494 moveChildrenToIgnoringContinuation(cloneInline, beforeChild); |
479 } | 495 } |
480 | 496 |
481 void LayoutInline::splitFlow(LayoutObject* beforeChild, | 497 void LayoutInline::splitFlow(LayoutObject* beforeChild, |
482 LayoutBlockFlow* newBlockBox, | 498 LayoutBlockFlow* newBlockBox, |
483 LayoutObject* newChild, | 499 LayoutObject* newChild, |
484 LayoutBoxModelObject* oldCont) { | 500 LayoutBoxModelObject* oldCont) { |
485 LayoutBlockFlow* block = toLayoutBlockFlow(containingBlock()); | 501 LayoutBlockFlow* block = toLayoutBlockFlow(containingBlock()); |
486 LayoutBlockFlow* pre = nullptr; | 502 LayoutBlockFlow* pre = nullptr; |
487 | 503 |
488 // Delete our line boxes before we do the inline split into continuations. | 504 // Delete our line boxes before we do the inline split into continuations. |
489 block->deleteLineBoxTree(); | 505 block->deleteLineBoxTree(); |
490 | 506 |
491 bool reusedAnonymousBlock = false; | 507 bool reusedAnonymousBlock = false; |
492 if (block->isAnonymousBlock()) { | 508 if (block->isAnonymousBlock()) { |
493 LayoutBlock* outerContainingBlock = block->containingBlock(); | 509 LayoutBlock* outerContainingBlock = block->containingBlock(); |
494 if (outerContainingBlock && outerContainingBlock->isLayoutBlockFlow() && | 510 if (outerContainingBlock && outerContainingBlock->isLayoutBlockFlow() && |
495 !outerContainingBlock->createsAnonymousWrapper()) { | 511 !outerContainingBlock->createsAnonymousWrapper()) { |
496 // We can reuse this block and make it the preBlock of the next continuati
on. | 512 // We can reuse this block and make it the preBlock of the next |
| 513 // continuation. |
497 block->removePositionedObjects(nullptr); | 514 block->removePositionedObjects(nullptr); |
498 block->removeFloatingObjects(); | 515 block->removeFloatingObjects(); |
499 pre = block; | 516 pre = block; |
500 block = toLayoutBlockFlow(outerContainingBlock); | 517 block = toLayoutBlockFlow(outerContainingBlock); |
501 reusedAnonymousBlock = true; | 518 reusedAnonymousBlock = true; |
502 } | 519 } |
503 } | 520 } |
| 521 |
| 522 // No anonymous block available for use. Make one. |
504 if (!reusedAnonymousBlock) | 523 if (!reusedAnonymousBlock) |
505 pre = toLayoutBlockFlow( | 524 pre = toLayoutBlockFlow(block->createAnonymousBlock()); |
506 block | |
507 ->createAnonymousBlock()); // No anonymous block available for use.
Make one. | |
508 | 525 |
509 LayoutBlockFlow* post = toLayoutBlockFlow(pre->createAnonymousBlock()); | 526 LayoutBlockFlow* post = toLayoutBlockFlow(pre->createAnonymousBlock()); |
510 | 527 |
511 LayoutObject* boxFirst = | 528 LayoutObject* boxFirst = |
512 !reusedAnonymousBlock ? block->firstChild() : pre->nextSibling(); | 529 !reusedAnonymousBlock ? block->firstChild() : pre->nextSibling(); |
513 if (!reusedAnonymousBlock) | 530 if (!reusedAnonymousBlock) |
514 block->children()->insertChildNode(block, pre, boxFirst); | 531 block->children()->insertChildNode(block, pre, boxFirst); |
515 block->children()->insertChildNode(block, newBlockBox, boxFirst); | 532 block->children()->insertChildNode(block, newBlockBox, boxFirst); |
516 block->children()->insertChildNode(block, post, boxFirst); | 533 block->children()->insertChildNode(block, post, boxFirst); |
517 block->setChildrenInline(false); | 534 block->setChildrenInline(false); |
518 | 535 |
519 if (!reusedAnonymousBlock) { | 536 if (!reusedAnonymousBlock) { |
520 LayoutObject* o = boxFirst; | 537 LayoutObject* o = boxFirst; |
521 while (o) { | 538 while (o) { |
522 LayoutObject* no = o; | 539 LayoutObject* no = o; |
523 o = no->nextSibling(); | 540 o = no->nextSibling(); |
524 pre->children()->appendChildNode( | 541 pre->children()->appendChildNode( |
525 pre, block->children()->removeChildNode(block, no)); | 542 pre, block->children()->removeChildNode(block, no)); |
526 no->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 543 no->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
527 LayoutInvalidationReason::AnonymousBlockChange); | 544 LayoutInvalidationReason::AnonymousBlockChange); |
528 } | 545 } |
529 } | 546 } |
530 | 547 |
531 splitInlines(pre, post, newBlockBox, beforeChild, oldCont); | 548 splitInlines(pre, post, newBlockBox, beforeChild, oldCont); |
532 | 549 |
533 // We already know the newBlockBox isn't going to contain inline kids, so avoi
d wasting | 550 // We already know the newBlockBox isn't going to contain inline kids, so |
534 // time in makeChildrenNonInline by just setting this explicitly up front. | 551 // avoid wasting time in makeChildrenNonInline by just setting this explicitly |
| 552 // up front. |
535 newBlockBox->setChildrenInline(false); | 553 newBlockBox->setChildrenInline(false); |
536 | 554 |
537 newBlockBox->addChild(newChild); | 555 newBlockBox->addChild(newChild); |
538 | 556 |
539 // Always just do a full layout in order to ensure that line boxes (especially
wrappers for images) | 557 // 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 | 558 // wrappers for images) get deleted properly. Because objects moves from the |
541 // make new line boxes instead of leaving the old line boxes around. | 559 // pre block into the post block, we want to make new line boxes instead of |
| 560 // leaving the old line boxes around. |
542 pre->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 561 pre->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
543 LayoutInvalidationReason::AnonymousBlockChange); | 562 LayoutInvalidationReason::AnonymousBlockChange); |
544 block->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 563 block->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
545 LayoutInvalidationReason::AnonymousBlockChange); | 564 LayoutInvalidationReason::AnonymousBlockChange); |
546 post->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( | 565 post->setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation( |
547 LayoutInvalidationReason::AnonymousBlockChange); | 566 LayoutInvalidationReason::AnonymousBlockChange); |
548 } | 567 } |
549 | 568 |
550 void LayoutInline::addChildToContinuation(LayoutObject* newChild, | 569 void LayoutInline::addChildToContinuation(LayoutObject* newChild, |
551 LayoutObject* beforeChild) { | 570 LayoutObject* beforeChild) { |
552 // A continuation always consists of two potential candidates: an inline or an
anonymous | 571 // A continuation always consists of two potential candidates: an inline or an |
553 // block box holding block children. | 572 // anonymous block box holding block children. |
554 LayoutBoxModelObject* flow = continuationBefore(beforeChild); | 573 LayoutBoxModelObject* flow = continuationBefore(beforeChild); |
555 ASSERT(!beforeChild || beforeChild->parent()->isAnonymousBlock() || | 574 ASSERT(!beforeChild || beforeChild->parent()->isAnonymousBlock() || |
556 beforeChild->parent()->isLayoutInline()); | 575 beforeChild->parent()->isLayoutInline()); |
557 LayoutBoxModelObject* beforeChildParent = nullptr; | 576 LayoutBoxModelObject* beforeChildParent = nullptr; |
558 if (beforeChild) { | 577 if (beforeChild) { |
559 beforeChildParent = toLayoutBoxModelObject(beforeChild->parent()); | 578 beforeChildParent = toLayoutBoxModelObject(beforeChild->parent()); |
560 } else { | 579 } else { |
561 LayoutBoxModelObject* cont = nextContinuation(flow); | 580 LayoutBoxModelObject* cont = nextContinuation(flow); |
562 if (cont) | 581 if (cont) |
563 beforeChildParent = cont; | 582 beforeChildParent = cont; |
564 else | 583 else |
565 beforeChildParent = flow; | 584 beforeChildParent = flow; |
566 } | 585 } |
567 | 586 |
568 // TODO(rhogan): Should we treat out-of-flows and floats as through they're in
line below? | 587 // TODO(rhogan): Should we treat out-of-flows and floats as through they're |
| 588 // inline below? |
569 if (newChild->isFloatingOrOutOfFlowPositioned()) | 589 if (newChild->isFloatingOrOutOfFlowPositioned()) |
570 return beforeChildParent->addChildIgnoringContinuation(newChild, | 590 return beforeChildParent->addChildIgnoringContinuation(newChild, |
571 beforeChild); | 591 beforeChild); |
572 | 592 |
573 // A table part will be wrapped by an inline anonymous table when it is added
to the layout | 593 // 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. | 594 // to the layout tree, so treat it as inline when deciding where to add it. |
575 bool childInline = newChild->isInline() || newChild->isTablePart(); | 595 bool childInline = newChild->isInline() || newChild->isTablePart(); |
576 bool bcpInline = beforeChildParent->isInline(); | 596 bool bcpInline = beforeChildParent->isInline(); |
577 bool flowInline = flow->isInline(); | 597 bool flowInline = flow->isInline(); |
578 | 598 |
579 if (flow == beforeChildParent) | 599 if (flow == beforeChildParent) |
580 return flow->addChildIgnoringContinuation(newChild, beforeChild); | 600 return flow->addChildIgnoringContinuation(newChild, beforeChild); |
581 | 601 |
582 // The goal here is to match up if we can, so that we can coalesce and create
the | 602 // 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. | 603 // the minimal # of continuations needed for the inline. |
584 if (childInline == bcpInline || (beforeChild && beforeChild->isInline())) | 604 if (childInline == bcpInline || (beforeChild && beforeChild->isInline())) |
585 return beforeChildParent->addChildIgnoringContinuation(newChild, | 605 return beforeChildParent->addChildIgnoringContinuation(newChild, |
586 beforeChild); | 606 beforeChild); |
587 if (flowInline == childInline) | 607 if (flowInline == childInline) { |
588 return flow->addChildIgnoringContinuation(newChild, | 608 // Just treat like an append. |
589 0); // Just treat like an append. | 609 return flow->addChildIgnoringContinuation(newChild, 0); |
| 610 } |
590 return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); | 611 return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild); |
591 } | 612 } |
592 | 613 |
593 void LayoutInline::paint(const PaintInfo& paintInfo, | 614 void LayoutInline::paint(const PaintInfo& paintInfo, |
594 const LayoutPoint& paintOffset) const { | 615 const LayoutPoint& paintOffset) const { |
595 InlinePainter(*this).paint(paintInfo, paintOffset); | 616 InlinePainter(*this).paint(paintInfo, paintOffset); |
596 } | 617 } |
597 | 618 |
598 template <typename GeneratorContext> | 619 template <typename GeneratorContext> |
599 void LayoutInline::generateLineBoxRects(GeneratorContext& yield) const { | 620 void LayoutInline::generateLineBoxRects(GeneratorContext& yield) const { |
(...skipping 11 matching lines...) Expand all Loading... |
611 const LayoutInline* container) const { | 632 const LayoutInline* container) const { |
612 if (!culledInlineFirstLineBox()) | 633 if (!culledInlineFirstLineBox()) |
613 return; | 634 return; |
614 | 635 |
615 bool isHorizontal = style()->isHorizontalWritingMode(); | 636 bool isHorizontal = style()->isHorizontalWritingMode(); |
616 | 637 |
617 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { | 638 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { |
618 if (curr->isFloatingOrOutOfFlowPositioned()) | 639 if (curr->isFloatingOrOutOfFlowPositioned()) |
619 continue; | 640 continue; |
620 | 641 |
621 // We want to get the margin box in the inline direction, and then use our f
ont ascent/descent in the block | 642 // We want to get the margin box in the inline direction, and then use our |
622 // direction (aligned to the root box's baseline). | 643 // font ascent/descent in the block direction (aligned to the root box's |
| 644 // baseline). |
623 if (curr->isBox()) { | 645 if (curr->isBox()) { |
624 LayoutBox* currBox = toLayoutBox(curr); | 646 LayoutBox* currBox = toLayoutBox(curr); |
625 if (currBox->inlineBoxWrapper()) { | 647 if (currBox->inlineBoxWrapper()) { |
626 RootInlineBox& rootBox = currBox->inlineBoxWrapper()->root(); | 648 RootInlineBox& rootBox = currBox->inlineBoxWrapper()->root(); |
627 LayoutUnit logicalTop = | 649 LayoutUnit logicalTop = |
628 rootBox.logicalTop() + (rootBox.getLineLayoutItem() | 650 rootBox.logicalTop() + (rootBox.getLineLayoutItem() |
629 .style(rootBox.isFirstLineStyle()) | 651 .style(rootBox.isFirstLineStyle()) |
630 ->font() | 652 ->font() |
631 .getFontMetrics() | 653 .getFontMetrics() |
632 .ascent() - | 654 .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 | 962 // If there are continuations, test them first because our containing block |
941 // will not check them. | 963 // will not check them. |
942 LayoutBoxModelObject* continuation = this->continuation(); | 964 LayoutBoxModelObject* continuation = this->continuation(); |
943 while (continuation) { | 965 while (continuation) { |
944 if (continuation->isInline() || continuation->slowFirstChild()) | 966 if (continuation->isInline() || continuation->slowFirstChild()) |
945 return continuation->positionForPoint(point); | 967 return continuation->positionForPoint(point); |
946 continuation = toLayoutBlockFlow(continuation)->inlineElementContinuation(); | 968 continuation = toLayoutBlockFlow(continuation)->inlineElementContinuation(); |
947 } | 969 } |
948 | 970 |
949 if (firstLineBoxIncludingCulling()) { | 971 if (firstLineBoxIncludingCulling()) { |
950 // This inline actually has a line box. We must have clicked in the border/
padding of one of these boxes. We | 972 // This inline actually has a line box. We must have clicked in the |
| 973 // border/padding of one of these boxes. We |
951 // should try to find a result by asking our containing block. | 974 // should try to find a result by asking our containing block. |
952 return containingBlock()->positionForPoint(point); | 975 return containingBlock()->positionForPoint(point); |
953 } | 976 } |
954 | 977 |
955 return LayoutBoxModelObject::positionForPoint(point); | 978 return LayoutBoxModelObject::positionForPoint(point); |
956 } | 979 } |
957 | 980 |
958 namespace { | 981 namespace { |
959 | 982 |
960 class LinesBoundingBoxGeneratorContext { | 983 class LinesBoundingBoxGeneratorContext { |
(...skipping 12 matching lines...) Expand all Loading... |
973 if (!alwaysCreateLineBoxes()) { | 996 if (!alwaysCreateLineBoxes()) { |
974 ASSERT(!firstLineBox()); | 997 ASSERT(!firstLineBox()); |
975 FloatRect floatResult; | 998 FloatRect floatResult; |
976 LinesBoundingBoxGeneratorContext context(floatResult); | 999 LinesBoundingBoxGeneratorContext context(floatResult); |
977 generateCulledLineBoxRects(context, this); | 1000 generateCulledLineBoxRects(context, this); |
978 return enclosingLayoutRect(floatResult); | 1001 return enclosingLayoutRect(floatResult); |
979 } | 1002 } |
980 | 1003 |
981 LayoutRect result; | 1004 LayoutRect result; |
982 | 1005 |
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 | 1006 // 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 | 1007 // 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. | 1008 // unable to reproduce this at all (and consequently unable to figure ot why |
| 1009 // this is happening). The assert will hopefully catch the problem in debug |
| 1010 // builds and help us someday figure out why. We also put in a redundant |
| 1011 // check of lastLineBox() to avoid the crash for now. |
986 ASSERT(!firstLineBox() == | 1012 ASSERT(!firstLineBox() == |
987 !lastLineBox()); // Either both are null or both exist. | 1013 !lastLineBox()); // Either both are null or both exist. |
988 if (firstLineBox() && lastLineBox()) { | 1014 if (firstLineBox() && lastLineBox()) { |
989 // Return the width of the minimal left side and the maximal right side. | 1015 // Return the width of the minimal left side and the maximal right side. |
990 LayoutUnit logicalLeftSide; | 1016 LayoutUnit logicalLeftSide; |
991 LayoutUnit logicalRightSide; | 1017 LayoutUnit logicalRightSide; |
992 for (InlineFlowBox* curr = firstLineBox(); curr; | 1018 for (InlineFlowBox* curr = firstLineBox(); curr; |
993 curr = curr->nextLineBox()) { | 1019 curr = curr->nextLineBox()) { |
994 if (curr == firstLineBox() || curr->logicalLeft() < logicalLeftSide) | 1020 if (curr == firstLineBox() || curr->logicalLeft() < logicalLeftSide) |
995 logicalLeftSide = curr->logicalLeft(); | 1021 logicalLeftSide = curr->logicalLeft(); |
(...skipping 13 matching lines...) Expand all Loading... |
1009 } | 1035 } |
1010 | 1036 |
1011 return result; | 1037 return result; |
1012 } | 1038 } |
1013 | 1039 |
1014 InlineBox* LayoutInline::culledInlineFirstLineBox() const { | 1040 InlineBox* LayoutInline::culledInlineFirstLineBox() const { |
1015 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { | 1041 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { |
1016 if (curr->isFloatingOrOutOfFlowPositioned()) | 1042 if (curr->isFloatingOrOutOfFlowPositioned()) |
1017 continue; | 1043 continue; |
1018 | 1044 |
1019 // We want to get the margin box in the inline direction, and then use our f
ont ascent/descent in the block | 1045 // We want to get the margin box in the inline direction, and then use our |
1020 // direction (aligned to the root box's baseline). | 1046 // font ascent/descent in the block direction (aligned to the root box's |
| 1047 // baseline). |
1021 if (curr->isBox()) | 1048 if (curr->isBox()) |
1022 return toLayoutBox(curr)->inlineBoxWrapper(); | 1049 return toLayoutBox(curr)->inlineBoxWrapper(); |
1023 if (curr->isLayoutInline()) { | 1050 if (curr->isLayoutInline()) { |
1024 LayoutInline* currInline = toLayoutInline(curr); | 1051 LayoutInline* currInline = toLayoutInline(curr); |
1025 InlineBox* result = currInline->firstLineBoxIncludingCulling(); | 1052 InlineBox* result = currInline->firstLineBoxIncludingCulling(); |
1026 if (result) | 1053 if (result) |
1027 return result; | 1054 return result; |
1028 } else if (curr->isText()) { | 1055 } else if (curr->isText()) { |
1029 LayoutText* currText = toLayoutText(curr); | 1056 LayoutText* currText = toLayoutText(curr); |
1030 if (currText->firstTextBox()) | 1057 if (currText->firstTextBox()) |
1031 return currText->firstTextBox(); | 1058 return currText->firstTextBox(); |
1032 } | 1059 } |
1033 } | 1060 } |
1034 return nullptr; | 1061 return nullptr; |
1035 } | 1062 } |
1036 | 1063 |
1037 InlineBox* LayoutInline::culledInlineLastLineBox() const { | 1064 InlineBox* LayoutInline::culledInlineLastLineBox() const { |
1038 for (LayoutObject* curr = lastChild(); curr; curr = curr->previousSibling()) { | 1065 for (LayoutObject* curr = lastChild(); curr; curr = curr->previousSibling()) { |
1039 if (curr->isFloatingOrOutOfFlowPositioned()) | 1066 if (curr->isFloatingOrOutOfFlowPositioned()) |
1040 continue; | 1067 continue; |
1041 | 1068 |
1042 // We want to get the margin box in the inline direction, and then use our f
ont ascent/descent in the block | 1069 // We want to get the margin box in the inline direction, and then use our |
1043 // direction (aligned to the root box's baseline). | 1070 // font ascent/descent in the block direction (aligned to the root box's |
| 1071 // baseline). |
1044 if (curr->isBox()) | 1072 if (curr->isBox()) |
1045 return toLayoutBox(curr)->inlineBoxWrapper(); | 1073 return toLayoutBox(curr)->inlineBoxWrapper(); |
1046 if (curr->isLayoutInline()) { | 1074 if (curr->isLayoutInline()) { |
1047 LayoutInline* currInline = toLayoutInline(curr); | 1075 LayoutInline* currInline = toLayoutInline(curr); |
1048 InlineBox* result = currInline->lastLineBoxIncludingCulling(); | 1076 InlineBox* result = currInline->lastLineBoxIncludingCulling(); |
1049 if (result) | 1077 if (result) |
1050 return result; | 1078 return result; |
1051 } else if (curr->isText()) { | 1079 } else if (curr->isText()) { |
1052 LayoutText* currText = toLayoutText(curr); | 1080 LayoutText* currText = toLayoutText(curr); |
1053 if (currText->lastTextBox()) | 1081 if (currText->lastTextBox()) |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1172 | 1200 |
1173 return visualOverflowRect(); | 1201 return visualOverflowRect(); |
1174 } | 1202 } |
1175 | 1203 |
1176 LayoutRect LayoutInline::visualOverflowRect() const { | 1204 LayoutRect LayoutInline::visualOverflowRect() const { |
1177 LayoutRect overflowRect = linesVisualOverflowBoundingBox(); | 1205 LayoutRect overflowRect = linesVisualOverflowBoundingBox(); |
1178 LayoutUnit outlineOutset(style()->outlineOutsetExtent()); | 1206 LayoutUnit outlineOutset(style()->outlineOutsetExtent()); |
1179 if (outlineOutset) { | 1207 if (outlineOutset) { |
1180 Vector<LayoutRect> rects; | 1208 Vector<LayoutRect> rects; |
1181 if (document().inNoQuirksMode()) { | 1209 if (document().inNoQuirksMode()) { |
1182 // We have already included outline extents of line boxes in linesVisualOv
erflowBoundingBox(), | 1210 // We have already included outline extents of line boxes in |
1183 // so the following just add outline rects for children and continuations. | 1211 // linesVisualOverflowBoundingBox(), so the following just add outline |
| 1212 // rects for children and continuations. |
1184 addOutlineRectsForChildrenAndContinuations( | 1213 addOutlineRectsForChildrenAndContinuations( |
1185 rects, LayoutPoint(), outlineRectsShouldIncludeBlockVisualOverflow()); | 1214 rects, LayoutPoint(), outlineRectsShouldIncludeBlockVisualOverflow()); |
1186 } else { | 1215 } else { |
1187 // In non-standard mode, because the difference in LayoutBlock::minLineHei
ghtForReplacedObject(), | 1216 // In non-standard mode, because the difference in |
1188 // linesVisualOverflowBoundingBox() may not cover outline rects of lines c
ontaining replaced objects. | 1217 // LayoutBlock::minLineHeightForReplacedObject(), |
| 1218 // linesVisualOverflowBoundingBox() may not cover outline rects of lines |
| 1219 // containing replaced objects. |
1189 addOutlineRects(rects, LayoutPoint(), | 1220 addOutlineRects(rects, LayoutPoint(), |
1190 outlineRectsShouldIncludeBlockVisualOverflow()); | 1221 outlineRectsShouldIncludeBlockVisualOverflow()); |
1191 } | 1222 } |
1192 if (!rects.isEmpty()) { | 1223 if (!rects.isEmpty()) { |
1193 LayoutRect outlineRect = unionRectEvenIfEmpty(rects); | 1224 LayoutRect outlineRect = unionRectEvenIfEmpty(rects); |
1194 outlineRect.inflate(outlineOutset); | 1225 outlineRect.inflate(outlineOutset); |
1195 overflowRect.unite(outlineRect); | 1226 overflowRect.unite(outlineRect); |
1196 } | 1227 } |
1197 } | 1228 } |
1198 return overflowRect; | 1229 return overflowRect; |
1199 } | 1230 } |
1200 | 1231 |
1201 bool LayoutInline::mapToVisualRectInAncestorSpace( | 1232 bool LayoutInline::mapToVisualRectInAncestorSpace( |
1202 const LayoutBoxModelObject* ancestor, | 1233 const LayoutBoxModelObject* ancestor, |
1203 LayoutRect& rect, | 1234 LayoutRect& rect, |
1204 VisualRectFlags visualRectFlags) const { | 1235 VisualRectFlags visualRectFlags) const { |
1205 if (ancestor == this) | 1236 if (ancestor == this) |
1206 return true; | 1237 return true; |
1207 | 1238 |
1208 LayoutObject* container = this->container(); | 1239 LayoutObject* container = this->container(); |
1209 ASSERT(container == parent()); | 1240 ASSERT(container == parent()); |
1210 if (!container) | 1241 if (!container) |
1211 return true; | 1242 return true; |
1212 | 1243 |
1213 if (style()->hasInFlowPosition() && layer()) { | 1244 if (style()->hasInFlowPosition() && layer()) { |
1214 // Apply the in-flow position offset when invalidating a rectangle. The laye
r | 1245 // 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 | 1246 // 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 | 1247 // 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(). | 1248 // setStyle, the relative position flag on the LayoutObject has been |
| 1249 // cleared, so use the one on the style(). |
1218 rect.move(layer()->offsetForInFlowPosition()); | 1250 rect.move(layer()->offsetForInFlowPosition()); |
1219 } | 1251 } |
1220 | 1252 |
1221 LayoutBox* containerBox = | 1253 LayoutBox* containerBox = |
1222 container->isBox() ? toLayoutBox(container) : nullptr; | 1254 container->isBox() ? toLayoutBox(container) : nullptr; |
1223 if (containerBox && | 1255 if (containerBox && |
1224 !containerBox->mapScrollingContentsRectToBoxSpace( | 1256 !containerBox->mapScrollingContentsRectToBoxSpace( |
1225 rect, container == ancestor ? ApplyNonScrollOverflowClip | 1257 rect, container == ancestor ? ApplyNonScrollOverflowClip |
1226 : ApplyOverflowClip, | 1258 : ApplyOverflowClip, |
1227 visualRectFlags)) | 1259 visualRectFlags)) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1269 | 1301 |
1270 void LayoutInline::updateHitTestResult(HitTestResult& result, | 1302 void LayoutInline::updateHitTestResult(HitTestResult& result, |
1271 const LayoutPoint& point) { | 1303 const LayoutPoint& point) { |
1272 if (result.innerNode()) | 1304 if (result.innerNode()) |
1273 return; | 1305 return; |
1274 | 1306 |
1275 Node* n = node(); | 1307 Node* n = node(); |
1276 LayoutPoint localPoint(point); | 1308 LayoutPoint localPoint(point); |
1277 if (n) { | 1309 if (n) { |
1278 if (isInlineElementContinuation()) { | 1310 if (isInlineElementContinuation()) { |
1279 // We're in the continuation of a split inline. Adjust our local point to
be in the coordinate space | 1311 // 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. | 1312 // be in the coordinate space of the principal layoutObject's containing |
| 1313 // block. This will end up being the innerNode. |
1281 LayoutBlock* firstBlock = n->layoutObject()->containingBlock(); | 1314 LayoutBlock* firstBlock = n->layoutObject()->containingBlock(); |
1282 | 1315 |
1283 // Get our containing block. | 1316 // Get our containing block. |
1284 LayoutBox* block = containingBlock(); | 1317 LayoutBox* block = containingBlock(); |
1285 localPoint.moveBy(block->location() - firstBlock->locationOffset()); | 1318 localPoint.moveBy(block->location() - firstBlock->locationOffset()); |
1286 } | 1319 } |
1287 | 1320 |
1288 result.setNodeAndPosition(n, localPoint); | 1321 result.setNodeAndPosition(n, localPoint); |
1289 } | 1322 } |
1290 } | 1323 } |
1291 | 1324 |
1292 void LayoutInline::dirtyLineBoxes(bool fullLayout) { | 1325 void LayoutInline::dirtyLineBoxes(bool fullLayout) { |
1293 if (fullLayout) { | 1326 if (fullLayout) { |
1294 m_lineBoxes.deleteLineBoxes(); | 1327 m_lineBoxes.deleteLineBoxes(); |
1295 return; | 1328 return; |
1296 } | 1329 } |
1297 | 1330 |
1298 if (!alwaysCreateLineBoxes()) { | 1331 if (!alwaysCreateLineBoxes()) { |
1299 // We have to grovel into our children in order to dirty the appropriate lin
es. | 1332 // We have to grovel into our children in order to dirty the appropriate |
| 1333 // lines. |
1300 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { | 1334 for (LayoutObject* curr = firstChild(); curr; curr = curr->nextSibling()) { |
1301 if (curr->isFloatingOrOutOfFlowPositioned()) | 1335 if (curr->isFloatingOrOutOfFlowPositioned()) |
1302 continue; | 1336 continue; |
1303 if (curr->isBox() && !curr->needsLayout()) { | 1337 if (curr->isBox() && !curr->needsLayout()) { |
1304 LayoutBox* currBox = toLayoutBox(curr); | 1338 LayoutBox* currBox = toLayoutBox(curr); |
1305 if (currBox->inlineBoxWrapper()) | 1339 if (currBox->inlineBoxWrapper()) |
1306 currBox->inlineBoxWrapper()->root().markDirty(); | 1340 currBox->inlineBoxWrapper()->root().markDirty(); |
1307 } else if (!curr->selfNeedsLayout()) { | 1341 } else if (!curr->selfNeedsLayout()) { |
1308 if (curr->isLayoutInline()) { | 1342 if (curr->isLayoutInline()) { |
1309 LayoutInline* currInline = toLayoutInline(curr); | 1343 LayoutInline* currInline = toLayoutInline(curr); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1361 } | 1395 } |
1362 | 1396 |
1363 LayoutSize LayoutInline::offsetForInFlowPositionedInline( | 1397 LayoutSize LayoutInline::offsetForInFlowPositionedInline( |
1364 const LayoutBox& child) const { | 1398 const LayoutBox& child) const { |
1365 // FIXME: This function isn't right with mixed writing modes. | 1399 // FIXME: This function isn't right with mixed writing modes. |
1366 | 1400 |
1367 ASSERT(isInFlowPositioned()); | 1401 ASSERT(isInFlowPositioned()); |
1368 if (!isInFlowPositioned()) | 1402 if (!isInFlowPositioned()) |
1369 return LayoutSize(); | 1403 return LayoutSize(); |
1370 | 1404 |
1371 // When we have an enclosing relpositioned inline, we need to add in the offse
t of the first line | 1405 // 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 | 1406 // offset of the first line box from the rest of the content, but only in the |
1373 // relative to the inline itself. | 1407 // cases where we know we're positioned relative to the inline itself. |
1374 | 1408 |
1375 LayoutSize logicalOffset; | 1409 LayoutSize logicalOffset; |
1376 LayoutUnit inlinePosition; | 1410 LayoutUnit inlinePosition; |
1377 LayoutUnit blockPosition; | 1411 LayoutUnit blockPosition; |
1378 if (firstLineBox()) { | 1412 if (firstLineBox()) { |
1379 inlinePosition = firstLineBox()->logicalLeft(); | 1413 inlinePosition = firstLineBox()->logicalLeft(); |
1380 blockPosition = firstLineBox()->logicalTop(); | 1414 blockPosition = firstLineBox()->logicalTop(); |
1381 } else { | 1415 } else { |
1382 inlinePosition = layer()->staticInlinePosition(); | 1416 inlinePosition = layer()->staticInlinePosition(); |
1383 blockPosition = layer()->staticBlockPosition(); | 1417 blockPosition = layer()->staticBlockPosition(); |
1384 } | 1418 } |
1385 | 1419 |
1386 // Per http://www.w3.org/TR/CSS2/visudet.html#abs-non-replaced-width an absolu
te positioned box | 1420 // 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 | 1421 // 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 | 1422 // 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. | 1423 // relative-positioned inline has a negative offset we need to compensate for |
| 1424 // it so that we align the positioned object with the edge of its containing |
| 1425 // block. |
1390 if (child.style()->hasStaticInlinePosition( | 1426 if (child.style()->hasStaticInlinePosition( |
1391 style()->isHorizontalWritingMode())) | 1427 style()->isHorizontalWritingMode())) |
1392 logicalOffset.setWidth( | 1428 logicalOffset.setWidth( |
1393 std::max(LayoutUnit(), -offsetForInFlowPosition().width())); | 1429 std::max(LayoutUnit(), -offsetForInFlowPosition().width())); |
1394 else | 1430 else |
1395 logicalOffset.setWidth(inlinePosition); | 1431 logicalOffset.setWidth(inlinePosition); |
1396 | 1432 |
1397 if (!child.style()->hasStaticBlockPosition( | 1433 if (!child.style()->hasStaticBlockPosition( |
1398 style()->isHorizontalWritingMode())) | 1434 style()->isHorizontalWritingMode())) |
1399 logicalOffset.setHeight(blockPosition); | 1435 logicalOffset.setHeight(blockPosition); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1516 paintInvalidator.invalidateDisplayItemClient(*box, invalidationReason); | 1552 paintInvalidator.invalidateDisplayItemClient(*box, invalidationReason); |
1517 } | 1553 } |
1518 | 1554 |
1519 // TODO(lunalu): Not to just dump 0, 0 as the x and y here | 1555 // TODO(lunalu): Not to just dump 0, 0 as the x and y here |
1520 LayoutRect LayoutInline::debugRect() const { | 1556 LayoutRect LayoutInline::debugRect() const { |
1521 IntRect linesBox = enclosingIntRect(linesBoundingBox()); | 1557 IntRect linesBox = enclosingIntRect(linesBoundingBox()); |
1522 return LayoutRect(IntRect(0, 0, linesBox.width(), linesBox.height())); | 1558 return LayoutRect(IntRect(0, 0, linesBox.width(), linesBox.height())); |
1523 } | 1559 } |
1524 | 1560 |
1525 } // namespace blink | 1561 } // namespace blink |
OLD | NEW |