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
33#include <math/util.h> // for KiROUND
34
35#include <cmath>
36
37using namespace KIGFX;
38
39
40GAL::GAL( GAL_DISPLAY_OPTIONS& aDisplayOptions ) :
41 m_options( aDisplayOptions ),
42
43 // m_currentNativeCursor is initialized with KICURSOR::DEFAULT value to avoid
44 // if comparison with uninitialized value on SetNativeCursorStyle method.
45 // Some classes inheriting from GAL has different SetNativeCursorStyle method
46 // implementation and therefore it's called also on constructor
47 // to change the value from DEFAULT to KICURSOR::ARROW
49{
50 // Set the default values for the internal variables
51 SetIsFill( false );
52 SetIsStroke( true );
53 SetFillColor( COLOR4D( 0.0, 0.0, 0.0, 0.0 ) );
54 SetStrokeColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
55 SetLookAtPoint( VECTOR2D( 0, 0 ) );
56 SetZoomFactor( 1.0 );
57 SetRotation( 0.0 );
58
59 // this value for SetWorldUnitLength is only suitable for Pcbnew.
60 // Other editors/viewer must call SetWorldUnitLength with their internal units
61 SetWorldUnitLength( 1e-9 /* 1 nm */ / 0.0254 /* 1 inch in meters */ );
62
63 // wxDC::GetPPI() reports 96 DPI, but somehow this value
64 // is the closest match to the legacy renderer
65 SetScreenDPI( ADVANCED_CFG::GetCfg().m_ScreenDPI );
67 SetLayerDepth( 0.0 );
68 SetFlip( false, false );
69 SetLineWidth( 1.0f );
70 SetMinLineWidth( 1.0f );
72 SetAxesEnabled( false );
73
74 // Set grid defaults
75 SetGridVisibility( true );
76 SetCoarseGrid( 10 );
77 m_gridLineWidth = 0.5f;
80
81 // Initialize the cursor shape
82 SetCursorColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
85 SetCursorEnabled( false );
86
87 // Initialize the native widget to an arrow cursor
89
90 // Initialize text properties
92
93 // subscribe for settings updates
94 m_observerLink = m_options.Subscribe( this );
95}
96
97
99{
100}
101
102
104{
105 // defer to the child class first
106 updatedGalDisplayOptions( aOptions );
107
108 // there is no refresh to do at this level
109}
110
111
113{
114 bool refresh = false;
115
116 if( m_options.m_gridStyle != m_gridStyle )
117 {
118 m_gridStyle = m_options.m_gridStyle;
119 refresh = true;
120 }
121
122 if( m_options.m_gridLineWidth != m_gridLineWidth )
123 {
124 m_gridLineWidth = m_options.m_scaleFactor * m_options.m_gridLineWidth + 0.25;
125 refresh = true;
126 }
127
128 if( m_options.m_gridMinSpacing != m_gridMinSpacing )
129 {
130 m_gridMinSpacing = m_options.m_gridMinSpacing;
131 refresh = true;
132 }
133
134 if( m_options.m_axesEnabled != m_axesEnabled )
135 {
136 m_axesEnabled = m_options.m_axesEnabled;
137 refresh = true;
138 }
139
140 if( m_options.m_forceDisplayCursor != m_forceDisplayCursor )
141 {
142 m_forceDisplayCursor = m_options.m_forceDisplayCursor;
143 refresh = true;
144 }
145
146 if( m_options.GetCursorMode() != m_crossHairMode )
147 {
148 m_crossHairMode = m_options.GetCursorMode();
149 refresh = true;
150 }
151
152 // tell the derived class if the base class needs an update or not
153 return refresh;
154}
155
156
158{
159 // Tiny but non-zero - this will always need setting
160 // there is no built-in default
161 SetGlyphSize( { 1, 1 } );
162
165
166 SetFontBold( false );
167 SetFontItalic( false );
168 SetFontUnderlined( false );
169 SetTextMirrored( false );
170}
171
172
174{
176
177 MATRIX3x3D translation;
178 translation.SetIdentity();
179 // We're deliberately dividing integers to avoid fractional pixel offsets.
180 translation.SetTranslation( VECTOR2D( m_screenSize.x/2, m_screenSize.y/2 ) );
181
182 MATRIX3x3D rotate;
183 rotate.SetIdentity();
184 rotate.SetRotation( m_rotation );
185
187 scale.SetIdentity();
188 scale.SetScale( VECTOR2D( m_worldScale, m_worldScale ) );
189
190 MATRIX3x3D flip;
191 flip.SetIdentity();
192 flip.SetScale( VECTOR2D( m_globalFlipX ? -1.0 : 1.0, m_globalFlipY ? -1.0 : 1.0 ) );
193
194 MATRIX3x3D lookat;
195 lookat.SetIdentity();
196 lookat.SetTranslation( -m_lookAtPoint );
197
198 m_worldScreenMatrix = translation * rotate * flip * scale * lookat;
200}
201
202
204{
205 const MATRIX3x3D& matrix = GetScreenWorldMatrix();
206
207 VECTOR2D halfSize = VECTOR2D( matrix.GetScale().x * m_screenSize.x * 0.5,
208 matrix.GetScale().y * m_screenSize.y * 0.5 );
209
210 BOX2D extents;
211 extents.SetOrigin( GetLookAtPoint() - halfSize );
212 extents.SetSize( halfSize * 2 );
213
214 return extents;
215}
216
217
219{
220 // just return the current value. This could be cleverer and take
221 // into account other settings in future
222 return m_gridMinSpacing;
223}
224
225
226VECTOR2D GAL::GetGridPoint( const VECTOR2D& aPoint ) const
227{
228#if 0
229 // This old code expects a non zero grid size, which can be wrong here.
230 return VECTOR2D( KiROUND( ( aPoint.x - m_gridOffset.x ) / m_gridSize.x ) *
232 KiROUND( ( aPoint.y - m_gridOffset.y ) / m_gridSize.y ) *
233 m_gridSize.y + m_gridOffset.y );
234#else
235 // if grid size == 0.0 there is no grid, so use aPoint as grid reference position
236 double cx = m_gridSize.x > 0.0 ? KiROUND( ( aPoint.x - m_gridOffset.x ) / m_gridSize.x ) *
238 : aPoint.x;
239 double cy = m_gridSize.y > 0.0 ? KiROUND( ( aPoint.y - m_gridOffset.y ) / m_gridSize.y ) *
241 : aPoint.y;
242
243 return VECTOR2D( cx, cy );
244#endif
245}
246
247
248// MIN_DEPTH must be set to be - (VIEW::VIEW_MAX_LAYERS + abs(VIEW::TOP_LAYER_MODIFIER))
249// MAX_DEPTH must be set to be VIEW::VIEW_MAX_LAYERS + abs(VIEW::TOP_LAYER_MODIFIER) -1
250// VIEW_MAX_LAYERS and TOP_LAYER_MODIFIER are defined in view.h.
251// TOP_LAYER_MODIFIER is set as -VIEW_MAX_LAYERS
252// Currently KIGFX::VIEW::VIEW_MAX_LAYERS = MAX_LAYERS_FOR_VIEW
254const int GAL::MAX_DEPTH = 2*MAX_LAYERS_FOR_VIEW - 1;
255const int GAL::GRID_DEPTH = MAX_DEPTH - 1;
256
257
259{
261
262 // dim the cursor if it's only on because it was forced
263 // (this helps to provide a hint for active tools)
264 if( !m_isCursorEnabled )
265 color.a = color.a * 0.5;
266
267 return color;
268}
269
270
271void GAL::BitmapText( const wxString& aText, const VECTOR2I& aPosition, const EDA_ANGLE& aAngle )
272{
274
275 if( aText.IsEmpty() )
276 return;
277
279 attrs.m_Angle = aAngle;
280 attrs.m_Mirrored = m_globalFlipX; // Prevent text flipping when view is flipped
281
282 // Bitmap font has different metrics than the stroke font so we compensate a bit before
283 // stroking
284 attrs.m_Size = VECTOR2I( m_attributes.m_Size.x, m_attributes.m_Size.y * 0.95 );
285 attrs.m_StrokeWidth = GetLineWidth() * 0.74;
286
287 font->Draw( this, aText, aPosition, attrs, KIFONT::METRICS::Default() );
288}
289
290
291bool GAL::SetNativeCursorStyle( KICURSOR aCursor, bool aHiDPI )
292{
293 if( m_currentNativeCursor == aCursor )
294 return false;
295
296 m_currentNativeCursor = aCursor;
297
298 return true;
299}
int color
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:131
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) 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:104
virtual void SetLayerDepth(double aLayerDepth)
Set the depth of the layer (position on the z-axis)
virtual void SetIsFill(bool aIsFillEnabled)
Enable/disable fill.
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)
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)
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
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
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_CENTER
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695
VECTOR2< double > VECTOR2D
Definition vector2d.h:694