KiCad PCB EDA Suite
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 (C) 1992-2020 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, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 
26 #include <common.h>
27 #include <pgm_base.h>
28 #include <base_screen.h>
29 #include <eda_draw_frame.h>
30 #include <title_block.h>
31 #include <build_version.h>
35 
38 
39 #include <wx/app.h>
40 
41 using namespace KIGFX;
42 
43 static const wxString productName = wxT( "KiCad E.D.A. " );
44 
46 {
47  m_backgroundColor = COLOR4D( 1.0, 1.0, 1.0, 1.0 );
50  m_brightenedColor = COLOR4D( 0.0, 1.0, 0.0, 0.9 );
51  m_pageBorderColor = COLOR4D( 0.4, 0.4, 0.4, 1.0 );
52 
53  update();
54 }
55 
56 
58 {
59  for( int layer = SCH_LAYER_ID_START; layer < SCH_LAYER_ID_END; layer ++)
60  m_layerColors[ layer ] = aSettings->GetColor( layer );
61 
62  for( int layer = GAL_LAYER_ID_START; layer < GAL_LAYER_ID_END; layer ++)
63  m_layerColors[ layer ] = aSettings->GetColor( layer );
64 
68 }
69 
70 
71 COLOR4D DS_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) const
72 {
73  const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
74 
75  if( item )
76  {
77  // Selection disambiguation
78  if( item->IsBrightened() )
79  return m_brightenedColor;
80 
81  if( item->IsSelected() )
82  return m_selectedColor;
83  }
84 
85  return m_normalColor;
86 }
87 
88 
89 void DS_DRAW_ITEM_LIST::GetTextVars( wxArrayString* aVars )
90 {
91  aVars->push_back( wxT( "KICAD_VERSION" ) );
92  aVars->push_back( wxT( "#" ) );
93  aVars->push_back( wxT( "##" ) );
94  aVars->push_back( wxT( "SHEETNAME" ) );
95  aVars->push_back( wxT( "FILENAME" ) );
96  aVars->push_back( wxT( "PAPER" ) );
97  aVars->push_back( wxT( "LAYER" ) );
99 }
100 
101 
102 // returns the full text corresponding to the aTextbase,
103 // after replacing format symbols by the corresponding value
104 wxString DS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
105 {
106  std::function<bool( wxString* )> wsResolver =
107  [ this ]( wxString* token ) -> bool
108  {
109  bool tokenUpdated = false;
110 
111  if( token->IsSameAs( wxT( "KICAD_VERSION" ) ) && PgmOrNull() )
112  {
113  // TODO: it'd be nice to get the Python script name/version here for when
114  // PgmOrNull() is null...
115 
116  *token = wxString::Format( wxT( "%s%s %s" ),
117  productName,
118  Pgm().App().GetAppName(),
119  GetBuildVersion() );
120  tokenUpdated = true;
121  }
122  else if( token->IsSameAs( wxT( "#" ) ) )
123  {
124  *token = wxString::Format( wxT( "%s" ), m_pageNumber );
125  tokenUpdated = true;
126  }
127  else if( token->IsSameAs( wxT( "##" ) ) )
128  {
129  *token = wxString::Format( wxT( "%d" ), m_sheetCount );
130  tokenUpdated = true;
131  }
132  else if( token->IsSameAs( wxT( "SHEETNAME" ) ) )
133  {
134  *token = m_sheetFullName;
135  tokenUpdated = true;
136  }
137  else if( token->IsSameAs( wxT( "FILENAME" ) ) )
138  {
139  wxFileName fn( m_fileName );
140  *token = fn.GetFullName();
141  tokenUpdated = true;
142  }
143  else if( token->IsSameAs( wxT( "PAPER" ) ) )
144  {
145  *token = m_paperFormat ? *m_paperFormat : wxString( wxEmptyString );
146  tokenUpdated = true;
147  }
148  else if( token->IsSameAs( wxT( "LAYER" ) ) )
149  {
150  *token = m_sheetLayer ? *m_sheetLayer : wxString( wxEmptyString );
151  tokenUpdated = true;
152  }
153  else if( m_titleBlock )
154  {
155  // no need for tokenUpdated; TextVarResolver() did a full resolve
156  return m_titleBlock->TextVarResolver( token, m_project );
157  }
158 
159  if( tokenUpdated )
160  {
161  *token = ExpandTextVars( *token, m_project );
162  return true;
163  }
164 
165  return false;
166  };
167 
168  return ExpandTextVars( aTextbase, &wsResolver, nullptr, m_project );
169 }
170 
171 
172 bool KIGFX::DS_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
173 {
174  auto item = dynamic_cast<const EDA_ITEM*>( aItem );
175 
176  if( !item )
177  return false;
178 
179  switch( item->Type() )
180  {
181  case WSG_LINE_T: draw( (DS_DRAW_ITEM_LINE*) item, aLayer ); break;
182  case WSG_POLY_T: draw( (DS_DRAW_ITEM_POLYPOLYGONS*) item, aLayer ); break;
183  case WSG_RECT_T: draw( (DS_DRAW_ITEM_RECT*) item, aLayer ); break;
184  case WSG_TEXT_T: draw( (DS_DRAW_ITEM_TEXT*) item, aLayer ); break;
185  case WSG_BITMAP_T: draw( (DS_DRAW_ITEM_BITMAP*) item, aLayer ); break;
186  case WSG_PAGE_T: draw( (DS_DRAW_ITEM_PAGE*) item, aLayer ); break;
187  default: return false;
188  }
189 
190  return true;
191 }
192 
193 
194 void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_LINE* aItem, int aLayer ) const
195 {
196  m_gal->SetIsStroke( true );
197  m_gal->SetIsFill( false );
198  m_gal->SetStrokeColor( m_renderSettings.GetColor( aItem, aLayer ) );
199  m_gal->SetLineWidth( std::max( aItem->GetPenWidth(), m_renderSettings.GetDefaultPenWidth() ) );
200  m_gal->DrawLine( VECTOR2D( aItem->GetStart() ), VECTOR2D( aItem->GetEnd() ) );
201 }
202 
203 
204 void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_RECT* aItem, int aLayer ) const
205 {
206  m_gal->SetIsStroke( true );
207  m_gal->SetIsFill( false );
208  m_gal->SetStrokeColor( m_renderSettings.GetColor( aItem, aLayer ) );
209  m_gal->SetLineWidth( std::max( aItem->GetPenWidth(), m_renderSettings.GetDefaultPenWidth() ) );
210  m_gal->DrawRectangle( VECTOR2D( aItem->GetStart() ), VECTOR2D( aItem->GetEnd() ) );
211 }
212 
213 
214 void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_POLYPOLYGONS* aItem, int aLayer ) const
215 {
216  m_gal->SetFillColor( m_renderSettings.GetColor( aItem, aLayer ) );
217  m_gal->SetIsFill( true );
218  m_gal->SetIsStroke( false );
219 
221 
222  for( int idx = 0; idx < item->GetPolygons().OutlineCount(); ++idx )
223  {
224  SHAPE_LINE_CHAIN& outline = item->GetPolygons().Outline( idx );
225  m_gal->DrawPolygon( outline );
226  }
227 }
228 
229 
230 void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_TEXT* aItem, int aLayer ) const
231 {
232  VECTOR2D position( aItem->GetTextPos().x, aItem->GetTextPos().y );
233  int penWidth = std::max( aItem->GetEffectiveTextPenWidth(),
234  m_renderSettings.GetDefaultPenWidth() );
235 
236  m_gal->Save();
237  m_gal->Translate( position );
238  m_gal->Rotate( -aItem->GetTextAngle() * M_PI / 1800.0 );
239  m_gal->SetStrokeColor( m_renderSettings.GetColor( aItem, aLayer ) );
240  m_gal->SetLineWidth( penWidth );
241  m_gal->SetTextAttributes( aItem );
242  m_gal->SetIsFill( false );
243  m_gal->SetIsStroke( true );
244  m_gal->StrokeText( aItem->GetShownText(), VECTOR2D( 0, 0 ), 0.0 );
245  m_gal->Restore();
246 }
247 
248 
249 void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_BITMAP* aItem, int aLayer ) const
250 {
251  m_gal->Save();
252  auto* bitmap = static_cast<DS_DATA_ITEM_BITMAP*>( aItem->GetPeer() );
253 
254  VECTOR2D position = aItem->GetPosition();
255  m_gal->Translate( position );
256 
257  // When the image scale factor is not 1.0, we need to modify the actual scale
258  // as the image scale factor is similar to a local zoom
259  double img_scale = bitmap->m_ImageBitmap->GetScale();
260 
261  if( img_scale != 1.0 )
262  m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
263 
264  m_gal->DrawBitmap( *bitmap->m_ImageBitmap );
265 
266 #if 0 // For bounding box debug purpose only
267  EDA_RECT bbox = aItem->GetBoundingBox();
268  m_gal->SetIsFill( true );
269  m_gal->SetIsStroke( true );
270  m_gal->SetFillColor( COLOR4D( 1, 1, 1, 0.4 ) );
271  m_gal->SetStrokeColor( COLOR4D( 0, 0, 0, 1 ) );
272 
273  if( img_scale != 1.0 )
274  m_gal->Scale( VECTOR2D( 1.0, 1.0 ) );
275 
276  m_gal->DrawRectangle( VECTOR2D( bbox.GetOrigin() ) - position,
277  VECTOR2D( bbox.GetEnd() ) - position );
278 #endif
279 
280  m_gal->Restore();
281 }
282 
283 
284 void KIGFX::DS_PAINTER::draw( const DS_DRAW_ITEM_PAGE* aItem, int aLayer ) const
285 {
286  VECTOR2D origin = VECTOR2D( 0.0, 0.0 );
287  VECTOR2D end = VECTOR2D( aItem->GetPageSize().x,
288  aItem->GetPageSize().y );
289 
290  m_gal->SetIsStroke( true );
291 
292  // Use a gray color for the border color
293  m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
294  m_gal->SetIsFill( false );
295  m_gal->SetLineWidth( m_renderSettings.GetDefaultPenWidth() );
296 
297  m_gal->DrawRectangle( origin, end );
298 
299  // Draw the corner marker
300  double marker_size = aItem->GetMarkerSize();
301 
302  m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
303  VECTOR2D pos = VECTOR2D( aItem->GetMarkerPos().x, aItem->GetMarkerPos().y );
304 
305  // Draw a circle and a X
306  m_gal->DrawCircle( pos, marker_size );
307  m_gal->DrawLine( VECTOR2D( pos.x - marker_size, pos.y - marker_size),
308  VECTOR2D( pos.x + marker_size, pos.y + marker_size ) );
309  m_gal->DrawLine( VECTOR2D( pos.x + marker_size, pos.y - marker_size),
310  VECTOR2D( pos.x - marker_size, pos.y + marker_size ) );
311 }
312 
313 
314 void KIGFX::DS_PAINTER::DrawBorder( const PAGE_INFO* aPageInfo, int aScaleFactor ) const
315 {
316  VECTOR2D origin = VECTOR2D( 0.0, 0.0 );
317  VECTOR2D end = VECTOR2D( aPageInfo->GetWidthMils() * aScaleFactor,
318  aPageInfo->GetHeightMils() * aScaleFactor );
319 
320  m_gal->SetIsStroke( true );
321  // Use a gray color for the border color
322  m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
323  m_gal->SetIsFill( false );
324  m_gal->DrawRectangle( origin, end );
325 }
int OutlineCount() const
Return the number of vertices in a given outline/hole.
const wxPoint & GetMarkerPos() const
Definition: ds_draw_item.h:266
The Cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:243
wxString BuildFullText(const wxString &aTextbase)
Return the full text corresponding to the aTextbase, after replacing format symbols by the correspond...
Definition: ds_painter.cpp:104
bool IsSelected() const
Definition: eda_item.h:122
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject)
Definition: common.cpp:57
COLOR4D m_layerColors[LAYER_ID_COUNT]
wxPoint GetPosition() const override
Definition: ds_draw_item.h:350
int GetHeightMils() const
Definition: page_info.h:133
void DrawBorder(const PAGE_INFO *aPageInfo, int aScaleFactor) const
Definition: ds_painter.cpp:314
double GetTextAngle() const
Definition: eda_text.h:195
bool IsBrightened() const
Definition: eda_item.h:125
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
An abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:76
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:106
const wxPoint & GetStart() const
Definition: ds_draw_item.h:133
static const wxString productName
Definition: ds_painter.cpp:43
const wxPoint & GetStart() const
Definition: ds_draw_item.h:219
static void GetContextualTextVars(wxArrayString *aVars)
Definition: title_block.cpp:73
int GetEffectiveTextPenWidth(int aDefaultWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultWidth.
Definition: eda_text.cpp:159
COLOR4D Brightened(double aFactor) const
Return a color that is brighter by a given factor, without modifying object.
Definition: color4d.h:278
A graphic text.
Definition: ds_draw_item.h:297
const wxPoint GetEnd() const
Definition: eda_rect.h:112
SHAPE_POLY_SET & GetPolygons()
Definition: ds_draw_item.h:170
VECTOR2< double > VECTOR2D
Definition: vector2d.h:621
PGM_BASE * PgmOrNull()
similar to PGM_BASE& Pgm(), but return a reference that can be nullptr when running a shared lib from...
Definition: cvpcb.cpp:125
wxString GetBuildVersion()
Get the full KiCad version string.
static void GetTextVars(wxArrayString *aVars)
Definition: ds_painter.cpp:89
virtual void update()
Precalculates extra colors for layers (e.g.
SHAPE_LINE_CHAIN & Outline(int aIndex)
const wxPoint GetOrigin() const
Definition: eda_rect.h:110
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:53
wxSize GetPageSize() const
Definition: ds_draw_item.h:265
A rectangle with thick segment showing the page limits and a marker showing the coordinate origin.
Definition: ds_draw_item.h:252
Definition: color4d.h:59
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
Non filled rectangle with thick segment.
Definition: ds_draw_item.h:205
COLOR4D GetColor(int aLayer) const
DS_DATA_ITEM * GetPeer() const
Definition: ds_draw_item.h:63
VECTOR2< T > Rotate(double aAngle) const
Rotate the vector by a given angle.
Definition: vector2d.h:371
double GetMarkerSize() const
Definition: ds_draw_item.h:268
see class PGM_BASE
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...
Definition: ds_painter.cpp:71
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Handle the component boundary box.
Definition: eda_rect.h:42
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:99
The common library.
Color settings are a bit different than most of the settings objects in that there can be more than o...
const wxPoint & GetTextPos() const
Definition: eda_text.h:268
const wxPoint & GetEnd() const
Definition: ds_draw_item.h:221
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.
Definition: ds_painter.cpp:172
virtual int GetPenWidth() const
Definition: ds_draw_item.h:70
BASE_SCREEN class implementation.
void LoadColors(const COLOR_SETTINGS *aSettings) override
Definition: ds_painter.cpp:57
virtual wxString GetShownText(int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition: eda_text.h:162
const wxPoint & GetEnd() const
Definition: ds_draw_item.h:135
int GetWidthMils() const
Definition: page_info.h:130
void draw(const DS_DRAW_ITEM_LINE *aItem, int aLayer) const
Definition: ds_painter.cpp:194
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103