90 cairo_surface_destroy( imageSurface );
137 world_rotation = M_PI - world_rotation;
139 return std::fmod( aAngle + world_rotation, 2.0 * M_PI );
146 bool is_360deg_arc =
std::abs( aEndAngle - aStartAngle ) >= 2 * M_PI;
147 double startAngle = aStartAngle;
148 double endAngle = aEndAngle;
154 startAngle = M_PI - startAngle;
155 endAngle = M_PI - endAngle;
159 SWAP( startAngle, >, endAngle );
171 aEndAngle = aStartAngle + 2 * M_PI;
181 return sqrt( dx * dx + dy * dy );
187 return floor( x + 0.5 ) + 0.5;
196 return VECTOR2D( floor( v.
x + 0.5 ), floor( v.
y + 0.5 ) );
240 for(
size_t i = 0; i + 1 < aPointList.size(); ++i )
241 DrawSegment( aPointList[i], aPointList[i + 1], aWidth );
252 for(
int i = 0; i + 1 < numPoints; ++i )
280 VECTOR2D startEndVector = aEndPoint - aStartPoint;
281 double lineAngle = atan2( startEndVector.
y, startEndVector.
x );
283 double sa = sin( lineAngle + M_PI / 2.0 );
284 double ca = cos( lineAngle + M_PI / 2.0 );
304 startEndVector = center_b - center_a;
305 lineAngle = atan2( startEndVector.
y, startEndVector.
x );
309 double arcStartAngle = lineAngle - M_PI / 2.0;
311 arcStartAngle + M_PI );
314 arcStartAngle = lineAngle + M_PI / 2.0;
316 arcStartAngle + M_PI );
346 double startAngle = aStartAngle.
AsRadians();
353 double r =
xform( aRadius );
382 double aWidth,
double aMaxError )
390 DrawArc( aCenterPoint, aRadius, aStartAngle, aEndAngle );
400 double startAngleS = aStartAngle.
AsRadians();
401 double endAngleS = aEndAngle.
AsRadians();
404 double r =
xform( aRadius );
413 double width =
xform( aWidth / 2.0 );
433 cairo_arc_negative(
m_currentContext, startPointS.
x, startPointS.
y, width, startAngleS,
434 startAngleS + M_PI );
437 cairo_arc(
m_currentContext, endPointS.
x, endPointS.
y, width, endAngleS, endAngleS + M_PI );
483 double aFilterValue )
507 alphaBlend = std::clamp( alphaBlend, 0.0, 1.0 );
523 cairo_surface_t*
image = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, w, h );
524 cairo_surface_flush(
image );
526 unsigned char* pix_buffer = cairo_image_surface_get_data(
image );
531 uint32_t mask_color = ( bm_pix_buffer.GetMaskRed() << 16 )
532 + ( bm_pix_buffer.GetMaskGreen() << 8 ) + ( bm_pix_buffer.GetMaskBlue() );
537 for(
int row = 0; row < h; row++ )
539 for(
int col = 0; col < w; col++ )
542 uint32_t pixel = bm_pix_buffer.GetRed( col, row ) << 16;
543 pixel += bm_pix_buffer.GetGreen( col, row ) << 8;
544 pixel += bm_pix_buffer.GetBlue( col, row );
546 if( bm_pix_buffer.HasAlpha() )
547 pixel += bm_pix_buffer.GetAlpha( col, row ) << 24;
548 else if( bm_pix_buffer.HasMask() && pixel == mask_color )
549 pixel += ( wxALPHA_TRANSPARENT << 24 );
551 pixel += ( wxALPHA_OPAQUE << 24 );
554 uint32_t* pix_ptr = (uint32_t*) pix_buffer;
560 cairo_surface_mark_dirty(
image );
687 cairo_matrix_t cairoTransformation, newXform;
689 cairo_matrix_init( &cairoTransformation, aTransformation.
m_data[0][0],
690 aTransformation.
m_data[1][0], aTransformation.
m_data[0][1],
691 aTransformation.
m_data[1][1], aTransformation.
m_data[0][2],
692 aTransformation.
m_data[1][2] );
694 cairo_matrix_multiply( &newXform, &
m_currentXform, &cairoTransformation );
829 for(
auto it =
m_groups[aGroupNumber].begin(); it !=
m_groups[aGroupNumber].end(); ++it )
831 switch( it->m_Command )
843 it->m_Argument.DblArg[2], it->m_Argument.DblArg[3] );
848 it->m_Argument.DblArg[2], it->m_Argument.DblArg[3] );
854 double x = 1.0, y = 1.0;
856 double minWidth = std::min( fabs( x ), fabs( y ) );
858 std::max( it->m_Argument.DblArg[0], minWidth ) );
892 cairo_translate(
m_currentContext, it->m_Argument.DblArg[0], it->m_Argument.DblArg[1] );
896 cairo_scale(
m_currentContext, it->m_Argument.DblArg[0], it->m_Argument.DblArg[1] );
919 for(
auto it =
m_groups[aGroupNumber].begin(); it !=
m_groups[aGroupNumber].end(); ++it )
923 it->m_Argument.DblArg[0] = aNewColor.
r;
924 it->m_Argument.DblArg[1] = aNewColor.
g;
925 it->m_Argument.DblArg[2] = aNewColor.
b;
926 it->m_Argument.DblArg[3] = aNewColor.
a;
944 std::deque<GROUP_ELEMENT>::iterator it, end;
946 for( it =
m_groups[aGroupNumber].begin(), end =
m_groups[aGroupNumber].end(); it != end; ++it )
949 cairo_path_destroy( it->m_CairoPath );
966 cairo_set_operator(
m_currentContext, aSetting ? CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_OVER );
1010 cairo_surface_destroy( imageSurface );
1096 double sw = std::max( 1.0, aWidth );
1097 double sh = std::max( 1.0, aHeight );
1102 p.
y - std::floor( sh / 2 ) - 0.5, sw, sh );
1194 wxColour
color( cColor.
r * cColor.
a * 255, cColor.
g * cColor.
a * 255, cColor.
b * cColor.
a * 255,
1196 clientDC.SetPen( wxPen(
color ) );
1197 clientDC.DrawLine( p.
x - cursorSize / 2, p.
y, p.
x + cursorSize / 2, p.
y );
1198 clientDC.DrawLine( p.
x, p.
y - cursorSize / 2, p.
x, p.
y + cursorSize / 2 );
1204 wxCHECK( aPointList.size() > 1, );
1207 std::deque<VECTOR2D>::const_iterator it = aPointList.begin();
1215 for( ++it; it != aPointList.end(); ++it )
1229 wxCHECK( aPointList.size() > 1, );
1232 std::vector<VECTOR2D>::const_iterator it = aPointList.begin();
1240 for( ++it; it != aPointList.end(); ++it )
1254 wxCHECK( aListSize > 1, );
1264 for(
int i = 1; i < aListSize; ++i )
1291 for(
int i = 1; i < numPoints; ++i )
1305 wxASSERT_MSG(
m_groups.size() < std::numeric_limits<unsigned int>::max(),
1306 wxT(
"There are no free slots to store a group" ) );
1316 wxEvtHandler* aMouseListener, wxEvtHandler* aPaintListener,
1317 const wxString& aName ) :
1319 wxWindow( aParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxEXPAND, aName )
1362#if defined _WIN32 || defined _WIN64
1366 SetSize( aParent->GetClientSize() );
1406 pixman_image_t* dstImg = pixman_image_create_bits(
1407 wxPlatformInfo::Get().GetEndianness() == wxENDIAN_LITTLE ? PIXMAN_b8g8r8
1410 pixman_image_t* srcImg =
1414 pixman_image_composite( PIXMAN_OP_SRC, srcImg,
nullptr, dstImg, 0, 0, 0, 0, 0, 0,
1418 pixman_image_unref( srcImg );
1419 pixman_image_unref( dstImg );
1422 wxBitmap bmp( img );
1423 wxMemoryDC mdc( bmp );
1424 wxClientDC clientDC(
this );
1455 SetSize( wxSize( aWidth, aHeight ) );
1461 bool s = wxWindow::Show( aShow );
1517 unsigned int currentBuffer =
m_compositor->GetBuffer();
1547 cairo_status_t status = cairo_status(
m_context );
1548 wxASSERT_MSG( status == CAIRO_STATUS_SUCCESS, wxT(
"Cairo context creation error" ) );
1690 float doubleMarker = 2.0f * marker;
1696 drawAxes( worldStartPoint, worldEndPoint );
1707 gridThreshold *= 2.0;
1711 while( std::min( gridScreenSize.
x, gridScreenSize.
y ) <= gridThreshold )
1713 gridScreenSize = gridScreenSize *
static_cast<double>(
m_gridTick );
1725 SWAP( gridStartX, >, gridEndX );
1726 SWAP( gridStartY, >, gridEndY );
1742 for(
int j = gridStartY; j <= gridEndY; j++ )
1755 for(
int i = gridStartX; i <= gridEndX; i++ )
1772 for(
int j = gridStartY; j <= gridEndY; j++ )
1776 for(
int i = gridStartX; i <= gridEndX; i++ )
1784 SetLineWidth( ( tickX && tickY ) ? doubleMarker : marker );
1805 for(
const std::vector<VECTOR2D>& pointList : glyph )
1844 if( aNth == aTotal - 1 )
Class that handles multitarget rendering (ie.
static double roundp(double x)
This class handle bitmap images in KiCad.
VECTOR2I GetSizePixels() const
static const wxCursor GetCursor(KICURSOR aCursorType)
virtual bool IsStroke() const
virtual bool IsOutline() const
void Triangulate(std::function< void(const VECTOR2I &aPt1, const VECTOR2I &aPt2, const VECTOR2I &aPt3)> aCallback) const
void DrawGlyph(const KIFONT::GLYPH &aPolySet, int aNth, int aTotal) override
Draw a polygon representing a font glyph.
void blitCursor(wxMemoryDC &clientDC)
Blit cursor into the current screen.
void drawGridLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
Draw a grid line (usually a simplified line function).
cairo_surface_t * m_surface
Cairo surface.
cairo_matrix_t m_cairoWorldScreenMatrix
Cairo world to screen transform matrix.
void Flush() override
Force all remaining objects to be drawn.
void BeginDrawing() override
Start/end drawing functions, draw calls can be only made in between the calls to BeginDrawing()/EndDr...
void Restore() override
Restore the context.
unsigned int m_groupCounter
Counter used for generating group keys.
void Translate(const VECTOR2D &aTranslation) override
Translate the context.
void Save() override
Save the context.
void ClearCache() override
Delete all data created during caching of graphic items.
bool m_isElementAdded
Was an graphic element added ?
const double xform(double x)
void DeleteGroup(int aGroupNumber) override
Delete the group from the memory.
std::deque< GROUP_ELEMENT > GROUP
A graphic group type definition.
void DrawLine(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint) override
Draw a line.
void ClearScreen() override
Clear the screen.
void storePath()
Store the actual path.
void DrawGroup(int aGroupNumber) override
Draw the stored group.
void drawAxes(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint)
std::vector< cairo_surface_t * > m_imageSurfaces
List of surfaces that were created by painting images, to be cleaned up later.
void DrawArc(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle) override
Draw an arc.
void SetFillColor(const COLOR4D &aColor) override
Set the fill color.
GROUP * m_currentGroup
Currently used group.
void DrawCursor(const VECTOR2D &aCursorPosition) override
Draw the cursor.
const VECTOR2D roundp(const VECTOR2D &v)
bool m_isGrouping
Is grouping enabled ?
static constexpr cairo_format_t GAL_FORMAT
Format used to store pixels.
void SetNegativeDrawMode(bool aSetting) override
Set negative draw mode in the renderer.
void ChangeGroupDepth(int aGroupNumber, int aDepth) override
Change the depth (Z-axis position) of the group.
int BeginGroup() override
Begin a group.
void SetLayerDepth(double aLayerDepth) override
Set the depth of the layer (position on the z-axis)
unsigned int getNewGroupNumber()
Return a valid key that can be used as a new group number.
cairo_matrix_t m_currentXform
void SetIsStroke(bool aIsStrokeEnabled) override
Enable/disable stroked outlines.
void EndGroup() override
End the group.
void drawPoly(const std::deque< VECTOR2D > &aPointList)
Drawing polygons & polylines is the same in Cairo, so here is the common code.
void Transform(const MATRIX3x3D &aTransformation) override
Transform the context.
void DrawRectangle(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint) override
Draw a rectangle.
void ChangeGroupColor(int aGroupNumber, const COLOR4D &aNewColor) override
Change the color used to draw the group.
std::map< int, GROUP > m_groups
List of graphic groups.
void SetStrokeColor(const COLOR4D &aColor) override
Set the stroke color.
cairo_t * m_context
Cairo image.
void EndDrawing() override
End the drawing, needs to be called for every new frame.
void updateWorldScreenMatrix()
void EnableDepthTest(bool aEnabled=false) override
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 Scale(const VECTOR2D &aScale) override
Scale the context.
std::vector< cairo_matrix_t > m_xformStack
void DrawPolygon(const std::deque< VECTOR2D > &aPointList) override
Draw a polygon.
void DrawArcSegment(const VECTOR2D &aCenterPoint, double aRadius, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle, double aWidth, double aMaxError) override
Draw an arc segment.
cairo_matrix_t m_currentWorld2Screen
void drawGridCross(const VECTOR2D &aPoint)
void SetLineWidth(float aLineWidth) override
Set the line width.
void arc_angles_xform_and_normalize(double &aStartAngle, double &aEndAngle)
Transform according to the rotation from m_currentWorld2Screen transform matrix for the start angle a...
void syncLineWidth(bool aForceWidth=false, double aWidth=0.0)
cairo_t * m_currentContext
Currently used Cairo context for drawing.
void DrawCircle(const VECTOR2D &aCenterPoint, double aRadius) override
Draw a circle using world coordinates.
const double angle_xform(const double aAngle)
Transform according to the rotation from m_currentWorld2Screen transform matrix.
void DrawSegment(const VECTOR2D &aStartPoint, const VECTOR2D &aEndPoint, double aWidth) override
Draw a rounded segment.
void drawGridPoint(const VECTOR2D &aPoint, double aWidth, double aHeight)
void SetIsFill(bool aIsFillEnabled) override
Enable/disable fill.
void DrawBitmap(const BITMAP_BASE &aBitmap, double alphaBlend=1.0) override
Draw a bitmap image.
@ CMD_SET_STROKE
Enable/disable stroking.
@ CMD_SAVE
Save the transformation matrix.
@ CMD_SCALE
Scale the context.
@ CMD_SET_LINE_WIDTH
Set the line width.
@ CMD_SET_FILL
Enable/disable filling.
@ CMD_CALL_GROUP
Call a group.
@ CMD_ROTATE
Rotate the context.
@ CMD_STROKE_PATH
Set the stroke path.
@ CMD_TRANSLATE
Translate the context.
@ CMD_SET_FILLCOLOR
Set the fill color.
@ CMD_FILL_PATH
Set the fill path.
@ CMD_RESTORE
Restore the transformation matrix.
@ CMD_SET_STROKECOLOR
Set the stroke color.
void ResizeScreen(int aWidth, int aHeight) override
Resizes the canvas.
void Rotate(double aAngle) override
Rotate the context.
void DrawSegmentChain(const std::vector< VECTOR2D > &aPointList, double aWidth) override
Draw a chain of rounded segments.
double m_lineWidthInPixels
void EndGroup() override
End the group.
void deinitSurface()
Destroy Cairo surfaces when are not needed anymore.
void PostPaint(wxPaintEvent &aEvent)
Post an event to m_paint_listener.
bool Show(bool aShow) override
Show/hide the GAL canvas.
void SetTarget(RENDER_TARGET aTarget) override
Set the target for rendering.
wxCursor m_currentwxCursor
wxCursor showing the current native cursor
void skipMouseEvent(wxMouseEvent &aEvent)
Mouse event handler, forwards the event to the child.
unsigned int m_overlayBuffer
Handle to the overlay buffer.
unsigned int m_bufferSize
Size of buffers cairoOutput, bitmapBuffers.
CAIRO_GAL(GAL_DISPLAY_OPTIONS &aDisplayOptions, wxWindow *aParent, wxEvtHandler *aMouseListener=nullptr, wxEvtHandler *aPaintListener=nullptr, const wxString &aName=wxT("CairoCanvas"))
void initSurface()
Prepare Cairo surfaces for drawing.
int BeginGroup() override
Begin a group.
bool SetNativeCursorStyle(KICURSOR aCursor) override
Set the cursor in the native panel.
unsigned char * m_wxOutput
wxImage compatible buffer
bool m_isInitialized
Are Cairo image & surface ready to use.
bool m_validCompositor
Compositor initialization flag.
unsigned int m_mainBuffer
Handle to the main buffer.
int m_stride
Stride value for Cairo.
void onSetNativeCursor(wxSetCursorEvent &aEvent)
Give the correct cursor image when the native widget asks for it.
void EndDrawing() override
End the drawing, needs to be called for every new frame.
void allocateBitmaps()
Allocate the bitmaps for drawing.
void onPaint(wxPaintEvent &aEvent)
Paint event handler.
void StartNegativesLayer() override
Begins rendering in a new layer that will be copied to the main layer in EndNegativesLayer().
void ResizeScreen(int aWidth, int aHeight) override
Resizes the canvas.
RENDER_TARGET GetTarget() const override
Get the currently used target for rendering.
void setCompositor()
Prepare the compositor.
unsigned char * m_bitmapBuffer
Storage of the Cairo image.
wxEvtHandler * m_mouseListener
Mouse listener.
void ClearTarget(RENDER_TARGET aTarget) override
Clear the target for rendering.
bool updatedGalDisplayOptions(const GAL_DISPLAY_OPTIONS &aOptions) override
Handle updating display options.
~CAIRO_GAL()
Return true if the GAL canvas is visible on the screen.
void BeginDrawing() override
Start/end drawing functions, draw calls can be only made in between the calls to BeginDrawing()/EndDr...
wxEvtHandler * m_paintListener
Paint listener.
unsigned int m_tempBuffer
Handle to the temp buffer.
RENDER_TARGET m_currentTarget
Current rendering target.
wxWindow * m_parentWindow
Parent window.
void EndDiffLayer() override
Ends rendering of a differential layer.
std::shared_ptr< CAIRO_COMPOSITOR > m_compositor
Object for layers compositing.
void deleteBitmaps()
Allocate the bitmaps for drawing.
void EndNegativesLayer() override
Ends rendering of a negatives layer and draws it to the main layer.
void StartDiffLayer() override
Begins rendering of a differential layer.
unsigned int m_savedBuffer
Handle to buffer to restore after rendering to temp buffer.
A color representation with 4 components: red, green, blue, alpha.
static const COLOR4D BLACK
CAIRO_ANTIALIASING_MODE cairo_antialiasing_mode
Abstract interface for drawing on a 2D-surface.
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.
MATRIX3x3D m_worldScreenMatrix
World transformation.
MATRIX3x3D m_screenWorldMatrix
Screen transformation.
bool m_axesEnabled
Should the axes be drawn.
float m_gridLineWidth
Line width of the grid.
VECTOR2I m_screenSize
Screen size in screen coordinates.
VECTOR2D m_depthRange
Range of the depth.
VECTOR2D ToScreen(const VECTOR2D &aPoint) const
Compute the point position in screen coordinates from given world coordinates.
GRID_STYLE m_gridStyle
Grid display style.
COLOR4D m_axesColor
Color of the axes.
float m_lineWidth
The line width.
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.
VECTOR2D m_cursorPosition
Current cursor position (world coordinates)
int m_gridTick
Every tick line gets the double width.
double m_worldScale
The scale factor world->screen.
virtual bool SetNativeCursorStyle(KICURSOR aCursor)
Set the cursor in the native panel.
VECTOR2D m_gridOrigin
The grid origin.
KICURSOR m_currentNativeCursor
Current cursor.
bool m_fullscreenCursor
Shape of the cursor (fullscreen or small cross)
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 ?
GAL_DISPLAY_OPTIONS & m_options
bool m_gridVisibility
Should the grid be shown.
virtual void SetTarget(RENDER_TARGET aTarget)
Set the target for rendering.
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.
Represent a set of closed polygons.
int OutlineCount() const
Return the number of vertices in a given outline/hole.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
#define SWAP(varA, condition, varB)
Swap the variables if a condition is met.
The Cairo implementation of the graphics abstraction layer.
@ SMALL_CROSS
Use small cross instead of dots for the grid.
@ DOTS
Use dots for the grid.
@ LINES
Use lines for the grid.
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)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
void Refresh()
Update the board display after modifying it by a python script (note: it is automatically called by a...
Type definition for an graphics group element.
GRAPHICS_COMMAND m_Command
Command to execute.
cairo_path_t * m_CairoPath
Pointer to a Cairo path.
double DblArg[MAX_CAIRO_ARGUMENTS]
Arguments for Cairo commands.
union KIGFX::CAIRO_GAL_BASE::GROUP_ELEMENT::@31 m_Argument
bool BoolArg
A bool argument.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
double EuclideanNorm(const VECTOR2I &vector)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
VECTOR2< double > VECTOR2D
VECTOR2I ToVECTOR2I(const wxSize &aSize)