OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/renderer/print_web_view_helper.h" | 5 #include "chrome/renderer/print_web_view_helper.h" |
6 | 6 |
7 #import <AppKit/AppKit.h> | 7 #import <AppKit/AppKit.h> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/mac/scoped_nsautorelease_pool.h" | 10 #include "base/mac/scoped_nsautorelease_pool.h" |
11 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
12 #include "chrome/common/print_messages.h" | 12 #include "chrome/common/print_messages.h" |
13 #include "printing/metafile.h" | 13 #include "printing/metafile.h" |
14 #include "printing/metafile_impl.h" | 14 #include "printing/metafile_impl.h" |
| 15 #include "printing/metafile_skia_wrapper.h" |
15 #include "printing/page_size_margins.h" | 16 #include "printing/page_size_margins.h" |
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | |
17 | |
18 #if defined(USE_SKIA) | |
19 #include "printing/metafile_skia_wrapper.h" | |
20 #include "skia/ext/platform_device.h" | 17 #include "skia/ext/platform_device.h" |
21 #include "skia/ext/vector_canvas.h" | 18 #include "skia/ext/vector_canvas.h" |
22 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCanvas.h" | 19 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCanvas.h" |
23 #endif | 20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
24 | 21 |
25 using WebKit::WebFrame; | 22 using WebKit::WebFrame; |
26 | 23 |
27 void PrintWebViewHelper::PrintPageInternal( | 24 void PrintWebViewHelper::PrintPageInternal( |
28 const PrintMsg_PrintPage_Params& params, | 25 const PrintMsg_PrintPage_Params& params, |
29 const gfx::Size& canvas_size, | 26 const gfx::Size& canvas_size, |
30 WebFrame* frame) { | 27 WebFrame* frame) { |
31 printing::NativeMetafile metafile; | 28 printing::NativeMetafile metafile; |
32 if (!metafile.Init()) | 29 if (!metafile.Init()) |
33 return; | 30 return; |
(...skipping 22 matching lines...) Expand all Loading... |
56 } | 53 } |
57 | 54 |
58 bool PrintWebViewHelper::RenderPreviewPage( | 55 bool PrintWebViewHelper::RenderPreviewPage( |
59 int page_number, | 56 int page_number, |
60 const PrintMsg_Print_Params& print_params) { | 57 const PrintMsg_Print_Params& print_params) { |
61 PrintMsg_Print_Params printParams = print_params; | 58 PrintMsg_Print_Params printParams = print_params; |
62 scoped_ptr<printing::Metafile> draft_metafile; | 59 scoped_ptr<printing::Metafile> draft_metafile; |
63 printing::Metafile* initial_render_metafile = | 60 printing::Metafile* initial_render_metafile = |
64 print_preview_context_.metafile(); | 61 print_preview_context_.metafile(); |
65 | 62 |
66 #if defined(USE_SKIA) | |
67 bool render_to_draft = print_preview_context_.IsModifiable() && | 63 bool render_to_draft = print_preview_context_.IsModifiable() && |
68 is_print_ready_metafile_sent_; | 64 is_print_ready_metafile_sent_; |
69 #else | |
70 // If the page needs to be in both draft metafile and print ready metafile, | |
71 // we should always render to the draft metafile first and then copy that | |
72 // into the print ready metafile because CG does not allow us to do it in | |
73 // the other order. | |
74 bool render_to_draft = print_preview_context_.IsModifiable() && | |
75 print_preview_context_.generate_draft_pages(); | |
76 #endif | |
77 | 65 |
78 if (render_to_draft) { | 66 if (render_to_draft) { |
79 draft_metafile.reset(new printing::PreviewMetafile()); | 67 draft_metafile.reset(new printing::PreviewMetafile()); |
80 if (!draft_metafile->Init()) { | 68 if (!draft_metafile->Init()) { |
81 print_preview_context_.set_error( | 69 print_preview_context_.set_error( |
82 PREVIEW_ERROR_MAC_DRAFT_METAFILE_INIT_FAILED); | 70 PREVIEW_ERROR_MAC_DRAFT_METAFILE_INIT_FAILED); |
83 LOG(ERROR) << "Draft PreviewMetafile Init failed"; | 71 LOG(ERROR) << "Draft PreviewMetafile Init failed"; |
84 return false; | 72 return false; |
85 } | 73 } |
86 initial_render_metafile = draft_metafile.get(); | 74 initial_render_metafile = draft_metafile.get(); |
87 } | 75 } |
88 | 76 |
89 base::TimeTicks begin_time = base::TimeTicks::Now(); | 77 base::TimeTicks begin_time = base::TimeTicks::Now(); |
90 gfx::Size page_size; | 78 gfx::Size page_size; |
91 RenderPage(printParams, page_number, print_preview_context_.frame(), true, | 79 RenderPage(printParams, page_number, print_preview_context_.frame(), true, |
92 initial_render_metafile, &page_size, NULL); | 80 initial_render_metafile, &page_size, NULL); |
93 print_preview_context_.RenderedPreviewPage( | 81 print_preview_context_.RenderedPreviewPage( |
94 base::TimeTicks::Now() - begin_time); | 82 base::TimeTicks::Now() - begin_time); |
95 | 83 |
96 if (draft_metafile.get()) { | 84 if (draft_metafile.get()) { |
97 draft_metafile->FinishDocument(); | 85 draft_metafile->FinishDocument(); |
98 #if !defined(USE_SKIA) | |
99 if (!is_print_ready_metafile_sent_) { | |
100 // With CG, we rendered into a new metafile so we could get it as a draft | |
101 // document. Now we need to add it to print ready document. But the | |
102 // document has already been scaled and adjusted for margins, so do a 1:1 | |
103 // drawing. | |
104 printing::Metafile* print_ready_metafile = | |
105 print_preview_context_.metafile(); | |
106 bool success = print_ready_metafile->StartPage(page_size, | |
107 gfx::Rect(page_size), 1.0); | |
108 DCHECK(success); | |
109 // StartPage unconditionally flips the content over, flip it back since it | |
110 // was already flipped in |draft_metafile|. | |
111 CGContextTranslateCTM(print_ready_metafile->context(), 0, | |
112 page_size.height()); | |
113 CGContextScaleCTM(print_ready_metafile->context(), 1.0, -1.0); | |
114 draft_metafile->RenderPage(1, | |
115 print_ready_metafile->context(), | |
116 draft_metafile->GetPageBounds(1).ToCGRect(), | |
117 false /* shrink_to_fit */, | |
118 false /* stretch_to_fit */, | |
119 true /* center_horizontally */, | |
120 true /* center_vertically */); | |
121 print_ready_metafile->FinishPage(); | |
122 } | |
123 #endif | |
124 } else { | 86 } else { |
125 #if defined(USE_SKIA) | |
126 if (print_preview_context_.IsModifiable() && | 87 if (print_preview_context_.IsModifiable() && |
127 print_preview_context_.generate_draft_pages()) { | 88 print_preview_context_.generate_draft_pages()) { |
128 DCHECK(!draft_metafile.get()); | 89 DCHECK(!draft_metafile.get()); |
129 draft_metafile.reset( | 90 draft_metafile.reset( |
130 print_preview_context_.metafile()->GetMetafileForCurrentPage()); | 91 print_preview_context_.metafile()->GetMetafileForCurrentPage()); |
131 } | 92 } |
132 #endif | |
133 } | 93 } |
134 return PreviewPageRendered(page_number, draft_metafile.get()); | 94 return PreviewPageRendered(page_number, draft_metafile.get()); |
135 } | 95 } |
136 | 96 |
137 void PrintWebViewHelper::RenderPage( | 97 void PrintWebViewHelper::RenderPage( |
138 const PrintMsg_Print_Params& params, int page_number, WebFrame* frame, | 98 const PrintMsg_Print_Params& params, int page_number, WebFrame* frame, |
139 bool is_preview, printing::Metafile* metafile, gfx::Size* page_size, | 99 bool is_preview, printing::Metafile* metafile, gfx::Size* page_size, |
140 gfx::Rect* content_rect) { | 100 gfx::Rect* content_rect) { |
141 double scale_factor = 1.0f; | 101 double scale_factor = 1.0f; |
142 double webkit_shrink_factor = frame->getPrintPageShrink(page_number); | 102 double webkit_shrink_factor = frame->getPrintPageShrink(page_number); |
143 printing::PageSizeMargins page_layout_in_points; | 103 printing::PageSizeMargins page_layout_in_points; |
144 gfx::Rect content_area; | 104 gfx::Rect content_area; |
145 | 105 |
146 ComputePageLayoutInPointsForCss(frame, page_number, params, | 106 ComputePageLayoutInPointsForCss(frame, page_number, params, |
147 ignore_css_margins_, &scale_factor, | 107 ignore_css_margins_, &scale_factor, |
148 &page_layout_in_points); | 108 &page_layout_in_points); |
149 GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, page_size, | 109 GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, page_size, |
150 &content_area); | 110 &content_area); |
151 if (content_rect) | 111 if (content_rect) |
152 *content_rect = content_area; | 112 *content_rect = content_area; |
153 | 113 |
154 scale_factor *= webkit_shrink_factor; | 114 scale_factor *= webkit_shrink_factor; |
155 { | 115 { |
156 #if defined(USE_SKIA) | |
157 SkDevice* device = metafile->StartPageForVectorCanvas( | 116 SkDevice* device = metafile->StartPageForVectorCanvas( |
158 *page_size, content_area, scale_factor); | 117 *page_size, content_area, scale_factor); |
159 if (!device) | 118 if (!device) |
160 return; | 119 return; |
161 | 120 |
162 SkRefPtr<skia::VectorCanvas> canvas = new skia::VectorCanvas(device); | 121 SkRefPtr<skia::VectorCanvas> canvas = new skia::VectorCanvas(device); |
163 canvas->unref(); // SkRefPtr and new both took a reference. | 122 canvas->unref(); // SkRefPtr and new both took a reference. |
164 WebKit::WebCanvas* canvas_ptr = canvas.get(); | 123 WebKit::WebCanvas* canvas_ptr = canvas.get(); |
165 printing::MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas, metafile); | 124 printing::MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas, metafile); |
166 skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_); | 125 skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_); |
167 skia::SetIsPreviewMetafile(*canvas, is_preview); | 126 skia::SetIsPreviewMetafile(*canvas, is_preview); |
168 #else | |
169 bool success = metafile->StartPage(*page_size, content_area, scale_factor); | |
170 DCHECK(success); | |
171 // printPage can create autoreleased references to |context|. PDF contexts | |
172 // don't write all their data until they are destroyed, so we need to make | |
173 // certain that there are no lingering references. | |
174 base::mac::ScopedNSAutoreleasePool pool; | |
175 CGContextRef cgContext = metafile->context(); | |
176 CGContextRef canvas_ptr = cgContext; | |
177 | |
178 // For CoreGraphics, print in the margins before printing in the content | |
179 // area so that we don't spill over. Webkit draws a white background in the | |
180 // content area and this acts as a clip. | |
181 // TODO(aayushkumar): Combine the calls to PrintHeaderAndFooter once we | |
182 // can draw in the margins safely in Skia in any order. | |
183 if (print_pages_params_->params.display_header_footer) { | |
184 PrintHeaderAndFooter(canvas_ptr, page_number + 1, | |
185 print_preview_context_.total_page_count(), | |
186 scale_factor, page_layout_in_points, | |
187 *header_footer_info_, params); | |
188 } | |
189 #endif // !USE_SKIA | |
190 | 127 |
191 frame->printPage(page_number, canvas_ptr); | 128 frame->printPage(page_number, canvas_ptr); |
192 | 129 |
193 #if defined(USE_SKIA) | |
194 if (print_pages_params_->params.display_header_footer) { | 130 if (print_pages_params_->params.display_header_footer) { |
195 // |page_number| is 0-based, so 1 is added. | 131 // |page_number| is 0-based, so 1 is added. |
196 PrintHeaderAndFooter(canvas_ptr, page_number + 1, | 132 PrintHeaderAndFooter(canvas_ptr, page_number + 1, |
197 print_preview_context_.total_page_count(), | 133 print_preview_context_.total_page_count(), |
198 scale_factor, page_layout_in_points, | 134 scale_factor, page_layout_in_points, |
199 *header_footer_info_, params); | 135 *header_footer_info_, params); |
200 } | 136 } |
201 #endif // defined(USE_SKIA) | |
202 } | 137 } |
203 | 138 |
204 // Done printing. Close the device context to retrieve the compiled metafile. | 139 // Done printing. Close the device context to retrieve the compiled metafile. |
205 metafile->FinishPage(); | 140 metafile->FinishPage(); |
206 } | 141 } |
OLD | NEW |