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
43namespace WebCore {
44
45struct ScopedFramePaintingState {
46    ScopedFramePaintingState(Frame& frame, Node* node)
47        : frame(frame)
48        , node(node)
49        , paintBehavior(frame.view()->paintBehavior())
50        , backgroundColor(frame.view()->baseBackgroundColor())
51    {
52        ASSERT(!node || node->renderer());
53    }
54
55    ~ScopedFramePaintingState()
56    {
57        frame.view()->setPaintBehavior(paintBehavior);
58        frame.view()->setBaseBackgroundColor(backgroundColor);
59        frame.view()->setNodeToDraw(nullptr);
60    }
61
62    const Frame& frame;
63    const Node* node;
64    const PaintBehavior paintBehavior;
65    const Color backgroundColor;
66};
67
68std::unique_ptr<ImageBuffer> snapshotFrameRect(Frame& frame, const IntRect& imageRect, SnapshotOptions options)
69{
70    if (!frame.page())
71        return nullptr;
72
73    frame.document()->updateLayout();
74
75    FrameView::SelectionInSnapshot shouldIncludeSelection = FrameView::IncludeSelection;
76    if (options & SnapshotOptionsExcludeSelectionHighlighting)
77        shouldIncludeSelection = FrameView::ExcludeSelection;
78
79    FrameView::CoordinateSpaceForSnapshot coordinateSpace = FrameView::DocumentCoordinates;
80    if (options & SnapshotOptionsInViewCoordinates)
81        coordinateSpace = FrameView::ViewCoordinates;
82
83    ScopedFramePaintingState state(frame, nullptr);
84
85    PaintBehavior paintBehavior = state.paintBehavior;
86    if (options & SnapshotOptionsForceBlackText)
87        paintBehavior |= PaintBehaviorForceBlackText;
88    if (options & SnapshotOptionsPaintSelectionOnly)
89        paintBehavior |= PaintBehaviorSelectionOnly;
90
91    // Other paint behaviors are set by paintContentsForSnapshot.
92    frame.view()->setPaintBehavior(paintBehavior);
93
94    std::unique_ptr<ImageBuffer> buffer = ImageBuffer::create(imageRect.size(), frame.page()->deviceScaleFactor(), ColorSpaceDeviceRGB);
95    if (!buffer)
96        return nullptr;
97    buffer->context()->translate(-imageRect.x(), -imageRect.y());
98
99    frame.view()->paintContentsForSnapshot(buffer->context(), imageRect, shouldIncludeSelection, coordinateSpace);
100    return buffer;
101}
102
103std::unique_ptr<ImageBuffer> snapshotSelection(Frame& frame, SnapshotOptions options)
104{
105    if (!frame.selection().isRange())
106        return nullptr;
107
108    options |= SnapshotOptionsPaintSelectionOnly;
109    return snapshotFrameRect(frame, enclosingIntRect(frame.selection().selectionBounds()), options);
110}
111
112std::unique_ptr<ImageBuffer> snapshotNode(Frame& frame, Node& node)
113{
114    if (!node.renderer())
115        return nullptr;
116
117    ScopedFramePaintingState state(frame, &node);
118
119    frame.view()->setBaseBackgroundColor(Color::transparent);
120    frame.view()->setNodeToDraw(&node);
121
122    LayoutRect topLevelRect;
123    return snapshotFrameRect(frame, pixelSnappedIntRect(node.renderer()->paintingRootRect(topLevelRect)));
124}
125
126} // namespace WebCore
127