Bug 1028288 Add canvas global transparency support to svgs. r=seth

This commit is contained in:
James Kolb 2014-08-29 23:04:34 +09:00
parent f41f3ebd5b
commit 74a487913a
7 changed files with 43 additions and 17 deletions

View File

@ -9,6 +9,7 @@
#include "nsIServiceManager.h"
#include "nsMathUtils.h"
#include "SVGImageContext.h"
#include "nsContentUtils.h"
@ -3484,11 +3485,13 @@ CanvasRenderingContext2D::DrawDirectlyToCanvas(
// FLAG_CLAMP is added for increased performance, since we never tile here.
uint32_t modifiedFlags = image.mDrawingFlags | imgIContainer::FLAG_CLAMP;
SVGImageContext svgContext(scaledImageSize, Nothing(), CurrentState().globalAlpha);
nsresult rv = image.mImgContainer->
Draw(context, scaledImageSize,
ImageRegion::Create(gfxRect(src.x, src.y, src.width, src.height)),
image.mWhichFrame, GraphicsFilter::FILTER_GOOD,
Nothing(), modifiedFlags);
Some(svgContext), modifiedFlags);
NS_ENSURE_SUCCESS_VOID(rv);
}

View File

@ -31,6 +31,7 @@ gfxSurfaceDrawable::Draw(gfxContext* aContext,
const gfxRect& aFillRect,
bool aRepeat,
const GraphicsFilter& aFilter,
gfxFloat aOpacity,
const gfxMatrix& aTransform)
{
ExtendMode extend = ExtendMode::CLAMP;
@ -50,7 +51,8 @@ gfxSurfaceDrawable::Draw(gfxContext* aContext,
if (aContext->CurrentOperator() == gfxContext::OPERATOR_CLEAR) {
dt->ClearRect(fillRect);
} else if (aContext->CurrentOperator() == gfxContext::OPERATOR_SOURCE) {
} else if (aContext->CurrentOperator() == gfxContext::OPERATOR_SOURCE &&
aOpacity == 1.0) {
// Emulate cairo operator source which is bound by mask!
dt->ClearRect(fillRect);
dt->FillRect(fillRect, pattern);
@ -60,7 +62,7 @@ gfxSurfaceDrawable::Draw(gfxContext* aContext,
aContext->CurrentAntialiasMode() == gfxContext::MODE_ALIASED ?
AntialiasMode::NONE :
AntialiasMode::SUBPIXEL;
dt->FillRect(fillRect, pattern, DrawOptions(1.0f, op, aaMode));
dt->FillRect(fillRect, pattern, DrawOptions(aOpacity, op, aaMode));
}
return true;
}
@ -96,15 +98,16 @@ gfxCallbackDrawable::Draw(gfxContext* aContext,
const gfxRect& aFillRect,
bool aRepeat,
const GraphicsFilter& aFilter,
gfxFloat aOpacity,
const gfxMatrix& aTransform)
{
if (aRepeat && !mSurfaceDrawable) {
if ((aRepeat || aOpacity != 1.0) && !mSurfaceDrawable) {
mSurfaceDrawable = MakeSurfaceDrawable(aFilter);
}
if (mSurfaceDrawable)
return mSurfaceDrawable->Draw(aContext, aFillRect, aRepeat, aFilter,
aTransform);
aOpacity, aTransform);
if (mCallback)
return (*mCallback)(aContext, aFillRect, aFilter, aTransform);
@ -137,7 +140,7 @@ public:
const GraphicsFilter& aFilter,
const gfxMatrix& aTransform = gfxMatrix())
{
return mDrawable->Draw(aContext, aFillRect, false, aFilter,
return mDrawable->Draw(aContext, aFillRect, false, aFilter, 1.0,
aTransform);
}
private:
@ -159,6 +162,7 @@ gfxPatternDrawable::Draw(gfxContext* aContext,
const gfxRect& aFillRect,
bool aRepeat,
const GraphicsFilter& aFilter,
gfxFloat aOpacity,
const gfxMatrix& aTransform)
{
if (!mPattern)
@ -174,7 +178,7 @@ gfxPatternDrawable::Draw(gfxContext* aContext,
// will happen through this Draw() method with aRepeat = false.
nsRefPtr<gfxCallbackDrawable> callbackDrawable = MakeCallbackDrawable();
return callbackDrawable->Draw(aContext, aFillRect, true, aFilter,
aTransform);
aOpacity, aTransform);
}
aContext->NewPath();
@ -182,7 +186,7 @@ gfxPatternDrawable::Draw(gfxContext* aContext,
mPattern->SetMatrix(aTransform * oldMatrix);
aContext->SetPattern(mPattern);
aContext->Rectangle(aFillRect);
aContext->Fill();
aContext->FillWithOpacity(aOpacity);
mPattern->SetMatrix(oldMatrix);
return true;
}

View File

@ -38,6 +38,7 @@ public:
const gfxRect& aFillRect,
bool aRepeat,
const GraphicsFilter& aFilter,
gfxFloat aOpacity = 1.0,
const gfxMatrix& aTransform = gfxMatrix()) = 0;
virtual gfxIntSize Size() { return mSize; }
@ -62,6 +63,7 @@ public:
const gfxRect& aFillRect,
bool aRepeat,
const GraphicsFilter& aFilter,
gfxFloat aOpacity = 1.0,
const gfxMatrix& aTransform = gfxMatrix());
protected:
@ -107,6 +109,7 @@ public:
const gfxRect& aFillRect,
bool aRepeat,
const GraphicsFilter& aFilter,
gfxFloat aOpacity = 1.0,
const gfxMatrix& aTransform = gfxMatrix());
protected:
@ -130,6 +133,7 @@ public:
const gfxRect& aFillRect,
bool aRepeat,
const GraphicsFilter& aFilter,
gfxFloat aOpacity = 1.0,
const gfxMatrix& aTransform = gfxMatrix());
protected:

View File

@ -407,7 +407,7 @@ CreateSamplingRestrictedDrawable(gfxDrawable* aDrawable,
nsRefPtr<gfxContext> tmpCtx = new gfxContext(target);
tmpCtx->SetOperator(OptimalFillOperator());
aDrawable->Draw(tmpCtx, needed - needed.TopLeft(), true,
GraphicsFilter::FILTER_FAST, gfxMatrix().Translate(needed.TopLeft()));
GraphicsFilter::FILTER_FAST, 1.0, gfxMatrix().Translate(needed.TopLeft()));
RefPtr<SourceSurface> surface = target->Snapshot();
nsRefPtr<gfxDrawable> drawable = new gfxSurfaceDrawable(surface, size, gfxMatrix().Translate(-needed.TopLeft()));
@ -567,7 +567,8 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext,
const ImageRegion& aRegion,
const SurfaceFormat aFormat,
GraphicsFilter aFilter,
uint32_t aImageFlags)
uint32_t aImageFlags,
gfxFloat aOpacity)
{
PROFILER_LABEL("gfxUtils", "DrawPixelSnapped",
js::ProfileEntry::Category::GRAPHICS);
@ -617,7 +618,7 @@ gfxUtils::DrawPixelSnapped(gfxContext* aContext,
}
#endif
drawable->Draw(aContext, aRegion.Rect(), doTile, aFilter);
drawable->Draw(aContext, aRegion.Rect(), doTile, aFilter, aOpacity);
}
/* static */ int

View File

@ -81,7 +81,8 @@ public:
const ImageRegion& aRegion,
const mozilla::gfx::SurfaceFormat aFormat,
GraphicsFilter aFilter,
uint32_t aImageFlags = imgIContainer::FLAG_NONE);
uint32_t aImageFlags = imgIContainer::FLAG_NONE,
gfxFloat aOpacity = 1.0);
/**
* Clip aContext to the region aRegion.

View File

@ -779,6 +779,7 @@ struct SVGDrawingParameters
, viewportSize(aSVGContext ? aSVGContext->GetViewportSize() : aSize)
, animationTime(aAnimationTime)
, flags(aFlags)
, opacity(aSVGContext ? aSVGContext->GetGlobalOpacity() : 1.0)
{ }
gfxContext* context;
@ -790,6 +791,7 @@ struct SVGDrawingParameters
nsIntSize viewportSize;
float animationTime;
uint32_t flags;
gfxFloat opacity;
};
//******************************************************************************
@ -929,7 +931,7 @@ VectorImage::Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams)
ThebesIntSize(aParams.size),
aParams.region,
SurfaceFormat::B8G8R8A8,
aParams.filter, aParams.flags);
aParams.filter, aParams.flags, aParams.opacity);
MOZ_ASSERT(mRenderingObserver, "Should have a rendering observer by now");
mRenderingObserver->ResumeHonoringInvalidations();

View File

@ -19,12 +19,16 @@ namespace mozilla {
class SVGImageContext
{
public:
SVGImageContext() { }
SVGImageContext()
: mGlobalOpacity(1.0)
{ }
SVGImageContext(nsIntSize aViewportSize,
Maybe<SVGPreserveAspectRatio> aPreserveAspectRatio)
Maybe<SVGPreserveAspectRatio> aPreserveAspectRatio,
gfxFloat aOpacity = 1.0)
: mViewportSize(aViewportSize)
, mPreserveAspectRatio(aPreserveAspectRatio)
, mGlobalOpacity(aOpacity)
{ }
const nsIntSize& GetViewportSize() const {
@ -35,9 +39,14 @@ public:
return mPreserveAspectRatio;
}
gfxFloat GetGlobalOpacity() const {
return mGlobalOpacity;
}
bool operator==(const SVGImageContext& aOther) const {
return mViewportSize == aOther.mViewportSize &&
mPreserveAspectRatio == aOther.mPreserveAspectRatio;
mPreserveAspectRatio == aOther.mPreserveAspectRatio &&
mGlobalOpacity == aOther.mGlobalOpacity;
}
bool operator!=(const SVGImageContext& aOther) const {
@ -47,7 +56,8 @@ public:
uint32_t Hash() const {
return HashGeneric(mViewportSize.width,
mViewportSize.height,
mPreserveAspectRatio.map(HashPAR).valueOr(0));
mPreserveAspectRatio.map(HashPAR).valueOr(0),
HashBytes(&mGlobalOpacity, sizeof(gfxFloat)));
}
private:
@ -57,6 +67,7 @@ private:
nsIntSize mViewportSize;
Maybe<SVGPreserveAspectRatio> mPreserveAspectRatio;
gfxFloat mGlobalOpacity;
};
} // namespace mozilla