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:
dbaron%dbaron.org 2006-12-08 05:38:33 +00:00
parent cd352c37e1
commit 31f1898810
201 changed files with 8730 additions and 18257 deletions

View File

@ -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")

View File

@ -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.

View File

@ -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

View File

@ -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;
}

View File

@ -57,7 +57,6 @@ struct nsFrameItems;
struct nsAbsoluteItems;
struct nsTableCreator;
class nsStyleContext;
struct nsTableList;
struct nsStyleContent;
struct nsStyleDisplay;
class nsIPresShell;

View File

@ -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));

View File

@ -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);
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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__

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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));
}

View File

@ -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;
/**

View File

@ -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)
{

View File

@ -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();
//
//-------------------------------------------------------------------------------------

View File

@ -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,

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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));
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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___ */

View File

@ -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)

View File

@ -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;

View File

@ -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 \

View File

@ -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;
}

View File

@ -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:

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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___ */

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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)) {

View File

@ -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

View File

@ -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 = &ll;
@ -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

View File

@ -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

View File

@ -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",

View File

@ -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;
}

View File

@ -148,6 +148,9 @@ public:
nsReflowStatus& aStatus);
virtual nsIAtom* GetType() const;
#ifdef DEBUG
NS_IMETHOD GetFrameName(nsAString& aResult) const;
#endif
virtual PRBool IsLeaf() const;

View File

@ -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);
}
}
}

View File

@ -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___ */

View File

@ -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

View File

@ -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;

View File

@ -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"

View File

@ -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

View File

@ -42,8 +42,6 @@
#include "nscore.h"
#include "nsISupports.h"
#include "nsReflowType.h"
class nsHTMLReflowCommand;
class nsIAtom;
class nsNodeInfoManager;
class nsIContent;

View File

@ -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;
}

View File

@ -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___ */

View File

@ -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

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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);
}

View File

@ -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.

View File

@ -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);
}

View File

@ -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___ */

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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__

View File

@ -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( &ltime );
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( &ltime );
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;

View File

@ -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

View File

@ -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()
{

View File

@ -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);
}

View File

@ -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,

View File

@ -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