michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "DrawTargetRecording.h" michael@0: #include "PathRecording.h" michael@0: #include michael@0: michael@0: #include "Logging.h" michael@0: #include "Tools.h" michael@0: #include "Filters.h" michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: michael@0: class SourceSurfaceRecording : public SourceSurface michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording) michael@0: SourceSurfaceRecording(SourceSurface *aFinalSurface, DrawEventRecorderPrivate *aRecorder) michael@0: : mFinalSurface(aFinalSurface), mRecorder(aRecorder) michael@0: { michael@0: } michael@0: michael@0: ~SourceSurfaceRecording() michael@0: { michael@0: mRecorder->RecordEvent(RecordedSourceSurfaceDestruction(this)); michael@0: } michael@0: michael@0: virtual SurfaceType GetType() const { return SurfaceType::RECORDING; } michael@0: virtual IntSize GetSize() const { return mFinalSurface->GetSize(); } michael@0: virtual SurfaceFormat GetFormat() const { return mFinalSurface->GetFormat(); } michael@0: virtual TemporaryRef GetDataSurface() { return mFinalSurface->GetDataSurface(); } michael@0: michael@0: RefPtr mFinalSurface; michael@0: RefPtr mRecorder; michael@0: }; michael@0: michael@0: class GradientStopsRecording : public GradientStops michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsRecording) michael@0: GradientStopsRecording(GradientStops *aFinalGradientStops, DrawEventRecorderPrivate *aRecorder) michael@0: : mFinalGradientStops(aFinalGradientStops), mRecorder(aRecorder) michael@0: { michael@0: } michael@0: michael@0: ~GradientStopsRecording() michael@0: { michael@0: mRecorder->RecordEvent(RecordedGradientStopsDestruction(this)); michael@0: } michael@0: michael@0: virtual BackendType GetBackendType() const { return BackendType::RECORDING; } michael@0: michael@0: RefPtr mFinalGradientStops; michael@0: RefPtr mRecorder; michael@0: }; michael@0: michael@0: static SourceSurface * michael@0: GetSourceSurface(SourceSurface *aSurface) michael@0: { michael@0: if (aSurface->GetType() != SurfaceType::RECORDING) { michael@0: return aSurface; michael@0: } michael@0: michael@0: return static_cast(aSurface)->mFinalSurface; michael@0: } michael@0: michael@0: static GradientStops * michael@0: GetGradientStops(GradientStops *aStops) michael@0: { michael@0: if (aStops->GetBackendType() != BackendType::RECORDING) { michael@0: return aStops; michael@0: } michael@0: michael@0: return static_cast(aStops)->mFinalGradientStops; michael@0: } michael@0: michael@0: class FilterNodeRecording : public FilterNode michael@0: { michael@0: public: michael@0: MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeRecording) michael@0: using FilterNode::SetAttribute; michael@0: michael@0: FilterNodeRecording(FilterNode *aFinalFilterNode, DrawEventRecorderPrivate *aRecorder) michael@0: : mFinalFilterNode(aFinalFilterNode), mRecorder(aRecorder) michael@0: { michael@0: } michael@0: michael@0: ~FilterNodeRecording() michael@0: { michael@0: mRecorder->RecordEvent(RecordedFilterNodeDestruction(this)); michael@0: } michael@0: michael@0: virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface) michael@0: { michael@0: mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aSurface)); michael@0: mFinalFilterNode->SetInput(aIndex, GetSourceSurface(aSurface)); michael@0: } michael@0: virtual void SetInput(uint32_t aIndex, FilterNode *aFilter) michael@0: { michael@0: FilterNode *finalNode = aFilter; michael@0: if (aFilter->GetBackendType() != FILTER_BACKEND_RECORDING) { michael@0: gfxWarning() << "Non recording filter node used with recording DrawTarget!"; michael@0: } else { michael@0: finalNode = static_cast(aFilter)->mFinalFilterNode; michael@0: } michael@0: michael@0: mRecorder->RecordEvent(RecordedFilterNodeSetInput(this, aIndex, aFilter)); michael@0: mFinalFilterNode->SetInput(aIndex, finalNode); michael@0: } michael@0: michael@0: michael@0: #define FORWARD_SET_ATTRIBUTE(type, argtype) \ michael@0: virtual void SetAttribute(uint32_t aIndex, type aValue) { \ michael@0: mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aValue, RecordedFilterNodeSetAttribute::ARGTYPE_##argtype)); \ michael@0: mFinalFilterNode->SetAttribute(aIndex, aValue); \ michael@0: } michael@0: michael@0: FORWARD_SET_ATTRIBUTE(bool, BOOL); michael@0: FORWARD_SET_ATTRIBUTE(uint32_t, UINT32); michael@0: FORWARD_SET_ATTRIBUTE(Float, FLOAT); michael@0: FORWARD_SET_ATTRIBUTE(const Size&, SIZE); michael@0: FORWARD_SET_ATTRIBUTE(const IntSize&, INTSIZE); michael@0: FORWARD_SET_ATTRIBUTE(const IntPoint&, INTPOINT); michael@0: FORWARD_SET_ATTRIBUTE(const Rect&, RECT); michael@0: FORWARD_SET_ATTRIBUTE(const IntRect&, INTRECT); michael@0: FORWARD_SET_ATTRIBUTE(const Point&, POINT); michael@0: FORWARD_SET_ATTRIBUTE(const Matrix5x4&, MATRIX5X4); michael@0: FORWARD_SET_ATTRIBUTE(const Point3D&, POINT3D); michael@0: FORWARD_SET_ATTRIBUTE(const Color&, COLOR); michael@0: michael@0: #undef FORWARD_SET_ATTRIBUTE michael@0: michael@0: virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) { michael@0: mRecorder->RecordEvent(RecordedFilterNodeSetAttribute(this, aIndex, aFloat, aSize)); michael@0: mFinalFilterNode->SetAttribute(aIndex, aFloat, aSize); michael@0: } michael@0: michael@0: virtual FilterBackend GetBackendType() MOZ_OVERRIDE { return FILTER_BACKEND_RECORDING; } michael@0: michael@0: RefPtr mFinalFilterNode; michael@0: RefPtr mRecorder; michael@0: }; michael@0: michael@0: static FilterNode* michael@0: GetFilterNode(FilterNode* aNode) michael@0: { michael@0: if (aNode->GetBackendType() != FILTER_BACKEND_RECORDING) { michael@0: gfxWarning() << "Non recording filter node used with recording DrawTarget!"; michael@0: return aNode; michael@0: } michael@0: michael@0: return static_cast(aNode)->mFinalFilterNode; michael@0: } michael@0: michael@0: struct AdjustedPattern michael@0: { michael@0: AdjustedPattern(const Pattern &aPattern) michael@0: : mPattern(nullptr) michael@0: { michael@0: mOrigPattern = const_cast(&aPattern); michael@0: } michael@0: michael@0: ~AdjustedPattern() { michael@0: if (mPattern) { michael@0: mPattern->~Pattern(); michael@0: } michael@0: } michael@0: michael@0: operator Pattern*() michael@0: { michael@0: switch(mOrigPattern->GetType()) { michael@0: case PatternType::COLOR: michael@0: return mOrigPattern; michael@0: case PatternType::SURFACE: michael@0: { michael@0: SurfacePattern *surfPat = static_cast(mOrigPattern); michael@0: mPattern = michael@0: new (mSurfPat) SurfacePattern(GetSourceSurface(surfPat->mSurface), michael@0: surfPat->mExtendMode, surfPat->mMatrix, michael@0: surfPat->mFilter); michael@0: return mPattern; michael@0: } michael@0: case PatternType::LINEAR_GRADIENT: michael@0: { michael@0: LinearGradientPattern *linGradPat = static_cast(mOrigPattern); michael@0: mPattern = michael@0: new (mLinGradPat) LinearGradientPattern(linGradPat->mBegin, linGradPat->mEnd, michael@0: GetGradientStops(linGradPat->mStops), michael@0: linGradPat->mMatrix); michael@0: return mPattern; michael@0: } michael@0: case PatternType::RADIAL_GRADIENT: michael@0: { michael@0: RadialGradientPattern *radGradPat = static_cast(mOrigPattern); michael@0: mPattern = michael@0: new (mRadGradPat) RadialGradientPattern(radGradPat->mCenter1, radGradPat->mCenter2, michael@0: radGradPat->mRadius1, radGradPat->mRadius2, michael@0: GetGradientStops(radGradPat->mStops), michael@0: radGradPat->mMatrix); michael@0: return mPattern; michael@0: } michael@0: default: michael@0: return new (mColPat) ColorPattern(Color()); michael@0: } michael@0: michael@0: return mPattern; michael@0: } michael@0: michael@0: union { michael@0: char mColPat[sizeof(ColorPattern)]; michael@0: char mLinGradPat[sizeof(LinearGradientPattern)]; michael@0: char mRadGradPat[sizeof(RadialGradientPattern)]; michael@0: char mSurfPat[sizeof(SurfacePattern)]; michael@0: }; michael@0: michael@0: Pattern *mOrigPattern; michael@0: Pattern *mPattern; michael@0: }; michael@0: michael@0: DrawTargetRecording::DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData) michael@0: : mRecorder(static_cast(aRecorder)) michael@0: , mFinalDT(aDT) michael@0: { michael@0: RefPtr snapshot = aHasData ? mFinalDT->Snapshot() : nullptr; michael@0: mRecorder->RecordEvent(RecordedDrawTargetCreation(this, mFinalDT->GetType(), mFinalDT->GetSize(), mFinalDT->GetFormat(), michael@0: aHasData, snapshot)); michael@0: mFormat = mFinalDT->GetFormat(); michael@0: } michael@0: michael@0: DrawTargetRecording::~DrawTargetRecording() michael@0: { michael@0: mRecorder->RecordEvent(RecordedDrawTargetDestruction(this)); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::FillRect(const Rect &aRect, michael@0: const Pattern &aPattern, michael@0: const DrawOptions &aOptions) michael@0: { michael@0: mRecorder->RecordEvent(RecordedFillRect(this, aRect, aPattern, aOptions)); michael@0: mFinalDT->FillRect(aRect, *AdjustedPattern(aPattern), aOptions); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::StrokeRect(const Rect &aRect, michael@0: const Pattern &aPattern, michael@0: const StrokeOptions &aStrokeOptions, michael@0: const DrawOptions &aOptions) michael@0: { michael@0: mRecorder->RecordEvent(RecordedStrokeRect(this, aRect, aPattern, aStrokeOptions, aOptions)); michael@0: mFinalDT->StrokeRect(aRect, *AdjustedPattern(aPattern), aStrokeOptions, aOptions); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::StrokeLine(const Point &aBegin, michael@0: const Point &aEnd, michael@0: const Pattern &aPattern, michael@0: const StrokeOptions &aStrokeOptions, michael@0: const DrawOptions &aOptions) michael@0: { michael@0: mRecorder->RecordEvent(RecordedStrokeLine(this, aBegin, aEnd, aPattern, aStrokeOptions, aOptions)); michael@0: mFinalDT->StrokeLine(aBegin, aEnd, *AdjustedPattern(aPattern), aStrokeOptions, aOptions); michael@0: } michael@0: michael@0: Path* michael@0: DrawTargetRecording::GetPathForPathRecording(const Path *aPath) const michael@0: { michael@0: if (aPath->GetBackendType() != BackendType::RECORDING) { michael@0: return nullptr; michael@0: } michael@0: michael@0: return static_cast(aPath)->mPath; michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::Fill(const Path *aPath, michael@0: const Pattern &aPattern, michael@0: const DrawOptions &aOptions) michael@0: { michael@0: EnsureStored(aPath); michael@0: michael@0: mRecorder->RecordEvent(RecordedFill(this, const_cast(aPath), aPattern, aOptions)); michael@0: mFinalDT->Fill(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aOptions); michael@0: } michael@0: michael@0: struct RecordingFontUserData michael@0: { michael@0: void *refPtr; michael@0: RefPtr recorder; michael@0: }; michael@0: michael@0: void RecordingFontUserDataDestroyFunc(void *aUserData) michael@0: { michael@0: RecordingFontUserData *userData = michael@0: static_cast(aUserData); michael@0: michael@0: // TODO support font in b2g recordings michael@0: #ifndef MOZ_WIDGET_GONK michael@0: userData->recorder->RecordEvent(RecordedScaledFontDestruction(userData->refPtr)); michael@0: #endif michael@0: michael@0: delete userData; michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::FillGlyphs(ScaledFont *aFont, michael@0: const GlyphBuffer &aBuffer, michael@0: const Pattern &aPattern, michael@0: const DrawOptions &aOptions, michael@0: const GlyphRenderingOptions *aRenderingOptions) michael@0: { michael@0: if (!aFont->GetUserData(reinterpret_cast(mRecorder.get()))) { michael@0: // TODO support font in b2g recordings michael@0: #ifndef MOZ_WIDGET_GONK michael@0: mRecorder->RecordEvent(RecordedScaledFontCreation(aFont, aFont)); michael@0: #endif michael@0: RecordingFontUserData *userData = new RecordingFontUserData; michael@0: userData->refPtr = aFont; michael@0: userData->recorder = mRecorder; michael@0: aFont->AddUserData(reinterpret_cast(mRecorder.get()), userData, michael@0: &RecordingFontUserDataDestroyFunc); michael@0: } michael@0: michael@0: // TODO support font in b2g recordings michael@0: #ifndef MOZ_WIDGET_GONK michael@0: mRecorder->RecordEvent(RecordedFillGlyphs(this, aFont, aPattern, aOptions, aBuffer.mGlyphs, aBuffer.mNumGlyphs)); michael@0: #endif michael@0: mFinalDT->FillGlyphs(aFont, aBuffer, aPattern, aOptions, aRenderingOptions); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::Mask(const Pattern &aSource, michael@0: const Pattern &aMask, michael@0: const DrawOptions &aOptions) michael@0: { michael@0: mRecorder->RecordEvent(RecordedMask(this, aSource, aMask, aOptions)); michael@0: mFinalDT->Mask(*AdjustedPattern(aSource), *AdjustedPattern(aMask), aOptions); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::MaskSurface(const Pattern &aSource, michael@0: SourceSurface *aMask, michael@0: Point aOffset, michael@0: const DrawOptions &aOptions) michael@0: { michael@0: mRecorder->RecordEvent(RecordedMaskSurface(this, aSource, aMask, aOffset, aOptions)); michael@0: mFinalDT->MaskSurface(*AdjustedPattern(aSource), GetSourceSurface(aMask), aOffset, aOptions); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::Stroke(const Path *aPath, michael@0: const Pattern &aPattern, michael@0: const StrokeOptions &aStrokeOptions, michael@0: const DrawOptions &aOptions) michael@0: { michael@0: EnsureStored(aPath); michael@0: michael@0: mRecorder->RecordEvent(RecordedStroke(this, const_cast(aPath), aPattern, aStrokeOptions, aOptions)); michael@0: mFinalDT->Stroke(GetPathForPathRecording(aPath), *AdjustedPattern(aPattern), aStrokeOptions, aOptions); michael@0: } michael@0: michael@0: TemporaryRef michael@0: DrawTargetRecording::Snapshot() michael@0: { michael@0: RefPtr surf = mFinalDT->Snapshot(); michael@0: michael@0: RefPtr retSurf = new SourceSurfaceRecording(surf, mRecorder); michael@0: michael@0: mRecorder->RecordEvent(RecordedSnapshot(retSurf, this)); michael@0: michael@0: return retSurf; michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::DrawSurface(SourceSurface *aSurface, michael@0: const Rect &aDest, michael@0: const Rect &aSource, michael@0: const DrawSurfaceOptions &aSurfOptions, michael@0: const DrawOptions &aOptions) michael@0: { michael@0: mRecorder->RecordEvent(RecordedDrawSurface(this, aSurface, aDest, aSource, aSurfOptions, aOptions)); michael@0: mFinalDT->DrawSurface(GetSourceSurface(aSurface), aDest, aSource, aSurfOptions, aOptions); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::DrawSurfaceWithShadow(SourceSurface *aSurface, michael@0: const Point &aDest, michael@0: const Color &aColor, michael@0: const Point &aOffset, michael@0: Float aSigma, michael@0: CompositionOp aOp) michael@0: { michael@0: mRecorder->RecordEvent(RecordedDrawSurfaceWithShadow(this, aSurface, aDest, aColor, aOffset, aSigma, aOp)); michael@0: mFinalDT->DrawSurfaceWithShadow(GetSourceSurface(aSurface), aDest, aColor, aOffset, aSigma, aOp); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::DrawFilter(FilterNode *aNode, michael@0: const Rect &aSourceRect, michael@0: const Point &aDestPoint, michael@0: const DrawOptions &aOptions) michael@0: { michael@0: mRecorder->RecordEvent(RecordedDrawFilter(this, aNode, aSourceRect, aDestPoint, aOptions)); michael@0: mFinalDT->DrawFilter(GetFilterNode(aNode), aSourceRect, aDestPoint, aOptions); michael@0: } michael@0: michael@0: TemporaryRef michael@0: DrawTargetRecording::CreateFilter(FilterType aType) michael@0: { michael@0: RefPtr node = mFinalDT->CreateFilter(aType); michael@0: michael@0: RefPtr retNode = new FilterNodeRecording(node, mRecorder); michael@0: michael@0: mRecorder->RecordEvent(RecordedFilterNodeCreation(retNode, aType)); michael@0: michael@0: return retNode; michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::ClearRect(const Rect &aRect) michael@0: { michael@0: mRecorder->RecordEvent(RecordedClearRect(this, aRect)); michael@0: mFinalDT->ClearRect(aRect); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::CopySurface(SourceSurface *aSurface, michael@0: const IntRect &aSourceRect, michael@0: const IntPoint &aDestination) michael@0: { michael@0: mRecorder->RecordEvent(RecordedCopySurface(this, aSurface, aSourceRect, aDestination)); michael@0: mFinalDT->CopySurface(GetSourceSurface(aSurface), aSourceRect, aDestination); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::PushClip(const Path *aPath) michael@0: { michael@0: EnsureStored(aPath); michael@0: michael@0: mRecorder->RecordEvent(RecordedPushClip(this, const_cast(aPath))); michael@0: mFinalDT->PushClip(GetPathForPathRecording(aPath)); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::PushClipRect(const Rect &aRect) michael@0: { michael@0: mRecorder->RecordEvent(RecordedPushClipRect(this, aRect)); michael@0: mFinalDT->PushClipRect(aRect); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::PopClip() michael@0: { michael@0: mRecorder->RecordEvent(RecordedPopClip(this)); michael@0: mFinalDT->PopClip(); michael@0: } michael@0: michael@0: TemporaryRef michael@0: DrawTargetRecording::CreateSourceSurfaceFromData(unsigned char *aData, michael@0: const IntSize &aSize, michael@0: int32_t aStride, michael@0: SurfaceFormat aFormat) const michael@0: { michael@0: RefPtr surf = mFinalDT->CreateSourceSurfaceFromData(aData, aSize, aStride, aFormat); michael@0: michael@0: RefPtr retSurf = new SourceSurfaceRecording(surf, mRecorder); michael@0: michael@0: mRecorder->RecordEvent(RecordedSourceSurfaceCreation(retSurf, aData, aStride, aSize, aFormat)); michael@0: michael@0: return retSurf; michael@0: } michael@0: michael@0: TemporaryRef michael@0: DrawTargetRecording::OptimizeSourceSurface(SourceSurface *aSurface) const michael@0: { michael@0: RefPtr surf = mFinalDT->OptimizeSourceSurface(aSurface); michael@0: michael@0: RefPtr retSurf = new SourceSurfaceRecording(surf, mRecorder); michael@0: michael@0: RefPtr dataSurf = surf->GetDataSurface(); michael@0: michael@0: if (!dataSurf) { michael@0: // Let's try get it off the original surface. michael@0: dataSurf = aSurface->GetDataSurface(); michael@0: } michael@0: michael@0: if (!dataSurf) { michael@0: gfxWarning() << "Recording failed to record SourceSurface created from OptimizeSourceSurface"; michael@0: // Insert a bogus source surface. michael@0: uint8_t *sourceData = new uint8_t[surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat())]; michael@0: memset(sourceData, 0, surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat())); michael@0: mRecorder->RecordEvent( michael@0: RecordedSourceSurfaceCreation(retSurf, sourceData, michael@0: surf->GetSize().width * BytesPerPixel(surf->GetFormat()), michael@0: surf->GetSize(), surf->GetFormat())); michael@0: delete [] sourceData; michael@0: } else { michael@0: mRecorder->RecordEvent( michael@0: RecordedSourceSurfaceCreation(retSurf, dataSurf->GetData(), dataSurf->Stride(), michael@0: dataSurf->GetSize(), dataSurf->GetFormat())); michael@0: } michael@0: michael@0: return retSurf; michael@0: } michael@0: michael@0: TemporaryRef michael@0: DrawTargetRecording::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const michael@0: { michael@0: RefPtr surf = mFinalDT->CreateSourceSurfaceFromNativeSurface(aSurface); michael@0: michael@0: RefPtr retSurf = new SourceSurfaceRecording(surf, mRecorder); michael@0: michael@0: RefPtr dataSurf = surf->GetDataSurface(); michael@0: michael@0: if (!dataSurf) { michael@0: gfxWarning() << "Recording failed to record SourceSurface created from OptimizeSourceSurface"; michael@0: // Insert a bogus source surface. michael@0: uint8_t *sourceData = new uint8_t[surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat())]; michael@0: memset(sourceData, 0, surf->GetSize().width * surf->GetSize().height * BytesPerPixel(surf->GetFormat())); michael@0: mRecorder->RecordEvent( michael@0: RecordedSourceSurfaceCreation(retSurf, sourceData, michael@0: surf->GetSize().width * BytesPerPixel(surf->GetFormat()), michael@0: surf->GetSize(), surf->GetFormat())); michael@0: delete [] sourceData; michael@0: } else { michael@0: mRecorder->RecordEvent( michael@0: RecordedSourceSurfaceCreation(retSurf, dataSurf->GetData(), dataSurf->Stride(), michael@0: dataSurf->GetSize(), dataSurf->GetFormat())); michael@0: } michael@0: michael@0: return retSurf; michael@0: } michael@0: michael@0: TemporaryRef michael@0: DrawTargetRecording::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const michael@0: { michael@0: RefPtr dt = mFinalDT->CreateSimilarDrawTarget(aSize, aFormat); michael@0: michael@0: RefPtr retDT = new DrawTargetRecording(mRecorder.get(), dt); michael@0: michael@0: return retDT; michael@0: } michael@0: michael@0: TemporaryRef michael@0: DrawTargetRecording::CreatePathBuilder(FillRule aFillRule) const michael@0: { michael@0: RefPtr builder = mFinalDT->CreatePathBuilder(aFillRule); michael@0: return new PathBuilderRecording(builder, aFillRule); michael@0: } michael@0: michael@0: TemporaryRef michael@0: DrawTargetRecording::CreateGradientStops(GradientStop *aStops, michael@0: uint32_t aNumStops, michael@0: ExtendMode aExtendMode) const michael@0: { michael@0: RefPtr stops = mFinalDT->CreateGradientStops(aStops, aNumStops, aExtendMode); michael@0: michael@0: RefPtr retStops = new GradientStopsRecording(stops, mRecorder); michael@0: michael@0: mRecorder->RecordEvent(RecordedGradientStopsCreation(retStops, aStops, aNumStops, aExtendMode)); michael@0: michael@0: return retStops; michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::SetTransform(const Matrix &aTransform) michael@0: { michael@0: mRecorder->RecordEvent(RecordedSetTransform(this, aTransform)); michael@0: DrawTarget::SetTransform(aTransform); michael@0: mFinalDT->SetTransform(aTransform); michael@0: } michael@0: michael@0: void michael@0: DrawTargetRecording::EnsureStored(const Path *aPath) michael@0: { michael@0: if (!mRecorder->HasStoredPath(aPath)) { michael@0: if (aPath->GetBackendType() != BackendType::RECORDING) { michael@0: gfxWarning() << "Cannot record this fill path properly!"; michael@0: } else { michael@0: PathRecording *recPath = const_cast(static_cast(aPath)); michael@0: mRecorder->RecordEvent(RecordedPathCreation(recPath)); michael@0: mRecorder->AddStoredPath(aPath); michael@0: recPath->mStoredRecorders.push_back(mRecorder); michael@0: } michael@0: } michael@0: } michael@0: michael@0: } michael@0: }