gecko-dev/gfx/2d/RecordedEventImpl.h
sotaro 9c96712d23 Bug 1887818 - Prevent to call GPUVideoImage::GetAsSourceSurface() in CanvasRenderingContext2D::DrawImage() for RemoteDecoderVideoSubDescriptor::Tnull_t if CanvasTranslator is used r=gfx-reviewers,lsalzman
GPUVideoImage::GetAsSourceSurface() is heavy weight. It seems better to prevent to call it if possible.

The change handles only a case that CanvasTranslator is used, SurfaceDescriptor is RemoteDecoderVideoSubDescriptor::Tnull_t and OptimizeShadow is not used.

DrawTargetRecording::DrawSurfaceDescriptor() also holds layers::Image of SurfaceDescriptor. It is necessary to keep the Image alive in CanvasDrawEventRecorder until end of its usage in CanvasTranslator.

Differential Revision: https://phabricator.services.mozilla.com/D205677
2024-03-28 06:24:41 +00:00

4524 lines
134 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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/. */
#ifndef MOZILLA_GFX_RECORDEDEVENTIMPL_H_
#define MOZILLA_GFX_RECORDEDEVENTIMPL_H_
#include "RecordedEvent.h"
#include "PathRecording.h"
#include "RecordingTypes.h"
#include "Tools.h"
#include "Filters.h"
#include "Logging.h"
#include "ScaledFontBase.h"
#include "SFNTData.h"
#include "mozilla/layers/LayersSurfaces.h"
namespace mozilla {
namespace gfx {
class RecordedDrawTargetCreation
: public RecordedEventDerived<RecordedDrawTargetCreation> {
public:
RecordedDrawTargetCreation(ReferencePtr aRefPtr, BackendType aType,
const IntRect& aRect, SurfaceFormat aFormat,
bool aHasExistingData = false,
SourceSurface* aExistingData = nullptr)
: RecordedEventDerived(DRAWTARGETCREATION),
mRefPtr(aRefPtr),
mBackendType(aType),
mRect(aRect),
mFormat(aFormat),
mHasExistingData(aHasExistingData),
mExistingData(aExistingData) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
virtual void OutputSimpleEventInfo(
std::stringstream& aStringStream) const override;
std::string GetName() const override { return "DrawTarget Creation"; }
ReferencePtr mRefPtr;
BackendType mBackendType;
IntRect mRect;
SurfaceFormat mFormat;
bool mHasExistingData = false;
RefPtr<SourceSurface> mExistingData;
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedDrawTargetCreation(S& aStream);
};
class RecordedDrawTargetDestruction
: public RecordedEventDerived<RecordedDrawTargetDestruction> {
public:
MOZ_IMPLICIT RecordedDrawTargetDestruction(ReferencePtr aRefPtr)
: RecordedEventDerived(DRAWTARGETDESTRUCTION),
mRefPtr(aRefPtr),
mBackendType(BackendType::NONE) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "DrawTarget Destruction"; }
ReferencePtr mRefPtr;
BackendType mBackendType;
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedDrawTargetDestruction(S& aStream);
};
class RecordedSetCurrentDrawTarget
: public RecordedEventDerived<RecordedSetCurrentDrawTarget> {
public:
MOZ_IMPLICIT RecordedSetCurrentDrawTarget(ReferencePtr aRefPtr)
: RecordedEventDerived(SETCURRENTDRAWTARGET), mRefPtr(aRefPtr) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "SetCurrentDrawTarget"; }
ReferencePtr mRefPtr;
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedSetCurrentDrawTarget(S& aStream);
};
class RecordedCreateSimilarDrawTarget
: public RecordedEventDerived<RecordedCreateSimilarDrawTarget> {
public:
RecordedCreateSimilarDrawTarget(ReferencePtr aRefPtr, const IntSize& aSize,
SurfaceFormat aFormat)
: RecordedEventDerived(CREATESIMILARDRAWTARGET),
mRefPtr(aRefPtr),
mSize(aSize),
mFormat(aFormat) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
virtual void OutputSimpleEventInfo(
std::stringstream& aStringStream) const override;
std::string GetName() const override { return "CreateSimilarDrawTarget"; }
ReferencePtr mRefPtr;
IntSize mSize;
SurfaceFormat mFormat;
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedCreateSimilarDrawTarget(S& aStream);
};
class RecordedCreateClippedDrawTarget
: public RecordedEventDerived<RecordedCreateClippedDrawTarget> {
public:
RecordedCreateClippedDrawTarget(ReferencePtr aRefPtr, const Rect& aBounds,
SurfaceFormat aFormat)
: RecordedEventDerived(CREATECLIPPEDDRAWTARGET),
mRefPtr(aRefPtr),
mBounds(aBounds),
mFormat(aFormat) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
virtual void OutputSimpleEventInfo(
std::stringstream& aStringStream) const override;
std::string GetName() const override { return "CreateClippedDrawTarget"; }
ReferencePtr mRefPtr;
Rect mBounds;
SurfaceFormat mFormat;
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedCreateClippedDrawTarget(S& aStream);
};
class RecordedCreateDrawTargetForFilter
: public RecordedEventDerived<RecordedCreateDrawTargetForFilter> {
public:
RecordedCreateDrawTargetForFilter(ReferencePtr aRefPtr,
const IntSize& aMaxSize,
SurfaceFormat aFormat, FilterNode* aFilter,
FilterNode* aSource,
const Rect& aSourceRect,
const Point& aDestPoint)
: RecordedEventDerived(CREATEDRAWTARGETFORFILTER),
mRefPtr(aRefPtr),
mMaxSize(aMaxSize),
mFormat(aFormat),
mFilter(aFilter),
mSource(aSource),
mSourceRect(aSourceRect),
mDestPoint(aDestPoint) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
virtual void OutputSimpleEventInfo(
std::stringstream& aStringStream) const override;
std::string GetName() const override {
return "CreateSimilarDrawTargetForFilter";
}
ReferencePtr mRefPtr;
IntSize mMaxSize;
SurfaceFormat mFormat;
ReferencePtr mFilter;
ReferencePtr mSource;
Rect mSourceRect;
Point mDestPoint;
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedCreateDrawTargetForFilter(S& aStream);
};
class RecordedFillRect : public RecordedEventDerived<RecordedFillRect> {
public:
RecordedFillRect(const Rect& aRect, const Pattern& aPattern,
const DrawOptions& aOptions)
: RecordedEventDerived(FILLRECT),
mRect(aRect),
mPattern(),
mOptions(aOptions) {
StorePattern(mPattern, aPattern);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "FillRect"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedFillRect(S& aStream);
Rect mRect;
PatternStorage mPattern;
DrawOptions mOptions;
};
class RecordedStrokeRect : public RecordedEventDerived<RecordedStrokeRect> {
public:
RecordedStrokeRect(const Rect& aRect, const Pattern& aPattern,
const StrokeOptions& aStrokeOptions,
const DrawOptions& aOptions)
: RecordedEventDerived(STROKERECT),
mRect(aRect),
mPattern(),
mStrokeOptions(aStrokeOptions),
mOptions(aOptions) {
StorePattern(mPattern, aPattern);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "StrokeRect"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedStrokeRect(S& aStream);
Rect mRect;
PatternStorage mPattern;
StrokeOptions mStrokeOptions;
DrawOptions mOptions;
};
class RecordedStrokeLine : public RecordedEventDerived<RecordedStrokeLine> {
public:
RecordedStrokeLine(const Point& aBegin, const Point& aEnd,
const Pattern& aPattern,
const StrokeOptions& aStrokeOptions,
const DrawOptions& aOptions)
: RecordedEventDerived(STROKELINE),
mBegin(aBegin),
mEnd(aEnd),
mPattern(),
mStrokeOptions(aStrokeOptions),
mOptions(aOptions) {
StorePattern(mPattern, aPattern);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "StrokeLine"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedStrokeLine(S& aStream);
Point mBegin;
Point mEnd;
PatternStorage mPattern;
StrokeOptions mStrokeOptions;
DrawOptions mOptions;
};
class RecordedStrokeCircle : public RecordedEventDerived<RecordedStrokeCircle> {
public:
RecordedStrokeCircle(Circle aCircle, const Pattern& aPattern,
const StrokeOptions& aStrokeOptions,
const DrawOptions& aOptions)
: RecordedEventDerived(STROKECIRCLE),
mCircle(aCircle),
mPattern(),
mStrokeOptions(aStrokeOptions),
mOptions(aOptions) {
StorePattern(mPattern, aPattern);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "StrokeCircle"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedStrokeCircle(S& aStream);
Circle mCircle;
PatternStorage mPattern;
StrokeOptions mStrokeOptions;
DrawOptions mOptions;
};
class RecordedFill : public RecordedEventDerived<RecordedFill> {
public:
RecordedFill(ReferencePtr aPath, const Pattern& aPattern,
const DrawOptions& aOptions)
: RecordedEventDerived(FILL),
mPath(aPath),
mPattern(),
mOptions(aOptions) {
StorePattern(mPattern, aPattern);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "Fill"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedFill(S& aStream);
ReferencePtr mPath;
PatternStorage mPattern;
DrawOptions mOptions;
};
class RecordedFillCircle : public RecordedEventDerived<RecordedFillCircle> {
public:
RecordedFillCircle(Circle aCircle, const Pattern& aPattern,
const DrawOptions& aOptions)
: RecordedEventDerived(FILLCIRCLE),
mCircle(aCircle),
mPattern(),
mOptions(aOptions) {
StorePattern(mPattern, aPattern);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "FillCircle"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedFillCircle(S& aStream);
Circle mCircle;
PatternStorage mPattern;
DrawOptions mOptions;
};
template <class Derived>
class RecordedDrawGlyphs : public RecordedEventDerived<Derived> {
public:
RecordedDrawGlyphs(RecordedEvent::EventType aType, ReferencePtr aScaledFont,
const Pattern& aPattern, const DrawOptions& aOptions,
const Glyph* aGlyphs, uint32_t aNumGlyphs)
: RecordedEventDerived<Derived>(aType),
mScaledFont(aScaledFont),
mPattern(),
mOptions(aOptions) {
this->StorePattern(mPattern, aPattern);
mNumGlyphs = aNumGlyphs;
mGlyphs = new Glyph[aNumGlyphs];
memcpy(mGlyphs, aGlyphs, sizeof(Glyph) * aNumGlyphs);
}
virtual ~RecordedDrawGlyphs();
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
protected:
friend class RecordedEvent;
template <class S>
RecordedDrawGlyphs(RecordedEvent::EventType aType, S& aStream);
virtual void DrawGlyphs(DrawTarget* aDT, ScaledFont* aScaledFont,
const GlyphBuffer& aBuffer,
const Pattern& aPattern) const = 0;
ReferencePtr mScaledFont;
PatternStorage mPattern;
DrawOptions mOptions;
Glyph* mGlyphs = nullptr;
uint32_t mNumGlyphs = 0;
};
class RecordedFillGlyphs : public RecordedDrawGlyphs<RecordedFillGlyphs> {
public:
RecordedFillGlyphs(ReferencePtr aScaledFont, const Pattern& aPattern,
const DrawOptions& aOptions, const Glyph* aGlyphs,
uint32_t aNumGlyphs)
: RecordedDrawGlyphs(FILLGLYPHS, aScaledFont, aPattern, aOptions, aGlyphs,
aNumGlyphs) {}
std::string GetName() const override { return "FillGlyphs"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedFillGlyphs(S& aStream)
: RecordedDrawGlyphs(FILLGLYPHS, aStream) {}
void DrawGlyphs(DrawTarget* aDT, ScaledFont* aScaledFont,
const GlyphBuffer& aBuffer,
const Pattern& aPattern) const override {
aDT->FillGlyphs(aScaledFont, aBuffer, aPattern, mOptions);
}
};
class RecordedStrokeGlyphs : public RecordedDrawGlyphs<RecordedStrokeGlyphs> {
public:
RecordedStrokeGlyphs(ReferencePtr aScaledFont, const Pattern& aPattern,
const StrokeOptions& aStrokeOptions,
const DrawOptions& aOptions, const Glyph* aGlyphs,
uint32_t aNumGlyphs)
: RecordedDrawGlyphs(STROKEGLYPHS, aScaledFont, aPattern, aOptions,
aGlyphs, aNumGlyphs),
mStrokeOptions(aStrokeOptions) {}
std::string GetName() const override { return "StrokeGlyphs"; }
template <class S>
void Record(S& aStream) const {
RecordedDrawGlyphs::Record(aStream);
RecordStrokeOptions(aStream, mStrokeOptions);
}
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedStrokeGlyphs(S& aStream)
: RecordedDrawGlyphs(STROKEGLYPHS, aStream) {
ReadStrokeOptions(aStream, mStrokeOptions);
}
void DrawGlyphs(DrawTarget* aDT, ScaledFont* aScaledFont,
const GlyphBuffer& aBuffer,
const Pattern& aPattern) const override {
aDT->StrokeGlyphs(aScaledFont, aBuffer, aPattern, mStrokeOptions, mOptions);
}
StrokeOptions mStrokeOptions;
};
class RecordedMask : public RecordedEventDerived<RecordedMask> {
public:
RecordedMask(const Pattern& aSource, const Pattern& aMask,
const DrawOptions& aOptions)
: RecordedEventDerived(MASK), mSource(), mMask(), mOptions(aOptions) {
StorePattern(mSource, aSource);
StorePattern(mMask, aMask);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "Mask"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedMask(S& aStream);
PatternStorage mSource;
PatternStorage mMask;
DrawOptions mOptions;
};
class RecordedStroke : public RecordedEventDerived<RecordedStroke> {
public:
RecordedStroke(ReferencePtr aPath, const Pattern& aPattern,
const StrokeOptions& aStrokeOptions,
const DrawOptions& aOptions)
: RecordedEventDerived(STROKE),
mPath(aPath),
mPattern(),
mStrokeOptions(aStrokeOptions),
mOptions(aOptions) {
StorePattern(mPattern, aPattern);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
virtual void OutputSimpleEventInfo(
std::stringstream& aStringStream) const override;
std::string GetName() const override { return "Stroke"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedStroke(S& aStream);
ReferencePtr mPath;
PatternStorage mPattern;
StrokeOptions mStrokeOptions;
DrawOptions mOptions;
};
class RecordedClearRect : public RecordedEventDerived<RecordedClearRect> {
public:
explicit RecordedClearRect(const Rect& aRect)
: RecordedEventDerived(CLEARRECT), mRect(aRect) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "ClearRect"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedClearRect(S& aStream);
Rect mRect;
};
class RecordedCopySurface : public RecordedEventDerived<RecordedCopySurface> {
public:
RecordedCopySurface(ReferencePtr aSourceSurface, const IntRect& aSourceRect,
const IntPoint& aDest)
: RecordedEventDerived(COPYSURFACE),
mSourceSurface(aSourceSurface),
mSourceRect(aSourceRect),
mDest(aDest) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "CopySurface"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedCopySurface(S& aStream);
ReferencePtr mSourceSurface;
IntRect mSourceRect;
IntPoint mDest;
};
class RecordedPushClip : public RecordedEventDerived<RecordedPushClip> {
public:
explicit RecordedPushClip(ReferencePtr aPath)
: RecordedEventDerived(PUSHCLIP), mPath(aPath) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "PushClip"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedPushClip(S& aStream);
ReferencePtr mPath;
};
class RecordedPushClipRect : public RecordedEventDerived<RecordedPushClipRect> {
public:
explicit RecordedPushClipRect(const Rect& aRect)
: RecordedEventDerived(PUSHCLIPRECT), mRect(aRect) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "PushClipRect"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedPushClipRect(S& aStream);
Rect mRect;
};
class RecordedPopClip : public RecordedEventDerived<RecordedPopClip> {
public:
MOZ_IMPLICIT RecordedPopClip() : RecordedEventDerived(POPCLIP) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "PopClip"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedPopClip(S& aStream);
};
class RecordedPushLayer : public RecordedEventDerived<RecordedPushLayer> {
public:
RecordedPushLayer(bool aOpaque, Float aOpacity, SourceSurface* aMask,
const Matrix& aMaskTransform, const IntRect& aBounds,
bool aCopyBackground)
: RecordedEventDerived(PUSHLAYER),
mOpaque(aOpaque),
mOpacity(aOpacity),
mMask(aMask),
mMaskTransform(aMaskTransform),
mBounds(aBounds),
mCopyBackground(aCopyBackground) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "PushLayer"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedPushLayer(S& aStream);
bool mOpaque;
Float mOpacity;
ReferencePtr mMask;
Matrix mMaskTransform;
IntRect mBounds;
bool mCopyBackground;
};
class RecordedPushLayerWithBlend
: public RecordedEventDerived<RecordedPushLayerWithBlend> {
public:
RecordedPushLayerWithBlend(bool aOpaque, Float aOpacity, SourceSurface* aMask,
const Matrix& aMaskTransform,
const IntRect& aBounds, bool aCopyBackground,
CompositionOp aCompositionOp)
: RecordedEventDerived(PUSHLAYERWITHBLEND),
mOpaque(aOpaque),
mOpacity(aOpacity),
mMask(aMask),
mMaskTransform(aMaskTransform),
mBounds(aBounds),
mCopyBackground(aCopyBackground),
mCompositionOp(aCompositionOp) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
virtual void OutputSimpleEventInfo(
std::stringstream& aStringStream) const override;
std::string GetName() const override { return "PushLayerWithBlend"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedPushLayerWithBlend(S& aStream);
bool mOpaque;
Float mOpacity;
ReferencePtr mMask;
Matrix mMaskTransform;
IntRect mBounds;
bool mCopyBackground;
CompositionOp mCompositionOp;
};
class RecordedPopLayer : public RecordedEventDerived<RecordedPopLayer> {
public:
RecordedPopLayer() : RecordedEventDerived(POPLAYER) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "PopLayer"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedPopLayer(S& aStream);
};
class RecordedSetPermitSubpixelAA
: public RecordedEventDerived<RecordedSetPermitSubpixelAA> {
public:
explicit RecordedSetPermitSubpixelAA(bool aPermitSubpixelAA)
: RecordedEventDerived(SETPERMITSUBPIXELAA),
mPermitSubpixelAA(aPermitSubpixelAA) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "SetPermitSubpixelAA"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedSetPermitSubpixelAA(S& aStream);
bool mPermitSubpixelAA = false;
};
class RecordedSetTransform : public RecordedEventDerived<RecordedSetTransform> {
public:
explicit RecordedSetTransform(const Matrix& aTransform)
: RecordedEventDerived(SETTRANSFORM), mTransform(aTransform) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "SetTransform"; }
Matrix mTransform;
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedSetTransform(S& aStream);
};
class RecordedDrawSurface : public RecordedEventDerived<RecordedDrawSurface> {
public:
RecordedDrawSurface(ReferencePtr aRefSource, const Rect& aDest,
const Rect& aSource, const DrawSurfaceOptions& aDSOptions,
const DrawOptions& aOptions)
: RecordedEventDerived(DRAWSURFACE),
mRefSource(aRefSource),
mDest(aDest),
mSource(aSource),
mDSOptions(aDSOptions),
mOptions(aOptions) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "DrawSurface"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedDrawSurface(S& aStream);
ReferencePtr mRefSource;
Rect mDest;
Rect mSource;
DrawSurfaceOptions mDSOptions;
DrawOptions mOptions;
};
class RecordedDrawSurfaceDescriptor
: public RecordedEventDerived<RecordedDrawSurfaceDescriptor> {
public:
RecordedDrawSurfaceDescriptor(const layers::SurfaceDescriptor& aDesc,
const Rect& aDest, const Rect& aSource,
const DrawSurfaceOptions& aDSOptions,
const DrawOptions& aOptions)
: RecordedEventDerived(DRAWSURFACEDESCRIPTOR),
mDesc(aDesc),
mDest(aDest),
mSource(aSource),
mDSOptions(aDSOptions),
mOptions(aOptions) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "DrawSurfaceDescriptor"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedDrawSurfaceDescriptor(S& aStream);
layers::SurfaceDescriptor mDesc;
Rect mDest;
Rect mSource;
DrawSurfaceOptions mDSOptions;
DrawOptions mOptions;
};
class RecordedDrawDependentSurface
: public RecordedEventDerived<RecordedDrawDependentSurface> {
public:
RecordedDrawDependentSurface(uint64_t aId, const Rect& aDest)
: RecordedEventDerived(DRAWDEPENDENTSURFACE), mId(aId), mDest(aDest) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "DrawDependentSurface"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedDrawDependentSurface(S& aStream);
uint64_t mId;
Rect mDest;
};
class RecordedDrawSurfaceWithShadow
: public RecordedEventDerived<RecordedDrawSurfaceWithShadow> {
public:
RecordedDrawSurfaceWithShadow(ReferencePtr aRefSource, const Point& aDest,
const ShadowOptions& aShadow, CompositionOp aOp)
: RecordedEventDerived(DRAWSURFACEWITHSHADOW),
mRefSource(aRefSource),
mDest(aDest),
mShadow(aShadow),
mOp(aOp) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "DrawSurfaceWithShadow"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedDrawSurfaceWithShadow(S& aStream);
ReferencePtr mRefSource;
Point mDest;
ShadowOptions mShadow;
CompositionOp mOp;
};
class RecordedDrawShadow : public RecordedEventDerived<RecordedDrawShadow> {
public:
RecordedDrawShadow(ReferencePtr aPath, const Pattern& aPattern,
const ShadowOptions& aShadow, const DrawOptions& aOptions,
const StrokeOptions* aStrokeOptions)
: RecordedEventDerived(DRAWSHADOW),
mPath(aPath),
mPattern(),
mShadow(aShadow),
mOptions(aOptions),
mHasStrokeOptions(!!aStrokeOptions),
mStrokeOptions(aStrokeOptions ? *aStrokeOptions : StrokeOptions()) {
StorePattern(mPattern, aPattern);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "DrawShadow"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedDrawShadow(S& aStream);
ReferencePtr mPath;
PatternStorage mPattern;
ShadowOptions mShadow;
DrawOptions mOptions;
bool mHasStrokeOptions;
StrokeOptions mStrokeOptions;
};
class RecordedDrawFilter : public RecordedEventDerived<RecordedDrawFilter> {
public:
RecordedDrawFilter(ReferencePtr aNode, const Rect& aSourceRect,
const Point& aDestPoint, const DrawOptions& aOptions)
: RecordedEventDerived(DRAWFILTER),
mNode(aNode),
mSourceRect(aSourceRect),
mDestPoint(aDestPoint),
mOptions(aOptions) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "DrawFilter"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedDrawFilter(S& aStream);
ReferencePtr mNode;
Rect mSourceRect;
Point mDestPoint;
DrawOptions mOptions;
};
class RecordedPathCreation : public RecordedEventDerived<RecordedPathCreation> {
public:
MOZ_IMPLICIT RecordedPathCreation(PathRecording* aPath);
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "Path Creation"; }
private:
friend class RecordedEvent;
ReferencePtr mDT;
ReferencePtr mRefPtr;
FillRule mFillRule;
RefPtr<PathRecording> mPath;
UniquePtr<PathOps> mPathOps;
template <class S>
MOZ_IMPLICIT RecordedPathCreation(S& aStream);
};
class RecordedPathDestruction
: public RecordedEventDerived<RecordedPathDestruction> {
public:
MOZ_IMPLICIT RecordedPathDestruction(PathRecording* aPath)
: RecordedEventDerived(PATHDESTRUCTION), mRefPtr(aPath) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "Path Destruction"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
template <class S>
MOZ_IMPLICIT RecordedPathDestruction(S& aStream);
};
class RecordedSourceSurfaceCreation
: public RecordedEventDerived<RecordedSourceSurfaceCreation> {
public:
RecordedSourceSurfaceCreation(ReferencePtr aRefPtr, uint8_t* aData,
int32_t aStride, const IntSize& aSize,
SurfaceFormat aFormat)
: RecordedEventDerived(SOURCESURFACECREATION),
mRefPtr(aRefPtr),
mData(aData),
mStride(aStride),
mSize(aSize),
mFormat(aFormat),
mDataOwned(false) {}
~RecordedSourceSurfaceCreation();
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "SourceSurface Creation"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
uint8_t* mData = nullptr;
int32_t mStride;
IntSize mSize;
SurfaceFormat mFormat;
mutable bool mDataOwned;
template <class S>
MOZ_IMPLICIT RecordedSourceSurfaceCreation(S& aStream);
};
class RecordedSourceSurfaceDestruction
: public RecordedEventDerived<RecordedSourceSurfaceDestruction> {
public:
MOZ_IMPLICIT RecordedSourceSurfaceDestruction(ReferencePtr aRefPtr)
: RecordedEventDerived(SOURCESURFACEDESTRUCTION), mRefPtr(aRefPtr) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "SourceSurface Destruction"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
template <class S>
MOZ_IMPLICIT RecordedSourceSurfaceDestruction(S& aStream);
};
class RecordedOptimizeSourceSurface
: public RecordedEventDerived<RecordedOptimizeSourceSurface> {
public:
RecordedOptimizeSourceSurface(ReferencePtr aSurface,
ReferencePtr aOptimizedSurface)
: RecordedEventDerived(OPTIMIZESOURCESURFACE),
mSurface(aSurface),
mOptimizedSurface(aOptimizedSurface) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "OptimizeSourceSurface"; }
private:
friend class RecordedEvent;
ReferencePtr mSurface;
ReferencePtr mOptimizedSurface;
template <class S>
MOZ_IMPLICIT RecordedOptimizeSourceSurface(S& aStream);
};
class RecordedExternalSurfaceCreation
: public RecordedEventDerived<RecordedExternalSurfaceCreation> {
public:
RecordedExternalSurfaceCreation(ReferencePtr aRefPtr, const uint64_t aKey)
: RecordedEventDerived(EXTERNALSURFACECREATION),
mRefPtr(aRefPtr),
mKey(aKey) {}
~RecordedExternalSurfaceCreation() = default;
virtual bool PlayEvent(Translator* aTranslator) const;
template <class S>
void Record(S& aStream) const;
virtual void OutputSimpleEventInfo(std::stringstream& aStringStream) const;
virtual std::string GetName() const {
return "SourceSurfaceSharedData Creation";
}
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
uint64_t mKey;
template <class S>
MOZ_IMPLICIT RecordedExternalSurfaceCreation(S& aStream);
};
class RecordedFilterNodeCreation
: public RecordedEventDerived<RecordedFilterNodeCreation> {
public:
RecordedFilterNodeCreation(ReferencePtr aRefPtr, FilterType aType)
: RecordedEventDerived(FILTERNODECREATION),
mRefPtr(aRefPtr),
mType(aType) {}
~RecordedFilterNodeCreation();
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "FilterNode Creation"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
FilterType mType;
template <class S>
MOZ_IMPLICIT RecordedFilterNodeCreation(S& aStream);
};
class RecordedFilterNodeDestruction
: public RecordedEventDerived<RecordedFilterNodeDestruction> {
public:
MOZ_IMPLICIT RecordedFilterNodeDestruction(ReferencePtr aRefPtr)
: RecordedEventDerived(FILTERNODEDESTRUCTION), mRefPtr(aRefPtr) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "FilterNode Destruction"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
template <class S>
MOZ_IMPLICIT RecordedFilterNodeDestruction(S& aStream);
};
class RecordedGradientStopsCreation
: public RecordedEventDerived<RecordedGradientStopsCreation> {
public:
RecordedGradientStopsCreation(ReferencePtr aRefPtr, GradientStop* aStops,
uint32_t aNumStops, ExtendMode aExtendMode)
: RecordedEventDerived(GRADIENTSTOPSCREATION),
mRefPtr(aRefPtr),
mStops(aStops),
mNumStops(aNumStops),
mExtendMode(aExtendMode),
mDataOwned(false) {}
~RecordedGradientStopsCreation();
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "GradientStops Creation"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
GradientStop* mStops = nullptr;
uint32_t mNumStops = 0;
ExtendMode mExtendMode;
bool mDataOwned;
template <class S>
MOZ_IMPLICIT RecordedGradientStopsCreation(S& aStream);
};
class RecordedGradientStopsDestruction
: public RecordedEventDerived<RecordedGradientStopsDestruction> {
public:
MOZ_IMPLICIT RecordedGradientStopsDestruction(ReferencePtr aRefPtr)
: RecordedEventDerived(GRADIENTSTOPSDESTRUCTION), mRefPtr(aRefPtr) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "GradientStops Destruction"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
template <class S>
MOZ_IMPLICIT RecordedGradientStopsDestruction(S& aStream);
};
class RecordedFlush : public RecordedEventDerived<RecordedFlush> {
public:
explicit RecordedFlush() : RecordedEventDerived(FLUSH) {}
bool PlayEvent(Translator* aTranslator) const final;
template <class S>
void Record(S& aStream) const;
virtual void OutputSimpleEventInfo(
std::stringstream& aStringStream) const override;
virtual std::string GetName() const override { return "Flush"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedFlush(S& aStream);
};
class RecordedDetachAllSnapshots
: public RecordedEventDerived<RecordedDetachAllSnapshots> {
public:
explicit RecordedDetachAllSnapshots()
: RecordedEventDerived(DETACHALLSNAPSHOTS) {}
bool PlayEvent(Translator* aTranslator) const final;
template <class S>
void Record(S& aStream) const;
virtual void OutputSimpleEventInfo(
std::stringstream& aStringStream) const override;
virtual std::string GetName() const override { return "DetachAllSnapshots"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedDetachAllSnapshots(S& aStream);
};
class RecordedSnapshot : public RecordedEventDerived<RecordedSnapshot> {
public:
explicit RecordedSnapshot(ReferencePtr aRefPtr)
: RecordedEventDerived(SNAPSHOT), mRefPtr(aRefPtr) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "Snapshot"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
template <class S>
MOZ_IMPLICIT RecordedSnapshot(S& aStream);
};
class RecordedIntoLuminanceSource
: public RecordedEventDerived<RecordedIntoLuminanceSource> {
public:
RecordedIntoLuminanceSource(ReferencePtr aRefPtr,
LuminanceType aLuminanceType, float aOpacity)
: RecordedEventDerived(INTOLUMINANCE),
mRefPtr(aRefPtr),
mLuminanceType(aLuminanceType),
mOpacity(aOpacity) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "IntoLuminanceSource"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
LuminanceType mLuminanceType;
float mOpacity;
template <class S>
MOZ_IMPLICIT RecordedIntoLuminanceSource(S& aStream);
};
class RecordedExtractSubrect
: public RecordedEventDerived<RecordedExtractSubrect> {
public:
RecordedExtractSubrect(ReferencePtr aRefPtr, ReferencePtr aSourceSurface,
const IntRect& aSubrect)
: RecordedEventDerived(EXTRACTSUBRECT),
mRefPtr(aRefPtr),
mSourceSurface(aSourceSurface),
mSubrect(aSubrect) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "ExtractSubrect"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
ReferencePtr mSourceSurface;
IntRect mSubrect;
template <class S>
MOZ_IMPLICIT RecordedExtractSubrect(S& aStream);
};
class RecordedFontData : public RecordedEventDerived<RecordedFontData> {
public:
static void FontDataProc(const uint8_t* aData, uint32_t aSize,
uint32_t aIndex, void* aBaton) {
auto recordedFontData = static_cast<RecordedFontData*>(aBaton);
recordedFontData->SetFontData(aData, aSize, aIndex);
}
explicit RecordedFontData(UnscaledFont* aUnscaledFont)
: RecordedEventDerived(FONTDATA),
mType(aUnscaledFont->GetType()),
mFontDetails() {
mGetFontFileDataSucceeded =
aUnscaledFont->GetFontFileData(&FontDataProc, this) && mData;
}
virtual ~RecordedFontData();
bool IsValid() const { return mGetFontFileDataSucceeded; }
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "Font Data"; }
void SetFontData(const uint8_t* aData, uint32_t aSize, uint32_t aIndex);
bool GetFontDetails(RecordedFontDetails& fontDetails);
private:
friend class RecordedEvent;
FontType mType;
uint8_t* mData = nullptr;
RecordedFontDetails mFontDetails;
bool mGetFontFileDataSucceeded;
template <class S>
MOZ_IMPLICIT RecordedFontData(S& aStream);
};
class RecordedFontDescriptor
: public RecordedEventDerived<RecordedFontDescriptor> {
public:
static void FontDescCb(const uint8_t* aData, uint32_t aSize, uint32_t aIndex,
void* aBaton) {
auto recordedFontDesc = static_cast<RecordedFontDescriptor*>(aBaton);
recordedFontDesc->SetFontDescriptor(aData, aSize, aIndex);
}
explicit RecordedFontDescriptor(UnscaledFont* aUnscaledFont)
: RecordedEventDerived(FONTDESC),
mType(aUnscaledFont->GetType()),
mIndex(0),
mRefPtr(aUnscaledFont) {
mHasDesc = aUnscaledFont->GetFontDescriptor(FontDescCb, this);
}
virtual ~RecordedFontDescriptor();
bool IsValid() const { return mHasDesc; }
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "Font Desc"; }
private:
friend class RecordedEvent;
void SetFontDescriptor(const uint8_t* aData, uint32_t aSize, uint32_t aIndex);
bool mHasDesc;
FontType mType;
std::vector<uint8_t> mData;
uint32_t mIndex;
ReferencePtr mRefPtr;
template <class S>
MOZ_IMPLICIT RecordedFontDescriptor(S& aStream);
};
class RecordedUnscaledFontCreation
: public RecordedEventDerived<RecordedUnscaledFontCreation> {
public:
static void FontInstanceDataProc(const uint8_t* aData, uint32_t aSize,
void* aBaton) {
auto recordedUnscaledFontCreation =
static_cast<RecordedUnscaledFontCreation*>(aBaton);
recordedUnscaledFontCreation->SetFontInstanceData(aData, aSize);
}
RecordedUnscaledFontCreation(UnscaledFont* aUnscaledFont,
RecordedFontDetails aFontDetails)
: RecordedEventDerived(UNSCALEDFONTCREATION),
mRefPtr(aUnscaledFont),
mFontDataKey(aFontDetails.fontDataKey),
mIndex(aFontDetails.index) {
aUnscaledFont->GetFontInstanceData(FontInstanceDataProc, this);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "UnscaledFont Creation"; }
void SetFontInstanceData(const uint8_t* aData, uint32_t aSize);
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
uint64_t mFontDataKey;
uint32_t mIndex;
std::vector<uint8_t> mInstanceData;
template <class S>
MOZ_IMPLICIT RecordedUnscaledFontCreation(S& aStream);
};
class RecordedUnscaledFontDestruction
: public RecordedEventDerived<RecordedUnscaledFontDestruction> {
public:
MOZ_IMPLICIT RecordedUnscaledFontDestruction(ReferencePtr aRefPtr)
: RecordedEventDerived(UNSCALEDFONTDESTRUCTION), mRefPtr(aRefPtr) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "UnscaledFont Destruction"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
template <class S>
MOZ_IMPLICIT RecordedUnscaledFontDestruction(S& aStream);
};
class RecordedScaledFontCreation
: public RecordedEventDerived<RecordedScaledFontCreation> {
public:
static void FontInstanceDataProc(const uint8_t* aData, uint32_t aSize,
const FontVariation* aVariations,
uint32_t aNumVariations, void* aBaton) {
auto recordedScaledFontCreation =
static_cast<RecordedScaledFontCreation*>(aBaton);
recordedScaledFontCreation->SetFontInstanceData(aData, aSize, aVariations,
aNumVariations);
}
RecordedScaledFontCreation(ScaledFont* aScaledFont,
UnscaledFont* aUnscaledFont)
: RecordedEventDerived(SCALEDFONTCREATION),
mRefPtr(aScaledFont),
mUnscaledFont(aUnscaledFont),
mGlyphSize(aScaledFont->GetSize()) {
aScaledFont->GetFontInstanceData(FontInstanceDataProc, this);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "ScaledFont Creation"; }
void SetFontInstanceData(const uint8_t* aData, uint32_t aSize,
const FontVariation* aVariations,
uint32_t aNumVariations);
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
ReferencePtr mUnscaledFont;
Float mGlyphSize;
std::vector<uint8_t> mInstanceData;
std::vector<FontVariation> mVariations;
template <class S>
MOZ_IMPLICIT RecordedScaledFontCreation(S& aStream);
};
class RecordedScaledFontDestruction
: public RecordedEventDerived<RecordedScaledFontDestruction> {
public:
MOZ_IMPLICIT RecordedScaledFontDestruction(ReferencePtr aRefPtr)
: RecordedEventDerived(SCALEDFONTDESTRUCTION), mRefPtr(aRefPtr) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "ScaledFont Destruction"; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
template <class S>
MOZ_IMPLICIT RecordedScaledFontDestruction(S& aStream);
};
class RecordedMaskSurface : public RecordedEventDerived<RecordedMaskSurface> {
public:
RecordedMaskSurface(const Pattern& aPattern, ReferencePtr aRefMask,
const Point& aOffset, const DrawOptions& aOptions)
: RecordedEventDerived(MASKSURFACE),
mPattern(),
mRefMask(aRefMask),
mOffset(aOffset),
mOptions(aOptions) {
StorePattern(mPattern, aPattern);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "MaskSurface"; }
private:
friend class RecordedEvent;
template <class S>
MOZ_IMPLICIT RecordedMaskSurface(S& aStream);
PatternStorage mPattern;
ReferencePtr mRefMask;
Point mOffset;
DrawOptions mOptions;
};
class RecordedFilterNodeSetAttribute
: public RecordedEventDerived<RecordedFilterNodeSetAttribute> {
public:
enum ArgType {
ARGTYPE_UINT32,
ARGTYPE_BOOL,
ARGTYPE_FLOAT,
ARGTYPE_SIZE,
ARGTYPE_INTSIZE,
ARGTYPE_INTPOINT,
ARGTYPE_RECT,
ARGTYPE_INTRECT,
ARGTYPE_POINT,
ARGTYPE_MATRIX,
ARGTYPE_MATRIX5X4,
ARGTYPE_POINT3D,
ARGTYPE_COLOR,
ARGTYPE_FLOAT_ARRAY
};
template <typename T>
RecordedFilterNodeSetAttribute(FilterNode* aNode, uint32_t aIndex,
T aArgument, ArgType aArgType)
: RecordedEventDerived(FILTERNODESETATTRIBUTE),
mNode(aNode),
mIndex(aIndex),
mArgType(aArgType) {
mPayload.resize(sizeof(T));
memcpy(&mPayload.front(), &aArgument, sizeof(T));
}
RecordedFilterNodeSetAttribute(FilterNode* aNode, uint32_t aIndex,
const Float* aFloat, uint32_t aSize)
: RecordedEventDerived(FILTERNODESETATTRIBUTE),
mNode(aNode),
mIndex(aIndex),
mArgType(ARGTYPE_FLOAT_ARRAY) {
mPayload.resize(sizeof(Float) * aSize);
memcpy(&mPayload.front(), aFloat, sizeof(Float) * aSize);
}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "SetAttribute"; }
private:
friend class RecordedEvent;
ReferencePtr mNode;
uint32_t mIndex;
ArgType mArgType;
std::vector<uint8_t> mPayload;
template <class S>
MOZ_IMPLICIT RecordedFilterNodeSetAttribute(S& aStream);
};
class RecordedFilterNodeSetInput
: public RecordedEventDerived<RecordedFilterNodeSetInput> {
public:
RecordedFilterNodeSetInput(FilterNode* aNode, uint32_t aIndex,
FilterNode* aInputNode)
: RecordedEventDerived(FILTERNODESETINPUT),
mNode(aNode),
mIndex(aIndex),
mInputFilter(aInputNode),
mInputSurface(nullptr) {}
RecordedFilterNodeSetInput(FilterNode* aNode, uint32_t aIndex,
SourceSurface* aInputSurface)
: RecordedEventDerived(FILTERNODESETINPUT),
mNode(aNode),
mIndex(aIndex),
mInputFilter(nullptr),
mInputSurface(aInputSurface) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "SetInput"; }
private:
friend class RecordedEvent;
ReferencePtr mNode;
uint32_t mIndex;
ReferencePtr mInputFilter;
ReferencePtr mInputSurface;
template <class S>
MOZ_IMPLICIT RecordedFilterNodeSetInput(S& aStream);
};
class RecordedLink : public RecordedEventDerived<RecordedLink> {
public:
RecordedLink(const char* aDestination, const Rect& aRect)
: RecordedEventDerived(LINK), mDestination(aDestination), mRect(aRect) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "Link"; }
private:
friend class RecordedEvent;
std::string mDestination;
Rect mRect;
template <class S>
MOZ_IMPLICIT RecordedLink(S& aStream);
};
class RecordedDestination : public RecordedEventDerived<RecordedDestination> {
public:
RecordedDestination(const char* aDestination, const Point& aPoint)
: RecordedEventDerived(DESTINATION),
mDestination(aDestination),
mPoint(aPoint) {}
bool PlayEvent(Translator* aTranslator) const override;
template <class S>
void Record(S& aStream) const;
void OutputSimpleEventInfo(std::stringstream& aStringStream) const override;
std::string GetName() const override { return "Destination"; }
private:
friend class RecordedEvent;
std::string mDestination;
Point mPoint;
template <class S>
MOZ_IMPLICIT RecordedDestination(S& aStream);
};
static std::string NameFromBackend(BackendType aType) {
switch (aType) {
case BackendType::NONE:
return "None";
case BackendType::DIRECT2D:
return "Direct2D";
default:
return "Unknown";
}
}
template <class S>
void RecordedEvent::RecordPatternData(S& aStream,
const PatternStorage& aPattern) const {
WriteElement(aStream, aPattern.mType);
switch (aPattern.mType) {
case PatternType::COLOR: {
WriteElement(aStream, *reinterpret_cast<const ColorPatternStorage*>(
&aPattern.mStorage));
return;
}
case PatternType::LINEAR_GRADIENT: {
WriteElement(aStream,
*reinterpret_cast<const LinearGradientPatternStorage*>(
&aPattern.mStorage));
return;
}
case PatternType::RADIAL_GRADIENT: {
WriteElement(aStream,
*reinterpret_cast<const RadialGradientPatternStorage*>(
&aPattern.mStorage));
return;
}
case PatternType::CONIC_GRADIENT: {
WriteElement(aStream,
*reinterpret_cast<const ConicGradientPatternStorage*>(
&aPattern.mStorage));
return;
}
case PatternType::SURFACE: {
WriteElement(aStream, *reinterpret_cast<const SurfacePatternStorage*>(
&aPattern.mStorage));
return;
}
default:
return;
}
}
template <class S>
void RecordedEvent::ReadPatternData(S& aStream,
PatternStorage& aPattern) const {
ReadElementConstrained(aStream, aPattern.mType, PatternType::COLOR,
kHighestPatternType);
switch (aPattern.mType) {
case PatternType::COLOR: {
ReadElement(aStream,
*reinterpret_cast<ColorPatternStorage*>(&aPattern.mStorage));
return;
}
case PatternType::LINEAR_GRADIENT: {
ReadElement(aStream, *reinterpret_cast<LinearGradientPatternStorage*>(
&aPattern.mStorage));
return;
}
case PatternType::RADIAL_GRADIENT: {
ReadElement(aStream, *reinterpret_cast<RadialGradientPatternStorage*>(
&aPattern.mStorage));
return;
}
case PatternType::CONIC_GRADIENT: {
ReadElement(aStream, *reinterpret_cast<ConicGradientPatternStorage*>(
&aPattern.mStorage));
return;
}
case PatternType::SURFACE: {
SurfacePatternStorage* sps =
reinterpret_cast<SurfacePatternStorage*>(&aPattern.mStorage);
ReadElement(aStream, *sps);
if (sps->mExtend < ExtendMode::CLAMP ||
sps->mExtend > ExtendMode::REFLECT) {
aStream.SetIsBad();
return;
}
if (sps->mSamplingFilter < SamplingFilter::GOOD ||
sps->mSamplingFilter >= SamplingFilter::SENTINEL) {
aStream.SetIsBad();
}
return;
}
default:
return;
}
}
inline void RecordedEvent::StorePattern(PatternStorage& aDestination,
const Pattern& aSource) const {
aDestination.mType = aSource.GetType();
switch (aSource.GetType()) {
case PatternType::COLOR: {
reinterpret_cast<ColorPatternStorage*>(&aDestination.mStorage)->mColor =
static_cast<const ColorPattern*>(&aSource)->mColor;
return;
}
case PatternType::LINEAR_GRADIENT: {
LinearGradientPatternStorage* store =
reinterpret_cast<LinearGradientPatternStorage*>(
&aDestination.mStorage);
const LinearGradientPattern* pat =
static_cast<const LinearGradientPattern*>(&aSource);
store->mBegin = pat->mBegin;
store->mEnd = pat->mEnd;
store->mMatrix = pat->mMatrix;
store->mStops = pat->mStops.get();
return;
}
case PatternType::RADIAL_GRADIENT: {
RadialGradientPatternStorage* store =
reinterpret_cast<RadialGradientPatternStorage*>(
&aDestination.mStorage);
const RadialGradientPattern* pat =
static_cast<const RadialGradientPattern*>(&aSource);
store->mCenter1 = pat->mCenter1;
store->mCenter2 = pat->mCenter2;
store->mRadius1 = pat->mRadius1;
store->mRadius2 = pat->mRadius2;
store->mMatrix = pat->mMatrix;
store->mStops = pat->mStops.get();
return;
}
case PatternType::CONIC_GRADIENT: {
ConicGradientPatternStorage* store =
reinterpret_cast<ConicGradientPatternStorage*>(
&aDestination.mStorage);
const ConicGradientPattern* pat =
static_cast<const ConicGradientPattern*>(&aSource);
store->mCenter = pat->mCenter;
store->mAngle = pat->mAngle;
store->mStartOffset = pat->mStartOffset;
store->mEndOffset = pat->mEndOffset;
store->mMatrix = pat->mMatrix;
store->mStops = pat->mStops.get();
return;
}
case PatternType::SURFACE: {
SurfacePatternStorage* store =
reinterpret_cast<SurfacePatternStorage*>(&aDestination.mStorage);
const SurfacePattern* pat = static_cast<const SurfacePattern*>(&aSource);
store->mExtend = pat->mExtendMode;
store->mSamplingFilter = pat->mSamplingFilter;
store->mMatrix = pat->mMatrix;
store->mSurface = pat->mSurface;
store->mSamplingRect = pat->mSamplingRect;
return;
}
}
}
template <class S>
void RecordedEvent::RecordStrokeOptions(
S& aStream, const StrokeOptions& aStrokeOptions) const {
JoinStyle joinStyle = aStrokeOptions.mLineJoin;
CapStyle capStyle = aStrokeOptions.mLineCap;
WriteElement(aStream, uint64_t(aStrokeOptions.mDashLength));
WriteElement(aStream, aStrokeOptions.mLineWidth);
WriteElement(aStream, aStrokeOptions.mMiterLimit);
WriteElement(aStream, joinStyle);
WriteElement(aStream, capStyle);
if (!aStrokeOptions.mDashPattern) {
return;
}
WriteElement(aStream, aStrokeOptions.mDashOffset);
aStream.write((char*)aStrokeOptions.mDashPattern,
sizeof(Float) * aStrokeOptions.mDashLength);
}
template <class S>
void RecordedEvent::ReadStrokeOptions(S& aStream,
StrokeOptions& aStrokeOptions) {
uint64_t dashLength;
JoinStyle joinStyle;
CapStyle capStyle;
ReadElement(aStream, dashLength);
ReadElement(aStream, aStrokeOptions.mLineWidth);
ReadElement(aStream, aStrokeOptions.mMiterLimit);
ReadElementConstrained(aStream, joinStyle, JoinStyle::BEVEL,
JoinStyle::MITER_OR_BEVEL);
ReadElementConstrained(aStream, capStyle, CapStyle::BUTT, CapStyle::SQUARE);
// On 32 bit we truncate the value of dashLength.
// See also bug 811850 for history.
aStrokeOptions.mDashLength = size_t(dashLength);
aStrokeOptions.mLineJoin = joinStyle;
aStrokeOptions.mLineCap = capStyle;
if (!aStrokeOptions.mDashLength || !aStream.good()) {
return;
}
ReadElement(aStream, aStrokeOptions.mDashOffset);
mDashPatternStorage.resize(aStrokeOptions.mDashLength);
aStrokeOptions.mDashPattern = &mDashPatternStorage.front();
aStream.read((char*)aStrokeOptions.mDashPattern,
sizeof(Float) * aStrokeOptions.mDashLength);
}
template <class S>
static void ReadDrawOptions(S& aStream, DrawOptions& aDrawOptions) {
ReadElement(aStream, aDrawOptions);
if (aDrawOptions.mAntialiasMode < AntialiasMode::NONE ||
aDrawOptions.mAntialiasMode > AntialiasMode::DEFAULT) {
aStream.SetIsBad();
return;
}
if (aDrawOptions.mCompositionOp < CompositionOp::OP_CLEAR ||
aDrawOptions.mCompositionOp > CompositionOp::OP_COUNT) {
aStream.SetIsBad();
}
}
template <class S>
static void ReadDrawSurfaceOptions(S& aStream,
DrawSurfaceOptions& aDrawSurfaceOptions) {
ReadElement(aStream, aDrawSurfaceOptions);
if (aDrawSurfaceOptions.mSamplingFilter < SamplingFilter::GOOD ||
aDrawSurfaceOptions.mSamplingFilter >= SamplingFilter::SENTINEL) {
aStream.SetIsBad();
return;
}
if (aDrawSurfaceOptions.mSamplingBounds < SamplingBounds::UNBOUNDED ||
aDrawSurfaceOptions.mSamplingBounds > SamplingBounds::BOUNDED) {
aStream.SetIsBad();
}
}
inline void RecordedEvent::OutputSimplePatternInfo(
const PatternStorage& aStorage, std::stringstream& aOutput) const {
switch (aStorage.mType) {
case PatternType::COLOR: {
const DeviceColor color =
reinterpret_cast<const ColorPatternStorage*>(&aStorage.mStorage)
->mColor;
aOutput << "DeviceColor: (" << color.r << ", " << color.g << ", "
<< color.b << ", " << color.a << ")";
return;
}
case PatternType::LINEAR_GRADIENT: {
const LinearGradientPatternStorage* store =
reinterpret_cast<const LinearGradientPatternStorage*>(
&aStorage.mStorage);
aOutput << "LinearGradient (" << store->mBegin.x << ", "
<< store->mBegin.y << ") - (" << store->mEnd.x << ", "
<< store->mEnd.y << ") Stops: " << store->mStops;
return;
}
case PatternType::RADIAL_GRADIENT: {
const RadialGradientPatternStorage* store =
reinterpret_cast<const RadialGradientPatternStorage*>(
&aStorage.mStorage);
aOutput << "RadialGradient (Center 1: (" << store->mCenter1.x << ", "
<< store->mCenter2.y << ") Radius 2: " << store->mRadius2;
return;
}
case PatternType::CONIC_GRADIENT: {
const ConicGradientPatternStorage* store =
reinterpret_cast<const ConicGradientPatternStorage*>(
&aStorage.mStorage);
aOutput << "ConicGradient (Center: (" << store->mCenter.x << ", "
<< store->mCenter.y << ") Angle: " << store->mAngle
<< " Range:" << store->mStartOffset << " - " << store->mEndOffset;
return;
}
case PatternType::SURFACE: {
const SurfacePatternStorage* store =
reinterpret_cast<const SurfacePatternStorage*>(&aStorage.mStorage);
aOutput << "Surface (0x" << store->mSurface << ")";
return;
}
}
}
inline bool RecordedDrawTargetCreation::PlayEvent(
Translator* aTranslator) const {
RefPtr<DrawTarget> newDT =
aTranslator->CreateDrawTarget(mRefPtr, mRect.Size(), mFormat);
// 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;
}
if (mHasExistingData) {
Rect dataRect(0, 0, mExistingData->GetSize().width,
mExistingData->GetSize().height);
newDT->DrawSurface(mExistingData, dataRect, dataRect);
}
return true;
}
template <class S>
void RecordedDrawTargetCreation::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mBackendType);
WriteElement(aStream, mRect);
WriteElement(aStream, mFormat);
WriteElement(aStream, mHasExistingData);
if (mHasExistingData) {
MOZ_ASSERT(mExistingData);
MOZ_ASSERT(mExistingData->GetSize() == mRect.Size());
RefPtr<DataSourceSurface> dataSurf = mExistingData->GetDataSurface();
DataSourceSurface::ScopedMap map(dataSurf, DataSourceSurface::READ);
for (int y = 0; y < mRect.height; y++) {
aStream.write((const char*)map.GetData() + y * map.GetStride(),
BytesPerPixel(mFormat) * mRect.width);
}
}
}
template <class S>
RecordedDrawTargetCreation::RecordedDrawTargetCreation(S& aStream)
: RecordedEventDerived(DRAWTARGETCREATION), mExistingData(nullptr) {
ReadElement(aStream, mRefPtr);
ReadElementConstrained(aStream, mBackendType, BackendType::NONE,
BackendType::WEBRENDER_TEXT);
ReadElement(aStream, mRect);
ReadElementConstrained(aStream, mFormat, SurfaceFormat::A8R8G8B8_UINT32,
SurfaceFormat::UNKNOWN);
ReadElement(aStream, mHasExistingData);
if (mHasExistingData) {
RefPtr<DataSourceSurface> dataSurf =
Factory::CreateDataSourceSurface(mRect.Size(), mFormat);
if (!dataSurf) {
gfxWarning()
<< "RecordedDrawTargetCreation had to reset mHasExistingData";
mHasExistingData = false;
return;
}
DataSourceSurface::ScopedMap map(dataSurf, DataSourceSurface::READ);
for (int y = 0; y < mRect.height; y++) {
aStream.read((char*)map.GetData() + y * map.GetStride(),
BytesPerPixel(mFormat) * mRect.width);
}
mExistingData = dataSurf;
}
}
inline void RecordedDrawTargetCreation::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] DrawTarget Creation (Type: "
<< NameFromBackend(mBackendType) << ", Size: " << mRect.width
<< "x" << mRect.height << ")";
}
inline bool RecordedDrawTargetDestruction::PlayEvent(
Translator* aTranslator) const {
aTranslator->RemoveDrawTarget(mRefPtr);
return true;
}
template <class S>
void RecordedDrawTargetDestruction::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
}
template <class S>
RecordedDrawTargetDestruction::RecordedDrawTargetDestruction(S& aStream)
: RecordedEventDerived(DRAWTARGETDESTRUCTION) {
ReadElement(aStream, mRefPtr);
}
inline void RecordedDrawTargetDestruction::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] DrawTarget Destruction";
}
inline bool RecordedSetCurrentDrawTarget::PlayEvent(
Translator* aTranslator) const {
return aTranslator->SetCurrentDrawTarget(mRefPtr);
}
template <class S>
void RecordedSetCurrentDrawTarget::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
}
template <class S>
RecordedSetCurrentDrawTarget::RecordedSetCurrentDrawTarget(S& aStream)
: RecordedEventDerived(SETCURRENTDRAWTARGET) {
ReadElement(aStream, mRefPtr);
}
inline void RecordedSetCurrentDrawTarget::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] SetCurrentDrawTarget";
}
inline bool RecordedCreateSimilarDrawTarget::PlayEvent(
Translator* aTranslator) const {
DrawTarget* drawTarget = aTranslator->GetCurrentDrawTarget();
if (!drawTarget) {
return false;
}
RefPtr<DrawTarget> newDT =
drawTarget->CreateSimilarDrawTarget(mSize, mFormat);
// 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 RecordedCreateSimilarDrawTarget::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mSize);
WriteElement(aStream, mFormat);
}
template <class S>
RecordedCreateSimilarDrawTarget::RecordedCreateSimilarDrawTarget(S& aStream)
: RecordedEventDerived(CREATESIMILARDRAWTARGET) {
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mSize);
ReadElementConstrained(aStream, mFormat, SurfaceFormat::A8R8G8B8_UINT32,
SurfaceFormat::UNKNOWN);
}
inline void RecordedCreateSimilarDrawTarget::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr
<< "] CreateSimilarDrawTarget (Size: " << mSize.width << "x"
<< mSize.height << ")";
}
inline bool RecordedCreateDrawTargetForFilter::PlayEvent(
Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
IntRect baseRect = dt->GetRect();
auto maxRect = IntRect(IntPoint(0, 0), mMaxSize);
auto clone = dt->GetTransform();
bool invertible = clone.Invert();
// mSourceRect is in filter space. The filter outputs from mSourceRect need
// to be drawn at mDestPoint in user space.
Rect userSpaceSource = Rect(mDestPoint, mSourceRect.Size());
if (invertible) {
// Try to reduce the source rect so that it's not much bigger
// than the draw target. The result is not minimal. Examples
// are left as an exercise for the reader.
auto destRect = IntRectToRect(baseRect);
Rect userSpaceBounds = clone.TransformBounds(destRect);
userSpaceSource = userSpaceSource.Intersect(userSpaceBounds);
}
// Compute how much we moved the top-left of the source rect by, and use that
// to compute the new dest point, and move our intersected source rect back
// into the (new) filter space.
Point shift = userSpaceSource.TopLeft() - mDestPoint;
Rect filterSpaceSource =
Rect(mSourceRect.TopLeft() + shift, userSpaceSource.Size());
baseRect = RoundedOut(filterSpaceSource);
FilterNode* filter = aTranslator->LookupFilterNode(mFilter);
if (!filter) {
return false;
}
IntRect transformedRect = filter->MapRectToSource(
baseRect, maxRect, aTranslator->LookupFilterNode(mSource));
// Intersect with maxRect to make sure we didn't end up with something bigger
transformedRect = transformedRect.Intersect(maxRect);
// If we end up with an empty rect make it 1x1 so that things don't break.
if (transformedRect.IsEmpty()) {
transformedRect = IntRect(0, 0, 1, 1);
}
RefPtr<DrawTarget> newDT =
dt->CreateSimilarDrawTarget(transformedRect.Size(), mFormat);
if (!newDT) {
return false;
}
newDT =
gfx::Factory::CreateOffsetDrawTarget(newDT, transformedRect.TopLeft());
// 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;
}
inline bool RecordedCreateClippedDrawTarget::PlayEvent(
Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
RefPtr<DrawTarget> newDT = dt->CreateClippedDrawTarget(mBounds, mFormat);
// 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, mBounds);
WriteElement(aStream, mFormat);
}
template <class S>
RecordedCreateClippedDrawTarget::RecordedCreateClippedDrawTarget(S& aStream)
: RecordedEventDerived(CREATECLIPPEDDRAWTARGET) {
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mBounds);
ReadElementConstrained(aStream, mFormat, SurfaceFormat::A8R8G8B8_UINT32,
SurfaceFormat::UNKNOWN);
}
inline void RecordedCreateClippedDrawTarget::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] CreateClippedDrawTarget ()";
}
template <class S>
void RecordedCreateDrawTargetForFilter::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mMaxSize);
WriteElement(aStream, mFormat);
WriteElement(aStream, mFilter);
WriteElement(aStream, mSource);
WriteElement(aStream, mSourceRect);
WriteElement(aStream, mDestPoint);
}
template <class S>
RecordedCreateDrawTargetForFilter::RecordedCreateDrawTargetForFilter(S& aStream)
: RecordedEventDerived(CREATEDRAWTARGETFORFILTER) {
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mMaxSize);
ReadElementConstrained(aStream, mFormat, SurfaceFormat::A8R8G8B8_UINT32,
SurfaceFormat::UNKNOWN);
ReadElement(aStream, mFilter);
ReadElement(aStream, mSource);
ReadElement(aStream, mSourceRect);
ReadElement(aStream, mDestPoint);
}
inline void RecordedCreateDrawTargetForFilter::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] CreateDrawTargetForFilter ()";
}
struct GenericPattern {
GenericPattern(const PatternStorage& aStorage, Translator* aTranslator)
: mPattern(nullptr), mTranslator(aTranslator) {
mStorage = const_cast<PatternStorage*>(&aStorage);
}
~GenericPattern() {
if (mPattern) {
mPattern->~Pattern();
}
}
operator Pattern*() {
switch (mStorage->mType) {
case PatternType::COLOR:
return new (mColPat) ColorPattern(
reinterpret_cast<ColorPatternStorage*>(&mStorage->mStorage)
->mColor);
case PatternType::SURFACE: {
SurfacePatternStorage* storage =
reinterpret_cast<SurfacePatternStorage*>(&mStorage->mStorage);
mPattern = new (mSurfPat)
SurfacePattern(mTranslator->LookupSourceSurface(storage->mSurface),
storage->mExtend, storage->mMatrix,
storage->mSamplingFilter, storage->mSamplingRect);
return mPattern;
}
case PatternType::LINEAR_GRADIENT: {
LinearGradientPatternStorage* storage =
reinterpret_cast<LinearGradientPatternStorage*>(
&mStorage->mStorage);
mPattern = new (mLinGradPat) LinearGradientPattern(
storage->mBegin, storage->mEnd,
storage->mStops ? mTranslator->LookupGradientStops(storage->mStops)
: nullptr,
storage->mMatrix);
return mPattern;
}
case PatternType::RADIAL_GRADIENT: {
RadialGradientPatternStorage* storage =
reinterpret_cast<RadialGradientPatternStorage*>(
&mStorage->mStorage);
mPattern = new (mRadGradPat) RadialGradientPattern(
storage->mCenter1, storage->mCenter2, storage->mRadius1,
storage->mRadius2,
storage->mStops ? mTranslator->LookupGradientStops(storage->mStops)
: nullptr,
storage->mMatrix);
return mPattern;
}
case PatternType::CONIC_GRADIENT: {
ConicGradientPatternStorage* storage =
reinterpret_cast<ConicGradientPatternStorage*>(&mStorage->mStorage);
mPattern = new (mConGradPat) ConicGradientPattern(
storage->mCenter, storage->mAngle, storage->mStartOffset,
storage->mEndOffset,
storage->mStops ? mTranslator->LookupGradientStops(storage->mStops)
: nullptr,
storage->mMatrix);
return mPattern;
}
default:
return new (mColPat) ColorPattern(DeviceColor());
}
return mPattern;
}
union {
char mColPat[sizeof(ColorPattern)];
char mLinGradPat[sizeof(LinearGradientPattern)];
char mRadGradPat[sizeof(RadialGradientPattern)];
char mConGradPat[sizeof(ConicGradientPattern)];
char mSurfPat[sizeof(SurfacePattern)];
};
PatternStorage* mStorage;
Pattern* mPattern;
Translator* mTranslator;
};
inline bool RecordedFillRect::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->FillRect(mRect, *GenericPattern(mPattern, aTranslator), mOptions);
return true;
}
template <class S>
void RecordedFillRect::Record(S& aStream) const {
WriteElement(aStream, mRect);
WriteElement(aStream, mOptions);
RecordPatternData(aStream, mPattern);
}
template <class S>
RecordedFillRect::RecordedFillRect(S& aStream)
: RecordedEventDerived(FILLRECT) {
ReadElement(aStream, mRect);
ReadDrawOptions(aStream, mOptions);
ReadPatternData(aStream, mPattern);
}
inline void RecordedFillRect::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "FillRect (" << mRect.X() << ", " << mRect.Y() << " - "
<< mRect.Width() << " x " << mRect.Height() << ") ";
OutputSimplePatternInfo(mPattern, aStringStream);
}
inline bool RecordedStrokeRect::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->StrokeRect(mRect, *GenericPattern(mPattern, aTranslator), mStrokeOptions,
mOptions);
return true;
}
template <class S>
void RecordedStrokeRect::Record(S& aStream) const {
WriteElement(aStream, mRect);
WriteElement(aStream, mOptions);
RecordPatternData(aStream, mPattern);
RecordStrokeOptions(aStream, mStrokeOptions);
}
template <class S>
RecordedStrokeRect::RecordedStrokeRect(S& aStream)
: RecordedEventDerived(STROKERECT) {
ReadElement(aStream, mRect);
ReadDrawOptions(aStream, mOptions);
ReadPatternData(aStream, mPattern);
ReadStrokeOptions(aStream, mStrokeOptions);
}
inline void RecordedStrokeRect::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "StrokeRect (" << mRect.X() << ", " << mRect.Y() << " - "
<< mRect.Width() << " x " << mRect.Height()
<< ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
OutputSimplePatternInfo(mPattern, aStringStream);
}
inline bool RecordedStrokeLine::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->StrokeLine(mBegin, mEnd, *GenericPattern(mPattern, aTranslator),
mStrokeOptions, mOptions);
return true;
}
template <class S>
void RecordedStrokeLine::Record(S& aStream) const {
WriteElement(aStream, mBegin);
WriteElement(aStream, mEnd);
WriteElement(aStream, mOptions);
RecordPatternData(aStream, mPattern);
RecordStrokeOptions(aStream, mStrokeOptions);
}
template <class S>
RecordedStrokeLine::RecordedStrokeLine(S& aStream)
: RecordedEventDerived(STROKELINE) {
ReadElement(aStream, mBegin);
ReadElement(aStream, mEnd);
ReadDrawOptions(aStream, mOptions);
ReadPatternData(aStream, mPattern);
ReadStrokeOptions(aStream, mStrokeOptions);
}
inline void RecordedStrokeLine::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "StrokeLine (" << mBegin.x << ", " << mBegin.y << " - "
<< mEnd.x << ", " << mEnd.y
<< ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
OutputSimplePatternInfo(mPattern, aStringStream);
}
inline bool RecordedStrokeCircle::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->StrokeCircle(mCircle.origin, mCircle.radius,
*GenericPattern(mPattern, aTranslator), mStrokeOptions,
mOptions);
return true;
}
template <class S>
void RecordedStrokeCircle::Record(S& aStream) const {
WriteElement(aStream, mCircle);
WriteElement(aStream, mOptions);
RecordPatternData(aStream, mPattern);
RecordStrokeOptions(aStream, mStrokeOptions);
}
template <class S>
RecordedStrokeCircle::RecordedStrokeCircle(S& aStream)
: RecordedEventDerived(STROKECIRCLE) {
ReadElement(aStream, mCircle);
ReadDrawOptions(aStream, mOptions);
ReadPatternData(aStream, mPattern);
ReadStrokeOptions(aStream, mStrokeOptions);
}
inline void RecordedStrokeCircle::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "StrokeCircle (" << mCircle.origin.x << ", "
<< mCircle.origin.y << " - " << mCircle.radius
<< ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
OutputSimplePatternInfo(mPattern, aStringStream);
}
inline bool RecordedFill::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->Fill(aTranslator->LookupPath(mPath),
*GenericPattern(mPattern, aTranslator), mOptions);
return true;
}
template <class S>
RecordedFill::RecordedFill(S& aStream) : RecordedEventDerived(FILL) {
ReadElement(aStream, mPath);
ReadDrawOptions(aStream, mOptions);
ReadPatternData(aStream, mPattern);
}
template <class S>
void RecordedFill::Record(S& aStream) const {
WriteElement(aStream, mPath);
WriteElement(aStream, mOptions);
RecordPatternData(aStream, mPattern);
}
inline void RecordedFill::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "Fill (" << mPath << ") ";
OutputSimplePatternInfo(mPattern, aStringStream);
}
inline bool RecordedFillCircle::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->FillCircle(mCircle.origin, mCircle.radius,
*GenericPattern(mPattern, aTranslator), mOptions);
return true;
}
template <class S>
void RecordedFillCircle::Record(S& aStream) const {
WriteElement(aStream, mCircle);
WriteElement(aStream, mOptions);
RecordPatternData(aStream, mPattern);
}
template <class S>
RecordedFillCircle::RecordedFillCircle(S& aStream)
: RecordedEventDerived(FILLCIRCLE) {
ReadElement(aStream, mCircle);
ReadDrawOptions(aStream, mOptions);
ReadPatternData(aStream, mPattern);
}
inline void RecordedFillCircle::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "FillCircle (" << mCircle.origin.x << ", "
<< mCircle.origin.y << " - " << mCircle.radius << ")";
OutputSimplePatternInfo(mPattern, aStringStream);
}
template <class T>
inline RecordedDrawGlyphs<T>::~RecordedDrawGlyphs() {
delete[] mGlyphs;
}
template <class T>
inline bool RecordedDrawGlyphs<T>::PlayEvent(Translator* aTranslator) const {
if (mNumGlyphs > 0 && !mGlyphs) {
// Glyph allocation failed
return false;
}
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
ScaledFont* scaledFont = aTranslator->LookupScaledFont(mScaledFont);
if (!scaledFont) {
return false;
}
GlyphBuffer buffer;
buffer.mGlyphs = mGlyphs;
buffer.mNumGlyphs = mNumGlyphs;
DrawGlyphs(dt, scaledFont, buffer, *GenericPattern(mPattern, aTranslator));
return true;
}
template <class T>
template <class S>
RecordedDrawGlyphs<T>::RecordedDrawGlyphs(RecordedEvent::EventType aType,
S& aStream)
: RecordedEventDerived<T>(aType) {
ReadElement(aStream, mScaledFont);
ReadDrawOptions(aStream, mOptions);
this->ReadPatternData(aStream, mPattern);
ReadElement(aStream, mNumGlyphs);
if (!aStream.good() || mNumGlyphs <= 0) {
return;
}
mGlyphs = new (fallible) Glyph[mNumGlyphs];
if (!mGlyphs) {
gfxCriticalNote << "RecordedDrawGlyphs failed to allocate glyphs of size "
<< mNumGlyphs;
aStream.SetIsBad();
} else {
aStream.read((char*)mGlyphs, sizeof(Glyph) * mNumGlyphs);
}
}
template <class T>
template <class S>
void RecordedDrawGlyphs<T>::Record(S& aStream) const {
WriteElement(aStream, mScaledFont);
WriteElement(aStream, mOptions);
this->RecordPatternData(aStream, mPattern);
WriteElement(aStream, mNumGlyphs);
aStream.write((char*)mGlyphs, sizeof(Glyph) * mNumGlyphs);
}
template <class T>
inline void RecordedDrawGlyphs<T>::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << this->GetName() << " (" << mScaledFont << ") ";
this->OutputSimplePatternInfo(mPattern, aStringStream);
}
inline bool RecordedMask::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->Mask(*GenericPattern(mSource, aTranslator),
*GenericPattern(mMask, aTranslator), mOptions);
return true;
}
template <class S>
RecordedMask::RecordedMask(S& aStream) : RecordedEventDerived(MASK) {
ReadDrawOptions(aStream, mOptions);
ReadPatternData(aStream, mSource);
ReadPatternData(aStream, mMask);
}
template <class S>
void RecordedMask::Record(S& aStream) const {
WriteElement(aStream, mOptions);
RecordPatternData(aStream, mSource);
RecordPatternData(aStream, mMask);
}
inline void RecordedMask::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "Mask (Source: ";
OutputSimplePatternInfo(mSource, aStringStream);
aStringStream << " Mask: ";
OutputSimplePatternInfo(mMask, aStringStream);
}
inline bool RecordedStroke::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
Path* path = aTranslator->LookupPath(mPath);
if (!path) {
return false;
}
dt->Stroke(path, *GenericPattern(mPattern, aTranslator), mStrokeOptions,
mOptions);
return true;
}
template <class S>
void RecordedStroke::Record(S& aStream) const {
WriteElement(aStream, mPath);
WriteElement(aStream, mOptions);
RecordPatternData(aStream, mPattern);
RecordStrokeOptions(aStream, mStrokeOptions);
}
template <class S>
RecordedStroke::RecordedStroke(S& aStream) : RecordedEventDerived(STROKE) {
ReadElement(aStream, mPath);
ReadDrawOptions(aStream, mOptions);
ReadPatternData(aStream, mPattern);
ReadStrokeOptions(aStream, mStrokeOptions);
}
inline void RecordedStroke::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "Stroke (" << mPath
<< ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
OutputSimplePatternInfo(mPattern, aStringStream);
}
inline bool RecordedClearRect::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->ClearRect(mRect);
return true;
}
template <class S>
void RecordedClearRect::Record(S& aStream) const {
WriteElement(aStream, mRect);
}
template <class S>
RecordedClearRect::RecordedClearRect(S& aStream)
: RecordedEventDerived(CLEARRECT) {
ReadElement(aStream, mRect);
}
inline void RecordedClearRect::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "ClearRect (" << mRect.X() << ", " << mRect.Y() << " - "
<< mRect.Width() << " x " << mRect.Height() << ") ";
}
inline bool RecordedCopySurface::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
SourceSurface* surface = aTranslator->LookupSourceSurface(mSourceSurface);
if (!surface) {
return false;
}
dt->CopySurface(surface, mSourceRect, mDest);
return true;
}
template <class S>
void RecordedCopySurface::Record(S& aStream) const {
WriteElement(aStream, mSourceSurface);
WriteElement(aStream, mSourceRect);
WriteElement(aStream, mDest);
}
template <class S>
RecordedCopySurface::RecordedCopySurface(S& aStream)
: RecordedEventDerived(COPYSURFACE) {
ReadElement(aStream, mSourceSurface);
ReadElement(aStream, mSourceRect);
ReadElement(aStream, mDest);
}
inline void RecordedCopySurface::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "CopySurface (" << mSourceSurface << ")";
}
inline bool RecordedPushClip::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
Path* path = aTranslator->LookupPath(mPath);
if (!path) {
return false;
}
dt->PushClip(path);
return true;
}
template <class S>
void RecordedPushClip::Record(S& aStream) const {
WriteElement(aStream, mPath);
}
template <class S>
RecordedPushClip::RecordedPushClip(S& aStream)
: RecordedEventDerived(PUSHCLIP) {
ReadElement(aStream, mPath);
}
inline void RecordedPushClip::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "PushClip (" << mPath << ") ";
}
inline bool RecordedPushClipRect::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->PushClipRect(mRect);
return true;
}
template <class S>
void RecordedPushClipRect::Record(S& aStream) const {
WriteElement(aStream, mRect);
}
template <class S>
RecordedPushClipRect::RecordedPushClipRect(S& aStream)
: RecordedEventDerived(PUSHCLIPRECT) {
ReadElement(aStream, mRect);
}
inline void RecordedPushClipRect::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "PushClipRect (" << mRect.X() << ", " << mRect.Y() << " - "
<< mRect.Width() << " x " << mRect.Height() << ") ";
}
inline bool RecordedPopClip::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->PopClip();
return true;
}
template <class S>
void RecordedPopClip::Record(S& aStream) const {}
template <class S>
RecordedPopClip::RecordedPopClip(S& aStream) : RecordedEventDerived(POPCLIP) {}
inline void RecordedPopClip::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "PopClip";
}
inline bool RecordedPushLayer::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
SourceSurface* mask =
mMask ? aTranslator->LookupSourceSurface(mMask) : nullptr;
dt->PushLayer(mOpaque, mOpacity, mask, mMaskTransform, mBounds,
mCopyBackground);
return true;
}
template <class S>
void RecordedPushLayer::Record(S& aStream) const {
WriteElement(aStream, mOpaque);
WriteElement(aStream, mOpacity);
WriteElement(aStream, mMask);
WriteElement(aStream, mMaskTransform);
WriteElement(aStream, mBounds);
WriteElement(aStream, mCopyBackground);
}
template <class S>
RecordedPushLayer::RecordedPushLayer(S& aStream)
: RecordedEventDerived(PUSHLAYER) {
ReadElement(aStream, mOpaque);
ReadElement(aStream, mOpacity);
ReadElement(aStream, mMask);
ReadElement(aStream, mMaskTransform);
ReadElement(aStream, mBounds);
ReadElement(aStream, mCopyBackground);
}
inline void RecordedPushLayer::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "PushPLayer (Opaque=" << mOpaque << ", Opacity=" << mOpacity
<< ", Mask Ref=" << mMask << ") ";
}
inline bool RecordedPushLayerWithBlend::PlayEvent(
Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
SourceSurface* mask =
mMask ? aTranslator->LookupSourceSurface(mMask) : nullptr;
dt->PushLayerWithBlend(mOpaque, mOpacity, mask, mMaskTransform, mBounds,
mCopyBackground, mCompositionOp);
return true;
}
template <class S>
void RecordedPushLayerWithBlend::Record(S& aStream) const {
WriteElement(aStream, mOpaque);
WriteElement(aStream, mOpacity);
WriteElement(aStream, mMask);
WriteElement(aStream, mMaskTransform);
WriteElement(aStream, mBounds);
WriteElement(aStream, mCopyBackground);
WriteElement(aStream, mCompositionOp);
}
template <class S>
RecordedPushLayerWithBlend::RecordedPushLayerWithBlend(S& aStream)
: RecordedEventDerived(PUSHLAYERWITHBLEND) {
ReadElement(aStream, mOpaque);
ReadElement(aStream, mOpacity);
ReadElement(aStream, mMask);
ReadElement(aStream, mMaskTransform);
ReadElement(aStream, mBounds);
ReadElement(aStream, mCopyBackground);
ReadElementConstrained(aStream, mCompositionOp, CompositionOp::OP_OVER,
CompositionOp::OP_COUNT);
}
inline void RecordedPushLayerWithBlend::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "PushLayerWithBlend (Opaque=" << mOpaque
<< ", Opacity=" << mOpacity << ", Mask Ref=" << mMask << ") ";
}
inline bool RecordedPopLayer::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->PopLayer();
return true;
}
template <class S>
void RecordedPopLayer::Record(S& aStream) const {}
template <class S>
RecordedPopLayer::RecordedPopLayer(S& aStream)
: RecordedEventDerived(POPLAYER) {}
inline void RecordedPopLayer::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "PopLayer";
}
inline bool RecordedSetPermitSubpixelAA::PlayEvent(
Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->SetPermitSubpixelAA(mPermitSubpixelAA);
return true;
}
template <class S>
void RecordedSetPermitSubpixelAA::Record(S& aStream) const {
WriteElement(aStream, mPermitSubpixelAA);
}
template <class S>
RecordedSetPermitSubpixelAA::RecordedSetPermitSubpixelAA(S& aStream)
: RecordedEventDerived(SETPERMITSUBPIXELAA) {
ReadElement(aStream, mPermitSubpixelAA);
}
inline void RecordedSetPermitSubpixelAA::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "SetPermitSubpixelAA (" << mPermitSubpixelAA << ")";
}
inline bool RecordedSetTransform::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
// If we're drawing to the reference DT, then we need to manually apply
// its initial transform, otherwise we'll just clobber it with only the
// the transform that was visible to the code doing the recording.
if (dt == aTranslator->GetReferenceDrawTarget()) {
dt->SetTransform(mTransform *
aTranslator->GetReferenceDrawTargetTransform());
} else {
dt->SetTransform(mTransform);
}
return true;
}
template <class S>
void RecordedSetTransform::Record(S& aStream) const {
WriteElement(aStream, mTransform);
}
template <class S>
RecordedSetTransform::RecordedSetTransform(S& aStream)
: RecordedEventDerived(SETTRANSFORM) {
ReadElement(aStream, mTransform);
}
inline void RecordedSetTransform::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "SetTransform [ " << mTransform._11 << " " << mTransform._12
<< " ; " << mTransform._21 << " " << mTransform._22 << " ; "
<< mTransform._31 << " " << mTransform._32 << " ]";
}
inline bool RecordedDrawSurface::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
SourceSurface* surface = aTranslator->LookupSourceSurface(mRefSource);
if (!surface) {
return false;
}
dt->DrawSurface(surface, mDest, mSource, mDSOptions, mOptions);
return true;
}
template <class S>
void RecordedDrawSurface::Record(S& aStream) const {
WriteElement(aStream, mRefSource);
WriteElement(aStream, mDest);
WriteElement(aStream, mSource);
WriteElement(aStream, mDSOptions);
WriteElement(aStream, mOptions);
}
template <class S>
RecordedDrawSurface::RecordedDrawSurface(S& aStream)
: RecordedEventDerived(DRAWSURFACE) {
ReadElement(aStream, mRefSource);
ReadElement(aStream, mDest);
ReadElement(aStream, mSource);
ReadDrawSurfaceOptions(aStream, mDSOptions);
ReadDrawOptions(aStream, mOptions);
}
inline void RecordedDrawSurface::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "DrawSurface (" << mRefSource << ")";
}
inline bool RecordedDrawSurfaceDescriptor::PlayEvent(
Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
RefPtr<SourceSurface> surface =
aTranslator->LookupSourceSurfaceFromSurfaceDescriptor(mDesc);
if (!surface) {
return false;
}
RefPtr<SourceSurface> opt = dt->OptimizeSourceSurface(surface);
if (opt) {
surface = opt;
}
dt->DrawSurface(surface, mDest, mSource, mDSOptions, mOptions);
return true;
}
template <class S>
void RecordedDrawSurfaceDescriptor::Record(S& aStream) const {
WriteElement(aStream, mDesc);
WriteElement(aStream, mDest);
WriteElement(aStream, mSource);
WriteElement(aStream, mDSOptions);
WriteElement(aStream, mOptions);
}
template <class S>
RecordedDrawSurfaceDescriptor::RecordedDrawSurfaceDescriptor(S& aStream)
: RecordedEventDerived(DRAWSURFACEDESCRIPTOR) {
ReadElement(aStream, mDesc);
ReadElement(aStream, mDest);
ReadElement(aStream, mSource);
ReadDrawSurfaceOptions(aStream, mDSOptions);
ReadDrawOptions(aStream, mOptions);
}
inline void RecordedDrawSurfaceDescriptor::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "DrawSurfaceDescriptor (" << mDesc.type() << ")";
}
inline bool RecordedDrawDependentSurface::PlayEvent(
Translator* aTranslator) const {
aTranslator->DrawDependentSurface(mId, mDest);
return true;
}
template <class S>
void RecordedDrawDependentSurface::Record(S& aStream) const {
WriteElement(aStream, mId);
WriteElement(aStream, mDest);
}
template <class S>
RecordedDrawDependentSurface::RecordedDrawDependentSurface(S& aStream)
: RecordedEventDerived(DRAWDEPENDENTSURFACE) {
ReadElement(aStream, mId);
ReadElement(aStream, mDest);
}
inline void RecordedDrawDependentSurface::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "DrawDependentSurface (" << mId << ")";
}
inline bool RecordedDrawFilter::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
FilterNode* filter = aTranslator->LookupFilterNode(mNode);
if (!filter) {
return false;
}
dt->DrawFilter(filter, mSourceRect, mDestPoint, mOptions);
return true;
}
template <class S>
void RecordedDrawFilter::Record(S& aStream) const {
WriteElement(aStream, mNode);
WriteElement(aStream, mSourceRect);
WriteElement(aStream, mDestPoint);
WriteElement(aStream, mOptions);
}
template <class S>
RecordedDrawFilter::RecordedDrawFilter(S& aStream)
: RecordedEventDerived(DRAWFILTER) {
ReadElement(aStream, mNode);
ReadElement(aStream, mSourceRect);
ReadElement(aStream, mDestPoint);
ReadDrawOptions(aStream, mOptions);
}
inline void RecordedDrawFilter::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "DrawFilter (" << mNode << ")";
}
inline bool RecordedDrawSurfaceWithShadow::PlayEvent(
Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
SourceSurface* surface = aTranslator->LookupSourceSurface(mRefSource);
if (!surface) {
return false;
}
dt->DrawSurfaceWithShadow(surface, mDest, mShadow, mOp);
return true;
}
template <class S>
void RecordedDrawSurfaceWithShadow::Record(S& aStream) const {
WriteElement(aStream, mRefSource);
WriteElement(aStream, mDest);
WriteElement(aStream, mShadow);
WriteElement(aStream, mOp);
}
template <class S>
RecordedDrawSurfaceWithShadow::RecordedDrawSurfaceWithShadow(S& aStream)
: RecordedEventDerived(DRAWSURFACEWITHSHADOW) {
ReadElement(aStream, mRefSource);
ReadElement(aStream, mDest);
ReadElement(aStream, mShadow);
ReadElementConstrained(aStream, mOp, CompositionOp::OP_OVER,
CompositionOp::OP_COUNT);
}
inline void RecordedDrawSurfaceWithShadow::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "DrawSurfaceWithShadow (" << mRefSource << ") DeviceColor: ("
<< mShadow.mColor.r << ", " << mShadow.mColor.g << ", "
<< mShadow.mColor.b << ", " << mShadow.mColor.a << ")";
}
inline bool RecordedDrawShadow::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
Path* path = aTranslator->LookupPath(mPath);
if (!path) {
return false;
}
dt->DrawShadow(path, *GenericPattern(mPattern, aTranslator), mShadow,
mOptions, mHasStrokeOptions ? &mStrokeOptions : nullptr);
return true;
}
template <class S>
void RecordedDrawShadow::Record(S& aStream) const {
WriteElement(aStream, mPath);
RecordPatternData(aStream, mPattern);
WriteElement(aStream, mShadow);
WriteElement(aStream, mOptions);
WriteElement(aStream, mHasStrokeOptions);
if (mHasStrokeOptions) {
RecordStrokeOptions(aStream, mStrokeOptions);
}
}
template <class S>
RecordedDrawShadow::RecordedDrawShadow(S& aStream)
: RecordedEventDerived(DRAWSHADOW) {
ReadElement(aStream, mPath);
ReadPatternData(aStream, mPattern);
ReadElement(aStream, mShadow);
ReadDrawOptions(aStream, mOptions);
ReadElement(aStream, mHasStrokeOptions);
if (mHasStrokeOptions) {
ReadStrokeOptions(aStream, mStrokeOptions);
}
}
inline void RecordedDrawShadow::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "DrawShadow (" << mPath << ") DeviceColor: ("
<< mShadow.mColor.r << ", " << mShadow.mColor.g << ", "
<< mShadow.mColor.b << ", " << mShadow.mColor.a << ")";
}
inline RecordedPathCreation::RecordedPathCreation(PathRecording* aPath)
: RecordedEventDerived(PATHCREATION),
mRefPtr(aPath),
mFillRule(aPath->mFillRule),
mPath(aPath) {}
inline bool RecordedPathCreation::PlayEvent(Translator* aTranslator) const {
DrawTarget* drawTarget = aTranslator->GetCurrentDrawTarget();
if (!drawTarget) {
return false;
}
RefPtr<PathBuilder> builder = drawTarget->CreatePathBuilder(mFillRule);
if (!mPathOps->CheckedStreamToSink(*builder)) {
return false;
}
RefPtr<Path> path = builder->Finish();
aTranslator->AddPath(mRefPtr, path);
return true;
}
template <class S>
void RecordedPathCreation::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mFillRule);
mPath->mPathOps.Record(aStream);
}
template <class S>
RecordedPathCreation::RecordedPathCreation(S& aStream)
: RecordedEventDerived(PATHCREATION) {
ReadElement(aStream, mRefPtr);
ReadElementConstrained(aStream, mFillRule, FillRule::FILL_WINDING,
FillRule::FILL_EVEN_ODD);
mPathOps = MakeUnique<PathOps>(aStream);
}
inline void RecordedPathCreation::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
size_t numberOfOps =
mPath ? mPath->mPathOps.NumberOfOps() : mPathOps->NumberOfOps();
aStringStream << "[" << mRefPtr << "] Path created (OpCount: " << numberOfOps
<< ")";
}
inline bool RecordedPathDestruction::PlayEvent(Translator* aTranslator) const {
aTranslator->RemovePath(mRefPtr);
return true;
}
template <class S>
void RecordedPathDestruction::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
}
template <class S>
RecordedPathDestruction::RecordedPathDestruction(S& aStream)
: RecordedEventDerived(PATHDESTRUCTION) {
ReadElement(aStream, mRefPtr);
}
inline void RecordedPathDestruction::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] Path Destroyed";
}
inline RecordedSourceSurfaceCreation::~RecordedSourceSurfaceCreation() {
if (mDataOwned) {
delete[] mData;
}
}
inline bool RecordedSourceSurfaceCreation::PlayEvent(
Translator* aTranslator) const {
if (!mData) {
return false;
}
RefPtr<SourceSurface> src = Factory::CreateWrappingDataSourceSurface(
mData, mSize.width * BytesPerPixel(mFormat), mSize, mFormat,
[](void* aClosure) { delete[] static_cast<uint8_t*>(aClosure); }, mData);
if (src) {
mDataOwned = false;
}
aTranslator->AddSourceSurface(mRefPtr, src);
return true;
}
template <class S>
void RecordedSourceSurfaceCreation::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mSize);
WriteElement(aStream, mFormat);
MOZ_ASSERT(mData);
size_t dataFormatWidth = BytesPerPixel(mFormat) * mSize.width;
const char* endSrc = (const char*)(mData + (mSize.height * mStride));
for (const char* src = (const char*)mData; src < endSrc; src += mStride) {
aStream.write(src, dataFormatWidth);
}
}
template <class S>
RecordedSourceSurfaceCreation::RecordedSourceSurfaceCreation(S& aStream)
: RecordedEventDerived(SOURCESURFACECREATION), mDataOwned(true) {
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mSize);
ReadElementConstrained(aStream, mFormat, SurfaceFormat::A8R8G8B8_UINT32,
SurfaceFormat::UNKNOWN);
if (!Factory::AllowedSurfaceSize(mSize)) {
gfxCriticalNote << "RecordedSourceSurfaceCreation read invalid size "
<< mSize;
aStream.SetIsBad();
}
if (!aStream.good()) {
return;
}
size_t size = 0;
if (mSize.width >= 0 && mSize.height >= 0) {
size = size_t(mSize.width) * size_t(mSize.height) * BytesPerPixel(mFormat);
mData = new (fallible) uint8_t[size];
}
if (!mData) {
gfxCriticalNote
<< "RecordedSourceSurfaceCreation failed to allocate data of size "
<< size;
aStream.SetIsBad();
} else {
aStream.read((char*)mData, size);
}
}
inline void RecordedSourceSurfaceCreation::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr
<< "] SourceSurface created (Size: " << mSize.width << "x"
<< mSize.height << ")";
}
inline bool RecordedSourceSurfaceDestruction::PlayEvent(
Translator* aTranslator) const {
aTranslator->RemoveSourceSurface(mRefPtr);
return true;
}
template <class S>
void RecordedSourceSurfaceDestruction::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
}
template <class S>
RecordedSourceSurfaceDestruction::RecordedSourceSurfaceDestruction(S& aStream)
: RecordedEventDerived(SOURCESURFACEDESTRUCTION) {
ReadElement(aStream, mRefPtr);
}
inline void RecordedSourceSurfaceDestruction::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] SourceSurface Destroyed";
}
inline bool RecordedOptimizeSourceSurface::PlayEvent(
Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
SourceSurface* surface = aTranslator->LookupSourceSurface(mSurface);
if (!surface) {
return false;
}
RefPtr<SourceSurface> optimizedSurface = dt->OptimizeSourceSurface(surface);
aTranslator->AddSourceSurface(mOptimizedSurface, optimizedSurface);
return true;
}
template <class S>
void RecordedOptimizeSourceSurface::Record(S& aStream) const {
WriteElement(aStream, mSurface);
WriteElement(aStream, mOptimizedSurface);
}
template <class S>
RecordedOptimizeSourceSurface::RecordedOptimizeSourceSurface(S& aStream)
: RecordedEventDerived(OPTIMIZESOURCESURFACE) {
ReadElement(aStream, mSurface);
ReadElement(aStream, mOptimizedSurface);
}
inline void RecordedOptimizeSourceSurface::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mSurface << "] Surface Optimized";
}
inline bool RecordedExternalSurfaceCreation::PlayEvent(
Translator* aTranslator) const {
RefPtr<SourceSurface> surface = aTranslator->LookupExternalSurface(mKey);
if (!surface) {
return false;
}
aTranslator->AddSourceSurface(mRefPtr, surface);
return true;
}
template <class S>
void RecordedExternalSurfaceCreation::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mKey);
}
template <class S>
RecordedExternalSurfaceCreation::RecordedExternalSurfaceCreation(S& aStream)
: RecordedEventDerived(EXTERNALSURFACECREATION) {
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mKey);
}
inline void RecordedExternalSurfaceCreation::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr
<< "] SourceSurfaceSharedData created (Key: " << mKey << ")";
}
inline RecordedFilterNodeCreation::~RecordedFilterNodeCreation() = default;
inline bool RecordedFilterNodeCreation::PlayEvent(
Translator* aTranslator) const {
DrawTarget* drawTarget = aTranslator->GetCurrentDrawTarget();
if (!drawTarget) {
return false;
}
RefPtr<FilterNode> node = drawTarget->CreateFilter(mType);
aTranslator->AddFilterNode(mRefPtr, node);
return true;
}
template <class S>
void RecordedFilterNodeCreation::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mType);
}
template <class S>
RecordedFilterNodeCreation::RecordedFilterNodeCreation(S& aStream)
: RecordedEventDerived(FILTERNODECREATION) {
ReadElement(aStream, mRefPtr);
ReadElementConstrained(aStream, mType, FilterType::BLEND,
FilterType::OPACITY);
}
inline void RecordedFilterNodeCreation::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "CreateFilter [" << mRefPtr
<< "] FilterNode created (Type: " << int(mType) << ")";
}
inline bool RecordedFilterNodeDestruction::PlayEvent(
Translator* aTranslator) const {
aTranslator->RemoveFilterNode(mRefPtr);
return true;
}
template <class S>
void RecordedFilterNodeDestruction::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
}
template <class S>
RecordedFilterNodeDestruction::RecordedFilterNodeDestruction(S& aStream)
: RecordedEventDerived(FILTERNODEDESTRUCTION) {
ReadElement(aStream, mRefPtr);
}
inline void RecordedFilterNodeDestruction::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] FilterNode Destroyed";
}
inline RecordedGradientStopsCreation::~RecordedGradientStopsCreation() {
if (mDataOwned) {
delete[] mStops;
}
}
inline bool RecordedGradientStopsCreation::PlayEvent(
Translator* aTranslator) const {
if (mNumStops > 0 && !mStops) {
// Stops allocation failed
return false;
}
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
RefPtr<GradientStops> src =
aTranslator->GetOrCreateGradientStops(dt, mStops, mNumStops, mExtendMode);
aTranslator->AddGradientStops(mRefPtr, src);
return true;
}
template <class S>
void RecordedGradientStopsCreation::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mExtendMode);
WriteElement(aStream, mNumStops);
aStream.write((const char*)mStops, mNumStops * sizeof(GradientStop));
}
template <class S>
RecordedGradientStopsCreation::RecordedGradientStopsCreation(S& aStream)
: RecordedEventDerived(GRADIENTSTOPSCREATION), mDataOwned(true) {
ReadElement(aStream, mRefPtr);
ReadElementConstrained(aStream, mExtendMode, ExtendMode::CLAMP,
ExtendMode::REFLECT);
ReadElement(aStream, mNumStops);
if (!aStream.good() || mNumStops <= 0) {
return;
}
mStops = new (fallible) GradientStop[mNumStops];
if (!mStops) {
gfxCriticalNote
<< "RecordedGradientStopsCreation failed to allocate stops of size "
<< mNumStops;
aStream.SetIsBad();
} else {
aStream.read((char*)mStops, mNumStops * sizeof(GradientStop));
}
}
inline void RecordedGradientStopsCreation::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr
<< "] GradientStops created (Stops: " << mNumStops << ")";
}
inline bool RecordedGradientStopsDestruction::PlayEvent(
Translator* aTranslator) const {
aTranslator->RemoveGradientStops(mRefPtr);
return true;
}
template <class S>
void RecordedGradientStopsDestruction::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
}
template <class S>
RecordedGradientStopsDestruction::RecordedGradientStopsDestruction(S& aStream)
: RecordedEventDerived(GRADIENTSTOPSDESTRUCTION) {
ReadElement(aStream, mRefPtr);
}
inline void RecordedGradientStopsDestruction::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] GradientStops Destroyed";
}
inline bool RecordedIntoLuminanceSource::PlayEvent(
Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
RefPtr<SourceSurface> src = dt->IntoLuminanceSource(mLuminanceType, mOpacity);
aTranslator->AddSourceSurface(mRefPtr, src);
return true;
}
template <class S>
void RecordedIntoLuminanceSource::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mLuminanceType);
WriteElement(aStream, mOpacity);
}
template <class S>
RecordedIntoLuminanceSource::RecordedIntoLuminanceSource(S& aStream)
: RecordedEventDerived(INTOLUMINANCE) {
ReadElement(aStream, mRefPtr);
ReadElementConstrained(aStream, mLuminanceType, LuminanceType::LUMINANCE,
LuminanceType::LINEARRGB);
ReadElement(aStream, mOpacity);
}
inline void RecordedIntoLuminanceSource::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] Into Luminance Source";
}
inline bool RecordedExtractSubrect::PlayEvent(Translator* aTranslator) const {
SourceSurface* sourceSurf = aTranslator->LookupSourceSurface(mSourceSurface);
if (!sourceSurf) {
return false;
}
RefPtr<SourceSurface> subSurf = sourceSurf->ExtractSubrect(mSubrect);
if (!subSurf) {
RefPtr<DrawTarget> dt =
aTranslator->GetReferenceDrawTarget()->CreateSimilarDrawTarget(
mSubrect.Size(), sourceSurf->GetFormat());
if (dt) {
dt->CopySurface(sourceSurf, mSubrect, IntPoint());
subSurf = dt->Snapshot();
}
}
if (!subSurf) {
return false;
}
aTranslator->AddSourceSurface(mRefPtr, subSurf);
return true;
}
template <class S>
void RecordedExtractSubrect::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mSourceSurface);
WriteElement(aStream, mSubrect);
}
template <class S>
RecordedExtractSubrect::RecordedExtractSubrect(S& aStream)
: RecordedEventDerived(EXTRACTSUBRECT) {
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mSourceSurface);
ReadElement(aStream, mSubrect);
}
inline void RecordedExtractSubrect::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] Exract Subrect";
}
inline bool RecordedFlush::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->Flush();
return true;
}
template <class S>
void RecordedFlush::Record(S& aStream) const {}
template <class S>
RecordedFlush::RecordedFlush(S& aStream) : RecordedEventDerived(FLUSH) {}
inline void RecordedFlush::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "Flush";
}
inline bool RecordedDetachAllSnapshots::PlayEvent(
Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->DetachAllSnapshots();
return true;
}
template <class S>
void RecordedDetachAllSnapshots::Record(S& aStream) const {}
template <class S>
RecordedDetachAllSnapshots::RecordedDetachAllSnapshots(S& aStream)
: RecordedEventDerived(DETACHALLSNAPSHOTS) {}
inline void RecordedDetachAllSnapshots::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "DetachAllSnapshots";
}
inline bool RecordedSnapshot::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
RefPtr<SourceSurface> src = dt->Snapshot();
aTranslator->AddSourceSurface(mRefPtr, src);
return true;
}
template <class S>
void RecordedSnapshot::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
}
template <class S>
RecordedSnapshot::RecordedSnapshot(S& aStream)
: RecordedEventDerived(SNAPSHOT) {
ReadElement(aStream, mRefPtr);
}
inline void RecordedSnapshot::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] Snapshot Created";
}
inline RecordedFontData::~RecordedFontData() { delete[] mData; }
inline bool RecordedFontData::PlayEvent(Translator* aTranslator) const {
if (!mData) {
return false;
}
RefPtr<NativeFontResource> fontResource = Factory::CreateNativeFontResource(
mData, mFontDetails.size, mType, aTranslator->GetFontContext());
if (!fontResource) {
return false;
}
aTranslator->AddNativeFontResource(mFontDetails.fontDataKey, fontResource);
return true;
}
template <class S>
void RecordedFontData::Record(S& aStream) const {
MOZ_ASSERT(mGetFontFileDataSucceeded);
WriteElement(aStream, mType);
WriteElement(aStream, mFontDetails.fontDataKey);
if (!mData) {
WriteElement(aStream, 0);
} else {
WriteElement(aStream, mFontDetails.size);
aStream.write((const char*)mData, mFontDetails.size);
}
}
inline void RecordedFontData::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "Font Data of size " << mFontDetails.size;
}
inline void RecordedFontData::SetFontData(const uint8_t* aData, uint32_t aSize,
uint32_t aIndex) {
mData = new (fallible) uint8_t[aSize];
if (!mData) {
gfxCriticalNote
<< "RecordedFontData failed to allocate data for recording of size "
<< aSize;
} else {
memcpy(mData, aData, aSize);
}
mFontDetails.fontDataKey = SFNTData::GetUniqueKey(aData, aSize, 0, nullptr);
mFontDetails.size = aSize;
mFontDetails.index = aIndex;
}
inline bool RecordedFontData::GetFontDetails(RecordedFontDetails& fontDetails) {
if (!mGetFontFileDataSucceeded) {
return false;
}
fontDetails.fontDataKey = mFontDetails.fontDataKey;
fontDetails.size = mFontDetails.size;
fontDetails.index = mFontDetails.index;
return true;
}
template <class S>
RecordedFontData::RecordedFontData(S& aStream)
: RecordedEventDerived(FONTDATA), mType(FontType::UNKNOWN) {
ReadElementConstrained(aStream, mType, FontType::DWRITE, FontType::UNKNOWN);
ReadElement(aStream, mFontDetails.fontDataKey);
ReadElement(aStream, mFontDetails.size);
if (!mFontDetails.size || !aStream.good()) {
return;
}
mData = new (fallible) uint8_t[mFontDetails.size];
if (!mData) {
gfxCriticalNote
<< "RecordedFontData failed to allocate data for playback of size "
<< mFontDetails.size;
aStream.SetIsBad();
} else {
aStream.read((char*)mData, mFontDetails.size);
}
}
inline RecordedFontDescriptor::~RecordedFontDescriptor() = default;
inline bool RecordedFontDescriptor::PlayEvent(Translator* aTranslator) const {
RefPtr<UnscaledFont> font = Factory::CreateUnscaledFontFromFontDescriptor(
mType, mData.data(), mData.size(), mIndex);
if (!font) {
gfxDevCrash(LogReason::InvalidFont)
<< "Failed creating UnscaledFont of type " << int(mType)
<< " from font descriptor";
return false;
}
aTranslator->AddUnscaledFont(mRefPtr, font);
return true;
}
template <class S>
void RecordedFontDescriptor::Record(S& aStream) const {
MOZ_ASSERT(mHasDesc);
WriteElement(aStream, mType);
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mIndex);
WriteElement(aStream, (size_t)mData.size());
if (mData.size()) {
aStream.write((char*)mData.data(), mData.size());
}
}
inline void RecordedFontDescriptor::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] Font Descriptor";
}
inline void RecordedFontDescriptor::SetFontDescriptor(const uint8_t* aData,
uint32_t aSize,
uint32_t aIndex) {
mData.assign(aData, aData + aSize);
mIndex = aIndex;
}
template <class S>
RecordedFontDescriptor::RecordedFontDescriptor(S& aStream)
: RecordedEventDerived(FONTDESC) {
ReadElementConstrained(aStream, mType, FontType::DWRITE, FontType::UNKNOWN);
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mIndex);
size_t size;
ReadElement(aStream, size);
if (!aStream.good()) {
return;
}
if (size) {
mData.resize(size);
aStream.read((char*)mData.data(), size);
}
}
inline bool RecordedUnscaledFontCreation::PlayEvent(
Translator* aTranslator) const {
NativeFontResource* fontResource =
aTranslator->LookupNativeFontResource(mFontDataKey);
if (!fontResource) {
gfxDevCrash(LogReason::NativeFontResourceNotFound)
<< "NativeFontResource lookup failed for key |" << hexa(mFontDataKey)
<< "|.";
return false;
}
RefPtr<UnscaledFont> unscaledFont = fontResource->CreateUnscaledFont(
mIndex, mInstanceData.data(), mInstanceData.size());
aTranslator->AddUnscaledFont(mRefPtr, unscaledFont);
return true;
}
template <class S>
void RecordedUnscaledFontCreation::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mFontDataKey);
WriteElement(aStream, mIndex);
WriteElement(aStream, (size_t)mInstanceData.size());
if (mInstanceData.size()) {
aStream.write((char*)mInstanceData.data(), mInstanceData.size());
}
}
inline void RecordedUnscaledFontCreation::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] UnscaledFont Created";
}
inline void RecordedUnscaledFontCreation::SetFontInstanceData(
const uint8_t* aData, uint32_t aSize) {
if (aSize) {
mInstanceData.assign(aData, aData + aSize);
}
}
template <class S>
RecordedUnscaledFontCreation::RecordedUnscaledFontCreation(S& aStream)
: RecordedEventDerived(UNSCALEDFONTCREATION) {
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mFontDataKey);
ReadElement(aStream, mIndex);
size_t size;
ReadElement(aStream, size);
if (!aStream.good()) {
return;
}
if (size) {
mInstanceData.resize(size);
aStream.read((char*)mInstanceData.data(), size);
}
}
inline bool RecordedUnscaledFontDestruction::PlayEvent(
Translator* aTranslator) const {
aTranslator->RemoveUnscaledFont(mRefPtr);
return true;
}
template <class S>
void RecordedUnscaledFontDestruction::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
}
template <class S>
RecordedUnscaledFontDestruction::RecordedUnscaledFontDestruction(S& aStream)
: RecordedEventDerived(UNSCALEDFONTDESTRUCTION) {
ReadElement(aStream, mRefPtr);
}
inline void RecordedUnscaledFontDestruction::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] UnscaledFont Destroyed";
}
inline bool RecordedScaledFontCreation::PlayEvent(
Translator* aTranslator) const {
UnscaledFont* unscaledFont = aTranslator->LookupUnscaledFont(mUnscaledFont);
if (!unscaledFont) {
gfxDevCrash(LogReason::UnscaledFontNotFound)
<< "UnscaledFont lookup failed for key |" << hexa(mUnscaledFont)
<< "|.";
return false;
}
RefPtr<ScaledFont> scaledFont = unscaledFont->CreateScaledFont(
mGlyphSize, mInstanceData.data(), mInstanceData.size(),
mVariations.data(), mVariations.size());
aTranslator->AddScaledFont(mRefPtr, scaledFont);
return true;
}
template <class S>
void RecordedScaledFontCreation::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
WriteElement(aStream, mUnscaledFont);
WriteElement(aStream, mGlyphSize);
WriteElement(aStream, (size_t)mInstanceData.size());
if (mInstanceData.size()) {
aStream.write((char*)mInstanceData.data(), mInstanceData.size());
}
WriteElement(aStream, (size_t)mVariations.size());
if (mVariations.size()) {
aStream.write((char*)mVariations.data(),
sizeof(FontVariation) * mVariations.size());
}
}
inline void RecordedScaledFontCreation::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] ScaledFont Created";
}
inline void RecordedScaledFontCreation::SetFontInstanceData(
const uint8_t* aData, uint32_t aSize, const FontVariation* aVariations,
uint32_t aNumVariations) {
if (aSize) {
mInstanceData.assign(aData, aData + aSize);
}
if (aNumVariations) {
mVariations.assign(aVariations, aVariations + aNumVariations);
}
}
template <class S>
RecordedScaledFontCreation::RecordedScaledFontCreation(S& aStream)
: RecordedEventDerived(SCALEDFONTCREATION) {
ReadElement(aStream, mRefPtr);
ReadElement(aStream, mUnscaledFont);
ReadElement(aStream, mGlyphSize);
size_t size;
ReadElement(aStream, size);
if (!aStream.good()) {
return;
}
if (size) {
mInstanceData.resize(size);
aStream.read((char*)mInstanceData.data(), size);
}
size_t numVariations;
ReadElement(aStream, numVariations);
if (!aStream.good()) {
return;
}
if (numVariations) {
mVariations.resize(numVariations);
aStream.read((char*)mVariations.data(),
sizeof(FontVariation) * numVariations);
}
}
inline bool RecordedScaledFontDestruction::PlayEvent(
Translator* aTranslator) const {
aTranslator->RemoveScaledFont(mRefPtr);
return true;
}
template <class S>
void RecordedScaledFontDestruction::Record(S& aStream) const {
WriteElement(aStream, mRefPtr);
}
template <class S>
RecordedScaledFontDestruction::RecordedScaledFontDestruction(S& aStream)
: RecordedEventDerived(SCALEDFONTDESTRUCTION) {
ReadElement(aStream, mRefPtr);
}
inline void RecordedScaledFontDestruction::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mRefPtr << "] ScaledFont Destroyed";
}
inline bool RecordedMaskSurface::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
SourceSurface* surface = aTranslator->LookupSourceSurface(mRefMask);
if (!surface) {
return false;
}
dt->MaskSurface(*GenericPattern(mPattern, aTranslator), surface, mOffset,
mOptions);
return true;
}
template <class S>
void RecordedMaskSurface::Record(S& aStream) const {
RecordPatternData(aStream, mPattern);
WriteElement(aStream, mRefMask);
WriteElement(aStream, mOffset);
WriteElement(aStream, mOptions);
}
template <class S>
RecordedMaskSurface::RecordedMaskSurface(S& aStream)
: RecordedEventDerived(MASKSURFACE) {
ReadPatternData(aStream, mPattern);
ReadElement(aStream, mRefMask);
ReadElement(aStream, mOffset);
ReadDrawOptions(aStream, mOptions);
}
inline void RecordedMaskSurface::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "MaskSurface (" << mRefMask << ") Offset: (" << mOffset.x
<< "x" << mOffset.y << ") Pattern: ";
OutputSimplePatternInfo(mPattern, aStringStream);
}
template <typename T>
void ReplaySetAttribute(FilterNode* aNode, uint32_t aIndex, T aValue) {
aNode->SetAttribute(aIndex, aValue);
}
inline bool RecordedFilterNodeSetAttribute::PlayEvent(
Translator* aTranslator) const {
FilterNode* node = aTranslator->LookupFilterNode(mNode);
if (!node) {
return false;
}
#define REPLAY_SET_ATTRIBUTE(type, argtype) \
case ARGTYPE_##argtype: \
ReplaySetAttribute(node, mIndex, *(type*)&mPayload.front()); \
break
switch (mArgType) {
REPLAY_SET_ATTRIBUTE(bool, BOOL);
REPLAY_SET_ATTRIBUTE(uint32_t, UINT32);
REPLAY_SET_ATTRIBUTE(Float, FLOAT);
REPLAY_SET_ATTRIBUTE(Size, SIZE);
REPLAY_SET_ATTRIBUTE(IntSize, INTSIZE);
REPLAY_SET_ATTRIBUTE(IntPoint, INTPOINT);
REPLAY_SET_ATTRIBUTE(Rect, RECT);
REPLAY_SET_ATTRIBUTE(IntRect, INTRECT);
REPLAY_SET_ATTRIBUTE(Point, POINT);
REPLAY_SET_ATTRIBUTE(Matrix, MATRIX);
REPLAY_SET_ATTRIBUTE(Matrix5x4, MATRIX5X4);
REPLAY_SET_ATTRIBUTE(Point3D, POINT3D);
REPLAY_SET_ATTRIBUTE(DeviceColor, COLOR);
case ARGTYPE_FLOAT_ARRAY:
node->SetAttribute(mIndex,
reinterpret_cast<const Float*>(&mPayload.front()),
mPayload.size() / sizeof(Float));
break;
}
return true;
}
template <class S>
void RecordedFilterNodeSetAttribute::Record(S& aStream) const {
WriteElement(aStream, mNode);
WriteElement(aStream, mIndex);
WriteElement(aStream, mArgType);
WriteElement(aStream, uint64_t(mPayload.size()));
aStream.write((const char*)&mPayload.front(), mPayload.size());
}
template <class S>
RecordedFilterNodeSetAttribute::RecordedFilterNodeSetAttribute(S& aStream)
: RecordedEventDerived(FILTERNODESETATTRIBUTE) {
ReadElement(aStream, mNode);
ReadElement(aStream, mIndex);
ReadElementConstrained(aStream, mArgType, ArgType::ARGTYPE_UINT32,
ArgType::ARGTYPE_FLOAT_ARRAY);
uint64_t size;
ReadElement(aStream, size);
if (!aStream.good()) {
return;
}
mPayload.resize(size_t(size));
aStream.read((char*)&mPayload.front(), size);
}
inline void RecordedFilterNodeSetAttribute::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mNode << "] SetAttribute (" << mIndex << ")";
}
inline bool RecordedFilterNodeSetInput::PlayEvent(
Translator* aTranslator) const {
FilterNode* node = aTranslator->LookupFilterNode(mNode);
if (!node) {
return false;
}
if (mInputFilter) {
node->SetInput(mIndex, aTranslator->LookupFilterNode(mInputFilter));
} else {
node->SetInput(mIndex, aTranslator->LookupSourceSurface(mInputSurface));
}
return true;
}
template <class S>
void RecordedFilterNodeSetInput::Record(S& aStream) const {
WriteElement(aStream, mNode);
WriteElement(aStream, mIndex);
WriteElement(aStream, mInputFilter);
WriteElement(aStream, mInputSurface);
}
template <class S>
RecordedFilterNodeSetInput::RecordedFilterNodeSetInput(S& aStream)
: RecordedEventDerived(FILTERNODESETINPUT) {
ReadElement(aStream, mNode);
ReadElement(aStream, mIndex);
ReadElement(aStream, mInputFilter);
ReadElement(aStream, mInputSurface);
}
inline void RecordedFilterNodeSetInput::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "[" << mNode << "] SetAttribute (" << mIndex << ", ";
if (mInputFilter) {
aStringStream << "Filter: " << mInputFilter;
} else {
aStringStream << "Surface: " << mInputSurface;
}
aStringStream << ")";
}
inline bool RecordedLink::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->Link(mDestination.c_str(), mRect);
return true;
}
template <class S>
void RecordedLink::Record(S& aStream) const {
WriteElement(aStream, mRect);
uint32_t len = mDestination.length();
WriteElement(aStream, len);
if (len) {
aStream.write(mDestination.data(), len);
}
}
template <class S>
RecordedLink::RecordedLink(S& aStream) : RecordedEventDerived(LINK) {
ReadElement(aStream, mRect);
uint32_t len;
ReadElement(aStream, len);
mDestination.resize(size_t(len));
if (len && aStream.good()) {
aStream.read(&mDestination.front(), len);
}
}
inline void RecordedLink::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "Link [" << mDestination << " @ " << mRect << "]";
}
inline bool RecordedDestination::PlayEvent(Translator* aTranslator) const {
DrawTarget* dt = aTranslator->GetCurrentDrawTarget();
if (!dt) {
return false;
}
dt->Destination(mDestination.c_str(), mPoint);
return true;
}
template <class S>
void RecordedDestination::Record(S& aStream) const {
WriteElement(aStream, mPoint);
uint32_t len = mDestination.length();
WriteElement(aStream, len);
if (len) {
aStream.write(mDestination.data(), len);
}
}
template <class S>
RecordedDestination::RecordedDestination(S& aStream)
: RecordedEventDerived(DESTINATION) {
ReadElement(aStream, mPoint);
uint32_t len;
ReadElement(aStream, len);
mDestination.resize(size_t(len));
if (len && aStream.good()) {
aStream.read(&mDestination.front(), len);
}
}
inline void RecordedDestination::OutputSimpleEventInfo(
std::stringstream& aStringStream) const {
aStringStream << "Destination [" << mDestination << " @ " << mPoint << "]";
}
#define FOR_EACH_EVENT(f) \
f(DRAWTARGETCREATION, RecordedDrawTargetCreation); \
f(DRAWTARGETDESTRUCTION, RecordedDrawTargetDestruction); \
f(SETCURRENTDRAWTARGET, RecordedSetCurrentDrawTarget); \
f(FILLRECT, RecordedFillRect); \
f(STROKERECT, RecordedStrokeRect); \
f(STROKELINE, RecordedStrokeLine); \
f(STROKECIRCLE, RecordedStrokeCircle); \
f(CLEARRECT, RecordedClearRect); \
f(COPYSURFACE, RecordedCopySurface); \
f(SETPERMITSUBPIXELAA, RecordedSetPermitSubpixelAA); \
f(SETTRANSFORM, RecordedSetTransform); \
f(PUSHCLIPRECT, RecordedPushClipRect); \
f(PUSHCLIP, RecordedPushClip); \
f(POPCLIP, RecordedPopClip); \
f(FILL, RecordedFill); \
f(FILLCIRCLE, RecordedFillCircle); \
f(FILLGLYPHS, RecordedFillGlyphs); \
f(STROKEGLYPHS, RecordedStrokeGlyphs); \
f(MASK, RecordedMask); \
f(STROKE, RecordedStroke); \
f(DRAWSURFACE, RecordedDrawSurface); \
f(DRAWSURFACEDESCRIPTOR, RecordedDrawSurfaceDescriptor); \
f(DRAWDEPENDENTSURFACE, RecordedDrawDependentSurface); \
f(DRAWSURFACEWITHSHADOW, RecordedDrawSurfaceWithShadow); \
f(DRAWSHADOW, RecordedDrawShadow); \
f(DRAWFILTER, RecordedDrawFilter); \
f(PATHCREATION, RecordedPathCreation); \
f(PATHDESTRUCTION, RecordedPathDestruction); \
f(SOURCESURFACECREATION, RecordedSourceSurfaceCreation); \
f(SOURCESURFACEDESTRUCTION, RecordedSourceSurfaceDestruction); \
f(FILTERNODECREATION, RecordedFilterNodeCreation); \
f(FILTERNODEDESTRUCTION, RecordedFilterNodeDestruction); \
f(GRADIENTSTOPSCREATION, RecordedGradientStopsCreation); \
f(GRADIENTSTOPSDESTRUCTION, RecordedGradientStopsDestruction); \
f(SNAPSHOT, RecordedSnapshot); \
f(SCALEDFONTCREATION, RecordedScaledFontCreation); \
f(SCALEDFONTDESTRUCTION, RecordedScaledFontDestruction); \
f(MASKSURFACE, RecordedMaskSurface); \
f(FILTERNODESETATTRIBUTE, RecordedFilterNodeSetAttribute); \
f(FILTERNODESETINPUT, RecordedFilterNodeSetInput); \
f(CREATESIMILARDRAWTARGET, RecordedCreateSimilarDrawTarget); \
f(CREATECLIPPEDDRAWTARGET, RecordedCreateClippedDrawTarget); \
f(CREATEDRAWTARGETFORFILTER, RecordedCreateDrawTargetForFilter); \
f(FONTDATA, RecordedFontData); \
f(FONTDESC, RecordedFontDescriptor); \
f(PUSHLAYER, RecordedPushLayer); \
f(PUSHLAYERWITHBLEND, RecordedPushLayerWithBlend); \
f(POPLAYER, RecordedPopLayer); \
f(UNSCALEDFONTCREATION, RecordedUnscaledFontCreation); \
f(UNSCALEDFONTDESTRUCTION, RecordedUnscaledFontDestruction); \
f(INTOLUMINANCE, RecordedIntoLuminanceSource); \
f(EXTRACTSUBRECT, RecordedExtractSubrect); \
f(EXTERNALSURFACECREATION, RecordedExternalSurfaceCreation); \
f(FLUSH, RecordedFlush); \
f(DETACHALLSNAPSHOTS, RecordedDetachAllSnapshots); \
f(OPTIMIZESOURCESURFACE, RecordedOptimizeSourceSurface); \
f(LINK, RecordedLink); \
f(DESTINATION, RecordedDestination);
#define DO_WITH_EVENT_TYPE(_typeenum, _class) \
case _typeenum: { \
auto e = _class(aStream); \
return aAction(&e); \
}
template <class S>
bool RecordedEvent::DoWithEvent(
S& aStream, EventType aType,
const std::function<bool(RecordedEvent*)>& aAction) {
switch (aType) {
FOR_EACH_EVENT(DO_WITH_EVENT_TYPE)
default:
return false;
}
}
} // namespace gfx
} // namespace mozilla
#endif