1 | /* |
2 | * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Apple Inc. All rights reserved. |
3 | * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com) |
4 | * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
5 | * Copyright (C) 2013 University of Washington. |
6 | * |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions |
9 | * are met: |
10 | * |
11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
18 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
19 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A |
20 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
21 | * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
22 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
23 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
24 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
25 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
26 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
27 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
28 | */ |
29 | |
30 | |
31 | #include "config.h" |
32 | #include "FrameSnapshotting.h" |
33 | |
34 | #include "Document.h" |
35 | #include "FloatRect.h" |
36 | #include "Frame.h" |
37 | #include "FrameSelection.h" |
38 | #include "FrameView.h" |
39 | #include "GraphicsContext.h" |
40 | #include "ImageBuffer.h" |
41 | #include "Page.h" |
42 | #include "RenderObject.h" |
43 | #include "Settings.h" |
44 | |
45 | namespace WebCore { |
46 | |
47 | struct ScopedFramePaintingState { |
48 | ScopedFramePaintingState(Frame& frame, Node* node) |
49 | : frame(frame) |
50 | , node(node) |
51 | , paintBehavior(frame.view()->paintBehavior()) |
52 | , backgroundColor(frame.view()->baseBackgroundColor()) |
53 | { |
54 | ASSERT(!node || node->renderer()); |
55 | } |
56 | |
57 | ~ScopedFramePaintingState() |
58 | { |
59 | frame.view()->setPaintBehavior(paintBehavior); |
60 | frame.view()->setBaseBackgroundColor(backgroundColor); |
61 | frame.view()->setNodeToDraw(nullptr); |
62 | } |
63 | |
64 | const Frame& frame; |
65 | const Node* node; |
66 | const OptionSet<PaintBehavior> paintBehavior; |
67 | const Color backgroundColor; |
68 | }; |
69 | |
70 | std::unique_ptr<ImageBuffer> snapshotFrameRect(Frame& frame, const IntRect& imageRect, SnapshotOptions options) |
71 | { |
72 | Vector<FloatRect> clipRects; |
73 | return snapshotFrameRectWithClip(frame, imageRect, clipRects, options); |
74 | } |
75 | |
76 | std::unique_ptr<ImageBuffer> snapshotFrameRectWithClip(Frame& frame, const IntRect& imageRect, const Vector<FloatRect>& clipRects, SnapshotOptions options) |
77 | { |
78 | if (!frame.page()) |
79 | return nullptr; |
80 | |
81 | frame.document()->updateLayout(); |
82 | |
83 | FrameView::SelectionInSnapshot shouldIncludeSelection = FrameView::IncludeSelection; |
84 | if (options & SnapshotOptionsExcludeSelectionHighlighting) |
85 | shouldIncludeSelection = FrameView::ExcludeSelection; |
86 | |
87 | FrameView::CoordinateSpaceForSnapshot coordinateSpace = FrameView::DocumentCoordinates; |
88 | if (options & SnapshotOptionsInViewCoordinates) |
89 | coordinateSpace = FrameView::ViewCoordinates; |
90 | |
91 | ScopedFramePaintingState state(frame, nullptr); |
92 | |
93 | auto paintBehavior = state.paintBehavior; |
94 | if (options & SnapshotOptionsForceBlackText) |
95 | paintBehavior.add(PaintBehavior::ForceBlackText); |
96 | if (options & SnapshotOptionsPaintSelectionOnly) |
97 | paintBehavior.add(PaintBehavior::SelectionOnly); |
98 | if (options & SnapshotOptionsPaintSelectionAndBackgroundsOnly) |
99 | paintBehavior.add(PaintBehavior::SelectionAndBackgroundsOnly); |
100 | if (options & SnapshotOptionsPaintEverythingExcludingSelection) |
101 | paintBehavior.add(PaintBehavior::ExcludeSelection); |
102 | |
103 | // Other paint behaviors are set by paintContentsForSnapshot. |
104 | frame.view()->setPaintBehavior(paintBehavior); |
105 | |
106 | float scaleFactor = frame.page()->deviceScaleFactor(); |
107 | |
108 | if (frame.settings().delegatesPageScaling()) |
109 | scaleFactor *= frame.page()->pageScaleFactor(); |
110 | |
111 | std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(imageRect.size(), Unaccelerated, scaleFactor); |
112 | if (!buffer) |
113 | return nullptr; |
114 | buffer->context().translate(-imageRect.x(), -imageRect.y()); |
115 | |
116 | if (!clipRects.isEmpty()) { |
117 | Path clipPath; |
118 | for (auto& rect : clipRects) |
119 | clipPath.addRect(rect); |
120 | buffer->context().clipPath(clipPath); |
121 | } |
122 | |
123 | frame.view()->paintContentsForSnapshot(buffer->context(), imageRect, shouldIncludeSelection, coordinateSpace); |
124 | return buffer; |
125 | } |
126 | |
127 | std::unique_ptr<ImageBuffer> snapshotSelection(Frame& frame, SnapshotOptions options) |
128 | { |
129 | auto& selection = frame.selection(); |
130 | |
131 | if (!selection.isRange()) |
132 | return nullptr; |
133 | |
134 | FloatRect selectionBounds = selection.selectionBounds(); |
135 | |
136 | // It is possible for the selection bounds to be empty; see https://bugs.webkit.org/show_bug.cgi?id=56645. |
137 | if (selectionBounds.isEmpty()) |
138 | return nullptr; |
139 | |
140 | options |= SnapshotOptionsPaintSelectionOnly; |
141 | return snapshotFrameRect(frame, enclosingIntRect(selectionBounds), options); |
142 | } |
143 | |
144 | std::unique_ptr<ImageBuffer> snapshotNode(Frame& frame, Node& node) |
145 | { |
146 | if (!node.renderer()) |
147 | return nullptr; |
148 | |
149 | ScopedFramePaintingState state(frame, &node); |
150 | |
151 | frame.view()->setBaseBackgroundColor(Color::transparent); |
152 | frame.view()->setNodeToDraw(&node); |
153 | |
154 | LayoutRect topLevelRect; |
155 | return snapshotFrameRect(frame, snappedIntRect(node.renderer()->paintingRootRect(topLevelRect))); |
156 | } |
157 | |
158 | } // namespace WebCore |
159 | |