From 5078f71c322e373a23ff76f4c867271f7e7a368b Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Sun, 2 Nov 2014 15:41:08 +0000 Subject: [PATCH] Bug 1091787, part 1 - Port the nsCSSRenderingBorders code that uses gfxContext::RoundedRectangle and gfxRGBA to Moz2D. r=mattwoodrow --- layout/base/nsCSSRenderingBorders.cpp | 142 +++++++++++---------- layout/base/nsCSSRenderingBorders.h | 15 ++- layout/reftests/border-radius/reftest.list | 8 +- layout/reftests/bugs/reftest.list | 6 +- layout/reftests/image-element/reftest.list | 4 +- layout/reftests/outline/reftest.list | 2 +- 6 files changed, 92 insertions(+), 85 deletions(-) diff --git a/layout/base/nsCSSRenderingBorders.cpp b/layout/base/nsCSSRenderingBorders.cpp index 38447c53f9de..7acbcdd7152e 100644 --- a/layout/base/nsCSSRenderingBorders.cpp +++ b/layout/base/nsCSSRenderingBorders.cpp @@ -60,22 +60,22 @@ static void ComputeBorderCornerDimensions(const Rect& aOuterRect, // from the given base color and the background color, turn // color into a color for the given border pattern style -static gfxRGBA MakeBorderColor(const gfxRGBA& aColor, - const gfxRGBA& aBackgroundColor, - BorderColorStyle aBorderColorStyle); +static Color MakeBorderColor(nscolor aColor, + nscolor aBackgroundColor, + BorderColorStyle aBorderColorStyle); // Given a line index (an index starting from the outside of the // border going inwards) and an array of line styles, calculate the // color that that stripe of the border should be rendered in. -static gfxRGBA ComputeColorForLine(uint32_t aLineIndex, +static Color ComputeColorForLine(uint32_t aLineIndex, const BorderColorStyle* aBorderColorStyle, uint32_t aBorderColorStyleCount, nscolor aBorderColor, nscolor aBackgroundColor); -static gfxRGBA ComputeCompositeColorForLine(uint32_t aLineIndex, - const nsBorderColors* aBorderColors); +static Color ComputeCompositeColorForLine(uint32_t aLineIndex, + const nsBorderColors* aBorderColors); // little helper function to check if the array of 4 floats given are // equal to the given value @@ -521,33 +521,36 @@ nsCSSBorderRenderer::DoSideClipSubPath(mozilla::css::Side aSide) } void -nsCSSBorderRenderer::FillSolidBorder(const gfxRect& aOuterRect, - const gfxRect& aInnerRect, +nsCSSBorderRenderer::FillSolidBorder(const Rect& aOuterRect, + const Rect& aInnerRect, const RectCornerRadii& aBorderRadii, const Float* aBorderSizes, int aSides, - const gfxRGBA& aColor) + const ColorPattern& aColor) { - mContext->SetColor(aColor); + DrawTarget* drawTarget = mContext->GetDrawTarget(); + // Note that this function is allowed to draw more than just the // requested sides. // If we have a border radius, do full rounded rectangles // and fill, regardless of what sides we're asked to draw. if (!AllCornersZeroSize(aBorderRadii)) { + RefPtr builder = + drawTarget->CreatePathBuilder(FillRule::FILL_EVEN_ODD); + RectCornerRadii innerRadii; ComputeInnerRadii(aBorderRadii, aBorderSizes, &innerRadii); - mContext->NewPath(); - // do the outer border - mContext->RoundedRectangle(aOuterRect, aBorderRadii, true); + AppendRoundedRectToPath(builder, aOuterRect, aBorderRadii, true); // then do the inner border CCW - mContext->RoundedRectangle(aInnerRect, innerRadii, false); + AppendRoundedRectToPath(builder, aInnerRect, innerRadii, false); - mContext->Fill(); + RefPtr path = builder->Finish(); + drawTarget->Fill(path, aColor); return; } @@ -560,14 +563,10 @@ nsCSSBorderRenderer::FillSolidBorder(const gfxRect& aOuterRect, CheckFourFloatsEqual(aBorderSizes, aBorderSizes[0]) && !mAvoidStroke) { - gfxRect r(aOuterRect); - r.Deflate(aBorderSizes[0] / 2.0); - mContext->SetLineWidth(aBorderSizes[0]); - - mContext->NewPath(); - mContext->Rectangle(r); - mContext->Stroke(); - + Float strokeWidth = aBorderSizes[0]; + Rect r(aOuterRect); + r.Deflate(strokeWidth / 2.f); + drawTarget->StrokeRect(r, aColor, StrokeOptions(strokeWidth)); return; } @@ -632,37 +631,37 @@ nsCSSBorderRenderer::FillSolidBorder(const gfxRect& aOuterRect, // Filling these one by one is faster than filling them all at once. for (uint32_t i = 0; i < 4; i++) { if (aSides & (1 << i)) { - mContext->NewPath(); - mContext->Rectangle(ThebesRect(r[i]), true); - mContext->Fill(); + MaybeSnapToDevicePixels(r[i], *drawTarget, true); + drawTarget->FillRect(r[i], aColor); } } } -gfxRGBA -MakeBorderColor(const gfxRGBA& aColor, const gfxRGBA& aBackgroundColor, BorderColorStyle aBorderColorStyle) +Color +MakeBorderColor(nscolor aColor, nscolor aBackgroundColor, + BorderColorStyle aBorderColorStyle) { nscolor colors[2]; int k = 0; switch (aBorderColorStyle) { case BorderColorStyleNone: - return gfxRGBA(0.0, 0.0, 0.0, 0.0); + return Color(0.f, 0.f, 0.f, 0.f); // transparent black case BorderColorStyleLight: k = 1; /* fall through */ case BorderColorStyleDark: - NS_GetSpecial3DColors(colors, aBackgroundColor.Packed(), aColor.Packed()); - return gfxRGBA(colors[k]); + NS_GetSpecial3DColors(colors, aBackgroundColor, aColor); + return Color::FromABGR(colors[k]); case BorderColorStyleSolid: default: - return aColor; + return Color::FromABGR(aColor); } } -gfxRGBA +Color ComputeColorForLine(uint32_t aLineIndex, const BorderColorStyle* aBorderColorStyle, uint32_t aBorderColorStyleCount, @@ -671,17 +670,18 @@ ComputeColorForLine(uint32_t aLineIndex, { NS_ASSERTION(aLineIndex < aBorderColorStyleCount, "Invalid lineIndex given"); - return MakeBorderColor(gfxRGBA(aBorderColor), gfxRGBA(aBackgroundColor), aBorderColorStyle[aLineIndex]); + return MakeBorderColor(aBorderColor, aBackgroundColor, + aBorderColorStyle[aLineIndex]); } -gfxRGBA +Color ComputeCompositeColorForLine(uint32_t aLineIndex, const nsBorderColors* aBorderColors) { while (aLineIndex-- && aBorderColors->mNext) aBorderColors = aBorderColors->mNext; - return gfxRGBA(aBorderColors->mColor); + return Color::FromABGR(aBorderColors->mColor); } void @@ -702,7 +702,8 @@ nsCSSBorderRenderer::DrawBorderSidesCompositeColors(int aSides, const nsBorderCo Point ibr = ToPoint(mInnerRect.BottomRight()); for (uint32_t i = 0; i < uint32_t(maxBorderWidth); i++) { - gfxRGBA lineColor = ComputeCompositeColorForLine(i, aCompositeColors); + ColorPattern color(ToDeviceColor( + ComputeCompositeColorForLine(i, aCompositeColors))); Rect siRect = soRect; siRect.Deflate(1.0); @@ -724,7 +725,7 @@ nsCSSBorderRenderer::DrawBorderSidesCompositeColors(int aSides, const nsBorderCo fakeBorderSizes[NS_SIDE_BOTTOM] = soRect.BottomRight().y - siRect.BottomRight().y; fakeBorderSizes[NS_SIDE_LEFT] = siRect.BottomLeft().x - soRect.BottomLeft().x; - FillSolidBorder(ThebesRect(soRect), ThebesRect(siRect), radii, fakeBorderSizes, aSides, lineColor); + FillSolidBorder(soRect, siRect, radii, fakeBorderSizes, aSides, color); soRect = siRect; @@ -906,11 +907,11 @@ nsCSSBorderRenderer::DrawBorderSides(int aSides) borderWidths[i][2], borderWidths[i][3])); if (borderColorStyle[i] != BorderColorStyleNone) { - gfxRGBA color = ComputeColorForLine(i, - borderColorStyle, borderColorStyleCount, - borderRenderColor, mBackgroundColor); + Color c = ComputeColorForLine(i, borderColorStyle, borderColorStyleCount, + borderRenderColor, mBackgroundColor); + ColorPattern color(ToDeviceColor(c)); - FillSolidBorder(ThebesRect(soRect), ThebesRect(siRect), radii, borderWidths[i], aSides, color); + FillSolidBorder(soRect, siRect, radii, borderWidths[i], aSides, color); } ComputeInnerRadii(radii, borderWidths[i], &radii); @@ -1055,8 +1056,8 @@ bool IsVisible(int aStyle) TemporaryRef nsCSSBorderRenderer::CreateCornerGradient(mozilla::css::Corner aCorner, - const gfxRGBA &aFirstColor, - const gfxRGBA &aSecondColor, + nscolor aFirstColor, + nscolor aSecondColor, DrawTarget *aDT, Point &aPoint1, Point &aPoint2) @@ -1088,8 +1089,8 @@ nsCSSBorderRenderer::CreateCornerGradient(mozilla::css::Corner aCorner, aPoint1 = Point(pat1.x, pat1.y); aPoint2 = Point(pat2.x, pat2.y); - Color firstColor = ToColor(aFirstColor); - Color secondColor = ToColor(aSecondColor); + Color firstColor = Color::FromABGR(aFirstColor); + Color secondColor = Color::FromABGR(aSecondColor); nsTArray rawStops(2); rawStops.SetLength(2); @@ -1334,11 +1335,11 @@ nsCSSBorderRenderer::DrawRectangularCompositeColors() secondCorner.x -= cornerAdjusts[side].a; secondCorner.y -= cornerAdjusts[side].b; - gfxRGBA currentColor = - currentColors[side] ? gfxRGBA(currentColors[side]->mColor) - : gfxRGBA(mBorderColors[side]); + Color currentColor = Color::FromABGR( + currentColors[side] ? currentColors[side]->mColor + : mBorderColors[side]); - mContext->SetColor(currentColor); + mContext->SetColor(ThebesColor(currentColor)); mContext->NewPath(); mContext->MoveTo(firstCorner); mContext->LineTo(secondCorner); @@ -1349,15 +1350,15 @@ nsCSSBorderRenderer::DrawRectangularCompositeColors() cornerTopLeft.x -= 0.5; cornerTopLeft.y -= 0.5; mContext->Rectangle(gfxRect(cornerTopLeft, gfxSize(1, 1))); - gfxRGBA nextColor = - currentColors[sideNext] ? gfxRGBA(currentColors[sideNext]->mColor) - : gfxRGBA(mBorderColors[sideNext]); + Color nextColor = Color::FromABGR( + currentColors[sideNext] ? currentColors[sideNext]->mColor + : mBorderColors[sideNext]); - gfxRGBA cornerColor((currentColor.r + nextColor.r) / 2.0, - (currentColor.g + nextColor.g) / 2.0, - (currentColor.b + nextColor.b) / 2.0, - (currentColor.a + nextColor.a) / 2.0); - mContext->SetColor(cornerColor); + Color cornerColor((currentColor.r + nextColor.r) / 2.f, + (currentColor.g + nextColor.g) / 2.f, + (currentColor.b + nextColor.b) / 2.f, + (currentColor.a + nextColor.a) / 2.f); + mContext->SetColor(ThebesColor(cornerColor)); mContext->Fill(); if (side != 0) { @@ -1378,6 +1379,8 @@ nsCSSBorderRenderer::DrawRectangularCompositeColors() void nsCSSBorderRenderer::DrawBorders() { + DrawTarget* drawTarget = mContext->GetDrawTarget(); + bool forceSeparateCorners = false; // Examine the border style to figure out if we can draw it in one @@ -1435,6 +1438,9 @@ nsCSSBorderRenderer::DrawBorders() return; } + ColorPattern color(ToDeviceColor(mBorderColors[NS_SIDE_TOP])); + StrokeOptions strokeOptions(mBorderWidths[NS_SIDE_TOP]); // stroke width + bool allBordersSolid; // First there's a couple of 'special cases' that have specifically optimized @@ -1488,8 +1494,6 @@ nsCSSBorderRenderer::DrawBorders() !mNoBorderRadius) { // Relatively simple case. - SetupStrokeStyle(NS_SIDE_TOP); - RoundedRect borderInnerRect(mOuterRect, mBorderRadii); borderInnerRect.Deflate(mBorderWidths[NS_SIDE_TOP], mBorderWidths[NS_SIDE_BOTTOM], @@ -1505,11 +1509,12 @@ nsCSSBorderRenderer::DrawBorders() // doesn't need to compute an offset curve to stroke the path. We know that // the rounded parts are elipses we can offset exactly and can just compute // a new cubic approximation. - mContext->NewPath(); - mContext->RoundedRectangle(mOuterRect, mBorderRadii, true); - mContext->RoundedRectangle(borderInnerRect.rect, borderInnerRect.corners, false); - mContext->Fill(); - return; + RefPtr builder = + drawTarget->CreatePathBuilder(FillRule::FILL_EVEN_ODD); + AppendRoundedRectToPath(builder, ToRect(mOuterRect), mBorderRadii, true); + AppendRoundedRectToPath(builder, ToRect(borderInnerRect.rect), borderInnerRect.corners, false); + RefPtr path = builder->Finish(); + drawTarget->Fill(path, color); } bool hasCompositeColors; @@ -1633,9 +1638,10 @@ nsCSSBorderRenderer::DrawBorders() { mContext->NewPath(); DoCornerSubPath(corner); - mContext->SetColor(MakeBorderColor(mBorderColors[sides[0]], - mBackgroundColor, - BorderColorStyleForSolidCorner(mBorderStyles[sides[0]], corner))); + Color color = MakeBorderColor(mBorderColors[sides[0]], + mBackgroundColor, + BorderColorStyleForSolidCorner(mBorderStyles[sides[0]], corner)); + mContext->SetColor(ThebesColor(color)); mContext->Fill(); continue; } diff --git a/layout/base/nsCSSRenderingBorders.h b/layout/base/nsCSSRenderingBorders.h index 3a59984f2dd9..93c5b7ae8f62 100644 --- a/layout/base/nsCSSRenderingBorders.h +++ b/layout/base/nsCSSRenderingBorders.h @@ -16,7 +16,6 @@ #include "nsStyleConsts.h" class gfxContext; -struct gfxRGBA; struct nsBorderColors; namespace mozilla { @@ -77,7 +76,9 @@ typedef enum { } BorderColorStyle; struct nsCSSBorderRenderer { + typedef mozilla::gfx::ColorPattern ColorPattern; typedef mozilla::gfx::Float Float; + typedef mozilla::gfx::Rect Rect; typedef mozilla::gfx::RectCornerRadii RectCornerRadii; nsCSSBorderRenderer(int32_t aAppUnitsPerPixel, @@ -162,12 +163,12 @@ struct nsCSSBorderRenderer { // // Calling code is expected to only set up a clip as necessary; no // clip is needed if we can render the entire border in 1 or 2 passes. - void FillSolidBorder(const gfxRect& aOuterRect, - const gfxRect& aInnerRect, + void FillSolidBorder(const Rect& aOuterRect, + const Rect& aInnerRect, const RectCornerRadii& aBorderRadii, - const Float *aBorderSizes, + const Float* aBorderSizes, int aSides, - const gfxRGBA& aColor); + const ColorPattern& aColor); // // core rendering @@ -196,8 +197,8 @@ struct nsCSSBorderRenderer { // Azure variant of CreateCornerGradient. mozilla::TemporaryRef - CreateCornerGradient(mozilla::css::Corner aCorner, const gfxRGBA &aFirstColor, - const gfxRGBA &aSecondColor, mozilla::gfx::DrawTarget *aDT, + CreateCornerGradient(mozilla::css::Corner aCorner, nscolor aFirstColor, + nscolor aSecondColor, mozilla::gfx::DrawTarget *aDT, mozilla::gfx::Point &aPoint1, mozilla::gfx::Point &aPoint2); // Draw a solid color border that is uniformly the same width. diff --git a/layout/reftests/border-radius/reftest.list b/layout/reftests/border-radius/reftest.list index 494038534a47..e20972f4c642 100644 --- a/layout/reftests/border-radius/reftest.list +++ b/layout/reftests/border-radius/reftest.list @@ -23,11 +23,11 @@ == percent-3.html percent-3-ref.html # more serious tests, using SVG reference -== border-circle-2.html border-circle-2-ref.xhtml +fuzzy(64,75) == border-circle-2.html border-circle-2-ref.xhtml fails == curved-stripe-border.html curved-stripe-border-ref.svg # bug 459945 # Corners -== corner-1.html corner-1-ref.svg # bottom corners different radius than top corners +fuzzy(64,58) == corner-1.html corner-1-ref.svg # bottom corners different radius than top corners random == corner-2.html corner-2-ref.svg # right corners different radius than left corners; see bug 500804 # Test that radii too long are reduced @@ -37,7 +37,7 @@ random == corner-2.html corner-2-ref.svg # right corners different radius than l fails == clipping-1.html clipping-1-ref.html # background color should completely fill box; bug 466572 != clipping-2.html about:blank # background color clipped to inner/outer border, can't get # great tests for this due to antialiasing problems described in bug 466572 -fuzzy-if(Android&&AndroidVersion<15,9,73) fuzzy-if(Android&&AndroidVersion>=15,9,200) == clipping-3.html clipping-3-ref.xhtml # edge of border-radius clips an underlying object's background +fuzzy(64,75) == clipping-3.html clipping-3-ref.xhtml # edge of border-radius clips an underlying object's background # Tests for clipping the contents of replaced elements and overflow!=visible != clipping-4-ref.html clipping-4-notref.html @@ -85,6 +85,6 @@ skip-if(B2G) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,20) fuzzy-if(A == iframe-1.html iframe-1-ref.html # Test for antialiasing gaps between background and border -skip-if(B2G) fails-if(winWidget) fuzzy-if(Android,1,5) == curved-border-background-nogap.html curved-border-background-nogap-ref.html +skip-if(B2G) fails-if(d2d) fuzzy-if(Android,1,5) == curved-border-background-nogap.html curved-border-background-nogap-ref.html == color-layer-1a.html color-layer-1-ref.html diff --git a/layout/reftests/bugs/reftest.list b/layout/reftests/bugs/reftest.list index f1c6bef29d92..213b44b4da54 100644 --- a/layout/reftests/bugs/reftest.list +++ b/layout/reftests/bugs/reftest.list @@ -1195,9 +1195,9 @@ test-pref(dom.use_xbl_scopes_for_remote_xul,true) != 449149-1b.html about:blank == 455280-1.xhtml 455280-1-ref.xhtml skip-if(B2G) fails-if(Android) == 455826-1.html 455826-1-ref.html skip-if(B2G) fails-if(cocoaWidget) fails-if(Android) == 456147.xul 456147-ref.html # bug 458047 -skip-if(B2G) fails-if(Android) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),1,1) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1a.html 456219-1-ref.html # bug 853273 -skip-if(B2G) fails-if(Android) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),1,1) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1b.html 456219-1-ref.html # bug 853273 -skip-if(B2G) fails-if(Android) fuzzy-if(/^Windows\x20NT\x206\.1/.test(http.oscpu),1,1) fuzzy-if(/^Windows\x20NT\x206\.2/.test(http.oscpu),1,69) == 456219-1c.html 456219-1-ref.html # bug 853273 +skip-if(B2G) fails-if(Android) fuzzy-if(xulRuntime.OS=="Linux",1,75) fuzzy-if(azureQuartz,1,33) fuzzy-if(winWidget&&!d2d,6,82) fuzzy-if(d2d,43,208) == 456219-1a.html 456219-1-ref.html # bug 853273 +skip-if(B2G) fails-if(Android) fuzzy-if(xulRuntime.OS=="Linux",1,75) fuzzy-if(azureQuartz,1,33) fuzzy-if(winWidget&&!d2d,6,82) fuzzy-if(d2d,43,208) == 456219-1b.html 456219-1-ref.html # bug 853273 +skip-if(B2G) fails-if(Android) fuzzy-if(xulRuntime.OS=="Linux",1,75) fuzzy-if(azureQuartz,1,33) fuzzy-if(winWidget&&!d2d,6,82) fuzzy-if(d2d,43,208) == 456219-1c.html 456219-1-ref.html # bug 853273 == 456219-2.html 456219-2-ref.html == 456330-1.gif 456330-1-ref.png == 456484-1.html 456484-1-ref.html diff --git a/layout/reftests/image-element/reftest.list b/layout/reftests/image-element/reftest.list index cc29288af9aa..d57706d1d702 100644 --- a/layout/reftests/image-element/reftest.list +++ b/layout/reftests/image-element/reftest.list @@ -13,11 +13,11 @@ skip-if(B2G) fails-if(azureSkia) fails-if(cocoaWidget) == canvas-outside-documen skip-if(B2G) HTTP(..) == element-paint-continuation.html element-paint-continuation-ref.html == element-paint-transform-01.html element-paint-transform-01-ref.html random-if(d2d) == element-paint-transform-02.html element-paint-transform-02-ref.html # bug 587133 -== element-paint-background-size-01.html element-paint-background-size-01-ref.html +fuzzy-if(d2d&&/^Windows\x20NT\x206\.1/.test(http.oscpu),16,90) == element-paint-background-size-01.html element-paint-background-size-01-ref.html == element-paint-background-size-02.html element-paint-background-size-02-ref.html == element-paint-transform-repeated.html element-paint-transform-repeated-ref.html fuzzy-if(d2d,255,24) == element-paint-transform-03.html element-paint-transform-03-ref.html -fuzzy-if(B2G,1,5) fuzzy-if(gtk2Widget,1,32) fuzzy-if(cocoaWidget,1,106) == element-paint-native-widget.html element-paint-native-widget-ref.html +fuzzy-if(B2G,1,15) fuzzy-if(gtk2Widget,1,32) fuzzy-if(cocoaWidget,1,106) == element-paint-native-widget.html element-paint-native-widget-ref.html == element-paint-subimage-sampling-restriction.html about:blank == element-paint-clippath.html element-paint-clippath-ref.html == element-paint-sharpness-01a.html element-paint-sharpness-01b.html diff --git a/layout/reftests/outline/reftest.list b/layout/reftests/outline/reftest.list index b9d33d6de872..703894ac5b05 100644 --- a/layout/reftests/outline/reftest.list +++ b/layout/reftests/outline/reftest.list @@ -1,7 +1,7 @@ == outline-and-box-shadow.html outline-and-box-shadow-ref.html == outline-and-3d-transform-1a.html outline-and-3d-transform-1-ref.html == outline-and-3d-transform-1b.html outline-and-3d-transform-1-ref.html -== outline-and-3d-transform-2.html outline-and-3d-transform-2-ref.html +fuzzy-if(d2d,16,96) == outline-and-3d-transform-2.html outline-and-3d-transform-2-ref.html == outline-overflow-block-abspos.html outline-overflow-block-ref.html == outline-overflow-block-float.html outline-overflow-block-ref.html == outline-overflow-inlineblock-abspos.html outline-overflow-inlineblock-ref.html