gal: pixel alignment hacks, works for Retina display too now.
gal: pixel alignment for Cairo. gal: pixel alignment for OpenGL Cleanup of pixel alignment patches gal/opengl: more pixel alignment patches: - works on Retina displays now - pixel alignment for circles - correct 1-pixel strokes - fixed unfinished 1-pixel line ends GAL: Restore antialiasing options in Cairo GAL: Fix arc drawing Removes DrawArcSegment, which drew arcs whose edge was optionally stroked (a feature that we did not use). Fixes Cairo arc drawing issue where arcs were not visible in pcbnew. gal: further cleanup gal: removed unused shader parameter
This commit is contained in:
parent
303b7ac7f8
commit
bbee30671a
|
@ -35,7 +35,7 @@ using namespace KIGFX;
|
|||
|
||||
CAIRO_COMPOSITOR::CAIRO_COMPOSITOR( cairo_t** aMainContext ) :
|
||||
m_current( 0 ), m_currentContext( aMainContext ), m_mainContext( *aMainContext ),
|
||||
m_currentAntialiasingMode( CAIRO_ANTIALIAS_NONE )
|
||||
m_currentAntialiasingMode( CAIRO_ANTIALIAS_DEFAULT )
|
||||
{
|
||||
// Do not have uninitialized members:
|
||||
cairo_matrix_init_identity( &m_matrix );
|
||||
|
@ -109,9 +109,7 @@ unsigned int CAIRO_COMPOSITOR::CreateBuffer()
|
|||
#endif /* __WXDEBUG__ */
|
||||
|
||||
// Set default settings for the buffer
|
||||
cairo_set_antialias( context, m_currentAntialiasingMode );
|
||||
cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND );
|
||||
cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );
|
||||
cairo_set_antialias( context, m_currentAntialiasingMode );
|
||||
|
||||
// Use the same transformation matrix as the main context
|
||||
cairo_get_matrix( m_mainContext, &m_matrix );
|
||||
|
|
|
@ -88,26 +88,95 @@ void CAIRO_GAL_BASE::endDrawing()
|
|||
Flush();
|
||||
}
|
||||
|
||||
void CAIRO_GAL_BASE::updateWorldScreenMatrix()
|
||||
{
|
||||
cairo_matrix_multiply( ¤tWorld2Screen, ¤tXform, &cairoWorldScreenMatrix );
|
||||
}
|
||||
|
||||
const VECTOR2D CAIRO_GAL_BASE::xform( double x, double y )
|
||||
{
|
||||
VECTOR2D rv;
|
||||
|
||||
rv.x = currentWorld2Screen.xx * x + currentWorld2Screen.xy * y + currentWorld2Screen.x0;
|
||||
rv.y = currentWorld2Screen.yx * x + currentWorld2Screen.yy * y + currentWorld2Screen.y0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
const VECTOR2D CAIRO_GAL_BASE::xform( const VECTOR2D& aP )
|
||||
{
|
||||
return xform(aP.x, aP.y);
|
||||
}
|
||||
|
||||
const double CAIRO_GAL_BASE::xform( double x )
|
||||
{
|
||||
double dx = currentWorld2Screen.xx * x;
|
||||
double dy = currentWorld2Screen.yx * x;
|
||||
return sqrt( dx * dx + dy * dy );
|
||||
}
|
||||
|
||||
static double roundp( double x )
|
||||
{
|
||||
return floor( x + 0.5 ) + 0.5;
|
||||
}
|
||||
|
||||
const VECTOR2D CAIRO_GAL_BASE::roundp( const VECTOR2D& v )
|
||||
{
|
||||
if ( lineWidthIsOdd )
|
||||
return VECTOR2D( ::roundp( v.x ), ::roundp( v.y ) );
|
||||
else
|
||||
return VECTOR2D( floor( v.x + 0.5 ), floor( v.y + 0.5 ) );
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_GAL_BASE::DrawLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
||||
{
|
||||
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
|
||||
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
|
||||
syncLineWidth();
|
||||
|
||||
auto p0 = roundp( xform( aStartPoint ) );
|
||||
auto p1 = roundp( xform( aEndPoint ) );
|
||||
|
||||
cairo_move_to( currentContext, p0.x, p0.y );
|
||||
cairo_line_to( currentContext, p1.x, p1.y );
|
||||
flushPath();
|
||||
isElementAdded = true;
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_GAL_BASE::syncLineWidth( bool aForceWidth, double aWidth )
|
||||
{
|
||||
auto w = floor( xform( aForceWidth ? aWidth : lineWidth ) + 0.5 );
|
||||
|
||||
if (w <= 1.0)
|
||||
{
|
||||
w = 1.0;
|
||||
cairo_set_line_join( currentContext, CAIRO_LINE_JOIN_MITER );
|
||||
cairo_set_line_cap( currentContext, CAIRO_LINE_CAP_BUTT );
|
||||
cairo_set_line_width( currentContext, 1.0 );
|
||||
lineWidthIsOdd = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_set_line_join( currentContext, CAIRO_LINE_JOIN_ROUND );
|
||||
cairo_set_line_cap( currentContext, CAIRO_LINE_CAP_ROUND );
|
||||
cairo_set_line_width( currentContext, w );
|
||||
lineWidthIsOdd = ((int)w % 2) == 1;
|
||||
}
|
||||
|
||||
lineWidthInPixels = w;
|
||||
}
|
||||
|
||||
void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint,
|
||||
double aWidth )
|
||||
{
|
||||
if( isFillEnabled )
|
||||
{
|
||||
// Filled tracks mode
|
||||
SetLineWidth( aWidth );
|
||||
syncLineWidth( true, aWidth );
|
||||
|
||||
cairo_move_to( currentContext, (double) aStartPoint.x, (double) aStartPoint.y );
|
||||
cairo_line_to( currentContext, (double) aEndPoint.x, (double) aEndPoint.y );
|
||||
auto p0 = roundp( xform( aStartPoint ) );
|
||||
auto p1 = roundp( xform( aEndPoint ) );
|
||||
|
||||
cairo_move_to( currentContext, p0.x, p0.y );
|
||||
cairo_line_to( currentContext, p1.x, p1.y );
|
||||
cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, fillColor.a );
|
||||
cairo_stroke( currentContext );
|
||||
}
|
||||
|
@ -116,25 +185,29 @@ void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& a
|
|||
// Outline mode for tracks
|
||||
VECTOR2D startEndVector = aEndPoint - aStartPoint;
|
||||
double lineAngle = atan2( startEndVector.y, startEndVector.x );
|
||||
double lineLength = startEndVector.EuclideanNorm();
|
||||
|
||||
cairo_save( currentContext );
|
||||
double sa = sin( lineAngle + M_PI / 2.0 );
|
||||
double ca = cos( lineAngle + M_PI / 2.0 );
|
||||
|
||||
auto pa0 = roundp( xform ( aStartPoint + VECTOR2D(aWidth * ca, aWidth * sa ) ) );
|
||||
auto pa1 = roundp( xform ( aStartPoint - VECTOR2D(aWidth * ca, aWidth * sa ) ) );
|
||||
auto pb0 = roundp( xform ( aEndPoint + VECTOR2D(aWidth * ca, aWidth * sa ) ) );
|
||||
auto pb1 = roundp( xform ( aEndPoint - VECTOR2D(aWidth * ca, aWidth * sa ) ) );
|
||||
auto pa = roundp( xform( aStartPoint ) );
|
||||
auto pb = roundp( xform( aEndPoint ) );
|
||||
auto rb = ::roundp( (pa0 - pa).EuclideanNorm() );
|
||||
|
||||
cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
|
||||
|
||||
cairo_translate( currentContext, aStartPoint.x, aStartPoint.y );
|
||||
cairo_rotate( currentContext, lineAngle );
|
||||
cairo_move_to( currentContext, pa0.x, pa0.y );
|
||||
cairo_line_to( currentContext, pb0.x, pb0.y );
|
||||
|
||||
cairo_arc( currentContext, 0.0, 0.0, aWidth / 2.0, M_PI / 2.0, 3.0 * M_PI / 2.0 );
|
||||
cairo_arc( currentContext, lineLength, 0.0, aWidth / 2.0, -M_PI / 2.0, M_PI / 2.0 );
|
||||
cairo_move_to( currentContext, pa1.x, pa1.y );
|
||||
cairo_line_to( currentContext, pb1.x, pb1.y );
|
||||
|
||||
cairo_move_to( currentContext, 0.0, aWidth / 2.0 );
|
||||
cairo_line_to( currentContext, lineLength, aWidth / 2.0 );
|
||||
cairo_arc( currentContext, pb.x, pb.y, rb, lineAngle - M_PI / 2.0, lineAngle + M_PI / 2.0 );
|
||||
cairo_arc( currentContext, pa.x, pa.y, rb, lineAngle + M_PI / 2.0, lineAngle + 3.0 * M_PI / 2.0 );
|
||||
|
||||
cairo_move_to( currentContext, 0.0, -aWidth / 2.0 );
|
||||
cairo_line_to( currentContext, lineLength, -aWidth / 2.0 );
|
||||
|
||||
cairo_restore( currentContext );
|
||||
flushPath();
|
||||
}
|
||||
|
||||
|
@ -144,8 +217,14 @@ void CAIRO_GAL_BASE::DrawSegment( const VECTOR2D& aStartPoint, const VECTOR2D& a
|
|||
|
||||
void CAIRO_GAL_BASE::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
||||
{
|
||||
syncLineWidth();
|
||||
|
||||
auto c = roundp( xform( aCenterPoint ) );
|
||||
auto r = ::roundp( xform( aRadius ) );
|
||||
|
||||
cairo_new_sub_path( currentContext );
|
||||
cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, 0.0, 2 * M_PI );
|
||||
cairo_arc( currentContext, c.x, c.y, r, 0.0, 2 * M_PI);
|
||||
cairo_close_path( currentContext );
|
||||
flushPath();
|
||||
isElementAdded = true;
|
||||
}
|
||||
|
@ -154,97 +233,60 @@ void CAIRO_GAL_BASE::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
|||
void CAIRO_GAL_BASE::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
|
||||
double aEndAngle )
|
||||
{
|
||||
syncLineWidth();
|
||||
|
||||
auto c = roundp( xform( aCenterPoint ) );
|
||||
auto r = ::roundp( xform( aRadius ) );
|
||||
|
||||
VECTOR2D startPoint( cos( aStartAngle ) * aRadius + aCenterPoint.x,
|
||||
sin( aStartAngle ) * aRadius + aCenterPoint.y );
|
||||
VECTOR2D endPoint( cos( aEndAngle ) * aRadius + aCenterPoint.x,
|
||||
sin( aEndAngle ) * aRadius + aCenterPoint.y );
|
||||
|
||||
auto startPointS = roundp( xform ( startPoint ) );
|
||||
auto endPointS = roundp( xform ( endPoint ) );
|
||||
|
||||
SWAP( aStartAngle, >, aEndAngle );
|
||||
|
||||
if( isFillEnabled ) // Draw the filled area of the shape, before drawing the outline itself
|
||||
{
|
||||
auto pen_size = GetLineWidth();
|
||||
auto fgcolor = GetStrokeColor();
|
||||
SetStrokeColor( GetFillColor() );
|
||||
|
||||
SetLineWidth( 0 );
|
||||
cairo_set_line_width( currentContext, 1.0 );
|
||||
cairo_new_sub_path( currentContext );
|
||||
cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, aStartAngle, aEndAngle );
|
||||
VECTOR2D startPoint( cos( aStartAngle ) * aRadius + aCenterPoint.x,
|
||||
sin( aStartAngle ) * aRadius + aCenterPoint.y );
|
||||
VECTOR2D endPoint( cos( aEndAngle ) * aRadius + aCenterPoint.x,
|
||||
sin( aEndAngle ) * aRadius + aCenterPoint.y );
|
||||
cairo_arc( currentContext, c.x, c.y, r, aStartAngle, aEndAngle );
|
||||
|
||||
cairo_move_to( currentContext, aCenterPoint.x, aCenterPoint.y );
|
||||
cairo_line_to( currentContext, startPoint.x, startPoint.y );
|
||||
cairo_line_to( currentContext, endPoint.x, endPoint.y );
|
||||
cairo_move_to( currentContext, c.x, c.y );
|
||||
cairo_line_to( currentContext, startPointS.x, startPointS.y );
|
||||
cairo_line_to( currentContext, endPointS.x, endPointS.y );
|
||||
cairo_close_path( currentContext );
|
||||
flushPath();
|
||||
SetLineWidth( pen_size );
|
||||
SetStrokeColor( fgcolor );
|
||||
}
|
||||
|
||||
cairo_set_line_width(currentContext, lineWidthInPixels );
|
||||
cairo_new_sub_path( currentContext );
|
||||
cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, aStartAngle, aEndAngle );
|
||||
cairo_arc( currentContext, c.x, c.y, r, aStartAngle, aEndAngle );
|
||||
flushPath();
|
||||
|
||||
isElementAdded = true;
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_GAL_BASE::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
|
||||
double aEndAngle, double aWidth )
|
||||
{
|
||||
SWAP( aStartAngle, >, aEndAngle );
|
||||
|
||||
if( isFillEnabled )
|
||||
{
|
||||
// Filled segments mode
|
||||
SetLineWidth( aWidth );
|
||||
cairo_arc( currentContext, aCenterPoint.x, aCenterPoint.y, aRadius, aStartAngle, aEndAngle );
|
||||
cairo_set_source_rgba( currentContext, fillColor.r, fillColor.g, fillColor.b, fillColor.a );
|
||||
cairo_stroke( currentContext );
|
||||
}
|
||||
else
|
||||
{
|
||||
double width = aWidth / 2.0;
|
||||
VECTOR2D startPoint( cos( aStartAngle ) * aRadius,
|
||||
sin( aStartAngle ) * aRadius );
|
||||
VECTOR2D endPoint( cos( aEndAngle ) * aRadius,
|
||||
sin( aEndAngle ) * aRadius );
|
||||
|
||||
cairo_save( currentContext );
|
||||
|
||||
cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
|
||||
|
||||
cairo_translate( currentContext, aCenterPoint.x, aCenterPoint.y );
|
||||
|
||||
cairo_new_sub_path( currentContext );
|
||||
cairo_arc( currentContext, 0, 0, aRadius - width, aStartAngle, aEndAngle );
|
||||
|
||||
cairo_new_sub_path( currentContext );
|
||||
cairo_arc( currentContext, 0, 0, aRadius + width, aStartAngle, aEndAngle );
|
||||
|
||||
cairo_new_sub_path( currentContext );
|
||||
cairo_arc_negative( currentContext, startPoint.x, startPoint.y, width, aStartAngle, aStartAngle + M_PI );
|
||||
|
||||
cairo_new_sub_path( currentContext );
|
||||
cairo_arc( currentContext, endPoint.x, endPoint.y, width, aEndAngle, aEndAngle + M_PI );
|
||||
|
||||
cairo_restore( currentContext );
|
||||
flushPath();
|
||||
}
|
||||
|
||||
isElementAdded = true;
|
||||
}
|
||||
|
||||
|
||||
void CAIRO_GAL_BASE::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
||||
{
|
||||
// Calculate the diagonal points
|
||||
VECTOR2D diagonalPointA( aEndPoint.x, aStartPoint.y );
|
||||
VECTOR2D diagonalPointB( aStartPoint.x, aEndPoint.y );
|
||||
syncLineWidth();
|
||||
|
||||
const auto p0 = roundp( xform( aStartPoint ) );
|
||||
const auto p1 = roundp( xform( aEndPoint ) );
|
||||
|
||||
// The path is composed from 4 segments
|
||||
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
|
||||
cairo_line_to( currentContext, diagonalPointA.x, diagonalPointA.y );
|
||||
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
|
||||
cairo_line_to( currentContext, diagonalPointB.x, diagonalPointB.y );
|
||||
cairo_move_to( currentContext, p0.x, p0.y );
|
||||
cairo_line_to( currentContext, p1.x, p0.y );
|
||||
cairo_line_to( currentContext, p1.x, p1.y );
|
||||
cairo_line_to( currentContext, p0.x, p1.y );
|
||||
cairo_close_path( currentContext );
|
||||
flushPath();
|
||||
|
||||
|
@ -268,10 +310,16 @@ void CAIRO_GAL_BASE::DrawPolygon( const SHAPE_LINE_CHAIN& aPolygon )
|
|||
void CAIRO_GAL_BASE::DrawCurve( const VECTOR2D& aStartPoint, const VECTOR2D& aControlPointA,
|
||||
const VECTOR2D& aControlPointB, const VECTOR2D& aEndPoint )
|
||||
{
|
||||
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
|
||||
cairo_curve_to( currentContext, aControlPointA.x, aControlPointA.y, aControlPointB.x,
|
||||
aControlPointB.y, aEndPoint.x, aEndPoint.y );
|
||||
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
|
||||
syncLineWidth();
|
||||
|
||||
const auto sp = roundp( xform( aStartPoint ) );
|
||||
const auto cpa = roundp( xform( aControlPointA ) );
|
||||
const auto cpb = roundp( xform( aControlPointB ) );
|
||||
const auto ep = roundp( xform( aEndPoint ) );
|
||||
|
||||
cairo_move_to( currentContext, sp.x, sp.y );
|
||||
cairo_curve_to( currentContext, cpa.x, cpa.y, cpb.x, cpb.y, ep.x, ep.y );
|
||||
cairo_line_to( currentContext, ep.x, ep.y );
|
||||
|
||||
flushPath();
|
||||
isElementAdded = true;
|
||||
|
@ -285,13 +333,22 @@ void CAIRO_GAL_BASE::DrawBitmap( const BITMAP_BASE& aBitmap )
|
|||
// We have to calculate the pixel size in users units to draw the image.
|
||||
// worldUnitLength is a factor used for converting IU to inches
|
||||
double scale = 1.0 / ( aBitmap.GetPPI() * worldUnitLength );
|
||||
cairo_scale( currentContext, scale, scale );
|
||||
|
||||
// The position of the bitmap is the bitmap center.
|
||||
// move the draw origin to the top left bitmap corner:
|
||||
int w = aBitmap.GetSizePixels().x;
|
||||
int h = aBitmap.GetSizePixels().y;
|
||||
cairo_translate( currentContext, -w/2, -h/2 );
|
||||
|
||||
auto matrix = currentWorld2Screen;
|
||||
|
||||
// hack: fix the world 2 screen matrix so that our bitmap is placed where it should
|
||||
// (cairo_translate does not chain transforms)
|
||||
matrix.xx *= scale;
|
||||
matrix.yy *= scale;
|
||||
matrix.x0 -= matrix.xx * (double)w / 2;
|
||||
matrix.y0 -= matrix.yy * (double)h / 2;
|
||||
|
||||
cairo_set_matrix( currentContext, &matrix );
|
||||
|
||||
cairo_new_path( currentContext );
|
||||
cairo_surface_t* image = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, w, h );
|
||||
|
@ -441,11 +498,7 @@ void CAIRO_GAL_BASE::SetLineWidth( float aLineWidth )
|
|||
}
|
||||
else
|
||||
{
|
||||
// Make lines appear at least 1 pixel wide, no matter of zoom
|
||||
double x = 1.0, y = 1.0;
|
||||
cairo_device_to_user_distance( currentContext, &x, &y );
|
||||
auto minWidth = std::min( fabs( x ), fabs( y ) );
|
||||
cairo_set_line_width( currentContext, std::fmax( aLineWidth, minWidth ) );
|
||||
lineWidth = aLineWidth;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -459,7 +512,7 @@ void CAIRO_GAL_BASE::SetLayerDepth( double aLayerDepth )
|
|||
|
||||
void CAIRO_GAL_BASE::Transform( const MATRIX3x3D& aTransformation )
|
||||
{
|
||||
cairo_matrix_t cairoTransformation;
|
||||
cairo_matrix_t cairoTransformation, newXform;
|
||||
|
||||
cairo_matrix_init( &cairoTransformation,
|
||||
aTransformation.m_data[0][0],
|
||||
|
@ -469,7 +522,9 @@ void CAIRO_GAL_BASE::Transform( const MATRIX3x3D& aTransformation )
|
|||
aTransformation.m_data[0][2],
|
||||
aTransformation.m_data[1][2] );
|
||||
|
||||
cairo_transform( currentContext, &cairoTransformation );
|
||||
cairo_matrix_multiply( &newXform, ¤tXform, &cairoTransformation );
|
||||
currentXform = newXform;
|
||||
updateWorldScreenMatrix();
|
||||
}
|
||||
|
||||
|
||||
|
@ -486,7 +541,8 @@ void CAIRO_GAL_BASE::Rotate( double aAngle )
|
|||
}
|
||||
else
|
||||
{
|
||||
cairo_rotate( currentContext, aAngle );
|
||||
cairo_matrix_rotate( ¤tXform, aAngle );
|
||||
updateWorldScreenMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -505,7 +561,8 @@ void CAIRO_GAL_BASE::Translate( const VECTOR2D& aTranslation )
|
|||
}
|
||||
else
|
||||
{
|
||||
cairo_translate( currentContext, aTranslation.x, aTranslation.y );
|
||||
cairo_matrix_translate ( ¤tXform, aTranslation.x, aTranslation.y );
|
||||
updateWorldScreenMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -524,7 +581,8 @@ void CAIRO_GAL_BASE::Scale( const VECTOR2D& aScale )
|
|||
}
|
||||
else
|
||||
{
|
||||
cairo_scale( currentContext, aScale.x, aScale.y );
|
||||
cairo_matrix_scale( ¤tXform, aScale.x, aScale.y );
|
||||
updateWorldScreenMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -541,7 +599,8 @@ void CAIRO_GAL_BASE::Save()
|
|||
}
|
||||
else
|
||||
{
|
||||
cairo_save( currentContext );
|
||||
xformStack.push_back( currentXform );
|
||||
updateWorldScreenMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -558,7 +617,12 @@ void CAIRO_GAL_BASE::Restore()
|
|||
}
|
||||
else
|
||||
{
|
||||
cairo_restore( currentContext );
|
||||
if( !xformStack.empty() )
|
||||
{
|
||||
currentXform = xformStack.back();
|
||||
xformStack.pop_back();
|
||||
updateWorldScreenMatrix();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -747,9 +811,6 @@ void CAIRO_GAL_BASE::EnableDepthTest( bool aEnabled )
|
|||
|
||||
void CAIRO_GAL_BASE::resetContext()
|
||||
{
|
||||
|
||||
cairo_set_antialias( context, CAIRO_ANTIALIAS_NONE );
|
||||
|
||||
ClearScreen();
|
||||
|
||||
// Compute the world <-> screen transformations
|
||||
|
@ -760,14 +821,16 @@ void CAIRO_GAL_BASE::resetContext()
|
|||
worldScreenMatrix.m_data[1][1], worldScreenMatrix.m_data[0][2],
|
||||
worldScreenMatrix.m_data[1][2] );
|
||||
|
||||
cairo_set_matrix( context, &cairoWorldScreenMatrix );
|
||||
// we work in screen-space coordinates and do the transforms outside.
|
||||
cairo_identity_matrix( context );
|
||||
|
||||
cairo_matrix_init_identity( ¤tXform );
|
||||
|
||||
// Start drawing with a new path
|
||||
cairo_new_path( context );
|
||||
isElementAdded = true;
|
||||
|
||||
cairo_set_line_join( context, CAIRO_LINE_JOIN_ROUND );
|
||||
cairo_set_line_cap( context, CAIRO_LINE_CAP_ROUND );
|
||||
updateWorldScreenMatrix();
|
||||
|
||||
lineWidth = 0;
|
||||
}
|
||||
|
@ -775,12 +838,39 @@ void CAIRO_GAL_BASE::resetContext()
|
|||
|
||||
void CAIRO_GAL_BASE::drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
||||
{
|
||||
cairo_move_to( currentContext, aStartPoint.x, aStartPoint.y );
|
||||
cairo_line_to( currentContext, aEndPoint.x, aEndPoint.y );
|
||||
auto p0 = roundp( xform( aStartPoint ) );
|
||||
auto p1 = roundp( xform( aEndPoint ) );
|
||||
|
||||
syncLineWidth();
|
||||
|
||||
cairo_move_to( currentContext, p0.x, p0.y );
|
||||
cairo_line_to( currentContext, p1.x, p1.y );
|
||||
cairo_set_source_rgba( currentContext, strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
|
||||
cairo_stroke( currentContext );
|
||||
}
|
||||
|
||||
void CAIRO_GAL_BASE::drawGridPoint( const VECTOR2D& aPoint, double aSize )
|
||||
{
|
||||
auto p = roundp( xform( aPoint ) );
|
||||
auto s = aSize / 2.0;
|
||||
|
||||
if( (((int)aSize) % 2) == 0 ) // s even
|
||||
{
|
||||
p += VECTOR2D( 0.5, 0.5 );
|
||||
}
|
||||
|
||||
cairo_set_line_join( currentContext, CAIRO_LINE_JOIN_MITER );
|
||||
cairo_set_line_cap( currentContext, CAIRO_LINE_CAP_BUTT );
|
||||
cairo_set_line_width( currentContext, 1.0 ); //floor( aSize + 0.5 ) - 0.5 );
|
||||
|
||||
cairo_move_to( currentContext, p.x - s, p.y - s);
|
||||
cairo_line_to( currentContext, p.x + s, p.y - s);
|
||||
cairo_line_to( currentContext, p.x + s, p.y + s);
|
||||
cairo_line_to( currentContext, p.x - s, p.y + s);
|
||||
cairo_close_path( currentContext );
|
||||
|
||||
cairo_fill( currentContext );
|
||||
}
|
||||
|
||||
void CAIRO_GAL_BASE::flushPath()
|
||||
{
|
||||
|
@ -875,11 +965,17 @@ void CAIRO_GAL_BASE::drawPoly( const std::deque<VECTOR2D>& aPointList )
|
|||
// Iterate over the point list and draw the segments
|
||||
std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
|
||||
|
||||
cairo_move_to( currentContext, it->x, it->y );
|
||||
syncLineWidth();
|
||||
|
||||
const auto p = roundp( xform( it->x, it->y ) );
|
||||
|
||||
cairo_move_to( currentContext, p.x, p.y );
|
||||
|
||||
for( ++it; it != aPointList.end(); ++it )
|
||||
{
|
||||
cairo_line_to( currentContext, it->x, it->y );
|
||||
const auto p2 = roundp( xform( it->x, it->y ) );
|
||||
|
||||
cairo_line_to( currentContext, p2.x, p2.y );
|
||||
}
|
||||
|
||||
flushPath();
|
||||
|
@ -892,12 +988,16 @@ void CAIRO_GAL_BASE::drawPoly( const VECTOR2D aPointList[], int aListSize )
|
|||
// Iterate over the point list and draw the segments
|
||||
const VECTOR2D* ptr = aPointList;
|
||||
|
||||
cairo_move_to( currentContext, ptr->x, ptr->y );
|
||||
syncLineWidth();
|
||||
|
||||
const auto p = roundp( xform( ptr->x, ptr->y ) );
|
||||
cairo_move_to( currentContext, p.x, p.y );
|
||||
|
||||
for( int i = 0; i < aListSize; ++i )
|
||||
{
|
||||
++ptr;
|
||||
cairo_line_to( currentContext, ptr->x, ptr->y );
|
||||
const auto p2 = roundp( xform( ptr->x, ptr->y ) );
|
||||
cairo_line_to( currentContext, p2.x, p2.y );
|
||||
}
|
||||
|
||||
flushPath();
|
||||
|
@ -910,18 +1010,22 @@ void CAIRO_GAL_BASE::drawPoly( const SHAPE_LINE_CHAIN& aLineChain )
|
|||
if( aLineChain.PointCount() < 2 )
|
||||
return;
|
||||
|
||||
syncLineWidth();
|
||||
|
||||
auto numPoints = aLineChain.PointCount();
|
||||
|
||||
if( aLineChain.IsClosed() )
|
||||
numPoints += 1;
|
||||
|
||||
const VECTOR2I start = aLineChain.CPoint( 0 );
|
||||
cairo_move_to( currentContext, start.x, start.y );
|
||||
const auto p = roundp( xform( start.x, start.y ) );
|
||||
cairo_move_to( currentContext, p.x, p.y );
|
||||
|
||||
for( int i = 1; i < numPoints; ++i )
|
||||
{
|
||||
const VECTOR2I& p = aLineChain.CPoint( i );
|
||||
cairo_line_to( currentContext, p.x, p.y );
|
||||
const VECTOR2I& pw = aLineChain.CPoint( i );
|
||||
const auto ps = roundp( xform( pw.x, pw.y ) );
|
||||
cairo_line_to( currentContext, ps.x, ps.y );
|
||||
}
|
||||
|
||||
flushPath();
|
||||
|
@ -1238,6 +1342,7 @@ void CAIRO_GAL::setCompositor()
|
|||
compositor->Resize( screenSize.x, screenSize.y );
|
||||
compositor->SetAntialiasingMode( options.cairo_antialiasing_mode );
|
||||
|
||||
|
||||
// Prepare buffers
|
||||
mainBuffer = compositor->CreateBuffer();
|
||||
overlayBuffer = compositor->CreateBuffer();
|
||||
|
@ -1282,3 +1387,188 @@ bool CAIRO_GAL::updatedGalDisplayOptions( const GAL_DISPLAY_OPTIONS& aOptions )
|
|||
|
||||
return refresh;
|
||||
}
|
||||
|
||||
void CAIRO_GAL_BASE::DrawGrid()
|
||||
{
|
||||
SetTarget( TARGET_NONCACHED );
|
||||
|
||||
// Draw the grid
|
||||
// For the drawing the start points, end points and increments have
|
||||
// to be calculated in world coordinates
|
||||
VECTOR2D worldStartPoint = screenWorldMatrix * VECTOR2D( 0.0, 0.0 );
|
||||
VECTOR2D worldEndPoint = screenWorldMatrix * VECTOR2D( screenSize );
|
||||
|
||||
const double gridThreshold = computeMinGridSpacing();
|
||||
|
||||
int gridScreenSizeDense = KiROUND( gridSize.x * worldScale );
|
||||
int gridScreenSizeCoarse = KiROUND( gridSize.x * static_cast<double>( gridTick ) * worldScale );
|
||||
|
||||
// Compute the line marker or point radius of the grid
|
||||
// Note: generic grids can't handle sub-pixel lines without
|
||||
// either losing fine/course distinction or having some dots
|
||||
// fail to render
|
||||
float marker = std::fmax( 1.0f, gridLineWidth ) / worldScale;
|
||||
float doubleMarker = 2.0f * marker;
|
||||
|
||||
// Draw axes if desired
|
||||
if( axesEnabled )
|
||||
{
|
||||
SetIsFill( false );
|
||||
SetIsStroke( true );
|
||||
SetStrokeColor( axesColor );
|
||||
SetLineWidth( marker );
|
||||
|
||||
drawGridLine( VECTOR2D( worldStartPoint.x, 0 ),
|
||||
VECTOR2D( worldEndPoint.x, 0 ) );
|
||||
|
||||
drawGridLine( VECTOR2D( 0, worldStartPoint.y ),
|
||||
VECTOR2D( 0, worldEndPoint.y ) );
|
||||
}
|
||||
|
||||
if( !gridVisibility )
|
||||
return;
|
||||
|
||||
// Check if the grid would not be too dense
|
||||
if( std::max( gridScreenSizeDense, gridScreenSizeCoarse ) <= gridThreshold )
|
||||
return;
|
||||
|
||||
// Compute grid staring and ending indexes to draw grid points on the
|
||||
// visible screen area
|
||||
// Note: later any point coordinate will be offsetted by gridOrigin
|
||||
int gridStartX = KiROUND( ( worldStartPoint.x - gridOrigin.x ) / gridSize.x );
|
||||
int gridEndX = KiROUND( ( worldEndPoint.x - gridOrigin.x ) / gridSize.x );
|
||||
int gridStartY = KiROUND( ( worldStartPoint.y - gridOrigin.y ) / gridSize.y );
|
||||
int gridEndY = KiROUND( ( worldEndPoint.y - gridOrigin.y ) / gridSize.y );
|
||||
|
||||
// Ensure start coordinate > end coordinate
|
||||
if( gridStartX > gridEndX )
|
||||
std::swap( gridStartX, gridEndX );
|
||||
|
||||
if( gridStartY > gridEndY )
|
||||
std::swap( gridStartY, gridEndY );
|
||||
|
||||
// Ensure the grid fills the screen
|
||||
--gridStartX; ++gridEndX;
|
||||
--gridStartY; ++gridEndY;
|
||||
|
||||
// Draw the grid behind all other layers
|
||||
SetLayerDepth( depthRange.y * 0.75 );
|
||||
|
||||
if( gridStyle == GRID_STYLE::LINES )
|
||||
{
|
||||
SetIsFill( false );
|
||||
SetIsStroke( true );
|
||||
SetStrokeColor( gridColor );
|
||||
|
||||
// Now draw the grid, every coarse grid line gets the double width
|
||||
|
||||
// Vertical lines
|
||||
for( int j = gridStartY; j <= gridEndY; j++ )
|
||||
{
|
||||
const double y = j * gridSize.y + gridOrigin.y;
|
||||
|
||||
if( axesEnabled && y == 0 )
|
||||
continue;
|
||||
|
||||
if( j % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
||||
SetLineWidth( doubleMarker );
|
||||
else
|
||||
SetLineWidth( marker );
|
||||
|
||||
if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
||||
|| gridScreenSizeDense > gridThreshold )
|
||||
{
|
||||
drawGridLine( VECTOR2D( gridStartX * gridSize.x + gridOrigin.x, y ),
|
||||
VECTOR2D( gridEndX * gridSize.x + gridOrigin.x, y ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Horizontal lines
|
||||
for( int i = gridStartX; i <= gridEndX; i++ )
|
||||
{
|
||||
const double x = i * gridSize.x + gridOrigin.x;
|
||||
|
||||
if( axesEnabled && x == 0 )
|
||||
continue;
|
||||
|
||||
if( i % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
||||
SetLineWidth( doubleMarker );
|
||||
else
|
||||
SetLineWidth( marker );
|
||||
|
||||
if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
||||
|| gridScreenSizeDense > gridThreshold )
|
||||
{
|
||||
drawGridLine( VECTOR2D( x, gridStartY * gridSize.y + gridOrigin.y ),
|
||||
VECTOR2D( x, gridEndY * gridSize.y + gridOrigin.y ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( gridStyle == GRID_STYLE::SMALL_CROSS )
|
||||
{
|
||||
SetIsFill( false );
|
||||
SetIsStroke( true );
|
||||
SetStrokeColor( gridColor );
|
||||
|
||||
SetLineWidth( marker );
|
||||
double lineLen = GetLineWidth() * 2;
|
||||
|
||||
// Vertical positions:
|
||||
for( int j = gridStartY; j <= gridEndY; j++ )
|
||||
{
|
||||
if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
||||
|| gridScreenSizeDense > gridThreshold )
|
||||
{
|
||||
int posY = j * gridSize.y + gridOrigin.y;
|
||||
|
||||
// Horizontal positions:
|
||||
for( int i = gridStartX; i <= gridEndX; i++ )
|
||||
{
|
||||
if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
||||
|| gridScreenSizeDense > gridThreshold )
|
||||
{
|
||||
int posX = i * gridSize.x + gridOrigin.x;
|
||||
|
||||
drawGridLine( VECTOR2D( posX - lineLen, posY ),
|
||||
VECTOR2D( posX + lineLen, posY ) );
|
||||
|
||||
drawGridLine( VECTOR2D( posX, posY - lineLen ),
|
||||
VECTOR2D( posX, posY + lineLen ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Dotted grid
|
||||
{
|
||||
bool tickX, tickY;
|
||||
SetIsFill( true );
|
||||
SetIsStroke( false );
|
||||
SetFillColor( gridColor );
|
||||
|
||||
for( int j = gridStartY; j <= gridEndY; j++ )
|
||||
{
|
||||
if( j % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
||||
tickY = true;
|
||||
else
|
||||
tickY = false;
|
||||
|
||||
for( int i = gridStartX; i <= gridEndX; i++ )
|
||||
{
|
||||
if( i % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
||||
tickX = true;
|
||||
else
|
||||
tickX = false;
|
||||
|
||||
if( tickX || tickY || gridScreenSizeDense > gridThreshold )
|
||||
{
|
||||
double radius = ( ( tickX && tickY ) ? 2.0 : 1.0 );
|
||||
drawGridPoint( VECTOR2D( i * gridSize.x + gridOrigin.x,
|
||||
j * gridSize.y + gridOrigin.y ), radius );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -213,191 +213,6 @@ double GAL::computeMinGridSpacing() const
|
|||
}
|
||||
|
||||
|
||||
void GAL::DrawGrid()
|
||||
{
|
||||
SetTarget( TARGET_NONCACHED );
|
||||
|
||||
// Draw the grid
|
||||
// For the drawing the start points, end points and increments have
|
||||
// to be calculated in world coordinates
|
||||
VECTOR2D worldStartPoint = screenWorldMatrix * VECTOR2D( 0.0, 0.0 );
|
||||
VECTOR2D worldEndPoint = screenWorldMatrix * VECTOR2D( screenSize );
|
||||
|
||||
const double gridThreshold = computeMinGridSpacing();
|
||||
|
||||
int gridScreenSizeDense = KiROUND( gridSize.x * worldScale );
|
||||
int gridScreenSizeCoarse = KiROUND( gridSize.x * static_cast<double>( gridTick ) * worldScale );
|
||||
|
||||
// Compute the line marker or point radius of the grid
|
||||
// Note: generic grids can't handle sub-pixel lines without
|
||||
// either losing fine/course distinction or having some dots
|
||||
// fail to render
|
||||
float marker = std::fmax( 1.0f, gridLineWidth ) / worldScale;
|
||||
float doubleMarker = 2.0f * marker;
|
||||
|
||||
// Draw axes if desired
|
||||
if( axesEnabled )
|
||||
{
|
||||
SetIsFill( false );
|
||||
SetIsStroke( true );
|
||||
SetStrokeColor( axesColor );
|
||||
SetLineWidth( marker );
|
||||
|
||||
drawGridLine( VECTOR2D( worldStartPoint.x, 0 ),
|
||||
VECTOR2D( worldEndPoint.x, 0 ) );
|
||||
|
||||
drawGridLine( VECTOR2D( 0, worldStartPoint.y ),
|
||||
VECTOR2D( 0, worldEndPoint.y ) );
|
||||
}
|
||||
|
||||
if( !gridVisibility )
|
||||
return;
|
||||
|
||||
// Check if the grid would not be too dense
|
||||
if( std::max( gridScreenSizeDense, gridScreenSizeCoarse ) <= gridThreshold )
|
||||
return;
|
||||
|
||||
// Compute grid staring and ending indexes to draw grid points on the
|
||||
// visible screen area
|
||||
// Note: later any point coordinate will be offsetted by gridOrigin
|
||||
int gridStartX = KiROUND( ( worldStartPoint.x - gridOrigin.x ) / gridSize.x );
|
||||
int gridEndX = KiROUND( ( worldEndPoint.x - gridOrigin.x ) / gridSize.x );
|
||||
int gridStartY = KiROUND( ( worldStartPoint.y - gridOrigin.y ) / gridSize.y );
|
||||
int gridEndY = KiROUND( ( worldEndPoint.y - gridOrigin.y ) / gridSize.y );
|
||||
|
||||
// Ensure start coordinate > end coordinate
|
||||
if( gridStartX > gridEndX )
|
||||
std::swap( gridStartX, gridEndX );
|
||||
|
||||
if( gridStartY > gridEndY )
|
||||
std::swap( gridStartY, gridEndY );
|
||||
|
||||
// Ensure the grid fills the screen
|
||||
--gridStartX; ++gridEndX;
|
||||
--gridStartY; ++gridEndY;
|
||||
|
||||
// Draw the grid behind all other layers
|
||||
SetLayerDepth( depthRange.y * 0.75 );
|
||||
|
||||
if( gridStyle == GRID_STYLE::LINES )
|
||||
{
|
||||
SetIsFill( false );
|
||||
SetIsStroke( true );
|
||||
SetStrokeColor( gridColor );
|
||||
|
||||
// Now draw the grid, every coarse grid line gets the double width
|
||||
|
||||
// Vertical lines
|
||||
for( int j = gridStartY; j <= gridEndY; j++ )
|
||||
{
|
||||
const double y = j * gridSize.y + gridOrigin.y;
|
||||
|
||||
if( axesEnabled && y == 0 )
|
||||
continue;
|
||||
|
||||
if( j % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
||||
SetLineWidth( doubleMarker );
|
||||
else
|
||||
SetLineWidth( marker );
|
||||
|
||||
if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
||||
|| gridScreenSizeDense > gridThreshold )
|
||||
{
|
||||
drawGridLine( VECTOR2D( gridStartX * gridSize.x + gridOrigin.x, y ),
|
||||
VECTOR2D( gridEndX * gridSize.x + gridOrigin.x, y ) );
|
||||
}
|
||||
}
|
||||
|
||||
// Horizontal lines
|
||||
for( int i = gridStartX; i <= gridEndX; i++ )
|
||||
{
|
||||
const double x = i * gridSize.x + gridOrigin.x;
|
||||
|
||||
if( axesEnabled && x == 0 )
|
||||
continue;
|
||||
|
||||
if( i % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
||||
SetLineWidth( doubleMarker );
|
||||
else
|
||||
SetLineWidth( marker );
|
||||
|
||||
if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
||||
|| gridScreenSizeDense > gridThreshold )
|
||||
{
|
||||
drawGridLine( VECTOR2D( x, gridStartY * gridSize.y + gridOrigin.y ),
|
||||
VECTOR2D( x, gridEndY * gridSize.y + gridOrigin.y ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if( gridStyle == GRID_STYLE::SMALL_CROSS )
|
||||
{
|
||||
SetIsFill( false );
|
||||
SetIsStroke( true );
|
||||
SetStrokeColor( gridColor );
|
||||
|
||||
SetLineWidth( marker );
|
||||
double lineLen = GetLineWidth() * 2;
|
||||
|
||||
// Vertical positions:
|
||||
for( int j = gridStartY; j <= gridEndY; j++ )
|
||||
{
|
||||
if( ( j % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
||||
|| gridScreenSizeDense > gridThreshold )
|
||||
{
|
||||
int posY = j * gridSize.y + gridOrigin.y;
|
||||
|
||||
// Horizontal positions:
|
||||
for( int i = gridStartX; i <= gridEndX; i++ )
|
||||
{
|
||||
if( ( i % gridTick == 0 && gridScreenSizeCoarse > gridThreshold )
|
||||
|| gridScreenSizeDense > gridThreshold )
|
||||
{
|
||||
int posX = i * gridSize.x + gridOrigin.x;
|
||||
|
||||
drawGridLine( VECTOR2D( posX - lineLen, posY ),
|
||||
VECTOR2D( posX + lineLen, posY ) );
|
||||
|
||||
drawGridLine( VECTOR2D( posX, posY - lineLen ),
|
||||
VECTOR2D( posX, posY + lineLen ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Dotted grid
|
||||
{
|
||||
bool tickX, tickY;
|
||||
SetIsFill( true );
|
||||
SetIsStroke( false );
|
||||
SetFillColor( gridColor );
|
||||
|
||||
for( int j = gridStartY; j <= gridEndY; j++ )
|
||||
{
|
||||
if( j % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
||||
tickY = true;
|
||||
else
|
||||
tickY = false;
|
||||
|
||||
for( int i = gridStartX; i <= gridEndX; i++ )
|
||||
{
|
||||
if( i % gridTick == 0 && gridScreenSizeDense > gridThreshold )
|
||||
tickX = true;
|
||||
else
|
||||
tickX = false;
|
||||
|
||||
if( tickX || tickY || gridScreenSizeDense > gridThreshold )
|
||||
{
|
||||
double radius = ( ( tickX && tickY ) ? doubleMarker : marker ) / 2.0;
|
||||
DrawRectangle( VECTOR2D( i * gridSize.x - radius + gridOrigin.x,
|
||||
j * gridSize.y - radius + gridOrigin.y ),
|
||||
VECTOR2D( i * gridSize.x + radius + gridOrigin.x,
|
||||
j * gridSize.y + radius + gridOrigin.y ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VECTOR2D GAL::GetGridPoint( const VECTOR2D& aPoint ) const
|
||||
{
|
||||
|
|
|
@ -43,7 +43,7 @@ HIDPI_GL_CANVAS::HIDPI_GL_CANVAS( wxWindow *parent,
|
|||
}
|
||||
|
||||
|
||||
wxSize HIDPI_GL_CANVAS::GetClientSize() const
|
||||
wxSize HIDPI_GL_CANVAS::GetNativePixelSize() const
|
||||
{
|
||||
wxSize size = wxGLCanvas::GetClientSize();
|
||||
|
||||
|
|
|
@ -80,24 +80,110 @@ attribute vec4 attrShaderParams;
|
|||
varying vec4 shaderParams;
|
||||
varying vec2 circleCoords;
|
||||
uniform float worldPixelSize;
|
||||
uniform vec2 screenPixelSize;
|
||||
uniform float pixelSizeMultiplier;
|
||||
uniform float minLinePixelWidth;
|
||||
|
||||
void computeLineCoords( bool posture, vec2 offset, vec2 texcoord, vec2 dir )
|
||||
|
||||
float roundr( float f, float r )
|
||||
{
|
||||
float w = length( offset );
|
||||
return floor(f / r + 0.5) * r;
|
||||
}
|
||||
|
||||
if( w > worldPixelSize )
|
||||
vec4 roundv( vec4 x, vec2 t)
|
||||
{
|
||||
return vec4( roundr(x.x, t.x), roundr(x.y, t.y), x.z, x.w );
|
||||
}
|
||||
|
||||
void computeLineCoords( bool posture, vec2 vs, vec2 vp, vec2 texcoord, vec2 dir, float lineWidth, bool endV )
|
||||
{
|
||||
float lineLength = length(vs);
|
||||
vec4 screenPos = gl_ModelViewProjectionMatrix * gl_Vertex + vec4(1, 1, 0, 0);
|
||||
float w = ((lineWidth == 0.0) ? worldPixelSize : lineWidth );
|
||||
float pixelWidth = roundr( w / worldPixelSize, 1.0 );
|
||||
float aspect = ( lineLength + w ) / w;
|
||||
vec4 color = gl_Color;
|
||||
|
||||
if( pixelWidth < 1.0 )
|
||||
pixelWidth = 1.0;
|
||||
|
||||
if ( pixelWidth > 1.0 || pixelSizeMultiplier > 1.0 )
|
||||
{
|
||||
gl_Position = gl_ModelViewProjectionMatrix * vec4( gl_Vertex.x + offset.x, gl_Vertex.y + offset.y, gl_Vertex.z, gl_Vertex.w );
|
||||
vec2 offsetNorm = (vs + vp) * pixelWidth / lineLength * 0.5;
|
||||
vec4 screenOffset = vec4( offsetNorm.x * screenPixelSize.x, -offsetNorm.y * screenPixelSize.y , 0, 0);
|
||||
vec4 adjust = vec4(-1, -1, 0, 0);
|
||||
|
||||
if( mod( pixelWidth * pixelSizeMultiplier, 2.0 ) > 0.9 )
|
||||
{
|
||||
adjust += vec4( screenPixelSize.x, screenPixelSize.y, 0, 0 ) * 0.5;
|
||||
}
|
||||
|
||||
gl_Position = roundv(screenPos, screenPixelSize) + adjust + screenOffset;
|
||||
|
||||
shaderParams[0] = SHADER_LINE_A;
|
||||
gl_TexCoord[0].st = texcoord;
|
||||
}
|
||||
else
|
||||
{
|
||||
vec4 pos = gl_Vertex;
|
||||
pos.xy += ( posture ? dir : dir.yx ) * worldPixelSize / 2.0;
|
||||
gl_Position = gl_ModelViewProjectionMatrix * pos;
|
||||
else {
|
||||
vec4 pos0 = screenPos;
|
||||
pos0.xy += ( posture ? dir.xy : dir.yx ) * screenPixelSize / 2.0;
|
||||
|
||||
if(posture)
|
||||
{
|
||||
pos0.y -= screenPixelSize.y * sign(vs.y) * 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
pos0.x += screenPixelSize.x * sign(vs.x) * 0.5;
|
||||
}
|
||||
|
||||
gl_Position = pos0 - vec4(1, 1, 0, 0);
|
||||
shaderParams[0] = SHADER_LINE_B;
|
||||
}
|
||||
|
||||
shaderParams[1] = aspect;
|
||||
|
||||
gl_TexCoord[0].st = vec2(aspect * texcoord.x, texcoord.y);
|
||||
gl_FrontColor = gl_Color;
|
||||
}
|
||||
|
||||
|
||||
void computeCircleCoords( float vertexIndex, float radius, float lineWidth )
|
||||
{
|
||||
vec4 delta;
|
||||
vec4 center = roundv(gl_ModelViewProjectionMatrix * gl_Vertex + vec4(1, 1, 0, 0), screenPixelSize);
|
||||
float pixelWidth = roundr(lineWidth / worldPixelSize, 1.0);
|
||||
float pixelR = roundr(radius / worldPixelSize, 1.0);
|
||||
//float pixelWidth = lineWidth / worldPixelSize;
|
||||
|
||||
vec4 adjust = vec4(-1, -1, 0, 0);
|
||||
|
||||
if( pixelWidth < 1.0 )
|
||||
pixelWidth = 1.0;
|
||||
|
||||
if( vertexIndex == 1.0 )
|
||||
{
|
||||
circleCoords = vec2( -sqrt( 3.0 ), -1.0 );
|
||||
delta = vec4(- pixelR * sqrt(3.0), -pixelR, 0, 0);
|
||||
}
|
||||
else if( vertexIndex == 2.0 )
|
||||
{
|
||||
circleCoords = vec2( sqrt( 3.0 ), -1.0 );
|
||||
delta = vec4( pixelR * sqrt(3.0), -pixelR, 0, 0);
|
||||
}
|
||||
else if( vertexIndex == 3.0 )
|
||||
{
|
||||
circleCoords = vec2( 0.0, 2.0 );
|
||||
delta = vec4(0, 2*pixelR, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
shaderParams[2] = pixelR;
|
||||
shaderParams[3] = pixelWidth;
|
||||
|
||||
delta.x *= screenPixelSize.x;
|
||||
delta.y *= screenPixelSize.y;
|
||||
|
||||
gl_Position = center + delta + adjust;
|
||||
gl_FrontColor = gl_Color;
|
||||
}
|
||||
|
||||
|
||||
|
@ -108,59 +194,33 @@ void main()
|
|||
// Pass attributes to the fragment shader
|
||||
shaderParams = attrShaderParams;
|
||||
|
||||
float aspect = shaderParams.y;
|
||||
float lineWidth = shaderParams.y;
|
||||
vec2 vs = shaderParams.zw;
|
||||
vec2 vp = vec2(-vs.y, vs.x);
|
||||
bool posture = abs( vs.x ) < abs(vs.y);
|
||||
|
||||
if( mode == SHADER_LINE_A )
|
||||
computeLineCoords( posture, vp - vs, vec2( -aspect, -1 ), vec2( -1, 0 ) );
|
||||
if( mode == SHADER_LINE_A )
|
||||
computeLineCoords( posture, -vs, vp, vec2( -1, -1 ), vec2( -1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_LINE_B )
|
||||
computeLineCoords( posture, -vp - vs, vec2( -aspect, 1 ), vec2( 1, 0 ) );
|
||||
computeLineCoords( posture, -vs, -vp, vec2( -1, 1 ), vec2( 1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_LINE_C )
|
||||
computeLineCoords( posture, -vp + vs, vec2( aspect, 1 ), vec2( 1, 0 ) );
|
||||
computeLineCoords( posture, vs, -vp, vec2( 1, 1 ), vec2( 1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_D )
|
||||
computeLineCoords( posture, -vp + vs, vec2( -aspect, -1 ), vec2( 1, 0 ) );
|
||||
computeLineCoords( posture, vs, -vp, vec2( -1, -1 ), vec2( 1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_E )
|
||||
computeLineCoords( posture, vp + vs, vec2( -aspect, 1 ), vec2( -1, 0 ) );
|
||||
computeLineCoords( posture, vs, vp, vec2( -1, 1 ), vec2( -1, 0 ), lineWidth, true );
|
||||
else if( mode == SHADER_LINE_F )
|
||||
computeLineCoords( posture, vp - vs, vec2( aspect, 1 ), vec2( -1, 0 ) );
|
||||
else if( mode == SHADER_STROKED_CIRCLE ||
|
||||
mode == SHADER_FILLED_CIRCLE )
|
||||
{
|
||||
// Compute relative circle coordinates basing on indices
|
||||
// Circle
|
||||
if( shaderParams[1] == 1.0 )
|
||||
circleCoords = vec2( -sqrt( 3.0 ), -1.0 );
|
||||
else if( shaderParams[1] == 2.0 )
|
||||
circleCoords = vec2( sqrt( 3.0 ), -1.0 );
|
||||
else if( shaderParams[1] == 3.0 )
|
||||
circleCoords = vec2( 0.0, 2.0 );
|
||||
|
||||
// Semicircle
|
||||
else if( shaderParams[1] == 4.0 )
|
||||
circleCoords = vec2( -3.0 / sqrt( 3.0 ), 0.0 );
|
||||
else if( shaderParams[1] == 5.0 )
|
||||
circleCoords = vec2( 3.0 / sqrt( 3.0 ), 0.0 );
|
||||
else if( shaderParams[1] == 6.0 )
|
||||
circleCoords = vec2( 0.0, 2.0 );
|
||||
|
||||
// Make the line appear to be at least 1 pixel wide
|
||||
float lineWidth = shaderParams[3];
|
||||
float worldScale = abs( gl_ModelViewMatrix[0][0] );
|
||||
|
||||
if( worldScale * lineWidth < MIN_WIDTH )
|
||||
shaderParams[3] = shaderParams[3] / ( worldScale * lineWidth );
|
||||
|
||||
gl_Position = ftransform();
|
||||
}
|
||||
computeLineCoords( posture, -vs, vp, vec2( 1, 1 ), vec2( -1, 0 ), lineWidth, false );
|
||||
else if( mode == SHADER_FILLED_CIRCLE || mode == SHADER_STROKED_CIRCLE)
|
||||
computeCircleCoords( shaderParams.y, shaderParams.z, shaderParams.w );
|
||||
else
|
||||
{
|
||||
// Pass through the coordinates like in the fixed pipeline
|
||||
gl_Position = ftransform();
|
||||
gl_FrontColor = gl_Color;
|
||||
|
||||
}
|
||||
|
||||
gl_FrontColor = gl_Color;
|
||||
}
|
||||
|
||||
)SHADER_SOURCE";
|
||||
|
|
|
@ -404,3 +404,16 @@ void OPENGL_COMPOSITOR::clean()
|
|||
|
||||
m_initialized = false;
|
||||
}
|
||||
|
||||
int OPENGL_COMPOSITOR::GetAntialiasSupersamplingFactor() const
|
||||
{
|
||||
switch( m_currentAntialiasingMode )
|
||||
{
|
||||
case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X2:
|
||||
return 2;
|
||||
case OPENGL_ANTIALIASING_MODE::SUPERSAMPLING_X4:
|
||||
return 4;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -262,7 +262,7 @@ OPENGL_GAL::OPENGL_GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions, wxWindow* aParent,
|
|||
#endif
|
||||
|
||||
SetSize( aParent->GetClientSize() );
|
||||
screenSize = VECTOR2I( aParent->GetClientSize() );
|
||||
screenSize = VECTOR2I( GetNativePixelSize() );
|
||||
|
||||
// Grid color settings are different in Cairo and OpenGL
|
||||
SetGridColor( COLOR4D( 0.8, 0.8, 0.8, 0.1 ) );
|
||||
|
@ -352,6 +352,13 @@ double OPENGL_GAL::getWorldPixelSize() const
|
|||
return std::min( std::abs( matrix.GetScale().x ), std::abs( matrix.GetScale().y ) );
|
||||
}
|
||||
|
||||
VECTOR2D OPENGL_GAL::getScreenPixelSize() const
|
||||
{
|
||||
auto sf = GetBackingScaleFactor();
|
||||
return VECTOR2D( 2.0 / (double) ( screenSize.x * sf ), 2.0 / (double) ( screenSize.y * sf ) );
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::beginDrawing()
|
||||
{
|
||||
#ifdef __WXDEBUG__
|
||||
|
@ -460,6 +467,8 @@ void OPENGL_GAL::beginDrawing()
|
|||
GLint ufm_fontTexture = shader->AddParameter( "fontTexture" );
|
||||
GLint ufm_fontTextureWidth = shader->AddParameter( "fontTextureWidth" );
|
||||
ufm_worldPixelSize = shader->AddParameter( "worldPixelSize" );
|
||||
ufm_screenPixelSize = shader->AddParameter( "screenPixelSize" );
|
||||
ufm_pixelSizeMultiplier = shader->AddParameter( "pixelSizeMultiplier" );
|
||||
|
||||
shader->Use();
|
||||
shader->SetParameter( ufm_fontTexture, (int) FONT_TEXTURE_UNIT );
|
||||
|
@ -471,7 +480,10 @@ void OPENGL_GAL::beginDrawing()
|
|||
}
|
||||
|
||||
shader->Use();
|
||||
shader->SetParameter( ufm_worldPixelSize, (float) getWorldPixelSize() );
|
||||
shader->SetParameter( ufm_worldPixelSize, (float) getWorldPixelSize() / GetBackingScaleFactor() );
|
||||
shader->SetParameter( ufm_screenPixelSize, getScreenPixelSize() );
|
||||
double pixelSizeMultiplier = compositor->GetAntialiasSupersamplingFactor();
|
||||
shader->SetParameter( ufm_pixelSizeMultiplier, (float) pixelSizeMultiplier );
|
||||
shader->Deactivate();
|
||||
|
||||
// Something betreen BeginDrawing and EndDrawing seems to depend on
|
||||
|
@ -636,24 +648,21 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
|||
* Parameters given to Shader() are indices of the triangle's vertices
|
||||
* (if you want to understand more, check the vertex shader source [shader.vert]).
|
||||
* Shader uses this coordinates to determine if fragments are inside the circle or not.
|
||||
* Does the calculations in the vertex shader now (pixel alignment)
|
||||
* v2
|
||||
* /\
|
||||
* //\\
|
||||
* v0 /_\/_\ v1
|
||||
*/
|
||||
currentManager->Shader( SHADER_FILLED_CIRCLE, 1.0 );
|
||||
currentManager->Vertex( aCenterPoint.x - aRadius * sqrt( 3.0f ), // v0
|
||||
aCenterPoint.y - aRadius, layerDepth );
|
||||
currentManager->Shader( SHADER_FILLED_CIRCLE, 1.0, aRadius );
|
||||
currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, layerDepth );
|
||||
|
||||
currentManager->Shader( SHADER_FILLED_CIRCLE, 2.0 );
|
||||
currentManager->Vertex( aCenterPoint.x + aRadius * sqrt( 3.0f), // v1
|
||||
aCenterPoint.y - aRadius, layerDepth );
|
||||
currentManager->Shader( SHADER_FILLED_CIRCLE, 2.0, aRadius );
|
||||
currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, layerDepth );
|
||||
|
||||
currentManager->Shader( SHADER_FILLED_CIRCLE, 3.0 );
|
||||
currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + aRadius * 2.0f, // v2
|
||||
layerDepth );
|
||||
currentManager->Shader( SHADER_FILLED_CIRCLE, 3.0, aRadius );
|
||||
currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, layerDepth );
|
||||
}
|
||||
|
||||
if( isStrokeEnabled )
|
||||
{
|
||||
currentManager->Reserve( 3 );
|
||||
|
@ -669,17 +678,16 @@ void OPENGL_GAL::DrawCircle( const VECTOR2D& aCenterPoint, double aRadius )
|
|||
* //\\
|
||||
* v0 /_\/_\ v1
|
||||
*/
|
||||
double outerRadius = aRadius + ( lineWidth / 2 );
|
||||
currentManager->Shader( SHADER_STROKED_CIRCLE, 1.0, aRadius, lineWidth );
|
||||
currentManager->Vertex( aCenterPoint.x - outerRadius * sqrt( 3.0f ), // v0
|
||||
aCenterPoint.y - outerRadius, layerDepth );
|
||||
currentManager->Vertex( aCenterPoint.x, // v0
|
||||
aCenterPoint.y, layerDepth );
|
||||
|
||||
currentManager->Shader( SHADER_STROKED_CIRCLE, 2.0, aRadius, lineWidth );
|
||||
currentManager->Vertex( aCenterPoint.x + outerRadius * sqrt( 3.0f ), // v1
|
||||
aCenterPoint.y - outerRadius, layerDepth );
|
||||
currentManager->Vertex( aCenterPoint.x, // v1
|
||||
aCenterPoint.y, layerDepth );
|
||||
|
||||
currentManager->Shader( SHADER_STROKED_CIRCLE, 3.0, aRadius, lineWidth );
|
||||
currentManager->Vertex( aCenterPoint.x, aCenterPoint.y + outerRadius * 2.0f, // v2
|
||||
currentManager->Vertex( aCenterPoint.x, aCenterPoint.y, // v2
|
||||
layerDepth );
|
||||
}
|
||||
}
|
||||
|
@ -751,102 +759,6 @@ void OPENGL_GAL::DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double a
|
|||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
|
||||
double aEndAngle, double aWidth )
|
||||
{
|
||||
if( aRadius <= 0 )
|
||||
{
|
||||
// Arcs of zero radius are a circle of aWidth diameter
|
||||
if( aWidth > 0 )
|
||||
DrawCircle( aCenterPoint, aWidth / 2.0 );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Swap the angles, if start angle is greater than end angle
|
||||
SWAP( aStartAngle, >, aEndAngle );
|
||||
|
||||
const double alphaIncrement = calcAngleStep( aRadius );
|
||||
|
||||
Save();
|
||||
currentManager->Translate( aCenterPoint.x, aCenterPoint.y, 0.0 );
|
||||
|
||||
if( isStrokeEnabled )
|
||||
{
|
||||
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
|
||||
|
||||
double width = aWidth / 2.0;
|
||||
VECTOR2D startPoint( cos( aStartAngle ) * aRadius,
|
||||
sin( aStartAngle ) * aRadius );
|
||||
VECTOR2D endPoint( cos( aEndAngle ) * aRadius,
|
||||
sin( aEndAngle ) * aRadius );
|
||||
|
||||
drawStrokedSemiCircle( startPoint, width, aStartAngle + M_PI );
|
||||
drawStrokedSemiCircle( endPoint, width, aEndAngle );
|
||||
|
||||
VECTOR2D pOuter( cos( aStartAngle ) * ( aRadius + width ),
|
||||
sin( aStartAngle ) * ( aRadius + width ) );
|
||||
|
||||
VECTOR2D pInner( cos( aStartAngle ) * ( aRadius - width ),
|
||||
sin( aStartAngle ) * ( aRadius - width ) );
|
||||
|
||||
double alpha;
|
||||
|
||||
for( alpha = aStartAngle + alphaIncrement; alpha <= aEndAngle; alpha += alphaIncrement )
|
||||
{
|
||||
VECTOR2D pNextOuter( cos( alpha ) * ( aRadius + width ),
|
||||
sin( alpha ) * ( aRadius + width ) );
|
||||
VECTOR2D pNextInner( cos( alpha ) * ( aRadius - width ),
|
||||
sin( alpha ) * ( aRadius - width ) );
|
||||
|
||||
DrawLine( pOuter, pNextOuter );
|
||||
DrawLine( pInner, pNextInner );
|
||||
|
||||
pOuter = pNextOuter;
|
||||
pInner = pNextInner;
|
||||
}
|
||||
|
||||
// Draw the last missing part
|
||||
if( alpha != aEndAngle )
|
||||
{
|
||||
VECTOR2D pLastOuter( cos( aEndAngle ) * ( aRadius + width ),
|
||||
sin( aEndAngle ) * ( aRadius + width ) );
|
||||
VECTOR2D pLastInner( cos( aEndAngle ) * ( aRadius - width ),
|
||||
sin( aEndAngle ) * ( aRadius - width ) );
|
||||
|
||||
DrawLine( pOuter, pLastOuter );
|
||||
DrawLine( pInner, pLastInner );
|
||||
}
|
||||
}
|
||||
|
||||
if( isFillEnabled )
|
||||
{
|
||||
currentManager->Color( fillColor.r, fillColor.g, fillColor.b, fillColor.a );
|
||||
SetLineWidth( aWidth );
|
||||
|
||||
VECTOR2D p( cos( aStartAngle ) * aRadius, sin( aStartAngle ) * aRadius );
|
||||
double alpha;
|
||||
|
||||
for( alpha = aStartAngle + alphaIncrement; alpha <= aEndAngle; alpha += alphaIncrement )
|
||||
{
|
||||
VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
|
||||
DrawLine( p, p_next );
|
||||
|
||||
p = p_next;
|
||||
}
|
||||
|
||||
// Draw the last missing part
|
||||
if( alpha != aEndAngle )
|
||||
{
|
||||
VECTOR2D p_last( cos( aEndAngle ) * aRadius, sin( aEndAngle ) * aRadius );
|
||||
DrawLine( p, p_last );
|
||||
}
|
||||
}
|
||||
|
||||
Restore();
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint )
|
||||
{
|
||||
// Compute the diagonal points of the rectangle
|
||||
|
@ -1632,43 +1544,27 @@ void OPENGL_GAL::drawLineQuad( const VECTOR2D& aStartPoint, const VECTOR2D& aEnd
|
|||
auto v1 = currentManager->GetTransformation() * glm::vec4( aStartPoint.x, aStartPoint.y, 0.0, 0.0 );
|
||||
auto v2 = currentManager->GetTransformation() * glm::vec4( aEndPoint.x, aEndPoint.y, 0.0, 0.0 );
|
||||
|
||||
VECTOR2D startEndVector( v2.x - v1.x, v2.y - v1.y );
|
||||
|
||||
double lineLength = startEndVector.EuclideanNorm();
|
||||
|
||||
VECTOR2D vs ( startEndVector );
|
||||
float aspect;
|
||||
|
||||
if ( lineWidth == 0.0 ) // pixel-width line
|
||||
{
|
||||
vs = vs.Resize( 0.5 );
|
||||
aspect = ( lineLength + 1.0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
vs = vs.Resize( 0.5 * lineWidth );
|
||||
aspect = ( lineLength + lineWidth ) / lineWidth;
|
||||
}
|
||||
VECTOR2D vs( v2.x - v1.x, v2.y - v1.y );
|
||||
|
||||
currentManager->Reserve( 6 );
|
||||
|
||||
// Line width is maintained by the vertex shader
|
||||
currentManager->Shader( SHADER_LINE_A, aspect, vs.x, vs.y );
|
||||
currentManager->Shader( SHADER_LINE_A, lineWidth, vs.x, vs.y );
|
||||
currentManager->Vertex( aStartPoint, layerDepth );
|
||||
|
||||
currentManager->Shader( SHADER_LINE_B, aspect, vs.x, vs.y );
|
||||
currentManager->Shader( SHADER_LINE_B, lineWidth, vs.x, vs.y );
|
||||
currentManager->Vertex( aStartPoint, layerDepth );
|
||||
|
||||
currentManager->Shader( SHADER_LINE_C, aspect, vs.x, vs.y );
|
||||
currentManager->Shader( SHADER_LINE_C, lineWidth, vs.x, vs.y );
|
||||
currentManager->Vertex( aEndPoint, layerDepth );
|
||||
|
||||
currentManager->Shader( SHADER_LINE_D, aspect, vs.x, vs.y );
|
||||
currentManager->Shader( SHADER_LINE_D, lineWidth, vs.x, vs.y );
|
||||
currentManager->Vertex( aEndPoint, layerDepth );
|
||||
|
||||
currentManager->Shader( SHADER_LINE_E, aspect, vs.x, vs.y );
|
||||
currentManager->Shader( SHADER_LINE_E, lineWidth, vs.x, vs.y );
|
||||
currentManager->Vertex( aEndPoint, layerDepth );
|
||||
|
||||
currentManager->Shader( SHADER_LINE_F, aspect, vs.x, vs.y );
|
||||
currentManager->Shader( SHADER_LINE_F, lineWidth, vs.x, vs.y );
|
||||
currentManager->Vertex( aStartPoint, layerDepth );
|
||||
}
|
||||
|
||||
|
@ -2124,3 +2020,21 @@ void OPENGL_GAL::EnableDepthTest( bool aEnabled )
|
|||
nonCachedManager->EnableDepthTest( aEnabled );
|
||||
overlayManager->EnableDepthTest( aEnabled );
|
||||
}
|
||||
|
||||
|
||||
static double roundr( double f, double r )
|
||||
{
|
||||
return floor(f / r + 0.5) * r;
|
||||
}
|
||||
|
||||
|
||||
void OPENGL_GAL::ComputeWorldScreenMatrix()
|
||||
{
|
||||
auto pixelSize = worldScale;
|
||||
|
||||
lookAtPoint.x = roundr( lookAtPoint.x, pixelSize );
|
||||
lookAtPoint.y = roundr( lookAtPoint.y, pixelSize );
|
||||
|
||||
GAL::ComputeWorldScreenMatrix();
|
||||
}
|
||||
|
||||
|
|
|
@ -157,6 +157,12 @@ void SHADER::SetParameter( int parameterNumber, float f0, float f1, float f2, fl
|
|||
glUniform4fv( parameterLocation[parameterNumber], 1, arr );
|
||||
}
|
||||
|
||||
void SHADER::SetParameter( int aParameterNumber, const VECTOR2D& aValue ) const
|
||||
{
|
||||
assert( (unsigned)aParameterNumber < parameterLocation.size() );
|
||||
glUniform2f( parameterLocation[aParameterNumber], aValue.x, aValue.y );
|
||||
}
|
||||
|
||||
|
||||
int SHADER::GetAttribute( const std::string& aAttributeName ) const
|
||||
{
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <gr_basic.h>
|
||||
#include <eda_rect.h>
|
||||
|
||||
#include <class_drawpanel.h>
|
||||
#include <legacy_gal/class_drawpanel.h>
|
||||
|
||||
|
||||
namespace KIGFX
|
||||
|
|
|
@ -322,7 +322,7 @@ void GERBVIEW_PAINTER::draw( /*const*/ GERBER_DRAW_ITEM* aItem, int aLayer )
|
|||
endAngle = 2 * M_PI;
|
||||
}
|
||||
|
||||
m_gal->DrawArcSegment( center, radius, startAngle, endAngle, width );
|
||||
m_gal->DrawArc( center, radius, startAngle, endAngle );
|
||||
|
||||
// Arc Debugging
|
||||
// m_gal->SetLineWidth( 5 );
|
||||
|
|
|
@ -91,10 +91,6 @@ public:
|
|||
virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
|
||||
double aStartAngle, double aEndAngle ) override;
|
||||
|
||||
/// @copydoc GAL::DrawArcSegment()
|
||||
virtual void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
|
||||
double aStartAngle, double aEndAngle, double aWidth ) override;
|
||||
|
||||
/// @copydoc GAL::DrawRectangle()
|
||||
virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;
|
||||
|
||||
|
@ -214,7 +210,15 @@ public:
|
|||
|
||||
virtual void EnableDepthTest( bool aEnabled = false ) override;
|
||||
|
||||
///> @copydoc GAL::DrawGrid()
|
||||
virtual void DrawGrid() override;
|
||||
|
||||
|
||||
protected:
|
||||
const double xform( double x );
|
||||
const VECTOR2D xform( double x, double y );
|
||||
const VECTOR2D xform( const VECTOR2D& aP );
|
||||
|
||||
/// @copydoc GAL::BeginDrawing()
|
||||
virtual void beginDrawing() override;
|
||||
|
||||
|
@ -224,6 +228,7 @@ protected:
|
|||
void resetContext();
|
||||
|
||||
virtual void drawGridLine( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;
|
||||
virtual void drawGridPoint( const VECTOR2D& aPoint, double aSize );
|
||||
|
||||
/// Super class definition
|
||||
typedef GAL super;
|
||||
|
@ -270,11 +275,20 @@ protected:
|
|||
unsigned int groupCounter; ///< Counter used for generating keys for groups
|
||||
GROUP* currentGroup; ///< Currently used group
|
||||
|
||||
double lineWidth;
|
||||
double linePixelWidth;
|
||||
double lineWidthInPixels;
|
||||
bool lineWidthIsOdd;
|
||||
|
||||
cairo_matrix_t cairoWorldScreenMatrix; ///< Cairo world to screen transformation matrix
|
||||
cairo_matrix_t currentXform;
|
||||
cairo_matrix_t currentWorld2Screen;
|
||||
cairo_t* currentContext; ///< Currently used Cairo context for drawing
|
||||
cairo_t* context; ///< Cairo image
|
||||
cairo_surface_t* surface; ///< Cairo surface
|
||||
|
||||
std::vector<cairo_matrix_t> xformStack;
|
||||
|
||||
void flushPath();
|
||||
void storePath(); ///< Store the actual path
|
||||
|
||||
|
@ -295,6 +309,11 @@ protected:
|
|||
*/
|
||||
unsigned int getNewGroupNumber();
|
||||
|
||||
void syncLineWidth( bool aForceWidth = false, double aWidth = 0.0);
|
||||
void updateWorldScreenMatrix();
|
||||
const VECTOR2D roundp( const VECTOR2D& v );
|
||||
|
||||
|
||||
/// Format used to store pixels
|
||||
static constexpr cairo_format_t GAL_FORMAT = CAIRO_FORMAT_RGB24;
|
||||
};
|
||||
|
|
|
@ -134,24 +134,6 @@ public:
|
|||
virtual void
|
||||
DrawArc( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle, double aEndAngle ) {};
|
||||
|
||||
/**
|
||||
* @brief Draw an arc segment.
|
||||
*
|
||||
* This method differs from DrawArc() in what happens when fill/stroke are on or off.
|
||||
* DrawArc() draws a "pie piece" when fill is turned on, and a thick stroke when fill is off.
|
||||
* DrawArcSegment() with fill *on* behaves like DrawArc() with fill *off*.
|
||||
* DrawArcSegment() with fill *off* draws the outline of what it would have drawn with fill on.
|
||||
*
|
||||
* @param aCenterPoint is the center point of the arc.
|
||||
* @param aRadius is the arc radius.
|
||||
* @param aStartAngle is the start angle of the arc.
|
||||
* @param aEndAngle is the end angle of the arc.
|
||||
* @param aWidth is the thickness of the arc (pen size).
|
||||
*/
|
||||
virtual void
|
||||
DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius, double aStartAngle,
|
||||
double aEndAngle, double aWidth ) {};
|
||||
|
||||
/**
|
||||
* @brief Draw a rectangle.
|
||||
*
|
||||
|
@ -944,7 +926,7 @@ public:
|
|||
}
|
||||
|
||||
///> @brief Draw the grid
|
||||
virtual void DrawGrid();
|
||||
virtual void DrawGrid() {};
|
||||
|
||||
/**
|
||||
* Function GetGridPoint()
|
||||
|
|
|
@ -51,10 +51,7 @@ public:
|
|||
const wxPalette& palette = wxNullPalette );
|
||||
|
||||
|
||||
// wxGLCanvas override
|
||||
virtual wxSize GetClientSize() const;
|
||||
|
||||
// wxGLCanvas override (with patch applied) or default value of 1.0
|
||||
virtual wxSize GetNativePixelSize() const;
|
||||
virtual float GetBackingScaleFactor() const;
|
||||
};
|
||||
|
||||
|
|
|
@ -91,6 +91,8 @@ public:
|
|||
void SetAntialiasingMode( OPENGL_ANTIALIASING_MODE aMode ); // clears all buffers
|
||||
OPENGL_ANTIALIASING_MODE GetAntialiasingMode() const;
|
||||
|
||||
int GetAntialiasSupersamplingFactor() const;
|
||||
|
||||
protected:
|
||||
// Buffers are simply textures storing a result of certain target rendering.
|
||||
typedef struct
|
||||
|
|
|
@ -119,10 +119,6 @@ public:
|
|||
virtual void DrawArc( const VECTOR2D& aCenterPoint, double aRadius,
|
||||
double aStartAngle, double aEndAngle ) override;
|
||||
|
||||
/// @copydoc GAL::DrawArcSegment()
|
||||
virtual void DrawArcSegment( const VECTOR2D& aCenterPoint, double aRadius,
|
||||
double aStartAngle, double aEndAngle, double aWidth ) override;
|
||||
|
||||
/// @copydoc GAL::DrawRectangle()
|
||||
virtual void DrawRectangle( const VECTOR2D& aStartPoint, const VECTOR2D& aEndPoint ) override;
|
||||
|
||||
|
@ -236,6 +232,8 @@ public:
|
|||
/// @copydoc GAL::SetNegativeDrawMode()
|
||||
virtual void SetNegativeDrawMode( bool aSetting ) override {}
|
||||
|
||||
virtual void ComputeWorldScreenMatrix() override;
|
||||
|
||||
// -------
|
||||
// Cursor
|
||||
// -------
|
||||
|
@ -322,6 +320,9 @@ private:
|
|||
bool isContextLocked; ///< Used for assertion checking
|
||||
int lockClientCookie;
|
||||
GLint ufm_worldPixelSize;
|
||||
GLint ufm_screenPixelSize;
|
||||
GLint ufm_pixelSizeMultiplier;
|
||||
GLint ufm_backingScaleFactor;
|
||||
|
||||
std::unique_ptr<GL_BITMAP_CACHE> bitmapCache;
|
||||
|
||||
|
@ -477,6 +478,9 @@ private:
|
|||
|
||||
double getWorldPixelSize() const;
|
||||
|
||||
VECTOR2D getScreenPixelSize() const;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Basic OpenGL initialization.
|
||||
*/
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include <math/vector2d.h>
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
|
||||
|
@ -182,6 +184,7 @@ public:
|
|||
*/
|
||||
void SetParameter( int aParameterNumber, float aValue ) const;
|
||||
void SetParameter( int aParameterNumber, int aValue ) const;
|
||||
void SetParameter( int aParameterNumber, const VECTOR2D& aValue ) const;
|
||||
void SetParameter( int aParameterNumber, float f0, float f1, float f2, float f3 ) const;
|
||||
|
||||
/**
|
||||
|
|
|
@ -937,10 +937,13 @@ void PCB_PAINTER::draw( const DRAWSEGMENT* aSegment, int aLayer )
|
|||
break;
|
||||
|
||||
case S_ARC:
|
||||
m_gal->DrawArcSegment( start, aSegment->GetRadius(),
|
||||
|
||||
m_gal->SetLineWidth( thickness );
|
||||
m_gal->SetIsFill( false );
|
||||
m_gal->SetIsStroke( true );
|
||||
m_gal->DrawArc( start, aSegment->GetRadius(),
|
||||
DECIDEG2RAD( aSegment->GetArcAngleStart() ),
|
||||
DECIDEG2RAD( aSegment->GetArcAngleStart() + aSegment->GetAngle() ),
|
||||
thickness );
|
||||
DECIDEG2RAD( aSegment->GetArcAngleStart() + aSegment->GetAngle() ) );
|
||||
break;
|
||||
|
||||
case S_CIRCLE:
|
||||
|
|
|
@ -27,3 +27,4 @@ add_subdirectory( common_tools )
|
|||
add_subdirectory( pcbnew_tools )
|
||||
|
||||
# add_subdirectory( pcb_test_window )
|
||||
add_subdirectory( gal/gal_pixel_alignment )
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
|
||||
#
|
||||
# This program source code file is part of KiCad, a free EDA CAD application.
|
||||
#
|
||||
# Copyright (C) 2017 CERN
|
||||
# @author Alejandro García Montoro <alejandro.garciamontoro@gmail.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
# as published by the Free Software Foundation; either version 2
|
||||
# of the License, or (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, you may find one here:
|
||||
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
||||
# or you may search the http://www.gnu.org website for the version 2 license,
|
||||
# or you may write to the Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
|
||||
find_package(Boost COMPONENTS unit_test_framework REQUIRED)
|
||||
find_package( wxWidgets 3.0.0 COMPONENTS gl aui adv html core net base xml stc REQUIRED )
|
||||
|
||||
add_definitions(-DBOOST_TEST_DYN_LINK -DPCBNEW -DUSE_TOOL_MANAGER)
|
||||
|
||||
if( BUILD_GITHUB_PLUGIN )
|
||||
set( GITHUB_PLUGIN_LIBRARIES github_plugin )
|
||||
endif()
|
||||
|
||||
add_dependencies( pnsrouter pcbcommon pcad2kicadpcb ${GITHUB_PLUGIN_LIBRARIES} )
|
||||
|
||||
add_executable(test_gal_pixel_alignment WIN32
|
||||
test_gal_pixel_alignment.cpp
|
||||
../../qa_utils/pcb_test_frame.cpp
|
||||
../../qa_utils/mocks.cpp
|
||||
../../../common/base_units.cpp
|
||||
../../../pcbnew/tools/pcb_tool.cpp
|
||||
../../../pcbnew/tools/selection.cpp
|
||||
../../../pcbnew/tools/selection_tool.cpp
|
||||
../../../pcbnew/tools/tool_event_utils.cpp
|
||||
#../../pcbnew/tools/outline_editor.cpp
|
||||
)
|
||||
|
||||
include_directories( BEFORE ${INC_BEFORE} )
|
||||
include_directories(
|
||||
${CMAKE_SOURCE_DIR}
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_SOURCE_DIR}/3d-viewer
|
||||
${CMAKE_SOURCE_DIR}/common
|
||||
${CMAKE_SOURCE_DIR}/pcbnew
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/router
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/tools
|
||||
${CMAKE_SOURCE_DIR}/pcbnew/dialogs
|
||||
${CMAKE_SOURCE_DIR}/polygon
|
||||
${CMAKE_SOURCE_DIR}/common/geometry
|
||||
${CMAKE_SOURCE_DIR}/qa/qa_utils
|
||||
${Boost_INCLUDE_DIR}
|
||||
${INC_AFTER}
|
||||
)
|
||||
|
||||
target_link_libraries( test_gal_pixel_alignment
|
||||
polygon
|
||||
pnsrouter
|
||||
common
|
||||
pcbcommon
|
||||
bitmaps
|
||||
polygon
|
||||
pnsrouter
|
||||
common
|
||||
pcbcommon
|
||||
bitmaps
|
||||
polygon
|
||||
pnsrouter
|
||||
common
|
||||
pcbcommon
|
||||
legacy_gal
|
||||
bitmaps
|
||||
polygon
|
||||
pnsrouter
|
||||
common
|
||||
pcbcommon
|
||||
3d-viewer
|
||||
bitmaps
|
||||
gal
|
||||
pcad2kicadpcb
|
||||
common
|
||||
pcbcommon
|
||||
legacy_gal
|
||||
${GITHUB_PLUGIN_LIBRARIES}
|
||||
common
|
||||
pcbcommon
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
|
||||
${wxWidgets_LIBRARIES}
|
||||
)
|
|
@ -0,0 +1,231 @@
|
|||
#include <pcb_test_frame.h>
|
||||
#include <tool/tool_manager.h>
|
||||
|
||||
#include <gal/graphics_abstraction_layer.h>
|
||||
#include <view/view.h>
|
||||
#include <view/view_item.h>
|
||||
#include <pcb_draw_panel_gal.h>
|
||||
|
||||
#include <layers_id_colors_and_visibility.h>
|
||||
|
||||
const VECTOR2D xform2( const MATRIX3x3D& minv, const VECTOR2D& p )
|
||||
{
|
||||
auto t = minv * p;
|
||||
return VECTOR2D((float)t.x, (float)t.y);
|
||||
}
|
||||
|
||||
void screenSpaceLine( KIGFX::GAL* gal, const VECTOR2D& p0, const VECTOR2D& p1, double w )
|
||||
{
|
||||
auto minv = gal->GetScreenWorldMatrix();
|
||||
|
||||
auto pa = xform2 ( minv, p0 );
|
||||
auto pb = xform2 ( minv, p1 );
|
||||
|
||||
#if 0
|
||||
//shader->Deactivate();
|
||||
|
||||
currentManager->Reserve( 6 );
|
||||
currentManager->Shader( SHADER_NONE );
|
||||
currentManager->Color( strokeColor.r, strokeColor.g, strokeColor.b, strokeColor.a );
|
||||
|
||||
currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pa.x, pa.y, layerDepth );
|
||||
currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pb.x, pb.y, layerDepth );
|
||||
currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pc.x, pc.y, layerDepth );
|
||||
currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pa.x, pa.y, layerDepth );
|
||||
currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pc.x, pc.y, layerDepth );
|
||||
currentManager->Shader( SHADER_NONE ); currentManager->Vertex( pd.x, pd.y, layerDepth );
|
||||
shader->Use();
|
||||
#endif
|
||||
|
||||
gal->SetLineWidth( w * minv.GetScale().x );
|
||||
gal->DrawLine( pa, pb );
|
||||
|
||||
|
||||
}
|
||||
|
||||
void screenSpaceCircle( KIGFX::GAL* gal, const VECTOR2D& p0, double r, double w )
|
||||
{
|
||||
auto minv = gal->GetScreenWorldMatrix();
|
||||
|
||||
auto pa = xform2 ( minv, p0 );
|
||||
|
||||
gal->SetLineWidth( w * minv.GetScale().x );
|
||||
gal->DrawCircle( pa, r * minv.GetScale().x );
|
||||
|
||||
}
|
||||
|
||||
|
||||
class MY_DRAWING : public EDA_ITEM
|
||||
{
|
||||
public:
|
||||
MY_DRAWING() : EDA_ITEM( NOT_USED ) {};
|
||||
virtual ~MY_DRAWING(){};
|
||||
|
||||
wxString GetClass() const override
|
||||
{
|
||||
return wxT( "MyDrawing" );
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
virtual void Show( int nestLevel, std::ostream& os ) const override {}
|
||||
#endif
|
||||
|
||||
const BOX2I ViewBBox() const override
|
||||
{
|
||||
BOX2I bb;
|
||||
bb.SetMaximum();
|
||||
return bb;
|
||||
}
|
||||
|
||||
virtual void ViewDraw( int aLayer, KIGFX::VIEW* aView ) const override
|
||||
{
|
||||
auto gal = aView->GetGAL();
|
||||
int i;
|
||||
gal->SetTarget( KIGFX::TARGET_NONCACHED );
|
||||
gal->SetIsStroke( true );
|
||||
gal->SetStrokeColor( COLOR4D::WHITE );
|
||||
|
||||
/* for(i=0;i < 100; i++)
|
||||
{
|
||||
gal->SetLineWidth( 10000 );
|
||||
gal->DrawLine( VECTOR2I(0, i * 30000), VECTOR2I(1000000, i * 30000) );
|
||||
gal->DrawLine( VECTOR2I(- 2000000 + i * 30000, 0), VECTOR2I(- 2000000 + i * 30000, 1000000) );
|
||||
}
|
||||
|
||||
for( float alpha = 0.0; alpha <= 360.0; alpha += 6.0)
|
||||
{
|
||||
float ca = cos(alpha * M_PI / 180.0);
|
||||
float sa = sin(alpha * M_PI / 180.0);
|
||||
VECTOR2I p0(2000000, 0);
|
||||
float r = 800000.0;
|
||||
gal->DrawLine( p0, p0 + VECTOR2I( r*ca, r*sa));
|
||||
}
|
||||
*/
|
||||
|
||||
int k = 0;
|
||||
double w = 0.0;
|
||||
//gal->Rotate( 1.0 / 3.0 * M_PI );
|
||||
for(int step = 10; step < 80; step += 11, k+=100)
|
||||
{
|
||||
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
/*auto p0 = VECTOR2D( k + 100, 100 + i * step );
|
||||
auto p1 = VECTOR2D( k + 100 + step/2, 100 + i * step );
|
||||
auto p2 = VECTOR2D( k + 100 + step/2, 100 + i * step + step/2 );
|
||||
auto p3 = VECTOR2D( k + 100, 100 + i * step + step/2 );
|
||||
auto p4 = VECTOR2D( k + 100, 100 + i * step + step );*/
|
||||
|
||||
auto p0 = VECTOR2D( k + 100, 100 + i * step );
|
||||
auto p1 = VECTOR2D( k + 100 + step/2, 100 + i * step );
|
||||
auto p2 = VECTOR2D( k + 100 + step/2, 100 + i * step + step/2 );
|
||||
auto p3 = VECTOR2D( k + 100, 100 + i * step + step/2 );
|
||||
auto p4 = VECTOR2D( k + 100, 100 + i * step + step );
|
||||
|
||||
|
||||
screenSpaceLine( gal, p0, p1 , w);
|
||||
screenSpaceLine( gal, p3, p2 , w);
|
||||
|
||||
p0 += VECTOR2D(50, 0);
|
||||
p1 += VECTOR2D(50, 0);
|
||||
p2 += VECTOR2D(50, 0);
|
||||
p3 += VECTOR2D(50, 0);
|
||||
|
||||
screenSpaceLine( gal, p0, p3 , w);
|
||||
screenSpaceLine( gal, p1, p2 , w);
|
||||
|
||||
|
||||
/* screenSpaceLine( gal, p1, p2 , w);
|
||||
screenSpaceLine( gal, p2, p3 , w);
|
||||
screenSpaceLine( gal, p3, p4 , w);
|
||||
|
||||
std::swap(p0.x, p0.y );
|
||||
std::swap(p1.x, p1.y );
|
||||
std::swap(p2.x, p2.y );
|
||||
std::swap(p3.x, p3.y );
|
||||
std::swap(p4.x, p4.y );
|
||||
|
||||
screenSpaceLine( gal, p0, p1 , w);
|
||||
screenSpaceLine( gal, p1, p2 , w);
|
||||
screenSpaceLine( gal, p2, p3 , w);
|
||||
screenSpaceLine( gal, p3, p4 , w);*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
for(i=0;i < 1000; i++)
|
||||
{
|
||||
int k = 0;
|
||||
|
||||
for(double w=1.0; w<=8.0; w+=1.0, k += 50)
|
||||
{
|
||||
//screenSpaceLine( gal, VECTOR2D( k, i*step ), VECTOR2D( k, i*step ) + VECTOR2D( 50, 0 ), w );
|
||||
//screenSpaceLine( gal, VECTOR2D( i*step, k ), VECTOR2D( i*step, k ) + VECTOR2D( 0, 50 ), w );
|
||||
}
|
||||
|
||||
|
||||
//gal->ScreenSpaceQuad( VECTOR2D( 250, 100 + i*8 ), VECTOR2D( 100, 2 ) );
|
||||
//gal->ScreenSpaceQuad( VECTOR2D( 400, 100 + i*4 + 0.5 ), VECTOR2D( 100, 1 ) );
|
||||
//gal->ScreenSpaceQuad( VECTOR2D( 550, 100 + i*8 + 0.5 ), VECTOR2D( 100, 2 ) );
|
||||
|
||||
}*/
|
||||
|
||||
for(int i = 1; i < 16; i+=1)
|
||||
{
|
||||
for(int j = 1; j < 16; j+=1)
|
||||
{
|
||||
gal->SetIsStroke( true );
|
||||
gal->SetIsFill( false );
|
||||
//screenSpaceCircle(gal, VECTOR2D(100 + i * 25, 100 + j * 25), (float)i/2.0, 1);
|
||||
gal->SetIsStroke( false );
|
||||
gal->SetIsFill( true );
|
||||
//screenSpaceCircle(gal, VECTOR2D(100 + i * 25, 500 + 100 + j * 25), (float)i/2.0, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ViewGetLayers( int aLayers[], int& aCount ) const override
|
||||
{
|
||||
aLayers[0] = LAYER_GP_OVERLAY;
|
||||
aCount = 1;
|
||||
}
|
||||
};
|
||||
|
||||
class MY_PCB_TEST_FRAME : public PCB_TEST_FRAME
|
||||
{
|
||||
public:
|
||||
MY_PCB_TEST_FRAME( wxFrame* frame, const wxString& title,
|
||||
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
|
||||
long style = wxDEFAULT_FRAME_STYLE )
|
||||
: PCB_TEST_FRAME( frame, title, pos, size, style, PCB_DRAW_PANEL_GAL::GAL_TYPE_OPENGL )
|
||||
{
|
||||
registerTools();
|
||||
m_galPanel->GetView()->Add( new MY_DRAWING );
|
||||
m_galPanel->GetView()->SetScale( 41.3526000000, VECTOR2D( 837362.6373626292, 1581684.9816849837 ) );
|
||||
|
||||
}
|
||||
|
||||
void registerTools();
|
||||
|
||||
virtual ~MY_PCB_TEST_FRAME()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
wxFrame* CreateMainFrame( const std::string& aFileName )
|
||||
{
|
||||
auto frame = new MY_PCB_TEST_FRAME( nullptr, wxT( "Test PCB Frame" ) );
|
||||
|
||||
if( aFileName != "" )
|
||||
{
|
||||
frame->LoadAndDisplayBoard( aFileName );
|
||||
}
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
void MY_PCB_TEST_FRAME::registerTools()
|
||||
{
|
||||
m_toolManager->InitTools();
|
||||
m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
|
||||
}
|
|
@ -263,6 +263,9 @@ MODULE* PCB_BASE_FRAME::GetFootprintFromBoardByReference()
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::hideLocalRatsnest( "pcbnew.Control.hideLocalRatsnest",
|
||||
AS_GLOBAL, 0,
|
||||
"", "" );
|
||||
|
||||
TOOL_ACTION PCB_ACTIONS::selectionModified( "pcbnew.InteractiveEdit.ModifiedSelection",
|
||||
AS_GLOBAL, 0,
|
||||
|
@ -356,3 +359,23 @@ void PCB_SCREEN::ClearUndoORRedoList( UNDO_REDO_CONTAINER& aList, int aItemCount
|
|||
void ROUTER_TOOL::NeighboringSegmentFilter( const VECTOR2I&, GENERAL_COLLECTOR& )
|
||||
{
|
||||
}
|
||||
|
||||
EDA_DRAW_FRAME* EDA_DRAW_PANEL::GetParent() const
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* EDA_DRAW_PANEL::GetDisplayOptions()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BASE_SCREEN* EDA_DRAW_PANEL::GetScreen()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void DrawAndSizingBlockOutlines(EDA_DRAW_PANEL*, wxDC*, wxPoint const&, bool)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -129,10 +129,12 @@ void PCB_TEST_FRAME::SetBoard( BOARD* b )
|
|||
m_board.reset( b );
|
||||
m_board->GetConnectivity()->Build( m_board.get() );
|
||||
m_galPanel->DisplayBoard( m_board.get() );
|
||||
#ifdef USE_TOOL_MANAGER
|
||||
m_toolManager->SetEnvironment( m_board.get(), m_galPanel->GetView(),
|
||||
m_galPanel->GetViewControls(), nullptr );
|
||||
|
||||
m_toolManager->ResetTools( TOOL_BASE::MODEL_RELOAD );
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -161,7 +163,7 @@ BOARD* PCB_TEST_FRAME::LoadAndDisplayBoard( const std::string& filename )
|
|||
|
||||
|
||||
PCB_TEST_FRAME::PCB_TEST_FRAME( wxFrame* frame, const wxString& title, const wxPoint& pos,
|
||||
const wxSize& size, long style ) :
|
||||
const wxSize& size, long style, PCB_DRAW_PANEL_GAL::GAL_TYPE aGalType ) :
|
||||
wxFrame( frame, wxID_ANY, title, pos, size, style )
|
||||
{
|
||||
// Make a menubar
|
||||
|
@ -180,8 +182,10 @@ PCB_TEST_FRAME::PCB_TEST_FRAME( wxFrame* frame, const wxString& title, const wxP
|
|||
|
||||
KIGFX::GAL_DISPLAY_OPTIONS options;
|
||||
|
||||
options.gl_antialiasing_mode = KIGFX::OPENGL_ANTIALIASING_MODE::NONE; //SUPERSAMPLING_X4;
|
||||
|
||||
m_galPanel.reset( new PCB_DRAW_PANEL_GAL( this, -1, wxPoint( 0,
|
||||
0 ), wxDefaultSize, options, EDA_DRAW_PANEL_GAL::GAL_TYPE_CAIRO ) );
|
||||
0 ), wxDefaultSize, options, aGalType ) );
|
||||
|
||||
m_galPanel->SetEvtHandlerEnabled( true );
|
||||
m_galPanel->SetFocus();
|
||||
|
@ -200,6 +204,7 @@ PCB_TEST_FRAME::PCB_TEST_FRAME( wxFrame* frame, const wxString& title, const wxP
|
|||
|
||||
m_galPanel->GetViewControls()->ShowCursor( true );
|
||||
|
||||
#ifdef USE_TOOL_MANAGER
|
||||
m_toolManager.reset( new TOOL_MANAGER );
|
||||
m_toolManager->SetEnvironment( m_board.get(), m_galPanel->GetView(),
|
||||
m_galPanel->GetViewControls(), nullptr );
|
||||
|
@ -212,6 +217,7 @@ PCB_TEST_FRAME::PCB_TEST_FRAME( wxFrame* frame, const wxString& title, const wxP
|
|||
m_toolManager->InitTools();
|
||||
m_galPanel->SetEventDispatcher( m_toolDispatcher.get() );
|
||||
m_toolManager->InvokeTool( "pcbnew.InteractiveSelection" );
|
||||
#endif
|
||||
|
||||
SetBoard( new BOARD );
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#include <memory>
|
||||
|
||||
#include <pcb_draw_panel_gal.h>
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
class PCB_DRAW_PANEL_GAL;
|
||||
|
@ -64,7 +66,8 @@ public:
|
|||
const wxString& title,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize,
|
||||
long style = wxDEFAULT_FRAME_STYLE);
|
||||
long style = wxDEFAULT_FRAME_STYLE,
|
||||
PCB_DRAW_PANEL_GAL::GAL_TYPE aGalType = PCB_DRAW_PANEL_GAL::GAL_TYPE_OPENGL );
|
||||
|
||||
virtual ~PCB_TEST_FRAME();
|
||||
|
||||
|
@ -81,9 +84,11 @@ protected:
|
|||
|
||||
unique_ptr < PCB_DRAW_PANEL_GAL > m_galPanel;
|
||||
unique_ptr < BOARD > m_board;
|
||||
#ifdef USE_TOOL_MANAGER
|
||||
unique_ptr < TOOL_MANAGER > m_toolManager;
|
||||
unique_ptr < TOOL_DISPATCHER > m_toolDispatcher;
|
||||
unique_ptr < ACTIONS > m_pcbActions;
|
||||
#endif
|
||||
};
|
||||
|
||||
wxFrame* CreateMainFrame( const std::string& aFileName );
|
||||
|
|
Loading…
Reference in New Issue