Browse Source

Protect TesselatePolygon() against degenerated polygons (less than 3 corners) to avoid crashes.

Use TesselatePolygon() to draw polygons in Gerbview instead of GLU tesselation, much slower.
Add helper methods in GAL to know if the current GAL engine is Cairo, OpenGL or something else,
useful to optimize drawing code.
pull/13/head
jean-pierre charras 7 years ago
parent
commit
388397f97d
  1. 3
      common/geometry/shape_poly_set.cpp
  2. 12
      gerbview/gerbview_painter.cpp
  3. 2
      include/gal/cairo/cairo_gal.h
  4. 6
      include/gal/graphics_abstraction_layer.h
  5. 2
      include/gal/opengl/opengl_gal.h
  6. 4
      include/geometry/polygon_triangulation.h
  7. 11
      pcbnew/pcb_painter.cpp

3
common/geometry/shape_poly_set.cpp

@ -1872,6 +1872,9 @@ void SHAPE_POLY_SET::CacheTriangulation()
for( int i = 0; i < tmpSet.OutlineCount(); i++ )
{
if( tmpSet.Outline( i ).PointCount() < 3 ) // malformed polygon
continue;
m_triangulatedPolys.push_back( std::make_unique<TRIANGULATED_POLYGON>() );
PolygonTriangulation tess( *m_triangulatedPolys.back() );

12
gerbview/gerbview_painter.cpp

@ -260,10 +260,20 @@ void GERBVIEW_PAINTER::draw( /*const*/ GERBER_DRAW_ITEM* aItem, int aLayer )
for( auto it = absolutePolygon.Iterate( 0 ); it; ++it )
*it = aItem->GetABPosition( *it );
if( !isFilled )
// Degenerated polygons (having < 3 points) are drawn as lines
// to avoid issues in draw polygon functions
if( !isFilled || absolutePolygon.COutline( 0 ).PointCount() < 3 )
m_gal->DrawPolyline( absolutePolygon.COutline( 0 ) );
else
{
// On Opengl, a not convex filled polygon is usually drawn by using triangles as primitives.
// CacheTriangulation() can create basic triangle primitives to draw the polygon solid shape
// on Opengl
if( m_gal->IsOpenGlEngine() )
absolutePolygon.CacheTriangulation();
m_gal->DrawPolygon( absolutePolygon );
}
break;
}

2
include/gal/cairo/cairo_gal.h

@ -72,6 +72,8 @@ public:
virtual ~CAIRO_GAL_BASE();
virtual bool IsCairoEngine() override { return true; }
// ---------------
// Drawing methods
// ---------------

6
include/gal/graphics_abstraction_layer.h

@ -75,6 +75,12 @@ public:
/// @brief Returns true if the GAL canvas is visible on the screen.
virtual bool IsVisible() const { return true; }
/// @brief Returns true if the GAL engine is a cairo based type.
virtual bool IsCairoEngine() { return false; }
/// @brief Returns true if the GAL engine is a opengl based type.
virtual bool IsOpenGlEngine() { return false; }
// ---------------
// Drawing methods
// ---------------

2
include/gal/opengl/opengl_gal.h

@ -86,6 +86,8 @@ public:
virtual ~OPENGL_GAL();
virtual bool IsOpenGlEngine() override { return true; }
/// @copydoc GAL::IsInitialized()
virtual bool IsInitialized() const override
{

4
include/geometry/polygon_triangulation.h

@ -650,6 +650,10 @@ public:
bool TesselatePolygon( const SHAPE_LINE_CHAIN& aPoly )
{
ClipperLib::Clipper c;
if( aPoly.PointCount() < 3 ) // Malformed polygon
return false;
m_bbox = aPoly.BBox();
m_result.Clear();

11
pcbnew/pcb_painter.cpp

@ -974,13 +974,10 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment, int aLayer )
break;
// On Opengl, a not convex filled polygon is usually drawn by using triangles as primitives.
// Although CacheTriangulation() can create basic triangle primitives
// to draw the polygon solid shape on Opengl, it is not used because it does not work fine
// with any polygon. It must be a simple polygon.
// And unfortunately, calling shape.Simplify( PM_FAST) is very slow.
// So for now we just use GLU tesselation (much slower, but works with any polygon)
// This section is left until a better way is found
if( !shape.IsTriangulationUpToDate() )
// CacheTriangulation() can create basic triangle primitives to draw the polygon solid shape
// on Opengl.
// GLU tesselation is much slower, so currently we are using our tesselation.
if( m_gal->IsOpenGlEngine() && !shape.IsTriangulationUpToDate() )
{
shape.CacheTriangulation();
}

Loading…
Cancel
Save