59using namespace std::placeholders;
67#include <glsl_kicad_frag.h>
68#include <glsl_kicad_vert.h>
80constexpr GLuint STENCIL_DOTS_MARKER = 0x01;
82constexpr GLuint STENCIL_GRID_COVERAGE = 0x80;
89 wxGLAttributes attribs;
90 attribs.RGBA().DoubleBuffer().Depth( 8 ).EndList();
139 glDeleteTextures( 1, &bitmap.second.id );
145#ifndef DISABLE_BITMAP_CACHE
151 if( glIsTexture( it->second.id ) )
153 it->second.accessTime = wxGetUTCTimeMillis().GetValue();
154 return it->second.id;
159 glDeleteTextures( 1, &it->second.id );
187 return std::numeric_limits< GLuint >::max();
189 wxImage imgData = *imgPtr;
192 GLint maxTextureSize;
193 glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxTextureSize );
195 int imgWidth = imgData.GetWidth();
196 int imgHeight = imgData.GetHeight();
198 if( imgWidth > maxTextureSize || imgHeight > maxTextureSize )
202 double scaleX =
static_cast<double>( maxTextureSize ) / imgWidth;
203 double scaleY =
static_cast<double>( maxTextureSize ) / imgHeight;
204 double scale = std::min( scaleX, scaleY );
206 int newWidth = std::clamp(
KiROUND( imgWidth *
scale ), 1, maxTextureSize );
207 int newHeight = std::clamp(
KiROUND( imgHeight *
scale ), 1, maxTextureSize );
209 imgData = imgData.Scale( newWidth, newHeight, wxIMAGE_QUALITY_HIGH );
211 if( !imgData.IsOk() )
212 return std::numeric_limits< GLuint >::max();
215 bmp.
w = imgData.GetSize().x;
216 bmp.
h = imgData.GetSize().y;
222 glGenTextures( 1, &textureID );
230 glPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
232 if( imgData.HasAlpha() || imgData.HasMask() )
234 bmp.
size =
static_cast<size_t>( bmp.
w ) * bmp.
h * 4;
235 auto buf = std::make_unique<uint8_t[]>( bmp.
size );
237 uint8_t* dstP = buf.get();
238 uint8_t* srcP = imgData.GetData();
240 long long pxCount =
static_cast<long long>( bmp.
w ) * bmp.
h;
242 if( imgData.HasAlpha() )
244 uint8_t* srcAlpha = imgData.GetAlpha();
246 for(
long long px = 0; px < pxCount; px++ )
248 memcpy( dstP, srcP, 3 );
256 else if( imgData.HasMask() )
258 uint8_t maskRed = imgData.GetMaskRed();
259 uint8_t maskGreen = imgData.GetMaskGreen();
260 uint8_t maskBlue = imgData.GetMaskBlue();
262 for(
long long px = 0; px < pxCount; px++ )
264 memcpy( dstP, srcP, 3 );
266 if( srcP[0] == maskRed && srcP[1] == maskGreen && srcP[2] == maskBlue )
267 dstP[3] = wxALPHA_TRANSPARENT;
269 dstP[3] = wxALPHA_OPAQUE;
276 glBindTexture( GL_TEXTURE_2D, textureID );
277 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, bmp.
w, bmp.
h, 0, GL_RGBA, GL_UNSIGNED_BYTE,
282 bmp.
size =
static_cast<size_t>( bmp.
w ) * bmp.
h * 3;
284 uint8_t* srcP = imgData.GetData();
286 glBindTexture( GL_TEXTURE_2D, textureID );
287 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, bmp.
w, bmp.
h, 0, GL_RGB, GL_UNSIGNED_BYTE, srcP );
290 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
291 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
293 long long currentTime = wxGetUTCTimeMillis().GetValue();
298#ifndef DISABLE_BITMAP_CACHE
308 for(
const auto& [kiid, cachedBmp] :
m_bitmaps )
310 const int cacheTimeoutMillis = 1000L;
312 if( currentTime - cachedBmp.accessTime > cacheTimeoutMillis )
326 toRemove = *toRemoveLru;
332 glDeleteTextures( 1, &cachedBitmap.
id );
350 wxEvtHandler* aMouseListener, wxEvtHandler* aPaintListener,
351 const wxString& aName ) :
352 GAL( aDisplayOptions ),
374 throw std::runtime_error(
"Could not create the main OpenGL context" );
383 throw std::runtime_error(
"Could not create a private OpenGL context" );
428#if defined _WIN32 || defined _WIN64
435 SetSize( aParent->GetClientSize() );
446 gluTessProperty(
m_tesselator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_POSITIVE );
518 static std::optional<wxString> cached;
520 if( cached.has_value() )
523 wxString retVal = wxEmptyString;
525 wxFrame* testFrame =
new wxFrame(
nullptr, wxID_ANY, wxT(
"" ), wxDefaultPosition,
526 wxSize( 1, 1 ), wxFRAME_TOOL_WINDOW | wxNO_BORDER );
548 catch( std::runtime_error& err )
551 retVal = wxString( err.what() );
610#ifdef KICAD_GAL_PROFILE
611 PROF_TIMER totalRealTime(
"OPENGL_GAL::beginDrawing()",
true );
614 wxASSERT_MSG(
m_isContextLocked,
"GAL_DRAWING_CONTEXT RAII object should have locked context. "
615 "Calling GAL::beginDrawing() directly is not allowed." );
617 wxASSERT_MSG(
IsVisible(),
"GAL::beginDrawing() must not be entered when GAL is not visible. "
618 "Other drawing routines will expect everything to be initialized "
619 "which will not be the case." );
625 glMatrixMode( GL_PROJECTION );
641 catch(
const std::runtime_error& )
643 wxLogVerbose(
"Could not create a framebuffer for diff mode blending.\n" );
650 catch(
const std::runtime_error& )
652 wxLogVerbose(
"Could not create a framebuffer for overlays.\n" );
662 glDisable( GL_TEXTURE_2D );
664 glShadeModel( GL_FLAT );
667 glEnable( GL_DEPTH_TEST );
668 glDepthFunc( GL_LESS );
671 glEnable( GL_BLEND );
672 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
674 glMatrixMode( GL_MODELVIEW );
678 GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
688 glLoadMatrixd( matrixData );
707 const GLint FONT_TEXTURE_UNIT = 2;
712 glActiveTexture( GL_TEXTURE0 + FONT_TEXTURE_UNIT );
717 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
718 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
719 checkGlError(
"loading bitmap font", __FILE__, __LINE__ );
721 glActiveTexture( GL_TEXTURE0 );
727 glActiveTexture( GL_TEXTURE0 + FONT_TEXTURE_UNIT );
729 glActiveTexture( GL_TEXTURE0 );
736 checkGlError(
"setting bitmap font sampler as shader parameter", __FILE__, __LINE__ );
746 double pixelSizeMultiplier =
m_compositor->GetAntialiasSupersamplingFactor();
749 renderingOffset.
x *= screenPixelSize.
x;
750 renderingOffset.
y *= screenPixelSize.
y;
757 glActiveTexture( GL_TEXTURE0 );
762#ifdef KICAD_GAL_PROFILE
763 totalRealTime.
Stop();
764 wxLogTrace(
traceGalProfile, wxT(
"OPENGL_GAL::beginDrawing(): %.1f ms" ),
765 totalRealTime.
msecs() );
788 PROF_TIMER cntEndNoncached(
"gl-end-noncached" );
798 cntEndNoncached.
Start();
800 cntEndNoncached.
Stop();
802 cntEndCached.
Start();
806 cntEndOverlay.
Start();
812 cntEndOverlay.
Stop();
814 cntComposite.
Start();
817 glColor4d( 1.0, 1.0, 1.0, 1.0 );
836#ifdef KICAD_GAL_PROFILE
854 glGetIntegerv( GL_VIEWPORT, viewport );
856 const int w = viewport[2];
857 const int h = viewport[3];
859 GLint readBuffer = GL_COLOR_ATTACHMENT0;
860 glGetIntegerv( GL_DRAW_BUFFER, &readBuffer );
866 std::vector<unsigned char> rgba( (
size_t) w * h * 4 );
869 glPixelStorei( GL_PACK_ALIGNMENT, 1 );
870 glReadBuffer( (GLenum) readBuffer );
871 glReadPixels( 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgba.data() );
874 unsigned char* rgb = (
unsigned char*) malloc( (
size_t) w * h * 3 );
875 unsigned char* alpha = (
unsigned char*) malloc( (
size_t) w * h );
877 for(
int i = 0; i < w * h; ++i )
879 rgb[i * 3 + 0] = rgba[i * 4 + 0];
880 rgb[i * 3 + 1] = rgba[i * 4 + 1];
881 rgb[i * 3 + 2] = rgba[i * 4 + 2];
882 alpha[i] = rgba[i * 4 + 3];
885 aDstImage.SetData( rgb, w, h,
false );
886 aDstImage.SetAlpha( alpha,
false );
888 aDstImage = aDstImage.Mirror(
false );
915 wxASSERT_MSG(
m_isContextLocked,
"Context not locked. A GAL_CONTEXT_LOCKER RAII object must "
916 "be stacked rather than making separate lock/unlock calls." );
919 "Context was locked by a different client. "
920 "Should not be possible with RAII objects." );
935 wxASSERT_MSG(
m_isContextLocked,
"GAL_UPDATE_CONTEXT RAII object should have locked context. "
936 "Calling this from anywhere else is not allowed." );
938 wxASSERT_MSG(
IsVisible(),
"GAL::beginUpdate() must not be entered when GAL is not visible. "
939 "Other update routines will expect everything to be initialized "
940 "which will not be the case." );
976 VECTOR2D startEndVector = aEndPoint - aStartPoint;
983 float startX =
static_cast<float>( aStartPoint.
x );
984 float startY =
static_cast<float>( aStartPoint.
y );
985 float endX =
static_cast<float>( aEndPoint.
x );
986 float endY =
static_cast<float>( aEndPoint.
y );
988 if( startX == endX && startY == endY )
990 drawCircle( aStartPoint, aWidth / 2, aReserve );
1125 double startAngle = aStartAngle.
AsRadians();
1126 double endAngle = startAngle + aAngle.
AsRadians();
1143 for( alpha = startAngle; ( alpha + alphaIncrement ) < endAngle; )
1149 alpha += alphaIncrement;
1155 const VECTOR2D endPoint( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
1168 VECTOR2D p( cos( startAngle ) * aRadius, sin( startAngle ) * aRadius );
1170 unsigned int lineCount = 0;
1172 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1175 if( alpha != endAngle )
1180 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1182 VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
1189 if( alpha != endAngle )
1191 VECTOR2D p_last( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
1202 double aWidth,
double aMaxError )
1213 double startAngle = aStartAngle.
AsRadians();
1214 double endAngle = startAngle + aAngle.
AsRadians();
1222 double alphaIncrement = 2.0 *
M_PI / segCount360;
1227 int seg_count =
KiROUND( ( endAngle - startAngle ) / alphaIncrement );
1229 if( seg_count % 2 != 0 )
1233 if( seg_count == 0 )
1235 VECTOR2D p_start( aCenterPoint.
x + cos( startAngle ) * aRadius,
1236 aCenterPoint.
y + sin( startAngle ) * aRadius );
1238 VECTOR2D p_end( aCenterPoint.
x + cos( endAngle ) * aRadius,
1239 aCenterPoint.
y + sin( endAngle ) * aRadius );
1246 alphaIncrement = ( endAngle - startAngle ) / seg_count;
1256 double width = aWidth / 2.0;
1257 VECTOR2D startPoint( cos( startAngle ) * aRadius, sin( startAngle ) * aRadius );
1258 VECTOR2D endPoint( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
1263 VECTOR2D pOuter( cos( startAngle ) * ( aRadius + width ),
1264 sin( startAngle ) * ( aRadius + width ) );
1266 VECTOR2D pInner( cos( startAngle ) * ( aRadius - width ),
1267 sin( startAngle ) * ( aRadius - width ) );
1271 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1273 VECTOR2D pNextOuter( cos( alpha ) * ( aRadius + width ),
1274 sin( alpha ) * ( aRadius + width ) );
1275 VECTOR2D pNextInner( cos( alpha ) * ( aRadius - width ),
1276 sin( alpha ) * ( aRadius - width ) );
1281 pOuter = pNextOuter;
1282 pInner = pNextInner;
1286 if( alpha != endAngle )
1288 VECTOR2D pLastOuter( cos( endAngle ) * ( aRadius + width ),
1289 sin( endAngle ) * ( aRadius + width ) );
1290 VECTOR2D pLastInner( cos( endAngle ) * ( aRadius - width ),
1291 sin( endAngle ) * ( aRadius - width ) );
1303 VECTOR2D p( cos( startAngle ) * aRadius, sin( startAngle ) * aRadius );
1308 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1314 if( alpha != endAngle )
1321 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1323 VECTOR2D p_next( cos( alpha ) * aRadius, sin( alpha ) * aRadius );
1330 if( alpha != endAngle )
1332 VECTOR2D p_last( cos( endAngle ) * aRadius, sin( endAngle ) * aRadius );
1344 if( aMajorRadius <= 0 || aMinorRadius <= 0 )
1347 const double alphaIncrement =
calcAngleStep( aMajorRadius );
1348 const double cosPhi = std::cos( aRotation.
AsRadians() );
1349 const double sinPhi = std::sin( aRotation.
AsRadians() );
1351 auto eval = [&](
double theta ) ->
VECTOR2D
1353 const double lx = aMajorRadius * std::cos( theta );
1354 const double ly = aMinorRadius * std::sin( theta );
1355 return VECTOR2D( lx * cosPhi - ly * sinPhi, lx * sinPhi + ly * cosPhi );
1368 for( alpha = 0.0; ( alpha + alphaIncrement ) < 2.0 *
M_PI; )
1371 alpha += alphaIncrement;
1395 unsigned int lineCount = 0;
1398 for( countAlpha = alphaIncrement; countAlpha < 2.0 *
M_PI; countAlpha += alphaIncrement )
1408 for( alpha = alphaIncrement; alpha < 2.0 *
M_PI; alpha += alphaIncrement )
1410 const VECTOR2D p_next = eval( alpha );
1426 if( aMajorRadius <= 0 || aMinorRadius <= 0 )
1429 double startAngle = aStartAngle.
AsRadians();
1430 double endAngle = aEndAngle.
AsRadians();
1433 const double alphaIncrement =
calcAngleStep( aMajorRadius );
1434 const double cosPhi = std::cos( aRotation.
AsRadians() );
1435 const double sinPhi = std::sin( aRotation.
AsRadians() );
1437 auto eval = [&](
double theta ) ->
VECTOR2D
1439 const double lx = aMajorRadius * std::cos( theta );
1440 const double ly = aMinorRadius * std::sin( theta );
1441 return VECTOR2D( lx * cosPhi - ly * sinPhi, lx * sinPhi + ly * cosPhi );
1455 for( alpha = startAngle; ( alpha + alphaIncrement ) < endAngle; )
1458 alpha += alphaIncrement;
1469 const VECTOR2D p2 = eval( endAngle );
1481 unsigned int lineCount = 0;
1484 for( countAlpha = startAngle + alphaIncrement; countAlpha <= endAngle; countAlpha += alphaIncrement )
1487 if( countAlpha != endAngle )
1495 for( alpha = startAngle + alphaIncrement; alpha <= endAngle; alpha += alphaIncrement )
1497 const VECTOR2D p_next = eval( alpha );
1503 if( alpha != endAngle )
1505 const VECTOR2D p_last = eval( endAngle );
1517 VECTOR2D diagonalPointA( aEndPoint.
x, aStartPoint.
y );
1518 VECTOR2D diagonalPointB( aStartPoint.
x, aEndPoint.
y );
1544 if( aStartPoint == aEndPoint )
1550 std::deque<VECTOR2D> pointList;
1552 pointList.push_back( aStartPoint );
1553 pointList.push_back( diagonalPointA );
1554 pointList.push_back( aEndPoint );
1555 pointList.push_back( diagonalPointB );
1556 pointList.push_back( aStartPoint );
1568 return aPointList[idx];
1570 aPointList.size(), aWidth );
1584 return aLineChain.
CPoint( idx );
1586 numPoints, aWidth );
1595 return aPointList[idx];
1597 aPointList.size() );
1606 return aPointList[idx];
1608 aPointList.size() );
1617 return aPointList[idx];
1633 return aLineChain.
CPoint( idx );
1641 int lineQuadCount = 0;
1643 for(
const std::vector<VECTOR2D>& points : aPointList )
1644 lineQuadCount += points.size() - 1;
1648 for(
const std::vector<VECTOR2D>& points : aPointList )
1655 points.size(),
false );
1662 wxCHECK( aPointList.size() >= 2, );
1663 auto points = std::unique_ptr<GLdouble[]>(
new GLdouble[3 * aPointList.size()] );
1664 GLdouble* ptr = points.get();
1666 for(
const VECTOR2D& p : aPointList )
1679 wxCHECK( aListSize >= 2, );
1680 auto points = std::unique_ptr<GLdouble[]>(
new GLdouble[3 * aListSize] );
1681 GLdouble* target = points.get();
1684 for(
int i = 0; i < aListSize; ++i )
1697 bool aStrokeTriangulation )
1704 int totalTriangleCount = 0;
1719 for(
size_t i = 0; i < triPoly->GetTriangleCount(); i++ )
1722 triPoly->GetTriangle( i, a, b, c );
1734 const auto& poly = aPolySet.
Polygon( j );
1736 for(
const auto& lc : poly )
1745 aStrokeTriangulation =
true;
1749 if( aStrokeTriangulation )
1758 for(
size_t i = 0; i < triPoly->GetTriangleCount(); i++ )
1761 triPoly->GetTriangle( i, a, b, c );
1793 std::unique_ptr<GLdouble[]> points(
new GLdouble[3 * pointCount] );
1794 GLdouble* ptr = points.get();
1796 for(
int i = 0; i < pointCount; ++i )
1810 double aFilterValue )
1812 std::vector<VECTOR2D> output;
1813 std::vector<VECTOR2D> pointCtrl;
1815 pointCtrl.push_back( aStartPoint );
1816 pointCtrl.push_back( aControlPointA );
1817 pointCtrl.push_back( aControlPointB );
1818 pointCtrl.push_back( aEndPoint );
1821 converter.
GetPoly( output, aFilterValue );
1823 if( output.size() == 1 )
1824 output.push_back( output.front() );
1832 GLfloat alpha = std::clamp( alphaBlend, 0.0, 1.0 );
1842 glm::vec4 v0 = xform * glm::vec4( -w / 2, -h / 2, 0.0, 0.0 );
1843 glm::vec4
v1 = xform * glm::vec4( w / 2, h / 2, 0.0, 0.0 );
1844 glm::vec4 trans = xform[3];
1848 if( !glIsTexture( texture_id ) )
1851 GLboolean depthMask = GL_TRUE;
1852 glGetBooleanv( GL_DEPTH_WRITEMASK, &depthMask );
1855 glDepthMask( GL_FALSE );
1857 glDepthFunc( GL_ALWAYS );
1859 glAlphaFunc( GL_GREATER, 0.01f );
1860 glEnable( GL_ALPHA_TEST );
1862 glMatrixMode( GL_TEXTURE );
1864 glTranslated( 0.5, 0.5, 0.5 );
1866 glTranslated( -0.5, -0.5, -0.5 );
1868 glMatrixMode( GL_MODELVIEW );
1870 glTranslated( trans.x, trans.y, trans.z );
1872 glEnable( GL_TEXTURE_2D );
1873 glActiveTexture( GL_TEXTURE0 );
1874 glBindTexture( GL_TEXTURE_2D, texture_id );
1876 float texStartX = aBitmap.
IsMirroredX() ? 1.0 : 0.0;
1877 float texEndX = aBitmap.
IsMirroredX() ? 0.0 : 1.0;
1878 float texStartY = aBitmap.
IsMirroredY() ? 1.0 : 0.0;
1879 float texEndY = aBitmap.
IsMirroredY() ? 0.0 : 1.0;
1881 glBegin( GL_QUADS );
1882 glColor4f( 1.0, 1.0, 1.0, alpha );
1883 glTexCoord2f( texStartX, texStartY );
1885 glColor4f( 1.0, 1.0, 1.0, alpha );
1886 glTexCoord2f( texEndX, texStartY);
1888 glColor4f( 1.0, 1.0, 1.0, alpha );
1889 glTexCoord2f( texEndX, texEndY);
1891 glColor4f( 1.0, 1.0, 1.0, alpha );
1892 glTexCoord2f( texStartX, texEndY);
1896 glBindTexture( GL_TEXTURE_2D, 0 );
1898#ifdef DISABLE_BITMAP_CACHE
1899 glDeleteTextures( 1, &texture_id );
1904 glMatrixMode( GL_TEXTURE );
1906 glMatrixMode( GL_MODELVIEW );
1908 glDisable( GL_ALPHA_TEST );
1910 glDepthMask( depthMask );
1912 glDepthFunc( GL_LESS );
1921 || aText.Contains( wxT(
"^{" ) )
1922 || aText.Contains( wxT(
"_{" ) )
1923 || aText.Contains( wxT(
"\n" ) ) )
1934 double overbarHeight = textSize.
y;
1965 wxFAIL_MSG( wxT(
"Indeterminate state legal only in dialogs." ) );
1981 overbarHeight = -textSize.
y / 2.0;
1985 wxFAIL_MSG( wxT(
"Indeterminate state legal only in dialogs." ) );
1989 int overbarLength = 0;
1990 int overbarDepth = -1;
1991 int braceNesting = 0;
1993 auto iterateString =
1994 [&](
const std::function<void(
int aOverbarLength,
int aOverbarHeight )>& overbarFn,
1995 const std::function<int(
unsigned long aChar )>& bitmapCharFn )
1999 wxASSERT_MSG( *chIt !=
'\n' && *chIt !=
'\r',
2000 "No support for multiline bitmap text yet" );
2002 if( *chIt ==
'~' && overbarDepth == -1 )
2006 if( ++lookahead !=
end && *lookahead ==
'{' )
2009 overbarDepth = braceNesting;
2014 else if( *chIt ==
'{' )
2018 else if( *chIt ==
'}' )
2020 if( braceNesting > 0 )
2023 if( braceNesting == overbarDepth )
2025 overbarFn( overbarLength, overbarHeight );
2033 if( overbarDepth != -1 )
2034 overbarLength += bitmapCharFn( *chIt );
2036 bitmapCharFn( *chIt );
2043 int overbarsCount = 0;
2046 [&overbarsCount](
int aOverbarLength,
int aOverbarHeight )
2050 [&charsCount](
unsigned long aChar ) ->
int
2066 [&](
int aOverbarLength,
int aOverbarHeight )
2070 [&](
unsigned long aChar ) ->
int
2078 if( overbarDepth != -1 && overbarLength > 0 )
2108 if( renderGlobalGrid )
2130 if( renderGlobalGrid )
2154 const double rMax = src.
extent.
x;
2155 const double phiMax = src.
extent.
y;
2157 if( rMax > 0.0 && phiMax > 0.0 )
2159 if( phiMax >= 2 *
M_PI - 1e-6 )
2165 const int kArcSegments = std::max( 16, (
int) ( phiMax / (
M_PI / 16 ) ) );
2166 std::deque<VECTOR2D> poly;
2167 poly.emplace_back( 0.0, 0.0 );
2169 for(
int i = 0; i <= kArcSegments; ++i )
2171 const double phi = phiMax * i / kArcSegments;
2172 poly.emplace_back( rMax * std::cos( phi ), rMax * std::sin( phi ) );
2175 poly.emplace_back( 0.0, 0.0 );
2187 default: wxFAIL_MSG( wxT(
"drawGridCoverageShape: unhandled GRID_SOURCE::KIND" ) );
break;
2201 std::vector<const GRID_SOURCE*> ordered;
2206 if( !src.highlighted )
2207 ordered.push_back( &src );
2212 if( src.highlighted )
2213 ordered.push_back( &src );
2217 const float majorLineWidth = minorLineWidth * 2.0f;
2220 glDisable( GL_DEPTH_TEST );
2221 glDisable( GL_TEXTURE_2D );
2224 glEnable( GL_STENCIL_TEST );
2225 glStencilMask( 0xFF );
2226 glClear( GL_STENCIL_BUFFER_BIT );
2233 const GLuint coverageMask = src.
highlighted ? 0 : STENCIL_GRID_COVERAGE;
2235 glStencilMask( 0x00 );
2236 glStencilFunc( GL_EQUAL, 0, coverageMask );
2237 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
2256 glColor4d( color.
r, color.
g, color.
b, color.
a );
2264 const unsigned tick = ( src.
tick > 0 ) ? src.
tick :
static_cast<unsigned>(
m_gridTick );
2265 const double threshold =
2269 auto drawCrossAt = [&](
const VECTOR2D& pos,
bool aMajor,
double aArmAngle )
2271 const float w = aMajor ? majorLineWidth : minorLineWidth;
2272 const double len = 2.0 * w;
2273 const double c = std::cos( aArmAngle );
2274 const double s = std::sin( aArmAngle );
2275 const VECTOR2D arm1( c * len, s * len );
2276 const VECTOR2D arm2( -s * len, c * len );
2281 DrawLine( pos - arm1, pos + arm1 );
2282 DrawLine( pos - arm2, pos + arm2 );
2286 auto beginLines = [&]()
2293 auto drawDotsViaStencil = [&](
auto&& aMarkAxis,
auto&& aRenderAxis )
2296 glStencilMask( STENCIL_DOTS_MARKER );
2297 glClear( GL_STENCIL_BUFFER_BIT );
2300 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
2301 glStencilFunc( GL_EQUAL, STENCIL_DOTS_MARKER, coverageMask );
2302 glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
2309 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
2310 glStencilMask( 0x00 );
2311 glStencilFunc( GL_EQUAL, STENCIL_DOTS_MARKER, STENCIL_DOTS_MARKER | coverageMask );
2312 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
2324 double dPhi = src.
pitch.
y;
2332 rMax = std::hypot( farX, farY ) * 1.01;
2346 wxASSERT( dr > 0.0 && dPhi > 0.0 );
2348 auto drawArcs = [&]()
2351 for(
double r = 0; r <= rMax + 1e-6; r += dr, ++rIdx )
2356 SetLineWidth( ( tick && rIdx % (
int) tick == 0 ) ? majorLineWidth : minorLineWidth );
2361 auto drawSpokes = [&]()
2364 for(
double phi = 0; phi <= phiMax + 1e-6; phi += dPhi, ++pIdx )
2366 SetLineWidth( ( tick && pIdx % (
int) tick == 0 ) ? majorLineWidth : minorLineWidth );
2367 const double cx = std::cos( phi );
2368 const double cy = std::sin( phi );
2381 drawDotsViaStencil( drawArcs, drawSpokes );
2386 for(
double r = 0; r <= rMax + 1e-6; r += dr, ++rIdx )
2389 for(
double phi = 0; phi <= phiMax + 1e-6; phi += dPhi, ++pIdx )
2391 const bool major = tick && ( rIdx % (int) tick == 0 ) && ( pIdx % (
int) tick == 0 );
2392 const VECTOR2D pos( r * std::cos( phi ), r * std::sin( phi ) );
2393 drawCrossAt( pos, major, phi );
2406 const double minPitch = std::min( dx, dy );
2409 if( sparsed != minPitch )
2411 const double scale = sparsed / minPitch;
2416 wxASSERT( dx > 0.0 && dy > 0.0 );
2418 double xMin, xMax, yMin, yMax;
2419 int ixMin, ixMax, iyMin, iyMax;
2430 yMin = localBBox.
GetTop();
2433 ixMin = (int) std::floor( xMin / dx );
2434 ixMax = (int) std::ceil( xMax / dx );
2435 iyMin = (int) std::floor( yMin / dy );
2436 iyMax = (int) std::ceil( yMax / dy );
2444 ixMin = (int) -( src.
extent.
x / dx );
2445 ixMax = (int) ( src.
extent.
x / dx );
2446 iyMin = (int) -( src.
extent.
y / dy );
2447 iyMax = (int) ( src.
extent.
y / dy );
2450 auto drawVerticals = [&]()
2452 for(
int ix = ixMin; ix <= ixMax; ++ix )
2454 const double x = ix * dx;
2460 SetLineWidth( ( tick &&
std::abs( ix ) % (
int) tick == 0 ) ? majorLineWidth : minorLineWidth );
2465 auto drawHorizontals = [&]()
2467 for(
int iy = iyMin; iy <= iyMax; ++iy )
2469 const double y = iy * dy;
2474 SetLineWidth( ( tick &&
std::abs( iy ) % (
int) tick == 0 ) ? majorLineWidth : minorLineWidth );
2487 drawDotsViaStencil( drawVerticals, drawHorizontals );
2491 for(
int ix = ixMin; ix <= ixMax; ++ix )
2493 for(
int iy = iyMin; iy <= iyMax; ++iy )
2496 tick && (
std::abs( ix ) % (int) tick == 0 ) && (
std::abs( iy ) % (int) tick == 0 );
2497 drawCrossAt(
VECTOR2D( ix * dx, iy * dy ), major, 0.0 );
2504 default: wxFAIL_MSG( wxT(
"drawGridSources: unhandled GRID_SOURCE::KIND" ) );
break;
2513 glStencilMask( 0x00 );
2514 glStencilFunc( GL_EQUAL, 0, coverageMask );
2515 glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
2528 glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
2529 glStencilMask( STENCIL_GRID_COVERAGE );
2530 glStencilFunc( GL_ALWAYS, STENCIL_GRID_COVERAGE, STENCIL_GRID_COVERAGE );
2531 glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
2538 glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
2542 glDisable( GL_STENCIL_TEST );
2544 glEnable( GL_DEPTH_TEST );
2545 glEnable( GL_TEXTURE_2D );
2555 m_compositor->Resize( aWidth * scaleFactor, aHeight * scaleFactor );
2558 wxGLCanvas::SetSize( aWidth, aHeight );
2564 bool s = wxGLCanvas::Show( aShow );
2567 wxGLCanvas::Raise();
2585 glClearColor( 0, 0, 0, 1 );
2586 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
2592 GLdouble matrixData[16] = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 };
2594 matrixData[0] = aTransformation.
m_data[0][0];
2595 matrixData[1] = aTransformation.
m_data[1][0];
2596 matrixData[2] = aTransformation.
m_data[2][0];
2597 matrixData[4] = aTransformation.
m_data[0][1];
2598 matrixData[5] = aTransformation.
m_data[1][1];
2599 matrixData[6] = aTransformation.
m_data[2][1];
2600 matrixData[12] = aTransformation.
m_data[0][2];
2601 matrixData[13] = aTransformation.
m_data[1][2];
2602 matrixData[14] = aTransformation.
m_data[2][2];
2604 glMultMatrixd( matrixData );
2642 std::shared_ptr<VERTEX_ITEM> newItem = std::make_shared<VERTEX_ITEM>( *
m_cachedManager );
2644 m_groups.insert( std::make_pair( groupNumber, newItem ) );
2773 wxLogTrace(
traceGalXorMode, wxT(
"OPENGL_GAL::StartDiffLayer() called" ) );
2780 wxLogTrace(
traceGalXorMode, wxT(
"StartDiffLayer(): setting target to TARGET_TEMP" ) );
2787 wxLogTrace(
traceGalXorMode, wxT(
"StartDiffLayer(): TARGET_TEMP set and cleared, compositor buffer=%u" ),
2792 wxLogTrace(
traceGalXorMode, wxT(
"StartDiffLayer(): WARNING - no temp buffer!" ) );
2799 wxLogTrace(
traceGalXorMode, wxT(
"OPENGL_GAL::EndDiffLayer() called" ) );
2800 wxLogTrace(
traceGalXorMode, wxT(
"EndDiffLayer(): m_tempBuffer=%u, m_mainBuffer=%u" ),
2805 wxLogTrace(
traceGalXorMode, wxT(
"EndDiffLayer(): using temp buffer path" ) );
2810 wxLogTrace(
traceGalXorMode, wxT(
"EndDiffLayer(): calling DrawBufferDifference" ) );
2818 wxLogTrace(
traceGalXorMode, wxT(
"EndDiffLayer(): DrawBufferDifference returned" ) );
2822 wxLogTrace(
traceGalXorMode, wxT(
"EndDiffLayer(): NO temp buffer, using fallback path" ) );
2825 glBlendFunc( GL_SRC_ALPHA, GL_ONE );
2827 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
2830 wxLogTrace(
traceGalXorMode, wxT(
"OPENGL_GAL::EndDiffLayer() complete" ) );
2842#if wxCHECK_VERSION( 3, 3, 0 )
2854#if wxCHECK_VERSION( 3, 3, 0 )
2873 const bool aReserve )
2891 * glm::vec4( aStartPoint.
x, aStartPoint.
y, 0.0, 0.0 );
2893 * glm::vec4( aEndPoint.
x, aEndPoint.
y, 0.0, 0.0 );
2977 double outerRadius = aRadius + (
m_lineWidth / 2 );
3023 GLdouble* point = aPoints;
3025 for(
int i = 0; i < aPointCount; ++i )
3043 return VECTOR2D( aPoints[idx * 3], aPoints[idx * 3 + 1] );
3053 wxCHECK( aPointCount > 0, );
3057 if( aPointCount == 1 )
3059 drawLineQuad( aPointGetter( 0 ), aPointGetter( 0 ), aReserve );
3068 for(
int i = 1; i < aPointCount; ++i )
3070 auto start = aPointGetter( i - 1 );
3071 auto end = aPointGetter( i );
3079 int aPointCount,
double aWidth,
bool aReserve )
3081 wxCHECK( aPointCount >= 2, );
3087 for(
int i = 1; i < aPointCount; ++i )
3089 auto start = aPointGetter( i - 1 );
3090 auto end = aPointGetter( i );
3092 float startx = start.x;
3093 float starty = start.y;
3102 if( startx == endx && starty == endy )
3114 vertices += 6 + 6 + 3 + 3;
3120 for(
int i = 1; i < aPointCount; ++i )
3122 auto start = aPointGetter( i - 1 );
3123 auto end = aPointGetter( i );
3142 double spaceWidth = g->
advance * 0.74;
3160 const float XOFF = glyph->
minx;
3163 const float round_adjust = ( glyph->
maxy - glyph->
miny )
3166 const float YOFF = round_adjust + top_adjust;
3215 const float H = glyph->
maxy - glyph->
miny;
3245 float commonOffset = std::numeric_limits<float>::max();
3247 int overbarDepth = -1;
3248 int braceNesting = 0;
3252 if( *chIt ==
'~' && overbarDepth == -1 )
3256 if( ++lookahead !=
end && *lookahead ==
'{' )
3259 overbarDepth = braceNesting;
3264 else if( *chIt ==
'{' )
3268 else if( *chIt ==
'}' )
3270 if( braceNesting > 0 )
3273 if( braceNesting == overbarDepth )
3283 || *chIt ==
'-' || *chIt ==
'_' )
3285 glyph = defaultGlyph;
3292 textSize.
y = std::max<float>( textSize.
y, charHeight );
3294 textSize.
y -= commonOffset;
3296 return std::make_pair( textSize, commonOffset );
3340 const int cursorSize = 80;
3347 GLboolean depthTestEnabled = glIsEnabled( GL_DEPTH_TEST );
3348 glDisable( GL_DEPTH_TEST );
3350 glActiveTexture( GL_TEXTURE0 );
3351 glDisable( GL_TEXTURE_2D );
3352 glEnable( GL_BLEND );
3353 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
3356 glColor4d( color.
r, color.
g, color.
b, color.
a );
3358 glMatrixMode( GL_PROJECTION );
3360 glTranslated( 0, 0, -0.5 );
3362 glBegin( GL_LINES );
3377 double offset1 = cy - cx;
3378 VECTOR2D pos_start( screenTopLeft.
x, screenTopLeft.
x + offset1 );
3379 VECTOR2D pos_end( screenBottomRight.
x, screenBottomRight.
x + offset1 );
3382 glVertex2d( pos_start.
x, pos_start.
y );
3383 glVertex2d( pos_end.
x, pos_end.
y );
3386 double offset2 = cy + cx;
3387 VECTOR2D neg_start( screenTopLeft.
x, offset2 - screenTopLeft.
x );
3388 VECTOR2D neg_end( screenBottomRight.
x, offset2 - screenBottomRight.
x );
3391 glVertex2d( neg_start.
x, neg_start.
y );
3392 glVertex2d( neg_end.
x, neg_end.
y );
3396 glVertex2d( cursorCenter.
x, cursorBegin.
y );
3397 glVertex2d( cursorCenter.
x, cursorEnd.
y );
3399 glVertex2d( cursorBegin.
x, cursorCenter.
y );
3400 glVertex2d( cursorEnd.
x, cursorCenter.
y );
3407 if( depthTestEnabled )
3408 glEnable( GL_DEPTH_TEST );
3414 wxASSERT_MSG(
m_groups.size() < std::numeric_limits<unsigned int>::max(),
3415 wxT(
"There are no free slots to store a group" ) );
3426 wxASSERT_MSG(
m_isContextLocked,
"This should only be called from within a locked context." );
3430 throw std::runtime_error(
"Could not create the tesselator" );
3434 int glVersion = gladLoaderLoadGL();
3436 if( glVersion == 0 )
3437 throw std::runtime_error(
"Failed to load OpenGL via loader" );
3439 const char* vendor = (
const char*) glGetString( GL_VENDOR );
3440 const char* renderer = (
const char*) glGetString( GL_RENDERER );
3441 const char* version = (
const char*) glGetString( GL_VERSION );
3444 throw std::runtime_error(
"No GL context is current (glGetString returned NULL)" );
3449 if( !GLAD_GL_VERSION_2_1 )
3450 throw std::runtime_error(
"OpenGL 2.1 or higher is required!" );
3452#if defined( __LINUX__ )
3454 if( glDebugMessageCallback )
3460 if( !GLAD_GL_ARB_framebuffer_object )
3461 throw std::runtime_error(
"Framebuffer objects are not supported!" );
3464 if( !GLAD_GL_ARB_vertex_buffer_object )
3465 throw std::runtime_error(
"Vertex buffer objects are not supported!" );
3470 BUILTIN_SHADERS::glsl_kicad_vert ) )
3472 throw std::runtime_error(
"Cannot compile vertex shader!" );
3477 BUILTIN_SHADERS::glsl_kicad_frag ) )
3479 throw std::runtime_error(
"Cannot compile fragment shader!" );
3483 throw std::runtime_error(
"Cannot link the shaders!" );
3490 glGetIntegerv( GL_MAX_TEXTURE_SIZE, &maxTextureSize );
3496 throw std::runtime_error(
"Requested texture size is not supported" );
3499#if wxCHECK_VERSION( 3, 3, 3 )
3500 wxGLCanvas::SetSwapInterval( -1 );
3537 GLdouble* vertex =
static_cast<GLdouble*
>( aVertexPtr );
3541 assert( vboManager );
3542 vboManager->
Vertex( vertex[0], vertex[1], vertex[2] );
3547 GLdouble** dataOut,
void* aData )
3549 GLdouble* vertex =
new GLdouble[3];
3555 param->
intersectPoints.emplace_back( vertex, std::default_delete<GLdouble[]>() );
3557 memcpy( vertex, coords, 3 *
sizeof( GLdouble ) );
3578#if defined( _MSC_VER )
3579#pragma warning( push )
3580#pragma warning( disable : 4191 )
3586#if defined( _MSC_VER )
3587#pragma warning( pop )
3602 return ( ceil( f / r ) - 0.5 ) * r;
3635 outlineGlyph.Triangulate(
3650 if( aGlyphs.empty() )
3653 bool allGlyphsAreStroke =
true;
3654 bool allGlyphsAreOutline =
true;
3656 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3658 if( !glyph->IsStroke() )
3660 allGlyphsAreStroke =
false;
3665 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3667 if( !glyph->IsOutline() )
3669 allGlyphsAreOutline =
false;
3674 if( allGlyphsAreStroke )
3677 int lineQuadCount = 0;
3679 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3683 for(
const std::vector<VECTOR2D>& points : strokeGlyph )
3684 lineQuadCount += points.size() - 1;
3689 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3693 for(
const std::vector<VECTOR2D>& points : strokeGlyph )
3700 points.size(),
false );
3706 else if( allGlyphsAreOutline )
3709 int triangleCount = 0;
3711 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3715 for(
unsigned int i = 0; i < outlineGlyph.TriangulatedPolyCount(); i++ )
3718 outlineGlyph.TriangulatedPolygon( i );
3729 for(
const std::unique_ptr<KIFONT::GLYPH>& glyph : aGlyphs )
3733 for(
unsigned int i = 0; i < outlineGlyph.TriangulatedPolyCount(); i++ )
3736 outlineGlyph.TriangulatedPolygon( i );
3753 for(
size_t i = 0; i < aGlyphs.size(); i++ )
3754 DrawGlyph( *aGlyphs[i], i, aGlyphs.size() );
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
void SetOpenGLInfo(const char *aVendor, const char *aRenderer, const char *aVersion)
A setter for OpenGL info when it's initialized.
void SetOpenGLBackendInfo(wxString aBackend)
A setter for OpenGL backend info after the canvas is created.
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
Bezier curves to polygon converter.
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMaxError=10)
Convert a Bezier curve to a polygon.
This class handle bitmap images in KiCad.
const wxImage * GetOriginalImageData() const
VECTOR2I GetSizePixels() const
EDA_ANGLE Rotation() const
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
constexpr const Vec GetEnd() const
constexpr coord_type GetLeft() const
constexpr const Vec & GetOrigin() const
constexpr coord_type GetRight() const
constexpr coord_type GetTop() const
constexpr coord_type GetBottom() const
static const WX_CURSOR_TYPE GetCursor(KICURSOR aCursorType, bool aHiDPI=false)
Get a cursor bundle (wx 3.3+) or appropriate cursor (older versions)
void UnlockCtx(wxGLContext *aContext)
Allow other canvases to bind an OpenGL context.
void DestroyCtx(wxGLContext *aContext)
Destroy a managed OpenGL context.
void LockCtx(wxGLContext *aContext, wxGLCanvas *aCanvas)
Set a context as current and prevents other canvases from switching it.
wxGLContext * CreateCtx(wxGLCanvas *aCanvas, const wxGLContext *aOther=nullptr)
Create a managed OpenGL context.
static int SetSwapInterval(wxGLCanvas *aCanvas, int aVal)
Attempt to set the OpenGL swap interval.
static wxString DetectGLBackend(wxGLCanvas *aCanvas)
HIDPI_GL_CANVAS(const KIGFX::VC_SETTINGS &aSettings, wxWindow *aParent, const wxGLAttributes &aGLAttribs, wxWindowID aId=wxID_ANY, const wxPoint &aPos=wxDefaultPosition, const wxSize &aSize=wxDefaultSize, long aStyle=0, const wxString &aName=wxGLCanvasName, const wxPalette &aPalette=wxNullPalette)
virtual wxSize GetNativePixelSize() const
double GetScaleFactor() const
Get the current scale factor.
virtual bool IsStroke() const
virtual bool IsOutline() const
A color representation with 4 components: red, green, blue, alpha.
COLOR4D Darkened(double aFactor) const
Return a color that is darker by a given factor, without modifying object.
COLOR4D & Brighten(double aFactor)
Makes the color brighter by a given factor.
static const COLOR4D BLACK
bool IsTextMirrored() const
void SetGridColor(const COLOR4D &aGridColor)
Set the grid color.
virtual void SetLayerDepth(double aLayerDepth)
Set the depth of the layer (position on the z-axis)
bool IsCursorEnabled() const
Return information about cursor visibility.
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
friend class GAL_CONTEXT_LOCKER
MATRIX3x3D m_worldScreenMatrix
World transformation.
VECTOR2D GetVisibleGridSize() const
Return the visible grid size in x and y directions.
double m_layerDepth
The actual layer depth.
MATRIX3x3D m_screenWorldMatrix
Screen transformation.
friend class GAL_SCOPED_ATTRS
bool m_axesEnabled
Should the axes be drawn.
float m_gridLineWidth
Line width of the grid.
VECTOR2I m_screenSize
Screen size in screen (wx logical) coordinates.
GR_TEXT_H_ALIGN_T GetHorizontalJustify() const
void normalize(T &a, T &b)
Ensure that the first element is smaller than the second.
VECTOR2D m_depthRange
Range of the depth.
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
virtual bool SetNativeCursorStyle(KICURSOR aCursor, bool aHiDPI)
Set the cursor in the native panel.
GRID_STYLE m_gridStyle
Grid display style.
COLOR4D m_axesColor
Color of the axes.
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
float m_lineWidth
The line width.
void computeWorldScale()
Compute the scaling factor for the world->screen matrix.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
VECTOR2D m_gridSize
The grid size.
COLOR4D getCursorColor() const
Get the actual cursor color to draw.
COLOR4D m_fillColor
The fill color.
double m_worldUnitLength
The unit length of the world coordinates [inch].
virtual bool updatedGalDisplayOptions(const GAL_DISPLAY_OPTIONS &aOptions)
Handle updating display options.
void SetAxesColor(const COLOR4D &aAxesColor)
Set the axes color.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
BOX2D gridScreenBBox(const GRID_SOURCE &aSrc) const
VECTOR2D m_cursorPosition
Current cursor position (world coordinates)
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
const VECTOR2I & GetGlyphSize() const
int m_gridTick
Every tick line gets the double width.
double m_worldScale
The scale factor world->screen.
VECTOR2D m_gridOrigin
The grid origin.
virtual void SetMinLineWidth(float aLineWidth)
Set the minimum line width in pixels.
KICURSOR m_currentNativeCursor
Current cursor.
bool m_globalFlipY
Flag for Y axis flipping.
float GetMinLineWidth() const
Get the minimum line width in pixels.
bool m_isFillEnabled
Is filling of graphic objects enabled ?
virtual void ComputeWorldScreenMatrix()
Compute the world <-> screen transformation matrix.
COLOR4D m_gridColor
Color of the grid.
COLOR4D m_strokeColor
The color of the outlines.
double computeMinGridSpacing() const
Compute minimum grid spacing from the grid settings.
bool m_isStrokeEnabled
Are the outlines stroked ?
std::vector< GRID_SOURCE > m_gridSources
Sources overlayed on the display grid.
GAL_DISPLAY_OPTIONS & m_options
bool m_gridVisibility
Should the grid be shown.
virtual void BitmapText(const wxString &aText, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle)
Draw a text using a bitmap font.
bool m_globalFlipX
Flag for X axis flipping.
GR_TEXT_V_ALIGN_T GetVerticalJustify() const
KIGFX::CROSS_HAIR_MODE m_crossHairMode
Crosshair drawing mode.
VECTOR2D m_lookAtPoint
Point to be looked at in world space.
GAL(GAL_DISPLAY_OPTIONS &aOptions)
GLuint cacheBitmap(const BITMAP_BASE *aBitmap)
const size_t m_cacheMaxElements
GLuint RequestBitmap(const BITMAP_BASE *aBitmap)
std::list< GLuint > m_freedTextureIds
const size_t m_cacheMaxSize
std::map< const KIID, CACHED_BITMAP > m_bitmaps
std::list< KIID > m_cacheLru
static const unsigned int DIRECT_RENDERING
OpenGL implementation of the Graphics Abstraction Layer.
void Transform(const MATRIX3x3D &aTransformation) override
Transform the context.
void drawPolygon(GLdouble *aPoints, int aPointCount)
Draw a filled polygon.
void ChangeGroupDepth(int aGroupNumber, int aDepth) override
Change the depth (Z-axis position) of the group.
void skipMouseEvent(wxMouseEvent &aEvent)
Skip the mouse event to the parent.
void drawSegment(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, double aWidth, bool aReserve=true)
Internal method for segment drawing.
unsigned int m_groupCounter
Counter used for generating keys for groups.
void EndDiffLayer() override
Ends rendering of a differential layer.
VERTEX_MANAGER * m_overlayManager
Container for storing overlaid VERTEX_ITEMs.
void Scale(const VECTOR2D &aScale) override
Scale the context.
bool m_isInitialized
Basic initialization flag, has to be done when the window is visible.
VERTEX_MANAGER * m_currentManager
Currently used VERTEX_MANAGER (for storing VERTEX_ITEMs).
void drawCircle(const VECTOR2D &aCenterPoint, double aRadius, bool aReserve=true)
Internal method for circle drawing.
std::deque< std::shared_ptr< GLdouble > > m_tessIntersects
void DrawEllipseArc(const VECTOR2D &aCenterPoint, double aMajorRadius, double aMinorRadius, const EDA_ANGLE &aRotation, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle) override
Draw an elliptical arc in world coordinates.
void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius) override
Draw a circle using world coordinates.
bool IsInitialized() const override
Return the initialization status for the canvas.
void LockContext(int aClientCookie) override
Use GAL_CONTEXT_LOCKER RAII object unless you know what you're doing.
WX_CURSOR_TYPE m_currentwxCursor
wx cursor showing the current native cursor.
unsigned int m_mainBuffer
Main rendering target.
std::unique_ptr< GL_BITMAP_CACHE > m_bitmapCache
std::pair< VECTOR2D, float > computeBitmapTextSize(const UTF8 &aText) const
Compute a size of text drawn using bitmap font with current text setting applied.
void SetTarget(RENDER_TARGET aTarget) override
Set the target for rendering.
void blitCursor()
Blit cursor into the current screen.
static wxString CheckFeatures(GAL_DISPLAY_OPTIONS &aOptions)
Checks OpenGL features.
void ClearTarget(RENDER_TARGET aTarget) override
Clear the target for rendering.
void drawBitmapOverbar(double aLength, double aHeight, bool aReserve=true)
Draw an overbar over the currently drawn text.
void EndGroup() override
End the group.
bool m_isBitmapFontInitialized
Is the shader set to use bitmap fonts?
void drawSegmentChain(const std::function< VECTOR2D(int)> &aPointGetter, int aPointCount, double aWidth, bool aReserve=true)
Generic way of drawing a chain of segments stored in different containers.
void DrawArcSegment(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle, double aWidth, double aMaxError) override
Draw an arc segment.
void BitmapText(const wxString &aText, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle) override
Draw a text using a bitmap font.
bool updatedGalDisplayOptions(const GAL_DISPLAY_OPTIONS &aOptions) override
Handle updating display options.
unsigned int m_overlayBuffer
Auxiliary rendering target (for menus etc.)
void PostPaint(wxPaintEvent &aEvent)
Post an event to #m_paint_listener.
OPENGL_COMPOSITOR * m_compositor
Handles multiple rendering targets.
VERTEX_MANAGER * m_cachedManager
Container for storing cached VERTEX_ITEMs.
void Translate(const VECTOR2D &aTranslation) override
Translate the context.
void DrawPolyline(const std::deque< VECTOR2D > &aPointList) override
Draw a polyline.
bool SetNativeCursorStyle(KICURSOR aCursor, bool aHiDPI) override
Set the cursor in the native panel.
void DrawCurve(const VECTOR2D &startPoint, const VECTOR2D &controlPointA, const VECTOR2D &controlPointB, const VECTOR2D &endPoint, double aFilterValue=0.0) override
Draw a cubic bezier spline.
void drawFilledSemiCircle(const VECTOR2D &aCenterPoint, double aRadius, double aAngle)
Draw a filled semicircle.
void onPaint(wxPaintEvent &aEvent)
This is the OnPaint event handler.
void DrawGroup(int aGroupNumber) override
Draw the stored group.
GLint ufm_minLinePixelWidth
void Restore() override
Restore the context.
void DrawSegmentChain(const std::vector< VECTOR2D > &aPointList, double aWidth) override
Draw a chain of rounded segments.
void drawStrokedSemiCircle(const VECTOR2D &aCenterPoint, double aRadius, double aAngle, bool aReserve=true)
Draw a stroked semicircle.
unsigned int getNewGroupNumber()
Return a valid key that can be used as a new group number.
void Flush() override
Force all remaining objects to be drawn.
GLint ufm_antialiasingOffset
void DeleteGroup(int aGroupNumber) override
Delete the group from the memory.
bool IsVisible() const override
Return true if the GAL canvas is visible on the screen.
wxEvtHandler * m_mouseListener
int m_swapInterval
Used to store swap interval information.
void ClearCache() override
Delete all data created during caching of graphic items.
double getWorldPixelSize() const
void DrawSegment(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, double aWidth) override
Draw a rounded segment.
GROUPS_MAP m_groups
Stores information about VBO objects (groups)
void endUpdate() override
void ClearScreen() override
Clear the screen.
void ResizeScreen(int aWidth, int aHeight) override
Resizes the canvas.
GLint ufm_fontTextureWidth
void DrawPolygon(const std::deque< VECTOR2D > &aPointList) override
Draw a polygon.
void drawTriangulatedPolyset(const SHAPE_POLY_SET &aPoly, bool aStrokeTriangulation)
Draw a set of polygons with a cached triangulation.
void DrawCursor(const VECTOR2D &aCursorPosition) override
Draw the cursor.
void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint) override
Draw a rectangle.
VERTEX_MANAGER * m_nonCachedManager
Container for storing non-cached VERTEX_ITEMs.
int drawBitmapChar(unsigned long aChar, bool aReserve=true)
Draw a single character using bitmap font.
GLUtesselator * m_tesselator
wxEvtHandler * m_paintListener
void StartDiffLayer() override
Begins rendering of a differential layer.
void drawGridCoverageShape(const GRID_SOURCE &aSrc)
Fill a source's coverage region into the current color/stencil state.
bool m_isContextLocked
Used for assertion checking.
void Save() override
Save the context.
void DrawHoleWall(const VECTOR2D &aCenterPoint, double aHoleRadius, double aWallWidth) override
Draw a hole wall ring.
bool m_isFramebufferInitialized
Are the framebuffers initialized?
void ComputeWorldScreenMatrix() override
Compute the world <-> screen transformation matrix.
bool Show(bool aShow) override
Shows/hides the GAL canvas.
void SetMinLineWidth(float aLineWidth) override
Set the minimum line width in pixels.
static GLuint g_fontTexture
Bitmap font texture handle (shared)
virtual bool HasTarget(RENDER_TARGET aTarget) override
Return true if the target exists.
bool GetScreenshot(wxImage &aDstImage)
Parameters passed to the GLU tesselator.
void reserveLineQuads(const int aLineCount)
Reserve specified number of line quads.
void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint) override
Draw a line.
OPENGL_GAL(const KIGFX::VC_SETTINGS &aVcSettings, GAL_DISPLAY_OPTIONS &aDisplayOptions, wxWindow *aParent, wxEvtHandler *aMouseListener=nullptr, wxEvtHandler *aPaintListener=nullptr, const wxString &aName=wxT("GLCanvas"))
void beginUpdate() override
void DrawEllipse(const VECTOR2D &aCenterPoint, double aMajorRadius, double aMinorRadius, const EDA_ANGLE &aRotation) override
Draw a closed ellipse.
double calcAngleStep(double aRadius) const
Compute the angle step when drawing arcs/circles approximated with lines.
virtual void DrawGlyph(const KIFONT::GLYPH &aGlyph, int aNth, int aTotal) override
Draw a polygon representing a font glyph.
bool m_isGrouping
Was a group started?
void BeginDrawing() override
Start/end drawing functions, draw calls can be only made in between the calls to BeginDrawing()/EndDr...
GLint ufm_screenPixelSize
void Rotate(double aAngle) override
Rotate the context.
int BeginGroup() override
Begin a group.
GLint ufm_pixelSizeMultiplier
VECTOR2D getScreenPixelSize() const
void drawGridSources()
Render m_gridSources priority-descending; each writes its coverage into the stencil so lower-priority...
void DrawBitmap(const BITMAP_BASE &aBitmap, double alphaBlend=1.0) override
Draw a bitmap image.
void drawPolyline(const std::function< VECTOR2D(int)> &aPointGetter, int aPointCount, bool aReserve=true)
Generic way of drawing a polyline stored in different containers.
RENDER_TARGET GetTarget() const override
Get the currently used target for rendering.
void skipGestureEvent(wxGestureEvent &aEvent)
Skip the gesture event to the parent.
void UnlockContext(int aClientCookie) override
void drawSemiCircle(const VECTOR2D &aCenterPoint, double aRadius, double aAngle)
Draw a semicircle.
void drawLineQuad(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, bool aReserve=true)
Draw a quad for the line.
VERTEX_MANAGER * m_tempManager
Container for storing temp (diff mode) VERTEX_ITEMs.
virtual void DrawGlyphs(const std::vector< std::unique_ptr< KIFONT::GLYPH > > &aGlyphs) override
Draw polygons representing font glyphs.
void onSetNativeCursor(wxSetCursorEvent &aEvent)
Give the correct cursor image when the native widget asks for it.
void EnableDepthTest(bool aEnabled=false) override
void EndDrawing() override
End the drawing, needs to be called for every new frame.
SHADER * m_shader
There is only one shader used for different objects.
void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle) override
Draw an arc.
void DrawPolylines(const std::vector< std::vector< VECTOR2D > > &aPointLists) override
Draw multiple polylines.
RENDER_TARGET m_currentTarget
Current rendering target.
wxGLContext * m_glPrivContext
Canvas-specific OpenGL context.
void ChangeGroupColor(int aGroupNumber, const COLOR4D &aNewColor) override
Change the color used to draw the group.
static bool m_isBitmapFontLoaded
Is the bitmap font texture loaded?
static wxGLContext * m_glMainContext
Parent OpenGL context.
void setupShaderParameters()
Set up the shader parameters for OpenGL rendering.
unsigned int m_tempBuffer
Temporary rendering target (for diffing etc.)
void init()
Basic OpenGL initialization and feature checks.
static int m_instanceCounter
GL GAL instance counter.
Provide the access to the OpenGL shaders.
Class to control vertex container and GPU with possibility of emulating old-style OpenGL 1....
bool Vertex(const VERTEX &aVertex)
Add a vertex with the given coordinates to the currently set item.
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
GL_CONTEXT_MANAGER * GetGLContextManager()
A small class to help profiling.
void Stop()
Save the time when this function was called, and set the counter stane to stop.
void Start()
Start or restart the counter.
double msecs(bool aSinceLast=false)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsClosed() const override
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
size_t GetTriangleCount() const
void GetTriangle(int index, VECTOR2I &a, VECTOR2I &b, VECTOR2I &c) const
Represent a set of closed polygons.
bool IsTriangulationUpToDate() const
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
const TRIANGULATED_POLYGON * TriangulatedPolygon(int aIndex) const
unsigned int TriangulatedPolyCount() const
Return the number of triangulated polygons.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
uni_iter is a non-mutating iterator that walks through unicode code points in the UTF8 encoded string...
An 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to and fro...
uni_iter uend() const
Return a uni_iter initialized to the end of "this" UTF8 byte sequence.
uni_iter ubegin() const
Returns a uni_iter initialized to the start of "this" UTF8 byte sequence.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
static constexpr EDA_ANGLE FULL_CIRCLE
a few functions useful in geometry calculations.
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
const wxChar *const traceGalProfile
Flag to enable debug output of GAL performance profiling.
This file contains miscellaneous commonly used macros and functions.
MATRIX3x3< double > MATRIX3x3D
const FONT_GLYPH_TYPE * LookupGlyph(unsigned int aCodepoint)
FONT_INFO_TYPE font_information
GAL_API FONT_IMAGE_TYPE font_image
The Cairo implementation of the graphics abstraction layer.
constexpr double GRID_DIM_ALPHA
Opacity of the background wash laid over a selected grid item's area, to fade the grids showing throu...
@ SMALL_CROSS
Use small cross instead of dots for the grid.
@ DOTS
Use dots for the grid.
@ LINES
Use lines for the grid.
constexpr double GRID_SELECTED_BRIGHTEN
How far the grid being edited is lifted above its own colour.
@ SHADER_TYPE_VERTEX
Vertex shader.
@ SHADER_TYPE_FRAGMENT
Fragment shader.
double AutoSparsePitch(double aPitch, unsigned aTick, double aThreshold)
Multiply aPitch by aTick until it exceeds aThreshold, so a sub-threshold grid still shows every Nth l...
RENDER_TARGET
RENDER_TARGET: Possible rendering targets.
@ TARGET_NONCACHED
Auxiliary rendering target (noncached)
@ TARGET_TEMP
Temporary target for drawing in separate layer.
@ TARGET_CACHED
Main rendering target (cached)
@ TARGET_OVERLAY
Items that may change while the view stays the same (noncached)
constexpr double GRID_EDGE_DARKEN
How far the hairline round a grid's coverage sits below its own colour.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
static const wxChar *const traceGalXorMode
static void InitTesselatorCallbacks(GLUtesselator *aTesselator)
void CALLBACK CombineCallback(GLdouble coords[3], GLdouble *vertex_data[4], GLfloat weight[4], GLdouble **dataOut, void *aData)
void CALLBACK VertexCallback(GLvoid *aVertexPtr, void *aData)
void CALLBACK EdgeCallback(GLboolean aEdgeFlag)
static wxGLAttributes getGLAttribs()
void CALLBACK ErrorCallback(GLenum aErrorCode)
double round_to_half_pixel(double f, double r)
#define SEG_PER_CIRCLE_COUNT
#define CALLBACK
The default number of points for circle approximation.
PGM_BASE & Pgm()
The global program "get" accessor.
std::vector< FAB_LAYER_COLOR > dummy
unsigned priority
Higher wins where grids overlap.
double orientation
Rotation about origin, radians CCW.
VECTOR2D extent
Cartesian: (dx, dy) = size/2 from origin.
VECTOR2D pitch
Cartesian: (dx, dy); polar: (dr, dPhi rad).
Render-time projection of a grid: GRID_GEOMETRY (kind/origin/pitch/orientation/extent) plus rendering...
unsigned tick
Major-tick interval (0 = inherit default).
bool axesEnabled
Skip grid lines coincident with the world axes (only meaningful for unbounded cartesian).
bool highlighted
Render with edit-mode emphasis (selected grid).
bool unbounded
No extent; visible range derived from screen corners.
VERTEX_MANAGER * vboManager
Manager used for storing new vertices.
std::deque< std::shared_ptr< GLdouble > > & intersectPoints
Intersect points, that have to be freed after tessellation.
Structure to keep VIEW_CONTROLS settings for easy store/restore operations.
@ GR_TEXT_H_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_INDETERMINATE
wxLogTrace helper definitions.
void enableGlDebug(bool aEnable)
Enable or disable OpenGL driver messages output.
int checkGlError(const std::string &aInfo, const char *aFile, int aLine, bool aThrow)
Check if a recent OpenGL operation has failed.
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D
VECTOR2I ToVECTOR2I(const wxSize &aSize)