Loading common/gal/cairo/cairo_gal.cpp +2 −58 Original line number Diff line number Diff line Loading @@ -72,15 +72,6 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); #endif // Initialize line attributes map lineCapMap[LINE_CAP_BUTT] = CAIRO_LINE_CAP_BUTT; lineCapMap[LINE_CAP_ROUND] = CAIRO_LINE_CAP_ROUND; lineCapMap[LINE_CAP_SQUARED] = CAIRO_LINE_CAP_SQUARE; lineJoinMap[LINE_JOIN_BEVEL] = CAIRO_LINE_JOIN_BEVEL; lineJoinMap[LINE_JOIN_ROUND] = CAIRO_LINE_JOIN_ROUND; lineJoinMap[LINE_JOIN_MITER] = CAIRO_LINE_JOIN_MITER; // Initialize the cursor shape SetCursorColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) ); initCursor( 21 ); Loading Loading @@ -179,8 +170,8 @@ void CAIRO_GAL::initSurface() cairo_new_path( cairoImage ); isElementAdded = true; cairo_set_line_join( cairoImage, lineJoinMap[lineJoin] ); cairo_set_line_cap( cairoImage, lineCapMap[lineCap] ); cairo_set_line_join( cairoImage, CAIRO_LINE_JOIN_ROUND ); cairo_set_line_cap( cairoImage, CAIRO_LINE_CAP_ROUND ); lineWidth = 0; Loading Loading @@ -298,9 +289,6 @@ void CAIRO_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth ) { cairo_set_line_cap( cairoImage, CAIRO_LINE_CAP_ROUND ); cairo_set_line_join( cairoImage, CAIRO_LINE_JOIN_ROUND ); if( isFillEnabled ) { SetLineWidth( aWidth ); Loading Loading @@ -520,42 +508,6 @@ void CAIRO_GAL::SetLineWidth( double aLineWidth ) } void CAIRO_GAL::SetLineCap( LineCap aLineCap ) { storePath(); lineCap = aLineCap; cairo_set_line_cap( cairoImage, lineCapMap[aLineCap] ); if( isGrouping ) { GroupElement groupElement; groupElement.command = CMD_SET_LINE_CAP; groupElement.intArgument = (int) aLineCap; currentGroup->push_back( groupElement ); } } void CAIRO_GAL::SetLineJoin( LineJoin aLineJoin ) { storePath(); lineJoin = aLineJoin; cairo_set_line_join( cairoImage, lineJoinMap[aLineJoin] ); if( isGrouping ) { GroupElement groupElement; groupElement.command = CMD_SET_LINE_JOIN; groupElement.intArgument = (int) aLineJoin; currentGroup->push_back( groupElement ); } } void CAIRO_GAL::ClearScreen() { // Clear screen Loading Loading @@ -767,14 +719,6 @@ void CAIRO_GAL::DrawGroup( int aGroupNumber ) cairo_set_line_width( cairoImage, it->arguments[0] ); break; case CMD_SET_LINE_JOIN: cairo_set_line_join( cairoImage, lineJoinMap[(LineJoin) ( it->intArgument )] ); break; case CMD_SET_LINE_CAP: cairo_set_line_cap( cairoImage, lineCapMap[(LineCap) ( it->intArgument )] ); break; case CMD_STROKE_PATH: cairo_set_source_rgb( cairoImage, strokeColor.r, strokeColor.g, strokeColor.b ); cairo_append_path( cairoImage, it->cairoPath ); Loading common/gal/graphics_abstraction_layer.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -38,8 +38,6 @@ GAL::GAL() // Set the default values for the internal variables SetIsFill( false ); SetIsStroke( true ); SetLineJoin( LINE_JOIN_ROUND ); SetLineCap( LINE_CAP_ROUND ); SetIsCursorEnabled( false ); SetZoomFactor( 1.0 ); SetFillColor( COLOR4D( 0.0, 0.0, 0.0, 0.0 ) ); Loading common/gal/opengl/opengl_gal.cpp +144 −296 Original line number Diff line number Diff line Loading @@ -658,9 +658,11 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); SetLineWidth( aWidth ); drawSemiCircle( aStartPoint, aWidth / 2, lineAngle + M_PI / 2 ); drawSemiCircle( aEndPoint, aWidth / 2, lineAngle - M_PI / 2 ); drawLineQuad( aStartPoint, aEndPoint ); // Draw line caps drawFilledSemiCircle( aStartPoint, aWidth / 2, lineAngle + M_PI / 2 ); drawFilledSemiCircle( aEndPoint, aWidth / 2, lineAngle - M_PI / 2 ); } else { Loading @@ -680,41 +682,15 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP drawLineQuad( VECTOR2D( 0.0, -aWidth / 2.0 ), VECTOR2D( lineLength, -aWidth / 2.0 ) ); drawSemiCircle( VECTOR2D( 0.0, 0.0 ), aWidth / 2, M_PI / 2 ); drawSemiCircle( VECTOR2D( lineLength, 0.0 ), aWidth / 2, -M_PI / 2 ); // Draw line caps drawStrokedSemiCircle( VECTOR2D( 0.0, 0.0 ), ( aWidth + lineWidth ) / 2, M_PI / 2 ); drawStrokedSemiCircle( VECTOR2D( lineLength, 0.0 ), ( aWidth + lineWidth ) / 2, -M_PI / 2 ); Restore(); } } inline void OPENGL_GAL::drawLineCap( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) { VECTOR2D startEndVector = aEndPoint - aStartPoint; // double lineLength = startEndVector.EuclideanNorm(); double lineAngle = startEndVector.Angle(); switch( lineCap ) { case LINE_CAP_BUTT: // TODO break; case LINE_CAP_ROUND: // Add a semicircle at the line end drawSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 ); break; case LINE_CAP_SQUARED: // FIXME? VECTOR2D offset; // offset = startEndVector * ( lineWidth / lineLength / 2.0 ); // aStartPoint = aStartPoint - offset; // aEndPoint = aEndPoint + offset; break; } } unsigned int OPENGL_GAL::getGroupNumber() { wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(), Loading @@ -731,32 +707,19 @@ unsigned int OPENGL_GAL::getGroupNumber() void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) { if( isFillEnabled ) { color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); const VECTOR2D startEndVector = aEndPoint - aStartPoint; double lineAngle = startEndVector.Angle(); drawLineCap( aStartPoint, aEndPoint ); drawLineCap( aEndPoint, aStartPoint ); drawLineQuad( aStartPoint, aEndPoint ); } if( isStrokeEnabled ) { // TODO outline mode color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); drawLineCap( aStartPoint, aEndPoint ); drawLineCap( aEndPoint, aStartPoint ); drawLineQuad( aStartPoint, aEndPoint ); } // Line caps drawFilledSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 ); drawFilledSemiCircle( aEndPoint, lineWidth / 2, lineAngle + M_PI / 2 ); } void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList ) { if( isUseShader ) { // This method reduces amount of triangles used for drawing std::deque<VECTOR2D>::const_iterator it = aPointList.begin(); // Start from the second point Loading @@ -764,223 +727,6 @@ void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList ) { DrawLine( *( it - 1 ), *it ); } return; } bool isFirstPoint = true; LineCap savedLineCap = lineCap; bool isFirstLine = true; VECTOR2D startEndVector; VECTOR2D lastStartEndVector; VECTOR2D lastPoint; unsigned int i = 0; // Draw for each segment a line for( std::deque<VECTOR2D>::const_iterator it = aPointList.begin(); it != aPointList.end(); it++ ) { // First point if( it == aPointList.begin() ) { isFirstPoint = false; lastPoint = *it; } else { VECTOR2D actualPoint = *it; startEndVector = actualPoint - lastPoint; if( isFirstLine ) { drawLineCap( lastPoint, actualPoint ); isFirstLine = false; } else { // Compute some variables for the joints double lineLengthA = lastStartEndVector.EuclideanNorm(); double scale = 0.5 * lineWidth / lineLengthA; VECTOR2D perpendicularVector1( -lastStartEndVector.y * scale, lastStartEndVector.x * scale ); double lineLengthB = startEndVector.EuclideanNorm(); scale = 0.5 * lineWidth / lineLengthB; VECTOR2D perpendicularVector2( -startEndVector.y * scale, startEndVector.x * scale ); switch( lineJoin ) { case LINE_JOIN_ROUND: { // Insert a triangle fan at the line joint // Compute the start and end angle for the triangle fan double angle1 = startEndVector.Angle(); double angle2 = lastStartEndVector.Angle(); double angleDiff = angle1 - angle2; // Determines the side of the triangle fan double adjust = angleDiff < 0 ? -0.5 * lineWidth : 0.5 * lineWidth; // Angle correction for some special cases if( angleDiff < -M_PI ) { if( angle1 < 0 ) { angle1 += 2 * M_PI; } if( angle2 < 0 ) { angle2 += 2 * M_PI; } adjust = -adjust; } else if( angleDiff > M_PI ) { if( angle1 > 0 ) { angle1 -= 2 * M_PI; } if( angle2 > 0 ) { angle2 -= 2 * M_PI; } adjust = -adjust; } // Now draw the fan SWAP( angle1, >, angle2 ); begin( GL_TRIANGLES ); for( double a = angle1; a < angle2; ) { // Compute vertices vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( lastPoint.x + adjust * sin( a ), lastPoint.y - adjust * cos( a ), layerDepth ); a += M_PI / 32; if(a > angle2) a = angle2; vertex3( lastPoint.x + adjust * sin( a ), lastPoint.y - adjust * cos( a ), layerDepth ); } end(); break; } case LINE_JOIN_BEVEL: { // We compute the edge points of the line segments at the joint VECTOR2D edgePoint1; VECTOR2D edgePoint2; // Determine the correct side if( lastStartEndVector.x * startEndVector.y - lastStartEndVector.y * startEndVector.x < 0 ) { edgePoint1 = lastPoint + perpendicularVector1; edgePoint2 = lastPoint + perpendicularVector2; } else { edgePoint1 = lastPoint - perpendicularVector1; edgePoint2 = lastPoint - perpendicularVector2; } // Insert a triangle at the joint to close the gap begin( GL_TRIANGLES ); vertex3( edgePoint1.x, edgePoint1.y, layerDepth ); vertex3( edgePoint2.x, edgePoint2.y, layerDepth ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); end(); break; } case LINE_JOIN_MITER: { // Compute points of the outer edges VECTOR2D point1 = lastPoint - perpendicularVector1; VECTOR2D point3 = lastPoint - perpendicularVector2; if( lastStartEndVector.x * startEndVector.y - lastStartEndVector.y * startEndVector.x < 0 ) { point1 = lastPoint + perpendicularVector1; point3 = lastPoint + perpendicularVector2; } VECTOR2D point2 = point1 - lastStartEndVector; VECTOR2D point4 = point3 + startEndVector; // Now compute the intersection point of the edges double c1 = point1.Cross( point2 ); double c2 = point3.Cross( point4 ); double quot = startEndVector.Cross( lastStartEndVector ); VECTOR2D miterPoint( -c1 * startEndVector.x - c2 * lastStartEndVector.x, -c1 * startEndVector.y - c2 * lastStartEndVector.y ); miterPoint = ( 1 / quot ) * miterPoint; // Check if the point is outside the limit if( ( lastPoint - miterPoint ).EuclideanNorm() > 2 * lineWidth ) { // if it's outside cut the edge and insert three triangles double limit = MITER_LIMIT * lineWidth; VECTOR2D mp1 = point1 + ( limit / lineLengthA ) * lastStartEndVector; VECTOR2D mp2 = point3 - ( limit / lineLengthB ) * startEndVector; begin( GL_TRIANGLES ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( point1.x, point1.y, layerDepth ); vertex3( mp1.x, mp1.y, layerDepth ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( mp1.x, mp1.y, layerDepth ); vertex3( mp2.x, mp2.y, layerDepth ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( mp2.x, mp2.y, layerDepth ); vertex3( point3.x, point3.y, layerDepth ); end(); } else { // Insert two triangles for the mitered edge begin( GL_TRIANGLES ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( point1.x, point1.y, layerDepth ); vertex3( miterPoint.x, miterPoint.y, layerDepth ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( miterPoint.x, miterPoint.y, layerDepth ); vertex3( point3.x, point3.y, layerDepth ); end(); } break; } } } if( it == aPointList.end() - 1 ) { drawLineCap( actualPoint, lastPoint ); } drawLineQuad( lastPoint, *it ); lastPoint = *it; lastStartEndVector = startEndVector; } i++; } lineCap = savedLineCap; } Loading Loading @@ -1058,7 +804,8 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) /* Draw a triangle that contains the circle, then shade it leaving only the circle. Parameters given to setShader are relative coordinates of the triangle's vertices and the line width. Shader uses this coordinates to determine if fragments are inside the circle or not. Width parameter has to be passed as a relative value. the circle or not. Width parameter has to be passed as a ratio of inner radius to outer radius. v2 /\ //\\ Loading @@ -1084,15 +831,14 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) return; } // Draw the middle of the circle (not anti-aliased) if( isStrokeEnabled ) { // Compute the factors for the unit circle double outerScale = lineWidth / aRadius / 2; double innerScale = -outerScale; outerScale += 1.0; innerScale += 1.0; if( isStrokeEnabled ) { if( innerScale < outerScale ) { // Draw the outline Loading Loading @@ -1167,6 +913,22 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ) { if( isFillEnabled ) { color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); drawFilledSemiCircle( aCenterPoint, aRadius, aAngle ); } if( isStrokeEnabled ) { color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); drawStrokedSemiCircle( aCenterPoint, aRadius, aAngle ); } } void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ) { if( isUseShader && isGrouping ) { Loading @@ -1174,8 +936,6 @@ void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, d Translate( aCenterPoint ); Rotate( aAngle ); color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); /* Draw a triangle that contains the semicircle, then shade it to leave only the semicircle. Parameters given to setShader are relative coordinates of the triangle's vertices. Shader uses this coordinates to determine if fragments are inside the semicircle or not. Loading @@ -1184,13 +944,13 @@ void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, d /__\ v0 //__\\ v1 */ setShader( SHADER_FILLED_CIRCLE, -3.0f / sqrt( 3.0f ), 0.0f, lineWidth ); setShader( SHADER_FILLED_CIRCLE, -3.0f / sqrt( 3.0f ), 0.0f ); vertex3( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0 setShader( SHADER_FILLED_CIRCLE, 3.0f / sqrt( 3.0f ), 0.0f, lineWidth ); setShader( SHADER_FILLED_CIRCLE, 3.0f / sqrt( 3.0f ), 0.0f ); vertex3( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1 setShader( SHADER_FILLED_CIRCLE, 0.0f, 2.0f, lineWidth ); setShader( SHADER_FILLED_CIRCLE, 0.0f, 2.0f ); vertex3( 0.0f, aRadius * 2.0f, layerDepth ); // v2 Restore(); Loading @@ -1217,6 +977,96 @@ void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, d } void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ) { if( isUseShader && isGrouping ) { Save(); Translate( aCenterPoint ); Rotate( aAngle ); /* Draw a triangle that contains the semicircle, then shade it to leave only the semicircle. Parameters given to setShader are relative coordinates of the triangle's vertices and the line width. Shader uses this coordinates to determine if fragments are inside the semicircle or not. Width parameter has to be passed as a ratio of inner radius to outer radius. v2 /\ /__\ v0 //__\\ v1 */ float outerRadius = aRadius; float innerRadius = aRadius - lineWidth; float relWidth = innerRadius / outerRadius; setShader( SHADER_STROKED_CIRCLE, -3.0f / sqrt( 3.0f ), 0.0f, relWidth ); vertex3( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0 setShader( SHADER_STROKED_CIRCLE, 3.0f / sqrt( 3.0f ), 0.0f, relWidth ); vertex3( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1 setShader( SHADER_STROKED_CIRCLE, 0.0f, 2.0f, relWidth ); vertex3( 0.0f, aRadius * 2.0f, layerDepth ); // v2 Restore(); } else { // Compute the factors for the unit circle double outerScale = lineWidth / aRadius / 2; double innerScale = -outerScale; outerScale += 1.0; innerScale += 1.0; if( innerScale < outerScale ) { Save(); Translate( aCenterPoint ); Rotate( aAngle ); // Draw the outline VBO_VERTEX* circle = verticesCircle->GetVertices(); int next; begin( GL_TRIANGLES ); for( int i = 0; i < ( 3 * CIRCLE_POINTS ) / 2; ++i ) { // verticesCircle contains precomputed circle points interleaved with vertex // (0,0,0), so filled circles can be drawn as consecutive triangles, ie: // { 0,a,b, 0,c,d, 0,e,f, 0,g,h, ... } // where letters stand for consecutive circle points and 0 for (0,0,0) vertex. // We have to skip all (0,0,0) vertices (every third vertex) if( i % 3 == 0 ) { i++; // Depending on the vertex, next circle point may be stored in the next vertex.. next = i + 1; } else { // ..or 2 vertices away (in case it is preceded by (0,0,0) vertex) next = i + 2; } vertex3( circle[i].x * innerScale, circle[i].y * innerScale, layerDepth ); vertex3( circle[i].x * outerScale, circle[i].y * outerScale, layerDepth ); vertex3( circle[next].x * innerScale, circle[next].y * innerScale, layerDepth ); vertex3( circle[i].x * outerScale, circle[i].y * outerScale, layerDepth ); vertex3( circle[next].x * outerScale, circle[next].y * outerScale, layerDepth ); vertex3( circle[next].x * innerScale, circle[next].y * innerScale, layerDepth ); } end(); Restore(); } } } // FIXME Optimize void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle ) Loading Loading @@ -1300,11 +1150,9 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a end(); if( lineCap == LINE_CAP_ROUND ) { drawSemiCircle( startPoint, lineWidth / aRadius / 2.0, aStartAngle + M_PI ); drawSemiCircle( endPoint, lineWidth / aRadius / 2.0, aEndAngle ); } // Draw line caps drawFilledSemiCircle( startPoint, lineWidth / aRadius / 2.0, aStartAngle + M_PI ); drawFilledSemiCircle( endPoint, lineWidth / aRadius / 2.0, aEndAngle ); } } Loading common/gal/stroke_font.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -233,8 +233,6 @@ void STROKE_FONT::Draw( std::string aText, const VECTOR2D& aPosition, double aRo m_gal->SetIsStroke( true ); m_gal->SetIsFill( false ); m_gal->SetLineCap( LINE_CAP_ROUND ); m_gal->SetLineJoin( LINE_JOIN_ROUND ); if( m_bold ) { Loading include/gal/cairo/cairo_gal.h +0 −12 Original line number Diff line number Diff line Loading @@ -159,12 +159,6 @@ public: /// @copydoc GAL::SetBackgroundColor() virtual void SetBackgroundColor( const COLOR4D& aColor ); /// @copydoc GAL::SetLineCap() virtual void SetLineCap( LineCap aLineCap ); /// @copydoc GAL::SetLineJoin() virtual void SetLineJoin( LineJoin aLineJoin ); /// @copydoc GAL::SetLineWidth() virtual void SetLineWidth( double aLineWidth ); Loading Loading @@ -334,8 +328,6 @@ private: CMD_SET_FILLCOLOR, ///< Set the fill color CMD_SET_STROKECOLOR, ///< Set the stroke color CMD_SET_LINE_WIDTH, ///< Set the line width CMD_SET_LINE_CAP, ///< Set the line cap style CMD_SET_LINE_JOIN, ///< Set the line join style CMD_STROKE_PATH, ///< Set the stroke path CMD_FILL_PATH, ///< Set the fill path CMD_TRANSFORM, ///< Transform the actual context Loading Loading @@ -371,10 +363,6 @@ private: int stride; ///< Stride value for Cairo bool isInitialized; ///< Are Cairo image & surface ready to use // Mapping between Cairo and GAL line attributes std::map<LineCap, cairo_line_cap_t> lineCapMap; ///< Line cap style mapping std::map<LineJoin, cairo_line_join_t> lineJoinMap; ///< Line join style mapping // Methods void storePath(); ///< Store the actual path Loading Loading
common/gal/cairo/cairo_gal.cpp +2 −58 Original line number Diff line number Diff line Loading @@ -72,15 +72,6 @@ CAIRO_GAL::CAIRO_GAL( wxWindow* aParent, wxEvtHandler* aMouseListener, Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( CAIRO_GAL::skipMouseEvent ) ); #endif // Initialize line attributes map lineCapMap[LINE_CAP_BUTT] = CAIRO_LINE_CAP_BUTT; lineCapMap[LINE_CAP_ROUND] = CAIRO_LINE_CAP_ROUND; lineCapMap[LINE_CAP_SQUARED] = CAIRO_LINE_CAP_SQUARE; lineJoinMap[LINE_JOIN_BEVEL] = CAIRO_LINE_JOIN_BEVEL; lineJoinMap[LINE_JOIN_ROUND] = CAIRO_LINE_JOIN_ROUND; lineJoinMap[LINE_JOIN_MITER] = CAIRO_LINE_JOIN_MITER; // Initialize the cursor shape SetCursorColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) ); initCursor( 21 ); Loading Loading @@ -179,8 +170,8 @@ void CAIRO_GAL::initSurface() cairo_new_path( cairoImage ); isElementAdded = true; cairo_set_line_join( cairoImage, lineJoinMap[lineJoin] ); cairo_set_line_cap( cairoImage, lineCapMap[lineCap] ); cairo_set_line_join( cairoImage, CAIRO_LINE_JOIN_ROUND ); cairo_set_line_cap( cairoImage, CAIRO_LINE_CAP_ROUND ); lineWidth = 0; Loading Loading @@ -298,9 +289,6 @@ void CAIRO_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint void CAIRO_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth ) { cairo_set_line_cap( cairoImage, CAIRO_LINE_CAP_ROUND ); cairo_set_line_join( cairoImage, CAIRO_LINE_JOIN_ROUND ); if( isFillEnabled ) { SetLineWidth( aWidth ); Loading Loading @@ -520,42 +508,6 @@ void CAIRO_GAL::SetLineWidth( double aLineWidth ) } void CAIRO_GAL::SetLineCap( LineCap aLineCap ) { storePath(); lineCap = aLineCap; cairo_set_line_cap( cairoImage, lineCapMap[aLineCap] ); if( isGrouping ) { GroupElement groupElement; groupElement.command = CMD_SET_LINE_CAP; groupElement.intArgument = (int) aLineCap; currentGroup->push_back( groupElement ); } } void CAIRO_GAL::SetLineJoin( LineJoin aLineJoin ) { storePath(); lineJoin = aLineJoin; cairo_set_line_join( cairoImage, lineJoinMap[aLineJoin] ); if( isGrouping ) { GroupElement groupElement; groupElement.command = CMD_SET_LINE_JOIN; groupElement.intArgument = (int) aLineJoin; currentGroup->push_back( groupElement ); } } void CAIRO_GAL::ClearScreen() { // Clear screen Loading Loading @@ -767,14 +719,6 @@ void CAIRO_GAL::DrawGroup( int aGroupNumber ) cairo_set_line_width( cairoImage, it->arguments[0] ); break; case CMD_SET_LINE_JOIN: cairo_set_line_join( cairoImage, lineJoinMap[(LineJoin) ( it->intArgument )] ); break; case CMD_SET_LINE_CAP: cairo_set_line_cap( cairoImage, lineCapMap[(LineCap) ( it->intArgument )] ); break; case CMD_STROKE_PATH: cairo_set_source_rgb( cairoImage, strokeColor.r, strokeColor.g, strokeColor.b ); cairo_append_path( cairoImage, it->cairoPath ); Loading
common/gal/graphics_abstraction_layer.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -38,8 +38,6 @@ GAL::GAL() // Set the default values for the internal variables SetIsFill( false ); SetIsStroke( true ); SetLineJoin( LINE_JOIN_ROUND ); SetLineCap( LINE_CAP_ROUND ); SetIsCursorEnabled( false ); SetZoomFactor( 1.0 ); SetFillColor( COLOR4D( 0.0, 0.0, 0.0, 0.0 ) ); Loading
common/gal/opengl/opengl_gal.cpp +144 −296 Original line number Diff line number Diff line Loading @@ -658,9 +658,11 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); SetLineWidth( aWidth ); drawSemiCircle( aStartPoint, aWidth / 2, lineAngle + M_PI / 2 ); drawSemiCircle( aEndPoint, aWidth / 2, lineAngle - M_PI / 2 ); drawLineQuad( aStartPoint, aEndPoint ); // Draw line caps drawFilledSemiCircle( aStartPoint, aWidth / 2, lineAngle + M_PI / 2 ); drawFilledSemiCircle( aEndPoint, aWidth / 2, lineAngle - M_PI / 2 ); } else { Loading @@ -680,41 +682,15 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP drawLineQuad( VECTOR2D( 0.0, -aWidth / 2.0 ), VECTOR2D( lineLength, -aWidth / 2.0 ) ); drawSemiCircle( VECTOR2D( 0.0, 0.0 ), aWidth / 2, M_PI / 2 ); drawSemiCircle( VECTOR2D( lineLength, 0.0 ), aWidth / 2, -M_PI / 2 ); // Draw line caps drawStrokedSemiCircle( VECTOR2D( 0.0, 0.0 ), ( aWidth + lineWidth ) / 2, M_PI / 2 ); drawStrokedSemiCircle( VECTOR2D( lineLength, 0.0 ), ( aWidth + lineWidth ) / 2, -M_PI / 2 ); Restore(); } } inline void OPENGL_GAL::drawLineCap( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) { VECTOR2D startEndVector = aEndPoint - aStartPoint; // double lineLength = startEndVector.EuclideanNorm(); double lineAngle = startEndVector.Angle(); switch( lineCap ) { case LINE_CAP_BUTT: // TODO break; case LINE_CAP_ROUND: // Add a semicircle at the line end drawSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 ); break; case LINE_CAP_SQUARED: // FIXME? VECTOR2D offset; // offset = startEndVector * ( lineWidth / lineLength / 2.0 ); // aStartPoint = aStartPoint - offset; // aEndPoint = aEndPoint + offset; break; } } unsigned int OPENGL_GAL::getGroupNumber() { wxASSERT_MSG( groups.size() < std::numeric_limits<unsigned int>::max(), Loading @@ -731,32 +707,19 @@ unsigned int OPENGL_GAL::getGroupNumber() void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) { if( isFillEnabled ) { color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); const VECTOR2D startEndVector = aEndPoint - aStartPoint; double lineAngle = startEndVector.Angle(); drawLineCap( aStartPoint, aEndPoint ); drawLineCap( aEndPoint, aStartPoint ); drawLineQuad( aStartPoint, aEndPoint ); } if( isStrokeEnabled ) { // TODO outline mode color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); drawLineCap( aStartPoint, aEndPoint ); drawLineCap( aEndPoint, aStartPoint ); drawLineQuad( aStartPoint, aEndPoint ); } // Line caps drawFilledSemiCircle( aStartPoint, lineWidth / 2, lineAngle + M_PI / 2 ); drawFilledSemiCircle( aEndPoint, lineWidth / 2, lineAngle + M_PI / 2 ); } void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList ) { if( isUseShader ) { // This method reduces amount of triangles used for drawing std::deque<VECTOR2D>::const_iterator it = aPointList.begin(); // Start from the second point Loading @@ -764,223 +727,6 @@ void OPENGL_GAL::DrawPolyline( std::deque<VECTOR2D>& aPointList ) { DrawLine( *( it - 1 ), *it ); } return; } bool isFirstPoint = true; LineCap savedLineCap = lineCap; bool isFirstLine = true; VECTOR2D startEndVector; VECTOR2D lastStartEndVector; VECTOR2D lastPoint; unsigned int i = 0; // Draw for each segment a line for( std::deque<VECTOR2D>::const_iterator it = aPointList.begin(); it != aPointList.end(); it++ ) { // First point if( it == aPointList.begin() ) { isFirstPoint = false; lastPoint = *it; } else { VECTOR2D actualPoint = *it; startEndVector = actualPoint - lastPoint; if( isFirstLine ) { drawLineCap( lastPoint, actualPoint ); isFirstLine = false; } else { // Compute some variables for the joints double lineLengthA = lastStartEndVector.EuclideanNorm(); double scale = 0.5 * lineWidth / lineLengthA; VECTOR2D perpendicularVector1( -lastStartEndVector.y * scale, lastStartEndVector.x * scale ); double lineLengthB = startEndVector.EuclideanNorm(); scale = 0.5 * lineWidth / lineLengthB; VECTOR2D perpendicularVector2( -startEndVector.y * scale, startEndVector.x * scale ); switch( lineJoin ) { case LINE_JOIN_ROUND: { // Insert a triangle fan at the line joint // Compute the start and end angle for the triangle fan double angle1 = startEndVector.Angle(); double angle2 = lastStartEndVector.Angle(); double angleDiff = angle1 - angle2; // Determines the side of the triangle fan double adjust = angleDiff < 0 ? -0.5 * lineWidth : 0.5 * lineWidth; // Angle correction for some special cases if( angleDiff < -M_PI ) { if( angle1 < 0 ) { angle1 += 2 * M_PI; } if( angle2 < 0 ) { angle2 += 2 * M_PI; } adjust = -adjust; } else if( angleDiff > M_PI ) { if( angle1 > 0 ) { angle1 -= 2 * M_PI; } if( angle2 > 0 ) { angle2 -= 2 * M_PI; } adjust = -adjust; } // Now draw the fan SWAP( angle1, >, angle2 ); begin( GL_TRIANGLES ); for( double a = angle1; a < angle2; ) { // Compute vertices vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( lastPoint.x + adjust * sin( a ), lastPoint.y - adjust * cos( a ), layerDepth ); a += M_PI / 32; if(a > angle2) a = angle2; vertex3( lastPoint.x + adjust * sin( a ), lastPoint.y - adjust * cos( a ), layerDepth ); } end(); break; } case LINE_JOIN_BEVEL: { // We compute the edge points of the line segments at the joint VECTOR2D edgePoint1; VECTOR2D edgePoint2; // Determine the correct side if( lastStartEndVector.x * startEndVector.y - lastStartEndVector.y * startEndVector.x < 0 ) { edgePoint1 = lastPoint + perpendicularVector1; edgePoint2 = lastPoint + perpendicularVector2; } else { edgePoint1 = lastPoint - perpendicularVector1; edgePoint2 = lastPoint - perpendicularVector2; } // Insert a triangle at the joint to close the gap begin( GL_TRIANGLES ); vertex3( edgePoint1.x, edgePoint1.y, layerDepth ); vertex3( edgePoint2.x, edgePoint2.y, layerDepth ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); end(); break; } case LINE_JOIN_MITER: { // Compute points of the outer edges VECTOR2D point1 = lastPoint - perpendicularVector1; VECTOR2D point3 = lastPoint - perpendicularVector2; if( lastStartEndVector.x * startEndVector.y - lastStartEndVector.y * startEndVector.x < 0 ) { point1 = lastPoint + perpendicularVector1; point3 = lastPoint + perpendicularVector2; } VECTOR2D point2 = point1 - lastStartEndVector; VECTOR2D point4 = point3 + startEndVector; // Now compute the intersection point of the edges double c1 = point1.Cross( point2 ); double c2 = point3.Cross( point4 ); double quot = startEndVector.Cross( lastStartEndVector ); VECTOR2D miterPoint( -c1 * startEndVector.x - c2 * lastStartEndVector.x, -c1 * startEndVector.y - c2 * lastStartEndVector.y ); miterPoint = ( 1 / quot ) * miterPoint; // Check if the point is outside the limit if( ( lastPoint - miterPoint ).EuclideanNorm() > 2 * lineWidth ) { // if it's outside cut the edge and insert three triangles double limit = MITER_LIMIT * lineWidth; VECTOR2D mp1 = point1 + ( limit / lineLengthA ) * lastStartEndVector; VECTOR2D mp2 = point3 - ( limit / lineLengthB ) * startEndVector; begin( GL_TRIANGLES ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( point1.x, point1.y, layerDepth ); vertex3( mp1.x, mp1.y, layerDepth ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( mp1.x, mp1.y, layerDepth ); vertex3( mp2.x, mp2.y, layerDepth ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( mp2.x, mp2.y, layerDepth ); vertex3( point3.x, point3.y, layerDepth ); end(); } else { // Insert two triangles for the mitered edge begin( GL_TRIANGLES ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( point1.x, point1.y, layerDepth ); vertex3( miterPoint.x, miterPoint.y, layerDepth ); vertex3( lastPoint.x, lastPoint.y, layerDepth ); vertex3( miterPoint.x, miterPoint.y, layerDepth ); vertex3( point3.x, point3.y, layerDepth ); end(); } break; } } } if( it == aPointList.end() - 1 ) { drawLineCap( actualPoint, lastPoint ); } drawLineQuad( lastPoint, *it ); lastPoint = *it; lastStartEndVector = startEndVector; } i++; } lineCap = savedLineCap; } Loading Loading @@ -1058,7 +804,8 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) /* Draw a triangle that contains the circle, then shade it leaving only the circle. Parameters given to setShader are relative coordinates of the triangle's vertices and the line width. Shader uses this coordinates to determine if fragments are inside the circle or not. Width parameter has to be passed as a relative value. the circle or not. Width parameter has to be passed as a ratio of inner radius to outer radius. v2 /\ //\\ Loading @@ -1084,15 +831,14 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) return; } // Draw the middle of the circle (not anti-aliased) if( isStrokeEnabled ) { // Compute the factors for the unit circle double outerScale = lineWidth / aRadius / 2; double innerScale = -outerScale; outerScale += 1.0; innerScale += 1.0; if( isStrokeEnabled ) { if( innerScale < outerScale ) { // Draw the outline Loading Loading @@ -1167,6 +913,22 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ) { if( isFillEnabled ) { color4( fillColor.r, fillColor.g, fillColor.b, fillColor.a ); drawFilledSemiCircle( aCenterPoint, aRadius, aAngle ); } if( isStrokeEnabled ) { color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); drawStrokedSemiCircle( aCenterPoint, aRadius, aAngle ); } } void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ) { if( isUseShader && isGrouping ) { Loading @@ -1174,8 +936,6 @@ void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, d Translate( aCenterPoint ); Rotate( aAngle ); color4( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a ); /* Draw a triangle that contains the semicircle, then shade it to leave only the semicircle. Parameters given to setShader are relative coordinates of the triangle's vertices. Shader uses this coordinates to determine if fragments are inside the semicircle or not. Loading @@ -1184,13 +944,13 @@ void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, d /__\ v0 //__\\ v1 */ setShader( SHADER_FILLED_CIRCLE, -3.0f / sqrt( 3.0f ), 0.0f, lineWidth ); setShader( SHADER_FILLED_CIRCLE, -3.0f / sqrt( 3.0f ), 0.0f ); vertex3( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0 setShader( SHADER_FILLED_CIRCLE, 3.0f / sqrt( 3.0f ), 0.0f, lineWidth ); setShader( SHADER_FILLED_CIRCLE, 3.0f / sqrt( 3.0f ), 0.0f ); vertex3( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1 setShader( SHADER_FILLED_CIRCLE, 0.0f, 2.0f, lineWidth ); setShader( SHADER_FILLED_CIRCLE, 0.0f, 2.0f ); vertex3( 0.0f, aRadius * 2.0f, layerDepth ); // v2 Restore(); Loading @@ -1217,6 +977,96 @@ void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, d } void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle ) { if( isUseShader && isGrouping ) { Save(); Translate( aCenterPoint ); Rotate( aAngle ); /* Draw a triangle that contains the semicircle, then shade it to leave only the semicircle. Parameters given to setShader are relative coordinates of the triangle's vertices and the line width. Shader uses this coordinates to determine if fragments are inside the semicircle or not. Width parameter has to be passed as a ratio of inner radius to outer radius. v2 /\ /__\ v0 //__\\ v1 */ float outerRadius = aRadius; float innerRadius = aRadius - lineWidth; float relWidth = innerRadius / outerRadius; setShader( SHADER_STROKED_CIRCLE, -3.0f / sqrt( 3.0f ), 0.0f, relWidth ); vertex3( -aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v0 setShader( SHADER_STROKED_CIRCLE, 3.0f / sqrt( 3.0f ), 0.0f, relWidth ); vertex3( aRadius * 3.0f / sqrt( 3.0f ), 0.0f, layerDepth ); // v1 setShader( SHADER_STROKED_CIRCLE, 0.0f, 2.0f, relWidth ); vertex3( 0.0f, aRadius * 2.0f, layerDepth ); // v2 Restore(); } else { // Compute the factors for the unit circle double outerScale = lineWidth / aRadius / 2; double innerScale = -outerScale; outerScale += 1.0; innerScale += 1.0; if( innerScale < outerScale ) { Save(); Translate( aCenterPoint ); Rotate( aAngle ); // Draw the outline VBO_VERTEX* circle = verticesCircle->GetVertices(); int next; begin( GL_TRIANGLES ); for( int i = 0; i < ( 3 * CIRCLE_POINTS ) / 2; ++i ) { // verticesCircle contains precomputed circle points interleaved with vertex // (0,0,0), so filled circles can be drawn as consecutive triangles, ie: // { 0,a,b, 0,c,d, 0,e,f, 0,g,h, ... } // where letters stand for consecutive circle points and 0 for (0,0,0) vertex. // We have to skip all (0,0,0) vertices (every third vertex) if( i % 3 == 0 ) { i++; // Depending on the vertex, next circle point may be stored in the next vertex.. next = i + 1; } else { // ..or 2 vertices away (in case it is preceded by (0,0,0) vertex) next = i + 2; } vertex3( circle[i].x * innerScale, circle[i].y * innerScale, layerDepth ); vertex3( circle[i].x * outerScale, circle[i].y * outerScale, layerDepth ); vertex3( circle[next].x * innerScale, circle[next].y * innerScale, layerDepth ); vertex3( circle[i].x * outerScale, circle[i].y * outerScale, layerDepth ); vertex3( circle[next].x * outerScale, circle[next].y * outerScale, layerDepth ); vertex3( circle[next].x * innerScale, circle[next].y * innerScale, layerDepth ); } end(); Restore(); } } } // FIXME Optimize void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle ) Loading Loading @@ -1300,11 +1150,9 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a end(); if( lineCap == LINE_CAP_ROUND ) { drawSemiCircle( startPoint, lineWidth / aRadius / 2.0, aStartAngle + M_PI ); drawSemiCircle( endPoint, lineWidth / aRadius / 2.0, aEndAngle ); } // Draw line caps drawFilledSemiCircle( startPoint, lineWidth / aRadius / 2.0, aStartAngle + M_PI ); drawFilledSemiCircle( endPoint, lineWidth / aRadius / 2.0, aEndAngle ); } } Loading
common/gal/stroke_font.cpp +0 −2 Original line number Diff line number Diff line Loading @@ -233,8 +233,6 @@ void STROKE_FONT::Draw( std::string aText, const VECTOR2D& aPosition, double aRo m_gal->SetIsStroke( true ); m_gal->SetIsFill( false ); m_gal->SetLineCap( LINE_CAP_ROUND ); m_gal->SetLineJoin( LINE_JOIN_ROUND ); if( m_bold ) { Loading
include/gal/cairo/cairo_gal.h +0 −12 Original line number Diff line number Diff line Loading @@ -159,12 +159,6 @@ public: /// @copydoc GAL::SetBackgroundColor() virtual void SetBackgroundColor( const COLOR4D& aColor ); /// @copydoc GAL::SetLineCap() virtual void SetLineCap( LineCap aLineCap ); /// @copydoc GAL::SetLineJoin() virtual void SetLineJoin( LineJoin aLineJoin ); /// @copydoc GAL::SetLineWidth() virtual void SetLineWidth( double aLineWidth ); Loading Loading @@ -334,8 +328,6 @@ private: CMD_SET_FILLCOLOR, ///< Set the fill color CMD_SET_STROKECOLOR, ///< Set the stroke color CMD_SET_LINE_WIDTH, ///< Set the line width CMD_SET_LINE_CAP, ///< Set the line cap style CMD_SET_LINE_JOIN, ///< Set the line join style CMD_STROKE_PATH, ///< Set the stroke path CMD_FILL_PATH, ///< Set the fill path CMD_TRANSFORM, ///< Transform the actual context Loading Loading @@ -371,10 +363,6 @@ private: int stride; ///< Stride value for Cairo bool isInitialized; ///< Are Cairo image & surface ready to use // Mapping between Cairo and GAL line attributes std::map<LineCap, cairo_line_cap_t> lineCapMap; ///< Line cap style mapping std::map<LineJoin, cairo_line_join_t> lineJoinMap; ///< Line join style mapping // Methods void storePath(); ///< Store the actual path Loading