# HG changeset patch # User Morris Tseng # Date 1516801570 18000 # Node ID 366bca651d898810d6313986d63b60dec147365e # Parent ed7b10af78e55166f99c42559de09e2eacc3de10 Bug 1393907 - Handle bevel borders. r=kats Since bevel only appear outmost border of table. I collect all bevel border and combined them as a single border with four sides. MozReview-Commit-ID: Bvu8Zf56YDF diff --git a/layout/reftests/writing-mode/tables/reftest.list b/layout/reftests/writing-mode/tables/reftest.list --- a/layout/reftests/writing-mode/tables/reftest.list +++ b/layout/reftests/writing-mode/tables/reftest.list @@ -3,17 +3,17 @@ == vertical-table-2a.html vertical-table-2-ref.html fuzzy-if(skiaContent,3,750) == vertical-table-2b.html vertical-table-2-ref.html == vertical-table-rowspan-1.html vertical-table-rowspan-1-ref.html == vertical-table-rowspan-2.html vertical-table-rowspan-2-ref.html == vertical-table-colspan-1.html vertical-table-colspan-1-ref.html == vertical-table-colspan-2.html vertical-table-colspan-2-ref.html == vertical-table-specified-width-1.html vertical-table-specified-width-1-ref.html asserts(1) == vertical-table-specified-width-2.html vertical-table-specified-width-2-ref.html # bug 1179741 -fuzzy-if(cocoaWidget,141,24) fails-if(webrender) == vertical-border-collapse-1.html vertical-border-collapse-1-ref.html # bug 1393907 for webrender +fuzzy-if(cocoaWidget,141,24) == vertical-border-collapse-1.html vertical-border-collapse-1-ref.html fuzzy-if(cocoaWidget,141,24) fails-if(webrender) == vertical-border-collapse-2.html vertical-border-collapse-2-ref.html # bug 1393907 for webrender == fixed-table-layout-002-vlr.html fixed-table-layout-002-ref.html == fixed-table-layout-003-vlr.html fixed-table-layout-002-ref.html == fixed-table-layout-004-vlr.html fixed-table-layout-004-ref.html == fixed-table-layout-005-vlr.html fixed-table-layout-005-ref.html == fixed-table-layout-006-vlr.html fixed-table-layout-006-ref.html == fixed-table-layout-007-vlr.html fixed-table-layout-007-ref.html @@ -75,19 +75,19 @@ fuzzy-if(winWidget,48,600) fuzzy-if(coco fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) == wm-row-progression-007.xht multicol-count-002-ref.xht fuzzy-if(Android,255,38) == table-caption-top-1.html table-caption-top-1-ref.html fuzzy-if(Android,255,38) == table-caption-bottom-1.html table-caption-bottom-1-ref.html fuzzy-if(Android,244,27) == table-caption-left-1.html table-caption-left-1-ref.html fuzzy-if(Android,244,27) == table-caption-right-1.html table-caption-right-1-ref.html == border-collapse-bevels-1a.html border-collapse-bevels-1-ref.html -fuzzy-if(cocoaWidget,23,162) fails-if(webrender) == border-collapse-bevels-1b.html border-collapse-bevels-1-ref.html # bug 1393907 for webrender -fuzzy-if(cocoaWidget,23,162) fails-if(webrender) == border-collapse-bevels-1c.html border-collapse-bevels-1-ref.html # bug 1393907 for webrender -fuzzy-if(cocoaWidget,23,162) fails-if(webrender) == border-collapse-bevels-1d.html border-collapse-bevels-1-ref.html # bug 1393907 for webrender -fuzzy-if(cocoaWidget,23,162) fails-if(webrender) == border-collapse-bevels-1e.html border-collapse-bevels-1-ref.html # bug 1393907 for webrender +fuzzy-if(cocoaWidget,23,162) == border-collapse-bevels-1b.html border-collapse-bevels-1-ref.html +fuzzy-if(cocoaWidget,23,162) == border-collapse-bevels-1c.html border-collapse-bevels-1-ref.html +fuzzy-if(cocoaWidget,23,162) == border-collapse-bevels-1d.html border-collapse-bevels-1-ref.html +fuzzy-if(cocoaWidget,23,162) == border-collapse-bevels-1e.html border-collapse-bevels-1-ref.html == vertical-rl-row-progression-1a.html vertical-rl-row-progression-1-ref.html == vertical-rl-row-progression-1b.html vertical-rl-row-progression-1-ref.html == sideways-lr-row-progression-1a.html sideways-lr-row-progression-1-ref.html == sideways-lr-row-progression-1b.html sideways-lr-row-progression-1-ref.html == sideways-rl-row-progression-1a.html sideways-rl-row-progression-1-ref.html == sideways-rl-row-progression-1b.html sideways-rl-row-progression-1-ref.html diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -6532,17 +6532,18 @@ struct BCBlockDirSeg BCPixelSize aInlineSegBSize); void Paint(BCPaintBorderIterator& aIter, DrawTarget& aDrawTarget, BCPixelSize aInlineSegBSize); void CreateWebRenderCommands(BCPaintBorderIterator& aIter, BCPixelSize aInlineSegBSize, wr::DisplayListBuilder& aBuilder, const layers::StackingContextHelper& aSc, - const nsPoint& aPt); + const nsPoint& aPt, + Maybe* aBevelBorders); void AdvanceOffsetB(); void IncludeCurrentBorder(BCPaintBorderIterator& aIter); union { nsTableColFrame* mCol; int32_t mColWidth; }; @@ -6586,17 +6587,18 @@ struct BCInlineDirSeg BCPixelSize aIStartSegISize); void AdvanceOffsetI(); void IncludeCurrentBorder(BCPaintBorderIterator& aIter); Maybe BuildBorderParameters(BCPaintBorderIterator& aIter); void Paint(BCPaintBorderIterator& aIter, DrawTarget& aDrawTarget); void CreateWebRenderCommands(BCPaintBorderIterator& aIter, wr::DisplayListBuilder& aBuilder, const layers::StackingContextHelper& aSc, - const nsPoint& aPt); + const nsPoint& aPt, + Maybe* aBevelBorders); nscoord mOffsetI; // i-offset with respect to the table edge nscoord mOffsetB; // b-offset with respect to the table edge nscoord mLength; // inline-dir length including corners BCPixelSize mWidth; // border thickness in pixels nscoord mIStartBevelOffset; // how much to bevel at the iStart LogicalSide mIStartBevelSide; // direction to bevel at the iStart bool mIsIEndBevel; // should we bevel at the iEnd end @@ -6633,16 +6635,17 @@ struct BCCreateWebRenderCommandsData , mSc(aSc) , mOffsetToReferenceFrame(aOffsetToReferenceFrame) { } wr::DisplayListBuilder& mBuilder; const layers::StackingContextHelper& mSc; const nsPoint& mOffsetToReferenceFrame; + Maybe mBevelBorders[4]; }; struct BCPaintBorderAction { explicit BCPaintBorderAction(DrawTarget& aDrawTarget) : mMode(Mode::PAINT) , mPaintData(aDrawTarget) { @@ -6652,16 +6655,26 @@ struct BCPaintBorderAction const layers::StackingContextHelper& aSc, const nsPoint& aOffsetToReferenceFrame) : mMode(Mode::CREATE_WEBRENDER_COMMANDS) , mCreateWebRenderCommandsData(aBuilder, aSc, aOffsetToReferenceFrame) { mMode = Mode::CREATE_WEBRENDER_COMMANDS; } + ~BCPaintBorderAction() + { + // mCreateWebRenderCommandsData is in a union which means the destructor + // wouldn't be called when BCPaintBorderAction get destroyed. So call the + // destructor here explicitly. + if (mMode == Mode::CREATE_WEBRENDER_COMMANDS) { + mCreateWebRenderCommandsData.~BCCreateWebRenderCommandsData(); + } + } + enum class Mode { PAINT, CREATE_WEBRENDER_COMMANDS, }; Mode mMode; union { @@ -7464,27 +7477,55 @@ BCBlockDirSeg::Paint(BCPaintBorderIterat param->mEndBevelSide, param->mEndBevelOffset); } void BCBlockDirSeg::CreateWebRenderCommands(BCPaintBorderIterator& aIter, BCPixelSize aInlineSegBSize, wr::DisplayListBuilder& aBuilder, const layers::StackingContextHelper& aSc, - const nsPoint& aOffset) + const nsPoint& aOffset, + Maybe* aBevelBorders) { Maybe param = BuildBorderParameters(aIter, aInlineSegBSize); if (param.isNothing()) { return; } - //TODO: Currently, we don't support border with m{Start,End}Bevel{Side,Offset} attributes. + if (param->mStartBevelOffset != 0 || param->mEndBevelOffset != 0) { + // If both bevel offsets are non zero, the parameters of two bevels should + // be the same. So we choose start bevel side here. + mozilla::Side bevelSide = param->mStartBevelOffset != 0 ? param->mStartBevelSide : param->mEndBevelSide; + + // The left border is going to be beveled on its right edge because that's + // the edge that intersects other borders (in this case the top and bottom borders). + // Correspondingly, if the bevel side is "right" that means we are operating on + // the left border, and so store the parameters for that entry in aBevelBorders. + // Same goes for the other directions. + switch (bevelSide) { + case eSideTop: + aBevelBorders[eSideBottom] = param; + break; + case eSideBottom: + aBevelBorders[eSideTop] = param; + break; + case eSideLeft: + aBevelBorders[eSideRight] = param; + break; + case eSideRight: + aBevelBorders[eSideLeft] = param; + break; + } + + return; + } LayoutDeviceRect borderRect = LayoutDeviceRect::FromUnknownRect(NSRectToRect(param->mBorderRect + aOffset, param->mAppUnitsPerDevPixel)); + wr::LayoutRect transformedRect = aSc.ToRelativeLayoutRect(borderRect); wr::BorderSide wrSide[4]; NS_FOR_CSS_SIDES(i) { wrSide[i] = wr::ToBorderSide(ToDeviceColor(param->mBorderColor), NS_STYLE_BORDER_STYLE_NONE); } wrSide[eSideLeft] = wr::ToBorderSide(ToDeviceColor(param->mBorderColor), param->mBorderStyle); wr::BorderRadius borderRadii = wr::EmptyBorderRadius(); @@ -7725,24 +7766,45 @@ BCInlineDirSeg::Paint(BCPaintBorderItera param->mStartBevelSide, param->mStartBevelOffset, param->mEndBevelSide, param->mEndBevelOffset); } void BCInlineDirSeg::CreateWebRenderCommands(BCPaintBorderIterator& aIter, wr::DisplayListBuilder& aBuilder, const layers::StackingContextHelper& aSc, - const nsPoint& aPt) + const nsPoint& aPt, + Maybe* aBevelBorders) { Maybe param = BuildBorderParameters(aIter); if (param.isNothing()) { return; } - //TODO: Currently, we don't support border with m{Start,End}Bevel{Side,Offset} attributes. + if (param->mStartBevelOffset != 0 || param->mEndBevelOffset != 0) { + mozilla::Side bevelSide = param->mStartBevelOffset != 0 ? param->mStartBevelSide : param->mEndBevelSide; + + // See detailed comment on equivalent code in BCBlockDirSeg::CreateWebRenderCommands. + switch (bevelSide) { + case eSideTop: + aBevelBorders[eSideBottom] = param; + break; + case eSideBottom: + aBevelBorders[eSideTop] = param; + break; + case eSideLeft: + aBevelBorders[eSideRight] = param; + break; + case eSideRight: + aBevelBorders[eSideLeft] = param; + break; + } + + return; + } LayoutDeviceRect borderRect = LayoutDeviceRect::FromUnknownRect(NSRectToRect(param->mBorderRect + aPt, param->mAppUnitsPerDevPixel)); wr::LayoutRect transformedRect = aSc.ToRelativeLayoutRect(borderRect); wr::BorderSide wrSide[4]; NS_FOR_CSS_SIDES(i) { wrSide[i] = wr::ToBorderSide(ToDeviceColor(param->mBorderColor), NS_STYLE_BORDER_STYLE_NONE); } @@ -7854,17 +7916,18 @@ BCPaintBorderIterator::AccumulateOrDoAct if (mInlineSeg.mWidth > 0) { if (aAction.mMode == BCPaintBorderAction::Mode::PAINT) { mInlineSeg.Paint(*this, aAction.mPaintData.mDrawTarget); } else { MOZ_ASSERT(aAction.mMode == BCPaintBorderAction::Mode::CREATE_WEBRENDER_COMMANDS); mInlineSeg.CreateWebRenderCommands(*this, aAction.mCreateWebRenderCommandsData.mBuilder, aAction.mCreateWebRenderCommandsData.mSc, - aAction.mCreateWebRenderCommandsData.mOffsetToReferenceFrame); + aAction.mCreateWebRenderCommandsData.mOffsetToReferenceFrame, + aAction.mCreateWebRenderCommandsData.mBevelBorders); } } mInlineSeg.AdvanceOffsetI(); } mInlineSeg.Start(*this, borderOwner, iStartSegISize, bStartSegBSize); } mInlineSeg.IncludeCurrentBorder(*this); mBlockDirInfo[relColIndex].mWidth = iStartSegISize; @@ -7906,17 +7969,18 @@ BCPaintBorderIterator::AccumulateOrDoAct if (aAction.mMode == BCPaintBorderAction::Mode::PAINT) { blockDirSeg.Paint(*this, aAction.mPaintData.mDrawTarget, inlineSegBSize); } else { MOZ_ASSERT(aAction.mMode == BCPaintBorderAction::Mode::CREATE_WEBRENDER_COMMANDS); blockDirSeg.CreateWebRenderCommands(*this, inlineSegBSize, aAction.mCreateWebRenderCommandsData.mBuilder, aAction.mCreateWebRenderCommandsData.mSc, - aAction.mCreateWebRenderCommandsData.mOffsetToReferenceFrame); + aAction.mCreateWebRenderCommandsData.mOffsetToReferenceFrame, + aAction.mCreateWebRenderCommandsData.mBevelBorders); } } blockDirSeg.AdvanceOffsetB(); } blockDirSeg.Start(*this, borderOwner, blockSegISize, inlineSegBSize); } blockDirSeg.IncludeCurrentBorder(*this); mPrevInlineSegBSize = inlineSegBSize; @@ -7986,16 +8050,64 @@ void nsTableFrame::CreateWebRenderCommandsForBCBorders(wr::DisplayListBuilder& aBuilder, const mozilla::layers::StackingContextHelper& aSc, const nsPoint& aOffsetToReferenceFrame) { BCPaintBorderAction action(aBuilder, aSc, aOffsetToReferenceFrame); // We always draw whole table border for webrender. Passing the table rect as // dirty rect. IterateBCBorders(action, GetRect()); + + LayoutDeviceRect allBorderRect; + wr::BorderSide wrSide[4]; + wr::BorderWidths wrWidths; + wr::BorderRadius borderRadii = wr::EmptyBorderRadius(); + bool backfaceIsVisible = false; + NS_FOR_CSS_SIDES(side) { + auto param = action.mCreateWebRenderCommandsData.mBevelBorders[side]; + LayoutDeviceRect borderRect; + nscolor borderColor = NS_RGBA(0, 0, 0, 255); + uint8_t borderStyle = NS_STYLE_BORDER_STYLE_NONE; + if (param.isSome()) { + borderRect = LayoutDeviceRect::FromUnknownRect(NSRectToRect(param->mBorderRect + aOffsetToReferenceFrame, + param->mAppUnitsPerDevPixel)); + borderColor = param->mBorderColor; + borderStyle = param->mBorderStyle; + backfaceIsVisible |= param->mBackfaceIsVisible; + } + + wr::LayoutRect transformedRect = aSc.ToRelativeLayoutRect(borderRect); + allBorderRect = allBorderRect.Union(borderRect); + wrSide[side] = wr::ToBorderSide(ToDeviceColor(borderColor), borderStyle); + switch (side) { + case eSideTop: + wrWidths.top = transformedRect.size.height; + break; + case eSideBottom: + wrWidths.bottom = transformedRect.size.height; + break; + case eSideLeft: + wrWidths.left = transformedRect.size.width; + break; + case eSideRight: + wrWidths.right = transformedRect.size.width; + break; + } + } + + if (!allBorderRect.IsEmpty()) { + Range wrsides(wrSide, 4); + wr::LayoutRect allTransformedRect = aSc.ToRelativeLayoutRect(allBorderRect); + aBuilder.PushBorder(allTransformedRect, + allTransformedRect, + backfaceIsVisible, + wrWidths, + wrsides, + borderRadii); + } } bool nsTableFrame::RowHasSpanningCells(int32_t aRowIndex, int32_t aNumEffCols) { bool result = false; nsTableCellMap* cellMap = GetCellMap(); NS_PRECONDITION (cellMap, "bad call, cellMap not yet allocated.");