From 9f711724377fd3d4735c1927a8d3f43f66994b81 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 13 May 2013 10:55:35 +0200 Subject: [PATCH] Fixed Cairo issues and some possible memory leaks --- common/gal/cairo/cairo_gal.cpp | 53 +++++++++++++++++++++++--------- common/gal/opengl/opengl_gal.cpp | 10 ++---- common/view/view.cpp | 8 +---- include/gal/cairo/cairo_gal.h | 9 ++++-- 4 files changed, 49 insertions(+), 31 deletions(-) diff --git a/common/gal/cairo/cairo_gal.cpp b/common/gal/cairo/cairo_gal.cpp index 48fb12326d..cd52bcf94f 100644 --- a/common/gal/cairo/cairo_gal.cpp +++ b/common/gal/cairo/cairo_gal.cpp @@ -40,7 +40,7 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, // Default values fillColor = COLOR4D( 0, 0, 0, 1 ); strokeColor = COLOR4D( 1, 1, 1, 1 ); - screenSize = VECTOR2D( 20, 20 ); // window will be soon resized + screenSize = VECTOR2D( aParent->GetSize() ); parentWindow = aParent; mouseListener = aMouseListener; @@ -101,7 +101,11 @@ CAIRO_GAL::~CAIRO_GAL() delete cursorPixels; delete cursorPixelsSaved; - // TODO Deleting of list contents like groups and paths + for( int i = groups.size() - 1; i >= 0; --i ) + { + DeleteGroup( i ); + } + deleteBitmaps(); } @@ -133,7 +137,7 @@ void CAIRO_GAL::skipMouseEvent( wxMouseEvent& aEvent ) } -void CAIRO_GAL::BeginDrawing() throw( int ) +void CAIRO_GAL::initSurface() { // The size of the client area needs to be greater than zero clientRectangle = parentWindow->GetClientRect(); @@ -141,13 +145,15 @@ void CAIRO_GAL::BeginDrawing() throw( int ) if( clientRectangle.width == 0 || clientRectangle.height == 0 ) throw EXCEPTION_ZERO_CLIENT_RECTANGLE; - // clientDC = new wxClientDC( this ); - - // Create the CAIRO surface + // Create the Cairo surface cairoSurface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer, CAIRO_FORMAT_RGB24, clientRectangle.width, clientRectangle.height, stride ); - cairoImage = cairo_create( cairoSurface ); + cairoImage = cairo_create ( cairoSurface ); +#ifdef __WXDEBUG__ + cairo_status_t status = cairo_status( cairoImage ); + wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, "Cairo context creation error" ); +#endif /* __WXDEBUG__ */ // ----------------------------------------------------------------- @@ -178,6 +184,20 @@ void CAIRO_GAL::BeginDrawing() throw( int ) lineWidth = 0; isDeleteSavedPixels = true; +} + + +void CAIRO_GAL::deinitSurface() +{ + // Destroy Cairo objects + cairo_destroy( cairoImage ); + cairo_surface_destroy( cairoSurface ); +} + + +void CAIRO_GAL::BeginDrawing() throw( int ) +{ + initSurface(); cairo_push_group( cairoImage ); } @@ -211,9 +231,7 @@ void CAIRO_GAL::EndDrawing() wxBufferedDC dc; dc.Init( &client_dc, bmp ); - // Destroy Cairo objects - cairo_destroy( cairoImage ); - cairo_surface_destroy( cairoSurface ); + deinitSurface(); } @@ -637,6 +655,8 @@ void CAIRO_GAL::Restore() int CAIRO_GAL::BeginGroup() { + initSurface(); + // If the grouping is started: the actual path is stored in the group, when // a attribute was changed or when grouping stops with the end group method. storePath(); @@ -651,6 +671,8 @@ void CAIRO_GAL::EndGroup() { storePath(); isGrouping = false; + + deinitSurface(); } @@ -659,12 +681,13 @@ void CAIRO_GAL::DeleteGroup( int aGroupNumber ) storePath(); // Delete the Cairo paths - for( std::deque::iterator it = groups[aGroupNumber].begin(); - it != groups[aGroupNumber].end(); ++it ) + for( std::deque::iterator it = groups[aGroupNumber].begin(), end = groups[aGroupNumber].end(); + it != end; ++it ) { if( it->command == CMD_FILL_PATH || it->command == CMD_STROKE_PATH ) { - cairo_path_destroy( it->cairoPath ); + if( it->cairoPath->status == CAIRO_STATUS_SUCCESS ) + cairo_path_destroy( it->cairoPath ); } } @@ -817,7 +840,7 @@ void CAIRO_GAL::storePath() // add this command to the group list; cairo_path_t* path = cairo_copy_path( cairoImage ); - pathList.push_back( path ); + // pathList.push_back( path ); // FIXME: it's not used anywhere else? if( isStrokeEnabled ) { @@ -924,7 +947,7 @@ void CAIRO_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP void CAIRO_GAL::allocateBitmaps() { - // Create buffer, use the system independent CAIRO image back end + // Create buffer, use the system independent Cairo image backend stride = cairo_format_stride_for_width( CAIRO_FORMAT_RGB24, screenSize.x ); bufferSize = stride * screenSize.y; diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index bde328fdf6..f454b2ccdb 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -1488,19 +1488,15 @@ void OPENGL_GAL::EndGroup() void OPENGL_GAL::DeleteGroup( int aGroupNumber ) { - if( aGroupNumber >= vboItems.size() ) - { - // This should not happen - wxLogDebug( wxT( "Tried to delete not existing group" ) ); - return; - } + wxASSERT_MSG( aGroupNumber < vboItems.size(), + "OPENGL_GAL: Tried to delete not existing group" ); std::deque::iterator it = vboItems.begin(); std::advance( it, aGroupNumber ); //vboSize -= it->GetSize(); // FIXME? delete *it; - //vboItems.erase( it ); + //vboItems.erase( it ); // makes change to group numbers - that's veeery bad vboNeedsUpdate = true; } diff --git a/common/view/view.cpp b/common/view/view.cpp index 9302fc1e6d..0b04449aac 100644 --- a/common/view/view.cpp +++ b/common/view/view.cpp @@ -469,8 +469,8 @@ struct VIEW::recacheItem if( immediately ) { int group = gal->BeginGroup(); - view->m_painter->Draw( static_cast( aItem ), layer ); aItem->setGroup( layer, group ); + view->m_painter->Draw( static_cast( aItem ), layer ); gal->EndGroup(); } else @@ -603,9 +603,6 @@ void VIEW::RecacheAllItems( bool aImmediately ) r.SetMaximum(); - //if( aImmediately ) - m_gal->BeginDrawing(); - wxLogDebug( wxT( "RecacheAllItems::immediately: %u" ), aImmediately ); for( LayerMapIter i = m_layers.begin(); i != m_layers.end(); ++i ) @@ -614,7 +611,4 @@ void VIEW::RecacheAllItems( bool aImmediately ) recacheItem visitor( this, m_gal, l->id, aImmediately ); l->items->Query( r, visitor ); } - - //if( aImmediately ) - m_gal->EndDrawing(); } diff --git a/include/gal/cairo/cairo_gal.h b/include/gal/cairo/cairo_gal.h index 5eb425e81e..16343cd077 100644 --- a/include/gal/cairo/cairo_gal.h +++ b/include/gal/cairo/cairo_gal.h @@ -359,14 +359,13 @@ private: unsigned int* bitmapBuffer; ///< Storage of the cairo image unsigned int* bitmapBufferBackup; ///< Backup storage of the cairo image int stride; ///< Stride value for Cairo - // wxClientDC* clientDC; ///< Pointer to the clientDC // Mapping between Cairo and GAL line attributes std::map lineCapMap; ///< Line cap style mapping std::map lineJoinMap; ///< Line join style mapping // Methods - void storePath(); ///< Store the actual path + void storePath(); ///< Store the actual path // Event handlers /** @@ -395,6 +394,12 @@ private: /// Allocate the bitmaps for drawing void deleteBitmaps(); + + /// Prepare Cairo surfaces for drawing + void initSurface(); + + // Destroy Cairo surfaces when are not needed anymore + void deinitSurface(); }; } // namespace KiGfx