Bug 1319423 - Part 1 - Introduce DrawEventRecorderPRFileDesc to allow switching away from std::ofstream in printing; r?jrmuizel
MozReview-Commit-ID: 1gn8J2fhejS
--- a/gfx/2d/DrawEventRecorder.cpp
+++ b/gfx/2d/DrawEventRecorder.cpp
@@ -11,25 +11,16 @@ namespace mozilla {
namespace gfx {
using namespace std;
DrawEventRecorderPrivate::DrawEventRecorderPrivate()
{
}
-template<class S>
-void
-DrawEventRecorderPrivate::WriteHeader(S &aStream)
-{
- WriteElement(aStream, kMagicInt);
- WriteElement(aStream, kMajorRevision);
- WriteElement(aStream, kMinorRevision);
-}
-
void
DrawEventRecorderFile::RecordEvent(const RecordedEvent &aEvent)
{
WriteElement(mOutputStream, aEvent.mType);
aEvent.RecordToStream(mOutputStream);
Flush();
--- a/gfx/2d/DrawEventRecorder.h
+++ b/gfx/2d/DrawEventRecorder.h
@@ -3,16 +3,17 @@
* 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_DRAWEVENTRECORDER_H_
#define MOZILLA_GFX_DRAWEVENTRECORDER_H_
#include "2D.h"
#include "RecordedEvent.h"
+#include "RecordingTypes.h"
#include <ostream>
#include <fstream>
#include <unordered_set>
namespace mozilla {
namespace gfx {
@@ -34,17 +35,21 @@ public:
for (auto surface = mStoredSurfaces.begin(); surface != mStoredSurfaces.end(); ) {
auto oldSurface = surface++;
(*oldSurface)->RemoveUserData(reinterpret_cast<UserDataKey*>(this));
}
}
template<class S>
- void WriteHeader(S &aStream);
+ void WriteHeader(S& aStream) {
+ WriteElement(aStream, kMagicInt);
+ WriteElement(aStream, kMajorRevision);
+ WriteElement(aStream, kMinorRevision);
+ }
virtual void RecordEvent(const RecordedEvent &aEvent) = 0;
void WritePath(const PathRecording *aPath);
void AddStoredObject(const ReferencePtr aObject) {
mStoredObjects.insert(aObject);
}
--- a/gfx/2d/RecordedEvent.h
+++ b/gfx/2d/RecordedEvent.h
@@ -202,16 +202,21 @@ struct MemStream {
Resize(mLength + aSize);
memcpy(mData + mLength - aSize, aData, aSize);
}
MemStream() : mData(nullptr), mLength(0), mCapacity(0) {}
~MemStream() { free(mData); }
};
+class EventStream {
+public:
+ virtual void write(const char* aData, size_t aSize) = 0;
+};
+
class RecordedEvent {
public:
enum EventType {
DRAWTARGETCREATION = 0,
DRAWTARGETDESTRUCTION,
FILLRECT,
STROKERECT,
STROKELINE,
@@ -261,18 +266,19 @@ public:
* only return false when there is a fatal error, as it will probably mean the
* translation will abort.
* @param aTranslator Translator to be used for retrieving other referenced
* objects and making playback decisions.
* @return true unless a fatal problem has occurred and playback should abort.
*/
virtual bool PlayEvent(Translator *aTranslator) const { return true; }
- virtual void RecordToStream(std::ostream &aStream) const {}
- virtual void RecordToStream(MemStream &aStream) const = 0;
+ virtual void RecordToStream(std::ostream& aStream) const = 0;
+ virtual void RecordToStream(EventStream& aStream) const = 0;
+ virtual void RecordToStream(MemStream& aStream) const = 0;
virtual void OutputSimpleEventInfo(std::stringstream &aStringStream) const { }
template<class S>
void RecordPatternData(S &aStream, const PatternStorage &aPatternStorage) const;
template<class S>
void ReadPatternData(S &aStream, PatternStorage &aPatternStorage) const;
void StorePattern(PatternStorage &aDestination, const Pattern &aSource) const;
@@ -293,26 +299,25 @@ public:
static RecordedEvent *LoadEvent(S &aStream, EventType aType);
static RecordedEvent *LoadEventFromStream(std::istream &aStream, EventType aType);
// An alternative to LoadEvent that avoids a heap allocation for the event.
// This accepts a callable `f' that will take a RecordedEvent* as a single parameter
template<class S, class F>
static bool DoWithEvent(S &aStream, EventType aType, F f);
- EventType GetType() { return (EventType)mType; }
+ EventType GetType() const { return (EventType)mType; }
protected:
friend class DrawEventRecorderPrivate;
friend class DrawEventRecorderFile;
friend class DrawEventRecorderMemory;
MOZ_IMPLICIT RecordedEvent(int32_t aType) : mType(aType)
{}
int32_t mType;
std::vector<Float> mDashPatternStorage;
};
} // namespace gfx
} // namespace mozilla
#endif
-
--- a/gfx/2d/RecordedEventImpl.h
+++ b/gfx/2d/RecordedEventImpl.h
@@ -20,16 +20,19 @@ namespace mozilla {
namespace gfx {
template<class Derived>
class RecordedEventDerived : public RecordedEvent {
using RecordedEvent::RecordedEvent;
void RecordToStream(std::ostream &aStream) const {
static_cast<const Derived*>(this)->Record(aStream);
}
+ void RecordToStream(EventStream& aStream) const {
+ static_cast<const Derived*>(this)->Record(aStream);
+ }
void RecordToStream(MemStream &aStream) const {
SizeCollector size;
static_cast<const Derived*>(this)->Record(size);
aStream.Resize(aStream.mLength + size.mTotalSize);
MemWriter writer(aStream.mData + aStream.mLength - size.mTotalSize);
static_cast<const Derived*>(this)->Record(writer);
}
};
@@ -74,17 +77,17 @@ public:
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
ReferencePtr mRefPtr;
BackendType mBackendType;
IntSize mSize;
SurfaceFormat mFormat;
bool mHasExistingData;
RefPtr<SourceSurface> mExistingData;
-
+
private:
friend class RecordedEvent;
template<class S>
MOZ_IMPLICIT RecordedDrawTargetCreation(S &aStream);
};
class RecordedDrawTargetDestruction : public RecordedEventDerived<RecordedDrawTargetDestruction> {
@@ -506,17 +509,17 @@ public:
: RecordedDrawingEvent(SETTRANSFORM, aDT), mTransform(aTransform)
{
}
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 "SetTransform"; }
Matrix mTransform;
private:
friend class RecordedEvent;
template<class S>
MOZ_IMPLICIT RecordedSetTransform(S &aStream);
@@ -531,17 +534,17 @@ public:
, mSource(aSource), mDSOptions(aDSOptions), mOptions(aOptions)
{
}
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 "DrawSurface"; }
private:
friend class RecordedEvent;
template<class S>
MOZ_IMPLICIT RecordedDrawSurface(S &aStream);
ReferencePtr mRefSource;
@@ -560,17 +563,17 @@ public:
, mColor(aColor), mOffset(aOffset), mSigma(aSigma), mOp(aOp)
{
}
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 "DrawSurfaceWithShadow"; }
private:
friend class RecordedEvent;
template<class S>
MOZ_IMPLICIT RecordedDrawSurfaceWithShadow(S &aStream);
ReferencePtr mRefSource;
@@ -609,22 +612,22 @@ private:
Point mDestPoint;
DrawOptions mOptions;
};
class RecordedPathCreation : public RecordedEventDerived<RecordedPathCreation> {
public:
MOZ_IMPLICIT RecordedPathCreation(PathRecording *aPath);
~RecordedPathCreation();
-
+
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 "Path Creation"; }
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
FillRule mFillRule;
std::vector<PathOp> mPathOps;
@@ -634,22 +637,22 @@ private:
};
class RecordedPathDestruction : public RecordedEventDerived<RecordedPathDestruction> {
public:
MOZ_IMPLICIT RecordedPathDestruction(PathRecording *aPath)
: RecordedEventDerived(PATHDESTRUCTION), mRefPtr(aPath)
{
}
-
+
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 "Path Destruction"; }
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
template<class S>
@@ -666,17 +669,17 @@ public:
}
~RecordedSourceSurfaceCreation();
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 "SourceSurface Creation"; }
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
uint8_t *mData;
int32_t mStride;
@@ -694,17 +697,17 @@ public:
: RecordedEventDerived(SOURCESURFACEDESTRUCTION), mRefPtr(aRefPtr)
{
}
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 "SourceSurface Destruction"; }
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
template<class S>
@@ -770,17 +773,17 @@ public:
}
~RecordedGradientStopsCreation();
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 "GradientStops Creation"; }
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
GradientStop *mStops;
uint32_t mNumStops;
@@ -797,17 +800,17 @@ public:
: RecordedEventDerived(GRADIENTSTOPSDESTRUCTION), mRefPtr(aRefPtr)
{
}
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 "GradientStops Destruction"; }
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
template<class S>
@@ -820,17 +823,17 @@ public:
: RecordedEventDerived(SNAPSHOT), mRefPtr(aRefPtr), mDT(aDT)
{
}
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 "Snapshot"; }
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
private:
friend class RecordedEvent;
ReferencePtr mRefPtr;
ReferencePtr mDT;
@@ -1040,17 +1043,17 @@ public:
{
aScaledFont->GetFontInstanceData(FontInstanceDataProc, this);
}
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 "ScaledFont Creation"; }
virtual ReferencePtr GetObjectRef() const { return mRefPtr; }
void SetFontInstanceData(const uint8_t *aData, uint32_t aSize,
const FontVariation* aVariations, uint32_t aNumVariations);
private:
friend class RecordedEvent;
@@ -1098,17 +1101,17 @@ public:
{
StorePattern(mPattern, aPattern);
}
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 "MaskSurface"; }
private:
friend class RecordedEvent;
template<class S>
MOZ_IMPLICIT RecordedMaskSurface(S &aStream);
PatternStorage mPattern;
@@ -1283,17 +1286,17 @@ RecordedEvent::ReadPatternData(S &aStrea
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:
@@ -2278,17 +2281,17 @@ RecordedPathCreation::RecordedPathCreati
inline
RecordedPathCreation::~RecordedPathCreation()
{
}
inline bool
RecordedPathCreation::PlayEvent(Translator *aTranslator) const
{
- RefPtr<PathBuilder> builder =
+ RefPtr<PathBuilder> builder =
aTranslator->GetReferenceDrawTarget()->CreatePathBuilder(mFillRule);
for (size_t i = 0; i < mPathOps.size(); i++) {
const PathOp &op = mPathOps[i];
switch (op.mType) {
case PathOp::OP_MOVETO:
builder->MoveTo(op.mP1);
break;
new file mode 100644
--- /dev/null
+++ b/layout/printing/DrawEventRecorder.cpp
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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/. */
+
+#include "DrawEventRecorder.h"
+
+namespace mozilla {
+namespace layout {
+
+void
+DrawEventRecorderPRFileDesc::RecordEvent(const gfx::RecordedEvent& aEvent)
+{
+ WriteElement(mOutputStream, aEvent.GetType());
+
+ aEvent.RecordToStream(mOutputStream);
+
+ Flush();
+}
+
+DrawEventRecorderPRFileDesc::DrawEventRecorderPRFileDesc(const char* aFilename)
+{
+ mOutputStream.Open(aFilename);
+ WriteHeader(mOutputStream);
+}
+
+DrawEventRecorderPRFileDesc::~DrawEventRecorderPRFileDesc()
+{
+ if (IsOpen()) {
+ Close();
+ }
+}
+
+void
+DrawEventRecorderPRFileDesc::Flush()
+{
+ mOutputStream.Flush();
+}
+
+bool
+DrawEventRecorderPRFileDesc::IsOpen()
+{
+ return mOutputStream.IsOpen();
+}
+
+void
+DrawEventRecorderPRFileDesc::OpenNew(const char* aFilename)
+{
+ MOZ_ASSERT(!IsOpen());
+
+ mOutputStream.Open(aFilename);
+ WriteHeader(mOutputStream);
+}
+
+void
+DrawEventRecorderPRFileDesc::Close()
+{
+ MOZ_ASSERT(IsOpen());
+
+ mOutputStream.Close();
+}
+
+}
+}
new file mode 100644
--- /dev/null
+++ b/layout/printing/DrawEventRecorder.h
@@ -0,0 +1,90 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * 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_layout_printing_DrawEventRecorder_h
+#define mozilla_layout_printing_DrawEventRecorder_h
+
+#include "mozilla/gfx/DrawEventRecorder.h"
+#include "mozilla/gfx/RecordingTypes.h"
+#include "prio.h"
+
+namespace mozilla {
+namespace layout {
+
+class PRFileDescStream : public mozilla::gfx::EventStream {
+public:
+ PRFileDescStream() : mFd(nullptr) {}
+
+ void Open(const char* aFilename) {
+ MOZ_ASSERT(!IsOpen());
+ mFd = PR_Open(aFilename, PR_RDWR | PR_CREATE_FILE, PR_IRUSR | PR_IWUSR);
+ }
+
+ void Close() {
+ PR_Close(mFd);
+ mFd = nullptr;
+ }
+
+ bool IsOpen() {
+ return mFd != nullptr;
+ }
+
+ void Flush() {
+ // We need to be API compatible with std::ostream, and so we silently handle
+ // flushes on a closed FD.
+ if (IsOpen()) {
+ PR_Sync(mFd);
+ }
+ }
+
+ void write(const char* aData, size_t aSize) {
+ // See comment in Flush().
+ if (IsOpen()) {
+ PR_Write(mFd, static_cast<const void*>(aData), aSize);
+ }
+ }
+
+private:
+ PRFileDesc* mFd;
+};
+
+class DrawEventRecorderPRFileDesc : public gfx::DrawEventRecorderPrivate
+{
+public:
+ MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPRFileDesc, override)
+ explicit DrawEventRecorderPRFileDesc(const char* aFilename);
+ ~DrawEventRecorderPRFileDesc();
+
+ void RecordEvent(const gfx::RecordedEvent& aEvent) override;
+
+ /**
+ * Returns whether a recording file is currently open.
+ */
+ bool IsOpen();
+
+ /**
+ * Opens new file with the provided name. The recorder does NOT forget which
+ * objects it has recorded. This can be used with Close, so that a recording
+ * can be processed in chunks. The file must not already be open.
+ */
+ void OpenNew(const char* aFilename);
+
+ /**
+ * Closes the file so that it can be processed. The recorder does NOT forget
+ * which objects it has recorded. This can be used with OpenNew, so that a
+ * recording can be processed in chunks. The file must be open.
+ */
+ void Close();
+
+private:
+ void Flush() override;
+
+ PRFileDescStream mOutputStream;
+};
+
+}
+}
+
+#endif /* mozilla_layout_printing_DrawEventRecorder_h */
--- a/layout/printing/moz.build
+++ b/layout/printing/moz.build
@@ -10,28 +10,34 @@ XPIDL_SOURCES += [
'nsIPrintStatusFeedback.idl',
]
EXPORTS.mozilla.layout += [
'ipc/RemotePrintJobChild.h',
'ipc/RemotePrintJobParent.h',
]
+EXPORTS.mozilla.layout.printing += [
+ 'DrawEventRecorder.h'
+]
+
XPIDL_MODULE = 'layout_printing'
UNIFIED_SOURCES += [
+ 'DrawEventRecorder.cpp',
'ipc/RemotePrintJobChild.cpp',
'ipc/RemotePrintJobParent.cpp',
'nsPagePrintTimer.cpp',
'nsPrintData.cpp',
'nsPrintEngine.cpp',
'nsPrintObject.cpp',
'nsPrintPreviewListener.cpp',
'PrintTranslator.cpp',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
LOCAL_INCLUDES += [
'../base',
'/dom/base',
+ '/gfx/2d/'
]
--- a/widget/nsDeviceContextSpecProxy.cpp
+++ b/widget/nsDeviceContextSpecProxy.cpp
@@ -179,17 +179,17 @@ nsDeviceContextSpecProxy::BeginDocument(
int32_t aStartPage, int32_t aEndPage)
{
nsAutoCString recordingPath;
nsresult rv = CreateUniqueTempPath(recordingPath);
if (NS_FAILED(rv)) {
return rv;
}
- mRecorder = new mozilla::gfx::DrawEventRecorderFile(recordingPath.get());
+ mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc(recordingPath.get());
return mRemotePrintJob->InitializePrint(nsString(aTitle),
nsString(aPrintToFileName),
aStartPage, aEndPage);
}
NS_IMETHODIMP
nsDeviceContextSpecProxy::EndDocument()
{
--- a/widget/nsDeviceContextSpecProxy.h
+++ b/widget/nsDeviceContextSpecProxy.h
@@ -5,26 +5,23 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsDeviceContextSpecProxy_h
#define nsDeviceContextSpecProxy_h
#include "nsIDeviceContextSpec.h"
#include "nsCOMPtr.h"
#include "nsString.h"
+#include "mozilla/layout/printing/DrawEventRecorder.h"
class nsIFile;
class nsIPrintSession;
class nsIUUIDGenerator;
namespace mozilla {
-namespace gfx {
-class DrawEventRecorderFile;
-}
-
namespace layout {
class RemotePrintJobChild;
}
}
class nsDeviceContextSpecProxy final : public nsIDeviceContextSpec
{
public:
@@ -58,15 +55,15 @@ private:
~nsDeviceContextSpecProxy() {}
nsresult CreateUniqueTempPath(nsACString& aFilePath);
nsCOMPtr<nsIPrintSettings> mPrintSettings;
nsCOMPtr<nsIPrintSession> mPrintSession;
nsCOMPtr<nsIDeviceContextSpec> mRealDeviceContextSpec;
RefPtr<mozilla::layout::RemotePrintJobChild> mRemotePrintJob;
- RefPtr<mozilla::gfx::DrawEventRecorderFile> mRecorder;
+ RefPtr<mozilla::layout::DrawEventRecorderPRFileDesc> mRecorder;
nsCOMPtr<nsIFile> mRecordingDir;
nsCOMPtr<nsIUUIDGenerator> mUuidGenerator;
nsCString mRecordingFileName;
};
#endif // nsDeviceContextSpecProxy_h