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 "components/printing/renderer/print_web_view_helper.h"
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/process/process_handle.h"
10 #include "components/printing/common/print_messages.h"
11 #include "content/public/renderer/render_thread.h"
12 #include "printing/metafile_skia_wrapper.h"
13 #include "printing/page_size_margins.h"
14 #include "printing/pdf_metafile_skia.h"
15 #include "printing/units.h"
16 #include "skia/ext/platform_device.h"
17 #include "third_party/WebKit/public/web/WebLocalFrame.h"
21 using blink::WebFrame
;
23 bool PrintWebViewHelper::RenderPreviewPage(
25 const PrintMsg_Print_Params
& print_params
) {
26 PrintMsg_PrintPage_Params page_params
;
27 page_params
.params
= print_params
;
28 page_params
.page_number
= page_number
;
29 scoped_ptr
<PdfMetafileSkia
> draft_metafile
;
30 PdfMetafileSkia
* initial_render_metafile
= print_preview_context_
.metafile();
31 if (print_preview_context_
.IsModifiable() && is_print_ready_metafile_sent_
) {
32 draft_metafile
.reset(new PdfMetafileSkia
);
33 initial_render_metafile
= draft_metafile
.get();
36 base::TimeTicks begin_time
= base::TimeTicks::Now();
37 PrintPageInternal(page_params
,
38 print_preview_context_
.prepared_frame(),
39 initial_render_metafile
,
42 print_preview_context_
.RenderedPreviewPage(
43 base::TimeTicks::Now() - begin_time
);
44 if (draft_metafile
.get()) {
45 draft_metafile
->FinishDocument();
46 } else if (print_preview_context_
.IsModifiable() &&
47 print_preview_context_
.generate_draft_pages()) {
48 DCHECK(!draft_metafile
.get());
50 print_preview_context_
.metafile()->GetMetafileForCurrentPage();
52 return PreviewPageRendered(page_number
, draft_metafile
.get());
55 bool PrintWebViewHelper::PrintPagesNative(blink::WebFrame
* frame
,
57 PdfMetafileSkia metafile
;
61 const PrintMsg_PrintPages_Params
& params
= *print_pages_params_
;
62 std::vector
<int> printed_pages
;
63 if (params
.pages
.empty()) {
64 for (int i
= 0; i
< page_count
; ++i
) {
65 printed_pages
.push_back(i
);
68 // TODO(vitalybuka): redesign to make more code cross platform.
69 for (size_t i
= 0; i
< params
.pages
.size(); ++i
) {
70 if (params
.pages
[i
] >= 0 && params
.pages
[i
] < page_count
) {
71 printed_pages
.push_back(params
.pages
[i
]);
75 if (printed_pages
.empty())
78 std::vector
<gfx::Size
> page_size_in_dpi(printed_pages
.size());
79 std::vector
<gfx::Rect
> content_area_in_dpi(printed_pages
.size());
81 PrintMsg_PrintPage_Params page_params
;
82 page_params
.params
= params
.params
;
83 for (size_t i
= 0; i
< printed_pages
.size(); ++i
) {
84 page_params
.page_number
= printed_pages
[i
];
85 PrintPageInternal(page_params
,
89 &content_area_in_dpi
[i
]);
92 // blink::printEnd() for PDF should be called before metafile is closed.
93 FinishFramePrinting();
95 metafile
.FinishDocument();
97 PrintHostMsg_DidPrintPage_Params printed_page_params
;
98 if (!CopyMetafileDataToSharedMem(
99 metafile
, &printed_page_params
.metafile_data_handle
)) {
103 printed_page_params
.content_area
= params
.params
.printable_area
;
104 printed_page_params
.data_size
= metafile
.GetDataSize();
105 printed_page_params
.document_cookie
= params
.params
.document_cookie
;
106 printed_page_params
.page_size
= params
.params
.page_size
;
108 for (size_t i
= 0; i
< printed_pages
.size(); ++i
) {
109 printed_page_params
.page_number
= printed_pages
[i
];
110 printed_page_params
.page_size
= page_size_in_dpi
[i
];
111 printed_page_params
.content_area
= content_area_in_dpi
[i
];
112 Send(new PrintHostMsg_DidPrintPage(routing_id(), printed_page_params
));
113 printed_page_params
.metafile_data_handle
= INVALID_HANDLE_VALUE
;
118 void PrintWebViewHelper::PrintPageInternal(
119 const PrintMsg_PrintPage_Params
& params
,
121 PdfMetafileSkia
* metafile
,
122 gfx::Size
* page_size_in_dpi
,
123 gfx::Rect
* content_area_in_dpi
) {
124 PageSizeMargins page_layout_in_points
;
125 double css_scale_factor
= 1.0f
;
126 ComputePageLayoutInPointsForCss(frame
, params
.page_number
, params
.params
,
127 ignore_css_margins_
, &css_scale_factor
,
128 &page_layout_in_points
);
130 gfx::Rect content_area
;
131 GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points
, &page_size
,
133 int dpi
= static_cast<int>(params
.params
.dpi
);
134 // Calculate the actual page size and content area in dpi.
135 if (page_size_in_dpi
) {
137 gfx::Size(static_cast<int>(ConvertUnitDouble(page_size
.width(),
138 kPointsPerInch
, dpi
)),
139 static_cast<int>(ConvertUnitDouble(page_size
.height(),
140 kPointsPerInch
, dpi
)));
143 if (content_area_in_dpi
) {
144 // Output PDF matches paper size and should be printer edge to edge.
145 *content_area_in_dpi
=
146 gfx::Rect(0, 0, page_size_in_dpi
->width(), page_size_in_dpi
->height());
149 gfx::Rect canvas_area
=
150 params
.params
.display_header_footer
? gfx::Rect(page_size
) : content_area
;
152 float webkit_page_shrink_factor
=
153 frame
->getPrintPageShrink(params
.page_number
);
154 float scale_factor
= css_scale_factor
* webkit_page_shrink_factor
;
156 skia::PlatformCanvas
* canvas
=
157 metafile
->GetVectorCanvasForNewPage(page_size
, canvas_area
, scale_factor
);
161 MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas
, metafile
);
162 skia::SetIsDraftMode(*canvas
, is_print_ready_metafile_sent_
);
164 #if defined(ENABLE_PRINT_PREVIEW)
165 if (params
.params
.display_header_footer
) {
166 // |page_number| is 0-based, so 1 is added.
167 PrintHeaderAndFooter(canvas
, params
.page_number
+ 1,
168 print_preview_context_
.total_page_count(), *frame
,
169 scale_factor
, page_layout_in_points
, params
.params
);
171 #endif // defined(ENABLE_PRINT_PREVIEW)
173 float webkit_scale_factor
=
174 RenderPageContent(frame
, params
.page_number
, canvas_area
, content_area
,
175 scale_factor
, canvas
);
176 DCHECK_GT(webkit_scale_factor
, 0.0f
);
177 // Done printing. Close the canvas to retrieve the compiled metafile.
178 if (!metafile
->FinishPage())
179 NOTREACHED() << "metafile failed";
182 bool PrintWebViewHelper::CopyMetafileDataToSharedMem(
183 const PdfMetafileSkia
& metafile
,
184 base::SharedMemoryHandle
* shared_mem_handle
) {
185 uint32_t buf_size
= metafile
.GetDataSize();
189 base::SharedMemory shared_buf
;
190 // Allocate a shared memory buffer to hold the generated metafile data.
191 if (!shared_buf
.CreateAndMapAnonymous(buf_size
))
194 // Copy the bits into shared memory.
195 if (!metafile
.GetData(shared_buf
.memory(), buf_size
))
198 if (!shared_buf
.GiveToProcess(base::GetCurrentProcessHandle(),
199 shared_mem_handle
)) {
203 Send(new PrintHostMsg_DuplicateSection(routing_id(), *shared_mem_handle
,
208 } // namespace printing