Don't draw ruler ticks outside the viewport.

Fixes https://gitlab.com/kicad/code/kicad/issues/6518
This commit is contained in:
Jeff Young 2020-12-02 00:27:44 +00:00
parent 1cd8426bcb
commit 4b2d9a5054
1 changed files with 36 additions and 15 deletions

View File

@ -139,18 +139,19 @@ static TICK_FORMAT getTickFormatForScale( double aScale, double& aTickSpace, EDA
* @param aLine line vector * @param aLine line vector
* @param aMinorTickLen length of minor ticks in IU * @param aMinorTickLen length of minor ticks in IU
*/ */
void drawTicksAlongLine( KIGFX::GAL* aGal, const VECTOR2D& aOrigin, const VECTOR2D& aLine, void drawTicksAlongLine( KIGFX::VIEW* aView, const VECTOR2D& aOrigin, const VECTOR2D& aLine,
double aMinorTickLen, EDA_UNITS aUnits, bool aDrawingDropShadows ) double aMinorTickLen, EDA_UNITS aUnits, bool aDrawingDropShadows )
{ {
KIGFX::GAL* gal = aView->GetGAL();
VECTOR2D tickLine = aLine.Rotate( -M_PI_2 ); VECTOR2D tickLine = aLine.Rotate( -M_PI_2 );
double tickSpace; double tickSpace;
TICK_FORMAT tickF = getTickFormatForScale( aGal->GetWorldScale(), tickSpace, aUnits ); TICK_FORMAT tickF = getTickFormatForScale( gal->GetWorldScale(), tickSpace, aUnits );
// number of ticks in whole ruler // number of ticks in whole ruler
int numTicks = (int) std::ceil( aLine.EuclideanNorm() / tickSpace ); int numTicks = (int) std::ceil( aLine.EuclideanNorm() / tickSpace );
// work out which way up the tick labels go // work out which way up the tick labels go
TEXT_DIMS textDims = SetConstantGlyphHeight( aGal, -1 ); TEXT_DIMS textDims = SetConstantGlyphHeight( gal, -1 );
double textThickness = textDims.StrokeWidth; double textThickness = textDims.StrokeWidth;
double labelAngle = -tickLine.Angle(); double labelAngle = -tickLine.Angle();
double textOffset = 0; double textOffset = 0;
@ -166,18 +167,27 @@ void drawTicksAlongLine( KIGFX::GAL* aGal, const VECTOR2D& aOrigin, const VECTOR
if( aLine.Angle() > 0 ) if( aLine.Angle() > 0 )
{ {
aGal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_LEFT ); gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_LEFT );
} }
else else
{ {
aGal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_RIGHT ); gal->SetHorizontalJustify( GR_TEXT_HJUSTIFY_RIGHT );
labelAngle += M_PI; labelAngle += M_PI;
} }
BOX2D viewportD = aView->GetViewport();
BOX2I viewport( VECTOR2I( viewportD.GetPosition() ), VECTOR2I( viewportD.GetSize() ) );
viewport.Inflate( majorTickLen * 2 ); // Doesn't have to be accurate, just big enough not
// to exclude anything that should be partially drawn
for( int i = 0; i < numTicks; ++i ) for( int i = 0; i < numTicks; ++i )
{ {
const VECTOR2D tickPos = aOrigin + aLine.Resize( tickSpace * i ); const VECTOR2D tickPos = aOrigin + aLine.Resize( tickSpace * i );
if( !viewport.Contains( tickPos ) )
continue;
double length = aMinorTickLen; double length = aMinorTickLen;
bool drawLabel = false; bool drawLabel = false;
@ -192,14 +202,14 @@ void drawTicksAlongLine( KIGFX::GAL* aGal, const VECTOR2D& aOrigin, const VECTOR
length *= midTickLengthFactor; length *= midTickLengthFactor;
} }
aGal->SetLineWidth( textThickness / 2 ); gal->SetLineWidth( textThickness / 2 );
aGal->DrawLine( tickPos, tickPos + tickLine.Resize( length ) ); gal->DrawLine( tickPos, tickPos + tickLine.Resize( length ) );
if( drawLabel ) if( drawLabel )
{ {
wxString label = DimensionLabel( "", tickSpace * i, aUnits, false ); wxString label = DimensionLabel( "", tickSpace * i, aUnits, false );
aGal->SetLineWidth( textThickness ); gal->SetLineWidth( textThickness );
aGal->StrokeText( label, tickPos + labelOffset, labelAngle ); gal->StrokeText( label, tickPos + labelOffset, labelAngle );
} }
} }
} }
@ -215,18 +225,29 @@ void drawTicksAlongLine( KIGFX::GAL* aGal, const VECTOR2D& aOrigin, const VECTOR
* @param aTickLen length of ticks in IU * @param aTickLen length of ticks in IU
* @param aNumDivisions number of parts to divide the line into * @param aNumDivisions number of parts to divide the line into
*/ */
void drawBacksideTicks( KIGFX::GAL* aGal, const VECTOR2D& aOrigin, const VECTOR2D& aLine, void drawBacksideTicks( KIGFX::VIEW* aView, const VECTOR2D& aOrigin, const VECTOR2D& aLine,
double aTickLen, int aNumDivisions, bool aDrawingDropShadows ) double aTickLen, int aNumDivisions, bool aDrawingDropShadows )
{ {
KIGFX::GAL* gal = aView->GetGAL();
const double backTickSpace = aLine.EuclideanNorm() / aNumDivisions; const double backTickSpace = aLine.EuclideanNorm() / aNumDivisions;
const VECTOR2D backTickVec = aLine.Rotate( M_PI_2 ).Resize( aTickLen ); const VECTOR2D backTickVec = aLine.Rotate( M_PI_2 ).Resize( aTickLen );
TEXT_DIMS textDims = SetConstantGlyphHeight( aGal, -1 ); TEXT_DIMS textDims = SetConstantGlyphHeight( gal, -1 );
BOX2D viewportD = aView->GetViewport();
BOX2I viewport( VECTOR2I( viewportD.GetPosition() ), VECTOR2I( viewportD.GetSize() ) );
viewport.Inflate( aTickLen * 4 ); // Doesn't have to be accurate, just big enough not to
// exclude anything that should be partially drawn
for( int i = 0; i < aNumDivisions + 1; ++i ) for( int i = 0; i < aNumDivisions + 1; ++i )
{ {
const VECTOR2D backTickPos = aOrigin + aLine.Resize( backTickSpace * i ); const VECTOR2D backTickPos = aOrigin + aLine.Resize( backTickSpace * i );
aGal->SetLineWidth( getTickLineWidth( textDims, aDrawingDropShadows ) );
aGal->DrawLine( backTickPos, backTickPos + backTickVec ); if( !viewport.Contains( backTickPos ) )
continue;
gal->SetLineWidth( getTickLineWidth( textDims, aDrawingDropShadows ) );
gal->DrawLine( backTickPos, backTickPos + backTickVec );
} }
} }
@ -297,9 +318,9 @@ void RULER_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
const double minorTickLen = 5.0 / gal->GetWorldScale(); const double minorTickLen = 5.0 / gal->GetWorldScale();
const double majorTickLen = minorTickLen * majorTickLengthFactor; const double majorTickLen = minorTickLen * majorTickLengthFactor;
drawTicksAlongLine( gal, origin, rulerVec, minorTickLen, m_userUnits, drawingDropShadows ); drawTicksAlongLine( aView, origin, rulerVec, minorTickLen, m_userUnits, drawingDropShadows );
drawBacksideTicks( gal, origin, rulerVec, majorTickLen, 2, drawingDropShadows ); drawBacksideTicks( aView, origin, rulerVec, majorTickLen, 2, drawingDropShadows );
// draw the back of the origin "crosshair" // draw the back of the origin "crosshair"
gal->DrawLine( origin, origin + rulerVec.Resize( -minorTickLen * midTickLengthFactor ) ); gal->DrawLine( origin, origin + rulerVec.Resize( -minorTickLen * midTickLengthFactor ) );