mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 613659 - Implement box-decoration-break layout for border/box-shadow and paddding/margin for inlines. r=cam
This commit is contained in:
parent
1f9f1cafa0
commit
8fca6e72ff
@ -61,6 +61,19 @@ using mozilla::CSSSizeOrRatio;
|
|||||||
|
|
||||||
static int gFrameTreeLockCount = 0;
|
static int gFrameTreeLockCount = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
ApplySkipSides(int aSkipSides, nsMargin* aMargin)
|
||||||
|
{
|
||||||
|
if (aSkipSides & SIDE_BIT_LEFT)
|
||||||
|
aMargin->left = 0;
|
||||||
|
if (aSkipSides & SIDE_BIT_TOP)
|
||||||
|
aMargin->top = 0;
|
||||||
|
if (aSkipSides & SIDE_BIT_RIGHT)
|
||||||
|
aMargin->right = 0;
|
||||||
|
if (aSkipSides & SIDE_BIT_BOTTOM)
|
||||||
|
aMargin->bottom = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// To avoid storing this data on nsInlineFrame (bloat) and to avoid
|
// To avoid storing this data on nsInlineFrame (bloat) and to avoid
|
||||||
// recalculating this for each frame in a continuation (perf), hold
|
// recalculating this for each frame in a continuation (perf), hold
|
||||||
// a cache of various coordinate information that we need in order
|
// a cache of various coordinate information that we need in order
|
||||||
@ -81,10 +94,18 @@ struct InlineBackgroundData
|
|||||||
mBoundingBox.SetRect(0,0,0,0);
|
mBoundingBox.SetRect(0,0,0,0);
|
||||||
mContinuationPoint = mLineContinuationPoint = mUnbrokenWidth = 0;
|
mContinuationPoint = mLineContinuationPoint = mUnbrokenWidth = 0;
|
||||||
mFrame = mBlockFrame = nullptr;
|
mFrame = mBlockFrame = nullptr;
|
||||||
|
mLeftBorderData.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a continuous rect for (an inline) aFrame relative to the
|
||||||
|
* continuation that draws the left-most part of the background.
|
||||||
|
* This is used when painting backgrounds.
|
||||||
|
*/
|
||||||
nsRect GetContinuousRect(nsIFrame* aFrame)
|
nsRect GetContinuousRect(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
|
MOZ_ASSERT(aFrame->GetType() == nsGkAtoms::inlineFrame);
|
||||||
|
|
||||||
SetFrame(aFrame);
|
SetFrame(aFrame);
|
||||||
|
|
||||||
nscoord x;
|
nscoord x;
|
||||||
@ -98,12 +119,9 @@ struct InlineBackgroundData
|
|||||||
NS_STYLE_DIRECTION_RTL);
|
NS_STYLE_DIRECTION_RTL);
|
||||||
nscoord curOffset = aFrame->GetOffsetTo(mBlockFrame).x;
|
nscoord curOffset = aFrame->GetOffsetTo(mBlockFrame).x;
|
||||||
|
|
||||||
// No need to use our GetPrevContinuation/GetNextContinuation methods
|
|
||||||
// here, since ib-split siblings are certainly not on the same line.
|
|
||||||
|
|
||||||
nsIFrame* inlineFrame = aFrame->GetPrevContinuation();
|
|
||||||
// If the continuation is fluid we know inlineFrame is not on the same line.
|
// If the continuation is fluid we know inlineFrame is not on the same line.
|
||||||
// If it's not fluid, we need to test further to be sure.
|
// If it's not fluid, we need to test further to be sure.
|
||||||
|
nsIFrame* inlineFrame = aFrame->GetPrevContinuation();
|
||||||
while (inlineFrame && !inlineFrame->GetNextInFlow() &&
|
while (inlineFrame && !inlineFrame->GetNextInFlow() &&
|
||||||
AreOnSameLine(aFrame, inlineFrame)) {
|
AreOnSameLine(aFrame, inlineFrame)) {
|
||||||
nscoord frameXOffset = inlineFrame->GetOffsetTo(mBlockFrame).x;
|
nscoord frameXOffset = inlineFrame->GetOffsetTo(mBlockFrame).x;
|
||||||
@ -140,6 +158,39 @@ struct InlineBackgroundData
|
|||||||
return nsRect(-x, 0, mUnbrokenWidth, mFrame->GetSize().height);
|
return nsRect(-x, 0, mUnbrokenWidth, mFrame->GetSize().height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a continuous rect for (an inline) aFrame relative to the
|
||||||
|
* continuation that should draw the left-border. This is used when painting
|
||||||
|
* borders and clipping backgrounds. This may NOT be the same continuous rect
|
||||||
|
* as for drawing backgrounds; the continuation with the left-border might be
|
||||||
|
* somewhere in the middle of that rect (e.g. BIDI), in those cases we need
|
||||||
|
* the reverse background order starting at the left-border continuation.
|
||||||
|
*/
|
||||||
|
nsRect GetBorderContinuousRect(nsIFrame* aFrame, nsRect aBorderArea)
|
||||||
|
{
|
||||||
|
// Calling GetContinuousRect(aFrame) here may lead to Reset/Init which
|
||||||
|
// resets our mLeftBorderData so we save it ...
|
||||||
|
LeftBorderData saved(mLeftBorderData);
|
||||||
|
nsRect joinedBorderArea = GetContinuousRect(aFrame);
|
||||||
|
if (!saved.mIsValid || saved.mFrame != mLeftBorderData.mFrame) {
|
||||||
|
if (aFrame == mLeftBorderData.mFrame) {
|
||||||
|
mLeftBorderData.SetX(joinedBorderArea.x);
|
||||||
|
} else if (mLeftBorderData.mFrame) {
|
||||||
|
mLeftBorderData.SetX(GetContinuousRect(mLeftBorderData.mFrame).x);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// ... and restore it when possible.
|
||||||
|
mLeftBorderData.mX = saved.mX;
|
||||||
|
}
|
||||||
|
if (joinedBorderArea.x > mLeftBorderData.mX) {
|
||||||
|
joinedBorderArea.x =
|
||||||
|
-(mUnbrokenWidth + joinedBorderArea.x - aBorderArea.width);
|
||||||
|
} else {
|
||||||
|
joinedBorderArea.x -= mLeftBorderData.mX;
|
||||||
|
}
|
||||||
|
return joinedBorderArea;
|
||||||
|
}
|
||||||
|
|
||||||
nsRect GetBoundingRect(nsIFrame* aFrame)
|
nsRect GetBoundingRect(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
SetFrame(aFrame);
|
SetFrame(aFrame);
|
||||||
@ -157,12 +208,21 @@ struct InlineBackgroundData
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
struct LeftBorderData {
|
||||||
|
nsIFrame* mFrame; // the continuation that may have a left-border
|
||||||
|
nscoord mX; // cached GetContinuousRect(mFrame).x
|
||||||
|
bool mIsValid; // true if mX is valid
|
||||||
|
void Reset() { mFrame = nullptr; mIsValid = false; }
|
||||||
|
void SetX(nscoord aX) { mX = aX; mIsValid = true; }
|
||||||
|
};
|
||||||
|
|
||||||
nsIFrame* mFrame;
|
nsIFrame* mFrame;
|
||||||
nsBlockFrame* mBlockFrame;
|
nsBlockFrame* mBlockFrame;
|
||||||
nsRect mBoundingBox;
|
nsRect mBoundingBox;
|
||||||
nscoord mContinuationPoint;
|
nscoord mContinuationPoint;
|
||||||
nscoord mUnbrokenWidth;
|
nscoord mUnbrokenWidth;
|
||||||
nscoord mLineContinuationPoint;
|
nscoord mLineContinuationPoint;
|
||||||
|
LeftBorderData mLeftBorderData;
|
||||||
bool mBidiEnabled;
|
bool mBidiEnabled;
|
||||||
|
|
||||||
void SetFrame(nsIFrame* aFrame)
|
void SetFrame(nsIFrame* aFrame)
|
||||||
@ -236,6 +296,7 @@ protected:
|
|||||||
|
|
||||||
void Init(nsIFrame* aFrame)
|
void Init(nsIFrame* aFrame)
|
||||||
{
|
{
|
||||||
|
mLeftBorderData.Reset();
|
||||||
mBidiEnabled = aFrame->PresContext()->BidiEnabled();
|
mBidiEnabled = aFrame->PresContext()->BidiEnabled();
|
||||||
if (mBidiEnabled) {
|
if (mBidiEnabled) {
|
||||||
// Find the containing block frame
|
// Find the containing block frame
|
||||||
@ -252,8 +313,11 @@ protected:
|
|||||||
// Start with the previous flow frame as our continuation point
|
// Start with the previous flow frame as our continuation point
|
||||||
// is the total of the widths of the previous frames.
|
// is the total of the widths of the previous frames.
|
||||||
nsIFrame* inlineFrame = GetPrevContinuation(aFrame);
|
nsIFrame* inlineFrame = GetPrevContinuation(aFrame);
|
||||||
|
|
||||||
while (inlineFrame) {
|
while (inlineFrame) {
|
||||||
|
if (!mLeftBorderData.mFrame &&
|
||||||
|
!(inlineFrame->GetSkipSides() & SIDE_BIT_LEFT)) {
|
||||||
|
mLeftBorderData.mFrame = inlineFrame;
|
||||||
|
}
|
||||||
nsRect rect = inlineFrame->GetRect();
|
nsRect rect = inlineFrame->GetRect();
|
||||||
mContinuationPoint += rect.width;
|
mContinuationPoint += rect.width;
|
||||||
if (mBidiEnabled && !AreOnSameLine(aFrame, inlineFrame)) {
|
if (mBidiEnabled && !AreOnSameLine(aFrame, inlineFrame)) {
|
||||||
@ -268,6 +332,10 @@ protected:
|
|||||||
// unbroken width.
|
// unbroken width.
|
||||||
inlineFrame = aFrame;
|
inlineFrame = aFrame;
|
||||||
while (inlineFrame) {
|
while (inlineFrame) {
|
||||||
|
if (!mLeftBorderData.mFrame &&
|
||||||
|
!(inlineFrame->GetSkipSides() & SIDE_BIT_LEFT)) {
|
||||||
|
mLeftBorderData.mFrame = inlineFrame;
|
||||||
|
}
|
||||||
nsRect rect = inlineFrame->GetRect();
|
nsRect rect = inlineFrame->GetRect();
|
||||||
mUnbrokenWidth += rect.width;
|
mUnbrokenWidth += rect.width;
|
||||||
mBoundingBox.UnionRect(mBoundingBox, rect);
|
mBoundingBox.UnionRect(mBoundingBox, rect);
|
||||||
@ -371,6 +439,94 @@ MakeBevelColor(mozilla::css::Side whichSide, uint8_t style,
|
|||||||
return theColor;
|
return theColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
GetRadii(nsIFrame* aForFrame, const nsStyleBorder& aBorder,
|
||||||
|
const nsRect& aOrigBorderArea, const nsRect& aBorderArea,
|
||||||
|
gfxCornerSizes* aBgRadii)
|
||||||
|
{
|
||||||
|
nscoord radii[8];
|
||||||
|
bool haveRoundedCorners;
|
||||||
|
nsSize sz = aBorderArea.Size();
|
||||||
|
nsSize frameSize = aForFrame->GetSize();
|
||||||
|
if (&aBorder == aForFrame->StyleBorder() &&
|
||||||
|
frameSize == aOrigBorderArea.Size()) {
|
||||||
|
haveRoundedCorners = aForFrame->GetBorderRadii(sz, sz, 0, radii);
|
||||||
|
} else {
|
||||||
|
haveRoundedCorners =
|
||||||
|
nsIFrame::ComputeBorderRadii(aBorder.mBorderRadius, frameSize, sz, 0, radii);
|
||||||
|
}
|
||||||
|
if (haveRoundedCorners) {
|
||||||
|
auto d2a = aForFrame->PresContext()->AppUnitsPerDevPixel();
|
||||||
|
nsCSSRendering::ComputePixelRadii(radii, d2a, aBgRadii);
|
||||||
|
}
|
||||||
|
return haveRoundedCorners;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsRect
|
||||||
|
JoinBoxesForVerticalSlice(nsIFrame* aFrame, const nsRect& aBorderArea)
|
||||||
|
{
|
||||||
|
// Inflate vertically as if our continuations were laid out vertically
|
||||||
|
// adjacent. Note that we don't touch the width.
|
||||||
|
nsRect borderArea = aBorderArea;
|
||||||
|
nscoord h = 0;
|
||||||
|
nsIFrame* f = aFrame->GetNextContinuation();
|
||||||
|
for (; f; f = f->GetNextContinuation()) {
|
||||||
|
MOZ_ASSERT(!(f->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT),
|
||||||
|
"anonymous ib-split block shouldn't have border/background");
|
||||||
|
h += f->GetRect().height;
|
||||||
|
}
|
||||||
|
borderArea.height += h;
|
||||||
|
h = 0;
|
||||||
|
f = aFrame->GetPrevContinuation();
|
||||||
|
for (; f; f = f->GetPrevContinuation()) {
|
||||||
|
MOZ_ASSERT(!(f->GetStateBits() & NS_FRAME_PART_OF_IBSPLIT),
|
||||||
|
"anonymous ib-split block shouldn't have border/background");
|
||||||
|
h += f->GetRect().height;
|
||||||
|
}
|
||||||
|
borderArea.y -= h;
|
||||||
|
borderArea.height += h;
|
||||||
|
return borderArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inflate aBorderArea which is relative to aFrame's origin to calculate
|
||||||
|
* a hypothetical non-split frame area for all the continuations.
|
||||||
|
* See "Joining Boxes for 'slice'" in
|
||||||
|
* http://dev.w3.org/csswg/css-break/#break-decoration
|
||||||
|
*/
|
||||||
|
enum InlineBoxOrder { eForBorder, eForBackground };
|
||||||
|
static nsRect
|
||||||
|
JoinBoxesForSlice(nsIFrame* aFrame, const nsRect& aBorderArea,
|
||||||
|
InlineBoxOrder aOrder)
|
||||||
|
{
|
||||||
|
if (aFrame->GetType() == nsGkAtoms::inlineFrame) {
|
||||||
|
return (aOrder == eForBorder
|
||||||
|
? gInlineBGData->GetBorderContinuousRect(aFrame, aBorderArea)
|
||||||
|
: gInlineBGData->GetContinuousRect(aFrame)) +
|
||||||
|
aBorderArea.TopLeft();
|
||||||
|
}
|
||||||
|
return JoinBoxesForVerticalSlice(aFrame, aBorderArea);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
IsBoxDecorationSlice(const nsStyleBorder& aStyleBorder)
|
||||||
|
{
|
||||||
|
return aStyleBorder.mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_SLICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static nsRect
|
||||||
|
BoxDecorationRectForBorder(nsIFrame* aFrame, const nsRect& aBorderArea,
|
||||||
|
const nsStyleBorder* aStyleBorder = nullptr)
|
||||||
|
{
|
||||||
|
if (!aStyleBorder) {
|
||||||
|
aStyleBorder = aFrame->StyleBorder();
|
||||||
|
}
|
||||||
|
return ::IsBoxDecorationSlice(*aStyleBorder)
|
||||||
|
? ::JoinBoxesForSlice(aFrame, aBorderArea, eForBorder)
|
||||||
|
: aBorderArea;
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
//----------------------------------------------------------------------
|
||||||
// Thebes Border Rendering Code Start
|
// Thebes Border Rendering Code Start
|
||||||
|
|
||||||
@ -449,10 +605,6 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
|||||||
nsStyleContext* aStyleContext,
|
nsStyleContext* aStyleContext,
|
||||||
int aSkipSides)
|
int aSkipSides)
|
||||||
{
|
{
|
||||||
nsMargin border;
|
|
||||||
nscoord twipsRadii[8];
|
|
||||||
nsCompatibility compatMode = aPresContext->CompatibilityMode();
|
|
||||||
|
|
||||||
SN("++ PaintBorder");
|
SN("++ PaintBorder");
|
||||||
|
|
||||||
// Check to see if we have an appearance defined. If so, we let the theme
|
// Check to see if we have an appearance defined. If so, we let the theme
|
||||||
@ -474,59 +626,67 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
|||||||
// Get our style context's color struct.
|
// Get our style context's color struct.
|
||||||
const nsStyleColor* ourColor = aStyleContext->StyleColor();
|
const nsStyleColor* ourColor = aStyleContext->StyleColor();
|
||||||
|
|
||||||
// in NavQuirks mode we want to use the parent's context as a starting point
|
// In NavQuirks mode we want to use the parent's context as a starting point
|
||||||
// for determining the background color
|
// for determining the background color.
|
||||||
nsIFrame* bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame
|
bool quirks = aPresContext->CompatibilityMode() == eCompatibility_NavQuirks;
|
||||||
(aForFrame, compatMode == eCompatibility_NavQuirks ? true : false);
|
nsIFrame* bgFrame = FindNonTransparentBackgroundFrame(aForFrame, quirks);
|
||||||
nsStyleContext* bgContext = bgFrame->StyleContext();
|
nsStyleContext* bgContext = bgFrame->StyleContext();
|
||||||
nscolor bgColor =
|
nscolor bgColor =
|
||||||
bgContext->GetVisitedDependentColor(eCSSProperty_background_color);
|
bgContext->GetVisitedDependentColor(eCSSProperty_background_color);
|
||||||
|
|
||||||
border = aStyleBorder.GetComputedBorder();
|
nsMargin border = aStyleBorder.GetComputedBorder();
|
||||||
if ((0 == border.left) && (0 == border.right) &&
|
if ((0 == border.left) && (0 == border.right) &&
|
||||||
(0 == border.top) && (0 == border.bottom)) {
|
(0 == border.top) && (0 == border.bottom)) {
|
||||||
// Empty border area
|
// Empty border area
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsSize frameSize = aForFrame->GetSize();
|
// Compute the outermost boundary of the area that might be painted.
|
||||||
if (&aStyleBorder == aForFrame->StyleBorder() &&
|
// Same coordinate space as aBorderArea & aBGClipRect.
|
||||||
frameSize == aBorderArea.Size()) {
|
nsRect joinedBorderArea =
|
||||||
aForFrame->GetBorderRadii(twipsRadii);
|
::BoxDecorationRectForBorder(aForFrame, aBorderArea, &aStyleBorder);
|
||||||
|
gfxCornerSizes bgRadii;
|
||||||
|
::GetRadii(aForFrame, aStyleBorder, aBorderArea, joinedBorderArea, &bgRadii);
|
||||||
|
|
||||||
|
|
||||||
|
SF(" joinedBorderArea: %d %d %d %d\n", joinedBorderArea.x, joinedBorderArea.y,
|
||||||
|
joinedBorderArea.width, joinedBorderArea.height);
|
||||||
|
|
||||||
|
// start drawing
|
||||||
|
gfxContext* ctx = aRenderingContext.ThebesContext();
|
||||||
|
ctx->Save();
|
||||||
|
|
||||||
|
if (::IsBoxDecorationSlice(aStyleBorder)) {
|
||||||
|
if (aSkipSides == 0) {
|
||||||
|
// No continuations most likely, or ::first-letter that wants all border-
|
||||||
|
// sides on the first continuation.
|
||||||
|
joinedBorderArea = aBorderArea;
|
||||||
|
} else if (joinedBorderArea.IsEqualEdges(aBorderArea)) {
|
||||||
|
// No need for a clip, just skip the sides we don't want.
|
||||||
|
::ApplySkipSides(aSkipSides, &border);
|
||||||
} else {
|
} else {
|
||||||
nsIFrame::ComputeBorderRadii(aStyleBorder.mBorderRadius, frameSize,
|
// We're drawing borders around the joined continuation boxes so we need
|
||||||
aBorderArea.Size(), aSkipSides, twipsRadii);
|
// to clip that to the slice that we want for this frame.
|
||||||
|
aRenderingContext.IntersectClip(aBorderArea);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MOZ_ASSERT(joinedBorderArea.IsEqualEdges(aBorderArea),
|
||||||
|
"Should use aBorderArea for box-decoration-break:clone");
|
||||||
|
MOZ_ASSERT(aForFrame->GetSkipSides() == 0,
|
||||||
|
"Should not skip sides for box-decoration-break:clone except "
|
||||||
|
"::first-letter/line continuations or other frame types that "
|
||||||
|
"don't have borders but those shouldn't reach this point.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn off rendering for all of the zero sized sides
|
// Convert to dev pixels.
|
||||||
if (aSkipSides & SIDE_BIT_TOP) border.top = 0;
|
|
||||||
if (aSkipSides & SIDE_BIT_RIGHT) border.right = 0;
|
|
||||||
if (aSkipSides & SIDE_BIT_BOTTOM) border.bottom = 0;
|
|
||||||
if (aSkipSides & SIDE_BIT_LEFT) border.left = 0;
|
|
||||||
|
|
||||||
// get the inside and outside parts of the border
|
|
||||||
nsRect outerRect(aBorderArea);
|
|
||||||
|
|
||||||
SF(" outerRect: %d %d %d %d\n", outerRect.x, outerRect.y, outerRect.width, outerRect.height);
|
|
||||||
|
|
||||||
// we can assume that we're already clipped to aDirtyRect -- I think? (!?)
|
|
||||||
|
|
||||||
// Get our conversion values
|
|
||||||
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
||||||
|
gfxRect joinedBorderAreaPx =
|
||||||
// convert outer and inner rects
|
nsLayoutUtils::RectToGfxRect(joinedBorderArea, twipsPerPixel);
|
||||||
gfxRect oRect(nsLayoutUtils::RectToGfxRect(outerRect, twipsPerPixel));
|
|
||||||
|
|
||||||
// convert the border widths
|
|
||||||
gfxFloat borderWidths[4] = { gfxFloat(border.top / twipsPerPixel),
|
gfxFloat borderWidths[4] = { gfxFloat(border.top / twipsPerPixel),
|
||||||
gfxFloat(border.right / twipsPerPixel),
|
gfxFloat(border.right / twipsPerPixel),
|
||||||
gfxFloat(border.bottom / twipsPerPixel),
|
gfxFloat(border.bottom / twipsPerPixel),
|
||||||
gfxFloat(border.left / twipsPerPixel) };
|
gfxFloat(border.left / twipsPerPixel) };
|
||||||
|
|
||||||
// convert the radii
|
|
||||||
gfxCornerSizes borderRadii;
|
|
||||||
ComputePixelRadii(twipsRadii, twipsPerPixel, &borderRadii);
|
|
||||||
|
|
||||||
uint8_t borderStyles[4];
|
uint8_t borderStyles[4];
|
||||||
nscolor borderColors[4];
|
nscolor borderColors[4];
|
||||||
nsBorderColors *compositeColors[4];
|
nsBorderColors *compositeColors[4];
|
||||||
@ -543,32 +703,25 @@ nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
SF(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
|
SF(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
|
||||||
|
//SF ("bgRadii: %f %f %f %f\n", bgRadii[0], bgRadii[1], bgRadii[2], bgRadii[3]);
|
||||||
// start drawing
|
|
||||||
gfxContext *ctx = aRenderingContext.ThebesContext();
|
|
||||||
|
|
||||||
ctx->Save();
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// this will draw a transparent red backround underneath the oRect area
|
// this will draw a transparent red backround underneath the border area
|
||||||
ctx->Save();
|
ctx->Save();
|
||||||
ctx->Rectangle(oRect);
|
ctx->Rectangle(joinedBorderAreaPx);
|
||||||
ctx->SetColor(gfxRGBA(1.0, 0.0, 0.0, 0.5));
|
ctx->SetColor(gfxRGBA(1.0, 0.0, 0.0, 0.5));
|
||||||
ctx->Fill();
|
ctx->Fill();
|
||||||
ctx->Restore();
|
ctx->Restore();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//SF ("borderRadii: %f %f %f %f\n", borderRadii[0], borderRadii[1], borderRadii[2], borderRadii[3]);
|
|
||||||
|
|
||||||
nsCSSBorderRenderer br(twipsPerPixel,
|
nsCSSBorderRenderer br(twipsPerPixel,
|
||||||
ctx,
|
ctx,
|
||||||
oRect,
|
joinedBorderAreaPx,
|
||||||
borderStyles,
|
borderStyles,
|
||||||
borderWidths,
|
borderWidths,
|
||||||
borderRadii,
|
bgRadii,
|
||||||
borderColors,
|
borderColors,
|
||||||
compositeColors,
|
compositeColors,
|
||||||
aSkipSides,
|
|
||||||
bgColor);
|
bgColor);
|
||||||
br.DrawBorders();
|
br.DrawBorders();
|
||||||
|
|
||||||
@ -688,7 +841,7 @@ nsCSSRendering::PaintOutline(nsPresContext* aPresContext,
|
|||||||
outlineWidths,
|
outlineWidths,
|
||||||
outlineRadii,
|
outlineRadii,
|
||||||
outlineColors,
|
outlineColors,
|
||||||
nullptr, 0,
|
nullptr,
|
||||||
bgColor);
|
bgColor);
|
||||||
br.DrawBorders();
|
br.DrawBorders();
|
||||||
|
|
||||||
@ -741,7 +894,7 @@ nsCSSRendering::PaintFocus(nsPresContext* aPresContext,
|
|||||||
focusWidths,
|
focusWidths,
|
||||||
focusRadii,
|
focusRadii,
|
||||||
focusColors,
|
focusColors,
|
||||||
nullptr, 0,
|
nullptr,
|
||||||
NS_RGB(255, 0, 0));
|
NS_RGB(255, 0, 0));
|
||||||
br.DrawBorders();
|
br.DrawBorders();
|
||||||
|
|
||||||
@ -996,13 +1149,10 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
|||||||
nsCSSShadowArray* shadows = styleBorder->mBoxShadow;
|
nsCSSShadowArray* shadows = styleBorder->mBoxShadow;
|
||||||
if (!shadows)
|
if (!shadows)
|
||||||
return;
|
return;
|
||||||
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
|
||||||
|
|
||||||
|
gfxContextAutoSaveRestore gfxStateRestorer;
|
||||||
bool hasBorderRadius;
|
bool hasBorderRadius;
|
||||||
bool nativeTheme; // mutually exclusive with hasBorderRadius
|
bool nativeTheme; // mutually exclusive with hasBorderRadius
|
||||||
gfxCornerSizes borderRadii;
|
|
||||||
|
|
||||||
// Get any border radius, since box-shadow must also have rounded corners if the frame does
|
|
||||||
const nsStyleDisplay* styleDisplay = aForFrame->StyleDisplay();
|
const nsStyleDisplay* styleDisplay = aForFrame->StyleDisplay();
|
||||||
nsITheme::Transparency transparency;
|
nsITheme::Transparency transparency;
|
||||||
if (aForFrame->IsThemed(styleDisplay, &transparency)) {
|
if (aForFrame->IsThemed(styleDisplay, &transparency)) {
|
||||||
@ -1013,17 +1163,29 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
|||||||
nativeTheme = transparency != nsITheme::eOpaque;
|
nativeTheme = transparency != nsITheme::eOpaque;
|
||||||
} else {
|
} else {
|
||||||
nativeTheme = false;
|
nativeTheme = false;
|
||||||
|
hasBorderRadius = true; // we'll update this below
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRect frameRect = nativeTheme ?
|
||||||
|
aForFrame->GetVisualOverflowRectRelativeToSelf() + aFrameArea.TopLeft() :
|
||||||
|
aFrameArea;
|
||||||
|
frameRect = ::BoxDecorationRectForBorder(aForFrame, frameRect);
|
||||||
|
|
||||||
|
// Get any border radius, since box-shadow must also have rounded corners if
|
||||||
|
// the frame does.
|
||||||
|
gfxCornerSizes borderRadii;
|
||||||
|
const nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
||||||
|
if (hasBorderRadius) {
|
||||||
nscoord twipsRadii[8];
|
nscoord twipsRadii[8];
|
||||||
NS_ASSERTION(aFrameArea.Size() == aForFrame->VisualBorderRectRelativeToSelf().Size(),
|
NS_ASSERTION(aFrameArea.Size() == aForFrame->VisualBorderRectRelativeToSelf().Size(),
|
||||||
"unexpected size");
|
"unexpected size");
|
||||||
hasBorderRadius = aForFrame->GetBorderRadii(twipsRadii);
|
nsSize sz = frameRect.Size();
|
||||||
|
hasBorderRadius = aForFrame->GetBorderRadii(sz, sz, 0, twipsRadii);
|
||||||
if (hasBorderRadius) {
|
if (hasBorderRadius) {
|
||||||
ComputePixelRadii(twipsRadii, twipsPerPixel, &borderRadii);
|
ComputePixelRadii(twipsRadii, twipsPerPixel, &borderRadii);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nsRect frameRect =
|
|
||||||
nativeTheme ? aForFrame->GetVisualOverflowRectRelativeToSelf() + aFrameArea.TopLeft() : aFrameArea;
|
|
||||||
gfxRect frameGfxRect(nsLayoutUtils::RectToGfxRect(frameRect, twipsPerPixel));
|
gfxRect frameGfxRect(nsLayoutUtils::RectToGfxRect(frameRect, twipsPerPixel));
|
||||||
frameGfxRect.Round();
|
frameGfxRect.Round();
|
||||||
|
|
||||||
@ -1047,6 +1209,7 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
|||||||
std::max(borderRadii[C_BL].height, borderRadii[C_BR].height), 0));
|
std::max(borderRadii[C_BL].height, borderRadii[C_BR].height), 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int skipSides = aForFrame->GetSkipSides();
|
||||||
for (uint32_t i = shadows->Length(); i > 0; --i) {
|
for (uint32_t i = shadows->Length(); i > 0; --i) {
|
||||||
nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1);
|
nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1);
|
||||||
if (shadowItem->mInset)
|
if (shadowItem->mInset)
|
||||||
@ -1127,7 +1290,7 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
|||||||
} else {
|
} else {
|
||||||
renderContext->Save();
|
renderContext->Save();
|
||||||
// Clip out the area of the actual frame so the shadow is not shown within
|
// Clip out the area of the actual frame so the shadow is not shown within
|
||||||
// the frame
|
// the frame.
|
||||||
renderContext->NewPath();
|
renderContext->NewPath();
|
||||||
renderContext->Rectangle(shadowGfxRectPlusBlur);
|
renderContext->Rectangle(shadowGfxRectPlusBlur);
|
||||||
if (hasBorderRadius) {
|
if (hasBorderRadius) {
|
||||||
@ -1139,6 +1302,36 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
|||||||
renderContext->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
|
renderContext->SetFillRule(gfxContext::FILL_RULE_EVEN_ODD);
|
||||||
renderContext->Clip();
|
renderContext->Clip();
|
||||||
|
|
||||||
|
// Clip the shadow so that we only get the part that applies to aForFrame.
|
||||||
|
nsRect fragmentClip = shadowRectPlusBlur;
|
||||||
|
if (skipSides) {
|
||||||
|
if (skipSides & SIDE_BIT_LEFT) {
|
||||||
|
nscoord xmost = fragmentClip.XMost();
|
||||||
|
fragmentClip.x = aFrameArea.x;
|
||||||
|
fragmentClip.width = xmost - fragmentClip.x;
|
||||||
|
}
|
||||||
|
if (skipSides & SIDE_BIT_RIGHT) {
|
||||||
|
nscoord xmost = fragmentClip.XMost();
|
||||||
|
nscoord overflow = xmost - aFrameArea.XMost();
|
||||||
|
if (overflow > 0) {
|
||||||
|
fragmentClip.width -= overflow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (skipSides & SIDE_BIT_TOP) {
|
||||||
|
nscoord ymost = fragmentClip.YMost();
|
||||||
|
fragmentClip.y = aFrameArea.y;
|
||||||
|
fragmentClip.height = ymost - fragmentClip.y;
|
||||||
|
}
|
||||||
|
if (skipSides & SIDE_BIT_BOTTOM) {
|
||||||
|
nscoord ymost = fragmentClip.YMost();
|
||||||
|
nscoord overflow = ymost - aFrameArea.YMost();
|
||||||
|
if (overflow > 0) {
|
||||||
|
fragmentClip.height -= overflow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aRenderingContext.IntersectClip(fragmentClip);
|
||||||
|
|
||||||
gfxCornerSizes clipRectRadii;
|
gfxCornerSizes clipRectRadii;
|
||||||
if (hasBorderRadius) {
|
if (hasBorderRadius) {
|
||||||
gfxFloat spreadDistance = shadowItem->mSpread / twipsPerPixel;
|
gfxFloat spreadDistance = shadowItem->mSpread / twipsPerPixel;
|
||||||
@ -1188,18 +1381,20 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_ASSERTION(aForFrame->GetType() == nsGkAtoms::fieldSetFrame ||
|
||||||
|
aFrameArea.Size() == aForFrame->GetSize(), "unexpected size");
|
||||||
|
|
||||||
|
nsRect frameRect = ::BoxDecorationRectForBorder(aForFrame, aFrameArea);
|
||||||
|
nsRect paddingRect = frameRect;
|
||||||
|
nsMargin border = aForFrame->GetUsedBorder();
|
||||||
|
paddingRect.Deflate(border);
|
||||||
|
|
||||||
// Get any border radius, since box-shadow must also have rounded corners
|
// Get any border radius, since box-shadow must also have rounded corners
|
||||||
// if the frame does.
|
// if the frame does.
|
||||||
nscoord twipsRadii[8];
|
nscoord twipsRadii[8];
|
||||||
NS_ASSERTION(aForFrame->GetType() == nsGkAtoms::fieldSetFrame ||
|
nsSize sz = frameRect.Size();
|
||||||
aFrameArea.Size() == aForFrame->GetSize(), "unexpected size");
|
bool hasBorderRadius = aForFrame->GetBorderRadii(sz, sz, 0, twipsRadii);
|
||||||
bool hasBorderRadius = aForFrame->GetBorderRadii(twipsRadii);
|
const nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
||||||
nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
|
||||||
|
|
||||||
nsRect paddingRect = aFrameArea;
|
|
||||||
nsMargin border = aForFrame->GetUsedBorder();
|
|
||||||
aForFrame->ApplySkipSides(border);
|
|
||||||
paddingRect.Deflate(border);
|
|
||||||
|
|
||||||
gfxCornerSizes innerRadii;
|
gfxCornerSizes innerRadii;
|
||||||
if (hasBorderRadius) {
|
if (hasBorderRadius) {
|
||||||
@ -1221,13 +1416,9 @@ nsCSSRendering::PaintBoxShadowInner(nsPresContext* aPresContext,
|
|||||||
if (!shadowItem->mInset)
|
if (!shadowItem->mInset)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
// shadowPaintRect: the area to paint on the temp surface
|
||||||
* shadowRect: the frame's padding rect
|
// shadowClipRect: the area on the temporary surface within shadowPaintRect
|
||||||
* shadowPaintRect: the area to paint on the temp surface, larger than shadowRect
|
// that we will NOT paint in
|
||||||
* so that blurs still happen properly near the edges
|
|
||||||
* shadowClipRect: the area on the temporary surface within shadowPaintRect
|
|
||||||
* that we will NOT paint in
|
|
||||||
*/
|
|
||||||
nscoord blurRadius = shadowItem->mRadius;
|
nscoord blurRadius = shadowItem->mRadius;
|
||||||
nsMargin blurMargin =
|
nsMargin blurMargin =
|
||||||
nsContextBoxBlur::GetBlurRadiusMargin(blurRadius, twipsPerPixel);
|
nsContextBoxBlur::GetBlurRadiusMargin(blurRadius, twipsPerPixel);
|
||||||
@ -4935,10 +5126,8 @@ nsContextBoxBlur::GetBlurRadiusMargin(nscoord aBlurRadius,
|
|||||||
gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel);
|
gfxIntSize blurRadius = ComputeBlurRadius(aBlurRadius, aAppUnitsPerDevPixel);
|
||||||
|
|
||||||
nsMargin result;
|
nsMargin result;
|
||||||
result.top = blurRadius.height * aAppUnitsPerDevPixel;
|
result.top = result.bottom = blurRadius.height * aAppUnitsPerDevPixel;
|
||||||
result.right = blurRadius.width * aAppUnitsPerDevPixel;
|
result.left = result.right = blurRadius.width * aAppUnitsPerDevPixel;
|
||||||
result.bottom = blurRadius.height * aAppUnitsPerDevPixel;
|
|
||||||
result.left = blurRadius.width * aAppUnitsPerDevPixel;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,6 @@ nsCSSBorderRenderer::nsCSSBorderRenderer(int32_t aAppUnitsPerPixel,
|
|||||||
gfxCornerSizes& aBorderRadii,
|
gfxCornerSizes& aBorderRadii,
|
||||||
const nscolor* aBorderColors,
|
const nscolor* aBorderColors,
|
||||||
nsBorderColors* const* aCompositeColors,
|
nsBorderColors* const* aCompositeColors,
|
||||||
int aSkipSides,
|
|
||||||
nscolor aBackgroundColor)
|
nscolor aBackgroundColor)
|
||||||
: mContext(aDestContext),
|
: mContext(aDestContext),
|
||||||
mOuterRect(aOuterRect),
|
mOuterRect(aOuterRect),
|
||||||
@ -130,7 +129,6 @@ nsCSSBorderRenderer::nsCSSBorderRenderer(int32_t aAppUnitsPerPixel,
|
|||||||
mBorderColors(aBorderColors),
|
mBorderColors(aBorderColors),
|
||||||
mCompositeColors(aCompositeColors),
|
mCompositeColors(aCompositeColors),
|
||||||
mAUPP(aAppUnitsPerPixel),
|
mAUPP(aAppUnitsPerPixel),
|
||||||
mSkipSides(aSkipSides),
|
|
||||||
mBackgroundColor(aBackgroundColor)
|
mBackgroundColor(aBackgroundColor)
|
||||||
{
|
{
|
||||||
if (!mCompositeColors) {
|
if (!mCompositeColors) {
|
||||||
|
@ -79,7 +79,6 @@ struct nsCSSBorderRenderer {
|
|||||||
gfxCornerSizes& aBorderRadii,
|
gfxCornerSizes& aBorderRadii,
|
||||||
const nscolor* aBorderColors,
|
const nscolor* aBorderColors,
|
||||||
nsBorderColors* const* aCompositeColors,
|
nsBorderColors* const* aCompositeColors,
|
||||||
int aSkipSides,
|
|
||||||
nscolor aBackgroundColor);
|
nscolor aBackgroundColor);
|
||||||
|
|
||||||
gfxCornerSizes mBorderCornerDimensions;
|
gfxCornerSizes mBorderCornerDimensions;
|
||||||
@ -105,8 +104,7 @@ struct nsCSSBorderRenderer {
|
|||||||
// core app units per pixel
|
// core app units per pixel
|
||||||
int32_t mAUPP;
|
int32_t mAUPP;
|
||||||
|
|
||||||
// misc -- which sides to skip, the background color
|
// the background color
|
||||||
int mSkipSides;
|
|
||||||
nscolor mBackgroundColor;
|
nscolor mBackgroundColor;
|
||||||
|
|
||||||
// calculated values
|
// calculated values
|
||||||
|
@ -2839,11 +2839,8 @@ nsDisplayBoxShadowOuter::Paint(nsDisplayListBuilder* aBuilder,
|
|||||||
|
|
||||||
PROFILER_LABEL("nsDisplayBoxShadowOuter", "Paint");
|
PROFILER_LABEL("nsDisplayBoxShadowOuter", "Paint");
|
||||||
for (uint32_t i = 0; i < rects.Length(); ++i) {
|
for (uint32_t i = 0; i < rects.Length(); ++i) {
|
||||||
aCtx->PushState();
|
|
||||||
aCtx->IntersectClip(rects[i]);
|
|
||||||
nsCSSRendering::PaintBoxShadowOuter(presContext, *aCtx, mFrame,
|
nsCSSRendering::PaintBoxShadowOuter(presContext, *aCtx, mFrame,
|
||||||
borderRect, rects[i], mOpacity);
|
borderRect, rects[i], mOpacity);
|
||||||
aCtx->PopState();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,12 +849,31 @@ nsContainerFrame::DoInlineIntrinsicWidth(nsRenderingContext *aRenderingContext,
|
|||||||
// This frame is a first-in-flow, but it might have a previous bidi
|
// This frame is a first-in-flow, but it might have a previous bidi
|
||||||
// continuation, in which case that continuation should handle the startSide
|
// continuation, in which case that continuation should handle the startSide
|
||||||
// border.
|
// border.
|
||||||
|
// For box-decoration-break:clone we setup clonePBM = startPBM + endPBM and
|
||||||
|
// add that to each line. For box-decoration-break:slice clonePBM is zero.
|
||||||
|
nscoord clonePBM = 0; // PBM = PaddingBorderMargin
|
||||||
|
const bool sliceBreak =
|
||||||
|
styleBorder->mBoxDecorationBreak == NS_STYLE_BOX_DECORATION_BREAK_SLICE;
|
||||||
if (!GetPrevContinuation()) {
|
if (!GetPrevContinuation()) {
|
||||||
aData->currentLine +=
|
nscoord startPBM =
|
||||||
// clamp negative calc() to 0
|
// clamp negative calc() to 0
|
||||||
std::max(GetCoord(stylePadding->mPadding.Get(startSide), 0), 0) +
|
std::max(GetCoord(stylePadding->mPadding.Get(startSide), 0), 0) +
|
||||||
styleBorder->GetComputedBorderWidth(startSide) +
|
styleBorder->GetComputedBorderWidth(startSide) +
|
||||||
GetCoord(styleMargin->mMargin.Get(startSide), 0);
|
GetCoord(styleMargin->mMargin.Get(startSide), 0);
|
||||||
|
if (MOZ_LIKELY(sliceBreak)) {
|
||||||
|
aData->currentLine += startPBM;
|
||||||
|
} else {
|
||||||
|
clonePBM = startPBM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nscoord endPBM =
|
||||||
|
// clamp negative calc() to 0
|
||||||
|
std::max(GetCoord(stylePadding->mPadding.Get(endSide), 0), 0) +
|
||||||
|
styleBorder->GetComputedBorderWidth(endSide) +
|
||||||
|
GetCoord(styleMargin->mMargin.Get(endSide), 0);
|
||||||
|
if (MOZ_UNLIKELY(!sliceBreak)) {
|
||||||
|
clonePBM += endPBM;
|
||||||
}
|
}
|
||||||
|
|
||||||
const nsLineList_iterator* savedLine = aData->line;
|
const nsLineList_iterator* savedLine = aData->line;
|
||||||
@ -863,6 +882,9 @@ nsContainerFrame::DoInlineIntrinsicWidth(nsRenderingContext *aRenderingContext,
|
|||||||
nsContainerFrame *lastInFlow;
|
nsContainerFrame *lastInFlow;
|
||||||
for (nsContainerFrame *nif = this; nif;
|
for (nsContainerFrame *nif = this; nif;
|
||||||
nif = static_cast<nsContainerFrame*>(nif->GetNextInFlow())) {
|
nif = static_cast<nsContainerFrame*>(nif->GetNextInFlow())) {
|
||||||
|
if (aData->currentLine == 0) {
|
||||||
|
aData->currentLine = clonePBM;
|
||||||
|
}
|
||||||
for (nsIFrame *kid = nif->mFrames.FirstChild(); kid;
|
for (nsIFrame *kid = nif->mFrames.FirstChild(); kid;
|
||||||
kid = kid->GetNextSibling()) {
|
kid = kid->GetNextSibling()) {
|
||||||
if (aType == nsLayoutUtils::MIN_WIDTH)
|
if (aType == nsLayoutUtils::MIN_WIDTH)
|
||||||
@ -891,12 +913,8 @@ nsContainerFrame::DoInlineIntrinsicWidth(nsRenderingContext *aRenderingContext,
|
|||||||
// We reached the last-in-flow, but it might have a next bidi
|
// We reached the last-in-flow, but it might have a next bidi
|
||||||
// continuation, in which case that continuation should handle
|
// continuation, in which case that continuation should handle
|
||||||
// the endSide border.
|
// the endSide border.
|
||||||
if (!lastInFlow->GetNextContinuation()) {
|
if (MOZ_LIKELY(!lastInFlow->GetNextContinuation() && sliceBreak)) {
|
||||||
aData->currentLine +=
|
aData->currentLine += endPBM;
|
||||||
// clamp negative calc() to 0
|
|
||||||
std::max(GetCoord(stylePadding->mPadding.Get(endSide), 0), 0) +
|
|
||||||
styleBorder->GetComputedBorderWidth(endSide) +
|
|
||||||
GetCoord(styleMargin->mMargin.Get(endSide), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -953,6 +953,11 @@ nsIFrame::GetUsedPadding() const
|
|||||||
int
|
int
|
||||||
nsIFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsIFrame::GetSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Convert the logical skip sides to physical sides using the frame's
|
// Convert the logical skip sides to physical sides using the frame's
|
||||||
// writing mode
|
// writing mode
|
||||||
WritingMode writingMode = GetWritingMode();
|
WritingMode writingMode = GetWritingMode();
|
||||||
|
@ -1782,6 +1782,10 @@ nsImageFrame::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
|
|||||||
int
|
int
|
||||||
nsImageFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsImageFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (nullptr != GetPrevInFlow()) {
|
if (nullptr != GetPrevInFlow()) {
|
||||||
skip |= LOGICAL_SIDE_B_START;
|
skip |= LOGICAL_SIDE_B_START;
|
||||||
|
@ -115,7 +115,11 @@ nsInlineFrame::IsSelfEmpty()
|
|||||||
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetLeft()) ||
|
!nsLayoutUtils::IsPaddingZero(padding->mPadding.GetLeft()) ||
|
||||||
!IsMarginZero(margin->mMargin.GetLeft());
|
!IsMarginZero(margin->mMargin.GetLeft());
|
||||||
if (haveLeft || haveRight) {
|
if (haveLeft || haveRight) {
|
||||||
if (GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) {
|
// We skip this block and return false for box-decoration-break:clone since
|
||||||
|
// in that case all the continuations will have the border/padding/margin.
|
||||||
|
if ((GetStateBits() & NS_FRAME_PART_OF_IBSPLIT) &&
|
||||||
|
StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_SLICE) {
|
||||||
bool haveStart, haveEnd;
|
bool haveStart, haveEnd;
|
||||||
if (NS_STYLE_DIRECTION_LTR == StyleVisibility()->mDirection) {
|
if (NS_STYLE_DIRECTION_LTR == StyleVisibility()->mDirection) {
|
||||||
haveStart = haveLeft;
|
haveStart = haveLeft;
|
||||||
@ -491,9 +495,15 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
|||||||
RestyleManager* restyleManager = aPresContext->RestyleManager();
|
RestyleManager* restyleManager = aPresContext->RestyleManager();
|
||||||
WritingMode wm = aReflowState.GetWritingMode();
|
WritingMode wm = aReflowState.GetWritingMode();
|
||||||
nscoord startEdge = 0;
|
nscoord startEdge = 0;
|
||||||
|
const bool boxDecorationBreakClone =
|
||||||
|
MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE);
|
||||||
// Don't offset by our start borderpadding if we have a prev continuation or
|
// Don't offset by our start borderpadding if we have a prev continuation or
|
||||||
// if we're in a part of an {ib} split other than the first one.
|
// if we're in a part of an {ib} split other than the first one. For
|
||||||
if (!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) {
|
// box-decoration-break:clone we always offset our start since all
|
||||||
|
// continuations have border/padding.
|
||||||
|
if ((!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) ||
|
||||||
|
boxDecorationBreakClone) {
|
||||||
startEdge = aReflowState.ComputedLogicalBorderPadding().IStart(wm);
|
startEdge = aReflowState.ComputedLogicalBorderPadding().IStart(wm);
|
||||||
}
|
}
|
||||||
nscoord availableISize = aReflowState.AvailableISize();
|
nscoord availableISize = aReflowState.AvailableISize();
|
||||||
@ -654,8 +664,10 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
|||||||
|
|
||||||
// Make sure to not include our start border and padding if we have a prev
|
// Make sure to not include our start border and padding if we have a prev
|
||||||
// continuation or if we're in a part of an {ib} split other than the first
|
// continuation or if we're in a part of an {ib} split other than the first
|
||||||
// one.
|
// one. For box-decoration-break:clone we always include our start border
|
||||||
if (!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) {
|
// and padding since all continuations have them.
|
||||||
|
if ((!GetPrevContinuation() && !FrameIsNonFirstInIBSplit()) ||
|
||||||
|
boxDecorationBreakClone) {
|
||||||
aMetrics.ISize() += aReflowState.ComputedLogicalBorderPadding().IStart(wm);
|
aMetrics.ISize() += aReflowState.ComputedLogicalBorderPadding().IStart(wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -664,11 +676,13 @@ nsInlineFrame::ReflowFrames(nsPresContext* aPresContext,
|
|||||||
* continuation and either not in an {ib} split or the last part of it. To
|
* continuation and either not in an {ib} split or the last part of it. To
|
||||||
* be the last continuation we have to be complete (so that we won't get a
|
* be the last continuation we have to be complete (so that we won't get a
|
||||||
* next-in-flow) and have no non-fluid continuations on our continuation
|
* next-in-flow) and have no non-fluid continuations on our continuation
|
||||||
* chain.
|
* chain. For box-decoration-break:clone we always apply the end border and
|
||||||
|
* padding since all continuations have them.
|
||||||
*/
|
*/
|
||||||
if (NS_FRAME_IS_COMPLETE(aStatus) &&
|
if ((NS_FRAME_IS_COMPLETE(aStatus) &&
|
||||||
!LastInFlow()->GetNextContinuation() &&
|
!LastInFlow()->GetNextContinuation() &&
|
||||||
!FrameIsNonLastInIBSplit()) {
|
!FrameIsNonLastInIBSplit()) ||
|
||||||
|
boxDecorationBreakClone) {
|
||||||
aMetrics.Width() += aReflowState.ComputedLogicalBorderPadding().IEnd(wm);
|
aMetrics.Width() += aReflowState.ComputedLogicalBorderPadding().IEnd(wm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -872,6 +886,11 @@ nsInlineFrame::PushFrames(nsPresContext* aPresContext,
|
|||||||
int
|
int
|
||||||
nsInlineFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsInlineFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (!IsFirst()) {
|
if (!IsFirst()) {
|
||||||
nsInlineFrame* prev = (nsInlineFrame*) GetPrevContinuation();
|
nsInlineFrame* prev = (nsInlineFrame*) GetPrevContinuation();
|
||||||
|
@ -1076,9 +1076,12 @@ nsLineLayout::ApplyStartMargin(PerFrameData* pfd,
|
|||||||
// in an ib split. Note that the ib sibling (block-in-inline
|
// in an ib split. Note that the ib sibling (block-in-inline
|
||||||
// sibling) annotations only live on the first continuation, but we
|
// sibling) annotations only live on the first continuation, but we
|
||||||
// don't want to apply the start margin for later continuations
|
// don't want to apply the start margin for later continuations
|
||||||
// anyway.
|
// anyway. For box-decoration-break:clone we apply the start-margin
|
||||||
if (pfd->mFrame->GetPrevContinuation() ||
|
// on all continuations.
|
||||||
pfd->mFrame->FrameIsNonFirstInIBSplit()) {
|
if ((pfd->mFrame->GetPrevContinuation() ||
|
||||||
|
pfd->mFrame->FrameIsNonFirstInIBSplit()) &&
|
||||||
|
aReflowState.mStyleBorder->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_SLICE) {
|
||||||
// Zero this out so that when we compute the max-element-width of
|
// Zero this out so that when we compute the max-element-width of
|
||||||
// the frame we will properly avoid adding in the starting margin.
|
// the frame we will properly avoid adding in the starting margin.
|
||||||
pfd->mMargin.IStart(frameWM) = 0;
|
pfd->mMargin.IStart(frameWM) = 0;
|
||||||
@ -1160,6 +1163,9 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
|||||||
* 3) The frame is in an {ib} split and is not the last part.
|
* 3) The frame is in an {ib} split and is not the last part.
|
||||||
*
|
*
|
||||||
* However, none of that applies if this is a letter frame (XXXbz why?)
|
* However, none of that applies if this is a letter frame (XXXbz why?)
|
||||||
|
*
|
||||||
|
* For box-decoration-break:clone we apply the end margin on all
|
||||||
|
* continuations (that are not letter frames).
|
||||||
*/
|
*/
|
||||||
if (pfd->mFrame->GetPrevContinuation() ||
|
if (pfd->mFrame->GetPrevContinuation() ||
|
||||||
pfd->mFrame->FrameIsNonFirstInIBSplit()) {
|
pfd->mFrame->FrameIsNonFirstInIBSplit()) {
|
||||||
@ -1167,8 +1173,10 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd,
|
|||||||
}
|
}
|
||||||
if ((NS_FRAME_IS_NOT_COMPLETE(aStatus) ||
|
if ((NS_FRAME_IS_NOT_COMPLETE(aStatus) ||
|
||||||
pfd->mFrame->LastInFlow()->GetNextContinuation() ||
|
pfd->mFrame->LastInFlow()->GetNextContinuation() ||
|
||||||
pfd->mFrame->FrameIsNonLastInIBSplit())
|
pfd->mFrame->FrameIsNonLastInIBSplit()) &&
|
||||||
&& !pfd->GetFlag(PFD_ISLETTERFRAME)) {
|
!pfd->GetFlag(PFD_ISLETTERFRAME) &&
|
||||||
|
pfd->mFrame->StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_SLICE) {
|
||||||
pfd->mMargin.IEnd(frameWM) = 0;
|
pfd->mMargin.IEnd(frameWM) = 0;
|
||||||
}
|
}
|
||||||
LogicalMargin usedMargins = pfd->mMargin.ConvertTo(lineWM, frameWM);
|
LogicalMargin usedMargins = pfd->mMargin.ConvertTo(lineWM, frameWM);
|
||||||
|
@ -253,8 +253,12 @@ nsSplittableFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) co
|
|||||||
return LOGICAL_SIDES_B_BOTH;
|
return LOGICAL_SIDES_B_BOTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
int skip = 0;
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int skip = 0;
|
||||||
if (GetPrevInFlow()) {
|
if (GetPrevInFlow()) {
|
||||||
skip |= LOGICAL_SIDE_B_START;
|
skip |= LOGICAL_SIDE_B_START;
|
||||||
}
|
}
|
||||||
|
@ -550,6 +550,11 @@ nsTableCellFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
int
|
int
|
||||||
nsTableCellFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsTableCellFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (nullptr != GetPrevInFlow()) {
|
if (nullptr != GetPrevInFlow()) {
|
||||||
skip |= LOGICAL_SIDE_B_START;
|
skip |= LOGICAL_SIDE_B_START;
|
||||||
|
@ -343,6 +343,11 @@ nsTableColGroupFrame::RemoveFrame(ChildListID aListID,
|
|||||||
int
|
int
|
||||||
nsTableColGroupFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsTableColGroupFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (nullptr != GetPrevInFlow()) {
|
if (nullptr != GetPrevInFlow()) {
|
||||||
skip |= 1 << LOGICAL_SIDE_B_START;
|
skip |= 1 << LOGICAL_SIDE_B_START;
|
||||||
|
@ -1409,6 +1409,11 @@ nsTableFrame::PaintTableBorderBackground(nsRenderingContext& aRenderingContext,
|
|||||||
int
|
int
|
||||||
nsTableFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsTableFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
// frame attribute was accounted for in nsHTMLTableElement::MapTableBorderInto
|
// frame attribute was accounted for in nsHTMLTableElement::MapTableBorderInto
|
||||||
// account for pagination
|
// account for pagination
|
||||||
|
@ -605,6 +605,11 @@ nsTableRowFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
int
|
int
|
||||||
nsTableRowFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsTableRowFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (nullptr != GetPrevInFlow()) {
|
if (nullptr != GetPrevInFlow()) {
|
||||||
skip |= LOGICAL_SIDE_B_START;
|
skip |= LOGICAL_SIDE_B_START;
|
||||||
|
@ -256,6 +256,11 @@ nsTableRowGroupFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||||||
int
|
int
|
||||||
nsTableRowGroupFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
nsTableRowGroupFrame::GetLogicalSkipSides(const nsHTMLReflowState* aReflowState) const
|
||||||
{
|
{
|
||||||
|
if (MOZ_UNLIKELY(StyleBorder()->mBoxDecorationBreak ==
|
||||||
|
NS_STYLE_BOX_DECORATION_BREAK_CLONE)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int skip = 0;
|
int skip = 0;
|
||||||
if (nullptr != GetPrevInFlow()) {
|
if (nullptr != GetPrevInFlow()) {
|
||||||
skip |= LOGICAL_SIDE_B_START;
|
skip |= LOGICAL_SIDE_B_START;
|
||||||
|
Loading…
Reference in New Issue
Block a user