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.
5 #include "chrome/utility/printing_handler.h"
7 #include "base/files/file_util.h"
8 #include "base/lazy_instance.h"
9 #include "base/path_service.h"
10 #include "base/scoped_native_library.h"
11 #include "chrome/common/chrome_paths.h"
12 #include "chrome/common/chrome_utility_printing_messages.h"
13 #include "chrome/utility/cloud_print/bitmap_image.h"
14 #include "chrome/utility/cloud_print/pwg_encoder.h"
15 #include "content/public/utility/utility_thread.h"
17 #include "printing/page_range.h"
18 #include "printing/pdf_render_settings.h"
21 #include "printing/emf_win.h"
22 #include "ui/gfx/gdi_util.h"
25 #if defined(ENABLE_PRINT_PREVIEW)
26 #include "chrome/common/crash_keys.h"
27 #include "printing/backend/print_backend.h"
32 bool Send(IPC::Message
* message
) {
33 return content::UtilityThread::Get()->Send(message
);
36 void ReleaseProcessIfNeeded() {
37 content::UtilityThread::Get()->ReleaseProcessIfNeeded();
42 PrintingHandler::PrintingHandler() {}
44 PrintingHandler::~PrintingHandler() {}
46 bool PrintingHandler::OnMessageReceived(const IPC::Message
& message
) {
48 IPC_BEGIN_MESSAGE_MAP(PrintingHandler
, message
)
50 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles
,
51 OnRenderPDFPagesToMetafile
)
52 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_GetPage
,
53 OnRenderPDFPagesToMetafileGetPage
)
54 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToMetafiles_Stop
,
55 OnRenderPDFPagesToMetafileStop
)
57 #if defined(ENABLE_PRINT_PREVIEW)
58 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_RenderPDFPagesToPWGRaster
,
59 OnRenderPDFPagesToPWGRaster
)
60 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterCapsAndDefaults
,
61 OnGetPrinterCapsAndDefaults
)
62 IPC_MESSAGE_HANDLER(ChromeUtilityMsg_GetPrinterSemanticCapsAndDefaults
,
63 OnGetPrinterSemanticCapsAndDefaults
)
64 #endif // ENABLE_PRINT_PREVIEW
65 IPC_MESSAGE_UNHANDLED(handled
= false)
71 void PrintingHandler::OnRenderPDFPagesToMetafile(
72 IPC::PlatformFileForTransit pdf_transit
,
73 const printing::PdfRenderSettings
& settings
) {
74 pdf_rendering_settings_
= settings
;
75 base::File pdf_file
= IPC::PlatformFileForTransitToFile(pdf_transit
);
76 int page_count
= LoadPDF(pdf_file
.Pass());
78 new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageCount(page_count
));
81 void PrintingHandler::OnRenderPDFPagesToMetafileGetPage(
83 IPC::PlatformFileForTransit output_file
) {
84 base::File emf_file
= IPC::PlatformFileForTransitToFile(output_file
);
85 float scale_factor
= 1.0f
;
87 RenderPdfPageToMetafile(page_number
, emf_file
.Pass(), &scale_factor
);
88 Send(new ChromeUtilityHostMsg_RenderPDFPagesToMetafiles_PageDone(
89 success
, scale_factor
));
92 void PrintingHandler::OnRenderPDFPagesToMetafileStop() {
93 ReleaseProcessIfNeeded();
98 #if defined(ENABLE_PRINT_PREVIEW)
99 void PrintingHandler::OnRenderPDFPagesToPWGRaster(
100 IPC::PlatformFileForTransit pdf_transit
,
101 const printing::PdfRenderSettings
& settings
,
102 const printing::PwgRasterSettings
& bitmap_settings
,
103 IPC::PlatformFileForTransit bitmap_transit
) {
104 base::File pdf
= IPC::PlatformFileForTransitToFile(pdf_transit
);
105 base::File bitmap
= IPC::PlatformFileForTransitToFile(bitmap_transit
);
106 if (RenderPDFPagesToPWGRaster(pdf
.Pass(), settings
, bitmap_settings
,
108 Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Succeeded());
110 Send(new ChromeUtilityHostMsg_RenderPDFPagesToPWGRaster_Failed());
112 ReleaseProcessIfNeeded();
114 #endif // ENABLE_PRINT_PREVIEW
117 int PrintingHandler::LoadPDF(base::File pdf_file
) {
118 int64 length64
= pdf_file
.GetLength();
119 if (length64
<= 0 || length64
> std::numeric_limits
<int>::max())
121 int length
= static_cast<int>(length64
);
123 pdf_data_
.resize(length
);
124 if (length
!= pdf_file
.Read(0, pdf_data_
.data(), pdf_data_
.size()))
127 int total_page_count
= 0;
128 if (!chrome_pdf::GetPDFDocInfo(
129 &pdf_data_
.front(), pdf_data_
.size(), &total_page_count
, NULL
)) {
132 return total_page_count
;
135 bool PrintingHandler::RenderPdfPageToMetafile(int page_number
,
136 base::File output_file
,
137 float* scale_factor
) {
138 printing::Emf metafile
;
141 // We need to scale down DC to fit an entire page into DC available area.
142 // Current metafile is based on screen DC and have current screen size.
143 // Writing outside of those boundaries will result in the cut-off output.
144 // On metafiles (this is the case here), scaling down will still record
145 // original coordinates and we'll be able to print in full resolution.
146 // Before playback we'll need to counter the scaling up that will happen
147 // in the service (print_system_win.cc).
149 gfx::CalculatePageScale(metafile
.context(),
150 pdf_rendering_settings_
.area().right(),
151 pdf_rendering_settings_
.area().bottom());
152 gfx::ScaleDC(metafile
.context(), *scale_factor
);
154 // The underlying metafile is of type Emf and ignores the arguments passed
156 metafile
.StartPage(gfx::Size(), gfx::Rect(), 1);
157 if (!chrome_pdf::RenderPDFPageToDC(
162 pdf_rendering_settings_
.dpi(),
163 pdf_rendering_settings_
.area().x(),
164 pdf_rendering_settings_
.area().y(),
165 pdf_rendering_settings_
.area().width(),
166 pdf_rendering_settings_
.area().height(),
171 pdf_rendering_settings_
.autorotate())) {
174 metafile
.FinishPage();
175 metafile
.FinishDocument();
176 return metafile
.SaveTo(&output_file
);
181 #if defined(ENABLE_PRINT_PREVIEW)
182 bool PrintingHandler::RenderPDFPagesToPWGRaster(
184 const printing::PdfRenderSettings
& settings
,
185 const printing::PwgRasterSettings
& bitmap_settings
,
186 base::File bitmap_file
) {
187 bool autoupdate
= true;
188 base::File::Info info
;
189 if (!pdf_file
.GetInfo(&info
) || info
.size
<= 0 ||
190 info
.size
> std::numeric_limits
<int>::max())
192 int data_size
= static_cast<int>(info
.size
);
194 std::string
data(data_size
, 0);
195 if (pdf_file
.Read(0, &data
[0], data_size
) != data_size
)
198 int total_page_count
= 0;
199 if (!chrome_pdf::GetPDFDocInfo(data
.data(), data_size
,
200 &total_page_count
, NULL
)) {
204 cloud_print::PwgEncoder encoder
;
205 std::string pwg_header
;
206 encoder
.EncodeDocumentHeader(&pwg_header
);
207 int bytes_written
= bitmap_file
.WriteAtCurrentPos(pwg_header
.data(),
209 if (bytes_written
!= static_cast<int>(pwg_header
.size()))
212 cloud_print::BitmapImage
image(settings
.area().size(),
213 cloud_print::BitmapImage::BGRA
);
214 for (int i
= 0; i
< total_page_count
; ++i
) {
217 if (bitmap_settings
.reverse_page_order
) {
218 page_number
= total_page_count
- 1 - page_number
;
221 if (!chrome_pdf::RenderPDFPageToBitmap(data
.data(),
225 image
.size().width(),
226 image
.size().height(),
232 cloud_print::PwgHeaderInfo header_info
;
233 header_info
.dpi
= settings
.dpi();
234 header_info
.total_pages
= total_page_count
;
236 // Transform odd pages.
237 if (page_number
% 2) {
238 switch (bitmap_settings
.odd_page_transform
) {
239 case printing::TRANSFORM_NORMAL
:
241 case printing::TRANSFORM_ROTATE_180
:
242 header_info
.flipx
= true;
243 header_info
.flipy
= true;
245 case printing::TRANSFORM_FLIP_HORIZONTAL
:
246 header_info
.flipx
= true;
248 case printing::TRANSFORM_FLIP_VERTICAL
:
249 header_info
.flipy
= true;
254 if (bitmap_settings
.rotate_all_pages
) {
255 header_info
.flipx
= !header_info
.flipx
;
256 header_info
.flipy
= !header_info
.flipy
;
259 std::string pwg_page
;
260 if (!encoder
.EncodePage(image
, header_info
, &pwg_page
))
262 bytes_written
= bitmap_file
.WriteAtCurrentPos(pwg_page
.data(),
264 if (bytes_written
!= static_cast<int>(pwg_page
.size()))
270 void PrintingHandler::OnGetPrinterCapsAndDefaults(
271 const std::string
& printer_name
) {
272 scoped_refptr
<printing::PrintBackend
> print_backend
=
273 printing::PrintBackend::CreateInstance(NULL
);
274 printing::PrinterCapsAndDefaults printer_info
;
276 crash_keys::ScopedPrinterInfo
crash_key(
277 print_backend
->GetPrinterDriverInfo(printer_name
));
279 if (print_backend
->GetPrinterCapsAndDefaults(printer_name
, &printer_info
)) {
280 Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Succeeded(
281 printer_name
, printer_info
));
283 Send(new ChromeUtilityHostMsg_GetPrinterCapsAndDefaults_Failed(
286 ReleaseProcessIfNeeded();
289 void PrintingHandler::OnGetPrinterSemanticCapsAndDefaults(
290 const std::string
& printer_name
) {
291 scoped_refptr
<printing::PrintBackend
> print_backend
=
292 printing::PrintBackend::CreateInstance(NULL
);
293 printing::PrinterSemanticCapsAndDefaults printer_info
;
295 crash_keys::ScopedPrinterInfo
crash_key(
296 print_backend
->GetPrinterDriverInfo(printer_name
));
298 if (print_backend
->GetPrinterSemanticCapsAndDefaults(printer_name
,
300 Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Succeeded(
301 printer_name
, printer_info
));
303 Send(new ChromeUtilityHostMsg_GetPrinterSemanticCapsAndDefaults_Failed(
306 ReleaseProcessIfNeeded();
308 #endif // ENABLE_PRINT_PREVIEW