Change the way HTML tables are rendered.
This commit is contained in:
parent
5cfd8a746e
commit
133c7d2f81
|
@ -474,15 +474,6 @@ RecomputePosition(nsIFrame* aFrame)
|
||||||
if (display->IsRelativelyPositionedStyle()) {
|
if (display->IsRelativelyPositionedStyle()) {
|
||||||
// Move the frame
|
// Move the frame
|
||||||
if (display->mPosition == NS_STYLE_POSITION_STICKY) {
|
if (display->mPosition == NS_STYLE_POSITION_STICKY) {
|
||||||
if (display->IsInnerTableStyle()) {
|
|
||||||
// We don't currently support sticky positioning of inner table
|
|
||||||
// elements (bug 975644). Bail.
|
|
||||||
//
|
|
||||||
// When this is fixed, remove the null-check for the computed
|
|
||||||
// offsets in nsTableRowFrame::ReflowChildren.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update sticky positioning for an entire element at once, starting with
|
// Update sticky positioning for an entire element at once, starting with
|
||||||
// the first continuation or ib-split sibling.
|
// the first continuation or ib-split sibling.
|
||||||
// It's rare that the frame we already have isn't already the first
|
// It's rare that the frame we already have isn't already the first
|
||||||
|
|
|
@ -56,9 +56,7 @@ DECLARE_DISPLAY_ITEM_TYPE(SVG_PATH_GEOMETRY)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT)
|
DECLARE_DISPLAY_ITEM_TYPE(SVG_TEXT)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND)
|
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_BACKGROUND)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION)
|
DECLARE_DISPLAY_ITEM_TYPE(TABLE_CELL_SELECTION)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_BACKGROUND)
|
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_COLLAPSE)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_ROW_GROUP_BACKGROUND)
|
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(TABLE_BORDER_BACKGROUND)
|
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(TEXT)
|
DECLARE_DISPLAY_ITEM_TYPE(TEXT)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW)
|
DECLARE_DISPLAY_ITEM_TYPE(TEXT_OVERFLOW)
|
||||||
DECLARE_DISPLAY_ITEM_TYPE_FLAGS(TRANSFORM,TYPE_RENDERS_NO_IMAGES)
|
DECLARE_DISPLAY_ITEM_TYPE_FLAGS(TRANSFORM,TYPE_RENDERS_NO_IMAGES)
|
||||||
|
|
|
@ -80,6 +80,8 @@
|
||||||
#include "nsPluginFrame.h"
|
#include "nsPluginFrame.h"
|
||||||
#include "DisplayItemScrollClip.h"
|
#include "DisplayItemScrollClip.h"
|
||||||
#include "nsSVGMaskFrame.h"
|
#include "nsSVGMaskFrame.h"
|
||||||
|
#include "nsTableCellFrame.h"
|
||||||
|
#include "nsTableColFrame.h"
|
||||||
|
|
||||||
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
||||||
// GetTickCount().
|
// GetTickCount().
|
||||||
|
@ -2631,11 +2633,17 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
|
||||||
const nsRect& aBackgroundRect,
|
const nsRect& aBackgroundRect,
|
||||||
nsDisplayList* aList,
|
nsDisplayList* aList,
|
||||||
bool aAllowWillPaintBorderOptimization,
|
bool aAllowWillPaintBorderOptimization,
|
||||||
nsStyleContext* aStyleContext)
|
nsStyleContext* aStyleContext,
|
||||||
|
const nsRect& aBackgroundOriginRect,
|
||||||
|
nsIFrame* aSecondaryReferenceFrame)
|
||||||
{
|
{
|
||||||
nsStyleContext* bgSC = aStyleContext;
|
nsStyleContext* bgSC = aStyleContext;
|
||||||
const nsStyleBackground* bg = nullptr;
|
const nsStyleBackground* bg = nullptr;
|
||||||
nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
|
nsRect bgRect = aBackgroundRect + aBuilder->ToReferenceFrame(aFrame);
|
||||||
|
nsRect bgOriginRect = bgRect;
|
||||||
|
if (!aBackgroundOriginRect.IsEmpty()) {
|
||||||
|
bgOriginRect = aBackgroundOriginRect + aBuilder->ToReferenceFrame(aFrame);
|
||||||
|
}
|
||||||
nsPresContext* presContext = aFrame->PresContext();
|
nsPresContext* presContext = aFrame->PresContext();
|
||||||
bool isThemed = aFrame->IsThemed();
|
bool isThemed = aFrame->IsThemed();
|
||||||
if (!isThemed) {
|
if (!isThemed) {
|
||||||
|
@ -2743,12 +2751,31 @@ nsDisplayBackgroundImage::AppendBackgroundItemsToTop(nsDisplayListBuilder* aBuil
|
||||||
}
|
}
|
||||||
|
|
||||||
nsDisplayList thisItemList;
|
nsDisplayList thisItemList;
|
||||||
nsDisplayBackgroundImage* bgItem =
|
nsDisplayBackgroundImage* bgItem;
|
||||||
new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgRect, bg);
|
if (aSecondaryReferenceFrame) {
|
||||||
|
bgItem =
|
||||||
|
new (aBuilder) nsDisplayTableBackgroundImage(aBuilder,
|
||||||
|
aFrame,
|
||||||
|
i,
|
||||||
|
bgOriginRect,
|
||||||
|
bg,
|
||||||
|
aSecondaryReferenceFrame);
|
||||||
|
} else {
|
||||||
|
bgItem =
|
||||||
|
new (aBuilder) nsDisplayBackgroundImage(aBuilder, aFrame, i, bgOriginRect, bg);
|
||||||
|
}
|
||||||
if (bgItem->ShouldFixToViewport(aBuilder)) {
|
if (bgItem->ShouldFixToViewport(aBuilder)) {
|
||||||
thisItemList.AppendNewToTop(
|
if (aSecondaryReferenceFrame) {
|
||||||
nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i));
|
thisItemList.AppendNewToTop(
|
||||||
|
nsDisplayTableFixedPosition::CreateForFixedBackground(aBuilder,
|
||||||
|
aSecondaryReferenceFrame,
|
||||||
|
bgItem,
|
||||||
|
i,
|
||||||
|
aFrame));
|
||||||
|
} else {
|
||||||
|
thisItemList.AppendNewToTop(
|
||||||
|
nsDisplayFixedPosition::CreateForFixedBackground(aBuilder, aFrame, bgItem, i));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
thisItemList.AppendNewToTop(bgItem);
|
thisItemList.AppendNewToTop(bgItem);
|
||||||
}
|
}
|
||||||
|
@ -2889,7 +2916,7 @@ nsDisplayBackgroundImage::ImageLayerization
|
||||||
nsDisplayBackgroundImage::ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
|
nsDisplayBackgroundImage::ShouldCreateOwnLayer(nsDisplayListBuilder* aBuilder,
|
||||||
LayerManager* aManager)
|
LayerManager* aManager)
|
||||||
{
|
{
|
||||||
nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(mFrame);
|
nsIFrame* backgroundStyleFrame = nsCSSRendering::FindBackgroundStyleFrame(StyleFrame());
|
||||||
if (ActiveLayerTracker::IsBackgroundPositionAnimated(aBuilder,
|
if (ActiveLayerTracker::IsBackgroundPositionAnimated(aBuilder,
|
||||||
backgroundStyleFrame)) {
|
backgroundStyleFrame)) {
|
||||||
return WHENEVER_POSSIBLE;
|
return WHENEVER_POSSIBLE;
|
||||||
|
@ -3144,16 +3171,16 @@ nsDisplayBackgroundImage::PaintInternal(nsDisplayListBuilder* aBuilder,
|
||||||
StyleGeometryBox clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip;
|
StyleGeometryBox clip = mBackgroundStyle->mImage.mLayers[mLayer].mClip;
|
||||||
|
|
||||||
if (clip == StyleGeometryBox::Text) {
|
if (clip == StyleGeometryBox::Text) {
|
||||||
if (!GenerateAndPushTextMask(mFrame, aCtx, mBackgroundRect, aBuilder)) {
|
if (!GenerateAndPushTextMask(StyleFrame(), aCtx, mBackgroundRect, aBuilder)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCSSRendering::PaintBGParams params =
|
nsCSSRendering::PaintBGParams params =
|
||||||
nsCSSRendering::PaintBGParams::ForSingleLayer(*mFrame->PresContext(),
|
nsCSSRendering::PaintBGParams::ForSingleLayer(*StyleFrame()->PresContext(),
|
||||||
*aCtx,
|
*aCtx,
|
||||||
aBounds, mBackgroundRect,
|
aBounds, mBackgroundRect,
|
||||||
mFrame, flags, mLayer,
|
StyleFrame(), flags, mLayer,
|
||||||
CompositionOp::OP_OVER);
|
CompositionOp::OP_OVER);
|
||||||
params.bgClipRect = aClipRect;
|
params.bgClipRect = aClipRect;
|
||||||
image::DrawResult result =
|
image::DrawResult result =
|
||||||
|
@ -3255,6 +3282,27 @@ nsDisplayBackgroundImage::GetPerFrameKey()
|
||||||
nsDisplayItem::GetPerFrameKey();
|
nsDisplayItem::GetPerFrameKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsDisplayTableBackgroundImage::nsDisplayTableBackgroundImage(nsDisplayListBuilder* aBuilder,
|
||||||
|
nsIFrame* aFrame,
|
||||||
|
uint32_t aLayer,
|
||||||
|
const nsRect& aBackgroundRect,
|
||||||
|
const nsStyleBackground* aBackgroundStyle,
|
||||||
|
nsIFrame* aCellFrame)
|
||||||
|
: nsDisplayBackgroundImage(aBuilder, aFrame, aLayer, aBackgroundRect, aBackgroundStyle)
|
||||||
|
, mStyleFrame(aFrame)
|
||||||
|
, mTableType(GetTableTypeFromFrame(mStyleFrame))
|
||||||
|
{
|
||||||
|
mFrame = aCellFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsDisplayTableBackgroundImage::IsInvalid(nsRect& aRect)
|
||||||
|
{
|
||||||
|
bool result = mStyleFrame ? mStyleFrame->IsInvalid(aRect) : false;
|
||||||
|
aRect += ToReferenceFrame();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
nsDisplayThemedBackground::nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder,
|
nsDisplayThemedBackground::nsDisplayThemedBackground(nsDisplayListBuilder* aBuilder,
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
const nsRect& aBackgroundRect)
|
const nsRect& aBackgroundRect)
|
||||||
|
@ -5272,6 +5320,51 @@ bool nsDisplayFixedPosition::TryMerge(nsDisplayItem* aItem) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TableType
|
||||||
|
GetTableTypeFromFrame(nsIFrame* aFrame)
|
||||||
|
{
|
||||||
|
nsIAtom* type = aFrame->GetType();
|
||||||
|
if (type == nsGkAtoms::tableFrame) {
|
||||||
|
return TableType::TABLE;
|
||||||
|
} else if (type == nsGkAtoms::tableColFrame) {
|
||||||
|
return TableType::TABLE_COL;
|
||||||
|
} else if (type == nsGkAtoms::tableColGroupFrame) {
|
||||||
|
return TableType::TABLE_COL_GROUP;
|
||||||
|
} else if (type == nsGkAtoms::tableRowFrame) {
|
||||||
|
return TableType::TABLE_ROW;
|
||||||
|
} else if (type == nsGkAtoms::tableRowGroupFrame) {
|
||||||
|
return TableType::TABLE_ROW_GROUP;
|
||||||
|
} else if (type == nsGkAtoms::tableCellFrame) {
|
||||||
|
return TableType::TABLE_CELL;
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT_UNREACHABLE("Invalid frame.");
|
||||||
|
return TableType::TABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nsDisplayTableFixedPosition::nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder,
|
||||||
|
nsIFrame* aFrame,
|
||||||
|
nsDisplayList* aList,
|
||||||
|
uint32_t aIndex,
|
||||||
|
nsIFrame* aAncestorFrame)
|
||||||
|
: nsDisplayFixedPosition(aBuilder, aFrame, aList, aIndex)
|
||||||
|
, mTableType(GetTableTypeFromFrame(aAncestorFrame))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ nsDisplayTableFixedPosition*
|
||||||
|
nsDisplayTableFixedPosition::CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
|
||||||
|
nsIFrame* aFrame,
|
||||||
|
nsDisplayBackgroundImage* aImage,
|
||||||
|
uint32_t aIndex,
|
||||||
|
nsIFrame* aAncestorFrame)
|
||||||
|
{
|
||||||
|
nsDisplayList temp;
|
||||||
|
temp.AppendToTop(aImage);
|
||||||
|
|
||||||
|
return new (aBuilder) nsDisplayTableFixedPosition(aBuilder, aFrame, &temp, aIndex + 1, aAncestorFrame);
|
||||||
|
}
|
||||||
|
|
||||||
nsDisplayStickyPosition::nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder,
|
nsDisplayStickyPosition::nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder,
|
||||||
nsIFrame* aFrame,
|
nsIFrame* aFrame,
|
||||||
nsDisplayList* aList)
|
nsDisplayList* aList)
|
||||||
|
|
|
@ -2737,7 +2737,9 @@ public:
|
||||||
const nsRect& aBackgroundRect,
|
const nsRect& aBackgroundRect,
|
||||||
nsDisplayList* aList,
|
nsDisplayList* aList,
|
||||||
bool aAllowWillPaintBorderOptimization = true,
|
bool aAllowWillPaintBorderOptimization = true,
|
||||||
nsStyleContext* aStyleContext = nullptr);
|
nsStyleContext* aStyleContext = nullptr,
|
||||||
|
const nsRect& aBackgroundOriginRect = nsRect(),
|
||||||
|
nsIFrame* aSecondaryReferenceFrame = nullptr);
|
||||||
|
|
||||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||||
LayerManager* aManager,
|
LayerManager* aManager,
|
||||||
|
@ -2812,6 +2814,8 @@ protected:
|
||||||
void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
|
void PaintInternal(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx,
|
||||||
const nsRect& aBounds, nsRect* aClipRect);
|
const nsRect& aBounds, nsRect* aClipRect);
|
||||||
|
|
||||||
|
virtual nsIFrame* StyleFrame() { return mFrame; }
|
||||||
|
|
||||||
// Determine whether we want to be separated into our own layer, independent
|
// Determine whether we want to be separated into our own layer, independent
|
||||||
// of whether this item can actually be layerized.
|
// of whether this item can actually be layerized.
|
||||||
enum ImageLayerization {
|
enum ImageLayerization {
|
||||||
|
@ -2837,6 +2841,60 @@ protected:
|
||||||
bool mShouldTreatAsFixed;
|
bool mShouldTreatAsFixed;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class TableType : uint8_t {
|
||||||
|
TABLE,
|
||||||
|
TABLE_COL,
|
||||||
|
TABLE_COL_GROUP,
|
||||||
|
TABLE_ROW,
|
||||||
|
TABLE_ROW_GROUP,
|
||||||
|
TABLE_CELL,
|
||||||
|
|
||||||
|
TABLE_TYPE_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class TableTypeBits : uint8_t {
|
||||||
|
COUNT = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(
|
||||||
|
static_cast<uint8_t>(TableType::TABLE_TYPE_MAX) < (1 << (static_cast<uint8_t>(TableTypeBits::COUNT) + 1)),
|
||||||
|
"TableType cannot fit with TableTypeBits::COUNT");
|
||||||
|
TableType GetTableTypeFromFrame(nsIFrame* aFrame);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A display item to paint background image for table. For table parts, such
|
||||||
|
* as row, row group, col, col group, when drawing its background, we'll
|
||||||
|
* create separate background image display item for its containning cell.
|
||||||
|
* Those background image display items will reference to same DisplayItemData
|
||||||
|
* if we keep the mFrame point to cell's ancestor frame. We don't want to this
|
||||||
|
* happened bacause share same DisplatItemData will cause many bugs. So that
|
||||||
|
* we let mFrame point to cell frame and store the table type of the ancestor
|
||||||
|
* frame. And use mFrame and table type as key to generate DisplayItemData to
|
||||||
|
* avoid sharing DisplayItemData.
|
||||||
|
*
|
||||||
|
* Also store ancestor frame as mStyleFrame for all rendering informations.
|
||||||
|
*/
|
||||||
|
class nsDisplayTableBackgroundImage : public nsDisplayBackgroundImage {
|
||||||
|
public:
|
||||||
|
nsDisplayTableBackgroundImage(nsDisplayListBuilder* aBuilder,
|
||||||
|
nsIFrame* aFrame,
|
||||||
|
uint32_t aLayer,
|
||||||
|
const nsRect& aBackgroundRect,
|
||||||
|
const nsStyleBackground* aBackgroundStyle,
|
||||||
|
nsIFrame* aCellFrame);
|
||||||
|
|
||||||
|
virtual uint32_t GetPerFrameKey() override {
|
||||||
|
return (static_cast<uint8_t>(mTableType) << nsDisplayItem::TYPE_BITS) |
|
||||||
|
nsDisplayItem::GetPerFrameKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsInvalid(nsRect& aRect) override;
|
||||||
|
protected:
|
||||||
|
virtual nsIFrame* StyleFrame() override { return mStyleFrame; }
|
||||||
|
|
||||||
|
nsIFrame* mStyleFrame;
|
||||||
|
TableType mTableType;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A display item to paint the native theme background for a frame.
|
* A display item to paint the native theme background for a frame.
|
||||||
|
@ -3735,7 +3793,7 @@ public:
|
||||||
return mAnimatedGeometryRootForScrollMetadata;
|
return mAnimatedGeometryRootForScrollMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
// For background-attachment:fixed
|
// For background-attachment:fixed
|
||||||
nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
nsDisplayFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||||
nsDisplayList* aList, uint32_t aIndex);
|
nsDisplayList* aList, uint32_t aIndex);
|
||||||
|
@ -3746,6 +3804,27 @@ private:
|
||||||
bool mIsFixedBackground;
|
bool mIsFixedBackground;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class nsDisplayTableFixedPosition : public nsDisplayFixedPosition
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static nsDisplayTableFixedPosition* CreateForFixedBackground(nsDisplayListBuilder* aBuilder,
|
||||||
|
nsIFrame* aFrame,
|
||||||
|
nsDisplayBackgroundImage* aImage,
|
||||||
|
uint32_t aIndex,
|
||||||
|
nsIFrame* aAncestorFrame);
|
||||||
|
|
||||||
|
virtual uint32_t GetPerFrameKey() override {
|
||||||
|
return (mIndex << (nsDisplayItem::TYPE_BITS + static_cast<uint8_t>(TableTypeBits::COUNT))) |
|
||||||
|
(static_cast<uint8_t>(mTableType) << nsDisplayItem::TYPE_BITS) |
|
||||||
|
nsDisplayItem::GetPerFrameKey();
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
nsDisplayTableFixedPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||||
|
nsDisplayList* aList, uint32_t aIndex, nsIFrame* aAncestorFrame);
|
||||||
|
|
||||||
|
TableType mTableType;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This creates an empty scrollable layer. It has no child layers.
|
* This creates an empty scrollable layer. It has no child layers.
|
||||||
* It is used to record the existence of a scrollable frame in the layer
|
* It is used to record the existence of a scrollable frame in the layer
|
||||||
|
|
|
@ -45,7 +45,7 @@ StickyScrollContainer::GetStickyScrollContainerForFrame(nsIFrame* aFrame)
|
||||||
// <html style="position: fixed">
|
// <html style="position: fixed">
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto frame = static_cast<nsIFrame*>(do_QueryFrame(scrollFrame));
|
nsIFrame* frame = do_QueryFrame(scrollFrame);
|
||||||
StickyScrollContainer* s =
|
StickyScrollContainer* s =
|
||||||
frame->GetProperty(StickyScrollContainerProperty());
|
frame->GetProperty(StickyScrollContainerProperty());
|
||||||
if (!s) {
|
if (!s) {
|
||||||
|
@ -176,6 +176,14 @@ StickyScrollContainer::ComputeStickyLimits(nsIFrame* aFrame, nsRect* aStick,
|
||||||
nsRect rect =
|
nsRect rect =
|
||||||
nsLayoutUtils::GetAllInFlowRectsUnion(aFrame, aFrame->GetParent());
|
nsLayoutUtils::GetAllInFlowRectsUnion(aFrame, aFrame->GetParent());
|
||||||
|
|
||||||
|
// Note: Table row groups aren't supposed to be containing blocks, but we treat
|
||||||
|
// them as such anyway.
|
||||||
|
// Not having this basically disables position:sticky on table cells, which
|
||||||
|
// would be really unfortunate, and doesn't match what other browsers do.
|
||||||
|
if (cbFrame != scrolledFrame && cbFrame->GetType() == nsGkAtoms::tableRowGroupFrame) {
|
||||||
|
cbFrame = cbFrame->GetContainingBlock();
|
||||||
|
}
|
||||||
|
|
||||||
// Containing block limits for the position of aFrame relative to its parent.
|
// Containing block limits for the position of aFrame relative to its parent.
|
||||||
// The margin box of the sticky element stays within the content box of the
|
// The margin box of the sticky element stays within the content box of the
|
||||||
// contaning-block element.
|
// contaning-block element.
|
||||||
|
|
|
@ -562,15 +562,12 @@ nsFrame::Init(nsIContent* aContent,
|
||||||
}
|
}
|
||||||
if (disp->mPosition == NS_STYLE_POSITION_STICKY &&
|
if (disp->mPosition == NS_STYLE_POSITION_STICKY &&
|
||||||
!aPrevInFlow &&
|
!aPrevInFlow &&
|
||||||
!(mState & NS_FRAME_IS_NONDISPLAY) &&
|
!(mState & NS_FRAME_IS_NONDISPLAY)) {
|
||||||
!disp->IsInnerTableStyle()) {
|
|
||||||
// Note that we only add first continuations, but we really only
|
// Note that we only add first continuations, but we really only
|
||||||
// want to add first continuation-or-ib-split-siblings. But since we
|
// want to add first continuation-or-ib-split-siblings. But since we
|
||||||
// don't yet know if we're a later part of a block-in-inline split,
|
// don't yet know if we're a later part of a block-in-inline split,
|
||||||
// we'll just add later members of a block-in-inline split here, and
|
// we'll just add later members of a block-in-inline split here, and
|
||||||
// then StickyScrollContainer will remove them later.
|
// then StickyScrollContainer will remove them later.
|
||||||
// We don't currently support relative positioning of inner table
|
|
||||||
// elements (bug 35168), so exclude them from sticky positioning too.
|
|
||||||
StickyScrollContainer* ssc =
|
StickyScrollContainer* ssc =
|
||||||
StickyScrollContainer::GetStickyScrollContainerForFrame(this);
|
StickyScrollContainer::GetStickyScrollContainerForFrame(this);
|
||||||
if (ssc) {
|
if (ssc) {
|
||||||
|
@ -6629,6 +6626,9 @@ GetNearestBlockContainer(nsIFrame* frame)
|
||||||
// Since the parent of such a block is either a normal block or
|
// Since the parent of such a block is either a normal block or
|
||||||
// another such pseudo, this shouldn't cause anything bad to happen.
|
// another such pseudo, this shouldn't cause anything bad to happen.
|
||||||
// Also the anonymous blocks inside table cells are not containing blocks.
|
// Also the anonymous blocks inside table cells are not containing blocks.
|
||||||
|
//
|
||||||
|
// If we ever start skipping table row groups from being containing blocks,
|
||||||
|
// we need to remove the containing block assignment in StickyScrollContainer .
|
||||||
while (frame->IsFrameOfType(nsIFrame::eLineParticipant) ||
|
while (frame->IsFrameOfType(nsIFrame::eLineParticipant) ||
|
||||||
frame->IsBlockWrapper() ||
|
frame->IsBlockWrapper() ||
|
||||||
// Table rows are not containing blocks either
|
// Table rows are not containing blocks either
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<!-- Any copyright is dedicated to the Public Domain.
|
|
||||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<link rel="author" title="Corey Ford" href="mailto:corey@coreyford.name">
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<td>a</td>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tr>
|
|
||||||
<td>b</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>c</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>d</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,35 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<!-- Any copyright is dedicated to the Public Domain.
|
|
||||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<title>CSS Test: Sticky Positioning - inner table elements</title>
|
|
||||||
<link rel="author" title="Corey Ford" href="mailto:corey@coreyford.name">
|
|
||||||
<link rel="match" href="inner-table-1-ref.html">
|
|
||||||
<meta name="assert" content="Sticky positioning on inner table elements should have no effect (until bug 35168 is fixed)">
|
|
||||||
<style>
|
|
||||||
.sticky {
|
|
||||||
position: sticky;
|
|
||||||
top: 1000px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<table>
|
|
||||||
<thead class="sticky">
|
|
||||||
<tr>
|
|
||||||
<td>a</td>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tr class="sticky">
|
|
||||||
<td>b</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="sticky">c</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>d</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -48,4 +48,3 @@ fails == column-contain-1a.html column-contain-1-ref.html
|
||||||
fuzzy-if(skiaContent,1,22) fuzzy-if(winWidget&&!layersGPUAccelerated,116,1320) fuzzy-if(Android,8,1533) == block-in-inline-2.html block-in-inline-2-ref.html
|
fuzzy-if(skiaContent,1,22) fuzzy-if(winWidget&&!layersGPUAccelerated,116,1320) fuzzy-if(Android,8,1533) == block-in-inline-2.html block-in-inline-2-ref.html
|
||||||
fuzzy-if(Android,8,630) fuzzy-if(OSX>=1008,1,11) fuzzy-if(skiaContent,1,220) fuzzy-if(winWidget&&!layersGPUAccelerated,116,1320) == block-in-inline-3.html block-in-inline-3-ref.html
|
fuzzy-if(Android,8,630) fuzzy-if(OSX>=1008,1,11) fuzzy-if(skiaContent,1,220) fuzzy-if(winWidget&&!layersGPUAccelerated,116,1320) == block-in-inline-3.html block-in-inline-3-ref.html
|
||||||
== block-in-inline-continuations.html block-in-inline-continuations-ref.html
|
== block-in-inline-continuations.html block-in-inline-continuations-ref.html
|
||||||
fuzzy-if(winWidget&&!layersGPUAccelerated,140,140) == inner-table-1.html inner-table-1-ref.html
|
|
||||||
|
|
|
@ -44,11 +44,11 @@ fuzzy-if(d2d,1,1083) fuzzy-if(skiaContent,1,2200) == border-collapse-opacity-tab
|
||||||
fails == border-collapse-opacity-table-column-group.html border-collapse-opacity-table-column-group-ref.html # bug 424274
|
fails == border-collapse-opacity-table-column-group.html border-collapse-opacity-table-column-group-ref.html # bug 424274
|
||||||
fails == border-collapse-opacity-table-column.html border-collapse-opacity-table-column-ref.html # bug 424274
|
fails == border-collapse-opacity-table-column.html border-collapse-opacity-table-column-ref.html # bug 424274
|
||||||
fuzzy-if(d2d,1,16359) fuzzy-if(skiaContent,1,17000) == border-collapse-opacity-table-row-group.html border-collapse-opacity-table-row-group-ref.html
|
fuzzy-if(d2d,1,16359) fuzzy-if(skiaContent,1,17000) == border-collapse-opacity-table-row-group.html border-collapse-opacity-table-row-group-ref.html
|
||||||
fuzzy-if(d2d,1,5453) fuzzy-if(skiaContent,1,11000) == border-collapse-opacity-table-row.html border-collapse-opacity-table-row-ref.html
|
fuzzy-if(d2d,1,11000) fuzzy-if(skiaContent,1,11000) == border-collapse-opacity-table-row.html border-collapse-opacity-table-row-ref.html
|
||||||
fuzzy-if(d2d||skiaContent,1,60000) == border-collapse-opacity-table.html border-collapse-opacity-table-ref.html
|
fuzzy-if(d2d||skiaContent,1,60000) == border-collapse-opacity-table.html border-collapse-opacity-table-ref.html
|
||||||
fuzzy-if(d2d,1,2478) fuzzy-if(skiaContent,1,2500) == border-separate-opacity-table-cell.html border-separate-opacity-table-cell-ref.html
|
fuzzy-if(d2d,1,2478) fuzzy-if(skiaContent,1,2500) == border-separate-opacity-table-cell.html border-separate-opacity-table-cell-ref.html
|
||||||
fails == border-separate-opacity-table-column-group.html border-separate-opacity-table-column-group-ref.html # bug 424274
|
fuzzy-if(d2d,1,38000) == border-separate-opacity-table-column-group.html border-separate-opacity-table-column-group-ref.html # bug 424274
|
||||||
fails == border-separate-opacity-table-column.html border-separate-opacity-table-column-ref.html # bug 424274
|
fuzzy-if(d2d,1,13000) == border-separate-opacity-table-column.html border-separate-opacity-table-column-ref.html # bug 424274
|
||||||
fuzzy-if(d2d,1,37170) fuzzy-if(skiaContent,1,38000) == border-separate-opacity-table-row-group.html border-separate-opacity-table-row-group-ref.html
|
fuzzy-if(d2d,1,37170) fuzzy-if(skiaContent,1,38000) == border-separate-opacity-table-row-group.html border-separate-opacity-table-row-group-ref.html
|
||||||
fuzzy-if(d2d,1,12390) fuzzy-if(skiaContent,1,13000) == border-separate-opacity-table-row.html border-separate-opacity-table-row-ref.html
|
fuzzy-if(d2d,1,12390) fuzzy-if(skiaContent,1,13000) == border-separate-opacity-table-row.html border-separate-opacity-table-row-ref.html
|
||||||
fuzzy-if(d2d||skiaContent,1,95000) == border-separate-opacity-table.html border-separate-opacity-table-ref.html
|
fuzzy-if(d2d||skiaContent,1,95000) == border-separate-opacity-table.html border-separate-opacity-table-ref.html
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
background-color: rgb(0, 255, 0);
|
||||||
|
margin-bottom: 10px;
|
||||||
|
height: 100px;
|
||||||
|
width:100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<style>
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
td {
|
||||||
|
background-color: rgb(0, 255, 0);
|
||||||
|
margin-bottom: 10px;
|
||||||
|
height: 100px;
|
||||||
|
width:100px;
|
||||||
|
border-radius: 50px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
|
@ -20,6 +20,7 @@
|
||||||
== bc_dyn_table3.html bc_dyn_table3_ref.html
|
== bc_dyn_table3.html bc_dyn_table3_ref.html
|
||||||
== bc_borderoffset1.html bc_borderoffset1_ref.html
|
== bc_borderoffset1.html bc_borderoffset1_ref.html
|
||||||
== bc_borderoffset2.html bc_borderoffset2_ref.html
|
== bc_borderoffset2.html bc_borderoffset2_ref.html
|
||||||
|
== bc_borderradius.html bc_borderradius-ref.html
|
||||||
== frame_above_rules_all.html frame_above_rules_all_ref.html
|
== frame_above_rules_all.html frame_above_rules_all_ref.html
|
||||||
== frame_above_rules_cols.html frame_above_rules_cols_ref.html
|
== frame_above_rules_cols.html frame_above_rules_cols_ref.html
|
||||||
== frame_above_rules_groups.html frame_above_rules_groups_ref.html
|
== frame_above_rules_groups.html frame_above_rules_groups_ref.html
|
||||||
|
@ -104,4 +105,5 @@ fuzzy(255,40) == border-style-outset-becomes-groove.html border-style-outset-bec
|
||||||
# So get 40 pixels of fuzz, 20 at each beveled corner (because the border width
|
# So get 40 pixels of fuzz, 20 at each beveled corner (because the border width
|
||||||
# is 20px).
|
# is 20px).
|
||||||
fuzzy(255,40) == border-style-inset-becomes-ridge.html border-style-inset-becomes-ridge-ref.html
|
fuzzy(255,40) == border-style-inset-becomes-ridge.html border-style-inset-becomes-ridge-ref.html
|
||||||
fuzzy(2,8301) == 1324524.html 1324524-ref.html
|
fuzzy(2,11000) == 1324524.html 1324524-ref.html
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ UNIFIED_SOURCES += [
|
||||||
'nsTableColFrame.cpp',
|
'nsTableColFrame.cpp',
|
||||||
'nsTableColGroupFrame.cpp',
|
'nsTableColGroupFrame.cpp',
|
||||||
'nsTableFrame.cpp',
|
'nsTableFrame.cpp',
|
||||||
'nsTablePainter.cpp',
|
|
||||||
'nsTableRowFrame.cpp',
|
'nsTableRowFrame.cpp',
|
||||||
'nsTableRowGroupFrame.cpp',
|
'nsTableRowGroupFrame.cpp',
|
||||||
'nsTableWrapperFrame.cpp',
|
'nsTableWrapperFrame.cpp',
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
#include "nsTableColFrame.h"
|
#include "nsTableColFrame.h"
|
||||||
#include "nsTableRowFrame.h"
|
#include "nsTableRowFrame.h"
|
||||||
#include "nsTableRowGroupFrame.h"
|
#include "nsTableRowGroupFrame.h"
|
||||||
#include "nsTablePainter.h"
|
|
||||||
#include "nsStyleContext.h"
|
#include "nsStyleContext.h"
|
||||||
#include "nsStyleConsts.h"
|
#include "nsStyleConsts.h"
|
||||||
#include "nsPresContext.h"
|
#include "nsPresContext.h"
|
||||||
|
@ -380,19 +379,6 @@ nsTableCellFrame::PaintBackground(nsRenderingContext& aRenderingContext,
|
||||||
return nsCSSRendering::PaintBackground(params);
|
return nsCSSRendering::PaintBackground(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by nsTablePainter
|
|
||||||
DrawResult
|
|
||||||
nsTableCellFrame::PaintCellBackground(nsRenderingContext& aRenderingContext,
|
|
||||||
const nsRect& aDirtyRect, nsPoint aPt,
|
|
||||||
uint32_t aFlags)
|
|
||||||
{
|
|
||||||
if (!StyleVisibility()->IsVisible()) {
|
|
||||||
return DrawResult::SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
return PaintBackground(aRenderingContext, aDirtyRect, aPt, aFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
nsTableCellFrame::ProcessBorders(nsTableFrame* aFrame,
|
nsTableCellFrame::ProcessBorders(nsTableFrame* aFrame,
|
||||||
nsDisplayListBuilder* aBuilder,
|
nsDisplayListBuilder* aBuilder,
|
||||||
|
@ -484,70 +470,51 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
const nsDisplayListSet& aLists)
|
const nsDisplayListSet& aLists)
|
||||||
{
|
{
|
||||||
DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
|
DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
|
||||||
if (IsVisibleInSelection(aBuilder)) {
|
nsTableFrame* tableFrame = GetTableFrame();
|
||||||
nsTableFrame* tableFrame = GetTableFrame();
|
int32_t emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
|
||||||
int32_t emptyCellStyle = GetContentEmpty() && !tableFrame->IsBorderCollapse() ?
|
StyleTableBorder()->mEmptyCells
|
||||||
StyleTableBorder()->mEmptyCells
|
: NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
|
||||||
: NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
|
// take account of 'empty-cells'
|
||||||
// take account of 'empty-cells'
|
if (StyleVisibility()->IsVisible() &&
|
||||||
if (StyleVisibility()->IsVisible() &&
|
(NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
|
||||||
(NS_STYLE_TABLE_EMPTY_CELLS_HIDE != emptyCellStyle)) {
|
// display outset box-shadows if we need to.
|
||||||
// display outset box-shadows if we need to.
|
bool hasBoxShadow = !!StyleEffects()->mBoxShadow;
|
||||||
bool hasBoxShadow = !!StyleEffects()->mBoxShadow;
|
if (hasBoxShadow) {
|
||||||
if (hasBoxShadow) {
|
aLists.BorderBackground()->AppendNewToTop(
|
||||||
aLists.BorderBackground()->AppendNewToTop(
|
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
|
||||||
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
|
}
|
||||||
}
|
|
||||||
|
// display background if we need to.
|
||||||
// display background if we need to.
|
if (aBuilder->IsForEventDelivery() ||
|
||||||
if (aBuilder->IsForEventDelivery() ||
|
!StyleBackground()->IsTransparent() ||
|
||||||
!StyleBackground()->IsTransparent() || StyleDisplay()->mAppearance) {
|
StyleDisplay()->mAppearance) {
|
||||||
if (!tableFrame->IsBorderCollapse()) {
|
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder,
|
||||||
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder,
|
this,
|
||||||
this,
|
GetRectRelativeToSelf(),
|
||||||
GetRectRelativeToSelf(),
|
aLists.BorderBackground());
|
||||||
aLists.BorderBackground());
|
}
|
||||||
} else if (aBuilder->IsAtRootOfPseudoStackingContext() ||
|
|
||||||
aBuilder->IsForEventDelivery()) {
|
// display inset box-shadows if we need to.
|
||||||
// The cell background was not painted by the nsTablePainter,
|
if (hasBoxShadow) {
|
||||||
// so we need to do it. We have special background processing here
|
aLists.BorderBackground()->AppendNewToTop(
|
||||||
// so we need to duplicate some code from nsFrame::DisplayBorderBackgroundOutline
|
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, this));
|
||||||
nsDisplayTableItem* item =
|
}
|
||||||
new (aBuilder) nsDisplayTableCellBackground(aBuilder, this);
|
|
||||||
aLists.BorderBackground()->AppendNewToTop(item);
|
// display borders if we need to
|
||||||
item->UpdateForFrameBackground(this);
|
ProcessBorders(tableFrame, aBuilder, aLists);
|
||||||
} else {
|
|
||||||
// The nsTablePainter will paint our background. Make sure it
|
// and display the selection border if we need to
|
||||||
// knows if we're background-attachment:fixed.
|
if (IsSelected()) {
|
||||||
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
|
aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
||||||
if (currentItem) {
|
nsDisplayGeneric(aBuilder, this, ::PaintTableCellSelection,
|
||||||
currentItem->UpdateForFrameBackground(this);
|
"TableCellSelection",
|
||||||
}
|
nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// display inset box-shadows if we need to.
|
|
||||||
if (hasBoxShadow) {
|
|
||||||
aLists.BorderBackground()->AppendNewToTop(
|
|
||||||
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
// display borders if we need to
|
|
||||||
ProcessBorders(tableFrame, aBuilder, aLists);
|
|
||||||
|
|
||||||
// and display the selection border if we need to
|
|
||||||
if (IsSelected()) {
|
|
||||||
aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
|
|
||||||
nsDisplayGeneric(aBuilder, this, ::PaintTableCellSelection,
|
|
||||||
"TableCellSelection",
|
|
||||||
nsDisplayItem::TYPE_TABLE_CELL_SELECTION));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the 'empty-cells' property has no effect on 'outline'
|
|
||||||
DisplayOutline(aBuilder, aLists);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the 'empty-cells' property has no effect on 'outline'
|
||||||
|
DisplayOutline(aBuilder, aLists);
|
||||||
|
|
||||||
// Push a null 'current table item' so that descendant tables can't
|
// Push a null 'current table item' so that descendant tables can't
|
||||||
// accidentally mess with our table
|
// accidentally mess with our table
|
||||||
nsAutoPushCurrentTableItem pushTableItem;
|
nsAutoPushCurrentTableItem pushTableItem;
|
||||||
|
|
|
@ -107,11 +107,6 @@ public:
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
const nsDisplayListSet& aLists) override;
|
const nsDisplayListSet& aLists) override;
|
||||||
|
|
||||||
DrawResult PaintCellBackground(nsRenderingContext& aRenderingContext,
|
|
||||||
const nsRect& aDirtyRect, nsPoint aPt,
|
|
||||||
uint32_t aFlags);
|
|
||||||
|
|
||||||
|
|
||||||
virtual nsresult ProcessBorders(nsTableFrame* aFrame,
|
virtual nsresult ProcessBorders(nsTableFrame* aFrame,
|
||||||
nsDisplayListBuilder* aBuilder,
|
nsDisplayListBuilder* aBuilder,
|
||||||
const nsDisplayListSet& aLists);
|
const nsDisplayListSet& aLists);
|
||||||
|
|
|
@ -108,6 +108,14 @@ nsTableColFrame::Reflow(nsPresContext* aPresContext,
|
||||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTableColFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
|
const nsRect& aDirtyRect,
|
||||||
|
const nsDisplayListSet& aLists)
|
||||||
|
{
|
||||||
|
nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t nsTableColFrame::GetSpan()
|
int32_t nsTableColFrame::GetSpan()
|
||||||
{
|
{
|
||||||
return StyleTable()->mSpan;
|
return StyleTable()->mSpan;
|
||||||
|
|
|
@ -59,12 +59,9 @@ public:
|
||||||
const ReflowInput& aReflowInput,
|
const ReflowInput& aReflowInput,
|
||||||
nsReflowStatus& aStatus) override;
|
nsReflowStatus& aStatus) override;
|
||||||
|
|
||||||
/**
|
|
||||||
* Table columns never paint anything, nor receive events.
|
|
||||||
*/
|
|
||||||
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
const nsDisplayListSet& aLists) override {}
|
const nsDisplayListSet& aLists) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the "type" of the frame
|
* Get the "type" of the frame
|
||||||
|
|
|
@ -383,6 +383,14 @@ nsTableColGroupFrame::Reflow(nsPresContext* aPresContext,
|
||||||
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
|
NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsTableColGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
|
const nsRect& aDirtyRect,
|
||||||
|
const nsDisplayListSet& aLists)
|
||||||
|
{
|
||||||
|
nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
|
||||||
|
}
|
||||||
|
|
||||||
nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
|
nsTableColFrame * nsTableColGroupFrame::GetFirstColumn()
|
||||||
{
|
{
|
||||||
return GetNextColumn(nullptr);
|
return GetNextColumn(nullptr);
|
||||||
|
|
|
@ -43,12 +43,9 @@ public:
|
||||||
return static_cast<nsTableFrame*>(parent);
|
return static_cast<nsTableFrame*>(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* ColGroups never paint anything, nor receive events.
|
|
||||||
*/
|
|
||||||
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
const nsDisplayListSet& aLists) override {}
|
const nsDisplayListSet& aLists) override;
|
||||||
|
|
||||||
/** A colgroup can be caused by three things:
|
/** A colgroup can be caused by three things:
|
||||||
* 1) An element with table-column-group display
|
* 1) An element with table-column-group display
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include "nsTableRowFrame.h"
|
#include "nsTableRowFrame.h"
|
||||||
#include "nsTableRowGroupFrame.h"
|
#include "nsTableRowGroupFrame.h"
|
||||||
#include "nsTableWrapperFrame.h"
|
#include "nsTableWrapperFrame.h"
|
||||||
#include "nsTablePainter.h"
|
|
||||||
|
|
||||||
#include "BasicTableLayoutStrategy.h"
|
#include "BasicTableLayoutStrategy.h"
|
||||||
#include "FixedTableLayoutStrategy.h"
|
#include "FixedTableLayoutStrategy.h"
|
||||||
|
@ -1131,67 +1130,40 @@ nsDisplayTableItem::ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
|
||||||
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
|
nsDisplayItem::ComputeInvalidationRegion(aBuilder, aGeometry, aInvalidRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
class nsDisplayTableBorderBackground : public nsDisplayTableItem {
|
// A display item that draws all collapsed borders for a table.
|
||||||
|
class nsDisplayTableBorderCollapse : public nsDisplayTableItem {
|
||||||
public:
|
public:
|
||||||
nsDisplayTableBorderBackground(nsDisplayListBuilder* aBuilder,
|
nsDisplayTableBorderCollapse(nsDisplayListBuilder* aBuilder,
|
||||||
nsTableFrame* aFrame,
|
nsTableFrame* aFrame)
|
||||||
bool aDrawsBackground) :
|
: nsDisplayTableItem(aBuilder, aFrame) {
|
||||||
nsDisplayTableItem(aBuilder, aFrame, aDrawsBackground) {
|
MOZ_COUNT_CTOR(nsDisplayTableBorderCollapse);
|
||||||
MOZ_COUNT_CTOR(nsDisplayTableBorderBackground);
|
}
|
||||||
}
|
|
||||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||||
virtual ~nsDisplayTableBorderBackground() {
|
virtual ~nsDisplayTableBorderCollapse() {
|
||||||
MOZ_COUNT_DTOR(nsDisplayTableBorderBackground);
|
MOZ_COUNT_DTOR(nsDisplayTableBorderCollapse);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||||
nsRenderingContext* aCtx) override;
|
nsRenderingContext* aCtx) override;
|
||||||
NS_DISPLAY_DECL_NAME("TableBorderBackground", TYPE_TABLE_BORDER_BACKGROUND)
|
NS_DISPLAY_DECL_NAME("TableBorderCollapse", TYPE_TABLE_BORDER_COLLAPSE)
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static bool
|
|
||||||
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
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsDisplayTableBorderBackground::Paint(nsDisplayListBuilder* aBuilder,
|
nsDisplayTableBorderCollapse::Paint(nsDisplayListBuilder* aBuilder,
|
||||||
nsRenderingContext* aCtx)
|
nsRenderingContext* aCtx)
|
||||||
{
|
{
|
||||||
DrawResult result = static_cast<nsTableFrame*>(mFrame)->
|
nsPoint pt = ToReferenceFrame();
|
||||||
PaintTableBorderBackground(aBuilder, *aCtx, mVisibleRect,
|
DrawTarget* drawTarget = aCtx->GetDrawTarget();
|
||||||
ToReferenceFrame());
|
|
||||||
|
|
||||||
nsDisplayTableItemGeometry::UpdateDrawResult(this, result);
|
gfxPoint devPixelOffset =
|
||||||
}
|
nsLayoutUtils::PointToGfxPoint(pt, mFrame->PresContext()->AppUnitsPerDevPixel());
|
||||||
|
|
||||||
static int32_t
|
AutoRestoreTransform autoRestoreTransform(drawTarget);
|
||||||
GetTablePartRank(nsDisplayItem* aItem)
|
drawTarget->SetTransform(
|
||||||
{
|
drawTarget->GetTransform().PreTranslate(ToPoint(devPixelOffset)));
|
||||||
nsIAtom* type = aItem->Frame()->GetType();
|
|
||||||
if (type == nsGkAtoms::tableFrame)
|
|
||||||
return 0;
|
|
||||||
if (type == nsGkAtoms::tableRowGroupFrame)
|
|
||||||
return 1;
|
|
||||||
if (type == nsGkAtoms::tableRowFrame)
|
|
||||||
return 2;
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool CompareByTablePartRank(nsDisplayItem* aItem1, nsDisplayItem* aItem2,
|
static_cast<nsTableFrame*>(mFrame)->PaintBCBorders(*drawTarget, mVisibleRect - pt);
|
||||||
void* aClosure)
|
|
||||||
{
|
|
||||||
return GetTablePartRank(aItem1) <= GetTablePartRank(aItem2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
|
@ -1206,31 +1178,75 @@ nsTableFrame::GenericTraversal(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
|
||||||
// stacking context, in which case the child won't use its passed-in
|
// stacking context, in which case the child won't use its passed-in
|
||||||
// BorderBackground list anyway. It does affect cell borders though; this
|
// BorderBackground list anyway. It does affect cell borders though; this
|
||||||
// lets us get cell borders into the nsTableFrame's BorderBackground list.
|
// lets us get cell borders into the nsTableFrame's BorderBackground list.
|
||||||
|
for (nsIFrame* kid : aFrame->GetChildList(kColGroupList)) {
|
||||||
|
aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
|
||||||
|
}
|
||||||
|
|
||||||
for (nsIFrame* kid : aFrame->PrincipalChildList()) {
|
for (nsIFrame* kid : aFrame->PrincipalChildList()) {
|
||||||
aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
|
aFrame->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
PaintRowBackground(nsTableRowFrame* aRow,
|
||||||
|
nsIFrame* aFrame,
|
||||||
|
nsDisplayListBuilder* aBuilder,
|
||||||
|
const nsDisplayListSet& aLists,
|
||||||
|
const nsPoint& aOffset = nsPoint())
|
||||||
|
{
|
||||||
|
// Compute background rect by iterating over all cell frames.
|
||||||
|
for (nsTableCellFrame* cell = aRow->GetFirstCell(); cell; cell = cell->GetNextCell()) {
|
||||||
|
auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + aOffset;
|
||||||
|
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
|
||||||
|
aLists.BorderBackground(),
|
||||||
|
true, nullptr,
|
||||||
|
aFrame->GetRectRelativeToSelf(),
|
||||||
|
cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
PaintRowGroupBackground(nsTableRowGroupFrame* aRowGroup,
|
||||||
|
nsIFrame* aFrame,
|
||||||
|
nsDisplayListBuilder* aBuilder,
|
||||||
|
const nsDisplayListSet& aLists)
|
||||||
|
{
|
||||||
|
for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
|
||||||
|
PaintRowBackground(row, aFrame, aBuilder, aLists, row->GetNormalPosition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
PaintRowGroupBackgroundByColIdx(nsTableRowGroupFrame* aRowGroup,
|
||||||
|
nsIFrame* aFrame,
|
||||||
|
nsDisplayListBuilder* aBuilder,
|
||||||
|
const nsDisplayListSet& aLists,
|
||||||
|
const nsTArray<int32_t>& aColIdx,
|
||||||
|
const nsPoint& aOffset)
|
||||||
|
{
|
||||||
|
for (nsTableRowFrame* row = aRowGroup->GetFirstRow(); row; row = row->GetNextRow()) {
|
||||||
|
for (nsTableCellFrame* cell = row->GetFirstCell(); cell; cell = cell->GetNextCell()) {
|
||||||
|
int32_t curColIdx;
|
||||||
|
cell->GetColIndex(curColIdx);
|
||||||
|
if (aColIdx.Contains(curColIdx)) {
|
||||||
|
auto cellRect = cell->GetRectRelativeToSelf() + cell->GetNormalPosition() + row->GetNormalPosition() + aOffset;
|
||||||
|
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame, cellRect,
|
||||||
|
aLists.BorderBackground(),
|
||||||
|
true, nullptr,
|
||||||
|
aFrame->GetRectRelativeToSelf(),
|
||||||
|
cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
||||||
nsFrame* aFrame,
|
nsFrame* aFrame,
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
const nsDisplayListSet& aLists,
|
const nsDisplayListSet& aLists,
|
||||||
nsDisplayTableItem* aDisplayItem,
|
|
||||||
DisplayGenericTablePartTraversal aTraversal)
|
DisplayGenericTablePartTraversal aTraversal)
|
||||||
{
|
{
|
||||||
nsDisplayList eventsBorderBackground;
|
|
||||||
// If we need to sort the event backgrounds, then we'll put descendants'
|
|
||||||
// display items into their own set of lists.
|
|
||||||
bool sortEventBackgrounds = aDisplayItem && aBuilder->IsForEventDelivery();
|
|
||||||
nsDisplayListCollection separatedCollection;
|
|
||||||
const nsDisplayListSet* lists = sortEventBackgrounds ? &separatedCollection : &aLists;
|
|
||||||
|
|
||||||
nsAutoPushCurrentTableItem pushTableItem;
|
|
||||||
if (aDisplayItem) {
|
|
||||||
pushTableItem.Push(aBuilder, aDisplayItem);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aFrame->IsVisibleForPainting(aBuilder)) {
|
if (aFrame->IsVisibleForPainting(aBuilder)) {
|
||||||
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
|
nsDisplayTableItem* currentItem = aBuilder->GetCurrentTableItem();
|
||||||
// currentItem may be null, when none of the table parts have a
|
// currentItem may be null, when none of the table parts have a
|
||||||
|
@ -1242,72 +1258,79 @@ nsTableFrame::DisplayGenericTablePart(nsDisplayListBuilder* aBuilder,
|
||||||
// Paint the outset box-shadows for the table frames
|
// Paint the outset box-shadows for the table frames
|
||||||
bool hasBoxShadow = aFrame->StyleEffects()->mBoxShadow != nullptr;
|
bool hasBoxShadow = aFrame->StyleEffects()->mBoxShadow != nullptr;
|
||||||
if (hasBoxShadow) {
|
if (hasBoxShadow) {
|
||||||
lists->BorderBackground()->AppendNewToTop(
|
aLists.BorderBackground()->AppendNewToTop(
|
||||||
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
|
new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, aFrame));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create dedicated background display items per-frame when we're
|
if (aFrame->GetType() == nsGkAtoms::tableRowGroupFrame) {
|
||||||
// handling events.
|
nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame);
|
||||||
// XXX how to handle collapsed borders?
|
PaintRowGroupBackground(rowGroup, aFrame, aBuilder, aLists);
|
||||||
if (aBuilder->IsForEventDelivery()) {
|
} else if (aFrame->GetType() == nsGkAtoms::tableRowFrame) {
|
||||||
|
nsTableRowFrame* row = static_cast<nsTableRowFrame*>(aFrame);
|
||||||
|
PaintRowBackground(row, aFrame, aBuilder, aLists);
|
||||||
|
} else if (aFrame->GetType() == nsGkAtoms::tableColGroupFrame) {
|
||||||
|
// Compute background rect by iterating all cell frame.
|
||||||
|
nsTableColGroupFrame* colGroup = static_cast<nsTableColGroupFrame*>(aFrame);
|
||||||
|
// Collecting column index.
|
||||||
|
AutoTArray<int32_t, 1> colIdx;
|
||||||
|
for (nsTableColFrame* col = colGroup->GetFirstColumn(); col; col = col->GetNextCol()) {
|
||||||
|
colIdx.AppendElement(col->GetColIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTableFrame* table = colGroup->GetTableFrame();
|
||||||
|
RowGroupArray rowGroups;
|
||||||
|
table->OrderRowGroups(rowGroups);
|
||||||
|
for (nsTableRowGroupFrame* rowGroup : rowGroups) {
|
||||||
|
auto offset = rowGroup->GetNormalPosition() - colGroup->GetNormalPosition();
|
||||||
|
PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
|
||||||
|
}
|
||||||
|
} else if (aFrame->GetType() == nsGkAtoms::tableColFrame) {
|
||||||
|
// Compute background rect by iterating all cell frame.
|
||||||
|
nsTableColFrame* col = static_cast<nsTableColFrame*>(aFrame);
|
||||||
|
AutoTArray<int32_t, 1> colIdx;
|
||||||
|
colIdx.AppendElement(col->GetColIndex());
|
||||||
|
|
||||||
|
nsTableFrame* table = col->GetTableFrame();
|
||||||
|
RowGroupArray rowGroups;
|
||||||
|
table->OrderRowGroups(rowGroups);
|
||||||
|
for (nsTableRowGroupFrame* rowGroup : rowGroups) {
|
||||||
|
auto offset = rowGroup->GetNormalPosition() -
|
||||||
|
col->GetNormalPosition() -
|
||||||
|
col->GetTableColGroupFrame()->GetNormalPosition();
|
||||||
|
PaintRowGroupBackgroundByColIdx(rowGroup, aFrame, aBuilder, aLists, colIdx, offset);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
|
nsDisplayBackgroundImage::AppendBackgroundItemsToTop(aBuilder, aFrame,
|
||||||
aFrame->GetRectRelativeToSelf(),
|
aFrame->GetRectRelativeToSelf(),
|
||||||
lists->BorderBackground());
|
aLists.BorderBackground());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paint the inset box-shadows for the table frames
|
// Paint the inset box-shadows for the table frames
|
||||||
if (hasBoxShadow) {
|
if (hasBoxShadow) {
|
||||||
lists->BorderBackground()->AppendNewToTop(
|
aLists.BorderBackground()->AppendNewToTop(
|
||||||
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
|
new (aBuilder) nsDisplayBoxShadowInner(aBuilder, aFrame));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aTraversal(aBuilder, aFrame, aDirtyRect, *lists);
|
aTraversal(aBuilder, aFrame, aDirtyRect, aLists);
|
||||||
|
|
||||||
if (sortEventBackgrounds) {
|
if (aFrame->IsVisibleForPainting(aBuilder)) {
|
||||||
// Ensure that the table frame event background goes before the
|
if (aFrame->GetType() == nsGkAtoms::tableFrame) {
|
||||||
// table rowgroups event backgrounds, before the table row event backgrounds,
|
nsTableFrame* table = static_cast<nsTableFrame*>(aFrame);
|
||||||
// before everything else (cells and their blocks)
|
// In the collapsed border model, overlay all collapsed borders.
|
||||||
separatedCollection.BorderBackground()->Sort(CompareByTablePartRank, nullptr);
|
if (table->IsBorderCollapse()) {
|
||||||
separatedCollection.MoveTo(aLists);
|
aLists.BorderBackground()->AppendNewToTop(
|
||||||
|
new (aBuilder) nsDisplayTableBorderCollapse(aBuilder, table));
|
||||||
|
} else {
|
||||||
|
aLists.BorderBackground()->AppendNewToTop(
|
||||||
|
new (aBuilder) nsDisplayBorder(aBuilder, table));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
aFrame->DisplayOutline(aBuilder, aLists);
|
aFrame->DisplayOutline(aBuilder, aLists);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
AnyTablePartHasBorderOrBackground(nsIFrame* aStart, nsIFrame* aEnd)
|
|
||||||
{
|
|
||||||
for (nsIFrame* f = aStart; f != aEnd; f = f->GetNextSibling()) {
|
|
||||||
NS_ASSERTION(IsFrameAllowedInTable(f->GetType()), "unexpected frame type");
|
|
||||||
|
|
||||||
if (FrameHasBorderOrBackground(f))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
nsTableCellFrame *cellFrame = do_QueryFrame(f);
|
|
||||||
if (cellFrame)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (AnyTablePartHasBorderOrBackground(f->PrincipalChildList().FirstChild(), nullptr))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
UpdateItemForColGroupBackgrounds(nsDisplayTableItem* item,
|
|
||||||
const nsFrameList& aFrames) {
|
|
||||||
for (nsFrameList::Enumerator e(aFrames); !e.AtEnd(); e.Next()) {
|
|
||||||
nsTableColGroupFrame* cg = static_cast<nsTableColGroupFrame*>(e.get());
|
|
||||||
item->UpdateForFrameBackground(cg);
|
|
||||||
for (nsTableColFrame* colFrame = cg->GetFirstColumn(); colFrame;
|
|
||||||
colFrame = colFrame->GetNextCol()) {
|
|
||||||
item->UpdateForFrameBackground(colFrame);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// table paint code is concerned primarily with borders and bg color
|
// table paint code is concerned primarily with borders and bg color
|
||||||
// SEC: TODO: adjust the rect for captions
|
// SEC: TODO: adjust the rect for captions
|
||||||
void
|
void
|
||||||
|
@ -1317,35 +1340,7 @@ nsTableFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
{
|
{
|
||||||
DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255));
|
DO_GLOBAL_REFLOW_COUNT_DSP_COLOR("nsTableFrame", NS_RGB(255,128,255));
|
||||||
|
|
||||||
nsDisplayTableItem* item = nullptr;
|
DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
|
||||||
if (IsVisibleInSelection(aBuilder)) {
|
|
||||||
nsMargin deflate = GetDeflationForBackground(PresContext());
|
|
||||||
if (StyleVisibility()->IsVisible()) {
|
|
||||||
// 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)) {
|
|
||||||
DisplayBackgroundUnconditional(aBuilder, aLists, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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()) ||
|
|
||||||
AnyTablePartHasBorderOrBackground(mColGroups.FirstChild(), nullptr)) {
|
|
||||||
item = new (aBuilder) nsDisplayTableBorderBackground(aBuilder, this,
|
|
||||||
deflate != nsMargin(0, 0, 0, 0));
|
|
||||||
aLists.BorderBackground()->AppendNewToTop(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, item);
|
|
||||||
if (item) {
|
|
||||||
UpdateItemForColGroupBackgrounds(item, mColGroups);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsMargin
|
nsMargin
|
||||||
|
@ -1359,59 +1354,6 @@ nsTableFrame::GetDeflationForBackground(nsPresContext* aPresContext) const
|
||||||
return GetOuterBCBorder(wm).GetPhysicalMargin(wm);
|
return GetOuterBCBorder(wm).GetPhysicalMargin(wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
|
||||||
DrawResult
|
|
||||||
nsTableFrame::PaintTableBorderBackground(nsDisplayListBuilder* aBuilder,
|
|
||||||
nsRenderingContext& aRenderingContext,
|
|
||||||
const nsRect& aDirtyRect,
|
|
||||||
nsPoint aPt)
|
|
||||||
{
|
|
||||||
nsPresContext* presContext = PresContext();
|
|
||||||
|
|
||||||
uint32_t bgFlags = aBuilder->GetBackgroundPaintFlags();
|
|
||||||
PaintBorderFlags borderFlags = aBuilder->ShouldSyncDecodeImages()
|
|
||||||
? PaintBorderFlags::SYNC_DECODE_IMAGES
|
|
||||||
: PaintBorderFlags();
|
|
||||||
|
|
||||||
TableBackgroundPainter painter(this, TableBackgroundPainter::eOrigin_Table,
|
|
||||||
presContext, aRenderingContext,
|
|
||||||
aDirtyRect, aPt, bgFlags);
|
|
||||||
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.
|
|
||||||
DrawResult result =
|
|
||||||
painter.PaintTable(this, deflate, deflate != nsMargin(0, 0, 0, 0));
|
|
||||||
|
|
||||||
if (StyleVisibility()->IsVisible()) {
|
|
||||||
if (!IsBorderCollapse()) {
|
|
||||||
Sides skipSides = GetSkipSides();
|
|
||||||
nsRect rect(aPt, mRect.Size());
|
|
||||||
|
|
||||||
result &=
|
|
||||||
nsCSSRendering::PaintBorder(presContext, aRenderingContext, this,
|
|
||||||
aDirtyRect, rect, mStyleContext,
|
|
||||||
borderFlags, skipSides);
|
|
||||||
} else {
|
|
||||||
DrawTarget* drawTarget = aRenderingContext.GetDrawTarget();
|
|
||||||
|
|
||||||
gfxPoint devPixelOffset =
|
|
||||||
nsLayoutUtils::PointToGfxPoint(aPt,
|
|
||||||
PresContext()->AppUnitsPerDevPixel());
|
|
||||||
|
|
||||||
// XXX we should probably get rid of this translation at some stage
|
|
||||||
// But that would mean modifying PaintBCBorders, ugh
|
|
||||||
AutoRestoreTransform autoRestoreTransform(drawTarget);
|
|
||||||
drawTarget->SetTransform(
|
|
||||||
drawTarget->GetTransform().PreTranslate(ToPoint(devPixelOffset)));
|
|
||||||
|
|
||||||
PaintBCBorders(*drawTarget, aDirtyRect - aPt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsIFrame::LogicalSides
|
nsIFrame::LogicalSides
|
||||||
nsTableFrame::GetLogicalSkipSides(const ReflowInput* aReflowInput) const
|
nsTableFrame::GetLogicalSkipSides(const ReflowInput* aReflowInput) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -250,7 +250,6 @@ public:
|
||||||
nsFrame* aFrame,
|
nsFrame* aFrame,
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
const nsDisplayListSet& aLists,
|
const nsDisplayListSet& aLists,
|
||||||
nsDisplayTableItem* aDisplayItem,
|
|
||||||
DisplayGenericTablePartTraversal aTraversal = GenericTraversal);
|
DisplayGenericTablePartTraversal aTraversal = GenericTraversal);
|
||||||
|
|
||||||
// Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
|
// Return the closest sibling of aPriorChildFrame (including aPriroChildFrame)
|
||||||
|
@ -272,16 +271,6 @@ public:
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
const nsDisplayListSet& aLists) override;
|
const nsDisplayListSet& aLists) override;
|
||||||
|
|
||||||
/**
|
|
||||||
* Paint the background of the table and its parts (column groups,
|
|
||||||
* columns, row groups, rows, and cells), and the table border, and all
|
|
||||||
* internal borders if border-collapse is on.
|
|
||||||
*/
|
|
||||||
DrawResult PaintTableBorderBackground(nsDisplayListBuilder* aBuilder,
|
|
||||||
nsRenderingContext& aRenderingContext,
|
|
||||||
const nsRect& aDirtyRect,
|
|
||||||
nsPoint aPt);
|
|
||||||
|
|
||||||
/** Get the outer half (i.e., the part outside the height and width of
|
/** Get the outer half (i.e., the part outside the height and width of
|
||||||
* the table) of the largest segment (?) of border-collapsed border on
|
* the table) of the largest segment (?) of border-collapsed border on
|
||||||
* the table on each side, or 0 for non border-collapsed tables.
|
* the table on each side, or 0 for non border-collapsed tables.
|
||||||
|
|
|
@ -1,696 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#include "nsTableFrame.h"
|
|
||||||
#include "nsTableRowGroupFrame.h"
|
|
||||||
#include "nsTableRowFrame.h"
|
|
||||||
#include "nsTableColGroupFrame.h"
|
|
||||||
#include "nsTableColFrame.h"
|
|
||||||
#include "nsTableCellFrame.h"
|
|
||||||
#include "nsTablePainter.h"
|
|
||||||
#include "nsCSSRendering.h"
|
|
||||||
#include "nsDisplayList.h"
|
|
||||||
#include "mozilla/WritingModes.h"
|
|
||||||
|
|
||||||
/* ~*~ Table Background Painting ~*~
|
|
||||||
|
|
||||||
Mozilla's Table Background painting follows CSS2.1:17.5.1
|
|
||||||
That section does not, however, describe the effect of
|
|
||||||
borders on background image positioning. What we do is:
|
|
||||||
|
|
||||||
- in separate borders, the borders are passed in so that
|
|
||||||
their width figures in image positioning, even for rows/cols, which
|
|
||||||
don't have visible borders. This is done to allow authors
|
|
||||||
to position row backgrounds by, for example, aligning the
|
|
||||||
top left corner with the top left padding corner of the
|
|
||||||
top left table cell in the row in cases where all cells
|
|
||||||
have consistent border widths. If we didn't honor these
|
|
||||||
invisible borders, there would be no way to align
|
|
||||||
backgrounds with the padding edges, and designs would be
|
|
||||||
lost underneath the border.
|
|
||||||
|
|
||||||
- in collapsing borders, because the borders collapse, we
|
|
||||||
use the -continuous border- width to synthesize a border
|
|
||||||
style and pass that in instead of using the element's
|
|
||||||
assigned style directly.
|
|
||||||
|
|
||||||
The continuous border on a given edge of an element is
|
|
||||||
the collapse of all borders guaranteed to be continuous
|
|
||||||
along that edge. Cell borders are ignored (because, for
|
|
||||||
example, setting a thick border on the leftmost cell
|
|
||||||
should not shift the row background over; this way a
|
|
||||||
striped background set on <tr> will line up across rows
|
|
||||||
even if the cells are assigned arbitrary border widths.
|
|
||||||
|
|
||||||
For example, the continuous border on the top edge of a
|
|
||||||
row group is the collapse of any row group, row, and
|
|
||||||
table borders involved. (The first row group's top would
|
|
||||||
be [table-top + row group top + first row top]. It's bottom
|
|
||||||
would be [row group bottom + last row bottom + next row
|
|
||||||
top + next row group top].)
|
|
||||||
The top edge of a column group likewise includes the
|
|
||||||
table top, row group top, and first row top borders. However,
|
|
||||||
it *also* includes its own top border, since that is guaranteed
|
|
||||||
to be continuous. It does not include column borders because
|
|
||||||
those are not guaranteed to be continuous: there may be two
|
|
||||||
columns with different borders in a single column group.
|
|
||||||
|
|
||||||
An alternative would be to define the continuous border as
|
|
||||||
[table? + row group + row] for horizontal
|
|
||||||
[table? + col group + col] for vertical
|
|
||||||
This makes it easier to line up backgrounds across elements
|
|
||||||
despite varying border widths, but it does not give much
|
|
||||||
flexibility in aligning /to/ those border widths.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/* ~*~ TableBackgroundPainter ~*~
|
|
||||||
|
|
||||||
The TableBackgroundPainter is created and destroyed in one painting call.
|
|
||||||
Its principal function is PaintTable, which paints all table element
|
|
||||||
backgrounds. The initial code in that method sets up an array of column
|
|
||||||
data that caches the background styles and the border sizes for the
|
|
||||||
columns and colgroups in TableBackgroundData structs in mCols. Data for
|
|
||||||
BC borders are calculated and stashed in a synthesized border style struct
|
|
||||||
in the data struct since collapsed borders aren't the same width as style-
|
|
||||||
assigned borders. The data struct optimizes by only doing this if there's
|
|
||||||
an image background; otherwise we don't care. //XXX should also check background-origin
|
|
||||||
The class then loops through the row groups, rows, and cells. At the cell
|
|
||||||
level, it paints the backgrounds, one over the other, inside the cell rect.
|
|
||||||
|
|
||||||
The exception to this pattern is when a table element creates a (pseudo)
|
|
||||||
stacking context. Elements with stacking contexts (e.g., 'opacity' applied)
|
|
||||||
are <dfn>passed through</dfn>, which means their data (and their
|
|
||||||
descendants' data) are not cached. The full loop is still executed, however,
|
|
||||||
so that underlying layers can get painted at the cell level.
|
|
||||||
|
|
||||||
The TableBackgroundPainter is then destroyed.
|
|
||||||
|
|
||||||
Elements with stacking contexts set up their own painter to finish the
|
|
||||||
painting process, since they were skipped. They call the appropriate
|
|
||||||
sub-part of the loop (e.g. PaintRow) which will paint the frame and
|
|
||||||
descendants.
|
|
||||||
|
|
||||||
XXX views are going
|
|
||||||
*/
|
|
||||||
|
|
||||||
using namespace mozilla;
|
|
||||||
using namespace mozilla::image;
|
|
||||||
|
|
||||||
TableBackgroundPainter::TableBackgroundData::TableBackgroundData()
|
|
||||||
: mFrame(nullptr)
|
|
||||||
, mVisible(false)
|
|
||||||
, mUsesSynthBorder(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
TableBackgroundPainter::TableBackgroundData::TableBackgroundData(nsIFrame* aFrame)
|
|
||||||
: mFrame(aFrame)
|
|
||||||
, mRect(aFrame->GetRect())
|
|
||||||
, mVisible(mFrame->IsVisibleForPainting())
|
|
||||||
, mUsesSynthBorder(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool
|
|
||||||
TableBackgroundPainter::TableBackgroundData::ShouldSetBCBorder() const
|
|
||||||
{
|
|
||||||
/* we only need accurate border data when positioning background images*/
|
|
||||||
if (!mVisible) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nsStyleImageLayers& layers = mFrame->StyleBackground()->mImage;
|
|
||||||
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, layers) {
|
|
||||||
if (!layers.mLayers[i].mImage.IsEmpty())
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TableBackgroundPainter::TableBackgroundData::SetBCBorder(const nsMargin& aBorder)
|
|
||||||
{
|
|
||||||
mUsesSynthBorder = true;
|
|
||||||
mSynthBorderWidths = aBorder;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsStyleBorder
|
|
||||||
TableBackgroundPainter::TableBackgroundData::StyleBorder(const nsStyleBorder& aZeroBorder) const
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(mVisible, "Don't call StyleBorder on an invisible TableBackgroundData");
|
|
||||||
|
|
||||||
if (mUsesSynthBorder) {
|
|
||||||
nsStyleBorder result = aZeroBorder;
|
|
||||||
NS_FOR_CSS_SIDES(side) {
|
|
||||||
result.SetBorderWidth(side, mSynthBorderWidths.Side(side));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
MOZ_ASSERT(mFrame);
|
|
||||||
|
|
||||||
return *mFrame->StyleBorder();
|
|
||||||
}
|
|
||||||
|
|
||||||
TableBackgroundPainter::TableBackgroundPainter(nsTableFrame* aTableFrame,
|
|
||||||
Origin aOrigin,
|
|
||||||
nsPresContext* aPresContext,
|
|
||||||
nsRenderingContext& aRenderingContext,
|
|
||||||
const nsRect& aDirtyRect,
|
|
||||||
const nsPoint& aRenderPt,
|
|
||||||
uint32_t aBGPaintFlags)
|
|
||||||
: mPresContext(aPresContext),
|
|
||||||
mRenderingContext(aRenderingContext),
|
|
||||||
mRenderPt(aRenderPt),
|
|
||||||
mDirtyRect(aDirtyRect),
|
|
||||||
mOrigin(aOrigin),
|
|
||||||
mZeroBorder(aPresContext),
|
|
||||||
mBGPaintFlags(aBGPaintFlags)
|
|
||||||
{
|
|
||||||
MOZ_COUNT_CTOR(TableBackgroundPainter);
|
|
||||||
|
|
||||||
NS_FOR_CSS_SIDES(side) {
|
|
||||||
mZeroBorder.SetBorderStyle(side, NS_STYLE_BORDER_STYLE_SOLID);
|
|
||||||
mZeroBorder.SetBorderWidth(side, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
mIsBorderCollapse = aTableFrame->IsBorderCollapse();
|
|
||||||
#ifdef DEBUG
|
|
||||||
mCompatMode = mPresContext->CompatibilityMode();
|
|
||||||
#endif
|
|
||||||
mNumCols = aTableFrame->GetColCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
TableBackgroundPainter::~TableBackgroundPainter()
|
|
||||||
{
|
|
||||||
MOZ_COUNT_DTOR(TableBackgroundPainter);
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawResult
|
|
||||||
TableBackgroundPainter::PaintTableFrame(nsTableFrame* aTableFrame,
|
|
||||||
nsTableRowGroupFrame* aFirstRowGroup,
|
|
||||||
nsTableRowGroupFrame* aLastRowGroup,
|
|
||||||
const nsMargin& aDeflate)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aTableFrame, "null frame");
|
|
||||||
TableBackgroundData tableData(aTableFrame);
|
|
||||||
tableData.mRect.MoveTo(0,0); //using table's coords
|
|
||||||
tableData.mRect.Deflate(aDeflate);
|
|
||||||
WritingMode wm = aTableFrame->GetWritingMode();
|
|
||||||
if (mIsBorderCollapse && tableData.ShouldSetBCBorder()) {
|
|
||||||
if (aFirstRowGroup && aLastRowGroup && mNumCols > 0) {
|
|
||||||
//only handle non-degenerate tables; we need a more robust BC model
|
|
||||||
//to make degenerate tables' borders reasonable to deal with
|
|
||||||
LogicalMargin border(wm);
|
|
||||||
LogicalMargin tempBorder(wm);
|
|
||||||
nsTableColFrame* colFrame = aTableFrame->GetColFrame(mNumCols - 1);
|
|
||||||
if (colFrame) {
|
|
||||||
colFrame->GetContinuousBCBorderWidth(wm, tempBorder);
|
|
||||||
}
|
|
||||||
border.IEnd(wm) = tempBorder.IEnd(wm);
|
|
||||||
|
|
||||||
aLastRowGroup->GetContinuousBCBorderWidth(wm, tempBorder);
|
|
||||||
border.BEnd(wm) = tempBorder.BEnd(wm);
|
|
||||||
|
|
||||||
nsTableRowFrame* rowFrame = aFirstRowGroup->GetFirstRow();
|
|
||||||
if (rowFrame) {
|
|
||||||
rowFrame->GetContinuousBCBorderWidth(wm, tempBorder);
|
|
||||||
border.BStart(wm) = tempBorder.BStart(wm);
|
|
||||||
}
|
|
||||||
|
|
||||||
border.IStart(wm) = aTableFrame->GetContinuousIStartBCBorderWidth();
|
|
||||||
|
|
||||||
tableData.SetBCBorder(border.GetPhysicalMargin(wm));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawResult result = DrawResult::SUCCESS;
|
|
||||||
|
|
||||||
if (tableData.IsVisible()) {
|
|
||||||
nsCSSRendering::PaintBGParams params =
|
|
||||||
nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext,
|
|
||||||
mRenderingContext,
|
|
||||||
mDirtyRect,
|
|
||||||
tableData.mRect + mRenderPt,
|
|
||||||
tableData.mFrame,
|
|
||||||
mBGPaintFlags);
|
|
||||||
|
|
||||||
result &=
|
|
||||||
nsCSSRendering::PaintBackgroundWithSC(params,
|
|
||||||
tableData.mFrame->StyleContext(),
|
|
||||||
tableData.StyleBorder(mZeroBorder));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TableBackgroundPainter::TranslateContext(nscoord aDX,
|
|
||||||
nscoord aDY)
|
|
||||||
{
|
|
||||||
mRenderPt += nsPoint(aDX, aDY);
|
|
||||||
for (auto& col : mCols) {
|
|
||||||
col.mCol.mRect.MoveBy(-aDX, -aDY);
|
|
||||||
}
|
|
||||||
for (auto& colGroup : mColGroups) {
|
|
||||||
colGroup.mRect.MoveBy(-aDX, -aDY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TableBackgroundPainter::ColData::ColData(nsIFrame* aFrame, TableBackgroundData& aColGroupBGData)
|
|
||||||
: mCol(aFrame)
|
|
||||||
, mColGroup(aColGroupBGData)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawResult
|
|
||||||
TableBackgroundPainter::PaintTable(nsTableFrame* aTableFrame,
|
|
||||||
const nsMargin& aDeflate,
|
|
||||||
bool aPaintTableBackground)
|
|
||||||
{
|
|
||||||
NS_PRECONDITION(aTableFrame, "null table frame");
|
|
||||||
|
|
||||||
nsTableFrame::RowGroupArray rowGroups;
|
|
||||||
aTableFrame->OrderRowGroups(rowGroups);
|
|
||||||
WritingMode wm = aTableFrame->GetWritingMode();
|
|
||||||
|
|
||||||
DrawResult result = DrawResult::SUCCESS;
|
|
||||||
|
|
||||||
if (rowGroups.Length() < 1) { //degenerate case
|
|
||||||
if (aPaintTableBackground) {
|
|
||||||
result &= PaintTableFrame(aTableFrame, nullptr, nullptr, nsMargin(0,0,0,0));
|
|
||||||
}
|
|
||||||
/* No cells; nothing else to paint */
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aPaintTableBackground) {
|
|
||||||
result &=
|
|
||||||
PaintTableFrame(aTableFrame, rowGroups[0], rowGroups[rowGroups.Length() - 1],
|
|
||||||
aDeflate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Set up column background/border data*/
|
|
||||||
if (mNumCols > 0) {
|
|
||||||
nsFrameList& colGroupList = aTableFrame->GetColGroups();
|
|
||||||
NS_ASSERTION(colGroupList.FirstChild(), "table should have at least one colgroup");
|
|
||||||
|
|
||||||
// Collect all col group frames first so that we know how many there are.
|
|
||||||
nsTArray<nsTableColGroupFrame*> colGroupFrames;
|
|
||||||
for (nsTableColGroupFrame* cgFrame = static_cast<nsTableColGroupFrame*>(colGroupList.FirstChild());
|
|
||||||
cgFrame; cgFrame = static_cast<nsTableColGroupFrame*>(cgFrame->GetNextSibling())) {
|
|
||||||
|
|
||||||
if (cgFrame->GetColCount() < 1) {
|
|
||||||
//No columns, no cells, so no need for data
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
colGroupFrames.AppendElement(cgFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that mColGroups won't reallocate during the loop below, because
|
|
||||||
// we grab references to its contents and need those to stay valid until
|
|
||||||
// mColGroups is destroyed as part of TablePainter destruction.
|
|
||||||
mColGroups.SetCapacity(colGroupFrames.Length());
|
|
||||||
|
|
||||||
LogicalMargin border(wm);
|
|
||||||
/* BC iStart borders aren't stored on cols, but the previous column's
|
|
||||||
iEnd border is the next one's iStart border.*/
|
|
||||||
//Start with table's iStart border.
|
|
||||||
nscoord lastIStartBorder = aTableFrame->GetContinuousIStartBCBorderWidth();
|
|
||||||
|
|
||||||
for (nsTableColGroupFrame* cgFrame : colGroupFrames) {
|
|
||||||
/*Create data struct for column group*/
|
|
||||||
TableBackgroundData& cgData = *mColGroups.AppendElement(TableBackgroundData(cgFrame));
|
|
||||||
if (mIsBorderCollapse && cgData.ShouldSetBCBorder()) {
|
|
||||||
border.IStart(wm) = lastIStartBorder;
|
|
||||||
cgFrame->GetContinuousBCBorderWidth(wm, border);
|
|
||||||
cgData.SetBCBorder(border.GetPhysicalMargin(wm));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Loop over columns in this colgroup*/
|
|
||||||
for (nsTableColFrame* col = cgFrame->GetFirstColumn(); col;
|
|
||||||
col = static_cast<nsTableColFrame*>(col->GetNextSibling())) {
|
|
||||||
MOZ_ASSERT(size_t(col->GetColIndex()) == mCols.Length());
|
|
||||||
// Store a reference to the colGroup in the ColData element.
|
|
||||||
ColData& colData = *mCols.AppendElement(ColData(col, cgData));
|
|
||||||
//Bring column mRect into table's coord system
|
|
||||||
colData.mCol.mRect.MoveBy(cgData.mRect.x, cgData.mRect.y);
|
|
||||||
if (mIsBorderCollapse) {
|
|
||||||
border.IStart(wm) = lastIStartBorder;
|
|
||||||
lastIStartBorder = col->GetContinuousBCBorderWidth(wm, border);
|
|
||||||
if (colData.mCol.ShouldSetBCBorder()) {
|
|
||||||
colData.mCol.SetBCBorder(border.GetPhysicalMargin(wm));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < rowGroups.Length(); i++) {
|
|
||||||
nsTableRowGroupFrame* rg = rowGroups[i];
|
|
||||||
TableBackgroundData rowGroupBGData(rg);
|
|
||||||
// Need to compute the right rect via GetOffsetTo, since the row
|
|
||||||
// group may not be a child of the table.
|
|
||||||
rowGroupBGData.mRect.MoveTo(rg->GetOffsetTo(aTableFrame));
|
|
||||||
|
|
||||||
// We have to draw backgrounds not only within the overflow region of this
|
|
||||||
// row group, but also possibly (in the case of column / column group
|
|
||||||
// backgrounds) at its pre-relative-positioning location.
|
|
||||||
nsRect rgVisualOverflow = rg->GetVisualOverflowRectRelativeToSelf();
|
|
||||||
nsRect rgOverflowRect = rgVisualOverflow + rg->GetPosition();
|
|
||||||
nsRect rgNormalRect = rgVisualOverflow + rg->GetNormalPosition();
|
|
||||||
|
|
||||||
if (rgOverflowRect.Union(rgNormalRect).Intersects(mDirtyRect - mRenderPt)) {
|
|
||||||
result &=
|
|
||||||
PaintRowGroup(rg, rowGroupBGData, rg->IsPseudoStackingContextFromStyle());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawResult
|
|
||||||
TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame)
|
|
||||||
{
|
|
||||||
return PaintRowGroup(aFrame, TableBackgroundData(aFrame), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawResult
|
|
||||||
TableBackgroundPainter::PaintRowGroup(nsTableRowGroupFrame* aFrame,
|
|
||||||
TableBackgroundData aRowGroupBGData,
|
|
||||||
bool aPassThrough)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aFrame, "null frame");
|
|
||||||
|
|
||||||
nsTableRowFrame* firstRow = aFrame->GetFirstRow();
|
|
||||||
WritingMode wm = aFrame->GetWritingMode();
|
|
||||||
|
|
||||||
/* Load row group data */
|
|
||||||
if (aPassThrough) {
|
|
||||||
aRowGroupBGData.MakeInvisible();
|
|
||||||
} else {
|
|
||||||
if (mIsBorderCollapse && aRowGroupBGData.ShouldSetBCBorder()) {
|
|
||||||
LogicalMargin border(wm);
|
|
||||||
if (firstRow) {
|
|
||||||
//pick up first row's bstart border (= rg bstart border)
|
|
||||||
firstRow->GetContinuousBCBorderWidth(wm, border);
|
|
||||||
/* (row group doesn't store its bstart border) */
|
|
||||||
}
|
|
||||||
//overwrite sides+bottom borders with rg's own
|
|
||||||
aFrame->GetContinuousBCBorderWidth(wm, border);
|
|
||||||
aRowGroupBGData.SetBCBorder(border.GetPhysicalMargin(wm));
|
|
||||||
}
|
|
||||||
aPassThrough = !aRowGroupBGData.IsVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* translate everything into row group coord system*/
|
|
||||||
if (eOrigin_TableRowGroup != mOrigin) {
|
|
||||||
TranslateContext(aRowGroupBGData.mRect.x, aRowGroupBGData.mRect.y);
|
|
||||||
}
|
|
||||||
nsRect rgRect = aRowGroupBGData.mRect;
|
|
||||||
aRowGroupBGData.mRect.MoveTo(0, 0);
|
|
||||||
|
|
||||||
/* Find the right row to start with */
|
|
||||||
|
|
||||||
// Note that mDirtyRect - mRenderPt is guaranteed to be in the row
|
|
||||||
// group's coordinate system here, so passing its .y to
|
|
||||||
// GetFirstRowContaining is ok.
|
|
||||||
nscoord overflowAbove;
|
|
||||||
nsIFrame* cursor = aFrame->GetFirstRowContaining(mDirtyRect.y - mRenderPt.y, &overflowAbove);
|
|
||||||
|
|
||||||
// Sadly, it seems like there may be non-row frames in there... or something?
|
|
||||||
// There are certainly null-checks in GetFirstRow() and GetNextRow(). :(
|
|
||||||
while (cursor && cursor->GetType() != nsGkAtoms::tableRowFrame) {
|
|
||||||
cursor = cursor->GetNextSibling();
|
|
||||||
}
|
|
||||||
|
|
||||||
// It's OK if cursor is null here.
|
|
||||||
nsTableRowFrame* row = static_cast<nsTableRowFrame*>(cursor);
|
|
||||||
if (!row) {
|
|
||||||
// No useful cursor; just start at the top. Don't bother to set up a
|
|
||||||
// cursor; if we've gotten this far then we've already built the display
|
|
||||||
// list for the rowgroup, so not having a cursor means that there's some
|
|
||||||
// good reason we don't have a cursor and we shouldn't create one here.
|
|
||||||
row = firstRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawResult result = DrawResult::SUCCESS;
|
|
||||||
|
|
||||||
/* Finally paint */
|
|
||||||
for (; row; row = row->GetNextRow()) {
|
|
||||||
TableBackgroundData rowBackgroundData(row);
|
|
||||||
|
|
||||||
// Be sure to consider our positions both pre- and post-relative
|
|
||||||
// positioning, since we potentially need to paint at both places.
|
|
||||||
nscoord rowY = std::min(rowBackgroundData.mRect.y, row->GetNormalPosition().y);
|
|
||||||
|
|
||||||
// Intersect wouldn't handle rowspans.
|
|
||||||
if (cursor &&
|
|
||||||
(mDirtyRect.YMost() - mRenderPt.y) <= (rowY - overflowAbove)) {
|
|
||||||
// All done; cells originating in later rows can't intersect mDirtyRect.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
result &=
|
|
||||||
PaintRow(row, aRowGroupBGData, rowBackgroundData,
|
|
||||||
aPassThrough || row->IsPseudoStackingContextFromStyle());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* translate back into table coord system */
|
|
||||||
if (eOrigin_TableRowGroup != mOrigin) {
|
|
||||||
TranslateContext(-rgRect.x, -rgRect.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawResult
|
|
||||||
TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame)
|
|
||||||
{
|
|
||||||
return PaintRow(aFrame, TableBackgroundData(), TableBackgroundData(aFrame), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawResult
|
|
||||||
TableBackgroundPainter::PaintRow(nsTableRowFrame* aFrame,
|
|
||||||
const TableBackgroundData& aRowGroupBGData,
|
|
||||||
TableBackgroundData aRowBGData,
|
|
||||||
bool aPassThrough)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aFrame, "null frame");
|
|
||||||
|
|
||||||
/* Load row data */
|
|
||||||
WritingMode wm = aFrame->GetWritingMode();
|
|
||||||
if (aPassThrough) {
|
|
||||||
aRowBGData.MakeInvisible();
|
|
||||||
} else {
|
|
||||||
if (mIsBorderCollapse && aRowBGData.ShouldSetBCBorder()) {
|
|
||||||
LogicalMargin border(wm);
|
|
||||||
nsTableRowFrame* nextRow = aFrame->GetNextRow();
|
|
||||||
if (nextRow) { //outer bStart after us is inner bEnd for us
|
|
||||||
border.BEnd(wm) = nextRow->GetOuterBStartContBCBorderWidth();
|
|
||||||
}
|
|
||||||
else { //acquire rg's bEnd border
|
|
||||||
nsTableRowGroupFrame* rowGroup = static_cast<nsTableRowGroupFrame*>(aFrame->GetParent());
|
|
||||||
rowGroup->GetContinuousBCBorderWidth(wm, border);
|
|
||||||
}
|
|
||||||
//get the rest of the borders; will overwrite all but bEnd
|
|
||||||
aFrame->GetContinuousBCBorderWidth(wm, border);
|
|
||||||
|
|
||||||
aRowBGData.SetBCBorder(border.GetPhysicalMargin(wm));
|
|
||||||
}
|
|
||||||
aPassThrough = !aRowBGData.IsVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Translate */
|
|
||||||
if (eOrigin_TableRow == mOrigin) {
|
|
||||||
/* If we originate from the row, then make the row the origin. */
|
|
||||||
aRowBGData.mRect.MoveTo(0, 0);
|
|
||||||
}
|
|
||||||
//else: Use row group's coord system -> no translation necessary
|
|
||||||
|
|
||||||
DrawResult result = DrawResult::SUCCESS;
|
|
||||||
|
|
||||||
for (nsTableCellFrame* cell = aFrame->GetFirstCell(); cell; cell = cell->GetNextCell()) {
|
|
||||||
nsRect cellBGRect, rowBGRect, rowGroupBGRect, colBGRect;
|
|
||||||
ComputeCellBackgrounds(cell, aRowGroupBGData, aRowBGData,
|
|
||||||
cellBGRect, rowBGRect,
|
|
||||||
rowGroupBGRect, colBGRect);
|
|
||||||
|
|
||||||
// Find the union of all the cell background layers.
|
|
||||||
nsRect combinedRect(cellBGRect);
|
|
||||||
combinedRect.UnionRect(combinedRect, rowBGRect);
|
|
||||||
combinedRect.UnionRect(combinedRect, rowGroupBGRect);
|
|
||||||
combinedRect.UnionRect(combinedRect, colBGRect);
|
|
||||||
|
|
||||||
if (combinedRect.Intersects(mDirtyRect)) {
|
|
||||||
bool passCell = aPassThrough || cell->IsPseudoStackingContextFromStyle();
|
|
||||||
result &=
|
|
||||||
PaintCell(cell, aRowGroupBGData, aRowBGData, cellBGRect, rowBGRect,
|
|
||||||
rowGroupBGRect, colBGRect, passCell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawResult
|
|
||||||
TableBackgroundPainter::PaintCell(nsTableCellFrame* aCell,
|
|
||||||
const TableBackgroundData& aRowGroupBGData,
|
|
||||||
const TableBackgroundData& aRowBGData,
|
|
||||||
nsRect& aCellBGRect,
|
|
||||||
nsRect& aRowBGRect,
|
|
||||||
nsRect& aRowGroupBGRect,
|
|
||||||
nsRect& aColBGRect,
|
|
||||||
bool aPassSelf)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(aCell, "null frame");
|
|
||||||
|
|
||||||
const nsStyleTableBorder* cellTableStyle;
|
|
||||||
cellTableStyle = aCell->StyleTableBorder();
|
|
||||||
if (NS_STYLE_TABLE_EMPTY_CELLS_SHOW != cellTableStyle->mEmptyCells &&
|
|
||||||
aCell->GetContentEmpty() && !mIsBorderCollapse) {
|
|
||||||
return DrawResult::SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t colIndex;
|
|
||||||
aCell->GetColIndex(colIndex);
|
|
||||||
// We're checking mNumCols instead of mCols.Length() here because mCols can
|
|
||||||
// be empty even if mNumCols > 0.
|
|
||||||
NS_ASSERTION(size_t(colIndex) < mNumCols, "out-of-bounds column index");
|
|
||||||
if (size_t(colIndex) >= mNumCols) {
|
|
||||||
return DrawResult::SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If callers call PaintRowGroup or PaintRow directly, we haven't processed
|
|
||||||
// our columns. Ignore column / col group backgrounds in that case.
|
|
||||||
bool haveColumns = !mCols.IsEmpty();
|
|
||||||
|
|
||||||
DrawResult result = DrawResult::SUCCESS;
|
|
||||||
|
|
||||||
//Paint column group background
|
|
||||||
if (haveColumns && mCols[colIndex].mColGroup.IsVisible()) {
|
|
||||||
nsCSSRendering::PaintBGParams params =
|
|
||||||
nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, mRenderingContext,
|
|
||||||
mDirtyRect,
|
|
||||||
mCols[colIndex].mColGroup.mRect + mRenderPt,
|
|
||||||
mCols[colIndex].mColGroup.mFrame,
|
|
||||||
mBGPaintFlags);
|
|
||||||
params.bgClipRect = &aColBGRect;
|
|
||||||
result &=
|
|
||||||
nsCSSRendering::PaintBackgroundWithSC(params,
|
|
||||||
mCols[colIndex].mColGroup.mFrame->StyleContext(),
|
|
||||||
mCols[colIndex].mColGroup.StyleBorder(mZeroBorder));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Paint column background
|
|
||||||
if (haveColumns && mCols[colIndex].mCol.IsVisible()) {
|
|
||||||
nsCSSRendering::PaintBGParams params =
|
|
||||||
nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, mRenderingContext,
|
|
||||||
mDirtyRect,
|
|
||||||
mCols[colIndex].mCol.mRect + mRenderPt,
|
|
||||||
mCols[colIndex].mCol.mFrame,
|
|
||||||
mBGPaintFlags);
|
|
||||||
params.bgClipRect = &aColBGRect;
|
|
||||||
result &=
|
|
||||||
nsCSSRendering::PaintBackgroundWithSC(params,
|
|
||||||
mCols[colIndex].mCol.mFrame->StyleContext(),
|
|
||||||
mCols[colIndex].mCol.StyleBorder(mZeroBorder));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Paint row group background
|
|
||||||
if (aRowGroupBGData.IsVisible()) {
|
|
||||||
nsCSSRendering::PaintBGParams params =
|
|
||||||
nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, mRenderingContext,
|
|
||||||
mDirtyRect,
|
|
||||||
aRowGroupBGData.mRect + mRenderPt,
|
|
||||||
aRowGroupBGData.mFrame, mBGPaintFlags);
|
|
||||||
params.bgClipRect = &aRowGroupBGRect;
|
|
||||||
result &=
|
|
||||||
nsCSSRendering::PaintBackgroundWithSC(params,
|
|
||||||
aRowGroupBGData.mFrame->StyleContext(),
|
|
||||||
aRowGroupBGData.StyleBorder(mZeroBorder));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Paint row background
|
|
||||||
if (aRowBGData.IsVisible()) {
|
|
||||||
nsCSSRendering::PaintBGParams params =
|
|
||||||
nsCSSRendering::PaintBGParams::ForAllLayers(*mPresContext, mRenderingContext,
|
|
||||||
mDirtyRect,
|
|
||||||
aRowBGData.mRect + mRenderPt,
|
|
||||||
aRowBGData.mFrame, mBGPaintFlags);
|
|
||||||
params.bgClipRect = &aRowBGRect;
|
|
||||||
result &=
|
|
||||||
nsCSSRendering::PaintBackgroundWithSC(params,
|
|
||||||
aRowBGData.mFrame->StyleContext(),
|
|
||||||
aRowBGData.StyleBorder(mZeroBorder));
|
|
||||||
}
|
|
||||||
|
|
||||||
//Paint cell background in border-collapse unless we're just passing
|
|
||||||
if (mIsBorderCollapse && !aPassSelf) {
|
|
||||||
result &=
|
|
||||||
aCell->PaintCellBackground(mRenderingContext, mDirtyRect,
|
|
||||||
aCellBGRect.TopLeft(), mBGPaintFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
TableBackgroundPainter::ComputeCellBackgrounds(nsTableCellFrame* aCell,
|
|
||||||
const TableBackgroundData& aRowGroupBGData,
|
|
||||||
const TableBackgroundData& aRowBGData,
|
|
||||||
nsRect& aCellBGRect,
|
|
||||||
nsRect& aRowBGRect,
|
|
||||||
nsRect& aRowGroupBGRect,
|
|
||||||
nsRect& aColBGRect)
|
|
||||||
{
|
|
||||||
// We need to compute table background layer rects for this cell space,
|
|
||||||
// adjusted for possible relative positioning. This behavior is not specified
|
|
||||||
// at the time of this writing, but the approach below should be web
|
|
||||||
// compatible.
|
|
||||||
//
|
|
||||||
// Our goal is that relative positioning of a table part should leave
|
|
||||||
// backgrounds *under* that part unchanged. ("Under" being defined by CSS 2.1
|
|
||||||
// Section 17.5.1.) If a cell is positioned, we do not expect the row
|
|
||||||
// background to move. On the other hand, the backgrounds of layers *above*
|
|
||||||
// the positioned part are taken along for the ride -- for example,
|
|
||||||
// positioning a row group will also cause the row background to be drawn in
|
|
||||||
// the new location, unless it has further positioning applied.
|
|
||||||
//
|
|
||||||
// Each table part layer has its position stored in the coordinate space of
|
|
||||||
// the layer below (which is to say, its geometric parent), and the stored
|
|
||||||
// position is the post-relative-positioning one. The position of each
|
|
||||||
// background layer rect is thus determined by peeling off successive table
|
|
||||||
// part layers, removing the contribution of each layer's positioning one by
|
|
||||||
// one. Every rect we generate will be the same size, the size of the cell
|
|
||||||
// space.
|
|
||||||
|
|
||||||
// We cannot rely on the row group background data to be available, since some
|
|
||||||
// callers enter through PaintRow.
|
|
||||||
nsIFrame* rowGroupFrame =
|
|
||||||
aRowGroupBGData.mFrame ? aRowGroupBGData.mFrame : aRowBGData.mFrame->GetParent();
|
|
||||||
|
|
||||||
// The cell background goes at the cell's position, translated to use the same
|
|
||||||
// coordinate system as aRowBGData.
|
|
||||||
aCellBGRect = aCell->GetRect() + aRowBGData.mRect.TopLeft() + mRenderPt;
|
|
||||||
|
|
||||||
// The row background goes at the normal position of the cell, which is to say
|
|
||||||
// the position without relative positioning applied.
|
|
||||||
aRowBGRect = aCellBGRect + (aCell->GetNormalPosition() - aCell->GetPosition());
|
|
||||||
|
|
||||||
// The row group background goes at the position we'd find the cell if neither
|
|
||||||
// the cell's relative positioning nor the row's were applied.
|
|
||||||
aRowGroupBGRect = aRowBGRect +
|
|
||||||
(aRowBGData.mFrame->GetNormalPosition() - aRowBGData.mFrame->GetPosition());
|
|
||||||
|
|
||||||
// The column and column group backgrounds (they're always at the same
|
|
||||||
// location, since relative positioning doesn't apply to columns or column
|
|
||||||
// groups) are drawn at the position we'd find the cell if none of the cell's,
|
|
||||||
// row's, or row group's relative positioning were applied.
|
|
||||||
aColBGRect = aRowGroupBGRect +
|
|
||||||
(rowGroupFrame->GetNormalPosition() - rowGroupFrame->GetPosition());
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,268 +0,0 @@
|
||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* 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/. */
|
|
||||||
|
|
||||||
#ifndef nsTablePainter_h__
|
|
||||||
#define nsTablePainter_h__
|
|
||||||
|
|
||||||
#include "imgIContainer.h"
|
|
||||||
|
|
||||||
#include "celldata.h"
|
|
||||||
|
|
||||||
// flags for Paint, PaintChild, PaintChildren are currently only used by tables.
|
|
||||||
//Table-based paint call; not a direct call as with views
|
|
||||||
#define NS_PAINT_FLAG_TABLE_BG_PAINT 0x00000001
|
|
||||||
//Cells should paint their backgrounds only, no children
|
|
||||||
#define NS_PAINT_FLAG_TABLE_CELL_BG_PASS 0x00000002
|
|
||||||
|
|
||||||
class nsIFrame;
|
|
||||||
class nsTableFrame;
|
|
||||||
class nsTableRowGroupFrame;
|
|
||||||
class nsTableRowFrame;
|
|
||||||
class nsTableCellFrame;
|
|
||||||
|
|
||||||
class TableBackgroundPainter
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Helper class for painting table backgrounds
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef mozilla::image::DrawResult DrawResult;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum Origin { eOrigin_Table, eOrigin_TableRowGroup, eOrigin_TableRow };
|
|
||||||
|
|
||||||
/** Public constructor
|
|
||||||
* @param aTableFrame - the table's table frame
|
|
||||||
* @param aOrigin - what type of table frame is creating this instance
|
|
||||||
* @param aPresContext - the presentation context
|
|
||||||
* @param aRenderingContext - the rendering context
|
|
||||||
* @param aDirtyRect - the area that needs to be painted,
|
|
||||||
* relative to aRenderingContext
|
|
||||||
* @param aPt - offset of the table frame relative to
|
|
||||||
* aRenderingContext
|
|
||||||
* @param aBGPaintFlags - Flags of the nsCSSRendering::PAINTBG_* variety
|
|
||||||
*/
|
|
||||||
TableBackgroundPainter(nsTableFrame* aTableFrame,
|
|
||||||
Origin aOrigin,
|
|
||||||
nsPresContext* aPresContext,
|
|
||||||
nsRenderingContext& aRenderingContext,
|
|
||||||
const nsRect& aDirtyRect,
|
|
||||||
const nsPoint& aPt,
|
|
||||||
uint32_t aBGPaintFlags);
|
|
||||||
|
|
||||||
/** Destructor */
|
|
||||||
~TableBackgroundPainter();
|
|
||||||
|
|
||||||
/* ~*~ The Border Collapse Painting Issue ~*~
|
|
||||||
|
|
||||||
In border-collapse, the *table* paints the cells' borders,
|
|
||||||
so we need to make sure the backgrounds get painted first
|
|
||||||
(underneath) by doing a cell-background-only painting pass.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ~*~ Using nsTablePainter Background Painting ~*~
|
|
||||||
|
|
||||||
A call to PaintTable will normally paint all of the table's
|
|
||||||
elements (except for the table background, if aPaintTableBackground
|
|
||||||
is false).
|
|
||||||
Elements with views however, will be skipped and must create their
|
|
||||||
own painter to call the appropriate paint function in their ::Paint
|
|
||||||
method (e.g. painter.PaintRow in nsTableRow::Paint)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** Paint background for the table frame (if requested) and its children
|
|
||||||
* down through cells.
|
|
||||||
* (Cells themselves will only be painted in border collapse)
|
|
||||||
* Table must do a flagged TABLE_BG_PAINT ::Paint call on its
|
|
||||||
* children afterwards
|
|
||||||
* @param aTableFrame - the table frame
|
|
||||||
* @param aDeflate - deflation needed to bring table's mRect
|
|
||||||
* to the outer grid lines in border-collapse
|
|
||||||
* @param aPaintTableBackground - if true, the table background
|
|
||||||
* is included, otherwise it isn't
|
|
||||||
* @returns DrawResult::SUCCESS if all painting was successful. If some
|
|
||||||
* painting failed or an improved result could be achieved by sync
|
|
||||||
* decoding images, returns another value.
|
|
||||||
*/
|
|
||||||
DrawResult PaintTable(nsTableFrame* aTableFrame, const nsMargin& aDeflate,
|
|
||||||
bool aPaintTableBackground);
|
|
||||||
|
|
||||||
/** Paint background for the row group and its children down through cells
|
|
||||||
* (Cells themselves will only be painted in border collapse)
|
|
||||||
* Standards mode only
|
|
||||||
* Table Row Group must do a flagged TABLE_BG_PAINT ::Paint call on its
|
|
||||||
* children afterwards
|
|
||||||
* @param aFrame - the table row group frame
|
|
||||||
* @returns DrawResult::SUCCESS if all painting was successful. If some
|
|
||||||
* painting failed or an improved result could be achieved by sync
|
|
||||||
* decoding images, returns another value.
|
|
||||||
*/
|
|
||||||
DrawResult PaintRowGroup(nsTableRowGroupFrame* aFrame);
|
|
||||||
|
|
||||||
/** Paint background for the row and its children down through cells
|
|
||||||
* (Cells themselves will only be painted in border collapse)
|
|
||||||
* Standards mode only
|
|
||||||
* Table Row must do a flagged TABLE_BG_PAINT ::Paint call on its
|
|
||||||
* children afterwards
|
|
||||||
* @param aFrame - the table row frame
|
|
||||||
* @returns DrawResult::SUCCESS if all painting was successful. If some
|
|
||||||
* painting failed or an improved result could be achieved by sync
|
|
||||||
* decoding images, returns another value.
|
|
||||||
*/
|
|
||||||
DrawResult PaintRow(nsTableRowFrame* aFrame);
|
|
||||||
|
|
||||||
private:
|
|
||||||
struct TableBackgroundData;
|
|
||||||
|
|
||||||
/** Paint table frame's background
|
|
||||||
* @param aTableFrame - the table frame
|
|
||||||
* @param aFirstRowGroup - the first (in layout order) row group
|
|
||||||
* may be null
|
|
||||||
* @param aLastRowGroup - the last (in layout order) row group
|
|
||||||
* may be null
|
|
||||||
* @param aDeflate - adjustment to frame's rect (used for quirks BC)
|
|
||||||
* may be null
|
|
||||||
*/
|
|
||||||
DrawResult PaintTableFrame(nsTableFrame* aTableFrame,
|
|
||||||
nsTableRowGroupFrame* aFirstRowGroup,
|
|
||||||
nsTableRowGroupFrame* aLastRowGroup,
|
|
||||||
const nsMargin& aDeflate);
|
|
||||||
|
|
||||||
/* aPassThrough params indicate whether to paint the element or to just
|
|
||||||
* pass through and paint underlying layers only.
|
|
||||||
* aRowGroupBGData is not a const reference because the function modifies
|
|
||||||
* its copy. Same for aRowBGData in PaintRow.
|
|
||||||
* See Public versions for function descriptions
|
|
||||||
*/
|
|
||||||
DrawResult PaintRowGroup(nsTableRowGroupFrame* aFrame,
|
|
||||||
TableBackgroundData aRowGroupBGData,
|
|
||||||
bool aPassThrough);
|
|
||||||
|
|
||||||
DrawResult PaintRow(nsTableRowFrame* aFrame,
|
|
||||||
const TableBackgroundData& aRowGroupBGData,
|
|
||||||
TableBackgroundData aRowBGData,
|
|
||||||
bool aPassThrough);
|
|
||||||
|
|
||||||
/** Paint table background layers for this cell space
|
|
||||||
* Also paints cell's own background in border-collapse mode
|
|
||||||
* @param aCell - the cell
|
|
||||||
* @param aRowGroupBGData - background drawing info for the row group
|
|
||||||
* @param aRowBGData - background drawing info for the row
|
|
||||||
* @param aCellBGRect - background rect for the cell
|
|
||||||
* @param aRowBGRect - background rect for the row
|
|
||||||
* @param aRowGroupBGRect - background rect for the row group
|
|
||||||
* @param aColBGRect - background rect for the column and column group
|
|
||||||
* @param aPassSelf - pass this cell; i.e. paint only underlying layers
|
|
||||||
*/
|
|
||||||
DrawResult PaintCell(nsTableCellFrame* aCell,
|
|
||||||
const TableBackgroundData& aRowGroupBGData,
|
|
||||||
const TableBackgroundData& aRowBGData,
|
|
||||||
nsRect& aCellBGRect,
|
|
||||||
nsRect& aRowBGRect,
|
|
||||||
nsRect& aRowGroupBGRect,
|
|
||||||
nsRect& aColBGRect,
|
|
||||||
bool aPassSelf);
|
|
||||||
|
|
||||||
/** Compute table background layer positions for this cell space
|
|
||||||
* @param aCell - the cell
|
|
||||||
* @param aRowGroupBGData - background drawing info for the row group
|
|
||||||
* @param aRowBGData - background drawing info for the row
|
|
||||||
* @param aCellBGRectOut - outparam: background rect for the cell
|
|
||||||
* @param aRowBGRectOut - outparam: background rect for the row
|
|
||||||
* @param aRowGroupBGRectOut - outparam: background rect for the row group
|
|
||||||
* @param aColBGRectOut - outparam: background rect for the column
|
|
||||||
and column group
|
|
||||||
*/
|
|
||||||
void ComputeCellBackgrounds(nsTableCellFrame* aCell,
|
|
||||||
const TableBackgroundData& aRowGroupBGData,
|
|
||||||
const TableBackgroundData& aRowBGData,
|
|
||||||
nsRect& aCellBGRect,
|
|
||||||
nsRect& aRowBGRect,
|
|
||||||
nsRect& aRowGroupBGRect,
|
|
||||||
nsRect& aColBGRect);
|
|
||||||
|
|
||||||
/** Translate mRenderingContext, mDirtyRect, and mCols' column and
|
|
||||||
* colgroup coords
|
|
||||||
* @param aDX - origin's x-coord change
|
|
||||||
* @param aDY - origin's y-coord change
|
|
||||||
*/
|
|
||||||
void TranslateContext(nscoord aDX,
|
|
||||||
nscoord aDY);
|
|
||||||
|
|
||||||
struct TableBackgroundData {
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
* Construct an empty TableBackgroundData instance, which is invisible.
|
|
||||||
*/
|
|
||||||
TableBackgroundData();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a TableBackgroundData instance for a frame. Visibility will
|
|
||||||
* be derived from the frame and can be overridden using MakeInvisible().
|
|
||||||
*/
|
|
||||||
explicit TableBackgroundData(nsIFrame* aFrame);
|
|
||||||
|
|
||||||
/** Destructor */
|
|
||||||
~TableBackgroundData() {}
|
|
||||||
|
|
||||||
/** Data is valid & frame is visible */
|
|
||||||
bool IsVisible() const { return mVisible; }
|
|
||||||
|
|
||||||
/** Override visibility of the frame, force it to be invisible */
|
|
||||||
void MakeInvisible() { mVisible = false; }
|
|
||||||
|
|
||||||
/** True if need to set border-collapse border; must call SetFull beforehand */
|
|
||||||
bool ShouldSetBCBorder() const;
|
|
||||||
|
|
||||||
/** Set border-collapse border with aBorderWidth as widths */
|
|
||||||
void SetBCBorder(const nsMargin& aBorderWidth);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param aZeroBorder An nsStyleBorder instance that has been initialized
|
|
||||||
* for the right nsPresContext, with all border widths
|
|
||||||
* set to zero and border styles set to solid.
|
|
||||||
* @return The nsStyleBorder that should be used for rendering
|
|
||||||
* this background.
|
|
||||||
*/
|
|
||||||
nsStyleBorder StyleBorder(const nsStyleBorder& aZeroBorder) const;
|
|
||||||
|
|
||||||
nsIFrame* const mFrame;
|
|
||||||
|
|
||||||
/** mRect is the rect of mFrame in the current coordinate system */
|
|
||||||
nsRect mRect;
|
|
||||||
|
|
||||||
private:
|
|
||||||
nsMargin mSynthBorderWidths;
|
|
||||||
bool mVisible;
|
|
||||||
bool mUsesSynthBorder;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ColData {
|
|
||||||
ColData(nsIFrame* aFrame, TableBackgroundData& aColGroupBGData);
|
|
||||||
TableBackgroundData mCol;
|
|
||||||
TableBackgroundData& mColGroup; // reference to col's parent colgroup's data, owned by TablePainter in mColGroups
|
|
||||||
};
|
|
||||||
|
|
||||||
nsPresContext* mPresContext;
|
|
||||||
nsRenderingContext& mRenderingContext;
|
|
||||||
nsPoint mRenderPt;
|
|
||||||
nsRect mDirtyRect;
|
|
||||||
#ifdef DEBUG
|
|
||||||
nsCompatibility mCompatMode;
|
|
||||||
#endif
|
|
||||||
bool mIsBorderCollapse;
|
|
||||||
Origin mOrigin; //user's table frame type
|
|
||||||
|
|
||||||
nsTArray<TableBackgroundData> mColGroups;
|
|
||||||
nsTArray<ColData> mCols;
|
|
||||||
size_t mNumCols;
|
|
||||||
|
|
||||||
nsStyleBorder mZeroBorder; //cached zero-width border
|
|
||||||
uint32_t mBGPaintFlags;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -561,65 +561,12 @@ nsTableRowFrame::CalcBSize(const ReflowInput& aReflowInput)
|
||||||
return GetInitialBSize();
|
return GetInitialBSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* We need a custom display item for table row backgrounds. This is only used
|
|
||||||
* when the table row is the root of a stacking context (e.g., has 'opacity').
|
|
||||||
* Table row backgrounds can extend beyond the row frame bounds, when
|
|
||||||
* the row contains row-spanning cells.
|
|
||||||
*/
|
|
||||||
class nsDisplayTableRowBackground : public nsDisplayTableItem {
|
|
||||||
public:
|
|
||||||
nsDisplayTableRowBackground(nsDisplayListBuilder* aBuilder,
|
|
||||||
nsTableRowFrame* aFrame) :
|
|
||||||
nsDisplayTableItem(aBuilder, aFrame) {
|
|
||||||
MOZ_COUNT_CTOR(nsDisplayTableRowBackground);
|
|
||||||
}
|
|
||||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
|
||||||
virtual ~nsDisplayTableRowBackground() {
|
|
||||||
MOZ_COUNT_DTOR(nsDisplayTableRowBackground);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
|
||||||
nsRenderingContext* aCtx) override;
|
|
||||||
NS_DISPLAY_DECL_NAME("TableRowBackground", TYPE_TABLE_ROW_BACKGROUND)
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
nsDisplayTableRowBackground::Paint(nsDisplayListBuilder* aBuilder,
|
|
||||||
nsRenderingContext* aCtx)
|
|
||||||
{
|
|
||||||
auto rowFrame = static_cast<nsTableRowFrame*>(mFrame);
|
|
||||||
TableBackgroundPainter painter(rowFrame->GetTableFrame(),
|
|
||||||
TableBackgroundPainter::eOrigin_TableRow,
|
|
||||||
mFrame->PresContext(), *aCtx,
|
|
||||||
mVisibleRect, ToReferenceFrame(),
|
|
||||||
aBuilder->GetBackgroundPaintFlags());
|
|
||||||
|
|
||||||
DrawResult result = painter.PaintRow(rowFrame);
|
|
||||||
nsDisplayTableItemGeometry::UpdateDrawResult(this, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
const nsDisplayListSet& aLists)
|
const nsDisplayListSet& aLists)
|
||||||
{
|
{
|
||||||
nsDisplayTableItem* item = nullptr;
|
nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists);
|
||||||
if (IsVisibleInSelection(aBuilder)) {
|
|
||||||
bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
|
|
||||||
if (isRoot) {
|
|
||||||
// This background is created regardless of whether this frame is
|
|
||||||
// visible or not. Visibility decisions are delegated to the
|
|
||||||
// table background painter.
|
|
||||||
// We would use nsDisplayGeneric for this rare case except that we
|
|
||||||
// need the background to be larger than the row frame in some
|
|
||||||
// cases.
|
|
||||||
item = new (aBuilder) nsDisplayTableRowBackground(aBuilder, this);
|
|
||||||
aLists.BorderBackground()->AppendNewToTop(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect, aLists, item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame::LogicalSides
|
nsIFrame::LogicalSides
|
||||||
|
@ -979,12 +926,11 @@ nsTableRowFrame::ReflowChildren(nsPresContext* aPresContext,
|
||||||
// be merged into the else below if we can.)
|
// be merged into the else below if we can.)
|
||||||
nsMargin* computedOffsetProp =
|
nsMargin* computedOffsetProp =
|
||||||
kidFrame->GetProperty(nsIFrame::ComputedOffsetProperty());
|
kidFrame->GetProperty(nsIFrame::ComputedOffsetProperty());
|
||||||
// Bug 975644: a position:sticky kid can end up with a null
|
|
||||||
// property value here.
|
// On our fist reflow sticky children may not have the property yet (we
|
||||||
LogicalMargin computedOffsets(wm, computedOffsetProp ?
|
// need to reflow the children first to size the scroll frame).
|
||||||
*computedOffsetProp : nsMargin());
|
LogicalMargin computedOffsets(wm, computedOffsetProp ? *computedOffsetProp : nsMargin());
|
||||||
ReflowInput::ApplyRelativePositioning(kidFrame, wm, computedOffsets,
|
ReflowInput::ApplyRelativePositioning(kidFrame, wm, computedOffsets, &kidPosition, containerSize);
|
||||||
&kidPosition, containerSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// In vertical-rl mode, we are likely to have containerSize.width = 0
|
// In vertical-rl mode, we are likely to have containerSize.width = 0
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "nscore.h"
|
#include "nscore.h"
|
||||||
#include "nsContainerFrame.h"
|
#include "nsContainerFrame.h"
|
||||||
#include "nsTablePainter.h"
|
|
||||||
#include "nsTableRowGroupFrame.h"
|
#include "nsTableRowGroupFrame.h"
|
||||||
#include "mozilla/WritingModes.h"
|
#include "mozilla/WritingModes.h"
|
||||||
|
|
||||||
|
|
|
@ -154,46 +154,6 @@ nsTableRowGroupFrame::InitRepeatedFrame(nsTableRowGroupFrame* aHeaderFooterFrame
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* We need a custom display item for table row backgrounds. This is only used
|
|
||||||
* when the table row is the root of a stacking context (e.g., has 'opacity').
|
|
||||||
* Table row backgrounds can extend beyond the row frame bounds, when
|
|
||||||
* the row contains row-spanning cells.
|
|
||||||
*/
|
|
||||||
class nsDisplayTableRowGroupBackground : public nsDisplayTableItem {
|
|
||||||
public:
|
|
||||||
nsDisplayTableRowGroupBackground(nsDisplayListBuilder* aBuilder,
|
|
||||||
nsTableRowGroupFrame* aFrame) :
|
|
||||||
nsDisplayTableItem(aBuilder, aFrame) {
|
|
||||||
MOZ_COUNT_CTOR(nsDisplayTableRowGroupBackground);
|
|
||||||
}
|
|
||||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
|
||||||
virtual ~nsDisplayTableRowGroupBackground() {
|
|
||||||
MOZ_COUNT_DTOR(nsDisplayTableRowGroupBackground);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
|
||||||
nsRenderingContext* aCtx) override;
|
|
||||||
|
|
||||||
NS_DISPLAY_DECL_NAME("TableRowGroupBackground", TYPE_TABLE_ROW_GROUP_BACKGROUND)
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
nsDisplayTableRowGroupBackground::Paint(nsDisplayListBuilder* aBuilder,
|
|
||||||
nsRenderingContext* aCtx)
|
|
||||||
{
|
|
||||||
auto rgFrame = static_cast<nsTableRowGroupFrame*>(mFrame);
|
|
||||||
TableBackgroundPainter painter(rgFrame->GetTableFrame(),
|
|
||||||
TableBackgroundPainter::eOrigin_TableRowGroup,
|
|
||||||
mFrame->PresContext(), *aCtx,
|
|
||||||
mVisibleRect, ToReferenceFrame(),
|
|
||||||
aBuilder->GetBackgroundPaintFlags());
|
|
||||||
|
|
||||||
DrawResult result = painter.PaintRowGroup(rgFrame);
|
|
||||||
nsDisplayTableItemGeometry::UpdateDrawResult(this, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Handle the child-traversal part of DisplayGenericTablePart
|
// Handle the child-traversal part of DisplayGenericTablePart
|
||||||
static void
|
static void
|
||||||
DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
|
DisplayRows(nsDisplayListBuilder* aBuilder, nsFrame* aFrame,
|
||||||
|
@ -249,19 +209,8 @@ nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
const nsRect& aDirtyRect,
|
const nsRect& aDirtyRect,
|
||||||
const nsDisplayListSet& aLists)
|
const nsDisplayListSet& aLists)
|
||||||
{
|
{
|
||||||
nsDisplayTableItem* item = nullptr;
|
|
||||||
if (IsVisibleInSelection(aBuilder)) {
|
|
||||||
bool isRoot = aBuilder->IsAtRootOfPseudoStackingContext();
|
|
||||||
if (isRoot) {
|
|
||||||
// This background is created regardless of whether this frame is
|
|
||||||
// visible or not. Visibility decisions are delegated to the
|
|
||||||
// table background painter.
|
|
||||||
item = new (aBuilder) nsDisplayTableRowGroupBackground(aBuilder, this);
|
|
||||||
aLists.BorderBackground()->AppendNewToTop(item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect,
|
nsTableFrame::DisplayGenericTablePart(aBuilder, this, aDirtyRect,
|
||||||
aLists, item, DisplayRows);
|
aLists, DisplayRows);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame::LogicalSides
|
nsIFrame::LogicalSides
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include "nsContainerFrame.h"
|
#include "nsContainerFrame.h"
|
||||||
#include "nsIAtom.h"
|
#include "nsIAtom.h"
|
||||||
#include "nsILineIterator.h"
|
#include "nsILineIterator.h"
|
||||||
#include "nsTablePainter.h"
|
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsTableFrame.h"
|
#include "nsTableFrame.h"
|
||||||
#include "mozilla/WritingModes.h"
|
#include "mozilla/WritingModes.h"
|
||||||
|
|
|
@ -190,7 +190,11 @@ nsTableWrapperFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
|
|
||||||
// Now we have to sort everything by content order, since the caption
|
// Now we have to sort everything by content order, since the caption
|
||||||
// may be somewhere inside the table
|
// may be somewhere inside the table
|
||||||
set.SortAllByContentOrder(GetContent());
|
set.BlockBorderBackgrounds()->SortByContentOrder(GetContent());
|
||||||
|
set.Floats()->SortByContentOrder(GetContent());
|
||||||
|
set.Content()->SortByContentOrder(GetContent());
|
||||||
|
set.PositionedDescendants()->SortByContentOrder(GetContent());
|
||||||
|
set.Outlines()->SortByContentOrder(GetContent());
|
||||||
set.MoveTo(aLists);
|
set.MoveTo(aLists);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue