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.

400 lines
18 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2020 Jean-Pierre Charras, jp.charras at wanadoo.fr
  5. * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software: you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation, either version 3 of the License, or (at your
  10. * option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #pragma once
  21. #include "plotter.h"
  22. #include "gbr_plotter_apertures.h"
  23. class SHAPE_ARC;
  24. class GBR_METADATA;
  25. class GERBER_PLOTTER : public PLOTTER
  26. {
  27. public:
  28. GERBER_PLOTTER();
  29. virtual PLOT_FORMAT GetPlotterType() const override
  30. {
  31. return PLOT_FORMAT::GERBER;
  32. }
  33. static wxString GetDefaultFileExtension()
  34. {
  35. return wxString( wxT( "gbr" ) );
  36. }
  37. /**
  38. * Write GERBER header to file initialize global variable g_Plot_PlotOutputFile.
  39. */
  40. virtual bool StartPlot( const wxString& pageNumber ) override;
  41. virtual bool EndPlot() override;
  42. virtual void SetCurrentLineWidth( int aLineWidth, void* aData = nullptr ) override;
  43. // RS274X has no dashing, nor colors
  44. virtual void SetDash( int aLineWidth, LINE_STYLE aLineStyle ) override
  45. {
  46. }
  47. virtual void SetColor( const COLOR4D& aColor ) override {}
  48. // Currently, aScale and aMirror are not used in gerber plotter
  49. virtual void SetViewport( const VECTOR2I& aOffset, double aIusPerDecimil,
  50. double aScale, bool aMirror ) override;
  51. // Basic plot primitives
  52. virtual void Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill,
  53. int width = USE_DEFAULT_LINE_WIDTH ) override;
  54. virtual void Circle( const VECTOR2I& pos, int diametre, FILL_T fill,
  55. int width = USE_DEFAULT_LINE_WIDTH ) override;
  56. virtual void Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
  57. const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill,
  58. int aWidth = USE_DEFAULT_LINE_WIDTH ) override;
  59. // These functions plot an item and manage X2 gerber attributes
  60. virtual void ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int width,
  61. OUTLINE_MODE tracemode, void* aData ) override;
  62. virtual void ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width,
  63. OUTLINE_MODE tracemode, void* aData ) override;
  64. virtual void ThickCircle( const VECTOR2I& pos, int diametre, int width,
  65. OUTLINE_MODE tracemode, void* aData ) override;
  66. virtual void FilledCircle( const VECTOR2I& pos, int diametre,
  67. OUTLINE_MODE tracemode, void* aData ) override;
  68. /**
  69. * Gerber polygon: they can (and *should*) be filled with the
  70. * appropriate G36/G37 sequence
  71. */
  72. virtual void PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFill,
  73. int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
  74. virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill,
  75. int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) override;
  76. /**
  77. * Similar to PlotPoly(), plot a filled polygon using Gerber region,
  78. * therefore adding X2 attributes to the region object, like TA.xxx
  79. */
  80. void PlotPolyAsRegion( const SHAPE_LINE_CHAIN& aPoly, FILL_T aFill,
  81. int aWidth, GBR_METADATA* aGbrMetadata );
  82. virtual void PenTo( const VECTOR2I& pos, char plume ) override;
  83. virtual void Text( const VECTOR2I& aPos,
  84. const COLOR4D& aColor,
  85. const wxString& aText,
  86. const EDA_ANGLE& aOrient,
  87. const VECTOR2I& aSize,
  88. enum GR_TEXT_H_ALIGN_T aH_justify,
  89. enum GR_TEXT_V_ALIGN_T aV_justify,
  90. int aWidth,
  91. bool aItalic,
  92. bool aBold,
  93. bool aMultilineAllowed,
  94. KIFONT::FONT* aFont,
  95. const KIFONT::METRICS& aFontMetrics,
  96. void* aData = nullptr ) override;
  97. virtual void PlotText( const VECTOR2I& aPos,
  98. const COLOR4D& aColor,
  99. const wxString& aText,
  100. const TEXT_ATTRIBUTES& aAttributes,
  101. KIFONT::FONT* aFont,
  102. const KIFONT::METRICS& aFontMetrics,
  103. void* aData = nullptr ) override;
  104. /**
  105. * Filled circular flashes are stored as apertures
  106. */
  107. virtual void FlashPadCircle( const VECTOR2I& pos, int diametre,
  108. OUTLINE_MODE trace_mode, void* aData ) override;
  109. virtual void FlashPadOval( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
  110. const EDA_ANGLE& aOrient, OUTLINE_MODE aTraceMode,
  111. void* aData ) override;
  112. virtual void FlashPadRect( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
  113. const EDA_ANGLE& aOrient, OUTLINE_MODE aTraceMode,
  114. void* aData ) override;
  115. virtual void FlashPadRoundRect( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
  116. int aCornerRadius, const EDA_ANGLE& aOrient,
  117. OUTLINE_MODE aTraceMode, void* aData ) override;
  118. virtual void FlashPadCustom( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
  119. const EDA_ANGLE& aPadOrient, SHAPE_POLY_SET* aPolygons,
  120. OUTLINE_MODE aTraceMode, void* aData ) override;
  121. virtual void FlashPadTrapez( const VECTOR2I& aPadPos, const VECTOR2I* aCorners,
  122. const EDA_ANGLE& aPadOrient, OUTLINE_MODE aTraceMode,
  123. void* aData ) override;
  124. virtual void FlashRegularPolygon( const VECTOR2I& aShapePos, int aDiameter, int aCornerCount,
  125. const EDA_ANGLE& aOrient, OUTLINE_MODE aTraceMode,
  126. void* aData ) override;
  127. /**
  128. * Flash a chamfered round rect pad.
  129. *
  130. * @param aShapePos is the position of the pad shape.
  131. * @param aPadSize is the size of the rectangle.
  132. * @param aCornerRadius is the radius of rounded corners.
  133. * @param aChamferRatio is the chamfer value (ratio < 0.5 between smallest size and chamfer).
  134. * @param aChamferPositions is the identifier of the corners to chamfer:
  135. * 0 = no chamfer
  136. * 1 = TOP_LEFT
  137. * 2 = TOP_RIGHT
  138. * 4 = BOTTOM_LEFT
  139. * 8 = BOTTOM_RIGHT
  140. * @param aPadOrient is the rotation of the shape.
  141. * @param aPlotMode is the drawing mode, FILLED or SKETCH.
  142. * @param aData is the a reference to Gerber attributes descr.
  143. */
  144. void FlashPadChamferRoundRect( const VECTOR2I& aShapePos, const VECTOR2I& aPadSize,
  145. int aCornerRadius, double aChamferRatio,
  146. int aChamferPositions, const EDA_ANGLE& aPadOrient,
  147. OUTLINE_MODE aPlotMode, void* aData );
  148. /**
  149. * Plot a Gerber region: similar to PlotPoly but plot only filled polygon,
  150. * and add the TA.AperFunction if aGbrMetadata contains this attribute, and clear it
  151. * after plotting.
  152. */
  153. void PlotGerberRegion( const std::vector<VECTOR2I>& aCornerList, GBR_METADATA* aGbrMetadata );
  154. void PlotGerberRegion( const SHAPE_LINE_CHAIN& aPoly, GBR_METADATA* aGbrMetadata );
  155. /**
  156. * Change the plot polarity and begin a new layer.
  157. *
  158. * Used to 'scratch off' silk screen away from solder mask.
  159. */
  160. virtual void SetLayerPolarity( bool aPositive ) override;
  161. /**
  162. * Selection of Gerber units and resolution (number of digits in mantissa).
  163. *
  164. * Should be called only after SetViewport() is called.
  165. *
  166. * @param aResolution is the number of digits in mantissa of coordinate
  167. * use 5 or 6 for mm and 6 or 7 for inches
  168. * do not use value > 6 (mm) or > 7 (in) to avoid overflow.
  169. * @param aUseInches use true to use inches, false to use mm (default).
  170. */
  171. virtual void SetGerberCoordinatesFormat( int aResolution, bool aUseInches = false ) override;
  172. void UseX2format( bool aEnable ) { m_useX2format = aEnable; }
  173. void UseX2NetAttributes( bool aEnable ) { m_useNetAttributes = aEnable; }
  174. /**
  175. * Disable Aperture Macro (AM) command, only for broken Gerber Readers.
  176. *
  177. * Regions will be used instead of AM shapes to draw complex shapes.
  178. *
  179. * @param aDisable use true to disable Aperture Macro (AM) command.
  180. */
  181. void DisableApertMacros( bool aDisable ) { m_gerberDisableApertMacros = aDisable; }
  182. /**
  183. * Calling this function allows one to define the beginning of a group
  184. * of drawing items (used in X2 format with netlist attributes).
  185. *
  186. * @param aData can define any parameter.
  187. */
  188. virtual void StartBlock( void* aData ) override;
  189. /**
  190. * Define the end of a group of drawing items the group is started by StartBlock().
  191. *
  192. * Used in X2 format with netlist attributes.
  193. *
  194. * @param aData can define any parameter
  195. */
  196. virtual void EndBlock( void* aData ) override;
  197. /**
  198. * Remove (clear) all attributes from object attributes dictionary (TO. and TA commands)
  199. * similar to clearNetAttribute(), this is an unconditional reset of TO. and TA. attributes.
  200. */
  201. void ClearAllAttributes();
  202. /**
  203. * @param aSize is the size of tool.
  204. * @param aRadius is the radius used for some shapes tool (oval, roundrect macros).
  205. * @param aRotation is the rotation of tool (primitives round, oval rect accept only 0.0).
  206. * @param aType is the type ( shape ) of tool.
  207. * @param aApertureAttribute is an aperture attribute of the tool (a tool can have only one
  208. * attribute) 0 = no specific attribute.
  209. * @return an index to the aperture in aperture list which meets the size and type of tool
  210. * if the aperture does not exist, it is created and entered in aperture list.
  211. */
  212. int GetOrCreateAperture( const VECTOR2I& aSize, int aRadius, const EDA_ANGLE& aRotation,
  213. APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
  214. /**
  215. * @param aCorners is the corner list.
  216. * @param aRotation is the rotation of tool.
  217. * @param aType is the type ( shape ) of tool that can manage a list of corners (polygon).
  218. * @param aApertureAttribute is an aperture attribute of the tool (a tool can have only one
  219. * attribute) 0 = no specific attribute.
  220. * @return an index to the aperture in aperture list which meets the data and type of tool
  221. * if the aperture does not exist, it is created and entered in aperture list.
  222. */
  223. int GetOrCreateAperture( const std::vector<VECTOR2I>& aCorners, const EDA_ANGLE& aRotation,
  224. APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
  225. protected:
  226. virtual void ThickArc( const VECTOR2D& aCentre, const EDA_ANGLE& aStartAngle,
  227. const EDA_ANGLE& aAngle, double aRadius, int aWidth,
  228. OUTLINE_MODE aTraceMode, void* aData ) override;
  229. /**
  230. * Plot a round rect (a round rect shape in fact) as a Gerber region using lines and arcs
  231. * for corners.
  232. *
  233. * @note Only the G36 ... G37 region is created.
  234. *
  235. * @param aRectCenter is the center of the rectangle.
  236. * @param aSize is the size of the rectangle.
  237. * @param aCornerRadius is the radius of the corners.
  238. * @param aOrient is the rotation of the rectangle.
  239. */
  240. void plotRoundRectAsRegion( const VECTOR2I& aRectCenter, const VECTOR2I& aSize,
  241. int aCornerRadius, const EDA_ANGLE& aOrient );
  242. /**
  243. * Plot a Gerber arc.
  244. *
  245. * If aPlotInRegion = true, the current pen position will not be initialized to the arc
  246. * start position, and therefore the arc can be used to define a region outline item
  247. * a line will be created from current position to arc start point. If aPlotInRegion
  248. * = false, the current pen position will be initialized to the arc start position, to
  249. * plot an usual arc item. The line thickness is not initialized in plotArc, and must
  250. * be initialized before calling it if needed.
  251. */
  252. void plotArc( const VECTOR2I& aCenter, const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aEndAngle,
  253. double aRadius, bool aPlotInRegion );
  254. void plotArc( const SHAPE_ARC& aArc, bool aPlotInRegion );
  255. /**
  256. * Pick an existing aperture or create a new one, matching the size, type and attributes.
  257. *
  258. * Write the DCode selection on gerber file.
  259. */
  260. void selectAperture( const VECTOR2I& aSize, int aRadius, const EDA_ANGLE& aRotation,
  261. APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
  262. /**
  263. * Pick an existing aperture or create a new one, matching the aDiameter, aPolygonRotation,
  264. * type and attributes.
  265. *
  266. * It apply only to apertures with type = AT_REGULAR_POLY3 to AT_REGULAR_POLY12
  267. * write the DCode selection on gerber file
  268. */
  269. void selectAperture( const std::vector<VECTOR2I>& aCorners, const EDA_ANGLE& aPolygonRotation,
  270. APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
  271. /**
  272. * Pick an existing aperture or create a new one, matching the corner list, aRotDegree,
  273. * type and attributes.
  274. *
  275. * It only applies to apertures managing a polygon that differs from AT_REGULAR_POLY3
  276. * to AT_REGULAR_POLY12 (for instance APER_MACRO_TRAPEZOID ) write the DCode selection
  277. * on gerber file.
  278. */
  279. void selectAperture( int aDiameter, const EDA_ANGLE& aRotation,
  280. APERTURE::APERTURE_TYPE aType, int aApertureAttribute );
  281. /**
  282. * Emit a D-Code record, using proper conversions to format a leading zero omitted gerber
  283. * coordinate.
  284. *
  285. * For n decimal positions, see header generation in start_plot.
  286. */
  287. void emitDcode( const VECTOR2D& pt, int dcode );
  288. /**
  289. * Print a Gerber net attribute object record.
  290. *
  291. * In a gerber file, a net attribute is owned by a graphic object formatNetAttribute must
  292. * be called before creating the object. The generated string depends on the type of
  293. * netlist info.
  294. *
  295. * @param aData contains the data to format.
  296. */
  297. void formatNetAttribute( GBR_NETLIST_METADATA* aData );
  298. /**
  299. * Clear a Gerber net attribute record (clear object attribute dictionary)
  300. * and output the clear object attribute dictionary command to gerber file
  301. * has effect only if a net attribute is stored in m_objectAttributesDictionary.
  302. */
  303. void clearNetAttribute();
  304. // the attributes dictionary created/modified by %TO, attached to objects, when they are created
  305. // by D01, D03, G36/G37 commands
  306. // standard attributes are .P, .C and .N
  307. // this is used by gerber readers when creating a new object. Cleared by %TD command
  308. // Note: m_objectAttributesDictionary can store more than one attribute
  309. // the string stores the line(s) actually written to the gerber file
  310. // it can store a .P, .C or .N attribute, or 2 or 3 attributes, separated by a \n char (EOL)
  311. std::string m_objectAttributesDictionary;
  312. // The last aperture attribute generated (only one aperture attribute can be set)
  313. int m_apertureAttribute;
  314. FILE* workFile;
  315. FILE* finalFile;
  316. wxString m_workFilename;
  317. /**
  318. * Generate the table of D codes
  319. */
  320. void writeApertureList();
  321. std::vector<APERTURE> m_apertures; // The list of available apertures
  322. int m_currentApertureIdx; // The index of the current aperture in m_apertures
  323. bool m_hasApertureRoundRect; // true is at least one round rect aperture is in use
  324. bool m_hasApertureRotOval; // true is at least one oval rotated aperture is in use
  325. bool m_hasApertureRotRect; // true is at least one rect. rotated aperture is in use
  326. bool m_hasApertureOutline4P; // true is at least one 4 corners outline (free polygon
  327. // with 4 corners) aperture is in use
  328. bool m_hasApertureChamferedRect; // true is at least one chamfered rect is in use
  329. // (with no rounded corner)
  330. bool m_gerberUnitInch; // true if the gerber units are inches, false for mm
  331. int m_gerberUnitFmt; // number of digits in mantissa.
  332. // usually 6 in Inches and 5 or 6 in mm
  333. bool m_gerberDisableApertMacros; // True to disable Aperture Macro (AM) command,
  334. // for broken Gerber Readers
  335. // Regions will be used instead of AM shapes
  336. bool m_useX2format; // Add X2 file header attributes. If false, attributes
  337. // will be added as comments.
  338. bool m_useNetAttributes; // In recent gerber files, netlist info can be added.
  339. // It will be added if this param is true, using X2 or
  340. // X1 format
  341. // A list of aperture macros defined "on the fly" because the number of parameters is not
  342. // defined: this is the case of the macro using the primitive 4 to create a polygon.
  343. // The number of vertices is not known for free polygonal shapes, and an aperture macro
  344. // must be created for each specific polygon
  345. APER_MACRO_FREEPOLY_LIST m_am_freepoly_list;
  346. };