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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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"
11 #include "base/win/scoped_gdi_object.h" 11 #include "base/win/scoped_gdi_object.h"
12 #include "base/win/scoped_hdc.h" 12 #include "base/win/scoped_hdc.h"
13 #include "base/win/scoped_select_object.h" 13 #include "base/win/scoped_select_object.h"
14 #include "chrome/common/print_messages.h" 14 #include "chrome/common/print_messages.h"
15 #include "printing/metafile.h" 15 #include "printing/metafile.h"
16 #include "printing/metafile_impl.h" 16 #include "printing/metafile_impl.h"
17 #include "printing/metafile_skia_wrapper.h" 17 #include "printing/metafile_skia_wrapper.h"
18 #include "printing/page_size_margins.h" 18 #include "printing/page_size_margins.h"
19 #include "printing/units.h" 19 #include "printing/units.h"
20 #include "skia/ext/vector_canvas.h" 20 #include "skia/ext/vector_canvas.h"
21 #include "skia/ext/platform_device.h" 21 #include "skia/ext/platform_device.h"
22 #include "third_party/skia/include/core/SkRefCnt.h" 22 #include "third_party/skia/include/core/SkRefCnt.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
24 #include "ui/gfx/gdi_util.h" 25 #include "ui/gfx/gdi_util.h"
25 #include "ui/gfx/point.h" 26 #include "ui/gfx/point.h"
26 #include "ui/gfx/rect.h" 27 #include "ui/gfx/rect.h"
27 #include "ui/gfx/size.h" 28 #include "ui/gfx/size.h"
28 29
29 using printing::ConvertUnit; 30 using printing::ConvertUnit;
30 using printing::ConvertUnitDouble; 31 using printing::ConvertUnitDouble;
31 using printing::kPointsPerInch; 32 using printing::kPointsPerInch;
32 using printing::Metafile; 33 using printing::Metafile;
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
86 break; 87 break;
87 88
88 default: 89 default:
89 // Play this command to the metafile DC. 90 // Play this command to the metafile DC.
90 PlayEnhMetaFileRecord(dc, handle_table, record, num_objects); 91 PlayEnhMetaFileRecord(dc, handle_table, record, num_objects);
91 break; 92 break;
92 } 93 }
93 return 1; // Continue enumeration 94 return 1; // Continue enumeration
94 } 95 }
95 96
97 // Tracks bitmap resources.
98 class WhitePageBitmap {
99 public:
100 explicit WhitePageBitmap(const gfx::Size& page_size) : old_select_(NULL) {
101 context_.Set(CreateCompatibleDC(NULL));
102 if (!context_) {
103 NOTREACHED() << "Bitmap DC creation failed";
104 return;
105 }
106 SetGraphicsMode(context_, GM_ADVANCED);
107 void* bits = NULL;
108 BITMAPINFO hdr;
109 gfx::CreateBitmapHeader(page_size.width(), page_size.height(),
110 &hdr.bmiHeader);
111 bitmap_.Set(CreateDIBSection(
112 context_, &hdr, DIB_RGB_COLORS, &bits, NULL, 0));
113 if (!bitmap_) {
114 NOTREACHED() << "Raster bitmap creation for printing failed";
115 context_.Close();
116 return;
117 }
118
119 old_select_ = ::SelectObject(context_, bitmap_);
120
121 RECT rect = { 0, 0, page_size.width(), page_size.height() };
122 HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
123 FillRect(context_, &rect, whiteBrush);
124 }
125
126 ~WhitePageBitmap() {
127 if (context_) {
128 ::SelectObject(context_, old_select_);
129 }
130 }
131
132 HDC context() const {
133 return context_;
134 }
135
136 private:
137 base::win::ScopedCreateDC context_;
138 base::win::ScopedBitmap bitmap_;
139 HGDIOBJ old_select_;
140
141 DISALLOW_COPY_AND_ASSIGN(WhitePageBitmap);
142 };
143
96 Metafile* FlattenTransparency(Metafile* metafile, const gfx::Size& page_size) { 144 Metafile* FlattenTransparency(Metafile* metafile, const gfx::Size& page_size) {
97 // Currently, we handle alpha blend transparency for a single page. 145 // Currently, we handle alpha blend transparency for a single page.
98 // Therefore, expecting a metafile with page count 1. 146 // Therefore, expecting a metafile with page count 1.
99 DCHECK_EQ(1U, metafile->GetPageCount()); 147 DCHECK_EQ(1U, metafile->GetPageCount());
100 148
101 // Close the device context to retrieve the compiled metafile. 149 // Close the device context to retrieve the compiled metafile.
102 if (!metafile->FinishDocument()) 150 if (!metafile->FinishDocument())
103 NOTREACHED(); 151 NOTREACHED();
104 152
105 // Page used alpha blend, but printer doesn't support it. Rewrite the 153 // Page used alpha blend, but printer doesn't support it. Rewrite the
106 // metafile and flatten out the transparency. 154 // metafile and flatten out the transparency.
107 base::win::ScopedGetDC screen_dc(NULL); 155 WhitePageBitmap white_page(page_size);
108 base::win::ScopedCreateDC bitmap_dc(CreateCompatibleDC(screen_dc)); 156 HDC bitmap_dc = white_page.context();
109 if (!bitmap_dc) 157 if (!bitmap_dc)
110 NOTREACHED() << "Bitmap DC creation failed"; 158 return metafile;
111 SetGraphicsMode(bitmap_dc, GM_ADVANCED);
112 void* bits = NULL;
113 BITMAPINFO hdr;
114 gfx::CreateBitmapHeader(page_size.width(), page_size.height(),
115 &hdr.bmiHeader);
116 base::win::ScopedBitmap hbitmap(CreateDIBSection(
117 bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0));
118 if (!hbitmap)
119 NOTREACHED() << "Raster bitmap creation for printing failed";
120 159
121 base::win::ScopedSelectObject selectBitmap(bitmap_dc, hbitmap); 160 scoped_ptr<Metafile> metafile2(new printing::NativeMetafile);
122 RECT rect = { 0, 0, page_size.width(), page_size.height() };
123 HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
124 FillRect(bitmap_dc, &rect, whiteBrush);
125
126 Metafile* metafile2(new printing::NativeMetafile);
127 metafile2->Init(); 161 metafile2->Init();
128 HDC hdc = metafile2->context(); 162 HDC hdc = metafile2->context();
129 DCHECK(hdc); 163 DCHECK(hdc);
130 skia::InitializeDC(hdc); 164 skia::InitializeDC(hdc);
131 165
132 RECT metafile_bounds = metafile->GetPageBounds(1).ToRECT();
133 // Process the old metafile, placing all non-AlphaBlend calls into the 166 // Process the old metafile, placing all non-AlphaBlend calls into the
134 // new metafile, and copying the results of all the AlphaBlend calls 167 // new metafile, and copying the results of all the AlphaBlend calls
135 // from the bitmap DC. 168 // from the bitmap DC.
136 EnumEnhMetaFile(hdc, 169 EnumEnhMetaFile(hdc,
137 metafile->emf(), 170 metafile->emf(),
138 EnhMetaFileProc, 171 EnhMetaFileProc,
139 &bitmap_dc, 172 &bitmap_dc,
140 &metafile_bounds); 173 &metafile->GetPageBounds(1).ToRECT());
141 return metafile2; 174
175 return metafile2.release();
176 }
177
178 Metafile* FlattenAll(Metafile* metafile, int raster_size) {
179 DCHECK_EQ(1U, metafile->GetPageCount());
180
181 // Close the device context to retrieve the compiled metafile.
182 if (!metafile->FinishDocument())
183 NOTREACHED();
184
185 gfx::Rect page_bounds = metafile->GetPageBounds(1);
186 gfx::Size page_size(page_bounds.size());
187
188 float scale = sqrt(float(raster_size) / page_size.GetArea());
189 page_size.set_width(std::max<int>(1, page_size.width() * scale));
190 page_size.set_height(std::max<int>(1, page_size.height() * scale));
191
192 // Rewrite the metafile and flatten out content.
193 WhitePageBitmap white_page(page_size);
194 HDC bitmap_dc = white_page.context();
195 if (!bitmap_dc)
196 return metafile;
197
198 gfx::Rect bitmap_rect(page_size);
199 metafile->Playback(bitmap_dc, &bitmap_rect.ToRECT());
200
201 scoped_ptr<Metafile> metafile2(new printing::NativeMetafile);
202 metafile2->Init();
203 HDC hdc = metafile2->context();
204 DCHECK(hdc);
205 skia::InitializeDC(hdc);
206
207 metafile2->StartPageForVectorCanvas(page_bounds.size(), page_bounds, 1);
208
209 ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
210 ModifyWorldTransform(bitmap_dc, NULL, MWT_IDENTITY);
211 StretchBlt(hdc,
212 page_bounds.x(),
213 page_bounds.y(),
214 page_bounds.width(),
215 page_bounds.height(),
216 bitmap_dc,
217 bitmap_rect.x(),
218 bitmap_rect.y(),
219 bitmap_rect.width(),
220 bitmap_rect.height(),
221 SRCCOPY);
222
223 metafile2->FinishPage();
224
225 return metafile2.release();
142 } 226 }
143 227
144 } // namespace 228 } // namespace
145 229
146 void PrintWebViewHelper::PrintPageInternal( 230 void PrintWebViewHelper::PrintPageInternal(
147 const PrintMsg_PrintPage_Params& params, 231 const PrintMsg_PrintPage_Params& params,
148 const gfx::Size& canvas_size, 232 const gfx::Size& canvas_size,
149 WebFrame* frame) { 233 WebFrame* frame) {
150 // Generate a memory-based metafile. It will use the current screen's DPI. 234 // Generate a memory-based metafile. It will use the current screen's DPI.
151 // Each metafile contains a single page. 235 // Each metafile contains a single page.
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 *canvas, actual_shrink)) { 397 *canvas, actual_shrink)) {
314 // Update the dpi adjustment with the "page |actual_shrink|" calculated in 398 // Update the dpi adjustment with the "page |actual_shrink|" calculated in
315 // webkit. 399 // webkit.
316 *actual_shrink /= (webkit_scale_factor * css_scale_factor); 400 *actual_shrink /= (webkit_scale_factor * css_scale_factor);
317 } 401 }
318 } 402 }
319 403
320 bool result = metafile->FinishPage(); 404 bool result = metafile->FinishPage();
321 DCHECK(result); 405 DCHECK(result);
322 406
407 if (!is_preview &&
408 (params.raster_type == PrintMsg_Print_Params::RASTER_ALL ||
409 (frame->document().isPluginDocument() &&
410 params.raster_type == PrintMsg_Print_Params::RASTER_PLUGINS))) {
411 return FlattenAll(metafile, params.raster_size);
412 }
413
323 if (!params.supports_alpha_blend) { 414 if (!params.supports_alpha_blend) {
324 // PreviewMetafile (PDF) supports alpha blend, so we only hit this case 415 // PreviewMetafile (PDF) supports alpha blend, so we only hit this case
325 // for NativeMetafile. 416 // for NativeMetafile.
326 DCHECK(!is_preview); 417 DCHECK(!is_preview);
327 skia::PlatformDevice* platform_device = skia::GetPlatformDevice(device); 418 skia::PlatformDevice* platform_device = skia::GetPlatformDevice(device);
328 if (platform_device && platform_device->AlphaBlendUsed()) { 419 if (platform_device && platform_device->AlphaBlendUsed()) {
Vitaly Buka (NO REVIEWS) 2012/08/20 16:41:51 I found that FlattenTransparency use low-res bitma
Albert Bodenhamer 2012/08/20 18:18:10 I'm ok with that. Just unify it all.
Vitaly Buka (NO REVIEWS) 2012/08/21 19:40:54 Done.
329 return FlattenTransparency(metafile, page_size); 420 return FlattenTransparency(metafile, page_size);
330 } 421 }
331 } 422 }
332 return metafile; 423 return metafile;
333 } 424 }
334 425
335 bool PrintWebViewHelper::CopyMetafileDataToSharedMem( 426 bool PrintWebViewHelper::CopyMetafileDataToSharedMem(
336 Metafile* metafile, base::SharedMemoryHandle* shared_mem_handle) { 427 Metafile* metafile, base::SharedMemoryHandle* shared_mem_handle) {
337 uint32 buf_size = metafile->GetDataSize(); 428 uint32 buf_size = metafile->GetDataSize();
338 base::SharedMemory shared_buf; 429 base::SharedMemory shared_buf;
(...skipping 17 matching lines...) Expand all
356 shared_buf.Unmap(); 447 shared_buf.Unmap();
357 return false; 448 return false;
358 } 449 }
359 shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), shared_mem_handle); 450 shared_buf.GiveToProcess(base::GetCurrentProcessHandle(), shared_mem_handle);
360 shared_buf.Unmap(); 451 shared_buf.Unmap();
361 452
362 Send(new PrintHostMsg_DuplicateSection(routing_id(), *shared_mem_handle, 453 Send(new PrintHostMsg_DuplicateSection(routing_id(), *shared_mem_handle,
363 shared_mem_handle)); 454 shared_mem_handle));
364 return true; 455 return true;
365 } 456 }
OLDNEW
« 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