Removed different styles of line caps and line joins, leaving only round caps & joins.
Fixed drawing stroked semicircles using OpenGL backend.
This commit is contained in:
parent
8a44751b61
commit
4360860bee
|
@ -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 );
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 );
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
|
|
|
@ -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 ) );
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
@ -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(),
|
||||
|
@ -731,256 +707,26 @@ 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 );
|
||||
}
|
||||
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 )
|
||||
std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
|
||||
|
||||
// Start from the second point
|
||||
for( it++; it != aPointList.end(); it++ )
|
||||
{
|
||||
// This method reduces amount of triangles used for drawing
|
||||
std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
|
||||
|
||||
// Start from the second point
|
||||
for( it++; it != aPointList.end(); it++ )
|
||||
{
|
||||
DrawLine( *( it - 1 ), *it );
|
||||
}
|
||||
|
||||
return;
|
||||
DrawLine( *( it - 1 ), *it );
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
/\
|
||||
//\\
|
||||
|
@ -1084,15 +831,14 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
|||
return;
|
||||
}
|
||||
|
||||
// Draw the middle of the circle (not anti-aliased)
|
||||
// Compute the factors for the unit circle
|
||||
double outerScale = lineWidth / aRadius / 2;
|
||||
double innerScale = -outerScale;
|
||||
outerScale += 1.0;
|
||||
innerScale += 1.0;
|
||||
|
||||
if( isStrokeEnabled )
|
||||
{
|
||||
// Compute the factors for the unit circle
|
||||
double outerScale = lineWidth / aRadius / 2;
|
||||
double innerScale = -outerScale;
|
||||
outerScale += 1.0;
|
||||
innerScale += 1.0;
|
||||
|
||||
if( innerScale < outerScale )
|
||||
{
|
||||
// Draw the outline
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -1174,23 +936,21 @@ 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.
|
||||
v2
|
||||
/\
|
||||
/__\
|
||||
v0 //__\\ v1
|
||||
*/
|
||||
setShader( SHADER_FILLED_CIRCLE, -3.0f / sqrt( 3.0f ), 0.0f, lineWidth );
|
||||
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.
|
||||
v2
|
||||
/\
|
||||
/__\
|
||||
v0 //__\\ v1
|
||||
*/
|
||||
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();
|
||||
|
@ -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 )
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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 );
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
|
|
@ -38,27 +38,6 @@
|
|||
|
||||
namespace KiGfx
|
||||
{
|
||||
|
||||
/**
|
||||
* LineCap: Type definition of the line end point style
|
||||
*/
|
||||
enum LineCap
|
||||
{
|
||||
LINE_CAP_BUTT, ///< Stop line at the end point
|
||||
LINE_CAP_ROUND, ///< Draw a circle at the end point
|
||||
LINE_CAP_SQUARED ///< Draw a square at the end point
|
||||
};
|
||||
|
||||
/**
|
||||
* LineJoin: Type definition of the line joint style
|
||||
*/
|
||||
enum LineJoin
|
||||
{
|
||||
LINE_JOIN_MITER, ///< Use sharp corners
|
||||
LINE_JOIN_ROUND, ///< Insert a circle at the joints
|
||||
LINE_JOIN_BEVEL ///< Diagonal corner
|
||||
};
|
||||
|
||||
/**
|
||||
* GridStyle: Type definition of the grid style
|
||||
*/
|
||||
|
@ -251,26 +230,6 @@ public:
|
|||
*/
|
||||
virtual void SetBackgroundColor( const COLOR4D& aColor ) = 0;
|
||||
|
||||
/**
|
||||
* @brief Set the style of the line caps.
|
||||
*
|
||||
* @param aLineCap is the line cap style.
|
||||
*/
|
||||
inline virtual void SetLineCap( LineCap aLineCap )
|
||||
{
|
||||
lineCap = aLineCap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the line join style.
|
||||
*
|
||||
* @param aLineJoin is the line join style.
|
||||
*/
|
||||
inline virtual void SetLineJoin( LineJoin aLineJoin )
|
||||
{
|
||||
lineJoin = aLineJoin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the line width.
|
||||
*
|
||||
|
@ -710,8 +669,6 @@ protected:
|
|||
double worldScale; ///< The scale factor world->screen
|
||||
|
||||
double lineWidth; ///< The line width
|
||||
LineCap lineCap; ///< Line end style
|
||||
LineJoin lineJoin; ///< Style of the line joints
|
||||
|
||||
bool isFillEnabled; ///< Is filling of graphic objects enabled ?
|
||||
bool isStrokeEnabled; ///< Are the outlines stroked ?
|
||||
|
|
|
@ -176,18 +176,6 @@ public:
|
|||
/// @copydoc GAL::SetBackgroundColor()
|
||||
virtual void SetBackgroundColor( const COLOR4D& aColor );
|
||||
|
||||
/// @copydoc GAL::SetLineCap()
|
||||
virtual void SetLineCap( LineCap aLineCap )
|
||||
{
|
||||
lineCap = aLineCap;
|
||||
}
|
||||
|
||||
/// @copydoc GAL::SetLineJoin()
|
||||
virtual void SetLineJoin( LineJoin aLineJoin )
|
||||
{
|
||||
lineJoin = aLineJoin;
|
||||
}
|
||||
|
||||
/// @copydoc GAL::SetLineWidth()
|
||||
virtual void SetLineWidth( double aLineWidth );
|
||||
|
||||
|
@ -421,6 +409,9 @@ private:
|
|||
*/
|
||||
void drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
|
||||
|
||||
void drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
|
||||
void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
|
||||
|
||||
/// Compute the points of a unit circle.
|
||||
void computeUnitCircle();
|
||||
|
||||
|
@ -514,15 +505,6 @@ private:
|
|||
*/
|
||||
inline void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
|
||||
|
||||
/**
|
||||
* @brief Draw the line cap
|
||||
*
|
||||
* @param aStartPoint is the start point of the line.
|
||||
* @param aEndPoint is the end point of the line.
|
||||
* @param aDepthOffset is the relative depth of the line cap.
|
||||
*/
|
||||
inline void drawLineCap( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
|
||||
|
||||
/**
|
||||
* @brief Returns a valid key that can be used as a group number.
|
||||
*
|
||||
|
|
|
@ -314,8 +314,6 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
|
|||
// Outline mode
|
||||
m_gal->SetIsFill( false );
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetLineCap( LINE_CAP_ROUND );
|
||||
m_gal->SetLineJoin( LINE_JOIN_MITER );
|
||||
m_gal->SetLineWidth( m_pcbSettings->m_outlineWidth );
|
||||
m_gal->SetStrokeColor( color );
|
||||
}
|
||||
|
@ -420,8 +418,6 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment )
|
|||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetStrokeColor( strokeColor );
|
||||
m_gal->SetLineWidth( aSegment->GetWidth() );
|
||||
m_gal->SetLineCap( LINE_CAP_ROUND );
|
||||
m_gal->SetLineJoin( LINE_JOIN_ROUND );
|
||||
|
||||
switch( aSegment->GetShape() )
|
||||
{
|
||||
|
@ -430,9 +426,8 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment )
|
|||
break;
|
||||
|
||||
case S_RECT:
|
||||
m_gal->SetLineCap( LINE_CAP_SQUARED );
|
||||
m_gal->SetLineJoin( LINE_JOIN_BEVEL );
|
||||
m_gal->DrawLine( VECTOR2D( aSegment->GetStart() ), VECTOR2D( aSegment->GetEnd() ) );
|
||||
wxASSERT_MSG( false, wxT( "Not tested yet" ) );
|
||||
m_gal->DrawRectangle( VECTOR2D( aSegment->GetStart() ), VECTOR2D( aSegment->GetEnd() ) );
|
||||
break;
|
||||
|
||||
case S_ARC:
|
||||
|
@ -506,8 +501,6 @@ void PCB_PAINTER::draw( const ZONE_CONTAINER* aContainer )
|
|||
m_gal->SetIsFill( !fillMode );
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->SetLineWidth( aContainer->GetThermalReliefCopperBridge() / 2.0 );
|
||||
m_gal->SetLineCap( LINE_CAP_ROUND );
|
||||
m_gal->SetLineJoin( LINE_JOIN_ROUND );
|
||||
|
||||
// FIXME implement hatch mode
|
||||
|
||||
|
|
Loading…
Reference in New Issue