Cairo GAL: fix incorrect arc position in mirror mode.

the previous fix (2e43c6c64e) did not really work.
Add also comments to a few not yet documented methods.

Fixes: lp:1822772
https://bugs.launchpad.net/kicad/+bug/1822772
This commit is contained in:
jean-pierre charras 2019-05-08 11:17:06 +02:00
parent e6fe220f84
commit 533fdcf00a
2 changed files with 58 additions and 35 deletions

View File

@ -117,9 +117,37 @@ const VECTOR2D CAIRO_GAL_BASE::xform( const VECTOR2D& aP )
const double CAIRO_GAL_BASE::angle_xform( const double aAngle )
{
double world_angle = -std::atan2( currentWorld2Screen.xy, currentWorld2Screen.xx );
// calculate rotation angle due to the rotation transform
// and if flipped on X axis.
double world_rotation = -std::atan2( currentWorld2Screen.xy, currentWorld2Screen.xx );
return std::fmod( aAngle + world_angle, 2.0 * M_PI );
// When flipped on X axis, the rotation angle is M_PI - initial angle:
if( IsFlippedX() )
world_rotation = M_PI - world_rotation;
return std::fmod( aAngle + world_rotation, 2.0 * M_PI );
}
void CAIRO_GAL_BASE::arc_angles_xform_and_normalize( double& aStartAngle, double& aEndAngle )
{
double startAngle = aStartAngle;
double endAngle = aEndAngle;
// When the view is flipped, the coordinates are flipped by the matrix transform
// However, arc angles need to be "flipped": the flipped angle is M_PI - initial angle.
if( IsFlippedX() )
{
startAngle = M_PI - startAngle;
endAngle = M_PI - endAngle;
}
// Normalize arc angles
SWAP( startAngle, >, endAngle );
// now rotate arc according to the rotation transform matrix
aStartAngle = angle_xform( startAngle );
aEndAngle = angle_xform( endAngle );
}
@ -259,21 +287,11 @@ void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, doub
{
syncLineWidth();
// When the view is flipped, the coordinates are flipped by the matrix transform
// However, arc angles need a small change: swapping start and end, *without changing*
// the arc orientation.
// TODO: see the changes if the flip is for the Y axis
if( IsFlippedX() )
{
double delta = aEndAngle - aStartAngle;
aEndAngle = aStartAngle;
aStartAngle -= delta;
}
// calculate start and end arc angles according to the rotation transform matrix
// and normalize:
arc_angles_xform_and_normalize( aStartAngle, aEndAngle );
SWAP( aStartAngle, >, aEndAngle );
auto startAngleS = angle_xform( aStartAngle );
auto endAngleS = angle_xform( aEndAngle );
auto r = xform( aRadius );
double r = xform( aRadius );
// N.B. This is backwards. We set this because we want to adjust the center
// point that changes both endpoints. In the worst case, this is twice as far.
@ -289,7 +307,7 @@ void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, doub
if( isFillEnabled )
cairo_move_to( currentContext, mid.x, mid.y );
cairo_arc( currentContext, mid.x, mid.y, r, startAngleS, endAngleS );
cairo_arc( currentContext, mid.x, mid.y, r, aStartAngle, aEndAngle );
if( isFillEnabled )
cairo_close_path( currentContext );
@ -316,21 +334,13 @@ void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadiu
syncLineWidth();
// When the view is flipped, the coordinates are flipped by the matrix transform
// However, arc angles need a small change: swapping start and end, *without changing*
// the arc orientation.
// TODO: see the changes if the flip is for the Y axis
if( IsFlippedX() )
{
double delta = aEndAngle - aStartAngle;
aEndAngle = aStartAngle;
aStartAngle -= delta;
}
// calculate start and end arc angles according to the rotation transform matrix
// and normalize:
double startAngleS = aStartAngle;
double endAngleS = aEndAngle;
arc_angles_xform_and_normalize( startAngleS, endAngleS );
SWAP( aStartAngle, >, aEndAngle );
auto startAngleS = angle_xform( aStartAngle );
auto endAngleS = angle_xform( aEndAngle );
auto r = xform( aRadius );
double r = xform( aRadius );
// N.B. This is backwards. We set this because we want to adjust the center
// point that changes both endpoints. In the worst case, this is twice as far.
@ -339,7 +349,7 @@ void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadiu
lineWidthIsOdd = !( static_cast<int>( aRadius ) % 1 );
auto mid = roundp( xform( aCenterPoint ) );
auto width = xform( aWidth / 2.0 );
double width = xform( aWidth / 2.0 );
auto startPointS = VECTOR2D( r, 0.0 ).Rotate( startAngleS );
auto endPointS = VECTOR2D( r, 0.0 ).Rotate( endAngleS );

View File

@ -219,11 +219,24 @@ public:
protected:
const double xform( double x );
const VECTOR2D xform( double x, double y );
const VECTOR2D xform( const VECTOR2D& aP );
// Geometric transforms according to the currentWorld2Screen transform matrix:
const double xform( double x ); // scale
const VECTOR2D xform( double x, double y ); // rotation, scale and offset
const VECTOR2D xform( const VECTOR2D& aP ); // rotation, scale and offset
/** Transform according to the rotation from currentWorld2Screen transform matrix:
* @param aAngle is the angle in radians to transform
* @return the modified angle
*/
const double angle_xform( const double aAngle );
/** Transform according to the rotation from currentWorld2Screen transform matrix
* for the start angle and the end angle of an arc
* @param aStartAngle is the arc starting point in radians to transform
* @param aEndAngle is the arc ending point in radians to transform
*/
void arc_angles_xform_and_normalize( double& aStartAngle, double& aEndAngle );
/// @copydoc GAL::BeginDrawing()
virtual void beginDrawing() override;