From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- layout/printing/DrawEventRecorder.cpp | 51 + layout/printing/DrawEventRecorder.h | 167 ++ layout/printing/PrintTranslator.cpp | 86 + layout/printing/PrintTranslator.h | 170 ++ layout/printing/crashtests/1662259.html | 7 + layout/printing/crashtests/1663722.html | 11 + layout/printing/crashtests/1671503.html | 12 + layout/printing/crashtests/1748277.html | 26 + layout/printing/crashtests/1748277.png | Bin 0 -> 228 bytes layout/printing/crashtests/1758199-1.html | 13 + layout/printing/crashtests/1804571.html | 11 + layout/printing/crashtests/1804794.html | 10 + layout/printing/crashtests/1804798.html | 7 + layout/printing/crashtests/1819468-1.html | 21 + layout/printing/crashtests/1819468-2.html | 18 + layout/printing/crashtests/509839-1.html | 10 + layout/printing/crashtests/509839-2.html | 8 + layout/printing/crashtests/576878.xhtml | 9 + layout/printing/crashtests/793844.html | 10 + layout/printing/crashtests/crashtests.list | 14 + layout/printing/ipc/PRemotePrintJob.ipdl | 57 + layout/printing/ipc/RemotePrintJobChild.cpp | 169 ++ layout/printing/ipc/RemotePrintJobChild.h | 66 + layout/printing/ipc/RemotePrintJobParent.cpp | 316 ++++ layout/printing/ipc/RemotePrintJobParent.h | 98 ++ layout/printing/moz.build | 33 + layout/printing/nsPagePrintTimer.cpp | 221 +++ layout/printing/nsPagePrintTimer.h | 84 + layout/printing/nsPrintData.cpp | 126 ++ layout/printing/nsPrintData.h | 53 + layout/printing/nsPrintJob.cpp | 2436 ++++++++++++++++++++++++++ layout/printing/nsPrintJob.h | 311 ++++ layout/printing/nsPrintObject.cpp | 93 + layout/printing/nsPrintObject.h | 88 + 34 files changed, 4812 insertions(+) create mode 100644 layout/printing/DrawEventRecorder.cpp create mode 100644 layout/printing/DrawEventRecorder.h create mode 100644 layout/printing/PrintTranslator.cpp create mode 100644 layout/printing/PrintTranslator.h create mode 100644 layout/printing/crashtests/1662259.html create mode 100644 layout/printing/crashtests/1663722.html create mode 100644 layout/printing/crashtests/1671503.html create mode 100644 layout/printing/crashtests/1748277.html create mode 100644 layout/printing/crashtests/1748277.png create mode 100644 layout/printing/crashtests/1758199-1.html create mode 100644 layout/printing/crashtests/1804571.html create mode 100644 layout/printing/crashtests/1804794.html create mode 100644 layout/printing/crashtests/1804798.html create mode 100644 layout/printing/crashtests/1819468-1.html create mode 100644 layout/printing/crashtests/1819468-2.html create mode 100644 layout/printing/crashtests/509839-1.html create mode 100644 layout/printing/crashtests/509839-2.html create mode 100644 layout/printing/crashtests/576878.xhtml create mode 100644 layout/printing/crashtests/793844.html create mode 100644 layout/printing/crashtests/crashtests.list create mode 100644 layout/printing/ipc/PRemotePrintJob.ipdl create mode 100644 layout/printing/ipc/RemotePrintJobChild.cpp create mode 100644 layout/printing/ipc/RemotePrintJobChild.h create mode 100644 layout/printing/ipc/RemotePrintJobParent.cpp create mode 100644 layout/printing/ipc/RemotePrintJobParent.h create mode 100644 layout/printing/moz.build create mode 100644 layout/printing/nsPagePrintTimer.cpp create mode 100644 layout/printing/nsPagePrintTimer.h create mode 100644 layout/printing/nsPrintData.cpp create mode 100644 layout/printing/nsPrintData.h create mode 100644 layout/printing/nsPrintJob.cpp create mode 100644 layout/printing/nsPrintJob.h create mode 100644 layout/printing/nsPrintObject.cpp create mode 100644 layout/printing/nsPrintObject.h (limited to 'layout/printing') diff --git a/layout/printing/DrawEventRecorder.cpp b/layout/printing/DrawEventRecorder.cpp new file mode 100644 index 0000000000..69b9b48ae6 --- /dev/null +++ b/layout/printing/DrawEventRecorder.cpp @@ -0,0 +1,51 @@ +/* -*- 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/. */ + +#include "DrawEventRecorder.h" + +namespace mozilla { +namespace layout { + +void DrawEventRecorderPRFileDesc::RecordEvent( + const gfx::RecordedEvent& aEvent) { + aEvent.RecordToStream(mOutputStream); + + Flush(); +} + +DrawEventRecorderPRFileDesc::~DrawEventRecorderPRFileDesc() { + if (IsOpen()) { + Close(); + } +} + +void DrawEventRecorderPRFileDesc::Flush() { mOutputStream.Flush(); } + +bool DrawEventRecorderPRFileDesc::IsOpen() { return mOutputStream.IsOpen(); } + +void DrawEventRecorderPRFileDesc::OpenFD(PRFileDesc* aFd) { + MOZ_DIAGNOSTIC_ASSERT(!IsOpen()); + + mOutputStream.OpenFD(aFd); + WriteHeader(mOutputStream); +} + +void DrawEventRecorderPRFileDesc::Close() { + MOZ_DIAGNOSTIC_ASSERT(IsOpen()); + + mOutputStream.Close(); +} + +void DrawEventRecorderPRFileDesc::AddDependentSurface(uint64_t aDependencyId) { + mDependentSurfaces.AppendElement(aDependencyId); +} + +nsTArray&& DrawEventRecorderPRFileDesc::TakeDependentSurfaces() { + return std::move(mDependentSurfaces); +} + +} // namespace layout +} // namespace mozilla diff --git a/layout/printing/DrawEventRecorder.h b/layout/printing/DrawEventRecorder.h new file mode 100644 index 0000000000..79eaa65ef4 --- /dev/null +++ b/layout/printing/DrawEventRecorder.h @@ -0,0 +1,167 @@ +/* -*- 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_layout_printing_DrawEventRecorder_h +#define mozilla_layout_printing_DrawEventRecorder_h + +#include + +#include "mozilla/gfx/DrawEventRecorder.h" +#include "mozilla/gfx/RecordingTypes.h" +#include "prio.h" +#include "nsTArray.h" + +namespace mozilla { +namespace layout { + +class PRFileDescStream final : public mozilla::gfx::EventStream { + // Most writes, as seen in the print IPC use case, are very small (<32 bytes), + // with a small number of very large (>40KB) writes. Writes larger than this + // value are not buffered. + static const size_t kBufferSize = 1024; + + public: + PRFileDescStream() + : mFd(nullptr), mBuffer(nullptr), mBufferPos(0), mGood(true) {} + PRFileDescStream(const PRFileDescStream& other) = delete; + ~PRFileDescStream() { Close(); } + + void OpenFD(PRFileDesc* aFd) { + MOZ_DIAGNOSTIC_ASSERT(!IsOpen()); + mFd = aFd; + mGood = !!mFd; + mBuffer.reset(new uint8_t[kBufferSize]); + mBufferPos = 0; + } + + void Close() { + // We need to be API compatible with std::ostream, and so we silently handle + // closes on a closed FD. + if (IsOpen()) { + Flush(); + PR_Close(mFd); + mFd = nullptr; + mBuffer.reset(); + mBufferPos = 0; + } + } + + bool IsOpen() { return mFd != nullptr; } + + void Flush() { + // See comment in Close(). + if (IsOpen() && mBufferPos > 0) { + PRInt32 length = + PR_Write(mFd, static_cast(mBuffer.get()), mBufferPos); + mGood = length >= 0 && static_cast(length) == mBufferPos; + mBufferPos = 0; + } + } + + void Seek(PRInt64 aOffset, PRSeekWhence aWhence) { + Flush(); + PRInt64 pos = PR_Seek64(mFd, aOffset, aWhence); + mGood = pos != -1; + } + + void write(const char* aData, size_t aSize) override { + if (!good()) { + return; + } + + // See comment in Close(). + if (IsOpen()) { + // If we're writing more data than could ever fit in our buffer, flush the + // buffer and write directly. + if (aSize > kBufferSize) { + Flush(); + PRInt32 length = PR_Write(mFd, static_cast(aData), aSize); + mGood = length >= 0 && static_cast(length) == aSize; + // If our write could fit in our buffer, but doesn't because the buffer + // is partially full, write to the buffer, flush the buffer, and then + // write the rest of the data to the buffer. + } else if (aSize > AvailableBufferSpace()) { + size_t length = AvailableBufferSpace(); + WriteToBuffer(aData, length); + Flush(); + + WriteToBuffer(aData + length, aSize - length); + // Write fits in the buffer. + } else { + WriteToBuffer(aData, aSize); + } + } + } + + void read(char* aOut, size_t aSize) override { + if (!good()) { + return; + } + + Flush(); + PRInt32 res = PR_Read(mFd, static_cast(aOut), aSize); + mGood = res >= 0 && (static_cast(res) == aSize); + } + + bool good() final { return mGood; } + + void SetIsBad() final { mGood = false; } + + private: + size_t AvailableBufferSpace() { return kBufferSize - mBufferPos; } + + void WriteToBuffer(const char* aData, size_t aSize) { + MOZ_ASSERT(aSize <= AvailableBufferSpace()); + memcpy(mBuffer.get() + mBufferPos, aData, aSize); + mBufferPos += aSize; + } + + PRFileDesc* mFd; + std::unique_ptr mBuffer; + size_t mBufferPos; + bool mGood; +}; + +class DrawEventRecorderPRFileDesc final : public gfx::DrawEventRecorderPrivate { + public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPRFileDesc, override) + explicit DrawEventRecorderPRFileDesc() = default; + ~DrawEventRecorderPRFileDesc(); + + void RecordEvent(const gfx::RecordedEvent& aEvent) override; + + /** + * Returns whether a recording file is currently open. + */ + bool IsOpen(); + + /** + * Opens the recorder with the provided PRFileDesc *. + */ + void OpenFD(PRFileDesc* aFd); + + /** + * 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(); + + void AddDependentSurface(uint64_t aDependencyId) override; + nsTArray&& TakeDependentSurfaces(); + + private: + void Flush() override; + + PRFileDescStream mOutputStream; + nsTArray mDependentSurfaces; +}; + +} // namespace layout + +} // namespace mozilla + +#endif /* mozilla_layout_printing_DrawEventRecorder_h */ diff --git a/layout/printing/PrintTranslator.cpp b/layout/printing/PrintTranslator.cpp new file mode 100644 index 0000000000..b3d5609a08 --- /dev/null +++ b/layout/printing/PrintTranslator.cpp @@ -0,0 +1,86 @@ +/* -*- 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/. */ + +#include "PrintTranslator.h" + +#include "gfxContext.h" +#include "nsDeviceContext.h" +#include "mozilla/gfx/RecordedEvent.h" +#include "mozilla/gfx/RecordingTypes.h" +#include "mozilla/UniquePtr.h" +#include "InlineTranslator.h" + +using namespace mozilla::gfx; + +namespace mozilla { +namespace layout { + +PrintTranslator::PrintTranslator(nsDeviceContext* aDeviceContext) + : mDeviceContext(aDeviceContext) { + UniquePtr context = + mDeviceContext->CreateReferenceRenderingContext(); + mBaseDT = context->GetDrawTarget(); +} + +bool PrintTranslator::TranslateRecording(PRFileDescStream& aRecording) { + uint32_t magicInt; + ReadElement(aRecording, magicInt); + if (magicInt != mozilla::gfx::kMagicInt) { + return false; + } + + uint16_t majorRevision; + ReadElement(aRecording, majorRevision); + if (majorRevision != kMajorRevision) { + return false; + } + + uint16_t minorRevision; + ReadElement(aRecording, minorRevision); + if (minorRevision > kMinorRevision) { + return false; + } + + int32_t eventType; + ReadElement(aRecording, eventType); + while (aRecording.good()) { + bool success = RecordedEvent::DoWithEventFromStream( + aRecording, static_cast(eventType), + [&](RecordedEvent* recordedEvent) -> bool { + // Make sure that the whole event was read from the stream. + if (!aRecording.good()) { + return false; + } + + return recordedEvent->PlayEvent(this); + }); + + if (!success) { + return false; + } + + ReadElement(aRecording, eventType); + } + + return true; +} + +already_AddRefed PrintTranslator::CreateDrawTarget( + ReferencePtr aRefPtr, const gfx::IntSize& aSize, + gfx::SurfaceFormat aFormat) { + UniquePtr context = mDeviceContext->CreateRenderingContext(); + if (!context) { + NS_WARNING("Failed to create rendering context for print."); + return nullptr; + } + + RefPtr drawTarget = context->GetDrawTarget(); + AddDrawTarget(aRefPtr, drawTarget); + return drawTarget.forget(); +} + +} // namespace layout +} // namespace mozilla diff --git a/layout/printing/PrintTranslator.h b/layout/printing/PrintTranslator.h new file mode 100644 index 0000000000..87a8fed808 --- /dev/null +++ b/layout/printing/PrintTranslator.h @@ -0,0 +1,170 @@ +/* -*- 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_layout_PrintTranslator_h +#define mozilla_layout_PrintTranslator_h + +#include + +#include "DrawEventRecorder.h" +#include "mozilla/gfx/2D.h" +#include "mozilla/gfx/Filters.h" +#include "mozilla/gfx/RecordedEvent.h" + +class nsDeviceContext; + +namespace mozilla { +namespace layout { + +using gfx::DrawTarget; +using gfx::FilterNode; +using gfx::GradientStops; +using gfx::NativeFontResource; +using gfx::Path; +using gfx::RecordedDependentSurface; +using gfx::ReferencePtr; +using gfx::ScaledFont; +using gfx::SourceSurface; +using gfx::Translator; +using gfx::UnscaledFont; + +class PrintTranslator final : public Translator { + public: + explicit PrintTranslator(nsDeviceContext* aDeviceContext); + + bool TranslateRecording(PRFileDescStream& aRecording); + + DrawTarget* LookupDrawTarget(ReferencePtr aRefPtr) final { + DrawTarget* result = mDrawTargets.GetWeak(aRefPtr); + MOZ_ASSERT(result); + return result; + } + + Path* LookupPath(ReferencePtr aRefPtr) final { + Path* result = mPaths.GetWeak(aRefPtr); + MOZ_ASSERT(result); + return result; + } + + SourceSurface* LookupSourceSurface(ReferencePtr aRefPtr) final { + SourceSurface* result = mSourceSurfaces.GetWeak(aRefPtr); + MOZ_ASSERT(result); + return result; + } + + FilterNode* LookupFilterNode(ReferencePtr aRefPtr) final { + FilterNode* result = mFilterNodes.GetWeak(aRefPtr); + MOZ_ASSERT(result); + return result; + } + + already_AddRefed LookupGradientStops( + ReferencePtr aRefPtr) final { + return mGradientStops.Get(aRefPtr); + } + + ScaledFont* LookupScaledFont(ReferencePtr aRefPtr) final { + ScaledFont* result = mScaledFonts.GetWeak(aRefPtr); + MOZ_ASSERT(result); + return result; + } + + UnscaledFont* LookupUnscaledFont(ReferencePtr aRefPtr) final { + UnscaledFont* result = mUnscaledFonts.GetWeak(aRefPtr); + MOZ_ASSERT(result); + return result; + } + + NativeFontResource* LookupNativeFontResource(uint64_t aKey) final { + NativeFontResource* result = mNativeFontResources.GetWeak(aKey); + MOZ_ASSERT(result); + return result; + } + + void AddDrawTarget(ReferencePtr aRefPtr, DrawTarget* aDT) final { + mDrawTargets.InsertOrUpdate(aRefPtr, RefPtr{aDT}); + } + + void AddPath(ReferencePtr aRefPtr, Path* aPath) final { + mPaths.InsertOrUpdate(aRefPtr, RefPtr{aPath}); + } + + void AddSourceSurface(ReferencePtr aRefPtr, SourceSurface* aSurface) final { + mSourceSurfaces.InsertOrUpdate(aRefPtr, RefPtr{aSurface}); + } + + void AddFilterNode(ReferencePtr aRefPtr, FilterNode* aFilter) final { + mFilterNodes.InsertOrUpdate(aRefPtr, RefPtr{aFilter}); + } + + void AddGradientStops(ReferencePtr aRefPtr, GradientStops* aStops) final { + mGradientStops.InsertOrUpdate(aRefPtr, RefPtr{aStops}); + } + + void AddScaledFont(ReferencePtr aRefPtr, ScaledFont* aScaledFont) final { + mScaledFonts.InsertOrUpdate(aRefPtr, RefPtr{aScaledFont}); + } + + void AddUnscaledFont(ReferencePtr aRefPtr, + UnscaledFont* aUnscaledFont) final { + mUnscaledFonts.InsertOrUpdate(aRefPtr, RefPtr{aUnscaledFont}); + } + + void AddNativeFontResource(uint64_t aKey, + NativeFontResource* aScaledFontResouce) final { + mNativeFontResources.InsertOrUpdate(aKey, RefPtr{aScaledFontResouce}); + } + + void RemoveDrawTarget(ReferencePtr aRefPtr) final { + mDrawTargets.Remove(aRefPtr); + } + + void RemovePath(ReferencePtr aRefPtr) final { mPaths.Remove(aRefPtr); } + + void RemoveSourceSurface(ReferencePtr aRefPtr) final { + mSourceSurfaces.Remove(aRefPtr); + } + + void RemoveFilterNode(ReferencePtr aRefPtr) final { + mFilterNodes.Remove(aRefPtr); + } + + void RemoveGradientStops(ReferencePtr aRefPtr) final { + mGradientStops.Remove(aRefPtr); + } + + void RemoveScaledFont(ReferencePtr aRefPtr) final { + mScaledFonts.Remove(aRefPtr); + } + + void RemoveUnscaledFont(ReferencePtr aRefPtr) final { + mUnscaledFonts.Remove(aRefPtr); + } + + already_AddRefed CreateDrawTarget( + ReferencePtr aRefPtr, const gfx::IntSize& aSize, + gfx::SurfaceFormat aFormat) final; + + mozilla::gfx::DrawTarget* GetReferenceDrawTarget() final { return mBaseDT; } + + private: + RefPtr mDeviceContext; + RefPtr mBaseDT; + + nsRefPtrHashtable, DrawTarget> mDrawTargets; + nsRefPtrHashtable, Path> mPaths; + nsRefPtrHashtable, SourceSurface> mSourceSurfaces; + nsRefPtrHashtable, FilterNode> mFilterNodes; + nsRefPtrHashtable, GradientStops> mGradientStops; + nsRefPtrHashtable, ScaledFont> mScaledFonts; + nsRefPtrHashtable, UnscaledFont> mUnscaledFonts; + nsRefPtrHashtable mNativeFontResources; +}; + +} // namespace layout +} // namespace mozilla + +#endif // mozilla_layout_PrintTranslator_h diff --git a/layout/printing/crashtests/1662259.html b/layout/printing/crashtests/1662259.html new file mode 100644 index 0000000000..0e5d338635 --- /dev/null +++ b/layout/printing/crashtests/1662259.html @@ -0,0 +1,7 @@ + + + + diff --git a/layout/printing/crashtests/1748277.html b/layout/printing/crashtests/1748277.html new file mode 100644 index 0000000000..9cfbef2c46 --- /dev/null +++ b/layout/printing/crashtests/1748277.html @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/layout/printing/crashtests/1748277.png b/layout/printing/crashtests/1748277.png new file mode 100644 index 0000000000..6bcf82782e Binary files /dev/null and b/layout/printing/crashtests/1748277.png differ diff --git a/layout/printing/crashtests/1758199-1.html b/layout/printing/crashtests/1758199-1.html new file mode 100644 index 0000000000..9a2deedce2 --- /dev/null +++ b/layout/printing/crashtests/1758199-1.html @@ -0,0 +1,13 @@ + + + + diff --git a/layout/printing/crashtests/1804571.html b/layout/printing/crashtests/1804571.html new file mode 100644 index 0000000000..b4f1c7dad3 --- /dev/null +++ b/layout/printing/crashtests/1804571.html @@ -0,0 +1,11 @@ + + + +