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

Side by Side Diff: chrome/renderer/print_web_view_helper_win.cc

Issue 8585017: PrintPreview: Honor the print media page size and margin values. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase + fix conflicts Created 8 years, 11 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h" 8 #include "base/memory/scoped_ptr.h"
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "base/process_util.h" 10 #include "base/process_util.h"
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 // Generate a memory-based metafile. It will use the current screen's DPI. 102 // Generate a memory-based metafile. It will use the current screen's DPI.
103 // Each metafile contains a single page. 103 // Each metafile contains a single page.
104 scoped_ptr<Metafile> metafile(new printing::NativeMetafile); 104 scoped_ptr<Metafile> metafile(new printing::NativeMetafile);
105 metafile->Init(); 105 metafile->Init();
106 DCHECK(metafile->context()); 106 DCHECK(metafile->context());
107 skia::InitializeDC(metafile->context()); 107 skia::InitializeDC(metafile->context());
108 108
109 int page_number = params.page_number; 109 int page_number = params.page_number;
110 110
111 // Calculate the dpi adjustment. 111 // Calculate the dpi adjustment.
112 float scale_factor = static_cast<float>(params.params.desired_dpi / 112 double scale_factor = static_cast<float>(params.params.desired_dpi /
113 params.params.dpi); 113 params.params.dpi);
114 114
115 gfx::Size page_size_in_dpi;
116 gfx::Rect content_area_in_dpi;
115 // Render page for printing. 117 // Render page for printing.
116 metafile.reset(RenderPage(params.params, &scale_factor, page_number, false, 118 metafile.reset(RenderPage(params.params, &scale_factor, page_number, false,
117 frame, metafile.get())); 119 frame, metafile.get(), &page_size_in_dpi,
120 &content_area_in_dpi));
118 121
119 // Close the device context to retrieve the compiled metafile. 122 // Close the device context to retrieve the compiled metafile.
120 if (!metafile->FinishDocument()) 123 if (!metafile->FinishDocument())
121 NOTREACHED(); 124 NOTREACHED();
122 125
123 // Get the size of the compiled metafile. 126 // Get the size of the compiled metafile.
124 uint32 buf_size = metafile->GetDataSize(); 127 uint32 buf_size = metafile->GetDataSize();
125 DCHECK_GT(buf_size, 128u); 128 DCHECK_GT(buf_size, 128u);
126 129
127 PrintHostMsg_DidPrintPage_Params page_params; 130 PrintHostMsg_DidPrintPage_Params page_params;
128 page_params.data_size = buf_size; 131 page_params.data_size = buf_size;
129 page_params.metafile_data_handle = NULL; 132 page_params.metafile_data_handle = NULL;
130 page_params.page_number = page_number; 133 page_params.page_number = page_number;
131 page_params.document_cookie = params.params.document_cookie; 134 page_params.document_cookie = params.params.document_cookie;
132 page_params.actual_shrink = scale_factor; 135 page_params.actual_shrink = scale_factor;
133 page_params.page_size = params.params.page_size; 136 page_params.page_size = page_size_in_dpi;
134 page_params.content_area = gfx::Rect(params.params.margin_left, 137 page_params.content_area = content_area_in_dpi;
135 params.params.margin_top, params.params.content_size.width(),
136 params.params.content_size.height());
137 138
138 if (!CopyMetafileDataToSharedMem(metafile.get(), 139 if (!CopyMetafileDataToSharedMem(metafile.get(),
139 &(page_params.metafile_data_handle))) { 140 &(page_params.metafile_data_handle))) {
140 page_params.data_size = 0; 141 page_params.data_size = 0;
141 } 142 }
142 143
143 Send(new PrintHostMsg_DidPrintPage(routing_id(), page_params)); 144 Send(new PrintHostMsg_DidPrintPage(routing_id(), page_params));
144 } 145 }
145 146
146 bool PrintWebViewHelper::RenderPreviewPage(int page_number) { 147 bool PrintWebViewHelper::RenderPreviewPage(int page_number) {
147 PrintMsg_Print_Params print_params = print_preview_context_.print_params(); 148 PrintMsg_Print_Params print_params = print_preview_context_.print_params();
148 // Calculate the dpi adjustment. 149 // Calculate the dpi adjustment.
149 float scale_factor = static_cast<float>(print_params.desired_dpi / 150 double scale_factor = static_cast<float>(print_params.desired_dpi /
150 print_params.dpi); 151 print_params.dpi);
151 scoped_ptr<Metafile> draft_metafile; 152 scoped_ptr<Metafile> draft_metafile;
152 printing::Metafile* initial_render_metafile = 153 printing::Metafile* initial_render_metafile =
153 print_preview_context_.metafile(); 154 print_preview_context_.metafile();
154 155
155 if (print_preview_context_.IsModifiable() && is_print_ready_metafile_sent_) { 156 if (print_preview_context_.IsModifiable() && is_print_ready_metafile_sent_) {
156 draft_metafile.reset(new printing::PreviewMetafile); 157 draft_metafile.reset(new printing::PreviewMetafile);
157 initial_render_metafile = draft_metafile.get(); 158 initial_render_metafile = draft_metafile.get();
158 } 159 }
159 160
160 base::TimeTicks begin_time = base::TimeTicks::Now(); 161 base::TimeTicks begin_time = base::TimeTicks::Now();
161 printing::Metafile* render_page_result = 162 printing::Metafile* render_page_result =
162 RenderPage(print_params, &scale_factor, page_number, true, 163 RenderPage(print_params, &scale_factor, page_number, true,
163 print_preview_context_.frame(), initial_render_metafile); 164 print_preview_context_.frame(), initial_render_metafile,
165 NULL, NULL);
164 // In the preview flow, RenderPage will never return a new metafile. 166 // In the preview flow, RenderPage will never return a new metafile.
165 DCHECK_EQ(render_page_result, initial_render_metafile); 167 DCHECK_EQ(render_page_result, initial_render_metafile);
166 print_preview_context_.RenderedPreviewPage( 168 print_preview_context_.RenderedPreviewPage(
167 base::TimeTicks::Now() - begin_time); 169 base::TimeTicks::Now() - begin_time);
168 170
169 if (draft_metafile.get()) { 171 if (draft_metafile.get()) {
170 draft_metafile->FinishDocument(); 172 draft_metafile->FinishDocument();
171 } else if (print_preview_context_.IsModifiable() && 173 } else if (print_preview_context_.IsModifiable() &&
172 print_preview_context_.generate_draft_pages()) { 174 print_preview_context_.generate_draft_pages()) {
173 DCHECK(!draft_metafile.get()); 175 DCHECK(!draft_metafile.get());
174 draft_metafile.reset( 176 draft_metafile.reset(
175 print_preview_context_.metafile()->GetMetafileForCurrentPage()); 177 print_preview_context_.metafile()->GetMetafileForCurrentPage());
176 } 178 }
177 return PreviewPageRendered(page_number, draft_metafile.get()); 179 return PreviewPageRendered(page_number, draft_metafile.get());
178 } 180 }
179 181
180 Metafile* PrintWebViewHelper::RenderPage( 182 Metafile* PrintWebViewHelper::RenderPage(
181 const PrintMsg_Print_Params& params, float* scale_factor, int page_number, 183 const PrintMsg_Print_Params& params, double* scale_factor, int page_number,
182 bool is_preview, WebFrame* frame, Metafile* metafile) { 184 bool is_preview, WebFrame* frame, Metafile* metafile,
185 gfx::Size* page_size_in_dpi, gfx::Rect* content_area_in_dpi) {
183 printing::PageSizeMargins page_layout_in_points; 186 printing::PageSizeMargins page_layout_in_points;
184 GetPageSizeAndMarginsInPoints(frame, page_number, params, 187 double shrink_factor = 1.0f;
185 &page_layout_in_points); 188 ComputePageLayout(frame, page_number, params, ignore_css_margins_,
189 fit_to_page_, &shrink_factor, &page_layout_in_points);
190 gfx::Size page_size;
191 gfx::Rect content_area;
192 GetPageSizeAndContentAreaFromPageLayout(page_layout_in_points, &page_size,
193 &content_area);
194 if (!is_preview) {
195 int dpi = static_cast<int>(params.dpi);
196 // Calculate the actual page size and content area in dpi.
197 if (page_size_in_dpi) {
198 *page_size_in_dpi = gfx::Size(
vandebo (ex-Chrome) 2012/01/03 21:55:12 is this the same as params.params.page_size in the
kmadhusu 2012/01/04 16:55:35 page_size != params.params.page_size. We set |page
199 static_cast<int>(ConvertUnitDouble(
200 page_size.width(), printing::kPointsPerInch, dpi)),
201 static_cast<int>(ConvertUnitDouble(
202 page_size.height(), printing::kPointsPerInch, dpi)));
203 }
204 if (content_area_in_dpi) {
205 *content_area_in_dpi = gfx::Rect(
206 static_cast<int>(ConvertUnitDouble(content_area.x(),
207 printing::kPointsPerInch, dpi)),
208 static_cast<int>(ConvertUnitDouble(content_area.y(),
209 printing::kPointsPerInch, dpi)),
210 static_cast<int>(ConvertUnitDouble(content_area.width(),
211 printing::kPointsPerInch, dpi)),
212 static_cast<int>(ConvertUnitDouble(content_area.height(),
213 printing::kPointsPerInch, dpi)));
214 }
186 215
187 int width;
188 int height;
189 if (is_preview) {
190 int dpi = static_cast<int>(params.dpi);
191 int desired_dpi = printing::kPointsPerInch;
192 width = ConvertUnit(params.page_size.width(), dpi, desired_dpi);
193 height = ConvertUnit(params.page_size.height(), dpi, desired_dpi);
194 } else {
195 // Since WebKit extends the page width depending on the magical scale factor 216 // Since WebKit extends the page width depending on the magical scale factor
196 // we make sure the canvas covers the worst case scenario (x2.0 currently). 217 // we make sure the canvas covers the worst case scenario (x2.0 currently).
197 // PrintContext will then set the correct clipping region. 218 // PrintContext will then set the correct clipping region.
198 width = static_cast<int>(page_layout_in_points.content_width * 219 page_size = gfx::Size(
199 params.max_shrink); 220 static_cast<int>(page_layout_in_points.content_width *
200 height = static_cast<int>(page_layout_in_points.content_height * 221 params.max_shrink),
201 params.max_shrink); 222 static_cast<int>(page_layout_in_points.content_height *
223 params.max_shrink));
202 } 224 }
203 225 float webkit_page_shrink_factor = frame->getPrintPageShrink(page_number);
204 gfx::Size page_size(width, height);
205 gfx::Rect content_area(
206 static_cast<int>(page_layout_in_points.margin_left),
207 static_cast<int>(page_layout_in_points.margin_top),
208 static_cast<int>(page_layout_in_points.content_width),
209 static_cast<int>(page_layout_in_points.content_height));
210 SkDevice* device = metafile->StartPageForVectorCanvas( 226 SkDevice* device = metafile->StartPageForVectorCanvas(
211 page_size, content_area, frame->getPrintPageShrink(page_number)); 227 page_size, content_area, shrink_factor * webkit_page_shrink_factor);
212 DCHECK(device); 228 DCHECK(device);
213 // The printPage method may take a reference to the canvas we pass down, so it 229 // The printPage method may take a reference to the canvas we pass down, so it
214 // can't be a stack object. 230 // can't be a stack object.
215 SkRefPtr<skia::VectorCanvas> canvas = new skia::VectorCanvas(device); 231 SkRefPtr<skia::VectorCanvas> canvas = new skia::VectorCanvas(device);
216 canvas->unref(); // SkRefPtr and new both took a reference. 232 canvas->unref(); // SkRefPtr and new both took a reference.
217 if (is_preview) { 233 if (is_preview) {
218 printing::MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas, metafile); 234 printing::MetafileSkiaWrapper::SetMetafileOnCanvas(*canvas, metafile);
219 skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_); 235 skia::SetIsDraftMode(*canvas, is_print_ready_metafile_sent_);
220 skia::SetIsPreviewMetafile(*canvas, is_preview); 236 skia::SetIsPreviewMetafile(*canvas, is_preview);
221 } 237 }
222 238
223 float webkit_scale_factor = frame->printPage(page_number, canvas.get()); 239 float webkit_scale_factor = frame->printPage(page_number, canvas.get());
224 240
225 if (params.display_header_footer) { 241 if (params.display_header_footer) {
226 // |page_number| is 0-based, so 1 is added. 242 // |page_number| is 0-based, so 1 is added.
227 PrintHeaderAndFooter(canvas.get(), page_number + 1, 243 PrintHeaderAndFooter(canvas.get(), page_number + 1,
228 print_preview_context_.total_page_count(), 244 print_preview_context_.total_page_count(),
229 webkit_scale_factor, page_layout_in_points, 245 shrink_factor * webkit_page_shrink_factor,
246 page_layout_in_points,
230 *header_footer_info_); 247 *header_footer_info_);
231 } 248 }
232 249
233 if (*scale_factor <= 0 || webkit_scale_factor <= 0) { 250 if (*scale_factor <= 0 || webkit_scale_factor <= 0) {
234 NOTREACHED() << "Printing page " << page_number << " failed."; 251 NOTREACHED() << "Printing page " << page_number << " failed.";
235 } else { 252 } else {
236 // Update the dpi adjustment with the "page |scale_factor|" calculated in 253 // Update the dpi adjustment with the "page |scale_factor|" calculated in
237 // webkit. 254 // webkit.
238 *scale_factor /= webkit_scale_factor; 255 *scale_factor /= (webkit_scale_factor * shrink_factor);
239 } 256 }
240 257
241 bool result = metafile->FinishPage(); 258 bool result = metafile->FinishPage();
242 DCHECK(result); 259 DCHECK(result);
243 260
244 if (!params.supports_alpha_blend) { 261 if (!params.supports_alpha_blend) {
245 // PreviewMetafile (PDF) supports alpha blend, so we only hit this case 262 // PreviewMetafile (PDF) supports alpha blend, so we only hit this case
246 // for NativeMetafile. 263 // for NativeMetafile.
247 DCHECK(!is_preview); 264 DCHECK(!is_preview);
248 skia::PlatformDevice* platform_device = skia::GetPlatformDevice(device); 265 skia::PlatformDevice* platform_device = skia::GetPlatformDevice(device);
249 if (platform_device && platform_device->AlphaBlendUsed()) { 266 if (platform_device && platform_device->AlphaBlendUsed()) {
250 // Currently, we handle alpha blend transparency for a single page. 267 // Currently, we handle alpha blend transparency for a single page.
251 // Therefore, expecting a metafile with page count 1. 268 // Therefore, expecting a metafile with page count 1.
252 DCHECK_EQ(1U, metafile->GetPageCount()); 269 DCHECK_EQ(1U, metafile->GetPageCount());
253 270
254 // Close the device context to retrieve the compiled metafile. 271 // Close the device context to retrieve the compiled metafile.
255 if (!metafile->FinishDocument()) 272 if (!metafile->FinishDocument())
256 NOTREACHED(); 273 NOTREACHED();
257 274
258 // Page used alpha blend, but printer doesn't support it. Rewrite the 275 // Page used alpha blend, but printer doesn't support it. Rewrite the
259 // metafile and flatten out the transparency. 276 // metafile and flatten out the transparency.
260 base::win::ScopedGetDC screen_dc(NULL); 277 base::win::ScopedGetDC screen_dc(NULL);
261 base::win::ScopedCreateDC bitmap_dc(CreateCompatibleDC(screen_dc)); 278 base::win::ScopedCreateDC bitmap_dc(CreateCompatibleDC(screen_dc));
262 if (!bitmap_dc) 279 if (!bitmap_dc)
263 NOTREACHED() << "Bitmap DC creation failed"; 280 NOTREACHED() << "Bitmap DC creation failed";
264 SetGraphicsMode(bitmap_dc, GM_ADVANCED); 281 SetGraphicsMode(bitmap_dc, GM_ADVANCED);
265 void* bits = NULL; 282 void* bits = NULL;
266 BITMAPINFO hdr; 283 BITMAPINFO hdr;
267 gfx::CreateBitmapHeader(width, height, &hdr.bmiHeader); 284 gfx::CreateBitmapHeader(page_size.width(), page_size.height(),
285 &hdr.bmiHeader);
268 base::win::ScopedBitmap hbitmap(CreateDIBSection( 286 base::win::ScopedBitmap hbitmap(CreateDIBSection(
269 bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0)); 287 bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0));
270 if (!hbitmap) 288 if (!hbitmap)
271 NOTREACHED() << "Raster bitmap creation for printing failed"; 289 NOTREACHED() << "Raster bitmap creation for printing failed";
272 290
273 base::win::ScopedSelectObject selectBitmap(bitmap_dc, hbitmap); 291 base::win::ScopedSelectObject selectBitmap(bitmap_dc, hbitmap);
274 RECT rect = {0, 0, width, height }; 292 RECT rect = { 0, 0, page_size.width(), page_size.height() };
275 HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); 293 HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
276 FillRect(bitmap_dc, &rect, whiteBrush); 294 FillRect(bitmap_dc, &rect, whiteBrush);
277 295
278 Metafile* metafile2(new printing::NativeMetafile); 296 Metafile* metafile2(new printing::NativeMetafile);
279 metafile2->Init(); 297 metafile2->Init();
280 HDC hdc = metafile2->context(); 298 HDC hdc = metafile2->context();
281 DCHECK(hdc); 299 DCHECK(hdc);
282 skia::InitializeDC(hdc); 300 skia::InitializeDC(hdc);
283 301
284 RECT metafile_bounds = metafile->GetPageBounds(1).ToRECT(); 302 RECT metafile_bounds = metafile->GetPageBounds(1).ToRECT();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 shared_buf.Unmap(); 338 shared_buf.Unmap();
321 return false; 339 return false;
322 } 340 }
323 shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), shared_mem_handle); 341 shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), shared_mem_handle);
324 shared_buf.Unmap(); 342 shared_buf.Unmap();
325 343
326 Send(new PrintHostMsg_DuplicateSection(routing_id(), *shared_mem_handle, 344 Send(new PrintHostMsg_DuplicateSection(routing_id(), *shared_mem_handle,
327 shared_mem_handle)); 345 shared_mem_handle));
328 return true; 346 return true;
329 } 347 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698