1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013 CERN
5  * Copyright (C) 2019-2020 KiCad Developers, see AUTHORS.txt for contributors.
6  * @author Maciej Suminski <maciej.suminski@cern.ch>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
24  */
25 
26 /**
27  * @file cairo_compositor.h
28  * Class that handles multitarget rendering (ie. to different textures/surfaces) and
29  * later compositing into a single image (Cairo flavour).
30  */
31 
32 #ifndef CAIRO_COMPOSITOR_H_
33 #define CAIRO_COMPOSITOR_H_
34 
35 #include <gal/compositor.h>
36 #include <gal/gal_display_options.h>
37 #include <cairo.h>
38 
39 #include <cstdint>
40 #include <deque>
41 
42 namespace KIGFX
43 {
44 class CAIRO_COMPOSITOR : public COMPOSITOR
45 {
46 public:
47     CAIRO_COMPOSITOR( cairo_t** aMainContext );
48     virtual ~CAIRO_COMPOSITOR();
49 
50     /// @copydoc COMPOSITOR::Initialize()
51     virtual void Initialize() override;
52 
53     /// @copydoc COMPOSITOR::Resize()
54     virtual void Resize( unsigned int aWidth, unsigned int aHeight ) override;
55 
56     /// @copydoc COMPOSITOR::CreateBuffer()
57     virtual unsigned int CreateBuffer() override;
58 
59     /// @copydoc COMPOSITOR::GetBuffer()
GetBuffer()60     inline virtual unsigned int GetBuffer() const override
61     {
62         return m_current + 1;
63     }
64 
65     /// @copydoc COMPOSITOR::SetBuffer()
66     virtual void SetBuffer( unsigned int aBufferHandle ) override;
67 
68     /// @copydoc COMPOSITOR::Begin()
69     virtual void Begin() override;
70 
71     /// @copydoc COMPOSITOR::ClearBuffer()
72     virtual void ClearBuffer( const COLOR4D& aColor ) override;
73 
74     /**
75      * Paints source to destination using the cairo operator. Useful for differential mode.
76      *
77      * @param aSourceHandle Source buffer to paint
78      * @param aDestHandle Destination buffer to paint on to
79      * @param op Painting operation
80      */
81     void DrawBuffer( unsigned int aSourceHandle, unsigned int aDestHandle, cairo_operator_t op );
82 
83     /// @copydoc COMPOSITOR::DrawBuffer()
84     virtual void DrawBuffer( unsigned int aBufferHandle ) override;
85 
86     /// @copydoc COMPOSITOR::Present()
87     virtual void Present() override;
88 
89     void SetAntialiasingMode( CAIRO_ANTIALIASING_MODE aMode ); // clears all buffers
GetAntialiasingMode()90     CAIRO_ANTIALIASING_MODE GetAntialiasingMode() const
91     {
92         switch( m_currentAntialiasingMode )
93         {
94         case CAIRO_ANTIALIAS_FAST:
95             return CAIRO_ANTIALIASING_MODE::FAST;
96         case CAIRO_ANTIALIAS_GOOD:
97             return CAIRO_ANTIALIASING_MODE::GOOD;
98         default:
99             return CAIRO_ANTIALIASING_MODE::NONE;
100         }
101     }
102 
103     /**
104      * Set a context to be treated as the main context (ie. as a target of buffers rendering and
105      * as a source of settings for newly created buffers).
106      *
107      * @param aMainContext is the context that should be treated as the main one.
108      */
SetMainContext(cairo_t * aMainContext)109     inline virtual void SetMainContext( cairo_t* aMainContext )
110     {
111         m_mainContext = aMainContext;
112 
113         // Use the context's transformation matrix
114         cairo_get_matrix( m_mainContext, &m_matrix );
115     }
116 
117 protected:
118     /**
119      * Perform freeing of resources.
120      */
121     void clean();
122 
123     /// Return number of currently used buffers.
usedBuffers()124     unsigned int usedBuffers()
125     {
126         return m_buffers.size();
127     }
128 
129     typedef uint32_t* BitmapPtr;
130     struct CAIRO_BUFFER
131     {
132         cairo_t*            context;        ///< Main texture handle
133         cairo_surface_t*    surface;        ///< Point to which an image from texture is attached
134         BitmapPtr           bitmap;         ///< Pixel storage
135     };
136 
137     unsigned int            m_current;      ///< Currently used buffer handle
138     typedef std::deque<CAIRO_BUFFER> CAIRO_BUFFERS;
139 
140     /// Pointer to the current context, so it can be changed
141     cairo_t**               m_currentContext;
142 
143     /// Rendering target used for compositing (the main display)
144     cairo_t*                m_mainContext;
145 
146     /// Transformation matrix
147     cairo_matrix_t          m_matrix;
148 
149     /// Stores information about initialized buffers
150     CAIRO_BUFFERS           m_buffers;
151 
152     unsigned int m_stride;              ///< Stride to use given the desired format and width
153     unsigned int m_bufferSize;          ///< Amount of memory needed to store a buffer
154 
155     cairo_antialias_t       m_currentAntialiasingMode;
156 };
157 } // namespace KIGFX
158 
159 #endif /* COMPOSITOR_H_ */
160