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.

790 lines
23 KiB

  1. /*************************************/
  2. /**** Pcbnew: Routine de trace PS ****/
  3. /*************************************/
  4. #include "fctsys.h"
  5. #include "gr_basic.h"
  6. #include "common.h"
  7. #include "plot_common.h"
  8. #include "pcbnew.h"
  9. #include "pcbplot.h"
  10. #include "trigo.h"
  11. #include "protos.h"
  12. #include "wx/defs.h"
  13. // Routines Locales
  14. static void PrintDrillMark( BOARD* Pcb );
  15. static Ki_PageDescr* SheetPS;
  16. // variables locales:
  17. const int DRILL_MARK = 1;
  18. /****************************************************************************/
  19. void WinEDA_BasePcbFrame::Genere_PS( const wxString& FullFileName, int Layer )
  20. /****************************************************************************/
  21. /* Genere un fichier POSTSCRIPT (*.ps) de trace du circuit, couche layer
  22. * if layer < 0: all layers
  23. */
  24. {
  25. int modetrace, tracevia;
  26. wxSize PcbSheetSize;
  27. wxSize PaperSize;
  28. wxSize BoardSize;
  29. wxPoint BoardCenter;
  30. bool Center = FALSE;
  31. Ki_PageDescr* currentsheet = m_CurrentScreen->m_CurrentSheet;
  32. double scale_format; // Facteur correctif pour conversion forlat Ax->A4
  33. double scale_x, scale_y;
  34. int PlotMarge_in_mils = 0;
  35. MsgPanel->EraseMsgBox();
  36. dest = wxFopen( FullFileName, wxT( "wt" ) );
  37. if( dest == NULL )
  38. {
  39. wxString msg = _( "Unable to create file " ) + FullFileName;
  40. DisplayError( this, msg );
  41. return;
  42. }
  43. setlocale( LC_NUMERIC, "C" );
  44. Affiche_1_Parametre( this, 0, _( "File" ), FullFileName, CYAN );
  45. if( g_PlotScaleOpt != 1 )
  46. Center = TRUE; // Echelle != 1 donc trace centree du PCB
  47. modetrace = Plot_Mode;
  48. scale_format = 1.0;
  49. // Set default line width
  50. if( g_PlotLine_Width < 1 )
  51. g_PlotLine_Width = 1;
  52. // calcul en unites internes des dimensions des feuilles ( connues en 1/1000 pouce )
  53. PcbSheetSize.x = currentsheet->m_Size.x * U_PCB;
  54. PcbSheetSize.y = currentsheet->m_Size.y * U_PCB;
  55. if( g_ForcePlotPS_On_A4 )
  56. {
  57. SheetPS = &g_Sheet_A4;
  58. PaperSize.x = g_Sheet_A4.m_Size.x * U_PCB;
  59. PaperSize.y = g_Sheet_A4.m_Size.y * U_PCB;
  60. scale_format = (float) PaperSize.x / PcbSheetSize.x;
  61. }
  62. else
  63. {
  64. SheetPS = currentsheet;
  65. PaperSize = PcbSheetSize;
  66. }
  67. // calcul de l'offset de trace:
  68. // calcul du cadrage horizontal du mode paysage ( val algebr. plus grande = decalage a gauche )
  69. g_PlotOffset.x = PlotMarge_in_mils * U_PCB;
  70. // cadrage vertical du mode paysage ( val algebr. plus grande = decalage vers le haut )
  71. g_PlotOffset.y = PaperSize.y - PlotMarge_in_mils * U_PCB;
  72. int BBox[4];
  73. BBox[0] = BBox[1] = PlotMarge_in_mils;
  74. BBox[2] = SheetPS->m_Size.x - PlotMarge_in_mils;
  75. BBox[3] = SheetPS->m_Size.y - PlotMarge_in_mils;
  76. scale_x = scale_y = 1.0;
  77. InitPlotParametresPS( g_PlotOffset, SheetPS, 1.0 / m_InternalUnits, 1.0 / m_InternalUnits );
  78. SetDefaultLineWidthPS( g_PlotLine_Width );
  79. PrintHeaderPS( dest, wxT( "PCBNEW-PS" ), FullFileName, 1, BBox, wxLANDSCAPE );
  80. if( Plot_Sheet_Ref )
  81. {
  82. int tmp = g_PlotOrient;
  83. g_PlotOrient = 0;
  84. SetPlotScale( 1.0, 1.0 );
  85. PlotWorkSheet( PLOT_FORMAT_POST, m_CurrentScreen );
  86. g_PlotOrient = tmp;
  87. }
  88. // calcul des dimensions et centre du PCB
  89. m_Pcb->ComputeBoundaryBox();
  90. BoardSize = m_Pcb->m_BoundaryBox.GetSize();
  91. BoardCenter = m_Pcb->m_BoundaryBox.Centre();
  92. scale_x = Scale_X;
  93. scale_y = Scale_Y;
  94. if( g_PlotScaleOpt == 0 ) // Optimum scale
  95. {
  96. float Xscale, Yscale;
  97. int noprint_size = 2 * PlotMarge_in_mils * U_PCB;
  98. if( Plot_Sheet_Ref )
  99. noprint_size += 500 * U_PCB;
  100. Xscale = (float) ( PaperSize.x - noprint_size ) / BoardSize.x;
  101. Yscale = (float) ( PaperSize.y - noprint_size ) / BoardSize.y;
  102. scale_x = scale_y = MIN( Xscale, Yscale );
  103. }
  104. BoardCenter.x = (int) (BoardCenter.x * scale_x);
  105. BoardCenter.y = (int) (BoardCenter.y * scale_y);
  106. // Calcul du cadrage (echelle != 1 donc recadrage du trace)
  107. if( Center )
  108. {
  109. g_PlotOffset.x -= PaperSize.x / 2 - BoardCenter.x + PlotMarge_in_mils * U_PCB;
  110. g_PlotOffset.y = PaperSize.y / 2 + BoardCenter.y; // cadrage horizontal du mode paysage
  111. }
  112. if( g_PlotOrient == PLOT_MIROIR )
  113. {
  114. if( Center )
  115. g_PlotOffset.y = -PaperSize.y / 2 + BoardCenter.y;
  116. else
  117. g_PlotOffset.y = -PaperSize.y + m_Pcb->m_BoundaryBox.GetBottom()
  118. + m_Pcb->m_BoundaryBox.GetY() + PlotMarge_in_mils * U_PCB;
  119. }
  120. InitPlotParametresPS( g_PlotOffset, SheetPS, scale_x, scale_y, g_PlotOrient );
  121. // If plot a negative board:
  122. // Draw a black rectangle (background for plot board in white)
  123. // and switch the current color to WHITE
  124. if( g_Plot_PS_Negative )
  125. {
  126. int Rectangle[10]; // Put here the board corners
  127. int margin = 500; // Add a 0.1 inch margin around the board
  128. Rectangle[0] = m_Pcb->m_BoundaryBox.GetX() - margin;
  129. Rectangle[1] = m_Pcb->m_BoundaryBox.GetY() - margin;
  130. Rectangle[2] = m_Pcb->m_BoundaryBox.GetRight() + margin;
  131. Rectangle[3] = Rectangle[1];
  132. Rectangle[4] = Rectangle[2];
  133. Rectangle[5] = m_Pcb->m_BoundaryBox.GetBottom() + margin;
  134. Rectangle[6] = Rectangle[0];
  135. Rectangle[7] = Rectangle[5];
  136. Rectangle[8] = Rectangle[0];
  137. Rectangle[9] = Rectangle[1];
  138. SetColorMapPS( BLACK );
  139. PlotPolyPS( 5, Rectangle, TRUE );
  140. SetColorMapPS( WHITE );
  141. }
  142. switch( Layer )
  143. {
  144. case - 1:
  145. Plot_Layer_PS( dest, g_TabOneLayerMask[Layer], 0, 1, modetrace );
  146. break;
  147. case CUIVRE_N:
  148. case LAYER_N_2:
  149. case LAYER_N_3:
  150. case LAYER_N_4:
  151. case LAYER_N_5:
  152. case LAYER_N_6:
  153. case LAYER_N_7:
  154. case LAYER_N_8:
  155. case LAYER_N_9:
  156. case LAYER_N_10:
  157. case LAYER_N_11:
  158. case LAYER_N_12:
  159. case LAYER_N_13:
  160. case LAYER_N_14:
  161. case LAYER_N_15:
  162. case CMP_N:
  163. Plot_Layer_PS( dest, g_TabOneLayerMask[Layer], 0, 1, modetrace );
  164. break;
  165. case SILKSCREEN_N_CU:
  166. case SILKSCREEN_N_CMP:
  167. Plot_Serigraphie( PLOT_FORMAT_POST, dest, g_TabOneLayerMask[Layer] );
  168. break;
  169. case SOLDERMASK_N_CU:
  170. case SOLDERMASK_N_CMP: // Trace du vernis epargne
  171. if( g_DrawViaOnMaskLayer )
  172. tracevia = 1;
  173. else
  174. tracevia = 0;
  175. Plot_Layer_PS( dest, g_TabOneLayerMask[Layer], g_DesignSettings.m_MaskMargin,
  176. tracevia, modetrace );
  177. break;
  178. case SOLDERPASTE_N_CU:
  179. case SOLDERPASTE_N_CMP: // Trace du masque de pate de soudure
  180. Plot_Layer_PS( dest, g_TabOneLayerMask[Layer], 0, 0, modetrace );
  181. break;
  182. default:
  183. Plot_Serigraphie( PLOT_FORMAT_POST, dest, g_TabOneLayerMask[Layer] );
  184. break;
  185. }
  186. // fin
  187. CloseFilePS( dest );
  188. setlocale( LC_NUMERIC, "" );
  189. }
  190. /********************************************************************/
  191. void WinEDA_BasePcbFrame::Plot_Layer_PS( FILE* File, int masque_layer,
  192. int garde, int tracevia, int modetrace )
  193. /********************************************************************/
  194. /* Trace en format POSTSCRIPT d'une couche cuivre ou masque
  195. */
  196. {
  197. wxPoint pos, end;
  198. wxSize size;
  199. MODULE* Module;
  200. D_PAD* PtPad;
  201. TRACK* pts;
  202. BOARD_ITEM* PtStruct;
  203. wxString msg;
  204. masque_layer |= EDGE_LAYER; // Les elements de la couche EDGE sont tj traces
  205. // trace des elements type Drawings Pcb :
  206. PtStruct = m_Pcb->m_Drawings;
  207. for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
  208. {
  209. switch( PtStruct->m_StructType )
  210. {
  211. case TYPEDRAWSEGMENT:
  212. PlotDrawSegment( (DRAWSEGMENT*) PtStruct, PLOT_FORMAT_POST,
  213. masque_layer );
  214. break;
  215. case TYPETEXTE:
  216. PlotTextePcb( (TEXTE_PCB*) PtStruct, PLOT_FORMAT_POST,
  217. masque_layer );
  218. break;
  219. case TYPECOTATION:
  220. PlotCotation( (COTATION*) PtStruct, PLOT_FORMAT_POST,
  221. masque_layer );
  222. break;
  223. case TYPEMIRE:
  224. PlotMirePcb( (MIREPCB*) PtStruct, PLOT_FORMAT_POST,
  225. masque_layer );
  226. break;
  227. case TYPEMARQUEUR:
  228. break;
  229. default:
  230. DisplayError( this,
  231. wxT( "WinEDA_BasePcbFrame::Plot_Layer_PS() : Unexpected Draw Type" ) );
  232. break;
  233. }
  234. }
  235. // Trace des Elements des modules autres que pads
  236. nb_items = 0;
  237. Affiche_1_Parametre( this, 48, wxT( "DrawMod" ), wxEmptyString, GREEN );
  238. Module = m_Pcb->m_Modules;
  239. for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
  240. {
  241. PtStruct = Module->m_Drawings;
  242. for( ; PtStruct != NULL; PtStruct = PtStruct->Next() )
  243. {
  244. switch( PtStruct->m_StructType )
  245. {
  246. case TYPEEDGEMODULE:
  247. if( masque_layer & g_TabOneLayerMask[ PtStruct->GetLayer() ] )
  248. Plot_1_EdgeModule( PLOT_FORMAT_POST, (EDGE_MODULE*) PtStruct );
  249. break;
  250. default:
  251. break;
  252. }
  253. }
  254. }
  255. // Trace des Elements des modules : Pastilles
  256. nb_items = 0;
  257. Affiche_1_Parametre( this, 48, wxT( "Pads " ), wxEmptyString, GREEN );
  258. Module = m_Pcb->m_Modules;
  259. for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
  260. {
  261. PtPad = (D_PAD*) Module->m_Pads;
  262. for( ; PtPad != NULL; PtPad = (D_PAD*) PtPad->Pnext )
  263. {
  264. if( (PtPad->m_Masque_Layer & masque_layer) == 0 )
  265. continue;
  266. wxPoint shape_pos = PtPad->ReturnShapePos();
  267. pos = shape_pos;
  268. size.x = PtPad->m_Size.x + garde * 2;
  269. size.y = PtPad->m_Size.y + garde * 2;
  270. nb_items++;
  271. switch( PtPad->m_PadShape )
  272. {
  273. case CIRCLE:
  274. trace_1_pastille_RONDE_POST( pos, size.x, modetrace );
  275. break;
  276. case OVALE:
  277. trace_1_pastille_OVALE_POST( pos, size, PtPad->m_Orient, modetrace );
  278. break;
  279. case TRAPEZE:
  280. {
  281. wxSize delta;
  282. delta = PtPad->m_DeltaSize;
  283. trace_1_pad_TRAPEZE_POST( pos, size, delta,
  284. PtPad->m_Orient, modetrace );
  285. break;
  286. }
  287. case RECT:
  288. default:
  289. trace_1_pad_rectangulaire_POST( pos, size, PtPad->m_Orient, modetrace );
  290. break;
  291. }
  292. msg.Printf( wxT( "%d" ), nb_items );
  293. Affiche_1_Parametre( this, 48, wxT( "Pads" ), msg, GREEN );
  294. }
  295. }
  296. // trace des VIAS :
  297. if( tracevia )
  298. {
  299. nb_items = 0;
  300. Affiche_1_Parametre( this, 56, _( "Vias" ), wxEmptyString, RED );
  301. for( pts = m_Pcb->m_Track; pts != NULL; pts = pts->Next() )
  302. {
  303. if( pts->m_StructType != TYPEVIA )
  304. continue;
  305. SEGVIA* Via = (SEGVIA*) pts;
  306. // vias not plotted if not on selected layer, but if layer
  307. // == SOLDERMASK_LAYER_CU or SOLDERMASK_LAYER_CMP, vias are drawn,
  308. // if they are on a external copper layer
  309. int via_mask_layer = Via->ReturnMaskLayer();
  310. if( via_mask_layer & CUIVRE_LAYER )
  311. via_mask_layer |= SOLDERMASK_LAYER_CU;
  312. if( via_mask_layer & CMP_LAYER )
  313. via_mask_layer |= SOLDERMASK_LAYER_CMP;
  314. if( (via_mask_layer & masque_layer) == 0 )
  315. continue;
  316. pos = Via->m_Start;
  317. size.x = size.y = Via->m_Width + garde * 2;
  318. trace_1_pastille_RONDE_POST( pos, size.x, modetrace );
  319. nb_items++;
  320. msg.Printf( wxT( "%d" ), nb_items );
  321. Affiche_1_Parametre( this, 56, wxEmptyString, msg, RED );
  322. }
  323. }
  324. // trace des pistes et zones:
  325. nb_items = 0;
  326. Affiche_1_Parametre( this, 64, _( "Tracks" ), wxEmptyString, YELLOW );
  327. for( pts = m_Pcb->m_Track; pts != NULL; pts = (TRACK*) pts->Pnext )
  328. {
  329. if( pts->m_StructType == TYPEVIA )
  330. continue;
  331. if( (g_TabOneLayerMask[pts->GetLayer()] & masque_layer) == 0 )
  332. continue;
  333. size.x = size.y = pts->m_Width;
  334. pos = pts->m_Start;
  335. end = pts->m_End;
  336. PlotFilledSegmentPS( pos, end, size.x );
  337. nb_items++;
  338. msg.Printf( wxT( "%d" ), nb_items );
  339. Affiche_1_Parametre( this, 64, wxEmptyString, msg, YELLOW );
  340. }
  341. nb_items = 0;
  342. Affiche_1_Parametre( this, 64, wxT( "Zones " ), wxEmptyString, YELLOW );
  343. for( pts = m_Pcb->m_Zone; pts != NULL; pts = (TRACK*) pts->Pnext )
  344. {
  345. if( (g_TabOneLayerMask[pts->GetLayer()] & masque_layer) == 0 )
  346. continue;
  347. size.x = size.y = pts->m_Width;
  348. pos = pts->m_Start;
  349. end = pts->m_End;
  350. PlotFilledSegmentPS( pos, end, size.x );
  351. nb_items++;
  352. msg.Printf( wxT( "%d" ), nb_items );
  353. Affiche_1_Parametre( this, 64, wxEmptyString, msg, YELLOW );
  354. }
  355. // Trace des trous de percage
  356. if( modetrace == FILLED )
  357. PrintDrillMark( m_Pcb );
  358. }
  359. /*************************************/
  360. static void PrintDrillMark( BOARD* Pcb )
  361. /*************************************/
  362. /* Draw a drill mark for pads and vias.
  363. * Must be called after all drawings, because it
  364. * redraw the drill mark on a pad or via
  365. */
  366. {
  367. const int SMALL_DRILL = 150;
  368. wxPoint pos;
  369. wxSize diam;
  370. MODULE* Module;
  371. D_PAD* PtPad;
  372. TRACK* pts;
  373. if( g_DrillShapeOpt == 0 )
  374. return;
  375. if( g_Plot_PS_Negative )
  376. fprintf( dest, " 0 setgray\n" );
  377. else
  378. fprintf( dest, " 1 setgray\n" );
  379. diam.x = diam.y = (g_DrillShapeOpt == DRILL_MARK) ? SMALL_DRILL :
  380. g_DesignSettings.m_ViaDrill;
  381. for( pts = Pcb->m_Track; pts != NULL; pts = (TRACK*) pts->Pnext )
  382. {
  383. if( pts->m_StructType != TYPEVIA )
  384. continue;
  385. pos = pts->m_Start;
  386. if( g_DrillShapeOpt == DRILL_MARK )
  387. diam.x = diam.y = SMALL_DRILL;
  388. else
  389. {
  390. if( pts->m_Drill < 0 )
  391. diam.x = diam.y = g_DesignSettings.m_ViaDrill;
  392. else
  393. diam.x = diam.y = pts->m_Drill;
  394. }
  395. trace_1_pastille_RONDE_POST( pos, diam.x, FILLED );
  396. }
  397. Module = Pcb->m_Modules;
  398. for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
  399. {
  400. PtPad = (D_PAD*) Module->m_Pads;
  401. for( ; PtPad != NULL; PtPad = (D_PAD*) PtPad->Pnext )
  402. {
  403. if( PtPad->m_Drill.x == 0 )
  404. continue;
  405. // calcul de la position des trous, selon echelle
  406. pos = PtPad->m_Pos;
  407. diam.x = diam.y = (g_DrillShapeOpt == DRILL_MARK) ? SMALL_DRILL :
  408. PtPad->m_Drill.x;
  409. trace_1_pastille_RONDE_POST( pos, diam.x, FILLED );
  410. }
  411. }
  412. fprintf( dest, " 0 setgray\n" );
  413. }
  414. /***********************************************************************************/
  415. void trace_1_pastille_OVALE_POST( wxPoint pos, wxSize size, int orient, int modetrace )
  416. /************************************************************************************/
  417. /* Trace 1 pastille OVALE en position pos_X,Y:
  418. * dimensions dx,dy,
  419. * orientation orient
  420. * La forme est tracee comme un segment
  421. */
  422. {
  423. int x0, y0, x1, y1, delta;
  424. int w, rayon;
  425. // la pastille est ramenee a une pastille ovale avec dy > dx
  426. if( size.x > size.y )
  427. {
  428. EXCHG( size.x, size.y );
  429. orient += 900;
  430. if( orient >= 3600 )
  431. orient -= 3600;
  432. }
  433. delta = size.y - size.x;
  434. x0 = 0;
  435. y0 = -delta / 2;
  436. x1 = 0;
  437. y1 = delta / 2;
  438. RotatePoint( &x0, &y0, orient );
  439. RotatePoint( &x1, &y1, orient );
  440. if( modetrace == FILLED )
  441. {
  442. PlotFilledSegmentPS( wxPoint( pos.x + x0, pos.y + y0 ),
  443. wxPoint( pos.x + x1, pos.y + y1 ), size.x );
  444. }
  445. else
  446. {
  447. w = g_PlotLine_Width;
  448. rayon = (size.x - w) / 2;
  449. if( rayon < 1 )
  450. rayon = 1;
  451. if( rayon < w )
  452. w = rayon;
  453. PlotArcPS( wxPoint( pos.x + x1, pos.y + y1 ), -orient, -orient + 1800, rayon, w );
  454. PlotArcPS( wxPoint( pos.x + x0, pos.y + y0 ), -orient + 1800, -orient, rayon, w );
  455. x0 = -rayon;
  456. y0 = -delta / 2;
  457. x1 = -rayon;
  458. y1 = delta / 2;
  459. RotatePoint( &x0, &y0, orient );
  460. RotatePoint( &x1, &y1, orient );
  461. PlotFilledSegmentPS( wxPoint( pos.x + x0, pos.y + y0 ),
  462. wxPoint( pos.x + x1, pos.y + y1 ), w );
  463. x0 = rayon;
  464. y0 = -delta / 2;
  465. x1 = rayon;
  466. y1 = delta / 2;
  467. RotatePoint( &x0, &y0, orient );
  468. RotatePoint( &x1, &y1, orient );
  469. PlotFilledSegmentPS( wxPoint( pos.x + x0, pos.y + y0 ),
  470. wxPoint( pos.x + x1, pos.y + y1 ), w );
  471. }
  472. }
  473. /*******************************************************************************/
  474. void trace_1_pastille_RONDE_POST( wxPoint centre, int diametre, int modetrace )
  475. /*******************************************************************************/
  476. /* Trace 1 pastille RONDE (via,pad rond) en position pos_X,Y
  477. */
  478. {
  479. int rayon, w;
  480. wxSize diam( diametre, diametre );
  481. UserToDeviceCoordinate( centre );
  482. UserToDeviceSize( diam );
  483. if( modetrace == FILLED )
  484. {
  485. fprintf( dest, "%d setlinewidth\n", g_PlotLine_Width );
  486. rayon = diam.x / 2;
  487. if( rayon < 1 )
  488. rayon = 1;
  489. fprintf( dest, "newpath %d %d %d 0 360 arc fill stroke\n",
  490. centre.x, centre.y, rayon );
  491. }
  492. else
  493. {
  494. w = g_PlotLine_Width;
  495. rayon = (diam.x - w) / 2;
  496. if( rayon < 1 )
  497. rayon = 1;
  498. if( rayon < w )
  499. w = rayon;
  500. fprintf( dest, "%d setlinewidth\n", w );
  501. fprintf( dest, "newpath %d %d %d 0 360 arc stroke\n",
  502. centre.x, centre.y, rayon );
  503. }
  504. }
  505. /**************************************************************************/
  506. void trace_1_pad_rectangulaire_POST( wxPoint centre,
  507. wxSize size, int orient, int modetrace )
  508. /**************************************************************************/
  509. /*
  510. * Trace 1 pad rectangulaire d'orientation quelconque
  511. * donne par son centre, ses dimensions,
  512. * et son orientation orient
  513. */
  514. {
  515. int x0, y0, x1, y1, w;
  516. if( modetrace == FILLED )
  517. {
  518. x0 = centre.x - size.x / 2;
  519. x1 = centre.x + size.x / 2;
  520. y0 = y1 = centre.y;
  521. w = size.y;
  522. RotatePoint( &x0, &y0, centre.x, centre.y, orient );
  523. RotatePoint( &x1, &y1, centre.x, centre.y, orient );
  524. fprintf( dest, "0 setlinewidth 0 setlinecap 0 setlinejoin\n" );
  525. ForcePenReinit(); // Force init line width for PlotFilledSegmentPS
  526. PlotFilledSegmentPS( wxPoint( x0, y0 ), wxPoint( x1, y1 ), w );
  527. ForcePenReinit();
  528. SetCurrentLineWidthPS( 0 ); // Force init line width to default
  529. fprintf( dest, "1 setlinecap 1 setlinejoin\n" );
  530. }
  531. else
  532. {
  533. w = g_PlotLine_Width;
  534. size.x -= w;
  535. if( size.x < 1 )
  536. size.x = 1;
  537. size.y -= w;
  538. if( size.y < 1 )
  539. size.y = 1;
  540. trace_1_contour_POST( centre, size, wxSize( 0, 0 ), w, orient );
  541. }
  542. }
  543. /**************************************************************/
  544. void trace_1_contour_POST( wxPoint centre, wxSize size, wxSize delta,
  545. int dim_trait, int orient )
  546. /**************************************************************/
  547. /*
  548. * Trace 1 contour rectangulaire ou trapezoidal d'orientation quelconque
  549. * donne par son centre centre,
  550. * ses dimensions size,
  551. * ses variations delta
  552. * epaisseur de trait dim_trait
  553. * et son orientation orient (en 0.1 degres)
  554. */
  555. {
  556. int ii;
  557. int dx, dy, lpen;
  558. int ddx, ddy;
  559. wxPoint coord[4];
  560. lpen = dim_trait;
  561. dx = size.x / 2;
  562. dy = size.y / 2;
  563. ddx = delta.x >> 1;
  564. ddy = delta.y >> 1; // demi dim dx et dy
  565. coord[0].x = centre.x - dx - ddy;
  566. coord[0].y = centre.y + dy + ddx;
  567. coord[1].x = centre.x - dx + ddy;
  568. coord[1].y = centre.y - dy - ddx;
  569. coord[2].x = centre.x + dx - ddy;
  570. coord[2].y = centre.y - dy + ddx;
  571. coord[3].x = centre.x + dx + ddy;
  572. coord[3].y = centre.y + dy - ddx;
  573. for( ii = 0; ii < 4; ii++ )
  574. {
  575. RotatePoint( &coord[ii], centre, orient );
  576. }
  577. PlotFilledSegmentPS( coord[0], coord[1], lpen );
  578. PlotFilledSegmentPS( coord[1], coord[2], lpen );
  579. PlotFilledSegmentPS( coord[2], coord[3], lpen );
  580. PlotFilledSegmentPS( coord[3], coord[0], lpen );
  581. }
  582. /*******************************************************************/
  583. void trace_1_pad_TRAPEZE_POST( wxPoint centre, wxSize size, wxSize delta,
  584. int orient, int modetrace )
  585. /*******************************************************************/
  586. /*
  587. * Trace 1 pad trapezoidal donne par :
  588. * son centre centre
  589. * ses dimensions size
  590. * les variations delta ( 1 des deux au moins doit etre nulle)
  591. * son orientation orient en 0.1 degres
  592. * le mode de trace (FILLED, SKETCH, FILAIRE)
  593. *
  594. * Le trace n'est fait que pour un trapeze, c.a.d que deltaX ou deltaY
  595. * = 0.
  596. *
  597. * les notation des sommets sont ( vis a vis de la table tracante )
  598. *
  599. * " 0 ------------- 3 "
  600. * " . . "
  601. * " . O . "
  602. * " . . "
  603. * " 1 ---- 2 "
  604. *
  605. *
  606. * exemple de Disposition pour deltaY > 0, deltaX = 0
  607. * " 1 ---- 2 "
  608. * " . . "
  609. * " . O . "
  610. * " . . "
  611. * " 0 ------------- 3 "
  612. *
  613. *
  614. * exemple de Disposition pour deltaY = 0, deltaX > 0
  615. * " 0 "
  616. * " . . "
  617. * " . . "
  618. * " . 3 "
  619. * " . . "
  620. * " . O . "
  621. * " . . "
  622. * " . 2 "
  623. * " . . "
  624. * " . . "
  625. * " 1 "
  626. */
  627. {
  628. int ii;
  629. int dx, dy;
  630. wxPoint polygone[4]; // coord des sommets / centre du pad
  631. int ddx, ddy;
  632. int l_pen; // diam spot (plume)
  633. l_pen = 1;
  634. if( modetrace == FILAIRE || Plot_Mode == FILAIRE )
  635. {
  636. wxSize lsize( g_PlotLine_Width, g_PlotLine_Width );
  637. UserToDeviceSize( lsize );
  638. l_pen = lsize.x;
  639. }
  640. dx = size.x / 2;
  641. dy = size.y / 2;
  642. ddx = delta.x / 2;
  643. ddy = delta.y / 2;
  644. polygone[0].x = -dx - ddy;
  645. polygone[0].y = +dy + ddx;
  646. polygone[1].x = -dx + ddy;
  647. polygone[1].y = -dy - ddx;
  648. polygone[2].x = +dx - ddy;
  649. polygone[2].y = -dy + ddx;
  650. polygone[3].x = +dx + ddy;
  651. polygone[3].y = +dy - ddx;
  652. for( ii = 0; ii < 4; ii++ )
  653. {
  654. RotatePoint( &polygone[ii].x, &polygone[ii].y, orient );
  655. polygone[ii].x += centre.x;
  656. polygone[ii].y += centre.y;
  657. }
  658. SetCurrentLineWidthPS( l_pen );
  659. UserToDeviceCoordinate( polygone[0] );
  660. fprintf( dest, "newpath %d %d moveto\n", polygone[0].x, polygone[0].y );
  661. for( ii = 1; ii < 4; ii++ )
  662. {
  663. UserToDeviceCoordinate( polygone[ii] );
  664. fprintf( dest, "%d %d lineto\n", polygone[ii].x, polygone[ii].y );
  665. }
  666. fprintf( dest, "%d %d lineto ", polygone[0].x, polygone[0].y );
  667. if( modetrace == FILLED )
  668. fprintf( dest, "fill " );
  669. fprintf( dest, "stroke\n" );
  670. }