d85147dc2cedf658848bdab76010a1b3f660290e
[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 "Frame.h"
36 #include "FrameSelection.h"
37 #include "FrameView.h"
38 #include "GraphicsContext.h"
39 #include "ImageBuffer.h"
40 #include "Page.h"
41 #include "RenderObject.h"
42 #include "Settings.h"
43
44 namespace WebCore {
45
46 struct ScopedFramePaintingState {
47     ScopedFramePaintingState(Frame& frame, Node* node)
48         : frame(frame)
49         , node(node)
50         , paintBehavior(frame.view()->paintBehavior())
51         , backgroundColor(frame.view()->baseBackgroundColor())
52     {
53         ASSERT(!node || node->renderer());
54     }
55
56     ~ScopedFramePaintingState()
57     {
58         frame.view()->setPaintBehavior(paintBehavior);
59         frame.view()->setBaseBackgroundColor(backgroundColor);
60         frame.view()->setNodeToDraw(nullptr);
61     }
62
63     const Frame& frame;
64     const Node* node;
65     const PaintBehavior paintBehavior;
66     const Color backgroundColor;
67 };
68
69 std::unique_ptr<ImageBuffer> snapshotFrameRect(Frame& frame, const IntRect& imageRect, SnapshotOptions options)
70 {
71     if (!frame.page())
72         return nullptr;
73
74     frame.document()->updateLayout();
75
76     FrameView::SelectionInSnapshot shouldIncludeSelection = FrameView::IncludeSelection;
77     if (options & SnapshotOptionsExcludeSelectionHighlighting)
78         shouldIncludeSelection = FrameView::ExcludeSelection;
79
80     FrameView::CoordinateSpaceForSnapshot coordinateSpace = FrameView::DocumentCoordinates;
81     if (options & SnapshotOptionsInViewCoordinates)
82         coordinateSpace = FrameView::ViewCoordinates;
83
84     ScopedFramePaintingState state(frame, nullptr);
85
86     PaintBehavior paintBehavior = state.paintBehavior;
87     if (options & SnapshotOptionsForceBlackText)
88         paintBehavior |= PaintBehaviorForceBlackText;
89     if (options & SnapshotOptionsPaintSelectionOnly)
90         paintBehavior |= PaintBehaviorSelectionOnly;
91     if (options & SnapshotOptionsPaintSelectionAndBackgroundsOnly)
92         paintBehavior |= PaintBehaviorSelectionAndBackgroundsOnly;
93
94     // Other paint behaviors are set by paintContentsForSnapshot.
95     frame.view()->setPaintBehavior(paintBehavior);
96
97     float scaleFactor = frame.page()->deviceScaleFactor();
98
99     if (frame.settings().delegatesPageScaling())
100         scaleFactor *= frame.page()->pageScaleFactor();
101
102     std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(imageRect.size(), scaleFactor, ColorSpaceDeviceRGB);
103     if (!buffer)
104         return nullptr;
105     buffer->context().translate(-imageRect.x(), -imageRect.y());
106
107     frame.view()->paintContentsForSnapshot(buffer->context(), imageRect, shouldIncludeSelection, coordinateSpace);
108     return buffer;
109 }
110
111 std::unique_ptr<ImageBuffer> snapshotSelection(Frame& frame, SnapshotOptions options)
112 {
113     auto& selection = frame.selection();
114
115     if (!selection.isRange())
116         return nullptr;
117
118     FloatRect selectionBounds = selection.selectionBounds();
119
120     // It is possible for the selection bounds to be empty; see https://bugs.webkit.org/show_bug.cgi?id=56645.
121     if (selectionBounds.isEmpty())
122         return nullptr;
123
124     options |= SnapshotOptionsPaintSelectionOnly;
125     return snapshotFrameRect(frame, enclosingIntRect(selectionBounds), options);
126 }
127
128 std::unique_ptr<ImageBuffer> snapshotNode(Frame& frame, Node& node)
129 {
130     if (!node.renderer())
131         return nullptr;
132
133     ScopedFramePaintingState state(frame, &node);
134
135     frame.view()->setBaseBackgroundColor(Color::transparent);
136     frame.view()->setNodeToDraw(&node);
137
138     LayoutRect topLevelRect;
139     return snapshotFrameRect(frame, snappedIntRect(node.renderer()->paintingRootRect(topLevelRect)));
140 }
141
142 } // namespace WebCore