Bug 1399787 - Part 2.b. Add functions to read/write EMF content from/to a buffer. r=jwatt

With the help of these new function, we can serialize/deserialize EMF content
in/out a share memory object.

MozReview-Commit-ID: Dm45xEXmMqS

--HG--
extra : rebase_source : 02b571735de70b499aea30bfdb3c0a35fece3332
extra : source : 61f81b148f8b1d1569d7cf279575b38f4570171f
This commit is contained in:
cku 2017-11-01 20:27:17 +08:00
parent 7637aa84f2
commit b846eba123
5 changed files with 113 additions and 8 deletions

View File

@ -10,6 +10,7 @@
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/dom/File.h"
#include "mozilla/Unused.h"
#include "mozilla/ipc/ProtocolUtils.h"
/* Scale DC by keeping aspect ratio */
static
@ -186,6 +187,8 @@ PDFViaEMFPrintHelper::DrawPageToFile(const wchar_t* aFilePath,
unsigned int aPageIndex,
int aPageWidth, int aPageHeight)
{
MOZ_ASSERT(aFilePath);
// OpenDocument might fail.
if (!mPDFDoc) {
MOZ_ASSERT_UNREACHABLE("Make sure OpenDocument return true before"
@ -202,6 +205,43 @@ PDFViaEMFPrintHelper::DrawPageToFile(const wchar_t* aFilePath,
return emf.SaveToFile();
}
bool
PDFViaEMFPrintHelper::SavePageToBuffer(unsigned int aPageIndex,
int aPageWidth, int aPageHeight,
ipc::Shmem& aMem,
mozilla::ipc::IShmemAllocator* aAllocator)
{
MOZ_ASSERT(aAllocator);
// OpenDocument might fail.
if (!mPDFDoc) {
MOZ_ASSERT_UNREACHABLE("Make sure OpenDocument return true before"
"using DrawPageToFile.");
return false;
}
WindowsEMF emf;
bool result = emf.InitForDrawing();
NS_ENSURE_TRUE(result, false);
result = RenderPageToDC(emf.GetDC(), aPageIndex, aPageWidth, aPageHeight);
NS_ENSURE_TRUE(result, false);
UINT emfSize = emf.GetEMFContentSize();
NS_ENSURE_TRUE(emfSize != 0, false);
auto shmType = ipc::SharedMemory::SharedMemoryType::TYPE_BASIC;
result = aAllocator->AllocShmem(emfSize, shmType, &aMem);
NS_ENSURE_TRUE(result, false);
if (!emf.GetEMFContentBits(aMem.get<BYTE>())) {
aAllocator->DeallocShmem(aMem);
return false;;
}
return true;
}
void
PDFViaEMFPrintHelper::CloseDocument()
{
@ -221,6 +261,7 @@ PDFViaEMFPrintHelper::CreatePDFiumEngineIfNeed()
{
if (!mPDFiumEngine) {
mPDFiumEngine = PDFiumEngineShim::GetInstanceOrNull();
MOZ_ASSERT(mPDFiumEngine);
}
return !!mPDFiumEngine;

View File

@ -10,6 +10,7 @@
#include "PDFiumEngineShim.h"
#include "mozilla/Vector.h"
#include "mozilla/ipc/FileDescriptor.h"
#include "mozilla/ipc/Shmem.h"
/* include windows.h for the HDC definitions that we need. */
#include <windows.h>
@ -18,6 +19,11 @@ class nsIFile;
class nsFileInputStream;
namespace mozilla {
namespace ipc {
class IShmemAllocator;
}
namespace widget {
/**
@ -35,7 +41,7 @@ public:
virtual ~PDFViaEMFPrintHelper();
/** Loads the specified PDF file. */
NS_IMETHOD OpenDocument(nsIFile *aFile);
NS_IMETHOD OpenDocument(nsIFile* aFile);
NS_IMETHOD OpenDocument(const char* aFileName);
NS_IMETHOD OpenDocument(const FileDescriptor& aFD);
@ -48,10 +54,15 @@ public:
bool DrawPage(HDC aPrinterDC, unsigned int aPageIndex,
int aPageWidth, int aPageHeight);
/** Convert specified PDF page to EMF and save it to file. */
/** Convert a specified PDF page to EMF and save it to file. */
bool DrawPageToFile(const wchar_t* aFilePath, unsigned int aPageIndex,
int aPageWidth, int aPageHeight);
/** Create a share memory and serialize the EMF content into it. */
bool SavePageToBuffer(unsigned int aPageIndex, int aPageWidth,
int aPageHeight, ipc::Shmem& aMem,
mozilla::ipc::IShmemAllocator* aAllocator);
protected:
virtual bool CreatePDFiumEngineIfNeed();
bool RenderPageToDC(HDC aDC, unsigned int aPageIndex,

View File

@ -39,6 +39,17 @@ WindowsEMF::InitFromFileContents(const wchar_t* aMetafilePath)
return !!mEmf;
}
bool
WindowsEMF::InitFromFileContents(LPBYTE aBytes, UINT aSize)
{
MOZ_ASSERT(aBytes && aSize != 0);
ReleaseAllResource();
mEmf = SetEnhMetaFileBits(aSize, aBytes);
return !!mEmf;
}
bool
WindowsEMF::FinishDocument()
{
@ -68,9 +79,8 @@ WindowsEMF::ReleaseAllResource()
bool
WindowsEMF::Playback(HDC aDeviceContext, const RECT& aRect)
{
if (!FinishDocument()) {
return false;
}
DebugOnly<bool> result = FinishDocument();
MOZ_ASSERT(result, "This function should be used after InitXXX.");
return ::PlayEnhMetaFile(aDeviceContext, mEmf, &aRect) != 0;
}
@ -78,10 +88,33 @@ WindowsEMF::Playback(HDC aDeviceContext, const RECT& aRect)
bool
WindowsEMF::SaveToFile()
{
if (!FinishDocument()) {
DebugOnly<bool> result = FinishDocument();
MOZ_ASSERT(result, "This function should be used after InitXXX.");
ReleaseEMFHandle();
return true;
}
UINT
WindowsEMF::GetEMFContentSize()
{
DebugOnly<bool> result = FinishDocument();
MOZ_ASSERT(result, "This function should be used after InitXXX.");
return GetEnhMetaFileBits(mEmf, 0, NULL);
}
bool
WindowsEMF::GetEMFContentBits(LPBYTE aBytes)
{
DebugOnly<bool> result = FinishDocument();
MOZ_ASSERT(result, "This function should be used after InitXXX.");
UINT emfSize = GetEMFContentSize();
if (GetEnhMetaFileBits(mEmf, emfSize, aBytes) != emfSize) {
return false;
}
ReleaseEMFHandle();
return true;
}

View File

@ -43,6 +43,14 @@ public:
*/
bool InitFromFileContents(const wchar_t* aMetafilePath);
/**
* Creates the EMF from the specified data
*
* @param aByte Pointer to a buffer that contains EMF data.
* @param aSize Specifies the size, in bytes, of aByte.
*/
bool InitFromFileContents(PBYTE aBytes, UINT aSize);
/**
* If this object was initiaziled using InitForDrawing() then this function
* returns an HDC that can be drawn to generate the EMF output. Otherwise it
@ -70,6 +78,18 @@ public:
*/
bool SaveToFile();
/**
* Return the size of the enhanced metafile, in bytes.
*/
UINT GetEMFContentSize();
/**
* Retrieves the contents of the EMF and copies them into a buffer.
*
* @param aByte the buffer to receive the data.
*/
bool GetEMFContentBits(PBYTE aBytes);
private:
WindowsEMF(const WindowsEMF& aEMF) = delete;

View File

@ -195,7 +195,7 @@ TEST(TestEMFConversion, TestInsufficientWidthAndHeight)
emfPath)));
ASSERT_FALSE(PDFHelper->DrawPageToFile(emfPath.get(), 0, 0, 0));
ASSERT_FALSE(PDFHelper->DrawPageToFile(emfPath.get(), 0, 100, -1));
ASSERT_FALSE(PDFHelper->PageToFile(emfPath.get(), 0, 100, -1));
PDFHelper->CloseDocument();
}