| 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 d3e6576b2aa1e7dc05945aa36e3975e4a977fd53..eed65f55f22a4f4d7776e96f1caec9981272f0d2 100644
|
| --- a/chrome/renderer/print_web_view_helper_win.cc
|
| +++ b/chrome/renderer/print_web_view_helper_win.cc
|
| @@ -20,6 +20,7 @@
|
| #include "skia/ext/vector_canvas.h"
|
| #include "skia/ext/platform_device.h"
|
| #include "third_party/skia/include/core/SkRefCnt.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
|
| #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
| #include "ui/gfx/gdi_util.h"
|
| #include "ui/gfx/point.h"
|
| @@ -93,6 +94,53 @@ int CALLBACK EnhMetaFileProc(HDC dc,
|
| return 1; // Continue enumeration
|
| }
|
|
|
| +// Tracks bitmap resources.
|
| +class WhitePageBitmap {
|
| + public:
|
| + explicit WhitePageBitmap(const gfx::Size& page_size) : old_select_(NULL) {
|
| + context_.Set(CreateCompatibleDC(NULL));
|
| + if (!context_) {
|
| + NOTREACHED() << "Bitmap DC creation failed";
|
| + return;
|
| + }
|
| + SetGraphicsMode(context_, GM_ADVANCED);
|
| + void* bits = NULL;
|
| + BITMAPINFO hdr;
|
| + gfx::CreateBitmapHeader(page_size.width(), page_size.height(),
|
| + &hdr.bmiHeader);
|
| + bitmap_.Set(CreateDIBSection(
|
| + context_, &hdr, DIB_RGB_COLORS, &bits, NULL, 0));
|
| + if (!bitmap_) {
|
| + NOTREACHED() << "Raster bitmap creation for printing failed";
|
| + context_.Close();
|
| + return;
|
| + }
|
| +
|
| + old_select_ = ::SelectObject(context_, bitmap_);
|
| +
|
| + RECT rect = { 0, 0, page_size.width(), page_size.height() };
|
| + HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
|
| + FillRect(context_, &rect, whiteBrush);
|
| + }
|
| +
|
| + ~WhitePageBitmap() {
|
| + if (context_) {
|
| + ::SelectObject(context_, old_select_);
|
| + }
|
| + }
|
| +
|
| + HDC context() const {
|
| + return context_;
|
| + }
|
| +
|
| + private:
|
| + base::win::ScopedCreateDC context_;
|
| + base::win::ScopedBitmap bitmap_;
|
| + HGDIOBJ old_select_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(WhitePageBitmap);
|
| +};
|
| +
|
| Metafile* FlattenTransparency(Metafile* metafile, const gfx::Size& page_size) {
|
| // Currently, we handle alpha blend transparency for a single page.
|
| // Therefore, expecting a metafile with page count 1.
|
| @@ -104,32 +152,17 @@ Metafile* FlattenTransparency(Metafile* metafile, const gfx::Size& page_size) {
|
|
|
| // Page used alpha blend, but printer doesn't support it. Rewrite the
|
| // metafile and flatten out the transparency.
|
| - base::win::ScopedGetDC screen_dc(NULL);
|
| - base::win::ScopedCreateDC bitmap_dc(CreateCompatibleDC(screen_dc));
|
| + WhitePageBitmap white_page(page_size);
|
| + HDC bitmap_dc = white_page.context();
|
| if (!bitmap_dc)
|
| - NOTREACHED() << "Bitmap DC creation failed";
|
| - SetGraphicsMode(bitmap_dc, GM_ADVANCED);
|
| - void* bits = NULL;
|
| - BITMAPINFO hdr;
|
| - gfx::CreateBitmapHeader(page_size.width(), page_size.height(),
|
| - &hdr.bmiHeader);
|
| - base::win::ScopedBitmap hbitmap(CreateDIBSection(
|
| - bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0));
|
| - if (!hbitmap)
|
| - NOTREACHED() << "Raster bitmap creation for printing failed";
|
| -
|
| - base::win::ScopedSelectObject selectBitmap(bitmap_dc, hbitmap);
|
| - RECT rect = { 0, 0, page_size.width(), page_size.height() };
|
| - HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
|
| - FillRect(bitmap_dc, &rect, whiteBrush);
|
| -
|
| - Metafile* metafile2(new printing::NativeMetafile);
|
| + return metafile;
|
| +
|
| + scoped_ptr<Metafile> metafile2(new printing::NativeMetafile);
|
| metafile2->Init();
|
| HDC hdc = metafile2->context();
|
| DCHECK(hdc);
|
| skia::InitializeDC(hdc);
|
|
|
| - RECT metafile_bounds = metafile->GetPageBounds(1).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.
|
| @@ -137,8 +170,59 @@ Metafile* FlattenTransparency(Metafile* metafile, const gfx::Size& page_size) {
|
| metafile->emf(),
|
| EnhMetaFileProc,
|
| &bitmap_dc,
|
| - &metafile_bounds);
|
| - return metafile2;
|
| + &metafile->GetPageBounds(1).ToRECT());
|
| +
|
| + return metafile2.release();
|
| +}
|
| +
|
| +Metafile* FlattenAll(Metafile* metafile, int raster_size) {
|
| + DCHECK_EQ(1U, metafile->GetPageCount());
|
| +
|
| + // Close the device context to retrieve the compiled metafile.
|
| + if (!metafile->FinishDocument())
|
| + NOTREACHED();
|
| +
|
| + gfx::Rect page_bounds = metafile->GetPageBounds(1);
|
| + gfx::Size page_size(page_bounds.size());
|
| +
|
| + float scale = sqrt(float(raster_size) / page_size.GetArea());
|
| + page_size.set_width(std::max<int>(1, page_size.width() * scale));
|
| + page_size.set_height(std::max<int>(1, page_size.height() * scale));
|
| +
|
| + // Rewrite the metafile and flatten out content.
|
| + WhitePageBitmap white_page(page_size);
|
| + HDC bitmap_dc = white_page.context();
|
| + if (!bitmap_dc)
|
| + return metafile;
|
| +
|
| + gfx::Rect bitmap_rect(page_size);
|
| + metafile->Playback(bitmap_dc, &bitmap_rect.ToRECT());
|
| +
|
| + scoped_ptr<Metafile> metafile2(new printing::NativeMetafile);
|
| + metafile2->Init();
|
| + HDC hdc = metafile2->context();
|
| + DCHECK(hdc);
|
| + skia::InitializeDC(hdc);
|
| +
|
| + metafile2->StartPageForVectorCanvas(page_bounds.size(), page_bounds, 1);
|
| +
|
| + ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
|
| + ModifyWorldTransform(bitmap_dc, NULL, MWT_IDENTITY);
|
| + StretchBlt(hdc,
|
| + page_bounds.x(),
|
| + page_bounds.y(),
|
| + page_bounds.width(),
|
| + page_bounds.height(),
|
| + bitmap_dc,
|
| + bitmap_rect.x(),
|
| + bitmap_rect.y(),
|
| + bitmap_rect.width(),
|
| + bitmap_rect.height(),
|
| + SRCCOPY);
|
| +
|
| + metafile2->FinishPage();
|
| +
|
| + return metafile2.release();
|
| }
|
|
|
| } // namespace
|
| @@ -320,6 +404,13 @@ Metafile* PrintWebViewHelper::RenderPage(
|
| bool result = metafile->FinishPage();
|
| DCHECK(result);
|
|
|
| + if (!is_preview &&
|
| + (params.raster_type == PrintMsg_Print_Params::RASTER_ALL ||
|
| + (frame->document().isPluginDocument() &&
|
| + params.raster_type == PrintMsg_Print_Params::RASTER_PLUGINS))) {
|
| + return FlattenAll(metafile, params.raster_size);
|
| + }
|
| +
|
| if (!params.supports_alpha_blend) {
|
| // PreviewMetafile (PDF) supports alpha blend, so we only hit this case
|
| // for NativeMetafile.
|
|
|