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

Side by Side Diff: chrome/renderer/print_web_view_helper_win.cc

Issue 6321017: Refactor win printing workflow. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « chrome/renderer/print_web_view_helper.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/process_util.h"
8 #include "chrome/common/render_messages.h" 9 #include "chrome/common/render_messages.h"
9 #include "chrome/common/render_messages_params.h" 10 #include "chrome/common/render_messages_params.h"
10 #include "chrome/renderer/render_view.h" 11 #include "chrome/renderer/render_view.h"
11 #include "gfx/gdi_util.h" 12 #include "gfx/gdi_util.h"
12 #include "gfx/size.h" 13 #include "gfx/size.h"
13 #include "grit/generated_resources.h" 14 #include "grit/generated_resources.h"
14 #include "printing/native_metafile.h" 15 #include "printing/native_metafile.h"
15 #include "printing/units.h" 16 #include "printing/units.h"
16 #include "skia/ext/vector_canvas.h" 17 #include "skia/ext/vector_canvas.h"
17 #include "skia/ext/vector_platform_device.h" 18 #include "skia/ext/vector_platform_device.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 // Play this command to the metafile DC. 60 // Play this command to the metafile DC.
60 PlayEnhMetaFileRecord(dc, handle_table, record, num_objects); 61 PlayEnhMetaFileRecord(dc, handle_table, record, num_objects);
61 } 62 }
62 return 1; // Continue enumeration 63 return 1; // Continue enumeration
63 } 64 }
64 65
65 void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params, 66 void PrintWebViewHelper::PrintPage(const ViewMsg_PrintPage_Params& params,
66 const gfx::Size& canvas_size, 67 const gfx::Size& canvas_size,
67 WebFrame* frame) { 68 WebFrame* frame) {
68 // Generate a memory-based metafile. It will use the current screen's DPI. 69 // Generate a memory-based metafile. It will use the current screen's DPI.
69 printing::NativeMetafile metafile; 70 // Each metafile contains a single page.
70 71 scoped_ptr<printing::NativeMetafile> metafile(new printing::NativeMetafile());
71 metafile.CreateDc(NULL, NULL); 72 metafile->CreateDc(NULL, NULL);
72 HDC hdc = metafile.hdc(); 73 DCHECK(metafile->hdc());
73 DCHECK(hdc); 74 skia::PlatformDevice::InitializeDC(metafile->hdc());
74 skia::PlatformDevice::InitializeDC(hdc);
75 75
76 int page_number = params.page_number; 76 int page_number = params.page_number;
77 77
78 double content_width_in_points; 78 double content_width_in_points;
79 double content_height_in_points; 79 double content_height_in_points;
80 GetPageSizeAndMarginsInPoints(frame, page_number, params.params, 80 GetPageSizeAndMarginsInPoints(frame, page_number, params.params,
81 &content_width_in_points, &content_height_in_points, NULL, NULL, NULL, 81 &content_width_in_points, &content_height_in_points, NULL, NULL, NULL,
82 NULL); 82 NULL);
83 83
84 // Calculate the dpi adjustment. 84 // Calculate the dpi adjustment.
85 float scale_factor = static_cast<float>(params.params.desired_dpi / 85 float scale_factor = static_cast<float>(params.params.desired_dpi /
86 params.params.dpi); 86 params.params.dpi);
87 87
88 // Since WebKit extends the page width depending on the magical |scale_factor| 88 // Since WebKit extends the page width depending on the magical |scale_factor|
89 // we make sure the canvas covers the worst case scenario (x2.0 currently). 89 // we make sure the canvas covers the worst case scenario (x2.0 currently).
90 // PrintContext will then set the correct clipping region. 90 // PrintContext will then set the correct clipping region.
91 int width = static_cast<int>(content_width_in_points * 91 gfx::Size page_size(
92 params.params.max_shrink); 92 static_cast<int>(content_width_in_points * params.params.max_shrink),
93 int height = static_cast<int>(content_height_in_points * 93 static_cast<int>(content_height_in_points * params.params.max_shrink));
94 params.params.max_shrink); 94
95 // Render page for printing.
96 RenderPage(page_size, &scale_factor, page_number, frame, &metafile,
97 params.params.supports_alpha_blend);
98
99 // Close the device context to retrieve the compiled metafile.
100 if (!metafile->CloseDc())
101 NOTREACHED();
102
103 ViewHostMsg_DidPrintPage_Params page_params;
104 page_params.data_size = metafile->GetDataSize();
105 page_params.metafile_data_handle = base::SharedMemory::NULLHandle();
kmadhusu 2011/01/24 16:23:22 Removed this code because metafile_data_handle is
106 page_params.page_number = page_number;
107 page_params.document_cookie = params.params.document_cookie;
108 page_params.actual_shrink = scale_factor;
109 page_params.page_size = params.params.page_size;
110 page_params.content_area = gfx::Rect(params.params.margin_left,
111 params.params.margin_top, params.params.printable_size.width(),
112 params.params.printable_size.height());
113 page_params.has_visible_overlays = frame->isPageBoxVisible(page_number);
114
115 if (CopyMetafileDataToSharedMem(metafile,
116 &(page_params.metafile_data_handle))) {
117 Send(new ViewHostMsg_DidPrintPage(routing_id(), page_params));
118 }
119 }
120
121 void PrintWebViewHelper::RenderPage(
122 const gfx::Size& page_size, float* scale_factor, int page_number,
123 WebFrame* frame, scoped_ptr<printing::NativeMetafile>* metafile,
124 bool supports_alpha_blend) {
125 HDC hdc = (*metafile)->hdc();
126 DCHECK(hdc);
127
128 int width = page_size.width();
129 int height = page_size.height();
95 #if 0 130 #if 0
96 // TODO(maruel): This code is kept for testing until the 100% GDI drawing 131 // TODO(maruel): This code is kept for testing until the 100% GDI drawing
97 // code is stable. maruels use this code's output as a reference when the 132 // code is stable. maruels use this code's output as a reference when the
98 // GDI drawing code fails. 133 // GDI drawing code fails.
99 134
100 // Mix of Skia and GDI based. 135 // Mix of Skia and GDI based.
101 skia::PlatformCanvas canvas(width, height, true); 136 skia::PlatformCanvas canvas(width, height, true);
102 canvas.drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode); 137 canvas.drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode);
103 float webkit_scale_factor = frame->printPage(page_number, &canvas); 138 float webkit_scale_factor = frame->printPage(page_number, &canvas);
104 if (scale_factor <= 0 || webkit_scale_factor <= 0) { 139 if (*scale_factor <= 0 || webkit_scale_factor <= 0) {
105 NOTREACHED() << "Printing page " << page_number << " failed."; 140 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.
106 } else { 141 } else {
107 // Update the dpi adjustment with the "page |scale_factor|" calculated 142 // Update the dpi adjustment with the "page |scale_factor|" calculated in
108 // in webkit. 143 // webkit.
109 scale_factor /= webkit_scale_factor; 144 *scale_factor /= webkit_scale_factor;
110 } 145 }
111 146
112 // Create a BMP v4 header that we can serialize. 147 // Create a BMP v4 header that we can serialize.
113 BITMAPV4HEADER bitmap_header; 148 BITMAPV4HEADER bitmap_header;
114 gfx::CreateBitmapV4Header(width, height, &bitmap_header); 149 gfx::CreateBitmapV4Header(width, height, &bitmap_header);
115 const SkBitmap& src_bmp = canvas.getDevice()->accessBitmap(true); 150 const SkBitmap& src_bmp = canvas.getDevice()->accessBitmap(true);
116 SkAutoLockPixels src_lock(src_bmp); 151 SkAutoLockPixels src_lock(src_bmp);
117 int retval = StretchDIBits(hdc, 152 int retval = StretchDIBits(hdc,
118 0, 153 0,
119 0, 154 0,
120 width, height, 155 width, height,
121 0, 0, 156 0, 0,
122 width, height, 157 width, height,
123 src_bmp.getPixels(), 158 src_bmp.getPixels(),
124 reinterpret_cast<BITMAPINFO*>(&bitmap_header), 159 reinterpret_cast<BITMAPINFO*>(&bitmap_header),
125 DIB_RGB_COLORS, 160 DIB_RGB_COLORS,
126 SRCCOPY); 161 SRCCOPY);
127 DCHECK(retval != GDI_ERROR); 162 DCHECK(retval != GDI_ERROR);
128 #else 163 #else
129 // 100% GDI based. 164 // 100% GDI based.
130 skia::VectorCanvas canvas(hdc, width, height); 165 skia::VectorCanvas canvas(hdc, width, height);
131 float webkit_scale_factor = frame->printPage(page_number, &canvas); 166 float webkit_scale_factor = frame->printPage(page_number, &canvas);
132 if (scale_factor <= 0 || webkit_scale_factor <= 0) { 167 if (*scale_factor <= 0 || webkit_scale_factor <= 0) {
133 NOTREACHED() << "Printing page " << page_number << " failed."; 168 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.
134 } else { 169 } else {
135 // Update the dpi adjustment with the "page scale_factor" calculated 170 // Update the dpi adjustment with the "page |scale_factor|" calculated in
136 // in webkit. 171 // webkit.
137 scale_factor /= webkit_scale_factor; 172 *scale_factor /= webkit_scale_factor;
138 } 173 }
139 #endif 174 #endif
140 175
141 // Done printing. Close the device context to retrieve the compiled metafile. 176 skia::VectorPlatformDevice* platform_device =
142 if (!metafile.CloseDc()) { 177 static_cast<skia::VectorPlatformDevice*>(canvas.getDevice());
143 NOTREACHED() << "metafile failed"; 178 if (platform_device->alpha_blend_used() && !supports_alpha_blend) {
144 } 179 // Close the device context to retrieve the compiled metafile.
145 printing::NativeMetafile* mf = &metafile; 180 if (!(*metafile)->CloseDc())
146 printing::NativeMetafile metafile2; 181 NOTREACHED();
147 182
148 skia::VectorPlatformDevice* platform_device = 183 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.
149 static_cast<skia::VectorPlatformDevice*>(canvas.getDevice());
150 if (platform_device->alpha_blend_used() &&
151 !params.params.supports_alpha_blend) {
152 // Page used alpha blend, but printer doesn't support it. Rewrite the 184 // Page used alpha blend, but printer doesn't support it. Rewrite the
153 // metafile and flatten out the transparency. 185 // metafile and flatten out the transparency.
154 HDC bitmap_dc = CreateCompatibleDC(GetDC(NULL)); 186 HDC bitmap_dc = CreateCompatibleDC(GetDC(NULL));
155 if (!bitmap_dc) { 187 if (!bitmap_dc) {
156 NOTREACHED() << "Bitmap DC creation failed"; 188 NOTREACHED() << "Bitmap DC creation failed";
157 } 189 }
158 SetGraphicsMode(bitmap_dc, GM_ADVANCED); 190 SetGraphicsMode(bitmap_dc, GM_ADVANCED);
159 void* bits = NULL; 191 void* bits = NULL;
160 BITMAPINFO hdr; 192 BITMAPINFO hdr;
161 gfx::CreateBitmapHeader(width, height, &hdr.bmiHeader); 193 gfx::CreateBitmapHeader(width, height, &hdr.bmiHeader);
162 HBITMAP hbitmap = CreateDIBSection( 194 HBITMAP hbitmap = CreateDIBSection(
163 bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0); 195 bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0);
164 if (!hbitmap) { 196 if (!hbitmap) {
165 NOTREACHED() << "Raster bitmap creation for printing failed"; 197 NOTREACHED() << "Raster bitmap creation for printing failed";
166 } 198 }
167 199
168 HGDIOBJ old_bitmap = SelectObject(bitmap_dc, hbitmap); 200 HGDIOBJ old_bitmap = SelectObject(bitmap_dc, hbitmap);
169 RECT rect = {0, 0, width, height }; 201 RECT rect = {0, 0, width, height };
170 HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); 202 HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
171 FillRect(bitmap_dc, &rect, whiteBrush); 203 FillRect(bitmap_dc, &rect, whiteBrush);
172 204
173 metafile2.CreateDc(NULL, NULL); 205 metafile2->CreateDc(NULL, NULL);
174 HDC hdc = metafile2.hdc(); 206 HDC hdc = metafile2->hdc();
175 DCHECK(hdc); 207 DCHECK(hdc);
176 skia::PlatformDevice::InitializeDC(hdc); 208 skia::PlatformDevice::InitializeDC(hdc);
177 209
178 RECT metafile_bounds = metafile.GetBounds().ToRECT(); 210 RECT metafile_bounds = (*metafile)->GetBounds().ToRECT();
179 // Process the old metafile, placing all non-AlphaBlend calls into the 211 // Process the old metafile, placing all non-AlphaBlend calls into the
180 // new metafile, and copying the results of all the AlphaBlend calls 212 // new metafile, and copying the results of all the AlphaBlend calls
181 // from the bitmap DC. 213 // from the bitmap DC.
182 EnumEnhMetaFile(hdc, 214 EnumEnhMetaFile(hdc,
183 metafile.emf(), 215 (*metafile)->emf(),
184 EnhMetaFileProc, 216 EnhMetaFileProc,
185 &bitmap_dc, 217 &bitmap_dc,
186 &metafile_bounds); 218 &metafile_bounds);
187 219
188 SelectObject(bitmap_dc, old_bitmap); 220 SelectObject(bitmap_dc, old_bitmap);
221 (*metafile)->CloseEmf();
222 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.
223 }
224 }
189 225
190 if (!metafile2.CloseDc()) { 226 bool PrintWebViewHelper::CopyMetafileDataToSharedMem(
191 NOTREACHED() << "metafile failed"; 227 scoped_ptr<printing::NativeMetafile>& metafile,
192 } 228 base::SharedMemoryHandle* shared_mem_handle) {
193 mf = &metafile2; 229 uint32 buf_size = metafile->GetDataSize();
194 }
195
196 // Get the size of the compiled metafile.
197 uint32 buf_size = mf->GetDataSize();
198 DCHECK_GT(buf_size, 128u);
199 ViewHostMsg_DidPrintPage_Params page_params;
200 page_params.data_size = 0;
201 page_params.metafile_data_handle = NULL;
202 page_params.page_number = page_number;
203 page_params.document_cookie = params.params.document_cookie;
204 page_params.actual_shrink = scale_factor;
205 page_params.page_size = params.params.page_size;
206 page_params.content_area = gfx::Rect(params.params.margin_left,
207 params.params.margin_top, params.params.printable_size.width(),
208 params.params.printable_size.height());
209 page_params.has_visible_overlays = frame->isPageBoxVisible(page_number);
210 base::SharedMemory shared_buf;
211
212 // http://msdn2.microsoft.com/en-us/library/ms535522.aspx 230 // http://msdn2.microsoft.com/en-us/library/ms535522.aspx
213 // Windows 2000/XP: When a page in a spooled file exceeds approximately 350 231 // Windows 2000/XP: When a page in a spooled file exceeds approximately 350
214 // MB, it can fail to print and not send an error message. 232 // MB, it can fail to print and not send an error message.
215 if (buf_size < 350*1024*1024) { 233 if (buf_size > 350*1024*1024) {
216 // Allocate a shared memory buffer to hold the generated metafile data. 234 NOTREACHED() << "Buffer too large: " << buf_size;
217 if (shared_buf.CreateAndMapAnonymous(buf_size)) { 235 metafile->CloseEmf();
218 // Copy the bits into shared memory. 236 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
219 if (mf->GetData(shared_buf.memory(), buf_size)) { 237 }
220 page_params.metafile_data_handle = shared_buf.handle(); 238
221 page_params.data_size = buf_size; 239 base::SharedMemory shared_buf;
222 } else { 240 // Allocate a shared memory buffer to hold the generated metafile data.
223 NOTREACHED() << "GetData() failed"; 241 if (!shared_buf.CreateAndMapAnonymous(buf_size)) {
224 } 242 NOTREACHED() << "Buffer allocation failed";
225 shared_buf.Unmap(); 243 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.
226 } else { 244 }
227 NOTREACHED() << "Buffer allocation failed"; 245
228 } 246 // Copy the bits into shared memory.
247 if (metafile->GetData(shared_buf.memory(), buf_size)) {
248 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.
249 shared_mem_handle);
229 } else { 250 } else {
230 NOTREACHED() << "Buffer too large: " << buf_size; 251 NOTREACHED() << "GetData() failed";
231 } 252 }
232 mf->CloseEmf(); 253 shared_buf.Unmap();
233 if (Send(new ViewHostMsg_DuplicateSection( 254 metafile->CloseEmf();
234 routing_id(), 255
235 page_params.metafile_data_handle, 256 return (Send(new ViewHostMsg_DuplicateSection(routing_id(),
236 &page_params.metafile_data_handle))) { 257 *shared_mem_handle, shared_mem_handle)));
237 if (!is_preview_) {
238 Send(new ViewHostMsg_DidPrintPage(routing_id(), page_params));
239 }
240 }
241 } 258 }
OLDNEW
« no previous file with comments | « chrome/renderer/print_web_view_helper.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698