bug 127286 (part II due to cvs problems) - Handle splitting of floaters when lines impacting them are outside the block containing the floaters. sr=kin, r=alexsavulov

This commit is contained in:
karnaze%netscape.com 2002-12-04 00:58:52 +00:00
Родитель fe81ae2252
Коммит 0f0042a430
21 изменённых файлов: 565 добавлений и 269 удалений

Просмотреть файл

@ -371,10 +371,10 @@ public:
nsIAtom* aPropertyName,
PRUint32 aOptions,
void** aPropertyValue);
NS_IMETHOD SetFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFMPropertyDtorFunc aPropDtorFunc);
NS_IMETHOD SetFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFramePropertyDtorFunc aPropDtorFunc);
NS_IMETHOD RemoveFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName);
@ -383,13 +383,13 @@ public:
#endif
struct PropertyList {
nsCOMPtr<nsIAtom> mName; // property name
PLDHashTable mFrameValueMap; // map of frame/value pairs
NSFMPropertyDtorFunc mDtorFunc; // property specific value dtor function
PropertyList* mNext;
nsCOMPtr<nsIAtom> mName; // property name
PLDHashTable mFrameValueMap; // map of frame/value pairs
NSFramePropertyDtorFunc mDtorFunc; // property specific value dtor function
PropertyList* mNext;
PropertyList(nsIAtom* aName,
NSFMPropertyDtorFunc aDtorFunc);
PropertyList(nsIAtom* aName,
NSFramePropertyDtorFunc aDtorFunc);
~PropertyList();
// Removes the property associated with the given frame, and destroys
@ -2452,10 +2452,10 @@ FrameManager::GetFrameProperty(nsIFrame* aFrame,
}
NS_IMETHODIMP
FrameManager::SetFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFMPropertyDtorFunc aPropDtorFunc)
FrameManager::SetFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFramePropertyDtorFunc aPropDtorFunc)
{
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
NS_PRECONDITION(aPropertyName && aFrame, "unexpected null param");
@ -2667,8 +2667,8 @@ UndisplayedMap::Clear(void)
//----------------------------------------------------------------------
FrameManager::PropertyList::PropertyList(nsIAtom* aName,
NSFMPropertyDtorFunc aDtorFunc)
FrameManager::PropertyList::PropertyList(nsIAtom* aName,
NSFramePropertyDtorFunc aDtorFunc)
: mName(aName), mDtorFunc(aDtorFunc), mNext(nsnull)
{
PL_DHashTableInit(&mFrameValueMap, PL_DHashGetStubOps(), this,

Просмотреть файл

@ -90,6 +90,13 @@ struct nsRect;
struct nsSize;
struct nsMargin;
// Calback function used to destroy the value associated with a property.
typedef void
(*NSFramePropertyDtorFunc)(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue);
// IID for the nsIFrame interface
// a6cf9050-15b3-11d2-932e-00805f8add32
#define NS_IFRAME_IID \
@ -1158,6 +1165,14 @@ public:
PRBool aIsPre,
PRBool* aResult) = 0;
virtual void* GetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropertyName,
PRBool aRemoveProperty) const = 0;
virtual nsresult SetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFramePropertyDtorFunc aPropDtorFunc) = 0;
#ifdef IBMBIDI
/**
* retrieve and set Bidi property of this frame

Просмотреть файл

@ -41,10 +41,10 @@
#include "nsIStatefulFrame.h"
#include "nsString.h"
#include "nsChangeHint.h"
#include "nsIFrame.h"
class nsIAtom;
class nsIContent;
class nsIFrame;
class nsIPresContext;
class nsIPresShell;
class nsIStyleSet;
@ -57,14 +57,6 @@ class nsPlaceholderFrame;
{ 0xa6cf9107, 0x15b3, 0x11d2, \
{0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32} }
// Calback function used to destroy the value associated with a
// given property. used by RemoveFrameProperty()
typedef void
(*NSFMPropertyDtorFunc)(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue);
// Option flags for GetFrameProperty() member function
#define NS_IFRAME_MGR_REMOVE_PROP 0x0001
@ -233,10 +225,10 @@ public:
* NS_ERROR_INVALID_ARG if the dtor function does not match the
* existing dtor function
*/
NS_IMETHOD SetFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFMPropertyDtorFunc aPropertyDtorFunc) = 0;
NS_IMETHOD SetFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFramePropertyDtorFunc aPropertyDtorFunc) = 0;
/**
* Removes a property and destroys its property value by calling the dtor

Просмотреть файл

@ -945,42 +945,78 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed");
if (NS_FAILED(rv)) return rv;
// Put continued floaters at the beginning of the first overflow line. If the first line
// is a block then create a new line as the first line and put the floaters there. If there
// are no overflow lines, then create one and put the floaters in it.
if (state.mOverflowFloaters.NotEmpty()) {
nsLineList* overflowLines = GetOverflowLines(aPresContext, PR_FALSE);
if (overflowLines) {
line_iterator firstLine = overflowLines->begin();
if (firstLine->IsBlock()) { // floaters go on a new line before 1st overflow line
nsLineBox* newLine = state.NewLineBox(state.mOverflowFloaters.FirstChild(),
state.mOverflowFloaters.GetLength(), PR_FALSE);
firstLine = mLines.before_insert(firstLine, newLine);
}
else { // floaters go on 1st overflow line
nsIFrame* firstFrame = firstLine->mFirstChild;
firstLine->mFirstChild = state.mOverflowFloaters.FirstChild();
PRInt32 numOverflowFloaters = state.mOverflowFloaters.GetLength();
// hook up the last placeholder with the original frames
nsPlaceholderFrame* lastPlaceholder =
(nsPlaceholderFrame*)state.mOverflowFloaters.LastChild();
lastPlaceholder->SetNextSibling(firstFrame);
NS_ASSERTION(firstFrame != lastPlaceholder, "trying to set next sibling to self");
firstLine->SetChildCount(firstLine->GetChildCount() + numOverflowFloaters);
// If the block is complete, put continuted floaters in the closest ancestor
// block that uses the same space manager and leave the block complete; this
// allows subsequent lines on the page to be impacted by floaters. If the
// block is incomplete or there is no ancestor using the same space manager,
// put continued floaters at the beginning of the first overflow line.
nsFrameList* overflowPlace = nsnull;
if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) &&
(overflowPlace = GetOverflowPlaceholders(aPresContext, PR_TRUE))) {
PRBool gaveToAncestor = PR_FALSE;
if (NS_FRAME_IS_COMPLETE(state.mReflowStatus)) {
// find the nearest block ancestor that uses the same space manager
for (const nsHTMLReflowState* ancestorRS = aReflowState.parentReflowState;
ancestorRS;
ancestorRS = ancestorRS->parentReflowState) {
nsIFrame* ancestor = ancestorRS->frame;
nsCOMPtr<nsIAtom> fType;
ancestor->GetFrameType(getter_AddRefs(fType));
if ((nsLayoutAtoms::blockFrame == fType) || (nsLayoutAtoms::areaFrame == fType)) {
if (aReflowState.mSpaceManager == ancestorRS->mSpaceManager) {
// Put the continued floaters in ancestor since it uses the same space manager
nsFrameList* ancestorPlace =
((nsBlockFrame*)ancestor)->GetOverflowPlaceholders(aPresContext, PR_FALSE);
if (ancestorPlace) {
ancestorPlace->AppendFrames(ancestor, overflowPlace->FirstChild());
}
else {
ancestorPlace = new nsFrameList(overflowPlace->FirstChild());
if (ancestorPlace) {
((nsBlockFrame*)ancestor)->SetOverflowPlaceholders(aPresContext, ancestorPlace);
}
else
return NS_ERROR_OUT_OF_MEMORY;
}
gaveToAncestor = PR_TRUE;
break;
}
}
}
}
else {
// Create a line, put the floaters in it, and then push.
nsLineBox* newLine = state.NewLineBox(state.mOverflowFloaters.FirstChild(),
state.mOverflowFloaters.GetLength(), PR_FALSE);
if (!newLine)
return NS_ERROR_OUT_OF_MEMORY;
mLines.push_back(newLine);
nsLineList::iterator nextToLastLine = ----end_lines();
PushLines(state, nextToLastLine);
if (!gaveToAncestor) {
PRInt32 numOverflowPlace = overflowPlace->GetLength();
nsLineList* overflowLines = GetOverflowLines(aPresContext, PR_FALSE);
if (overflowLines) {
line_iterator firstLine = overflowLines->begin();
if (firstLine->IsBlock()) {
// Create a new line as the first line and put the floaters there;
nsLineBox* newLine = state.NewLineBox(overflowPlace->FirstChild(), numOverflowPlace, PR_FALSE);
firstLine = mLines.before_insert(firstLine, newLine);
}
else { // floaters go on 1st overflow line
nsIFrame* firstFrame = firstLine->mFirstChild;
firstLine->mFirstChild = overflowPlace->FirstChild();
// hook up the last placeholder with the original frames
nsPlaceholderFrame* lastPlaceholder =
(nsPlaceholderFrame*)overflowPlace->LastChild();
lastPlaceholder->SetNextSibling(firstFrame);
NS_ASSERTION(firstFrame != lastPlaceholder, "trying to set next sibling to self");
firstLine->SetChildCount(firstLine->GetChildCount() + numOverflowPlace);
}
}
else {
// Create a line, put the floaters in it, and then push.
nsLineBox* newLine = state.NewLineBox(overflowPlace->FirstChild(), numOverflowPlace, PR_FALSE);
if (!newLine)
return NS_ERROR_OUT_OF_MEMORY;
mLines.push_back(newLine);
nsLineList::iterator nextToLastLine = ----end_lines();
PushLines(state, nextToLastLine);
}
state.mReflowStatus = NS_FRAME_NOT_COMPLETE;
}
state.mReflowStatus = NS_FRAME_NOT_COMPLETE;
state.mOverflowFloaters.SetFrames(nsnull);
delete overflowPlace;
}
if (NS_FRAME_IS_NOT_COMPLETE(state.mReflowStatus)) {
@ -3151,9 +3187,9 @@ nsBlockFrame::GetTopBlockChild(nsIPresContext* aPresContext)
// If placeholders/floaters split during reflowing a line, but that line will
// be put on the next page, then put the placeholders/floaters back the way
// they were before the line was reflowed.
static void
UndoPlaceholders(nsBlockReflowState& aState,
nsIFrame* aLastPlaceholder)
void
nsBlockFrame::UndoSplitPlaceholders(nsBlockReflowState& aState,
nsIFrame* aLastPlaceholder)
{
nsIFrame* undoPlaceholder = nsnull;
if (aLastPlaceholder) {
@ -3161,8 +3197,9 @@ UndoPlaceholders(nsBlockReflowState& aState,
aLastPlaceholder->SetNextSibling(nsnull);
}
else {
undoPlaceholder = aState.mOverflowFloaters.FirstChild();
aState.mOverflowFloaters.SetFrames(nsnull);
// just remove the property
nsFrameList* overflowPlace = GetOverflowPlaceholders(aState.mPresContext, PR_TRUE);
delete overflowPlace;
}
// remove the next in flows of the placeholders that need to be removed
for (nsIFrame* placeholder = undoPlaceholder; placeholder; ) {
@ -3320,7 +3357,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
}
// keep track of the last overflow floater in case we need to undo any new additions
nsIFrame* lastPlaceholder = aState.mOverflowFloaters.LastChild();
nsFrameList* overflowPlace = GetOverflowPlaceholders(aState.mPresContext, PR_FALSE);
nsIFrame* lastPlaceholder = (overflowPlace) ? overflowPlace->LastChild() : nsnull;
// Reflow the block into the available space
nsReflowStatus frameReflowStatus=NS_FRAME_COMPLETE;
@ -3353,7 +3391,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
if (NS_INLINE_IS_BREAK_BEFORE(frameReflowStatus)) {
// None of the child block fits.
::UndoPlaceholders(aState, lastPlaceholder);
UndoSplitPlaceholders(aState, lastPlaceholder);
PushLines(aState, aLine.prev());
*aKeepReflowGoing = PR_FALSE;
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;
@ -3530,7 +3568,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
else {
// Push the line that didn't fit and any lines that follow it
// to our next-in-flow.
::UndoPlaceholders(aState, lastPlaceholder);
UndoSplitPlaceholders(aState, lastPlaceholder);
PushLines(aState, aLine.prev());
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;
}
@ -3644,7 +3682,7 @@ nsBlockFrame::PushTruncatedPlaceholderLine(nsBlockReflowState& aState,
nsIFrame* aLastPlaceholder,
PRBool& aKeepReflowGoing)
{
::UndoPlaceholders(aState, aLastPlaceholder);
UndoSplitPlaceholders(aState, aLastPlaceholder);
line_iterator prevLine = aLine;
--prevLine;
@ -3716,7 +3754,8 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
}
// keep track of the last overflow floater in case we need to undo any new additions
nsIFrame* lastPlaceholder = aState.mOverflowFloaters.LastChild();
nsFrameList* overflowPlace = GetOverflowPlaceholders(aState.mPresContext, PR_FALSE);
nsIFrame* lastPlaceholder = (overflowPlace) ? overflowPlace->LastChild() : nsnull;
// Reflow the frames that are already on the line first
nsresult rv = NS_OK;
@ -3814,7 +3853,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// no point in placing the line.
if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
if (PlaceLine(aState, aLineLayout, aLine, aKeepReflowGoing, aUpdateMaximumWidth)) {
::UndoPlaceholders(aState, lastPlaceholder); // undo since we pushed the current line
UndoSplitPlaceholders(aState, lastPlaceholder); // undo since we pushed the current line
}
}
}
@ -3991,7 +4030,7 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
// frame may already have a continuation.
PRBool madeContinuation;
rv = (nsLayoutAtoms::placeholderFrame == frameType)
? SplitPlaceholder(aState, *aFrame)
? SplitPlaceholder(*aState.mPresContext, *aFrame)
: CreateContinuationFor(aState, aLine, aFrame, madeContinuation);
if (NS_FAILED(rv))
return rv;
@ -4070,11 +4109,11 @@ nsBlockFrame::CreateContinuationFor(nsBlockReflowState& aState,
}
nsresult
nsBlockFrame::SplitPlaceholder(nsBlockReflowState& aState,
nsIFrame& aPlaceholder)
nsBlockFrame::SplitPlaceholder(nsIPresContext& aPresContext,
nsIFrame& aPlaceholder)
{
nsIFrame* nextInFlow;
nsresult rv = CreateNextInFlow(aState.mPresContext, this, &aPlaceholder, nextInFlow);
nsresult rv = CreateNextInFlow(&aPresContext, this, &aPlaceholder, nextInFlow);
if (NS_FAILED(rv))
return rv;
// put the sibling list back to what it was before the continuation was created
@ -4084,7 +4123,17 @@ nsBlockFrame::SplitPlaceholder(nsBlockReflowState& aState,
aPlaceholder.SetNextSibling(next);
contFrame->SetNextSibling(nsnull);
// add the placehoder to the overflow floaters
aState.mOverflowFloaters.AppendFrames(this, contFrame);
nsFrameList* overflowPlace = GetOverflowPlaceholders(&aPresContext, PR_FALSE);
if (overflowPlace) {
overflowPlace->AppendFrames(this, contFrame);
}
else {
overflowPlace = new nsFrameList(contFrame);
if (overflowPlace) {
SetOverflowPlaceholders(&aPresContext, overflowPlace);
}
else return NS_ERROR_NULL_POINTER;
}
return NS_OK;
}
@ -4415,7 +4464,8 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
// Any below current line floaters to place?
if (aState.mBelowCurrentLineFloaters.NotEmpty()) {
// keep track of the last overflow floater in case we need to undo and push the line
nsIFrame* lastPlaceholder = aState.mOverflowFloaters.LastChild();
nsFrameList* overflowPlace = GetOverflowPlaceholders(aState.mPresContext, PR_FALSE);
nsIFrame* lastPlaceholder = (overflowPlace) ? overflowPlace->LastChild() : nsnull;
// Reflow the below-current-line floaters, then add them to the
// lines floater list if there aren't any truncated floaters.
if (aState.PlaceBelowCurrentLineFloaters(aState.mBelowCurrentLineFloaters)) {
@ -4739,31 +4789,12 @@ nsLineList*
nsBlockFrame::GetOverflowLines(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const
{
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
PRUint32 options = 0;
nsLineList* value;
if (aRemoveProperty) {
options |= NS_IFRAME_MGR_REMOVE_PROP;
}
frameManager->GetFrameProperty(NS_CONST_CAST(nsBlockFrame*, this),
nsLayoutAtoms::overflowLinesProperty,
options,
NS_REINTERPRET_CAST(void**, &value));
NS_ASSERTION(!value || !value->empty(),
"value should never be stored as empty");
return value;
}
}
return nsnull;
nsLineList* lines =
NS_STATIC_CAST(nsLineList*, GetProperty(aPresContext,
nsLayoutAtoms::overflowLinesProperty,
aRemoveProperty));
NS_ASSERTION(!lines || !lines->empty(), "value should never be stored as empty");
return lines;
}
// Destructor function for the overflowLines frame property
@ -4786,27 +4817,48 @@ nsresult
nsBlockFrame::SetOverflowLines(nsIPresContext* aPresContext,
nsLineList* aOverflowLines)
{
nsCOMPtr<nsIPresShell> presShell;
nsresult rv = NS_ERROR_FAILURE;
NS_ASSERTION(aOverflowLines, "null lines");
NS_ASSERTION(! aOverflowLines->empty(), "empty lines");
NS_ASSERTION(!aOverflowLines->empty(), "empty lines");
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
rv = frameManager->SetFrameProperty(this,
nsLayoutAtoms::overflowLinesProperty,
aOverflowLines,
DestroyOverflowLines);
nsresult rv = SetProperty(aPresContext, nsLayoutAtoms::overflowLinesProperty,
aOverflowLines, DestroyOverflowLines);
// Verify that we didn't overwrite an existing overflow list
NS_ASSERTION(rv != NS_IFRAME_MGR_PROP_OVERWRITTEN, "existing overflow list");
return rv;
}
// Verify that we didn't overwrite an existing overflow list
NS_ASSERTION(rv != NS_IFRAME_MGR_PROP_OVERWRITTEN, "existing overflow list");
}
}
nsFrameList*
nsBlockFrame::GetOverflowPlaceholders(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const
{
nsFrameList* placeholders =
NS_STATIC_CAST(nsFrameList*,
GetProperty(aPresContext, nsLayoutAtoms::overflowPlaceholdersProperty,
aRemoveProperty));
return placeholders;
}
// Destructor function for the overflowPlaceholders frame property
static void
DestroyOverflowPlaceholders(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue)
{
nsFrameList* overflowPlace = NS_STATIC_CAST(nsFrameList*, aPropertyValue);
delete overflowPlace;
}
// This takes ownership of aOverflowLines.
// XXX We should allocate overflowLines from presShell arena!
nsresult
nsBlockFrame::SetOverflowPlaceholders(nsIPresContext* aPresContext,
nsFrameList* aOverflowPlaceholders)
{
nsresult rv = SetProperty(aPresContext, nsLayoutAtoms::overflowPlaceholdersProperty,
aOverflowPlaceholders, DestroyOverflowPlaceholders);
// Verify that we didn't overwrite an existing overflow list
NS_ASSERTION(rv != NS_IFRAME_MGR_PROP_OVERWRITTEN, "existing overflow placeholder list");
return rv;
}

Просмотреть файл

@ -201,9 +201,11 @@ public:
// Create a contination for aPlaceholder and its out of flow frame and
// add it to the list of overflow floaters
nsresult SplitPlaceholder(nsBlockReflowState& aState,
nsIFrame& aPlaceholder);
nsresult SplitPlaceholder(nsIPresContext& aPresContext, nsIFrame& aPlaceholder);
void UndoSplitPlaceholders(nsBlockReflowState& aState,
nsIFrame* aLastPlaceholder);
protected:
nsBlockFrame();
virtual ~nsBlockFrame();
@ -503,6 +505,12 @@ protected:
nsresult SetOverflowLines(nsIPresContext* aPresContext,
nsLineList* aOverflowLines);
nsFrameList* GetOverflowPlaceholders(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const;
nsresult SetOverflowPlaceholders(nsIPresContext* aPresContext,
nsFrameList* aOverflowPlaceholders);
nsIFrame* LastChild();
#ifdef NS_DEBUG

Просмотреть файл

@ -46,6 +46,7 @@
#include "nsIPresContext.h"
#include "nsLayoutAtoms.h"
#include "nsIFrame.h"
#include "nsIFrameManager.h"
#include "nsINameSpaceManager.h"
#include "nsHTMLAtoms.h"
@ -124,7 +125,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
}
}
mHaveRightFloaters = PR_FALSE;
mOverflowFloaters.SetFrames(nsnull);
// Compute content area height. Unlike the width, if we have a
// specified style height we ignore it since extra content is
@ -847,7 +847,8 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
// content.
nscoord saveY = mY;
nsIFrame* floater = aFloaterCache->mPlaceholder->GetOutOfFlowFrame();
nsPlaceholderFrame* placeholder = aFloaterCache->mPlaceholder;
nsIFrame* floater = placeholder->GetOutOfFlowFrame();
// Grab the floater's display information
const nsStyleDisplay* floaterDisplay;
@ -879,8 +880,8 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
}
// Reflow the floater
mBlock->ReflowFloater(*this, aFloaterCache->mPlaceholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets, aReflowStatus);
mBlock->ReflowFloater(*this, placeholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets, aReflowStatus);
// Get the floaters bounding box and margin information
floater->GetRect(region);
@ -963,7 +964,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
mY += mAvailSpaceRect.height;
GetAvailableSpace();
// reflow the floater again now since we have more space
mBlock->ReflowFloater(*this, aFloaterCache->mPlaceholder, aFloaterCache->mCombinedArea,
mBlock->ReflowFloater(*this, placeholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets, aReflowStatus);
// Get the floaters bounding box and margin information
floater->GetRect(region);
@ -974,12 +975,33 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
}
}
// If the floater is continued, it will get the same x value as its prev-in-flow
nsRect prevInFlowRect(0,0,0,0);
// If the floater is continued, it will get the same absolute x value as its prev-in-flow
nsRect prevRect(0,0,0,0);
nsIFrame* prevInFlow;
floater->GetPrevInFlow(&prevInFlow);
if (prevInFlow) {
prevInFlow->GetRect(prevInFlowRect);
prevInFlow->GetRect(prevRect);
nsCOMPtr<nsIPresShell> presShell;
mPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
nsIFrame *placeParent, *placeParentPrev, *prevPlace, *prevPlaceParent;
// If prevInFlow's placeholder is in a block that wasn't continued, we need to adjust
// prevRect.x to account for the missing frame offsets.
placeholder->GetParent(&placeParent);
placeParent->GetPrevInFlow(&placeParentPrev);
frameManager->GetPlaceholderFrameFor(prevInFlow, &prevPlace);
prevPlace->GetParent(&prevPlaceParent);
for (nsIFrame* ancestor = prevPlaceParent;
ancestor && (ancestor != placeParentPrev);
ancestor->GetParent(&ancestor)) {
nsRect rect;
ancestor->GetRect(rect);
prevRect.x += rect.x;
}
}
// Assign an x and y coordinate to the floater. Note that the x,y
// coordinates are computed <b>relative to the translation in the
@ -989,7 +1011,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
PRBool isLeftFloater;
if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
isLeftFloater = PR_TRUE;
region.x = (prevInFlow) ? prevInFlowRect.x : mAvailSpaceRect.x;
region.x = (prevInFlow) ? prevRect.x : mAvailSpaceRect.x;
}
else {
isLeftFloater = PR_FALSE;
@ -997,7 +1019,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
nsIFrame* prevInFlow;
floater->GetPrevInFlow(&prevInFlow);
if (prevInFlow) {
region.x = prevInFlowRect.x;
region.x = prevRect.x;
}
else if (!keepFloaterOnSameLine) {
region.x = mAvailSpaceRect.XMost() - region.width;
@ -1030,7 +1052,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
// if the floater split, then take up all of the vertical height
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
(NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
region.height += PR_MAX(region.height, mContentArea.height);
region.height = PR_MAX(region.height, mContentArea.height);
}
#ifdef DEBUG
nsresult rv =
@ -1160,7 +1182,7 @@ nsBlockReflowState::PlaceBelowCurrentLineFloaters(nsFloaterCacheList& aList)
}
else if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) {
// Create a continuation for the incomplete floater and its placeholder.
nsresult rv = mBlock->SplitPlaceholder(*this, *fc->mPlaceholder);
nsresult rv = mBlock->SplitPlaceholder(*mPresContext, *fc->mPlaceholder);
if (NS_FAILED(rv))
return PR_FALSE;
}

Просмотреть файл

@ -199,9 +199,6 @@ public:
nsFloaterCacheFreeList mFloaterCacheFreeList;
// next-in-flows of incomplete floaters which get put into overflow lines
nsFrameList mOverflowFloaters;
// Previous child. This is used when pulling up a frame to update
// the sibling list.
nsIFrame* mPrevChild;

Просмотреть файл

@ -4621,6 +4621,54 @@ nsFrame::IsMouseCaptured(nsIPresContext* aPresContext)
return PR_FALSE;
}
nsresult
nsFrame::SetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropName,
void* aPropValue,
NSFramePropertyDtorFunc aPropDtorFunc)
{
nsCOMPtr<nsIPresShell> presShell;
nsresult rv = NS_ERROR_FAILURE;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
rv = frameManager->SetFrameProperty(this, aPropName, aPropValue, aPropDtorFunc);
}
}
return rv;
}
void*
nsFrame::GetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropName,
PRBool aRemoveProp) const
{
void* value = nsnull;
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
PRUint32 options = 0;
if (aRemoveProp) {
options |= NS_IFRAME_MGR_REMOVE_PROP;
}
frameManager->GetFrameProperty((nsIFrame*)this, aPropName, options, &value);
}
}
return value;
}
#ifdef IBMBIDI
/**
* retrieve Bidi property of this frame

Просмотреть файл

@ -386,6 +386,16 @@ public:
//Mouse Capturing code used by the frames to tell the view to capture all the following events
NS_IMETHOD CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents);
PRBool IsMouseCaptured(nsIPresContext* aPresContext);
virtual void* GetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropertyName,
PRBool aRemoveProperty) const;
virtual nsresult SetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFramePropertyDtorFunc aPropDtorFunc);
#ifdef IBMBIDI
NS_IMETHOD GetBidiProperty(nsIPresContext* aPresContext,
nsIAtom* aPropertyName,

Просмотреть файл

@ -90,6 +90,13 @@ struct nsRect;
struct nsSize;
struct nsMargin;
// Calback function used to destroy the value associated with a property.
typedef void
(*NSFramePropertyDtorFunc)(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue);
// IID for the nsIFrame interface
// a6cf9050-15b3-11d2-932e-00805f8add32
#define NS_IFRAME_IID \
@ -1158,6 +1165,14 @@ public:
PRBool aIsPre,
PRBool* aResult) = 0;
virtual void* GetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropertyName,
PRBool aRemoveProperty) const = 0;
virtual nsresult SetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFramePropertyDtorFunc aPropDtorFunc) = 0;
#ifdef IBMBIDI
/**
* retrieve and set Bidi property of this frame

Просмотреть файл

@ -779,7 +779,7 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext* aPresContext,
aFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::placeholderFrame == frameType) {
nsBlockReflowState* blockRS = lineLayout->mBlockRS;
blockRS->mBlock->SplitPlaceholder(*blockRS, *aFrame);
blockRS->mBlock->SplitPlaceholder(*aPresContext, *aFrame);
}
else {
nsIFrame* newFrame;

Просмотреть файл

@ -945,42 +945,78 @@ nsBlockFrame::Reflow(nsIPresContext* aPresContext,
NS_ASSERTION(NS_SUCCEEDED(rv), "reflow dirty lines failed");
if (NS_FAILED(rv)) return rv;
// Put continued floaters at the beginning of the first overflow line. If the first line
// is a block then create a new line as the first line and put the floaters there. If there
// are no overflow lines, then create one and put the floaters in it.
if (state.mOverflowFloaters.NotEmpty()) {
nsLineList* overflowLines = GetOverflowLines(aPresContext, PR_FALSE);
if (overflowLines) {
line_iterator firstLine = overflowLines->begin();
if (firstLine->IsBlock()) { // floaters go on a new line before 1st overflow line
nsLineBox* newLine = state.NewLineBox(state.mOverflowFloaters.FirstChild(),
state.mOverflowFloaters.GetLength(), PR_FALSE);
firstLine = mLines.before_insert(firstLine, newLine);
}
else { // floaters go on 1st overflow line
nsIFrame* firstFrame = firstLine->mFirstChild;
firstLine->mFirstChild = state.mOverflowFloaters.FirstChild();
PRInt32 numOverflowFloaters = state.mOverflowFloaters.GetLength();
// hook up the last placeholder with the original frames
nsPlaceholderFrame* lastPlaceholder =
(nsPlaceholderFrame*)state.mOverflowFloaters.LastChild();
lastPlaceholder->SetNextSibling(firstFrame);
NS_ASSERTION(firstFrame != lastPlaceholder, "trying to set next sibling to self");
firstLine->SetChildCount(firstLine->GetChildCount() + numOverflowFloaters);
// If the block is complete, put continuted floaters in the closest ancestor
// block that uses the same space manager and leave the block complete; this
// allows subsequent lines on the page to be impacted by floaters. If the
// block is incomplete or there is no ancestor using the same space manager,
// put continued floaters at the beginning of the first overflow line.
nsFrameList* overflowPlace = nsnull;
if ((NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight) &&
(overflowPlace = GetOverflowPlaceholders(aPresContext, PR_TRUE))) {
PRBool gaveToAncestor = PR_FALSE;
if (NS_FRAME_IS_COMPLETE(state.mReflowStatus)) {
// find the nearest block ancestor that uses the same space manager
for (const nsHTMLReflowState* ancestorRS = aReflowState.parentReflowState;
ancestorRS;
ancestorRS = ancestorRS->parentReflowState) {
nsIFrame* ancestor = ancestorRS->frame;
nsCOMPtr<nsIAtom> fType;
ancestor->GetFrameType(getter_AddRefs(fType));
if ((nsLayoutAtoms::blockFrame == fType) || (nsLayoutAtoms::areaFrame == fType)) {
if (aReflowState.mSpaceManager == ancestorRS->mSpaceManager) {
// Put the continued floaters in ancestor since it uses the same space manager
nsFrameList* ancestorPlace =
((nsBlockFrame*)ancestor)->GetOverflowPlaceholders(aPresContext, PR_FALSE);
if (ancestorPlace) {
ancestorPlace->AppendFrames(ancestor, overflowPlace->FirstChild());
}
else {
ancestorPlace = new nsFrameList(overflowPlace->FirstChild());
if (ancestorPlace) {
((nsBlockFrame*)ancestor)->SetOverflowPlaceholders(aPresContext, ancestorPlace);
}
else
return NS_ERROR_OUT_OF_MEMORY;
}
gaveToAncestor = PR_TRUE;
break;
}
}
}
}
else {
// Create a line, put the floaters in it, and then push.
nsLineBox* newLine = state.NewLineBox(state.mOverflowFloaters.FirstChild(),
state.mOverflowFloaters.GetLength(), PR_FALSE);
if (!newLine)
return NS_ERROR_OUT_OF_MEMORY;
mLines.push_back(newLine);
nsLineList::iterator nextToLastLine = ----end_lines();
PushLines(state, nextToLastLine);
if (!gaveToAncestor) {
PRInt32 numOverflowPlace = overflowPlace->GetLength();
nsLineList* overflowLines = GetOverflowLines(aPresContext, PR_FALSE);
if (overflowLines) {
line_iterator firstLine = overflowLines->begin();
if (firstLine->IsBlock()) {
// Create a new line as the first line and put the floaters there;
nsLineBox* newLine = state.NewLineBox(overflowPlace->FirstChild(), numOverflowPlace, PR_FALSE);
firstLine = mLines.before_insert(firstLine, newLine);
}
else { // floaters go on 1st overflow line
nsIFrame* firstFrame = firstLine->mFirstChild;
firstLine->mFirstChild = overflowPlace->FirstChild();
// hook up the last placeholder with the original frames
nsPlaceholderFrame* lastPlaceholder =
(nsPlaceholderFrame*)overflowPlace->LastChild();
lastPlaceholder->SetNextSibling(firstFrame);
NS_ASSERTION(firstFrame != lastPlaceholder, "trying to set next sibling to self");
firstLine->SetChildCount(firstLine->GetChildCount() + numOverflowPlace);
}
}
else {
// Create a line, put the floaters in it, and then push.
nsLineBox* newLine = state.NewLineBox(overflowPlace->FirstChild(), numOverflowPlace, PR_FALSE);
if (!newLine)
return NS_ERROR_OUT_OF_MEMORY;
mLines.push_back(newLine);
nsLineList::iterator nextToLastLine = ----end_lines();
PushLines(state, nextToLastLine);
}
state.mReflowStatus = NS_FRAME_NOT_COMPLETE;
}
state.mReflowStatus = NS_FRAME_NOT_COMPLETE;
state.mOverflowFloaters.SetFrames(nsnull);
delete overflowPlace;
}
if (NS_FRAME_IS_NOT_COMPLETE(state.mReflowStatus)) {
@ -3151,9 +3187,9 @@ nsBlockFrame::GetTopBlockChild(nsIPresContext* aPresContext)
// If placeholders/floaters split during reflowing a line, but that line will
// be put on the next page, then put the placeholders/floaters back the way
// they were before the line was reflowed.
static void
UndoPlaceholders(nsBlockReflowState& aState,
nsIFrame* aLastPlaceholder)
void
nsBlockFrame::UndoSplitPlaceholders(nsBlockReflowState& aState,
nsIFrame* aLastPlaceholder)
{
nsIFrame* undoPlaceholder = nsnull;
if (aLastPlaceholder) {
@ -3161,8 +3197,9 @@ UndoPlaceholders(nsBlockReflowState& aState,
aLastPlaceholder->SetNextSibling(nsnull);
}
else {
undoPlaceholder = aState.mOverflowFloaters.FirstChild();
aState.mOverflowFloaters.SetFrames(nsnull);
// just remove the property
nsFrameList* overflowPlace = GetOverflowPlaceholders(aState.mPresContext, PR_TRUE);
delete overflowPlace;
}
// remove the next in flows of the placeholders that need to be removed
for (nsIFrame* placeholder = undoPlaceholder; placeholder; ) {
@ -3320,7 +3357,8 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
}
// keep track of the last overflow floater in case we need to undo any new additions
nsIFrame* lastPlaceholder = aState.mOverflowFloaters.LastChild();
nsFrameList* overflowPlace = GetOverflowPlaceholders(aState.mPresContext, PR_FALSE);
nsIFrame* lastPlaceholder = (overflowPlace) ? overflowPlace->LastChild() : nsnull;
// Reflow the block into the available space
nsReflowStatus frameReflowStatus=NS_FRAME_COMPLETE;
@ -3353,7 +3391,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
if (NS_INLINE_IS_BREAK_BEFORE(frameReflowStatus)) {
// None of the child block fits.
::UndoPlaceholders(aState, lastPlaceholder);
UndoSplitPlaceholders(aState, lastPlaceholder);
PushLines(aState, aLine.prev());
*aKeepReflowGoing = PR_FALSE;
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;
@ -3530,7 +3568,7 @@ nsBlockFrame::ReflowBlockFrame(nsBlockReflowState& aState,
else {
// Push the line that didn't fit and any lines that follow it
// to our next-in-flow.
::UndoPlaceholders(aState, lastPlaceholder);
UndoSplitPlaceholders(aState, lastPlaceholder);
PushLines(aState, aLine.prev());
aState.mReflowStatus = NS_FRAME_NOT_COMPLETE;
}
@ -3644,7 +3682,7 @@ nsBlockFrame::PushTruncatedPlaceholderLine(nsBlockReflowState& aState,
nsIFrame* aLastPlaceholder,
PRBool& aKeepReflowGoing)
{
::UndoPlaceholders(aState, aLastPlaceholder);
UndoSplitPlaceholders(aState, aLastPlaceholder);
line_iterator prevLine = aLine;
--prevLine;
@ -3716,7 +3754,8 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
}
// keep track of the last overflow floater in case we need to undo any new additions
nsIFrame* lastPlaceholder = aState.mOverflowFloaters.LastChild();
nsFrameList* overflowPlace = GetOverflowPlaceholders(aState.mPresContext, PR_FALSE);
nsIFrame* lastPlaceholder = (overflowPlace) ? overflowPlace->LastChild() : nsnull;
// Reflow the frames that are already on the line first
nsresult rv = NS_OK;
@ -3814,7 +3853,7 @@ nsBlockFrame::DoReflowInlineFrames(nsBlockReflowState& aState,
// no point in placing the line.
if (!NS_INLINE_IS_BREAK_BEFORE(aState.mReflowStatus)) {
if (PlaceLine(aState, aLineLayout, aLine, aKeepReflowGoing, aUpdateMaximumWidth)) {
::UndoPlaceholders(aState, lastPlaceholder); // undo since we pushed the current line
UndoSplitPlaceholders(aState, lastPlaceholder); // undo since we pushed the current line
}
}
}
@ -3991,7 +4030,7 @@ nsBlockFrame::ReflowInlineFrame(nsBlockReflowState& aState,
// frame may already have a continuation.
PRBool madeContinuation;
rv = (nsLayoutAtoms::placeholderFrame == frameType)
? SplitPlaceholder(aState, *aFrame)
? SplitPlaceholder(*aState.mPresContext, *aFrame)
: CreateContinuationFor(aState, aLine, aFrame, madeContinuation);
if (NS_FAILED(rv))
return rv;
@ -4070,11 +4109,11 @@ nsBlockFrame::CreateContinuationFor(nsBlockReflowState& aState,
}
nsresult
nsBlockFrame::SplitPlaceholder(nsBlockReflowState& aState,
nsIFrame& aPlaceholder)
nsBlockFrame::SplitPlaceholder(nsIPresContext& aPresContext,
nsIFrame& aPlaceholder)
{
nsIFrame* nextInFlow;
nsresult rv = CreateNextInFlow(aState.mPresContext, this, &aPlaceholder, nextInFlow);
nsresult rv = CreateNextInFlow(&aPresContext, this, &aPlaceholder, nextInFlow);
if (NS_FAILED(rv))
return rv;
// put the sibling list back to what it was before the continuation was created
@ -4084,7 +4123,17 @@ nsBlockFrame::SplitPlaceholder(nsBlockReflowState& aState,
aPlaceholder.SetNextSibling(next);
contFrame->SetNextSibling(nsnull);
// add the placehoder to the overflow floaters
aState.mOverflowFloaters.AppendFrames(this, contFrame);
nsFrameList* overflowPlace = GetOverflowPlaceholders(&aPresContext, PR_FALSE);
if (overflowPlace) {
overflowPlace->AppendFrames(this, contFrame);
}
else {
overflowPlace = new nsFrameList(contFrame);
if (overflowPlace) {
SetOverflowPlaceholders(&aPresContext, overflowPlace);
}
else return NS_ERROR_NULL_POINTER;
}
return NS_OK;
}
@ -4415,7 +4464,8 @@ nsBlockFrame::PlaceLine(nsBlockReflowState& aState,
// Any below current line floaters to place?
if (aState.mBelowCurrentLineFloaters.NotEmpty()) {
// keep track of the last overflow floater in case we need to undo and push the line
nsIFrame* lastPlaceholder = aState.mOverflowFloaters.LastChild();
nsFrameList* overflowPlace = GetOverflowPlaceholders(aState.mPresContext, PR_FALSE);
nsIFrame* lastPlaceholder = (overflowPlace) ? overflowPlace->LastChild() : nsnull;
// Reflow the below-current-line floaters, then add them to the
// lines floater list if there aren't any truncated floaters.
if (aState.PlaceBelowCurrentLineFloaters(aState.mBelowCurrentLineFloaters)) {
@ -4739,31 +4789,12 @@ nsLineList*
nsBlockFrame::GetOverflowLines(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const
{
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
PRUint32 options = 0;
nsLineList* value;
if (aRemoveProperty) {
options |= NS_IFRAME_MGR_REMOVE_PROP;
}
frameManager->GetFrameProperty(NS_CONST_CAST(nsBlockFrame*, this),
nsLayoutAtoms::overflowLinesProperty,
options,
NS_REINTERPRET_CAST(void**, &value));
NS_ASSERTION(!value || !value->empty(),
"value should never be stored as empty");
return value;
}
}
return nsnull;
nsLineList* lines =
NS_STATIC_CAST(nsLineList*, GetProperty(aPresContext,
nsLayoutAtoms::overflowLinesProperty,
aRemoveProperty));
NS_ASSERTION(!lines || !lines->empty(), "value should never be stored as empty");
return lines;
}
// Destructor function for the overflowLines frame property
@ -4786,27 +4817,48 @@ nsresult
nsBlockFrame::SetOverflowLines(nsIPresContext* aPresContext,
nsLineList* aOverflowLines)
{
nsCOMPtr<nsIPresShell> presShell;
nsresult rv = NS_ERROR_FAILURE;
NS_ASSERTION(aOverflowLines, "null lines");
NS_ASSERTION(! aOverflowLines->empty(), "empty lines");
NS_ASSERTION(!aOverflowLines->empty(), "empty lines");
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
rv = frameManager->SetFrameProperty(this,
nsLayoutAtoms::overflowLinesProperty,
aOverflowLines,
DestroyOverflowLines);
nsresult rv = SetProperty(aPresContext, nsLayoutAtoms::overflowLinesProperty,
aOverflowLines, DestroyOverflowLines);
// Verify that we didn't overwrite an existing overflow list
NS_ASSERTION(rv != NS_IFRAME_MGR_PROP_OVERWRITTEN, "existing overflow list");
return rv;
}
// Verify that we didn't overwrite an existing overflow list
NS_ASSERTION(rv != NS_IFRAME_MGR_PROP_OVERWRITTEN, "existing overflow list");
}
}
nsFrameList*
nsBlockFrame::GetOverflowPlaceholders(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const
{
nsFrameList* placeholders =
NS_STATIC_CAST(nsFrameList*,
GetProperty(aPresContext, nsLayoutAtoms::overflowPlaceholdersProperty,
aRemoveProperty));
return placeholders;
}
// Destructor function for the overflowPlaceholders frame property
static void
DestroyOverflowPlaceholders(nsIPresContext* aPresContext,
nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue)
{
nsFrameList* overflowPlace = NS_STATIC_CAST(nsFrameList*, aPropertyValue);
delete overflowPlace;
}
// This takes ownership of aOverflowLines.
// XXX We should allocate overflowLines from presShell arena!
nsresult
nsBlockFrame::SetOverflowPlaceholders(nsIPresContext* aPresContext,
nsFrameList* aOverflowPlaceholders)
{
nsresult rv = SetProperty(aPresContext, nsLayoutAtoms::overflowPlaceholdersProperty,
aOverflowPlaceholders, DestroyOverflowPlaceholders);
// Verify that we didn't overwrite an existing overflow list
NS_ASSERTION(rv != NS_IFRAME_MGR_PROP_OVERWRITTEN, "existing overflow placeholder list");
return rv;
}

Просмотреть файл

@ -201,9 +201,11 @@ public:
// Create a contination for aPlaceholder and its out of flow frame and
// add it to the list of overflow floaters
nsresult SplitPlaceholder(nsBlockReflowState& aState,
nsIFrame& aPlaceholder);
nsresult SplitPlaceholder(nsIPresContext& aPresContext, nsIFrame& aPlaceholder);
void UndoSplitPlaceholders(nsBlockReflowState& aState,
nsIFrame* aLastPlaceholder);
protected:
nsBlockFrame();
virtual ~nsBlockFrame();
@ -503,6 +505,12 @@ protected:
nsresult SetOverflowLines(nsIPresContext* aPresContext,
nsLineList* aOverflowLines);
nsFrameList* GetOverflowPlaceholders(nsIPresContext* aPresContext,
PRBool aRemoveProperty) const;
nsresult SetOverflowPlaceholders(nsIPresContext* aPresContext,
nsFrameList* aOverflowPlaceholders);
nsIFrame* LastChild();
#ifdef NS_DEBUG

Просмотреть файл

@ -46,6 +46,7 @@
#include "nsIPresContext.h"
#include "nsLayoutAtoms.h"
#include "nsIFrame.h"
#include "nsIFrameManager.h"
#include "nsINameSpaceManager.h"
#include "nsHTMLAtoms.h"
@ -124,7 +125,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
}
}
mHaveRightFloaters = PR_FALSE;
mOverflowFloaters.SetFrames(nsnull);
// Compute content area height. Unlike the width, if we have a
// specified style height we ignore it since extra content is
@ -847,7 +847,8 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
// content.
nscoord saveY = mY;
nsIFrame* floater = aFloaterCache->mPlaceholder->GetOutOfFlowFrame();
nsPlaceholderFrame* placeholder = aFloaterCache->mPlaceholder;
nsIFrame* floater = placeholder->GetOutOfFlowFrame();
// Grab the floater's display information
const nsStyleDisplay* floaterDisplay;
@ -879,8 +880,8 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
}
// Reflow the floater
mBlock->ReflowFloater(*this, aFloaterCache->mPlaceholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets, aReflowStatus);
mBlock->ReflowFloater(*this, placeholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets, aReflowStatus);
// Get the floaters bounding box and margin information
floater->GetRect(region);
@ -963,7 +964,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
mY += mAvailSpaceRect.height;
GetAvailableSpace();
// reflow the floater again now since we have more space
mBlock->ReflowFloater(*this, aFloaterCache->mPlaceholder, aFloaterCache->mCombinedArea,
mBlock->ReflowFloater(*this, placeholder, aFloaterCache->mCombinedArea,
aFloaterCache->mMargins, aFloaterCache->mOffsets, aReflowStatus);
// Get the floaters bounding box and margin information
floater->GetRect(region);
@ -974,12 +975,33 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
}
}
// If the floater is continued, it will get the same x value as its prev-in-flow
nsRect prevInFlowRect(0,0,0,0);
// If the floater is continued, it will get the same absolute x value as its prev-in-flow
nsRect prevRect(0,0,0,0);
nsIFrame* prevInFlow;
floater->GetPrevInFlow(&prevInFlow);
if (prevInFlow) {
prevInFlow->GetRect(prevInFlowRect);
prevInFlow->GetRect(prevRect);
nsCOMPtr<nsIPresShell> presShell;
mPresContext->GetShell(getter_AddRefs(presShell));
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
nsIFrame *placeParent, *placeParentPrev, *prevPlace, *prevPlaceParent;
// If prevInFlow's placeholder is in a block that wasn't continued, we need to adjust
// prevRect.x to account for the missing frame offsets.
placeholder->GetParent(&placeParent);
placeParent->GetPrevInFlow(&placeParentPrev);
frameManager->GetPlaceholderFrameFor(prevInFlow, &prevPlace);
prevPlace->GetParent(&prevPlaceParent);
for (nsIFrame* ancestor = prevPlaceParent;
ancestor && (ancestor != placeParentPrev);
ancestor->GetParent(&ancestor)) {
nsRect rect;
ancestor->GetRect(rect);
prevRect.x += rect.x;
}
}
// Assign an x and y coordinate to the floater. Note that the x,y
// coordinates are computed <b>relative to the translation in the
@ -989,7 +1011,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
PRBool isLeftFloater;
if (NS_STYLE_FLOAT_LEFT == floaterDisplay->mFloats) {
isLeftFloater = PR_TRUE;
region.x = (prevInFlow) ? prevInFlowRect.x : mAvailSpaceRect.x;
region.x = (prevInFlow) ? prevRect.x : mAvailSpaceRect.x;
}
else {
isLeftFloater = PR_FALSE;
@ -997,7 +1019,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
nsIFrame* prevInFlow;
floater->GetPrevInFlow(&prevInFlow);
if (prevInFlow) {
region.x = prevInFlowRect.x;
region.x = prevRect.x;
}
else if (!keepFloaterOnSameLine) {
region.x = mAvailSpaceRect.XMost() - region.width;
@ -1030,7 +1052,7 @@ nsBlockReflowState::FlowAndPlaceFloater(nsFloaterCache* aFloaterCache,
// if the floater split, then take up all of the vertical height
if (NS_FRAME_IS_NOT_COMPLETE(aReflowStatus) &&
(NS_UNCONSTRAINEDSIZE != mContentArea.height)) {
region.height += PR_MAX(region.height, mContentArea.height);
region.height = PR_MAX(region.height, mContentArea.height);
}
#ifdef DEBUG
nsresult rv =
@ -1160,7 +1182,7 @@ nsBlockReflowState::PlaceBelowCurrentLineFloaters(nsFloaterCacheList& aList)
}
else if (NS_FRAME_IS_NOT_COMPLETE(reflowStatus)) {
// Create a continuation for the incomplete floater and its placeholder.
nsresult rv = mBlock->SplitPlaceholder(*this, *fc->mPlaceholder);
nsresult rv = mBlock->SplitPlaceholder(*mPresContext, *fc->mPlaceholder);
if (NS_FAILED(rv))
return PR_FALSE;
}

Просмотреть файл

@ -199,9 +199,6 @@ public:
nsFloaterCacheFreeList mFloaterCacheFreeList;
// next-in-flows of incomplete floaters which get put into overflow lines
nsFrameList mOverflowFloaters;
// Previous child. This is used when pulling up a frame to update
// the sibling list.
nsIFrame* mPrevChild;

Просмотреть файл

@ -4621,6 +4621,54 @@ nsFrame::IsMouseCaptured(nsIPresContext* aPresContext)
return PR_FALSE;
}
nsresult
nsFrame::SetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropName,
void* aPropValue,
NSFramePropertyDtorFunc aPropDtorFunc)
{
nsCOMPtr<nsIPresShell> presShell;
nsresult rv = NS_ERROR_FAILURE;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
rv = frameManager->SetFrameProperty(this, aPropName, aPropValue, aPropDtorFunc);
}
}
return rv;
}
void*
nsFrame::GetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropName,
PRBool aRemoveProp) const
{
void* value = nsnull;
nsCOMPtr<nsIPresShell> presShell;
aPresContext->GetShell(getter_AddRefs(presShell));
if (presShell) {
nsCOMPtr<nsIFrameManager> frameManager;
presShell->GetFrameManager(getter_AddRefs(frameManager));
if (frameManager) {
PRUint32 options = 0;
if (aRemoveProp) {
options |= NS_IFRAME_MGR_REMOVE_PROP;
}
frameManager->GetFrameProperty((nsIFrame*)this, aPropName, options, &value);
}
}
return value;
}
#ifdef IBMBIDI
/**
* retrieve Bidi property of this frame

Просмотреть файл

@ -386,6 +386,16 @@ public:
//Mouse Capturing code used by the frames to tell the view to capture all the following events
NS_IMETHOD CaptureMouse(nsIPresContext* aPresContext, PRBool aGrabMouseEvents);
PRBool IsMouseCaptured(nsIPresContext* aPresContext);
virtual void* GetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropertyName,
PRBool aRemoveProperty) const;
virtual nsresult SetProperty(nsIPresContext* aPresContext,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFramePropertyDtorFunc aPropDtorFunc);
#ifdef IBMBIDI
NS_IMETHOD GetBidiProperty(nsIPresContext* aPresContext,
nsIAtom* aPropertyName,

Просмотреть файл

@ -371,10 +371,10 @@ public:
nsIAtom* aPropertyName,
PRUint32 aOptions,
void** aPropertyValue);
NS_IMETHOD SetFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFMPropertyDtorFunc aPropDtorFunc);
NS_IMETHOD SetFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFramePropertyDtorFunc aPropDtorFunc);
NS_IMETHOD RemoveFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName);
@ -383,13 +383,13 @@ public:
#endif
struct PropertyList {
nsCOMPtr<nsIAtom> mName; // property name
PLDHashTable mFrameValueMap; // map of frame/value pairs
NSFMPropertyDtorFunc mDtorFunc; // property specific value dtor function
PropertyList* mNext;
nsCOMPtr<nsIAtom> mName; // property name
PLDHashTable mFrameValueMap; // map of frame/value pairs
NSFramePropertyDtorFunc mDtorFunc; // property specific value dtor function
PropertyList* mNext;
PropertyList(nsIAtom* aName,
NSFMPropertyDtorFunc aDtorFunc);
PropertyList(nsIAtom* aName,
NSFramePropertyDtorFunc aDtorFunc);
~PropertyList();
// Removes the property associated with the given frame, and destroys
@ -2452,10 +2452,10 @@ FrameManager::GetFrameProperty(nsIFrame* aFrame,
}
NS_IMETHODIMP
FrameManager::SetFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFMPropertyDtorFunc aPropDtorFunc)
FrameManager::SetFrameProperty(nsIFrame* aFrame,
nsIAtom* aPropertyName,
void* aPropertyValue,
NSFramePropertyDtorFunc aPropDtorFunc)
{
NS_ENSURE_TRUE(mPresShell, NS_ERROR_NOT_AVAILABLE);
NS_PRECONDITION(aPropertyName && aFrame, "unexpected null param");
@ -2667,8 +2667,8 @@ UndisplayedMap::Clear(void)
//----------------------------------------------------------------------
FrameManager::PropertyList::PropertyList(nsIAtom* aName,
NSFMPropertyDtorFunc aDtorFunc)
FrameManager::PropertyList::PropertyList(nsIAtom* aName,
NSFramePropertyDtorFunc aDtorFunc)
: mName(aName), mDtorFunc(aDtorFunc), mNext(nsnull)
{
PL_DHashTableInit(&mFrameValueMap, PL_DHashGetStubOps(), this,

Просмотреть файл

@ -779,7 +779,7 @@ nsInlineFrame::ReflowInlineFrame(nsIPresContext* aPresContext,
aFrame->GetFrameType(getter_AddRefs(frameType));
if (nsLayoutAtoms::placeholderFrame == frameType) {
nsBlockReflowState* blockRS = lineLayout->mBlockRS;
blockRS->mBlock->SplitPlaceholder(*blockRS, *aFrame);
blockRS->mBlock->SplitPlaceholder(*aPresContext, *aFrame);
}
else {
nsIFrame* newFrame;

Просмотреть файл

@ -7412,7 +7412,7 @@ nsTableFrame::GetProperty(nsIPresContext* aPresContext,
// The property isn't set yet, so allocate a new value, set the property,
// and return the newly allocated value
void* value = nsnull;
NSFMPropertyDtorFunc dtorFunc = nsnull;
NSFramePropertyDtorFunc dtorFunc = nsnull;
if (aPropertyName == nsLayoutAtoms::collapseOffsetProperty) {
value = new nsPoint(0, 0);
dtorFunc = DestroyPointFunc;

Просмотреть файл

@ -7412,7 +7412,7 @@ nsTableFrame::GetProperty(nsIPresContext* aPresContext,
// The property isn't set yet, so allocate a new value, set the property,
// and return the newly allocated value
void* value = nsnull;
NSFMPropertyDtorFunc dtorFunc = nsnull;
NSFramePropertyDtorFunc dtorFunc = nsnull;
if (aPropertyName == nsLayoutAtoms::collapseOffsetProperty) {
value = new nsPoint(0, 0);
dtorFunc = DestroyPointFunc;