cairo_compositor.cpp 4.66 KB
Newer Older
1
/*
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2013 CERN
 * @author Maciej Suminski <maciej.suminski@cern.ch>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http:O//www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

/**
 * @file cairo_compositor.cpp
 * @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
 * later compositing into a single image (Cairo flavour).
 */

#include <gal/cairo/cairo_compositor.h>
#include <wx/log.h>

34
using namespace KIGFX;
35 36

CAIRO_COMPOSITOR::CAIRO_COMPOSITOR( cairo_t** aMainContext ) :
Maciej Suminski's avatar
Maciej Suminski committed
37
    m_current( 0 ), m_currentContext( aMainContext ), m_mainContext( *aMainContext )
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
{
}


CAIRO_COMPOSITOR::~CAIRO_COMPOSITOR()
{
    clean();
}


void CAIRO_COMPOSITOR::Initialize()
{
    // Nothing has to be done
}


void CAIRO_COMPOSITOR::Resize( unsigned int aWidth, unsigned int aHeight )
{
    clean();

    m_width  = aWidth;
    m_height = aHeight;

    m_stride     = cairo_format_stride_for_width( CAIRO_FORMAT_ARGB32, m_width );
    m_bufferSize = m_stride * m_height;
}


66
unsigned int CAIRO_COMPOSITOR::CreateBuffer()
67 68 69
{
    // Pixel storage
    BitmapPtr bitmap( new unsigned int[m_bufferSize] );
70

71
    memset( bitmap.get(), 0x00, m_bufferSize * sizeof(int) );
72 73 74 75 76 77 78

    // Create the Cairo surface
    cairo_surface_t* surface = cairo_image_surface_create_for_data(
                                                        (unsigned char*) bitmap.get(),
                                                        CAIRO_FORMAT_ARGB32, m_width,
                                                        m_height, m_stride );
    cairo_t* context = cairo_create( surface );
79 80
#ifdef __WXDEBUG__
    cairo_status_t status = cairo_status( context );
81
    wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, wxT( "Cairo context creation error" ) );
82
#endif /* __WXDEBUG__ */
83 84 85 86 87 88 89

    // Set default settings for the buffer
    cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL );
    cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND );
    cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );

    // Use the same transformation matrix as the main context
90
    cairo_get_matrix( m_mainContext, &m_matrix );
91 92 93 94 95 96 97 98 99 100 101 102
    cairo_set_matrix( context, &m_matrix );

    // Store the new buffer
    CAIRO_BUFFER buffer = { context, surface, bitmap };
    m_buffers.push_back( buffer );

    return usedBuffers();
}


void CAIRO_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
{
103
    wxASSERT_MSG( aBufferHandle <= usedBuffers(), wxT( "Tried to use a not existing buffer" ) );
Maciej Suminski's avatar
Maciej Suminski committed
104

105 106 107 108 109 110 111 112
    // Get currently used transformation matrix, so it can be applied to the new buffer
    cairo_get_matrix( *m_currentContext, &m_matrix );

    m_current = aBufferHandle - 1;
    *m_currentContext = m_buffers[m_current].context;

    // Apply the current transformation matrix
    cairo_set_matrix( *m_currentContext, &m_matrix );
113 114 115 116 117
}


void CAIRO_COMPOSITOR::ClearBuffer()
{
118 119
    // Clear the pixel storage
    memset( m_buffers[m_current].bitmap.get(), 0x00, m_bufferSize * sizeof(int) );
120 121 122 123 124
}


void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
{
125
    wxASSERT_MSG( aBufferHandle <= usedBuffers(), wxT( "Tried to use a not existing buffer" ) );
126

127 128 129 130
    // Reset the transformation matrix, so it is possible to composite images using
    // screen coordinates instead of world coordinates
    cairo_get_matrix( m_mainContext, &m_matrix );
    cairo_identity_matrix( m_mainContext );
131

132 133 134
    // Draw the selected buffer contents
    cairo_set_source_surface( m_mainContext, m_buffers[aBufferHandle - 1].surface, 0.0, 0.0 );
    cairo_paint( m_mainContext );
Maciej Suminski's avatar
Maciej Suminski committed
135

136 137
    // Restore the transformation matrix
    cairo_set_matrix( m_mainContext, &m_matrix );
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
}


void CAIRO_COMPOSITOR::clean()
{
    CAIRO_BUFFERS::const_iterator it;

    for( it = m_buffers.begin(); it != m_buffers.end(); ++it )
    {
        cairo_destroy( it->context );
        cairo_surface_destroy( it->surface );
    }

    m_buffers.clear();
}