Bug 1156742 Part 9: Add a new nsIDeviceContextSpec for proxied printing. r=roc

This also changes aPrintToFileName parameter for BeginDocument to an nsAString& from char16_t*.
Having a char16_t* caused a pain with VS2105 where wchar_t != char16_t (as on VS2103), after it had been sent over IPDL.
This could have been worked around with casting, but this seemed like the tidier solution.
This commit is contained in:
Bob Owen 2016-01-05 10:08:57 +00:00
parent 3e8e2fd0de
commit 00e78ab6fc
22 changed files with 312 additions and 30 deletions

View File

@ -5,6 +5,7 @@
#include "DrawEventRecorder.h"
#include "PathRecording.h"
#include "RecordingTypes.h"
namespace mozilla {
namespace gfx {

View File

@ -12,6 +12,7 @@
#include "Tools.h"
#include "Filters.h"
#include "mozilla/UniquePtr.h"
#include "RecordingTypes.h"
namespace mozilla {
namespace gfx {

View File

@ -4,8 +4,9 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "RecordedEvent.h"
#include "PathRecording.h"
#include "PathRecording.h"
#include "RecordingTypes.h"
#include "Tools.h"
#include "Filters.h"
#include "Logging.h"

View File

@ -10,12 +10,14 @@
#include <ostream>
#include <sstream>
#include <cstring>
#include "RecordingTypes.h"
#include "PathRecording.h"
#include <vector>
namespace mozilla {
namespace gfx {
struct PathOp;
class PathRecording;
// A change in major revision means a change in event binary format, causing
// loss of backwards compatibility. Old streams will not work in a player
// using a newer major revision. And new streams will not work in a player

View File

@ -22,6 +22,7 @@ EXPORTS.mozilla.gfx += [
'Coord.h',
'CriticalSection.h',
'DataSurfaceHelpers.h',
'DrawEventRecorder.h',
'DrawTargetTiled.h',
'Filters.h',
'Helpers.h',
@ -38,6 +39,7 @@ EXPORTS.mozilla.gfx += [
'PatternHelpers.h',
'Point.h',
'Quaternion.h',
'RecordedEvent.h',
'Rect.h',
'Scale.h',
'ScaleFactor.h',

View File

@ -400,6 +400,12 @@ nsDeviceContext::CreateRenderingContext()
return nullptr;
}
RefPtr<DrawEventRecorder> recorder;
nsresult rv = mDeviceContextSpec->GetDrawEventRecorder(getter_AddRefs(recorder));
if (NS_SUCCEEDED(rv) && recorder) {
dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dt);
}
#ifdef XP_MACOSX
dt->AddUserData(&gfxContext::sDontUseAsSourceKey, dt, nullptr);
#endif
@ -506,18 +512,16 @@ nsDeviceContext::InitForPrinting(nsIDeviceContextSpec *aDevice)
nsresult
nsDeviceContext::BeginDocument(const nsAString& aTitle,
char16_t* aPrintToFileName,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage)
{
static const char16_t kEmpty[] = { '\0' };
nsresult rv;
nsresult rv = mPrintingSurface->BeginPrinting(aTitle, aPrintToFileName);
rv = mPrintingSurface->BeginPrinting(aTitle,
nsDependentString(aPrintToFileName ? aPrintToFileName : kEmpty));
if (NS_SUCCEEDED(rv) && mDeviceContextSpec)
rv = mDeviceContextSpec->BeginDocument(aTitle, aPrintToFileName, aStartPage, aEndPage);
if (NS_SUCCEEDED(rv) && mDeviceContextSpec) {
rv = mDeviceContextSpec->BeginDocument(aTitle, aPrintToFileName,
aStartPage, aEndPage);
}
return rv;
}

View File

@ -182,8 +182,8 @@ public:
* EndDocument() or AbortDocument().
*
* @param aTitle - title of Document
* @param aPrintToFileName - name of file to print to, if nullptr
* then don't print to file
* @param aPrintToFileName - name of file to print to, if empty then don't
* print to file
* @param aStartPage - starting page number (must be greater than zero)
* @param aEndPage - ending page number (must be less than or
* equal to number of pages)
@ -191,7 +191,7 @@ public:
* @return error status
*/
nsresult BeginDocument(const nsAString& aTitle,
char16_t* aPrintToFileName,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage);

View File

@ -1678,14 +1678,15 @@ nsPrintEngine::SetupToPrintContent()
mPrt->OnStartPrinting();
}
char16_t* fileName = nullptr;
nsAutoString fileNameStr;
// check to see if we are printing to a file
bool isPrintToFile = false;
mPrt->mPrintSettings->GetPrintToFile(&isPrintToFile);
if (isPrintToFile) {
// On some platforms The BeginDocument needs to know the name of the file
// and it uses the PrintService to get it, so we need to set it into the PrintService here
// On some platforms The BeginDocument needs to know the name of the file.
char16_t* fileName = nullptr;
mPrt->mPrintSettings->GetToFileName(&fileName);
fileNameStr = fileName;
}
nsAutoString docTitleStr;
@ -1711,7 +1712,8 @@ nsPrintEngine::SetupToPrintContent()
// to the "File Name" dialog, this comes back as an error
// Don't start printing when regression test are executed
if (!mPrt->mDebugFilePtr && mIsDoingPrinting) {
rv = mPrt->mPrintDC->BeginDocument(docTitleStr, fileName, startPage, endPage);
rv = mPrt->mPrintDC->BeginDocument(docTitleStr, fileNameStr, startPage,
endPage);
}
if (mIsCreatingPrintPreview) {

View File

@ -52,7 +52,7 @@ nsDeviceContextSpecAndroid::Init(nsIWidget* aWidget,
NS_IMETHODIMP
nsDeviceContextSpecAndroid::BeginDocument(const nsAString& aTitle,
char16_t* aPrintToFileName,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage)
{

View File

@ -19,7 +19,7 @@ public:
nsIPrintSettings* aPS,
bool aIsPrintPreview) override;
NS_IMETHOD BeginDocument(const nsAString& aTitle,
char16_t* aPrintToFileName,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage) override;
NS_IMETHOD EndDocument() override;

View File

@ -20,7 +20,7 @@ public:
NS_IMETHOD Init(nsIWidget *aWidget, nsIPrintSettings* aPS, bool aIsPrintPreview) override;
NS_IMETHOD GetSurfaceForPrinter(gfxASurface **surface) override;
NS_IMETHOD BeginDocument(const nsAString& aTitle,
char16_t* aPrintToFileName,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage) override;
NS_IMETHOD EndDocument() override;

View File

@ -59,7 +59,7 @@ NS_IMETHODIMP nsDeviceContextSpecX::Init(nsIWidget *aWidget,
}
NS_IMETHODIMP nsDeviceContextSpecX::BeginDocument(const nsAString& aTitle,
char16_t* aPrintToFileName,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage)
{

View File

@ -300,8 +300,10 @@ nsDeviceContextSpecGTK::EnumeratePrinters()
nullptr, TRUE);
}
NS_IMETHODIMP nsDeviceContextSpecGTK::BeginDocument(const nsAString& aTitle, char16_t * aPrintToFileName,
int32_t aStartPage, int32_t aEndPage)
NS_IMETHODIMP
nsDeviceContextSpecGTK::BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage, int32_t aEndPage)
{
mTitle.Truncate();
AppendUTF16toUTF8(aTitle, mTitle);

View File

@ -34,7 +34,8 @@ public:
NS_IMETHOD Init(nsIWidget *aWidget, nsIPrintSettings* aPS,
bool aIsPrintPreview) override;
NS_IMETHOD BeginDocument(const nsAString& aTitle, char16_t * aPrintToFileName,
NS_IMETHOD BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage, int32_t aEndPage) override;
NS_IMETHOD EndDocument() override;
NS_IMETHOD BeginPage() override { return NS_OK; }

View File

@ -148,6 +148,7 @@ UNIFIED_SOURCES += [
'nsClipboardProxy.cpp',
'nsColorPickerProxy.cpp',
'nsContentProcessWidgetFactory.cpp',
'nsDeviceContextSpecProxy.cpp',
'nsDragServiceProxy.cpp',
'nsFilePickerProxy.cpp',
'nsHTMLFormatConverter.cpp',

View File

@ -0,0 +1,179 @@
/* -*- 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"
#include "gfxASurface.h"
#include "gfxPlatform.h"
#include "mozilla/gfx/DrawEventRecorder.h"
#include "mozilla/layout/RemotePrintJobChild.h"
#include "mozilla/RefPtr.h"
#include "mozilla/unused.h"
#include "nsComponentManagerUtils.h"
#include "nsIPrintSession.h"
#include "nsIPrintSettings.h"
using mozilla::Unused;
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, false);
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 rv;
}
rv = mPrintSession->GetRemotePrintJob(getter_AddRefs(mRemotePrintJob));
if (NS_FAILED(rv) || !mRemotePrintJob) {
NS_WARNING("We can't print via the parent without a RemotePrintJobChild.");
return rv;
}
return NS_OK;
}
NS_IMETHODIMP
nsDeviceContextSpecProxy::GetSurfaceForPrinter(gfxASurface** aSurface)
{
MOZ_ASSERT(aSurface);
MOZ_ASSERT(mRealDeviceContextSpec);
// The real device context may need to have created a real printing surface
// even though we're not using it directly.
nsresult rv = mRealDeviceContextSpec->GetSurfaceForPrinter(aSurface);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
double width, height;
rv = mPrintSettings->GetEffectivePageSize(&width, &height);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
// convert twips to points
width /= TWIPS_PER_POINT_FLOAT;
height /= TWIPS_PER_POINT_FLOAT;
RefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()->
CreateOffscreenSurface(mozilla::gfx::IntSize(width, height),
gfxImageFormat::ARGB32);
surface.forget(aSurface);
return NS_OK;
}
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();
}
NS_IMETHODIMP
nsDeviceContextSpecProxy::BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage, int32_t aEndPage)
{
mRecorder = new DrawEventRecorderMemory();
Unused << mRemotePrintJob->SendInitializePrint(nsString(aTitle),
nsString(aPrintToFileName),
aStartPage, aEndPage);
return NS_OK;
}
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()
{
return NS_OK;
}
NS_IMETHODIMP
nsDeviceContextSpecProxy::EndPage()
{
// Save the current page recording to shared memory.
mozilla::ipc::Shmem storedPage;
size_t recordingSize = mRecorder->RecordingSize();
if (!mRemotePrintJob->AllocShmem(recordingSize,
mozilla::ipc::SharedMemory::TYPE_BASIC,
&storedPage)) {
NS_WARNING("Failed to create shared memory for remote printing.");
return NS_ERROR_FAILURE;
}
bool success = mRecorder->CopyRecording(storedPage.get<char>(), recordingSize);
if (!success) {
NS_WARNING("Copying recording to shared memory was not succesful.");
return NS_ERROR_FAILURE;
}
// Wipe the recording to free memory. The recorder does not forget which data
// backed objects that it has stored.
mRecorder->WipeRecording();
// Send the page recording to the parent.
mRemotePrintJob->ProcessPage(storedPage);
return NS_OK;
}

View File

@ -0,0 +1,63 @@
/* -*- 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 nsDeviceContextSpecProxy_h
#define nsDeviceContextSpecProxy_h
#include "nsIDeviceContextSpec.h"
#include "nsCOMPtr.h"
class nsIPrintSession;
namespace mozilla {
namespace gfx {
class DrawEventRecorderMemory;
}
namespace layout {
class RemotePrintJobChild;
}
}
class nsDeviceContextSpecProxy final : public nsIDeviceContextSpec
{
public:
NS_DECL_ISUPPORTS
NS_METHOD Init(nsIWidget* aWidget, nsIPrintSettings* aPrintSettings,
bool aIsPrintPreview) final;
NS_METHOD GetSurfaceForPrinter(gfxASurface** aSurface) final;
NS_METHOD GetDrawEventRecorder(mozilla::gfx::DrawEventRecorder** aDrawEventRecorder) final;
float GetDPI() final;
float GetPrintingScale() final;
NS_METHOD BeginDocument(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage, int32_t aEndPage) final;
NS_METHOD EndDocument() final;
NS_METHOD AbortDocument() final;
NS_METHOD BeginPage() final;
NS_METHOD EndPage() final;
private:
~nsDeviceContextSpecProxy() {}
nsCOMPtr<nsIPrintSettings> mPrintSettings;
nsCOMPtr<nsIPrintSession> mPrintSession;
nsCOMPtr<nsIDeviceContextSpec> mRealDeviceContextSpec;
RefPtr<mozilla::layout::RemotePrintJobChild> mRemotePrintJob;
RefPtr<mozilla::gfx::DrawEventRecorderMemory> mRecorder;
};
#endif // nsDeviceContextSpecProxy_h

View File

@ -12,6 +12,12 @@ class nsIWidget;
class nsIPrintSettings;
class gfxASurface;
namespace mozilla {
namespace gfx{
class DrawEventRecorder;
}
}
#define NS_IDEVICE_CONTEXT_SPEC_IID \
{ 0xf407cfba, 0xbe28, 0x46c9, \
{ 0x8a, 0xba, 0x04, 0x2d, 0xae, 0xbb, 0x4f, 0x23 } }
@ -34,6 +40,19 @@ public:
NS_IMETHOD GetSurfaceForPrinter(gfxASurface **nativeSurface) = 0;
/**
* If required override to return a recorder to record the print.
*
* @param aDrawEventRecorder out param for the recorder to use
* @return NS_OK or a suitable error code
*/
NS_IMETHOD GetDrawEventRecorder(mozilla::gfx::DrawEventRecorder** aDrawEventRecorder)
{
MOZ_ASSERT(aDrawEventRecorder);
*aDrawEventRecorder = nullptr;
return NS_OK;
}
/**
* Override to return something other than the default.
*
@ -49,11 +68,12 @@ public:
virtual float GetPrintingScale() { return 1.0f; }
NS_IMETHOD BeginDocument(const nsAString& aTitle,
char16_t* aPrintToFileName,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage) = 0;
NS_IMETHOD EndDocument() = 0;
NS_IMETHOD AbortDocument() { return EndDocument(); }
NS_IMETHOD BeginPage() = 0;
NS_IMETHOD EndPage() = 0;
};

View File

@ -21,6 +21,9 @@
#include "nsPrimitiveHelpers.h"
#include "mozilla/UniquePtr.h"
#include "nsAutoPtr.h"
#include "nsCOMPtr.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
@ -60,7 +63,7 @@ nsPrimitiveHelpers :: CreatePrimitiveForData ( const char* aFlavor, const void*
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
if (primitive ) {
if (aDataLen % 2) {
auto buffer = MakeUnique<char[]>(aDataLen + 1);
auto buffer = mozilla::MakeUnique<char[]>(aDataLen + 1);
if (!MOZ_LIKELY(buffer))
return;

View File

@ -151,7 +151,7 @@ NS_IMETHODIMP nsDeviceContextSpecQt::Init(nsIWidget* aWidget,
NS_IMETHODIMP nsDeviceContextSpecQt::BeginDocument(
const nsAString& aTitle,
char16_t* aPrintToFileName,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage)
{

View File

@ -28,7 +28,7 @@ public:
nsIPrintSettings* aPS,
bool aIsPrintPreview);
NS_IMETHOD BeginDocument(const nsAString& aTitle,
char16_t* aPrintToFileName,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage);
NS_IMETHOD EndDocument();

View File

@ -26,7 +26,7 @@ public:
NS_IMETHOD GetSurfaceForPrinter(gfxASurface **surface) override;
NS_IMETHOD BeginDocument(const nsAString& aTitle,
char16_t* aPrintToFileName,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage) override { return NS_OK; }
NS_IMETHOD EndDocument() override { return NS_OK; }