Files
tubestation/layout/mathml/nsMathMLSelectedFrame.cpp
Ting-Yu Lin d93880e505 Bug 1341009 - Add nsReflowStatus::IsEmpty() assertions to all nsIFrame::Reflow() methods and some reflow helpers, and remove unneeded Reset(). r=dholbert
nsReflowStatus::IsEmpty() assertions are added after DISPLAY_REFLOW in the
beginning of the Reflow().

A few Reflow() implementations have Reset() calls at the end which are left
in place by this patch (with an explanatory comment added to each). These
ending Reset()s are only needed for cases where a non-splittable frame
passes its own nsReflowStatus to a child's reflow method. Just in case the
child leaves a "not fully complete" value in the nsReflowStatus, the
non-splittable parent frame must clear out the nsReflowStatus before
returning, so that its own parent doesn't then try to split it.

MozReview-Commit-ID: 6Jj3jfMAqj4
2017-09-13 18:00:25 +08:00

177 lines
6.5 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsMathMLSelectedFrame.h"
#include "nsDisplayList.h"
using namespace mozilla;
nsMathMLSelectedFrame::~nsMathMLSelectedFrame()
{
}
NS_IMETHODIMP
nsMathMLSelectedFrame::TransmitAutomaticData()
{
// Note that to determine space-like and embellished op properties:
// - <semantics> behaves the same as <maction>
// - <annotation-xml> behaves the same as <mrow>
// The REC defines the following element to be space-like:
// * an maction element whose selected sub-expression exists and is
// space-like;
nsIMathMLFrame* mathMLFrame = do_QueryFrame(mSelectedFrame);
if (mathMLFrame && mathMLFrame->IsSpaceLike()) {
mPresentationData.flags |= NS_MATHML_SPACE_LIKE;
} else {
mPresentationData.flags &= ~NS_MATHML_SPACE_LIKE;
}
// The REC defines the following element to be an embellished operator:
// * an maction element whose selected sub-expression exists and is an
// embellished operator;
mPresentationData.baseFrame = mSelectedFrame;
GetEmbellishDataFrom(mSelectedFrame, mEmbellishData);
return NS_OK;
}
nsresult
nsMathMLSelectedFrame::ChildListChanged(int32_t aModType)
{
GetSelectedFrame();
return nsMathMLContainerFrame::ChildListChanged(aModType);
}
void
nsMathMLSelectedFrame::SetInitialChildList(ChildListID aListID,
nsFrameList& aChildList)
{
nsMathMLContainerFrame::SetInitialChildList(aListID, aChildList);
// This very first call to GetSelectedFrame() will cause us to be marked as an
// embellished operator if the selected child is an embellished operator
GetSelectedFrame();
}
// Only paint the selected child...
void
nsMathMLSelectedFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists)
{
// Report an error if something wrong was found in this frame.
// We can't call nsDisplayMathMLError from here,
// so ask nsMathMLContainerFrame to do the work for us.
if (NS_MATHML_HAS_ERROR(mPresentationData.flags)) {
nsMathMLContainerFrame::BuildDisplayList(aBuilder, aLists);
return;
}
DisplayBorderBackgroundOutline(aBuilder, aLists);
nsIFrame* childFrame = GetSelectedFrame();
if (childFrame) {
// Put the child's background directly onto the content list
nsDisplayListSet set(aLists, aLists.Content());
// The children should be in content order
BuildDisplayListForChild(aBuilder, childFrame, set);
}
#if defined(DEBUG) && defined(SHOW_BOUNDING_BOX)
// visual debug
DisplayBoundingMetrics(aBuilder, this, mReference, mBoundingMetrics, aLists);
#endif
}
/* virtual */
LogicalSize
nsMathMLSelectedFrame::ComputeSize(gfxContext *aRenderingContext,
WritingMode aWM,
const LogicalSize& aCBSize,
nscoord aAvailableISize,
const LogicalSize& aMargin,
const LogicalSize& aBorder,
const LogicalSize& aPadding,
ComputeSizeFlags aFlags)
{
nsIFrame* childFrame = GetSelectedFrame();
if (childFrame) {
// Delegate size computation to the child frame.
// Try to account for border/padding/margin on this frame and the child,
// though we don't really support them during reflow anyway...
nscoord availableISize = aAvailableISize - aBorder.ISize(aWM) -
aPadding.ISize(aWM) - aMargin.ISize(aWM);
LogicalSize cbSize = aCBSize - aBorder - aPadding - aMargin;
SizeComputationInput offsetState(childFrame, aRenderingContext, aWM,
availableISize);
LogicalSize size =
childFrame->ComputeSize(aRenderingContext, aWM, cbSize,
availableISize, offsetState.ComputedLogicalMargin().Size(aWM),
offsetState.ComputedLogicalBorderPadding().Size(aWM) -
offsetState.ComputedLogicalPadding().Size(aWM),
offsetState.ComputedLogicalPadding().Size(aWM),
aFlags);
return size + offsetState.ComputedLogicalBorderPadding().Size(aWM);
}
return LogicalSize(aWM);
}
// Only reflow the selected child ...
void
nsMathMLSelectedFrame::Reflow(nsPresContext* aPresContext,
ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput,
nsReflowStatus& aStatus)
{
MarkInReflow();
MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
mPresentationData.flags &= ~NS_MATHML_ERROR;
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);
}
// Only place the selected child ...
/* virtual */ nsresult
nsMathMLSelectedFrame::Place(DrawTarget* aDrawTarget,
bool aPlaceOrigin,
ReflowOutput& aDesiredSize)
{
nsIFrame* childFrame = GetSelectedFrame();
if (mInvalidMarkup) {
return ReflowError(aDrawTarget, aDesiredSize);
}
aDesiredSize.ClearSize();
aDesiredSize.SetBlockStartAscent(0);
mBoundingMetrics = nsBoundingMetrics();
if (childFrame) {
GetReflowAndBoundingMetricsFor(childFrame, aDesiredSize, mBoundingMetrics);
if (aPlaceOrigin) {
FinishReflowChild(childFrame, PresContext(), aDesiredSize, nullptr, 0, 0, 0);
}
mReference.x = 0;
mReference.y = aDesiredSize.BlockStartAscent();
}
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
return NS_OK;
}