KiCad PCB EDA Suite
cairo_compositor.cpp
Go to the documentation of this file.
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-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Maciej Suminski <[email protected]>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http:O//www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
34#include <wx/log.h>
35
36using namespace KIGFX;
37
38CAIRO_COMPOSITOR::CAIRO_COMPOSITOR( cairo_t** aMainContext ) :
39 m_current( 0 ),
40 m_currentContext( aMainContext ),
41 m_mainContext( *aMainContext ),
42 m_currentAntialiasingMode( CAIRO_ANTIALIAS_DEFAULT )
43{
44 // Do not have uninitialized members:
45 cairo_matrix_init_identity( &m_matrix );
46 m_stride = 0;
47 m_bufferSize = 0;
48}
49
50
52{
53 clean();
54}
55
56
58{
59 // Nothing has to be done
60}
61
62
64{
65 switch( aMode )
66 {
67 case CAIRO_ANTIALIASING_MODE::FAST: m_currentAntialiasingMode = CAIRO_ANTIALIAS_FAST; break;
68 case CAIRO_ANTIALIASING_MODE::GOOD: m_currentAntialiasingMode = CAIRO_ANTIALIAS_GOOD; break;
69 default: m_currentAntialiasingMode = CAIRO_ANTIALIAS_NONE;
70 }
71
72 clean();
73}
74
75
76void CAIRO_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight )
77{
78 clean();
79
80 m_width = aWidth;
81 m_height = aHeight;
82
83 m_stride = cairo_format_stride_for_width( CAIRO_FORMAT_ARGB32, m_width );
85}
86
87
89{
90 // Pixel storage
91 BitmapPtr bitmap = new uint32_t[m_bufferSize]();
92
93 // Create the Cairo surface
94 cairo_surface_t* surface = cairo_image_surface_create_for_data(
95 (unsigned char*) bitmap, CAIRO_FORMAT_ARGB32, m_width, m_height, m_stride );
96 cairo_t* context = cairo_create( surface );
97
98#ifdef DEBUG
99 cairo_status_t status = cairo_status( context );
100 wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, wxT( "Cairo context creation error" ) );
101#endif /* DEBUG */
102
103 // Set default settings for the buffer
104 cairo_set_antialias( context, m_currentAntialiasingMode );
105
106 // Use the same transformation matrix as the main context
107 cairo_get_matrix( m_mainContext, &m_matrix );
108 cairo_set_matrix( context, &m_matrix );
109
110 // Store the new buffer
111 CAIRO_BUFFER buffer = { context, surface, bitmap };
112 m_buffers.push_back( buffer );
113
114 return usedBuffers();
115}
116
117
118void CAIRO_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
119{
120 wxASSERT_MSG( aBufferHandle <= usedBuffers(), wxT( "Tried to use a not existing buffer" ) );
121
122 // Get currently used transformation matrix, so it can be applied to the new buffer
123 cairo_get_matrix( *m_currentContext, &m_matrix );
124
125 m_current = aBufferHandle - 1;
127
128 // Apply the current transformation matrix
129 cairo_set_matrix( *m_currentContext, &m_matrix );
130}
131
132
134{
135}
136
137
139{
140 // Clear the pixel storage
141 memset( m_buffers[m_current].bitmap, 0x00, m_bufferSize * sizeof( int ) );
142}
143
144
145void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aSourceHandle, unsigned int aDestHandle,
146 cairo_operator_t op )
147{
148 wxASSERT_MSG( aSourceHandle <= usedBuffers() && aDestHandle <= usedBuffers(),
149 wxT( "Tried to use a not existing buffer" ) );
150
151 // Reset the transformation matrix, so it is possible to composite images using
152 // screen coordinates instead of world coordinates
153 cairo_get_matrix( m_mainContext, &m_matrix );
154 cairo_identity_matrix( m_mainContext );
155
156 // Draw the selected buffer contents
157 cairo_t* ct = cairo_create( m_buffers[aDestHandle - 1].surface );
158 cairo_set_operator( ct, op );
159 cairo_set_source_surface( ct, m_buffers[aSourceHandle - 1].surface, 0.0, 0.0 );
160 cairo_paint( ct );
161 cairo_destroy( ct );
162
163 // Restore the transformation matrix
164 cairo_set_matrix( m_mainContext, &m_matrix );
165}
166
167
168void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
169{
170 wxASSERT_MSG( aBufferHandle <= usedBuffers(), wxT( "Tried to use a not existing buffer" ) );
171
172 // Reset the transformation matrix, so it is possible to composite images using
173 // screen coordinates instead of world coordinates
174 cairo_get_matrix( m_mainContext, &m_matrix );
175 cairo_identity_matrix( m_mainContext );
176
177 // Draw the selected buffer contents
178 cairo_set_source_surface( m_mainContext, m_buffers[aBufferHandle - 1].surface, 0.0, 0.0 );
179 cairo_paint( m_mainContext );
180
181 // Restore the transformation matrix
182 cairo_set_matrix( m_mainContext, &m_matrix );
183}
184
185
187{
188}
189
190
192{
193 CAIRO_BUFFERS::const_iterator it;
194
195 for( it = m_buffers.begin(); it != m_buffers.end(); ++it )
196 {
197 cairo_destroy( it->context );
198 cairo_surface_destroy( it->surface );
199 delete[] it->bitmap;
200 }
201
202 m_buffers.clear();
203}
Class that handles multitarget rendering (ie.
unsigned int m_bufferSize
Amount of memory needed to store a buffer.
virtual void Present() override
Call this to present the output buffer to the screen.
unsigned int m_stride
Stride to use given the desired format and width.
cairo_antialias_t m_currentAntialiasingMode
virtual unsigned int CreateBuffer() override
Prepare a new buffer that may be used as a rendering target.
cairo_t * m_mainContext
Rendering target used for compositing (the main display)
virtual void ClearBuffer(const COLOR4D &aColor) override
Clear the selected buffer (set by the SetBuffer() function).
virtual void Begin() override
Call this at the beginning of each frame.
void clean()
Perform freeing of resources.
void DrawBuffer(unsigned int aSourceHandle, unsigned int aDestHandle, cairo_operator_t op)
Paints source to destination using the cairo operator.
unsigned int usedBuffers()
Return number of currently used buffers.
cairo_matrix_t m_matrix
Transformation matrix.
cairo_t ** m_currentContext
Pointer to the current context, so it can be changed.
void SetAntialiasingMode(CAIRO_ANTIALIASING_MODE aMode)
unsigned int m_current
Currently used buffer handle.
CAIRO_BUFFERS m_buffers
Stores information about initialized buffers.
virtual void Resize(unsigned int aWidth, unsigned int aHeight) override
Clear the state of COMPOSITOR, so it has to be reinitialized again with the new dimensions.
virtual void SetBuffer(unsigned int aBufferHandle) override
Set the selected buffer as the rendering target.
virtual void Initialize() override
Perform primary initialization, necessary to use the object.
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
unsigned int m_height
Height of the buffer (in pixels)
Definition: compositor.h:113
unsigned int m_width
Width of the buffer (in pixels)
Definition: compositor.h:112
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:243