123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- /* -*- Mode: C++; tab-width: 8; 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 "nsDeviceContextSpecProxy.h"
- #include "gfxASurface.h"
- #include "gfxPlatform.h"
- #include "mozilla/gfx/DrawEventRecorder.h"
- #include "mozilla/gfx/PrintTargetThebes.h"
- #include "mozilla/layout/RemotePrintJobChild.h"
- #include "mozilla/RefPtr.h"
- #include "mozilla/Unused.h"
- #include "nsComponentManagerUtils.h"
- #include "nsAppDirectoryServiceDefs.h"
- #include "nsDirectoryServiceUtils.h"
- #include "nsIPrintSession.h"
- #include "nsIPrintSettings.h"
- #include "nsIUUIDGenerator.h"
- using mozilla::Unused;
- using namespace mozilla;
- using namespace mozilla::gfx;
- 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;
- }
- mRealDeviceContextSpec->Init(nullptr, aPrintSettings, aIsPrintPreview);
- 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.");
- return NS_ERROR_FAILURE;
- }
- rv = mPrintSession->GetRemotePrintJob(getter_AddRefs(mRemotePrintJob));
- if (NS_FAILED(rv) || !mRemotePrintJob) {
- NS_WARNING("We can't print via the parent without a RemotePrintJobChild.");
- return NS_ERROR_FAILURE;
- }
- 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;
- }
- return NS_OK;
- }
- already_AddRefed<PrintTarget>
- nsDeviceContextSpecProxy::MakePrintTarget()
- {
- MOZ_ASSERT(mRealDeviceContextSpec);
- double width, height;
- nsresult rv = mPrintSettings->GetEffectivePageSize(&width, &height);
- if (NS_WARN_IF(NS_FAILED(rv)) || width <= 0 || height <= 0) {
- return nullptr;
- }
- // convert twips to points
- width /= TWIPS_PER_POINT_FLOAT;
- height /= TWIPS_PER_POINT_FLOAT;
- RefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()->
- CreateOffscreenSurface(mozilla::gfx::IntSize::Truncate(width, height),
- 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
- // the DrawTarget returned by the PrintTarget will be a DrawTargetRecording.
- // 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();
- }
- 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();
- }
- 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);
- }
- NS_IMETHODIMP
- nsDeviceContextSpecProxy::BeginDocument(const nsAString& aTitle,
- const nsAString& aPrintToFileName,
- 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());
- return mRemotePrintJob->InitializePrint(nsString(aTitle),
- nsString(aPrintToFileName),
- aStartPage, aEndPage);
- }
- 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()
- {
- // 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());
- }
- return NS_OK;
- }
- NS_IMETHODIMP
- nsDeviceContextSpecProxy::EndPage()
- {
- // Send the page recording to the parent.
- mRecorder->Close();
- mRemotePrintJob->ProcessPage(mRecordingFileName);
- return NS_OK;
- }
|