--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -5095,17 +5095,17 @@ CanvasRenderingContext2D::DrawDirectlyTo
uint32_t modifiedFlags = aImage.mDrawingFlags | imgIContainer::FLAG_CLAMP;
CSSIntSize sz(scaledImageSize.width, scaledImageSize.height); // XXX hmm is scaledImageSize really in CSS pixels?
SVGImageContext svgContext(sz, Nothing(), CurrentState().globalAlpha);
auto result = aImage.mImgContainer->
Draw(context, scaledImageSize,
ImageRegion::Create(gfxRect(aSrc.x, aSrc.y, aSrc.width, aSrc.height)),
- aImage.mWhichFrame, SamplingFilter::GOOD, Some(svgContext), modifiedFlags);
+ aImage.mWhichFrame, SamplingFilter::GOOD, Some(svgContext), modifiedFlags, 1.0);
if (result != DrawResult::SUCCESS) {
NS_WARNING("imgIContainer::Draw failed");
}
}
void
CanvasRenderingContext2D::SetGlobalCompositeOperation(const nsAString& aOp,
--- a/image/ClippedImage.cpp
+++ b/image/ClippedImage.cpp
@@ -93,23 +93,25 @@ private:
class DrawSingleTileCallback : public gfxDrawingCallback
{
public:
DrawSingleTileCallback(ClippedImage* aImage,
const nsIntSize& aSize,
const Maybe<SVGImageContext>& aSVGContext,
uint32_t aWhichFrame,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
: mImage(aImage)
, mSize(aSize)
, mSVGContext(aSVGContext)
, mWhichFrame(aWhichFrame)
, mFlags(aFlags)
, mDrawResult(DrawResult::NOT_READY)
+ , mOpacity(aOpacity)
{
MOZ_ASSERT(mImage, "Must have an image to clip");
}
virtual bool operator()(gfxContext* aContext,
const gfxRect& aFillRect,
const SamplingFilter aSamplingFilter,
const gfxMatrix& aTransform)
@@ -117,30 +119,32 @@ public:
MOZ_ASSERT(aTransform.IsIdentity(),
"Caller is probably CreateSamplingRestrictedDrawable, "
"which should not happen");
// Draw the image. |gfxCallbackDrawable| always calls this function with
// arguments that guarantee we never tile.
mDrawResult =
mImage->DrawSingleTile(aContext, mSize, ImageRegion::Create(aFillRect),
- mWhichFrame, aSamplingFilter, mSVGContext, mFlags);
+ mWhichFrame, aSamplingFilter, mSVGContext, mFlags,
+ mOpacity);
return true;
}
DrawResult GetDrawResult() { return mDrawResult; }
private:
RefPtr<ClippedImage> mImage;
const nsIntSize mSize;
const Maybe<SVGImageContext>& mSVGContext;
const uint32_t mWhichFrame;
const uint32_t mFlags;
DrawResult mDrawResult;
+ float mOpacity;
};
ClippedImage::ClippedImage(Image* aImage,
nsIntRect aClip,
const Maybe<nsSize>& aSVGViewportSize)
: ImageWrapper(aImage)
, mClip(aClip)
{
@@ -253,17 +257,17 @@ ClippedImage::GetIntrinsicRatio(nsSize*
}
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
ClippedImage::GetFrame(uint32_t aWhichFrame,
uint32_t aFlags)
{
DrawResult result;
RefPtr<SourceSurface> surface;
- Tie(result, surface) = GetFrameInternal(mClip.Size(), Nothing(), aWhichFrame, aFlags);
+ Tie(result, surface) = GetFrameInternal(mClip.Size(), Nothing(), aWhichFrame, aFlags, 1.0);
return surface.forget();
}
NS_IMETHODIMP_(already_AddRefed<SourceSurface>)
ClippedImage::GetFrameAtSize(const IntSize& aSize,
uint32_t aWhichFrame,
uint32_t aFlags)
{
@@ -271,17 +275,18 @@ ClippedImage::GetFrameAtSize(const IntSi
// but right now we just fall back to the intrinsic size.
return GetFrame(aWhichFrame, aFlags);
}
Pair<DrawResult, RefPtr<SourceSurface>>
ClippedImage::GetFrameInternal(const nsIntSize& aSize,
const Maybe<SVGImageContext>& aSVGContext,
uint32_t aWhichFrame,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
{
if (!ShouldClip()) {
RefPtr<SourceSurface> surface = InnerImage()->GetFrame(aWhichFrame, aFlags);
return MakePair(surface ? DrawResult::SUCCESS : DrawResult::NOT_READY,
Move(surface));
}
float frameToDraw = InnerImage()->GetFrameIndex(aWhichFrame);
@@ -297,17 +302,18 @@ ClippedImage::GetFrameInternal(const nsI
return MakePair(DrawResult::TEMPORARY_ERROR, RefPtr<SourceSurface>());
}
RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(target);
MOZ_ASSERT(ctx); // already checked the draw target above
// Create our callback.
RefPtr<DrawSingleTileCallback> drawTileCallback =
- new DrawSingleTileCallback(this, aSize, aSVGContext, aWhichFrame, aFlags);
+ new DrawSingleTileCallback(this, aSize, aSVGContext, aWhichFrame, aFlags,
+ aOpacity);
RefPtr<gfxDrawable> drawable =
new gfxCallbackDrawable(drawTileCallback, aSize);
// Actually draw. The callback will end up invoking DrawSingleTile.
gfxUtils::DrawPixelSnapped(ctx, drawable, aSize,
ImageRegion::Create(aSize),
SurfaceFormat::B8G8R8A8,
SamplingFilter::LINEAR,
@@ -366,60 +372,63 @@ MustCreateSurface(gfxContext* aContext,
NS_IMETHODIMP_(DrawResult)
ClippedImage::Draw(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
{
if (!ShouldClip()) {
return InnerImage()->Draw(aContext, aSize, aRegion, aWhichFrame,
- aSamplingFilter, aSVGContext, aFlags);
+ aSamplingFilter, aSVGContext, aFlags, aOpacity);
}
// Check for tiling. If we need to tile then we need to create a
// gfxCallbackDrawable to handle drawing for us.
if (MustCreateSurface(aContext, aSize, aRegion, aFlags)) {
// Create a temporary surface containing a single tile of this image.
// GetFrame will call DrawSingleTile internally.
DrawResult result;
RefPtr<SourceSurface> surface;
Tie(result, surface) =
- GetFrameInternal(aSize, aSVGContext, aWhichFrame, aFlags);
+ GetFrameInternal(aSize, aSVGContext, aWhichFrame, aFlags, aOpacity);
if (!surface) {
MOZ_ASSERT(result != DrawResult::SUCCESS);
return result;
}
// Create a drawable from that surface.
RefPtr<gfxSurfaceDrawable> drawable =
new gfxSurfaceDrawable(surface, aSize);
// Draw.
gfxUtils::DrawPixelSnapped(aContext, drawable, aSize, aRegion,
- SurfaceFormat::B8G8R8A8, aSamplingFilter);
+ SurfaceFormat::B8G8R8A8, aSamplingFilter,
+ aOpacity);
return result;
}
return DrawSingleTile(aContext, aSize, aRegion, aWhichFrame,
- aSamplingFilter, aSVGContext, aFlags);
+ aSamplingFilter, aSVGContext, aFlags, aOpacity);
}
DrawResult
ClippedImage::DrawSingleTile(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
{
MOZ_ASSERT(!MustCreateSurface(aContext, aSize, aRegion, aFlags),
"Shouldn't need to create a surface");
gfxRect clip(mClip.x, mClip.y, mClip.width, mClip.height);
nsIntSize size(aSize), innerSize(aSize);
bool needScale = false;
if (mSVGViewportSize && !mSVGViewportSize->IsEmpty()) {
@@ -465,17 +474,17 @@ ClippedImage::DrawSingleTile(gfxContext*
return SVGImageContext(vSize,
aOldContext.GetPreserveAspectRatio());
};
return InnerImage()->Draw(aContext, size, region,
aWhichFrame, aSamplingFilter,
aSVGContext.map(unclipViewport),
- aFlags);
+ aFlags, aOpacity);
}
NS_IMETHODIMP
ClippedImage::RequestDiscard()
{
// We're very aggressive about discarding.
mCachedSurface = nullptr;
--- a/image/ClippedImage.h
+++ b/image/ClippedImage.h
@@ -48,17 +48,18 @@ public:
GetImageContainer(layers::LayerManager* aManager,
uint32_t aFlags) override;
NS_IMETHOD_(DrawResult) Draw(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
gfx::SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags) override;
+ uint32_t aFlags,
+ float aOpacity) override;
NS_IMETHOD RequestDiscard() override;
NS_IMETHOD_(Orientation) GetOrientation() override;
NS_IMETHOD_(nsIntRect) GetImageSpaceInvalidationRect(const nsIntRect& aRect)
override;
nsIntSize OptimalImageSizeForDest(const gfxSize& aDest,
uint32_t aWhichFrame,
gfx::SamplingFilter aSamplingFilter,
uint32_t aFlags) override;
@@ -69,25 +70,27 @@ protected:
virtual ~ClippedImage();
private:
Pair<DrawResult, RefPtr<SourceSurface>>
GetFrameInternal(const nsIntSize& aSize,
const Maybe<SVGImageContext>& aSVGContext,
uint32_t aWhichFrame,
- uint32_t aFlags);
+ uint32_t aFlags,
+ float aOpacity);
bool ShouldClip();
DrawResult DrawSingleTile(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
gfx::SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags);
+ uint32_t aFlags,
+ float aOpacity);
// If we are forced to draw a temporary surface, we cache it here.
UniquePtr<ClippedImageCachedSurface> mCachedSurface;
nsIntRect mClip; // The region to clip to.
Maybe<bool> mShouldClip; // Memoized ShouldClip() if present.
Maybe<nsIntSize> mSVGViewportSize; // If we're clipping a VectorImage, this
// is the size of viewport of that image.
--- a/image/DynamicImage.cpp
+++ b/image/DynamicImage.cpp
@@ -184,17 +184,18 @@ DynamicImage::GetFrameAtSize(const IntSi
gfxWarning() <<
"DynamicImage::GetFrame failed in CreateOffscreenContentDrawTarget";
return nullptr;
}
RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
MOZ_ASSERT(context); // already checked the draw target above
auto result = Draw(context, aSize, ImageRegion::Create(aSize),
- aWhichFrame, SamplingFilter::POINT, Nothing(), aFlags);
+ aWhichFrame, SamplingFilter::POINT, Nothing(), aFlags,
+ 1.0);
return result == DrawResult::SUCCESS ? dt->Snapshot() : nullptr;
}
NS_IMETHODIMP_(bool)
DynamicImage::WillDrawOpaqueNow()
{
return false;
@@ -214,39 +215,42 @@ DynamicImage::GetImageContainer(LayerMan
NS_IMETHODIMP_(DrawResult)
DynamicImage::Draw(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
{
MOZ_ASSERT(!aSize.IsEmpty(), "Unexpected empty size");
IntSize drawableSize(mDrawable->Size());
if (aSize == drawableSize) {
gfxUtils::DrawPixelSnapped(aContext, mDrawable, drawableSize, aRegion,
- SurfaceFormat::B8G8R8A8, aSamplingFilter);
+ SurfaceFormat::B8G8R8A8, aSamplingFilter,
+ aOpacity);
return DrawResult::SUCCESS;
}
gfxSize scale(double(aSize.width) / drawableSize.width,
double(aSize.height) / drawableSize.height);
ImageRegion region(aRegion);
region.Scale(1.0 / scale.width, 1.0 / scale.height);
gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
aContext->Multiply(gfxMatrix::Scaling(scale.width, scale.height));
gfxUtils::DrawPixelSnapped(aContext, mDrawable, drawableSize, region,
- SurfaceFormat::B8G8R8A8, aSamplingFilter);
+ SurfaceFormat::B8G8R8A8, aSamplingFilter,
+ aOpacity);
return DrawResult::SUCCESS;
}
NS_IMETHODIMP
DynamicImage::StartDecoding(uint32_t aFlags)
{
return NS_OK;
}
--- a/image/FrozenImage.cpp
+++ b/image/FrozenImage.cpp
@@ -73,20 +73,21 @@ FrozenImage::GetImageContainer(layers::L
NS_IMETHODIMP_(DrawResult)
FrozenImage::Draw(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t /* aWhichFrame - ignored */,
SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
{
return InnerImage()->Draw(aContext, aSize, aRegion, FRAME_FIRST,
- aSamplingFilter, aSVGContext, aFlags);
+ aSamplingFilter, aSVGContext, aFlags, aOpacity);
}
NS_IMETHODIMP_(void)
FrozenImage::RequestRefresh(const TimeStamp& aTime)
{
// Do nothing.
}
--- a/image/FrozenImage.h
+++ b/image/FrozenImage.h
@@ -47,17 +47,18 @@ public:
GetImageContainer(layers::LayerManager* aManager,
uint32_t aFlags) override;
NS_IMETHOD_(DrawResult) Draw(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
gfx::SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags) override;
+ uint32_t aFlags,
+ float aOpacity) override;
NS_IMETHOD_(void) RequestRefresh(const TimeStamp& aTime) override;
NS_IMETHOD GetAnimationMode(uint16_t* aAnimationMode) override;
NS_IMETHOD SetAnimationMode(uint16_t aAnimationMode) override;
NS_IMETHOD ResetAnimation() override;
NS_IMETHOD_(float) GetFrameIndex(uint32_t aWhichFrame) override;
protected:
explicit FrozenImage(Image* aImage) : ImageWrapper(aImage) { }
--- a/image/ImageWrapper.cpp
+++ b/image/ImageWrapper.cpp
@@ -204,20 +204,21 @@ ImageWrapper::GetImageContainer(LayerMan
NS_IMETHODIMP_(DrawResult)
ImageWrapper::Draw(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
{
return mInnerImage->Draw(aContext, aSize, aRegion, aWhichFrame,
- aSamplingFilter, aSVGContext, aFlags);
+ aSamplingFilter, aSVGContext, aFlags, aOpacity);
}
NS_IMETHODIMP
ImageWrapper::StartDecoding(uint32_t aFlags)
{
return mInnerImage->StartDecoding(aFlags);
}
--- a/image/OrientedImage.cpp
+++ b/image/OrientedImage.cpp
@@ -258,22 +258,23 @@ OrientedImage::OrientationMatrix(const n
NS_IMETHODIMP_(DrawResult)
OrientedImage::Draw(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
{
if (mOrientation.IsIdentity()) {
return InnerImage()->Draw(aContext, aSize, aRegion,
aWhichFrame, aSamplingFilter,
- aSVGContext, aFlags);
+ aSVGContext, aFlags, aOpacity);
}
// Update the image size to match the image's coordinate system. (This could
// be done using TransformBounds but since it's only a size a swap is enough.)
nsIntSize size(aSize);
if (mOrientation.SwapsWidthAndHeight()) {
swap(size.width, size.height);
}
@@ -295,18 +296,20 @@ OrientedImage::Draw(gfxContext* aContext
CSSIntSize viewportSize(aOldContext.GetViewportSize());
if (mOrientation.SwapsWidthAndHeight()) {
swap(viewportSize.width, viewportSize.height);
}
return SVGImageContext(viewportSize,
aOldContext.GetPreserveAspectRatio());
};
- return InnerImage()->Draw(aContext, size, region, aWhichFrame, aSamplingFilter,
- aSVGContext.map(orientViewport), aFlags);
+ return InnerImage()->Draw(aContext, size, region, aWhichFrame,
+ aSamplingFilter,
+ aSVGContext.map(orientViewport), aFlags,
+ aOpacity);
}
nsIntSize
OrientedImage::OptimalImageSizeForDest(const gfxSize& aDest,
uint32_t aWhichFrame,
SamplingFilter aSamplingFilter,
uint32_t aFlags)
{
--- a/image/OrientedImage.h
+++ b/image/OrientedImage.h
@@ -44,17 +44,18 @@ public:
GetImageContainer(layers::LayerManager* aManager,
uint32_t aFlags) override;
NS_IMETHOD_(DrawResult) Draw(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
gfx::SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags) override;
+ uint32_t aFlags,
+ float aOpacity) override;
NS_IMETHOD_(nsIntRect) GetImageSpaceInvalidationRect(
const nsIntRect& aRect) override;
nsIntSize OptimalImageSizeForDest(const gfxSize& aDest,
uint32_t aWhichFrame,
gfx::SamplingFilter aSamplingFilter,
uint32_t aFlags) override;
protected:
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -1306,17 +1306,18 @@ RasterImage::CanDownscaleDuringDecode(co
}
DrawResult
RasterImage::DrawInternal(DrawableSurface&& aSurface,
gfxContext* aContext,
const IntSize& aSize,
const ImageRegion& aRegion,
SamplingFilter aSamplingFilter,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
{
gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
ImageRegion region(aRegion);
bool frameIsFinished = aSurface->IsFinished();
// By now we may have a frame with the requested size. If not, we need to
// adjust the drawing parameters accordingly.
IntSize finalSize = aSurface->GetImageSize();
@@ -1325,17 +1326,17 @@ RasterImage::DrawInternal(DrawableSurfac
gfx::Size scale(double(aSize.width) / finalSize.width,
double(aSize.height) / finalSize.height);
aContext->Multiply(gfxMatrix::Scaling(scale.width, scale.height));
region.Scale(1.0 / scale.width, 1.0 / scale.height);
couldRedecodeForBetterFrame = CanDownscaleDuringDecode(aSize, aFlags);
}
- if (!aSurface->Draw(aContext, region, aSamplingFilter, aFlags)) {
+ if (!aSurface->Draw(aContext, region, aSamplingFilter, aFlags, aOpacity)) {
RecoverFromInvalidFrames(aSize, aFlags);
return DrawResult::TEMPORARY_ERROR;
}
if (!frameIsFinished) {
return DrawResult::INCOMPLETE;
}
if (couldRedecodeForBetterFrame) {
return DrawResult::WRONG_SIZE;
@@ -1346,17 +1347,18 @@ RasterImage::DrawInternal(DrawableSurfac
//******************************************************************************
NS_IMETHODIMP_(DrawResult)
RasterImage::Draw(gfxContext* aContext,
const IntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& /*aSVGContext - ignored*/,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
{
if (aWhichFrame > FRAME_MAX_VALUE) {
return DrawResult::BAD_ARGS;
}
if (mError) {
return DrawResult::BAD_IMAGE;
}
@@ -1392,17 +1394,17 @@ RasterImage::Draw(gfxContext* aContext,
}
return DrawResult::NOT_READY;
}
bool shouldRecordTelemetry = !mDrawStartTime.IsNull() &&
surface->IsFinished();
auto result = DrawInternal(Move(surface), aContext, aSize,
- aRegion, aSamplingFilter, flags);
+ aRegion, aSamplingFilter, flags, aOpacity);
if (shouldRecordTelemetry) {
TimeDuration drawLatency = TimeStamp::Now() - mDrawStartTime;
Telemetry::Accumulate(Telemetry::IMAGE_DECODE_ON_DRAW_LATENCY,
int32_t(drawLatency.ToMicroseconds()));
mDrawStartTime = TimeStamp();
}
--- a/image/RasterImage.h
+++ b/image/RasterImage.h
@@ -297,17 +297,18 @@ private:
uint32_t aFlags,
PlaybackType aPlaybackType);
DrawResult DrawInternal(DrawableSurface&& aFrameRef,
gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
gfx::SamplingFilter aSamplingFilter,
- uint32_t aFlags);
+ uint32_t aFlags,
+ float aOpacity);
Pair<DrawResult, RefPtr<gfx::SourceSurface>>
GetFrameInternal(const gfx::IntSize& aSize,
uint32_t aWhichFrame,
uint32_t aFlags);
Pair<DrawResult, RefPtr<layers::Image>>
GetCurrentImage(layers::ImageContainer* aContainer, uint32_t aFlags);
--- a/image/VectorImage.cpp
+++ b/image/VectorImage.cpp
@@ -745,17 +745,18 @@ VectorImage::GetFrameAtSize(const IntSiz
NS_ERROR("Could not create a DrawTarget");
return nullptr;
}
RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
MOZ_ASSERT(context); // already checked the draw target above
auto result = Draw(context, aSize, ImageRegion::Create(aSize),
- aWhichFrame, SamplingFilter::POINT, Nothing(), aFlags);
+ aWhichFrame, SamplingFilter::POINT, Nothing(), aFlags,
+ 1.0);
return result == DrawResult::SUCCESS ? dt->Snapshot() : nullptr;
}
NS_IMETHODIMP_(bool)
VectorImage::IsImageContainerAvailable(LayerManager* aManager, uint32_t aFlags)
{
return false;
@@ -771,26 +772,27 @@ VectorImage::GetImageContainer(LayerMana
struct SVGDrawingParameters
{
SVGDrawingParameters(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
float aAnimationTime,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
: context(aContext)
, size(aSize.width, aSize.height)
, region(aRegion)
, samplingFilter(aSamplingFilter)
, svgContext(aSVGContext)
, viewportSize(aSize)
, animationTime(aAnimationTime)
, flags(aFlags)
- , opacity(aSVGContext ? aSVGContext->GetGlobalOpacity() : 1.0)
+ , opacity(aSVGContext ? aSVGContext->GetGlobalOpacity() : aOpacity)
{
if (aSVGContext) {
CSSIntSize sz = aSVGContext->GetViewportSize();
viewportSize = nsIntSize(sz.width, sz.height); // XXX losing unit
}
}
gfxContext* context;
@@ -807,17 +809,18 @@ struct SVGDrawingParameters
//******************************************************************************
NS_IMETHODIMP_(DrawResult)
VectorImage::Draw(gfxContext* aContext,
const nsIntSize& aSize,
const ImageRegion& aRegion,
uint32_t aWhichFrame,
SamplingFilter aSamplingFilter,
const Maybe<SVGImageContext>& aSVGContext,
- uint32_t aFlags)
+ uint32_t aFlags,
+ float aOpacity)
{
if (aWhichFrame > FRAME_MAX_VALUE) {
return DrawResult::BAD_ARGS;
}
if (!aContext) {
return DrawResult::BAD_ARGS;
}
@@ -862,17 +865,17 @@ VectorImage::Draw(gfxContext* aContext,
float animTime =
(aWhichFrame == FRAME_FIRST) ? 0.0f
: mSVGDocumentWrapper->GetCurrentTime();
AutoSVGRenderingState autoSVGState(svgContext, animTime,
mSVGDocumentWrapper->GetRootSVGElem());
SVGDrawingParameters params(aContext, aSize, aRegion, aSamplingFilter,
- svgContext, animTime, aFlags);
+ svgContext, animTime, aFlags, aOpacity);
// If we have an prerasterized version of this image that matches the
// drawing parameters, use that.
RefPtr<gfxDrawable> svgDrawable = LookupCachedSurface(params);
if (svgDrawable) {
Show(svgDrawable, params);
return DrawResult::SUCCESS;
}
--- a/image/imgFrame.cpp
+++ b/image/imgFrame.cpp
@@ -534,17 +534,18 @@ imgFrame::SurfaceForDrawing(bool
aRegion = aRegion.Intersect(available);
IntSize availableSize(mDecoded.width, mDecoded.height);
return SurfaceWithFormat(new gfxSurfaceDrawable(aSurface, availableSize),
mFormat);
}
bool imgFrame::Draw(gfxContext* aContext, const ImageRegion& aRegion,
- SamplingFilter aSamplingFilter, uint32_t aImageFlags)
+ SamplingFilter aSamplingFilter, uint32_t aImageFlags,
+ float aOpacity)
{
PROFILER_LABEL("imgFrame", "Draw",
js::ProfileEntry::Category::GRAPHICS);
MOZ_ASSERT(NS_IsMainThread());
NS_ASSERTION(!aRegion.Rect().IsEmpty(), "Drawing empty region!");
NS_ASSERTION(!aRegion.IsRestricted() ||
!aRegion.Rect().Intersect(aRegion.Restriction()).IsEmpty(),
@@ -576,17 +577,17 @@ bool imgFrame::Draw(gfxContext* aContext
ImageRegion region(aRegion);
SurfaceWithFormat surfaceResult =
SurfaceForDrawing(doPartialDecode, doTile, region, surf);
if (surfaceResult.IsValid()) {
gfxUtils::DrawPixelSnapped(aContext, surfaceResult.mDrawable,
imageRect.Size(), region, surfaceResult.mFormat,
- aSamplingFilter, aImageFlags);
+ aSamplingFilter, aImageFlags, aOpacity);
}
return true;
}
nsresult
imgFrame::ImageUpdated(const nsIntRect& aUpdateRect)
{
MonitorAutoLock lock(mMonitor);
--- a/image/imgFrame.h
+++ b/image/imgFrame.h
@@ -252,17 +252,18 @@ public:
* volatile buffer to be freed.
*
* It is an error to call this without already holding a RawAccessFrameRef to
* this imgFrame.
*/
void SetRawAccessOnly();
bool Draw(gfxContext* aContext, const ImageRegion& aRegion,
- SamplingFilter aSamplingFilter, uint32_t aImageFlags);
+ SamplingFilter aSamplingFilter, uint32_t aImageFlags,
+ float aOpacity);
nsresult ImageUpdated(const nsIntRect& aUpdateRect);
/**
* Mark this imgFrame as completely decoded, and set final options.
*
* You must always call either Finish() or Abort() before releasing the last
* RawAccessFrameRef pointing to an imgFrame.
--- a/image/imgIContainer.idl
+++ b/image/imgIContainer.idl
@@ -402,17 +402,18 @@ interface imgIContainer : nsISupports
*/
[noscript, notxpcom] DrawResult
draw(in gfxContext aContext,
[const] in nsIntSize aSize,
[const] in ImageRegion aRegion,
in uint32_t aWhichFrame,
in SamplingFilter aSamplingFilter,
[const] in MaybeSVGImageContext aSVGContext,
- in uint32_t aFlags);
+ in uint32_t aFlags,
+ in float aOpacity);
/*
* Ensures that an image is decoding. Calling this function guarantees that
* the image will at some point fire off decode notifications. Images that
* can be decoded "quickly" according to some heuristic will be decoded
* synchronously.
*
* @param aFlags Flags of the FLAG_* variety. Only FLAG_ASYNC_NOTIFY
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -6458,17 +6458,18 @@ DrawImageInternal(gfxContext&
imgIContainer* aImage,
const SamplingFilter aSamplingFilter,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsRect& aDirty,
const SVGImageContext* aSVGContext,
uint32_t aImageFlags,
- ExtendMode aExtendMode = ExtendMode::CLAMP)
+ ExtendMode aExtendMode = ExtendMode::CLAMP,
+ float aOpacity = 1.0)
{
DrawResult result = DrawResult::SUCCESS;
aImageFlags |= imgIContainer::FLAG_ASYNC_NOTIFY;
if (aPresContext->Type() == nsPresContext::eContext_Print) {
// We want vector images to be passed on as vector commands, not a raster
// image.
@@ -6499,17 +6500,17 @@ DrawImageInternal(gfxContext&
Maybe<SVGImageContext> svgContext = ToMaybe(aSVGContext);
if (!svgContext) {
// Use the default viewport.
svgContext = Some(SVGImageContext(params.svgViewportSize, Nothing()));
}
result = aImage->Draw(destCtx, params.size, params.region,
imgIContainer::FRAME_CURRENT, aSamplingFilter,
- svgContext, aImageFlags);
+ svgContext, aImageFlags, aOpacity);
}
return result;
}
/* static */ DrawResult
nsLayoutUtils::DrawSingleUnscaledImage(gfxContext& aContext,
@@ -6671,39 +6672,42 @@ nsLayoutUtils::DrawBackgroundImage(gfxCo
const CSSIntSize& aImageSize,
SamplingFilter aSamplingFilter,
const nsRect& aDest,
const nsRect& aFill,
const nsSize& aRepeatSize,
const nsPoint& aAnchor,
const nsRect& aDirty,
uint32_t aImageFlags,
- ExtendMode aExtendMode)
+ ExtendMode aExtendMode,
+ float aOpacity)
{
PROFILER_LABEL("layout", "nsLayoutUtils::DrawBackgroundImage",
js::ProfileEntry::Category::GRAPHICS);
SVGImageContext svgContext(aImageSize, Nothing());
/* Fast path when there is no need for image spacing */
if (aRepeatSize.width == aDest.width && aRepeatSize.height == aDest.height) {
return DrawImageInternal(aContext, aPresContext, aImage,
aSamplingFilter, aDest, aFill, aAnchor,
- aDirty, &svgContext, aImageFlags, aExtendMode);
+ aDirty, &svgContext, aImageFlags, aExtendMode,
+ aOpacity);
}
nsPoint firstTilePos = aDest.TopLeft() +
nsPoint(NSToIntFloor(float(aFill.x - aDest.x) / aRepeatSize.width) * aRepeatSize.width,
NSToIntFloor(float(aFill.y - aDest.y) / aRepeatSize.height) * aRepeatSize.height);
for (int32_t i = firstTilePos.x; i < aFill.XMost(); i += aRepeatSize.width) {
for (int32_t j = firstTilePos.y; j < aFill.YMost(); j += aRepeatSize.height) {
nsRect dest(i, j, aDest.width, aDest.height);
DrawResult result = DrawImageInternal(aContext, aPresContext, aImage, aSamplingFilter,
dest, dest, aAnchor, aDirty, &svgContext,
- aImageFlags, ExtendMode::CLAMP);
+ aImageFlags, ExtendMode::CLAMP,
+ aOpacity);
if (result != DrawResult::SUCCESS) {
return result;
}
}
}
return DrawResult::SUCCESS;
}
@@ -6712,21 +6716,23 @@ nsLayoutUtils::DrawBackgroundImage(gfxCo
nsLayoutUtils::DrawImage(gfxContext& aContext,
nsPresContext* aPresContext,
imgIContainer* aImage,
const SamplingFilter aSamplingFilter,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsRect& aDirty,
- uint32_t aImageFlags)
+ uint32_t aImageFlags,
+ float aOpacity)
{
return DrawImageInternal(aContext, aPresContext, aImage,
aSamplingFilter, aDest, aFill, aAnchor,
- aDirty, nullptr, aImageFlags);
+ aDirty, nullptr, aImageFlags, ExtendMode::CLAMP,
+ aOpacity);
}
/* static */ nsRect
nsLayoutUtils::GetWholeImageDestination(const nsSize& aWholeImageSize,
const nsRect& aImageSourceArea,
const nsRect& aDestArea)
{
double scaleX = double(aDestArea.width)/aImageSourceArea.width;
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1750,17 +1750,18 @@ public:
const CSSIntSize& aImageSize,
SamplingFilter aSamplingFilter,
const nsRect& aDest,
const nsRect& aFill,
const nsSize& aRepeatSize,
const nsPoint& aAnchor,
const nsRect& aDirty,
uint32_t aImageFlags,
- ExtendMode aExtendMode);
+ ExtendMode aExtendMode,
+ float aOpacity);
/**
* Draw an image.
* See https://wiki.mozilla.org/Gecko:Image_Snapping_and_Rendering
* @param aRenderingContext Where to draw the image, set up with an
* appropriate scale and transform for drawing in
* app units.
* @param aImage The image.
@@ -1775,17 +1776,18 @@ public:
static DrawResult DrawImage(gfxContext& aContext,
nsPresContext* aPresContext,
imgIContainer* aImage,
const SamplingFilter aSamplingFilter,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsRect& aDirty,
- uint32_t aImageFlags);
+ uint32_t aImageFlags,
+ float aOpacity = 1.0);
static inline void InitDashPattern(StrokeOptions& aStrokeOptions,
uint8_t aBorderStyle) {
if (aBorderStyle == NS_STYLE_BORDER_STYLE_DOTTED) {
static Float dot[] = { 1.f, 1.f };
aStrokeOptions.mDashLength = MOZ_ARRAY_LENGTH(dot);
aStrokeOptions.mDashPattern = dot;
} else if (aBorderStyle == NS_STYLE_BORDER_STYLE_DASHED) {
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -1773,41 +1773,45 @@ nsCSSRendering::PaintBoxShadowInner(nsPr
/* static */
nsCSSRendering::PaintBGParams
nsCSSRendering::PaintBGParams::ForAllLayers(nsPresContext& aPresCtx,
nsRenderingContext& aRenderingCtx,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
nsIFrame *aFrame,
- uint32_t aPaintFlags)
+ uint32_t aPaintFlags,
+ float aOpacity)
{
MOZ_ASSERT(aFrame);
- PaintBGParams result(aPresCtx, aRenderingCtx, aDirtyRect, aBorderArea, aFrame,
- aPaintFlags, -1, CompositionOp::OP_OVER);
+ PaintBGParams result(aPresCtx, aRenderingCtx, aDirtyRect, aBorderArea,
+ aFrame, aPaintFlags, -1, CompositionOp::OP_OVER,
+ aOpacity);
return result;
}
/* static */
nsCSSRendering::PaintBGParams
nsCSSRendering::PaintBGParams::ForSingleLayer(nsPresContext& aPresCtx,
nsRenderingContext& aRenderingCtx,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
nsIFrame *aFrame,
uint32_t aPaintFlags,
int32_t aLayer,
- CompositionOp aCompositionOp)
+ CompositionOp aCompositionOp,
+ float aOpacity)
{
MOZ_ASSERT(aFrame && (aLayer != -1));
- PaintBGParams result(aPresCtx, aRenderingCtx, aDirtyRect, aBorderArea, aFrame,
- aPaintFlags, aLayer, aCompositionOp);
+ PaintBGParams result(aPresCtx, aRenderingCtx, aDirtyRect, aBorderArea,
+ aFrame, aPaintFlags, aLayer, aCompositionOp,
+ aOpacity);
return result;
}
DrawResult
nsCSSRendering::PaintStyleImageLayer(const PaintBGParams& aParams)
{
PROFILER_LABEL("nsCSSRendering", "PaintBackground",
@@ -3448,17 +3452,17 @@ nsCSSRendering::PaintStyleImageLayerWith
}
result &=
state.mImageRenderer.DrawLayer(&aParams.presCtx,
aParams.renderingCtx,
state.mDestArea, state.mFillArea,
state.mAnchor + paintBorderArea.TopLeft(),
clipState.mDirtyRect,
- state.mRepeatSize);
+ state.mRepeatSize, aParams.opacity);
if (co != CompositionOp::OP_OVER) {
ctx->SetOp(CompositionOp::OP_OVER);
}
}
}
}
}
@@ -5640,17 +5644,18 @@ RGBALuminanceOperation(uint8_t *aData,
DrawResult
nsImageRenderer::Draw(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsSize& aRepeatSize,
- const CSSIntRect& aSrc)
+ const CSSIntRect& aSrc,
+ float aOpacity)
{
if (!IsReady()) {
NS_NOTREACHED("Ensure PrepareImage() has returned true before calling me");
return DrawResult::TEMPORARY_ERROR;
}
if (aDest.IsEmpty() || aFill.IsEmpty() ||
mSize.width <= 0 || mSize.height <= 0) {
return DrawResult::SUCCESS;
@@ -5691,17 +5696,17 @@ nsImageRenderer::Draw(nsPresContext*
result =
nsLayoutUtils::DrawBackgroundImage(*ctx,
aPresContext,
mImageContainer, imageSize,
samplingFilter,
aDest, aFill, aRepeatSize,
aAnchor, aDirtyRect,
ConvertImageRendererToDrawFlags(mFlags),
- mExtendMode);
+ mExtendMode, aOpacity);
break;
}
case eStyleImageType_Gradient:
{
nsCSSRendering::PaintGradient(aPresContext, aRenderingContext,
mGradientData, aDirtyRect,
aDest, aFill, aRepeatSize, aSrc, mSize);
break;
@@ -5715,17 +5720,18 @@ nsImageRenderer::Draw(nsPresContext*
return DrawResult::TEMPORARY_ERROR;
}
nsCOMPtr<imgIContainer> image(ImageOps::CreateFromDrawable(drawable));
result =
nsLayoutUtils::DrawImage(*ctx,
aPresContext, image,
samplingFilter, aDest, aFill, aAnchor, aDirtyRect,
- ConvertImageRendererToDrawFlags(mFlags));
+ ConvertImageRendererToDrawFlags(mFlags),
+ aOpacity);
break;
}
case eStyleImageType_Null:
default:
break;
}
if (!tmpDTRect.IsEmpty()) {
@@ -5787,32 +5793,34 @@ nsImageRenderer::DrawableForElement(cons
DrawResult
nsImageRenderer::DrawLayer(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsRect& aDirty,
- const nsSize& aRepeatSize)
+ const nsSize& aRepeatSize,
+ float aOpacity)
{
if (!IsReady()) {
NS_NOTREACHED("Ensure PrepareImage() has returned true before calling me");
return DrawResult::TEMPORARY_ERROR;
}
if (aDest.IsEmpty() || aFill.IsEmpty() ||
mSize.width <= 0 || mSize.height <= 0) {
return DrawResult::SUCCESS;
}
return Draw(aPresContext, aRenderingContext,
aDirty, aDest, aFill, aAnchor, aRepeatSize,
CSSIntRect(0, 0,
nsPresContext::AppUnitsToIntCSSPixels(mSize.width),
- nsPresContext::AppUnitsToIntCSSPixels(mSize.height)));
+ nsPresContext::AppUnitsToIntCSSPixels(mSize.height)),
+ aOpacity);
}
/**
* Compute the size and position of the master copy of the image. I.e., a single
* tile used to fill the dest rect.
* aFill The destination rect to be filled
* aHFill and aVFill are the repeat patterns for the component -
* NS_STYLE_BORDER_IMAGE_REPEAT_* - i.e., how a tiling unit is used to fill aFill
@@ -5995,17 +6003,17 @@ nsImageRenderer::DrawBorderImageComponen
nsRect tile = ComputeTile(fillRect, aHFill, aVFill, aUnitSize, repeatSize);
CSSIntSize imageSize(srcRect.width, srcRect.height);
return nsLayoutUtils::DrawBackgroundImage(*aRenderingContext.ThebesContext(),
aPresContext,
subImage, imageSize, samplingFilter,
tile, fillRect, repeatSize,
tile.TopLeft(), aDirtyRect,
drawFlags,
- ExtendMode::CLAMP);
+ ExtendMode::CLAMP, 1.0);
}
nsSize repeatSize(aFill.Size());
nsRect fillRect(aFill);
nsRect destTile = RequiresScaling(fillRect, aHFill, aVFill, aUnitSize)
? ComputeTile(fillRect, aHFill, aVFill, aUnitSize, repeatSize)
: fillRect;
return Draw(aPresContext, aRenderingContext, aDirtyRect, destTile,
--- a/layout/painting/nsCSSRendering.h
+++ b/layout/painting/nsCSSRendering.h
@@ -214,17 +214,18 @@ public:
* @see nsLayoutUtils::DrawImage() for parameters.
*/
DrawResult DrawLayer(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsRect& aDirty,
- const nsSize& aRepeatSize);
+ const nsSize& aRepeatSize,
+ float aOpacity);
/**
* Draw the image to a single component of a border-image style rendering.
* aFill The destination rect to be drawn into
* aSrc is the part of the image to be rendered into a tile (aUnitSize in
* aFill), if aSrc and the dest tile are different sizes, the image will be
* scaled to map aSrc onto the dest tile.
* aHFill and aVFill are the repeat patterns for the component -
@@ -276,17 +277,18 @@ private:
*/
DrawResult Draw(nsPresContext* aPresContext,
nsRenderingContext& aRenderingContext,
const nsRect& aDirtyRect,
const nsRect& aDest,
const nsRect& aFill,
const nsPoint& aAnchor,
const nsSize& aRepeatSize,
- const mozilla::CSSIntRect& aSrc);
+ const mozilla::CSSIntRect& aSrc,
+ float aOpacity = 1.0);
/**
* Helper method for creating a gfxDrawable from mPaintServerFrame or
* mImageElementSurface.
* Requires mType is eStyleImageType_Element.
* Returns null if we cannot create the drawable.
*/
already_AddRefed<gfxDrawable> DrawableForElement(const nsRect& aImageRect,
@@ -629,49 +631,54 @@ struct nsCSSRendering {
nsRect borderArea;
nsIFrame* frame;
uint32_t paintFlags;
nsRect* bgClipRect = nullptr;
int32_t layer; // -1 means painting all layers; other
// value means painting one specific
// layer only.
CompositionOp compositionOp;
+ float opacity;
static PaintBGParams ForAllLayers(nsPresContext& aPresCtx,
nsRenderingContext& aRenderingCtx,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
nsIFrame *aFrame,
- uint32_t aPaintFlags);
+ uint32_t aPaintFlags,
+ float aOpacity = 1.0);
static PaintBGParams ForSingleLayer(nsPresContext& aPresCtx,
nsRenderingContext& aRenderingCtx,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
nsIFrame *aFrame,
uint32_t aPaintFlags,
int32_t aLayer,
- CompositionOp aCompositionOp = CompositionOp::OP_OVER);
+ CompositionOp aCompositionOp = CompositionOp::OP_OVER,
+ float aOpacity = 1.0);
private:
PaintBGParams(nsPresContext& aPresCtx,
nsRenderingContext& aRenderingCtx,
const nsRect& aDirtyRect,
const nsRect& aBorderArea,
nsIFrame* aFrame,
uint32_t aPaintFlags,
int32_t aLayer,
- CompositionOp aCompositionOp)
+ CompositionOp aCompositionOp,
+ float aOpacity)
: presCtx(aPresCtx),
renderingCtx(aRenderingCtx),
dirtyRect(aDirtyRect),
borderArea(aBorderArea),
frame(aFrame),
paintFlags(aPaintFlags),
layer(aLayer),
- compositionOp(aCompositionOp) {}
+ compositionOp(aCompositionOp),
+ opacity(aOpacity) {}
};
static DrawResult PaintStyleImageLayer(const PaintBGParams& aParams);
/**
* Same as |PaintStyleImageLayer|, except using the provided style structs.
* This short-circuits the code that ensures that the root element's
--- a/widget/cocoa/nsCocoaUtils.mm
+++ b/widget/cocoa/nsCocoaUtils.mm
@@ -488,17 +488,17 @@ nsresult nsCocoaUtils::CreateNSImageFrom
RefPtr<gfxContext> context = gfxContext::CreateOrNull(drawTarget);
MOZ_ASSERT(context);
mozilla::image::DrawResult res =
aImage->Draw(context, scaledSize, ImageRegion::Create(scaledSize),
aWhichFrame, SamplingFilter::POINT,
/* no SVGImageContext */ Nothing(),
- imgIContainer::FLAG_SYNC_DECODE);
+ imgIContainer::FLAG_SYNC_DECODE, 1.0);
if (res != mozilla::image::DrawResult::SUCCESS) {
return NS_ERROR_FAILURE;
}
surface = drawTarget->Snapshot();
} else {
surface = aImage->GetFrame(aWhichFrame, imgIContainer::FLAG_SYNC_DECODE);
--- a/widget/nsBaseDragService.cpp
+++ b/widget/nsBaseDragService.cpp
@@ -752,17 +752,17 @@ nsBaseDragService::DrawDragForImage(nsPr
RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
if (!ctx)
return NS_ERROR_FAILURE;
DrawResult res =
imgContainer->Draw(ctx, destSize, ImageRegion::Create(destSize),
imgIContainer::FRAME_CURRENT,
SamplingFilter::GOOD, /* no SVGImageContext */ Nothing(),
- imgIContainer::FLAG_SYNC_DECODE);
+ imgIContainer::FLAG_SYNC_DECODE, 1.0);
if (res == DrawResult::BAD_IMAGE || res == DrawResult::BAD_ARGS) {
return NS_ERROR_FAILURE;
}
*aSurface = dt->Snapshot();
} else {
*aSurface = aCanvas->GetSurfaceSnapshot();
}