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