Cairo GAL: fix incorrect arc position in mirror mode. the previous fix

(c56e540e5d) did not really work.

Fix from master branch.
This commit is contained in:
jean-pierre charras 2019-05-08 11:17:06 +02:00
parent 89f9bf545d
commit cebba6c0b9
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 ) 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(); syncLineWidth();
// When the view is flipped, the coordinates are flipped by the matrix transform // calculate start and end arc angles according to the rotation transform matrix
// However, arc angles need a small change: swapping start and end, *without changing* // and normalize:
// the arc orientation. arc_angles_xform_and_normalize( aStartAngle, aEndAngle );
// TODO: see the changes if the flip is for the Y axis
if( IsFlippedX() )
{
double delta = aEndAngle - aStartAngle;
aEndAngle = aStartAngle;
aStartAngle -= delta;
}
SWAP( aStartAngle, >, aEndAngle ); double r = xform( aRadius );
auto startAngleS = angle_xform( aStartAngle );
auto endAngleS = angle_xform( aEndAngle );
auto r = xform( aRadius );
// N.B. This is backwards. We set this because we want to adjust the center // 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. // 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 ) if( isFillEnabled )
cairo_move_to( currentContext, mid.x, mid.y ); 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 ) if( isFillEnabled )
cairo_close_path( currentContext ); cairo_close_path( currentContext );
@ -316,21 +334,13 @@ void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadiu
syncLineWidth(); syncLineWidth();
// When the view is flipped, the coordinates are flipped by the matrix transform // calculate start and end arc angles according to the rotation transform matrix
// However, arc angles need a small change: swapping start and end, *without changing* // and normalize:
// the arc orientation. double startAngleS = aStartAngle;
// TODO: see the changes if the flip is for the Y axis double endAngleS = aEndAngle;
if( IsFlippedX() ) arc_angles_xform_and_normalize( startAngleS, endAngleS );
{
double delta = aEndAngle - aStartAngle;
aEndAngle = aStartAngle;
aStartAngle -= delta;
}
SWAP( aStartAngle, >, aEndAngle ); double r = xform( aRadius );
auto startAngleS = angle_xform( aStartAngle );
auto endAngleS = angle_xform( aEndAngle );
auto r = xform( aRadius );
// N.B. This is backwards. We set this because we want to adjust the center // 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. // 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 ); lineWidthIsOdd = !( static_cast<int>( aRadius ) % 1 );
auto mid = roundp( xform( aCenterPoint ) ); 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 startPointS = VECTOR2D( r, 0.0 ).Rotate( startAngleS );
auto endPointS = VECTOR2D( r, 0.0 ).Rotate( endAngleS ); auto endPointS = VECTOR2D( r, 0.0 ).Rotate( endAngleS );

View File

@ -219,11 +219,24 @@ public:
protected: protected:
const double xform( double x ); // Geometric transforms according to the currentWorld2Screen transform matrix:
const VECTOR2D xform( double x, double y ); const double xform( double x ); // scale
const VECTOR2D xform( const VECTOR2D& aP ); 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 ); 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() /// @copydoc GAL::BeginDrawing()
virtual void beginDrawing() override; virtual void beginDrawing() override;