KiCad PCB EDA Suite
Loading...
Searching...
No Matches
plotter.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
38
39#include <trigo.h>
40#include <plotters/plotter.h>
43#include <bezier_curves.h>
44#include <callback_gal.h>
45#include <math/util.h> // for KiROUND
47
48PLOTTER::PLOTTER( const PROJECT* aProject ) :
49 m_project( aProject )
50{
51 m_plotScale = 1;
52 m_currentPenWidth = -1; // To-be-set marker
53 m_penState = 'Z'; // End-of-path idle
54 m_plotMirror = false; // Plot mirror option flag
56 m_yaxisReversed = false;
57 m_outputFile = nullptr;
58 m_colorMode = false; // Starts as a BW plot
59 m_negativeMode = false;
60
61 // Temporary init to avoid not initialized vars, will be set later
62 m_IUsPerDecimil = 1; // will be set later to the actual value
63 m_iuPerDeviceUnit = 1; // will be set later to the actual value
64 m_renderSettings = nullptr;
66}
67
68
70{
71 // Emergency cleanup, but closing the file is usually made in EndPlot().
72 if( m_outputFile )
73 fclose( m_outputFile );
74}
75
76
77bool PLOTTER::OpenFile( const wxString& aFullFilename )
78{
79 m_filename = aFullFilename;
80
81 wxASSERT( !m_outputFile );
82
83 // Open the file in text mode (not suitable for all plotters but only for most of them.
84 m_outputFile = wxFopen( m_filename, wxT( "wt" ) );
85
86 if( m_outputFile == nullptr )
87 return false ;
88
89 return true;
90}
91
92
94{
95 VECTOR2I pos = aCoordinate - m_plotOffset;
96
97 double x = pos.x * m_plotScale;
98 double y = ( m_paperSize.y - pos.y * m_plotScale );
99
100 if( m_plotMirror )
101 {
103 x = ( m_paperSize.x - pos.x * m_plotScale );
104 else
105 y = pos.y * m_plotScale;
106 }
107
108 if( m_yaxisReversed )
109 y = m_paperSize.y - y;
110
113
114 return VECTOR2D( x, y );
115}
116
117
123
124
125double PLOTTER::userToDeviceSize( double size ) const
126{
127 return size * m_plotScale * m_iuPerDeviceUnit;
128}
129
130
131#define IU_PER_MILS ( m_IUsPerDecimil * 10 )
132
133
134double PLOTTER::GetDotMarkLenIU( int aLineWidth ) const
135{
136 return userToDeviceSize( m_renderSettings->GetDotLength( aLineWidth ) );
137}
138
139
140double PLOTTER::GetDashMarkLenIU( int aLineWidth ) const
141{
142 return userToDeviceSize( m_renderSettings->GetDashLength( aLineWidth ) );
143}
144
145
146double PLOTTER::GetDashGapLenIU( int aLineWidth ) const
147{
148 return userToDeviceSize( m_renderSettings->GetGapLength( aLineWidth ) );
149}
150
151
152void PLOTTER::Arc( const VECTOR2D& aStart, const VECTOR2D& aMid, const VECTOR2D& aEnd, FILL_T aFill,
153 int aWidth )
154{
155 VECTOR2D aCenter = CalcArcCenter( aStart, aMid, aEnd );
156
157 EDA_ANGLE startAngle( aStart - aCenter );
158 EDA_ANGLE endAngle( aEnd - aCenter );
159
160 // < 0: left, 0 : on the line, > 0 : right
161 double det = ( aEnd - aStart ).Cross( aMid - aStart );
162
163 int cw = det <= 0;
164 EDA_ANGLE angle = endAngle - startAngle;
165
166 if( cw )
167 angle.Normalize();
168 else
169 angle.NormalizeNegative();
170
171 double radius = ( aStart - aCenter ).EuclideanNorm();
172 Arc( aCenter, startAngle, angle, radius, aFill, aWidth );
173}
174
175
176void PLOTTER::Arc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle, const EDA_ANGLE& aAngle,
177 double aRadius, FILL_T aFill, int aWidth )
178{
179 polyArc( aCenter, aStartAngle, aAngle, aRadius, aFill, aWidth );
180}
181
182
183void PLOTTER::polyArc( const VECTOR2D& aCenter, const EDA_ANGLE& aStartAngle,
184 const EDA_ANGLE& aAngle, double aRadius, FILL_T aFill, int aWidth )
185{
186 EDA_ANGLE startAngle = aStartAngle;
187 EDA_ANGLE endAngle = startAngle + aAngle;
188 const EDA_ANGLE delta( 5.0, DEGREES_T ); // increment to draw arc
189 VECTOR2I start, end;
190 const int sign = 1;
191
192 if( aAngle < ANGLE_0 )
193 std::swap( startAngle, endAngle );
194
195 SetCurrentLineWidth( aWidth );
196
197 start.x = KiROUND( aCenter.x + aRadius * startAngle.Cos() );
198 start.y = KiROUND( aCenter.y + sign * aRadius * startAngle.Sin() );
199
200 if( aFill != FILL_T::NO_FILL )
201 {
202 MoveTo( aCenter );
203 LineTo( start );
204 }
205 else
206 {
207 MoveTo( start );
208 }
209
210 for( EDA_ANGLE ii = startAngle + delta; ii < endAngle; ii += delta )
211 {
212 end.x = KiROUND( aCenter.x + aRadius * ii.Cos() );
213 end.y = KiROUND( aCenter.y + sign * aRadius * ii.Sin() );
214 LineTo( end );
215 }
216
217 end.x = KiROUND( aCenter.x + aRadius * endAngle.Cos() );
218 end.y = KiROUND( aCenter.y + sign * aRadius * endAngle.Sin() );
219
220 if( aFill != FILL_T::NO_FILL )
221 {
222 LineTo( end );
223 FinishTo( aCenter );
224 }
225 else
226 {
227 FinishTo( end );
228 }
229}
230
231
232void PLOTTER::BezierCurve( const VECTOR2I& aStart, const VECTOR2I& aControl1,
233 const VECTOR2I& aControl2, const VECTOR2I& aEnd,
234 int aTolerance, int aLineThickness )
235{
236 // Generic fallback: Quadratic Bezier curve plotted as a polyline
237 std::vector<VECTOR2I> ctrlPoints;
238 ctrlPoints.reserve( 4 );
239
240 ctrlPoints.push_back( aStart );
241 ctrlPoints.push_back( aControl1 );
242 ctrlPoints.push_back( aControl2 );
243 ctrlPoints.push_back( aEnd );
244
245 BEZIER_POLY bezier_converter( ctrlPoints );
246
247 std::vector<VECTOR2I> approxPoints;
248 bezier_converter.GetPoly( approxPoints, aTolerance );
249
250 SetCurrentLineWidth( aLineThickness );
251 MoveTo( aStart );
252
253 for( unsigned ii = 1; ii < approxPoints.size()-1; ii++ )
254 LineTo( approxPoints[ii] );
255
256 FinishTo( aEnd );
257}
258
259
260void PLOTTER::PlotImage( const wxImage& aImage, const VECTOR2I& aPos, double aScaleFactor )
261{
262 VECTOR2I size( aImage.GetWidth() * aScaleFactor, aImage.GetHeight() * aScaleFactor );
263
264 VECTOR2I start = aPos;
265 start.x -= size.x / 2;
266 start.y -= size.y / 2;
267
268 VECTOR2I end = start;
269 end.x += size.x;
270 end.y += size.y;
271
273}
274
275
276void PLOTTER::markerSquare( const VECTOR2I& position, int radius )
277{
278 double r = KiROUND( radius / 1.4142 );
279 std::vector<VECTOR2I> corner_list;
280 VECTOR2I corner;
281
282 corner_list.reserve( 4 );
283
284 corner.x = position.x + r;
285 corner.y = position.y + r;
286 corner_list.push_back( corner );
287 corner.x = position.x + r;
288 corner.y = position.y - r;
289 corner_list.push_back( corner );
290 corner.x = position.x - r;
291 corner.y = position.y - r;
292 corner_list.push_back( corner );
293 corner.x = position.x - r;
294 corner.y = position.y + r;
295 corner_list.push_back( corner );
296 corner.x = position.x + r;
297 corner.y = position.y + r;
298 corner_list.push_back( corner );
299
300 PlotPoly( corner_list, FILL_T::NO_FILL, GetCurrentLineWidth(), nullptr );
301}
302
303
304void PLOTTER::markerCircle( const VECTOR2I& position, int radius )
305{
307}
308
309
310void PLOTTER::markerLozenge( const VECTOR2I& position, int radius )
311{
312 std::vector<VECTOR2I> corner_list;
313 VECTOR2I corner;
314
315 corner_list.reserve( 4 );
316
317 corner.x = position.x;
318 corner.y = position.y + radius;
319 corner_list.push_back( corner );
320 corner.x = position.x + radius;
321 corner.y = position.y,
322 corner_list.push_back( corner );
323 corner.x = position.x;
324 corner.y = position.y - radius;
325 corner_list.push_back( corner );
326 corner.x = position.x - radius;
327 corner.y = position.y;
328 corner_list.push_back( corner );
329 corner.x = position.x;
330 corner.y = position.y + radius;
331 corner_list.push_back( corner );
332
333 PlotPoly( corner_list, FILL_T::NO_FILL, GetCurrentLineWidth(), nullptr );
334}
335
336
337void PLOTTER::markerHBar( const VECTOR2I& pos, int radius )
338{
339 MoveTo( VECTOR2I( pos.x - radius, pos.y ) );
340 FinishTo( VECTOR2I( pos.x + radius, pos.y ) );
341}
342
343
344void PLOTTER::markerSlash( const VECTOR2I& pos, int radius )
345{
346 MoveTo( VECTOR2I( pos.x - radius, pos.y - radius ) );
347 FinishTo( VECTOR2I( pos.x + radius, pos.y + radius ) );
348}
349
350
352{
353 MoveTo( VECTOR2I( pos.x + radius, pos.y - radius ) );
354 FinishTo( VECTOR2I( pos.x - radius, pos.y + radius ) );
355}
356
357
358void PLOTTER::markerVBar( const VECTOR2I& pos, int radius )
359{
360 MoveTo( VECTOR2I( pos.x, pos.y - radius ) );
361 FinishTo( VECTOR2I( pos.x, pos.y + radius ) );
362}
363
364
365void PLOTTER::Marker( const VECTOR2I& position, int diametre, unsigned aShapeId )
366{
367 int radius = diametre / 2;
368
369 /* Marker are composed by a series of 'parts' superimposed; not every
370 combination make sense, obviously. Since they are used in order I
371 tried to keep the uglier/more complex constructions at the end.
372 Also I avoided the |/ |\ -/ -\ construction because they're *very*
373 ugly... if needed they could be added anyway... I'd like to see
374 a board with more than 58 drilling/slotting tools!
375 If Visual C++ supported the 0b literals they would be optimally
376 and easily encoded as an integer array. We have to do with octal */
377 static const unsigned char marker_patterns[MARKER_COUNT] = {
378
379 // Bit order: O Square Lozenge - | \ /
380 // First choice: simple shapes
381 0003, // X
382 0100, // O
383 0014, // +
384 0040, // Sq
385 0020, // Lz
386
387 // Two simple shapes
388 0103, // X O
389 0017, // X +
390 0043, // X Sq
391 0023, // X Lz
392 0114, // O +
393 0140, // O Sq
394 0120, // O Lz
395 0054, // + Sq
396 0034, // + Lz
397 0060, // Sq Lz
398
399 // Three simple shapes
400 0117, // X O +
401 0143, // X O Sq
402 0123, // X O Lz
403 0057, // X + Sq
404 0037, // X + Lz
405 0063, // X Sq Lz
406 0154, // O + Sq
407 0134, // O + Lz
408 0074, // + Sq Lz
409
410 // Four simple shapes
411 0174, // O Sq Lz +
412 0163, // X O Sq Lz
413 0157, // X O Sq +
414 0137, // X O Lz +
415 0077, // X Sq Lz +
416
417 // This draws *everything *
418 0177, // X O Sq Lz +
419
420 // Here we use the single bars... so the cross is forbidden
421 0110, // O -
422 0104, // O |
423 0101, // O /
424 0050, // Sq -
425 0044, // Sq |
426 0041, // Sq /
427 0030, // Lz -
428 0024, // Lz |
429 0021, // Lz /
430 0150, // O Sq -
431 0144, // O Sq |
432 0141, // O Sq /
433 0130, // O Lz -
434 0124, // O Lz |
435 0121, // O Lz /
436 0070, // Sq Lz -
437 0064, // Sq Lz |
438 0061, // Sq Lz /
439 0170, // O Sq Lz -
440 0164, // O Sq Lz |
441 0161, // O Sq Lz /
442
443 // Last resort: the backlash component (easy to confound)
444 0102, // \ O
445 0042, // \ Sq
446 0022, // \ Lz
447 0142, // \ O Sq
448 0122, // \ O Lz
449 0062, // \ Sq Lz
450 0162 // \ O Sq Lz
451 };
452
453 if( aShapeId >= MARKER_COUNT )
454 {
455 // Fallback shape
456 markerCircle( position, radius );
457 }
458 else
459 {
460 // Decode the pattern and draw the corresponding parts
461 unsigned char pat = marker_patterns[aShapeId];
462
463 if( pat & 0001 )
464 markerSlash( position, radius );
465
466 if( pat & 0002 )
467 markerBackSlash( position, radius );
468
469 if( pat & 0004 )
470 markerVBar( position, radius );
471
472 if( pat & 0010 )
473 markerHBar( position, radius );
474
475 if( pat & 0020 )
476 markerLozenge( position, radius );
477
478 if( pat & 0040 )
479 markerSquare( position, radius );
480
481 if( pat & 0100 )
482 markerCircle( position, radius );
483 }
484}
485
486
487void PLOTTER::ThickOval( const VECTOR2I& aPos, const VECTOR2I& aSize, const EDA_ANGLE& aOrient,
488 int aWidth, void* aData )
489{
490 SetCurrentLineWidth( aWidth, aData );
491
492 EDA_ANGLE orient( aOrient );
493 VECTOR2I size( aSize );
494
495 if( size.x > size.y )
496 {
497 std::swap( size.x, size.y );
498 orient += ANGLE_90;
499 }
500
501 int deltaxy = size.y - size.x; /* distance between centers of the oval */
502 int radius = size.x / 2;
503
504 // Build a vertical oval shape giving the start and end points of arcs and edges,
505 // and the middle point of arcs
506 std::vector<VECTOR2I> corners;
507 corners.reserve( 6 );
508 // Shape is (x = corner and arc ends, c = arc centre)
509 // xcx
510 //
511 // xcx
512 int half_height = deltaxy / 2;
513 corners.emplace_back( -radius, -half_height );
514 corners.emplace_back( -radius, half_height );
515 corners.emplace_back( 0, half_height );
516 corners.emplace_back( radius, half_height );
517 corners.emplace_back( radius, -half_height );
518 corners.emplace_back( 0, -half_height );
519
520 // Rotate and move to the actual position
521 for( VECTOR2I& corner : corners )
522 {
523 RotatePoint( corner, orient );
524 corner += aPos;
525 }
526
527 // Gen shape (2 lines and 2 180 deg arcs):
528 MoveTo( corners[0] );
529 FinishTo( corners[1] );
530
531 Arc( corners[2], -orient, ANGLE_180, radius, FILL_T::NO_FILL, aWidth );
532
533 MoveTo( corners[3] );
534 FinishTo( corners[4] );
535
536 Arc( corners[5], -orient, -ANGLE_180, radius, FILL_T::NO_FILL, aWidth );
537}
538
539
540void PLOTTER::ThickSegment( const VECTOR2I& start, const VECTOR2I& end, int width, void* aData )
541{
542 if( start == end )
543 {
544 // The width parameter doubles as a sentinel. DO_NOT_SET_LINE_WIDTH means the
545 // caller already configured the pen so we use the live pen width as the diameter.
546 // USE_DEFAULT_LINE_WIDTH must be resolved through SetCurrentLineWidth so the pen
547 // is also set to the default value, otherwise we would emit whatever the prior
548 // pen width happened to be.
549 int diameter = width;
550
551 if( width == USE_DEFAULT_LINE_WIDTH )
552 {
553 SetCurrentLineWidth( width, aData );
554 diameter = GetCurrentLineWidth();
555 }
556 else if( width == DO_NOT_SET_LINE_WIDTH )
557 {
558 diameter = GetCurrentLineWidth();
559 }
560
561 wxCHECK2_MSG( diameter >= 0, return,
562 wxT( "Plotter called with unresolved line width sentinel" ) );
563
564 Circle( start, diameter, FILL_T::FILLED_SHAPE, 0 );
565 }
566 else
567 {
568 SetCurrentLineWidth( width );
569 MoveTo( start );
570 FinishTo( end );
571 }
572}
573
574
575void PLOTTER::ThickArc( const VECTOR2D& centre, const EDA_ANGLE& aStartAngle,
576 const EDA_ANGLE& aAngle, double aRadius, int aWidth, void* aData )
577{
578 Arc( centre, aStartAngle, aAngle, aRadius, FILL_T::NO_FILL, aWidth );
579}
580
581
582void PLOTTER::ThickArc( const EDA_SHAPE& aArcShape, void* aData, int aWidth )
583{
584 VECTOR2D center = aArcShape.getCenter();
585 VECTOR2D mid = aArcShape.GetArcMid();
586 VECTOR2D start = aArcShape.GetStart();
587 VECTOR2D end = aArcShape.GetEnd();
588
589 EDA_ANGLE startAngle( start - center );
590 EDA_ANGLE endAngle( end - center );
591 EDA_ANGLE angle = endAngle - startAngle;
592
593 // < 0: left, 0 : on the line, > 0 : right
594 double det = ( end - start ).Cross( mid - start );
595
596 if( det <= 0 ) // cw
597 angle.Normalize();
598 else
599 angle.NormalizeNegative();
600
601 double radius = ( start - center ).EuclideanNorm();
602
603 ThickArc( center, startAngle, angle, radius, aWidth, aData );
604}
605
606
607void PLOTTER::ThickRect( const VECTOR2I& p1, const VECTOR2I& p2, int width, void* aData )
608{
609 Rect( p1, p2, FILL_T::NO_FILL, width, 0 );
610}
611
612
613void PLOTTER::ThickCircle( const VECTOR2I& pos, int diametre, int width, void* aData )
614{
615 Circle( pos, diametre, FILL_T::NO_FILL, width );
616}
617
618
619void PLOTTER::FilledCircle( const VECTOR2I& pos, int diametre, void* aData )
620{
621 Circle( pos, diametre, FILL_T::FILLED_SHAPE, 0 );
622}
623
624
625void PLOTTER::ThickPoly( const SHAPE_POLY_SET& aPoly, int aWidth, void* aData )
626{
627 PlotPoly( aPoly.COutline( 0 ), FILL_T::NO_FILL, aWidth, aData );
628}
629
630
631void PLOTTER::PlotPoly( const SHAPE_LINE_CHAIN& aLineChain, FILL_T aFill, int aWidth, void* aData )
632{
633 std::vector<VECTOR2I> cornerList;
634 cornerList.reserve( aLineChain.PointCount() );
635
636 for( int ii = 0; ii < aLineChain.PointCount(); ii++ )
637 cornerList.emplace_back( aLineChain.CPoint( ii ) );
638
639 if( aLineChain.IsClosed() && cornerList.front() != cornerList.back() )
640 cornerList.emplace_back( aLineChain.CPoint( 0 ) );
641
642 PlotPoly( cornerList, aFill, aWidth, aData );
643}
644
645
646void PLOTTER::Text( const VECTOR2I& aPos,
647 const COLOR4D& aColor,
648 const wxString& aText,
649 const EDA_ANGLE& aOrient,
650 const VECTOR2I& aSize,
651 enum GR_TEXT_H_ALIGN_T aH_justify,
652 enum GR_TEXT_V_ALIGN_T aV_justify,
653 int aPenWidth,
654 bool aItalic,
655 bool aBold,
656 bool aMultilineAllowed,
657 KIFONT::FONT* aFont,
658 const KIFONT::METRICS& aFontMetrics,
659 void* aData )
660{
662 wxString text( aText );
663
664 if( text.Contains( wxS( "@{" ) ) )
665 {
666 EXPRESSION_EVALUATOR evaluator;
667 text = evaluator.Evaluate( text );
668 }
669
670 SetColor( aColor );
671
672 if( aPenWidth == 0 && aBold ) // Use default values if aPenWidth == 0
673 aPenWidth = GetPenSizeForBold( std::min( aSize.x, aSize.y ) );
674
675 if( aPenWidth < 0 )
676 aPenWidth = -aPenWidth;
677
678 CALLBACK_GAL callback_gal( empty_opts,
679 // Stroke callback
680 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
681 {
682 SetCurrentLineWidth( aPenWidth );
683 MoveTo( aPt1 );
684 LineTo( aPt2 );
685 PenFinish();
686 },
687 // Polygon callback
688 [&]( const SHAPE_LINE_CHAIN& aPoly )
689 {
690 PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0, aData );
691 } );
692
693 TEXT_ATTRIBUTES attributes;
694 attributes.m_Angle = aOrient;
695 attributes.m_StrokeWidth = aPenWidth;
696 attributes.m_Italic = aItalic;
697 attributes.m_Bold = aBold;
698 attributes.m_Halign = aH_justify;
699 attributes.m_Valign = aV_justify;
700 attributes.m_Size = aSize;
701
702 // if Size.x is < 0, the text is mirrored (we have no other param to know a text is mirrored)
703 if( attributes.m_Size.x < 0 )
704 {
705 attributes.m_Size.x = -attributes.m_Size.x;
706 attributes.m_Mirrored = true;
707 }
708
709 if( !aFont )
710 aFont = KIFONT::FONT::GetFont( m_renderSettings->GetDefaultFont() );
711
712 aFont->Draw( &callback_gal, text, aPos, attributes, aFontMetrics );
713}
714
715
716void PLOTTER::PlotText( const VECTOR2I& aPos,
717 const COLOR4D& aColor,
718 const wxString& aText,
719 const TEXT_ATTRIBUTES& aAttributes,
720 KIFONT::FONT* aFont,
721 const KIFONT::METRICS& aFontMetrics,
722 void* aData )
723{
725 wxString text( aText );
726
727 if( text.Contains( wxS( "@{" ) ) )
728 {
729 EXPRESSION_EVALUATOR evaluator;
730 text = evaluator.Evaluate( text );
731 }
732
733 TEXT_ATTRIBUTES attributes = aAttributes;
734 int penWidth = attributes.m_StrokeWidth;
735
736 SetColor( aColor );
737 SetCurrentLineWidth( penWidth, aData );
738
739 if( penWidth == 0 && attributes.m_Bold ) // Use default values if aPenWidth == 0
740 penWidth = GetPenSizeForBold( std::min( attributes.m_Size.x, attributes.m_Size.y ) );
741
742 if( penWidth < 0 )
743 penWidth = -penWidth;
744
745 attributes.m_StrokeWidth = penWidth;
746
747 CALLBACK_GAL callback_gal( empty_opts,
748 // Stroke callback
749 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
750 {
751 MoveTo( aPt1 );
752 LineTo( aPt2 );
753 PenFinish();
754 },
755 // Polygon callback
756 [&]( const SHAPE_LINE_CHAIN& aPoly )
757 {
758 PlotPoly( aPoly, FILL_T::FILLED_SHAPE, 0, aData );
759 } );
760
761 if( !aFont )
762 aFont = KIFONT::FONT::GetFont( m_renderSettings->GetDefaultFont() );
763
764 aFont->Draw( &callback_gal, text, aPos, attributes, aFontMetrics );
765}
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
Bezier curves to polygon converter.
void GetPoly(std::vector< VECTOR2I > &aOutput, int aMaxError=10)
Convert a Bezier curve to a polygon.
EDA_ANGLE Normalize()
Definition eda_angle.h:229
EDA_ANGLE NormalizeNegative()
Definition eda_angle.h:246
double Sin() const
Definition eda_angle.h:178
double Cos() const
Definition eda_angle.h:197
VECTOR2I getCenter() const
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:236
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:194
VECTOR2I GetArcMid() const
High-level wrapper for evaluating mathematical and string expressions in wxString format.
wxString Evaluate(const wxString &aInput)
Main evaluation function - processes input string and evaluates all} expressions.
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:98
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
Definition font.cpp:147
void Draw(KIGFX::GAL *aGal, const wxString &aText, const VECTOR2I &aPosition, const VECTOR2I &aCursor, const TEXT_ATTRIBUTES &aAttributes, const METRICS &aFontMetrics, std::optional< VECTOR2I > aMousePos=std::nullopt, wxString *aActiveUrl=nullptr) const
Draw a string.
Definition font.cpp:250
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:105
double GetDotMarkLenIU(int aLineWidth) const
Definition plotter.cpp:134
virtual void PlotImage(const wxImage &aImage, const VECTOR2I &aPos, double aScaleFactor)
Only PostScript plotters can plot bitmaps.
Definition plotter.cpp:260
static const unsigned MARKER_COUNT
Draw a marker (used for the drill map).
Definition plotter.h:538
double GetDashGapLenIU(int aLineWidth) const
Definition plotter.cpp:146
const PROJECT * m_project
Definition plotter.h:728
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width)=0
virtual bool OpenFile(const wxString &aFullFilename)
Open or create the plot file aFullFilename.
Definition plotter.cpp:77
bool m_mirrorIsHorizontal
Definition plotter.h:703
virtual void ThickPoly(const SHAPE_POLY_SET &aPoly, int aWidth, void *aData)
Definition plotter.cpp:625
bool m_plotMirror
Definition plotter.h:701
static const int USE_DEFAULT_LINE_WIDTH
Definition plotter.h:141
virtual void FilledCircle(const VECTOR2I &pos, int diametre, void *aData)
Definition plotter.cpp:619
void MoveTo(const VECTOR2I &pos)
Definition plotter.h:309
virtual void ThickOval(const VECTOR2I &aPos, const VECTOR2I &aSize, const EDA_ANGLE &aOrient, int aWidth, void *aData)
Definition plotter.cpp:487
void markerSlash(const VECTOR2I &pos, int radius)
Plot a / bar centered on the position.
Definition plotter.cpp:344
void FinishTo(const VECTOR2I &pos)
Definition plotter.h:319
bool m_yaxisReversed
Definition plotter.h:704
virtual void polyArc(const VECTOR2D &aCentre, const EDA_ANGLE &aStartAngle, const EDA_ANGLE &aAngle, double aRadius, FILL_T aFill, int aWidth)
Generic fallback: arc rendered as a polyline.
Definition plotter.cpp:183
double m_iuPerDeviceUnit
Definition plotter.h:698
PCB_LAYER_ID m_layer
Definition plotter.h:731
VECTOR2I m_plotOffset
Definition plotter.h:700
virtual VECTOR2D userToDeviceCoordinates(const VECTOR2I &aCoordinate)
Modify coordinates according to the orientation, scale factor, and offsets trace.
Definition plotter.cpp:93
virtual ~PLOTTER()
Definition plotter.cpp:69
VECTOR2I m_paperSize
Definition plotter.h:722
virtual VECTOR2D userToDeviceSize(const VECTOR2I &size)
Modify size according to the plotter scale factors (VECTOR2I version, returns a VECTOR2D).
Definition plotter.cpp:118
virtual void ThickArc(const EDA_SHAPE &aArcShape, void *aData, int aWidth)
Definition plotter.cpp:582
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width, int aCornerRadius=0)=0
char m_penState
Definition plotter.h:713
void Marker(const VECTOR2I &position, int diametre, unsigned aShapeId)
Draw a pattern shape number aShapeId, to coord position.
Definition plotter.cpp:365
virtual void BezierCurve(const VECTOR2I &aStart, const VECTOR2I &aControl1, const VECTOR2I &aControl2, const VECTOR2I &aEnd, int aTolerance, int aLineThickness)
Generic fallback: Cubic Bezier curve rendered as a polyline.
Definition plotter.cpp:232
void markerHBar(const VECTOR2I &pos, int radius)
Plot a - bar centered on the position.
Definition plotter.cpp:337
int m_currentPenWidth
Definition plotter.h:712
double m_plotScale
Plot scale - chosen by the user (even implicitly with 'fit in a4')
Definition plotter.h:690
void markerCircle(const VECTOR2I &pos, int radius)
Plot a circle centered on the position.
Definition plotter.cpp:304
PLOTTER(const PROJECT *aProject=nullptr)
Definition plotter.cpp:48
FILE * m_outputFile
Output file.
Definition plotter.h:707
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
void LineTo(const VECTOR2I &pos)
Definition plotter.h:314
void PenFinish()
Definition plotter.h:325
static const int DO_NOT_SET_LINE_WIDTH
Definition plotter.h:140
virtual void ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData)
Definition plotter.cpp:540
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:716
void markerLozenge(const VECTOR2I &position, int radius)
Plot a lozenge centered on the position.
Definition plotter.cpp:310
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth, void *aData)=0
Draw a polygon ( filled or not ).
virtual void ThickRect(const VECTOR2I &p1, const VECTOR2I &p2, int width, void *aData)
Definition plotter.cpp:607
RENDER_SETTINGS * m_renderSettings
Definition plotter.h:726
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:646
void markerBackSlash(const VECTOR2I &pos, int radius)
Plot a \ bar centered on the position.
Definition plotter.cpp:351
bool m_negativeMode
Definition plotter.h:711
double m_IUsPerDecimil
Definition plotter.h:696
void markerVBar(const VECTOR2I &pos, int radius)
Plot a | bar centered on the position.
Definition plotter.cpp:358
void markerSquare(const VECTOR2I &position, int radius)
Plot a square centered on the position.
Definition plotter.cpp:276
virtual void ThickCircle(const VECTOR2I &pos, int diametre, int width, void *aData)
Definition plotter.cpp:613
virtual int GetCurrentLineWidth() const
Definition plotter.h:183
bool m_colorMode
Definition plotter.h:710
double GetDashMarkLenIU(int aLineWidth) const
Definition plotter.cpp:140
virtual void SetColor(const COLOR4D &color)=0
wxString m_filename
Definition plotter.h:717
virtual void Arc(const VECTOR2D &aStart, const VECTOR2D &aMid, const VECTOR2D &aEnd, FILL_T aFill, int aWidth)
Definition plotter.cpp:152
Container for project specific data.
Definition project.h:66
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.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:411
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
@ DEGREES_T
Definition eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:415
FILL_T
Definition eda_shape.h:63
@ NO_FILL
Definition eda_shape.h:64
@ FILLED_SHAPE
Fill with object color.
Definition eda_shape.h:65
int GetPenSizeForBold(int aTextSize)
Definition gr_text.cpp:37
@ UNDEFINED_LAYER
Definition layer_ids.h:61
bool cw
VECTOR2I center
int radius
VECTOR2I end
int delta
GR_TEXT_H_ALIGN_T
This is API surface mapped to common.types.HorizontalAlignment.
GR_TEXT_V_ALIGN_T
This is API surface mapped to common.types.VertialAlignment.
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
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition trigo.cpp:534
constexpr int sign(T val)
Definition util.h:145
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:687
VECTOR2< double > VECTOR2D
Definition vector2d.h:686