Added a layer compositor for the Cairo backend.
This commit is contained in:
parent
27113348b9
commit
4076f99332
|
@ -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})
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*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();
|
||||||
|
}
|
|
@ -29,6 +29,7 @@
|
||||||
#include <wx/log.h>
|
#include <wx/log.h>
|
||||||
|
|
||||||
#include <gal/cairo/cairo_gal.h>
|
#include <gal/cairo/cairo_gal.h>
|
||||||
|
#include <gal/cairo/cairo_compositor.h>
|
||||||
#include <gal/definitions.h>
|
#include <gal/definitions.h>
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
@ -89,13 +90,12 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
|
||||||
CAIRO_GAL::~CAIRO_GAL()
|
CAIRO_GAL::~CAIRO_GAL()
|
||||||
{
|
{
|
||||||
deinitSurface();
|
deinitSurface();
|
||||||
|
deleteBitmaps();
|
||||||
|
|
||||||
delete cursorPixels;
|
delete cursorPixels;
|
||||||
delete cursorPixelsSaved;
|
delete cursorPixelsSaved;
|
||||||
|
|
||||||
ClearCache();
|
ClearCache();
|
||||||
|
|
||||||
deleteBitmaps();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,11 +107,10 @@ void CAIRO_GAL::onPaint( wxPaintEvent& aEvent )
|
||||||
|
|
||||||
void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight )
|
void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight )
|
||||||
{
|
{
|
||||||
deleteBitmaps();
|
|
||||||
|
|
||||||
screenSize = VECTOR2D( aWidth, aHeight );
|
screenSize = VECTOR2D( aWidth, aHeight );
|
||||||
|
|
||||||
// Recreate the bitmaps
|
// Recreate the bitmaps
|
||||||
|
deleteBitmaps();
|
||||||
allocateBitmaps();
|
allocateBitmaps();
|
||||||
|
|
||||||
SetSize( wxSize( aWidth, aHeight ) );
|
SetSize( wxSize( aWidth, aHeight ) );
|
||||||
|
@ -128,28 +127,19 @@ void CAIRO_GAL::skipMouseEvent( wxMouseEvent& aEvent )
|
||||||
|
|
||||||
void CAIRO_GAL::initSurface()
|
void CAIRO_GAL::initSurface()
|
||||||
{
|
{
|
||||||
if( isInitialized )
|
wxASSERT( !isInitialized );
|
||||||
return;
|
|
||||||
|
|
||||||
// The size of the client area needs to be greater than zero
|
|
||||||
clientRectangle = parentWindow->GetClientRect();
|
|
||||||
|
|
||||||
if( clientRectangle.width == 0 || clientRectangle.height == 0 )
|
|
||||||
throw EXCEPTION_ZERO_CLIENT_RECTANGLE;
|
|
||||||
|
|
||||||
// Create the Cairo surface
|
// Create the Cairo surface
|
||||||
cairoSurface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer,
|
surface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer, GAL_FORMAT,
|
||||||
CAIRO_FORMAT_RGB24, clientRectangle.width,
|
screenSize.x, screenSize.y, stride );
|
||||||
clientRectangle.height, stride );
|
context = cairo_create( surface );
|
||||||
cairoImage = cairo_create( cairoSurface );
|
|
||||||
#ifdef __WXDEBUG__
|
#ifdef __WXDEBUG__
|
||||||
cairo_status_t status = cairo_status( cairoImage );
|
cairo_status_t status = cairo_status( context );
|
||||||
wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, "Cairo context creation error" );
|
wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, "Cairo context creation error" );
|
||||||
#endif /* __WXDEBUG__ */
|
#endif /* __WXDEBUG__ */
|
||||||
|
currentContext = context;
|
||||||
|
|
||||||
// -----------------------------------------------------------------
|
cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL );
|
||||||
|
|
||||||
cairo_set_antialias( cairoImage, CAIRO_ANTIALIAS_SUBPIXEL );
|
|
||||||
|
|
||||||
// Clear the screen
|
// Clear the screen
|
||||||
ClearScreen();
|
ClearScreen();
|
||||||
|
@ -162,21 +152,20 @@ void CAIRO_GAL::initSurface()
|
||||||
worldScreenMatrix.m_data[1][1], worldScreenMatrix.m_data[0][2],
|
worldScreenMatrix.m_data[1][1], worldScreenMatrix.m_data[0][2],
|
||||||
worldScreenMatrix.m_data[1][2] );
|
worldScreenMatrix.m_data[1][2] );
|
||||||
|
|
||||||
cairo_set_matrix( cairoImage, &cairoWorldScreenMatrix );
|
cairo_set_matrix( context, &cairoWorldScreenMatrix );
|
||||||
|
|
||||||
isSetAttributes = false;
|
isSetAttributes = false;
|
||||||
|
|
||||||
// Start drawing with a new path
|
// Start drawing with a new path
|
||||||
cairo_new_path( cairoImage );
|
cairo_new_path( context );
|
||||||
isElementAdded = true;
|
isElementAdded = true;
|
||||||
|
|
||||||
cairo_set_line_join( cairoImage, CAIRO_LINE_JOIN_ROUND );
|
cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND );
|
||||||
cairo_set_line_cap( cairoImage, CAIRO_LINE_CAP_ROUND );
|
cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );
|
||||||
|
|
||||||
lineWidth = 0;
|
lineWidth = 0;
|
||||||
|
|
||||||
isDeleteSavedPixels = true;
|
isDeleteSavedPixels = true;
|
||||||
|
|
||||||
isInitialized = true;
|
isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,13 +176,25 @@ void CAIRO_GAL::deinitSurface()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Destroy Cairo objects
|
// Destroy Cairo objects
|
||||||
cairo_destroy( cairoImage );
|
cairo_destroy( context );
|
||||||
cairo_surface_destroy( cairoSurface );
|
cairo_surface_destroy( surface );
|
||||||
|
|
||||||
isInitialized = false;
|
isInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CAIRO_GAL::setCompositor()
|
||||||
|
{
|
||||||
|
// Recreate the compositor with the new Cairo context
|
||||||
|
compositor.reset( new CAIRO_COMPOSITOR( ¤tContext ) );
|
||||||
|
compositor->Resize( screenSize.x, screenSize.y );
|
||||||
|
|
||||||
|
// Prepare buffers
|
||||||
|
mainBuffer = compositor->GetBuffer();
|
||||||
|
overlayBuffer = compositor->GetBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
unsigned int CAIRO_GAL::getNewGroupNumber()
|
unsigned int CAIRO_GAL::getNewGroupNumber()
|
||||||
{
|
{
|
||||||
wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(),
|
wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(),
|
||||||
|
@ -211,8 +212,10 @@ unsigned int CAIRO_GAL::getNewGroupNumber()
|
||||||
void CAIRO_GAL::BeginDrawing() throw( int )
|
void CAIRO_GAL::BeginDrawing() throw( int )
|
||||||
{
|
{
|
||||||
initSurface();
|
initSurface();
|
||||||
|
setCompositor();
|
||||||
|
|
||||||
cairo_push_group( cairoImage );
|
// Cairo grouping prevents display of overlapping items on the same layer in the lighter color
|
||||||
|
cairo_push_group( currentContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -221,13 +224,18 @@ void CAIRO_GAL::EndDrawing()
|
||||||
// Force remaining objects to be drawn
|
// Force remaining objects to be drawn
|
||||||
Flush();
|
Flush();
|
||||||
|
|
||||||
cairo_pop_group_to_source( cairoImage );
|
// Cairo grouping prevents display of overlapping items on the same layer in the lighter color
|
||||||
cairo_paint_with_alpha( cairoImage, fillColor.a );
|
cairo_pop_group_to_source( currentContext );
|
||||||
|
cairo_paint_with_alpha( currentContext, fillColor.a );
|
||||||
|
|
||||||
|
// Merge buffers on the screen
|
||||||
|
compositor->DrawBuffer( mainBuffer );
|
||||||
|
compositor->DrawBuffer( overlayBuffer );
|
||||||
|
|
||||||
// This code was taken from the wxCairo example - it's not the most efficient one
|
// This code was taken from the wxCairo example - it's not the most efficient one
|
||||||
// Here is a good place for optimizations
|
// Here is a good place for optimizations
|
||||||
|
|
||||||
// Now translate the raw image data from the format stored
|
// Now translate the raw context data from the format stored
|
||||||
// by cairo into a format understood by wxImage.
|
// by cairo into a format understood by wxImage.
|
||||||
unsigned char* wxOutputPtr = wxOutput;
|
unsigned char* wxOutputPtr = wxOutput;
|
||||||
|
|
||||||
|
@ -282,14 +290,36 @@ void CAIRO_GAL::RestoreScreen()
|
||||||
|
|
||||||
void CAIRO_GAL::SetTarget( RenderTarget aTarget )
|
void CAIRO_GAL::SetTarget( RenderTarget aTarget )
|
||||||
{
|
{
|
||||||
wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
|
// If the compositor is not set, that means that there is a recaching process going on
|
||||||
|
// and we do not need the compositor now
|
||||||
|
if( !compositor )
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Cairo grouping prevents display of overlapping items on the same layer in the lighter color
|
||||||
|
cairo_pop_group_to_source( currentContext );
|
||||||
|
cairo_paint_with_alpha( currentContext, fillColor.a );
|
||||||
|
|
||||||
|
switch( aTarget )
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case TARGET_CACHED:
|
||||||
|
case TARGET_NONCACHED:
|
||||||
|
compositor->SetBuffer( mainBuffer );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TARGET_OVERLAY:
|
||||||
|
compositor->SetBuffer( overlayBuffer );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_push_group( currentContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CAIRO_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
void CAIRO_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
||||||
{
|
{
|
||||||
cairo_move_to( cairoImage, aStartPoint.x, aStartPoint.y );
|
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
|
||||||
cairo_line_to( cairoImage, aEndPoint.x, aEndPoint.y );
|
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
|
||||||
isElementAdded = true;
|
isElementAdded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,32 +329,34 @@ void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPo
|
||||||
{
|
{
|
||||||
if( isFillEnabled )
|
if( isFillEnabled )
|
||||||
{
|
{
|
||||||
|
// Filled tracks mode
|
||||||
SetLineWidth( aWidth );
|
SetLineWidth( aWidth );
|
||||||
|
|
||||||
cairo_move_to( cairoImage, (double) aStartPoint.x, (double) aStartPoint.y );
|
cairo_move_to( currentContext, (double) aStartPoint.x, (double) aStartPoint.y );
|
||||||
cairo_line_to( cairoImage, (double) aEndPoint.x, (double) aEndPoint.y );
|
cairo_line_to( currentContext, (double) aEndPoint.x, (double) aEndPoint.y );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Outline mode for tracks
|
||||||
VECTOR2D startEndVector = aEndPoint - aStartPoint;
|
VECTOR2D startEndVector = aEndPoint - aStartPoint;
|
||||||
double lineAngle = atan2( startEndVector.y, startEndVector.x );
|
double lineAngle = atan2( startEndVector.y, startEndVector.x );
|
||||||
double lineLength = startEndVector.EuclideanNorm();
|
double lineLength = startEndVector.EuclideanNorm();
|
||||||
|
|
||||||
cairo_save( cairoImage );
|
cairo_save( currentContext );
|
||||||
|
|
||||||
cairo_translate( cairoImage, aStartPoint.x, aStartPoint.y );
|
cairo_translate( currentContext, aStartPoint.x, aStartPoint.y );
|
||||||
cairo_rotate( cairoImage, lineAngle );
|
cairo_rotate( currentContext, lineAngle );
|
||||||
|
|
||||||
cairo_arc( cairoImage, 0.0, 0.0, aWidth / 2.0, M_PI / 2.0, 3.0 * M_PI / 2.0 );
|
cairo_arc( currentContext, 0.0, 0.0, aWidth / 2.0, M_PI / 2.0, 3.0 * M_PI / 2.0 );
|
||||||
cairo_arc( cairoImage, lineLength, 0.0, aWidth / 2.0, -M_PI / 2.0, M_PI / 2.0 );
|
cairo_arc( currentContext, lineLength, 0.0, aWidth / 2.0, -M_PI / 2.0, M_PI / 2.0 );
|
||||||
|
|
||||||
cairo_move_to( cairoImage, 0.0, aWidth / 2.0 );
|
cairo_move_to( currentContext, 0.0, aWidth / 2.0 );
|
||||||
cairo_line_to( cairoImage, lineLength, aWidth / 2.0 );
|
cairo_line_to( currentContext, lineLength, aWidth / 2.0 );
|
||||||
|
|
||||||
cairo_move_to( cairoImage, 0.0, -aWidth / 2.0 );
|
cairo_move_to( currentContext, 0.0, -aWidth / 2.0 );
|
||||||
cairo_line_to( cairoImage, lineLength, -aWidth / 2.0 );
|
cairo_line_to( currentContext, lineLength, -aWidth / 2.0 );
|
||||||
|
|
||||||
cairo_restore( cairoImage );
|
cairo_restore( currentContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
isElementAdded = true;
|
isElementAdded = true;
|
||||||
|
@ -334,8 +366,8 @@ void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPo
|
||||||
void CAIRO_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
void CAIRO_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
||||||
{
|
{
|
||||||
// A circle is drawn using an arc
|
// A circle is drawn using an arc
|
||||||
cairo_new_sub_path( cairoImage );
|
cairo_new_sub_path( currentContext );
|
||||||
cairo_arc( cairoImage, aCenterPoint.x, aCenterPoint.y, aRadius, 0.0, 2 * M_PI );
|
cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, 0.0, 2 * M_PI );
|
||||||
|
|
||||||
isElementAdded = true;
|
isElementAdded = true;
|
||||||
}
|
}
|
||||||
|
@ -346,8 +378,8 @@ void CAIRO_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aS
|
||||||
{
|
{
|
||||||
SWAP( aStartAngle, >, aEndAngle );
|
SWAP( aStartAngle, >, aEndAngle );
|
||||||
|
|
||||||
cairo_new_sub_path( cairoImage );
|
cairo_new_sub_path( currentContext );
|
||||||
cairo_arc( cairoImage, aCenterPoint.x, aCenterPoint.y, aRadius, aStartAngle, aEndAngle );
|
cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, aStartAngle, aEndAngle );
|
||||||
|
|
||||||
isElementAdded = true;
|
isElementAdded = true;
|
||||||
}
|
}
|
||||||
|
@ -355,21 +387,13 @@ void CAIRO_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aS
|
||||||
|
|
||||||
void CAIRO_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
|
void CAIRO_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
|
||||||
{
|
{
|
||||||
bool isFirstPoint = true;
|
|
||||||
|
|
||||||
// Iterate over the point list and draw the segments
|
// Iterate over the point list and draw the segments
|
||||||
std::deque<VECTOR2D>::const_iterator it;
|
std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
|
||||||
for( it = aPointList.begin(); it != aPointList.end(); ++it )
|
|
||||||
|
cairo_move_to( currentContext, it->x, it->y );
|
||||||
|
for( ++it; it != aPointList.end(); ++it )
|
||||||
{
|
{
|
||||||
if( isFirstPoint )
|
cairo_line_to( currentContext, it->x, it->y );
|
||||||
{
|
|
||||||
cairo_move_to( cairoImage, it->x, it->y );
|
|
||||||
isFirstPoint = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cairo_line_to( cairoImage, it->x, it->y );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isElementAdded = true;
|
isElementAdded = true;
|
||||||
|
@ -378,21 +402,13 @@ void CAIRO_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
|
||||||
|
|
||||||
void CAIRO_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
|
void CAIRO_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
|
||||||
{
|
{
|
||||||
bool isFirstPoint = true;
|
|
||||||
|
|
||||||
// Iterate over the point list and draw the polygon
|
// Iterate over the point list and draw the polygon
|
||||||
std::deque<VECTOR2D>::const_iterator it;
|
std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
|
||||||
for( it = aPointList.begin(); it != aPointList.end(); ++it )
|
|
||||||
|
cairo_move_to( currentContext, it->x, it->y );
|
||||||
|
for( ++it; it != aPointList.end(); ++it )
|
||||||
{
|
{
|
||||||
if( isFirstPoint )
|
cairo_line_to( currentContext, it->x, it->y );
|
||||||
{
|
|
||||||
cairo_move_to( cairoImage, it->x, it->y );
|
|
||||||
isFirstPoint = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
cairo_line_to( cairoImage, it->x, it->y );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isElementAdded = true;
|
isElementAdded = true;
|
||||||
|
@ -406,11 +422,11 @@ void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
|
||||||
VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y );
|
VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y );
|
||||||
|
|
||||||
// The path is composed from 4 segments
|
// The path is composed from 4 segments
|
||||||
cairo_move_to( cairoImage, aStartPoint.x, aStartPoint.y );
|
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
|
||||||
cairo_line_to( cairoImage, diagonalPointA.x, diagonalPointA.y );
|
cairo_line_to( currentContext, diagonalPointA.x, diagonalPointA.y );
|
||||||
cairo_line_to( cairoImage, aEndPoint.x, aEndPoint.y );
|
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
|
||||||
cairo_line_to( cairoImage, diagonalPointB.x, diagonalPointB.y );
|
cairo_line_to( currentContext, diagonalPointB.x, diagonalPointB.y );
|
||||||
cairo_close_path( cairoImage );
|
cairo_close_path( currentContext );
|
||||||
|
|
||||||
isElementAdded = true;
|
isElementAdded = true;
|
||||||
}
|
}
|
||||||
|
@ -419,10 +435,11 @@ void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
|
||||||
void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA,
|
void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA,
|
||||||
const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint )
|
const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint )
|
||||||
{
|
{
|
||||||
cairo_move_to( cairoImage, aStartPoint.x, aStartPoint.y );
|
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
|
||||||
cairo_curve_to( cairoImage, aControlPointA.x, aControlPointA.y, aControlPointB.x,
|
cairo_curve_to( currentContext, aControlPointA.x, aControlPointA.y, aControlPointB.x,
|
||||||
aControlPointB.y, aEndPoint.x, aEndPoint.y );
|
aControlPointB.y, aEndPoint.x, aEndPoint.y );
|
||||||
cairo_line_to( cairoImage, aEndPoint.x, aEndPoint.y );
|
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
|
||||||
|
|
||||||
isElementAdded = true;
|
isElementAdded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -466,7 +483,6 @@ void CAIRO_GAL::SetIsStroke( bool aIsStrokeEnabled )
|
||||||
void CAIRO_GAL::SetStrokeColor( const COLOR4D& aColor )
|
void CAIRO_GAL::SetStrokeColor( const COLOR4D& aColor )
|
||||||
{
|
{
|
||||||
storePath();
|
storePath();
|
||||||
|
|
||||||
strokeColor = aColor;
|
strokeColor = aColor;
|
||||||
|
|
||||||
if( isGrouping )
|
if( isGrouping )
|
||||||
|
@ -506,12 +522,6 @@ void CAIRO_GAL::SetLineWidth( double aLineWidth )
|
||||||
|
|
||||||
lineWidth = aLineWidth;
|
lineWidth = aLineWidth;
|
||||||
|
|
||||||
// Make lines appear at least 1 pixel wide, no matter of zoom
|
|
||||||
double x = 1.0, y = 1.0;
|
|
||||||
cairo_device_to_user_distance( cairoImage, &x, &y );
|
|
||||||
double minWidth = std::min( fabs( x ), fabs( y ) );
|
|
||||||
cairo_set_line_width( cairoImage, std::max( aLineWidth, minWidth ) );
|
|
||||||
|
|
||||||
if( isGrouping )
|
if( isGrouping )
|
||||||
{
|
{
|
||||||
GroupElement groupElement;
|
GroupElement groupElement;
|
||||||
|
@ -519,16 +529,23 @@ void CAIRO_GAL::SetLineWidth( double aLineWidth )
|
||||||
groupElement.arguments[0] = aLineWidth;
|
groupElement.arguments[0] = aLineWidth;
|
||||||
currentGroup->push_back( groupElement );
|
currentGroup->push_back( groupElement );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Make lines appear at least 1 pixel wide, no matter of zoom
|
||||||
|
double x = 1.0, y = 1.0;
|
||||||
|
cairo_device_to_user_distance( currentContext, &x, &y );
|
||||||
|
double minWidth = std::min( fabs( x ), fabs( y ) );
|
||||||
|
cairo_set_line_width( currentContext, std::max( aLineWidth, minWidth ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CAIRO_GAL::ClearScreen()
|
void CAIRO_GAL::ClearScreen()
|
||||||
{
|
{
|
||||||
// Clear screen
|
cairo_set_source_rgb( currentContext,
|
||||||
cairo_set_source_rgba( cairoImage,
|
backgroundColor.r, backgroundColor.g, backgroundColor.b );
|
||||||
backgroundColor.r, backgroundColor.g, backgroundColor.b, 1.0 );
|
cairo_rectangle( currentContext, 0.0, 0.0, screenSize.x, screenSize.y );
|
||||||
cairo_rectangle( cairoImage, 0.0, 0.0, screenSize.x, screenSize.y );
|
cairo_fill( currentContext );
|
||||||
cairo_fill( cairoImage );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -540,10 +557,10 @@ void CAIRO_GAL::SetLayerDepth( double aLayerDepth )
|
||||||
{
|
{
|
||||||
storePath();
|
storePath();
|
||||||
|
|
||||||
cairo_pop_group_to_source( cairoImage );
|
// cairo_pop_group_to_source( currentContext );
|
||||||
cairo_paint_with_alpha( cairoImage, fillColor.a );
|
// cairo_paint_with_alpha( currentContext, fillColor.a );
|
||||||
|
//
|
||||||
cairo_push_group( cairoImage );
|
// cairo_push_group( currentContext );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -560,7 +577,7 @@ void CAIRO_GAL::Transform( MATRIX3x3D aTransformation )
|
||||||
aTransformation.m_data[0][2],
|
aTransformation.m_data[0][2],
|
||||||
aTransformation.m_data[1][2] );
|
aTransformation.m_data[1][2] );
|
||||||
|
|
||||||
cairo_transform( cairoImage, &cairoTransformation );
|
cairo_transform( currentContext, &cairoTransformation );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -568,8 +585,6 @@ void CAIRO_GAL::Rotate( double aAngle )
|
||||||
{
|
{
|
||||||
storePath();
|
storePath();
|
||||||
|
|
||||||
cairo_rotate( cairoImage, aAngle );
|
|
||||||
|
|
||||||
if( isGrouping )
|
if( isGrouping )
|
||||||
{
|
{
|
||||||
GroupElement groupElement;
|
GroupElement groupElement;
|
||||||
|
@ -577,6 +592,10 @@ void CAIRO_GAL::Rotate( double aAngle )
|
||||||
groupElement.arguments[0] = aAngle;
|
groupElement.arguments[0] = aAngle;
|
||||||
currentGroup->push_back( groupElement );
|
currentGroup->push_back( groupElement );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cairo_rotate( currentContext, aAngle );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -584,8 +603,6 @@ void CAIRO_GAL::Translate( const VECTOR2D& aTranslation )
|
||||||
{
|
{
|
||||||
storePath();
|
storePath();
|
||||||
|
|
||||||
cairo_translate( cairoImage, aTranslation.x, aTranslation.y );
|
|
||||||
|
|
||||||
if( isGrouping )
|
if( isGrouping )
|
||||||
{
|
{
|
||||||
GroupElement groupElement;
|
GroupElement groupElement;
|
||||||
|
@ -594,6 +611,10 @@ void CAIRO_GAL::Translate( const VECTOR2D& aTranslation )
|
||||||
groupElement.arguments[1] = aTranslation.y;
|
groupElement.arguments[1] = aTranslation.y;
|
||||||
currentGroup->push_back( groupElement );
|
currentGroup->push_back( groupElement );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cairo_translate( currentContext, aTranslation.x, aTranslation.y );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -601,8 +622,6 @@ void CAIRO_GAL::Scale( const VECTOR2D& aScale )
|
||||||
{
|
{
|
||||||
storePath();
|
storePath();
|
||||||
|
|
||||||
cairo_scale( cairoImage, aScale.x, aScale.y );
|
|
||||||
|
|
||||||
if( isGrouping )
|
if( isGrouping )
|
||||||
{
|
{
|
||||||
GroupElement groupElement;
|
GroupElement groupElement;
|
||||||
|
@ -611,6 +630,10 @@ void CAIRO_GAL::Scale( const VECTOR2D& aScale )
|
||||||
groupElement.arguments[1] = aScale.y;
|
groupElement.arguments[1] = aScale.y;
|
||||||
currentGroup->push_back( groupElement );
|
currentGroup->push_back( groupElement );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cairo_scale( currentContext, aScale.x, aScale.y );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -618,14 +641,16 @@ void CAIRO_GAL::Save()
|
||||||
{
|
{
|
||||||
storePath();
|
storePath();
|
||||||
|
|
||||||
cairo_save( cairoImage );
|
|
||||||
|
|
||||||
if( isGrouping )
|
if( isGrouping )
|
||||||
{
|
{
|
||||||
GroupElement groupElement;
|
GroupElement groupElement;
|
||||||
groupElement.command = CMD_SAVE;
|
groupElement.command = CMD_SAVE;
|
||||||
currentGroup->push_back( groupElement );
|
currentGroup->push_back( groupElement );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cairo_save( currentContext );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -633,14 +658,16 @@ void CAIRO_GAL::Restore()
|
||||||
{
|
{
|
||||||
storePath();
|
storePath();
|
||||||
|
|
||||||
cairo_restore( cairoImage );
|
|
||||||
|
|
||||||
if( isGrouping )
|
if( isGrouping )
|
||||||
{
|
{
|
||||||
GroupElement groupElement;
|
GroupElement groupElement;
|
||||||
groupElement.command = CMD_RESTORE;
|
groupElement.command = CMD_RESTORE;
|
||||||
currentGroup->push_back( groupElement );
|
currentGroup->push_back( groupElement );
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cairo_restore( currentContext );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -734,50 +761,50 @@ void CAIRO_GAL::DrawGroup( int aGroupNumber )
|
||||||
{
|
{
|
||||||
// Make lines appear at least 1 pixel wide, no matter of zoom
|
// Make lines appear at least 1 pixel wide, no matter of zoom
|
||||||
double x = 1.0, y = 1.0;
|
double x = 1.0, y = 1.0;
|
||||||
cairo_device_to_user_distance( cairoImage, &x, &y );
|
cairo_device_to_user_distance( currentContext, &x, &y );
|
||||||
double minWidth = std::min( fabs( x ), fabs( y ) );
|
double minWidth = std::min( fabs( x ), fabs( y ) );
|
||||||
cairo_set_line_width( cairoImage, std::max( it->arguments[0], minWidth ) );
|
cairo_set_line_width( currentContext, std::max( it->arguments[0], minWidth ) );
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case CMD_STROKE_PATH:
|
case CMD_STROKE_PATH:
|
||||||
cairo_set_source_rgb( cairoImage, strokeColor.r, strokeColor.g, strokeColor.b );
|
cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g, strokeColor.b );
|
||||||
cairo_append_path( cairoImage, it->cairoPath );
|
cairo_append_path( currentContext, it->cairoPath );
|
||||||
cairo_stroke( cairoImage );
|
cairo_stroke( currentContext );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_FILL_PATH:
|
case CMD_FILL_PATH:
|
||||||
cairo_set_source_rgb( cairoImage, fillColor.r, fillColor.g, fillColor.b );
|
cairo_set_source_rgb( currentContext, fillColor.r, fillColor.g, fillColor.b );
|
||||||
cairo_append_path( cairoImage, it->cairoPath );
|
cairo_append_path( currentContext, it->cairoPath );
|
||||||
cairo_fill( cairoImage );
|
cairo_fill( currentContext );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_TRANSFORM:
|
case CMD_TRANSFORM:
|
||||||
cairo_matrix_t matrix;
|
cairo_matrix_t matrix;
|
||||||
cairo_matrix_init( &matrix, it->arguments[0], it->arguments[1], it->arguments[2],
|
cairo_matrix_init( &matrix, it->arguments[0], it->arguments[1], it->arguments[2],
|
||||||
it->arguments[3], it->arguments[4], it->arguments[5] );
|
it->arguments[3], it->arguments[4], it->arguments[5] );
|
||||||
cairo_transform( cairoImage, &matrix );
|
cairo_transform( currentContext, &matrix );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_ROTATE:
|
case CMD_ROTATE:
|
||||||
cairo_rotate( cairoImage, it->arguments[0] );
|
cairo_rotate( currentContext, it->arguments[0] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_TRANSLATE:
|
case CMD_TRANSLATE:
|
||||||
cairo_translate( cairoImage, it->arguments[0], it->arguments[1] );
|
cairo_translate( currentContext, it->arguments[0], it->arguments[1] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_SCALE:
|
case CMD_SCALE:
|
||||||
cairo_scale( cairoImage, it->arguments[0], it->arguments[1] );
|
cairo_scale( currentContext, it->arguments[0], it->arguments[1] );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_SAVE:
|
case CMD_SAVE:
|
||||||
cairo_save( cairoImage );
|
cairo_save( currentContext );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_RESTORE:
|
case CMD_RESTORE:
|
||||||
cairo_restore( cairoImage );
|
cairo_restore( currentContext );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CMD_CALL_GROUP:
|
case CMD_CALL_GROUP:
|
||||||
|
@ -851,14 +878,14 @@ void CAIRO_GAL::storePath()
|
||||||
{
|
{
|
||||||
if( isFillEnabled )
|
if( isFillEnabled )
|
||||||
{
|
{
|
||||||
cairo_set_source_rgb( cairoImage, fillColor.r, fillColor.g, fillColor.b );
|
cairo_set_source_rgb( currentContext, fillColor.r, fillColor.g, fillColor.b );
|
||||||
cairo_fill_preserve( cairoImage );
|
cairo_fill_preserve( currentContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
if( isStrokeEnabled )
|
if( isStrokeEnabled )
|
||||||
{
|
{
|
||||||
cairo_set_source_rgb( cairoImage, strokeColor.r, strokeColor.g, strokeColor.b );
|
cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g, strokeColor.b );
|
||||||
cairo_stroke_preserve( cairoImage );
|
cairo_stroke_preserve( currentContext );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -869,7 +896,7 @@ void CAIRO_GAL::storePath()
|
||||||
if( isStrokeEnabled )
|
if( isStrokeEnabled )
|
||||||
{
|
{
|
||||||
GroupElement groupElement;
|
GroupElement groupElement;
|
||||||
groupElement.cairoPath = cairo_copy_path( cairoImage );
|
groupElement.cairoPath = cairo_copy_path( currentContext );
|
||||||
groupElement.command = CMD_STROKE_PATH;
|
groupElement.command = CMD_STROKE_PATH;
|
||||||
currentGroup->push_back( groupElement );
|
currentGroup->push_back( groupElement );
|
||||||
}
|
}
|
||||||
|
@ -877,13 +904,13 @@ void CAIRO_GAL::storePath()
|
||||||
if( isFillEnabled )
|
if( isFillEnabled )
|
||||||
{
|
{
|
||||||
GroupElement groupElement;
|
GroupElement groupElement;
|
||||||
groupElement.cairoPath = cairo_copy_path( cairoImage );
|
groupElement.cairoPath = cairo_copy_path( currentContext );
|
||||||
groupElement.command = CMD_FILL_PATH;
|
groupElement.command = CMD_FILL_PATH;
|
||||||
currentGroup->push_back( groupElement );
|
currentGroup->push_back( groupElement );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_new_path( cairoImage );
|
cairo_new_path( currentContext );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -962,17 +989,17 @@ void CAIRO_GAL::DrawCursor( VECTOR2D aCursorPosition )
|
||||||
|
|
||||||
void CAIRO_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
void CAIRO_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
||||||
{
|
{
|
||||||
cairo_move_to( cairoImage, aStartPoint.x, aStartPoint.y );
|
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
|
||||||
cairo_line_to( cairoImage, aEndPoint.x, aEndPoint.y );
|
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
|
||||||
cairo_set_source_rgba( cairoImage, gridColor.r, gridColor.g, gridColor.b, gridColor.a );
|
cairo_set_source_rgb( currentContext, gridColor.r, gridColor.g, gridColor.b );
|
||||||
cairo_stroke( cairoImage );
|
cairo_stroke( currentContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CAIRO_GAL::allocateBitmaps()
|
void CAIRO_GAL::allocateBitmaps()
|
||||||
{
|
{
|
||||||
// Create buffer, use the system independent Cairo image backend
|
// Create buffer, use the system independent Cairo context backend
|
||||||
stride = cairo_format_stride_for_width( CAIRO_FORMAT_RGB24, screenSize.x );
|
stride = cairo_format_stride_for_width( GAL_FORMAT, screenSize.x );
|
||||||
bufferSize = stride * screenSize.y;
|
bufferSize = stride * screenSize.y;
|
||||||
|
|
||||||
bitmapBuffer = new unsigned int[bufferSize];
|
bitmapBuffer = new unsigned int[bufferSize];
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* 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 @@
|
||||||
#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 @@
|
||||||
*/
|
*/
|
||||||
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:
|
||||||
* @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:
|
||||||
/// 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:
|
||||||
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,15 +353,19 @@ 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
|
||||||
Group* currentGroup; ///< Currently used group
|
Group* currentGroup; ///< Currently used group
|
||||||
|
|
||||||
// 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:
|
||||||
/// 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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue