mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1090614 - Make nsCSSRendering::PaintBoxShadowOuter construct a Moz2D Path to do its clipping. r=mattwoodrow
This commit is contained in:
parent
6a77b8e610
commit
8466e5627a
@ -13,6 +13,7 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/Helpers.h"
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "mozilla/MathAlgorithms.h"
|
||||
|
||||
@ -577,6 +578,25 @@ nsCSSRendering::ComputePixelRadii(const nscoord *aAppUnitsRadii,
|
||||
radii[NS_CORNER_BOTTOM_LEFT_Y]);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsCSSRendering::ComputePixelRadii(const nscoord *aAppUnitsRadii,
|
||||
nscoord aAppUnitsPerPixel,
|
||||
RectCornerRadii *oBorderRadii)
|
||||
{
|
||||
Float radii[8];
|
||||
NS_FOR_CSS_HALF_CORNERS(corner)
|
||||
radii[corner] = Float(aAppUnitsRadii[corner]) / aAppUnitsPerPixel;
|
||||
|
||||
(*oBorderRadii)[C_TL] = Size(radii[NS_CORNER_TOP_LEFT_X],
|
||||
radii[NS_CORNER_TOP_LEFT_Y]);
|
||||
(*oBorderRadii)[C_TR] = Size(radii[NS_CORNER_TOP_RIGHT_X],
|
||||
radii[NS_CORNER_TOP_RIGHT_Y]);
|
||||
(*oBorderRadii)[C_BR] = Size(radii[NS_CORNER_BOTTOM_RIGHT_X],
|
||||
radii[NS_CORNER_BOTTOM_RIGHT_Y]);
|
||||
(*oBorderRadii)[C_BL] = Size(radii[NS_CORNER_BOTTOM_LEFT_X],
|
||||
radii[NS_CORNER_BOTTOM_LEFT_Y]);
|
||||
}
|
||||
|
||||
void
|
||||
nsCSSRendering::PaintBorder(nsPresContext* aPresContext,
|
||||
nsRenderingContext& aRenderingContext,
|
||||
@ -1194,6 +1214,7 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
const nsRect& aDirtyRect,
|
||||
float aOpacity)
|
||||
{
|
||||
DrawTarget& aDrawTarget = *aRenderingContext.GetDrawTarget();
|
||||
const nsStyleBorder* styleBorder = aForFrame->StyleBorder();
|
||||
nsCSSShadowArray* shadows = styleBorder->mBoxShadow;
|
||||
if (!shadows)
|
||||
@ -1223,7 +1244,7 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
|
||||
// Get any border radius, since box-shadow must also have rounded corners if
|
||||
// the frame does.
|
||||
gfxCornerSizes borderRadii;
|
||||
RectCornerRadii borderRadii;
|
||||
const nscoord twipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
|
||||
if (hasBorderRadius) {
|
||||
nscoord twipsRadii[8];
|
||||
@ -1236,12 +1257,12 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
|
||||
gfxRect frameGfxRect(nsLayoutUtils::RectToGfxRect(frameRect, twipsPerPixel));
|
||||
Rect frameGfxRect = NSRectToRect(frameRect, twipsPerPixel);
|
||||
frameGfxRect.Round();
|
||||
|
||||
// We don't show anything that intersects with the frame we're blurring on. So tell the
|
||||
// blurrer not to do unnecessary work there.
|
||||
gfxRect skipGfxRect = frameGfxRect;
|
||||
gfxRect skipGfxRect = ThebesRect(frameGfxRect);
|
||||
bool useSkipGfxRect = true;
|
||||
if (nativeTheme) {
|
||||
// Optimize non-leaf native-themed frames by skipping computing pixels
|
||||
@ -1259,6 +1280,8 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
std::max(borderRadii[C_BL].height, borderRadii[C_BR].height), 0));
|
||||
}
|
||||
|
||||
gfxContext* renderContext = aRenderingContext.ThebesContext();
|
||||
|
||||
for (uint32_t i = shadows->Length(); i > 0; --i) {
|
||||
nsCSSShadowItem* shadowItem = shadows->ShadowAt(i - 1);
|
||||
if (shadowItem->mInset)
|
||||
@ -1277,9 +1300,10 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
shadowRectPlusBlur.Inflate(
|
||||
nsContextBoxBlur::GetBlurRadiusMargin(blurRadius, twipsPerPixel));
|
||||
|
||||
gfxRect shadowGfxRectPlusBlur =
|
||||
nsLayoutUtils::RectToGfxRect(shadowRectPlusBlur, twipsPerPixel);
|
||||
Rect shadowGfxRectPlusBlur =
|
||||
NSRectToRect(shadowRectPlusBlur, twipsPerPixel);
|
||||
shadowGfxRectPlusBlur.RoundOut();
|
||||
MaybeSnapToDevicePixels(shadowGfxRectPlusBlur, aDrawTarget, true);
|
||||
|
||||
// Set the shadow color; if not specified, use the foreground color
|
||||
nscolor shadowColor;
|
||||
@ -1291,7 +1315,6 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
gfxRGBA gfxShadowColor(shadowColor);
|
||||
gfxShadowColor.a *= aOpacity;
|
||||
|
||||
gfxContext* renderContext = aRenderingContext.ThebesContext();
|
||||
if (nativeTheme) {
|
||||
nsContextBoxBlur blurringArea;
|
||||
|
||||
@ -1307,7 +1330,6 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
if (!shadowContext)
|
||||
continue;
|
||||
|
||||
// shadowContext is owned by either blurringArea or aRenderingContext.
|
||||
MOZ_ASSERT(shadowContext == blurringArea.GetContext());
|
||||
|
||||
renderContext->Save();
|
||||
@ -1342,18 +1364,21 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
renderContext->Restore();
|
||||
} else {
|
||||
renderContext->Save();
|
||||
// Clip out the area of the actual frame so the shadow is not shown within
|
||||
// the frame.
|
||||
renderContext->NewPath();
|
||||
renderContext->Rectangle(shadowGfxRectPlusBlur);
|
||||
if (hasBorderRadius) {
|
||||
renderContext->RoundedRectangle(frameGfxRect, borderRadii);
|
||||
} else {
|
||||
renderContext->Rectangle(frameGfxRect);
|
||||
}
|
||||
|
||||
renderContext->SetFillRule(FillRule::FILL_EVEN_ODD);
|
||||
renderContext->Clip();
|
||||
{
|
||||
// Clip out the interior of the frame's border edge so that the shadow
|
||||
// is only painted outside that area.
|
||||
RefPtr<PathBuilder> builder =
|
||||
aDrawTarget.CreatePathBuilder(FillRule::FILL_EVEN_ODD);
|
||||
AppendRectToPath(builder, shadowGfxRectPlusBlur);
|
||||
if (hasBorderRadius) {
|
||||
AppendRoundedRectToPath(builder, frameGfxRect, borderRadii);
|
||||
} else {
|
||||
AppendRectToPath(builder, frameGfxRect);
|
||||
}
|
||||
RefPtr<Path> path = builder->Finish();
|
||||
renderContext->Clip(path);
|
||||
}
|
||||
|
||||
// Clip the shadow so that we only get the part that applies to aForFrame.
|
||||
nsRect fragmentClip = shadowRectPlusBlur;
|
||||
@ -1383,16 +1408,16 @@ nsCSSRendering::PaintBoxShadowOuter(nsPresContext* aPresContext,
|
||||
}
|
||||
}
|
||||
}
|
||||
aRenderingContext.ThebesContext()->
|
||||
renderContext->
|
||||
Clip(NSRectToSnappedRect(fragmentClip,
|
||||
aForFrame->PresContext()->AppUnitsPerDevPixel(),
|
||||
*aRenderingContext.GetDrawTarget()));
|
||||
aDrawTarget));
|
||||
|
||||
gfxCornerSizes clipRectRadii;
|
||||
if (hasBorderRadius) {
|
||||
gfxFloat spreadDistance = shadowItem->mSpread / twipsPerPixel;
|
||||
Float spreadDistance = shadowItem->mSpread / twipsPerPixel;
|
||||
|
||||
gfxFloat borderSizes[4];
|
||||
Float borderSizes[4];
|
||||
|
||||
borderSizes[NS_SIDE_LEFT] = spreadDistance;
|
||||
borderSizes[NS_SIDE_TOP] = spreadDistance;
|
||||
|
@ -24,6 +24,7 @@ namespace mozilla {
|
||||
|
||||
namespace gfx {
|
||||
class DrawTarget;
|
||||
struct RectCornerRadii;
|
||||
}
|
||||
|
||||
namespace layers {
|
||||
@ -319,6 +320,7 @@ struct nsCSSRendering {
|
||||
typedef mozilla::gfx::DrawTarget DrawTarget;
|
||||
typedef mozilla::gfx::Float Float;
|
||||
typedef mozilla::gfx::Rect Rect;
|
||||
typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
|
||||
typedef nsIFrame::Sides Sides;
|
||||
|
||||
/**
|
||||
@ -344,6 +346,10 @@ struct nsCSSRendering {
|
||||
const nsRect& aDirtyRect,
|
||||
float aOpacity = 1.0);
|
||||
|
||||
static void ComputePixelRadii(const nscoord *aAppUnitsRadii,
|
||||
nscoord aAppUnitsPerPixel,
|
||||
RectCornerRadii *oBorderRadii);
|
||||
|
||||
static void ComputePixelRadii(const nscoord *aAppUnitsRadii,
|
||||
nscoord aAppUnitsPerPixel,
|
||||
gfxCornerSizes *oBorderRadii);
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "nsCSSRenderingBorders.h"
|
||||
|
||||
#include "gfxUtils.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/PathHelpers.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "nsCSSColorUtils.h"
|
||||
#include "GeckoProfiler.h"
|
||||
@ -173,8 +175,8 @@ nsCSSBorderRenderer::ComputeInnerRadii(const gfxCornerSizes& aRadii,
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsCSSBorderRenderer::ComputeOuterRadii(const gfxCornerSizes& aRadii,
|
||||
const gfxFloat *aBorderSizes,
|
||||
nsCSSBorderRenderer::ComputeOuterRadii(const RectCornerRadii& aRadii,
|
||||
const Float *aBorderSizes,
|
||||
gfxCornerSizes *aOuterRadiiRet)
|
||||
{
|
||||
gfxCornerSizes& oRadii = *aOuterRadiiRet;
|
||||
@ -183,24 +185,24 @@ nsCSSBorderRenderer::ComputeOuterRadii(const gfxCornerSizes& aRadii,
|
||||
oRadii = gfxCornerSizes(0.0);
|
||||
|
||||
// round the edges that have radii > 0.0 to start with
|
||||
if (aRadii[C_TL].width > 0.0 && aRadii[C_TL].height > 0.0) {
|
||||
oRadii[C_TL].width = std::max(0.0, aRadii[C_TL].width + aBorderSizes[NS_SIDE_LEFT]);
|
||||
oRadii[C_TL].height = std::max(0.0, aRadii[C_TL].height + aBorderSizes[NS_SIDE_TOP]);
|
||||
if (aRadii[C_TL].width > 0.f && aRadii[C_TL].height > 0.f) {
|
||||
oRadii[C_TL].width = std::max(0.f, aRadii[C_TL].width + aBorderSizes[NS_SIDE_LEFT]);
|
||||
oRadii[C_TL].height = std::max(0.f, aRadii[C_TL].height + aBorderSizes[NS_SIDE_TOP]);
|
||||
}
|
||||
|
||||
if (aRadii[C_TR].width > 0.0 && aRadii[C_TR].height > 0.0) {
|
||||
oRadii[C_TR].width = std::max(0.0, aRadii[C_TR].width + aBorderSizes[NS_SIDE_RIGHT]);
|
||||
oRadii[C_TR].height = std::max(0.0, aRadii[C_TR].height + aBorderSizes[NS_SIDE_TOP]);
|
||||
if (aRadii[C_TR].width > 0.f && aRadii[C_TR].height > 0.f) {
|
||||
oRadii[C_TR].width = std::max(0.f, aRadii[C_TR].width + aBorderSizes[NS_SIDE_RIGHT]);
|
||||
oRadii[C_TR].height = std::max(0.f, aRadii[C_TR].height + aBorderSizes[NS_SIDE_TOP]);
|
||||
}
|
||||
|
||||
if (aRadii[C_BR].width > 0.0 && aRadii[C_BR].height > 0.0) {
|
||||
oRadii[C_BR].width = std::max(0.0, aRadii[C_BR].width + aBorderSizes[NS_SIDE_RIGHT]);
|
||||
oRadii[C_BR].height = std::max(0.0, aRadii[C_BR].height + aBorderSizes[NS_SIDE_BOTTOM]);
|
||||
if (aRadii[C_BR].width > 0.f && aRadii[C_BR].height > 0.f) {
|
||||
oRadii[C_BR].width = std::max(0.f, aRadii[C_BR].width + aBorderSizes[NS_SIDE_RIGHT]);
|
||||
oRadii[C_BR].height = std::max(0.f, aRadii[C_BR].height + aBorderSizes[NS_SIDE_BOTTOM]);
|
||||
}
|
||||
|
||||
if (aRadii[C_BL].width > 0.0 && aRadii[C_BL].height > 0.0) {
|
||||
oRadii[C_BL].width = std::max(0.0, aRadii[C_BL].width + aBorderSizes[NS_SIDE_LEFT]);
|
||||
oRadii[C_BL].height = std::max(0.0, aRadii[C_BL].height + aBorderSizes[NS_SIDE_BOTTOM]);
|
||||
if (aRadii[C_BL].width > 0.f && aRadii[C_BL].height > 0.f) {
|
||||
oRadii[C_BL].width = std::max(0.f, aRadii[C_BL].width + aBorderSizes[NS_SIDE_LEFT]);
|
||||
oRadii[C_BL].height = std::max(0.f, aRadii[C_BL].height + aBorderSizes[NS_SIDE_BOTTOM]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ struct nsBorderColors;
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
class GradientStops;
|
||||
struct RectCornerRadii;
|
||||
}
|
||||
}
|
||||
|
||||
@ -76,6 +77,9 @@ typedef enum {
|
||||
} BorderColorStyle;
|
||||
|
||||
struct nsCSSBorderRenderer {
|
||||
typedef mozilla::gfx::Float Float;
|
||||
typedef mozilla::gfx::RectCornerRadii RectCornerRadii;
|
||||
|
||||
nsCSSBorderRenderer(int32_t aAppUnitsPerPixel,
|
||||
gfxContext* aDestContext,
|
||||
gfxRect& aOuterRect,
|
||||
@ -219,8 +223,8 @@ struct nsCSSBorderRenderer {
|
||||
// appropriate radii for another rectangle *outside* that rectangle
|
||||
// by increasing the radii, except keeping sharp corners sharp.
|
||||
// Used for spread box-shadows
|
||||
static void ComputeOuterRadii(const gfxCornerSizes& aRadii,
|
||||
const gfxFloat *aBorderSizes,
|
||||
static void ComputeOuterRadii(const RectCornerRadii& aRadii,
|
||||
const Float *aBorderSizes,
|
||||
gfxCornerSizes *aOuterRadiiRet);
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user