[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / platform / graphics / nicosia / cairo / NicosiaPaintingContextCairo.cpp
1 /*
2  * Copyright (C) 2017 Metrological Group B.V.
3  * Copyright (C) 2017 Igalia S.L.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above
12  *    copyright notice, this list of conditions and the following
13  *    disclaimer in the documentation and/or other materials provided
14  *    with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "NicosiaPaintingContextCairo.h"
31
32 #if USE(CAIRO)
33
34 #include "GraphicsContext.h"
35 #include "GraphicsContextImplCairo.h"
36 #include "NicosiaBuffer.h"
37 #include "NicosiaCairoOperationRecorder.h"
38 #include "NicosiaPaintingOperationReplayCairo.h"
39 #include "PlatformContextCairo.h"
40 #include "RefPtrCairo.h"
41 #include <cairo.h>
42 #include <utility>
43
44 namespace Nicosia {
45
46 PaintingContextCairo::ForPainting::ForPainting(Buffer& buffer)
47 {
48     // Balanced by the deref in the s_bufferKey user data destroy callback.
49     buffer.ref();
50
51     m_cairo.surface = adoptRef(cairo_image_surface_create_for_data(buffer.data(),
52         CAIRO_FORMAT_ARGB32, buffer.size().width(), buffer.size().height(), buffer.stride()));
53
54     static cairo_user_data_key_t s_bufferKey;
55     cairo_surface_set_user_data(m_cairo.surface.get(), &s_bufferKey,
56         new std::pair<Buffer*, ForPainting*> { &buffer, this },
57         [](void* data)
58         {
59             auto* userData = static_cast<std::pair<Buffer*, ForPainting*>*>(data);
60
61             // Deref the Buffer object.
62             userData->first->deref();
63 #if !ASSERT_DISABLED
64             // Mark the deletion of the cairo_surface_t object associated with this
65             // PaintingContextCairo as complete. This way we check that the cairo_surface_t
66             // object doesn't outlive the PaintingContextCairo through which it was used.
67             userData->second->m_deletionComplete = true;
68 #endif
69             delete userData;
70         });
71
72     m_cairo.context = adoptRef(cairo_create(m_cairo.surface.get()));
73     m_platformContext = makeUnique<WebCore::PlatformContextCairo>(m_cairo.context.get());
74     m_graphicsContext = makeUnique<WebCore::GraphicsContext>(WebCore::GraphicsContextImplCairo::createFactory(*m_platformContext));
75 }
76
77 PaintingContextCairo::ForPainting::~ForPainting()
78 {
79     cairo_surface_flush(m_cairo.surface.get());
80
81     m_graphicsContext = nullptr;
82     m_platformContext = nullptr;
83     m_cairo.context = nullptr;
84     m_cairo.surface = nullptr;
85
86     // With all the Cairo references purged, the cairo_surface_t object should be destroyed
87     // as well. This is checked by asserting that m_deletionComplete is true, which should
88     // be the case if the s_bufferKey user data destroy callback has been invoked upon the
89     // cairo_surface_t destruction.
90     ASSERT(m_deletionComplete);
91 }
92
93 WebCore::GraphicsContext& PaintingContextCairo::ForPainting::graphicsContext()
94 {
95     return *m_graphicsContext;
96 }
97
98 void PaintingContextCairo::ForPainting::replay(const PaintingOperations& paintingOperations)
99 {
100     PaintingOperationReplayCairo operationReplay { *m_platformContext };
101     for (auto& operation : paintingOperations)
102         operation->execute(operationReplay);
103 }
104
105 PaintingContextCairo::ForRecording::ForRecording(PaintingOperations& paintingOperations)
106 {
107     m_graphicsContext = makeUnique<WebCore::GraphicsContext>(
108         [&paintingOperations](WebCore::GraphicsContext& context)
109         {
110             return makeUnique<CairoOperationRecorder>(context, paintingOperations);
111         });
112 }
113
114 PaintingContextCairo::ForRecording::~ForRecording() = default;
115
116 WebCore::GraphicsContext& PaintingContextCairo::ForRecording::graphicsContext()
117 {
118     return *m_graphicsContext;
119 }
120
121 void PaintingContextCairo::ForRecording::replay(const PaintingOperations&)
122 {
123     ASSERT_NOT_REACHED();
124 }
125
126 } // namespace Nicosia
127
128 #endif // USE(CAIRO)