Chromium Code Reviews| Index: chrome/renderer/print_web_view_helper_win.cc |
| diff --git a/chrome/renderer/print_web_view_helper_win.cc b/chrome/renderer/print_web_view_helper_win.cc |
| index 286e801610071d418fa2ce693ec073432377ca4a..2e90ce5e8dfce585f1216aef4137dfb3ee175007 100644 |
| --- a/chrome/renderer/print_web_view_helper_win.cc |
| +++ b/chrome/renderer/print_web_view_helper_win.cc |
| @@ -1,10 +1,11 @@ |
| -// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| #include "chrome/renderer/print_web_view_helper.h" |
| #include "base/logging.h" |
| +#include "base/process_util.h" |
| #include "chrome/common/render_messages.h" |
| #include "chrome/common/render_messages_params.h" |
| #include "chrome/renderer/render_view.h" |
| @@ -66,12 +67,11 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, |
| const gfx::Size& canvas_size, |
| WebFrame* frame) { |
| // Generate a memory-based metafile. It will use the current screen's DPI. |
| - printing::NativeMetafile metafile; |
| - |
| - metafile.CreateDc(NULL, NULL); |
| - HDC hdc = metafile.hdc(); |
| - DCHECK(hdc); |
| - skia::PlatformDevice::InitializeDC(hdc); |
| + // Each metafile contains a single page. |
| + scoped_ptr<printing::NativeMetafile> metafile(new printing::NativeMetafile()); |
| + metafile->CreateDc(NULL, NULL); |
| + DCHECK(metafile->hdc()); |
| + skia::PlatformDevice::InitializeDC(metafile->hdc()); |
| int page_number = params.page_number; |
| @@ -88,10 +88,45 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, |
| // Since WebKit extends the page width depending on the magical |scale_factor| |
| // we make sure the canvas covers the worst case scenario (x2.0 currently). |
| // PrintContext will then set the correct clipping region. |
| - int width = static_cast<int>(content_width_in_points * |
| - params.params.max_shrink); |
| - int height = static_cast<int>(content_height_in_points * |
| - params.params.max_shrink); |
| + gfx::Size page_size( |
| + static_cast<int>(content_width_in_points * params.params.max_shrink), |
| + static_cast<int>(content_height_in_points * params.params.max_shrink)); |
| + |
| + // Render page for printing. |
| + RenderPage(page_size, &scale_factor, page_number, frame, &metafile, |
| + params.params.supports_alpha_blend); |
| + |
| + // Close the device context to retrieve the compiled metafile. |
| + if (!metafile->CloseDc()) |
| + NOTREACHED(); |
| + |
| + ViewHostMsg_DidPrintPage_Params page_params; |
| + page_params.data_size = metafile->GetDataSize(); |
| + page_params.metafile_data_handle = base::SharedMemory::NULLHandle(); |
|
kmadhusu
2011/01/24 16:23:22
Removed this code because metafile_data_handle is
|
| + page_params.page_number = page_number; |
| + page_params.document_cookie = params.params.document_cookie; |
| + page_params.actual_shrink = scale_factor; |
| + page_params.page_size = params.params.page_size; |
| + page_params.content_area = gfx::Rect(params.params.margin_left, |
| + params.params.margin_top, params.params.printable_size.width(), |
| + params.params.printable_size.height()); |
| + page_params.has_visible_overlays = frame->isPageBoxVisible(page_number); |
| + |
| + if (CopyMetafileDataToSharedMem(metafile, |
| + &(page_params.metafile_data_handle))) { |
| + Send(new ViewHostMsg_DidPrintPage(routing_id(), page_params)); |
| + } |
| +} |
| + |
| +void PrintWebViewHelper::RenderPage( |
| + const gfx::Size& page_size, float* scale_factor, int page_number, |
| + WebFrame* frame, scoped_ptr<printing::NativeMetafile>* metafile, |
| + bool supports_alpha_blend) { |
| + HDC hdc = (*metafile)->hdc(); |
| + DCHECK(hdc); |
| + |
| + int width = page_size.width(); |
| + int height = page_size.height(); |
| #if 0 |
| // TODO(maruel): This code is kept for testing until the 100% GDI drawing |
| // code is stable. maruels use this code's output as a reference when the |
| @@ -101,12 +136,12 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, |
| skia::PlatformCanvas canvas(width, height, true); |
| canvas.drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode); |
| float webkit_scale_factor = frame->printPage(page_number, &canvas); |
| - if (scale_factor <= 0 || webkit_scale_factor <= 0) { |
| - NOTREACHED() << "Printing page " << page_number << " failed."; |
| + if (*scale_factor <= 0 || webkit_scale_factor <= 0) { |
| + NOTREACHED() << "Printing page " << page_number << "failed."; |
|
vandebo (ex-Chrome)
2011/01/21 21:53:28
nit: "failed" -> " failed."
kmadhusu
2011/01/24 16:23:22
Done.
|
| } else { |
| - // Update the dpi adjustment with the "page |scale_factor|" calculated |
| - // in webkit. |
| - scale_factor /= webkit_scale_factor; |
| + // Update the dpi adjustment with the "page |scale_factor|" calculated in |
| + // webkit. |
| + *scale_factor /= webkit_scale_factor; |
| } |
| // Create a BMP v4 header that we can serialize. |
| @@ -129,26 +164,23 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, |
| // 100% GDI based. |
| skia::VectorCanvas canvas(hdc, width, height); |
| float webkit_scale_factor = frame->printPage(page_number, &canvas); |
| - if (scale_factor <= 0 || webkit_scale_factor <= 0) { |
| - NOTREACHED() << "Printing page " << page_number << " failed."; |
| + if (*scale_factor <= 0 || webkit_scale_factor <= 0) { |
| + NOTREACHED() << "Printing page " << page_number << "failed"; |
|
vandebo (ex-Chrome)
2011/01/21 21:53:28
And here
kmadhusu
2011/01/24 16:23:22
Done.
|
| } else { |
| - // Update the dpi adjustment with the "page scale_factor" calculated |
| - // in webkit. |
| - scale_factor /= webkit_scale_factor; |
| + // Update the dpi adjustment with the "page |scale_factor|" calculated in |
| + // webkit. |
| + *scale_factor /= webkit_scale_factor; |
| } |
| #endif |
| - // Done printing. Close the device context to retrieve the compiled metafile. |
| - if (!metafile.CloseDc()) { |
| - NOTREACHED() << "metafile failed"; |
| - } |
| - printing::NativeMetafile* mf = &metafile; |
| - printing::NativeMetafile metafile2; |
| - |
| skia::VectorPlatformDevice* platform_device = |
| - static_cast<skia::VectorPlatformDevice*>(canvas.getDevice()); |
| - if (platform_device->alpha_blend_used() && |
| - !params.params.supports_alpha_blend) { |
| + static_cast<skia::VectorPlatformDevice*>(canvas.getDevice()); |
| + if (platform_device->alpha_blend_used() && !supports_alpha_blend) { |
| + // Close the device context to retrieve the compiled metafile. |
| + if (!(*metafile)->CloseDc()) |
| + NOTREACHED(); |
| + |
| + printing::NativeMetafile* metafile2(new printing::NativeMetafile()); |
|
vandebo (ex-Chrome)
2011/01/21 21:53:28
scoped_ptr<>
kmadhusu
2011/01/24 16:23:22
Done.
|
| // Page used alpha blend, but printer doesn't support it. Rewrite the |
| // metafile and flatten out the transparency. |
| HDC bitmap_dc = CreateCompatibleDC(GetDC(NULL)); |
| @@ -170,72 +202,57 @@ void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, |
| HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); |
| FillRect(bitmap_dc, &rect, whiteBrush); |
| - metafile2.CreateDc(NULL, NULL); |
| - HDC hdc = metafile2.hdc(); |
| + metafile2->CreateDc(NULL, NULL); |
| + HDC hdc = metafile2->hdc(); |
| DCHECK(hdc); |
| skia::PlatformDevice::InitializeDC(hdc); |
| - RECT metafile_bounds = metafile.GetBounds().ToRECT(); |
| + RECT metafile_bounds = (*metafile)->GetBounds().ToRECT(); |
| // Process the old metafile, placing all non-AlphaBlend calls into the |
| // new metafile, and copying the results of all the AlphaBlend calls |
| // from the bitmap DC. |
| EnumEnhMetaFile(hdc, |
| - metafile.emf(), |
| + (*metafile)->emf(), |
| EnhMetaFileProc, |
| &bitmap_dc, |
| &metafile_bounds); |
| SelectObject(bitmap_dc, old_bitmap); |
| - |
| - if (!metafile2.CloseDc()) { |
| - NOTREACHED() << "metafile failed"; |
| - } |
| - mf = &metafile2; |
| + (*metafile)->CloseEmf(); |
| + metafile->reset(metafile2); |
|
vandebo (ex-Chrome)
2011/01/21 21:53:28
to go with the scoped_ptr<>:
metafile->reset(metaf
kmadhusu
2011/01/24 16:23:22
Done.
|
| } |
| +} |
| - // Get the size of the compiled metafile. |
| - uint32 buf_size = mf->GetDataSize(); |
| - DCHECK_GT(buf_size, 128u); |
| - ViewHostMsg_DidPrintPage_Params page_params; |
| - page_params.data_size = 0; |
| - page_params.metafile_data_handle = NULL; |
| - page_params.page_number = page_number; |
| - page_params.document_cookie = params.params.document_cookie; |
| - page_params.actual_shrink = scale_factor; |
| - page_params.page_size = params.params.page_size; |
| - page_params.content_area = gfx::Rect(params.params.margin_left, |
| - params.params.margin_top, params.params.printable_size.width(), |
| - params.params.printable_size.height()); |
| - page_params.has_visible_overlays = frame->isPageBoxVisible(page_number); |
| - base::SharedMemory shared_buf; |
| - |
| +bool PrintWebViewHelper::CopyMetafileDataToSharedMem( |
| + scoped_ptr<printing::NativeMetafile>& metafile, |
| + base::SharedMemoryHandle* shared_mem_handle) { |
| + uint32 buf_size = metafile->GetDataSize(); |
| // http://msdn2.microsoft.com/en-us/library/ms535522.aspx |
| // Windows 2000/XP: When a page in a spooled file exceeds approximately 350 |
| // MB, it can fail to print and not send an error message. |
| - if (buf_size < 350*1024*1024) { |
| - // Allocate a shared memory buffer to hold the generated metafile data. |
| - if (shared_buf.CreateAndMapAnonymous(buf_size)) { |
| - // Copy the bits into shared memory. |
| - if (mf->GetData(shared_buf.memory(), buf_size)) { |
| - page_params.metafile_data_handle = shared_buf.handle(); |
| - page_params.data_size = buf_size; |
| - } else { |
| - NOTREACHED() << "GetData() failed"; |
| - } |
| - shared_buf.Unmap(); |
| - } else { |
| - NOTREACHED() << "Buffer allocation failed"; |
| - } |
| - } else { |
| + if (buf_size > 350*1024*1024) { |
| NOTREACHED() << "Buffer too large: " << buf_size; |
| + metafile->CloseEmf(); |
| + return false; |
|
vandebo (ex-Chrome)
2011/01/21 21:53:28
The old code Sends the DuplicateSection call even
kmadhusu
2011/01/24 16:23:22
metafile_data_handle is initialized to "INVALID_HA
|
| } |
| - mf->CloseEmf(); |
| - if (Send(new ViewHostMsg_DuplicateSection( |
| - routing_id(), |
| - page_params.metafile_data_handle, |
| - &page_params.metafile_data_handle))) { |
| - if (!is_preview_) { |
| - Send(new ViewHostMsg_DidPrintPage(routing_id(), page_params)); |
| - } |
| + |
| + base::SharedMemory shared_buf; |
| + // Allocate a shared memory buffer to hold the generated metafile data. |
| + if (!shared_buf.CreateAndMapAnonymous(buf_size)) { |
| + NOTREACHED() << "Buffer allocation failed"; |
| + return false; |
|
vandebo (ex-Chrome)
2011/01/21 21:53:28
You're missing the CloseEmf() here. This comment
kmadhusu
2011/01/24 16:23:22
Reverted to the old control flow.
|
| } |
| + |
| + // Copy the bits into shared memory. |
| + if (metafile->GetData(shared_buf.memory(), buf_size)) { |
| + shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), |
|
vandebo (ex-Chrome)
2011/01/21 21:53:28
Will this cause the shared mem handle to leak? Yo
kmadhusu
2011/01/24 16:23:22
No. I confirmed this with brettw@chromium.org.
|
| + shared_mem_handle); |
| + } else { |
| + NOTREACHED() << "GetData() failed"; |
| + } |
| + shared_buf.Unmap(); |
| + metafile->CloseEmf(); |
| + |
| + return (Send(new ViewHostMsg_DuplicateSection(routing_id(), |
| + *shared_mem_handle, shared_mem_handle))); |
| } |