2016-01-05 13:08:57 +03:00
|
|
|
/* -*- 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 "nsDeviceContextSpecProxy.h"
|
|
|
|
|
2016-06-16 19:28:50 +03:00
|
|
|
#include "gfxASurface.h"
|
2016-01-05 13:08:57 +03:00
|
|
|
#include "gfxPlatform.h"
|
|
|
|
#include "mozilla/gfx/DrawEventRecorder.h"
|
2016-06-16 19:28:50 +03:00
|
|
|
#include "mozilla/gfx/PrintTargetThebes.h"
|
2016-01-05 13:08:57 +03:00
|
|
|
#include "mozilla/layout/RemotePrintJobChild.h"
|
|
|
|
#include "mozilla/RefPtr.h"
|
2016-08-23 07:09:32 +03:00
|
|
|
#include "mozilla/Unused.h"
|
2016-01-05 13:08:57 +03:00
|
|
|
#include "nsComponentManagerUtils.h"
|
2016-11-22 17:06:46 +03:00
|
|
|
#include "nsAppDirectoryServiceDefs.h"
|
|
|
|
#include "nsDirectoryServiceUtils.h"
|
2016-01-05 13:08:57 +03:00
|
|
|
#include "nsIPrintSettings.h"
|
2017-11-03 21:37:15 +03:00
|
|
|
#include "private/pprio.h"
|
2016-01-05 13:08:57 +03:00
|
|
|
|
|
|
|
using mozilla::Unused;
|
|
|
|
|
2016-06-03 13:27:31 +03:00
|
|
|
using namespace mozilla;
|
|
|
|
using namespace mozilla::gfx;
|
|
|
|
|
2016-01-05 13:08:57 +03:00
|
|
|
NS_IMPL_ISUPPORTS(nsDeviceContextSpecProxy, nsIDeviceContextSpec)
|
|
|
|
|
2022-05-16 11:38:01 +03:00
|
|
|
nsDeviceContextSpecProxy::nsDeviceContextSpecProxy(
|
|
|
|
RemotePrintJobChild* aRemotePrintJob)
|
|
|
|
: mRemotePrintJob(aRemotePrintJob) {}
|
2021-06-13 12:16:53 +03:00
|
|
|
nsDeviceContextSpecProxy::~nsDeviceContextSpecProxy() = default;
|
|
|
|
|
2016-01-05 13:08:57 +03:00
|
|
|
NS_IMETHODIMP
|
2022-06-07 15:32:55 +03:00
|
|
|
nsDeviceContextSpecProxy::Init(nsIPrintSettings* aPrintSettings,
|
|
|
|
bool aIsPrintPreview) {
|
2016-01-05 13:08:57 +03:00
|
|
|
mPrintSettings = aPrintSettings;
|
|
|
|
|
|
|
|
if (aIsPrintPreview) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2018-11-20 04:17:54 +03:00
|
|
|
if (!mRemotePrintJob) {
|
2016-01-05 13:08:57 +03:00
|
|
|
NS_WARNING("We can't print via the parent without a RemotePrintJobChild.");
|
2016-03-05 21:25:14 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
2016-01-05 13:08:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2016-06-03 13:27:31 +03:00
|
|
|
already_AddRefed<PrintTarget> nsDeviceContextSpecProxy::MakePrintTarget() {
|
2016-01-05 13:08:57 +03:00
|
|
|
double width, height;
|
Bug 1669905 part 2: Add nsIPrintSettings APIs to handle the possibility that pages and sheets may have orthogonal orientation, in pages-per-sheet printouts. r=jfkthame
This patch does three things, all centered around these new APIs:
(1) Add the APIs themselves -- some nsIPrintSettings methods to reason about
the sheet-orientation being potentially flipped to accomodate 2 and 6
pages-per-sheet.
(2) Use these new APIs, where appropriate, in places where we previously used
the page-orientation to set up the platform-native print-settings objects and
print-target. Now, we'll use the *sheet* orientation instead of the page
orientation, to be sure we produce the appropriately-oriented platform-native
surfaces. Also, for symmetry, this patch adds similar logic to the reverse
codepaths, where we update an existing nsIPrintSettings object based on a
platform-native print-settings object.
(3) Update nsPrintJob's code that informs nsPresContext about the page-size.
This patch makes sure that this code uses the *page* size, rather than the
*sheet* size, in cases where they differ. (The code that consumes this
nsPresContext::GetPageSize API, e.g. our CSS media-query code, really does want
the page size, not the sheet size.)
Differential Revision: https://phabricator.services.mozilla.com/D100372
2021-01-05 05:24:00 +03:00
|
|
|
mPrintSettings->GetEffectiveSheetSize(&width, &height);
|
|
|
|
if (width <= 0 || height <= 0) {
|
2016-06-03 13:27:31 +03:00
|
|
|
return nullptr;
|
2016-01-05 13:08:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// convert twips to points
|
|
|
|
width /= TWIPS_PER_POINT_FLOAT;
|
|
|
|
height /= TWIPS_PER_POINT_FLOAT;
|
|
|
|
|
2016-06-16 19:28:50 +03:00
|
|
|
RefPtr<gfxASurface> surface =
|
|
|
|
gfxPlatform::GetPlatform()->CreateOffscreenSurface(
|
2021-02-06 03:28:29 +03:00
|
|
|
mozilla::gfx::IntSize::Ceil(width, height),
|
2016-06-16 19:28:50 +03:00
|
|
|
mozilla::gfx::SurfaceFormat::A8R8G8B8_UINT32);
|
|
|
|
if (!surface) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The type of PrintTarget that we return here shouldn't really matter since
|
|
|
|
// our implementation of GetDrawEventRecorder returns an object, which means
|
2017-06-12 23:52:29 +03:00
|
|
|
// the DrawTarget returned by the PrintTarget will be a
|
2016-06-16 19:28:50 +03:00
|
|
|
// DrawTargetWrapAndRecord. The recording will be serialized and sent over to
|
|
|
|
// the parent process where PrintTranslator::TranslateRecording will call
|
|
|
|
// MakePrintTarget (indirectly via PrintTranslator::CreateDrawTarget) on
|
|
|
|
// whatever type of nsIDeviceContextSpecProxy is created for the platform that
|
|
|
|
// we are running on. It is that DrawTarget that the recording will be
|
|
|
|
// replayed on to print.
|
|
|
|
// XXX(jwatt): The above isn't quite true. We do want to use a
|
|
|
|
// PrintTargetRecording here, but we can't until bug 1280324 is figured out
|
|
|
|
// and fixed otherwise we will cause bug 1280181 to happen again.
|
|
|
|
RefPtr<PrintTarget> target = PrintTargetThebes::CreateOrNull(surface);
|
|
|
|
|
|
|
|
return target.forget();
|
2016-01-05 13:08:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::GetDrawEventRecorder(
|
|
|
|
mozilla::gfx::DrawEventRecorder** aDrawEventRecorder) {
|
|
|
|
MOZ_ASSERT(aDrawEventRecorder);
|
|
|
|
RefPtr<mozilla::gfx::DrawEventRecorder> result = mRecorder;
|
|
|
|
result.forget(aDrawEventRecorder);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::BeginDocument(const nsAString& aTitle,
|
|
|
|
const nsAString& aPrintToFileName,
|
|
|
|
int32_t aStartPage, int32_t aEndPage) {
|
2021-03-18 22:39:09 +03:00
|
|
|
if (!mRemotePrintJob || mRemotePrintJob->IsDestroyed()) {
|
|
|
|
mRemotePrintJob = nullptr;
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2017-11-03 21:37:15 +03:00
|
|
|
mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc();
|
2022-05-21 01:50:59 +03:00
|
|
|
nsresult rv =
|
|
|
|
mRemotePrintJob->InitializePrint(nsString(aTitle), aStartPage, aEndPage);
|
2018-02-16 17:53:26 +03:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
// The parent process will send a 'delete' message to tell this process to
|
|
|
|
// delete our RemotePrintJobChild. As soon as we return to the event loop
|
|
|
|
// and evaluate that message we will crash if we try to access
|
|
|
|
// mRemotePrintJob. We must not try to use it again.
|
|
|
|
mRemotePrintJob = nullptr;
|
|
|
|
}
|
|
|
|
return rv;
|
2016-01-05 13:08:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::EndDocument() {
|
2021-03-18 22:39:09 +03:00
|
|
|
if (!mRemotePrintJob || mRemotePrintJob->IsDestroyed()) {
|
|
|
|
mRemotePrintJob = nullptr;
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2018-02-16 17:53:26 +03:00
|
|
|
}
|
2021-03-18 22:39:09 +03:00
|
|
|
|
|
|
|
Unused << mRemotePrintJob->SendFinalizePrint();
|
|
|
|
|
2016-01-05 13:08:57 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::AbortDocument() {
|
2021-03-18 22:39:09 +03:00
|
|
|
if (!mRemotePrintJob || mRemotePrintJob->IsDestroyed()) {
|
|
|
|
mRemotePrintJob = nullptr;
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
2018-02-16 17:53:26 +03:00
|
|
|
}
|
2021-03-18 22:39:09 +03:00
|
|
|
|
|
|
|
Unused << mRemotePrintJob->SendAbortPrint(NS_OK);
|
|
|
|
|
2016-01-05 13:08:57 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::BeginPage() {
|
2021-03-18 22:39:09 +03:00
|
|
|
if (!mRemotePrintJob || mRemotePrintJob->IsDestroyed()) {
|
|
|
|
mRemotePrintJob = nullptr;
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2017-11-03 21:37:15 +03:00
|
|
|
mRecorder->OpenFD(mRemotePrintJob->GetNextPageFD());
|
2016-11-22 17:06:46 +03:00
|
|
|
|
2016-01-05 13:08:57 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::EndPage() {
|
2021-03-18 22:39:09 +03:00
|
|
|
if (!mRemotePrintJob || mRemotePrintJob->IsDestroyed()) {
|
|
|
|
mRemotePrintJob = nullptr;
|
|
|
|
return NS_ERROR_NOT_AVAILABLE;
|
|
|
|
}
|
|
|
|
|
2016-01-05 13:08:57 +03:00
|
|
|
// Send the page recording to the parent.
|
2016-11-22 17:06:46 +03:00
|
|
|
mRecorder->Close();
|
2020-10-08 11:40:15 +03:00
|
|
|
mRemotePrintJob->ProcessPage(std::move(mRecorder->TakeDependentSurfaces()));
|
2016-01-05 13:08:57 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|