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" ) );
if( m_visible )
{
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();
if( !m_visible )
return;
wxCoord startPx = m_drawOutsideMargins ? 0 : w.GetMarginLeft();
wxCoord endPx = m_drawOutsideMargins ? w.GetScrX() : w.GetScrX() - w.GetMarginRight();
wxCoord minYpx = m_drawOutsideMargins ? 0 : w.GetMarginTop();
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 );
if( !m_continuous )
@ -618,19 +627,14 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
for( auto& iy: ys )
{
if( m_drawOutsideMargins
|| ( (ix >= startPx) && (ix <= endPx) && (iy >= minYpx)
&& (iy <= maxYpx) ) )
|| ( (ix >= startPx) && (ix <= endPx) && (iy >= minYpx) && (iy <= maxYpx) ) )
{
// for some reason DrawPoint does not use the current pen,
// so we use DrawLine for fat pens
// for some reason DrawPoint does not use the current pen, so we use
// DrawLine for fat pens
if( m_pen.GetWidth() <= 1 )
{
dc.DrawPoint( ix, iy );
}
else
{
dc.DrawLine( ix, iy, 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.
// (> 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 artifacts when skipping points to the same x coordinate, for each
// group of points at a give, x coordinate we also draw a vertical line at this coord,
// from the ymin to the ymax vertical coordinates of skipped points
// To avoid artifacts when skipping points to the same x coordinate, for each group of
// points at a give, x coordinate we also draw a vertical line at this coord, from the
// ymin to the ymax vertical coordinates of skipped points
while( GetNextXY( x, y ) )
{
double px = m_scaleX->TransformToPlot( x );
@ -670,8 +674,8 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
wxCoord y1 = w.y2p( py );
// 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
// first point is drawn, the x1 low limit is startPx-1 in plot coordinates
// Note: x1 is a value truncated from px by w.x2p(). So to be sure the first point
// is drawn, the x1 low limit is startPx-1 in plot coordinates
if( x1 >= startPx-1 && x1 <= endPx )
{
if( !count || line_start.x != x1 )
@ -679,8 +683,8 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
if( count && dupx0 > 1 && ymin0 != ymax0 )
{
// Vertical points are merged, draw the pending vertical line
// However, if the line is one pixel length, it is not drawn,
// because the main trace show this point
// However, if the line is one pixel length, it is not drawn, because
// the main trace show this point
dc.DrawLine( x0, ymin0, x0, ymax0 );
}
@ -706,10 +710,10 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
if( pointList.size() > 1 )
{
// For a better look (when using dashed lines) and more optimization,
// try to merge horizontal segments, in order to plot longer lines
// we are merging horizontal segments because this is easy,
// and horizontal segments are a frequent cases
// For a better look (when using dashed lines) and more optimization, try to merge
// horizontal segments, in order to plot longer lines
// We are merging horizontal segments because this is easy, and horizontal segments
// are a frequent cases
std::vector<wxPoint> drawPoints;
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++ )
{
// Skip intermediate points between the first point and the last
// point of the segment candidate
// Skip intermediate points between the first point and the last point of the
// segment candidate
if( drawPoints.back().y == pointList[ii].y &&
drawPoints.back().y == pointList[ii+1].y )
{
continue;
}
else
{
drawPoints.push_back( pointList[ii] );
}
}
// push the last point to draw in list
if( drawPoints.back() != pointList.back() )
@ -771,7 +779,6 @@ void mpFXY::Plot( wxDC& dc, mpWindow& w )
dc.DrawText( m_name, tx, ty );
}
}
dc.DestroyClippingRegion();
}