LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const { // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size. if (!m_containerSize.isEmpty()) return m_containerSize.height(); if (style()->logicalHeight().isSpecified() || style()->logicalMaxHeight().isSpecified()) return RenderReplaced::computeReplacedLogicalHeight(); if (svgSVGElement().heightAttributeEstablishesViewport()) { Length height = svgSVGElement().intrinsicHeight(SVGSVGElement::IgnoreCSSProperties); if (height.isPercent()) { RenderBlock* cb = containingBlock(); ASSERT(cb); while (cb->isAnonymous() && !cb->isRenderView()) { cb = cb->containingBlock(); cb->addPercentHeightDescendant(const_cast<RenderSVGRoot&>(*this)); } } else RenderBlock::removePercentHeightDescendant(const_cast<RenderSVGRoot&>(*this)); return resolveLengthAttributeForSVG(height, style()->effectiveZoom(), containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding), &view()); } // SVG embedded through object/embed/iframe. if (isEmbeddedThroughFrameContainingSVGDocument()) return frame().ownerRenderer()->availableLogicalHeight(IncludeMarginBorderPadding); // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG. return RenderReplaced::computeReplacedLogicalHeight(); }
LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const { SVGSVGElement* svg = static_cast<SVGSVGElement*>(node()); ASSERT(svg); // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size. if (!m_containerSize.isEmpty()) return m_containerSize.height(); if (hasReplacedLogicalHeight()) return RenderReplaced::computeReplacedLogicalHeight(); if (svg->heightAttributeEstablishesViewport()) { Length height = svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties); if (height.isPercent()) { RenderBlock* cb = containingBlock(); ASSERT(cb); while (cb->isAnonymous()) { cb = cb->containingBlock(); cb->addPercentHeightDescendant(const_cast<RenderSVGRoot*>(this)); } } else RenderBlock::removePercentHeightDescendant(const_cast<RenderSVGRoot*>(this)); return resolveLengthAttributeForSVG(height, style()->effectiveZoom(), containingBlock()->availableLogicalHeight()); } // Only SVGs embedded in <object> reach this point. ASSERT(isEmbeddedThroughFrameContainingSVGDocument()); return document()->frame()->ownerRenderer()->availableLogicalHeight(); }
bool RenderVTTCue::shouldSwitchDirection(InlineFlowBox* firstLineBox, LayoutUnit step) const { LayoutUnit top = y(); LayoutUnit left = x(); LayoutUnit bottom = top + firstLineBox->height(); LayoutUnit right = left + firstLineBox->width(); // 12. Horizontal: If step is negative and the top of the first line // box in boxes is now above the top of the video's rendering area, // or if step is positive and the bottom of the first line box in // boxes is now below the bottom of the video's rendering area, jump // to the step labeled switch direction. LayoutUnit parentHeight = containingBlock()->height(); if (m_cue->getWritingDirection() == VTTCue::Horizontal && ((step < 0 && top < 0) || (step > 0 && bottom > parentHeight))) return true; // 12. Vertical: If step is negative and the left edge of the first line // box in boxes is now to the left of the left edge of the video's // rendering area, or if step is positive and the right edge of the // first line box in boxes is now to the right of the right edge of // the video's rendering area, jump to the step labeled switch direction. LayoutUnit parentWidth = containingBlock()->width(); if (m_cue->getWritingDirection() != VTTCue::Horizontal && ((step < 0 && left < 0) || (step > 0 && right > parentWidth))) return true; return false; }
IntRect RenderReplaced::selectionRect(bool clipToVisibleContent) { ASSERT(!needsLayout()); if (!isSelected()) return IntRect(); if (!m_inlineBoxWrapper) // We're a block-level replaced element. Just return our own dimensions. return absoluteBoundingBoxRect(); RenderBlock* cb = containingBlock(); if (!cb) return IntRect(); RootInlineBox* root = m_inlineBoxWrapper->root(); IntRect rect(0, root->selectionTop() - yPos(), width(), root->selectionHeight()); if (clipToVisibleContent) computeAbsoluteRepaintRect(rect); else { int absx, absy; absolutePositionForContent(absx, absy); rect.move(absx, absy); } return rect; }
void RenderInline::absoluteRects(Vector<IntRect>& rects, int tx, int ty, bool topLevel) { for (InlineRunBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) rects.append(IntRect(tx + curr->xPos(), ty + curr->yPos(), curr->width(), curr->height())); for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) curr->absoluteRects(rects, tx + curr->xPos(), ty + curr->yPos(), false); } if (continuation() && topLevel) continuation()->absoluteRects(rects, tx - containingBlock()->xPos() + continuation()->xPos(), ty - containingBlock()->yPos() + continuation()->yPos(), topLevel); }
IntRect RenderSVGInlineText::computeAbsoluteRectForRange(int startPos, int endPos) { IntRect rect; RenderBlock* cb = containingBlock(); if (!cb || !cb->container()) return rect; RenderSVGRoot* root = findSVGRootObject(parent()); if (!root) return rect; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) rect.unite(box->selectionRect(0, 0, startPos, endPos)); // Mimic RenderBox::computeAbsoluteRepaintRect() functionality. But only the subset needed for SVG and respecting SVG transformations. int x, y; cb->container()->absolutePosition(x, y); // Remove HTML parent translation offsets here! These need to be retrieved from the RenderSVGRoot object. // But do take the containingBlocks's container position into account, ie. SVG text in scrollable <div>. AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform(); FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + x - xPos() - htmlParentCtm.e()), narrowPrecisionToFloat(rect.y() + y - yPos() - htmlParentCtm.f()), rect.width(), rect.height()); return enclosingIntRect(absoluteTransform().mapRect(fixedRect)); }
IntRect RenderReplaced::selectionRect() { if (!isSelected()) return IntRect(); if (!m_inlineBoxWrapper) // We're a block-level replaced element. Just return our own dimensions. return absoluteBoundingBoxRect(); RenderBlock* cb = containingBlock(); if (!cb) return IntRect(); RootInlineBox* root = m_inlineBoxWrapper->root(); int selectionTop = root->selectionTop(); int selectionHeight = root->selectionHeight(); int selectionLeft = xPos(); int selectionRight = xPos() + width(); int absx, absy; cb->absolutePosition(absx, absy); if (cb->hasOverflowClip()) cb->layer()->subtractScrollOffset(absx, absy); return IntRect(selectionLeft + absx, selectionTop + absy, selectionRight - selectionLeft, selectionHeight); }
void RenderDialog::layout() { LayoutRepainter repainter(*this, true); LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode()); RenderBlock::layout(); RenderStyle* styleToUse = style(); if (styleToUse->position() != AbsolutePosition || !styleToUse->top().isAuto() || !styleToUse->bottom().isAuto()) { statePusher.pop(); return; } // Adjust the dialog's position to be centered in or at the top of the viewport. // FIXME: Figure out what to do in vertical writing mode. FrameView* frameView = document()->view(); int scrollTop = frameView->scrollOffset().height(); FloatPoint absolutePoint(0, scrollTop); int visibleHeight = frameView->visibleContentRect(true).height(); if (height() < visibleHeight) absolutePoint.move(0, (visibleHeight - height()) / 2); FloatPoint localPoint = containingBlock()->absoluteToLocal(absolutePoint); LayoutUnit localTop = LayoutSize(localPoint.x(), localPoint.y()).height(); setY(localTop); statePusher.pop(); // FIXME: Since there is always a layer here, repainter shouldn't be necessary. But without it, the dialog is sometimes not painted (see bug 90670). repainter.repaintAfterLayout(); }
void RenderTextTrackCue::moveIfNecessaryToKeepWithinContainer() { IntRect containerRect = containingBlock()->absoluteBoundingBoxRect(); IntRect cueRect = absoluteBoundingBoxRect(); int topOverflow = cueRect.y() - containerRect.y(); int bottomOverflow = containerRect.maxY() - cueRect.maxY(); int verticalAdjustment = 0; if (topOverflow < 0) verticalAdjustment = -topOverflow; else if (bottomOverflow < 0) verticalAdjustment = bottomOverflow; if (verticalAdjustment) setY(y() + verticalAdjustment); int leftOverflow = cueRect.x() - containerRect.x(); int rightOverflow = containerRect.maxX() - cueRect.maxX(); int horizontalAdjustment = 0; if (leftOverflow < 0) horizontalAdjustment = -leftOverflow; else if (rightOverflow < 0) horizontalAdjustment = rightOverflow; if (horizontalAdjustment) setX(x() + horizontalAdjustment); }
LayoutUnit RenderReplaced::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const { if (style()->logicalWidth().isSpecified() || style()->logicalWidth().isIntrinsic()) return computeReplacedLogicalWidthRespectingMinMaxWidth(computeReplacedLogicalWidthUsing(style()->logicalWidth()), shouldComputePreferred); // 10.3.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width double intrinsicRatio = 0; FloatSize constrainedSize; computeAspectRatioInformationForRenderBox(constrainedSize, intrinsicRatio); if (style()->logicalWidth().isAuto()) { bool computedHeightIsAuto = hasAutoHeightOrContainingBlockWithAutoHeight(); bool hasIntrinsicWidth = constrainedSize.width() > 0; // If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic width, then that intrinsic width is the used value of 'width'. if (computedHeightIsAuto && hasIntrinsicWidth) return computeReplacedLogicalWidthRespectingMinMaxWidth(constrainedSize.width(), shouldComputePreferred); bool hasIntrinsicHeight = constrainedSize.height() > 0; if (intrinsicRatio) { // If 'height' and 'width' both have computed values of 'auto' and the element has no intrinsic width, but does have an intrinsic height and intrinsic ratio; // or if 'width' has a computed value of 'auto', 'height' has some other computed value, and the element does have an intrinsic ratio; then the used value // of 'width' is: (used height) * (intrinsic ratio) if (intrinsicRatio && ((computedHeightIsAuto && !hasIntrinsicWidth && hasIntrinsicHeight) || !computedHeightIsAuto)) { LayoutUnit logicalHeight = computeReplacedLogicalHeight(); return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(round(logicalHeight * intrinsicRatio)), shouldComputePreferred); } // If 'height' and 'width' both have computed values of 'auto' and the element has an intrinsic ratio but no intrinsic height or width, then the used value of // 'width' is undefined in CSS 2.1. However, it is suggested that, if the containing block's width does not itself depend on the replaced element's width, then // the used value of 'width' is calculated from the constraint equation used for block-level, non-replaced elements in normal flow. if (computedHeightIsAuto && !hasIntrinsicWidth && !hasIntrinsicHeight) { if (shouldComputePreferred == ComputePreferred) return 0; // The aforementioned 'constraint equation' used for block-level, non-replaced elements in normal flow: // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block LayoutUnit logicalWidth = containingBlock()->availableLogicalWidth(); // This solves above equation for 'width' (== logicalWidth). LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), logicalWidth); LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), logicalWidth); logicalWidth = std::max<LayoutUnit>(0, logicalWidth - (marginStart + marginEnd + (width() - clientWidth()))); return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth, shouldComputePreferred); } } // Otherwise, if 'width' has a computed value of 'auto', and the element has an intrinsic width, then that intrinsic width is the used value of 'width'. if (hasIntrinsicWidth) return computeReplacedLogicalWidthRespectingMinMaxWidth(constrainedSize.width(), shouldComputePreferred); // Otherwise, if 'width' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'width' becomes 300px. If 300px is too // wide to fit the device, UAs should use the width of the largest rectangle that has a 2:1 ratio and fits the device instead. // Note: We fall through and instead return intrinsicLogicalWidth() here - to preserve existing WebKit behavior, which might or might not be correct, or desired. // Changing this to return cDefaultWidth, will affect lots of test results. Eg. some tests assume that a blank <img> tag (which implies width/height=auto) // has no intrinsic size, which is wrong per CSS 2.1, but matches our behavior since a long time. } return computeReplacedLogicalWidthRespectingMinMaxWidth(intrinsicLogicalWidth(), shouldComputePreferred); }
void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild, RenderFlow* oldCont) { RenderBlock* pre = 0; RenderBlock* block = containingBlock(); // Delete our line boxes before we do the inline split into continuations. block->deleteLineBoxTree(); bool madeNewBeforeBlock = false; if (block->isAnonymousBlock() && (!block->parent() || !block->parent()->createsAnonymousWrapper())) { // We can reuse this block and make it the preBlock of the next continuation. pre = block; block = block->containingBlock(); } else { // No anonymous block available for use. Make one. pre = block->createAnonymousBlock(); madeNewBeforeBlock = true; } RenderBlock* post = block->createAnonymousBlock(); RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling(); if (madeNewBeforeBlock) block->insertChildNode(pre, boxFirst); block->insertChildNode(newBlockBox, boxFirst); block->insertChildNode(post, boxFirst); block->setChildrenInline(false); if (madeNewBeforeBlock) { RenderObject* o = boxFirst; while (o) { RenderObject* no = o; o = no->nextSibling(); pre->appendChildNode(block->removeChildNode(no)); no->setNeedsLayoutAndPrefWidthsRecalc(); } } splitInlines(pre, post, newBlockBox, beforeChild, oldCont); // We already know the newBlockBox isn't going to contain inline kids, so avoid wasting // time in makeChildrenNonInline by just setting this explicitly up front. newBlockBox->setChildrenInline(false); // We don't just call addChild, since it would pass things off to the // continuation, so we call addChildToFlow explicitly instead. We delayed // adding the newChild until now so that the |newBlockBox| would be fully // connected, thus allowing newChild access to a renderArena should it need // to wrap itself in additional boxes (e.g., table construction). newBlockBox->addChildToFlow(newChild, 0); // Always just do a full layout in order to ensure that line boxes (especially wrappers for images) // get deleted properly. Because objects moves from the pre block into the post block, we want to // make new line boxes instead of leaving the old line boxes around. pre->setNeedsLayoutAndPrefWidthsRecalc(); block->setNeedsLayoutAndPrefWidthsRecalc(); post->setNeedsLayoutAndPrefWidthsRecalc(); }
IntRect RenderInline::clippedOverflowRectForRepaint(RenderBox* repaintContainer) { // Only run-ins are allowed in here during layout. ASSERT(!view() || !view()->layoutStateEnabled() || isRunIn()); if (!firstLineBox() && !continuation()) return IntRect(); // Find our leftmost position. IntRect boundingBox(linesBoundingBox()); int left = boundingBox.x(); int top = boundingBox.y(); // Now invalidate a rectangle. int ow = style() ? style()->outlineSize() : 0; // We need to add in the relative position offsets of any inlines (including us) up to our // containing block. RenderBlock* cb = containingBlock(); for (RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isRenderInline() && inlineFlow != cb; inlineFlow = inlineFlow->parent()) { if (inlineFlow->style()->position() == RelativePosition && inlineFlow->hasLayer()) toRenderBox(inlineFlow)->layer()->relativePositionOffset(left, top); } IntRect r(-ow + left, -ow + top, boundingBox.width() + ow * 2, boundingBox.height() + ow * 2); if (cb->hasColumns()) cb->adjustRectForColumns(r); if (cb->hasOverflowClip()) { // cb->height() is inaccurate if we're in the middle of a layout of |cb|, so use the // layer's size instead. Even if the layer's size is wrong, the layer itself will repaint // anyway if its size does change. int x = r.x(); int y = r.y(); IntRect boxRect(0, 0, cb->layer()->width(), cb->layer()->height()); cb->layer()->subtractScrolledContentOffset(x, y); // For overflow:auto/scroll/hidden. IntRect repaintRect(x, y, r.width(), r.height()); r = intersection(repaintRect, boxRect); } ASSERT(repaintContainer != this); cb->computeRectForRepaint(r, repaintContainer); if (ow) { for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) { if (!curr->isText()) { IntRect childRect = curr->rectWithOutlineForRepaint(repaintContainer, ow); r.unite(childRect); } } if (continuation() && !continuation()->isInline()) { IntRect contRect = continuation()->rectWithOutlineForRepaint(repaintContainer, ow); r.unite(contRect); } } return r; }
void RenderListMarker::setSelectionState(SelectionState state) { m_selectionState = state; if (InlineBox* box = inlineBoxWrapper()) if (RootInlineBox* root = box->root()) root->setHasSelectedChildren(state != SelectionNone); containingBlock()->setSelectionState(state); }
void RenderReplaced::setSelectionState(SelectionState s) { m_selectionState = s; if (m_inlineBoxWrapper) { RootInlineBox* line = m_inlineBoxWrapper->root(); if (line) line->setHasSelectedChildren(isSelected()); } containingBlock()->setSelectionState(s); }
LayoutUnit LayoutSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const { // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size. if (!m_containerSize.isEmpty()) return m_containerSize.width(); if (isEmbeddedThroughFrameContainingSVGDocument()) return containingBlock()->availableLogicalWidth(); return LayoutReplaced::computeReplacedLogicalWidth(shouldComputePreferred); }
void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { bool hadTransform = hasTransform(); RenderObject::styleDidChange(diff, oldStyle); updateFromStyle(); LayerType type = layerTypeRequired(); if (type != NoLayer) { if (!layer() && layerCreationAllowedForSubtree()) { if (s_wasFloating && isFloating()) setChildNeedsLayout(); createLayer(type); if (parent() && !needsLayout() && containingBlock()) { // FIXME: This invalidation is overly broad. We should update to // do the correct invalidation at RenderStyle::diff time. crbug.com/349061 if (RuntimeEnabledFeatures::repaintAfterLayoutEnabled()) layer()->renderer()->setShouldDoFullPaintInvalidationAfterLayout(true); else layer()->repainter().setRepaintStatus(NeedsFullRepaint); // Hit in animations/interpolation/perspective-interpolation.html // FIXME: I suspect we can remove this assert disabler now. DisableCompositingQueryAsserts disabler; layer()->updateLayerPositionRecursive(); } } } else if (layer() && layer()->parent()) { setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit. setHasReflection(false); layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer if (s_wasFloating && isFloating()) setChildNeedsLayout(); if (hadTransform) setNeedsLayoutAndPrefWidthsRecalcAndFullPaintInvalidation(); } if (layer()) { // FIXME: Ideally we shouldn't need this setter but we can't easily infer an overflow-only layer // from the style. layer()->setLayerType(type); layer()->styleChanged(diff, oldStyle); } if (FrameView *frameView = view()->frameView()) { bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition(); bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition(); if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) { if (newStyleIsViewportConstained && layer()) frameView->addViewportConstrainedObject(this); else frameView->removeViewportConstrainedObject(this); } } }
LayoutUnit LayoutSVGRoot::computeReplacedLogicalHeight() const { // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size. if (!m_containerSize.isEmpty()) return m_containerSize.height(); if (isEmbeddedThroughFrameContainingSVGDocument()) return containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding); return LayoutReplaced::computeReplacedLogicalHeight(); }
void RenderTextTrackCue::repositionGenericCue() { ASSERT(firstChild()); InlineFlowBox* firstLineBox = toRenderInline(firstChild())->firstLineBox(); if (static_cast<TextTrackCueGeneric*>(m_cue)->useDefaultPosition() && firstLineBox) { LayoutUnit parentWidth = containingBlock()->logicalWidth(); LayoutUnit width = firstLineBox->width(); LayoutUnit right = (parentWidth / 2) - (width / 2); setX(right); } repositionCueSnapToLinesNotSet(); }
int RenderSVGContainer::calcReplacedHeight() const { switch (style()->height().type()) { case Fixed: return max(0, style()->height().value()); case Percent: { RenderBlock* cb = containingBlock(); return style()->height().calcValue(cb->availableHeight()); } default: return 0; } }
void RenderVTTCue::repositionCueSnapToLinesSet() { InlineFlowBox* firstLineBox; LayoutUnit step; LayoutUnit position; if (!findFirstLineBox(firstLineBox)) return; if (!initializeLayoutParameters(firstLineBox, step, position)) return; bool switched; placeBoxInDefaultPosition(position, switched); // 11. Step loop: If none of the boxes in boxes would overlap any of the boxes // in output and all the boxes in output are within the video's rendering area // then jump to the step labeled done positioning. while (isOutside() || isOverlapping()) { if (!shouldSwitchDirection(firstLineBox, step)) { // 13. Move all the boxes in boxes ... // 14. Jump back to the step labeled step loop. moveBoxesByStep(step); } else if (!switchDirection(switched, step)) { break; } // 19. Jump back to the step labeled step loop. } // Acommodate extra top and bottom padding, border or margin. // Note: this is supported only for internal UA styling, not through the cue selector. if (hasInlineDirectionBordersPaddingOrMargin()) { IntRect containerRect = containingBlock()->absoluteBoundingBoxRect(); IntRect cueRect = absoluteBoundingBoxRect(); int topOverflow = cueRect.y() - containerRect.y(); int bottomOverflow = containerRect.y() + containerRect.height() - cueRect.y() - cueRect.height(); int adjustment = 0; if (topOverflow < 0) adjustment = -topOverflow; else if (bottomOverflow < 0) adjustment = bottomOverflow; if (adjustment) setY(y() + adjustment); } }
void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { bool hadTransform = hasTransform(); bool hadLayer = hasLayer(); bool layerWasSelfPainting = hadLayer && layer()->isSelfPaintingLayer(); RenderObject::styleDidChange(diff, oldStyle); updateFromStyle(); if (requiresLayer()) { if (!layer() && layerCreationAllowedForSubtree()) { if (s_wasFloating && isFloating()) setChildNeedsLayout(); createLayer(); if (parent() && !needsLayout() && containingBlock()) { layer()->repainter().setRepaintStatus(NeedsFullRepaint); // There is only one layer to update, it is not worth using |cachedOffset| since // we are not sure the value will be used. layer()->updateLayerPositions(0); } } } else if (layer() && layer()->parent()) { setHasTransform(false); // Either a transform wasn't specified or the object doesn't support transforms, so just null out the bit. setHasReflection(false); layer()->removeOnlyThisLayer(); // calls destroyLayer() which clears m_layer if (s_wasFloating && isFloating()) setChildNeedsLayout(); if (hadTransform) setNeedsLayoutAndPrefWidthsRecalc(); } if (layer()) { layer()->styleChanged(diff, oldStyle); if (hadLayer && layer()->isSelfPaintingLayer() != layerWasSelfPainting) setChildNeedsLayout(); } if (FrameView *frameView = view()->frameView()) { bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition(); bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition(); if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) { if (newStyleIsViewportConstained && layer()) frameView->addViewportConstrainedObject(this); else frameView->removeViewportConstrainedObject(this); } } }
FloatQuad RenderSVGInlineText::computeRepaintQuadForRange(RenderBoxModelObject* repaintContainer, int startPos, int endPos) { RenderBlock* cb = containingBlock(); if (!cb || !cb->container()) return FloatQuad(); RenderSVGRoot* root = findSVGRootObject(parent()); if (!root) return FloatQuad(); IntRect rect; for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) rect.unite(box->selectionRect(0, 0, startPos, endPos)); return localToContainerQuad(FloatQuad(rect), repaintContainer); }
VisiblePosition RenderInline::positionForCoordinates(int x, int y) { // Translate the coords from the pre-anonymous block to the post-anonymous block. RenderBlock* cb = containingBlock(); int parentBlockX = cb->xPos() + x; int parentBlockY = cb->yPos() + y; for (RenderObject* c = continuation(); c; c = c->continuation()) { RenderObject* contBlock = c; if (c->isInline()) contBlock = c->containingBlock(); if (c->isInline() || c->firstChild()) return c->positionForCoordinates(parentBlockX - contBlock->xPos(), parentBlockY - contBlock->yPos()); } return RenderFlow::positionForCoordinates(x, y); }
IntRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const { if (checkWhetherSelected && !isSelected()) return IntRect(); if (!m_inlineBoxWrapper) // We're a block-level replaced element. Just return our own dimensions. return IntRect(0, 0, width(), height()); RenderBlock* cb = containingBlock(); if (!cb) return IntRect(); RootInlineBox* root = m_inlineBoxWrapper->root(); return IntRect(0, root->selectionTop() - y(), width(), root->selectionHeight()); }
bool RenderVTTCue::initializeLayoutParameters(InlineFlowBox*& firstLineBox, LayoutUnit& step, LayoutUnit& position) { ASSERT(firstChild()); RenderBlock* parentBlock = containingBlock(); firstLineBox = toRenderInline(firstChild())->firstLineBox(); if (!firstLineBox) firstLineBox = this->firstRootBox(); // 1. Horizontal: Let step be the height of the first line box in boxes. // Vertical: Let step be the width of the first line box in boxes. step = m_cue->getWritingDirection() == VTTCue::Horizontal ? firstLineBox->height() : firstLineBox->width(); // 2. If step is zero, then jump to the step labeled done positioning below. if (!step) return false; // 3. Let line position be the text track cue computed line position. int linePosition = m_cue->calculateComputedLinePosition(); // 4. Vertical Growing Left: Add one to line position then negate it. if (m_cue->getWritingDirection() == VTTCue::VerticalGrowingLeft) linePosition = -(linePosition + 1); // 5. Let position be the result of multiplying step and line position. position = step * linePosition; // 6. Vertical Growing Left: Decrease position by the width of the // bounding box of the boxes in boxes, then increase position by step. if (m_cue->getWritingDirection() == VTTCue::VerticalGrowingLeft) { position -= width(); position += step; } // 7. If line position is less than zero... if (linePosition < 0) { // Horizontal / Vertical: ... then increase position by the // height / width of the video's rendering area ... position += m_cue->getWritingDirection() == VTTCue::Horizontal ? parentBlock->height() : parentBlock->width(); // ... and negate step. step = -step; } return true; }
void RenderTextTrackCue::repositionGenericCue() { TextTrackCueGeneric* cue = static_cast<TextTrackCueGeneric*>(m_cue); if (!cue->useDefaultPosition()) return; ASSERT(firstChild()); InlineFlowBox* firstLineBox = toRenderInline(firstChild())->firstLineBox(); if (!firstLineBox) return; LayoutUnit parentWidth = containingBlock()->logicalWidth(); LayoutUnit width = firstLineBox->width(); LayoutUnit right = (parentWidth / 2) - (width / 2); setX(right); }
LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const { // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size. if (!m_containerSize.isEmpty()) return m_containerSize.width(); if (isEmbeddedThroughFrameContainingSVGDocument()) return containingBlock()->availableLogicalWidth(); if (style().logicalWidth().isSpecified() || style().logicalMaxWidth().isSpecified()) return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred); if (svgSVGElement().hasIntrinsicWidth()) return resolveLengthAttributeForSVG(svgSVGElement().intrinsicWidth(), style().effectiveZoom(), containingBlock()->availableLogicalWidth(), &view()); // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG. return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred); }
LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const { // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size. if (!m_containerSize.isEmpty()) return m_containerSize.height(); if (isEmbeddedThroughFrameContainingSVGDocument()) return containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding); if (style().logicalHeight().isSpecified() || style().logicalMaxHeight().isSpecified()) return RenderReplaced::computeReplacedLogicalHeight(); if (svgSVGElement().hasIntrinsicHeight()) return resolveLengthAttributeForSVG(svgSVGElement().intrinsicHeight(), style().effectiveZoom(), containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding).toFloat()); // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG. return RenderReplaced::computeReplacedLogicalHeight(); }
void LayoutVTTCue::adjustForTopAndBottomMarginBorderAndPadding() { // Accommodate extra top and bottom padding, border or margin. // Note: this is supported only for internal UA styling, not through the cue selector. if (!hasInlineDirectionBordersPaddingOrMargin()) return; IntRect containerRect = containingBlock()->absoluteBoundingBoxRect(); IntRect cueRect = absoluteBoundingBoxRect(); int topOverflow = cueRect.y() - containerRect.y(); int bottomOverflow = containerRect.y() + containerRect.height() - cueRect.y() - cueRect.height(); int adjustment = 0; if (topOverflow < 0) adjustment = -topOverflow; else if (bottomOverflow < 0) adjustment = bottomOverflow; if (!adjustment) return; setY(location().y() + adjustment); }
LayoutUnit LayoutReplaced::computeConstrainedLogicalWidth( ShouldComputePreferred shouldComputePreferred) const { if (shouldComputePreferred == ComputePreferred) return computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit(), ComputePreferred); // The aforementioned 'constraint equation' used for block-level, non-replaced // elements in normal flow: // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + // 'padding-right' + 'border-right-width' + 'margin-right' = width of // containing block LayoutUnit logicalWidth = containingBlock()->availableLogicalWidth(); // This solves above equation for 'width' (== logicalWidth). LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), logicalWidth); LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), logicalWidth); logicalWidth = (logicalWidth - (marginStart + marginEnd + (size().width() - clientWidth()))) .clampNegativeToZero(); return computeReplacedLogicalWidthRespectingMinMaxWidth( logicalWidth, shouldComputePreferred); }