mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-16 14:55:47 +00:00
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
This commit is contained in:
parent
cd352c37e1
commit
31f1898810
@ -1301,6 +1301,7 @@ GK_ATOM(boxFrame, "BoxFrame")
|
||||
GK_ATOM(brFrame, "BRFrame")
|
||||
GK_ATOM(bulletFrame, "BulletFrame")
|
||||
GK_ATOM(columnSetFrame, "ColumnSetFrame")
|
||||
GK_ATOM(comboboxControlFrame, "ComboboxControlFrame")
|
||||
GK_ATOM(directionalFrame, "DirectionalFrame")
|
||||
GK_ATOM(fieldSetFrame, "FieldSetFrame")
|
||||
GK_ATOM(frameSetFrame, "FrameSetFrame")
|
||||
|
@ -1179,7 +1179,7 @@ nsGenericHTMLElement::GetClientHeight(PRInt32* aClientHeight)
|
||||
*aClientHeight = NSTwipsToIntPixels(r.height, t2p);
|
||||
} else if (frame &&
|
||||
(frame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE ||
|
||||
(frame->GetStateBits() & NS_FRAME_REPLACED_ELEMENT))) {
|
||||
(frame->IsFrameOfType(nsIFrame::eReplaced)))) {
|
||||
// Special case code to make clientHeight work even when there isn't
|
||||
// a scroll view, see bug 180552 and bug 227567.
|
||||
|
||||
@ -1207,7 +1207,7 @@ nsGenericHTMLElement::GetClientWidth(PRInt32* aClientWidth)
|
||||
*aClientWidth = NSTwipsToIntPixels(r.width, t2p);
|
||||
} else if (frame &&
|
||||
(frame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE ||
|
||||
(frame->GetStateBits() & NS_FRAME_REPLACED_ELEMENT))) {
|
||||
(frame->IsFrameOfType(nsIFrame::eReplaced)))) {
|
||||
// Special case code to make clientWidth work even when there isn't
|
||||
// a scroll view, see bug 180552 and bug 227567.
|
||||
|
||||
|
@ -463,10 +463,11 @@ nsBidiPresUtils::Resolve(nsPresContext* aPresContext,
|
||||
PRBool IsBidiLeaf(nsIFrame* aFrame) {
|
||||
nsIAtom* frameType = aFrame->GetType();
|
||||
nsIFrame* kid = aFrame->GetFirstChild(nsnull);
|
||||
// Need the IsBlockLevel() check because nsFirstLetterFrame is
|
||||
// always of type eBidiInlineContainer, even if it's floating.
|
||||
return !kid
|
||||
|| aFrame->GetStyleDisplay()->IsBlockLevel()
|
||||
|| !(aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer)
|
||||
|| nsLayoutAtoms::blockFrame == frameType);
|
||||
|| !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer)
|
||||
|| aFrame->GetStyleDisplay()->IsBlockLevel();
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -5103,6 +5103,7 @@ nsCSSFrameConstructor::ConstructButtonFrame(nsFrameConstructorState& aState,
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsCSSFrameConstructor::ConstructSelectFrame(nsFrameConstructorState& aState,
|
||||
nsIContent* aContent,
|
||||
@ -5487,10 +5488,6 @@ nsCSSFrameConstructor::ConstructTextFrame(nsFrameConstructorState& aState,
|
||||
if (NS_UNLIKELY(!newFrame))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Set the frame state bit for text frames to mark them as replaced.
|
||||
// XXX kipp: temporary
|
||||
newFrame->AddStateBits(NS_FRAME_REPLACED_ELEMENT);
|
||||
|
||||
nsresult rv = InitAndRestoreFrame(aState, aContent, aParentFrame,
|
||||
nsnull, newFrame);
|
||||
|
||||
@ -5532,7 +5529,6 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
|
||||
PRBool frameHasBeenInitialized = PR_FALSE;
|
||||
nsIFrame* newFrame = nsnull; // the frame we construct
|
||||
PRBool isReplaced = PR_FALSE;
|
||||
PRBool addToHashTable = PR_TRUE;
|
||||
PRBool isFloatContainer = PR_FALSE;
|
||||
PRBool addedToFrameList = PR_FALSE;
|
||||
@ -5546,7 +5542,6 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
// Create a frame based on the tag
|
||||
if (nsHTMLAtoms::img == aTag) {
|
||||
// Make sure to keep IsSpecialContent in synch with this code
|
||||
isReplaced = PR_TRUE;
|
||||
rv = CreateHTMLImageFrame(aContent, aStyleContext, NS_NewImageFrame,
|
||||
&newFrame);
|
||||
if (newFrame) {
|
||||
@ -5562,7 +5557,6 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
newFrame = NS_NewBRFrame(mPresShell, aStyleContext);
|
||||
triedFrame = PR_TRUE;
|
||||
|
||||
isReplaced = PR_TRUE;
|
||||
// BR frames don't go in the content->frame hash table: typically
|
||||
// there are many BR content objects and this would increase the size
|
||||
// of the hash table, and it's doubtful we need the mapping anyway
|
||||
@ -5584,13 +5578,11 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
aTag, aStyleContext, &newFrame,
|
||||
display, frameHasBeenInitialized,
|
||||
addedToFrameList, aFrameItems);
|
||||
isReplaced = PR_TRUE;
|
||||
}
|
||||
else if (nsHTMLAtoms::textarea == aTag) {
|
||||
if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
|
||||
ProcessPseudoFrames(aState, aFrameItems);
|
||||
}
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewTextControlFrame(mPresShell, aStyleContext);
|
||||
triedFrame = PR_TRUE;
|
||||
}
|
||||
@ -5599,15 +5591,16 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
|
||||
ProcessPseudoFrames(aState, aFrameItems);
|
||||
}
|
||||
isReplaced = PR_TRUE;
|
||||
rv = ConstructSelectFrame(aState, aContent, aParentFrame,
|
||||
aTag, aStyleContext, newFrame,
|
||||
display, frameHasBeenInitialized,
|
||||
aFrameItems);
|
||||
NS_ASSERTION(nsPlaceholderFrame::GetRealFrameFor(aFrameItems.lastChild) ==
|
||||
newFrame,
|
||||
"Frame didn't get added to aFrameItems?");
|
||||
addedToFrameList = PR_TRUE;
|
||||
if (newFrame) {
|
||||
NS_ASSERTION(nsPlaceholderFrame::GetRealFrameFor(aFrameItems.lastChild) ==
|
||||
newFrame,
|
||||
"Frame didn't get added to aFrameItems?");
|
||||
addedToFrameList = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (nsHTMLAtoms::object == aTag ||
|
||||
@ -5620,7 +5613,6 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
|
||||
ProcessPseudoFrames(aState, aFrameItems);
|
||||
}
|
||||
isReplaced = PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIObjectLoadingContent> objContent(do_QueryInterface(aContent));
|
||||
NS_ASSERTION(objContent,
|
||||
@ -5634,6 +5626,8 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
objContent->GetDisplayedType(&type);
|
||||
if (type == nsIObjectLoadingContent::TYPE_LOADING) {
|
||||
// Ideally, this should show the standby attribute
|
||||
// XXX Should we return something that is replaced, or make
|
||||
// nsFrame replaced but not its subclasses?
|
||||
newFrame = NS_NewEmptyFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
else if (type == nsIObjectLoadingContent::TYPE_PLUGIN)
|
||||
@ -5691,7 +5685,6 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
ProcessPseudoFrames(aState, aFrameItems);
|
||||
}
|
||||
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewSubDocumentFrame(mPresShell, aStyleContext);
|
||||
triedFrame = PR_TRUE;
|
||||
|
||||
@ -5727,7 +5720,6 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
// so it must be replaced or html outside it will
|
||||
// draw into its borders. -EDV
|
||||
frameHasBeenInitialized = PR_TRUE;
|
||||
isReplaced = PR_TRUE;
|
||||
addedToFrameList = PR_TRUE;
|
||||
isFloatContainer = PR_TRUE;
|
||||
}
|
||||
@ -5735,7 +5727,6 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
|
||||
ProcessPseudoFrames(aState, aFrameItems);
|
||||
}
|
||||
isReplaced = PR_FALSE;
|
||||
newFrame = NS_NewIsIndexFrame(mPresShell, aStyleContext);
|
||||
triedFrame = PR_TRUE;
|
||||
}
|
||||
@ -5743,7 +5734,6 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
if (!aHasPseudoParent && !aState.mPseudoFrames.IsEmpty()) {
|
||||
ProcessPseudoFrames(aState, aFrameItems);
|
||||
}
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewHTMLCanvasFrame(mPresShell, aStyleContext);
|
||||
triedFrame = PR_TRUE;
|
||||
}
|
||||
@ -5758,11 +5748,6 @@ nsCSSFrameConstructor::ConstructHTMLFrame(nsFrameConstructorState& aState,
|
||||
// If we succeeded in creating a frame then initialize it, process its
|
||||
// children (if requested), and set the initial child list
|
||||
|
||||
// If the frame is a replaced element, then set the frame state bit
|
||||
if (isReplaced) {
|
||||
newFrame->AddStateBits(NS_FRAME_REPLACED_ELEMENT);
|
||||
}
|
||||
|
||||
// Note: at this point we should construct kids for newFrame only if
|
||||
// it's not a leaf and hasn't been initialized yet.
|
||||
|
||||
@ -6030,7 +6015,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
PRBool primaryFrameSet = PR_FALSE;
|
||||
nsresult rv = NS_OK;
|
||||
PRBool isPopup = PR_FALSE;
|
||||
PRBool isReplaced = PR_FALSE;
|
||||
PRBool frameHasBeenInitialized = PR_FALSE;
|
||||
|
||||
// XXXbz somewhere here we should process pseudo frames if !aHasPseudoParent
|
||||
@ -6073,7 +6057,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
#ifdef MOZ_XUL
|
||||
// BUTTON CONSTRUCTION
|
||||
if (aTag == nsXULAtoms::button || aTag == nsXULAtoms::checkbox || aTag == nsXULAtoms::radio) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewButtonBoxFrame(mPresShell, aStyleContext);
|
||||
|
||||
// Boxes can scroll.
|
||||
@ -6081,7 +6064,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
} // End of BUTTON CONSTRUCTION logic
|
||||
// AUTOREPEATBUTTON CONSTRUCTION
|
||||
else if (aTag == nsXULAtoms::autorepeatbutton) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewAutoRepeatBoxFrame(mPresShell, aStyleContext);
|
||||
|
||||
// Boxes can scroll.
|
||||
@ -6090,7 +6072,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
|
||||
// TITLEBAR CONSTRUCTION
|
||||
else if (aTag == nsXULAtoms::titlebar) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewTitleBarFrame(mPresShell, aStyleContext);
|
||||
|
||||
// Boxes can scroll.
|
||||
@ -6099,7 +6080,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
|
||||
// RESIZER CONSTRUCTION
|
||||
else if (aTag == nsXULAtoms::resizer) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewResizerFrame(mPresShell, aStyleContext);
|
||||
|
||||
// Boxes can scroll.
|
||||
@ -6107,20 +6087,16 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
} // End of RESIZER CONSTRUCTION logic
|
||||
|
||||
else if (aTag == nsXULAtoms::image) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewImageBoxFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
else if (aTag == nsXULAtoms::spring ||
|
||||
aTag == nsHTMLAtoms::spacer) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewLeafBoxFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
else if (aTag == nsXULAtoms::treechildren) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewTreeBodyFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
else if (aTag == nsXULAtoms::treecol) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewTreeColFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
// TEXT CONSTRUCTION
|
||||
@ -6132,7 +6108,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
NS_BLOCK_SPACE_MGR | NS_BLOCK_SHRINK_WRAP | NS_BLOCK_MARGIN_ROOT);
|
||||
}
|
||||
else {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewTextBoxFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
}
|
||||
@ -6145,7 +6120,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
// A derived class box frame
|
||||
// that has custom reflow to prevent menu children
|
||||
// from becoming part of the flow.
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewMenuFrame(mPresShell, aStyleContext,
|
||||
(aTag != nsXULAtoms::menuitem));
|
||||
}
|
||||
@ -6179,17 +6153,14 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
}
|
||||
else if (aTag == nsXULAtoms::popupgroup) {
|
||||
// This frame contains child popups
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewPopupSetFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
else if (aTag == nsXULAtoms::iframe || aTag == nsXULAtoms::editor ||
|
||||
aTag == nsXULAtoms::browser) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewSubDocumentFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
// PROGRESS METER CONSTRUCTION
|
||||
else if (aTag == nsXULAtoms::progressmeter) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewProgressMeterFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
// End of PROGRESS METER CONSTRUCTION logic
|
||||
@ -6197,25 +6168,21 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
#endif
|
||||
// SLIDER CONSTRUCTION
|
||||
if (aTag == nsXULAtoms::slider) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewSliderFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
// End of SLIDER CONSTRUCTION logic
|
||||
|
||||
// SCROLLBAR CONSTRUCTION
|
||||
else if (aTag == nsXULAtoms::scrollbar) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewScrollbarFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
else if (aTag == nsXULAtoms::nativescrollbar) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewNativeScrollbarFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
// End of SCROLLBAR CONSTRUCTION logic
|
||||
|
||||
// SCROLLBUTTON CONSTRUCTION
|
||||
else if (aTag == nsXULAtoms::scrollbarbutton) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewScrollbarButtonFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
// End of SCROLLBUTTON CONSTRUCTION logic
|
||||
@ -6223,7 +6190,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
#ifdef MOZ_XUL
|
||||
// SPLITTER CONSTRUCTION
|
||||
else if (aTag == nsXULAtoms::splitter) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewSplitterFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
// End of SPLITTER CONSTRUCTION logic
|
||||
@ -6242,8 +6208,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
|
||||
if (display->mDisplay == NS_STYLE_DISPLAY_INLINE_BOX ||
|
||||
display->mDisplay == NS_STYLE_DISPLAY_BOX) {
|
||||
isReplaced = PR_TRUE;
|
||||
|
||||
newFrame = NS_NewBoxFrame(mPresShell, aStyleContext, PR_FALSE, nsnull);
|
||||
|
||||
// Boxes can scroll.
|
||||
@ -6253,7 +6217,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
// ------- Begin Grid ---------
|
||||
else if (display->mDisplay == NS_STYLE_DISPLAY_INLINE_GRID ||
|
||||
display->mDisplay == NS_STYLE_DISPLAY_GRID) {
|
||||
isReplaced = PR_TRUE;
|
||||
nsCOMPtr<nsIBoxLayout> layout;
|
||||
NS_NewGridLayout2(mPresShell, getter_AddRefs(layout));
|
||||
newFrame = NS_NewBoxFrame(mPresShell, aStyleContext, PR_FALSE, layout);
|
||||
@ -6264,8 +6227,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
|
||||
// ------- Begin Rows/Columns ---------
|
||||
else if (display->mDisplay == NS_STYLE_DISPLAY_GRID_GROUP) {
|
||||
isReplaced = PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIBoxLayout> layout;
|
||||
|
||||
if (aTag == nsXULAtoms::listboxbody) {
|
||||
@ -6295,8 +6256,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
|
||||
// ------- Begin Row/Column ---------
|
||||
else if (display->mDisplay == NS_STYLE_DISPLAY_GRID_LINE) {
|
||||
isReplaced = PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIBoxLayout> layout;
|
||||
|
||||
|
||||
@ -6313,13 +6272,11 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
// End of STACK CONSTRUCTION logic
|
||||
// DECK CONSTRUCTION
|
||||
else if (display->mDisplay == NS_STYLE_DISPLAY_DECK) {
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewDeckFrame(mPresShell, aStyleContext);
|
||||
}
|
||||
// End of DECK CONSTRUCTION logic
|
||||
else if (display->mDisplay == NS_STYLE_DISPLAY_GROUPBOX) {
|
||||
newFrame = NS_NewGroupBoxFrame(mPresShell, aStyleContext);
|
||||
isReplaced = PR_TRUE;
|
||||
|
||||
// Boxes can scroll.
|
||||
mayBeScrollable = PR_TRUE;
|
||||
@ -6327,8 +6284,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
// STACK CONSTRUCTION
|
||||
else if (display->mDisplay == NS_STYLE_DISPLAY_STACK ||
|
||||
display->mDisplay == NS_STYLE_DISPLAY_INLINE_STACK) {
|
||||
isReplaced = PR_TRUE;
|
||||
|
||||
newFrame = NS_NewStackFrame(mPresShell, aStyleContext);
|
||||
|
||||
mayBeScrollable = PR_TRUE;
|
||||
@ -6359,7 +6314,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
}
|
||||
|
||||
// This is its own frame that derives from box.
|
||||
isReplaced = PR_TRUE;
|
||||
newFrame = NS_NewMenuPopupFrame(mPresShell, aStyleContext);
|
||||
|
||||
if (aTag == nsXULAtoms::tooltip) {
|
||||
@ -6406,11 +6360,6 @@ nsCSSFrameConstructor::ConstructXULFrame(nsFrameConstructorState& aState,
|
||||
if (topFrame == nsnull)
|
||||
topFrame = newFrame;
|
||||
|
||||
// If the frame is a replaced element, then set the frame state bit
|
||||
if (isReplaced) {
|
||||
newFrame->AddStateBits(NS_FRAME_REPLACED_ELEMENT);
|
||||
}
|
||||
|
||||
// xul does not support absolute positioning
|
||||
nsIFrame* geometricParent;
|
||||
#ifdef MOZ_XUL
|
||||
@ -7074,7 +7023,6 @@ nsCSSFrameConstructor::ConstructMathMLFrame(nsFrameConstructorState& aState,
|
||||
return NS_OK;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
PRBool isReplaced = PR_FALSE;
|
||||
PRBool ignoreInterTagWhitespace = PR_TRUE;
|
||||
|
||||
NS_ASSERTION(aTag != nsnull, "null MathML tag");
|
||||
@ -7226,10 +7174,6 @@ nsCSSFrameConstructor::ConstructMathMLFrame(nsFrameConstructorState& aState,
|
||||
// If we succeeded in creating a frame then initialize it, process its
|
||||
// children (if requested), and set the initial child list
|
||||
if (newFrame) {
|
||||
// If the frame is a replaced element, then set the frame state bit
|
||||
if (isReplaced) {
|
||||
newFrame->AddStateBits(NS_FRAME_REPLACED_ELEMENT);
|
||||
}
|
||||
// record that children that are ignorable whitespace should be excluded
|
||||
if (ignoreInterTagWhitespace) {
|
||||
newFrame->AddStateBits(NS_FRAME_EXCLUDE_IGNORABLE_WHITESPACE);
|
||||
@ -10158,22 +10102,15 @@ nsCSSFrameConstructor::StyleChangeReflow(nsIFrame* aFrame,
|
||||
}
|
||||
#endif
|
||||
|
||||
// Is it a box? If so we can coelesce.
|
||||
if (aFrame->IsBoxFrame()) {
|
||||
nsBoxLayoutState state(mPresShell->GetPresContext());
|
||||
aFrame->MarkStyleChange(state);
|
||||
}
|
||||
else {
|
||||
// If the frame is part of a split block-in-inline hierarchy, then
|
||||
// target the style-change reflow at the first ``normal'' ancestor
|
||||
// so we're sure that the style change will propagate to any
|
||||
// anonymously created siblings.
|
||||
if (IsFrameSpecial(aFrame))
|
||||
aFrame = GetIBContainingBlockFor(aFrame);
|
||||
// If the frame is part of a split block-in-inline hierarchy, then
|
||||
// target the style-change reflow at the first ``normal'' ancestor
|
||||
// so we're sure that the style change will propagate to any
|
||||
// anonymously created siblings.
|
||||
if (IsFrameSpecial(aFrame))
|
||||
aFrame = GetIBContainingBlockFor(aFrame);
|
||||
|
||||
// Target a style-change reflow at the frame.
|
||||
mPresShell->AppendReflowCommand(aFrame, eReflowType_StyleChanged, nsnull);
|
||||
}
|
||||
aFrame->AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
mPresShell->FrameNeedsReflow(aFrame, nsIPresShell::eStyleChange);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -57,7 +57,6 @@ struct nsFrameItems;
|
||||
struct nsAbsoluteItems;
|
||||
struct nsTableCreator;
|
||||
class nsStyleContext;
|
||||
struct nsTableList;
|
||||
struct nsStyleContent;
|
||||
struct nsStyleDisplay;
|
||||
class nsIPresShell;
|
||||
|
@ -3136,9 +3136,20 @@ NS_IMETHODIMP DocumentViewerImpl::SizeToContent()
|
||||
// Flush out all content and style updates. We can't use a resize reflow
|
||||
// because it won't change some sizes that a style change reflow will.
|
||||
mDocument->FlushPendingNotifications(Flush_Layout);
|
||||
|
||||
NS_ENSURE_SUCCESS(presShell->ResizeReflow(NS_UNCONSTRAINEDSIZE,
|
||||
NS_UNCONSTRAINEDSIZE), NS_ERROR_FAILURE);
|
||||
|
||||
nsIFrame *root = presShell->GetRootFrame();
|
||||
NS_ENSURE_TRUE(root, NS_ERROR_FAILURE);
|
||||
|
||||
nscoord prefWidth;
|
||||
{
|
||||
nsCOMPtr<nsIRenderingContext> rcx;
|
||||
presShell->CreateRenderingContext(root, getter_AddRefs(rcx));
|
||||
NS_ENSURE_TRUE(rcx, NS_ERROR_FAILURE);
|
||||
prefWidth = root->GetPrefWidth(rcx);
|
||||
}
|
||||
|
||||
nsresult rv = presShell->ResizeReflow(prefWidth, NS_UNCONSTRAINEDSIZE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsPresContext> presContext;
|
||||
GetPresContext(getter_AddRefs(presContext));
|
||||
|
@ -701,6 +701,12 @@ nsFrameManager::RemoveFrame(nsIFrame* aParentFrame,
|
||||
nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame)
|
||||
{
|
||||
// In case the reflow doesn't invalidate anything since it just leaves
|
||||
// a gap where the old frame was, we invalidate it here. (This is
|
||||
// reasonably likely to happen when removing a last child in a way
|
||||
// that doesn't change the size of the parent.)
|
||||
aOldFrame->Invalidate(nsRect(nsPoint(0, 0), aOldFrame->GetSize()));
|
||||
|
||||
return aParentFrame->RemoveFrame(aListName, aOldFrame);
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,6 @@
|
||||
#include "nsRect.h"
|
||||
#include "nsColor.h"
|
||||
#include "nsEvent.h"
|
||||
#include "nsReflowType.h"
|
||||
#include "nsCompatibility.h"
|
||||
#include "nsFrameManagerBase.h"
|
||||
#include "mozFlushType.h"
|
||||
@ -98,10 +97,10 @@ class nsWeakFrame;
|
||||
|
||||
typedef short SelectionType;
|
||||
|
||||
// 845BA869-F93B-4026-8F42-CB058F0E4D87
|
||||
// b6cf677a-aa50-47c2-b381-5a82e7e792da
|
||||
#define NS_IPRESSHELL_IID \
|
||||
{ 0x845BA869, 0xF93B, 0x4026, \
|
||||
{ 0x8F, 0x42, 0xCB, 0x05, 0x8F, 0x0E, 0x4D, 0x87 } }
|
||||
{ 0xb6cf677a, 0xaa50, 0x47c2, \
|
||||
{ 0xb3, 0x81, 0x5a, 0x82, 0xe7, 0xe7, 0x92, 0xda } }
|
||||
|
||||
// Constants uses for ScrollFrameIntoView() function
|
||||
#define NS_PRESSHELL_SCROLL_TOP 0
|
||||
@ -338,14 +337,21 @@ public:
|
||||
nsIFrame** aPlaceholderFrame) const = 0;
|
||||
|
||||
/**
|
||||
* Reflow commands
|
||||
* Tell the pres shell that a frame is dirty (as indicated by bits)
|
||||
* and needs Reflow. It's OK if this is an ancestor of the frame needing
|
||||
* reflow as long as the ancestor chain between them doesn't cross a reflow
|
||||
* root.
|
||||
*/
|
||||
NS_IMETHOD AppendReflowCommand(nsIFrame* aTargetFrame,
|
||||
nsReflowType aReflowType,
|
||||
nsIAtom* aChildListName) = 0;
|
||||
// XXXbz don't we need a child list name on this too?
|
||||
NS_IMETHOD CancelReflowCommand(nsIFrame* aTargetFrame, nsReflowType* aCmdType) = 0;
|
||||
NS_IMETHOD CancelAllReflowCommands() = 0;
|
||||
enum IntrinsicDirty {
|
||||
// XXXldb eResize should be renamed
|
||||
eResize, // don't mark any intrinsic widths dirty
|
||||
eTreeChange, // mark intrinsic widths dirty on aFrame and its ancestors
|
||||
eStyleChange // Do eTreeChange, plus all of aFrame's descendants
|
||||
};
|
||||
NS_IMETHOD FrameNeedsReflow(nsIFrame *aFrame,
|
||||
IntrinsicDirty aIntrinsicDirty) = 0;
|
||||
|
||||
NS_IMETHOD CancelAllPendingReflows() = 0;
|
||||
|
||||
/**
|
||||
* Recreates the frames for a node
|
||||
@ -652,7 +658,7 @@ public:
|
||||
|
||||
#ifdef MOZ_REFLOW_PERF
|
||||
NS_IMETHOD DumpReflows() = 0;
|
||||
NS_IMETHOD CountReflows(const char * aName, PRUint32 aType, nsIFrame * aFrame) = 0;
|
||||
NS_IMETHOD CountReflows(const char * aName, nsIFrame * aFrame) = 0;
|
||||
NS_IMETHOD PaintCount(const char * aName,
|
||||
nsIRenderingContext* aRenderingContext,
|
||||
nsPresContext * aPresContext,
|
||||
|
@ -21,6 +21,7 @@
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -1085,3 +1086,453 @@ nsLayoutUtils::IsViewportScrollbarFrame(nsIFrame* aFrame)
|
||||
return !(rootScrolledFrame == aFrame ||
|
||||
IsProperAncestorFrame(rootScrolledFrame, aFrame));
|
||||
}
|
||||
|
||||
static nscoord AddPercents(nsLayoutUtils::IntrinsicWidthType aType,
|
||||
nscoord aCurrent, float aPercent)
|
||||
{
|
||||
nscoord result = aCurrent;
|
||||
if (aPercent > 0.0f && aType == nsLayoutUtils::PREF_WIDTH) {
|
||||
// XXX Should we also consider percentages for min widths, up to a
|
||||
// limit?
|
||||
if (aPercent >= 1.0f)
|
||||
result = nscoord_MAX;
|
||||
else
|
||||
result = NSToCoordRound(float(result) / (1.0f - aPercent));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#undef DEBUG_INTRINSIC_WIDTH
|
||||
|
||||
#ifdef DEBUG_INTRINSIC_WIDTH
|
||||
static PRInt32 gNoiseIndent = 0;
|
||||
#endif
|
||||
|
||||
/* static */ nscoord
|
||||
nsLayoutUtils::IntrinsicForContainer(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame *aFrame,
|
||||
IntrinsicWidthType aType)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "null frame");
|
||||
NS_PRECONDITION(aType == MIN_WIDTH || aType == PREF_WIDTH, "bad type");
|
||||
|
||||
#ifdef DEBUG_INTRINSIC_WIDTH
|
||||
nsFrame::IndentBy(stdout, gNoiseIndent);
|
||||
NS_STATIC_CAST(nsFrame*, aFrame)->ListTag(stdout);
|
||||
printf(" %s intrinsic width for container:\n",
|
||||
aType == MIN_WIDTH ? "min" : "pref");
|
||||
#endif
|
||||
|
||||
nsIFrame::IntrinsicWidthOffsetData offsets = aFrame->IntrinsicWidthOffsets();
|
||||
|
||||
const nsStylePosition *stylePos = aFrame->GetStylePosition();
|
||||
const PRUint8 boxSizing = stylePos->mBoxSizing;
|
||||
const nsStyleCoord &styleWidth = stylePos->mWidth;
|
||||
const nsStyleCoord &styleMinWidth = stylePos->mMinWidth;
|
||||
const nsStyleCoord &styleMaxWidth = stylePos->mMaxWidth;
|
||||
|
||||
// We build up two values starting with the content box, and then
|
||||
// adding padding, border and margin. The result is normally
|
||||
// |result|. Then, when we handle 'width', 'min-width', and
|
||||
// 'max-width', we use the results we've been building in |min| as a
|
||||
// minimum, overriding 'min-width'. This ensures two things:
|
||||
// * that we don't let a value of 'box-sizing' specifying a width
|
||||
// smaller than the padding/border inside the box-sizing box give
|
||||
// a content width less than zero
|
||||
// * that we prevent tables from becoming smaller than their
|
||||
// intrinsic minimum width
|
||||
nscoord result = 0, min = 0;
|
||||
|
||||
// If we have a specified width (or a specified 'min-width' greater
|
||||
// than the specified 'max-width', which works out to the same thing),
|
||||
// don't even bother getting the frame's intrinsic width.
|
||||
if (styleWidth.GetUnit() != eStyleUnit_Coord &&
|
||||
(styleMinWidth.GetUnit() != eStyleUnit_Coord ||
|
||||
styleMaxWidth.GetUnit() != eStyleUnit_Coord ||
|
||||
styleMaxWidth.GetCoordValue() > styleMinWidth.GetCoordValue())) {
|
||||
#ifdef DEBUG_INTRINSIC_WIDTH
|
||||
++gNoiseIndent;
|
||||
#endif
|
||||
if (aType == MIN_WIDTH)
|
||||
result = aFrame->GetMinWidth(aRenderingContext);
|
||||
else
|
||||
result = aFrame->GetPrefWidth(aRenderingContext);
|
||||
#ifdef DEBUG_INTRINSIC_WIDTH
|
||||
--gNoiseIndent;
|
||||
nsFrame::IndentBy(stdout, gNoiseIndent);
|
||||
NS_STATIC_CAST(nsFrame*, aFrame)->ListTag(stdout);
|
||||
printf(" %s intrinsic width from frame is %d.\n",
|
||||
aType == MIN_WIDTH ? "min" : "pref", result);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (aFrame->GetType() == nsLayoutAtoms::tableFrame) {
|
||||
// Tables can't shrink smaller than their intrinsic minimum width,
|
||||
// no matter what.
|
||||
min = aFrame->GetMinWidth(aRenderingContext);
|
||||
}
|
||||
|
||||
// We also need to track what has been added on outside of the box
|
||||
// (controlled by 'box-sizing') where 'width', 'min-width' and
|
||||
// 'max-width' are applied. We have to account for these properties
|
||||
// after getting all the offsets (margin, border, padding) because
|
||||
// percentages do not operate linearly.
|
||||
// Doing this is ok because although percentages aren't handled
|
||||
// linearly, they are handled monotonically.
|
||||
nscoord coordOutsideWidth = offsets.hPadding;
|
||||
float pctOutsideWidth = offsets.hPctPadding;
|
||||
|
||||
float pctTotal = 0.0f;
|
||||
|
||||
if (boxSizing == NS_STYLE_BOX_SIZING_PADDING) {
|
||||
min += coordOutsideWidth;
|
||||
result += coordOutsideWidth;
|
||||
pctTotal += pctOutsideWidth;
|
||||
|
||||
coordOutsideWidth = 0;
|
||||
pctOutsideWidth = 0.0f;
|
||||
}
|
||||
|
||||
coordOutsideWidth += offsets.hBorder;
|
||||
|
||||
if (boxSizing == NS_STYLE_BOX_SIZING_BORDER) {
|
||||
min += coordOutsideWidth;
|
||||
result += coordOutsideWidth;
|
||||
pctTotal += pctOutsideWidth;
|
||||
|
||||
coordOutsideWidth = 0;
|
||||
pctOutsideWidth = 0.0f;
|
||||
}
|
||||
|
||||
coordOutsideWidth += offsets.hMargin;
|
||||
pctOutsideWidth += offsets.hPctMargin;
|
||||
|
||||
min += coordOutsideWidth;
|
||||
result += coordOutsideWidth;
|
||||
pctTotal += pctOutsideWidth;
|
||||
|
||||
result = AddPercents(aType, result, pctTotal);
|
||||
|
||||
switch (styleWidth.GetUnit()) {
|
||||
case eStyleUnit_Coord:
|
||||
result = AddPercents(aType,
|
||||
styleWidth.GetCoordValue() + coordOutsideWidth,
|
||||
pctOutsideWidth);
|
||||
break;
|
||||
case eStyleUnit_Percent:
|
||||
if (aType == MIN_WIDTH && aFrame->IsFrameOfType(nsIFrame::eReplaced)) {
|
||||
// A percentage width on replaced elements means they can shrink to 0.
|
||||
result = 0; // let |min| handle padding/border/margin
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (styleMaxWidth.GetUnit() == eStyleUnit_Coord) {
|
||||
nscoord maxw = AddPercents(aType,
|
||||
styleMaxWidth.GetCoordValue() + coordOutsideWidth, pctOutsideWidth);
|
||||
if (result > maxw)
|
||||
result = maxw;
|
||||
}
|
||||
|
||||
if (styleMinWidth.GetUnit() == eStyleUnit_Coord) {
|
||||
nscoord minw = AddPercents(aType,
|
||||
styleMinWidth.GetCoordValue() + coordOutsideWidth, pctOutsideWidth);
|
||||
if (result < minw)
|
||||
result = minw;
|
||||
}
|
||||
|
||||
min = AddPercents(aType, min, pctTotal);
|
||||
if (result < min)
|
||||
result = min;
|
||||
|
||||
#ifdef DEBUG_INTRINSIC_WIDTH
|
||||
nsFrame::IndentBy(stdout, gNoiseIndent);
|
||||
NS_STATIC_CAST(nsFrame*, aFrame)->ListTag(stdout);
|
||||
printf(" %s intrinsic width for container is %d twips.\n",
|
||||
aType == MIN_WIDTH ? "min" : "pref", result);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* static */ nscoord
|
||||
nsLayoutUtils::ComputeHorizontalValue(nsIRenderingContext* aRenderingContext,
|
||||
nsIFrame* aFrame,
|
||||
nscoord aContainingBlockWidth,
|
||||
const nsStyleCoord& aCoord)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "non-null frame expected");
|
||||
NS_PRECONDITION(aRenderingContext, "non-null rendering context expected");
|
||||
NS_PRECONDITION(aContainingBlockWidth != NS_UNCONSTRAINEDSIZE,
|
||||
"unconstrained widths no longer supported");
|
||||
|
||||
nscoord result = 0;
|
||||
nsStyleUnit unit = aCoord.GetUnit();
|
||||
if (eStyleUnit_Percent == unit) {
|
||||
result = NSToCoordFloor(aContainingBlockWidth * aCoord.GetPercentValue());
|
||||
} else if (eStyleUnit_Coord == unit) {
|
||||
result = aCoord.GetCoordValue();
|
||||
}
|
||||
else if (eStyleUnit_Chars == unit) {
|
||||
SetFontFromStyle(aRenderingContext, aFrame->GetStyleContext());
|
||||
nscoord fontWidth;
|
||||
aRenderingContext->GetWidth('M', fontWidth);
|
||||
result = aCoord.GetIntValue() * fontWidth;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* static */ nscoord
|
||||
nsLayoutUtils::ComputeVerticalValue(nsIRenderingContext* aRenderingContext,
|
||||
nsIFrame* aFrame,
|
||||
nscoord aContainingBlockHeight,
|
||||
const nsStyleCoord& aCoord)
|
||||
{
|
||||
NS_PRECONDITION(aFrame, "non-null frame expected");
|
||||
NS_PRECONDITION(aRenderingContext, "non-null rendering context expected");
|
||||
nscoord result = 0;
|
||||
nsStyleUnit unit = aCoord.GetUnit();
|
||||
if (eStyleUnit_Percent == unit) {
|
||||
// XXXldb Some callers explicitly check aContainingBlockHeight
|
||||
// against NS_AUTOHEIGHT *and* unit against eStyleUnit_Percent
|
||||
// before calling this function, so this assertion probably needs to
|
||||
// be inside the percentage case. However, it would be much more
|
||||
// likely to catch problems if it were at the start of the function.
|
||||
// XXXldb Many callers pass a non-'auto' containing block height when
|
||||
// according to CSS2.1 they should be passing 'auto'.
|
||||
NS_PRECONDITION(NS_AUTOHEIGHT != aContainingBlockHeight,
|
||||
"unexpected 'containing block height'");
|
||||
|
||||
if (NS_AUTOHEIGHT != aContainingBlockHeight) {
|
||||
result =
|
||||
NSToCoordFloor(aContainingBlockHeight * aCoord.GetPercentValue());
|
||||
}
|
||||
} else if (eStyleUnit_Coord == unit) {
|
||||
result = aCoord.GetCoordValue();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline PRBool
|
||||
IsAutoHeight(const nsStyleCoord &aCoord, nscoord aCBHeight)
|
||||
{
|
||||
nsStyleUnit unit = aCoord.GetUnit();
|
||||
return unit == eStyleUnit_Auto || // only for 'height'
|
||||
unit == eStyleUnit_Null || // only for 'max-height'
|
||||
(unit == eStyleUnit_Percent &&
|
||||
aCBHeight == NS_AUTOHEIGHT);
|
||||
}
|
||||
|
||||
|
||||
/* static */ nsSize
|
||||
nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
|
||||
nsIRenderingContext* aRenderingContext,
|
||||
nsIFrame* aFrame, nsSize aIntrinsicSize, nsSize aCBSize,
|
||||
nsSize aBorder, nsSize aPadding)
|
||||
{
|
||||
const nsStylePosition *stylePos = aFrame->GetStylePosition();
|
||||
// Handle intrinsic sizes and their interaction with
|
||||
// {min-,max-,}{width,height} according to the rules in
|
||||
// http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
|
||||
|
||||
// Note: throughout the following section of the function, I avoid
|
||||
// a * (b / c) because of its reduced accuracy relative to a * b / c
|
||||
// or (a * b) / c (which are equivalent).
|
||||
|
||||
PRBool isAutoWidth = stylePos->mWidth.GetUnit() == eStyleUnit_Auto;
|
||||
PRBool isAutoHeight = IsAutoHeight(stylePos->mHeight, aCBSize.height);
|
||||
|
||||
nsSize boxSizingAdjust(0,0);
|
||||
switch (stylePos->mBoxSizing) {
|
||||
case NS_STYLE_BOX_SIZING_BORDER:
|
||||
boxSizingAdjust += aBorder;
|
||||
// fall through
|
||||
case NS_STYLE_BOX_SIZING_PADDING:
|
||||
boxSizingAdjust += aPadding;
|
||||
}
|
||||
|
||||
nscoord width, minWidth, maxWidth, height, minHeight, maxHeight;
|
||||
|
||||
if (!isAutoWidth) {
|
||||
width = nsLayoutUtils::ComputeHorizontalValue(aRenderingContext,
|
||||
aFrame, aCBSize.width, stylePos->mWidth) -
|
||||
boxSizingAdjust.width;
|
||||
if (width < 0)
|
||||
width = 0;
|
||||
}
|
||||
|
||||
if (stylePos->mMaxWidth.GetUnit() != eStyleUnit_Null) {
|
||||
maxWidth = nsLayoutUtils::ComputeHorizontalValue(aRenderingContext,
|
||||
aFrame, aCBSize.width, stylePos->mMaxWidth) -
|
||||
boxSizingAdjust.width;
|
||||
if (maxWidth < 0)
|
||||
maxWidth = 0;
|
||||
} else {
|
||||
maxWidth = nscoord_MAX;
|
||||
}
|
||||
|
||||
minWidth = nsLayoutUtils::ComputeHorizontalValue(aRenderingContext,
|
||||
aFrame, aCBSize.width, stylePos->mMinWidth) -
|
||||
boxSizingAdjust.width;
|
||||
if (minWidth < 0)
|
||||
minWidth = 0;
|
||||
|
||||
if (!isAutoHeight) {
|
||||
height = nsLayoutUtils::ComputeVerticalValue(aRenderingContext,
|
||||
aFrame, aCBSize.height, stylePos->mHeight) -
|
||||
boxSizingAdjust.height;
|
||||
if (height < 0)
|
||||
height = 0;
|
||||
}
|
||||
|
||||
if (!IsAutoHeight(stylePos->mMaxHeight, aCBSize.height)) {
|
||||
maxHeight = nsLayoutUtils::ComputeVerticalValue(aRenderingContext,
|
||||
aFrame, aCBSize.height, stylePos->mMaxHeight) -
|
||||
boxSizingAdjust.height;
|
||||
if (maxHeight < 0)
|
||||
maxHeight = 0;
|
||||
} else {
|
||||
maxHeight = nscoord_MAX;
|
||||
}
|
||||
|
||||
if (!IsAutoHeight(stylePos->mMinHeight, aCBSize.height)) {
|
||||
minHeight = nsLayoutUtils::ComputeVerticalValue(aRenderingContext,
|
||||
aFrame, aCBSize.height, stylePos->mMinHeight) -
|
||||
boxSizingAdjust.height;
|
||||
if (minHeight < 0)
|
||||
minHeight = 0;
|
||||
} else {
|
||||
minHeight = 0;
|
||||
}
|
||||
|
||||
if (isAutoWidth) {
|
||||
if (isAutoHeight) {
|
||||
|
||||
// 'auto' width, 'auto' height
|
||||
if (minWidth > maxWidth)
|
||||
maxWidth = minWidth;
|
||||
if (minHeight > maxHeight)
|
||||
maxHeight = minHeight;
|
||||
|
||||
nscoord heightAtMaxWidth, heightAtMinWidth,
|
||||
widthAtMaxHeight, widthAtMinHeight;
|
||||
if (aIntrinsicSize.width > 0) {
|
||||
heightAtMaxWidth = maxWidth * aIntrinsicSize.height / aIntrinsicSize.width;
|
||||
if (heightAtMaxWidth < minHeight)
|
||||
heightAtMaxWidth = minHeight;
|
||||
heightAtMinWidth = minWidth * aIntrinsicSize.height / aIntrinsicSize.width;
|
||||
if (heightAtMinWidth > maxHeight)
|
||||
heightAtMinWidth = maxHeight;
|
||||
} else {
|
||||
heightAtMaxWidth = aIntrinsicSize.height;
|
||||
heightAtMinWidth = aIntrinsicSize.height;
|
||||
}
|
||||
|
||||
if (aIntrinsicSize.height > 0) {
|
||||
widthAtMaxHeight = maxHeight * aIntrinsicSize.width / aIntrinsicSize.height;
|
||||
if (widthAtMaxHeight < minWidth)
|
||||
widthAtMaxHeight = minWidth;
|
||||
widthAtMinHeight = minHeight * aIntrinsicSize.width / aIntrinsicSize.height;
|
||||
if (widthAtMinHeight > maxWidth)
|
||||
widthAtMinHeight = maxWidth;
|
||||
} else {
|
||||
widthAtMaxHeight = aIntrinsicSize.width;
|
||||
widthAtMinHeight = aIntrinsicSize.width;
|
||||
}
|
||||
|
||||
if (aIntrinsicSize.width > maxWidth) {
|
||||
if (aIntrinsicSize.height > maxHeight) {
|
||||
if (maxWidth * aIntrinsicSize.height <= maxHeight * aIntrinsicSize.width) {
|
||||
width = maxWidth;
|
||||
height = heightAtMaxWidth;
|
||||
} else {
|
||||
height = maxHeight;
|
||||
width = widthAtMaxHeight;
|
||||
}
|
||||
} else {
|
||||
width = maxWidth;
|
||||
height = heightAtMaxWidth;
|
||||
}
|
||||
} else if (aIntrinsicSize.width < minWidth) {
|
||||
if (aIntrinsicSize.height < minHeight) {
|
||||
if (minWidth * aIntrinsicSize.height <= minHeight * aIntrinsicSize.width) {
|
||||
height = minHeight;
|
||||
width = widthAtMinHeight;
|
||||
} else {
|
||||
width = minWidth;
|
||||
height = heightAtMinWidth;
|
||||
}
|
||||
} else {
|
||||
width = minWidth;
|
||||
height = heightAtMinWidth;
|
||||
}
|
||||
} else {
|
||||
if (aIntrinsicSize.height > maxHeight) {
|
||||
height = maxHeight;
|
||||
width = widthAtMaxHeight;
|
||||
} else if (aIntrinsicSize.height < minHeight) {
|
||||
height = minHeight;
|
||||
width = widthAtMinHeight;
|
||||
} else {
|
||||
width = aIntrinsicSize.width;
|
||||
height = aIntrinsicSize.height;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// 'auto' width, non-'auto' height
|
||||
height = NS_CSS_MINMAX(height, minHeight, maxHeight);
|
||||
if (aIntrinsicSize.height != 0) {
|
||||
width = aIntrinsicSize.width * height / aIntrinsicSize.height;
|
||||
} else {
|
||||
width = aIntrinsicSize.width;
|
||||
}
|
||||
width = NS_CSS_MINMAX(width, minWidth, maxWidth);
|
||||
|
||||
}
|
||||
} else {
|
||||
if (isAutoHeight) {
|
||||
|
||||
// non-'auto' width, 'auto' height
|
||||
width = NS_CSS_MINMAX(width, minWidth, maxWidth);
|
||||
if (aIntrinsicSize.width != 0) {
|
||||
height = aIntrinsicSize.height * width / aIntrinsicSize.width;
|
||||
} else {
|
||||
height = aIntrinsicSize.height;
|
||||
}
|
||||
height = NS_CSS_MINMAX(height, minHeight, maxHeight);
|
||||
|
||||
} else {
|
||||
|
||||
// non-'auto' width, non-'auto' height
|
||||
height = NS_CSS_MINMAX(height, minHeight, maxHeight);
|
||||
width = NS_CSS_MINMAX(width, minWidth, maxWidth);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nsSize(width, height);
|
||||
}
|
||||
|
||||
/* static */ nscoord
|
||||
nsLayoutUtils::MinWidthFromInline(nsIFrame *aFrame,
|
||||
nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nsIFrame::InlineMinWidthData data;
|
||||
DISPLAY_MIN_WIDTH(aFrame, data.prevLines);
|
||||
aFrame->AddInlineMinWidth(aRenderingContext, &data);
|
||||
data.Break(aRenderingContext);
|
||||
return data.prevLines;
|
||||
}
|
||||
|
||||
/* static */ nscoord
|
||||
nsLayoutUtils::PrefWidthFromInline(nsIFrame *aFrame,
|
||||
nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nsIFrame::InlinePrefWidthData data;
|
||||
DISPLAY_PREF_WIDTH(aFrame, data.prevLines);
|
||||
aFrame->AddInlinePrefWidth(aRenderingContext, &data);
|
||||
data.Break(aRenderingContext);
|
||||
return data.prevLines;
|
||||
}
|
||||
|
@ -461,6 +461,40 @@ public:
|
||||
* the root content.
|
||||
*/
|
||||
static PRBool IsViewportScrollbarFrame(nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Get the contribution of aFrame to its containing block's intrinsic
|
||||
* width. This considers the child's intrinsic width, its 'width',
|
||||
* 'min-width', and 'max-width' properties, and its padding, border,
|
||||
* and margin.
|
||||
*/
|
||||
enum IntrinsicWidthType { MIN_WIDTH, PREF_WIDTH };
|
||||
static nscoord IntrinsicForContainer(nsIRenderingContext* aRenderingContext,
|
||||
nsIFrame* aFrame,
|
||||
IntrinsicWidthType aType);
|
||||
|
||||
static nscoord ComputeHorizontalValue(nsIRenderingContext* aRenderingContext,
|
||||
nsIFrame *aFrame,
|
||||
nscoord aContainingBlockWidth,
|
||||
const nsStyleCoord& aCoord);
|
||||
|
||||
static nscoord ComputeVerticalValue(nsIRenderingContext* aRenderingContext,
|
||||
nsIFrame *aFrame,
|
||||
nscoord aContainingBlockHeight,
|
||||
const nsStyleCoord& aCoord);
|
||||
|
||||
static nsSize ComputeSizeWithIntrinsicDimensions(
|
||||
nsIRenderingContext* aRenderingContext,
|
||||
nsIFrame* aFrame, nsSize aIntrinsicSize, nsSize aCBSize,
|
||||
nsSize aBorder, nsSize aPadding);
|
||||
|
||||
// Implement nsIFrame::GetPrefWidth in terms of nsIFrame::AddInlinePrefWidth
|
||||
static nscoord PrefWidthFromInline(nsIFrame* aFrame,
|
||||
nsIRenderingContext* aRenderingContext);
|
||||
|
||||
// Implement nsIFrame::GetMinWidth in terms of nsIFrame::AddInlineMinWidth
|
||||
static nscoord MinWidthFromInline(nsIFrame* aFrame,
|
||||
nsIRenderingContext* aRenderingContext);
|
||||
};
|
||||
|
||||
#endif // nsLayoutUtils_h__
|
||||
|
@ -1387,11 +1387,10 @@ nsPresContext::EnsureVisible(PRBool aUnsuppressFocus)
|
||||
|
||||
#ifdef MOZ_REFLOW_PERF
|
||||
void
|
||||
nsPresContext::CountReflows(const char * aName,
|
||||
PRUint32 aType, nsIFrame * aFrame)
|
||||
nsPresContext::CountReflows(const char * aName, nsIFrame * aFrame)
|
||||
{
|
||||
if (mShell) {
|
||||
mShell->CountReflows(aName, aType, aFrame);
|
||||
mShell->CountReflows(aName, aFrame);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -650,7 +650,7 @@ public:
|
||||
|
||||
#ifdef MOZ_REFLOW_PERF
|
||||
NS_HIDDEN_(void) CountReflows(const char * aName,
|
||||
PRUint32 aType, nsIFrame * aFrame);
|
||||
nsIFrame * aFrame);
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -930,10 +930,10 @@ private:
|
||||
|
||||
#ifdef MOZ_REFLOW_PERF
|
||||
|
||||
#define DO_GLOBAL_REFLOW_COUNT(_name, _type) \
|
||||
aPresContext->CountReflows((_name), (_type), (nsIFrame*)this);
|
||||
#define DO_GLOBAL_REFLOW_COUNT(_name) \
|
||||
aPresContext->CountReflows((_name), (nsIFrame*)this);
|
||||
#else
|
||||
#define DO_GLOBAL_REFLOW_COUNT(_name, _type)
|
||||
#define DO_GLOBAL_REFLOW_COUNT(_name)
|
||||
#endif // MOZ_REFLOW_PERF
|
||||
|
||||
#endif /* nsPresContext_h___ */
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -72,6 +72,7 @@ class nsIView;
|
||||
class nsStyleContext;
|
||||
class nsIListControlFrame;
|
||||
class nsIScrollableView;
|
||||
class nsComboboxDisplayFrame;
|
||||
|
||||
/**
|
||||
* Child list name indices
|
||||
@ -90,6 +91,7 @@ class nsComboboxControlFrame : public nsAreaFrame,
|
||||
{
|
||||
public:
|
||||
friend nsIFrame* NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRUint32 aFlags);
|
||||
friend class nsComboboxDisplayFrame;
|
||||
|
||||
nsComboboxControlFrame(nsStyleContext* aContext);
|
||||
~nsComboboxControlFrame();
|
||||
@ -108,6 +110,10 @@ public:
|
||||
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
|
||||
#endif
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aCX,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -123,6 +129,13 @@ public:
|
||||
|
||||
void PaintFocus(nsIRenderingContext& aRenderingContext, nsPoint aPt);
|
||||
|
||||
// XXXbz this is only needed to prevent the quirk percent height stuff from
|
||||
// leaking out of the combobox. We may be able to get rid of this as more
|
||||
// things move to IsFrameOfType.
|
||||
virtual nsIAtom* GetType() const;
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
||||
#endif
|
||||
@ -186,20 +199,9 @@ public:
|
||||
|
||||
protected:
|
||||
|
||||
#ifdef DO_NEW_REFLOW
|
||||
NS_IMETHOD ReflowItems(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
#endif
|
||||
|
||||
// Utilities
|
||||
nsresult ReflowComboChildFrame(nsIFrame* aFrame,
|
||||
nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nscoord aAvailableWidth,
|
||||
nscoord aAvailableHeight);
|
||||
// Utilities
|
||||
nsresult ReflowDropdown(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState);
|
||||
|
||||
public:
|
||||
nsresult PositionDropdown(nsPresContext* aPresContext,
|
||||
@ -221,26 +223,13 @@ protected:
|
||||
|
||||
void ShowPopup(PRBool aShowPopup);
|
||||
void ShowList(nsPresContext* aPresContext, PRBool aShowList);
|
||||
void SetButtonFrameSize(const nsSize& aSize);
|
||||
void CheckFireOnChange();
|
||||
void FireValueChangeEvent();
|
||||
nsresult RedisplayText(PRInt32 aIndex);
|
||||
void HandleRedisplayTextEvent();
|
||||
void ActuallyDisplayText(PRBool aNotify);
|
||||
nsresult GetPrimaryComboFrame(nsPresContext* aPresContext, nsIContent* aContent, nsIFrame** aFrame);
|
||||
NS_IMETHOD ToggleList(nsPresContext* aPresContext);
|
||||
|
||||
void ReflowCombobox(nsPresContext * aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
nsReflowStatus& aStatus,
|
||||
nsIFrame * aDisplayFrame,
|
||||
nscoord& aDisplayWidth,
|
||||
nscoord aBtnWidth,
|
||||
const nsMargin& aBorderPadding,
|
||||
nscoord aFallBackHgt = -1,
|
||||
PRBool aCheckHeight = PR_FALSE);
|
||||
|
||||
nsFrameList mPopupFrames; // additional named child list
|
||||
nsCOMPtr<nsIContent> mDisplayContent; // Anonymous content used to display the current selection
|
||||
nsIFrame* mDisplayFrame; // frame to display selection
|
||||
@ -249,18 +238,10 @@ protected:
|
||||
nsIFrame* mTextFrame; // display area frame
|
||||
nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame
|
||||
|
||||
// Resize Reflow Optimization
|
||||
nsSize mCacheSize;
|
||||
nsSize mCachedAvailableSize;
|
||||
nscoord mCachedMaxElementWidth;
|
||||
nscoord mCachedAscent;
|
||||
|
||||
nsSize mCachedUncDropdownSize;
|
||||
nsSize mCachedUncComboSize;
|
||||
|
||||
nscoord mItemDisplayWidth;
|
||||
//nscoord mItemDisplayHeight;
|
||||
|
||||
// The width of our display area. Used by that frame's reflow to
|
||||
// size to the full width except the drop-marker.
|
||||
nscoord mDisplayWidth;
|
||||
|
||||
PRPackedBool mDroppedDown; // Current state of the dropdown list, PR_TRUE is dropped down
|
||||
PRPackedBool mInRedisplayText;
|
||||
|
||||
|
@ -73,6 +73,17 @@ public:
|
||||
NS_IMETHOD SetInitialChildList(nsIAtom* aListName,
|
||||
nsIFrame* aChildList);
|
||||
|
||||
NS_HIDDEN_(nscoord)
|
||||
GetLegendPrefWidth(nsIRenderingContext* aRenderingContext);
|
||||
NS_HIDDEN_(nscoord)
|
||||
GetContentMinWidth(nsIRenderingContext* aRenderingContext);
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext* aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext* aRenderingContext);
|
||||
virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -311,221 +322,259 @@ nsFieldSetFrame::PaintBorderBackground(nsIRenderingContext& aRenderingContext,
|
||||
}
|
||||
}
|
||||
|
||||
// XXXbz This duplicates code in nsLayoutAtoms (near IntrinsicForContainer)
|
||||
|
||||
static nscoord GetCoord(const nsStyleCoord& aCoord, nscoord aIfNotCoord)
|
||||
{
|
||||
return aCoord.GetUnit() == eStyleUnit_Coord
|
||||
? aCoord.GetCoordValue()
|
||||
: aIfNotCoord;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFieldSetFrame::GetLegendPrefWidth(nsIRenderingContext* aRenderingContext)
|
||||
{
|
||||
NS_ASSERTION(mLegendFrame, "Don't call me if there is no legend frame!");
|
||||
|
||||
// We don't want to use nsLayoutUtils::IntrinsicForContainer,
|
||||
// because legends ignore their CSS-specified width.
|
||||
nscoord result = mLegendFrame->GetPrefWidth(aRenderingContext);
|
||||
|
||||
nsStyleCoord tmp;
|
||||
|
||||
const nsStylePadding *stylePadding = mLegendFrame->GetStylePadding();
|
||||
result += GetCoord(stylePadding->mPadding.GetLeft(tmp), 0);
|
||||
result += GetCoord(stylePadding->mPadding.GetRight(tmp), 0);
|
||||
|
||||
const nsStyleBorder *styleBorder = mLegendFrame->GetStyleBorder();
|
||||
result += styleBorder->GetBorderWidth(NS_SIDE_LEFT);
|
||||
result += styleBorder->GetBorderWidth(NS_SIDE_RIGHT);
|
||||
|
||||
const nsStyleMargin *styleMargin = mLegendFrame->GetStyleMargin();
|
||||
result += GetCoord(styleMargin->mMargin.GetLeft(tmp), 0);
|
||||
result += GetCoord(styleMargin->mMargin.GetRight(tmp), 0);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFieldSetFrame::GetContentMinWidth(nsIRenderingContext* aRenderingContext)
|
||||
{
|
||||
NS_ASSERTION(mContentFrame, "Don't call me if there is no legend frame!");
|
||||
|
||||
return nsLayoutUtils::IntrinsicForContainer(aRenderingContext, mContentFrame,
|
||||
nsLayoutUtils::MIN_WIDTH);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFieldSetFrame::GetMinWidth(nsIRenderingContext* aRenderingContext)
|
||||
{
|
||||
nscoord result = 0;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
|
||||
nscoord legendPrefWidth = 0;
|
||||
nscoord contentMinWidth = 0;
|
||||
if (mLegendFrame) {
|
||||
legendPrefWidth = GetLegendPrefWidth(aRenderingContext);
|
||||
}
|
||||
|
||||
if (mContentFrame) {
|
||||
contentMinWidth = GetContentMinWidth(aRenderingContext);
|
||||
}
|
||||
|
||||
result = PR_MAX(legendPrefWidth, contentMinWidth);
|
||||
return result;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFieldSetFrame::GetPrefWidth(nsIRenderingContext* aRenderingContext)
|
||||
{
|
||||
nscoord result = 0;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
|
||||
nscoord legendPrefWidth = 0;
|
||||
nscoord contentPrefWidth = 0;
|
||||
if (mLegendFrame) {
|
||||
legendPrefWidth = GetLegendPrefWidth(aRenderingContext);
|
||||
}
|
||||
|
||||
if (mContentFrame) {
|
||||
contentPrefWidth =
|
||||
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, mContentFrame,
|
||||
nsLayoutUtils::PREF_WIDTH);
|
||||
}
|
||||
|
||||
result = PR_MAX(legendPrefWidth, contentPrefWidth);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nsSize
|
||||
nsFieldSetFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap)
|
||||
{
|
||||
nsSize result =
|
||||
nsHTMLContainerFrame::ComputeSize(aRenderingContext, aCBSize,
|
||||
aAvailableWidth,
|
||||
aMargin, aBorder, aPadding, aShrinkWrap);
|
||||
|
||||
// Fieldsets never shrink below their min width.
|
||||
nscoord minWidth = GetMinWidth(aRenderingContext);
|
||||
if (minWidth > result.width)
|
||||
result.width = minWidth;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsFieldSetFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
NS_PRECONDITION(aReflowState.mComputedWidth != NS_INTRINSICSIZE,
|
||||
"Should have a precomputed width!");
|
||||
|
||||
// Initialize OUT parameter
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
//------------ Handle Incremental Reflow -----------------
|
||||
PRBool reflowContent = PR_TRUE;
|
||||
PRBool reflowLegend = PR_TRUE;
|
||||
nsReflowReason reason = aReflowState.reason;
|
||||
PRBool reflowContent;
|
||||
PRBool reflowLegend;
|
||||
|
||||
if (reason == eReflowReason_Incremental) {
|
||||
nsHTMLReflowCommand *command = aReflowState.path->mReflowCommand;
|
||||
if (aReflowState.ShouldReflowAllKids()) {
|
||||
reflowContent = mContentFrame != nsnull;
|
||||
reflowLegend = mLegendFrame != nsnull;
|
||||
} else {
|
||||
reflowContent = mContentFrame &&
|
||||
(mContentFrame->GetStateBits() &
|
||||
(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0;
|
||||
|
||||
// See if it's targeted at us
|
||||
if (command) {
|
||||
nsReflowType reflowType;
|
||||
command->GetType(reflowType);
|
||||
|
||||
switch (reflowType) {
|
||||
case eReflowType_StyleChanged:
|
||||
reason = eReflowReason_StyleChange;
|
||||
break;
|
||||
|
||||
case eReflowType_ReflowDirty:
|
||||
reason = eReflowReason_Dirty;
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ERROR("Unexpected Reflow Type");
|
||||
}
|
||||
} else {
|
||||
reflowContent = PR_FALSE;
|
||||
reflowLegend = PR_FALSE;
|
||||
|
||||
nsReflowPath::iterator iter = aReflowState.path->FirstChild();
|
||||
nsReflowPath::iterator end = aReflowState.path->EndChildren();
|
||||
|
||||
for ( ; iter != end; ++iter) {
|
||||
if (*iter == mLegendFrame)
|
||||
reflowLegend = PR_TRUE;
|
||||
else if (*iter == mContentFrame)
|
||||
reflowContent = PR_TRUE;
|
||||
}
|
||||
}
|
||||
reflowLegend = mLegendFrame &&
|
||||
(mLegendFrame->GetStateBits() &
|
||||
(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0;
|
||||
}
|
||||
|
||||
if (aDesiredSize.mFlags & NS_REFLOW_CALC_MAX_WIDTH) {
|
||||
reflowLegend = PR_TRUE;
|
||||
reflowContent = PR_TRUE;
|
||||
} else if (reason == eReflowReason_Dirty) {
|
||||
// if dirty then check dirty flags
|
||||
if (GetStateBits() & NS_FRAME_IS_DIRTY) {
|
||||
reflowLegend = PR_TRUE;
|
||||
reflowContent = PR_TRUE;
|
||||
} else {
|
||||
if (reflowContent) {
|
||||
reflowContent = mContentFrame ?
|
||||
(mContentFrame->GetStateBits()
|
||||
& (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0 : PR_FALSE;
|
||||
}
|
||||
|
||||
if (reflowLegend) {
|
||||
reflowLegend = mLegendFrame ?
|
||||
(mLegendFrame->GetStateBits()
|
||||
& (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0 : PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// availSize could have unconstrained values, don't perform any addition on them
|
||||
nsSize availSize(aReflowState.mComputedWidth, aReflowState.availableHeight);
|
||||
NS_ASSERTION(!mContentFrame ||
|
||||
GetContentMinWidth(aReflowState.rendContext) <= availSize.width,
|
||||
"Bogus availSize.width; should be bigger");
|
||||
|
||||
// get our border and padding
|
||||
const nsMargin &borderPadding = aReflowState.mComputedBorderPadding;
|
||||
const nsMargin &padding = aReflowState.mComputedPadding;
|
||||
nsMargin border = borderPadding - padding;
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = borderPadding.left + borderPadding.right;
|
||||
}
|
||||
|
||||
nsMargin border = borderPadding - padding;
|
||||
|
||||
// Figure out how big the legend is if there is one.
|
||||
// get the legend's margin
|
||||
nsMargin legendMargin(0,0,0,0);
|
||||
// reflow the legend only if needed
|
||||
if (mLegendFrame) {
|
||||
if (reflowLegend) {
|
||||
const nsStyleMargin* marginStyle = mLegendFrame->GetStyleMargin();
|
||||
marginStyle->GetMargin(legendMargin);
|
||||
|
||||
if (reflowLegend) {
|
||||
nsHTMLReflowState legendReflowState(aPresContext, aReflowState,
|
||||
mLegendFrame, nsSize(NS_INTRINSICSIZE,NS_INTRINSICSIZE),
|
||||
reason);
|
||||
// Give the legend all the space it wants.
|
||||
nsSize legendAvailSize(GetLegendPrefWidth(aReflowState.rendContext),
|
||||
NS_INTRINSICSIZE);
|
||||
|
||||
// always give the legend as much size as it needs
|
||||
legendReflowState.mComputedWidth = NS_INTRINSICSIZE;
|
||||
legendReflowState.mComputedHeight = NS_INTRINSICSIZE;
|
||||
nsHTMLReflowState legendReflowState(aPresContext, aReflowState,
|
||||
mLegendFrame,
|
||||
legendAvailSize);
|
||||
|
||||
nsHTMLReflowMetrics legendDesiredSize(0,0);
|
||||
// always give the legend as much size as it wants
|
||||
legendReflowState.mComputedWidth =
|
||||
mLegendFrame->GetPrefWidth(aReflowState.rendContext);
|
||||
legendReflowState.mComputedHeight = NS_INTRINSICSIZE;
|
||||
|
||||
ReflowChild(mLegendFrame, aPresContext, legendDesiredSize, legendReflowState,
|
||||
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
|
||||
nsHTMLReflowMetrics legendDesiredSize;
|
||||
|
||||
ReflowChild(mLegendFrame, aPresContext, legendDesiredSize, legendReflowState,
|
||||
0, 0, NS_FRAME_NO_MOVE_FRAME, aStatus);
|
||||
#ifdef NOISY_REFLOW
|
||||
printf(" returned (%d, %d)\n", legendDesiredSize.width, legendDesiredSize.height);
|
||||
if (legendDesiredSize.mComputeMEW)
|
||||
printf(" and maxEW %d\n",
|
||||
legendDesiredSize.mMaxElementWidth);
|
||||
printf(" returned (%d, %d)\n", legendDesiredSize.width, legendDesiredSize.height);
|
||||
#endif
|
||||
// figure out the legend's rectangle
|
||||
mLegendRect.width = legendDesiredSize.width + legendMargin.left + legendMargin.right;
|
||||
mLegendRect.height = legendDesiredSize.height + legendMargin.top + legendMargin.bottom;
|
||||
mLegendRect.x = borderPadding.left;
|
||||
mLegendRect.y = 0;
|
||||
|
||||
nscoord oldSpace = mLegendSpace;
|
||||
mLegendSpace = 0;
|
||||
if (mLegendRect.height > border.top) {
|
||||
// center the border on the legend
|
||||
mLegendSpace = mLegendRect.height - border.top;
|
||||
} else {
|
||||
mLegendRect.y = (border.top - mLegendRect.height)/2;
|
||||
}
|
||||
|
||||
// if the legend space changes then we need to reflow the
|
||||
// content area as well.
|
||||
if (mLegendSpace != oldSpace) {
|
||||
if (reflowContent == PR_FALSE || reason == eReflowReason_Dirty) {
|
||||
reflowContent = PR_TRUE;
|
||||
reason = eReflowReason_Resize;
|
||||
}
|
||||
}
|
||||
|
||||
// if we are contrained then remove the legend from our available height.
|
||||
if (NS_INTRINSICSIZE != availSize.height) {
|
||||
if (availSize.height >= mLegendSpace)
|
||||
availSize.height -= mLegendSpace;
|
||||
}
|
||||
|
||||
// don't get any smaller than the legend
|
||||
if (NS_INTRINSICSIZE != availSize.width) {
|
||||
if (availSize.width < mLegendRect.width)
|
||||
availSize.width = mLegendRect.width;
|
||||
}
|
||||
|
||||
FinishReflowChild(mLegendFrame, aPresContext, &legendReflowState,
|
||||
legendDesiredSize, 0, 0, NS_FRAME_NO_MOVE_FRAME);
|
||||
// figure out the legend's rectangle
|
||||
mLegendRect.width = legendDesiredSize.width + legendMargin.left + legendMargin.right;
|
||||
mLegendRect.height = legendDesiredSize.height + legendMargin.top + legendMargin.bottom;
|
||||
mLegendRect.x = borderPadding.left;
|
||||
mLegendRect.y = 0;
|
||||
|
||||
nscoord oldSpace = mLegendSpace;
|
||||
mLegendSpace = 0;
|
||||
if (mLegendRect.height > border.top) {
|
||||
// center the border on the legend
|
||||
mLegendSpace = mLegendRect.height - border.top;
|
||||
} else {
|
||||
mLegendRect.y = (border.top - mLegendRect.height)/2;
|
||||
}
|
||||
} else {
|
||||
|
||||
// if the legend space changes then we need to reflow the
|
||||
// content area as well.
|
||||
if (mLegendSpace != oldSpace && mContentFrame) {
|
||||
reflowContent = PR_TRUE;
|
||||
}
|
||||
|
||||
// if we are contrained then remove the legend from our available height.
|
||||
if (NS_INTRINSICSIZE != availSize.height) {
|
||||
availSize.height -= mLegendSpace;
|
||||
availSize.height = PR_MAX(availSize.height, 0);
|
||||
}
|
||||
|
||||
NS_ASSERTION(availSize.width >= mLegendRect.width,
|
||||
"Bogus availSize.width. Should be bigger");
|
||||
|
||||
FinishReflowChild(mLegendFrame, aPresContext, &legendReflowState,
|
||||
legendDesiredSize, 0, 0, NS_FRAME_NO_MOVE_FRAME);
|
||||
} else if (!mLegendFrame) {
|
||||
mLegendRect.Empty();
|
||||
mLegendSpace = 0;
|
||||
}
|
||||
} // else mLegendSpace and mLegendRect haven't changed...
|
||||
|
||||
nsRect contentRect;
|
||||
|
||||
// reflow the content frame only if needed
|
||||
if (mContentFrame) {
|
||||
if (reflowContent) {
|
||||
availSize.width = aReflowState.mComputedWidth;
|
||||
if (reflowContent) {
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, mContentFrame,
|
||||
availSize);
|
||||
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, mContentFrame,
|
||||
availSize, reason);
|
||||
nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mFlags);
|
||||
// Reflow the frame
|
||||
ReflowChild(mContentFrame, aPresContext, kidDesiredSize, kidReflowState,
|
||||
borderPadding.left + kidReflowState.mComputedMargin.left,
|
||||
borderPadding.top + mLegendSpace + kidReflowState.mComputedMargin.top,
|
||||
0, aStatus);
|
||||
|
||||
nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mComputeMEW, aDesiredSize.mFlags);
|
||||
// Reflow the frame
|
||||
ReflowChild(mContentFrame, aPresContext, kidDesiredSize, kidReflowState,
|
||||
borderPadding.left + kidReflowState.mComputedMargin.left,
|
||||
borderPadding.top + mLegendSpace + kidReflowState.mComputedMargin.top,
|
||||
0, aStatus);
|
||||
|
||||
// set the rect. make sure we add the margin back in.
|
||||
contentRect.SetRect(borderPadding.left,borderPadding.top + mLegendSpace,kidDesiredSize.width ,kidDesiredSize.height);
|
||||
if (aReflowState.mComputedHeight != NS_INTRINSICSIZE &&
|
||||
borderPadding.top + mLegendSpace+kidDesiredSize.height > aReflowState.mComputedHeight) {
|
||||
kidDesiredSize.height = aReflowState.mComputedHeight-(borderPadding.top + mLegendSpace);
|
||||
}
|
||||
|
||||
FinishReflowChild(mContentFrame, aPresContext, &kidReflowState,
|
||||
kidDesiredSize, contentRect.x, contentRect.y, 0);
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = kidDesiredSize.mMaxElementWidth;
|
||||
if (eStyleUnit_Coord == aReflowState.mStylePosition->mWidth.GetUnit() &&
|
||||
NS_INTRINSICSIZE != aReflowState.mComputedWidth)
|
||||
aDesiredSize.mMaxElementWidth = aReflowState.mComputedWidth;
|
||||
if (eStyleUnit_Percent == aReflowState.mStylePosition->mWidth.GetUnit())
|
||||
aDesiredSize.mMaxElementWidth = 0;
|
||||
aDesiredSize.mMaxElementWidth += borderPadding.left + borderPadding.right;
|
||||
}
|
||||
if (aDesiredSize.mFlags & NS_REFLOW_CALC_MAX_WIDTH) {
|
||||
aDesiredSize.mMaximumWidth = kidDesiredSize.mMaximumWidth +
|
||||
borderPadding.left + borderPadding.right;
|
||||
}
|
||||
NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus);
|
||||
|
||||
} else {
|
||||
// if we don't need to reflow just get the old size
|
||||
contentRect = mContentFrame->GetRect();
|
||||
const nsStyleMargin* marginStyle = mContentFrame->GetStyleMargin();
|
||||
|
||||
nsMargin m(0,0,0,0);
|
||||
marginStyle->GetMargin(m);
|
||||
contentRect.Inflate(m);
|
||||
// set the rect. make sure we add the margin back in.
|
||||
contentRect.SetRect(borderPadding.left,borderPadding.top + mLegendSpace,kidDesiredSize.width ,kidDesiredSize.height);
|
||||
if (aReflowState.mComputedHeight != NS_INTRINSICSIZE &&
|
||||
borderPadding.top + mLegendSpace+kidDesiredSize.height > aReflowState.mComputedHeight) {
|
||||
kidDesiredSize.height = aReflowState.mComputedHeight-(borderPadding.top + mLegendSpace);
|
||||
}
|
||||
|
||||
FinishReflowChild(mContentFrame, aPresContext, &kidReflowState,
|
||||
kidDesiredSize, contentRect.x, contentRect.y, 0);
|
||||
NS_FRAME_TRACE_REFLOW_OUT("FieldSet::Reflow", aStatus);
|
||||
|
||||
} else if (mContentFrame) {
|
||||
// if we don't need to reflow just get the old size
|
||||
// XXXbz what about auto or percent margins? Those wouldn't be in
|
||||
// the style!
|
||||
contentRect = mContentFrame->GetRect();
|
||||
const nsStyleMargin* marginStyle = mContentFrame->GetStyleMargin();
|
||||
|
||||
nsMargin m(0,0,0,0);
|
||||
marginStyle->GetMargin(m);
|
||||
contentRect.Inflate(m);
|
||||
} else {
|
||||
contentRect.Empty();
|
||||
}
|
||||
|
||||
// use the computed width if the inner content does not fill it
|
||||
if (aReflowState.mComputedWidth != NS_INTRINSICSIZE &&
|
||||
aReflowState.mComputedWidth > contentRect.width) {
|
||||
if (aReflowState.mComputedWidth > contentRect.width) {
|
||||
contentRect.width = aReflowState.mComputedWidth;
|
||||
}
|
||||
|
||||
@ -581,17 +630,7 @@ nsFieldSetFrame::Reflow(nsPresContext* aPresContext,
|
||||
aDesiredSize.width = contentRect.width + borderPadding.left + borderPadding.right;
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
// if the legend is wider use it
|
||||
if (aDesiredSize.mMaxElementWidth < mLegendRect.width + borderPadding.left + borderPadding.right)
|
||||
aDesiredSize.mMaxElementWidth = mLegendRect.width + borderPadding.left + borderPadding.right;
|
||||
}
|
||||
aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
||||
// make the mMaximumWidth large enough if the legendframe determines the size
|
||||
if ((aDesiredSize.mFlags & NS_REFLOW_CALC_MAX_WIDTH) && mLegendFrame) {
|
||||
aDesiredSize.mMaximumWidth = PR_MAX(aDesiredSize.mMaximumWidth, mLegendRect.width +
|
||||
borderPadding.left + borderPadding.right);
|
||||
}
|
||||
if (mLegendFrame)
|
||||
ConsiderChildOverflow(aDesiredSize.mOverflowArea, mLegendFrame);
|
||||
if (mContentFrame)
|
||||
@ -656,7 +695,7 @@ nsFieldSetFrame::RemoveFrame(nsIAtom* aListName,
|
||||
mLegendFrame = nsnull;
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
if (GetParent()) {
|
||||
GetParent()->ReflowDirtyChild(GetPresContext()->GetPresShell(), this);
|
||||
GetParent()->ChildIsDirty(this);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -687,7 +726,7 @@ nsFieldSetFrame::MaybeSetLegend(nsIFrame* aFrameList, nsIAtom* aListName)
|
||||
mFrames.SetFrames(mLegendFrame);
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
if (GetParent()) {
|
||||
GetParent()->ReflowDirtyChild(mLegendFrame->GetPresContext()->GetPresShell(), this);
|
||||
GetParent()->ChildIsDirty(this);
|
||||
}
|
||||
}
|
||||
return aFrameList;
|
||||
|
@ -355,18 +355,28 @@ nsFileControlFrame::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
return NS_FAILED(result) ? result : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsFileControlFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
|
||||
// Our min width is our pref width
|
||||
result = GetPrefWidth(aRenderingContext);
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsFileControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsFileControlFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsFileControlFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
if (eReflowReason_Initial == aReflowState.reason) {
|
||||
if (mState & NS_FRAME_FIRST_REFLOW) {
|
||||
mTextFrame = GetTextControlFrame(aPresContext, this);
|
||||
NS_ENSURE_TRUE(mTextFrame, NS_ERROR_UNEXPECTED);
|
||||
if (mCachedState) {
|
||||
@ -378,7 +388,10 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
// The Areaframe takes care of all our reflow
|
||||
// except for when style is used to change its size.
|
||||
nsresult rv = nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
// XXXbz do we care? This setup just needs to die.... Leaving it
|
||||
// in for now just because I don't want to regress things, but....
|
||||
nsresult rv = nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState,
|
||||
aStatus);
|
||||
if (NS_SUCCEEDED(rv) && mTextFrame != nsnull) {
|
||||
nsIFrame* child = GetFirstChild(nsnull);
|
||||
if (child == mTextFrame) {
|
||||
@ -394,12 +407,11 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
// messes up the button's rect
|
||||
if (txtRect.width + buttonRect.width != aDesiredSize.width ||
|
||||
txtRect.height != aDesiredSize.height) {
|
||||
nsHTMLReflowMetrics txtKidSize(PR_TRUE);
|
||||
nsHTMLReflowMetrics txtKidSize;
|
||||
nsSize txtAvailSize(aReflowState.availableWidth, aDesiredSize.height);
|
||||
nsHTMLReflowState txtKidReflowState(aPresContext,
|
||||
*aReflowState.parentReflowState,
|
||||
this, txtAvailSize,
|
||||
eReflowReason_Resize);
|
||||
this, txtAvailSize);
|
||||
txtKidReflowState.mComputedHeight = aDesiredSize.height;
|
||||
rv = nsAreaFrame::WillReflow(aPresContext);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Should have succeeded");
|
||||
@ -408,14 +420,11 @@ NS_IMETHODIMP nsFileControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
rv = nsAreaFrame::DidReflow(aPresContext, &txtKidReflowState, aStatus);
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Should have succeeded");
|
||||
|
||||
// Re-calc and set the correct rect
|
||||
// And now manually resize the frame...
|
||||
txtRect = mTextFrame->GetRect();
|
||||
txtRect.y = aReflowState.mComputedBorderPadding.top;
|
||||
txtRect.height = aDesiredSize.height;
|
||||
mTextFrame->SetRect(txtRect);
|
||||
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -611,4 +620,8 @@ nsFileControlFrame::MouseListener::MouseClick(nsIDOMEvent* aMouseEvent)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsFileControlFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced | eReplacedContainsBlock));
|
||||
}
|
||||
|
@ -72,6 +72,8 @@ public:
|
||||
virtual nsresult GetFormProperty(nsIAtom* aName, nsAString& aValue) const;
|
||||
virtual void SetFocus(PRBool aOn, PRBool aRepaint);
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aCX,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -128,6 +130,8 @@ protected:
|
||||
|
||||
nsresult MouseClick(nsIDOMEvent* aMouseEvent);
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
|
||||
/**
|
||||
|
@ -80,157 +80,22 @@ nsFormControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
return nsLeafFrame::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
void nsFormControlFrame::SetupCachedSizes(nsSize& aCacheSize,
|
||||
nscoord& aCachedAscent,
|
||||
nscoord& aCachedMaxElementWidth,
|
||||
nsHTMLReflowMetrics& aDesiredSize)
|
||||
nscoord
|
||||
nsFormControlFrame::GetIntrinsicWidth()
|
||||
{
|
||||
aCacheSize.width = aDesiredSize.width;
|
||||
aCacheSize.height = aDesiredSize.height;
|
||||
aCachedAscent = aDesiredSize.ascent;
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aCachedMaxElementWidth = aDesiredSize.mMaxElementWidth;
|
||||
}
|
||||
// Intrinsic width is 144 twips. Why? I have no idea; that's what
|
||||
// it was before I touched this code, and the original checkin
|
||||
// comment is not so helpful.
|
||||
return 144;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------
|
||||
void nsFormControlFrame::SkipResizeReflow(nsSize& aCacheSize,
|
||||
nscoord& aCachedAscent,
|
||||
nscoord& aCachedMaxElementWidth,
|
||||
nsSize& aCachedAvailableSize,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
PRBool& aBailOnWidth,
|
||||
PRBool& aBailOnHeight)
|
||||
nscoord
|
||||
nsFormControlFrame::GetIntrinsicHeight()
|
||||
{
|
||||
|
||||
if (aReflowState.reason == eReflowReason_Incremental ||
|
||||
#ifdef IBMBIDI
|
||||
aReflowState.reason == eReflowReason_StyleChange ||
|
||||
#endif
|
||||
aReflowState.reason == eReflowReason_Dirty) {
|
||||
aBailOnHeight = PR_FALSE;
|
||||
aBailOnWidth = PR_FALSE;
|
||||
|
||||
} else if (eReflowReason_Initial == aReflowState.reason) {
|
||||
aBailOnHeight = PR_FALSE;
|
||||
aBailOnWidth = PR_FALSE;
|
||||
|
||||
} else {
|
||||
|
||||
nscoord width;
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedWidth) {
|
||||
if (aReflowState.availableWidth == NS_UNCONSTRAINEDSIZE) {
|
||||
width = NS_UNCONSTRAINEDSIZE;
|
||||
aBailOnWidth = aCacheSize.width != kSizeNotSet;
|
||||
#ifdef FCF_NOISY
|
||||
if (aBailOnWidth) {
|
||||
printf("-------------- #1 Bailing on aCachedAvailableSize.width %d != kSizeNotSet\n", aCachedAvailableSize.width);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
width = aReflowState.availableWidth - aReflowState.mComputedBorderPadding.left -
|
||||
aReflowState.mComputedBorderPadding.right;
|
||||
aBailOnWidth = aCachedAvailableSize.width <= width && aCachedAvailableSize.width != kSizeNotSet;
|
||||
#ifdef FCF_NOISY
|
||||
if (aBailOnWidth) {
|
||||
printf("-------------- #2 Bailing on aCachedAvailableSize.width %d <= width %d\n", aCachedAvailableSize.width, width );
|
||||
} else {
|
||||
aBailOnWidth = width <= (aCacheSize.width - aReflowState.mComputedBorderPadding.left - aReflowState.mComputedBorderPadding.right) &&
|
||||
aCachedAvailableSize.width == kSizeNotSet;
|
||||
if (aBailOnWidth) {
|
||||
printf("-------------- #2.2 Bailing on width %d <= aCachedAvailableSize.width %d\n",(aCacheSize.width - aReflowState.mComputedBorderPadding.left - aReflowState.mComputedBorderPadding.right), width );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
width = aReflowState.mComputedWidth;
|
||||
//if (aCachedAvailableSize.width == kSizeNotSet) {
|
||||
// //aBailOnWidth = aCachedAvailableSize.width == aCacheSize.width;
|
||||
aBailOnWidth = PR_FALSE;
|
||||
//} else {
|
||||
aBailOnWidth = width == (aCacheSize.width - aReflowState.mComputedBorderPadding.left - aReflowState.mComputedBorderPadding.right);
|
||||
//}
|
||||
#ifdef FCF_NOISY
|
||||
if (aBailOnWidth) {
|
||||
printf("-------------- #3 Bailing on aCachedAvailableSize.width %d == aReflowState.mComputedWidth %d\n", aCachedAvailableSize.width, width );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nscoord height;
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.mComputedHeight) {
|
||||
if (aReflowState.availableHeight == NS_UNCONSTRAINEDSIZE) {
|
||||
height = NS_UNCONSTRAINEDSIZE;
|
||||
aBailOnHeight = aCacheSize.height != kSizeNotSet;
|
||||
#ifdef FCF_NOISY
|
||||
if (aBailOnHeight) {
|
||||
printf("-------------- #1 Bailing on aCachedAvailableSize.height %d != kSizeNotSet\n", aCachedAvailableSize.height);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
height = aReflowState.availableHeight - aReflowState.mComputedBorderPadding.left -
|
||||
aReflowState.mComputedBorderPadding.right;
|
||||
aBailOnHeight = aCachedAvailableSize.height <= height && aCachedAvailableSize.height != kSizeNotSet;
|
||||
#ifdef FCF_NOISY
|
||||
if (aBailOnHeight) {
|
||||
printf("-------------- #2 Bailing on aCachedAvailableSize.height %d <= height %d\n", aCachedAvailableSize.height, height );
|
||||
} else {
|
||||
aBailOnHeight = height <= (aCacheSize.height - aReflowState.mComputedBorderPadding.left - aReflowState.mComputedBorderPadding.right) &&
|
||||
aCachedAvailableSize.height == kSizeNotSet;
|
||||
if (aBailOnHeight) {
|
||||
printf("-------------- #2.2 Bailing on height %d <= aCachedAvailableSize.height %d\n",(aCacheSize.height - aReflowState.mComputedBorderPadding.left - aReflowState.mComputedBorderPadding.right), height );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
height = aReflowState.mComputedHeight;
|
||||
//if (aCachedAvailableSize.height == kSizeNotSet) {
|
||||
// //aBailOnHeight = aCachedAvailableSize.height == aCacheSize.height;
|
||||
aBailOnHeight = PR_FALSE;
|
||||
//} else {
|
||||
aBailOnHeight = height == (aCacheSize.height - aReflowState.mComputedBorderPadding.left - aReflowState.mComputedBorderPadding.right);
|
||||
//}
|
||||
#ifdef FCF_NOISY
|
||||
if (aBailOnHeight) {
|
||||
printf("-------------- #3 Bailing on aCachedAvailableSize.height %d == aReflowState.mComputedHeight %d\n", aCachedAvailableSize.height, height );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (aBailOnWidth || aBailOnHeight) {
|
||||
aDesiredSize.width = aCacheSize.width;
|
||||
aDesiredSize.height = aCacheSize.height;
|
||||
aDesiredSize.ascent = aCachedAscent;
|
||||
aDesiredSize.descent = aDesiredSize.height - aDesiredSize.ascent;
|
||||
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = aCachedMaxElementWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFormControlFrame::GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
// get the css size and let the frame use or override it
|
||||
nsSize styleSize;
|
||||
GetStyleSize(aPresContext, aReflowState, styleSize);
|
||||
|
||||
// subclasses should always override this method, but if not and no css, make it small
|
||||
aDesiredSize.width = (styleSize.width > CSS_NOTSET) ? styleSize.width : 144;
|
||||
aDesiredSize.height = (styleSize.height > CSS_NOTSET) ? styleSize.height : 144;
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit());
|
||||
}
|
||||
// Intrinsic height is 144 twips. Why? I have no idea; that's what
|
||||
// it was before I touched this code, and the original checkin
|
||||
// comment is not so helpful.
|
||||
return 144;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -275,21 +140,15 @@ nsFormControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsFormControlFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsFormControlFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
if (!mDidInit) {
|
||||
if (mState & NS_FRAME_FIRST_REFLOW) {
|
||||
RegUnRegAccessKey(NS_STATIC_CAST(nsIFrame*, this), PR_TRUE);
|
||||
mDidInit = PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult rv = nsLeafFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
||||
FinishAndStoreOverflow(&aDesiredSize);
|
||||
return rv;
|
||||
return nsLeafFrame::Reflow(aPresContext, aDesiredSize, aReflowState,
|
||||
aStatus);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -335,25 +194,6 @@ nsFormControlFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsFormControlFrame::GetStyleSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsSize& aSize)
|
||||
{
|
||||
if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) {
|
||||
aSize.width = aReflowState.mComputedWidth;
|
||||
}
|
||||
else {
|
||||
aSize.width = CSS_NOTSET;
|
||||
}
|
||||
if (aReflowState.mComputedHeight != NS_INTRINSICSIZE) {
|
||||
aSize.height = aReflowState.mComputedHeight;
|
||||
}
|
||||
else {
|
||||
aSize.height = CSS_NOTSET;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsFormControlFrame::GetCurrentCheckState(PRBool *aState)
|
||||
{
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "nsIFormControlFrame.h"
|
||||
#include "nsLeafFrame.h"
|
||||
|
||||
#define CSS_NOTSET -1
|
||||
#define ATTR_NOTSET -1
|
||||
|
||||
#ifdef DEBUG_rods
|
||||
@ -114,36 +113,11 @@ public:
|
||||
|
||||
virtual void SetFocus(PRBool aOn = PR_TRUE, PRBool aRepaint = PR_FALSE);
|
||||
|
||||
/**
|
||||
* Get the width and height of this control based on CSS
|
||||
* @param aPresContext the presentation context
|
||||
* @param aSize the size that this frame wants, set by this method. values of -1
|
||||
* for aSize.width or aSize.height indicate unset values.
|
||||
*/
|
||||
static void GetStyleSize(nsPresContext* aContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsSize& aSize);
|
||||
|
||||
// nsIFormControlFrame
|
||||
virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue);
|
||||
|
||||
virtual nsresult GetFormProperty(nsIAtom* aName, nsAString& aValue) const;
|
||||
|
||||
// Resize Reflow Optimization Methods
|
||||
static void SetupCachedSizes(nsSize& aCacheSize,
|
||||
nscoord& aCachedAscent,
|
||||
nscoord& aCachedMaxElementWidth,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
|
||||
static void SkipResizeReflow(nsSize& aCacheSize,
|
||||
nscoord& aCachedAscent,
|
||||
nscoord& aCachedMaxElementWidth,
|
||||
nsSize& aCachedAvailableSize,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
PRBool& aBailOnWidth,
|
||||
PRBool& aBailOnHeight);
|
||||
// AccessKey Helper function
|
||||
static nsresult RegUnRegAccessKey(nsIFrame * aFrame, PRBool aDoReg);
|
||||
|
||||
@ -165,15 +139,8 @@ protected:
|
||||
|
||||
virtual ~nsFormControlFrame();
|
||||
|
||||
/**
|
||||
* Get the size that this frame would occupy without any constraints
|
||||
* @param aPresContext the presentation context
|
||||
* @param aDesiredSize the size desired by this frame, to be set by this method
|
||||
* @param aMaxSize the maximum size available for this frame
|
||||
*/
|
||||
virtual void GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
virtual nscoord GetIntrinsicWidth();
|
||||
virtual nscoord GetIntrinsicHeight();
|
||||
|
||||
//
|
||||
//-------------------------------------------------------------------------------------
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsStyleSet.h"
|
||||
#include "nsContentUtils.h"
|
||||
@ -63,8 +62,7 @@
|
||||
const nscoord kSuggestedNotSet = -1;
|
||||
|
||||
nsGfxButtonControlFrame::nsGfxButtonControlFrame(nsStyleContext* aContext):
|
||||
nsHTMLButtonControlFrame(aContext),
|
||||
mSuggestedSize(kSuggestedNotSet, kSuggestedNotSet)
|
||||
nsHTMLButtonControlFrame(aContext)
|
||||
{
|
||||
}
|
||||
|
||||
@ -308,44 +306,6 @@ nsGfxButtonControlFrame::IsLeaf() const
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGfxButtonControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsGfxButtonControlFrame", aReflowState.reason);
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
if ((kSuggestedNotSet != mSuggestedSize.width) ||
|
||||
(kSuggestedNotSet != mSuggestedSize.height)) {
|
||||
nsHTMLReflowState suggestedReflowState(aReflowState);
|
||||
|
||||
// Honor the suggested width and/or height.
|
||||
if (kSuggestedNotSet != mSuggestedSize.width) {
|
||||
suggestedReflowState.mComputedWidth = mSuggestedSize.width;
|
||||
}
|
||||
|
||||
if (kSuggestedNotSet != mSuggestedSize.height) {
|
||||
suggestedReflowState.mComputedHeight = mSuggestedSize.height;
|
||||
}
|
||||
|
||||
return nsHTMLButtonControlFrame::Reflow(aPresContext, aDesiredSize, suggestedReflowState, aStatus);
|
||||
|
||||
}
|
||||
|
||||
// Normal reflow.
|
||||
|
||||
return nsHTMLButtonControlFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
}
|
||||
|
||||
void
|
||||
nsGfxButtonControlFrame::SetSuggestedSize(const nsSize& aSize)
|
||||
{
|
||||
mSuggestedSize = aSize;
|
||||
//mState |= NS_FRAME_IS_DIRTY;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsGfxButtonControlFrame::HandleEvent(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
|
@ -58,12 +58,6 @@ class nsGfxButtonControlFrame : public nsHTMLButtonControlFrame,
|
||||
public:
|
||||
nsGfxButtonControlFrame(nsStyleContext* aContext);
|
||||
|
||||
//nsIFrame
|
||||
NS_IMETHOD Reflow(nsPresContext* aCX,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
NS_IMETHOD HandleEvent(nsPresContext* aPresContext,
|
||||
nsGUIEvent* aEvent,
|
||||
nsEventStatus* aEventStatus);
|
||||
@ -94,14 +88,6 @@ public:
|
||||
|
||||
virtual PRBool IsLeaf() const;
|
||||
|
||||
/**
|
||||
* Set the suggested size of the button.
|
||||
* @note This is NOT a virtual function, it will be called
|
||||
* directly on an instance of this class.
|
||||
* @param aSize The suggested size.
|
||||
*/
|
||||
void SetSuggestedSize(const nsSize& aSize);
|
||||
|
||||
protected:
|
||||
nsresult GetDefaultLabel(nsXPIDLString& aLabel);
|
||||
|
||||
|
@ -112,6 +112,12 @@ nsGfxCheckboxControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr
|
||||
return nsFormControlFrame::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsGfxCheckboxControlFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced | eReplacedContainsBlock));
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
NS_IMETHODIMP nsGfxCheckboxControlFrame::GetAccessible(nsIAccessible** aAccessible)
|
||||
{
|
||||
@ -283,4 +289,3 @@ nsGfxCheckboxControlFrame::GetCheckboxState ( )
|
||||
elem->GetChecked(&retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,8 @@ public:
|
||||
nsGfxCheckboxControlFrame(nsStyleContext* aContext);
|
||||
virtual ~nsGfxCheckboxControlFrame();
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const {
|
||||
return MakeFrameName(NS_LITERAL_STRING("CheckboxControl"), aResult);
|
||||
|
@ -77,6 +77,12 @@ nsGfxRadioControlFrame::QueryInterface(const nsIID& aIID, void** aInstancePtr)
|
||||
return nsFormControlFrame::QueryInterface(aIID, aInstancePtr);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsGfxRadioControlFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced | eReplacedContainsBlock));
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
NS_IMETHODIMP nsGfxRadioControlFrame::GetAccessible(nsIAccessible** aAccessible)
|
||||
{
|
||||
|
@ -60,6 +60,8 @@ public:
|
||||
nsGfxRadioControlFrame(nsStyleContext* aContext);
|
||||
~nsGfxRadioControlFrame();
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
//nsIRadioControlFrame methods
|
||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||
NS_IMETHOD SetRadioButtonFaceStyleContext(nsStyleContext *aRadioButtonFaceStyleContext);
|
||||
|
@ -61,7 +61,6 @@
|
||||
#include "nsFormControlFrame.h"
|
||||
#include "nsFrameManager.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMHTMLButtonElement.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
@ -81,9 +80,6 @@ NS_NewHTMLButtonControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
nsHTMLButtonControlFrame::nsHTMLButtonControlFrame(nsStyleContext* aContext)
|
||||
: nsHTMLContainerFrame(aContext)
|
||||
{
|
||||
mCacheSize.width = -1;
|
||||
mCacheSize.height = -1;
|
||||
mCachedMaxElementWidth = -1;
|
||||
}
|
||||
|
||||
nsHTMLButtonControlFrame::~nsHTMLButtonControlFrame()
|
||||
@ -104,7 +100,9 @@ nsHTMLButtonControlFrame::Init(
|
||||
nsIFrame* aPrevInFlow)
|
||||
{
|
||||
nsresult rv = nsHTMLContainerFrame::Init(aContent, aParent, aPrevInFlow);
|
||||
mRenderer.SetFrame(this, GetPresContext());
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mRenderer.SetFrame(this, GetPresContext());
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -248,6 +246,51 @@ nsHTMLButtonControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
return DisplaySelectionOverlay(aBuilder, aLists);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsHTMLButtonControlFrame::GetMinWidth(nsIRenderingContext* aRenderingContext)
|
||||
{
|
||||
return DoGetMinWidth(aRenderingContext, PR_TRUE);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsHTMLButtonControlFrame::DoGetMinWidth(nsIRenderingContext* aRenderingContext,
|
||||
PRBool aZeroIfWidthSpecified)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
|
||||
// Note: to fix the button equivalent of bug 40596 while still working
|
||||
// correctly in general, we want to return our actual min width as our min
|
||||
// width if our style width is auto. Otherwise, we're ok with shrinking as
|
||||
// small as needed.
|
||||
if (!aZeroIfWidthSpecified ||
|
||||
GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto) {
|
||||
nsIFrame* kid = mFrames.FirstChild();
|
||||
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
|
||||
kid,
|
||||
nsLayoutUtils::MIN_WIDTH);
|
||||
|
||||
result += mRenderer.GetAddedButtonBorderAndPadding().LeftRight();
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsHTMLButtonControlFrame::GetPrefWidth(nsIRenderingContext* aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
|
||||
nsIFrame* kid = mFrames.FirstChild();
|
||||
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
|
||||
kid,
|
||||
nsLayoutUtils::PREF_WIDTH);
|
||||
result += mRenderer.GetAddedButtonBorderAndPadding().LeftRight();
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLButtonControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
@ -255,120 +298,62 @@ nsHTMLButtonControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLButtonControlFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLButtonControlFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
if (eReflowReason_Initial == aReflowState.reason) {
|
||||
NS_PRECONDITION(aReflowState.mComputedWidth != NS_INTRINSICSIZE,
|
||||
"Should have real computed width by now");
|
||||
|
||||
if (mState & NS_FRAME_FIRST_REFLOW) {
|
||||
nsFormControlFrame::RegUnRegAccessKey(NS_STATIC_CAST(nsIFrame*, this), PR_TRUE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
nsresult skiprv = nsFormControlFrame::SkipResizeReflow(mCacheSize, mCachedMaxElementWidth, aPresContext,
|
||||
aDesiredSize, aReflowState, aStatus);
|
||||
if (NS_SUCCEEDED(skiprv)) {
|
||||
return skiprv;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Reflow the child
|
||||
nsIFrame* firstKid = mFrames.FirstChild();
|
||||
nsSize availSize(aReflowState.mComputedWidth, NS_INTRINSICSIZE);
|
||||
|
||||
// Indent the child inside us by the focus border. We must do this separate from the
|
||||
// regular border.
|
||||
// XXXbz Eventually we may want to check-and-bail if
|
||||
// !aReflowState.ShouldReflowAllKids() &&
|
||||
// !(firstKid->GetStateBits() &
|
||||
// (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)).
|
||||
// We'd need to cache our ascent for that, of course.
|
||||
|
||||
nsMargin focusPadding = mRenderer.GetAddedButtonBorderAndPadding();
|
||||
|
||||
|
||||
if (NS_INTRINSICSIZE != availSize.width) {
|
||||
availSize.width -= focusPadding.left + focusPadding.right;
|
||||
availSize.width = PR_MAX(availSize.width,0);
|
||||
}
|
||||
if (NS_AUTOHEIGHT != availSize.height) {
|
||||
availSize.height -= focusPadding.top + focusPadding.bottom;
|
||||
availSize.height = PR_MAX(availSize.height,0);
|
||||
}
|
||||
|
||||
// XXX Proper handling of incremental reflow...
|
||||
nsReflowReason reason = aReflowState.reason;
|
||||
if (eReflowReason_Incremental == reason) {
|
||||
// See if it's targeted at us
|
||||
nsHTMLReflowCommand *command = aReflowState.path->mReflowCommand;
|
||||
if (command) {
|
||||
// I'm not sure what exactly this Invalidate is for
|
||||
Invalidate(nsRect(0,0,mRect.width,mRect.height), PR_FALSE);
|
||||
|
||||
nsReflowType reflowType;
|
||||
command->GetType(reflowType);
|
||||
if (eReflowType_StyleChanged == reflowType) {
|
||||
reason = eReflowReason_StyleChange;
|
||||
}
|
||||
else {
|
||||
reason = eReflowReason_Resize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reflow the contents of the button a first time.
|
||||
// Reflow the contents of the button.
|
||||
ReflowButtonContents(aPresContext, aDesiredSize, aReflowState, firstKid,
|
||||
availSize, reason, focusPadding, aStatus);
|
||||
focusPadding, aStatus);
|
||||
|
||||
// If we just performed the first pass of a shrink-wrap reflow (which will have
|
||||
// found the requested size of the children, but not placed them), perform
|
||||
// the second pass of a shrink-wrap reflow (which places the children
|
||||
// within this parent button which has now shrink-wrapped around them).
|
||||
if (availSize.width == NS_SHRINKWRAPWIDTH) {
|
||||
nsSize newAvailSize(aDesiredSize.width, NS_INTRINSICSIZE);
|
||||
|
||||
ReflowButtonContents(aPresContext, aDesiredSize, aReflowState, firstKid,
|
||||
newAvailSize, eReflowReason_Resize, focusPadding, aStatus);
|
||||
}
|
||||
|
||||
// If computed use the computed values.
|
||||
if (aReflowState.mComputedWidth != NS_INTRINSICSIZE)
|
||||
aDesiredSize.width = aReflowState.mComputedWidth;
|
||||
else
|
||||
aDesiredSize.width += focusPadding.left + focusPadding.right;
|
||||
aDesiredSize.width = aReflowState.mComputedWidth;
|
||||
|
||||
// If computed use the computed value.
|
||||
if (aReflowState.mComputedHeight != NS_INTRINSICSIZE)
|
||||
aDesiredSize.height = aReflowState.mComputedHeight;
|
||||
else
|
||||
aDesiredSize.height += focusPadding.top + focusPadding.bottom;
|
||||
aDesiredSize.height += focusPadding.TopBottom();
|
||||
|
||||
aDesiredSize.width += aReflowState.mComputedBorderPadding.LeftRight();
|
||||
aDesiredSize.height += aReflowState.mComputedBorderPadding.TopBottom();
|
||||
|
||||
|
||||
// Make sure we obey min/max-height. Note that we do this after adjusting
|
||||
// for borderpadding, since buttons have border-box sizing...
|
||||
|
||||
aDesiredSize.width += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right;
|
||||
aDesiredSize.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom;
|
||||
// XXXbz unless someone overrides that, of course! We should really consider
|
||||
// exposing nsHTMLReflowState::AdjustComputed* or something.
|
||||
aDesiredSize.height = NS_CSS_MINMAX(aDesiredSize.height,
|
||||
aReflowState.mComputedMinHeight,
|
||||
aReflowState.mComputedMaxHeight);
|
||||
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit());
|
||||
}
|
||||
|
||||
// Make sure we obey min/max-width and min/max-height
|
||||
if (aDesiredSize.width > aReflowState.mComputedMaxWidth) {
|
||||
aDesiredSize.width = aReflowState.mComputedMaxWidth;
|
||||
}
|
||||
if (aDesiredSize.width < aReflowState.mComputedMinWidth) {
|
||||
aDesiredSize.width = aReflowState.mComputedMinWidth;
|
||||
}
|
||||
|
||||
if (aDesiredSize.height > aReflowState.mComputedMaxHeight) {
|
||||
aDesiredSize.height = aReflowState.mComputedMaxHeight;
|
||||
}
|
||||
if (aDesiredSize.height < aReflowState.mComputedMinHeight) {
|
||||
aDesiredSize.height = aReflowState.mComputedMinHeight;
|
||||
}
|
||||
|
||||
aDesiredSize.ascent += aReflowState.mComputedBorderPadding.top + focusPadding.top;
|
||||
aDesiredSize.ascent +=
|
||||
aReflowState.mComputedBorderPadding.top + focusPadding.top;
|
||||
aDesiredSize.descent = aDesiredSize.height - aDesiredSize.ascent;
|
||||
|
||||
aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
||||
aDesiredSize.mOverflowArea =
|
||||
nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
||||
ConsiderChildOverflow(aDesiredSize.mOverflowArea, firstKid);
|
||||
FinishAndStoreOverflow(&aDesiredSize);
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
nsFormControlFrame::SetupCachedSizes(mCacheSize, mCachedAscent,
|
||||
mCachedMaxElementWidth, aDesiredSize);
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
return NS_OK;
|
||||
}
|
||||
@ -378,25 +363,48 @@ nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame* aFirstKid,
|
||||
const nsSize& aAvailSize,
|
||||
nsReflowReason aReason,
|
||||
nsMargin aFocusPadding,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
nsHTMLReflowState reflowState(aPresContext, aReflowState, aFirstKid, aAvailSize, aReason);
|
||||
nsSize availSize(aReflowState.mComputedWidth, NS_INTRINSICSIZE);
|
||||
|
||||
// Indent the child inside us by the focus border. We must do this separate
|
||||
// from the regular border.
|
||||
availSize.width -= aFocusPadding.LeftRight();
|
||||
availSize.width = PR_MAX(availSize.width,0);
|
||||
|
||||
// See whether out availSize's width is big enough. If it's smaller than our
|
||||
// intrinsic min width, that means that the kid wouldn't really fit; for a
|
||||
// better look in such cases we adjust the available width and our left
|
||||
// offset to allow the kid to spill left into our padding.
|
||||
nscoord xoffset = aFocusPadding.left + aReflowState.mComputedBorderPadding.left;
|
||||
nscoord extrawidth = DoGetMinWidth(aReflowState.rendContext, PR_FALSE) -
|
||||
aReflowState.mComputedWidth;
|
||||
if (extrawidth > 0) {
|
||||
nscoord extraleft = extrawidth / 2;
|
||||
nscoord extraright = extrawidth - extraleft;
|
||||
NS_ASSERTION(extraright >=0, "How'd that happen?");
|
||||
|
||||
// Do not allow the extras to be bigger than the relevant padding
|
||||
extraleft = PR_MIN(extraleft, aReflowState.mComputedPadding.left);
|
||||
extraright = PR_MIN(extraright, aReflowState.mComputedPadding.right);
|
||||
xoffset -= extraleft;
|
||||
availSize.width += extraleft + extraright;
|
||||
}
|
||||
|
||||
nsHTMLReflowState reflowState(aPresContext, aReflowState, aFirstKid,
|
||||
availSize);
|
||||
|
||||
ReflowChild(aFirstKid, aPresContext, aDesiredSize, reflowState,
|
||||
aFocusPadding.left + aReflowState.mComputedBorderPadding.left,
|
||||
xoffset,
|
||||
aFocusPadding.top + aReflowState.mComputedBorderPadding.top,
|
||||
0, aStatus);
|
||||
|
||||
// calculate the min internal size so the contents gets centered correctly
|
||||
// minInternalWidth is not being used at all and causes a warning--commenting
|
||||
// out until someone wants it.
|
||||
// nscoord minInternalWidth = aReflowState.mComputedMinWidth == 0?0:aReflowState.mComputedMinWidth -
|
||||
// (aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right);
|
||||
nscoord minInternalHeight = aReflowState.mComputedMinHeight == 0?0:aReflowState.mComputedMinHeight -
|
||||
(aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom);
|
||||
// calculate the min internal height so the contents gets centered correctly.
|
||||
// XXXbz this assumes border-box sizing.
|
||||
nscoord minInternalHeight = aReflowState.mComputedMinHeight -
|
||||
aReflowState.mComputedBorderPadding.TopBottom();
|
||||
minInternalHeight = PR_MAX(minInternalHeight, 0);
|
||||
|
||||
// center child vertically
|
||||
nscoord yoff = 0;
|
||||
@ -413,27 +421,6 @@ nsHTMLButtonControlFrame::ReflowButtonContents(nsPresContext* aPresContext,
|
||||
// baseline by that much).
|
||||
aDesiredSize.ascent += yoff;
|
||||
|
||||
// Place the child. If we have a non-intrinsic width, we want to
|
||||
// reduce the left padding as needed to try and fit the text in the
|
||||
// button
|
||||
nscoord xoffset = aFocusPadding.left + aReflowState.mComputedBorderPadding.left;
|
||||
if (aReflowState.mComputedWidth != NS_INTRINSICSIZE) {
|
||||
// First, how much did we "overflow"? This is the width of our
|
||||
// kid plus our special focus stuff (which did not get accounted
|
||||
// for in calculating aReflowState.mComputedWidth minus the width
|
||||
// we're forced to be.
|
||||
nscoord extrawidth =
|
||||
aDesiredSize.width + aFocusPadding.left + aFocusPadding.right
|
||||
- aReflowState.mComputedWidth;
|
||||
if (extrawidth > 0) {
|
||||
// Split it evenly between right and left
|
||||
extrawidth /= 2;
|
||||
// But do not shoot out the left side of the button, please
|
||||
extrawidth = PR_MIN(extrawidth, aReflowState.mComputedPadding.left);
|
||||
xoffset -= extrawidth;
|
||||
}
|
||||
}
|
||||
|
||||
// Place the child
|
||||
FinishReflowChild(aFirstKid, aPresContext, &reflowState, aDesiredSize,
|
||||
xoffset,
|
||||
@ -506,3 +493,9 @@ nsHTMLButtonControlFrame::RemoveFrame(nsIAtom* aListName,
|
||||
NS_NOTREACHED("unsupported operation");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLButtonControlFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced | eReplacedContainsBlock));
|
||||
}
|
||||
|
@ -71,6 +71,15 @@ public:
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
// Differs from GetMinWidth in that it allows one to specify whether
|
||||
// to fall back on 0 for the min width if we have a specified width.
|
||||
nscoord DoGetMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
PRBool aZeroIfWidthSpecified);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -122,6 +131,8 @@ public:
|
||||
return GetFirstChild(nsnull)->GetContentInsertionFrame();
|
||||
}
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
protected:
|
||||
virtual PRBool IsReset(PRInt32 type);
|
||||
virtual PRBool IsSubmit(PRInt32 type);
|
||||
@ -129,8 +140,6 @@ protected:
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIFrame* aFirstKid,
|
||||
const nsSize& aAvailSize,
|
||||
nsReflowReason aReason,
|
||||
nsMargin aFocusPadding,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
@ -139,11 +148,6 @@ protected:
|
||||
|
||||
PRIntn GetSkipSides() const;
|
||||
nsButtonFrameRenderer mRenderer;
|
||||
|
||||
//Resize Reflow OpitmizationSize;
|
||||
nsSize mCacheSize;
|
||||
nscoord mCachedAscent;
|
||||
nscoord mCachedMaxElementWidth;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -46,8 +46,8 @@ class nsIContent;
|
||||
|
||||
// IID for the nsIListControlFrame class
|
||||
#define NS_ILISTCONTROLFRAME_IID \
|
||||
{ 0xa28ca6f, 0x6850, 0x11da, \
|
||||
{ 0x95, 0x2c, 0x0, 0xe0, 0x81, 0x61, 0x16, 0x5f } }
|
||||
{ 0x4de9ab73, 0x31b5, 0x4d92, \
|
||||
{ 0xb7, 0xe4, 0x73, 0xb4, 0x4d, 0xcb, 0xfc, 0xda } }
|
||||
|
||||
/**
|
||||
* nsIListControlFrame is the interface for frame-based listboxes.
|
||||
@ -81,10 +81,10 @@ public:
|
||||
virtual void CaptureMouseEvents(PRBool aGrabMouseEvents) = 0;
|
||||
|
||||
/**
|
||||
* Returns the maximum width and height of an item in the listbox
|
||||
* Returns the height of a single row in the list. This is the
|
||||
* maximum of the heights of all the options/optgroups.
|
||||
*/
|
||||
|
||||
virtual nsSize GetMaximumSize() = 0;
|
||||
virtual nscoord GetHeightOfARow() = 0;
|
||||
|
||||
/**
|
||||
* Returns the number of options in the listbox
|
||||
@ -112,11 +112,6 @@ public:
|
||||
*/
|
||||
virtual void FireOnChange() = 0;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
virtual void SetOverrideReflowOptimization(PRBool aValue) = 0;
|
||||
|
||||
/**
|
||||
* Tell the selected list to roll up and ensure that the proper index is
|
||||
* selected, possibly firing onChange if the index has changed
|
||||
|
@ -84,6 +84,7 @@ public:
|
||||
nsEventStatus* aEventStatus);
|
||||
|
||||
virtual nsIAtom* GetType() const;
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
|
||||
@ -193,15 +194,21 @@ nsImageControlFrame::GetType() const
|
||||
return nsLayoutAtoms::imageControlFrame;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsImageControlFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced));
|
||||
}
|
||||
|
||||
NS_METHOD
|
||||
nsImageControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsImageControlFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsImageControlFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
if (aReflowState.reason == eReflowReason_Initial) {
|
||||
if (mState & NS_FRAME_FIRST_REFLOW) {
|
||||
nsFormControlFrame::RegUnRegAccessKey(NS_STATIC_CAST(nsIFrame*, this), PR_TRUE);
|
||||
}
|
||||
return nsImageControlFrameSuper::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
|
@ -267,23 +267,16 @@ nsIsIndexFrame::ScrollIntoView(nsPresContext* aPresContext)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsIsIndexFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
nscoord
|
||||
nsIsIndexFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsIsIndexFrame", aReflowState.reason);
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
|
||||
// The Areaframe takes care of all our reflow
|
||||
// (except for when style is used to change its size?)
|
||||
nsresult rv = nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit());
|
||||
}
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
return rv;
|
||||
// Our min width is our pref width; the rest of our reflow is
|
||||
// happily handled by nsAreaFrame
|
||||
result = GetPrefWidth(aRenderingContext);
|
||||
return result;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -84,11 +84,8 @@ public:
|
||||
// nsIFormControlFrame
|
||||
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aCX,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
virtual PRBool IsLeaf() const;
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
|
@ -99,11 +99,11 @@ nsLegendFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsLegendFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsLegendFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
if (eReflowReason_Initial == aReflowState.reason) {
|
||||
if (mState & NS_FRAME_FIRST_REFLOW) {
|
||||
nsFormControlFrame::RegUnRegAccessKey(NS_STATIC_CAST(nsIFrame*, this), PR_TRUE);
|
||||
}
|
||||
}
|
||||
return nsAreaFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,7 @@
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsSelectsAreaFrame.h"
|
||||
|
||||
class nsIDOMHTMLSelectElement;
|
||||
class nsIDOMHTMLOptionsCollection;
|
||||
@ -92,6 +93,9 @@ public:
|
||||
NS_IMETHOD SetInitialChildList(nsIAtom* aListName,
|
||||
nsIFrame* aChildList);
|
||||
|
||||
// Our min width is our pref width
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aCX,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -119,6 +123,10 @@ public:
|
||||
*/
|
||||
virtual nsIAtom* GetType() const;
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
virtual PRBool IsContainingBlock() const;
|
||||
|
||||
virtual void InvalidateInternal(const nsRect& aDamageRect,
|
||||
nscoord aX, nscoord aY, nsIFrame* aForChild,
|
||||
PRBool aImmediate);
|
||||
@ -148,12 +156,11 @@ public:
|
||||
virtual PRInt32 GetSelectedIndex();
|
||||
virtual void GetOptionText(PRInt32 aIndex, nsAString & aStr);
|
||||
virtual void CaptureMouseEvents(PRBool aGrabMouseEvents);
|
||||
virtual nsSize GetMaximumSize();
|
||||
virtual nscoord GetHeightOfARow();
|
||||
virtual PRInt32 GetNumberOfOptions();
|
||||
virtual void SyncViewWithFrame();
|
||||
virtual void AboutToDropDown();
|
||||
virtual void AboutToRollup();
|
||||
virtual void SetOverrideReflowOptimization(PRBool aValue) { mOverrideReflowOpt = aValue; }
|
||||
virtual void FireOnChange();
|
||||
virtual void ComboboxFinish(PRInt32 aIndex);
|
||||
virtual void OnContentReset();
|
||||
@ -190,11 +197,38 @@ public:
|
||||
static void ComboboxFocusSet();
|
||||
|
||||
// Helper
|
||||
void SetPassId(PRInt16 aId) { mPassId = aId; }
|
||||
|
||||
PRBool IsFocused() { return this == mFocused; }
|
||||
|
||||
/**
|
||||
* Function to paint the focus rect when our nsSelectsAreaFrame is painting.
|
||||
* @param aPt the offset of this frame, relative to the rendering reference
|
||||
* frame
|
||||
*/
|
||||
void PaintFocus(nsIRenderingContext& aRC, nsPoint aPt);
|
||||
|
||||
/**
|
||||
* Function to calculate the height a row, for use with the "size" attribute.
|
||||
* Can't be const because GetNumberOfOptions() isn't const.
|
||||
*/
|
||||
nscoord CalcHeightOfARow();
|
||||
|
||||
/**
|
||||
* Function to ask whether we're currently in what might be the
|
||||
* first pass of a two-pass reflow.
|
||||
*/
|
||||
PRBool MightNeedSecondPass() const {
|
||||
return mMightNeedSecondPass;
|
||||
}
|
||||
|
||||
void SetSuppressScrollbarUpdate(PRBool aSuppress) {
|
||||
nsHTMLScrollFrame::SetSuppressScrollbarUpdate(aSuppress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the list is in dropdown mode.
|
||||
*/
|
||||
PRBool IsInDropDownMode() const;
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
void FireMenuItemActiveEvent(); // Inform assistive tech what got focused
|
||||
#endif
|
||||
@ -232,9 +266,22 @@ protected:
|
||||
// we'll just guess at a row height based on our own style.
|
||||
nscoord CalcFallbackRowHeight(PRInt32 aNumOptions);
|
||||
|
||||
// CalcIntrinsicHeight computes our intrinsic height (taking the "size"
|
||||
// attribute into account). This should only be called in non-dropdown mode.
|
||||
nscoord CalcIntrinsicHeight(nscoord aHeightOfARow, PRInt32 aNumberOfOptions);
|
||||
|
||||
// Dropped down stuff
|
||||
void SetComboboxItem(PRInt32 aIndex);
|
||||
PRBool IsInDropDownMode() const;
|
||||
|
||||
/**
|
||||
* Method to reflow ourselves as a dropdown list. This differs from
|
||||
* reflow as a listbox because the criteria for needing a second
|
||||
* pass are different. This will be called from Reflow() as needed.
|
||||
*/
|
||||
nsresult ReflowAsDropdown(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
// Selection
|
||||
PRBool SetOptionsSelectedFromFrame(PRInt32 aStartIndex,
|
||||
@ -250,8 +297,12 @@ protected:
|
||||
PRBool HandleListSelection(nsIDOMEvent * aDOMEvent, PRInt32 selectedIndex);
|
||||
void InitSelectionRange(PRInt32 aClickedIndex);
|
||||
|
||||
nsIFrame* GetOptionsContainer() {
|
||||
return GetScrolledFrame();
|
||||
nsSelectsAreaFrame* GetOptionsContainer() const {
|
||||
return NS_STATIC_CAST(nsSelectsAreaFrame*, GetScrolledFrame());
|
||||
}
|
||||
|
||||
nscoord HeightOfARow() {
|
||||
return GetOptionsContainer()->HeightOfARow();
|
||||
}
|
||||
|
||||
// Data Members
|
||||
@ -259,8 +310,6 @@ protected:
|
||||
PRInt32 mEndSelectionIndex;
|
||||
|
||||
nsIComboboxControlFrame *mComboboxFrame;
|
||||
nscoord mMaxWidth;
|
||||
nscoord mMaxHeight;
|
||||
PRInt32 mNumDisplayRows;
|
||||
PRPackedBool mChangesSinceDragStart:1;
|
||||
PRPackedBool mButtonDown:1;
|
||||
@ -274,23 +323,20 @@ protected:
|
||||
PRPackedBool mNeedToReset:1;
|
||||
PRPackedBool mPostChildrenLoadedReset:1;
|
||||
|
||||
PRPackedBool mOverrideReflowOpt:1;
|
||||
|
||||
//bool value for multiple discontiguous selection
|
||||
PRPackedBool mControlSelectMode:1;
|
||||
|
||||
PRInt16 mPassId;
|
||||
nscoord mCachedDesiredMEW;
|
||||
// True if we're in the middle of a reflow and might need a second
|
||||
// pass. This only happens for auto heights.
|
||||
PRPackedBool mMightNeedSecondPass:1;
|
||||
|
||||
// The last computed height we reflowed at if we're a combobox dropdown.
|
||||
// XXXbz should we be using a subclass here? Or just not worry
|
||||
// about the extra member on listboxes?
|
||||
nscoord mLastDropdownComputedHeight;
|
||||
|
||||
nsRefPtr<nsListEventListener> mEventListener;
|
||||
|
||||
//Resize Reflow OpitmizationSize;
|
||||
nsSize mCacheSize;
|
||||
nscoord mCachedAscent;
|
||||
nscoord mCachedMaxElementWidth;
|
||||
nsSize mCachedUnconstrainedSize;
|
||||
nsSize mCachedAvailableSize;
|
||||
|
||||
static nsListControlFrame * mFocused;
|
||||
|
||||
#ifdef DO_REFLOW_COUNTER
|
||||
|
@ -229,3 +229,51 @@ nsSelectsAreaFrame::BuildDisplayListInternal(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSelectsAreaFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
nsListControlFrame* list = GetEnclosingListFrame(this);
|
||||
NS_ASSERTION(list,
|
||||
"Must have an nsListControlFrame! Frame constructor is "
|
||||
"broken");
|
||||
|
||||
PRBool isInDropdownMode = list->IsInDropDownMode();
|
||||
|
||||
// See similar logic in nsListControlFrame::Reflow and
|
||||
// nsListControlFrame::ReflowAsDropdown. We need to match it here.
|
||||
nscoord oldHeight;
|
||||
if (isInDropdownMode) {
|
||||
// Store the height now in case it changes during
|
||||
// nsAreaFrame::Reflow for some odd reason.
|
||||
if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
oldHeight = GetSize().height;
|
||||
} else {
|
||||
oldHeight = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult rv = nsAreaFrame::Reflow(aPresContext, aDesiredSize,
|
||||
aReflowState, aStatus);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Check whether we need to suppress scrolbar updates. We want to do that if
|
||||
// we're in a possible first pass and our height of a row has changed.
|
||||
if (list->MightNeedSecondPass()) {
|
||||
nscoord newHeightOfARow = list->CalcHeightOfARow();
|
||||
// We'll need a second pass if our height of a row changed. For
|
||||
// comboboxes, we'll also need it if our height changed. If we're going
|
||||
// to do a second pass, suppress scrollbar updates for this pass.
|
||||
if (newHeightOfARow != mHeightOfARow ||
|
||||
(isInDropdownMode && (oldHeight != aDesiredSize.height ||
|
||||
oldHeight != GetSize().height))) {
|
||||
mHeightOfARow = newHeightOfARow;
|
||||
list->SetSuppressScrollbarUpdate(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -62,11 +62,27 @@ public:
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aCX,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
static PRBool IsOptionElement(nsIContent* aContent);
|
||||
static PRBool IsOptionElementFrame(nsIFrame *aFrame);
|
||||
|
||||
nscoord HeightOfARow() const { return mHeightOfARow; }
|
||||
|
||||
protected:
|
||||
nsSelectsAreaFrame(nsStyleContext* aContext) : nsAreaFrame(aContext) {}
|
||||
nsSelectsAreaFrame(nsStyleContext* aContext) :
|
||||
nsAreaFrame(aContext),
|
||||
mHeightOfARow(0)
|
||||
{}
|
||||
|
||||
// We cache the height of a single row so that changes to the "size"
|
||||
// attribute, padding, etc. can all be handled with only one reflow. We'll
|
||||
// have to reflow twice if someone changes our font size or something like
|
||||
// that, so that the heights of our options will change.
|
||||
nscoord mHeightOfARow;
|
||||
};
|
||||
|
||||
#endif /* nsSelectsAreaFrame_h___ */
|
||||
|
@ -1292,23 +1292,78 @@ nsTextControlFrame::GetRows()
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextControlFrame::ReflowStandard(nsPresContext* aPresContext,
|
||||
nsSize& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
nsTextControlFrame::CalcIntrinsicSize(nsIRenderingContext* aRenderingContext,
|
||||
nsSize& aIntrinsicSize)
|
||||
{
|
||||
// get the css size and let the frame use or override it
|
||||
nsSize minSize;
|
||||
nsresult rv = CalculateSizeStandard(aPresContext, aReflowState,
|
||||
aDesiredSize, minSize);
|
||||
// Get leading and the Average/MaxAdvance char width
|
||||
nscoord lineHeight = 0;
|
||||
nscoord charWidth = 0;
|
||||
nscoord charMaxAdvance = 0;
|
||||
|
||||
nsCOMPtr<nsIFontMetrics> fontMet;
|
||||
nsresult rv =
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aRenderingContext->SetFont(fontMet);
|
||||
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
lineHeight = nsHTMLReflowState::CalcLineHeight(presContext,
|
||||
aRenderingContext,
|
||||
this);
|
||||
fontMet->GetAveCharWidth(charWidth);
|
||||
fontMet->GetMaxAdvance(charMaxAdvance);
|
||||
|
||||
// Set the width equal to the width in characters
|
||||
PRInt32 cols = GetCols();
|
||||
aIntrinsicSize.width = cols * charWidth;
|
||||
|
||||
// To better match IE, take the maximum character width(in twips) and remove
|
||||
// 4 pixels add this on as additional padding(internalPadding). But only do
|
||||
// this if charMaxAdvance != charWidth; if they are equal, this is almost
|
||||
// certainly a fixed-width font.
|
||||
if (charWidth != charMaxAdvance) {
|
||||
float p2t;
|
||||
p2t = presContext->PixelsToTwips();
|
||||
nscoord internalPadding = PR_MAX(charMaxAdvance - NSToCoordRound(4 * p2t), 0);
|
||||
// round to a multiple of p2t
|
||||
nscoord t = NSToCoordRound(p2t);
|
||||
nscoord rest = internalPadding % t;
|
||||
if (rest < t - rest) {
|
||||
internalPadding -= rest;
|
||||
} else {
|
||||
internalPadding += t - rest;
|
||||
}
|
||||
// Now add the extra padding on (so that small input sizes work well)
|
||||
aIntrinsicSize.width += internalPadding;
|
||||
} else {
|
||||
// This is to account for the anonymous <br> having a 1 twip width
|
||||
// in Full Standards mode, see BRFrame::Reflow and bug 228752.
|
||||
if (presContext->CompatibilityMode() == eCompatibility_FullStandards) {
|
||||
aIntrinsicSize.width += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment width with cols * letter-spacing.
|
||||
{
|
||||
const nsStyleCoord& lsCoord = GetStyleText()->mLetterSpacing;
|
||||
if (eStyleUnit_Coord == lsCoord.GetUnit()) {
|
||||
nscoord letterSpacing = lsCoord.GetCoordValue();
|
||||
if (letterSpacing != 0) {
|
||||
aIntrinsicSize.width += cols * letterSpacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the height equal to total number of rows (times the height of each
|
||||
// line, of course)
|
||||
aIntrinsicSize.height = lineHeight * GetRows();
|
||||
|
||||
// Add in the size of the scrollbars for textarea
|
||||
if (IsTextArea()) {
|
||||
float p2t;
|
||||
p2t = aPresContext->PixelsToTwips();
|
||||
p2t = presContext->PixelsToTwips();
|
||||
|
||||
nsIDeviceContext *dx = aPresContext->DeviceContext();
|
||||
nsIDeviceContext *dx = presContext->DeviceContext();
|
||||
|
||||
float scale;
|
||||
dx->GetCanonicalPixelScale(scale);
|
||||
@ -1320,96 +1375,10 @@ nsTextControlFrame::ReflowStandard(nsPresContext* aPresContext,
|
||||
nscoord scrollbarWidth = PRInt32(sbWidth * scale);
|
||||
nscoord scrollbarHeight = PRInt32(sbHeight * scale);
|
||||
|
||||
aDesiredSize.height += scrollbarHeight;
|
||||
minSize.height += scrollbarHeight;
|
||||
aIntrinsicSize.height += scrollbarHeight;
|
||||
|
||||
aDesiredSize.width += scrollbarWidth;
|
||||
minSize.width += scrollbarWidth;
|
||||
aIntrinsicSize.width += scrollbarWidth;
|
||||
}
|
||||
aDesiredSize.width += aReflowState.mComputedBorderPadding.left + aReflowState.mComputedBorderPadding.right;
|
||||
aDesiredSize.height += aReflowState.mComputedBorderPadding.top + aReflowState.mComputedBorderPadding.bottom;
|
||||
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
nsresult
|
||||
nsTextControlFrame::CalculateSizeStandard(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsSize& aDesiredSize,
|
||||
nsSize& aMinSize)
|
||||
{
|
||||
aDesiredSize.width = CSS_NOTSET;
|
||||
aDesiredSize.height = CSS_NOTSET;
|
||||
|
||||
// Get leading and the Average/MaxAdvance char width
|
||||
nscoord lineHeight = 0;
|
||||
nscoord charWidth = 0;
|
||||
nscoord charMaxAdvance = 0;
|
||||
|
||||
nsCOMPtr<nsIFontMetrics> fontMet;
|
||||
nsresult rv =
|
||||
nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsIRenderingContext* rendContext = aReflowState.rendContext;
|
||||
rendContext->SetFont(fontMet);
|
||||
lineHeight = aReflowState.CalcLineHeight(aPresContext, rendContext, this);
|
||||
fontMet->GetAveCharWidth(charWidth);
|
||||
fontMet->GetMaxAdvance(charMaxAdvance);
|
||||
|
||||
// Set the width equal to the width in characters
|
||||
PRInt32 cols = GetCols();
|
||||
aDesiredSize.width = cols * charWidth;
|
||||
|
||||
// To better match IE, take the maximum character width(in twips) and remove
|
||||
// 4 pixels add this on as additional padding(internalPadding). But only do
|
||||
// this if charMaxAdvance != charWidth; if they are equal, this is almost
|
||||
// certainly a fixed-width font.
|
||||
if (charWidth != charMaxAdvance) {
|
||||
float p2t;
|
||||
p2t = aPresContext->PixelsToTwips();
|
||||
nscoord internalPadding = PR_MAX(charMaxAdvance - NSToCoordRound(4 * p2t), 0);
|
||||
// round to a multiple of p2t
|
||||
nscoord t = NSToCoordRound(p2t);
|
||||
nscoord rest = internalPadding % t;
|
||||
if (rest < t - rest) {
|
||||
internalPadding -= rest;
|
||||
} else {
|
||||
internalPadding += t - rest;
|
||||
}
|
||||
// Now add the extra padding on (so that small input sizes work well)
|
||||
aDesiredSize.width += internalPadding;
|
||||
} else {
|
||||
// This is to account for the anonymous <br> having a 1 twip width
|
||||
// in Full Standards mode, see BRFrame::Reflow and bug 228752.
|
||||
if (aPresContext->CompatibilityMode() == eCompatibility_FullStandards) {
|
||||
aDesiredSize.width += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Increment width with cols * letter-spacing.
|
||||
{
|
||||
const nsStyleCoord& lsCoord = GetStyleText()->mLetterSpacing;
|
||||
if (eStyleUnit_Coord == lsCoord.GetUnit()) {
|
||||
nscoord letterSpacing = lsCoord.GetCoordValue();
|
||||
if (letterSpacing != 0) {
|
||||
aDesiredSize.width += cols * letterSpacing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the height equal to total number of rows (times the height of each
|
||||
// line, of course)
|
||||
aDesiredSize.height = lineHeight * GetRows();
|
||||
|
||||
// Set minimum size equal to desired size. We are form controls. We are Gods
|
||||
// among elements. We do not yield for anybody, not even a table cell. None
|
||||
// shall pass.
|
||||
aMinSize.width = aDesiredSize.width;
|
||||
aMinSize.height = aDesiredSize.height;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1783,13 +1752,33 @@ nsTextControlFrame::CreateAnonymousContent(nsPresContext* aPresContext,
|
||||
return aChildList.AppendElement(divContent);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsTextControlFrame::GetMinWidth(nsIRenderingContext* aRenderingContext)
|
||||
{
|
||||
// Note: to fix bug 40596 while still working correctly in general, we want
|
||||
// to return our preferred width as our min width if our style width is auto.
|
||||
// Otherwise, we're ok with shrinking as small as needed.
|
||||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
|
||||
if (GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto) {
|
||||
result = GetPrefWidth(aRenderingContext);
|
||||
} else {
|
||||
result = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// We inherit our GetPrefWidth from nsBoxFrame
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsTextControlFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsTextControlFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
// make sure the the form registers itself on the initial/first reflow
|
||||
@ -1797,19 +1786,8 @@ nsTextControlFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsFormControlFrame::RegUnRegAccessKey(this, PR_TRUE);
|
||||
}
|
||||
|
||||
nsresult rv = nsStackFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{ // fix for bug 40596, width:auto means the control sets it's mMaxElementWidth to it's default width
|
||||
if (aDesiredSize.mComputeMEW)
|
||||
{
|
||||
const nsStylePosition* stylePosition = GetStylePosition();
|
||||
nsStyleUnit widthUnit = stylePosition->mWidth.GetUnit();
|
||||
if (eStyleUnit_Auto == widthUnit) {
|
||||
aDesiredSize.mMaxElementWidth = aDesiredSize.width;
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
return nsStackFrame::Reflow(aPresContext, aDesiredSize, aReflowState,
|
||||
aStatus);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1827,24 +1805,15 @@ nsTextControlFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize)
|
||||
aSize.width = 0;
|
||||
aSize.height = 0;
|
||||
|
||||
// XXXbz this is almost certainly wrong.
|
||||
PRBool collapsed = PR_FALSE;
|
||||
IsCollapsed(aState, collapsed);
|
||||
if (collapsed)
|
||||
return NS_OK;
|
||||
|
||||
nsPresContext* presContext = aState.PresContext();
|
||||
const nsHTMLReflowState* reflowState = aState.GetReflowState();
|
||||
// XXXldb Is there a good reason to think this is both non-null and the
|
||||
// correct reflow state?
|
||||
if (!reflowState)
|
||||
return NS_OK;
|
||||
|
||||
nsSize styleSize(CSS_NOTSET,CSS_NOTSET);
|
||||
nsFormControlFrame::GetStyleSize(presContext, *reflowState, styleSize);
|
||||
|
||||
nsReflowStatus status;
|
||||
nsresult rv = ReflowStandard(presContext, aSize, *reflowState, status);
|
||||
nsresult rv = CalcIntrinsicSize(aState.GetRenderingContext(), aSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
AddBorderAndPadding(aSize);
|
||||
AddInset(aSize);
|
||||
|
||||
mPrefSize = aSize;
|
||||
@ -1869,18 +1838,14 @@ nsTextControlFrame::GetPrefSize(nsBoxLayoutState& aState, nsSize& aSize)
|
||||
NS_IMETHODIMP
|
||||
nsTextControlFrame::GetMinSize(nsBoxLayoutState& aState, nsSize& aSize)
|
||||
{
|
||||
#define FIX_FOR_BUG_40596
|
||||
#ifdef FIX_FOR_BUG_40596
|
||||
aSize = mMinSize;
|
||||
return NS_OK;
|
||||
#else
|
||||
// XXXbz why? Why not the nsBoxFrame sizes?
|
||||
return nsBox::GetMinSize(aState, aSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextControlFrame::GetMaxSize(nsBoxLayoutState& aState, nsSize& aSize)
|
||||
{
|
||||
// XXXbz why? Why not the nsBoxFrame sizes?
|
||||
return nsBox::GetMaxSize(aState, aSize);
|
||||
}
|
||||
|
||||
@ -1892,7 +1857,9 @@ nsTextControlFrame::GetAscent(nsBoxLayoutState& aState, nscoord& aAscent)
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Now adjust the ascent for our borders and padding
|
||||
aAscent += aState.GetReflowState()->mComputedBorderPadding.top;
|
||||
nsMargin borderPadding;
|
||||
GetBorderAndPadding(borderPadding);
|
||||
aAscent += borderPadding.top;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1903,7 +1870,11 @@ nsTextControlFrame::IsLeaf() const
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsTextControlFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced | eReplacedContainsBlock));
|
||||
}
|
||||
|
||||
static PRBool
|
||||
IsFocusedContent(nsPresContext* aPresContext, nsIContent* aContent)
|
||||
|
@ -79,6 +79,8 @@ public:
|
||||
|
||||
virtual void Destroy();
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext* aRenderingContext);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -105,6 +107,8 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
// from nsIAnonymousContentCreator
|
||||
NS_IMETHOD CreateAnonymousContent(nsPresContext* aPresContext,
|
||||
nsISupportsArray& aChildList);
|
||||
@ -252,15 +256,11 @@ protected:
|
||||
*/
|
||||
PRInt32 GetRows();
|
||||
|
||||
nsresult ReflowStandard(nsPresContext* aPresContext,
|
||||
nsSize& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
nsresult CalculateSizeStandard(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsSize& aDesiredSize,
|
||||
nsSize& aMinSize);
|
||||
// Compute our intrinsic size. This does not include any borders, paddings,
|
||||
// etc. Just the size of our actual area for the text (and the scrollbars,
|
||||
// for <textarea>).
|
||||
nsresult CalcIntrinsicSize(nsIRenderingContext* aRenderingContext,
|
||||
nsSize& aIntrinsicSize);
|
||||
|
||||
// nsIScrollableViewProvider
|
||||
virtual nsIScrollableView* GetScrollableView();
|
||||
@ -275,9 +275,6 @@ private:
|
||||
private:
|
||||
nsCOMPtr<nsIEditor> mEditor;
|
||||
|
||||
//cached sizes and states
|
||||
nsSize mSize;
|
||||
|
||||
// these packed bools could instead use the high order bits on mState, saving 4 bytes
|
||||
PRPackedBool mUseEditor;
|
||||
PRPackedBool mIsProcessing;
|
||||
|
@ -105,7 +105,6 @@ EXPORTS = \
|
||||
nsIScrollableFrame.h \
|
||||
nsIScrollableViewProvider.h \
|
||||
nsIStatefulFrame.h \
|
||||
nsReflowType.h \
|
||||
nsFrameSelection.h \
|
||||
$(NULL)
|
||||
|
||||
@ -138,7 +137,6 @@ CPPSRCS = \
|
||||
nsHTMLCanvasFrame.cpp \
|
||||
nsHTMLContainerFrame.cpp \
|
||||
nsHTMLFrame.cpp \
|
||||
nsHTMLReflowCommand.cpp \
|
||||
nsHTMLReflowState.cpp \
|
||||
nsImageFrame.cpp \
|
||||
nsImageMap.cpp \
|
||||
@ -151,7 +149,6 @@ CPPSRCS = \
|
||||
nsPageContentFrame.cpp \
|
||||
nsPageFrame.cpp \
|
||||
nsPlaceholderFrame.cpp \
|
||||
nsReflowPath.cpp \
|
||||
nsSelection.cpp \
|
||||
nsSimplePageSequence.cpp \
|
||||
nsSpaceManager.cpp \
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsAbsoluteContainingBlock.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsIViewManager.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsIPresShell.h"
|
||||
@ -91,10 +90,11 @@ nsAbsoluteContainingBlock::AppendFrames(nsIFrame* aDelegatingFrame,
|
||||
#endif
|
||||
mAbsoluteFrames.AppendFrames(nsnull, aFrameList);
|
||||
|
||||
// Generate a reflow command to reflow the dirty frames
|
||||
aDelegatingFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
|
||||
// no damage to intrinsic widths, since absolutely positioned frames can't
|
||||
// change them
|
||||
return aDelegatingFrame->GetPresContext()->PresShell()->
|
||||
AppendReflowCommand(aDelegatingFrame, eReflowType_ReflowDirty,
|
||||
GetChildListName());
|
||||
FrameNeedsReflow(aDelegatingFrame, nsIPresShell::eResize);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -112,10 +112,11 @@ nsAbsoluteContainingBlock::InsertFrames(nsIFrame* aDelegatingFrame,
|
||||
#endif
|
||||
mAbsoluteFrames.InsertFrames(nsnull, aPrevFrame, aFrameList);
|
||||
|
||||
// Generate a reflow command to reflow the dirty frames
|
||||
aDelegatingFrame->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
|
||||
// no damage to intrinsic widths, since absolutely positioned frames can't
|
||||
// change them
|
||||
return aDelegatingFrame->GetPresContext()->PresShell()->
|
||||
AppendReflowCommand(aDelegatingFrame, eReflowType_ReflowDirty,
|
||||
GetChildListName());
|
||||
FrameNeedsReflow(aDelegatingFrame, nsIPresShell::eResize);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -158,104 +159,33 @@ nsAbsoluteContainingBlock::Reflow(nsIFrame* aDelegatingFrame,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight,
|
||||
nsRect* aChildBounds,
|
||||
PRBool aForceReflow,
|
||||
PRBool aCBWidthChanged,
|
||||
PRBool aCBHeightChanged)
|
||||
PRBool aCBHeightChanged,
|
||||
nsRect* aChildBounds)
|
||||
{
|
||||
// Initialize OUT parameter
|
||||
if (aChildBounds)
|
||||
aChildBounds->SetRect(0, 0, 0, 0);
|
||||
|
||||
// Make a copy of the reflow state. If the reason is
|
||||
// eReflowReason_Incremental (which should mean either that the target
|
||||
// is the frame for which this is the absolute container or that the
|
||||
// container changed size due to incremental reflow of its children),
|
||||
// then change it to eReflowReason_Resize.
|
||||
// XXXldb If the target is this frame, shouldn't we be setting it
|
||||
// appropriately (which might mean to StyleChanged)?
|
||||
nsHTMLReflowState reflowState(aReflowState);
|
||||
if (eReflowReason_Incremental == reflowState.reason) {
|
||||
reflowState.reason = eReflowReason_Resize;
|
||||
}
|
||||
PRBool reflowAll = aReflowState.ShouldReflowAllKids();
|
||||
|
||||
nsIFrame* kidFrame;
|
||||
for (kidFrame = mAbsoluteFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) {
|
||||
if (!aForceReflow &&
|
||||
!FrameDependsOnContainer(kidFrame, aCBWidthChanged, aCBHeightChanged)) {
|
||||
// Skip this frame, but add it in to the child bounds as needed
|
||||
AddFrameToChildBounds(kidFrame, aChildBounds);
|
||||
continue;
|
||||
if (reflowAll ||
|
||||
(kidFrame->GetStateBits() &
|
||||
(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) ||
|
||||
FrameDependsOnContainer(kidFrame, aCBWidthChanged, aCBHeightChanged)) {
|
||||
// Reflow the frame
|
||||
nsReflowStatus kidStatus;
|
||||
ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, aContainingBlockWidth,
|
||||
aContainingBlockHeight, kidFrame, kidStatus);
|
||||
|
||||
}
|
||||
nsReflowReason reason = reflowState.reason;
|
||||
|
||||
nsFrameState kidState = kidFrame->GetStateBits();
|
||||
if (NS_FRAME_FIRST_REFLOW & kidState) {
|
||||
// The frame has never had a reflow, so change the reason to eReflowReason_Initial
|
||||
reason = eReflowReason_Initial;
|
||||
|
||||
} else if (NS_FRAME_IS_DIRTY & kidState) {
|
||||
// The frame is dirty so give it the correct reflow reason
|
||||
reason = eReflowReason_Dirty;
|
||||
}
|
||||
|
||||
// Reflow the frame
|
||||
nsReflowStatus kidStatus;
|
||||
ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, reflowState, aContainingBlockWidth,
|
||||
aContainingBlockHeight, kidFrame, reason, kidStatus);
|
||||
|
||||
AddFrameToChildBounds(kidFrame, aChildBounds);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsAbsoluteContainingBlock::CalculateChildBounds(nsPresContext* aPresContext,
|
||||
nsRect& aChildBounds)
|
||||
{
|
||||
// Initialize the OUT parameters
|
||||
aChildBounds.SetRect(0, 0, 0, 0);
|
||||
|
||||
for (nsIFrame* f = mAbsoluteFrames.FirstChild(); f; f = f->GetNextSibling()) {
|
||||
AddFrameToChildBounds(f, &aChildBounds);
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsAbsoluteContainingBlock::ReflowingAbsolutesOnly(nsIFrame* aDelegatingFrame,
|
||||
const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
// See if the reflow command is targeted at us.
|
||||
nsReflowPath *path = aReflowState.path;
|
||||
nsHTMLReflowCommand *command = path->mReflowCommand;
|
||||
|
||||
if (command) {
|
||||
// It's targeted at us. See if it's for the positioned child frames
|
||||
if (GetChildListName() != command->GetChildListName()) {
|
||||
// A reflow command is targeted directly at this block.
|
||||
// The block will have to do a proper reflow.
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
nsReflowPath::iterator iter = path->FirstChild();
|
||||
nsReflowPath::iterator end = path->EndChildren();
|
||||
|
||||
if (iter != end && mAbsoluteFrames.NotEmpty()) {
|
||||
for ( ; iter != end; ++iter) {
|
||||
// See if it's one of our absolutely positioned child frames
|
||||
if (!mAbsoluteFrames.ContainsFrame(*iter)) {
|
||||
// At least one of the frames along the reflow path wasn't
|
||||
// absolutely positioned, so we'll need to deal with it in
|
||||
// normal block reflow.
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static PRBool IsFixedPaddingSize(nsStyleUnit aUnit) {
|
||||
return aUnit == eStyleUnit_Coord || aUnit == eStyleUnit_Null;
|
||||
}
|
||||
@ -363,64 +293,6 @@ nsAbsoluteContainingBlock::FrameDependsOnContainer(nsIFrame* f,
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsAbsoluteContainingBlock::IncrementalReflow(nsIFrame* aDelegatingFrame,
|
||||
nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight)
|
||||
{
|
||||
// See if the reflow command is targeted at us.
|
||||
nsReflowPath *path = aReflowState.path;
|
||||
nsHTMLReflowCommand *command = path->mReflowCommand;
|
||||
|
||||
if (command) {
|
||||
// It's targeted at us. See if it's for the positioned child frames
|
||||
if (GetChildListName() == command->GetChildListName()) {
|
||||
// The only type of reflow command we expect is that we have dirty
|
||||
// child frames to reflow
|
||||
NS_ASSERTION(command->Type() == eReflowType_ReflowDirty,
|
||||
"unexpected reflow type");
|
||||
|
||||
// Walk the positioned frames and reflow the dirty frames
|
||||
for (nsIFrame* f = mAbsoluteFrames.FirstChild(); f; f = f->GetNextSibling()) {
|
||||
nsFrameState frameState = f->GetStateBits();
|
||||
|
||||
if (frameState & NS_FRAME_IS_DIRTY) {
|
||||
nsReflowStatus status;
|
||||
nsReflowReason reason;
|
||||
|
||||
reason = (frameState & NS_FRAME_FIRST_REFLOW)
|
||||
? eReflowReason_Initial
|
||||
: eReflowReason_Dirty;
|
||||
|
||||
ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState,
|
||||
aContainingBlockWidth, aContainingBlockHeight, f,
|
||||
reason, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsReflowPath::iterator iter = path->FirstChild();
|
||||
nsReflowPath::iterator end = path->EndChildren();
|
||||
|
||||
if (iter != end && mAbsoluteFrames.NotEmpty()) {
|
||||
for ( ; iter != end; ++iter) {
|
||||
// See if it's one of our absolutely positioned child frames
|
||||
if (mAbsoluteFrames.ContainsFrame(*iter)) {
|
||||
// Remove the next frame from the reflow path
|
||||
nsReflowStatus kidStatus;
|
||||
ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState,
|
||||
aContainingBlockWidth, aContainingBlockHeight, *iter,
|
||||
aReflowState.reason, kidStatus);
|
||||
|
||||
aReflowState.path->Remove(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAbsoluteContainingBlock::DestroyFrames(nsIFrame* aDelegatingFrame)
|
||||
{
|
||||
@ -442,7 +314,6 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight,
|
||||
nsIFrame* aKidFrame,
|
||||
nsReflowReason aReason,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
@ -457,16 +328,7 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat
|
||||
printf("%s ", NS_LossyConvertUTF16toASCII(name).get());
|
||||
}
|
||||
}
|
||||
printf("r=%d",aReflowState.reason);
|
||||
|
||||
if (aReflowState.reason == eReflowReason_Incremental) {
|
||||
nsHTMLReflowCommand *command = aReflowState.path->mReflowCommand;
|
||||
|
||||
if (command) {
|
||||
// We're the target.
|
||||
printf("(%d)", command->Type());
|
||||
}
|
||||
}
|
||||
char width[16];
|
||||
char height[16];
|
||||
PrettyUC(aReflowState.availableWidth, width);
|
||||
@ -483,207 +345,137 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat
|
||||
// Get the border values
|
||||
const nsMargin& border = aReflowState.mStyleBorder->GetBorder();
|
||||
|
||||
nscoord availWidth = aReflowState.mComputedWidth;
|
||||
enum { NOT_SHRINK_TO_FIT, SHRINK_TO_FIT_AVAILWIDTH, SHRINK_TO_FIT_MEW };
|
||||
PRUint32 situation = NOT_SHRINK_TO_FIT;
|
||||
while (1) {
|
||||
nsHTMLReflowMetrics kidDesiredSize(nsnull);
|
||||
if (situation == NOT_SHRINK_TO_FIT &&
|
||||
!(aKidFrame->GetStateBits() & NS_FRAME_REPLACED_ELEMENT)) {
|
||||
// CSS2.1 10.3.7 width:auto and at least one of left/right is auto...
|
||||
const nsStylePosition* stylePosition = aKidFrame->GetStylePosition();
|
||||
if (eStyleUnit_Auto == stylePosition->mWidth.GetUnit() &&
|
||||
(eStyleUnit_Auto == stylePosition->mOffset.GetLeftUnit() ||
|
||||
eStyleUnit_Auto == stylePosition->mOffset.GetRightUnit())) {
|
||||
situation = SHRINK_TO_FIT_AVAILWIDTH;
|
||||
if (aContainingBlockWidth != -1) {
|
||||
availWidth = aContainingBlockWidth;
|
||||
} else {
|
||||
availWidth = aReflowState.mComputedWidth;
|
||||
}
|
||||
kidDesiredSize.mComputeMEW = PR_TRUE;
|
||||
}
|
||||
nscoord availWidth = aContainingBlockWidth;
|
||||
if (availWidth == -1) {
|
||||
NS_ASSERTION(aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE,
|
||||
"Must have a useful width _somewhere_");
|
||||
availWidth =
|
||||
aReflowState.mComputedWidth + aReflowState.mComputedPadding.LeftRight();
|
||||
}
|
||||
|
||||
nsHTMLReflowMetrics kidDesiredSize;
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame,
|
||||
nsSize(availWidth, NS_UNCONSTRAINEDSIZE),
|
||||
aContainingBlockWidth,
|
||||
aContainingBlockHeight);
|
||||
|
||||
// Send the WillReflow() notification and position the frame
|
||||
aKidFrame->WillReflow(aPresContext);
|
||||
|
||||
// XXXldb We can simplify this if we come up with a better way to
|
||||
// position views.
|
||||
nscoord x;
|
||||
if (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left) {
|
||||
// Just use the current x-offset
|
||||
x = aKidFrame->GetPosition().x;
|
||||
} else {
|
||||
x = border.left + kidReflowState.mComputedOffsets.left + kidReflowState.mComputedMargin.left;
|
||||
}
|
||||
aKidFrame->SetPosition(nsPoint(x, border.top +
|
||||
kidReflowState.mComputedOffsets.top +
|
||||
kidReflowState.mComputedMargin.top));
|
||||
|
||||
// Position its view, but don't bother it doing it now if we haven't
|
||||
// yet determined the left offset
|
||||
if (NS_AUTOOFFSET != kidReflowState.mComputedOffsets.left) {
|
||||
nsContainerFrame::PositionFrameView(aKidFrame);
|
||||
}
|
||||
|
||||
// Do the reflow
|
||||
rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus);
|
||||
|
||||
// If we're solving for 'left' or 'top', then compute it now that we know the
|
||||
// width/height
|
||||
if ((NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left) ||
|
||||
(NS_AUTOOFFSET == kidReflowState.mComputedOffsets.top)) {
|
||||
if (-1 == aContainingBlockWidth) {
|
||||
// Get the containing block width/height
|
||||
kidReflowState.ComputeContainingBlockRectangle(aPresContext,
|
||||
&aReflowState,
|
||||
aContainingBlockWidth,
|
||||
aContainingBlockHeight);
|
||||
}
|
||||
|
||||
nsSize availSize(availWidth, NS_UNCONSTRAINEDSIZE);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame,
|
||||
availSize, aContainingBlockWidth,
|
||||
aContainingBlockHeight,
|
||||
aReason);
|
||||
|
||||
if (situation == SHRINK_TO_FIT_MEW) {
|
||||
situation = NOT_SHRINK_TO_FIT; // This is the last reflow
|
||||
kidReflowState.mComputedWidth = PR_MIN(availWidth, kidReflowState.mComputedMaxWidth);
|
||||
if (kidReflowState.mComputedWidth < kidReflowState.mComputedMinWidth) {
|
||||
kidReflowState.mComputedWidth = kidReflowState.mComputedMinWidth;
|
||||
}
|
||||
} else if (situation == SHRINK_TO_FIT_AVAILWIDTH) {
|
||||
NS_ASSERTION(availWidth != NS_UNCONSTRAINEDSIZE,
|
||||
"shrink-to-fit: expected a constrained available width");
|
||||
PRInt32 maxWidth = availWidth -
|
||||
(kidReflowState.mComputedMargin.left + kidReflowState.mComputedBorderPadding.left +
|
||||
kidReflowState.mComputedBorderPadding.right + kidReflowState.mComputedMargin.right);
|
||||
if (NS_AUTOOFFSET != kidReflowState.mComputedOffsets.right) {
|
||||
maxWidth -= kidReflowState.mComputedOffsets.right;
|
||||
}
|
||||
if (NS_AUTOOFFSET != kidReflowState.mComputedOffsets.left) {
|
||||
maxWidth -= kidReflowState.mComputedOffsets.left;
|
||||
}
|
||||
// The following also takes care of maxWidth<0
|
||||
if (kidReflowState.mComputedMaxWidth > maxWidth) {
|
||||
kidReflowState.mComputedMaxWidth = PR_MAX(maxWidth, kidReflowState.mComputedMinWidth);
|
||||
}
|
||||
}
|
||||
|
||||
// Send the WillReflow() notification and position the frame
|
||||
aKidFrame->WillReflow(aPresContext);
|
||||
|
||||
// XXXldb We can simplify this if we come up with a better way to
|
||||
// position views.
|
||||
nscoord x;
|
||||
if (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left) {
|
||||
// Just use the current x-offset
|
||||
x = aKidFrame->GetPosition().x;
|
||||
} else {
|
||||
x = border.left + kidReflowState.mComputedOffsets.left + kidReflowState.mComputedMargin.left;
|
||||
NS_ASSERTION(NS_AUTOOFFSET != kidReflowState.mComputedOffsets.right,
|
||||
"Can't solve for both left and right");
|
||||
kidReflowState.mComputedOffsets.left = aContainingBlockWidth -
|
||||
kidReflowState.mComputedOffsets.right -
|
||||
kidReflowState.mComputedMargin.right -
|
||||
kidDesiredSize.width -
|
||||
kidReflowState.mComputedMargin.left;
|
||||
}
|
||||
aKidFrame->SetPosition(nsPoint(x, border.top +
|
||||
kidReflowState.mComputedOffsets.top +
|
||||
kidReflowState.mComputedMargin.top));
|
||||
|
||||
// Position its view, but don't bother it doing it now if we haven't
|
||||
// yet determined the left offset
|
||||
if (NS_AUTOOFFSET != kidReflowState.mComputedOffsets.left) {
|
||||
nsContainerFrame::PositionFrameView(aKidFrame);
|
||||
if (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.top) {
|
||||
kidReflowState.mComputedOffsets.top = aContainingBlockHeight -
|
||||
kidReflowState.mComputedOffsets.bottom -
|
||||
kidReflowState.mComputedMargin.bottom -
|
||||
kidDesiredSize.height -
|
||||
kidReflowState.mComputedMargin.top;
|
||||
}
|
||||
}
|
||||
|
||||
// Do the reflow
|
||||
rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus);
|
||||
// Position the child relative to our padding edge
|
||||
nsRect rect(border.left + kidReflowState.mComputedOffsets.left + kidReflowState.mComputedMargin.left,
|
||||
border.top + kidReflowState.mComputedOffsets.top + kidReflowState.mComputedMargin.top,
|
||||
kidDesiredSize.width, kidDesiredSize.height);
|
||||
nsRect oldRect = aKidFrame->GetRect();
|
||||
aKidFrame->SetRect(rect);
|
||||
|
||||
if (situation == SHRINK_TO_FIT_AVAILWIDTH) {
|
||||
// ...continued CSS2.1 10.3.7 width:auto and at least one of left/right is auto
|
||||
availWidth -= kidReflowState.mComputedMargin.left + kidReflowState.mComputedMargin.right;
|
||||
// Size and position the view and set its opacity, visibility, content
|
||||
// transparency, and clip
|
||||
nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame,
|
||||
aKidFrame->GetView(),
|
||||
&kidDesiredSize.mOverflowArea);
|
||||
// if the frame moved, then the view would have invalidated everything so
|
||||
// we don't need to do any invalidation here.
|
||||
if (oldRect.TopLeft() == rect.TopLeft() &&
|
||||
!(aDelegatingFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
|
||||
oldRect.Size() != rect.Size()) {
|
||||
// Invalidate the area where the frame changed size. We can't
|
||||
// rely on the view to do this ... the view size might not change even
|
||||
// though the frame size changed (and besides, views will go away).
|
||||
// Invalidate the vertical strip
|
||||
nscoord innerWidth = PR_MIN(oldRect.width, rect.width);
|
||||
nscoord innerHeight = PR_MIN(oldRect.height, rect.height);
|
||||
nscoord outerWidth = PR_MAX(oldRect.width, rect.width);
|
||||
nscoord outerHeight = PR_MAX(oldRect.height, rect.height);
|
||||
aKidFrame->GetParent()->Invalidate(
|
||||
nsRect(rect.x + innerWidth, rect.y, outerWidth - innerWidth, outerHeight));
|
||||
// Invalidate the horizontal strip
|
||||
aKidFrame->GetParent()->Invalidate(
|
||||
nsRect(rect.x, rect.y + innerHeight, outerWidth, outerHeight - innerHeight));
|
||||
}
|
||||
aKidFrame->DidReflow(aPresContext, &kidReflowState, NS_FRAME_REFLOW_FINISHED);
|
||||
|
||||
if (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.right) {
|
||||
NS_ASSERTION(NS_AUTOOFFSET != kidReflowState.mComputedOffsets.left,
|
||||
"Can't solve for both left and right");
|
||||
availWidth -= kidReflowState.mComputedOffsets.left;
|
||||
} else {
|
||||
NS_ASSERTION(NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left,
|
||||
"Expected to solve for left");
|
||||
availWidth -= kidReflowState.mComputedOffsets.right;
|
||||
}
|
||||
if (availWidth < 0) {
|
||||
availWidth = 0;
|
||||
}
|
||||
// If the frame has visible overflow, then store it as a property on the
|
||||
// frame. This allows us to be able to recover it without having to reflow
|
||||
// the frame
|
||||
if (aKidFrame->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
||||
// Get the property (creating a rect struct if necessary)
|
||||
nsRect* overflowArea = aKidFrame->GetOverflowAreaProperty(PR_TRUE);
|
||||
|
||||
// Shrink-to-fit: min(max(preferred minimum width, available width), preferred width).
|
||||
// XXX this is not completely correct - see bug 201897 comment 56/58 and bug 268499.
|
||||
if (kidDesiredSize.mMaxElementWidth > availWidth) {
|
||||
aKidFrame->DidReflow(aPresContext, &kidReflowState, NS_FRAME_REFLOW_FINISHED);
|
||||
availWidth = PR_MAX(0, kidDesiredSize.mMaxElementWidth -
|
||||
kidReflowState.mComputedBorderPadding.left -
|
||||
kidReflowState.mComputedBorderPadding.right);
|
||||
situation = SHRINK_TO_FIT_MEW;
|
||||
aReason = eReflowReason_Resize;
|
||||
continue; // Do a second reflow constrained to MEW.
|
||||
}
|
||||
}
|
||||
|
||||
// If we're solving for 'left' or 'top', then compute it now that we know the
|
||||
// width/height
|
||||
if ((NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left) ||
|
||||
(NS_AUTOOFFSET == kidReflowState.mComputedOffsets.top)) {
|
||||
if (-1 == aContainingBlockWidth) {
|
||||
// Get the containing block width/height
|
||||
kidReflowState.ComputeContainingBlockRectangle(aPresContext,
|
||||
&aReflowState,
|
||||
aContainingBlockWidth,
|
||||
aContainingBlockHeight);
|
||||
}
|
||||
|
||||
if (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left) {
|
||||
NS_ASSERTION(NS_AUTOOFFSET != kidReflowState.mComputedOffsets.right,
|
||||
"Can't solve for both left and right");
|
||||
kidReflowState.mComputedOffsets.left = aContainingBlockWidth -
|
||||
kidReflowState.mComputedOffsets.right -
|
||||
kidReflowState.mComputedMargin.right -
|
||||
kidDesiredSize.width -
|
||||
kidReflowState.mComputedMargin.left;
|
||||
}
|
||||
if (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.top) {
|
||||
kidReflowState.mComputedOffsets.top = aContainingBlockHeight -
|
||||
kidReflowState.mComputedOffsets.bottom -
|
||||
kidReflowState.mComputedMargin.bottom -
|
||||
kidDesiredSize.height -
|
||||
kidReflowState.mComputedMargin.top;
|
||||
}
|
||||
}
|
||||
|
||||
// Position the child relative to our padding edge
|
||||
nsRect rect(border.left + kidReflowState.mComputedOffsets.left + kidReflowState.mComputedMargin.left,
|
||||
border.top + kidReflowState.mComputedOffsets.top + kidReflowState.mComputedMargin.top,
|
||||
kidDesiredSize.width, kidDesiredSize.height);
|
||||
nsRect oldRect = aKidFrame->GetRect();
|
||||
aKidFrame->SetRect(rect);
|
||||
|
||||
// Size and position the view and set its opacity, visibility, content
|
||||
// transparency, and clip
|
||||
nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame,
|
||||
aKidFrame->GetView(),
|
||||
&kidDesiredSize.mOverflowArea);
|
||||
// if the frame moved, then the view would have invalidated everything so
|
||||
// we don't need to do any invalidation here.
|
||||
if (oldRect.TopLeft() == rect.TopLeft() &&
|
||||
aReason != eReflowReason_Initial &&
|
||||
oldRect.Size() != rect.Size()) {
|
||||
// Invalidate the area where the frame changed size. We can't
|
||||
// rely on the view to do this ... the view size might not change even
|
||||
// though the frame size changed (and besides, views will go away).
|
||||
// Invalidate the vertical strip
|
||||
nscoord innerWidth = PR_MIN(oldRect.width, rect.width);
|
||||
nscoord innerHeight = PR_MIN(oldRect.height, rect.height);
|
||||
nscoord outerWidth = PR_MAX(oldRect.width, rect.width);
|
||||
nscoord outerHeight = PR_MAX(oldRect.height, rect.height);
|
||||
aKidFrame->GetParent()->Invalidate(
|
||||
nsRect(rect.x + innerWidth, rect.y, outerWidth - innerWidth, outerHeight));
|
||||
// Invalidate the horizontal strip
|
||||
aKidFrame->GetParent()->Invalidate(
|
||||
nsRect(rect.x, rect.y + innerHeight, outerWidth, outerHeight - innerHeight));
|
||||
}
|
||||
aKidFrame->DidReflow(aPresContext, &kidReflowState, NS_FRAME_REFLOW_FINISHED);
|
||||
|
||||
// If the frame has visible overflow, then store it as a property on the
|
||||
// frame. This allows us to be able to recover it without having to reflow
|
||||
// the frame
|
||||
if (aKidFrame->GetStateBits() & NS_FRAME_OUTSIDE_CHILDREN) {
|
||||
// Get the property (creating a rect struct if necessary)
|
||||
nsRect* overflowArea = aKidFrame->GetOverflowAreaProperty(PR_TRUE);
|
||||
|
||||
NS_ASSERTION(overflowArea, "should have created rect");
|
||||
if (overflowArea) {
|
||||
*overflowArea = kidDesiredSize.mOverflowArea;
|
||||
}
|
||||
NS_ASSERTION(overflowArea, "should have created rect");
|
||||
if (overflowArea) {
|
||||
*overflowArea = kidDesiredSize.mOverflowArea;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyReflow) {
|
||||
nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent - 1);
|
||||
printf("abs pos ");
|
||||
if (nsnull != aKidFrame) {
|
||||
nsIFrameDebug* frameDebug;
|
||||
if (NS_SUCCEEDED(CallQueryInterface(aKidFrame, &frameDebug))) {
|
||||
nsAutoString name;
|
||||
frameDebug->GetFrameName(name);
|
||||
printf("%s ", NS_LossyConvertUTF16toASCII(name).get());
|
||||
}
|
||||
if (nsBlockFrame::gNoisyReflow) {
|
||||
nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent - 1);
|
||||
printf("abs pos ");
|
||||
if (nsnull != aKidFrame) {
|
||||
nsIFrameDebug* frameDebug;
|
||||
if (NS_SUCCEEDED(CallQueryInterface(aKidFrame, &frameDebug))) {
|
||||
nsAutoString name;
|
||||
frameDebug->GetFrameName(name);
|
||||
printf("%s ", NS_LossyConvertUTF16toASCII(name).get());
|
||||
}
|
||||
printf("%p rect=%d,%d,%d,%d", aKidFrame, rect.x, rect.y, rect.width, rect.height);
|
||||
printf("\n");
|
||||
}
|
||||
printf("%p rect=%d,%d,%d,%d", aKidFrame, rect.x, rect.y, rect.width, rect.height);
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
break;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -102,33 +102,19 @@ public:
|
||||
// placeholders for positioning and on whether the containing block
|
||||
// width or height changed.
|
||||
nsresult Reflow(nsIFrame* aDelegatingFrame,
|
||||
nsPresContext* aPresContext,
|
||||
nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight,
|
||||
nsRect* aChildBounds = nsnull,
|
||||
PRBool aForceReflow = PR_TRUE,
|
||||
PRBool aCBWidthChanged = PR_TRUE,
|
||||
PRBool aCBHeightChanged = PR_TRUE);
|
||||
PRBool aCBWidthChanged,
|
||||
PRBool aCBHeightChanged,
|
||||
nsRect* aChildBounds = nsnull);
|
||||
|
||||
// Called by the delegating frame to determine whether the
|
||||
// incremental reflow is entirely targeted at absolute children
|
||||
PRBool ReflowingAbsolutesOnly(nsIFrame* aDelegatingFrame,
|
||||
const nsHTMLReflowState& aReflowState);
|
||||
|
||||
// Called only for a reflow reason of eReflowReason_Incremental.
|
||||
void IncrementalReflow(nsIFrame* aDelegatingFrame,
|
||||
nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight);
|
||||
|
||||
void DestroyFrames(nsIFrame* aDelegatingFrame);
|
||||
|
||||
PRBool HasAbsoluteFrames() {return mAbsoluteFrames.NotEmpty();}
|
||||
|
||||
void CalculateChildBounds(nsPresContext* aPresContext, nsRect& aChildBounds);
|
||||
|
||||
protected:
|
||||
// Returns PR_TRUE if the position of f depends on the position of
|
||||
// its placeholder or if the position or size of f depends on a
|
||||
@ -142,7 +128,6 @@ protected:
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight,
|
||||
nsIFrame* aKidFrame,
|
||||
nsReflowReason aReason,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
protected:
|
||||
|
@ -75,7 +75,14 @@ public:
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
virtual void AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineMinWidthData *aData);
|
||||
virtual void AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlinePrefWidthData *aData);
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nsIAtom* GetType() const;
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
|
||||
@ -102,11 +109,8 @@ BRFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("BRFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("BRFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.mMaxElementWidth = 0;
|
||||
}
|
||||
aMetrics.height = 0; // BR frames with height 0 are ignored in quirks
|
||||
// mode by nsLineLayout::VerticalAlignFrames .
|
||||
// However, it's not always 0. See below.
|
||||
@ -166,11 +170,6 @@ BRFrame::Reflow(nsPresContext* aPresContext,
|
||||
// Warning: nsTextControlFrame::CalculateSizeStandard depends on
|
||||
// the following line, see bug 228752.
|
||||
aMetrics.width = 1;
|
||||
|
||||
// Update max-element-width to keep us honest
|
||||
if (aMetrics.mComputeMEW && aMetrics.width > aMetrics.mMaxElementWidth) {
|
||||
aMetrics.mMaxElementWidth = aMetrics.width;
|
||||
}
|
||||
}
|
||||
|
||||
// Return our reflow status
|
||||
@ -191,12 +190,48 @@ BRFrame::Reflow(nsPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
BRFrame::AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlineMinWidthData *aData)
|
||||
{
|
||||
aData->Break(aRenderingContext);
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
BRFrame::AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlinePrefWidthData *aData)
|
||||
{
|
||||
aData->Break(aRenderingContext);
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
BRFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result = 0;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
BRFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result = 0;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
nsIAtom*
|
||||
BRFrame::GetType() const
|
||||
{
|
||||
return nsLayoutAtoms::brFrame;
|
||||
}
|
||||
|
||||
PRBool
|
||||
BRFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced));
|
||||
}
|
||||
|
||||
nsIFrame::ContentOffsets BRFrame::CalcContentOffsetsFromFramePoint(nsPoint aPoint)
|
||||
{
|
||||
ContentOffsets offsets;
|
||||
|
@ -43,7 +43,6 @@
|
||||
#undef NOISY_FIRST_LETTER // enables debug output for first-letter specific layout
|
||||
#undef NOISY_MAX_ELEMENT_SIZE // enables debug output for max element size computation
|
||||
#undef NOISY_MAXIMUM_WIDTH // enables debug output for max width computation
|
||||
#undef NOISY_KIDXMOST // enables debug output for aState.mKidXMost computation
|
||||
#undef NOISY_FLOAT // enables debug output for float reflow (the in/out metrics for the floated block)
|
||||
#undef NOISY_FLOAT_CLEARING
|
||||
#undef NOISY_FINAL_SIZE // enables debug output for desired width/height computation, once all children have been reflowed
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -48,7 +48,6 @@
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsAbsoluteContainingBlock.h"
|
||||
#include "nsLineBox.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsStyleSet.h"
|
||||
|
||||
@ -222,14 +221,17 @@ public:
|
||||
// are non-decreasing.
|
||||
void SetupLineCursor();
|
||||
|
||||
NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild);
|
||||
virtual void ChildIsDirty(nsIFrame* aChild);
|
||||
virtual PRBool IsVisibleInSelection(nsISelection* aSelection);
|
||||
|
||||
virtual PRBool IsEmpty();
|
||||
virtual PRBool CachedIsEmpty();
|
||||
virtual PRBool IsSelfEmpty();
|
||||
|
||||
// nsIHTMLReflow
|
||||
virtual void MarkIntrinsicWidthsDirty();
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -277,7 +279,10 @@ public:
|
||||
nsBlockReflowState& aState, nsLineBox* aLine);
|
||||
|
||||
protected:
|
||||
nsBlockFrame(nsStyleContext* aContext) : nsHTMLContainerFrame(aContext)
|
||||
nsBlockFrame(nsStyleContext* aContext)
|
||||
: nsHTMLContainerFrame(aContext)
|
||||
, mMinWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
|
||||
, mPrefWidth(NS_INTRINSIC_WIDTH_UNKNOWN)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
InitDebugFlags();
|
||||
@ -378,49 +383,13 @@ protected:
|
||||
// Remove a float, abs, rel positioned frame from the appropriate block's list
|
||||
static void DoRemoveOutOfFlowFrame(nsIFrame* aFrame);
|
||||
|
||||
/** set up the conditions necessary for an initial reflow */
|
||||
nsresult PrepareInitialReflow(nsBlockReflowState& aState);
|
||||
|
||||
/** set up the conditions necessary for an styleChanged reflow */
|
||||
nsresult PrepareStyleChangedReflow(nsBlockReflowState& aState);
|
||||
|
||||
/** set up the conditions necessary for an incremental reflow.
|
||||
* the primary task is to mark the minimumly sufficient lines dirty.
|
||||
*/
|
||||
nsresult PrepareChildIncrementalReflow(nsBlockReflowState& aState);
|
||||
|
||||
/**
|
||||
* Retarget an inline incremental reflow from continuing frames that
|
||||
* will be destroyed.
|
||||
*
|
||||
* @param aState |aState.mNextRCFrame| contains the next frame in
|
||||
* the reflow path; this will be ``rewound'' to either the target
|
||||
* frame's primary frame, or to the first continuation frame after a
|
||||
* ``hard break''. In other words, it will be set to the closest
|
||||
* continuation which will not be destroyed by the unconstrained
|
||||
* reflow. The remaining frames in the reflow path for
|
||||
* |aState.mReflowState.reflowCommand| will be altered similarly.
|
||||
*
|
||||
* @param aLine is initially the line box that contains the target
|
||||
* frame. It will be ``rewound'' in lockstep with
|
||||
* |aState.mNextRCFrame|.
|
||||
*
|
||||
* @param aPrevInFlow points to the target frame's prev-in-flow.
|
||||
*/
|
||||
void RetargetInlineIncrementalReflow(nsReflowPath::iterator &aFrame,
|
||||
line_iterator &aLine,
|
||||
nsIFrame *aPrevInFlow);
|
||||
|
||||
/** set up the conditions necessary for an resize reflow
|
||||
* the primary task is to mark the minimumly sufficient lines dirty.
|
||||
*/
|
||||
nsresult PrepareResizeReflow(nsBlockReflowState& aState);
|
||||
|
||||
/** reflow all lines that have been marked dirty.
|
||||
* @param aTryPull set this to PR_TRUE if you want to try pulling content from
|
||||
* our next in flow while there is room.
|
||||
*/
|
||||
nsresult ReflowDirtyLines(nsBlockReflowState& aState, PRBool aTryPull);
|
||||
/** reflow all lines that have been marked dirty */
|
||||
nsresult ReflowDirtyLines(nsBlockReflowState& aState);
|
||||
|
||||
//----------------------------------------
|
||||
// Methods for line reflow
|
||||
@ -429,24 +398,17 @@ protected:
|
||||
* @param aState the current reflow state
|
||||
* @param aLine the line to reflow. can contain a single block frame
|
||||
* or contain 1 or more inline frames.
|
||||
* @param aTryPull controls whether we are allowed to try pulling
|
||||
* frames from the next-in-flow
|
||||
* @param aKeepReflowGoing [OUT] indicates whether the caller should continue to reflow more lines
|
||||
* @param aDamageDirtyArea if PR_TRUE, do extra work to mark the changed areas as damaged for painting
|
||||
* this indicates that frames may have changed size, for example
|
||||
*/
|
||||
nsresult ReflowLine(nsBlockReflowState& aState,
|
||||
line_iterator aLine,
|
||||
PRBool aTryPull,
|
||||
PRBool* aKeepReflowGoing,
|
||||
PRBool aDamageDirtyArea = PR_FALSE);
|
||||
PRBool* aKeepReflowGoing);
|
||||
|
||||
// Return PR_TRUE if aLine gets pushed.
|
||||
PRBool PlaceLine(nsBlockReflowState& aState,
|
||||
nsLineLayout& aLineLayout,
|
||||
line_iterator aLine,
|
||||
PRBool* aKeepReflowGoing,
|
||||
PRBool aUpdateMaximumWidth);
|
||||
PRBool* aKeepReflowGoing);
|
||||
|
||||
/**
|
||||
* Mark |aLine| dirty, and, if necessary because of possible
|
||||
@ -454,11 +416,6 @@ protected:
|
||||
*/
|
||||
nsresult MarkLineDirty(line_iterator aLine);
|
||||
|
||||
// XXX blech
|
||||
void PostPlaceLine(nsBlockReflowState& aState,
|
||||
nsLineBox* aLine,
|
||||
nscoord aMaxElementWidth);
|
||||
|
||||
// XXX where to go
|
||||
PRBool ShouldJustifyLine(nsBlockReflowState& aState,
|
||||
line_iterator aLine);
|
||||
@ -479,18 +436,13 @@ protected:
|
||||
|
||||
nsresult ReflowInlineFrames(nsBlockReflowState& aState,
|
||||
line_iterator aLine,
|
||||
PRBool aTryPull,
|
||||
PRBool* aKeepLineGoing,
|
||||
PRBool aDamageDirtyArea,
|
||||
PRBool aUpdateMaximumWidth = PR_FALSE);
|
||||
PRBool* aKeepLineGoing);
|
||||
|
||||
nsresult DoReflowInlineFrames(nsBlockReflowState& aState,
|
||||
nsLineLayout& aLineLayout,
|
||||
line_iterator aLine,
|
||||
PRBool* aKeepReflowGoing,
|
||||
LineReflowStatus* aLineReflowStatus,
|
||||
PRBool aUpdateMaximumWidth,
|
||||
PRBool aDamageDirtyArea,
|
||||
PRBool aAllowPullUp);
|
||||
|
||||
nsresult ReflowInlineFrame(nsBlockReflowState& aState,
|
||||
@ -529,7 +481,6 @@ protected:
|
||||
|
||||
nsresult PullFrame(nsBlockReflowState& aState,
|
||||
line_iterator aLine,
|
||||
PRBool aDamageDeletedLine,
|
||||
nsIFrame*& aFrameResult);
|
||||
|
||||
PRBool PullFrameFrom(nsBlockReflowState& aState,
|
||||
@ -537,7 +488,6 @@ protected:
|
||||
nsBlockFrame* aFromContainer,
|
||||
PRBool aFromOverflowLine,
|
||||
nsLineList::iterator aFromLine,
|
||||
PRBool aDamageDeletedLines,
|
||||
nsIFrame*& aFrameResult);
|
||||
|
||||
void PushLines(nsBlockReflowState& aState,
|
||||
@ -567,8 +517,6 @@ protected:
|
||||
|
||||
static PRBool FrameStartsCounterScope(nsIFrame* aFrame);
|
||||
|
||||
nsresult UpdateBulletPosition(nsBlockReflowState& aState);
|
||||
|
||||
void ReflowBullet(nsBlockReflowState& aState,
|
||||
nsHTMLReflowMetrics& aMetrics);
|
||||
|
||||
@ -620,6 +568,8 @@ protected:
|
||||
// Ascent of our first line to support 'vertical-align: baseline' in table-cells
|
||||
nscoord mAscent;
|
||||
|
||||
nscoord mMinWidth, mPrefWidth;
|
||||
|
||||
nsLineList mLines;
|
||||
|
||||
// List of all floats in this block
|
||||
@ -641,7 +591,7 @@ public:
|
||||
static PRBool gLameReflowMetrics;
|
||||
static PRBool gNoisy;
|
||||
static PRBool gNoisyDamageRepair;
|
||||
static PRBool gNoisyMaxElementWidth;
|
||||
static PRBool gNoisyIntrinsic;
|
||||
static PRBool gNoisyReflow;
|
||||
static PRBool gReallyNoisyReflow;
|
||||
static PRBool gNoisySpaceManager;
|
||||
|
@ -47,7 +47,6 @@
|
||||
#include "nsFrameManager.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsHTMLReflowCommand.h"
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
#include "nsBlockFrame.h"
|
||||
#include "nsLineBox.h"
|
||||
@ -68,19 +67,14 @@
|
||||
#endif
|
||||
|
||||
nsBlockReflowContext::nsBlockReflowContext(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aParentRS,
|
||||
PRBool aComputeMaxElementWidth,
|
||||
PRBool aComputeMaximumWidth)
|
||||
const nsHTMLReflowState& aParentRS)
|
||||
: mPresContext(aPresContext),
|
||||
mOuterReflowState(aParentRS),
|
||||
mMetrics(aComputeMaxElementWidth),
|
||||
mComputeMaximumWidth(aComputeMaximumWidth)
|
||||
mMetrics()
|
||||
{
|
||||
mStyleBorder = nsnull;
|
||||
mStyleMargin = nsnull;
|
||||
mStylePadding = nsnull;
|
||||
if (mComputeMaximumWidth)
|
||||
mMetrics.mFlags |= NS_REFLOW_CALC_MAX_WIDTH;
|
||||
}
|
||||
|
||||
static nsIFrame* DescendIntoBlockLevelFrame(nsIFrame* aFrame)
|
||||
@ -171,9 +165,7 @@ nsBlockReflowContext::ComputeCollapsedTopMargin(const nsHTMLReflowState& aRS,
|
||||
// generational collapse is required we need to compute the
|
||||
// child blocks margin and so in so that we can look into
|
||||
// it. For its margins to be computed we need to have a reflow
|
||||
// state for it. Since the reflow reason is irrelevant, we'll
|
||||
// arbitrarily make it a `resize' to avoid the path-plucking
|
||||
// behavior if we're in an incremental reflow.
|
||||
// state for it.
|
||||
|
||||
// We may have to construct an extra reflow state here if
|
||||
// we drilled down through a block wrapper. At the moment
|
||||
@ -185,8 +177,7 @@ nsBlockReflowContext::ComputeCollapsedTopMargin(const nsHTMLReflowState& aRS,
|
||||
"Can only drill through one level of block wrapper");
|
||||
nsSize availSpace(aRS.mComputedWidth, aRS.mComputedHeight);
|
||||
outerReflowState = new nsHTMLReflowState(prescontext,
|
||||
aRS, frame,
|
||||
availSpace, eReflowReason_Resize);
|
||||
aRS, frame, availSpace);
|
||||
if (!outerReflowState)
|
||||
goto done;
|
||||
}
|
||||
@ -195,7 +186,7 @@ nsBlockReflowContext::ComputeCollapsedTopMargin(const nsHTMLReflowState& aRS,
|
||||
outerReflowState->mComputedHeight);
|
||||
nsHTMLReflowState innerReflowState(prescontext,
|
||||
*outerReflowState, kid,
|
||||
availSpace, eReflowReason_Resize);
|
||||
availSpace);
|
||||
// Record that we're being optimistic by assuming the kid
|
||||
// has no clearance
|
||||
if (kid->GetStyleDisplay()->mBreakType != NS_STYLE_CLEAR_NONE) {
|
||||
@ -245,179 +236,6 @@ nsBlockReflowContext::ComputeCollapsedTopMargin(const nsHTMLReflowState& aRS,
|
||||
return dirtiedLine;
|
||||
}
|
||||
|
||||
struct nsBlockHorizontalAlign {
|
||||
nscoord mXOffset; // left edge
|
||||
nscoord mLeftMargin;
|
||||
nscoord mRightMargin;
|
||||
};
|
||||
|
||||
// Given the width of the block frame and a suggested x-offset calculate
|
||||
// the actual x-offset taking into account horizontal alignment. Also returns
|
||||
// the actual left and right margin
|
||||
void
|
||||
nsBlockReflowContext::AlignBlockHorizontally(nscoord aWidth,
|
||||
nsBlockHorizontalAlign &aAlign)
|
||||
{
|
||||
// Initialize OUT parameters
|
||||
aAlign.mLeftMargin = mMargin.left;
|
||||
aAlign.mRightMargin = mMargin.right;
|
||||
|
||||
// Get style unit associated with the left and right margins
|
||||
PRBool leftIsAuto = mStyleMargin->mMargin.GetLeftUnit() == eStyleUnit_Auto;
|
||||
PRBool rightIsAuto = mStyleMargin->mMargin.GetRightUnit() == eStyleUnit_Auto;
|
||||
|
||||
// Apply post-reflow horizontal alignment. When a block element
|
||||
// doesn't use it all of the available width then we need to
|
||||
// align it using the text-align property.
|
||||
if (NS_UNCONSTRAINEDSIZE != mSpace.width &&
|
||||
NS_UNCONSTRAINEDSIZE != mOuterReflowState.mComputedWidth) {
|
||||
// It is possible that the object reflowed was given a
|
||||
// constrained width and ended up picking a different width
|
||||
// (e.g. a table width a set width that ended up larger
|
||||
// because its contents required it). When this happens we
|
||||
// need to recompute auto margins because the reflow state's
|
||||
// computations are no longer valid.
|
||||
if (aWidth != mComputedWidth) {
|
||||
if (leftIsAuto) {
|
||||
aAlign.mXOffset = mSpace.x;
|
||||
aAlign.mLeftMargin = 0;
|
||||
}
|
||||
if (rightIsAuto) {
|
||||
aAlign.mRightMargin = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute how much remaining space there is, and in special
|
||||
// cases apply it (normally we should get zero here because of
|
||||
// the logic in nsHTMLReflowState).
|
||||
nscoord remainingSpace = mSpace.XMost() - (aAlign.mXOffset + aWidth +
|
||||
aAlign.mRightMargin);
|
||||
if (remainingSpace != 0) {
|
||||
if (remainingSpace < 0) {
|
||||
// CSS2.1, 10.3.3 says:
|
||||
// If 'width' is not 'auto' and 'border-left-width' +
|
||||
// 'padding-left' + 'width' + 'padding-right' +
|
||||
// 'border-right-width' (plus any of 'margin-left' or
|
||||
// 'margin-right' that are not 'auto') is larger than the width
|
||||
// of the containing block, then any 'auto' values for
|
||||
// 'margin-left' or 'margin-right' are, for the following rules,
|
||||
// treated as zero.
|
||||
leftIsAuto = rightIsAuto = PR_FALSE;
|
||||
}
|
||||
|
||||
// The block/table frame didn't use all of the available
|
||||
// space. Synthesize margins for its horizontal placement.
|
||||
if (leftIsAuto) {
|
||||
if (rightIsAuto) {
|
||||
// When both margins are auto, we center the block
|
||||
aAlign.mXOffset += remainingSpace / 2;
|
||||
}
|
||||
else {
|
||||
// When the left margin is auto we right align the block
|
||||
aAlign.mXOffset += remainingSpace;
|
||||
}
|
||||
}
|
||||
else if (!rightIsAuto) {
|
||||
// The block/table doesn't have auto margins.
|
||||
|
||||
// For normal (non-table) blocks we don't get here because
|
||||
// nsHTMLReflowState::CalculateBlockSideMargins handles this.
|
||||
// (I think there may be an exception to that, though...)
|
||||
|
||||
// We use a special value of the text-align property for
|
||||
// HTML alignment (the CENTER element and DIV ALIGN=...)
|
||||
// since it acts on blocks and tables rather than just
|
||||
// being a text-align.
|
||||
// So, check the text-align value from the parent to see if
|
||||
// it has one of these special values.
|
||||
// But only use this value when the content is narrower than the
|
||||
// container, not when it is too wide.
|
||||
PRUint8 textAlign;
|
||||
if (remainingSpace > 0)
|
||||
textAlign = mOuterReflowState.mStyleText->mTextAlign;
|
||||
else
|
||||
textAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
|
||||
|
||||
if (textAlign == NS_STYLE_TEXT_ALIGN_MOZ_RIGHT) {
|
||||
aAlign.mXOffset += remainingSpace;
|
||||
} else if (textAlign == NS_STYLE_TEXT_ALIGN_MOZ_CENTER) {
|
||||
aAlign.mXOffset += remainingSpace / 2;
|
||||
} else if (textAlign != NS_STYLE_TEXT_ALIGN_MOZ_LEFT) {
|
||||
// If we don't have a special text-align value indicating
|
||||
// HTML alignment, then use the CSS rules.
|
||||
|
||||
// When neither margin is auto then the block is said to
|
||||
// be over constrained, Depending on the direction, choose
|
||||
// which margin to treat as auto.
|
||||
PRUint8 direction = mOuterReflowState.mStyleVisibility->mDirection;
|
||||
if (NS_STYLE_DIRECTION_RTL == direction) {
|
||||
// The left margin becomes auto
|
||||
aAlign.mXOffset += remainingSpace;
|
||||
}
|
||||
//else {
|
||||
// The right margin becomes auto which is a no-op
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ComputeShrinkwrapMargins(const nsStyleMargin* aStyleMargin, nscoord aWidth,
|
||||
nsMargin& aMargin, nscoord& aXToUpdate)
|
||||
{
|
||||
nscoord boxWidth = aWidth;
|
||||
float leftPct = 0.0, rightPct = 0.0;
|
||||
const nsStyleSides& margin = aStyleMargin->mMargin;
|
||||
|
||||
if (eStyleUnit_Percent == margin.GetLeftUnit()) {
|
||||
nsStyleCoord coord;
|
||||
leftPct = margin.GetLeft(coord).GetPercentValue();
|
||||
} else {
|
||||
boxWidth += aMargin.left;
|
||||
}
|
||||
|
||||
if (eStyleUnit_Percent == margin.GetRightUnit()) {
|
||||
nsStyleCoord coord;
|
||||
rightPct = margin.GetRight(coord).GetPercentValue();
|
||||
} else {
|
||||
boxWidth += aMargin.right;
|
||||
}
|
||||
|
||||
// The total shrink wrap width "sww" (i.e., the width that the
|
||||
// containing block needs to be to shrink-wrap this block) is
|
||||
// calculated by the expression:
|
||||
// sww = bw + (mp * sww)
|
||||
// where "bw" is the box width (frame width plus margins that aren't
|
||||
// percentage based) and "mp" are the total margin percentages (i.e.,
|
||||
// the left percentage value plus the right percentage value).
|
||||
// Solving for "sww" gives:
|
||||
// sww = bw / (1 - mp)
|
||||
// Note that this is only well defined for "mp" less than 100% and
|
||||
// greater than -100% (XXXldb but we only accept 0 to 100%).
|
||||
|
||||
float marginPct = leftPct + rightPct;
|
||||
if (marginPct >= 1.0) {
|
||||
// Ignore the right percentage and just use the left percentage
|
||||
// XXX Pay attention to direction property...
|
||||
marginPct = leftPct;
|
||||
rightPct = 0.0;
|
||||
}
|
||||
|
||||
if ((marginPct > 0.0) && (marginPct < 1.0)) {
|
||||
double shrinkWrapWidth = float(boxWidth) / (1.0 - marginPct);
|
||||
|
||||
if (eStyleUnit_Percent == margin.GetLeftUnit()) {
|
||||
aMargin.left = NSToCoordFloor((float)(shrinkWrapWidth * leftPct));
|
||||
aXToUpdate += aMargin.left;
|
||||
}
|
||||
if (eStyleUnit_Percent == margin.GetRightUnit()) {
|
||||
aMargin.right = NSToCoordFloor((float)(shrinkWrapWidth * rightPct));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nsPointDtor(void *aFrame, nsIAtom *aPropertyName,
|
||||
void *aPropertyValue, void *aDtorData)
|
||||
@ -440,48 +258,6 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
mFrame = aFrameRS.frame;
|
||||
mSpace = aSpace;
|
||||
|
||||
// Get reflow reason set correctly. It's possible that a child was
|
||||
// created and then it was decided that it could not be reflowed
|
||||
// (for example, a block frame that isn't at the start of a
|
||||
// line). In this case the reason will be wrong so we need to check
|
||||
// the frame state.
|
||||
aFrameRS.reason = eReflowReason_Resize;
|
||||
if (NS_FRAME_FIRST_REFLOW & mFrame->GetStateBits()) {
|
||||
aFrameRS.reason = eReflowReason_Initial;
|
||||
}
|
||||
else if (mOuterReflowState.reason == eReflowReason_Incremental) {
|
||||
// If the frame we're about to reflow is on the reflow path, then
|
||||
// propagate the reflow as `incremental' so it unwinds correctly
|
||||
// to the target frames below us.
|
||||
PRBool frameIsOnReflowPath = mOuterReflowState.path->HasChild(mFrame);
|
||||
if (frameIsOnReflowPath)
|
||||
aFrameRS.reason = eReflowReason_Incremental;
|
||||
|
||||
// But...if the incremental reflow command is a StyleChanged
|
||||
// reflow and its target is the current block, change the reason
|
||||
// to `style change', so that it propagates through the entire
|
||||
// subtree.
|
||||
nsHTMLReflowCommand* rc = mOuterReflowState.path->mReflowCommand;
|
||||
if (rc) {
|
||||
nsReflowType type;
|
||||
rc->GetType(type);
|
||||
if (type == eReflowType_StyleChanged)
|
||||
aFrameRS.reason = eReflowReason_StyleChange;
|
||||
else if (type == eReflowType_ReflowDirty &&
|
||||
(mFrame->GetStateBits() & NS_FRAME_IS_DIRTY) &&
|
||||
!frameIsOnReflowPath) {
|
||||
aFrameRS.reason = eReflowReason_Dirty;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mOuterReflowState.reason == eReflowReason_StyleChange) {
|
||||
aFrameRS.reason = eReflowReason_StyleChange;
|
||||
}
|
||||
else if (mOuterReflowState.reason == eReflowReason_Dirty) {
|
||||
if (mFrame->GetStateBits() & NS_FRAME_IS_DIRTY)
|
||||
aFrameRS.reason = eReflowReason_Dirty;
|
||||
}
|
||||
|
||||
const nsStyleDisplay* display = mFrame->GetStyleDisplay();
|
||||
|
||||
aComputedOffsets = aFrameRS.mComputedOffsets;
|
||||
@ -560,23 +336,6 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
mX = x;
|
||||
mY = y;
|
||||
|
||||
// If it's an auto-width table, then it doesn't behave like other blocks
|
||||
// XXX why not for a floating table too?
|
||||
if (aFrameRS.mStyleDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE &&
|
||||
!aFrameRS.mStyleDisplay->IsFloating()) {
|
||||
// If this isn't the table's initial reflow, then use its existing
|
||||
// width to determine where it will be placed horizontally
|
||||
if (aFrameRS.reason != eReflowReason_Initial) {
|
||||
nsBlockHorizontalAlign align;
|
||||
|
||||
align.mXOffset = x;
|
||||
AlignBlockHorizontally(mFrame->GetSize().width, align);
|
||||
// Don't reset "mX". because PlaceBlock() will recompute the
|
||||
// x-offset and expects "mX" to be at the left margin edge
|
||||
x = align.mXOffset;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the translation to be used for adjusting the spacemanagager
|
||||
// coordinate system for the frame. The spacemanager coordinates are
|
||||
// <b>inside</b> the callers border+padding, but the x/y coordinates
|
||||
@ -608,44 +367,9 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
mMetrics.height = nscoord(0xdeadbeef);
|
||||
mMetrics.ascent = nscoord(0xdeadbeef);
|
||||
mMetrics.descent = nscoord(0xdeadbeef);
|
||||
if (mMetrics.mComputeMEW) {
|
||||
mMetrics.mMaxElementWidth = nscoord(0xdeadbeef);
|
||||
}
|
||||
#endif
|
||||
|
||||
mOuterReflowState.mSpaceManager->Translate(tx, ty);
|
||||
|
||||
// See if this is the child's initial reflow and we are supposed to
|
||||
// compute our maximum width
|
||||
if (mComputeMaximumWidth && (eReflowReason_Initial == aFrameRS.reason)) {
|
||||
nsSpaceManager::SavedState spaceManagerState;
|
||||
mOuterReflowState.mSpaceManager->PushState(&spaceManagerState);
|
||||
|
||||
nscoord oldAvailableWidth = aFrameRS.availableWidth;
|
||||
nscoord oldComputedWidth = aFrameRS.mComputedWidth;
|
||||
|
||||
aFrameRS.availableWidth = NS_UNCONSTRAINEDSIZE;
|
||||
// XXX Is this really correct? This means we don't compute the
|
||||
// correct maximum width if the element's width is determined by
|
||||
// its 'width' style
|
||||
aFrameRS.mComputedWidth = NS_UNCONSTRAINEDSIZE;
|
||||
rv = mFrame->Reflow(mPresContext, mMetrics, aFrameRS, aFrameReflowStatus);
|
||||
|
||||
// Update the reflow metrics with the maximum width
|
||||
mMetrics.mMaximumWidth = mMetrics.width;
|
||||
#ifdef NOISY_REFLOW
|
||||
printf("*** nsBlockReflowContext::ReflowBlock block %p returning max width %d\n",
|
||||
mFrame, mMetrics.mMaximumWidth);
|
||||
#endif
|
||||
// The second reflow is just as a resize reflow with the constrained
|
||||
// width
|
||||
aFrameRS.availableWidth = oldAvailableWidth;
|
||||
aFrameRS.mComputedWidth = oldComputedWidth;
|
||||
aFrameRS.reason = eReflowReason_Resize;
|
||||
|
||||
mOuterReflowState.mSpaceManager->PopState(&spaceManagerState);
|
||||
}
|
||||
|
||||
rv = mFrame->Reflow(mPresContext, mMetrics, aFrameRS, aFrameReflowStatus);
|
||||
mOuterReflowState.mSpaceManager->Translate(-tx, -ty);
|
||||
|
||||
@ -656,24 +380,6 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
nsFrame::ListTag(stdout, mFrame);
|
||||
printf(" metrics=%d,%d!\n", mMetrics.width, mMetrics.height);
|
||||
}
|
||||
if (mMetrics.mComputeMEW &&
|
||||
(nscoord(0xdeadbeef) == mMetrics.mMaxElementWidth)) {
|
||||
printf("nsBlockReflowContext: ");
|
||||
nsFrame::ListTag(stdout, mFrame);
|
||||
printf(" didn't set max-element-size!\n");
|
||||
}
|
||||
#ifdef REALLY_NOISY_MAX_ELEMENT_SIZE
|
||||
// Note: there are common reflow situations where this *correctly*
|
||||
// occurs; so only enable this debug noise when you really need to
|
||||
// analyze in detail.
|
||||
if (mMetrics.mComputeMEW &&
|
||||
(mMetrics.mMaxElementWidth > mMetrics.width)) {
|
||||
printf("nsBlockReflowContext: ");
|
||||
nsFrame::ListTag(stdout, mFrame);
|
||||
printf(": WARNING: maxElementWidth=%d > metrics=%d\n",
|
||||
mMetrics.mMaxElementWidth, mMetrics.width);
|
||||
}
|
||||
#endif
|
||||
if ((mMetrics.width == nscoord(0xdeadbeef)) ||
|
||||
(mMetrics.height == nscoord(0xdeadbeef)) ||
|
||||
(mMetrics.ascent == nscoord(0xdeadbeef)) ||
|
||||
@ -686,20 +392,6 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyMaxElementWidth) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
if (!NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus)) {
|
||||
if (mMetrics.mComputeMEW) {
|
||||
printf(" ");
|
||||
nsFrame::ListTag(stdout, mFrame);
|
||||
printf(": maxElementSize=%d wh=%d,%d\n",
|
||||
mMetrics.mMaxElementWidth,
|
||||
mMetrics.width, mMetrics.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!(NS_FRAME_OUTSIDE_CHILDREN & mFrame->GetStateBits())) {
|
||||
// Provide overflow area for child that doesn't have any
|
||||
@ -709,13 +401,6 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
mMetrics.mOverflowArea.height = mMetrics.height;
|
||||
}
|
||||
|
||||
// Now that frame has been reflowed at least one time make sure that
|
||||
// the NS_FRAME_FIRST_REFLOW bit is cleared so that never give it an
|
||||
// initial reflow reason again.
|
||||
if (eReflowReason_Initial == aFrameRS.reason) {
|
||||
mFrame->RemoveStateBits(NS_FRAME_FIRST_REFLOW);
|
||||
}
|
||||
|
||||
if (!NS_INLINE_IS_BREAK_BEFORE(aFrameReflowStatus) ||
|
||||
(mFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
||||
// If frame is complete and has a next-in-flow, we need to delete
|
||||
@ -737,13 +422,6 @@ nsBlockReflowContext::ReflowBlock(const nsRect& aSpace,
|
||||
}
|
||||
}
|
||||
|
||||
// If the block is shrink wrapping its width, then see if we have percentage
|
||||
// based margins. If so, we can calculate them now that we know the shrink
|
||||
// wrap width
|
||||
if (NS_SHRINKWRAPWIDTH == aFrameRS.mComputedWidth) {
|
||||
ComputeShrinkwrapMargins(aFrameRS.mStyleMargin, mMetrics.width, mMargin, mX);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -831,64 +509,6 @@ nsBlockReflowContext::PlaceBlock(const nsHTMLReflowState& aReflowState,
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty)
|
||||
{
|
||||
// Adjust the max-element-size in the metrics to take into
|
||||
// account the margins around the block element.
|
||||
// Do not allow auto margins to impact the max-element size
|
||||
// since they are springy and don't really count!
|
||||
if (mMetrics.mComputeMEW) {
|
||||
nsMargin maxElemMargin;
|
||||
const nsStyleSides &styleMargin = mStyleMargin->mMargin;
|
||||
nsStyleCoord coord;
|
||||
if (styleMargin.GetLeftUnit() == eStyleUnit_Coord)
|
||||
maxElemMargin.left = styleMargin.GetLeft(coord).GetCoordValue();
|
||||
else
|
||||
maxElemMargin.left = 0;
|
||||
if (styleMargin.GetRightUnit() == eStyleUnit_Coord)
|
||||
maxElemMargin.right = styleMargin.GetRight(coord).GetCoordValue();
|
||||
else
|
||||
maxElemMargin.right = 0;
|
||||
|
||||
nscoord dummyXOffset;
|
||||
// Base the margins on the max-element size
|
||||
ComputeShrinkwrapMargins(mStyleMargin, mMetrics.mMaxElementWidth,
|
||||
maxElemMargin, dummyXOffset);
|
||||
|
||||
mMetrics.mMaxElementWidth += maxElemMargin.left + maxElemMargin.right;
|
||||
}
|
||||
|
||||
// do the same for the maximum width
|
||||
if (mComputeMaximumWidth) {
|
||||
nsMargin maxWidthMargin;
|
||||
const nsStyleSides &styleMargin = mStyleMargin->mMargin;
|
||||
nsStyleCoord coord;
|
||||
if (styleMargin.GetLeftUnit() == eStyleUnit_Coord)
|
||||
maxWidthMargin.left = styleMargin.GetLeft(coord).GetCoordValue();
|
||||
else
|
||||
maxWidthMargin.left = 0;
|
||||
if (styleMargin.GetRightUnit() == eStyleUnit_Coord)
|
||||
maxWidthMargin.right = styleMargin.GetRight(coord).GetCoordValue();
|
||||
else
|
||||
maxWidthMargin.right = 0;
|
||||
|
||||
nscoord dummyXOffset;
|
||||
// Base the margins on the maximum width
|
||||
ComputeShrinkwrapMargins(mStyleMargin, mMetrics.mMaximumWidth,
|
||||
maxWidthMargin, dummyXOffset);
|
||||
|
||||
mMetrics.mMaximumWidth += maxWidthMargin.left + maxWidthMargin.right;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the actual x-offset and left and right margin
|
||||
nsBlockHorizontalAlign align;
|
||||
align.mXOffset = x;
|
||||
AlignBlockHorizontally(mMetrics.width, align);
|
||||
x = align.mXOffset;
|
||||
mMargin.left = align.mLeftMargin;
|
||||
mMargin.right = align.mRightMargin;
|
||||
|
||||
aInFlowBounds = nsRect(x, y - backupContainingBlockAdvance,
|
||||
mMetrics.width, mMetrics.height);
|
||||
|
||||
|
@ -60,9 +60,7 @@ struct nsBlockHorizontalAlign;
|
||||
class nsBlockReflowContext {
|
||||
public:
|
||||
nsBlockReflowContext(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aParentRS,
|
||||
PRBool aComputeMaxElementWidth,
|
||||
PRBool aComputeMaximumWidth);
|
||||
const nsHTMLReflowState& aParentRS);
|
||||
~nsBlockReflowContext() { }
|
||||
|
||||
nsresult ReflowBlock(const nsRect& aSpace,
|
||||
@ -83,8 +81,6 @@ public:
|
||||
nsRect& aCombinedRect,
|
||||
nsReflowStatus aReflowStatus);
|
||||
|
||||
void AlignBlockHorizontally(nscoord aWidth, nsBlockHorizontalAlign&);
|
||||
|
||||
nsCollapsingMargin& GetCarriedOutBottomMargin() {
|
||||
return mMetrics.mCarriedOutBottomMargin;
|
||||
}
|
||||
@ -101,14 +97,6 @@ public:
|
||||
return mMetrics;
|
||||
}
|
||||
|
||||
nscoord GetMaxElementWidth() const {
|
||||
return mMetrics.mMaxElementWidth;
|
||||
}
|
||||
|
||||
nscoord GetMaximumWidth() const {
|
||||
return mMetrics.mMaximumWidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the collapsed top margin for a block whose reflow state is in aRS.
|
||||
* The computed margin is added into aMargin.
|
||||
@ -144,7 +132,6 @@ protected:
|
||||
nscoord mX, mY;
|
||||
nsHTMLReflowMetrics mMetrics;
|
||||
nsCollapsingMargin mTopMargin;
|
||||
PRPackedBool mComputeMaximumWidth;
|
||||
};
|
||||
|
||||
#endif /* nsBlockReflowContext_h___ */
|
||||
|
@ -108,29 +108,10 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||
|
||||
mPresContext = aPresContext;
|
||||
mNextInFlow = NS_STATIC_CAST(nsBlockFrame*, mBlock->GetNextInFlow());
|
||||
mKidXMost = 0;
|
||||
|
||||
// Compute content area width (the content area is inside the border
|
||||
// and padding)
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
||||
mContentArea.width = aReflowState.mComputedWidth;
|
||||
}
|
||||
else {
|
||||
if (NS_UNCONSTRAINEDSIZE == aReflowState.availableWidth) {
|
||||
mContentArea.width = NS_UNCONSTRAINEDSIZE;
|
||||
SetFlag(BRS_UNCONSTRAINEDWIDTH, PR_TRUE);
|
||||
}
|
||||
else if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedMaxWidth) {
|
||||
// Choose a width based on the content (shrink wrap width) up
|
||||
// to the maximum width
|
||||
mContentArea.width = aReflowState.mComputedMaxWidth;
|
||||
SetFlag(BRS_SHRINKWRAPWIDTH, PR_TRUE);
|
||||
}
|
||||
else {
|
||||
nscoord lr = borderPadding.left + borderPadding.right;
|
||||
mContentArea.width = PR_MAX(0, aReflowState.availableWidth - lr);
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth,
|
||||
"no unconstrained widths should be present anymore");
|
||||
mContentArea.width = aReflowState.mComputedWidth;
|
||||
|
||||
// Compute content area height. Unlike the width, if we have a
|
||||
// specified style height we ignore it since extra content is
|
||||
@ -158,22 +139,6 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState,
|
||||
mPrevChild = nsnull;
|
||||
mCurrentLine = aFrame->end_lines();
|
||||
|
||||
SetFlag(BRS_COMPUTEMAXELEMENTWIDTH, aMetrics.mComputeMEW);
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyMaxElementWidth) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
printf("BRS: setting compute-MEW to %d\n", aMetrics.mComputeMEW);
|
||||
}
|
||||
#endif
|
||||
mMaxElementWidth = 0;
|
||||
SetFlag(BRS_COMPUTEMAXWIDTH,
|
||||
(NS_REFLOW_CALC_MAX_WIDTH == (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH)));
|
||||
|
||||
// Preset mMaximumWidth to our left border + padding. All the values we'll
|
||||
// try to set it to already include that, and we depend on it always
|
||||
// including the left border + padding in nsBlockFrame::ComputeFinalSize.
|
||||
mMaximumWidth = BorderPadding().left;
|
||||
|
||||
mMinLineHeight = nsHTMLReflowState::CalcLineHeight(mPresContext,
|
||||
aReflowState.rendContext,
|
||||
aReflowState.frame);
|
||||
@ -235,7 +200,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
|
||||
if ((NS_FRAME_SPLITTABLE_NON_RECTANGULAR == aSplitType || // normal blocks
|
||||
NS_FRAME_NOT_SPLITTABLE == aSplitType) && // things like images mapped to display: block
|
||||
!(aFrame->GetStateBits() & NS_FRAME_REPLACED_ELEMENT) && // but not replaced elements
|
||||
!(aFrame->IsFrameOfType(nsIFrame::eReplaced)) && // but not replaced elements
|
||||
aFrame->GetType() != nsLayoutAtoms::scrollFrame) // or scroll frames
|
||||
{
|
||||
if (mBand.GetFloatCount()) {
|
||||
@ -248,10 +213,8 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
// The child block will flow around the float. Therefore
|
||||
// give it all of the available space.
|
||||
aResult.x = borderPadding.left;
|
||||
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||
? NS_UNCONSTRAINEDSIZE
|
||||
: mContentArea.width;
|
||||
break;
|
||||
aResult.width = mContentArea.width;
|
||||
break;
|
||||
case NS_STYLE_FLOAT_EDGE_BORDER:
|
||||
case NS_STYLE_FLOAT_EDGE_PADDING:
|
||||
{
|
||||
@ -274,22 +237,17 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
}
|
||||
|
||||
// determine width
|
||||
if (GetFlag(BRS_UNCONSTRAINEDWIDTH)) {
|
||||
aResult.width = NS_UNCONSTRAINEDSIZE;
|
||||
}
|
||||
else {
|
||||
if (mBand.GetRightFloatCount()) {
|
||||
if (mBand.GetLeftFloatCount()) {
|
||||
aResult.width = mAvailSpaceRect.width + m.left + m.right;
|
||||
}
|
||||
else {
|
||||
aResult.width = mAvailSpaceRect.width + m.right;
|
||||
}
|
||||
if (mBand.GetRightFloatCount()) {
|
||||
if (mBand.GetLeftFloatCount()) {
|
||||
aResult.width = mAvailSpaceRect.width + m.left + m.right;
|
||||
}
|
||||
else {
|
||||
aResult.width = mAvailSpaceRect.width + m.left;
|
||||
aResult.width = mAvailSpaceRect.width + m.right;
|
||||
}
|
||||
}
|
||||
else {
|
||||
aResult.width = mAvailSpaceRect.width + m.left;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -308,9 +266,7 @@ nsBlockReflowState::ComputeBlockAvailSpace(nsIFrame* aFrame,
|
||||
// doesn't matter therefore give the block element all of the
|
||||
// available space since it will flow around the float itself.
|
||||
aResult.x = borderPadding.left;
|
||||
aResult.width = GetFlag(BRS_UNCONSTRAINEDWIDTH)
|
||||
? NS_UNCONSTRAINEDSIZE
|
||||
: mContentArea.width;
|
||||
aResult.width = mContentArea.width;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -488,54 +444,6 @@ nsBlockReflowState::RecoverStateFrom(nsLineList::iterator aLine,
|
||||
// Make the line being recovered the current line
|
||||
mCurrentLine = aLine;
|
||||
|
||||
// Recover mKidXMost and mMaxElementWidth
|
||||
nscoord xmost = aLine->mBounds.XMost();
|
||||
// If we're shrink-wrapping, then include the right margin in the xmost
|
||||
// so that shrink-wrapping includes it.
|
||||
if (GetFlag(BRS_SHRINKWRAPWIDTH) && aLine->IsBlock()) {
|
||||
nsHTMLReflowState blockHtmlRS(mPresContext, mReflowState, aLine->mFirstChild,
|
||||
nsSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE),
|
||||
mReflowState.reason, PR_TRUE);
|
||||
xmost += blockHtmlRS.mComputedMargin.right;
|
||||
}
|
||||
if (xmost > mKidXMost) {
|
||||
#ifdef DEBUG
|
||||
if (CRAZY_WIDTH(xmost)) {
|
||||
nsFrame::ListTag(stdout, mBlock);
|
||||
printf(": WARNING: xmost:%d\n", xmost);
|
||||
}
|
||||
#endif
|
||||
#ifdef NOISY_KIDXMOST
|
||||
printf("%p RecoverState block %p aState.mKidXMost=%d\n", this, mBlock, xmost);
|
||||
#endif
|
||||
mKidXMost = xmost;
|
||||
}
|
||||
if (GetFlag(BRS_COMPUTEMAXELEMENTWIDTH)) {
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyMaxElementWidth) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
printf("nsBlockReflowState::RecoverStateFrom block %p caching max width %d\n", mBlock, aLine->mMaxElementWidth);
|
||||
}
|
||||
#endif
|
||||
UpdateMaxElementWidth(aLine->mMaxElementWidth);
|
||||
|
||||
// Recover the float MEWs for floats in this line (but not in
|
||||
// blocks within it, since their MEWs are already part of the block's
|
||||
// MEW).
|
||||
if (aLine->HasFloats()) {
|
||||
for (nsFloatCache* fc = aLine->GetFirstFloat(); fc; fc = fc->Next())
|
||||
UpdateMaxElementWidth(fc->mMaxElementWidth);
|
||||
}
|
||||
}
|
||||
|
||||
// If computing the maximum width, then update mMaximumWidth
|
||||
if (GetFlag(BRS_COMPUTEMAXWIDTH)) {
|
||||
#ifdef NOISY_MAXIMUM_WIDTH
|
||||
printf("nsBlockReflowState::RecoverStateFrom block %p caching max width %d\n", mBlock, aLine->mMaximumWidth);
|
||||
#endif
|
||||
UpdateMaximumWidth(aLine->mMaximumWidth);
|
||||
}
|
||||
|
||||
// Place floats for this line into the space manager
|
||||
if (aLine->HasFloats() || aLine->IsBlock()) {
|
||||
// Undo border/padding translation since the nsFloatCache's
|
||||
@ -604,7 +512,6 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
||||
nsFloatCache* fc = mFloatCacheFreeList.Alloc();
|
||||
fc->mPlaceholder = aPlaceholder;
|
||||
fc->mIsCurrentLineFloat = aLineLayout.CanPlaceFloatNow();
|
||||
fc->mMaxElementWidth = 0;
|
||||
|
||||
PRBool placed;
|
||||
|
||||
@ -634,7 +541,7 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
||||
// Pass on updated available space to the current inline reflow engine
|
||||
GetAvailableSpace(mY, forceFit);
|
||||
aLineLayout.UpdateBand(mAvailSpaceRect.x + BorderPadding().left, mY,
|
||||
GetFlag(BRS_UNCONSTRAINEDWIDTH) ? NS_UNCONSTRAINEDSIZE : mAvailSpaceRect.width,
|
||||
mAvailSpaceRect.width,
|
||||
mAvailSpaceRect.height,
|
||||
isLeftFloat,
|
||||
aPlaceholder->GetOutOfFlowFrame());
|
||||
@ -675,41 +582,6 @@ nsBlockReflowState::AddFloat(nsLineLayout& aLineLayout,
|
||||
return placed;
|
||||
}
|
||||
|
||||
void
|
||||
nsBlockReflowState::UpdateMaxElementWidth(nscoord aMaxElementWidth)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
nscoord oldWidth = mMaxElementWidth;
|
||||
#endif
|
||||
if (aMaxElementWidth > mMaxElementWidth) {
|
||||
mMaxElementWidth = aMaxElementWidth;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyMaxElementWidth) {
|
||||
if (mMaxElementWidth != oldWidth) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
if (NS_UNCONSTRAINEDSIZE == mReflowState.availableWidth) {
|
||||
printf("PASS1 ");
|
||||
}
|
||||
nsFrame::ListTag(stdout, mBlock);
|
||||
printf(": old max-element-width=%d new=%d\n",
|
||||
oldWidth, mMaxElementWidth);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
nsBlockReflowState::UpdateMaximumWidth(nscoord aMaximumWidth)
|
||||
{
|
||||
if (aMaximumWidth > mMaximumWidth) {
|
||||
#ifdef NOISY_MAXIMUM_WIDTH
|
||||
printf("nsBlockReflowState::UpdateMaximumWidth block %p caching max width %d\n", mBlock, aMaximumWidth);
|
||||
#endif
|
||||
mMaximumWidth = aMaximumWidth;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsBlockReflowState::CanPlaceFloat(const nsSize& aFloatSize,
|
||||
PRUint8 aFloats, PRBool aForceFit)
|
||||
@ -934,6 +806,9 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||
mY += mAvailSpaceRect.height;
|
||||
GetAvailableSpace(mY, aForceFit);
|
||||
// reflow the float again now since we have more space
|
||||
// XXXldb We really don't need to Reflow in a loop, we just need
|
||||
// to ComputeSize in a loop (once ComputeSize depends on
|
||||
// availableWidth, which should make this work again).
|
||||
mBlock->ReflowFloat(*this, placeholder, aFloatCache, aReflowStatus);
|
||||
// Get the floats bounding box and margin information
|
||||
floatSize = floatFrame->GetSize();
|
||||
@ -961,20 +836,13 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||
}
|
||||
else {
|
||||
isLeftFloat = PR_FALSE;
|
||||
if (NS_UNCONSTRAINEDSIZE != mAvailSpaceRect.width) {
|
||||
if (!keepFloatOnSameLine) {
|
||||
floatX = mAvailSpaceRect.XMost() - floatSize.width;
|
||||
}
|
||||
else {
|
||||
// this is the IE quirk (see few lines above)
|
||||
// the table is keept in the same line: don't let it overlap the previous float
|
||||
floatX = mAvailSpaceRect.x;
|
||||
}
|
||||
}
|
||||
if (!keepFloatOnSameLine) {
|
||||
floatX = mAvailSpaceRect.XMost() - floatSize.width;
|
||||
}
|
||||
else {
|
||||
// For unconstrained reflows, pretend that a right float is
|
||||
// instead a left float. This will make us end up with the
|
||||
// correct unconstrained width, and we'll place it later.
|
||||
// this is the IE quirk (see few lines above)
|
||||
// the table is kept in the same line: don't let it overlap the
|
||||
// previous float
|
||||
floatX = mAvailSpaceRect.x;
|
||||
}
|
||||
}
|
||||
@ -1079,16 +947,7 @@ nsBlockReflowState::FlowAndPlaceFloat(nsFloatCache* aFloatCache,
|
||||
// reflow, and since there's no need to change the code that was
|
||||
// necessary back when the float was positioned relative to
|
||||
// NS_UNCONSTRAINEDSIZE.
|
||||
if (isLeftFloat ||
|
||||
!GetFlag(BRS_UNCONSTRAINEDWIDTH) ||
|
||||
!GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||
mFloatCombinedArea.UnionRect(combinedArea, mFloatCombinedArea);
|
||||
} else if (GetFlag(BRS_SHRINKWRAPWIDTH)) {
|
||||
// Mark the line dirty so we come back and re-place the float once
|
||||
// the shrink wrap width is determined
|
||||
mCurrentLine->MarkDirty();
|
||||
SetFlag(BRS_NEEDRESIZEREFLOW, PR_TRUE);
|
||||
}
|
||||
mFloatCombinedArea.UnionRect(combinedArea, mFloatCombinedArea);
|
||||
|
||||
// Now restore mY
|
||||
mY = saveY;
|
||||
|
@ -50,18 +50,13 @@
|
||||
class nsBlockFrame;
|
||||
|
||||
// block reflow state flags
|
||||
#define BRS_UNCONSTRAINEDWIDTH 0x00000001
|
||||
#define BRS_UNCONSTRAINEDHEIGHT 0x00000002
|
||||
#define BRS_SHRINKWRAPWIDTH 0x00000004
|
||||
#define BRS_NEEDRESIZEREFLOW 0x00000008
|
||||
#define BRS_ISTOPMARGINROOT 0x00000020 // Is this frame a root for top/bottom margin collapsing?
|
||||
#define BRS_ISBOTTOMMARGINROOT 0x00000040
|
||||
#define BRS_APPLYTOPMARGIN 0x00000080 // See ShouldApplyTopMargin
|
||||
#define BRS_COMPUTEMAXELEMENTWIDTH 0x00000100
|
||||
#define BRS_COMPUTEMAXWIDTH 0x00000200
|
||||
#define BRS_ISFIRSTINFLOW 0x00000400
|
||||
#define BRS_UNCONSTRAINEDHEIGHT 0x00000001
|
||||
#define BRS_ISTOPMARGINROOT 0x00000002 // Is this frame a root for top/bottom margin collapsing?
|
||||
#define BRS_ISBOTTOMMARGINROOT 0x00000004
|
||||
#define BRS_APPLYTOPMARGIN 0x00000008 // See ShouldApplyTopMargin
|
||||
#define BRS_ISFIRSTINFLOW 0x00000010
|
||||
// Set when mLineAdjacentToTop is valid
|
||||
#define BRS_HAVELINEADJACENTTOTOP 0x00000800
|
||||
#define BRS_HAVELINEADJACENTTOTOP 0x00000020
|
||||
#define BRS_LASTFLAG BRS_HAVELINEADJACENTTOTOP
|
||||
|
||||
class nsBlockReflowState {
|
||||
@ -127,10 +122,6 @@ public:
|
||||
return mReflowState.mComputedMargin;
|
||||
}
|
||||
|
||||
void UpdateMaxElementWidth(nscoord aMaxElementWidth);
|
||||
|
||||
void UpdateMaximumWidth(nscoord aMaximumWidth);
|
||||
|
||||
// Reconstruct the previous bottom margin that goes above |aLine|.
|
||||
void ReconstructMarginAbove(nsLineList::iterator aLine);
|
||||
|
||||
@ -218,9 +209,6 @@ public:
|
||||
// The available space within the current band.
|
||||
nsRect mAvailSpaceRect;
|
||||
|
||||
// The maximum x-most of each line
|
||||
nscoord mKidXMost;
|
||||
|
||||
// The combined area of all floats placed so far
|
||||
nsRect mFloatCombinedArea;
|
||||
|
||||
@ -258,11 +246,6 @@ public:
|
||||
// being N^2.
|
||||
nsFloatCacheFreeList mBelowCurrentLineFloats;
|
||||
|
||||
nscoord mMaxElementWidth;
|
||||
|
||||
// maximum width includes the left border/padding but not the right
|
||||
nscoord mMaximumWidth;
|
||||
|
||||
nscoord mMinLineHeight;
|
||||
|
||||
PRInt32 mLineNumber;
|
||||
|
@ -47,7 +47,6 @@
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsIRenderingContext.h"
|
||||
#include "nsILoadGroup.h"
|
||||
#include "nsIURL.h"
|
||||
@ -1408,17 +1407,9 @@ nsBulletFrame::GetListItemText(const nsStyleList& aListStyle,
|
||||
#define MIN_BULLET_SIZE 1
|
||||
|
||||
|
||||
#define MINMAX(_value,_min,_max) \
|
||||
((_value) < (_min) \
|
||||
? (_min) \
|
||||
: ((_value) > (_max) \
|
||||
? (_max) \
|
||||
: (_value)))
|
||||
|
||||
|
||||
void
|
||||
nsBulletFrame::GetDesiredSize(nsPresContext* aCX,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIRenderingContext *aRenderingContext,
|
||||
nsHTMLReflowMetrics& aMetrics)
|
||||
{
|
||||
// Reset our padding. If we need it, we'll set it below.
|
||||
@ -1432,73 +1423,9 @@ nsBulletFrame::GetDesiredSize(nsPresContext* aCX,
|
||||
mImageRequest->GetImageStatus(&status);
|
||||
if (status & imgIRequest::STATUS_SIZE_AVAILABLE &&
|
||||
!(status & imgIRequest::STATUS_ERROR)) {
|
||||
nscoord widthConstraint = NS_INTRINSICSIZE;
|
||||
nscoord heightConstraint = NS_INTRINSICSIZE;
|
||||
PRBool fixedContentWidth = PR_FALSE;
|
||||
PRBool fixedContentHeight = PR_FALSE;
|
||||
|
||||
nscoord minWidth, maxWidth, minHeight, maxHeight;
|
||||
|
||||
// Determine whether the image has fixed content width
|
||||
widthConstraint = aReflowState.mComputedWidth;
|
||||
minWidth = aReflowState.mComputedMinWidth;
|
||||
maxWidth = aReflowState.mComputedMaxWidth;
|
||||
if (widthConstraint != NS_INTRINSICSIZE) {
|
||||
fixedContentWidth = PR_TRUE;
|
||||
}
|
||||
|
||||
// Determine whether the image has fixed content height
|
||||
heightConstraint = aReflowState.mComputedHeight;
|
||||
minHeight = aReflowState.mComputedMinHeight;
|
||||
maxHeight = aReflowState.mComputedMaxHeight;
|
||||
if (heightConstraint != NS_UNCONSTRAINEDSIZE) {
|
||||
fixedContentHeight = PR_TRUE;
|
||||
}
|
||||
|
||||
PRBool haveComputedSize = PR_FALSE;
|
||||
PRBool needIntrinsicImageSize = PR_FALSE;
|
||||
|
||||
nscoord newWidth=0, newHeight=0;
|
||||
if (fixedContentWidth) {
|
||||
newWidth = MINMAX(widthConstraint, minWidth, maxWidth);
|
||||
if (fixedContentHeight) {
|
||||
newHeight = MINMAX(heightConstraint, minHeight, maxHeight);
|
||||
haveComputedSize = PR_TRUE;
|
||||
} else {
|
||||
// We have a width, and an auto height. Compute height from
|
||||
// width once we have the intrinsic image size.
|
||||
if (mIntrinsicSize.height != 0) {
|
||||
newHeight = (mIntrinsicSize.height * newWidth) / mIntrinsicSize.width;
|
||||
haveComputedSize = PR_TRUE;
|
||||
} else {
|
||||
newHeight = 0;
|
||||
needIntrinsicImageSize = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else if (fixedContentHeight) {
|
||||
// We have a height, and an auto width. Compute width from height
|
||||
// once we have the intrinsic image size.
|
||||
newHeight = MINMAX(heightConstraint, minHeight, maxHeight);
|
||||
if (mIntrinsicSize.width != 0) {
|
||||
newWidth = (mIntrinsicSize.width * newHeight) / mIntrinsicSize.height;
|
||||
haveComputedSize = PR_TRUE;
|
||||
} else {
|
||||
newWidth = 0;
|
||||
needIntrinsicImageSize = PR_TRUE;
|
||||
}
|
||||
} else {
|
||||
// auto size the image
|
||||
if (mIntrinsicSize.width == 0 && mIntrinsicSize.height == 0)
|
||||
needIntrinsicImageSize = PR_TRUE;
|
||||
else
|
||||
haveComputedSize = PR_TRUE;
|
||||
|
||||
newWidth = mIntrinsicSize.width;
|
||||
newHeight = mIntrinsicSize.height;
|
||||
}
|
||||
|
||||
mComputedSize.width = newWidth;
|
||||
mComputedSize.height = newHeight;
|
||||
// auto size the image
|
||||
mComputedSize.width = mIntrinsicSize.width;
|
||||
mComputedSize.height = mIntrinsicSize.height;
|
||||
|
||||
#if 0 // don't do scaled images in bullets
|
||||
if (mComputedSize == mIntrinsicSize) {
|
||||
@ -1617,8 +1544,8 @@ nsBulletFrame::GetDesiredSize(nsPresContext* aCX,
|
||||
case NS_STYLE_LIST_STYLE_MOZ_ETHIOPIC_HALEHAME_TI_ET:
|
||||
GetListItemText(*myList, text);
|
||||
fm->GetHeight(aMetrics.height);
|
||||
aReflowState.rendContext->SetFont(fm);
|
||||
aReflowState.rendContext->GetWidth(text, aMetrics.width);
|
||||
aRenderingContext->SetFont(fm);
|
||||
aRenderingContext->GetWidth(text, aMetrics.width);
|
||||
aMetrics.width += mPadding.right;
|
||||
fm->GetMaxAscent(aMetrics.ascent);
|
||||
fm->GetMaxDescent(aMetrics.descent);
|
||||
@ -1632,11 +1559,11 @@ nsBulletFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsBulletFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsBulletFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
||||
|
||||
// Get the base size
|
||||
GetDesiredSize(aPresContext, aReflowState, aMetrics);
|
||||
GetDesiredSize(aPresContext, aReflowState.rendContext, aMetrics);
|
||||
|
||||
// Add in the border and padding; split the top/bottom between the
|
||||
// ascent and descent to make things look nice
|
||||
@ -1646,14 +1573,29 @@ nsBulletFrame::Reflow(nsPresContext* aPresContext,
|
||||
aMetrics.ascent += borderPadding.top;
|
||||
aMetrics.descent += borderPadding.bottom;
|
||||
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.mMaxElementWidth = aMetrics.width;
|
||||
}
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsBulletFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nsHTMLReflowMetrics metrics;
|
||||
DISPLAY_MIN_WIDTH(this, metrics.width);
|
||||
GetDesiredSize(GetPresContext(), aRenderingContext, metrics);
|
||||
return metrics.width;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsBulletFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nsHTMLReflowMetrics metrics;
|
||||
DISPLAY_PREF_WIDTH(this, metrics.width);
|
||||
GetDesiredSize(GetPresContext(), aRenderingContext, metrics);
|
||||
return metrics.width;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP nsBulletFrame::OnStartContainer(imgIRequest *aRequest,
|
||||
imgIContainer *aImage)
|
||||
@ -1687,7 +1629,7 @@ NS_IMETHODIMP nsBulletFrame::OnStartContainer(imgIRequest *aRequest,
|
||||
NS_ASSERTION(mParent, "No parent to pass the reflow request up to.");
|
||||
if (mParent) {
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
mParent->ReflowDirtyChild(shell, this);
|
||||
shell->FrameNeedsReflow(this, nsIPresShell::eStyleChange);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,8 @@ public:
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
// nsBulletFrame
|
||||
PRInt32 SetListItemOrdinal(PRInt32 aNextOrdinal, PRBool* aChanged);
|
||||
@ -101,7 +103,7 @@ public:
|
||||
|
||||
protected:
|
||||
void GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsIRenderingContext *aRenderingContext,
|
||||
nsHTMLReflowMetrics& aMetrics);
|
||||
|
||||
void GetLoadGroup(nsPresContext *aPresContext, nsILoadGroup **aLoadGroup);
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsReflowPath.h"
|
||||
|
||||
class nsColumnSetFrame : public nsHTMLContainerFrame {
|
||||
public:
|
||||
@ -128,7 +127,6 @@ protected:
|
||||
*/
|
||||
PRBool ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowReason aReason,
|
||||
nsReflowStatus& aStatus,
|
||||
const ReflowConfig& aConfig,
|
||||
PRBool aLastColumnUnbounded,
|
||||
@ -327,14 +325,13 @@ static void MoveChildTo(nsIFrame* aParent, nsIFrame* aChild, nsPoint aOrigin) {
|
||||
PRBool
|
||||
nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowReason aKidReason,
|
||||
nsReflowStatus& aStatus,
|
||||
const ReflowConfig& aConfig,
|
||||
PRBool aUnboundedLastColumn,
|
||||
nsCollapsingMargin* aBottomMarginCarriedOut) {
|
||||
PRBool allFit = PR_TRUE;
|
||||
PRBool RTL = GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
|
||||
PRBool shrinkingHeightOnly = aKidReason == eReflowReason_Resize &&
|
||||
PRBool shrinkingHeightOnly = !(GetStateBits() & (NS_FRAME_IS_DIRTY|NS_FRAME_HAS_DIRTY_CHILDREN)) &&
|
||||
mLastBalanceHeight > aConfig.mColMaxHeight;
|
||||
|
||||
#ifdef DEBUG_roc
|
||||
@ -352,15 +349,14 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
||||
// We need a way to do an incremental reflow and be sure availableHeight
|
||||
// changes are taken account of! Right now I think block frames with absolute
|
||||
// children might exit early.
|
||||
NS_ASSERTION(aKidReason != eReflowReason_Incremental,
|
||||
"incremental reflow should not have changed the balance height");
|
||||
//NS_ASSERTION(aKidReason != eReflowReason_Incremental,
|
||||
// "incremental reflow should not have changed the balance height");
|
||||
}
|
||||
|
||||
// get our border and padding
|
||||
const nsMargin &borderPadding = aReflowState.mComputedBorderPadding;
|
||||
|
||||
nsRect contentRect(0, 0, 0, 0);
|
||||
aDesiredSize.mMaxElementWidth = 0;
|
||||
nsRect overflowRect(0, 0, 0, 0);
|
||||
|
||||
nsIFrame* child = mFrames.FirstChild();
|
||||
@ -391,11 +387,10 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
||||
// skip if the next column is dirty, because the next column's first line(s)
|
||||
// might be pullable back to this column. We can't skip if it's the last child
|
||||
// because we need to obtain the bottom margin.
|
||||
PRBool skipIncremental = aKidReason == eReflowReason_Incremental
|
||||
PRBool skipIncremental = !(GetStateBits() & NS_FRAME_IS_DIRTY)
|
||||
&& !(child->GetStateBits() & NS_FRAME_IS_DIRTY)
|
||||
&& child->GetNextSibling()
|
||||
&& !(child->GetNextSibling()->GetStateBits() & NS_FRAME_IS_DIRTY)
|
||||
&& !aDesiredSize.mComputeMEW;
|
||||
&& !(child->GetNextSibling()->GetStateBits() & NS_FRAME_IS_DIRTY);
|
||||
// If we need to pull up content from the prev-in-flow then this is not just
|
||||
// a height shrink. The prev in flow will have set the dirty bit.
|
||||
// Check the overflow rect YMost instead of just the child's content height. The child
|
||||
@ -426,23 +421,12 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
||||
availSize.height = GetAvailableContentHeight(aReflowState);
|
||||
}
|
||||
|
||||
nsReflowReason tmpReason = aKidReason;
|
||||
if (reflowNext && aKidReason == eReflowReason_Incremental
|
||||
&& !(child->GetStateBits() & NS_FRAME_IS_DIRTY)) {
|
||||
// If this frame was not being incrementally reflowed but was
|
||||
// just reflowed because the previous frame wants us to
|
||||
// reflow, then force this child to reflow its dirty lines!
|
||||
// XXX what we should really do here is add the child block to
|
||||
// the incremental reflow path! Currently I think if there's an
|
||||
// incremental reflow targeted only at the absolute frames of a
|
||||
// column, then the column will be dirty BUT reflowing it will
|
||||
// not reflow any lines affected by the prev-in-flow!
|
||||
tmpReason = eReflowReason_Dirty;
|
||||
}
|
||||
if (reflowNext)
|
||||
child->AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
|
||||
nsHTMLReflowState kidReflowState(GetPresContext(), aReflowState, child,
|
||||
availSize, availSize.width,
|
||||
aReflowState.mComputedHeight, tmpReason);
|
||||
aReflowState.mComputedHeight);
|
||||
kidReflowState.mFlags.mIsTopOfPage = PR_TRUE;
|
||||
|
||||
#ifdef DEBUG_roc
|
||||
@ -452,12 +436,13 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
||||
|
||||
// Note if the column's next in flow is not being changed by this incremental reflow.
|
||||
// This may allow the current column to avoid trying to pull lines from the next column.
|
||||
if (child->GetNextSibling() && aKidReason == eReflowReason_Incremental &&
|
||||
if (child->GetNextSibling() &&
|
||||
!(GetStateBits() & NS_FRAME_IS_DIRTY) &&
|
||||
!(child->GetNextSibling()->GetStateBits() & NS_FRAME_IS_DIRTY)) {
|
||||
kidReflowState.mFlags.mNextInFlowUntouched = PR_TRUE;
|
||||
}
|
||||
|
||||
nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mComputeMEW, aDesiredSize.mFlags);
|
||||
nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mFlags);
|
||||
|
||||
// XXX it would be cool to consult the space manager for the
|
||||
// previous block to figure out the region of floats from the
|
||||
@ -489,11 +474,6 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
||||
|
||||
FinishReflowChild(child, GetPresContext(), &kidReflowState,
|
||||
kidDesiredSize, childOrigin.x, childOrigin.y, 0);
|
||||
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = PR_MAX(aDesiredSize.mMaxElementWidth,
|
||||
kidDesiredSize.mMaxElementWidth);
|
||||
}
|
||||
}
|
||||
|
||||
contentRect.UnionRect(contentRect, child->GetRect());
|
||||
@ -525,9 +505,6 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
||||
}
|
||||
|
||||
kidNextInFlow->AddStateBits(NS_BLOCK_SPACE_MGR);
|
||||
|
||||
// Do an initial reflow if we're going to reflow this thing.
|
||||
aKidReason = eReflowReason_Initial;
|
||||
}
|
||||
|
||||
if (columnCount >= aConfig.mBalanceColCount) {
|
||||
@ -611,11 +588,6 @@ nsColumnSetFrame::ReflowChildren(nsHTMLReflowMetrics& aDesiredSize,
|
||||
aDesiredSize.width = contentSize.width + borderPadding.left + borderPadding.right;
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
aDesiredSize.mMaximumWidth = aDesiredSize.width;
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
// add in padding.
|
||||
aDesiredSize.mMaxElementWidth += borderPadding.left + borderPadding.right;
|
||||
}
|
||||
overflowRect.UnionRect(overflowRect, nsRect(0, 0, aDesiredSize.width, aDesiredSize.height));
|
||||
aDesiredSize.mOverflowArea = overflowRect;
|
||||
|
||||
@ -680,44 +652,13 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsColumnSetFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsColumnSetFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
// Initialize OUT parameter
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
//------------ Handle Incremental Reflow -----------------
|
||||
nsReflowReason kidReason = aReflowState.reason;
|
||||
|
||||
if ( aReflowState.reason == eReflowReason_Incremental ) {
|
||||
nsHTMLReflowCommand *command = aReflowState.path->mReflowCommand;
|
||||
|
||||
// Dirty any frames on the incremental reflow path
|
||||
nsReflowPath *path = aReflowState.path;
|
||||
nsReflowPath::iterator iter = path->FirstChild();
|
||||
nsReflowPath::iterator end = path->EndChildren();
|
||||
for ( ; iter != end; ++iter) {
|
||||
(*iter)->AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
}
|
||||
|
||||
// See if it's targeted at us
|
||||
if (command) {
|
||||
switch (command->Type()) {
|
||||
|
||||
case eReflowType_StyleChanged:
|
||||
kidReason = eReflowReason_StyleChange;
|
||||
break;
|
||||
|
||||
// if it's a dirty type then reflow us with a dirty reflow
|
||||
case eReflowType_ReflowDirty:
|
||||
kidReason = eReflowReason_Dirty;
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ERROR("Unexpected Reflow Type");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ReflowConfig config = ChooseColumnStrategy(aReflowState);
|
||||
PRBool isBalancing = config.mBalanceColCount < PR_INT32_MAX;
|
||||
@ -731,22 +672,10 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsIFrame* nextInFlow = GetNextInFlow();
|
||||
PRBool unboundedLastColumn = isBalancing && nextInFlow;
|
||||
nsCollapsingMargin carriedOutBottomMargin;
|
||||
PRBool feasible = ReflowChildren(aDesiredSize, aReflowState, kidReason,
|
||||
PRBool feasible = ReflowChildren(aDesiredSize, aReflowState,
|
||||
aStatus, config, unboundedLastColumn, &carriedOutBottomMargin);
|
||||
|
||||
if (isBalancing) {
|
||||
if (feasible ||
|
||||
// All children were reflowed as necessary, so we can go ahead
|
||||
// and do resize reflows from now on
|
||||
kidReason != eReflowReason_StyleChange) {
|
||||
// Any non-stylechange reflow can be followed by resize
|
||||
// reflows. But a stylechange reflow demands that all children
|
||||
// be reflowed, which may not have happened yet; some of them
|
||||
// might just have been pushed to an overflow list. So we have to
|
||||
// keep doing stylechange reflows.
|
||||
kidReason = eReflowReason_Resize;
|
||||
}
|
||||
|
||||
nscoord availableContentHeight = GetAvailableContentHeight(aReflowState);
|
||||
|
||||
// Termination of the algorithm below is guaranteed because
|
||||
@ -848,8 +777,9 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
|
||||
config.mColMaxHeight = nextGuess;
|
||||
|
||||
unboundedLastColumn = PR_FALSE;
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
feasible = ReflowChildren(aDesiredSize, aReflowState,
|
||||
kidReason, aStatus, config, PR_FALSE,
|
||||
aStatus, config, PR_FALSE,
|
||||
&carriedOutBottomMargin);
|
||||
}
|
||||
|
||||
@ -866,7 +796,8 @@ nsColumnSetFrame::Reflow(nsPresContext* aPresContext,
|
||||
config.mColMaxHeight = knownFeasibleHeight;
|
||||
}
|
||||
if (!skip) {
|
||||
ReflowChildren(aDesiredSize, aReflowState, eReflowReason_Resize,
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
ReflowChildren(aDesiredSize, aReflowState,
|
||||
aStatus, config, PR_FALSE, &carriedOutBottomMargin);
|
||||
}
|
||||
}
|
||||
|
@ -227,18 +227,10 @@ nsContainerFrame::BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aB
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsContainerFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild)
|
||||
/* virtual */ void
|
||||
nsContainerFrame::ChildIsDirty(nsIFrame* aChild)
|
||||
{
|
||||
// The container frame always generates a reflow command
|
||||
// targeted at its child
|
||||
// Note that even if this flag is already set, we still need to reflow the
|
||||
// child because the frame may have more than one child
|
||||
mState |= NS_FRAME_HAS_DIRTY_CHILDREN;
|
||||
|
||||
aPresShell->AppendReflowCommand(aChild, eReflowType_ReflowDirty, nsnull);
|
||||
|
||||
return NS_OK;
|
||||
AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
|
||||
}
|
||||
|
||||
PRBool
|
||||
@ -698,6 +690,91 @@ nsContainerFrame::FrameNeedsView(nsIFrame* aFrame)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
static nscoord GetCoord(const nsStyleCoord& aCoord, nscoord aIfNotCoord)
|
||||
{
|
||||
return aCoord.GetUnit() == eStyleUnit_Coord
|
||||
? aCoord.GetCoordValue()
|
||||
: aIfNotCoord;
|
||||
}
|
||||
|
||||
void
|
||||
nsContainerFrame::DoInlineIntrinsicWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineIntrinsicWidthData *aData,
|
||||
nsLayoutUtils::IntrinsicWidthType aType)
|
||||
{
|
||||
if (GetPrevInFlow())
|
||||
return; // Already added.
|
||||
|
||||
NS_PRECONDITION(aType == nsLayoutUtils::MIN_WIDTH ||
|
||||
aType == nsLayoutUtils::PREF_WIDTH, "bad type");
|
||||
|
||||
PRUint8 startSide, endSide;
|
||||
if (GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR) {
|
||||
startSide = NS_SIDE_LEFT;
|
||||
endSide = NS_SIDE_RIGHT;
|
||||
} else {
|
||||
startSide = NS_SIDE_RIGHT;
|
||||
endSide = NS_SIDE_LEFT;
|
||||
}
|
||||
|
||||
const nsStylePadding *stylePadding = GetStylePadding();
|
||||
const nsStyleBorder *styleBorder = GetStyleBorder();
|
||||
const nsStyleMargin *styleMargin = GetStyleMargin();
|
||||
nsStyleCoord tmp;
|
||||
|
||||
// This goes at the beginning no matter how things are broken and how
|
||||
// messy the bidi situations are, since per CSS2.1 section 8.6
|
||||
// (implemented in bug 328168), the startSide border is always on the
|
||||
// first line.
|
||||
aData->currentLine +=
|
||||
GetCoord(stylePadding->mPadding.Get(startSide, tmp), 0) +
|
||||
styleBorder->GetBorderWidth(startSide) +
|
||||
GetCoord(styleMargin->mMargin.Get(startSide, tmp), 0);
|
||||
|
||||
for (nsContainerFrame *nif = this; nif;
|
||||
nif = (nsContainerFrame*) nif->GetNextInFlow()) {
|
||||
for (nsIFrame *kid = nif->mFrames.FirstChild(); kid;
|
||||
kid = kid->GetNextSibling()) {
|
||||
if (aType == nsLayoutUtils::MIN_WIDTH)
|
||||
kid->AddInlineMinWidth(aRenderingContext,
|
||||
NS_STATIC_CAST(InlineMinWidthData*, aData));
|
||||
else
|
||||
kid->AddInlinePrefWidth(aRenderingContext,
|
||||
NS_STATIC_CAST(InlinePrefWidthData*, aData));
|
||||
}
|
||||
}
|
||||
|
||||
// This goes at the end no matter how things are broken and how
|
||||
// messy the bidi situations are, since per CSS2.1 section 8.6
|
||||
// (implemented in bug 328168), the endSide border is always on the
|
||||
// last line.
|
||||
aData->currentLine +=
|
||||
GetCoord(stylePadding->mPadding.Get(endSide, tmp), 0) +
|
||||
styleBorder->GetBorderWidth(endSide) +
|
||||
GetCoord(styleMargin->mMargin.Get(endSide, tmp), 0);
|
||||
}
|
||||
|
||||
/* virtual */ nsSize
|
||||
nsContainerFrame::ComputeAutoSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder,
|
||||
nsSize aPadding, PRBool aShrinkWrap)
|
||||
{
|
||||
nsSize result(0xdeadbeef, NS_UNCONSTRAINEDSIZE);
|
||||
nscoord availBased = aAvailableWidth - aMargin.width - aBorder.width -
|
||||
aPadding.width;
|
||||
// replaced elements always shrink-wrap
|
||||
if (aShrinkWrap || IsFrameOfType(eReplaced)) {
|
||||
// don't bother setting it if the result won't be used
|
||||
if (GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto) {
|
||||
result.width = ShrinkWidthToFit(aRenderingContext, availBased);
|
||||
}
|
||||
} else {
|
||||
result.width = availBased;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the WillReflow() function, positions the frame and its view (if
|
||||
* requested), and then calls Reflow(). If the reflow succeeds and the child
|
||||
@ -717,14 +794,6 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
||||
|
||||
nsresult result;
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef REALLY_NOISY_MAX_ELEMENT_SIZE
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = nscoord(0xdeadbeef);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Send the WillReflow() notification, and position the child frame
|
||||
// and its view if requested
|
||||
aKidFrame->WillReflow(aPresContext);
|
||||
@ -741,17 +810,6 @@ nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
||||
result = aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowState,
|
||||
aStatus);
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef REALLY_NOISY_MAX_ELEMENT_SIZE
|
||||
if (aDesiredSize.mComputeMEW &&
|
||||
(nscoord(0xdeadbeef) == aDesiredSize.mMaxElementWidth)) {
|
||||
printf("nsContainerFrame: ");
|
||||
nsFrame::ListTag(stdout, aKidFrame);
|
||||
printf(" didn't set max-element-width!\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If the reflow was successful and the child frame is complete, delete any
|
||||
// next-in-flows
|
||||
if (NS_SUCCEEDED(result) && NS_FRAME_IS_COMPLETE(aStatus)) {
|
||||
|
@ -42,6 +42,7 @@
|
||||
|
||||
#include "nsSplittableFrame.h"
|
||||
#include "nsFrameList.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
||||
// Option flags for ReflowChild() and FinishReflowChild()
|
||||
// member functions
|
||||
@ -65,7 +66,7 @@ public:
|
||||
virtual nsIFrame* GetFirstChild(nsIAtom* aListName) const;
|
||||
virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
|
||||
virtual void Destroy();
|
||||
NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild);
|
||||
virtual void ChildIsDirty(nsIFrame* aChild);
|
||||
|
||||
virtual PRBool IsLeaf() const;
|
||||
|
||||
@ -124,6 +125,20 @@ public:
|
||||
// Returns PR_TRUE if the frame requires a view
|
||||
static PRBool FrameNeedsView(nsIFrame* aFrame);
|
||||
|
||||
// Used by both nsInlineFrame and nsFirstLetterFrame.
|
||||
void DoInlineIntrinsicWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineIntrinsicWidthData *aData,
|
||||
nsLayoutUtils::IntrinsicWidthType aType);
|
||||
|
||||
/**
|
||||
* This is the CSS block concept of computing 'auto' widths, which most
|
||||
* classes derived from nsContainerFrame want.
|
||||
*/
|
||||
virtual nsSize ComputeAutoSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder,
|
||||
nsSize aPadding, PRBool aShrinkWrap);
|
||||
|
||||
/**
|
||||
* Invokes the WillReflow() function, positions the frame and its view (if
|
||||
* requested), and then calls Reflow(). If the reflow succeeds and the child
|
||||
|
@ -66,12 +66,18 @@ public:
|
||||
virtual nsIAtom* GetType() const;
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual void AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineMinWidthData *aData);
|
||||
virtual void AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlinePrefWidthData *aData);
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
NS_IMETHOD CanContinueTextRun(PRBool& aContinueTextRun) const;
|
||||
virtual PRBool CanContinueTextRun() const;
|
||||
|
||||
NS_IMETHOD SetSelected(nsPresContext* aPresContext, nsIDOMRange *aRange,PRBool aSelected, nsSpread aSpread);
|
||||
|
||||
@ -185,13 +191,45 @@ nsFirstLetterFrame::GetChildFrameContainingOffset(PRInt32 inContentOffset,
|
||||
return nsFrame::GetChildFrameContainingOffset(inContentOffset, inHint, outFrameContentOffset, outChildFrame);
|
||||
}
|
||||
|
||||
// Needed for non-floating first-letter frames and for the continuations
|
||||
// following the first-letter that we also use nsFirstLetterFrame for.
|
||||
/* virtual */ void
|
||||
nsFirstLetterFrame::AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlineMinWidthData *aData)
|
||||
{
|
||||
DoInlineIntrinsicWidth(aRenderingContext, aData, nsLayoutUtils::MIN_WIDTH);
|
||||
}
|
||||
|
||||
// Needed for non-floating first-letter frames and for the continuations
|
||||
// following the first-letter that we also use nsFirstLetterFrame for.
|
||||
/* virtual */ void
|
||||
nsFirstLetterFrame::AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlinePrefWidthData *aData)
|
||||
{
|
||||
DoInlineIntrinsicWidth(aRenderingContext, aData, nsLayoutUtils::PREF_WIDTH);
|
||||
}
|
||||
|
||||
// Needed for floating first-letter frames.
|
||||
/* virtual */ nscoord
|
||||
nsFirstLetterFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
return nsLayoutUtils::MinWidthFromInline(this, aRenderingContext);
|
||||
}
|
||||
|
||||
// Needed for floating first-letter frames.
|
||||
/* virtual */ nscoord
|
||||
nsFirstLetterFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
return nsLayoutUtils::PrefWidthFromInline(this, aRenderingContext);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aReflowStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsFirstLetterFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsFirstLetterFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aReflowStatus);
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
@ -218,8 +256,7 @@ nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
|
||||
// only time that the first-letter-frame is not reflowing in a
|
||||
// line context is when its floating.
|
||||
nsHTMLReflowState rs(aPresContext, aReflowState, kid, availSize);
|
||||
nsLineLayout ll(aPresContext, nsnull, &aReflowState,
|
||||
aMetrics.mComputeMEW);
|
||||
nsLineLayout ll(aPresContext, nsnull, &aReflowState);
|
||||
ll.BeginLineReflow(0, 0, NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE,
|
||||
PR_FALSE, PR_TRUE);
|
||||
rs.mLineLayout = ≪
|
||||
@ -238,8 +275,7 @@ nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
|
||||
ll->BeginSpan(this, &aReflowState, bp.left, availSize.width);
|
||||
ll->ReflowFrame(kid, aReflowStatus, &aMetrics, pushedFrame);
|
||||
nsSize size;
|
||||
ll->EndSpan(this, size,
|
||||
aMetrics.mComputeMEW ? &aMetrics.mMaxElementWidth : nsnull);
|
||||
ll->EndSpan(this, size);
|
||||
}
|
||||
|
||||
// Place and size the child and update the output metrics
|
||||
@ -249,9 +285,6 @@ nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
|
||||
aMetrics.height += tb;
|
||||
aMetrics.ascent += bp.top;
|
||||
aMetrics.descent += bp.bottom;
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.mMaxElementWidth += lr;
|
||||
}
|
||||
|
||||
// Create a continuation or remove existing continuations based on
|
||||
// the reflow completion status.
|
||||
@ -290,12 +323,11 @@ nsFirstLetterFrame::Reflow(nsPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFirstLetterFrame::CanContinueTextRun(PRBool& aContinueTextRun) const
|
||||
/* virtual */ PRBool
|
||||
nsFirstLetterFrame::CanContinueTextRun() const
|
||||
{
|
||||
// We can continue a text run through a first-letter frame.
|
||||
aContinueTextRun = PR_TRUE;
|
||||
return NS_OK;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -50,7 +50,6 @@
|
||||
#endif
|
||||
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsHTMLReflowCommand.h"
|
||||
#include "nsFrameSelection.h"
|
||||
#include "nsHTMLReflowState.h"
|
||||
#include "nsHTMLReflowMetrics.h"
|
||||
@ -115,6 +114,7 @@
|
||||
#endif
|
||||
|
||||
// handy utilities
|
||||
// XXXldb Move to nsLayoutUtils!
|
||||
void SetFontFromStyle(nsIRenderingContext* aRC, nsStyleContext* aSC);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
@ -259,7 +259,7 @@ public:
|
||||
NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval);
|
||||
|
||||
NS_IMETHOD GetOffsets(PRInt32 &aStart, PRInt32 &aEnd) const;
|
||||
NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild);
|
||||
virtual void ChildIsDirty(nsIFrame* aChild);
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible);
|
||||
@ -272,7 +272,47 @@ public:
|
||||
virtual PRBool IsEmpty();
|
||||
virtual PRBool IsSelfEmpty();
|
||||
|
||||
// nsIHTMLReflow
|
||||
virtual void MarkIntrinsicWidthsDirty();
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual void AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineMinWidthData *aData);
|
||||
virtual void AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlinePrefWidthData *aData);
|
||||
virtual IntrinsicWidthOffsetData IntrinsicWidthOffsets();
|
||||
|
||||
virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap);
|
||||
|
||||
/**
|
||||
* A helper, used by |nsFrame::ComputeSize| (for frames that need to
|
||||
* override only this part of ComputeSize), that computes the size
|
||||
* that should be returned when 'width', 'height', and
|
||||
* min/max-width/height are all 'auto' or equivalent.
|
||||
*
|
||||
* In general, frames that can accept any computed width/height should
|
||||
* override only ComputeAutoSize, and frames that cannot do so need to
|
||||
* override ComputeSize to enforce their width/height invariants.
|
||||
*
|
||||
* Implementations may optimize by returning a garbage width if
|
||||
* GetStylePosition()->mWidth.GetUnit() == eStyleUnit_Auto, and
|
||||
* likewise for height, since in such cases the result is guaranteed
|
||||
* to be unused.
|
||||
*/
|
||||
virtual nsSize ComputeAutoSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder,
|
||||
nsSize aPadding, PRBool aShrinkWrap);
|
||||
|
||||
/**
|
||||
* Utility function for ComputeAutoSize implementations. Return
|
||||
* max(GetMinWidth(), min(aWidthInCB, GetPrefWidth()))
|
||||
*/
|
||||
nscoord ShrinkWidthToFit(nsIRenderingContext *aRenderingContext,
|
||||
nscoord aWidthInCB);
|
||||
|
||||
NS_IMETHOD WillReflow(nsPresContext* aPresContext);
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
@ -281,7 +321,7 @@ public:
|
||||
NS_IMETHOD DidReflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState* aReflowState,
|
||||
nsDidReflowStatus aStatus);
|
||||
NS_IMETHOD CanContinueTextRun(PRBool& aContinueTextRun) const;
|
||||
virtual PRBool CanContinueTextRun() const;
|
||||
NS_IMETHOD TrimTrailingWhiteSpace(nsPresContext* aPresContext,
|
||||
nsIRenderingContext& aRC,
|
||||
nscoord& aDeltaWidth,
|
||||
@ -326,7 +366,6 @@ public:
|
||||
NS_IMETHOD GetAscent(nsBoxLayoutState& aBoxLayoutState, nscoord& aAscent);
|
||||
NS_IMETHOD SetIncludeOverflow(PRBool aInclude);
|
||||
NS_IMETHOD GetOverflow(nsSize& aOverflow);
|
||||
NS_IMETHOD NeedsRecalc();
|
||||
|
||||
//--------------------------------------------------
|
||||
// Additional methods
|
||||
@ -431,11 +470,26 @@ public:
|
||||
static void* DisplayReflowEnter(nsPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
const nsHTMLReflowState& aReflowState);
|
||||
static void* DisplayLayoutEnter(nsIFrame* aFrame);
|
||||
static void* DisplayIntrinsicWidthEnter(nsIFrame* aFrame,
|
||||
const char* aType);
|
||||
static void* DisplayIntrinsicSizeEnter(nsIFrame* aFrame,
|
||||
const char* aType);
|
||||
static void DisplayReflowExit(nsPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
PRUint32 aStatus,
|
||||
void* aFrameTreeNode);
|
||||
static void DisplayLayoutExit(nsIFrame* aFrame,
|
||||
void* aFrameTreeNode);
|
||||
static void DisplayIntrinsicWidthExit(nsIFrame* aFrame,
|
||||
const char* aType,
|
||||
nscoord aResult,
|
||||
void* aFrameTreeNode);
|
||||
static void DisplayIntrinsicSizeExit(nsIFrame* aFrame,
|
||||
const char* aType,
|
||||
nsSize aResult,
|
||||
void* aFrameTreeNode);
|
||||
|
||||
static void DisplayReflowStartup();
|
||||
static void DisplayReflowShutdown();
|
||||
@ -523,8 +577,6 @@ protected:
|
||||
#ifdef DEBUG_LAYOUT
|
||||
virtual void GetBoxName(nsAutoString& aName);
|
||||
#endif
|
||||
virtual PRBool HasStyleChange();
|
||||
virtual void SetStyleChangeFlag(PRBool aDirty);
|
||||
|
||||
virtual PRBool GetWasCollapsed(nsBoxLayoutState& aState);
|
||||
virtual void SetWasCollapsed(nsBoxLayoutState& aState, PRBool aWas);
|
||||
@ -539,27 +591,13 @@ private:
|
||||
nsresult BoxReflow(nsBoxLayoutState& aState,
|
||||
nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus,
|
||||
nsIRenderingContext* aRenderingContext,
|
||||
nscoord aX,
|
||||
nscoord aY,
|
||||
nscoord aWidth,
|
||||
nscoord aHeight,
|
||||
PRBool aMoveFrame = PR_TRUE);
|
||||
|
||||
void HandleIncrementalReflow(nsBoxLayoutState& aState,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowReason& aReason,
|
||||
nsReflowPath** aReflowPath,
|
||||
PRBool& aRedrawNow,
|
||||
PRBool& aNeedReflow,
|
||||
PRBool& aRedrawAfterReflow,
|
||||
PRBool& aMoveFrame);
|
||||
|
||||
PRBool CanSetMaxElementWidth(nsBoxLayoutState& aState,
|
||||
nsReflowReason& aReason,
|
||||
nsReflowPath **aReflowPath);
|
||||
|
||||
NS_IMETHODIMP RefreshSizeCache(nsBoxLayoutState& aState);
|
||||
|
||||
protected:
|
||||
@ -586,16 +624,64 @@ protected:
|
||||
nsReflowStatus& mStatus;
|
||||
void* mValue;
|
||||
};
|
||||
|
||||
struct DR_layout_cookie {
|
||||
DR_layout_cookie(nsIFrame* aFrame);
|
||||
~DR_layout_cookie();
|
||||
|
||||
nsIFrame* mFrame;
|
||||
void* mValue;
|
||||
};
|
||||
|
||||
struct DR_intrinsic_width_cookie {
|
||||
DR_intrinsic_width_cookie(nsIFrame* aFrame, const char* aType,
|
||||
nscoord& aResult);
|
||||
~DR_intrinsic_width_cookie();
|
||||
|
||||
nsIFrame* mFrame;
|
||||
const char* mType;
|
||||
nscoord& mResult;
|
||||
void* mValue;
|
||||
};
|
||||
|
||||
struct DR_intrinsic_size_cookie {
|
||||
DR_intrinsic_size_cookie(nsIFrame* aFrame, const char* aType,
|
||||
nsSize& aResult);
|
||||
~DR_intrinsic_size_cookie();
|
||||
|
||||
nsIFrame* mFrame;
|
||||
const char* mType;
|
||||
nsSize& mResult;
|
||||
void* mValue;
|
||||
};
|
||||
|
||||
#define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status) \
|
||||
DR_cookie dr_cookie(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status);
|
||||
#define DISPLAY_REFLOW_CHANGE() \
|
||||
dr_cookie.Change();
|
||||
#define DISPLAY_LAYOUT(dr_frame) \
|
||||
DR_layout_cookie dr_cookie(dr_frame);
|
||||
#define DISPLAY_MIN_WIDTH(dr_frame, dr_result) \
|
||||
DR_intrinsic_width_cookie dr_cookie(dr_frame, "Min", dr_result)
|
||||
#define DISPLAY_PREF_WIDTH(dr_frame, dr_result) \
|
||||
DR_intrinsic_width_cookie dr_cookie(dr_frame, "Pref", dr_result)
|
||||
#define DISPLAY_PREF_SIZE(dr_frame, dr_result) \
|
||||
DR_intrinsic_size_cookie dr_cookie(dr_frame, "Pref", dr_result)
|
||||
#define DISPLAY_MIN_SIZE(dr_frame, dr_result) \
|
||||
DR_intrinsic_size_cookie dr_cookie(dr_frame, "Min", dr_result)
|
||||
#define DISPLAY_MAX_SIZE(dr_frame, dr_result) \
|
||||
DR_intrinsic_size_cookie dr_cookie(dr_frame, "Max", dr_result)
|
||||
|
||||
#else
|
||||
|
||||
#define DISPLAY_REFLOW(dr_pres_context, dr_frame, dr_rf_state, dr_rf_metrics, dr_rf_status)
|
||||
#define DISPLAY_REFLOW_CHANGE()
|
||||
#define DISPLAY_LAYOUT(dr_frame) PR_BEGIN_MACRO PR_END_MACRO
|
||||
#define DISPLAY_MIN_WIDTH(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
|
||||
#define DISPLAY_PREF_WIDTH(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
|
||||
#define DISPLAY_PREF_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
|
||||
#define DISPLAY_MIN_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
|
||||
#define DISPLAY_MAX_SIZE(dr_frame, dr_result) PR_BEGIN_MACRO PR_END_MACRO
|
||||
|
||||
#endif
|
||||
// End Display Reflow Debugging
|
||||
|
@ -118,6 +118,7 @@ public:
|
||||
NS_IMETHOD_(nsrefcnt) Release(void) { return 1; }
|
||||
|
||||
virtual nsIAtom* GetType() const;
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
NS_IMETHOD Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
@ -125,6 +126,9 @@ public:
|
||||
|
||||
virtual void Destroy();
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -159,9 +163,9 @@ protected:
|
||||
nsresult ShowDocShell();
|
||||
nsresult CreateViewAndWidget(nsContentType aContentType);
|
||||
|
||||
virtual void GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
virtual nscoord GetIntrinsicWidth();
|
||||
virtual nscoord GetIntrinsicHeight();
|
||||
|
||||
virtual PRIntn GetSkipSides() const;
|
||||
|
||||
nsCOMPtr<nsIFrameLoader> mFrameLoader;
|
||||
@ -312,36 +316,35 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsSubDocumentFrame::GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize)
|
||||
nscoord
|
||||
nsSubDocumentFrame::GetIntrinsicWidth()
|
||||
{
|
||||
if (!IsInline()) {
|
||||
return 0; // <frame> has no useful intrinsic width
|
||||
}
|
||||
|
||||
if (!mContent->IsNodeOfType(nsINode::eXUL)) {
|
||||
return 0; // <xul:iframe> also has no useful intrinsic width
|
||||
}
|
||||
|
||||
// We must be an HTML <iframe>. Default to a width of 300, for IE
|
||||
// compat (and per CSS2.1 draft).
|
||||
return NSIntPixelsToTwips(300, GetPresContext()->ScaledPixelsToTwips());
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsSubDocumentFrame::GetIntrinsicHeight()
|
||||
{
|
||||
// <frame> processing does not use this routine, only <iframe>
|
||||
float p2t = 0;
|
||||
if (!mContent->IsNodeOfType(nsINode::eXUL))
|
||||
// If no width/height was specified, use 300/150.
|
||||
// This is for compatibility with IE.
|
||||
p2t = aPresContext->ScaledPixelsToTwips();
|
||||
NS_ASSERTION(IsInline(), "Shouldn't have been called");
|
||||
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedWidth) {
|
||||
aDesiredSize.width = aReflowState.mComputedWidth;
|
||||
if (mContent->IsNodeOfType(nsINode::eXUL)) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
aDesiredSize.width = PR_MAX(PR_MIN(NSIntPixelsToTwips(300, p2t),
|
||||
aReflowState.mComputedMaxWidth),
|
||||
aReflowState.mComputedMinWidth);
|
||||
}
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.mComputedHeight) {
|
||||
aDesiredSize.height = aReflowState.mComputedHeight;
|
||||
}
|
||||
else {
|
||||
aDesiredSize.height = PR_MAX(PR_MIN(NSIntPixelsToTwips(150, p2t),
|
||||
aReflowState.mComputedMaxHeight),
|
||||
aReflowState.mComputedMinHeight);
|
||||
}
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
|
||||
// Use 150px, for compatibility with IE, and per CSS2.1 draft.
|
||||
return NSIntPixelsToTwips(150,
|
||||
GetPresContext()->ScaledPixelsToTwips());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -357,69 +360,73 @@ nsSubDocumentFrame::GetType() const
|
||||
return nsLayoutAtoms::subDocumentFrame;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsSubDocumentFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced | eReplacedContainsBlock));
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsSubDocumentFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
return nsSubDocumentFrame::GetPrefWidth(aRenderingContext);
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsSubDocumentFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
// XUL frames don't have a default 300px width
|
||||
nscoord result;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
if (mContent->IsNodeOfType(nsINode::eXUL))
|
||||
result = 0;
|
||||
else
|
||||
result = NSIntPixelsToTwips(300, GetPresContext()->ScaledPixelsToTwips());
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSubDocumentFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsSubDocumentFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsSubDocumentFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
// printf("OuterFrame::Reflow %X (%d,%d) \n", this, aReflowState.availableWidth, aReflowState.availableHeight);
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("enter nsSubDocumentFrame::Reflow: maxSize=%d,%d reason=%d",
|
||||
aReflowState.availableWidth, aReflowState.availableHeight, aReflowState.reason));
|
||||
("enter nsSubDocumentFrame::Reflow: maxSize=%d,%d",
|
||||
aReflowState.availableWidth, aReflowState.availableHeight));
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
// "offset" is the offset of our content area from our frame's
|
||||
// top-left corner.
|
||||
nsPoint offset(0, 0);
|
||||
|
||||
if (IsInline()) {
|
||||
GetDesiredSize(aPresContext, aReflowState, aDesiredSize); // IFRAME
|
||||
// IFRAME
|
||||
nsresult rv = nsLeafFrame::Reflow(aPresContext, aDesiredSize, aReflowState,
|
||||
aStatus);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
offset = nsPoint(aReflowState.mComputedBorderPadding.left,
|
||||
aReflowState.mComputedBorderPadding.top);
|
||||
} else {
|
||||
aDesiredSize.width = aReflowState.availableWidth; // FRAME
|
||||
aDesiredSize.height = aReflowState.availableHeight;
|
||||
// FRAME
|
||||
SizeToAvailSize(aReflowState, aDesiredSize);
|
||||
}
|
||||
|
||||
nsSize innerSize(aDesiredSize.width, aDesiredSize.height);
|
||||
nsPoint offset(0, 0);
|
||||
nsMargin border = aReflowState.mComputedBorderPadding;
|
||||
|
||||
if (IsInline()) {
|
||||
offset = nsPoint(border.left, border.top);
|
||||
aDesiredSize.width += border.left + border.right;
|
||||
aDesiredSize.height += border.top + border.bottom;
|
||||
innerSize.width -= aReflowState.mComputedBorderPadding.LeftRight();
|
||||
innerSize.height -= aReflowState.mComputedBorderPadding.TopBottom();
|
||||
}
|
||||
|
||||
nsIViewManager* vm = mInnerView->GetViewManager();
|
||||
vm->MoveViewTo(mInnerView, offset.x, offset.y);
|
||||
vm->ResizeView(mInnerView, nsRect(nsPoint(0, 0), innerSize), PR_TRUE);
|
||||
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
nscoord defaultAutoWidth = NSIntPixelsToTwips(300, aPresContext->ScaledPixelsToTwips());
|
||||
if (mContent->IsNodeOfType(nsINode::eXUL)) {
|
||||
// XUL frames don't have a default 300px width
|
||||
defaultAutoWidth = 0;
|
||||
}
|
||||
nsStyleUnit widthUnit = GetStylePosition()->mWidth.GetUnit();
|
||||
switch (widthUnit) {
|
||||
case eStyleUnit_Percent:
|
||||
// if our width is percentage, then we can shrink until
|
||||
// there's nothing left but our borders
|
||||
aDesiredSize.mMaxElementWidth = border.left + border.right;
|
||||
break;
|
||||
case eStyleUnit_Auto:
|
||||
aDesiredSize.mMaxElementWidth = PR_MAX(PR_MIN(defaultAutoWidth,
|
||||
aReflowState.mComputedMaxWidth),
|
||||
aReflowState.mComputedMinWidth) +
|
||||
border.left + border.right;
|
||||
break;
|
||||
default:
|
||||
// If our width is set by style to some fixed length,
|
||||
// then our actual width is our minimum width
|
||||
aDesiredSize.mMaxElementWidth = aDesiredSize.width;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if we need to repaint our border, background or outline
|
||||
CheckInvalidateSizeChange(aPresContext, aDesiredSize, aReflowState);
|
||||
|
||||
@ -447,9 +454,8 @@ nsSubDocumentFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
// printf("OuterFrame::Reflow DONE %X (%d,%d), MEW=%d(%d)\n", this,
|
||||
// aDesiredSize.width, aDesiredSize.height, aDesiredSize.mMaxElementWidth,
|
||||
// aDesiredSize.mComputeMEW);
|
||||
// printf("OuterFrame::Reflow DONE %X (%d,%d)\n", this,
|
||||
// aDesiredSize.width, aDesiredSize.height);
|
||||
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("exit nsSubDocumentFrame::Reflow: size=%d,%d status=%x",
|
||||
|
@ -161,9 +161,8 @@ public:
|
||||
protected:
|
||||
nsHTMLFramesetBorderFrame(nsStyleContext* aContext, PRInt32 aWidth, PRBool aVertical, PRBool aVisible);
|
||||
virtual ~nsHTMLFramesetBorderFrame();
|
||||
virtual void GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
virtual nscoord GetIntrinsicWidth();
|
||||
|
||||
PRInt32 mWidth;
|
||||
PRPackedBool mVertical;
|
||||
PRPackedBool mVisibility;
|
||||
@ -198,9 +197,8 @@ public:
|
||||
protected:
|
||||
nsHTMLFramesetBlankFrame(nsStyleContext* aContext) : nsLeafFrame(aContext) {}
|
||||
virtual ~nsHTMLFramesetBlankFrame();
|
||||
virtual void GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
virtual nscoord GetIntrinsicWidth();
|
||||
|
||||
friend class nsHTMLFramesetFrame;
|
||||
friend class nsHTMLFrameset;
|
||||
};
|
||||
@ -323,7 +321,7 @@ nsHTMLFramesetFrame::Init(nsIContent* aContent,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nsPresContext* aPresContext = GetPresContext();
|
||||
|
||||
// create the view. a view is needed since it needs to be a mouse grabber
|
||||
@ -875,7 +873,7 @@ nsHTMLFramesetFrame::ReflowPlaceChild(nsIFrame* aChild,
|
||||
{
|
||||
// reflow the child
|
||||
nsHTMLReflowState reflowState(aPresContext, aReflowState, aChild, aSize);
|
||||
nsHTMLReflowMetrics metrics(nsnull);
|
||||
nsHTMLReflowMetrics metrics;
|
||||
metrics.width = aSize.width;
|
||||
metrics.height= aSize.height;
|
||||
nsReflowStatus status;
|
||||
@ -981,11 +979,13 @@ nsHTMLFramesetFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
nsIPresShell *shell = aPresContext->PresShell();
|
||||
nsStyleSet *styleSet = shell->StyleSet();
|
||||
|
||||
mParent->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
|
||||
|
||||
//printf("FramesetFrame2::Reflow %X (%d,%d) \n", this, aReflowState.availableWidth, aReflowState.availableHeight);
|
||||
// Always get the size so that the caller knows how big we are
|
||||
GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
|
||||
@ -1268,10 +1268,6 @@ nsHTMLFramesetFrame::Reflow(nsPresContext* aPresContext,
|
||||
mChildBorderColors = nsnull;
|
||||
}
|
||||
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = aDesiredSize.width;
|
||||
}
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
mDrag.UnSet();
|
||||
|
||||
@ -1285,6 +1281,14 @@ nsHTMLFramesetFrame::GetType() const
|
||||
return nsLayoutAtoms::frameSetFrame;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHODIMP
|
||||
nsHTMLFramesetFrame::GetFrameName(nsAString& aResult) const
|
||||
{
|
||||
return MakeFrameName(NS_LITERAL_STRING("Frameset"), aResult);
|
||||
}
|
||||
#endif
|
||||
|
||||
PRBool
|
||||
nsHTMLFramesetFrame::IsLeaf() const
|
||||
{
|
||||
@ -1618,14 +1622,10 @@ nsHTMLFramesetBorderFrame::~nsHTMLFramesetBorderFrame()
|
||||
//printf("nsHTMLFramesetBorderFrame destructor %p \n", this);
|
||||
}
|
||||
|
||||
void nsHTMLFramesetBorderFrame::GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize)
|
||||
nscoord nsHTMLFramesetBorderFrame::GetIntrinsicWidth()
|
||||
{
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
aDesiredSize.height = aReflowState.availableHeight;
|
||||
aDesiredSize.ascent = aDesiredSize.width;
|
||||
aDesiredSize.descent = 0;
|
||||
// No intrinsic width
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nsHTMLFramesetBorderFrame::SetVisibility(PRBool aVisibility)
|
||||
@ -1645,8 +1645,13 @@ nsHTMLFramesetBorderFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBorderFrame", aReflowState.reason);
|
||||
GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBorderFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
// Override Reflow(), since we don't want to deal with what our
|
||||
// computed values are.
|
||||
SizeToAvailSize(aReflowState, aDesiredSize);
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1830,14 +1835,10 @@ nsHTMLFramesetBlankFrame::~nsHTMLFramesetBlankFrame()
|
||||
//printf("nsHTMLFramesetBlankFrame destructor %p \n", this);
|
||||
}
|
||||
|
||||
void nsHTMLFramesetBlankFrame::GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize)
|
||||
nscoord nsHTMLFramesetBlankFrame::GetIntrinsicWidth()
|
||||
{
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
aDesiredSize.height = aReflowState.availableHeight;
|
||||
aDesiredSize.ascent = aDesiredSize.width;
|
||||
aDesiredSize.descent = 0;
|
||||
// No intrinsic width
|
||||
return 0;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -1846,8 +1847,12 @@ nsHTMLFramesetBlankFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBlankFrame", aReflowState.reason);
|
||||
GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLFramesetBlankFrame");
|
||||
|
||||
// Override Reflow(), since we don't want to deal with what our
|
||||
// computed values are.
|
||||
SizeToAvailSize(aReflowState, aDesiredSize);
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -148,6 +148,9 @@ public:
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
virtual nsIAtom* GetType() const;
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
||||
#endif
|
||||
|
||||
virtual PRBool IsLeaf() const;
|
||||
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsReflowType.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIView.h"
|
||||
#include "nsIScrollableView.h"
|
||||
@ -69,13 +68,13 @@
|
||||
#include "nsGUIEvent.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsPresState.h"
|
||||
#include "nsIGlobalHistory3.h"
|
||||
#include "nsDocShellCID.h"
|
||||
#include "nsIDOMHTMLDocument.h"
|
||||
#include "nsEventDispatcher.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "nsIAccessibilityService.h"
|
||||
#endif
|
||||
@ -245,7 +244,6 @@ struct ScrollReflowState {
|
||||
const nsHTMLReflowState& mReflowState;
|
||||
nsBoxLayoutState mBoxState;
|
||||
nsGfxScrollFrameInner::ScrollbarStyles mStyles;
|
||||
nsReflowReason mNewReason;
|
||||
nsMargin mComputedBorder;
|
||||
|
||||
// === Filled in when TryLayout succeeds ===
|
||||
@ -255,25 +253,20 @@ struct ScrollReflowState {
|
||||
nsSize mInsideBorderSize;
|
||||
// Taken from kid metrics; ascent from the inner-border top edge
|
||||
nscoord mAscent;
|
||||
// Taken from kid metrics; does not include our border widths,
|
||||
// does include vertical scrollbar if present
|
||||
nscoord mMaxElementWidth;
|
||||
// Taken from kid metrics; does not include our border widths,
|
||||
// does include vertical scrollbar if present
|
||||
nscoord mMaximumWidth;
|
||||
// Whether we decided to show the horizontal scrollbar
|
||||
PRPackedBool mShowHScrollbar;
|
||||
// Whether we decided to show the vertical scrollbar
|
||||
PRPackedBool mShowVScrollbar;
|
||||
|
||||
ScrollReflowState(nsIScrollableFrame* aFrame,
|
||||
const nsHTMLReflowState& aState, nsHTMLReflowMetrics& aMetrics) :
|
||||
const nsHTMLReflowState& aState) :
|
||||
mReflowState(aState),
|
||||
mBoxState(aState.frame->GetPresContext(), aState, aMetrics),
|
||||
mBoxState(aState.frame->GetPresContext(), aState.rendContext),
|
||||
mStyles(aFrame->GetScrollbarStyles()) {
|
||||
}
|
||||
};
|
||||
|
||||
// XXXldb Can this go away?
|
||||
static nsSize ComputeInsideBorderSize(ScrollReflowState* aState,
|
||||
const nsSize& aDesiredInsideBorderSize)
|
||||
{
|
||||
@ -300,6 +293,10 @@ static void
|
||||
GetScrollbarMetrics(nsBoxLayoutState& aState, nsIBox* aBox, nsSize* aMin,
|
||||
nsSize* aPref, PRBool aVertical)
|
||||
{
|
||||
NS_ASSERTION(aState.GetRenderingContext(),
|
||||
"Must have rendering context in layout state for size "
|
||||
"computations");
|
||||
|
||||
if (aMin) {
|
||||
aBox->GetMinSize(aState, *aMin);
|
||||
nsBox::AddMargin(aBox, *aMin);
|
||||
@ -365,6 +362,7 @@ nsHTMLScrollFrame::TryLayout(ScrollReflowState* aState,
|
||||
nscoord hScrollbarDesiredWidth = aAssumeHScroll ? hScrollbarPrefSize.width : 0;
|
||||
|
||||
// First, compute our inside-border size and scrollport size
|
||||
// XXXldb Can we depend more on ComputeSize here?
|
||||
nsSize desiredInsideBorderSize;
|
||||
desiredInsideBorderSize.width = vScrollbarDesiredWidth +
|
||||
PR_MAX(aKidMetrics.width, hScrollbarDesiredWidth);
|
||||
@ -416,48 +414,6 @@ nsHTMLScrollFrame::TryLayout(ScrollReflowState* aState,
|
||||
}
|
||||
aState->mScrollPortRect = nsRect(scrollPortOrigin, scrollPortSize);
|
||||
aState->mAscent = aKidMetrics.ascent;
|
||||
if (aKidMetrics.mComputeMEW) {
|
||||
// XXXBernd the following code is controversial see bug 295459 and bug
|
||||
// 234593, however to get the main customer of MEW - tables happy. It
|
||||
// seems to be necessary
|
||||
// It looks at the MEW as the minimum width that the parent has to give its
|
||||
// children so that the childs margin box can layout its content without
|
||||
// overflowing the parents content box. If the child has a fixed width
|
||||
// the MEW will be allways this width regardless whether it makes the grand
|
||||
// children overflow the child. Please notice that fixed widths for table
|
||||
// related frames are not covered by this as they mean more a min-width.
|
||||
//
|
||||
// This means for scrolling boxes that if the width is auto or percent
|
||||
// their content box can be squeezed down to 0, as they will either create
|
||||
// a scrollbar so that content of the scrollframe will not leak out or it
|
||||
// will cut the content at the frame boundaries.
|
||||
|
||||
// The width of the vertical scrollbar comes out of the budget for the
|
||||
// content width (see above where we include the scrollbar width before
|
||||
// we call ComputeInsideBorderSize, which overrides the given
|
||||
// width with the style computed width if there is one). So allow
|
||||
// the vertical scrollbar width to be overridden by style information
|
||||
// here, too.
|
||||
nscoord minContentWidth =
|
||||
aState->mReflowState.AdjustIntrinsicMinContentWidthForStyle(vScrollbarActualWidth);
|
||||
aState->mMaxElementWidth = minContentWidth +
|
||||
aState->mReflowState.mComputedPadding.LeftRight();
|
||||
// borders get added on the way out of Reflow()
|
||||
}
|
||||
if (aKidMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH) {
|
||||
// We need to do what we did above: include the vertical scrollbar width in the
|
||||
// content width before applying style.
|
||||
nscoord kidMaxWidth = aKidMetrics.mMaximumWidth;
|
||||
if (kidMaxWidth != NS_UNCONSTRAINEDSIZE) {
|
||||
nscoord kidContentMaxWidth = kidMaxWidth -
|
||||
aState->mReflowState.mComputedPadding.LeftRight() + vScrollbarActualWidth;
|
||||
NS_ASSERTION(kidContentMaxWidth >= 0, "max-width didn't include padding?");
|
||||
kidMaxWidth = aState->mReflowState.mComputedPadding.LeftRight() +
|
||||
aState->mReflowState.AdjustIntrinsicContentWidthForStyle(kidContentMaxWidth);
|
||||
}
|
||||
aState->mMaximumWidth = kidMaxWidth;
|
||||
// borders get added on the way out of Reflow()
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
@ -472,35 +428,24 @@ nsHTMLScrollFrame::ReflowScrolledFrame(const ScrollReflowState& aState,
|
||||
// be OK
|
||||
nscoord paddingLR = aState.mReflowState.mComputedPadding.LeftRight();
|
||||
|
||||
nscoord availWidth = aState.mReflowState.availableWidth;
|
||||
if (aState.mReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE) {
|
||||
availWidth = aState.mReflowState.mComputedWidth + paddingLR;
|
||||
} else {
|
||||
if (aState.mReflowState.mComputedMaxWidth != NS_UNCONSTRAINEDSIZE) {
|
||||
availWidth = PR_MIN(availWidth,
|
||||
aState.mReflowState.mComputedMaxWidth + paddingLR);
|
||||
}
|
||||
if (aState.mReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE) {
|
||||
availWidth = PR_MIN(availWidth,
|
||||
aState.mReflowState.mComputedWidth + paddingLR);
|
||||
}
|
||||
}
|
||||
if (availWidth != NS_UNCONSTRAINEDSIZE && aAssumeVScroll) {
|
||||
nscoord availWidth = aState.mReflowState.mComputedWidth + paddingLR;
|
||||
|
||||
if (aAssumeVScroll) {
|
||||
nsSize vScrollbarPrefSize;
|
||||
mInner.mVScrollbarBox->GetPrefSize(NS_CONST_CAST(nsBoxLayoutState&, aState.mBoxState),
|
||||
vScrollbarPrefSize);
|
||||
availWidth = PR_MAX(0, availWidth - vScrollbarPrefSize.width);
|
||||
}
|
||||
if (availWidth != NS_UNCONSTRAINEDSIZE) {
|
||||
// pixel align the content
|
||||
nscoord twp = GetPresContext()->IntScaledPixelsToTwips(1);
|
||||
availWidth -= availWidth % twp;
|
||||
}
|
||||
// pixel align the content
|
||||
nscoord twp = GetPresContext()->IntScaledPixelsToTwips(1);
|
||||
availWidth -= availWidth % twp;
|
||||
|
||||
if (!aFirstPass)
|
||||
mInner.mScrolledFrame->AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
|
||||
nsHTMLReflowState kidReflowState(GetPresContext(), aState.mReflowState,
|
||||
mInner.mScrolledFrame,
|
||||
nsSize(availWidth, NS_UNCONSTRAINEDSIZE),
|
||||
aFirstPass ? aState.mNewReason : eReflowReason_Resize);
|
||||
nsSize(availWidth, NS_UNCONSTRAINEDSIZE));
|
||||
kidReflowState.mFlags.mAssumingHScrollbar = aAssumeHScroll;
|
||||
kidReflowState.mFlags.mAssumingVScrollbar = aAssumeVScroll;
|
||||
|
||||
@ -546,7 +491,7 @@ nsHTMLScrollFrame::GuessVScrollbarNeeded(const ScrollReflowState& aState)
|
||||
|
||||
// If this is the initial reflow, guess PR_FALSE because usually
|
||||
// we have very little content by then.
|
||||
if (aState.mReflowState.reason == eReflowReason_Initial)
|
||||
if (GetStateBits() & NS_FRAME_FIRST_REFLOW)
|
||||
return PR_FALSE;
|
||||
|
||||
if (mInner.mIsRoot) {
|
||||
@ -575,7 +520,7 @@ nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState,
|
||||
const nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
PRBool currentlyUsingVScrollbar = GuessVScrollbarNeeded(*aState);
|
||||
nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mComputeMEW, aDesiredSize.mFlags);
|
||||
nsHTMLReflowMetrics kidDesiredSize(aDesiredSize.mFlags);
|
||||
nsresult rv = ReflowScrolledFrame(*aState, PR_FALSE, currentlyUsingVScrollbar,
|
||||
&kidDesiredSize, PR_TRUE);
|
||||
if (NS_FAILED(rv))
|
||||
@ -630,7 +575,7 @@ nsHTMLScrollFrame::ReflowContents(ScrollReflowState* aState,
|
||||
// That didn't work. Try the other setting for the vertical scrollbar.
|
||||
// But don't try to show a scrollbar if we know there can't be one.
|
||||
if (currentlyUsingVScrollbar || canHaveVerticalScrollbar) {
|
||||
nsHTMLReflowMetrics kidRetrySize(aDesiredSize.mComputeMEW, aDesiredSize.mFlags);
|
||||
nsHTMLReflowMetrics kidRetrySize(aDesiredSize.mFlags);
|
||||
rv = ReflowScrolledFrame(*aState, PR_FALSE, !currentlyUsingVScrollbar,
|
||||
&kidRetrySize, PR_FALSE);
|
||||
if (NS_FAILED(rv))
|
||||
@ -703,16 +648,57 @@ nsHTMLScrollFrame::PlaceScrollArea(const ScrollReflowState& aState)
|
||||
mInner.PostOverflowEvents();
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsHTMLScrollFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result = 0;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsHTMLScrollFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
// XXX Might this make us count padding/border/margin twice?
|
||||
result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext,
|
||||
mInner.mScrolledFrame, nsLayoutUtils::PREF_WIDTH);
|
||||
|
||||
nsGfxScrollFrameInner::ScrollbarStyles ss = GetScrollbarStyles();
|
||||
if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN && // ideal?
|
||||
mInner.mVScrollbarBox) {
|
||||
nsBoxLayoutState bls(GetPresContext(), aRenderingContext);
|
||||
nsSize vScrollbarMinSize(0, 0);
|
||||
GetScrollbarMetrics(bls, mInner.mVScrollbarBox,
|
||||
&vScrollbarMinSize, nsnull, PR_TRUE);
|
||||
result += vScrollbarMinSize.width;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLScrollFrame::GetPadding(nsMargin& aMargin)
|
||||
{
|
||||
// Our padding hangs out on the inside of the scrollframe, but XUL doesn't
|
||||
// reaize that. If we're stuck inside a XUL box, we need to claim no
|
||||
// padding.
|
||||
// @see also nsXULScrollFrame::GetPadding.
|
||||
aMargin.SizeTo(0,0,0,0);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLScrollFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLScrollFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
ScrollReflowState state(this, aReflowState, aDesiredSize);
|
||||
ScrollReflowState state(this, aReflowState);
|
||||
// sanity check: ensure that if we have no scrollbar, we treat it
|
||||
// as hidden.
|
||||
if (!mInner.mVScrollbarBox || mInner.mNeverHasVerticalScrollbar)
|
||||
@ -721,53 +707,23 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
|
||||
state.mStyles.mHorizontal = NS_STYLE_OVERFLOW_HIDDEN;
|
||||
|
||||
//------------ Handle Incremental Reflow -----------------
|
||||
PRBool reflowContents = PR_TRUE;
|
||||
PRBool reflowContents = PR_TRUE; // XXX Ignored
|
||||
PRBool reflowHScrollbar = PR_TRUE;
|
||||
PRBool reflowVScrollbar = PR_TRUE;
|
||||
PRBool reflowScrollCorner = PR_TRUE;
|
||||
nsReflowReason reason = aReflowState.reason;
|
||||
if (!aReflowState.ShouldReflowAllKids()) {
|
||||
#define NEEDS_REFLOW(frame_) \
|
||||
((frame_) && \
|
||||
((frame_)->GetStateBits() & \
|
||||
(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN)) != 0)
|
||||
|
||||
if (reason == eReflowReason_Incremental) {
|
||||
nsHTMLReflowCommand *command = aReflowState.path->mReflowCommand;
|
||||
// See if it's targeted at us
|
||||
if (command) {
|
||||
nsReflowType reflowType;
|
||||
command->GetType(reflowType);
|
||||
reflowContents = NEEDS_REFLOW(mInner.mScrolledFrame);
|
||||
reflowHScrollbar = NEEDS_REFLOW(mInner.mHScrollbarBox);
|
||||
reflowVScrollbar = NEEDS_REFLOW(mInner.mVScrollbarBox);
|
||||
reflowScrollCorner = NEEDS_REFLOW(mInner.mScrollCornerBox);
|
||||
|
||||
switch (reflowType) {
|
||||
case eReflowType_StyleChanged:
|
||||
reason = eReflowReason_StyleChange;
|
||||
break;
|
||||
|
||||
case eReflowType_ReflowDirty:
|
||||
reason = eReflowReason_Dirty;
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ERROR("Unexpected Reflow Type");
|
||||
}
|
||||
} else {
|
||||
reflowContents = PR_FALSE;
|
||||
reflowHScrollbar = PR_FALSE;
|
||||
reflowVScrollbar = PR_FALSE;
|
||||
reflowScrollCorner = PR_FALSE;
|
||||
|
||||
nsReflowPath::iterator iter = aReflowState.path->FirstChild();
|
||||
nsReflowPath::iterator end = aReflowState.path->EndChildren();
|
||||
|
||||
for ( ; iter != end; ++iter) {
|
||||
if (*iter == mInner.mScrolledFrame)
|
||||
reflowContents = PR_TRUE;
|
||||
else if (*iter == mInner.mHScrollbarBox)
|
||||
reflowHScrollbar = PR_TRUE;
|
||||
else if (*iter == mInner.mVScrollbarBox)
|
||||
reflowVScrollbar = PR_TRUE;
|
||||
else if (*iter == mInner.mScrollCornerBox)
|
||||
reflowScrollCorner = PR_TRUE;
|
||||
}
|
||||
}
|
||||
#undef NEEDS_REFLOW
|
||||
}
|
||||
state.mNewReason = reason;
|
||||
|
||||
nsRect oldScrollAreaBounds = mInner.mScrollableView->View()->GetBounds();
|
||||
nsRect oldScrolledAreaBounds = mInner.mScrolledFrame->GetView()->GetBounds();
|
||||
@ -789,7 +745,7 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsRect newScrollAreaBounds = mInner.mScrollableView->View()->GetBounds();
|
||||
nsRect newScrolledAreaBounds = mInner.mScrolledFrame->GetView()->GetBounds();
|
||||
if (reflowHScrollbar || reflowVScrollbar || reflowScrollCorner ||
|
||||
reason != eReflowReason_Incremental ||
|
||||
(GetStateBits() & NS_FRAME_IS_DIRTY) ||
|
||||
didHaveHScrollbar != state.mShowHScrollbar ||
|
||||
didHaveVScrollbar != state.mShowVScrollbar ||
|
||||
oldScrollAreaBounds != newScrollAreaBounds ||
|
||||
@ -809,23 +765,15 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext,
|
||||
state.mComputedBorder.LeftRight();
|
||||
aDesiredSize.height = state.mInsideBorderSize.height +
|
||||
state.mComputedBorder.TopBottom();
|
||||
aDesiredSize.ascent = state.mAscent + state.mComputedBorder.top;
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = state.mMaxElementWidth +
|
||||
state.mComputedBorder.LeftRight();
|
||||
}
|
||||
if (aDesiredSize.mFlags & NS_REFLOW_CALC_MAX_WIDTH) {
|
||||
aDesiredSize.mMaximumWidth = state.mMaximumWidth;
|
||||
if (aDesiredSize.mMaximumWidth != NS_UNCONSTRAINEDSIZE) {
|
||||
aDesiredSize.mMaximumWidth += state.mComputedBorder.LeftRight();
|
||||
}
|
||||
}
|
||||
aDesiredSize.ascent =
|
||||
state.mAscent + aReflowState.mComputedBorderPadding.top;
|
||||
|
||||
aDesiredSize.descent = aDesiredSize.height - aDesiredSize.ascent;
|
||||
aDesiredSize.mOverflowArea = nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
||||
FinishAndStoreOverflow(&aDesiredSize);
|
||||
|
||||
if (reason != eReflowReason_Initial && !mInner.mHadNonInitialReflow) {
|
||||
if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW) &&
|
||||
!mInner.mHadNonInitialReflow) {
|
||||
mInner.mHadNonInitialReflow = PR_TRUE;
|
||||
if (mInner.mIsRoot) {
|
||||
// For viewports, record whether we needed a vertical scrollbar
|
||||
@ -912,8 +860,7 @@ NS_NewXULScrollFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, PRBool
|
||||
|
||||
nsXULScrollFrame::nsXULScrollFrame(nsIPresShell* aShell, nsStyleContext* aContext, PRBool aIsRoot)
|
||||
: nsBoxFrame(aShell, aContext, aIsRoot),
|
||||
mInner(this, aIsRoot, PR_TRUE),
|
||||
mMaxElementWidth(0)
|
||||
mInner(this, aIsRoot, PR_TRUE)
|
||||
{
|
||||
SetLayoutManager(nsnull);
|
||||
}
|
||||
@ -956,6 +903,10 @@ nsMargin nsXULScrollFrame::GetDesiredScrollbarSizes(nsBoxLayoutState* aState) {
|
||||
}
|
||||
|
||||
nsMargin nsGfxScrollFrameInner::GetDesiredScrollbarSizes(nsBoxLayoutState* aState) {
|
||||
NS_ASSERTION(aState && aState->GetRenderingContext(),
|
||||
"Must have rendering context in layout state for size "
|
||||
"computations");
|
||||
|
||||
nsMargin result(0, 0, 0, 0);
|
||||
|
||||
if (mVScrollbarBox) {
|
||||
@ -1188,42 +1139,28 @@ nsXULScrollFrame::GetMaxSize(nsBoxLayoutState& aState, nsSize& aSize)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULScrollFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
#if 0 // XXXldb I don't think this is even needed
|
||||
/* virtual */ nscoord
|
||||
nsXULScrollFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsXULScrollFrame", aReflowState.reason);
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
// if there is a max element request then set it to -1 so we can see if it gets set
|
||||
if (aDesiredSize.mComputeMEW)
|
||||
{
|
||||
aDesiredSize.mMaxElementWidth = -1;
|
||||
}
|
||||
|
||||
nsresult rv = nsBoxFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
|
||||
|
||||
if (aDesiredSize.mComputeMEW)
|
||||
{
|
||||
nsStyleUnit widthUnit = GetStylePosition()->mWidth.GetUnit();
|
||||
if (widthUnit == eStyleUnit_Percent || widthUnit == eStyleUnit_Auto) {
|
||||
nsMargin border = aReflowState.mComputedBorderPadding;
|
||||
aDesiredSize.mMaxElementWidth = border.right + border.left;
|
||||
nsStyleUnit widthUnit = GetStylePosition()->mWidth.GetUnit();
|
||||
if (widthUnit == eStyleUnit_Percent || widthUnit == eStyleUnit_Auto) {
|
||||
nsMargin border = aReflowState.mComputedBorderPadding;
|
||||
aDesiredSize.mMaxElementWidth = border.right + border.left;
|
||||
mMaxElementWidth = aDesiredSize.mMaxElementWidth;
|
||||
} else {
|
||||
NS_NOTYETIMPLEMENTED("Use the info from the scrolled frame");
|
||||
#if 0
|
||||
// if not set then use the cached size. If set then set it.
|
||||
if (aDesiredSize.mMaxElementWidth == -1)
|
||||
aDesiredSize.mMaxElementWidth = mMaxElementWidth;
|
||||
else
|
||||
mMaxElementWidth = aDesiredSize.mMaxElementWidth;
|
||||
} else {
|
||||
// if not set then use the cached size. If set then set it.
|
||||
if (aDesiredSize.mMaxElementWidth == -1)
|
||||
aDesiredSize.mMaxElementWidth = mMaxElementWidth;
|
||||
else
|
||||
mMaxElementWidth = aDesiredSize.mMaxElementWidth;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
return rv;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP_(nsrefcnt)
|
||||
nsXULScrollFrame::AddRef(void)
|
||||
@ -1237,6 +1174,13 @@ nsXULScrollFrame::Release(void)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXULScrollFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
// Override nsBoxFrame.
|
||||
return !aFlags;
|
||||
}
|
||||
|
||||
#ifdef NS_DEBUG
|
||||
NS_IMETHODIMP
|
||||
nsXULScrollFrame::GetFrameName(nsAString& aResult) const
|
||||
@ -1999,54 +1943,6 @@ nsXULScrollFrame::AddRemoveScrollbar(PRBool& aHasScrollbar, nscoord& aXY,
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* When reflowing a HTML document where the content model is being created
|
||||
* The nsGfxScrollFrame will get an Initial reflow when the body is opened by the content sink.
|
||||
* But there isn't enough content to really reflow very much of the document
|
||||
* so it never needs to do layout for the scrollbars
|
||||
*
|
||||
* So later other reflows happen and these are Incremental reflows, and then the scrollbars
|
||||
* get reflowed. The important point here is that when they reflowed the ReflowState inside the
|
||||
* BoxLayoutState contains an "Incremental" reason and never a "Initial" reason.
|
||||
*
|
||||
* When it reflows for Print Preview, the content model is already full constructed and it lays
|
||||
* out the entire document at that time. When it returns back here it discovers it needs scrollbars
|
||||
* and this is a problem because the ReflowState inside the BoxLayoutState still has a "Initial"
|
||||
* reason and if it does a Layout it is essentially asking everything to reflow yet again with
|
||||
* an "Initial" reason. This causes a lot of problems especially for tables.
|
||||
*
|
||||
* The solution for this is to change the ReflowState's reason from Initial to Resize and let
|
||||
* all the frames do what is necessary for a resize refow. Now, we only need to do this when
|
||||
* it is doing PrintPreview and we need only do it for HTML documents and NOT chrome.
|
||||
*
|
||||
*/
|
||||
void
|
||||
nsXULScrollFrame::AdjustReflowStateForPrintPreview(nsBoxLayoutState& aState, PRBool& aSetBack)
|
||||
{
|
||||
aSetBack = PR_FALSE;
|
||||
PRBool isChrome;
|
||||
PRBool isInitialPP = nsBoxFrame::IsInitialReflowForPrintPreview(aState, isChrome);
|
||||
if (isInitialPP && !isChrome) {
|
||||
// I know you shouldn't, but we cast away the "const" here
|
||||
nsHTMLReflowState* reflowState = (nsHTMLReflowState*)aState.GetReflowState();
|
||||
reflowState->reason = eReflowReason_Resize;
|
||||
aSetBack = PR_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets reflow state back to Initial when we are done.
|
||||
*/
|
||||
void
|
||||
nsXULScrollFrame::AdjustReflowStateBack(nsBoxLayoutState& aState, PRBool aSetBack)
|
||||
{
|
||||
// I know you shouldn't, but we cast away the "const" here
|
||||
nsHTMLReflowState* reflowState = (nsHTMLReflowState*)aState.GetReflowState();
|
||||
if (aSetBack && reflowState->reason == eReflowReason_Resize) {
|
||||
reflowState->reason = eReflowReason_Initial;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXULScrollFrame::LayoutScrollArea(nsBoxLayoutState& aState, const nsRect& aRect)
|
||||
{
|
||||
@ -2267,11 +2163,7 @@ nsXULScrollFrame::Layout(nsBoxLayoutState& aState)
|
||||
// ok layout at the right size
|
||||
if (needsLayout) {
|
||||
nsBoxLayoutState resizeState(aState);
|
||||
resizeState.SetLayoutReason(nsBoxLayoutState::Resize);
|
||||
PRBool setBack;
|
||||
AdjustReflowStateForPrintPreview(aState, setBack);
|
||||
LayoutScrollArea(resizeState, scrollAreaRect);
|
||||
AdjustReflowStateBack(aState, setBack);
|
||||
needsLayout = PR_FALSE;
|
||||
}
|
||||
}
|
||||
@ -2311,11 +2203,7 @@ nsXULScrollFrame::Layout(nsBoxLayoutState& aState)
|
||||
// we only need to set the rect. The inner child stays the same size.
|
||||
if (needsLayout) {
|
||||
nsBoxLayoutState resizeState(aState);
|
||||
resizeState.SetLayoutReason(nsBoxLayoutState::Resize);
|
||||
PRBool setBack;
|
||||
AdjustReflowStateForPrintPreview(aState, setBack);
|
||||
LayoutScrollArea(resizeState, scrollAreaRect);
|
||||
AdjustReflowStateBack(aState, setBack);
|
||||
needsLayout = PR_FALSE;
|
||||
}
|
||||
|
||||
@ -2351,7 +2239,7 @@ nsXULScrollFrame::Layout(nsBoxLayoutState& aState)
|
||||
// we only need to set the rect. The inner child stays the same size.
|
||||
if (needsLayout) {
|
||||
nsBoxLayoutState resizeState(aState);
|
||||
resizeState.SetLayoutReason(nsBoxLayoutState::Resize);
|
||||
mInner.mScrolledFrame->AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
LayoutScrollArea(resizeState, scrollAreaRect);
|
||||
}
|
||||
|
||||
@ -2359,7 +2247,7 @@ nsXULScrollFrame::Layout(nsBoxLayoutState& aState)
|
||||
mInner.LayoutScrollbars(aState, clientRect, oldScrollAreaBounds, scrollAreaRect);
|
||||
}
|
||||
mInner.ScrollToRestoredPosition();
|
||||
if (aState.GetReflowState()->reason != eReflowReason_Initial) {
|
||||
if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
mInner.mHadNonInitialReflow = PR_TRUE;
|
||||
}
|
||||
return NS_OK;
|
||||
@ -2485,20 +2373,21 @@ nsGfxScrollFrameInner::LayoutScrollbars(nsBoxLayoutState& aState,
|
||||
}
|
||||
|
||||
// may need to update fixed position children of the viewport,
|
||||
// if the client area changed size because of some dirty reflow
|
||||
// (if the reflow is initial or resize, the fixed children will
|
||||
// be re-laid out anyway)
|
||||
if (aOldScrollArea.Size() != aScrollArea.Size()
|
||||
&& nsBoxLayoutState::Dirty == aState.LayoutReason() &&
|
||||
// if the client area changed size because of an incremental
|
||||
// reflow of a descendant. (If the outer frame is dirty, the fixed
|
||||
// children will be re-laid out anyway)
|
||||
if (aOldScrollArea.Size() != aScrollArea.Size() &&
|
||||
!(mOuter->GetStateBits() & NS_FRAME_IS_DIRTY) &&
|
||||
mIsRoot) {
|
||||
// Usually there are no fixed children, so don't do anything unless there's
|
||||
// at least one fixed child
|
||||
nsIFrame* parentFrame = mOuter->GetParent();
|
||||
if (parentFrame->GetFirstChild(nsLayoutAtoms::fixedList)) {
|
||||
// force a reflow of the fixed children
|
||||
for (nsIFrame *fixedChild =
|
||||
parentFrame->GetFirstChild(nsLayoutAtoms::fixedList);
|
||||
fixedChild; fixedChild = fixedChild->GetNextSibling()) {
|
||||
// force a reflow of the fixed child
|
||||
fixedChild->AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
|
||||
// XXX Will this work given where we currently are in reflow?
|
||||
mOuter->GetPresContext()->PresShell()->
|
||||
AppendReflowCommand(parentFrame, eReflowType_UserDefined,
|
||||
nsLayoutAtoms::fixedList);
|
||||
FrameNeedsReflow(fixedChild, nsIPresShell::eResize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +239,10 @@ public:
|
||||
const nsHTMLReflowMetrics& aDesiredSize);
|
||||
void PlaceScrollArea(const ScrollReflowState& aState);
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
NS_IMETHOD GetPadding(nsMargin& aPadding);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -355,6 +359,12 @@ protected:
|
||||
}
|
||||
PRBool GuessVScrollbarNeeded(const ScrollReflowState& aState);
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool IsScrollbarUpdateSuppressed() const {
|
||||
return mInner.mSupppressScrollbarUpdate;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class nsGfxScrollFrameInner;
|
||||
nsGfxScrollFrameInner mInner;
|
||||
@ -387,10 +397,10 @@ public:
|
||||
return mInner.BuildDisplayList(aBuilder, aDirtyRect, aLists);
|
||||
}
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
// XXXldb Is this actually used?
|
||||
#if 0
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
#endif
|
||||
|
||||
// Because there can be only one child frame, these two function return
|
||||
// NS_ERROR_FAILURE
|
||||
@ -517,6 +527,7 @@ public:
|
||||
*/
|
||||
virtual nsIAtom* GetType() const;
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
#ifdef NS_DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
||||
#endif
|
||||
@ -530,7 +541,6 @@ protected:
|
||||
private:
|
||||
friend class nsGfxScrollFrameInner;
|
||||
nsGfxScrollFrameInner mInner;
|
||||
nscoord mMaxElementWidth;
|
||||
};
|
||||
|
||||
#endif /* nsGfxScrollFrame_h___ */
|
||||
|
@ -59,13 +59,60 @@ nsHTMLCanvasFrame::~nsHTMLCanvasFrame()
|
||||
{
|
||||
}
|
||||
|
||||
// We really want a PR_MINMAX to go along with PR_MIN/PR_MAX
|
||||
#define MINMAX(_value,_min,_max) \
|
||||
((_value) < (_min) \
|
||||
? (_min) \
|
||||
: ((_value) > (_max) \
|
||||
? (_max) \
|
||||
: (_value)))
|
||||
nsSize
|
||||
nsHTMLCanvasFrame::GetCanvasSize()
|
||||
{
|
||||
PRUint32 w, h;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
|
||||
if (canvas) {
|
||||
rv = canvas->GetSize(&w, &h);
|
||||
} else {
|
||||
rv = NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_NOTREACHED("couldn't get canvas size");
|
||||
h = w = 1;
|
||||
}
|
||||
|
||||
float p2t = GetPresContext()->PixelsToTwips();
|
||||
|
||||
return nsSize(NSIntPixelsToTwips(w, p2t), NSIntPixelsToTwips(h, p2t));
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsHTMLCanvasFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
// XXX The caller doesn't account for constraints of the height,
|
||||
// min-height, and max-height properties.
|
||||
nscoord result = GetCanvasSize().width;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsHTMLCanvasFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
// XXX The caller doesn't account for constraints of the height,
|
||||
// min-height, and max-height properties.
|
||||
nscoord result = GetCanvasSize().width;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nsSize
|
||||
nsHTMLCanvasFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap)
|
||||
{
|
||||
mCanvasSize = GetCanvasSize();
|
||||
|
||||
return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
|
||||
aRenderingContext, this, mCanvasSize,
|
||||
aCBSize, aBorder, aPadding);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
|
||||
@ -73,7 +120,7 @@ nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLCanvasFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsHTMLCanvasFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("enter nsHTMLCanvasFrame::Reflow: availSize=%d,%d",
|
||||
@ -83,30 +130,8 @@ nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
nsCOMPtr<nsICanvasElement> canvas(do_QueryInterface(GetContent()));
|
||||
NS_ENSURE_TRUE(canvas, NS_ERROR_FAILURE);
|
||||
|
||||
PRUint32 w, h;
|
||||
nsresult rv = canvas->GetSize (&w, &h);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
float p2t = GetPresContext()->PixelsToTwips();
|
||||
|
||||
mCanvasSize.SizeTo(NSIntPixelsToTwips(w, p2t), NSIntPixelsToTwips(h, p2t));
|
||||
|
||||
if (aReflowState.mComputedWidth == NS_INTRINSICSIZE)
|
||||
aMetrics.width = mCanvasSize.width;
|
||||
else
|
||||
aMetrics.width = aReflowState.mComputedWidth;
|
||||
|
||||
if (aReflowState.mComputedHeight == NS_INTRINSICSIZE)
|
||||
aMetrics.height = mCanvasSize.height;
|
||||
else
|
||||
aMetrics.height = aReflowState.mComputedHeight;
|
||||
|
||||
// clamp
|
||||
aMetrics.height = MINMAX(aMetrics.height, aReflowState.mComputedMinHeight, aReflowState.mComputedMaxHeight);
|
||||
aMetrics.width = MINMAX(aMetrics.width, aReflowState.mComputedMinWidth, aReflowState.mComputedMaxWidth);
|
||||
aMetrics.width = aReflowState.mComputedWidth;
|
||||
aMetrics.height = aReflowState.mComputedHeight;
|
||||
|
||||
// stash this away so we can compute our inner area later
|
||||
mBorderPadding = aReflowState.mComputedBorderPadding;
|
||||
@ -123,13 +148,6 @@ nsHTMLCanvasFrame::Reflow(nsPresContext* aPresContext,
|
||||
aMetrics.ascent = aMetrics.height;
|
||||
aMetrics.descent = 0;
|
||||
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit());
|
||||
}
|
||||
|
||||
if (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH) {
|
||||
aMetrics.mMaximumWidth = aMetrics.width;
|
||||
}
|
||||
aMetrics.mOverflowArea.SetRect(0, 0, aMetrics.width, aMetrics.height);
|
||||
FinishAndStoreOverflow(&aMetrics);
|
||||
|
||||
@ -235,6 +253,12 @@ nsHTMLCanvasFrame::GetType() const
|
||||
return nsLayoutAtoms::HTMLCanvasFrame;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsHTMLCanvasFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced));
|
||||
}
|
||||
|
||||
// get the offset into the content area of the image where aImg starts if it is a continuation.
|
||||
// from nsImageFrame
|
||||
nscoord
|
||||
|
@ -60,6 +60,17 @@ public:
|
||||
void PaintCanvas(nsIRenderingContext& aRenderingContext,
|
||||
const nsRect& aDirtyRect, nsPoint aPt);
|
||||
|
||||
/* get the size of the canvas's image */
|
||||
nsSize GetCanvasSize();
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap);
|
||||
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -76,6 +87,7 @@ public:
|
||||
#endif
|
||||
|
||||
virtual nsIAtom* GetType() const;
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
||||
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
|
||||
|
@ -62,7 +62,6 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsIFontMetrics.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsCSSFrameConstructor.h"
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsBlockFrame.h"
|
||||
|
@ -41,7 +41,6 @@
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsHTMLContainerFrame.h"
|
||||
#include "nsCSSRendering.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsStyleContext.h"
|
||||
#include "nsIView.h"
|
||||
@ -101,6 +100,8 @@ public:
|
||||
NS_IMETHOD RemoveFrame(nsIAtom* aListName,
|
||||
nsIFrame* aOldFrame);
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -281,9 +282,8 @@ CanvasFrame::AppendFrames(nsIAtom* aListName,
|
||||
#endif
|
||||
mFrames.AppendFrame(nsnull, aFrameList);
|
||||
|
||||
// Generate a reflow command to reflow the newly inserted frame
|
||||
rv = GetPresContext()->PresShell()->
|
||||
AppendReflowCommand(this, eReflowType_ReflowDirty, nsnull);
|
||||
GetPresContext()->PresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eTreeChange);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -329,9 +329,8 @@ CanvasFrame::RemoveFrame(nsIAtom* aListName,
|
||||
// Remove the frame and destroy it
|
||||
mFrames.DestroyFrame(aOldFrame);
|
||||
|
||||
// Generate a reflow command so we get reflowed
|
||||
rv = GetPresContext()->PresShell()->
|
||||
AppendReflowCommand(this, eReflowType_ReflowDirty, nsnull);
|
||||
GetPresContext()->PresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eTreeChange);
|
||||
} else {
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
@ -525,53 +524,45 @@ CanvasFrame::PaintFocus(nsIRenderingContext& aRenderingContext, nsPoint aPt)
|
||||
nsnull);
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
CanvasFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
if (mFrames.IsEmpty())
|
||||
result = 0;
|
||||
else
|
||||
result = mFrames.FirstChild()->GetMinWidth(aRenderingContext);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
CanvasFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
if (mFrames.IsEmpty())
|
||||
result = 0;
|
||||
else
|
||||
result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
CanvasFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("CanvasFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("CanvasFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
NS_FRAME_TRACE_REFLOW_IN("CanvasFrame::Reflow");
|
||||
//NS_PRECONDITION(!aDesiredSize.mComputeMEW, "unexpected request");
|
||||
|
||||
// Initialize OUT parameter
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
PRBool isStyleChange = PR_FALSE;
|
||||
PRBool isDirtyChildReflow = PR_FALSE;
|
||||
|
||||
// Check for an incremental reflow
|
||||
if (eReflowReason_Incremental == aReflowState.reason) {
|
||||
// See if we're the target frame
|
||||
nsHTMLReflowCommand *command = aReflowState.path->mReflowCommand;
|
||||
if (command) {
|
||||
// Get the reflow type
|
||||
switch (command->Type()) {
|
||||
case eReflowType_ReflowDirty:
|
||||
isDirtyChildReflow = PR_TRUE;
|
||||
break;
|
||||
|
||||
case eReflowType_StyleChanged:
|
||||
// Remember it's a style change so we can set the reflow reason below
|
||||
isStyleChange = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ASSERTION(PR_FALSE, "unexpected reflow command type");
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef DEBUG
|
||||
nsReflowPath::iterator iter = aReflowState.path->FirstChild();
|
||||
NS_ASSERTION(*iter == mFrames.FirstChild(), "unexpected next reflow command frame");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Reflow our one and only child frame
|
||||
nsHTMLReflowMetrics kidDesiredSize(nsnull);
|
||||
nsHTMLReflowMetrics kidDesiredSize;
|
||||
if (mFrames.IsEmpty()) {
|
||||
// We have no child frame, so return an empty size
|
||||
aDesiredSize.width = aDesiredSize.height = 0;
|
||||
@ -579,24 +570,13 @@ CanvasFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
} else {
|
||||
nsIFrame* kidFrame = mFrames.FirstChild();
|
||||
|
||||
nsReflowReason reason;
|
||||
if (isDirtyChildReflow) {
|
||||
// Note: the only reason the frame would be dirty would be if it had
|
||||
// just been inserted or appended
|
||||
reason = eReflowReason_Initial;
|
||||
} else if (isStyleChange) {
|
||||
reason = eReflowReason_StyleChange;
|
||||
} else {
|
||||
reason = aReflowState.reason;
|
||||
}
|
||||
PRBool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0;
|
||||
|
||||
// We must specify an unconstrained available height, because constrained
|
||||
// is only for when we're paginated...
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
|
||||
nsSize(aReflowState.availableWidth,
|
||||
NS_UNCONSTRAINEDSIZE),
|
||||
reason);
|
||||
NS_UNCONSTRAINEDSIZE));
|
||||
|
||||
// Reflow the frame
|
||||
ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
|
||||
@ -610,7 +590,7 @@ CanvasFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
// If the child frame was just inserted, then we're responsible for making sure
|
||||
// it repaints
|
||||
if (isDirtyChildReflow) {
|
||||
if (kidDirty) {
|
||||
// But we have a new child, which will affect our background, so
|
||||
// invalidate our whole rect.
|
||||
// Note: Even though we request to be sized to our child's size, our
|
||||
|
@ -42,8 +42,6 @@
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsISupports.h"
|
||||
#include "nsReflowType.h"
|
||||
class nsHTMLReflowCommand;
|
||||
class nsIAtom;
|
||||
class nsNodeInfoManager;
|
||||
class nsIContent;
|
||||
|
@ -1,159 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsHTMLReflowCommand.h"
|
||||
#include "nsHTMLParts.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsFrame.h"
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
|
||||
#ifdef DEBUG_jesup
|
||||
PRInt32 gReflows;
|
||||
PRInt32 gReflowsInUse;
|
||||
PRInt32 gReflowsInUseMax;
|
||||
PRInt32 gReflowsZero;
|
||||
PRInt32 gReflowsAuto;
|
||||
PRInt32 gReflowsLarger;
|
||||
PRInt32 gReflowsMaxZero;
|
||||
PRInt32 gReflowsMaxAuto;
|
||||
PRInt32 gReflowsMaxLarger;
|
||||
class mPathStats {
|
||||
public:
|
||||
mPathStats();
|
||||
~mPathStats();
|
||||
};
|
||||
mPathStats::mPathStats()
|
||||
{
|
||||
}
|
||||
mPathStats::~mPathStats()
|
||||
{
|
||||
printf("nsHTMLReflowCommand->mPath stats:\n");
|
||||
printf("\tNumber created: %d\n",gReflows);
|
||||
printf("\tNumber in-use: %d\n",gReflowsInUseMax);
|
||||
|
||||
printf("\tNumber size == 0: %d\n",gReflowsZero);
|
||||
printf("\tNumber size <= 8: %d\n",gReflowsAuto);
|
||||
printf("\tNumber size > 8: %d\n",gReflowsLarger);
|
||||
printf("\tNum max size == 0: %d\n",gReflowsMaxZero);
|
||||
printf("\tNum max size <= 8: %d\n",gReflowsMaxAuto);
|
||||
printf("\tNum max size > 8: %d\n",gReflowsMaxLarger);
|
||||
}
|
||||
|
||||
// Just so constructor/destructor's get called
|
||||
mPathStats gmPathStats;
|
||||
#endif
|
||||
|
||||
// Construct a reflow command given a target frame, reflow command type,
|
||||
// and optional child frame
|
||||
nsHTMLReflowCommand::nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||
nsReflowType aReflowType,
|
||||
nsIAtom* aChildListName)
|
||||
: mType(aReflowType), mTargetFrame(aTargetFrame), mListName(aChildListName),
|
||||
mFlags(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsHTMLReflowCommand);
|
||||
NS_PRECONDITION(mTargetFrame != nsnull, "null target frame");
|
||||
#ifdef DEBUG_jesup
|
||||
gReflows++;
|
||||
gReflowsInUse++;
|
||||
if (gReflowsInUse > gReflowsInUseMax)
|
||||
gReflowsInUseMax = gReflowsInUse;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsHTMLReflowCommand::~nsHTMLReflowCommand()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsHTMLReflowCommand);
|
||||
#ifdef DEBUG_jesup
|
||||
if (mPath.GetArraySize() == 0)
|
||||
gReflowsMaxZero++;
|
||||
else if (mPath.GetArraySize() <= 8)
|
||||
gReflowsMaxAuto++;
|
||||
else
|
||||
gReflowsMaxLarger++;
|
||||
gReflowsInUse--;
|
||||
#endif
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLReflowCommand::List(FILE* out) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
static const char* kReflowCommandType[] = {
|
||||
"ContentChanged",
|
||||
"StyleChanged",
|
||||
"ReflowDirty",
|
||||
"UserDefined",
|
||||
};
|
||||
|
||||
fprintf(out, "ReflowCommand@%p[%s]:",
|
||||
this, kReflowCommandType[mType]);
|
||||
if (mTargetFrame) {
|
||||
fprintf(out, " target=");
|
||||
nsFrame::ListTag(out, mTargetFrame);
|
||||
}
|
||||
if (mListName) {
|
||||
fprintf(out, " list=");
|
||||
nsAutoString attr;
|
||||
mListName->ToString(attr);
|
||||
fputs(NS_LossyConvertUTF16toASCII(attr).get(), out);
|
||||
}
|
||||
fprintf(out, "\n");
|
||||
|
||||
// Show the path, but without using mPath which is in an undefined
|
||||
// state at this point.
|
||||
if (mTargetFrame) {
|
||||
PRBool didOne = PR_FALSE;
|
||||
for (nsIFrame* f = mTargetFrame; f; f = f->GetParent()) {
|
||||
if (f != mTargetFrame) {
|
||||
fprintf(out, " ");
|
||||
nsFrame::ListTag(out, f);
|
||||
didOne = PR_TRUE;
|
||||
}
|
||||
}
|
||||
if (didOne) {
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef nsHTMLReflowCommand_h___
|
||||
#define nsHTMLReflowCommand_h___
|
||||
#include "nsReflowType.h"
|
||||
#include <stdio.h>
|
||||
#include "nsIAtom.h"
|
||||
|
||||
class nsIFrame;
|
||||
class nsPresContext;
|
||||
class nsIRenderingContext;
|
||||
struct nsHTMLReflowMetrics;
|
||||
struct nsSize;
|
||||
|
||||
// Reflow command flags
|
||||
#define NS_RC_CREATED_DURING_DOCUMENT_LOAD 0x0001
|
||||
|
||||
|
||||
/**
|
||||
* A reflow command is an object that is generated in response to a content
|
||||
* model change notification. The reflow command is given to a presentation
|
||||
* shell where it is queued and then dispatched by invoking the reflow
|
||||
* commands's Dispatch() member function.
|
||||
*
|
||||
* Reflow command processing follows a path from the root frame down to the
|
||||
* target frame (the frame for which the reflow command is destined). Reflow
|
||||
* commands are processed by invoking the frame's Reflow() member function.
|
||||
*
|
||||
* The typical flow of control for a given reflow command starts with a content
|
||||
* change notification. The content notifications are sent to document observers.
|
||||
* The presentation shell forwards the notifications to the style set. The style
|
||||
* system responds to the notifications by creating new frame (or destroying
|
||||
* existing frames) as appropriate, and then generating a reflow command.
|
||||
*
|
||||
* @see nsIDocumentObserver
|
||||
* @see nsIStyleSet
|
||||
* @see nsIFrameReflow#Reflow()
|
||||
* @see nsIPresShell#AppendReflowCommand()
|
||||
* @see nsIPresShell#ProcessReflowCommands()
|
||||
*/
|
||||
class nsHTMLReflowCommand {
|
||||
public:
|
||||
/**
|
||||
* Construct an HTML reflow command of type aReflowType and with target
|
||||
* frame aTargetFrame. You can also specify an optional child frame, e.g.
|
||||
* to indicate the inserted child frame
|
||||
*/
|
||||
nsHTMLReflowCommand(nsIFrame* aTargetFrame,
|
||||
nsReflowType aReflowType,
|
||||
nsIAtom* aChildListName);
|
||||
|
||||
~nsHTMLReflowCommand();
|
||||
|
||||
/**
|
||||
* Get the target of the reflow command.
|
||||
*/
|
||||
nsIFrame* GetTarget() const { return mTargetFrame; }
|
||||
|
||||
/**
|
||||
* Get the type of reflow command.
|
||||
*/
|
||||
nsReflowType Type() const { return mType; }
|
||||
|
||||
/**
|
||||
* Returns the name of the child list to which the child frame belongs.
|
||||
* Only used for reflow command types FrameAppended, FrameInserted, and
|
||||
* FrameRemoved
|
||||
*
|
||||
* Returns nsnull if the child frame is associated with the unnamed
|
||||
* principal child list
|
||||
*/
|
||||
nsIAtom* GetChildListName() const { return mListName; }
|
||||
|
||||
/**
|
||||
* Dump out the reflow-command to out
|
||||
*/
|
||||
nsresult List(FILE* out) const;
|
||||
|
||||
/**
|
||||
* Get/set reflow command flags
|
||||
*/
|
||||
PRInt32 GetFlagBits() { return mFlags; }
|
||||
void AddFlagBits(PRInt32 aBits) { mFlags |= aBits; }
|
||||
void RemoveFlagBits(PRInt32 aBits) { mFlags &= ~aBits; }
|
||||
|
||||
/**
|
||||
* DEPRECATED compatibility methods
|
||||
*/
|
||||
nsresult GetTarget(nsIFrame*& aTargetFrame) const {
|
||||
aTargetFrame = mTargetFrame;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetType(nsReflowType& aReflowType) const {
|
||||
aReflowType = mType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetChildListName(nsIAtom*& aListName) const {
|
||||
aListName = mListName;
|
||||
NS_IF_ADDREF(aListName);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsReflowType mType;
|
||||
nsIFrame* mTargetFrame;
|
||||
nsCOMPtr<nsIAtom> mListName;
|
||||
// XXXbz remove the flags? They're not being used for much...
|
||||
PRInt32 mFlags;
|
||||
};
|
||||
|
||||
#endif /* nsHTMLReflowCommand_h___ */
|
@ -50,9 +50,8 @@
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
// Option flags
|
||||
#define NS_REFLOW_CALC_MAX_WIDTH 0x0001
|
||||
#ifdef MOZ_MATHML
|
||||
#define NS_REFLOW_CALC_BOUNDING_METRICS 0x0002
|
||||
#define NS_REFLOW_CALC_BOUNDING_METRICS 0x0001
|
||||
#endif
|
||||
|
||||
/**
|
||||
@ -143,12 +142,6 @@ struct nsHTMLReflowMetrics {
|
||||
nscoord width, height; // [OUT] desired width and height
|
||||
nscoord ascent, descent; // [OUT] ascent and descent information
|
||||
|
||||
nscoord mMaxElementWidth; // [OUT]
|
||||
|
||||
// Used for incremental reflow. If the NS_REFLOW_CALC_MAX_WIDTH flag is set,
|
||||
// then the caller is requesting that you update and return your maximum width
|
||||
nscoord mMaximumWidth; // [OUT]
|
||||
|
||||
#ifdef MOZ_MATHML
|
||||
// Metrics that _exactly_ enclose the text to allow precise MathML placements.
|
||||
// If the NS_REFLOW_CALC_BOUNDING_METRICS flag is set, then the caller is
|
||||
@ -175,22 +168,15 @@ struct nsHTMLReflowMetrics {
|
||||
|
||||
PRUint32 mFlags;
|
||||
|
||||
// used by tables to optimize common cases
|
||||
PRPackedBool mNothingChanged;
|
||||
|
||||
// Should we compute mMaxElementWidth?
|
||||
PRPackedBool mComputeMEW;
|
||||
|
||||
nsHTMLReflowMetrics(PRBool aComputeMEW, PRUint32 aFlags = 0) {
|
||||
mComputeMEW = aComputeMEW;
|
||||
mMaxElementWidth = 0;
|
||||
mMaximumWidth = 0;
|
||||
// XXXldb Should |aFlags| generally be passed from parent to child?
|
||||
// Some places do it, and some don't. |aFlags| should perhaps go away
|
||||
// entirely.
|
||||
nsHTMLReflowMetrics(PRUint32 aFlags = 0) {
|
||||
mFlags = aFlags;
|
||||
mOverflowArea.x = 0;
|
||||
mOverflowArea.y = 0;
|
||||
mOverflowArea.width = 0;
|
||||
mOverflowArea.height = 0;
|
||||
mNothingChanged = PR_FALSE;
|
||||
#ifdef MOZ_MATHML
|
||||
mBoundingMetrics.Clear();
|
||||
#endif
|
||||
@ -202,31 +188,14 @@ struct nsHTMLReflowMetrics {
|
||||
ascent = descent = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* set the maxElementWidth to the desired width. If the frame has a percent
|
||||
* width specification it can be shrinked to 0 if the containing frame shrinks
|
||||
* so we need to report 0 otherwise the incr. reflow will fail
|
||||
* @param aWidthUnit - the width unit from the corresponding reflowstate
|
||||
*/
|
||||
void SetMEWToActualWidth(nsStyleUnit aWidthUnit) {
|
||||
if (aWidthUnit != eStyleUnit_Percent) {
|
||||
mMaxElementWidth = width;
|
||||
} else {
|
||||
mMaxElementWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
nsHTMLReflowMetrics& operator=(const nsHTMLReflowMetrics& aOther)
|
||||
{
|
||||
mMaxElementWidth = aOther.mMaxElementWidth;
|
||||
mMaximumWidth = aOther.mMaximumWidth;
|
||||
mFlags = aOther.mFlags;
|
||||
mCarriedOutBottomMargin = aOther.mCarriedOutBottomMargin;
|
||||
mOverflowArea.x = aOther.mOverflowArea.x;
|
||||
mOverflowArea.y = aOther.mOverflowArea.y;
|
||||
mOverflowArea.width = aOther.mOverflowArea.width;
|
||||
mOverflowArea.height = aOther.mOverflowArea.height;
|
||||
mNothingChanged = aOther.mNothingChanged;
|
||||
#ifdef MOZ_MATHML
|
||||
mBoundingMetrics = aOther.mBoundingMetrics;
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -42,10 +42,9 @@
|
||||
|
||||
#include "nsMargin.h"
|
||||
#include "nsStyleCoord.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
class nsIFrame;
|
||||
class nsPresContext;
|
||||
class nsReflowPath;
|
||||
class nsIRenderingContext;
|
||||
class nsSpaceManager;
|
||||
class nsLineLayout;
|
||||
@ -60,6 +59,13 @@ struct nsStylePadding;
|
||||
struct nsStyleText;
|
||||
struct nsHypotheticalBox;
|
||||
|
||||
#define NS_CSS_MINMAX(_value,_min,_max) \
|
||||
((_value) < (_min) \
|
||||
? (_min) \
|
||||
: ((_value) > (_max) \
|
||||
? (_max) \
|
||||
: (_value)))
|
||||
|
||||
/**
|
||||
* Constant used to indicate an unconstrained size.
|
||||
*
|
||||
@ -67,23 +73,6 @@ struct nsHypotheticalBox;
|
||||
*/
|
||||
#define NS_UNCONSTRAINEDSIZE NS_MAXSIZE
|
||||
|
||||
/**
|
||||
* The reason the frame is being reflowed.
|
||||
*
|
||||
* XXX Should probably be a #define so it can be extended for specialized
|
||||
* reflow interfaces...
|
||||
*
|
||||
* @see nsHTMLReflowState
|
||||
*/
|
||||
enum nsReflowReason {
|
||||
eReflowReason_Initial = 0, // initial reflow of a newly created frame
|
||||
eReflowReason_Incremental = 1, // an incremental change has occurred. see the reflow command for details
|
||||
eReflowReason_Resize = 2, // general request to determine a desired size
|
||||
eReflowReason_StyleChange = 3, // request to reflow because of a style change. Note: you must reflow
|
||||
// all your child frames
|
||||
eReflowReason_Dirty = 4 // request to reflow because you and/or your children are dirty
|
||||
};
|
||||
|
||||
/**
|
||||
* CSS Frame type. Included as part of the reflow state.
|
||||
*/
|
||||
@ -100,25 +89,44 @@ typedef PRUint32 nsCSSFrameType;
|
||||
* Bit-flag that indicates whether the element is replaced. Applies to inline,
|
||||
* block-level, floating, and absolutely positioned elements
|
||||
*/
|
||||
#define NS_CSS_FRAME_TYPE_REPLACED 0x8000
|
||||
#define NS_CSS_FRAME_TYPE_REPLACED 0x08000
|
||||
|
||||
/**
|
||||
* Bit-flag that indicates that the element is replaced and contains a block
|
||||
* (eg some form controls). Applies to inline, block-level, floating, and
|
||||
* absolutely positioned elements. Mutually exclusive with
|
||||
* NS_CSS_FRAME_TYPE_REPLACED.
|
||||
*/
|
||||
#define NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK 0x10000
|
||||
|
||||
/**
|
||||
* Helper macros for telling whether items are replaced
|
||||
*/
|
||||
#define NS_FRAME_IS_REPLACED(_ft) \
|
||||
#define NS_FRAME_IS_REPLACED_NOBLOCK(_ft) \
|
||||
(NS_CSS_FRAME_TYPE_REPLACED == ((_ft) & NS_CSS_FRAME_TYPE_REPLACED))
|
||||
|
||||
#define NS_FRAME_IS_REPLACED(_ft) \
|
||||
(NS_FRAME_IS_REPLACED_NOBLOCK(_ft) || \
|
||||
NS_FRAME_IS_REPLACED_CONTAINS_BLOCK(_ft))
|
||||
|
||||
#define NS_FRAME_REPLACED(_ft) \
|
||||
(NS_CSS_FRAME_TYPE_REPLACED | (_ft))
|
||||
|
||||
#define NS_FRAME_IS_REPLACED_CONTAINS_BLOCK(_ft) \
|
||||
(NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK == \
|
||||
((_ft) & NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK))
|
||||
|
||||
#define NS_FRAME_REPLACED_CONTAINS_BLOCK(_ft) \
|
||||
(NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK | (_ft))
|
||||
|
||||
/**
|
||||
* A macro to extract the type. Masks off the 'replaced' bit-flag
|
||||
*/
|
||||
#define NS_FRAME_GET_TYPE(_ft) \
|
||||
((_ft) & ~NS_CSS_FRAME_TYPE_REPLACED)
|
||||
#define NS_FRAME_GET_TYPE(_ft) \
|
||||
((_ft) & ~(NS_CSS_FRAME_TYPE_REPLACED | \
|
||||
NS_CSS_FRAME_TYPE_REPLACED_CONTAINS_BLOCK))
|
||||
|
||||
#define NS_INTRINSICSIZE NS_UNCONSTRAINEDSIZE
|
||||
#define NS_SHRINKWRAPWIDTH NS_UNCONSTRAINEDSIZE
|
||||
#define NS_AUTOHEIGHT NS_UNCONSTRAINEDSIZE
|
||||
#define NS_AUTOMARGIN NS_UNCONSTRAINEDSIZE
|
||||
#define NS_AUTOOFFSET NS_UNCONSTRAINEDSIZE
|
||||
@ -126,29 +134,75 @@ typedef PRUint32 nsCSSFrameType;
|
||||
// if any are changed to be a value other than NS_UNCONSTRAINEDSIZE
|
||||
// at least update AdjustComputedHeight/Width and test ad nauseum
|
||||
|
||||
/**
|
||||
* Reflow state passed to a frame during reflow.
|
||||
*
|
||||
* @see nsIFrame#Reflow()
|
||||
*/
|
||||
struct nsHTMLReflowState {
|
||||
// the reflow states are linked together. this is the pointer to the
|
||||
// parent's reflow state
|
||||
const nsHTMLReflowState* parentReflowState;
|
||||
|
||||
// A base class of nsHTMLReflowState that computes only the padding,
|
||||
// border, and margin, since those values are needed more often.
|
||||
struct nsCSSOffsetState {
|
||||
public:
|
||||
// the frame being reflowed
|
||||
nsIFrame* frame;
|
||||
|
||||
// the reason for the reflow
|
||||
nsReflowReason reason;
|
||||
// rendering context to use for measurement
|
||||
nsIRenderingContext* rendContext;
|
||||
|
||||
// the incremental reflow path, when the reflow reason is
|
||||
// eReflowReason_Incremental. Specifically, this corresponds to the
|
||||
// portion of the incremental reflow path from `frame' down. Note
|
||||
// that it is safe to assume that this is non-null: we maintain the
|
||||
// invariant that it contains a valid nsReflowPath pointer when
|
||||
// reason == eReflowReason_Incremental.
|
||||
nsReflowPath *path;
|
||||
// Computed margin values
|
||||
nsMargin mComputedMargin;
|
||||
|
||||
// Cached copy of the border + padding values
|
||||
nsMargin mComputedBorderPadding;
|
||||
|
||||
// Computed padding values
|
||||
nsMargin mComputedPadding;
|
||||
|
||||
// Callers using this constructor must call InitOffsets on their own.
|
||||
nsCSSOffsetState(nsIFrame *aFrame, nsIRenderingContext *aRenderingContext)
|
||||
: frame(aFrame)
|
||||
, rendContext(aRenderingContext)
|
||||
{
|
||||
}
|
||||
|
||||
nsCSSOffsetState(nsIFrame *aFrame, nsIRenderingContext *aRenderingContext,
|
||||
nscoord aContainingBlockWidth)
|
||||
: frame(aFrame)
|
||||
, rendContext(aRenderingContext)
|
||||
{
|
||||
InitOffsets(aContainingBlockWidth);
|
||||
}
|
||||
|
||||
void InitOffsets(nscoord aContainingBlockWidth,
|
||||
nsMargin *aBorder = nsnull, nsMargin *aPadding = nsnull);
|
||||
|
||||
private:
|
||||
// Computes margin values from the specified margin style information, and
|
||||
// fills in the mComputedMargin member
|
||||
void ComputeMargin(nscoord aContainingBlockWidth);
|
||||
|
||||
// Computes padding values from the specified padding style information, and
|
||||
// fills in the mComputedPadding member
|
||||
void ComputePadding(nscoord aContainingBlockWidth);
|
||||
|
||||
protected:
|
||||
inline void ComputeHorizontalValue(nscoord aContainingBlockWidth,
|
||||
nsStyleUnit aUnit,
|
||||
const nsStyleCoord& aCoord,
|
||||
nscoord& aResult);
|
||||
inline void ComputeVerticalValue(nscoord aContainingBlockHeight,
|
||||
nsStyleUnit aUnit,
|
||||
const nsStyleCoord& aCoord,
|
||||
nscoord& aResult);
|
||||
};
|
||||
|
||||
/**
|
||||
* State passed to a frame during reflow or intrinsic size calculation.
|
||||
*
|
||||
* XXX Refactor so only a base class (nsSizingState?) is used for intrinsic
|
||||
* size calculation.
|
||||
*
|
||||
* @see nsIFrame#Reflow()
|
||||
*/
|
||||
struct nsHTMLReflowState : public nsCSSOffsetState {
|
||||
// the reflow states are linked together. this is the pointer to the
|
||||
// parent's reflow state
|
||||
const nsHTMLReflowState* parentReflowState;
|
||||
|
||||
// the available width in which to reflow the frame. The space
|
||||
// represents the amount of room for the frame's border, padding,
|
||||
@ -160,16 +214,13 @@ struct nsHTMLReflowState {
|
||||
// A value of NS_UNCONSTRAINEDSIZE for the available height means
|
||||
// you can choose whatever size you want. In galley mode the
|
||||
// available height is always NS_UNCONSTRAINEDSIZE, and only page
|
||||
// mode involves a constrained height. The element's the top border
|
||||
// and padding, and content, must fit. If the element is complete
|
||||
// after reflow then its bottom border, padding and margin (and
|
||||
// similar for its complete ancestors) will need to fit in this
|
||||
// height.
|
||||
// mode or multi-column layout involves a constrained height. The
|
||||
// element's the top border and padding, and content, must fit. If the
|
||||
// element is complete after reflow then its bottom border, padding
|
||||
// and margin (and similar for its complete ancestors) will need to
|
||||
// fit in this height.
|
||||
nscoord availableHeight;
|
||||
|
||||
// rendering context to use for measurement
|
||||
nsIRenderingContext* rendContext;
|
||||
|
||||
// The type of frame, from css's perspective. This value is
|
||||
// initialized by the Init method below.
|
||||
nsCSSFrameType mFrameType;
|
||||
@ -192,9 +243,6 @@ struct nsHTMLReflowState {
|
||||
//
|
||||
// For block-level frames, the computed width is based on the width of the
|
||||
// containing block, the margin/border/padding areas, and the min/max width.
|
||||
// A value of NS_SHRINKWRAPWIDTH means that you should choose a width based
|
||||
// on your content. The width may be as large as the specified maximum width
|
||||
// (see mComputedMaxWidth).
|
||||
nscoord mComputedWidth;
|
||||
|
||||
// The computed height specifies the frame's content height, and it does
|
||||
@ -212,20 +260,13 @@ struct nsHTMLReflowState {
|
||||
// means you use your intrinsic height as the computed height
|
||||
nscoord mComputedHeight;
|
||||
|
||||
// Computed margin values
|
||||
nsMargin mComputedMargin;
|
||||
|
||||
// Cached copy of the border values
|
||||
nsMargin mComputedBorderPadding;
|
||||
|
||||
// Computed padding values
|
||||
nsMargin mComputedPadding;
|
||||
|
||||
// Computed values for 'left/top/right/bottom' offsets. Only applies to
|
||||
// 'positioned' elements
|
||||
nsMargin mComputedOffsets;
|
||||
|
||||
// Computed values for 'min-width/max-width' and 'min-height/max-height'
|
||||
// XXXldb The width ones here should go; they should be needed only
|
||||
// internally.
|
||||
nscoord mComputedMinWidth, mComputedMaxWidth;
|
||||
nscoord mComputedMinHeight, mComputedMaxHeight;
|
||||
|
||||
@ -269,66 +310,45 @@ struct nsHTMLReflowState {
|
||||
// is assuming a horizontal scrollbar
|
||||
PRUint16 mAssumingVScrollbar:1; // parent frame is an nsIScrollableFrame and it
|
||||
// is assuming a vertical scrollbar
|
||||
|
||||
PRUint16 mHResize:1; // Is frame (a) not dirty and (b) a
|
||||
// different width than before?
|
||||
|
||||
PRUint16 mVResize:1; // Is frame (a) not dirty and (b) a
|
||||
// different height than before or
|
||||
// (potentially) in a context where
|
||||
// percent heights have a different
|
||||
// basis?
|
||||
} mFlags;
|
||||
|
||||
#ifdef IBMBIDI
|
||||
nscoord mRightEdge;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
// hook for attaching debug info (e.g. tables may attach a timer during reflow)
|
||||
void* mDebugHook;
|
||||
|
||||
static const char* ReasonToString(nsReflowReason aReason);
|
||||
#endif
|
||||
|
||||
// Note: The copy constructor is written by the compiler automatically. You
|
||||
// can use that and then override specific values if you want, or you can
|
||||
// call Init as desired...
|
||||
|
||||
// Initialize a <b>root</b> reflow state with a rendering context to
|
||||
// use for measuring things.
|
||||
nsHTMLReflowState(nsPresContext* aPresContext,
|
||||
nsHTMLReflowState(nsPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
nsReflowReason aReason,
|
||||
nsIRenderingContext* aRenderingContext,
|
||||
const nsSize& aAvailableSpace);
|
||||
|
||||
// Initialize a <b>root</b> reflow state for an <b>incremental</b>
|
||||
// reflow.
|
||||
nsHTMLReflowState(nsPresContext* aPresContext,
|
||||
nsIFrame* aFrame,
|
||||
nsReflowPath* aReflowPath,
|
||||
nsIRenderingContext* aRenderingContext,
|
||||
const nsSize& aAvailableSpace);
|
||||
|
||||
// Initialize a reflow state for a child frames reflow. Some state
|
||||
// is copied from the parent reflow state; the remaining state is
|
||||
// computed.
|
||||
nsHTMLReflowState(nsPresContext* aPresContext,
|
||||
nsHTMLReflowState(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aParentReflowState,
|
||||
nsIFrame* aFrame,
|
||||
const nsSize& aAvailableSpace,
|
||||
nsReflowReason aReason,
|
||||
// These two are used by absolute positioning code
|
||||
// to override default containing block w & h:
|
||||
nscoord aContainingBlockWidth = -1,
|
||||
nscoord aContainingBlockHeight = -1,
|
||||
PRBool aInit = PR_TRUE);
|
||||
|
||||
// Same as the previous except that the reason is taken from the
|
||||
// parent's reflow state.
|
||||
nsHTMLReflowState(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aParentReflowState,
|
||||
nsIFrame* aFrame,
|
||||
const nsSize& aAvailableSpace);
|
||||
|
||||
// Used when you want to override the default containing block
|
||||
// width and height. Used by absolute positioning code
|
||||
nsHTMLReflowState(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aParentReflowState,
|
||||
nsIFrame* aFrame,
|
||||
const nsSize& aAvailableSpace,
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight,
|
||||
nsReflowReason aReason);
|
||||
|
||||
// This method initializes various data members. It is automatically
|
||||
// called by the various constructors
|
||||
void Init(nsPresContext* aPresContext,
|
||||
@ -342,17 +362,6 @@ struct nsHTMLReflowState {
|
||||
static nscoord
|
||||
GetContainingBlockContentWidth(const nsHTMLReflowState* aReflowState);
|
||||
|
||||
/**
|
||||
* Adjust content MEW take into account the settings of the CSS
|
||||
* 'width', 'min-width' and 'max-width' properties.
|
||||
*/
|
||||
nscoord AdjustIntrinsicMinContentWidthForStyle(nscoord aWidth) const;
|
||||
/**
|
||||
* Adjust content maximum-width take into account the settings of
|
||||
* the CSS 'width', 'min-width' and 'max-width' properties.
|
||||
*/
|
||||
nscoord AdjustIntrinsicContentWidthForStyle(nscoord aWidth) const;
|
||||
|
||||
/**
|
||||
* Find the containing block of aFrame. This may return null if
|
||||
* there isn't one (but that should really only happen for root
|
||||
@ -360,26 +369,6 @@ struct nsHTMLReflowState {
|
||||
*/
|
||||
static nsIFrame* GetContainingBlockFor(const nsIFrame* aFrame);
|
||||
|
||||
/**
|
||||
* Get the page box reflow state, starting from a frames
|
||||
* <B>parent</B> reflow state (the parent reflow state may or may not end
|
||||
* up being the containing block reflow state)
|
||||
*/
|
||||
static const nsHTMLReflowState*
|
||||
GetPageBoxReflowState(const nsHTMLReflowState* aParentRS);
|
||||
|
||||
/**
|
||||
* Compute the border plus padding for <TT>aFrame</TT>. If a
|
||||
* percentage needs to be computed it will be computed by finding
|
||||
* the containing block, use GetContainingBlockReflowState.
|
||||
* aParentReflowState is aFrame's
|
||||
* parent's reflow state. The resulting computed border plus padding
|
||||
* is returned in aResult.
|
||||
*/
|
||||
static void ComputeBorderPaddingFor(nsIFrame* aFrame,
|
||||
const nsHTMLReflowState* aParentRS,
|
||||
nsMargin& aResult);
|
||||
|
||||
/**
|
||||
* Calculate the raw line-height property for the given frame. The return
|
||||
* value, if line-height was applied and is valid will be >= 0. Otherwise,
|
||||
@ -406,9 +395,23 @@ struct nsHTMLReflowState {
|
||||
*/
|
||||
void ApplyMinMaxConstraints(nscoord* aContentWidth, nscoord* aContentHeight) const;
|
||||
|
||||
PRBool ShouldReflowAllKids() const {
|
||||
// Note that we could make a stronger optimization for mVResize if
|
||||
// we use it in a ShouldReflowChild test that replaces the current
|
||||
// checks of NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN, if it
|
||||
// were tested there along with NS_FRAME_CONTAINS_RELATIVE_HEIGHT.
|
||||
// This would need to be combined with a slight change in which
|
||||
// frames NS_FRAME_CONTAINS_RELATIVE_HEIGHT is marked on.
|
||||
return (frame->GetStateBits() & NS_FRAME_IS_DIRTY) ||
|
||||
mFlags.mHResize ||
|
||||
(mFlags.mVResize &&
|
||||
(frame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
void InitCBReflowState();
|
||||
void InitResizeFlags(nsPresContext* aPresContext);
|
||||
|
||||
void InitConstraints(nsPresContext* aPresContext,
|
||||
nscoord aContainingBlockWidth,
|
||||
@ -432,33 +435,6 @@ protected:
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight);
|
||||
|
||||
void ComputeBlockBoxData(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState* cbrs,
|
||||
nsStyleUnit aWidthUnit,
|
||||
nsStyleUnit aHeightUnit,
|
||||
nscoord aContainingBlockWidth,
|
||||
nscoord aContainingBlockHeight);
|
||||
|
||||
void ComputeHorizontalValue(nscoord aContainingBlockWidth,
|
||||
nsStyleUnit aUnit,
|
||||
const nsStyleCoord& aCoord,
|
||||
nscoord& aResult);
|
||||
|
||||
void ComputeVerticalValue(nscoord aContainingBlockHeight,
|
||||
nsStyleUnit aUnit,
|
||||
const nsStyleCoord& aCoord,
|
||||
nscoord& aResult);
|
||||
|
||||
// Computes margin values from the specified margin style information, and
|
||||
// fills in the mComputedMargin member
|
||||
void ComputeMargin(nscoord aContainingBlockWidth,
|
||||
const nsHTMLReflowState* aContainingBlockRS);
|
||||
|
||||
// Computes padding values from the specified padding style information, and
|
||||
// fills in the mComputedPadding member
|
||||
void ComputePadding(nscoord aContainingBlockWidth,
|
||||
const nsHTMLReflowState* aContainingBlockRS);
|
||||
|
||||
// Calculates the computed values for the 'min-Width', 'max-Width',
|
||||
// 'min-Height', and 'max-Height' properties, and stores them in the assorted
|
||||
// data members
|
||||
@ -468,14 +444,6 @@ protected:
|
||||
|
||||
nscoord CalculateHorizBorderPaddingMargin(nscoord aContainingBlockWidth);
|
||||
|
||||
// Adjust Computed sizes for Min/Max Width and box-Sizing (if
|
||||
// aAdjustForBoxSizing is true)
|
||||
// - guarantees that the computed height/width will be non-negative
|
||||
// If the value goes negative (because the padding or border is greater than
|
||||
// the width/height and it is removed due to box sizing) then it is driven to 0
|
||||
void AdjustComputedHeight(PRBool aAdjustForBoxSizing);
|
||||
void AdjustComputedWidth(PRBool aAdjustForBoxSizing);
|
||||
|
||||
#ifdef IBMBIDI
|
||||
/**
|
||||
* Test whether the frame is a form control in a visual Bidi page.
|
||||
|
@ -100,10 +100,10 @@ struct nsMargin;
|
||||
typedef class nsIFrame nsIBox;
|
||||
|
||||
// IID for the nsIFrame interface
|
||||
// {0a099557-d85a-4bb1-8932-65717f245564}
|
||||
// a72e0b78-db39-401a-bafd-85daa7c0504a
|
||||
#define NS_IFRAME_IID \
|
||||
{ 0x0a099557, 0xd85a, 0x4bb1, \
|
||||
{ 0x89, 0x32, 0x65, 0x71, 0x7f, 0x24, 0x55, 0x64 } }
|
||||
{ 0xa72e0b78, 0xdb39, 0x401a, \
|
||||
{ 0xba, 0xfd, 0x85, 0xda, 0xa7, 0xc0, 0x50, 0x4a } }
|
||||
|
||||
/**
|
||||
* Indication of how the frame can be split. This is used when doing runaround
|
||||
@ -130,6 +130,8 @@ typedef PRUint32 nsSplittableType;
|
||||
#define NS_FRAME_IS_NOT_SPLITTABLE(type)\
|
||||
(0 == ((type) & NS_FRAME_SPLITTABLE))
|
||||
|
||||
#define NS_INTRINSIC_WIDTH_UNKNOWN nscoord_MIN
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
@ -164,9 +166,11 @@ typedef PRUint32 nsFrameState;
|
||||
// destroyed to allow these references to be cleared.
|
||||
#define NS_FRAME_EXTERNAL_REFERENCE 0x00000010
|
||||
|
||||
// If this bit is set, then the frame is a replaced element. For example,
|
||||
// a frame displaying an image
|
||||
#define NS_FRAME_REPLACED_ELEMENT 0x00000020
|
||||
// If this bit is set, this frame or one of its descendants has a
|
||||
// percentage height that depends on an ancestor of this frame.
|
||||
// (Or it did at one point in the past, since we don't necessarily clear
|
||||
// the bit when it's no longer needed; it's an optimization.)
|
||||
#define NS_FRAME_CONTAINS_RELATIVE_HEIGHT 0x00000020
|
||||
|
||||
// If this bit is set, then the frame corresponds to generated content
|
||||
#define NS_FRAME_GENERATED_CONTENT 0x00000040
|
||||
@ -183,13 +187,22 @@ typedef PRUint32 nsFrameState;
|
||||
#define NS_FRAME_SELECTED_CONTENT 0x00000200
|
||||
|
||||
// If this bit is set, then the frame is dirty and needs to be reflowed.
|
||||
// This bit is set when the frame is first created
|
||||
// This bit is set when the frame is first created.
|
||||
// This bit is cleared by DidReflow after the required call to Reflow has
|
||||
// finished.
|
||||
#define NS_FRAME_IS_DIRTY 0x00000400
|
||||
|
||||
// If this bit is set then the frame is unflowable.
|
||||
#define NS_FRAME_IS_UNFLOWABLE 0x00000800
|
||||
|
||||
// If this bit is set, the frame has dirty children.
|
||||
// If this bit is set, either:
|
||||
// 1. the frame has children that have either NS_FRAME_IS_DIRTY or
|
||||
// NS_FRAME_HAS_DIRTY_CHILDREN, or
|
||||
// 2. the frame has had descendants removed.
|
||||
// It means that Reflow needs to be called, but that Reflow will not
|
||||
// do as much work as it would if NS_FRAME_IS_DIRTY were set.
|
||||
// This bit is cleared by DidReflow after the required call to Reflow has
|
||||
// finished.
|
||||
#define NS_FRAME_HAS_DIRTY_CHILDREN 0x00001000
|
||||
|
||||
// If this bit is set, the frame has an associated view
|
||||
@ -970,6 +983,190 @@ public:
|
||||
return NS_CONST_CAST(nsIFrame*, this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Mark any stored intrinsic width information as dirty (requiring
|
||||
* re-calculation). Note that this should generally not be called
|
||||
* directly; nsPresShell::FrameNeedsReflow will call it instead.
|
||||
*/
|
||||
virtual void MarkIntrinsicWidthsDirty() = 0;
|
||||
|
||||
/**
|
||||
* Get the intrinsic minimum width of the frame. This must be less
|
||||
* than or equal to the intrinsic width.
|
||||
*
|
||||
* This is *not* affected by the CSS 'min-width', 'width', and
|
||||
* 'max-width' properties on this frame, but it is affected by the
|
||||
* values of those properties on this frame's descendants. (It may be
|
||||
* called during computation of the values of those properties, so it
|
||||
* cannot depend on any values in the nsStylePosition for this frame.)
|
||||
*
|
||||
* The value returned should **NOT** include the space required for
|
||||
* padding and border.
|
||||
*
|
||||
* Note that many frames will cache the result of this function call
|
||||
* unless MarkIntrinsicWidthsDirty is called.
|
||||
*
|
||||
* It is not acceptable for a frame to mark itself dirty when this
|
||||
* method is called.
|
||||
*/
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext) = 0;
|
||||
|
||||
/**
|
||||
* Get the intrinsic width of the frame. This must be greater than or
|
||||
* equal to the intrinsic minimum width.
|
||||
*
|
||||
* Otherwise, all the comments for |GetMinWidth| above apply.
|
||||
*/
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext) = 0;
|
||||
|
||||
/**
|
||||
* |InlineIntrinsicWidth| represents the intrinsic width information
|
||||
* in inline layout. Code that determines the intrinsic width of a
|
||||
* region of inline layout accumulates the result into this structure.
|
||||
* This pattern is needed because we need to maintain state
|
||||
* information about whitespace (for both collapsing and trimming).
|
||||
*/
|
||||
struct InlineIntrinsicWidthData {
|
||||
InlineIntrinsicWidthData()
|
||||
: prevLines(0)
|
||||
, currentLine(0)
|
||||
, skipWhitespace(PR_TRUE)
|
||||
, trailingWhitespace(0)
|
||||
{}
|
||||
|
||||
// The maximum intrinsic width for all previous lines.
|
||||
nscoord prevLines;
|
||||
|
||||
// The maximum intrinsic width for the current line. At a line
|
||||
// break (mandatory for preferred width; allowed for minimum width),
|
||||
// the caller should call |Break()|.
|
||||
nscoord currentLine;
|
||||
|
||||
// True if initial collapsable whitespace should be skipped. This
|
||||
// should be true at the beginning of a block and when the last text
|
||||
// ended with whitespace.
|
||||
PRBool skipWhitespace;
|
||||
|
||||
// This contains the width of the trimmable whitespace at the end of
|
||||
// |currentLine|; it is zero if there is no such whitespace.
|
||||
nscoord trailingWhitespace;
|
||||
|
||||
// Floats encountered in the lines.
|
||||
nsVoidArray floats; // of nsIFrame*
|
||||
};
|
||||
|
||||
struct InlineMinWidthData : public InlineIntrinsicWidthData {
|
||||
InlineMinWidthData()
|
||||
: trailingTextFrame(nsnull)
|
||||
{}
|
||||
|
||||
void Break(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
// The last text frame processed so far in the current line, when
|
||||
// the last characters in that text frame are relevant for line
|
||||
// break opportunities.
|
||||
nsIFrame *trailingTextFrame;
|
||||
};
|
||||
|
||||
struct InlinePrefWidthData : public InlineIntrinsicWidthData {
|
||||
void Break(nsIRenderingContext *aRenderingContext);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add the intrinsic minimum width of a frame in a way suitable for
|
||||
* use in inline layout to an |InlineIntrinsicWidthData| object that
|
||||
* represents the intrinsic width information of all the previous
|
||||
* frames in the inline layout region.
|
||||
*
|
||||
* All *allowed* breakpoints within the frame determine what counts as
|
||||
* a line for the |InlineIntrinsicWidthData|. This means that
|
||||
* |aData->trailingWhitespace| will always be zero (unlike for
|
||||
* AddInlinePrefWidth).
|
||||
*
|
||||
* All the comments for |GetMinWidth| apply, except that this function
|
||||
* is responsible for adding padding, border, and margin and for
|
||||
* considering the effects of 'width', 'min-width', and 'max-width'.
|
||||
*
|
||||
* This may be called on any frame. For frames that do not
|
||||
* participate in line breaking, the result will simply append the
|
||||
* result of |GetMinWidth| to the current line.
|
||||
*/
|
||||
virtual void
|
||||
AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineMinWidthData *aData) = 0;
|
||||
|
||||
/**
|
||||
* Get the intrinsic width of a frame in a way suitable for
|
||||
* use in inline layout.
|
||||
*
|
||||
* All the comments for |GetInlinePrefWidth| apply, except that this
|
||||
* fills in an |InlineIntrinsicWidthData| structure based on using all
|
||||
* *mandatory* breakpoints within the frame.
|
||||
*/
|
||||
virtual void
|
||||
AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlinePrefWidthData *aData) = 0;
|
||||
|
||||
/**
|
||||
* Return the horizontal components of padding, border, and margin
|
||||
* that contribute to the intrinsic width that applies to the parent.
|
||||
*/
|
||||
struct IntrinsicWidthOffsetData {
|
||||
nscoord hPadding, hBorder, hMargin;
|
||||
float hPctPadding, hPctMargin;
|
||||
|
||||
IntrinsicWidthOffsetData()
|
||||
: hPadding(0), hBorder(0), hMargin(0)
|
||||
, hPctPadding(0.0f), hPctMargin(0.0f)
|
||||
{}
|
||||
};
|
||||
virtual IntrinsicWidthOffsetData IntrinsicWidthOffsets() = 0;
|
||||
|
||||
/**
|
||||
* Compute the size that a frame will occupy. Called while
|
||||
* constructing the nsHTMLReflowState to be used to Reflow the frame,
|
||||
* in order to fill its mComputedWidth and mComputedHeight member
|
||||
* variables.
|
||||
*
|
||||
* The |height| member of the return value may be
|
||||
* NS_UNCONSTRAINEDSIZE, but the |width| member must not be.
|
||||
*
|
||||
* Note that the reason that border and padding need to be passed
|
||||
* separately is so that the 'box-sizing' property can be handled.
|
||||
* Thus aMargin includes absolute positioning offsets as well.
|
||||
*
|
||||
* @param aCBSize The size of the element's containing block. (Well,
|
||||
* the |height| component isn't really.)
|
||||
* @param aAvailableWidth The available width for 'auto' widths.
|
||||
* This is usually the same as aCBSize.width,
|
||||
* but differs in cases such as block
|
||||
* formatting context roots next to floats, or
|
||||
* in some cases of float reflow in quirks
|
||||
* mode.
|
||||
* @param aMargin The sum of the vertical / horizontal margins
|
||||
* ***AND*** absolute positioning offsets (top, right,
|
||||
* bottom, left) of the frame, including actual values
|
||||
* resulting from percentages and from the
|
||||
* "hypothetical box" for absolute positioning, but
|
||||
* not including actual values resulting from 'auto'
|
||||
* margins or ignored 'auto' values in absolute
|
||||
* positioning.
|
||||
* @param aBorder The sum of the vertical / horizontal border widths
|
||||
* of the frame.
|
||||
* @param aPadding The sum of the vertical / horizontal margins of
|
||||
* the frame, including actual values resulting from
|
||||
* percentages.
|
||||
* @param aShrinkWrap Whether the frame is in a context where
|
||||
* non-replaced blocks should shrink-wrap (e.g.,
|
||||
* it's floating, absolutely positioned, or
|
||||
* inline-block).
|
||||
*/
|
||||
virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap) = 0;
|
||||
|
||||
/**
|
||||
* Pre-reflow hook. Before a frame is reflowed this method will be called.
|
||||
* This call will always be invoked at least once before a subsequent Reflow
|
||||
@ -982,23 +1179,29 @@ public:
|
||||
NS_IMETHOD WillReflow(nsPresContext* aPresContext) = 0;
|
||||
|
||||
/**
|
||||
* The frame is given a maximum size and asked for its desired size.
|
||||
* This is the frame's opportunity to reflow its children.
|
||||
* The frame is given an available size and asked for its desired
|
||||
* size. This is the frame's opportunity to reflow its children.
|
||||
*
|
||||
* If the frame has the NS_FRAME_IS_DIRTY bit set then it is
|
||||
* responsible for completely reflowing itself and all of its
|
||||
* descendants.
|
||||
*
|
||||
* Otherwise, if the frame has the NS_FRAME_HAS_DIRTY_CHILDREN bit
|
||||
* set, then it is responsible for reflowing at least those
|
||||
* children that have NS_FRAME_HAS_DIRTY_CHILDREN or NS_FRAME_IS_DIRTY
|
||||
* set.
|
||||
*
|
||||
* If a difference in available size from the previous reflow causes
|
||||
* the frame's size to change, it should reflow descendants as needed.
|
||||
*
|
||||
* @param aReflowMetrics <i>out</i> parameter where you should return the
|
||||
* desired size and ascent/descent info. You should include any
|
||||
* space you want for border/padding in the desired size you return.
|
||||
*
|
||||
* It's okay to return a desired size that exceeds the max
|
||||
* It's okay to return a desired size that exceeds the avail
|
||||
* size if that's the smallest you can be, i.e. it's your
|
||||
* minimum size.
|
||||
*
|
||||
* maxElementSize is an optional parameter for returning your
|
||||
* maximum element size. If may be null in which case you
|
||||
* don't have to compute a maximum element size. The
|
||||
* maximum element size must be less than or equal to your
|
||||
* desired size.
|
||||
*
|
||||
* For an incremental reflow you are responsible for invalidating
|
||||
* any area within your frame that needs repainting (including
|
||||
* borders). If your new desired size is different than your current
|
||||
@ -1008,10 +1211,7 @@ public:
|
||||
* @param aReflowState information about your reflow including the reason
|
||||
* for the reflow and the available space in which to lay out. Each
|
||||
* dimension of the available space can either be constrained or
|
||||
* unconstrained (a value of NS_UNCONSTRAINEDSIZE). If constrained
|
||||
* you should choose a value that's less than or equal to the
|
||||
* constrained size. If unconstrained you can choose as
|
||||
* large a value as you like.
|
||||
* unconstrained (a value of NS_UNCONSTRAINEDSIZE).
|
||||
*
|
||||
* Note that the available space can be negative. In this case you
|
||||
* still must return an accurate desired size. If you're a container
|
||||
@ -1051,14 +1251,12 @@ public:
|
||||
* Helper method used by block reflow to identify runs of text so
|
||||
* that proper word-breaking can be done.
|
||||
*
|
||||
* @param aContinueTextRun A frame should set aContinueTextRun to
|
||||
* @return
|
||||
* PR_TRUE if we can continue a "text run" through the frame. A
|
||||
* text run is text that should be treated contiguously for line
|
||||
* and word breaking.
|
||||
*
|
||||
* @return The return value is irrelevant.
|
||||
*/
|
||||
NS_IMETHOD CanContinueTextRun(PRBool& aContinueTextRun) const = 0;
|
||||
virtual PRBool CanContinueTextRun() const = 0;
|
||||
|
||||
// Justification helper method that is used to remove trailing
|
||||
// whitespace before justification.
|
||||
@ -1165,10 +1363,15 @@ public:
|
||||
* Bit-flags to pass to IsFrameOfType()
|
||||
*/
|
||||
enum {
|
||||
eMathML = 1 << 0,
|
||||
eSVG = 1 << 1,
|
||||
eSVGForeignObject = 1 << 2,
|
||||
eBidiInlineContainer = 1 << 3
|
||||
eMathML = 1 << 0,
|
||||
eSVG = 1 << 1,
|
||||
eSVGForeignObject = 1 << 2,
|
||||
eBidiInlineContainer = 1 << 3,
|
||||
// the frame is for a replaced element, such as an image
|
||||
eReplaced = 1 << 4,
|
||||
// Frame that contains a block but looks like a replaced element
|
||||
// from the outside
|
||||
eReplacedContainsBlock = 1 << 5
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1357,12 +1560,12 @@ public:
|
||||
NS_IMETHOD CheckVisibility(nsPresContext* aContext, PRInt32 aStartIndex, PRInt32 aEndIndex, PRBool aRecurse, PRBool *aFinished, PRBool *_retval)=0;
|
||||
|
||||
/**
|
||||
* Called by a child frame on a parent frame to tell the parent frame that the child needs
|
||||
* to be reflowed. The parent should either propagate the request to its parent frame or
|
||||
* handle the request by generating a eReflowType_ReflowDirtyChildren reflow command.
|
||||
* Called to tell a frame that one of its child frames is dirty (i.e.,
|
||||
* has the NS_FRAME_IS_DIRTY *or* NS_FRAME_HAS_DIRTY_CHILDREN bit
|
||||
* set). This should always set the NS_FRAME_HAS_DIRTY_CHILDREN on
|
||||
* the frame, and may do other work.
|
||||
*/
|
||||
|
||||
NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild) = 0;
|
||||
virtual void ChildIsDirty(nsIFrame* aChild) = 0;
|
||||
|
||||
/**
|
||||
* Called to retrieve this frame's accessible.
|
||||
@ -1583,10 +1786,6 @@ NS_PTR_TO_INT32(frame->GetProperty(nsLayoutAtoms::embeddingLevel))
|
||||
NS_IMETHOD SetBounds(nsBoxLayoutState& aBoxLayoutState, const nsRect& aRect,
|
||||
PRBool aRemoveOverflowArea = PR_FALSE)=0;
|
||||
NS_HIDDEN_(nsresult) Layout(nsBoxLayoutState& aBoxLayoutState);
|
||||
nsresult IsDirty(PRBool& aIsDirty) { aIsDirty = (mState & NS_FRAME_IS_DIRTY) != 0; return NS_OK; }
|
||||
nsresult HasDirtyChildren(PRBool& aIsDirty) { aIsDirty = (mState & NS_FRAME_HAS_DIRTY_CHILDREN) != 0; return NS_OK; }
|
||||
NS_IMETHOD MarkDirty(nsBoxLayoutState& aState)=0;
|
||||
NS_HIDDEN_(nsresult) MarkDirtyChildren(nsBoxLayoutState& aState);
|
||||
nsresult GetChildBox(nsIBox** aBox)
|
||||
{
|
||||
// box layout ends at box-wrapped frames, so don't allow these frames
|
||||
@ -1627,12 +1826,8 @@ NS_PTR_TO_INT32(frame->GetProperty(nsLayoutAtoms::embeddingLevel))
|
||||
{ aIsNormal = IsNormalDirection(); return NS_OK; }
|
||||
|
||||
NS_HIDDEN_(nsresult) Redraw(nsBoxLayoutState& aState, const nsRect* aRect = nsnull, PRBool aImmediate = PR_FALSE);
|
||||
NS_IMETHOD NeedsRecalc()=0;
|
||||
NS_IMETHOD RelayoutDirtyChild(nsBoxLayoutState& aState, nsIBox* aChild)=0;
|
||||
NS_IMETHOD RelayoutChildAtOrdinal(nsBoxLayoutState& aState, nsIBox* aChild)=0;
|
||||
NS_IMETHOD GetMouseThrough(PRBool& aMouseThrough)=0;
|
||||
NS_IMETHOD MarkChildrenStyleChange()=0;
|
||||
NS_IMETHOD MarkStyleChange(nsBoxLayoutState& aState)=0;
|
||||
NS_IMETHOD SetIncludeOverflow(PRBool aInclude) = 0;
|
||||
NS_IMETHOD GetOverflow(nsSize& aOverflow) = 0;
|
||||
|
||||
|
@ -535,8 +535,9 @@ nsImageFrame::OnStartContainer(imgIRequest *aRequest, imgIContainer *aImage)
|
||||
NS_ASSERTION(mParent, "No parent to pass the reflow request up to.");
|
||||
NS_ASSERTION(presShell, "No PresShell.");
|
||||
if (mParent && presShell) {
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
mParent->ReflowDirtyChild(presShell, NS_STATIC_CAST(nsIFrame*, this));
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
presShell->FrameNeedsReflow(NS_STATIC_CAST(nsIFrame*, this),
|
||||
nsIPresShell::eStyleChange);
|
||||
}
|
||||
}
|
||||
|
||||
@ -638,8 +639,9 @@ nsImageFrame::OnStopDecode(imgIRequest *aRequest,
|
||||
if (!(mState & IMAGE_SIZECONSTRAINED) && intrinsicSizeChanged) {
|
||||
NS_ASSERTION(mParent, "No parent to pass the reflow request up to.");
|
||||
if (mParent && presShell) {
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
mParent->ReflowDirtyChild(presShell, NS_STATIC_CAST(nsIFrame*, this));
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
presShell->FrameNeedsReflow(NS_STATIC_CAST(nsIFrame*, this),
|
||||
nsIPresShell::eStyleChange);
|
||||
}
|
||||
} else {
|
||||
nsSize s = GetSize();
|
||||
@ -674,18 +676,8 @@ nsImageFrame::FrameChanged(imgIContainer *aContainer,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
#define MINMAX(_value,_min,_max) \
|
||||
((_value) < (_min) \
|
||||
? (_min) \
|
||||
: ((_value) > (_max) \
|
||||
? (_max) \
|
||||
: (_value)))
|
||||
|
||||
void
|
||||
nsImageFrame::GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize)
|
||||
nsImageFrame::EnsureIntrinsicSize(nsPresContext* aPresContext)
|
||||
{
|
||||
// if mIntrinsicSize.width and height are 0, then we should
|
||||
// check to see if the size is already known by the image container.
|
||||
@ -720,154 +712,29 @@ nsImageFrame::GetDesiredSize(nsPresContext* aPresContext,
|
||||
RecalculateTransform(nsnull);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle intrinsic sizes and their interaction with
|
||||
// {min-,max-,}{width,height} according to the rules in
|
||||
// http://www.w3.org/TR/CSS21/visudet.html#min-max-widths
|
||||
|
||||
// Note: throughout the following section of the function, I avoid
|
||||
// a * (b / c) because of its reduced accuracy relative to a * b / c
|
||||
// or (a * b) / c (which are equivalent).
|
||||
/* virtual */ nsSize
|
||||
nsImageFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap)
|
||||
{
|
||||
nsPresContext *presContext = GetPresContext();
|
||||
EnsureIntrinsicSize(presContext);
|
||||
|
||||
// convert from normal twips to scaled twips (printing...)
|
||||
float t2st = aPresContext->TwipsToPixels() *
|
||||
aPresContext->ScaledPixelsToTwips(); // twips to scaled twips
|
||||
float t2st = presContext->TwipsToPixels() *
|
||||
presContext->ScaledPixelsToTwips(); // twips to scaled twips
|
||||
nscoord intrinsicWidth =
|
||||
NSToCoordRound(float(mIntrinsicSize.width) * t2st);
|
||||
nscoord intrinsicHeight =
|
||||
NSToCoordRound(float(mIntrinsicSize.height) * t2st);
|
||||
|
||||
// Determine whether the image has fixed content width
|
||||
nscoord width = aReflowState.mComputedWidth;
|
||||
nscoord minWidth = aReflowState.mComputedMinWidth;
|
||||
nscoord maxWidth = aReflowState.mComputedMaxWidth;
|
||||
|
||||
// Determine whether the image has fixed content height
|
||||
nscoord height = aReflowState.mComputedHeight;
|
||||
nscoord minHeight = aReflowState.mComputedMinHeight;
|
||||
nscoord maxHeight = aReflowState.mComputedMaxHeight;
|
||||
|
||||
PRBool isAutoWidth = width == NS_INTRINSICSIZE;
|
||||
PRBool isAutoHeight = height == NS_UNCONSTRAINEDSIZE;
|
||||
if (isAutoWidth) {
|
||||
if (isAutoHeight) {
|
||||
|
||||
// 'auto' width, 'auto' height
|
||||
// XXX nsHTMLReflowState should already ensure this
|
||||
if (minWidth > maxWidth)
|
||||
maxWidth = minWidth;
|
||||
if (minHeight > maxHeight)
|
||||
maxHeight = minHeight;
|
||||
|
||||
nscoord heightAtMaxWidth, heightAtMinWidth,
|
||||
widthAtMaxHeight, widthAtMinHeight;
|
||||
if (intrinsicWidth > 0) {
|
||||
heightAtMaxWidth = maxWidth * intrinsicHeight / intrinsicWidth;
|
||||
if (heightAtMaxWidth < minHeight)
|
||||
heightAtMaxWidth = minHeight;
|
||||
heightAtMinWidth = minWidth * intrinsicHeight / intrinsicWidth;
|
||||
if (heightAtMinWidth > maxHeight)
|
||||
heightAtMinWidth = maxHeight;
|
||||
} else {
|
||||
heightAtMaxWidth = intrinsicHeight;
|
||||
heightAtMinWidth = intrinsicHeight;
|
||||
}
|
||||
|
||||
if (intrinsicHeight > 0) {
|
||||
widthAtMaxHeight = maxHeight * intrinsicWidth / intrinsicHeight;
|
||||
if (widthAtMaxHeight < minWidth)
|
||||
widthAtMaxHeight = minWidth;
|
||||
widthAtMinHeight = minHeight * intrinsicWidth / intrinsicHeight;
|
||||
if (widthAtMinHeight > maxWidth)
|
||||
widthAtMinHeight = maxWidth;
|
||||
} else {
|
||||
widthAtMaxHeight = intrinsicWidth;
|
||||
widthAtMinHeight = intrinsicWidth;
|
||||
}
|
||||
|
||||
if (intrinsicWidth > maxWidth) {
|
||||
if (intrinsicHeight > maxHeight) {
|
||||
if (maxWidth * intrinsicHeight <= maxHeight * intrinsicWidth) {
|
||||
width = maxWidth;
|
||||
height = heightAtMaxWidth;
|
||||
} else {
|
||||
height = maxHeight;
|
||||
width = widthAtMaxHeight;
|
||||
}
|
||||
} else {
|
||||
width = maxWidth;
|
||||
height = heightAtMaxWidth;
|
||||
}
|
||||
} else if (intrinsicWidth < minWidth) {
|
||||
if (intrinsicHeight < minHeight) {
|
||||
if (minWidth * intrinsicHeight <= minHeight * intrinsicWidth) {
|
||||
height = minHeight;
|
||||
width = widthAtMinHeight;
|
||||
} else {
|
||||
width = minWidth;
|
||||
height = heightAtMinWidth;
|
||||
}
|
||||
} else {
|
||||
width = minWidth;
|
||||
height = heightAtMinWidth;
|
||||
}
|
||||
} else {
|
||||
if (intrinsicHeight > maxHeight) {
|
||||
height = maxHeight;
|
||||
width = widthAtMaxHeight;
|
||||
} else if (intrinsicHeight < minHeight) {
|
||||
height = minHeight;
|
||||
width = widthAtMinHeight;
|
||||
} else {
|
||||
width = intrinsicWidth;
|
||||
height = intrinsicHeight;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// 'auto' width, non-'auto' height
|
||||
// XXX nsHTMLReflowState should already ensure this
|
||||
height = MINMAX(height, minHeight, maxHeight);
|
||||
if (intrinsicHeight != 0) {
|
||||
width = intrinsicWidth * height / intrinsicHeight;
|
||||
} else {
|
||||
width = intrinsicWidth;
|
||||
}
|
||||
width = MINMAX(width, minWidth, maxWidth);
|
||||
|
||||
}
|
||||
} else {
|
||||
if (isAutoHeight) {
|
||||
|
||||
// non-'auto' width, 'auto' height
|
||||
// XXX nsHTMLReflowState should already ensure this
|
||||
width = MINMAX(width, minWidth, maxWidth);
|
||||
if (intrinsicWidth != 0) {
|
||||
height = intrinsicHeight * width / intrinsicWidth;
|
||||
} else {
|
||||
height = intrinsicHeight;
|
||||
}
|
||||
height = MINMAX(height, minHeight, maxHeight);
|
||||
|
||||
} else {
|
||||
|
||||
// non-'auto' width, non-'auto' height
|
||||
// XXX nsHTMLReflowState should already ensure this
|
||||
height = MINMAX(height, minHeight, maxHeight);
|
||||
// XXX nsHTMLReflowState should already ensure this
|
||||
width = MINMAX(width, minWidth, maxWidth);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (mComputedSize.width != width || mComputedSize.height != height) {
|
||||
mComputedSize.SizeTo(width, height);
|
||||
RecalculateTransform(nsnull);
|
||||
}
|
||||
|
||||
aDesiredSize.width = mComputedSize.width;
|
||||
aDesiredSize.height = mComputedSize.height;
|
||||
return nsLayoutUtils::ComputeSizeWithIntrinsicDimensions(
|
||||
aRenderingContext, this,
|
||||
nsSize(intrinsicWidth, intrinsicHeight),
|
||||
aCBSize, aBorder, aPadding);
|
||||
}
|
||||
|
||||
nsRect
|
||||
@ -906,13 +773,45 @@ nsImageFrame::GetContinuationOffset(nscoord* aWidth) const
|
||||
return offset;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsImageFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
// XXX The caller doesn't account for constraints of the height,
|
||||
// min-height, and max-height properties.
|
||||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
nsPresContext *presContext = GetPresContext();
|
||||
EnsureIntrinsicSize(presContext);
|
||||
// convert from normal twips to scaled twips (printing...)
|
||||
float t2st = presContext->TwipsToPixels() *
|
||||
presContext->ScaledPixelsToTwips();
|
||||
result = NSToCoordRound(float(mIntrinsicSize.width) * t2st);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsImageFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
// XXX The caller doesn't account for constraints of the height,
|
||||
// min-height, and max-height properties.
|
||||
nscoord result;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
nsPresContext *presContext = GetPresContext();
|
||||
EnsureIntrinsicSize(presContext);
|
||||
// convert from normal twips to scaled twips (printing...)
|
||||
float t2st = presContext->TwipsToPixels() *
|
||||
presContext->ScaledPixelsToTwips();
|
||||
result = NSToCoordRound(float(mIntrinsicSize.width) * t2st);
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImageFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsImageFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsImageFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("enter nsImageFrame::Reflow: availSize=%d,%d",
|
||||
@ -929,7 +828,9 @@ nsImageFrame::Reflow(nsPresContext* aPresContext,
|
||||
mState &= ~IMAGE_SIZECONSTRAINED;
|
||||
}
|
||||
|
||||
if (aReflowState.reason == eReflowReason_Initial) {
|
||||
// XXXldb These two bits are almost exact opposites (except in the
|
||||
// middle of the initial reflow); remove IMAGE_GOTINITIALREFLOW.
|
||||
if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
|
||||
mState |= IMAGE_GOTINITIALREFLOW;
|
||||
}
|
||||
|
||||
@ -937,8 +838,14 @@ nsImageFrame::Reflow(nsPresContext* aPresContext,
|
||||
// transform it can.
|
||||
mBorderPadding = aReflowState.mComputedBorderPadding;
|
||||
|
||||
// get the desired size of the complete image
|
||||
GetDesiredSize(aPresContext, aReflowState, aMetrics);
|
||||
nsSize newSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
|
||||
if (mComputedSize != newSize) {
|
||||
mComputedSize = newSize;
|
||||
RecalculateTransform(nsnull);
|
||||
}
|
||||
|
||||
aMetrics.width = mComputedSize.width;
|
||||
aMetrics.height = mComputedSize.height;
|
||||
|
||||
// add borders and padding
|
||||
aMetrics.width += mBorderPadding.left + mBorderPadding.right;
|
||||
@ -978,13 +885,6 @@ nsImageFrame::Reflow(nsPresContext* aPresContext,
|
||||
aMetrics.ascent = aMetrics.height;
|
||||
aMetrics.descent = 0;
|
||||
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit());
|
||||
}
|
||||
|
||||
if (aMetrics.mFlags & NS_REFLOW_CALC_MAX_WIDTH) {
|
||||
aMetrics.mMaximumWidth = aMetrics.width;
|
||||
}
|
||||
aMetrics.mOverflowArea.SetRect(0, 0, aMetrics.width, aMetrics.height);
|
||||
FinishAndStoreOverflow(&aMetrics);
|
||||
|
||||
@ -1764,8 +1664,10 @@ nsImageFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
||||
}
|
||||
if (nsHTMLAtoms::alt == aAttribute)
|
||||
{
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
mParent->ReflowDirtyChild(GetPresContext()->PresShell(), (nsIFrame*) this);
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
GetPresContext()->PresShell()->FrameNeedsReflow(
|
||||
NS_STATIC_CAST(nsIFrame*, this),
|
||||
nsIPresShell::eStyleChange);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -1777,6 +1679,12 @@ nsImageFrame::GetType() const
|
||||
return nsLayoutAtoms::imageFrame;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsImageFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHODIMP
|
||||
nsImageFrame::GetFrameName(nsAString& aResult) const
|
||||
|
@ -105,6 +105,8 @@ public:
|
||||
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -127,6 +129,7 @@ public:
|
||||
#endif
|
||||
|
||||
virtual nsIAtom* GetType() const;
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD GetFrameName(nsAString& aResult) const;
|
||||
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
|
||||
@ -167,9 +170,12 @@ protected:
|
||||
|
||||
virtual ~nsImageFrame();
|
||||
|
||||
virtual void GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
void EnsureIntrinsicSize(nsPresContext* aPresContext);
|
||||
|
||||
virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap);
|
||||
|
||||
void TriggerLink(nsPresContext* aPresContext,
|
||||
nsIURI* aURI,
|
||||
|
@ -50,7 +50,6 @@
|
||||
#include "nsAbsoluteContainingBlock.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsCSSAnonBoxes.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsFrameManager.h"
|
||||
#ifdef ACCESSIBILITY
|
||||
@ -211,7 +210,11 @@ nsInlineFrame::AppendFrames(nsIAtom* aListName,
|
||||
#ifdef IBMBIDI
|
||||
if (nsnull == aListName)
|
||||
#endif
|
||||
ReflowDirtyChild(GetPresContext()->PresShell(), nsnull);
|
||||
{
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
GetPresContext()->PresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eTreeChange);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -241,7 +244,9 @@ nsInlineFrame::InsertFrames(nsIAtom* aListName,
|
||||
if (nsnull == aListName)
|
||||
#endif
|
||||
// Ask the parent frame to reflow me.
|
||||
ReflowDirtyChild(GetPresContext()->PresShell(), nsnull);
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
GetPresContext()->PresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eTreeChange);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
@ -296,7 +301,9 @@ nsInlineFrame::RemoveFrame(nsIAtom* aListName,
|
||||
|
||||
if (generateReflowCommand) {
|
||||
// Ask the parent frame to reflow me.
|
||||
ReflowDirtyChild(GetPresContext()->PresShell(), nsnull);
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
GetPresContext()->PresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eTreeChange);
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,13 +331,37 @@ nsInlineFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Reflow methods
|
||||
|
||||
/* virtual */ void
|
||||
nsInlineFrame::AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlineMinWidthData *aData)
|
||||
{
|
||||
DoInlineIntrinsicWidth(aRenderingContext, aData, nsLayoutUtils::MIN_WIDTH);
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsInlineFrame::AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlinePrefWidthData *aData)
|
||||
{
|
||||
DoInlineIntrinsicWidth(aRenderingContext, aData, nsLayoutUtils::PREF_WIDTH);
|
||||
}
|
||||
|
||||
/* virtual */ nsSize
|
||||
nsInlineFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap)
|
||||
{
|
||||
// Inlines and text don't compute size before reflow.
|
||||
return nsSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInlineFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsInlineFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsInlineFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
||||
if (nsnull == aReflowState.mLineLayout) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
@ -349,7 +380,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLContainerFrame::ReparentFrameViewList(aPresContext, prevOverflowFrames,
|
||||
prevInFlow, this);
|
||||
|
||||
if (aReflowState.reason == eReflowReason_Initial) {
|
||||
if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
|
||||
// If it's the initial reflow, then our child list must be empty, so
|
||||
// just set the child list rather than calling InsertFrame(). This avoids
|
||||
// having to get the last child frame in the list.
|
||||
@ -370,7 +401,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
|
||||
|
||||
// It's also possible that we have an overflow list for ourselves
|
||||
#ifdef DEBUG
|
||||
if (aReflowState.reason == eReflowReason_Initial) {
|
||||
if (GetStateBits() & NS_FRAME_FIRST_REFLOW) {
|
||||
// If it's our initial reflow, then we should not have an overflow list.
|
||||
// However, add an assertion in case we get reflowed more than once with
|
||||
// the initial reflow reason
|
||||
@ -378,7 +409,7 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
|
||||
NS_ASSERTION(!overflowFrames, "overflow list is not empty for initial reflow");
|
||||
}
|
||||
#endif
|
||||
if (aReflowState.reason != eReflowReason_Initial) {
|
||||
if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
||||
nsIFrame* overflowFrames = GetOverflowFrames(aPresContext, PR_TRUE);
|
||||
if (overflowFrames) {
|
||||
NS_ASSERTION(mFrames.NotEmpty(), "overflow list w/o frames");
|
||||
@ -429,36 +460,11 @@ nsInlineFrame::Reflow(nsPresContext* aPresContext,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInlineFrame::CanContinueTextRun(PRBool& aContinueTextRun) const
|
||||
/* virtual */ PRBool
|
||||
nsInlineFrame::CanContinueTextRun() const
|
||||
{
|
||||
// We can continue a text run through an inline frame
|
||||
aContinueTextRun = PR_TRUE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsInlineFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild)
|
||||
{
|
||||
// The inline container frame does not handle the reflow
|
||||
// request. It passes it up to its parent container.
|
||||
|
||||
// If you don't already have dirty children,
|
||||
if (!(mState & NS_FRAME_HAS_DIRTY_CHILDREN)) {
|
||||
if (mParent) {
|
||||
// Record that you are dirty and have dirty children
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
mState |= NS_FRAME_HAS_DIRTY_CHILDREN;
|
||||
|
||||
// Pass the reflow request up to the parent
|
||||
mParent->ReflowDirtyChild(aPresShell, this);
|
||||
}
|
||||
else {
|
||||
NS_ERROR("No parent to pass the reflow request up to.");
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -571,8 +577,7 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
||||
// that are empty we force to empty so that things like collapsed
|
||||
// whitespace in an inline element don't affect the line-height.
|
||||
nsSize size;
|
||||
lineLayout->EndSpan(this, size,
|
||||
aMetrics.mComputeMEW ? &aMetrics.mMaxElementWidth : nsnull);
|
||||
lineLayout->EndSpan(this, size);
|
||||
if ((0 == size.height) && (0 == size.width) &&
|
||||
((nsnull != GetPrevInFlow()) || (nsnull != GetNextInFlow()))) {
|
||||
// This is a continuation of a previous inline. Therefore make
|
||||
@ -581,9 +586,6 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
||||
aMetrics.height = 0;
|
||||
aMetrics.ascent = 0;
|
||||
aMetrics.descent = 0;
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.mMaxElementWidth = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Compute final width
|
||||
@ -633,9 +635,6 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
||||
ListTag(stdout);
|
||||
printf(": metrics=%d,%d ascent=%d descent=%d\n",
|
||||
aMetrics.width, aMetrics.height, aMetrics.ascent, aMetrics.descent);
|
||||
if (aMetrics.mComputeMEW) {
|
||||
printf(" maxElementWidth %d\n", aMetrics.mMaxElementWidth);
|
||||
}
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
@ -652,7 +651,7 @@ void MarkPercentAwareFrame(nsPresContext *aPresContext,
|
||||
nsInlineFrame *aInline,
|
||||
nsIFrame *aFrame)
|
||||
{
|
||||
if (aFrame->GetStateBits() & NS_FRAME_REPLACED_ELEMENT)
|
||||
if (aFrame->IsFrameOfType(nsIFrame::eReplaced))
|
||||
{ // aFrame is a replaced element, check it's style
|
||||
if (nsLineLayout::IsPercentageAwareReplacedElement(aPresContext, aFrame)) {
|
||||
SetContainsPercentAwareChild(aInline);
|
||||
@ -1190,20 +1189,13 @@ nsPositionedInlineFrame::Reflow(nsPresContext* aPresContext,
|
||||
nscoord containingBlockHeight =
|
||||
aDesiredSize.height - computedBorder.TopBottom();
|
||||
|
||||
// Do any incremental reflows ... would be nice to merge with
|
||||
// the reflows below but that would be more work, and more risky
|
||||
if (eReflowReason_Incremental == aReflowState.reason) {
|
||||
mAbsoluteContainer.IncrementalReflow(this, aPresContext, aReflowState,
|
||||
containingBlockWidth,
|
||||
containingBlockHeight);
|
||||
}
|
||||
|
||||
// Factor the absolutely positioned child bounds into the overflow area
|
||||
// Don't include this frame's bounds, nor its inline descendants' bounds,
|
||||
// and don't store the overflow property.
|
||||
// That will all be done by nsLineLayout::RelativePositionFrames.
|
||||
rv = mAbsoluteContainer.Reflow(this, aPresContext, aReflowState,
|
||||
containingBlockWidth, containingBlockHeight,
|
||||
PR_TRUE, PR_TRUE, // XXX could be optimized
|
||||
&aDesiredSize.mOverflowArea);
|
||||
}
|
||||
|
||||
|
@ -98,7 +98,6 @@ public:
|
||||
NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
NS_IMETHOD ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild);
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
NS_IMETHODIMP GetAccessible(nsIAccessible** aAccessible);
|
||||
@ -116,12 +115,20 @@ public:
|
||||
virtual PRBool PeekOffsetCharacter(PRBool aForward, PRInt32* aOffset);
|
||||
|
||||
// nsIHTMLReflow overrides
|
||||
virtual void AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineMinWidthData *aData);
|
||||
virtual void AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlinePrefWidthData *aData);
|
||||
virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap);
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
NS_IMETHOD CanContinueTextRun(PRBool& aContinueTextRun) const;
|
||||
virtual PRBool CanContinueTextRun() const;
|
||||
|
||||
// Take all of the frames away from this frame. The caller is
|
||||
// presumed to keep them alive.
|
||||
|
@ -49,13 +49,32 @@ nsLeafFrame::~nsLeafFrame()
|
||||
{
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsLeafFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
|
||||
result = GetIntrinsicWidth();
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsLeafFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
result = GetIntrinsicWidth();
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsLeafFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsLeafFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsLeafFrame");
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("enter nsLeafFrame::Reflow: aMaxSize=%d,%d",
|
||||
aReflowState.availableWidth, aReflowState.availableHeight));
|
||||
@ -65,33 +84,70 @@ nsLeafFrame::Reflow(nsPresContext* aPresContext,
|
||||
// XXX add in code to check for width/height being set via css
|
||||
// and if set use them instead of calling GetDesiredSize.
|
||||
|
||||
NS_ASSERTION(aReflowState.mComputedWidth != NS_UNCONSTRAINEDSIZE,
|
||||
"Shouldn't have unconstrained stuff here");
|
||||
|
||||
GetDesiredSize(aPresContext, aReflowState, aMetrics);
|
||||
nsMargin borderPadding;
|
||||
AddBordersAndPadding(aPresContext, aReflowState, aMetrics, borderPadding);
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit());
|
||||
aMetrics.width = aReflowState.mComputedWidth;
|
||||
if (NS_INTRINSICSIZE != aReflowState.mComputedHeight) {
|
||||
aMetrics.height = aReflowState.mComputedHeight;
|
||||
} else {
|
||||
aMetrics.height = GetIntrinsicHeight();
|
||||
// XXXbz using NS_CSS_MINMAX like this presupposes content-box sizing.
|
||||
aMetrics.height = NS_CSS_MINMAX(aMetrics.height,
|
||||
aReflowState.mComputedMinHeight,
|
||||
aReflowState.mComputedMaxHeight);
|
||||
}
|
||||
|
||||
AddBordersAndPadding(aReflowState, aMetrics);
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
|
||||
("exit nsLeafFrame::Reflow: size=%d,%d",
|
||||
aMetrics.width, aMetrics.height));
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
||||
|
||||
aMetrics.mOverflowArea =
|
||||
nsRect(0, 0, aMetrics.width, aMetrics.height);
|
||||
FinishAndStoreOverflow(&aMetrics);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsLeafFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
// We don't actually contain a block, but we do always want a
|
||||
// computed width, so tell a little white lie here.
|
||||
return !(aFlags & ~nsIFrame::eReplacedContainsBlock);
|
||||
}
|
||||
|
||||
nscoord
|
||||
nsLeafFrame::GetIntrinsicHeight()
|
||||
{
|
||||
NS_NOTREACHED("Someone didn't override Reflow");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXX how should border&padding effect baseline alignment?
|
||||
// => descent = borderPadding.bottom for example
|
||||
void
|
||||
nsLeafFrame::AddBordersAndPadding(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
nsMargin& aBorderPadding)
|
||||
nsLeafFrame::AddBordersAndPadding(const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aMetrics)
|
||||
{
|
||||
aBorderPadding = aReflowState.mComputedBorderPadding;
|
||||
aMetrics.width += aBorderPadding.left + aBorderPadding.right;
|
||||
aMetrics.height += aBorderPadding.top + aBorderPadding.bottom;
|
||||
aMetrics.width += aReflowState.mComputedBorderPadding.LeftRight();
|
||||
aMetrics.height += aReflowState.mComputedBorderPadding.TopBottom();
|
||||
aMetrics.ascent = aMetrics.height;
|
||||
aMetrics.descent = 0;
|
||||
}
|
||||
|
||||
void
|
||||
nsLeafFrame::SizeToAvailSize(const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
aDesiredSize.width = aReflowState.availableWidth; // FRAME
|
||||
aDesiredSize.height = aReflowState.availableHeight;
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
aDesiredSize.mOverflowArea =
|
||||
nsRect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
||||
FinishAndStoreOverflow(&aDesiredSize);
|
||||
}
|
||||
|
@ -59,32 +59,57 @@ public:
|
||||
DO_GLOBAL_REFLOW_COUNT_DSP("nsLeafFrame");
|
||||
return DisplayBorderBackgroundOutline(aBuilder, aLists);
|
||||
}
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
|
||||
/**
|
||||
* Both GetMinWidth and GetPrefWidth will return whatever GetIntrinsicWidth
|
||||
* returns.
|
||||
*/
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
|
||||
/**
|
||||
* Reflow our frame. This will use the computed width plus borderpadding for
|
||||
* the desired width, and use the return value of GetIntrinsicHeight plus
|
||||
* borderpadding for the desired height. Ascent will be set to the height,
|
||||
* and descent will be set to 0.
|
||||
*/
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
protected:
|
||||
nsLeafFrame(nsStyleContext* aContext) : nsFrame(aContext) {}
|
||||
virtual ~nsLeafFrame();
|
||||
|
||||
/**
|
||||
* Return the desired size of the frame's content area. Note that this
|
||||
* method doesn't need to deal with padding or borders (the caller will
|
||||
* deal with it). In addition, the ascent will be set to the height
|
||||
* and the descent will be set to zero.
|
||||
* Return the intrinsic width of the frame's content area. Note that this
|
||||
* should not include borders or padding and should not depend on the applied
|
||||
* styles.
|
||||
*/
|
||||
virtual void GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize) = 0;
|
||||
virtual nscoord GetIntrinsicWidth() = 0;
|
||||
|
||||
/**
|
||||
* Return the intrinsic height of the frame's content area. This should not
|
||||
* include border or padding. This will only be called if there is no
|
||||
* computed height. Note that subclasses must either implement this or
|
||||
* override Reflow; the default Reflow impl calls this method.
|
||||
*/
|
||||
virtual nscoord GetIntrinsicHeight();
|
||||
|
||||
/**
|
||||
* Subroutine to add in borders and padding
|
||||
*/
|
||||
void AddBordersAndPadding(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
nsMargin& aBorderPadding);
|
||||
void AddBordersAndPadding(const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
|
||||
/**
|
||||
* Set aDesiredSize to be the available size
|
||||
*/
|
||||
void SizeToAvailSize(const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
};
|
||||
|
||||
#endif /* nsLeafFrame_h___ */
|
||||
|
@ -59,8 +59,6 @@ PRInt32 nsLineBox::GetCtorCount() { return ctorCount; }
|
||||
nsLineBox::nsLineBox(nsIFrame* aFrame, PRInt32 aCount, PRBool aIsBlock)
|
||||
: mFirstChild(aFrame),
|
||||
mBounds(0, 0, 0, 0),
|
||||
mMaxElementWidth(0),
|
||||
mMaximumWidth(-1),
|
||||
mData(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsLineBox);
|
||||
@ -216,9 +214,6 @@ nsLineBox::List(FILE* out, PRInt32 aIndent) const
|
||||
if (IsBlock() && !GetCarriedOutBottomMargin().IsZero()) {
|
||||
fprintf(out, "bm=%d ", GetCarriedOutBottomMargin().get());
|
||||
}
|
||||
if (0 != mMaxElementWidth) {
|
||||
fprintf(out, "mew=%d ", mMaxElementWidth);
|
||||
}
|
||||
fprintf(out, "{%d,%d,%d,%d} ",
|
||||
mBounds.x, mBounds.y, mBounds.width, mBounds.height);
|
||||
if (mData) {
|
||||
|
@ -85,9 +85,6 @@ public:
|
||||
// the containing block frame.
|
||||
nsRect mCombinedArea;
|
||||
|
||||
// The float's max-element-width.
|
||||
nscoord mMaxElementWidth;
|
||||
|
||||
protected:
|
||||
nsFloatCache* mNext;
|
||||
|
||||
@ -503,9 +500,6 @@ public:
|
||||
nsIFrame* mFirstChild;
|
||||
|
||||
nsRect mBounds;
|
||||
nscoord mMaxElementWidth; // width part of max-element-size
|
||||
nscoord mMaximumWidth; // maximum width (needed for incremental reflow of tables)
|
||||
// includes the left border/padding but not the right
|
||||
|
||||
struct FlagBits {
|
||||
PRUint32 mDirty : 1;
|
||||
|
@ -59,7 +59,6 @@
|
||||
#include "nsIRenderingContext.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsPlaceholderFrame.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIHTMLDocument.h"
|
||||
#include "nsIContent.h"
|
||||
@ -93,66 +92,9 @@
|
||||
#define PLACED_LEFT 0x1
|
||||
#define PLACED_RIGHT 0x2
|
||||
|
||||
#define HACK_MEW
|
||||
//#undef HACK_MEW
|
||||
#ifdef HACK_MEW
|
||||
static nscoord AccumulateImageSizes(nsPresContext& aPresContext, nsIFrame& aFrame)
|
||||
{
|
||||
nscoord sizes = 0;
|
||||
|
||||
// see if aFrame is an image frame first
|
||||
if (aFrame.GetType() == nsLayoutAtoms::imageFrame) {
|
||||
sizes += aFrame.GetSize().width;
|
||||
} else {
|
||||
// see if there are children to process
|
||||
// XXX: process alternate child lists?
|
||||
nsIFrame* child = aFrame.GetFirstChild(nsnull);
|
||||
while (child) {
|
||||
// recurse: note that we already know we are in a child frame, so no need to track further
|
||||
sizes += AccumulateImageSizes(aPresContext, *child);
|
||||
// now next sibling
|
||||
child = child->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
return sizes;
|
||||
}
|
||||
|
||||
static PRBool InUnconstrainedTableCell(const nsHTMLReflowState& aBlockReflowState)
|
||||
{
|
||||
PRBool result = PR_FALSE;
|
||||
|
||||
// get the parent reflow state
|
||||
const nsHTMLReflowState* parentReflowState = aBlockReflowState.parentReflowState;
|
||||
if (parentReflowState) {
|
||||
// check if the frame is a tablecell
|
||||
NS_ASSERTION(parentReflowState->mStyleDisplay, "null styleDisplay in parentReflowState unexpected");
|
||||
if (parentReflowState->mStyleDisplay &&
|
||||
parentReflowState->mStyleDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_CELL) {
|
||||
// see if width is unconstrained or percent
|
||||
NS_ASSERTION(parentReflowState->mStylePosition, "null stylePosition in parentReflowState unexpected");
|
||||
if(parentReflowState->mStylePosition) {
|
||||
switch(parentReflowState->mStylePosition->mWidth.GetUnit()) {
|
||||
case eStyleUnit_Auto :
|
||||
case eStyleUnit_Null :
|
||||
result = PR_TRUE;
|
||||
break;
|
||||
default:
|
||||
result = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
nsLineLayout::nsLineLayout(nsPresContext* aPresContext,
|
||||
nsSpaceManager* aSpaceManager,
|
||||
const nsHTMLReflowState* aOuterReflowState,
|
||||
PRBool aComputeMaxElementWidth)
|
||||
const nsHTMLReflowState* aOuterReflowState)
|
||||
: mPresContext(aPresContext),
|
||||
mSpaceManager(aSpaceManager),
|
||||
mBlockReflowState(aOuterReflowState),
|
||||
@ -163,9 +105,11 @@ nsLineLayout::nsLineLayout(nsPresContext* aPresContext,
|
||||
mTrailingTextFrame(nsnull),
|
||||
mBlockRS(nsnull),/* XXX temporary */
|
||||
mMinLineHeight(0),
|
||||
mComputeMaxElementWidth(aComputeMaxElementWidth),
|
||||
mTextIndent(0)
|
||||
{
|
||||
NS_ASSERTION(aSpaceManager || aOuterReflowState->frame->GetType() ==
|
||||
nsLayoutAtoms::letterFrame,
|
||||
"space manager should be present");
|
||||
MOZ_COUNT_CTOR(nsLineLayout);
|
||||
|
||||
// Stash away some style data that we need
|
||||
@ -283,15 +227,7 @@ nsLineLayout::BeginLineReflow(nscoord aX, nscoord aY,
|
||||
|
||||
mTopEdge = aY;
|
||||
|
||||
switch (mStyleText->mWhiteSpace) {
|
||||
case NS_STYLE_WHITESPACE_PRE:
|
||||
case NS_STYLE_WHITESPACE_NOWRAP:
|
||||
psd->mNoWrap = PR_TRUE;
|
||||
break;
|
||||
default:
|
||||
psd->mNoWrap = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
psd->mNoWrap = !mStyleText->WhiteSpaceCanWrap();
|
||||
psd->mDirection = mBlockReflowState->mStyleVisibility->mDirection;
|
||||
psd->mChangedFrameDirection = PR_FALSE;
|
||||
|
||||
@ -513,16 +449,8 @@ nsLineLayout::BeginSpan(nsIFrame* aFrame,
|
||||
psd->mX = aLeftEdge;
|
||||
psd->mRightEdge = aRightEdge;
|
||||
|
||||
const nsStyleText* styleText = aSpanReflowState->frame->GetStyleText();
|
||||
switch (styleText->mWhiteSpace) {
|
||||
case NS_STYLE_WHITESPACE_PRE:
|
||||
case NS_STYLE_WHITESPACE_NOWRAP:
|
||||
psd->mNoWrap = PR_TRUE;
|
||||
break;
|
||||
default:
|
||||
psd->mNoWrap = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
psd->mNoWrap =
|
||||
!aSpanReflowState->frame->GetStyleText()->WhiteSpaceCanWrap();
|
||||
psd->mDirection = aSpanReflowState->mStyleVisibility->mDirection;
|
||||
psd->mChangedFrameDirection = PR_FALSE;
|
||||
|
||||
@ -534,9 +462,7 @@ nsLineLayout::BeginSpan(nsIFrame* aFrame,
|
||||
}
|
||||
|
||||
void
|
||||
nsLineLayout::EndSpan(nsIFrame* aFrame,
|
||||
nsSize& aSizeResult,
|
||||
nscoord* aMaxElementWidth)
|
||||
nsLineLayout::EndSpan(nsIFrame* aFrame, nsSize& aSizeResult)
|
||||
{
|
||||
NS_ASSERTION(mSpanDepth > 0, "end-span without begin-span");
|
||||
#ifdef NOISY_REFLOW
|
||||
@ -547,7 +473,6 @@ nsLineLayout::EndSpan(nsIFrame* aFrame,
|
||||
PerSpanData* psd = mCurrentSpan;
|
||||
nscoord width = 0;
|
||||
nscoord maxHeight = 0;
|
||||
nscoord maxElementWidth = 0;
|
||||
if (nsnull != psd->mLastFrame) {
|
||||
width = psd->mX - psd->mLeftEdge;
|
||||
PerFrameData* pfd = psd->mFirstFrame;
|
||||
@ -565,39 +490,12 @@ nsLineLayout::EndSpan(nsIFrame* aFrame,
|
||||
if (pfd->mBounds.height > maxHeight) maxHeight = pfd->mBounds.height;
|
||||
|
||||
// Compute max-element-width if necessary
|
||||
if (aMaxElementWidth) {
|
||||
nscoord mw = pfd->mMaxElementWidth;
|
||||
// add only fixed margins to the MEW
|
||||
if (pfd->mMargin.left) {
|
||||
if (pfd->mFrame->GetStyleMargin()->mMargin.GetLeftUnit() ==
|
||||
eStyleUnit_Coord)
|
||||
mw += pfd->mMargin.left;
|
||||
}
|
||||
if (pfd->mMargin.right) {
|
||||
if (pfd->mFrame->GetStyleMargin()->mMargin.GetRightUnit() ==
|
||||
eStyleUnit_Coord)
|
||||
mw += pfd->mMargin.right;
|
||||
}
|
||||
if (maxElementWidth < mw) {
|
||||
maxElementWidth = mw;
|
||||
}
|
||||
}
|
||||
}
|
||||
pfd = pfd->mNext;
|
||||
}
|
||||
}
|
||||
aSizeResult.width = width;
|
||||
aSizeResult.height = maxHeight;
|
||||
if (aMaxElementWidth) {
|
||||
if (psd->mNoWrap) {
|
||||
// When we have a non-breakable span, its max-element-width
|
||||
// width is its entire width.
|
||||
*aMaxElementWidth = width;
|
||||
}
|
||||
else {
|
||||
*aMaxElementWidth = maxElementWidth;
|
||||
}
|
||||
}
|
||||
|
||||
mSpanDepth--;
|
||||
mCurrentSpan->mReflowState = nsnull; // no longer valid so null it out!
|
||||
@ -830,69 +728,9 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||
// columns, but it's not clear how to handle that anyway
|
||||
availSize.height = NS_UNCONSTRAINEDSIZE;
|
||||
|
||||
// Get reflow reason set correctly. It's possible that a child was
|
||||
// created and then it was decided that it could not be reflowed
|
||||
// (for example, a block frame that isn't at the start of a
|
||||
// line). In this case the reason will be wrong so we need to check
|
||||
// the frame state.
|
||||
const nsHTMLReflowState* rs = psd->mReflowState;
|
||||
nsReflowReason reason = eReflowReason_Resize;
|
||||
if (NS_FRAME_FIRST_REFLOW & aFrame->GetStateBits()) {
|
||||
reason = eReflowReason_Initial;
|
||||
}
|
||||
else if (rs->reason == eReflowReason_Initial &&
|
||||
mBlockReflowState->reason == eReflowReason_StyleChange) {
|
||||
// The frame we're about to reflow is an _old_ frame that was
|
||||
// pushed inside a _new_ parent (overflow).
|
||||
|
||||
// So we propagate the same 'style change' that led to creating
|
||||
// the new overflow parent to which this frame is now the child
|
||||
reason = eReflowReason_StyleChange;
|
||||
}
|
||||
else if (rs->reason == eReflowReason_Incremental) { // XXX
|
||||
// XXXwaterson (above) previously used mBlockReflowState rather
|
||||
// than psd->mReflowState.
|
||||
|
||||
// If the frame we're about to reflow is on the reflow path, then
|
||||
// propagate the reflow as `incremental' so it unwinds correctly
|
||||
// to the target frames below us.
|
||||
PRBool frameIsOnReflowPath = rs->path->HasChild(aFrame);
|
||||
if (frameIsOnReflowPath)
|
||||
reason = eReflowReason_Incremental;
|
||||
|
||||
// But...if the incremental reflow command is a StyleChanged
|
||||
// reflow and its target is the current span, change the reason
|
||||
// to `style change', so that it propagates through the entire
|
||||
// subtree.
|
||||
nsHTMLReflowCommand* rc = rs->path->mReflowCommand;
|
||||
if (rc) {
|
||||
nsReflowType type = rc->Type();
|
||||
if (type == eReflowType_StyleChanged) {
|
||||
nsIFrame* parentFrame = psd->mFrame
|
||||
? psd->mFrame->mFrame
|
||||
: mBlockReflowState->frame;
|
||||
if (rc->GetTarget() == parentFrame) {
|
||||
reason = eReflowReason_StyleChange;
|
||||
}
|
||||
}
|
||||
else if (type == eReflowType_ReflowDirty &&
|
||||
(aFrame->GetStateBits() & NS_FRAME_IS_DIRTY) &&
|
||||
!frameIsOnReflowPath) {
|
||||
reason = eReflowReason_Dirty;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (rs->reason == eReflowReason_StyleChange) {
|
||||
reason = eReflowReason_StyleChange;
|
||||
}
|
||||
else if (rs->reason == eReflowReason_Dirty) {
|
||||
if (aFrame->GetStateBits() & NS_FRAME_IS_DIRTY)
|
||||
reason = eReflowReason_Dirty;
|
||||
}
|
||||
|
||||
// Setup reflow state for reflowing the frame
|
||||
nsHTMLReflowState reflowState(mPresContext, *psd->mReflowState,
|
||||
aFrame, availSize, reason);
|
||||
aFrame, availSize);
|
||||
reflowState.mLineLayout = this;
|
||||
reflowState.mFlags.mIsTopOfPage = GetFlag(LL_ISTOPOFPAGE);
|
||||
SetFlag(LL_UNDERSTANDSNWHITESPACE, PR_FALSE);
|
||||
@ -949,15 +787,12 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||
// parents border/padding is <b>inside</b> the parent
|
||||
// frame. Therefore we have to subtract out the parents
|
||||
// border+padding before translating.
|
||||
nsHTMLReflowMetrics metrics(mComputeMaxElementWidth);
|
||||
nsHTMLReflowMetrics metrics;
|
||||
#ifdef DEBUG
|
||||
metrics.width = nscoord(0xdeadbeef);
|
||||
metrics.height = nscoord(0xdeadbeef);
|
||||
metrics.ascent = nscoord(0xdeadbeef);
|
||||
metrics.descent = nscoord(0xdeadbeef);
|
||||
if (mComputeMaxElementWidth) {
|
||||
metrics.mMaxElementWidth = nscoord(0xdeadbeef);
|
||||
}
|
||||
#endif
|
||||
nscoord tx = x - psd->mReflowState->mComputedBorderPadding.left;
|
||||
nscoord ty = y - psd->mReflowState->mComputedBorderPadding.top;
|
||||
@ -997,7 +832,10 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||
nsIFrame* outOfFlowFrame = nsLayoutUtils::GetFloatFromPlaceholder(aFrame);
|
||||
if (outOfFlowFrame) {
|
||||
nsPlaceholderFrame* placeholder = NS_STATIC_CAST(nsPlaceholderFrame*, aFrame);
|
||||
if (eReflowReason_Incremental == reason) {
|
||||
// XXXldb What is this test supposed to be?
|
||||
if (!(aFrame->GetStateBits() &
|
||||
(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
|
||||
// incremental reflow of child
|
||||
placedFloat = InitFloat(placeholder, aReflowStatus);
|
||||
}
|
||||
else {
|
||||
@ -1067,24 +905,6 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||
nsFrame::ListTag(stdout, aFrame);
|
||||
printf(" metrics=%d,%d!\n", metrics.width, metrics.height);
|
||||
}
|
||||
if (mComputeMaxElementWidth &&
|
||||
(nscoord(0xdeadbeef) == metrics.mMaxElementWidth)) {
|
||||
printf("nsLineLayout: ");
|
||||
nsFrame::ListTag(stdout, aFrame);
|
||||
printf(" didn't set max-element-width!\n");
|
||||
}
|
||||
#ifdef REALLY_NOISY_MAX_ELEMENT_SIZE
|
||||
// Note: there are common reflow situations where this *correctly*
|
||||
// occurs; so only enable this debug noise when you really need to
|
||||
// analyze in detail.
|
||||
if (mComputeMaxElementWidth &&
|
||||
(metrics.mMaxElementWidth > metrics.width)) {
|
||||
printf("nsLineLayout: ");
|
||||
nsFrame::ListTag(stdout, aFrame);
|
||||
printf(": WARNING: maxElementWidth=%d > metrics=%d\n",
|
||||
metrics.mMaxElementWidth, metrics.width);
|
||||
}
|
||||
#endif
|
||||
if ((metrics.width == nscoord(0xdeadbeef)) ||
|
||||
(metrics.height == nscoord(0xdeadbeef)) ||
|
||||
(metrics.ascent == nscoord(0xdeadbeef)) ||
|
||||
@ -1096,20 +916,6 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyMaxElementWidth) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
if (!NS_INLINE_IS_BREAK_BEFORE(aReflowStatus)) {
|
||||
if (mComputeMaxElementWidth) {
|
||||
printf(" ");
|
||||
nsFrame::ListTag(stdout, aFrame);
|
||||
printf(": maxElementWidth=%d wh=%d,%d,\n",
|
||||
metrics.mMaxElementWidth,
|
||||
metrics.width, metrics.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unlike with non-inline reflow, the overflow area here does *not*
|
||||
// include the accumulation of the frame's bounds and its inline
|
||||
@ -1120,9 +926,6 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||
|
||||
pfd->mBounds.width = metrics.width;
|
||||
pfd->mBounds.height = metrics.height;
|
||||
if (mComputeMaxElementWidth) {
|
||||
pfd->mMaxElementWidth = metrics.mMaxElementWidth;
|
||||
}
|
||||
|
||||
// Size the frame, but |RelativePositionFrames| will size the view.
|
||||
aFrame->SetSize(nsSize(metrics.width, metrics.height));
|
||||
@ -1153,8 +956,7 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame,
|
||||
|
||||
// Check whether this frame breaks up text runs. All frames break up text
|
||||
// runs (hence return false here) except for text frames and inline containers.
|
||||
PRBool continuingTextRun;
|
||||
aFrame->CanContinueTextRun(continuingTextRun);
|
||||
PRBool continuingTextRun = aFrame->CanContinueTextRun();
|
||||
|
||||
// See if we can place the frame. If we can't fit it, then we
|
||||
// return now.
|
||||
@ -1484,7 +1286,7 @@ nsLineLayout::AddBulletFrame(nsIFrame* aFrame,
|
||||
pfd->mFrame = aFrame;
|
||||
pfd->mMargin.SizeTo(0, 0, 0, 0);
|
||||
pfd->mBorderPadding.SizeTo(0, 0, 0, 0);
|
||||
pfd->mFrameType = NS_CSS_FRAME_TYPE_INLINE|NS_FRAME_REPLACED_ELEMENT;
|
||||
pfd->mFrameType = NS_FRAME_REPLACED(NS_CSS_FRAME_TYPE_INLINE);
|
||||
pfd->mFlags = 0; // all flags default to false
|
||||
pfd->SetFlag(PFD_ISBULLET, PR_TRUE);
|
||||
pfd->mAscent = aMetrics.ascent;
|
||||
@ -1493,9 +1295,6 @@ nsLineLayout::AddBulletFrame(nsIFrame* aFrame,
|
||||
// Note: y value will be updated during vertical alignment
|
||||
pfd->mBounds = aFrame->GetRect();
|
||||
pfd->mCombinedArea = aMetrics.mOverflowArea;
|
||||
if (mComputeMaxElementWidth) {
|
||||
pfd->mMaxElementWidth = aMetrics.width;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@ -1538,7 +1337,7 @@ PRBool
|
||||
nsLineLayout::IsPercentageAwareReplacedElement(nsPresContext *aPresContext,
|
||||
nsIFrame* aFrame)
|
||||
{
|
||||
if (aFrame->GetStateBits() & NS_FRAME_REPLACED_ELEMENT)
|
||||
if (aFrame->IsFrameOfType(nsIFrame::eReplaced))
|
||||
{
|
||||
nsIAtom* frameType = aFrame->GetType();
|
||||
if (nsLayoutAtoms::brFrame != frameType &&
|
||||
@ -1574,7 +1373,7 @@ nsLineLayout::IsPercentageAwareReplacedElement(nsPresContext *aPresContext,
|
||||
|
||||
PRBool IsPercentageAwareFrame(nsPresContext *aPresContext, nsIFrame *aFrame)
|
||||
{
|
||||
if (aFrame->GetStateBits() & NS_FRAME_REPLACED_ELEMENT) {
|
||||
if (aFrame->IsFrameOfType(nsIFrame::eReplaced)) {
|
||||
if (nsLineLayout::IsPercentageAwareReplacedElement(aPresContext, aFrame)) {
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -1595,8 +1394,7 @@ PRBool IsPercentageAwareFrame(nsPresContext *aPresContext, nsIFrame *aFrame)
|
||||
|
||||
|
||||
void
|
||||
nsLineLayout::VerticalAlignLine(nsLineBox* aLineBox,
|
||||
nscoord* aMaxElementWidthResult)
|
||||
nsLineLayout::VerticalAlignLine(nsLineBox* aLineBox)
|
||||
{
|
||||
// Synthesize a PerFrameData for the block frame
|
||||
PerFrameData rootPFD;
|
||||
@ -1667,95 +1465,7 @@ nsLineLayout::VerticalAlignLine(nsLineBox* aLineBox,
|
||||
// frames we find.
|
||||
// XXX PERFORMANCE: set a bit per-span to avoid the extra work
|
||||
// (propagate it upward too)
|
||||
PerFrameData* pfd = psd->mFirstFrame;
|
||||
nscoord maxElementWidth = 0;
|
||||
PRBool prevFrameAccumulates = PR_FALSE;
|
||||
nscoord accumulatedWidth = 0;
|
||||
#ifdef HACK_MEW
|
||||
PRBool strictMode = InStrictMode();
|
||||
PRBool inUnconstrainedTable = InUnconstrainedTableCell(*mBlockReflowState);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
int frameCount = 0;
|
||||
#endif
|
||||
|
||||
nscoord indent = mTextIndent; // Used for the first frame.
|
||||
|
||||
while (nsnull != pfd) {
|
||||
|
||||
// Compute max-element-width if necessary
|
||||
if (mComputeMaxElementWidth) {
|
||||
|
||||
nscoord mw = pfd->mMaxElementWidth + indent;
|
||||
// add only fixed margins to the MEW
|
||||
if (pfd->mMargin.left) {
|
||||
if (pfd->mFrame->GetStyleMargin()->mMargin.GetLeftUnit() ==
|
||||
eStyleUnit_Coord)
|
||||
mw += pfd->mMargin.left;
|
||||
}
|
||||
if (pfd->mMargin.right) {
|
||||
if (pfd->mFrame->GetStyleMargin()->mMargin.GetRightUnit() ==
|
||||
eStyleUnit_Coord)
|
||||
mw += pfd->mMargin.right;
|
||||
}
|
||||
|
||||
// Zero |indent| after including the 'text-indent' only for the
|
||||
// frame that is indented.
|
||||
indent = 0;
|
||||
|
||||
if (psd->mNoWrap) {
|
||||
maxElementWidth += mw;
|
||||
}
|
||||
else {
|
||||
|
||||
#ifdef HACK_MEW
|
||||
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyMaxElementWidth)
|
||||
frameCount++;
|
||||
#endif
|
||||
// if in Quirks mode and in a table cell with an unconstrained width, then emulate an IE
|
||||
// quirk to keep consecutive images from breaking the line
|
||||
// - see bugs 54565, 32191, and their many dups
|
||||
// XXX - reconsider how textFrame text measurement happens and have it take into account
|
||||
// image frames as well, thus eliminating the need for this code
|
||||
if (!strictMode && inUnconstrainedTable ) {
|
||||
|
||||
nscoord imgSizes = AccumulateImageSizes(*mPresContext, *pfd->mFrame);
|
||||
PRBool curFrameAccumulates = (imgSizes > 0) ||
|
||||
(pfd->mMaxElementWidth == pfd->mBounds.width &&
|
||||
pfd->GetFlag(PFD_ISNONWHITESPACETEXTFRAME));
|
||||
// NOTE: we check for the maxElementWidth == the boundsWidth to detect when
|
||||
// a textframe has whitespace in it and thus should not be used as the basis
|
||||
// for accumulating the image width
|
||||
// - this is to handle images in a text run
|
||||
|
||||
if(prevFrameAccumulates && curFrameAccumulates) {
|
||||
accumulatedWidth += mw;
|
||||
} else {
|
||||
accumulatedWidth = mw;
|
||||
}
|
||||
// now update the prevFrame
|
||||
prevFrameAccumulates = curFrameAccumulates;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (nsBlockFrame::gNoisyMaxElementWidth) {
|
||||
nsFrame::IndentBy(stdout, nsBlockFrame::gNoiseIndent);
|
||||
printf("(%d) last frame's MEW=%d | Accumulated MEW=%d\n", frameCount, mw, accumulatedWidth);
|
||||
}
|
||||
#endif
|
||||
|
||||
mw = accumulatedWidth;
|
||||
}
|
||||
|
||||
#endif // HACK_MEW
|
||||
|
||||
// and finally reset the max element width
|
||||
if (maxElementWidth < mw) {
|
||||
maxElementWidth = mw;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (PerFrameData* pfd = psd->mFirstFrame; pfd; pfd = pfd->mNext) {
|
||||
PerSpanData* span = pfd->mSpan;
|
||||
#ifdef DEBUG
|
||||
NS_ASSERTION(0xFF != pfd->mVerticalAlign, "umr");
|
||||
@ -1804,7 +1514,6 @@ nsLineLayout::VerticalAlignLine(nsLineBox* aLineBox,
|
||||
if (IsPercentageAwareFrame(mPresContext, pfd->mFrame))
|
||||
aLineBox->DisableResizeReflowOptimization();
|
||||
}
|
||||
pfd = pfd->mNext;
|
||||
}
|
||||
|
||||
// Fill in returned line-box and max-element-width data
|
||||
@ -1813,15 +1522,13 @@ nsLineLayout::VerticalAlignLine(nsLineBox* aLineBox,
|
||||
aLineBox->mBounds.width = psd->mX - psd->mLeftEdge;
|
||||
aLineBox->mBounds.height = lineHeight;
|
||||
mFinalLineHeight = lineHeight;
|
||||
*aMaxElementWidthResult = maxElementWidth;
|
||||
aLineBox->SetAscent(baselineY - mTopEdge);
|
||||
#ifdef NOISY_VERTICAL_ALIGN
|
||||
printf(
|
||||
" [line]==> bounds{x,y,w,h}={%d,%d,%d,%d} lh=%d a=%d mew=%d\n",
|
||||
" [line]==> bounds{x,y,w,h}={%d,%d,%d,%d} lh=%d a=%d\n",
|
||||
aLineBox->mBounds.x, aLineBox->mBounds.y,
|
||||
aLineBox->mBounds.width, aLineBox->mBounds.height,
|
||||
mFinalLineHeight, aLineBox->GetAscent(),
|
||||
*aMaxElementWidthResult);
|
||||
mFinalLineHeight, aLineBox->GetAscent());
|
||||
#endif
|
||||
|
||||
// Undo root-span mFrame pointer to prevent brane damage later on...
|
||||
@ -2639,9 +2346,6 @@ nsLineLayout::TrimTrailingWhiteSpaceIn(PerSpanData* psd,
|
||||
|
||||
if (deltaWidth) {
|
||||
pfd->mBounds.width -= deltaWidth;
|
||||
if (0 == pfd->mBounds.width) {
|
||||
pfd->mMaxElementWidth = 0;
|
||||
}
|
||||
|
||||
// See if the text frame has already been placed in its parent
|
||||
if (psd != mRootSpan) {
|
||||
@ -2780,20 +2484,20 @@ nsLineLayout::ApplyFrameJustification(PerSpanData* aPSD, FrameJustificationState
|
||||
return deltaX;
|
||||
}
|
||||
|
||||
PRBool
|
||||
void
|
||||
nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
||||
PRBool aAllowJustify,
|
||||
PRBool aShrinkWrapWidth)
|
||||
PRBool aAllowJustify)
|
||||
{
|
||||
PerSpanData* psd = mRootSpan;
|
||||
nscoord availWidth = psd->mRightEdge;
|
||||
if (NS_UNCONSTRAINEDSIZE == availWidth) {
|
||||
NS_NOTREACHED("This shouldn't be called anymore");
|
||||
// Don't bother horizontal aligning on pass1 table reflow
|
||||
#ifdef NOISY_HORIZONTAL_ALIGN
|
||||
nsFrame::ListTag(stdout, mBlockReflowState->frame);
|
||||
printf(": skipping horizontal alignment in pass1 table reflow\n");
|
||||
#endif
|
||||
return PR_TRUE;
|
||||
return;
|
||||
}
|
||||
availWidth -= psd->mLeftEdge;
|
||||
nscoord remainingWidth = availWidth - aLineBounds.width;
|
||||
@ -2834,19 +2538,17 @@ nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
||||
// frames in the line. If it is the last line then if the
|
||||
// direction is right-to-left then we right-align the frames.
|
||||
if (aAllowJustify) {
|
||||
if (!aShrinkWrapWidth) {
|
||||
PRInt32 numSpaces;
|
||||
PRInt32 numLetters;
|
||||
PRInt32 numSpaces;
|
||||
PRInt32 numLetters;
|
||||
|
||||
ComputeJustificationWeights(psd, &numSpaces, &numLetters);
|
||||
ComputeJustificationWeights(psd, &numSpaces, &numLetters);
|
||||
|
||||
if (numSpaces > 0) {
|
||||
FrameJustificationState state = { numSpaces, numLetters, remainingWidth, 0, 0, 0, 0, 0 };
|
||||
if (numSpaces > 0) {
|
||||
FrameJustificationState state = { numSpaces, numLetters, remainingWidth, 0, 0, 0, 0, 0 };
|
||||
|
||||
// Apply the justification, and make sure to update our linebox
|
||||
// width to account for it.
|
||||
aLineBounds.width += ApplyFrameJustification(psd, &state);
|
||||
}
|
||||
// Apply the justification, and make sure to update our linebox
|
||||
// width to account for it.
|
||||
aLineBounds.width += ApplyFrameJustification(psd, &state);
|
||||
}
|
||||
}
|
||||
else if (NS_STYLE_DIRECTION_RTL == psd->mDirection) {
|
||||
@ -2889,11 +2591,6 @@ nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
||||
if (0 != dx)
|
||||
#endif
|
||||
{
|
||||
// If we need to move the frames but we're shrink wrapping, then
|
||||
// we need to wait until the final width is known
|
||||
if (aShrinkWrapWidth) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
for (PerFrameData* pfd = psd->mFirstFrame; pfd
|
||||
#ifdef IBMBIDI
|
||||
&& bulletPfd != pfd
|
||||
@ -2916,10 +2613,6 @@ nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
||||
!psd->mChangedFrameDirection) {
|
||||
psd->mChangedFrameDirection = PR_TRUE;
|
||||
|
||||
/* Assume that all frames have been right aligned.*/
|
||||
if (aShrinkWrapWidth) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
PerFrameData* pfd = psd->mFirstFrame;
|
||||
PRUint32 maxX = psd->mRightEdge;
|
||||
while (nsnull != pfd) {
|
||||
@ -2931,8 +2624,6 @@ nsLineLayout::HorizontalAlignFrames(nsRect& aLineBounds,
|
||||
}
|
||||
#endif // ndef IBMBIDI
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -66,8 +66,7 @@ class nsLineLayout {
|
||||
public:
|
||||
nsLineLayout(nsPresContext* aPresContext,
|
||||
nsSpaceManager* aSpaceManager,
|
||||
const nsHTMLReflowState* aOuterReflowState,
|
||||
PRBool aComputeMaxElementWidth);
|
||||
const nsHTMLReflowState* aOuterReflowState);
|
||||
~nsLineLayout();
|
||||
|
||||
void Init(nsBlockReflowState* aState, nscoord aMinLineHeight,
|
||||
@ -105,8 +104,7 @@ public:
|
||||
nscoord aLeftEdge,
|
||||
nscoord aRightEdge);
|
||||
|
||||
void EndSpan(nsIFrame* aFrame, nsSize& aSizeResult,
|
||||
nscoord* aMaxElementWidth);
|
||||
void EndSpan(nsIFrame* aFrame, nsSize& aSizeResult);
|
||||
|
||||
PRInt32 GetCurrentSpanCount() const;
|
||||
|
||||
@ -128,14 +126,11 @@ public:
|
||||
PushFrame(aFrame);
|
||||
}
|
||||
|
||||
void VerticalAlignLine(nsLineBox* aLineBox,
|
||||
nscoord* aMaxElementWidthResult);
|
||||
void VerticalAlignLine(nsLineBox* aLineBox);
|
||||
|
||||
PRBool TrimTrailingWhiteSpace();
|
||||
|
||||
PRBool HorizontalAlignFrames(nsRect& aLineBounds,
|
||||
PRBool aAllowJustify,
|
||||
PRBool aShrinkWrapWidth);
|
||||
void HorizontalAlignFrames(nsRect& aLineBounds, PRBool aAllowJustify);
|
||||
|
||||
/**
|
||||
* Handle all the relative positioning in the line, compute the
|
||||
@ -422,7 +417,6 @@ protected:
|
||||
nsBlockReflowState* mBlockRS;/* XXX hack! */
|
||||
nsCompatibility mCompatMode;
|
||||
nscoord mMinLineHeight;
|
||||
PRPackedBool mComputeMaxElementWidth;
|
||||
PRUint8 mTextAlign;
|
||||
|
||||
PRUint8 mPlacedFloats;
|
||||
@ -476,7 +470,6 @@ protected:
|
||||
// From metrics
|
||||
nscoord mAscent, mDescent;
|
||||
nsRect mBounds;
|
||||
nscoord mMaxElementWidth;
|
||||
nsRect mCombinedArea;
|
||||
|
||||
// From reflow-state
|
||||
|
@ -505,6 +505,12 @@ nsObjectFrame::GetType() const
|
||||
return nsLayoutAtoms::objectFrame;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsObjectFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
return !(aFlags & ~(eReplaced));
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHODIMP
|
||||
nsObjectFrame::GetFrameName(nsAString& aResult) const
|
||||
@ -591,6 +597,29 @@ nsObjectFrame::CreateWidget(nscoord aWidth,
|
||||
#define EMBED_DEF_WIDTH 240
|
||||
#define EMBED_DEF_HEIGHT 200
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsObjectFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result = 0;
|
||||
|
||||
if (!IsHidden(PR_FALSE)) {
|
||||
nsIAtom *atom = mContent->Tag();
|
||||
if (atom == nsHTMLAtoms::applet || atom == nsHTMLAtoms::embed) {
|
||||
float p2t = GetPresContext()->ScaledPixelsToTwips();
|
||||
result = NSIntPixelsToTwips(EMBED_DEF_WIDTH, p2t);
|
||||
}
|
||||
}
|
||||
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsObjectFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
return nsObjectFrame::GetMinWidth(aRenderingContext);
|
||||
}
|
||||
|
||||
void
|
||||
nsObjectFrame::GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -603,9 +632,6 @@ nsObjectFrame::GetDesiredSize(nsPresContext* aPresContext,
|
||||
aMetrics.descent = 0;
|
||||
|
||||
if (IsHidden(PR_FALSE)) {
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.mMaxElementWidth = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -664,10 +690,6 @@ nsObjectFrame::GetDesiredSize(nsPresContext* aPresContext,
|
||||
|
||||
// ascent
|
||||
aMetrics.ascent = aMetrics.height;
|
||||
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit());
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -676,7 +698,7 @@ nsObjectFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsObjectFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsObjectFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
||||
|
||||
// Get our desired size
|
||||
@ -738,8 +760,9 @@ nsObjectFrame::InstantiatePlugin(nsIPluginHost* aPluginHost,
|
||||
|
||||
// XXX having to do this sucks. it'd be better to move the code from DidReflow
|
||||
// to FixupWindow or something.
|
||||
nsIPresShell *shell = GetPresContext()->GetPresShell();
|
||||
shell->AppendReflowCommand(this, eReflowType_StyleChanged, nsnull);
|
||||
AddStateBits(NS_FRAME_IS_DIRTY);
|
||||
GetPresContext()->GetPresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eStyleChange);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1306,8 +1329,8 @@ nsObjectFrame::Instantiate(nsIChannel* aChannel, nsIStreamListener** aStreamList
|
||||
|
||||
// XXX having to do this sucks. it'd be better to move the code from DidReflow
|
||||
// to FixupWindow.
|
||||
nsIPresShell *shell = GetPresContext()->GetPresShell();
|
||||
shell->AppendReflowCommand(this, eReflowType_StyleChanged, nsnull);
|
||||
GetPresContext()->GetPresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eStyleChange);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,8 @@ public:
|
||||
NS_IMETHOD Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* aPrevInFlow);
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -89,6 +91,7 @@ public:
|
||||
nsEventStatus* aEventStatus);
|
||||
|
||||
virtual nsIAtom* GetType() const;
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
virtual PRBool SupportsVisibilityHidden() { return PR_FALSE; }
|
||||
virtual PRBool NeedsView() { return PR_TRUE; }
|
||||
virtual nsresult CreateWidgetForView(nsIView* aView);
|
||||
|
@ -65,7 +65,7 @@ NS_IMETHODIMP nsPageContentFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsPageContentFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsPageContentFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
aStatus = NS_FRAME_COMPLETE; // initialize out parameter
|
||||
|
||||
@ -121,8 +121,10 @@ NS_IMETHODIMP nsPageContentFrame::Reflow(nsPresContext* aPresContext,
|
||||
#endif
|
||||
}
|
||||
// Reflow our fixed frames
|
||||
mFixedContainer.Reflow(this, aPresContext, aReflowState, aReflowState.availableWidth,
|
||||
aReflowState.availableHeight);
|
||||
mFixedContainer.Reflow(this, aPresContext, aReflowState,
|
||||
aReflowState.availableWidth,
|
||||
aReflowState.availableHeight,
|
||||
PR_TRUE, PR_TRUE); // XXX could be optimized
|
||||
|
||||
// Return our desired size
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
|
@ -85,7 +85,7 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsPageFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsPageFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
aStatus = NS_FRAME_COMPLETE; // initialize out parameter
|
||||
|
||||
@ -98,8 +98,7 @@ NS_IMETHODIMP nsPageFrame::Reflow(nsPresContext* aPresContext,
|
||||
"This frame isn't a pageContentFrame");
|
||||
|
||||
if (contentPage && GetPrevInFlow() &&
|
||||
eReflowReason_Incremental != aReflowState.reason &&
|
||||
eReflowReason_Dirty != aReflowState.reason) {
|
||||
(GetStateBits() & NS_FRAME_IS_DIRTY)) {
|
||||
|
||||
nsPageFrame* prevPage = NS_STATIC_CAST(nsPageFrame*, GetPrevInFlow());
|
||||
nsPageContentFrame* prevContentPage = NS_STATIC_CAST(nsPageContentFrame*, prevPage->mFrames.FirstChild());
|
||||
@ -623,30 +622,10 @@ nsPageBreakFrame::~nsPageBreakFrame()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
nsPageBreakFrame::GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize)
|
||||
nscoord
|
||||
nsPageBreakFrame::GetIntrinsicWidth()
|
||||
{
|
||||
nscoord onePixel = aPresContext->IntScaledPixelsToTwips(1);
|
||||
|
||||
aDesiredSize.width = onePixel;
|
||||
if (mHaveReflowed) {
|
||||
// If blocks reflow us a 2nd time trying to put us on a new page, then return
|
||||
// a desired height of 0 to avoid an extra page break.
|
||||
aDesiredSize.height = 0;
|
||||
}
|
||||
else {
|
||||
aDesiredSize.height = aReflowState.availableHeight;
|
||||
// round the height down to the nearest pixel
|
||||
aDesiredSize.height -= aDesiredSize.height % onePixel;
|
||||
}
|
||||
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = onePixel;
|
||||
}
|
||||
aDesiredSize.ascent = 0;
|
||||
aDesiredSize.descent = 0;
|
||||
return GetPresContext()->IntScaledPixelsToTwips(1);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -655,13 +634,22 @@ nsPageBreakFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsPageBreakFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsPageBreakFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
GetDesiredSize(aPresContext, aReflowState, aDesiredSize);
|
||||
mHaveReflowed = PR_TRUE;
|
||||
// Override reflow, since we don't want to deal with what our
|
||||
// computed values are.
|
||||
aDesiredSize.width = GetIntrinsicWidth();
|
||||
aDesiredSize.height = aReflowState.availableHeight;
|
||||
// round the height down to the nearest pixel
|
||||
aDesiredSize.height -=
|
||||
aDesiredSize.height % GetPresContext()->IntScaledPixelsToTwips(1);
|
||||
aDesiredSize.ascent = aDesiredSize.descent = 0;
|
||||
|
||||
// Note: not using NS_FRAME_FIRST_REFLOW here, since it's not clear whether
|
||||
// DidReflow will always get called before the next Reflow() call.
|
||||
mHaveReflowed = PR_TRUE;
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -142,9 +142,8 @@ class nsPageBreakFrame : public nsLeafFrame {
|
||||
|
||||
protected:
|
||||
|
||||
virtual void GetDesiredSize(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsHTMLReflowMetrics& aDesiredSize);
|
||||
virtual nscoord GetIntrinsicWidth();
|
||||
|
||||
PRBool mHaveReflowed;
|
||||
|
||||
friend nsIFrame* NS_NewPageBreakFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
|
@ -59,21 +59,64 @@ nsPlaceholderFrame::~nsPlaceholderFrame()
|
||||
{
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsPlaceholderFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result = 0;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
nsPlaceholderFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result = 0;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsPlaceholderFrame::AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlineMinWidthData *aData)
|
||||
{
|
||||
// Override AddInlineMinWith so that *nothing* happens. In
|
||||
// particular, we don't want to zero out |aData->trailingWhitespace|,
|
||||
// since nsLineLayout skips placeholders when trimming trailing
|
||||
// whitespace, and we don't want to set aData->skipWhitespace to
|
||||
// false.
|
||||
|
||||
// ...but push floats onto the list
|
||||
if (mOutOfFlowFrame->GetStyleDisplay()->mFloats != NS_STYLE_FLOAT_NONE)
|
||||
aData->floats.AppendElement(mOutOfFlowFrame);
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsPlaceholderFrame::AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlinePrefWidthData *aData)
|
||||
{
|
||||
// Override AddInlinePrefWith so that *nothing* happens. In
|
||||
// particular, we don't want to zero out |aData->trailingWhitespace|,
|
||||
// since nsLineLayout skips placeholders when trimming trailing
|
||||
// whitespace, and we don't want to set aData->skipWhitespace to
|
||||
// false.
|
||||
|
||||
// ...but push floats onto the list
|
||||
if (mOutOfFlowFrame->GetStyleDisplay()->mFloats != NS_STYLE_FLOAT_NONE)
|
||||
aData->floats.AppendElement(mOutOfFlowFrame);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPlaceholderFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsPlaceholderFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsPlaceholderFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
aDesiredSize.width = 0;
|
||||
aDesiredSize.height = 0;
|
||||
aDesiredSize.ascent = 0;
|
||||
aDesiredSize.descent = 0;
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = 0;
|
||||
}
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
||||
@ -106,16 +149,15 @@ nsPlaceholderFrame::GetType() const
|
||||
return nsLayoutAtoms::placeholderFrame;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsPlaceholderFrame::CanContinueTextRun(PRBool& aContinueTextRun) const
|
||||
/* virtual */ PRBool
|
||||
nsPlaceholderFrame::CanContinueTextRun() const
|
||||
{
|
||||
if (!mOutOfFlowFrame) {
|
||||
aContinueTextRun = PR_FALSE;
|
||||
return NS_OK;
|
||||
return PR_FALSE;
|
||||
}
|
||||
// first-letter frames can continue text runs, and placeholders for floated
|
||||
// first-letter frames can too
|
||||
return mOutOfFlowFrame->CanContinueTextRun(aContinueTextRun);
|
||||
return mOutOfFlowFrame->CanContinueTextRun();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -97,6 +97,14 @@ public:
|
||||
void SetOutOfFlowFrame(nsIFrame* aFrame) {mOutOfFlowFrame = aFrame;}
|
||||
|
||||
// nsIHTMLReflow overrides
|
||||
// We need to override GetMinWidth and GetPrefWidth because XUL uses
|
||||
// placeholders not within lines.
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual void AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineMinWidthData *aData);
|
||||
virtual void AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlinePrefWidthData *aData);
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -130,7 +138,7 @@ public:
|
||||
virtual PRBool IsEmpty() { return PR_TRUE; }
|
||||
virtual PRBool IsSelfEmpty() { return PR_TRUE; }
|
||||
|
||||
NS_IMETHOD CanContinueTextRun(PRBool& aContinueTextRun) const;
|
||||
virtual PRBool CanContinueTextRun() const;
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
NS_IMETHOD GetAccessible(nsIAccessible** aAccessible)
|
||||
|
@ -1,133 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike Shaver <shaver@mozilla.org>
|
||||
* Randell Jesup <rjesup@wgate.com>
|
||||
* Chris Waterson <waterson@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "pldhash.h"
|
||||
#include "prenv.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsFrame.h"
|
||||
#include "nsIFrame.h"
|
||||
#include "nsHTMLReflowCommand.h"
|
||||
|
||||
nsReflowPath::~nsReflowPath()
|
||||
{
|
||||
for (PRInt32 i = mChildren.Count() - 1; i >= 0; --i)
|
||||
delete NS_STATIC_CAST(nsReflowPath *, mChildren[i]);
|
||||
|
||||
delete mReflowCommand;
|
||||
}
|
||||
|
||||
nsReflowPath::iterator
|
||||
nsReflowPath::FindChild(nsIFrame *aFrame)
|
||||
{
|
||||
for (PRInt32 i = mChildren.Count() - 1; i >= 0; --i) {
|
||||
nsReflowPath *subtree = NS_STATIC_CAST(nsReflowPath *, mChildren[i]);
|
||||
if (subtree->mFrame == aFrame)
|
||||
return iterator(this, i);
|
||||
}
|
||||
|
||||
return iterator(this, -1);
|
||||
}
|
||||
|
||||
nsReflowPath *
|
||||
nsReflowPath::GetSubtreeFor(nsIFrame *aFrame) const
|
||||
{
|
||||
for (PRInt32 i = mChildren.Count() - 1; i >= 0; --i) {
|
||||
nsReflowPath *subtree = NS_STATIC_CAST(nsReflowPath *, mChildren[i]);
|
||||
if (subtree->mFrame == aFrame)
|
||||
return subtree;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsReflowPath *
|
||||
nsReflowPath::EnsureSubtreeFor(nsIFrame *aFrame)
|
||||
{
|
||||
for (PRInt32 i = mChildren.Count() - 1; i >= 0; --i) {
|
||||
nsReflowPath *subtree = NS_STATIC_CAST(nsReflowPath *, mChildren[i]);
|
||||
if (subtree->mFrame == aFrame)
|
||||
return subtree;
|
||||
}
|
||||
|
||||
nsReflowPath *subtree = new nsReflowPath(aFrame);
|
||||
mChildren.AppendElement(subtree);
|
||||
|
||||
return subtree;
|
||||
}
|
||||
|
||||
void
|
||||
nsReflowPath::Remove(iterator &aIterator)
|
||||
{
|
||||
NS_ASSERTION(aIterator.mNode == this, "inconsistent iterator");
|
||||
|
||||
if (aIterator.mIndex >= 0 && aIterator.mIndex < mChildren.Count()) {
|
||||
delete NS_STATIC_CAST(nsReflowPath *, mChildren[aIterator.mIndex]);
|
||||
mChildren.RemoveElementAt(aIterator.mIndex);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
DebugListReflowPath(nsPresContext *aPresContext, nsReflowPath *aReflowPath)
|
||||
{
|
||||
aReflowPath->Dump(aPresContext, stdout, 0);
|
||||
}
|
||||
|
||||
void
|
||||
nsReflowPath::Dump(nsPresContext *aPresContext, FILE *aFile, int depth)
|
||||
{
|
||||
fprintf(aFile, "%*s nsReflowPath(%p): ", depth, "", this);
|
||||
|
||||
nsFrame::ListTag(aFile, mFrame);
|
||||
|
||||
if (mReflowCommand) {
|
||||
fprintf(aFile, " <- ");
|
||||
mReflowCommand->List(aFile);
|
||||
}
|
||||
|
||||
fprintf(aFile, "\n");
|
||||
|
||||
for (PRInt32 i = 0; i < mChildren.Count(); ++i) {
|
||||
nsReflowPath *child = NS_STATIC_CAST(nsReflowPath *, mChildren[i]);
|
||||
child->Dump(aPresContext, aFile, depth + 1);
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1,232 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2002
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Mike Shaver <shaver@mozilla.org>
|
||||
* Randell Jesup <rjesup@wgate.com>
|
||||
* Chris Waterson <waterson@netscape.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsReflowPath_h__
|
||||
#define nsReflowPath_h__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "pldhash.h"
|
||||
#include "nsReflowType.h"
|
||||
#include "nsVoidArray.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
class nsIFrame;
|
||||
class nsHTMLReflowCommand;
|
||||
class nsPresContext;
|
||||
|
||||
/**
|
||||
* A reflow `path' that is a sparse tree the parallels the frame
|
||||
* hierarchy. This is used during an incremental reflow to record the
|
||||
* path which the reflow must trace through the frame hierarchy.
|
||||
*/
|
||||
class nsReflowPath
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Construct a reflow path object that parallels the specified
|
||||
* frame.
|
||||
*/
|
||||
nsReflowPath(nsIFrame *aFrame)
|
||||
: mFrame(aFrame),
|
||||
mReflowCommand(nsnull) {}
|
||||
|
||||
~nsReflowPath();
|
||||
|
||||
/**
|
||||
* An iterator for enumerating the reflow path's immediate
|
||||
* children.
|
||||
*/
|
||||
class iterator
|
||||
{
|
||||
protected:
|
||||
nsReflowPath *mNode;
|
||||
PRInt32 mIndex;
|
||||
|
||||
friend class nsReflowPath;
|
||||
|
||||
iterator(nsReflowPath *aNode, PRInt32 aIndex)
|
||||
: mNode(aNode), mIndex(aIndex) {}
|
||||
|
||||
void
|
||||
Advance() { --mIndex; }
|
||||
|
||||
public:
|
||||
iterator()
|
||||
: mNode(nsnull) {}
|
||||
|
||||
iterator(const iterator &iter)
|
||||
: mNode(iter.mNode), mIndex(iter.mIndex) {}
|
||||
|
||||
iterator &
|
||||
operator=(const iterator &iter) {
|
||||
mNode = iter.mNode;
|
||||
mIndex = iter.mIndex;
|
||||
return *this; }
|
||||
|
||||
nsReflowPath *
|
||||
get() const {
|
||||
return NS_STATIC_CAST(nsReflowPath *, mNode->mChildren[mIndex]); }
|
||||
|
||||
nsReflowPath *
|
||||
get() {
|
||||
return NS_STATIC_CAST(nsReflowPath *, mNode->mChildren[mIndex]); }
|
||||
|
||||
nsIFrame *
|
||||
operator*() const {
|
||||
return get()->mFrame; }
|
||||
|
||||
nsIFrame *&
|
||||
operator*() {
|
||||
return get()->mFrame; }
|
||||
|
||||
iterator &
|
||||
operator++() { Advance(); return *this; }
|
||||
|
||||
iterator
|
||||
operator++(int) {
|
||||
iterator temp(*this);
|
||||
Advance();
|
||||
return temp; }
|
||||
|
||||
PRBool
|
||||
operator==(const iterator &iter) const {
|
||||
return (mNode == iter.mNode) && (mIndex == iter.mIndex); }
|
||||
|
||||
PRBool
|
||||
operator!=(const iterator &iter) const {
|
||||
return !iter.operator==(*this); }
|
||||
};
|
||||
|
||||
/**
|
||||
* Return an iterator that points to the first immediate child of
|
||||
* the reflow path.
|
||||
*/
|
||||
iterator FirstChild() { return iterator(this, mChildren.Count() - 1); }
|
||||
|
||||
/**
|
||||
* Return an iterator that points `one past the end' of the
|
||||
* immediate children of the reflow path.
|
||||
*/
|
||||
iterator EndChildren() { return iterator(this, -1); }
|
||||
|
||||
/**
|
||||
* Determine if the reflow path contains the specified frame as
|
||||
* one of its immediate children.
|
||||
*/
|
||||
PRBool
|
||||
HasChild(nsIFrame *aFrame) const {
|
||||
return GetSubtreeFor(aFrame) != nsnull; }
|
||||
|
||||
/**
|
||||
* Return an iterator over the current reflow path that
|
||||
* corresponds to the specified child frame. Returns EndChildren
|
||||
* if aFrame is not an immediate child of the reflow path.
|
||||
*/
|
||||
iterator
|
||||
FindChild(nsIFrame *aFrame);
|
||||
|
||||
/**
|
||||
* Remove the specified child frame from the reflow path, along
|
||||
* with any of its descendants. Does nothing if aFrame is not an
|
||||
* immediate child of the reflow path.
|
||||
*/
|
||||
void
|
||||
RemoveChild(nsIFrame *aFrame) {
|
||||
iterator iter = FindChild(aFrame);
|
||||
Remove(iter); }
|
||||
|
||||
/**
|
||||
* Return the child reflow path that corresponds to the specified
|
||||
* frame, or null if the frame is not an immediate descendant.
|
||||
*/
|
||||
nsReflowPath *
|
||||
GetSubtreeFor(nsIFrame *aFrame) const;
|
||||
|
||||
/**
|
||||
* Return the child reflow path that corresponds to the specified
|
||||
* frame, constructing a new child reflow path if one doesn't
|
||||
* exist already.
|
||||
*/
|
||||
nsReflowPath *
|
||||
EnsureSubtreeFor(nsIFrame *aFrame);
|
||||
|
||||
/**
|
||||
* Remove the child reflow path that corresponds to the specified
|
||||
* iterator.
|
||||
*/
|
||||
void
|
||||
Remove(iterator &aIterator);
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* Recursively dump the reflow path object and its descendants.
|
||||
*/
|
||||
void
|
||||
Dump(nsPresContext *aPresContext, FILE *aFile, int aDepth);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The frame that this reflow path object is associated with.
|
||||
*/
|
||||
nsIFrame *mFrame;
|
||||
|
||||
/**
|
||||
* If mFrame is the immediate target of an incremental reflow,
|
||||
* this contains the reflow command that targeted it. Otherwise,
|
||||
* this is null (and mFrame simply lies along the path to a target
|
||||
* frame). The reflow path object assumes ownership of the reflow
|
||||
* command.
|
||||
*/
|
||||
nsHTMLReflowCommand *mReflowCommand;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The children of this reflow path; also contains pointers to
|
||||
* nsReflowPath objects.
|
||||
*/
|
||||
nsSmallVoidArray mChildren;
|
||||
|
||||
friend class iterator;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,71 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Netscape Communications Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 1998
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsReflowType_h__
|
||||
#define nsReflowType_h__
|
||||
|
||||
enum nsReflowType {
|
||||
/**
|
||||
* This reflow command is used when a leaf node's content changes
|
||||
* (e.g. some text in a text run, an image's source, etc.). The
|
||||
* target of the reflow command is the frame that changed (see
|
||||
* nsIFrame#ContentChanged() for how the target frame is
|
||||
* determined).
|
||||
*/
|
||||
eReflowType_ContentChanged,
|
||||
|
||||
/**
|
||||
* This reflow command is used when the style for a frame has
|
||||
* changed. This also implies that if the frame is a container
|
||||
* that its children's style has also changed. The target of the
|
||||
* reflow command is the frame that changed style.
|
||||
*/
|
||||
eReflowType_StyleChanged,
|
||||
|
||||
/**
|
||||
* Reflow dirty stuff (really a per-frame extension)
|
||||
*/
|
||||
eReflowType_ReflowDirty,
|
||||
|
||||
/**
|
||||
* Trap door for extensions.
|
||||
*/
|
||||
eReflowType_UserDefined
|
||||
};
|
||||
|
||||
#endif // nsReflowType_h__
|
||||
|
@ -199,13 +199,13 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext,
|
||||
{
|
||||
NS_PRECONDITION(aPresContext->IsRootPaginatedDocument(),
|
||||
"A Page Sequence is only for real pages");
|
||||
DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow");
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE; // we're always complete
|
||||
|
||||
if (eReflowReason_Resize == aReflowState.reason) {
|
||||
if (!(GetStateBits() & (NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
|
||||
// Return our desired size
|
||||
aDesiredSize.height = mSize.height;
|
||||
aDesiredSize.width = mSize.width;
|
||||
@ -284,103 +284,93 @@ nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext,
|
||||
pageSize.height + shadowSize.height +
|
||||
extraMargin.TopBottom());
|
||||
|
||||
// See if it's an incremental reflow command
|
||||
if (!aPresContext->IsDynamic() &&
|
||||
eReflowReason_Incremental == aReflowState.reason) {
|
||||
// XXX Skip Incremental reflow,
|
||||
// in fact, all we want is the initial reflow
|
||||
y = mRect.height;
|
||||
} else {
|
||||
nsReflowReason reflowReason = aReflowState.reason;
|
||||
// Tile the pages vertically
|
||||
nsHTMLReflowMetrics kidSize;
|
||||
for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; ) {
|
||||
// Reflow the page
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
|
||||
availSize);
|
||||
nsReflowStatus status;
|
||||
|
||||
// Tile the pages vertically
|
||||
nsHTMLReflowMetrics kidSize(nsnull);
|
||||
for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; ) {
|
||||
// Reflow the page
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
|
||||
availSize, reflowReason);
|
||||
nsReflowStatus status;
|
||||
kidReflowState.mComputedWidth = kidReflowState.availableWidth;
|
||||
//kidReflowState.mComputedHeight = kidReflowState.availableHeight;
|
||||
PR_PL(("AV W: %d H: %d\n", kidReflowState.availableWidth, kidReflowState.availableHeight));
|
||||
|
||||
kidReflowState.mComputedWidth = kidReflowState.availableWidth;
|
||||
//kidReflowState.mComputedHeight = kidReflowState.availableHeight;
|
||||
PR_PL(("AV W: %d H: %d\n", kidReflowState.availableWidth, kidReflowState.availableHeight));
|
||||
// Set the shared data into the page frame before reflow
|
||||
nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, kidFrame);
|
||||
pf->SetSharedPageData(mPageData);
|
||||
|
||||
// Set the shared data into the page frame before reflow
|
||||
nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, kidFrame);
|
||||
pf->SetSharedPageData(mPageData);
|
||||
// Place and size the page. If the page is narrower than our
|
||||
// max width then center it horizontally
|
||||
ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status);
|
||||
|
||||
// Place and size the page. If the page is narrower than our
|
||||
// max width then center it horizontally
|
||||
ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status);
|
||||
reflowPageSize.SizeTo(kidSize.width, kidSize.height);
|
||||
|
||||
reflowPageSize.SizeTo(kidSize.width, kidSize.height);
|
||||
FinishReflowChild(kidFrame, aPresContext, nsnull, kidSize, x, y, 0);
|
||||
y += kidSize.height;
|
||||
|
||||
FinishReflowChild(kidFrame, aPresContext, nsnull, kidSize, x, y, 0);
|
||||
y += kidSize.height;
|
||||
// Leave a slight gap between the pages
|
||||
y += deadSpaceGap;
|
||||
|
||||
// Leave a slight gap between the pages
|
||||
y += deadSpaceGap;
|
||||
// Is the page complete?
|
||||
nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();
|
||||
|
||||
// Is the page complete?
|
||||
nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();
|
||||
|
||||
if (NS_FRAME_IS_COMPLETE(status)) {
|
||||
NS_ASSERTION(nsnull == kidNextInFlow, "bad child flow list");
|
||||
} else if (nsnull == kidNextInFlow) {
|
||||
// The page isn't complete and it doesn't have a next-in-flow, so
|
||||
// create a continuing page
|
||||
nsIFrame* continuingPage;
|
||||
nsresult rv = CreateContinuingPageFrame(aPresContext, kidFrame,
|
||||
&continuingPage);
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
// Add it to our child list
|
||||
kidFrame->SetNextSibling(continuingPage);
|
||||
reflowReason = eReflowReason_Initial;
|
||||
if (NS_FRAME_IS_COMPLETE(status)) {
|
||||
NS_ASSERTION(nsnull == kidNextInFlow, "bad child flow list");
|
||||
} else if (nsnull == kidNextInFlow) {
|
||||
// The page isn't complete and it doesn't have a next-in-flow, so
|
||||
// create a continuing page
|
||||
nsIFrame* continuingPage;
|
||||
nsresult rv = CreateContinuingPageFrame(aPresContext, kidFrame,
|
||||
&continuingPage);
|
||||
if (NS_FAILED(rv)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Get the next page
|
||||
kidFrame = kidFrame->GetNextSibling();
|
||||
// Add it to our child list
|
||||
kidFrame->SetNextSibling(continuingPage);
|
||||
}
|
||||
|
||||
// Get Total Page Count
|
||||
nsIFrame* page;
|
||||
PRInt32 pageTot = 0;
|
||||
for (page = mFrames.FirstChild(); page; page = page->GetNextSibling()) {
|
||||
pageTot++;
|
||||
}
|
||||
|
||||
// Set Page Number Info
|
||||
PRInt32 pageNum = 1;
|
||||
for (page = mFrames.FirstChild(); page; page = page->GetNextSibling()) {
|
||||
nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, page);
|
||||
if (pf != nsnull) {
|
||||
pf->SetPageNumInfo(pageNum, pageTot);
|
||||
}
|
||||
pageNum++;
|
||||
}
|
||||
|
||||
// Create current Date/Time String
|
||||
if (!mDateFormatter)
|
||||
mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID);
|
||||
#ifndef WINCE
|
||||
NS_ENSURE_TRUE(mDateFormatter, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoString formattedDateString;
|
||||
time_t ltime;
|
||||
time( <ime );
|
||||
if (NS_SUCCEEDED(mDateFormatter->FormatTime(nsnull /* nsILocale* locale */,
|
||||
kDateFormatShort,
|
||||
kTimeFormatNoSeconds,
|
||||
ltime,
|
||||
formattedDateString))) {
|
||||
PRUnichar * uStr = ToNewUnicode(formattedDateString);
|
||||
SetDateTimeStr(uStr); // memory will be freed
|
||||
}
|
||||
#endif
|
||||
// Get the next page
|
||||
kidFrame = kidFrame->GetNextSibling();
|
||||
}
|
||||
|
||||
// Get Total Page Count
|
||||
nsIFrame* page;
|
||||
PRInt32 pageTot = 0;
|
||||
for (page = mFrames.FirstChild(); page; page = page->GetNextSibling()) {
|
||||
pageTot++;
|
||||
}
|
||||
|
||||
// Set Page Number Info
|
||||
PRInt32 pageNum = 1;
|
||||
for (page = mFrames.FirstChild(); page; page = page->GetNextSibling()) {
|
||||
nsPageFrame * pf = NS_STATIC_CAST(nsPageFrame*, page);
|
||||
if (pf != nsnull) {
|
||||
pf->SetPageNumInfo(pageNum, pageTot);
|
||||
}
|
||||
pageNum++;
|
||||
}
|
||||
|
||||
// Create current Date/Time String
|
||||
if (!mDateFormatter)
|
||||
mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID);
|
||||
#ifndef WINCE
|
||||
NS_ENSURE_TRUE(mDateFormatter, NS_ERROR_FAILURE);
|
||||
|
||||
nsAutoString formattedDateString;
|
||||
time_t ltime;
|
||||
time( <ime );
|
||||
if (NS_SUCCEEDED(mDateFormatter->FormatTime(nsnull /* nsILocale* locale */,
|
||||
kDateFormatShort,
|
||||
kTimeFormatNoSeconds,
|
||||
ltime,
|
||||
formattedDateString))) {
|
||||
PRUnichar * uStr = ToNewUnicode(formattedDateString);
|
||||
SetDateTimeStr(uStr); // memory will be freed
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return our desired size
|
||||
aDesiredSize.height = y; // includes page heights and dead space
|
||||
aDesiredSize.width = x + availSize.width + deadSpaceGap;
|
||||
|
@ -56,6 +56,8 @@ public:
|
||||
friend nsIFrame* NS_NewSpacerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext);
|
||||
|
||||
// nsIHTMLReflow
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
@ -66,6 +68,7 @@ public:
|
||||
protected:
|
||||
SpacerFrame(nsStyleContext* aContext) : nsFrame(aContext) {}
|
||||
virtual ~SpacerFrame();
|
||||
void GetDesiredSize(nsHTMLReflowMetrics& aMetrics, nsSize aPercentBase);
|
||||
};
|
||||
|
||||
nsIFrame*
|
||||
@ -78,16 +81,52 @@ SpacerFrame::~SpacerFrame()
|
||||
{
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
SpacerFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nsHTMLReflowMetrics metrics;
|
||||
DISPLAY_MIN_WIDTH(this, metrics.width);
|
||||
GetDesiredSize(metrics, nsSize(0, 0));
|
||||
return metrics.width;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
SpacerFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nsHTMLReflowMetrics metrics;
|
||||
DISPLAY_PREF_WIDTH(this, metrics.width);
|
||||
GetDesiredSize(metrics, nsSize(0, 0));
|
||||
return metrics.width;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
SpacerFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("SpacerFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("SpacerFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
nsSize percentBase(aReflowState.availableWidth, aReflowState.availableHeight);
|
||||
if (percentBase.width == NS_UNCONSTRAINEDSIZE)
|
||||
percentBase.width = 0;
|
||||
if (percentBase.height == NS_UNCONSTRAINEDSIZE)
|
||||
percentBase.height = 0;
|
||||
|
||||
if (GetType() == TYPE_LINE)
|
||||
aStatus = NS_INLINE_LINE_BREAK_AFTER(NS_FRAME_COMPLETE);
|
||||
|
||||
GetDesiredSize(aMetrics, percentBase);
|
||||
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
SpacerFrame::GetDesiredSize(nsHTMLReflowMetrics& aMetrics, nsSize aPercentBase)
|
||||
{
|
||||
// By default, we have no area
|
||||
aMetrics.width = 0;
|
||||
aMetrics.height = 0;
|
||||
@ -102,9 +141,8 @@ SpacerFrame::Reflow(nsPresContext* aPresContext,
|
||||
break;
|
||||
|
||||
case TYPE_LINE:
|
||||
aStatus = NS_INLINE_LINE_BREAK_AFTER(NS_FRAME_COMPLETE);
|
||||
if (eStyleUnit_Coord == position->mHeight.GetUnit()) {
|
||||
aMetrics.width = position->mHeight.GetCoordValue();
|
||||
aMetrics.height = position->mHeight.GetCoordValue();
|
||||
}
|
||||
aMetrics.ascent = aMetrics.height;
|
||||
break;
|
||||
@ -117,11 +155,8 @@ SpacerFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
else if (eStyleUnit_Percent == unit)
|
||||
{
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)
|
||||
{
|
||||
float factor = position->mWidth.GetPercentValue();
|
||||
aMetrics.width = NSToCoordRound (factor * aReflowState.availableWidth);
|
||||
}
|
||||
float factor = position->mWidth.GetPercentValue();
|
||||
aMetrics.width = NSToCoordRound(factor * aPercentBase.width);
|
||||
}
|
||||
|
||||
// height
|
||||
@ -131,11 +166,8 @@ SpacerFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
else if (eStyleUnit_Percent == unit)
|
||||
{
|
||||
if (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)
|
||||
{
|
||||
float factor = position->mHeight.GetPercentValue();
|
||||
aMetrics.width = NSToCoordRound (factor * aReflowState.availableHeight);
|
||||
}
|
||||
float factor = position->mHeight.GetPercentValue();
|
||||
aMetrics.width = NSToCoordRound(factor * aPercentBase.height);
|
||||
}
|
||||
// accent
|
||||
aMetrics.ascent = aMetrics.height;
|
||||
@ -147,13 +179,6 @@ SpacerFrame::Reflow(nsPresContext* aPresContext,
|
||||
if (!aMetrics.width) aMetrics.width = 1;
|
||||
if (!aMetrics.height) aMetrics.height = 1;
|
||||
}
|
||||
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.SetMEWToActualWidth(aReflowState.mStylePosition->mWidth.GetUnit());
|
||||
}
|
||||
|
||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRUint8
|
||||
|
@ -320,6 +320,8 @@ public:
|
||||
* @see nsLayoutAtoms::textFrame
|
||||
*/
|
||||
virtual nsIAtom* GetType() const;
|
||||
|
||||
virtual PRBool IsFrameOfType(PRUint32 aFlags) const;
|
||||
|
||||
#ifdef DEBUG
|
||||
NS_IMETHOD List(FILE* out, PRInt32 aIndent) const;
|
||||
@ -382,11 +384,22 @@ public:
|
||||
#endif
|
||||
|
||||
// nsIHTMLReflow
|
||||
virtual void MarkIntrinsicWidthsDirty();
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual void AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineMinWidthData *aData);
|
||||
virtual void AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlinePrefWidthData *aData);
|
||||
virtual nsSize ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap);
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus);
|
||||
NS_IMETHOD CanContinueTextRun(PRBool& aContinueTextRun) const;
|
||||
virtual PRBool CanContinueTextRun() const;
|
||||
NS_IMETHOD TrimTrailingWhiteSpace(nsPresContext* aPresContext,
|
||||
nsIRenderingContext& aRC,
|
||||
nscoord& aDeltaWidth,
|
||||
@ -395,7 +408,6 @@ public:
|
||||
struct TextReflowData {
|
||||
PRInt32 mX; // OUT
|
||||
PRInt32 mOffset; // IN/OUT How far along we are in the content
|
||||
nscoord mMaxWordWidth; // OUT
|
||||
nscoord mAscent; // OUT
|
||||
nscoord mDescent; // OUT
|
||||
PRPackedBool mWrapping; // IN
|
||||
@ -404,7 +416,6 @@ public:
|
||||
PRPackedBool mInWord; // IN
|
||||
PRPackedBool mFirstLetterOK; // IN
|
||||
PRPackedBool mCanBreakBefore; // IN
|
||||
PRPackedBool mComputeMaxWordWidth; // IN
|
||||
PRPackedBool mTrailingSpaceTrimmed; // IN/OUT
|
||||
|
||||
TextReflowData(PRInt32 aStartingOffset,
|
||||
@ -414,11 +425,9 @@ public:
|
||||
PRBool aInWord,
|
||||
PRBool aFirstLetterOK,
|
||||
PRBool aCanBreakBefore,
|
||||
PRBool aComputeMaxWordWidth,
|
||||
PRBool aTrailingSpaceTrimmed)
|
||||
: mX(0),
|
||||
mOffset(aStartingOffset),
|
||||
mMaxWordWidth(0),
|
||||
mAscent(0),
|
||||
mDescent(0),
|
||||
mWrapping(aWrapping),
|
||||
@ -427,7 +436,6 @@ public:
|
||||
mInWord(aInWord),
|
||||
mFirstLetterOK(aFirstLetterOK),
|
||||
mCanBreakBefore(aCanBreakBefore),
|
||||
mComputeMaxWordWidth(aComputeMaxWordWidth),
|
||||
mTrailingSpaceTrimmed(aTrailingSpaceTrimmed)
|
||||
{}
|
||||
};
|
||||
@ -483,7 +491,7 @@ public:
|
||||
nscoord aWidth,
|
||||
SelectionDetails *aDetails = nsnull);
|
||||
|
||||
void MeasureSmallCapsText(const nsHTMLReflowState& aReflowState,
|
||||
void MeasureSmallCapsText(nsIRenderingContext* aRenderingContext,
|
||||
nsTextStyle& aStyle,
|
||||
PRUnichar* aWord,
|
||||
PRInt32 aWordLength,
|
||||
@ -1406,6 +1414,11 @@ public:
|
||||
}
|
||||
virtual nsIFrame* GetFirstInFlow() const;
|
||||
virtual nsIFrame* GetFirstContinuation() const;
|
||||
|
||||
virtual void AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineMinWidthData *aData);
|
||||
virtual void AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlinePrefWidthData *aData);
|
||||
|
||||
protected:
|
||||
nsContinuingTextFrame(nsStyleContext* aContext) : nsTextFrame(aContext) {}
|
||||
@ -1491,6 +1504,46 @@ nsContinuingTextFrame::GetFirstContinuation() const
|
||||
return firstContinuation;
|
||||
}
|
||||
|
||||
// XXX Do we want to do all the work for the first-in-flow or do the
|
||||
// work for each part? (Be careful of first-letter / first-line, though,
|
||||
// especially first-line!) Doing all the work on the first-in-flow has
|
||||
// the advantage of avoiding the potential for incremental reflow bugs,
|
||||
// but depends on our maintining the frame tree in reasonable ways even
|
||||
// for edge cases (block-within-inline splits, nextBidi, etc.)
|
||||
|
||||
// XXX We really need to make :first-letter happen during frame
|
||||
// construction.
|
||||
|
||||
// Needed for text frames in XUL.
|
||||
/* virtual */ nscoord
|
||||
nsTextFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
return nsLayoutUtils::MinWidthFromInline(this, aRenderingContext);
|
||||
}
|
||||
|
||||
// Needed for text frames in XUL.
|
||||
/* virtual */ nscoord
|
||||
nsTextFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
return nsLayoutUtils::PrefWidthFromInline(this, aRenderingContext);
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsContinuingTextFrame::AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlineMinWidthData *aData)
|
||||
{
|
||||
// Do nothing, since the first-in-flow accounts for everything.
|
||||
return;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsContinuingTextFrame::AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
InlinePrefWidthData *aData)
|
||||
{
|
||||
// Do nothing, since the first-in-flow accounts for everything.
|
||||
return;
|
||||
}
|
||||
|
||||
//DRAW SELECTION ITERATOR USED FOR TEXTFRAMES ONLY
|
||||
//helper class for drawing multiply selected text
|
||||
class DrawSelectionIterator
|
||||
@ -1911,11 +1964,8 @@ nsTextFrame::CharacterDataChanged(nsPresContext* aPresContext,
|
||||
}
|
||||
|
||||
// Ask the parent frame to reflow me.
|
||||
nsIPresShell *shell = aPresContext->GetPresShell();
|
||||
if (shell && mParent) {
|
||||
mParent->ReflowDirtyChild(shell, targetTextFrame);
|
||||
}
|
||||
|
||||
aPresContext->GetPresShell()->FrameNeedsReflow(targetTextFrame,
|
||||
nsIPresShell::eStyleChange);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -3382,18 +3432,18 @@ nsTextFrame::RenderString(nsIRenderingContext& aRenderingContext,
|
||||
}
|
||||
|
||||
inline void
|
||||
nsTextFrame::MeasureSmallCapsText(const nsHTMLReflowState& aReflowState,
|
||||
nsTextFrame::MeasureSmallCapsText(nsIRenderingContext* aRenderingContext,
|
||||
nsTextStyle& aTextStyle,
|
||||
PRUnichar* aWord,
|
||||
PRInt32 aWordLength,
|
||||
PRBool aIsEndOfFrame,
|
||||
nsTextDimensions* aDimensionsResult)
|
||||
{
|
||||
nsIRenderingContext& rc = *aReflowState.rendContext;
|
||||
aDimensionsResult->Clear();
|
||||
GetTextDimensions(rc, aTextStyle, aWord, aWordLength, aIsEndOfFrame, aDimensionsResult);
|
||||
GetTextDimensions(*aRenderingContext, aTextStyle, aWord, aWordLength,
|
||||
aIsEndOfFrame, aDimensionsResult);
|
||||
if (aTextStyle.mLastFont != aTextStyle.mNormalFont) {
|
||||
rc.SetFont(aTextStyle.mNormalFont);
|
||||
aRenderingContext->SetFont(aTextStyle.mNormalFont);
|
||||
aTextStyle.mLastFont = aTextStyle.mNormalFont;
|
||||
}
|
||||
}
|
||||
@ -4974,7 +5024,7 @@ nsTextFrame::MeasureText(nsPresContext* aPresContext,
|
||||
PRInt32 contentLength = aTx.GetContentLength();
|
||||
PRInt32 startingOffset = aTextData.mOffset;
|
||||
PRInt32 column = mColumn;
|
||||
nscoord prevMaxWordWidth = 0, prevAscent = 0, prevDescent = 0;
|
||||
nscoord prevAscent = 0, prevDescent = 0;
|
||||
PRInt32 lastWordLen = 0;
|
||||
PRUnichar* lastWordPtr = nsnull;
|
||||
PRBool endsInWhitespace = PR_FALSE;
|
||||
@ -5009,7 +5059,7 @@ nsTextFrame::MeasureText(nsPresContext* aPresContext,
|
||||
PRUint32 hints = 0;
|
||||
aReflowState.rendContext->GetHints(hints);
|
||||
if (hints & NS_RENDERING_HINT_FAST_MEASURE) {
|
||||
measureTextRuns = !aTextData.mComputeMaxWordWidth && !aTs.mPreformatted &&
|
||||
measureTextRuns = !aTs.mPreformatted &&
|
||||
!aTs.mSmallCaps && !aTs.mWordSpacing && !aTs.mLetterSpacing &&
|
||||
aTextData.mWrapping;
|
||||
}
|
||||
@ -5100,7 +5150,7 @@ nsTextFrame::MeasureText(nsPresContext* aPresContext,
|
||||
if (firstWordDone) {
|
||||
// The first word has been processed, and 2nd word is seen
|
||||
// we can set it be breakable here after.
|
||||
aTextData.mCanBreakBefore = PR_TRUE;
|
||||
aTextData.mCanBreakBefore = PR_TRUE;
|
||||
}
|
||||
} else {
|
||||
if (textRun.IsBuffering()) {
|
||||
@ -5138,7 +5188,7 @@ nsTextFrame::MeasureText(nsPresContext* aPresContext,
|
||||
}
|
||||
if (aTextData.mSkipWhitespace) {
|
||||
aTextData.mOffset += contentLen;
|
||||
aTextData.mSkipWhitespace = PR_FALSE;
|
||||
aTextData.mSkipWhitespace = PR_FALSE; // XXXldb Eh?
|
||||
|
||||
if (wasTransformed) {
|
||||
// As long as there were no discarded characters, then don't consider
|
||||
@ -5213,11 +5263,12 @@ nsTextFrame::MeasureText(nsPresContext* aPresContext,
|
||||
} //(aTextData.mMeasureText)
|
||||
}
|
||||
else {
|
||||
PRBool currentWordIsFirstThing = firstThing;
|
||||
firstThing = PR_FALSE;
|
||||
|
||||
aTextData.mSkipWhitespace = PR_FALSE;
|
||||
|
||||
// XXX :first-letter should be handled during frame construction
|
||||
// (and it has a good bit in common with nextBidi)
|
||||
if (aTextData.mFirstLetterOK) {
|
||||
if (IsPunctuationMark(firstChar)) {
|
||||
if (contentLen > 1)
|
||||
@ -5246,7 +5297,7 @@ nsTextFrame::MeasureText(nsPresContext* aPresContext,
|
||||
}
|
||||
else {
|
||||
if (aTs.mSmallCaps) {
|
||||
MeasureSmallCapsText(aReflowState, aTs, bp2, wordLen, PR_FALSE, &dimensions);
|
||||
MeasureSmallCapsText(aReflowState.rendContext, aTs, bp2, wordLen, PR_FALSE, &dimensions);
|
||||
}
|
||||
else {
|
||||
// Measure just the one word
|
||||
@ -5315,24 +5366,10 @@ nsTextFrame::MeasureText(nsPresContext* aPresContext,
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
prevMaxWordWidth = aTextData.mMaxWordWidth;
|
||||
prevAscent = aTextData.mAscent;
|
||||
prevDescent = aTextData.mDescent;
|
||||
|
||||
aTextData.mX += dimensions.width;
|
||||
if (aTextData.mComputeMaxWordWidth) {
|
||||
lastWordWidth = dimensions.width;
|
||||
if (currentWordIsFirstThing) {
|
||||
nscoord incomingWordWidth;
|
||||
if (lineLayout.InWord(&incomingWordWidth)) {
|
||||
lastWordWidth += incomingWordWidth;
|
||||
}
|
||||
}
|
||||
if (lastWordWidth > aTextData.mMaxWordWidth) {
|
||||
aTextData.mMaxWordWidth = lastWordWidth;
|
||||
}
|
||||
}
|
||||
if (aTextData.mAscent < dimensions.ascent) {
|
||||
aTextData.mAscent = dimensions.ascent;
|
||||
}
|
||||
@ -5599,13 +5636,262 @@ nsTextFrame::MeasureText(nsPresContext* aPresContext,
|
||||
return rs;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsTextFrame::MarkIntrinsicWidthsDirty()
|
||||
{
|
||||
// Clear the TEXT_OPTIMIZE_RESIZE for the next time around. It'll get
|
||||
// reset late in Reflow.
|
||||
RemoveStateBits(TEXT_OPTIMIZE_RESIZE);
|
||||
|
||||
nsFrame::MarkIntrinsicWidthsDirty();
|
||||
}
|
||||
|
||||
// XXX This should really share more code with the first half of MeasureText.
|
||||
/* virtual */ void
|
||||
nsTextFrame::AddInlineMinWidth(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlineMinWidthData *aData)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsPresContext *presContext = GetPresContext();
|
||||
nsTextStyle ts(presContext, *aRenderingContext, mStyleContext);
|
||||
if (!ts.mFont->mSize)
|
||||
// XXX If font size is zero, we still need to figure out whether we've
|
||||
// got non-whitespace text and whether we end in whitespace.
|
||||
return;
|
||||
|
||||
const nsStyleText *styleText = GetStyleText();
|
||||
PRBool wrapping = styleText->WhiteSpaceCanWrap();
|
||||
PRBool wsSignificant = styleText->WhiteSpaceIsSignificant();
|
||||
PRBool atStart = PR_TRUE;
|
||||
PRBool forceArabicShaping = (ts.mSmallCaps ||
|
||||
(0 != ts.mWordSpacing) ||
|
||||
(0 != ts.mLetterSpacing) ||
|
||||
ts.mJustifying);
|
||||
nsTextTransformer tx(presContext);
|
||||
// Keep the text in ascii if possible. Note that if we're measuring small
|
||||
// caps text then transform to Unicode because the helper function only
|
||||
// accepts Unicode text
|
||||
rv = tx.Init(this, mContent, mContentOffset, forceArabicShaping,
|
||||
!ts.mSmallCaps);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_NOTREACHED("failure initializing text transformer");
|
||||
return;
|
||||
}
|
||||
|
||||
if (aData->trailingTextFrame &&
|
||||
CanBreakBetween(NS_STATIC_CAST(nsTextFrame*, aData->trailingTextFrame),
|
||||
aData->trailingTextFrame->
|
||||
GetStyleText()->WhiteSpaceCanWrap(),
|
||||
this, wrapping,
|
||||
aData->skipWhitespace, // XXX ???
|
||||
nsnull)) // XXX Better to pass real frame
|
||||
{
|
||||
aData->Break(aRenderingContext);
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
union {
|
||||
char* bp1;
|
||||
PRUnichar* bp2;
|
||||
};
|
||||
PRInt32 wordLen, contentLen;
|
||||
#ifdef IBMBIDI
|
||||
// Is this right for this purpose?
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI) ? mContentOffset + mContentLength : -1;
|
||||
#endif // IBMBIDI
|
||||
PRBool isWhitespace, wasTransformed;
|
||||
// XXX Is !aData->skipWhitespace the right criterion for when the
|
||||
// text transformer should capitalize the first letter?
|
||||
bp2 = tx.GetNextWord(!aData->skipWhitespace, &wordLen, &contentLen,
|
||||
&isWhitespace, &wasTransformed);
|
||||
if (!bp2)
|
||||
break;
|
||||
// XXX Watch mContentLength!
|
||||
|
||||
if (isWhitespace) {
|
||||
PRUnichar firstChar;
|
||||
if (tx.TransformedTextIsAscii()) {
|
||||
firstChar = *bp1;
|
||||
} else {
|
||||
firstChar = *bp2;
|
||||
}
|
||||
if ('\n' == firstChar) {
|
||||
aData->Break(aRenderingContext);
|
||||
aData->skipWhitespace = PR_TRUE;
|
||||
aData->trailingWhitespace = 0;
|
||||
} else if (!aData->skipWhitespace || wsSignificant) {
|
||||
atStart = PR_FALSE;
|
||||
nscoord width;
|
||||
if ('\t' == firstChar) {
|
||||
// XXX Need to track column!
|
||||
wordLen = 8;
|
||||
// Apply word spacing to every space derived from a tab
|
||||
width =
|
||||
(ts.mSpaceWidth + ts.mWordSpacing + ts.mLetterSpacing)*wordLen;
|
||||
} else {
|
||||
// Apply word spacing to every space, if there's more than one
|
||||
width =
|
||||
wordLen*(ts.mWordSpacing + ts.mLetterSpacing + ts.mSpaceWidth);// XXX simplistic
|
||||
}
|
||||
aData->currentLine += width;
|
||||
if (wsSignificant) {
|
||||
aData->trailingWhitespace = 0;
|
||||
aData->skipWhitespace = PR_FALSE;
|
||||
} else {
|
||||
aData->trailingWhitespace += width;
|
||||
aData->skipWhitespace = PR_TRUE;
|
||||
}
|
||||
|
||||
if (wrapping) {
|
||||
aData->Break(aRenderingContext);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!atStart && wrapping) {
|
||||
aData->Break(aRenderingContext);
|
||||
}
|
||||
|
||||
atStart = PR_FALSE;
|
||||
|
||||
nsTextDimensions dimensions;
|
||||
if (ts.mSmallCaps) {
|
||||
MeasureSmallCapsText(aRenderingContext, ts, bp2, wordLen, PR_FALSE,
|
||||
&dimensions);
|
||||
} else {
|
||||
if (tx.TransformedTextIsAscii()) {
|
||||
aRenderingContext->GetTextDimensions(bp1, wordLen, dimensions);
|
||||
} else {
|
||||
aRenderingContext->GetTextDimensions(bp2, wordLen, dimensions);
|
||||
}
|
||||
dimensions.width += ts.mLetterSpacing * wordLen;
|
||||
}
|
||||
|
||||
aData->currentLine += dimensions.width;
|
||||
aData->skipWhitespace = PR_FALSE;
|
||||
aData->trailingWhitespace = 0;
|
||||
}
|
||||
}
|
||||
|
||||
aData->trailingTextFrame = this;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsTextFrame::AddInlinePrefWidth(nsIRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlinePrefWidthData *aData)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsPresContext *presContext = GetPresContext();
|
||||
nsTextStyle ts(presContext, *aRenderingContext, mStyleContext);
|
||||
if (!ts.mFont->mSize)
|
||||
// XXX If font size is zero, we still need to figure out whether we've
|
||||
// got non-whitespace text and whether we end in whitespace.
|
||||
return;
|
||||
|
||||
PRBool forceArabicShaping = (ts.mSmallCaps ||
|
||||
(0 != ts.mWordSpacing) ||
|
||||
(0 != ts.mLetterSpacing) ||
|
||||
ts.mJustifying);
|
||||
nsTextTransformer tx(presContext);
|
||||
// Keep the text in ascii if possible. Note that if we're measuring small
|
||||
// caps text then transform to Unicode because the helper function only
|
||||
// accepts Unicode text
|
||||
rv = tx.Init(this, mContent, mContentOffset, forceArabicShaping,
|
||||
!ts.mSmallCaps);
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_NOTREACHED("failure initializing text transformer");
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
union {
|
||||
char* bp1;
|
||||
PRUnichar* bp2;
|
||||
};
|
||||
PRInt32 wordLen = -1, contentLen;
|
||||
#ifdef IBMBIDI
|
||||
// Is this right for this purpose?
|
||||
wordLen = (mState & NS_FRAME_IS_BIDI) ? mContentOffset + mContentLength : -1;
|
||||
#endif // IBMBIDI
|
||||
PRBool isWhitespace, wasTransformed;
|
||||
// XXX Should fix this to use something better than GetNextWord!
|
||||
// XXX Is !aData->skipWhitespace the right criterion for when the
|
||||
// text transformer should capitalize the first letter?
|
||||
bp2 = tx.GetNextWord(!aData->skipWhitespace, &wordLen, &contentLen,
|
||||
&isWhitespace, &wasTransformed);
|
||||
if (!bp2)
|
||||
break;
|
||||
// XXX Watch mContentLength!
|
||||
|
||||
if (isWhitespace) {
|
||||
PRUnichar firstChar;
|
||||
if (tx.TransformedTextIsAscii()) {
|
||||
firstChar = *bp1;
|
||||
} else {
|
||||
firstChar = *bp2;
|
||||
}
|
||||
if ('\n' == firstChar) {
|
||||
aData->Break(aRenderingContext);
|
||||
} else if (!aData->skipWhitespace) {
|
||||
nscoord width;
|
||||
if ('\t' == firstChar) {
|
||||
// XXX Need to track column!
|
||||
wordLen = 8;
|
||||
// Apply word spacing to every space derived from a tab
|
||||
width =
|
||||
(ts.mSpaceWidth + ts.mWordSpacing + ts.mLetterSpacing)*wordLen;
|
||||
} else {
|
||||
// Apply word spacing to every space, if there's more than one
|
||||
width =
|
||||
wordLen*(ts.mWordSpacing + ts.mLetterSpacing + ts.mSpaceWidth);// XXX simplistic
|
||||
}
|
||||
aData->currentLine += width;
|
||||
if (GetStyleText()->WhiteSpaceIsSignificant())
|
||||
// XXX Should we also subtract the old value of
|
||||
// trailingWhitespace from currentLine?
|
||||
aData->trailingWhitespace = 0;
|
||||
else
|
||||
aData->trailingWhitespace += width;
|
||||
}
|
||||
} else {
|
||||
nsTextDimensions dimensions;
|
||||
if (ts.mSmallCaps) {
|
||||
MeasureSmallCapsText(aRenderingContext, ts, bp2, wordLen, PR_FALSE,
|
||||
&dimensions);
|
||||
} else {
|
||||
if (tx.TransformedTextIsAscii()) {
|
||||
aRenderingContext->GetTextDimensions(bp1, wordLen, dimensions);
|
||||
} else {
|
||||
aRenderingContext->GetTextDimensions(bp2, wordLen, dimensions);
|
||||
}
|
||||
dimensions.width += ts.mLetterSpacing * wordLen;
|
||||
}
|
||||
|
||||
aData->currentLine += dimensions.width;
|
||||
aData->skipWhitespace = PR_FALSE;
|
||||
aData->trailingWhitespace = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* virtual */ nsSize
|
||||
nsTextFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
|
||||
nsSize aCBSize, nscoord aAvailableWidth,
|
||||
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
||||
PRBool aShrinkWrap)
|
||||
{
|
||||
// Inlines and text don't compute size before reflow.
|
||||
return nsSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aMetrics,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("nsTextFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("nsTextFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);
|
||||
#ifdef NOISY_REFLOW
|
||||
ListTag(stdout);
|
||||
@ -5624,9 +5910,6 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
aMetrics.height = 0;
|
||||
aMetrics.ascent = 0;
|
||||
aMetrics.descent = 0;
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.mMaxElementWidth = 0;
|
||||
}
|
||||
#ifdef MOZ_MATHML
|
||||
if (NS_REFLOW_CALC_BOUNDING_METRICS & aMetrics.mFlags)
|
||||
aMetrics.mBoundingMetrics.Clear();
|
||||
@ -5664,6 +5947,7 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
(hints & NS_RENDERING_HINT_ARABIC_SHAPING) == NS_RENDERING_HINT_ARABIC_SHAPING) ||
|
||||
(eCharType_RightToLeft == charType &&
|
||||
(hints & NS_RENDERING_HINT_BIDI_REORDERING) == NS_RENDERING_HINT_BIDI_REORDERING)) {
|
||||
// XXXldb This needs to happen before |Reflow|.
|
||||
aPresContext->SetIsBidiSystem(PR_TRUE);
|
||||
}
|
||||
}
|
||||
@ -5732,8 +6016,8 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
PRBool measureText = PR_TRUE;
|
||||
|
||||
// We can avoid actually measuring the text if:
|
||||
// - this is a resize reflow
|
||||
// - we're not dirty (see CharacterDataChanged() function)
|
||||
// - intrinsic widths haven't been marked dirty (which clears
|
||||
// TEXT_OPTIMIZE_RESIZE)
|
||||
// - we don't have a next in flow
|
||||
// - the previous reflow successfully reflowed all text in the
|
||||
// available space
|
||||
@ -5745,44 +6029,38 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
// we're not wrapping text and we're at the same column as before (this is
|
||||
// an issue for preformatted tabbed text only)
|
||||
// - AND we aren't justified (in which case the frame width has already been tweaked and can't be used)
|
||||
if ((eReflowReason_Resize == aReflowState.reason) &&
|
||||
(0 == (mState & NS_FRAME_IS_DIRTY))) {
|
||||
|
||||
nscoord realWidth = mRect.width;
|
||||
if (mState & TEXT_TRIMMED_WS) {
|
||||
// NOTE: Trailing whitespace includes word and letter spacing!
|
||||
realWidth += ts.mSpaceWidth + ts.mWordSpacing + ts.mLetterSpacing;
|
||||
}
|
||||
if (!GetNextInFlow() &&
|
||||
(mState & TEXT_OPTIMIZE_RESIZE) &&
|
||||
!aMetrics.mComputeMEW &&
|
||||
lineLayout.GetForcedBreakPosition(GetContent()) == -1 &&
|
||||
(lastTimeWeSkippedLeadingWS == skipWhitespace) &&
|
||||
((wrapping && (maxWidth >= realWidth)) ||
|
||||
(!wrapping && (prevColumn == column))) &&
|
||||
nscoord realWidth = mRect.width;
|
||||
if (mState & TEXT_TRIMMED_WS) {
|
||||
// NOTE: Trailing whitespace includes word and letter spacing!
|
||||
realWidth += ts.mSpaceWidth + ts.mWordSpacing + ts.mLetterSpacing;
|
||||
}
|
||||
if (!GetNextInFlow() &&
|
||||
(mState & TEXT_OPTIMIZE_RESIZE) &&
|
||||
lineLayout.GetForcedBreakPosition(GetContent()) == -1 &&
|
||||
(lastTimeWeSkippedLeadingWS == skipWhitespace) &&
|
||||
((wrapping && (maxWidth >= realWidth)) ||
|
||||
(!wrapping && (prevColumn == column))) &&
|
||||
#ifdef IBMBIDI
|
||||
(0 == (mState & NS_FRAME_IS_BIDI) ) &&
|
||||
(0 == (mState & NS_FRAME_IS_BIDI) ) &&
|
||||
#endif // IBMBIDI
|
||||
!ts.mJustifying) {
|
||||
// We can skip measuring of text and use the value from our
|
||||
// previous reflow
|
||||
measureText = PR_FALSE;
|
||||
!ts.mJustifying) {
|
||||
// We can skip measuring of text and use the value from our
|
||||
// previous reflow
|
||||
measureText = PR_FALSE;
|
||||
#ifdef NOISY_REFLOW
|
||||
printf(" => measureText=%s wrapping=%s skipWhitespace=%s",
|
||||
measureText ? "yes" : "no",
|
||||
wrapping ? "yes" : "no",
|
||||
skipWhitespace ? "yes" : "no");
|
||||
printf(" realWidth=%d maxWidth=%d\n",
|
||||
realWidth, maxWidth);
|
||||
printf(" => measureText=%s wrapping=%s skipWhitespace=%s",
|
||||
measureText ? "yes" : "no",
|
||||
wrapping ? "yes" : "no",
|
||||
skipWhitespace ? "yes" : "no");
|
||||
printf(" realWidth=%d maxWidth=%d\n",
|
||||
realWidth, maxWidth);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// Local state passed to the routines that do the actual text measurement
|
||||
TextReflowData textData(startingOffset, wrapping, skipWhitespace,
|
||||
measureText, inWord, lineLayout.GetFirstLetterStyleOK(),
|
||||
lineLayout.LineIsBreakable(), aMetrics.mComputeMEW,
|
||||
PR_FALSE);
|
||||
lineLayout.LineIsBreakable(), PR_FALSE);
|
||||
|
||||
// Measure the text
|
||||
// MeasureText may set TEXT_TRIMMED_WS flag, so don't clear after the call
|
||||
@ -5816,12 +6094,6 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
aMetrics.height = aMetrics.ascent + aMetrics.descent;
|
||||
}
|
||||
mAscent = aMetrics.ascent;
|
||||
if (!wrapping) {
|
||||
textData.mMaxWordWidth = textData.mX;
|
||||
}
|
||||
if (aMetrics.mComputeMEW) {
|
||||
aMetrics.mMaxElementWidth = textData.mMaxWordWidth;
|
||||
}
|
||||
|
||||
// Set content offset and length
|
||||
mContentOffset = startingOffset;
|
||||
@ -5922,12 +6194,11 @@ nsTextFrame::Reflow(nsPresContext* aPresContext,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsTextFrame::CanContinueTextRun(PRBool& aContinueTextRun) const
|
||||
/* virtual */ PRBool
|
||||
nsTextFrame::CanContinueTextRun() const
|
||||
{
|
||||
// We can continue a text run through a text frame
|
||||
aContinueTextRun = PR_TRUE;
|
||||
return NS_OK;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@ -6040,6 +6311,14 @@ nsTextFrame::GetType() const
|
||||
return nsLayoutAtoms::textFrame;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsTextFrame::IsFrameOfType(PRUint32 aFlags) const
|
||||
{
|
||||
// Set the frame state bit for text frames to mark them as replaced.
|
||||
// XXX kipp: temporary
|
||||
return !(aFlags & ~(eReplaced));
|
||||
}
|
||||
|
||||
/* virtual */ PRBool
|
||||
nsTextFrame::IsEmpty()
|
||||
{
|
||||
|
@ -48,7 +48,6 @@
|
||||
#include "nsIScrollableFrame.h"
|
||||
#include "nsIDeviceContext.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsDisplayList.h"
|
||||
|
||||
@ -58,6 +57,14 @@ NS_NewViewportFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
return new (aPresShell) ViewportFrame(aContext);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ViewportFrame::Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* aPrevInFlow)
|
||||
{
|
||||
return Super::Init(aContent, aParent, aPrevInFlow);
|
||||
}
|
||||
|
||||
void
|
||||
ViewportFrame::Destroy()
|
||||
{
|
||||
@ -185,6 +192,36 @@ ViewportFrame::GetFirstChild(nsIAtom* aListName) const
|
||||
return nsContainerFrame::GetFirstChild(aListName);
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
ViewportFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_MIN_WIDTH(this, result);
|
||||
if (mFrames.IsEmpty())
|
||||
result = 0;
|
||||
else
|
||||
result = mFrames.FirstChild()->GetMinWidth(aRenderingContext);
|
||||
|
||||
// XXXldb Deal with mFixedContainer (matters for SizeToContent)!
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
ViewportFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
|
||||
{
|
||||
nscoord result;
|
||||
DISPLAY_PREF_WIDTH(this, result);
|
||||
if (mFrames.IsEmpty())
|
||||
result = 0;
|
||||
else
|
||||
result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
|
||||
|
||||
// XXXldb Deal with mFixedContainer (matters for SizeToContent)!
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
nsPoint
|
||||
ViewportFrame::AdjustReflowStateForScrollbars(nsHTMLReflowState* aReflowState) const
|
||||
{
|
||||
@ -213,14 +250,17 @@ ViewportFrame::Reflow(nsPresContext* aPresContext,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
nsReflowStatus& aStatus)
|
||||
{
|
||||
DO_GLOBAL_REFLOW_COUNT("ViewportFrame", aReflowState.reason);
|
||||
DO_GLOBAL_REFLOW_COUNT("ViewportFrame");
|
||||
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
||||
NS_FRAME_TRACE_REFLOW_IN("ViewportFrame::Reflow");
|
||||
NS_PRECONDITION(!aDesiredSize.mComputeMEW, "unexpected request");
|
||||
|
||||
// Initialize OUT parameters
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
|
||||
// Because |Reflow| sets mComputedHeight on the child to
|
||||
// availableHeight.
|
||||
AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
|
||||
|
||||
// Reflow the main content first so that the placeholders of the
|
||||
// fixed-position frames will be in the right places on an initial
|
||||
// reflow.
|
||||
@ -231,11 +271,13 @@ ViewportFrame::Reflow(nsPresContext* aPresContext,
|
||||
if (mFrames.NotEmpty()) {
|
||||
// Deal with a non-incremental reflow or an incremental reflow
|
||||
// targeted at our one-and-only principal child frame.
|
||||
if (eReflowReason_Incremental != aReflowState.reason ||
|
||||
aReflowState.path->HasChild(mFrames.FirstChild())) {
|
||||
if (aReflowState.ShouldReflowAllKids() ||
|
||||
aReflowState.mFlags.mVResize ||
|
||||
(mFrames.FirstChild()->GetStateBits() &
|
||||
(NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN))) {
|
||||
// Reflow our one-and-only principal child frame
|
||||
nsIFrame* kidFrame = mFrames.FirstChild();
|
||||
nsHTMLReflowMetrics kidDesiredSize(nsnull);
|
||||
nsHTMLReflowMetrics kidDesiredSize;
|
||||
nsSize availableSpace(aReflowState.availableWidth,
|
||||
aReflowState.availableHeight);
|
||||
nsHTMLReflowState kidReflowState(aPresContext, aReflowState,
|
||||
@ -252,24 +294,18 @@ ViewportFrame::Reflow(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
// If we were flowed initially at both an unconstrained width and height,
|
||||
// this is a hint that we should return our child's intrinsic size.
|
||||
if ((eReflowReason_Initial == aReflowState.reason ||
|
||||
eReflowReason_Resize == aReflowState.reason) &&
|
||||
aReflowState.availableWidth == NS_UNCONSTRAINEDSIZE &&
|
||||
aReflowState.availableHeight == NS_UNCONSTRAINEDSIZE) {
|
||||
aDesiredSize.width = kidRect.width;
|
||||
aDesiredSize.height = kidRect.height;
|
||||
aDesiredSize.ascent = kidRect.height;
|
||||
aDesiredSize.descent = 0;
|
||||
}
|
||||
else {
|
||||
// Return the max size as our desired size
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
aDesiredSize.height = aReflowState.availableHeight;
|
||||
aDesiredSize.ascent = aReflowState.availableHeight;
|
||||
aDesiredSize.descent = 0;
|
||||
}
|
||||
NS_ASSERTION(aReflowState.availableWidth != NS_UNCONSTRAINEDSIZE,
|
||||
"shouldn't happen anymore");
|
||||
|
||||
// Return the max size as our desired size
|
||||
aDesiredSize.width = aReflowState.availableWidth;
|
||||
// Being flowed initially at an unconstrained height means we should
|
||||
// return our child's intrinsic size.
|
||||
aDesiredSize.height = aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE
|
||||
? aReflowState.availableHeight
|
||||
: kidRect.height;
|
||||
aDesiredSize.ascent = aDesiredSize.height;
|
||||
aDesiredSize.descent = 0;
|
||||
|
||||
// Make a copy of the reflow state and change the computed width and height
|
||||
// to reflect the available space for the fixed items
|
||||
@ -284,34 +320,14 @@ ViewportFrame::Reflow(nsPresContext* aPresContext,
|
||||
"scrollbars in odd positions");
|
||||
#endif
|
||||
|
||||
nsReflowType reflowType = eReflowType_ContentChanged;
|
||||
if (aReflowState.path) {
|
||||
// XXXwaterson this is more restrictive than the previous code
|
||||
// was: it insists that the UserDefined reflow be targeted at
|
||||
// _this_ frame.
|
||||
nsHTMLReflowCommand *command = aReflowState.path->mReflowCommand;
|
||||
if (command)
|
||||
command->GetType(reflowType);
|
||||
}
|
||||
|
||||
if (reflowType != eReflowType_UserDefined &&
|
||||
aReflowState.reason == eReflowReason_Incremental) {
|
||||
// Incremental reflow
|
||||
mFixedContainer.IncrementalReflow(this, aPresContext, reflowState,
|
||||
reflowState.mComputedWidth,
|
||||
reflowState.mComputedHeight);
|
||||
}
|
||||
|
||||
// Just reflow all the fixed-pos frames.
|
||||
rv = mFixedContainer.Reflow(this, aPresContext, reflowState,
|
||||
reflowState.mComputedWidth,
|
||||
reflowState.mComputedHeight);
|
||||
reflowState.mComputedHeight,
|
||||
PR_TRUE, PR_TRUE); // XXX could be optimized
|
||||
|
||||
// If this is an initial reflow, resize reflow, or style change reflow
|
||||
// then do a repaint
|
||||
if ((eReflowReason_Initial == aReflowState.reason) ||
|
||||
(eReflowReason_Resize == aReflowState.reason) ||
|
||||
(eReflowReason_StyleChange == aReflowState.reason)) {
|
||||
// If we were dirty then do a repaint
|
||||
if (GetStateBits() & NS_FRAME_IS_DIRTY) {
|
||||
nsRect damageRect(0, 0, aDesiredSize.width, aDesiredSize.height);
|
||||
Invalidate(damageRect, PR_FALSE);
|
||||
}
|
||||
|
@ -46,7 +46,6 @@
|
||||
#include "nsContainerFrame.h"
|
||||
#include "nsLayoutAtoms.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsReflowPath.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsAbsoluteContainingBlock.h"
|
||||
|
||||
@ -67,11 +66,17 @@ public:
|
||||
*/
|
||||
class ViewportFrame : public nsContainerFrame {
|
||||
public:
|
||||
typedef nsContainerFrame Super;
|
||||
|
||||
ViewportFrame(nsStyleContext* aContext) : nsContainerFrame(aContext) {}
|
||||
virtual ~ViewportFrame() { } // useful for debugging
|
||||
|
||||
virtual void Destroy();
|
||||
|
||||
NS_IMETHOD Init(nsIContent* aContent,
|
||||
nsIFrame* aParent,
|
||||
nsIFrame* asPrevInFlow);
|
||||
|
||||
NS_IMETHOD SetInitialChildList(nsIAtom* aListName,
|
||||
nsIFrame* aChildList);
|
||||
|
||||
@ -93,6 +98,8 @@ public:
|
||||
const nsRect& aDirtyRect,
|
||||
const nsDisplayListSet& aLists);
|
||||
|
||||
virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
|
||||
virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
|
||||
NS_IMETHOD Reflow(nsPresContext* aPresContext,
|
||||
nsHTMLReflowMetrics& aDesiredSize,
|
||||
const nsHTMLReflowState& aReflowState,
|
||||
|
@ -116,9 +116,6 @@ nsMathMLContainerFrame::ReflowError(nsIRenderingContext& aRenderingContext,
|
||||
aDesiredSize.height = aDesiredSize.ascent + aDesiredSize.descent;
|
||||
aDesiredSize.width = mBoundingMetrics.width;
|
||||
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = aDesiredSize.width;
|
||||
}
|
||||
// Also return our bounding metrics
|
||||
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
|
||||
|
||||
@ -221,7 +218,7 @@ nsMathMLContainerFrame::GetPreferredStretchSize(nsIRenderingContext& aRenderingC
|
||||
}
|
||||
else if (aOptions & STRETCH_CONSIDER_EMBELLISHMENTS) {
|
||||
// compute our up-to-date size using Place()
|
||||
nsHTMLReflowMetrics metrics(nsnull);
|
||||
nsHTMLReflowMetrics metrics;
|
||||
Place(aRenderingContext, PR_FALSE, metrics);
|
||||
aPreferredStretchSize = metrics.mBoundingMetrics;
|
||||
}
|
||||
@ -520,9 +517,6 @@ nsMathMLContainerFrame::FinalizeReflow(nsIRenderingContext& aRenderingContext,
|
||||
aDesiredSize);
|
||||
}
|
||||
}
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = aDesiredSize.width;
|
||||
}
|
||||
// Also return our bounding metrics
|
||||
aDesiredSize.mBoundingMetrics = mBoundingMetrics;
|
||||
|
||||
@ -823,6 +817,7 @@ nsMathMLContainerFrame::ReLayoutChildren(nsIFrame* aParentFrame)
|
||||
NS_ASSERTION(content, "dangling frame without a content node");
|
||||
if (!content)
|
||||
break;
|
||||
// XXXldb This should check namespaces too.
|
||||
if (content->Tag() == nsMathMLAtoms::math)
|
||||
break;
|
||||
|
||||
@ -857,7 +852,8 @@ nsMathMLContainerFrame::ReLayoutChildren(nsIFrame* aParentFrame)
|
||||
if (!parent)
|
||||
return NS_OK;
|
||||
|
||||
return parent->ReflowDirtyChild(frame->GetPresContext()->PresShell(), frame);
|
||||
return frame->GetPresContext()->PresShell()->
|
||||
FrameNeedsReflow(frame, nsIPresShell::eStyleChange);
|
||||
}
|
||||
|
||||
// There are precise rules governing children of a MathML frame,
|
||||
@ -937,32 +933,9 @@ nsMathMLContainerFrame::AttributeChanged(PRInt32 aNameSpaceID,
|
||||
|
||||
// XXX Since they are numerous MathML attributes that affect layout, and
|
||||
// we can't check all of them here, play safe by requesting a reflow.
|
||||
return ReflowDirtyChild(GetPresContext()->PresShell(), nsnull);
|
||||
}
|
||||
|
||||
// We are an inline frame, so we handle dirty request like nsInlineFrame
|
||||
NS_IMETHODIMP
|
||||
nsMathMLContainerFrame::ReflowDirtyChild(nsIPresShell* aPresShell, nsIFrame* aChild)
|
||||
{
|
||||
// The inline container frame does not handle the reflow
|
||||
// request. It passes it up to its parent container.
|
||||
|
||||
// If you don't already have dirty children,
|
||||
if (!(mState & NS_FRAME_HAS_DIRTY_CHILDREN)) {
|
||||
if (mParent) {
|
||||
// Record that you are dirty and have dirty children
|
||||
mState |= NS_FRAME_IS_DIRTY;
|
||||
mState |= NS_FRAME_HAS_DIRTY_CHILDREN;
|
||||
|
||||
// Pass the reflow request up to the parent
|
||||
mParent->ReflowDirtyChild(aPresShell, (nsIFrame*) this);
|
||||
}
|
||||
else {
|
||||
NS_ASSERTION(0, "No parent to pass the reflow request up to.");
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
// XXXldb This should only do work for attributes that cause changes!
|
||||
return GetPresContext()->PresShell()->
|
||||
FrameNeedsReflow(this, nsIPresShell::eStyleChange);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -1011,8 +984,8 @@ nsMathMLContainerFrame::ReflowForeignChild(nsIFrame* aChildFrame,
|
||||
|
||||
// provide a local, self-contained linelayout where to reflow the nsInlineFrame
|
||||
nsSize availSize(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
|
||||
nsLineLayout ll(aPresContext, aReflowState.mSpaceManager, aReflowState.parentReflowState,
|
||||
aDesiredSize.mComputeMEW);
|
||||
nsLineLayout ll(aPresContext, aReflowState.mSpaceManager,
|
||||
aReflowState.parentReflowState);
|
||||
ll.BeginLineReflow(0, 0, availSize.width, availSize.height, PR_FALSE, PR_FALSE);
|
||||
PRBool pushedFrame;
|
||||
ll.ReflowFrame(aChildFrame, aStatus, &aDesiredSize, pushedFrame);
|
||||
@ -1044,33 +1017,18 @@ nsMathMLContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
aDesiredSize.ascent = aDesiredSize.descent = 0;
|
||||
aDesiredSize.mBoundingMetrics.Clear();
|
||||
|
||||
// See if this is an incremental reflow
|
||||
if (aReflowState.reason == eReflowReason_Incremental) {
|
||||
#ifdef MATHML_NOISY_INCREMENTAL_REFLOW
|
||||
printf("nsMathMLContainerFrame::Reflow:IncrementalReflow received by: ");
|
||||
nsFrame::ListTag(stdout, this);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
/////////////
|
||||
// Reflow children
|
||||
// Asking each child to cache its bounding metrics
|
||||
|
||||
nsReflowStatus childStatus;
|
||||
nsSize availSize(aReflowState.mComputedWidth, aReflowState.mComputedHeight);
|
||||
nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mComputeMEW,
|
||||
nsHTMLReflowMetrics childDesiredSize(
|
||||
aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS);
|
||||
nsIFrame* childFrame = mFrames.FirstChild();
|
||||
while (childFrame) {
|
||||
nsReflowReason reason = aReflowState.reason;
|
||||
if (childFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)
|
||||
reason = eReflowReason_Initial;
|
||||
else if (aReflowState.path && aReflowState.path->mReflowCommand &&
|
||||
aReflowState.path->mReflowCommand->Type() == eReflowType_StyleChanged)
|
||||
reason = eReflowReason_StyleChange;
|
||||
nsHTMLReflowState childReflowState(aPresContext, aReflowState,
|
||||
childFrame, availSize, reason);
|
||||
childFrame, availSize);
|
||||
rv = ReflowChild(childFrame, aPresContext, childDesiredSize,
|
||||
childReflowState, childStatus);
|
||||
//NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status");
|
||||
@ -1129,10 +1087,6 @@ printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (aDesiredSize.mComputeMEW) {
|
||||
aDesiredSize.mMaxElementWidth = childDesiredSize.mMaxElementWidth;
|
||||
}
|
||||
|
||||
/////////////
|
||||
// Place children now by re-adjusting the origins to align the baselines
|
||||
FinalizeReflow(*aReflowState.rendContext, aDesiredSize);
|
||||
@ -1270,7 +1224,7 @@ nsMathMLContainerFrame::Place(nsIRenderingContext& aRenderingContext,
|
||||
|
||||
PRInt32 count = 0;
|
||||
PRInt32 carrySpace = 0;
|
||||
nsHTMLReflowMetrics childSize (nsnull);
|
||||
nsHTMLReflowMetrics childSize;
|
||||
nsBoundingMetrics bmChild;
|
||||
nscoord leftCorrection = 0, italicCorrection = 0;
|
||||
eMathMLFrameType fromFrameType = eMathMLFrameType_UNKNOWN;
|
||||
@ -1409,6 +1363,7 @@ nsMathMLContainerFrame::FixInterFrameSpacing(nsHTMLReflowMetrics& aDesiredSize)
|
||||
{
|
||||
nscoord gap = 0;
|
||||
nsIContent* parentContent = mParent->GetContent();
|
||||
// XXXldb This should check namespaces too.
|
||||
nsIAtom *parentTag = parentContent->Tag();
|
||||
if (parentTag == nsMathMLAtoms::math ||
|
||||
parentTag == nsMathMLAtoms::mtd_) {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user