mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-24 02:35:41 +00:00
bfe3b297fb
Before we introduce PrintTargetEMF, all PrintTargets finish page printing task before the end of PrintTarget::EndPage(). Unlike others, a page printing in PrintTargetEMF is done after receiving an async callback from the pdfium process. So we have both async and sync page printing behavior now. This patch is trying to make both of them work correctly while priting a content document. MozReview-Commit-ID: 2PHJToFlvtu --HG-- extra : rebase_source : 3531dd6a100e9518d8cb9904326250a8318cdad2 extra : source : f61eb00f83acf45511d8448922212dccb12b05aa
181 lines
5.1 KiB
C++
181 lines
5.1 KiB
C++
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* 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 "PrintTargetEMF.h"
|
|
#include "nsAnonymousTemporaryFile.h"
|
|
#include "nsIFile.h"
|
|
#include "mozilla/widget/PDFiumProcessParent.h"
|
|
#include "mozilla/widget/PDFiumParent.h"
|
|
#include "mozilla/widget/WindowsEMF.h"
|
|
#include "mozilla/ipc/FileDescriptor.h"
|
|
#include "private/pprio.h"
|
|
|
|
using mozilla::gfx::DrawTarget;
|
|
using mozilla::ipc::FileDescriptor;
|
|
|
|
namespace mozilla {
|
|
namespace gfx {
|
|
|
|
PrintTargetEMF::PrintTargetEMF(HDC aDC, const IntSize& aSize)
|
|
: PrintTarget(/* not using cairo_surface_t */ nullptr, aSize)
|
|
, mPrinterDC(aDC)
|
|
{
|
|
}
|
|
|
|
PrintTargetEMF::~PrintTargetEMF()
|
|
{
|
|
if (mPDFiumProcess) {
|
|
mPDFiumProcess->Delete();
|
|
}
|
|
}
|
|
|
|
/* static */ already_AddRefed<PrintTargetEMF>
|
|
PrintTargetEMF::CreateOrNull(HDC aDC, const IntSize& aSizeInPoints)
|
|
{
|
|
return do_AddRef(new PrintTargetEMF(aDC, aSizeInPoints));
|
|
}
|
|
|
|
nsresult
|
|
PrintTargetEMF::BeginPrinting(const nsAString& aTitle,
|
|
const nsAString& aPrintToFileName,
|
|
int32_t aStartPage,
|
|
int32_t aEndPage)
|
|
{
|
|
mTitle = aTitle;
|
|
|
|
const uint32_t DOC_TITLE_LENGTH = MAX_PATH - 1;
|
|
|
|
DOCINFOW docinfo;
|
|
|
|
nsString titleStr(aTitle);
|
|
if (titleStr.Length() > DOC_TITLE_LENGTH) {
|
|
titleStr.SetLength(DOC_TITLE_LENGTH - 3);
|
|
titleStr.AppendLiteral("...");
|
|
}
|
|
|
|
nsString docName(aPrintToFileName);
|
|
docinfo.cbSize = sizeof(docinfo);
|
|
docinfo.lpszDocName = titleStr.Length() > 0 ? titleStr.get() : L"Mozilla Document";
|
|
docinfo.lpszOutput = docName.Length() > 0 ? docName.get() : nullptr;
|
|
docinfo.lpszDatatype = nullptr;
|
|
docinfo.fwType = 0;
|
|
|
|
::StartDocW(mPrinterDC, &docinfo);
|
|
|
|
mPDFiumProcess = new PDFiumProcessParent();
|
|
NS_ENSURE_TRUE(mPDFiumProcess->Launch(this), NS_ERROR_FAILURE);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
PrintTargetEMF::EndPrinting()
|
|
{
|
|
return (::EndDoc(mPrinterDC) <= 0) ? NS_ERROR_FAILURE : NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
PrintTargetEMF::AbortPrinting()
|
|
{
|
|
return (::AbortDoc(mPrinterDC) <= 0) ? NS_ERROR_FAILURE : NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
PrintTargetEMF::BeginPage()
|
|
{
|
|
MOZ_ASSERT(!mPDFFileForOnePage && !mTargetForCurrentPage);
|
|
|
|
NS_ENSURE_TRUE(::StartPage(mPrinterDC) >0, NS_ERROR_FAILURE);
|
|
|
|
// We create a new file for each page so that we can make sure each new
|
|
// mPDFFileForOnePage contains one single page.
|
|
nsresult rv =
|
|
NS_OpenAnonymousTemporaryNsIFile(getter_AddRefs(mPDFFileForOnePage));
|
|
NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
|
|
|
|
nsAutoCString filePath;
|
|
mPDFFileForOnePage->GetNativePath(filePath);
|
|
auto stream = MakeUnique<SkFILEWStream>(filePath.get());
|
|
|
|
// Creating a new PrintTargetSkPDF for each page so that we can convert each
|
|
// of them into EMF contents individually by the PDFium processes.
|
|
mTargetForCurrentPage = PrintTargetSkPDF::CreateOrNull(Move(stream), mSize);
|
|
mTargetForCurrentPage->BeginPrinting(mTitle, NS_LITERAL_STRING(""), 0, 0);
|
|
mTargetForCurrentPage->BeginPage();
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
nsresult
|
|
PrintTargetEMF::EndPage()
|
|
{
|
|
mTargetForCurrentPage->EndPage();
|
|
mTargetForCurrentPage->EndPrinting();
|
|
mTargetForCurrentPage->Finish();
|
|
mTargetForCurrentPage = nullptr;
|
|
|
|
PRFileDesc* prfile;
|
|
nsresult rv = mPDFFileForOnePage->OpenNSPRFileDesc(PR_RDONLY, PR_IRWXU,
|
|
&prfile);
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
FileDescriptor descriptor(FileDescriptor::PlatformHandleType(PR_FileDesc2NativeHandle(prfile)));
|
|
mPDFiumProcess->GetActor()->SendConvertToEMF(descriptor,
|
|
::GetDeviceCaps(mPrinterDC, HORZRES),
|
|
::GetDeviceCaps(mPrinterDC, VERTRES));
|
|
PR_Close(prfile);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
already_AddRefed<DrawTarget>
|
|
PrintTargetEMF::MakeDrawTarget(const IntSize& aSize,
|
|
DrawEventRecorder* aRecorder)
|
|
{
|
|
return mTargetForCurrentPage->MakeDrawTarget(aSize, aRecorder);
|
|
}
|
|
|
|
already_AddRefed<DrawTarget>
|
|
PrintTargetEMF::GetReferenceDrawTarget(DrawEventRecorder* aRecorder)
|
|
{
|
|
if (!mRefTarget) {
|
|
auto dummy = MakeUnique<SkNullWStream>();
|
|
mRefTarget = PrintTargetSkPDF::CreateOrNull(Move(dummy), mSize);
|
|
}
|
|
|
|
if (!mRefDT) {
|
|
mRefDT = mRefTarget->GetReferenceDrawTarget(aRecorder);
|
|
}
|
|
|
|
return mRefDT.forget();
|
|
}
|
|
|
|
void
|
|
PrintTargetEMF::ConvertToEMFDone(const nsresult& aResult,
|
|
mozilla::ipc::Shmem&& aEMF)
|
|
{
|
|
if (::StartPage(mPrinterDC) > 0) {
|
|
mozilla::widget::WindowsEMF emf;
|
|
emf.InitFromFileContents(aEMF.get<BYTE>(), aEMF.Size<BYTE>());
|
|
RECT printRect = {0, 0, ::GetDeviceCaps(mPrinterDC, HORZRES),
|
|
::GetDeviceCaps(mPrinterDC, VERTRES)};
|
|
DebugOnly<bool> ret = emf.Playback(mPrinterDC, printRect);
|
|
MOZ_ASSERT(ret);
|
|
|
|
::EndPage(mPrinterDC);
|
|
}
|
|
|
|
mPDFiumProcess->GetActor()->DeallocShmem(aEMF);
|
|
|
|
mPDFFileForOnePage->Remove(/* aRecursive */ false);
|
|
mPDFFileForOnePage = nullptr;
|
|
|
|
if (mPageDoneCallback) {
|
|
mPageDoneCallback(aResult);
|
|
}
|
|
}
|
|
|
|
} // namespace gfx
|
|
} // namespace mozilla
|