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