Update Windows printing code to latest
This commit is contained in:
parent
d483352f78
commit
1ed8743da8
9 changed files with 133 additions and 144 deletions
|
@ -4,13 +4,22 @@
|
|||
|
||||
#include "chrome/browser/printing/pdf_to_emf_converter.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include <memory>
|
||||
#include <queue>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/files/file.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/files/scoped_temp_dir.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "chrome/common/chrome_utility_messages.h"
|
||||
#include "chrome/common/print_messages.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
@ -19,6 +28,7 @@
|
|||
#include "content/public/browser/utility_process_host_client.h"
|
||||
#include "printing/emf_win.h"
|
||||
#include "printing/pdf_render_settings.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
namespace printing {
|
||||
|
||||
|
@ -59,7 +69,9 @@ typedef std::unique_ptr<base::File, BrowserThread::DeleteOnFileThread>
|
|||
class LazyEmf : public MetafilePlayer {
|
||||
public:
|
||||
LazyEmf(const scoped_refptr<RefCountedTempDir>& temp_dir, ScopedTempFile file)
|
||||
: temp_dir_(temp_dir), file_(std::move(file)) {}
|
||||
: temp_dir_(temp_dir), file_(std::move(file)) {
|
||||
CHECK(file_);
|
||||
}
|
||||
~LazyEmf() override { Close(); }
|
||||
|
||||
bool SafePlayback(HDC hdc) const override;
|
||||
|
@ -97,6 +109,7 @@ class PdfToEmfUtilityProcessHostClient
|
|||
const PdfRenderSettings& settings);
|
||||
|
||||
void Start(const scoped_refptr<base::RefCountedMemory>& data,
|
||||
bool print_text_with_gdi,
|
||||
const PdfToEmfConverter::StartCallback& start_callback);
|
||||
|
||||
void GetPage(int page_number,
|
||||
|
@ -104,10 +117,14 @@ class PdfToEmfUtilityProcessHostClient
|
|||
|
||||
void Stop();
|
||||
|
||||
// Needs to be public to handle ChromeUtilityHostMsg_PreCacheFontCharacters
|
||||
// sync message replies.
|
||||
bool Send(IPC::Message* msg);
|
||||
|
||||
// UtilityProcessHostClient implementation.
|
||||
virtual void OnProcessCrashed(int exit_code) override;
|
||||
virtual void OnProcessLaunchFailed(int exit_code) override;
|
||||
virtual bool OnMessageReceived(const IPC::Message& message) override;
|
||||
void OnProcessCrashed(int exit_code) override;
|
||||
void OnProcessLaunchFailed(int exit_code) override;
|
||||
bool OnMessageReceived(const IPC::Message& message) override;
|
||||
|
||||
private:
|
||||
class GetPageCallbackData {
|
||||
|
@ -138,19 +155,20 @@ class PdfToEmfUtilityProcessHostClient
|
|||
int page_number_;
|
||||
PdfToEmfConverter::GetPageCallback callback_;
|
||||
ScopedTempFile emf_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData);
|
||||
};
|
||||
|
||||
virtual ~PdfToEmfUtilityProcessHostClient();
|
||||
|
||||
bool Send(IPC::Message* msg);
|
||||
~PdfToEmfUtilityProcessHostClient() override;
|
||||
|
||||
// Message handlers.
|
||||
void OnProcessStarted();
|
||||
void OnPageCount(int page_count);
|
||||
void OnPageDone(bool success, float scale_factor);
|
||||
void OnPreCacheFontCharacters(const LOGFONT& log_font,
|
||||
const base::string16& characters);
|
||||
|
||||
void OnFailed();
|
||||
void OnTempPdfReady(ScopedTempFile pdf);
|
||||
void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf);
|
||||
void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf);
|
||||
|
||||
scoped_refptr<RefCountedTempDir> temp_dir_;
|
||||
|
@ -158,7 +176,6 @@ class PdfToEmfUtilityProcessHostClient
|
|||
// Used to suppress callbacks after PdfToEmfConverterImpl is deleted.
|
||||
base::WeakPtr<PdfToEmfConverterImpl> converter_;
|
||||
PdfRenderSettings settings_;
|
||||
scoped_refptr<base::RefCountedMemory> data_;
|
||||
|
||||
// Document loaded callback.
|
||||
PdfToEmfConverter::StartCallback start_callback_;
|
||||
|
@ -179,14 +196,15 @@ class PdfToEmfConverterImpl : public PdfToEmfConverter {
|
|||
public:
|
||||
PdfToEmfConverterImpl();
|
||||
|
||||
virtual ~PdfToEmfConverterImpl();
|
||||
~PdfToEmfConverterImpl() override;
|
||||
|
||||
virtual void Start(const scoped_refptr<base::RefCountedMemory>& data,
|
||||
const PdfRenderSettings& conversion_settings,
|
||||
const StartCallback& start_callback) override;
|
||||
void Start(const scoped_refptr<base::RefCountedMemory>& data,
|
||||
const PdfRenderSettings& conversion_settings,
|
||||
bool print_text_with_gdi,
|
||||
const StartCallback& start_callback) override;
|
||||
|
||||
virtual void GetPage(int page_number,
|
||||
const GetPageCallback& get_page_callback) override;
|
||||
void GetPage(int page_number,
|
||||
const GetPageCallback& get_page_callback) override;
|
||||
|
||||
// Helps to cancel callbacks if this object is destroyed.
|
||||
void RunCallback(const base::Closure& callback);
|
||||
|
@ -205,16 +223,21 @@ ScopedTempFile CreateTempFile(scoped_refptr<RefCountedTempDir>* temp_dir) {
|
|||
if (!(*temp_dir)->IsValid())
|
||||
return file;
|
||||
base::FilePath path;
|
||||
if (!base::CreateTemporaryFileInDir((*temp_dir)->GetPath(), &path))
|
||||
if (!base::CreateTemporaryFileInDir((*temp_dir)->GetPath(), &path)) {
|
||||
PLOG(ERROR) << "Failed to create file in "
|
||||
<< (*temp_dir)->GetPath().value();
|
||||
return file;
|
||||
}
|
||||
file.reset(new base::File(path,
|
||||
base::File::FLAG_CREATE_ALWAYS |
|
||||
base::File::FLAG_WRITE |
|
||||
base::File::FLAG_READ |
|
||||
base::File::FLAG_DELETE_ON_CLOSE |
|
||||
base::File::FLAG_TEMPORARY));
|
||||
if (!file->IsValid())
|
||||
if (!file->IsValid()) {
|
||||
PLOG(ERROR) << "Failed to create " << path.value();
|
||||
file.reset();
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
|
@ -228,6 +251,7 @@ ScopedTempFile CreateTempPdfFile(
|
|||
static_cast<int>(data->size()) !=
|
||||
pdf_file->WriteAtCurrentPos(data->front_as<char>(), data->size())) {
|
||||
pdf_file.reset();
|
||||
return pdf_file;
|
||||
}
|
||||
pdf_file->Seek(base::File::FROM_BEGIN, 0);
|
||||
return pdf_file;
|
||||
|
@ -281,17 +305,15 @@ PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() {
|
|||
|
||||
void PdfToEmfUtilityProcessHostClient::Start(
|
||||
const scoped_refptr<base::RefCountedMemory>& data,
|
||||
bool print_text_with_gdi,
|
||||
const PdfToEmfConverter::StartCallback& start_callback) {
|
||||
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
|
||||
BrowserThread::PostTask(BrowserThread::IO,
|
||||
FROM_HERE,
|
||||
base::Bind(&PdfToEmfUtilityProcessHostClient::Start,
|
||||
this,
|
||||
data,
|
||||
start_callback));
|
||||
BrowserThread::PostTask(
|
||||
BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&PdfToEmfUtilityProcessHostClient::Start, this, data,
|
||||
print_text_with_gdi, start_callback));
|
||||
return;
|
||||
}
|
||||
data_ = data;
|
||||
|
||||
// Store callback before any OnFailed() call to make it called on failure.
|
||||
start_callback_ = start_callback;
|
||||
|
@ -299,37 +321,28 @@ void PdfToEmfUtilityProcessHostClient::Start(
|
|||
// NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load
|
||||
// gdiplus.dll, change how rendering happens, and not be able to correctly
|
||||
// generate when sent to a metafile DC.
|
||||
utility_process_host_ =
|
||||
content::UtilityProcessHost::Create(
|
||||
this, base::MessageLoop::current()->task_runner())->AsWeakPtr();
|
||||
if (!utility_process_host_)
|
||||
return OnFailed();
|
||||
// Should reply with OnProcessStarted().
|
||||
Send(new ChromeUtilityMsg_StartupPing);
|
||||
}
|
||||
utility_process_host_ = content::UtilityProcessHost::Create(
|
||||
this, base::ThreadTaskRunnerHandle::Get())
|
||||
->AsWeakPtr();
|
||||
utility_process_host_->SetName(base::ASCIIToUTF16(
|
||||
"IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME"));
|
||||
|
||||
void PdfToEmfUtilityProcessHostClient::OnProcessStarted() {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
if (!utility_process_host_)
|
||||
return OnFailed();
|
||||
|
||||
scoped_refptr<base::RefCountedMemory> data = data_;
|
||||
data_ = NULL;
|
||||
BrowserThread::PostTaskAndReplyWithResult(
|
||||
BrowserThread::FILE,
|
||||
FROM_HERE,
|
||||
BrowserThread::FILE, FROM_HERE,
|
||||
base::Bind(&CreateTempPdfFile, data, &temp_dir_),
|
||||
base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this));
|
||||
base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this,
|
||||
print_text_with_gdi));
|
||||
}
|
||||
|
||||
void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(ScopedTempFile pdf) {
|
||||
void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(bool print_text_with_gdi,
|
||||
ScopedTempFile pdf) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
||||
if (!utility_process_host_ || !pdf)
|
||||
return OnFailed();
|
||||
// Should reply with OnPageCount().
|
||||
Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
|
||||
IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false),
|
||||
settings_));
|
||||
IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), settings_,
|
||||
print_text_with_gdi));
|
||||
}
|
||||
|
||||
void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) {
|
||||
|
@ -413,6 +426,38 @@ void PdfToEmfUtilityProcessHostClient::OnPageDone(bool success,
|
|||
get_page_callbacks_.pop();
|
||||
}
|
||||
|
||||
void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters(
|
||||
const LOGFONT& font,
|
||||
const base::string16& str) {
|
||||
// TODO(scottmg): pdf/ppapi still require the renderer to be able to precache
|
||||
// GDI fonts (http://crbug.com/383227), even when using DirectWrite.
|
||||
// Eventually this shouldn't be added and should be moved to
|
||||
// FontCacheDispatcher too. http://crbug.com/356346.
|
||||
|
||||
// First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
|
||||
// Except that for True Type fonts,
|
||||
// GetTextMetrics will not load the font in memory.
|
||||
// The only way windows seem to load properly, it is to create a similar
|
||||
// device (like the one in which we print), then do an ExtTextOut,
|
||||
// as we do in the printing thread, which is sandboxed.
|
||||
HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr);
|
||||
HFONT font_handle = CreateFontIndirect(&font);
|
||||
DCHECK(font_handle != nullptr);
|
||||
|
||||
HGDIOBJ old_font = SelectObject(hdc, font_handle);
|
||||
DCHECK(old_font != nullptr);
|
||||
|
||||
ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr);
|
||||
|
||||
SelectObject(hdc, old_font);
|
||||
DeleteObject(font_handle);
|
||||
|
||||
HENHMETAFILE metafile = CloseEnhMetaFile(hdc);
|
||||
|
||||
if (metafile)
|
||||
DeleteEnhMetaFile(metafile);
|
||||
}
|
||||
|
||||
void PdfToEmfUtilityProcessHostClient::Stop() {
|
||||
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
|
||||
BrowserThread::PostTask(
|
||||
|
@ -436,11 +481,12 @@ bool PdfToEmfUtilityProcessHostClient::OnMessageReceived(
|
|||
const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message)
|
||||
IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ProcessStarted, OnProcessStarted)
|
||||
IPC_MESSAGE_HANDLER(
|
||||
ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount)
|
||||
IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
|
||||
OnPageDone)
|
||||
IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PreCacheFontCharacters,
|
||||
OnPreCacheFontCharacters)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
IPC_END_MESSAGE_MAP()
|
||||
return handled;
|
||||
|
@ -473,11 +519,12 @@ PdfToEmfConverterImpl::~PdfToEmfConverterImpl() {
|
|||
void PdfToEmfConverterImpl::Start(
|
||||
const scoped_refptr<base::RefCountedMemory>& data,
|
||||
const PdfRenderSettings& conversion_settings,
|
||||
bool print_text_with_gdi,
|
||||
const StartCallback& start_callback) {
|
||||
DCHECK(!utility_client_.get());
|
||||
utility_client_ = new PdfToEmfUtilityProcessHostClient(
|
||||
weak_ptr_factory_.GetWeakPtr(), conversion_settings);
|
||||
utility_client_->Start(data, start_callback);
|
||||
utility_client_->Start(data, print_text_with_gdi, start_callback);
|
||||
}
|
||||
|
||||
void PdfToEmfConverterImpl::GetPage(int page_number,
|
||||
|
|
|
@ -10,21 +10,18 @@
|
|||
#include "base/callback.h"
|
||||
#include "base/memory/ref_counted_memory.h"
|
||||
|
||||
namespace base {
|
||||
class FilePath;
|
||||
}
|
||||
|
||||
namespace printing {
|
||||
|
||||
class MetafilePlayer;
|
||||
class PdfRenderSettings;
|
||||
struct PdfRenderSettings;
|
||||
|
||||
class PdfToEmfConverter {
|
||||
public:
|
||||
typedef base::Callback<void(int page_count)> StartCallback;
|
||||
typedef base::Callback<void(int page_number,
|
||||
float scale_factor,
|
||||
std::unique_ptr<MetafilePlayer> emf)> GetPageCallback;
|
||||
std::unique_ptr<MetafilePlayer> emf)>
|
||||
GetPageCallback;
|
||||
|
||||
virtual ~PdfToEmfConverter();
|
||||
|
||||
|
@ -34,6 +31,7 @@ class PdfToEmfConverter {
|
|||
// with positive |page_count|. |page_count| is 0 if initialization failed.
|
||||
virtual void Start(const scoped_refptr<base::RefCountedMemory>& data,
|
||||
const PdfRenderSettings& conversion_settings,
|
||||
bool print_text_with_gdi,
|
||||
const StartCallback& start_callback) = 0;
|
||||
|
||||
// Requests conversion of the page. |page_number| is 0-base page number in
|
||||
|
|
|
@ -160,13 +160,18 @@ void PrintViewManagerBase::OnDidPrintPage(
|
|||
ShouldQuitFromInnerMessageLoop();
|
||||
#else
|
||||
if (metafile_must_be_valid) {
|
||||
bool print_text_with_gdi =
|
||||
document->settings().print_text_with_gdi() &&
|
||||
!document->settings().printer_is_xps();
|
||||
|
||||
scoped_refptr<base::RefCountedBytes> bytes = new base::RefCountedBytes(
|
||||
reinterpret_cast<const unsigned char*>(shared_buf.memory()),
|
||||
params.data_size);
|
||||
|
||||
document->DebugDumpData(bytes.get(), FILE_PATH_LITERAL(".pdf"));
|
||||
print_job_->StartPdfToEmfConversion(
|
||||
bytes, params.page_size, params.content_area);
|
||||
bytes, params.page_size, params.content_area,
|
||||
print_text_with_gdi);
|
||||
}
|
||||
#endif // !OS_WIN
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue