void
nsTableWrapperFrame::InitChildReflowInput(nsPresContext& aPresContext,
                                          ReflowInput&   aReflowInput)
{
  nsMargin collapseBorder;
  nsMargin collapsePadding(0,0,0,0);
  nsMargin* pCollapseBorder  = nullptr;
  nsMargin* pCollapsePadding = nullptr;
  Maybe<LogicalSize> cbSize;
  if (aReflowInput.mFrame == InnerTableFrame()) {
    WritingMode wm = aReflowInput.GetWritingMode();
    if (InnerTableFrame()->IsBorderCollapse()) {
      LogicalMargin border = InnerTableFrame()->GetIncludedOuterBCBorder(wm);
      collapseBorder = border.GetPhysicalMargin(wm);
      pCollapseBorder = &collapseBorder;
      pCollapsePadding = &collapsePadding;
    }
    // Propagate our stored CB size if present, minus any margins.
    if (!HasAnyStateBits(NS_FRAME_OUT_OF_FLOW)) {
      LogicalSize* cb = Properties().Get(GridItemCBSizeProperty());
      if (cb) {
        cbSize.emplace(*cb);
        *cbSize -= aReflowInput.ComputedLogicalMargin().Size(wm);
      }
    }
  }
  aReflowInput.Init(&aPresContext, cbSize.ptrOr(nullptr), pCollapseBorder,
                    pCollapsePadding);
}
void
nsSVGForeignObjectFrame::Reflow(nsPresContext*           aPresContext,
                                ReflowOutput&     aDesiredSize,
                                const ReflowInput& aReflowInput,
                                nsReflowStatus&          aStatus)
{
  MOZ_ASSERT(!(GetStateBits() & NS_FRAME_IS_NONDISPLAY),
             "Should not have been called");

  // Only InvalidateAndScheduleBoundsUpdate marks us with NS_FRAME_IS_DIRTY,
  // so if that bit is still set we still have a resize pending. If we hit
  // this assertion, then we should get the presShell to skip reflow roots
  // that have a dirty parent since a reflow is going to come via the
  // reflow root's parent anyway.
  NS_ASSERTION(!(GetStateBits() & NS_FRAME_IS_DIRTY),
               "Reflowing while a resize is pending is wasteful");

  // ReflowSVG makes sure mRect is up to date before we're called.

  NS_ASSERTION(!aReflowInput.mParentReflowInput,
               "should only get reflow from being reflow root");
  NS_ASSERTION(aReflowInput.ComputedWidth() == GetSize().width &&
               aReflowInput.ComputedHeight() == GetSize().height,
               "reflow roots should be reflowed at existing size and "
               "svg.css should ensure we have no padding/border/margin");

  DoReflow();

  WritingMode wm = aReflowInput.GetWritingMode();
  LogicalSize finalSize(wm, aReflowInput.ComputedISize(),
                        aReflowInput.ComputedBSize());
  aDesiredSize.SetSize(wm, finalSize);
  aDesiredSize.SetOverflowAreasToDesiredBounds();
  aStatus = NS_FRAME_COMPLETE;
}
Ejemplo n.º 3
0
// Return the inline-size that the float (including margins) will take up
// in the writing mode of the containing block. If this returns
// NS_UNCONSTRAINEDSIZE, we're dealing with an orthogonal block that
// has block-size:auto, and we'll need to actually reflow it to find out
// how much inline-size it will occupy in the containing block's mode.
static nscoord
FloatMarginISize(const ReflowInput& aCBReflowInput,
                 nscoord aFloatAvailableISize,
                 nsIFrame *aFloat,
                 const SizeComputationInput& aFloatOffsetState)
{
  AutoMaybeDisableFontInflation an(aFloat);
  WritingMode wm = aFloatOffsetState.GetWritingMode();

  LogicalSize floatSize =
    aFloat->ComputeSize(
              aCBReflowInput.mRenderingContext,
              wm,
              aCBReflowInput.ComputedSize(wm),
              aFloatAvailableISize,
              aFloatOffsetState.ComputedLogicalMargin().Size(wm),
              aFloatOffsetState.ComputedLogicalBorderPadding().Size(wm) -
                aFloatOffsetState.ComputedLogicalPadding().Size(wm),
              aFloatOffsetState.ComputedLogicalPadding().Size(wm),
              nsIFrame::ComputeSizeFlags::eShrinkWrap);

  WritingMode cbwm = aCBReflowInput.GetWritingMode();
  nscoord floatISize = floatSize.ConvertTo(cbwm, wm).ISize(cbwm);
  if (floatISize == NS_UNCONSTRAINEDSIZE) {
    return NS_UNCONSTRAINEDSIZE; // reflow is needed to get the true size
  }

  return floatISize +
         aFloatOffsetState.ComputedLogicalMargin().Size(wm).
           ConvertTo(cbwm, wm).ISize(cbwm) +
         aFloatOffsetState.ComputedLogicalBorderPadding().Size(wm).
           ConvertTo(cbwm, wm).ISize(cbwm);
}
Ejemplo n.º 4
0
void
nsProgressFrame::Reflow(nsPresContext*           aPresContext,
                        ReflowOutput&     aDesiredSize,
                        const ReflowInput& aReflowInput,
                        nsReflowStatus&          aStatus)
{
  MarkInReflow();
  DO_GLOBAL_REFLOW_COUNT("nsProgressFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);

  NS_ASSERTION(mBarDiv, "Progress bar div must exist!");
  NS_ASSERTION(!GetPrevContinuation(),
               "nsProgressFrame should not have continuations; if it does we "
               "need to call RegUnregAccessKey only for the first.");

  if (mState & NS_FRAME_FIRST_REFLOW) {
    nsFormControlFrame::RegUnRegAccessKey(this, true);
  }

  nsIFrame* barFrame = mBarDiv->GetPrimaryFrame();
  NS_ASSERTION(barFrame, "The progress frame should have a child with a frame!");

  ReflowBarFrame(barFrame, aPresContext, aReflowInput, aStatus);

  aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
                       aReflowInput.ComputedSizeWithBorderPadding());
  aDesiredSize.SetOverflowAreasToDesiredBounds();
  ConsiderChildOverflow(aDesiredSize.mOverflowAreas, barFrame);
  FinishAndStoreOverflow(&aDesiredSize);

  aStatus = NS_FRAME_COMPLETE;

  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
Ejemplo n.º 5
0
static nscoord
GetAvailableContentISize(const ReflowInput& aReflowInput)
{
  if (aReflowInput.AvailableISize() == NS_INTRINSICSIZE) {
    return NS_INTRINSICSIZE;
  }

  WritingMode wm = aReflowInput.GetWritingMode();
  nscoord borderPaddingISize =
    aReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm);
  return std::max(0, aReflowInput.AvailableISize() - borderPaddingISize);
}
Ejemplo n.º 6
0
nscoord
nsColumnSetFrame::GetAvailableContentBSize(const ReflowInput& aReflowInput)
{
  if (aReflowInput.AvailableBSize() == NS_INTRINSICSIZE) {
    return NS_INTRINSICSIZE;
  }

  WritingMode wm = aReflowInput.GetWritingMode();
  LogicalMargin bp = aReflowInput.ComputedLogicalBorderPadding();
  bp.ApplySkipSides(GetLogicalSkipSides(&aReflowInput));
  bp.BEnd(wm) = aReflowInput.ComputedLogicalBorderPadding().BEnd(wm);
  return std::max(0, aReflowInput.AvailableBSize() - bp.BStartEnd(wm));
}
void
nsSimplePageSequenceFrame::SetDesiredSize(ReflowOutput& aDesiredSize,
                                          const ReflowInput& aReflowInput,
                                          nscoord aWidth,
                                          nscoord aHeight)
{
    // Aim to fill the whole size of the document, not only so we
    // can act as a background in print preview but also handle overflow
    // in child page frames correctly.
    // Use availableWidth so we don't cause a needless horizontal scrollbar.
    aDesiredSize.Width() = std::max(aReflowInput.AvailableWidth(),
                                nscoord(aWidth * PresContext()->GetPrintPreviewScale()));
    aDesiredSize.Height() = std::max(aReflowInput.ComputedHeight(),
                                 nscoord(aHeight * PresContext()->GetPrintPreviewScale()));
}
/* virtual */ void
BasicTableLayoutStrategy::ComputeColumnISizes(const ReflowInput& aReflowInput)
{
    nscoord iSize = aReflowInput.ComputedISize();

    if (mLastCalcISize == iSize) {
        return;
    }
    mLastCalcISize = iSize;

    NS_ASSERTION((mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) ==
                 (mPrefISize == NS_INTRINSIC_WIDTH_UNKNOWN),
                 "dirtyness out of sync");
    NS_ASSERTION((mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) ==
                 (mPrefISizePctExpand == NS_INTRINSIC_WIDTH_UNKNOWN),
                 "dirtyness out of sync");
    // XXX Is this needed?
    if (mMinISize == NS_INTRINSIC_WIDTH_UNKNOWN) {
        ComputeIntrinsicISizes(aReflowInput.mRenderingContext);
    }

    nsTableCellMap *cellMap = mTableFrame->GetCellMap();
    int32_t colCount = cellMap->GetColCount();
    if (colCount <= 0)
        return; // nothing to do

    DistributeISizeToColumns(iSize, 0, colCount, BTLS_FINAL_ISIZE, false);

#ifdef DEBUG_TABLE_STRATEGY
    printf("ComputeColumnISizes final\n");
    mTableFrame->Dump(false, true, false);
#endif
}
void
nsTableWrapperFrame::OuterDoReflowChild(nsPresContext*             aPresContext,
                                        nsIFrame*                  aChildFrame,
                                        const ReflowInput&   aChildRI,
                                        ReflowOutput&       aMetrics,
                                        nsReflowStatus&            aStatus)
{
  // Using zero as containerSize here because we want consistency between
  // the GetLogicalPosition and ReflowChild calls, to avoid unnecessarily
  // changing the frame's coordinates; but we don't yet know its final
  // position anyway so the actual value is unimportant.
  const nsSize zeroCSize;
  WritingMode wm = aChildRI.GetWritingMode();

  // Use the current position as a best guess for placement.
  LogicalPoint childPt = aChildFrame->GetLogicalPosition(wm, zeroCSize);
  uint32_t flags = NS_FRAME_NO_MOVE_FRAME;

  // We don't want to delete our next-in-flow's child if it's an inner table
  // frame, because table wrapper frames always assume that their inner table
  // frames don't go away. If a table wrapper frame is removed because it is
  // a next-in-flow of an already complete table wrapper frame, then it will
  // take care of removing it's inner table frame.
  if (aChildFrame == InnerTableFrame()) {
    flags |= NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD;
  }

  ReflowChild(aChildFrame, aPresContext, aMetrics, aChildRI,
              wm, childPt, zeroCSize, flags, aStatus);
}
// Only reflow the selected child ...
void
nsMathMLSelectedFrame::Reflow(nsPresContext*          aPresContext,
                              ReflowOutput&     aDesiredSize,
                              const ReflowInput& aReflowInput,
                              nsReflowStatus&          aStatus)
{
  MarkInReflow();
  mPresentationData.flags &= ~NS_MATHML_ERROR;
  aStatus.Reset();
  aDesiredSize.ClearSize();
  aDesiredSize.SetBlockStartAscent(0);
  mBoundingMetrics = nsBoundingMetrics();
  nsIFrame* childFrame = GetSelectedFrame();
  if (childFrame) {
    WritingMode wm = childFrame->GetWritingMode();
    LogicalSize availSize = aReflowInput.ComputedSize(wm);
    availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
    ReflowInput childReflowInput(aPresContext, aReflowInput,
                                       childFrame, availSize);
    ReflowChild(childFrame, aPresContext, aDesiredSize,
                childReflowInput, aStatus);
    SaveReflowAndBoundingMetricsFor(childFrame, aDesiredSize,
                                    aDesiredSize.mBoundingMetrics);
    mBoundingMetrics = aDesiredSize.mBoundingMetrics;
  }
  FinalizeReflow(aReflowInput.mRenderingContext->GetDrawTarget(), aDesiredSize);
  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
Ejemplo n.º 11
0
nscoord
nsSplittableFrame::GetEffectiveComputedBSize(const ReflowInput& aReflowInput,
                                              nscoord aConsumedBSize) const
{
  nscoord bSize = aReflowInput.ComputedBSize();
  if (bSize == NS_INTRINSICSIZE) {
    return NS_INTRINSICSIZE;
  }

  if (aConsumedBSize == NS_INTRINSICSIZE) {
    aConsumedBSize = ConsumedBSize(aReflowInput.GetWritingMode());
  }

  bSize -= aConsumedBSize;

  // We may have stretched the frame beyond its computed height. Oh well.
  return std::max(0, bSize);
}
Ejemplo n.º 12
0
void
nsTableWrapperFrame::InitChildReflowInput(nsPresContext&     aPresContext,
                                          ReflowInput& aReflowInput)
{
  nsMargin collapseBorder;
  nsMargin collapsePadding(0,0,0,0);
  nsMargin* pCollapseBorder  = nullptr;
  nsMargin* pCollapsePadding = nullptr;
  if (aReflowInput.mFrame == InnerTableFrame() &&
      InnerTableFrame()->IsBorderCollapse()) {
    WritingMode wm = aReflowInput.GetWritingMode();
    LogicalMargin border = InnerTableFrame()->GetIncludedOuterBCBorder(wm);
    collapseBorder = border.GetPhysicalMargin(wm);
    pCollapseBorder = &collapseBorder;
    pCollapsePadding = &collapsePadding;
  }
  aReflowInput.Init(&aPresContext, nullptr, pCollapseBorder, pCollapsePadding);
}
Ejemplo n.º 13
0
/* virtual */ void
nsBackdropFrame::Reflow(nsPresContext* aPresContext,
                        ReflowOutput& aDesiredSize,
                        const ReflowInput& aReflowInput,
                        nsReflowStatus& aStatus)
{
  MarkInReflow();
  DO_GLOBAL_REFLOW_COUNT("nsBackdropFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);

  // Note that this frame is a child of the viewport frame.
  WritingMode wm = aReflowInput.GetWritingMode();
  LogicalMargin borderPadding = aReflowInput.ComputedLogicalBorderPadding();
  nscoord isize = aReflowInput.ComputedISize() + borderPadding.IStartEnd(wm);
  nscoord bsize = aReflowInput.ComputedBSize() + borderPadding.BStartEnd(wm);
  aDesiredSize.SetSize(wm, LogicalSize(wm, isize, bsize));
  aStatus = NS_FRAME_COMPLETE;
}
void
nsHTMLButtonControlFrame::Reflow(nsPresContext* aPresContext,
                                 ReflowOutput& aDesiredSize,
                                 const ReflowInput& aReflowInput,
                                 nsReflowStatus& aStatus)
{
  MarkInReflow();
  DO_GLOBAL_REFLOW_COUNT("nsHTMLButtonControlFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);

  NS_PRECONDITION(aReflowInput.ComputedISize() != NS_INTRINSICSIZE,
                  "Should have real computed inline-size by now");

  if (mState & NS_FRAME_FIRST_REFLOW) {
    nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), true);
  }

  // Reflow the child
  nsIFrame* firstKid = mFrames.FirstChild();

  MOZ_ASSERT(firstKid, "Button should have a child frame for its contents");
  MOZ_ASSERT(!firstKid->GetNextSibling(),
             "Button should have exactly one child frame");
  MOZ_ASSERT(firstKid->StyleContext()->GetPseudo() ==
             nsCSSAnonBoxes::buttonContent,
             "Button's child frame has unexpected pseudo type!");

  // XXXbz Eventually we may want to check-and-bail if
  // !aReflowInput.ShouldReflowAllKids() &&
  // !NS_SUBTREE_DIRTY(firstKid).
  // We'd need to cache our ascent for that, of course.

  // Reflow the contents of the button.
  // (This populates our aDesiredSize, too.)
  ReflowButtonContents(aPresContext, aDesiredSize,
                       aReflowInput, firstKid);

  if (!ShouldClipPaintingToBorderBox()) {
    ConsiderChildOverflow(aDesiredSize.mOverflowAreas, firstKid);
  }
  // else, we ignore child overflow -- anything that overflows beyond our
  // own border-box will get clipped when painting.

  aStatus = NS_FRAME_COMPLETE;
  FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize,
                                 aReflowInput, aStatus);

  // We're always complete and we don't support overflow containers
  // so we shouldn't have a next-in-flow ever.
  aStatus = NS_FRAME_COMPLETE;
  MOZ_ASSERT(!GetNextInFlow());

  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
void
nsSimplePageSequenceFrame::SetDesiredSize(ReflowOutput& aDesiredSize,
                                          const ReflowInput& aReflowInput,
                                          nscoord aWidth,
                                          nscoord aHeight)
{
  // Aim to fill the whole size of the document, not only so we
  // can act as a background in print preview but also handle overflow
  // in child page frames correctly.
  // Use availableISize so we don't cause a needless horizontal scrollbar.
  WritingMode wm = aReflowInput.GetWritingMode();
  nscoord scaledWidth = aWidth * PresContext()->GetPrintPreviewScale();
  nscoord scaledHeight = aHeight * PresContext()->GetPrintPreviewScale();

  nscoord scaledISize = (wm.IsVertical() ? scaledHeight : scaledWidth);
  nscoord scaledBSize = (wm.IsVertical() ? scaledWidth : scaledHeight);

  aDesiredSize.ISize(wm) = std::max(scaledISize, aReflowInput.AvailableISize());
  aDesiredSize.BSize(wm) = std::max(scaledBSize, aReflowInput.ComputedBSize());
}
Ejemplo n.º 16
0
void
nsTextControlFrame::Reflow(nsPresContext*   aPresContext,
                           ReflowOutput&     aDesiredSize,
                           const ReflowInput& aReflowInput,
                           nsReflowStatus&          aStatus)
{
  MarkInReflow();
  DO_GLOBAL_REFLOW_COUNT("nsTextControlFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);

  // make sure that the form registers itself on the initial/first reflow
  if (mState & NS_FRAME_FIRST_REFLOW) {
    nsFormControlFrame::RegUnRegAccessKey(this, true);
  }

  // set values of reflow's out parameters
  WritingMode wm = aReflowInput.GetWritingMode();
  LogicalSize
    finalSize(wm,
              aReflowInput.ComputedISize() +
              aReflowInput.ComputedLogicalBorderPadding().IStartEnd(wm),
              aReflowInput.ComputedBSize() +
              aReflowInput.ComputedLogicalBorderPadding().BStartEnd(wm));
  aDesiredSize.SetSize(wm, finalSize);

  // computation of the ascent wrt the input height
  nscoord lineHeight = aReflowInput.ComputedBSize();
  float inflation = nsLayoutUtils::FontSizeInflationFor(this);
  if (!IsSingleLineTextControl()) {
    lineHeight = ReflowInput::CalcLineHeight(GetContent(), StyleContext(),
                                                   NS_AUTOHEIGHT, inflation);
  }
  RefPtr<nsFontMetrics> fontMet =
    nsLayoutUtils::GetFontMetricsForFrame(this, inflation);
  // now adjust for our borders and padding
  aDesiredSize.SetBlockStartAscent(
    nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight,
                                           wm.IsLineInverted()) +
    aReflowInput.ComputedLogicalBorderPadding().BStart(wm));

  // overflow handling
  aDesiredSize.SetOverflowAreasToDesiredBounds();
  // perform reflow on all kids
  nsIFrame* kid = mFrames.FirstChild();
  while (kid) {
    ReflowTextControlChild(kid, aPresContext, aReflowInput, aStatus, aDesiredSize);
    kid = kid->GetNextSibling();
  }

  // take into account css properties that affect overflow handling
  FinishAndStoreOverflow(&aDesiredSize);

  aStatus = NS_FRAME_COMPLETE;
  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
// Helper-function that lets us clone the button's reflow state, but with its
// ComputedWidth and ComputedHeight reduced by the amount of renderer-specific
// focus border and padding that we're using. (This lets us provide a more
// appropriate content-box size for descendents' percent sizes to resolve
// against.)
static ReflowInput
CloneReflowInputWithReducedContentBox(
  const ReflowInput& aButtonReflowInput,
  const LogicalMargin& aFocusPadding)
{
  auto wm = aButtonReflowInput.GetWritingMode();
  nscoord adjustedISize = aButtonReflowInput.ComputedISize();
  adjustedISize -= aFocusPadding.IStartEnd(wm);
  adjustedISize = std::max(0, adjustedISize);

  // (Only adjust the block-size if it's an actual length.)
  nscoord adjustedBSize = aButtonReflowInput.ComputedBSize();
  if (adjustedBSize != NS_INTRINSICSIZE) {
    adjustedBSize -= aFocusPadding.BStartEnd(wm);
    adjustedBSize = std::max(0, adjustedBSize);
  }

  ReflowInput clone(aButtonReflowInput);
  clone.SetComputedISize(adjustedISize);
  clone.SetComputedBSize(adjustedBSize);

  return clone;
}
// get the margin and padding data. ReflowInput doesn't handle the
// case of auto margins
void
nsTableWrapperFrame::GetChildMargin(nsPresContext*           aPresContext,
                                    const ReflowInput& aOuterRI,
                                    nsIFrame*                aChildFrame,
                                    nscoord                  aAvailISize,
                                    LogicalMargin&           aMargin)
{
  NS_ASSERTION(!aChildFrame->IsTableCaption(),
               "didn't expect caption frame; writing-mode may be wrong!");

  // construct a reflow state to compute margin and padding. Auto margins
  // will not be computed at this time.

  // create and init the child reflow state
  // XXX We really shouldn't construct a reflow state to do this.
  WritingMode wm = aOuterRI.GetWritingMode();
  LogicalSize availSize(wm, aAvailISize, aOuterRI.AvailableSize(wm).BSize(wm));
  ReflowInput childRI(aPresContext, aOuterRI, aChildFrame, availSize,
                            nullptr, ReflowInput::CALLER_WILL_INIT);
  InitChildReflowInput(*aPresContext, childRI);

  aMargin = childRI.ComputedLogicalMargin();
}
Ejemplo n.º 19
0
static nscoord
ComputeDescendantISize(const ReflowInput& aAncestorReflowInput,
                       nsIFrame *aDescendantFrame)
{
  nsIFrame *ancestorFrame = aAncestorReflowInput.mFrame->FirstInFlow();
  if (aDescendantFrame == ancestorFrame) {
    return aAncestorReflowInput.ComputedISize();
  }

  AutoTArray<nsIFrame*, 16> frames;
  for (nsIFrame *f = aDescendantFrame; f != ancestorFrame;
       f = f->GetParent()->FirstInFlow()) {
    frames.AppendElement(f);
  }

  // This ignores the inline-size contributions made by scrollbars, though in
  // reality we don't have any scrollbars on the sorts of devices on
  // which we use font inflation, so it's not a problem.  But it may
  // occasionally cause problems when writing tests on desktop.

  uint32_t len = frames.Length();
  ReflowInput *reflowInputs = static_cast<ReflowInput*>
                                (moz_xmalloc(sizeof(ReflowInput) * len));
  nsPresContext *presContext = aDescendantFrame->PresContext();
  for (uint32_t i = 0; i < len; ++i) {
    const ReflowInput &parentReflowInput =
      (i == 0) ? aAncestorReflowInput : reflowInputs[i - 1];
    nsIFrame *frame = frames[len - i - 1];
    WritingMode wm = frame->GetWritingMode();
    LogicalSize availSize = parentReflowInput.ComputedSize(wm);
    availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;
    MOZ_ASSERT(frame->GetParent()->FirstInFlow() ==
                 parentReflowInput.mFrame->FirstInFlow(),
               "bad logic in this function");
    new (reflowInputs + i) ReflowInput(presContext, parentReflowInput,
                                             frame, availSize);
  }

  MOZ_ASSERT(reflowInputs[len - 1].mFrame == aDescendantFrame,
             "bad logic in this function");
  nscoord result = reflowInputs[len - 1].ComputedISize();

  for (uint32_t i = len; i-- != 0; ) {
    reflowInputs[i].~ReflowInput();
  }
  free(reflowInputs);

  return result;
}
void
nsTableWrapperFrame::OuterBeginReflowChild(nsPresContext*            aPresContext,
                                           nsIFrame*                 aChildFrame,
                                           const ReflowInput&  aOuterRI,
                                           Maybe<ReflowInput>& aChildRI,
                                           nscoord                   aAvailISize)
{
  // work around pixel rounding errors, round down to ensure we don't exceed the avail height in
  WritingMode wm = aChildFrame->GetWritingMode();
  LogicalSize outerSize = aOuterRI.AvailableSize(wm);
  nscoord availBSize = outerSize.BSize(wm);
  if (NS_UNCONSTRAINEDSIZE != availBSize) {
    if (mCaptionFrames.FirstChild() == aChildFrame) {
      availBSize = NS_UNCONSTRAINEDSIZE;
    } else {
      LogicalMargin margin(wm);
      GetChildMargin(aPresContext, aOuterRI, aChildFrame,
                     outerSize.ISize(wm), margin);

      NS_ASSERTION(NS_UNCONSTRAINEDSIZE != margin.BStart(wm),
                   "No unconstrainedsize arithmetic, please");
      availBSize -= margin.BStart(wm);

      NS_ASSERTION(NS_UNCONSTRAINEDSIZE != margin.BEnd(wm),
                   "No unconstrainedsize arithmetic, please");
      availBSize -= margin.BEnd(wm);
    }
  }
  LogicalSize availSize(wm, aAvailISize, availBSize);
  // create and init the child reflow state, using passed-in Maybe<>,
  // so that caller can use it after we return.
  aChildRI.emplace(aPresContext, aOuterRI, aChildFrame, availSize,
                  nullptr, ReflowInput::CALLER_WILL_INIT);
  InitChildReflowInput(*aPresContext, *aChildRI);

  // see if we need to reset top-of-page due to a caption
  if (aChildRI->mFlags.mIsTopOfPage &&
      mCaptionFrames.FirstChild() == aChildFrame) {
    uint8_t captionSide = GetCaptionSide();
    if (captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM ||
        captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) {
      aChildRI->mFlags.mIsTopOfPage = false;
    }
  }
}
Ejemplo n.º 21
0
void
nsTextControlFrame::ReflowTextControlChild(nsIFrame*                aKid,
                                           nsPresContext*           aPresContext,
                                           const ReflowInput& aReflowInput,
                                           nsReflowStatus&          aStatus,
                                           ReflowOutput& aParentDesiredSize)
{
  // compute available size and frame offsets for child
  WritingMode wm = aKid->GetWritingMode();
  LogicalSize availSize = aReflowInput.ComputedSizeWithPadding(wm);
  availSize.BSize(wm) = NS_UNCONSTRAINEDSIZE;

  ReflowInput kidReflowInput(aPresContext, aReflowInput, 
                                   aKid, availSize, nullptr,
                                   ReflowInput::CALLER_WILL_INIT);
  // Override padding with our computed padding in case we got it from theming or percentage
  kidReflowInput.Init(aPresContext, nullptr, nullptr, &aReflowInput.ComputedPhysicalPadding());

  // Set computed width and computed height for the child
  kidReflowInput.SetComputedWidth(aReflowInput.ComputedWidth());
  kidReflowInput.SetComputedHeight(aReflowInput.ComputedHeight());

  // Offset the frame by the size of the parent's border
  nscoord xOffset = aReflowInput.ComputedPhysicalBorderPadding().left -
                    aReflowInput.ComputedPhysicalPadding().left;
  nscoord yOffset = aReflowInput.ComputedPhysicalBorderPadding().top -
                    aReflowInput.ComputedPhysicalPadding().top;

  // reflow the child
  ReflowOutput desiredSize(aReflowInput);
  ReflowChild(aKid, aPresContext, desiredSize, kidReflowInput, 
              xOffset, yOffset, 0, aStatus);

  // place the child
  FinishReflowChild(aKid, aPresContext, desiredSize,
                    &kidReflowInput, xOffset, yOffset, 0);

  // consider the overflow
  aParentDesiredSize.mOverflowAreas.UnionWith(desiredSize.mOverflowAreas);
}
Ejemplo n.º 22
0
void
nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
                            const ReflowInput& aReflowInput,
                            InlineReflowInput& irs,
                            ReflowOutput& aMetrics,
                            nsReflowStatus& aStatus)
{
  MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");

  nsLineLayout* lineLayout = aReflowInput.mLineLayout;
  bool inFirstLine = aReflowInput.mLineLayout->GetInFirstLine();
  RestyleManager* restyleManager = aPresContext->RestyleManager();
  WritingMode frameWM = aReflowInput.GetWritingMode();
  WritingMode lineWM = aReflowInput.mLineLayout->mRootSpan->mWritingMode;
  LogicalMargin framePadding = aReflowInput.ComputedLogicalBorderPadding();
  nscoord startEdge = 0;
  const bool boxDecorationBreakClone =
    MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
                   StyleBoxDecorationBreak::Clone);
  // Don't offset by our start borderpadding if we have a prev continuation or
  // if we're in a part of an {ib} split other than the first one. For
  // box-decoration-break:clone we always offset our start since all
  // continuations have border/padding.
  if ((!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) ||
      boxDecorationBreakClone) {
    startEdge = framePadding.IStart(frameWM);
  }
  nscoord availableISize = aReflowInput.AvailableISize();
  NS_ASSERTION(availableISize != NS_UNCONSTRAINEDSIZE,
               "should no longer use available widths");
  // Subtract off inline axis border+padding from availableISize
  availableISize -= startEdge;
  availableISize -= framePadding.IEnd(frameWM);
  lineLayout->BeginSpan(this, &aReflowInput, startEdge,
                        startEdge + availableISize, &mBaseline);

  // First reflow our principal children.
  nsIFrame* frame = mFrames.FirstChild();
  bool done = false;
  while (frame) {
    // Check if we should lazily set the child frame's parent pointer.
    if (irs.mSetParentPointer) {
      nsIFrame* child = frame;
      do {
        child->SetParent(this);
        if (inFirstLine) {
          restyleManager->ReparentStyleContext(child);
          nsLayoutUtils::MarkDescendantsDirty(child);
        }
        // We also need to do the same for |frame|'s next-in-flows that are in
        // the sibling list. Otherwise, if we reflow |frame| and it's complete
        // we'll crash when trying to delete its next-in-flow.
        // This scenario doesn't happen often, but it can happen.
        nsIFrame* nextSibling = child->GetNextSibling();
        child = child->GetNextInFlow();
        if (MOZ_UNLIKELY(child)) {
          while (child != nextSibling && nextSibling) {
            nextSibling = nextSibling->GetNextSibling();
          }
          if (!nextSibling) {
            child = nullptr;
          }
        }
        MOZ_ASSERT(!child || mFrames.ContainsFrame(child));
      } while (child);

      // Fix the parent pointer for ::first-letter child frame next-in-flows,
      // so nsFirstLetterFrame::Reflow can destroy them safely (bug 401042).
      nsIFrame* realFrame = nsPlaceholderFrame::GetRealFrameFor(frame);
      if (realFrame->IsLetterFrame()) {
        nsIFrame* child = realFrame->PrincipalChildList().FirstChild();
        if (child) {
          NS_ASSERTION(child->IsTextFrame(), "unexpected frame type");
          nsIFrame* nextInFlow = child->GetNextInFlow();
          for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) {
            NS_ASSERTION(nextInFlow->IsTextFrame(), "unexpected frame type");
            if (mFrames.ContainsFrame(nextInFlow)) {
              nextInFlow->SetParent(this);
              if (inFirstLine) {
                restyleManager->ReparentStyleContext(nextInFlow);
                nsLayoutUtils::MarkDescendantsDirty(nextInFlow);
              }
            }
            else {
#ifdef DEBUG
              // Once we find a next-in-flow that isn't ours none of the
              // remaining next-in-flows should be either.
              for ( ; nextInFlow; nextInFlow = nextInFlow->GetNextInFlow()) {
                NS_ASSERTION(!mFrames.ContainsFrame(nextInFlow),
                             "unexpected letter frame flow");
              }
#endif
              break;
            }
          }
        }
      }
    }
    MOZ_ASSERT(frame->GetParent() == this);

    if (!done) {
      bool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
      ReflowInlineFrame(aPresContext, aReflowInput, irs, frame, aStatus);
      done = aStatus.IsInlineBreak() ||
             (!reflowingFirstLetter && aStatus.IsIncomplete());
      if (done) {
        if (!irs.mSetParentPointer) {
          break;
        }
        // Keep reparenting the remaining siblings, but don't reflow them.
        nsFrameList* pushedFrames = GetOverflowFrames();
        if (pushedFrames && pushedFrames->FirstChild() == frame) {
          // Don't bother if |frame| was pushed to our overflow list.
          break;
        }
      } else {
        irs.mPrevFrame = frame;
      }
    }
    frame = frame->GetNextSibling();
  }

  // Attempt to pull frames from our next-in-flow until we can't
  if (!done && GetNextInFlow()) {
    while (true) {
      bool reflowingFirstLetter = lineLayout->GetFirstLetterStyleOK();
      bool isComplete;
      if (!frame) { // Could be non-null if we pulled a first-letter frame and
                    // it created a continuation, since we don't push those.
        frame = PullOneFrame(aPresContext, irs, &isComplete);
      }
#ifdef NOISY_PUSHING
      printf("%p pulled up %p\n", this, frame);
#endif
      if (nullptr == frame) {
        if (!isComplete) {
          aStatus.Reset();
          aStatus.SetIncomplete();
        }
        break;
      }
      ReflowInlineFrame(aPresContext, aReflowInput, irs, frame, aStatus);
      if (aStatus.IsInlineBreak() ||
          (!reflowingFirstLetter && aStatus.IsIncomplete())) {
        break;
      }
      irs.mPrevFrame = frame;
      frame = frame->GetNextSibling();
    }
  }

  NS_ASSERTION(!aStatus.IsComplete() || !GetOverflowFrames(),
               "We can't be complete AND have overflow frames!");

  // If after reflowing our children they take up no area then make
  // sure that we don't either.
  //
  // Note: CSS demands that empty inline elements still affect the
  // line-height calculations. However, continuations of an inline
  // that are empty we force to empty so that things like collapsed
  // whitespace in an inline element don't affect the line-height.
  aMetrics.ISize(lineWM) = lineLayout->EndSpan(this);

  // Compute final width.

  // XXX Note that that the padding start and end are in the frame's
  //     writing mode, but the metrics' inline-size is in the line's
  //     writing mode. This makes sense if the line and frame are both
  //     vertical or both horizontal, but what should happen with
  //     orthogonal inlines?

  // Make sure to not include our start border and padding if we have a prev
  // continuation or if we're in a part of an {ib} split other than the first
  // one.  For box-decoration-break:clone we always include our start border
  // and padding since all continuations have them.
  if ((!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) ||
      boxDecorationBreakClone) {
    aMetrics.ISize(lineWM) += framePadding.IStart(frameWM);
  }

  /*
   * We want to only apply the end border and padding if we're the last
   * continuation and either not in an {ib} split or the last part of it.  To
   * be the last continuation we have to be complete (so that we won't get a
   * next-in-flow) and have no non-fluid continuations on our continuation
   * chain.  For box-decoration-break:clone we always apply the end border and
   * padding since all continuations have them.
   */
  if ((aStatus.IsComplete() &&
       !LastInFlow()->GetNextContinuation() &&
       !FrameIsNonLastInIBSplit()) ||
      boxDecorationBreakClone) {
    aMetrics.ISize(lineWM) += framePadding.IEnd(frameWM);
  }

  nsLayoutUtils::SetBSizeFromFontMetrics(this, aMetrics,
                                         framePadding, lineWM, frameWM);

  // For now our overflow area is zero. The real value will be
  // computed in |nsLineLayout::RelativePositionFrames|.
  aMetrics.mOverflowAreas.Clear();

#ifdef NOISY_FINAL_SIZE
  ListTag(stdout);
  printf(": metrics=%d,%d ascent=%d\n",
         aMetrics.Width(), aMetrics.Height(), aMetrics.TopAscent());
#endif
}
Ejemplo n.º 23
0
void
ViewportFrame::Reflow(nsPresContext*           aPresContext,
                      ReflowOutput&     aDesiredSize,
                      const ReflowInput& aReflowInput,
                      nsReflowStatus&          aStatus)
{
  MarkInReflow();
  DO_GLOBAL_REFLOW_COUNT("ViewportFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
  NS_FRAME_TRACE_REFLOW_IN("ViewportFrame::Reflow");

  // Initialize OUT parameters
  aStatus = NS_FRAME_COMPLETE;

  // Because |Reflow| sets ComputedBSize() on the child to our
  // ComputedBSize().
  AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);

  // Set our size up front, since some parts of reflow depend on it
  // being already set.  Note that the computed height may be
  // unconstrained; that's ok.  Consumers should watch out for that.
  SetSize(nsSize(aReflowInput.ComputedWidth(), aReflowInput.ComputedHeight()));

  // Reflow the main content first so that the placeholders of the
  // fixed-position frames will be in the right places on an initial
  // reflow.
  nscoord kidBSize = 0;
  WritingMode wm = aReflowInput.GetWritingMode();

  if (mFrames.NotEmpty()) {
    // Deal with a non-incremental reflow or an incremental reflow
    // targeted at our one-and-only principal child frame.
    if (aReflowInput.ShouldReflowAllKids() ||
        aReflowInput.IsBResize() ||
        NS_SUBTREE_DIRTY(mFrames.FirstChild())) {
      // Reflow our one-and-only principal child frame
      nsIFrame*           kidFrame = mFrames.FirstChild();
      ReflowOutput kidDesiredSize(aReflowInput);
      WritingMode         wm = kidFrame->GetWritingMode();
      LogicalSize         availableSpace = aReflowInput.AvailableSize(wm);
      ReflowInput   kidReflowInput(aPresContext, aReflowInput,
                                         kidFrame, availableSpace);

      // Reflow the frame
      kidReflowInput.SetComputedBSize(aReflowInput.ComputedBSize());
      ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowInput,
                  0, 0, 0, aStatus);
      kidBSize = kidDesiredSize.BSize(wm);

      FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, nullptr, 0, 0, 0);
    } else {
      kidBSize = LogicalSize(wm, mFrames.FirstChild()->GetSize()).BSize(wm);
    }
  }

  NS_ASSERTION(aReflowInput.AvailableISize() != NS_UNCONSTRAINEDSIZE,
               "shouldn't happen anymore");

  // Return the max size as our desired size
  LogicalSize maxSize(wm, aReflowInput.AvailableISize(),
                      // Being flowed initially at an unconstrained block size
                      // means we should return our child's intrinsic size.
                      aReflowInput.ComputedBSize() != NS_UNCONSTRAINEDSIZE
                        ? aReflowInput.ComputedBSize()
                        : kidBSize);
  aDesiredSize.SetSize(wm, maxSize);
  aDesiredSize.SetOverflowAreasToDesiredBounds();

  if (HasAbsolutelyPositionedChildren()) {
    // Make a copy of the reflow state and change the computed width and height
    // to reflect the available space for the fixed items
    ReflowInput reflowInput(aReflowInput);

    if (reflowInput.AvailableBSize() == NS_UNCONSTRAINEDSIZE) {
      // We have an intrinsic-height document with abs-pos/fixed-pos children.
      // Set the available height and mComputedHeight to our chosen height.
      reflowInput.AvailableBSize() = maxSize.BSize(wm);
      // Not having border/padding simplifies things
      NS_ASSERTION(reflowInput.ComputedPhysicalBorderPadding() == nsMargin(0,0,0,0),
                   "Viewports can't have border/padding");
      reflowInput.SetComputedBSize(maxSize.BSize(wm));
    }

    nsRect rect = AdjustReflowInputAsContainingBlock(&reflowInput);
    nsOverflowAreas* overflowAreas = &aDesiredSize.mOverflowAreas;
    nsIScrollableFrame* rootScrollFrame =
                    aPresContext->PresShell()->GetRootScrollFrameAsScrollable();
    if (rootScrollFrame && !rootScrollFrame->IsIgnoringViewportClipping()) {
      overflowAreas = nullptr;
    }
    AbsPosReflowFlags flags =
      AbsPosReflowFlags::eCBWidthAndHeightChanged; // XXX could be optimized
    GetAbsoluteContainingBlock()->Reflow(this, aPresContext, reflowInput, aStatus,
                                         rect, flags, overflowAreas);
  }

  if (mFrames.NotEmpty()) {
    ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mFrames.FirstChild());
  }

  // If we were dirty then do a repaint
  if (GetStateBits() & NS_FRAME_IS_DIRTY) {
    InvalidateFrame();
  }

  // Clipping is handled by the document container (e.g., nsSubDocumentFrame),
  // so we don't need to change our overflow areas.
  bool overflowChanged = FinishAndStoreOverflow(&aDesiredSize);
  if (overflowChanged) {
    // We may need to alert our container to get it to pick up the
    // overflow change.
    nsSubDocumentFrame* container = static_cast<nsSubDocumentFrame*>
      (nsLayoutUtils::GetCrossDocParentFrame(this));
    if (container && !container->ShouldClipSubdocument()) {
      container->PresContext()->PresShell()->
        FrameNeedsReflow(container, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
    }
  }

  NS_FRAME_TRACE_REFLOW_OUT("ViewportFrame::Reflow", aStatus);
  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
/*
 * Note: we largely position/size out our children (page frames) using
 * \*physical\* x/y/width/height values, because the print preview UI is always
 * arranged in the same orientation, regardless of writing mode.
 */
void
nsSimplePageSequenceFrame::Reflow(nsPresContext*     aPresContext,
                                  ReflowOutput&      aDesiredSize,
                                  const ReflowInput& aReflowInput,
                                  nsReflowStatus&    aStatus)
{
  MarkInReflow();
  NS_PRECONDITION(aPresContext->IsRootPaginatedDocument(),
                  "A Page Sequence is only for real pages");
  DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
  MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
  NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow");

  // Don't do incremental reflow until we've taught tables how to do
  // it right in paginated mode.
  if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
    // Return our desired size
    SetDesiredSize(aDesiredSize, aReflowInput, mSize.width, mSize.height);
    aDesiredSize.SetOverflowAreasToDesiredBounds();
    FinishAndStoreOverflow(&aDesiredSize);

    if (GetRect().Width() != aDesiredSize.Width()) {
      // Our width is changing; we need to re-center our children (our pages).
      for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
        nsIFrame* child = e.get();
        nsMargin pageCSSMargin = child->GetUsedMargin();
        nscoord centeringMargin =
          ComputeCenteringMargin(aReflowInput.ComputedWidth(),
                                 child->GetRect().Width(),
                                 pageCSSMargin);
        nscoord newX = pageCSSMargin.left + centeringMargin;

        // Adjust the child's x-position:
        child->MovePositionBy(nsPoint(newX - child->GetNormalPosition().x, 0));
      }
    }
    return;
  }

  // See if we can get a Print Settings from the Context
  if (!mPageData->mPrintSettings &&
      aPresContext->Medium() == nsGkAtoms::print) {
      mPageData->mPrintSettings = aPresContext->GetPrintSettings();
  }

  // now get out margins & edges
  if (mPageData->mPrintSettings) {
    nsIntMargin unwriteableTwips;
    mPageData->mPrintSettings->GetUnwriteableMarginInTwips(unwriteableTwips);
    NS_ASSERTION(unwriteableTwips.left  >= 0 && unwriteableTwips.top >= 0 &&
                 unwriteableTwips.right >= 0 && unwriteableTwips.bottom >= 0,
                 "Unwriteable twips should be non-negative");

    nsIntMargin marginTwips;
    mPageData->mPrintSettings->GetMarginInTwips(marginTwips);
    mMargin = aPresContext->CSSTwipsToAppUnits(marginTwips + unwriteableTwips);

    int16_t printType;
    mPageData->mPrintSettings->GetPrintRange(&printType);
    mPrintRangeType = printType;

    nsIntMargin edgeTwips;
    mPageData->mPrintSettings->GetEdgeInTwips(edgeTwips);

    // sanity check the values. three inches are sometimes needed
    int32_t inchInTwips = NS_INCHES_TO_INT_TWIPS(3.0);
    edgeTwips.top    = clamped(edgeTwips.top,    0, inchInTwips);
    edgeTwips.bottom = clamped(edgeTwips.bottom, 0, inchInTwips);
    edgeTwips.left   = clamped(edgeTwips.left,   0, inchInTwips);
    edgeTwips.right  = clamped(edgeTwips.right,  0, inchInTwips);

    mPageData->mEdgePaperMargin =
      aPresContext->CSSTwipsToAppUnits(edgeTwips + unwriteableTwips);
  }

  // *** Special Override ***
  // If this is a sub-sdoc (meaning it doesn't take the whole page)
  // and if this Document is in the upper left hand corner
  // we need to suppress the top margin or it will reflow too small

  nsSize pageSize = aPresContext->GetPageSize();

  mPageData->mReflowSize = pageSize;
  mPageData->mReflowMargin = mMargin;

  // We use the CSS "margin" property on the -moz-page pseudoelement
  // to determine the space between each page in print preview.
  // Keep a running y-offset for each page.
  nscoord y = 0;
  nscoord maxXMost = 0;

  // Tile the pages vertically
  ReflowOutput kidSize(aReflowInput);
  for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
    nsIFrame* kidFrame = e.get();
    // Set the shared data into the page frame before reflow
    nsPageFrame * pf = static_cast<nsPageFrame*>(kidFrame);
    pf->SetSharedPageData(mPageData);

    // Reflow the page
    ReflowInput kidReflowInput(aPresContext, aReflowInput, kidFrame,
                               LogicalSize(kidFrame->GetWritingMode(),
                                                 pageSize));
    nsReflowStatus  status;

    kidReflowInput.SetComputedISize(kidReflowInput.AvailableISize());
    //kidReflowInput.SetComputedHeight(kidReflowInput.AvailableHeight());
    PR_PL(("AV ISize: %d   BSize: %d\n",
           kidReflowInput.AvailableISize(),
           kidReflowInput.AvailableBSize()));

    nsMargin pageCSSMargin = kidReflowInput.ComputedPhysicalMargin();
    y += pageCSSMargin.top;

    nscoord x = pageCSSMargin.left;

    // Place and size the page.
    ReflowChild(kidFrame, aPresContext, kidSize, kidReflowInput, x, y, 0, status);

    // If the page is narrower than our width, then center it horizontally:
    x += ComputeCenteringMargin(aReflowInput.ComputedWidth(),
                                kidSize.Width(), pageCSSMargin);

    FinishReflowChild(kidFrame, aPresContext, kidSize, nullptr, x, y, 0);
    y += kidSize.Height();
    y += pageCSSMargin.bottom;

    maxXMost = std::max(maxXMost, x + kidSize.Width() + pageCSSMargin.right);

    // Is the page complete?
    nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();

    if (status.IsFullyComplete()) {
      NS_ASSERTION(!kidNextInFlow, "bad child flow list");
    } else if (!kidNextInFlow) {
      // The page isn't complete and it doesn't have a next-in-flow, so
      // create a continuing page.
      nsIFrame* continuingPage = aPresContext->PresShell()->FrameConstructor()->
        CreateContinuingFrame(aPresContext, kidFrame, this);

      // Add it to our child list
      mFrames.InsertFrame(nullptr, kidFrame, continuingPage);
    }
  }

  // Get Total Page Count
  // XXXdholbert technically we could calculate this in the loop above,
  // instead of needing a separate walk.
  int32_t pageTot = mFrames.GetLength();

  // Set Page Number Info
  int32_t pageNum = 1;
  for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
    MOZ_ASSERT(e.get()->IsPageFrame(),
               "only expecting nsPageFrame children. Other children will make "
               "this static_cast bogus & probably violate other assumptions");
    nsPageFrame* pf = static_cast<nsPageFrame*>(e.get());
    pf->SetPageNumInfo(pageNum, pageTot);
    pageNum++;
  }

  nsAutoString formattedDateString;
  PRTime now = PR_Now();
  if (NS_SUCCEEDED(DateTimeFormat::FormatPRTime(kDateFormatShort,
                                                kTimeFormatNoSeconds,
                                                now,
                                                formattedDateString))) {
    SetDateTimeStr(formattedDateString);
  }

  // Return our desired size
  // Adjust the reflow size by PrintPreviewScale so the scrollbars end up the
  // correct size
  SetDesiredSize(aDesiredSize, aReflowInput, maxXMost, y);

  aDesiredSize.SetOverflowAreasToDesiredBounds();
  FinishAndStoreOverflow(&aDesiredSize);

  // cache the size so we can set the desired size
  // for the other reflows that happen
  mSize.width  = maxXMost;
  mSize.height = y;

  NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus);
  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
Ejemplo n.º 25
0
void
nsTableCellFrame::Reflow(nsPresContext*           aPresContext,
                         ReflowOutput&     aDesiredSize,
                         const ReflowInput& aReflowInput,
                         nsReflowStatus&          aStatus)
{
  MarkInReflow();
  DO_GLOBAL_REFLOW_COUNT("nsTableCellFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);

  if (aReflowInput.mFlags.mSpecialBSizeReflow) {
    FirstInFlow()->AddStateBits(NS_TABLE_CELL_HAD_SPECIAL_REFLOW);
  }

  // see if a special bsize reflow needs to occur due to having a pct height
  nsTableFrame::CheckRequestSpecialBSizeReflow(aReflowInput);

  aStatus = NS_FRAME_COMPLETE;
  WritingMode wm = aReflowInput.GetWritingMode();
  LogicalSize availSize(wm, aReflowInput.AvailableISize(),
                            aReflowInput.AvailableBSize());

  LogicalMargin borderPadding = aReflowInput.ComputedLogicalPadding();
  LogicalMargin border = GetBorderWidth(wm);
  borderPadding += border;

  // reduce available space by insets, if we're in a constrained situation
  availSize.ISize(wm) -= borderPadding.IStartEnd(wm);
  if (NS_UNCONSTRAINEDSIZE != availSize.BSize(wm)) {
    availSize.BSize(wm) -= borderPadding.BStartEnd(wm);
  }

  // Try to reflow the child into the available space. It might not
  // fit or might need continuing.
  if (availSize.BSize(wm) < 0) {
    availSize.BSize(wm) = 1;
  }

  ReflowOutput kidSize(wm, aDesiredSize.mFlags);
  kidSize.ClearSize();
  SetPriorAvailISize(aReflowInput.AvailableISize());
  nsIFrame* firstKid = mFrames.FirstChild();
  NS_ASSERTION(firstKid, "Frame construction error, a table cell always has an inner cell frame");
  nsTableFrame* tableFrame = GetTableFrame();

  if (aReflowInput.mFlags.mSpecialBSizeReflow) {
    const_cast<ReflowInput&>(aReflowInput).
      SetComputedBSize(BSize(wm) - borderPadding.BStartEnd(wm));
    DISPLAY_REFLOW_CHANGE();
  }
  else if (aPresContext->IsPaginated()) {
    nscoord computedUnpaginatedBSize =
      CalcUnpaginatedBSize((nsTableCellFrame&)*this,
                           *tableFrame, borderPadding.BStartEnd(wm));
    if (computedUnpaginatedBSize > 0) {
      const_cast<ReflowInput&>(aReflowInput).SetComputedBSize(computedUnpaginatedBSize);
      DISPLAY_REFLOW_CHANGE();
    }
  }
  else {
    SetHasPctOverBSize(false);
  }

  WritingMode kidWM = firstKid->GetWritingMode();
  ReflowInput kidReflowInput(aPresContext, aReflowInput, firstKid,
                                   availSize.ConvertTo(kidWM, wm));

  // Don't be a percent height observer if we're in the middle of
  // special-bsize reflow, in case we get an accidental NotifyPercentBSize()
  // call (which we shouldn't honor during special-bsize reflow)
  if (!aReflowInput.mFlags.mSpecialBSizeReflow) {
    // mPercentBSizeObserver is for children of cells in quirks mode,
    // but only those than are tables in standards mode.  NeedsToObserve
    // will determine how far this is propagated to descendants.
    kidReflowInput.mPercentBSizeObserver = this;
  }
  // Don't propagate special bsize reflow state to our kids
  kidReflowInput.mFlags.mSpecialBSizeReflow = false;

  if (aReflowInput.mFlags.mSpecialBSizeReflow ||
      FirstInFlow()->HasAnyStateBits(NS_TABLE_CELL_HAD_SPECIAL_REFLOW)) {
    // We need to force the kid to have mBResize set if we've had a
    // special reflow in the past, since the non-special reflow needs to
    // resize back to what it was without the special bsize reflow.
    kidReflowInput.SetBResize(true);
  }

  nsSize containerSize =
    aReflowInput.ComputedSizeAsContainerIfConstrained();

  LogicalPoint kidOrigin(wm, borderPadding.IStart(wm),
                         borderPadding.BStart(wm));
  nsRect origRect = firstKid->GetRect();
  nsRect origVisualOverflow = firstKid->GetVisualOverflowRect();
  bool firstReflow = firstKid->HasAnyStateBits(NS_FRAME_FIRST_REFLOW);

  ReflowChild(firstKid, aPresContext, kidSize, kidReflowInput,
              wm, kidOrigin, containerSize, 0, aStatus);
  if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
    // Don't pass OVERFLOW_INCOMPLETE through tables until they can actually handle it
    //XXX should paginate overflow as overflow, but not in this patch (bug 379349)
    NS_FRAME_SET_INCOMPLETE(aStatus);
    printf("Set table cell incomplete %p\n", static_cast<void*>(this));
  }

  // XXXbz is this invalidate actually needed, really?
  if (HasAnyStateBits(NS_FRAME_IS_DIRTY)) {
    InvalidateFrameSubtree();
  }

#ifdef DEBUG
  DebugCheckChildSize(firstKid, kidSize);
#endif

  // 0 dimensioned cells need to be treated specially in Standard/NavQuirks mode
  // see testcase "emptyCells.html"
  nsIFrame* prevInFlow = GetPrevInFlow();
  bool isEmpty;
  if (prevInFlow) {
    isEmpty = static_cast<nsTableCellFrame*>(prevInFlow)->GetContentEmpty();
  } else {
    isEmpty = !CellHasVisibleContent(kidSize.Height(), tableFrame, firstKid);
  }
  SetContentEmpty(isEmpty);

  // Place the child
  FinishReflowChild(firstKid, aPresContext, kidSize, &kidReflowInput,
                    wm, kidOrigin, containerSize, 0);

  nsTableFrame::InvalidateTableFrame(firstKid, origRect, origVisualOverflow,
                                     firstReflow);

  // first, compute the bsize which can be set w/o being restricted by
  // available bsize
  LogicalSize cellSize(wm);
  cellSize.BSize(wm) = kidSize.BSize(wm);

  if (NS_UNCONSTRAINEDSIZE != cellSize.BSize(wm)) {
    cellSize.BSize(wm) += borderPadding.BStartEnd(wm);
  }

  // next determine the cell's isize
  cellSize.ISize(wm) = kidSize.ISize(wm);      // at this point, we've factored in the cell's style attributes

  // factor in border and padding
  if (NS_UNCONSTRAINEDSIZE != cellSize.ISize(wm)) {
    cellSize.ISize(wm) += borderPadding.IStartEnd(wm);
  }

  // set the cell's desired size and max element size
  aDesiredSize.SetSize(wm, cellSize);

  // the overflow area will be computed when BlockDirAlignChild() gets called

  if (aReflowInput.mFlags.mSpecialBSizeReflow) {
    if (aDesiredSize.BSize(wm) > BSize(wm)) {
      // set a bit indicating that the pct bsize contents exceeded
      // the height that they could honor in the pass 2 reflow
      SetHasPctOverBSize(true);
    }
    if (NS_UNCONSTRAINEDSIZE == aReflowInput.AvailableBSize()) {
      aDesiredSize.BSize(wm) = BSize(wm);
    }
  }

  // If our parent is in initial reflow, it'll handle invalidating our
  // entire overflow rect.
  if (!GetParent()->HasAnyStateBits(NS_FRAME_FIRST_REFLOW) &&
      nsSize(aDesiredSize.Width(), aDesiredSize.Height()) != mRect.Size()) {
    InvalidateFrame();
  }

  // remember the desired size for this reflow
  SetDesiredSize(aDesiredSize);

  // Any absolutely-positioned children will get reflowed in
  // nsFrame::FixupPositionedTableParts in another pass, so propagate our
  // dirtiness to them before our parent clears our dirty bits.
  PushDirtyBitToAbsoluteFrames();

  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}
Ejemplo n.º 26
0
void
nsRubyFrame::ReflowSegment(nsPresContext* aPresContext,
                           const ReflowInput& aReflowInput,
                           nsRubyBaseContainerFrame* aBaseContainer,
                           nsReflowStatus& aStatus)
{
  WritingMode lineWM = aReflowInput.mLineLayout->GetWritingMode();
  LogicalSize availSize(lineWM, aReflowInput.AvailableISize(),
                        aReflowInput.AvailableBSize());
  WritingMode rubyWM = GetWritingMode();
  NS_ASSERTION(!rubyWM.IsOrthogonalTo(lineWM),
               "Ruby frame writing-mode shouldn't be orthogonal to its line");

  AutoRubyTextContainerArray textContainers(aBaseContainer);
  const uint32_t rtcCount = textContainers.Length();

  ReflowOutput baseMetrics(aReflowInput);
  bool pushedFrame;
  aReflowInput.mLineLayout->ReflowFrame(aBaseContainer, aStatus,
                                        &baseMetrics, pushedFrame);

  if (NS_INLINE_IS_BREAK_BEFORE(aStatus)) {
    if (aBaseContainer != mFrames.FirstChild()) {
      // Some segments may have been reflowed before, hence it is not
      // a break-before for the ruby container.
      aStatus = NS_INLINE_LINE_BREAK_AFTER(NS_FRAME_NOT_COMPLETE);
      PushChildren(aBaseContainer, aBaseContainer->GetPrevSibling());
      aReflowInput.mLineLayout->SetDirtyNextLine();
    }
    // This base container is not placed at all, we can skip all
    // text containers paired with it.
    return;
  }
  if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
    // It always promise that if the status is incomplete, there is a
    // break occurs. Break before has been processed above. However,
    // it is possible that break after happens with the frame reflow
    // completed. It happens if there is a force break at the end.
    MOZ_ASSERT(NS_INLINE_IS_BREAK_AFTER(aStatus));
    // Find the previous sibling which we will
    // insert new continuations after.
    nsIFrame* lastChild;
    if (rtcCount > 0) {
      lastChild = textContainers.LastElement();
    } else {
      lastChild = aBaseContainer;
    }

    // Create continuations for the base container
    nsIFrame* newBaseContainer = CreateNextInFlow(aBaseContainer);
    // newBaseContainer is null if there are existing next-in-flows.
    // We only need to move and push if there were not.
    if (newBaseContainer) {
      // Move the new frame after all the text containers
      mFrames.RemoveFrame(newBaseContainer);
      mFrames.InsertFrame(nullptr, lastChild, newBaseContainer);

      // Create continuations for text containers
      nsIFrame* newLastChild = newBaseContainer;
      for (uint32_t i = 0; i < rtcCount; i++) {
        nsIFrame* newTextContainer = CreateNextInFlow(textContainers[i]);
        MOZ_ASSERT(newTextContainer, "Next-in-flow of rtc should not exist "
                   "if the corresponding rbc does not");
        mFrames.RemoveFrame(newTextContainer);
        mFrames.InsertFrame(nullptr, newLastChild, newTextContainer);
        newLastChild = newTextContainer;
      }
    }
    if (lastChild != mFrames.LastChild()) {
      // Always push the next frame after the last child in this segment.
      // It is possible that we pulled it back before our next-in-flow
      // drain our overflow.
      PushChildren(lastChild->GetNextSibling(), lastChild);
      aReflowInput.mLineLayout->SetDirtyNextLine();
    }
  } else {
    // If the ruby base container is reflowed completely, the line
    // layout will remove the next-in-flows of that frame. But the
    // line layout is not aware of the ruby text containers, hence
    // it is necessary to remove them here.
    for (uint32_t i = 0; i < rtcCount; i++) {
      nsIFrame* nextRTC = textContainers[i]->GetNextInFlow();
      if (nextRTC) {
        nextRTC->GetParent()->DeleteNextInFlowChild(nextRTC, true);
      }
    }
  }

  nscoord segmentISize = baseMetrics.ISize(lineWM);
  const nsSize dummyContainerSize;
  LogicalRect baseRect =
    aBaseContainer->GetLogicalRect(lineWM, dummyContainerSize);
  // We need to position our rtc frames on one side or the other of the
  // base container's rect, using a coordinate space that's relative to
  // the ruby frame. Right now, the base container's rect's block-axis
  // position is relative to the block container frame containing the
  // lines, so we use 0 instead. (i.e. we assume that the base container
  // is adjacent to the ruby frame's block-start edge.)
  // XXX We may need to add border/padding here. See bug 1055667.
  baseRect.BStart(lineWM) = 0;
  // The rect for offsets of text containers.
  LogicalRect offsetRect = baseRect;
  for (uint32_t i = 0; i < rtcCount; i++) {
    nsRubyTextContainerFrame* textContainer = textContainers[i];
    WritingMode rtcWM = textContainer->GetWritingMode();
    nsReflowStatus textReflowStatus;
    ReflowOutput textMetrics(aReflowInput);
    ReflowInput textReflowInput(aPresContext, aReflowInput, textContainer,
                                      availSize.ConvertTo(rtcWM, lineWM));
    // FIXME We probably shouldn't be using the same nsLineLayout for
    //       the text containers. But it should be fine now as we are
    //       not actually using this line layout to reflow something,
    //       but just read the writing mode from it.
    textReflowInput.mLineLayout = aReflowInput.mLineLayout;
    textContainer->Reflow(aPresContext, textMetrics,
                          textReflowInput, textReflowStatus);
    // Ruby text containers always return NS_FRAME_COMPLETE even when
    // they have continuations, because the breaking has already been
    // handled when reflowing the base containers.
    NS_ASSERTION(textReflowStatus == NS_FRAME_COMPLETE,
                 "Ruby text container must not break itself inside");
    // The metrics is initialized with reflow state of this ruby frame,
    // hence the writing-mode is tied to rubyWM instead of rtcWM.
    LogicalSize size = textMetrics.Size(rubyWM).ConvertTo(lineWM, rubyWM);
    textContainer->SetSize(lineWM, size);

    nscoord reservedISize = RubyUtils::GetReservedISize(textContainer);
    segmentISize = std::max(segmentISize, size.ISize(lineWM) + reservedISize);

    uint8_t rubyPosition = textContainer->StyleText()->mRubyPosition;
    MOZ_ASSERT(rubyPosition == NS_STYLE_RUBY_POSITION_OVER ||
               rubyPosition == NS_STYLE_RUBY_POSITION_UNDER);
    Maybe<LogicalSide> side;
    if (rubyPosition == NS_STYLE_RUBY_POSITION_OVER) {
      side.emplace(lineWM.LogicalSideForLineRelativeDir(eLineRelativeDirOver));
    } else if (rubyPosition == NS_STYLE_RUBY_POSITION_UNDER) {
      side.emplace(lineWM.LogicalSideForLineRelativeDir(eLineRelativeDirUnder));
    } else {
      // XXX inter-character support in bug 1055672
      MOZ_ASSERT_UNREACHABLE("Unsupported ruby-position");
    }

    LogicalPoint position(lineWM);
    if (side.isSome()) {
      if (side.value() == eLogicalSideBStart) {
        offsetRect.BStart(lineWM) -= size.BSize(lineWM);
        offsetRect.BSize(lineWM) += size.BSize(lineWM);
        position = offsetRect.Origin(lineWM);
      } else if (side.value() == eLogicalSideBEnd) {
        position = offsetRect.Origin(lineWM) +
          LogicalPoint(lineWM, 0, offsetRect.BSize(lineWM));
        offsetRect.BSize(lineWM) += size.BSize(lineWM);
      } else {
        MOZ_ASSERT_UNREACHABLE("???");
      }
    }
    // Using a dummy container-size here, so child positioning may not be
    // correct. We will fix it in nsLineLayout after the whole line is
    // reflowed.
    FinishReflowChild(textContainer, aPresContext, textMetrics,
                      &textReflowInput, lineWM, position, dummyContainerSize, 0);
  }
  MOZ_ASSERT(baseRect.ISize(lineWM) == offsetRect.ISize(lineWM),
             "Annotations should only be placed on the block directions");

  nscoord deltaISize = segmentISize - baseMetrics.ISize(lineWM);
  if (deltaISize <= 0) {
    RubyUtils::ClearReservedISize(aBaseContainer);
  } else {
    RubyUtils::SetReservedISize(aBaseContainer, deltaISize);
    aReflowInput.mLineLayout->AdvanceICoord(deltaISize);
  }

  // Set block leadings of the base container
  nscoord startLeading = baseRect.BStart(lineWM) - offsetRect.BStart(lineWM);
  nscoord endLeading = offsetRect.BEnd(lineWM) - baseRect.BEnd(lineWM);
  // XXX When bug 765861 gets fixed, this warning should be upgraded.
  NS_WARNING_ASSERTION(startLeading >= 0 && endLeading >= 0,
                       "Leadings should be non-negative (because adding "
                       "ruby annotation can only increase the size)");
  mBStartLeading = std::max(mBStartLeading, startLeading);
  mBEndLeading = std::max(mBEndLeading, endLeading);
}
Ejemplo n.º 27
0
void
nsVideoFrame::Reflow(nsPresContext*           aPresContext,
                     ReflowOutput&     aMetrics,
                     const ReflowInput& aReflowInput,
                     nsReflowStatus&          aStatus)
{
  MarkInReflow();
  DO_GLOBAL_REFLOW_COUNT("nsVideoFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
  NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                  ("enter nsVideoFrame::Reflow: availSize=%d,%d",
                  aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));

  NS_PRECONDITION(mState & NS_FRAME_IN_REFLOW, "frame is not in reflow");

  aStatus = NS_FRAME_COMPLETE;

  aMetrics.Width() = aReflowInput.ComputedWidth();
  aMetrics.Height() = aReflowInput.ComputedHeight();

  // stash this away so we can compute our inner area later
  mBorderPadding   = aReflowInput.ComputedPhysicalBorderPadding();

  aMetrics.Width() += mBorderPadding.left + mBorderPadding.right;
  aMetrics.Height() += mBorderPadding.top + mBorderPadding.bottom;

  // Reflow the child frames. We may have up to two, an image frame
  // which is the poster, and a box frame, which is the video controls.
  for (nsIFrame* child : mFrames) {
    if (child->GetContent() == mPosterImage) {
      // Reflow the poster frame.
      nsImageFrame* imageFrame = static_cast<nsImageFrame*>(child);
      ReflowOutput kidDesiredSize(aReflowInput);
      WritingMode wm = imageFrame->GetWritingMode();
      LogicalSize availableSize = aReflowInput.AvailableSize(wm);
      LogicalSize cbSize = aMetrics.Size(aMetrics.GetWritingMode()).
                             ConvertTo(wm, aMetrics.GetWritingMode());
      ReflowInput kidReflowInput(aPresContext,
                                       aReflowInput,
                                       imageFrame,
                                       availableSize,
                                       &cbSize);

      nsRect posterRenderRect;
      if (ShouldDisplayPoster()) {
        posterRenderRect =
          nsRect(nsPoint(mBorderPadding.left, mBorderPadding.top),
                 nsSize(aReflowInput.ComputedWidth(),
                        aReflowInput.ComputedHeight()));
      }
      kidReflowInput.SetComputedWidth(posterRenderRect.width);
      kidReflowInput.SetComputedHeight(posterRenderRect.height);
      ReflowChild(imageFrame, aPresContext, kidDesiredSize, kidReflowInput,
                  posterRenderRect.x, posterRenderRect.y, 0, aStatus);
      FinishReflowChild(imageFrame, aPresContext,
                        kidDesiredSize, &kidReflowInput,
                        posterRenderRect.x, posterRenderRect.y, 0);
    } else if (child->GetContent() == mVideoControls) {
      // Reflow the video controls frame.
      nsBoxLayoutState boxState(PresContext(), aReflowInput.mRenderingContext);
      nsSize size = child->GetSize();
      nsBoxFrame::LayoutChildAt(boxState,
                                child,
                                nsRect(mBorderPadding.left,
                                       mBorderPadding.top,
                                       aReflowInput.ComputedWidth(),
                                       aReflowInput.ComputedHeight()));
      if (child->GetSize() != size) {
        RefPtr<Runnable> event = new DispatchResizeToControls(child->GetContent());
        nsContentUtils::AddScriptRunner(event);
      }
    } else if (child->GetContent() == mCaptionDiv) {
      // Reflow to caption div
      ReflowOutput kidDesiredSize(aReflowInput);
      WritingMode wm = child->GetWritingMode();
      LogicalSize availableSize = aReflowInput.AvailableSize(wm);
      LogicalSize cbSize = aMetrics.Size(aMetrics.GetWritingMode()).
                             ConvertTo(wm, aMetrics.GetWritingMode());
      ReflowInput kidReflowInput(aPresContext,
                                       aReflowInput,
                                       child,
                                       availableSize,
                                       &cbSize);
      nsSize size(aReflowInput.ComputedWidth(), aReflowInput.ComputedHeight());
      size.width -= kidReflowInput.ComputedPhysicalBorderPadding().LeftRight();
      size.height -= kidReflowInput.ComputedPhysicalBorderPadding().TopBottom();

      kidReflowInput.SetComputedWidth(std::max(size.width, 0));
      kidReflowInput.SetComputedHeight(std::max(size.height, 0));

      ReflowChild(child, aPresContext, kidDesiredSize, kidReflowInput,
                  mBorderPadding.left, mBorderPadding.top, 0, aStatus);
      FinishReflowChild(child, aPresContext,
                        kidDesiredSize, &kidReflowInput,
                        mBorderPadding.left, mBorderPadding.top, 0);
    }
  }
  aMetrics.SetOverflowAreasToDesiredBounds();

  FinishAndStoreOverflow(&aMetrics);

  NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                  ("exit nsVideoFrame::Reflow: size=%d,%d",
                  aMetrics.Width(), aMetrics.Height()));
  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
}
Ejemplo n.º 28
0
void
BRFrame::Reflow(nsPresContext* aPresContext,
                ReflowOutput& aMetrics,
                const ReflowInput& aReflowInput,
                nsReflowStatus& aStatus)
{
  MarkInReflow();
  DO_GLOBAL_REFLOW_COUNT("BRFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aMetrics, aStatus);
  WritingMode wm = aReflowInput.GetWritingMode();
  LogicalSize finalSize(wm);
  finalSize.BSize(wm) = 0; // BR frames with block size 0 are ignored in quirks
                           // mode by nsLineLayout::VerticalAlignFrames .
                           // However, it's not always 0.  See below.
  finalSize.ISize(wm) = 0;
  aMetrics.SetBlockStartAscent(0);

  // Only when the BR is operating in a line-layout situation will it
  // behave like a BR. Additionally, we suppress breaks from BR inside
  // of ruby frames. To determine if we're inside ruby, we have to rely
  // on the *parent's* ShouldSuppressLineBreak() method, instead of our
  // own, because we may have custom "display" value that makes our
  // ShouldSuppressLineBreak() return false.
  nsLineLayout* ll = aReflowInput.mLineLayout;
  if (ll && !GetParent()->StyleContext()->ShouldSuppressLineBreak()) {
    // Note that the compatibility mode check excludes AlmostStandards
    // mode, since this is the inline box model.  See bug 161691.
    if ( ll->LineIsEmpty() ||
         aPresContext->CompatibilityMode() == eCompatibility_FullStandards ) {
      // The line is logically empty; any whitespace is trimmed away.
      //
      // If this frame is going to terminate the line we know
      // that nothing else will go on the line. Therefore, in this
      // case, we provide some height for the BR frame so that it
      // creates some vertical whitespace.  It's necessary to use the
      // line-height rather than the font size because the
      // quirks-mode fix that doesn't apply the block's min
      // line-height makes this necessary to make BR cause a line
      // of the full line-height

      // We also do this in strict mode because BR should act like a
      // normal inline frame.  That line-height is used is important
      // here for cases where the line-height is less than 1.
      RefPtr<nsFontMetrics> fm =
        nsLayoutUtils::GetInflatedFontMetricsForFrame(this);
      if (fm) {
        nscoord logicalHeight = aReflowInput.CalcLineHeight();
        finalSize.BSize(wm) = logicalHeight;
        aMetrics.SetBlockStartAscent(nsLayoutUtils::GetCenteredFontBaseline(
                                       fm, logicalHeight, wm.IsLineInverted()));
      }
      else {
        aMetrics.SetBlockStartAscent(aMetrics.BSize(wm) = 0);
      }

      // XXX temporary until I figure out a better solution; see the
      // code in nsLineLayout::VerticalAlignFrames that zaps minY/maxY
      // if the width is zero.
      // XXX This also fixes bug 10036!
      // Warning: nsTextControlFrame::CalculateSizeStandard depends on
      // the following line, see bug 228752.
      // The code below in AddInlinePrefISize also adds 1 appunit to width
      finalSize.ISize(wm) = 1;
    }

    // Return our reflow status
    uint32_t breakType = aReflowInput.mStyleDisplay->PhysicalBreakType(wm);
    if (NS_STYLE_CLEAR_NONE == breakType) {
      breakType = NS_STYLE_CLEAR_LINE;
    }

    aStatus = NS_INLINE_BREAK | NS_INLINE_BREAK_AFTER |
      NS_INLINE_MAKE_BREAK_TYPE(breakType);
    ll->SetLineEndsInBR(true);
  }
  else {
    aStatus = NS_FRAME_COMPLETE;
  }

  aMetrics.SetSize(wm, finalSize);
  aMetrics.SetOverflowAreasToDesiredBounds();

  mAscent = aMetrics.BlockStartAscent();

  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aMetrics);
}
Ejemplo n.º 29
0
/* virtual */ void
nsRubyFrame::Reflow(nsPresContext* aPresContext,
                    ReflowOutput& aDesiredSize,
                    const ReflowInput& aReflowInput,
                    nsReflowStatus& aStatus)
{
  MarkInReflow();
  DO_GLOBAL_REFLOW_COUNT("nsRubyFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
  
  if (!aReflowInput.mLineLayout) {
    NS_ASSERTION(aReflowInput.mLineLayout,
                 "No line layout provided to RubyFrame reflow method.");
    aStatus = NS_FRAME_COMPLETE;
    return;
  }

  // Grab overflow frames from prev-in-flow and its own.
  MoveOverflowToChildList();

  // Clear leadings
  mBStartLeading = mBEndLeading = 0;

  // Begin the span for the ruby frame
  WritingMode frameWM = aReflowInput.GetWritingMode();
  WritingMode lineWM = aReflowInput.mLineLayout->GetWritingMode();
  LogicalMargin borderPadding = aReflowInput.ComputedLogicalBorderPadding();
  nscoord startEdge = 0;
  const bool boxDecorationBreakClone =
    StyleBorder()->mBoxDecorationBreak == StyleBoxDecorationBreak::Clone;
  if (boxDecorationBreakClone || !GetPrevContinuation()) {
    startEdge = borderPadding.IStart(frameWM);
  }
  NS_ASSERTION(aReflowInput.AvailableISize() != NS_UNCONSTRAINEDSIZE,
               "should no longer use available widths");
  nscoord availableISize = aReflowInput.AvailableISize();
  availableISize -= startEdge + borderPadding.IEnd(frameWM);
  aReflowInput.mLineLayout->BeginSpan(this, &aReflowInput,
                                      startEdge, availableISize, &mBaseline);

  aStatus = NS_FRAME_COMPLETE;
  for (RubySegmentEnumerator e(this); !e.AtEnd(); e.Next()) {
    ReflowSegment(aPresContext, aReflowInput, e.GetBaseContainer(), aStatus);

    if (NS_INLINE_IS_BREAK(aStatus)) {
      // A break occurs when reflowing the segment.
      // Don't continue reflowing more segments.
      break;
    }
  }

  ContinuationTraversingState pullState(this);
  while (aStatus == NS_FRAME_COMPLETE) {
    nsRubyBaseContainerFrame* baseContainer =
      PullOneSegment(aReflowInput.mLineLayout, pullState);
    if (!baseContainer) {
      // No more continuations after, finish now.
      break;
    }
    ReflowSegment(aPresContext, aReflowInput, baseContainer, aStatus);
  }
  // We never handle overflow in ruby.
  MOZ_ASSERT(!NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus));

  aDesiredSize.ISize(lineWM) = aReflowInput.mLineLayout->EndSpan(this);
  if (boxDecorationBreakClone || !GetPrevContinuation()) {
    aDesiredSize.ISize(lineWM) += borderPadding.IStart(frameWM);
  }
  if (boxDecorationBreakClone || NS_FRAME_IS_COMPLETE(aStatus)) {
    aDesiredSize.ISize(lineWM) += borderPadding.IEnd(frameWM);
  }

  nsLayoutUtils::SetBSizeFromFontMetrics(this, aDesiredSize,
                                         borderPadding, lineWM, frameWM);
}
Ejemplo n.º 30
0
void
nsSubDocumentFrame::Reflow(nsPresContext*           aPresContext,
                           ReflowOutput&     aDesiredSize,
                           const ReflowInput& aReflowInput,
                           nsReflowStatus&          aStatus)
{
  MarkInReflow();
  DO_GLOBAL_REFLOW_COUNT("nsSubDocumentFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
  NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
     ("enter nsSubDocumentFrame::Reflow: maxSize=%d,%d",
      aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));

  NS_ASSERTION(aReflowInput.ComputedWidth() != NS_UNCONSTRAINEDSIZE,
               "Shouldn't have unconstrained stuff here "
               "thanks to the rules of reflow");
  NS_ASSERTION(NS_INTRINSICSIZE != aReflowInput.ComputedHeight(),
               "Shouldn't have unconstrained stuff here "
               "thanks to ComputeAutoSize");

  aStatus = NS_FRAME_COMPLETE;

  NS_ASSERTION(mContent->GetPrimaryFrame() == this,
               "Shouldn't happen");

  // XUL <iframe> or <browser>, or HTML <iframe>, <object> or <embed>
  aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
                       aReflowInput.ComputedSizeWithBorderPadding());

  // "offset" is the offset of our content area from our frame's
  // top-left corner.
  nsPoint offset = nsPoint(aReflowInput.ComputedPhysicalBorderPadding().left,
                           aReflowInput.ComputedPhysicalBorderPadding().top);

  if (mInnerView) {
    const nsMargin& bp = aReflowInput.ComputedPhysicalBorderPadding();
    nsSize innerSize(aDesiredSize.Width() - bp.LeftRight(),
                     aDesiredSize.Height() - bp.TopBottom());

    // Size & position the view according to 'object-fit' & 'object-position'.
    nsIFrame* subDocRoot = ObtainIntrinsicSizeFrame();
    IntrinsicSize intrinsSize;
    nsSize intrinsRatio;
    if (subDocRoot) {
      intrinsSize = subDocRoot->GetIntrinsicSize();
      intrinsRatio = subDocRoot->GetIntrinsicRatio();
    }
    nsRect destRect =
      nsLayoutUtils::ComputeObjectDestRect(nsRect(offset, innerSize),
                                           intrinsSize, intrinsRatio,
                                           StylePosition());

    nsViewManager* vm = mInnerView->GetViewManager();
    vm->MoveViewTo(mInnerView, destRect.x, destRect.y);
    vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), destRect.Size()), true);
  }

  aDesiredSize.SetOverflowAreasToDesiredBounds();
  if (!ShouldClipSubdocument()) {
    nsIFrame* subdocRootFrame = GetSubdocumentRootFrame();
    if (subdocRootFrame) {
      aDesiredSize.mOverflowAreas.UnionWith(subdocRootFrame->GetOverflowAreas() + offset);
    }
  }

  FinishAndStoreOverflow(&aDesiredSize);

  if (!aPresContext->IsPaginated() && !mPostedReflowCallback) {
    PresContext()->PresShell()->PostReflowCallback(this);
    mPostedReflowCallback = true;
  }

  NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
     ("exit nsSubDocumentFrame::Reflow: size=%d,%d status=%x",
      aDesiredSize.Width(), aDesiredSize.Height(), aStatus));

  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
}