Bug 1399787 - Part 6. Implement the bulk of a new PrintTargetEMF. r=jwatt

A new subclass of PrintTarget.
1. It uses PrintTargetSkPDF to generate one PDF FileDescriptor for one page.
2. In a later patch, it then passes that FD to PDFium process for converting
   a PDF page to EMF contents.

Implementation of integration with PDFium actor is added the subsequent patches.

MozReview-Commit-ID: EcuBJHRW8Wk

--HG--
extra : rebase_source : f977e6863b9f2ee961648ddaf13f5e30a3659410
This commit is contained in:
cku 2017-11-05 02:05:25 +08:00
Родитель 65b891af3e
Коммит 2755ec8823
3 изменённых файлов: 200 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,137 @@
/* -*- 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"
using mozilla::gfx::DrawTarget;
namespace mozilla {
namespace gfx {
PrintTargetEMF::PrintTargetEMF(HDC aDC, const IntSize& aSize)
: PrintTarget(/* not using cairo_surface_t */ nullptr, aSize)
, mPrinterDC(aDC)
{
}
/* 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);
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;
// TODO: pass mPDFFileForOnePage to the PDFium process.
mPDFFileForOnePage->Remove(/* aRecursive */ false);
mPDFFileForOnePage = nullptr;
// TODO: we should call EndPage(mPrinterDC), but not here. We should call it
// after the PDFium process calls Send ConvertToEMFDone.
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();
}
} // namespace gfx
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,62 @@
/* -*- 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/. */
#ifndef MOZILLA_GFX_PRINTTARGETEMF_H
#define MOZILLA_GFX_PRINTTARGETEMF_H
#include "PrintTargetSkPDF.h"
/* include windows.h for the HDC definitions that we need. */
#include <windows.h>
namespace mozilla {
namespace gfx {
/**
* A new subclass of PrintTarget.
* 1. It uses PrintTargetSkPDF to generate one PDF file for one page.
* 2. It then passes the FileDescriptor of that generated PDF file to the
* PDFium process for EMF conversion.
* 3. After getting the converted EMF contents from the PDFium process, it then
* draws it onto the printer DC to finish one page printing task.
*/
class PrintTargetEMF final : public mozilla::gfx::PrintTarget
{
public:
typedef gfx::IntSize IntSize;
static already_AddRefed<PrintTargetEMF>
CreateOrNull(HDC aDC, const IntSize& aSizeInPoints);
nsresult BeginPrinting(const nsAString& aTitle,
const nsAString& aPrintToFileName,
int32_t aStartPage,
int32_t aEndPage) final;
nsresult EndPrinting() final;
nsresult AbortPrinting() final;
nsresult BeginPage() final;
nsresult EndPage() final;
already_AddRefed<DrawTarget>
MakeDrawTarget(const IntSize& aSize,
DrawEventRecorder* aRecorder = nullptr) final;
already_AddRefed<DrawTarget>
GetReferenceDrawTarget(DrawEventRecorder* aRecorder) final;
private:
PrintTargetEMF(HDC aDC, const IntSize& aSize);
nsString mTitle;
RefPtr<PrintTargetSkPDF> mTargetForCurrentPage;
nsCOMPtr<nsIFile> mPDFFileForOnePage;
RefPtr<PrintTargetSkPDF> mRefTarget;
HDC mPrinterDC;
};
} // namespace gfx
} // namespace mozilla
#endif /* MOZILLA_GFX_PRINTTARGETEMF_H */

Просмотреть файл

@ -220,6 +220,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
UNIFIED_SOURCES += [
'D3D11Checks.cpp',
'DeviceManagerDx.cpp',
'PrintTargetEMF.cpp',
]
if CONFIG['MOZ_ENABLE_SKIA_PDF']: