Chromium Code Reviews| 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 |