mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 12:51:06 +00:00
Bug 1429508 - Allow created mask surfaces to be clipped to the necessary size when replaying a recording. r=bas
Add a command CreateClippedDrawTarget to DrawTarget, which takes the max required size and a transform between this draw target and the one to be created. The created draw target may have its size clipped to the size of this draw target, transformed to the new target's space. This means that the new surface will be large enough so that it is rendered to this draw target correctly, but not necessarily any larger. Usually this will just create a draw target of the requested size, for simplicity. However, when replaying a recorded draw target we do clip the size to the base draw target's size. This is done using a DrawTargetTiled, so when applying the mask in PopLayer, we must take the SourceSurface's offset in to account. MozReview-Commit-ID: 89ONElphzLu --HG-- extra : rebase_source : 7eebeb66a2686a7b6f4ade36f3004ebb06abc2fe
This commit is contained in:
parent
4c2f14974a
commit
61cdff34c5
11
gfx/2d/2D.h
11
gfx/2d/2D.h
@ -1287,6 +1287,17 @@ public:
|
||||
return CreateSimilarDrawTarget(aSize, aFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a similar DrawTarget whose requested size may be clipped based
|
||||
* on this DrawTarget's rect transformed to the new target's space.
|
||||
*/
|
||||
virtual RefPtr<DrawTarget> CreateClippedDrawTarget(const IntSize& aMaxSize,
|
||||
const Matrix& aTransform,
|
||||
SurfaceFormat aFormat) const
|
||||
{
|
||||
return CreateSimilarDrawTarget(aMaxSize, aFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a similar draw target, but if the draw target is not backed by a
|
||||
* raster backend (for example, it is capturing or recording), force it to
|
||||
|
@ -251,9 +251,6 @@ DrawTargetRecording::DrawTargetRecording(const DrawTargetRecording *aDT,
|
||||
, mFinalDT(aDT->mFinalDT)
|
||||
, mSize(aSize)
|
||||
{
|
||||
mRecorder->RecordEvent(RecordedCreateSimilarDrawTarget(this,
|
||||
aSize,
|
||||
aFormat));
|
||||
mFormat = aFormat;
|
||||
}
|
||||
|
||||
@ -568,9 +565,20 @@ already_AddRefed<DrawTarget>
|
||||
DrawTargetRecording::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
|
||||
{
|
||||
RefPtr<DrawTarget> similarDT = new DrawTargetRecording(this, aSize, aFormat);
|
||||
mRecorder->RecordEvent(RecordedCreateSimilarDrawTarget(similarDT.get(),
|
||||
aSize,
|
||||
aFormat));
|
||||
return similarDT.forget();
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget>
|
||||
DrawTargetRecording::CreateClippedDrawTarget(const IntSize& aMaxSize, const Matrix& aTransform, SurfaceFormat aFormat) const
|
||||
{
|
||||
RefPtr<DrawTarget> similarDT = new DrawTargetRecording(this, aMaxSize, aFormat);
|
||||
mRecorder->RecordEvent(RecordedCreateClippedDrawTarget(similarDT.get(), aMaxSize, aTransform, aFormat));
|
||||
return similarDT;
|
||||
}
|
||||
|
||||
already_AddRefed<PathBuilder>
|
||||
DrawTargetRecording::CreatePathBuilder(FillRule aFillRule) const
|
||||
{
|
||||
|
@ -270,6 +270,14 @@ public:
|
||||
virtual already_AddRefed<DrawTarget>
|
||||
CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const override;
|
||||
|
||||
/**
|
||||
* Create a similar DrawTarget whose requested size may be clipped based
|
||||
* on this DrawTarget's rect transformed to the new target's space.
|
||||
*/
|
||||
virtual RefPtr<DrawTarget> CreateClippedDrawTarget(const IntSize& aMaxSize,
|
||||
const Matrix& aTransform,
|
||||
SurfaceFormat aFormat) const override;
|
||||
|
||||
/*
|
||||
* Create a path builder with the specified fillmode.
|
||||
*
|
||||
|
@ -2162,6 +2162,8 @@ DrawTargetSkia::PopLayer()
|
||||
paint.setColor(SK_ColorTRANSPARENT);
|
||||
}
|
||||
|
||||
maskMat.postTranslate(layer.mMask->GetRect().X(), layer.mMask->GetRect().Y());
|
||||
|
||||
sk_sp<SkImage> alphaMask = ExtractAlphaForSurface(layer.mMask);
|
||||
if (!alphaMask) {
|
||||
gfxDebug() << *this << ": PopLayer() failed to extract alpha for mask";
|
||||
|
@ -252,6 +252,7 @@ public:
|
||||
FILTERNODESETATTRIBUTE,
|
||||
FILTERNODESETINPUT,
|
||||
CREATESIMILARDRAWTARGET,
|
||||
CREATECLIPPEDDRAWTARGET,
|
||||
FONTDATA,
|
||||
FONTDESC,
|
||||
PUSHLAYER,
|
||||
|
@ -146,6 +146,38 @@ private:
|
||||
MOZ_IMPLICIT RecordedCreateSimilarDrawTarget(S &aStream);
|
||||
};
|
||||
|
||||
class RecordedCreateClippedDrawTarget : public RecordedEventDerived<RecordedCreateClippedDrawTarget> {
|
||||
public:
|
||||
RecordedCreateClippedDrawTarget(ReferencePtr aRefPtr, const IntSize& aMaxSize, const Matrix& aTransform, SurfaceFormat aFormat)
|
||||
: RecordedEventDerived(CREATECLIPPEDDRAWTARGET)
|
||||
, mRefPtr(aRefPtr)
|
||||
, mMaxSize(aMaxSize)
|
||||
, mTransform(aTransform)
|
||||
, mFormat(aFormat)
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool PlayEvent(Translator *aTranslator) const override;
|
||||
|
||||
template<class S>
|
||||
void Record(S &aStream) const;
|
||||
virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const override;
|
||||
|
||||
virtual std::string GetName() const override { return "CreateClippedDrawTarget"; }
|
||||
virtual ReferencePtr GetObjectRef() const override { return mRefPtr; }
|
||||
|
||||
ReferencePtr mRefPtr;
|
||||
IntSize mMaxSize;
|
||||
Matrix mTransform;
|
||||
SurfaceFormat mFormat;
|
||||
|
||||
private:
|
||||
friend class RecordedEvent;
|
||||
|
||||
template<class S>
|
||||
MOZ_IMPLICIT RecordedCreateClippedDrawTarget(S &aStream);
|
||||
};
|
||||
|
||||
class RecordedFillRect : public RecordedDrawingEvent<RecordedFillRect> {
|
||||
public:
|
||||
RecordedFillRect(DrawTarget *aDT, const Rect &aRect, const Pattern &aPattern, const DrawOptions &aOptions)
|
||||
@ -1672,6 +1704,60 @@ RecordedCreateSimilarDrawTarget::OutputSimpleEventInfo(std::stringstream &aStrin
|
||||
aStringStream << "[" << mRefPtr << "] CreateSimilarDrawTarget (Size: " << mSize.width << "x" << mSize.height << ")";
|
||||
}
|
||||
|
||||
inline bool
|
||||
RecordedCreateClippedDrawTarget::PlayEvent(Translator *aTranslator) const
|
||||
{
|
||||
const IntRect baseRect = aTranslator->GetReferenceDrawTarget()->GetRect();
|
||||
const IntRect transformedRect = RoundedToInt(mTransform.Inverse().TransformBounds(IntRectToRect(baseRect)));
|
||||
const IntRect intersection = IntRect(IntPoint(0, 0), mMaxSize).Intersect(transformedRect);
|
||||
|
||||
RefPtr<DrawTarget> newDT = aTranslator->GetReferenceDrawTarget()->CreateSimilarDrawTarget(intersection.Size(), SurfaceFormat::A8);
|
||||
// It's overkill to use a TiledDrawTarget for a single tile
|
||||
// but it was the easiest way to get the offset handling working
|
||||
gfx::TileSet tileset;
|
||||
gfx::Tile tile;
|
||||
tile.mDrawTarget = newDT;
|
||||
tile.mTileOrigin = gfx::IntPoint(intersection.X(), intersection.Y());
|
||||
tileset.mTiles = &tile;
|
||||
tileset.mTileCount = 1;
|
||||
newDT = gfx::Factory::CreateTiledDrawTarget(tileset);
|
||||
|
||||
// If we couldn't create a DrawTarget this will probably cause us to crash
|
||||
// with nullptr later in the playback, so return false to abort.
|
||||
if (!newDT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
aTranslator->AddDrawTarget(mRefPtr, newDT);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class S>
|
||||
void
|
||||
RecordedCreateClippedDrawTarget::Record(S &aStream) const
|
||||
{
|
||||
WriteElement(aStream, mRefPtr);
|
||||
WriteElement(aStream, mMaxSize);
|
||||
WriteElement(aStream, mTransform);
|
||||
WriteElement(aStream, mFormat);
|
||||
}
|
||||
|
||||
template<class S>
|
||||
RecordedCreateClippedDrawTarget::RecordedCreateClippedDrawTarget(S &aStream)
|
||||
: RecordedEventDerived(CREATECLIPPEDDRAWTARGET)
|
||||
{
|
||||
ReadElement(aStream, mRefPtr);
|
||||
ReadElement(aStream, mMaxSize);
|
||||
ReadElement(aStream, mTransform);
|
||||
ReadElement(aStream, mFormat);
|
||||
}
|
||||
|
||||
inline void
|
||||
RecordedCreateClippedDrawTarget::OutputSimpleEventInfo(std::stringstream &aStringStream) const
|
||||
{
|
||||
aStringStream << "[" << mRefPtr << "] CreateClippedDrawTarget ()";
|
||||
}
|
||||
|
||||
struct GenericPattern
|
||||
{
|
||||
GenericPattern(const PatternStorage &aStorage, Translator *aTranslator)
|
||||
@ -3321,6 +3407,7 @@ RecordedFilterNodeSetInput::OutputSimpleEventInfo(std::stringstream &aStringStre
|
||||
f(FILTERNODESETATTRIBUTE, RecordedFilterNodeSetAttribute); \
|
||||
f(FILTERNODESETINPUT, RecordedFilterNodeSetInput); \
|
||||
f(CREATESIMILARDRAWTARGET, RecordedCreateSimilarDrawTarget); \
|
||||
f(CREATECLIPPEDDRAWTARGET, RecordedCreateClippedDrawTarget); \
|
||||
f(FONTDATA, RecordedFontData); \
|
||||
f(FONTDESC, RecordedFontDescriptor); \
|
||||
f(PUSHLAYER, RecordedPushLayer); \
|
||||
|
@ -795,17 +795,22 @@ GenerateAndPushTextMask(nsIFrame* aFrame, gfxContext* aContext,
|
||||
IntRect drawRect =
|
||||
RoundedOut(ToRect(sourceCtx->GetClipExtents(gfxContext::eDeviceSpace)));
|
||||
|
||||
Matrix currentMatrix = sourceCtx->CurrentMatrix();
|
||||
Matrix maskTransform = currentMatrix *
|
||||
Matrix::Translation(-drawRect.x, -drawRect.y);
|
||||
maskTransform.Invert();
|
||||
|
||||
// Create a mask surface.
|
||||
RefPtr<DrawTarget> sourceTarget = sourceCtx->GetDrawTarget();
|
||||
RefPtr<DrawTarget> maskDT =
|
||||
sourceTarget->CreateSimilarDrawTarget(drawRect.Size(),
|
||||
sourceTarget->CreateClippedDrawTarget(drawRect.Size(),
|
||||
maskTransform * currentMatrix,
|
||||
SurfaceFormat::A8);
|
||||
if (!maskDT || !maskDT->IsValid()) {
|
||||
return false;
|
||||
}
|
||||
RefPtr<gfxContext> maskCtx = gfxContext::CreatePreservingTransformOrNull(maskDT);
|
||||
MOZ_ASSERT(maskCtx);
|
||||
Matrix currentMatrix = sourceCtx->CurrentMatrix();
|
||||
maskCtx->SetMatrix(Matrix::Translation(bounds.TopLeft().ToUnknownPoint()) *
|
||||
currentMatrix *
|
||||
Matrix::Translation(-drawRect.TopLeft()));
|
||||
@ -818,10 +823,6 @@ GenerateAndPushTextMask(nsIFrame* aFrame, gfxContext* aContext,
|
||||
|
||||
// Push the generated mask into aContext, so that the caller can pop and
|
||||
// blend with it.
|
||||
Matrix maskTransform = currentMatrix *
|
||||
Matrix::Translation(-drawRect.x, -drawRect.y);
|
||||
maskTransform.Invert();
|
||||
|
||||
RefPtr<SourceSurface> maskSurface = maskDT->Snapshot();
|
||||
sourceCtx->PushGroupForBlendBack(gfxContentType::COLOR_ALPHA, 1.0, maskSurface, maskTransform);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user