| 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..94b622ff96eaa848ecfb147e0514ea92e5ef3e72 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,56 @@ 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();
|
| +
|
| + // Get the size of the compiled metafile.
|
| + uint32 buf_size = metafile->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);
|
| +
|
| + if (CopyMetafileDataToSharedMem(metafile.get(),
|
| + &(page_params.metafile_data_handle))) {
|
| + page_params.data_size = buf_size;
|
| + }
|
| + metafile->CloseEmf();
|
| + if (Send(new ViewHostMsg_DuplicateSection(
|
| + routing_id(),
|
| + page_params.metafile_data_handle,
|
| + &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 +147,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) {
|
| + if (*scale_factor <= 0 || webkit_scale_factor <= 0) {
|
| NOTREACHED() << "Printing page " << page_number << " failed.";
|
| } 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 +175,24 @@ 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) {
|
| + if (*scale_factor <= 0 || webkit_scale_factor <= 0) {
|
| NOTREACHED() << "Printing page " << page_number << " failed.";
|
| } 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();
|
| +
|
| + scoped_ptr<printing::NativeMetafile> metafile2(
|
| + new printing::NativeMetafile);
|
| // 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 +214,53 @@ 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->reset(metafile2.release());
|
| }
|
| +}
|
|
|
| - // 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);
|
| +bool PrintWebViewHelper::CopyMetafileDataToSharedMem(
|
| + printing::NativeMetafile* metafile,
|
| + base::SharedMemoryHandle* shared_mem_handle) {
|
| + uint32 buf_size = metafile->GetDataSize();
|
| base::SharedMemory shared_buf;
|
|
|
| // 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;
|
| + return false;
|
| }
|
| - 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));
|
| - }
|
| +
|
| + // Allocate a shared memory buffer to hold the generated metafile data.
|
| + if (!shared_buf.CreateAndMapAnonymous(buf_size)) {
|
| + NOTREACHED() << "Buffer allocation failed";
|
| + return false;
|
| + }
|
| +
|
| + // Copy the bits into shared memory.
|
| + if (!metafile->GetData(shared_buf.memory(), buf_size)) {
|
| + NOTREACHED() << "GetData() failed";
|
| + shared_buf.Unmap();
|
| + return false;
|
| }
|
| + shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), shared_mem_handle);
|
| + shared_buf.Unmap();
|
| + return true;
|
| }
|
|
|