KiCad PCB EDA Suite
ws_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-2019 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 <fctsys.h>
27 #include <pgm_base.h>
28 #include <gr_basic.h>
29 #include <common.h>
30 #include <base_screen.h>
31 #include <eda_draw_frame.h>
32 #include <title_block.h>
33 #include <build_version.h>
35 #include <ws_draw_item.h>
37 
38 #include <ws_painter.h>
39 #include <ws_data_item.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 
67 }
68 
69 
70 const COLOR4D& WS_RENDER_SETTINGS::GetColor( const VIEW_ITEM* aItem, int aLayer ) const
71 {
72  const EDA_ITEM* item = dynamic_cast<const EDA_ITEM*>( aItem );
73 
74  if( item )
75  {
76  // Selection disambiguation
77  if( item->IsBrightened() )
78  return m_brightenedColor;
79 
80  if( item->IsSelected() )
81  return m_selectedColor;
82  }
83 
84  return m_normalColor;
85 }
86 
87 
88 // returns the full text corresponding to the aTextbase,
89 // after replacing format symbols by the corresponding value
90 wxString WS_DRAW_ITEM_LIST::BuildFullText( const wxString& aTextbase )
91 {
92  wxString msg;
93 
94  /* Known formats
95  * %% = replaced by %
96  * %K = Kicad version
97  * %Z = paper format name (A4, USLetter)
98  * %Y = company name
99  * %D = date
100  * %R = revision
101  * %S = sheet number
102  * %N = number of sheets
103  * %L = layer name
104  * %Cx = comment (x = 0 to 9 to identify the comment)
105  * %F = filename
106  * %P = sheet path (sheet full name)
107  * %T = title
108  */
109 
110  for( unsigned ii = 0; ii < aTextbase.Len(); ii++ )
111  {
112  if( aTextbase[ii] != '%' )
113  {
114  msg << aTextbase[ii];
115  continue;
116  }
117 
118  if( ++ii >= aTextbase.Len() )
119  break;
120 
121  wxChar format = aTextbase[ii];
122  switch( format )
123  {
124  case '%':
125  msg += '%';
126  break;
127 
128  case 'D':
129  if( m_titleBlock )
130  msg += m_titleBlock->GetDate();
131  break;
132 
133  case 'R':
134  if( m_titleBlock )
135  msg += m_titleBlock->GetRevision();
136  break;
137 
138  case 'K':
139  msg += productName + Pgm().App().GetAppName();
140  msg += wxT( " " ) + GetBuildVersion();
141  break;
142 
143  case 'Z':
144  if( m_paperFormat )
145  msg += *m_paperFormat;
146  break;
147 
148  case 'S':
149  msg << m_sheetNumber;
150  break;
151 
152  case 'N':
153  msg << m_sheetCount;
154  break;
155 
156  case 'F':
157  {
158  wxFileName fn( m_fileName );
159  msg += fn.GetFullName();
160  }
161  break;
162 
163  case 'L':
164  if( m_sheetLayer )
165  msg += *m_sheetLayer;
166  break;
167 
168  case 'P':
169  msg += m_sheetFullName;
170  break;
171 
172  case 'Y':
173  if( m_titleBlock )
174  msg += m_titleBlock->GetCompany();
175  break;
176 
177  case 'T':
178  if( m_titleBlock )
179  msg += m_titleBlock->GetTitle();
180  break;
181 
182  case 'C':
183  format = aTextbase[++ii];
184  switch( format )
185  {
186  case '0':
187  case '1':
188  case '2':
189  case '3':
190  case '4':
191  case '5':
192  case '6':
193  case '7':
194  case '8':
195  case '9':
196  if( m_titleBlock )
197  msg += m_titleBlock->GetComment( format - '0');
198  break;
199 
200  default:
201  break;
202  }
203 
204  default:
205  break;
206  }
207  }
208 
209  return msg;
210 }
211 
212 
213 void TITLE_BLOCK::Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
214 
215 {
216  // Don't write the title block information if there is nothing to write.
217  bool isempty = true;
218  for( unsigned idx = 0; idx < m_tbTexts.GetCount(); idx++ )
219  {
220  if( ! m_tbTexts[idx].IsEmpty() )
221  {
222  isempty = false;
223  break;
224  }
225  }
226 
227  if( !isempty )
228  {
229  aFormatter->Print( aNestLevel, "(title_block\n" );
230 
231  if( !GetTitle().IsEmpty() )
232  aFormatter->Print( aNestLevel+1, "(title %s)\n",
233  aFormatter->Quotew( GetTitle() ).c_str() );
234 
235  if( !GetDate().IsEmpty() )
236  aFormatter->Print( aNestLevel+1, "(date %s)\n",
237  aFormatter->Quotew( GetDate() ).c_str() );
238 
239  if( !GetRevision().IsEmpty() )
240  aFormatter->Print( aNestLevel+1, "(rev %s)\n",
241  aFormatter->Quotew( GetRevision() ).c_str() );
242 
243  if( !GetCompany().IsEmpty() )
244  aFormatter->Print( aNestLevel+1, "(company %s)\n",
245  aFormatter->Quotew( GetCompany() ).c_str() );
246 
247  for( int ii = 0; ii < 9; ii++ )
248  {
249  if( !GetComment(ii).IsEmpty() )
250  aFormatter->Print( aNestLevel+1, "(comment %d %s)\n", ii+1,
251  aFormatter->Quotew( GetComment(ii) ).c_str() );
252  }
253 
254  aFormatter->Print( aNestLevel, ")\n\n" );
255  }
256 }
257 
258 
259 bool KIGFX::WS_PAINTER::Draw( const VIEW_ITEM* aItem, int aLayer )
260 {
261  auto item = static_cast<const EDA_ITEM*>( aItem );
262 
263  switch( item->Type() )
264  {
265  case WSG_LINE_T: draw( (WS_DRAW_ITEM_LINE*) item, aLayer ); break;
266  case WSG_POLY_T: draw( (WS_DRAW_ITEM_POLYPOLYGONS*) item, aLayer ); break;
267  case WSG_RECT_T: draw( (WS_DRAW_ITEM_RECT*) item, aLayer ); break;
268  case WSG_TEXT_T: draw( (WS_DRAW_ITEM_TEXT*) item, aLayer ); break;
269  case WSG_BITMAP_T: draw( (WS_DRAW_ITEM_BITMAP*) item, aLayer ); break;
270  case WSG_PAGE_T: draw( (WS_DRAW_ITEM_PAGE*) item, aLayer ); break;
271  default: return false;
272  }
273 
274  return true;
275 }
276 
277 
278 void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_LINE* aItem, int aLayer ) const
279 {
280  m_gal->SetIsStroke( true );
281  m_gal->SetIsFill( false );
282  m_gal->SetStrokeColor( m_renderSettings.GetColor( aItem, aLayer ) );
283  m_gal->SetLineWidth( aItem->GetPenWidth() );
284  m_gal->DrawLine( VECTOR2D( aItem->GetStart() ), VECTOR2D( aItem->GetEnd() ) );
285 }
286 
287 
288 void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_RECT* aItem, int aLayer ) const
289 {
290  m_gal->SetIsStroke( true );
291  m_gal->SetIsFill( false );
292  m_gal->SetStrokeColor( m_renderSettings.GetColor( aItem, aLayer ) );
293  m_gal->SetLineWidth( aItem->GetPenWidth() );
294  m_gal->DrawRectangle( VECTOR2D( aItem->GetStart() ), VECTOR2D( aItem->GetEnd() ) );
295 }
296 
297 
298 void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_POLYPOLYGONS* aItem, int aLayer ) const
299 {
300  m_gal->SetFillColor( m_renderSettings.GetColor( aItem, aLayer ) );
301  m_gal->SetIsFill( true );
302  m_gal->SetIsStroke( false );
303 
305 
306  for( int idx = 0; idx < item->GetPolygons().OutlineCount(); ++idx )
307  {
308  SHAPE_LINE_CHAIN& outline = item->GetPolygons().Outline( idx );
309  m_gal->DrawPolygon( outline );
310  }
311 }
312 
313 
314 void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_TEXT* aItem, int aLayer ) const
315 {
316  VECTOR2D position( aItem->GetTextPos().x, aItem->GetTextPos().y );
317 
318  m_gal->Save();
319  m_gal->Translate( position );
320  m_gal->Rotate( -aItem->GetTextAngle() * M_PI / 1800.0 );
321  m_gal->SetStrokeColor( m_renderSettings.GetColor( aItem, aLayer ) );
322  m_gal->SetLineWidth( aItem->GetThickness() );
323  m_gal->SetTextAttributes( aItem );
324  m_gal->SetIsFill( false );
325  m_gal->SetIsStroke( true );
326  m_gal->StrokeText( aItem->GetShownText(), VECTOR2D( 0, 0 ), 0.0 );
327  m_gal->Restore();
328 }
329 
330 
331 void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_BITMAP* aItem, int aLayer ) const
332 {
333  m_gal->Save();
334  auto* bitmap = static_cast<WS_DATA_ITEM_BITMAP*>( aItem->GetPeer() );
335 
336  VECTOR2D position = aItem->GetPosition();
337  m_gal->Translate( position );
338 
339  // When the image scale factor is not 1.0, we need to modify the actual scale
340  // as the image scale factor is similar to a local zoom
341  double img_scale = bitmap->m_ImageBitmap->GetScale();
342 
343  if( img_scale != 1.0 )
344  m_gal->Scale( VECTOR2D( img_scale, img_scale ) );
345 
346  m_gal->DrawBitmap( *bitmap->m_ImageBitmap );
347 
348 #if 0 // For bounding box debug purpose only
349  EDA_RECT bbox = aItem->GetBoundingBox();
350  m_gal->SetIsFill( true );
351  m_gal->SetIsStroke( true );
352  m_gal->SetFillColor( COLOR4D( 1, 1, 1, 0.4 ) );
353  m_gal->SetStrokeColor( COLOR4D( 0, 0, 0, 1 ) );
354 
355  if( img_scale != 1.0 )
356  m_gal->Scale( VECTOR2D( 1.0, 1.0 ) );
357 
358  m_gal->DrawRectangle( VECTOR2D( bbox.GetOrigin() ) - position,
359  VECTOR2D( bbox.GetEnd() ) - position );
360 #endif
361 
362  m_gal->Restore();
363 }
364 
365 
366 void KIGFX::WS_PAINTER::draw( const WS_DRAW_ITEM_PAGE* aItem, int aLayer ) const
367 {
368  VECTOR2D origin = VECTOR2D( 0.0, 0.0 );
369  VECTOR2D end = VECTOR2D( aItem->GetPageSize().x,
370  aItem->GetPageSize().y );
371 
372  m_gal->SetIsStroke( true );
373 
374  // Use a gray color for the border color
375  m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
376  m_gal->SetIsFill( false );
377  m_gal->DrawRectangle( origin, end );
378 
379  // Draw the corner marker
380  double marker_size = aItem->GetMarkerSize();
381 
382  m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
383  VECTOR2D pos = VECTOR2D( aItem->GetMarkerPos().x, aItem->GetMarkerPos().y );
384 
385  // Draw a cirle and a X
386  m_gal->DrawCircle( pos, marker_size );
387  m_gal->DrawLine( VECTOR2D( pos.x - marker_size, pos.y - marker_size),
388  VECTOR2D( pos.x + marker_size, pos.y + marker_size ) );
389  m_gal->DrawLine( VECTOR2D( pos.x + marker_size, pos.y - marker_size),
390  VECTOR2D( pos.x - marker_size, pos.y + marker_size ) );
391 }
392 
393 
394 void KIGFX::WS_PAINTER::DrawBorder( const PAGE_INFO* aPageInfo, int aScaleFactor ) const
395 {
396  VECTOR2D origin = VECTOR2D( 0.0, 0.0 );
397  VECTOR2D end = VECTOR2D( aPageInfo->GetWidthMils() * aScaleFactor,
398  aPageInfo->GetHeightMils() * aScaleFactor );
399 
400  m_gal->SetIsStroke( true );
401  // Use a gray color for the border color
402  m_gal->SetStrokeColor( m_renderSettings.m_pageBorderColor );
403  m_gal->SetIsFill( false );
404  m_gal->DrawRectangle( origin, end );
405 }
const wxPoint & GetStart() const
Definition: ws_draw_item.h:206
WS_DATA_ITEM * GetPeer() const
Definition: ws_draw_item.h:66
const wxPoint & GetEnd() const
Definition: ws_draw_item.h:208
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:103
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes.
int OutlineCount() const
Returns the number of outlines in the set
Class CAIRO_GAL is the cairo implementation of the graphics abstraction layer.
Definition: color4d.cpp:131
bool IsSelected() const
Definition: base_struct.h:225
const wxPoint & GetEnd() const
Definition: ws_draw_item.h:124
COLOR4D m_layerColors[LAYER_ID_COUNT]
Colors for all layers (normal)
Definition: painter.h:260
int GetHeightMils() const
Definition: page_info.h:140
SHAPE_POLY_SET & GetPolygons()
Definition: ws_draw_item.h:167
int GetPenWidth() const
Definition: ws_draw_item.h:205
double GetTextAngle() const
Definition: eda_text.h:158
OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a convenient ...
Definition: richio.h:327
bool IsBrightened() const
Definition: base_struct.h:228
int GetThickness() const
Return the pen width.
Definition: eda_text.h:148
void LoadColors(const COLOR_SETTINGS *aSettings) override
Definition: ws_painter.cpp:57
Add new GAL layers here.
VIEW_ITEM - is an abstract base class for deriving all objects that can be added to a VIEW.
Definition: view_item.h:84
COLOR4D Brightened(double aFactor) const
Function Brightened Returns a color that is brighter by a given factor, without modifying object.
Definition: color4d.h:200
const wxPoint GetEnd() const
Definition: eda_rect.h:116
VECTOR2< double > VECTOR2D
Definition: vector2d.h:593
void DrawBorder(const PAGE_INFO *aPageInfo, int aScaleFactor) const
Definition: ws_painter.cpp:394
wxString GetBuildVersion()
Get the full KiCad version string.
virtual void update()
Function update Precalculates extra colors for layers (e.g.
Definition: painter.cpp:54
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
const wxPoint GetOrigin() const
Definition: eda_rect.h:114
PAGE_INFO describes the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
const wxPoint & GetStart() const
Definition: ws_draw_item.h:122
int GetPenWidth() const
Definition: ws_draw_item.h:121
void draw(const WS_DRAW_ITEM_LINE *aItem, int aLayer) const
Definition: ws_painter.cpp:278
Definition: colors.h:60
virtual void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControlBits) const
Function Format outputs the object to aFormatter in s-expression form.
Definition: ws_painter.cpp:213
std::string Quotew(const wxString &aWrapee)
Definition: richio.cpp:472
COLOR4D GetColor(int aLayer) const
wxSize GetPageSize() const
Definition: ws_draw_item.h:250
COLOR4D m_backgroundColor
The background color.
Definition: painter.h:292
VECTOR2< T > Rotate(double aAngle) const
Function Rotate rotates the vector by a given angle.
Definition: vector2d.h:377
see class PGM_BASE
wxString BuildFullText(const wxString &aTextbase)
Function BuildFullText returns the full text corresponding to the aTextbase, after replacing format s...
Definition: ws_painter.cpp:90
const wxPoint GetPosition() const override
Definition: ws_draw_item.h:330
SHAPE_LINE_CHAIN.
virtual const COLOR4D & GetColor(const VIEW_ITEM *aItem, int aLayer) const override
Function GetColor Returns the color that should be used to draw the specific VIEW_ITEM on the specifi...
Definition: ws_painter.cpp:70
EDA_RECT handles the component boundary box.
Definition: eda_rect.h:44
double GetMarkerSize() const
Definition: ws_draw_item.h:253
EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boards.
Definition: base_struct.h:166
The common library.
const wxPoint & GetTextPos() const
Definition: eda_text.h:232
virtual wxString GetShownText() const
Return the string actually shown after processing of the base text.
Definition: eda_text.h:129
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:404
BASE_SCREEN class implementation.
virtual bool Draw(const VIEW_ITEM *, int) override
Function Draw Takes an instance of VIEW_ITEM and passes it to a function that know how to draw the it...
Definition: ws_painter.cpp:259
static const wxString productName
Definition: ws_painter.cpp:43
const wxPoint & GetMarkerPos() const
Definition: ws_draw_item.h:251
int GetWidthMils() const
Definition: page_info.h:137
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:40