Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(330)

Side by Side Diff: chrome/browser/printing/pdf_to_emf_converter.cc

Issue 2114583002: Windows: Make it possible to print text with GDI. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/printing/pdf_to_emf_converter.h" 5 #include "chrome/browser/printing/pdf_to_emf_converter.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <windows.h>
8 9
9 #include <memory> 10 #include <memory>
10 #include <queue> 11 #include <queue>
11 #include <utility> 12 #include <utility>
12 13
13 #include "base/files/file.h" 14 #include "base/files/file.h"
14 #include "base/files/file_util.h" 15 #include "base/files/file_util.h"
15 #include "base/files/scoped_temp_dir.h" 16 #include "base/files/scoped_temp_dir.h"
16 #include "base/logging.h" 17 #include "base/logging.h"
17 #include "base/macros.h" 18 #include "base/macros.h"
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
98 // All these steps work sequentially, so no data should be accessed 99 // All these steps work sequentially, so no data should be accessed
99 // simultaneously by several threads. 100 // simultaneously by several threads.
100 class PdfToEmfUtilityProcessHostClient 101 class PdfToEmfUtilityProcessHostClient
101 : public content::UtilityProcessHostClient { 102 : public content::UtilityProcessHostClient {
102 public: 103 public:
103 PdfToEmfUtilityProcessHostClient( 104 PdfToEmfUtilityProcessHostClient(
104 base::WeakPtr<PdfToEmfConverterImpl> converter, 105 base::WeakPtr<PdfToEmfConverterImpl> converter,
105 const PdfRenderSettings& settings); 106 const PdfRenderSettings& settings);
106 107
107 void Start(const scoped_refptr<base::RefCountedMemory>& data, 108 void Start(const scoped_refptr<base::RefCountedMemory>& data,
109 bool print_text_with_gdi,
108 const PdfToEmfConverter::StartCallback& start_callback); 110 const PdfToEmfConverter::StartCallback& start_callback);
109 111
110 void GetPage(int page_number, 112 void GetPage(int page_number,
111 const PdfToEmfConverter::GetPageCallback& get_page_callback); 113 const PdfToEmfConverter::GetPageCallback& get_page_callback);
112 114
113 void Stop(); 115 void Stop();
114 116
117 // Needs to be public to handle ChromeUtilityHostMsg_PreCacheFontCharacters
118 // sync message replies.
119 bool Send(IPC::Message* msg);
120
115 // UtilityProcessHostClient implementation. 121 // UtilityProcessHostClient implementation.
116 void OnProcessCrashed(int exit_code) override; 122 void OnProcessCrashed(int exit_code) override;
117 void OnProcessLaunchFailed(int exit_code) override; 123 void OnProcessLaunchFailed(int exit_code) override;
118 bool OnMessageReceived(const IPC::Message& message) override; 124 bool OnMessageReceived(const IPC::Message& message) override;
119 125
120 private: 126 private:
121 class GetPageCallbackData { 127 class GetPageCallbackData {
122 public: 128 public:
123 GetPageCallbackData(int page_number, 129 GetPageCallbackData(int page_number,
124 PdfToEmfConverter::GetPageCallback callback) 130 PdfToEmfConverter::GetPageCallback callback)
(...skipping 20 matching lines...) Expand all
145 private: 151 private:
146 int page_number_; 152 int page_number_;
147 PdfToEmfConverter::GetPageCallback callback_; 153 PdfToEmfConverter::GetPageCallback callback_;
148 ScopedTempFile emf_; 154 ScopedTempFile emf_;
149 155
150 DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData); 156 DISALLOW_COPY_AND_ASSIGN(GetPageCallbackData);
151 }; 157 };
152 158
153 ~PdfToEmfUtilityProcessHostClient() override; 159 ~PdfToEmfUtilityProcessHostClient() override;
154 160
155 bool Send(IPC::Message* msg);
156
157 // Message handlers. 161 // Message handlers.
158 void OnPageCount(int page_count); 162 void OnPageCount(int page_count);
159 void OnPageDone(bool success, float scale_factor); 163 void OnPageDone(bool success, float scale_factor);
164 void OnPreCacheFontCharacters(const LOGFONT& log_font,
165 const base::string16& characters);
160 166
161 void OnFailed(); 167 void OnFailed();
162 void OnTempPdfReady(ScopedTempFile pdf); 168 void OnTempPdfReady(bool print_text_with_gdi, ScopedTempFile pdf);
163 void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf); 169 void OnTempEmfReady(GetPageCallbackData* callback_data, ScopedTempFile emf);
164 170
165 scoped_refptr<RefCountedTempDir> temp_dir_; 171 scoped_refptr<RefCountedTempDir> temp_dir_;
166 172
167 // Used to suppress callbacks after PdfToEmfConverterImpl is deleted. 173 // Used to suppress callbacks after PdfToEmfConverterImpl is deleted.
168 base::WeakPtr<PdfToEmfConverterImpl> converter_; 174 base::WeakPtr<PdfToEmfConverterImpl> converter_;
169 PdfRenderSettings settings_; 175 PdfRenderSettings settings_;
170 176
171 // Document loaded callback. 177 // Document loaded callback.
172 PdfToEmfConverter::StartCallback start_callback_; 178 PdfToEmfConverter::StartCallback start_callback_;
(...skipping 11 matching lines...) Expand all
184 }; 190 };
185 191
186 class PdfToEmfConverterImpl : public PdfToEmfConverter { 192 class PdfToEmfConverterImpl : public PdfToEmfConverter {
187 public: 193 public:
188 PdfToEmfConverterImpl(); 194 PdfToEmfConverterImpl();
189 195
190 ~PdfToEmfConverterImpl() override; 196 ~PdfToEmfConverterImpl() override;
191 197
192 void Start(const scoped_refptr<base::RefCountedMemory>& data, 198 void Start(const scoped_refptr<base::RefCountedMemory>& data,
193 const PdfRenderSettings& conversion_settings, 199 const PdfRenderSettings& conversion_settings,
200 bool print_text_with_gdi,
194 const StartCallback& start_callback) override; 201 const StartCallback& start_callback) override;
195 202
196 void GetPage(int page_number, 203 void GetPage(int page_number,
197 const GetPageCallback& get_page_callback) override; 204 const GetPageCallback& get_page_callback) override;
198 205
199 // Helps to cancel callbacks if this object is destroyed. 206 // Helps to cancel callbacks if this object is destroyed.
200 void RunCallback(const base::Closure& callback); 207 void RunCallback(const base::Closure& callback);
201 208
202 private: 209 private:
203 scoped_refptr<PdfToEmfUtilityProcessHostClient> utility_client_; 210 scoped_refptr<PdfToEmfUtilityProcessHostClient> utility_client_;
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 base::WeakPtr<PdfToEmfConverterImpl> converter, 290 base::WeakPtr<PdfToEmfConverterImpl> converter,
284 const PdfRenderSettings& settings) 291 const PdfRenderSettings& settings)
285 : converter_(converter), settings_(settings) { 292 : converter_(converter), settings_(settings) {
286 } 293 }
287 294
288 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() { 295 PdfToEmfUtilityProcessHostClient::~PdfToEmfUtilityProcessHostClient() {
289 } 296 }
290 297
291 void PdfToEmfUtilityProcessHostClient::Start( 298 void PdfToEmfUtilityProcessHostClient::Start(
292 const scoped_refptr<base::RefCountedMemory>& data, 299 const scoped_refptr<base::RefCountedMemory>& data,
300 bool print_text_with_gdi,
293 const PdfToEmfConverter::StartCallback& start_callback) { 301 const PdfToEmfConverter::StartCallback& start_callback) {
294 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 302 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
295 BrowserThread::PostTask(BrowserThread::IO, 303 BrowserThread::PostTask(
296 FROM_HERE, 304 BrowserThread::IO, FROM_HERE,
297 base::Bind(&PdfToEmfUtilityProcessHostClient::Start, 305 base::Bind(&PdfToEmfUtilityProcessHostClient::Start, this, data,
298 this, 306 print_text_with_gdi, start_callback));
299 data,
300 start_callback));
301 return; 307 return;
302 } 308 }
303 309
304 // Store callback before any OnFailed() call to make it called on failure. 310 // Store callback before any OnFailed() call to make it called on failure.
305 start_callback_ = start_callback; 311 start_callback_ = start_callback;
306 312
307 // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load 313 // NOTE: This process _must_ be sandboxed, otherwise the pdf dll will load
308 // gdiplus.dll, change how rendering happens, and not be able to correctly 314 // gdiplus.dll, change how rendering happens, and not be able to correctly
309 // generate when sent to a metafile DC. 315 // generate when sent to a metafile DC.
310 utility_process_host_ = content::UtilityProcessHost::Create( 316 utility_process_host_ = content::UtilityProcessHost::Create(
311 this, base::ThreadTaskRunnerHandle::Get()) 317 this, base::ThreadTaskRunnerHandle::Get())
312 ->AsWeakPtr(); 318 ->AsWeakPtr();
313 utility_process_host_->SetName(l10n_util::GetStringUTF16( 319 utility_process_host_->SetName(l10n_util::GetStringUTF16(
314 IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME)); 320 IDS_UTILITY_PROCESS_EMF_CONVERTOR_NAME));
315 321
316 BrowserThread::PostTaskAndReplyWithResult( 322 BrowserThread::PostTaskAndReplyWithResult(
317 BrowserThread::FILE, 323 BrowserThread::FILE, FROM_HERE,
318 FROM_HERE,
319 base::Bind(&CreateTempPdfFile, data, &temp_dir_), 324 base::Bind(&CreateTempPdfFile, data, &temp_dir_),
320 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this)); 325 base::Bind(&PdfToEmfUtilityProcessHostClient::OnTempPdfReady, this,
326 print_text_with_gdi));
321 } 327 }
322 328
323 void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(ScopedTempFile pdf) { 329 void PdfToEmfUtilityProcessHostClient::OnTempPdfReady(bool print_text_with_gdi,
330 ScopedTempFile pdf) {
324 DCHECK_CURRENTLY_ON(BrowserThread::IO); 331 DCHECK_CURRENTLY_ON(BrowserThread::IO);
325 if (!utility_process_host_ || !pdf) 332 if (!utility_process_host_ || !pdf)
326 return OnFailed(); 333 return OnFailed();
327 // Should reply with OnPageCount(). 334 // Should reply with OnPageCount().
328 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles( 335 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles(
329 IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), 336 IPC::GetPlatformFileForTransit(pdf->GetPlatformFile(), false), settings_,
330 settings_)); 337 print_text_with_gdi));
331 } 338 }
332 339
333 void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) { 340 void PdfToEmfUtilityProcessHostClient::OnPageCount(int page_count) {
334 DCHECK_CURRENTLY_ON(BrowserThread::IO); 341 DCHECK_CURRENTLY_ON(BrowserThread::IO);
335 if (start_callback_.is_null()) 342 if (start_callback_.is_null())
336 return OnFailed(); 343 return OnFailed();
337 BrowserThread::PostTask(BrowserThread::UI, 344 BrowserThread::PostTask(BrowserThread::UI,
338 FROM_HERE, 345 FROM_HERE,
339 base::Bind(&PdfToEmfConverterImpl::RunCallback, 346 base::Bind(&PdfToEmfConverterImpl::RunCallback,
340 converter_, 347 converter_,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
404 FROM_HERE, 411 FROM_HERE,
405 base::Bind(&PdfToEmfConverterImpl::RunCallback, 412 base::Bind(&PdfToEmfConverterImpl::RunCallback,
406 converter_, 413 converter_,
407 base::Bind(data.callback(), 414 base::Bind(data.callback(),
408 data.page_number(), 415 data.page_number(),
409 scale_factor, 416 scale_factor,
410 base::Passed(&emf)))); 417 base::Passed(&emf))));
411 get_page_callbacks_.pop(); 418 get_page_callbacks_.pop();
412 } 419 }
413 420
421 void PdfToEmfUtilityProcessHostClient::OnPreCacheFontCharacters(
422 const LOGFONT& font,
423 const base::string16& str) {
424 // TODO(scottmg): pdf/ppapi still require the renderer to be able to precache
425 // GDI fonts (http://crbug.com/383227), even when using DirectWrite.
426 // Eventually this shouldn't be added and should be moved to
427 // FontCacheDispatcher too. http://crbug.com/356346.
428
429 // First, comments from FontCacheDispatcher::OnPreCacheFont do apply here too.
430 // Except that for True Type fonts,
431 // GetTextMetrics will not load the font in memory.
432 // The only way windows seem to load properly, it is to create a similar
433 // device (like the one in which we print), then do an ExtTextOut,
434 // as we do in the printing thread, which is sandboxed.
435 HDC hdc = CreateEnhMetaFile(nullptr, nullptr, nullptr, nullptr);
436 HFONT font_handle = CreateFontIndirect(&font);
437 DCHECK(font_handle != nullptr);
438
439 HGDIOBJ old_font = SelectObject(hdc, font_handle);
440 DCHECK(old_font != nullptr);
441
442 ExtTextOut(hdc, 0, 0, ETO_GLYPH_INDEX, 0, str.c_str(), str.length(), nullptr);
443
444 SelectObject(hdc, old_font);
445 DeleteObject(font_handle);
446
447 HENHMETAFILE metafile = CloseEnhMetaFile(hdc);
448
449 if (metafile)
450 DeleteEnhMetaFile(metafile);
451 }
452
414 void PdfToEmfUtilityProcessHostClient::Stop() { 453 void PdfToEmfUtilityProcessHostClient::Stop() {
415 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { 454 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
416 BrowserThread::PostTask( 455 BrowserThread::PostTask(
417 BrowserThread::IO, 456 BrowserThread::IO,
418 FROM_HERE, 457 FROM_HERE,
419 base::Bind(&PdfToEmfUtilityProcessHostClient::Stop, this)); 458 base::Bind(&PdfToEmfUtilityProcessHostClient::Stop, this));
420 return; 459 return;
421 } 460 }
422 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop()); 461 Send(new ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop());
423 } 462 }
424 463
425 void PdfToEmfUtilityProcessHostClient::OnProcessCrashed(int exit_code) { 464 void PdfToEmfUtilityProcessHostClient::OnProcessCrashed(int exit_code) {
426 OnFailed(); 465 OnFailed();
427 } 466 }
428 467
429 void PdfToEmfUtilityProcessHostClient::OnProcessLaunchFailed(int exit_code) { 468 void PdfToEmfUtilityProcessHostClient::OnProcessLaunchFailed(int exit_code) {
430 OnFailed(); 469 OnFailed();
431 } 470 }
432 471
433 bool PdfToEmfUtilityProcessHostClient::OnMessageReceived( 472 bool PdfToEmfUtilityProcessHostClient::OnMessageReceived(
434 const IPC::Message& message) { 473 const IPC::Message& message) {
435 bool handled = true; 474 bool handled = true;
436 IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message) 475 IPC_BEGIN_MESSAGE_MAP(PdfToEmfUtilityProcessHostClient, message)
437 IPC_MESSAGE_HANDLER( 476 IPC_MESSAGE_HANDLER(
438 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount) 477 ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount, OnPageCount)
439 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone, 478 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone,
440 OnPageDone) 479 OnPageDone)
480 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_PreCacheFontCharacters,
481 OnPreCacheFontCharacters)
441 IPC_MESSAGE_UNHANDLED(handled = false) 482 IPC_MESSAGE_UNHANDLED(handled = false)
442 IPC_END_MESSAGE_MAP() 483 IPC_END_MESSAGE_MAP()
443 return handled; 484 return handled;
444 } 485 }
445 486
446 bool PdfToEmfUtilityProcessHostClient::Send(IPC::Message* msg) { 487 bool PdfToEmfUtilityProcessHostClient::Send(IPC::Message* msg) {
447 if (utility_process_host_) 488 if (utility_process_host_)
448 return utility_process_host_->Send(msg); 489 return utility_process_host_->Send(msg);
449 delete msg; 490 delete msg;
450 return false; 491 return false;
(...skipping 12 matching lines...) Expand all
463 } 504 }
464 505
465 PdfToEmfConverterImpl::~PdfToEmfConverterImpl() { 506 PdfToEmfConverterImpl::~PdfToEmfConverterImpl() {
466 if (utility_client_.get()) 507 if (utility_client_.get())
467 utility_client_->Stop(); 508 utility_client_->Stop();
468 } 509 }
469 510
470 void PdfToEmfConverterImpl::Start( 511 void PdfToEmfConverterImpl::Start(
471 const scoped_refptr<base::RefCountedMemory>& data, 512 const scoped_refptr<base::RefCountedMemory>& data,
472 const PdfRenderSettings& conversion_settings, 513 const PdfRenderSettings& conversion_settings,
514 bool print_text_with_gdi,
473 const StartCallback& start_callback) { 515 const StartCallback& start_callback) {
474 DCHECK(!utility_client_.get()); 516 DCHECK(!utility_client_.get());
475 utility_client_ = new PdfToEmfUtilityProcessHostClient( 517 utility_client_ = new PdfToEmfUtilityProcessHostClient(
476 weak_ptr_factory_.GetWeakPtr(), conversion_settings); 518 weak_ptr_factory_.GetWeakPtr(), conversion_settings);
477 utility_client_->Start(data, start_callback); 519 utility_client_->Start(data, print_text_with_gdi, start_callback);
478 } 520 }
479 521
480 void PdfToEmfConverterImpl::GetPage(int page_number, 522 void PdfToEmfConverterImpl::GetPage(int page_number,
481 const GetPageCallback& get_page_callback) { 523 const GetPageCallback& get_page_callback) {
482 utility_client_->GetPage(page_number, get_page_callback); 524 utility_client_->GetPage(page_number, get_page_callback);
483 } 525 }
484 526
485 void PdfToEmfConverterImpl::RunCallback(const base::Closure& callback) { 527 void PdfToEmfConverterImpl::RunCallback(const base::Closure& callback) {
486 DCHECK_CURRENTLY_ON(BrowserThread::UI); 528 DCHECK_CURRENTLY_ON(BrowserThread::UI);
487 callback.Run(); 529 callback.Run();
488 } 530 }
489 531
490 } // namespace 532 } // namespace
491 533
492 PdfToEmfConverter::~PdfToEmfConverter() { 534 PdfToEmfConverter::~PdfToEmfConverter() {
493 } 535 }
494 536
495 // static 537 // static
496 std::unique_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() { 538 std::unique_ptr<PdfToEmfConverter> PdfToEmfConverter::CreateDefault() {
497 return std::unique_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl()); 539 return std::unique_ptr<PdfToEmfConverter>(new PdfToEmfConverterImpl());
498 } 540 }
499 541
500 } // namespace printing 542 } // namespace printing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698