GAL: Do better job at reserving vertices.
This commit is contained in:
parent
397a93029e
commit
bd8b737c44
|
@ -264,8 +264,7 @@ void FONT::drawSingleLineText( KIGFX::GAL* aGal, BOX2I* aBoundingBox, const wxSt
|
||||||
(void) drawMarkup( aBoundingBox, &glyphs, aText, aPosition, aSize, aAngle, aMirror, aOrigin,
|
(void) drawMarkup( aBoundingBox, &glyphs, aText, aPosition, aSize, aAngle, aMirror, aOrigin,
|
||||||
textStyle );
|
textStyle );
|
||||||
|
|
||||||
for( const std::unique_ptr<GLYPH>& glyph : glyphs )
|
aGal->DrawGlyphs( glyphs );
|
||||||
aGal->DrawGlyph( *glyph.get() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ using namespace KIFONT;
|
||||||
|
|
||||||
STROKE_GLYPH::STROKE_GLYPH( const STROKE_GLYPH& aGlyph )
|
STROKE_GLYPH::STROKE_GLYPH( const STROKE_GLYPH& aGlyph )
|
||||||
{
|
{
|
||||||
|
reserve( aGlyph.size() );
|
||||||
|
|
||||||
for( const std::vector<VECTOR2D>& pointList : aGlyph )
|
for( const std::vector<VECTOR2D>& pointList : aGlyph )
|
||||||
push_back( pointList );
|
push_back( pointList );
|
||||||
|
|
||||||
|
|
|
@ -234,6 +234,25 @@ void CAIRO_GAL_BASE::syncLineWidth( bool aForceWidth, double aWidth )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CAIRO_GAL_BASE::DrawSegmentChain( const std::vector<VECTOR2D>& aPointList, double aWidth )
|
||||||
|
{
|
||||||
|
for( size_t i = 0; i + 1 < aPointList.size(); ++i )
|
||||||
|
DrawSegment( aPointList[i], aPointList[i + 1], aWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CAIRO_GAL_BASE::DrawSegmentChain( const SHAPE_LINE_CHAIN& aLineChain, double aWidth )
|
||||||
|
{
|
||||||
|
int numPoints = aLineChain.PointCount();
|
||||||
|
|
||||||
|
if( aLineChain.IsClosed() )
|
||||||
|
numPoints += 1;
|
||||||
|
|
||||||
|
for( int i = 0; i + 1 < numPoints; ++i )
|
||||||
|
DrawSegment( aLineChain.CPoint( i ), aLineChain.CPoint( i + 1 ), aWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||||
double aWidth )
|
double aWidth )
|
||||||
{
|
{
|
||||||
|
|
|
@ -719,6 +719,13 @@ void OPENGL_GAL::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoin
|
||||||
|
|
||||||
void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||||
double aWidth )
|
double aWidth )
|
||||||
|
{
|
||||||
|
drawSegment( aStartPoint, aEndPoint, aWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_GAL::drawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth,
|
||||||
|
bool aReserve )
|
||||||
{
|
{
|
||||||
VECTOR2D startEndVector = aEndPoint - aStartPoint;
|
VECTOR2D startEndVector = aEndPoint - aStartPoint;
|
||||||
double lineLength = startEndVector.EuclideanNorm();
|
double lineLength = startEndVector.EuclideanNorm();
|
||||||
|
@ -733,7 +740,7 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
|
||||||
// segments. In this case, we need to draw a circle for the minimal segment.
|
// segments. In this case, we need to draw a circle for the minimal segment.
|
||||||
if( startx == endx || starty == endy )
|
if( startx == endx || starty == endy )
|
||||||
{
|
{
|
||||||
DrawCircle( aStartPoint, aWidth / 2 );
|
drawCircle( aStartPoint, aWidth / 2, aReserve );
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -742,7 +749,7 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
|
||||||
m_currentManager->Color( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
|
m_currentManager->Color( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
|
||||||
|
|
||||||
SetLineWidth( aWidth );
|
SetLineWidth( aWidth );
|
||||||
drawLineQuad( aStartPoint, aEndPoint );
|
drawLineQuad( aStartPoint, aEndPoint, aReserve );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -755,16 +762,20 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
|
|
||||||
|
if( aReserve )
|
||||||
|
m_currentManager->Reserve( 6 + 6 + 3 + 3 ); // Two line quads and two semicircles
|
||||||
|
|
||||||
m_currentManager->Translate( aStartPoint.x, aStartPoint.y, 0.0 );
|
m_currentManager->Translate( aStartPoint.x, aStartPoint.y, 0.0 );
|
||||||
m_currentManager->Rotate( lineAngle.AsRadians(), 0.0f, 0.0f, 1.0f );
|
m_currentManager->Rotate( lineAngle.AsRadians(), 0.0f, 0.0f, 1.0f );
|
||||||
|
|
||||||
drawLineQuad( VECTOR2D( 0.0, aWidth / 2.0 ), VECTOR2D( lineLength, aWidth / 2.0 ) );
|
drawLineQuad( VECTOR2D( 0.0, aWidth / 2.0 ), VECTOR2D( lineLength, aWidth / 2.0 ), false );
|
||||||
|
|
||||||
drawLineQuad( VECTOR2D( 0.0, -aWidth / 2.0 ), VECTOR2D( lineLength, -aWidth / 2.0 ) );
|
drawLineQuad( VECTOR2D( 0.0, -aWidth / 2.0 ), VECTOR2D( lineLength, -aWidth / 2.0 ),
|
||||||
|
false );
|
||||||
|
|
||||||
// Draw line caps
|
// Draw line caps
|
||||||
drawStrokedSemiCircle( VECTOR2D( 0.0, 0.0 ), aWidth / 2, M_PI / 2 );
|
drawStrokedSemiCircle( VECTOR2D( 0.0, 0.0 ), aWidth / 2, M_PI / 2, false );
|
||||||
drawStrokedSemiCircle( VECTOR2D( lineLength, 0.0 ), aWidth / 2, -M_PI / 2 );
|
drawStrokedSemiCircle( VECTOR2D( lineLength, 0.0 ), aWidth / 2, -M_PI / 2, false );
|
||||||
|
|
||||||
Restore();
|
Restore();
|
||||||
}
|
}
|
||||||
|
@ -772,10 +783,18 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
|
||||||
|
|
||||||
|
|
||||||
void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
||||||
|
{
|
||||||
|
drawCircle( aCenterPoint, aRadius );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_GAL::drawCircle( const VECTOR2D& aCenterPoint, double aRadius, bool aReserve )
|
||||||
{
|
{
|
||||||
if( m_isFillEnabled )
|
if( m_isFillEnabled )
|
||||||
{
|
{
|
||||||
m_currentManager->Reserve( 3 );
|
if( aReserve )
|
||||||
|
m_currentManager->Reserve( 3 );
|
||||||
|
|
||||||
m_currentManager->Color( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
|
m_currentManager->Color( m_fillColor.r, m_fillColor.g, m_fillColor.b, m_fillColor.a );
|
||||||
|
|
||||||
/* Draw a triangle that contains the circle, then shade it leaving only the circle.
|
/* Draw a triangle that contains the circle, then shade it leaving only the circle.
|
||||||
|
@ -799,7 +818,9 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
||||||
}
|
}
|
||||||
if( m_isStrokeEnabled )
|
if( m_isStrokeEnabled )
|
||||||
{
|
{
|
||||||
m_currentManager->Reserve( 3 );
|
if( aReserve )
|
||||||
|
m_currentManager->Reserve( 3 );
|
||||||
|
|
||||||
m_currentManager->Color( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b,
|
m_currentManager->Color( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b,
|
||||||
m_strokeColor.a );
|
m_strokeColor.a );
|
||||||
|
|
||||||
|
@ -994,10 +1015,25 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
|
||||||
VECTOR2D p( cos( startAngle ) * aRadius, sin( startAngle ) * aRadius );
|
VECTOR2D p( cos( startAngle ) * aRadius, sin( startAngle ) * aRadius );
|
||||||
double alpha;
|
double alpha;
|
||||||
|
|
||||||
|
int lineCount = 0;
|
||||||
|
|
||||||
|
for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
|
||||||
|
{
|
||||||
|
lineCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The last missing part
|
||||||
|
if( alpha != endAngle )
|
||||||
|
{
|
||||||
|
lineCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
reserveLineQuads( lineCount );
|
||||||
|
|
||||||
for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
|
for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
|
||||||
{
|
{
|
||||||
VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
|
VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
|
||||||
DrawLine( p, p_next );
|
drawLineQuad( p, p_next, false );
|
||||||
|
|
||||||
p = p_next;
|
p = p_next;
|
||||||
}
|
}
|
||||||
|
@ -1006,7 +1042,7 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
|
||||||
if( alpha != endAngle )
|
if( alpha != endAngle )
|
||||||
{
|
{
|
||||||
VECTOR2D p_last( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
|
VECTOR2D p_last( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
|
||||||
DrawLine( p, p_last );
|
drawLineQuad( p, p_last, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1053,6 +1089,33 @@ void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_GAL::DrawSegmentChain( const std::vector<VECTOR2D>& aPointList, double aWidth )
|
||||||
|
{
|
||||||
|
drawSegmentChain(
|
||||||
|
[&]( int idx )
|
||||||
|
{
|
||||||
|
return aPointList[idx];
|
||||||
|
},
|
||||||
|
aPointList.size(), aWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_GAL::DrawSegmentChain( const SHAPE_LINE_CHAIN& aLineChain, double aWidth )
|
||||||
|
{
|
||||||
|
auto numPoints = aLineChain.PointCount();
|
||||||
|
|
||||||
|
if( aLineChain.IsClosed() )
|
||||||
|
numPoints += 1;
|
||||||
|
|
||||||
|
drawSegmentChain(
|
||||||
|
[&]( int idx )
|
||||||
|
{
|
||||||
|
return aLineChain.CPoint( idx );
|
||||||
|
},
|
||||||
|
numPoints, aWidth );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void OPENGL_GAL::DrawPolyline( const std::deque<VECTOR2D>& aPointList )
|
void OPENGL_GAL::DrawPolyline( const std::deque<VECTOR2D>& aPointList )
|
||||||
{
|
{
|
||||||
drawPolyline(
|
drawPolyline(
|
||||||
|
@ -1102,6 +1165,27 @@ void OPENGL_GAL::DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_GAL::DrawPolylines( const std::vector<std::vector<VECTOR2D>>& aPointList )
|
||||||
|
{
|
||||||
|
int lineQuadCount = 0;
|
||||||
|
|
||||||
|
for( const std::vector<VECTOR2D>& points : aPointList )
|
||||||
|
lineQuadCount += points.size() - 1;
|
||||||
|
|
||||||
|
reserveLineQuads( lineQuadCount );
|
||||||
|
|
||||||
|
for( const std::vector<VECTOR2D>& points : aPointList )
|
||||||
|
{
|
||||||
|
drawPolyline(
|
||||||
|
[&]( int idx )
|
||||||
|
{
|
||||||
|
return points[idx];
|
||||||
|
},
|
||||||
|
points.size(), false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void OPENGL_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
|
void OPENGL_GAL::DrawPolygon( const std::deque<VECTOR2D>& aPointList )
|
||||||
{
|
{
|
||||||
wxCHECK( aPointList.size() >= 2, /* void */ );
|
wxCHECK( aPointList.size() >= 2, /* void */ );
|
||||||
|
@ -1146,6 +1230,17 @@ void OPENGL_GAL::drawTriangulatedPolyset( const SHAPE_POLY_SET& aPolySet,
|
||||||
|
|
||||||
if( m_isFillEnabled )
|
if( m_isFillEnabled )
|
||||||
{
|
{
|
||||||
|
int totalTriangleCount = 0;
|
||||||
|
|
||||||
|
for( unsigned int j = 0; j < aPolySet.TriangulatedPolyCount(); ++j )
|
||||||
|
{
|
||||||
|
auto triPoly = aPolySet.TriangulatedPolygon( j );
|
||||||
|
|
||||||
|
totalTriangleCount += triPoly->GetTriangleCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentManager->Reserve( 3 * totalTriangleCount );
|
||||||
|
|
||||||
for( unsigned int j = 0; j < aPolySet.TriangulatedPolyCount(); ++j )
|
for( unsigned int j = 0; j < aPolySet.TriangulatedPolyCount(); ++j )
|
||||||
{
|
{
|
||||||
auto triPoly = aPolySet.TriangulatedPolygon( j );
|
auto triPoly = aPolySet.TriangulatedPolygon( j );
|
||||||
|
@ -1333,7 +1428,6 @@ void OPENGL_GAL::BitmapText( const wxString& aText, const VECTOR2I& aPosition,
|
||||||
std::tie( textSize, commonOffset ) = computeBitmapTextSize( text );
|
std::tie( textSize, commonOffset ) = computeBitmapTextSize( text );
|
||||||
|
|
||||||
const double SCALE = 1.4 * GetGlyphSize().y / textSize.y;
|
const double SCALE = 1.4 * GetGlyphSize().y / textSize.y;
|
||||||
int overbarLength = 0;
|
|
||||||
double overbarHeight = textSize.y;
|
double overbarHeight = textSize.y;
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
|
@ -1381,49 +1475,91 @@ void OPENGL_GAL::BitmapText( const wxString& aText, const VECTOR2I& aPosition,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int overbarLength = 0;
|
||||||
int overbarDepth = -1;
|
int overbarDepth = -1;
|
||||||
int braceNesting = 0;
|
int braceNesting = 0;
|
||||||
|
|
||||||
for( UTF8::uni_iter chIt = text.ubegin(), end = text.uend(); chIt < end; ++chIt )
|
auto iterateString =
|
||||||
|
[&]( std::function<void( int aOverbarLength, int aOverbarHeight )> overbarFn,
|
||||||
|
std::function<int( unsigned long aChar )> bitmapCharFn )
|
||||||
{
|
{
|
||||||
wxASSERT_MSG( *chIt != '\n' && *chIt != '\r', "No support for multiline bitmap text yet" );
|
for( UTF8::uni_iter chIt = text.ubegin(), end = text.uend(); chIt < end; ++chIt )
|
||||||
|
|
||||||
if( *chIt == '~' && overbarDepth == -1 )
|
|
||||||
{
|
{
|
||||||
UTF8::uni_iter lookahead = chIt;
|
wxASSERT_MSG( *chIt != '\n' && *chIt != '\r',
|
||||||
|
"No support for multiline bitmap text yet" );
|
||||||
|
|
||||||
if( ++lookahead != end && *lookahead == '{' )
|
if( *chIt == '~' && overbarDepth == -1 )
|
||||||
|
{
|
||||||
|
UTF8::uni_iter lookahead = chIt;
|
||||||
|
|
||||||
|
if( ++lookahead != end && *lookahead == '{' )
|
||||||
|
{
|
||||||
|
chIt = lookahead;
|
||||||
|
overbarDepth = braceNesting;
|
||||||
|
braceNesting++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( *chIt == '{' )
|
||||||
{
|
{
|
||||||
chIt = lookahead;
|
|
||||||
overbarDepth = braceNesting;
|
|
||||||
braceNesting++;
|
braceNesting++;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
else if( *chIt == '}' )
|
||||||
else if( *chIt == '{' )
|
|
||||||
{
|
|
||||||
braceNesting++;
|
|
||||||
}
|
|
||||||
else if( *chIt == '}' )
|
|
||||||
{
|
|
||||||
if( braceNesting > 0 )
|
|
||||||
braceNesting--;
|
|
||||||
|
|
||||||
if( braceNesting == overbarDepth )
|
|
||||||
{
|
{
|
||||||
drawBitmapOverbar( overbarLength, overbarHeight );
|
if( braceNesting > 0 )
|
||||||
overbarLength = 0;
|
braceNesting--;
|
||||||
|
|
||||||
overbarDepth = -1;
|
if( braceNesting == overbarDepth )
|
||||||
continue;
|
{
|
||||||
|
overbarFn( overbarLength, overbarHeight );
|
||||||
|
overbarLength = 0;
|
||||||
|
|
||||||
|
overbarDepth = -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if( overbarDepth != -1 )
|
if( overbarDepth != -1 )
|
||||||
overbarLength += drawBitmapChar( *chIt );
|
overbarLength += bitmapCharFn( *chIt );
|
||||||
else
|
else
|
||||||
drawBitmapChar( *chIt );
|
bitmapCharFn( *chIt );
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// First, calculate the amount of characters and overbars to reserve
|
||||||
|
|
||||||
|
int charsCount = 0;
|
||||||
|
int overbarsCount = 0;
|
||||||
|
|
||||||
|
iterateString(
|
||||||
|
[&overbarsCount]( int aOverbarLength, int aOverbarHeight )
|
||||||
|
{
|
||||||
|
overbarsCount++;
|
||||||
|
},
|
||||||
|
[&charsCount]( unsigned long aChar ) -> int
|
||||||
|
{
|
||||||
|
if( aChar != ' ' )
|
||||||
|
charsCount++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
} );
|
||||||
|
|
||||||
|
m_currentManager->Reserve( 6 * charsCount + 6 * overbarsCount );
|
||||||
|
|
||||||
|
// Now reset the state and actually draw the characters and overbars
|
||||||
|
overbarLength = 0;
|
||||||
|
overbarDepth = -1;
|
||||||
|
braceNesting = 0;
|
||||||
|
|
||||||
|
iterateString(
|
||||||
|
[&]( int aOverbarLength, int aOverbarHeight )
|
||||||
|
{
|
||||||
|
drawBitmapOverbar( aOverbarLength, aOverbarHeight, false );
|
||||||
|
},
|
||||||
|
[&]( unsigned long aChar ) -> int
|
||||||
|
{
|
||||||
|
return drawBitmapChar( aChar, false );
|
||||||
|
} );
|
||||||
|
|
||||||
// Handle the case when overbar is active till the end of the drawn text
|
// Handle the case when overbar is active till the end of the drawn text
|
||||||
m_currentManager->Translate( 0, commonOffset, 0 );
|
m_currentManager->Translate( 0, commonOffset, 0 );
|
||||||
|
@ -1864,7 +2000,8 @@ void OPENGL_GAL::DrawCursor( const VECTOR2D& aCursorPosition )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||||
|
const bool aReserve )
|
||||||
{
|
{
|
||||||
/* Helper drawing: ____--- v3 ^
|
/* Helper drawing: ____--- v3 ^
|
||||||
* ____---- ... \ \
|
* ____---- ... \ \
|
||||||
|
@ -1888,7 +2025,8 @@ void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
|
||||||
|
|
||||||
VECTOR2D vs( v2.x - v1.x, v2.y - v1.y );
|
VECTOR2D vs( v2.x - v1.x, v2.y - v1.y );
|
||||||
|
|
||||||
m_currentManager->Reserve( 6 );
|
if( aReserve )
|
||||||
|
reserveLineQuads( 1 );
|
||||||
|
|
||||||
// Line width is maintained by the vertex shader
|
// Line width is maintained by the vertex shader
|
||||||
m_currentManager->Shader( SHADER_LINE_A, m_lineWidth, vs.x, vs.y );
|
m_currentManager->Shader( SHADER_LINE_A, m_lineWidth, vs.x, vs.y );
|
||||||
|
@ -1911,6 +2049,12 @@ void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_GAL::reserveLineQuads( const int aLineCount )
|
||||||
|
{
|
||||||
|
m_currentManager->Reserve( 6 * aLineCount );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle )
|
void OPENGL_GAL::drawSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle )
|
||||||
{
|
{
|
||||||
if( m_isFillEnabled )
|
if( m_isFillEnabled )
|
||||||
|
@ -1958,14 +2102,16 @@ void OPENGL_GAL::drawFilledSemiCircle( const VECTOR2D& aCenterPoint, double aRad
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius,
|
void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle,
|
||||||
double aAngle )
|
bool aReserve )
|
||||||
{
|
{
|
||||||
double outerRadius = aRadius + ( m_lineWidth / 2 );
|
double outerRadius = aRadius + ( m_lineWidth / 2 );
|
||||||
|
|
||||||
Save();
|
Save();
|
||||||
|
|
||||||
m_currentManager->Reserve( 3 );
|
if( aReserve )
|
||||||
|
m_currentManager->Reserve( 3 );
|
||||||
|
|
||||||
m_currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.0f );
|
m_currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.0f );
|
||||||
m_currentManager->Rotate( aAngle, 0.0f, 0.0f, 1.0f );
|
m_currentManager->Rotate( aAngle, 0.0f, 0.0f, 1.0f );
|
||||||
|
|
||||||
|
@ -2032,24 +2178,81 @@ void OPENGL_GAL::drawPolygon( GLdouble* aPoints, int aPointCount )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OPENGL_GAL::drawPolyline( const std::function<VECTOR2D( int )>& aPointGetter, int aPointCount )
|
void OPENGL_GAL::drawPolyline( const std::function<VECTOR2D( int )>& aPointGetter, int aPointCount,
|
||||||
|
bool aReserve )
|
||||||
{
|
{
|
||||||
wxCHECK( aPointCount >= 2, /* return */ );
|
wxCHECK( aPointCount >= 2, /* return */ );
|
||||||
|
|
||||||
m_currentManager->Color( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
|
m_currentManager->Color( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
|
||||||
int i;
|
|
||||||
|
|
||||||
for( i = 1; i < aPointCount; ++i )
|
if( aReserve )
|
||||||
|
{
|
||||||
|
reserveLineQuads( aPointCount - 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i = 1; i < aPointCount; ++i )
|
||||||
{
|
{
|
||||||
auto start = aPointGetter( i - 1 );
|
auto start = aPointGetter( i - 1 );
|
||||||
auto end = aPointGetter( i );
|
auto end = aPointGetter( i );
|
||||||
|
|
||||||
drawLineQuad( start, end );
|
drawLineQuad( start, end, false );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int OPENGL_GAL::drawBitmapChar( unsigned long aChar )
|
void OPENGL_GAL::drawSegmentChain( const std::function<VECTOR2D( int )>& aPointGetter,
|
||||||
|
int aPointCount, double aWidth, bool aReserve )
|
||||||
|
{
|
||||||
|
wxCHECK( aPointCount >= 2, /* return */ );
|
||||||
|
|
||||||
|
m_currentManager->Color( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
|
||||||
|
|
||||||
|
int vertices = 0;
|
||||||
|
|
||||||
|
for( int i = 1; i < aPointCount; ++i )
|
||||||
|
{
|
||||||
|
auto start = aPointGetter( i - 1 );
|
||||||
|
auto end = aPointGetter( i );
|
||||||
|
|
||||||
|
VECTOR2D startEndVector = start - end;
|
||||||
|
double lineLength = startEndVector.EuclideanNorm();
|
||||||
|
|
||||||
|
float startx = start.x;
|
||||||
|
float starty = end.y;
|
||||||
|
float endx = start.x + lineLength;
|
||||||
|
float endy = end.y + lineLength;
|
||||||
|
|
||||||
|
// Be careful about floating point rounding. As we draw segments in larger and larger
|
||||||
|
// coordinates, the shader (which uses floats) will lose precision and stop drawing small
|
||||||
|
// segments. In this case, we need to draw a circle for the minimal segment.
|
||||||
|
if( startx == endx || starty == endy )
|
||||||
|
{
|
||||||
|
vertices += 3; // One circle
|
||||||
|
}
|
||||||
|
|
||||||
|
if( m_isFillEnabled || aWidth == 1.0 )
|
||||||
|
{
|
||||||
|
vertices += 6; // One line
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vertices += 6 + 6 + 3 + 3; // Two lines and two half-circles
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentManager->Reserve( vertices );
|
||||||
|
|
||||||
|
for( int i = 1; i < aPointCount; ++i )
|
||||||
|
{
|
||||||
|
auto start = aPointGetter( i - 1 );
|
||||||
|
auto end = aPointGetter( i );
|
||||||
|
|
||||||
|
drawSegment( start, end, aWidth, false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int OPENGL_GAL::drawBitmapChar( unsigned long aChar, bool aReserve )
|
||||||
{
|
{
|
||||||
const float TEX_X = font_image.width;
|
const float TEX_X = font_image.width;
|
||||||
const float TEX_Y = font_image.height;
|
const float TEX_Y = font_image.height;
|
||||||
|
@ -2090,7 +2293,9 @@ int OPENGL_GAL::drawBitmapChar( unsigned long aChar )
|
||||||
const float H = glyph->atlas_h - font_information.smooth_pixels * 2;
|
const float H = glyph->atlas_h - font_information.smooth_pixels * 2;
|
||||||
const float B = 0;
|
const float B = 0;
|
||||||
|
|
||||||
m_currentManager->Reserve( 6 );
|
if( aReserve )
|
||||||
|
m_currentManager->Reserve( 6 );
|
||||||
|
|
||||||
Translate( VECTOR2D( XOFF, YOFF ) );
|
Translate( VECTOR2D( XOFF, YOFF ) );
|
||||||
|
|
||||||
/* Glyph:
|
/* Glyph:
|
||||||
|
@ -2126,7 +2331,7 @@ int OPENGL_GAL::drawBitmapChar( unsigned long aChar )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void OPENGL_GAL::drawBitmapOverbar( double aLength, double aHeight )
|
void OPENGL_GAL::drawBitmapOverbar( double aLength, double aHeight, bool aReserve )
|
||||||
{
|
{
|
||||||
// To draw an overbar, simply draw an overbar
|
// To draw an overbar, simply draw an overbar
|
||||||
const FONT_GLYPH_TYPE* glyph = LookupGlyph( '_' );
|
const FONT_GLYPH_TYPE* glyph = LookupGlyph( '_' );
|
||||||
|
@ -2138,7 +2343,9 @@ void OPENGL_GAL::drawBitmapOverbar( double aLength, double aHeight )
|
||||||
|
|
||||||
Translate( VECTOR2D( -aLength, -aHeight ) );
|
Translate( VECTOR2D( -aLength, -aHeight ) );
|
||||||
|
|
||||||
m_currentManager->Reserve( 6 );
|
if( aReserve )
|
||||||
|
m_currentManager->Reserve( 6 );
|
||||||
|
|
||||||
m_currentManager->Color( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
|
m_currentManager->Color( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b, m_strokeColor.a );
|
||||||
|
|
||||||
m_currentManager->Shader( 0 );
|
m_currentManager->Shader( 0 );
|
||||||
|
@ -2452,8 +2659,7 @@ void OPENGL_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal )
|
||||||
{
|
{
|
||||||
const auto& strokeGlyph = static_cast<const KIFONT::STROKE_GLYPH&>( aGlyph );
|
const auto& strokeGlyph = static_cast<const KIFONT::STROKE_GLYPH&>( aGlyph );
|
||||||
|
|
||||||
for( const std::vector<VECTOR2D>& pointList : strokeGlyph )
|
DrawPolylines( strokeGlyph );
|
||||||
DrawPolyline( pointList );
|
|
||||||
}
|
}
|
||||||
else if( aGlyph.IsOutline() )
|
else if( aGlyph.IsOutline() )
|
||||||
{
|
{
|
||||||
|
@ -2465,9 +2671,124 @@ void OPENGL_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal )
|
||||||
outlineGlyph.Triangulate(
|
outlineGlyph.Triangulate(
|
||||||
[&]( const VECTOR2D& aPt1, const VECTOR2D& aPt2, const VECTOR2D& aPt3 )
|
[&]( const VECTOR2D& aPt1, const VECTOR2D& aPt2, const VECTOR2D& aPt3 )
|
||||||
{
|
{
|
||||||
|
m_currentManager->Reserve( 3 );
|
||||||
|
|
||||||
m_currentManager->Vertex( aPt1.x, aPt1.y, m_layerDepth );
|
m_currentManager->Vertex( aPt1.x, aPt1.y, m_layerDepth );
|
||||||
m_currentManager->Vertex( aPt2.x, aPt2.y, m_layerDepth );
|
m_currentManager->Vertex( aPt2.x, aPt2.y, m_layerDepth );
|
||||||
m_currentManager->Vertex( aPt3.x, aPt3.y, m_layerDepth );
|
m_currentManager->Vertex( aPt3.x, aPt3.y, m_layerDepth );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void OPENGL_GAL::DrawGlyphs( const std::vector<std::unique_ptr<KIFONT::GLYPH>>& aGlyphs )
|
||||||
|
{
|
||||||
|
bool allGlyphsAreStroke = true;
|
||||||
|
bool allGlyphsAreOutline = true;
|
||||||
|
|
||||||
|
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
|
||||||
|
{
|
||||||
|
if( !glyph->IsStroke() )
|
||||||
|
{
|
||||||
|
allGlyphsAreStroke = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
|
||||||
|
{
|
||||||
|
if( !glyph->IsOutline() )
|
||||||
|
{
|
||||||
|
allGlyphsAreOutline = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( allGlyphsAreStroke )
|
||||||
|
{
|
||||||
|
// Optimized path for stroke fonts that pre-reserves line quads.
|
||||||
|
int lineQuadCount = 0;
|
||||||
|
|
||||||
|
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
|
||||||
|
{
|
||||||
|
const auto& strokeGlyph = static_cast<const KIFONT::STROKE_GLYPH&>( *glyph );
|
||||||
|
|
||||||
|
for( const std::vector<VECTOR2D>& points : strokeGlyph )
|
||||||
|
lineQuadCount += points.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
reserveLineQuads( lineQuadCount );
|
||||||
|
|
||||||
|
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
|
||||||
|
{
|
||||||
|
const auto& strokeGlyph = static_cast<const KIFONT::STROKE_GLYPH&>( *glyph );
|
||||||
|
|
||||||
|
for( const std::vector<VECTOR2D>& points : strokeGlyph )
|
||||||
|
{
|
||||||
|
drawPolyline(
|
||||||
|
[&]( int idx )
|
||||||
|
{
|
||||||
|
return points[idx];
|
||||||
|
},
|
||||||
|
points.size(), false );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if( allGlyphsAreOutline )
|
||||||
|
{
|
||||||
|
// Optimized path for stroke fonts that pre-reserves glyph triangles.
|
||||||
|
int triangleCount = 0;
|
||||||
|
|
||||||
|
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
|
||||||
|
{
|
||||||
|
const auto& outlineGlyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( *glyph );
|
||||||
|
|
||||||
|
// Only call CacheTriangulation if it has never been done before. Otherwise we'll hash
|
||||||
|
// the triangulation to see if it has been edited, and glyphs after creation are read-only.
|
||||||
|
if( outlineGlyph.TriangulatedPolyCount() == 0 )
|
||||||
|
const_cast<KIFONT::OUTLINE_GLYPH&>( outlineGlyph ).CacheTriangulation( false );
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < outlineGlyph.TriangulatedPolyCount(); i++ )
|
||||||
|
{
|
||||||
|
const SHAPE_POLY_SET::TRIANGULATED_POLYGON* polygon =
|
||||||
|
outlineGlyph.TriangulatedPolygon( i );
|
||||||
|
|
||||||
|
triangleCount += polygon->GetTriangleCount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentManager->Shader( SHADER_NONE );
|
||||||
|
m_currentManager->Color( m_fillColor );
|
||||||
|
|
||||||
|
m_currentManager->Reserve( 3 * triangleCount );
|
||||||
|
|
||||||
|
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
|
||||||
|
{
|
||||||
|
const auto& outlineGlyph = static_cast<const KIFONT::OUTLINE_GLYPH&>( *glyph );
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < outlineGlyph.TriangulatedPolyCount(); i++ )
|
||||||
|
{
|
||||||
|
const SHAPE_POLY_SET::TRIANGULATED_POLYGON* polygon =
|
||||||
|
outlineGlyph.TriangulatedPolygon( i );
|
||||||
|
|
||||||
|
for( size_t j = 0; j < polygon->GetTriangleCount(); j++ )
|
||||||
|
{
|
||||||
|
VECTOR2I a, b, c;
|
||||||
|
polygon->GetTriangle( j, a, b, c );
|
||||||
|
|
||||||
|
m_currentManager->Vertex( a.x, a.y, m_layerDepth );
|
||||||
|
m_currentManager->Vertex( b.x, b.y, m_layerDepth );
|
||||||
|
m_currentManager->Vertex( c.x, c.y, m_layerDepth );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Regular path
|
||||||
|
for( size_t i = 0; i < aGlyphs.size(); i++ )
|
||||||
|
DrawGlyph( *aGlyphs[i], i, aGlyphs.size() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -111,17 +111,17 @@ bool VERTEX_MANAGER::Vertex( GLfloat aX, GLfloat aY, GLfloat aZ )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newVertex = m_container->Allocate( 1 );
|
newVertex = m_container->Allocate( 1 );
|
||||||
}
|
|
||||||
|
|
||||||
if( newVertex == nullptr )
|
if( newVertex == nullptr )
|
||||||
{
|
|
||||||
if( show_err )
|
|
||||||
{
|
{
|
||||||
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Vertex: Vertex allocation error" ) );
|
if( show_err )
|
||||||
show_err = false;
|
{
|
||||||
}
|
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Vertex: Vertex allocation error" ) );
|
||||||
|
show_err = false;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
putVertex( *newVertex, aX, aY, aZ );
|
putVertex( *newVertex, aX, aY, aZ );
|
||||||
|
|
|
@ -90,6 +90,10 @@ public:
|
||||||
/// @copydoc GAL::DrawRectangle()
|
/// @copydoc GAL::DrawRectangle()
|
||||||
void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;
|
void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawSegmentChain()
|
||||||
|
void DrawSegmentChain( const std::vector<VECTOR2D>& aPointList, double aWidth ) override;
|
||||||
|
void DrawSegmentChain( const SHAPE_LINE_CHAIN& aLineChain, double aWidth ) override;
|
||||||
|
|
||||||
/// @copydoc GAL::DrawPolyline()
|
/// @copydoc GAL::DrawPolyline()
|
||||||
void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) override { drawPoly( aPointList ); }
|
void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) override { drawPoly( aPointList ); }
|
||||||
void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override
|
void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override
|
||||||
|
@ -99,6 +103,13 @@ public:
|
||||||
|
|
||||||
void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) override { drawPoly( aLineChain ); }
|
void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) override { drawPoly( aLineChain ); }
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawPolylines()
|
||||||
|
void DrawPolylines( const std::vector<std::vector<VECTOR2D>>& aPointLists ) override
|
||||||
|
{
|
||||||
|
for( const std::vector<VECTOR2D>& points : aPointLists )
|
||||||
|
drawPoly( points );
|
||||||
|
}
|
||||||
|
|
||||||
/// @copydoc GAL::DrawPolygon()
|
/// @copydoc GAL::DrawPolygon()
|
||||||
void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override { drawPoly( aPointList ); }
|
void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override { drawPoly( aPointList ); }
|
||||||
void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override
|
void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override
|
||||||
|
@ -112,6 +123,13 @@ public:
|
||||||
/// @copydoc GAL::DrawGlyph()
|
/// @copydoc GAL::DrawGlyph()
|
||||||
void DrawGlyph( const KIFONT::GLYPH& aPolySet, int aNth, int aTotal ) override;
|
void DrawGlyph( const KIFONT::GLYPH& aPolySet, int aNth, int aTotal ) override;
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawGlyphs()
|
||||||
|
void DrawGlyphs( const std::vector<std::unique_ptr<KIFONT::GLYPH>>& aGlyphs ) override
|
||||||
|
{
|
||||||
|
for( size_t i = 0; i < aGlyphs.size(); i++ )
|
||||||
|
DrawGlyph( *aGlyphs[i], i, aGlyphs.size() );
|
||||||
|
}
|
||||||
|
|
||||||
/// @copydoc GAL::DrawCurve()
|
/// @copydoc GAL::DrawCurve()
|
||||||
void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
|
void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
|
||||||
const VECTOR2D& controlPointB, const VECTOR2D& endPoint,
|
const VECTOR2D& controlPointB, const VECTOR2D& endPoint,
|
||||||
|
|
|
@ -106,7 +106,16 @@ public:
|
||||||
* @param aWidth is a width of the segment
|
* @param aWidth is a width of the segment
|
||||||
*/
|
*/
|
||||||
virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
virtual void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||||
double aWidth ) {};
|
double aWidth ){};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw a chain of rounded segments.
|
||||||
|
*
|
||||||
|
* @param aPointList is a list of 2D-Vectors containing the chain points.
|
||||||
|
* @param aWidth is a width of the segments
|
||||||
|
*/
|
||||||
|
virtual void DrawSegmentChain( const std::vector<VECTOR2D>& aPointList, double aWidth ){};
|
||||||
|
virtual void DrawSegmentChain( const SHAPE_LINE_CHAIN& aLineChain, double aWidth ){};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw a polyline
|
* Draw a polyline
|
||||||
|
@ -118,6 +127,13 @@ public:
|
||||||
virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) {};
|
virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) {};
|
||||||
virtual void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) {};
|
virtual void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw multiple polylines
|
||||||
|
*
|
||||||
|
* @param aPointLists are lists of 2D-Vectors containing the polyline points.
|
||||||
|
*/
|
||||||
|
virtual void DrawPolylines( const std::vector<std::vector<VECTOR2D>>& aPointLists ){};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw a circle using world coordinates.
|
* Draw a circle using world coordinates.
|
||||||
*
|
*
|
||||||
|
@ -173,10 +189,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw a polygon representing an outline font glyph.
|
* Draw a polygon representing a font glyph.
|
||||||
*/
|
*/
|
||||||
virtual void DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth = 0, int aTotal = 1 ) {};
|
virtual void DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth = 0, int aTotal = 1 ) {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw polygons representing font glyphs.
|
||||||
|
*/
|
||||||
|
virtual void DrawGlyphs( const std::vector<std::unique_ptr<KIFONT::GLYPH>>& aGlyphs ) {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw a polygon.
|
* Draw a polygon.
|
||||||
*
|
*
|
||||||
|
|
|
@ -122,6 +122,10 @@ public:
|
||||||
void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||||
double aWidth ) override;
|
double aWidth ) override;
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawSegmentChain()
|
||||||
|
void DrawSegmentChain( const std::vector<VECTOR2D>& aPointList, double aWidth ) override;
|
||||||
|
void DrawSegmentChain( const SHAPE_LINE_CHAIN& aLineChain, double aWidth ) override;
|
||||||
|
|
||||||
/// @copydoc GAL::DrawCircle()
|
/// @copydoc GAL::DrawCircle()
|
||||||
void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) override;
|
void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) override;
|
||||||
|
|
||||||
|
@ -142,6 +146,9 @@ public:
|
||||||
void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override;
|
void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override;
|
||||||
void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) override;
|
void DrawPolyline( const SHAPE_LINE_CHAIN& aLineChain ) override;
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawPolylines()
|
||||||
|
void DrawPolylines( const std::vector<std::vector<VECTOR2D>>& aPointLists ) override;
|
||||||
|
|
||||||
/// @copydoc GAL::DrawPolygon()
|
/// @copydoc GAL::DrawPolygon()
|
||||||
void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override;
|
void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override;
|
||||||
void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override;
|
void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override;
|
||||||
|
@ -151,6 +158,9 @@ public:
|
||||||
/// @copydoc GAL::DrawGlyph()
|
/// @copydoc GAL::DrawGlyph()
|
||||||
virtual void DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal ) override;
|
virtual void DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal ) override;
|
||||||
|
|
||||||
|
/// @copydoc GAL::DrawGlyphs()
|
||||||
|
virtual void DrawGlyphs( const std::vector<std::unique_ptr<KIFONT::GLYPH>>& aGlyphs ) override;
|
||||||
|
|
||||||
/// @copydoc GAL::DrawCurve()
|
/// @copydoc GAL::DrawCurve()
|
||||||
void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
|
void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
|
||||||
const VECTOR2D& controlPointB, const VECTOR2D& endPoint,
|
const VECTOR2D& controlPointB, const VECTOR2D& endPoint,
|
||||||
|
@ -382,8 +392,18 @@ private:
|
||||||
*
|
*
|
||||||
* @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.
|
||||||
|
* @param aReserve if set to false, call reserveLineQuads beforehand
|
||||||
|
* to reserve the right amount of vertices.
|
||||||
*/
|
*/
|
||||||
void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint );
|
void drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||||
|
bool aReserve = true );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reserves specified number of line quads.
|
||||||
|
*
|
||||||
|
* @param aLineCount the number of line quads to reserve.
|
||||||
|
*/
|
||||||
|
void reserveLineQuads( const int aLineCount );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw a semicircle.
|
* Draw a semicircle.
|
||||||
|
@ -414,17 +434,44 @@ private:
|
||||||
* @param aCenterPoint is the center point.
|
* @param aCenterPoint is the center point.
|
||||||
* @param aRadius is the radius of the semicircle.
|
* @param aRadius is the radius of the semicircle.
|
||||||
* @param aAngle is the angle of the semicircle.
|
* @param aAngle is the angle of the semicircle.
|
||||||
|
* @param aReserve if set to false, reserve 3 vertices for each semicircle.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle );
|
void drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle,
|
||||||
|
bool aReserve = true );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal method for circle drawing.
|
||||||
|
*
|
||||||
|
* @param aReserve if set to false, reserve 3 vertices for each circle.
|
||||||
|
*/
|
||||||
|
void drawCircle( const VECTOR2D& aCenterPoint, double aRadius, bool aReserve = true );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic way of drawing a polyline stored in different containers.
|
* Generic way of drawing a polyline stored in different containers.
|
||||||
*
|
*
|
||||||
* @param aPointGetter is a function to obtain coordinates of n-th vertex.
|
* @param aPointGetter is a function to obtain coordinates of n-th vertex.
|
||||||
* @param aPointCount is the number of points to be drawn.
|
* @param aPointCount is the number of points to be drawn.
|
||||||
|
* @param aReserve if set to false, reserve aPointCount - 1 line quads.
|
||||||
*/
|
*/
|
||||||
void drawPolyline( const std::function<VECTOR2D (int)>& aPointGetter, int aPointCount );
|
void drawPolyline( const std::function<VECTOR2D( int )>& aPointGetter, int aPointCount,
|
||||||
|
bool aReserve = true );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic way of drawing a chain of segments stored in different containers.
|
||||||
|
*
|
||||||
|
* @param aPointGetter is a function to obtain coordinates of n-th vertex.
|
||||||
|
* @param aPointCount is the number of points to be drawn.
|
||||||
|
* @param aReserve if set to false, do not reserve vertices internally.
|
||||||
|
*/
|
||||||
|
void drawSegmentChain( const std::function<VECTOR2D( int )>& aPointGetter, int aPointCount,
|
||||||
|
double aWidth, bool aReserve = true );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal method for segment drawing
|
||||||
|
*/
|
||||||
|
void drawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth,
|
||||||
|
bool aReserve = true );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw a filled polygon. It does not need the last point to have the same coordinates
|
* Draw a filled polygon. It does not need the last point to have the same coordinates
|
||||||
|
@ -443,7 +490,6 @@ private:
|
||||||
*/
|
*/
|
||||||
void drawTriangulatedPolyset( const SHAPE_POLY_SET& aPoly, bool aStrokeTriangulation );
|
void drawTriangulatedPolyset( const SHAPE_POLY_SET& aPoly, bool aStrokeTriangulation );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw a single character using bitmap font.
|
* Draw a single character using bitmap font.
|
||||||
*
|
*
|
||||||
|
@ -451,8 +497,9 @@ private:
|
||||||
*
|
*
|
||||||
* @param aChar is the character to be drawn.
|
* @param aChar is the character to be drawn.
|
||||||
* @return Width of the drawn glyph.
|
* @return Width of the drawn glyph.
|
||||||
|
* @param aReserve if set to false, reserve 6 vertices for each character.
|
||||||
*/
|
*/
|
||||||
int drawBitmapChar( unsigned long aChar );
|
int drawBitmapChar( unsigned long aChar, bool aReserve = true );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw an overbar over the currently drawn text.
|
* Draw an overbar over the currently drawn text.
|
||||||
|
@ -463,8 +510,9 @@ private:
|
||||||
*
|
*
|
||||||
* @param aLength is the width of the overbar.
|
* @param aLength is the width of the overbar.
|
||||||
* @param aHeight is the height for the overbar.
|
* @param aHeight is the height for the overbar.
|
||||||
|
* @param aReserve if set to false, reserve 6 vertices for each overbar.
|
||||||
*/
|
*/
|
||||||
void drawBitmapOverbar( double aLength, double aHeight );
|
void drawBitmapOverbar( double aLength, double aHeight, bool aReserve = true );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute a size of text drawn using bitmap font with current text setting applied.
|
* Compute a size of text drawn using bitmap font with current text setting applied.
|
||||||
|
|
|
@ -1629,11 +1629,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
|
||||||
|
|
||||||
if( outline_mode )
|
if( outline_mode )
|
||||||
{
|
{
|
||||||
for( int ii = 0; ii < shape.Outline( 0 ).SegmentCount(); ++ii )
|
m_gal->DrawSegmentChain( shape.Outline( 0 ), thickness );
|
||||||
{
|
|
||||||
SEG seg = shape.Outline( 0 ).Segment( ii );
|
|
||||||
m_gal->DrawSegment( seg.A, seg.B, thickness );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1642,11 +1638,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
|
||||||
|
|
||||||
if( thickness > 0 )
|
if( thickness > 0 )
|
||||||
{
|
{
|
||||||
for( int ii = 0; ii < shape.Outline( 0 ).SegmentCount(); ++ii )
|
m_gal->DrawSegmentChain( shape.Outline( 0 ), thickness );
|
||||||
{
|
|
||||||
SEG seg = shape.Outline( 0 ).Segment( ii );
|
|
||||||
m_gal->DrawSegment( seg.A, seg.B, thickness );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( aShape->IsFilled() )
|
if( aShape->IsFilled() )
|
||||||
|
@ -1682,8 +1674,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
|
||||||
BEZIER_POLY converter( pointCtrl );
|
BEZIER_POLY converter( pointCtrl );
|
||||||
converter.GetPoly( output, thickness );
|
converter.GetPoly( output, thickness );
|
||||||
|
|
||||||
for( unsigned ii = 0; ii + 1 < output.size(); ++ii )
|
m_gal->DrawSegmentChain( output, thickness );
|
||||||
m_gal->DrawSegment( output[ii], output[ii+1], thickness );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1867,8 +1858,7 @@ void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer )
|
||||||
|
|
||||||
if( cache )
|
if( cache )
|
||||||
{
|
{
|
||||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
m_gal->DrawGlyphs( *cache );
|
||||||
m_gal->DrawGlyph( *glyph.get() );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1953,8 +1943,7 @@ void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer )
|
||||||
|
|
||||||
if( cache )
|
if( cache )
|
||||||
{
|
{
|
||||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
m_gal->DrawGlyphs( *cache );
|
||||||
m_gal->DrawGlyph( *glyph.get() );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2022,8 +2011,7 @@ void PCB_PAINTER::draw( const FP_TEXT* aText, int aLayer )
|
||||||
|
|
||||||
if( cache )
|
if( cache )
|
||||||
{
|
{
|
||||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
m_gal->DrawGlyphs( *cache );
|
||||||
m_gal->DrawGlyph( *glyph.get() );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2092,8 +2080,7 @@ void PCB_PAINTER::draw( const FP_TEXTBOX* aTextBox, int aLayer )
|
||||||
|
|
||||||
if( cache )
|
if( cache )
|
||||||
{
|
{
|
||||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
m_gal->DrawGlyphs( *cache );
|
||||||
m_gal->DrawGlyph( *glyph.get() );
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue