1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
23  */
24 
25 /**
26  * Plot settings, and plotting engines (PostScript, Gerber, HPGL and DXF)
27  *
28  * @file plotter.h
29  */
30 
31 #ifndef PLOT_COMMON_H_
32 #define PLOT_COMMON_H_
33 
34 #include <eda_shape.h>
35 #include <vector>
36 #include <math/box2.h>
37 #include <gr_text.h>
38 #include <page_info.h>
39 #include <outline_mode.h>
40 #include <gal/color4d.h>
41 #include <render_settings.h>
42 
43 class COLOR_SETTINGS;
44 class SHAPE_ARC;
45 class SHAPE_POLY_SET;
46 class SHAPE_LINE_CHAIN;
47 class GBR_NETLIST_METADATA;
48 class PROJECT;
49 
50 using KIGFX::RENDER_SETTINGS;
51 
52 
53 // Must be in the same order as the drop-down list in the plot dialog inside pcbnew
54 // Units (inch/mm for DXF plotter
55 enum class DXF_UNITS
56 {
57     INCHES = 0,
58     MILLIMETERS = 1
59 };
60 
61 
62 /**
63  * The set of supported output plot formats.
64  *
65    They should be kept in order of the radio buttons in the plot panel/windows.
66  */
67 enum class PLOT_FORMAT
68 {
69     UNDEFINED    = -1,
70     FIRST_FORMAT = 0,
71     HPGL         = FIRST_FORMAT,
72     GERBER,
73     POST,
74     DXF,
75     PDF,
76     SVG,
77     LAST_FORMAT = SVG
78 };
79 
80 /**
81  * Which kind of text to output with the PSLIKE plotters.
82  *
83  * You can:
84  * 1) only use the internal vector font
85  * 2) only use native postscript fonts
86  * 3) use the internal vector font and add 'phantom' text to aid
87  *    searching
88  * 4) keep the default for the plot driver
89  *
90  * This is recognized by the DXF driver too, where NATIVE emits
91  * TEXT entities instead of stroking the text
92  */
93 enum class PLOT_TEXT_MODE
94 {
95     STROKE,
96     NATIVE,
97     PHANTOM,
98     DEFAULT
99 };
100 
101 /**
102  * Dashed line types.
103  */
104 enum class PLOT_DASH_TYPE
105 {
106     DEFAULT    = -1,
107     SOLID      = 0,
108     FIRST_TYPE = SOLID,
109     DASH,
110     DOT,
111     DASHDOT,
112     LAST_TYPE = DASHDOT
113 };
114 
115 /**
116  * Base plotter engine class. General rule: all the interface with the caller
117  * is done in IU, the IU size is specified with SetViewport. Internal and
118  * output processing is usually done in decimils (or whatever unit the
119  * effective engine class need to use)
120  */
121 class PLOTTER
122 {
123 public:
124     // These values are used as flag for pen or aperture selection
125     static const int DO_NOT_SET_LINE_WIDTH = -2;    // Skip selection
126     static const int USE_DEFAULT_LINE_WIDTH = -1;   // use the default pen
127 
128     PLOTTER();
129 
130     virtual ~PLOTTER();
131 
132     /**
133      * Returns the effective plot engine in use. It's not very OO but for
134      * now is required since some things are only done with some output devices
135      * (like drill marks, emitted only for postscript
136      */
137     virtual PLOT_FORMAT GetPlotterType() const = 0;
138 
139     virtual bool StartPlot() = 0;
140     virtual bool EndPlot() = 0;
141 
SetNegative(bool aNegative)142     virtual void SetNegative( bool aNegative )
143     {
144         m_negativeMode = aNegative;
145     }
146 
147     /**
148      * Plot in B/W or color.
149      *
150      * @param aColorMode use true to plot in color, false to plot in black and white.
151      */
SetColorMode(bool aColorMode)152     virtual void SetColorMode( bool aColorMode ) { m_colorMode = aColorMode; }
GetColorMode()153     bool GetColorMode() const { return m_colorMode; }
154 
SetRenderSettings(RENDER_SETTINGS * aSettings)155     void SetRenderSettings( RENDER_SETTINGS* aSettings ) { m_renderSettings = aSettings; }
RenderSettings()156     RENDER_SETTINGS* RenderSettings() { return m_renderSettings; }
157 
SetPageSettings(const PAGE_INFO & aPageSettings)158     virtual void SetPageSettings( const PAGE_INFO& aPageSettings ) { m_pageInfo = aPageSettings; }
PageSettings()159     PAGE_INFO& PageSettings() { return m_pageInfo; }
160 
161     /**
162      * Set the line width for the next drawing.
163      *
164      * @param width is specified in IUs.
165      * @param aData is an auxiliary parameter, mainly used in gerber plotter.
166      */
167     virtual void SetCurrentLineWidth( int width, void* aData = nullptr ) = 0;
GetCurrentLineWidth()168     virtual int GetCurrentLineWidth() const  { return m_currentPenWidth; }
169 
170     virtual void SetColor( const COLOR4D& color ) = 0;
171 
172     virtual void SetDash( PLOT_DASH_TYPE dashed ) = 0;
173 
SetCreator(const wxString & aCreator)174     virtual void SetCreator( const wxString& aCreator ) { m_creator = aCreator; }
175 
SetTitle(const wxString & aTitle)176     virtual void SetTitle( const wxString& aTitle ) { m_title = aTitle; }
177 
178     /**
179      * Add a line to the list of free lines to print at the beginning of the file.
180      *
181      * @param aExtraString is the string to print
182      */
AddLineToHeader(const wxString & aExtraString)183     void AddLineToHeader( const wxString& aExtraString )
184     {
185         m_headerExtraLines.Add( aExtraString );
186     }
187 
188     /**
189      * Remove all lines from the list of free lines to print at the beginning of the file
190      */
ClearHeaderLinesList()191     void ClearHeaderLinesList()
192     {
193         m_headerExtraLines.Clear();
194     }
195 
196     /**
197      * Set the plot offset and scaling for the current plot
198      *
199      * @param aOffset is the plot offset.
200      * @param aIusPerDecimil gives the scaling factor from IUs to device units
201      * @param aScale is the user set plot scaling factor (either explicitly
202      *      or using 'fit to A4').
203      * @param aMirror flips the plot in the Y direction (useful for toner
204      *      transfers or some kind of film).
205      */
206     virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
207                               double aScale, bool aMirror ) = 0;
208 
209     /**
210      * Open or create the plot file \a aFullFilename.
211      *
212      * @param aFullFilename is the full file name of the file to create.
213      * @return true if success, false if the file cannot be created/opened.
214      *
215      * Virtual because some plotters use ascii files, some others binary files (PDF)
216      * The base class open the file in text mode
217      */
218     virtual bool OpenFile( const wxString& aFullFilename );
219 
220     /**
221      * The IUs per decimil are an essential scaling factor when
222      * plotting; they are set and saved when establishing the viewport.
223      * Here they can be get back again
224      */
GetIUsPerDecimil()225     double GetIUsPerDecimil() const { return m_IUsPerDecimil; }
226 
GetPlotterArcLowDef()227     int GetPlotterArcLowDef() const { return m_IUsPerDecimil * 8; }
GetPlotterArcHighDef()228     int GetPlotterArcHighDef() const { return m_IUsPerDecimil * 2; }
229 
230     // Low level primitives
231     virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
232                        int width = USE_DEFAULT_LINE_WIDTH ) = 0;
233     virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
234                          int width = USE_DEFAULT_LINE_WIDTH ) = 0;
235 
236     /**
237      * Generic fallback: arc rendered as a polyline.
238      */
239     virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle, int rayon,
240                       FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH );
241     virtual void Arc(  const SHAPE_ARC& aArc );
242 
243     /**
244      * Generic fallback: Cubic Bezier curve rendered as a polyline
245      * In KiCad the bezier curves have 4 control points:
246      * start ctrl1 ctrl2 end
247      */
248     virtual void BezierCurve( const wxPoint& aStart, const wxPoint& aControl1,
249                               const wxPoint& aControl2, const wxPoint& aEnd,
250                               int aTolerance, int aLineThickness = USE_DEFAULT_LINE_WIDTH );
251 
252     /**
253      * Moveto/lineto primitive, moves the 'pen' to the specified direction.
254      *
255      * @param pos is the target position.
256      * @param plume specifies the kind of motion: 'U' only moves the pen,
257      *      'D' draw a line from the current position and 'Z' finish
258      *      the drawing and returns the 'pen' to rest (flushes the trace).
259      */
260     virtual void PenTo( const wxPoint& pos, char plume ) = 0;
261 
262     // Convenience functions for PenTo
MoveTo(const wxPoint & pos)263     void MoveTo( const wxPoint& pos )
264     {
265         PenTo( pos, 'U' );
266     }
267 
LineTo(const wxPoint & pos)268     void LineTo( const wxPoint& pos )
269     {
270         PenTo( pos, 'D' );
271     }
272 
FinishTo(const wxPoint & pos)273     void FinishTo( const wxPoint& pos )
274     {
275         PenTo( pos, 'D' );
276         PenTo( pos, 'Z' );
277     }
278 
PenFinish()279     void PenFinish()
280     {
281         // The point is not important with Z motion
282         PenTo( wxPoint( 0, 0 ), 'Z' );
283     }
284 
285     /**
286      * Draw a polygon ( filled or not ).
287      *
288      * @param aCornerList is the corners list (a std::vector< wxPoint >).
289      * @param aFill is the type of fill.
290      * @param aWidth is the line width.
291      * @param aData is an auxiliary info (mainly for gerber format).
292      */
293     virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
294                            int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr ) = 0;
295 
296     /**
297      * Draw a polygon ( filled or not ).
298      * @param aCornerList is the corners list (a SHAPE_LINE_CHAIN).
299      *        must be closed (IsClosed() == true) for a polygon. Otherwise this is a polyline.
300      * @param aFill is the type of fill.
301      * @param aWidth is the line width.
302      * @param aData is an auxiliary info (mainly for gerber format).
303      */
304     virtual void PlotPoly( const SHAPE_LINE_CHAIN& aCornerList, FILL_T aFill,
305                            int aWidth = USE_DEFAULT_LINE_WIDTH, void* aData = nullptr );
306 
307     /**
308      * Only PostScript plotters can plot bitmaps.
309      *
310      * A rectangle is plotted for plotters that cannot plot a bitmap.
311      *
312      * @param aImage is the bitmap.
313      * @param aPos is position of the center of the bitmap.
314      * @param aScaleFactor is the scale factor to apply to the bitmap size
315      *                      (this is not the plot scale factor).
316      */
317     virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos, double aScaleFactor );
318 
319     // Higher level primitives -- can be drawn as line, sketch or 'filled'
320     virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width,
321                                OUTLINE_MODE tracemode, void* aData );
322     virtual void ThickArc( const wxPoint& centre, double StAngle, double EndAngle,
323                            int rayon, int width, OUTLINE_MODE tracemode, void* aData );
324     virtual void ThickRect( const wxPoint& p1, const wxPoint& p2, int width,
325                             OUTLINE_MODE tracemode, void* aData );
326     virtual void ThickCircle( const wxPoint& pos, int diametre, int width,
327                               OUTLINE_MODE tracemode, void* aData );
328     virtual void FilledCircle( const wxPoint& pos, int diametre,
329                               OUTLINE_MODE tracemode, void* aData );
330 
331 
332     // Flash primitives
333 
334     /**
335      * @param aPadPos Position of the shape (center of the rectangle.
336      * @param aDiameter is the diameter of round pad.
337      * @param aTraceMode is the drawing mode, FILLED or SKETCH.
338      * @param aData is an auxiliary info (mainly for gerber format attributes).
339      */
340     virtual void FlashPadCircle( const wxPoint& aPadPos, int aDiameter,
341                                  OUTLINE_MODE aTraceMode, void* aData ) = 0;
342 
343     /**
344      * @param aPadPos Position of the shape (center of the rectangle.
345      * @param aSize is the size of oblong shape.
346      * @param aPadOrient The rotation of the shape.
347      * @param aTraceMode is the drawing mode, FILLED or SKETCH.
348      * @param aData an auxiliary info (mainly for gerber format attributes).
349      */
350     virtual void FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient,
351                                OUTLINE_MODE aTraceMode, void* aData ) = 0;
352 
353     /**
354      * @param aPadPos Position of the shape (center of the rectangle).
355      * @param aSize is the size of rounded rect.
356      * @param aPadOrient The rotation of the shape.
357      * @param aTraceMode is the drawing mode, FILLED or SKETCH.
358      * @param aData an auxiliary info (mainly for gerber format attributes).
359      */
360     virtual void FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize,
361                                double aPadOrient, OUTLINE_MODE aTraceMode, void* aData ) = 0;
362 
363     /**
364      * @param aPadPos Position of the shape (center of the rectangle.
365      * @param aSize is the size of rounded rect.
366      * @param aCornerRadius Radius of the rounded corners.
367      * @param aOrient The rotation of the shape.
368      * @param aTraceMode is the drawing mode, FILLED or SKETCH.
369      * @param aData an auxiliary info (mainly for gerber format attributes).
370      */
371     virtual void FlashPadRoundRect( const wxPoint& aPadPos, const wxSize& aSize,
372                                     int aCornerRadius, double aOrient,
373                                     OUTLINE_MODE aTraceMode, void* aData ) = 0;
374 
375     /**
376      * @param aPadPos Position of the shape.
377      * @param aSize is the size of round reference pad.
378      * @param aPadOrient is the pad rotation, used only with aperture macros (Gerber plotter).
379      * @param aPolygons the shape as polygon set.
380      * @param aTraceMode is the drawing mode, FILLED or SKETCH.
381      * @param aData an auxiliary info (mainly for gerber format attributes).
382      */
383     virtual void FlashPadCustom( const wxPoint& aPadPos, const wxSize& aSize,
384                                  double aPadOrient, SHAPE_POLY_SET* aPolygons,
385                                  OUTLINE_MODE aTraceMode, void* aData ) = 0;
386 
387     /**
388      * Flash a trapezoidal pad.
389      *
390      * @param aPadPos is the the position of the shape.
391      * @param aCorners is the list of 4 corners positions, relative to the shape position,
392      *                 pad orientation 0.
393      * @param aPadOrient is the rotation of the shape.
394      * @param aTraceMode is the drawing mode, FILLED or SKETCH.
395      * @param aData an auxiliary info (mainly for gerber format attributes).
396      */
397     virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
398                                  double aPadOrient, OUTLINE_MODE aTraceMode,
399                                  void* aData ) = 0;
400 
401     /**
402      * Flash a regular polygon. Useful only in Gerber files to flash a regular polygon.
403      *
404      * @param aShapePos is the center of the circle containing the polygon.
405      * @param aRadius is the radius of the circle containing the polygon.
406      * @param aCornerCount is the number of vertices.
407      * @param aOrient is the polygon rotation in degrees.
408      * @param aData is a auxiliary parameter used (if needed) to handle extra info
409      *              specific to the plotter.
410      */
411     virtual void FlashRegularPolygon( const wxPoint& aShapePos, int aDiameter, int aCornerCount,
412                                       double aOrient, OUTLINE_MODE aTraceMode, void* aData ) = 0 ;
413 
414     /**
415      * Draw text with the plotter.
416      *
417      * For convenience it accept the color to use for specific plotters (GERBER) aData is used
418      * to pass extra parameters.
419      */
420     virtual void Text( const wxPoint&              aPos,
421                        const COLOR4D&              aColor,
422                        const wxString&             aText,
423                        double                      aOrient,
424                        const wxSize&               aSize,
425                        enum EDA_TEXT_HJUSTIFY_T    aH_justify,
426                        enum EDA_TEXT_VJUSTIFY_T    aV_justify,
427                        int                         aWidth,
428                        bool                        aItalic,
429                        bool                        aBold,
430                        bool                        aMultilineAllowed = false,
431                        void*                       aData = nullptr );
432 
433     /**
434      * Draw a marker (used for the drill map).
435      */
436     static const unsigned MARKER_COUNT = 58;
437 
438     /**
439      * Draw a pattern shape number aShapeId, to coord position.
440      *
441      * @param aPosition is the position of the marker.
442      * @param aDiameter is the diameter of the marker.
443      * @param aShapeId is the index (used to generate forms characters).
444      */
445     void Marker( const wxPoint& position, int diametre, unsigned aShapeId );
446 
447     /**
448      * Set the current Gerber layer polarity to positive or negative
449      * by writing \%LPD*\% or \%LPC*\% to the Gerber file, respectively.
450      * (obviously starts a new Gerber layer, too)
451      *
452      * @param aPositive is the layer polarity and true for positive.
453      * It's not useful with most other plotter since they can't 'scratch'
454      * the film like photoplotter imagers do
455      */
SetLayerPolarity(bool aPositive)456     virtual void SetLayerPolarity( bool aPositive )
457     {
458         // NOP for most plotters
459     }
460 
461     /**
462      * Change the current text mode. See the PlotTextMode
463      * explanation at the beginning of the file.
464      */
SetTextMode(PLOT_TEXT_MODE mode)465     virtual void SetTextMode( PLOT_TEXT_MODE mode )
466     {
467         // NOP for most plotters.
468     }
469 
470     virtual void SetGerberCoordinatesFormat( int aResolution, bool aUseInches = false )
471     {
472         // NOP for most plotters. Only for Gerber plotter
473     }
474 
475     virtual void SetSvgCoordinatesFormat( unsigned aResolution, bool aUseInches = false )
476     {
477         // NOP for most plotters. Only for SVG plotter
478     }
479 
480     /**
481      * calling this function allows one to define the beginning of a group
482      * of drawing items, for instance in SVG  or Gerber format.
483      * (example: group all segments of a letter or a text)
484      * @param aData can define any parameter
485      * for most of plotters: do nothing
486      */
StartBlock(void * aData)487     virtual void StartBlock( void* aData ) {}
488 
489     /**
490      * calling this function allows one to define the end of a group of drawing
491      * items for instance in SVG  or Gerber format.
492      * the group is started by StartBlock()
493      * @param aData can define any parameter
494      * for most of plotters: do nothing
495      */
EndBlock(void * aData)496     virtual void EndBlock( void* aData ) {}
497 
498 
499 protected:
500     // These are marker subcomponents
501     /**
502      * Plot a circle centered on the position. Building block for markers
503      */
504     void markerCircle( const wxPoint& pos, int radius );
505 
506     /**
507      * Plot a - bar centered on the position. Building block for markers
508      */
509     void markerHBar( const wxPoint& pos, int radius );
510 
511     /**
512      * Plot a / bar centered on the position. Building block for markers
513      */
514     void markerSlash( const wxPoint& pos, int radius );
515 
516     /**
517      * Plot a \ bar centered on the position. Building block for markers
518      */
519     void markerBackSlash( const wxPoint& pos, int radius );
520 
521     /**
522      * Plot a | bar centered on the position. Building block for markers
523      */
524     void markerVBar( const wxPoint& pos, int radius );
525 
526     /**
527      * Plot a square centered on the position. Building block for markers
528      */
529     void markerSquare( const wxPoint& position, int radius );
530 
531     /**
532      * Plot a lozenge centered on the position. Building block for markers
533      */
534     void markerLozenge( const wxPoint& position, int radius );
535 
536     // Helper function for sketched filler segment
537 
538     /**
539      * Convert a thick segment and plot it as an oval
540      */
541     void segmentAsOval( const wxPoint& start, const wxPoint& end, int width,
542                         OUTLINE_MODE tracemode );
543 
544     void sketchOval( const wxPoint& pos, const wxSize& size, double orient, int width );
545 
546     // Coordinate and scaling conversion functions
547 
548     /**
549      * Modify coordinates according to the orientation, scale factor, and offsets trace. Also
550      * convert from a wxPoint to DPOINT, since some output engines needs floating point
551      * coordinates.
552      */
553     virtual DPOINT userToDeviceCoordinates( const wxPoint& aCoordinate );
554 
555     /**
556      * Modify size according to the plotter scale factors (wxSize version, returns a DPOINT).
557      */
558     virtual DPOINT userToDeviceSize( const wxSize& size );
559 
560     /**
561      * Modify size according to the plotter scale factors (simple double version).
562      */
563     virtual double userToDeviceSize( double size ) const;
564 
565     double GetDotMarkLenIU() const;
566 
567     double GetDashMarkLenIU() const;
568 
569     double GetDashGapLenIU() const;
570 
571 protected:      // variables used in most of plotters:
572     /// Plot scale - chosen by the user (even implicitly with 'fit in a4')
573     double           m_plotScale;
574 
575     /* Caller scale (how many IUs in a decimil - always); it's a double
576      * because in Eeschema there are 0.1 IUs in a decimil (Eeschema
577      * always works in mils internally) while PcbNew can work in decimil
578      * or nanometers, so this value would be >= 1 */
579     double           m_IUsPerDecimil;
580 
581     double           m_iuPerDeviceUnit;     // Device scale (from IUs to plotter device units;
582                                             // usually decimils)
583     wxPoint          m_plotOffset;          // Plot offset (in IUs)
584     bool             m_plotMirror;          // X axis orientation (SVG)
585                                             // and plot mirrored (only for PS, PDF HPGL and SVG)
586     bool             m_mirrorIsHorizontal;  // true to mirror horizontally (else vertically)
587     bool             m_yaxisReversed;       // true if the Y axis is top to bottom (SVG)
588 
589     /// Output file
590     FILE*            m_outputFile;
591 
592     // Pen handling
593     bool             m_colorMode;           // true to plot in color, otherwise black & white
594     bool             m_negativeMode;        // true to generate a negative image (PS mode mainly)
595     int              m_currentPenWidth;
596     char             m_penState;            // current pen state: 'U', 'D' or 'Z' (see PenTo)
597     wxPoint          m_penLastpos;          // last pen position; -1,-1 when pen is at rest
598 
599     wxString         m_creator;
600     wxString         m_filename;
601     wxString         m_title;
602     PAGE_INFO        m_pageInfo;
603     wxSize           m_paperSize;           // Paper size in IU - not in mils
604 
605     wxArrayString    m_headerExtraLines;    // a set of string to print in header file
606 
607     RENDER_SETTINGS* m_renderSettings;
608 };
609 
610 
611 class TITLE_BLOCK;
612 
613 void PlotDrawingSheet( PLOTTER* plotter, const PROJECT* aProject, const TITLE_BLOCK& aTitleBlock,
614                        const PAGE_INFO& aPageInfo, const wxString& aSheetNumber, int aSheetCount,
615                        const wxString& aSheetDesc, const wxString& aFilename,
616                        COLOR4D aColor = COLOR4D::UNSPECIFIED, bool aIsFirstPage = true );
617 
618 /** Returns the default plot extension for a format
619   */
620 wxString GetDefaultPlotExtension( PLOT_FORMAT aFormat );
621 
622 
623 #endif  // PLOT_COMMON_H_
624