diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index 54f965e9d2..0bca63885b 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -1743,7 +1743,9 @@ nsCSSRendering::PaintBackground(const PaintBGParams& aParams) } static bool -IsOpaqueBorderEdge(const nsStyleBorder& aBorder, mozilla::Side aSide) +IsOpaqueBorderEdge(const nsStyleBorder& aBorder, + const nsStyleColor& aColor, + mozilla::Side aSide) { if (aBorder.GetComputedBorder().Side(aSide) == 0) return true; @@ -1765,25 +1767,20 @@ IsOpaqueBorderEdge(const nsStyleBorder& aBorder, mozilla::Side aSide) if (aBorder.mBorderImageSource.GetType() != eStyleImageType_Null) return false; - StyleComplexColor color = aBorder.mBorderColor[aSide]; - // We don't know the foreground color here, so if it's being used - // we must assume it might be transparent. - if (!color.IsNumericColor()) { - return false; - } - return NS_GET_A(color.mColor) == 255; + nscolor color = aColor.CalcComplexColor(aBorder.mBorderColor[aSide]); + return NS_GET_A(color) == 255; } /** * Returns true if all border edges are either missing or opaque. */ static bool -IsOpaqueBorder(const nsStyleBorder& aBorder) +IsOpaqueBorder(const nsStyleBorder& aBorder, const nsStyleColor& aColor) { if (aBorder.mBorderColors) return false; NS_FOR_CSS_SIDES(i) { - if (!IsOpaqueBorderEdge(aBorder, i)) + if (!IsOpaqueBorderEdge(aBorder, aColor, i)) return false; } return true; @@ -1916,7 +1913,7 @@ nsCSSRendering::GetImageLayerClip(const nsStyleImageLayers::Layer& aLayer, } bool isSolidBorder = - aWillPaintBorder && IsOpaqueBorder(aBorder); + aWillPaintBorder && IsOpaqueBorder(aBorder, *aForFrame->StyleColor()); if (isSolidBorder && layerClip == StyleGeometryBox::Border) { // If we have rounded corners, we need to inflate the background // drawing area a bit to avoid seams between the border and diff --git a/layout/reftests/border-radius/currentcolor-border-radius-ref.html b/layout/reftests/border-radius/currentcolor-border-radius-ref.html new file mode 100644 index 0000000000..94f7b98702 --- /dev/null +++ b/layout/reftests/border-radius/currentcolor-border-radius-ref.html @@ -0,0 +1,18 @@ + + + +
diff --git a/layout/reftests/border-radius/currentcolor-border-radius.html b/layout/reftests/border-radius/currentcolor-border-radius.html new file mode 100644 index 0000000000..ae93c104b9 --- /dev/null +++ b/layout/reftests/border-radius/currentcolor-border-radius.html @@ -0,0 +1,18 @@ + + + +
diff --git a/layout/reftests/border-radius/reftest.list b/layout/reftests/border-radius/reftest.list index 4b2d2f4ee6..c9de171ba0 100644 --- a/layout/reftests/border-radius/reftest.list +++ b/layout/reftests/border-radius/reftest.list @@ -89,6 +89,8 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||/^Windows\x20NT\x206\.2/.te # Test for antialiasing gaps between background and border fuzzy-if(gtkWidget,1,9) fuzzy-if(winWidget&&!d2d,1,9) fuzzy-if(d2d,5,40) fuzzy-if(skiaContent,1,9) == curved-border-background-nogap.html curved-border-background-nogap-ref.html +== currentcolor-border-radius.html currentcolor-border-radius-ref.html + == color-layer-1a.html color-layer-1-ref.html == corner-split.html corner-split-ref.svg # bug 1185636 diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index af512e2626..2657bad496 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -3312,6 +3312,66 @@ nsComputedDOMStyle::DoGetBorderRightWidth() return GetBorderWidthFor(eSideRight); } +already_AddRefed +nsComputedDOMStyle::DoGetBorderWidth() +{ + nscoord widths[4]; + if (mInnerFrame) { + AssertFlushedPendingReflows(); + const nsMargin& usedBorder = mInnerFrame->GetUsedBorder(); + NS_FOR_CSS_SIDES(side) { + widths[side] = usedBorder.Side(side); + } + } else { + const nsStyleBorder* border = StyleBorder(); + NS_FOR_CSS_SIDES(side) { + widths[side] = border->GetComputedBorderWidth(side); + } + } + + RefPtr valueList = GetROCSSValueList(false); + + RefPtr top = new nsROCSSPrimitiveValue; + top->SetAppUnits(widths[eSideTop]); + valueList->AppendCSSValue(top.forget()); + + if (widths[eSideRight] == widths[eSideLeft]) { + if (widths[eSideTop] == widths[eSideBottom]) { + if (widths[eSideTop] == widths[eSideRight]) { + return valueList.forget(); + } + + RefPtr right = new nsROCSSPrimitiveValue; + right->SetAppUnits(widths[eSideRight]); + valueList->AppendCSSValue(right.forget()); + return valueList.forget(); + } + + RefPtr right = new nsROCSSPrimitiveValue; + right->SetAppUnits(widths[eSideRight]); + valueList->AppendCSSValue(right.forget()); + + RefPtr bottom = new nsROCSSPrimitiveValue; + bottom->SetAppUnits(widths[eSideBottom]); + valueList->AppendCSSValue(bottom.forget()); + return valueList.forget(); + } + + RefPtr right = new nsROCSSPrimitiveValue; + right->SetAppUnits(widths[eSideRight]); + valueList->AppendCSSValue(right.forget()); + + RefPtr bottom = new nsROCSSPrimitiveValue; + bottom->SetAppUnits(widths[eSideBottom]); + valueList->AppendCSSValue(bottom.forget()); + + RefPtr left = new nsROCSSPrimitiveValue; + left->SetAppUnits(widths[eSideLeft]); + valueList->AppendCSSValue(left.forget()); + + return valueList.forget(); +} + already_AddRefed nsComputedDOMStyle::DoGetBorderTopColor() { @@ -6960,4 +7020,5 @@ already_AddRefed nsComputedDOMStyle::DoGetOverflowBlockEnd() { return DoGetOverflowBlock(); -} \ No newline at end of file +} + diff --git a/layout/style/nsComputedDOMStyle.h b/layout/style/nsComputedDOMStyle.h index a4c1b559a0..0715f18444 100644 --- a/layout/style/nsComputedDOMStyle.h +++ b/layout/style/nsComputedDOMStyle.h @@ -345,6 +345,7 @@ private: already_AddRefed DoGetBorderBottomWidth(); already_AddRefed DoGetBorderLeftWidth(); already_AddRefed DoGetBorderRightWidth(); + already_AddRefed DoGetBorderWidth(); already_AddRefed DoGetBorderTopColor(); already_AddRefed DoGetBorderBottomColor(); already_AddRefed DoGetBorderLeftColor(); diff --git a/layout/style/nsComputedDOMStylePropertyList.h b/layout/style/nsComputedDOMStylePropertyList.h index 50a32dccc6..b62a484376 100644 --- a/layout/style/nsComputedDOMStylePropertyList.h +++ b/layout/style/nsComputedDOMStylePropertyList.h @@ -96,7 +96,7 @@ COMPUTED_STYLE_PROP(border_top_left_radius, BorderTopLeftRadius) COMPUTED_STYLE_PROP(border_top_right_radius, BorderTopRightRadius) COMPUTED_STYLE_PROP(border_top_style, BorderTopStyle) COMPUTED_STYLE_PROP(border_top_width, BorderTopWidth) -//// COMPUTED_STYLE_PROP(border_width, BorderWidth) +COMPUTED_STYLE_PROP(border_width, BorderWidth) COMPUTED_STYLE_PROP(bottom, Bottom) COMPUTED_STYLE_PROP(box_decoration_break, BoxDecorationBreak) COMPUTED_STYLE_PROP(box_shadow, BoxShadow) diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 063e6cc10e..8721fcc6bf 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -8352,7 +8352,9 @@ nsRuleNode::ComputeOutlineData(void* aStartStruct, SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INITIAL, aContext, mPresContext, conditions)) { - outline->mOutlineOffset = tempCoord.GetCoordValue(); + outline->mOutlineOffset = + NS_ROUND_OFFSET_TO_PIXELS(tempCoord.GetCoordValue(), + mPresContext->AppUnitsPerDevPixel()); } else { NS_ASSERTION(outlineOffsetValue->GetUnit() == eCSSUnit_Null, "unexpected unit"); diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h index edecefdf08..0584f2afca 100644 --- a/layout/style/nsStyleStruct.h +++ b/layout/style/nsStyleStruct.h @@ -1148,18 +1148,16 @@ private: // Border widths are rounded to the nearest integer number of pixels, but values // between zero and one device pixels are always rounded up to one device pixel. #define NS_ROUND_BORDER_TO_PIXELS(l,tpp) \ - ((l) == 0) ? 0 : std::max((tpp), ((l) + ((tpp) / 2)) / (tpp) * (tpp)) + (((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp))) // Caret widths are rounded to the nearest-below integer number of pixels, but values // between zero and one device pixels are always rounded up to one device pixel. #define NS_ROUND_CARET_TO_PIXELS(l,tpp) \ - ((l) == 0) ? 0 : std::max((tpp), (l) / (tpp) * (tpp)) -// Outline offset is rounded to the nearest integer number of pixels, but values -// between zero and one device pixels are always rounded up to one device pixel. -// Note that the offset can be negative. + NS_ROUND_BORDER_TO_PIXELS(l,tpp) +// Outline offset is snapped like border widths, preserving the sign. #define NS_ROUND_OFFSET_TO_PIXELS(l,tpp) \ (((l) == 0) ? 0 : \ - ((l) > 0) ? std::max( (tpp), ((l) + ((tpp) / 2)) / (tpp) * (tpp)) : \ - std::min(-(tpp), ((l) - ((tpp) / 2)) / (tpp) * (tpp))) + (((l) > 0) ? NS_ROUND_BORDER_TO_PIXELS((l), (tpp)) : \ + std::min(-(tpp), (l) / (tpp) * (tpp)))) // Returns if the given border style type is visible or not static bool IsVisibleBorderStyle(uint8_t aStyle) diff --git a/layout/style/test/test_border_width_rounding.html b/layout/style/test/test_border_width_rounding.html index f7c2faabda..2de866b200 100644 --- a/layout/style/test/test_border_width_rounding.html +++ b/layout/style/test/test_border_width_rounding.html @@ -42,8 +42,37 @@ function checkWidth(property, setupProperty, setupValue) { }); } +function checkOffset(property) { + tests.forEach(function(test) { + var specified = test[0]; + var expected = test[1]; + var div = document.createElement("div"); + div.style[property] = specified; + display.appendChild(div); + + is(document.defaultView.getComputedStyle(div, "")[property], expected, + property + " computes " + specified + " as " + expected); + + display.removeChild(div); + }); + + tests.forEach(function(test) { + var specified = test[0]; + var expected = test[0] == "0px" ? "0px" : "-" + test[1]; + var div = document.createElement("div"); + div.style[property] = "-" + specified; + display.appendChild(div); + + is(document.defaultView.getComputedStyle(div, "")[property], expected, + property + " computes -" + specified + " as " + expected); + + display.removeChild(div); + }); +} + checkWidth("borderWidth", "borderStyle", "solid"); checkWidth("outlineWidth", "outlineStyle", "solid"); +checkOffset("outlineOffset");