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.

412 lines
13 KiB

  1. /******************************************/
  2. /* Kicad: Common plot Postscript Routines */
  3. /******************************************/
  4. #include "fctsys.h"
  5. #include "gr_basic.h"
  6. #include "trigo.h"
  7. #include "wxstruct.h"
  8. #include "base_struct.h"
  9. #include "common.h"
  10. #include "plot_common.h"
  11. #include "macros.h"
  12. #include "wx/defs.h"
  13. // Variables partagees avec Common plot Postscript Routines
  14. extern wxPoint LastPenPosition;
  15. extern wxPoint PlotOffset;
  16. extern FILE* PlotOutputFile;
  17. extern double XScale, YScale;
  18. extern int g_DefaultPenWidth, g_CurrentPenWidth;
  19. extern int PlotOrientOptions, etat_plume;
  20. // Locales
  21. static Ki_PageDescr* SheetPS;
  22. /*************************************************************************************/
  23. void InitPlotParametresPS( wxPoint offset, Ki_PageDescr* sheet,
  24. double xscale, double yscale, int orient )
  25. /*************************************************************************************/
  26. /* Set the plot offset for the current plotting
  27. * xscale,yscale = coordinate scale (scale coefficient for coordinates)
  28. * device_xscale,device_yscale = device coordinate scale (i.e scale used by plot device)
  29. */
  30. {
  31. PlotOrientOptions = orient;
  32. PlotOffset = offset;
  33. SheetPS = sheet;
  34. XScale = xscale;
  35. YScale = yscale;
  36. g_CurrentPenWidth = -1;
  37. }
  38. /*************************************************************************************/
  39. void SetDefaultLineWidthPS( int width )
  40. /*************************************************************************************/
  41. /* Set the default line width (in 1/1000 inch) for the current plotting
  42. */
  43. {
  44. g_DefaultPenWidth = width; // epaisseur du trait standard en 1/1000 pouce
  45. g_CurrentPenWidth = -1;
  46. }
  47. /***************************************/
  48. void SetCurrentLineWidthPS( int width )
  49. /***************************************/
  50. /* Set the Current line width (in 1/1000 inch) for the next plot
  51. */
  52. {
  53. int pen_width;
  54. if( width > 0 )
  55. pen_width = width;
  56. else
  57. pen_width = g_DefaultPenWidth;
  58. if( pen_width != g_CurrentPenWidth )
  59. fprintf( PlotOutputFile, "%d setlinewidth\n", (int) (XScale * pen_width) );
  60. g_CurrentPenWidth = pen_width;
  61. }
  62. /******************************/
  63. void SetColorMapPS( int color )
  64. /******************************/
  65. /* Print the postscript set color command:
  66. * r g b setrgbcolor,
  67. * r, g, b = color values (= 0 .. 1.0 )
  68. *
  69. * color = color index in ColorRefs[]
  70. */
  71. {
  72. char Line[1024];
  73. sprintf( Line, "%.3f %.3f %.3f setrgbcolor\n",
  74. (float) ColorRefs[color].m_Red / 255,
  75. (float) ColorRefs[color].m_Green / 255,
  76. (float) ColorRefs[color].m_Blue / 255 );
  77. to_point( Line );
  78. fputs( Line, PlotOutputFile );
  79. }
  80. /***************************************************************/
  81. void PlotFilledSegmentPS( wxPoint start, wxPoint end, int width )
  82. /***************************************************************/
  83. /* Plot 1 segment like a track segment
  84. */
  85. {
  86. UserToDeviceCoordinate( start );
  87. UserToDeviceCoordinate( end );
  88. SetCurrentLineWidthPS( width );
  89. fprintf( PlotOutputFile, "%d %d %d %d line\n", start.x, start.y, end.x, end.y );
  90. }
  91. /***************************************************************/
  92. void PlotRectPS( wxPoint p1, wxPoint p2, int fill, int width )
  93. /***************************************************************/
  94. {
  95. UserToDeviceCoordinate( p1 );
  96. UserToDeviceCoordinate( p2 );
  97. SetCurrentLineWidthPS( width );
  98. fprintf( PlotOutputFile, "%d %d %d %d rect%d\n", p1.x, p1.y,
  99. p2.x-p1.x, p2.y-p1.y, fill );
  100. }
  101. /******************************************************/
  102. void PlotCirclePS( wxPoint pos, int diametre, int fill, int width )
  103. /******************************************************/
  104. {
  105. int rayon;
  106. char Line[256];
  107. UserToDeviceCoordinate( pos );
  108. rayon = (int) (XScale * diametre / 2);
  109. if( rayon < 0 )
  110. rayon = 0;
  111. SetCurrentLineWidthPS( width );
  112. sprintf(Line, "%d %d %d cir%d\n", pos.x, pos.y, rayon, fill);
  113. fputs( Line, PlotOutputFile );
  114. }
  115. /**************************************************************************************/
  116. void PlotArcPS( wxPoint centre, int StAngle, int EndAngle, int rayon, int fill, int width )
  117. /**************************************************************************************/
  118. /* Plot an arc:
  119. * StAngle, EndAngle = start and end arc in 0.1 degree
  120. */
  121. {
  122. char Line[256];
  123. if( rayon <= 0 )
  124. return;
  125. SetCurrentLineWidthPS( width );
  126. // Calcul des coord du point de depart :
  127. UserToDeviceCoordinate( centre );
  128. if( PlotOrientOptions == PLOT_MIROIR )
  129. sprintf( Line, "%d %d %d %f %f arc%d\n", centre.x, centre.y,
  130. (int) (rayon * XScale), (float) StAngle / 10, (float) EndAngle / 10,
  131. fill);
  132. else
  133. sprintf( Line, "%d %d %d %f %f arc%d\n", centre.x, centre.y,
  134. (int) (rayon * XScale), -(float) EndAngle / 10, -(float) StAngle / 10,
  135. fill);
  136. // Undo internationalization printf (float x.y printed x,y)
  137. to_point( Line );
  138. fputs( Line, PlotOutputFile );
  139. }
  140. /*****************************************************************/
  141. void PlotPolyPS( int nb_segm, int* coord, int fill, int width )
  142. /*****************************************************************/
  143. /* Draw a polygon ( a filled polygon if fill == 1 ) in POSTSCRIPT format
  144. * @param nb_segm = corner count
  145. * @param coord = corner list (a corner uses 2 int = X coordinate followed by Y coordinate
  146. * @param fill :if == 0 : filled polygon
  147. * @param width = line width
  148. */
  149. {
  150. int ii;
  151. wxPoint pos;
  152. if( nb_segm <= 1 )
  153. return;
  154. SetCurrentLineWidthPS( width );
  155. pos.x = coord[0];
  156. pos.y = coord[1];
  157. UserToDeviceCoordinate( pos );
  158. fprintf( PlotOutputFile, "newpath %d %d moveto\n", pos.x, pos.y );
  159. for( ii = 1; ii < nb_segm; ii++ )
  160. {
  161. pos.x = coord[2 * ii];
  162. pos.y = coord[2 * ii + 1];
  163. UserToDeviceCoordinate( pos );
  164. fprintf( PlotOutputFile, "%d %d lineto\n", pos.x, pos.y );
  165. }
  166. // Fermeture du polygone
  167. fprintf(PlotOutputFile, "poly%d\n", fill);
  168. }
  169. /*************************************/
  170. void LineTo_PS( wxPoint pos, int plume )
  171. /*************************************/
  172. /* Routine to draw to a new position
  173. */
  174. {
  175. if( plume == 'Z' )
  176. return;
  177. UserToDeviceCoordinate( pos );
  178. if( plume == 'D' )
  179. {
  180. char Line[256];
  181. sprintf( Line, "%d %d %d %d line\n",
  182. LastPenPosition.x, LastPenPosition.y, pos.x, pos.y );
  183. fputs( Line, PlotOutputFile );
  184. }
  185. LastPenPosition = pos;
  186. }
  187. /***********************************************************/
  188. void PrintHeaderPS( FILE* file, const wxString& Creator,
  189. const wxString& FileName, int PageCount,
  190. int BBox[4], int PaperOrientation )
  191. /***********************************************************/
  192. /* The code within this function (and the CloseFilePS function)
  193. * creates postscript files whose contents comply with Adobe's
  194. * Document Structuring Convention, as documented by assorted
  195. * details described within the following URLs:
  196. *
  197. * http://en.wikipedia.org/wiki/Document_Structuring_Conventions
  198. * http://partners.adobe.com/public/developer/en/ps/5001.DSC_Spec.pdf
  199. *
  200. *
  201. * The PageCount and PaperOrientation parameters have been provided to
  202. * respectively cater for the production of multiple-page postscript
  203. * files, and postscript files having either a portrait orientation
  204. * or a landscape orientation.
  205. *
  206. * BBox is the boundary box (position and size of the "client rectangle"
  207. * for drawings (page - margins) in mils (0.001 inch)
  208. */
  209. {
  210. wxString msg;
  211. char Line[1024];
  212. static const char* PSMacro[] = {
  213. "/line {\n",
  214. " newpath\n",
  215. " moveto\n",
  216. " lineto\n",
  217. " stroke\n",
  218. "} bind def\n",
  219. "/cir0 { newpath 0 360 arc stroke } bind def\n",
  220. "/cir1 { newpath 0 360 arc gsave fill grestore stroke } bind def\n",
  221. "/cir2 { newpath 0 360 arc gsave fill grestore stroke } bind def\n",
  222. "/arc0 { newpath arc stroke } bind def\n",
  223. "/arc1 { newpath 4 index 4 index moveto arc closepath gsave fill grestore stroke } bind def\n",
  224. "/arc2 { newpath 4 index 4 index moveto arc closepath gsave fill grestore stroke } bind def\n",
  225. "/poly0 { stroke } bind def\n",
  226. "/poly1 { closepath gsave fill grestore stroke } bind def\n",
  227. "/poly2 { closepath gsave fill grestore stroke } bind def\n",
  228. "/rect0 { rectstroke } bind def\n",
  229. "/rect1 { rectfill } bind def\n",
  230. "/rect2 { rectfill } bind def\n",
  231. "gsave\n",
  232. "72 72 scale\t\t\t% Talk inches\n",
  233. "1 setlinecap\n",
  234. "1 setlinejoin\n",
  235. "1 setlinewidth\n",
  236. NULL
  237. };
  238. const double MIL_TO_INCH = 0.001;
  239. int ii;
  240. time_t time1970 = time( NULL );
  241. PlotOutputFile = file;
  242. fputs( "%!PS-Adobe-3.0\n", PlotOutputFile ); // Print header
  243. sprintf( Line, "%%%%Creator: %s\n", CONV_TO_UTF8( Creator ) );
  244. fputs( Line, PlotOutputFile );
  245. // A "newline" character ("\n") is not included in the following string,
  246. // because it is provided by the ctime() function.
  247. sprintf( Line, "%%%%CreationDate: %s", ctime( &time1970 ) );
  248. fputs( Line, PlotOutputFile );
  249. sprintf( Line, "%%%%Title: %s\n", CONV_TO_UTF8( FileName ) );
  250. fputs( Line, PlotOutputFile );
  251. sprintf( Line, "%%%%Pages: %d\n", PageCount );
  252. fputs( Line, PlotOutputFile );
  253. sprintf( Line, "%%%%PageOrder: Ascend\n" );
  254. fputs( Line, PlotOutputFile );
  255. // Print boundary box en 1/72 pouce, box is in mils
  256. const double CONV_SCALE = MIL_TO_INCH * 72;
  257. // The coordinates of the lower left corner of the boundary
  258. // box need to be "rounded down", but the coordinates of its
  259. // upper right corner need to be "rounded up" instead.
  260. sprintf( Line, "%%%%BoundingBox: %d %d %d %d\n",
  261. (int) floor( (BBox[1] * CONV_SCALE) ), (int) floor( (BBox[0] * CONV_SCALE) ),
  262. (int) ceil( (BBox[3] * CONV_SCALE) ), (int) ceil( (BBox[2] * CONV_SCALE) ) );
  263. fputs( Line, PlotOutputFile );
  264. // Specify the size of the sheet and the name associated with that size.
  265. // (If the "User size" option has been selected for the sheet size,
  266. // identify the sheet size as "Custom" (rather than as "User"), but
  267. // otherwise use the name assigned by KiCad for each sheet size.)
  268. //
  269. // (The Document Structuring Convention also supports sheet weight,
  270. // sheet colour, and sheet type properties being specified within a
  271. // %%DocumentMedia comment, but they are not being specified here;
  272. // a zero and two null strings are subsequently provided instead.)
  273. //
  274. // (NOTE: m_Size.y is *supposed* to be listed before m_Size.x;
  275. // the order in which they are specified is not wrong!)
  276. if( SheetPS->m_Name.Cmp( wxT( "User" ) ) == 0 )
  277. sprintf( Line, "%%%%DocumentMedia: Custom %d %d 0 () ()\n",
  278. (int) round( SheetPS->m_Size.y * CONV_SCALE ),
  279. (int) round( SheetPS->m_Size.x * CONV_SCALE ) );
  280. else // ( if SheetPS->m_Name does not equal "User" )
  281. sprintf( Line, "%%%%DocumentMedia: %s %d %d 0 () ()\n",
  282. CONV_TO_UTF8( SheetPS->m_Name ),
  283. (int) round( SheetPS->m_Size.y * CONV_SCALE ),
  284. (int) round( SheetPS->m_Size.x * CONV_SCALE ) );
  285. fputs( Line, PlotOutputFile );
  286. if( PaperOrientation == wxPORTRAIT )
  287. sprintf( Line, "%%%%Orientation: Portrait\n" );
  288. else
  289. sprintf( Line, "%%%%Orientation: Landscape\n" );
  290. fputs( Line, PlotOutputFile );
  291. sprintf( Line, "%%%%EndComments\n" );
  292. fputs( Line, PlotOutputFile );
  293. // Now specify various other details.
  294. // The following string has been specified here (rather than within
  295. // PSMacro[]) to highlight that it has been provided to ensure that the
  296. // contents of the postscript file comply with the details specified
  297. // within the Document Structuring Convention.
  298. sprintf( Line, "%%%%Page: 1 1\n" );
  299. fputs( Line, PlotOutputFile );
  300. for( ii = 0; PSMacro[ii] != NULL; ii++ )
  301. {
  302. fputs( PSMacro[ii], PlotOutputFile );
  303. }
  304. if( PaperOrientation == wxLANDSCAPE )
  305. sprintf( Line, "%f %f translate 90 rotate\n",
  306. (float) BBox[3] * MIL_TO_INCH, (float) BBox[0] * MIL_TO_INCH );
  307. // (If support for creating postscript files with a portrait orientation
  308. // is ever provided, determine whether it would be necessary to provide
  309. // an "else" command and then an appropriate "sprintf" command here.)
  310. // compensation internationalisation printf (float x.y g�n�r� x,y)
  311. to_point( Line );
  312. fputs( Line, PlotOutputFile );
  313. sprintf( Line, "%f %f scale\t\t%% Move to User coordinates\n",
  314. XScale, YScale );
  315. to_point( Line );
  316. fputs( Line, PlotOutputFile );
  317. // Set default line width ( g_DefaultPenWidth is in user units )
  318. fprintf( PlotOutputFile, "%d setlinewidth\n", g_DefaultPenWidth );
  319. }
  320. /******************************************/
  321. bool CloseFilePS( FILE* plot_file )
  322. /******************************************/
  323. {
  324. fputs( "showpage\n", plot_file );
  325. fputs( "grestore\n", plot_file );
  326. fputs( "%%EOF\n", plot_file );
  327. fclose( plot_file );
  328. return TRUE;
  329. }