KiCad PCB EDA Suite
Loading...
Searching...
No Matches
graphics_abstraction_layer.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KICAD, a free EDA CAD application.
3 *
4 * Copyright (C) 2012 Torsten Hueter, torstenhtr <at> gmx.de
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * Graphics Abstraction Layer (GAL) - base class
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23#include <wx/log.h>
24#include <advanced_config.h>
26#include <gal/definitions.h>
27#include <font/font.h>
28
31
32#include <math/util.h> // for KiROUND
33
34#include <cmath>
35
36using namespace KIGFX;
37
38
39GAL::GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions ) :
40 m_options( aDisplayOptions ),
41
42 // m_currentNativeCursor is initialized with KICURSOR::DEFAULT value to avoid
43 // if comparison with uninitialized value on SetNativeCursorStyle method.
44 // Some classes inheriting from GAL has different SetNativeCursorStyle method
45 // implementation and therefore it's called also on constructor
46 // to change the value from DEFAULT to KICURSOR::ARROW
48{
49 // Set the default values for the internal variables
50 SetIsFill( false );
51 SetIsStroke( true );
52 SetFillColor( COLOR4D( 0.0, 0.0, 0.0, 0.0 ) );
53 SetStrokeColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
54 SetLookAtPoint( VECTOR2D( 0, 0 ) );
55 SetZoomFactor( 1.0 );
56 SetRotation( 0.0 );
57
58 // this value for SetWorldUnitLength is only suitable for Pcbnew.
59 // Other editors/viewer must call SetWorldUnitLength with their internal units
60 SetWorldUnitLength( 1e-9 /* 1 nm */ / 0.0254 /* 1 inch in meters */ );
61
62 // wxDC::GetPPI() reports 96 DPI, but somehow this value
63 // is the closest match to the legacy renderer
64 SetScreenDPI( ADVANCED_CFG::GetCfg().m_ScreenDPI );
66 SetLayerDepth( 0.0 );
67 SetFlip( false, false );
68 SetLineWidth( 1.0f );
69 SetMinLineWidth( 1.0f );
71 SetAxesEnabled( false );
72
73 // Set grid defaults
74 SetGridVisibility( true );
75 SetCoarseGrid( 10 );
76 m_gridLineWidth = 0.5f;
79
80 // Initialize the cursor shape
81 SetCursorColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
84 SetCursorEnabled( false );
85
86 // Initialize the native widget to an arrow cursor
88
89 // Initialize text properties
91
92 // subscribe for settings updates
93 m_observerLink = m_options.Subscribe( this );
94}
95
96
98{
99}
100
101
103{
104 // defer to the child class first
105 updatedGalDisplayOptions( aOptions );
106
107 // there is no refresh to do at this level
108}
109
110
111void GAL::DrawEllipse( const VECTOR2D& aCenterPoint, double aMajorRadius, double aMinorRadius,
112 const EDA_ANGLE& aRotation )
113{
114 const VECTOR2I intCenter( KiROUND( aCenterPoint.x ), KiROUND( aCenterPoint.y ) );
115
116 SHAPE_ELLIPSE e( intCenter, KiROUND( aMajorRadius ), KiROUND( aMinorRadius ), aRotation );
117
118 SHAPE_LINE_CHAIN chain = e.ConvertToPolyline( std::max( 1, KiROUND( aMajorRadius / 500.0 ) ) );
120}
121
122
123void GAL::DrawEllipseArc( const VECTOR2D& aCenterPoint, double aMajorRadius, double aMinorRadius,
124 const EDA_ANGLE& aRotation, const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle )
125{
126 const VECTOR2I intCenter( KiROUND( aCenterPoint.x ), KiROUND( aCenterPoint.y ) );
127
128 SHAPE_ELLIPSE e( intCenter, KiROUND( aMajorRadius ), KiROUND( aMinorRadius ), aRotation, aStartAngle, aEndAngle );
129
130 SHAPE_LINE_CHAIN chain = e.ConvertToPolyline( std::max( 1, KiROUND( aMajorRadius / 500.0 ) ) );
132}
133
134
136{
137 bool refresh = false;
138
139 if( m_options.m_gridStyle != m_gridStyle )
140 {
141 m_gridStyle = m_options.m_gridStyle;
142 refresh = true;
143 }
144
145 if( m_options.m_gridLineWidth != m_gridLineWidth )
146 {
147 m_gridLineWidth = m_options.m_scaleFactor * m_options.m_gridLineWidth + 0.25;
148 refresh = true;
149 }
150
151 if( m_options.m_gridMinSpacing != m_gridMinSpacing )
152 {
153 m_gridMinSpacing = m_options.m_gridMinSpacing;
154 refresh = true;
155 }
156
157 if( m_options.m_axesEnabled != m_axesEnabled )
158 {
159 m_axesEnabled = m_options.m_axesEnabled;
160 refresh = true;
161 }
162
163 if( m_options.m_forceDisplayCursor != m_forceDisplayCursor )
164 {
165 m_forceDisplayCursor = m_options.m_forceDisplayCursor;
166 refresh = true;
167 }
168
169 if( m_options.GetCursorMode() != m_crossHairMode )
170 {
171 m_crossHairMode = m_options.GetCursorMode();
172 refresh = true;
173 }
174
175 // tell the derived class if the base class needs an update or not
176 return refresh;
177}
178
179
181{
182 // Tiny but non-zero - this will always need setting
183 // there is no built-in default
184 SetGlyphSize( { 1, 1 } );
185
188
189 SetFontBold( false );
190 SetFontItalic( false );
191 SetFontUnderlined( false );
192 SetTextMirrored( false );
193}
194
195
197{
199
200 MATRIX3x3D translation;
201 translation.SetIdentity();
202 // We're deliberately dividing integers to avoid fractional pixel offsets.
203 translation.SetTranslation( VECTOR2D( m_screenSize.x/2, m_screenSize.y/2 ) );
204
205 MATRIX3x3D rotate;
206 rotate.SetIdentity();
207 rotate.SetRotation( m_rotation );
208
210 scale.SetIdentity();
211 scale.SetScale( VECTOR2D( m_worldScale, m_worldScale ) );
212
213 MATRIX3x3D flip;
214 flip.SetIdentity();
215 flip.SetScale( VECTOR2D( m_globalFlipX ? -1.0 : 1.0, m_globalFlipY ? -1.0 : 1.0 ) );
216
217 MATRIX3x3D lookat;
218 lookat.SetIdentity();
219 lookat.SetTranslation( -m_lookAtPoint );
220
221 m_worldScreenMatrix = translation * rotate * flip * scale * lookat;
223}
224
225
227{
228 const MATRIX3x3D& matrix = GetScreenWorldMatrix();
229
230 VECTOR2D halfSize = VECTOR2D( matrix.GetScale().x * m_screenSize.x * 0.5,
231 matrix.GetScale().y * m_screenSize.y * 0.5 );
232
233 BOX2D extents;
234 extents.SetOrigin( GetLookAtPoint() - halfSize );
235 extents.SetSize( halfSize * 2 );
236
237 return extents;
238}
239
240
242{
243 // just return the current value. This could be cleverer and take
244 // into account other settings in future
245 return m_gridMinSpacing;
246}
247
248
249VECTOR2D GAL::GetGridPoint( const VECTOR2D& aPoint ) const
250{
251#if 0
252 // This old code expects a non zero grid size, which can be wrong here.
253 return VECTOR2D( KiROUND( ( aPoint.x - m_gridOffset.x ) / m_gridSize.x ) *
255 KiROUND( ( aPoint.y - m_gridOffset.y ) / m_gridSize.y ) *
256 m_gridSize.y + m_gridOffset.y );
257#else
258 // if grid size == 0.0 there is no grid, so use aPoint as grid reference position
259 double cx = m_gridSize.x > 0.0 ? KiROUND( ( aPoint.x - m_gridOffset.x ) / m_gridSize.x ) *
261 : aPoint.x;
262 double cy = m_gridSize.y > 0.0 ? KiROUND( ( aPoint.y - m_gridOffset.y ) / m_gridSize.y ) *
264 : aPoint.y;
265
266 return VECTOR2D( cx, cy );
267#endif
268}
269
270
271// MIN_DEPTH must be set to be - (VIEW::VIEW_MAX_LAYERS + abs(VIEW::TOP_LAYER_MODIFIER))
272// MAX_DEPTH must be set to be VIEW::VIEW_MAX_LAYERS + abs(VIEW::TOP_LAYER_MODIFIER) -1
273// VIEW_MAX_LAYERS and TOP_LAYER_MODIFIER are defined in view.h.
274// TOP_LAYER_MODIFIER is set as -VIEW_MAX_LAYERS
275// Currently KIGFX::VIEW::VIEW_MAX_LAYERS = MAX_LAYERS_FOR_VIEW
277const int GAL::MAX_DEPTH = 2*MAX_LAYERS_FOR_VIEW - 1;
278const int GAL::GRID_DEPTH = MAX_DEPTH - 1;
279
280
282{
283 COLOR4D color = m_cursorColor;
284
285 // dim the cursor if it's only on because it was forced
286 // (this helps to provide a hint for active tools)
287 if( !m_isCursorEnabled )
288 color.a = color.a * 0.5;
289
290 return color;
291}
292
293
294void GAL::BitmapText( const wxString& aText, const VECTOR2I& aPosition, const EDA_ANGLE& aAngle )
295{
297
298 if( aText.IsEmpty() )
299 return;
300
302 attrs.m_Angle = aAngle;
303 attrs.m_Mirrored = m_globalFlipX; // Prevent text flipping when view is flipped
304
305 // Bitmap font has different metrics than the stroke font so we compensate a bit before
306 // stroking
307 attrs.m_Size = VECTOR2I( m_attributes.m_Size.x, m_attributes.m_Size.y * 0.95 );
308 attrs.m_StrokeWidth = GetLineWidth() * 0.74;
309
310 font->Draw( this, aText, aPosition, attrs, KIFONT::METRICS::Default() );
311}
312
313
314bool GAL::SetNativeCursorStyle( KICURSOR aCursor, bool aHiDPI )
315{
316 if( m_currentNativeCursor == aCursor )
317 return false;
318
319 m_currentNativeCursor = aCursor;
320
321 return true;
322}
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
BOX2< VECTOR2D > BOX2D
Definition box2.h:919
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
constexpr void SetOrigin(const Vec &pos)
Definition box2.h:233
constexpr void SetSize(const SizeVec &size)
Definition box2.h:244
GAL(GAL_DISPLAY_OPTIONS &aOptions)
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:94
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition font.cpp:143
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttributes, const METRICS &aFontMetrics, std::optional< VECTOR2I > aMousePos=std::nullopt, wxString *aActiveUrl=nullptr) const
Draw a string.
Definition font.cpp:246
static const METRICS & Default()
Definition font.cpp:48
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
double a
Alpha component.
Definition color4d.h:392
virtual void SetLayerDepth(double aLayerDepth)
Set the depth of the layer (position on the z-axis)
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
virtual void DrawEllipseArc(const VECTOR2D &aCenterPoint, double aMajorRadius, double aMinorRadius, const EDA_ANGLE &aRotation, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aEndAngle)
Draw an elliptical arc in world coordinates.
bool m_isCursorEnabled
Is the cursor enabled?
BOX2D GetVisibleWorldExtents() const
MATRIX3x3D m_worldScreenMatrix
World transformation.
void SetVerticalJustify(const GR_TEXT_V_ALIGN_T aVerticalJustify)
void SetFontBold(const bool aBold)
MATRIX3x3D m_screenWorldMatrix
Screen transformation.
void SetFontUnderlined(bool aUnderlined)
void SetHorizontalJustify(const GR_TEXT_H_ALIGN_T aHorizontalJustify)
bool m_axesEnabled
Should the axes be drawn.
void SetRotation(double aRotation)
Get/set the rotation angle (in radians).
float m_gridLineWidth
Line width of the grid.
void SetFlip(bool xAxis, bool yAxis)
Sets flipping of the screen.
VECTOR2I m_screenSize
Screen size in screen (wx logical) coordinates.
virtual void SetFillColor(const COLOR4D &aColor)
Set the fill color.
void OnGalDisplayOptionsChanged(const GAL_DISPLAY_OPTIONS &aOptions) override
Handler for observer settings changes.
void SetCursorEnabled(bool aCursorEnabled)
Enable/disable cursor.
void SetAxesEnabled(bool aAxesEnabled)
Enable drawing the axes.
virtual bool SetNativeCursorStyle(KICURSOR aCursor, bool aHiDPI)
Set the cursor in the native panel.
GRID_STYLE m_gridStyle
Grid display style.
void SetCursorColor(const COLOR4D &aCursorColor)
Set the cursor color.
COLOR4D m_cursorColor
Cursor color.
int m_gridMinSpacing
Minimum screen size of the grid (pixels) below which the grid is not drawn.
const VECTOR2D & GetLookAtPoint() const
const MATRIX3x3D & GetScreenWorldMatrix() const
Get the screen <-> world transformation matrix.
void SetZoomFactor(double aZoomFactor)
void computeWorldScale()
Compute the scaling factor for the world->screen matrix.
TEXT_ATTRIBUTES m_attributes
void ResetTextAttributes()
Reset text attributes to default styling.
static const int MIN_DEPTH
Possible depth range.
virtual void SetLineWidth(float aLineWidth)
Set the line width.
double m_rotation
Rotation transformation (radians)
VECTOR2D m_gridSize
The grid size.
COLOR4D getCursorColor() const
Get the actual cursor color to draw.
void SetTextMirrored(const bool aMirrored)
virtual void DrawPolyline(const std::deque< VECTOR2D > &aPointList)
Draw a polyline.
void SetCoarseGrid(int aInterval)
Draw every tick line wider.
virtual bool updatedGalDisplayOptions(const GAL_DISPLAY_OPTIONS &aOptions)
Handle updating display options.
virtual void SetStrokeColor(const COLOR4D &aColor)
Set the stroke color.
VECTOR2D m_gridOffset
The grid offset to compensate cursor position.
virtual void SetIsStroke(bool aIsStrokeEnabled)
Enable/disable stroked outlines.
double m_worldScale
The scale factor world->screen.
void SetLookAtPoint(const VECTOR2D &aPoint)
Get/set the Point in world space to look at.
VECTOR2D GetGridPoint(const VECTOR2D &aPoint) const
For a given point it returns the nearest point belonging to the grid in world coordinates.
void SetWorldUnitLength(double aWorldUnitLength)
Set the unit length.
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.
static const int GRID_DEPTH
Depth level on which the grid is drawn.
void SetGlyphSize(const VECTOR2I aSize)
virtual void ComputeWorldScreenMatrix()
Compute the world <-> screen transformation matrix.
double computeMinGridSpacing() const
Compute minimum grid spacing from the grid settings.
void SetFontItalic(bool aItalic)
virtual void DrawEllipse(const VECTOR2D &aCenterPoint, double aMajorRadius, double aMinorRadius, const EDA_ANGLE &aRotation)
Draw a closed ellipse.
GAL_DISPLAY_OPTIONS & m_options
virtual void BitmapText(const wxString &aText, const VECTOR2I &aPosition, const EDA_ANGLE &aAngle)
Draw a text using a bitmap font.
void SetGridVisibility(bool aVisibility)
Set the visibility setting of the grid.
float GetLineWidth() const
Get the line width.
bool m_globalFlipX
Flag for X axis flipping.
KIGFX::CROSS_HAIR_MODE m_crossHairMode
Crosshair drawing mode.
void SetDepthRange(const VECTOR2D &aDepthRange)
Set the range of the layer depth.
VECTOR2D m_lookAtPoint
Point to be looked at in world space.
void SetScreenDPI(double aScreenDPI)
Set the dots per inch of the screen.
bool m_forceDisplayCursor
Always show cursor.
static const int MAX_DEPTH
void SetIdentity()
Set the matrix to the identity matrix.
Definition matrix3x3.h:236
void SetRotation(T aAngle)
Set the rotation components of the matrix.
Definition matrix3x3.h:271
void SetScale(VECTOR2< T > aScale)
Set the scale components of the matrix.
Definition matrix3x3.h:283
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition matrix3x3.h:291
void SetTranslation(VECTOR2< T > aTranslation)
Set the translation components of the matrix.
Definition matrix3x3.h:252
SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError) const
Build a polyline approximation of the ellipse or arc.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
KICURSOR
Definition cursors.h:40
@ ARROW
Definition cursors.h:42
#define MAX_LAYERS_FOR_VIEW
Definition definitions.h:41
MATRIX3x3< double > MATRIX3x3D
Definition matrix3x3.h:469
The Cairo implementation of the graphics abstraction layer.
Definition eda_group.h:29
@ LINES
Use lines for the grid.
const int scale
const SHAPE_LINE_CHAIN chain
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_CENTER
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682