1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
|
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
* Copyright (C) 2015 KiCad Developers, see CHANGELOG.TXT for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* Common plot library \n
* Plot settings, and plotting engines (Postscript, Gerber, HPGL and DXF)
*
* @file plot_common.h
*/
#ifndef PLOT_COMMON_H_
#define PLOT_COMMON_H_
#include <vector>
#include <math/box2.h>
#include <drawtxt.h>
#include <class_page_info.h>
#include <eda_text.h> // FILL_T
/**
* Enum PlotFormat
* is the set of supported output plot formats. They should be kept in order
* of the radio buttons in the plot panel/windows.
*/
enum PlotFormat {
PLOT_FIRST_FORMAT = 0,
PLOT_FORMAT_HPGL = PLOT_FIRST_FORMAT,
PLOT_FORMAT_GERBER,
PLOT_FORMAT_POST,
PLOT_FORMAT_DXF,
PLOT_FORMAT_PDF,
PLOT_FORMAT_SVG,
PLOT_LAST_FORMAT = PLOT_FORMAT_SVG
};
/**
* Enum for choosing which kind of text to output with the PSLIKE
* plotters. You can:
* 1) only use the internal vector font
* 2) only use native postscript fonts
* 3) use the internal vector font and add 'phantom' text to aid
* searching
* 4) keep the default for the plot driver
*
* This is recognized by the DXF driver too, where NATIVE emits
* TEXT entities instead of stroking the text
*/
enum PlotTextMode {
PLOTTEXTMODE_STROKE,
PLOTTEXTMODE_NATIVE,
PLOTTEXTMODE_PHANTOM,
PLOTTEXTMODE_DEFAULT
};
/**
* Base plotter engine class. General rule: all the interface with the caller
* is done in IU, the IU size is specified with SetViewport. Internal and
* output processing is usually done in decimils (or whatever unit the
* effective engine class need to use)
*/
class PLOTTER
{
private:
double m_dashMarkLength_mm ; ///< Dashed line parameter in mm: segment
double m_dashGapLength_mm; ///< Dashed line parameter in mm: gap
public:
static const int USE_DEFAULT_LINE_WIDTH = -1;
PLOTTER();
virtual ~PLOTTER();
/**
* Returns the effective plot engine in use. It's not very OO but for
* now is required since some things are only done with some output devices
* (like drill marks, emitted only for postscript
*/
virtual PlotFormat GetPlotterType() const = 0;
virtual bool StartPlot() = 0;
virtual bool EndPlot() = 0;
virtual void SetNegative( bool _negative )
{
negativeMode = _negative;
}
virtual void SetColorMode( bool _color_mode )
{
colorMode = _color_mode;
}
bool GetColorMode() const
{
return colorMode;
}
virtual void SetPageSettings( const PAGE_INFO& aPageSettings );
/**
* Set the line width for the next drawing.
* @param width is specified in IUs
*/
virtual void SetCurrentLineWidth( int width ) = 0;
/**
* Set the default line width. Used at the beginning and when a width
* of -1 (USE_DEFAULT_LINE_WIDTH) is requested.
* @param width is specified in IUs
*/
virtual void SetDefaultLineWidth( int width ) = 0;
virtual int GetCurrentLineWidth() const
{
return currentPenWidth;
}
virtual void SetColor( EDA_COLOR_T color ) = 0;
virtual void SetDash( bool dashed ) = 0;
virtual void SetCreator( const wxString& aCreator )
{
creator = aCreator;
}
/**
* Function AddLineToHeader
* Add a line to the list of free lines to print at the beginning of the file
* @param aExtraString is the string to print
*/
void AddLineToHeader( const wxString& aExtraString )
{
m_headerExtraLines.Add( aExtraString );
}
/**
* Function ClearHeaderLinesList
* remove all lines from the list of free lines to print at the beginning of the file
*/
void ClearHeaderLinesList()
{
m_headerExtraLines.Clear();
}
/**
* Set the plot offset and scaling for the current plot
* @param aOffset is the plot offset
* @param aIusPerDecimil gives the scaling factor from IUs to device units
* @param aScale is the user set plot scaling factor (either explicitly
* or using 'fit to A4')
* @param aMirror flips the plot in the Y direction (useful for toner
* transfers or some kind of film)
*/
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror ) = 0;
/**
* Open or create the plot file aFullFilename
* @param aFullFilename = the full file name of the file to create
* @return true if success, false if the file cannot be created/opened
*
* Virtual because some plotters use ascii files, some others binary files (PDF)
* The base class open the file in text mode
*/
virtual bool OpenFile( const wxString& aFullFilename );
/**
* The IUs per decimil are an essential scaling factor when
* plotting; they are set and saved when establishing the viewport.
* Here they can be get back again
*/
double GetIUsPerDecimil() const { return m_IUsPerDecimil; }
// Low level primitives
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) = 0;
virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH ) = 0;
/**
* Generic fallback: arc rendered as a polyline
*/
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH );
/**
* moveto/lineto primitive, moves the 'pen' to the specified direction
* @param pos is the target position
* @param plume specifies the kind of motion: 'U' only moves the pen,
* 'D' draw a line from the current position and 'Z' finish
* the drawing and returns the 'pen' to rest (flushes the trace)
*/
virtual void PenTo( const wxPoint& pos, char plume ) = 0;
// Convenience functions for PenTo
void MoveTo( const wxPoint& pos )
{
PenTo( pos, 'U' );
}
void LineTo( const wxPoint& pos )
{
PenTo( pos, 'D' );
}
void FinishTo( const wxPoint& pos )
{
PenTo( pos, 'D' );
PenTo( pos, 'Z' );
}
void PenFinish()
{
// The point is not important with Z motion
PenTo( wxPoint( 0, 0 ), 'Z' );
}
/**
* Function PlotPoly
* @brief Draw a polygon ( filled or not )
* @param aCornerList = corners list
* @param aFill = type of fill
* @param aWidth = line width
*/
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList, FILL_T aFill,
int aWidth = USE_DEFAULT_LINE_WIDTH ) = 0;
/**
* Function PlotImage
* Only Postscript plotters can plot bitmaps
* for plotters that cannot plot a bitmap, a rectangle is plotted
* @brief Draw an image bitmap
* @param aImage = the bitmap
* @param aPos = position of the center of the bitmap
* @param aScaleFactor = the scale factor to apply to the bitmap size
* (this is not the plot scale factor)
*/
virtual void PlotImage( const wxImage & aImage, const wxPoint& aPos,
double aScaleFactor );
// Higher level primitives -- can be drawn as line, sketch or 'filled'
virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width,
EDA_DRAW_MODE_T tracemode );
virtual void ThickArc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, int width, EDA_DRAW_MODE_T tracemode );
virtual void ThickRect( const wxPoint& p1, const wxPoint& p2, int width,
EDA_DRAW_MODE_T tracemode );
virtual void ThickCircle( const wxPoint& pos, int diametre, int width,
EDA_DRAW_MODE_T tracemode );
// Flash primitives
virtual void FlashPadCircle( const wxPoint& aPadPos, int aDiameter,
EDA_DRAW_MODE_T aTraceMode ) = 0;
virtual void FlashPadOval( const wxPoint& aPadPos, const wxSize& aSize, double aPadOrient,
EDA_DRAW_MODE_T aTraceMode ) = 0;
virtual void FlashPadRect( const wxPoint& aPadPos, const wxSize& aSize,
double aPadOrient, EDA_DRAW_MODE_T aTraceMode ) = 0;
/** virtual function FlashPadTrapez
* flash a trapezoidal pad
* @param aPadPos = the position of the shape
* @param aCorners = the list of 4 corners positions,
* relative to the shape position, pad orientation 0
* @param aPadOrient = the rotation of the shape
* @param aTrace_Mode = FILLED or SKETCH
*/
virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
double aPadOrient, EDA_DRAW_MODE_T aTraceMode ) = 0;
/**
* Draws text with the plotter. For convenience it accept the color to use
*/
virtual void Text( const wxPoint& aPos,
enum EDA_COLOR_T aColor,
const wxString& aText,
double aOrient,
const wxSize& aSize,
enum EDA_TEXT_HJUSTIFY_T aH_justify,
enum EDA_TEXT_VJUSTIFY_T aV_justify,
int aWidth,
bool aItalic,
bool aBold,
bool aMultilineAllowed = false );
/**
* Draw a marker (used for the drill map)
*/
static const unsigned MARKER_COUNT = 58;
/**
* Draw a pattern shape number aShapeId, to coord x0, y0.
* x0, y0 = coordinates tables
* Diameter diameter = (coord table) hole
* AShapeId = index (used to generate forms characters)
*/
void Marker( const wxPoint& position, int diametre, unsigned aShapeId );
/**
* Function SetLayerPolarity
* sets current Gerber layer polarity to positive or negative
* by writing \%LPD*\% or \%LPC*\% to the Gerber file, respectively.
* (obviously starts a new Gerber layer, too)
* @param aPositive is the layer polarity and true for positive.
* It's not useful with most other plotter since they can't 'scratch'
* the film like photoplotter imagers do
*/
virtual void SetLayerPolarity( bool aPositive )
{
// NOP for most plotters
}
/**
* Change the current text mode. See the PlotTextMode
* explanation at the beginning of the file
*/
virtual void SetTextMode( PlotTextMode mode )
{
// NOP for most plotters.
}
virtual void SetGerberCoordinatesFormat( int aResolution, bool aUseInches = false )
{
// NOP for most plotters. Only for Gerber plotter
}
protected:
// These are marker subcomponents
/**
* Plot a circle centered on the position. Building block for markers
*/
void markerCircle( const wxPoint& pos, int radius );
/**
* Plot a - bar centered on the position. Building block for markers
*/
void markerHBar( const wxPoint& pos, int radius );
/**
* Plot a / bar centered on the position. Building block for markers
*/
void markerSlash( const wxPoint& pos, int radius );
/**
* Plot a \ bar centered on the position. Building block for markers
*/
void markerBackSlash( const wxPoint& pos, int radius );
/**
* Plot a | bar centered on the position. Building block for markers
*/
void markerVBar( const wxPoint& pos, int radius );
/**
* Plot a square centered on the position. Building block for markers
*/
void markerSquare( const wxPoint& position, int radius );
/**
* Plot a lozenge centered on the position. Building block for markers
*/
void markerLozenge( const wxPoint& position, int radius );
// Helper function for sketched filler segment
/**
* Cdonvert a thick segment and plot it as an oval
*/
void segmentAsOval( const wxPoint& start, const wxPoint& end, int width,
EDA_DRAW_MODE_T tracemode );
void sketchOval( const wxPoint& pos, const wxSize& size, double orient, int width );
// Coordinate and scaling conversion functions
/**
* Modifies coordinates according to the orientation,
* scale factor, and offsets trace. Also convert from a wxPoint to DPOINT,
* since some output engines needs floating point coordinates.
*/
virtual DPOINT userToDeviceCoordinates( const wxPoint& aCoordinate );
/**
* Modifies size according to the plotter scale factors
* (wxSize version, returns a DPOINT)
*/
virtual DPOINT userToDeviceSize( const wxSize& size );
/**
* Modifies size according to the plotter scale factors
* (simple double version)
*/
virtual double userToDeviceSize( double size ) const;
double GetDashMarkLenIU() const;
double GetDashGapLenIU() const;
protected: // variables used in most of plotters:
/// Plot scale - chosen by the user (even implicitly with 'fit in a4')
double plotScale;
/* Caller scale (how many IUs in a decimil - always); it's a double
* because in eeschema there are 0.1 IUs in a decimil (eeschema
* always works in mils internally) while pcbnew can work in decimil
* or nanometers, so this value would be >= 1 */
double m_IUsPerDecimil;
/// Device scale (from IUs to plotter device units - usually decimils)
double iuPerDeviceUnit;
/// Plot offset (in IUs)
wxPoint plotOffset;
/// X axis orientation (SVG)
/// and plot mirrored (only for PS, PDF HPGL and SVG)
bool m_plotMirror;
bool m_mirrorIsHorizontal; /// true to mirror horizontally (else vertically)
bool m_yaxisReversed; /// true if the Y axis is top to bottom (SVG)
/// Output file
FILE* outputFile;
// Pen handling
bool colorMode; /// true to plot in color, false to plot in black and white
bool negativeMode; /// true to generate a negative image (PS mode mainly)
int defaultPenWidth;
int currentPenWidth;
/// Current pen state: 'U', 'D' or 'Z' (see PenTo)
char penState;
/// Last pen positions; set to -1,-1 when the pen is at rest
wxPoint penLastpos;
wxString creator;
wxString filename;
PAGE_INFO pageInfo;
/// Paper size in IU - not in mils
wxSize paperSize;
wxArrayString m_headerExtraLines; /// a set of string to print in header file
};
class HPGL_PLOTTER : public PLOTTER
{
public:
HPGL_PLOTTER();
virtual PlotFormat GetPlotterType() const
{
return PLOT_FORMAT_HPGL;
}
static wxString GetDefaultFileExtension()
{
return wxString( wxT( "plt" ) );
}
virtual bool StartPlot();
virtual bool EndPlot();
/// HPGL doesn't handle line thickness or color
virtual void SetCurrentLineWidth( int width )
{
// This is the truth
currentPenWidth = userToDeviceSize( penDiameter );
}
virtual void SetDefaultLineWidth( int width ) {};
virtual void SetDash( bool dashed );
virtual void SetColor( EDA_COLOR_T color ) {};
virtual void SetPenSpeed( int speed )
{
penSpeed = speed;
}
virtual void SetPenNumber( int number )
{
penNumber = number;
}
virtual void SetPenDiameter( double diameter )
{
penDiameter = diameter;
}
virtual void SetPenOverlap( double overlap )
{
penOverlap = overlap;
}
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror );
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH);
virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width,
EDA_DRAW_MODE_T tracemode );
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH );
virtual void PenTo( const wxPoint& pos, char plume );
virtual void FlashPadCircle( const wxPoint& pos, int diametre,
EDA_DRAW_MODE_T trace_mode );
virtual void FlashPadOval( const wxPoint& pos, const wxSize& size, double orient,
EDA_DRAW_MODE_T trace_mode );
virtual void FlashPadRect( const wxPoint& pos, const wxSize& size,
double orient, EDA_DRAW_MODE_T trace_mode );
virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode );
protected:
void penControl( char plume );
int penSpeed;
int penNumber;
double penDiameter;
double penOverlap;
};
/**
* The PSLIKE_PLOTTER class is an intermediate class to handle common
* routines for engines working more or less with the postscript imaging
* model
*/
class PSLIKE_PLOTTER : public PLOTTER
{
public:
PSLIKE_PLOTTER() : plotScaleAdjX( 1 ), plotScaleAdjY( 1 ),
m_textMode( PLOTTEXTMODE_PHANTOM )
{
}
/**
* PS and PDF fully implement native text (for the Latin-1 subset)
*/
virtual void SetTextMode( PlotTextMode mode )
{
if( mode != PLOTTEXTMODE_DEFAULT )
m_textMode = mode;
}
virtual void SetDefaultLineWidth( int width );
/**
* Set the 'fine' scaling for the postscript engine
*/
void SetScaleAdjust( double scaleX, double scaleY )
{
plotScaleAdjX = scaleX;
plotScaleAdjY = scaleY;
}
// Pad routines are handled with lower level primitives
virtual void FlashPadCircle( const wxPoint& pos, int diametre,
EDA_DRAW_MODE_T trace_mode );
virtual void FlashPadOval( const wxPoint& pos, const wxSize& size, double orient,
EDA_DRAW_MODE_T trace_mode );
virtual void FlashPadRect( const wxPoint& pos, const wxSize& size,
double orient, EDA_DRAW_MODE_T trace_mode );
virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode );
/** The SetColor implementation is split with the subclasses:
* The PSLIKE computes the rgb values, the subclass emits the
* operator to actually do it
*/
virtual void SetColor( EDA_COLOR_T color );
protected:
void computeTextParameters( const wxPoint& aPos,
const wxString& aText,
int aOrient,
const wxSize& aSize,
enum EDA_TEXT_HJUSTIFY_T aH_justify,
enum EDA_TEXT_VJUSTIFY_T aV_justify,
int aWidth,
bool aItalic,
bool aBold,
double *wideningFactor,
double *ctm_a,
double *ctm_b,
double *ctm_c,
double *ctm_d,
double *ctm_e,
double *ctm_f,
double *heightFactor );
void postscriptOverlinePositions( const wxString& aText, int aXSize,
bool aItalic, bool aBold,
std::vector<int> *pos_pairs );
void fputsPostscriptString(FILE *fout, const wxString& txt);
/// Virtual primitive for emitting the setrgbcolor operator
virtual void emitSetRGBColor( double r, double g, double b ) = 0;
/// Height of the postscript font (from the AFM)
static const double postscriptTextAscent; // = 0.718;
int returnPostscriptTextWidth( const wxString& aText, int aXSize,
bool aItalic, bool aBold );
/// Fine user scale adjust ( = 1.0 if no correction)
double plotScaleAdjX, plotScaleAdjY;
/// How to draw text
PlotTextMode m_textMode;
};
class PS_PLOTTER : public PSLIKE_PLOTTER
{
public:
PS_PLOTTER()
{
// The phantom plot in postscript is an hack and reportedly
// crashes Adobe's own postscript interpreter!
m_textMode = PLOTTEXTMODE_STROKE;
}
static wxString GetDefaultFileExtension()
{
return wxString( wxT( "ps" ) );
}
virtual PlotFormat GetPlotterType() const
{
return PLOT_FORMAT_POST;
}
virtual bool StartPlot();
virtual bool EndPlot();
virtual void SetCurrentLineWidth( int width );
virtual void SetDash( bool dashed );
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror );
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH );
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH );
virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos,
double aScaleFactor );
virtual void PenTo( const wxPoint& pos, char plume );
virtual void Text( const wxPoint& aPos,
enum EDA_COLOR_T aColor,
const wxString& aText,
double aOrient,
const wxSize& aSize,
enum EDA_TEXT_HJUSTIFY_T aH_justify,
enum EDA_TEXT_VJUSTIFY_T aV_justify,
int aWidth,
bool aItalic,
bool aBold,
bool aMultilineAllowed = false );
protected:
virtual void emitSetRGBColor( double r, double g, double b );
};
class PDF_PLOTTER : public PSLIKE_PLOTTER
{
public:
PDF_PLOTTER() : pageStreamHandle( 0 ), workFile( NULL )
{
// Avoid non initialized variables:
pageStreamHandle = streamLengthHandle = fontResDictHandle = 0;
pageTreeHandle = 0;
}
virtual PlotFormat GetPlotterType() const
{
return PLOT_FORMAT_PDF;
}
static wxString GetDefaultFileExtension()
{
return wxString( wxT( "pdf" ) );
}
/**
* Open or create the plot file aFullFilename
* @param aFullFilename = the full file name of the file to create
* @return true if success, false if the file cannot be created/opened
*
* The base class open the file in text mode, so we should have this
* function overlaid for PDF files, which are binary files
*/
virtual bool OpenFile( const wxString& aFullFilename );
virtual bool StartPlot();
virtual bool EndPlot();
virtual void StartPage();
virtual void ClosePage();
virtual void SetCurrentLineWidth( int width );
virtual void SetDash( bool dashed );
/** PDF can have multiple pages, so SetPageSettings can be called
* with the outputFile open (but not inside a page stream!) */
virtual void SetPageSettings( const PAGE_INFO& aPageSettings );
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror );
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH );
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH);
virtual void PenTo( const wxPoint& pos, char plume );
virtual void Text( const wxPoint& aPos,
enum EDA_COLOR_T aColor,
const wxString& aText,
double aOrient,
const wxSize& aSize,
enum EDA_TEXT_HJUSTIFY_T aH_justify,
enum EDA_TEXT_VJUSTIFY_T aV_justify,
int aWidth,
bool aItalic,
bool aBold,
bool aMultilineAllowed = false );
virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos,
double aScaleFactor );
protected:
virtual void emitSetRGBColor( double r, double g, double b );
int allocPdfObject();
int startPdfObject(int handle = -1);
void closePdfObject();
int startPdfStream(int handle = -1);
void closePdfStream();
int pageTreeHandle; /// Handle to the root of the page tree object
int fontResDictHandle; /// Font resource dictionary
std::vector<int> pageHandles;/// Handles to the page objects
int pageStreamHandle; /// Handle of the page content object
int streamLengthHandle; /// Handle to the deferred stream length
wxString workFilename;
FILE* workFile; /// Temporary file to costruct the stream before zipping
std::vector<long> xrefTable; /// The PDF xref offset table
};
class SVG_PLOTTER : public PSLIKE_PLOTTER
{
public:
SVG_PLOTTER();
static wxString GetDefaultFileExtension()
{
return wxString( wxT( "svg" ) );
}
virtual PlotFormat GetPlotterType() const
{
return PLOT_FORMAT_SVG;
}
virtual void SetColor( EDA_COLOR_T color );
virtual bool StartPlot();
virtual bool EndPlot();
virtual void SetCurrentLineWidth( int width );
virtual void SetDash( bool dashed );
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror );
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH );
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH );
virtual void PlotImage( const wxImage& aImage, const wxPoint& aPos,
double aScaleFactor );
virtual void PenTo( const wxPoint& pos, char plume );
virtual void Text( const wxPoint& aPos,
enum EDA_COLOR_T aColor,
const wxString& aText,
double aOrient,
const wxSize& aSize,
enum EDA_TEXT_HJUSTIFY_T aH_justify,
enum EDA_TEXT_VJUSTIFY_T aV_justify,
int aWidth,
bool aItalic,
bool aBold,
bool aMultilineAllowed = false );
protected:
FILL_T m_fillMode; // true if the current contour
// rect, arc, circle, polygon must be filled
long m_pen_rgb_color; // current rgb color value: each color has
// a value 0 ... 255, and the 3 colors are
// grouped in a 3x8 bits value
// (written in hex to svg files)
long m_brush_rgb_color; // same as m_pen_rgb_color, used to fill
// some contours.
bool m_graphics_changed; // true if a pen/brush parameter is modified
// color, pen size, fil mode ...
// the new SVG stype must be output on file
bool m_dashed; // true to use plot dashed line style
/**
* function emitSetRGBColor()
* initialize m_pen_rgb_color from reduced values r, g ,b
* ( reduced values are 0.0 to 1.0 )
*/
virtual void emitSetRGBColor( double r, double g, double b );
/**
* function setSVGPlotStyle()
* output the string which define pen and brush color, shape, transparence
*/
void setSVGPlotStyle();
/**
* function setFillMode()
* prepare parameters for setSVGPlotStyle()
*/
void setFillMode( FILL_T fill );
};
/* Class to handle a D_CODE when plotting a board : */
#define FIRST_DCODE_VALUE 10 // D_CODE < 10 is a command, D_CODE >= 10 is a tool
struct APERTURE
{
enum APERTURE_TYPE {
Circle = 1,
Rect = 2,
Plotting = 3,
Oval = 4
};
wxSize Size; // horiz and Vert size
APERTURE_TYPE Type; // Type ( Line, rect , circulaire , ovale .. )
int DCode; // code number ( >= 10 );
/* Trivia question: WHY Gerber decided to use D instead of the usual T for
* tool change? */
};
class GERBER_PLOTTER : public PLOTTER
{
public:
GERBER_PLOTTER();
virtual PlotFormat GetPlotterType() const
{
return PLOT_FORMAT_GERBER;
}
static wxString GetDefaultFileExtension()
{
return wxString( wxT( "gbr" ) );
}
/**
* Function StartPlot
* Write GERBER header to file
* initialize global variable g_Plot_PlotOutputFile
*/
virtual bool StartPlot();
virtual bool EndPlot();
virtual void SetCurrentLineWidth( int width );
virtual void SetDefaultLineWidth( int width );
// RS274X has no dashing, nor colours
virtual void SetDash( bool dashed ) {};
virtual void SetColor( EDA_COLOR_T color ) {};
// Currently, aScale and aMirror are not used in gerber plotter
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror );
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void Arc( const wxPoint& aCenter, double aStAngle, double aEndAngle,
int aRadius, FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH );
/**
* Gerber polygon: they can (and *should*) be filled with the
* appropriate G36/G37 sequence
*/
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH );
virtual void PenTo( const wxPoint& pos, char plume );
/**
* Filled circular flashes are stored as apertures
*/
virtual void FlashPadCircle( const wxPoint& pos, int diametre,
EDA_DRAW_MODE_T trace_mode );
/**
* Filled oval flashes are handled as aperture in the 90 degree positions only
*/
virtual void FlashPadOval( const wxPoint& pos, const wxSize& size, double orient,
EDA_DRAW_MODE_T trace_mode );
/**
* Filled rect flashes are handled as aperture in the 90 degree positions only
*/
virtual void FlashPadRect( const wxPoint& pos, const wxSize& size,
double orient, EDA_DRAW_MODE_T trace_mode );
/**
* Trapezoidal pad at the moment are *never* handled as aperture, since
* they require aperture macros
*/
virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode );
/**
* Change the plot polarity and begin a new layer
* Used to 'scratch off' silk screen away from solder mask
*/
virtual void SetLayerPolarity( bool aPositive );
/**
* Function SetGerberCoordinatesFormat
* selection of Gerber units and resolution (number of digits in mantissa)
* @param aResolution = number of digits in mantissa of coordinate
* use 5 or 6 for mm and 6 or 7 for inches
* do not use value > 6 (mm) or > 7 (in) to avoid overflow
* @param aUseInches = true to use inches, false to use mm (default)
*
* Should be called only after SetViewport() is called
*/
virtual void SetGerberCoordinatesFormat( int aResolution, bool aUseInches = false );
protected:
void selectAperture( const wxSize& size, APERTURE::APERTURE_TYPE type );
/**
* Emit a D-Code record, using proper conversions
* to format a leading zero omitted gerber coordinate
* (for n decimal positions, see header generation in start_plot
*/
void emitDcode( const DPOINT& pt, int dcode );
std::vector<APERTURE>::iterator
getAperture( const wxSize& size, APERTURE::APERTURE_TYPE type );
FILE* workFile;
FILE* finalFile;
wxString m_workFilename;
/**
* Generate the table of D codes
*/
void writeApertureList();
std::vector<APERTURE> apertures;
std::vector<APERTURE>::iterator currentAperture;
bool m_gerberUnitInch; // true if the gerber units are inches, false for mm
int m_gerberUnitFmt; // number of digits in mantissa.
// usually 6 in Inches and 5 or 6 in mm
};
class DXF_PLOTTER : public PLOTTER
{
public:
DXF_PLOTTER() : textAsLines( false )
{
textAsLines = true;
m_currentColor = BLACK;
}
virtual PlotFormat GetPlotterType() const
{
return PLOT_FORMAT_DXF;
}
static wxString GetDefaultFileExtension()
{
return wxString( wxT( "dxf" ) );
}
/**
* DXF handles NATIVE text emitting TEXT entities
*/
virtual void SetTextMode( PlotTextMode mode )
{
if( mode != PLOTTEXTMODE_DEFAULT )
textAsLines = ( mode != PLOTTEXTMODE_NATIVE );
}
virtual bool StartPlot();
virtual bool EndPlot();
// For now we don't use 'thick' primitives, so no line width
virtual void SetCurrentLineWidth( int width )
{
currentPenWidth = 0;
}
virtual void SetDefaultLineWidth( int width )
{
// DXF lines are infinitesimal
defaultPenWidth = 0;
}
virtual void SetDash( bool dashed );
virtual void SetColor( EDA_COLOR_T color );
virtual void SetViewport( const wxPoint& aOffset, double aIusPerDecimil,
double aScale, bool aMirror );
virtual void Rect( const wxPoint& p1, const wxPoint& p2, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void Circle( const wxPoint& pos, int diametre, FILL_T fill,
int width = USE_DEFAULT_LINE_WIDTH );
virtual void PlotPoly( const std::vector< wxPoint >& aCornerList,
FILL_T aFill, int aWidth = USE_DEFAULT_LINE_WIDTH );
virtual void ThickSegment( const wxPoint& start, const wxPoint& end, int width,
EDA_DRAW_MODE_T tracemode );
virtual void Arc( const wxPoint& centre, double StAngle, double EndAngle,
int rayon, FILL_T fill, int width = USE_DEFAULT_LINE_WIDTH );
virtual void PenTo( const wxPoint& pos, char plume );
virtual void FlashPadCircle( const wxPoint& pos, int diametre,
EDA_DRAW_MODE_T trace_mode );
virtual void FlashPadOval( const wxPoint& pos, const wxSize& size, double orient,
EDA_DRAW_MODE_T trace_mode );
virtual void FlashPadRect( const wxPoint& pos, const wxSize& size,
double orient, EDA_DRAW_MODE_T trace_mode );
virtual void FlashPadTrapez( const wxPoint& aPadPos, const wxPoint *aCorners,
double aPadOrient, EDA_DRAW_MODE_T aTrace_Mode );
virtual void Text( const wxPoint& aPos,
enum EDA_COLOR_T aColor,
const wxString& aText,
double aOrient,
const wxSize& aSize,
enum EDA_TEXT_HJUSTIFY_T aH_justify,
enum EDA_TEXT_VJUSTIFY_T aV_justify,
int aWidth,
bool aItalic,
bool aBold,
bool aMultilineAllowed = false );
protected:
bool textAsLines;
EDA_COLOR_T m_currentColor;
};
class TITLE_BLOCK;
void PlotWorkSheet( PLOTTER* plotter, const TITLE_BLOCK& aTitleBlock,
const PAGE_INFO& aPageInfo,
int aSheetNumber, int aNumberOfSheets,
const wxString &aSheetDesc,
const wxString &aFilename );
/** Returns the default plot extension for a format
*/
wxString GetDefaultPlotExtension( PlotFormat aFormat );
#endif // PLOT_COMMON_H_
|