You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1054 lines
33 KiB

17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
18 years ago
17 years ago
18 years ago
17 years ago
17 years ago
17 years ago
18 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
17 years ago
  1. /*************************/
  2. /* Common plot routines. */
  3. /*************************/
  4. #include "fctsys.h"
  5. #include "common.h"
  6. #include "plot_common.h"
  7. #include "base_struct.h"
  8. #include "drawtxt.h"
  9. #include "confirm.h"
  10. #include "pcbnew.h"
  11. #include "pcbplot.h"
  12. #include "trigo.h"
  13. #include "class_board_design_settings.h"
  14. static void Plot_Edges_Modules( PLOTTER* plotter, BOARD* pcb, int masque_layer,
  15. GRTraceMode trace_mode );
  16. static void PlotTextModule( PLOTTER* plotter, TEXTE_MODULE* pt_texte,
  17. GRTraceMode trace_mode );
  18. /* Creates the plot for silkscreen layers
  19. */
  20. void WinEDA_BasePcbFrame::Plot_Serigraphie( PLOTTER* plotter,
  21. int masque_layer,
  22. GRTraceMode trace_mode )
  23. {
  24. wxPoint pos, shape_pos;
  25. wxSize size;
  26. bool trace_val, trace_ref;
  27. D_PAD* pt_pad;
  28. TEXTE_MODULE* pt_texte;
  29. EDA_BaseStruct* PtStruct;
  30. /* Plot edge layer and graphic items */
  31. for( PtStruct = m_Pcb->m_Drawings;
  32. PtStruct != NULL;
  33. PtStruct = PtStruct->Next() )
  34. {
  35. switch( PtStruct->Type() )
  36. {
  37. case TYPE_DRAWSEGMENT:
  38. PlotDrawSegment( plotter,
  39. (DRAWSEGMENT*) PtStruct,
  40. masque_layer,
  41. trace_mode );
  42. break;
  43. case TYPE_TEXTE:
  44. PlotTextePcb( plotter,
  45. (TEXTE_PCB*) PtStruct,
  46. masque_layer,
  47. trace_mode );
  48. break;
  49. case TYPE_COTATION:
  50. PlotCotation( plotter,
  51. (COTATION*) PtStruct,
  52. masque_layer,
  53. trace_mode );
  54. break;
  55. case TYPE_MIRE:
  56. PlotMirePcb( plotter,
  57. (MIREPCB*) PtStruct,
  58. masque_layer,
  59. trace_mode );
  60. break;
  61. case TYPE_MARKER_PCB:
  62. break;
  63. default:
  64. DisplayError( this,
  65. wxT( "Plot_Serigraphie() error: unexpected Type()" ) );
  66. break;
  67. }
  68. }
  69. /* Plot footprint outlines : */
  70. Plot_Edges_Modules( plotter, m_Pcb, masque_layer, trace_mode );
  71. /* Plot pads (creates pads outlines, for pads on silkscreen layers) */
  72. if( g_pcb_plot_options.PlotPadsOnSilkLayer )
  73. {
  74. for( MODULE* Module = m_Pcb->m_Modules;
  75. Module;
  76. Module = Module->Next() )
  77. {
  78. for( pt_pad = (D_PAD*) Module->m_Pads;
  79. pt_pad != NULL;
  80. pt_pad = pt_pad->Next() )
  81. {
  82. /* See if the pad is on this layer */
  83. if( (pt_pad->m_Masque_Layer & masque_layer) == 0 )
  84. continue;
  85. shape_pos = pt_pad->ReturnShapePos();
  86. pos = shape_pos;
  87. size = pt_pad->m_Size;
  88. switch( pt_pad->m_PadShape & 0x7F )
  89. {
  90. case PAD_CIRCLE:
  91. plotter->flash_pad_circle( pos, size.x, FILAIRE );
  92. break;
  93. case PAD_OVAL:
  94. plotter->flash_pad_oval( pos, size,
  95. pt_pad->m_Orient, FILAIRE );
  96. break;
  97. case PAD_TRAPEZOID:
  98. {
  99. wxSize delta;
  100. delta = pt_pad->m_DeltaSize;
  101. plotter->flash_pad_trapez( pos, size,
  102. delta, pt_pad->m_Orient,
  103. FILAIRE );
  104. break;
  105. }
  106. case PAD_RECT:
  107. default:
  108. plotter->flash_pad_rect( pos,
  109. size,
  110. pt_pad->m_Orient,
  111. FILAIRE );
  112. break;
  113. }
  114. }
  115. }
  116. }
  117. /* Plot footprints fields (ref, value ...) */
  118. for( MODULE* Module = m_Pcb->m_Modules; Module; Module = Module->Next() )
  119. {
  120. /* see if we want to plot VALUE and REF fields */
  121. trace_val = g_pcb_plot_options.Sel_Texte_Valeur;
  122. trace_ref = g_pcb_plot_options.Sel_Texte_Reference;
  123. TEXTE_MODULE* text = Module->m_Reference;
  124. unsigned textLayer = text->GetLayer();
  125. if( textLayer >= 32 )
  126. {
  127. wxString errMsg;
  128. errMsg.Printf( _( "Your BOARD has a bad layer number of %u for \
  129. module\n %s's \"reference\" text." ),
  130. textLayer, GetChars( Module->GetReference() ) );
  131. DisplayError( this, errMsg );
  132. return;
  133. }
  134. if( ( ( 1 << textLayer ) & masque_layer ) == 0 )
  135. trace_ref = FALSE;
  136. if( text->m_NoShow && !g_pcb_plot_options.Sel_Texte_Invisible )
  137. trace_ref = FALSE;
  138. text = Module->m_Value;
  139. textLayer = text->GetLayer();
  140. if( textLayer > 32 )
  141. {
  142. wxString errMsg;
  143. errMsg.Printf( _( "Your BOARD has a bad layer number of %u for \
  144. module\n %s's \"value\" text." ),
  145. textLayer, GetChars( Module->GetReference() ) );
  146. DisplayError( this, errMsg );
  147. return;
  148. }
  149. if( ( (1 << textLayer) & masque_layer ) == 0 )
  150. trace_val = FALSE;
  151. if( text->m_NoShow && !g_pcb_plot_options.Sel_Texte_Invisible )
  152. trace_val = FALSE;
  153. /* Plot text fields, if allowed */
  154. if( trace_ref )
  155. PlotTextModule( plotter, Module->m_Reference, trace_mode );
  156. if( trace_val )
  157. PlotTextModule( plotter, Module->m_Value, trace_mode );
  158. for( pt_texte = (TEXTE_MODULE*) Module->m_Drawings.GetFirst();
  159. pt_texte != NULL;
  160. pt_texte = pt_texte->Next() )
  161. {
  162. if( pt_texte->Type() != TYPE_TEXTE_MODULE )
  163. continue;
  164. if( !g_pcb_plot_options.Sel_Texte_Divers )
  165. continue;
  166. if( (pt_texte->m_NoShow)
  167. && !g_pcb_plot_options.Sel_Texte_Invisible )
  168. continue;
  169. textLayer = pt_texte->GetLayer();
  170. if( textLayer >= 32 )
  171. {
  172. wxString errMsg;
  173. errMsg.Printf( _( "Your BOARD has a bad layer number of %u \
  174. for module\n %s's \"module text\" text of %s." ),
  175. textLayer, GetChars( Module->GetReference() ),
  176. GetChars( pt_texte->m_Text ) );
  177. DisplayError( this, errMsg );
  178. return;
  179. }
  180. if( !( ( 1 << textLayer ) & masque_layer ) )
  181. continue;
  182. PlotTextModule( plotter, pt_texte, trace_mode );
  183. }
  184. }
  185. /* Plot filled areas */
  186. for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ )
  187. {
  188. ZONE_CONTAINER* edge_zone = m_Pcb->GetArea( ii );
  189. if( ( ( 1 << edge_zone->GetLayer() ) & masque_layer ) == 0 )
  190. continue;
  191. PlotFilledAreas( plotter, edge_zone, trace_mode );
  192. }
  193. // Plot segments used to fill zone areas (outdated, but here for old boards
  194. // compatibility):
  195. for( SEGZONE* seg = m_Pcb->m_Zone; seg != NULL; seg = seg->Next() )
  196. {
  197. if( ( ( 1 << seg->GetLayer() ) & masque_layer ) == 0 )
  198. continue;
  199. plotter->thick_segment( seg->m_Start, seg->m_End, seg->m_Width,
  200. trace_mode );
  201. }
  202. }
  203. static void PlotTextModule( PLOTTER* plotter, TEXTE_MODULE* pt_texte,
  204. GRTraceMode trace_mode )
  205. {
  206. wxSize size;
  207. wxPoint pos;
  208. int orient, thickness;
  209. /* calculate some text parameters :*/
  210. size = pt_texte->m_Size;
  211. pos = pt_texte->m_Pos;
  212. orient = pt_texte->GetDrawRotation();
  213. thickness = pt_texte->m_Width;
  214. if( trace_mode == FILAIRE )
  215. thickness = -1;
  216. if( pt_texte->m_Mirror )
  217. NEGATE( size.x ); // Text is mirrored
  218. plotter->text( pos, BLACK,
  219. pt_texte->m_Text,
  220. orient, size,
  221. pt_texte->m_HJustify, pt_texte->m_VJustify,
  222. thickness, pt_texte->m_Italic, pt_texte->m_Bold );
  223. }
  224. void PlotCotation( PLOTTER* plotter, COTATION* Cotation, int masque_layer,
  225. GRTraceMode trace_mode )
  226. {
  227. DRAWSEGMENT* DrawTmp;
  228. if( (g_TabOneLayerMask[Cotation->GetLayer()] & masque_layer) == 0 )
  229. return;
  230. DrawTmp = new DRAWSEGMENT( NULL );
  231. DrawTmp->m_Width = (trace_mode==FILAIRE) ? -1 : Cotation->m_Width;
  232. DrawTmp->SetLayer( Cotation->GetLayer() );
  233. PlotTextePcb( plotter, Cotation->m_Text, masque_layer, trace_mode );
  234. DrawTmp->m_Start.x = Cotation->Barre_ox;
  235. DrawTmp->m_Start.y = Cotation->Barre_oy;
  236. DrawTmp->m_End.x = Cotation->Barre_fx;
  237. DrawTmp->m_End.y = Cotation->Barre_fy;
  238. PlotDrawSegment( plotter, DrawTmp, masque_layer, trace_mode );
  239. DrawTmp->m_Start.x = Cotation->TraitG_ox;
  240. DrawTmp->m_Start.y = Cotation->TraitG_oy;
  241. DrawTmp->m_End.x = Cotation->TraitG_fx;
  242. DrawTmp->m_End.y = Cotation->TraitG_fy;
  243. PlotDrawSegment( plotter, DrawTmp, masque_layer, trace_mode );
  244. DrawTmp->m_Start.x = Cotation->TraitD_ox;
  245. DrawTmp->m_Start.y = Cotation->TraitD_oy;
  246. DrawTmp->m_End.x = Cotation->TraitD_fx;
  247. DrawTmp->m_End.y = Cotation->TraitD_fy;
  248. PlotDrawSegment( plotter, DrawTmp, masque_layer, trace_mode );
  249. DrawTmp->m_Start.x = Cotation->FlecheD1_ox;
  250. DrawTmp->m_Start.y = Cotation->FlecheD1_oy;
  251. DrawTmp->m_End.x = Cotation->FlecheD1_fx;
  252. DrawTmp->m_End.y = Cotation->FlecheD1_fy;
  253. PlotDrawSegment( plotter, DrawTmp, masque_layer, trace_mode );
  254. DrawTmp->m_Start.x = Cotation->FlecheD2_ox;
  255. DrawTmp->m_Start.y = Cotation->FlecheD2_oy;
  256. DrawTmp->m_End.x = Cotation->FlecheD2_fx;
  257. DrawTmp->m_End.y = Cotation->FlecheD2_fy;
  258. PlotDrawSegment( plotter, DrawTmp, masque_layer, trace_mode );
  259. DrawTmp->m_Start.x = Cotation->FlecheG1_ox;
  260. DrawTmp->m_Start.y = Cotation->FlecheG1_oy;
  261. DrawTmp->m_End.x = Cotation->FlecheG1_fx;
  262. DrawTmp->m_End.y = Cotation->FlecheG1_fy;
  263. PlotDrawSegment( plotter, DrawTmp, masque_layer, trace_mode );
  264. DrawTmp->m_Start.x = Cotation->FlecheG2_ox;
  265. DrawTmp->m_Start.y = Cotation->FlecheG2_oy;
  266. DrawTmp->m_End.x = Cotation->FlecheG2_fx;
  267. DrawTmp->m_End.y = Cotation->FlecheG2_fy;
  268. PlotDrawSegment( plotter, DrawTmp, masque_layer, trace_mode );
  269. delete DrawTmp;
  270. }
  271. void PlotMirePcb( PLOTTER* plotter, MIREPCB* Mire, int masque_layer,
  272. GRTraceMode trace_mode )
  273. {
  274. DRAWSEGMENT* DrawTmp;
  275. int dx1, dx2, dy1, dy2, radius;
  276. if( (g_TabOneLayerMask[Mire->GetLayer()] & masque_layer) == 0 )
  277. return;
  278. DrawTmp = new DRAWSEGMENT( NULL );
  279. DrawTmp->m_Width = ( trace_mode == FILAIRE ) ? -1 : Mire->m_Width;
  280. DrawTmp->SetLayer( Mire->GetLayer() );
  281. DrawTmp->m_Start.x = Mire->m_Pos.x; DrawTmp->m_Start.y = Mire->m_Pos.y;
  282. DrawTmp->m_End.x = DrawTmp->m_Start.x + ( Mire->m_Size / 4 );
  283. DrawTmp->m_End.y = DrawTmp->m_Start.y;
  284. DrawTmp->m_Shape = S_CIRCLE;
  285. PlotDrawSegment( plotter, DrawTmp, masque_layer, trace_mode );
  286. DrawTmp->m_Shape = S_SEGMENT;
  287. radius = Mire->m_Size / 2;
  288. dx1 = radius;
  289. dy1 = 0;
  290. dx2 = 0;
  291. dy2 = radius;
  292. if( Mire->m_Shape ) /* Shape X */
  293. {
  294. dx1 = dy1 = ( radius * 7 ) / 5;
  295. dx2 = dx1;
  296. dy2 = -dy1;
  297. }
  298. DrawTmp->m_Start.x = Mire->m_Pos.x - dx1;
  299. DrawTmp->m_Start.y = Mire->m_Pos.y - dy1;
  300. DrawTmp->m_End.x = Mire->m_Pos.x + dx1;
  301. DrawTmp->m_End.y = Mire->m_Pos.y + dy1;
  302. PlotDrawSegment( plotter, DrawTmp, masque_layer, trace_mode );
  303. DrawTmp->m_Start.x = Mire->m_Pos.x - dx2;
  304. DrawTmp->m_Start.y = Mire->m_Pos.y - dy2;
  305. DrawTmp->m_End.x = Mire->m_Pos.x + dx2;
  306. DrawTmp->m_End.y = Mire->m_Pos.y + dy2;
  307. PlotDrawSegment( plotter, DrawTmp, masque_layer, trace_mode );
  308. delete DrawTmp;
  309. }
  310. /* Plot footprints graphic items (outlines) */
  311. void Plot_Edges_Modules( PLOTTER* plotter, BOARD* pcb, int masque_layer,
  312. GRTraceMode trace_mode )
  313. {
  314. for( MODULE* module = pcb->m_Modules; module; module = module->Next() )
  315. {
  316. for( EDGE_MODULE* edge = (EDGE_MODULE*) module->m_Drawings.GetFirst();
  317. edge;
  318. edge = edge->Next() )
  319. {
  320. if( edge->Type() != TYPE_EDGE_MODULE )
  321. continue;
  322. if( ( g_TabOneLayerMask[edge->GetLayer()] & masque_layer ) == 0 )
  323. continue;
  324. Plot_1_EdgeModule( plotter, edge, trace_mode );
  325. }
  326. }
  327. }
  328. /* Plot a graphic item (outline) relative to a footprint */
  329. void Plot_1_EdgeModule( PLOTTER* plotter, EDGE_MODULE* PtEdge,
  330. GRTraceMode trace_mode )
  331. {
  332. int type_trace; /* Type of item to plot. */
  333. int thickness; /* Segment thickness. */
  334. int radius; /* Circle radius. */
  335. int StAngle, EndAngle;
  336. wxPoint pos, end;
  337. if( PtEdge->Type() != TYPE_EDGE_MODULE )
  338. return;
  339. type_trace = PtEdge->m_Shape;
  340. thickness = PtEdge->m_Width;
  341. pos = PtEdge->m_Start;
  342. end = PtEdge->m_End;
  343. switch( type_trace )
  344. {
  345. case S_SEGMENT:
  346. plotter->thick_segment( pos, end, thickness, trace_mode );
  347. break;
  348. case S_CIRCLE:
  349. radius = (int) hypot( (double) ( end.x - pos.x ),
  350. (double) ( end.y - pos.y ) );
  351. plotter->thick_circle( pos, radius * 2, thickness, trace_mode );
  352. break;
  353. case S_ARC:
  354. radius = (int) hypot( (double) ( end.x - pos.x ),
  355. (double) ( end.y - pos.y ) );
  356. StAngle = ArcTangente( end.y - pos.y, end.x - pos.x );
  357. EndAngle = StAngle + PtEdge->m_Angle;
  358. plotter->thick_arc( pos,
  359. -EndAngle,
  360. -StAngle,
  361. radius,
  362. thickness,
  363. trace_mode );
  364. break;
  365. case S_POLYGON:
  366. {
  367. // We must compute true coordinates from m_PolyList
  368. // which are relative to module position, orientation 0
  369. MODULE* Module = NULL;
  370. if( PtEdge->GetParent() && (PtEdge->GetParent()->Type() == TYPE_MODULE) )
  371. Module = (MODULE*) PtEdge->GetParent();
  372. int* ptr_base =
  373. (int*) MyMalloc( 2 * PtEdge->m_PolyPoints.size() * sizeof(int) );
  374. int* ptr = ptr_base;
  375. int* source = (int*) &PtEdge->m_PolyPoints[0];
  376. for( unsigned ii = 0; ii < PtEdge->m_PolyPoints.size(); ii++ )
  377. {
  378. int x = *source++;
  379. int y = *source++;
  380. if( Module )
  381. {
  382. RotatePoint( &x, &y, Module->m_Orient );
  383. x += Module->m_Pos.x;
  384. y += Module->m_Pos.y;
  385. }
  386. x += PtEdge->m_Start0.x;
  387. y += PtEdge->m_Start0.y;
  388. *ptr++ = x;
  389. *ptr++ = y;
  390. }
  391. plotter->poly( PtEdge->m_PolyPoints.size(), ptr_base, NO_FILL,
  392. thickness );
  393. free( ptr_base );
  394. }
  395. break;
  396. }
  397. }
  398. /* Plot a PCB Text, i;e. a text found on a copper or technical layer */
  399. void PlotTextePcb( PLOTTER* plotter, TEXTE_PCB* pt_texte, int masque_layer,
  400. GRTraceMode trace_mode )
  401. {
  402. int orient, thickness;
  403. wxPoint pos;
  404. wxSize size;
  405. if( pt_texte->m_Text.IsEmpty() )
  406. return;
  407. if( ( g_TabOneLayerMask[pt_texte->GetLayer()] & masque_layer ) == 0 )
  408. return;
  409. size = pt_texte->m_Size;
  410. pos = pt_texte->m_Pos;
  411. orient = pt_texte->m_Orient;
  412. thickness = ( trace_mode==FILAIRE ) ? -1 : pt_texte->m_Width;
  413. if( pt_texte->m_Mirror )
  414. size.x = -size.x;
  415. if( pt_texte->m_MultilineAllowed )
  416. {
  417. wxArrayString* list = wxStringSplit( pt_texte->m_Text, '\n' );
  418. wxPoint offset;
  419. offset.y = pt_texte->GetInterline();
  420. RotatePoint( &offset, orient );
  421. for( unsigned i = 0; i < list->Count(); i++ )
  422. {
  423. wxString txt = list->Item( i );
  424. plotter->text( pos, BLACK,
  425. txt,
  426. orient, size,
  427. pt_texte->m_HJustify, pt_texte->m_VJustify,
  428. thickness, pt_texte->m_Italic, pt_texte->m_Bold );
  429. pos += offset;
  430. }
  431. delete (list);
  432. }
  433. else
  434. plotter->text( pos, BLACK,
  435. pt_texte->m_Text,
  436. orient, size,
  437. pt_texte->m_HJustify, pt_texte->m_VJustify,
  438. thickness, pt_texte->m_Italic, pt_texte->m_Bold );
  439. }
  440. /* Plot areas (given by .m_FilledPolysList member) in a zone
  441. */
  442. void PlotFilledAreas( PLOTTER* plotter, ZONE_CONTAINER* aZone,
  443. GRTraceMode trace_mode )
  444. {
  445. static int* CornersBuffer = NULL;
  446. static unsigned CornersBufferSize = 0;
  447. unsigned imax = aZone->m_FilledPolysList.size();
  448. if( imax == 0 ) // Nothing to draw
  449. return;
  450. // We need a buffer to store corners coordinates:
  451. imax++; // provide room to sore an extra coordinate to close the polygon
  452. if( CornersBuffer == NULL )
  453. {
  454. CornersBufferSize = imax * 2;
  455. CornersBuffer = (int*) MyMalloc( CornersBufferSize * sizeof(int) );
  456. }
  457. if( (imax * 4) > CornersBufferSize )
  458. {
  459. CornersBufferSize = imax * 2;
  460. CornersBuffer = (int*) realloc( CornersBuffer,
  461. CornersBufferSize * sizeof(int) );
  462. }
  463. imax--;
  464. /* Plot all filled areas: filled areas have a filled area and a thick
  465. * outline we must plot the filled area itself ( as a filled polygon
  466. * OR a set of segments ) and plot the thick outline itself
  467. *
  468. * in non filled mode the outline is plotted, but not the filling items
  469. */
  470. int corners_count = 0;
  471. for( unsigned ic = 0, ii = 0; ic < imax; ic++ )
  472. {
  473. CPolyPt* corner = &aZone->m_FilledPolysList[ic];
  474. CornersBuffer[ii++] = corner->x;
  475. CornersBuffer[ii++] = corner->y;
  476. corners_count++;
  477. if( corner->end_contour ) // Plot the current filled area outline
  478. {
  479. // First, close the outline
  480. if( CornersBuffer[0] != CornersBuffer[ii - 2]
  481. || CornersBuffer[1] != CornersBuffer[ii - 1] )
  482. {
  483. CornersBuffer[ii++] = CornersBuffer[0];
  484. CornersBuffer[ii] = CornersBuffer[1];
  485. corners_count++;
  486. }
  487. // Plot the current filled area and its outline
  488. if( trace_mode == FILLED )
  489. {
  490. // Plot the current filled area polygon
  491. if( aZone->m_FillMode == 0 ) // We are using solid polygons
  492. // (if != 0: using segments )
  493. plotter->poly( corners_count, CornersBuffer, FILLED_SHAPE );
  494. else // We are using areas filled by
  495. // segments: plot hem )
  496. {
  497. for( unsigned iseg = 0;
  498. iseg < aZone->m_FillSegmList.size();
  499. iseg++ )
  500. {
  501. wxPoint start = aZone->m_FillSegmList[iseg].m_Start;
  502. wxPoint end = aZone->m_FillSegmList[iseg].m_End;
  503. plotter->thick_segment( start,
  504. end,
  505. aZone->m_ZoneMinThickness,
  506. trace_mode );
  507. }
  508. }
  509. // Plot the current filled area outline
  510. if( aZone->m_ZoneMinThickness > 0 )
  511. plotter->poly( corners_count, CornersBuffer, NO_FILL,
  512. aZone->m_ZoneMinThickness );
  513. }
  514. else
  515. {
  516. if( aZone->m_ZoneMinThickness > 0 )
  517. {
  518. for( int ii = 1; ii<corners_count; ii++ )
  519. plotter->thick_segment(
  520. wxPoint( CornersBuffer[ii * 2 - 2],
  521. CornersBuffer[ii * 2 - 1] ),
  522. wxPoint( CornersBuffer[ii * 2],
  523. CornersBuffer[ii * 2 + 1] ),
  524. ( trace_mode == FILAIRE ) ? -1 : aZone->m_ZoneMinThickness,
  525. trace_mode );
  526. }
  527. plotter->set_current_line_width( -1 );
  528. }
  529. corners_count = 0;
  530. ii = 0;
  531. }
  532. }
  533. }
  534. /* Plot items type DRAWSEGMENT on layers allowed by masque_layer
  535. */
  536. void PlotDrawSegment( PLOTTER* plotter, DRAWSEGMENT* pt_segm, int masque_layer,
  537. GRTraceMode trace_mode )
  538. {
  539. wxPoint start, end;
  540. int thickness;
  541. int radius = 0, StAngle = 0, EndAngle = 0;
  542. if( (g_TabOneLayerMask[pt_segm->GetLayer()] & masque_layer) == 0 )
  543. return;
  544. if( trace_mode == FILAIRE )
  545. thickness = g_pcb_plot_options.PlotLine_Width;
  546. else
  547. thickness = pt_segm->m_Width;
  548. start = pt_segm->m_Start;
  549. end = pt_segm->m_End;
  550. plotter->set_current_line_width( thickness );
  551. switch( pt_segm->m_Shape )
  552. {
  553. case S_CIRCLE:
  554. radius =
  555. (int) hypot( (double) ( end.x - start.x ),
  556. (double) ( end.y - start.y ) );
  557. plotter->thick_circle( start, radius * 2, thickness, trace_mode );
  558. break;
  559. case S_ARC:
  560. radius =
  561. (int) hypot( (double) ( end.x - start.x ),
  562. (double) ( end.y - start.y ) );
  563. StAngle = ArcTangente( end.y - start.y, end.x - start.x );
  564. EndAngle = StAngle + pt_segm->m_Angle;
  565. plotter->thick_arc( start,
  566. -EndAngle,
  567. -StAngle,
  568. radius,
  569. thickness,
  570. trace_mode );
  571. break;
  572. case S_CURVE:
  573. for( unsigned i = 1; i < pt_segm->m_BezierPoints.size(); i++ )
  574. plotter->thick_segment( pt_segm->m_BezierPoints[i - 1],
  575. pt_segm->m_BezierPoints[i],
  576. thickness,
  577. trace_mode );
  578. break;
  579. default:
  580. plotter->thick_segment( start, end, thickness, trace_mode );
  581. }
  582. }
  583. void WinEDA_BasePcbFrame::Plot_Layer( PLOTTER* plotter, int Layer,
  584. GRTraceMode trace_mode )
  585. {
  586. // Specify that the contents of the "Edges Pcb" layer are to be plotted
  587. // in addition to the contents of the currently specified layer.
  588. int layer_mask = g_TabOneLayerMask[Layer];
  589. if( !g_pcb_plot_options.Exclude_Edges_Pcb )
  590. layer_mask |= EDGE_LAYER;
  591. switch( Layer )
  592. {
  593. case FIRST_COPPER_LAYER:
  594. case LAYER_N_2:
  595. case LAYER_N_3:
  596. case LAYER_N_4:
  597. case LAYER_N_5:
  598. case LAYER_N_6:
  599. case LAYER_N_7:
  600. case LAYER_N_8:
  601. case LAYER_N_9:
  602. case LAYER_N_10:
  603. case LAYER_N_11:
  604. case LAYER_N_12:
  605. case LAYER_N_13:
  606. case LAYER_N_14:
  607. case LAYER_N_15:
  608. case LAST_COPPER_LAYER:
  609. Plot_Standard_Layer( plotter, layer_mask, true, trace_mode );
  610. // Adding drill marks, if required and if the plotter is able to plot
  611. // them:
  612. if( g_pcb_plot_options.DrillShapeOpt !=
  613. PCB_Plot_Options::NO_DRILL_SHAPE )
  614. {
  615. if( plotter->GetPlotterType() == PLOT_FORMAT_POST )
  616. PlotDrillMark( plotter,
  617. trace_mode,
  618. g_pcb_plot_options.DrillShapeOpt ==
  619. PCB_Plot_Options::SMALL_DRILL_SHAPE );
  620. }
  621. break;
  622. case SOLDERMASK_N_BACK:
  623. case SOLDERMASK_N_FRONT:
  624. Plot_Standard_Layer( plotter, layer_mask,
  625. g_pcb_plot_options.DrawViaOnMaskLayer, trace_mode );
  626. break;
  627. case SOLDERPASTE_N_BACK:
  628. case SOLDERPASTE_N_FRONT:
  629. Plot_Standard_Layer( plotter, layer_mask, false, trace_mode );
  630. break;
  631. default:
  632. Plot_Serigraphie( plotter, layer_mask, trace_mode );
  633. break;
  634. }
  635. }
  636. /* Plot a copper layer or mask in HPGL format.
  637. * HPGL unit = 0.98 mils (1 mil = 1.02041 unit HPGL).
  638. */
  639. void WinEDA_BasePcbFrame::Plot_Standard_Layer( PLOTTER* aPlotter,
  640. int aLayerMask,
  641. bool aPlotVia,
  642. GRTraceMode aPlotMode )
  643. {
  644. wxPoint pos;
  645. wxSize size;
  646. wxString msg;
  647. // Plot pcb draw items.
  648. for( BOARD_ITEM* item = m_Pcb->m_Drawings; item; item = item->Next() )
  649. {
  650. switch( item->Type() )
  651. {
  652. case TYPE_DRAWSEGMENT:
  653. PlotDrawSegment( aPlotter,
  654. (DRAWSEGMENT*) item,
  655. aLayerMask,
  656. aPlotMode );
  657. break;
  658. case TYPE_TEXTE:
  659. PlotTextePcb( aPlotter, (TEXTE_PCB*) item, aLayerMask, aPlotMode );
  660. break;
  661. case TYPE_COTATION:
  662. PlotCotation( aPlotter, (COTATION*) item, aLayerMask, aPlotMode );
  663. break;
  664. case TYPE_MIRE:
  665. PlotMirePcb( aPlotter, (MIREPCB*) item, aLayerMask, aPlotMode );
  666. break;
  667. case TYPE_MARKER_PCB:
  668. break;
  669. default:
  670. DisplayError( this,
  671. wxT( "Plot_Standard_Layer() error : Unexpected Draw Type" ) );
  672. break;
  673. }
  674. }
  675. /* Draw footprint shapes without pads (pads will plotted later) */
  676. for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() )
  677. {
  678. for( BOARD_ITEM* item = module->m_Drawings; item; item = item->Next() )
  679. {
  680. switch( item->Type() )
  681. {
  682. case TYPE_EDGE_MODULE:
  683. if( aLayerMask & g_TabOneLayerMask[ item->GetLayer() ] )
  684. Plot_1_EdgeModule( aPlotter,
  685. (EDGE_MODULE*) item,
  686. aPlotMode );
  687. break;
  688. default:
  689. break;
  690. }
  691. }
  692. }
  693. /* Plot footprint pads */
  694. for( MODULE* module = m_Pcb->m_Modules; module; module = module->Next() )
  695. {
  696. for( D_PAD* pad = module->m_Pads; pad; pad = pad->Next() )
  697. {
  698. wxPoint shape_pos;
  699. if( (pad->m_Masque_Layer & aLayerMask) == 0 )
  700. continue;
  701. shape_pos = pad->ReturnShapePos();
  702. pos = shape_pos;
  703. wxSize margin;
  704. switch( aLayerMask &
  705. ( SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT |
  706. SOLDERPASTE_LAYER_BACK | SOLDERPASTE_LAYER_FRONT ) )
  707. {
  708. case SOLDERMASK_LAYER_FRONT:
  709. case SOLDERMASK_LAYER_BACK:
  710. margin.x = margin.y = pad->GetSolderMaskMargin();
  711. break;
  712. case SOLDERPASTE_LAYER_FRONT:
  713. case SOLDERPASTE_LAYER_BACK:
  714. margin = pad->GetSolderPasteMargin();
  715. break;
  716. default:
  717. break;
  718. }
  719. size.x = pad->m_Size.x + ( 2 * margin.x );
  720. size.y = pad->m_Size.y + ( 2 * margin.y );
  721. /* Don't draw a null size item : */
  722. if( size.x <= 0 || size.y <= 0 )
  723. continue;
  724. switch( pad->m_PadShape )
  725. {
  726. case PAD_CIRCLE:
  727. aPlotter->flash_pad_circle( pos, size.x, aPlotMode );
  728. break;
  729. case PAD_OVAL:
  730. aPlotter->flash_pad_oval( pos, size, pad->m_Orient, aPlotMode );
  731. break;
  732. case PAD_TRAPEZOID:
  733. {
  734. wxSize delta = pad->m_DeltaSize;
  735. aPlotter->flash_pad_trapez( pos,
  736. size,
  737. delta,
  738. pad->m_Orient,
  739. aPlotMode );
  740. }
  741. break;
  742. case PAD_RECT:
  743. default:
  744. aPlotter->flash_pad_rect( pos, size, pad->m_Orient, aPlotMode );
  745. break;
  746. }
  747. }
  748. }
  749. /* Plot vias : */
  750. if( aPlotVia )
  751. {
  752. for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() )
  753. {
  754. if( track->Type() != TYPE_VIA )
  755. continue;
  756. SEGVIA* Via = (SEGVIA*) track;
  757. // vias are not plotted if not on selected layer, but if layer
  758. // is SOLDERMASK_LAYER_BACK or SOLDERMASK_LAYER_FRONT,vias are drawn,
  759. // if they are on an external copper layer
  760. int via_mask_layer = Via->ReturnMaskLayer();
  761. if( via_mask_layer & LAYER_BACK )
  762. via_mask_layer |= SOLDERMASK_LAYER_BACK;
  763. if( via_mask_layer & LAYER_FRONT )
  764. via_mask_layer |= SOLDERMASK_LAYER_FRONT;
  765. if( ( via_mask_layer & aLayerMask ) == 0 )
  766. continue;
  767. int via_margin = 0;
  768. // If the current layer is a solder mask, use the global mask
  769. // clearance for vias
  770. if( ( aLayerMask & ( SOLDERMASK_LAYER_BACK | SOLDERMASK_LAYER_FRONT ) ) )
  771. via_margin = g_DesignSettings.m_SolderMaskMargin;
  772. pos = Via->m_Start;
  773. size.x = size.y = Via->m_Width + 2 * via_margin;
  774. /* Don't draw a null size item : */
  775. if( size.x <= 0 )
  776. continue;
  777. aPlotter->flash_pad_circle( pos, size.x, aPlotMode );
  778. }
  779. }
  780. /* Plot tracks (not vias) : */
  781. for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() )
  782. {
  783. wxPoint end;
  784. if( track->Type() == TYPE_VIA )
  785. continue;
  786. if( (g_TabOneLayerMask[track->GetLayer()] & aLayerMask) == 0 )
  787. continue;
  788. size.x = size.y = track->m_Width;
  789. pos = track->m_Start;
  790. end = track->m_End;
  791. aPlotter->thick_segment( pos, end, size.x, aPlotMode );
  792. }
  793. /* Plot zones (outdated, for old boards compatibility): */
  794. for( TRACK* track = m_Pcb->m_Zone; track; track = track->Next() )
  795. {
  796. wxPoint end;
  797. if( (g_TabOneLayerMask[track->GetLayer()] & aLayerMask) == 0 )
  798. continue;
  799. size.x = size.y = track->m_Width;
  800. pos = track->m_Start;
  801. end = track->m_End;
  802. aPlotter->thick_segment( pos, end, size.x, aPlotMode );
  803. }
  804. /* Plot filled ares */
  805. for( int ii = 0; ii < m_Pcb->GetAreaCount(); ii++ )
  806. {
  807. ZONE_CONTAINER* edge_zone = m_Pcb->GetArea( ii );
  808. if( ( ( 1 << edge_zone->GetLayer() ) & aLayerMask ) == 0 )
  809. continue;
  810. PlotFilledAreas( aPlotter, edge_zone, aPlotMode );
  811. }
  812. }
  813. /** function PlotDrillMark
  814. * Draw a drill mark for pads and vias.
  815. * Must be called after all drawings, because it
  816. * redraw the drill mark on a pad or via, as a negative (i.e. white) shape in
  817. * FILLED plot mode
  818. * @param aPlotter = the PLOTTER
  819. * @param aTraceMode = the mode of plot (FILLED, SKETCH)
  820. * @param aSmallDrillShape = true to plot a small drill shape, false to plot
  821. * the actual drill shape
  822. */
  823. void WinEDA_BasePcbFrame::PlotDrillMark( PLOTTER* aPlotter,
  824. GRTraceMode aTraceMode,
  825. bool aSmallDrillShape )
  826. {
  827. wxPoint pos;
  828. wxSize diam;
  829. MODULE* Module;
  830. D_PAD* PtPad;
  831. TRACK* pts;
  832. if( aTraceMode == FILLED )
  833. {
  834. aPlotter->set_color( WHITE );
  835. }
  836. for( pts = m_Pcb->m_Track; pts != NULL; pts = pts->Next() )
  837. {
  838. if( pts->Type() != TYPE_VIA )
  839. continue;
  840. pos = pts->m_Start;
  841. if( g_pcb_plot_options.DrillShapeOpt ==
  842. PCB_Plot_Options::SMALL_DRILL_SHAPE )
  843. diam.x = diam.y = SMALL_DRILL;
  844. else
  845. diam.x = diam.y = pts->GetDrillValue();
  846. aPlotter->flash_pad_circle( pos, diam.x, aTraceMode );
  847. }
  848. for( Module = m_Pcb->m_Modules;
  849. Module != NULL;
  850. Module = Module->Next() )
  851. {
  852. for( PtPad = Module->m_Pads;
  853. PtPad != NULL;
  854. PtPad = PtPad->Next() )
  855. {
  856. if( PtPad->m_Drill.x == 0 )
  857. continue;
  858. // Output hole shapes:
  859. pos = PtPad->m_Pos;
  860. if( PtPad->m_DrillShape == PAD_OVAL )
  861. {
  862. diam = PtPad->m_Drill;
  863. aPlotter->flash_pad_oval( pos,
  864. diam,
  865. PtPad->m_Orient,
  866. aTraceMode );
  867. }
  868. else
  869. {
  870. diam.x = aSmallDrillShape ? SMALL_DRILL : PtPad->m_Drill.x;
  871. aPlotter->flash_pad_circle( pos, diam.x, aTraceMode );
  872. }
  873. }
  874. }
  875. if( aTraceMode == FILLED )
  876. {
  877. aPlotter->set_color( BLACK );
  878. }
  879. }