Commit 4076f993 authored by Maciej Suminski's avatar Maciej Suminski

Added a layer compositor for the Cairo backend.

parent 27113348
...@@ -50,6 +50,7 @@ set(GAL_SRCS ...@@ -50,6 +50,7 @@ set(GAL_SRCS
# Cairo GAL # Cairo GAL
gal/cairo/cairo_gal.cpp gal/cairo/cairo_gal.cpp
gal/cairo/cairo_compositor.cpp
) )
add_library(gal STATIC ${GAL_SRCS}) add_library(gal STATIC ${GAL_SRCS})
......
/*i
* 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>
using namespace KiGfx;
CAIRO_COMPOSITOR::CAIRO_COMPOSITOR( cairo_t** aMainContext ) :
m_current( 0 ), m_currentContext( aMainContext ), m_mainContext( *aMainContext )
{
// Obtain the transformation matrix used in the main context
cairo_get_matrix( m_mainContext, &m_matrix );
}
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;
}
unsigned int CAIRO_COMPOSITOR::GetBuffer()
{
// Pixel storage
BitmapPtr bitmap( new unsigned int[m_bufferSize] );
// 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 );
#ifdef __WXDEBUG__
cairo_status_t status = cairo_status( context );
wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, "Cairo context creation error" );
#endif /* __WXDEBUG__ */
// 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
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 )
{
if( aBufferHandle <= usedBuffers() )
{
m_current = aBufferHandle - 1;
*m_currentContext = m_buffers[m_current].context;
}
#ifdef __WXDEBUG__
else
wxLogDebug( wxT( "Tried to use a not existing buffer" ) );
#endif
}
void CAIRO_COMPOSITOR::ClearBuffer()
{
// Reset the transformation matrix, so it is possible to composite images using
// screen coordinates instead of world coordinates
cairo_identity_matrix( m_buffers[m_current].context );
cairo_set_source_rgba( m_buffers[m_current].context, 0.0, 0.0, 0.0, 0.0 );
cairo_rectangle( m_buffers[m_current].context, 0.0, 0.0, m_width, m_height );
cairo_fill( m_buffers[m_current].context );
// Restore the transformation matrix
cairo_set_matrix( m_buffers[m_current].context, &m_matrix );
}
void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
{
if( aBufferHandle <= usedBuffers() )
{
// Reset the transformation matrix, so it is possible to composite images using
// screen coordinates instead of world coordinates
cairo_identity_matrix( m_mainContext );
cairo_set_source_surface( m_mainContext, m_buffers[aBufferHandle - 1].surface, 0.0, 0.0 );
cairo_paint( m_mainContext );
// Restore the transformation matrix
cairo_set_matrix( m_mainContext, &m_matrix );
}
#ifdef __WXDEBUG__
else
wxLogDebug( wxT( "Tried to use a not existing buffer" ) );
#endif
}
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();
}
This diff is collapsed.
/*
* 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://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.h
* @brief Class that handles multitarget rendering (ie. to different textures/surfaces) and
* later compositing into a single image (Cairo flavour).
*/
#ifndef CAIRO_COMPOSITOR_H_
#define CAIRO_COMPOSITOR_H_
#include <gal/compositor.h>
#include <cairo.h>
#include <boost/smart_ptr/shared_array.hpp>
#include <deque>
namespace KiGfx
{
class CAIRO_COMPOSITOR : public COMPOSITOR
{
public:
CAIRO_COMPOSITOR( cairo_t** aMainContext );
virtual ~CAIRO_COMPOSITOR();
/// @copydoc COMPOSITOR::Initialize()
virtual void Initialize();
/// @copydoc COMPOSITOR::Resize()
virtual void Resize( unsigned int aWidth, unsigned int aHeight );
/// @copydoc COMPOSITOR::GetBuffer()
virtual unsigned int GetBuffer();
/// @copydoc COMPOSITOR::SetBuffer()
virtual void SetBuffer( unsigned int aBufferHandle );
/// @copydoc COMPOSITOR::ClearBuffer()
virtual void ClearBuffer();
/// @copydoc COMPOSITOR::DrawBuffer()
virtual void DrawBuffer( unsigned int aBufferHandle );
protected:
typedef boost::shared_array<unsigned int> BitmapPtr;
typedef struct
{
cairo_t* context; ///< Main texture handle
cairo_surface_t* surface; ///< Point to which an image from texture is attached
BitmapPtr bitmap; ///< Pixel storage
} CAIRO_BUFFER;
unsigned int m_current; ///< Currently used buffer handle
typedef std::deque<CAIRO_BUFFER> CAIRO_BUFFERS;
/// Pointer to the current context, so it can be changed
cairo_t** m_currentContext;
/// Rendering target used for compositing (the main display)
cairo_t* m_mainContext;
/// Transformation matrix
cairo_matrix_t m_matrix;
/// Stores information about initialized buffers
CAIRO_BUFFERS m_buffers;
unsigned int m_stride; ///< Stride to use given the desired format and width
unsigned int m_bufferSize; ///< Amount of memory needed to store a buffer
/**
* Function clean()
* performs freeing of resources.
*/
void clean();
/// Returns number of currently used buffers
unsigned int usedBuffers()
{
return m_buffers.size();
}
};
} // namespace KiGfx
#endif /* COMPOSITOR_H_ */
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include <cairo.h> #include <cairo.h>
#include <gal/graphics_abstraction_layer.h> #include <gal/graphics_abstraction_layer.h>
#include <boost/smart_ptr/shared_ptr.hpp>
#if defined(__WXMSW__) #if defined(__WXMSW__)
#define SCREEN_DEPTH 24 #define SCREEN_DEPTH 24
...@@ -62,6 +62,8 @@ ...@@ -62,6 +62,8 @@
*/ */
namespace KiGfx namespace KiGfx
{ {
class CAIRO_COMPOSITOR;
class CAIRO_GAL : public GAL, public wxWindow class CAIRO_GAL : public GAL, public wxWindow
{ {
public: public:
...@@ -81,7 +83,7 @@ public: ...@@ -81,7 +83,7 @@ public:
* @param aName is the name of this window for use by wxWindow::FindWindowByName() * @param aName is the name of this window for use by wxWindow::FindWindowByName()
*/ */
CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener = NULL, CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener = NULL,
wxEvtHandler* aPaintListener = NULL, const wxString& aName = wxT("CairoCanvas") ); wxEvtHandler* aPaintListener = NULL, const wxString& aName = wxT( "CairoCanvas" ) );
virtual ~CAIRO_GAL(); virtual ~CAIRO_GAL();
...@@ -299,11 +301,15 @@ private: ...@@ -299,11 +301,15 @@ private:
/// Super class definition /// Super class definition
typedef GAL super; typedef GAL super;
// Compositing variables
boost::shared_ptr<CAIRO_COMPOSITOR> compositor; ///< Object for layers compositing
unsigned int mainBuffer; ///< Handle to the main buffer
unsigned int overlayBuffer; ///< Handle to the overlay buffer
// Variables related to wxWidgets // Variables related to wxWidgets
wxWindow* parentWindow; ///< Parent window wxWindow* parentWindow; ///< Parent window
wxEvtHandler* mouseListener; ///< Mouse listener wxEvtHandler* mouseListener; ///< Mouse listener
wxEvtHandler* paintListener; ///< Paint listener wxEvtHandler* paintListener; ///< Paint listener
wxRect clientRectangle; ///< Area definition of the surface
unsigned int bufferSize; ///< Size of buffers cairoOutput, bitmapBuffers unsigned int bufferSize; ///< Size of buffers cairoOutput, bitmapBuffers
unsigned char* wxOutput; ///< wxImage comaptible buffer unsigned char* wxOutput; ///< wxImage comaptible buffer
...@@ -315,11 +321,6 @@ private: ...@@ -315,11 +321,6 @@ private:
wxBitmap* cursorPixelsSaved; ///< Saved cursor pixels wxBitmap* cursorPixelsSaved; ///< Saved cursor pixels
int cursorSize; ///< Cursor size int cursorSize; ///< Cursor size
// Variables for the grouping function
int actualGroupIndex; ///< The index of the actual group
bool isGrouping; ///< Is grouping enabled ?
bool isElementAdded; ///< Was an graphic element added ?
/// Maximum number of arguments for one command /// Maximum number of arguments for one command
static const int MAX_CAIRO_ARGUMENTS = 6; static const int MAX_CAIRO_ARGUMENTS = 6;
...@@ -352,6 +353,9 @@ private: ...@@ -352,6 +353,9 @@ private:
cairo_path_t* cairoPath; ///< Pointer to a Cairo path cairo_path_t* cairoPath; ///< Pointer to a Cairo path
} GroupElement; } GroupElement;
// Variables for the grouping function
bool isGrouping; ///< Is grouping enabled ?
bool isElementAdded; ///< Was an graphic element added ?
typedef std::deque<GroupElement> Group; ///< A graphic group type definition typedef std::deque<GroupElement> Group; ///< A graphic group type definition
std::map<int, Group> groups; ///< List of graphic groups std::map<int, Group> groups; ///< List of graphic groups
unsigned int groupCounter; ///< Counter used for generating keys for groups unsigned int groupCounter; ///< Counter used for generating keys for groups
...@@ -359,8 +363,9 @@ private: ...@@ -359,8 +363,9 @@ private:
// Variables related to Cairo <-> wxWidgets // Variables related to Cairo <-> wxWidgets
cairo_matrix_t cairoWorldScreenMatrix; ///< Cairo world to screen transformation matrix cairo_matrix_t cairoWorldScreenMatrix; ///< Cairo world to screen transformation matrix
cairo_t* cairoImage; ///< Cairo image cairo_t* currentContext; ///< Currently used Cairo context for drawing
cairo_surface_t* cairoSurface; ///< Cairo surface cairo_t* context; ///< Cairo image
cairo_surface_t* surface; ///< Cairo surface
unsigned int* bitmapBuffer; ///< Storage of the cairo image unsigned int* bitmapBuffer; ///< Storage of the cairo image
unsigned int* bitmapBufferBackup; ///< Backup storage of the cairo image unsigned int* bitmapBufferBackup; ///< Backup storage of the cairo image
int stride; ///< Stride value for Cairo int stride; ///< Stride value for Cairo
...@@ -400,15 +405,21 @@ private: ...@@ -400,15 +405,21 @@ private:
/// Prepare Cairo surfaces for drawing /// Prepare Cairo surfaces for drawing
void initSurface(); void initSurface();
// Destroy Cairo surfaces when are not needed anymore /// Destroy Cairo surfaces when are not needed anymore
void deinitSurface(); void deinitSurface();
/// Prepare the compositor
void setCompositor();
/** /**
* @brief Returns a valid key that can be used as a new group number. * @brief Returns a valid key that can be used as a new group number.
* *
* @return An unique group number that is not used by any other group. * @return An unique group number that is not used by any other group.
*/ */
unsigned int getNewGroupNumber(); unsigned int getNewGroupNumber();
/// Format used to store pixels
static const cairo_format_t GAL_FORMAT = CAIRO_FORMAT_RGB24;
}; };
} // namespace KiGfx } // namespace KiGfx
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment