Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007 Alp Toker <alp@atoker.com> | 2 * Copyright (C) 2007 Alp Toker <alp@atoker.com> |
| 3 * Copyright (C) 2007 Apple Inc. | 3 * Copyright (C) 2007 Apple Inc. |
| 4 * | 4 * |
| 5 * This library is free software; you can redistribute it and/or | 5 * This library is free software; you can redistribute it and/or |
| 6 * modify it under the terms of the GNU Library General Public | 6 * modify it under the terms of the GNU Library General Public |
| 7 * License as published by the Free Software Foundation; either | 7 * License as published by the Free Software Foundation; either |
| 8 * version 2 of the License, or (at your option) any later version. | 8 * version 2 of the License, or (at your option) any later version. |
| 9 * | 9 * |
| 10 * This library is distributed in the hope that it will be useful, | 10 * This library is distributed in the hope that it will be useful, |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 21 #include "core/page/PrintContext.h" | 21 #include "core/page/PrintContext.h" |
| 22 | 22 |
| 23 #include "core/frame/FrameView.h" | 23 #include "core/frame/FrameView.h" |
| 24 #include "core/frame/LocalFrame.h" | 24 #include "core/frame/LocalFrame.h" |
| 25 #include "core/layout/LayoutView.h" | 25 #include "core/layout/LayoutView.h" |
| 26 #include "core/layout/api/LayoutViewItem.h" | 26 #include "core/layout/api/LayoutViewItem.h" |
| 27 #include "platform/graphics/GraphicsContext.h" | 27 #include "platform/graphics/GraphicsContext.h" |
| 28 | 28 |
| 29 namespace blink { | 29 namespace blink { |
| 30 | 30 |
| 31 namespace { | |
| 32 | |
| 31 // By shrinking to a width of 75% (1.333f) we will render the correct physical | 33 // By shrinking to a width of 75% (1.333f) we will render the correct physical |
| 32 // dimensions in paged media (i.e. cm, pt,). The shrinkage used | 34 // dimensions in paged media (i.e. cm, pt,). The shrinkage used |
| 33 // to be 80% (1.25f) to match other browsers - they have since moved on. | 35 // to be 80% (1.25f) to match other browsers - they have since moved on. |
| 34 // Wide pages will be scaled down more than this. | 36 // Wide pages will be scaled down more than this. |
| 35 const float kPrintingMinimumShrinkFactor = 1.333f; | 37 const float kPrintingMinimumShrinkFactor = 1.333f; |
| 36 | 38 |
| 37 // This number determines how small we are willing to reduce the page content | 39 // This number determines how small we are willing to reduce the page content |
| 38 // in order to accommodate the widest line. If the page would have to be | 40 // in order to accommodate the widest line. If the page would have to be |
| 39 // reduced smaller to make the widest line fit, we just clip instead (this | 41 // reduced smaller to make the widest line fit, we just clip instead (this |
| 40 // behavior matches MacIE and Mozilla, at least). | 42 // behavior matches MacIE and Mozilla, at least). |
| 41 // TODO(rhogan): Decide if this quirk is still required. | 43 // TODO(rhogan): Decide if this quirk is still required. |
| 42 const float kPrintingMaximumShrinkFactor = 2; | 44 const float kPrintingMaximumShrinkFactor = 2; |
| 43 | 45 |
| 46 LayoutBoxModelObject* EnclosingBoxModelObject(LayoutObject* object) { | |
| 47 while (object && !object->IsBoxModelObject()) | |
| 48 object = object->Parent(); | |
| 49 if (!object) | |
| 50 return nullptr; | |
| 51 return ToLayoutBoxModelObject(object); | |
| 52 } | |
| 53 | |
| 54 bool IsCoordinateInPage(int top, int left, const IntRect& page) { | |
| 55 return page.X() <= left && left < page.MaxX() && page.Y() <= top && | |
| 56 top < page.MaxY(); | |
| 57 } | |
| 58 | |
| 59 } // namespace | |
| 60 | |
| 44 PrintContext::PrintContext(LocalFrame* frame) | 61 PrintContext::PrintContext(LocalFrame* frame) |
| 45 : frame_(frame), is_printing_(false), linked_destinations_valid_(false) {} | 62 : frame_(frame), is_printing_(false), linked_destinations_valid_(false) {} |
| 46 | 63 |
| 47 PrintContext::~PrintContext() { | 64 PrintContext::~PrintContext() { |
| 48 if (is_printing_) | 65 DCHECK(!is_printing_); |
| 49 EndPrintMode(); | |
| 50 } | 66 } |
| 51 | 67 |
| 52 void PrintContext::ComputePageRects(const FloatRect& print_rect, | 68 void PrintContext::ComputePageRects(const FloatRect& print_rect, |
| 53 float header_height, | 69 float header_height, |
| 54 float footer_height, | 70 float footer_height, |
| 55 float user_scale_factor, | 71 float user_scale_factor, |
| 56 float& out_page_height) { | 72 float& out_page_height) { |
| 57 page_rects_.clear(); | 73 page_rects_.clear(); |
| 58 out_page_height = 0; | 74 out_page_height = 0; |
| 59 | 75 |
| 60 if (!frame_->GetDocument() || !frame_->View() || | 76 if (!IsFrameValid()) |
| 61 frame_->GetDocument()->GetLayoutViewItem().IsNull()) | |
| 62 return; | 77 return; |
| 63 | 78 |
| 64 if (user_scale_factor <= 0) { | 79 if (user_scale_factor <= 0) { |
| 65 DLOG(ERROR) << "userScaleFactor has bad value " << user_scale_factor; | 80 DLOG(ERROR) << "userScaleFactor has bad value " << user_scale_factor; |
| 66 return; | 81 return; |
| 67 } | 82 } |
| 68 | 83 |
| 69 LayoutViewItem view = frame_->GetDocument()->GetLayoutViewItem(); | 84 LayoutViewItem view = frame_->GetDocument()->GetLayoutViewItem(); |
| 70 const IntRect& document_rect = view.DocumentRect(); | 85 const IntRect& document_rect = view.DocumentRect(); |
| 71 FloatSize page_size = frame_->ResizePageRectsKeepingRatio( | 86 FloatSize page_size = frame_->ResizePageRectsKeepingRatio( |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 88 } | 103 } |
| 89 | 104 |
| 90 void PrintContext::ComputePageRectsWithPageSize( | 105 void PrintContext::ComputePageRectsWithPageSize( |
| 91 const FloatSize& page_size_in_pixels) { | 106 const FloatSize& page_size_in_pixels) { |
| 92 page_rects_.clear(); | 107 page_rects_.clear(); |
| 93 ComputePageRectsWithPageSizeInternal(page_size_in_pixels); | 108 ComputePageRectsWithPageSizeInternal(page_size_in_pixels); |
| 94 } | 109 } |
| 95 | 110 |
| 96 void PrintContext::ComputePageRectsWithPageSizeInternal( | 111 void PrintContext::ComputePageRectsWithPageSizeInternal( |
| 97 const FloatSize& page_size_in_pixels) { | 112 const FloatSize& page_size_in_pixels) { |
| 98 if (!frame_->GetDocument() || !frame_->View() || | 113 if (!IsFrameValid()) |
| 99 frame_->GetDocument()->GetLayoutViewItem().IsNull()) | |
| 100 return; | 114 return; |
| 101 | 115 |
| 102 LayoutViewItem view = frame_->GetDocument()->GetLayoutViewItem(); | 116 LayoutViewItem view = frame_->GetDocument()->GetLayoutViewItem(); |
| 103 | 117 |
| 104 IntRect doc_rect = view.DocumentRect(); | 118 IntRect doc_rect = view.DocumentRect(); |
| 105 | 119 |
| 106 int page_width = page_size_in_pixels.Width(); | 120 int page_width = page_size_in_pixels.Width(); |
| 107 // We scaled with floating point arithmetic and need to ensure results like | 121 // We scaled with floating point arithmetic and need to ensure results like |
| 108 // 13329.99 are treated as 13330 so that we don't mistakenly assign an extra | 122 // 13329.99 are treated as 13330 so that we don't mistakenly assign an extra |
| 109 // page for the stray pixel. | 123 // page for the stray pixel. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 179 // This changes layout, so callers need to make sure that they don't paint to | 193 // This changes layout, so callers need to make sure that they don't paint to |
| 180 // screen while in printing mode. | 194 // screen while in printing mode. |
| 181 frame_->SetPrinting( | 195 frame_->SetPrinting( |
| 182 true, min_layout_size, original_page_size, | 196 true, min_layout_size, original_page_size, |
| 183 kPrintingMaximumShrinkFactor / kPrintingMinimumShrinkFactor); | 197 kPrintingMaximumShrinkFactor / kPrintingMinimumShrinkFactor); |
| 184 } | 198 } |
| 185 | 199 |
| 186 void PrintContext::EndPrintMode() { | 200 void PrintContext::EndPrintMode() { |
| 187 ASSERT(is_printing_); | 201 ASSERT(is_printing_); |
| 188 is_printing_ = false; | 202 is_printing_ = false; |
| 189 frame_->SetPrinting(false, FloatSize(), FloatSize(), 0); | 203 if (IsFrameValid()) |
| 204 frame_->SetPrinting(false, FloatSize(), FloatSize(), 0); | |
| 190 linked_destinations_.clear(); | 205 linked_destinations_.clear(); |
| 191 linked_destinations_valid_ = false; | 206 linked_destinations_valid_ = false; |
| 192 } | 207 } |
| 193 | 208 |
| 194 static LayoutBoxModelObject* EnclosingBoxModelObject(LayoutObject* object) { | 209 // static |
| 195 while (object && !object->IsBoxModelObject()) | |
| 196 object = object->Parent(); | |
| 197 if (!object) | |
| 198 return nullptr; | |
| 199 return ToLayoutBoxModelObject(object); | |
| 200 } | |
| 201 | |
| 202 int PrintContext::PageNumberForElement(Element* element, | 210 int PrintContext::PageNumberForElement(Element* element, |
| 203 const FloatSize& page_size_in_pixels) { | 211 const FloatSize& page_size_in_pixels) { |
| 204 element->GetDocument().UpdateStyleAndLayout(); | 212 element->GetDocument().UpdateStyleAndLayout(); |
| 205 | 213 |
| 206 LocalFrame* frame = element->GetDocument().GetFrame(); | 214 LocalFrame* frame = element->GetDocument().GetFrame(); |
| 207 FloatRect page_rect(FloatPoint(0, 0), page_size_in_pixels); | 215 FloatRect page_rect(FloatPoint(0, 0), page_size_in_pixels); |
| 208 PrintContext print_context(frame); | 216 PrintContext print_context(frame); |
| 209 print_context.BeginPrintMode(page_rect.Width(), page_rect.Height()); | 217 ScopedPrintMode(&print_context, page_rect.Width(), page_rect.Height()); |
|
haraken
2017/05/01 00:21:16
Would it be simpler to create ScopedPrintContext (
Lei Zhang
2017/05/01 03:18:27
Sure. See patch set 5. I tried it earlier but I di
| |
| 210 | 218 |
| 211 LayoutBoxModelObject* box = | 219 LayoutBoxModelObject* box = |
| 212 EnclosingBoxModelObject(element->GetLayoutObject()); | 220 EnclosingBoxModelObject(element->GetLayoutObject()); |
| 213 if (!box) | 221 if (!box) |
| 214 return -1; | 222 return -1; |
| 215 | 223 |
| 216 FloatSize scaled_page_size = page_size_in_pixels; | 224 FloatSize scaled_page_size = page_size_in_pixels; |
| 217 scaled_page_size.Scale(frame->View()->ContentsSize().Width() / | 225 scaled_page_size.Scale(frame->View()->ContentsSize().Width() / |
| 218 page_rect.Width()); | 226 page_rect.Width()); |
| 219 print_context.ComputePageRectsWithPageSize(scaled_page_size); | 227 print_context.ComputePageRectsWithPageSize(scaled_page_size); |
| 220 | 228 |
| 221 int top = box->PixelSnappedOffsetTop(box->OffsetParent()); | 229 int top = box->PixelSnappedOffsetTop(box->OffsetParent()); |
| 222 int left = box->PixelSnappedOffsetLeft(box->OffsetParent()); | 230 int left = box->PixelSnappedOffsetLeft(box->OffsetParent()); |
| 223 size_t page_number = 0; | 231 for (size_t page_number = 0; page_number < print_context.PageCount(); |
| 224 for (; page_number < print_context.PageCount(); page_number++) { | 232 ++page_number) { |
| 225 const IntRect& page = print_context.PageRect(page_number); | 233 if (IsCoordinateInPage(top, left, print_context.PageRect(page_number))) |
| 226 if (page.X() <= left && left < page.MaxX() && page.Y() <= top && | |
| 227 top < page.MaxY()) | |
| 228 return page_number; | 234 return page_number; |
| 229 } | 235 } |
| 230 return -1; | 236 return -1; |
| 231 } | 237 } |
| 232 | 238 |
| 233 void PrintContext::CollectLinkedDestinations(Node* node) { | 239 void PrintContext::CollectLinkedDestinations(Node* node) { |
| 234 for (Node* i = node->firstChild(); i; i = i->nextSibling()) | 240 for (Node* i = node->firstChild(); i; i = i->nextSibling()) |
| 235 CollectLinkedDestinations(i); | 241 CollectLinkedDestinations(i); |
| 236 | 242 |
| 237 if (!node->IsLink() || !node->IsElementNode()) | 243 if (!node->IsLink() || !node->IsElementNode()) |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 270 // the root frame. | 276 // the root frame. |
| 271 IntPoint point = layout_object->GetFrameView()->ConvertToRootFrame( | 277 IntPoint point = layout_object->GetFrameView()->ConvertToRootFrame( |
| 272 bounding_box.Location()); | 278 bounding_box.Location()); |
| 273 if (!page_rect.Contains(point)) | 279 if (!page_rect.Contains(point)) |
| 274 continue; | 280 continue; |
| 275 point.ClampNegativeToZero(); | 281 point.ClampNegativeToZero(); |
| 276 context.SetURLDestinationLocation(entry.key, point); | 282 context.SetURLDestinationLocation(entry.key, point); |
| 277 } | 283 } |
| 278 } | 284 } |
| 279 | 285 |
| 286 // static | |
| 280 String PrintContext::PageProperty(LocalFrame* frame, | 287 String PrintContext::PageProperty(LocalFrame* frame, |
| 281 const char* property_name, | 288 const char* property_name, |
| 282 int page_number) { | 289 int page_number) { |
| 283 Document* document = frame->GetDocument(); | 290 Document* document = frame->GetDocument(); |
| 284 PrintContext print_context(frame); | 291 PrintContext print_context(frame); |
| 285 // Any non-zero size is OK here. We don't care about actual layout. We just | 292 // Any non-zero size is OK here. We don't care about actual layout. We just |
| 286 // want to collect @page rules and figure out what declarations apply on a | 293 // want to collect @page rules and figure out what declarations apply on a |
| 287 // given page (that may or may not exist). | 294 // given page (that may or may not exist). |
| 288 print_context.BeginPrintMode(800, 1000); | 295 ScopedPrintMode(&print_context, 800, 1000); |
| 289 RefPtr<ComputedStyle> style = document->StyleForPage(page_number); | 296 RefPtr<ComputedStyle> style = document->StyleForPage(page_number); |
| 290 | 297 |
| 291 // Implement formatters for properties we care about. | 298 // Implement formatters for properties we care about. |
| 292 if (!strcmp(property_name, "margin-left")) { | 299 if (!strcmp(property_name, "margin-left")) { |
| 293 if (style->MarginLeft().IsAuto()) | 300 if (style->MarginLeft().IsAuto()) |
| 294 return String("auto"); | 301 return String("auto"); |
| 295 return String::Number(style->MarginLeft().Value()); | 302 return String::Number(style->MarginLeft().Value()); |
| 296 } | 303 } |
| 297 if (!strcmp(property_name, "line-height")) | 304 if (!strcmp(property_name, "line-height")) |
| 298 return String::Number(style->LineHeight().Value()); | 305 return String::Number(style->LineHeight().Value()); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 323 frame->GetDocument()->PageSizeAndMarginsInPixels(page_number, page_size, | 330 frame->GetDocument()->PageSizeAndMarginsInPixels(page_number, page_size, |
| 324 margin_top, margin_right, | 331 margin_top, margin_right, |
| 325 margin_bottom, margin_left); | 332 margin_bottom, margin_left); |
| 326 | 333 |
| 327 return "(" + String::Number(floor(page_size.Width())) + ", " + | 334 return "(" + String::Number(floor(page_size.Width())) + ", " + |
| 328 String::Number(floor(page_size.Height())) + ") " + | 335 String::Number(floor(page_size.Height())) + ") " + |
| 329 String::Number(margin_top) + ' ' + String::Number(margin_right) + ' ' + | 336 String::Number(margin_top) + ' ' + String::Number(margin_right) + ' ' + |
| 330 String::Number(margin_bottom) + ' ' + String::Number(margin_left); | 337 String::Number(margin_bottom) + ' ' + String::Number(margin_left); |
| 331 } | 338 } |
| 332 | 339 |
| 340 // static | |
| 333 int PrintContext::NumberOfPages(LocalFrame* frame, | 341 int PrintContext::NumberOfPages(LocalFrame* frame, |
| 334 const FloatSize& page_size_in_pixels) { | 342 const FloatSize& page_size_in_pixels) { |
| 335 frame->GetDocument()->UpdateStyleAndLayout(); | 343 frame->GetDocument()->UpdateStyleAndLayout(); |
| 336 | 344 |
| 337 FloatRect page_rect(FloatPoint(0, 0), page_size_in_pixels); | 345 FloatRect page_rect(FloatPoint(0, 0), page_size_in_pixels); |
| 338 PrintContext print_context(frame); | 346 PrintContext print_context(frame); |
| 339 print_context.BeginPrintMode(page_rect.Width(), page_rect.Height()); | 347 ScopedPrintMode(&print_context, page_rect.Width(), page_rect.Height()); |
| 340 // Account for shrink-to-fit. | 348 // Account for shrink-to-fit. |
| 341 FloatSize scaled_page_size = page_size_in_pixels; | 349 FloatSize scaled_page_size = page_size_in_pixels; |
| 342 scaled_page_size.Scale(frame->View()->ContentsSize().Width() / | 350 scaled_page_size.Scale(frame->View()->ContentsSize().Width() / |
| 343 page_rect.Width()); | 351 page_rect.Width()); |
| 344 print_context.ComputePageRectsWithPageSize(scaled_page_size); | 352 print_context.ComputePageRectsWithPageSize(scaled_page_size); |
| 345 return print_context.PageCount(); | 353 return print_context.PageCount(); |
| 346 } | 354 } |
| 347 | 355 |
| 356 bool PrintContext::IsFrameValid() const { | |
| 357 return frame_->View() && frame_->GetDocument() && | |
| 358 !frame_->GetDocument()->GetLayoutViewItem().IsNull(); | |
| 359 } | |
| 360 | |
| 348 DEFINE_TRACE(PrintContext) { | 361 DEFINE_TRACE(PrintContext) { |
| 349 visitor->Trace(frame_); | 362 visitor->Trace(frame_); |
| 350 visitor->Trace(linked_destinations_); | 363 visitor->Trace(linked_destinations_); |
| 351 } | 364 } |
| 352 | 365 |
| 366 ScopedPrintMode::ScopedPrintMode(PrintContext* context, | |
| 367 float width, | |
| 368 float height) | |
| 369 : context_(context) { | |
| 370 context_->BeginPrintMode(width, height); | |
| 371 } | |
| 372 | |
| 373 ScopedPrintMode::~ScopedPrintMode() { | |
| 374 context_->EndPrintMode(); | |
| 375 } | |
| 376 | |
| 353 } // namespace blink | 377 } // namespace blink |
| OLD | NEW |