Commit 190ed585 authored by Maciej Suminski's avatar Maciej Suminski

Code refactoring.

parent 790a1f85
...@@ -69,6 +69,7 @@ unsigned int CAIRO_COMPOSITOR::GetBuffer() ...@@ -69,6 +69,7 @@ unsigned int CAIRO_COMPOSITOR::GetBuffer()
{ {
// Pixel storage // Pixel storage
BitmapPtr bitmap( new unsigned int[m_bufferSize] ); BitmapPtr bitmap( new unsigned int[m_bufferSize] );
memset( bitmap.get(), 0x00, m_bufferSize * sizeof(int) ); memset( bitmap.get(), 0x00, m_bufferSize * sizeof(int) );
// Create the Cairo surface // Create the Cairo surface
...@@ -105,6 +106,7 @@ void CAIRO_COMPOSITOR::SetBuffer( unsigned int aBufferHandle ) ...@@ -105,6 +106,7 @@ void CAIRO_COMPOSITOR::SetBuffer( unsigned int aBufferHandle )
m_current = aBufferHandle - 1; m_current = aBufferHandle - 1;
*m_currentContext = m_buffers[m_current].context; *m_currentContext = m_buffers[m_current].context;
} }
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
else else
wxLogDebug( wxT( "Tried to use a not existing buffer" ) ); wxLogDebug( wxT( "Tried to use a not existing buffer" ) );
...@@ -141,6 +143,7 @@ void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle ) ...@@ -141,6 +143,7 @@ void CAIRO_COMPOSITOR::DrawBuffer( unsigned int aBufferHandle )
// Restore the transformation matrix // Restore the transformation matrix
cairo_set_matrix( m_mainContext, &m_matrix ); cairo_set_matrix( m_mainContext, &m_matrix );
} }
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
else else
wxLogDebug( wxT( "Tried to use a not existing buffer" ) ); wxLogDebug( wxT( "Tried to use a not existing buffer" ) );
......
...@@ -87,117 +87,7 @@ CAIRO_GAL::~CAIRO_GAL() ...@@ -87,117 +87,7 @@ CAIRO_GAL::~CAIRO_GAL()
} }
void CAIRO_GAL::onPaint( wxPaintEvent& aEvent ) void CAIRO_GAL::BeginDrawing()
{
PostPaint();
}
void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight )
{
screenSize = VECTOR2D( aWidth, aHeight );
// Recreate the bitmaps
deleteBitmaps();
allocateBitmaps();
SetSize( wxSize( aWidth, aHeight ) );
}
void CAIRO_GAL::skipMouseEvent( wxMouseEvent& aEvent )
{
// Post the mouse event to the event listener registered in constructor, if any
if( mouseListener )
wxPostEvent( mouseListener, aEvent );
}
void CAIRO_GAL::initSurface()
{
wxASSERT( !isInitialized );
// Create the Cairo surface
surface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer, GAL_FORMAT,
screenSize.x, screenSize.y, stride );
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__ */
currentContext = context;
cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL );
// Clear the screen
ClearScreen();
// Compute the world <-> screen transformations
ComputeWorldScreenMatrix();
cairo_matrix_init( &cairoWorldScreenMatrix, worldScreenMatrix.m_data[0][0],
worldScreenMatrix.m_data[1][0], worldScreenMatrix.m_data[0][1],
worldScreenMatrix.m_data[1][1], worldScreenMatrix.m_data[0][2],
worldScreenMatrix.m_data[1][2] );
cairo_set_matrix( context, &cairoWorldScreenMatrix );
isSetAttributes = false;
// Start drawing with a new path
cairo_new_path( context );
isElementAdded = true;
cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND );
cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );
lineWidth = 0;
isDeleteSavedPixels = true;
isInitialized = true;
}
void CAIRO_GAL::deinitSurface()
{
if( !isInitialized )
return;
// Destroy Cairo objects
cairo_destroy( context );
cairo_surface_destroy( surface );
isInitialized = false;
}
void CAIRO_GAL::setCompositor()
{
// Recreate the compositor with the new Cairo context
compositor.reset( new CAIRO_COMPOSITOR( &currentContext ) );
compositor->Resize( screenSize.x, screenSize.y );
// Prepare buffers
mainBuffer = compositor->GetBuffer();
overlayBuffer = compositor->GetBuffer();
}
unsigned int CAIRO_GAL::getNewGroupNumber()
{
wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(),
wxT( "There are no free slots to store a group" ) );
while( groups.find( groupCounter ) != groups.end() )
{
groupCounter++;
}
return groupCounter++;
}
void CAIRO_GAL::BeginDrawing() throw( int )
{ {
initSurface(); initSurface();
setCompositor(); setCompositor();
...@@ -245,65 +135,6 @@ void CAIRO_GAL::EndDrawing() ...@@ -245,65 +135,6 @@ void CAIRO_GAL::EndDrawing()
} }
void CAIRO_GAL::SaveScreen()
{
// Copy the current bitmap to the backup buffer
int offset = 0;
for( int j = 0; j < screenSize.y; j++ )
{
for( int i = 0; i < stride; i++ )
{
bitmapBufferBackup[offset + i] = bitmapBuffer[offset + i];
offset += stride;
}
}
}
void CAIRO_GAL::RestoreScreen()
{
int offset = 0;
for( int j = 0; j < screenSize.y; j++ )
{
for( int i = 0; i < stride; i++ )
{
bitmapBuffer[offset + i] = bitmapBufferBackup[offset + i];
offset += stride;
}
}
}
void CAIRO_GAL::SetTarget( RenderTarget aTarget )
{
// 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( currentContext, aStartPoint.x, aStartPoint.y ); cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
...@@ -373,12 +204,30 @@ void CAIRO_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aS ...@@ -373,12 +204,30 @@ void CAIRO_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aS
} }
void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{
// Calculate the diagonal points
VECTOR2D diagonalPointA( aEndPoint.x, aStartPoint.y );
VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y );
// The path is composed from 4 segments
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
cairo_line_to( currentContext, diagonalPointA.x, diagonalPointA.y );
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
cairo_line_to( currentContext, diagonalPointB.x, diagonalPointB.y );
cairo_close_path( currentContext );
isElementAdded = true;
}
void CAIRO_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList ) void CAIRO_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
{ {
// Iterate over the point list and draw the segments // Iterate over the point list and draw the segments
std::deque<VECTOR2D>::const_iterator it = aPointList.begin(); std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
cairo_move_to( currentContext, it->x, it->y ); cairo_move_to( currentContext, it->x, it->y );
for( ++it; it != aPointList.end(); ++it ) for( ++it; it != aPointList.end(); ++it )
{ {
cairo_line_to( currentContext, it->x, it->y ); cairo_line_to( currentContext, it->x, it->y );
...@@ -394,6 +243,7 @@ void CAIRO_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList ) ...@@ -394,6 +243,7 @@ void CAIRO_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
std::deque<VECTOR2D>::const_iterator it = aPointList.begin(); std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
cairo_move_to( currentContext, it->x, it->y ); cairo_move_to( currentContext, it->x, it->y );
for( ++it; it != aPointList.end(); ++it ) for( ++it; it != aPointList.end(); ++it )
{ {
cairo_line_to( currentContext, it->x, it->y ); cairo_line_to( currentContext, it->x, it->y );
...@@ -403,38 +253,53 @@ void CAIRO_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList ) ...@@ -403,38 +253,53 @@ void CAIRO_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
} }
void CAIRO_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA,
const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint )
{ {
// Calculate the diagonal points
VECTOR2D diagonalPointA( aEndPoint.x, aStartPoint.y );
VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y );
// The path is composed from 4 segments
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y ); cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
cairo_line_to( currentContext, diagonalPointA.x, diagonalPointA.y ); cairo_curve_to( currentContext, aControlPointA.x, aControlPointA.y, aControlPointB.x,
aControlPointB.y, aEndPoint.x, aEndPoint.y );
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y ); cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
cairo_line_to( currentContext, diagonalPointB.x, diagonalPointB.y );
cairo_close_path( currentContext );
isElementAdded = true; isElementAdded = true;
} }
void CAIRO_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA, void CAIRO_GAL::ResizeScreen( int aWidth, int aHeight )
const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint )
{ {
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y ); screenSize = VECTOR2D( aWidth, aHeight );
cairo_curve_to( currentContext, aControlPointA.x, aControlPointA.y, aControlPointB.x,
aControlPointB.y, aEndPoint.x, aEndPoint.y );
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
isElementAdded = true; // Recreate the bitmaps
deleteBitmaps();
allocateBitmaps();
SetSize( wxSize( aWidth, aHeight ) );
}
bool CAIRO_GAL::Show( bool aShow )
{
bool s = wxWindow::Show( aShow );
if( aShow )
wxWindow::Raise();
return s;
}
void CAIRO_GAL::Flush()
{
storePath();
} }
void CAIRO_GAL::SetBackgroundColor( const COLOR4D& aColor ) void CAIRO_GAL::ClearScreen()
{ {
backgroundColor = aColor; cairo_set_source_rgb( currentContext,
backgroundColor.r, backgroundColor.g, backgroundColor.b );
cairo_rectangle( currentContext, 0.0, 0.0, screenSize.x, screenSize.y );
cairo_fill( currentContext );
} }
...@@ -528,15 +393,6 @@ void CAIRO_GAL::SetLineWidth( double aLineWidth ) ...@@ -528,15 +393,6 @@ void CAIRO_GAL::SetLineWidth( double aLineWidth )
} }
void CAIRO_GAL::ClearScreen()
{
cairo_set_source_rgb( currentContext,
backgroundColor.r, backgroundColor.g, backgroundColor.b );
cairo_rectangle( currentContext, 0.0, 0.0, screenSize.x, screenSize.y );
cairo_fill( currentContext );
}
void CAIRO_GAL::SetLayerDepth( double aLayerDepth ) void CAIRO_GAL::SetLayerDepth( double aLayerDepth )
{ {
super::SetLayerDepth( aLayerDepth ); super::SetLayerDepth( aLayerDepth );
...@@ -686,41 +542,12 @@ void CAIRO_GAL::EndGroup() ...@@ -686,41 +542,12 @@ void CAIRO_GAL::EndGroup()
} }
void CAIRO_GAL::ClearCache() void CAIRO_GAL::DrawGroup( int aGroupNumber )
{ {
for( int i = groups.size() - 1; i >= 0; --i ) // This method implements a small Virtual Machine - all stored commands
{ // are executed; nested calling is also possible
DeleteGroup( i );
}
}
storePath();
void CAIRO_GAL::DeleteGroup( int aGroupNumber )
{
storePath();
// Delete the Cairo paths
std::deque<GroupElement>::iterator it, end;
for( 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 );
}
}
// Delete the group
groups.erase( aGroupNumber );
}
void CAIRO_GAL::DrawGroup( int aGroupNumber )
{
// This method implements a small Virtual Machine - all stored commands
// are executed; nested calling is also possible
storePath();
for( Group::iterator it = groups[aGroupNumber].begin(); for( Group::iterator it = groups[aGroupNumber].begin();
it != groups[aGroupNumber].end(); ++it ) it != groups[aGroupNumber].end(); ++it )
...@@ -828,31 +655,147 @@ void CAIRO_GAL::ChangeGroupDepth( int aGroupNumber, int aDepth ) ...@@ -828,31 +655,147 @@ void CAIRO_GAL::ChangeGroupDepth( int aGroupNumber, int aDepth )
} }
void CAIRO_GAL::Flush() void CAIRO_GAL::DeleteGroup( int aGroupNumber )
{ {
storePath(); storePath();
// Delete the Cairo paths
std::deque<GroupElement>::iterator it, end;
for( 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 );
}
}
// Delete the group
groups.erase( aGroupNumber );
}
void CAIRO_GAL::ClearCache()
{
for( int i = groups.size() - 1; i >= 0; --i )
{
DeleteGroup( i );
}
}
void CAIRO_GAL::SaveScreen()
{
// Copy the current bitmap to the backup buffer
int offset = 0;
for( int j = 0; j < screenSize.y; j++ )
{
for( int i = 0; i < stride; i++ )
{
bitmapBufferBackup[offset + i] = bitmapBuffer[offset + i];
offset += stride;
}
}
}
void CAIRO_GAL::RestoreScreen()
{
int offset = 0;
for( int j = 0; j < screenSize.y; j++ )
{
for( int i = 0; i < stride; i++ )
{
bitmapBuffer[offset + i] = bitmapBufferBackup[offset + i];
offset += stride;
}
}
} }
void CAIRO_GAL::ComputeWorldScreenMatrix() void CAIRO_GAL::SetTarget( RenderTarget aTarget )
{ {
ComputeWorldScale(); // 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;
worldScreenMatrix.SetIdentity(); // 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 );
MATRIX3x3D translation; switch( aTarget )
translation.SetIdentity(); {
translation.SetTranslation( 0.5 * screenSize ); default:
case TARGET_CACHED:
case TARGET_NONCACHED:
compositor->SetBuffer( mainBuffer );
break;
case TARGET_OVERLAY:
compositor->SetBuffer( overlayBuffer );
break;
}
MATRIX3x3D scale; cairo_push_group( currentContext );
scale.SetIdentity(); }
scale.SetScale( VECTOR2D( worldScale, worldScale ) );
MATRIX3x3D lookat;
lookat.SetIdentity();
lookat.SetTranslation( -lookAtPoint );
worldScreenMatrix = translation * scale * lookat * worldScreenMatrix; VECTOR2D CAIRO_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition )
{
MATRIX3x3D inverseMatrix = worldScreenMatrix.Inverse();
VECTOR2D cursorPositionWorld = inverseMatrix * aCursorPosition;
return cursorPositionWorld;
}
void CAIRO_GAL::DrawCursor( VECTOR2D aCursorPosition )
{
if( !IsShownOnScreen() )
return;
wxClientDC clientDC( this );
wxMemoryDC cursorSave( *cursorPixelsSaved );
wxMemoryDC cursorShape( *cursorPixels );
// Snap to grid
VECTOR2D cursorPositionWorld = ComputeCursorToWorld( aCursorPosition );
cursorPositionWorld.x = round( cursorPositionWorld.x / gridSize.x ) * gridSize.x;
cursorPositionWorld.y = round( cursorPositionWorld.y / gridSize.y ) * gridSize.y;
aCursorPosition = worldScreenMatrix * cursorPositionWorld;
aCursorPosition = aCursorPosition - VECTOR2D( cursorSize / 2, cursorSize / 2 );
if( !isDeleteSavedPixels )
{
clientDC.Blit( savedCursorPosition.x, savedCursorPosition.y, cursorSize, cursorSize,
&cursorSave, 0, 0 );
}
else
{
isDeleteSavedPixels = false;
}
cursorSave.Blit( 0, 0, cursorSize, cursorSize, &clientDC, aCursorPosition.x,
aCursorPosition.y );
clientDC.Blit( aCursorPosition.x, aCursorPosition.y, cursorSize, cursorSize, &cursorShape, 0,
0, wxOR );
savedCursorPosition.x = (wxCoord) aCursorPosition.x;
savedCursorPosition.y = (wxCoord) aCursorPosition.y;
}
void CAIRO_GAL::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
cairo_set_source_rgb( currentContext, gridColor.r, gridColor.g, gridColor.b );
cairo_stroke( currentContext );
} }
...@@ -872,7 +815,8 @@ void CAIRO_GAL::storePath() ...@@ -872,7 +815,8 @@ void CAIRO_GAL::storePath()
if( isStrokeEnabled ) if( isStrokeEnabled )
{ {
cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g, strokeColor.b ); cairo_set_source_rgb( currentContext, strokeColor.r, strokeColor.g,
strokeColor.b );
cairo_stroke_preserve( currentContext ); cairo_stroke_preserve( currentContext );
} }
} }
...@@ -903,9 +847,18 @@ void CAIRO_GAL::storePath() ...@@ -903,9 +847,18 @@ void CAIRO_GAL::storePath()
} }
// --------------- void CAIRO_GAL::onPaint( wxPaintEvent& aEvent )
// Cursor handling {
// --------------- PostPaint();
}
void CAIRO_GAL::skipMouseEvent( wxMouseEvent& aEvent )
{
// Post the mouse event to the event listener registered in constructor, if any
if( mouseListener )
wxPostEvent( mouseListener, aEvent );
}
void CAIRO_GAL::initCursor( int aCursorSize ) void CAIRO_GAL::initCursor( int aCursorSize )
...@@ -928,88 +881,103 @@ void CAIRO_GAL::initCursor( int aCursorSize ) ...@@ -928,88 +881,103 @@ void CAIRO_GAL::initCursor( int aCursorSize )
} }
VECTOR2D CAIRO_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition ) void CAIRO_GAL::allocateBitmaps()
{ {
MATRIX3x3D inverseMatrix = worldScreenMatrix.Inverse(); // Create buffer, use the system independent Cairo context backend
VECTOR2D cursorPositionWorld = inverseMatrix * aCursorPosition; stride = cairo_format_stride_for_width( GAL_FORMAT, screenSize.x );
bufferSize = stride * screenSize.y;
return cursorPositionWorld; bitmapBuffer = new unsigned int[bufferSize];
bitmapBufferBackup = new unsigned int[bufferSize];
wxOutput = new unsigned char[bufferSize * 3];
} }
void CAIRO_GAL::DrawCursor( VECTOR2D aCursorPosition ) void CAIRO_GAL::deleteBitmaps()
{ {
if( !IsShownOnScreen() ) delete[] bitmapBuffer;
return; delete[] bitmapBufferBackup;
delete[] wxOutput;
}
wxClientDC clientDC( this );
wxMemoryDC cursorSave( *cursorPixelsSaved );
wxMemoryDC cursorShape( *cursorPixels );
// Snap to grid void CAIRO_GAL::initSurface()
VECTOR2D cursorPositionWorld = ComputeCursorToWorld( aCursorPosition ); {
wxASSERT( !isInitialized );
cursorPositionWorld.x = round( cursorPositionWorld.x / gridSize.x ) * gridSize.x; // Create the Cairo surface
cursorPositionWorld.y = round( cursorPositionWorld.y / gridSize.y ) * gridSize.y; surface = cairo_image_surface_create_for_data( (unsigned char*) bitmapBuffer, GAL_FORMAT,
aCursorPosition = worldScreenMatrix * cursorPositionWorld; screenSize.x, screenSize.y, stride );
aCursorPosition = aCursorPosition - VECTOR2D( cursorSize / 2, cursorSize / 2 ); 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__ */
currentContext = context;
if( !isDeleteSavedPixels ) cairo_set_antialias( context, CAIRO_ANTIALIAS_SUBPIXEL );
{
clientDC.Blit( savedCursorPosition.x, savedCursorPosition.y, cursorSize, cursorSize,
&cursorSave, 0, 0 );
}
else
{
isDeleteSavedPixels = false;
}
cursorSave.Blit( 0, 0, cursorSize, cursorSize, &clientDC, aCursorPosition.x, // Clear the screen
aCursorPosition.y ); ClearScreen();
clientDC.Blit( aCursorPosition.x, aCursorPosition.y, cursorSize, cursorSize, &cursorShape, 0, // Compute the world <-> screen transformations
0, wxOR ); ComputeWorldScreenMatrix();
savedCursorPosition.x = (wxCoord) aCursorPosition.x; cairo_matrix_init( &cairoWorldScreenMatrix, worldScreenMatrix.m_data[0][0],
savedCursorPosition.y = (wxCoord) aCursorPosition.y; worldScreenMatrix.m_data[1][0], worldScreenMatrix.m_data[0][1],
} worldScreenMatrix.m_data[1][1], worldScreenMatrix.m_data[0][2],
worldScreenMatrix.m_data[1][2] );
cairo_set_matrix( context, &cairoWorldScreenMatrix );
void CAIRO_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) // Start drawing with a new path
{ cairo_new_path( context );
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y ); isElementAdded = true;
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
cairo_set_source_rgb( currentContext, gridColor.r, gridColor.g, gridColor.b ); cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND );
cairo_stroke( currentContext ); cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );
lineWidth = 0;
isDeleteSavedPixels = true;
isInitialized = true;
} }
void CAIRO_GAL::allocateBitmaps() void CAIRO_GAL::deinitSurface()
{ {
// Create buffer, use the system independent Cairo context backend if( !isInitialized )
stride = cairo_format_stride_for_width( GAL_FORMAT, screenSize.x ); return;
bufferSize = stride * screenSize.y;
bitmapBuffer = new unsigned int[bufferSize]; // Destroy Cairo objects
bitmapBufferBackup = new unsigned int[bufferSize]; cairo_destroy( context );
wxOutput = new unsigned char[bufferSize * 3]; cairo_surface_destroy( surface );
isInitialized = false;
} }
void CAIRO_GAL::deleteBitmaps() void CAIRO_GAL::setCompositor()
{ {
delete[] bitmapBuffer; // Recreate the compositor with the new Cairo context
delete[] bitmapBufferBackup; compositor.reset( new CAIRO_COMPOSITOR( &currentContext ) );
delete[] wxOutput; compositor->Resize( screenSize.x, screenSize.y );
// Prepare buffers
mainBuffer = compositor->GetBuffer();
overlayBuffer = compositor->GetBuffer();
} }
bool CAIRO_GAL::Show( bool aShow ) unsigned int CAIRO_GAL::getNewGroupNumber()
{ {
bool s = wxWindow::Show( aShow ); wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(),
wxT( "There are no free slots to store a group" ) );
if( aShow ) while( groups.find( groupCounter ) != groups.end() )
wxWindow::Raise(); {
groupCounter++;
}
return s; return groupCounter++;
} }
...@@ -63,6 +63,33 @@ GAL::~GAL() ...@@ -63,6 +63,33 @@ GAL::~GAL()
} }
void GAL::ComputeWorldScreenMatrix()
{
ComputeWorldScale();
worldScreenMatrix.SetIdentity();
MATRIX3x3D translation;
translation.SetIdentity();
translation.SetTranslation( 0.5 * screenSize );
MATRIX3x3D scale;
scale.SetIdentity();
scale.SetScale( VECTOR2D( worldScale, worldScale ) );
MATRIX3x3D flip;
flip.SetIdentity();
flip.SetScale( VECTOR2D( 1.0, 1.0 ) );
MATRIX3x3D lookat;
lookat.SetIdentity();
lookat.SetTranslation( -lookAtPoint );
worldScreenMatrix = translation * flip * scale * lookat * worldScreenMatrix;
}
void GAL::DrawGrid() void GAL::DrawGrid()
{ {
if( !gridVisibility ) if( !gridVisibility )
...@@ -136,7 +163,7 @@ void GAL::DrawGrid() ...@@ -136,7 +163,7 @@ void GAL::DrawGrid()
if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridDrawThreshold ) if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridDrawThreshold )
|| gridScreenSizeDense > gridDrawThreshold ) || gridScreenSizeDense > gridDrawThreshold )
{ {
DrawGridLine( VECTOR2D( gridStartX * gridSize.x, j * gridSize.y ), drawGridLine( VECTOR2D( gridStartX * gridSize.x, j * gridSize.y ),
VECTOR2D( gridEndX * gridSize.x, j * gridSize.y ) ); VECTOR2D( gridEndX * gridSize.x, j * gridSize.y ) );
} }
} }
...@@ -155,7 +182,7 @@ void GAL::DrawGrid() ...@@ -155,7 +182,7 @@ void GAL::DrawGrid()
if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridDrawThreshold ) if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridDrawThreshold )
|| gridScreenSizeDense > gridDrawThreshold ) || gridScreenSizeDense > gridDrawThreshold )
{ {
DrawGridLine( VECTOR2D( i * gridSize.x, gridStartY * gridSize.y ), drawGridLine( VECTOR2D( i * gridSize.x, gridStartY * gridSize.y ),
VECTOR2D( i * gridSize.x, gridEndY * gridSize.y ) ); VECTOR2D( i * gridSize.x, gridEndY * gridSize.y ) );
} }
} }
......
...@@ -229,9 +229,11 @@ void OPENGL_COMPOSITOR::clean() ...@@ -229,9 +229,11 @@ void OPENGL_COMPOSITOR::clean()
{ {
glDeleteTextures( 1, &it->textureTarget ); glDeleteTextures( 1, &it->textureTarget );
} }
m_buffers.clear(); m_buffers.clear();
m_initialized = false; m_initialized = false;
} }
GLuint OPENGL_COMPOSITOR::m_currentFbo = 0; GLuint OPENGL_COMPOSITOR::m_currentFbo = 0;
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#endif /* __WXDEBUG__ */ #endif /* __WXDEBUG__ */
#include <limits> #include <limits>
#include <boost/foreach.hpp>
#ifndef CALLBACK #ifndef CALLBACK
#define CALLBACK #define CALLBACK
...@@ -94,9 +93,6 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, ...@@ -94,9 +93,6 @@ OPENGL_GAL::OPENGL_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener,
tesselator = gluNewTess(); tesselator = gluNewTess();
InitTesselatorCallbacks( tesselator ); InitTesselatorCallbacks( tesselator );
gluTessProperty( tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE ); gluTessProperty( tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
// Compute the unit circle vertices and store them in a buffer for faster drawing
computeCircle();
} }
...@@ -111,109 +107,6 @@ OPENGL_GAL::~OPENGL_GAL() ...@@ -111,109 +107,6 @@ OPENGL_GAL::~OPENGL_GAL()
} }
void OPENGL_GAL::onPaint( wxPaintEvent& aEvent )
{
PostPaint();
}
void OPENGL_GAL::ResizeScreen( int aWidth, int aHeight )
{
screenSize = VECTOR2D( aWidth, aHeight );
// Resize framebuffers
compositor.Resize( aWidth, aHeight );
isFramebufferInitialized = false;
wxGLCanvas::SetSize( aWidth, aHeight );
}
void OPENGL_GAL::skipMouseEvent( wxMouseEvent& aEvent )
{
// Post the mouse event to the event listener registered in constructor, if any
if( mouseListener )
wxPostEvent( mouseListener, aEvent );
}
void OPENGL_GAL::SaveScreen()
{
wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
}
void OPENGL_GAL::RestoreScreen()
{
wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
}
void OPENGL_GAL::SetTarget( RenderTarget aTarget )
{
switch( aTarget )
{
default:
case TARGET_CACHED:
currentManager = &cachedManager;
break;
case TARGET_NONCACHED:
currentManager = &nonCachedManager;
break;
case TARGET_OVERLAY:
currentManager = &overlayManager;
break;
}
}
void OPENGL_GAL::initGlew()
{
// Initialize GLEW library
GLenum err = glewInit();
if( GLEW_OK != err )
{
wxLogError( wxString::FromUTF8( (char*) glewGetErrorString( err ) ) );
exit( 1 );
}
else
{
wxLogDebug( wxString( wxT( "Status: Using GLEW " ) ) +
FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
}
// Check the OpenGL version (minimum 2.1 is required)
if( GLEW_VERSION_2_1 )
{
wxLogInfo( wxT( "OpenGL Version 2.1 supported." ) );
}
else
{
wxLogError( wxT( "OpenGL Version 2.1 is not supported!" ) );
exit( 1 );
}
// Framebuffers have to be supported
if( !GLEW_ARB_framebuffer_object )
{
wxLogError( wxT( "Framebuffer objects are not supported!" ) );
exit( 1 );
}
// Vertex buffer have to be supported
if( !GLEW_ARB_vertex_buffer_object )
{
wxLogError( wxT( "Vertex buffer objects are not supported!" ) );
exit( 1 );
}
isGlewInitialized = true;
}
void OPENGL_GAL::BeginDrawing() void OPENGL_GAL::BeginDrawing()
{ {
SetCurrent( *glContext ); SetCurrent( *glContext );
...@@ -232,7 +125,8 @@ void OPENGL_GAL::BeginDrawing() ...@@ -232,7 +125,8 @@ void OPENGL_GAL::BeginDrawing()
glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y ); glViewport( 0, 0, (GLsizei) screenSize.x, (GLsizei) screenSize.y );
// Create the screen transformation // Create the screen transformation
glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y, -depthRange.x, -depthRange.y ); glOrtho( 0, (GLint) screenSize.x, 0, (GLsizei) screenSize.y,
-depthRange.x, -depthRange.y );
// Prepare rendering target buffers // Prepare rendering target buffers
compositor.Initialize(); compositor.Initialize();
...@@ -333,37 +227,16 @@ void OPENGL_GAL::EndDrawing() ...@@ -333,37 +227,16 @@ void OPENGL_GAL::EndDrawing()
} }
inline void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{ {
VECTOR2D startEndVector = aEndPoint - aStartPoint; const VECTOR2D startEndVector = aEndPoint - aStartPoint;
double lineLength = startEndVector.EuclideanNorm(); double lineAngle = startEndVector.Angle();
double scale = 0.5 * lineWidth / lineLength;
if( lineLength <= 0.0 )
return;
// The perpendicular vector also needs transformations
glm::vec4 vector = currentManager->GetTransformation() *
glm::vec4( -startEndVector.y * scale, startEndVector.x * scale, 0.0, 0.0 );
// Line width is maintained by the vertex shader
currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth );
currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v0
currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v1
currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3
currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth );
currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v0
currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth ); drawLineQuad( aStartPoint, aEndPoint );
currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3
currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth ); // Line caps
currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v2 drawFilledSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 );
drawFilledSemiCircle( aEndPoint, lineWidth / 2, lineAngle - M_PI / 2 );
} }
...@@ -414,53 +287,124 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP ...@@ -414,53 +287,124 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
} }
unsigned int OPENGL_GAL::getNewGroupNumber() void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
{ {
wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(), if( isFillEnabled )
wxT( "There are no free slots to store a group" ) );
while( groups.find( groupCounter ) != groups.end() )
{ {
groupCounter++; currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
/* Draw a triangle that contains the circle, then shade it leaving only the circle.
* Parameters given to setShader are indices of the triangle's vertices
* (if you want to understand more, check the vertex shader source [shader.vert]).
* Shader uses this coordinates to determine if fragments are inside the circle or not.
* v2
* /\
* //\\
* v0 /_\/_\ v1
*/
currentManager->Shader( SHADER_FILLED_CIRCLE, 1.0 );
currentManager->Vertex( aCenterPoint.x - aRadius * sqrt( 3.0f ), // v0
aCenterPoint.y - aRadius, layerDepth );
currentManager->Shader( SHADER_FILLED_CIRCLE, 2.0 );
currentManager->Vertex( aCenterPoint.x + aRadius * sqrt( 3.0f ), // v1
aCenterPoint.y - aRadius, layerDepth );
currentManager->Shader( SHADER_FILLED_CIRCLE, 3.0 );
currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + aRadius * 2.0f, // v2
layerDepth );
} }
return groupCounter++; if( isStrokeEnabled )
{
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
/* Draw a triangle that contains the circle, then shade it leaving only the circle.
* Parameters given to setShader are indices of the triangle's vertices
* (if you want to understand more, check the vertex shader source [shader.vert]).
* and the line width. Shader uses this coordinates to determine if fragments are
* inside the circle or not.
* v2
* /\
* //\\
* v0 /_\/_\ v1
*/
double outerRadius = aRadius + ( lineWidth / 2 );
currentManager->Shader( SHADER_STROKED_CIRCLE, 1.0, aRadius, lineWidth );
currentManager->Vertex( aCenterPoint.x - outerRadius * sqrt( 3.0f ), // v0
aCenterPoint.y - outerRadius, layerDepth );
currentManager->Shader( SHADER_STROKED_CIRCLE, 2.0, aRadius, lineWidth );
currentManager->Vertex( aCenterPoint.x + outerRadius * sqrt( 3.0f ), // v1
aCenterPoint.y - outerRadius, layerDepth );
currentManager->Shader( SHADER_STROKED_CIRCLE, 3.0, aRadius, lineWidth );
currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + outerRadius * 2.0f, // v2
layerDepth );
}
} }
void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
double aEndAngle )
{ {
const VECTOR2D startEndVector = aEndPoint - aStartPoint; if( aRadius <= 0 )
double lineAngle = startEndVector.Angle(); return;
drawLineQuad( aStartPoint, aEndPoint ); // Swap the angles, if start angle is greater than end angle
SWAP( aStartAngle, >, aEndAngle );
// Line caps VECTOR2D startPoint( cos( aStartAngle ), sin( aStartAngle ) );
drawFilledSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 ); VECTOR2D endPoint( cos( aEndAngle ), sin( aEndAngle ) );
drawFilledSemiCircle( aEndPoint, lineWidth / 2, lineAngle - M_PI / 2 ); VECTOR2D startEndPoint = startPoint + endPoint;
} VECTOR2D middlePoint = 0.5 * startEndPoint;
Save();
currentManager->Translate( aCenterPoint.x, aCenterPoint.y, layerDepth );
void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList ) if( isStrokeEnabled )
{ {
std::deque<VECTOR2D>::const_iterator it = aPointList.begin(); double alphaIncrement = 2.0 * M_PI / CIRCLE_POINTS;
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
// Start from the second point VECTOR2D p( cos( aStartAngle ) * aRadius, sin( aStartAngle ) * aRadius );
for( it++; it != aPointList.end(); it++ ) double alpha;
for( alpha = aStartAngle + alphaIncrement; alpha < aEndAngle; alpha += alphaIncrement )
{ {
const VECTOR2D startEndVector = ( *it - *( it - 1 ) ); VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
double lineAngle = startEndVector.Angle(); DrawLine( p, p_next );
drawLineQuad( *( it - 1 ), *it ); p = p_next;
}
// There is no need to draw line caps on both ends of polyline's segments // Draw the last missing part
drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle + M_PI / 2 ); if( alpha != aEndAngle )
{
VECTOR2D p_last( cos( aEndAngle ) * aRadius, sin( aEndAngle ) * aRadius );
DrawLine( p, p_last );
}
} }
// ..and now - draw the ending cap if( isFillEnabled )
const VECTOR2D startEndVector = ( *( it - 1 ) - *( it - 2 ) ); {
double lineAngle = startEndVector.Angle(); double alphaIncrement = 2 * M_PI / CIRCLE_POINTS;
drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle - M_PI / 2 ); double alpha;
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
for( alpha = aStartAngle; ( alpha + alphaIncrement ) < aEndAngle; )
{
currentManager->Vertex( middlePoint.x, middlePoint.y, 0.0 );
currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 );
alpha += alphaIncrement;
currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 );
}
currentManager->Vertex( middlePoint.x, middlePoint.y, 0.0 );
currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 );
currentManager->Vertex( endPoint.x, endPoint.y, 0.0 );
}
Restore();
} }
...@@ -501,234 +445,29 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn ...@@ -501,234 +445,29 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn
} }
void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList )
{ {
if( isFillEnabled ) std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
{
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
/* Draw a triangle that contains the circle, then shade it leaving only the circle.
Parameters given to setShader are indices of the triangle's vertices
(if you want to understand more, check the vertex shader source [shader.vert]).
Shader uses this coordinates to determine if fragments are inside the circle or not.
v2
/\
//\\
v0 /_\/_\ v1
*/
currentManager->Shader( SHADER_FILLED_CIRCLE, 1.0 );
currentManager->Vertex( aCenterPoint.x - aRadius * sqrt( 3.0f ), // v0
aCenterPoint.y - aRadius, layerDepth );
currentManager->Shader( SHADER_FILLED_CIRCLE, 2.0 );
currentManager->Vertex( aCenterPoint.x + aRadius* sqrt( 3.0f ), // v1
aCenterPoint.y - aRadius, layerDepth );
currentManager->Shader( SHADER_FILLED_CIRCLE, 3.0 );
currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + aRadius * 2.0f, // v2
layerDepth );
}
if( isStrokeEnabled )
{
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
/* Draw a triangle that contains the circle, then shade it leaving only the circle.
Parameters given to setShader are indices of the triangle's vertices
(if you want to understand more, check the vertex shader source [shader.vert]).
and the line width. Shader uses this coordinates to determine if fragments are
inside the circle or not.
v2
/\
//\\
v0 /_\/_\ v1
*/
double outerRadius = aRadius + ( lineWidth / 2 );
currentManager->Shader( SHADER_STROKED_CIRCLE, 1.0, aRadius, lineWidth );
currentManager->Vertex( aCenterPoint.x - outerRadius * sqrt( 3.0f ), // v0
aCenterPoint.y - outerRadius, layerDepth );
currentManager->Shader( SHADER_STROKED_CIRCLE, 2.0, aRadius, lineWidth );
currentManager->Vertex( aCenterPoint.x + outerRadius * sqrt( 3.0f ), // v1
aCenterPoint.y - outerRadius, layerDepth );
currentManager->Shader( SHADER_STROKED_CIRCLE, 3.0, aRadius, lineWidth );
currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + outerRadius * 2.0f, // v2
layerDepth );
}
}
void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle )
{
if( isFillEnabled )
{
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
drawFilledSemiCircle( aCenterPoint, aRadius, aAngle );
}
if( isStrokeEnabled )
{
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
drawStrokedSemiCircle( aCenterPoint, aRadius, aAngle );
}
}
void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius,
double aAngle )
{
Save();
currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.0f );
currentManager->Rotate( aAngle, 0.0f, 0.0f, 1.0f );
/* Draw a triangle that contains the semicircle, then shade it to leave only
* the semicircle. Parameters given to setShader are indices of the triangle's vertices
(if you want to understand more, check the vertex shader source [shader.vert]).
Shader uses this coordinates to determine if fragments are inside the semicircle or not.
v2
/\
/__\
v0 //__\\ v1
*/
currentManager->Shader( SHADER_FILLED_CIRCLE, 4.0f );
currentManager->Vertex( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0
currentManager->Shader( SHADER_FILLED_CIRCLE, 5.0f );
currentManager->Vertex( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1
currentManager->Shader( SHADER_FILLED_CIRCLE, 6.0f );
currentManager->Vertex( 0.0f, aRadius * 2.0f, layerDepth ); // v2
Restore();
}
void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius,
double aAngle )
{
double outerRadius = aRadius + ( lineWidth / 2 );
Save();
currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.0f );
currentManager->Rotate( aAngle, 0.0f, 0.0f, 1.0f );
/* Draw a triangle that contains the semicircle, then shade it to leave only
* the semicircle. Parameters given to setShader are indices of the triangle's vertices
(if you want to understand more, check the vertex shader source [shader.vert]), the
radius and the line width. Shader uses this coordinates to determine if fragments are
inside the semicircle or not.
v2
/\
/__\
v0 //__\\ v1
*/
currentManager->Shader( SHADER_STROKED_CIRCLE, 4.0f, aRadius, lineWidth );
currentManager->Vertex( -outerRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0
currentManager->Shader( SHADER_STROKED_CIRCLE, 5.0f, aRadius, lineWidth );
currentManager->Vertex( outerRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1
currentManager->Shader( SHADER_STROKED_CIRCLE, 6.0f, aRadius, lineWidth );
currentManager->Vertex( 0.0f, outerRadius * 2.0f, layerDepth ); // v2
Restore();
}
// FIXME Optimize
void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
double aEndAngle )
{
if( aRadius <= 0 )
return;
// Swap the angles, if start angle is greater than end angle
SWAP( aStartAngle, >, aEndAngle );
VECTOR2D startPoint( cos( aStartAngle ), sin( aStartAngle ) );
VECTOR2D endPoint( cos( aEndAngle ), sin( aEndAngle ) );
VECTOR2D startEndPoint = startPoint + endPoint;
VECTOR2D middlePoint = 0.5 * startEndPoint;
Save();
currentManager->Translate( aCenterPoint.x, aCenterPoint.y, layerDepth );
if( isStrokeEnabled )
{
double alphaIncrement = 2.0 * M_PI / CIRCLE_POINTS;
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
VECTOR2D p( cos( aStartAngle ) * aRadius, sin( aStartAngle ) * aRadius );
double alpha;
for( alpha = aStartAngle + alphaIncrement; alpha < aEndAngle; alpha += alphaIncrement )
{
VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
DrawLine( p, p_next );
p = p_next;
}
// Draw the last missing part
if( alpha != aEndAngle )
{
VECTOR2D p_last( cos( aEndAngle ) * aRadius, sin( aEndAngle ) * aRadius );
DrawLine( p, p_last );
}
}
if( isFillEnabled ) // Start from the second point
for( it++; it != aPointList.end(); it++ )
{ {
double alphaIncrement = 2 * M_PI / CIRCLE_POINTS; const VECTOR2D startEndVector = ( *it - *( it - 1 ) );
double alpha; double lineAngle = startEndVector.Angle();
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
for( alpha = aStartAngle; ( alpha + alphaIncrement ) < aEndAngle; ) drawLineQuad( *( it - 1 ), *it );
{
currentManager->Vertex( middlePoint.x, middlePoint.y, 0.0 );
currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 );
alpha += alphaIncrement;
currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 );
}
currentManager->Vertex( middlePoint.x, middlePoint.y, 0.0 ); // There is no need to draw line caps on both ends of polyline's segments
currentManager->Vertex( cos( alpha ), sin( alpha ), 0.0 ); drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle + M_PI / 2 );
currentManager->Vertex( endPoint.x, endPoint.y, 0.0 );
} }
Restore(); // ..and now - draw the ending cap
const VECTOR2D startEndVector = ( *( it - 1 ) - *( it - 2 ) );
double lineAngle = startEndVector.Angle();
drawFilledSemiCircle( *( it - 1 ), lineWidth / 2, lineAngle - M_PI / 2 );
} }
struct OGLPOINT
{
OGLPOINT() :
x( 0.0 ), y( 0.0 ), z( 0.0 )
{}
OGLPOINT( const char* fastest )
{
// do nothing for fastest speed, and keep inline
}
OGLPOINT( const VECTOR2D& aPoint ) :
x( aPoint.x ), y( aPoint.y ), z( 0.0 )
{}
OGLPOINT& operator=( const VECTOR2D& aPoint )
{
x = aPoint.x;
y = aPoint.y;
z = 0.0;
return *this;
}
GLdouble x;
GLdouble y;
GLdouble z;
};
void OPENGL_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList ) void OPENGL_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
{ {
// Any non convex polygon needs to be tesselated // Any non convex polygon needs to be tesselated
...@@ -808,34 +547,32 @@ void OPENGL_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aContro ...@@ -808,34 +547,32 @@ void OPENGL_GAL::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aContro
} }
void OPENGL_GAL::SetStrokeColor( const COLOR4D& aColor ) void OPENGL_GAL::ResizeScreen( int aWidth, int aHeight )
{ {
isSetAttributes = true; screenSize = VECTOR2D( aWidth, aHeight );
strokeColor = aColor;
// This is the default drawing color // Resize framebuffers
currentManager->Color( aColor.r, aColor.g, aColor.b, aColor.a ); compositor.Resize( aWidth, aHeight );
isFramebufferInitialized = false;
wxGLCanvas::SetSize( aWidth, aHeight );
} }
void OPENGL_GAL::SetFillColor( const COLOR4D& aColor ) bool OPENGL_GAL::Show( bool aShow )
{ {
isSetAttributes = true; bool s = wxGLCanvas::Show( aShow );
fillColor = aColor;
}
if( aShow )
wxGLCanvas::Raise();
void OPENGL_GAL::SetBackgroundColor( const COLOR4D& aColor ) return s;
{
isSetAttributes = true;
backgroundColor = aColor;
} }
void OPENGL_GAL::SetLineWidth( double aLineWidth ) void OPENGL_GAL::Flush()
{ {
isSetAttributes = true; glFlush();
lineWidth = aLineWidth;
} }
...@@ -847,6 +584,15 @@ void OPENGL_GAL::ClearScreen() ...@@ -847,6 +584,15 @@ void OPENGL_GAL::ClearScreen()
} }
void OPENGL_GAL::SetStrokeColor( const COLOR4D& aColor )
{
strokeColor = aColor;
// This is the default drawing color
currentManager->Color( aColor.r, aColor.g, aColor.b, aColor.a );
}
void OPENGL_GAL::Transform( MATRIX3x3D aTransformation ) void OPENGL_GAL::Transform( MATRIX3x3D aTransformation )
{ {
GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 }; GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
...@@ -883,12 +629,6 @@ void OPENGL_GAL::Scale( const VECTOR2D& aScale ) ...@@ -883,12 +629,6 @@ void OPENGL_GAL::Scale( const VECTOR2D& aScale )
} }
void OPENGL_GAL::Flush()
{
glFlush();
}
void OPENGL_GAL::Save() void OPENGL_GAL::Save()
{ {
currentManager->PushMatrix(); currentManager->PushMatrix();
...@@ -919,19 +659,6 @@ void OPENGL_GAL::EndGroup() ...@@ -919,19 +659,6 @@ void OPENGL_GAL::EndGroup()
} }
void OPENGL_GAL::ClearCache()
{
groups.clear();
cachedManager.Clear();
}
void OPENGL_GAL::DeleteGroup( int aGroupNumber )
{
groups.erase( aGroupNumber );
}
void OPENGL_GAL::DrawGroup( int aGroupNumber ) void OPENGL_GAL::DrawGroup( int aGroupNumber )
{ {
cachedManager.DrawItem( *groups[aGroupNumber] ); cachedManager.DrawItem( *groups[aGroupNumber] );
...@@ -950,123 +677,48 @@ void OPENGL_GAL::ChangeGroupDepth( int aGroupNumber, int aDepth ) ...@@ -950,123 +677,48 @@ void OPENGL_GAL::ChangeGroupDepth( int aGroupNumber, int aDepth )
} }
void OPENGL_GAL::computeCircle() void OPENGL_GAL::DeleteGroup( int aGroupNumber )
{ {
VERTEX* vertex = circleContainer.Allocate( CIRCLE_POINTS ); groups.erase( aGroupNumber );
// Compute the circle points for a given number of segments
for( int i = 0; i < CIRCLE_POINTS; ++i )
{
vertex->x = 0.0f;
vertex->y = 0.0f;
vertex->z = 0.0f;
vertex++;
vertex->x = cos( 2.0 * M_PI / CIRCLE_POINTS * i );
vertex->y = sin( 2.0 * M_PI / CIRCLE_POINTS * i );
vertex->z = 0.0f;
vertex++;
vertex->x = cos( 2.0 * M_PI / CIRCLE_POINTS * ( i + 1 ) );
vertex->y = sin( 2.0 * M_PI / CIRCLE_POINTS * ( i + 1 ) );
vertex->z = 0.0f;
vertex++;
}
} }
void OPENGL_GAL::ComputeWorldScreenMatrix() void OPENGL_GAL::ClearCache()
{ {
ComputeWorldScale(); groups.clear();
cachedManager.Clear();
worldScreenMatrix.SetIdentity(); }
MATRIX3x3D translation;
translation.SetIdentity();
translation.SetTranslation( 0.5 * screenSize );
MATRIX3x3D scale;
scale.SetIdentity();
scale.SetScale( VECTOR2D( worldScale, worldScale ) );
MATRIX3x3D flip;
flip.SetIdentity();
flip.SetScale( VECTOR2D( 1.0, 1.0 ) );
MATRIX3x3D lookat;
lookat.SetIdentity();
lookat.SetTranslation( -lookAtPoint );
worldScreenMatrix = translation * flip * scale * lookat * worldScreenMatrix; void OPENGL_GAL::SaveScreen()
{
wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
} }
// ------------------------------------- void OPENGL_GAL::RestoreScreen()
// Callback functions for the tesselator {
// ------------------------------------- wxASSERT_MSG( false, wxT( "Not implemented yet" ) );
}
// Compare Redbook Chapter 11
void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData ) void OPENGL_GAL::SetTarget( RenderTarget aTarget )
{ {
GLdouble* vertex = static_cast<GLdouble*>( aVertexPtr ); switch( aTarget )
OPENGL_GAL::TessParams* param = static_cast<OPENGL_GAL::TessParams*>( aData ); {
VERTEX_MANAGER* vboManager = param->vboManager; default:
case TARGET_CACHED:
if( vboManager ) currentManager = &cachedManager;
vboManager->Vertex( vertex[0], vertex[1], vertex[2] ); break;
}
void CALLBACK CombineCallback( GLdouble coords[3],
GLdouble* vertex_data[4],
GLfloat weight[4], GLdouble** dataOut, void* aData )
{
GLdouble* vertex = new GLdouble[3];
OPENGL_GAL::TessParams* param = static_cast<OPENGL_GAL::TessParams*>( aData );
// Save the pointer so we can delete it later
param->intersectPoints.push_back( vertex );
memcpy( vertex, coords, 3 * sizeof(GLdouble) );
*dataOut = vertex;
}
void CALLBACK EdgeCallback(void)
{
// This callback is needed to force GLU tesselator to use triangles only
}
void CALLBACK ErrorCallback( GLenum aErrorCode )
{
const GLubyte* estring;
estring = gluErrorString( aErrorCode );
wxLogError( wxT( "Tessellation Error: %s" ), (char*) estring );
}
void InitTesselatorCallbacks( GLUtesselator* aTesselator )
{
gluTessCallback( aTesselator, GLU_TESS_VERTEX_DATA, ( void (CALLBACK*)() )VertexCallback );
gluTessCallback( aTesselator, GLU_TESS_COMBINE_DATA, ( void (CALLBACK*)() )CombineCallback );
gluTessCallback( aTesselator, GLU_TESS_EDGE_FLAG, ( void (CALLBACK*)() )EdgeCallback );
gluTessCallback( aTesselator, GLU_TESS_ERROR_DATA, ( void (CALLBACK*)() )ErrorCallback );
}
// ---------------
// Cursor handling
// ---------------
case TARGET_NONCACHED:
currentManager = &nonCachedManager;
break;
void OPENGL_GAL::initCursor( int aCursorSize ) case TARGET_OVERLAY:
{ currentManager = &overlayManager;
cursorSize = aCursorSize; break;
}
} }
...@@ -1083,7 +735,7 @@ VECTOR2D OPENGL_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition ) ...@@ -1083,7 +735,7 @@ VECTOR2D OPENGL_GAL::ComputeCursorToWorld( const VECTOR2D& aCursorPosition )
void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition ) void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition )
{ {
wxLogWarning( wxT( "Not tested ") ); wxLogWarning( wxT( "Not tested" ) );
SetCurrent( *glContext ); SetCurrent( *glContext );
...@@ -1096,8 +748,8 @@ void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition ) ...@@ -1096,8 +748,8 @@ void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition )
aCursorPosition = worldScreenMatrix * cursorPositionWorld; aCursorPosition = worldScreenMatrix * cursorPositionWorld;
// Switch to the main framebuffer and blit the scene // Switch to the main framebuffer and blit the scene
//glBindFramebuffer( GL_FRAMEBUFFER, 0 ); // glBindFramebuffer( GL_FRAMEBUFFER, 0 );
//glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity(); glLoadIdentity();
...@@ -1140,7 +792,7 @@ void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition ) ...@@ -1140,7 +792,7 @@ void OPENGL_GAL::DrawCursor( VECTOR2D aCursorPosition )
} }
void OPENGL_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) void OPENGL_GAL::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{ {
compositor.SetBuffer( mainBuffer ); compositor.SetBuffer( mainBuffer );
...@@ -1165,12 +817,247 @@ void OPENGL_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd ...@@ -1165,12 +817,247 @@ void OPENGL_GAL::DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
} }
bool OPENGL_GAL::Show( bool aShow ) inline void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
{ {
bool s = wxGLCanvas::Show( aShow ); VECTOR2D startEndVector = aEndPoint - aStartPoint;
double lineLength = startEndVector.EuclideanNorm();
double scale = 0.5 * lineWidth / lineLength;
if( aShow ) if( lineLength <= 0.0 )
wxGLCanvas::Raise(); return;
return s; // The perpendicular vector also needs transformations
glm::vec4 vector = currentManager->GetTransformation() *
glm::vec4( -startEndVector.y * scale, startEndVector.x * scale, 0.0, 0.0 );
// Line width is maintained by the vertex shader
currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth );
currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v0
currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v1
currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3
currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth );
currentManager->Vertex( aStartPoint.x, aStartPoint.y, layerDepth ); // v0
currentManager->Shader( SHADER_LINE, -vector.x, -vector.y, lineWidth );
currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v3
currentManager->Shader( SHADER_LINE, vector.x, vector.y, lineWidth );
currentManager->Vertex( aEndPoint.x, aEndPoint.y, layerDepth ); // v2
}
void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle )
{
if( isFillEnabled )
{
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
drawFilledSemiCircle( aCenterPoint, aRadius, aAngle );
}
if( isStrokeEnabled )
{
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
drawStrokedSemiCircle( aCenterPoint, aRadius, aAngle );
}
}
void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius,
double aAngle )
{
Save();
currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.0f );
currentManager->Rotate( aAngle, 0.0f, 0.0f, 1.0f );
/* Draw a triangle that contains the semicircle, then shade it to leave only
* the semicircle. Parameters given to setShader are indices of the triangle's vertices
* (if you want to understand more, check the vertex shader source [shader.vert]).
* Shader uses this coordinates to determine if fragments are inside the semicircle or not.
* v2
* /\
* /__\
* v0 //__\\ v1
*/
currentManager->Shader( SHADER_FILLED_CIRCLE, 4.0f );
currentManager->Vertex( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0
currentManager->Shader( SHADER_FILLED_CIRCLE, 5.0f );
currentManager->Vertex( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1
currentManager->Shader( SHADER_FILLED_CIRCLE, 6.0f );
currentManager->Vertex( 0.0f, aRadius * 2.0f, layerDepth ); // v2
Restore();
}
void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius,
double aAngle )
{
double outerRadius = aRadius + ( lineWidth / 2 );
Save();
currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.0f );
currentManager->Rotate( aAngle, 0.0f, 0.0f, 1.0f );
/* Draw a triangle that contains the semicircle, then shade it to leave only
* the semicircle. Parameters given to setShader are indices of the triangle's vertices
* (if you want to understand more, check the vertex shader source [shader.vert]), the
* radius and the line width. Shader uses this coordinates to determine if fragments are
* inside the semicircle or not.
* v2
* /\
* /__\
* v0 //__\\ v1
*/
currentManager->Shader( SHADER_STROKED_CIRCLE, 4.0f, aRadius, lineWidth );
currentManager->Vertex( -outerRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0
currentManager->Shader( SHADER_STROKED_CIRCLE, 5.0f, aRadius, lineWidth );
currentManager->Vertex( outerRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1
currentManager->Shader( SHADER_STROKED_CIRCLE, 6.0f, aRadius, lineWidth );
currentManager->Vertex( 0.0f, outerRadius * 2.0f, layerDepth ); // v2
Restore();
}
void OPENGL_GAL::onPaint( wxPaintEvent& aEvent )
{
PostPaint();
}
void OPENGL_GAL::skipMouseEvent( wxMouseEvent& aEvent )
{
// Post the mouse event to the event listener registered in constructor, if any
if( mouseListener )
wxPostEvent( mouseListener, aEvent );
}
void OPENGL_GAL::initGlew()
{
// Initialize GLEW library
GLenum err = glewInit();
if( GLEW_OK != err )
{
wxLogError( wxString::FromUTF8( (char*) glewGetErrorString( err ) ) );
exit( 1 );
}
else
{
wxLogDebug( wxString( wxT( "Status: Using GLEW " ) ) +
FROM_UTF8( (char*) glewGetString( GLEW_VERSION ) ) );
}
// Check the OpenGL version (minimum 2.1 is required)
if( GLEW_VERSION_2_1 )
{
wxLogInfo( wxT( "OpenGL Version 2.1 supported." ) );
}
else
{
wxLogError( wxT( "OpenGL Version 2.1 is not supported!" ) );
exit( 1 );
}
// Framebuffers have to be supported
if( !GLEW_ARB_framebuffer_object )
{
wxLogError( wxT( "Framebuffer objects are not supported!" ) );
exit( 1 );
}
// Vertex buffer have to be supported
if( !GLEW_ARB_vertex_buffer_object )
{
wxLogError( wxT( "Vertex buffer objects are not supported!" ) );
exit( 1 );
}
isGlewInitialized = true;
}
void OPENGL_GAL::initCursor( int aCursorSize )
{
cursorSize = aCursorSize;
}
unsigned int OPENGL_GAL::getNewGroupNumber()
{
wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(),
wxT( "There are no free slots to store a group" ) );
while( groups.find( groupCounter ) != groups.end() )
{
groupCounter++;
}
return groupCounter++;
}
// -------------------------------------
// Callback functions for the tesselator
// -------------------------------------
// Compare Redbook Chapter 11
void CALLBACK VertexCallback( GLvoid* aVertexPtr, void* aData )
{
GLdouble* vertex = static_cast<GLdouble*>( aVertexPtr );
OPENGL_GAL::TessParams* param = static_cast<OPENGL_GAL::TessParams*>( aData );
VERTEX_MANAGER* vboManager = param->vboManager;
if( vboManager )
vboManager->Vertex( vertex[0], vertex[1], vertex[2] );
}
void CALLBACK CombineCallback( GLdouble coords[3],
GLdouble* vertex_data[4],
GLfloat weight[4], GLdouble** dataOut, void* aData )
{
GLdouble* vertex = new GLdouble[3];
OPENGL_GAL::TessParams* param = static_cast<OPENGL_GAL::TessParams*>( aData );
// Save the pointer so we can delete it later
param->intersectPoints.push_back( vertex );
memcpy( vertex, coords, 3 * sizeof(GLdouble) );
*dataOut = vertex;
}
void CALLBACK EdgeCallback()
{
// This callback is needed to force GLU tesselator to use triangles only
}
void CALLBACK ErrorCallback( GLenum aErrorCode )
{
const GLubyte* estring;
estring = gluErrorString( aErrorCode );
wxLogError( wxT( "Tessellation Error: %s" ), (char*) estring );
}
void InitTesselatorCallbacks( GLUtesselator* aTesselator )
{
gluTessCallback( aTesselator, GLU_TESS_VERTEX_DATA, ( void (CALLBACK*)() )VertexCallback );
gluTessCallback( aTesselator, GLU_TESS_COMBINE_DATA, ( void (CALLBACK*)() )CombineCallback );
gluTessCallback( aTesselator, GLU_TESS_EDGE_FLAG, ( void (CALLBACK*)() )EdgeCallback );
gluTessCallback( aTesselator, GLU_TESS_ERROR_DATA, ( void (CALLBACK*)() )ErrorCallback );
} }
...@@ -97,7 +97,8 @@ bool SHADER::Link() ...@@ -97,7 +97,8 @@ bool SHADER::Link()
programInfo( programNumber ); programInfo( programNumber );
// Check the Link state // Check the Link state
glGetObjectParameterivARB( programNumber, GL_OBJECT_LINK_STATUS_ARB, (GLint*) &isShaderLinked ); glGetObjectParameterivARB( programNumber, GL_OBJECT_LINK_STATUS_ARB,
(GLint*) &isShaderLinked );
#ifdef __WXDEBUG__ #ifdef __WXDEBUG__
if( !isShaderLinked ) if( !isShaderLinked )
...@@ -253,6 +254,7 @@ bool SHADER::addSource( const std::string& aShaderSource, ShaderType aShaderType ...@@ -253,6 +254,7 @@ bool SHADER::addSource( const std::string& aShaderSource, ShaderType aShaderType
glCompileShader( shaderNumber ); glCompileShader( shaderNumber );
GLint status; GLint status;
glGetShaderiv( shaderNumber, GL_COMPILE_STATUS, &status ); glGetShaderiv( shaderNumber, GL_COMPILE_STATUS, &status );
if( status != GL_TRUE ) if( status != GL_TRUE )
{ {
wxLogError( wxT( "Shader compilation error" ) ); wxLogError( wxT( "Shader compilation error" ) );
...@@ -275,4 +277,3 @@ bool SHADER::addSource( const std::string& aShaderSource, ShaderType aShaderType ...@@ -275,4 +277,3 @@ bool SHADER::addSource( const std::string& aShaderSource, ShaderType aShaderType
return true; return true;
} }
...@@ -52,6 +52,7 @@ void VERTEX_MANAGER::Vertex( GLfloat aX, GLfloat aY, GLfloat aZ ) const ...@@ -52,6 +52,7 @@ void VERTEX_MANAGER::Vertex( GLfloat aX, GLfloat aY, GLfloat aZ ) const
{ {
// Obtain the pointer to the vertex in the currently used container // Obtain the pointer to the vertex in the currently used container
VERTEX* newVertex = m_container->Allocate( 1 ); VERTEX* newVertex = m_container->Allocate( 1 );
if( newVertex == NULL ) if( newVertex == NULL )
{ {
wxLogError( wxT( "Vertex allocation error" ) ); wxLogError( wxT( "Vertex allocation error" ) );
...@@ -66,6 +67,7 @@ void VERTEX_MANAGER::Vertices( const VERTEX aVertices[], unsigned int aSize ) co ...@@ -66,6 +67,7 @@ void VERTEX_MANAGER::Vertices( const VERTEX aVertices[], unsigned int aSize ) co
{ {
// Obtain pointer to the vertex in currently used container // Obtain pointer to the vertex in currently used container
VERTEX* newVertex = m_container->Allocate( aSize ); VERTEX* newVertex = m_container->Allocate( aSize );
if( newVertex == NULL ) if( newVertex == NULL )
{ {
wxLogError( wxT( "Vertex allocation error" ) ); wxLogError( wxT( "Vertex allocation error" ) );
...@@ -158,6 +160,7 @@ void VERTEX_MANAGER::BeginDrawing() const ...@@ -158,6 +160,7 @@ void VERTEX_MANAGER::BeginDrawing() const
void VERTEX_MANAGER::DrawItem( const VERTEX_ITEM& aItem ) const void VERTEX_MANAGER::DrawItem( const VERTEX_ITEM& aItem ) const
{ {
int size = aItem.GetSize(); int size = aItem.GetSize();
if( size > 0 ) if( size > 0 )
{ {
int offset = aItem.GetOffset(); int offset = aItem.GetOffset();
......
...@@ -85,7 +85,6 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& event ) ...@@ -85,7 +85,6 @@ void WX_VIEW_CONTROLS::onWheel( wxMouseEvent& event )
else else
scrollSpeed = scrollVec.y; scrollSpeed = scrollVec.y;
VECTOR2D t = m_view->GetScreenPixelSize();
VECTOR2D delta( event.ControlDown() ? -scrollSpeed : 0.0, VECTOR2D delta( event.ControlDown() ? -scrollSpeed : 0.0,
event.ShiftDown() ? -scrollSpeed : 0.0 ); event.ShiftDown() ? -scrollSpeed : 0.0 );
......
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
namespace KiGfx namespace KiGfx
{ {
class CAIRO_COMPOSITOR : public COMPOSITOR class CAIRO_COMPOSITOR : public COMPOSITOR
{ {
public: public:
...@@ -102,7 +101,6 @@ protected: ...@@ -102,7 +101,6 @@ protected:
return m_buffers.size(); return m_buffers.size();
} }
}; };
} // namespace KiGfx } // namespace KiGfx
#endif /* COMPOSITOR_H_ */ #endif /* COMPOSITOR_H_ */
...@@ -45,9 +45,6 @@ ...@@ -45,9 +45,6 @@
#endif #endif
#endif #endif
#define EXCEPTION_ZERO_CLIENT_RECTANGLE 0
#define EXCEPTION_ZERO_CONTEXT 1
/** /**
* @brief Class CAIRO_GAL is the cairo implementation of the graphics abstraction layer. * @brief Class CAIRO_GAL is the cairo implementation of the graphics abstraction layer.
* *
...@@ -92,7 +89,7 @@ public: ...@@ -92,7 +89,7 @@ public:
// --------------- // ---------------
/// @copydoc GAL::BeginDrawing() /// @copydoc GAL::BeginDrawing()
virtual void BeginDrawing() throw (int); virtual void BeginDrawing();
/// @copydoc GAL::EndDrawing() /// @copydoc GAL::EndDrawing()
virtual void EndDrawing(); virtual void EndDrawing();
...@@ -103,19 +100,19 @@ public: ...@@ -103,19 +100,19 @@ public:
/// @copydoc GAL::DrawSegment() /// @copydoc GAL::DrawSegment()
virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth ); virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth );
/// @copydoc GAL::DrawPolyline()
virtual void DrawPolyline( std::deque<VECTOR2D>& aPointList );
/// @copydoc GAL::DrawCircle() /// @copydoc GAL::DrawCircle()
virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ); virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius );
/// @copydoc GAL::DrawArc() /// @copydoc GAL::DrawArc()
virtual void virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle ); double aStartAngle, double aEndAngle );
/// @copydoc GAL::DrawRectangle() /// @copydoc GAL::DrawRectangle()
virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
/// @copydoc GAL::DrawPolyline()
virtual void DrawPolyline( std::deque<VECTOR2D>& aPointList );
/// @copydoc GAL::DrawPolygon() /// @copydoc GAL::DrawPolygon()
virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList ); virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList );
...@@ -149,24 +146,15 @@ public: ...@@ -149,24 +146,15 @@ public:
/// @copydoc GAL::SetIsStroke() /// @copydoc GAL::SetIsStroke()
virtual void SetIsStroke( bool aIsStrokeEnabled ); virtual void SetIsStroke( bool aIsStrokeEnabled );
/// @copydoc GAL::SetFillColor()
virtual void SetFillColor( const COLOR4D& aColor );
/// @copydoc GAL::SetStrokeColor() /// @copydoc GAL::SetStrokeColor()
virtual void SetStrokeColor( const COLOR4D& aColor ); virtual void SetStrokeColor( const COLOR4D& aColor );
/// @copydoc GAL::GetStrokeColor() /// @copydoc GAL::SetFillColor()
COLOR4D GetStrokeColor(); virtual void SetFillColor( const COLOR4D& aColor );
/// @copydoc GAL::SetBackgroundColor()
virtual void SetBackgroundColor( const COLOR4D& aColor );
/// @copydoc GAL::SetLineWidth() /// @copydoc GAL::SetLineWidth()
virtual void SetLineWidth( double aLineWidth ); virtual void SetLineWidth( double aLineWidth );
/// @copydoc GAL::GetLineWidth()
double GetLineWidth();
/// @copydoc GAL::SetLayerDepth() /// @copydoc GAL::SetLayerDepth()
virtual void SetLayerDepth( double aLayerDepth ); virtual void SetLayerDepth( double aLayerDepth );
...@@ -221,33 +209,6 @@ public: ...@@ -221,33 +209,6 @@ public:
// Handling the world <-> screen transformation // Handling the world <-> screen transformation
// -------------------------------------------------------- // --------------------------------------------------------
/// @copydoc GAL::ComputeWorldScreenMatrix()
virtual void ComputeWorldScreenMatrix();
/// @copydoc GAL::GetWorldScreenMatrix()
MATRIX3x3D GetWorldScreenMatrix();
/// @copydoc GAL::SetWorldScreenMatrix()
void SetWorldScreenMatrix( MATRIX3x3D aMatrix );
/// @copydoc GAL::SetWorldUnitLength()
void SetWorldUnitLength( double aWorldUnitLength );
/// @copydoc GAL::SetScreenDPI()
void SetScreenDPI( double aScreenDPI );
/// @copydoc GAL::SetLookAtPoint()
void SetLookAtPoint( const VECTOR2D& aPoint );
/// @copydoc GAL::GetLookAtPoint()
VECTOR2D GetLookAtPoint();
/// @copydoc GAL::SetZoomFactor()
void SetZoomFactor( double aZoomFactor );
/// @copydoc GAL::GetZoomFactor()
double GetZoomFactor();
/// @copydoc GAL::SaveScreen() /// @copydoc GAL::SaveScreen()
virtual void SaveScreen(); virtual void SaveScreen();
...@@ -264,9 +225,6 @@ public: ...@@ -264,9 +225,6 @@ public:
/// @copydoc GAL::ComputeCursorToWorld() /// @copydoc GAL::ComputeCursorToWorld()
virtual VECTOR2D ComputeCursorToWorld( const VECTOR2D& aCursorPosition ); virtual VECTOR2D ComputeCursorToWorld( const VECTOR2D& aCursorPosition );
/// @copydoc GAL::SetIsCursorEnabled()
void SetIsCursorEnabled( bool aIsCursorEnabled );
/// @copydoc GAL::DrawCursor() /// @copydoc GAL::DrawCursor()
virtual void DrawCursor( VECTOR2D aCursorPosition ); virtual void DrawCursor( VECTOR2D aCursorPosition );
...@@ -295,7 +253,7 @@ public: ...@@ -295,7 +253,7 @@ public:
} }
protected: protected:
virtual void DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
private: private:
/// Super class definition /// Super class definition
...@@ -325,8 +283,7 @@ private: ...@@ -325,8 +283,7 @@ private:
static const int MAX_CAIRO_ARGUMENTS = 6; static const int MAX_CAIRO_ARGUMENTS = 6;
/// Definitions for the command recorder /// Definitions for the command recorder
enum GraphicsCommand enum GraphicsCommand {
{
CMD_SET_FILL, ///< Enable/disable filling CMD_SET_FILL, ///< Enable/disable filling
CMD_SET_STROKE, ///< Enable/disable stroking CMD_SET_STROKE, ///< Enable/disable stroking
CMD_SET_FILLCOLOR, ///< Set the fill color CMD_SET_FILLCOLOR, ///< Set the fill color
...@@ -392,18 +349,18 @@ private: ...@@ -392,18 +349,18 @@ private:
/// @copydoc GAL::initCursor() /// @copydoc GAL::initCursor()
virtual void initCursor( int aCursorSize ); virtual void initCursor( int aCursorSize );
/// Allocate the bitmaps for drawing
void allocateBitmaps();
/// Allocate the bitmaps for drawing
void deleteBitmaps();
/// 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();
/// Allocate the bitmaps for drawing
void allocateBitmaps();
/// Allocate the bitmaps for drawing
void deleteBitmaps();
/// Prepare the compositor /// Prepare the compositor
void setCompositor(); void setCompositor();
......
...@@ -231,7 +231,10 @@ public: ...@@ -231,7 +231,10 @@ public:
* *
* @param aColor is the color for background filling. * @param aColor is the color for background filling.
*/ */
virtual void SetBackgroundColor( const COLOR4D& aColor ) = 0; inline virtual void SetBackgroundColor( const COLOR4D& aColor )
{
backgroundColor = aColor;
}
/** /**
* @brief Set the line width. * @brief Set the line width.
...@@ -417,7 +420,7 @@ public: ...@@ -417,7 +420,7 @@ public:
// -------------------------------------------------------- // --------------------------------------------------------
/// @brief Compute the world <-> screen transformation matrix /// @brief Compute the world <-> screen transformation matrix
virtual void ComputeWorldScreenMatrix() = 0; virtual void ComputeWorldScreenMatrix();
/** /**
* @brief Get the world <-> screen transformation matrix. * @brief Get the world <-> screen transformation matrix.
...@@ -745,7 +748,6 @@ protected: ...@@ -745,7 +748,6 @@ protected:
bool isFillEnabled; ///< Is filling of graphic objects enabled ? bool isFillEnabled; ///< Is filling of graphic objects enabled ?
bool isStrokeEnabled; ///< Are the outlines stroked ? bool isStrokeEnabled; ///< Are the outlines stroked ?
bool isSetAttributes; ///< True, if the attributes have been set
COLOR4D backgroundColor; ///< The background color COLOR4D backgroundColor; ///< The background color
COLOR4D fillColor; ///< The fill color COLOR4D fillColor; ///< The fill color
...@@ -784,7 +786,7 @@ protected: ...@@ -784,7 +786,7 @@ protected:
* @param aStartPoint is the start point of the line. * @param aStartPoint is the start point of the line.
* @param aEndPoint is the end point of the line. * @param aEndPoint is the end point of the line.
*/ */
virtual void DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) = 0; virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) = 0;
/** /**
* @brief Initialize the cursor. * @brief Initialize the cursor.
......
...@@ -37,7 +37,6 @@ ...@@ -37,7 +37,6 @@
namespace KiGfx namespace KiGfx
{ {
class OPENGL_COMPOSITOR : public COMPOSITOR class OPENGL_COMPOSITOR : public COMPOSITOR
{ {
public: public:
...@@ -94,7 +93,6 @@ protected: ...@@ -94,7 +93,6 @@ protected:
return m_buffers.size(); return m_buffers.size();
} }
}; };
} // namespace KiGfx } // namespace KiGfx
#endif /* COMPOSITOR_H_ */ #endif /* COMPOSITOR_H_ */
...@@ -104,19 +104,19 @@ public: ...@@ -104,19 +104,19 @@ public:
/// @copydoc GAL::DrawSegment() /// @copydoc GAL::DrawSegment()
virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth ); virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth );
/// @copydoc GAL::DrawPolyline()
virtual void DrawPolyline( std::deque<VECTOR2D>& aPointList );
/// @copydoc GAL::DrawCircle() /// @copydoc GAL::DrawCircle()
virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ); virtual void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius );
/// @copydoc GAL::DrawArc() /// @copydoc GAL::DrawArc()
virtual void virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle ); double aStartAngle, double aEndAngle );
/// @copydoc GAL::DrawRectangle() /// @copydoc GAL::DrawRectangle()
virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
/// @copydoc GAL::DrawPolyline()
virtual void DrawPolyline( std::deque<VECTOR2D>& aPointList );
/// @copydoc GAL::DrawPolygon() /// @copydoc GAL::DrawPolygon()
virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList ); virtual void DrawPolygon( const std::deque<VECTOR2D>& aPointList );
...@@ -129,7 +129,7 @@ public: ...@@ -129,7 +129,7 @@ public:
// -------------- // --------------
/// @brief Resizes the canvas. /// @brief Resizes the canvas.
virtual void ResizeScreen ( int aWidth, int aHeight ); virtual void ResizeScreen( int aWidth, int aHeight );
/// @brief Shows/hides the GAL canvas /// @brief Shows/hides the GAL canvas
virtual bool Show( bool aShow ); virtual bool Show( bool aShow );
...@@ -144,42 +144,9 @@ public: ...@@ -144,42 +144,9 @@ public:
// Attribute setting // Attribute setting
// ----------------- // -----------------
/// @copydoc GAL::SetIsFill()
virtual void SetIsFill( bool aIsFillEnabled )
{
isFillEnabled = aIsFillEnabled;
}
/// @copydoc GAL::SetIsStroke()
virtual void SetIsStroke( bool aIsStrokeEnabled )
{
isStrokeEnabled = aIsStrokeEnabled;
}
/// @copydoc GAL::SetFillColor()
virtual void SetFillColor( const COLOR4D& aColor );
/// @copydoc GAL::SetStrokeColor() /// @copydoc GAL::SetStrokeColor()
virtual void SetStrokeColor( const COLOR4D& aColor ); virtual void SetStrokeColor( const COLOR4D& aColor );
/// @copydoc GAL::GetStrokeColor()
COLOR4D GetStrokeColor();
/// @copydoc GAL::SetBackgroundColor()
virtual void SetBackgroundColor( const COLOR4D& aColor );
/// @copydoc GAL::SetLineWidth()
virtual void SetLineWidth( double aLineWidth );
/// @copydoc GAL::GetLineWidth()
double GetLineWidth();
/// @copydoc GAL::SetLayerDepth()
virtual void SetLayerDepth( double aLayerDepth )
{
super::SetLayerDepth( aLayerDepth );
}
// -------------- // --------------
// Transformation // Transformation
// -------------- // --------------
...@@ -231,33 +198,6 @@ public: ...@@ -231,33 +198,6 @@ public:
// Handling the world <-> screen transformation // Handling the world <-> screen transformation
// -------------------------------------------------------- // --------------------------------------------------------
/// @copydoc GAL::ComputeWorldScreenMatrix()
virtual void ComputeWorldScreenMatrix();
/// @copydoc GAL::GetWorldScreenMatrix()
MATRIX3x3D GetWorldScreenMatrix();
/// @copydoc GAL::SetWorldScreenMatrix()
void SetWorldScreenMatrix( MATRIX3x3D aMatrix );
/// @copydoc GAL::SetWorldUnitLength()
void SetWorldUnitLength( double aWorldUnitLength );
/// @copydoc GAL::SetScreenDPI()
void SetScreenDPI( double aScreenDPI );
/// @copydoc GAL::SetLookAtPoint()
void SetLookAtPoint( const VECTOR2D& aPoint );
/// @copydoc GAL::GetLookAtPoint()
VECTOR2D GetLookAtPoint();
/// @copydoc GAL::SetZoomFactor()
void SetZoomFactor( double aZoomFactor );
/// @copydoc GAL::GetZoomFactor()
double GetZoomFactor();
/// @copydoc GAL::SaveScreen() /// @copydoc GAL::SaveScreen()
virtual void SaveScreen(); virtual void SaveScreen();
...@@ -274,9 +214,6 @@ public: ...@@ -274,9 +214,6 @@ public:
/// @copydoc GAL::ComputeCursorToWorld() /// @copydoc GAL::ComputeCursorToWorld()
virtual VECTOR2D ComputeCursorToWorld( const VECTOR2D& aCursorPosition ); virtual VECTOR2D ComputeCursorToWorld( const VECTOR2D& aCursorPosition );
/// @copydoc GAL::SetIsCursorEnabled()
void SetIsCursorEnabled( bool aIsCursorEnabled );
/// @copydoc GAL::DrawCursor() /// @copydoc GAL::DrawCursor()
virtual void DrawCursor( VECTOR2D aCursorPosition ); virtual void DrawCursor( VECTOR2D aCursorPosition );
...@@ -312,7 +249,7 @@ public: ...@@ -312,7 +249,7 @@ public:
} TessParams; } TessParams;
protected: protected:
virtual void DrawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ); virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
private: private:
/// Super class definition /// Super class definition
...@@ -327,9 +264,6 @@ private: ...@@ -327,9 +264,6 @@ private:
wxEvtHandler* mouseListener; wxEvtHandler* mouseListener;
wxEvtHandler* paintListener; wxEvtHandler* paintListener;
// Precomputed vertices for faster circle & semicircle drawing
NONCACHED_CONTAINER circleContainer; ///< Container for storing circle vertices
// Vertex buffer objects related fields // Vertex buffer objects related fields
typedef std::map< unsigned int, boost::shared_ptr<VERTEX_ITEM> > GroupsMap; typedef std::map< unsigned int, boost::shared_ptr<VERTEX_ITEM> > GroupsMap;
GroupsMap groups; ///< Stores informations about VBO objects (groups) GroupsMap groups; ///< Stores informations about VBO objects (groups)
...@@ -344,10 +278,6 @@ private: ...@@ -344,10 +278,6 @@ private:
unsigned int mainBuffer; ///< Main rendering target unsigned int mainBuffer; ///< Main rendering target
unsigned int overlayBuffer; ///< Auxiliary rendering target (for menus etc.) unsigned int overlayBuffer; ///< Auxiliary rendering target (for menus etc.)
// Polygon tesselation
GLUtesselator* tesselator; ///< Pointer to the tesselator
std::vector<GLdouble*> tessIntersects; ///< Storage of intersecting points
// Shader // Shader
SHADER shader; ///< There is only one shader used for different objects SHADER shader; ///< There is only one shader used for different objects
...@@ -363,48 +293,79 @@ private: ...@@ -363,48 +293,79 @@ private:
bool isShaderInitialized; ///< Was the shader initialized? bool isShaderInitialized; ///< Was the shader initialized?
bool isGrouping; ///< Was a group started? bool isGrouping; ///< Was a group started?
// Polygon tesselation
GLUtesselator* tesselator; ///< Pointer to the tesselator
std::vector<GLdouble*> tessIntersects; ///< Storage of intersecting points
// Structure used for tesselation of polygons
struct OGLPOINT
{
OGLPOINT() :
x( 0.0 ), y( 0.0 ), z( 0.0 )
{}
OGLPOINT( const char* fastest )
{
// do nothing for fastest speed, and keep inline
}
OGLPOINT( const VECTOR2D& aPoint ) :
x( aPoint.x ), y( aPoint.y ), z( 0.0 )
{}
OGLPOINT& operator=( const VECTOR2D& aPoint )
{
x = aPoint.x;
y = aPoint.y;
z = 0.0;
return *this;
}
GLdouble x;
GLdouble y;
GLdouble z;
};
/** /**
* @brief Draw a semi circle. Depending on settings (isStrokeEnabled & isFilledEnabled) it runs * @brief Draw a quad for the line.
*
* @param aStartPoint is the start point of the line.
* @param aEndPoint is the end point of the line.
*/
inline void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
/**
* @brief Draw a semicircle. Depending on settings (isStrokeEnabled & isFilledEnabled) it runs
* the proper function (drawStrokedSemiCircle or drawFilledSemiCircle). * the proper function (drawStrokedSemiCircle or drawFilledSemiCircle).
* *
* @param aCenterPoint is the center point. * @param aCenterPoint is the center point.
* @param aRadius is the radius of the semi-circle. * @param aRadius is the radius of the semicircle.
* @param aAngle is the angle of the semi-circle. * @param aAngle is the angle of the semicircle.
* *
*/ */
void drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ); void drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
/** /**
* @brief Draw a filled semi circle. * @brief Draw a filled semicircle.
* *
* @param aCenterPoint is the center point. * @param aCenterPoint is the center point.
* @param aRadius is the radius of the semi-circle. * @param aRadius is the radius of the semicircle.
* @param aAngle is the angle of the semi-circle. * @param aAngle is the angle of the semicircle.
* *
*/ */
void drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ); void drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
/** /**
* @brief Draw a stroked semi circle. * @brief Draw a stroked semicircle.
* *
* @param aCenterPoint is the center point. * @param aCenterPoint is the center point.
* @param aRadius is the radius of the semi-circle. * @param aRadius is the radius of the semicircle.
* @param aAngle is the angle of the semi-circle. * @param aAngle is the angle of the semicircle.
* *
*/ */
void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ); void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
/// Compute the points of the unit circle and store them in VBO.
void computeCircle();
// Event handling // Event handling
/**
* @brief This is the window creation event handler.
*
* @param aEvent is the window creation event.
*/
void onCreate( wxWindowCreateEvent& aEvent );
/** /**
* @brief This is the OnPaint event handler. * @brief This is the OnPaint event handler.
* *
...@@ -419,20 +380,12 @@ private: ...@@ -419,20 +380,12 @@ private:
*/ */
void skipMouseEvent( wxMouseEvent& aEvent ); void skipMouseEvent( wxMouseEvent& aEvent );
/// Initialize GLEW. /// Initialize GLEW
void initGlew(); void initGlew();
/// @copydoc GAL::initCursor() /// @copydoc GAL::initCursor()
virtual void initCursor( int aCursorSize ); virtual void initCursor( int aCursorSize );
/**
* @brief Draw a quad for the line.
*
* @param aStartPoint is the start point of the line.
* @param aEndPoint is the end point of the line.
*/
inline void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
/** /**
* @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.
* *
......
...@@ -35,8 +35,7 @@ ...@@ -35,8 +35,7 @@
namespace KiGfx namespace KiGfx
{ {
// Possible types of shaders // Possible types of shaders
enum SHADER_TYPE enum SHADER_TYPE {
{
SHADER_NONE = 0, SHADER_NONE = 0,
SHADER_LINE, SHADER_LINE,
SHADER_FILLED_CIRCLE, SHADER_FILLED_CIRCLE,
......
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