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, you may find one here:
21 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
22 * or you may search the http://www.gnu.org website for the version 2 license,
23 * or you may write to the Free Software Foundation, Inc.,
24 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include <wx/log.h>
28#include <advanced_config.h>
30#include <gal/definitions.h>
31#include <font/font.h>
32
35
36#include <math/util.h> // for KiROUND
37
38#include <cmath>
39
40using namespace KIGFX;
41
42
43GAL::GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions ) :
44 m_options( aDisplayOptions ),
45
46 // m_currentNativeCursor is initialized with KICURSOR::DEFAULT value to avoid
47 // if comparison with uninitialized value on SetNativeCursorStyle method.
48 // Some classes inheriting from GAL has different SetNativeCursorStyle method
49 // implementation and therefore it's called also on constructor
50 // to change the value from DEFAULT to KICURSOR::ARROW
52{
53 // Set the default values for the internal variables
54 SetIsFill( false );
55 SetIsStroke( true );
56 SetFillColor( COLOR4D( 0.0, 0.0, 0.0, 0.0 ) );
57 SetStrokeColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
58 SetLookAtPoint( VECTOR2D( 0, 0 ) );
59 SetZoomFactor( 1.0 );
60 SetRotation( 0.0 );
61
62 // this value for SetWorldUnitLength is only suitable for Pcbnew.
63 // Other editors/viewer must call SetWorldUnitLength with their internal units
64 SetWorldUnitLength( 1e-9 /* 1 nm */ / 0.0254 /* 1 inch in meters */ );
65
66 // wxDC::GetPPI() reports 96 DPI, but somehow this value
67 // is the closest match to the legacy renderer
68 SetScreenDPI( ADVANCED_CFG::GetCfg().m_ScreenDPI );
70 SetLayerDepth( 0.0 );
71 SetFlip( false, false );
72 SetLineWidth( 1.0f );
73 SetMinLineWidth( 1.0f );
75 SetAxesEnabled( false );
76
77 // Set grid defaults
78 SetGridVisibility( true );
79 SetCoarseGrid( 10 );
80 m_gridLineWidth = 0.5f;
83
84 // Initialize the cursor shape
85 SetCursorColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
88 SetCursorEnabled( false );
89
90 // Initialize the native widget to an arrow cursor
92
93 // Initialize text properties
95
96 // subscribe for settings updates
97 m_observerLink = m_options.Subscribe( this );
98}
99
100
102{
103}
104
105
107{
108 // defer to the child class first
109 updatedGalDisplayOptions( aOptions );
110
111 // there is no refresh to do at this level
112}
113
114
115void GAL::DrawEllipse( const VECTOR2D& aCenterPoint, double aMajorRadius, double aMinorRadius,
116 const EDA_ANGLE& aRotation )
117{
118 const VECTOR2I intCenter( KiROUND( aCenterPoint.x ), KiROUND( aCenterPoint.y ) );
119
120 SHAPE_ELLIPSE e( intCenter, KiROUND( aMajorRadius ), KiROUND( aMinorRadius ), aRotation );
121
122 SHAPE_LINE_CHAIN chain = e.ConvertToPolyline( std::max( 1, KiROUND( aMajorRadius / 500.0 ) ) );
124}
125
126
127void GAL::DrawEllipseArc( const VECTOR2D& aCenterPoint, double aMajorRadius, double aMinorRadius,
128 const EDA_ANGLE& aRotation, const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle )
129{
130 const VECTOR2I intCenter( KiROUND( aCenterPoint.x ), KiROUND( aCenterPoint.y ) );
131
132 SHAPE_ELLIPSE e( intCenter, KiROUND( aMajorRadius ), KiROUND( aMinorRadius ), aRotation, aStartAngle, aEndAngle );
133
134 SHAPE_LINE_CHAIN chain = e.ConvertToPolyline( std::max( 1, KiROUND( aMajorRadius / 500.0 ) ) );
136}
137
138
140{
141 bool refresh = false;
142
143 if( m_options.m_gridStyle != m_gridStyle )
144 {
145 m_gridStyle = m_options.m_gridStyle;
146 refresh = true;
147 }
148
149 if( m_options.m_gridLineWidth != m_gridLineWidth )
150 {
151 m_gridLineWidth = m_options.m_scaleFactor * m_options.m_gridLineWidth + 0.25;
152 refresh = true;
153 }
154
155 if( m_options.m_gridMinSpacing != m_gridMinSpacing )
156 {
157 m_gridMinSpacing = m_options.m_gridMinSpacing;
158 refresh = true;
159 }
160
161 if( m_options.m_axesEnabled != m_axesEnabled )
162 {
163 m_axesEnabled = m_options.m_axesEnabled;
164 refresh = true;
165 }
166
167 if( m_options.m_forceDisplayCursor != m_forceDisplayCursor )
168 {
169 m_forceDisplayCursor = m_options.m_forceDisplayCursor;
170 refresh = true;
171 }
172
173 if( m_options.GetCursorMode() != m_crossHairMode )
174 {
175 m_crossHairMode = m_options.GetCursorMode();
176 refresh = true;
177 }
178
179 // tell the derived class if the base class needs an update or not
180 return refresh;
181}
182
183
185{
186 // Tiny but non-zero - this will always need setting
187 // there is no built-in default
188 SetGlyphSize( { 1, 1 } );
189
192
193 SetFontBold( false );
194 SetFontItalic( false );
195 SetFontUnderlined( false );
196 SetTextMirrored( false );
197}
198
199
201{
203
204 MATRIX3x3D translation;
205 translation.SetIdentity();
206 // We're deliberately dividing integers to avoid fractional pixel offsets.
207 translation.SetTranslation( VECTOR2D( m_screenSize.x/2, m_screenSize.y/2 ) );
208
209 MATRIX3x3D rotate;
210 rotate.SetIdentity();
211 rotate.SetRotation( m_rotation );
212
214 scale.SetIdentity();
215 scale.SetScale( VECTOR2D( m_worldScale, m_worldScale ) );
216
217 MATRIX3x3D flip;
218 flip.SetIdentity();
219 flip.SetScale( VECTOR2D( m_globalFlipX ? -1.0 : 1.0, m_globalFlipY ? -1.0 : 1.0 ) );
220
221 MATRIX3x3D lookat;
222 lookat.SetIdentity();
223 lookat.SetTranslation( -m_lookAtPoint );
224
225 m_worldScreenMatrix = translation * rotate * flip * scale * lookat;
227}
228
229
231{
232 const MATRIX3x3D& matrix = GetScreenWorldMatrix();
233
234 VECTOR2D halfSize = VECTOR2D( matrix.GetScale().x * m_screenSize.x * 0.5,
235 matrix.GetScale().y * m_screenSize.y * 0.5 );
236
237 BOX2D extents;
238 extents.SetOrigin( GetLookAtPoint() - halfSize );
239 extents.SetSize( halfSize * 2 );
240
241 return extents;
242}
243
244
246{
247 // just return the current value. This could be cleverer and take
248 // into account other settings in future
249 return m_gridMinSpacing;
250}
251
252
253VECTOR2D GAL::GetGridPoint( const VECTOR2D& aPoint ) const
254{
255#if 0
256 // This old code expects a non zero grid size, which can be wrong here.
257 return VECTOR2D( KiROUND( ( aPoint.x - m_gridOffset.x ) / m_gridSize.x ) *
259 KiROUND( ( aPoint.y - m_gridOffset.y ) / m_gridSize.y ) *
260 m_gridSize.y + m_gridOffset.y );
261#else
262 // if grid size == 0.0 there is no grid, so use aPoint as grid reference position
263 double cx = m_gridSize.x > 0.0 ? KiROUND( ( aPoint.x - m_gridOffset.x ) / m_gridSize.x ) *
265 : aPoint.x;
266 double cy = m_gridSize.y > 0.0 ? KiROUND( ( aPoint.y - m_gridOffset.y ) / m_gridSize.y ) *
268 : aPoint.y;
269
270 return VECTOR2D( cx, cy );
271#endif
272}
273
274
275// MIN_DEPTH must be set to be - (VIEW::VIEW_MAX_LAYERS + abs(VIEW::TOP_LAYER_MODIFIER))
276// MAX_DEPTH must be set to be VIEW::VIEW_MAX_LAYERS + abs(VIEW::TOP_LAYER_MODIFIER) -1
277// VIEW_MAX_LAYERS and TOP_LAYER_MODIFIER are defined in view.h.
278// TOP_LAYER_MODIFIER is set as -VIEW_MAX_LAYERS
279// Currently KIGFX::VIEW::VIEW_MAX_LAYERS = MAX_LAYERS_FOR_VIEW
281const int GAL::MAX_DEPTH = 2*MAX_LAYERS_FOR_VIEW - 1;
282const int GAL::GRID_DEPTH = MAX_DEPTH - 1;
283
284
286{
287 COLOR4D color = m_cursorColor;
288
289 // dim the cursor if it's only on because it was forced
290 // (this helps to provide a hint for active tools)
291 if( !m_isCursorEnabled )
292 color.a = color.a * 0.5;
293
294 return color;
295}
296
297
298void GAL::BitmapText( const wxString& aText, const VECTOR2I& aPosition, const EDA_ANGLE& aAngle )
299{
301
302 if( aText.IsEmpty() )
303 return;
304
306 attrs.m_Angle = aAngle;
307 attrs.m_Mirrored = m_globalFlipX; // Prevent text flipping when view is flipped
308
309 // Bitmap font has different metrics than the stroke font so we compensate a bit before
310 // stroking
311 attrs.m_Size = VECTOR2I( m_attributes.m_Size.x, m_attributes.m_Size.y * 0.95 );
312 attrs.m_StrokeWidth = GetLineWidth() * 0.74;
313
314 font->Draw( this, aText, aPosition, attrs, KIFONT::METRICS::Default() );
315}
316
317
318bool GAL::SetNativeCursorStyle( KICURSOR aCursor, bool aHiDPI )
319{
320 if( m_currentNativeCursor == aCursor )
321 return false;
322
323 m_currentNativeCursor = aCursor;
324
325 return true;
326}
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
BOX2< VECTOR2D > BOX2D
Definition box2.h:923
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:237
constexpr void SetSize(const SizeVec &size)
Definition box2.h:248
GAL(GAL_DISPLAY_OPTIONS &aOptions)
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:98
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:147
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:250
static const METRICS & Default()
Definition font.cpp:52
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
double a
Alpha component.
Definition color4d.h:396
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:240
void SetRotation(T aAngle)
Set the rotation components of the matrix.
Definition matrix3x3.h:275
void SetScale(VECTOR2< T > aScale)
Set the scale components of the matrix.
Definition matrix3x3.h:287
VECTOR2< T > GetScale() const
Get the scale components of the matrix.
Definition matrix3x3.h:295
void SetTranslation(VECTOR2< T > aTranslation)
Set the translation components of the matrix.
Definition matrix3x3.h:256
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:44
@ ARROW
Definition cursors.h:46
#define MAX_LAYERS_FOR_VIEW
Definition definitions.h:45
MATRIX3x3< double > MATRIX3x3D
Definition matrix3x3.h:473
The Cairo implementation of the graphics abstraction layer.
Definition eda_group.h:33
@ 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:687
VECTOR2< double > VECTOR2D
Definition vector2d.h:686