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