KiCad PCB EDA Suite
Loading...
Searching...
No Matches
ds_painter.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21
22#include <common.h>
23#include <pgm_base.h>
24#include <base_screen.h>
25#include <eda_draw_frame.h>
26#include <title_block.h>
27#include <build_version.h>
32
35
36#include <wx/app.h>
37
38using namespace KIGFX;
39
40static const wxString productName = wxT( "KiCad E.D.A." );
41
43{
44 m_backgroundColor = COLOR4D( 1.0, 1.0, 1.0, 1.0 );
46 m_selectedColor = m_normalColor.Brightened( 0.5 );
47 m_brightenedColor = COLOR4D( 0.0, 1.0, 0.0, 0.9 );
48 m_pageBorderColor = COLOR4D( 0.4, 0.4, 0.4, 1.0 );
49
50 update();
51}
52
53
55{
56 for( int layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; layer++ )
57 m_layerColors[ layer ] = aSettings->GetColor( layer );
58
59 for( int layer = GAL_LAYER_ID_START; layer < GAL_LAYER_ID_END; layer++ )
60 m_layerColors[ layer ] = aSettings->GetColor( layer );
61
65}
66
67
68COLOR4D DS_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) const
69{
70 const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
71
72 if( item )
73 {
74 // Selection disambiguation
75 if( item->IsBrightened() )
76 return m_brightenedColor;
77
78 if( item->IsSelected() )
79 return m_selectedColor;
80
81 if( item->Type() == WSG_TEXT_T )
82 {
83 COLOR4D color = static_cast<const DS_DRAW_ITEM_TEXT*>( item )->GetTextColor();
84
85 if( color != COLOR4D::UNSPECIFIED )
86 return color;
87 }
88 }
89
90 return m_normalColor;
91}
92
93
94void DS_DRAW_ITEM_LIST::GetTextVars( wxArrayString* aVars )
95{
96 aVars->push_back( wxT( "KICAD_VERSION" ) );
97 aVars->push_back( wxT( "#" ) );
98 aVars->push_back( wxT( "##" ) );
99 aVars->push_back( wxT( "SHEETNAME" ) );
100 aVars->push_back( wxT( "SHEETPATH" ) );
101 aVars->push_back( wxT( "FILENAME" ) );
102 aVars->push_back( wxT( "FILEPATH" ) );
103 aVars->push_back( wxT( "PROJECTNAME" ) );
104 aVars->push_back( wxT( "PAPER" ) );
105 aVars->push_back( wxT( "LAYER" ) );
106 aVars->push_back( wxT( "VARIANT" ) );
107 aVars->push_back( wxT( "VARIANT_DESC" ) );
109}
110
111
112wxString DS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
113{
114 std::function<bool( wxString* )> wsResolver =
115 [&]( wxString* token ) -> bool
116 {
117 bool tokenUpdated = false;
118
119 if( token->IsSameAs( wxT( "KICAD_VERSION" ) ) && PgmOrNull() )
120 {
121 *token = wxString::Format( wxT( "%s %s" ), productName, GetBaseVersion() );
122 tokenUpdated = true;
123 }
124 else if( token->IsSameAs( wxT( "#" ) ) )
125 {
126 *token = wxString::Format( wxT( "%s" ), m_pageNumber );
127 tokenUpdated = true;
128 }
129 else if( token->IsSameAs( wxT( "##" ) ) )
130 {
131 *token = wxString::Format( wxT( "%d" ), m_sheetCount );
132 tokenUpdated = true;
133 }
134 else if( token->IsSameAs( wxT( "SHEETNAME" ) ) )
135 {
136 *token = m_sheetName;
137 tokenUpdated = true;
138 }
139 else if( token->IsSameAs( wxT( "SHEETPATH" ) ) )
140 {
141 *token = m_sheetPath;
142 tokenUpdated = true;
143 }
144 else if( token->IsSameAs( wxT( "FILENAME" ) ) )
145 {
146 wxFileName fn( m_fileName );
147 *token = fn.GetFullName();
148 tokenUpdated = true;
149 }
150 else if( token->IsSameAs( wxT( "FILEPATH" ) ) )
151 {
152 wxFileName fn( m_fileName );
153 *token = fn.GetFullPath();
154 return true;
155 }
156 else if( token->IsSameAs( wxT( "PAPER" ) ) )
157 {
158 *token = m_paperFormat;
159 tokenUpdated = true;
160 }
161 else if( token->IsSameAs( wxT( "LAYER" ) ) )
162 {
163 *token = m_sheetLayer;
164 tokenUpdated = true;
165 }
166 else if( token->IsSameAs( wxT( "VARIANT" ) ) )
167 {
168 *token = m_variantName;
169 tokenUpdated = true;
170 }
171 else if( token->IsSameAs( wxT( "VARIANT_DESC" ) ) )
172 {
173 *token = m_variantDesc;
174 tokenUpdated = true;
175 }
176 else if( m_titleBlock )
177 {
178 if( m_titleBlock->TextVarResolver( token, m_project, m_flags ) )
179 {
180 // No need for tokenUpdated; TITLE_BLOCK::TextVarResolver() already goes
181 // up to the project.
182 //
183 // However, the title block may have variables in it itself, so we need
184 // to run the worksheet resolver again.
185 //
186 const TITLE_BLOCK* savedTitleBlock = m_titleBlock;
187
188 m_titleBlock = nullptr;
189 {
190 *token = ExpandTextVars( *token, &wsResolver, m_flags );
191 }
192 m_titleBlock = savedTitleBlock;
193
194 return true;
195 }
196 }
197 else if( m_properties && m_properties->count( *token ) )
198 {
199 *token = m_properties->at( *token );
200 tokenUpdated = true;
201 }
202
203 if( tokenUpdated )
204 {
205 *token = ExpandTextVars( *token, m_project, m_flags );
206 return true;
207 }
208
209 if( m_project && m_project->TextVarResolver( token ) )
210 return true;
211
212 return false;
213 };
214
215 wxString retv = ExpandTextVars( aTextbase, &wsResolver, m_flags );
216
217 if( retv.Contains( wxS( "@{" ) ) )
218 {
219 // Must not be static. Painting can run on parallel workers and a shared
220 // evaluator races on its internal error collector.
221 EXPRESSION_EVALUATOR evaluator;
222 retv = evaluator.Evaluate( retv );
223 }
224
225 return retv;
226}
227
228
229bool KIGFX::DS_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
230{
231 auto item = dynamic_cast<const EDA_ITEM*>( aItem );
232
233 if( !item )
234 return false;
235
236 switch( item->Type() )
237 {
238 case WSG_LINE_T: draw( (DS_DRAW_ITEM_LINE*) item, aLayer ); break;
239 case WSG_POLY_T: draw( (DS_DRAW_ITEM_POLYPOLYGONS*) item, aLayer ); break;
240 case WSG_RECT_T: draw( (DS_DRAW_ITEM_RECT*) item, aLayer ); break;
241 case WSG_TEXT_T: draw( (DS_DRAW_ITEM_TEXT*) item, aLayer ); break;
242 case WSG_BITMAP_T: draw( (DS_DRAW_ITEM_BITMAP*) item, aLayer ); break;
243 case WSG_PAGE_T: draw( (DS_DRAW_ITEM_PAGE*) item, aLayer ); break;
244 default: return false;
245 }
246
247 return true;
248}
249
250
251void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_LINE* aItem, int aLayer ) const
252{
253 m_gal->SetIsStroke( true );
254 m_gal->SetIsFill( false );
255 m_gal->SetStrokeColor( m_renderSettings.GetColor( aItem, aLayer ) );
256 m_gal->SetLineWidth( std::max( aItem->GetPenWidth(), m_renderSettings.GetDefaultPenWidth() ) );
257 m_gal->DrawLine( VECTOR2D( aItem->GetStart() ), VECTOR2D( aItem->GetEnd() ) );
258}
259
260
261void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_RECT* aItem, int aLayer ) const
262{
263 m_gal->SetIsStroke( true );
264 m_gal->SetIsFill( false );
265 m_gal->SetStrokeColor( m_renderSettings.GetColor( aItem, aLayer ) );
266 m_gal->SetLineWidth( std::max( aItem->GetPenWidth(), m_renderSettings.GetDefaultPenWidth() ) );
267 m_gal->DrawRectangle( VECTOR2D( aItem->GetStart() ), VECTOR2D( aItem->GetEnd() ) );
268}
269
270
271void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_POLYPOLYGONS* aItem, int aLayer ) const
272{
273 m_gal->SetFillColor( m_renderSettings.GetColor( aItem, aLayer ) );
274 m_gal->SetIsFill( true );
275 m_gal->SetIsStroke( false );
276
278
279 for( int idx = 0; idx < item->GetPolygons().OutlineCount(); ++idx )
280 {
281 SHAPE_LINE_CHAIN& outline = item->GetPolygons().Outline( idx );
282 m_gal->DrawPolygon( outline );
283 }
284}
285
286
287void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_TEXT* aItem, int aLayer ) const
288{
289 KIFONT::FONT* font = aItem->GetFont();
290
291 if( !font )
292 {
293 font = KIFONT::FONT::GetFont( m_renderSettings.GetDefaultFont(), aItem->IsBold(),
294 aItem->IsItalic(), nullptr, true );
295 }
296
297 const COLOR4D& color = m_renderSettings.GetColor( aItem, aLayer );
298
299 m_gal->SetStrokeColor( color );
300 m_gal->SetFillColor( color );
301
302 TEXT_ATTRIBUTES attrs = aItem->GetAttributes();
303 attrs.m_StrokeWidth = std::max( aItem->GetEffectiveTextPenWidth(),
304 m_renderSettings.GetDefaultPenWidth() );
305
306 font->Draw( m_gal, aItem->GetShownText( true ), aItem->GetTextPos(), attrs,
307 aItem->GetFontMetrics() );
308}
309
310
311void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_BITMAP* aItem, int aLayer ) const
312{
313 m_gal->Save();
314 auto* bitmap = static_cast<DS_DATA_ITEM_BITMAP*>( aItem->GetPeer() );
315
316 VECTOR2D position = aItem->GetPosition();
317 m_gal->Translate( position );
318
319 // If we've failed to read the bitmap data, don't try to draw it
320 if( !( bitmap && bitmap->m_ImageBitmap
321 && bitmap->m_ImageBitmap->GetImageData() ) )
322 {
323 return;
324 }
325
326 // When the image scale factor is not 1.0, we need to modify the actual scale
327 // as the image scale factor is similar to a local zoom
328 double img_scale = bitmap->m_ImageBitmap->GetScale();
329
330 if( img_scale != 1.0 )
331 m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
332
333 m_gal->DrawBitmap( *bitmap->m_ImageBitmap );
334
335#if 0 // For bounding box debug purpose only
336 BOX2I bbox = aItem->GetBoundingBox();
337 m_canvas->SetIsFill( true );
338 m_canvas->SetIsStroke( true );
339 m_canvas->SetFillColor( COLOR4D( 1, 1, 1, 0.4 ) );
340 m_canvas->SetStrokeColor( COLOR4D( 0, 0, 0, 1 ) );
341
342 if( img_scale != 1.0 )
343 m_canvas->Scale( VECTOR2D( 1.0, 1.0 ) );
344
345 m_canvas->DrawRectangle( VECTOR2D( bbox.GetOrigin() ) - position,
346 VECTOR2D( bbox.GetEnd() ) - position );
347#endif
348
349 m_gal->Restore();
350}
351
352
353void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_PAGE* aItem, int aLayer ) const
354{
355 VECTOR2D origin = VECTOR2D( 0.0, 0.0 );
356 VECTOR2D end = VECTOR2D( aItem->GetPageSize().x,
357 aItem->GetPageSize().y );
358
359 m_gal->SetIsStroke( true );
360
361 // Use a gray color for the border color
362 m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
363 m_gal->SetIsFill( false );
364 m_gal->SetLineWidth( m_renderSettings.GetDefaultPenWidth() );
365
366 m_gal->DrawRectangle( origin, end );
367
368 // Draw the corner marker
369 double marker_size = aItem->GetMarkerSize();
370
371 m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
372 VECTOR2D pos = VECTOR2D( aItem->GetMarkerPos().x, aItem->GetMarkerPos().y );
373
374 // Draw a circle and a X
375 m_gal->DrawCircle( pos, marker_size );
376 m_gal->DrawLine( VECTOR2D( pos.x - marker_size, pos.y - marker_size),
377 VECTOR2D( pos.x + marker_size, pos.y + marker_size ) );
378 m_gal->DrawLine( VECTOR2D( pos.x + marker_size, pos.y - marker_size),
379 VECTOR2D( pos.x - marker_size, pos.y + marker_size ) );
380}
381
382
383void KIGFX::DS_PAINTER::DrawBorder( const PAGE_INFO* aPageInfo, int aScaleFactor ) const
384{
385 VECTOR2D origin = VECTOR2D( 0.0, 0.0 );
386 VECTOR2D end = VECTOR2D( aPageInfo->GetWidthMils() * aScaleFactor,
387 aPageInfo->GetHeightMils() * aScaleFactor );
388
389 m_gal->SetIsStroke( true );
390
391 // Use a gray color for the border color
392 m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
393 m_gal->SetIsFill( false );
394 m_gal->SetLineWidth( m_renderSettings.GetDefaultPenWidth() );
395 m_gal->DrawRectangle( origin, end );
396}
BASE_SCREEN class implementation.
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
wxString GetBaseVersion()
Get the KiCad version string without the information added by the packagers.
constexpr const Vec GetEnd() const
Definition box2.h:208
constexpr const Vec & GetOrigin() const
Definition box2.h:206
Color settings are a bit different than most of the settings objects in that there can be more than o...
COLOR4D GetColor(int aLayer) const
virtual int GetPenWidth() const
DS_DATA_ITEM * GetPeer() const
const KIFONT::METRICS & GetFontMetrics() const
VECTOR2I GetPosition() const override
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
const VECTOR2I & GetStart() const
const VECTOR2I & GetEnd() const
int m_sheetCount
The number of sheets.
static void GetTextVars(wxArrayString *aVars)
const std::map< wxString, wxString > * m_properties
wxString BuildFullText(const wxString &aTextbase)
const TITLE_BLOCK * m_titleBlock
const PROJECT * m_project
wxString m_pageNumber
The actual page number displayed in the title block.
A rectangle with thick segment showing the page limits and a marker showing the coordinate origin.
const VECTOR2I & GetMarkerPos() const
double GetMarkerSize() const
VECTOR2I GetPageSize() const
SHAPE_POLY_SET & GetPolygons()
Non filled rectangle with thick segment.
const VECTOR2I & GetEnd() const
const VECTOR2I & GetStart() const
A graphic text.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
bool IsSelected() const
Definition eda_item.h:132
bool IsBrightened() const
Definition eda_item.h:134
virtual VECTOR2I GetTextPos() const
Definition eda_text.h:294
bool IsItalic() const
Definition eda_text.h:190
KIFONT::FONT * GetFont() const
Definition eda_text.h:268
const TEXT_ATTRIBUTES & GetAttributes() const
Definition eda_text.h:252
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:461
bool IsBold() const
Definition eda_text.h:205
virtual wxString GetShownText(bool aAllowExtraText, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition eda_text.h:121
High-level wrapper for evaluating mathematical and string expressions in wxString format.
wxString Evaluate(const wxString &aInput)
Main evaluation function - processes input string and evaluates all} expressions.
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
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:398
void DrawBorder(const PAGE_INFO *aPageInfo, int aScaleFactor) const
DS_RENDER_SETTINGS m_renderSettings
Definition ds_painter.h:117
void draw(const DS_DRAW_ITEM_LINE *aItem, int aLayer) const
virtual bool Draw(const VIEW_ITEM *, int) override
Takes an instance of VIEW_ITEM and passes it to a function that knows how to draw the item.
void LoadColors(const COLOR_SETTINGS *aSettings) override
virtual COLOR4D GetColor(const VIEW_ITEM *aItem, int aLayer) const override
Returns the color that should be used to draw the specific VIEW_ITEM on the specific layer using curr...
GAL * m_gal
Instance of graphic abstraction layer that gives an interface to call commands used to draw (eg.
Definition painter.h:98
virtual void update()
Precalculates extra colors for layers (e.g.
std::map< int, COLOR4D > m_layerColors
An abstract base class for deriving all objects that can be added to a VIEW.
Definition view_item.h:82
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition page_info.h:75
double GetHeightMils() const
Definition page_info.h:143
double GetWidthMils() const
Definition page_info.h:138
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition title_block.h:37
static void GetContextualTextVars(wxArrayString *aVars)
@ RED
Definition color4d.h:55
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, int aFlags)
Definition common.cpp:59
The common library.
static const wxString productName
@ GAL_LAYER_ID_START
Definition layer_ids.h:225
@ GAL_LAYER_ID_END
Definition layer_ids.h:358
@ SCH_LAYER_ID_END
Definition layer_ids.h:503
@ SCH_LAYER_ID_START
Definition layer_ids.h:448
@ LAYER_SCHEMATIC_DRAWINGSHEET
Definition layer_ids.h:494
@ LAYER_SCHEMATIC_BACKGROUND
Definition layer_ids.h:486
@ LAYER_SCHEMATIC_GRID
Definition layer_ids.h:484
The Cairo implementation of the graphics abstraction layer.
Definition eda_group.h:29
PGM_BASE * PgmOrNull()
Return a reference that can be nullptr when running a shared lib from a script, not from a kicad app.
see class PGM_BASE
VECTOR2I end
@ WSG_POLY_T
Definition typeinfo.h:215
@ WSG_LINE_T
Definition typeinfo.h:213
@ WSG_TEXT_T
Definition typeinfo.h:216
@ WSG_PAGE_T
Definition typeinfo.h:218
@ WSG_RECT_T
Definition typeinfo.h:214
@ WSG_BITMAP_T
Definition typeinfo.h:217
VECTOR2< double > VECTOR2D
Definition vector2d.h:682