| OLD | NEW |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/common/render_messages.h" | 8 #include "chrome/common/render_messages.h" |
| 9 #include "chrome/common/render_messages_params.h" | 9 #include "chrome/common/render_messages_params.h" |
| 10 #include "chrome/renderer/render_view.h" | 10 #include "chrome/renderer/render_view.h" |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 const gfx::Size& canvas_size, | 66 const gfx::Size& canvas_size, |
| 67 WebFrame* frame) { | 67 WebFrame* frame) { |
| 68 // Generate a memory-based metafile. It will use the current screen's DPI. | 68 // Generate a memory-based metafile. It will use the current screen's DPI. |
| 69 printing::NativeMetafile metafile; | 69 printing::NativeMetafile metafile; |
| 70 | 70 |
| 71 metafile.CreateDc(NULL, NULL); | 71 metafile.CreateDc(NULL, NULL); |
| 72 HDC hdc = metafile.hdc(); | 72 HDC hdc = metafile.hdc(); |
| 73 DCHECK(hdc); | 73 DCHECK(hdc); |
| 74 skia::PlatformDevice::InitializeDC(hdc); | 74 skia::PlatformDevice::InitializeDC(hdc); |
| 75 | 75 |
| 76 int page_number = params.page_number; |
| 77 |
| 76 double content_width_in_points; | 78 double content_width_in_points; |
| 77 double content_height_in_points; | 79 double content_height_in_points; |
| 78 double margin_top_in_points; | 80 GetPageSizeAndMarginsInPoints(frame, page_number, params.params, |
| 79 double margin_right_in_points; | 81 &content_width_in_points, &content_height_in_points, NULL, NULL, NULL, |
| 80 double margin_bottom_in_points; | 82 NULL); |
| 81 double margin_left_in_points; | |
| 82 GetPageSizeAndMarginsInPoints(frame, | |
| 83 params.page_number, | |
| 84 params.params, | |
| 85 &content_width_in_points, | |
| 86 &content_height_in_points, | |
| 87 &margin_top_in_points, | |
| 88 &margin_right_in_points, | |
| 89 &margin_bottom_in_points, | |
| 90 &margin_left_in_points); | |
| 91 | 83 |
| 92 // Since WebKit extends the page width depending on the magical shrink | 84 // Calculate the dpi adjustment. |
| 93 // factor we make sure the canvas covers the worst case scenario | 85 float scale_factor = static_cast<float>(params.params.desired_dpi / |
| 94 // (x2.0 currently). PrintContext will then set the correct clipping region. | 86 params.params.dpi); |
| 95 int size_x = static_cast<int>(content_width_in_points * | 87 |
| 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). |
| 90 // PrintContext will then set the correct clipping region. |
| 91 int width = static_cast<int>(content_width_in_points * |
| 92 params.params.max_shrink); |
| 93 int height = static_cast<int>(content_height_in_points * |
| 96 params.params.max_shrink); | 94 params.params.max_shrink); |
| 97 int size_y = static_cast<int>(content_height_in_points * | |
| 98 params.params.max_shrink); | |
| 99 // Calculate the dpi adjustment. | |
| 100 float shrink = static_cast<float>(params.params.desired_dpi / | |
| 101 params.params.dpi); | |
| 102 #if 0 | 95 #if 0 |
| 103 // TODO(maruel): This code is kept for testing until the 100% GDI drawing | 96 // TODO(maruel): This code is kept for testing until the 100% GDI drawing |
| 104 // code is stable. maruels use this code's output as a reference when the | 97 // code is stable. maruels use this code's output as a reference when the |
| 105 // GDI drawing code fails. | 98 // GDI drawing code fails. |
| 106 | 99 |
| 107 // Mix of Skia and GDI based. | 100 // Mix of Skia and GDI based. |
| 108 skia::PlatformCanvas canvas(size_x, size_y, true); | 101 skia::PlatformCanvas canvas(width, height, true); |
| 109 canvas.drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode); | 102 canvas.drawARGB(255, 255, 255, 255, SkXfermode::kSrc_Mode); |
| 110 float webkit_shrink = frame->printPage(params.page_number, &canvas); | 103 float webkit_scale_factor = frame->printPage(page_number, &canvas); |
| 111 if (shrink <= 0 || webkit_shrink <= 0) { | 104 if (scale_factor <= 0 || webkit_scale_factor <= 0) { |
| 112 NOTREACHED() << "Printing page " << params.page_number << " failed."; | 105 NOTREACHED() << "Printing page " << page_number << " failed."; |
| 113 } else { | 106 } else { |
| 114 // Update the dpi adjustment with the "page shrink" calculated in webkit. | 107 // Update the dpi adjustment with the "page |scale_factor|" calculated |
| 115 shrink /= webkit_shrink; | 108 // in webkit. |
| 109 scale_factor /= webkit_scale_factor; |
| 116 } | 110 } |
| 117 | 111 |
| 118 // Create a BMP v4 header that we can serialize. | 112 // Create a BMP v4 header that we can serialize. |
| 119 BITMAPV4HEADER bitmap_header; | 113 BITMAPV4HEADER bitmap_header; |
| 120 gfx::CreateBitmapV4Header(size_x, size_y, &bitmap_header); | 114 gfx::CreateBitmapV4Header(width, height, &bitmap_header); |
| 121 const SkBitmap& src_bmp = canvas.getDevice()->accessBitmap(true); | 115 const SkBitmap& src_bmp = canvas.getDevice()->accessBitmap(true); |
| 122 SkAutoLockPixels src_lock(src_bmp); | 116 SkAutoLockPixels src_lock(src_bmp); |
| 123 int retval = StretchDIBits(hdc, | 117 int retval = StretchDIBits(hdc, |
| 124 0, | 118 0, |
| 125 0, | 119 0, |
| 126 size_x, size_y, | 120 width, height, |
| 127 0, 0, | 121 0, 0, |
| 128 size_x, size_y, | 122 width, height, |
| 129 src_bmp.getPixels(), | 123 src_bmp.getPixels(), |
| 130 reinterpret_cast<BITMAPINFO*>(&bitmap_header), | 124 reinterpret_cast<BITMAPINFO*>(&bitmap_header), |
| 131 DIB_RGB_COLORS, | 125 DIB_RGB_COLORS, |
| 132 SRCCOPY); | 126 SRCCOPY); |
| 133 DCHECK(retval != GDI_ERROR); | 127 DCHECK(retval != GDI_ERROR); |
| 134 #else | 128 #else |
| 135 // 100% GDI based. | 129 // 100% GDI based. |
| 136 skia::VectorCanvas canvas(hdc, size_x, size_y); | 130 skia::VectorCanvas canvas(hdc, width, height); |
| 137 float webkit_shrink = frame->printPage(params.page_number, &canvas); | 131 float webkit_scale_factor = frame->printPage(page_number, &canvas); |
| 138 if (shrink <= 0 || webkit_shrink <= 0) { | 132 if (scale_factor <= 0 || webkit_scale_factor <= 0) { |
| 139 NOTREACHED() << "Printing page " << params.page_number << " failed."; | 133 NOTREACHED() << "Printing page " << page_number << " failed."; |
| 140 } else { | 134 } else { |
| 141 // Update the dpi adjustment with the "page shrink" calculated in webkit. | 135 // Update the dpi adjustment with the "page scale_factor" calculated |
| 142 shrink /= webkit_shrink; | 136 // in webkit. |
| 137 scale_factor /= webkit_scale_factor; |
| 143 } | 138 } |
| 144 #endif | 139 #endif |
| 145 | 140 |
| 146 // Done printing. Close the device context to retrieve the compiled metafile. | 141 // Done printing. Close the device context to retrieve the compiled metafile. |
| 147 if (!metafile.CloseDc()) { | 142 if (!metafile.CloseDc()) { |
| 148 NOTREACHED() << "metafile failed"; | 143 NOTREACHED() << "metafile failed"; |
| 149 } | 144 } |
| 150 printing::NativeMetafile* mf = &metafile; | 145 printing::NativeMetafile* mf = &metafile; |
| 151 printing::NativeMetafile metafile2; | 146 printing::NativeMetafile metafile2; |
| 152 | 147 |
| 153 skia::VectorPlatformDevice* platform_device = | 148 skia::VectorPlatformDevice* platform_device = |
| 154 static_cast<skia::VectorPlatformDevice*>(canvas.getDevice()); | 149 static_cast<skia::VectorPlatformDevice*>(canvas.getDevice()); |
| 155 if (platform_device->alpha_blend_used() && | 150 if (platform_device->alpha_blend_used() && |
| 156 !params.params.supports_alpha_blend) { | 151 !params.params.supports_alpha_blend) { |
| 157 // Page used alpha blend, but printer doesn't support it. Rewrite the | 152 // Page used alpha blend, but printer doesn't support it. Rewrite the |
| 158 // metafile and flatten out the transparency. | 153 // metafile and flatten out the transparency. |
| 159 HDC bitmap_dc = CreateCompatibleDC(GetDC(NULL)); | 154 HDC bitmap_dc = CreateCompatibleDC(GetDC(NULL)); |
| 160 if (!bitmap_dc) { | 155 if (!bitmap_dc) { |
| 161 NOTREACHED() << "Bitmap DC creation failed"; | 156 NOTREACHED() << "Bitmap DC creation failed"; |
| 162 } | 157 } |
| 163 SetGraphicsMode(bitmap_dc, GM_ADVANCED); | 158 SetGraphicsMode(bitmap_dc, GM_ADVANCED); |
| 164 void* bits = NULL; | 159 void* bits = NULL; |
| 165 BITMAPINFO hdr; | 160 BITMAPINFO hdr; |
| 166 gfx::CreateBitmapHeader(size_x, size_y, &hdr.bmiHeader); | 161 gfx::CreateBitmapHeader(width, height, &hdr.bmiHeader); |
| 167 HBITMAP hbitmap = CreateDIBSection( | 162 HBITMAP hbitmap = CreateDIBSection( |
| 168 bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0); | 163 bitmap_dc, &hdr, DIB_RGB_COLORS, &bits, NULL, 0); |
| 169 if (!hbitmap) { | 164 if (!hbitmap) { |
| 170 NOTREACHED() << "Raster bitmap creation for printing failed"; | 165 NOTREACHED() << "Raster bitmap creation for printing failed"; |
| 171 } | 166 } |
| 172 | 167 |
| 173 HGDIOBJ old_bitmap = SelectObject(bitmap_dc, hbitmap); | 168 HGDIOBJ old_bitmap = SelectObject(bitmap_dc, hbitmap); |
| 174 RECT rect = {0, 0, size_x, size_y }; | 169 RECT rect = {0, 0, width, height }; |
| 175 HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); | 170 HBRUSH whiteBrush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)); |
| 176 FillRect(bitmap_dc, &rect, whiteBrush); | 171 FillRect(bitmap_dc, &rect, whiteBrush); |
| 177 | 172 |
| 178 metafile2.CreateDc(NULL, NULL); | 173 metafile2.CreateDc(NULL, NULL); |
| 179 HDC hdc = metafile2.hdc(); | 174 HDC hdc = metafile2.hdc(); |
| 180 DCHECK(hdc); | 175 DCHECK(hdc); |
| 181 skia::PlatformDevice::InitializeDC(hdc); | 176 skia::PlatformDevice::InitializeDC(hdc); |
| 182 | 177 |
| 183 RECT metafile_bounds = metafile.GetBounds().ToRECT(); | 178 RECT metafile_bounds = metafile.GetBounds().ToRECT(); |
| 184 // Process the old metafile, placing all non-AlphaBlend calls into the | 179 // Process the old metafile, placing all non-AlphaBlend calls into the |
| (...skipping 12 matching lines...) Expand all Loading... |
| 197 } | 192 } |
| 198 mf = &metafile2; | 193 mf = &metafile2; |
| 199 } | 194 } |
| 200 | 195 |
| 201 // Get the size of the compiled metafile. | 196 // Get the size of the compiled metafile. |
| 202 uint32 buf_size = mf->GetDataSize(); | 197 uint32 buf_size = mf->GetDataSize(); |
| 203 DCHECK_GT(buf_size, 128u); | 198 DCHECK_GT(buf_size, 128u); |
| 204 ViewHostMsg_DidPrintPage_Params page_params; | 199 ViewHostMsg_DidPrintPage_Params page_params; |
| 205 page_params.data_size = 0; | 200 page_params.data_size = 0; |
| 206 page_params.metafile_data_handle = NULL; | 201 page_params.metafile_data_handle = NULL; |
| 207 page_params.page_number = params.page_number; | 202 page_params.page_number = page_number; |
| 208 page_params.document_cookie = params.params.document_cookie; | 203 page_params.document_cookie = params.params.document_cookie; |
| 209 page_params.actual_shrink = shrink; | 204 page_params.actual_shrink = scale_factor; |
| 210 page_params.page_size = gfx::Size( | 205 page_params.page_size = params.params.page_size; |
| 211 static_cast<int>(ConvertUnitDouble( | 206 page_params.content_area = gfx::Rect(params.params.margin_left, |
| 212 content_width_in_points + | 207 params.params.margin_top, params.params.printable_size.width(), |
| 213 margin_left_in_points + margin_right_in_points, | 208 params.params.printable_size.height()); |
| 214 kPointsPerInch, params.params.dpi)), | 209 page_params.has_visible_overlays = frame->isPageBoxVisible(page_number); |
| 215 static_cast<int>(ConvertUnitDouble( | |
| 216 content_height_in_points + | |
| 217 margin_top_in_points + margin_bottom_in_points, | |
| 218 kPointsPerInch, params.params.dpi))); | |
| 219 page_params.content_area = gfx::Rect( | |
| 220 static_cast<int>(ConvertUnitDouble( | |
| 221 margin_left_in_points, kPointsPerInch, params.params.dpi)), | |
| 222 static_cast<int>(ConvertUnitDouble( | |
| 223 margin_top_in_points, kPointsPerInch, params.params.dpi)), | |
| 224 static_cast<int>(ConvertUnitDouble( | |
| 225 content_width_in_points, kPointsPerInch, params.params.dpi)), | |
| 226 static_cast<int>(ConvertUnitDouble( | |
| 227 content_height_in_points, kPointsPerInch, params.params.dpi))); | |
| 228 page_params.has_visible_overlays = | |
| 229 frame->isPageBoxVisible(params.page_number); | |
| 230 base::SharedMemory shared_buf; | 210 base::SharedMemory shared_buf; |
| 231 | 211 |
| 232 // http://msdn2.microsoft.com/en-us/library/ms535522.aspx | 212 // http://msdn2.microsoft.com/en-us/library/ms535522.aspx |
| 233 // Windows 2000/XP: When a page in a spooled file exceeds approximately 350 | 213 // Windows 2000/XP: When a page in a spooled file exceeds approximately 350 |
| 234 // MB, it can fail to print and not send an error message. | 214 // MB, it can fail to print and not send an error message. |
| 235 if (buf_size < 350*1024*1024) { | 215 if (buf_size < 350*1024*1024) { |
| 236 // Allocate a shared memory buffer to hold the generated metafile data. | 216 // Allocate a shared memory buffer to hold the generated metafile data. |
| 237 if (shared_buf.CreateAndMapAnonymous(buf_size)) { | 217 if (shared_buf.CreateAndMapAnonymous(buf_size)) { |
| 238 // Copy the bits into shared memory. | 218 // Copy the bits into shared memory. |
| 239 if (mf->GetData(shared_buf.memory(), buf_size)) { | 219 if (mf->GetData(shared_buf.memory(), buf_size)) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 252 mf->CloseEmf(); | 232 mf->CloseEmf(); |
| 253 if (Send(new ViewHostMsg_DuplicateSection( | 233 if (Send(new ViewHostMsg_DuplicateSection( |
| 254 routing_id(), | 234 routing_id(), |
| 255 page_params.metafile_data_handle, | 235 page_params.metafile_data_handle, |
| 256 &page_params.metafile_data_handle))) { | 236 &page_params.metafile_data_handle))) { |
| 257 if (!is_preview_) { | 237 if (!is_preview_) { |
| 258 Send(new ViewHostMsg_DidPrintPage(routing_id(), page_params)); | 238 Send(new ViewHostMsg_DidPrintPage(routing_id(), page_params)); |
| 259 } | 239 } |
| 260 } | 240 } |
| 261 } | 241 } |
| OLD | NEW |