1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204 |
- /* -*- 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 "nsTableCellFrame.h"
- #include "gfxUtils.h"
- #include "mozilla/gfx/2D.h"
- #include "mozilla/gfx/Helpers.h"
- #include "nsTableFrame.h"
- #include "nsTableColFrame.h"
- #include "nsTableRowFrame.h"
- #include "nsTableRowGroupFrame.h"
- #include "nsStyleContext.h"
- #include "nsStyleConsts.h"
- #include "nsPresContext.h"
- #include "nsRenderingContext.h"
- #include "nsCSSRendering.h"
- #include "nsIContent.h"
- #include "nsGenericHTMLElement.h"
- #include "nsAttrValueInlines.h"
- #include "nsHTMLParts.h"
- #include "nsGkAtoms.h"
- #include "nsIPresShell.h"
- #include "nsCOMPtr.h"
- #include "nsIServiceManager.h"
- #include "nsIDOMNode.h"
- #include "nsNameSpaceManager.h"
- #include "nsDisplayList.h"
- #include "nsLayoutUtils.h"
- #include "nsTextFrame.h"
- #include "FrameLayerBuilder.h"
- #include <algorithm>
- //TABLECELL SELECTION
- #include "nsFrameSelection.h"
- #include "mozilla/LookAndFeel.h"
- using namespace mozilla;
- using namespace mozilla::gfx;
- using namespace mozilla::image;
- nsTableCellFrame::nsTableCellFrame(nsStyleContext* aContext,
- nsTableFrame* aTableFrame)
- : nsContainerFrame(aContext)
- , mDesiredSize(aTableFrame->GetWritingMode())
- {
- mColIndex = 0;
- mPriorAvailISize = 0;
- SetContentEmpty(false);
- SetHasPctOverBSize(false);
- }
- nsTableCellFrame::~nsTableCellFrame()
- {
- }
- NS_IMPL_FRAMEARENA_HELPERS(nsTableCellFrame)
- void
- nsTableCellFrame::Init(nsIContent* aContent,
- nsContainerFrame* aParent,
- nsIFrame* aPrevInFlow)
- {
- // Let the base class do its initialization
- nsContainerFrame::Init(aContent, aParent, aPrevInFlow);
- if (HasAnyStateBits(NS_FRAME_FONT_INFLATION_CONTAINER)) {
- AddStateBits(NS_FRAME_FONT_INFLATION_FLOW_ROOT);
- }
- if (aPrevInFlow) {
- // Set the column index
- nsTableCellFrame* cellFrame = (nsTableCellFrame*)aPrevInFlow;
- uint32_t colIndex = cellFrame->ColIndex();
- SetColIndex(colIndex);
- }
- }
- void
- nsTableCellFrame::DestroyFrom(nsIFrame* aDestructRoot)
- {
- if (HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
- nsTableFrame::UnregisterPositionedTablePart(this, aDestructRoot);
- }
- nsContainerFrame::DestroyFrom(aDestructRoot);
- }
- // nsIPercentBSizeObserver methods
- void
- nsTableCellFrame::NotifyPercentBSize(const ReflowInput& aReflowInput)
- {
- // ReflowInput ensures the mCBReflowInput of blocks inside a
- // cell is the cell frame, not the inner-cell block, and that the
- // containing block of an inner table is the containing block of its
- // table wrapper.
- // XXXldb Given the now-stricter |NeedsToObserve|, many if not all of
- // these tests are probably unnecessary.
- // Maybe the cell reflow state; we sure if we're inside the |if|.
- const ReflowInput *cellRI = aReflowInput.mCBReflowInput;
- if (cellRI && cellRI->mFrame == this &&
- (cellRI->ComputedBSize() == NS_UNCONSTRAINEDSIZE ||
- cellRI->ComputedBSize() == 0)) { // XXXldb Why 0?
- // This is a percentage bsize on a frame whose percentage bsizes
- // are based on the bsize of the cell, since its containing block
- // is the inner cell frame.
- // We'll only honor the percent bsize if sibling-cells/ancestors
- // have specified/pct bsize. (Also, siblings only count for this if
- // both this cell and the sibling cell span exactly 1 row.)
- if (nsTableFrame::AncestorsHaveStyleBSize(*cellRI) ||
- (GetTableFrame()->GetEffectiveRowSpan(*this) == 1 &&
- cellRI->mParentReflowInput->mFrame->
- HasAnyStateBits(NS_ROW_HAS_CELL_WITH_STYLE_BSIZE))) {
- for (const ReflowInput *rs = aReflowInput.mParentReflowInput;
- rs != cellRI;
- rs = rs->mParentReflowInput) {
- rs->mFrame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE);
- }
- nsTableFrame::RequestSpecialBSizeReflow(*cellRI);
- }
- }
- }
- // The cell needs to observe its block and things inside its block but nothing below that
- bool
- nsTableCellFrame::NeedsToObserve(const ReflowInput& aReflowInput)
- {
- const ReflowInput *rs = aReflowInput.mParentReflowInput;
- if (!rs)
- return false;
- if (rs->mFrame == this) {
- // We always observe the child block. It will never send any
- // notifications, but we need this so that the observer gets
- // propagated to its kids.
- return true;
- }
- rs = rs->mParentReflowInput;
- if (!rs) {
- return false;
- }
- // We always need to let the percent bsize observer be propagated
- // from a table wrapper frame to an inner table frame.
- nsIAtom *fType = aReflowInput.mFrame->GetType();
- if (fType == nsGkAtoms::tableFrame) {
- return true;
- }
- // We need the observer to be propagated to all children of the cell
- // (i.e., children of the child block) in quirks mode, but only to
- // tables in standards mode.
- // XXX This may not be true in the case of orthogonal flows within
- // the cell (bug 1174711 comment 8); we may need to observe isizes
- // instead of bsizes for orthogonal children.
- return rs->mFrame == this &&
- (PresContext()->CompatibilityMode() == eCompatibility_NavQuirks ||
- fType == nsGkAtoms::tableWrapperFrame);
- }
- nsresult
- nsTableCellFrame::AttributeChanged(int32_t aNameSpaceID,
- nsIAtom* aAttribute,
- int32_t aModType)
- {
- // We need to recalculate in this case because of the nowrap quirk in
- // BasicTableLayoutStrategy
- if (aNameSpaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::nowrap &&
- PresContext()->CompatibilityMode() == eCompatibility_NavQuirks) {
- PresContext()->PresShell()->
- FrameNeedsReflow(this, nsIPresShell::eTreeChange, NS_FRAME_IS_DIRTY);
- }
- // let the table frame decide what to do
- GetTableFrame()->AttributeChangedFor(this, mContent, aAttribute);
- return NS_OK;
- }
- /* virtual */ void
- nsTableCellFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
- {
- nsContainerFrame::DidSetStyleContext(aOldStyleContext);
- if (!aOldStyleContext) //avoid this on init
- return;
- nsTableFrame* tableFrame = GetTableFrame();
- if (tableFrame->IsBorderCollapse() &&
- tableFrame->BCRecalcNeeded(aOldStyleContext, StyleContext())) {
- uint32_t colIndex = ColIndex();
- uint32_t rowIndex = RowIndex();
- // row span needs to be clamped as we do not create rows in the cellmap
- // which do not have cells originating in them
- TableArea damageArea(colIndex, rowIndex, GetColSpan(),
- std::min(static_cast<uint32_t>(GetRowSpan()),
- tableFrame->GetRowCount() - rowIndex));
- tableFrame->AddBCDamageArea(damageArea);
- }
- }
- #ifdef DEBUG
- void
- nsTableCellFrame::AppendFrames(ChildListID aListID,
- nsFrameList& aFrameList)
- {
- MOZ_CRASH("unsupported operation");
- }
- void
- nsTableCellFrame::InsertFrames(ChildListID aListID,
- nsIFrame* aPrevFrame,
- nsFrameList& aFrameList)
- {
- MOZ_CRASH("unsupported operation");
- }
- void
- nsTableCellFrame::RemoveFrame(ChildListID aListID,
- nsIFrame* aOldFrame)
- {
- MOZ_CRASH("unsupported operation");
- }
- #endif
- void nsTableCellFrame::SetColIndex(int32_t aColIndex)
- {
- mColIndex = aColIndex;
- }
- /* virtual */ nsMargin
- nsTableCellFrame::GetUsedMargin() const
- {
- return nsMargin(0,0,0,0);
- }
- //ASSURE DIFFERENT COLORS for selection
- inline nscolor EnsureDifferentColors(nscolor colorA, nscolor colorB)
- {
- if (colorA == colorB)
- {
- nscolor res;
- res = NS_RGB(NS_GET_R(colorA) ^ 0xff,
- NS_GET_G(colorA) ^ 0xff,
- NS_GET_B(colorA) ^ 0xff);
- return res;
- }
- return colorA;
- }
- void
- nsTableCellFrame::DecorateForSelection(DrawTarget* aDrawTarget, nsPoint aPt)
- {
- NS_ASSERTION(IsSelected(), "Should only be called for selected cells");
- int16_t displaySelection;
- nsPresContext* presContext = PresContext();
- displaySelection = DisplaySelection(presContext);
- if (displaySelection) {
- RefPtr<nsFrameSelection> frameSelection =
- presContext->PresShell()->FrameSelection();
- if (frameSelection->GetTableCellSelection()) {
- nscolor bordercolor;
- if (displaySelection == nsISelectionController::SELECTION_DISABLED) {
- bordercolor = NS_RGB(176,176,176);// disabled color
- }
- else {
- bordercolor =
- LookAndFeel::GetColor(LookAndFeel::eColorID_TextSelectBackground);
- }
- nscoord threePx = nsPresContext::CSSPixelsToAppUnits(3);
- if ((mRect.width > threePx) && (mRect.height > threePx))
- {
- //compare bordercolor to ((nsStyleColor *)myColor)->mBackgroundColor)
- bordercolor = EnsureDifferentColors(bordercolor,
- StyleBackground()->mBackgroundColor);
- int32_t appUnitsPerDevPixel = PresContext()->AppUnitsPerDevPixel();
- Point devPixelOffset = NSPointToPoint(aPt, appUnitsPerDevPixel);
- AutoRestoreTransform autoRestoreTransform(aDrawTarget);
- aDrawTarget->SetTransform(
- aDrawTarget->GetTransform().PreTranslate(devPixelOffset));
- ColorPattern color(ToDeviceColor(bordercolor));
- nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
- StrokeLineWithSnapping(nsPoint(onePixel, 0), nsPoint(mRect.width, 0),
- appUnitsPerDevPixel, *aDrawTarget, color);
- StrokeLineWithSnapping(nsPoint(0, onePixel), nsPoint(0, mRect.height),
- appUnitsPerDevPixel, *aDrawTarget, color);
- StrokeLineWithSnapping(nsPoint(onePixel, mRect.height),
- nsPoint(mRect.width, mRect.height),
- appUnitsPerDevPixel, *aDrawTarget, color);
- StrokeLineWithSnapping(nsPoint(mRect.width, onePixel),
- nsPoint(mRect.width, mRect.height),
- appUnitsPerDevPixel, *aDrawTarget, color);
- //middle
- nsRect r(onePixel, onePixel,
- mRect.width - onePixel, mRect.height - onePixel);
- Rect devPixelRect =
- NSRectToSnappedRect(r, appUnitsPerDevPixel, *aDrawTarget);
- aDrawTarget->StrokeRect(devPixelRect, color);
- //shading
- StrokeLineWithSnapping(nsPoint(2*onePixel, mRect.height-2*onePixel),
- nsPoint(mRect.width-onePixel, mRect.height- (2*onePixel)),
- appUnitsPerDevPixel, *aDrawTarget, color);
- StrokeLineWithSnapping(nsPoint(mRect.width - (2*onePixel), 2*onePixel),
- nsPoint(mRect.width - (2*onePixel), mRect.height-onePixel),
- appUnitsPerDevPixel, *aDrawTarget, color);
- }
- }
- }
- }
- DrawResult
- nsTableCellFrame::PaintBackground(nsRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect,
- nsPoint aPt,
- uint32_t aFlags)
- {
- nsRect rect(aPt, GetSize());
- nsCSSRendering::PaintBGParams params =
- nsCSSRendering::PaintBGParams::ForAllLayers(*PresContext(),
- aRenderingContext,
- aDirtyRect, rect,
- this, aFlags);
- return nsCSSRendering::PaintBackground(params);
- }
- nsresult
- nsTableCellFrame::ProcessBorders(nsTableFrame* aFrame,
- nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists)
- {
- const nsStyleBorder* borderStyle = StyleBorder();
- if (aFrame->IsBorderCollapse() || !borderStyle->HasBorder())
- return NS_OK;
- if (!GetContentEmpty() ||
- StyleTableBorder()->mEmptyCells == NS_STYLE_TABLE_EMPTY_CELLS_SHOW) {
- aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
- nsDisplayBorder(aBuilder, this));
- }
- return NS_OK;
- }
- class nsDisplayTableCellBackground : public nsDisplayTableItem {
- public:
- nsDisplayTableCellBackground(nsDisplayListBuilder* aBuilder,
- nsTableCellFrame* aFrame) :
- nsDisplayTableItem(aBuilder, aFrame) {
- MOZ_COUNT_CTOR(nsDisplayTableCellBackground);
- }
- #ifdef NS_BUILD_REFCNT_LOGGING
- virtual ~nsDisplayTableCellBackground() {
- MOZ_COUNT_DTOR(nsDisplayTableCellBackground);
- }
- #endif
- virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
- HitTestState* aState,
- nsTArray<nsIFrame*> *aOutFrames) override {
- aOutFrames->AppendElement(mFrame);
- }
- virtual void Paint(nsDisplayListBuilder* aBuilder,
- nsRenderingContext* aCtx) override;
- virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
- bool* aSnap) override;
- NS_DISPLAY_DECL_NAME("TableCellBackground", TYPE_TABLE_CELL_BACKGROUND)
- };
- void nsDisplayTableCellBackground::Paint(nsDisplayListBuilder* aBuilder,
- nsRenderingContext* aCtx)
- {
- DrawResult result = static_cast<nsTableCellFrame*>(mFrame)->
- PaintBackground(*aCtx, mVisibleRect, ToReferenceFrame(),
- aBuilder->GetBackgroundPaintFlags());
- nsDisplayTableItemGeometry::UpdateDrawResult(this, result);
- }
- nsRect
- nsDisplayTableCellBackground::GetBounds(nsDisplayListBuilder* aBuilder,
- bool* aSnap)
- {
- // revert from nsDisplayTableItem's implementation ... cell backgrounds
- // don't overflow the cell
- return nsDisplayItem::GetBounds(aBuilder, aSnap);
- }
- void nsTableCellFrame::InvalidateFrame(uint32_t aDisplayItemKey)
- {
- nsIFrame::InvalidateFrame(aDisplayItemKey);
- GetParent()->InvalidateFrameWithRect(GetVisualOverflowRect() + GetPosition(), aDisplayItemKey);
- }
- void nsTableCellFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
- {
- nsIFrame::InvalidateFrameWithRect(aRect, aDisplayItemKey);
- // If we have filters applied that would affects our bounds, then
- // we get an inactive layer created and this is computed
- // within FrameLayerBuilder
- GetParent()->InvalidateFrameWithRect(aRect + GetPosition(), aDisplayItemKey);
- }
- static void
- PaintTableCellSelection(nsIFrame* aFrame, DrawTarget* aDrawTarget,
- const nsRect& aRect, nsPoint aPt)
- {
- static_cast<nsTableCellFrame*>(aFrame)->DecorateForSelection(aDrawTarget,
- aPt);
- }
- bool
- nsTableCellFrame::ShouldPaintBordersAndBackgrounds() const
- {
- // If we're not visible, we don't paint.
- if (!StyleVisibility()->IsVisible()) {
- return false;
- }
- // Consider 'empty-cells', but only in separated borders mode.
- if (!GetContentEmpty()) {
- return true;
- }
- nsTableFrame* tableFrame = GetTableFrame();
- if (tableFrame->IsBorderCollapse()) {
- return true;
- }
- return StyleTableBorder()->mEmptyCells == NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
- }
- bool
- nsTableCellFrame::ShouldPaintBackground(nsDisplayListBuilder* aBuilder)
- {
- return ShouldPaintBordersAndBackgrounds() && IsVisibleInSelection(aBuilder);
- }
- void
- nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
- const nsDisplayListSet& aLists)
- {
- DO_GLOBAL_REFLOW_COUNT_DSP("nsTableCellFrame");
- if (ShouldPaintBordersAndBackgrounds()) {
- // display outset box-shadows if we need to.
- bool hasBoxShadow = !!StyleEffects()->mBoxShadow;
- if (hasBoxShadow) {
- aLists.BorderBackground()->AppendNewToTop(
- new (aBuilder) nsDisplayBoxShadowOuter(aBuilder, this));
- }
- nsRect bgRect = GetRectRelativeToSelf() + aBuilder->ToReferenceFrame(this);
- // display background if we need to.
- if (aBuilder->IsForEventDelivery() ||
- !StyleBackground()->IsTransparent() ||
- StyleDisplay()->mAppearance) {
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
- aBuilder, this, bgRect, aLists.BorderBackground());
- }
- // 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(GetTableFrame(), 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));
- }
- // This can be null if display list building initiated in the middle
- // of the table, which can happen with background-clip:text and
- // -moz-element.
- nsDisplayTableBackgroundSet* backgrounds =
- aBuilder->GetTableBackgroundSet();
- if (backgrounds) {
- // Compute bgRect relative to reference frame, but using the
- // normal (without position:relative offsets) positions for the
- // cell, row and row group.
- bgRect = GetRectRelativeToSelf() + GetNormalPosition();
- nsTableRowFrame* row = GetTableRowFrame();
- bgRect += row->GetNormalPosition();
- nsTableRowGroupFrame* rowGroup = row->GetTableRowGroupFrame();
- bgRect += rowGroup->GetNormalPosition();
- bgRect += backgrounds->TableToReferenceFrame();
- // Create backgrounds items as needed for the column and column
- // group that this cell occupies.
- nsTableColFrame* col = backgrounds->GetColForIndex(ColIndex());
- nsTableColGroupFrame* colGroup = col->GetTableColGroupFrame();
- Maybe<nsDisplayListBuilder::AutoBuildingDisplayList> buildingForColGroup;
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
- aBuilder, colGroup, bgRect, backgrounds->ColGroupBackgrounds(), false,
- nullptr, colGroup->GetRect() + backgrounds->TableToReferenceFrame(),
- this, &buildingForColGroup);
- Maybe<nsDisplayListBuilder::AutoBuildingDisplayList> buildingForCol;
- nsDisplayBackgroundImage::AppendBackgroundItemsToTop(
- aBuilder, col, bgRect, backgrounds->ColBackgrounds(), false, nullptr,
- col->GetRect() + colGroup->GetPosition() +
- backgrounds->TableToReferenceFrame(),
- this, &buildingForCol);
- }
- }
- // the 'empty-cells' property has no effect on 'outline'
- DisplayOutline(aBuilder, aLists);
- nsIFrame* kid = mFrames.FirstChild();
- NS_ASSERTION(kid && !kid->GetNextSibling(), "Table cells should have just one child");
- // The child's background will go in our BorderBackground() list.
- // This isn't a problem since it won't have a real background except for
- // event handling. We do not call BuildDisplayListForNonBlockChildren
- // because that/ would put the child's background in the Content() list
- // which isn't right (e.g., would end up on top of our child floats for
- // event handling).
- BuildDisplayListForChild(aBuilder, kid, aLists);
- }
- nsIFrame::LogicalSides
- nsTableCellFrame::GetLogicalSkipSides(const ReflowInput* aReflowInput) const
- {
- if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
- StyleBoxDecorationBreak::Clone)) {
- return LogicalSides();
- }
- LogicalSides skip;
- if (nullptr != GetPrevInFlow()) {
- skip |= eLogicalSideBitsBStart;
- }
- if (nullptr != GetNextInFlow()) {
- skip |= eLogicalSideBitsBEnd;
- }
- return skip;
- }
- /* virtual */ nsMargin
- nsTableCellFrame::GetBorderOverflow()
- {
- return nsMargin(0, 0, 0, 0);
- }
- // Align the cell's child frame within the cell
- void nsTableCellFrame::BlockDirAlignChild(WritingMode aWM, nscoord aMaxAscent)
- {
- /* It's the 'border-collapse' on the table that matters */
- LogicalMargin borderPadding = GetLogicalUsedBorderAndPadding(aWM);
- nscoord bStartInset = borderPadding.BStart(aWM);
- nscoord bEndInset = borderPadding.BEnd(aWM);
- uint8_t verticalAlignFlags = GetVerticalAlign();
- nscoord bSize = BSize(aWM);
- nsIFrame* firstKid = mFrames.FirstChild();
- nsSize containerSize = mRect.Size();
- NS_ASSERTION(firstKid, "Frame construction error, a table cell always has "
- "an inner cell frame");
- LogicalRect kidRect = firstKid->GetLogicalRect(aWM, containerSize);
- nscoord childBSize = kidRect.BSize(aWM);
- // Vertically align the child
- nscoord kidBStart = 0;
- switch (verticalAlignFlags)
- {
- case NS_STYLE_VERTICAL_ALIGN_BASELINE:
- // Align the baselines of the child frame with the baselines of
- // other children in the same row which have 'vertical-align: baseline'
- kidBStart = bStartInset + aMaxAscent - GetCellBaseline();
- break;
- case NS_STYLE_VERTICAL_ALIGN_TOP:
- // Align the top of the child frame with the top of the content area,
- kidBStart = bStartInset;
- break;
- case NS_STYLE_VERTICAL_ALIGN_BOTTOM:
- // Align the bottom of the child frame with the bottom of the content area,
- kidBStart = bSize - childBSize - bEndInset;
- break;
- default:
- case NS_STYLE_VERTICAL_ALIGN_MIDDLE:
- // Align the middle of the child frame with the middle of the content area,
- kidBStart = (bSize - childBSize - bEndInset + bStartInset) / 2;
- }
- // If the content is larger than the cell bsize, align from bStartInset
- // (cell's content-box bstart edge).
- kidBStart = std::max(bStartInset, kidBStart);
- if (kidBStart != kidRect.BStart(aWM)) {
- // Invalidate at the old position first
- firstKid->InvalidateFrameSubtree();
- }
- firstKid->SetPosition(aWM, LogicalPoint(aWM, kidRect.IStart(aWM),
- kidBStart), containerSize);
- ReflowOutput desiredSize(aWM);
- desiredSize.SetSize(aWM, GetLogicalSize(aWM));
- nsRect overflow(nsPoint(0,0), GetSize());
- overflow.Inflate(GetBorderOverflow());
- desiredSize.mOverflowAreas.SetAllTo(overflow);
- ConsiderChildOverflow(desiredSize.mOverflowAreas, firstKid);
- FinishAndStoreOverflow(&desiredSize);
- if (kidBStart != kidRect.BStart(aWM)) {
- // Make sure any child views are correctly positioned. We know the inner table
- // cell won't have a view
- nsContainerFrame::PositionChildViews(firstKid);
- // Invalidate new overflow rect
- firstKid->InvalidateFrameSubtree();
- }
- if (HasView()) {
- nsContainerFrame::SyncFrameViewAfterReflow(PresContext(), this,
- GetView(),
- desiredSize.VisualOverflow(), 0);
- }
- }
- bool
- nsTableCellFrame::ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas)
- {
- nsRect bounds(nsPoint(0,0), GetSize());
- bounds.Inflate(GetBorderOverflow());
- aOverflowAreas.UnionAllWith(bounds);
- return nsContainerFrame::ComputeCustomOverflow(aOverflowAreas);
- }
- // Per CSS 2.1, we map 'sub', 'super', 'text-top', 'text-bottom',
- // length, percentage, and calc() values to 'baseline'.
- uint8_t
- nsTableCellFrame::GetVerticalAlign() const
- {
- const nsStyleCoord& verticalAlign = StyleDisplay()->mVerticalAlign;
- if (verticalAlign.GetUnit() == eStyleUnit_Enumerated) {
- uint8_t value = verticalAlign.GetIntValue();
- if (value == NS_STYLE_VERTICAL_ALIGN_TOP ||
- value == NS_STYLE_VERTICAL_ALIGN_MIDDLE ||
- value == NS_STYLE_VERTICAL_ALIGN_BOTTOM) {
- return value;
- }
- }
- return NS_STYLE_VERTICAL_ALIGN_BASELINE;
- }
- bool
- nsTableCellFrame::CellHasVisibleContent(nscoord height,
- nsTableFrame* tableFrame,
- nsIFrame* kidFrame)
- {
- // see http://www.w3.org/TR/CSS21/tables.html#empty-cells
- if (height > 0)
- return true;
- if (tableFrame->IsBorderCollapse())
- return true;
- for (nsIFrame* innerFrame : kidFrame->PrincipalChildList()) {
- nsIAtom* frameType = innerFrame->GetType();
- if (nsGkAtoms::textFrame == frameType) {
- nsTextFrame* textFrame = static_cast<nsTextFrame*>(innerFrame);
- if (textFrame->HasNoncollapsedCharacters())
- return true;
- }
- else if (nsGkAtoms::placeholderFrame != frameType) {
- return true;
- }
- else {
- nsIFrame *floatFrame = nsLayoutUtils::GetFloatFromPlaceholder(innerFrame);
- if (floatFrame)
- return true;
- }
- }
- return false;
- }
- nscoord
- nsTableCellFrame::GetCellBaseline() const
- {
- // Ignore the position of the inner frame relative to the cell frame
- // since we want the position as though the inner were top-aligned.
- nsIFrame *inner = mFrames.FirstChild();
- nscoord borderPadding = GetUsedBorderAndPadding().top;
- nscoord result;
- if (nsLayoutUtils::GetFirstLineBaseline(GetWritingMode(), inner, &result))
- return result + borderPadding;
- return inner->GetContentRectRelativeToSelf().YMost() +
- borderPadding;
- }
- int32_t
- nsTableCellFrame::GetRowSpan()
- {
- int32_t rowSpan=1;
- // Don't look at the content's rowspan if we're a pseudo cell
- if (!StyleContext()->GetPseudo()) {
- dom::Element* elem = mContent->AsElement();
- const nsAttrValue* attr = elem->GetParsedAttr(nsGkAtoms::rowspan);
- // Note that we don't need to check the tag name, because only table cells
- // (including MathML <mtd>) and table headers parse the "rowspan" attribute
- // into an integer.
- if (attr && attr->Type() == nsAttrValue::eInteger) {
- rowSpan = attr->GetIntegerValue();
- }
- }
- return rowSpan;
- }
- int32_t
- nsTableCellFrame::GetColSpan()
- {
- int32_t colSpan=1;
- // Don't look at the content's colspan if we're a pseudo cell
- if (!StyleContext()->GetPseudo()) {
- dom::Element* elem = mContent->AsElement();
- const nsAttrValue* attr = elem->GetParsedAttr(
- MOZ_UNLIKELY(elem->IsMathMLElement()) ? nsGkAtoms::columnspan_
- : nsGkAtoms::colspan);
- // Note that we don't need to check the tag name, because only table cells
- // (including MathML <mtd>) and table headers parse the "colspan" attribute
- // into an integer.
- if (attr && attr->Type() == nsAttrValue::eInteger) {
- colSpan = attr->GetIntegerValue();
- }
- }
- return colSpan;
- }
- /* virtual */ nscoord
- nsTableCellFrame::GetMinISize(nsRenderingContext *aRenderingContext)
- {
- nscoord result = 0;
- DISPLAY_MIN_WIDTH(this, result);
- nsIFrame *inner = mFrames.FirstChild();
- result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner,
- nsLayoutUtils::MIN_ISIZE);
- return result;
- }
- /* virtual */ nscoord
- nsTableCellFrame::GetPrefISize(nsRenderingContext *aRenderingContext)
- {
- nscoord result = 0;
- DISPLAY_PREF_WIDTH(this, result);
- nsIFrame *inner = mFrames.FirstChild();
- result = nsLayoutUtils::IntrinsicForContainer(aRenderingContext, inner,
- nsLayoutUtils::PREF_ISIZE);
- return result;
- }
- /* virtual */ nsIFrame::IntrinsicISizeOffsetData
- nsTableCellFrame::IntrinsicISizeOffsets(nscoord aPercentageBasis)
- {
- IntrinsicISizeOffsetData result =
- nsContainerFrame::IntrinsicISizeOffsets(aPercentageBasis);
- result.hMargin = 0;
- WritingMode wm = GetWritingMode();
- result.hBorder = GetBorderWidth(wm).IStartEnd(wm);
- return result;
- }
- #ifdef DEBUG
- #define PROBABLY_TOO_LARGE 1000000
- static
- void DebugCheckChildSize(nsIFrame* aChild,
- ReflowOutput& aMet)
- {
- WritingMode wm = aMet.GetWritingMode();
- if ((aMet.ISize(wm) < 0) || (aMet.ISize(wm) > PROBABLY_TOO_LARGE)) {
- printf("WARNING: cell content %p has large inline size %d \n",
- static_cast<void*>(aChild), int32_t(aMet.ISize(wm)));
- }
- }
- #endif
- // the computed bsize for the cell, which descendants use for percent bsize calculations
- // it is the bsize (minus border, padding) of the cell's first in flow during its final
- // reflow without an unconstrained bsize.
- static nscoord
- CalcUnpaginatedBSize(nsTableCellFrame& aCellFrame,
- nsTableFrame& aTableFrame,
- nscoord aBlockDirBorderPadding)
- {
- const nsTableCellFrame* firstCellInFlow =
- static_cast<nsTableCellFrame*>(aCellFrame.FirstInFlow());
- nsTableFrame* firstTableInFlow =
- static_cast<nsTableFrame*>(aTableFrame.FirstInFlow());
- nsTableRowFrame* row =
- static_cast<nsTableRowFrame*>(firstCellInFlow->GetParent());
- nsTableRowGroupFrame* firstRGInFlow =
- static_cast<nsTableRowGroupFrame*>(row->GetParent());
- uint32_t rowIndex = firstCellInFlow->RowIndex();
- int32_t rowSpan = aTableFrame.GetEffectiveRowSpan(*firstCellInFlow);
- nscoord computedBSize = firstTableInFlow->GetRowSpacing(rowIndex,
- rowIndex + rowSpan - 1);
- computedBSize -= aBlockDirBorderPadding;
- uint32_t rowX;
- for (row = firstRGInFlow->GetFirstRow(), rowX = 0; row; row = row->GetNextRow(), rowX++) {
- if (rowX > rowIndex + rowSpan - 1) {
- break;
- }
- else if (rowX >= rowIndex) {
- computedBSize += row->GetUnpaginatedBSize();
- }
- }
- return computedBSize;
- }
- void
- nsTableCellFrame::Reflow(nsPresContext* aPresContext,
- ReflowOutput& aDesiredSize,
- const ReflowInput& aReflowInput,
- nsReflowStatus& aStatus)
- {
- MarkInReflow();
- DO_GLOBAL_REFLOW_COUNT("nsTableCellFrame");
- DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
- if (aReflowInput.mFlags.mSpecialBSizeReflow) {
- FirstInFlow()->AddStateBits(NS_TABLE_CELL_HAD_SPECIAL_REFLOW);
- }
- // see if a special bsize reflow needs to occur due to having a pct height
- nsTableFrame::CheckRequestSpecialBSizeReflow(aReflowInput);
- aStatus = NS_FRAME_COMPLETE;
- WritingMode wm = aReflowInput.GetWritingMode();
- LogicalSize availSize(wm, aReflowInput.AvailableISize(),
- aReflowInput.AvailableBSize());
- LogicalMargin borderPadding = aReflowInput.ComputedLogicalPadding();
- LogicalMargin border = GetBorderWidth(wm);
- borderPadding += border;
- // reduce available space by insets, if we're in a constrained situation
- availSize.ISize(wm) -= borderPadding.IStartEnd(wm);
- if (NS_UNCONSTRAINEDSIZE != availSize.BSize(wm)) {
- availSize.BSize(wm) -= borderPadding.BStartEnd(wm);
- }
- // Try to reflow the child into the available space. It might not
- // fit or might need continuing.
- if (availSize.BSize(wm) < 0) {
- availSize.BSize(wm) = 1;
- }
- ReflowOutput kidSize(wm, aDesiredSize.mFlags);
- kidSize.ClearSize();
- SetPriorAvailISize(aReflowInput.AvailableISize());
- nsIFrame* firstKid = mFrames.FirstChild();
- NS_ASSERTION(firstKid, "Frame construction error, a table cell always has an inner cell frame");
- nsTableFrame* tableFrame = GetTableFrame();
- if (aReflowInput.mFlags.mSpecialBSizeReflow) {
- const_cast<ReflowInput&>(aReflowInput).
- SetComputedBSize(BSize(wm) - borderPadding.BStartEnd(wm));
- DISPLAY_REFLOW_CHANGE();
- }
- else if (aPresContext->IsPaginated()) {
- nscoord computedUnpaginatedBSize =
- CalcUnpaginatedBSize((nsTableCellFrame&)*this,
- *tableFrame, borderPadding.BStartEnd(wm));
- if (computedUnpaginatedBSize > 0) {
- const_cast<ReflowInput&>(aReflowInput).SetComputedBSize(computedUnpaginatedBSize);
- DISPLAY_REFLOW_CHANGE();
- }
- }
- else {
- SetHasPctOverBSize(false);
- }
- WritingMode kidWM = firstKid->GetWritingMode();
- ReflowInput kidReflowInput(aPresContext, aReflowInput, firstKid,
- availSize.ConvertTo(kidWM, wm));
- // Don't be a percent height observer if we're in the middle of
- // special-bsize reflow, in case we get an accidental NotifyPercentBSize()
- // call (which we shouldn't honor during special-bsize reflow)
- if (!aReflowInput.mFlags.mSpecialBSizeReflow) {
- // mPercentBSizeObserver is for children of cells in quirks mode,
- // but only those than are tables in standards mode. NeedsToObserve
- // will determine how far this is propagated to descendants.
- kidReflowInput.mPercentBSizeObserver = this;
- }
- // Don't propagate special bsize reflow state to our kids
- kidReflowInput.mFlags.mSpecialBSizeReflow = false;
- if (aReflowInput.mFlags.mSpecialBSizeReflow ||
- FirstInFlow()->HasAnyStateBits(NS_TABLE_CELL_HAD_SPECIAL_REFLOW)) {
- // We need to force the kid to have mBResize set if we've had a
- // special reflow in the past, since the non-special reflow needs to
- // resize back to what it was without the special bsize reflow.
- kidReflowInput.SetBResize(true);
- }
- nsSize containerSize =
- aReflowInput.ComputedSizeAsContainerIfConstrained();
- LogicalPoint kidOrigin(wm, borderPadding.IStart(wm),
- borderPadding.BStart(wm));
- nsRect origRect = firstKid->GetRect();
- nsRect origVisualOverflow = firstKid->GetVisualOverflowRect();
- bool firstReflow = firstKid->HasAnyStateBits(NS_FRAME_FIRST_REFLOW);
- ReflowChild(firstKid, aPresContext, kidSize, kidReflowInput,
- wm, kidOrigin, containerSize, 0, aStatus);
- if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
- // Don't pass OVERFLOW_INCOMPLETE through tables until they can actually handle it
- //XXX should paginate overflow as overflow, but not in this patch (bug 379349)
- NS_FRAME_SET_INCOMPLETE(aStatus);
- printf("Set table cell incomplete %p\n", static_cast<void*>(this));
- }
- // XXXbz is this invalidate actually needed, really?
- if (HasAnyStateBits(NS_FRAME_IS_DIRTY)) {
- InvalidateFrameSubtree();
- }
- #ifdef DEBUG
- DebugCheckChildSize(firstKid, kidSize);
- #endif
- // 0 dimensioned cells need to be treated specially in Standard/NavQuirks mode
- // see testcase "emptyCells.html"
- nsIFrame* prevInFlow = GetPrevInFlow();
- bool isEmpty;
- if (prevInFlow) {
- isEmpty = static_cast<nsTableCellFrame*>(prevInFlow)->GetContentEmpty();
- } else {
- isEmpty = !CellHasVisibleContent(kidSize.Height(), tableFrame, firstKid);
- }
- SetContentEmpty(isEmpty);
- // Place the child
- FinishReflowChild(firstKid, aPresContext, kidSize, &kidReflowInput,
- wm, kidOrigin, containerSize, 0);
- nsTableFrame::InvalidateTableFrame(firstKid, origRect, origVisualOverflow,
- firstReflow);
- // first, compute the bsize which can be set w/o being restricted by
- // available bsize
- LogicalSize cellSize(wm);
- cellSize.BSize(wm) = kidSize.BSize(wm);
- if (NS_UNCONSTRAINEDSIZE != cellSize.BSize(wm)) {
- cellSize.BSize(wm) += borderPadding.BStartEnd(wm);
- }
- // next determine the cell's isize
- cellSize.ISize(wm) = kidSize.ISize(wm); // at this point, we've factored in the cell's style attributes
- // factor in border and padding
- if (NS_UNCONSTRAINEDSIZE != cellSize.ISize(wm)) {
- cellSize.ISize(wm) += borderPadding.IStartEnd(wm);
- }
- // set the cell's desired size and max element size
- aDesiredSize.SetSize(wm, cellSize);
- // the overflow area will be computed when BlockDirAlignChild() gets called
- if (aReflowInput.mFlags.mSpecialBSizeReflow) {
- if (aDesiredSize.BSize(wm) > BSize(wm)) {
- // set a bit indicating that the pct bsize contents exceeded
- // the height that they could honor in the pass 2 reflow
- SetHasPctOverBSize(true);
- }
- if (NS_UNCONSTRAINEDSIZE == aReflowInput.AvailableBSize()) {
- aDesiredSize.BSize(wm) = BSize(wm);
- }
- }
- // If our parent is in initial reflow, it'll handle invalidating our
- // entire overflow rect.
- if (!GetParent()->HasAnyStateBits(NS_FRAME_FIRST_REFLOW) &&
- nsSize(aDesiredSize.Width(), aDesiredSize.Height()) != mRect.Size()) {
- InvalidateFrame();
- }
- // remember the desired size for this reflow
- SetDesiredSize(aDesiredSize);
- // Any absolutely-positioned children will get reflowed in
- // nsFrame::FixupPositionedTableParts in another pass, so propagate our
- // dirtiness to them before our parent clears our dirty bits.
- PushDirtyBitToAbsoluteFrames();
- NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
- }
- /* ----- global methods ----- */
- NS_QUERYFRAME_HEAD(nsTableCellFrame)
- NS_QUERYFRAME_ENTRY(nsTableCellFrame)
- NS_QUERYFRAME_ENTRY(nsITableCellLayout)
- NS_QUERYFRAME_ENTRY(nsIPercentBSizeObserver)
- NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
- #ifdef ACCESSIBILITY
- a11y::AccType
- nsTableCellFrame::AccessibleType()
- {
- return a11y::eHTMLTableCellType;
- }
- #endif
- /* This is primarily for editor access via nsITableLayout */
- NS_IMETHODIMP
- nsTableCellFrame::GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex)
- {
- aRowIndex = RowIndex();
- aColIndex = mColIndex;
- return NS_OK;
- }
- nsTableCellFrame*
- NS_NewTableCellFrame(nsIPresShell* aPresShell,
- nsStyleContext* aContext,
- nsTableFrame* aTableFrame)
- {
- if (aTableFrame->IsBorderCollapse())
- return new (aPresShell) nsBCTableCellFrame(aContext, aTableFrame);
- else
- return new (aPresShell) nsTableCellFrame(aContext, aTableFrame);
- }
- NS_IMPL_FRAMEARENA_HELPERS(nsBCTableCellFrame)
- LogicalMargin
- nsTableCellFrame::GetBorderWidth(WritingMode aWM) const
- {
- return LogicalMargin(aWM, StyleBorder()->GetComputedBorder());
- }
- nsIAtom*
- nsTableCellFrame::GetType() const
- {
- return nsGkAtoms::tableCellFrame;
- }
- #ifdef DEBUG_FRAME_DUMP
- nsresult
- nsTableCellFrame::GetFrameName(nsAString& aResult) const
- {
- return MakeFrameName(NS_LITERAL_STRING("TableCell"), aResult);
- }
- #endif
- // nsBCTableCellFrame
- nsBCTableCellFrame::nsBCTableCellFrame(nsStyleContext* aContext,
- nsTableFrame* aTableFrame)
- : nsTableCellFrame(aContext, aTableFrame)
- {
- mBStartBorder = mIEndBorder = mBEndBorder = mIStartBorder = 0;
- }
- nsBCTableCellFrame::~nsBCTableCellFrame()
- {
- }
- nsIAtom*
- nsBCTableCellFrame::GetType() const
- {
- return nsGkAtoms::bcTableCellFrame;
- }
- /* virtual */ nsMargin
- nsBCTableCellFrame::GetUsedBorder() const
- {
- WritingMode wm = GetWritingMode();
- return GetBorderWidth(wm).GetPhysicalMargin(wm);
- }
- #ifdef DEBUG_FRAME_DUMP
- nsresult
- nsBCTableCellFrame::GetFrameName(nsAString& aResult) const
- {
- return MakeFrameName(NS_LITERAL_STRING("BCTableCell"), aResult);
- }
- #endif
- LogicalMargin
- nsBCTableCellFrame::GetBorderWidth(WritingMode aWM) const
- {
- int32_t pixelsToTwips = nsPresContext::AppUnitsPerCSSPixel();
- return LogicalMargin(aWM,
- BC_BORDER_END_HALF_COORD(pixelsToTwips, mBStartBorder),
- BC_BORDER_START_HALF_COORD(pixelsToTwips, mIEndBorder),
- BC_BORDER_START_HALF_COORD(pixelsToTwips, mBEndBorder),
- BC_BORDER_END_HALF_COORD(pixelsToTwips, mIStartBorder));
- }
- BCPixelSize
- nsBCTableCellFrame::GetBorderWidth(LogicalSide aSide) const
- {
- switch(aSide) {
- case eLogicalSideBStart:
- return BC_BORDER_END_HALF(mBStartBorder);
- case eLogicalSideIEnd:
- return BC_BORDER_START_HALF(mIEndBorder);
- case eLogicalSideBEnd:
- return BC_BORDER_START_HALF(mBEndBorder);
- default:
- return BC_BORDER_END_HALF(mIStartBorder);
- }
- }
- void
- nsBCTableCellFrame::SetBorderWidth(LogicalSide aSide, BCPixelSize aValue)
- {
- switch(aSide) {
- case eLogicalSideBStart:
- mBStartBorder = aValue;
- break;
- case eLogicalSideIEnd:
- mIEndBorder = aValue;
- break;
- case eLogicalSideBEnd:
- mBEndBorder = aValue;
- break;
- default:
- mIStartBorder = aValue;
- }
- }
- /* virtual */ nsMargin
- nsBCTableCellFrame::GetBorderOverflow()
- {
- WritingMode wm = GetWritingMode();
- int32_t p2t = nsPresContext::AppUnitsPerCSSPixel();
- LogicalMargin halfBorder(wm,
- BC_BORDER_START_HALF_COORD(p2t, mBStartBorder),
- BC_BORDER_END_HALF_COORD(p2t, mIEndBorder),
- BC_BORDER_END_HALF_COORD(p2t, mBEndBorder),
- BC_BORDER_START_HALF_COORD(p2t, mIStartBorder));
- return halfBorder.GetPhysicalMargin(wm);
- }
- DrawResult
- nsBCTableCellFrame::PaintBackground(nsRenderingContext& aRenderingContext,
- const nsRect& aDirtyRect,
- nsPoint aPt,
- uint32_t aFlags)
- {
- // make border-width reflect the half of the border-collapse
- // assigned border that's inside the cell
- WritingMode wm = GetWritingMode();
- nsMargin borderWidth = GetBorderWidth(wm).GetPhysicalMargin(wm);
- nsStyleBorder myBorder(*StyleBorder());
- NS_FOR_CSS_SIDES(side) {
- myBorder.SetBorderWidth(side, borderWidth.Side(side));
- }
- // bypassing nsCSSRendering::PaintBackground is safe because this kind
- // of frame cannot be used for the root element
- nsRect rect(aPt, GetSize());
- nsCSSRendering::PaintBGParams params =
- nsCSSRendering::PaintBGParams::ForAllLayers(*PresContext(),
- aRenderingContext, aDirtyRect,
- rect, this,
- aFlags);
- return nsCSSRendering::PaintBackgroundWithSC(params, StyleContext(), myBorder);
- }
|