KiCad PCB EDA Suite
Loading...
Searching...
No Matches
DXF_plotter.cpp
Go to the documentation of this file.
1
5/*
6 * This program source code file is part of KiCad, a free EDA CAD application.
7 *
8 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, you may find one here:
22 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
23 * or you may search the http://www.gnu.org website for the version 2 license,
24 * or you may write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
26 */
27
29#include <macros.h>
30#include <string_utils.h>
32#include <trigo.h>
33#include <fmt/core.h>
34
39static const double DXF_OBLIQUE_ANGLE = 15;
40
41// No support for linewidths in DXF
42#define DXF_LINE_WIDTH DO_NOT_SET_LINE_WIDTH
43
60static const struct
61{
62 const char *name;
63 int color;
65{
66 { "BLACK", 7 }, // In DXF, color 7 is *both* white and black!
67 { "GRAY1", 251 },
68 { "GRAY2", 8 },
69 { "GRAY3", 9 },
70 { "WHITE", 7 },
71 { "LYELLOW", 51 },
72 { "LORANGE", 41 },
73 { "BLUE1", 178 },
74 { "GREEN1", 98 },
75 { "CYAN1", 138 },
76 { "RED1", 18 },
77 { "MAGENTA1", 228 },
78 { "BROWN1", 58 },
79 { "ORANGE1", 34 },
80 { "BLUE2", 5 },
81 { "GREEN2", 3 },
82 { "CYAN2", 4 },
83 { "RED2", 1 },
84 { "MAGENTA2", 6 },
85 { "BROWN2", 54 },
86 { "ORANGE2", 42 },
87 { "BLUE3", 171 },
88 { "GREEN3", 91 },
89 { "CYAN3", 131 },
90 { "RED3", 11 },
91 { "MAGENTA3", 221 },
92 { "YELLOW3", 2 },
93 { "ORANGE3", 32 },
94 { "BLUE4", 5 },
95 { "GREEN4", 3 },
96 { "CYAN4", 4 },
97 { "RED4", 1 },
98 { "MAGENTA4", 6 },
99 { "YELLOW4", 2 },
100 { "ORANGE4", 40 }
102
103
104static const char* getDXFLineType( LINE_STYLE aType )
105{
106 switch( aType )
107 {
110 return "CONTINUOUS";
111 case LINE_STYLE::DASH:
112 return "DASHED";
113 case LINE_STYLE::DOT:
114 return "DOTTED";
116 return "DASHDOT";
118 return "DIVIDE";
119 default:
120 wxFAIL_MSG( "Unhandled LINE_STYLE" );
121 return "CONTINUOUS";
122 }
123}
124
125
126// A helper function to create a color name acceptable in DXF files
127// DXF files do not use a RGB definition
128static wxString getDXFColorName( const COLOR4D& aColor )
129{
130 EDA_COLOR_T color = COLOR4D::FindNearestLegacyColor( int( aColor.r * 255 ),
131 int( aColor.g * 255 ),
132 int( aColor.b * 255 ) );
133 wxString cname( dxf_layer[color].name );
134 return cname;
135}
136
137
139{
140 m_plotUnits = aUnit;
141
142 switch( aUnit )
143 {
144 case DXF_UNITS::MM:
145 m_unitScalingFactor = 0.00254;
147 break;
148
149 case DXF_UNITS::INCH:
150 default:
151 m_unitScalingFactor = 0.0001;
153 }
154}
155
156
157// convert aValue to a string, and remove trailing zeros
158// In DXF files coordinates need a high precision: at least 9 digits when given
159// in inches and 7 digits when in mm.
160// So we use 16 digits and remove trailing 0 (if any)
161static std::string formatCoord( double aValue )
162{
163 std::string buf;
164
165 buf = fmt::format( "{:.16f}", aValue );
166
167 // remove trailing zeros
168 while( !buf.empty() && buf[buf.size() - 1] == '0' )
169 {
170 buf.pop_back();
171 }
172
173 return buf;
174}
175
176
177void DXF_PLOTTER::SetViewport( const VECTOR2I& aOffset, double aIusPerDecimil,
178 double aScale, bool aMirror )
179{
180 m_plotOffset = aOffset;
181 m_plotScale = aScale;
182
183 /* DXF paper is 'virtual' so there is no need of a paper size.
184 Also this way we can handle the aux origin which can be useful
185 (for example when aligning to a mechanical drawing) */
186 m_paperSize.x = 0;
187 m_paperSize.y = 0;
188
189 /* Like paper size DXF units are abstract too. Anyway there is a
190 * system variable (MEASUREMENT) which will be set to 0 to indicate
191 * english units */
192 m_IUsPerDecimil = aIusPerDecimil;
193 m_iuPerDeviceUnit = 1.0 / aIusPerDecimil; // Gives a DXF in decimils
194 m_iuPerDeviceUnit *= GetUnitScaling(); // Get the scaling factor for the current units
195
196 m_plotMirror = false; // No mirroring on DXF
197 m_currentColor = COLOR4D::BLACK;
198}
199
200
201bool DXF_PLOTTER::StartPlot( const wxString& aPageNumber )
202{
203 wxASSERT( m_outputFile );
204
205 // DXF HEADER - Boilerplate
206 // Defines the minimum for drawing i.e. the angle system and the
207 // 4 linetypes (CONTINUOUS, DOTDASH, DASHED and DOTTED)
208 fmt::print( m_outputFile,
209 " 0\n"
210 "SECTION\n"
211 " 2\n"
212 "HEADER\n"
213 " 9\n"
214 "$ANGBASE\n"
215 " 50\n"
216 "0.0\n"
217 " 9\n"
218 "$ANGDIR\n"
219 " 70\n"
220 "1\n"
221 " 9\n"
222 "$MEASUREMENT\n"
223 " 70\n"
224 "{}\n"
225 " 0\n"
226 "ENDSEC\n"
227 " 0\n"
228 "SECTION\n"
229 " 2\n"
230 "TABLES\n"
231 " 0\n"
232 "TABLE\n"
233 " 2\n"
234 "LTYPE\n"
235 " 70\n"
236 "4\n"
237 " 0\n"
238 "LTYPE\n"
239 " 5\n"
240 "40F\n"
241 " 2\n"
242 "CONTINUOUS\n"
243 " 70\n"
244 "0\n"
245 " 3\n"
246 "Solid line\n"
247 " 72\n"
248 "65\n"
249 " 73\n"
250 "0\n"
251 " 40\n"
252 "0.0\n"
253 " 0\n"
254 "LTYPE\n"
255 " 5\n"
256 "410\n"
257 " 2\n"
258 "DASHDOT\n"
259 " 70\n"
260 "0\n"
261 " 3\n"
262 "Dash Dot ____ _ ____ _\n"
263 " 72\n"
264 "65\n"
265 " 73\n"
266 "4\n"
267 " 40\n"
268 "2.0\n"
269 " 49\n"
270 "1.25\n"
271 " 49\n"
272 "-0.25\n"
273 " 49\n"
274 "0.25\n"
275 " 49\n"
276 "-0.25\n"
277 " 0\n"
278 "LTYPE\n"
279 " 5\n"
280 "411\n"
281 " 2\n"
282 "DASHED\n"
283 " 70\n"
284 "0\n"
285 " 3\n"
286 "Dashed __ __ __ __ __\n"
287 " 72\n"
288 "65\n"
289 " 73\n"
290 "2\n"
291 " 40\n"
292 "0.75\n"
293 " 49\n"
294 "0.5\n"
295 " 49\n"
296 "-0.25\n"
297 " 0\n"
298 "LTYPE\n"
299 " 5\n"
300 "43B\n"
301 " 2\n"
302 "DOTTED\n"
303 " 70\n"
304 "0\n"
305 " 3\n"
306 "Dotted . . . .\n"
307 " 72\n"
308 "65\n"
309 " 73\n"
310 "2\n"
311 " 40\n"
312 "0.2\n"
313 " 49\n"
314 "0.0\n"
315 " 49\n"
316 "-0.2\n"
317 " 0\n"
318 "ENDTAB\n",
320
321 // Text styles table
322 // Defines 4 text styles, one for each bold/italic combination
323 fmt::print( m_outputFile,
324 " 0\n"
325 "TABLE\n"
326 " 2\n"
327 "STYLE\n"
328 " 70\n"
329 "4\n" );
330
331 static const char *style_name[4] = {"KICAD", "KICADB", "KICADI", "KICADBI"};
332
333 for(int i = 0; i < 4; i++ )
334 {
335 fmt::print( m_outputFile,
336 " 0\n"
337 "STYLE\n"
338 " 2\n"
339 "{}\n" // Style name
340 " 70\n"
341 "0\n" // Standard flags
342 " 40\n"
343 "0\n" // Non-fixed height text
344 " 41\n"
345 "1\n" // Width factor (base)
346 " 42\n"
347 "1\n" // Last height (mandatory)
348 " 50\n"
349 "{:g}\n" // Oblique angle
350 " 71\n"
351 "0\n" // Generation flags (default)
352 " 3\n"
353 // The standard ISO font (when kicad is build with it
354 // the dxf text in acad matches *perfectly*)
355 "isocp.shx\n", // Font name (when not bigfont)
356 // Apply a 15 degree angle to italic text
357 style_name[i], i < 2 ? 0 : DXF_OBLIQUE_ANGLE );
358 }
359
360 EDA_COLOR_T numLayers = NBCOLORS;
361
362 // If printing in monochrome, only output the black layer
363 if( !GetColorMode() )
364 numLayers = static_cast<EDA_COLOR_T>( 1 );
365
366 // Layer table - one layer per color
367 fmt::print( m_outputFile,
368 " 0\n"
369 "ENDTAB\n"
370 " 0\n"
371 "TABLE\n"
372 " 2\n"
373 "LAYER\n"
374 " 70\n"
375 "{}\n", (int)numLayers );
376
377 /* The layer/colors palette. The acad/DXF palette is divided in 3 zones:
378
379 - The primary colors (1 - 9)
380 - An HSV zone (10-250, 5 values x 2 saturations x 10 hues
381 - Greys (251 - 255)
382 */
383
384 wxASSERT( numLayers <= NBCOLORS );
385
386 for( EDA_COLOR_T i = BLACK; i < numLayers; i = static_cast<EDA_COLOR_T>( int( i ) + 1 ) )
387 {
388 fmt::print( m_outputFile,
389 " 0\n"
390 "LAYER\n"
391 " 2\n"
392 "{}\n" // Layer name
393 " 70\n"
394 "0\n" // Standard flags
395 " 62\n"
396 "{}\n" // Color number
397 " 6\n"
398 "CONTINUOUS\n",// Linetype name
399 dxf_layer[i].name, dxf_layer[i].color );
400 }
401
402 // End of layer table, begin entities
403 fmt::print( m_outputFile,
404 " 0\n"
405 "ENDTAB\n"
406 " 0\n"
407 "ENDSEC\n"
408 " 0\n"
409 "SECTION\n"
410 " 2\n"
411 "ENTITIES\n" );
412
413 return true;
414}
415
416
418{
419 wxASSERT( m_outputFile );
420
421 // DXF FOOTER
422 fmt::print( m_outputFile,
423 " 0\n"
424 "ENDSEC\n"
425 " 0\n"
426 "EOF\n" );
427 fclose( m_outputFile );
428 m_outputFile = nullptr;
429
430 return true;
431}
432
433
435{
436 if( ( m_colorMode )
437 || ( color == COLOR4D::BLACK )
438 || ( color == COLOR4D::WHITE ) )
439 {
441 }
442 else
443 {
444 m_currentColor = COLOR4D::BLACK;
445 }
446}
447
448
449void DXF_PLOTTER::Rect( const VECTOR2I& p1, const VECTOR2I& p2, FILL_T fill, int width )
450{
451 wxASSERT( m_outputFile );
452
453 if( p1 != p2 )
454 {
455 MoveTo( p1 );
456 LineTo( VECTOR2I( p1.x, p2.y ) );
457 LineTo( VECTOR2I( p2.x, p2.y ) );
458 LineTo( VECTOR2I( p2.x, p1.y ) );
459 FinishTo( VECTOR2I( p1.x, p1.y ) );
460 }
461 else
462 {
463 // Draw as a point
464 wxString cname = getDXFColorName( m_currentColor );
465 VECTOR2D point_dev = userToDeviceCoordinates( p1 );
466
467 fmt::print( m_outputFile, "0\nPOINT\n8\n{}\n10\n{}\n20\n{}\n",
468 TO_UTF8( cname ),
469 formatCoord( point_dev.x ),
470 formatCoord( point_dev.y ) );
471 }
472}
473
474
475void DXF_PLOTTER::Circle( const VECTOR2I& centre, int diameter, FILL_T fill, int width )
476{
477 wxASSERT( m_outputFile );
478 double radius = userToDeviceSize( diameter / 2 );
479 VECTOR2D centre_dev = userToDeviceCoordinates( centre );
480
481 wxString cname = getDXFColorName( m_currentColor );
482
483 if( radius > 0 )
484 {
485 if( fill == FILL_T::NO_FILL )
486 {
487 fmt::print( m_outputFile, "0\nCIRCLE\n8\n{}\n10\n{}\n20\n{}\n40\n{}\n",
488 TO_UTF8( cname ),
489 formatCoord( centre_dev.x ),
490 formatCoord( centre_dev.y ),
491 formatCoord( radius ) );
492 }
493 else if( fill == FILL_T::FILLED_SHAPE )
494 {
495 double r = radius * 0.5;
496 fmt::print( m_outputFile, "0\nPOLYLINE\n" );
497 fmt::print( m_outputFile, "8\n{}\n66\n1\n70\n1\n", TO_UTF8( cname ) );
498 fmt::print( m_outputFile, "40\n{}\n41\n{}\n",
500 formatCoord( radius ) );
501 fmt::print( m_outputFile, "0\nVERTEX\n8\n{}\n", TO_UTF8( cname ) );
502 fmt::print( m_outputFile, "10\n{}\n 20\n{}\n42\n1.0\n",
503 formatCoord( centre_dev.x-r ),
504 formatCoord( centre_dev.y ) );
505 fmt::print( m_outputFile, "0\nVERTEX\n8\n{}\n", TO_UTF8( cname ) );
506 fmt::print( m_outputFile, "10\n{}\n 20\n{}\n42\n1.0\n",
507 formatCoord( centre_dev.x+r ),
508 formatCoord( centre_dev.y ) );
509 fmt::print( m_outputFile, "0\nSEQEND\n" );
510 }
511 }
512 else
513 {
514 // Draw as a point
515 fmt::print( m_outputFile, "0\nPOINT\n8\n{}\n10\n{}\n20\n{}\n",
516 TO_UTF8( cname ),
517 formatCoord( centre_dev.x ),
518 formatCoord( centre_dev.y ) );
519 }
520}
521
522
523void DXF_PLOTTER::PlotPoly( const std::vector<VECTOR2I>& aCornerList, FILL_T aFill, int aWidth,
524 void* aData )
525{
526 if( aCornerList.size() <= 1 )
527 return;
528
529 unsigned last = aCornerList.size() - 1;
530
531 // Plot outlines with lines (thickness = 0) to define the polygon
532 if( aWidth <= 0 || aFill == FILL_T::NO_FILL )
533 {
534 MoveTo( aCornerList[0] );
535
536 for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
537 LineTo( aCornerList[ii] );
538
539 // Close polygon if 'fill' requested
540 if( aFill != FILL_T::NO_FILL )
541 {
542 if( aCornerList[last] != aCornerList[0] )
543 LineTo( aCornerList[0] );
544 }
545
546 PenFinish();
547 return;
548 }
549
550 // The polygon outline has thickness, and is filled
551 // Build and plot the polygon which contains the initial
552 // polygon and its thick outline
553 SHAPE_POLY_SET bufferOutline;
554 SHAPE_POLY_SET bufferPolybase;
555
556 bufferPolybase.NewOutline();
557
558 // enter outline as polygon:
559 for( unsigned ii = 1; ii < aCornerList.size(); ii++ )
560 {
561 TransformOvalToPolygon( bufferOutline, aCornerList[ ii - 1 ], aCornerList[ ii ],
563 }
564
565 // enter the initial polygon:
566 for( const VECTOR2I& corner : aCornerList )
567 bufferPolybase.Append( corner );
568
569 // Merge polygons to build the polygon which contains the initial
570 // polygon and its thick outline
571
572 // create the outline which contains thick outline:
573 bufferPolybase.BooleanAdd( bufferOutline );
574 bufferPolybase.Fracture();
575
576 if( bufferPolybase.OutlineCount() < 1 ) // should not happen
577 return;
578
579 const SHAPE_LINE_CHAIN& path = bufferPolybase.COutline( 0 );
580
581 if( path.PointCount() < 2 ) // should not happen
582 return;
583
584 // Now, output the final polygon to DXF file:
585 last = path.PointCount() - 1;
586 VECTOR2I point = path.CPoint( 0 );
587
588 VECTOR2I startPoint( point.x, point.y );
589 MoveTo( startPoint );
590
591 for( int ii = 1; ii < path.PointCount(); ii++ )
592 {
593 point = path.CPoint( ii );
594 LineTo( VECTOR2I( point.x, point.y ) );
595 }
596
597 // Close polygon, if needed
598 point = path.CPoint( last );
599 VECTOR2I endPoint( point.x, point.y );
600
601 if( endPoint != startPoint )
602 LineTo( startPoint );
603
604 PenFinish();
605}
606
607
608void DXF_PLOTTER::PenTo( const VECTOR2I& pos, char plume )
609{
610 wxASSERT( m_outputFile );
611
612 if( plume == 'Z' )
613 {
614 return;
615 }
616
617 VECTOR2D pos_dev = userToDeviceCoordinates( pos );
618 VECTOR2D pen_lastpos_dev = userToDeviceCoordinates( m_penLastpos );
619
620 if( m_penLastpos != pos && plume == 'D' )
621 {
622 wxASSERT( m_currentLineType >= LINE_STYLE::FIRST_TYPE
623 && m_currentLineType <= LINE_STYLE::LAST_TYPE );
624
625 // DXF LINE
626 wxString cname = getDXFColorName( m_currentColor );
627 const char* lname = getDXFLineType( static_cast<LINE_STYLE>( m_currentLineType ) );
628 fmt::print( m_outputFile, "0\nLINE\n8\n{}\n6\n{}\n10\n{}\n20\n{}\n11\n{}\n21\n{}\n",
629 TO_UTF8( cname ),
630 lname,
631 formatCoord( pen_lastpos_dev.x ),
632 formatCoord( pen_lastpos_dev.y ),
633 formatCoord( pos_dev.x ),
634 formatCoord( pos_dev.y ) );
635 }
636
637 m_penLastpos = pos;
638}
639
640
641void DXF_PLOTTER::SetDash( int aLineWidth, LINE_STYLE aLineStyle )
642{
643 wxASSERT( aLineStyle >= LINE_STYLE::FIRST_TYPE
644 && aLineStyle <= LINE_STYLE::LAST_TYPE );
645
646 m_currentLineType = aLineStyle;
647}
648
649
650void DXF_PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
651 const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth )
652{
653 wxASSERT( m_outputFile );
654
655 if( aRadius <= 0 )
656 return;
657
658 EDA_ANGLE startAngle = -aStartAngle;
659 EDA_ANGLE endAngle = startAngle - aAngle;
660
661 // In DXF, arcs are drawn CCW.
662 // If startAngle > endAngle, it is CW. So transform it to CCW
663 if( endAngle < startAngle )
664 std::swap( startAngle, endAngle );
665
666 VECTOR2D centre_device = userToDeviceCoordinates( aCenter );
667 double radius_device = userToDeviceSize( aRadius );
668
669 // Emit a DXF ARC entity
670 wxString cname = getDXFColorName( m_currentColor );
671 fmt::print( m_outputFile,
672 "0\nARC\n8\n{}\n10\n{}\n20\n{}\n40\n{}\n50\n{:.8f}\n51\n{:.8f}\n",
673 TO_UTF8( cname ),
674 formatCoord( centre_device.x ),
675 formatCoord( centre_device.y ),
676 formatCoord( radius_device ),
677 startAngle.AsDegrees(),
678 endAngle.AsDegrees() );
679}
680
681
682void DXF_PLOTTER::ThickSegment( const VECTOR2I& aStart, const VECTOR2I& aEnd, int aWidth, void* aData )
683{
684 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
685
686 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
687 {
688 std::vector<VECTOR2I> cornerList;
689 SHAPE_POLY_SET outlineBuffer;
690 TransformOvalToPolygon( outlineBuffer, aStart, aEnd, aWidth, GetPlotterArcHighDef(),
691 ERROR_INSIDE );
692 const SHAPE_LINE_CHAIN& path = outlineBuffer.COutline( 0 );
693
694 cornerList.reserve( path.PointCount() );
695
696 for( int jj = 0; jj < path.PointCount(); jj++ )
697 cornerList.emplace_back( path.CPoint( jj ).x, path.CPoint( jj ).y );
698
699 // Ensure the polygon is closed
700 if( cornerList[0] != cornerList[cornerList.size() - 1] )
701 cornerList.push_back( cornerList[0] );
702
703 PlotPoly( cornerList, FILL_T::NO_FILL, DXF_LINE_WIDTH );
704 }
705 else
706 {
707 MoveTo( aStart );
708 FinishTo( aEnd );
709 }
710}
711
712
713void DXF_PLOTTER::ThickArc( const VECTOR2D& centre, const EDA_ANGLE& aStartAngle,
714 const EDA_ANGLE& aAngle, double aRadius, int aWidth, void* aData )
715{
716 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
717
718 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
719 {
720 Arc( centre, aStartAngle, aAngle, aRadius - aWidth/2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
721 Arc( centre, aStartAngle, aAngle, aRadius + aWidth/2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
722 }
723 else
724 {
725 Arc( centre, aStartAngle, aAngle, aRadius, FILL_T::NO_FILL, DXF_LINE_WIDTH );
726 }
727}
728
729
730void DXF_PLOTTER::ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width, void* aData )
731{
732 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
733
734 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
735 {
736 VECTOR2I offsetp1( p1.x - width/2, p1.y - width/2 );
737 VECTOR2I offsetp2( p2.x + width/2, p2.y + width/2 );
738 Rect( offsetp1, offsetp2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
739
740 offsetp1.x += width;
741 offsetp1.y += width;
742 offsetp2.x -= width;
743 offsetp2.y -= width;
744 Rect( offsetp1, offsetp2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
745 }
746 else
747 {
748 Rect( p1, p2, FILL_T::NO_FILL, DXF_LINE_WIDTH );
749 }
750}
751
752
753void DXF_PLOTTER::ThickCircle( const VECTOR2I& pos, int diametre, int width, void* aData )
754{
755 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
756
757 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
758 {
759 Circle( pos, diametre - width, FILL_T::NO_FILL, DXF_LINE_WIDTH );
760 Circle( pos, diametre + width, FILL_T::NO_FILL, DXF_LINE_WIDTH );
761 }
762 else
763 {
764 Circle( pos, diametre, FILL_T::NO_FILL, DXF_LINE_WIDTH );
765 }
766}
767
768
769void DXF_PLOTTER::FilledCircle( const VECTOR2I& pos, int diametre, void* aData )
770{
771 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
772
773 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
774 Circle( pos, diametre, FILL_T::NO_FILL, DXF_LINE_WIDTH );
775 else
776 Circle( pos, diametre, FILL_T::FILLED_SHAPE, 0 );
777}
778
779
780void DXF_PLOTTER::ThickPoly( const SHAPE_POLY_SET& aPoly, int aWidth, void* aData )
781{
782 const PLOT_PARAMS* cfg = static_cast<const PLOT_PARAMS*>( aData );
783
784 if( cfg && cfg->GetDXFPlotMode() == SKETCH )
785 {
786 SHAPE_POLY_SET outline = aPoly.CloneDropTriangulation();
787 outline.Inflate( aWidth / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS, GetPlotterArcHighDef() );
788 PLOTTER::PlotPoly( outline.COutline( 0 ), FILL_T::NO_FILL, DXF_LINE_WIDTH, aData );
789
790 outline = aPoly.CloneDropTriangulation();
791 outline.Deflate( aWidth / 2, CORNER_STRATEGY::ROUND_ALL_CORNERS, GetPlotterArcHighDef() );
792 PLOTTER::PlotPoly( outline.COutline( 0 ), FILL_T::NO_FILL, DXF_LINE_WIDTH, aData );
793 }
794 else
795 {
796 PLOTTER::PlotPoly( aPoly.COutline( 0 ), FILL_T::NO_FILL, aWidth, aData );
797 }
798}
799
800
801void DXF_PLOTTER::FlashPadOval( const VECTOR2I& aPos, const VECTOR2I& aSize,
802 const EDA_ANGLE& aOrient, void* aData )
803{
804 wxASSERT( m_outputFile );
805
806 VECTOR2I size( aSize );
807 EDA_ANGLE orient( aOrient );
808
809 /* The chip is reduced to an oval tablet with size.y > size.x
810 * (Oval vertical orientation 0) */
811 if( size.x > size.y )
812 {
813 std::swap( size.x, size.y );
814 orient += ANGLE_90;
815 }
816
817 ThickOval( aPos, size, orient, DXF_LINE_WIDTH, aData );
818}
819
820
821void DXF_PLOTTER::FlashPadCircle( const VECTOR2I& pos, int diametre, void* aData )
822{
823 wxASSERT( m_outputFile );
824 Circle( pos, diametre, FILL_T::NO_FILL, DXF_LINE_WIDTH );
825}
826
827
828void DXF_PLOTTER::FlashPadRect( const VECTOR2I& aPos, const VECTOR2I& aPadSize,
829 const EDA_ANGLE& aOrient, void* aData )
830{
831 wxASSERT( m_outputFile );
832
833 VECTOR2I size, start, end;
834
835 size.x = aPadSize.x / 2;
836 size.y = aPadSize.y / 2;
837
838 if( size.x < 0 )
839 size.x = 0;
840
841 if( size.y < 0 )
842 size.y = 0;
843
844 // If a dimension is zero, the trace is reduced to 1 line
845 if( size.x == 0 )
846 {
847 start = VECTOR2I( aPos.x, aPos.y - size.y );
848 end = VECTOR2I( aPos.x, aPos.y + size.y );
849 RotatePoint( start, aPos, aOrient );
850 RotatePoint( end, aPos, aOrient );
851 MoveTo( start );
852 FinishTo( end );
853 return;
854 }
855
856 if( size.y == 0 )
857 {
858 start = VECTOR2I( aPos.x - size.x, aPos.y );
859 end = VECTOR2I( aPos.x + size.x, aPos.y );
860 RotatePoint( start, aPos, aOrient );
861 RotatePoint( end, aPos, aOrient );
862 MoveTo( start );
863 FinishTo( end );
864 return;
865 }
866
867 start = VECTOR2I( aPos.x - size.x, aPos.y - size.y );
868 RotatePoint( start, aPos, aOrient );
869 MoveTo( start );
870
871 end = VECTOR2I( aPos.x - size.x, aPos.y + size.y );
872 RotatePoint( end, aPos, aOrient );
873 LineTo( end );
874
875 end = VECTOR2I( aPos.x + size.x, aPos.y + size.y );
876 RotatePoint( end, aPos, aOrient );
877 LineTo( end );
878
879 end = VECTOR2I( aPos.x + size.x, aPos.y - size.y );
880 RotatePoint( end, aPos, aOrient );
881 LineTo( end );
882
883 FinishTo( start );
884}
885
886
887void DXF_PLOTTER::FlashPadRoundRect( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
888 int aCornerRadius, const EDA_ANGLE& aOrient, void* aData )
889{
890 SHAPE_POLY_SET outline;
891 TransformRoundChamferedRectToPolygon( outline, aPadPos, aSize, aOrient, aCornerRadius, 0.0, 0,
893
894 // TransformRoundRectToPolygon creates only one convex polygon
895 SHAPE_LINE_CHAIN& poly = outline.Outline( 0 );
896
897 MoveTo( VECTOR2I( poly.CPoint( 0 ).x, poly.CPoint( 0 ).y ) );
898
899 for( int ii = 1; ii < poly.PointCount(); ++ii )
900 LineTo( VECTOR2I( poly.CPoint( ii ).x, poly.CPoint( ii ).y ) );
901
902 FinishTo( VECTOR2I( poly.CPoint( 0 ).x, poly.CPoint( 0 ).y ) );
903}
904
905
906void DXF_PLOTTER::FlashPadCustom( const VECTOR2I& aPadPos, const VECTOR2I& aSize,
907 const EDA_ANGLE& aOrient, SHAPE_POLY_SET* aPolygons,
908 void* aData )
909{
910 for( int cnt = 0; cnt < aPolygons->OutlineCount(); ++cnt )
911 {
912 SHAPE_LINE_CHAIN& poly = aPolygons->Outline( cnt );
913
914 MoveTo( VECTOR2I( poly.CPoint( 0 ).x, poly.CPoint( 0 ).y ) );
915
916 for( int ii = 1; ii < poly.PointCount(); ++ii )
917 LineTo( VECTOR2I( poly.CPoint( ii ).x, poly.CPoint( ii ).y ) );
918
919 FinishTo( VECTOR2I( poly.CPoint( 0 ).x, poly.CPoint( 0 ).y ) );
920 }
921}
922
923
924void DXF_PLOTTER::FlashPadTrapez( const VECTOR2I& aPadPos, const VECTOR2I* aCorners,
925 const EDA_ANGLE& aPadOrient, void* aData )
926{
927 wxASSERT( m_outputFile );
928 VECTOR2I coord[4]; /* coord actual corners of a trapezoidal trace */
929
930 for( int ii = 0; ii < 4; ii++ )
931 {
932 coord[ii] = aCorners[ii];
933 RotatePoint( coord[ii], aPadOrient );
934 coord[ii] += aPadPos;
935 }
936
937 // Plot edge:
938 MoveTo( coord[0] );
939 LineTo( coord[1] );
940 LineTo( coord[2] );
941 LineTo( coord[3] );
942 FinishTo( coord[0] );
943}
944
945
946void DXF_PLOTTER::FlashRegularPolygon( const VECTOR2I& aShapePos, int aRadius, int aCornerCount,
947 const EDA_ANGLE& aOrient, void* aData )
948{
949 // Do nothing
950 wxASSERT( 0 );
951}
952
953
961bool containsNonAsciiChars( const wxString& string )
962{
963 for( unsigned i = 0; i < string.length(); i++ )
964 {
965 wchar_t ch = string[i];
966
967 if( ch > 255 )
968 return true;
969 }
970 return false;
971}
972
973
974void DXF_PLOTTER::Text( const VECTOR2I& aPos,
975 const COLOR4D& aColor,
976 const wxString& aText,
977 const EDA_ANGLE& aOrient,
978 const VECTOR2I& aSize,
979 enum GR_TEXT_H_ALIGN_T aH_justify,
980 enum GR_TEXT_V_ALIGN_T aV_justify,
981 int aWidth,
982 bool aItalic,
983 bool aBold,
984 bool aMultilineAllowed,
985 KIFONT::FONT* aFont,
986 const KIFONT::METRICS& aFontMetrics,
987 void* aData )
988{
989 // Fix me: see how to use DXF text mode for multiline texts
990 if( aMultilineAllowed && !aText.Contains( wxT( "\n" ) ) )
991 aMultilineAllowed = false; // the text has only one line.
992
993 bool processSuperSub = aText.Contains( wxT( "^{" ) ) || aText.Contains( wxT( "_{" ) );
994
995 if( m_textAsLines || containsNonAsciiChars( aText ) || aMultilineAllowed || processSuperSub )
996 {
997 // output text as graphics.
998 // Perhaps multiline texts could be handled as DXF text entity
999 // but I do not want spend time about this (JPC)
1000 PLOTTER::Text( aPos, aColor, aText, aOrient, aSize, aH_justify, aV_justify, aWidth, aItalic,
1001 aBold, aMultilineAllowed, aFont, aFontMetrics, aData );
1002 }
1003 else
1004 {
1005 TEXT_ATTRIBUTES attrs;
1006 attrs.m_Halign = aH_justify;
1007 attrs.m_Valign =aV_justify;
1008 attrs.m_StrokeWidth = aWidth;
1009 attrs.m_Angle = aOrient;
1010 attrs.m_Italic = aItalic;
1011 attrs.m_Bold = aBold;
1012 attrs.m_Mirrored = aSize.x < 0;
1013 attrs.m_Multiline = false;
1014 plotOneLineOfText( aPos, aColor, aText, attrs );
1015 }
1016}
1017
1018
1020 const COLOR4D& aColor,
1021 const wxString& aText,
1022 const TEXT_ATTRIBUTES& aAttributes,
1023 KIFONT::FONT* aFont,
1024 const KIFONT::METRICS& aFontMetrics,
1025 void* aData )
1026{
1027 TEXT_ATTRIBUTES attrs = aAttributes;
1028
1029 // Fix me: see how to use DXF text mode for multiline texts
1030 if( attrs.m_Multiline && !aText.Contains( wxT( "\n" ) ) )
1031 attrs.m_Multiline = false; // the text has only one line.
1032
1033 bool processSuperSub = aText.Contains( wxT( "^{" ) ) || aText.Contains( wxT( "_{" ) );
1034
1035 if( m_textAsLines || containsNonAsciiChars( aText ) || attrs.m_Multiline || processSuperSub )
1036 {
1037 // output text as graphics.
1038 // Perhaps multiline texts could be handled as DXF text entity
1039 // but I do not want spend time about that (JPC)
1040 PLOTTER::PlotText( aPos, aColor, aText, aAttributes, aFont, aFontMetrics, aData );
1041 }
1042 else
1043 {
1044 plotOneLineOfText( aPos, aColor, aText, attrs );
1045 }
1046}
1047
1048
1049void DXF_PLOTTER::plotOneLineOfText( const VECTOR2I& aPos, const COLOR4D& aColor,
1050 const wxString& aText, const TEXT_ATTRIBUTES& aAttributes )
1051{
1052 /* Emit text as a text entity. This loses formatting and shape but it's
1053 more useful as a CAD object */
1054 VECTOR2D origin_dev = userToDeviceCoordinates( aPos );
1055 SetColor( aColor );
1056 wxString cname = getDXFColorName( m_currentColor );
1057 VECTOR2D size_dev = userToDeviceSize( aAttributes.m_Size );
1058 int h_code = 0, v_code = 0;
1059
1060 switch( aAttributes.m_Halign )
1061 {
1062 case GR_TEXT_H_ALIGN_LEFT: h_code = 0; break;
1063 case GR_TEXT_H_ALIGN_CENTER: h_code = 1; break;
1064 case GR_TEXT_H_ALIGN_RIGHT: h_code = 2; break;
1065 case GR_TEXT_H_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); break;
1066 }
1067
1068 switch( aAttributes.m_Valign )
1069 {
1070 case GR_TEXT_V_ALIGN_TOP: v_code = 3; break;
1071 case GR_TEXT_V_ALIGN_CENTER: v_code = 2; break;
1072 case GR_TEXT_V_ALIGN_BOTTOM: v_code = 1; break;
1073 case GR_TEXT_V_ALIGN_INDETERMINATE: wxFAIL_MSG( wxT( "Indeterminate state legal only in dialogs." ) ); break;
1074 }
1075
1076 std::string textStyle = "KICAD";
1077 if( aAttributes.m_Bold )
1078 {
1079 if( aAttributes.m_Italic )
1080 textStyle = "KICADBI";
1081 else
1082 textStyle = "KICADB";
1083 }
1084 else if( aAttributes.m_Italic )
1085 textStyle = "KICADI";
1086
1087 // Position, size, rotation and alignment
1088 // The two alignment point usages is somewhat idiot (see the DXF ref)
1089 // Anyway since we don't use the fit/aligned options, they're the same
1090 fmt::print( m_outputFile,
1091 " 0\n"
1092 "TEXT\n"
1093 " 7\n"
1094 "{}\n" // Text style
1095 " 8\n"
1096 "{}\n" // Layer name
1097 " 10\n"
1098 "{}\n" // First point X
1099 " 11\n"
1100 "{}\n" // Second point X
1101 " 20\n"
1102 "{}\n" // First point Y
1103 " 21\n"
1104 "{}\n" // Second point Y
1105 " 40\n"
1106 "{}\n" // Text height
1107 " 41\n"
1108 "{}\n" // Width factor
1109 " 50\n"
1110 "{:.8f}\n" // Rotation
1111 " 51\n"
1112 "{:.8f}\n" // Oblique angle
1113 " 71\n"
1114 "{}\n" // Mirror flags
1115 " 72\n"
1116 "{}\n" // H alignment
1117 " 73\n"
1118 "{}\n", // V alignment
1119 textStyle,
1120 TO_UTF8( cname ),
1121 formatCoord( origin_dev.x ),
1122 formatCoord( origin_dev.x ),
1123 formatCoord( origin_dev.y ),
1124 formatCoord( origin_dev.y ),
1125 formatCoord( size_dev.y ),
1126 formatCoord( fabs( size_dev.x / size_dev.y ) ),
1127 aAttributes.m_Angle.AsDegrees(),
1128 aAttributes.m_Italic ? DXF_OBLIQUE_ANGLE : 0,
1129 aAttributes.m_Mirrored ? 2 : 0, // X mirror flag
1130 h_code, v_code );
1131
1132 /* There are two issue in emitting the text:
1133 - Our overline character (~) must be converted to the appropriate
1134 control sequence %%O or %%o
1135 - Text encoding in DXF is more or less unspecified since depends on
1136 the DXF declared version, the acad version reading it *and* some
1137 system variables to be put in the header handled only by newer acads
1138 Also before R15 unicode simply is not supported (you need to use
1139 bigfonts which are a massive PITA). Common denominator solution:
1140 use Latin1 (and however someone could choke on it, anyway). Sorry
1141 for the extended latin people. If somewant want to try fixing this
1142 recent version seems to use UTF-8 (and not UCS2 like the rest of
1143 Windows)
1144
1145 XXX Actually there is a *third* issue: older DXF formats are limited
1146 to 255 bytes records (it was later raised to 2048); since I'm lazy
1147 and text so long is not probable I just don't implement this rule.
1148 If someone is interested in fixing this, you have to emit the first
1149 partial lines with group code 3 (max 250 bytes each) and then finish
1150 with a group code 1 (less than 250 bytes). The DXF refs explains it
1151 in no more details...
1152 */
1153
1154 int braceNesting = 0;
1155 int overbarDepth = -1;
1156
1157 fmt::print( m_outputFile, " 1\n" );
1158
1159 for( unsigned int i = 0; i < aText.length(); i++ )
1160 {
1161 /* Here I do a bad thing: writing the output one byte at a time!
1162 but today I'm lazy and I have no idea on how to coerce a Unicode
1163 wxString to spit out latin1 encoded text ...
1164
1165 At least stdio is *supposed* to do output buffering, so there is
1166 hope is not too slow */
1167 wchar_t ch = aText[i];
1168
1169 if( ch > 255 )
1170 {
1171 // I can't encode this...
1172 putc( '?', m_outputFile );
1173 }
1174 else
1175 {
1176 if( aText[i] == '~' && i+1 < aText.length() && aText[i+1] == '{' )
1177 {
1178 fmt::print( m_outputFile, "%%o" );
1179 overbarDepth = braceNesting;
1180
1181 // Skip the '{'
1182 i++;
1183 continue;
1184 }
1185 else if( aText[i] == '{' )
1186 {
1187 braceNesting++;
1188 }
1189 else if( aText[i] == '}' )
1190 {
1191 if( braceNesting > 0 )
1192 braceNesting--;
1193
1194 if( braceNesting == overbarDepth )
1195 {
1196 fmt::print( m_outputFile, "%%O" );
1197 overbarDepth = -1;
1198 continue;
1199 }
1200 }
1201
1202 putc( ch, m_outputFile );
1203 }
1204 }
1205
1206 fmt::print( m_outputFile, "\n" );
1207}
int color
Definition: DXF_plotter.cpp:63
static const struct @18 dxf_layer[NBCOLORS]
The layer/colors palette.
static wxString getDXFColorName(const COLOR4D &aColor)
static const double DXF_OBLIQUE_ANGLE
Oblique angle for DXF native text (I don't remember if 15 degrees is the ISO value....
Definition: DXF_plotter.cpp:39
static std::string formatCoord(double aValue)
bool containsNonAsciiChars(const wxString &string)
Check if a given string contains non-ASCII characters.
static const char * getDXFLineType(LINE_STYLE aType)
const char * name
Definition: DXF_plotter.cpp:62
#define DXF_LINE_WIDTH
Definition: DXF_plotter.cpp:42
@ ERROR_INSIDE
Definition: approximation.h:34
void plotOneLineOfText(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const TEXT_ATTRIBUTES &aAttrs)
DXF_UNITS m_plotUnits
Definition: plotter_dxf.h:229
virtual void PlotText(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const TEXT_ATTRIBUTES &aAttributes, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, void *aData=nullptr) override
bool m_textAsLines
Definition: plotter_dxf.h:225
virtual void FlashPadCustom(const VECTOR2I &aPadPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, SHAPE_POLY_SET *aPolygons, void *aData) override
virtual void ThickCircle(const VECTOR2I &pos, int diametre, int width, void *aData) override
void SetUnits(DXF_UNITS aUnit)
Set the units to use for plotting the DXF file.
virtual void SetViewport(const VECTOR2I &aOffset, double aIusPerDecimil, double aScale, bool aMirror) override
Set the scale/position for the DXF plot.
virtual void ThickArc(const VECTOR2D &aCentre, const EDA_ANGLE &aStAngle, const EDA_ANGLE &aAngle, double aRadius, int aWidth, void *aData) override
virtual void Arc(const VECTOR2D &aCenter, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle, double aRadius, FILL_T aFill, int aWidth) override
double GetUnitScaling() const
Get the scale factor to apply to convert the device units to be in the currently set units.
Definition: plotter_dxf.h:206
virtual void FlashPadOval(const VECTOR2I &aPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, void *aData) override
DXF oval pad: always done in sketch mode.
virtual void FlashPadRect(const VECTOR2I &aPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, void *aData) override
DXF rectangular pad: always done in sketch mode.
virtual void ThickRect(const VECTOR2I &p1, const VECTOR2I &p2, int width, void *aData) override
virtual void FlashPadRoundRect(const VECTOR2I &aPadPos, const VECTOR2I &aSize, int aCornerRadius, const EDA_ANGLE &aOrient, void *aData) override
virtual void ThickPoly(const SHAPE_POLY_SET &aPoly, int aWidth, void *aData) override
virtual bool StartPlot(const wxString &aPageNumber) override
Open the DXF plot with a skeleton header.
unsigned int GetMeasurementDirective() const
Get the correct value for the $MEASUREMENT field given the current units.
Definition: plotter_dxf.h:216
virtual void FlashPadTrapez(const VECTOR2I &aPadPos, const VECTOR2I *aCorners, const EDA_ANGLE &aPadOrient, void *aData) override
DXF trapezoidal pad: only sketch mode is supported.
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width) override
DXF circle: full functionality; it even does 'fills' drawing a circle with a dual-arc polyline wide a...
virtual void FlashPadCircle(const VECTOR2I &pos, int diametre, void *aData) override
DXF round pad: always done in sketch mode; it could be filled but it isn't pretty if other kinds of p...
virtual void FilledCircle(const VECTOR2I &pos, int diametre, void *aData) override
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth, void *aData=nullptr) override
DXF polygon: doesn't fill it but at least it close the filled ones DXF does not know thick outline.
unsigned int m_measurementDirective
Definition: plotter_dxf.h:231
virtual bool EndPlot() override
virtual void FlashRegularPolygon(const VECTOR2I &aShapePos, int aDiameter, int aCornerCount, const EDA_ANGLE &aOrient, void *aData) override
Flash a regular polygon.
virtual void PenTo(const VECTOR2I &pos, char plume) override
Moveto/lineto primitive, moves the 'pen' to the specified direction.
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width) override
DXF rectangle: fill not supported.
virtual void SetColor(const COLOR4D &color) override
The DXF exporter handles 'colors' as layers...
virtual void Text(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const EDA_ANGLE &aOrient, const VECTOR2I &aSize, enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify, int aWidth, bool aItalic, bool aBold, bool aMultilineAllowed, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, void *aData=nullptr) override
Draw text with the plotter.
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData) override
double m_unitScalingFactor
Definition: plotter_dxf.h:230
virtual void SetDash(int aLineWidth, LINE_STYLE aLineStyle) override
COLOR4D m_currentColor
Definition: plotter_dxf.h:226
LINE_STYLE m_currentLineType
Definition: plotter_dxf.h:227
double AsDegrees() const
Definition: eda_angle.h:116
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:131
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
double r
Red component.
Definition: color4d.h:392
double g
Green component.
Definition: color4d.h:393
static EDA_COLOR_T FindNearestLegacyColor(int aR, int aG, int aB)
Returns a legacy color ID that is closest to the given 8-bit RGB values.
Definition: color4d.cpp:540
double b
Blue component.
Definition: color4d.h:394
bool m_plotMirror
Definition: plotter.h:654
void MoveTo(const VECTOR2I &pos)
Definition: plotter.h:261
virtual void ThickOval(const VECTOR2I &aPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, int aWidth, void *aData)
Definition: plotter.cpp:485
void FinishTo(const VECTOR2I &pos)
Definition: plotter.h:271
double m_iuPerDeviceUnit
Definition: plotter.h:651
VECTOR2I m_plotOffset
Definition: plotter.h:653
VECTOR2I m_penLastpos
Definition: plotter.h:667
virtual VECTOR2D userToDeviceCoordinates(const VECTOR2I &aCoordinate)
Modify coordinates according to the orientation, scale factor, and offsets trace.
Definition: plotter.cpp:91
VECTOR2I m_paperSize
Definition: plotter.h:675
virtual VECTOR2D userToDeviceSize(const VECTOR2I &size)
Modify size according to the plotter scale factors (VECTOR2I version, returns a VECTOR2D).
Definition: plotter.cpp:116
int GetPlotterArcHighDef() const
Definition: plotter.h:228
double m_plotScale
Plot scale - chosen by the user (even implicitly with 'fit in a4')
Definition: plotter.h:643
bool GetColorMode() const
Definition: plotter.h:149
FILE * m_outputFile
Output file.
Definition: plotter.h:660
void LineTo(const VECTOR2I &pos)
Definition: plotter.h:266
void PenFinish()
Definition: plotter.h:277
virtual void PlotText(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const TEXT_ATTRIBUTES &aAttributes, KIFONT::FONT *aFont=nullptr, const KIFONT::METRICS &aFontMetrics=KIFONT::METRICS::Default(), void *aData=nullptr)
Definition: plotter.cpp:687
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth, void *aData)=0
Draw a polygon ( filled or not ).
virtual void Text(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const EDA_ANGLE &aOrient, const VECTOR2I &aSize, enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify, int aPenWidth, bool aItalic, bool aBold, bool aMultilineAllowed, KIFONT::FONT *aFont, const KIFONT::METRICS &aFontMetrics, void *aData=nullptr)
Draw text with the plotter.
Definition: plotter.cpp:624
double m_IUsPerDecimil
Definition: plotter.h:649
bool m_colorMode
Definition: plotter.h:663
virtual DXF_OUTLINE_MODE GetDXFPlotMode() const
Definition: plotter.h:109
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
void Fracture()
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
int OutlineCount() const
Return the number of outlines in the set.
SHAPE_POLY_SET CloneDropTriangulation() const
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
EDA_COLOR_T
Legacy color enumeration.
Definition: color4d.h:42
@ NBCOLORS
Number of colors.
Definition: color4d.h:79
@ BLACK
Definition: color4d.h:44
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aInflate, int aError, ERROR_LOC aErrorLoc)
Convert a rectangle with rounded corners and/or chamfered corners to a polygon.
void TransformOvalToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aWidth, int aError, ERROR_LOC aErrorLoc, int aMinSegCount=0)
Convert a oblong shape to a polygon, using multiple segments.
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:413
FILL_T
Definition: eda_shape.h:56
This file contains miscellaneous commonly used macros and functions.
DXF_UNITS
Definition: plotter.h:52
@ SKETCH
Definition: plotter.h:81
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: string_utils.h:429
LINE_STYLE
Dashed line types.
Definition: stroke_params.h:46
int radius
VECTOR2I end
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_H_ALIGN_INDETERMINATE
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_INDETERMINATE
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:229
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695