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,
|
||||
textStyle );
|
||||
|
||||
for( const std::unique_ptr<GLYPH>& glyph : glyphs )
|
||||
aGal->DrawGlyph( *glyph.get() );
|
||||
aGal->DrawGlyphs( glyphs );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@ using namespace KIFONT;
|
|||
|
||||
STROKE_GLYPH::STROKE_GLYPH( const STROKE_GLYPH& aGlyph )
|
||||
{
|
||||
reserve( aGlyph.size() );
|
||||
|
||||
for( const std::vector<VECTOR2D>& pointList : aGlyph )
|
||||
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,
|
||||
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,
|
||||
double aWidth )
|
||||
{
|
||||
drawSegment( aStartPoint, aEndPoint, aWidth );
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::drawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint, double aWidth,
|
||||
bool aReserve )
|
||||
{
|
||||
VECTOR2D startEndVector = aEndPoint - aStartPoint;
|
||||
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.
|
||||
if( startx == endx || starty == endy )
|
||||
{
|
||||
DrawCircle( aStartPoint, aWidth / 2 );
|
||||
drawCircle( aStartPoint, aWidth / 2, aReserve );
|
||||
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 );
|
||||
|
||||
SetLineWidth( aWidth );
|
||||
drawLineQuad( aStartPoint, aEndPoint );
|
||||
drawLineQuad( aStartPoint, aEndPoint, aReserve );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -755,16 +762,20 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
|
|||
|
||||
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->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
|
||||
drawStrokedSemiCircle( VECTOR2D( 0.0, 0.0 ), aWidth / 2, M_PI / 2 );
|
||||
drawStrokedSemiCircle( VECTOR2D( lineLength, 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, false );
|
||||
|
||||
Restore();
|
||||
}
|
||||
|
@ -772,10 +783,18 @@ void OPENGL_GAL::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndP
|
|||
|
||||
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
m_currentManager->Reserve( 3 );
|
||||
if( aReserve )
|
||||
m_currentManager->Reserve( 3 );
|
||||
|
||||
m_currentManager->Color( m_strokeColor.r, m_strokeColor.g, m_strokeColor.b,
|
||||
m_strokeColor.a );
|
||||
|
||||
|
@ -994,10 +1015,25 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
|
|||
VECTOR2D p( cos( startAngle ) * aRadius, sin( startAngle ) * aRadius );
|
||||
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 )
|
||||
{
|
||||
VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
|
||||
DrawLine( p, p_next );
|
||||
drawLineQuad( p, p_next, false );
|
||||
|
||||
p = p_next;
|
||||
}
|
||||
|
@ -1006,7 +1042,7 @@ void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
|
|||
if( alpha != endAngle )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
wxCHECK( aPointList.size() >= 2, /* void */ );
|
||||
|
@ -1146,6 +1230,17 @@ void OPENGL_GAL::drawTriangulatedPolyset( const SHAPE_POLY_SET& aPolySet,
|
|||
|
||||
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 )
|
||||
{
|
||||
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 );
|
||||
|
||||
const double SCALE = 1.4 * GetGlyphSize().y / textSize.y;
|
||||
int overbarLength = 0;
|
||||
double overbarHeight = textSize.y;
|
||||
|
||||
Save();
|
||||
|
@ -1381,49 +1475,91 @@ void OPENGL_GAL::BitmapText( const wxString& aText, const VECTOR2I& aPosition,
|
|||
break;
|
||||
}
|
||||
|
||||
int overbarLength = 0;
|
||||
int overbarDepth = -1;
|
||||
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" );
|
||||
|
||||
if( *chIt == '~' && overbarDepth == -1 )
|
||||
for( UTF8::uni_iter chIt = text.ubegin(), end = text.uend(); chIt < end; ++chIt )
|
||||
{
|
||||
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++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if( *chIt == '{' )
|
||||
{
|
||||
braceNesting++;
|
||||
}
|
||||
else if( *chIt == '}' )
|
||||
{
|
||||
if( braceNesting > 0 )
|
||||
braceNesting--;
|
||||
|
||||
if( braceNesting == overbarDepth )
|
||||
else if( *chIt == '}' )
|
||||
{
|
||||
drawBitmapOverbar( overbarLength, overbarHeight );
|
||||
overbarLength = 0;
|
||||
if( braceNesting > 0 )
|
||||
braceNesting--;
|
||||
|
||||
overbarDepth = -1;
|
||||
continue;
|
||||
if( braceNesting == overbarDepth )
|
||||
{
|
||||
overbarFn( overbarLength, overbarHeight );
|
||||
overbarLength = 0;
|
||||
|
||||
overbarDepth = -1;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( overbarDepth != -1 )
|
||||
overbarLength += drawBitmapChar( *chIt );
|
||||
else
|
||||
drawBitmapChar( *chIt );
|
||||
}
|
||||
if( overbarDepth != -1 )
|
||||
overbarLength += bitmapCharFn( *chIt );
|
||||
else
|
||||
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
|
||||
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 ^
|
||||
* ____---- ... \ \
|
||||
|
@ -1888,7 +2025,8 @@ void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
|
|||
|
||||
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
|
||||
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 )
|
||||
{
|
||||
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,
|
||||
double aAngle )
|
||||
void OPENGL_GAL::drawStrokedSemiCircle( const VECTOR2D& aCenterPoint, double aRadius, double aAngle,
|
||||
bool aReserve )
|
||||
{
|
||||
double outerRadius = aRadius + ( m_lineWidth / 2 );
|
||||
|
||||
Save();
|
||||
|
||||
m_currentManager->Reserve( 3 );
|
||||
if( aReserve )
|
||||
m_currentManager->Reserve( 3 );
|
||||
|
||||
m_currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.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 */ );
|
||||
|
||||
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 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_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 B = 0;
|
||||
|
||||
m_currentManager->Reserve( 6 );
|
||||
if( aReserve )
|
||||
m_currentManager->Reserve( 6 );
|
||||
|
||||
Translate( VECTOR2D( XOFF, YOFF ) );
|
||||
|
||||
/* 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
|
||||
const FONT_GLYPH_TYPE* glyph = LookupGlyph( '_' );
|
||||
|
@ -2138,7 +2343,9 @@ void OPENGL_GAL::drawBitmapOverbar( double aLength, double 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->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 );
|
||||
|
||||
for( const std::vector<VECTOR2D>& pointList : strokeGlyph )
|
||||
DrawPolyline( pointList );
|
||||
DrawPolylines( strokeGlyph );
|
||||
}
|
||||
else if( aGlyph.IsOutline() )
|
||||
{
|
||||
|
@ -2465,9 +2671,124 @@ void OPENGL_GAL::DrawGlyph( const KIFONT::GLYPH& aGlyph, int aNth, int aTotal )
|
|||
outlineGlyph.Triangulate(
|
||||
[&]( 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( aPt2.x, aPt2.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
|
||||
{
|
||||
newVertex = m_container->Allocate( 1 );
|
||||
}
|
||||
|
||||
if( newVertex == nullptr )
|
||||
{
|
||||
if( show_err )
|
||||
if( newVertex == nullptr )
|
||||
{
|
||||
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Vertex: Vertex allocation error" ) );
|
||||
show_err = false;
|
||||
}
|
||||
if( show_err )
|
||||
{
|
||||
DisplayError( nullptr, wxT( "VERTEX_MANAGER::Vertex: Vertex allocation error" ) );
|
||||
show_err = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
putVertex( *newVertex, aX, aY, aZ );
|
||||
|
|
|
@ -90,6 +90,10 @@ public:
|
|||
/// @copydoc GAL::DrawRectangle()
|
||||
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()
|
||||
void DrawPolyline( const std::deque<VECTOR2D>& aPointList ) override { drawPoly( aPointList ); }
|
||||
void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) override
|
||||
|
@ -99,6 +103,13 @@ public:
|
|||
|
||||
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()
|
||||
void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override { drawPoly( aPointList ); }
|
||||
void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override
|
||||
|
@ -112,6 +123,13 @@ public:
|
|||
/// @copydoc GAL::DrawGlyph()
|
||||
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()
|
||||
void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
|
||||
const VECTOR2D& controlPointB, const VECTOR2D& endPoint,
|
||||
|
|
|
@ -106,7 +106,16 @@ public:
|
|||
* @param aWidth is a width of the segment
|
||||
*/
|
||||
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
|
||||
|
@ -118,6 +127,13 @@ public:
|
|||
virtual void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) {};
|
||||
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.
|
||||
*
|
||||
|
@ -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 ) {};
|
||||
|
||||
/**
|
||||
* Draw polygons representing font glyphs.
|
||||
*/
|
||||
virtual void DrawGlyphs( const std::vector<std::unique_ptr<KIFONT::GLYPH>>& aGlyphs ) {};
|
||||
|
||||
/**
|
||||
* Draw a polygon.
|
||||
*
|
||||
|
|
|
@ -122,6 +122,10 @@ public:
|
|||
void DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||
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()
|
||||
void DrawCircle( const VECTOR2D& aCenterPoint, double aRadius ) override;
|
||||
|
||||
|
@ -142,6 +146,9 @@ public:
|
|||
void DrawPolyline( const VECTOR2D aPointList[], int aListSize ) 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()
|
||||
void DrawPolygon( const std::deque<VECTOR2D>& aPointList ) override;
|
||||
void DrawPolygon( const VECTOR2D aPointList[], int aListSize ) override;
|
||||
|
@ -151,6 +158,9 @@ public:
|
|||
/// @copydoc GAL::DrawGlyph()
|
||||
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()
|
||||
void DrawCurve( const VECTOR2D& startPoint, const VECTOR2D& controlPointA,
|
||||
const VECTOR2D& controlPointB, const VECTOR2D& endPoint,
|
||||
|
@ -382,8 +392,18 @@ private:
|
|||
*
|
||||
* @param aStartPoint is the start 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.
|
||||
|
@ -414,17 +434,44 @@ private:
|
|||
* @param aCenterPoint is the center point.
|
||||
* @param aRadius is the radius 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.
|
||||
*
|
||||
* @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, 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
|
||||
|
@ -443,7 +490,6 @@ private:
|
|||
*/
|
||||
void drawTriangulatedPolyset( const SHAPE_POLY_SET& aPoly, bool aStrokeTriangulation );
|
||||
|
||||
|
||||
/**
|
||||
* Draw a single character using bitmap font.
|
||||
*
|
||||
|
@ -451,8 +497,9 @@ private:
|
|||
*
|
||||
* @param aChar is the character to be drawn.
|
||||
* @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.
|
||||
|
@ -463,8 +510,9 @@ private:
|
|||
*
|
||||
* @param aLength is the width of 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.
|
||||
|
|
|
@ -1629,11 +1629,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
|
|||
|
||||
if( outline_mode )
|
||||
{
|
||||
for( int ii = 0; ii < shape.Outline( 0 ).SegmentCount(); ++ii )
|
||||
{
|
||||
SEG seg = shape.Outline( 0 ).Segment( ii );
|
||||
m_gal->DrawSegment( seg.A, seg.B, thickness );
|
||||
}
|
||||
m_gal->DrawSegmentChain( shape.Outline( 0 ), thickness );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1642,11 +1638,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
|
|||
|
||||
if( thickness > 0 )
|
||||
{
|
||||
for( int ii = 0; ii < shape.Outline( 0 ).SegmentCount(); ++ii )
|
||||
{
|
||||
SEG seg = shape.Outline( 0 ).Segment( ii );
|
||||
m_gal->DrawSegment( seg.A, seg.B, thickness );
|
||||
}
|
||||
m_gal->DrawSegmentChain( shape.Outline( 0 ), thickness );
|
||||
}
|
||||
|
||||
if( aShape->IsFilled() )
|
||||
|
@ -1682,8 +1674,7 @@ void PCB_PAINTER::draw( const PCB_SHAPE* aShape, int aLayer )
|
|||
BEZIER_POLY converter( pointCtrl );
|
||||
converter.GetPoly( output, thickness );
|
||||
|
||||
for( unsigned ii = 0; ii + 1 < output.size(); ++ii )
|
||||
m_gal->DrawSegment( output[ii], output[ii+1], thickness );
|
||||
m_gal->DrawSegmentChain( output, thickness );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1867,8 +1858,7 @@ void PCB_PAINTER::draw( const PCB_TEXT* aText, int aLayer )
|
|||
|
||||
if( cache )
|
||||
{
|
||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
||||
m_gal->DrawGlyph( *glyph.get() );
|
||||
m_gal->DrawGlyphs( *cache );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1953,8 +1943,7 @@ void PCB_PAINTER::draw( const PCB_TEXTBOX* aTextBox, int aLayer )
|
|||
|
||||
if( cache )
|
||||
{
|
||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
||||
m_gal->DrawGlyph( *glyph.get() );
|
||||
m_gal->DrawGlyphs( *cache );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2022,8 +2011,7 @@ void PCB_PAINTER::draw( const FP_TEXT* aText, int aLayer )
|
|||
|
||||
if( cache )
|
||||
{
|
||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
||||
m_gal->DrawGlyph( *glyph.get() );
|
||||
m_gal->DrawGlyphs( *cache );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2092,8 +2080,7 @@ void PCB_PAINTER::draw( const FP_TEXTBOX* aTextBox, int aLayer )
|
|||
|
||||
if( cache )
|
||||
{
|
||||
for( const std::unique_ptr<KIFONT::GLYPH>& glyph : *cache )
|
||||
m_gal->DrawGlyph( *glyph.get() );
|
||||
m_gal->DrawGlyphs( *cache );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue