void nsSVGForeignObjectFrame::DoReflow() { // Skip reflow if we're zero-sized, unless this is our first reflow. if (IsDisabled() && !(GetStateBits() & NS_FRAME_FIRST_REFLOW)) return; nsPresContext *presContext = PresContext(); nsIFrame* kid = GetFirstPrincipalChild(); if (!kid) return; // initiate a synchronous reflow here and now: nsIPresShell* presShell = presContext->PresShell(); NS_ASSERTION(presShell, "null presShell"); nsRefPtr<nsRenderingContext> renderingContext = presShell->GetReferenceRenderingContext(); if (!renderingContext) return; mInReflow = true; nsHTMLReflowState reflowState(presContext, kid, renderingContext, nsSize(mRect.width, NS_UNCONSTRAINEDSIZE)); nsHTMLReflowMetrics desiredSize; nsReflowStatus status; // We don't use mRect.height above because that tells the child to do // page/column breaking at that height. NS_ASSERTION(reflowState.mComputedBorderPadding == nsMargin(0, 0, 0, 0) && reflowState.mComputedMargin == nsMargin(0, 0, 0, 0), "style system should ensure that :-moz-svg-foreign-content " "does not get styled"); NS_ASSERTION(reflowState.ComputedWidth() == mRect.width, "reflow state made child wrong size"); reflowState.SetComputedHeight(mRect.height); ReflowChild(kid, presContext, desiredSize, reflowState, 0, 0, NS_FRAME_NO_MOVE_FRAME, status); NS_ASSERTION(mRect.width == desiredSize.width && mRect.height == desiredSize.height, "unexpected size"); FinishReflowChild(kid, presContext, &reflowState, desiredSize, 0, 0, NS_FRAME_NO_MOVE_FRAME); mInReflow = false; if (!(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) { FlushDirtyRegion(0); } }
nsresult TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame, const nsMargin& aDeflate, bool aPaintTableBackground) { NS_PRECONDITION(aTableFrame, "null table frame"); nsTableFrame::RowGroupArray rowGroups; aTableFrame->OrderRowGroups(rowGroups); if (rowGroups.Length() < 1) { //degenerate case if (aPaintTableBackground) { PaintTableFrame(aTableFrame, nullptr, nullptr, nsMargin(0,0,0,0)); } /* No cells; nothing else to paint */ return NS_OK; } if (aPaintTableBackground) { PaintTableFrame(aTableFrame, rowGroups[0], rowGroups[rowGroups.Length() - 1], aDeflate); } /*Set up column background/border data*/ if (mNumCols > 0) { nsFrameList& colGroupList = aTableFrame->GetColGroups(); NS_ASSERTION(colGroupList.FirstChild(), "table should have at least one colgroup"); mCols = new ColData[mNumCols]; if (!mCols) return NS_ERROR_OUT_OF_MEMORY; TableBackgroundData* cgData = nullptr; nsMargin border; /* BC left borders aren't stored on cols, but the previous column's right border is the next one's left border.*/ //Start with table's left border. nscoord lastLeftBorder = aTableFrame->GetContinuousLeftBCBorderWidth(); for (nsTableColGroupFrame* cgFrame = static_cast<nsTableColGroupFrame*>(colGroupList.FirstChild()); cgFrame; cgFrame = static_cast<nsTableColGroupFrame*>(cgFrame->GetNextSibling())) { if (cgFrame->GetColCount() < 1) { //No columns, no cells, so no need for data continue; } /*Create data struct for column group*/ cgData = new TableBackgroundData; if (!cgData) return NS_ERROR_OUT_OF_MEMORY; cgData->SetFull(cgFrame); if (mIsBorderCollapse && cgData->ShouldSetBCBorder()) { border.left = lastLeftBorder; cgFrame->GetContinuousBCBorderWidth(border); nsresult rv = cgData->SetBCBorder(border, this); if (NS_FAILED(rv)) { cgData->Destroy(mPresContext); delete cgData; return rv; } } // Boolean that indicates whether mCols took ownership of cgData bool cgDataOwnershipTaken = false; /*Loop over columns in this colgroup*/ for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col; col = static_cast<nsTableColFrame*>(col->GetNextSibling())) { /*Create data struct for column*/ uint32_t colIndex = col->GetColIndex(); NS_ASSERTION(colIndex < mNumCols, "prevent array boundary violation"); if (mNumCols <= colIndex) break; mCols[colIndex].mCol.SetFull(col); //Bring column mRect into table's coord system mCols[colIndex].mCol.mRect.MoveBy(cgData->mRect.x, cgData->mRect.y); //link to parent colgroup's data mCols[colIndex].mColGroup = cgData; cgDataOwnershipTaken = true; if (mIsBorderCollapse) { border.left = lastLeftBorder; lastLeftBorder = col->GetContinuousBCBorderWidth(border); if (mCols[colIndex].mCol.ShouldSetBCBorder()) { nsresult rv = mCols[colIndex].mCol.SetBCBorder(border, this); if (NS_FAILED(rv)) return rv; } } } if (!cgDataOwnershipTaken) { cgData->Destroy(mPresContext); delete cgData; } } } for (uint32_t i = 0; i < rowGroups.Length(); i++) { nsTableRowGroupFrame* rg = rowGroups[i]; mRowGroup.SetFrame(rg); // Need to compute the right rect via GetOffsetTo, since the row // group may not be a child of the table. mRowGroup.mRect.MoveTo(rg->GetOffsetTo(aTableFrame)); if (mRowGroup.mRect.Intersects(mDirtyRect - mRenderPt)) { nsresult rv = PaintRowGroup(rg, rg->IsPseudoStackingContextFromStyle()); if (NS_FAILED(rv)) return rv; } } return NS_OK; }
void nsSVGForeignObjectFrame::DoReflow() { NS_ASSERTION(!(nsSVGUtils::GetOuterSVGFrame(this)-> GetStateBits() & NS_FRAME_FIRST_REFLOW), "Calling InitialUpdate too early - must not call DoReflow!!!"); // Skip reflow if we're zero-sized, unless this is our first reflow. if (IsDisabled() && !(GetStateBits() & NS_FRAME_FIRST_REFLOW)) return; if (GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD) return; nsPresContext *presContext = PresContext(); nsIFrame* kid = GetFirstChild(nsnull); if (!kid) return; // initiate a synchronous reflow here and now: nsSize availableSpace(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE); nsIPresShell* presShell = presContext->PresShell(); NS_ASSERTION(presShell, "null presShell"); nsRefPtr<nsRenderingContext> renderingContext = presShell->GetReferenceRenderingContext(); if (!renderingContext) return; nsSVGForeignObjectElement *fO = static_cast<nsSVGForeignObjectElement*> (mContent); float width = fO->mLengthAttributes[nsSVGForeignObjectElement::WIDTH].GetAnimValue(fO); float height = fO->mLengthAttributes[nsSVGForeignObjectElement::HEIGHT].GetAnimValue(fO); // Clamp height & width to be non-negative (to match UpdateCoveredRegion). width = NS_MAX(width, 0.0f); height = NS_MAX(height, 0.0f); nsSize size(nsPresContext::CSSPixelsToAppUnits(width), nsPresContext::CSSPixelsToAppUnits(height)); mInReflow = PR_TRUE; nsHTMLReflowState reflowState(presContext, kid, renderingContext, nsSize(size.width, NS_UNCONSTRAINEDSIZE)); nsHTMLReflowMetrics desiredSize; nsReflowStatus status; // We don't use size.height above because that tells the child to do // page/column breaking at that height. NS_ASSERTION(reflowState.mComputedBorderPadding == nsMargin(0, 0, 0, 0) && reflowState.mComputedMargin == nsMargin(0, 0, 0, 0), "style system should ensure that :-moz-svg-foreign content " "does not get styled"); NS_ASSERTION(reflowState.ComputedWidth() == size.width, "reflow state made child wrong size"); reflowState.SetComputedHeight(size.height); ReflowChild(kid, presContext, desiredSize, reflowState, 0, 0, NS_FRAME_NO_MOVE_FRAME, status); NS_ASSERTION(size.width == desiredSize.width && size.height == desiredSize.height, "unexpected size"); FinishReflowChild(kid, presContext, &reflowState, desiredSize, 0, 0, NS_FRAME_NO_MOVE_FRAME); mInReflow = PR_FALSE; FlushDirtyRegion(0); }
void StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame, nsRect* aStick, nsRect* aContain) const { NS_ASSERTION(nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame), "Can't sticky position individual continuations"); aStick->SetRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX); aContain->SetRect(nscoord_MIN/2, nscoord_MIN/2, nscoord_MAX, nscoord_MAX); const nsMargin* computedOffsets = static_cast<nsMargin*>( aFrame->Properties().Get(nsIFrame::ComputedOffsetProperty())); if (!computedOffsets) { // We haven't reflowed the scroll frame yet, so offsets haven't been // computed. Bail. return; } nsIFrame* scrolledFrame = mScrollFrame->GetScrolledFrame(); nsIFrame* cbFrame = aFrame->GetContainingBlock(); NS_ASSERTION(cbFrame == scrolledFrame || nsLayoutUtils::IsProperAncestorFrame(scrolledFrame, cbFrame), "Scroll frame should be an ancestor of the containing block"); nsRect rect = nsLayoutUtils::GetAllInFlowRectsUnion(aFrame, aFrame->GetParent()); // Containing block limits for the position of aFrame relative to its parent. // The margin box of the sticky element stays within the content box of the // contaning-block element. if (cbFrame != scrolledFrame) { *aContain = nsLayoutUtils:: GetAllInFlowRectsUnion(cbFrame, aFrame->GetParent(), nsLayoutUtils::RECTS_USE_CONTENT_BOX); nsRect marginRect = nsLayoutUtils:: GetAllInFlowRectsUnion(aFrame, aFrame->GetParent(), nsLayoutUtils::RECTS_USE_MARGIN_BOX); // Deflate aContain by the difference between the union of aFrame's // continuations' margin boxes and the union of their border boxes, so that // by keeping aFrame within aContain, we keep the union of the margin boxes // within the containing block's content box. aContain->Deflate(marginRect - rect); // Deflate aContain by the border-box size, to form a constraint on the // upper-left corner of aFrame and continuations. aContain->Deflate(nsMargin(0, rect.width, rect.height, 0)); } nsMargin sfPadding = scrolledFrame->GetUsedPadding(); nsPoint sfOffset = aFrame->GetParent()->GetOffsetTo(scrolledFrame); // Top if (computedOffsets->top != NS_AUTOOFFSET) { aStick->SetTopEdge(mScrollPosition.y + sfPadding.top + computedOffsets->top - sfOffset.y); } nsSize sfSize = scrolledFrame->GetContentRectRelativeToSelf().Size(); // Bottom if (computedOffsets->bottom != NS_AUTOOFFSET && (computedOffsets->top == NS_AUTOOFFSET || rect.height <= sfSize.height - computedOffsets->TopBottom())) { aStick->SetBottomEdge(mScrollPosition.y + sfPadding.top + sfSize.height - computedOffsets->bottom - rect.height - sfOffset.y); } uint8_t direction = cbFrame->StyleVisibility()->mDirection; // Left if (computedOffsets->left != NS_AUTOOFFSET && (computedOffsets->right == NS_AUTOOFFSET || direction == NS_STYLE_DIRECTION_LTR || rect.width <= sfSize.width - computedOffsets->LeftRight())) { aStick->SetLeftEdge(mScrollPosition.x + sfPadding.left + computedOffsets->left - sfOffset.x); } // Right if (computedOffsets->right != NS_AUTOOFFSET && (computedOffsets->left == NS_AUTOOFFSET || direction == NS_STYLE_DIRECTION_RTL || rect.width <= sfSize.width - computedOffsets->LeftRight())) { aStick->SetRightEdge(mScrollPosition.x + sfPadding.left + sfSize.width - computedOffsets->right - rect.width - sfOffset.x); } // These limits are for the bounding box of aFrame's continuations. Convert // to limits for aFrame itself. nsPoint frameOffset = aFrame->GetPosition() - rect.TopLeft(); aStick->MoveBy(frameOffset); aContain->MoveBy(frameOffset); }