author | Jonathan Watt <jwatt@jwatt.org> |
Tue, 04 Nov 2014 09:53:05 +0000 | |
changeset 213912 | 562fe9b665d6dbd08feda09f4fa2702f41ae8f66 |
parent 213911 | 672874702338dcadb45e203ad6164c5a1e39e0ab |
child 213913 | 7e273cf27553be2603231218c7f12108ebd50970 |
push id | 27768 |
push user | kwierso@gmail.com |
push date | Wed, 05 Nov 2014 02:19:03 +0000 |
treeherder | mozilla-central@a1823d3c7365 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc |
bugs | 1092392 |
milestone | 36.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -733,17 +733,17 @@ nsCSSRendering::PaintBorderWithStyleBord // this will draw a transparent red backround underneath the border area ctx->Save(); ctx->Rectangle(ThebesRect(joinedBorderAreaPx)); ctx->SetColor(gfxRGBA(1.0, 0.0, 0.0, 0.5)); ctx->Fill(); ctx->Restore(); #endif - nsCSSBorderRenderer br(ctx, + nsCSSBorderRenderer br(ctx->GetDrawTarget(), joinedBorderAreaPx, borderStyles, borderWidths, bgRadii, borderColors, compositeColors, bgColor); br.DrawBorders(); @@ -868,30 +868,26 @@ nsCSSRendering::PaintOutline(nsPresConte Float outlineWidths[4] = { Float(width / twipsPerPixel), Float(width / twipsPerPixel), Float(width / twipsPerPixel), Float(width / twipsPerPixel) }; // start drawing gfxContext *ctx = aRenderingContext.ThebesContext(); - ctx->Save(); - - nsCSSBorderRenderer br(ctx, + nsCSSBorderRenderer br(ctx->GetDrawTarget(), oRect, outlineStyles, outlineWidths, outlineRadii, outlineColors, nullptr, bgColor); br.DrawBorders(); - ctx->Restore(); - PrintAsStringNewline(); } void nsCSSRendering::PaintFocus(nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, const nsRect& aFocusRect, nscolor aColor) @@ -914,36 +910,32 @@ nsCSSRendering::PaintFocus(nsPresContext uint8_t focusStyles[4] = { NS_STYLE_BORDER_STYLE_DOTTED, NS_STYLE_BORDER_STYLE_DOTTED, NS_STYLE_BORDER_STYLE_DOTTED, NS_STYLE_BORDER_STYLE_DOTTED }; nscolor focusColors[4] = { aColor, aColor, aColor, aColor }; gfxContext *ctx = aRenderingContext.ThebesContext(); - ctx->Save(); - // Because this renders a dotted border, the background color // should not be used. Therefore, we provide a value that will // be blatantly wrong if it ever does get used. (If this becomes // something that CSS can style, this function will then have access // to a style context and can use the same logic that PaintBorder // and PaintOutline do.) - nsCSSBorderRenderer br(ctx, + nsCSSBorderRenderer br(ctx->GetDrawTarget(), focusRect, focusStyles, focusWidths, focusRadii, focusColors, nullptr, NS_RGB(255, 0, 0)); br.DrawBorders(); - ctx->Restore(); - PrintAsStringNewline(); } // Thebes Border Rendering Code End //---------------------------------------------------------------------- //----------------------------------------------------------------------
--- a/layout/base/nsCSSRenderingBorders.cpp +++ b/layout/base/nsCSSRenderingBorders.cpp @@ -2,26 +2,28 @@ // vim:cindent:ts=2:et:sw=2: /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsCSSRenderingBorders.h" #include "gfxUtils.h" +#include "mozilla/ArrayUtils.h" #include "mozilla/gfx/2D.h" +#include "mozilla/gfx/Helpers.h" #include "mozilla/gfx/PathHelpers.h" +#include "nsLayoutUtils.h" #include "nsStyleConsts.h" #include "nsCSSColorUtils.h" #include "GeckoProfiler.h" #include "nsExpirationTracker.h" #include "RoundedRect.h" #include "nsClassHashtable.h" #include "nsStyleStruct.h" -#include "gfxContext.h" #include "mozilla/gfx/2D.h" #include "gfx2DGlue.h" #include "gfxGradientCache.h" #include <algorithm> using namespace mozilla; using namespace mozilla::gfx; @@ -111,26 +113,25 @@ typedef enum { // adjacent corners. CORNER_SOLID, // Paint the corner as a dot, the size of the bigger of the adjacent // sides. CORNER_DOT } CornerStyle; -nsCSSBorderRenderer::nsCSSBorderRenderer(gfxContext* aDestContext, +nsCSSBorderRenderer::nsCSSBorderRenderer(DrawTarget* aDrawTarget, Rect& aOuterRect, const uint8_t* aBorderStyles, const Float* aBorderWidths, RectCornerRadii& aBorderRadii, const nscolor* aBorderColors, nsBorderColors* const* aCompositeColors, nscolor aBackgroundColor) - : mDrawTarget(aDestContext->GetDrawTarget()), - mContext(aDestContext), + : mDrawTarget(aDrawTarget), mOuterRect(aOuterRect), mBorderStyles(aBorderStyles), mBorderWidths(aBorderWidths), mBorderRadii(aBorderRadii), mBorderColors(aBorderColors), mCompositeColors(aCompositeColors), mBackgroundColor(aBackgroundColor) { @@ -910,57 +911,57 @@ nsCSSBorderRenderer::DrawBorderSides(int soRect = siRect; } } void nsCSSBorderRenderer::DrawDashedSide(mozilla::css::Side aSide) { Float dashWidth; - gfxFloat dash[2]; + Float dash[2]; uint8_t style = mBorderStyles[aSide]; Float borderWidth = mBorderWidths[aSide]; nscolor borderColor = mBorderColors[aSide]; if (borderWidth == 0.0) return; if (style == NS_STYLE_BORDER_STYLE_NONE || style == NS_STYLE_BORDER_STYLE_HIDDEN) return; + StrokeOptions strokeOptions(borderWidth); + if (style == NS_STYLE_BORDER_STYLE_DASHED) { dashWidth = Float(borderWidth * DOT_LENGTH * DASH_LENGTH); dash[0] = dashWidth; dash[1] = dashWidth; - - mContext->SetLineCap(CapStyle::BUTT); } else if (style == NS_STYLE_BORDER_STYLE_DOTTED) { dashWidth = Float(borderWidth * DOT_LENGTH); if (borderWidth > 2.0) { dash[0] = 0.0; dash[1] = dashWidth * 2.0; - - mContext->SetLineCap(CapStyle::ROUND); + strokeOptions.mLineCap = CapStyle::ROUND; } else { dash[0] = dashWidth; dash[1] = dashWidth; } } else { PrintAsFormatString("DrawDashedSide: style: %d!!\n", style); NS_ERROR("DrawDashedSide called with style other than DASHED or DOTTED; someone's not playing nice"); return; } PrintAsFormatString("dash: %f %f\n", dash[0], dash[1]); - mContext->SetDash(dash, 2, 0.0); + strokeOptions.mDashPattern = dash; + strokeOptions.mDashLength = MOZ_ARRAY_LENGTH(dash); Point start = mOuterRect.CCWCorner(aSide); Point end = mOuterRect.CWCorner(aSide); if (aSide == NS_SIDE_TOP) { start.x += mBorderCornerDimensions[C_TL].width; end.x -= mBorderCornerDimensions[C_TR].width; @@ -981,30 +982,18 @@ nsCSSBorderRenderer::DrawDashedSide(mozi } else if (aSide == NS_SIDE_LEFT) { start.x += borderWidth / 2.0; end.x += borderWidth / 2.0; start.y -= mBorderCornerDimensions[C_BL].height; end.y += mBorderCornerDimensions[C_TL].height; } - mContext->NewPath(); - mContext->MoveTo(ThebesPoint(start)); - mContext->LineTo(ThebesPoint(end)); - mContext->SetLineWidth(borderWidth); - mContext->SetColor(gfxRGBA(borderColor)); - //mContext->SetColor(gfxRGBA(1.0, 0.0, 0.0, 1.0)); - mContext->Stroke(); -} - -void -nsCSSBorderRenderer::SetupStrokeStyle(mozilla::css::Side aSide) -{ - mContext->SetColor(gfxRGBA(mBorderColors[aSide])); - mContext->SetLineWidth(mBorderWidths[aSide]); + mDrawTarget->StrokeLine(start, end, ColorPattern(ToDeviceColor(borderColor)), + strokeOptions); } bool nsCSSBorderRenderer::AllBordersSameWidth() { if (mBorderWidths[0] == mBorderWidths[1] && mBorderWidths[0] == mBorderWidths[2] && mBorderWidths[0] == mBorderWidths[3]) @@ -1108,37 +1097,34 @@ nsCSSBorderRenderer::CreateCornerGradien } typedef struct { Float a, b; } twoFloats; void nsCSSBorderRenderer::DrawSingleWidthSolidBorder() { // Easy enough to deal with. - mContext->SetLineWidth(1); Rect rect = mOuterRect; rect.Deflate(0.5); const twoFloats cornerAdjusts[4] = { { +0.5, 0 }, { 0, +0.5 }, { -0.5, 0 }, { 0, -0.5 } }; NS_FOR_CSS_SIDES(side) { Point firstCorner = rect.CCWCorner(side); firstCorner.x += cornerAdjusts[side].a; firstCorner.y += cornerAdjusts[side].b; Point secondCorner = rect.CWCorner(side); secondCorner.x += cornerAdjusts[side].a; secondCorner.y += cornerAdjusts[side].b; - mContext->SetColor(gfxRGBA(mBorderColors[side])); - mContext->NewPath(); - mContext->MoveTo(ThebesPoint(firstCorner)); - mContext->LineTo(ThebesPoint(secondCorner)); - mContext->Stroke(); + ColorPattern color(ToDeviceColor(mBorderColors[side])); + + mDrawTarget->StrokeLine(firstCorner, secondCorner, color); } } void nsCSSBorderRenderer::DrawNoCompositeColorSolidBorder() { const Float alpha = 0.55191497064665766025f; @@ -1295,17 +1281,16 @@ nsCSSBorderRenderer::DrawNoCompositeColo } } } void nsCSSBorderRenderer::DrawRectangularCompositeColors() { nsBorderColors *currentColors[4]; - mContext->SetLineWidth(1); memcpy(currentColors, mCompositeColors, sizeof(nsBorderColors*) * 4); Rect rect = mOuterRect; rect.Deflate(0.5); const twoFloats cornerAdjusts[4] = { { +0.5, 0 }, { 0, +0.5 }, { -0.5, 0 }, { 0, -0.5 } }; @@ -1320,21 +1305,18 @@ nsCSSBorderRenderer::DrawRectangularComp Point secondCorner = rect.CWCorner(side); secondCorner.x -= cornerAdjusts[side].a; secondCorner.y -= cornerAdjusts[side].b; Color currentColor = Color::FromABGR( currentColors[side] ? currentColors[side]->mColor : mBorderColors[side]); - mContext->SetColor(ThebesColor(currentColor)); - mContext->NewPath(); - mContext->MoveTo(ThebesPoint(firstCorner)); - mContext->LineTo(ThebesPoint(secondCorner)); - mContext->Stroke(); + mDrawTarget->StrokeLine(firstCorner, secondCorner, + ColorPattern(ToDeviceColor(currentColor))); Point cornerTopLeft = rect.CWCorner(side); cornerTopLeft.x -= 0.5; cornerTopLeft.y -= 0.5; Color nextColor = Color::FromABGR( currentColors[sideNext] ? currentColors[sideNext]->mColor : mBorderColors[sideNext]); @@ -1382,32 +1364,34 @@ nsCSSBorderRenderer::DrawBorders() // All borders are the same style, and the style is either none or hidden, or the color // is transparent. // This also checks if the first composite color is transparent, and there are // no others. It doesn't check if there are subsequent transparent ones, because // that would be very silly. return; } - gfxMatrix mat = mContext->CurrentMatrix(); + AutoRestoreTransform autoRestoreTransform; + Matrix mat = mDrawTarget->GetTransform(); // Clamp the CTM to be pixel-aligned; we do this only // for translation-only matrices now, but we could do it // if the matrix has just a scale as well. We should not // do it if there's a rotation. if (mat.HasNonTranslation()) { if (!mat.HasNonAxisAlignedTransform()) { // Scale + transform. Avoid stroke fast-paths so that we have a chance // of snapping to pixel boundaries. mAvoidStroke = true; } } else { mat._31 = floor(mat._31 + 0.5); mat._32 = floor(mat._32 + 0.5); - mContext->SetMatrix(mat); + autoRestoreTransform.Init(mDrawTarget); + mDrawTarget->SetTransform(mat); // round mOuterRect and mInnerRect; they're already an integer // number of pixels apart and should stay that way after // rounding. We don't do this if there's a scale in the current transform // since this loses information that might be relevant when we're scaling. mOuterRect.Round(); mInnerRect.Round(); } @@ -1415,61 +1399,58 @@ nsCSSBorderRenderer::DrawBorders() bool allBordersSameWidth = AllBordersSameWidth(); if (allBordersSameWidth && mBorderWidths[0] == 0.0) { // Some of the allBordersSameWidth codepaths depend on the border // width being greater than zero. return; } + // Initial values only used when the border colors/widths are all the same: 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 // drawing paths, when none of these can be used we move on to the generalized // border drawing code. if (allBordersSame && mCompositeColors[0] == nullptr && allBordersSameWidth && mBorderStyles[0] == NS_STYLE_BORDER_STYLE_SOLID && mNoBorderRadius && !mAvoidStroke) { // Very simple case. - SetupStrokeStyle(NS_SIDE_TOP); Rect rect = mOuterRect; rect.Deflate(mBorderWidths[0] / 2.0); - mContext->NewPath(); - mContext->Rectangle(ThebesRect(rect)); - mContext->Stroke(); + mDrawTarget->StrokeRect(rect, color, strokeOptions); return; } if (allBordersSame && mCompositeColors[0] == nullptr && allBordersSameWidth && mBorderStyles[0] == NS_STYLE_BORDER_STYLE_DOTTED && mBorderWidths[0] < 3 && mNoBorderRadius && !mAvoidStroke) { // Very simple case. We draw this rectangular dotted borner without // antialiasing. The dots should be pixel aligned. - SetupStrokeStyle(NS_SIDE_TOP); - - gfxFloat dash = mBorderWidths[0]; - mContext->SetDash(&dash, 1, 0.5); - mContext->SetAntialiasMode(AntialiasMode::NONE); Rect rect = mOuterRect; rect.Deflate(mBorderWidths[0] / 2.0); - mContext->NewPath(); - mContext->Rectangle(ThebesRect(rect)); - mContext->Stroke(); + Float dash = mBorderWidths[0]; + strokeOptions.mDashPattern = ‐ + strokeOptions.mDashLength = 1; + strokeOptions.mDashOffset = 0.5f; + DrawOptions drawOptions; + drawOptions.mAntialiasMode = AntialiasMode::NONE; + mDrawTarget->StrokeRect(rect, color, strokeOptions); return; } if (allBordersSame && mCompositeColors[0] == nullptr && mBorderStyles[0] == NS_STYLE_BORDER_STYLE_SOLID && !mAvoidStroke && @@ -1629,20 +1610,18 @@ nsCSSBorderRenderer::DrawBorders() Color color = MakeBorderColor(mBorderColors[sides[0]], mBackgroundColor, BorderColorStyleForSolidCorner(mBorderStyles[sides[0]], corner)); mDrawTarget->FillRect(GetCornerRect(corner), ColorPattern(ToDeviceColor(color))); continue; } - mContext->Save(); - // clip to the corner - mContext->Clip(GetCornerRect(corner)); + mDrawTarget->PushClipRect(GetCornerRect(corner)); if (simpleCornerStyle) { // we don't need a group for this corner, the sides are the same, // but we weren't able to render just a solid block for the corner. DrawBorderSides(sideBits); } else { // Sides are different. We could draw using OPERATOR_ADD to // get correct color blending behaviour at the seam. We'd need @@ -1656,28 +1635,26 @@ nsCSSBorderRenderer::DrawBorders() // advantages outway the modest easthetic improvement. for (int cornerSide = 0; cornerSide < 2; cornerSide++) { mozilla::css::Side side = mozilla::css::Side(sides[cornerSide]); uint8_t style = mBorderStyles[side]; PrintAsFormatString("corner: %d cornerSide: %d side: %d style: %d\n", corner, cornerSide, side, style); - mContext->Save(); - RefPtr<Path> path = GetSideClipSubPath(side); - mContext->Clip(path); + mDrawTarget->PushClip(path); DrawBorderSides(1 << side); - mContext->Restore(); + mDrawTarget->PopClip(); } } - mContext->Restore(); + mDrawTarget->PopClip(); PrintAsStringNewline(); } // in the case of a single-unit border, we already munged the // corners up above; so we can just draw the top left and bottom // right sides separately, if they're the same. // @@ -1725,19 +1702,18 @@ nsCSSBorderRenderer::DrawBorders() // Undashed sides will currently draw the entire side, // including parts that would normally be covered by a corner, // so we need to clip. // // XXX Optimization -- it would be good to make this work like // DrawDashedSide, and have a DrawOneSide function that just // draws one side and not the corners, because then we can // avoid the potentially expensive clip. - mContext->Save(); - mContext->Clip(GetSideClipWithoutCornersRect(side)); + mDrawTarget->PushClipRect(GetSideClipWithoutCornersRect(side)); DrawBorderSides(1 << side); - mContext->Restore(); + mDrawTarget->PopClip(); PrintAsStringNewline("---------------- (*)"); } } }
--- a/layout/base/nsCSSRenderingBorders.h +++ b/layout/base/nsCSSRenderingBorders.h @@ -11,17 +11,16 @@ #include "mozilla/Attributes.h" #include "mozilla/gfx/2D.h" #include "mozilla/gfx/PathHelpers.h" #include "mozilla/RefPtr.h" #include "nsColor.h" #include "nsCOMPtr.h" #include "nsStyleConsts.h" -class gfxContext; struct nsBorderColors; namespace mozilla { namespace gfx { class GradientStops; } } @@ -42,18 +41,17 @@ class GradientStops; #define C_TL NS_CORNER_TOP_LEFT #define C_TR NS_CORNER_TOP_RIGHT #define C_BR NS_CORNER_BOTTOM_RIGHT #define C_BL NS_CORNER_BOTTOM_LEFT /* * Helper class that handles border rendering. * - * appUnitsPerPixel -- current value of AUPP - * destContext -- the gfxContext to which the border should be rendered + * aDrawTarget -- the DrawTarget to which the border should be rendered * outsideRect -- the rectangle on the outer edge of the border * * For any parameter where an array of side values is passed in, * they are in top, right, bottom, left order. * * borderStyles -- one border style enum per side * borderWidths -- one border width per side * borderRadii -- a RectCornerRadii struct describing the w/h for each rounded corner. @@ -82,17 +80,17 @@ class nsCSSBorderRenderer MOZ_FINAL typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::gfx::Float Float; typedef mozilla::gfx::Path Path; typedef mozilla::gfx::Rect Rect; typedef mozilla::gfx::RectCornerRadii RectCornerRadii; public: - nsCSSBorderRenderer(gfxContext* aDestContext, + nsCSSBorderRenderer(DrawTarget* aDrawTarget, Rect& aOuterRect, const uint8_t* aBorderStyles, const Float* aBorderWidths, RectCornerRadii& aBorderRadii, const nscolor* aBorderColors, nsBorderColors* const* aCompositeColors, nscolor aBackgroundColor); @@ -111,19 +109,18 @@ public: static void ComputeOuterRadii(const RectCornerRadii& aRadii, const Float* aBorderSizes, RectCornerRadii* aOuterRadiiRet); private: RectCornerRadii mBorderCornerDimensions; - // destination context + // destination DrawTarget DrawTarget* mDrawTarget; - gfxContext* mContext; // the rectangle of the outside and the inside of the border Rect mOuterRect; Rect mInnerRect; // the style and size of the border const uint8_t* mBorderStyles; const Float* mBorderWidths; @@ -265,32 +262,21 @@ static inline void PrintAsStringNewline( static inline void PrintAsFormatString(const char *fmt, ...) { va_list vl; va_start(vl, fmt); vfprintf (stderr, fmt, vl); va_end(vl); } -static inline void PrintGfxContext(gfxContext *ctx) { - mozilla::gfx::Point p = ctx->CurrentPoint(); - fprintf (stderr, "p: %f %f\n", p.x, p.y); - return; - ctx->MoveTo(p + Point(-2, -2)); ctx->LineTo(p + Point(2, 2)); - ctx->MoveTo(p + Point(-2, 2)); ctx->LineTo(p + Point(2, -2)); - ctx->MoveTo(p); -} - - #else static inline void PrintAsString(const mozilla::gfx::Point& p) {} static inline void PrintAsString(const mozilla::gfx::Size& s) {} static inline void PrintAsString(const mozilla::gfx::Rect& r) {} static inline void PrintAsString(const mozilla::gfx::Float f) {} static inline void PrintAsString(const char *s) {} static inline void PrintAsStringNewline(const char *s = nullptr) {} static inline void PrintAsFormatString(const char *fmt, ...) {} -static inline void PrintGfxContext(gfxContext *ctx) {} #endif } #endif /* NS_CSS_RENDERING_BORDERS_H */