summaryrefslogtreecommitdiffstats
path: root/gfx/thebes/PrintTargetSkPDF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/thebes/PrintTargetSkPDF.cpp')
-rw-r--r--gfx/thebes/PrintTargetSkPDF.cpp127
1 files changed, 127 insertions, 0 deletions
diff --git a/gfx/thebes/PrintTargetSkPDF.cpp b/gfx/thebes/PrintTargetSkPDF.cpp
new file mode 100644
index 0000000000..2834877407
--- /dev/null
+++ b/gfx/thebes/PrintTargetSkPDF.cpp
@@ -0,0 +1,127 @@
+/* -*- 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 "PrintTargetSkPDF.h"
+
+#include "mozilla/gfx/2D.h"
+#include "nsString.h"
+#include <vector>
+
+namespace mozilla::gfx {
+
+PrintTargetSkPDF::PrintTargetSkPDF(const IntSize& aSize,
+ UniquePtr<SkWStream> aStream)
+ : PrintTarget(/* not using cairo_surface_t */ nullptr, aSize),
+ mOStream(std::move(aStream)),
+ mPageCanvas(nullptr),
+ mRefCanvas(nullptr) {}
+
+PrintTargetSkPDF::~PrintTargetSkPDF() {
+ Finish(); // ensure stream is flushed
+
+ // Make sure mPDFDoc and mRefPDFDoc are destroyed before our member streams
+ // (which they wrap) are destroyed:
+ mPDFDoc = nullptr;
+ mRefPDFDoc = nullptr;
+}
+
+/* static */
+already_AddRefed<PrintTargetSkPDF> PrintTargetSkPDF::CreateOrNull(
+ UniquePtr<SkWStream> aStream, const IntSize& aSizeInPoints) {
+ return do_AddRef(new PrintTargetSkPDF(aSizeInPoints, std::move(aStream)));
+}
+
+nsresult PrintTargetSkPDF::BeginPrinting(const nsAString& aTitle,
+ const nsAString& aPrintToFileName,
+ int32_t aStartPage, int32_t aEndPage) {
+ // We need to create the SkPDFDocument here rather than in CreateOrNull
+ // because it's only now that we are given aTitle which we want for the
+ // PDF metadata.
+
+ SkPDF::Metadata metadata;
+ metadata.fTitle = NS_ConvertUTF16toUTF8(aTitle).get();
+ metadata.fCreator = "Firefox";
+ SkTime::DateTime now;
+ SkTime::GetDateTime(&now);
+ metadata.fCreation = now;
+ metadata.fModified = now;
+
+ // SkDocument stores a non-owning raw pointer to aStream
+ mPDFDoc = SkPDF::MakeDocument(mOStream.get(), metadata);
+
+ return mPDFDoc ? NS_OK : NS_ERROR_FAILURE;
+}
+
+nsresult PrintTargetSkPDF::BeginPage(const IntSize& aSizeInPoints) {
+ mPageCanvas = mPDFDoc->beginPage(mSize.width, mSize.height);
+
+ return !mPageCanvas ? NS_ERROR_FAILURE
+ : PrintTarget::BeginPage(aSizeInPoints);
+}
+
+nsresult PrintTargetSkPDF::EndPage() {
+ mPageCanvas = nullptr;
+ mPageDT = nullptr;
+ return PrintTarget::EndPage();
+}
+
+nsresult PrintTargetSkPDF::EndPrinting() {
+ mPDFDoc->close();
+ if (mRefPDFDoc) {
+ mRefPDFDoc->close();
+ }
+ mPageCanvas = nullptr;
+ mPageDT = nullptr;
+ return NS_OK;
+}
+
+void PrintTargetSkPDF::Finish() {
+ if (mIsFinished) {
+ return;
+ }
+ mOStream->flush();
+ PrintTarget::Finish();
+}
+
+already_AddRefed<DrawTarget> PrintTargetSkPDF::MakeDrawTarget(
+ const IntSize& aSize, DrawEventRecorder* aRecorder) {
+ if (aRecorder) {
+ return PrintTarget::MakeDrawTarget(aSize, aRecorder);
+ }
+ // MOZ_ASSERT(aSize == mSize, "Should mPageCanvas size match?");
+ if (!mPageCanvas) {
+ return nullptr;
+ }
+ mPageDT = Factory::CreateDrawTargetWithSkCanvas(mPageCanvas);
+ if (!mPageDT) {
+ mPageCanvas = nullptr;
+ return nullptr;
+ }
+ return do_AddRef(mPageDT);
+}
+
+already_AddRefed<DrawTarget> PrintTargetSkPDF::GetReferenceDrawTarget() {
+ if (!mRefDT) {
+ SkPDF::Metadata metadata;
+ // SkDocument stores a non-owning raw pointer to aStream
+ mRefPDFDoc = SkPDF::MakeDocument(&mRefOStream, metadata);
+ if (!mRefPDFDoc) {
+ return nullptr;
+ }
+ mRefCanvas = mRefPDFDoc->beginPage(mSize.width, mSize.height);
+ if (!mRefCanvas) {
+ return nullptr;
+ }
+ RefPtr<DrawTarget> dt = Factory::CreateDrawTargetWithSkCanvas(mRefCanvas);
+ if (!dt) {
+ return nullptr;
+ }
+ mRefDT = std::move(dt);
+ }
+
+ return do_AddRef(mRefDT);
+}
+
+} // namespace mozilla::gfx