Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 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/file_descriptor_posix.h" | 7 #include "base/file_descriptor_posix.h" |
| 8 #include "base/i18n/time_formatting.h" | |
| 8 #include "base/logging.h" | 9 #include "base/logging.h" |
| 9 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
| 12 #include "base/string_number_conversions.h" | |
| 13 #include "base/time.h" | |
| 14 #include "base/utf_string_conversions.h" | |
| 11 #include "chrome/common/print_messages.h" | 15 #include "chrome/common/print_messages.h" |
| 12 #include "content/common/view_messages.h" | 16 #include "content/common/view_messages.h" |
| 13 #include "printing/metafile.h" | 17 #include "printing/metafile.h" |
| 14 #include "printing/metafile_impl.h" | 18 #include "printing/metafile_impl.h" |
| 15 #include "printing/metafile_skia_wrapper.h" | 19 #include "printing/metafile_skia_wrapper.h" |
| 16 #include "skia/ext/vector_canvas.h" | 20 #include "skia/ext/vector_canvas.h" |
| 21 #include "skia/ext/vector_platform_device_skia.h" | |
| 22 #include "third_party/skia/include/core/SkColor.h" | |
| 23 #include "third_party/skia/include/core/SkDraw.h" | |
| 17 #include "third_party/skia/include/core/SkRefCnt.h" | 24 #include "third_party/skia/include/core/SkRefCnt.h" |
| 25 #include "third_party/skia/include/core/SkTypeface.h" | |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 26 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 27 #include "ui/base/text/text_elider.h" | |
| 19 #include "ui/gfx/point.h" | 28 #include "ui/gfx/point.h" |
| 20 | 29 |
| 21 #if !defined(OS_CHROMEOS) | 30 #if !defined(OS_CHROMEOS) |
| 22 #include "base/process_util.h" | 31 #include "base/process_util.h" |
| 23 #endif // !defined(OS_CHROMEOS) | 32 #endif // !defined(OS_CHROMEOS) |
| 24 | 33 |
| 34 using base::Time; | |
| 25 using WebKit::WebFrame; | 35 using WebKit::WebFrame; |
| 26 using WebKit::WebNode; | 36 using WebKit::WebNode; |
| 27 | 37 |
| 28 bool PrintWebViewHelper::CreatePreviewDocument( | 38 bool PrintWebViewHelper::CreatePreviewDocument( |
| 29 const PrintMsg_PrintPages_Params& params, WebKit::WebFrame* frame, | 39 const PrintMsg_PrintPages_Params& params, WebKit::WebFrame* frame, |
| 30 WebKit::WebNode* node) { | 40 WebKit::WebNode* node) { |
| 31 if (!PreviewPageRendered(-1)) | 41 if (!PreviewPageRendered(-1)) |
| 32 return false; | 42 return false; |
| 33 | 43 |
| 34 printing::PreviewMetafile metafile; | 44 printing::PreviewMetafile metafile; |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 157 return false; | 167 return false; |
| 158 if (is_preview) { | 168 if (is_preview) { |
| 159 Send(new PrintHostMsg_DidGetPreviewPageCount(routing_id(), *page_count)); | 169 Send(new PrintHostMsg_DidGetPreviewPageCount(routing_id(), *page_count)); |
| 160 } else { | 170 } else { |
| 161 #if !defined(OS_CHROMEOS) | 171 #if !defined(OS_CHROMEOS) |
| 162 Send(new PrintHostMsg_DidGetPrintedPagesCount(routing_id(), | 172 Send(new PrintHostMsg_DidGetPrintedPagesCount(routing_id(), |
| 163 printParams.document_cookie, | 173 printParams.document_cookie, |
| 164 *page_count)); | 174 *page_count)); |
| 165 #endif | 175 #endif |
| 166 } | 176 } |
| 177 int total_pages = *page_count; | |
| 167 | 178 |
| 168 base::TimeTicks begin_time = base::TimeTicks::Now(); | 179 base::TimeTicks begin_time = base::TimeTicks::Now(); |
| 169 base::TimeTicks page_begin_time = begin_time; | 180 base::TimeTicks page_begin_time = begin_time; |
| 170 | 181 |
| 171 PrintMsg_PrintPage_Params page_params; | 182 PrintMsg_PrintPage_Params page_params; |
| 172 page_params.params = printParams; | 183 page_params.params = printParams; |
| 173 const gfx::Size& canvas_size = prep_frame_view.GetPrintCanvasSize(); | 184 const gfx::Size& canvas_size = prep_frame_view.GetPrintCanvasSize(); |
| 174 if (params.pages.empty()) { | 185 if (params.pages.empty()) { |
| 175 for (int i = 0; i < *page_count; ++i) { | 186 for (int i = 0; i < *page_count; ++i) { |
| 176 page_params.page_number = i; | 187 page_params.page_number = i; |
| 177 PrintPageInternal(page_params, canvas_size, frame, metafile); | 188 PrintPageInternal(page_params, canvas_size, frame, metafile, is_preview, |
| 189 total_pages); | |
| 178 if (is_preview) { | 190 if (is_preview) { |
| 179 page_begin_time = ReportPreviewPageRenderTime(page_begin_time); | 191 page_begin_time = ReportPreviewPageRenderTime(page_begin_time); |
| 180 if (!PreviewPageRendered(i)) | 192 if (!PreviewPageRendered(i)) |
| 181 return false; | 193 return false; |
| 182 } | 194 } |
| 183 } | 195 } |
| 184 } else { | 196 } else { |
| 185 for (size_t i = 0; i < params.pages.size(); ++i) { | 197 for (size_t i = 0; i < params.pages.size(); ++i) { |
| 186 page_params.page_number = params.pages[i]; | 198 page_params.page_number = params.pages[i]; |
| 187 PrintPageInternal(page_params, canvas_size, frame, metafile); | 199 PrintPageInternal(page_params, canvas_size, frame, metafile, is_preview, |
| 200 total_pages); | |
| 188 if (is_preview) { | 201 if (is_preview) { |
| 189 page_begin_time = ReportPreviewPageRenderTime(page_begin_time); | 202 page_begin_time = ReportPreviewPageRenderTime(page_begin_time); |
| 190 if (!PreviewPageRendered(params.pages[i])) | 203 if (!PreviewPageRendered(params.pages[i])) |
| 191 return false; | 204 return false; |
| 192 } | 205 } |
| 193 } | 206 } |
| 194 } | 207 } |
| 195 | 208 |
| 196 base::TimeDelta render_time = base::TimeTicks::Now() - begin_time; | 209 base::TimeDelta render_time = base::TimeTicks::Now() - begin_time; |
| 197 | 210 |
| 198 prep_frame_view.FinishPrinting(); | 211 prep_frame_view.FinishPrinting(); |
| 199 metafile->FinishDocument(); | 212 metafile->FinishDocument(); |
| 200 | 213 |
| 201 if (is_preview) { | 214 if (is_preview) { |
| 202 ReportTotalPreviewGenerationTime(params.pages.size(), *page_count, | 215 ReportTotalPreviewGenerationTime(params.pages.size(), *page_count, |
| 203 render_time, | 216 render_time, |
| 204 base::TimeTicks::Now() - begin_time); | 217 base::TimeTicks::Now() - begin_time); |
| 205 } | 218 } |
| 206 return true; | 219 return true; |
| 207 } | 220 } |
| 208 | 221 |
| 222 | |
| 223 size_t GetString16ByteLength(string16 text) { | |
| 224 return text.length()*sizeof(char16); | |
| 225 } | |
| 226 | |
| 227 SkScalar PrintWebViewHelper::GetHorizontalCoordinate( | |
| 228 string16 text, | |
| 229 SkPaint paint, | |
| 230 HorizontalHeaderFooterPosition pos, | |
| 231 SkScalar margin_left_in_points, | |
| 232 SkScalar margin_right_in_points, | |
| 233 SkScalar content_width_in_points) { | |
| 234 SkScalar text_width_in_points = paint.measureText(text.c_str(), | |
| 235 GetString16ByteLength(text)); | |
| 236 | |
| 237 switch (pos) { | |
| 238 case LEFT: | |
| 239 return margin_left_in_points*(-1) + header_footer_interstice; | |
| 240 case RIGHT: | |
| 241 return ((content_width_in_points+margin_right_in_points) - | |
| 242 (header_footer_interstice + text_width_in_points)); | |
| 243 case CENTER: | |
| 244 SkScalar available_width = (margin_left_in_points + | |
| 245 margin_right_in_points + | |
| 246 content_width_in_points - | |
| 247 4*header_footer_interstice)/3; | |
| 248 return (available_width - margin_left_in_points + | |
| 249 (available_width - text_width_in_points)/2); | |
| 250 } | |
| 251 NOTREACHED(); | |
| 252 return 0; | |
| 253 } | |
| 254 | |
| 255 SkScalar PrintWebViewHelper::GetVerticalCoordinate( | |
| 256 SkPaint paint, | |
| 257 VerticalHeaderFooterPosition pos, | |
| 258 SkScalar margin_top_in_points, | |
| 259 SkScalar margin_bottom_in_points, | |
| 260 SkScalar content_height_in_points) { | |
| 261 if (pos == TOP) { | |
| 262 return margin_top_in_points*(-0.5); | |
| 263 } else if (pos == BOTTOM) { | |
| 264 return margin_top_in_points+content_height_in_points; | |
| 265 } else { | |
| 266 NOTREACHED(); | |
| 267 return 0; | |
| 268 } | |
| 269 } | |
| 270 | |
| 271 void PrintWebViewHelper::PrintHeaderFooterText( | |
| 272 string16 text, | |
| 273 SkPaint paint, | |
| 274 const SkRefPtr<skia::VectorCanvas>& canvas, | |
| 275 SkScalar margin_left_in_points, | |
| 276 SkScalar margin_right_in_points, | |
| 277 SkScalar content_width_in_points, | |
| 278 SkScalar margin_top_in_points, | |
| 279 SkScalar margin_bottom_in_points, | |
| 280 SkScalar content_height_in_points, | |
| 281 HorizontalHeaderFooterPosition hor_pos, | |
| 282 VerticalHeaderFooterPosition ver_pos) { | |
| 283 SkScalar x_cord = GetHorizontalCoordinate(text, paint, hor_pos, | |
| 284 margin_left_in_points, | |
| 285 margin_right_in_points, | |
| 286 content_width_in_points); | |
| 287 SkScalar y_cord = GetVerticalCoordinate(paint, ver_pos, margin_top_in_points, | |
| 288 margin_bottom_in_points, | |
| 289 content_height_in_points); | |
| 290 size_t byte_length = GetString16ByteLength(text); | |
| 291 | |
| 292 canvas->drawText(text.c_str(), byte_length, x_cord, y_cord, paint); | |
| 293 } | |
| 294 | |
| 209 void PrintWebViewHelper::PrintPageInternal( | 295 void PrintWebViewHelper::PrintPageInternal( |
| 210 const PrintMsg_PrintPage_Params& params, | 296 const PrintMsg_PrintPage_Params& params, |
| 211 const gfx::Size& canvas_size, | 297 const gfx::Size& canvas_size, |
| 212 WebFrame* frame, | 298 WebFrame* frame, |
| 213 printing::Metafile* metafile) { | 299 printing::Metafile* metafile, |
| 300 bool is_preview, | |
| 301 int total_pages) { | |
| 302 // TODO(aayushkumar): Make these variables private variables of the class. | |
| 214 double content_width_in_points; | 303 double content_width_in_points; |
| 215 double content_height_in_points; | 304 double content_height_in_points; |
| 216 double margin_top_in_points; | 305 double margin_top_in_points; |
| 217 double margin_right_in_points; | 306 double margin_right_in_points; |
| 218 double margin_bottom_in_points; | 307 double margin_bottom_in_points; |
| 219 double margin_left_in_points; | 308 double margin_left_in_points; |
| 220 GetPageSizeAndMarginsInPoints(frame, | 309 GetPageSizeAndMarginsInPoints(frame, |
| 221 params.page_number, | 310 params.page_number, |
| 222 params.params, | 311 params.params, |
| 223 &content_width_in_points, | 312 &content_width_in_points, |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 238 SkDevice* device = metafile->StartPageForVectorCanvas( | 327 SkDevice* device = metafile->StartPageForVectorCanvas( |
| 239 page_size, content_area, 1.0f); | 328 page_size, content_area, 1.0f); |
| 240 if (!device) | 329 if (!device) |
| 241 return; | 330 return; |
| 242 | 331 |
| 243 // The printPage method take a reference to the canvas we pass down, so it | 332 // The printPage method take a reference to the canvas we pass down, so it |
| 244 // can't be a stack object. | 333 // can't be a stack object. |
| 245 SkRefPtr<skia::VectorCanvas> canvas = new skia::VectorCanvas(device); | 334 SkRefPtr<skia::VectorCanvas> canvas = new skia::VectorCanvas(device); |
| 246 canvas->unref(); // SkRefPtr and new both took a reference. | 335 canvas->unref(); // SkRefPtr and new both took a reference. |
| 247 printing::MetafileSkiaWrapper::SetMetafileOnCanvas(canvas.get(), metafile); | 336 printing::MetafileSkiaWrapper::SetMetafileOnCanvas(canvas.get(), metafile); |
| 337 | |
| 338 // TODO(aayushkumar): Have a seperate function for printing Headers and Footer | |
|
kmadhusu
2011/07/13 18:47:53
Implement this TODO.
Aayush Kumar
2011/07/13 21:52:16
Done.
| |
| 339 // that will hopefully be in common for all platforms. | |
| 340 if (is_preview && params.params.header_footer) { | |
| 341 // Set the drawing area to draw in the margins. | |
| 342 ((skia::VectorPlatformDeviceSkia* )device)-> | |
| 343 setDrawingArea(SkPDFDevice::kMargin_DrawingArea); | |
| 344 | |
| 345 // Setting up styles for the headers and footers text. | |
| 346 SkPaint paint; | |
| 347 paint.setColor(SK_ColorBLACK); | |
| 348 paint.setTextSize(SkIntToScalar(8)); | |
| 349 paint.setTypeface(SkTypeface::CreateFromName(NULL, SkTypeface::kNormal)); | |
| 350 paint.setTextEncoding(SkPaint::kUTF16_TextEncoding); | |
| 351 | |
| 352 // Printing the Date | |
| 353 Time now = Time::Now(); | |
| 354 string16 date = base::TimeFormatShortDateNumeric(now); | |
| 355 PrintHeaderFooterText(date, paint, canvas, margin_left_in_points, | |
| 356 margin_right_in_points, content_width_in_points, | |
| 357 margin_top_in_points, margin_bottom_in_points, | |
| 358 content_height_in_points, LEFT, TOP); | |
| 359 | |
| 360 // Printing the title | |
| 361 string16 title; | |
| 362 if (!header_footer_info_->GetString("title", &title)) | |
| 363 NOTREACHED(); | |
| 364 | |
| 365 SkScalar maxTitleSize = (margin_left_in_points + | |
| 366 content_width_in_points + | |
| 367 margin_right_in_points)/3; | |
| 368 title = ui::ElideText(title, paint, maxTitleSize, false); | |
| 369 PrintHeaderFooterText(title, paint, canvas, margin_left_in_points, | |
| 370 margin_right_in_points, content_width_in_points, | |
| 371 margin_top_in_points, margin_bottom_in_points, | |
| 372 content_height_in_points, CENTER, TOP); | |
| 373 | |
| 374 // Printing the URL | |
| 375 std::string url; | |
| 376 if (!header_footer_info_->GetString("url", &url)) | |
| 377 NOTREACHED(); | |
| 378 GURL gurl(url); | |
| 379 string16 url_elided = ui::ElideUrl(gurl, paint, maxTitleSize, | |
| 380 std::string()); | |
| 381 PrintHeaderFooterText(url_elided, paint, canvas, margin_left_in_points, | |
| 382 margin_right_in_points, content_width_in_points, | |
| 383 margin_top_in_points, margin_bottom_in_points, | |
| 384 content_height_in_points, LEFT, BOTTOM); | |
| 385 | |
| 386 // Printing the page numbers at the bottom right corner of page. | |
| 387 string16 page_on_page_total = base::IntToString16(params.page_number+1) + | |
| 388 UTF8ToUTF16("/") + | |
|
kmadhusu
2011/07/13 18:47:53
nit: Fix indentation.
Aayush Kumar
2011/07/13 21:52:16
Done.
| |
| 389 base::IntToString16(total_pages); | |
| 390 PrintHeaderFooterText(page_on_page_total, paint, canvas, | |
| 391 margin_left_in_points, margin_right_in_points, | |
| 392 content_width_in_points, margin_top_in_points, | |
| 393 margin_bottom_in_points, content_height_in_points, | |
| 394 RIGHT, BOTTOM); | |
| 395 | |
| 396 // Restore the drawing area to draw in the content area. | |
| 397 ((skia::VectorPlatformDeviceSkia* )device)-> | |
| 398 setDrawingArea(SkPDFDevice::kContent_DrawingArea); | |
| 399 } | |
| 400 | |
| 248 frame->printPage(params.page_number, canvas.get()); | 401 frame->printPage(params.page_number, canvas.get()); |
| 249 | 402 |
| 250 // TODO(myhuang): We should render the header and the footer. | 403 // TODO(myhuang): We should render the header and the footer. |
| 251 | 404 |
| 252 // Done printing. Close the device context to retrieve the compiled metafile. | 405 // Done printing. Close the device context to retrieve the compiled metafile. |
| 253 if (!metafile->FinishPage()) | 406 if (!metafile->FinishPage()) |
| 254 NOTREACHED() << "metafile failed"; | 407 NOTREACHED() << "metafile failed"; |
| 255 } | 408 } |
| OLD | NEW |