31d896daade722c91169e4244370171281d3d4ae
[WebKit-https.git] / Source / WebCore / page / FrameSnapshotting.cpp
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 |= PaintBehavior::ForceBlackText;
96     if (options & SnapshotOptionsPaintSelectionOnly)
97         paintBehavior |= PaintBehavior::SelectionOnly;
98     if (options & SnapshotOptionsPaintSelectionAndBackgroundsOnly)
99         paintBehavior |= PaintBehavior::SelectionAndBackgroundsOnly;
100     if (options & SnapshotOptionsPaintEverythingExcludingSelection)
101         paintBehavior |= 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