2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
5 * (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
6 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
7 * Copyright (C) 2010 Google Inc. All rights reserved.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
27 #include "core/rendering/RenderBoxModelObject.h"
29 #include "core/page/scrolling/ScrollingConstraints.h"
30 #include "core/rendering/ImageQualityController.h"
31 #include "core/rendering/RenderBlock.h"
32 #include "core/rendering/RenderFlowThread.h"
33 #include "core/rendering/RenderGeometryMap.h"
34 #include "core/rendering/RenderInline.h"
35 #include "core/rendering/RenderLayer.h"
36 #include "core/rendering/RenderObjectInlines.h"
37 #include "core/rendering/RenderRegion.h"
38 #include "core/rendering/RenderTextFragment.h"
39 #include "core/rendering/RenderView.h"
40 #include "core/rendering/compositing/CompositedLayerMapping.h"
41 #include "core/rendering/compositing/RenderLayerCompositor.h"
42 #include "core/rendering/style/BorderEdge.h"
43 #include "core/rendering/style/ShadowList.h"
44 #include "platform/LengthFunctions.h"
45 #include "platform/geometry/TransformState.h"
46 #include "platform/graphics/DrawLooperBuilder.h"
47 #include "platform/graphics/GraphicsContextStateSaver.h"
48 #include "platform/graphics/Path.h"
49 #include "wtf/CurrentTime.h"
53 // The HashMap for storing continuation pointers.
54 // An inline can be split with blocks occuring in between the inline content.
55 // When this occurs we need a pointer to the next object. We can basically be
56 // split into a sequence of inlines and blocks. The continuation will either be
57 // an anonymous block (that houses other blocks) or it will be an inline flow.
58 // <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as
59 // its continuation but the <b> will just have an inline as its continuation.
60 typedef WillBeHeapHashMap<RawPtrWillBeMember<const RenderBoxModelObject>, RawPtrWillBeMember<RenderBoxModelObject> > ContinuationMap;
61 static OwnPtrWillBePersistent<ContinuationMap>* continuationMap = 0;
63 // This HashMap is similar to the continuation map, but connects first-letter
64 // renderers to their remaining text fragments.
65 typedef WillBeHeapHashMap<RawPtrWillBeMember<const RenderBoxModelObject>, RawPtrWillBeMember<RenderTextFragment> > FirstLetterRemainingTextMap;
66 static OwnPtrWillBePersistent<FirstLetterRemainingTextMap>* firstLetterRemainingTextMap = 0;
68 void RenderBoxModelObject::setSelectionState(SelectionState state)
70 if (state == SelectionInside && selectionState() != SelectionNone)
73 if ((state == SelectionStart && selectionState() == SelectionEnd)
74 || (state == SelectionEnd && selectionState() == SelectionStart))
75 RenderObject::setSelectionState(SelectionBoth);
77 RenderObject::setSelectionState(state);
79 // FIXME: We should consider whether it is OK propagating to ancestor RenderInlines.
80 // This is a workaround for http://webkit.org/b/32123
81 // The containing block can be null in case of an orphaned tree.
82 RenderBlock* containingBlock = this->containingBlock();
83 if (containingBlock && !containingBlock->isRenderView())
84 containingBlock->setSelectionState(state);
87 void RenderBoxModelObject::contentChanged(ContentChangeType changeType)
92 layer()->contentChanged(changeType);
95 bool RenderBoxModelObject::hasAcceleratedCompositing() const
97 return view()->compositor()->hasAcceleratedCompositing();
100 RenderBoxModelObject::RenderBoxModelObject(ContainerNode* node)
101 : RenderLayerModelObject(node)
105 RenderBoxModelObject::~RenderBoxModelObject()
109 void RenderBoxModelObject::willBeDestroyed()
111 ImageQualityController::remove(this);
113 // A continuation of this RenderObject should be destroyed at subclasses.
114 ASSERT(!continuation());
116 // If this is a first-letter object with a remaining text fragment then the
117 // entry needs to be cleared from the map.
118 if (firstLetterRemainingText())
119 setFirstLetterRemainingText(0);
121 RenderLayerModelObject::willBeDestroyed();
124 bool RenderBoxModelObject::calculateHasBoxDecorations() const
126 RenderStyle* styleToUse = style();
128 return hasBackground() || styleToUse->hasBorder() || styleToUse->hasAppearance() || styleToUse->boxShadow();
131 void RenderBoxModelObject::updateFromStyle()
133 RenderLayerModelObject::updateFromStyle();
135 RenderStyle* styleToUse = style();
136 setHasBoxDecorationBackground(calculateHasBoxDecorations());
137 setInline(styleToUse->isDisplayInlineType());
138 setPositionState(styleToUse->position());
139 setHorizontalWritingMode(styleToUse->isHorizontalWritingMode());
142 static LayoutSize accumulateInFlowPositionOffsets(const RenderObject* child)
144 if (!child->isAnonymousBlock() || !child->isRelPositioned())
147 RenderObject* p = toRenderBlock(child)->inlineElementContinuation();
148 while (p && p->isRenderInline()) {
149 if (p->isRelPositioned()) {
150 RenderInline* renderInline = toRenderInline(p);
151 offset += renderInline->offsetForInFlowPosition();
158 bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const
160 Length logicalHeightLength = style()->logicalHeight();
161 if (logicalHeightLength.isAuto())
164 // For percentage heights: The percentage is calculated with respect to the height of the generated box's
165 // containing block. If the height of the containing block is not specified explicitly (i.e., it depends
166 // on content height), and this element is not absolutely positioned, the value computes to 'auto'.
167 if (!logicalHeightLength.isPercent() || isOutOfFlowPositioned() || document().inQuirksMode())
170 // Anonymous block boxes are ignored when resolving percentage values that would refer to it:
171 // the closest non-anonymous ancestor box is used instead.
172 RenderBlock* cb = containingBlock();
173 while (cb->isAnonymous())
174 cb = cb->containingBlock();
176 // Matching RenderBox::percentageLogicalHeightIsResolvableFromBlock() by
177 // ignoring table cell's attribute value, where it says that table cells violate
178 // what the CSS spec says to do with heights. Basically we
179 // don't care if the cell specified a height or not.
180 if (cb->isTableCell())
183 // Match RenderBox::availableLogicalHeightUsing by special casing
184 // the render view. The available height is taken from the frame.
185 if (cb->isRenderView())
188 if (cb->isOutOfFlowPositioned() && !cb->style()->logicalTop().isAuto() && !cb->style()->logicalBottom().isAuto())
191 // If the height of the containing block computes to 'auto', then it hasn't been 'specified explicitly'.
192 return cb->hasAutoHeightOrContainingBlockWithAutoHeight();
195 LayoutSize RenderBoxModelObject::relativePositionOffset() const
197 LayoutSize offset = accumulateInFlowPositionOffsets(this);
199 RenderBlock* containingBlock = this->containingBlock();
201 // Objects that shrink to avoid floats normally use available line width when computing containing block width. However
202 // in the case of relative positioning using percentages, we can't do this. The offset should always be resolved using the
203 // available width of the containing block. Therefore we don't use containingBlockLogicalWidthForContent() here, but instead explicitly
204 // call availableWidth on our containing block.
205 if (!style()->left().isAuto()) {
206 if (!style()->right().isAuto() && !containingBlock->style()->isLeftToRightDirection())
207 offset.setWidth(-valueForLength(style()->right(), containingBlock->availableWidth()));
209 offset.expand(valueForLength(style()->left(), containingBlock->availableWidth()), 0);
210 } else if (!style()->right().isAuto()) {
211 offset.expand(-valueForLength(style()->right(), containingBlock->availableWidth()), 0);
214 // If the containing block of a relatively positioned element does not
215 // specify a height, a percentage top or bottom offset should be resolved as
216 // auto. An exception to this is if the containing block has the WinIE quirk
217 // where <html> and <body> assume the size of the viewport. In this case,
218 // calculate the percent offset based on this height.
219 // See <https://bugs.webkit.org/show_bug.cgi?id=26396>.
220 if (!style()->top().isAuto()
221 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
222 || !style()->top().isPercent()
223 || containingBlock->stretchesToViewport()))
224 offset.expand(0, valueForLength(style()->top(), containingBlock->availableHeight()));
226 else if (!style()->bottom().isAuto()
227 && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
228 || !style()->bottom().isPercent()
229 || containingBlock->stretchesToViewport()))
230 offset.expand(0, -valueForLength(style()->bottom(), containingBlock->availableHeight()));
235 LayoutPoint RenderBoxModelObject::adjustedPositionRelativeToOffsetParent(const LayoutPoint& startPoint) const
237 // If the element is the HTML body element or doesn't have a parent
238 // return 0 and stop this algorithm.
239 if (isBody() || !parent())
240 return LayoutPoint();
242 LayoutPoint referencePoint = startPoint;
243 referencePoint.move(parent()->columnOffset(referencePoint));
245 // If the offsetParent of the element is null, or is the HTML body element,
246 // return the distance between the canvas origin and the left border edge
247 // of the element and stop this algorithm.
248 Element* element = offsetParent();
250 return referencePoint;
252 if (const RenderBoxModelObject* offsetParent = element->renderBoxModelObject()) {
253 if (offsetParent->isBox() && !offsetParent->isBody())
254 referencePoint.move(-toRenderBox(offsetParent)->borderLeft(), -toRenderBox(offsetParent)->borderTop());
255 if (!isOutOfFlowPositioned() || flowThreadContainingBlock()) {
256 if (isRelPositioned())
257 referencePoint.move(relativePositionOffset());
259 RenderObject* current;
260 for (current = parent(); current != offsetParent && current->parent(); current = current->parent()) {
261 // FIXME: What are we supposed to do inside SVG content?
262 if (!isOutOfFlowPositioned()) {
263 if (current->isBox() && !current->isTableRow())
264 referencePoint.moveBy(toRenderBox(current)->topLeftLocation());
265 referencePoint.move(current->parent()->columnOffset(referencePoint));
269 if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent->isPositioned())
270 referencePoint.moveBy(toRenderBox(offsetParent)->topLeftLocation());
274 return referencePoint;
277 LayoutSize RenderBoxModelObject::offsetForInFlowPosition() const
279 return isRelPositioned() ? relativePositionOffset() : LayoutSize();
282 LayoutUnit RenderBoxModelObject::offsetLeft() const
284 // Note that RenderInline and RenderBox override this to pass a different
285 // startPoint to adjustedPositionRelativeToOffsetParent.
286 return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x();
289 LayoutUnit RenderBoxModelObject::offsetTop() const
291 // Note that RenderInline and RenderBox override this to pass a different
292 // startPoint to adjustedPositionRelativeToOffsetParent.
293 return adjustedPositionRelativeToOffsetParent(LayoutPoint()).y();
296 int RenderBoxModelObject::pixelSnappedOffsetWidth() const
298 return snapSizeToPixel(offsetWidth(), offsetLeft());
301 int RenderBoxModelObject::pixelSnappedOffsetHeight() const
303 return snapSizeToPixel(offsetHeight(), offsetTop());
306 LayoutUnit RenderBoxModelObject::computedCSSPadding(const Length& padding) const
309 if (padding.isPercent())
310 w = containingBlockLogicalWidthForContent();
311 return minimumValueForLength(padding, w);
314 static inline int resolveWidthForRatio(int height, const FloatSize& intrinsicRatio)
316 return ceilf(height * intrinsicRatio.width() / intrinsicRatio.height());
319 static inline int resolveHeightForRatio(int width, const FloatSize& intrinsicRatio)
321 return ceilf(width * intrinsicRatio.height() / intrinsicRatio.width());
324 static inline IntSize resolveAgainstIntrinsicWidthOrHeightAndRatio(const IntSize& size, const FloatSize& intrinsicRatio, int useWidth, int useHeight)
326 if (intrinsicRatio.isEmpty()) {
328 return IntSize(useWidth, size.height());
329 return IntSize(size.width(), useHeight);
333 return IntSize(useWidth, resolveHeightForRatio(useWidth, intrinsicRatio));
334 return IntSize(resolveWidthForRatio(useHeight, intrinsicRatio), useHeight);
337 static inline IntSize resolveAgainstIntrinsicRatio(const IntSize& size, const FloatSize& intrinsicRatio)
339 // Two possible solutions: (size.width(), solutionHeight) or (solutionWidth, size.height())
340 // "... must be assumed to be the largest dimensions..." = easiest answer: the rect with the largest surface area.
342 int solutionWidth = resolveWidthForRatio(size.height(), intrinsicRatio);
343 int solutionHeight = resolveHeightForRatio(size.width(), intrinsicRatio);
344 if (solutionWidth <= size.width()) {
345 if (solutionHeight <= size.height()) {
346 // If both solutions fit, choose the one covering the larger area.
347 int areaOne = solutionWidth * size.height();
348 int areaTwo = size.width() * solutionHeight;
349 if (areaOne < areaTwo)
350 return IntSize(size.width(), solutionHeight);
351 return IntSize(solutionWidth, size.height());
354 // Only the first solution fits.
355 return IntSize(solutionWidth, size.height());
358 // Only the second solution fits, assert that.
359 ASSERT(solutionHeight <= size.height());
360 return IntSize(size.width(), solutionHeight);
363 IntSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* image, const IntSize& positioningAreaSize, ScaleByEffectiveZoomOrNot shouldScaleOrNot) const
365 // A generated image without a fixed size, will always return the container size as intrinsic size.
366 if (image->isGeneratedImage() && image->usesImageContainerSize())
367 return IntSize(positioningAreaSize.width(), positioningAreaSize.height());
369 Length intrinsicWidth;
370 Length intrinsicHeight;
371 FloatSize intrinsicRatio;
372 image->computeIntrinsicDimensions(this, intrinsicWidth, intrinsicHeight, intrinsicRatio);
374 ASSERT(!intrinsicWidth.isPercent());
375 ASSERT(!intrinsicHeight.isPercent());
377 IntSize resolvedSize(intrinsicWidth.value(), intrinsicHeight.value());
378 IntSize minimumSize(resolvedSize.width() > 0 ? 1 : 0, resolvedSize.height() > 0 ? 1 : 0);
379 if (shouldScaleOrNot == ScaleByEffectiveZoom)
380 resolvedSize.scale(style()->effectiveZoom());
381 resolvedSize.clampToMinimumSize(minimumSize);
383 if (!resolvedSize.isEmpty())
386 // If the image has one of either an intrinsic width or an intrinsic height:
387 // * and an intrinsic aspect ratio, then the missing dimension is calculated from the given dimension and the ratio.
388 // * and no intrinsic aspect ratio, then the missing dimension is assumed to be the size of the rectangle that
389 // establishes the coordinate system for the 'background-position' property.
390 if (resolvedSize.width() > 0 || resolvedSize.height() > 0)
391 return resolveAgainstIntrinsicWidthOrHeightAndRatio(positioningAreaSize, intrinsicRatio, resolvedSize.width(), resolvedSize.height());
393 // If the image has no intrinsic dimensions and has an intrinsic ratio the dimensions must be assumed to be the
394 // largest dimensions at that ratio such that neither dimension exceeds the dimensions of the rectangle that
395 // establishes the coordinate system for the 'background-position' property.
396 if (!intrinsicRatio.isEmpty())
397 return resolveAgainstIntrinsicRatio(positioningAreaSize, intrinsicRatio);
399 // If the image has no intrinsic ratio either, then the dimensions must be assumed to be the rectangle that
400 // establishes the coordinate system for the 'background-position' property.
401 return positioningAreaSize;
404 bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* inlineFlowBox) const
406 if (bleedAvoidance != BackgroundBleedNone)
409 if (style()->hasAppearance())
412 const ShadowList* shadowList = style()->boxShadow();
416 bool hasOneNormalBoxShadow = false;
417 size_t shadowCount = shadowList->shadows().size();
418 for (size_t i = 0; i < shadowCount; ++i) {
419 const ShadowData& currentShadow = shadowList->shadows()[i];
420 if (currentShadow.style() != Normal)
423 if (hasOneNormalBoxShadow)
425 hasOneNormalBoxShadow = true;
427 if (currentShadow.spread())
431 if (!hasOneNormalBoxShadow)
434 Color backgroundColor = resolveColor(CSSPropertyBackgroundColor);
435 if (backgroundColor.hasAlpha())
438 const FillLayer* lastBackgroundLayer = &style()->backgroundLayers();
439 for (const FillLayer* next = lastBackgroundLayer->next(); next; next = lastBackgroundLayer->next())
440 lastBackgroundLayer = next;
442 if (lastBackgroundLayer->clip() != BorderFillBox)
445 if (lastBackgroundLayer->image() && style()->hasBorderRadius())
448 if (inlineFlowBox && !inlineFlowBox->boxShadowCanBeAppliedToBackground(*lastBackgroundLayer))
451 if (hasOverflowClip() && lastBackgroundLayer->attachment() == LocalBackgroundAttachment)
459 LayoutUnit RenderBoxModelObject::containingBlockLogicalWidthForContent() const
461 return containingBlock()->availableLogicalWidth();
464 RenderBoxModelObject* RenderBoxModelObject::continuation() const
466 if (!continuationMap)
468 return (*continuationMap)->get(this);
471 void RenderBoxModelObject::setContinuation(RenderBoxModelObject* continuation)
474 if (!continuationMap)
475 continuationMap = new OwnPtrWillBePersistent<ContinuationMap>(adoptPtrWillBeNoop(new ContinuationMap));
476 (*continuationMap)->set(this, continuation);
479 (*continuationMap)->remove(this);
483 void RenderBoxModelObject::computeLayerHitTestRects(LayerHitTestRects& rects) const
485 RenderLayerModelObject::computeLayerHitTestRects(rects);
487 // If there is a continuation then we need to consult it here, since this is
488 // the root of the tree walk and it wouldn't otherwise get picked up.
489 // Continuations should always be siblings in the tree, so any others should
490 // get picked up already by the tree walk.
492 continuation()->computeLayerHitTestRects(rects);
495 RenderTextFragment* RenderBoxModelObject::firstLetterRemainingText() const
497 if (!firstLetterRemainingTextMap)
499 return (*firstLetterRemainingTextMap)->get(this);
502 void RenderBoxModelObject::setFirstLetterRemainingText(RenderTextFragment* remainingText)
505 if (!firstLetterRemainingTextMap)
506 firstLetterRemainingTextMap = new OwnPtrWillBePersistent<FirstLetterRemainingTextMap>(adoptPtrWillBeNoop(new FirstLetterRemainingTextMap));
507 (*firstLetterRemainingTextMap)->set(this, remainingText);
508 } else if (firstLetterRemainingTextMap) {
509 (*firstLetterRemainingTextMap)->remove(this);
513 LayoutRect RenderBoxModelObject::localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset)
515 ASSERT(!slowFirstChild());
517 // FIXME: This does not take into account either :first-line or :first-letter
518 // However, as soon as some content is entered, the line boxes will be
519 // constructed and this kludge is not called any more. So only the caret size
520 // of an empty :first-line'd block is wrong. I think we can live with that.
521 RenderStyle* currentStyle = firstLineStyle();
523 enum CaretAlignment { alignLeft, alignRight, alignCenter };
525 CaretAlignment alignment = alignLeft;
527 switch (currentStyle->textAlign()) {
533 alignment = alignCenter;
537 alignment = alignRight;
541 if (!currentStyle->isLeftToRightDirection())
542 alignment = alignRight;
545 if (currentStyle->isLeftToRightDirection())
546 alignment = alignRight;
550 LayoutUnit x = borderLeft() + paddingLeft();
551 LayoutUnit maxX = width - borderRight() - paddingRight();
555 if (currentStyle->isLeftToRightDirection())
556 x += textIndentOffset;
560 if (currentStyle->isLeftToRightDirection())
561 x += textIndentOffset / 2;
563 x -= textIndentOffset / 2;
566 x = maxX - caretWidth;
567 if (!currentStyle->isLeftToRightDirection())
568 x -= textIndentOffset;
571 x = std::min(x, std::max<LayoutUnit>(maxX - caretWidth, 0));
573 LayoutUnit height = style()->fontMetrics().height();
574 LayoutUnit verticalSpace = lineHeight(true, currentStyle->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes) - height;
575 LayoutUnit y = paddingTop() + borderTop() + (verticalSpace / 2);
576 return currentStyle->isHorizontalWritingMode() ? LayoutRect(x, y, caretWidth, height) : LayoutRect(y, x, height, caretWidth);
579 void RenderBoxModelObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
581 RenderObject* o = container();
585 if (o->isRenderFlowThread())
586 transformState.move(o->columnOffset(LayoutPoint(transformState.mappedPoint())));
588 o->mapAbsoluteToLocalPoint(mode, transformState);
590 LayoutSize containerOffset = offsetFromContainer(o, LayoutPoint());
592 if (!style()->hasOutOfFlowPosition() && o->hasColumns()) {
593 RenderBlock* block = toRenderBlock(o);
594 LayoutPoint point(roundedLayoutPoint(transformState.mappedPoint()));
595 point -= containerOffset;
596 block->adjustForColumnRect(containerOffset, point);
599 bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D());
600 if (mode & UseTransforms && shouldUseTransformFromContainer(o)) {
601 TransformationMatrix t;
602 getTransformFromContainer(o, containerOffset, t);
603 transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
605 transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
608 const RenderObject* RenderBoxModelObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
610 ASSERT(ancestorToStopAt != this);
612 bool ancestorSkipped;
613 RenderObject* container = this->container(ancestorToStopAt, &ancestorSkipped);
617 bool isInline = isRenderInline();
618 bool isFixedPos = !isInline && style()->position() == FixedPosition;
619 bool hasTransform = !isInline && hasLayer() && layer()->transform();
621 LayoutSize adjustmentForSkippedAncestor;
622 if (ancestorSkipped) {
623 // There can't be a transform between paintInvalidationContainer and o, because transforms create containers, so it should be safe
624 // to just subtract the delta between the ancestor and o.
625 adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(container);
628 bool offsetDependsOnPoint = false;
629 LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), &offsetDependsOnPoint);
631 bool preserve3D = container->style()->preserves3D() || style()->preserves3D();
632 if (shouldUseTransformFromContainer(container)) {
633 TransformationMatrix t;
634 getTransformFromContainer(container, containerOffset, t);
635 t.translateRight(adjustmentForSkippedAncestor.width().toFloat(), adjustmentForSkippedAncestor.height().toFloat());
636 geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform);
638 containerOffset += adjustmentForSkippedAncestor;
639 geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform);
642 return ancestorSkipped ? ancestorToStopAt : container;
645 void RenderBoxModelObject::moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)
647 // We assume that callers have cleared their positioned objects list for child moves (!fullRemoveInsert) so the
648 // positioned renderer maps don't become stale. It would be too slow to do the map lookup on each call.
649 ASSERT(!fullRemoveInsert || !isRenderBlock() || !toRenderBlock(this)->hasPositionedObjects());
651 ASSERT(this == child->parent());
652 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
653 if (fullRemoveInsert && (toBoxModelObject->isRenderBlock() || toBoxModelObject->isRenderInline())) {
654 // Takes care of adding the new child correctly if toBlock and fromBlock
655 // have different kind of children (block vs inline).
656 toBoxModelObject->addChild(virtualChildren()->removeChildNode(this, child), beforeChild);
658 toBoxModelObject->virtualChildren()->insertChildNode(toBoxModelObject, virtualChildren()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
661 void RenderBoxModelObject::moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
663 // This condition is rarely hit since this function is usually called on
664 // anonymous blocks which can no longer carry positioned objects (see r120761)
665 // or when fullRemoveInsert is false.
666 if (fullRemoveInsert && isRenderBlock()) {
667 RenderBlock* block = toRenderBlock(this);
668 block->removePositionedObjects(0);
669 if (block->isRenderBlockFlow())
670 toRenderBlockFlow(block)->removeFloatingObjects();
673 ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
674 for (RenderObject* child = startChild; child && child != endChild; ) {
675 // Save our next sibling as moveChildTo will clear it.
676 RenderObject* nextSibling = child->nextSibling();
677 moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert);