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 end(); | |
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::end() { | 200 void PrintContext::end() { |
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 ScopedPrintContext print_context(frame); |
209 print_context.begin(page_rect.Width(), page_rect.Height()); | 217 print_context->begin(page_rect.Width(), page_rect.Height()); |
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 ScopedPrintContext 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.begin(800, 1000); | 295 print_context->begin(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 ScopedPrintContext print_context(frame); |
339 print_context.begin(page_rect.Width(), page_rect.Height()); | 347 print_context->begin(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(); |
| 354 } |
| 355 |
| 356 bool PrintContext::IsFrameValid() const { |
| 357 return frame_->View() && frame_->GetDocument() && |
| 358 !frame_->GetDocument()->GetLayoutViewItem().IsNull(); |
346 } | 359 } |
347 | 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 ScopedPrintContext::ScopedPrintContext(LocalFrame* frame) |
| 367 : context_(new PrintContext(frame)) {} |
| 368 |
| 369 ScopedPrintContext::~ScopedPrintContext() { |
| 370 context_->end(); |
| 371 } |
| 372 |
353 } // namespace blink | 373 } // namespace blink |
OLD | NEW |