printing_handler_win.cc 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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
  3. // found in the LICENSE file.
  4. #include "chrome/utility/printing_handler_win.h"
  5. #include "base/files/file_util.h"
  6. #include "base/lazy_instance.h"
  7. #include "base/path_service.h"
  8. #include "base/scoped_native_library.h"
  9. #include "chrome/common/chrome_utility_printing_messages.h"
  10. #include "chrome/common/print_messages.h"
  11. #include "content/public/utility/utility_thread.h"
  12. #include "pdf/pdf.h"
  13. #include "printing/emf_win.h"
  14. #include "printing/page_range.h"
  15. #include "printing/pdf_render_settings.h"
  16. #include "ui/gfx/gdi_util.h"
  17. namespace printing {
  18. namespace {
  19. bool Send(IPC::Message* message) {
  20. return content::UtilityThread::Get()->Send(message);
  21. }
  22. void ReleaseProcessIfNeeded() {
  23. content::UtilityThread::Get()->ReleaseProcess();
  24. }
  25. void PreCacheFontCharacters(const LOGFONT* logfont,
  26. const wchar_t* text,
  27. size_t text_length) {
  28. Send(new ChromeUtilityHostMsg_PreCacheFontCharacters(
  29. *logfont, base::string16(text, text_length)));
  30. }
  31. } // namespace
  32. PrintingHandlerWin::PrintingHandlerWin() {
  33. chrome_pdf::SetPDFEnsureTypefaceCharactersAccessible(PreCacheFontCharacters);
  34. }
  35. PrintingHandlerWin::~PrintingHandlerWin() {}
  36. bool PrintingHandlerWin::OnMessageReceived(const IPC::Message& message) {
  37. bool handled = true;
  38. IPC_BEGIN_MESSAGE_MAP(PrintingHandlerWin, message)
  39. IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles,
  40. OnRenderPDFPagesToMetafile)
  41. IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage,
  42. OnRenderPDFPagesToMetafileGetPage)
  43. IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop,
  44. OnRenderPDFPagesToMetafileStop)
  45. IPC_MESSAGE_UNHANDLED(handled = false)
  46. IPC_END_MESSAGE_MAP()
  47. return handled;
  48. }
  49. void PrintingHandlerWin::OnRenderPDFPagesToMetafile(
  50. IPC::PlatformFileForTransit pdf_transit,
  51. const PdfRenderSettings& settings) {
  52. pdf_rendering_settings_ = settings;
  53. chrome_pdf::SetPDFUseGDIPrinting(pdf_rendering_settings_.mode ==
  54. PdfRenderSettings::Mode::GDI_TEXT);
  55. int postscript_level;
  56. switch (pdf_rendering_settings_.mode) {
  57. case PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2:
  58. postscript_level = chrome_pdf::PrintingMode::kPostScript2;
  59. break;
  60. case PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3:
  61. postscript_level = chrome_pdf::PrintingMode::kPostScript3;
  62. break;
  63. default:
  64. postscript_level =
  65. chrome_pdf::PrintingMode::kEmf; // Not using postscript.
  66. }
  67. chrome_pdf::SetPDFUsePrintMode(postscript_level);
  68. base::File pdf_file = IPC::PlatformFileForTransitToFile(pdf_transit);
  69. int page_count = LoadPDF(std::move(pdf_file));
  70. Send(
  71. new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount(page_count));
  72. }
  73. void PrintingHandlerWin::OnRenderPDFPagesToMetafileGetPage(
  74. int page_number,
  75. IPC::PlatformFileForTransit output_file) {
  76. base::File emf_file = IPC::PlatformFileForTransitToFile(output_file);
  77. float scale_factor = 1.0f;
  78. bool postscript = pdf_rendering_settings_.mode ==
  79. PdfRenderSettings::Mode::POSTSCRIPT_LEVEL2 ||
  80. pdf_rendering_settings_.mode ==
  81. PdfRenderSettings::Mode::POSTSCRIPT_LEVEL3;
  82. bool success = RenderPdfPageToMetafile(page_number, std::move(emf_file),
  83. &scale_factor, postscript);
  84. Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone(
  85. success, scale_factor));
  86. }
  87. void PrintingHandlerWin::OnRenderPDFPagesToMetafileStop() {
  88. ReleaseProcessIfNeeded();
  89. }
  90. int PrintingHandlerWin::LoadPDF(base::File pdf_file) {
  91. int64_t length64 = pdf_file.GetLength();
  92. if (length64 <= 0 || length64 > std::numeric_limits<int>::max())
  93. return 0;
  94. int length = static_cast<int>(length64);
  95. pdf_data_.resize(length);
  96. if (length != pdf_file.Read(0, pdf_data_.data(), pdf_data_.size()))
  97. return 0;
  98. int total_page_count = 0;
  99. if (!chrome_pdf::GetPDFDocInfo(&pdf_data_.front(), pdf_data_.size(),
  100. &total_page_count, nullptr)) {
  101. return 0;
  102. }
  103. return total_page_count;
  104. }
  105. bool PrintingHandlerWin::RenderPdfPageToMetafile(int page_number,
  106. base::File output_file,
  107. float* scale_factor,
  108. bool postscript) {
  109. Emf metafile;
  110. metafile.Init();
  111. // We need to scale down DC to fit an entire page into DC available area.
  112. // Current metafile is based on screen DC and have current screen size.
  113. // Writing outside of those boundaries will result in the cut-off output.
  114. // On metafiles (this is the case here), scaling down will still record
  115. // original coordinates and we'll be able to print in full resolution.
  116. // Before playback we'll need to counter the scaling up that will happen
  117. // in the service (print_system_win.cc).
  118. //
  119. // The postscript driver does not use the metafile size since it outputs
  120. // postscript rather than a metafile. Instead it uses the printable area
  121. // sent to RenderPDFPageToDC to determine the area to render. Therefore,
  122. // don't scale the DC to match the metafile, and send the printer physical
  123. // offsets to the driver.
  124. if (!postscript) {
  125. *scale_factor = gfx::CalculatePageScale(
  126. metafile.context(), pdf_rendering_settings_.area.right(),
  127. pdf_rendering_settings_.area.bottom());
  128. gfx::ScaleDC(metafile.context(), *scale_factor);
  129. }
  130. // The underlying metafile is of type Emf and ignores the arguments passed
  131. // to StartPage.
  132. metafile.StartPage(gfx::Size(), gfx::Rect(), 1);
  133. int offset_x = postscript ? pdf_rendering_settings_.offsets.x() : 0;
  134. int offset_y = postscript ? pdf_rendering_settings_.offsets.y() : 0;
  135. if (!chrome_pdf::RenderPDFPageToDC(
  136. &pdf_data_.front(), pdf_data_.size(), page_number, metafile.context(),
  137. pdf_rendering_settings_.dpi,
  138. pdf_rendering_settings_.area.x() - offset_x,
  139. pdf_rendering_settings_.area.y() - offset_y,
  140. pdf_rendering_settings_.area.width(),
  141. pdf_rendering_settings_.area.height(), true, false, true, true,
  142. pdf_rendering_settings_.autorotate)) {
  143. return false;
  144. }
  145. metafile.FinishPage();
  146. metafile.FinishDocument();
  147. return metafile.SaveTo(&output_file);
  148. }
  149. } // namespace printing