2001-09-29 00:14:13 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2005-10-28 23:49:51 +04:00
|
|
|
/* vim: set ts=2 sw=2 et tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
1999-02-12 20:45:58 +03:00
|
|
|
#include "nsCOMPtr.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
#include "nsTableFrame.h"
|
2011-04-08 05:04:40 +04:00
|
|
|
#include "nsRenderingContext.h"
|
2003-02-22 03:32:13 +03:00
|
|
|
#include "nsStyleContext.h"
|
1999-09-02 04:07:14 +04:00
|
|
|
#include "nsStyleConsts.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
#include "nsIContent.h"
|
|
|
|
#include "nsCellMap.h"
|
|
|
|
#include "nsTableCellFrame.h"
|
1998-09-15 21:58:24 +04:00
|
|
|
#include "nsHTMLParts.h"
|
1998-06-05 06:36:25 +04:00
|
|
|
#include "nsTableColFrame.h"
|
1998-06-17 20:38:24 +04:00
|
|
|
#include "nsTableColGroupFrame.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
#include "nsTableRowFrame.h"
|
|
|
|
#include "nsTableRowGroupFrame.h"
|
1998-09-30 03:15:01 +04:00
|
|
|
#include "nsTableOuterFrame.h"
|
2004-03-09 09:48:35 +03:00
|
|
|
#include "nsTablePainter.h"
|
1998-04-30 21:57:09 +04:00
|
|
|
|
|
|
|
#include "BasicTableLayoutStrategy.h"
|
1998-09-30 03:15:01 +04:00
|
|
|
#include "FixedTableLayoutStrategy.h"
|
1998-04-30 21:57:09 +04:00
|
|
|
|
2004-08-01 03:15:21 +04:00
|
|
|
#include "nsPresContext.h"
|
1998-04-14 00:24:54 +04:00
|
|
|
#include "nsCSSRendering.h"
|
2007-01-30 03:06:41 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2006-12-26 20:47:52 +03:00
|
|
|
#include "nsCSSAnonBoxes.h"
|
1999-02-24 07:03:50 +03:00
|
|
|
#include "nsIPresShell.h"
|
1999-08-01 02:11:50 +04:00
|
|
|
#include "nsIDOMElement.h"
|
1999-08-24 08:17:05 +04:00
|
|
|
#include "nsIDOMHTMLElement.h"
|
|
|
|
#include "nsIDOMHTMLBodyElement.h"
|
2004-02-24 00:29:06 +03:00
|
|
|
#include "nsFrameManager.h"
|
2012-07-27 18:03:27 +04:00
|
|
|
#include "nsError.h"
|
2003-02-22 03:32:13 +03:00
|
|
|
#include "nsAutoPtr.h"
|
2004-01-22 02:05:10 +03:00
|
|
|
#include "nsCSSFrameConstructor.h"
|
2004-01-28 03:18:22 +03:00
|
|
|
#include "nsStyleSet.h"
|
2006-01-26 05:29:17 +03:00
|
|
|
#include "nsDisplayList.h"
|
2009-12-14 06:40:55 +03:00
|
|
|
#include "nsIScrollableFrame.h"
|
2010-04-03 05:58:26 +04:00
|
|
|
#include "nsCSSProps.h"
|
2012-10-26 17:32:10 +04:00
|
|
|
#include "mozilla/Likely.h"
|
2000-01-28 05:19:45 +03:00
|
|
|
|
2010-03-29 05:46:55 +04:00
|
|
|
using namespace mozilla;
|
2012-01-25 05:21:29 +04:00
|
|
|
using namespace mozilla::layout;
|
2010-03-29 05:46:55 +04:00
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
/********************************************************************************
|
|
|
|
** nsTableReflowState **
|
|
|
|
********************************************************************************/
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
struct nsTableReflowState {
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
// the real reflow state
|
1998-10-02 08:10:00 +04:00
|
|
|
const nsHTMLReflowState& reflowState;
|
1998-05-30 00:36:05 +04:00
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
// The table's available size
|
1998-04-14 00:24:54 +04:00
|
|
|
nsSize availSize;
|
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
// Stationary x-offset
|
|
|
|
nscoord x;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
// Running y-offset
|
|
|
|
nscoord y;
|
|
|
|
|
2009-02-18 22:47:22 +03:00
|
|
|
nsTableReflowState(nsPresContext& aPresContext,
|
2002-02-19 18:48:28 +03:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
2001-03-13 09:38:59 +03:00
|
|
|
nsTableFrame& aTableFrame,
|
|
|
|
nscoord aAvailWidth,
|
|
|
|
nscoord aAvailHeight)
|
|
|
|
: reflowState(aReflowState)
|
|
|
|
{
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
Init(aPresContext, aTableFrame, aAvailWidth, aAvailHeight);
|
2001-03-13 09:38:59 +03:00
|
|
|
}
|
1999-08-03 18:26:00 +04:00
|
|
|
|
2009-02-18 22:47:22 +03:00
|
|
|
void Init(nsPresContext& aPresContext,
|
2002-02-19 18:48:28 +03:00
|
|
|
nsTableFrame& aTableFrame,
|
2001-03-13 09:38:59 +03:00
|
|
|
nscoord aAvailWidth,
|
|
|
|
nscoord aAvailHeight)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2001-03-13 09:38:59 +03:00
|
|
|
nsTableFrame* table = (nsTableFrame*)aTableFrame.GetFirstInFlow();
|
2003-12-28 20:02:40 +03:00
|
|
|
nsMargin borderPadding = table->GetChildAreaOffset(&reflowState);
|
2004-03-09 09:48:35 +03:00
|
|
|
nscoord cellSpacingX = table->GetCellSpacingX();
|
2000-01-03 01:55:48 +03:00
|
|
|
|
2004-03-09 09:48:35 +03:00
|
|
|
x = borderPadding.left + cellSpacingX;
|
|
|
|
y = borderPadding.top; //cellspacing added during reflow
|
2001-03-13 09:38:59 +03:00
|
|
|
|
|
|
|
availSize.width = aAvailWidth;
|
|
|
|
if (NS_UNCONSTRAINEDSIZE != availSize.width) {
|
2004-03-09 09:48:35 +03:00
|
|
|
availSize.width -= borderPadding.left + borderPadding.right
|
|
|
|
+ (2 * cellSpacingX);
|
2009-09-16 19:01:36 +04:00
|
|
|
availSize.width = NS_MAX(0, availSize.width);
|
1998-04-25 22:48:48 +04:00
|
|
|
}
|
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
availSize.height = aAvailHeight;
|
|
|
|
if (NS_UNCONSTRAINEDSIZE != availSize.height) {
|
2004-03-09 09:48:35 +03:00
|
|
|
availSize.height -= borderPadding.top + borderPadding.bottom
|
|
|
|
+ (2 * table->GetCellSpacingY());
|
2009-09-16 19:01:36 +04:00
|
|
|
availSize.height = NS_MAX(0, availSize.height);
|
1998-04-25 22:48:48 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
2001-03-13 09:38:59 +03:00
|
|
|
|
2009-02-18 22:47:22 +03:00
|
|
|
nsTableReflowState(nsPresContext& aPresContext,
|
2002-02-19 18:48:28 +03:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
2001-03-13 09:38:59 +03:00
|
|
|
nsTableFrame& aTableFrame)
|
|
|
|
: reflowState(aReflowState)
|
|
|
|
{
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
Init(aPresContext, aTableFrame, aReflowState.availableWidth, aReflowState.availableHeight);
|
2001-03-13 09:38:59 +03:00
|
|
|
}
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
};
|
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
/********************************************************************************
|
|
|
|
** nsTableFrame **
|
|
|
|
********************************************************************************/
|
1999-10-09 03:18:19 +04:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
struct BCPropertyData
|
|
|
|
{
|
2011-10-27 17:58:44 +04:00
|
|
|
BCPropertyData() : mTopBorderWidth(0), mRightBorderWidth(0),
|
|
|
|
mBottomBorderWidth(0), mLeftBorderWidth(0),
|
|
|
|
mLeftCellBorderWidth(0), mRightCellBorderWidth(0) {}
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect mDamageArea;
|
2005-04-07 22:04:38 +04:00
|
|
|
BCPixelSize mTopBorderWidth;
|
|
|
|
BCPixelSize mRightBorderWidth;
|
|
|
|
BCPixelSize mBottomBorderWidth;
|
|
|
|
BCPixelSize mLeftBorderWidth;
|
2009-02-08 19:46:42 +03:00
|
|
|
BCPixelSize mLeftCellBorderWidth;
|
|
|
|
BCPixelSize mRightCellBorderWidth;
|
2002-02-19 18:48:28 +03:00
|
|
|
};
|
|
|
|
|
2011-09-12 20:08:07 +04:00
|
|
|
nsIFrame*
|
2012-02-15 13:28:21 +04:00
|
|
|
nsTableFrame::GetParentStyleContextFrame() const
|
2002-03-27 05:38:13 +03:00
|
|
|
{
|
|
|
|
// Since our parent, the table outer frame, returned this frame, we
|
|
|
|
// must return whatever our parent would normally have returned.
|
|
|
|
|
|
|
|
NS_PRECONDITION(mParent, "table constructed without outer table");
|
2009-10-30 00:17:56 +03:00
|
|
|
if (!mContent->GetParent() && !GetStyleContext()->GetPseudo()) {
|
2007-05-08 07:59:12 +04:00
|
|
|
// We're the root. We have no style context parent.
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2007-05-08 07:59:12 +04:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2011-09-12 20:08:07 +04:00
|
|
|
return static_cast<nsFrame*>(GetParent())->DoGetParentStyleContextFrame();
|
2002-03-27 05:38:13 +03:00
|
|
|
}
|
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2003-10-31 23:19:18 +03:00
|
|
|
nsIAtom*
|
|
|
|
nsTableFrame::GetType() const
|
1999-02-24 08:54:31 +03:00
|
|
|
{
|
2010-04-27 20:15:01 +04:00
|
|
|
return nsGkAtoms::tableFrame;
|
1999-02-24 08:54:31 +03:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
|
|
|
|
2006-03-27 01:30:36 +04:00
|
|
|
nsTableFrame::nsTableFrame(nsStyleContext* aContext)
|
2011-12-28 00:18:48 +04:00
|
|
|
: nsContainerFrame(aContext),
|
2012-07-30 18:20:58 +04:00
|
|
|
mCellMap(nullptr),
|
|
|
|
mTableLayoutStrategy(nullptr)
|
2001-03-13 09:38:59 +03:00
|
|
|
{
|
2012-01-17 03:38:10 +04:00
|
|
|
memset(&mBits, 0, sizeof(mBits));
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2009-01-12 22:20:59 +03:00
|
|
|
NS_QUERYFRAME_HEAD(nsTableFrame)
|
|
|
|
NS_QUERYFRAME_ENTRY(nsITableLayout)
|
2011-12-28 00:18:48 +04:00
|
|
|
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
|
1999-08-01 02:11:50 +04:00
|
|
|
|
1998-12-05 08:27:21 +03:00
|
|
|
NS_IMETHODIMP
|
2006-03-09 21:55:21 +03:00
|
|
|
nsTableFrame::Init(nsIContent* aContent,
|
1999-01-14 08:16:23 +03:00
|
|
|
nsIFrame* aParent,
|
1999-02-25 06:27:57 +03:00
|
|
|
nsIFrame* aPrevInFlow)
|
1998-12-05 08:27:21 +03:00
|
|
|
{
|
2012-01-17 03:38:10 +04:00
|
|
|
NS_PRECONDITION(!mCellMap, "Init called twice");
|
|
|
|
NS_PRECONDITION(!aPrevInFlow ||
|
|
|
|
aPrevInFlow->GetType() == nsGkAtoms::tableFrame,
|
|
|
|
"prev-in-flow must be of same type");
|
1998-12-05 08:27:21 +03:00
|
|
|
|
1999-02-25 08:31:15 +03:00
|
|
|
// Let the base class do its processing
|
2012-01-17 03:38:10 +04:00
|
|
|
nsresult rv = nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
|
1999-02-25 08:31:15 +03:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
// see if border collapse is on, if so set it
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleTableBorder* tableStyle = GetStyleTableBorder();
|
2011-09-29 10:19:26 +04:00
|
|
|
bool borderCollapse = (NS_STYLE_BORDER_COLLAPSE == tableStyle->mBorderCollapse);
|
2002-02-19 18:48:28 +03:00
|
|
|
SetBorderCollapse(borderCollapse);
|
2012-02-11 01:05:00 +04:00
|
|
|
|
|
|
|
// Transforms need to affect the outer frame, not the inner frame (bug 722777)
|
|
|
|
mState &= ~NS_FRAME_MAY_BE_TRANSFORMED;
|
|
|
|
|
2012-01-17 03:38:10 +04:00
|
|
|
// Create the cell map if this frame is the first-in-flow.
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (!aPrevInFlow) {
|
|
|
|
mCellMap = new nsTableCellMap(*this, borderCollapse);
|
|
|
|
if (!mCellMap)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
|
1999-02-25 08:31:15 +03:00
|
|
|
if (aPrevInFlow) {
|
|
|
|
// set my width, because all frames in a table flow are the same width and
|
|
|
|
// code in nsTableOuterFrame depends on this being set
|
2003-07-07 06:01:29 +04:00
|
|
|
mRect.width = aPrevInFlow->GetSize().width;
|
1999-02-25 08:31:15 +03:00
|
|
|
}
|
2001-03-13 09:38:59 +03:00
|
|
|
else {
|
|
|
|
NS_ASSERTION(!mTableLayoutStrategy, "strategy was created before Init was called");
|
|
|
|
// create the strategy
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (IsAutoLayout())
|
|
|
|
mTableLayoutStrategy = new BasicTableLayoutStrategy(this);
|
|
|
|
else
|
|
|
|
mTableLayoutStrategy = new FixedTableLayoutStrategy(this);
|
|
|
|
if (!mTableLayoutStrategy)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
1999-10-28 08:09:39 +04:00
|
|
|
}
|
|
|
|
|
1999-02-25 08:31:15 +03:00
|
|
|
return rv;
|
1998-12-05 08:27:21 +03:00
|
|
|
}
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
nsTableFrame::~nsTableFrame()
|
|
|
|
{
|
2012-01-17 03:38:10 +04:00
|
|
|
delete mCellMap;
|
|
|
|
delete mTableLayoutStrategy;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2006-04-10 04:16:29 +04:00
|
|
|
void
|
2009-12-24 08:21:15 +03:00
|
|
|
nsTableFrame::DestroyFrom(nsIFrame* aDestructRoot)
|
1998-12-04 06:14:28 +03:00
|
|
|
{
|
2009-12-24 08:21:15 +03:00
|
|
|
mColGroups.DestroyFramesFrom(aDestructRoot);
|
2011-12-28 00:18:48 +04:00
|
|
|
nsContainerFrame::DestroyFrom(aDestructRoot);
|
1998-12-04 06:14:28 +03:00
|
|
|
}
|
|
|
|
|
2001-09-21 04:53:29 +04:00
|
|
|
// Make sure any views are positioned properly
|
2001-03-13 09:38:59 +03:00
|
|
|
void
|
2004-12-27 18:05:18 +03:00
|
|
|
nsTableFrame::RePositionViews(nsIFrame* aFrame)
|
2001-03-13 09:38:59 +03:00
|
|
|
{
|
2004-12-27 18:05:18 +03:00
|
|
|
nsContainerFrame::PositionFrameView(aFrame);
|
|
|
|
nsContainerFrame::PositionChildViews(aFrame);
|
2001-03-13 09:38:59 +03:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2005-02-05 07:23:52 +03:00
|
|
|
IsRepeatedFrame(nsIFrame* kidFrame)
|
|
|
|
{
|
2006-12-26 20:47:52 +03:00
|
|
|
return (kidFrame->GetType() == nsGkAtoms::tableRowFrame ||
|
|
|
|
kidFrame->GetType() == nsGkAtoms::tableRowGroupFrame) &&
|
2005-02-05 07:23:52 +03:00
|
|
|
(kidFrame->GetStateBits() & NS_REPEATED_ROW_OR_ROWGROUP);
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2010-05-13 18:15:49 +04:00
|
|
|
nsTableFrame::PageBreakAfter(nsIFrame* aSourceFrame,
|
2002-03-18 00:35:08 +03:00
|
|
|
nsIFrame* aNextFrame)
|
|
|
|
{
|
2010-05-13 18:15:49 +04:00
|
|
|
const nsStyleDisplay* display = aSourceFrame->GetStyleDisplay();
|
|
|
|
nsTableRowGroupFrame* prevRg = do_QueryFrame(aSourceFrame);
|
2005-02-05 07:23:52 +03:00
|
|
|
// don't allow a page break after a repeated element ...
|
2010-05-27 09:31:11 +04:00
|
|
|
if ((display->mBreakAfter || (prevRg && prevRg->HasInternalBreakAfter())) &&
|
2010-05-13 18:15:49 +04:00
|
|
|
!IsRepeatedFrame(aSourceFrame)) {
|
2005-02-05 07:23:52 +03:00
|
|
|
return !(aNextFrame && IsRepeatedFrame(aNextFrame)); // or before
|
2002-03-18 00:35:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (aNextFrame) {
|
2003-05-15 07:42:21 +04:00
|
|
|
display = aNextFrame->GetStyleDisplay();
|
2005-02-05 07:23:52 +03:00
|
|
|
// don't allow a page break before a repeated element ...
|
2010-05-13 18:15:49 +04:00
|
|
|
nsTableRowGroupFrame* nextRg = do_QueryFrame(aNextFrame);
|
2010-05-27 09:31:11 +04:00
|
|
|
if ((display->mBreakBefore ||
|
|
|
|
(nextRg && nextRg->HasInternalBreakBefore())) &&
|
2010-05-13 18:15:49 +04:00
|
|
|
!IsRepeatedFrame(aNextFrame)) {
|
|
|
|
return !IsRepeatedFrame(aSourceFrame); // or after
|
2002-03-18 00:35:08 +03:00
|
|
|
}
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2002-03-18 00:35:08 +03:00
|
|
|
}
|
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
// XXX this needs to be cleaned up so that the frame constructor breaks out col group
|
2006-06-29 06:32:36 +04:00
|
|
|
// frames into a separate child list, bug 343048.
|
1998-09-16 21:19:20 +04:00
|
|
|
NS_IMETHODIMP
|
2011-08-25 00:54:30 +04:00
|
|
|
nsTableFrame::SetInitialChildList(ChildListID aListID,
|
2009-07-28 16:53:20 +04:00
|
|
|
nsFrameList& aChildList)
|
1998-09-16 21:19:20 +04:00
|
|
|
{
|
1999-01-16 01:52:05 +03:00
|
|
|
|
2006-04-09 22:43:46 +04:00
|
|
|
if (!mFrames.IsEmpty() || !mColGroups.IsEmpty()) {
|
|
|
|
// We already have child frames which means we've already been
|
|
|
|
// initialized
|
|
|
|
NS_NOTREACHED("unexpected second call to SetInitialChildList");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
2011-08-25 00:54:30 +04:00
|
|
|
if (aListID != kPrincipalList) {
|
|
|
|
// All we know about is the principal child list.
|
2006-04-09 22:43:46 +04:00
|
|
|
NS_NOTREACHED("unknown frame list");
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
2010-04-27 20:15:01 +04:00
|
|
|
}
|
2009-07-28 16:53:20 +04:00
|
|
|
|
|
|
|
// XXXbz the below code is an icky cesspit that's only needed in its current
|
|
|
|
// form for two reasons:
|
|
|
|
// 1) Both rowgroups and column groups come in on the principal child list.
|
2009-09-18 15:09:36 +04:00
|
|
|
while (aChildList.NotEmpty()) {
|
2009-07-28 16:53:20 +04:00
|
|
|
nsIFrame* childFrame = aChildList.FirstChild();
|
2009-09-18 15:09:36 +04:00
|
|
|
aChildList.RemoveFirstChild();
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleDisplay* childDisplay = childFrame->GetStyleDisplay();
|
2009-07-28 16:53:20 +04:00
|
|
|
|
2009-09-18 15:09:36 +04:00
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == childDisplay->mDisplay) {
|
2006-12-26 20:47:52 +03:00
|
|
|
NS_ASSERTION(nsGkAtoms::tableColGroupFrame == childFrame->GetType(),
|
2006-06-22 08:19:36 +04:00
|
|
|
"This is not a colgroup");
|
2012-07-30 18:20:58 +04:00
|
|
|
mColGroups.AppendFrame(nullptr, childFrame);
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
2009-09-18 15:09:36 +04:00
|
|
|
else { // row groups and unknown frames go on the main list for now
|
2012-07-30 18:20:58 +04:00
|
|
|
mFrames.AppendFrame(nullptr, childFrame);
|
1998-12-03 21:01:35 +03:00
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
1998-12-03 21:01:35 +03:00
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
// If we have a prev-in-flow, then we're a table that has been split and
|
|
|
|
// so don't treat this like an append
|
2006-02-22 00:33:47 +03:00
|
|
|
if (!GetPrevInFlow()) {
|
1999-12-14 01:56:31 +03:00
|
|
|
// process col groups first so that real cols get constructed before
|
|
|
|
// anonymous ones due to cells in rows.
|
2009-07-30 21:23:32 +04:00
|
|
|
InsertColGroups(0, mColGroups);
|
|
|
|
InsertRowGroups(mFrames);
|
2010-04-27 20:15:01 +04:00
|
|
|
// calc collapsing borders
|
2008-08-04 11:14:39 +04:00
|
|
|
if (IsBorderCollapse()) {
|
2011-10-27 17:58:44 +04:00
|
|
|
SetFullBCDamageArea();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
1999-09-02 04:07:14 +04:00
|
|
|
}
|
|
|
|
|
2006-04-09 22:43:46 +04:00
|
|
|
return NS_OK;
|
1998-09-16 21:19:20 +04:00
|
|
|
}
|
|
|
|
|
2005-02-07 04:58:25 +03:00
|
|
|
void nsTableFrame::AttributeChangedFor(nsIFrame* aFrame,
|
2010-04-27 20:15:01 +04:00
|
|
|
nsIContent* aContent,
|
2000-01-04 08:31:56 +03:00
|
|
|
nsIAtom* aAttribute)
|
|
|
|
{
|
2009-03-25 01:10:06 +03:00
|
|
|
nsTableCellFrame *cellFrame = do_QueryFrame(aFrame);
|
|
|
|
if (cellFrame) {
|
2010-04-27 20:15:01 +04:00
|
|
|
if ((nsGkAtoms::rowspan == aAttribute) ||
|
2006-12-26 20:47:52 +03:00
|
|
|
(nsGkAtoms::colspan == aAttribute)) {
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
2000-01-04 08:31:56 +03:00
|
|
|
if (cellMap) {
|
|
|
|
// for now just remove the cell from the map and reinsert it
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rowIndex, colIndex;
|
2000-01-04 08:31:56 +03:00
|
|
|
cellFrame->GetRowIndex(rowIndex);
|
|
|
|
cellFrame->GetColIndex(colIndex);
|
2005-02-07 04:58:25 +03:00
|
|
|
RemoveCell(cellFrame, rowIndex);
|
2009-02-05 12:09:50 +03:00
|
|
|
nsAutoTArray<nsTableCellFrame*, 1> cells;
|
2000-01-04 08:31:56 +03:00
|
|
|
cells.AppendElement(cellFrame);
|
2005-02-07 04:58:25 +03:00
|
|
|
InsertCells(cells, rowIndex, colIndex - 1);
|
2001-03-13 09:38:59 +03:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
// XXX Should this use eStyleChange? It currently doesn't need
|
|
|
|
// to, but it might given more optimization.
|
2007-05-06 23:16:51 +04:00
|
|
|
PresContext()->PresShell()->
|
|
|
|
FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
|
2000-01-04 08:31:56 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-06-17 20:38:24 +04:00
|
|
|
/* ****** CellMap methods ******* */
|
|
|
|
|
2000-12-19 23:29:46 +03:00
|
|
|
/* return the effective col count */
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nsTableFrame::GetEffectiveColCount() const
|
2000-12-19 23:29:46 +03:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colCount = GetColCount();
|
2008-09-24 21:14:35 +04:00
|
|
|
if (LayoutStrategy()->GetType() == nsITableLayoutStrategy::Auto) {
|
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
|
|
|
if (!cellMap) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
// don't count cols at the end that don't have originating cells
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t colX = colCount - 1; colX >= 0; colX--) {
|
2010-04-27 20:15:01 +04:00
|
|
|
if (cellMap->GetNumCellsOriginatingInCol(colX) > 0) {
|
2008-09-24 21:14:35 +04:00
|
|
|
break;
|
|
|
|
}
|
2000-12-19 23:29:46 +03:00
|
|
|
colCount--;
|
|
|
|
}
|
|
|
|
}
|
1999-07-28 12:09:02 +04:00
|
|
|
return colCount;
|
1998-07-24 20:51:16 +04:00
|
|
|
}
|
1998-07-22 07:53:43 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nsTableFrame::GetIndexOfLastRealCol()
|
2001-05-17 16:40:27 +04:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numCols = mColFrames.Length();
|
2006-09-11 22:27:35 +04:00
|
|
|
if (numCols > 0) {
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t colX = numCols - 1; colX >= 0; colX--) {
|
2006-09-11 22:27:35 +04:00
|
|
|
nsTableColFrame* colFrame = GetColFrame(colX);
|
|
|
|
if (colFrame) {
|
|
|
|
if (eColAnonymousCell != colFrame->GetColType()) {
|
|
|
|
return colX;
|
|
|
|
}
|
2001-05-17 16:40:27 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
return -1;
|
2001-05-17 16:40:27 +04:00
|
|
|
}
|
1998-07-22 07:53:43 +04:00
|
|
|
|
2004-05-03 22:31:34 +04:00
|
|
|
nsTableColFrame*
|
2012-08-22 19:56:38 +04:00
|
|
|
nsTableFrame::GetColFrame(int32_t aColIndex) const
|
1998-07-11 04:00:31 +04:00
|
|
|
{
|
2006-02-22 00:33:47 +03:00
|
|
|
NS_ASSERTION(!GetPrevInFlow(), "GetColFrame called on next in flow");
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numCols = mColFrames.Length();
|
2001-03-13 09:38:59 +03:00
|
|
|
if ((aColIndex >= 0) && (aColIndex < numCols)) {
|
2009-02-05 12:09:50 +03:00
|
|
|
return mColFrames.ElementAt(aColIndex);
|
2001-03-13 09:38:59 +03:00
|
|
|
}
|
|
|
|
else {
|
2006-09-11 22:27:35 +04:00
|
|
|
NS_ERROR("invalid col index");
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2001-03-13 09:38:59 +03:00
|
|
|
}
|
1998-07-11 04:00:31 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nsTableFrame::GetEffectiveRowSpan(int32_t aRowIndex,
|
2000-02-01 06:23:29 +03:00
|
|
|
const nsTableCellFrame& aCell) const
|
1999-07-28 12:09:02 +04:00
|
|
|
{
|
2000-02-01 06:23:29 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_PRECONDITION (nullptr != cellMap, "bad call, cellMap not yet allocated.");
|
1999-07-28 12:09:02 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colIndex;
|
2000-02-01 06:23:29 +03:00
|
|
|
aCell.GetColIndex(colIndex);
|
|
|
|
return cellMap->GetEffectiveRowSpan(aRowIndex, colIndex);
|
|
|
|
}
|
1999-07-28 12:09:02 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nsTableFrame::GetEffectiveRowSpan(const nsTableCellFrame& aCell,
|
2002-03-05 18:23:28 +03:00
|
|
|
nsCellMap* aCellMap)
|
1998-07-17 03:23:31 +04:00
|
|
|
{
|
2002-03-05 18:23:28 +03:00
|
|
|
nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT1(1);
|
1998-07-17 03:23:31 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colIndex, rowIndex;
|
2000-02-01 06:23:29 +03:00
|
|
|
aCell.GetColIndex(colIndex);
|
|
|
|
aCell.GetRowIndex(rowIndex);
|
2002-03-05 18:23:28 +03:00
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
if (aCellMap)
|
2011-10-17 18:59:28 +04:00
|
|
|
return aCellMap->GetRowSpan(rowIndex, colIndex, true);
|
2002-03-05 18:23:28 +03:00
|
|
|
else
|
|
|
|
return tableCellMap->GetEffectiveRowSpan(rowIndex, colIndex);
|
1999-07-28 12:09:02 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nsTableFrame::GetEffectiveColSpan(const nsTableCellFrame& aCell,
|
2002-03-05 18:23:28 +03:00
|
|
|
nsCellMap* aCellMap) const
|
1999-07-28 12:09:02 +04:00
|
|
|
{
|
2002-03-05 18:23:28 +03:00
|
|
|
nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT1(1);
|
1999-07-28 12:09:02 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colIndex, rowIndex;
|
2000-02-01 06:23:29 +03:00
|
|
|
aCell.GetColIndex(colIndex);
|
|
|
|
aCell.GetRowIndex(rowIndex);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool ignore;
|
2002-03-05 18:23:28 +03:00
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
if (aCellMap)
|
2002-03-05 18:23:28 +03:00
|
|
|
return aCellMap->GetEffectiveColSpan(*tableCellMap, rowIndex, colIndex, ignore);
|
|
|
|
else
|
|
|
|
return tableCellMap->GetEffectiveColSpan(rowIndex, colIndex);
|
1998-07-17 03:23:31 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
bool nsTableFrame::HasMoreThanOneCell(int32_t aRowIndex) const
|
2004-04-13 10:21:16 +04:00
|
|
|
{
|
|
|
|
nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT1(1);
|
|
|
|
return tableCellMap->HasMoreThanOneCell(aRowIndex);
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
void nsTableFrame::AdjustRowIndices(int32_t aRowIndex,
|
|
|
|
int32_t aAdjustment)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2010-04-27 20:15:01 +04:00
|
|
|
// Iterate over the row groups and adjust the row indices of all rows
|
1999-12-14 01:56:31 +03:00
|
|
|
// whose index is >= aRowIndex.
|
2007-06-05 22:55:26 +04:00
|
|
|
RowGroupArray rowGroups;
|
|
|
|
OrderRowGroups(rowGroups);
|
2000-09-14 10:49:47 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
rowGroups[rgX]->AdjustRowIndices(aRowIndex, aAdjustment);
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-08-30 04:01:09 +04:00
|
|
|
|
2009-07-30 21:23:32 +04:00
|
|
|
void nsTableFrame::ResetRowIndices(const nsFrameList::Slice& aRowGroupsToExclude)
|
2006-06-28 23:00:01 +04:00
|
|
|
{
|
2006-08-04 23:15:50 +04:00
|
|
|
// Iterate over the row groups and adjust the row indices of all rows
|
|
|
|
// omit the rowgroups that will be inserted later
|
2007-06-05 22:55:26 +04:00
|
|
|
RowGroupArray rowGroups;
|
|
|
|
OrderRowGroups(rowGroups);
|
1999-08-30 04:01:09 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rowIndex = 0;
|
2010-01-16 19:05:46 +03:00
|
|
|
nsTHashtable<nsPtrHashKey<nsTableRowGroupFrame> > excludeRowGroups;
|
2012-05-18 21:30:49 +04:00
|
|
|
excludeRowGroups.Init();
|
2009-07-30 21:23:32 +04:00
|
|
|
nsFrameList::Enumerator excludeRowGroupsEnumerator(aRowGroupsToExclude);
|
2010-01-16 19:05:46 +03:00
|
|
|
while (!excludeRowGroupsEnumerator.AtEnd()) {
|
|
|
|
excludeRowGroups.PutEntry(static_cast<nsTableRowGroupFrame*>(excludeRowGroupsEnumerator.get()));
|
2009-07-30 21:23:32 +04:00
|
|
|
excludeRowGroupsEnumerator.Next();
|
2006-08-04 23:15:50 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
2010-01-16 19:05:46 +03:00
|
|
|
if (!excludeRowGroups.GetEntry(rgFrame)) {
|
2011-08-25 00:54:30 +04:00
|
|
|
const nsFrameList& rowFrames = rgFrame->PrincipalChildList();
|
2009-07-30 21:23:32 +04:00
|
|
|
for (nsFrameList::Enumerator rows(rowFrames); !rows.AtEnd(); rows.Next()) {
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_ROW==rows.get()->GetStyleDisplay()->mDisplay) {
|
|
|
|
((nsTableRowFrame *)rows.get())->SetRowIndex(rowIndex);
|
2006-08-04 23:15:50 +04:00
|
|
|
rowIndex++;
|
|
|
|
}
|
2006-06-28 23:00:01 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
void nsTableFrame::InsertColGroups(int32_t aStartColIndex,
|
2009-07-30 21:23:32 +04:00
|
|
|
const nsFrameList::Slice& aColGroups)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colIndex = aStartColIndex;
|
2009-07-30 21:23:32 +04:00
|
|
|
nsFrameList::Enumerator colGroups(aColGroups);
|
|
|
|
for (; !colGroups.AtEnd(); colGroups.Next()) {
|
2012-06-01 23:56:33 +04:00
|
|
|
MOZ_ASSERT(colGroups.get()->GetType() == nsGkAtoms::tableColGroupFrame);
|
2009-07-30 21:23:32 +04:00
|
|
|
nsTableColGroupFrame* cgFrame =
|
|
|
|
static_cast<nsTableColGroupFrame*>(colGroups.get());
|
|
|
|
cgFrame->SetStartColumnIndex(colIndex);
|
|
|
|
// XXXbz this sucks. AddColsToTable will actually remove colgroups from
|
|
|
|
// the list we're traversing! Need to fix things here. :( I guess this is
|
|
|
|
// why the old code used pointer-to-last-frame as opposed to
|
|
|
|
// pointer-to-frame-after-last....
|
|
|
|
|
|
|
|
// How about dealing with this by storing a const reference to the
|
|
|
|
// mNextSibling of the framelist's last frame, instead of storing a pointer
|
|
|
|
// to the first-after-next frame? Will involve making nsFrameList friend
|
|
|
|
// of nsIFrame, but it's time for that anyway.
|
2011-10-17 18:59:28 +04:00
|
|
|
cgFrame->AddColsToTable(colIndex, false,
|
2011-08-25 00:54:30 +04:00
|
|
|
colGroups.get()->PrincipalChildList());
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numCols = cgFrame->GetColCount();
|
2009-07-30 21:23:32 +04:00
|
|
|
colIndex += numCols;
|
1999-08-30 04:01:09 +04:00
|
|
|
}
|
|
|
|
|
2009-07-30 21:23:32 +04:00
|
|
|
nsFrameList::Enumerator remainingColgroups = colGroups.GetUnlimitedEnumerator();
|
|
|
|
if (!remainingColgroups.AtEnd()) {
|
|
|
|
nsTableColGroupFrame::ResetColIndices(
|
|
|
|
static_cast<nsTableColGroupFrame*>(remainingColgroups.get()), colIndex);
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
1999-08-30 04:01:09 +04:00
|
|
|
}
|
|
|
|
|
2005-02-07 04:58:25 +03:00
|
|
|
void nsTableFrame::InsertCol(nsTableColFrame& aColFrame,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aColIndex)
|
1999-08-30 04:01:09 +04:00
|
|
|
{
|
2009-02-05 12:09:50 +03:00
|
|
|
mColFrames.InsertElementAt(aColIndex, &aColFrame);
|
2003-10-31 23:19:18 +03:00
|
|
|
nsTableColType insertedColType = aColFrame.GetColType();
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numCacheCols = mColFrames.Length();
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (cellMap) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numMapCols = cellMap->GetColCount();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (numCacheCols > numMapCols) {
|
2011-09-29 10:19:26 +04:00
|
|
|
bool removedFromCache = false;
|
1999-12-14 01:56:31 +03:00
|
|
|
if (eColAnonymousCell != insertedColType) {
|
2009-02-05 12:09:50 +03:00
|
|
|
nsTableColFrame* lastCol = mColFrames.ElementAt(numCacheCols - 1);
|
1999-12-14 01:56:31 +03:00
|
|
|
if (lastCol) {
|
2003-10-31 23:19:18 +03:00
|
|
|
nsTableColType lastColType = lastCol->GetColType();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (eColAnonymousCell == lastColType) {
|
|
|
|
// remove the col from the cache
|
|
|
|
mColFrames.RemoveElementAt(numCacheCols - 1);
|
|
|
|
// remove the col from the eColGroupAnonymousCell col group
|
|
|
|
nsTableColGroupFrame* lastColGroup = (nsTableColGroupFrame *)mColGroups.LastChild();
|
|
|
|
if (lastColGroup) {
|
2011-10-17 18:59:28 +04:00
|
|
|
lastColGroup->RemoveChild(*lastCol, false);
|
2011-02-16 03:35:52 +03:00
|
|
|
|
|
|
|
// remove the col group if it is empty
|
|
|
|
if (lastColGroup->GetColCount() <= 0) {
|
|
|
|
mColGroups.DestroyFrame((nsIFrame*)lastColGroup);
|
|
|
|
}
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
removedFromCache = true;
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!removedFromCache) {
|
2000-01-13 08:29:38 +03:00
|
|
|
cellMap->AddColsAtEnd(1);
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
1999-08-30 04:01:09 +04:00
|
|
|
}
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
// for now, just bail and recalc all of the collapsing borders
|
|
|
|
if (IsBorderCollapse()) {
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea(aColIndex, 0, 1, GetRowCount());
|
2011-10-27 17:58:44 +04:00
|
|
|
AddBCDamageArea(damageArea);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
1999-08-30 04:01:09 +04:00
|
|
|
}
|
|
|
|
|
2005-02-07 04:58:25 +03:00
|
|
|
void nsTableFrame::RemoveCol(nsTableColGroupFrame* aColGroupFrame,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aColIndex,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aRemoveFromCache,
|
|
|
|
bool aRemoveFromCellMap)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
1999-12-14 01:56:31 +03:00
|
|
|
if (aRemoveFromCache) {
|
|
|
|
mColFrames.RemoveElementAt(aColIndex);
|
1998-12-03 21:01:35 +03:00
|
|
|
}
|
1999-12-14 01:56:31 +03:00
|
|
|
if (aRemoveFromCellMap) {
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-07-28 12:09:02 +04:00
|
|
|
if (cellMap) {
|
2009-07-12 21:47:10 +04:00
|
|
|
AppendAnonymousColFrames(1);
|
1999-07-28 12:09:02 +04:00
|
|
|
}
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
// for now, just bail and recalc all of the collapsing borders
|
|
|
|
if (IsBorderCollapse()) {
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea(0, 0, GetColCount(), GetRowCount());
|
2011-10-27 17:58:44 +04:00
|
|
|
AddBCDamageArea(damageArea);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
1998-09-01 01:23:28 +04:00
|
|
|
}
|
|
|
|
|
1998-08-14 20:16:43 +04:00
|
|
|
/** Get the cell map for this table frame. It is not always mCellMap.
|
|
|
|
* Only the firstInFlow has a legit cell map
|
|
|
|
*/
|
2001-03-13 09:38:59 +03:00
|
|
|
nsTableCellMap* nsTableFrame::GetCellMap() const
|
1998-08-14 20:16:43 +04:00
|
|
|
{
|
2001-03-13 09:38:59 +03:00
|
|
|
nsTableFrame* firstInFlow = (nsTableFrame *)GetFirstInFlow();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
return firstInFlow->mCellMap;
|
1998-08-14 20:16:43 +04:00
|
|
|
}
|
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
// XXX this needs to be moved to nsCSSFrameConstructor
|
|
|
|
nsTableColGroupFrame*
|
2005-02-07 04:58:25 +03:00
|
|
|
nsTableFrame::CreateAnonymousColGroupFrame(nsTableColGroupType aColGroupType)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2003-07-07 06:01:29 +04:00
|
|
|
nsIContent* colGroupContent = GetContent();
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext* presContext = PresContext();
|
2005-02-07 04:58:25 +03:00
|
|
|
nsIPresShell *shell = presContext->PresShell();
|
1999-12-14 01:56:31 +03:00
|
|
|
|
2003-02-22 03:32:13 +03:00
|
|
|
nsRefPtr<nsStyleContext> colGroupStyle;
|
2009-12-11 10:37:40 +03:00
|
|
|
colGroupStyle = shell->StyleSet()->
|
|
|
|
ResolveAnonymousBoxStyle(nsCSSAnonBoxes::tableColGroup, mStyleContext);
|
1999-12-14 01:56:31 +03:00
|
|
|
// Create a col group frame
|
2006-03-27 01:30:36 +04:00
|
|
|
nsIFrame* newFrame = NS_NewTableColGroupFrame(shell, colGroupStyle);
|
2005-11-04 05:38:33 +03:00
|
|
|
if (newFrame) {
|
2003-10-31 23:19:18 +03:00
|
|
|
((nsTableColGroupFrame *)newFrame)->SetColType(aColGroupType);
|
2012-07-30 18:20:58 +04:00
|
|
|
newFrame->Init(colGroupContent, this, nullptr);
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
return (nsTableColGroupFrame *)newFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
nsTableFrame::AppendAnonymousColFrames(int32_t aNumColsToAdd)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
|
|
|
// get the last col group frame
|
2009-07-28 16:53:18 +04:00
|
|
|
nsTableColGroupFrame* colGroupFrame =
|
|
|
|
static_cast<nsTableColGroupFrame*>(mColGroups.LastChild());
|
1999-12-14 01:56:31 +03:00
|
|
|
|
2009-07-28 16:53:18 +04:00
|
|
|
if (!colGroupFrame ||
|
|
|
|
(colGroupFrame->GetColType() != eColGroupAnonymousCell)) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colIndex = (colGroupFrame) ?
|
2009-07-12 21:47:10 +04:00
|
|
|
colGroupFrame->GetStartColumnIndex() +
|
|
|
|
colGroupFrame->GetColCount() : 0;
|
|
|
|
colGroupFrame = CreateAnonymousColGroupFrame(eColGroupAnonymousCell);
|
1999-12-14 01:56:31 +03:00
|
|
|
if (!colGroupFrame) {
|
|
|
|
return;
|
|
|
|
}
|
2009-07-12 21:47:10 +04:00
|
|
|
// add the new frame to the child list
|
|
|
|
mColGroups.AppendFrame(this, colGroupFrame);
|
1999-12-14 01:56:31 +03:00
|
|
|
colGroupFrame->SetStartColumnIndex(colIndex);
|
|
|
|
}
|
2009-07-28 16:53:18 +04:00
|
|
|
AppendAnonymousColFrames(colGroupFrame, aNumColsToAdd, eColAnonymousCell,
|
2011-10-17 18:59:28 +04:00
|
|
|
true);
|
2009-07-12 21:47:10 +04:00
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// XXX this needs to be moved to nsCSSFrameConstructor
|
2010-04-27 20:15:01 +04:00
|
|
|
// Right now it only creates the col frames at the end
|
1999-12-14 01:56:31 +03:00
|
|
|
void
|
2009-07-28 16:53:18 +04:00
|
|
|
nsTableFrame::AppendAnonymousColFrames(nsTableColGroupFrame* aColGroupFrame,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aNumColsToAdd,
|
1999-12-14 01:56:31 +03:00
|
|
|
nsTableColType aColType,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aAddToTable)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2004-10-29 21:44:29 +04:00
|
|
|
NS_PRECONDITION(aColGroupFrame, "null frame");
|
2007-12-05 22:38:26 +03:00
|
|
|
NS_PRECONDITION(aColType != eColAnonymousCol, "Shouldn't happen");
|
|
|
|
|
2009-07-28 16:53:18 +04:00
|
|
|
nsIPresShell *shell = PresContext()->PresShell();
|
1999-12-14 01:56:31 +03:00
|
|
|
|
|
|
|
// Get the last col frame
|
2009-09-18 15:09:36 +04:00
|
|
|
nsFrameList newColFrames;
|
1999-12-14 01:56:31 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t startIndex = mColFrames.Length();
|
|
|
|
int32_t lastIndex = startIndex + aNumColsToAdd - 1;
|
1999-12-14 01:56:31 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t childX = startIndex; childX <= lastIndex; childX++) {
|
2003-07-07 06:01:29 +04:00
|
|
|
nsIContent* iContent;
|
2003-02-22 03:32:13 +03:00
|
|
|
nsRefPtr<nsStyleContext> styleContext;
|
|
|
|
nsStyleContext* parentStyleContext;
|
1999-12-14 01:56:31 +03:00
|
|
|
|
2007-12-05 22:38:26 +03:00
|
|
|
// all anonymous cols that we create here use a pseudo style context of the
|
|
|
|
// col group
|
|
|
|
iContent = aColGroupFrame->GetContent();
|
|
|
|
parentStyleContext = aColGroupFrame->GetStyleContext();
|
2009-12-11 10:37:40 +03:00
|
|
|
styleContext = shell->StyleSet()->
|
|
|
|
ResolveAnonymousBoxStyle(nsCSSAnonBoxes::tableCol, parentStyleContext);
|
2000-10-05 02:22:46 +04:00
|
|
|
// ASSERTION to check for bug 54454 sneaking back in...
|
|
|
|
NS_ASSERTION(iContent, "null content in CreateAnonymousColFrames");
|
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
// create the new col frame
|
2006-03-27 01:30:36 +04:00
|
|
|
nsIFrame* colFrame = NS_NewTableColFrame(shell, styleContext);
|
2003-10-31 23:19:18 +03:00
|
|
|
((nsTableColFrame *) colFrame)->SetColType(aColType);
|
2012-07-30 18:20:58 +04:00
|
|
|
colFrame->Init(iContent, aColGroupFrame, nullptr);
|
1999-12-14 01:56:31 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
newColFrames.AppendFrame(nullptr, colFrame);
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
2009-07-28 16:53:18 +04:00
|
|
|
nsFrameList& cols = aColGroupFrame->GetWritableChildList();
|
|
|
|
nsIFrame* oldLastCol = cols.LastChild();
|
2009-07-30 21:23:32 +04:00
|
|
|
const nsFrameList::Slice& newCols =
|
2012-07-30 18:20:58 +04:00
|
|
|
cols.InsertFrames(nullptr, oldLastCol, newColFrames);
|
2009-07-28 16:53:18 +04:00
|
|
|
if (aAddToTable) {
|
1999-12-14 01:56:31 +03:00
|
|
|
// get the starting col index in the cache
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t startColIndex;
|
2009-07-28 16:53:18 +04:00
|
|
|
if (oldLastCol) {
|
|
|
|
startColIndex =
|
|
|
|
static_cast<nsTableColFrame*>(oldLastCol)->GetColIndex() + 1;
|
|
|
|
} else {
|
|
|
|
startColIndex = aColGroupFrame->GetStartColumnIndex();
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
2009-07-28 16:53:18 +04:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
aColGroupFrame->AddColsToTable(startColIndex, true, newCols);
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-28 21:39:36 +04:00
|
|
|
void
|
|
|
|
nsTableFrame::MatchCellMapToColCache(nsTableCellMap* aCellMap)
|
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numColsInMap = GetColCount();
|
|
|
|
int32_t numColsInCache = mColFrames.Length();
|
|
|
|
int32_t numColsToAdd = numColsInMap - numColsInCache;
|
2006-08-28 21:39:36 +04:00
|
|
|
if (numColsToAdd > 0) {
|
|
|
|
// this sets the child list, updates the col cache and cell map
|
2009-07-12 21:47:10 +04:00
|
|
|
AppendAnonymousColFrames(numColsToAdd);
|
2006-08-28 21:39:36 +04:00
|
|
|
}
|
|
|
|
if (numColsToAdd < 0) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numColsNotRemoved = DestroyAnonymousColFrames(-numColsToAdd);
|
2006-08-28 21:39:36 +04:00
|
|
|
// if the cell map has fewer cols than the cache, correct it
|
|
|
|
if (numColsNotRemoved > 0) {
|
|
|
|
aCellMap->AddColsAtEnd(numColsNotRemoved);
|
|
|
|
}
|
|
|
|
}
|
2006-10-20 11:37:24 +04:00
|
|
|
if (numColsToAdd && HasZeroColSpans()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
SetNeedColSpanExpansion(true);
|
2006-10-20 11:37:24 +04:00
|
|
|
}
|
|
|
|
if (NeedColSpanExpansion()) {
|
|
|
|
// This flag can be set in two ways -- either by changing
|
|
|
|
// the number of columns (that happens in the block above),
|
|
|
|
// or by adding a cell with colspan="0" to the cellmap. To
|
|
|
|
// handle the latter case we need to explicitly check the
|
|
|
|
// flag here -- it may be set even if the number of columns
|
|
|
|
// did not change.
|
|
|
|
//
|
|
|
|
// @see nsCellMap::AppendCell
|
|
|
|
|
|
|
|
aCellMap->ExpandZeroColSpans();
|
|
|
|
}
|
2006-08-28 21:39:36 +04:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
|
|
|
|
void
|
|
|
|
nsTableFrame::DidResizeColumns()
|
|
|
|
{
|
|
|
|
NS_PRECONDITION(!GetPrevInFlow(),
|
|
|
|
"should only be called on first-in-flow");
|
|
|
|
if (mBits.mResizedColumns)
|
|
|
|
return; // already marked
|
|
|
|
|
|
|
|
for (nsTableFrame *f = this; f;
|
2007-07-08 11:08:04 +04:00
|
|
|
f = static_cast<nsTableFrame*>(f->GetNextInFlow()))
|
2011-10-17 18:59:28 +04:00
|
|
|
f->mBits.mResizedColumns = true;
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
void
|
2005-02-07 04:58:25 +03:00
|
|
|
nsTableFrame::AppendCell(nsTableCellFrame& aCellFrame,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aRowIndex)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (cellMap) {
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea(0,0,0,0);
|
2011-10-17 18:59:28 +04:00
|
|
|
cellMap->AppendCell(aCellFrame, aRowIndex, true, damageArea);
|
2006-08-28 21:39:36 +04:00
|
|
|
MatchCellMapToColCache(cellMap);
|
2002-02-19 18:48:28 +03:00
|
|
|
if (IsBorderCollapse()) {
|
2011-10-27 17:58:44 +04:00
|
|
|
AddBCDamageArea(damageArea);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-05 12:09:50 +03:00
|
|
|
void nsTableFrame::InsertCells(nsTArray<nsTableCellFrame*>& aCellFrames,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aRowIndex,
|
|
|
|
int32_t aColIndexBefore)
|
1998-06-17 20:38:24 +04:00
|
|
|
{
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (cellMap) {
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea(0,0,0,0);
|
2002-02-19 18:48:28 +03:00
|
|
|
cellMap->InsertCells(aCellFrames, aRowIndex, aColIndexBefore, damageArea);
|
2006-08-28 21:39:36 +04:00
|
|
|
MatchCellMapToColCache(cellMap);
|
2002-02-19 18:48:28 +03:00
|
|
|
if (IsBorderCollapse()) {
|
2011-10-27 17:58:44 +04:00
|
|
|
AddBCDamageArea(damageArea);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// this removes the frames from the col group and table, but not the cell map
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t
|
|
|
|
nsTableFrame::DestroyAnonymousColFrames(int32_t aNumFrames)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
|
|
|
// only remove cols that are of type eTypeAnonymous cell (they are at the end)
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t endIndex = mColFrames.Length() - 1;
|
|
|
|
int32_t startIndex = (endIndex - aNumFrames) + 1;
|
|
|
|
int32_t numColsRemoved = 0;
|
|
|
|
for (int32_t colX = endIndex; colX >= startIndex; colX--) {
|
1999-12-14 01:56:31 +03:00
|
|
|
nsTableColFrame* colFrame = GetColFrame(colX);
|
2003-10-31 23:19:18 +03:00
|
|
|
if (colFrame && (eColAnonymousCell == colFrame->GetColType())) {
|
2003-07-07 06:01:29 +04:00
|
|
|
nsTableColGroupFrame* cgFrame =
|
2007-07-08 11:08:04 +04:00
|
|
|
static_cast<nsTableColGroupFrame*>(colFrame->GetParent());
|
1999-12-14 01:56:31 +03:00
|
|
|
// remove the frame from the colgroup
|
2011-10-17 18:59:28 +04:00
|
|
|
cgFrame->RemoveChild(*colFrame, false);
|
2010-04-27 20:15:01 +04:00
|
|
|
// remove the frame from the cache, but not the cell map
|
2012-07-30 18:20:58 +04:00
|
|
|
RemoveCol(nullptr, colX, true, false);
|
1999-12-14 01:56:31 +03:00
|
|
|
numColsRemoved++;
|
|
|
|
}
|
|
|
|
else {
|
2010-04-27 20:15:01 +04:00
|
|
|
break;
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (aNumFrames - numColsRemoved);
|
|
|
|
}
|
1998-09-01 01:23:28 +04:00
|
|
|
|
2005-02-07 04:58:25 +03:00
|
|
|
void nsTableFrame::RemoveCell(nsTableCellFrame* aCellFrame,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aRowIndex)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (cellMap) {
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea(0,0,0,0);
|
2002-02-19 18:48:28 +03:00
|
|
|
cellMap->RemoveCell(aCellFrame, aRowIndex, damageArea);
|
2006-08-28 21:39:36 +04:00
|
|
|
MatchCellMapToColCache(cellMap);
|
2002-02-19 18:48:28 +03:00
|
|
|
if (IsBorderCollapse()) {
|
2011-10-27 17:58:44 +04:00
|
|
|
AddBCDamageArea(damageArea);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
1999-07-28 12:09:02 +04:00
|
|
|
}
|
1998-07-02 02:22:28 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t
|
2010-01-16 19:05:46 +03:00
|
|
|
nsTableFrame::GetStartRowIndex(nsTableRowGroupFrame* aRowGroupFrame)
|
2000-09-14 10:49:47 +04:00
|
|
|
{
|
2007-06-05 22:55:26 +04:00
|
|
|
RowGroupArray orderedRowGroups;
|
|
|
|
OrderRowGroups(orderedRowGroups);
|
2000-09-14 10:49:47 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rowIndex = 0;
|
|
|
|
for (uint32_t rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
|
2010-01-16 19:05:46 +03:00
|
|
|
if (rgFrame == aRowGroupFrame) {
|
2000-09-14 10:49:47 +04:00
|
|
|
break;
|
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numRows = rgFrame->GetRowCount();
|
2000-09-14 10:49:47 +04:00
|
|
|
rowIndex += numRows;
|
|
|
|
}
|
|
|
|
return rowIndex;
|
|
|
|
}
|
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
// this cannot extend beyond a single row group
|
2010-01-16 19:05:46 +03:00
|
|
|
void nsTableFrame::AppendRows(nsTableRowGroupFrame* aRowGroupFrame,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aRowIndex,
|
2009-02-05 12:09:50 +03:00
|
|
|
nsTArray<nsTableRowFrame*>& aRowFrames)
|
1999-07-28 12:09:02 +04:00
|
|
|
{
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (cellMap) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t absRowIndex = GetStartRowIndex(aRowGroupFrame) + aRowIndex;
|
2011-10-17 18:59:28 +04:00
|
|
|
InsertRows(aRowGroupFrame, aRowFrames, absRowIndex, true);
|
1998-06-17 20:38:24 +04:00
|
|
|
}
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
// this cannot extend beyond a single row group
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t
|
2010-01-16 19:05:46 +03:00
|
|
|
nsTableFrame::InsertRows(nsTableRowGroupFrame* aRowGroupFrame,
|
2009-02-05 12:09:50 +03:00
|
|
|
nsTArray<nsTableRowFrame*>& aRowFrames,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aRowIndex,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aConsiderSpans)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2004-03-03 20:45:50 +03:00
|
|
|
#ifdef DEBUG_TABLE_CELLMAP
|
2006-06-22 08:19:36 +04:00
|
|
|
printf("=== insertRowsBefore firstRow=%d \n", aRowIndex);
|
2011-10-17 18:59:28 +04:00
|
|
|
Dump(true, false, true);
|
2004-03-03 20:45:50 +03:00
|
|
|
#endif
|
1999-12-14 01:56:31 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numColsToAdd = 0;
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (cellMap) {
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea(0,0,0,0);
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t origNumRows = cellMap->GetRowCount();
|
|
|
|
int32_t numNewRows = aRowFrames.Length();
|
2004-01-18 13:28:40 +03:00
|
|
|
cellMap->InsertRows(aRowGroupFrame, aRowFrames, aRowIndex, aConsiderSpans, damageArea);
|
2006-08-28 21:39:36 +04:00
|
|
|
MatchCellMapToColCache(cellMap);
|
1999-12-14 01:56:31 +03:00
|
|
|
if (aRowIndex < origNumRows) {
|
2004-01-18 13:28:40 +03:00
|
|
|
AdjustRowIndices(aRowIndex, numNewRows);
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
// assign the correct row indices to the new rows. If they were adjusted above
|
|
|
|
// it may not have been done correctly because each row is constructed with index 0
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t rowY = 0; rowY < numNewRows; rowY++) {
|
2009-06-21 20:31:40 +04:00
|
|
|
nsTableRowFrame* rowFrame = aRowFrames.ElementAt(rowY);
|
|
|
|
rowFrame->SetRowIndex(aRowIndex + rowY);
|
1999-06-14 12:01:00 +04:00
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
if (IsBorderCollapse()) {
|
2011-10-27 17:58:44 +04:00
|
|
|
AddBCDamageArea(damageArea);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
1999-06-14 12:01:00 +04:00
|
|
|
}
|
2004-03-03 20:45:50 +03:00
|
|
|
#ifdef DEBUG_TABLE_CELLMAP
|
2006-06-22 08:19:36 +04:00
|
|
|
printf("=== insertRowsAfter \n");
|
2011-10-17 18:59:28 +04:00
|
|
|
Dump(true, false, true);
|
2004-03-03 20:45:50 +03:00
|
|
|
#endif
|
1999-12-14 01:56:31 +03:00
|
|
|
|
|
|
|
return numColsToAdd;
|
1999-06-14 12:01:00 +04:00
|
|
|
}
|
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
// this cannot extend beyond a single row group
|
2005-02-07 04:58:25 +03:00
|
|
|
void nsTableFrame::RemoveRows(nsTableRowFrame& aFirstRowFrame,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aNumRowsToRemove,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aConsiderSpans)
|
1998-10-14 20:32:45 +04:00
|
|
|
{
|
2001-03-13 09:38:59 +03:00
|
|
|
#ifdef TBD_OPTIMIZATION
|
2010-04-27 20:15:01 +04:00
|
|
|
// decide if we need to rebalance. we have to do this here because the row group
|
2001-03-13 09:38:59 +03:00
|
|
|
// cannot do it when it gets the dirty reflow corresponding to the frame being destroyed
|
2011-09-29 10:19:26 +04:00
|
|
|
bool stopTelling = false;
|
2003-07-07 06:01:29 +04:00
|
|
|
for (nsIFrame* kidFrame = aFirstFrame.FirstChild(); (kidFrame && !stopAsking);
|
|
|
|
kidFrame = kidFrame->GetNextSibling()) {
|
2009-03-25 01:10:06 +03:00
|
|
|
nsTableCellFrame *cellFrame = do_QueryFrame(kidFrame);
|
|
|
|
if (cellFrame) {
|
2010-04-27 20:15:01 +04:00
|
|
|
stopTelling = tableFrame->CellChangedWidth(*cellFrame, cellFrame->GetPass1MaxElementWidth(),
|
2011-10-17 18:59:28 +04:00
|
|
|
cellFrame->GetMaximumWidth(), true);
|
2001-03-13 09:38:59 +03:00
|
|
|
}
|
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
// XXX need to consider what happens if there are cells that have rowspans
|
2001-03-13 09:38:59 +03:00
|
|
|
// into the deleted row. Need to consider moving rows if a rebalance doesn't happen
|
|
|
|
#endif
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t firstRowIndex = aFirstRowFrame.GetRowIndex();
|
2004-03-03 20:45:50 +03:00
|
|
|
#ifdef DEBUG_TABLE_CELLMAP
|
2006-06-22 08:19:36 +04:00
|
|
|
printf("=== removeRowsBefore firstRow=%d numRows=%d\n", firstRowIndex, aNumRowsToRemove);
|
2011-10-17 18:59:28 +04:00
|
|
|
Dump(true, false, true);
|
2004-03-03 20:45:50 +03:00
|
|
|
#endif
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (cellMap) {
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea(0,0,0,0);
|
2004-01-18 13:28:40 +03:00
|
|
|
cellMap->RemoveRows(firstRowIndex, aNumRowsToRemove, aConsiderSpans, damageArea);
|
2006-08-28 21:39:36 +04:00
|
|
|
MatchCellMapToColCache(cellMap);
|
2002-02-19 18:48:28 +03:00
|
|
|
if (IsBorderCollapse()) {
|
2011-10-27 17:58:44 +04:00
|
|
|
AddBCDamageArea(damageArea);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
2004-01-18 13:28:40 +03:00
|
|
|
AdjustRowIndices(firstRowIndex, -aNumRowsToRemove);
|
2004-03-03 20:45:50 +03:00
|
|
|
#ifdef DEBUG_TABLE_CELLMAP
|
2006-06-22 08:19:36 +04:00
|
|
|
printf("=== removeRowsAfter\n");
|
2011-10-17 18:59:28 +04:00
|
|
|
Dump(true, true, true);
|
2004-03-03 20:45:50 +03:00
|
|
|
#endif
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// collect the rows ancestors of aFrame
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t
|
2009-02-05 12:09:50 +03:00
|
|
|
nsTableFrame::CollectRows(nsIFrame* aFrame,
|
|
|
|
nsTArray<nsTableRowFrame*>& aCollection)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2010-01-16 19:05:46 +03:00
|
|
|
NS_PRECONDITION(aFrame, "null frame");
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numRows = 0;
|
2011-08-25 00:54:30 +04:00
|
|
|
nsIFrame* childFrame = aFrame->GetFirstPrincipalChild();
|
2010-01-16 19:05:46 +03:00
|
|
|
while (childFrame) {
|
|
|
|
aCollection.AppendElement(static_cast<nsTableRowFrame*>(childFrame));
|
|
|
|
numRows++;
|
|
|
|
childFrame = childFrame->GetNextSibling();
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
2000-01-13 08:29:38 +03:00
|
|
|
return numRows;
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-07-30 21:23:32 +04:00
|
|
|
nsTableFrame::InsertRowGroups(const nsFrameList::Slice& aRowGroups)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2005-12-16 22:10:56 +03:00
|
|
|
#ifdef DEBUG_TABLE_CELLMAP
|
2006-06-22 08:19:36 +04:00
|
|
|
printf("=== insertRowGroupsBefore\n");
|
2011-10-17 18:59:28 +04:00
|
|
|
Dump(true, false, true);
|
2005-12-16 22:10:56 +03:00
|
|
|
#endif
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (cellMap) {
|
2007-06-05 22:55:26 +04:00
|
|
|
RowGroupArray orderedRowGroups;
|
|
|
|
OrderRowGroups(orderedRowGroups);
|
|
|
|
|
2009-02-05 12:09:50 +03:00
|
|
|
nsAutoTArray<nsTableRowFrame*, 8> rows;
|
2005-12-16 22:10:56 +03:00
|
|
|
// Loop over the rowgroups and check if some of them are new, if they are
|
|
|
|
// insert cellmaps in the order that is predefined by OrderRowGroups,
|
2009-07-30 21:23:32 +04:00
|
|
|
// XXXbz this code is O(N*M) where N is number of new rowgroups
|
|
|
|
// and M is number of rowgroups we have!
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t rgIndex;
|
2007-06-05 22:55:26 +04:00
|
|
|
for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
2009-07-30 21:23:32 +04:00
|
|
|
for (nsFrameList::Enumerator rowgroups(aRowGroups); !rowgroups.AtEnd();
|
|
|
|
rowgroups.Next()) {
|
2010-01-16 19:05:46 +03:00
|
|
|
if (orderedRowGroups[rgIndex] == rowgroups.get()) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableRowGroupFrame* priorRG =
|
2012-07-30 18:20:58 +04:00
|
|
|
(0 == rgIndex) ? nullptr : orderedRowGroups[rgIndex - 1];
|
2005-12-16 22:10:56 +03:00
|
|
|
// create and add the cell map for the row group
|
2010-01-16 19:05:46 +03:00
|
|
|
cellMap->InsertGroupCellMap(orderedRowGroups[rgIndex], priorRG);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2006-08-04 23:15:50 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cellMap->Synchronize(this);
|
2009-07-30 21:23:32 +04:00
|
|
|
ResetRowIndices(aRowGroups);
|
2006-08-04 23:15:50 +04:00
|
|
|
|
|
|
|
//now that the cellmaps are reordered too insert the rows
|
2007-06-05 22:55:26 +04:00
|
|
|
for (rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
2009-07-30 21:23:32 +04:00
|
|
|
for (nsFrameList::Enumerator rowgroups(aRowGroups); !rowgroups.AtEnd();
|
|
|
|
rowgroups.Next()) {
|
2010-01-16 19:05:46 +03:00
|
|
|
if (orderedRowGroups[rgIndex] == rowgroups.get()) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableRowGroupFrame* priorRG =
|
2012-07-30 18:20:58 +04:00
|
|
|
(0 == rgIndex) ? nullptr : orderedRowGroups[rgIndex - 1];
|
2005-12-16 22:10:56 +03:00
|
|
|
// collect the new row frames in an array and add them to the table
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numRows = CollectRows(rowgroups.get(), rows);
|
2005-12-16 22:10:56 +03:00
|
|
|
if (numRows > 0) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rowIndex = 0;
|
2005-12-16 22:10:56 +03:00
|
|
|
if (priorRG) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t priorNumRows = priorRG->GetRowCount();
|
2005-12-16 22:10:56 +03:00
|
|
|
rowIndex = priorRG->GetStartRowIndex() + priorNumRows;
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
InsertRows(orderedRowGroups[rgIndex], rows, rowIndex, true);
|
2005-12-16 22:10:56 +03:00
|
|
|
rows.Clear();
|
2000-09-14 10:49:47 +04:00
|
|
|
}
|
2005-12-16 22:10:56 +03:00
|
|
|
break;
|
2000-09-14 10:49:47 +04:00
|
|
|
}
|
2000-01-13 08:29:38 +03:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
}
|
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
2005-12-16 22:10:56 +03:00
|
|
|
#ifdef DEBUG_TABLE_CELLMAP
|
2006-06-22 08:19:36 +04:00
|
|
|
printf("=== insertRowGroupsAfter\n");
|
2011-10-17 18:59:28 +04:00
|
|
|
Dump(true, true, true);
|
2005-12-16 22:10:56 +03:00
|
|
|
#endif
|
1998-10-14 20:32:45 +04:00
|
|
|
}
|
|
|
|
|
1998-12-17 10:04:42 +03:00
|
|
|
|
1998-12-03 21:01:35 +03:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Child frame enumeration
|
|
|
|
|
2012-03-08 05:57:37 +04:00
|
|
|
const nsFrameList&
|
2011-08-25 00:54:29 +04:00
|
|
|
nsTableFrame::GetChildList(ChildListID aListID) const
|
1998-12-03 21:01:35 +03:00
|
|
|
{
|
2011-08-25 00:54:29 +04:00
|
|
|
if (aListID == kColGroupList) {
|
2009-07-28 16:51:09 +04:00
|
|
|
return mColGroups;
|
1998-12-03 21:01:35 +03:00
|
|
|
}
|
2011-12-28 00:18:48 +04:00
|
|
|
return nsContainerFrame::GetChildList(aListID);
|
1998-12-03 21:01:35 +03:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2011-08-25 00:54:29 +04:00
|
|
|
void
|
|
|
|
nsTableFrame::GetChildLists(nsTArray<ChildList>* aLists) const
|
1998-12-03 21:01:35 +03:00
|
|
|
{
|
2011-12-28 00:18:48 +04:00
|
|
|
nsContainerFrame::GetChildLists(aLists);
|
2011-08-25 00:54:29 +04:00
|
|
|
mColGroups.AppendIfNonempty(aLists, kColGroupList);
|
1998-12-03 21:01:35 +03:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2008-04-06 15:34:14 +04:00
|
|
|
nsRect
|
2012-04-10 15:24:18 +04:00
|
|
|
nsDisplayTableItem::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
|
|
|
|
*aSnap = false;
|
2011-10-13 05:01:27 +04:00
|
|
|
return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame();
|
2008-04-06 15:34:14 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2010-08-13 13:54:37 +04:00
|
|
|
nsDisplayTableItem::IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsIFrame* aFrame)
|
2008-04-06 15:34:14 +04:00
|
|
|
{
|
|
|
|
if (!mPartHasFixedBackground)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2008-04-06 15:34:14 +04:00
|
|
|
|
2010-08-13 13:54:37 +04:00
|
|
|
// If aFrame is mFrame or an ancestor in this document, and aFrame is
|
|
|
|
// not the viewport frame, then moving aFrame will move mFrame
|
|
|
|
// relative to the viewport, so our fixed-pos background will change.
|
|
|
|
return mFrame == aFrame ||
|
|
|
|
nsLayoutUtils::IsProperAncestorFrame(aFrame, mFrame);
|
2008-04-06 15:34:14 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ void
|
|
|
|
nsDisplayTableItem::UpdateForFrameBackground(nsIFrame* aFrame)
|
|
|
|
{
|
2010-04-03 05:58:26 +04:00
|
|
|
nsStyleContext *bgSC;
|
|
|
|
if (!nsCSSRendering::FindBackground(aFrame->PresContext(), aFrame, &bgSC))
|
2008-04-06 15:34:14 +04:00
|
|
|
return;
|
2010-04-03 05:58:26 +04:00
|
|
|
if (!bgSC->GetStyleBackground()->HasFixedBackground())
|
2008-04-06 15:34:14 +04:00
|
|
|
return;
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mPartHasFixedBackground = true;
|
2008-04-06 15:34:14 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
class nsDisplayTableBorderBackground : public nsDisplayTableItem {
|
2006-01-26 05:29:17 +03:00
|
|
|
public:
|
2010-08-13 14:01:13 +04:00
|
|
|
nsDisplayTableBorderBackground(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsTableFrame* aFrame) :
|
|
|
|
nsDisplayTableItem(aBuilder, aFrame) {
|
2006-01-29 21:48:58 +03:00
|
|
|
MOZ_COUNT_CTOR(nsDisplayTableBorderBackground);
|
|
|
|
}
|
|
|
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
|
|
|
virtual ~nsDisplayTableBorderBackground() {
|
|
|
|
MOZ_COUNT_DTOR(nsDisplayTableBorderBackground);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-09-07 04:35:14 +04:00
|
|
|
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
2011-04-08 05:04:40 +04:00
|
|
|
nsRenderingContext* aCtx);
|
2010-07-16 01:07:49 +04:00
|
|
|
NS_DISPLAY_DECL_NAME("TableBorderBackground", TYPE_TABLE_BORDER_BACKGROUND)
|
2006-01-26 05:29:17 +03:00
|
|
|
};
|
2002-02-26 03:27:42 +03:00
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
void
|
|
|
|
nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
|
2011-04-08 05:04:40 +04:00
|
|
|
nsRenderingContext* aCtx)
|
2006-01-26 05:29:17 +03:00
|
|
|
{
|
2007-07-08 11:08:04 +04:00
|
|
|
static_cast<nsTableFrame*>(mFrame)->
|
2009-09-07 04:35:14 +04:00
|
|
|
PaintTableBorderBackground(*aCtx, mVisibleRect,
|
2010-08-13 14:01:58 +04:00
|
|
|
ToReferenceFrame(),
|
2009-09-13 02:44:18 +04:00
|
|
|
aBuilder->GetBackgroundPaintFlags());
|
2006-01-26 05:29:17 +03:00
|
|
|
}
|
2002-02-26 03:27:42 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
static int32_t GetTablePartRank(nsDisplayItem* aItem)
|
2006-04-18 02:16:24 +04:00
|
|
|
{
|
|
|
|
nsIAtom* type = aItem->GetUnderlyingFrame()->GetType();
|
|
|
|
if (type == nsGkAtoms::tableFrame)
|
|
|
|
return 0;
|
|
|
|
if (type == nsGkAtoms::tableRowGroupFrame)
|
|
|
|
return 1;
|
|
|
|
if (type == nsGkAtoms::tableRowFrame)
|
|
|
|
return 2;
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool CompareByTablePartRank(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
|
2006-04-18 02:16:24 +04:00
|
|
|
void* aClosure)
|
|
|
|
{
|
|
|
|
return GetTablePartRank(aItem1) <= GetTablePartRank(aItem2);
|
|
|
|
}
|
|
|
|
|
2006-09-20 01:39:33 +04:00
|
|
|
/* static */ nsresult
|
|
|
|
nsTableFrame::GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
|
|
|
|
const nsRect& aDirtyRect, const nsDisplayListSet& aLists)
|
|
|
|
{
|
|
|
|
// This is similar to what nsContainerFrame::BuildDisplayListForNonBlockChildren
|
|
|
|
// does, except that we allow the children's background and borders to go
|
|
|
|
// in our BorderBackground list. This doesn't really affect background
|
|
|
|
// painting --- the children won't actually draw their own backgrounds
|
|
|
|
// because the nsTableFrame already drew them, unless a child has its own
|
|
|
|
// stacking context, in which case the child won't use its passed-in
|
|
|
|
// BorderBackground list anyway. It does affect cell borders though; this
|
|
|
|
// lets us get cell borders into the nsTableFrame's BorderBackground list.
|
2011-08-25 00:54:30 +04:00
|
|
|
nsIFrame* kid = aFrame->GetFirstPrincipalChild();
|
2006-09-20 01:39:33 +04:00
|
|
|
while (kid) {
|
|
|
|
nsresult rv = aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
kid = kid->GetNextSibling();
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
/* static */ nsresult
|
|
|
|
nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
|
|
|
nsFrame* aFrame,
|
|
|
|
const nsRect& aDirtyRect,
|
2006-04-18 02:16:24 +04:00
|
|
|
const nsDisplayListSet& aLists,
|
2008-04-06 15:34:14 +04:00
|
|
|
nsDisplayTableItem* aDisplayItem,
|
2006-09-20 01:39:33 +04:00
|
|
|
DisplayGenericTablePartTraversal aTraversal)
|
2006-01-26 05:29:17 +03:00
|
|
|
{
|
2006-04-18 02:16:24 +04:00
|
|
|
nsDisplayList eventsBorderBackground;
|
2006-05-01 05:18:32 +04:00
|
|
|
// If we need to sort the event backgrounds, then we'll put descendants'
|
|
|
|
// display items into their own set of lists.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool sortEventBackgrounds = aDisplayItem && aBuilder->IsForEventDelivery();
|
2006-05-01 05:18:32 +04:00
|
|
|
nsDisplayListCollection separatedCollection;
|
|
|
|
const nsDisplayListSet* lists = sortEventBackgrounds ? &separatedCollection : &aLists;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2008-04-06 15:34:14 +04:00
|
|
|
nsAutoPushCurrentTableItem pushTableItem;
|
|
|
|
if (aDisplayItem) {
|
|
|
|
pushTableItem.Push(aBuilder, aDisplayItem);
|
|
|
|
}
|
2009-12-12 21:50:25 +03:00
|
|
|
|
|
|
|
if (aFrame->IsVisibleForPainting(aBuilder)) {
|
|
|
|
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
|
2009-12-12 21:50:30 +03:00
|
|
|
// currentItem may be null, when none of the table parts have a
|
|
|
|
// background or border
|
|
|
|
if (currentItem) {
|
|
|
|
currentItem->UpdateForFrameBackground(aFrame);
|
|
|
|
}
|
|
|
|
|
2009-12-12 21:50:25 +03:00
|
|
|
// Paint the outset box-shadows for the table frames
|
2012-07-30 18:20:58 +04:00
|
|
|
bool hasBoxShadow = aFrame->GetStyleBorder()->mBoxShadow != nullptr;
|
2009-12-12 21:50:25 +03:00
|
|
|
if (hasBoxShadow) {
|
2010-08-13 14:01:13 +04:00
|
|
|
nsresult rv = lists->BorderBackground()->AppendNewToTop(
|
|
|
|
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
|
2009-12-12 21:50:25 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2008-12-03 04:20:21 +03:00
|
|
|
|
2009-12-12 21:50:25 +03:00
|
|
|
// Create dedicated background display items per-frame when we're
|
|
|
|
// handling events.
|
|
|
|
// XXX how to handle collapsed borders?
|
|
|
|
if (aBuilder->IsForEventDelivery()) {
|
2012-11-10 03:14:59 +04:00
|
|
|
nsresult rv = nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
|
2012-09-13 14:34:23 +04:00
|
|
|
lists->BorderBackground());
|
2009-12-12 21:50:25 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2006-01-26 05:29:17 +03:00
|
|
|
|
2009-12-12 21:50:25 +03:00
|
|
|
// Paint the inset box-shadows for the table frames
|
|
|
|
if (hasBoxShadow) {
|
2010-08-13 14:01:13 +04:00
|
|
|
nsresult rv = lists->BorderBackground()->AppendNewToTop(
|
|
|
|
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
|
2009-12-12 21:50:25 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2009-02-10 11:45:13 +03:00
|
|
|
}
|
|
|
|
|
2006-09-20 01:39:33 +04:00
|
|
|
nsresult rv = aTraversal(aBuilder, aFrame, aDirtyRect, *lists);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2006-04-18 02:16:24 +04:00
|
|
|
if (sortEventBackgrounds) {
|
|
|
|
// Ensure that the table frame event background goes before the
|
|
|
|
// table rowgroups event backgrounds, before the table row event backgrounds,
|
|
|
|
// before everything else (cells and their blocks)
|
2012-07-30 18:20:58 +04:00
|
|
|
separatedCollection.BorderBackground()->Sort(aBuilder, CompareByTablePartRank, nullptr);
|
2006-05-01 05:18:32 +04:00
|
|
|
separatedCollection.MoveTo(aLists);
|
2006-04-18 02:16:24 +04:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2006-05-01 05:18:32 +04:00
|
|
|
return aFrame->DisplayOutline(aBuilder, aLists);
|
2002-02-26 03:27:42 +03:00
|
|
|
}
|
|
|
|
|
2009-12-12 21:50:25 +03:00
|
|
|
#ifdef DEBUG
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2009-12-12 21:50:25 +03:00
|
|
|
IsFrameAllowedInTable(nsIAtom* aType)
|
|
|
|
{
|
|
|
|
return IS_TABLE_CELL(aType) ||
|
|
|
|
nsGkAtoms::tableRowFrame == aType ||
|
|
|
|
nsGkAtoms::tableRowGroupFrame == aType ||
|
|
|
|
nsGkAtoms::scrollFrame == aType ||
|
|
|
|
nsGkAtoms::tableFrame == aType ||
|
|
|
|
nsGkAtoms::tableColFrame == aType ||
|
|
|
|
nsGkAtoms::tableColGroupFrame == aType;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2010-02-12 00:40:46 +03:00
|
|
|
AnyTablePartHasBorderOrBackground(nsIFrame* aStart, nsIFrame* aEnd)
|
2009-12-12 21:50:25 +03:00
|
|
|
{
|
2010-02-12 00:40:46 +03:00
|
|
|
for (nsIFrame* f = aStart; f != aEnd; f = f->GetNextSibling()) {
|
2010-02-02 02:21:13 +03:00
|
|
|
NS_ASSERTION(IsFrameAllowedInTable(f->GetType()), "unexpected frame type");
|
|
|
|
|
2012-08-29 09:39:31 +04:00
|
|
|
if (FrameHasBorderOrBackground(f))
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-12-12 21:50:30 +03:00
|
|
|
|
2010-02-02 02:21:13 +03:00
|
|
|
nsTableCellFrame *cellFrame = do_QueryFrame(f);
|
|
|
|
if (cellFrame)
|
|
|
|
continue;
|
2009-12-12 21:50:30 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
if (AnyTablePartHasBorderOrBackground(f->PrincipalChildList().FirstChild(), nullptr))
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-12-12 21:50:25 +03:00
|
|
|
}
|
2009-12-12 21:50:30 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2009-12-12 21:50:25 +03:00
|
|
|
}
|
|
|
|
|
2002-02-26 03:27:42 +03:00
|
|
|
// table paint code is concerned primarily with borders and bg color
|
2010-04-27 20:15:01 +04:00
|
|
|
// SEC: TODO: adjust the rect for captions
|
2006-01-26 05:29:17 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsRect& aDirtyRect,
|
|
|
|
const nsDisplayListSet& aLists)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2006-09-19 08:26:20 +04:00
|
|
|
DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255));
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsDisplayTableItem* item = nullptr;
|
2012-04-03 04:30:45 +04:00
|
|
|
if (IsVisibleInSelection(aBuilder)) {
|
|
|
|
if (GetStyleVisibility()->IsVisible()) {
|
|
|
|
nsMargin deflate = GetDeflationForBackground(PresContext());
|
|
|
|
// If 'deflate' is (0,0,0,0) then we can paint the table background
|
|
|
|
// in its own display item, so do that to take advantage of
|
|
|
|
// opacity and visibility optimizations
|
|
|
|
if (deflate == nsMargin(0, 0, 0, 0)) {
|
2012-11-10 03:14:59 +04:00
|
|
|
nsDisplayBackgroundImage* bg;
|
2012-04-13 15:44:06 +04:00
|
|
|
nsresult rv = DisplayBackgroundUnconditional(aBuilder, aLists, false, &bg);
|
2012-04-03 04:30:45 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// This background is created if any of the table parts are visible,
|
|
|
|
// or if we're doing event handling (since DisplayGenericTablePart
|
|
|
|
// needs the item for the |sortEventBackgrounds|-dependent code).
|
|
|
|
// Specific visibility decisions are delegated to the table background
|
|
|
|
// painter, which handles borders and backgrounds for the table.
|
|
|
|
if (aBuilder->IsForEventDelivery() ||
|
|
|
|
AnyTablePartHasBorderOrBackground(this, GetNextSibling()) ||
|
2012-07-30 18:20:58 +04:00
|
|
|
AnyTablePartHasBorderOrBackground(mColGroups.FirstChild(), nullptr)) {
|
2012-04-03 04:30:45 +04:00
|
|
|
item = new (aBuilder) nsDisplayTableBorderBackground(aBuilder, this);
|
|
|
|
nsresult rv = aLists.BorderBackground()->AppendNewToTop(item);
|
2009-07-22 04:44:52 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
}
|
2008-04-06 15:34:14 +04:00
|
|
|
return DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, item);
|
2006-01-26 05:29:17 +03:00
|
|
|
}
|
|
|
|
|
2009-07-22 04:44:52 +04:00
|
|
|
nsMargin
|
|
|
|
nsTableFrame::GetDeflationForBackground(nsPresContext* aPresContext) const
|
|
|
|
{
|
|
|
|
if (eCompatibility_NavQuirks != aPresContext->CompatibilityMode() ||
|
|
|
|
!IsBorderCollapse())
|
|
|
|
return nsMargin(0,0,0,0);
|
|
|
|
|
|
|
|
return GetOuterBCBorder();
|
|
|
|
}
|
|
|
|
|
2006-01-26 05:29:17 +03:00
|
|
|
// XXX We don't put the borders and backgrounds in tree order like we should.
|
|
|
|
// That requires some major surgery which we aren't going to do right now.
|
|
|
|
void
|
2011-04-08 05:04:40 +04:00
|
|
|
nsTableFrame::PaintTableBorderBackground(nsRenderingContext& aRenderingContext,
|
2006-01-26 05:29:17 +03:00
|
|
|
const nsRect& aDirtyRect,
|
2012-08-22 19:56:38 +04:00
|
|
|
nsPoint aPt, uint32_t aBGPaintFlags)
|
2006-01-26 05:29:17 +03:00
|
|
|
{
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext* presContext = PresContext();
|
2006-01-26 05:29:17 +03:00
|
|
|
|
|
|
|
TableBackgroundPainter painter(this, TableBackgroundPainter::eOrigin_Table,
|
2008-03-21 04:18:30 +03:00
|
|
|
presContext, aRenderingContext,
|
2009-09-13 02:44:18 +04:00
|
|
|
aDirtyRect, aPt, aBGPaintFlags);
|
2009-07-22 04:44:52 +04:00
|
|
|
nsMargin deflate = GetDeflationForBackground(presContext);
|
|
|
|
// If 'deflate' is (0,0,0,0) then we'll paint the table background
|
|
|
|
// in a separate display item, so don't do it here.
|
2011-04-19 07:07:22 +04:00
|
|
|
nsresult rv = painter.PaintTable(this, deflate, deflate != nsMargin(0, 0, 0, 0));
|
2009-07-22 04:44:52 +04:00
|
|
|
if (NS_FAILED(rv)) return;
|
2006-01-26 05:29:17 +03:00
|
|
|
|
|
|
|
if (GetStyleVisibility()->IsVisible()) {
|
|
|
|
if (!IsBorderCollapse()) {
|
2012-08-09 11:09:40 +04:00
|
|
|
int skipSides = GetSkipSides();
|
2008-03-21 04:18:30 +03:00
|
|
|
nsRect rect(aPt, mRect.Size());
|
2006-01-26 05:29:17 +03:00
|
|
|
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
|
2010-04-03 05:58:26 +04:00
|
|
|
aDirtyRect, rect, mStyleContext, skipSides);
|
2004-03-09 09:48:35 +03:00
|
|
|
}
|
2006-01-26 05:29:17 +03:00
|
|
|
else {
|
2008-03-21 04:18:30 +03:00
|
|
|
// XXX we should probably get rid of this translation at some stage
|
|
|
|
// But that would mean modifying PaintBCBorders, ugh
|
2011-04-08 05:04:40 +04:00
|
|
|
nsRenderingContext::AutoPushTranslation translate(&aRenderingContext, aPt);
|
2008-03-21 04:18:30 +03:00
|
|
|
PaintBCBorders(aRenderingContext, aDirtyRect - aPt);
|
1998-12-18 01:59:40 +03:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-08-09 11:09:40 +04:00
|
|
|
int
|
1998-10-20 21:45:07 +04:00
|
|
|
nsTableFrame::GetSkipSides() const
|
|
|
|
{
|
2012-08-09 11:09:40 +04:00
|
|
|
int skip = 0;
|
1998-11-11 22:56:02 +03:00
|
|
|
// frame attribute was accounted for in nsHTMLTableElement::MapTableBorderInto
|
|
|
|
// account for pagination
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != GetPrevInFlow()) {
|
1998-10-20 21:45:07 +04:00
|
|
|
skip |= 1 << NS_SIDE_TOP;
|
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != GetNextInFlow()) {
|
1998-10-20 21:45:07 +04:00
|
|
|
skip |= 1 << NS_SIDE_BOTTOM;
|
|
|
|
}
|
|
|
|
return skip;
|
|
|
|
}
|
|
|
|
|
2004-03-09 09:48:35 +03:00
|
|
|
void
|
2004-01-18 13:28:40 +03:00
|
|
|
nsTableFrame::SetColumnDimensions(nscoord aHeight,
|
2000-02-12 04:55:40 +03:00
|
|
|
const nsMargin& aBorderPadding)
|
1999-06-08 01:10:25 +04:00
|
|
|
{
|
|
|
|
nscoord cellSpacingX = GetCellSpacingX();
|
2004-03-09 09:48:35 +03:00
|
|
|
nscoord cellSpacingY = GetCellSpacingY();
|
|
|
|
nscoord colHeight = aHeight -= aBorderPadding.top + aBorderPadding.bottom +
|
|
|
|
2* cellSpacingY;
|
1999-06-08 01:10:25 +04:00
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
nsTableIterator iter(mColGroups);
|
2008-08-04 11:27:32 +04:00
|
|
|
nsIFrame* colGroupFrame = iter.First();
|
2011-09-29 10:19:26 +04:00
|
|
|
bool tableIsLTR = GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colX =tableIsLTR ? 0 : NS_MAX(0, GetColCount() - 1);
|
|
|
|
int32_t tableColIncr = tableIsLTR ? 1 : -1;
|
2004-03-09 09:48:35 +03:00
|
|
|
nsPoint colGroupOrigin(aBorderPadding.left + cellSpacingX,
|
|
|
|
aBorderPadding.top + cellSpacingY);
|
2012-06-01 23:56:33 +04:00
|
|
|
while (colGroupFrame) {
|
|
|
|
MOZ_ASSERT(colGroupFrame->GetType() == nsGkAtoms::tableColGroupFrame);
|
1999-06-08 01:10:25 +04:00
|
|
|
nscoord colGroupWidth = 0;
|
2010-04-27 20:15:01 +04:00
|
|
|
nsTableIterator iterCol(*colGroupFrame);
|
2008-08-04 11:27:32 +04:00
|
|
|
nsIFrame* colFrame = iterCol.First();
|
2000-04-29 01:05:31 +04:00
|
|
|
nsPoint colOrigin(0,0);
|
2012-06-01 23:56:33 +04:00
|
|
|
while (colFrame) {
|
2003-05-15 07:42:21 +04:00
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN ==
|
|
|
|
colFrame->GetStyleDisplay()->mDisplay) {
|
2004-12-01 21:47:34 +03:00
|
|
|
NS_ASSERTION(colX < GetColCount(), "invalid number of columns");
|
2001-03-13 09:38:59 +03:00
|
|
|
nscoord colWidth = GetColumnWidth(colX);
|
1999-08-10 06:45:18 +04:00
|
|
|
nsRect colRect(colOrigin.x, colOrigin.y, colWidth, colHeight);
|
2003-07-07 06:01:29 +04:00
|
|
|
colFrame->SetRect(colRect);
|
2000-04-29 01:05:31 +04:00
|
|
|
colOrigin.x += colWidth + cellSpacingX;
|
2004-03-09 09:48:35 +03:00
|
|
|
colGroupWidth += colWidth + cellSpacingX;
|
2008-08-04 11:27:32 +04:00
|
|
|
colX += tableColIncr;
|
1999-08-10 06:45:18 +04:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
colFrame = iterCol.Next();
|
1999-06-08 01:10:25 +04:00
|
|
|
}
|
2004-03-09 09:48:35 +03:00
|
|
|
if (colGroupWidth) {
|
|
|
|
colGroupWidth -= cellSpacingX;
|
|
|
|
}
|
|
|
|
|
1999-06-08 01:10:25 +04:00
|
|
|
nsRect colGroupRect(colGroupOrigin.x, colGroupOrigin.y, colGroupWidth, colHeight);
|
2003-07-07 06:01:29 +04:00
|
|
|
colGroupFrame->SetRect(colGroupRect);
|
2008-08-04 11:27:32 +04:00
|
|
|
colGroupFrame = iter.Next();
|
2004-03-09 09:48:35 +03:00
|
|
|
colGroupOrigin.x += colGroupWidth + cellSpacingX;
|
1999-06-08 01:10:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
// SEC: TODO need to worry about continuing frames prev/next in flow for splitting across pages.
|
|
|
|
|
2001-08-06 18:48:09 +04:00
|
|
|
// XXX this could be made more general to handle row modifications that change the
|
|
|
|
// table height, but first we need to scrutinize every Invalidate
|
2008-02-07 01:01:41 +03:00
|
|
|
void
|
|
|
|
nsTableFrame::ProcessRowInserted(nscoord aNewHeight)
|
2001-08-06 18:48:09 +04:00
|
|
|
{
|
2011-10-17 18:59:28 +04:00
|
|
|
SetRowInserted(false); // reset the bit that got us here
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableFrame::RowGroupArray rowGroups;
|
2008-02-07 01:01:41 +03:00
|
|
|
OrderRowGroups(rowGroups);
|
2001-08-06 18:48:09 +04:00
|
|
|
// find the row group containing the inserted row
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
|
|
|
NS_ASSERTION(rgFrame, "Must have rgFrame here");
|
2011-08-25 00:54:30 +04:00
|
|
|
nsIFrame* childFrame = rgFrame->GetFirstPrincipalChild();
|
2001-08-06 18:48:09 +04:00
|
|
|
// find the row that was inserted first
|
|
|
|
while (childFrame) {
|
2009-03-25 01:10:06 +03:00
|
|
|
nsTableRowFrame *rowFrame = do_QueryFrame(childFrame);
|
|
|
|
if (rowFrame) {
|
2001-08-06 18:48:09 +04:00
|
|
|
if (rowFrame->IsFirstInserted()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
rowFrame->SetFirstInserted(false);
|
2008-02-07 01:01:41 +03:00
|
|
|
// damage the table from the 1st row inserted to the end of the table
|
2012-08-29 09:48:45 +04:00
|
|
|
nsIFrame::InvalidateFrame();
|
2008-02-07 01:01:41 +03:00
|
|
|
// XXXbz didn't we do this up front? Why do we need to do it again?
|
2011-10-17 18:59:28 +04:00
|
|
|
SetRowInserted(false);
|
2001-08-06 18:48:09 +04:00
|
|
|
return; // found it, so leave
|
|
|
|
}
|
|
|
|
}
|
2003-07-07 06:01:29 +04:00
|
|
|
childFrame = childFrame->GetNextSibling();
|
2001-08-06 18:48:09 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2000-09-13 02:48:35 +04:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
/* virtual */ void
|
|
|
|
nsTableFrame::MarkIntrinsicWidthsDirty()
|
|
|
|
{
|
2010-11-14 21:26:36 +03:00
|
|
|
nsITableLayoutStrategy* tls = LayoutStrategy();
|
2012-10-26 17:32:10 +04:00
|
|
|
if (MOZ_UNLIKELY(!tls)) {
|
2010-11-14 21:26:36 +03:00
|
|
|
// This is a FrameNeedsReflow() from nsBlockFrame::RemoveFrame()
|
|
|
|
// walking up the ancestor chain in a table next-in-flow. In this case
|
|
|
|
// our original first-in-flow (which owns the TableLayoutStrategy) has
|
|
|
|
// already been destroyed and unhooked from the flow chain and thusly
|
|
|
|
// LayoutStrategy() returns null. All the frames in the flow will be
|
|
|
|
// destroyed so no need to mark anything dirty here. See bug 595758.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
tls->MarkIntrinsicWidthsDirty();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
|
|
|
// XXXldb Call SetBCDamageArea?
|
|
|
|
|
2011-12-28 00:18:48 +04:00
|
|
|
nsContainerFrame::MarkIntrinsicWidthsDirty();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nscoord
|
2011-04-08 05:04:40 +04:00
|
|
|
nsTableFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
{
|
|
|
|
if (NeedToCalcBCBorders())
|
|
|
|
CalcBCBorders();
|
|
|
|
|
|
|
|
ReflowColGroups(aRenderingContext);
|
|
|
|
|
|
|
|
return LayoutStrategy()->GetMinWidth(aRenderingContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nscoord
|
2011-04-08 05:04:40 +04:00
|
|
|
nsTableFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
{
|
|
|
|
if (NeedToCalcBCBorders())
|
|
|
|
CalcBCBorders();
|
|
|
|
|
|
|
|
ReflowColGroups(aRenderingContext);
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return LayoutStrategy()->GetPrefWidth(aRenderingContext, false);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nsIFrame::IntrinsicWidthOffsetData
|
2011-04-08 05:04:40 +04:00
|
|
|
nsTableFrame::IntrinsicWidthOffsets(nsRenderingContext* aRenderingContext)
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
{
|
|
|
|
IntrinsicWidthOffsetData result =
|
2011-12-28 00:18:48 +04:00
|
|
|
nsContainerFrame::IntrinsicWidthOffsets(aRenderingContext);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
Bug 659828 - Part 1: Apply table margins to the outer table frame instead of the inner table frame (also fixes bug 87277); r=dbaron
Outer table frames act as CSS2.1 table wrapper boxes. We used to lay them out
without taking their margins into the account, which meant that their width was
always equal to the available width. This breaks horizontal positioning of
absolutely positioned kids of a table frame.
The main purpose of this patch is to apply the margins of tables to their outer
frame, instead of the inner frame. This means that the inner table frame will
always have a zero margin, which means that a lot of the stuff which used to
rely on the fact that table margins are applied to the inner frame need to
change.
In particular, in order to get the computed margins of a table, we used to query
the inner table frame, and this patch corrects that. Also, when shrink wrapping
tables, we used to not take the margins of the inner table frame into account,
which is fixed by this patch too. nsBlockReflowState::
ComputeReplacedBlockOffsetsForFloats also needed to be changed to read the
margin values from the outer frame too.
Also, as part of this patch, we start to respect the CSS2.1 margin model for
captions on all sides. This means that in particular, the top/bottom margins on
the top-outside and bottom-outside captions will not be collapsed with the
top/bottom margins of the table, and that the margins of the caption element
contribute to the width and height of the outer table frame. The
427129-table-caption reftest has been modified to match this new behavior.
Another side effect of this bug is fixing bug 87277, and the reftests for that
bug are marked as passing in this patch.
2011-06-01 03:02:56 +04:00
|
|
|
result.hMargin = 0;
|
|
|
|
result.hPctMargin = 0;
|
|
|
|
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (IsBorderCollapse()) {
|
|
|
|
result.hPadding = 0;
|
|
|
|
result.hPctPadding = 0;
|
|
|
|
|
|
|
|
nsMargin outerBC = GetIncludedOuterBCBorder();
|
|
|
|
result.hBorder = outerBC.LeftRight();
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nsSize
|
2011-04-08 05:04:40 +04:00
|
|
|
nsTableFrame::ComputeSize(nsRenderingContext *aRenderingContext,
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nsSize aCBSize, nscoord aAvailableWidth,
|
|
|
|
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFlags)
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
{
|
|
|
|
nsSize result =
|
2011-12-28 00:18:48 +04:00
|
|
|
nsContainerFrame::ComputeSize(aRenderingContext, aCBSize, aAvailableWidth,
|
2012-03-16 22:01:05 +04:00
|
|
|
aMargin, aBorder, aPadding, aFlags);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
2012-01-25 05:21:29 +04:00
|
|
|
// If we're a container for font size inflation, then shrink
|
|
|
|
// wrapping inside of us should not apply font size inflation.
|
2012-05-21 09:18:27 +04:00
|
|
|
AutoMaybeDisableFontInflation an(this);
|
2012-01-25 05:21:29 +04:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
// Tables never shrink below their min width.
|
|
|
|
nscoord minWidth = GetMinWidth(aRenderingContext);
|
|
|
|
if (minWidth > result.width)
|
|
|
|
result.width = minWidth;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
nscoord
|
2011-04-08 05:04:40 +04:00
|
|
|
nsTableFrame::TableShrinkWidthToFit(nsRenderingContext *aRenderingContext,
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nscoord aWidthInCB)
|
|
|
|
{
|
2012-01-25 05:21:29 +04:00
|
|
|
// If we're a container for font size inflation, then shrink
|
|
|
|
// wrapping inside of us should not apply font size inflation.
|
2012-05-21 09:18:27 +04:00
|
|
|
AutoMaybeDisableFontInflation an(this);
|
2012-01-25 05:21:29 +04:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
nscoord result;
|
|
|
|
nscoord minWidth = GetMinWidth(aRenderingContext);
|
|
|
|
if (minWidth > aWidthInCB) {
|
|
|
|
result = minWidth;
|
|
|
|
} else {
|
|
|
|
// Tables shrink width to fit with a slightly different algorithm
|
|
|
|
// from the one they use for their intrinsic widths (the difference
|
|
|
|
// relates to handling of percentage widths on columns). So this
|
|
|
|
// function differs from nsFrame::ShrinkWidthToFit by only the
|
|
|
|
// following line.
|
|
|
|
// Since we've already called GetMinWidth, we don't need to do any
|
|
|
|
// of the other stuff GetPrefWidth does.
|
|
|
|
nscoord prefWidth =
|
2011-10-17 18:59:28 +04:00
|
|
|
LayoutStrategy()->GetPrefWidth(aRenderingContext, true);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (prefWidth > aWidthInCB) {
|
|
|
|
result = aWidthInCB;
|
|
|
|
} else {
|
|
|
|
result = prefWidth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nsSize
|
2011-04-08 05:04:40 +04:00
|
|
|
nsTableFrame::ComputeAutoSize(nsRenderingContext *aRenderingContext,
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nsSize aCBSize, nscoord aAvailableWidth,
|
|
|
|
nsSize aMargin, nsSize aBorder, nsSize aPadding,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aShrinkWrap)
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
{
|
|
|
|
// Tables always shrink-wrap.
|
|
|
|
nscoord cbBased = aAvailableWidth - aMargin.width - aBorder.width -
|
|
|
|
aPadding.width;
|
|
|
|
return nsSize(TableShrinkWidthToFit(aRenderingContext, cbBased),
|
|
|
|
NS_UNCONSTRAINEDSIZE);
|
|
|
|
}
|
|
|
|
|
2007-06-26 00:34:35 +04:00
|
|
|
// Return true if aParentReflowState.frame or any of its ancestors within
|
|
|
|
// the containing table have non-auto height. (e.g. pct or fixed height)
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2007-06-26 00:34:35 +04:00
|
|
|
nsTableFrame::AncestorsHaveStyleHeight(const nsHTMLReflowState& aParentReflowState)
|
2002-04-01 10:46:17 +04:00
|
|
|
{
|
2007-06-26 00:34:35 +04:00
|
|
|
for (const nsHTMLReflowState* rs = &aParentReflowState;
|
|
|
|
rs && rs->frame; rs = rs->parentReflowState) {
|
|
|
|
nsIAtom* frameType = rs->frame->GetType();
|
|
|
|
if (IS_TABLE_CELL(frameType) ||
|
2006-12-26 20:47:52 +03:00
|
|
|
(nsGkAtoms::tableRowFrame == frameType) ||
|
|
|
|
(nsGkAtoms::tableRowGroupFrame == frameType)) {
|
2010-08-25 14:17:55 +04:00
|
|
|
const nsStyleCoord &height = rs->mStylePosition->mHeight;
|
2012-11-21 20:19:30 +04:00
|
|
|
// calc() with percentages treated like 'auto' on internal table elements
|
|
|
|
if (height.GetUnit() != eStyleUnit_Auto &&
|
|
|
|
(!height.IsCalcUnit() || !height.HasPercent())) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2002-04-01 10:46:17 +04:00
|
|
|
}
|
|
|
|
}
|
2006-12-26 20:47:52 +03:00
|
|
|
else if (nsGkAtoms::tableFrame == frameType) {
|
2002-04-01 10:46:17 +04:00
|
|
|
// we reached the containing table, so always return
|
2007-06-26 00:34:35 +04:00
|
|
|
if (rs->mStylePosition->mHeight.GetUnit() != eStyleUnit_Auto) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2002-04-01 10:46:17 +04:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
else return false;
|
2002-04-01 10:46:17 +04:00
|
|
|
}
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2002-04-01 10:46:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// See if a special height reflow needs to occur and if so, call RequestSpecialHeightReflow
|
2001-11-05 03:15:51 +03:00
|
|
|
void
|
2002-04-01 10:46:17 +04:00
|
|
|
nsTableFrame::CheckRequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState)
|
2001-11-05 03:15:51 +03:00
|
|
|
{
|
2010-08-25 14:17:55 +04:00
|
|
|
NS_ASSERTION(IS_TABLE_CELL(aReflowState.frame->GetType()) ||
|
|
|
|
aReflowState.frame->GetType() == nsGkAtoms::tableRowFrame ||
|
|
|
|
aReflowState.frame->GetType() == nsGkAtoms::tableRowGroupFrame ||
|
|
|
|
aReflowState.frame->GetType() == nsGkAtoms::tableFrame,
|
|
|
|
"unexpected frame type");
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (!aReflowState.frame->GetPrevInFlow() && // 1st in flow
|
2007-08-02 22:08:05 +04:00
|
|
|
(NS_UNCONSTRAINEDSIZE == aReflowState.ComputedHeight() || // no computed height
|
2010-04-27 20:15:01 +04:00
|
|
|
0 == aReflowState.ComputedHeight()) &&
|
2007-06-26 00:34:35 +04:00
|
|
|
eStyleUnit_Percent == aReflowState.mStylePosition->mHeight.GetUnit() && // pct height
|
|
|
|
nsTableFrame::AncestorsHaveStyleHeight(*aReflowState.parentReflowState)) {
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nsTableFrame::RequestSpecialHeightReflow(aReflowState);
|
2002-04-01 10:46:17 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Notify the frame and its ancestors (up to the containing table) that a special
|
|
|
|
// height reflow will occur. During a special height reflow, a table, row group,
|
2010-04-27 20:15:01 +04:00
|
|
|
// row, or cell returns the last size it was reflowed at. However, the table may
|
|
|
|
// change the height of row groups, rows, cells in DistributeHeightToRows after.
|
2002-04-01 10:46:17 +04:00
|
|
|
// And the row group can change the height of rows, cells in CalculateRowHeights.
|
|
|
|
void
|
|
|
|
nsTableFrame::RequestSpecialHeightReflow(const nsHTMLReflowState& aReflowState)
|
|
|
|
{
|
|
|
|
// notify the frame and its ancestors of the special reflow, stopping at the containing table
|
|
|
|
for (const nsHTMLReflowState* rs = &aReflowState; rs && rs->frame; rs = rs->parentReflowState) {
|
2003-10-31 23:19:18 +03:00
|
|
|
nsIAtom* frameType = rs->frame->GetType();
|
2009-12-12 22:35:26 +03:00
|
|
|
NS_ASSERTION(IS_TABLE_CELL(frameType) ||
|
|
|
|
nsGkAtoms::tableRowFrame == frameType ||
|
|
|
|
nsGkAtoms::tableRowGroupFrame == frameType ||
|
|
|
|
nsGkAtoms::tableFrame == frameType,
|
|
|
|
"unexpected frame type");
|
2010-04-27 20:15:01 +04:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
rs->frame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
|
2006-12-26 20:47:52 +03:00
|
|
|
if (nsGkAtoms::tableFrame == frameType) {
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
NS_ASSERTION(rs != &aReflowState,
|
|
|
|
"should not request special height reflow for table");
|
|
|
|
// always stop when we reach a table
|
|
|
|
break;
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-04-01 10:46:17 +04:00
|
|
|
/******************************************************************************************
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
* Before reflow, intrinsic width calculation is done using GetMinWidth
|
|
|
|
* and GetPrefWidth. This used to be known as pass 1 reflow.
|
2002-04-01 10:46:17 +04:00
|
|
|
*
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
* After the intrinsic width calculation, the table determines the
|
|
|
|
* column widths using BalanceColumnWidths() and
|
2002-04-01 10:46:17 +04:00
|
|
|
* then reflows each child again with a constrained avail width. This reflow is referred to
|
2010-04-27 20:15:01 +04:00
|
|
|
* as the pass 2 reflow.
|
2002-04-01 10:46:17 +04:00
|
|
|
*
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
* A special height reflow (pass 3 reflow) can occur during an initial or resize reflow
|
2010-04-27 20:15:01 +04:00
|
|
|
* if (a) a row group, row, cell, or a frame inside a cell has a percent height but no computed
|
|
|
|
* height or (b) in paginated mode, a table has a height. (a) supports percent nested tables
|
|
|
|
* contained inside cells whose heights aren't known until after the pass 2 reflow. (b) is
|
|
|
|
* necessary because the table cannot split until after the pass 2 reflow. The mechanics of
|
|
|
|
* the special height reflow (variety a) are as follows:
|
|
|
|
*
|
2002-04-01 10:46:17 +04:00
|
|
|
* 1) Each table related frame (table, row group, row, cell) implements NeedsSpecialReflow()
|
2010-04-27 20:15:01 +04:00
|
|
|
* to indicate that it should get the reflow. It does this when it has a percent height but
|
2002-04-01 10:46:17 +04:00
|
|
|
* no computed height by calling CheckRequestSpecialHeightReflow(). This method calls
|
2010-04-27 20:15:01 +04:00
|
|
|
* RequestSpecialHeightReflow() which calls SetNeedSpecialReflow() on its ancestors until
|
|
|
|
* it reaches the containing table and calls SetNeedToInitiateSpecialReflow() on it. For
|
2002-04-01 10:46:17 +04:00
|
|
|
* percent height frames inside cells, during DidReflow(), the cell's NotifyPercentHeight()
|
2010-04-27 20:15:01 +04:00
|
|
|
* is called (the cell is the reflow state's mPercentHeightObserver in this case).
|
2002-04-01 10:46:17 +04:00
|
|
|
* NotifyPercentHeight() calls RequestSpecialHeightReflow().
|
|
|
|
*
|
|
|
|
* 2) After the pass 2 reflow, if the table's NeedToInitiateSpecialReflow(true) was called, it
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
* will do the special height reflow, setting the reflow state's mFlags.mSpecialHeightReflow
|
2002-04-01 10:46:17 +04:00
|
|
|
* to true and mSpecialHeightInitiator to itself. It won't do this if IsPrematureSpecialHeightReflow()
|
2005-11-21 01:05:24 +03:00
|
|
|
* returns true because in that case another special height reflow will be coming along with the
|
2002-04-01 10:46:17 +04:00
|
|
|
* containing table as the mSpecialHeightInitiator. It is only relevant to do the reflow when
|
|
|
|
* the mSpecialHeightInitiator is the containing table, because if it is a remote ancestor, then
|
|
|
|
* appropriate heights will not be known.
|
|
|
|
*
|
|
|
|
* 3) Since the heights of the table, row groups, rows, and cells was determined during the pass 2
|
|
|
|
* reflow, they return their last desired sizes during the special height reflow. The reflow only
|
|
|
|
* permits percent height frames inside the cells to resize based on the cells height and that height
|
|
|
|
* was determined during the pass 2 reflow.
|
|
|
|
*
|
|
|
|
* So, in the case of deeply nested tables, all of the tables that were told to initiate a special
|
|
|
|
* reflow will do so, but if a table is already in a special reflow, it won't inititate the reflow
|
|
|
|
* until the current initiator is its containing table. Since these reflows are only received by
|
|
|
|
* frames that need them and they don't cause any rebalancing of tables, the extra overhead is minimal.
|
|
|
|
*
|
|
|
|
* The type of special reflow that occurs during printing (variety b) follows the same mechanism except
|
|
|
|
* that all frames will receive the reflow even if they don't really need them.
|
|
|
|
*
|
|
|
|
* Open issues with the special height reflow:
|
|
|
|
*
|
2010-04-27 20:15:01 +04:00
|
|
|
* 1) At some point there should be 2 kinds of special height reflows because (a) and (b) above are
|
|
|
|
* really quite different. This would avoid unnecessary reflows during printing.
|
|
|
|
* 2) When a cell contains frames whose percent heights > 100%, there is data loss (see bug 115245).
|
|
|
|
* However, this can also occur if a cell has a fixed height and there is no special height reflow.
|
2002-04-01 10:46:17 +04:00
|
|
|
*
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
* XXXldb Special height reflow should really be its own method, not
|
|
|
|
* part of nsIFrame::Reflow. It should then call nsIFrame::Reflow on
|
|
|
|
* the contents of the cells to do the necessary vertical resizing.
|
|
|
|
*
|
2002-04-01 10:46:17 +04:00
|
|
|
******************************************************************************************/
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1998-05-29 01:39:22 +04:00
|
|
|
/* Layout the entire inner table. */
|
2009-02-18 22:47:22 +03:00
|
|
|
NS_METHOD nsTableFrame::Reflow(nsPresContext* aPresContext,
|
2001-03-13 09:38:59 +03:00
|
|
|
nsHTMLReflowMetrics& aDesiredSize,
|
1998-10-02 08:10:00 +04:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
2001-03-13 09:38:59 +03:00
|
|
|
nsReflowStatus& aStatus)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
DO_GLOBAL_REFLOW_COUNT("nsTableFrame");
|
2001-11-14 16:40:03 +03:00
|
|
|
DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isPaginated = aPresContext->IsPaginated();
|
2002-04-01 10:46:17 +04:00
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
2006-02-22 00:33:47 +03:00
|
|
|
if (!GetPrevInFlow() && !mTableLayoutStrategy) {
|
2011-10-17 18:59:28 +04:00
|
|
|
NS_ASSERTION(false, "strategy should have been created in Init");
|
2001-03-13 09:38:59 +03:00
|
|
|
return NS_ERROR_NULL_POINTER;
|
|
|
|
}
|
1998-10-11 13:18:27 +04:00
|
|
|
nsresult rv = NS_OK;
|
1998-10-01 08:46:11 +04:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
// see if collapsing borders need to be calculated
|
2006-02-22 00:33:47 +03:00
|
|
|
if (!GetPrevInFlow() && IsBorderCollapse() && NeedToCalcBCBorders()) {
|
2005-02-07 04:58:25 +03:00
|
|
|
CalcBCBorders();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
1998-06-23 09:43:27 +04:00
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
aDesiredSize.width = aReflowState.availableWidth;
|
2000-03-15 18:16:03 +03:00
|
|
|
|
2002-03-18 00:35:08 +03:00
|
|
|
// Check for an overflow list, and append any row group frames being pushed
|
|
|
|
MoveOverflowToChildList(aPresContext);
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool haveDesiredHeight = false;
|
2011-10-17 18:59:28 +04:00
|
|
|
SetHaveReflowedColGroups(false);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
// Reflow the entire table (pass 2 and possibly pass 3). This phase is necessary during a
|
|
|
|
// constrained initial reflow and other reflows which require either a strategy init or balance.
|
|
|
|
// This isn't done during an unconstrained reflow, because it will occur later when the parent
|
2002-05-09 18:28:28 +04:00
|
|
|
// reflows with a constrained width.
|
2007-05-06 23:16:51 +04:00
|
|
|
if (NS_SUBTREE_DIRTY(this) ||
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
aReflowState.ShouldReflowAllKids() ||
|
2006-12-13 06:45:28 +03:00
|
|
|
IsGeometryDirty() ||
|
2008-11-26 00:27:53 +03:00
|
|
|
aReflowState.mFlags.mVResize) {
|
2008-11-26 00:27:53 +03:00
|
|
|
|
|
|
|
if (aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE ||
|
|
|
|
// Also check mVResize, to handle the first Reflow preceding a
|
|
|
|
// special height Reflow, when we've already had a special height
|
|
|
|
// Reflow (where mComputedHeight would not be
|
|
|
|
// NS_UNCONSTRAINEDSIZE, but without a style change in between).
|
|
|
|
aReflowState.mFlags.mVResize) {
|
|
|
|
// XXX Eventually, we should modify DistributeHeightToRows to use
|
|
|
|
// nsTableRowFrame::GetHeight instead of nsIFrame::GetSize().height.
|
|
|
|
// That way, it will make its calculations based on internal table
|
|
|
|
// frame heights as they are before they ever had any extra height
|
|
|
|
// distributed to them. In the meantime, this reflows all the
|
|
|
|
// internal table frames, which restores them to their state before
|
|
|
|
// DistributeHeightToRows was called.
|
|
|
|
SetGeometryDirty();
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool needToInitiateSpecialReflow =
|
2008-11-26 00:27:53 +03:00
|
|
|
!!(GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
|
2010-04-27 20:15:01 +04:00
|
|
|
// see if an extra reflow will be necessary in pagination mode when there is a specified table height
|
2006-02-22 00:33:47 +03:00
|
|
|
if (isPaginated && !GetPrevInFlow() && (NS_UNCONSTRAINEDSIZE != aReflowState.availableHeight)) {
|
2003-12-28 20:02:40 +03:00
|
|
|
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
2010-04-27 20:15:01 +04:00
|
|
|
if ((tableSpecifiedHeight > 0) &&
|
2002-04-11 01:32:41 +04:00
|
|
|
(tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
needToInitiateSpecialReflow = true;
|
2000-02-11 06:55:33 +03:00
|
|
|
}
|
2001-03-13 09:38:59 +03:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame* lastChildReflowed = nullptr;
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
2007-10-09 06:39:06 +04:00
|
|
|
NS_ASSERTION(!aReflowState.mFlags.mSpecialHeightReflow,
|
|
|
|
"Shouldn't be in special height reflow here!");
|
2002-04-11 01:32:41 +04:00
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
// do the pass 2 reflow unless this is a special height reflow and we will be
|
2002-04-11 01:32:41 +04:00
|
|
|
// initiating a special height reflow
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
// XXXldb I changed this. Should I change it back?
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
// if we need to initiate a special height reflow, then don't constrain the
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
// height of the reflow before that
|
2010-04-27 20:15:01 +04:00
|
|
|
nscoord availHeight = needToInitiateSpecialReflow
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
? NS_UNCONSTRAINEDSIZE : aReflowState.availableHeight;
|
|
|
|
|
|
|
|
ReflowTable(aDesiredSize, aReflowState, availHeight,
|
|
|
|
lastChildReflowed, aStatus);
|
2002-04-11 01:32:41 +04:00
|
|
|
|
2005-06-21 08:50:42 +04:00
|
|
|
// reevaluate special height reflow conditions
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)
|
2011-10-17 18:59:28 +04:00
|
|
|
needToInitiateSpecialReflow = true;
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
|
|
|
// XXXldb Are all these conditions correct?
|
|
|
|
if (needToInitiateSpecialReflow && NS_FRAME_IS_COMPLETE(aStatus)) {
|
|
|
|
// XXXldb Do we need to set the mVResize flag on any reflow states?
|
|
|
|
|
2007-10-09 06:39:06 +04:00
|
|
|
nsHTMLReflowState &mutable_rs =
|
|
|
|
const_cast<nsHTMLReflowState&>(aReflowState);
|
|
|
|
|
2002-04-11 01:32:41 +04:00
|
|
|
// distribute extra vertical space to rows
|
2010-04-27 20:15:01 +04:00
|
|
|
CalcDesiredHeight(aReflowState, aDesiredSize);
|
2011-10-17 18:59:28 +04:00
|
|
|
mutable_rs.mFlags.mSpecialHeightReflow = true;
|
2002-04-01 10:46:17 +04:00
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
ReflowTable(aDesiredSize, aReflowState, aReflowState.availableHeight,
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
lastChildReflowed, aStatus);
|
2005-01-01 21:23:33 +03:00
|
|
|
|
2002-03-04 18:48:56 +03:00
|
|
|
if (lastChildReflowed && NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
|
|
|
// if there is an incomplete child, then set the desired height to include it but not the next one
|
2003-12-28 20:02:40 +03:00
|
|
|
nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
|
2005-01-01 21:23:33 +03:00
|
|
|
aDesiredSize.height = borderPadding.bottom + GetCellSpacingY() +
|
|
|
|
lastChildReflowed->GetRect().YMost();
|
2002-03-04 18:48:56 +03:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
haveDesiredHeight = true;
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mutable_rs.mFlags.mSpecialHeightReflow = false;
|
2007-10-09 06:39:06 +04:00
|
|
|
}
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
2008-08-07 18:19:33 +04:00
|
|
|
else {
|
|
|
|
// Calculate the overflow area contribution from our children.
|
2011-08-25 00:54:30 +04:00
|
|
|
for (nsIFrame* kid = GetFirstPrincipalChild(); kid; kid = kid->GetNextSibling()) {
|
2010-10-07 08:25:46 +04:00
|
|
|
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kid);
|
2008-08-07 18:19:33 +04:00
|
|
|
}
|
|
|
|
}
|
1999-09-13 07:19:39 +04:00
|
|
|
|
2007-01-26 03:05:12 +03:00
|
|
|
aDesiredSize.width = aReflowState.ComputedWidth() +
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
aReflowState.mComputedBorderPadding.LeftRight();
|
2001-11-05 03:15:51 +03:00
|
|
|
if (!haveDesiredHeight) {
|
2010-04-27 20:15:01 +04:00
|
|
|
CalcDesiredHeight(aReflowState, aDesiredSize);
|
2001-08-08 05:13:35 +04:00
|
|
|
}
|
2001-08-06 18:48:09 +04:00
|
|
|
if (IsRowInserted()) {
|
2008-02-07 01:01:41 +03:00
|
|
|
ProcessRowInserted(aDesiredSize.height);
|
2001-08-06 18:48:09 +04:00
|
|
|
}
|
|
|
|
|
2003-12-28 20:02:40 +03:00
|
|
|
nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
|
2004-01-18 13:28:40 +03:00
|
|
|
SetColumnDimensions(aDesiredSize.height, borderPadding);
|
2006-03-04 08:26:57 +03:00
|
|
|
if (NeedToCollapse() &&
|
|
|
|
(NS_UNCONSTRAINEDSIZE != aReflowState.availableWidth)) {
|
|
|
|
AdjustForCollapsingRowsCols(aDesiredSize, borderPadding);
|
1999-10-15 08:09:22 +04:00
|
|
|
}
|
1999-06-08 01:10:25 +04:00
|
|
|
|
2004-09-19 13:50:41 +04:00
|
|
|
// make sure the table overflow area does include the table rect.
|
|
|
|
nsRect tableRect(0, 0, aDesiredSize.width, aDesiredSize.height) ;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2012-01-19 00:04:51 +04:00
|
|
|
if (!ApplyOverflowClipping(this, aReflowState.mStyleDisplay)) {
|
2003-09-13 20:26:30 +04:00
|
|
|
// collapsed border may leak out
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nsMargin bcMargin = GetExcludedOuterBCBorder();
|
2003-09-13 20:26:30 +04:00
|
|
|
tableRect.Inflate(bcMargin);
|
|
|
|
}
|
2010-10-07 08:25:46 +04:00
|
|
|
aDesiredSize.mOverflowAreas.UnionAllWith(tableRect);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2012-08-29 09:48:45 +04:00
|
|
|
if ((GetStateBits() & NS_FRAME_FIRST_REFLOW) ||
|
|
|
|
nsSize(aDesiredSize.width, aDesiredSize.height) != mRect.Size()) {
|
|
|
|
nsIFrame::InvalidateFrame();
|
|
|
|
}
|
|
|
|
|
2004-07-16 20:56:21 +04:00
|
|
|
FinishAndStoreOverflow(&aDesiredSize);
|
2002-05-29 02:50:43 +04:00
|
|
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
|
1998-10-11 13:18:27 +04:00
|
|
|
return rv;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2011-06-16 01:03:49 +04:00
|
|
|
bool
|
|
|
|
nsTableFrame::UpdateOverflow()
|
|
|
|
{
|
|
|
|
nsRect bounds(nsPoint(0, 0), GetSize());
|
|
|
|
|
|
|
|
// As above in Reflow, make sure the table overflow area includes the table
|
|
|
|
// rect, and check for collapsed borders leaking out.
|
2012-01-19 00:04:51 +04:00
|
|
|
if (!ApplyOverflowClipping(this, GetStyleDisplay())) {
|
2011-06-16 01:03:49 +04:00
|
|
|
nsMargin bcMargin = GetExcludedOuterBCBorder();
|
|
|
|
bounds.Inflate(bcMargin);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsOverflowAreas overflowAreas(bounds, bounds);
|
|
|
|
nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
|
|
|
|
|
|
|
|
return FinishAndStoreOverflow(overflowAreas, GetSize());
|
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
nsresult
|
2005-02-07 04:58:25 +03:00
|
|
|
nsTableFrame::ReflowTable(nsHTMLReflowMetrics& aDesiredSize,
|
2001-08-08 05:13:35 +04:00
|
|
|
const nsHTMLReflowState& aReflowState,
|
|
|
|
nscoord aAvailHeight,
|
2002-03-04 18:48:56 +03:00
|
|
|
nsIFrame*& aLastChildReflowed,
|
2001-08-08 05:13:35 +04:00
|
|
|
nsReflowStatus& aStatus)
|
|
|
|
{
|
|
|
|
nsresult rv = NS_OK;
|
2012-07-30 18:20:58 +04:00
|
|
|
aLastChildReflowed = nullptr;
|
2001-08-08 05:13:35 +04:00
|
|
|
|
2006-02-22 00:33:47 +03:00
|
|
|
if (!GetPrevInFlow()) {
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
mTableLayoutStrategy->ComputeColumnWidths(aReflowState);
|
2001-08-08 05:13:35 +04:00
|
|
|
}
|
|
|
|
// Constrain our reflow width to the computed table width (of the 1st in flow).
|
|
|
|
// and our reflow height to our avail height minus border, padding, cellspacing
|
2007-01-26 03:05:12 +03:00
|
|
|
aDesiredSize.width = aReflowState.ComputedWidth() +
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
aReflowState.mComputedBorderPadding.LeftRight();
|
2007-03-31 01:11:41 +04:00
|
|
|
nsTableReflowState reflowState(*PresContext(), aReflowState, *this,
|
2001-08-08 05:13:35 +04:00
|
|
|
aDesiredSize.width, aAvailHeight);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
ReflowChildren(reflowState, aStatus, aLastChildReflowed,
|
2010-10-07 08:25:46 +04:00
|
|
|
aDesiredSize.mOverflowAreas);
|
2001-08-08 05:13:35 +04:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
ReflowColGroups(aReflowState.rendContext);
|
2001-08-08 05:13:35 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
1999-03-09 08:29:37 +03:00
|
|
|
nsIFrame*
|
|
|
|
nsTableFrame::GetFirstBodyRowGroupFrame()
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame* headerFrame = nullptr;
|
|
|
|
nsIFrame* footerFrame = nullptr;
|
1999-03-09 08:29:37 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
for (nsIFrame* kidFrame = mFrames.FirstChild(); nullptr != kidFrame; ) {
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleDisplay* childDisplay = kidFrame->GetStyleDisplay();
|
1999-03-09 08:29:37 +03:00
|
|
|
|
|
|
|
// We expect the header and footer row group frames to be first, and we only
|
|
|
|
// allow one header and one footer
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == childDisplay->mDisplay) {
|
|
|
|
if (headerFrame) {
|
|
|
|
// We already have a header frame and so this header frame is treated
|
|
|
|
// like an ordinary body row group frame
|
|
|
|
return kidFrame;
|
|
|
|
}
|
|
|
|
headerFrame = kidFrame;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
1999-03-09 08:29:37 +03:00
|
|
|
} else if (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == childDisplay->mDisplay) {
|
|
|
|
if (footerFrame) {
|
|
|
|
// We already have a footer frame and so this footer frame is treated
|
|
|
|
// like an ordinary body row group frame
|
|
|
|
return kidFrame;
|
|
|
|
}
|
|
|
|
footerFrame = kidFrame;
|
|
|
|
|
|
|
|
} else if (NS_STYLE_DISPLAY_TABLE_ROW_GROUP == childDisplay->mDisplay) {
|
|
|
|
return kidFrame;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the next child
|
2003-07-07 06:01:29 +04:00
|
|
|
kidFrame = kidFrame->GetNextSibling();
|
1999-03-09 08:29:37 +03:00
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
1999-03-09 08:29:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Table specific version that takes into account repeated header and footer
|
|
|
|
// frames when continuing table frames
|
|
|
|
void
|
2010-01-16 19:05:46 +03:00
|
|
|
nsTableFrame::PushChildren(const RowGroupArray& aRowGroups,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aPushFrom)
|
1999-03-09 08:29:37 +03:00
|
|
|
{
|
2005-02-16 23:02:14 +03:00
|
|
|
NS_PRECONDITION(aPushFrom > 0, "pushing first child");
|
1999-03-09 08:29:37 +03:00
|
|
|
|
2005-02-16 23:02:14 +03:00
|
|
|
// extract the frames from the array into a sibling list
|
|
|
|
nsFrameList frames;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t childX;
|
2010-01-16 19:05:46 +03:00
|
|
|
for (childX = aPushFrom; childX < aRowGroups.Length(); ++childX) {
|
|
|
|
nsTableRowGroupFrame* rgFrame = aRowGroups[childX];
|
2010-12-09 13:57:03 +03:00
|
|
|
if (!rgFrame->IsRepeatable()) {
|
2010-01-16 19:05:46 +03:00
|
|
|
mFrames.RemoveFrame(rgFrame);
|
2012-07-30 18:20:58 +04:00
|
|
|
frames.AppendFrame(nullptr, rgFrame);
|
2005-02-16 23:02:14 +03:00
|
|
|
}
|
|
|
|
}
|
1999-03-09 08:29:37 +03:00
|
|
|
|
2010-11-07 20:27:46 +03:00
|
|
|
if (frames.IsEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
1999-03-09 08:29:37 +03:00
|
|
|
|
2010-11-07 20:27:46 +03:00
|
|
|
nsTableFrame* nextInFlow = static_cast<nsTableFrame*>(GetNextInFlow());
|
|
|
|
if (nextInFlow) {
|
|
|
|
// Insert the frames after any repeated header and footer frames.
|
1999-03-09 08:29:37 +03:00
|
|
|
nsIFrame* firstBodyFrame = nextInFlow->GetFirstBodyRowGroupFrame();
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame* prevSibling = nullptr;
|
1999-03-09 08:29:37 +03:00
|
|
|
if (firstBodyFrame) {
|
2009-10-02 20:27:37 +04:00
|
|
|
prevSibling = firstBodyFrame->GetPrevSibling();
|
1999-03-09 08:29:37 +03:00
|
|
|
}
|
1999-04-13 06:38:09 +04:00
|
|
|
// When pushing and pulling frames we need to check for whether any
|
|
|
|
// views need to be reparented.
|
2009-07-30 21:23:32 +04:00
|
|
|
ReparentFrameViewList(PresContext(), frames, this, nextInFlow);
|
|
|
|
nextInFlow->mFrames.InsertFrames(nextInFlow, prevSibling,
|
|
|
|
frames);
|
1999-03-09 08:29:37 +03:00
|
|
|
}
|
2010-11-07 20:27:46 +03:00
|
|
|
else {
|
|
|
|
// Add the frames to our overflow list.
|
2009-07-28 16:51:09 +04:00
|
|
|
SetOverflowFrames(PresContext(), frames);
|
1999-03-09 08:29:37 +03:00
|
|
|
}
|
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1999-12-16 04:51:06 +03:00
|
|
|
// collapsing row groups, rows, col groups and cols are accounted for after both passes of
|
|
|
|
// reflow so that it has no effect on the calculations of reflow.
|
2006-03-04 08:26:57 +03:00
|
|
|
void
|
|
|
|
nsTableFrame::AdjustForCollapsingRowsCols(nsHTMLReflowMetrics& aDesiredSize,
|
|
|
|
nsMargin aBorderPadding)
|
1999-02-11 09:22:33 +03:00
|
|
|
{
|
|
|
|
nscoord yTotalOffset = 0; // total offset among all rows in all row groups
|
2006-03-04 08:26:57 +03:00
|
|
|
|
2009-05-16 18:22:56 +04:00
|
|
|
// reset the bit, it will be set again if row/rowgroup or col/colgroup are
|
|
|
|
// collapsed
|
2011-10-17 18:59:28 +04:00
|
|
|
SetNeedToCollapse(false);
|
2009-06-21 20:34:03 +04:00
|
|
|
|
1999-12-16 04:51:06 +03:00
|
|
|
// collapse the rows and/or row groups as necessary
|
2004-05-08 09:11:29 +04:00
|
|
|
// Get the ordered children
|
2007-06-05 22:55:26 +04:00
|
|
|
RowGroupArray rowGroups;
|
|
|
|
OrderRowGroups(rowGroups);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:34:03 +04:00
|
|
|
nsTableFrame* firstInFlow = static_cast<nsTableFrame*> (GetFirstInFlow());
|
|
|
|
nscoord width = firstInFlow->GetCollapsedWidth(aBorderPadding);
|
2006-03-04 08:26:57 +03:00
|
|
|
nscoord rgWidth = width - 2 * GetCellSpacingX();
|
2010-10-07 08:25:45 +04:00
|
|
|
nsOverflowAreas overflow;
|
2004-05-08 09:11:29 +04:00
|
|
|
// Walk the list of children
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t childX = 0; childX < rowGroups.Length(); childX++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableRowGroupFrame* rgFrame = rowGroups[childX];
|
|
|
|
NS_ASSERTION(rgFrame, "Must have row group frame here");
|
2006-03-04 08:26:57 +03:00
|
|
|
yTotalOffset += rgFrame->CollapseRowGroupIfNecessary(yTotalOffset, rgWidth);
|
2010-10-07 08:25:45 +04:00
|
|
|
ConsiderChildOverflow(overflow, rgFrame);
|
2010-04-27 20:15:01 +04:00
|
|
|
}
|
1999-02-11 09:22:33 +03:00
|
|
|
|
2004-05-08 09:11:29 +04:00
|
|
|
aDesiredSize.height -= yTotalOffset;
|
2006-03-04 08:26:57 +03:00
|
|
|
aDesiredSize.width = width;
|
2010-10-07 08:25:45 +04:00
|
|
|
overflow.UnionAllWith(nsRect(0, 0, aDesiredSize.width, aDesiredSize.height));
|
|
|
|
FinishAndStoreOverflow(overflow,
|
2006-03-04 08:26:57 +03:00
|
|
|
nsSize(aDesiredSize.width, aDesiredSize.height));
|
1999-02-11 09:22:33 +03:00
|
|
|
}
|
|
|
|
|
2009-06-21 20:34:03 +04:00
|
|
|
|
2006-03-04 08:26:57 +03:00
|
|
|
nscoord
|
|
|
|
nsTableFrame::GetCollapsedWidth(nsMargin aBorderPadding)
|
1999-02-11 09:22:33 +03:00
|
|
|
{
|
2009-06-21 20:34:03 +04:00
|
|
|
NS_ASSERTION(!GetPrevInFlow(), "GetCollapsedWidth called on next in flow");
|
1999-02-11 09:22:33 +03:00
|
|
|
nscoord cellSpacingX = GetCellSpacingX();
|
2006-03-04 08:26:57 +03:00
|
|
|
nscoord width = cellSpacingX;
|
|
|
|
width += aBorderPadding.left + aBorderPadding.right;
|
|
|
|
for (nsIFrame* groupFrame = mColGroups.FirstChild(); groupFrame;
|
|
|
|
groupFrame = groupFrame->GetNextSibling()) {
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleVisibility* groupVis = groupFrame->GetStyleVisibility();
|
2011-09-29 10:19:26 +04:00
|
|
|
bool collapseGroup = (NS_STYLE_VISIBILITY_COLLAPSE == groupVis->mVisible);
|
2006-03-04 08:26:57 +03:00
|
|
|
nsTableColGroupFrame* cgFrame = (nsTableColGroupFrame*)groupFrame;
|
|
|
|
for (nsTableColFrame* colFrame = cgFrame->GetFirstColumn(); colFrame;
|
|
|
|
colFrame = colFrame->GetNextCol()) {
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleDisplay* colDisplay = colFrame->GetStyleDisplay();
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colX = colFrame->GetColIndex();
|
1999-02-11 09:22:33 +03:00
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN == colDisplay->mDisplay) {
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleVisibility* colVis = colFrame->GetStyleVisibility();
|
2011-09-29 10:19:26 +04:00
|
|
|
bool collapseCol = (NS_STYLE_VISIBILITY_COLLAPSE == colVis->mVisible);
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colWidth = GetColumnWidth(colX);
|
2006-03-04 08:26:57 +03:00
|
|
|
if (!collapseGroup && !collapseCol) {
|
|
|
|
width += colWidth;
|
2008-09-24 21:14:35 +04:00
|
|
|
if (ColumnHasCellSpacingBefore(colX))
|
2006-03-04 08:26:57 +03:00
|
|
|
width += cellSpacingX;
|
1999-02-11 09:22:33 +03:00
|
|
|
}
|
2009-06-21 20:34:03 +04:00
|
|
|
else {
|
2011-10-17 18:59:28 +04:00
|
|
|
SetNeedToCollapse(true);
|
2009-06-21 20:34:03 +04:00
|
|
|
}
|
1999-02-11 09:22:33 +03:00
|
|
|
}
|
2006-03-04 08:26:57 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return width;
|
1999-02-11 09:22:33 +03:00
|
|
|
}
|
|
|
|
|
2008-11-01 11:52:29 +03:00
|
|
|
/* virtual */ void
|
2008-10-26 13:11:34 +03:00
|
|
|
nsTableFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
2008-10-18 21:25:26 +04:00
|
|
|
{
|
2012-08-14 01:13:34 +04:00
|
|
|
nsContainerFrame::DidSetStyleContext(aOldStyleContext);
|
|
|
|
|
2012-01-17 03:38:10 +04:00
|
|
|
if (!aOldStyleContext) //avoid this on init
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (IsBorderCollapse() &&
|
|
|
|
BCRecalcNeeded(aOldStyleContext, GetStyleContext())) {
|
|
|
|
SetFullBCDamageArea();
|
|
|
|
}
|
|
|
|
|
|
|
|
//avoid this on init or nextinflow
|
|
|
|
if (!mTableLayoutStrategy || GetPrevInFlow())
|
|
|
|
return;
|
|
|
|
|
|
|
|
bool isAuto = IsAutoLayout();
|
|
|
|
if (isAuto != (LayoutStrategy()->GetType() == nsITableLayoutStrategy::Auto)) {
|
|
|
|
nsITableLayoutStrategy* temp;
|
|
|
|
if (isAuto)
|
|
|
|
temp = new BasicTableLayoutStrategy(this);
|
|
|
|
else
|
|
|
|
temp = new FixedTableLayoutStrategy(this);
|
|
|
|
|
|
|
|
if (temp) {
|
|
|
|
delete mTableLayoutStrategy;
|
|
|
|
mTableLayoutStrategy = temp;
|
|
|
|
}
|
2008-10-18 21:25:26 +04:00
|
|
|
}
|
|
|
|
}
|
2006-03-04 08:26:57 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
1999-08-19 07:51:25 +04:00
|
|
|
NS_IMETHODIMP
|
2011-08-25 00:54:30 +04:00
|
|
|
nsTableFrame::AppendFrames(ChildListID aListID,
|
2009-07-30 21:23:32 +04:00
|
|
|
nsFrameList& aFrameList)
|
1999-08-19 07:51:25 +04:00
|
|
|
{
|
2011-08-25 00:54:30 +04:00
|
|
|
NS_ASSERTION(aListID == kPrincipalList || aListID == kColGroupList,
|
2006-06-29 06:32:36 +04:00
|
|
|
"unexpected child list");
|
|
|
|
|
1999-08-19 07:51:25 +04:00
|
|
|
// Because we actually have two child lists, one for col group frames and one
|
|
|
|
// for everything else, we need to look at each frame individually
|
2006-06-29 06:32:36 +04:00
|
|
|
// XXX The frame construction code should be separating out child frames
|
|
|
|
// based on the type, bug 343048.
|
2009-07-30 21:23:32 +04:00
|
|
|
while (!aFrameList.IsEmpty()) {
|
|
|
|
nsIFrame* f = aFrameList.FirstChild();
|
|
|
|
aFrameList.RemoveFrame(f);
|
1999-08-19 07:51:25 +04:00
|
|
|
|
|
|
|
// See what kind of frame we have
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleDisplay* display = f->GetStyleDisplay();
|
1999-08-19 07:51:25 +04:00
|
|
|
|
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) {
|
2009-07-30 21:23:32 +04:00
|
|
|
nsTableColGroupFrame* lastColGroup =
|
|
|
|
nsTableColGroupFrame::GetLastRealColGroup(this);
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t startColIndex = (lastColGroup)
|
2004-09-04 20:02:50 +04:00
|
|
|
? lastColGroup->GetStartColumnIndex() + lastColGroup->GetColCount() : 0;
|
2012-07-30 18:20:58 +04:00
|
|
|
mColGroups.InsertFrame(nullptr, lastColGroup, f);
|
2004-09-04 20:02:50 +04:00
|
|
|
// Insert the colgroup and its cols into the table
|
2009-07-30 21:23:32 +04:00
|
|
|
InsertColGroups(startColIndex,
|
|
|
|
nsFrameList::Slice(mColGroups, f, f->GetNextSibling()));
|
1999-08-19 07:51:25 +04:00
|
|
|
} else if (IsRowGroup(display->mDisplay)) {
|
1999-12-14 01:56:31 +03:00
|
|
|
// Append the new row group frame to the sibling chain
|
2012-07-30 18:20:58 +04:00
|
|
|
mFrames.AppendFrame(nullptr, f);
|
2000-09-14 10:49:47 +04:00
|
|
|
|
|
|
|
// insert the row group and its rows into the table
|
2012-07-30 18:20:58 +04:00
|
|
|
InsertRowGroups(nsFrameList::Slice(mFrames, f, nullptr));
|
1999-08-19 07:51:25 +04:00
|
|
|
} else {
|
|
|
|
// Nothing special to do, just add the frame to our child list
|
2009-07-30 21:23:32 +04:00
|
|
|
NS_NOTREACHED("How did we get here? Frame construction screwed up");
|
2012-07-30 18:20:58 +04:00
|
|
|
mFrames.AppendFrame(nullptr, f);
|
1999-08-19 07:51:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-09-04 20:02:50 +04:00
|
|
|
#ifdef DEBUG_TABLE_CELLMAP
|
2006-06-22 08:19:36 +04:00
|
|
|
printf("=== TableFrame::AppendFrames\n");
|
2011-10-17 18:59:28 +04:00
|
|
|
Dump(true, true, true);
|
2004-09-04 20:02:50 +04:00
|
|
|
#endif
|
2007-05-06 23:16:51 +04:00
|
|
|
PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
|
|
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
2006-12-13 06:45:28 +03:00
|
|
|
SetGeometryDirty();
|
1999-08-19 07:51:25 +04:00
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
return NS_OK;
|
1999-08-19 07:51:25 +04:00
|
|
|
}
|
|
|
|
|
2012-06-01 23:56:33 +04:00
|
|
|
// Needs to be at file scope or ArrayLength fails to compile.
|
|
|
|
struct ChildListInsertions {
|
|
|
|
nsIFrame::ChildListID mID;
|
|
|
|
nsFrameList mList;
|
|
|
|
};
|
|
|
|
|
1999-08-19 07:51:25 +04:00
|
|
|
NS_IMETHODIMP
|
2011-08-25 00:54:30 +04:00
|
|
|
nsTableFrame::InsertFrames(ChildListID aListID,
|
1999-08-19 07:51:25 +04:00
|
|
|
nsIFrame* aPrevFrame,
|
2009-07-30 21:23:32 +04:00
|
|
|
nsFrameList& aFrameList)
|
1999-08-19 07:51:25 +04:00
|
|
|
{
|
2012-06-01 23:56:33 +04:00
|
|
|
// The frames in aFrameList can be a mix of row group frames and col group
|
|
|
|
// frames. The problem is that they should go in separate child lists so
|
|
|
|
// we need to deal with that here...
|
1999-08-19 07:51:25 +04:00
|
|
|
// XXX The frame construction code should be separating out child frames
|
2006-06-29 06:32:36 +04:00
|
|
|
// based on the type, bug 343048.
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2006-06-29 06:32:36 +04:00
|
|
|
NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
|
|
|
|
"inserting after sibling frame with different parent");
|
1999-08-19 07:51:25 +04:00
|
|
|
|
2009-04-23 18:17:46 +04:00
|
|
|
if ((aPrevFrame && !aPrevFrame->GetNextSibling()) ||
|
2011-08-25 00:54:30 +04:00
|
|
|
(!aPrevFrame && GetChildList(aListID).IsEmpty())) {
|
2009-04-23 18:17:46 +04:00
|
|
|
// Treat this like an append; still a workaround for bug 343048.
|
2011-08-25 00:54:30 +04:00
|
|
|
return AppendFrames(aListID, aFrameList);
|
2009-04-23 18:17:46 +04:00
|
|
|
}
|
|
|
|
|
2012-06-01 23:56:33 +04:00
|
|
|
// Collect ColGroupFrames into a separate list and insert those separately
|
|
|
|
// from the other frames (bug 759249).
|
|
|
|
ChildListInsertions insertions[2]; // ColGroup, other
|
|
|
|
const nsStyleDisplay* display = aFrameList.FirstChild()->GetStyleDisplay();
|
|
|
|
nsFrameList::FrameLinkEnumerator e(aFrameList);
|
|
|
|
for (; !aFrameList.IsEmpty(); e.Next()) {
|
|
|
|
nsIFrame* next = e.NextFrame();
|
|
|
|
if (!next || next->GetStyleDisplay()->mDisplay != display->mDisplay) {
|
|
|
|
nsFrameList head = aFrameList.ExtractHead(e);
|
|
|
|
if (display->mDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP) {
|
|
|
|
insertions[0].mID = kColGroupList;
|
2012-07-30 18:20:58 +04:00
|
|
|
insertions[0].mList.AppendFrames(nullptr, head);
|
2012-06-01 23:56:33 +04:00
|
|
|
} else {
|
|
|
|
insertions[1].mID = kPrincipalList;
|
2012-07-30 18:20:58 +04:00
|
|
|
insertions[1].mList.AppendFrames(nullptr, head);
|
2012-06-01 23:56:33 +04:00
|
|
|
}
|
|
|
|
if (!next) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
display = next->GetStyleDisplay();
|
|
|
|
}
|
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t i = 0; i < ArrayLength(insertions); ++i) {
|
2012-06-01 23:56:33 +04:00
|
|
|
// We pass aPrevFrame for both ColGroup and other frames since
|
|
|
|
// HomogenousInsertFrames will only use it if it's a suitable
|
|
|
|
// prev-sibling for the frames in the frame list.
|
|
|
|
if (!insertions[i].mList.IsEmpty()) {
|
|
|
|
HomogenousInsertFrames(insertions[i].mID, aPrevFrame,
|
|
|
|
insertions[i].mList);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsTableFrame::HomogenousInsertFrames(ChildListID aListID,
|
|
|
|
nsIFrame* aPrevFrame,
|
|
|
|
nsFrameList& aFrameList)
|
|
|
|
{
|
1999-08-19 07:51:25 +04:00
|
|
|
// See what kind of frame we have
|
2009-07-30 21:23:32 +04:00
|
|
|
const nsStyleDisplay* display = aFrameList.FirstChild()->GetStyleDisplay();
|
2008-09-27 15:07:29 +04:00
|
|
|
#ifdef DEBUG
|
2012-06-01 23:56:33 +04:00
|
|
|
// Verify that either all siblings have display:table-column-group, or they
|
|
|
|
// all have display values different from table-column-group.
|
2009-07-30 21:23:32 +04:00
|
|
|
for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
|
|
|
|
const nsStyleDisplay* nextDisplay = e.get()->GetStyleDisplay();
|
2012-06-01 23:56:33 +04:00
|
|
|
MOZ_ASSERT((display->mDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP) ==
|
|
|
|
(nextDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP),
|
|
|
|
"heterogenous childlist");
|
2008-09-27 15:07:29 +04:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
#endif
|
2006-11-11 16:38:09 +03:00
|
|
|
if (aPrevFrame) {
|
|
|
|
const nsStyleDisplay* prevDisplay = aPrevFrame->GetStyleDisplay();
|
2007-03-01 01:42:20 +03:00
|
|
|
// Make sure they belong on the same frame list
|
|
|
|
if ((display->mDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP) !=
|
|
|
|
(prevDisplay->mDisplay == NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP)) {
|
2006-11-11 16:38:09 +03:00
|
|
|
// the previous frame is not valid, see comment at ::AppendFrames
|
2007-03-01 01:42:20 +03:00
|
|
|
// XXXbz Using content indices here means XBL will get screwed
|
|
|
|
// over... Oh, well.
|
2009-07-30 21:23:32 +04:00
|
|
|
nsIFrame* pseudoFrame = aFrameList.FirstChild();
|
2006-11-11 16:38:09 +03:00
|
|
|
nsIContent* parentContent = GetContent();
|
|
|
|
nsIContent* content;
|
2012-07-30 18:20:58 +04:00
|
|
|
aPrevFrame = nullptr;
|
2006-11-11 16:38:09 +03:00
|
|
|
while (pseudoFrame && (parentContent ==
|
|
|
|
(content = pseudoFrame->GetContent()))) {
|
2011-08-25 00:54:30 +04:00
|
|
|
pseudoFrame = pseudoFrame->GetFirstPrincipalChild();
|
2006-11-11 16:38:09 +03:00
|
|
|
}
|
|
|
|
nsCOMPtr<nsIContent> container = content->GetParent();
|
2012-10-26 17:32:10 +04:00
|
|
|
if (MOZ_LIKELY(container)) { // XXX need this null-check, see bug 411823.
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t newIndex = container->IndexOf(content);
|
2008-01-16 02:29:53 +03:00
|
|
|
nsIFrame* kidFrame;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isColGroup = (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP ==
|
2008-01-16 02:29:53 +03:00
|
|
|
display->mDisplay);
|
2008-10-26 12:20:42 +03:00
|
|
|
nsTableColGroupFrame* lastColGroup;
|
2006-11-11 16:38:09 +03:00
|
|
|
if (isColGroup) {
|
2008-01-16 02:29:53 +03:00
|
|
|
kidFrame = mColGroups.FirstChild();
|
2009-07-30 21:23:32 +04:00
|
|
|
lastColGroup = nsTableColGroupFrame::GetLastRealColGroup(this);
|
2006-11-11 16:38:09 +03:00
|
|
|
}
|
2008-01-16 02:29:53 +03:00
|
|
|
else {
|
|
|
|
kidFrame = mFrames.FirstChild();
|
2006-11-11 16:38:09 +03:00
|
|
|
}
|
2008-01-16 02:29:53 +03:00
|
|
|
// Important: need to start at a value smaller than all valid indices
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t lastIndex = -1;
|
2008-01-16 02:29:53 +03:00
|
|
|
while (kidFrame) {
|
|
|
|
if (isColGroup) {
|
2008-10-26 12:20:42 +03:00
|
|
|
if (kidFrame == lastColGroup) {
|
|
|
|
aPrevFrame = kidFrame; // there is no real colgroup after this one
|
|
|
|
break;
|
2008-01-16 02:29:53 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
pseudoFrame = kidFrame;
|
|
|
|
while (pseudoFrame && (parentContent ==
|
|
|
|
(content = pseudoFrame->GetContent()))) {
|
2011-08-25 00:54:30 +04:00
|
|
|
pseudoFrame = pseudoFrame->GetFirstPrincipalChild();
|
2008-01-16 02:29:53 +03:00
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t index = container->IndexOf(content);
|
2008-01-16 02:29:53 +03:00
|
|
|
if (index > lastIndex && index < newIndex) {
|
|
|
|
lastIndex = index;
|
|
|
|
aPrevFrame = kidFrame;
|
|
|
|
}
|
|
|
|
kidFrame = kidFrame->GetNextSibling();
|
2006-11-11 16:38:09 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1999-08-19 07:51:25 +04:00
|
|
|
if (NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP == display->mDisplay) {
|
2012-06-01 23:56:33 +04:00
|
|
|
NS_ASSERTION(aListID == kColGroupList, "unexpected child list");
|
2009-07-30 21:23:32 +04:00
|
|
|
// Insert the column group frames
|
|
|
|
const nsFrameList::Slice& newColgroups =
|
2012-07-30 18:20:58 +04:00
|
|
|
mColGroups.InsertFrames(nullptr, aPrevFrame, aFrameList);
|
1999-12-14 01:56:31 +03:00
|
|
|
// find the starting col index for the first new col group
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t startColIndex = 0;
|
1999-12-14 01:56:31 +03:00
|
|
|
if (aPrevFrame) {
|
2010-04-27 20:15:01 +04:00
|
|
|
nsTableColGroupFrame* prevColGroup =
|
2004-01-18 13:28:40 +03:00
|
|
|
(nsTableColGroupFrame*)GetFrameAtOrBefore(this, aPrevFrame,
|
2006-12-26 20:47:52 +03:00
|
|
|
nsGkAtoms::tableColGroupFrame);
|
1999-12-14 01:56:31 +03:00
|
|
|
if (prevColGroup) {
|
|
|
|
startColIndex = prevColGroup->GetStartColumnIndex() + prevColGroup->GetColCount();
|
|
|
|
}
|
|
|
|
}
|
2009-07-30 21:23:32 +04:00
|
|
|
InsertColGroups(startColIndex, newColgroups);
|
1999-08-19 07:51:25 +04:00
|
|
|
} else if (IsRowGroup(display->mDisplay)) {
|
2011-08-25 00:54:30 +04:00
|
|
|
NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
|
1999-12-14 01:56:31 +03:00
|
|
|
// Insert the frames in the sibling chain
|
2009-07-30 21:23:32 +04:00
|
|
|
const nsFrameList::Slice& newRowGroups =
|
2012-07-30 18:20:58 +04:00
|
|
|
mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
|
2000-09-14 10:49:47 +04:00
|
|
|
|
2009-07-30 21:23:32 +04:00
|
|
|
InsertRowGroups(newRowGroups);
|
1999-08-19 07:51:25 +04:00
|
|
|
} else {
|
2011-08-25 00:54:30 +04:00
|
|
|
NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
|
2009-07-30 21:23:32 +04:00
|
|
|
NS_NOTREACHED("How did we even get here?");
|
1999-08-19 07:51:25 +04:00
|
|
|
// Just insert the frame and don't worry about reflowing it
|
2012-07-30 18:20:58 +04:00
|
|
|
mFrames.InsertFrames(nullptr, aPrevFrame, aFrameList);
|
2012-06-01 23:56:33 +04:00
|
|
|
return;
|
1999-08-19 07:51:25 +04:00
|
|
|
}
|
|
|
|
|
2007-05-06 23:16:51 +04:00
|
|
|
PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
|
|
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
2006-12-13 06:45:28 +03:00
|
|
|
SetGeometryDirty();
|
2006-06-22 08:19:36 +04:00
|
|
|
#ifdef DEBUG_TABLE_CELLMAP
|
|
|
|
printf("=== TableFrame::InsertFrames\n");
|
2011-10-17 18:59:28 +04:00
|
|
|
Dump(true, true, true);
|
2006-06-22 08:19:36 +04:00
|
|
|
#endif
|
2012-06-01 23:56:33 +04:00
|
|
|
return;
|
1999-08-19 07:51:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2011-08-25 00:54:30 +04:00
|
|
|
nsTableFrame::RemoveFrame(ChildListID aListID,
|
1999-08-19 07:51:25 +04:00
|
|
|
nsIFrame* aOldFrame)
|
|
|
|
{
|
2011-08-25 00:54:30 +04:00
|
|
|
NS_ASSERTION(aListID == kColGroupList ||
|
2009-12-24 08:20:41 +03:00
|
|
|
NS_STYLE_DISPLAY_TABLE_COLUMN_GROUP !=
|
|
|
|
aOldFrame->GetStyleDisplay()->mDisplay,
|
2011-08-25 00:54:30 +04:00
|
|
|
"Wrong list name; use kColGroupList iff colgroup");
|
|
|
|
if (aListID == kColGroupList) {
|
2003-07-07 06:01:29 +04:00
|
|
|
nsIFrame* nextColGroupFrame = aOldFrame->GetNextSibling();
|
1999-12-14 01:56:31 +03:00
|
|
|
nsTableColGroupFrame* colGroup = (nsTableColGroupFrame*)aOldFrame;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t firstColIndex = colGroup->GetStartColumnIndex();
|
|
|
|
int32_t lastColIndex = firstColIndex + colGroup->GetColCount() - 1;
|
2006-04-10 04:16:29 +04:00
|
|
|
mColGroups.DestroyFrame(aOldFrame);
|
2004-01-18 13:28:40 +03:00
|
|
|
nsTableColGroupFrame::ResetColIndices(nextColGroupFrame, firstColIndex);
|
1999-12-14 01:56:31 +03:00
|
|
|
// remove the cols from the table
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colX;
|
1999-12-14 01:56:31 +03:00
|
|
|
for (colX = lastColIndex; colX >= firstColIndex; colX--) {
|
2009-02-05 12:09:50 +03:00
|
|
|
nsTableColFrame* colFrame = mColFrames.SafeElementAt(colX);
|
1999-12-14 01:56:31 +03:00
|
|
|
if (colFrame) {
|
2011-10-17 18:59:28 +04:00
|
|
|
RemoveCol(colGroup, colX, true, false);
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
}
|
1999-08-19 07:51:25 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numAnonymousColsToAdd = GetColCount() - mColFrames.Length();
|
1999-12-14 01:56:31 +03:00
|
|
|
if (numAnonymousColsToAdd > 0) {
|
|
|
|
// this sets the child list, updates the col cache and cell map
|
2009-07-12 21:47:10 +04:00
|
|
|
AppendAnonymousColFrames(numAnonymousColsToAdd);
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
1999-08-19 07:51:25 +04:00
|
|
|
|
|
|
|
} else {
|
2011-08-25 00:54:30 +04:00
|
|
|
NS_ASSERTION(aListID == kPrincipalList, "unexpected child list");
|
2010-01-16 19:05:46 +03:00
|
|
|
nsTableRowGroupFrame* rgFrame =
|
|
|
|
static_cast<nsTableRowGroupFrame*>(aOldFrame);
|
|
|
|
// remove the row group from the cell map
|
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
|
|
|
if (cellMap) {
|
|
|
|
cellMap->RemoveGroupCellMap(rgFrame);
|
|
|
|
}
|
2006-08-04 23:15:50 +04:00
|
|
|
|
2010-01-16 19:05:46 +03:00
|
|
|
// remove the row group frame from the sibling chain
|
|
|
|
mFrames.DestroyFrame(aOldFrame);
|
2006-08-04 23:15:50 +04:00
|
|
|
|
2010-01-16 19:05:46 +03:00
|
|
|
// the removal of a row group changes the cellmap, the columns might change
|
|
|
|
if (cellMap) {
|
|
|
|
cellMap->Synchronize(this);
|
|
|
|
// Create an empty slice
|
2012-07-30 18:20:58 +04:00
|
|
|
ResetRowIndices(nsFrameList::Slice(mFrames, nullptr, nullptr));
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea;
|
2012-07-30 18:20:58 +04:00
|
|
|
cellMap->RebuildConsideringCells(nullptr, nullptr, 0, 0, false, damageArea);
|
2010-01-16 19:05:46 +03:00
|
|
|
|
2011-03-26 07:37:35 +03:00
|
|
|
MatchCellMapToColCache(cellMap);
|
|
|
|
}
|
2000-01-13 08:29:38 +03:00
|
|
|
}
|
2006-08-28 21:41:46 +04:00
|
|
|
// for now, just bail and recalc all of the collapsing borders
|
2010-01-16 19:05:46 +03:00
|
|
|
// as the cellmap changes we need to recalc
|
2006-08-28 21:41:46 +04:00
|
|
|
if (IsBorderCollapse()) {
|
2011-10-27 17:58:44 +04:00
|
|
|
SetFullBCDamageArea();
|
2006-08-28 21:41:46 +04:00
|
|
|
}
|
2007-05-06 23:16:51 +04:00
|
|
|
PresContext()->PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
|
|
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
2006-12-13 06:45:28 +03:00
|
|
|
SetGeometryDirty();
|
2006-06-28 23:00:01 +04:00
|
|
|
#ifdef DEBUG_TABLE_CELLMAP
|
|
|
|
printf("=== TableFrame::RemoveFrame\n");
|
2011-10-17 18:59:28 +04:00
|
|
|
Dump(true, true, true);
|
2006-06-28 23:00:01 +04:00
|
|
|
#endif
|
2000-01-13 08:29:38 +03:00
|
|
|
return NS_OK;
|
1999-08-19 07:51:25 +04:00
|
|
|
}
|
|
|
|
|
2006-12-14 02:04:57 +03:00
|
|
|
/* virtual */ nsMargin
|
|
|
|
nsTableFrame::GetUsedBorder() const
|
|
|
|
{
|
|
|
|
if (!IsBorderCollapse())
|
2011-12-28 00:18:48 +04:00
|
|
|
return nsContainerFrame::GetUsedBorder();
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2006-12-14 02:04:57 +03:00
|
|
|
return GetIncludedOuterBCBorder();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ nsMargin
|
|
|
|
nsTableFrame::GetUsedPadding() const
|
|
|
|
{
|
|
|
|
if (!IsBorderCollapse())
|
2011-12-28 00:18:48 +04:00
|
|
|
return nsContainerFrame::GetUsedPadding();
|
2006-12-14 02:04:57 +03:00
|
|
|
|
|
|
|
return nsMargin(0,0,0,0);
|
|
|
|
}
|
|
|
|
|
Bug 659828 - Part 1: Apply table margins to the outer table frame instead of the inner table frame (also fixes bug 87277); r=dbaron
Outer table frames act as CSS2.1 table wrapper boxes. We used to lay them out
without taking their margins into the account, which meant that their width was
always equal to the available width. This breaks horizontal positioning of
absolutely positioned kids of a table frame.
The main purpose of this patch is to apply the margins of tables to their outer
frame, instead of the inner frame. This means that the inner table frame will
always have a zero margin, which means that a lot of the stuff which used to
rely on the fact that table margins are applied to the inner frame need to
change.
In particular, in order to get the computed margins of a table, we used to query
the inner table frame, and this patch corrects that. Also, when shrink wrapping
tables, we used to not take the margins of the inner table frame into account,
which is fixed by this patch too. nsBlockReflowState::
ComputeReplacedBlockOffsetsForFloats also needed to be changed to read the
margin values from the outer frame too.
Also, as part of this patch, we start to respect the CSS2.1 margin model for
captions on all sides. This means that in particular, the top/bottom margins on
the top-outside and bottom-outside captions will not be collapsed with the
top/bottom margins of the table, and that the margins of the caption element
contribute to the width and height of the outer table frame. The
427129-table-caption reftest has been modified to match this new behavior.
Another side effect of this bug is fixing bug 87277, and the reftests for that
bug are marked as passing in this patch.
2011-06-01 03:02:56 +04:00
|
|
|
/* virtual */ nsMargin
|
|
|
|
nsTableFrame::GetUsedMargin() const
|
|
|
|
{
|
|
|
|
// The margin is inherited to the outer table frame via
|
|
|
|
// the ::-moz-table-outer rule in ua.css.
|
|
|
|
return nsMargin(0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2010-03-29 05:46:55 +04:00
|
|
|
// Destructor function for BCPropertyData properties
|
|
|
|
static void
|
|
|
|
DestroyBCProperty(void* aPropertyValue)
|
|
|
|
{
|
|
|
|
delete static_cast<BCPropertyData*>(aPropertyValue);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_DECLARE_FRAME_PROPERTY(TableBCProperty, DestroyBCProperty)
|
|
|
|
|
2011-10-27 17:58:44 +04:00
|
|
|
BCPropertyData*
|
|
|
|
nsTableFrame::GetBCProperty(bool aCreateIfNecessary) const
|
|
|
|
{
|
|
|
|
FrameProperties props = Properties();
|
|
|
|
BCPropertyData* value = static_cast<BCPropertyData*>
|
|
|
|
(props.Get(TableBCProperty()));
|
|
|
|
if (!value && aCreateIfNecessary) {
|
|
|
|
value = new BCPropertyData();
|
|
|
|
props.Set(TableBCProperty(), value);
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
static void
|
2009-11-05 12:26:00 +03:00
|
|
|
DivideBCBorderSize(BCPixelSize aPixelSize,
|
|
|
|
BCPixelSize& aSmallHalf,
|
|
|
|
BCPixelSize& aLargeHalf)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
|
|
|
aSmallHalf = aPixelSize / 2;
|
2003-12-23 11:49:48 +03:00
|
|
|
aLargeHalf = aPixelSize - aSmallHalf;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2003-09-13 20:26:30 +04:00
|
|
|
nsMargin
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nsTableFrame::GetOuterBCBorder() const
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
if (NeedToCalcBCBorders())
|
2007-07-08 11:08:04 +04:00
|
|
|
const_cast<nsTableFrame*>(this)->CalcBCBorders();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
2003-09-13 20:26:30 +04:00
|
|
|
nsMargin border(0, 0, 0, 0);
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t p2t = nsPresContext::AppUnitsPerCSSPixel();
|
2011-10-27 17:58:44 +04:00
|
|
|
BCPropertyData* propData = GetBCProperty();
|
2002-02-19 18:48:28 +03:00
|
|
|
if (propData) {
|
2009-02-08 19:46:42 +03:00
|
|
|
border.top = BC_BORDER_TOP_HALF_COORD(p2t, propData->mTopBorderWidth);
|
|
|
|
border.right = BC_BORDER_RIGHT_HALF_COORD(p2t, propData->mRightBorderWidth);
|
|
|
|
border.bottom = BC_BORDER_BOTTOM_HALF_COORD(p2t, propData->mBottomBorderWidth);
|
|
|
|
border.left = BC_BORDER_LEFT_HALF_COORD(p2t, propData->mLeftBorderWidth);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2003-09-13 20:26:30 +04:00
|
|
|
return border;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2003-09-13 20:26:30 +04:00
|
|
|
nsMargin
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nsTableFrame::GetIncludedOuterBCBorder() const
|
2003-09-13 20:26:30 +04:00
|
|
|
{
|
2009-02-08 19:46:42 +03:00
|
|
|
if (NeedToCalcBCBorders())
|
|
|
|
const_cast<nsTableFrame*>(this)->CalcBCBorders();
|
|
|
|
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nsMargin border(0, 0, 0, 0);
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t p2t = nsPresContext::AppUnitsPerCSSPixel();
|
2011-10-27 17:58:44 +04:00
|
|
|
BCPropertyData* propData = GetBCProperty();
|
2009-02-08 19:46:42 +03:00
|
|
|
if (propData) {
|
|
|
|
border.top += BC_BORDER_TOP_HALF_COORD(p2t, propData->mTopBorderWidth);
|
|
|
|
border.right += BC_BORDER_RIGHT_HALF_COORD(p2t, propData->mRightCellBorderWidth);
|
|
|
|
border.bottom += BC_BORDER_BOTTOM_HALF_COORD(p2t, propData->mBottomBorderWidth);
|
|
|
|
border.left += BC_BORDER_LEFT_HALF_COORD(p2t, propData->mLeftCellBorderWidth);
|
|
|
|
}
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
return border;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsMargin
|
|
|
|
nsTableFrame::GetExcludedOuterBCBorder() const
|
|
|
|
{
|
2009-02-08 19:46:42 +03:00
|
|
|
return GetOuterBCBorder() - GetIncludedOuterBCBorder();
|
2003-09-13 20:26:30 +04:00
|
|
|
}
|
2009-07-22 04:44:52 +04:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
static
|
2003-09-13 20:26:30 +04:00
|
|
|
void GetSeparateModelBorderPadding(const nsHTMLReflowState* aReflowState,
|
2003-02-22 03:32:13 +03:00
|
|
|
nsStyleContext& aStyleContext,
|
2002-02-19 18:48:28 +03:00
|
|
|
nsMargin& aBorderPadding)
|
2001-03-13 09:38:59 +03:00
|
|
|
{
|
2005-04-29 19:44:38 +04:00
|
|
|
// XXXbz Either we _do_ have a reflow state and then we can use its
|
|
|
|
// mComputedBorderPadding or we don't and then we get the padding
|
|
|
|
// wrong!
|
2003-05-15 07:42:21 +04:00
|
|
|
const nsStyleBorder* border = aStyleContext.GetStyleBorder();
|
2012-05-31 09:19:49 +04:00
|
|
|
aBorderPadding = border->GetComputedBorder();
|
2002-02-19 18:48:28 +03:00
|
|
|
if (aReflowState) {
|
|
|
|
aBorderPadding += aReflowState->mComputedPadding;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
nsMargin
|
2003-12-28 20:02:40 +03:00
|
|
|
nsTableFrame::GetChildAreaOffset(const nsHTMLReflowState* aReflowState) const
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
|
|
|
nsMargin offset(0,0,0,0);
|
|
|
|
if (IsBorderCollapse()) {
|
2009-02-08 19:46:42 +03:00
|
|
|
offset = GetIncludedOuterBCBorder();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
2003-09-13 20:26:30 +04:00
|
|
|
GetSeparateModelBorderPadding(aReflowState, *mStyleContext, offset);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
return offset;
|
2001-03-13 09:38:59 +03:00
|
|
|
}
|
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
void
|
2010-04-27 20:15:01 +04:00
|
|
|
nsTableFrame::InitChildReflowState(nsHTMLReflowState& aReflowState)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
|
|
|
nsMargin collapseBorder;
|
|
|
|
nsMargin padding(0,0,0,0);
|
2012-07-30 18:20:58 +04:00
|
|
|
nsMargin* pCollapseBorder = nullptr;
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext* presContext = PresContext();
|
2002-02-19 18:48:28 +03:00
|
|
|
if (IsBorderCollapse()) {
|
2010-01-16 19:05:46 +03:00
|
|
|
nsTableRowGroupFrame* rgFrame =
|
|
|
|
static_cast<nsTableRowGroupFrame*>(aReflowState.frame);
|
|
|
|
pCollapseBorder = rgFrame->GetBCBorderWidth(collapseBorder);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2005-02-07 04:58:25 +03:00
|
|
|
aReflowState.Init(presContext, -1, -1, pCollapseBorder, &padding);
|
1998-10-11 13:18:27 +04:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
NS_ASSERTION(!mBits.mResizedColumns ||
|
|
|
|
!aReflowState.parentReflowState->mFlags.mSpecialHeightReflow,
|
|
|
|
"should not resize columns on special height reflow");
|
|
|
|
if (mBits.mResizedColumns) {
|
2011-10-17 18:59:28 +04:00
|
|
|
aReflowState.mFlags.mHResize = true;
|
1999-08-03 18:26:00 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Position and size aKidFrame and update our reflow state. The origin of
|
1999-01-05 03:41:40 +03:00
|
|
|
// aKidRect is relative to the upper-left origin of our frame
|
2005-02-07 04:58:25 +03:00
|
|
|
void nsTableFrame::PlaceChild(nsTableReflowState& aReflowState,
|
2001-03-13 09:38:59 +03:00
|
|
|
nsIFrame* aKidFrame,
|
2008-02-08 12:36:32 +03:00
|
|
|
nsHTMLReflowMetrics& aKidDesiredSize,
|
2008-03-16 23:32:48 +03:00
|
|
|
const nsRect& aOriginalKidRect,
|
2010-10-07 08:25:46 +04:00
|
|
|
const nsRect& aOriginalKidVisualOverflow)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2012-08-29 09:48:45 +04:00
|
|
|
bool isFirstReflow =
|
|
|
|
(aKidFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0;
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
// Place and size the child
|
2012-07-30 18:20:58 +04:00
|
|
|
FinishReflowChild(aKidFrame, PresContext(), nullptr, aKidDesiredSize,
|
2003-09-13 20:26:30 +04:00
|
|
|
aReflowState.x, aReflowState.y, 0);
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2012-08-29 09:48:45 +04:00
|
|
|
InvalidateTableFrame(aKidFrame, aOriginalKidRect, aOriginalKidVisualOverflow,
|
|
|
|
isFirstReflow);
|
|
|
|
|
1998-04-14 00:24:54 +04:00
|
|
|
// Adjust the running y-offset
|
2003-09-13 20:26:30 +04:00
|
|
|
aReflowState.y += aKidDesiredSize.height;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
1999-03-05 09:00:40 +03:00
|
|
|
// If our height is constrained, then update the available height
|
2001-03-13 09:38:59 +03:00
|
|
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height) {
|
2003-09-13 20:26:30 +04:00
|
|
|
aReflowState.availSize.height -= aKidDesiredSize.height;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2000-04-29 01:05:31 +04:00
|
|
|
void
|
2010-01-16 19:05:46 +03:00
|
|
|
nsTableFrame::OrderRowGroups(RowGroupArray& aChildren,
|
|
|
|
nsTableRowGroupFrame** aHead,
|
|
|
|
nsTableRowGroupFrame** aFoot) const
|
2007-06-05 22:55:26 +04:00
|
|
|
{
|
|
|
|
aChildren.Clear();
|
2012-07-30 18:20:58 +04:00
|
|
|
nsTableRowGroupFrame* head = nullptr;
|
|
|
|
nsTableRowGroupFrame* foot = nullptr;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2007-06-05 22:55:26 +04:00
|
|
|
nsIFrame* kidFrame = mFrames.FirstChild();
|
|
|
|
while (kidFrame) {
|
|
|
|
const nsStyleDisplay* kidDisplay = kidFrame->GetStyleDisplay();
|
2010-01-16 19:05:46 +03:00
|
|
|
nsTableRowGroupFrame* rowGroup =
|
|
|
|
static_cast<nsTableRowGroupFrame*>(kidFrame);
|
|
|
|
|
|
|
|
switch (kidDisplay->mDisplay) {
|
|
|
|
case NS_STYLE_DISPLAY_TABLE_HEADER_GROUP:
|
|
|
|
if (head) { // treat additional thead like tbody
|
2007-06-05 22:55:26 +04:00
|
|
|
aChildren.AppendElement(rowGroup);
|
|
|
|
}
|
2010-01-16 19:05:46 +03:00
|
|
|
else {
|
|
|
|
head = rowGroup;
|
2000-04-29 01:05:31 +04:00
|
|
|
}
|
2010-01-16 19:05:46 +03:00
|
|
|
break;
|
|
|
|
case NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP:
|
|
|
|
if (foot) { // treat additional tfoot like tbody
|
|
|
|
aChildren.AppendElement(rowGroup);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
foot = rowGroup;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case NS_STYLE_DISPLAY_TABLE_ROW_GROUP:
|
|
|
|
aChildren.AppendElement(rowGroup);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NS_NOTREACHED("How did this produce an nsTableRowGroupFrame?");
|
|
|
|
// Just ignore it
|
|
|
|
break;
|
2000-09-14 10:49:47 +04:00
|
|
|
}
|
2002-08-30 20:30:04 +04:00
|
|
|
// Get the next sibling but skip it if it's also the next-in-flow, since
|
|
|
|
// a next-in-flow will not be part of the current table.
|
|
|
|
while (kidFrame) {
|
2004-09-14 06:28:03 +04:00
|
|
|
nsIFrame* nif = kidFrame->GetNextInFlow();
|
2003-07-07 06:01:29 +04:00
|
|
|
kidFrame = kidFrame->GetNextSibling();
|
2010-04-27 20:15:01 +04:00
|
|
|
if (kidFrame != nif)
|
2002-08-30 20:30:04 +04:00
|
|
|
break;
|
|
|
|
}
|
2000-04-29 01:05:31 +04:00
|
|
|
}
|
2010-01-16 19:05:46 +03:00
|
|
|
|
2000-09-14 10:49:47 +04:00
|
|
|
// put the thead first
|
|
|
|
if (head) {
|
2007-06-05 22:55:26 +04:00
|
|
|
aChildren.InsertElementAt(0, head);
|
2000-09-14 10:49:47 +04:00
|
|
|
}
|
2010-01-16 19:05:46 +03:00
|
|
|
if (aHead)
|
|
|
|
*aHead = head;
|
2000-09-14 10:49:47 +04:00
|
|
|
// put the tfoot after the last tbody
|
|
|
|
if (foot) {
|
2007-06-05 22:55:26 +04:00
|
|
|
aChildren.AppendElement(foot);
|
2000-09-14 10:49:47 +04:00
|
|
|
}
|
2010-01-16 19:05:46 +03:00
|
|
|
if (aFoot)
|
|
|
|
*aFoot = foot;
|
2007-06-05 22:55:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsTableRowGroupFrame*
|
|
|
|
nsTableFrame::GetTHead() const
|
|
|
|
{
|
|
|
|
nsIFrame* kidFrame = mFrames.FirstChild();
|
|
|
|
while (kidFrame) {
|
|
|
|
if (kidFrame->GetStyleDisplay()->mDisplay ==
|
|
|
|
NS_STYLE_DISPLAY_TABLE_HEADER_GROUP) {
|
2010-01-16 19:05:46 +03:00
|
|
|
return static_cast<nsTableRowGroupFrame*>(kidFrame);
|
2007-06-05 22:55:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get the next sibling but skip it if it's also the next-in-flow, since
|
|
|
|
// a next-in-flow will not be part of the current table.
|
|
|
|
while (kidFrame) {
|
|
|
|
nsIFrame* nif = kidFrame->GetNextInFlow();
|
|
|
|
kidFrame = kidFrame->GetNextSibling();
|
2010-04-27 20:15:01 +04:00
|
|
|
if (kidFrame != nif)
|
2007-06-05 22:55:26 +04:00
|
|
|
break;
|
|
|
|
}
|
2000-09-14 10:49:47 +04:00
|
|
|
}
|
2007-06-05 22:55:26 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2007-06-05 22:55:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsTableRowGroupFrame*
|
|
|
|
nsTableFrame::GetTFoot() const
|
|
|
|
{
|
|
|
|
nsIFrame* kidFrame = mFrames.FirstChild();
|
|
|
|
while (kidFrame) {
|
|
|
|
if (kidFrame->GetStyleDisplay()->mDisplay ==
|
|
|
|
NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP) {
|
2010-01-16 19:05:46 +03:00
|
|
|
return static_cast<nsTableRowGroupFrame*>(kidFrame);
|
2007-06-05 22:55:26 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get the next sibling but skip it if it's also the next-in-flow, since
|
|
|
|
// a next-in-flow will not be part of the current table.
|
|
|
|
while (kidFrame) {
|
|
|
|
nsIFrame* nif = kidFrame->GetNextInFlow();
|
|
|
|
kidFrame = kidFrame->GetNextSibling();
|
2010-04-27 20:15:01 +04:00
|
|
|
if (kidFrame != nif)
|
2007-06-05 22:55:26 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2000-04-29 01:05:31 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2007-12-05 05:32:56 +03:00
|
|
|
IsRepeatable(nscoord aFrameHeight, nscoord aPageHeight)
|
2001-04-09 18:21:24 +04:00
|
|
|
{
|
2007-12-05 05:32:56 +03:00
|
|
|
return aFrameHeight < (aPageHeight / 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsTableFrame::SetupHeaderFooterChild(const nsTableReflowState& aReflowState,
|
|
|
|
nsTableRowGroupFrame* aFrame,
|
|
|
|
nscoord* aDesiredHeight)
|
|
|
|
{
|
|
|
|
nsPresContext* presContext = PresContext();
|
|
|
|
nscoord pageHeight = presContext->GetPageSize().height;
|
|
|
|
|
|
|
|
// Reflow the child with unconstrainted height
|
|
|
|
nsHTMLReflowState kidReflowState(presContext, aReflowState.reflowState,
|
|
|
|
aFrame,
|
|
|
|
nsSize(aReflowState.availSize.width, NS_UNCONSTRAINEDSIZE),
|
2011-10-17 18:59:28 +04:00
|
|
|
-1, -1, false);
|
2007-12-05 05:32:56 +03:00
|
|
|
InitChildReflowState(kidReflowState);
|
2011-10-17 18:59:28 +04:00
|
|
|
kidReflowState.mFlags.mIsTopOfPage = true;
|
2007-12-05 05:32:56 +03:00
|
|
|
nsHTMLReflowMetrics desiredSize;
|
|
|
|
desiredSize.width = desiredSize.height = 0;
|
|
|
|
nsReflowStatus status;
|
|
|
|
nsresult rv = ReflowChild(aFrame, presContext, desiredSize, kidReflowState,
|
|
|
|
aReflowState.x, aReflowState.y, 0, status);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
// The child will be reflowed again "for real" so no need to place it now
|
|
|
|
|
|
|
|
aFrame->SetRepeatable(IsRepeatable(desiredSize.height, pageHeight));
|
|
|
|
*aDesiredHeight = desiredSize.height;
|
|
|
|
return NS_OK;
|
2001-04-09 18:21:24 +04:00
|
|
|
}
|
|
|
|
|
2010-05-13 18:15:49 +04:00
|
|
|
void
|
|
|
|
nsTableFrame::PlaceRepeatedFooter(nsTableReflowState& aReflowState,
|
|
|
|
nsTableRowGroupFrame *aTfoot,
|
|
|
|
nscoord aFooterHeight)
|
|
|
|
{
|
|
|
|
nsPresContext* presContext = PresContext();
|
|
|
|
nsSize kidAvailSize(aReflowState.availSize);
|
|
|
|
kidAvailSize.height = aFooterHeight;
|
|
|
|
nsHTMLReflowState footerReflowState(presContext,
|
|
|
|
aReflowState.reflowState,
|
|
|
|
aTfoot, kidAvailSize,
|
2011-10-17 18:59:28 +04:00
|
|
|
-1, -1, false);
|
2010-05-13 18:15:49 +04:00
|
|
|
InitChildReflowState(footerReflowState);
|
|
|
|
aReflowState.y += GetCellSpacingY();
|
|
|
|
|
|
|
|
nsRect origTfootRect = aTfoot->GetRect();
|
2010-10-07 08:25:46 +04:00
|
|
|
nsRect origTfootVisualOverflow = aTfoot->GetVisualOverflowRect();
|
2010-05-13 18:15:49 +04:00
|
|
|
|
|
|
|
nsReflowStatus footerStatus;
|
|
|
|
nsHTMLReflowMetrics desiredSize;
|
|
|
|
desiredSize.width = desiredSize.height = 0;
|
|
|
|
ReflowChild(aTfoot, presContext, desiredSize, footerReflowState,
|
|
|
|
aReflowState.x, aReflowState.y,
|
|
|
|
NS_FRAME_INVALIDATE_ON_MOVE, footerStatus);
|
|
|
|
PlaceChild(aReflowState, aTfoot, desiredSize, origTfootRect,
|
2010-10-07 08:25:46 +04:00
|
|
|
origTfootVisualOverflow);
|
2010-05-13 18:15:49 +04:00
|
|
|
}
|
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
// Reflow the children based on the avail size and reason in aReflowState
|
|
|
|
// update aReflowMetrics a aStatus
|
2010-10-07 08:25:46 +04:00
|
|
|
nsresult
|
2005-02-07 04:58:25 +03:00
|
|
|
nsTableFrame::ReflowChildren(nsTableReflowState& aReflowState,
|
2002-03-04 18:48:56 +03:00
|
|
|
nsReflowStatus& aStatus,
|
|
|
|
nsIFrame*& aLastChildReflowed,
|
2010-10-07 08:25:46 +04:00
|
|
|
nsOverflowAreas& aOverflowAreas)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2001-03-13 09:38:59 +03:00
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
2012-07-30 18:20:58 +04:00
|
|
|
aLastChildReflowed = nullptr;
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame* prevKidFrame = nullptr;
|
1998-10-23 21:24:57 +04:00
|
|
|
nsresult rv = NS_OK;
|
2000-04-29 01:05:31 +04:00
|
|
|
nscoord cellSpacingY = GetCellSpacingY();
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext* presContext = PresContext();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
// XXXldb Should we be checking constrained height instead?
|
2011-08-13 20:37:43 +04:00
|
|
|
// tables are not able to pull back children from its next inflow, so even
|
|
|
|
// under paginated contexts tables are should not paginate if they are inside
|
|
|
|
// column set
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isPaginated = presContext->IsPaginated() &&
|
2011-08-13 20:37:43 +04:00
|
|
|
NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height &&
|
|
|
|
aReflowState.reflowState.mFlags.mTableIsSplittable;
|
2001-03-22 18:59:37 +03:00
|
|
|
|
2010-10-07 08:25:46 +04:00
|
|
|
aOverflowAreas.Clear();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool reflowAllKids = aReflowState.reflowState.ShouldReflowAllKids() ||
|
2007-05-18 10:04:43 +04:00
|
|
|
mBits.mResizedColumns ||
|
|
|
|
IsGeometryDirty();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
2010-01-16 19:05:46 +03:00
|
|
|
RowGroupArray rowGroups;
|
2001-04-09 18:21:24 +04:00
|
|
|
nsTableRowGroupFrame *thead, *tfoot;
|
2010-01-16 19:05:46 +03:00
|
|
|
OrderRowGroups(rowGroups, &thead, &tfoot);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool pageBreak = false;
|
2007-12-05 05:32:56 +03:00
|
|
|
nscoord footerHeight = 0;
|
|
|
|
|
|
|
|
// Determine the repeatablility of headers and footers, and also the desired
|
|
|
|
// height of any repeatable footer.
|
|
|
|
// The repeatability of headers on continued tables is handled
|
|
|
|
// when they are created in nsCSSFrameConstructor::CreateContinuingTableFrame.
|
|
|
|
// We handle the repeatability of footers again here because we need to
|
|
|
|
// determine the footer's height anyway. We could perhaps optimize by
|
|
|
|
// using the footer's prev-in-flow's height instead of reflowing it again,
|
|
|
|
// but there's no real need.
|
|
|
|
if (isPaginated) {
|
|
|
|
if (thead && !GetPrevInFlow()) {
|
|
|
|
nscoord desiredHeight;
|
|
|
|
rv = SetupHeaderFooterChild(aReflowState, thead, &desiredHeight);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
if (tfoot) {
|
|
|
|
rv = SetupHeaderFooterChild(aReflowState, tfoot, &footerHeight);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
2010-05-13 18:15:49 +04:00
|
|
|
// if the child is a tbody in paginated mode reduce the height by a repeated footer
|
2011-09-29 10:19:26 +04:00
|
|
|
bool allowRepeatedFooter = false;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t childX = 0; childX < rowGroups.Length(); childX++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsIFrame* kidFrame = rowGroups[childX];
|
2001-03-13 09:38:59 +03:00
|
|
|
// Get the frame state bits
|
|
|
|
// See if we should only reflow the dirty child frames
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (reflowAllKids ||
|
2007-05-06 23:16:51 +04:00
|
|
|
NS_SUBTREE_DIRTY(kidFrame) ||
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
(aReflowState.reflowState.mFlags.mSpecialHeightReflow &&
|
|
|
|
(isPaginated || (kidFrame->GetStateBits() &
|
|
|
|
NS_FRAME_CONTAINS_RELATIVE_HEIGHT)))) {
|
2002-03-18 00:35:08 +03:00
|
|
|
if (pageBreak) {
|
2010-05-13 18:15:49 +04:00
|
|
|
if (allowRepeatedFooter) {
|
|
|
|
PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
|
|
|
|
}
|
2011-08-13 20:37:43 +04:00
|
|
|
else if (tfoot && tfoot->IsRepeatable()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
tfoot->SetRepeatable(false);
|
2011-08-13 20:37:43 +04:00
|
|
|
}
|
|
|
|
PushChildren(rowGroups, childX);
|
2002-03-18 00:35:08 +03:00
|
|
|
aStatus = NS_FRAME_NOT_COMPLETE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2001-03-13 09:38:59 +03:00
|
|
|
nsSize kidAvailSize(aReflowState.availSize);
|
2011-10-17 18:59:28 +04:00
|
|
|
allowRepeatedFooter = false;
|
2001-03-22 18:59:37 +03:00
|
|
|
if (isPaginated && (NS_UNCONSTRAINEDSIZE != kidAvailSize.height)) {
|
2010-01-16 19:05:46 +03:00
|
|
|
nsTableRowGroupFrame* kidRG =
|
|
|
|
static_cast<nsTableRowGroupFrame*>(kidFrame);
|
2007-12-05 05:32:56 +03:00
|
|
|
if (kidRG != thead && kidRG != tfoot && tfoot && tfoot->IsRepeatable()) {
|
|
|
|
// the child is a tbody and there is a repeatable footer
|
|
|
|
NS_ASSERTION(tfoot == rowGroups[rowGroups.Length() - 1], "Missing footer!");
|
|
|
|
if (footerHeight + cellSpacingY < kidAvailSize.height) {
|
2011-10-17 18:59:28 +04:00
|
|
|
allowRepeatedFooter = true;
|
2007-12-05 05:32:56 +03:00
|
|
|
kidAvailSize.height -= footerHeight + cellSpacingY;
|
2001-03-22 18:59:37 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
nsRect oldKidRect = kidFrame->GetRect();
|
2010-10-07 08:25:46 +04:00
|
|
|
nsRect oldKidVisualOverflow = kidFrame->GetVisualOverflowRect();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
|
|
|
nsHTMLReflowMetrics desiredSize;
|
2007-01-23 07:06:56 +03:00
|
|
|
desiredSize.width = desiredSize.height = 0;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
// Reflow the child into the available space
|
|
|
|
nsHTMLReflowState kidReflowState(presContext, aReflowState.reflowState,
|
|
|
|
kidFrame, kidAvailSize,
|
2011-10-17 18:59:28 +04:00
|
|
|
-1, -1, false);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
InitChildReflowState(kidReflowState);
|
|
|
|
|
2008-04-17 22:18:41 +04:00
|
|
|
// If this isn't the first row group, and the previous row group has a
|
|
|
|
// nonzero YMost, then we can't be at the top of the page.
|
2012-11-08 20:09:38 +04:00
|
|
|
// We ignore a repeated head row group in this check to avoid causing
|
2008-04-17 22:18:41 +04:00
|
|
|
// infinite loops in some circumstances - see bug 344883.
|
2012-11-08 20:09:38 +04:00
|
|
|
if (childX > ((thead && IsRepeatedFrame(thead)) ? 1 : 0) &&
|
2008-04-17 22:18:41 +04:00
|
|
|
(rowGroups[childX - 1]->GetRect().YMost() > 0)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
kidReflowState.mFlags.mIsTopOfPage = false;
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
aReflowState.y += cellSpacingY;
|
|
|
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height) {
|
|
|
|
aReflowState.availSize.height -= cellSpacingY;
|
|
|
|
}
|
|
|
|
// record the presence of a next in flow, it might get destroyed so we
|
|
|
|
// need to reorder the row group array
|
2011-09-29 10:19:26 +04:00
|
|
|
bool reorder = false;
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (kidFrame->GetNextInFlow())
|
2011-10-17 18:59:28 +04:00
|
|
|
reorder = true;
|
2008-02-08 12:36:32 +03:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
rv = ReflowChild(kidFrame, presContext, desiredSize, kidReflowState,
|
2008-02-08 12:36:32 +03:00
|
|
|
aReflowState.x, aReflowState.y,
|
|
|
|
NS_FRAME_INVALIDATE_ON_MOVE, aStatus);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
|
|
|
if (reorder) {
|
|
|
|
// reorder row groups the reflow may have changed the nextinflows
|
2010-01-16 19:05:46 +03:00
|
|
|
OrderRowGroups(rowGroups, &thead, &tfoot);
|
2007-06-05 22:55:26 +04:00
|
|
|
childX = rowGroups.IndexOf(kidFrame);
|
|
|
|
if (childX == RowGroupArray::NoIndex) {
|
|
|
|
// XXXbz can this happen?
|
2010-01-16 19:05:46 +03:00
|
|
|
childX = rowGroups.Length();
|
2005-01-01 21:23:33 +03:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
2012-11-08 20:09:38 +04:00
|
|
|
if (isPaginated && !NS_FRAME_IS_FULLY_COMPLETE(aStatus) &&
|
|
|
|
ShouldAvoidBreakInside(aReflowState.reflowState)) {
|
|
|
|
aStatus = NS_INLINE_LINE_BREAK_BEFORE();
|
|
|
|
break;
|
|
|
|
}
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
// see if the rowgroup did not fit on this page might be pushed on
|
|
|
|
// the next page
|
2012-11-08 20:09:38 +04:00
|
|
|
if (isPaginated &&
|
|
|
|
(NS_INLINE_IS_BREAK_BEFORE(aStatus) ||
|
|
|
|
(NS_FRAME_IS_COMPLETE(aStatus) &&
|
|
|
|
(NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight) &&
|
|
|
|
kidReflowState.availableHeight < desiredSize.height))) {
|
|
|
|
if (ShouldAvoidBreakInside(aReflowState.reflowState)) {
|
|
|
|
aStatus = NS_INLINE_LINE_BREAK_BEFORE();
|
|
|
|
break;
|
|
|
|
}
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
// if we are on top of the page place with dataloss
|
|
|
|
if (kidReflowState.mFlags.mIsTopOfPage) {
|
2007-06-05 22:55:26 +04:00
|
|
|
if (childX+1 < rowGroups.Length()) {
|
|
|
|
nsIFrame* nextRowGroupFrame = rowGroups[childX + 1];
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (nextRowGroupFrame) {
|
2008-03-16 23:32:48 +03:00
|
|
|
PlaceChild(aReflowState, kidFrame, desiredSize, oldKidRect,
|
2010-10-07 08:25:46 +04:00
|
|
|
oldKidVisualOverflow);
|
2010-05-13 18:15:49 +04:00
|
|
|
if (allowRepeatedFooter) {
|
|
|
|
PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
|
|
|
|
}
|
2011-08-13 20:37:43 +04:00
|
|
|
else if (tfoot && tfoot->IsRepeatable()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
tfoot->SetRepeatable(false);
|
2011-08-13 20:37:43 +04:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
aStatus = NS_FRAME_NOT_COMPLETE;
|
|
|
|
PushChildren(rowGroups, childX + 1);
|
|
|
|
aLastChildReflowed = kidFrame;
|
2006-01-28 09:14:11 +03:00
|
|
|
break;
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
2006-01-28 09:14:11 +03:00
|
|
|
}
|
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
else { // we are not on top, push this rowgroup onto the next page
|
|
|
|
if (prevKidFrame) { // we had a rowgroup before so push this
|
2010-05-13 18:15:49 +04:00
|
|
|
if (allowRepeatedFooter) {
|
|
|
|
PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
|
|
|
|
}
|
2011-08-13 20:37:43 +04:00
|
|
|
else if (tfoot && tfoot->IsRepeatable()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
tfoot->SetRepeatable(false);
|
2011-08-13 20:37:43 +04:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
aStatus = NS_FRAME_NOT_COMPLETE;
|
|
|
|
PushChildren(rowGroups, childX);
|
|
|
|
aLastChildReflowed = prevKidFrame;
|
|
|
|
break;
|
2005-01-01 21:23:33 +03:00
|
|
|
}
|
2011-07-26 21:22:46 +04:00
|
|
|
else { // we can't push so lets make clear how much space we need
|
|
|
|
PlaceChild(aReflowState, kidFrame, desiredSize, oldKidRect,
|
|
|
|
oldKidVisualOverflow);
|
|
|
|
aLastChildReflowed = kidFrame;
|
|
|
|
if (allowRepeatedFooter) {
|
|
|
|
PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
|
|
|
|
aLastChildReflowed = tfoot;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
aLastChildReflowed = kidFrame;
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
pageBreak = false;
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
// see if there is a page break after this row group or before the next one
|
2010-04-27 20:15:01 +04:00
|
|
|
if (NS_FRAME_IS_COMPLETE(aStatus) && isPaginated &&
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
(NS_UNCONSTRAINEDSIZE != kidReflowState.availableHeight)) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsIFrame* nextKid =
|
2012-07-30 18:20:58 +04:00
|
|
|
(childX + 1 < rowGroups.Length()) ? rowGroups[childX + 1] : nullptr;
|
2010-05-13 18:15:49 +04:00
|
|
|
pageBreak = PageBreakAfter(kidFrame, nextKid);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Place the child
|
2008-03-16 23:32:48 +03:00
|
|
|
PlaceChild(aReflowState, kidFrame, desiredSize, oldKidRect,
|
2010-10-07 08:25:46 +04:00
|
|
|
oldKidVisualOverflow);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
|
|
|
// Remember where we just were in case we end up pushing children
|
|
|
|
prevKidFrame = kidFrame;
|
|
|
|
|
|
|
|
// Special handling for incomplete children
|
2010-04-27 20:15:01 +04:00
|
|
|
if (NS_FRAME_IS_NOT_COMPLETE(aStatus)) {
|
2011-03-29 00:50:13 +04:00
|
|
|
nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (!kidNextInFlow) {
|
|
|
|
// The child doesn't have a next-in-flow so create a continuing
|
|
|
|
// frame. This hooks the child into the flow
|
|
|
|
rv = presContext->PresShell()->FrameConstructor()->
|
2009-09-18 15:09:35 +04:00
|
|
|
CreateContinuingFrame(presContext, kidFrame, this, &kidNextInFlow);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
aStatus = NS_FRAME_COMPLETE;
|
|
|
|
break;
|
2005-01-01 21:23:33 +03:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
|
2009-09-18 15:09:35 +04:00
|
|
|
// Insert the continuing frame into the sibling list.
|
2012-07-30 18:20:58 +04:00
|
|
|
mFrames.InsertFrame(nullptr, kidFrame, kidNextInFlow);
|
2009-09-18 15:09:35 +04:00
|
|
|
|
|
|
|
// Fall through and update |rowGroups| with the new rowgroup, just as
|
|
|
|
// it would have been if we had called OrderRowGroups again.
|
|
|
|
// Note that rowGroups doesn't get used again after we PushChildren
|
|
|
|
// below, anyway.
|
2005-01-01 21:23:33 +03:00
|
|
|
}
|
2009-09-18 15:09:35 +04:00
|
|
|
|
|
|
|
// Put the nextinflow so that it will get pushed
|
2010-01-16 19:05:46 +03:00
|
|
|
rowGroups.InsertElementAt(childX + 1,
|
|
|
|
static_cast <nsTableRowGroupFrame*>(kidNextInFlow));
|
2009-09-18 15:09:35 +04:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
// We've used up all of our available space so push the remaining
|
|
|
|
// children to the next-in-flow
|
2011-08-13 20:37:43 +04:00
|
|
|
if (allowRepeatedFooter) {
|
|
|
|
PlaceRepeatedFooter(aReflowState, tfoot, footerHeight);
|
|
|
|
}
|
|
|
|
else if (tfoot && tfoot->IsRepeatable()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
tfoot->SetRepeatable(false);
|
2011-08-13 20:37:43 +04:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
nsIFrame* nextSibling = kidFrame->GetNextSibling();
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != nextSibling) {
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
PushChildren(rowGroups, childX + 1);
|
2002-03-18 00:35:08 +03:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
break;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
2001-03-13 09:38:59 +03:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
else { // it isn't being reflowed
|
|
|
|
aReflowState.y += cellSpacingY;
|
2003-07-07 06:01:29 +04:00
|
|
|
nsRect kidRect = kidFrame->GetRect();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
if (kidRect.y != aReflowState.y) {
|
2012-08-29 09:48:45 +04:00
|
|
|
// invalidate the old position
|
|
|
|
kidFrame->InvalidateFrameSubtree();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
kidRect.y = aReflowState.y;
|
|
|
|
kidFrame->SetRect(kidRect); // move to the new position
|
|
|
|
RePositionViews(kidFrame);
|
2012-08-29 09:48:45 +04:00
|
|
|
// invalidate the new position
|
|
|
|
kidFrame->InvalidateFrameSubtree();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
aReflowState.y += kidRect.height;
|
|
|
|
|
|
|
|
// If our height is constrained then update the available height.
|
|
|
|
if (NS_UNCONSTRAINEDSIZE != aReflowState.availSize.height) {
|
|
|
|
aReflowState.availSize.height -= cellSpacingY + kidRect.height;
|
2000-10-10 03:57:51 +04:00
|
|
|
}
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
2010-10-07 08:25:46 +04:00
|
|
|
ConsiderChildOverflow(aOverflowAreas, kidFrame);
|
2001-03-13 09:38:59 +03:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2006-12-13 06:45:28 +03:00
|
|
|
// We've now propagated the column resizes and geometry changes to all
|
|
|
|
// the children.
|
2011-10-17 18:59:28 +04:00
|
|
|
mBits.mResizedColumns = false;
|
2006-12-13 06:45:28 +03:00
|
|
|
ClearGeometryDirty();
|
1998-12-23 18:47:43 +03:00
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
return rv;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
void
|
2011-04-08 05:04:40 +04:00
|
|
|
nsTableFrame::ReflowColGroups(nsRenderingContext *aRenderingContext)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
if (!GetPrevInFlow() && !HaveReflowedColGroups()) {
|
|
|
|
nsHTMLReflowMetrics kidMet;
|
2007-03-31 01:11:41 +04:00
|
|
|
nsPresContext *presContext = PresContext();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
for (nsIFrame* kidFrame = mColGroups.FirstChild(); kidFrame;
|
|
|
|
kidFrame = kidFrame->GetNextSibling()) {
|
2007-08-18 03:51:58 +04:00
|
|
|
if (NS_SUBTREE_DIRTY(kidFrame)) {
|
2007-08-18 03:58:19 +04:00
|
|
|
// The column groups don't care about dimensions or reflow states.
|
|
|
|
nsHTMLReflowState kidReflowState(presContext, kidFrame,
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
aRenderingContext, nsSize(0,0));
|
2007-08-18 03:58:19 +04:00
|
|
|
nsReflowStatus cgStatus;
|
|
|
|
ReflowChild(kidFrame, presContext, kidMet, kidReflowState, 0, 0, 0,
|
|
|
|
cgStatus);
|
2012-07-30 18:20:58 +04:00
|
|
|
FinishReflowChild(kidFrame, presContext, nullptr, kidMet, 0, 0, 0);
|
2007-08-18 03:58:19 +04:00
|
|
|
}
|
2007-08-18 03:51:58 +04:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
SetHaveReflowedColGroups(true);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
|
|
|
nsTableFrame::CalcDesiredHeight(const nsHTMLReflowState& aReflowState, nsHTMLReflowMetrics& aDesiredSize)
|
1998-11-20 04:01:25 +03:00
|
|
|
{
|
2000-01-15 23:10:00 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
|
|
|
if (!cellMap) {
|
2011-10-17 18:59:28 +04:00
|
|
|
NS_ASSERTION(false, "never ever call me until the cell map is built!");
|
2004-09-13 22:21:03 +04:00
|
|
|
aDesiredSize.height = 0;
|
|
|
|
return;
|
2000-01-15 23:10:00 +03:00
|
|
|
}
|
2001-03-13 09:38:59 +03:00
|
|
|
nscoord cellSpacingY = GetCellSpacingY();
|
2003-12-28 20:02:40 +03:00
|
|
|
nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
|
2001-03-13 09:38:59 +03:00
|
|
|
|
2010-01-16 19:05:46 +03:00
|
|
|
// get the natural height based on the last child's (row group) rect
|
|
|
|
RowGroupArray rowGroups;
|
|
|
|
OrderRowGroups(rowGroups);
|
|
|
|
if (rowGroups.IsEmpty()) {
|
2003-12-23 10:22:16 +03:00
|
|
|
// tables can be used as rectangular items without content
|
2003-12-28 20:02:40 +03:00
|
|
|
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
2003-12-23 10:22:16 +03:00
|
|
|
if ((NS_UNCONSTRAINEDSIZE != tableSpecifiedHeight) &&
|
2004-06-09 08:13:53 +04:00
|
|
|
(tableSpecifiedHeight > 0) &&
|
2007-03-31 01:11:41 +04:00
|
|
|
eCompatibility_NavQuirks != PresContext()->CompatibilityMode()) {
|
2004-09-13 22:21:03 +04:00
|
|
|
// empty tables should not have a size in quirks mode
|
|
|
|
aDesiredSize.height = tableSpecifiedHeight;
|
2010-04-27 20:15:01 +04:00
|
|
|
}
|
2004-09-13 22:21:03 +04:00
|
|
|
else
|
|
|
|
aDesiredSize.height = 0;
|
|
|
|
return;
|
2003-12-23 10:22:16 +03:00
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rowCount = cellMap->GetRowCount();
|
|
|
|
int32_t colCount = cellMap->GetColCount();
|
2004-09-02 10:36:56 +04:00
|
|
|
nscoord desiredHeight = borderPadding.top + borderPadding.bottom;
|
|
|
|
if (rowCount > 0 && colCount > 0) {
|
|
|
|
desiredHeight += cellSpacingY;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
desiredHeight += rowGroups[rgX]->GetSize().height + cellSpacingY;
|
2001-03-22 18:59:37 +03:00
|
|
|
}
|
|
|
|
}
|
1998-11-20 04:01:25 +03:00
|
|
|
|
2001-08-08 05:13:35 +04:00
|
|
|
// see if a specified table height requires dividing additional space to rows
|
2006-02-22 00:33:47 +03:00
|
|
|
if (!GetPrevInFlow()) {
|
2003-12-28 20:02:40 +03:00
|
|
|
nscoord tableSpecifiedHeight = CalcBorderBoxHeight(aReflowState);
|
2010-04-27 20:15:01 +04:00
|
|
|
if ((tableSpecifiedHeight > 0) &&
|
2001-08-08 05:13:35 +04:00
|
|
|
(tableSpecifiedHeight != NS_UNCONSTRAINEDSIZE) &&
|
2001-11-05 03:15:51 +03:00
|
|
|
(tableSpecifiedHeight > desiredHeight)) {
|
|
|
|
// proportionately distribute the excess height to unconstrained rows in each
|
2007-05-18 10:04:43 +04:00
|
|
|
// unconstrained row group.
|
|
|
|
DistributeHeightToRows(aReflowState, tableSpecifiedHeight - desiredHeight);
|
|
|
|
// this might have changed the overflow area incorporate the childframe overflow area.
|
|
|
|
for (nsIFrame* kidFrame = mFrames.FirstChild(); kidFrame; kidFrame = kidFrame->GetNextSibling()) {
|
2010-10-07 08:25:46 +04:00
|
|
|
ConsiderChildOverflow(aDesiredSize.mOverflowAreas, kidFrame);
|
2010-04-27 20:15:01 +04:00
|
|
|
}
|
2001-08-08 05:13:35 +04:00
|
|
|
desiredHeight = tableSpecifiedHeight;
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
|
|
|
}
|
2004-09-13 22:21:03 +04:00
|
|
|
aDesiredSize.height = desiredHeight;
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
2001-08-08 05:13:35 +04:00
|
|
|
|
2001-11-05 03:15:51 +03:00
|
|
|
static
|
2007-01-28 01:22:24 +03:00
|
|
|
void ResizeCells(nsTableFrame& aTableFrame)
|
2001-11-05 03:15:51 +03:00
|
|
|
{
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableFrame::RowGroupArray rowGroups;
|
|
|
|
aTableFrame.OrderRowGroups(rowGroups);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nsHTMLReflowMetrics tableDesiredSize;
|
2003-09-13 20:26:30 +04:00
|
|
|
nsRect tableRect = aTableFrame.GetRect();
|
|
|
|
tableDesiredSize.width = tableRect.width;
|
|
|
|
tableDesiredSize.height = tableRect.height;
|
2010-10-07 08:25:46 +04:00
|
|
|
tableDesiredSize.SetOverflowAreasToDesiredBounds();
|
2001-11-05 03:15:51 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2003-09-13 20:26:30 +04:00
|
|
|
nsRect rowGroupRect = rgFrame->GetRect();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nsHTMLReflowMetrics groupDesiredSize;
|
2003-09-13 20:26:30 +04:00
|
|
|
groupDesiredSize.width = rowGroupRect.width;
|
|
|
|
groupDesiredSize.height = rowGroupRect.height;
|
2010-10-07 08:25:46 +04:00
|
|
|
groupDesiredSize.SetOverflowAreasToDesiredBounds();
|
|
|
|
|
2001-11-05 03:15:51 +03:00
|
|
|
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
|
|
|
while (rowFrame) {
|
2007-01-28 01:22:24 +03:00
|
|
|
rowFrame->DidResize();
|
2010-10-07 08:25:46 +04:00
|
|
|
rgFrame->ConsiderChildOverflow(groupDesiredSize.mOverflowAreas, rowFrame);
|
2001-11-05 03:15:51 +03:00
|
|
|
rowFrame = rowFrame->GetNextRow();
|
|
|
|
}
|
2010-10-07 08:25:45 +04:00
|
|
|
rgFrame->FinishAndStoreOverflow(&groupDesiredSize);
|
2010-10-07 08:25:46 +04:00
|
|
|
tableDesiredSize.mOverflowAreas.UnionWith(groupDesiredSize.mOverflowAreas +
|
|
|
|
rgFrame->GetPosition());
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
2010-10-07 08:25:45 +04:00
|
|
|
aTableFrame.FinishAndStoreOverflow(&tableDesiredSize);
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-12-28 20:02:40 +03:00
|
|
|
nsTableFrame::DistributeHeightToRows(const nsHTMLReflowState& aReflowState,
|
2001-11-05 03:15:51 +03:00
|
|
|
nscoord aAmount)
|
2007-02-07 10:46:44 +03:00
|
|
|
{
|
2001-11-05 03:15:51 +03:00
|
|
|
nscoord cellSpacingY = GetCellSpacingY();
|
|
|
|
|
2003-12-28 20:02:40 +03:00
|
|
|
nsMargin borderPadding = GetChildAreaOffset(&aReflowState);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2007-06-05 22:55:26 +04:00
|
|
|
RowGroupArray rowGroups;
|
|
|
|
OrderRowGroups(rowGroups);
|
2001-11-05 03:15:51 +03:00
|
|
|
|
|
|
|
nscoord amountUsed = 0;
|
2010-04-27 20:15:01 +04:00
|
|
|
// distribute space to each pct height row whose row group doesn't have a computed
|
|
|
|
// height, and base the pct on the table height. If the row group had a computed
|
2001-11-05 03:15:51 +03:00
|
|
|
// height, then this was already done in nsTableRowGroupFrame::CalculateRowHeights
|
2007-08-02 22:08:05 +04:00
|
|
|
nscoord pctBasis = aReflowState.ComputedHeight() - (GetCellSpacingY() * (GetRowCount() + 1));
|
2002-02-19 18:48:28 +03:00
|
|
|
nscoord yOriginRG = borderPadding.top + GetCellSpacingY();
|
2001-11-05 03:15:51 +03:00
|
|
|
nscoord yEndRG = yOriginRG;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t rgX;
|
2007-06-05 22:55:26 +04:00
|
|
|
for (rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
|
|
|
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
2001-11-05 03:15:51 +03:00
|
|
|
nscoord amountUsedByRG = 0;
|
|
|
|
nscoord yOriginRow = 0;
|
2003-07-07 06:01:29 +04:00
|
|
|
nsRect rgRect = rgFrame->GetRect();
|
2007-06-05 22:55:26 +04:00
|
|
|
if (!rgFrame->HasStyleHeight()) {
|
2001-11-05 03:15:51 +03:00
|
|
|
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
|
|
|
while (rowFrame) {
|
2003-07-07 06:01:29 +04:00
|
|
|
nsRect rowRect = rowFrame->GetRect();
|
2001-11-05 03:15:51 +03:00
|
|
|
if ((amountUsed < aAmount) && rowFrame->HasPctHeight()) {
|
2007-02-22 23:22:12 +03:00
|
|
|
nscoord pctHeight = rowFrame->GetHeight(pctBasis);
|
2009-09-16 19:01:36 +04:00
|
|
|
nscoord amountForRow = NS_MIN(aAmount - amountUsed, pctHeight - rowRect.height);
|
2001-11-05 03:15:51 +03:00
|
|
|
if (amountForRow > 0) {
|
2008-02-08 12:36:32 +03:00
|
|
|
nsRect oldRowRect = rowRect;
|
2001-11-05 03:15:51 +03:00
|
|
|
rowRect.height += amountForRow;
|
2008-02-08 12:36:32 +03:00
|
|
|
// XXXbz we don't need to change rowRect.y to be yOriginRow?
|
2003-07-07 06:01:29 +04:00
|
|
|
rowFrame->SetRect(rowRect);
|
2001-11-05 03:15:51 +03:00
|
|
|
yOriginRow += rowRect.height + cellSpacingY;
|
|
|
|
yEndRG += rowRect.height + cellSpacingY;
|
|
|
|
amountUsed += amountForRow;
|
|
|
|
amountUsedByRG += amountForRow;
|
2010-04-27 20:15:01 +04:00
|
|
|
//rowFrame->DidResize();
|
2004-12-27 18:05:18 +03:00
|
|
|
nsTableFrame::RePositionViews(rowFrame);
|
2012-08-29 09:48:45 +04:00
|
|
|
|
|
|
|
rgFrame->InvalidateFrameWithRect(oldRowRect);
|
|
|
|
rgFrame->InvalidateFrame();
|
2001-08-08 05:13:35 +04:00
|
|
|
}
|
1999-08-21 03:27:54 +04:00
|
|
|
}
|
2001-11-05 03:15:51 +03:00
|
|
|
else {
|
2008-02-08 12:36:32 +03:00
|
|
|
if (amountUsed > 0 && yOriginRow != rowRect.y &&
|
|
|
|
!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
|
2012-08-29 09:48:45 +04:00
|
|
|
rowFrame->InvalidateFrameSubtree();
|
2003-07-07 06:01:29 +04:00
|
|
|
rowFrame->SetPosition(nsPoint(rowRect.x, yOriginRow));
|
2004-12-27 18:05:18 +03:00
|
|
|
nsTableFrame::RePositionViews(rowFrame);
|
2012-08-29 09:48:45 +04:00
|
|
|
rowFrame->InvalidateFrameSubtree();
|
2001-08-08 05:13:35 +04:00
|
|
|
}
|
2001-11-05 03:15:51 +03:00
|
|
|
yOriginRow += rowRect.height + cellSpacingY;
|
|
|
|
yEndRG += rowRect.height + cellSpacingY;
|
1998-11-20 04:01:25 +03:00
|
|
|
}
|
2001-11-05 03:15:51 +03:00
|
|
|
rowFrame = rowFrame->GetNextRow();
|
1998-11-20 04:01:25 +03:00
|
|
|
}
|
2001-11-05 03:15:51 +03:00
|
|
|
if (amountUsed > 0) {
|
2012-08-29 09:48:45 +04:00
|
|
|
if (rgRect.y != yOriginRG) {
|
|
|
|
rgFrame->InvalidateFrameSubtree();
|
|
|
|
}
|
|
|
|
|
2008-02-08 12:36:32 +03:00
|
|
|
nsRect origRgRect = rgRect;
|
2012-08-29 09:48:45 +04:00
|
|
|
nsRect origRgVisualOverflow = rgFrame->GetVisualOverflowRect();
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2001-11-05 03:15:51 +03:00
|
|
|
rgRect.y = yOriginRG;
|
|
|
|
rgRect.height += amountUsedByRG;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2003-07-07 06:01:29 +04:00
|
|
|
rgFrame->SetRect(rgRect);
|
2012-08-29 09:48:45 +04:00
|
|
|
|
|
|
|
nsTableFrame::InvalidateTableFrame(rgFrame, origRgRect,
|
|
|
|
origRgVisualOverflow, false);
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
|
|
|
}
|
2008-08-07 00:53:36 +04:00
|
|
|
else if (amountUsed > 0 && yOriginRG != rgRect.y) {
|
2012-08-29 09:48:45 +04:00
|
|
|
rgFrame->InvalidateFrameSubtree();
|
2008-08-07 00:53:36 +04:00
|
|
|
rgFrame->SetPosition(nsPoint(rgRect.x, yOriginRG));
|
2001-11-05 03:15:51 +03:00
|
|
|
// Make sure child views are properly positioned
|
2004-12-27 18:05:18 +03:00
|
|
|
nsTableFrame::RePositionViews(rgFrame);
|
2012-08-29 09:48:45 +04:00
|
|
|
rgFrame->InvalidateFrameSubtree();
|
1998-11-20 04:01:25 +03:00
|
|
|
}
|
2001-11-05 03:15:51 +03:00
|
|
|
yOriginRG = yEndRG;
|
1998-11-20 04:01:25 +03:00
|
|
|
}
|
2001-11-05 03:15:51 +03:00
|
|
|
|
|
|
|
if (amountUsed >= aAmount) {
|
2007-01-28 01:22:24 +03:00
|
|
|
ResizeCells(*this);
|
2001-11-05 03:15:51 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-12-15 19:08:52 +03:00
|
|
|
// get the first row without a style height where its row group has an
|
|
|
|
// unconstrained height
|
2012-07-30 18:20:58 +04:00
|
|
|
nsTableRowGroupFrame* firstUnStyledRG = nullptr;
|
|
|
|
nsTableRowFrame* firstUnStyledRow = nullptr;
|
2007-06-05 22:55:26 +04:00
|
|
|
for (rgX = 0; rgX < rowGroups.Length() && !firstUnStyledRG; rgX++) {
|
|
|
|
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
|
|
|
if (!rgFrame->HasStyleHeight()) {
|
2001-11-05 03:15:51 +03:00
|
|
|
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
|
|
|
while (rowFrame) {
|
|
|
|
if (!rowFrame->HasStyleHeight()) {
|
|
|
|
firstUnStyledRG = rgFrame;
|
|
|
|
firstUnStyledRow = rowFrame;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rowFrame = rowFrame->GetNextRow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsTableRowFrame* lastEligibleRow = nullptr;
|
2007-12-15 19:08:52 +03:00
|
|
|
// Accumulate the correct divisor. This will be the total total height of all
|
|
|
|
// unstyled rows inside unstyled row groups, unless there are none, in which
|
|
|
|
// case, it will be number of all rows. If the unstyled rows don't have a
|
|
|
|
// height, divide the space equally among them.
|
2001-11-05 03:15:51 +03:00
|
|
|
nscoord divisor = 0;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t eligibleRows = 0;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool expandEmptyRows = false;
|
2007-12-15 19:08:52 +03:00
|
|
|
|
|
|
|
if (!firstUnStyledRow) {
|
|
|
|
// there is no unstyled row
|
|
|
|
divisor = GetRowCount();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
for (rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
|
|
|
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
|
|
|
if (!firstUnStyledRG || !rgFrame->HasStyleHeight()) {
|
|
|
|
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
|
|
|
while (rowFrame) {
|
|
|
|
if (!firstUnStyledRG || !rowFrame->HasStyleHeight()) {
|
|
|
|
NS_ASSERTION(rowFrame->GetSize().height >= 0,
|
|
|
|
"negative row frame height");
|
|
|
|
divisor += rowFrame->GetSize().height;
|
|
|
|
eligibleRows++;
|
|
|
|
lastEligibleRow = rowFrame;
|
|
|
|
}
|
|
|
|
rowFrame = rowFrame->GetNextRow();
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
2007-12-15 19:08:52 +03:00
|
|
|
}
|
|
|
|
}
|
2007-12-15 23:23:10 +03:00
|
|
|
if (divisor <= 0) {
|
|
|
|
if (eligibleRows > 0) {
|
2011-10-17 18:59:28 +04:00
|
|
|
expandEmptyRows = true;
|
2007-12-15 23:23:10 +03:00
|
|
|
}
|
2007-12-15 19:08:52 +03:00
|
|
|
else {
|
|
|
|
NS_ERROR("invalid divisor");
|
|
|
|
return;
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// allocate the extra height to the unstyled row groups and rows
|
2007-12-15 19:08:52 +03:00
|
|
|
nscoord heightToDistribute = aAmount - amountUsed;
|
2002-02-19 18:48:28 +03:00
|
|
|
yOriginRG = borderPadding.top + cellSpacingY;
|
2001-11-05 03:15:51 +03:00
|
|
|
yEndRG = yOriginRG;
|
2007-06-05 22:55:26 +04:00
|
|
|
for (rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
|
|
|
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
2001-11-05 03:15:51 +03:00
|
|
|
nscoord amountUsedByRG = 0;
|
|
|
|
nscoord yOriginRow = 0;
|
2003-07-07 06:01:29 +04:00
|
|
|
nsRect rgRect = rgFrame->GetRect();
|
2010-10-07 08:25:46 +04:00
|
|
|
nsRect rgVisualOverflow = rgFrame->GetVisualOverflowRect();
|
2007-12-15 19:08:52 +03:00
|
|
|
// see if there is an eligible row group or we distribute to all rows
|
|
|
|
if (!firstUnStyledRG || !rgFrame->HasStyleHeight() || !eligibleRows) {
|
2001-11-05 03:15:51 +03:00
|
|
|
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
|
|
|
while (rowFrame) {
|
2003-07-07 06:01:29 +04:00
|
|
|
nsRect rowRect = rowFrame->GetRect();
|
2010-10-07 08:25:46 +04:00
|
|
|
nsRect rowVisualOverflow = rowFrame->GetVisualOverflowRect();
|
2007-12-15 19:08:52 +03:00
|
|
|
// see if there is an eligible row or we distribute to all rows
|
2010-04-27 20:15:01 +04:00
|
|
|
if (!firstUnStyledRow || !rowFrame->HasStyleHeight() || !eligibleRows) {
|
2007-12-15 19:08:52 +03:00
|
|
|
float ratio;
|
|
|
|
if (eligibleRows) {
|
|
|
|
if (!expandEmptyRows) {
|
|
|
|
// The amount of additional space each row gets is proportional to
|
|
|
|
// its height
|
|
|
|
ratio = float(rowRect.height) / float(divisor);
|
|
|
|
} else {
|
|
|
|
// empty rows get all the same additional space
|
|
|
|
ratio = 1.0f / float(eligibleRows);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// all rows get the same additional space
|
|
|
|
ratio = 1.0f / float(divisor);
|
2007-11-14 04:24:21 +03:00
|
|
|
}
|
2007-12-15 19:08:52 +03:00
|
|
|
// give rows their additional space, except for the last row which
|
|
|
|
// gets the remainder
|
2010-04-27 20:15:01 +04:00
|
|
|
nscoord amountForRow = (rowFrame == lastEligibleRow)
|
2007-12-15 19:08:52 +03:00
|
|
|
? aAmount - amountUsed : NSToCoordRound(((float)(heightToDistribute)) * ratio);
|
2009-09-16 19:01:36 +04:00
|
|
|
amountForRow = NS_MIN(amountForRow, aAmount - amountUsed);
|
2008-02-08 12:36:32 +03:00
|
|
|
|
2012-08-29 09:48:45 +04:00
|
|
|
if (yOriginRow != rowRect.y) {
|
|
|
|
rowFrame->InvalidateFrameSubtree();
|
|
|
|
}
|
|
|
|
|
2001-11-05 03:15:51 +03:00
|
|
|
// update the row height
|
2008-02-08 12:36:32 +03:00
|
|
|
nsRect newRowRect(rowRect.x, yOriginRow, rowRect.width,
|
|
|
|
rowRect.height + amountForRow);
|
2003-07-07 06:01:29 +04:00
|
|
|
rowFrame->SetRect(newRowRect);
|
2008-02-08 12:36:32 +03:00
|
|
|
|
2001-11-05 03:15:51 +03:00
|
|
|
yOriginRow += newRowRect.height + cellSpacingY;
|
|
|
|
yEndRG += newRowRect.height + cellSpacingY;
|
|
|
|
|
|
|
|
amountUsed += amountForRow;
|
|
|
|
amountUsedByRG += amountForRow;
|
|
|
|
NS_ASSERTION((amountUsed <= aAmount), "invalid row allocation");
|
2010-04-27 20:15:01 +04:00
|
|
|
//rowFrame->DidResize();
|
2004-12-27 18:05:18 +03:00
|
|
|
nsTableFrame::RePositionViews(rowFrame);
|
2012-08-29 09:48:45 +04:00
|
|
|
|
|
|
|
nsTableFrame::InvalidateTableFrame(rowFrame, rowRect, rowVisualOverflow,
|
|
|
|
false);
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
|
|
|
else {
|
2008-02-08 12:36:32 +03:00
|
|
|
if (amountUsed > 0 && yOriginRow != rowRect.y) {
|
2012-08-29 09:48:45 +04:00
|
|
|
rowFrame->InvalidateFrameSubtree();
|
2003-07-07 06:01:29 +04:00
|
|
|
rowFrame->SetPosition(nsPoint(rowRect.x, yOriginRow));
|
2004-12-27 18:05:18 +03:00
|
|
|
nsTableFrame::RePositionViews(rowFrame);
|
2012-08-29 09:48:45 +04:00
|
|
|
rowFrame->InvalidateFrameSubtree();
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
|
|
|
yOriginRow += rowRect.height + cellSpacingY;
|
|
|
|
yEndRG += rowRect.height + cellSpacingY;
|
2004-03-09 09:48:35 +03:00
|
|
|
}
|
2001-11-05 03:15:51 +03:00
|
|
|
rowFrame = rowFrame->GetNextRow();
|
|
|
|
}
|
|
|
|
if (amountUsed > 0) {
|
2012-08-29 09:48:45 +04:00
|
|
|
if (rgRect.y != yOriginRG) {
|
|
|
|
rgFrame->InvalidateFrameSubtree();
|
|
|
|
}
|
|
|
|
|
2008-02-08 12:36:32 +03:00
|
|
|
rgFrame->SetRect(nsRect(rgRect.x, yOriginRG, rgRect.width,
|
|
|
|
rgRect.height + amountUsedByRG));
|
2012-08-29 09:48:45 +04:00
|
|
|
|
|
|
|
nsTableFrame::InvalidateTableFrame(rgFrame, rgRect, rgVisualOverflow,
|
|
|
|
false);
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
|
|
|
// Make sure child views are properly positioned
|
|
|
|
}
|
2008-08-07 00:53:36 +04:00
|
|
|
else if (amountUsed > 0 && yOriginRG != rgRect.y) {
|
2012-08-29 09:48:45 +04:00
|
|
|
rgFrame->InvalidateFrameSubtree();
|
2008-08-07 00:53:36 +04:00
|
|
|
rgFrame->SetPosition(nsPoint(rgRect.x, yOriginRG));
|
2001-11-05 03:15:51 +03:00
|
|
|
// Make sure child views are properly positioned
|
2004-12-27 18:05:18 +03:00
|
|
|
nsTableFrame::RePositionViews(rgFrame);
|
2012-08-29 09:48:45 +04:00
|
|
|
rgFrame->InvalidateFrameSubtree();
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
|
|
|
yOriginRG = yEndRG;
|
|
|
|
}
|
|
|
|
|
2007-01-28 01:22:24 +03:00
|
|
|
ResizeCells(*this);
|
1998-11-20 04:01:25 +03:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nsTableFrame::GetColumnWidth(int32_t aColIndex)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2012-01-17 03:38:10 +04:00
|
|
|
nsTableFrame* firstInFlow = static_cast<nsTableFrame*>(GetFirstInFlow());
|
2001-03-13 09:38:59 +03:00
|
|
|
if (this == firstInFlow) {
|
|
|
|
nsTableColFrame* colFrame = GetColFrame(aColIndex);
|
2012-01-17 03:38:10 +04:00
|
|
|
return colFrame ? colFrame->GetFinalWidth() : 0;
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
2012-01-17 03:38:10 +04:00
|
|
|
return firstInFlow->GetColumnWidth(aColIndex);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
1998-12-05 08:27:21 +03:00
|
|
|
// XXX: could cache this. But be sure to check style changes if you do!
|
1998-12-09 09:37:18 +03:00
|
|
|
nscoord nsTableFrame::GetCellSpacingX()
|
1998-07-17 03:23:31 +04:00
|
|
|
{
|
2004-11-30 21:30:58 +03:00
|
|
|
if (IsBorderCollapse())
|
|
|
|
return 0;
|
|
|
|
|
2008-09-13 07:45:37 +04:00
|
|
|
return GetStyleTableBorder()->mBorderSpacingX;
|
1998-12-09 09:37:18 +03:00
|
|
|
}
|
|
|
|
|
1999-05-18 09:18:16 +04:00
|
|
|
// XXX: could cache this. But be sure to check style changes if you do!
|
1998-12-09 09:37:18 +03:00
|
|
|
nscoord nsTableFrame::GetCellSpacingY()
|
|
|
|
{
|
2004-11-30 21:30:58 +03:00
|
|
|
if (IsBorderCollapse())
|
|
|
|
return 0;
|
|
|
|
|
2008-09-13 07:45:37 +04:00
|
|
|
return GetStyleTableBorder()->mBorderSpacingY;
|
1998-07-17 03:23:31 +04:00
|
|
|
}
|
|
|
|
|
2005-10-04 19:47:21 +04:00
|
|
|
|
2007-01-23 07:06:56 +03:00
|
|
|
/* virtual */ nscoord
|
|
|
|
nsTableFrame::GetBaseline() const
|
2005-10-04 19:47:21 +04:00
|
|
|
{
|
|
|
|
nscoord ascent = 0;
|
2007-06-05 22:55:26 +04:00
|
|
|
RowGroupArray orderedRowGroups;
|
|
|
|
OrderRowGroups(orderedRowGroups);
|
2012-07-30 18:20:58 +04:00
|
|
|
nsTableRowFrame* firstRow = nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t rgIndex = 0; rgIndex < orderedRowGroups.Length(); rgIndex++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableRowGroupFrame* rgFrame = orderedRowGroups[rgIndex];
|
2005-10-04 19:47:21 +04:00
|
|
|
if (rgFrame->GetRowCount()) {
|
2010-04-27 20:15:01 +04:00
|
|
|
firstRow = rgFrame->GetFirstRow();
|
2007-01-23 07:06:56 +03:00
|
|
|
ascent = rgFrame->GetRect().y + firstRow->GetRect().y + firstRow->GetRowBaseline();
|
2005-10-04 19:47:21 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!firstRow)
|
|
|
|
ascent = GetRect().height;
|
|
|
|
return ascent;
|
|
|
|
}
|
1998-09-15 21:58:24 +04:00
|
|
|
/* ----- global methods ----- */
|
1998-04-14 00:24:54 +04:00
|
|
|
|
2005-11-04 05:38:33 +03:00
|
|
|
nsIFrame*
|
2006-03-27 01:30:36 +04:00
|
|
|
NS_NewTableFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
1998-04-14 00:24:54 +04:00
|
|
|
{
|
2006-03-27 01:30:36 +04:00
|
|
|
return new (aPresShell) nsTableFrame(aContext);
|
1998-04-14 00:24:54 +04:00
|
|
|
}
|
|
|
|
|
2009-09-12 20:49:24 +04:00
|
|
|
NS_IMPL_FRAMEARENA_HELPERS(nsTableFrame)
|
|
|
|
|
2006-03-04 08:26:57 +03:00
|
|
|
nsTableFrame*
|
2012-01-17 03:38:10 +04:00
|
|
|
nsTableFrame::GetTableFrame(nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
for (nsIFrame* ancestor = aFrame->GetParent(); ancestor;
|
|
|
|
ancestor = ancestor->GetParent()) {
|
|
|
|
if (nsGkAtoms::tableFrame == ancestor->GetType()) {
|
|
|
|
return static_cast<nsTableFrame*>(ancestor);
|
1998-09-24 20:37:22 +04:00
|
|
|
}
|
|
|
|
}
|
2012-01-17 03:38:10 +04:00
|
|
|
NS_RUNTIMEABORT("unable to find table parent");
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
1998-09-24 20:37:22 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2001-05-14 18:28:00 +04:00
|
|
|
nsTableFrame::IsAutoHeight()
|
|
|
|
{
|
2010-08-25 14:17:55 +04:00
|
|
|
const nsStyleCoord &height = GetStylePosition()->mHeight;
|
|
|
|
// Don't consider calc() here like this quirk for percent.
|
|
|
|
return height.GetUnit() == eStyleUnit_Auto ||
|
|
|
|
(height.GetUnit() == eStyleUnit_Percent &&
|
|
|
|
height.GetPercentValue() <= 0.0f);
|
2001-05-14 18:28:00 +04:00
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
nscoord
|
2003-12-28 20:02:40 +03:00
|
|
|
nsTableFrame::CalcBorderBoxHeight(const nsHTMLReflowState& aState)
|
2000-01-03 01:55:48 +03:00
|
|
|
{
|
2007-08-02 22:08:05 +04:00
|
|
|
nscoord height = aState.ComputedHeight();
|
2000-04-29 01:05:31 +04:00
|
|
|
if (NS_AUTOHEIGHT != height) {
|
2009-02-08 19:46:42 +03:00
|
|
|
nsMargin borderPadding = GetChildAreaOffset(&aState);
|
2000-01-03 01:55:48 +03:00
|
|
|
height += borderPadding.top + borderPadding.bottom;
|
|
|
|
}
|
2009-09-16 19:01:36 +04:00
|
|
|
height = NS_MAX(0, height);
|
2000-01-03 01:55:48 +03:00
|
|
|
|
|
|
|
return height;
|
|
|
|
}
|
1999-08-28 01:15:21 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2000-11-15 17:59:47 +03:00
|
|
|
nsTableFrame::IsAutoLayout()
|
1998-10-21 00:05:44 +04:00
|
|
|
{
|
2007-05-04 03:11:00 +04:00
|
|
|
if (GetStyleTable()->mLayoutStrategy == NS_STYLE_TABLE_LAYOUT_AUTO)
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
// a fixed-layout inline-table must have a width
|
2007-11-15 21:10:31 +03:00
|
|
|
// and tables with 'width: -moz-max-content' must be auto-layout
|
2007-05-04 03:11:00 +04:00
|
|
|
// (at least as long as FixedTableLayoutStrategy::GetPrefWidth returns
|
|
|
|
// nscoord_MAX)
|
|
|
|
const nsStyleCoord &width = GetStylePosition()->mWidth;
|
2007-10-22 08:40:02 +04:00
|
|
|
return (width.GetUnit() == eStyleUnit_Auto) ||
|
2007-05-04 03:11:00 +04:00
|
|
|
(width.GetUnit() == eStyleUnit_Enumerated &&
|
2007-11-15 21:10:31 +03:00
|
|
|
width.GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT);
|
1998-10-21 00:05:44 +04:00
|
|
|
}
|
|
|
|
|
1999-11-02 01:12:45 +03:00
|
|
|
#ifdef DEBUG
|
1998-11-19 20:22:29 +03:00
|
|
|
NS_IMETHODIMP
|
2001-11-14 04:33:42 +03:00
|
|
|
nsTableFrame::GetFrameName(nsAString& aResult) const
|
1998-11-19 20:22:29 +03:00
|
|
|
{
|
2001-11-14 04:33:42 +03:00
|
|
|
return MakeFrameName(NS_LITERAL_STRING("Table"), aResult);
|
1998-11-19 20:22:29 +03:00
|
|
|
}
|
1999-11-02 01:12:45 +03:00
|
|
|
#endif
|
1999-01-18 02:35:56 +03:00
|
|
|
|
1999-12-14 01:56:31 +03:00
|
|
|
// Find the closet sibling before aPriorChildFrame (including aPriorChildFrame) that
|
|
|
|
// is of type aChildType
|
2010-04-27 20:15:01 +04:00
|
|
|
nsIFrame*
|
2004-01-18 13:28:40 +03:00
|
|
|
nsTableFrame::GetFrameAtOrBefore(nsIFrame* aParentFrame,
|
2000-01-22 04:16:50 +03:00
|
|
|
nsIFrame* aPriorChildFrame,
|
|
|
|
nsIAtom* aChildType)
|
1999-07-28 12:09:02 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame* result = nullptr;
|
1999-12-14 01:56:31 +03:00
|
|
|
if (!aPriorChildFrame) {
|
|
|
|
return result;
|
|
|
|
}
|
2003-10-31 23:19:18 +03:00
|
|
|
if (aChildType == aPriorChildFrame->GetType()) {
|
2004-05-02 13:51:57 +04:00
|
|
|
return aPriorChildFrame;
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
// aPriorChildFrame is not of type aChildType, so we need start from
|
|
|
|
// the beginnng and find the closest one
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame* lastMatchingFrame = nullptr;
|
2011-08-25 00:54:30 +04:00
|
|
|
nsIFrame* childFrame = aParentFrame->GetFirstPrincipalChild();
|
2001-03-13 09:38:59 +03:00
|
|
|
while (childFrame && (childFrame != aPriorChildFrame)) {
|
2003-10-31 23:19:18 +03:00
|
|
|
if (aChildType == childFrame->GetType()) {
|
1999-12-14 01:56:31 +03:00
|
|
|
lastMatchingFrame = childFrame;
|
|
|
|
}
|
2003-07-07 06:01:29 +04:00
|
|
|
childFrame = childFrame->GetNextSibling();
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
2004-05-02 13:51:57 +04:00
|
|
|
return lastMatchingFrame;
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
|
2002-03-06 18:56:32 +03:00
|
|
|
#ifdef DEBUG
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2004-01-18 13:28:40 +03:00
|
|
|
nsTableFrame::DumpRowGroup(nsIFrame* aKidFrame)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2010-01-16 19:05:46 +03:00
|
|
|
if (!aKidFrame)
|
|
|
|
return;
|
|
|
|
|
2011-08-25 00:54:30 +04:00
|
|
|
nsIFrame* cFrame = aKidFrame->GetFirstPrincipalChild();
|
2010-01-16 19:05:46 +03:00
|
|
|
while (cFrame) {
|
|
|
|
nsTableRowFrame *rowFrame = do_QueryFrame(cFrame);
|
|
|
|
if (rowFrame) {
|
2010-01-18 02:11:06 +03:00
|
|
|
printf("row(%d)=%p ", rowFrame->GetRowIndex(),
|
|
|
|
static_cast<void*>(rowFrame));
|
2011-08-25 00:54:30 +04:00
|
|
|
nsIFrame* childFrame = cFrame->GetFirstPrincipalChild();
|
2010-01-16 19:05:46 +03:00
|
|
|
while (childFrame) {
|
|
|
|
nsTableCellFrame *cellFrame = do_QueryFrame(childFrame);
|
|
|
|
if (cellFrame) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colIndex;
|
2010-01-16 19:05:46 +03:00
|
|
|
cellFrame->GetColIndex(colIndex);
|
2010-02-02 23:06:58 +03:00
|
|
|
printf("cell(%d)=%p ", colIndex, static_cast<void*>(childFrame));
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
2010-01-16 19:05:46 +03:00
|
|
|
childFrame = childFrame->GetNextSibling();
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
2010-01-16 19:05:46 +03:00
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DumpRowGroup(rowFrame);
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
2010-01-16 19:05:46 +03:00
|
|
|
cFrame = cFrame->GetNextSibling();
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2011-09-29 10:19:26 +04:00
|
|
|
nsTableFrame::Dump(bool aDumpRows,
|
|
|
|
bool aDumpCols,
|
|
|
|
bool aDumpCellMap)
|
1999-12-14 01:56:31 +03:00
|
|
|
{
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("***START TABLE DUMP*** \n");
|
1999-12-14 01:56:31 +03:00
|
|
|
// dump the columns widths array
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("mColWidths=");
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numCols = GetColCount();
|
|
|
|
int32_t colX;
|
1999-07-28 12:09:02 +04:00
|
|
|
for (colX = 0; colX < numCols; colX++) {
|
2001-03-13 09:38:59 +03:00
|
|
|
printf("%d ", GetColumnWidth(colX));
|
1999-07-28 12:09:02 +04:00
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("\n");
|
1999-12-14 01:56:31 +03:00
|
|
|
|
|
|
|
if (aDumpRows) {
|
|
|
|
nsIFrame* kidFrame = mFrames.FirstChild();
|
|
|
|
while (kidFrame) {
|
2004-01-18 13:28:40 +03:00
|
|
|
DumpRowGroup(kidFrame);
|
2003-07-07 06:01:29 +04:00
|
|
|
kidFrame = kidFrame->GetNextSibling();
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-07-28 12:09:02 +04:00
|
|
|
if (aDumpCols) {
|
1999-12-14 01:56:31 +03:00
|
|
|
// output col frame cache
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("\n col frame cache ->");
|
2004-09-04 20:02:50 +04:00
|
|
|
for (colX = 0; colX < numCols; colX++) {
|
2009-02-05 12:09:50 +03:00
|
|
|
nsTableColFrame* colFrame = mColFrames.ElementAt(colX);
|
1999-12-14 01:56:31 +03:00
|
|
|
if (0 == (colX % 8)) {
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("\n");
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
2010-01-18 02:11:06 +03:00
|
|
|
printf ("%d=%p ", colX, static_cast<void*>(colFrame));
|
2004-09-04 20:02:50 +04:00
|
|
|
nsTableColType colType = colFrame->GetColType();
|
|
|
|
switch (colType) {
|
|
|
|
case eColContent:
|
|
|
|
printf(" content ");
|
|
|
|
break;
|
2010-04-27 20:15:01 +04:00
|
|
|
case eColAnonymousCol:
|
2004-09-04 20:02:50 +04:00
|
|
|
printf(" anonymous-column ");
|
|
|
|
break;
|
|
|
|
case eColAnonymousColGroup:
|
|
|
|
printf(" anonymous-colgroup ");
|
|
|
|
break;
|
2010-04-27 20:15:01 +04:00
|
|
|
case eColAnonymousCell:
|
2004-09-04 20:02:50 +04:00
|
|
|
printf(" anonymous-cell ");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
printf("\n colgroups->");
|
|
|
|
for (nsIFrame* childFrame = mColGroups.FirstChild(); childFrame;
|
|
|
|
childFrame = childFrame->GetNextSibling()) {
|
2006-12-26 20:47:52 +03:00
|
|
|
if (nsGkAtoms::tableColGroupFrame == childFrame->GetType()) {
|
2004-09-04 20:02:50 +04:00
|
|
|
nsTableColGroupFrame* colGroupFrame = (nsTableColGroupFrame *)childFrame;
|
|
|
|
colGroupFrame->Dump(1);
|
|
|
|
}
|
1999-12-14 01:56:31 +03:00
|
|
|
}
|
1999-07-28 12:09:02 +04:00
|
|
|
for (colX = 0; colX < numCols; colX++) {
|
2000-10-29 02:17:53 +04:00
|
|
|
printf("\n");
|
1999-07-28 12:09:02 +04:00
|
|
|
nsTableColFrame* colFrame = GetColFrame(colX);
|
|
|
|
colFrame->Dump(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (aDumpCellMap) {
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-07-28 12:09:02 +04:00
|
|
|
cellMap->Dump();
|
|
|
|
}
|
2000-10-29 02:17:53 +04:00
|
|
|
printf(" ***END TABLE DUMP*** \n");
|
1999-07-28 12:09:02 +04:00
|
|
|
}
|
2002-03-06 18:56:32 +03:00
|
|
|
#endif
|
1999-07-28 12:09:02 +04:00
|
|
|
|
1999-04-22 07:51:58 +04:00
|
|
|
// nsTableIterator
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
nsTableIterator::nsTableIterator(nsIFrame& aSource)
|
1999-04-22 07:51:58 +04:00
|
|
|
{
|
2011-08-25 00:54:30 +04:00
|
|
|
nsIFrame* firstChild = aSource.GetFirstPrincipalChild();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
Init(firstChild);
|
1999-04-22 07:51:58 +04:00
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
nsTableIterator::nsTableIterator(nsFrameList& aSource)
|
1999-04-22 07:51:58 +04:00
|
|
|
{
|
|
|
|
nsIFrame* firstChild = aSource.FirstChild();
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
Init(firstChild);
|
1999-04-22 07:51:58 +04:00
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
void nsTableIterator::Init(nsIFrame* aFirstChild)
|
1999-04-22 07:51:58 +04:00
|
|
|
{
|
|
|
|
mFirstListChild = aFirstChild;
|
|
|
|
mFirstChild = aFirstChild;
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentChild = nullptr;
|
2011-10-17 18:59:28 +04:00
|
|
|
mLeftToRight = true;
|
1999-04-22 07:51:58 +04:00
|
|
|
mCount = -1;
|
|
|
|
|
|
|
|
if (!mFirstChild) {
|
|
|
|
return;
|
|
|
|
}
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
|
|
|
nsTableFrame* table = nsTableFrame::GetTableFrame(mFirstChild);
|
2012-01-17 03:38:10 +04:00
|
|
|
mLeftToRight = (NS_STYLE_DIRECTION_LTR ==
|
|
|
|
table->GetStyleVisibility()->mDirection);
|
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.
2006-12-08 08:38:33 +03:00
|
|
|
|
1999-04-22 07:51:58 +04:00
|
|
|
if (!mLeftToRight) {
|
|
|
|
mCount = 0;
|
2003-07-07 06:01:29 +04:00
|
|
|
nsIFrame* nextChild = mFirstChild->GetNextSibling();
|
2012-07-30 18:20:58 +04:00
|
|
|
while (nullptr != nextChild) {
|
1999-04-22 07:51:58 +04:00
|
|
|
mCount++;
|
|
|
|
mFirstChild = nextChild;
|
2003-07-07 06:01:29 +04:00
|
|
|
nextChild = nextChild->GetNextSibling();
|
1999-04-22 07:51:58 +04:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
}
|
1999-04-22 07:51:58 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsIFrame* nsTableIterator::First()
|
|
|
|
{
|
|
|
|
mCurrentChild = mFirstChild;
|
|
|
|
return mCurrentChild;
|
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
1999-04-22 07:51:58 +04:00
|
|
|
nsIFrame* nsTableIterator::Next()
|
|
|
|
{
|
|
|
|
if (!mCurrentChild) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
1999-04-22 07:51:58 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mLeftToRight) {
|
2003-07-07 06:01:29 +04:00
|
|
|
mCurrentChild = mCurrentChild->GetNextSibling();
|
1999-04-22 07:51:58 +04:00
|
|
|
return mCurrentChild;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nsIFrame* targetChild = mCurrentChild;
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentChild = nullptr;
|
1999-04-22 07:51:58 +04:00
|
|
|
nsIFrame* child = mFirstListChild;
|
|
|
|
while (child && (child != targetChild)) {
|
|
|
|
mCurrentChild = child;
|
2003-07-07 06:01:29 +04:00
|
|
|
child = child->GetNextSibling();
|
1999-04-22 07:51:58 +04:00
|
|
|
}
|
|
|
|
return mCurrentChild;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool nsTableIterator::IsLeftToRight()
|
1999-04-22 07:51:58 +04:00
|
|
|
{
|
|
|
|
return mLeftToRight;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nsTableIterator::Count()
|
1999-04-22 07:51:58 +04:00
|
|
|
{
|
|
|
|
if (-1 == mCount) {
|
|
|
|
mCount = 0;
|
|
|
|
nsIFrame* child = mFirstListChild;
|
2012-07-30 18:20:58 +04:00
|
|
|
while (nullptr != child) {
|
1999-04-22 07:51:58 +04:00
|
|
|
mCount++;
|
2003-07-07 06:01:29 +04:00
|
|
|
child = child->GetNextSibling();
|
1999-04-22 07:51:58 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return mCount;
|
|
|
|
}
|
|
|
|
|
1999-08-01 20:20:14 +04:00
|
|
|
/*------------------ nsITableLayout methods ------------------------------*/
|
2010-04-27 20:15:01 +04:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsTableFrame::GetCellDataAt(int32_t aRowIndex,
|
|
|
|
int32_t aColIndex,
|
1999-08-01 02:11:50 +04:00
|
|
|
nsIDOMElement* &aCell, //out params
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t& aStartRowIndex,
|
|
|
|
int32_t& aStartColIndex,
|
|
|
|
int32_t& aRowSpan,
|
|
|
|
int32_t& aColSpan,
|
|
|
|
int32_t& aActualRowSpan,
|
|
|
|
int32_t& aActualColSpan,
|
2011-12-20 13:15:41 +04:00
|
|
|
bool& aIsSelected)
|
1999-08-01 02:11:50 +04:00
|
|
|
{
|
|
|
|
// Initialize out params
|
2012-07-30 18:20:58 +04:00
|
|
|
aCell = nullptr;
|
1999-08-01 02:11:50 +04:00
|
|
|
aStartRowIndex = 0;
|
|
|
|
aStartColIndex = 0;
|
|
|
|
aRowSpan = 0;
|
|
|
|
aColSpan = 0;
|
2011-10-17 18:59:28 +04:00
|
|
|
aIsSelected = false;
|
1999-08-01 02:11:50 +04:00
|
|
|
|
2000-03-23 07:24:58 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-08-01 02:11:50 +04:00
|
|
|
if (!cellMap) { return NS_ERROR_NOT_INITIALIZED;}
|
1999-08-01 03:05:11 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool originates;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colSpan; // Is this the "effective" or "html" value?
|
1999-08-01 09:19:47 +04:00
|
|
|
|
2000-03-23 07:24:58 +03:00
|
|
|
nsTableCellFrame *cellFrame = cellMap->GetCellInfoAt(aRowIndex, aColIndex, &originates, &colSpan);
|
|
|
|
if (!cellFrame) return NS_TABLELAYOUT_CELL_NOT_FOUND;
|
1999-08-01 02:11:50 +04:00
|
|
|
|
2000-03-23 07:24:58 +03:00
|
|
|
nsresult result= cellFrame->GetRowIndex(aStartRowIndex);
|
1999-08-01 02:11:50 +04:00
|
|
|
if (NS_FAILED(result)) return result;
|
|
|
|
result = cellFrame->GetColIndex(aStartColIndex);
|
|
|
|
if (NS_FAILED(result)) return result;
|
2000-01-26 17:56:06 +03:00
|
|
|
//This returns HTML value, which may be 0
|
|
|
|
aRowSpan = cellFrame->GetRowSpan();
|
|
|
|
aColSpan = cellFrame->GetColSpan();
|
2000-02-01 06:23:29 +03:00
|
|
|
aActualRowSpan = GetEffectiveRowSpan(*cellFrame);
|
|
|
|
aActualColSpan = GetEffectiveColSpan(*cellFrame);
|
2001-05-17 16:40:27 +04:00
|
|
|
|
|
|
|
// If these aren't at least 1, we have a cellmap error
|
|
|
|
if (aActualRowSpan == 0 || aActualColSpan == 0)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
2011-12-20 13:15:41 +04:00
|
|
|
aIsSelected = cellFrame->IsSelected();
|
1999-08-01 02:11:50 +04:00
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
// do this last, because it addrefs,
|
1999-08-01 02:11:50 +04:00
|
|
|
// and we don't want the caller leaking it on error
|
2003-07-07 06:01:29 +04:00
|
|
|
nsIContent* content = cellFrame->GetContent();
|
2010-04-27 20:15:01 +04:00
|
|
|
if (!content) return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
return CallQueryInterface(content, &aCell);
|
1999-08-01 02:11:50 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
NS_IMETHODIMP nsTableFrame::GetTableSize(int32_t& aRowCount, int32_t& aColCount)
|
1999-08-01 20:20:14 +04:00
|
|
|
{
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-08-01 20:20:14 +04:00
|
|
|
// Initialize out params
|
|
|
|
aRowCount = 0;
|
|
|
|
aColCount = 0;
|
|
|
|
if (!cellMap) { return NS_ERROR_NOT_INITIALIZED;}
|
|
|
|
|
|
|
|
aRowCount = cellMap->GetRowCount();
|
|
|
|
aColCount = cellMap->GetColCount();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-02-07 10:03:26 +03:00
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsTableFrame::GetIndexByRowAndColumn(int32_t aRow, int32_t aColumn,
|
|
|
|
int32_t *aIndex)
|
2008-02-07 10:03:26 +03:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aIndex);
|
|
|
|
*aIndex = -1;
|
|
|
|
|
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
|
|
|
if (!cellMap)
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
*aIndex = cellMap->GetIndexByRowAndColumn(aRow, aColumn);
|
2009-06-29 14:54:26 +04:00
|
|
|
return (*aIndex == -1) ? NS_TABLELAYOUT_CELL_NOT_FOUND : NS_OK;
|
2008-02-07 10:03:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2012-08-22 19:56:38 +04:00
|
|
|
nsTableFrame::GetRowAndColumnByIndex(int32_t aIndex,
|
|
|
|
int32_t *aRow, int32_t *aColumn)
|
2008-02-07 10:03:26 +03:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aRow);
|
|
|
|
*aRow = -1;
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(aColumn);
|
|
|
|
*aColumn = -1;
|
|
|
|
|
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
|
|
|
if (!cellMap)
|
|
|
|
return NS_ERROR_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
cellMap->GetRowAndColumnByIndex(aIndex, aRow, aColumn);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
1999-08-01 20:20:14 +04:00
|
|
|
/*---------------- end of nsITableLayout implementation ------------------*/
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2012-08-22 19:56:38 +04:00
|
|
|
nsTableFrame::ColumnHasCellSpacingBefore(int32_t aColIndex) const
|
2001-11-05 03:15:51 +03:00
|
|
|
{
|
2008-09-24 21:14:35 +04:00
|
|
|
// Since fixed-layout tables should not have their column sizes change
|
|
|
|
// as they load, we assume that all columns are significant.
|
|
|
|
if (LayoutStrategy()->GetType() == nsITableLayoutStrategy::Fixed)
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2009-04-18 12:22:34 +04:00
|
|
|
// the first column is always significant
|
|
|
|
if (aColIndex == 0)
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2001-11-05 03:15:51 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
2010-04-27 20:15:01 +04:00
|
|
|
if (!cellMap)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2008-09-24 21:14:35 +04:00
|
|
|
return cellMap->GetNumCellsOriginatingInCol(aColIndex) > 0;
|
2001-11-05 03:15:51 +03:00
|
|
|
}
|
2001-03-13 09:38:59 +03:00
|
|
|
|
|
|
|
/********************************************************************************
|
2002-02-19 18:48:28 +03:00
|
|
|
* Collapsing Borders
|
|
|
|
*
|
|
|
|
* The CSS spec says to resolve border conflicts in this order:
|
|
|
|
* 1) any border with the style HIDDEN wins
|
|
|
|
* 2) the widest border with a style that is not NONE wins
|
2010-04-27 20:15:01 +04:00
|
|
|
* 3) the border styles are ranked in this order, highest to lowest precedence:
|
2002-02-19 18:48:28 +03:00
|
|
|
* double, solid, dashed, dotted, ridge, outset, groove, inset
|
|
|
|
* 4) borders that are of equal width and style (differ only in color) have this precedence:
|
|
|
|
* cell, row, rowgroup, col, colgroup, table
|
|
|
|
* 5) if all border styles are NONE, then that's the computed border style.
|
|
|
|
*******************************************************************************/
|
2001-01-25 18:55:51 +03:00
|
|
|
|
2011-10-27 17:58:44 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
#define VerifyNonNegativeDamageRect(r) \
|
|
|
|
NS_ASSERTION((r).x >= 0, "negative col index"); \
|
|
|
|
NS_ASSERTION((r).y >= 0, "negative row index"); \
|
|
|
|
NS_ASSERTION((r).width >= 0, "negative horizontal damage"); \
|
|
|
|
NS_ASSERTION((r).height >= 0, "negative vertical damage");
|
|
|
|
#define VerifyDamageRect(r) \
|
|
|
|
VerifyNonNegativeDamageRect(r); \
|
|
|
|
NS_ASSERTION((r).XMost() <= GetColCount(), \
|
|
|
|
"horizontal damage extends outside table"); \
|
|
|
|
NS_ASSERTION((r).YMost() <= GetRowCount(), \
|
|
|
|
"vertical damage extends outside table");
|
|
|
|
#endif
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2012-01-23 02:48:34 +04:00
|
|
|
nsTableFrame::AddBCDamageArea(const nsIntRect& aValue)
|
2001-01-25 18:55:51 +03:00
|
|
|
{
|
2011-10-27 17:58:44 +04:00
|
|
|
NS_ASSERTION(IsBorderCollapse(), "invalid AddBCDamageArea call");
|
|
|
|
#ifdef DEBUG
|
|
|
|
VerifyDamageRect(aValue);
|
|
|
|
#endif
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
SetNeedToCalcBCBorders(true);
|
2010-03-29 05:46:55 +04:00
|
|
|
// Get the property
|
2011-10-27 17:58:44 +04:00
|
|
|
BCPropertyData* value = GetBCProperty(true);
|
|
|
|
if (value) {
|
|
|
|
#ifdef DEBUG
|
|
|
|
VerifyNonNegativeDamageRect(value->mDamageArea);
|
|
|
|
#endif
|
|
|
|
// Clamp the old damage area to the current table area in case it shrunk.
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t cols = GetColCount();
|
2011-10-27 17:58:44 +04:00
|
|
|
if (value->mDamageArea.XMost() > cols) {
|
|
|
|
if (value->mDamageArea.x > cols) {
|
|
|
|
value->mDamageArea.x = cols;
|
|
|
|
value->mDamageArea.width = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
value->mDamageArea.width = cols - value->mDamageArea.x;
|
|
|
|
}
|
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rows = GetRowCount();
|
2011-10-27 17:58:44 +04:00
|
|
|
if (value->mDamageArea.YMost() > rows) {
|
|
|
|
if (value->mDamageArea.y > rows) {
|
|
|
|
value->mDamageArea.y = rows;
|
|
|
|
value->mDamageArea.height = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
value->mDamageArea.height = rows - value->mDamageArea.y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Construct a union of the new and old damage areas.
|
|
|
|
value->mDamageArea.UnionRect(value->mDamageArea, aValue);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
|
2011-10-27 17:58:44 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
nsTableFrame::SetFullBCDamageArea()
|
|
|
|
{
|
|
|
|
NS_ASSERTION(IsBorderCollapse(), "invalid SetFullBCDamageArea call");
|
|
|
|
|
|
|
|
SetNeedToCalcBCBorders(true);
|
|
|
|
|
|
|
|
BCPropertyData* value = GetBCProperty(true);
|
|
|
|
if (value) {
|
2012-01-23 02:48:34 +04:00
|
|
|
value->mDamageArea = nsIntRect(0, 0, GetColCount(), GetRowCount());
|
2011-10-27 17:58:44 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
/* BCCellBorder represents a border segment which can be either a horizontal
|
|
|
|
* or a vertical segment. For each segment we need to know the color, width,
|
|
|
|
* style, who owns it and how long it is in cellmap coordinates.
|
|
|
|
* Ownership of these segments is important to calculate which corners should
|
|
|
|
* be bevelled. This structure has dual use, its used first to compute the
|
|
|
|
* dominant border for horizontal and vertical segments and to store the
|
|
|
|
* preliminary computed border results in the BCCellBorders structure.
|
|
|
|
* This temporary storage is not symmetric with respect to horizontal and
|
|
|
|
* vertical border segments, its always column oriented. For each column in
|
|
|
|
* the cellmap there is a temporary stored vertical and horizontal segment.
|
|
|
|
* XXX_Bernd this asymmetry is the root of those rowspan bc border errors
|
|
|
|
*/
|
|
|
|
struct BCCellBorder
|
|
|
|
{
|
|
|
|
BCCellBorder() { Reset(0, 1); }
|
2012-08-22 19:56:38 +04:00
|
|
|
void Reset(uint32_t aRowIndex, uint32_t aRowSpan);
|
2009-06-21 20:31:40 +04:00
|
|
|
nscolor color; // border segment color
|
|
|
|
BCPixelSize width; // border segment width in pixel coordinates !!
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t style; // border segment style, possible values are defined
|
2009-06-21 20:31:40 +04:00
|
|
|
// in nsStyleConsts.h as NS_STYLE_BORDER_STYLE_*
|
|
|
|
BCBorderOwner owner; // border segment owner, possible values are defined
|
|
|
|
// in celldata.h. In the cellmap for each border
|
|
|
|
// segment we store the owner and later when
|
|
|
|
// painting we know the owner and can retrieve the
|
|
|
|
// style info from the corresponding frame
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rowIndex; // rowIndex of temporary stored horizontal border
|
2009-06-21 20:31:40 +04:00
|
|
|
// segments relative to the table
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rowSpan; // row span of temporary stored horizontal border
|
2009-06-21 20:31:40 +04:00
|
|
|
// segments
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
BCCellBorder::Reset(uint32_t aRowIndex,
|
|
|
|
uint32_t aRowSpan)
|
2009-06-21 20:31:40 +04:00
|
|
|
{
|
|
|
|
style = NS_STYLE_BORDER_STYLE_NONE;
|
|
|
|
color = 0;
|
|
|
|
width = 0;
|
|
|
|
owner = eTableOwner;
|
|
|
|
rowIndex = aRowIndex;
|
|
|
|
rowSpan = aRowSpan;
|
|
|
|
}
|
|
|
|
|
|
|
|
class BCMapCellIterator;
|
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
/*****************************************************************
|
2009-06-21 20:31:40 +04:00
|
|
|
* BCMapCellInfo
|
|
|
|
* This structure stores information about the cellmap and all involved
|
|
|
|
* table related frames that are used during the computation of winning borders
|
|
|
|
* in CalcBCBorders so that they do need to be looked up again and again when
|
|
|
|
* iterating over the cells.
|
2002-02-19 18:48:28 +03:00
|
|
|
****************************************************************/
|
2010-04-27 20:15:01 +04:00
|
|
|
struct BCMapCellInfo
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2009-06-21 20:31:40 +04:00
|
|
|
BCMapCellInfo(nsTableFrame* aTableFrame);
|
|
|
|
void ResetCellInfo();
|
|
|
|
void SetInfo(nsTableRowFrame* aNewRow,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aColIndex,
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCellData* aCellData,
|
|
|
|
BCMapCellIterator* aIter,
|
2012-07-30 18:20:58 +04:00
|
|
|
nsCellMap* aCellMap = nullptr);
|
2009-06-21 20:31:40 +04:00
|
|
|
// The BCMapCellInfo has functions to set the continous
|
|
|
|
// border widths (see nsTablePainter.cpp for a description of the continous
|
|
|
|
// borders concept). The widths are computed inside these functions based on
|
|
|
|
// the current position inside the table and the cached frames that correspond
|
|
|
|
// to this position. The widths are stored in member variables of the internal
|
|
|
|
// table frames.
|
|
|
|
void SetTableTopLeftContBCBorder();
|
|
|
|
void SetRowGroupLeftContBCBorder();
|
|
|
|
void SetRowGroupRightContBCBorder();
|
|
|
|
void SetRowGroupBottomContBCBorder();
|
|
|
|
void SetRowLeftContBCBorder();
|
|
|
|
void SetRowRightContBCBorder();
|
|
|
|
void SetColumnTopRightContBCBorder();
|
|
|
|
void SetColumnBottomContBCBorder();
|
|
|
|
void SetColGroupBottomContBCBorder();
|
|
|
|
void SetInnerRowGroupBottomContBCBorder(const nsIFrame* aNextRowGroup,
|
|
|
|
nsTableRowFrame* aNextRow);
|
|
|
|
|
|
|
|
// functions to set the border widths on the table related frames, where the
|
|
|
|
// knowledge about the current position in the table is used.
|
|
|
|
void SetTableTopBorderWidth(BCPixelSize aWidth);
|
2012-08-22 19:56:38 +04:00
|
|
|
void SetTableLeftBorderWidth(int32_t aRowY, BCPixelSize aWidth);
|
|
|
|
void SetTableRightBorderWidth(int32_t aRowY, BCPixelSize aWidth);
|
2009-06-21 20:31:40 +04:00
|
|
|
void SetTableBottomBorderWidth(BCPixelSize aWidth);
|
|
|
|
void SetLeftBorderWidths(BCPixelSize aWidth);
|
|
|
|
void SetRightBorderWidths(BCPixelSize aWidth);
|
|
|
|
void SetTopBorderWidths(BCPixelSize aWidth);
|
|
|
|
void SetBottomBorderWidths(BCPixelSize aWidth);
|
|
|
|
|
|
|
|
// functions to compute the borders; they depend on the
|
|
|
|
// knowledge about the current position in the table. The edge functions
|
|
|
|
// should be called if a table edge is involved, otherwise the internal
|
|
|
|
// functions should be called.
|
|
|
|
BCCellBorder GetTopEdgeBorder();
|
|
|
|
BCCellBorder GetBottomEdgeBorder();
|
|
|
|
BCCellBorder GetLeftEdgeBorder();
|
|
|
|
BCCellBorder GetRightEdgeBorder();
|
|
|
|
BCCellBorder GetRightInternalBorder();
|
|
|
|
BCCellBorder GetLeftInternalBorder();
|
|
|
|
BCCellBorder GetTopInternalBorder();
|
|
|
|
BCCellBorder GetBottomInternalBorder();
|
|
|
|
|
|
|
|
// functions to set the interal position information
|
2012-08-22 19:56:38 +04:00
|
|
|
void SetColumn(int32_t aColX);
|
2009-06-21 20:31:40 +04:00
|
|
|
// Increment the row as we loop over the rows of a rowspan
|
2011-09-29 10:19:26 +04:00
|
|
|
void IncrementRow(bool aResetToTopRowOfCell = false);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// Helper functions to get extent of the cell
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t GetCellEndRowIndex() const;
|
|
|
|
int32_t GetCellEndColIndex() const;
|
2009-06-21 20:31:40 +04:00
|
|
|
|
|
|
|
// storage of table information
|
|
|
|
nsTableFrame* mTableFrame;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mNumTableRows;
|
|
|
|
int32_t mNumTableCols;
|
2009-06-21 20:31:40 +04:00
|
|
|
BCPropertyData* mTableBCData;
|
|
|
|
|
|
|
|
// storage of table ltr information, the border collapse code swaps the sides
|
|
|
|
// to account for rtl tables, this is done through mStartSide and mEndSide
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mTableIsLTR;
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side mStartSide;
|
|
|
|
mozilla::css::Side mEndSide;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// a cell can only belong to one rowgroup
|
|
|
|
nsTableRowGroupFrame* mRowGroup;
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// a cell with a rowspan has a top and a bottom row, and rows in between
|
|
|
|
nsTableRowFrame* mTopRow;
|
|
|
|
nsTableRowFrame* mBottomRow;
|
|
|
|
nsTableRowFrame* mCurrentRowFrame;
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// a cell with a colspan has a left and right column and columns in between
|
|
|
|
// they can belong to different colgroups
|
|
|
|
nsTableColGroupFrame* mColGroup;
|
|
|
|
nsTableColGroupFrame* mCurrentColGroupFrame;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
nsTableColFrame* mLeftCol;
|
|
|
|
nsTableColFrame* mRightCol;
|
|
|
|
nsTableColFrame* mCurrentColFrame;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// cell information
|
|
|
|
BCCellData* mCellData;
|
|
|
|
nsBCTableCellFrame* mCell;
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mRowIndex;
|
|
|
|
int32_t mRowSpan;
|
|
|
|
int32_t mColIndex;
|
|
|
|
int32_t mColSpan;
|
2009-06-21 20:31:40 +04:00
|
|
|
|
|
|
|
// flags to describe the position of the cell with respect to the row- and
|
|
|
|
// colgroups, for instance mRgAtTop documents that the top cell border hits
|
|
|
|
// a rowgroup border
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mRgAtTop;
|
|
|
|
bool mRgAtBottom;
|
|
|
|
bool mCgAtLeft;
|
|
|
|
bool mCgAtRight;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
};
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
BCMapCellInfo::BCMapCellInfo(nsTableFrame* aTableFrame)
|
|
|
|
{
|
|
|
|
mTableFrame = aTableFrame;
|
|
|
|
mTableIsLTR =
|
|
|
|
aTableFrame->GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR;
|
|
|
|
if (mTableIsLTR) {
|
|
|
|
mStartSide = NS_SIDE_LEFT;
|
|
|
|
mEndSide = NS_SIDE_RIGHT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mStartSide = NS_SIDE_RIGHT;
|
|
|
|
mEndSide = NS_SIDE_LEFT;
|
|
|
|
}
|
|
|
|
mNumTableRows = mTableFrame->GetRowCount();
|
|
|
|
mNumTableCols = mTableFrame->GetColCount();
|
2010-03-29 05:46:55 +04:00
|
|
|
mTableBCData = static_cast<BCPropertyData*>
|
|
|
|
(mTableFrame->Properties().Get(TableBCProperty()));
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
ResetCellInfo();
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
void BCMapCellInfo::ResetCellInfo()
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
mCellData = nullptr;
|
|
|
|
mRowGroup = nullptr;
|
|
|
|
mTopRow = nullptr;
|
|
|
|
mBottomRow = nullptr;
|
|
|
|
mColGroup = nullptr;
|
|
|
|
mLeftCol = nullptr;
|
|
|
|
mRightCol = nullptr;
|
|
|
|
mCell = nullptr;
|
2009-06-21 20:31:40 +04:00
|
|
|
mRowIndex = mRowSpan = mColIndex = mColSpan = 0;
|
2011-10-17 18:59:28 +04:00
|
|
|
mRgAtTop = mRgAtBottom = mCgAtLeft = mCgAtRight = false;
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
inline int32_t BCMapCellInfo::GetCellEndRowIndex() const
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2009-06-21 20:31:40 +04:00
|
|
|
return mRowIndex + mRowSpan - 1;
|
2001-01-25 18:55:51 +03:00
|
|
|
}
|
2001-09-24 18:48:38 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
inline int32_t BCMapCellInfo::GetCellEndColIndex() const
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2009-06-21 20:31:40 +04:00
|
|
|
return mColIndex + mColSpan - 1;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2001-09-24 18:48:38 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
class BCMapCellIterator
|
|
|
|
{
|
|
|
|
public:
|
2009-06-21 20:31:40 +04:00
|
|
|
BCMapCellIterator(nsTableFrame* aTableFrame,
|
2012-01-23 02:48:34 +04:00
|
|
|
const nsIntRect& aDamageArea);
|
2001-09-24 18:48:38 +04:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
void First(BCMapCellInfo& aMapCellInfo);
|
|
|
|
|
|
|
|
void Next(BCMapCellInfo& aMapCellInfo);
|
|
|
|
|
|
|
|
void PeekRight(BCMapCellInfo& aRefInfo,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aRowIndex,
|
2002-02-19 18:48:28 +03:00
|
|
|
BCMapCellInfo& aAjaInfo);
|
|
|
|
|
|
|
|
void PeekBottom(BCMapCellInfo& aRefInfo,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aColIndex,
|
2002-02-19 18:48:28 +03:00
|
|
|
BCMapCellInfo& aAjaInfo);
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool IsNewRow() { return mIsNewRow; }
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
nsTableRowFrame* GetPrevRow() const { return mPrevRow; }
|
2009-06-21 20:31:40 +04:00
|
|
|
nsTableRowFrame* GetCurrentRow() const { return mRow; }
|
|
|
|
nsTableRowGroupFrame* GetCurrentRowGroup() const { return mRowGroup;}
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mRowGroupStart;
|
|
|
|
int32_t mRowGroupEnd;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mAtEnd;
|
2002-02-19 18:48:28 +03:00
|
|
|
nsCellMap* mCellMap;
|
|
|
|
|
|
|
|
private:
|
2012-07-30 18:20:58 +04:00
|
|
|
bool SetNewRow(nsTableRowFrame* row = nullptr);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool SetNewRowGroup(bool aFindFirstDamagedRow);
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
nsTableFrame* mTableFrame;
|
2002-02-19 18:48:28 +03:00
|
|
|
nsTableCellMap* mTableCellMap;
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableFrame::RowGroupArray mRowGroups;
|
2002-02-19 18:48:28 +03:00
|
|
|
nsTableRowGroupFrame* mRowGroup;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mRowGroupIndex;
|
|
|
|
uint32_t mNumTableRows;
|
2002-02-19 18:48:28 +03:00
|
|
|
nsTableRowFrame* mRow;
|
|
|
|
nsTableRowFrame* mPrevRow;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mIsNewRow;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mRowIndex;
|
|
|
|
uint32_t mNumTableCols;
|
|
|
|
int32_t mColIndex;
|
2002-02-19 18:48:28 +03:00
|
|
|
nsPoint mAreaStart;
|
|
|
|
nsPoint mAreaEnd;
|
|
|
|
};
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
BCMapCellIterator::BCMapCellIterator(nsTableFrame* aTableFrame,
|
2012-01-23 02:48:34 +04:00
|
|
|
const nsIntRect& aDamageArea)
|
2002-02-19 18:48:28 +03:00
|
|
|
:mTableFrame(aTableFrame)
|
2001-09-24 18:48:38 +04:00
|
|
|
{
|
2009-06-21 20:31:40 +04:00
|
|
|
mTableCellMap = aTableFrame->GetCellMap();
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
mAreaStart.x = aDamageArea.x;
|
|
|
|
mAreaStart.y = aDamageArea.y;
|
|
|
|
mAreaEnd.y = aDamageArea.y + aDamageArea.height - 1;
|
|
|
|
mAreaEnd.x = aDamageArea.x + aDamageArea.width - 1;
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
mNumTableRows = mTableFrame->GetRowCount();
|
2012-07-30 18:20:58 +04:00
|
|
|
mRow = nullptr;
|
2002-02-19 18:48:28 +03:00
|
|
|
mRowIndex = 0;
|
2009-06-21 20:31:40 +04:00
|
|
|
mNumTableCols = mTableFrame->GetColCount();
|
2002-02-19 18:48:28 +03:00
|
|
|
mColIndex = 0;
|
|
|
|
mRowGroupIndex = -1;
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
// Get the ordered row groups
|
2009-06-21 20:31:40 +04:00
|
|
|
aTableFrame->OrderRowGroups(mRowGroups);
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mAtEnd = true; // gets reset when First() is called
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// fill fields that we need for border collapse computation on a given cell
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetInfo(nsTableRowFrame* aNewRow,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t aColIndex,
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCellData* aCellData,
|
|
|
|
BCMapCellIterator* aIter,
|
|
|
|
nsCellMap* aCellMap)
|
|
|
|
{
|
|
|
|
// fill the cell information
|
|
|
|
mCellData = aCellData;
|
|
|
|
mColIndex = aColIndex;
|
|
|
|
|
|
|
|
// initialize the row information if it was not previously set for cells in
|
|
|
|
// this row
|
|
|
|
mRowIndex = 0;
|
|
|
|
if (aNewRow) {
|
|
|
|
mTopRow = aNewRow;
|
|
|
|
mRowIndex = aNewRow->GetRowIndex();
|
|
|
|
}
|
|
|
|
|
|
|
|
// fill cell frame info and row information
|
2012-07-30 18:20:58 +04:00
|
|
|
mCell = nullptr;
|
2009-06-21 20:31:40 +04:00
|
|
|
mRowSpan = 1;
|
|
|
|
mColSpan = 1;
|
2002-02-19 18:48:28 +03:00
|
|
|
if (aCellData) {
|
2009-06-21 20:31:40 +04:00
|
|
|
mCell = static_cast<nsBCTableCellFrame*>(aCellData->GetCellFrame());
|
|
|
|
if (mCell) {
|
|
|
|
if (!mTopRow) {
|
|
|
|
mTopRow = static_cast<nsTableRowFrame*>(mCell->GetParent());
|
|
|
|
if (!mTopRow) ABORT0();
|
|
|
|
mRowIndex = mTopRow->GetRowIndex();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
mColSpan = mTableFrame->GetEffectiveColSpan(*mCell, aCellMap);
|
|
|
|
mRowSpan = mTableFrame->GetEffectiveRowSpan(*mCell, aCellMap);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
if (!mTopRow) {
|
|
|
|
mTopRow = aIter->GetCurrentRow();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
if (1 == mRowSpan) {
|
|
|
|
mBottomRow = mTopRow;
|
2001-09-24 18:48:38 +04:00
|
|
|
}
|
|
|
|
else {
|
2009-06-21 20:31:40 +04:00
|
|
|
mBottomRow = mTopRow->GetNextRow();
|
|
|
|
if (mBottomRow) {
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t spanY = 2; mBottomRow && (spanY < mRowSpan); spanY++) {
|
2009-06-21 20:31:40 +04:00
|
|
|
mBottomRow = mBottomRow->GetNextRow();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
NS_ASSERTION(mBottomRow, "spanned row not found");
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
2011-10-17 18:59:28 +04:00
|
|
|
NS_ASSERTION(false, "error in cell map");
|
2009-06-21 20:31:40 +04:00
|
|
|
mRowSpan = 1;
|
|
|
|
mBottomRow = mTopRow;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2001-09-24 18:48:38 +04:00
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
// row group frame info
|
2009-06-21 20:31:40 +04:00
|
|
|
// try to reuse the rgStart and rgEnd from the iterator as calls to
|
|
|
|
// GetRowCount() are computationally expensive and should be avoided if
|
|
|
|
// possible
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t rgStart = aIter->mRowGroupStart;
|
|
|
|
uint32_t rgEnd = aIter->mRowGroupEnd;
|
2010-01-16 19:05:46 +03:00
|
|
|
mRowGroup = static_cast<nsTableRowGroupFrame*>(mTopRow->GetParent());
|
2009-06-21 20:31:40 +04:00
|
|
|
if (mRowGroup != aIter->GetCurrentRowGroup()) {
|
|
|
|
rgStart = mRowGroup->GetStartRowIndex();
|
|
|
|
rgEnd = rgStart + mRowGroup->GetRowCount() - 1;
|
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t rowIndex = mTopRow->GetRowIndex();
|
2009-06-21 20:31:40 +04:00
|
|
|
mRgAtTop = (rgStart == rowIndex);
|
|
|
|
mRgAtBottom = (rgEnd == rowIndex + mRowSpan - 1);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// col frame info
|
|
|
|
mLeftCol = mTableFrame->GetColFrame(aColIndex);
|
|
|
|
if (!mLeftCol) ABORT0();
|
|
|
|
|
|
|
|
mRightCol = mLeftCol;
|
|
|
|
if (mColSpan > 1) {
|
|
|
|
nsTableColFrame* colFrame = mTableFrame->GetColFrame(aColIndex +
|
|
|
|
mColSpan -1);
|
|
|
|
if (!colFrame) ABORT0();
|
|
|
|
mRightCol = colFrame;
|
1999-07-28 12:09:02 +04:00
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
// col group frame info
|
2009-06-21 20:31:40 +04:00
|
|
|
mColGroup = static_cast<nsTableColGroupFrame*>(mLeftCol->GetParent());
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t cgStart = mColGroup->GetStartColumnIndex();
|
|
|
|
int32_t cgEnd = NS_MAX(0, cgStart + mColGroup->GetColCount() - 1);
|
2009-06-21 20:31:40 +04:00
|
|
|
mCgAtLeft = (cgStart == aColIndex);
|
|
|
|
mCgAtRight = (cgEnd == aColIndex + mColSpan - 1);
|
1999-07-28 12:09:02 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2002-02-19 18:48:28 +03:00
|
|
|
BCMapCellIterator::SetNewRow(nsTableRowFrame* aRow)
|
|
|
|
{
|
2011-10-17 18:59:28 +04:00
|
|
|
mAtEnd = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
mPrevRow = mRow;
|
|
|
|
if (aRow) {
|
|
|
|
mRow = aRow;
|
|
|
|
}
|
|
|
|
else if (mRow) {
|
|
|
|
mRow = mRow->GetNextRow();
|
|
|
|
}
|
|
|
|
if (mRow) {
|
|
|
|
mRowIndex = mRow->GetRowIndex();
|
|
|
|
// get to the first entry with an originating cell
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rgRowIndex = mRowIndex - mRowGroupStart;
|
|
|
|
if (uint32_t(rgRowIndex) >= mCellMap->mRows.Length())
|
2011-10-17 18:59:28 +04:00
|
|
|
ABORT1(false);
|
2006-12-07 05:32:57 +03:00
|
|
|
const nsCellMap::CellDataArray& row = mCellMap->mRows[rgRowIndex];
|
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
for (mColIndex = mAreaStart.x; mColIndex <= mAreaEnd.x; mColIndex++) {
|
2006-12-07 05:32:57 +03:00
|
|
|
CellData* cellData = row.SafeElementAt(mColIndex);
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!cellData) { // add a dead cell data
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea;
|
2012-07-30 18:20:58 +04:00
|
|
|
cellData = mCellMap->AppendCell(*mTableCellMap, nullptr, rgRowIndex,
|
2011-10-27 17:58:44 +04:00
|
|
|
false, 0, damageArea);
|
|
|
|
if (!cellData) ABORT1(false);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
if (cellData && (cellData->IsOrig() || cellData->IsDead())) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
mIsNewRow = true;
|
|
|
|
mAtEnd = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
else ABORT1(false);
|
2002-03-25 18:03:14 +03:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
return !mAtEnd;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
|
|
|
BCMapCellIterator::SetNewRowGroup(bool aFindFirstDamagedRow)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2011-10-17 18:59:28 +04:00
|
|
|
mAtEnd = true;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numRowGroups = mRowGroups.Length();
|
2012-07-30 18:20:58 +04:00
|
|
|
mCellMap = nullptr;
|
2007-12-15 23:23:10 +03:00
|
|
|
for (mRowGroupIndex++; mRowGroupIndex < numRowGroups; mRowGroupIndex++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
mRowGroup = mRowGroups[mRowGroupIndex];
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rowCount = mRowGroup->GetRowCount();
|
2002-02-19 18:48:28 +03:00
|
|
|
mRowGroupStart = mRowGroup->GetStartRowIndex();
|
2003-09-27 16:00:56 +04:00
|
|
|
mRowGroupEnd = mRowGroupStart + rowCount - 1;
|
2007-12-15 23:23:10 +03:00
|
|
|
if (rowCount > 0) {
|
2007-01-22 07:35:25 +03:00
|
|
|
mCellMap = mTableCellMap->GetMapFor(mRowGroup, mCellMap);
|
2011-10-17 18:59:28 +04:00
|
|
|
if (!mCellMap) ABORT1(false);
|
2002-03-25 18:03:14 +03:00
|
|
|
nsTableRowFrame* firstRow = mRowGroup->GetFirstRow();
|
|
|
|
if (aFindFirstDamagedRow) {
|
|
|
|
if ((mAreaStart.y >= mRowGroupStart) && (mAreaStart.y <= mRowGroupEnd)) {
|
2010-04-27 20:15:01 +04:00
|
|
|
// the damage area starts in the row group
|
2002-03-25 18:03:14 +03:00
|
|
|
if (aFindFirstDamagedRow) {
|
|
|
|
// find the correct first damaged row
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numRows = mAreaStart.y - mRowGroupStart;
|
|
|
|
for (int32_t i = 0; i < numRows; i++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
firstRow = firstRow->GetNextRow();
|
2011-10-17 18:59:28 +04:00
|
|
|
if (!firstRow) ABORT1(false);
|
2002-03-25 18:03:14 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
else {
|
2002-03-25 18:03:14 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (SetNewRow(firstRow)) { // sets mAtEnd
|
|
|
|
break;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
return !mAtEnd;
|
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2002-02-19 18:48:28 +03:00
|
|
|
BCMapCellIterator::First(BCMapCellInfo& aMapInfo)
|
|
|
|
{
|
2009-06-21 20:31:40 +04:00
|
|
|
aMapInfo.ResetCellInfo();
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
SetNewRowGroup(true); // sets mAtEnd
|
2002-02-19 18:48:28 +03:00
|
|
|
while (!mAtEnd) {
|
|
|
|
if ((mAreaStart.y >= mRowGroupStart) && (mAreaStart.y <= mRowGroupEnd)) {
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCellData* cellData =
|
|
|
|
static_cast<BCCellData*>(mCellMap->GetDataAt(mAreaStart.y -
|
|
|
|
mRowGroupStart,
|
|
|
|
mAreaStart.x));
|
2011-03-28 18:49:48 +04:00
|
|
|
if (cellData && (cellData->IsOrig() || cellData->IsDead())) {
|
2009-06-21 20:31:40 +04:00
|
|
|
aMapInfo.SetInfo(mRow, mAreaStart.x, cellData, this);
|
2011-03-28 18:49:48 +04:00
|
|
|
return;
|
2002-03-07 18:33:49 +03:00
|
|
|
}
|
|
|
|
else {
|
2009-06-21 20:31:40 +04:00
|
|
|
NS_ASSERTION(((0 == mAreaStart.x) && (mRowGroupStart == mAreaStart.y)) ,
|
|
|
|
"damage area expanded incorrectly");
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
SetNewRowGroup(true); // sets mAtEnd
|
2010-04-27 20:15:01 +04:00
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2002-02-19 18:48:28 +03:00
|
|
|
BCMapCellIterator::Next(BCMapCellInfo& aMapInfo)
|
|
|
|
{
|
|
|
|
if (mAtEnd) ABORT0();
|
2009-06-21 20:31:40 +04:00
|
|
|
aMapInfo.ResetCellInfo();
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mIsNewRow = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
mColIndex++;
|
|
|
|
while ((mRowIndex <= mAreaEnd.y) && !mAtEnd) {
|
|
|
|
for (; mColIndex <= mAreaEnd.x; mColIndex++) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rgRowIndex = mRowIndex - mRowGroupStart;
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCellData* cellData =
|
|
|
|
static_cast<BCCellData*>(mCellMap->GetDataAt(rgRowIndex, mColIndex));
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!cellData) { // add a dead cell data
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea;
|
2009-06-21 20:31:40 +04:00
|
|
|
cellData =
|
2012-07-30 18:20:58 +04:00
|
|
|
static_cast<BCCellData*>(mCellMap->AppendCell(*mTableCellMap, nullptr,
|
2011-10-27 17:58:44 +04:00
|
|
|
rgRowIndex, false, 0,
|
2009-06-21 20:31:40 +04:00
|
|
|
damageArea));
|
|
|
|
if (!cellData) ABORT0();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
if (cellData && (cellData->IsOrig() || cellData->IsDead())) {
|
2009-06-21 20:31:40 +04:00
|
|
|
aMapInfo.SetInfo(mRow, mColIndex, cellData, this);
|
2002-02-19 18:48:28 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (mRowIndex >= mRowGroupEnd) {
|
2011-10-17 18:59:28 +04:00
|
|
|
SetNewRowGroup(false); // could set mAtEnd
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
SetNewRow(); // could set mAtEnd
|
|
|
|
}
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
mAtEnd = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2002-02-19 18:48:28 +03:00
|
|
|
BCMapCellIterator::PeekRight(BCMapCellInfo& aRefInfo,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aRowIndex,
|
2002-02-19 18:48:28 +03:00
|
|
|
BCMapCellInfo& aAjaInfo)
|
|
|
|
{
|
2009-06-21 20:31:40 +04:00
|
|
|
aAjaInfo.ResetCellInfo();
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colIndex = aRefInfo.mColIndex + aRefInfo.mColSpan;
|
|
|
|
uint32_t rgRowIndex = aRowIndex - mRowGroupStart;
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCellData* cellData =
|
|
|
|
static_cast<BCCellData*>(mCellMap->GetDataAt(rgRowIndex, colIndex));
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!cellData) { // add a dead cell data
|
|
|
|
NS_ASSERTION(colIndex < mTableCellMap->GetColCount(), "program error");
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea;
|
2009-06-21 20:31:40 +04:00
|
|
|
cellData =
|
2012-07-30 18:20:58 +04:00
|
|
|
static_cast<BCCellData*>(mCellMap->AppendCell(*mTableCellMap, nullptr,
|
2011-10-27 17:58:44 +04:00
|
|
|
rgRowIndex, false, 0,
|
2009-06-21 20:31:40 +04:00
|
|
|
damageArea));
|
|
|
|
if (!cellData) ABORT0();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
nsTableRowFrame* row = nullptr;
|
2002-02-19 18:48:28 +03:00
|
|
|
if (cellData->IsRowSpan()) {
|
|
|
|
rgRowIndex -= cellData->GetRowSpanOffset();
|
2009-06-21 20:31:40 +04:00
|
|
|
cellData =
|
|
|
|
static_cast<BCCellData*>(mCellMap->GetDataAt(rgRowIndex, colIndex));
|
2006-10-20 11:37:24 +04:00
|
|
|
if (!cellData)
|
|
|
|
ABORT0();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
row = mRow;
|
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
aAjaInfo.SetInfo(row, colIndex, cellData, this);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2002-02-19 18:48:28 +03:00
|
|
|
BCMapCellIterator::PeekBottom(BCMapCellInfo& aRefInfo,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aColIndex,
|
2002-02-19 18:48:28 +03:00
|
|
|
BCMapCellInfo& aAjaInfo)
|
|
|
|
{
|
2009-06-21 20:31:40 +04:00
|
|
|
aAjaInfo.ResetCellInfo();
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rowIndex = aRefInfo.mRowIndex + aRefInfo.mRowSpan;
|
|
|
|
int32_t rgRowIndex = rowIndex - mRowGroupStart;
|
2002-02-19 18:48:28 +03:00
|
|
|
nsTableRowGroupFrame* rg = mRowGroup;
|
|
|
|
nsCellMap* cellMap = mCellMap;
|
2012-07-30 18:20:58 +04:00
|
|
|
nsTableRowFrame* nextRow = nullptr;
|
2002-02-19 18:48:28 +03:00
|
|
|
if (rowIndex > mRowGroupEnd) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nextRgIndex = mRowGroupIndex;
|
2003-09-27 16:00:56 +04:00
|
|
|
do {
|
|
|
|
nextRgIndex++;
|
2007-06-05 22:55:26 +04:00
|
|
|
rg = mRowGroups.SafeElementAt(nextRgIndex);
|
2003-09-27 16:00:56 +04:00
|
|
|
if (rg) {
|
2007-01-22 07:35:25 +03:00
|
|
|
cellMap = mTableCellMap->GetMapFor(rg, cellMap); if (!cellMap) ABORT0();
|
2003-09-27 16:00:56 +04:00
|
|
|
rgRowIndex = 0;
|
|
|
|
nextRow = rg->GetFirstRow();
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2003-09-27 16:00:56 +04:00
|
|
|
while (rg && !nextRow);
|
|
|
|
if(!rg) return;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// get the row within the same row group
|
|
|
|
nextRow = mRow;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t i = 0; i < aRefInfo.mRowSpan; i++) {
|
2002-02-19 18:48:28 +03:00
|
|
|
nextRow = nextRow->GetNextRow(); if (!nextRow) ABORT0();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCellData* cellData =
|
|
|
|
static_cast<BCCellData*>(cellMap->GetDataAt(rgRowIndex, aColIndex));
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!cellData) { // add a dead cell data
|
|
|
|
NS_ASSERTION(rgRowIndex < cellMap->GetRowCount(), "program error");
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea;
|
2009-06-21 20:31:40 +04:00
|
|
|
cellData =
|
2012-07-30 18:20:58 +04:00
|
|
|
static_cast<BCCellData*>(cellMap->AppendCell(*mTableCellMap, nullptr,
|
2011-10-27 17:58:44 +04:00
|
|
|
rgRowIndex, false, 0,
|
2009-06-21 20:31:40 +04:00
|
|
|
damageArea));
|
|
|
|
if (!cellData) ABORT0();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
if (cellData->IsColSpan()) {
|
|
|
|
aColIndex -= cellData->GetColSpanOffset();
|
2009-06-21 20:31:40 +04:00
|
|
|
cellData =
|
|
|
|
static_cast<BCCellData*>(cellMap->GetDataAt(rgRowIndex, aColIndex));
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
aAjaInfo.SetInfo(nextRow, aColIndex, cellData, this, cellMap);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Assign priorities to border styles. For example, styleToPriority(NS_STYLE_BORDER_STYLE_SOLID)
|
2010-04-27 20:15:01 +04:00
|
|
|
// will return the priority of NS_STYLE_BORDER_STYLE_SOLID.
|
2012-08-22 19:56:38 +04:00
|
|
|
static uint8_t styleToPriority[13] = { 0, // NS_STYLE_BORDER_STYLE_NONE
|
2007-02-01 05:45:55 +03:00
|
|
|
2, // NS_STYLE_BORDER_STYLE_GROOVE
|
|
|
|
4, // NS_STYLE_BORDER_STYLE_RIDGE
|
|
|
|
5, // NS_STYLE_BORDER_STYLE_DOTTED
|
|
|
|
6, // NS_STYLE_BORDER_STYLE_DASHED
|
|
|
|
7, // NS_STYLE_BORDER_STYLE_SOLID
|
|
|
|
8, // NS_STYLE_BORDER_STYLE_DOUBLE
|
|
|
|
1, // NS_STYLE_BORDER_STYLE_INSET
|
|
|
|
3, // NS_STYLE_BORDER_STYLE_OUTSET
|
|
|
|
9 };// NS_STYLE_BORDER_STYLE_HIDDEN
|
2004-10-09 16:04:52 +04:00
|
|
|
// priority rules follow CSS 2.1 spec
|
|
|
|
// 'hidden', 'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', 'groove',
|
|
|
|
// and the lowest: 'inset'. none is even weaker
|
2011-10-17 18:59:28 +04:00
|
|
|
#define CELL_CORNER true
|
2004-10-09 16:04:52 +04:00
|
|
|
|
|
|
|
/** return the border style, border color for a given frame and side
|
2010-04-27 20:15:01 +04:00
|
|
|
* @param aFrame - query the info for this frame
|
2004-10-09 16:04:52 +04:00
|
|
|
* @param aSide - the side of the frame
|
|
|
|
* @param aStyle - the border style
|
|
|
|
* @param aColor - the border color
|
2004-12-27 21:43:55 +03:00
|
|
|
* @param aTableIsLTR - table direction is LTR
|
2004-10-09 16:04:52 +04:00
|
|
|
*/
|
2010-04-27 20:15:01 +04:00
|
|
|
static void
|
2004-10-09 16:04:52 +04:00
|
|
|
GetColorAndStyle(const nsIFrame* aFrame,
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side aSide,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t& aStyle,
|
2004-10-09 16:04:52 +04:00
|
|
|
nscolor& aColor,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aTableIsLTR)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2004-10-09 16:04:52 +04:00
|
|
|
NS_PRECONDITION(aFrame, "null frame");
|
|
|
|
// initialize out arg
|
|
|
|
aColor = 0;
|
|
|
|
const nsStyleBorder* styleData = aFrame->GetStyleBorder();
|
2004-12-27 21:43:55 +03:00
|
|
|
if(!aTableIsLTR) { // revert the directions
|
|
|
|
if (NS_SIDE_RIGHT == aSide) {
|
|
|
|
aSide = NS_SIDE_LEFT;
|
|
|
|
}
|
|
|
|
else if (NS_SIDE_LEFT == aSide) {
|
|
|
|
aSide = NS_SIDE_RIGHT;
|
|
|
|
}
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
aStyle = styleData->GetBorderStyle(aSide);
|
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
if ((NS_STYLE_BORDER_STYLE_NONE == aStyle) ||
|
|
|
|
(NS_STYLE_BORDER_STYLE_HIDDEN == aStyle)) {
|
2002-02-19 18:48:28 +03:00
|
|
|
return;
|
|
|
|
}
|
2010-04-03 05:58:26 +04:00
|
|
|
aColor = aFrame->GetStyleContext()->GetVisitedDependentColor(
|
|
|
|
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[aSide]);
|
2004-10-09 16:04:52 +04:00
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
/** coerce the paint style as required by CSS2.1
|
2010-04-27 20:15:01 +04:00
|
|
|
* @param aFrame - query the info for this frame
|
2004-10-09 16:04:52 +04:00
|
|
|
* @param aSide - the side of the frame
|
|
|
|
* @param aStyle - the border style
|
|
|
|
* @param aColor - the border color
|
2004-12-27 21:43:55 +03:00
|
|
|
* @param aTableIsLTR - table direction is LTR
|
2004-10-09 16:04:52 +04:00
|
|
|
*/
|
|
|
|
static void
|
|
|
|
GetPaintStyleInfo(const nsIFrame* aFrame,
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side aSide,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t& aStyle,
|
2004-10-09 16:04:52 +04:00
|
|
|
nscolor& aColor,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aTableIsLTR)
|
2004-10-09 16:04:52 +04:00
|
|
|
{
|
2010-01-09 18:33:03 +03:00
|
|
|
GetColorAndStyle(aFrame, aSide, aStyle, aColor, aTableIsLTR);
|
2007-02-01 05:45:55 +03:00
|
|
|
if (NS_STYLE_BORDER_STYLE_INSET == aStyle) {
|
2004-10-09 16:04:52 +04:00
|
|
|
aStyle = NS_STYLE_BORDER_STYLE_RIDGE;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2007-02-01 05:45:55 +03:00
|
|
|
else if (NS_STYLE_BORDER_STYLE_OUTSET == aStyle) {
|
2004-10-09 16:04:52 +04:00
|
|
|
aStyle = NS_STYLE_BORDER_STYLE_GROOVE;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/** return the border style, border color and the width in pixel for a given
|
|
|
|
* frame and side
|
2010-04-27 20:15:01 +04:00
|
|
|
* @param aFrame - query the info for this frame
|
2004-10-09 16:04:52 +04:00
|
|
|
* @param aSide - the side of the frame
|
|
|
|
* @param aStyle - the border style
|
|
|
|
* @param aColor - the border color
|
2004-12-27 21:43:55 +03:00
|
|
|
* @param aTableIsLTR - table direction is LTR
|
2004-10-09 16:04:52 +04:00
|
|
|
* @param aWidth - the border width in px.
|
|
|
|
* @param aTwipsToPixels - conversion factor from twips to pixel
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
GetColorAndStyle(const nsIFrame* aFrame,
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side aSide,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t& aStyle,
|
2004-10-09 16:04:52 +04:00
|
|
|
nscolor& aColor,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aTableIsLTR,
|
2009-06-21 20:31:40 +04:00
|
|
|
BCPixelSize& aWidth)
|
2004-10-09 16:04:52 +04:00
|
|
|
{
|
2010-01-09 18:33:03 +03:00
|
|
|
GetColorAndStyle(aFrame, aSide, aStyle, aColor, aTableIsLTR);
|
2004-10-09 16:04:52 +04:00
|
|
|
if ((NS_STYLE_BORDER_STYLE_NONE == aStyle) ||
|
|
|
|
(NS_STYLE_BORDER_STYLE_HIDDEN == aStyle)) {
|
|
|
|
aWidth = 0;
|
|
|
|
return;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
const nsStyleBorder* styleData = aFrame->GetStyleBorder();
|
|
|
|
nscoord width;
|
2004-12-27 21:43:55 +03:00
|
|
|
if(!aTableIsLTR) { // revert the directions
|
|
|
|
if (NS_SIDE_RIGHT == aSide) {
|
|
|
|
aSide = NS_SIDE_LEFT;
|
|
|
|
}
|
|
|
|
else if (NS_SIDE_LEFT == aSide) {
|
|
|
|
aSide = NS_SIDE_RIGHT;
|
|
|
|
}
|
|
|
|
}
|
2012-05-31 09:19:49 +04:00
|
|
|
width = styleData->GetComputedBorderWidth(aSide);
|
2007-02-07 10:46:44 +03:00
|
|
|
aWidth = nsPresContext::AppUnitsToIntCSSPixels(width);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2008-10-26 13:11:34 +03:00
|
|
|
|
|
|
|
class nsDelayedCalcBCBorders : public nsRunnable {
|
|
|
|
public:
|
|
|
|
nsDelayedCalcBCBorders(nsIFrame* aFrame) :
|
|
|
|
mFrame(aFrame) {}
|
|
|
|
|
|
|
|
NS_IMETHOD Run() {
|
|
|
|
if (mFrame) {
|
|
|
|
nsTableFrame* tableFrame = static_cast <nsTableFrame*>(mFrame.GetFrame());
|
2008-11-01 11:52:29 +03:00
|
|
|
if (tableFrame->NeedToCalcBCBorders()) {
|
|
|
|
tableFrame->CalcBCBorders();
|
2008-10-26 13:11:34 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
nsWeakFrame mFrame;
|
|
|
|
};
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2008-10-26 13:11:34 +03:00
|
|
|
nsTableFrame::BCRecalcNeeded(nsStyleContext* aOldStyleContext,
|
|
|
|
nsStyleContext* aNewStyleContext)
|
|
|
|
{
|
2008-11-01 11:52:29 +03:00
|
|
|
// Attention: the old style context is the one we're forgetting,
|
|
|
|
// and hence possibly completely bogus for GetStyle* purposes.
|
|
|
|
// We use PeekStyleData instead.
|
|
|
|
|
2010-03-03 02:27:21 +03:00
|
|
|
const nsStyleBorder* oldStyleData = aOldStyleContext->PeekStyleBorder();
|
2008-11-01 11:52:29 +03:00
|
|
|
if (!oldStyleData)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2008-11-01 11:52:29 +03:00
|
|
|
|
|
|
|
const nsStyleBorder* newStyleData = aNewStyleContext->GetStyleBorder();
|
|
|
|
nsChangeHint change = newStyleData->CalcDifference(*oldStyleData);
|
2008-11-05 01:03:14 +03:00
|
|
|
if (!change)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2012-09-08 02:57:06 +04:00
|
|
|
if (change & nsChangeHint_NeedReflow)
|
2011-10-17 18:59:28 +04:00
|
|
|
return true; // the caller only needs to mark the bc damage area
|
2008-11-05 01:03:14 +03:00
|
|
|
if (change & nsChangeHint_RepaintFrame) {
|
2008-11-02 21:41:35 +03:00
|
|
|
// we need to recompute the borders and the caller needs to mark
|
|
|
|
// the bc damage area
|
|
|
|
// XXX In principle this should only be necessary for border style changes
|
|
|
|
// However the bc painting code tries to maximize the drawn border segments
|
|
|
|
// so it stores in the cellmap where a new border segment starts and this
|
|
|
|
// introduces a unwanted cellmap data dependence on color
|
|
|
|
nsCOMPtr<nsIRunnable> evt = new nsDelayedCalcBCBorders(this);
|
|
|
|
NS_DispatchToCurrentThread(evt);
|
2011-10-17 18:59:28 +04:00
|
|
|
return true;
|
2008-11-01 11:52:29 +03:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2008-10-26 13:11:34 +03:00
|
|
|
}
|
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
|
|
|
|
// Compare two border segments, this comparison depends whether the two
|
|
|
|
// segments meet at a corner and whether the second segment is horizontal.
|
|
|
|
// The return value is whichever of aBorder1 or aBorder2 dominates.
|
|
|
|
static const BCCellBorder&
|
2011-09-29 10:19:26 +04:00
|
|
|
CompareBorders(bool aIsCorner, // Pass true for corner calculations
|
2004-10-09 16:04:52 +04:00
|
|
|
const BCCellBorder& aBorder1,
|
|
|
|
const BCCellBorder& aBorder2,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aSecondIsHorizontal,
|
2012-07-30 18:20:58 +04:00
|
|
|
bool* aFirstDominates = nullptr)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool firstDominates = true;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
if (NS_STYLE_BORDER_STYLE_HIDDEN == aBorder1.style) {
|
2011-10-17 18:59:28 +04:00
|
|
|
firstDominates = (aIsCorner) ? false : true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
else if (NS_STYLE_BORDER_STYLE_HIDDEN == aBorder2.style) {
|
2011-10-17 18:59:28 +04:00
|
|
|
firstDominates = (aIsCorner) ? true : false;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
else if (aBorder1.width < aBorder2.width) {
|
2011-10-17 18:59:28 +04:00
|
|
|
firstDominates = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
else if (aBorder1.width == aBorder2.width) {
|
|
|
|
if (styleToPriority[aBorder1.style] < styleToPriority[aBorder2.style]) {
|
2011-10-17 18:59:28 +04:00
|
|
|
firstDominates = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
else if (styleToPriority[aBorder1.style] == styleToPriority[aBorder2.style]) {
|
|
|
|
if (aBorder1.owner == aBorder2.owner) {
|
2002-02-19 18:48:28 +03:00
|
|
|
firstDominates = !aSecondIsHorizontal;
|
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
else if (aBorder1.owner < aBorder2.owner) {
|
2011-10-17 18:59:28 +04:00
|
|
|
firstDominates = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
if (aFirstDominates)
|
|
|
|
*aFirstDominates = firstDominates;
|
|
|
|
|
|
|
|
if (firstDominates)
|
|
|
|
return aBorder1;
|
|
|
|
return aBorder2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** calc the dominant border by considering the table, row/col group, row/col,
|
2010-04-27 20:15:01 +04:00
|
|
|
* cell.
|
2004-10-09 16:04:52 +04:00
|
|
|
* Depending on whether the side is vertical or horizontal and whether
|
|
|
|
* adjacent frames are taken into account the ownership of a single border
|
|
|
|
* segment is defined. The return value is the dominating border
|
|
|
|
* The cellmap stores only top and left borders for each cellmap position.
|
|
|
|
* If the cell border is owned by the cell that is left of the border
|
|
|
|
* it will be an adjacent owner aka eAjaCellOwner. See celldata.h for the other
|
|
|
|
* scenarios with a adjacent owner.
|
|
|
|
* @param xxxFrame - the frame for style information, might be zero if
|
|
|
|
* it should not be considered
|
|
|
|
* @param aSide - side of the frames that should be considered
|
|
|
|
* @param aAja - the border comparison takes place from the point of
|
|
|
|
* a frame that is adjacent to the cellmap entry, for
|
|
|
|
* when a cell owns its lower border it will be the
|
|
|
|
* adjacent owner as in the cellmap only top and left
|
2010-04-27 20:15:01 +04:00
|
|
|
* borders are stored.
|
2004-10-09 16:04:52 +04:00
|
|
|
* @param aTwipsToPixels - conversion factor as borders need to be drawn pixel
|
|
|
|
* aligned.
|
|
|
|
*/
|
|
|
|
static BCCellBorder
|
|
|
|
CompareBorders(const nsIFrame* aTableFrame,
|
|
|
|
const nsIFrame* aColGroupFrame,
|
|
|
|
const nsIFrame* aColFrame,
|
|
|
|
const nsIFrame* aRowGroupFrame,
|
|
|
|
const nsIFrame* aRowFrame,
|
|
|
|
const nsIFrame* aCellFrame,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aTableIsLTR,
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side aSide,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aAja)
|
2004-10-09 16:04:52 +04:00
|
|
|
{
|
|
|
|
BCCellBorder border, tempBorder;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool horizontal = (NS_SIDE_TOP == aSide) || (NS_SIDE_BOTTOM == aSide);
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
// start with the table as dominant if present
|
2002-02-19 18:48:28 +03:00
|
|
|
if (aTableFrame) {
|
2010-01-09 18:33:03 +03:00
|
|
|
GetColorAndStyle(aTableFrame, aSide, border.style, border.color, aTableIsLTR, border.width);
|
2004-10-09 16:04:52 +04:00
|
|
|
border.owner = eTableOwner;
|
|
|
|
if (NS_STYLE_BORDER_STYLE_HIDDEN == border.style) {
|
|
|
|
return border;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
// see if the colgroup is dominant
|
2002-02-19 18:48:28 +03:00
|
|
|
if (aColGroupFrame) {
|
2010-01-09 18:33:03 +03:00
|
|
|
GetColorAndStyle(aColGroupFrame, aSide, tempBorder.style, tempBorder.color, aTableIsLTR, tempBorder.width);
|
2004-10-09 16:04:52 +04:00
|
|
|
tempBorder.owner = (aAja && !horizontal) ? eAjaColGroupOwner : eColGroupOwner;
|
2011-10-17 18:59:28 +04:00
|
|
|
// pass here and below false for aSecondIsHorizontal as it is only used for corner calculations.
|
|
|
|
border = CompareBorders(!CELL_CORNER, border, tempBorder, false);
|
2004-10-09 16:04:52 +04:00
|
|
|
if (NS_STYLE_BORDER_STYLE_HIDDEN == border.style) {
|
|
|
|
return border;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
// see if the col is dominant
|
2002-02-19 18:48:28 +03:00
|
|
|
if (aColFrame) {
|
2010-01-09 18:33:03 +03:00
|
|
|
GetColorAndStyle(aColFrame, aSide, tempBorder.style, tempBorder.color, aTableIsLTR, tempBorder.width);
|
2004-10-09 16:04:52 +04:00
|
|
|
tempBorder.owner = (aAja && !horizontal) ? eAjaColOwner : eColOwner;
|
2011-10-17 18:59:28 +04:00
|
|
|
border = CompareBorders(!CELL_CORNER, border, tempBorder, false);
|
2004-10-09 16:04:52 +04:00
|
|
|
if (NS_STYLE_BORDER_STYLE_HIDDEN == border.style) {
|
|
|
|
return border;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
// see if the rowgroup is dominant
|
2002-02-19 18:48:28 +03:00
|
|
|
if (aRowGroupFrame) {
|
2010-01-09 18:33:03 +03:00
|
|
|
GetColorAndStyle(aRowGroupFrame, aSide, tempBorder.style, tempBorder.color, aTableIsLTR, tempBorder.width);
|
2004-10-09 16:04:52 +04:00
|
|
|
tempBorder.owner = (aAja && horizontal) ? eAjaRowGroupOwner : eRowGroupOwner;
|
2011-10-17 18:59:28 +04:00
|
|
|
border = CompareBorders(!CELL_CORNER, border, tempBorder, false);
|
2004-10-09 16:04:52 +04:00
|
|
|
if (NS_STYLE_BORDER_STYLE_HIDDEN == border.style) {
|
|
|
|
return border;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
// see if the row is dominant
|
2002-02-19 18:48:28 +03:00
|
|
|
if (aRowFrame) {
|
2010-01-09 18:33:03 +03:00
|
|
|
GetColorAndStyle(aRowFrame, aSide, tempBorder.style, tempBorder.color, aTableIsLTR, tempBorder.width);
|
2004-10-09 16:04:52 +04:00
|
|
|
tempBorder.owner = (aAja && horizontal) ? eAjaRowOwner : eRowOwner;
|
2011-10-17 18:59:28 +04:00
|
|
|
border = CompareBorders(!CELL_CORNER, border, tempBorder, false);
|
2004-10-09 16:04:52 +04:00
|
|
|
if (NS_STYLE_BORDER_STYLE_HIDDEN == border.style) {
|
|
|
|
return border;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
// see if the cell is dominant
|
2002-02-19 18:48:28 +03:00
|
|
|
if (aCellFrame) {
|
2010-01-09 18:33:03 +03:00
|
|
|
GetColorAndStyle(aCellFrame, aSide, tempBorder.style, tempBorder.color, aTableIsLTR, tempBorder.width);
|
2004-10-09 16:04:52 +04:00
|
|
|
tempBorder.owner = (aAja) ? eAjaCellOwner : eCellOwner;
|
2011-10-17 18:59:28 +04:00
|
|
|
border = CompareBorders(!CELL_CORNER, border, tempBorder, false);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
return border;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2010-04-27 20:15:02 +04:00
|
|
|
Perpendicular(mozilla::css::Side aSide1,
|
|
|
|
mozilla::css::Side aSide2)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
|
|
|
switch (aSide1) {
|
|
|
|
case NS_SIDE_TOP:
|
|
|
|
return (NS_SIDE_BOTTOM != aSide2);
|
|
|
|
case NS_SIDE_RIGHT:
|
|
|
|
return (NS_SIDE_LEFT != aSide2);
|
|
|
|
case NS_SIDE_BOTTOM:
|
|
|
|
return (NS_SIDE_TOP != aSide2);
|
|
|
|
default: // NS_SIDE_LEFT
|
|
|
|
return (NS_SIDE_RIGHT != aSide2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX allocate this as number-of-cols+1 instead of number-of-cols+1 * number-of-rows+1
|
2010-04-27 20:15:01 +04:00
|
|
|
struct BCCornerInfo
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2010-04-27 20:15:02 +04:00
|
|
|
BCCornerInfo() { ownerColor = 0; ownerWidth = subWidth = ownerElem = subSide =
|
|
|
|
subElem = hasDashDot = numSegs = bevel = 0; ownerSide = NS_SIDE_TOP;
|
2002-02-19 18:48:28 +03:00
|
|
|
ownerStyle = 0xFF; subStyle = NS_STYLE_BORDER_STYLE_SOLID; }
|
2010-04-27 20:15:02 +04:00
|
|
|
void Set(mozilla::css::Side aSide,
|
2004-10-09 16:04:52 +04:00
|
|
|
BCCellBorder border);
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2010-04-27 20:15:02 +04:00
|
|
|
void Update(mozilla::css::Side aSide,
|
2004-10-09 16:04:52 +04:00
|
|
|
BCCellBorder border);
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
nscolor ownerColor; // color of borderOwner
|
2012-08-22 19:56:38 +04:00
|
|
|
uint16_t ownerWidth; // pixel width of borderOwner
|
|
|
|
uint16_t subWidth; // pixel width of the largest border intersecting the border perpendicular
|
2002-02-19 18:48:28 +03:00
|
|
|
// to ownerSide
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t ownerSide:2; // mozilla::css::Side (e.g NS_SIDE_TOP, NS_SIDE_RIGHT, etc) of the border
|
2010-04-27 20:15:02 +04:00
|
|
|
// owning the corner relative to the corner
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t ownerElem:3; // elem type (e.g. eTable, eGroup, etc) owning the corner
|
|
|
|
uint32_t ownerStyle:8; // border style of ownerElem
|
|
|
|
uint32_t subSide:2; // side of border with subWidth relative to the corner
|
|
|
|
uint32_t subElem:3; // elem type (e.g. eTable, eGroup, etc) of sub owner
|
|
|
|
uint32_t subStyle:8; // border style of subElem
|
|
|
|
uint32_t hasDashDot:1; // does a dashed, dotted segment enter the corner, they cannot be beveled
|
|
|
|
uint32_t numSegs:3; // number of segments entering corner
|
|
|
|
uint32_t bevel:1; // is the corner beveled (uses the above two fields together with subWidth)
|
|
|
|
uint32_t unused:1;
|
2002-02-19 18:48:28 +03:00
|
|
|
};
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2010-04-27 20:15:02 +04:00
|
|
|
BCCornerInfo::Set(mozilla::css::Side aSide,
|
2004-10-09 16:04:52 +04:00
|
|
|
BCCellBorder aBorder)
|
|
|
|
{
|
|
|
|
ownerElem = aBorder.owner;
|
|
|
|
ownerStyle = aBorder.style;
|
|
|
|
ownerWidth = aBorder.width;
|
|
|
|
ownerColor = aBorder.color;
|
2002-02-19 18:48:28 +03:00
|
|
|
ownerSide = aSide;
|
|
|
|
hasDashDot = 0;
|
|
|
|
numSegs = 0;
|
2004-10-09 16:04:52 +04:00
|
|
|
if (aBorder.width > 0) {
|
2002-02-19 18:48:28 +03:00
|
|
|
numSegs++;
|
2004-10-09 16:04:52 +04:00
|
|
|
hasDashDot = (NS_STYLE_BORDER_STYLE_DASHED == aBorder.style) ||
|
|
|
|
(NS_STYLE_BORDER_STYLE_DOTTED == aBorder.style);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
bevel = 0;
|
|
|
|
subWidth = 0;
|
|
|
|
// the following will get set later
|
2010-04-27 20:15:01 +04:00
|
|
|
subSide = ((aSide == NS_SIDE_LEFT) || (aSide == NS_SIDE_RIGHT)) ? NS_SIDE_TOP : NS_SIDE_LEFT;
|
2002-02-19 18:48:28 +03:00
|
|
|
subElem = eTableOwner;
|
2010-04-27 20:15:01 +04:00
|
|
|
subStyle = NS_STYLE_BORDER_STYLE_SOLID;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2010-04-27 20:15:02 +04:00
|
|
|
BCCornerInfo::Update(mozilla::css::Side aSide,
|
2004-10-09 16:04:52 +04:00
|
|
|
BCCellBorder aBorder)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool existingWins = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
if (0xFF == ownerStyle) { // initial value indiating that it hasn't been set yet
|
2004-10-09 16:04:52 +04:00
|
|
|
Set(aSide, aBorder);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
2011-09-29 10:19:26 +04:00
|
|
|
bool horizontal = (NS_SIDE_LEFT == aSide) || (NS_SIDE_RIGHT == aSide); // relative to the corner
|
2004-10-09 16:04:52 +04:00
|
|
|
BCCellBorder oldBorder, tempBorder;
|
|
|
|
oldBorder.owner = (BCBorderOwner) ownerElem;
|
|
|
|
oldBorder.style = ownerStyle;
|
|
|
|
oldBorder.width = ownerWidth;
|
|
|
|
oldBorder.color = ownerColor;
|
|
|
|
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side oldSide = mozilla::css::Side(ownerSide);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
|
|
|
tempBorder = CompareBorders(CELL_CORNER, oldBorder, aBorder, horizontal, &existingWins);
|
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
ownerElem = tempBorder.owner;
|
|
|
|
ownerStyle = tempBorder.style;
|
|
|
|
ownerWidth = tempBorder.width;
|
|
|
|
ownerColor = tempBorder.color;
|
|
|
|
if (existingWins) { // existing corner is dominant
|
2010-04-27 20:15:02 +04:00
|
|
|
if (::Perpendicular(mozilla::css::Side(ownerSide), aSide)) {
|
2002-02-19 18:48:28 +03:00
|
|
|
// see if the new sub info replaces the old
|
2004-10-09 16:04:52 +04:00
|
|
|
BCCellBorder subBorder;
|
|
|
|
subBorder.owner = (BCBorderOwner) subElem;
|
|
|
|
subBorder.style = subStyle;
|
|
|
|
subBorder.width = subWidth;
|
|
|
|
subBorder.color = 0; // we are not interested in subBorder color
|
2011-09-29 10:19:26 +04:00
|
|
|
bool firstWins;
|
2004-10-09 16:04:52 +04:00
|
|
|
|
|
|
|
tempBorder = CompareBorders(CELL_CORNER, subBorder, aBorder, horizontal, &firstWins);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
subElem = tempBorder.owner;
|
|
|
|
subStyle = tempBorder.style;
|
|
|
|
subWidth = tempBorder.width;
|
|
|
|
if (!firstWins) {
|
2010-04-27 20:15:01 +04:00
|
|
|
subSide = aSide;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
else { // input args are dominant
|
2002-02-19 18:48:28 +03:00
|
|
|
ownerSide = aSide;
|
2010-04-27 20:15:02 +04:00
|
|
|
if (::Perpendicular(oldSide, mozilla::css::Side(ownerSide))) {
|
2004-10-09 16:04:52 +04:00
|
|
|
subElem = oldBorder.owner;
|
|
|
|
subStyle = oldBorder.style;
|
|
|
|
subWidth = oldBorder.width;
|
|
|
|
subSide = oldSide;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
if (aBorder.width > 0) {
|
2002-02-19 18:48:28 +03:00
|
|
|
numSegs++;
|
2004-10-09 16:04:52 +04:00
|
|
|
if (!hasDashDot && ((NS_STYLE_BORDER_STYLE_DASHED == aBorder.style) ||
|
|
|
|
(NS_STYLE_BORDER_STYLE_DOTTED == aBorder.style))) {
|
2002-02-19 18:48:28 +03:00
|
|
|
hasDashDot = 1;
|
|
|
|
}
|
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
// bevel the corner if only two perpendicular non dashed/dotted segments enter the corner
|
|
|
|
bevel = (2 == numSegs) && (subWidth > 1) && (0 == hasDashDot);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct BCCorners
|
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
BCCorners(int32_t aNumCorners,
|
|
|
|
int32_t aStartIndex);
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
~BCCorners() { delete [] corners; }
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
BCCornerInfo& operator [](int32_t i) const
|
2002-02-19 18:48:28 +03:00
|
|
|
{ NS_ASSERTION((i >= startIndex) && (i <= endIndex), "program error");
|
2011-10-28 22:33:28 +04:00
|
|
|
return corners[clamped(i, startIndex, endIndex) - startIndex]; }
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t startIndex;
|
|
|
|
int32_t endIndex;
|
2002-02-19 18:48:28 +03:00
|
|
|
BCCornerInfo* corners;
|
|
|
|
};
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
BCCorners::BCCorners(int32_t aNumCorners,
|
|
|
|
int32_t aStartIndex)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION((aNumCorners > 0) && (aStartIndex >= 0), "program error");
|
|
|
|
startIndex = aStartIndex;
|
|
|
|
endIndex = aStartIndex + aNumCorners - 1;
|
2010-04-27 20:15:01 +04:00
|
|
|
corners = new BCCornerInfo[aNumCorners];
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
struct BCCellBorders
|
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
BCCellBorders(int32_t aNumBorders,
|
|
|
|
int32_t aStartIndex);
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
~BCCellBorders() { delete [] borders; }
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
BCCellBorder& operator [](int32_t i) const
|
2002-02-19 18:48:28 +03:00
|
|
|
{ NS_ASSERTION((i >= startIndex) && (i <= endIndex), "program error");
|
2011-10-28 22:33:28 +04:00
|
|
|
return borders[clamped(i, startIndex, endIndex) - startIndex]; }
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t startIndex;
|
|
|
|
int32_t endIndex;
|
2002-02-19 18:48:28 +03:00
|
|
|
BCCellBorder* borders;
|
|
|
|
};
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
BCCellBorders::BCCellBorders(int32_t aNumBorders,
|
|
|
|
int32_t aStartIndex)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION((aNumBorders > 0) && (aStartIndex >= 0), "program error");
|
|
|
|
startIndex = aStartIndex;
|
|
|
|
endIndex = aStartIndex + aNumBorders - 1;
|
2010-04-27 20:15:01 +04:00
|
|
|
borders = new BCCellBorder[aNumBorders];
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
// this function sets the new border properties and returns true if the border
|
2009-11-05 12:26:00 +03:00
|
|
|
// segment will start a new segment and not be accumulated into the previous
|
|
|
|
// segment.
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2004-10-09 16:04:52 +04:00
|
|
|
SetBorder(const BCCellBorder& aNewBorder,
|
|
|
|
BCCellBorder& aBorder)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool changed = (aNewBorder.style != aBorder.style) ||
|
2004-10-09 16:04:52 +04:00
|
|
|
(aNewBorder.width != aBorder.width) ||
|
|
|
|
(aNewBorder.color != aBorder.color);
|
|
|
|
aBorder.color = aNewBorder.color;
|
|
|
|
aBorder.width = aNewBorder.width;
|
|
|
|
aBorder.style = aNewBorder.style;
|
|
|
|
aBorder.owner = aNewBorder.owner;
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
return changed;
|
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
// this function will set the horizontal border. It will return true if the
|
2004-10-09 16:04:52 +04:00
|
|
|
// existing segment will not be continued. Having a vertical owner of a corner
|
|
|
|
// should also start a new segment.
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2004-10-09 16:04:52 +04:00
|
|
|
SetHorBorder(const BCCellBorder& aNewBorder,
|
2002-02-19 18:48:28 +03:00
|
|
|
const BCCornerInfo& aCorner,
|
|
|
|
BCCellBorder& aBorder)
|
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool startSeg = ::SetBorder(aNewBorder, aBorder);
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!startSeg) {
|
|
|
|
startSeg = ((NS_SIDE_LEFT != aCorner.ownerSide) && (NS_SIDE_RIGHT != aCorner.ownerSide));
|
|
|
|
}
|
|
|
|
return startSeg;
|
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
// Make the damage area larger on the top and bottom by at least one row and on the left and right
|
|
|
|
// at least one column. This is done so that adjacent elements are part of the border calculations.
|
|
|
|
// The extra segments and borders outside the actual damage area will not be updated in the cell map,
|
2002-02-19 18:48:28 +03:00
|
|
|
// because they in turn would need info from adjacent segments outside the damage area to be accurate.
|
|
|
|
void
|
2012-01-23 02:48:34 +04:00
|
|
|
nsTableFrame::ExpandBCDamageArea(nsIntRect& aRect) const
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numRows = GetRowCount();
|
|
|
|
int32_t numCols = GetColCount();
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t dStartX = aRect.x;
|
|
|
|
int32_t dEndX = aRect.XMost() - 1;
|
|
|
|
int32_t dStartY = aRect.y;
|
|
|
|
int32_t dEndY = aRect.YMost() - 1;
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
// expand the damage area in each direction
|
|
|
|
if (dStartX > 0) {
|
|
|
|
dStartX--;
|
|
|
|
}
|
|
|
|
if (dEndX < (numCols - 1)) {
|
|
|
|
dEndX++;
|
|
|
|
}
|
|
|
|
if (dStartY > 0) {
|
|
|
|
dStartY--;
|
|
|
|
}
|
|
|
|
if (dEndY < (numRows - 1)) {
|
|
|
|
dEndY++;
|
|
|
|
}
|
|
|
|
// Check the damage area so that there are no cells spanning in or out. If there are any then
|
|
|
|
// make the damage area as big as the table, similarly to the way the cell map decides whether
|
|
|
|
// to rebuild versus expand. This could be optimized to expand to the smallest area that contains
|
|
|
|
// no spanners, but it may not be worth the effort in general, and it would need to be done in the
|
|
|
|
// cell map as well.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool haveSpanner = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
if ((dStartX > 0) || (dEndX < (numCols - 1)) || (dStartY > 0) || (dEndY < (numRows - 1))) {
|
|
|
|
nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT0();
|
2010-04-27 20:15:01 +04:00
|
|
|
// Get the ordered row groups
|
2007-06-05 22:55:26 +04:00
|
|
|
RowGroupArray rowGroups;
|
|
|
|
OrderRowGroups(rowGroups);
|
2007-01-22 07:35:25 +03:00
|
|
|
|
|
|
|
// Scope outside loop to be used as hint.
|
2012-07-30 18:20:58 +04:00
|
|
|
nsCellMap* cellMap = nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t rgX = 0; rgX < rowGroups.Length(); rgX++) {
|
2007-06-05 22:55:26 +04:00
|
|
|
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t rgStartY = rgFrame->GetStartRowIndex();
|
|
|
|
int32_t rgEndY = rgStartY + rgFrame->GetRowCount() - 1;
|
2010-04-27 20:15:01 +04:00
|
|
|
if (dEndY < rgStartY)
|
2002-02-19 18:48:28 +03:00
|
|
|
break;
|
2007-01-22 07:35:25 +03:00
|
|
|
cellMap = tableCellMap->GetMapFor(rgFrame, cellMap);
|
|
|
|
if (!cellMap) ABORT0();
|
2002-02-19 18:48:28 +03:00
|
|
|
// check for spanners from above and below
|
|
|
|
if ((dStartY > 0) && (dStartY >= rgStartY) && (dStartY <= rgEndY)) {
|
2012-08-22 19:56:38 +04:00
|
|
|
if (uint32_t(dStartY - rgStartY) >= cellMap->mRows.Length())
|
2006-12-26 16:55:32 +03:00
|
|
|
ABORT0();
|
2006-12-07 05:32:57 +03:00
|
|
|
const nsCellMap::CellDataArray& row =
|
|
|
|
cellMap->mRows[dStartY - rgStartY];
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t x = dStartX; x <= dEndX; x++) {
|
2006-12-07 05:32:57 +03:00
|
|
|
CellData* cellData = row.SafeElementAt(x);
|
2002-02-19 18:48:28 +03:00
|
|
|
if (cellData && (cellData->IsRowSpan())) {
|
2011-10-17 18:59:28 +04:00
|
|
|
haveSpanner = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dEndY < rgEndY) {
|
2012-08-22 19:56:38 +04:00
|
|
|
if (uint32_t(dEndY + 1 - rgStartY) >= cellMap->mRows.Length())
|
2006-12-26 16:55:32 +03:00
|
|
|
ABORT0();
|
2006-12-07 05:32:57 +03:00
|
|
|
const nsCellMap::CellDataArray& row2 =
|
|
|
|
cellMap->mRows[dEndY + 1 - rgStartY];
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t x = dStartX; x <= dEndX; x++) {
|
2006-12-07 05:32:57 +03:00
|
|
|
CellData* cellData = row2.SafeElementAt(x);
|
2002-02-19 18:48:28 +03:00
|
|
|
if (cellData && (cellData->IsRowSpan())) {
|
2011-10-17 18:59:28 +04:00
|
|
|
haveSpanner = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// check for spanners on the left and right
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t iterStartY = -1;
|
|
|
|
int32_t iterEndY = -1;
|
2002-02-19 18:48:28 +03:00
|
|
|
if ((dStartY >= rgStartY) && (dStartY <= rgEndY)) {
|
|
|
|
// the damage area starts in the row group
|
|
|
|
iterStartY = dStartY;
|
2009-09-16 19:01:36 +04:00
|
|
|
iterEndY = NS_MIN(dEndY, rgEndY);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else if ((dEndY >= rgStartY) && (dEndY <= rgEndY)) {
|
|
|
|
// the damage area ends in the row group
|
|
|
|
iterStartY = rgStartY;
|
2012-01-09 10:37:16 +04:00
|
|
|
iterEndY = dEndY;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else if ((rgStartY >= dStartY) && (rgEndY <= dEndY)) {
|
|
|
|
// the damage area contains the row group
|
|
|
|
iterStartY = rgStartY;
|
|
|
|
iterEndY = rgEndY;
|
|
|
|
}
|
|
|
|
if ((iterStartY >= 0) && (iterEndY >= 0)) {
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t y = iterStartY; y <= iterEndY; y++) {
|
|
|
|
if (uint32_t(y - rgStartY) >= cellMap->mRows.Length())
|
2006-12-26 16:55:32 +03:00
|
|
|
ABORT0();
|
2006-12-07 05:32:57 +03:00
|
|
|
const nsCellMap::CellDataArray& row =
|
|
|
|
cellMap->mRows[y - rgStartY];
|
|
|
|
CellData* cellData = row.SafeElementAt(dStartX);
|
2002-02-19 18:48:28 +03:00
|
|
|
if (cellData && (cellData->IsColSpan())) {
|
2011-10-17 18:59:28 +04:00
|
|
|
haveSpanner = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (dEndX < (numCols - 1)) {
|
2006-12-07 05:32:57 +03:00
|
|
|
cellData = row.SafeElementAt(dEndX + 1);
|
2002-02-19 18:48:28 +03:00
|
|
|
if (cellData && (cellData->IsColSpan())) {
|
2011-10-17 18:59:28 +04:00
|
|
|
haveSpanner = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-03-07 18:33:49 +03:00
|
|
|
if (haveSpanner) {
|
|
|
|
// make the damage area the whole table
|
|
|
|
aRect.x = 0;
|
|
|
|
aRect.y = 0;
|
|
|
|
aRect.width = numCols;
|
|
|
|
aRect.height = numRows;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aRect.x = dStartX;
|
|
|
|
aRect.y = dStartY;
|
|
|
|
aRect.width = 1 + dEndX - dStartX;
|
|
|
|
aRect.height = 1 + dEndY - dStartY;
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
#define ADJACENT true
|
|
|
|
#define HORIZONTAL true
|
2009-06-21 20:31:40 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetTableTopLeftContBCBorder()
|
|
|
|
{
|
|
|
|
BCCellBorder currentBorder;
|
|
|
|
//calculate continuous top first row & rowgroup border: special case
|
|
|
|
//because it must include the table in the collapse
|
|
|
|
if (mTopRow) {
|
2012-07-30 18:20:58 +04:00
|
|
|
currentBorder = CompareBorders(mTableFrame, nullptr, nullptr, mRowGroup,
|
|
|
|
mTopRow, nullptr, mTableIsLTR,
|
2010-01-09 18:33:03 +03:00
|
|
|
NS_SIDE_TOP, !ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
mTopRow->SetContinuousBCBorderWidth(NS_SIDE_TOP, currentBorder.width);
|
|
|
|
}
|
|
|
|
if (mCgAtRight && mColGroup) {
|
|
|
|
//calculate continuous top colgroup border once per colgroup
|
2012-07-30 18:20:58 +04:00
|
|
|
currentBorder = CompareBorders(mTableFrame, mColGroup, nullptr, mRowGroup,
|
|
|
|
mTopRow, nullptr, mTableIsLTR,
|
2010-01-09 18:33:03 +03:00
|
|
|
NS_SIDE_TOP, !ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
mColGroup->SetContinuousBCBorderWidth(NS_SIDE_TOP, currentBorder.width);
|
|
|
|
}
|
|
|
|
if (0 == mColIndex) {
|
2012-07-30 18:20:58 +04:00
|
|
|
currentBorder = CompareBorders(mTableFrame, mColGroup, mLeftCol, nullptr,
|
|
|
|
nullptr, nullptr, mTableIsLTR, NS_SIDE_LEFT,
|
2010-01-09 18:33:03 +03:00
|
|
|
!ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
mTableFrame->SetContinuousLeftBCBorderWidth(currentBorder.width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetRowGroupLeftContBCBorder()
|
|
|
|
{
|
|
|
|
BCCellBorder currentBorder;
|
|
|
|
//get row group continuous borders
|
|
|
|
if (mRgAtBottom && mRowGroup) { //once per row group, so check for bottom
|
|
|
|
currentBorder = CompareBorders(mTableFrame, mColGroup, mLeftCol, mRowGroup,
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr, nullptr, mTableIsLTR, NS_SIDE_LEFT,
|
2010-01-09 18:33:03 +03:00
|
|
|
!ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
mRowGroup->SetContinuousBCBorderWidth(mStartSide, currentBorder.width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetRowGroupRightContBCBorder()
|
|
|
|
{
|
|
|
|
BCCellBorder currentBorder;
|
|
|
|
//get row group continuous borders
|
|
|
|
if (mRgAtBottom && mRowGroup) { //once per mRowGroup, so check for bottom
|
|
|
|
currentBorder = CompareBorders(mTableFrame, mColGroup, mRightCol, mRowGroup,
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr, nullptr, mTableIsLTR, NS_SIDE_RIGHT,
|
2010-01-09 18:33:03 +03:00
|
|
|
ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
mRowGroup->SetContinuousBCBorderWidth(mEndSide, currentBorder.width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetColumnTopRightContBCBorder()
|
|
|
|
{
|
|
|
|
BCCellBorder currentBorder;
|
|
|
|
//calculate column continuous borders
|
|
|
|
//we only need to do this once, so we'll do it only on the first row
|
|
|
|
currentBorder = CompareBorders(mTableFrame, mCurrentColGroupFrame,
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentColFrame, mRowGroup, mTopRow, nullptr,
|
2010-01-09 18:33:03 +03:00
|
|
|
mTableIsLTR, NS_SIDE_TOP, !ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
((nsTableColFrame*) mCurrentColFrame)->SetContinuousBCBorderWidth(NS_SIDE_TOP,
|
|
|
|
currentBorder.width);
|
|
|
|
if (mNumTableCols == GetCellEndColIndex() + 1) {
|
|
|
|
currentBorder = CompareBorders(mTableFrame, mCurrentColGroupFrame,
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentColFrame, nullptr, nullptr, nullptr,
|
2010-01-09 18:33:03 +03:00
|
|
|
mTableIsLTR, NS_SIDE_RIGHT, !ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
else {
|
2012-07-30 18:20:58 +04:00
|
|
|
currentBorder = CompareBorders(nullptr, mCurrentColGroupFrame,
|
|
|
|
mCurrentColFrame, nullptr,nullptr, nullptr,
|
2010-01-09 18:33:03 +03:00
|
|
|
mTableIsLTR, NS_SIDE_RIGHT, !ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
mCurrentColFrame->SetContinuousBCBorderWidth(NS_SIDE_RIGHT,
|
|
|
|
currentBorder.width);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetColumnBottomContBCBorder()
|
|
|
|
{
|
|
|
|
BCCellBorder currentBorder;
|
|
|
|
//get col continuous border
|
|
|
|
currentBorder = CompareBorders(mTableFrame, mCurrentColGroupFrame,
|
|
|
|
mCurrentColFrame, mRowGroup, mBottomRow,
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr, mTableIsLTR, NS_SIDE_BOTTOM, ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
mCurrentColFrame->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM,
|
|
|
|
currentBorder.width);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetColGroupBottomContBCBorder()
|
|
|
|
{
|
|
|
|
BCCellBorder currentBorder;
|
|
|
|
if (mColGroup) {
|
2012-07-30 18:20:58 +04:00
|
|
|
currentBorder = CompareBorders(mTableFrame, mColGroup, nullptr, mRowGroup,
|
|
|
|
mBottomRow, nullptr, mTableIsLTR,
|
2009-06-21 20:31:40 +04:00
|
|
|
NS_SIDE_BOTTOM, ADJACENT);
|
|
|
|
mColGroup->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM, currentBorder.width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetRowGroupBottomContBCBorder()
|
|
|
|
{
|
|
|
|
BCCellBorder currentBorder;
|
|
|
|
if (mRowGroup) {
|
2012-07-30 18:20:58 +04:00
|
|
|
currentBorder = CompareBorders(mTableFrame, nullptr, nullptr, mRowGroup,
|
|
|
|
mBottomRow, nullptr, mTableIsLTR,
|
2009-06-21 20:31:40 +04:00
|
|
|
NS_SIDE_BOTTOM, ADJACENT);
|
|
|
|
mRowGroup->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM, currentBorder.width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetInnerRowGroupBottomContBCBorder(const nsIFrame* aNextRowGroup,
|
|
|
|
nsTableRowFrame* aNextRow)
|
|
|
|
{
|
|
|
|
BCCellBorder currentBorder, adjacentBorder;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
const nsIFrame* rowgroup = (mRgAtBottom) ? mRowGroup : nullptr;
|
|
|
|
currentBorder = CompareBorders(nullptr, nullptr, nullptr, rowgroup, mBottomRow,
|
|
|
|
nullptr, mTableIsLTR, NS_SIDE_BOTTOM, ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
adjacentBorder = CompareBorders(nullptr, nullptr, nullptr, aNextRowGroup,
|
|
|
|
aNextRow, nullptr, mTableIsLTR, NS_SIDE_TOP,
|
2010-01-09 18:33:03 +03:00
|
|
|
!ADJACENT);
|
2011-10-17 18:59:28 +04:00
|
|
|
currentBorder = CompareBorders(false, currentBorder, adjacentBorder,
|
2009-06-21 20:31:40 +04:00
|
|
|
HORIZONTAL);
|
|
|
|
if (aNextRow) {
|
|
|
|
aNextRow->SetContinuousBCBorderWidth(NS_SIDE_TOP, currentBorder.width);
|
|
|
|
}
|
|
|
|
if (mRgAtBottom && mRowGroup) {
|
|
|
|
mRowGroup->SetContinuousBCBorderWidth(NS_SIDE_BOTTOM, currentBorder.width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetRowLeftContBCBorder()
|
|
|
|
{
|
|
|
|
//get row continuous borders
|
|
|
|
if (mCurrentRowFrame) {
|
|
|
|
BCCellBorder currentBorder;
|
|
|
|
currentBorder = CompareBorders(mTableFrame, mColGroup, mLeftCol, mRowGroup,
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentRowFrame, nullptr, mTableIsLTR,
|
2010-01-09 18:33:03 +03:00
|
|
|
NS_SIDE_LEFT, !ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
mCurrentRowFrame->SetContinuousBCBorderWidth(mStartSide,
|
|
|
|
currentBorder.width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetRowRightContBCBorder()
|
|
|
|
{
|
|
|
|
if (mCurrentRowFrame) {
|
|
|
|
BCCellBorder currentBorder;
|
|
|
|
currentBorder = CompareBorders(mTableFrame, mColGroup, mRightCol, mRowGroup,
|
2012-07-30 18:20:58 +04:00
|
|
|
mCurrentRowFrame, nullptr, mTableIsLTR,
|
2010-01-09 18:33:03 +03:00
|
|
|
NS_SIDE_RIGHT, ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
mCurrentRowFrame->SetContinuousBCBorderWidth(mEndSide,
|
|
|
|
currentBorder.width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetTableTopBorderWidth(BCPixelSize aWidth)
|
|
|
|
{
|
2010-03-06 12:53:03 +03:00
|
|
|
mTableBCData->mTopBorderWidth = NS_MAX(mTableBCData->mTopBorderWidth, aWidth);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
BCMapCellInfo::SetTableLeftBorderWidth(int32_t aRowY, BCPixelSize aWidth)
|
2009-06-21 20:31:40 +04:00
|
|
|
{
|
|
|
|
// update the left/right first cell border
|
|
|
|
if (aRowY == 0) {
|
|
|
|
if (mTableIsLTR) {
|
|
|
|
mTableBCData->mLeftCellBorderWidth = aWidth;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mTableBCData->mRightCellBorderWidth = aWidth;
|
|
|
|
}
|
|
|
|
}
|
2010-03-06 12:53:03 +03:00
|
|
|
mTableBCData->mLeftBorderWidth = NS_MAX(mTableBCData->mLeftBorderWidth,
|
|
|
|
aWidth);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
BCMapCellInfo::SetTableRightBorderWidth(int32_t aRowY, BCPixelSize aWidth)
|
2009-06-21 20:31:40 +04:00
|
|
|
{
|
|
|
|
// update the left/right first cell border
|
|
|
|
if (aRowY == 0) {
|
|
|
|
if (mTableIsLTR) {
|
|
|
|
mTableBCData->mRightCellBorderWidth = aWidth;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mTableBCData->mLeftCellBorderWidth = aWidth;
|
|
|
|
}
|
|
|
|
}
|
2010-03-06 12:53:03 +03:00
|
|
|
mTableBCData->mRightBorderWidth = NS_MAX(mTableBCData->mRightBorderWidth,
|
|
|
|
aWidth);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetRightBorderWidths(BCPixelSize aWidth)
|
|
|
|
{
|
|
|
|
// update the borders of the cells and cols affected
|
|
|
|
if (mCell) {
|
2009-09-16 19:01:36 +04:00
|
|
|
mCell->SetBorderWidth(mEndSide, NS_MAX(aWidth,
|
2009-06-21 20:31:40 +04:00
|
|
|
mCell->GetBorderWidth(mEndSide)));
|
|
|
|
}
|
|
|
|
if (mRightCol) {
|
|
|
|
BCPixelSize half = BC_BORDER_LEFT_HALF(aWidth);
|
2009-09-16 19:01:36 +04:00
|
|
|
mRightCol->SetRightBorderWidth(NS_MAX(nscoord(half),
|
2009-06-21 20:31:40 +04:00
|
|
|
mRightCol->GetRightBorderWidth()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetBottomBorderWidths(BCPixelSize aWidth)
|
|
|
|
{
|
|
|
|
// update the borders of the affected cells and rows
|
|
|
|
if (mCell) {
|
2009-09-16 19:01:36 +04:00
|
|
|
mCell->SetBorderWidth(NS_SIDE_BOTTOM, NS_MAX(aWidth,
|
2009-06-21 20:31:40 +04:00
|
|
|
mCell->GetBorderWidth(NS_SIDE_BOTTOM)));
|
|
|
|
}
|
|
|
|
if (mBottomRow) {
|
|
|
|
BCPixelSize half = BC_BORDER_TOP_HALF(aWidth);
|
2009-09-16 19:01:36 +04:00
|
|
|
mBottomRow->SetBottomBCBorderWidth(NS_MAX(nscoord(half),
|
2009-06-21 20:31:40 +04:00
|
|
|
mBottomRow->GetBottomBCBorderWidth()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetTopBorderWidths(BCPixelSize aWidth)
|
|
|
|
{
|
|
|
|
if (mCell) {
|
2009-09-16 19:01:36 +04:00
|
|
|
mCell->SetBorderWidth(NS_SIDE_TOP, NS_MAX(aWidth,
|
2009-06-21 20:31:40 +04:00
|
|
|
mCell->GetBorderWidth(NS_SIDE_TOP)));
|
|
|
|
}
|
|
|
|
if (mTopRow) {
|
|
|
|
BCPixelSize half = BC_BORDER_BOTTOM_HALF(aWidth);
|
2009-09-16 19:01:36 +04:00
|
|
|
mTopRow->SetTopBCBorderWidth(NS_MAX(nscoord(half),
|
|
|
|
mTopRow->GetTopBCBorderWidth()));
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetLeftBorderWidths(BCPixelSize aWidth)
|
|
|
|
{
|
|
|
|
if (mCell) {
|
2009-09-16 19:01:36 +04:00
|
|
|
mCell->SetBorderWidth(mStartSide, NS_MAX(aWidth,
|
2009-06-21 20:31:40 +04:00
|
|
|
mCell->GetBorderWidth(mStartSide)));
|
|
|
|
}
|
|
|
|
if (mLeftCol) {
|
|
|
|
BCPixelSize half = BC_BORDER_RIGHT_HALF(aWidth);
|
2009-09-16 19:01:36 +04:00
|
|
|
mLeftCol->SetLeftBorderWidth(NS_MAX(nscoord(half),
|
|
|
|
mLeftCol->GetLeftBorderWidth()));
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
BCMapCellInfo::SetTableBottomBorderWidth(BCPixelSize aWidth)
|
|
|
|
{
|
2010-03-06 12:53:03 +03:00
|
|
|
mTableBCData->mBottomBorderWidth = NS_MAX(mTableBCData->mBottomBorderWidth,
|
|
|
|
aWidth);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
BCMapCellInfo::SetColumn(int32_t aColX)
|
2009-06-21 20:31:40 +04:00
|
|
|
{
|
|
|
|
mCurrentColFrame = mTableFrame->GetColFrame(aColX);
|
|
|
|
if (!mCurrentColFrame) {
|
|
|
|
NS_ERROR("null mCurrentColFrame");
|
|
|
|
}
|
|
|
|
mCurrentColGroupFrame = static_cast<nsTableColGroupFrame*>
|
|
|
|
(mCurrentColFrame->GetParent());
|
|
|
|
if (!mCurrentColGroupFrame) {
|
|
|
|
NS_ERROR("null mCurrentColGroupFrame");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-09-29 10:19:26 +04:00
|
|
|
BCMapCellInfo::IncrementRow(bool aResetToTopRowOfCell)
|
2009-06-21 20:31:40 +04:00
|
|
|
{
|
|
|
|
mCurrentRowFrame = (aResetToTopRowOfCell) ? mTopRow :
|
|
|
|
mCurrentRowFrame->GetNextRow();
|
|
|
|
}
|
|
|
|
|
|
|
|
BCCellBorder
|
|
|
|
BCMapCellInfo::GetTopEdgeBorder()
|
|
|
|
{
|
|
|
|
return CompareBorders(mTableFrame, mCurrentColGroupFrame, mCurrentColFrame,
|
2010-01-09 18:33:03 +03:00
|
|
|
mRowGroup, mTopRow, mCell, mTableIsLTR, NS_SIDE_TOP,
|
|
|
|
!ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
BCCellBorder
|
|
|
|
BCMapCellInfo::GetBottomEdgeBorder()
|
|
|
|
{
|
|
|
|
return CompareBorders(mTableFrame, mCurrentColGroupFrame, mCurrentColFrame,
|
2010-01-09 18:33:03 +03:00
|
|
|
mRowGroup, mBottomRow, mCell, mTableIsLTR,
|
2009-06-21 20:31:40 +04:00
|
|
|
NS_SIDE_BOTTOM, ADJACENT);
|
|
|
|
}
|
|
|
|
BCCellBorder
|
|
|
|
BCMapCellInfo::GetLeftEdgeBorder()
|
|
|
|
{
|
|
|
|
return CompareBorders(mTableFrame, mColGroup, mLeftCol, mRowGroup,
|
2010-01-09 18:33:03 +03:00
|
|
|
mCurrentRowFrame, mCell, mTableIsLTR, NS_SIDE_LEFT,
|
|
|
|
!ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
BCCellBorder
|
|
|
|
BCMapCellInfo::GetRightEdgeBorder()
|
|
|
|
{
|
|
|
|
return CompareBorders(mTableFrame, mColGroup, mRightCol, mRowGroup,
|
2010-04-27 20:15:01 +04:00
|
|
|
mCurrentRowFrame, mCell, mTableIsLTR, NS_SIDE_RIGHT,
|
2010-01-09 18:33:03 +03:00
|
|
|
ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
BCCellBorder
|
|
|
|
BCMapCellInfo::GetRightInternalBorder()
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
const nsIFrame* cg = (mCgAtRight) ? mColGroup : nullptr;
|
|
|
|
return CompareBorders(nullptr, cg, mRightCol, nullptr, nullptr, mCell,
|
2010-01-09 18:33:03 +03:00
|
|
|
mTableIsLTR, NS_SIDE_RIGHT, ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
BCCellBorder
|
|
|
|
BCMapCellInfo::GetLeftInternalBorder()
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
const nsIFrame* cg = (mCgAtLeft) ? mColGroup : nullptr;
|
|
|
|
return CompareBorders(nullptr, cg, mLeftCol, nullptr, nullptr, mCell,
|
2010-01-09 18:33:03 +03:00
|
|
|
mTableIsLTR, NS_SIDE_LEFT, !ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
BCCellBorder
|
|
|
|
BCMapCellInfo::GetBottomInternalBorder()
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
const nsIFrame* rg = (mRgAtBottom) ? mRowGroup : nullptr;
|
|
|
|
return CompareBorders(nullptr, nullptr, nullptr, rg, mBottomRow, mCell,
|
2010-01-09 18:33:03 +03:00
|
|
|
mTableIsLTR, NS_SIDE_BOTTOM, ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
BCCellBorder
|
|
|
|
BCMapCellInfo::GetTopInternalBorder()
|
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
const nsIFrame* rg = (mRgAtTop) ? mRowGroup : nullptr;
|
|
|
|
return CompareBorders(nullptr, nullptr, nullptr, rg, mTopRow, mCell,
|
2010-01-09 18:33:03 +03:00
|
|
|
mTableIsLTR, NS_SIDE_TOP, !ADJACENT);
|
2009-06-21 20:31:40 +04:00
|
|
|
}
|
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
/* Here is the order for storing border edges in the cell map as a cell is processed. There are
|
2002-02-19 18:48:28 +03:00
|
|
|
n=colspan top and bottom border edges per cell and n=rowspan left and right border edges per cell.
|
|
|
|
|
|
|
|
1) On the top edge of the table, store the top edge. Never store the top edge otherwise, since
|
|
|
|
a bottom edge from a cell above will take care of it.
|
|
|
|
2) On the left edge of the table, store the left edge. Never store the left edge othewise, since
|
|
|
|
a right edge from a cell to the left will take care of it.
|
2010-04-27 20:15:01 +04:00
|
|
|
3) Store the right edge (or edges if a row span)
|
2002-02-19 18:48:28 +03:00
|
|
|
4) Store the bottom edge (or edges if a col span)
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
Since corners are computed with only an array of BCCornerInfo indexed by the number-of-cols, corner
|
|
|
|
calculations are somewhat complicated. Using an array with number-of-rows * number-of-col entries
|
2010-04-27 20:15:01 +04:00
|
|
|
would simplify this, but at an extra in memory cost of nearly 12 bytes per cell map entry. Collapsing
|
2002-02-19 18:48:28 +03:00
|
|
|
borders already have about an extra 8 byte per cell map entry overhead (this could be
|
2010-04-27 20:15:01 +04:00
|
|
|
reduced to 4 bytes if we are willing to not store border widths in nsTableCellFrame), Here are the
|
2002-02-19 18:48:28 +03:00
|
|
|
rules in priority order for storing cornes in the cell map as a cell is processed. top-left means the
|
2010-04-27 20:15:01 +04:00
|
|
|
left endpoint of the border edge on the top of the cell. There are n=colspan top and bottom border
|
2002-02-19 18:48:28 +03:00
|
|
|
edges per cell and n=rowspan left and right border edges per cell.
|
|
|
|
|
|
|
|
1) On the top edge of the table, store the top-left corner, unless on the left edge of the table.
|
|
|
|
Never store the top-right corner, since it will get stored as a right-top corner.
|
|
|
|
2) On the left edge of the table, store the left-top corner. Never store the left-bottom corner,
|
|
|
|
since it will get stored as a bottom-left corner.
|
|
|
|
3) Store the right-top corner if (a) it is the top right corner of the table or (b) it is not on
|
2010-04-27 20:15:01 +04:00
|
|
|
the top edge of the table. Never store the right-bottom corner since it will get stored as a
|
2002-02-19 18:48:28 +03:00
|
|
|
bottom-right corner.
|
2010-04-27 20:15:01 +04:00
|
|
|
4) Store the bottom-right corner, if it is the bottom right corner of the table. Never store it
|
2002-02-19 18:48:28 +03:00
|
|
|
otherwise, since it will get stored as either a right-top corner by a cell below or
|
|
|
|
a bottom-left corner from a cell to the right.
|
2010-04-27 20:15:01 +04:00
|
|
|
5) Store the bottom-left corner, if (a) on the bottom edge of the table or (b) if the left edge hits
|
|
|
|
the top side of a colspan in its interior. Never store the corner otherwise, since it will
|
2002-02-19 18:48:28 +03:00
|
|
|
get stored as a right-top corner by a cell from below.
|
2004-12-27 21:43:55 +03:00
|
|
|
|
|
|
|
XXX the BC-RTL hack - The correct fix would be a rewrite as described in bug 203686.
|
|
|
|
In order to draw borders in rtl conditions somehow correct, the existing structure which relies
|
|
|
|
heavily on the assumption that the next cell sibling will be on the right side, has been modified.
|
|
|
|
We flip the border during painting and during style lookup. Look for tableIsLTR for places where
|
|
|
|
the flipping is done.
|
2002-02-19 18:48:28 +03:00
|
|
|
*/
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
|
|
|
|
// Calc the dominant border at every cell edge and corner within the current damage area
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2005-02-07 04:58:25 +03:00
|
|
|
nsTableFrame::CalcBCBorders()
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
NS_ASSERTION(IsBorderCollapse(),
|
|
|
|
"calling CalcBCBorders on separated-border table");
|
2002-02-19 18:48:28 +03:00
|
|
|
nsTableCellMap* tableCellMap = GetCellMap(); if (!tableCellMap) ABORT0();
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t numRows = GetRowCount();
|
|
|
|
int32_t numCols = GetColCount();
|
2006-09-02 12:48:39 +04:00
|
|
|
if (!numRows || !numCols)
|
|
|
|
return; // nothing to do
|
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
// Get the property holding the table damage area and border widths
|
2011-10-27 17:58:44 +04:00
|
|
|
BCPropertyData* propData = GetBCProperty();
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!propData) ABORT0();
|
2002-04-07 02:56:45 +04:00
|
|
|
|
2010-04-27 20:15:01 +04:00
|
|
|
|
|
|
|
|
|
|
|
// calculate an expanded damage area
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect damageArea(propData->mDamageArea);
|
2002-02-19 18:48:28 +03:00
|
|
|
ExpandBCDamageArea(damageArea);
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// segments that are on the table border edges need
|
|
|
|
// to be initialized only once
|
2011-09-29 10:19:26 +04:00
|
|
|
bool tableBorderReset[4];
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t sideX = NS_SIDE_TOP; sideX <= NS_SIDE_LEFT; sideX++) {
|
2011-10-17 18:59:28 +04:00
|
|
|
tableBorderReset[sideX] = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// vertical borders indexed in x-direction (cols)
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCellBorders lastVerBorders(damageArea.width + 1, damageArea.x);
|
|
|
|
if (!lastVerBorders.borders) ABORT0();
|
2002-02-19 18:48:28 +03:00
|
|
|
BCCellBorder lastTopBorder, lastBottomBorder;
|
|
|
|
// horizontal borders indexed in x-direction (cols)
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCellBorders lastBottomBorders(damageArea.width + 1, damageArea.x);
|
|
|
|
if (!lastBottomBorders.borders) ABORT0();
|
2011-09-29 10:19:26 +04:00
|
|
|
bool startSeg;
|
|
|
|
bool gotRowBorder = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
BCMapCellInfo info(this), ajaInfo(this);
|
|
|
|
|
2004-10-09 16:04:52 +04:00
|
|
|
BCCellBorder currentBorder, adjacentBorder;
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCorners topCorners(damageArea.width + 1, damageArea.x);
|
|
|
|
if (!topCorners.corners) ABORT0();
|
|
|
|
BCCorners bottomCorners(damageArea.width + 1, damageArea.x);
|
|
|
|
if (!bottomCorners.corners) ABORT0();
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
BCMapCellIterator iter(this, damageArea);
|
2002-02-19 18:48:28 +03:00
|
|
|
for (iter.First(info); !iter.mAtEnd; iter.Next(info)) {
|
|
|
|
// see if lastTopBorder, lastBottomBorder need to be reset
|
2010-04-27 20:15:01 +04:00
|
|
|
if (iter.IsNewRow()) {
|
2011-10-17 18:59:28 +04:00
|
|
|
gotRowBorder = false;
|
2009-06-21 20:31:40 +04:00
|
|
|
lastTopBorder.Reset(info.mRowIndex, info.mRowSpan);
|
|
|
|
lastBottomBorder.Reset(info.GetCellEndRowIndex() + 1, info.mRowSpan);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
else if (info.mColIndex > damageArea.x) {
|
|
|
|
lastBottomBorder = lastBottomBorders[info.mColIndex - 1];
|
|
|
|
if (info.mRowIndex >
|
|
|
|
(lastBottomBorder.rowIndex - lastBottomBorder.rowSpan)) {
|
2002-02-19 18:48:28 +03:00
|
|
|
// the top border's left edge butts against the middle of a rowspan
|
2009-06-21 20:31:40 +04:00
|
|
|
lastTopBorder.Reset(info.mRowIndex, info.mRowSpan);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
if (lastBottomBorder.rowIndex > (info.GetCellEndRowIndex() + 1)) {
|
2002-02-19 18:48:28 +03:00
|
|
|
// the bottom border's left edge butts against the middle of a rowspan
|
2009-06-21 20:31:40 +04:00
|
|
|
lastBottomBorder.Reset(info.GetCellEndRowIndex() + 1, info.mRowSpan);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// find the dominant border considering the cell's top border and the table,
|
|
|
|
// row group, row if the border is at the top of the table, otherwise it was
|
|
|
|
// processed in a previous row
|
|
|
|
if (0 == info.mRowIndex) {
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!tableBorderReset[NS_SIDE_TOP]) {
|
|
|
|
propData->mTopBorderWidth = 0;
|
2011-10-17 18:59:28 +04:00
|
|
|
tableBorderReset[NS_SIDE_TOP] = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t colX = info.mColIndex; colX <= info.GetCellEndColIndex();
|
2009-06-21 20:31:40 +04:00
|
|
|
colX++) {
|
|
|
|
info.SetColumn(colX);
|
|
|
|
currentBorder = info.GetTopEdgeBorder();
|
2010-04-27 20:15:01 +04:00
|
|
|
// update/store the top left & top right corners of the seg
|
2002-02-19 18:48:28 +03:00
|
|
|
BCCornerInfo& tlCorner = topCorners[colX]; // top left
|
|
|
|
if (0 == colX) {
|
2009-06-21 20:31:40 +04:00
|
|
|
// we are on right hand side of the corner
|
|
|
|
tlCorner.Set(NS_SIDE_RIGHT, currentBorder);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
2004-10-09 16:04:52 +04:00
|
|
|
tlCorner.Update(NS_SIDE_RIGHT, currentBorder);
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderCorner(eTopLeft, *iter.mCellMap, 0, 0, colX,
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side(tlCorner.ownerSide),
|
|
|
|
tlCorner.subWidth,
|
2009-06-21 20:31:40 +04:00
|
|
|
tlCorner.bevel);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2004-10-09 16:04:52 +04:00
|
|
|
topCorners[colX + 1].Set(NS_SIDE_LEFT, currentBorder); // top right
|
2002-02-19 18:48:28 +03:00
|
|
|
// update lastTopBorder and see if a new segment starts
|
2004-10-09 16:04:52 +04:00
|
|
|
startSeg = SetHorBorder(currentBorder, tlCorner, lastTopBorder);
|
|
|
|
// store the border segment in the cell map
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderEdge(NS_SIDE_TOP, *iter.mCellMap, 0, 0, colX,
|
|
|
|
1, currentBorder.owner,
|
|
|
|
currentBorder.width, startSeg);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
info.SetTableTopBorderWidth(currentBorder.width);
|
|
|
|
info.SetTopBorderWidths(currentBorder.width);
|
|
|
|
info.SetColumnTopRightContBCBorder();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
info.SetTableTopLeftContBCBorder();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
2009-06-21 20:31:40 +04:00
|
|
|
// see if the top border needs to be the start of a segment due to a
|
|
|
|
// vertical border owning the corner
|
|
|
|
if (info.mColIndex > 0) {
|
|
|
|
BCData& data = info.mCellData->mData;
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!data.IsTopStart()) {
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side cornerSide;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool bevel;
|
2002-02-19 18:48:28 +03:00
|
|
|
data.GetCorner(cornerSide, bevel);
|
|
|
|
if ((NS_SIDE_TOP == cornerSide) || (NS_SIDE_BOTTOM == cornerSide)) {
|
2011-10-17 18:59:28 +04:00
|
|
|
data.SetTopStart(true);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// find the dominant border considering the cell's left border and the
|
|
|
|
// table, col group, col if the border is at the left of the table,
|
|
|
|
// otherwise it was processed in a previous col
|
|
|
|
if (0 == info.mColIndex) {
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!tableBorderReset[NS_SIDE_LEFT]) {
|
|
|
|
propData->mLeftBorderWidth = 0;
|
2011-10-17 18:59:28 +04:00
|
|
|
tableBorderReset[NS_SIDE_LEFT] = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
info.mCurrentRowFrame = nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t rowY = info.mRowIndex; rowY <= info.GetCellEndRowIndex();
|
2009-06-21 20:31:40 +04:00
|
|
|
rowY++) {
|
|
|
|
info.IncrementRow(rowY == info.mRowIndex);
|
|
|
|
currentBorder = info.GetLeftEdgeBorder();
|
|
|
|
BCCornerInfo& tlCorner = (0 == rowY) ? topCorners[0] : bottomCorners[0];
|
2004-10-09 16:04:52 +04:00
|
|
|
tlCorner.Update(NS_SIDE_BOTTOM, currentBorder);
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderCorner(eTopLeft, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart, rowY, 0,
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side(tlCorner.ownerSide),
|
|
|
|
tlCorner.subWidth,
|
2009-06-21 20:31:40 +04:00
|
|
|
tlCorner.bevel);
|
|
|
|
bottomCorners[0].Set(NS_SIDE_TOP, currentBorder); // bottom left
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
// update lastVerBordersBorder and see if a new segment starts
|
2004-10-09 16:04:52 +04:00
|
|
|
startSeg = SetBorder(currentBorder, lastVerBorders[0]);
|
2010-04-27 20:15:01 +04:00
|
|
|
// store the border segment in the cell map
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderEdge(NS_SIDE_LEFT, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart, rowY, info.mColIndex,
|
|
|
|
1, currentBorder.owner,
|
|
|
|
currentBorder.width, startSeg);
|
|
|
|
info.SetTableLeftBorderWidth(rowY , currentBorder.width);
|
|
|
|
info.SetLeftBorderWidths(currentBorder.width);
|
|
|
|
info.SetRowLeftContBCBorder();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
info.SetRowGroupLeftContBCBorder();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// find the dominant border considering the cell's right border, adjacent
|
|
|
|
// cells and the table, row group, row
|
|
|
|
if (info.mNumTableCols == info.GetCellEndColIndex() + 1) {
|
|
|
|
// touches right edge of table
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!tableBorderReset[NS_SIDE_RIGHT]) {
|
|
|
|
propData->mRightBorderWidth = 0;
|
2011-10-17 18:59:28 +04:00
|
|
|
tableBorderReset[NS_SIDE_RIGHT] = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
info.mCurrentRowFrame = nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t rowY = info.mRowIndex; rowY <= info.GetCellEndRowIndex();
|
2009-06-21 20:31:40 +04:00
|
|
|
rowY++) {
|
|
|
|
info.IncrementRow(rowY == info.mRowIndex);
|
|
|
|
currentBorder = info.GetRightEdgeBorder();
|
2010-04-27 20:15:01 +04:00
|
|
|
// update/store the top right & bottom right corners
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCornerInfo& trCorner = (0 == rowY) ?
|
|
|
|
topCorners[info.GetCellEndColIndex() + 1] :
|
|
|
|
bottomCorners[info.GetCellEndColIndex() + 1];
|
2004-10-09 16:04:52 +04:00
|
|
|
trCorner.Update(NS_SIDE_BOTTOM, currentBorder); // top right
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderCorner(eTopRight, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart, rowY,
|
|
|
|
info.GetCellEndColIndex(),
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side(trCorner.ownerSide),
|
|
|
|
trCorner.subWidth,
|
2009-06-21 20:31:40 +04:00
|
|
|
trCorner.bevel);
|
|
|
|
BCCornerInfo& brCorner = bottomCorners[info.GetCellEndColIndex() + 1];
|
2004-10-09 16:04:52 +04:00
|
|
|
brCorner.Set(NS_SIDE_TOP, currentBorder); // bottom right
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderCorner(eBottomRight, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart, rowY,
|
|
|
|
info.GetCellEndColIndex(),
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side(brCorner.ownerSide),
|
|
|
|
brCorner.subWidth,
|
2009-06-21 20:31:40 +04:00
|
|
|
brCorner.bevel);
|
2002-02-19 18:48:28 +03:00
|
|
|
// update lastVerBorders and see if a new segment starts
|
2009-06-21 20:31:40 +04:00
|
|
|
startSeg = SetBorder(currentBorder,
|
|
|
|
lastVerBorders[info.GetCellEndColIndex() + 1]);
|
2002-02-19 18:48:28 +03:00
|
|
|
// store the border segment in the cell map and update cellBorders
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderEdge(NS_SIDE_RIGHT, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart, rowY,
|
|
|
|
info.GetCellEndColIndex(), 1,
|
|
|
|
currentBorder.owner, currentBorder.width,
|
|
|
|
startSeg);
|
|
|
|
info.SetTableRightBorderWidth(rowY, currentBorder.width);
|
|
|
|
info.SetRightBorderWidths(currentBorder.width);
|
|
|
|
info.SetRowRightContBCBorder();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
info.SetRowGroupRightContBCBorder();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t segLength = 0;
|
2009-06-21 20:31:40 +04:00
|
|
|
BCMapCellInfo priorAjaInfo(this);
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t rowY = info.mRowIndex; rowY <= info.GetCellEndRowIndex();
|
2009-06-21 20:31:40 +04:00
|
|
|
rowY += segLength) {
|
|
|
|
iter.PeekRight(info, rowY, ajaInfo);
|
|
|
|
currentBorder = info.GetRightInternalBorder();
|
|
|
|
adjacentBorder = ajaInfo.GetLeftInternalBorder();
|
|
|
|
currentBorder = CompareBorders(!CELL_CORNER, currentBorder,
|
|
|
|
adjacentBorder, !HORIZONTAL);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-09-16 19:01:36 +04:00
|
|
|
segLength = NS_MAX(1, ajaInfo.mRowIndex + ajaInfo.mRowSpan - rowY);
|
|
|
|
segLength = NS_MIN(segLength, info.mRowIndex + info.mRowSpan - rowY);
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
// update lastVerBorders and see if a new segment starts
|
2009-06-21 20:31:40 +04:00
|
|
|
startSeg = SetBorder(currentBorder,
|
|
|
|
lastVerBorders[info.GetCellEndColIndex() + 1]);
|
2002-02-19 18:48:28 +03:00
|
|
|
// store the border segment in the cell map and update cellBorders
|
2009-06-21 20:31:40 +04:00
|
|
|
if (info.GetCellEndColIndex() < damageArea.XMost() &&
|
|
|
|
rowY >= damageArea.y && rowY < damageArea.YMost()) {
|
|
|
|
tableCellMap->SetBCBorderEdge(NS_SIDE_RIGHT, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart, rowY,
|
|
|
|
info.GetCellEndColIndex(), segLength,
|
|
|
|
currentBorder.owner,
|
|
|
|
currentBorder.width, startSeg);
|
|
|
|
info.SetRightBorderWidths(currentBorder.width);
|
|
|
|
ajaInfo.SetLeftBorderWidths(currentBorder.width);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
// update the top right corner
|
2011-09-29 10:19:26 +04:00
|
|
|
bool hitsSpanOnRight = (rowY > ajaInfo.mRowIndex) &&
|
2009-06-21 20:31:40 +04:00
|
|
|
(rowY < ajaInfo.mRowIndex + ajaInfo.mRowSpan);
|
|
|
|
BCCornerInfo* trCorner = ((0 == rowY) || hitsSpanOnRight) ?
|
|
|
|
&topCorners[info.GetCellEndColIndex() + 1] :
|
|
|
|
&bottomCorners[info.GetCellEndColIndex() + 1];
|
2004-10-09 16:04:52 +04:00
|
|
|
trCorner->Update(NS_SIDE_BOTTOM, currentBorder);
|
2009-06-21 20:31:40 +04:00
|
|
|
// if this is not the first time through,
|
|
|
|
// consider the segment to the right
|
|
|
|
if (rowY != info.mRowIndex) {
|
|
|
|
currentBorder = priorAjaInfo.GetBottomInternalBorder();
|
|
|
|
adjacentBorder = ajaInfo.GetTopInternalBorder();
|
|
|
|
currentBorder = CompareBorders(!CELL_CORNER, currentBorder,
|
|
|
|
adjacentBorder, HORIZONTAL);
|
2004-10-09 16:04:52 +04:00
|
|
|
trCorner->Update(NS_SIDE_RIGHT, currentBorder);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
// store the top right corner in the cell map
|
2009-06-21 20:31:40 +04:00
|
|
|
if (info.GetCellEndColIndex() < damageArea.XMost() &&
|
|
|
|
rowY >= damageArea.y) {
|
|
|
|
if (0 != rowY) {
|
|
|
|
tableCellMap->SetBCBorderCorner(eTopRight, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart, rowY,
|
|
|
|
info.GetCellEndColIndex(),
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side(trCorner->ownerSide),
|
2009-06-21 20:31:40 +04:00
|
|
|
trCorner->subWidth,
|
|
|
|
trCorner->bevel);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
// store any corners this cell spans together with the aja cell
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t rX = rowY + 1; rX < rowY + segLength; rX++) {
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderCorner(eBottomRight, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart, rX,
|
|
|
|
info.GetCellEndColIndex(),
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side(trCorner->ownerSide),
|
2011-10-17 18:59:28 +04:00
|
|
|
trCorner->subWidth, false);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// update bottom right corner, topCorners, bottomCorners
|
2009-06-21 20:31:40 +04:00
|
|
|
hitsSpanOnRight = (rowY + segLength <
|
|
|
|
ajaInfo.mRowIndex + ajaInfo.mRowSpan);
|
|
|
|
BCCornerInfo& brCorner = (hitsSpanOnRight) ?
|
|
|
|
topCorners[info.GetCellEndColIndex() + 1] :
|
|
|
|
bottomCorners[info.GetCellEndColIndex() + 1];
|
2004-10-09 16:04:52 +04:00
|
|
|
brCorner.Set(NS_SIDE_TOP, currentBorder);
|
2002-02-19 18:48:28 +03:00
|
|
|
priorAjaInfo = ajaInfo;
|
|
|
|
}
|
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t colX = info.mColIndex + 1; colX <= info.GetCellEndColIndex();
|
2009-06-21 20:31:40 +04:00
|
|
|
colX++) {
|
2004-10-09 16:04:52 +04:00
|
|
|
lastVerBorders[colX].Reset(0,1);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// find the dominant border considering the cell's bottom border, adjacent
|
|
|
|
// cells and the table, row group, row
|
|
|
|
if (info.mNumTableRows == info.GetCellEndRowIndex() + 1) {
|
|
|
|
// touches bottom edge of table
|
2002-02-19 18:48:28 +03:00
|
|
|
if (!tableBorderReset[NS_SIDE_BOTTOM]) {
|
|
|
|
propData->mBottomBorderWidth = 0;
|
2011-10-17 18:59:28 +04:00
|
|
|
tableBorderReset[NS_SIDE_BOTTOM] = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t colX = info.mColIndex; colX <= info.GetCellEndColIndex();
|
2009-06-21 20:31:40 +04:00
|
|
|
colX++) {
|
|
|
|
info.SetColumn(colX);
|
|
|
|
currentBorder = info.GetBottomEdgeBorder();
|
2010-04-27 20:15:01 +04:00
|
|
|
// update/store the bottom left & bottom right corners
|
2002-02-19 18:48:28 +03:00
|
|
|
BCCornerInfo& blCorner = bottomCorners[colX]; // bottom left
|
2004-10-09 16:04:52 +04:00
|
|
|
blCorner.Update(NS_SIDE_RIGHT, currentBorder);
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderCorner(eBottomLeft, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart,
|
|
|
|
info.GetCellEndRowIndex(),
|
2010-04-27 20:15:02 +04:00
|
|
|
colX,
|
|
|
|
mozilla::css::Side(blCorner.ownerSide),
|
2009-06-21 20:31:40 +04:00
|
|
|
blCorner.subWidth, blCorner.bevel);
|
2002-02-19 18:48:28 +03:00
|
|
|
BCCornerInfo& brCorner = bottomCorners[colX + 1]; // bottom right
|
2004-10-09 16:04:52 +04:00
|
|
|
brCorner.Update(NS_SIDE_LEFT, currentBorder);
|
2009-06-21 20:31:40 +04:00
|
|
|
if (info.mNumTableCols == colX + 1) { // lower right corner of the table
|
|
|
|
tableCellMap->SetBCBorderCorner(eBottomRight, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart,
|
|
|
|
info.GetCellEndRowIndex(),colX,
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side(brCorner.ownerSide),
|
|
|
|
brCorner.subWidth,
|
2011-10-17 18:59:28 +04:00
|
|
|
brCorner.bevel, true);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
// update lastBottomBorder and see if a new segment starts
|
2004-10-09 16:04:52 +04:00
|
|
|
startSeg = SetHorBorder(currentBorder, blCorner, lastBottomBorder);
|
2010-04-27 20:15:01 +04:00
|
|
|
if (!startSeg) {
|
2009-06-21 20:31:40 +04:00
|
|
|
// make sure that we did not compare apples to oranges i.e. the
|
|
|
|
// current border should be a continuation of the lastBottomBorder,
|
|
|
|
// as it is a bottom border
|
|
|
|
// add 1 to the info.GetCellEndRowIndex()
|
|
|
|
startSeg = (lastBottomBorder.rowIndex !=
|
|
|
|
(info.GetCellEndRowIndex() + 1));
|
2003-02-22 22:24:49 +03:00
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
// store the border segment in the cell map and update cellBorders
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderEdge(NS_SIDE_BOTTOM, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart,
|
|
|
|
info.GetCellEndRowIndex(),
|
|
|
|
colX, 1, currentBorder.owner,
|
|
|
|
currentBorder.width, startSeg);
|
2002-02-19 18:48:28 +03:00
|
|
|
// update lastBottomBorders
|
2009-06-21 20:31:40 +04:00
|
|
|
lastBottomBorder.rowIndex = info.GetCellEndRowIndex() + 1;
|
|
|
|
lastBottomBorder.rowSpan = info.mRowSpan;
|
2002-02-19 18:48:28 +03:00
|
|
|
lastBottomBorders[colX] = lastBottomBorder;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
info.SetBottomBorderWidths(currentBorder.width);
|
|
|
|
info.SetTableBottomBorderWidth(currentBorder.width);
|
|
|
|
info.SetColumnBottomContBCBorder();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
info.SetRowGroupBottomContBCBorder();
|
|
|
|
info.SetColGroupBottomContBCBorder();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t segLength = 0;
|
|
|
|
for (int32_t colX = info.mColIndex; colX <= info.GetCellEndColIndex();
|
2009-06-21 20:31:40 +04:00
|
|
|
colX += segLength) {
|
2002-02-19 18:48:28 +03:00
|
|
|
iter.PeekBottom(info, colX, ajaInfo);
|
2009-06-21 20:31:40 +04:00
|
|
|
currentBorder = info.GetBottomInternalBorder();
|
|
|
|
adjacentBorder = ajaInfo.GetTopInternalBorder();
|
|
|
|
currentBorder = CompareBorders(!CELL_CORNER, currentBorder,
|
|
|
|
adjacentBorder, HORIZONTAL);
|
2009-09-16 19:01:36 +04:00
|
|
|
segLength = NS_MAX(1, ajaInfo.mColIndex + ajaInfo.mColSpan - colX);
|
|
|
|
segLength = NS_MIN(segLength, info.mColIndex + info.mColSpan - colX);
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
// update, store the bottom left corner
|
|
|
|
BCCornerInfo& blCorner = bottomCorners[colX]; // bottom left
|
2011-09-29 10:19:26 +04:00
|
|
|
bool hitsSpanBelow = (colX > ajaInfo.mColIndex) &&
|
2009-06-21 20:31:40 +04:00
|
|
|
(colX < ajaInfo.mColIndex + ajaInfo.mColSpan);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool update = true;
|
2009-06-21 20:31:40 +04:00
|
|
|
if ((colX == info.mColIndex) && (colX > damageArea.x)) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t prevRowIndex = lastBottomBorders[colX - 1].rowIndex;
|
2009-06-21 20:31:40 +04:00
|
|
|
if (prevRowIndex > info.GetCellEndRowIndex() + 1) {
|
|
|
|
// hits a rowspan on the right
|
2011-10-17 18:59:28 +04:00
|
|
|
update = false;
|
2009-06-21 20:31:40 +04:00
|
|
|
// the corner was taken care of during the cell on the left
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
else if (prevRowIndex < info.GetCellEndRowIndex() + 1) {
|
|
|
|
// spans below the cell to the left
|
2002-02-19 18:48:28 +03:00
|
|
|
topCorners[colX] = blCorner;
|
2004-10-09 16:04:52 +04:00
|
|
|
blCorner.Set(NS_SIDE_RIGHT, currentBorder);
|
2011-10-17 18:59:28 +04:00
|
|
|
update = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (update) {
|
2004-10-09 16:04:52 +04:00
|
|
|
blCorner.Update(NS_SIDE_RIGHT, currentBorder);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
if (info.GetCellEndRowIndex() < damageArea.YMost() &&
|
|
|
|
(colX >= damageArea.x)) {
|
2002-02-19 18:48:28 +03:00
|
|
|
if (hitsSpanBelow) {
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderCorner(eBottomLeft, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart,
|
|
|
|
info.GetCellEndRowIndex(), colX,
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side(blCorner.ownerSide),
|
2009-06-21 20:31:40 +04:00
|
|
|
blCorner.subWidth, blCorner.bevel);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
// store any corners this cell spans together with the aja cell
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t cX = colX + 1; cX < colX + segLength; cX++) {
|
2004-03-09 09:48:35 +03:00
|
|
|
BCCornerInfo& corner = bottomCorners[cX];
|
2004-10-09 16:04:52 +04:00
|
|
|
corner.Set(NS_SIDE_RIGHT, currentBorder);
|
2009-06-21 20:31:40 +04:00
|
|
|
tableCellMap->SetBCBorderCorner(eBottomLeft, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart,
|
|
|
|
info.GetCellEndRowIndex(), cX,
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side(corner.ownerSide),
|
|
|
|
corner.subWidth,
|
2011-10-17 18:59:28 +04:00
|
|
|
false);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// update lastBottomBorders and see if a new segment starts
|
2004-10-09 16:04:52 +04:00
|
|
|
startSeg = SetHorBorder(currentBorder, blCorner, lastBottomBorder);
|
2010-04-27 20:15:01 +04:00
|
|
|
if (!startSeg) {
|
2009-06-21 20:31:40 +04:00
|
|
|
// make sure that we did not compare apples to oranges i.e. the
|
|
|
|
// current border should be a continuation of the lastBottomBorder,
|
|
|
|
// as it is a bottom border
|
|
|
|
// add 1 to the info.GetCellEndRowIndex()
|
|
|
|
startSeg = (lastBottomBorder.rowIndex !=
|
|
|
|
info.GetCellEndRowIndex() + 1);
|
2003-02-22 22:24:49 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
lastBottomBorder.rowIndex = info.GetCellEndRowIndex() + 1;
|
|
|
|
lastBottomBorder.rowSpan = info.mRowSpan;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t cX = colX; cX < colX + segLength; cX++) {
|
2002-02-19 18:48:28 +03:00
|
|
|
lastBottomBorders[cX] = lastBottomBorder;
|
|
|
|
}
|
|
|
|
|
|
|
|
// store the border segment the cell map and update cellBorders
|
2009-06-21 20:31:40 +04:00
|
|
|
if (info.GetCellEndRowIndex() < damageArea.YMost() &&
|
|
|
|
(colX >= damageArea.x) &&
|
|
|
|
(colX < damageArea.XMost())) {
|
|
|
|
tableCellMap->SetBCBorderEdge(NS_SIDE_BOTTOM, *iter.mCellMap,
|
|
|
|
iter.mRowGroupStart,
|
|
|
|
info.GetCellEndRowIndex(),
|
|
|
|
colX, segLength, currentBorder.owner,
|
|
|
|
currentBorder.width, startSeg);
|
|
|
|
info.SetBottomBorderWidths(currentBorder.width);
|
|
|
|
ajaInfo.SetTopBorderWidths(currentBorder.width);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
// update bottom right corner
|
|
|
|
BCCornerInfo& brCorner = bottomCorners[colX + segLength];
|
2004-10-09 16:04:52 +04:00
|
|
|
brCorner.Update(NS_SIDE_LEFT, currentBorder);
|
2004-03-09 09:48:35 +03:00
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
if (!gotRowBorder && 1 == info.mRowSpan &&
|
|
|
|
(ajaInfo.mTopRow || info.mRgAtBottom)) {
|
2004-03-09 09:48:35 +03:00
|
|
|
//get continuous row/row group border
|
|
|
|
//we need to check the row group's bottom border if this is
|
|
|
|
//the last row in the row group, but only a cell with rowspan=1
|
|
|
|
//will know whether *this* row is at the bottom
|
2009-06-21 20:31:40 +04:00
|
|
|
const nsIFrame* nextRowGroup = (ajaInfo.mRgAtTop) ? ajaInfo.mRowGroup :
|
2012-07-30 18:20:58 +04:00
|
|
|
nullptr;
|
2009-06-21 20:31:40 +04:00
|
|
|
info.SetInnerRowGroupBottomContBCBorder(nextRowGroup, ajaInfo.mTopRow);
|
2011-10-17 18:59:28 +04:00
|
|
|
gotRowBorder = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-21 20:31:40 +04:00
|
|
|
// see if the cell to the right had a rowspan and its lower left border
|
|
|
|
// needs be joined with this one's bottom
|
|
|
|
// if there is a cell to the right and the cell to right was a rowspan
|
|
|
|
if ((info.mNumTableCols != info.GetCellEndColIndex() + 1) &&
|
|
|
|
(lastBottomBorders[info.GetCellEndColIndex() + 1].rowSpan > 1)) {
|
|
|
|
BCCornerInfo& corner = bottomCorners[info.GetCellEndColIndex() + 1];
|
|
|
|
if ((NS_SIDE_TOP != corner.ownerSide) &&
|
|
|
|
(NS_SIDE_BOTTOM != corner.ownerSide)) {
|
|
|
|
// not a vertical owner
|
2004-03-09 09:48:35 +03:00
|
|
|
BCCellBorder& thisBorder = lastBottomBorder;
|
2009-06-21 20:31:40 +04:00
|
|
|
BCCellBorder& nextBorder = lastBottomBorders[info.mColIndex + 1];
|
|
|
|
if ((thisBorder.color == nextBorder.color) &&
|
|
|
|
(thisBorder.width == nextBorder.width) &&
|
2002-02-19 18:48:28 +03:00
|
|
|
(thisBorder.style == nextBorder.style)) {
|
2009-06-21 20:31:40 +04:00
|
|
|
// set the flag on the next border indicating it is not the start of a
|
|
|
|
// new segment
|
2002-02-19 18:48:28 +03:00
|
|
|
if (iter.mCellMap) {
|
2011-02-16 16:14:18 +03:00
|
|
|
tableCellMap->ResetTopStart(NS_SIDE_BOTTOM, *iter.mCellMap,
|
|
|
|
info.GetCellEndRowIndex(),
|
|
|
|
info.GetCellEndColIndex() + 1);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-06-21 20:31:40 +04:00
|
|
|
} // for (iter.First(info); info.mCell; iter.Next(info)) {
|
2002-02-19 18:48:28 +03:00
|
|
|
// reset the bc flag and damage area
|
2011-10-17 18:59:28 +04:00
|
|
|
SetNeedToCalcBCBorders(false);
|
2012-01-23 02:48:34 +04:00
|
|
|
propData->mDamageArea = nsIntRect(0,0,0,0);
|
2004-03-03 20:45:50 +03:00
|
|
|
#ifdef DEBUG_TABLE_CELLMAP
|
|
|
|
mCellMap->Dump();
|
|
|
|
#endif
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
class BCPaintBorderIterator;
|
|
|
|
|
|
|
|
struct BCVerticalSeg
|
|
|
|
{
|
|
|
|
BCVerticalSeg();
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
void Start(BCPaintBorderIterator& aIter,
|
|
|
|
BCBorderOwner aBorderOwner,
|
|
|
|
BCPixelSize aVerSegWidth,
|
|
|
|
BCPixelSize aHorSegHeight);
|
|
|
|
|
|
|
|
void Initialize(BCPaintBorderIterator& aIter);
|
|
|
|
void GetBottomCorner(BCPaintBorderIterator& aIter,
|
|
|
|
BCPixelSize aHorSegHeight);
|
|
|
|
|
|
|
|
|
|
|
|
void Paint(BCPaintBorderIterator& aIter,
|
2011-04-08 05:04:40 +04:00
|
|
|
nsRenderingContext& aRenderingContext,
|
2009-11-05 12:26:00 +03:00
|
|
|
BCPixelSize aHorSegHeight);
|
|
|
|
void AdvanceOffsetY();
|
|
|
|
void IncludeCurrentBorder(BCPaintBorderIterator& aIter);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
union {
|
|
|
|
nsTableColFrame* mCol;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mColWidth;
|
2009-11-05 12:26:00 +03:00
|
|
|
};
|
|
|
|
nscoord mOffsetX; // x-offset with respect to the table edge
|
|
|
|
nscoord mOffsetY; // y-offset with respect to the table edge
|
|
|
|
nscoord mLength; // vertical length including corners
|
|
|
|
BCPixelSize mWidth; // width in pixels
|
|
|
|
|
|
|
|
nsTableCellFrame* mAjaCell; // previous sibling to the first cell
|
|
|
|
// where the segment starts, it can be
|
|
|
|
// the owner of a segment
|
|
|
|
nsTableCellFrame* mFirstCell; // cell at the start of the segment
|
|
|
|
nsTableRowGroupFrame* mFirstRowGroup; // row group at the start of the segment
|
|
|
|
nsTableRowFrame* mFirstRow; // row at the start of the segment
|
|
|
|
nsTableCellFrame* mLastCell; // cell at the current end of the
|
|
|
|
// segment
|
|
|
|
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t mOwner; // owner of the border, defines the
|
2009-11-05 12:26:00 +03:00
|
|
|
// style
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side mTopBevelSide; // direction to bevel at the top
|
2009-11-05 12:26:00 +03:00
|
|
|
nscoord mTopBevelOffset; // how much to bevel at the top
|
|
|
|
BCPixelSize mBottomHorSegHeight; // height of the crossing
|
|
|
|
//horizontal border
|
|
|
|
nscoord mBottomOffset; // how much longer is the segment due
|
|
|
|
// to the horizontal border, by this
|
|
|
|
// amount the next segment needs to be
|
|
|
|
// shifted.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mIsBottomBevel; // should we bevel at the bottom
|
2009-11-05 12:26:00 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
struct BCHorizontalSeg
|
|
|
|
{
|
|
|
|
BCHorizontalSeg();
|
|
|
|
|
|
|
|
void Start(BCPaintBorderIterator& aIter,
|
|
|
|
BCBorderOwner aBorderOwner,
|
|
|
|
BCPixelSize aBottomVerSegWidth,
|
|
|
|
BCPixelSize aHorSegHeight);
|
|
|
|
void GetRightCorner(BCPaintBorderIterator& aIter,
|
|
|
|
BCPixelSize aLeftSegWidth);
|
2012-08-22 19:56:38 +04:00
|
|
|
void AdvanceOffsetX(int32_t aIncrement);
|
2009-11-05 12:26:00 +03:00
|
|
|
void IncludeCurrentBorder(BCPaintBorderIterator& aIter);
|
|
|
|
void Paint(BCPaintBorderIterator& aIter,
|
2011-04-08 05:04:40 +04:00
|
|
|
nsRenderingContext& aRenderingContext);
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
nscoord mOffsetX; // x-offset with respect to the table edge
|
|
|
|
nscoord mOffsetY; // y-offset with respect to the table edge
|
|
|
|
nscoord mLength; // horizontal length including corners
|
|
|
|
BCPixelSize mWidth; // border width in pixels
|
|
|
|
nscoord mLeftBevelOffset; // how much to bevel at the left
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side mLeftBevelSide; // direction to bevel at the left
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mIsRightBevel; // should we bevel at the right end
|
2009-11-05 12:26:00 +03:00
|
|
|
nscoord mRightBevelOffset; // how much to bevel at the right
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side mRightBevelSide; // direction to bevel at the right
|
2009-11-05 12:26:00 +03:00
|
|
|
nscoord mEndOffset; // how much longer is the segment due
|
|
|
|
// to the vertical border, by this
|
|
|
|
// amount the next segment needs to be
|
|
|
|
// shifted.
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t mOwner; // owner of the border, defines the
|
2009-11-05 12:26:00 +03:00
|
|
|
// style
|
|
|
|
nsTableCellFrame* mFirstCell; // cell at the start of the segment
|
|
|
|
nsTableCellFrame* mAjaCell; // neighboring cell to the first cell
|
|
|
|
// where the segment starts, it can be
|
|
|
|
// the owner of a segment
|
|
|
|
};
|
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
// Iterates over borders (left border, corner, top border) in the cell map within a damage area
|
2010-04-27 20:15:01 +04:00
|
|
|
// from left to right, top to bottom. All members are in terms of the 1st in flow frames, except
|
|
|
|
// where suffixed by InFlow.
|
2009-11-05 12:26:00 +03:00
|
|
|
class BCPaintBorderIterator
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
|
|
|
public:
|
2009-11-05 12:26:00 +03:00
|
|
|
|
|
|
|
|
|
|
|
BCPaintBorderIterator(nsTableFrame* aTable);
|
|
|
|
~BCPaintBorderIterator() { if (mVerInfo) {
|
|
|
|
delete [] mVerInfo;
|
|
|
|
}}
|
|
|
|
void Reset();
|
|
|
|
|
2012-01-23 02:48:34 +04:00
|
|
|
/**
|
|
|
|
* Determine the damage area in terms of rows and columns and finalize
|
|
|
|
* mInitialOffsetX and mInitialOffsetY.
|
|
|
|
* @param aDirtyRect - dirty rect in table coordinates
|
|
|
|
* @return - true if we need to paint something given dirty rect
|
|
|
|
*/
|
|
|
|
bool SetDamageArea(const nsRect& aDamageRect);
|
2002-02-19 18:48:28 +03:00
|
|
|
void First();
|
|
|
|
void Next();
|
2011-04-08 05:04:40 +04:00
|
|
|
void AccumulateOrPaintHorizontalSegment(nsRenderingContext& aRenderingContext);
|
|
|
|
void AccumulateOrPaintVerticalSegment(nsRenderingContext& aRenderingContext);
|
2009-11-05 12:26:00 +03:00
|
|
|
void ResetVerInfo();
|
2012-08-22 19:56:38 +04:00
|
|
|
void StoreColumnWidth(int32_t aIndex);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool VerticalSegmentOwnsCorner();
|
2009-11-05 12:26:00 +03:00
|
|
|
|
|
|
|
nsTableFrame* mTable;
|
|
|
|
nsTableFrame* mTableFirstInFlow;
|
|
|
|
nsTableCellMap* mTableCellMap;
|
|
|
|
nsCellMap* mCellMap;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mTableIsLTR;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mColInc; // +1 for ltr -1 for rtl
|
2009-11-05 12:26:00 +03:00
|
|
|
const nsStyleBackground* mTableBgColor;
|
|
|
|
nsTableFrame::RowGroupArray mRowGroups;
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
nsTableRowGroupFrame* mPrevRg;
|
|
|
|
nsTableRowGroupFrame* mRg;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mIsRepeatedHeader;
|
|
|
|
bool mIsRepeatedFooter;
|
2009-11-05 12:26:00 +03:00
|
|
|
nsTableRowGroupFrame* mStartRg; // first row group in the damagearea
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mRgIndex; // current row group index in the
|
2009-11-05 12:26:00 +03:00
|
|
|
// mRowgroups array
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mFifRgFirstRowIndex; // start row index of the first in
|
2009-11-05 12:26:00 +03:00
|
|
|
// flow of the row group
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mRgFirstRowIndex; // row index of the first row in the
|
2009-11-05 12:26:00 +03:00
|
|
|
// row group
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mRgLastRowIndex; // row index of the last row in the row
|
2009-11-05 12:26:00 +03:00
|
|
|
// group
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mNumTableRows; // number of rows in the table and all
|
2009-11-05 12:26:00 +03:00
|
|
|
// continuations
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t mNumTableCols; // number of columns in the table
|
|
|
|
int32_t mColIndex; // with respect to the table
|
|
|
|
int32_t mRowIndex; // with respect to the table
|
|
|
|
int32_t mRepeatedHeaderRowIndex; // row index in a repeated
|
2009-11-05 12:26:00 +03:00
|
|
|
//header, it's equivalent to
|
|
|
|
// mRowIndex when we're in a repeated
|
|
|
|
// header, and set to the last row
|
|
|
|
// index of a repeated header when
|
|
|
|
// we're not
|
2011-09-29 10:19:26 +04:00
|
|
|
bool mIsNewRow;
|
|
|
|
bool mAtEnd; // the iterator cycled over all
|
2009-11-05 12:26:00 +03:00
|
|
|
// borders
|
|
|
|
nsTableRowFrame* mPrevRow;
|
|
|
|
nsTableRowFrame* mRow;
|
|
|
|
nsTableRowFrame* mStartRow; //first row in a inside the damagearea
|
2009-11-05 11:03:51 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
|
|
|
|
// cell properties
|
|
|
|
nsTableCellFrame* mPrevCell;
|
|
|
|
nsTableCellFrame* mCell;
|
|
|
|
BCCellData* mPrevCellData;
|
|
|
|
BCCellData* mCellData;
|
|
|
|
BCData* mBCData;
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool IsTableTopMost() {return (mRowIndex == 0) && !mTable->GetPrevInFlow();}
|
|
|
|
bool IsTableRightMost() {return (mColIndex >= mNumTableCols);}
|
|
|
|
bool IsTableBottomMost() {return (mRowIndex >= mNumTableRows) && !mTable->GetNextInFlow();}
|
|
|
|
bool IsTableLeftMost() {return (mColIndex == 0);}
|
|
|
|
bool IsDamageAreaTopMost() {return (mRowIndex == mDamageArea.y);}
|
|
|
|
bool IsDamageAreaRightMost() {return (mColIndex >= mDamageArea.XMost());}
|
|
|
|
bool IsDamageAreaBottomMost() {return (mRowIndex >= mDamageArea.YMost());}
|
|
|
|
bool IsDamageAreaLeftMost() {return (mColIndex == mDamageArea.x);}
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t GetRelativeColIndex() {return (mColIndex - mDamageArea.x);}
|
2009-11-05 12:26:00 +03:00
|
|
|
|
2012-01-23 02:48:34 +04:00
|
|
|
nsIntRect mDamageArea; // damageArea in cellmap coordinates
|
2011-09-29 10:19:26 +04:00
|
|
|
bool IsAfterRepeatedHeader() { return !mIsRepeatedHeader && (mRowIndex == (mRepeatedHeaderRowIndex + 1));}
|
|
|
|
bool StartRepeatedFooter() {return mIsRepeatedFooter && (mRowIndex == mRgFirstRowIndex) && (mRowIndex != mDamageArea.y);}
|
2009-11-05 12:26:00 +03:00
|
|
|
nscoord mInitialOffsetX; // offsetX of the first border with
|
|
|
|
// respect to the table
|
|
|
|
nscoord mInitialOffsetY; // offsetY of the first border with
|
|
|
|
// respect to the table
|
|
|
|
nscoord mNextOffsetY; // offsetY of the next segment
|
|
|
|
BCVerticalSeg* mVerInfo; // this array is used differently when
|
|
|
|
// horizontal and vertical borders are drawn
|
|
|
|
// When horizontal border are drawn we cache
|
|
|
|
// the column widths and the width of the
|
|
|
|
// vertical borders that arrive from top
|
|
|
|
// When we draw vertical borders we store
|
|
|
|
// lengths and width for vertical borders
|
|
|
|
// before they are drawn while we move over
|
|
|
|
// the columns in the damage area
|
|
|
|
// It has one more elements than columns are
|
|
|
|
//in the table.
|
|
|
|
BCHorizontalSeg mHorSeg; // the horizontal segment while we
|
|
|
|
// move over the colums
|
|
|
|
BCPixelSize mPrevHorSegHeight; // the height of the previous
|
|
|
|
// horizontal border
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
private:
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
bool SetNewRow(nsTableRowFrame* aRow = nullptr);
|
2011-09-29 10:19:26 +04:00
|
|
|
bool SetNewRowGroup();
|
2012-08-22 19:56:38 +04:00
|
|
|
void SetNewData(int32_t aRowIndex, int32_t aColIndex);
|
2002-02-19 18:48:28 +03:00
|
|
|
|
|
|
|
};
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
|
|
|
|
|
|
|
|
BCPaintBorderIterator::BCPaintBorderIterator(nsTableFrame* aTable)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2009-11-05 12:26:00 +03:00
|
|
|
mTable = aTable;
|
2012-07-30 18:20:58 +04:00
|
|
|
mVerInfo = nullptr;
|
|
|
|
nsMargin childAreaOffset = mTable->GetChildAreaOffset(nullptr);
|
2009-11-05 12:26:00 +03:00
|
|
|
mTableFirstInFlow = (nsTableFrame*) mTable->GetFirstInFlow();
|
|
|
|
mTableCellMap = mTable->GetCellMap();
|
|
|
|
// y position of first row in damage area
|
2012-01-23 02:48:34 +04:00
|
|
|
mInitialOffsetY = mTable->GetPrevInFlow() ? 0 : childAreaOffset.top;
|
2009-11-05 12:26:00 +03:00
|
|
|
mNumTableRows = mTable->GetRowCount();
|
|
|
|
mNumTableCols = mTable->GetColCount();
|
|
|
|
|
|
|
|
// Get the ordered row groups
|
|
|
|
mTable->OrderRowGroups(mRowGroups);
|
2010-01-19 20:49:12 +03:00
|
|
|
// initialize to a non existing index
|
|
|
|
mRepeatedHeaderRowIndex = -99;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
mTableIsLTR = mTable->GetStyleVisibility()->mDirection ==
|
|
|
|
NS_STYLE_DIRECTION_LTR;
|
|
|
|
mColInc = (mTableIsLTR) ? 1 : -1;
|
|
|
|
|
2010-04-08 16:44:57 +04:00
|
|
|
nsIFrame* bgFrame =
|
|
|
|
nsCSSRendering::FindNonTransparentBackgroundFrame(aTable);
|
|
|
|
mTableBgColor = bgFrame->GetStyleBackground();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2012-01-23 02:48:34 +04:00
|
|
|
BCPaintBorderIterator::SetDamageArea(const nsRect& aDirtyRect)
|
2009-11-05 12:26:00 +03:00
|
|
|
{
|
2009-11-05 11:03:51 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t startRowIndex, endRowIndex, startColIndex, endColIndex;
|
2009-11-05 12:26:00 +03:00
|
|
|
startRowIndex = endRowIndex = startColIndex = endColIndex = 0;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool done = false;
|
|
|
|
bool haveIntersect = false;
|
2012-01-23 02:48:34 +04:00
|
|
|
// find startRowIndex, endRowIndex
|
|
|
|
nscoord rowY = mInitialOffsetY;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t rgX = 0; rgX < mRowGroups.Length() && !done; rgX++) {
|
2009-11-05 12:26:00 +03:00
|
|
|
nsTableRowGroupFrame* rgFrame = mRowGroups[rgX];
|
|
|
|
for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow(); rowFrame;
|
|
|
|
rowFrame = rowFrame->GetNextRow()) {
|
|
|
|
// conservatively estimate the half border widths outside the row
|
|
|
|
nscoord topBorderHalf = (mTable->GetPrevInFlow()) ? 0 :
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(rowFrame->GetTopBCBorderWidth() + 1);
|
|
|
|
nscoord bottomBorderHalf = (mTable->GetNextInFlow()) ? 0 :
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(rowFrame->GetBottomBCBorderWidth() + 1);
|
|
|
|
// get the row rect relative to the table rather than the row group
|
|
|
|
nsSize rowSize = rowFrame->GetSize();
|
|
|
|
if (haveIntersect) {
|
|
|
|
if (aDirtyRect.YMost() >= (rowY - topBorderHalf)) {
|
|
|
|
nsTableRowFrame* fifRow =
|
2012-01-17 03:38:10 +04:00
|
|
|
static_cast<nsTableRowFrame*>(rowFrame->GetFirstInFlow());
|
2009-11-05 12:26:00 +03:00
|
|
|
endRowIndex = fifRow->GetRowIndex();
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
else done = true;
|
2009-11-05 12:26:00 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if ((rowY + rowSize.height + bottomBorderHalf) >= aDirtyRect.y) {
|
|
|
|
mStartRg = rgFrame;
|
|
|
|
mStartRow = rowFrame;
|
|
|
|
nsTableRowFrame* fifRow =
|
2012-01-17 03:38:10 +04:00
|
|
|
static_cast<nsTableRowFrame*>(rowFrame->GetFirstInFlow());
|
2009-11-05 12:26:00 +03:00
|
|
|
startRowIndex = endRowIndex = fifRow->GetRowIndex();
|
2011-10-17 18:59:28 +04:00
|
|
|
haveIntersect = true;
|
2009-11-05 12:26:00 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
mInitialOffsetY += rowSize.height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rowY += rowSize.height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mNextOffsetY = mInitialOffsetY;
|
|
|
|
|
|
|
|
// XXX comment refers to the obsolete NS_FRAME_OUTSIDE_CHILDREN flag
|
|
|
|
// XXX but I don't understand it, so not changing it for now
|
|
|
|
// outer table borders overflow the table, so the table might be
|
|
|
|
// target to other areas as the NS_FRAME_OUTSIDE_CHILDREN is set
|
|
|
|
// on the table
|
|
|
|
if (!haveIntersect)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2009-11-05 12:26:00 +03:00
|
|
|
// find startColIndex, endColIndex, startColX
|
2011-10-17 18:59:28 +04:00
|
|
|
haveIntersect = false;
|
2009-11-05 12:26:00 +03:00
|
|
|
if (0 == mNumTableCols)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t leftCol, rightCol; // columns are in the range [leftCol, rightCol)
|
2009-11-05 12:26:00 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsMargin childAreaOffset = mTable->GetChildAreaOffset(nullptr);
|
2009-11-05 12:26:00 +03:00
|
|
|
if (mTableIsLTR) {
|
|
|
|
mInitialOffsetX = childAreaOffset.left; // x position of first col in
|
|
|
|
// damage area
|
|
|
|
leftCol = 0;
|
|
|
|
rightCol = mNumTableCols;
|
|
|
|
} else {
|
|
|
|
// x position of first col in damage area
|
|
|
|
mInitialOffsetX = mTable->GetRect().width - childAreaOffset.right;
|
|
|
|
leftCol = mNumTableCols-1;
|
|
|
|
rightCol = -1;
|
|
|
|
}
|
|
|
|
nscoord x = 0;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t colX;
|
2009-11-05 12:26:00 +03:00
|
|
|
for (colX = leftCol; colX != rightCol; colX += mColInc) {
|
|
|
|
nsTableColFrame* colFrame = mTableFirstInFlow->GetColFrame(colX);
|
2011-10-17 18:59:28 +04:00
|
|
|
if (!colFrame) ABORT1(false);
|
2009-11-05 12:26:00 +03:00
|
|
|
// get the col rect relative to the table rather than the col group
|
|
|
|
nsSize size = colFrame->GetSize();
|
|
|
|
if (haveIntersect) {
|
2012-01-23 02:48:34 +04:00
|
|
|
// conservatively estimate the left half border width outside the col
|
|
|
|
nscoord leftBorderHalf =
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(colFrame->GetLeftBorderWidth() + 1);
|
2009-11-05 12:26:00 +03:00
|
|
|
if (aDirtyRect.XMost() >= (x - leftBorderHalf)) {
|
|
|
|
endColIndex = colX;
|
|
|
|
}
|
|
|
|
else break;
|
|
|
|
}
|
|
|
|
else {
|
2012-01-23 02:48:34 +04:00
|
|
|
// conservatively estimate the right half border width outside the col
|
|
|
|
nscoord rightBorderHalf =
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(colFrame->GetRightBorderWidth() + 1);
|
2009-11-05 12:26:00 +03:00
|
|
|
if ((x + size.width + rightBorderHalf) >= aDirtyRect.x) {
|
|
|
|
startColIndex = endColIndex = colX;
|
2011-10-17 18:59:28 +04:00
|
|
|
haveIntersect = true;
|
2009-11-05 12:26:00 +03:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
mInitialOffsetX += mColInc * size.width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
x += size.width;
|
|
|
|
}
|
|
|
|
if (!mTableIsLTR) {
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t temp;
|
2009-11-05 12:26:00 +03:00
|
|
|
mInitialOffsetX = mTable->GetRect().width - childAreaOffset.right;
|
|
|
|
temp = startColIndex; startColIndex = endColIndex; endColIndex = temp;
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t column = 0; column < startColIndex; column++) {
|
2009-11-05 12:26:00 +03:00
|
|
|
nsTableColFrame* colFrame = mTableFirstInFlow->GetColFrame(column);
|
2011-10-17 18:59:28 +04:00
|
|
|
if (!colFrame) ABORT1(false);
|
2009-11-05 12:26:00 +03:00
|
|
|
nsSize size = colFrame->GetSize();
|
|
|
|
mInitialOffsetX += mColInc * size.width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!haveIntersect)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2012-01-23 02:48:34 +04:00
|
|
|
mDamageArea = nsIntRect(startColIndex, startRowIndex,
|
2012-08-22 19:56:38 +04:00
|
|
|
1 + NS_ABS(int32_t(endColIndex - startColIndex)),
|
2012-01-23 02:48:34 +04:00
|
|
|
1 + endRowIndex - startRowIndex);
|
2009-11-05 12:26:00 +03:00
|
|
|
|
|
|
|
Reset();
|
|
|
|
mVerInfo = new BCVerticalSeg[mDamageArea.width + 1];
|
|
|
|
if (!mVerInfo)
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
|
|
|
return true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
void
|
|
|
|
BCPaintBorderIterator::Reset()
|
|
|
|
{
|
2011-10-17 18:59:28 +04:00
|
|
|
mAtEnd = true; // gets reset when First() is called
|
2009-11-05 12:26:00 +03:00
|
|
|
mRg = mStartRg;
|
2012-07-30 18:20:58 +04:00
|
|
|
mPrevRow = nullptr;
|
2009-11-05 12:26:00 +03:00
|
|
|
mRow = mStartRow;
|
|
|
|
mRowIndex = 0;
|
|
|
|
mColIndex = 0;
|
|
|
|
mRgIndex = -1;
|
2012-07-30 18:20:58 +04:00
|
|
|
mPrevCell = nullptr;
|
|
|
|
mCell = nullptr;
|
|
|
|
mPrevCellData = nullptr;
|
|
|
|
mCellData = nullptr;
|
|
|
|
mBCData = nullptr;
|
2009-11-05 12:26:00 +03:00
|
|
|
ResetVerInfo();
|
2012-01-23 02:48:34 +04:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the iterator data to a new cellmap coordinate
|
|
|
|
* @param aRowIndex - the row index
|
|
|
|
* @param aColIndex - the col index
|
|
|
|
*/
|
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
BCPaintBorderIterator::SetNewData(int32_t aY,
|
|
|
|
int32_t aX)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2009-11-05 12:26:00 +03:00
|
|
|
if (!mTableCellMap || !mTableCellMap->mBCInfo) ABORT0();
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
mColIndex = aX;
|
|
|
|
mRowIndex = aY;
|
|
|
|
mPrevCellData = mCellData;
|
|
|
|
if (IsTableRightMost() && IsTableBottomMost()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
mCell = nullptr;
|
2009-11-05 12:26:00 +03:00
|
|
|
mBCData = &mTableCellMap->mBCInfo->mLowerRightCorner;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
else if (IsTableRightMost()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
mCellData = nullptr;
|
2009-11-05 12:26:00 +03:00
|
|
|
mBCData = &mTableCellMap->mBCInfo->mRightBorders.ElementAt(aY);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
else if (IsTableBottomMost()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
mCellData = nullptr;
|
2009-11-05 12:26:00 +03:00
|
|
|
mBCData = &mTableCellMap->mBCInfo->mBottomBorders.ElementAt(aX);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
2012-08-22 19:56:38 +04:00
|
|
|
if (uint32_t(mRowIndex - mFifRgFirstRowIndex) < mCellMap->mRows.Length()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
mBCData = nullptr;
|
2009-11-05 12:26:00 +03:00
|
|
|
mCellData =
|
|
|
|
(BCCellData*)mCellMap->mRows[mRowIndex - mFifRgFirstRowIndex].SafeElementAt(mColIndex);
|
|
|
|
if (mCellData) {
|
|
|
|
mBCData = &mCellData->mData;
|
|
|
|
if (!mCellData->IsOrig()) {
|
|
|
|
if (mCellData->IsRowSpan()) {
|
|
|
|
aY -= mCellData->GetRowSpanOffset();
|
2006-12-26 16:55:32 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
if (mCellData->IsColSpan()) {
|
|
|
|
aX -= mCellData->GetColSpanOffset();
|
2006-12-26 16:55:32 +03:00
|
|
|
}
|
|
|
|
if ((aX >= 0) && (aY >= 0)) {
|
2009-11-05 12:26:00 +03:00
|
|
|
mCellData = (BCCellData*)mCellMap->mRows[aY - mFifRgFirstRowIndex][aX];
|
2006-12-26 16:55:32 +03:00
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
if (mCellData->IsOrig()) {
|
|
|
|
mPrevCell = mCell;
|
|
|
|
mCell = mCellData->GetCellFrame();
|
2006-12-07 05:32:57 +03:00
|
|
|
}
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Set the iterator to a new row
|
|
|
|
* @param aRow - the new row frame, if null the iterator will advance to the
|
|
|
|
* next row
|
|
|
|
*/
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2009-11-05 12:26:00 +03:00
|
|
|
BCPaintBorderIterator::SetNewRow(nsTableRowFrame* aRow)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2009-11-05 12:26:00 +03:00
|
|
|
mPrevRow = mRow;
|
|
|
|
mRow = (aRow) ? aRow : mRow->GetNextRow();
|
|
|
|
if (mRow) {
|
2011-10-17 18:59:28 +04:00
|
|
|
mIsNewRow = true;
|
2009-11-05 12:26:00 +03:00
|
|
|
mRowIndex = mRow->GetRowIndex();
|
|
|
|
mColIndex = mDamageArea.x;
|
|
|
|
mPrevHorSegHeight = 0;
|
|
|
|
if (mIsRepeatedHeader) {
|
|
|
|
mRepeatedHeaderRowIndex = mRowIndex;
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
2011-10-17 18:59:28 +04:00
|
|
|
mAtEnd = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
return !mAtEnd;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Advance the iterator to the next row group
|
|
|
|
*/
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2009-11-05 12:26:00 +03:00
|
|
|
BCPaintBorderIterator::SetNewRowGroup()
|
|
|
|
{
|
|
|
|
|
|
|
|
mRgIndex++;
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mIsRepeatedHeader = false;
|
|
|
|
mIsRepeatedFooter = false;
|
2009-11-05 12:26:00 +03:00
|
|
|
|
2010-03-05 21:41:54 +03:00
|
|
|
NS_ASSERTION(mRgIndex >= 0, "mRgIndex out of bounds");
|
2012-08-22 19:56:38 +04:00
|
|
|
if (uint32_t(mRgIndex) < mRowGroups.Length()) {
|
2009-11-05 12:26:00 +03:00
|
|
|
mPrevRg = mRg;
|
|
|
|
mRg = mRowGroups[mRgIndex];
|
2012-01-23 02:48:34 +04:00
|
|
|
nsTableRowGroupFrame* fifRg =
|
|
|
|
static_cast<nsTableRowGroupFrame*>(mRg->GetFirstInFlow());
|
|
|
|
mFifRgFirstRowIndex = fifRg->GetStartRowIndex();
|
2009-11-05 12:26:00 +03:00
|
|
|
mRgFirstRowIndex = mRg->GetStartRowIndex();
|
|
|
|
mRgLastRowIndex = mRgFirstRowIndex + mRg->GetRowCount() - 1;
|
|
|
|
|
|
|
|
if (SetNewRow(mRg->GetFirstRow())) {
|
2012-07-30 18:20:58 +04:00
|
|
|
mCellMap = mTableCellMap->GetMapFor(fifRg, nullptr);
|
2011-10-17 18:59:28 +04:00
|
|
|
if (!mCellMap) ABORT1(false);
|
2009-11-05 12:26:00 +03:00
|
|
|
}
|
|
|
|
if (mRg && mTable->GetPrevInFlow() && !mRg->GetPrevInFlow()) {
|
|
|
|
// if mRowGroup doesn't have a prev in flow, then it may be a repeated
|
|
|
|
// header or footer
|
|
|
|
const nsStyleDisplay* display = mRg->GetStyleDisplay();
|
|
|
|
if (mRowIndex == mDamageArea.y) {
|
|
|
|
mIsRepeatedHeader = (NS_STYLE_DISPLAY_TABLE_HEADER_GROUP == display->mDisplay);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
else {
|
2009-11-05 12:26:00 +03:00
|
|
|
mIsRepeatedFooter = (NS_STYLE_DISPLAY_TABLE_FOOTER_GROUP == display->mDisplay);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2011-10-17 18:59:28 +04:00
|
|
|
mAtEnd = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
return !mAtEnd;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Move the iterator to the first position in the damageArea
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCPaintBorderIterator::First()
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2009-11-05 12:26:00 +03:00
|
|
|
if (!mTable || (mDamageArea.x >= mNumTableCols) ||
|
|
|
|
(mDamageArea.y >= mNumTableRows)) ABORT0();
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
mAtEnd = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t numRowGroups = mRowGroups.Length();
|
|
|
|
for (uint32_t rgY = 0; rgY < numRowGroups; rgY++) {
|
2009-11-05 12:26:00 +03:00
|
|
|
nsTableRowGroupFrame* rowG = mRowGroups[rgY];
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t start = rowG->GetStartRowIndex();
|
|
|
|
int32_t end = start + rowG->GetRowCount() - 1;
|
2009-11-05 12:26:00 +03:00
|
|
|
if ((mDamageArea.y >= start) && (mDamageArea.y <= end)) {
|
|
|
|
mRgIndex = rgY - 1; // SetNewRowGroup increments rowGroupIndex
|
|
|
|
if (SetNewRowGroup()) {
|
|
|
|
while ((mRowIndex < mDamageArea.y) && !mAtEnd) {
|
2007-06-05 22:55:26 +04:00
|
|
|
SetNewRow();
|
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
if (!mAtEnd) {
|
|
|
|
SetNewData(mDamageArea.y, mDamageArea.x);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2007-06-05 22:55:26 +04:00
|
|
|
return;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
mAtEnd = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Advance the iterator to the next position
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCPaintBorderIterator::Next()
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2009-11-05 12:26:00 +03:00
|
|
|
if (mAtEnd) ABORT0();
|
2011-10-17 18:59:28 +04:00
|
|
|
mIsNewRow = false;
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
mColIndex++;
|
|
|
|
if (mColIndex > mDamageArea.XMost()) {
|
|
|
|
mRowIndex++;
|
|
|
|
if (mRowIndex == mDamageArea.YMost()) {
|
|
|
|
mColIndex = mDamageArea.x;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
else if (mRowIndex < mDamageArea.YMost()) {
|
|
|
|
if (mRowIndex <= mRgLastRowIndex) {
|
2002-02-19 18:48:28 +03:00
|
|
|
SetNewRow();
|
|
|
|
}
|
|
|
|
else {
|
2002-05-31 18:40:51 +04:00
|
|
|
SetNewRowGroup();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2011-10-17 18:59:28 +04:00
|
|
|
mAtEnd = true;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
if (!mAtEnd) {
|
|
|
|
SetNewData(mRowIndex, mColIndex);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
// XXX if CalcVerCornerOffset and CalcHorCornerOffset remain similar, combine
|
|
|
|
// them
|
|
|
|
/** Compute the vertical offset of a vertical border segment
|
|
|
|
* @param aCornerOwnerSide - which side owns the corner
|
|
|
|
* @param aCornerSubWidth - how wide is the nonwinning side of the corner
|
|
|
|
* @param aHorWidth - how wide is the horizontal edge of the corner
|
|
|
|
* @param aIsStartOfSeg - does this corner start a new segment
|
|
|
|
* @param aIsBevel - is this corner beveled
|
|
|
|
* @return - offset in twips
|
|
|
|
*/
|
2002-02-19 18:48:28 +03:00
|
|
|
static nscoord
|
2010-04-27 20:15:02 +04:00
|
|
|
CalcVerCornerOffset(mozilla::css::Side aCornerOwnerSide,
|
2009-11-05 12:26:00 +03:00
|
|
|
BCPixelSize aCornerSubWidth,
|
|
|
|
BCPixelSize aHorWidth,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aIsStartOfSeg,
|
|
|
|
bool aIsBevel)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
|
|
|
nscoord offset = 0;
|
2009-11-05 12:26:00 +03:00
|
|
|
// XXX These should be replaced with appropriate side-specific macros (which?)
|
|
|
|
BCPixelSize smallHalf, largeHalf;
|
|
|
|
if ((NS_SIDE_TOP == aCornerOwnerSide) ||
|
|
|
|
(NS_SIDE_BOTTOM == aCornerOwnerSide)) {
|
2002-02-19 18:48:28 +03:00
|
|
|
DivideBCBorderSize(aCornerSubWidth, smallHalf, largeHalf);
|
|
|
|
if (aIsBevel) {
|
|
|
|
offset = (aIsStartOfSeg) ? -largeHalf : smallHalf;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
offset = (NS_SIDE_TOP == aCornerOwnerSide) ? smallHalf : -largeHalf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DivideBCBorderSize(aHorWidth, smallHalf, largeHalf);
|
|
|
|
if (aIsBevel) {
|
|
|
|
offset = (aIsStartOfSeg) ? -largeHalf : smallHalf;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
offset = (aIsStartOfSeg) ? smallHalf : -largeHalf;
|
|
|
|
}
|
|
|
|
}
|
2007-02-07 10:46:44 +03:00
|
|
|
return nsPresContext::CSSPixelsToAppUnits(offset);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2004-10-31 18:52:52 +03:00
|
|
|
/** Compute the horizontal offset of a horizontal border segment
|
|
|
|
* @param aCornerOwnerSide - which side owns the corner
|
|
|
|
* @param aCornerSubWidth - how wide is the nonwinning side of the corner
|
|
|
|
* @param aVerWidth - how wide is the vertical edge of the corner
|
|
|
|
* @param aIsStartOfSeg - does this corner start a new segment
|
|
|
|
* @param aIsBevel - is this corner beveled
|
|
|
|
* @param aTableIsLTR - direction, the computation depends on ltr or rtl
|
2009-11-05 12:26:00 +03:00
|
|
|
* @return - offset in twips
|
2004-10-31 18:52:52 +03:00
|
|
|
*/
|
2002-02-19 18:48:28 +03:00
|
|
|
static nscoord
|
2010-04-27 20:15:02 +04:00
|
|
|
CalcHorCornerOffset(mozilla::css::Side aCornerOwnerSide,
|
2009-11-05 12:26:00 +03:00
|
|
|
BCPixelSize aCornerSubWidth,
|
|
|
|
BCPixelSize aVerWidth,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aIsStartOfSeg,
|
|
|
|
bool aIsBevel,
|
|
|
|
bool aTableIsLTR)
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
|
|
|
nscoord offset = 0;
|
2009-11-05 12:26:00 +03:00
|
|
|
// XXX These should be replaced with appropriate side-specific macros (which?)
|
|
|
|
BCPixelSize smallHalf, largeHalf;
|
|
|
|
if ((NS_SIDE_LEFT == aCornerOwnerSide) ||
|
|
|
|
(NS_SIDE_RIGHT == aCornerOwnerSide)) {
|
2004-10-31 18:52:52 +03:00
|
|
|
if (aTableIsLTR) {
|
|
|
|
DivideBCBorderSize(aCornerSubWidth, smallHalf, largeHalf);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DivideBCBorderSize(aCornerSubWidth, largeHalf, smallHalf);
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
if (aIsBevel) {
|
|
|
|
offset = (aIsStartOfSeg) ? -largeHalf : smallHalf;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
offset = (NS_SIDE_LEFT == aCornerOwnerSide) ? smallHalf : -largeHalf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2004-10-31 18:52:52 +03:00
|
|
|
if (aTableIsLTR) {
|
|
|
|
DivideBCBorderSize(aVerWidth, smallHalf, largeHalf);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
DivideBCBorderSize(aVerWidth, largeHalf, smallHalf);
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
if (aIsBevel) {
|
|
|
|
offset = (aIsStartOfSeg) ? -largeHalf : smallHalf;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
offset = (aIsStartOfSeg) ? smallHalf : -largeHalf;
|
|
|
|
}
|
|
|
|
}
|
2007-02-07 10:46:44 +03:00
|
|
|
return nsPresContext::CSSPixelsToAppUnits(offset);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
BCVerticalSeg::BCVerticalSeg()
|
2002-02-19 18:48:28 +03:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
mCol = nullptr;
|
|
|
|
mFirstCell = mLastCell = mAjaCell = nullptr;
|
2010-04-27 20:15:02 +04:00
|
|
|
mOffsetX = mOffsetY = mLength = mWidth = mTopBevelOffset = 0;
|
|
|
|
mTopBevelSide = NS_SIDE_TOP;
|
2009-11-05 12:26:00 +03:00
|
|
|
mOwner = eCellOwner;
|
2009-11-05 12:25:26 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Start a new vertical segment
|
|
|
|
* @param aIter - iterator containing the structural information
|
|
|
|
* @param aBorderOwner - determines the border style
|
|
|
|
* @param aVerSegWidth - the width of segment in pixel
|
|
|
|
* @param aHorSegHeight - the width of the horizontal segment joining the corner
|
|
|
|
* at the start
|
|
|
|
*/
|
2002-02-19 18:48:28 +03:00
|
|
|
void
|
2009-11-05 12:26:00 +03:00
|
|
|
BCVerticalSeg::Start(BCPaintBorderIterator& aIter,
|
|
|
|
BCBorderOwner aBorderOwner,
|
|
|
|
BCPixelSize aVerSegWidth,
|
|
|
|
BCPixelSize aHorSegHeight)
|
|
|
|
{
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side ownerSide = NS_SIDE_TOP;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool bevel = false;
|
2009-11-05 11:03:51 +03:00
|
|
|
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
nscoord cornerSubWidth = (aIter.mBCData) ?
|
|
|
|
aIter.mBCData->GetCorner(ownerSide, bevel) : 0;
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool topBevel = (aVerSegWidth > 0) ? bevel : false;
|
2011-06-02 16:56:50 +04:00
|
|
|
BCPixelSize maxHorSegHeight = NS_MAX(aIter.mPrevHorSegHeight, aHorSegHeight);
|
2009-11-05 12:26:00 +03:00
|
|
|
nscoord offset = CalcVerCornerOffset(ownerSide, cornerSubWidth,
|
2011-10-17 18:59:28 +04:00
|
|
|
maxHorSegHeight, true,
|
2009-11-05 12:26:00 +03:00
|
|
|
topBevel);
|
|
|
|
|
2012-01-23 02:48:34 +04:00
|
|
|
mTopBevelOffset = topBevel ?
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(maxHorSegHeight): 0;
|
2009-11-05 12:26:00 +03:00
|
|
|
// XXX this assumes that only corners where 2 segments join can be beveled
|
|
|
|
mTopBevelSide = (aHorSegHeight > 0) ? NS_SIDE_RIGHT : NS_SIDE_LEFT;
|
|
|
|
mOffsetY += offset;
|
|
|
|
mLength = -offset;
|
|
|
|
mWidth = aVerSegWidth;
|
|
|
|
mOwner = aBorderOwner;
|
|
|
|
mFirstCell = aIter.mCell;
|
|
|
|
mFirstRowGroup = aIter.mRg;
|
|
|
|
mFirstRow = aIter.mRow;
|
|
|
|
if (aIter.GetRelativeColIndex() > 0) {
|
|
|
|
mAjaCell = aIter.mVerInfo[aIter.GetRelativeColIndex() - 1].mLastCell;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize the vertical segments with information that will persist for any
|
|
|
|
* vertical segment in this column
|
|
|
|
* @param aIter - iterator containing the structural information
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCVerticalSeg::Initialize(BCPaintBorderIterator& aIter)
|
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t relColIndex = aIter.GetRelativeColIndex();
|
2009-11-05 12:26:00 +03:00
|
|
|
mCol = aIter.IsTableRightMost() ? aIter.mVerInfo[relColIndex - 1].mCol :
|
|
|
|
aIter.mTableFirstInFlow->GetColFrame(aIter.mColIndex);
|
|
|
|
if (!mCol) ABORT0();
|
|
|
|
if (0 == relColIndex) {
|
|
|
|
mOffsetX = aIter.mInitialOffsetX;
|
|
|
|
}
|
|
|
|
// set colX for the next column
|
|
|
|
if (!aIter.IsDamageAreaRightMost()) {
|
|
|
|
aIter.mVerInfo[relColIndex + 1].mOffsetX = mOffsetX +
|
|
|
|
aIter.mColInc * mCol->GetSize().width;
|
2009-11-05 11:03:51 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
mOffsetY = aIter.mInitialOffsetY;
|
|
|
|
mLastCell = aIter.mCell;
|
2009-11-05 11:03:51 +03:00
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Compute the offsets for the bottom corner of a vertical segment
|
|
|
|
* @param aIter - iterator containing the structural information
|
|
|
|
* @param aHorSegHeight - the width of the horizontal segment joining the corner
|
|
|
|
* at the start
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCVerticalSeg::GetBottomCorner(BCPaintBorderIterator& aIter,
|
|
|
|
BCPixelSize aHorSegHeight)
|
|
|
|
{
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side ownerSide = NS_SIDE_TOP;
|
2009-11-05 12:26:00 +03:00
|
|
|
nscoord cornerSubWidth = 0;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool bevel = false;
|
2009-11-05 12:26:00 +03:00
|
|
|
if (aIter.mBCData) {
|
|
|
|
cornerSubWidth = aIter.mBCData->GetCorner(ownerSide, bevel);
|
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
mIsBottomBevel = (mWidth > 0) ? bevel : false;
|
2011-06-02 16:56:50 +04:00
|
|
|
mBottomHorSegHeight = NS_MAX(aIter.mPrevHorSegHeight, aHorSegHeight);
|
2009-11-05 12:26:00 +03:00
|
|
|
mBottomOffset = CalcVerCornerOffset(ownerSide, cornerSubWidth,
|
|
|
|
mBottomHorSegHeight,
|
2011-10-17 18:59:28 +04:00
|
|
|
false, mIsBottomBevel);
|
2009-11-05 12:26:00 +03:00
|
|
|
mLength += mBottomOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Paint the vertical segment
|
|
|
|
* @param aIter - iterator containing the structural information
|
|
|
|
* @param aRenderingContext - the rendering context
|
|
|
|
* @param aHorSegHeight - the width of the horizontal segment joining the corner
|
|
|
|
* at the start
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCVerticalSeg::Paint(BCPaintBorderIterator& aIter,
|
2011-04-08 05:04:40 +04:00
|
|
|
nsRenderingContext& aRenderingContext,
|
2009-11-05 12:26:00 +03:00
|
|
|
BCPixelSize aHorSegHeight)
|
|
|
|
{
|
|
|
|
// get the border style, color and paint the segment
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side side = (aIter.IsDamageAreaRightMost()) ? NS_SIDE_RIGHT :
|
2009-11-05 12:26:00 +03:00
|
|
|
NS_SIDE_LEFT;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t relColIndex = aIter.GetRelativeColIndex();
|
2009-11-05 12:26:00 +03:00
|
|
|
nsTableColFrame* col = mCol; if (!col) ABORT0();
|
|
|
|
nsTableCellFrame* cell = mFirstCell; // ???
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame* owner = nullptr;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t style = NS_STYLE_BORDER_STYLE_SOLID;
|
2009-11-05 12:26:00 +03:00
|
|
|
nscolor color = 0xFFFFFFFF;
|
|
|
|
|
|
|
|
switch (mOwner) {
|
|
|
|
case eTableOwner:
|
2010-01-09 18:33:03 +03:00
|
|
|
owner = aIter.mTable;
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
|
|
|
case eAjaColGroupOwner:
|
|
|
|
side = NS_SIDE_RIGHT;
|
|
|
|
if (!aIter.IsTableRightMost() && (relColIndex > 0)) {
|
|
|
|
col = aIter.mVerInfo[relColIndex - 1].mCol;
|
|
|
|
} // and fall through
|
|
|
|
case eColGroupOwner:
|
|
|
|
if (col) {
|
2010-01-09 18:33:03 +03:00
|
|
|
owner = col->GetParent();
|
2009-11-05 12:26:00 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case eAjaColOwner:
|
|
|
|
side = NS_SIDE_RIGHT;
|
|
|
|
if (!aIter.IsTableRightMost() && (relColIndex > 0)) {
|
|
|
|
col = aIter.mVerInfo[relColIndex - 1].mCol;
|
|
|
|
} // and fall through
|
|
|
|
case eColOwner:
|
2010-01-09 18:33:03 +03:00
|
|
|
owner = col;
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
|
|
|
case eAjaRowGroupOwner:
|
|
|
|
NS_ERROR("a neighboring rowgroup can never own a vertical border");
|
|
|
|
// and fall through
|
|
|
|
case eRowGroupOwner:
|
|
|
|
NS_ASSERTION(aIter.IsTableLeftMost() || aIter.IsTableRightMost(),
|
|
|
|
"row group can own border only at table edge");
|
2010-01-09 18:33:03 +03:00
|
|
|
owner = mFirstRowGroup;
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
|
|
|
case eAjaRowOwner:
|
2011-10-17 18:59:28 +04:00
|
|
|
NS_ASSERTION(false, "program error"); // and fall through
|
2009-11-05 12:26:00 +03:00
|
|
|
case eRowOwner:
|
|
|
|
NS_ASSERTION(aIter.IsTableLeftMost() || aIter.IsTableRightMost(),
|
|
|
|
"row can own border only at table edge");
|
2010-01-09 18:33:03 +03:00
|
|
|
owner = mFirstRow;
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
|
|
|
case eAjaCellOwner:
|
|
|
|
side = NS_SIDE_RIGHT;
|
|
|
|
cell = mAjaCell; // and fall through
|
|
|
|
case eCellOwner:
|
2010-01-09 18:33:03 +03:00
|
|
|
owner = cell;
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
|
|
|
}
|
2010-01-09 18:33:03 +03:00
|
|
|
if (owner) {
|
|
|
|
::GetPaintStyleInfo(owner, side, style, color, aIter.mTableIsLTR);
|
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
BCPixelSize smallHalf, largeHalf;
|
|
|
|
DivideBCBorderSize(mWidth, smallHalf, largeHalf);
|
|
|
|
nsRect segRect(mOffsetX - nsPresContext::CSSPixelsToAppUnits(largeHalf),
|
|
|
|
mOffsetY,
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(mWidth), mLength);
|
|
|
|
nscoord bottomBevelOffset = (mIsBottomBevel) ?
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(mBottomHorSegHeight) : 0;
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side bottomBevelSide = ((aHorSegHeight > 0) ^ !aIter.mTableIsLTR) ?
|
2009-11-05 12:26:00 +03:00
|
|
|
NS_SIDE_RIGHT : NS_SIDE_LEFT;
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side topBevelSide = ((mTopBevelSide == NS_SIDE_RIGHT) ^ !aIter.mTableIsLTR)?
|
2009-11-05 12:26:00 +03:00
|
|
|
NS_SIDE_RIGHT : NS_SIDE_LEFT;
|
|
|
|
nsCSSRendering::DrawTableBorderSegment(aRenderingContext, style, color,
|
|
|
|
aIter.mTableBgColor, segRect,
|
|
|
|
nsPresContext::AppUnitsPerCSSPixel(),
|
|
|
|
topBevelSide, mTopBevelOffset,
|
|
|
|
bottomBevelSide, bottomBevelOffset);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Advance the start point of a segment
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCVerticalSeg::AdvanceOffsetY()
|
2009-11-05 11:03:51 +03:00
|
|
|
{
|
2009-11-05 12:26:00 +03:00
|
|
|
mOffsetY += mLength - mBottomOffset;
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Accumulate the current segment
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCVerticalSeg::IncludeCurrentBorder(BCPaintBorderIterator& aIter)
|
|
|
|
{
|
|
|
|
mLastCell = aIter.mCell;
|
|
|
|
mLength += aIter.mRow->GetRect().height;
|
|
|
|
}
|
2009-11-05 12:25:26 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
BCHorizontalSeg::BCHorizontalSeg()
|
|
|
|
{
|
|
|
|
mOffsetX = mOffsetY = mLength = mWidth = mLeftBevelOffset = 0;
|
2010-04-27 20:15:02 +04:00
|
|
|
mLeftBevelSide = NS_SIDE_TOP;
|
2012-07-30 18:20:58 +04:00
|
|
|
mFirstCell = mAjaCell = nullptr;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2004-10-31 18:52:52 +03:00
|
|
|
/** Initialize a horizontal border segment for painting
|
|
|
|
* @param aIter - iterator storing the current and adjacent frames
|
|
|
|
* @param aBorderOwner - which frame owns the border
|
2005-11-21 01:05:24 +03:00
|
|
|
* @param aBottomVerSegWidth - vertical segment width coming from up
|
2004-10-31 18:52:52 +03:00
|
|
|
* @param aHorSegHeight - the height of the segment
|
2009-11-05 12:26:00 +03:00
|
|
|
+ */
|
2002-02-19 18:48:28 +03:00
|
|
|
void
|
2009-11-05 12:26:00 +03:00
|
|
|
BCHorizontalSeg::Start(BCPaintBorderIterator& aIter,
|
2002-02-19 18:48:28 +03:00
|
|
|
BCBorderOwner aBorderOwner,
|
2009-11-05 12:26:00 +03:00
|
|
|
BCPixelSize aBottomVerSegWidth,
|
|
|
|
BCPixelSize aHorSegHeight)
|
|
|
|
{
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side cornerOwnerSide = NS_SIDE_TOP;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool bevel = false;
|
2009-11-05 12:26:00 +03:00
|
|
|
|
|
|
|
mOwner = aBorderOwner;
|
|
|
|
nscoord cornerSubWidth = (aIter.mBCData) ?
|
|
|
|
aIter.mBCData->GetCorner(cornerOwnerSide,
|
|
|
|
bevel) : 0;
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool leftBevel = (aHorSegHeight > 0) ? bevel : false;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t relColIndex = aIter.GetRelativeColIndex();
|
2011-06-02 16:56:50 +04:00
|
|
|
nscoord maxVerSegWidth = NS_MAX(aIter.mVerInfo[relColIndex].mWidth,
|
2009-11-05 12:26:00 +03:00
|
|
|
aBottomVerSegWidth);
|
|
|
|
nscoord offset = CalcHorCornerOffset(cornerOwnerSide, cornerSubWidth,
|
2011-10-17 18:59:28 +04:00
|
|
|
maxVerSegWidth, true, leftBevel,
|
2009-11-05 12:26:00 +03:00
|
|
|
aIter.mTableIsLTR);
|
|
|
|
mLeftBevelOffset = (leftBevel && (aHorSegHeight > 0)) ? maxVerSegWidth : 0;
|
|
|
|
// XXX this assumes that only corners where 2 segments join can be beveled
|
|
|
|
mLeftBevelSide = (aBottomVerSegWidth > 0) ? NS_SIDE_BOTTOM : NS_SIDE_TOP;
|
|
|
|
if (aIter.mTableIsLTR) {
|
|
|
|
mOffsetX += offset;
|
2004-10-31 18:52:52 +03:00
|
|
|
}
|
|
|
|
else {
|
2009-11-05 12:26:00 +03:00
|
|
|
mOffsetX -= offset;
|
2004-10-31 18:52:52 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
mLength = -offset;
|
|
|
|
mWidth = aHorSegHeight;
|
|
|
|
mFirstCell = aIter.mCell;
|
2012-07-30 18:20:58 +04:00
|
|
|
mAjaCell = (aIter.IsDamageAreaTopMost()) ? nullptr :
|
2009-11-05 12:26:00 +03:00
|
|
|
aIter.mVerInfo[relColIndex].mLastCell;
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Compute the offsets for the right corner of a horizontal segment
|
|
|
|
* @param aIter - iterator containing the structural information
|
|
|
|
* @param aLeftSegWidth - the width of the vertical segment joining the corner
|
|
|
|
* at the start
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCHorizontalSeg::GetRightCorner(BCPaintBorderIterator& aIter,
|
|
|
|
BCPixelSize aLeftSegWidth)
|
|
|
|
{
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side ownerSide = NS_SIDE_TOP;
|
2009-11-05 12:26:00 +03:00
|
|
|
nscoord cornerSubWidth = 0;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool bevel = false;
|
2009-11-05 12:26:00 +03:00
|
|
|
if (aIter.mBCData) {
|
|
|
|
cornerSubWidth = aIter.mBCData->GetCorner(ownerSide, bevel);
|
|
|
|
}
|
|
|
|
|
|
|
|
mIsRightBevel = (mWidth > 0) ? bevel : 0;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t relColIndex = aIter.GetRelativeColIndex();
|
2011-06-02 16:56:50 +04:00
|
|
|
nscoord verWidth = NS_MAX(aIter.mVerInfo[relColIndex].mWidth, aLeftSegWidth);
|
2009-11-05 12:26:00 +03:00
|
|
|
mEndOffset = CalcHorCornerOffset(ownerSide, cornerSubWidth, verWidth,
|
2011-10-17 18:59:28 +04:00
|
|
|
false, mIsRightBevel, aIter.mTableIsLTR);
|
2009-11-05 12:26:00 +03:00
|
|
|
mLength += mEndOffset;
|
|
|
|
mRightBevelOffset = (mIsRightBevel) ?
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(verWidth) : 0;
|
|
|
|
mRightBevelSide = (aLeftSegWidth > 0) ? NS_SIDE_BOTTOM : NS_SIDE_TOP;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Paint the horizontal segment
|
|
|
|
* @param aIter - iterator containing the structural information
|
|
|
|
* @param aRenderingContext - the rendering context
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCHorizontalSeg::Paint(BCPaintBorderIterator& aIter,
|
2011-04-08 05:04:40 +04:00
|
|
|
nsRenderingContext& aRenderingContext)
|
2009-11-05 12:26:00 +03:00
|
|
|
{
|
|
|
|
// get the border style, color and paint the segment
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side side = (aIter.IsDamageAreaBottomMost()) ? NS_SIDE_BOTTOM :
|
2009-11-05 12:26:00 +03:00
|
|
|
NS_SIDE_TOP;
|
2010-01-09 18:33:03 +03:00
|
|
|
nsIFrame* rg = aIter.mRg; if (!rg) ABORT0();
|
|
|
|
nsIFrame* row = aIter.mRow; if (!row) ABORT0();
|
2010-03-06 12:53:04 +03:00
|
|
|
nsIFrame* cell = mFirstCell;
|
2009-11-05 12:26:00 +03:00
|
|
|
nsIFrame* col;
|
2012-07-30 18:20:58 +04:00
|
|
|
nsIFrame* owner = nullptr;
|
2009-11-05 12:26:00 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t style = NS_STYLE_BORDER_STYLE_SOLID;
|
2009-11-05 12:26:00 +03:00
|
|
|
nscolor color = 0xFFFFFFFF;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
switch (mOwner) {
|
|
|
|
case eTableOwner:
|
2010-01-09 18:33:03 +03:00
|
|
|
owner = aIter.mTable;
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
|
|
|
case eAjaColGroupOwner:
|
|
|
|
NS_ERROR("neighboring colgroups can never own a horizontal border");
|
|
|
|
// and fall through
|
2010-04-27 20:15:01 +04:00
|
|
|
case eColGroupOwner:
|
2009-11-05 12:26:00 +03:00
|
|
|
NS_ASSERTION(aIter.IsTableTopMost() || aIter.IsTableBottomMost(),
|
|
|
|
"col group can own border only at the table edge");
|
|
|
|
col = aIter.mTableFirstInFlow->GetColFrame(aIter.mColIndex - 1);
|
|
|
|
if (!col) ABORT0();
|
2010-04-27 20:15:01 +04:00
|
|
|
owner = col->GetParent();
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
|
|
|
case eAjaColOwner:
|
|
|
|
NS_ERROR("neighboring column can never own a horizontal border");
|
|
|
|
// and fall through
|
|
|
|
case eColOwner:
|
|
|
|
NS_ASSERTION(aIter.IsTableTopMost() || aIter.IsTableBottomMost(),
|
|
|
|
"col can own border only at the table edge");
|
2010-01-09 18:33:03 +03:00
|
|
|
owner = aIter.mTableFirstInFlow->GetColFrame(aIter.mColIndex - 1);
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
|
|
|
case eAjaRowGroupOwner:
|
|
|
|
side = NS_SIDE_BOTTOM;
|
|
|
|
rg = (aIter.IsTableBottomMost()) ? aIter.mRg : aIter.mPrevRg;
|
|
|
|
// and fall through
|
|
|
|
case eRowGroupOwner:
|
2010-01-09 18:33:03 +03:00
|
|
|
owner = rg;
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
|
|
|
case eAjaRowOwner:
|
|
|
|
side = NS_SIDE_BOTTOM;
|
|
|
|
row = (aIter.IsTableBottomMost()) ? aIter.mRow : aIter.mPrevRow;
|
|
|
|
// and fall through
|
|
|
|
case eRowOwner:
|
2010-01-09 18:33:03 +03:00
|
|
|
owner = row;
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
|
|
|
case eAjaCellOwner:
|
|
|
|
side = NS_SIDE_BOTTOM;
|
|
|
|
// if this is null due to the damage area origin-y > 0, then the border
|
|
|
|
// won't show up anyway
|
|
|
|
cell = mAjaCell;
|
|
|
|
// and fall through
|
2010-01-09 18:33:03 +03:00
|
|
|
case eCellOwner:
|
|
|
|
owner = cell;
|
2009-11-05 12:26:00 +03:00
|
|
|
break;
|
2009-11-05 11:03:51 +03:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
if (owner) {
|
2010-01-09 18:33:03 +03:00
|
|
|
::GetPaintStyleInfo(owner, side, style, color, aIter.mTableIsLTR);
|
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
BCPixelSize smallHalf, largeHalf;
|
|
|
|
DivideBCBorderSize(mWidth, smallHalf, largeHalf);
|
|
|
|
nsRect segRect(mOffsetX,
|
|
|
|
mOffsetY - nsPresContext::CSSPixelsToAppUnits(largeHalf),
|
|
|
|
mLength,
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(mWidth));
|
|
|
|
if (aIter.mTableIsLTR) {
|
|
|
|
nsCSSRendering::DrawTableBorderSegment(aRenderingContext, style, color,
|
|
|
|
aIter.mTableBgColor, segRect,
|
|
|
|
nsPresContext::AppUnitsPerCSSPixel(),
|
|
|
|
mLeftBevelSide,
|
2010-04-27 20:15:01 +04:00
|
|
|
nsPresContext::CSSPixelsToAppUnits(mLeftBevelOffset),
|
2009-11-05 12:26:00 +03:00
|
|
|
mRightBevelSide, mRightBevelOffset);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
segRect.x -= segRect.width;
|
|
|
|
nsCSSRendering::DrawTableBorderSegment(aRenderingContext, style, color,
|
|
|
|
aIter.mTableBgColor, segRect,
|
|
|
|
nsPresContext::AppUnitsPerCSSPixel(),
|
|
|
|
mRightBevelSide, mRightBevelOffset,
|
|
|
|
mLeftBevelSide,
|
|
|
|
nsPresContext::CSSPixelsToAppUnits(mLeftBevelOffset));
|
|
|
|
}
|
|
|
|
}
|
2004-10-31 18:52:52 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Advance the start point of a segment
|
|
|
|
*/
|
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
BCHorizontalSeg::AdvanceOffsetX(int32_t aIncrement)
|
2009-11-05 12:26:00 +03:00
|
|
|
{
|
|
|
|
mOffsetX += aIncrement * (mLength - mEndOffset);
|
|
|
|
}
|
2009-11-05 11:03:51 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Accumulate the current segment
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCHorizontalSeg::IncludeCurrentBorder(BCPaintBorderIterator& aIter)
|
|
|
|
{
|
|
|
|
mLength += aIter.mVerInfo[aIter.GetRelativeColIndex()].mColWidth;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* store the column width information while painting horizontal segment
|
|
|
|
*/
|
|
|
|
void
|
2012-08-22 19:56:38 +04:00
|
|
|
BCPaintBorderIterator::StoreColumnWidth(int32_t aIndex)
|
2009-11-05 12:26:00 +03:00
|
|
|
{
|
|
|
|
if (IsTableRightMost()) {
|
|
|
|
mVerInfo[aIndex].mColWidth = mVerInfo[aIndex - 1].mColWidth;
|
2009-11-05 11:03:51 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
else {
|
|
|
|
nsTableColFrame* col = mTableFirstInFlow->GetColFrame(mColIndex);
|
|
|
|
if (!col) ABORT0();
|
|
|
|
mVerInfo[aIndex].mColWidth = col->GetSize().width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Determine if a vertical segment owns the corder
|
|
|
|
*/
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2009-11-05 12:26:00 +03:00
|
|
|
BCPaintBorderIterator::VerticalSegmentOwnsCorner()
|
|
|
|
{
|
2010-04-27 20:15:02 +04:00
|
|
|
mozilla::css::Side cornerOwnerSide = NS_SIDE_TOP;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool bevel = false;
|
2011-12-20 07:46:39 +04:00
|
|
|
if (mBCData) {
|
|
|
|
mBCData->GetCorner(cornerOwnerSide, bevel);
|
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
// unitialized ownerside, bevel
|
|
|
|
return (NS_SIDE_TOP == cornerOwnerSide) ||
|
|
|
|
(NS_SIDE_BOTTOM == cornerOwnerSide);
|
|
|
|
}
|
2009-11-05 12:25:26 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Paint if necessary a horizontal segment, otherwise accumulate it
|
|
|
|
* @param aRenderingContext - the rendering context
|
|
|
|
*/
|
|
|
|
void
|
2011-04-08 05:04:40 +04:00
|
|
|
BCPaintBorderIterator::AccumulateOrPaintHorizontalSegment(nsRenderingContext& aRenderingContext)
|
2009-11-05 12:26:00 +03:00
|
|
|
{
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t relColIndex = GetRelativeColIndex();
|
2009-11-05 12:26:00 +03:00
|
|
|
// store the current col width if it hasn't been already
|
|
|
|
if (mVerInfo[relColIndex].mColWidth < 0) {
|
|
|
|
StoreColumnWidth(relColIndex);
|
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
BCBorderOwner borderOwner = eCellOwner;
|
|
|
|
BCBorderOwner ignoreBorderOwner;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isSegStart = true;
|
|
|
|
bool ignoreSegStart;
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2012-01-23 02:48:34 +04:00
|
|
|
nscoord leftSegWidth =
|
|
|
|
mBCData ? mBCData->GetLeftEdge(ignoreBorderOwner, ignoreSegStart) : 0;
|
|
|
|
nscoord topSegHeight =
|
|
|
|
mBCData ? mBCData->GetTopEdge(borderOwner, isSegStart) : 0;
|
2009-11-05 12:26:00 +03:00
|
|
|
|
|
|
|
if (mIsNewRow || (IsDamageAreaLeftMost() && IsDamageAreaBottomMost())) {
|
|
|
|
// reset for every new row and on the bottom of the last row
|
|
|
|
mHorSeg.mOffsetY = mNextOffsetY;
|
|
|
|
mNextOffsetY = mNextOffsetY + mRow->GetSize().height;
|
|
|
|
mHorSeg.mOffsetX = mInitialOffsetX;
|
|
|
|
mHorSeg.Start(*this, borderOwner, leftSegWidth, topSegHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsDamageAreaLeftMost() && (isSegStart || IsDamageAreaRightMost() ||
|
|
|
|
VerticalSegmentOwnsCorner())) {
|
|
|
|
// paint the previous seg or the current one if IsDamageAreaRightMost()
|
|
|
|
if (mHorSeg.mLength > 0) {
|
|
|
|
mHorSeg.GetRightCorner(*this, leftSegWidth);
|
|
|
|
if (mHorSeg.mWidth > 0) {
|
|
|
|
mHorSeg.Paint(*this, aRenderingContext);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
mHorSeg.AdvanceOffsetX(mColInc);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
mHorSeg.Start(*this, borderOwner, leftSegWidth, topSegHeight);
|
|
|
|
}
|
|
|
|
mHorSeg.IncludeCurrentBorder(*this);
|
|
|
|
mVerInfo[relColIndex].mWidth = leftSegWidth;
|
|
|
|
mVerInfo[relColIndex].mLastCell = mCell;
|
|
|
|
}
|
|
|
|
/**
|
|
|
|
* Paint if necessary a vertical segment, otherwise it
|
|
|
|
* @param aRenderingContext - the rendering context
|
|
|
|
*/
|
|
|
|
void
|
2011-04-08 05:04:40 +04:00
|
|
|
BCPaintBorderIterator::AccumulateOrPaintVerticalSegment(nsRenderingContext& aRenderingContext)
|
2009-11-05 12:26:00 +03:00
|
|
|
{
|
|
|
|
BCBorderOwner borderOwner = eCellOwner;
|
|
|
|
BCBorderOwner ignoreBorderOwner;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool isSegStart = true;
|
|
|
|
bool ignoreSegStart;
|
2009-11-05 12:26:00 +03:00
|
|
|
|
2012-01-23 02:48:34 +04:00
|
|
|
nscoord verSegWidth =
|
|
|
|
mBCData ? mBCData->GetLeftEdge(borderOwner, isSegStart) : 0;
|
|
|
|
nscoord horSegHeight =
|
|
|
|
mBCData ? mBCData->GetTopEdge(ignoreBorderOwner, ignoreSegStart) : 0;
|
2009-11-05 12:26:00 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t relColIndex = GetRelativeColIndex();
|
2009-11-05 12:26:00 +03:00
|
|
|
BCVerticalSeg& verSeg = mVerInfo[relColIndex];
|
|
|
|
if (!verSeg.mCol) { // on the first damaged row and the first segment in the
|
|
|
|
// col
|
|
|
|
verSeg.Initialize(*this);
|
|
|
|
verSeg.Start(*this, borderOwner, verSegWidth, horSegHeight);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!IsDamageAreaTopMost() && (isSegStart || IsDamageAreaBottomMost() ||
|
|
|
|
IsAfterRepeatedHeader() ||
|
|
|
|
StartRepeatedFooter())) {
|
|
|
|
// paint the previous seg or the current one if IsDamageAreaBottomMost()
|
|
|
|
if (verSeg.mLength > 0) {
|
|
|
|
verSeg.GetBottomCorner(*this, horSegHeight);
|
|
|
|
if (verSeg.mWidth > 0) {
|
|
|
|
verSeg.Paint(*this, aRenderingContext, horSegHeight);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
verSeg.AdvanceOffsetY();
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
verSeg.Start(*this, borderOwner, verSegWidth, horSegHeight);
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
verSeg.IncludeCurrentBorder(*this);
|
|
|
|
mPrevHorSegHeight = horSegHeight;
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
/**
|
|
|
|
* Reset the vertical information cache
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
BCPaintBorderIterator::ResetVerInfo()
|
|
|
|
{
|
|
|
|
if (mVerInfo) {
|
|
|
|
memset(mVerInfo, 0, mDamageArea.width * sizeof(BCVerticalSeg));
|
|
|
|
// XXX reinitialize properly
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t xIndex = 0; xIndex < mDamageArea.width; xIndex++) {
|
2009-11-05 12:26:00 +03:00
|
|
|
mVerInfo[xIndex].mColWidth = -1;
|
2004-10-31 18:52:52 +03:00
|
|
|
}
|
|
|
|
}
|
2009-11-05 12:26:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Method to paint BCBorders, this does not use currently display lists although
|
|
|
|
* it will do this in future
|
|
|
|
* @param aRenderingContext - the rendering context
|
|
|
|
* @param aDirtyRect - inside this rectangle the BC Borders will redrawn
|
|
|
|
*/
|
2010-04-27 20:15:01 +04:00
|
|
|
void
|
2011-04-08 05:04:40 +04:00
|
|
|
nsTableFrame::PaintBCBorders(nsRenderingContext& aRenderingContext,
|
2009-11-05 12:26:00 +03:00
|
|
|
const nsRect& aDirtyRect)
|
|
|
|
{
|
|
|
|
// We first transfer the aDirtyRect into cellmap coordinates to compute which
|
|
|
|
// cell borders need to be painted
|
|
|
|
BCPaintBorderIterator iter(this);
|
|
|
|
if (!iter.SetDamageArea(aDirtyRect))
|
2004-01-02 11:26:36 +03:00
|
|
|
return;
|
2004-10-31 18:52:52 +03:00
|
|
|
|
2009-11-05 12:26:00 +03:00
|
|
|
// First, paint all of the vertical borders from top to bottom and left to
|
|
|
|
// right as they become complete. They are painted first, since they are less
|
|
|
|
// efficient to paint than horizontal segments. They were stored with as few
|
|
|
|
// segments as possible (since horizontal borders are painted last and
|
|
|
|
// possibly over them). For every cell in a row that fails in the damage are
|
|
|
|
// we look up if the current border would start a new segment, if so we paint
|
|
|
|
// the previously stored vertical segment and start a new segment. After
|
|
|
|
// this we the now active segment with the current border. These
|
|
|
|
// segments are stored in mVerInfo to be used on the next row
|
|
|
|
for (iter.First(); !iter.mAtEnd; iter.Next()) {
|
|
|
|
iter.AccumulateOrPaintVerticalSegment(aRenderingContext);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Next, paint all of the horizontal border segments from top to bottom reuse
|
|
|
|
// the mVerInfo array to keep track of col widths and vertical segments for
|
|
|
|
// corner calculations
|
|
|
|
iter.Reset();
|
|
|
|
for (iter.First(); !iter.mAtEnd; iter.Next()) {
|
|
|
|
iter.AccumulateOrPaintHorizontalSegment(aRenderingContext);
|
|
|
|
}
|
2002-02-19 18:48:28 +03:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
bool nsTableFrame::RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols)
|
1999-09-01 08:36:47 +04:00
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool result = false;
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-09-01 08:36:47 +04:00
|
|
|
NS_PRECONDITION (cellMap, "bad call, cellMap not yet allocated.");
|
|
|
|
if (cellMap) {
|
2005-11-04 21:41:32 +03:00
|
|
|
result = cellMap->RowHasSpanningCells(aRowIndex, aNumEffCols);
|
1999-09-01 08:36:47 +04:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
bool nsTableFrame::RowIsSpannedInto(int32_t aRowIndex, int32_t aNumEffCols)
|
1999-07-28 12:09:02 +04:00
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool result = false;
|
2000-01-13 08:29:38 +03:00
|
|
|
nsTableCellMap* cellMap = GetCellMap();
|
1999-08-19 23:52:37 +04:00
|
|
|
NS_PRECONDITION (cellMap, "bad call, cellMap not yet allocated.");
|
|
|
|
if (cellMap) {
|
2005-11-04 21:41:32 +03:00
|
|
|
result = cellMap->RowIsSpannedInto(aRowIndex, aNumEffCols);
|
1999-07-28 12:09:02 +04:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2012-08-29 09:48:45 +04:00
|
|
|
|
|
|
|
/* static */
|
|
|
|
void
|
|
|
|
nsTableFrame::InvalidateTableFrame(nsIFrame* aFrame,
|
|
|
|
const nsRect& aOrigRect,
|
|
|
|
const nsRect& aOrigVisualOverflow,
|
|
|
|
bool aIsFirstReflow)
|
|
|
|
{
|
|
|
|
nsIFrame* parent = aFrame->GetParent();
|
|
|
|
NS_ASSERTION(parent, "What happened here?");
|
|
|
|
|
|
|
|
if (parent->GetStateBits() & NS_FRAME_FIRST_REFLOW) {
|
|
|
|
// Don't bother; we'll invalidate the parent's overflow rect when
|
|
|
|
// we finish reflowing it.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The part that looks at both the rect and the overflow rect is a
|
|
|
|
// bit of a hack. See nsBlockFrame::ReflowLine for an eloquent
|
|
|
|
// description of its hackishness.
|
|
|
|
//
|
|
|
|
// This doesn't really make sense now that we have DLBI.
|
|
|
|
// This code can probably be simplified a fair bit.
|
|
|
|
nsRect visualOverflow = aFrame->GetVisualOverflowRect();
|
|
|
|
if (aIsFirstReflow ||
|
|
|
|
aOrigRect.TopLeft() != aFrame->GetPosition() ||
|
|
|
|
aOrigVisualOverflow.TopLeft() != visualOverflow.TopLeft()) {
|
|
|
|
// Invalidate the old and new overflow rects. Note that if the
|
|
|
|
// frame moved, we can't just use aOrigVisualOverflow, since it's in
|
|
|
|
// coordinates relative to the old position. So invalidate via
|
|
|
|
// aFrame's parent, and reposition that overflow rect to the right
|
|
|
|
// place.
|
|
|
|
// XXXbz this doesn't handle outlines, does it?
|
|
|
|
aFrame->InvalidateFrame();
|
|
|
|
parent->InvalidateFrameWithRect(aOrigVisualOverflow + aOrigRect.TopLeft());
|
|
|
|
} else {
|
|
|
|
aFrame->InvalidateFrameWithRect(aOrigVisualOverflow);;
|
|
|
|
aFrame->InvalidateFrame();
|
|
|
|
parent->InvalidateFrameWithRect(aOrigRect);;
|
|
|
|
parent->InvalidateFrame();
|
|
|
|
}
|
|
|
|
}
|