KiCad PCB EDA Suite
plot_brditems_plotter.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  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, you may find one here:
18  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
19  * or you may search the http://www.gnu.org website for the version 2 license,
20  * or you may write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22  */
23 
24 #include <fctsys.h>
25 #include <common.h>
26 #include <plotter.h>
27 #include <base_struct.h>
28 #include <gr_text.h>
29 #include <trigo.h>
30 #include <macros.h>
31 #include <pcb_base_frame.h>
32 
33 #include <class_board.h>
34 #include <class_module.h>
35 #include <class_track.h>
36 #include <class_edge_mod.h>
37 #include <class_pcb_text.h>
38 #include <class_zone.h>
39 #include <class_drawsegment.h>
40 #include <class_pcb_target.h>
41 #include <class_dimension.h>
43 
44 #include <pcbnew.h>
45 #include <pcbplot.h>
46 #include <gbr_metadata.h>
47 
48 /* class BRDITEMS_PLOTTER is a helper class to plot board items
49  * and a group of board items
50  */
51 
53 {
54  COLOR4D color = m_board->Colors().GetLayerColor( aLayer );
55 
56  // A hack to avoid plotting ahite itmen in white color, expecting the paper
57  // is also white: use a non white color:
58  if( color == COLOR4D::WHITE )
59  color = COLOR4D( LIGHTGRAY );
60 
61  return color;
62 }
63 
64 
65 void BRDITEMS_PLOTTER::PlotPad( D_PAD* aPad, COLOR4D aColor, EDA_DRAW_MODE_T aPlotMode )
66 {
67  wxPoint shape_pos = aPad->ShapePos();
68  GBR_METADATA gbr_metadata;
69 
70  bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
71  bool isOnExternalCopperLayer = ( m_layerMask & LSET::ExternalCuMask() ).any();
72  bool isPadOnBoardTechLayers = ( aPad->GetLayerSet() & LSET::AllBoardTechMask() ).any();
73 
74  gbr_metadata.SetCmpReference( aPad->GetParent()->GetReference() );
75 
76  if( isOnCopperLayer )
77  {
78  gbr_metadata.SetNetAttribType( GBR_NETINFO_ALL );
79  gbr_metadata.SetCopper( true );
80 
81  if( isOnExternalCopperLayer )
82  {
83  const bool useUTF8 = false;
84  const bool useQuoting = false;
85  gbr_metadata.SetPadName( aPad->GetName(), useUTF8, useQuoting );
86 
87  if( !aPad->GetName().IsEmpty() )
88  gbr_metadata.SetPadPinFunction( aPad->GetPinFunction(), useUTF8, useQuoting );
89  }
90 
91  gbr_metadata.SetNetName( aPad->GetNetname() );
92 
93  // Some pads are mechanical pads ( through hole or smd )
94  // when this is the case, they have no pad name and/or are not plated.
95  // In this case gerber files have slightly different attributes.
96  if( aPad->GetAttribute() == PAD_ATTRIB_HOLE_NOT_PLATED || aPad->GetName().IsEmpty() )
97  gbr_metadata.m_NetlistMetadata.m_NotInNet = true;
98 
99  if( !isOnExternalCopperLayer || !isPadOnBoardTechLayers )
100  {
101  // On internal layers one cannot use the GBR_NETLIST_METADATA::GBR_INFO_FLASHED_PAD
102  // attribute when the component is on an external layer (most of the case)
103  // Also, if a SMD pad is not on a tech layer (masks) use also net+cmp attribute, because
104  // it is not really a pad (can be a "pad", actually a node in a virtual component)
107 
108  if( !isPadOnBoardTechLayers )
109  // such a pad is not soldered and is not a connecting point.
110  // Just set aperture attribute as conductor
111  // If it is a through hole pad, it will be adjusted later
113 
114  switch( aPad->GetAttribute() )
115  {
116  case PAD_ATTRIB_HOLE_NOT_PLATED: // Mechanical pad through hole
118  break;
119 
120  case PAD_ATTRIB_STANDARD : // Pad through hole, a hole is also expected
122  break;
123 
124  default:
125  break;
126  }
127  }
128  else // Some attributes are reserved to the external copper layers
129  {
130  switch( aPad->GetAttribute() )
131  {
132  case PAD_ATTRIB_HOLE_NOT_PLATED: // Mechanical pad through hole
134  break;
135 
136  case PAD_ATTRIB_STANDARD : // Pad through hole, a hole is also expected
138  break;
139 
140  case PAD_ATTRIB_CONN: // Connector pads have no solder paste.
142  break;
143 
144  case PAD_ATTRIB_SMD: // SMD pads (One external copper layer only) with solder paste
145  // If round shape, perhaps a BGA pad but not sure: so use currently SMDPAD attribute,
146  // until an explicit BGA pad attribute is added in Pcbnew
147 // if( aPad->GetShape() == PAD_SHAPE_CIRCLE )
148 // gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_BGAPAD_CUDEF );
149 // else
151  break;
152  }
153  }
154 
157  }
158  else
159  {
161  }
162 
163  // Set plot color (change WHITE to LIGHTGRAY because
164  // the white items are not seen on a white paper or screen
165  m_plotter->SetColor( aColor != WHITE ? aColor : LIGHTGRAY);
166 
167  switch( aPad->GetShape() )
168  {
169  case PAD_SHAPE_CIRCLE:
170  m_plotter->FlashPadCircle( shape_pos, aPad->GetSize().x, aPlotMode, &gbr_metadata );
171  break;
172 
173  case PAD_SHAPE_OVAL:
174  m_plotter->FlashPadOval( shape_pos, aPad->GetSize(),
175  aPad->GetOrientation(), aPlotMode, &gbr_metadata );
176  break;
177 
178  case PAD_SHAPE_TRAPEZOID:
179  {
180  wxPoint coord[4];
181  aPad->BuildPadPolygon( coord, wxSize(0,0), 0 );
182  m_plotter->FlashPadTrapez( shape_pos, coord,
183  aPad->GetOrientation(), aPlotMode, &gbr_metadata );
184  }
185  break;
186 
187  case PAD_SHAPE_ROUNDRECT:
188  m_plotter->FlashPadRoundRect( shape_pos, aPad->GetSize(), aPad->GetRoundRectCornerRadius(),
189  aPad->GetOrientation(), aPlotMode, &gbr_metadata );
190  break;
191 
193  {
194  SHAPE_POLY_SET polygons;
195  const int corner_radius = aPad->GetRoundRectCornerRadius( aPad->GetSize() );
196  TransformRoundChamferedRectToPolygon( polygons, shape_pos, aPad->GetSize(),
197  aPad->GetOrientation(), corner_radius, aPad->GetChamferRectRatio(),
199 
200  if( polygons.OutlineCount() == 0 )
201  break;
202 
203  int min_dim = std::min( aPad->GetSize().x, aPad->GetSize().y ) /2;
204  m_plotter->FlashPadCustom( shape_pos,wxSize( min_dim, min_dim ), &polygons, aPlotMode, &gbr_metadata );
205  }
206  break;
207 
208  case PAD_SHAPE_CUSTOM:
209  {
210  SHAPE_POLY_SET polygons;
211  aPad->MergePrimitivesAsPolygon( &polygons );
212 
213  if( polygons.OutlineCount() == 0 )
214  break;
215 
216  aPad->CustomShapeAsPolygonToBoardPosition( &polygons, shape_pos, aPad->GetOrientation() );
217  m_plotter->FlashPadCustom( shape_pos, aPad->GetSize(), &polygons, aPlotMode, &gbr_metadata );
218  }
219  break;
220 
221  case PAD_SHAPE_RECT:
222  default:
223  m_plotter->FlashPadRect( shape_pos, aPad->GetSize(),
224  aPad->GetOrientation(), aPlotMode, &gbr_metadata );
225  break;
226  }
227 }
228 
229 
231 {
232  TEXTE_MODULE* textModule = &aModule->Reference();
233  LAYER_NUM textLayer = textModule->GetLayer();
234 
235  // Reference and value are specfic items, not in graphic items list
236  if( GetPlotReference() && m_layerMask[textLayer]
237  && ( textModule->IsVisible() || GetPlotInvisibleText() ) )
238  {
239  PlotTextModule( textModule, getColor( textLayer ) );
240  }
241 
242  textModule = &aModule->Value();
243  textLayer = textModule->GetLayer();
244 
245  if( GetPlotValue() && m_layerMask[textLayer]
246  && ( textModule->IsVisible() || GetPlotInvisibleText() ) )
247  {
248  PlotTextModule( textModule, getColor( textLayer ) );
249  }
250 
251  for( auto item : aModule->GraphicalItems() )
252  {
253  textModule = dyn_cast<TEXTE_MODULE*>( item );
254 
255  if( !textModule )
256  continue;
257 
258  if( !textModule->IsVisible() )
259  continue;
260 
261  textLayer = textModule->GetLayer();
262 
263  if( textLayer >= PCB_LAYER_ID_COUNT )
264  return false;
265 
266  if( !m_layerMask[textLayer] )
267  continue;
268 
269  if( textModule->GetText() == wxT( "%R" ) && !GetPlotReference() )
270  continue;
271 
272  if( textModule->GetText() == wxT( "%V" ) && !GetPlotValue() )
273  continue;
274 
275  PlotTextModule( textModule, getColor( textLayer ) );
276  }
277 
278  return true;
279 }
280 
281 
282 // plot items like text and graphics, but not tracks and module
284 {
285  for( auto item : m_board->Drawings() )
286  {
287  switch( item->Type() )
288  {
289  case PCB_LINE_T: PlotDrawSegment( (DRAWSEGMENT*) item); break;
290  case PCB_TEXT_T: PlotTextePcb( (TEXTE_PCB*) item ); break;
291  case PCB_DIMENSION_T: PlotDimension( (DIMENSION*) item ); break;
292  case PCB_TARGET_T: PlotPcbTarget( (PCB_TARGET*) item ); break;
293  default: break;
294  }
295  }
296 }
297 
299 {
300  wxSize size;
301  wxPoint pos;
302  double orient;
303  int thickness;
304 
305  if( aColor == COLOR4D::WHITE )
306  aColor = COLOR4D( LIGHTGRAY );
307 
308  m_plotter->SetColor( aColor );
309 
310  // calculate some text parameters :
311  size = pt_texte->GetTextSize();
312  pos = pt_texte->GetTextPos();
313 
314  orient = pt_texte->GetDrawRotation();
315 
316  thickness = pt_texte->GetThickness();
317 
318  if( pt_texte->IsMirrored() )
319  size.x = -size.x; // Text is mirrored
320 
321  // Non bold texts thickness is clamped at 1/6 char size by the low level draw function.
322  // but in Pcbnew we do not manage bold texts and thickness up to 1/4 char size
323  // (like bold text) and we manage the thickness.
324  // So we set bold flag to true
325  bool allow_bold = pt_texte->IsBold() || thickness;
326 
327  GBR_METADATA gbr_metadata;
329  MODULE* parent = static_cast<MODULE*> ( pt_texte->GetParent() );
330  gbr_metadata.SetCmpReference( parent->GetReference() );
331 
332  m_plotter->Text( pos, aColor, pt_texte->GetShownText(), orient, size,
333  pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(),
334  thickness, pt_texte->IsItalic(), allow_bold, false, &gbr_metadata );
335 }
336 
337 
339 {
340  if( !m_layerMask[aDim->GetLayer()] )
341  return;
342 
343  DRAWSEGMENT draw;
344 
345  draw.SetWidth( aDim->GetWidth() );
346  draw.SetLayer( aDim->GetLayer() );
347 
349 
350  // Set plot color (change WHITE to LIGHTGRAY because
351  // the white items are not seen on a white paper or screen
353 
354  PlotTextePcb( &aDim->Text() );
355 
356  draw.SetStart( aDim->m_crossBarO );
357  draw.SetEnd( aDim->m_crossBarF );
358  PlotDrawSegment( &draw );
359 
360  draw.SetStart( aDim->m_featureLineGO);
361  draw.SetEnd( aDim->m_featureLineGF );
362  PlotDrawSegment( &draw );
363 
364  draw.SetStart( aDim->m_featureLineDO );
365  draw.SetEnd( aDim->m_featureLineDF );
366  PlotDrawSegment( &draw );
367 
368  draw.SetStart( aDim->m_crossBarF );
369  draw.SetEnd( aDim->m_arrowD1F );
370  PlotDrawSegment( &draw );
371 
372  draw.SetStart( aDim->m_crossBarF );
373  draw.SetEnd( aDim->m_arrowD2F );
374  PlotDrawSegment( &draw );
375 
376  draw.SetStart( aDim->m_crossBarO );
377  draw.SetEnd( aDim->m_arrowG1F );
378  PlotDrawSegment( &draw );
379 
380  draw.SetStart( aDim->m_crossBarO );
381  draw.SetEnd( aDim->m_arrowG2F );
382  PlotDrawSegment( &draw );
383 }
384 
385 
387 {
388  int dx1, dx2, dy1, dy2, radius;
389 
390  if( !m_layerMask[aMire->GetLayer()] )
391  return;
392 
393  m_plotter->SetColor( getColor( aMire->GetLayer() ) );
394 
395  DRAWSEGMENT draw;
396 
397  draw.SetShape( S_CIRCLE );
398  draw.SetWidth( aMire->GetWidth() );
399  draw.SetLayer( aMire->GetLayer() );
400  draw.SetStart( aMire->GetPosition() );
401  radius = aMire->GetSize() / 3;
402 
403  if( aMire->GetShape() ) // shape X
404  radius = aMire->GetSize() / 2;
405 
406  // Draw the circle
407  draw.SetEnd( wxPoint( draw.GetStart().x + radius, draw.GetStart().y ));
408 
409  PlotDrawSegment( &draw );
410 
411  draw.SetShape( S_SEGMENT );
412 
413  radius = aMire->GetSize() / 2;
414  dx1 = radius;
415  dy1 = 0;
416  dx2 = 0;
417  dy2 = radius;
418 
419  if( aMire->GetShape() ) // Shape X
420  {
421  dx1 = dy1 = radius;
422  dx2 = dx1;
423  dy2 = -dy1;
424  }
425 
426  wxPoint mirePos( aMire->GetPosition() );
427 
428  // Draw the X or + shape:
429  draw.SetStart( wxPoint( mirePos.x - dx1, mirePos.y - dy1 ));
430  draw.SetEnd( wxPoint( mirePos.x + dx1, mirePos.y + dy1 ));
431  PlotDrawSegment( &draw );
432 
433  draw.SetStart( wxPoint( mirePos.x - dx2, mirePos.y - dy2 ));
434  draw.SetEnd( wxPoint( mirePos.x + dx2, mirePos.y + dy2 ));
435  PlotDrawSegment( &draw );
436 }
437 
438 
439 // Plot footprints graphic items (outlines)
441 {
442  for( auto module : m_board->Modules() )
443  {
444  for( auto item : module->GraphicalItems() )
445  {
446  EDGE_MODULE* edge = dyn_cast<EDGE_MODULE*>( item );
447 
448  if( edge && m_layerMask[edge->GetLayer()] )
449  Plot_1_EdgeModule( edge );
450  }
451  }
452 }
453 
454 
455 //* Plot a graphic item (outline) relative to a footprint
457 {
458  if( aEdge->Type() != PCB_MODULE_EDGE_T )
459  return;
460 
461  m_plotter->SetColor( getColor( aEdge->GetLayer() ) );
462 
463  int thickness = aEdge->GetWidth();
464 
465  wxPoint pos( aEdge->GetStart() );
466  wxPoint end( aEdge->GetEnd() );
467 
468  GBR_METADATA gbr_metadata;
470  MODULE* parent = static_cast<MODULE*> ( aEdge->GetParent() );
471  gbr_metadata.SetCmpReference( parent->GetReference() );
472 
473  bool isOnCopperLayer = ( m_layerMask & LSET::AllCuMask() ).any();
474 
475  if( isOnCopperLayer )
476  {
477  gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_ETCHEDCMP );
478  gbr_metadata.SetCopper( true );
479  }
480  else if( aEdge->GetLayer() == Edge_Cuts ) // happens also when plotting copper layers
481  {
482  gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_EDGECUT );
483  }
484 
485  int radius; // Circle/arc radius.
486 
487  switch( aEdge->GetShape() )
488  {
489  case S_SEGMENT:
490  m_plotter->ThickSegment( pos, end, thickness, GetPlotMode(), &gbr_metadata );
491  break;
492 
493  case S_CIRCLE:
494  radius = KiROUND( GetLineLength( end, pos ) );
495  m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode(), &gbr_metadata );
496  break;
497 
498  case S_ARC:
499  {
500  radius = KiROUND( GetLineLength( end, pos ) );
501  double startAngle = ArcTangente( end.y - pos.y, end.x - pos.x );
502  double endAngle = startAngle + aEdge->GetAngle();
503 
504  // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg
505  if( std::abs( aEdge->GetAngle() ) == 3600.0 )
506  m_plotter->ThickCircle( pos, radius * 2, thickness, GetPlotMode(), &gbr_metadata );
507  else
508  m_plotter->ThickArc( pos, -endAngle, -startAngle, radius, thickness, GetPlotMode(), &gbr_metadata );
509  }
510  break;
511 
512  case S_POLYGON:
513  if( aEdge->IsPolyShapeValid() )
514  {
515  const std::vector<wxPoint> &polyPoints = aEdge->BuildPolyPointsList();
516 
517  // We must compute true coordinates from m_PolyList
518  // which are relative to module position, orientation 0
519  MODULE *module = aEdge->GetParentModule();
520 
521  std::vector<wxPoint> cornerList;
522 
523  cornerList.reserve( polyPoints.size() );
524 
525  for( wxPoint corner : polyPoints )
526  {
527  if( module )
528  {
529  RotatePoint( &corner, module->GetOrientation() );
530  corner += module->GetPosition();
531  }
532 
533  cornerList.push_back( corner );
534  }
535 
536  if( !aEdge->IsPolygonFilled() )
537  {
538  for( size_t i = 1; i < cornerList.size(); i++ )
539  {
540  m_plotter->ThickSegment( cornerList[i - 1], cornerList[i], thickness,
541  GetPlotMode(), &gbr_metadata );
542  }
543 
544  m_plotter->ThickSegment( cornerList.back(), cornerList.front(), thickness,
545  GetPlotMode(), &gbr_metadata );
546 
547  }
548  else
549  {
550  // This must be simplified and fractured to prevent overlapping polygons
551  // from generating invalid Gerber files
552 
553  SHAPE_LINE_CHAIN line( cornerList );
554  SHAPE_POLY_SET tmpPoly;
555 
556  line.SetClosed( true );
557  tmpPoly.AddOutline( line );
559 
560  for( int jj = 0; jj < tmpPoly.OutlineCount(); ++jj )
561  {
562  SHAPE_LINE_CHAIN &poly = tmpPoly.Outline( jj );
563  m_plotter->PlotPoly( poly, FILLED_SHAPE, thickness, &gbr_metadata );
564  }
565  }
566  }
567  break;
568 
569  case S_CURVE:
570  m_plotter->BezierCurve( aEdge->GetStart(), aEdge->GetBezControl1(),
571  aEdge->GetBezControl2(), aEdge->GetEnd(),
572  0, thickness );
573  break;
574 
575  default:
576  wxASSERT_MSG( false, "Unhandled EDGE_MODULE shape" );
577  break;
578  }
579 }
580 
581 
582 // Plot a PCB Text, i.e. a text found on a copper or technical layer
584 {
585  double orient;
586  int thickness;
587  wxPoint pos;
588  wxSize size;
589  wxString shownText( pt_texte->GetShownText() );
590 
591  if( shownText.IsEmpty() )
592  return;
593 
594  if( !m_layerMask[pt_texte->GetLayer()] )
595  return;
596 
597  GBR_METADATA gbr_metadata;
598 
599  if( IsCopperLayer( pt_texte->GetLayer() ) )
601 
602  COLOR4D color = getColor( pt_texte->GetLayer() );
604 
605  size = pt_texte->GetTextSize();
606  pos = pt_texte->GetTextPos();
607  orient = pt_texte->GetTextAngle();
608  thickness = pt_texte->GetThickness();
609 
610  if( pt_texte->IsMirrored() )
611  size.x = -size.x;
612 
613  // Non bold texts thickness is clamped at 1/6 char size by the low level draw function.
614  // but in Pcbnew we do not manage bold texts and thickness up to 1/4 char size
615  // (like bold text) and we manage the thickness.
616  // So we set bold flag to true
617  bool allow_bold = pt_texte->IsBold() || thickness;
618 
619  if( pt_texte->IsMultilineAllowed() )
620  {
621  std::vector<wxPoint> positions;
622  wxArrayString strings_list;
623  wxStringSplit( shownText, strings_list, '\n' );
624  positions.reserve( strings_list.Count() );
625 
626  pt_texte->GetPositionsOfLinesOfMultilineText( positions, strings_list.Count() );
627 
628  for( unsigned ii = 0; ii < strings_list.Count(); ii++ )
629  {
630  wxString& txt = strings_list.Item( ii );
631  m_plotter->Text( positions[ii], color, txt, orient, size,
632  pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(),
633  thickness, pt_texte->IsItalic(), allow_bold, false, &gbr_metadata );
634  }
635  }
636  else
637  {
638  m_plotter->Text( pos, color, shownText, orient, size,
639  pt_texte->GetHorizJustify(), pt_texte->GetVertJustify(),
640  thickness, pt_texte->IsItalic(), allow_bold, false, &gbr_metadata );
641  }
642 }
643 
644 
646 {
647  if( polysList.IsEmpty() )
648  return;
649 
650  GBR_METADATA gbr_metadata;
651 
652  bool isOnCopperLayer = aZone->IsOnCopperLayer();
653 
654  if( isOnCopperLayer )
655  {
656  gbr_metadata.SetNetName( aZone->GetNetname() );
657  gbr_metadata.SetCopper( true );
658 
659  // Zones with no net name can exist.
660  // they are not used to connect items, so the aperture attribute cannot
661  // be set as conductor
662  if( aZone->GetNetname().IsEmpty() )
664  else
665  {
668  }
669  }
670 
671  // We need a buffer to store corners coordinates:
672  std::vector< wxPoint > cornerList;
673 
674  m_plotter->SetColor( getColor( aZone->GetLayer() ) );
675 
676  /* Plot all filled areas: filled areas have a filled area and a thick
677  * outline (depending on the fill area option we must plot the filled area itself
678  * and plot the thick outline itself, if the thickness has meaning (at least is > 1)
679  *
680  * in non filled mode the outline is plotted, but not the filling items
681  */
682  int outline_thickness = aZone->GetFilledPolysUseThickness() ? aZone->GetMinThickness() : 0;
683 
684  for( int idx = 0; idx < polysList.OutlineCount(); ++idx )
685  {
686  SHAPE_LINE_CHAIN& outline = polysList.Outline( idx );
687 
688  cornerList.clear();
689  cornerList.reserve( outline.PointCount() );
690 
691  for( int ic = 0; ic < outline.PointCount(); ++ic )
692  {
693  cornerList.emplace_back( wxPoint( outline.CPoint( ic ) ) );
694  }
695 
696  if( cornerList.size() ) // Plot the current filled area outline
697  {
698  // First, close the outline
699  if( cornerList[0] != cornerList[cornerList.size() - 1] )
700  cornerList.push_back( cornerList[0] );
701 
702  // Plot the current filled area and its outline
703  if( GetPlotMode() == FILLED )
704  {
705  m_plotter->PlotPoly( cornerList, FILLED_SHAPE, outline_thickness, &gbr_metadata );
706  }
707  else
708  {
709  if( outline_thickness )
710  {
711  for( unsigned jj = 1; jj < cornerList.size(); jj++ )
712  {
713  m_plotter->ThickSegment( cornerList[jj -1], cornerList[jj],
714  outline_thickness,
715  GetPlotMode(), &gbr_metadata );
716  }
717  }
718 
720  }
721  }
722  }
723 }
724 
725 
726 /* Plot items type DRAWSEGMENT on layers allowed by aLayerMask
727  */
729 {
730  if( !m_layerMask[aSeg->GetLayer()] )
731  return;
732 
733  int radius = 0;
734  double StAngle = 0, EndAngle = 0;
735  int thickness = aSeg->GetWidth();
736 
737  m_plotter->SetColor( getColor( aSeg->GetLayer() ) );
738 
739  wxPoint start( aSeg->GetStart() );
740  wxPoint end( aSeg->GetEnd() );
741 
742  GBR_METADATA gbr_metadata;
743 
744  if( aSeg->GetLayer() == Edge_Cuts )
746 
747  switch( aSeg->GetShape() )
748  {
749  case S_CIRCLE:
750  radius = KiROUND( GetLineLength( end, start ) );
751  m_plotter->ThickCircle( start, radius * 2, thickness, GetPlotMode(), &gbr_metadata );
752  break;
753 
754  case S_ARC:
755  radius = KiROUND( GetLineLength( end, start ) );
756  StAngle = ArcTangente( end.y - start.y, end.x - start.x );
757  EndAngle = StAngle + aSeg->GetAngle();
758 
759  // when startAngle == endAngle ThickArc() doesn't know whether it's 0 deg and 360 deg
760  if( std::abs( aSeg->GetAngle() ) == 3600.0 )
761  m_plotter->ThickCircle( start, radius * 2, thickness, GetPlotMode(), &gbr_metadata );
762  else
763  m_plotter->ThickArc( start, -EndAngle, -StAngle, radius, thickness, GetPlotMode(), &gbr_metadata );
764  break;
765 
766  case S_CURVE:
767  m_plotter->BezierCurve( aSeg->GetStart(), aSeg->GetBezControl1(),
768  aSeg->GetBezControl2(), aSeg->GetEnd(),
769  0, thickness );
770  break;
771 
772  case S_POLYGON:
773  {
774  if( !aSeg->IsPolygonFilled() )
775  {
776  for( auto it = aSeg->GetPolyShape().CIterateSegments( 0 ); it; it++ )
777  {
778  auto seg = it.Get();
779  m_plotter->ThickSegment( wxPoint( seg.A ), wxPoint( seg.B ),
780  thickness, GetPlotMode(), &gbr_metadata );
781  }
782  }
783  else
784  {
785  m_plotter->SetCurrentLineWidth( thickness, &gbr_metadata );
786  // Draw the polygon: only one polygon is expected
787  // However we provide a multi polygon shape drawing
788  // ( for the future or to show a non expected shape )
789  // This must be simplified and fractured to prevent overlapping polygons
790  // from generating invalid Gerber files
791  auto tmpPoly = SHAPE_POLY_SET( aSeg->GetPolyShape() );
793 
794  for( int jj = 0; jj < tmpPoly.OutlineCount(); ++jj )
795  {
796  SHAPE_LINE_CHAIN& poly = tmpPoly.Outline( jj );
797  m_plotter->PlotPoly( poly, FILLED_SHAPE, thickness, &gbr_metadata );
798  }
799  }
800  }
801  break;
802 
803  default:
804  m_plotter->ThickSegment( start, end, thickness, GetPlotMode(), &gbr_metadata );
805  }
806 }
807 
808 
812 void BRDITEMS_PLOTTER::plotOneDrillMark( PAD_DRILL_SHAPE_T aDrillShape, const wxPoint &aDrillPos,
813  wxSize aDrillSize, const wxSize &aPadSize,
814  double aOrientation, int aSmallDrill )
815 {
816  // Small drill marks have no significance when applied to slots
817  if( aSmallDrill && aDrillShape == PAD_DRILL_SHAPE_CIRCLE )
818  aDrillSize.x = std::min( aSmallDrill, aDrillSize.x );
819 
820  // Round holes only have x diameter, slots have both
821  aDrillSize.x -= getFineWidthAdj();
822  aDrillSize.x = Clamp( 1, aDrillSize.x, aPadSize.x - 1 );
823 
824  if( aDrillShape == PAD_DRILL_SHAPE_OBLONG )
825  {
826  aDrillSize.y -= getFineWidthAdj();
827  aDrillSize.y = Clamp( 1, aDrillSize.y, aPadSize.y - 1 );
828  m_plotter->FlashPadOval( aDrillPos, aDrillSize, aOrientation, GetPlotMode(), NULL );
829  }
830  else
831  m_plotter->FlashPadCircle( aDrillPos, aDrillSize.x, GetPlotMode(), NULL );
832 }
833 
834 
836 {
837  /* If small drills marks were requested prepare a clamp value to pass
838  to the helper function */
839  int small_drill = (GetDrillMarksType() == PCB_PLOT_PARAMS::SMALL_DRILL_SHAPE) ?
840  SMALL_DRILL : 0;
841 
842  /* In the filled trace mode drill marks are drawn white-on-black to scrape
843  the underlying pad. This works only for drivers supporting color change,
844  obviously... it means that:
845  - PS, SVG and PDF output is correct (i.e. you have a 'donut' pad)
846  - In HPGL you can't see them
847  - In gerbers you can't see them, too. This is arguably the right thing to
848  do since having drill marks and high speed drill stations is a sure
849  recipe for broken tools and angry manufacturers. If you *really* want them
850  you could start a layer with negative polarity to scrape the film.
851  - In DXF they go into the 'WHITE' layer. This could be useful.
852  */
853  if( GetPlotMode() == FILLED )
855 
856  for( auto pts : m_board->Tracks() )
857  {
858  const VIA* via = dyn_cast<const VIA*>( pts );
859 
860  if( via )
861  {
863  wxSize( via->GetDrillValue(), 0 ),
864  wxSize( via->GetWidth(), 0 ), 0, small_drill );
865  }
866  }
867 
868  for( auto Module : m_board->Modules() )
869  {
870  for( auto pad : Module->Pads() )
871  {
872  if( pad->GetDrillSize().x == 0 )
873  continue;
874 
875  plotOneDrillMark( pad->GetDrillShape(),
876  pad->GetPosition(), pad->GetDrillSize(),
877  pad->GetSize(), pad->GetOrientation(),
878  small_drill );
879  }
880  }
881 
882  if( GetPlotMode() == FILLED )
884 }
void wxStringSplit(const wxString &aText, wxArrayString &aStrings, wxChar aSplitter)
Split aString to a string list separated at aSplitter.
Definition: common.cpp:188
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
a class to handle special data (items attributes) during plot.
bool IsBold() const
Definition: eda_text.h:167
#define SMALL_DRILL
Definition: pcbplot.h:72
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:60
double GetOrientation() const
Definition: class_module.h:218
aperture used for etched components
Definition: gbr_metadata.h:83
TEXTE_MODULE & Reference()
Definition: class_module.h:473
void SetShape(STROKE_T aShape)
int OutlineCount() const
Returns the number of outlines in the set
aperture used for edge connecto pad (outer layers)
Definition: gbr_metadata.h:93
EDA_TEXT_VJUSTIFY_T GetVertJustify() const
Definition: eda_text.h:185
bool IsMirrored() const
Definition: eda_text.h:173
int GetWidth() const
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Function GetLineLength returns the length of a line segment defined by aPointA and aPointB.
Definition: trigo.h:202
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: macros.h:139
TEXTE_PCB class definition.
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:66
virtual void SetLayer(PCB_LAYER_ID aLayer)
Function SetLayer sets the layer this item is on.
wxPoint m_crossBarF
print info associated to a component (TO.C attribute)
wxPoint m_arrowD1F
virtual void SetColor(COLOR4D color)=0
virtual void ThickCircle(const wxPoint &pos, int diametre, int width, EDA_DRAW_MODE_T tracemode, void *aData)
Definition: plotter.cpp:560
const wxPoint & GetStart() const
Definition: class_track.h:109
STROKE_T GetShape() const
void PlotPad(D_PAD *aPad, COLOR4D aColor, EDA_DRAW_MODE_T aPlotMode)
Plot a pad.
int GetSize() const
bool IsVisible() const
Definition: eda_text.h:170
void SetNetAttribType(int aNetAttribType)
Definition: gbr_metadata.h:163
void PlotDimension(DIMENSION *Dimension)
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aCornerBuffer, const wxPoint &aPosition, const wxSize &aSize, double aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aApproxErrorMax, int aMinSegPerCircleCount)
convert a rectangle with rounded corners and/or chamfered corners to a polygon Convert rounded corner...
int color
Definition: DXF_plotter.cpp:62
polygon (not yet used for tracks, but could be in microwave apps)
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:62
virtual PCB_LAYER_ID GetLayer() const override
Function GetLayer returns the primary layer this item is on.
Definition: class_zone.cpp:203
PLOTTER * m_plotter
Definition: pcbplot.h:78
void PlotDrillMarks()
Function PlotDrillMarks Draw a drill mark for pads and vias.
double GetTextAngle() const
Definition: eda_text.h:158
bool GetFilledPolysUseThickness() const
Definition: class_zone.h:598
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:92
aperture used for through hole component on outer layer
Definition: gbr_metadata.h:88
bool PlotAllTextsModule(MODULE *aModule)
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:531
int GetThickness() const
Function GetThickness returns pen width.
Definition: eda_text.h:148
usual segment : line with rounded ends
virtual void BezierCurve(const wxPoint &aStart, const wxPoint &aControl1, const wxPoint &aControl2, const wxPoint &aEnd, int aTolerance, int aLineThickness=USE_DEFAULT_LINE_WIDTH)
Generic fallback: Cubic Bezier curve rendered as a polyline In Kicad the bezier curves have 4 control...
Definition: plotter.cpp:202
wxPoint m_featureLineDF
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:206
DRAWINGS & GraphicalItems()
Definition: class_module.h:186
const wxString & GetPinFunction() const
Definition: class_pad.h:211
const std::vector< wxPoint > BuildPolyPointsList() const
Build and return the list of corners in a std::vector<wxPoint> It must be used only to convert the SH...
virtual wxString GetShownText() const override
Returns the string actually shown after processing of the base text.
virtual void PlotPoly(const std::vector< wxPoint > &aCornerList, FILL_T aFill, int aWidth=USE_DEFAULT_LINE_WIDTH, void *aData=NULL)=0
Function PlotPoly.
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
int PointCount() const
Function PointCount()
#define abs(a)
Definition: auxiliary.h:84
PAD_DRILL_SHAPE_T
Enum PAD_DRILL_SHAPE_T is the set of pad drill shapes, used with D_PAD::{Set,Get}DrillShape()
Definition: pad_shapes.h:47
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:94
void PlotFilledAreas(ZONE_CONTAINER *aZone, SHAPE_POLY_SET &aPolysList)
BOARD * m_board
Definition: pcbplot.h:79
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:445
Definitions for tracks, vias and zones.
virtual void ThickArc(const wxPoint &centre, double StAngle, double EndAngle, int rayon, int width, EDA_DRAW_MODE_T tracemode, void *aData)
Definition: plotter.cpp:522
virtual void FlashPadCustom(const wxPoint &aPadPos, const wxSize &aSize, SHAPE_POLY_SET *aPolygons, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadCustom
This file contains miscellaneous commonly used macros and functions.
const wxString GetReference() const
Function GetReference.
Definition: class_module.h:432
int GetChamferPositions() const
has meaning only for chamfered rect pads
Definition: class_pad.h:709
void SetPadPinFunction(const wxString &aPadPinFunction, bool aUseUTF8, bool aEscapeString)
Definition: gbr_metadata.h:180
virtual void Text(const wxPoint &aPos, const COLOR4D aColor, const wxString &aText, double aOrient, const wxSize &aSize, enum EDA_TEXT_HJUSTIFY_T aH_justify, enum EDA_TEXT_VJUSTIFY_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed=false, void *aData=NULL)
Draws text with the plotter.
Definition: gr_text.cpp:215
Classes used in Pcbnew, CvPcb and GerbView.
Board plot function definition file.
wxPoint m_featureLineGO
bool IsItalic() const
Definition: eda_text.h:164
DIMENSION class definition.
const VECTOR2I & CPoint(int aIndex) const
Function Point()
COLOR4D GetLayerColor(LAYER_NUM aLayer) const
Function GetLayerColor.
void SetClosed(bool aClosed)
Function SetClosed()
virtual void FlashPadCircle(const wxPoint &aPadPos, int aDiameter, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadCircle
int GetWidth() const
EDA_TEXT_HJUSTIFY_T GetHorizJustify() const
Definition: eda_text.h:184
double ArcTangente(int dy, int dx)
Definition: trigo.cpp:160
int GetDrillValue() const
Function GetDrillValue "calculates" the drill value for vias (m-Drill if > 0, or default drill value ...
MODULES & Modules()
Definition: class_board.h:227
void PlotPcbTarget(PCB_TARGET *PtMire)
bool MergePrimitivesAsPolygon(SHAPE_POLY_SET *aMergedPolygon=NULL)
Merge all basic shapes, converted to a polygon in one polygon, in m_customShapeAsPolygon.
Class SHAPE_POLY_SET.
void SetPadName(const wxString &aPadname, bool aUseUTF8=false, bool aEscapeString=false)
Definition: gbr_metadata.h:175
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:472
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
EDA_DRAW_MODE_T
Definition: eda_text.h:59
void PlotBoardGraphicItems()
plot items like text and graphics, but not tracks and modules
COLOR4D GetColor() const
const wxSize & GetTextSize() const
Definition: eda_text.h:223
Arcs (with rounded ends)
double GetChamferRectRatio() const
has meaning only for chamfered rect pads
Definition: class_pad.h:686
virtual void FlashPadRoundRect(const wxPoint &aPadPos, const wxSize &aSize, int aCornerRadius, double aOrient, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadRoundRect
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:442
wxPoint m_arrowG1F
void Plot_1_EdgeModule(EDGE_MODULE *aEdge)
wxPoint m_arrowD2F
wxPoint m_arrowG2F
MODULE * GetParentModule() const
Function GetParentModule returns a pointer to the parent module, or NULL if DRAWSEGMENT does not belo...
static LSET ExternalCuMask()
Function ExternalCuMask returns a mask holding the Front and Bottom layers.
Definition: lset.cpp:706
const wxString & GetName() const
Definition: class_pad.h:203
aperture used for mechanical pads (NPTH)
Definition: gbr_metadata.h:94
SHAPE_POLY_SET & GetPolyShape()
Bezier Curve.
const wxString & GetNetname() const
Function GetNetname.
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:63
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:99
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
int GetWidth() const
bool IsMultilineAllowed() const
Definition: eda_text.h:182
aperture used for connected items like tracks (not vias)
Definition: gbr_metadata.h:84
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:100
void SetStart(const wxPoint &aStart)
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
bool GetPlotValue() const
MODULE * GetParent() const
Definition: class_pad.h:167
void BuildPadPolygon(wxPoint aCoord[4], wxSize aInflateValue, double aRotation) const
Function BuildPadPolygon Has meaning only for polygonal pads (trapezoid and rectangular) Build the Co...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
void SetNetName(const wxString &aNetname)
Definition: gbr_metadata.h:173
double GetAngle() const
const COLORS_DESIGN_SETTINGS & Colors() const
Function GetColorSettings.
Definition: class_board.h:561
virtual void FlashPadRect(const wxPoint &aPadPos, const wxSize &aSize, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadRect
int GetWidth() const
Definition: class_track.h:103
Class to handle a graphic segment.
void plotOneDrillMark(PAD_DRILL_SHAPE_T aDrillShape, const wxPoint &aDrillPos, wxSize aDrillSize, const wxSize &aPadSize, double aOrientation, int aSmallDrill)
Helper function to plot a single drill mark.
virtual void FlashPadOval(const wxPoint &aPadPos, const wxSize &aSize, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadOval
Class SHAPE_LINE_CHAIN.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees,...
Definition: class_pad.h:422
virtual void ThickSegment(const wxPoint &start, const wxPoint &end, int width, EDA_DRAW_MODE_T tracemode, void *aData)
Definition: plotter.cpp:505
void CustomShapeAsPolygonToBoardPosition(SHAPE_POLY_SET *aMergedPolygon, wxPoint aPosition, double aRotation) const
When created, the corners coordinates are relative to the pad position, orientation 0,...
LSET m_layerMask
Definition: pcbplot.h:80
TEXTE_PCB & Text()
size_t i
Definition: json11.cpp:649
wxPoint ShapePos() const
Definition: class_pad.cpp:562
int GetShape() const
const wxPoint & GetBezControl2() const
aperture used for SMD pad with a solder mask defined by the solder mask
Definition: gbr_metadata.h:90
The common library.
int GetMinThickness() const
Definition: class_zone.h:185
bool GetPlotInvisibleText() const
bool IsPolyShapeValid() const
void PlotTextePcb(TEXTE_PCB *pt_texte)
Definition: colors.h:49
void SetEnd(const wxPoint &aEnd)
int GetRoundRectCornerRadius() const
Function GetRoundRectCornerRadius Has meaning only for rounded rect pads.
Definition: class_pad.h:562
bool IsCopperLayer(LAYER_NUM aLayerId)
Function IsCopperLayer tests whether a layer is a copper layer.
static LSET AllBoardTechMask()
Function AllTechMask returns a mask holding board technical layers (no CU layer) on both side.
Definition: lset.cpp:753
const wxPoint & GetTextPos() const
Definition: eda_text.h:232
void GetPositionsOfLinesOfMultilineText(std::vector< wxPoint > &aPositions, int aLineCount) const
Function GetPositionsOfLinesOfMultilineText Populates aPositions with the position of each line of a ...
Definition: eda_text.cpp:399
wxPoint m_crossBarO
PCB_TARGET class definition.
void SetApertureAttrib(GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB aApertAttribute)
Definition: gbr_metadata.h:153
bool m_NotInNet
true if a pad of a footprint cannot be connected (for instance a mechanical NPTH, ot a not named pad)...
const wxPoint & GetBezControl1() const
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
int getFineWidthAdj()
Definition: pcbplot.h:95
GBR_NETLIST_METADATA m_NetlistMetadata
a item to handle object attribute:
Definition: gbr_metadata.h:205
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:237
CONST_SEGMENT_ITERATOR CIterateSegments(int aFirst, int aLast, bool aIterateHoles=false) const
Returns an iterator object, for iterating between aFirst and aLast outline, with or without holes (de...
Module description (excepted pads)
virtual wxString GetShownText() const
Returns the string actually shown after processing of the base text.
Definition: eda_text.h:129
aperture used for not connected items (texts, outlines on copper)
Definition: gbr_metadata.h:86
const wxSize & GetSize() const
Definition: class_pad.h:300
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:91
BOARD_ITEM_CONTAINER * GetParent() const
void SetCopper(bool aValue)
Definition: gbr_metadata.h:195
virtual void FlashPadTrapez(const wxPoint &aPadPos, const wxPoint *aCorners, double aPadOrient, EDA_DRAW_MODE_T aTraceMode, void *aData)=0
virtual function FlashPadTrapez flash a trapezoidal pad
double GetDrawRotation() const
DrillMarksType GetDrillMarksType() const
wxPoint m_featureLineDO
print info associated to a net (TO.N attribute)
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
bool IsPolygonFilled() const
Polygonal shape is not always filled.
bool GetPlotReference() const
const wxPoint GetPosition() const override
Definition: class_module.h:213
DRAWINGS & Drawings()
Definition: class_board.h:236
virtual const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:124
void SetCmpReference(const wxString &aComponentRef)
Definition: gbr_metadata.h:185
COLOR4D getColor(LAYER_NUM aLayer)
Function getColor.
Class DIMENSION.
TRACKS & Tracks()
Definition: class_board.h:218
bool IsOnCopperLayer() const override
Function IsOnCopperLayer.
Definition: class_zone.cpp:209
const wxPoint GetPosition() const override
#define GBR_NETINFO_ALL
KICAD_T Type() const
Function Type()
Definition: base_struct.h:210
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:114
#define min(a, b)
Definition: auxiliary.h:85
EDA_DRAW_MODE_T GetPlotMode() const
virtual void SetCurrentLineWidth(int width, void *aData=NULL)=0
Set the line width for the next drawing.
void PlotDrawSegment(DRAWSEGMENT *PtSegm)
Class COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:39
wxPoint m_featureLineGF
void SetWidth(int aWidth)
void PlotTextModule(TEXTE_MODULE *aTextMod, COLOR4D aColor)