Don't allocate all of memory when the coord system turns inside out.

Fixes https://gitlab.com/kicad/code/kicad/issues/14088
This commit is contained in:
Jeff Young 2023-02-26 21:50:43 +00:00
parent bcdb979128
commit fe9370ceea
1 changed files with 177 additions and 170 deletions

View File

@ -572,22 +572,31 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
wxCHECK_RET( m_scaleY, wxS( "Y scale was not set" ) ); wxCHECK_RET( m_scaleY, wxS( "Y scale was not set" ) );
if( m_visible ) if( !m_visible )
{ return;
dc.SetPen( m_pen );
double x, y;
// Do this to reset the counters to evaluate bounding box for label positioning
Rewind(); GetNextXY( x, y );
maxDrawX = x; minDrawX = x; maxDrawY = y; minDrawY = y;
// drawnPoints = 0;
Rewind();
wxCoord startPx = m_drawOutsideMargins ? 0 : w.GetMarginLeft(); wxCoord startPx = m_drawOutsideMargins ? 0 : w.GetMarginLeft();
wxCoord endPx = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight(); wxCoord endPx = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight();
wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop(); wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop();
wxCoord maxYpx = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom(); wxCoord maxYpx = m_drawOutsideMargins ? w.GetScrY() : w.GetScrY() - w.GetMarginBottom();
// Check for a collapsed window before we try to allocate a negative number of points
if( endPx <= startPx || minYpx >= maxYpx )
return;
dc.SetPen( m_pen );
double x, y;
// Do this to reset the counters to evaluate bounding box for label positioning
Rewind();
GetNextXY( x, y );
maxDrawX = x;
minDrawX = x;
maxDrawY = y;
minDrawY = y;
// drawnPoints = 0;
Rewind();
dc.SetClippingRegion( startPx, minYpx, endPx - startPx + 1, maxYpx - minYpx + 1 ); dc.SetClippingRegion( startPx, minYpx, endPx - startPx + 1, maxYpx - minYpx + 1 );
if( !m_continuous ) if( !m_continuous )
@ -618,19 +627,14 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
for( auto& iy: ys ) for( auto& iy: ys )
{ {
if( m_drawOutsideMargins if( m_drawOutsideMargins
|| ( (ix >= startPx) && (ix <= endPx) && (iy >= minYpx) || ( (ix >= startPx) && (ix <= endPx) && (iy >= minYpx) && (iy <= maxYpx) ) )
&& (iy <= maxYpx) ) )
{ {
// for some reason DrawPoint does not use the current pen, // for some reason DrawPoint does not use the current pen, so we use
// so we use DrawLine for fat pens // DrawLine for fat pens
if( m_pen.GetWidth() <= 1 ) if( m_pen.GetWidth() <= 1 )
{
dc.DrawPoint( ix, iy ); dc.DrawPoint( ix, iy );
}
else else
{
dc.DrawLine( ix, iy, ix, iy ); dc.DrawLine( ix, iy, ix, iy );
}
UpdateViewBoundary( ix, iy ); UpdateViewBoundary( ix, iy );
} }
@ -658,9 +662,9 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
// because at least on Windows dc.DrawLines() can hang for a lot of points. // because at least on Windows dc.DrawLines() can hang for a lot of points.
// (> 10000 points) (can happens when a lot of points is calculated) // (> 10000 points) (can happens when a lot of points is calculated)
// To avoid long draw time (and perhaps hanging) one plot only not redundant lines. // To avoid long draw time (and perhaps hanging) one plot only not redundant lines.
// To avoid artifacts when skipping points to the same x coordinate, for each // To avoid artifacts when skipping points to the same x coordinate, for each group of
// group of points at a give, x coordinate we also draw a vertical line at this coord, // points at a give, x coordinate we also draw a vertical line at this coord, from the
// from the ymin to the ymax vertical coordinates of skipped points // ymin to the ymax vertical coordinates of skipped points
while( GetNextXY( x, y ) ) while( GetNextXY( x, y ) )
{ {
double px = m_scaleX->TransformToPlot( x ); double px = m_scaleX->TransformToPlot( x );
@ -670,8 +674,8 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
wxCoord y1 = w.y2p( py ); wxCoord y1 = w.y2p( py );
// Store only points on the drawing area, to speed up the drawing time // Store only points on the drawing area, to speed up the drawing time
// Note: x1 is a value truncated from px by w.x2p(). So to be sure the // Note: x1 is a value truncated from px by w.x2p(). So to be sure the first point
// first point is drawn, the x1 low limit is startPx-1 in plot coordinates // is drawn, the x1 low limit is startPx-1 in plot coordinates
if( x1 >= startPx-1 && x1 <= endPx ) if( x1 >= startPx-1 && x1 <= endPx )
{ {
if( !count || line_start.x != x1 ) if( !count || line_start.x != x1 )
@ -679,8 +683,8 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
if( count && dupx0 > 1 && ymin0 != ymax0 ) if( count && dupx0 > 1 && ymin0 != ymax0 )
{ {
// Vertical points are merged, draw the pending vertical line // Vertical points are merged, draw the pending vertical line
// However, if the line is one pixel length, it is not drawn, // However, if the line is one pixel length, it is not drawn, because
// because the main trace show this point // the main trace show this point
dc.DrawLine( x0, ymin0, x0, ymax0 ); dc.DrawLine( x0, ymin0, x0, ymax0 );
} }
@ -706,10 +710,10 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
if( pointList.size() > 1 ) if( pointList.size() > 1 )
{ {
// For a better look (when using dashed lines) and more optimization, // For a better look (when using dashed lines) and more optimization, try to merge
// try to merge horizontal segments, in order to plot longer lines // horizontal segments, in order to plot longer lines
// we are merging horizontal segments because this is easy, // We are merging horizontal segments because this is easy, and horizontal segments
// and horizontal segments are a frequent cases // are a frequent cases
std::vector<wxPoint> drawPoints; std::vector<wxPoint> drawPoints;
drawPoints.reserve( endPx - startPx + 1 ); drawPoints.reserve( endPx - startPx + 1 );
@ -717,14 +721,18 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
for( size_t ii = 1; ii < pointList.size()-1; ii++ ) for( size_t ii = 1; ii < pointList.size()-1; ii++ )
{ {
// Skip intermediate points between the first point and the last // Skip intermediate points between the first point and the last point of the
// point of the segment candidate // segment candidate
if( drawPoints.back().y == pointList[ii].y && if( drawPoints.back().y == pointList[ii].y &&
drawPoints.back().y == pointList[ii+1].y ) drawPoints.back().y == pointList[ii+1].y )
{
continue; continue;
}
else else
{
drawPoints.push_back( pointList[ii] ); drawPoints.push_back( pointList[ii] );
} }
}
// push the last point to draw in list // push the last point to draw in list
if( drawPoints.back() != pointList.back() ) if( drawPoints.back() != pointList.back() )
@ -771,7 +779,6 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
dc.DrawText( m_name, tx, ty ); dc.DrawText( m_name, tx, ty );
} }
}
dc.DestroyClippingRegion(); dc.DestroyClippingRegion();
} }