summaryrefslogtreecommitdiffstats
path: root/gfx/2d/RecordedEventImpl.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/2d/RecordedEventImpl.h')
-rw-r--r--gfx/2d/RecordedEventImpl.h4088
1 files changed, 4088 insertions, 0 deletions
diff --git a/gfx/2d/RecordedEventImpl.h b/gfx/2d/RecordedEventImpl.h
new file mode 100644
index 0000000000..7190299825
--- /dev/null
+++ b/gfx/2d/RecordedEventImpl.h
@@ -0,0 +1,4088 @@
+/* -*- 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"
+
+namespace mozilla {
+namespace gfx {
+
+template <class Derived>
+class RecordedDrawingEvent : public RecordedEventDerived<Derived> {
+ public:
+ ReferencePtr GetDestinedDT() override { return mDT; }
+
+ protected:
+ RecordedDrawingEvent(RecordedEvent::EventType aType, DrawTarget* aTarget)
+ : RecordedEventDerived<Derived>(aType), mDT(aTarget) {}
+
+ template <class S>
+ RecordedDrawingEvent(RecordedEvent::EventType aType, S& aStream);
+ template <class S>
+ void Record(S& aStream) const;
+
+ ReferencePtr mDT;
+};
+
+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;
+ 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 RecordedCreateSimilarDrawTarget
+ : public RecordedEventDerived<RecordedCreateSimilarDrawTarget> {
+ public:
+ RecordedCreateSimilarDrawTarget(ReferencePtr aDT, ReferencePtr aRefPtr,
+ const IntSize& aSize, SurfaceFormat aFormat)
+ : RecordedEventDerived(CREATESIMILARDRAWTARGET),
+ mDT(aDT),
+ 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 mDT;
+ ReferencePtr mRefPtr;
+ IntSize mSize;
+ SurfaceFormat mFormat;
+
+ private:
+ friend class RecordedEvent;
+
+ template <class S>
+ MOZ_IMPLICIT RecordedCreateSimilarDrawTarget(S& aStream);
+};
+
+class RecordedCreateClippedDrawTarget
+ : public RecordedDrawingEvent<RecordedCreateClippedDrawTarget> {
+ public:
+ RecordedCreateClippedDrawTarget(DrawTarget* aDT, ReferencePtr aRefPtr,
+ const Rect& aBounds, SurfaceFormat aFormat)
+ : RecordedDrawingEvent(CREATECLIPPEDDRAWTARGET, aDT),
+ 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 RecordedDrawingEvent<RecordedCreateDrawTargetForFilter> {
+ public:
+ RecordedCreateDrawTargetForFilter(DrawTarget* aDT, ReferencePtr aRefPtr,
+ const IntSize& aMaxSize,
+ SurfaceFormat aFormat, FilterNode* aFilter,
+ FilterNode* aSource,
+ const Rect& aSourceRect,
+ const Point& aDestPoint)
+ : RecordedDrawingEvent(CREATEDRAWTARGETFORFILTER, aDT),
+ 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 RecordedDrawingEvent<RecordedFillRect> {
+ public:
+ RecordedFillRect(DrawTarget* aDT, const Rect& aRect, const Pattern& aPattern,
+ const DrawOptions& aOptions)
+ : RecordedDrawingEvent(FILLRECT, aDT),
+ 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 RecordedDrawingEvent<RecordedStrokeRect> {
+ public:
+ RecordedStrokeRect(DrawTarget* aDT, const Rect& aRect,
+ const Pattern& aPattern,
+ const StrokeOptions& aStrokeOptions,
+ const DrawOptions& aOptions)
+ : RecordedDrawingEvent(STROKERECT, aDT),
+ 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 RecordedDrawingEvent<RecordedStrokeLine> {
+ public:
+ RecordedStrokeLine(DrawTarget* aDT, const Point& aBegin, const Point& aEnd,
+ const Pattern& aPattern,
+ const StrokeOptions& aStrokeOptions,
+ const DrawOptions& aOptions)
+ : RecordedDrawingEvent(STROKELINE, aDT),
+ 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 RecordedFill : public RecordedDrawingEvent<RecordedFill> {
+ public:
+ RecordedFill(DrawTarget* aDT, ReferencePtr aPath, const Pattern& aPattern,
+ const DrawOptions& aOptions)
+ : RecordedDrawingEvent(FILL, aDT),
+ 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 RecordedFillGlyphs : public RecordedDrawingEvent<RecordedFillGlyphs> {
+ public:
+ RecordedFillGlyphs(DrawTarget* aDT, ReferencePtr aScaledFont,
+ const Pattern& aPattern, const DrawOptions& aOptions,
+ const Glyph* aGlyphs, uint32_t aNumGlyphs)
+ : RecordedDrawingEvent(FILLGLYPHS, aDT),
+ mScaledFont(aScaledFont),
+ mPattern(),
+ mOptions(aOptions) {
+ StorePattern(mPattern, aPattern);
+ mNumGlyphs = aNumGlyphs;
+ mGlyphs = new Glyph[aNumGlyphs];
+ memcpy(mGlyphs, aGlyphs, sizeof(Glyph) * aNumGlyphs);
+ }
+ virtual ~RecordedFillGlyphs();
+
+ 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 "FillGlyphs"; }
+
+ private:
+ friend class RecordedEvent;
+
+ template <class S>
+ MOZ_IMPLICIT RecordedFillGlyphs(S& aStream);
+
+ ReferencePtr mScaledFont;
+ PatternStorage mPattern;
+ DrawOptions mOptions;
+ Glyph* mGlyphs = nullptr;
+ uint32_t mNumGlyphs = 0;
+};
+
+class RecordedMask : public RecordedDrawingEvent<RecordedMask> {
+ public:
+ RecordedMask(DrawTarget* aDT, const Pattern& aSource, const Pattern& aMask,
+ const DrawOptions& aOptions)
+ : RecordedDrawingEvent(MASK, aDT),
+ 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 RecordedDrawingEvent<RecordedStroke> {
+ public:
+ RecordedStroke(DrawTarget* aDT, ReferencePtr aPath, const Pattern& aPattern,
+ const StrokeOptions& aStrokeOptions,
+ const DrawOptions& aOptions)
+ : RecordedDrawingEvent(STROKE, aDT),
+ 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 RecordedDrawingEvent<RecordedClearRect> {
+ public:
+ RecordedClearRect(DrawTarget* aDT, const Rect& aRect)
+ : RecordedDrawingEvent(CLEARRECT, aDT), 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 RecordedDrawingEvent<RecordedCopySurface> {
+ public:
+ RecordedCopySurface(DrawTarget* aDT, ReferencePtr aSourceSurface,
+ const IntRect& aSourceRect, const IntPoint& aDest)
+ : RecordedDrawingEvent(COPYSURFACE, aDT),
+ 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 RecordedDrawingEvent<RecordedPushClip> {
+ public:
+ RecordedPushClip(DrawTarget* aDT, ReferencePtr aPath)
+ : RecordedDrawingEvent(PUSHCLIP, aDT), 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 RecordedDrawingEvent<RecordedPushClipRect> {
+ public:
+ RecordedPushClipRect(DrawTarget* aDT, const Rect& aRect)
+ : RecordedDrawingEvent(PUSHCLIPRECT, aDT), 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 RecordedDrawingEvent<RecordedPopClip> {
+ public:
+ MOZ_IMPLICIT RecordedPopClip(DrawTarget* aDT)
+ : RecordedDrawingEvent(POPCLIP, aDT) {}
+
+ 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 RecordedDrawingEvent<RecordedPushLayer> {
+ public:
+ RecordedPushLayer(DrawTarget* aDT, bool aOpaque, Float aOpacity,
+ SourceSurface* aMask, const Matrix& aMaskTransform,
+ const IntRect& aBounds, bool aCopyBackground)
+ : RecordedDrawingEvent(PUSHLAYER, aDT),
+ 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 RecordedDrawingEvent<RecordedPushLayerWithBlend> {
+ public:
+ RecordedPushLayerWithBlend(DrawTarget* aDT, bool aOpaque, Float aOpacity,
+ SourceSurface* aMask, const Matrix& aMaskTransform,
+ const IntRect& aBounds, bool aCopyBackground,
+ CompositionOp aCompositionOp)
+ : RecordedDrawingEvent(PUSHLAYERWITHBLEND, aDT),
+ 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 RecordedDrawingEvent<RecordedPopLayer> {
+ public:
+ MOZ_IMPLICIT RecordedPopLayer(DrawTarget* aDT)
+ : RecordedDrawingEvent(POPLAYER, aDT) {}
+
+ 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 RecordedSetTransform : public RecordedDrawingEvent<RecordedSetTransform> {
+ public:
+ RecordedSetTransform(DrawTarget* aDT, const Matrix& aTransform)
+ : RecordedDrawingEvent(SETTRANSFORM, aDT), 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 RecordedDrawingEvent<RecordedDrawSurface> {
+ public:
+ RecordedDrawSurface(DrawTarget* aDT, ReferencePtr aRefSource,
+ const Rect& aDest, const Rect& aSource,
+ const DrawSurfaceOptions& aDSOptions,
+ const DrawOptions& aOptions)
+ : RecordedDrawingEvent(DRAWSURFACE, aDT),
+ 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 RecordedDrawDependentSurface
+ : public RecordedDrawingEvent<RecordedDrawDependentSurface> {
+ public:
+ RecordedDrawDependentSurface(DrawTarget* aDT, uint64_t aId, const Rect& aDest)
+ : RecordedDrawingEvent(DRAWDEPENDENTSURFACE, aDT),
+ 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 RecordedDrawingEvent<RecordedDrawSurfaceWithShadow> {
+ public:
+ RecordedDrawSurfaceWithShadow(DrawTarget* aDT, ReferencePtr aRefSource,
+ const Point& aDest,
+ const ShadowOptions& aShadow, CompositionOp aOp)
+ : RecordedDrawingEvent(DRAWSURFACEWITHSHADOW, aDT),
+ 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 RecordedDrawFilter : public RecordedDrawingEvent<RecordedDrawFilter> {
+ public:
+ RecordedDrawFilter(DrawTarget* aDT, ReferencePtr aNode,
+ const Rect& aSourceRect, const Point& aDestPoint,
+ const DrawOptions& aOptions)
+ : RecordedDrawingEvent(DRAWFILTER, aDT),
+ 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(DrawTarget* aDT, 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 aDT,
+ ReferencePtr aOptimizedSurface)
+ : RecordedEventDerived(OPTIMIZESOURCESURFACE),
+ mSurface(aSurface),
+ mDT(aDT),
+ 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 mDT;
+ 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 aDT, ReferencePtr aRefPtr,
+ FilterType aType)
+ : RecordedEventDerived(FILTERNODECREATION),
+ mDT(aDT),
+ 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 mDT;
+ 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 aDT, ReferencePtr aRefPtr,
+ GradientStop* aStops, uint32_t aNumStops,
+ ExtendMode aExtendMode)
+ : RecordedEventDerived(GRADIENTSTOPSCREATION),
+ mDT(aDT),
+ 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 mDT;
+ 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 RecordedDrawingEvent<RecordedFlush> {
+ public:
+ explicit RecordedFlush(DrawTarget* aDT) : RecordedDrawingEvent(FLUSH, aDT) {}
+
+ 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 RecordedDrawingEvent<RecordedDetachAllSnapshots> {
+ public:
+ explicit RecordedDetachAllSnapshots(DrawTarget* aDT)
+ : RecordedDrawingEvent(DETACHALLSNAPSHOTS, aDT) {}
+
+ 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:
+ RecordedSnapshot(ReferencePtr aRefPtr, DrawTarget* aDT)
+ : RecordedEventDerived(SNAPSHOT), mRefPtr(aRefPtr), mDT(aDT) {}
+
+ 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;
+ ReferencePtr mDT;
+
+ template <class S>
+ MOZ_IMPLICIT RecordedSnapshot(S& aStream);
+};
+
+class RecordedIntoLuminanceSource
+ : public RecordedEventDerived<RecordedIntoLuminanceSource> {
+ public:
+ RecordedIntoLuminanceSource(ReferencePtr aRefPtr, DrawTarget* aDT,
+ LuminanceType aLuminanceType, float aOpacity)
+ : RecordedEventDerived(INTOLUMINANCE),
+ mRefPtr(aRefPtr),
+ mDT(aDT),
+ 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;
+ ReferencePtr mDT;
+ LuminanceType mLuminanceType;
+ float mOpacity;
+
+ template <class S>
+ MOZ_IMPLICIT RecordedIntoLuminanceSource(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 RecordedDrawingEvent<RecordedMaskSurface> {
+ public:
+ RecordedMaskSurface(DrawTarget* aDT, const Pattern& aPattern,
+ ReferencePtr aRefMask, const Point& aOffset,
+ const DrawOptions& aOptions)
+ : RecordedDrawingEvent(MASKSURFACE, aDT),
+ 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 RecordedDrawingEvent<RecordedLink> {
+ public:
+ RecordedLink(DrawTarget* aDT, const char* aDestination, const Rect& aRect)
+ : RecordedDrawingEvent(LINK, aDT),
+ 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 RecordedDrawingEvent<RecordedDestination> {
+ public:
+ RecordedDestination(DrawTarget* aDT, const char* aDestination,
+ const Point& aPoint)
+ : RecordedDrawingEvent(DESTINATION, aDT),
+ 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.mDashOffset);
+ WriteElement(aStream, aStrokeOptions.mLineWidth);
+ WriteElement(aStream, aStrokeOptions.mMiterLimit);
+ WriteElement(aStream, joinStyle);
+ WriteElement(aStream, capStyle);
+
+ if (!aStrokeOptions.mDashPattern) {
+ return;
+ }
+
+ 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.mDashOffset);
+ 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;
+ }
+
+ 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;
+ }
+ }
+}
+
+template <class T>
+template <class S>
+RecordedDrawingEvent<T>::RecordedDrawingEvent(RecordedEvent::EventType aType,
+ S& aStream)
+ : RecordedEventDerived<T>(aType) {
+ ReadElement(aStream, mDT);
+}
+
+template <class T>
+template <class S>
+void RecordedDrawingEvent<T>::Record(S& aStream) const {
+ WriteElement(aStream, mDT);
+}
+
+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 RecordedCreateSimilarDrawTarget::PlayEvent(
+ Translator* aTranslator) const {
+ DrawTarget* drawTarget = aTranslator->LookupDrawTarget(mDT);
+ 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, mDT);
+ WriteElement(aStream, mRefPtr);
+ WriteElement(aStream, mSize);
+ WriteElement(aStream, mFormat);
+}
+
+template <class S>
+RecordedCreateSimilarDrawTarget::RecordedCreateSimilarDrawTarget(S& aStream)
+ : RecordedEventDerived(CREATESIMILARDRAWTARGET) {
+ ReadElement(aStream, mDT);
+ ReadElement(aStream, mRefPtr);
+ ReadElement(aStream, mSize);
+ ReadElementConstrained(aStream, mFormat, SurfaceFormat::A8R8G8B8_UINT32,
+ SurfaceFormat::UNKNOWN);
+}
+
+inline void RecordedCreateSimilarDrawTarget::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] [" << mRefPtr
+ << "] CreateSimilarDrawTarget (Size: " << mSize.width << "x"
+ << mSize.height << ")";
+}
+
+inline bool RecordedCreateDrawTargetForFilter::PlayEvent(
+ Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ 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);
+ 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->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mRefPtr);
+ WriteElement(aStream, mBounds);
+ WriteElement(aStream, mFormat);
+}
+
+template <class S>
+RecordedCreateClippedDrawTarget::RecordedCreateClippedDrawTarget(S& aStream)
+ : RecordedDrawingEvent(CREATECLIPPEDDRAWTARGET, aStream) {
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ 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)
+ : RecordedDrawingEvent(CREATEDRAWTARGETFORFILTER, aStream) {
+ 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->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->FillRect(mRect, *GenericPattern(mPattern, aTranslator), mOptions);
+ return true;
+}
+
+template <class S>
+void RecordedFillRect::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mRect);
+ WriteElement(aStream, mOptions);
+ RecordPatternData(aStream, mPattern);
+}
+
+template <class S>
+RecordedFillRect::RecordedFillRect(S& aStream)
+ : RecordedDrawingEvent(FILLRECT, aStream) {
+ ReadElement(aStream, mRect);
+ ReadDrawOptions(aStream, mOptions);
+ ReadPatternData(aStream, mPattern);
+}
+
+inline void RecordedFillRect::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] FillRect (" << mRect.X() << ", "
+ << mRect.Y() << " - " << mRect.Width() << " x "
+ << mRect.Height() << ") ";
+ OutputSimplePatternInfo(mPattern, aStringStream);
+}
+
+inline bool RecordedStrokeRect::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->StrokeRect(mRect, *GenericPattern(mPattern, aTranslator), mStrokeOptions,
+ mOptions);
+ return true;
+}
+
+template <class S>
+void RecordedStrokeRect::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mRect);
+ WriteElement(aStream, mOptions);
+ RecordPatternData(aStream, mPattern);
+ RecordStrokeOptions(aStream, mStrokeOptions);
+}
+
+template <class S>
+RecordedStrokeRect::RecordedStrokeRect(S& aStream)
+ : RecordedDrawingEvent(STROKERECT, aStream) {
+ ReadElement(aStream, mRect);
+ ReadDrawOptions(aStream, mOptions);
+ ReadPatternData(aStream, mPattern);
+ ReadStrokeOptions(aStream, mStrokeOptions);
+}
+
+inline void RecordedStrokeRect::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] 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->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->StrokeLine(mBegin, mEnd, *GenericPattern(mPattern, aTranslator),
+ mStrokeOptions, mOptions);
+ return true;
+}
+
+template <class S>
+void RecordedStrokeLine::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mBegin);
+ WriteElement(aStream, mEnd);
+ WriteElement(aStream, mOptions);
+ RecordPatternData(aStream, mPattern);
+ RecordStrokeOptions(aStream, mStrokeOptions);
+}
+
+template <class S>
+RecordedStrokeLine::RecordedStrokeLine(S& aStream)
+ : RecordedDrawingEvent(STROKELINE, aStream) {
+ ReadElement(aStream, mBegin);
+ ReadElement(aStream, mEnd);
+ ReadDrawOptions(aStream, mOptions);
+ ReadPatternData(aStream, mPattern);
+ ReadStrokeOptions(aStream, mStrokeOptions);
+}
+
+inline void RecordedStrokeLine::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] StrokeLine (" << mBegin.x << ", "
+ << mBegin.y << " - " << mEnd.x << ", " << mEnd.y
+ << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
+ OutputSimplePatternInfo(mPattern, aStringStream);
+}
+
+inline bool RecordedFill::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->Fill(aTranslator->LookupPath(mPath),
+ *GenericPattern(mPattern, aTranslator), mOptions);
+ return true;
+}
+
+template <class S>
+RecordedFill::RecordedFill(S& aStream) : RecordedDrawingEvent(FILL, aStream) {
+ ReadElement(aStream, mPath);
+ ReadDrawOptions(aStream, mOptions);
+ ReadPatternData(aStream, mPattern);
+}
+
+template <class S>
+void RecordedFill::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mPath);
+ WriteElement(aStream, mOptions);
+ RecordPatternData(aStream, mPattern);
+}
+
+inline void RecordedFill::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] Fill (" << mPath << ") ";
+ OutputSimplePatternInfo(mPattern, aStringStream);
+}
+
+inline RecordedFillGlyphs::~RecordedFillGlyphs() { delete[] mGlyphs; }
+
+inline bool RecordedFillGlyphs::PlayEvent(Translator* aTranslator) const {
+ if (mNumGlyphs > 0 && !mGlyphs) {
+ // Glyph allocation failed
+ return false;
+ }
+
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ ScaledFont* scaledFont = aTranslator->LookupScaledFont(mScaledFont);
+ if (!scaledFont) {
+ return false;
+ }
+
+ GlyphBuffer buffer;
+ buffer.mGlyphs = mGlyphs;
+ buffer.mNumGlyphs = mNumGlyphs;
+ dt->FillGlyphs(scaledFont, buffer, *GenericPattern(mPattern, aTranslator),
+ mOptions);
+ return true;
+}
+
+template <class S>
+RecordedFillGlyphs::RecordedFillGlyphs(S& aStream)
+ : RecordedDrawingEvent(FILLGLYPHS, aStream) {
+ ReadElement(aStream, mScaledFont);
+ ReadDrawOptions(aStream, mOptions);
+ ReadPatternData(aStream, mPattern);
+ ReadElement(aStream, mNumGlyphs);
+ if (!aStream.good() || mNumGlyphs <= 0) {
+ return;
+ }
+
+ mGlyphs = new (fallible) Glyph[mNumGlyphs];
+ if (!mGlyphs) {
+ gfxCriticalNote << "RecordedFillGlyphs failed to allocate glyphs of size "
+ << mNumGlyphs;
+ aStream.SetIsBad();
+ } else {
+ aStream.read((char*)mGlyphs, sizeof(Glyph) * mNumGlyphs);
+ }
+}
+
+template <class S>
+void RecordedFillGlyphs::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mScaledFont);
+ WriteElement(aStream, mOptions);
+ RecordPatternData(aStream, mPattern);
+ WriteElement(aStream, mNumGlyphs);
+ aStream.write((char*)mGlyphs, sizeof(Glyph) * mNumGlyphs);
+}
+
+inline void RecordedFillGlyphs::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] FillGlyphs (" << mScaledFont << ") ";
+ OutputSimplePatternInfo(mPattern, aStringStream);
+}
+
+inline bool RecordedMask::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->Mask(*GenericPattern(mSource, aTranslator),
+ *GenericPattern(mMask, aTranslator), mOptions);
+ return true;
+}
+
+template <class S>
+RecordedMask::RecordedMask(S& aStream) : RecordedDrawingEvent(MASK, aStream) {
+ ReadDrawOptions(aStream, mOptions);
+ ReadPatternData(aStream, mSource);
+ ReadPatternData(aStream, mMask);
+}
+
+template <class S>
+void RecordedMask::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mOptions);
+ RecordPatternData(aStream, mSource);
+ RecordPatternData(aStream, mMask);
+}
+
+inline void RecordedMask::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] Mask (Source: ";
+ OutputSimplePatternInfo(mSource, aStringStream);
+ aStringStream << " Mask: ";
+ OutputSimplePatternInfo(mMask, aStringStream);
+}
+
+inline bool RecordedStroke::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mPath);
+ WriteElement(aStream, mOptions);
+ RecordPatternData(aStream, mPattern);
+ RecordStrokeOptions(aStream, mStrokeOptions);
+}
+
+template <class S>
+RecordedStroke::RecordedStroke(S& aStream)
+ : RecordedDrawingEvent(STROKE, aStream) {
+ ReadElement(aStream, mPath);
+ ReadDrawOptions(aStream, mOptions);
+ ReadPatternData(aStream, mPattern);
+ ReadStrokeOptions(aStream, mStrokeOptions);
+}
+
+inline void RecordedStroke::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] Stroke (" << mPath
+ << ") LineWidth: " << mStrokeOptions.mLineWidth << "px ";
+ OutputSimplePatternInfo(mPattern, aStringStream);
+}
+
+inline bool RecordedClearRect::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->ClearRect(mRect);
+ return true;
+}
+
+template <class S>
+void RecordedClearRect::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mRect);
+}
+
+template <class S>
+RecordedClearRect::RecordedClearRect(S& aStream)
+ : RecordedDrawingEvent(CLEARRECT, aStream) {
+ ReadElement(aStream, mRect);
+}
+
+inline void RecordedClearRect::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] ClearRect (" << mRect.X() << ", "
+ << mRect.Y() << " - " << mRect.Width() << " x "
+ << mRect.Height() << ") ";
+}
+
+inline bool RecordedCopySurface::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mSourceSurface);
+ WriteElement(aStream, mSourceRect);
+ WriteElement(aStream, mDest);
+}
+
+template <class S>
+RecordedCopySurface::RecordedCopySurface(S& aStream)
+ : RecordedDrawingEvent(COPYSURFACE, aStream) {
+ ReadElement(aStream, mSourceSurface);
+ ReadElement(aStream, mSourceRect);
+ ReadElement(aStream, mDest);
+}
+
+inline void RecordedCopySurface::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] CopySurface (" << mSourceSurface << ")";
+}
+
+inline bool RecordedPushClip::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mPath);
+}
+
+template <class S>
+RecordedPushClip::RecordedPushClip(S& aStream)
+ : RecordedDrawingEvent(PUSHCLIP, aStream) {
+ ReadElement(aStream, mPath);
+}
+
+inline void RecordedPushClip::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] PushClip (" << mPath << ") ";
+}
+
+inline bool RecordedPushClipRect::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->PushClipRect(mRect);
+ return true;
+}
+
+template <class S>
+void RecordedPushClipRect::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mRect);
+}
+
+template <class S>
+RecordedPushClipRect::RecordedPushClipRect(S& aStream)
+ : RecordedDrawingEvent(PUSHCLIPRECT, aStream) {
+ ReadElement(aStream, mRect);
+}
+
+inline void RecordedPushClipRect::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] PushClipRect (" << mRect.X() << ", "
+ << mRect.Y() << " - " << mRect.Width() << " x "
+ << mRect.Height() << ") ";
+}
+
+inline bool RecordedPopClip::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->PopClip();
+ return true;
+}
+
+template <class S>
+void RecordedPopClip::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+}
+
+template <class S>
+RecordedPopClip::RecordedPopClip(S& aStream)
+ : RecordedDrawingEvent(POPCLIP, aStream) {}
+
+inline void RecordedPopClip::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] PopClip";
+}
+
+inline bool RecordedPushLayer::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ 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)
+ : RecordedDrawingEvent(PUSHLAYER, aStream) {
+ 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 << "[" << mDT << "] PushPLayer (Opaque=" << mOpaque
+ << ", Opacity=" << mOpacity << ", Mask Ref=" << mMask << ") ";
+}
+
+inline bool RecordedPushLayerWithBlend::PlayEvent(
+ Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ 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)
+ : RecordedDrawingEvent(PUSHLAYERWITHBLEND, aStream) {
+ 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 << "[" << mDT << "] PushLayerWithBlend (Opaque=" << mOpaque
+ << ", Opacity=" << mOpacity << ", Mask Ref=" << mMask << ") ";
+}
+
+inline bool RecordedPopLayer::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->PopLayer();
+ return true;
+}
+
+template <class S>
+void RecordedPopLayer::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+}
+
+template <class S>
+RecordedPopLayer::RecordedPopLayer(S& aStream)
+ : RecordedDrawingEvent(POPLAYER, aStream) {}
+
+inline void RecordedPopLayer::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] PopLayer";
+}
+
+inline bool RecordedSetTransform::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mTransform);
+}
+
+template <class S>
+RecordedSetTransform::RecordedSetTransform(S& aStream)
+ : RecordedDrawingEvent(SETTRANSFORM, aStream) {
+ ReadElement(aStream, mTransform);
+}
+
+inline void RecordedSetTransform::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] SetTransform [ " << mTransform._11 << " "
+ << mTransform._12 << " ; " << mTransform._21 << " "
+ << mTransform._22 << " ; " << mTransform._31 << " "
+ << mTransform._32 << " ]";
+}
+
+inline bool RecordedDrawSurface::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mRefSource);
+ WriteElement(aStream, mDest);
+ WriteElement(aStream, mSource);
+ WriteElement(aStream, mDSOptions);
+ WriteElement(aStream, mOptions);
+}
+
+template <class S>
+RecordedDrawSurface::RecordedDrawSurface(S& aStream)
+ : RecordedDrawingEvent(DRAWSURFACE, aStream) {
+ ReadElement(aStream, mRefSource);
+ ReadElement(aStream, mDest);
+ ReadElement(aStream, mSource);
+ ReadDrawSurfaceOptions(aStream, mDSOptions);
+ ReadDrawOptions(aStream, mOptions);
+}
+
+inline void RecordedDrawSurface::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] DrawSurface (" << mRefSource << ")";
+}
+
+inline bool RecordedDrawDependentSurface::PlayEvent(
+ Translator* aTranslator) const {
+ aTranslator->DrawDependentSurface(mDT, mId, mDest);
+ return true;
+}
+
+template <class S>
+void RecordedDrawDependentSurface::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mId);
+ WriteElement(aStream, mDest);
+}
+
+template <class S>
+RecordedDrawDependentSurface::RecordedDrawDependentSurface(S& aStream)
+ : RecordedDrawingEvent(DRAWDEPENDENTSURFACE, aStream) {
+ ReadElement(aStream, mId);
+ ReadElement(aStream, mDest);
+}
+
+inline void RecordedDrawDependentSurface::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] DrawDependentSurface (" << mId << ")";
+}
+
+inline bool RecordedDrawFilter::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mNode);
+ WriteElement(aStream, mSourceRect);
+ WriteElement(aStream, mDestPoint);
+ WriteElement(aStream, mOptions);
+}
+
+template <class S>
+RecordedDrawFilter::RecordedDrawFilter(S& aStream)
+ : RecordedDrawingEvent(DRAWFILTER, aStream) {
+ ReadElement(aStream, mNode);
+ ReadElement(aStream, mSourceRect);
+ ReadElement(aStream, mDestPoint);
+ ReadDrawOptions(aStream, mOptions);
+}
+
+inline void RecordedDrawFilter::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] DrawFilter (" << mNode << ")";
+}
+
+inline bool RecordedDrawSurfaceWithShadow::PlayEvent(
+ Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ WriteElement(aStream, mRefSource);
+ WriteElement(aStream, mDest);
+ WriteElement(aStream, mShadow);
+ WriteElement(aStream, mOp);
+}
+
+template <class S>
+RecordedDrawSurfaceWithShadow::RecordedDrawSurfaceWithShadow(S& aStream)
+ : RecordedDrawingEvent(DRAWSURFACEWITHSHADOW, aStream) {
+ 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 << "[" << mDT << "] DrawSurfaceWithShadow (" << mRefSource
+ << ") DeviceColor: (" << mShadow.mColor.r << ", "
+ << mShadow.mColor.g << ", " << mShadow.mColor.b << ", "
+ << mShadow.mColor.a << ")";
+}
+
+inline RecordedPathCreation::RecordedPathCreation(DrawTarget* aDT,
+ PathRecording* aPath)
+ : RecordedEventDerived(PATHCREATION),
+ mDT(aDT),
+ mRefPtr(aPath),
+ mFillRule(aPath->mFillRule),
+ mPath(aPath) {}
+
+inline bool RecordedPathCreation::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* drawTarget = aTranslator->LookupDrawTarget(mDT);
+ 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, mDT);
+ WriteElement(aStream, mRefPtr);
+ WriteElement(aStream, mFillRule);
+ mPath->mPathOps.Record(aStream);
+}
+
+template <class S>
+RecordedPathCreation::RecordedPathCreation(S& aStream)
+ : RecordedEventDerived(PATHCREATION) {
+ ReadElement(aStream, mDT);
+ 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 << "[" << mDT << "] [" << 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->LookupDrawTarget(mDT);
+ 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, mDT);
+ WriteElement(aStream, mOptimizedSurface);
+}
+
+template <class S>
+RecordedOptimizeSourceSurface::RecordedOptimizeSourceSurface(S& aStream)
+ : RecordedEventDerived(OPTIMIZESOURCESURFACE) {
+ ReadElement(aStream, mSurface);
+ ReadElement(aStream, mDT);
+ ReadElement(aStream, mOptimizedSurface);
+}
+
+inline void RecordedOptimizeSourceSurface::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mSurface << "] Surface Optimized (DT: " << mDT << ")";
+}
+
+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->LookupDrawTarget(mDT);
+ 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, mDT);
+ WriteElement(aStream, mRefPtr);
+ WriteElement(aStream, mType);
+}
+
+template <class S>
+RecordedFilterNodeCreation::RecordedFilterNodeCreation(S& aStream)
+ : RecordedEventDerived(FILTERNODECREATION) {
+ ReadElement(aStream, mDT);
+ ReadElement(aStream, mRefPtr);
+ ReadElementConstrained(aStream, mType, FilterType::BLEND,
+ FilterType::OPACITY);
+}
+
+inline void RecordedFilterNodeCreation::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] 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->LookupDrawTarget(mDT);
+ 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, mDT);
+ 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, mDT);
+ 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 << "[" << mDT << "] [" << 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->LookupDrawTarget(mDT);
+ 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, mDT);
+ WriteElement(aStream, mLuminanceType);
+ WriteElement(aStream, mOpacity);
+}
+
+template <class S>
+RecordedIntoLuminanceSource::RecordedIntoLuminanceSource(S& aStream)
+ : RecordedEventDerived(INTOLUMINANCE) {
+ ReadElement(aStream, mRefPtr);
+ ReadElement(aStream, mDT);
+ ReadElementConstrained(aStream, mLuminanceType, LuminanceType::LUMINANCE,
+ LuminanceType::LINEARRGB);
+ ReadElement(aStream, mOpacity);
+}
+
+inline void RecordedIntoLuminanceSource::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mRefPtr << "] Into Luminance Source (DT: " << mDT
+ << ")";
+}
+
+inline bool RecordedFlush::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->Flush();
+ return true;
+}
+
+template <class S>
+void RecordedFlush::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+}
+
+template <class S>
+RecordedFlush::RecordedFlush(S& aStream)
+ : RecordedDrawingEvent(FLUSH, aStream) {}
+
+inline void RecordedFlush::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] Flush";
+}
+
+inline bool RecordedDetachAllSnapshots::PlayEvent(
+ Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ dt->DetachAllSnapshots();
+ return true;
+}
+
+template <class S>
+void RecordedDetachAllSnapshots::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+}
+
+template <class S>
+RecordedDetachAllSnapshots::RecordedDetachAllSnapshots(S& aStream)
+ : RecordedDrawingEvent(DETACHALLSNAPSHOTS, aStream) {}
+
+inline void RecordedDetachAllSnapshots::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] DetachAllSnapshots";
+}
+
+inline bool RecordedSnapshot::PlayEvent(Translator* aTranslator) const {
+ DrawTarget* dt = aTranslator->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+
+ RefPtr<SourceSurface> src = aTranslator->LookupDrawTarget(mDT)->Snapshot();
+ aTranslator->AddSourceSurface(mRefPtr, src);
+ return true;
+}
+
+template <class S>
+void RecordedSnapshot::Record(S& aStream) const {
+ WriteElement(aStream, mRefPtr);
+ WriteElement(aStream, mDT);
+}
+
+template <class S>
+RecordedSnapshot::RecordedSnapshot(S& aStream)
+ : RecordedEventDerived(SNAPSHOT) {
+ ReadElement(aStream, mRefPtr);
+ ReadElement(aStream, mDT);
+}
+
+inline void RecordedSnapshot::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mRefPtr << "] Snapshot Created (DT: " << mDT << ")";
+}
+
+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->LookupDrawTarget(mDT);
+ 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 {
+ RecordedDrawingEvent::Record(aStream);
+ RecordPatternData(aStream, mPattern);
+ WriteElement(aStream, mRefMask);
+ WriteElement(aStream, mOffset);
+ WriteElement(aStream, mOptions);
+}
+
+template <class S>
+RecordedMaskSurface::RecordedMaskSurface(S& aStream)
+ : RecordedDrawingEvent(MASKSURFACE, aStream) {
+ ReadPatternData(aStream, mPattern);
+ ReadElement(aStream, mRefMask);
+ ReadElement(aStream, mOffset);
+ ReadDrawOptions(aStream, mOptions);
+}
+
+inline void RecordedMaskSurface::OutputSimpleEventInfo(
+ std::stringstream& aStringStream) const {
+ aStringStream << "[" << mDT << "] 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->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+ dt->Link(mDestination.c_str(), mRect);
+ return true;
+}
+
+template <class S>
+void RecordedLink::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ 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) : RecordedDrawingEvent(LINK, aStream) {
+ 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->LookupDrawTarget(mDT);
+ if (!dt) {
+ return false;
+ }
+ dt->Destination(mDestination.c_str(), mPoint);
+ return true;
+}
+
+template <class S>
+void RecordedDestination::Record(S& aStream) const {
+ RecordedDrawingEvent::Record(aStream);
+ 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)
+ : RecordedDrawingEvent(DESTINATION, aStream) {
+ 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(FILLRECT, RecordedFillRect); \
+ f(STROKERECT, RecordedStrokeRect); \
+ f(STROKELINE, RecordedStrokeLine); \
+ f(CLEARRECT, RecordedClearRect); \
+ f(COPYSURFACE, RecordedCopySurface); \
+ f(SETTRANSFORM, RecordedSetTransform); \
+ f(PUSHCLIPRECT, RecordedPushClipRect); \
+ f(PUSHCLIP, RecordedPushClip); \
+ f(POPCLIP, RecordedPopClip); \
+ f(FILL, RecordedFill); \
+ f(FILLGLYPHS, RecordedFillGlyphs); \
+ f(MASK, RecordedMask); \
+ f(STROKE, RecordedStroke); \
+ f(DRAWSURFACE, RecordedDrawSurface); \
+ f(DRAWDEPENDENTSURFACE, RecordedDrawDependentSurface); \
+ f(DRAWSURFACEWITHSHADOW, RecordedDrawSurfaceWithShadow); \
+ 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(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