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 "nsIPrintSession.h"
|
|
|
|
#include "nsIPrintSettings.h"
|
2016-11-22 17:06:46 +03:00
|
|
|
#include "nsIUUIDGenerator.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)
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::Init(nsIWidget* aWidget,
|
|
|
|
nsIPrintSettings* aPrintSettings,
|
|
|
|
bool aIsPrintPreview)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
mRealDeviceContextSpec =
|
|
|
|
do_CreateInstance("@mozilla.org/gfx/devicecontextspec;1", &rv);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2017-01-06 14:29:11 +03:00
|
|
|
mRealDeviceContextSpec->Init(nullptr, aPrintSettings, aIsPrintPreview);
|
2016-01-05 13:08:57 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
mRealDeviceContextSpec = nullptr;
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
mPrintSettings = aPrintSettings;
|
|
|
|
|
|
|
|
if (aIsPrintPreview) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// nsIPrintSettings only has a weak reference to nsIPrintSession, so we hold
|
|
|
|
// it to make sure it's available for the lifetime of the print.
|
|
|
|
rv = mPrintSettings->GetPrintSession(getter_AddRefs(mPrintSession));
|
|
|
|
if (NS_FAILED(rv) || !mPrintSession) {
|
|
|
|
NS_WARNING("We can't print via the parent without an nsIPrintSession.");
|
2016-03-05 21:25:14 +03:00
|
|
|
return NS_ERROR_FAILURE;
|
2016-01-05 13:08:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
rv = mPrintSession->GetRemotePrintJob(getter_AddRefs(mRemotePrintJob));
|
|
|
|
if (NS_FAILED(rv) || !mRemotePrintJob) {
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2016-11-22 17:06:46 +03:00
|
|
|
rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
|
|
|
|
getter_AddRefs(mRecordingDir));
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
mUuidGenerator = do_GetService("@mozilla.org/uuid-generator;1", &rv);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
|
|
|
MOZ_ASSERT(mRealDeviceContextSpec);
|
|
|
|
|
|
|
|
double width, height;
|
2016-01-22 19:05:19 +03:00
|
|
|
nsresult rv = mPrintSettings->GetEffectivePageSize(&width, &height);
|
2016-03-19 14:07:16 +03:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv)) || 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()->
|
2016-07-26 17:48:30 +03:00
|
|
|
CreateOffscreenSurface(mozilla::gfx::IntSize::Truncate(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 DrawTargetWrapAndRecord.
|
2016-06-16 19:28:50 +03:00
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
|
|
|
|
float
|
|
|
|
nsDeviceContextSpecProxy::GetDPI()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mRealDeviceContextSpec);
|
|
|
|
|
|
|
|
return mRealDeviceContextSpec->GetDPI();
|
|
|
|
}
|
|
|
|
|
|
|
|
float
|
|
|
|
nsDeviceContextSpecProxy::GetPrintingScale()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mRealDeviceContextSpec);
|
|
|
|
|
|
|
|
return mRealDeviceContextSpec->GetPrintingScale();
|
|
|
|
}
|
|
|
|
|
2017-11-03 21:03:02 +03:00
|
|
|
nsresult
|
|
|
|
nsDeviceContextSpecProxy::CreateUniqueTempPath(nsACString& aFilePath)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mRecordingDir);
|
|
|
|
MOZ_ASSERT(mUuidGenerator);
|
|
|
|
|
|
|
|
nsID uuid;
|
|
|
|
nsresult rv = mUuidGenerator->GenerateUUIDInPlace(&uuid);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
char uuidChars[NSID_LENGTH];
|
|
|
|
uuid.ToProvidedString(uuidChars);
|
|
|
|
mRecordingFileName.AssignASCII(uuidChars);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIFile> recordingFile;
|
|
|
|
rv = mRecordingDir->Clone(getter_AddRefs(recordingFile));
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
rv = recordingFile->AppendNative(mRecordingFileName);
|
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
return recordingFile->GetNativePath(aFilePath);
|
|
|
|
}
|
|
|
|
|
2016-01-05 13:08:57 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::BeginDocument(const nsAString& aTitle,
|
|
|
|
const nsAString& aPrintToFileName,
|
|
|
|
int32_t aStartPage, int32_t aEndPage)
|
|
|
|
{
|
2017-11-03 21:03:02 +03:00
|
|
|
nsAutoCString recordingPath;
|
|
|
|
nsresult rv = CreateUniqueTempPath(recordingPath);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
mRecorder = new mozilla::layout::DrawEventRecorderPRFileDesc(recordingPath.get());
|
2016-01-05 13:08:57 +03:00
|
|
|
return mRemotePrintJob->InitializePrint(nsString(aTitle),
|
|
|
|
nsString(aPrintToFileName),
|
|
|
|
aStartPage, aEndPage);
|
2016-01-05 13:08:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::EndDocument()
|
|
|
|
{
|
|
|
|
Unused << mRemotePrintJob->SendFinalizePrint();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::AbortDocument()
|
|
|
|
{
|
|
|
|
Unused << mRemotePrintJob->SendAbortPrint(NS_OK);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::BeginPage()
|
|
|
|
{
|
2017-11-03 21:03:02 +03:00
|
|
|
// Reopen the file, if necessary, ready for the next page.
|
|
|
|
if (!mRecorder->IsOpen()) {
|
|
|
|
nsAutoCString recordingPath;
|
|
|
|
nsresult rv = CreateUniqueTempPath(recordingPath);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
mRecorder->OpenNew(recordingPath.get());
|
|
|
|
}
|
2016-11-22 17:06:46 +03:00
|
|
|
|
2016-01-05 13:08:57 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDeviceContextSpecProxy::EndPage()
|
|
|
|
{
|
|
|
|
// Send the page recording to the parent.
|
2016-11-22 17:06:46 +03:00
|
|
|
mRecorder->Close();
|
2017-11-03 21:03:02 +03:00
|
|
|
mRemotePrintJob->ProcessPage(mRecordingFileName);
|
2016-01-05 13:08:57 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|