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

Unified Diff: chrome/renderer/print_web_view_helper_win.cc

Issue 10836330: Rasterize page before printing. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 4 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 side-by-side diff with in-line comments
Download patch
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.
« chrome/common/chrome_switches.cc ('K') | « chrome/renderer/print_web_view_helper.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698