mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 10:44:56 +00:00
Bug 947158 - Implement DrainSelfOverflowList for nsInlineFrame and nsFirstLineFrame. r=bz
This commit is contained in:
parent
0cf0347d66
commit
8882c5de34
@ -368,29 +368,12 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
#endif
|
||||
if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
AutoFrameListPtr overflowFrames(aPresContext, StealOverflowFrames());
|
||||
if (overflowFrames) {
|
||||
NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
|
||||
if (!lazilySetParentPointer) {
|
||||
// The frames on our own overflowlist may have been pushed by a
|
||||
// previous lazilySetParentPointer Reflow so we need to ensure
|
||||
// the correct parent pointer now since we're not setting it
|
||||
// lazily in this Reflow.
|
||||
nsIFrame* firstChild = overflowFrames->FirstChild();
|
||||
if (lineContainer && lineContainer->GetPrevContinuation()) {
|
||||
ReparentFloatsForInlineChild(lineContainer, firstChild, true);
|
||||
}
|
||||
const bool inFirstLine = aReflowState.mLineLayout->GetInFirstLine();
|
||||
RestyleManager* restyleManager = PresContext()->RestyleManager();
|
||||
for (nsIFrame* f = firstChild; f; f = f->GetNextSibling()) {
|
||||
f->SetParent(this);
|
||||
if (inFirstLine) {
|
||||
restyleManager->ReparentStyleContext(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
mFrames.AppendFrames(nullptr, *overflowFrames);
|
||||
DrainFlags flags =
|
||||
lazilySetParentPointer ? eDontReparentFrames : DrainFlags(0);
|
||||
if (aReflowState.mLineLayout->GetInFirstLine()) {
|
||||
flags = DrainFlags(flags | eInFirstLine);
|
||||
}
|
||||
DrainSelfOverflowListInternal(flags, lineContainer);
|
||||
}
|
||||
|
||||
// Set our own reflow state (additional state above and beyond
|
||||
@ -421,6 +404,53 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool
|
||||
nsInlineFrame::DrainSelfOverflowListInternal(DrainFlags aFlags,
|
||||
nsIFrame* aLineContainer)
|
||||
{
|
||||
AutoFrameListPtr overflowFrames(PresContext(), StealOverflowFrames());
|
||||
if (overflowFrames) {
|
||||
NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
|
||||
// The frames on our own overflowlist may have been pushed by a
|
||||
// previous lazilySetParentPointer Reflow so we need to ensure the
|
||||
// correct parent pointer. This is sometimes skipped by Reflow.
|
||||
if (!(aFlags & eDontReparentFrames)) {
|
||||
nsIFrame* firstChild = overflowFrames->FirstChild();
|
||||
if (aLineContainer && aLineContainer->GetPrevContinuation()) {
|
||||
ReparentFloatsForInlineChild(aLineContainer, firstChild, true);
|
||||
}
|
||||
const bool inFirstLine = (aFlags & eInFirstLine);
|
||||
RestyleManager* restyleManager = PresContext()->RestyleManager();
|
||||
for (nsIFrame* f = firstChild; f; f = f->GetNextSibling()) {
|
||||
f->SetParent(this);
|
||||
if (inFirstLine) {
|
||||
restyleManager->ReparentStyleContext(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
bool result = !overflowFrames->IsEmpty();
|
||||
mFrames.AppendFrames(nullptr, *overflowFrames);
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
nsInlineFrame::DrainSelfOverflowList()
|
||||
{
|
||||
nsIFrame* lineContainer = nsLayoutUtils::FindNearestBlockAncestor(this);
|
||||
// Add the eInFirstLine flag if we have a ::first-line ancestor frame.
|
||||
// No need to look further than the nearest line container though.
|
||||
DrainFlags flags = DrainFlags(0);
|
||||
for (nsIFrame* p = GetParent(); p != lineContainer; p = p->GetParent()) {
|
||||
if (p->GetType() == nsGkAtoms::lineFrame) {
|
||||
flags = DrainFlags(flags | eInFirstLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return DrainSelfOverflowListInternal(flags, lineContainer);
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
nsInlineFrame::CanContinueTextRun() const
|
||||
{
|
||||
@ -1018,15 +1048,8 @@ nsFirstLineFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
// It's also possible that we have an overflow list for ourselves
|
||||
AutoFrameListPtr overflowFrames(aPresContext, StealOverflowFrames());
|
||||
if (overflowFrames) {
|
||||
NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
|
||||
|
||||
const nsFrameList::Slice& newFrames =
|
||||
mFrames.AppendFrames(nullptr, *overflowFrames);
|
||||
ReparentChildListStyle(aPresContext, newFrames, this);
|
||||
}
|
||||
// It's also possible that we have an overflow list for ourselves.
|
||||
DrainSelfOverflowList();
|
||||
|
||||
// Set our own reflow state (additional state above and beyond
|
||||
// aReflowState)
|
||||
@ -1094,3 +1117,18 @@ nsFirstLineFrame::PullOverflowsFromPrevInFlow()
|
||||
}
|
||||
}
|
||||
|
||||
/* virtual */ bool
|
||||
nsFirstLineFrame::DrainSelfOverflowList()
|
||||
{
|
||||
AutoFrameListPtr overflowFrames(PresContext(), StealOverflowFrames());
|
||||
if (overflowFrames) {
|
||||
NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
|
||||
|
||||
bool result = !overflowFrames->IsEmpty();
|
||||
const nsFrameList::Slice& newFrames =
|
||||
mFrames.AppendFrames(nullptr, *overflowFrames);
|
||||
ReparentChildListStyle(PresContext(), newFrames, this);
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -92,6 +92,7 @@ public:
|
||||
|
||||
virtual void PullOverflowsFromPrevInFlow() MOZ_OVERRIDE;
|
||||
virtual nscoord GetBaseline() const MOZ_OVERRIDE;
|
||||
virtual bool DrainSelfOverflowList() MOZ_OVERRIDE;
|
||||
|
||||
/**
|
||||
* Return true if the frame is leftmost frame or continuation.
|
||||
@ -168,6 +169,22 @@ protected:
|
||||
nsIFrame* aPrevSibling,
|
||||
InlineReflowState& aState);
|
||||
|
||||
private:
|
||||
// Helper method for DrainSelfOverflowList() to deal with lazy parenting
|
||||
// (which we only do for nsInlineFrame, not nsFirstLineFrame).
|
||||
enum DrainFlags {
|
||||
eDontReparentFrames = 1, // skip reparenting the overflow list frames
|
||||
eInFirstLine = 2, // the request is for an inline descendant of a nsFirstLineFrame
|
||||
};
|
||||
/**
|
||||
* Move any frames on our overflow list to the end of our principal list.
|
||||
* @param aFlags one or more of the above DrainFlags
|
||||
* @param aLineContainer the nearest line container ancestor
|
||||
* @return true if there were any overflow frames
|
||||
*/
|
||||
bool DrainSelfOverflowListInternal(DrainFlags aFlags,
|
||||
nsIFrame* aLineContainer);
|
||||
protected:
|
||||
nscoord mBaseline;
|
||||
};
|
||||
|
||||
@ -177,7 +194,7 @@ protected:
|
||||
* Variation on inline-frame used to manage lines for line layout in
|
||||
* special situations (:first-line style in particular).
|
||||
*/
|
||||
class nsFirstLineFrame : public nsInlineFrame {
|
||||
class nsFirstLineFrame MOZ_FINAL : public nsInlineFrame {
|
||||
public:
|
||||
NS_DECL_FRAMEARENA_HELPERS
|
||||
|
||||
@ -195,6 +212,7 @@ public:
|
||||
virtual void Init(nsIContent* aContent, nsIFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) MOZ_OVERRIDE;
|
||||
virtual void PullOverflowsFromPrevInFlow() MOZ_OVERRIDE;
|
||||
virtual bool DrainSelfOverflowList() MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
nsFirstLineFrame(nsStyleContext* aContext) : nsInlineFrame(aContext) {}
|
||||
|
Loading…
Reference in New Issue
Block a user