--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -668,24 +668,152 @@ nsCSSRendering::PaintBorder(nsPresContex
nsStyleBorder newStyleBorder(*styleBorder);
NS_FOR_CSS_SIDES(side) {
nscolor color = aStyleContext->GetVisitedDependentColor(
nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[side]);
newStyleBorder.mBorderColor[side] = StyleComplexColor::FromColor(color);
}
- DrawResult result =
- PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
- aDirtyRect, aBorderArea, newStyleBorder,
- aStyleContext, aFlags, aSkipSides);
-
- return result;
+ return PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
+ aDirtyRect, aBorderArea, newStyleBorder,
+ aStyleContext, aFlags, aSkipSides);
+}
+
+Maybe<nsCSSBorderRenderer>
+nsCSSRendering::CreateBorderRenderer(nsPresContext* aPresContext,
+ DrawTarget* aDrawTarget,
+ nsIFrame* aForFrame,
+ const nsRect& aDirtyRect,
+ const nsRect& aBorderArea,
+ nsStyleContext* aStyleContext,
+ Sides aSkipSides)
+{
+ nsStyleContext *styleIfVisited = aStyleContext->GetStyleIfVisited();
+ const nsStyleBorder *styleBorder = aStyleContext->StyleBorder();
+ // Don't check RelevantLinkVisited here, since we want to take the
+ // same amount of time whether or not it's true.
+ if (!styleIfVisited) {
+ return CreateBorderRendererWithStyleBorder(aPresContext, aDrawTarget,
+ aForFrame, aDirtyRect,
+ aBorderArea, *styleBorder,
+ aStyleContext, aSkipSides);
+ }
+
+ nsStyleBorder newStyleBorder(*styleBorder);
+
+ NS_FOR_CSS_SIDES(side) {
+ nscolor color = aStyleContext->GetVisitedDependentColor(
+ nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[side]);
+ newStyleBorder.mBorderColor[side] = StyleComplexColor::FromColor(color);
+ }
+ return CreateBorderRendererWithStyleBorder(aPresContext, aDrawTarget,
+ aForFrame, aDirtyRect, aBorderArea,
+ newStyleBorder, aStyleContext,
+ aSkipSides);
}
+nsCSSBorderRenderer
+ConstructBorderRenderer(nsPresContext* aPresContext,
+ nsStyleContext* aStyleContext,
+ DrawTarget* aDrawTarget,
+ nsIFrame* aForFrame,
+ const nsRect& aDirtyRect,
+ const nsRect& aBorderArea,
+ const nsStyleBorder& aStyleBorder,
+ Sides aSkipSides,
+ bool* aNeedsClip)
+{
+ nsMargin border = aStyleBorder.GetComputedBorder();
+
+ // Get our style context's color struct.
+ const nsStyleColor* ourColor = aStyleContext->StyleColor();
+
+ // In NavQuirks mode we want to use the parent's context as a starting point
+ // for determining the background color.
+ bool quirks = aPresContext->CompatibilityMode() == eCompatibility_NavQuirks;
+ nsIFrame* bgFrame = nsCSSRendering::FindNonTransparentBackgroundFrame(aForFrame, quirks);
+ nsStyleContext* bgContext = bgFrame->StyleContext();
+ nscolor bgColor =
+ bgContext->GetVisitedDependentColor(eCSSProperty_background_color);
+
+ // Compute the outermost boundary of the area that might be painted.
+ // Same coordinate space as aBorderArea & aBGClipRect.
+ nsRect joinedBorderArea =
+ ::BoxDecorationRectForBorder(aForFrame, aBorderArea, aSkipSides, &aStyleBorder);
+ RectCornerRadii bgRadii;
+ ::GetRadii(aForFrame, aStyleBorder, aBorderArea, joinedBorderArea, &bgRadii);
+
+ PrintAsFormatString(" joinedBorderArea: %d %d %d %d\n", joinedBorderArea.x, joinedBorderArea.y,
+ joinedBorderArea.width, joinedBorderArea.height);
+
+ // start drawing
+ if (::IsBoxDecorationSlice(aStyleBorder)) {
+ if (joinedBorderArea.IsEqualEdges(aBorderArea)) {
+ // No need for a clip, just skip the sides we don't want.
+ border.ApplySkipSides(aSkipSides);
+ } else {
+ // We're drawing borders around the joined continuation boxes so we need
+ // to clip that to the slice that we want for this frame.
+ *aNeedsClip = true;
+ }
+ } else {
+ MOZ_ASSERT(joinedBorderArea.IsEqualEdges(aBorderArea),
+ "Should use aBorderArea for box-decoration-break:clone");
+ MOZ_ASSERT(aForFrame->GetSkipSides().IsEmpty() ||
+ IS_TRUE_OVERFLOW_CONTAINER(aForFrame),
+ "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. "
+ "Overflow containers do reach this point though.");
+ border.ApplySkipSides(aSkipSides);
+ }
+
+ // Convert to dev pixels.
+ nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
+ Rect joinedBorderAreaPx = NSRectToRect(joinedBorderArea, twipsPerPixel);
+ Float borderWidths[4] = { Float(border.top / twipsPerPixel),
+ Float(border.right / twipsPerPixel),
+ Float(border.bottom / twipsPerPixel),
+ Float(border.left / twipsPerPixel) };
+ Rect dirtyRect = NSRectToRect(aDirtyRect, twipsPerPixel);
+
+ uint8_t borderStyles[4];
+ nscolor borderColors[4];
+ nsBorderColors* compositeColors[4];
+
+ // pull out styles, colors, composite colors
+ NS_FOR_CSS_SIDES (i) {
+ borderStyles[i] = aStyleBorder.GetBorderStyle(i);
+ borderColors[i] = ourColor->CalcComplexColor(aStyleBorder.mBorderColor[i]);
+ aStyleBorder.GetCompositeColors(i, &compositeColors[i]);
+ }
+
+ PrintAsFormatString(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
+
+ nsIDocument* document = nullptr;
+ nsIContent* content = aForFrame->GetContent();
+ if (content) {
+ document = content->OwnerDoc();
+ }
+
+ return nsCSSBorderRenderer(aPresContext,
+ document,
+ aDrawTarget,
+ dirtyRect,
+ joinedBorderAreaPx,
+ borderStyles,
+ borderWidths,
+ bgRadii,
+ borderColors,
+ compositeColors,
+ bgColor);
+}
+
+
DrawResult
nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
const nsStyleBorder& aStyleBorder,
nsStyleContext* aStyleContext,
@@ -719,129 +847,99 @@ nsCSSRendering::PaintBorderWithStyleBord
// If we had a border-image, but it wasn't loaded, then we should return
// DrawResult::NOT_READY; we'll want to try again if we do a paint with sync
// decoding enabled.
if (aStyleBorder.mBorderImageSource.GetType() != eStyleImageType_Null) {
result = DrawResult::NOT_READY;
}
- // Get our style context's color struct.
- const nsStyleColor* ourColor = aStyleContext->StyleColor();
-
- // In NavQuirks mode we want to use the parent's context as a starting point
- // for determining the background color.
- bool quirks = aPresContext->CompatibilityMode() == eCompatibility_NavQuirks;
- nsIFrame* bgFrame = FindNonTransparentBackgroundFrame(aForFrame, quirks);
- nsStyleContext* bgContext = bgFrame->StyleContext();
- nscolor bgColor =
- bgContext->GetVisitedDependentColor(eCSSProperty_background_color);
-
nsMargin border = aStyleBorder.GetComputedBorder();
if (0 == border.left && 0 == border.right &&
0 == border.top && 0 == border.bottom) {
// Empty border area
return result;
}
- // Compute the outermost boundary of the area that might be painted.
- // Same coordinate space as aBorderArea & aBGClipRect.
- nsRect joinedBorderArea =
- ::BoxDecorationRectForBorder(aForFrame, aBorderArea, aSkipSides, &aStyleBorder);
- RectCornerRadii bgRadii;
- ::GetRadii(aForFrame, aStyleBorder, aBorderArea, joinedBorderArea, &bgRadii);
-
- PrintAsFormatString(" joinedBorderArea: %d %d %d %d\n", joinedBorderArea.x, joinedBorderArea.y,
- joinedBorderArea.width, joinedBorderArea.height);
-
- // start drawing
- bool needToPopClip = false;
-
- if (::IsBoxDecorationSlice(aStyleBorder)) {
- if (joinedBorderArea.IsEqualEdges(aBorderArea)) {
- // No need for a clip, just skip the sides we don't want.
- border.ApplySkipSides(aSkipSides);
- } else {
- // We're drawing borders around the joined continuation boxes so we need
- // to clip that to the slice that we want for this frame.
- aDrawTarget.PushClipRect(
+ bool needsClip = false;
+ nsCSSBorderRenderer br = ConstructBorderRenderer(aPresContext,
+ aStyleContext,
+ &aDrawTarget,
+ aForFrame,
+ aDirtyRect,
+ aBorderArea,
+ aStyleBorder,
+ aSkipSides,
+ &needsClip);
+
+ if (needsClip) {
+ aDrawTarget.PushClipRect(
NSRectToSnappedRect(aBorderArea,
aForFrame->PresContext()->AppUnitsPerDevPixel(),
aDrawTarget));
- needToPopClip = true;
- }
- } else {
- MOZ_ASSERT(joinedBorderArea.IsEqualEdges(aBorderArea),
- "Should use aBorderArea for box-decoration-break:clone");
- MOZ_ASSERT(aForFrame->GetSkipSides().IsEmpty() ||
- IS_TRUE_OVERFLOW_CONTAINER(aForFrame),
- "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. "
- "Overflow containers do reach this point though.");
- border.ApplySkipSides(aSkipSides);
- }
-
- // Convert to dev pixels.
- nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
- Rect joinedBorderAreaPx = NSRectToRect(joinedBorderArea, twipsPerPixel);
- Float borderWidths[4] = { Float(border.top / twipsPerPixel),
- Float(border.right / twipsPerPixel),
- Float(border.bottom / twipsPerPixel),
- Float(border.left / twipsPerPixel) };
- Rect dirtyRect = NSRectToRect(aDirtyRect, twipsPerPixel);
-
- uint8_t borderStyles[4];
- nscolor borderColors[4];
- nsBorderColors *compositeColors[4];
-
- // pull out styles, colors, composite colors
- NS_FOR_CSS_SIDES (i) {
- borderStyles[i] = aStyleBorder.GetBorderStyle(i);
- borderColors[i] = ourColor->CalcComplexColor(aStyleBorder.mBorderColor[i]);
- aStyleBorder.GetCompositeColors(i, &compositeColors[i]);
- }
-
- PrintAsFormatString(" borderStyles: %d %d %d %d\n", borderStyles[0], borderStyles[1], borderStyles[2], borderStyles[3]);
- //PrintAsFormatString ("bgRadii: %f %f %f %f\n", bgRadii[0], bgRadii[1], bgRadii[2], bgRadii[3]);
-
-#if 0
- // this will draw a transparent red backround underneath the border area
- ColorPattern color(ToDeviceColor(Color(1.f, 0.f, 0.f, 0.5f)));
- aDrawTarget.FillRect(joinedBorderAreaPx, color);
-#endif
-
- nsIDocument* document = nullptr;
- nsIContent* content = aForFrame->GetContent();
- if (content) {
- document = content->OwnerDoc();
- }
-
- nsCSSBorderRenderer br(aPresContext,
- document,
- &aDrawTarget,
- dirtyRect,
- joinedBorderAreaPx,
- borderStyles,
- borderWidths,
- bgRadii,
- borderColors,
- compositeColors,
- bgColor);
+ }
+
br.DrawBorders();
- if (needToPopClip) {
+ if (needsClip) {
aDrawTarget.PopClip();
}
PrintAsStringNewline();
return result;
}
+Maybe<nsCSSBorderRenderer>
+nsCSSRendering::CreateBorderRendererWithStyleBorder(nsPresContext* aPresContext,
+ DrawTarget* aDrawTarget,
+ nsIFrame* aForFrame,
+ const nsRect& aDirtyRect,
+ const nsRect& aBorderArea,
+ const nsStyleBorder& aStyleBorder,
+ nsStyleContext* aStyleContext,
+ Sides aSkipSides)
+{
+ const nsStyleDisplay* displayData = aStyleContext->StyleDisplay();
+ if (displayData->mAppearance) {
+ nsITheme *theme = aPresContext->GetTheme();
+ if (theme &&
+ theme->ThemeSupportsWidget(aPresContext, aForFrame,
+ displayData->mAppearance)) {
+ return Nothing();
+ }
+ }
+
+ if (aStyleBorder.mBorderImageSource.GetType() != eStyleImageType_Null) {
+ return Nothing();
+ }
+
+ nsMargin border = aStyleBorder.GetComputedBorder();
+ if (0 == border.left && 0 == border.right &&
+ 0 == border.top && 0 == border.bottom) {
+ // Empty border area
+ return Nothing();
+ }
+
+ bool needsClip = false;
+ nsCSSBorderRenderer br = ConstructBorderRenderer(aPresContext,
+ aStyleContext,
+ aDrawTarget,
+ aForFrame,
+ aDirtyRect,
+ aBorderArea,
+ aStyleBorder,
+ aSkipSides,
+ &needsClip);
+ if (needsClip) {
+ return Nothing();
+ }
+ return Some(br);
+}
+
static nsRect
GetOutlineInnerRect(nsIFrame* aFrame)
{
nsRect* savedOutlineInnerRect =
aFrame->Properties().Get(nsIFrame::OutlineInnerRectProperty());
if (savedOutlineInnerRect)
return *savedOutlineInnerRect;
NS_NOTREACHED("we should have saved a frame property");
--- a/layout/painting/nsCSSRendering.h
+++ b/layout/painting/nsCSSRendering.h
@@ -12,16 +12,17 @@
#include "gfxContext.h"
#include "imgIContainer.h"
#include "mozilla/gfx/PathHelpers.h"
#include "mozilla/gfx/Rect.h"
#include "mozilla/TypedEnumBits.h"
#include "nsLayoutUtils.h"
#include "nsStyleStruct.h"
#include "nsIFrame.h"
+#include "nsCSSRenderingBorders.h"
class gfxDrawable;
class nsStyleContext;
class nsPresContext;
class nsRenderingContext;
namespace mozilla {
@@ -411,16 +412,35 @@ struct nsCSSRendering {
nsIFrame* aForFrame,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
const nsStyleBorder& aBorderStyle,
nsStyleContext* aStyleContext,
mozilla::PaintBorderFlags aFlags,
Sides aSkipSides = Sides());
+ static mozilla::Maybe<nsCSSBorderRenderer>
+ CreateBorderRenderer(nsPresContext* aPresContext,
+ DrawTarget* aDrawTarget,
+ nsIFrame* aForFrame,
+ const nsRect& aDirtyRect,
+ const nsRect& aBorderArea,
+ nsStyleContext* aStyleContext,
+ Sides aSkipSides = Sides());
+
+ static mozilla::Maybe<nsCSSBorderRenderer>
+ CreateBorderRendererWithStyleBorder(nsPresContext* aPresContext,
+ DrawTarget* aDrawTarget,
+ nsIFrame* aForFrame,
+ const nsRect& aDirtyRect,
+ const nsRect& aBorderArea,
+ const nsStyleBorder& aBorderStyle,
+ nsStyleContext* aStyleContext,
+ Sides aSkipSides = Sides());
+
/**
* Render the outline for an element using css rendering rules
* for borders.
*/
static void PaintOutline(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
nsIFrame* aForFrame,
--- a/layout/painting/nsCSSRenderingBorders.cpp
+++ b/layout/painting/nsCSSRenderingBorders.cpp
@@ -101,18 +101,18 @@ CheckFourFloatsEqual(const Float *vals,
vals[3] == k);
}
static bool
IsZeroSize(const Size& sz) {
return sz.width == 0.0 || sz.height == 0.0;
}
-static bool
-AllCornersZeroSize(const RectCornerRadii& corners) {
+/* static */ bool
+nsCSSBorderRenderer::AllCornersZeroSize(const RectCornerRadii& corners) {
return IsZeroSize(corners[NS_CORNER_TOP_LEFT]) &&
IsZeroSize(corners[NS_CORNER_TOP_RIGHT]) &&
IsZeroSize(corners[NS_CORNER_BOTTOM_RIGHT]) &&
IsZeroSize(corners[NS_CORNER_BOTTOM_LEFT]);
}
static mozilla::css::Side
GetHorizontalSide(mozilla::css::Corner aCorner)
@@ -177,26 +177,27 @@ nsCSSBorderRenderer::nsCSSBorderRenderer
const nscolor* aBorderColors,
nsBorderColors* const* aCompositeColors,
nscolor aBackgroundColor)
: mPresContext(aPresContext),
mDocument(aDocument),
mDrawTarget(aDrawTarget),
mDirtyRect(aDirtyRect),
mOuterRect(aOuterRect),
- mBorderStyles(aBorderStyles),
- mBorderWidths(aBorderWidths),
mBorderRadii(aBorderRadii),
- mBorderColors(aBorderColors),
- mCompositeColors(aCompositeColors),
mBackgroundColor(aBackgroundColor)
{
- if (!mCompositeColors) {
+ PodCopy(mBorderStyles, aBorderStyles, 4);
+ PodCopy(mBorderWidths, aBorderWidths, 4);
+ PodCopy(mBorderColors, aBorderColors, 4);
+ if (aCompositeColors) {
+ PodCopy(mCompositeColors, aCompositeColors, 4);
+ } else {
static nsBorderColors * const noColors[4] = { nullptr };
- mCompositeColors = &noColors[0];
+ PodCopy(mCompositeColors, noColors, 4);
}
mInnerRect = mOuterRect;
mInnerRect.Deflate(
Margin(mBorderStyles[0] != NS_STYLE_BORDER_STYLE_NONE ? mBorderWidths[0] : 0,
mBorderStyles[1] != NS_STYLE_BORDER_STYLE_NONE ? mBorderWidths[1] : 0,
mBorderStyles[2] != NS_STYLE_BORDER_STYLE_NONE ? mBorderWidths[2] : 0,
mBorderStyles[3] != NS_STYLE_BORDER_STYLE_NONE ? mBorderWidths[3] : 0));
@@ -266,17 +267,17 @@ ComputeBorderCornerDimensions(const Floa
const RectCornerRadii& aRadii,
RectCornerRadii* aDimsRet)
{
Float leftWidth = aBorderWidths[NS_SIDE_LEFT];
Float topWidth = aBorderWidths[NS_SIDE_TOP];
Float rightWidth = aBorderWidths[NS_SIDE_RIGHT];
Float bottomWidth = aBorderWidths[NS_SIDE_BOTTOM];
- if (AllCornersZeroSize(aRadii)) {
+ if (nsCSSBorderRenderer::AllCornersZeroSize(aRadii)) {
// These will always be in pixel units from CSS
(*aDimsRet)[C_TL] = Size(leftWidth, topWidth);
(*aDimsRet)[C_TR] = Size(rightWidth, topWidth);
(*aDimsRet)[C_BR] = Size(rightWidth, bottomWidth);
(*aDimsRet)[C_BL] = Size(leftWidth, bottomWidth);
} else {
// Always round up to whole pixels for the corners; it's safe to
// make the corners bigger than necessary, and this way we ensure