KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_textbox.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20#include <advanced_config.h>
21#include <common.h>
22#include <pcb_edit_frame.h>
23#include <base_units.h>
24#include <bitmaps.h>
25#include <board.h>
27#include <footprint.h>
28#include <pcb_textbox.h>
29#include <pcb_painter.h>
30#include <trigo.h>
31#include <string_utils.h>
33#include <geometry/shape_rect.h>
35#include <callback_gal.h>
37#include <macros.h>
38#include <core/ignore.h>
39#include <api/api_enums.h>
40#include <api/api_utils.h>
41#include <api/board/board_types.pb.h>
42#include <properties/property.h>
44
45
47 PCB_SHAPE( aParent, aType, SHAPE_T::RECTANGLE ),
49 m_borderEnabled( true ),
51{
54 SetMultilineAllowed( true );
55
56 int defaultMargin = GetLegacyTextMargin();
57 m_marginLeft = defaultMargin;
58 m_marginTop = defaultMargin;
59 m_marginRight = defaultMargin;
60 m_marginBottom = defaultMargin;
61}
62
63
67
68
69void PCB_TEXTBOX::CopyFrom( const BOARD_ITEM* aOther )
70{
71 wxCHECK( aOther && aOther->Type() == PCB_TEXTBOX_T, /* void */ );
72 *this = *static_cast<const PCB_TEXTBOX*>( aOther );
73}
74
75
76void PCB_TEXTBOX::Serialize( google::protobuf::Any& aContainer ) const
77{
78 using namespace kiapi::common::types;
79 using namespace kiapi::board;
80 types::BoardTextBox boardText;
82 boardText.mutable_id()->set_value( m_Uuid.AsStdString() );
83 boardText.set_locked( IsLocked() ? LockedState::LS_LOCKED : LockedState::LS_UNLOCKED );
84
85 TextBox& text = *boardText.mutable_textbox();
86
87 kiapi::common::PackVector2( *text.mutable_top_left(), GetPosition() );
88 kiapi::common::PackVector2( *text.mutable_bottom_right(), GetEnd() );
89 text.set_text( GetText().ToStdString() );
90 //text.set_hyperlink( GetHyperlink().ToStdString() );
91
92 TextAttributes* attrs = text.mutable_attributes();
93
94 if( GetFont() )
95 attrs->set_font_name( GetFont()->GetName().ToStdString() );
96
97 attrs->set_horizontal_alignment( ToProtoEnum<GR_TEXT_H_ALIGN_T, HorizontalAlignment>( GetHorizJustify() ) );
98
99 attrs->set_vertical_alignment( ToProtoEnum<GR_TEXT_V_ALIGN_T, VerticalAlignment>( GetVertJustify() ) );
100
101 attrs->mutable_angle()->set_value_degrees( GetTextAngleDegrees() );
102 attrs->set_line_spacing( GetLineSpacing() );
103 attrs->mutable_stroke_width()->set_value_nm( GetTextThickness() );
104 attrs->set_italic( IsItalic() );
105 attrs->set_bold( IsBold() );
106 attrs->set_underlined( GetAttributes().m_Underlined );
107 attrs->set_mirrored( IsMirrored() );
108 attrs->set_multiline( IsMultilineAllowed() );
109 attrs->set_keep_upright( IsKeepUpright() );
110 kiapi::common::PackVector2( *attrs->mutable_size(), GetTextSize() );
111
112 aContainer.PackFrom( boardText );
113}
114
115
116bool PCB_TEXTBOX::Deserialize( const google::protobuf::Any& aContainer )
117{
118 using namespace kiapi::board;
119 types::BoardTextBox boardText;
120
121 if( !aContainer.UnpackTo( &boardText ) )
122 return false;
123
124 SetUuidDirect( KIID( boardText.id().value() ) );
126 SetLocked( boardText.locked() == kiapi::common::types::LockedState::LS_LOCKED );
127
128 const kiapi::common::types::TextBox& text = boardText.textbox();
129
131 SetEnd( kiapi::common::UnpackVector2( text.bottom_right() ) );
132 SetText( wxString( text.text().c_str(), wxConvUTF8 ) );
133 //SetHyperlink( wxString::FromUTF8( text.hyperlink() );
134
135 if( text.has_attributes() )
136 {
138
139 attrs.m_Bold = text.attributes().bold();
140 attrs.m_Italic = text.attributes().italic();
141 attrs.m_Underlined = text.attributes().underlined();
142 attrs.m_Mirrored = text.attributes().mirrored();
143 attrs.m_Multiline = text.attributes().multiline();
144 attrs.m_KeepUpright = text.attributes().keep_upright();
145 attrs.m_Size = kiapi::common::UnpackVector2( text.attributes().size() );
146
147 if( !text.attributes().font_name().empty() )
148 {
149 attrs.m_Font = KIFONT::FONT::GetFont( wxString( text.attributes().font_name().c_str(), wxConvUTF8 ),
150 attrs.m_Bold, attrs.m_Italic );
151 }
152
153 attrs.m_Angle = EDA_ANGLE( text.attributes().angle().value_degrees(), DEGREES_T );
154 attrs.m_LineSpacing = text.attributes().line_spacing();
155 attrs.m_StrokeWidth = text.attributes().stroke_width().value_nm();
157 text.attributes().horizontal_alignment() );
158
160 text.attributes().vertical_alignment() );
161
162 SetAttributes( attrs );
163 }
164
165 return true;
166}
167
168
169void PCB_TEXTBOX::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings, bool aCheckSide )
170{
171 PCB_SHAPE::StyleFromSettings( settings, aCheckSide );
172
173 SetTextSize( settings.GetTextSize( GetLayer() ) );
175 SetItalic( settings.GetTextItalic( GetLayer() ) );
176
177 if( GetParentFootprint() )
178 SetKeepUpright( settings.GetTextUpright( GetLayer() ) );
179
180 if( aCheckSide )
181 {
182 if( BOARD* board = GetBoard() )
183 SetMirrored( board->IsBackLayer( GetLayer() ) );
184 else
186 }
187}
188
189
191{
192 return KiROUND( GetStroke().GetWidth() / 2.0 ) + KiROUND( GetTextSize().y * 0.75 );
193}
194
195
197{
198 if( GetText().IsEmpty() )
199 return VECTOR2I( 0, 0 );
200
201 BOX2I textBox = GetTextBox( nullptr );
202
203 int textHeight = std::abs( textBox.GetHeight() );
204
205 if( GetTextAngle().IsHorizontal() )
206 textHeight += GetMarginTop() + GetMarginBottom();
207 else
208 textHeight += GetMarginLeft() + GetMarginRight();
209
210 // Only enforce minimum height. Width returns 0 so the user can freely shrink width
211 // (text rewraps) while height is constrained to fit the wrapped text content.
212 // GetTextBox returns dimensions in text-local coordinates. For 90/270 degree rotations,
213 // the text's natural height maps to screen x-axis.
214 EDA_ANGLE rotation = GetDrawRotation();
215
216 if( rotation == ANGLE_90 || rotation == ANGLE_270 )
217 return VECTOR2I( textHeight, 0 );
218
219 return VECTOR2I( 0, textHeight );
220}
221
222
224{
225 EDA_SHAPE::SetShape( aShape );
226 m_libShape = aShape;
227}
228
229
230std::vector<VECTOR2I> PCB_TEXTBOX::GetCorners() const
231{
233}
234
235
236std::vector<VECTOR2I> PCB_TEXTBOX::GetCornersInSequence( EDA_ANGLE angle ) const
237{
239 return EDA_SHAPE::GetCornersInSequence( angle );
240
241 const int left = std::min( m_start.x, m_end.x );
242 const int right = std::max( m_start.x, m_end.x );
243 const int top = std::min( m_start.y, m_end.y );
244 const int bottom = std::max( m_start.y, m_end.y );
245
246 const VECTOR2I center( ( left + right ) / 2, ( top + bottom ) / 2 );
247
248 std::vector<VECTOR2I> pts = {
249 VECTOR2I( left, top ),
250 VECTOR2I( right, top ),
251 VECTOR2I( right, bottom ),
252 VECTOR2I( left, bottom ),
253 };
254
255 angle.Normalize();
256
257 if( !angle.IsZero() )
258 {
259 for( VECTOR2I& p : pts )
260 RotatePoint( p, center, angle );
261 }
262
263 return pts;
264}
265
266
268{
269 EDA_ANGLE rotation = GetDrawRotation();
270
271 if( rotation == ANGLE_90 )
272 return VECTOR2I( GetStartX(), GetEndY() );
273 else if( rotation == ANGLE_180 )
274 return GetEnd();
275 else if( rotation == ANGLE_270 )
276 return VECTOR2I( GetEndX(), GetStartY() );
277 else
278 return GetStart();
279}
280
281
283{
284 EDA_ANGLE rotation = GetDrawRotation();
285
286 if( rotation == ANGLE_90 )
287 return VECTOR2I( GetEndX(), GetStartY() );
288 else if( rotation == ANGLE_180 )
289 return GetStart();
290 else if( rotation == ANGLE_270 )
291 return VECTOR2I( GetStartX(), GetEndY() );
292 else
293 return GetEnd();
294}
295
296
297void PCB_TEXTBOX::SetTop( int aVal )
298{
299 EDA_ANGLE rotation = GetDrawRotation();
300
301 if( rotation == ANGLE_90 || rotation == ANGLE_180 )
302 SetEndY( aVal );
303 else
304 SetStartY( aVal );
305}
306
307
309{
310 EDA_ANGLE rotation = GetDrawRotation();
311
312 if( rotation == ANGLE_90 || rotation == ANGLE_180 )
313 SetStartY( aVal );
314 else
315 SetEndY( aVal );
316}
317
318
319void PCB_TEXTBOX::SetLeft( int aVal )
320{
321 EDA_ANGLE rotation = GetDrawRotation();
322
323 if( rotation == ANGLE_180 || rotation == ANGLE_270 )
324 SetEndX( aVal );
325 else
326 SetStartX( aVal );
327}
328
329
330void PCB_TEXTBOX::SetRight( int aVal )
331{
332 EDA_ANGLE rotation = GetDrawRotation();
333
334 if( rotation == ANGLE_180 || rotation == ANGLE_270 )
335 SetStartX( aVal );
336 else
337 SetEndX( aVal );
338}
339
340
342{
343 if( const FOOTPRINT* fp = GetParentFootprint() )
344 return m_libTextAngle + fp->GetOrientation();
345
346 return m_libTextAngle;
347}
348
349
351{
352 EDA_ANGLE delta = aAngle.Normalized() - GetTextAngle();
354}
355
356
358{
359 return GetDrawPos( false );
360}
361
362
363VECTOR2I PCB_TEXTBOX::GetDrawPos( bool aIsFlipped ) const
364{
365 EDA_ANGLE drawAngle = GetDrawRotation();
366 std::vector<VECTOR2I> corners = GetCornersInSequence( drawAngle );
367 GR_TEXT_H_ALIGN_T horizontalAlignment = GetHorizJustify();
368 GR_TEXT_V_ALIGN_T verticalAlignment = GetVertJustify();
369 VECTOR2I textAnchor;
370 VECTOR2I offset;
371
372 // Calculate midpoints
373 VECTOR2I midTop = ( corners[0] + corners[1] ) / 2;
374 VECTOR2I midBottom = ( corners[3] + corners[2] ) / 2;
375 VECTOR2I midLeft = ( corners[0] + corners[3] ) / 2;
376 VECTOR2I midRight = ( corners[1] + corners[2] ) / 2;
377 VECTOR2I center = ( corners[0] + corners[1] + corners[2] + corners[3] ) / 4;
378
379 if( IsMirrored() != aIsFlipped )
380 {
381 switch( GetHorizJustify() )
382 {
383 case GR_TEXT_H_ALIGN_LEFT: horizontalAlignment = GR_TEXT_H_ALIGN_RIGHT; break;
384 case GR_TEXT_H_ALIGN_CENTER: horizontalAlignment = GR_TEXT_H_ALIGN_CENTER; break;
385 case GR_TEXT_H_ALIGN_RIGHT: horizontalAlignment = GR_TEXT_H_ALIGN_LEFT; break;
386 case GR_TEXT_H_ALIGN_INDETERMINATE: horizontalAlignment = GR_TEXT_H_ALIGN_INDETERMINATE; break;
387 }
388 }
389
390 wxASSERT_MSG( horizontalAlignment != GR_TEXT_H_ALIGN_INDETERMINATE
391 && verticalAlignment != GR_TEXT_V_ALIGN_INDETERMINATE,
392 wxS( "Indeterminate state legal only in dialogs. Horizontal and vertical alignment "
393 "must be set before calling PCB_TEXTBOX::GetDrawPos." ) );
394
395 if( horizontalAlignment == GR_TEXT_H_ALIGN_INDETERMINATE || verticalAlignment == GR_TEXT_V_ALIGN_INDETERMINATE )
396 {
397 return center;
398 }
399
400 if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT && verticalAlignment == GR_TEXT_V_ALIGN_TOP )
401 {
402 textAnchor = corners[0];
403 }
404 else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER && verticalAlignment == GR_TEXT_V_ALIGN_TOP )
405 {
406 textAnchor = midTop;
407 }
408 else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT && verticalAlignment == GR_TEXT_V_ALIGN_TOP )
409 {
410 textAnchor = corners[1];
411 }
412 else if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT && verticalAlignment == GR_TEXT_V_ALIGN_CENTER )
413 {
414 textAnchor = midLeft;
415 }
416 else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER && verticalAlignment == GR_TEXT_V_ALIGN_CENTER )
417 {
418 textAnchor = center;
419 }
420 else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT && verticalAlignment == GR_TEXT_V_ALIGN_CENTER )
421 {
422 textAnchor = midRight;
423 }
424 else if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM )
425 {
426 textAnchor = corners[3];
427 }
428 else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM )
429 {
430 textAnchor = midBottom;
431 }
432 else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM )
433 {
434 textAnchor = corners[2];
435 }
436
437 int marginLeft = GetMarginLeft();
438 int marginRight = GetMarginRight();
439 int marginTop = GetMarginTop();
440 int marginBottom = GetMarginBottom();
441
442 if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT )
443 offset.x = marginLeft;
444 else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT )
445 offset.x = -marginRight;
446
447 if( verticalAlignment == GR_TEXT_V_ALIGN_TOP )
448 offset.y = marginTop;
449 else if( verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM )
450 offset.y = -marginBottom;
451
452 RotatePoint( offset, GetDrawRotation() );
453 return textAnchor + offset;
454}
455
456
457double PCB_TEXTBOX::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
458{
459 KIGFX::PCB_PAINTER& painter = static_cast<KIGFX::PCB_PAINTER&>( *aView->GetPainter() );
460 KIGFX::PCB_RENDER_SETTINGS& renderSettings = *painter.GetSettings();
461
462 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
463 {
464 // Hide shadow if the main layer is not shown
465 if( !aView->IsLayerVisibleCached( m_layer ) )
466 return LOD_HIDE;
467
468 // Hide shadow on dimmed tracks
469 if( renderSettings.GetHighContrast() )
470 {
471 if( m_layer != renderSettings.GetPrimaryHighContrastLayer() )
472 return LOD_HIDE;
473 }
474 }
475
476 return LOD_SHOW;
477}
478
479
480std::vector<int> PCB_TEXTBOX::ViewGetLayers() const
481{
484
485 return { GetLayer() };
486}
487
488
489wxString PCB_TEXTBOX::GetShownText( bool aAllowExtraText, int aDepth ) const
490{
491 const FOOTPRINT* parentFootprint = GetParentFootprint();
492 const BOARD* board = GetBoard();
493
494 std::function<bool( wxString* )> resolver = [&]( wxString* token ) -> bool
495 {
496 if( token->IsSameAs( wxT( "LAYER" ) ) )
497 {
498 *token = GetLayerName();
499 return true;
500 }
501
502 if( parentFootprint && parentFootprint->ResolveTextVar( token, aDepth + 1 ) )
503 return true;
504
505 if( board->ResolveTextVar( token, aDepth + 1 ) )
506 return true;
507
508 return false;
509 };
510
511 wxString text = EDA_TEXT::GetShownText( aAllowExtraText, aDepth );
512
513 if( HasTextVars() )
514 text = ResolveTextVars( text, &resolver, aDepth );
515
516 KIFONT::FONT* font = GetDrawFont( nullptr );
517 EDA_ANGLE drawAngle = GetDrawRotation();
518 std::vector<VECTOR2I> corners = GetCornersInSequence( drawAngle );
519 int colWidth = ( corners[1] - corners[0] ).EuclideanNorm();
520
521 if( GetTextAngle().IsHorizontal() )
522 colWidth -= ( GetMarginLeft() + GetMarginRight() );
523 else
524 colWidth -= ( GetMarginTop() + GetMarginBottom() );
525
526 font->LinebreakText( text, colWidth, GetTextSize(), GetTextThickness(), IsBold(), IsItalic() );
527
528 // Convert escape markers back to literal ${} and @{} for final display
529 text.Replace( wxT( "<<<ESC_DOLLAR:" ), wxT( "${" ) );
530 text.Replace( wxT( "<<<ESC_AT:" ), wxT( "@{" ) );
531
532 return text;
533}
534
535
536bool PCB_TEXTBOX::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
537{
538 return BOARD_ITEM::Matches( UnescapeString( GetText() ), aSearchData );
539}
540
541
542void PCB_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
543{
544 // Don't use GetShownText() here; we want to show the user the variable references
545 aList.emplace_back( _( "Text Box" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
546
547 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
548 aList.emplace_back( _( "Status" ), _( "Locked" ) );
549
550 aList.emplace_back( _( "Layer" ), GetLayerName() );
551 aList.emplace_back( _( "Mirror" ), IsMirrored() ? _( "Yes" ) : _( "No" ) );
552 aList.emplace_back( _( "Angle" ), wxString::Format( "%g", GetTextAngle().AsDegrees() ) );
553
554 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
555
556 if( GetTextThickness() )
557 aList.emplace_back( _( "Text Thickness" ), aFrame->MessageTextFromValue( GetEffectiveTextPenWidth() ) );
558 else
559 aList.emplace_back( _( "Text Thickness" ), _( "Auto" ) );
560
561 aList.emplace_back( _( "Text Width" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
562 aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( GetTextHeight() ) );
563
564 aList.emplace_back( _( "Box Width" ), aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) );
565
566 aList.emplace_back( _( "Box Height" ), aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) );
567
568 m_stroke.GetMsgPanelInfo( aFrame, aList );
569}
570
571
572void PCB_TEXTBOX::Move( const VECTOR2I& aMoveVector )
573{
574 PCB_SHAPE::Move( aMoveVector );
575 EDA_TEXT::Offset( aMoveVector );
576}
577
578
580{
582
583 if( const FOOTPRINT* fp = GetParentFootprint() )
584 {
585 const TRANSFORM_TRS& xf = fp->GetTransform();
586 return { KiROUND( libSize.x * std::abs( xf.GetScaleX() ) ), KiROUND( libSize.y * std::abs( xf.GetScaleY() ) ) };
587 }
588
589 return libSize;
590}
591
592
593void PCB_TEXTBOX::SetTextSize( VECTOR2I aNewSize, bool aEnforceMinTextSize )
594{
595 if( const FOOTPRINT* fp = GetParentFootprint() )
596 {
597 const TRANSFORM_TRS& xf = fp->GetTransform();
598 aNewSize = { KiROUND( aNewSize.x / std::abs( xf.GetScaleX() ) ),
599 KiROUND( aNewSize.y / std::abs( xf.GetScaleY() ) ) };
600 }
601
602 EDA_TEXT::SetTextSize( aNewSize, aEnforceMinTextSize );
603}
604
605
607{
608 int libThickness = EDA_TEXT::GetTextThickness();
609
610 if( const FOOTPRINT* fp = GetParentFootprint() )
611 {
612 const TRANSFORM_TRS& xf = fp->GetTransform();
613 const double factor = ( std::abs( xf.GetScaleX() ) + std::abs( xf.GetScaleY() ) ) * 0.5;
614 return KiROUND( libThickness * factor );
615 }
616
617 return libThickness;
618}
619
620
622{
623 if( const FOOTPRINT* fp = GetParentFootprint() )
624 {
625 const TRANSFORM_TRS& xf = fp->GetTransform();
626 const double factor = ( std::abs( xf.GetScaleX() ) + std::abs( xf.GetScaleY() ) ) * 0.5;
627 aWidth = KiROUND( aWidth / factor );
628 }
629
631}
632
633
634void PCB_TEXTBOX::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
635{
636 // Slide the axis-aligned box, rotation lives in the text angle.
637 const VECTOR2D oldCenter( ( m_start.x + m_end.x ) * 0.5, ( m_start.y + m_end.y ) * 0.5 );
638 VECTOR2D newCenter = oldCenter;
639 RotatePoint( newCenter, VECTOR2D( aRotCentre.x, aRotCentre.y ), aAngle );
640
641 const VECTOR2I delta( KiROUND( newCenter.x - oldCenter.x ), KiROUND( newCenter.y - oldCenter.y ) );
644
646
647 EDA_ANGLE newAbs = ( GetTextAngle() + aAngle ).Normalize();
648 EDA_TEXT::SetTextAngle( newAbs );
649
650 if( const FOOTPRINT* fp = GetParentFootprint() )
651 m_libTextAngle = newAbs - fp->GetOrientation();
652 else
653 m_libTextAngle = newAbs;
654
655 m_libTextAngle.Normalize();
656}
657
658
659void PCB_TEXTBOX::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
660{
661 // the position and angle are mirrored, but not the text (or its justification)
662 PCB_SHAPE::Mirror( aCentre, aFlipDirection );
663
664 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
666 else
668
669 m_libTextAngle.Normalize();
671}
672
673
674void PCB_TEXTBOX::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
675{
676 PCB_SHAPE::Flip( aCentre, aFlipDirection );
677
678 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
680 else
682
683 m_libTextAngle.Normalize();
685
686 if( IsSideSpecific() )
688}
689
690
692{
693 if( const FOOTPRINT* fp = GetParentFootprint(); fp && GetLibraryShape() == SHAPE_T::RECTANGLE )
694 {
695 const TRANSFORM_TRS& xform = fp->GetTransform();
697
698 const VECTOR2I libCenter( ( m_libStart.x + m_libEnd.x ) / 2, ( m_libStart.y + m_libEnd.y ) / 2 );
699 const int libHalfW = std::abs( m_libEnd.x - m_libStart.x ) / 2;
700 const int libHalfH = std::abs( m_libEnd.y - m_libStart.y ) / 2;
701
702 const VECTOR2I newCenter = xform.Apply( libCenter );
703 const int newHalfW = std::abs( KiROUND( libHalfW * xform.GetScaleX() ) );
704 const int newHalfH = std::abs( KiROUND( libHalfH * xform.GetScaleY() ) );
705
706 EDA_SHAPE::SetStart( VECTOR2I( newCenter.x - newHalfW, newCenter.y - newHalfH ) );
707 EDA_SHAPE::SetEnd( VECTOR2I( newCenter.x + newHalfW, newCenter.y + newHalfH ) );
708 }
709 else
710 {
712 }
713
717}
718
719
721{
722 const FOOTPRINT* fp = GetParentFootprint();
723
724 // Only the axis-aligned rectangle case needs the textbox-specific inverse.
725 // Poly textboxes and standalone (non-FP) boxes use the base shape mapping.
726 if( !fp || GetShape() != SHAPE_T::RECTANGLE )
727 {
729 return;
730 }
731
732 const TRANSFORM_TRS& xform = fp->GetTransform();
733
734 const VECTOR2I boardCenter( ( m_start.x + m_end.x ) / 2, ( m_start.y + m_end.y ) / 2 );
735 const int boardHalfW = std::abs( m_end.x - m_start.x ) / 2;
736 const int boardHalfH = std::abs( m_end.y - m_start.y ) / 2;
737
738 const VECTOR2I libCenter = xform.InverseApply( boardCenter );
739 const int libHalfW = std::abs( KiROUND( boardHalfW / xform.GetScaleX() ) );
740 const int libHalfH = std::abs( KiROUND( boardHalfH / xform.GetScaleY() ) );
741
742 m_libStart = VECTOR2I( libCenter.x - libHalfW, libCenter.y - libHalfH );
743 m_libEnd = VECTOR2I( libCenter.x + libHalfW, libCenter.y + libHalfH );
744}
745
746
747void PCB_TEXTBOX::OnFootprintRescaled( double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I& aAnchor,
748 const EDA_ANGLE& aParentRotate )
749{
751}
752
753
754bool PCB_TEXTBOX::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
755{
756 BOX2I rect = GetBoundingBox();
757
758 rect.Inflate( aAccuracy );
759
760 return rect.Contains( aPosition );
761}
762
763
764bool PCB_TEXTBOX::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
765{
766 BOX2I rect = aRect;
767
768 rect.Inflate( aAccuracy );
769
770 if( aContained )
771 return rect.Contains( GetBoundingBox() );
772
773 return rect.Intersects( GetBoundingBox() );
774}
775
776
777bool PCB_TEXTBOX::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
778{
779 return PCB_SHAPE::HitTest( aPoly, aContained );
780}
781
782
783wxString PCB_TEXTBOX::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
784{
785 return wxString::Format( _( "PCB text box '%s' on %s" ),
786 aFull ? GetShownText( false ) : KIUI::EllipsizeMenuText( GetText() ), GetLayerName() );
787}
788
789
794
795
797{
798 return new PCB_TEXTBOX( *this );
799}
800
801
803{
804 wxASSERT( aImage->Type() == PCB_TEXTBOX_T );
805
806 std::swap( *( (PCB_TEXTBOX*) this ), *( (PCB_TEXTBOX*) aImage ) );
807}
808
809
810std::shared_ptr<SHAPE> PCB_TEXTBOX::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
811{
812 std::shared_ptr<SHAPE_COMPOUND> shape = GetEffectiveTextShape();
813
814 if( PCB_SHAPE::GetStroke().GetWidth() >= 0 )
815 shape->AddShape( PCB_SHAPE::GetEffectiveShape( aLayer, aFlash ) );
816
817 return shape;
818}
819
820
821void PCB_TEXTBOX::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance, int aMaxError,
822 ERROR_LOC aErrorLoc ) const
823{
825 KIFONT::FONT* font = GetDrawFont( nullptr );
826 int penWidth = GetEffectiveTextPenWidth();
828 wxString shownText = GetShownText( true );
829
830 // The polygonal shape of a text can have many basic shapes, so combining these shapes can
831 // be very useful to create a final shape with a lot less vertices to speedup calculations.
832 // Simplify shapes is not usually always efficient, but in this case it is.
833 SHAPE_POLY_SET textShape;
834
835 CALLBACK_GAL callback_gal(
836 empty_opts,
837 // Stroke callback
838 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
839 {
840 TransformOvalToPolygon( textShape, aPt1, aPt2, penWidth, aMaxError, aErrorLoc );
841 },
842 // Triangulation callback
843 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
844 {
845 textShape.NewOutline();
846
847 for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } )
848 textShape.Append( point.x, point.y );
849 } );
850
851 if( auto* cache = GetRenderCache( font, shownText ) )
852 callback_gal.DrawGlyphs( *cache );
853 else
854 font->Draw( &callback_gal, shownText, GetDrawPos(), attrs, GetFontMetrics() );
855
856 textShape.Simplify();
857
858 if( IsKnockout() )
859 {
860 SHAPE_POLY_SET finalPoly;
861
862 TransformShapeToPolygon( finalPoly, GetLayer(), aClearance, aMaxError, aErrorLoc );
863 finalPoly.BooleanSubtract( textShape );
864
865 aBuffer.Append( finalPoly );
866 }
867 else
868 {
869 if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE )
870 {
871 if( aErrorLoc == ERROR_OUTSIDE )
872 aClearance += aMaxError;
873
874 textShape.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aMaxError, true );
875 }
876
877 aBuffer.Append( textShape );
878 }
879}
880
881
882void PCB_TEXTBOX::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError,
883 ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
884{
885 // Don't use PCB_SHAPE::TransformShapeToPolygon. We want to treat the textbox as filled even
886 // if there's no background colour.
887
888 int width = GetWidth() + ( 2 * aClearance );
889
891 {
892 std::vector<VECTOR2I> pts = GetRectCorners();
893
894 aBuffer.NewOutline();
895
896 for( const VECTOR2I& pt : pts )
897 aBuffer.Append( pt );
898
899 if( m_borderEnabled && width > 0 )
900 {
901 // Add in segments
902 TransformOvalToPolygon( aBuffer, pts[0], pts[1], width, aMaxError, aErrorLoc );
903 TransformOvalToPolygon( aBuffer, pts[1], pts[2], width, aMaxError, aErrorLoc );
904 TransformOvalToPolygon( aBuffer, pts[2], pts[3], width, aMaxError, aErrorLoc );
905 TransformOvalToPolygon( aBuffer, pts[3], pts[0], width, aMaxError, aErrorLoc );
906 }
907 }
908 else if( GetShape() == SHAPE_T::POLY ) // Non-cardinally-rotated rect
909 {
910 aBuffer.NewOutline();
911
912 const SHAPE_LINE_CHAIN& poly = GetPolyShape().Outline( 0 );
913
914 for( int ii = 0; ii < poly.PointCount(); ++ii )
915 aBuffer.Append( poly.GetPoint( ii ) );
916
917 if( m_borderEnabled && width > 0 )
918 {
919 for( int ii = 0; ii < poly.SegmentCount(); ++ii )
920 {
921 const SEG& seg = poly.GetSegment( ii );
922 TransformOvalToPolygon( aBuffer, seg.A, seg.B, width, aMaxError, aErrorLoc );
923 }
924 }
925 }
926}
927
928
930{
931 return m_borderEnabled;
932}
933
934
936{
937 m_borderEnabled = enabled;
938}
939
940
941void PCB_TEXTBOX::SetBorderWidth( const int aSize )
942{
943 m_stroke.SetWidth( aSize );
944}
945
946
947bool PCB_TEXTBOX::operator==( const BOARD_ITEM& aBoardItem ) const
948{
949 if( aBoardItem.Type() != Type() )
950 return false;
951
952 const PCB_TEXTBOX& other = static_cast<const PCB_TEXTBOX&>( aBoardItem );
953
954 return *this == other;
955}
956
957
958bool PCB_TEXTBOX::operator==( const PCB_TEXTBOX& aOther ) const
959{
960 return m_borderEnabled == aOther.m_borderEnabled && EDA_TEXT::operator==( aOther );
961}
962
963
964double PCB_TEXTBOX::Similarity( const BOARD_ITEM& aBoardItem ) const
965{
966 if( aBoardItem.Type() != Type() )
967 return 0.0;
968
969 const PCB_TEXTBOX& other = static_cast<const PCB_TEXTBOX&>( aBoardItem );
970
971 double similarity = 1.0;
972
973 if( m_borderEnabled != other.m_borderEnabled )
974 similarity *= 0.9;
975
976 if( GetMarginLeft() != other.GetMarginLeft() )
977 similarity *= 0.9;
978
979 if( GetMarginTop() != other.GetMarginTop() )
980 similarity *= 0.9;
981
982 if( GetMarginRight() != other.GetMarginRight() )
983 similarity *= 0.9;
984
985 if( GetMarginBottom() != other.GetMarginBottom() )
986 similarity *= 0.9;
987
988 similarity *= EDA_TEXT::Similarity( other );
989
990 return similarity;
991}
992
993
994static struct PCB_TEXTBOX_DESC
995{
997 {
999
1000 if( lineStyleEnum.Choices().GetCount() == 0 )
1001 {
1002 lineStyleEnum.Map( LINE_STYLE::SOLID, _HKI( "Solid" ) )
1003 .Map( LINE_STYLE::DASH, _HKI( "Dashed" ) )
1004 .Map( LINE_STYLE::DOT, _HKI( "Dotted" ) )
1005 .Map( LINE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) )
1006 .Map( LINE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) );
1007 }
1008
1017
1018 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Shape" ) );
1019 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start X" ) );
1020 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start Y" ) );
1021 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "End X" ) );
1022 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "End Y" ) );
1023 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Width" ) );
1024 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Height" ) );
1025 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Width" ) );
1026 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Style" ) );
1027 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Filled" ) );
1028 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Color" ) );
1029 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Corner Radius" ) );
1030
1031 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Color" ) );
1032
1033 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( PCB_SHAPE ), _HKI( "Soldermask" ) );
1034 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( PCB_SHAPE ), _HKI( "Soldermask Margin Override" ) );
1035
1038 _HKI( "Text Properties" ) );
1039
1040 const wxString borderProps = _( "Border Properties" );
1041
1042 void ( PCB_TEXTBOX::*lineStyleSetter )( LINE_STYLE ) = &PCB_TEXTBOX::SetLineStyle;
1043 LINE_STYLE ( PCB_TEXTBOX::*lineStyleGetter )() const = &PCB_TEXTBOX::GetLineStyle;
1044
1047 borderProps );
1048
1049 propMgr.AddProperty(
1050 new PROPERTY_ENUM<PCB_TEXTBOX, LINE_STYLE>( _HKI( "Border Style" ), lineStyleSetter, lineStyleGetter ),
1051 borderProps );
1052
1055 borderProps );
1056
1057 const wxString marginProps = _( "Margins" );
1058
1061 marginProps );
1064 marginProps );
1067 marginProps );
1070 marginProps );
1071
1072 propMgr.Mask( TYPE_HASH( PCB_TEXT ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) );
1073 }
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:47
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_OUTSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:121
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
Container for design settings for a BOARD object.
bool GetTextUpright(PCB_LAYER_ID aLayer) const
int GetTextThickness(PCB_LAYER_ID aLayer) const
Return the default text thickness from the layer class for the given layer.
bool GetTextItalic(PCB_LAYER_ID aLayer) const
VECTOR2I GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:83
friend class BOARD
Definition board_item.h:512
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
void SetLocked(bool aLocked) override
Definition board_item.h:356
PCB_LAYER_ID m_layer
Definition board_item.h:508
virtual bool IsKnockout() const
Definition board_item.h:352
bool IsLocked() const override
virtual void SetIsKnockout(bool aKnockout)
Definition board_item.h:353
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
const KIFONT::METRICS & GetFontMetrics() const
bool IsSideSpecific() const
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:554
constexpr size_type GetHeight() const
Definition box2.h:211
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:164
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:307
EDA_ANGLE Normalize()
Definition eda_angle.h:229
bool IsZero() const
Definition eda_angle.h:136
EDA_ANGLE Normalized() const
Definition eda_angle.h:240
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:416
SHAPE_T m_shape
Definition eda_shape.h:592
virtual void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:244
void SetStartX(int x)
Definition eda_shape.h:208
int GetStartY() const
Definition eda_shape.h:191
void SetEndY(int aY)
Definition eda_shape.h:251
int GetEndX() const
Definition eda_shape.h:242
void SetLineStyle(const LINE_STYLE aStyle)
void SetStartY(int y)
Definition eda_shape.h:201
SHAPE_POLY_SET & GetPolyShape()
virtual std::vector< VECTOR2I > GetCornersInSequence(EDA_ANGLE angle) const
SHAPE_T GetShape() const
Definition eda_shape.h:185
int GetEndY() const
Definition eda_shape.h:241
void SetEndX(int aX)
Definition eda_shape.h:258
VECTOR2I m_start
Definition eda_shape.h:604
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:240
LINE_STYLE GetLineStyle() const
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:190
virtual void SetShape(SHAPE_T aShape)
Definition eda_shape.h:184
std::vector< VECTOR2I > GetRectCorners() const
int GetStartX() const
Definition eda_shape.h:192
VECTOR2I m_end
Definition eda_shape.h:605
STROKE_PARAMS m_stroke
Definition eda_shape.h:593
virtual void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:194
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:89
virtual VECTOR2I GetTextSize() const
Definition eda_text.h:282
bool IsItalic() const
Definition eda_text.h:190
virtual void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:532
bool IsMultilineAllowed() const
Definition eda_text.h:218
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:110
bool IsKeepUpright() const
Definition eda_text.h:227
virtual int GetTextHeight() const
Definition eda_text.h:288
KIFONT::FONT * GetFont() const
Definition eda_text.h:268
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition eda_text.cpp:428
void SetMirrored(bool isMirrored)
Definition eda_text.cpp:388
std::vector< std::unique_ptr< KIFONT::GLYPH > > * GetRenderCache(const KIFONT::FONT *aFont, const wxString &forResolvedText, const VECTOR2I &aOffset={ 0, 0 }) const
Definition eda_text.cpp:703
virtual EDA_ANGLE GetDrawRotation() const
Definition eda_text.h:400
BOX2I GetTextBox(const RENDER_SETTINGS *aSettings, int aLine=-1) const
Useful in multiline texts to calculate the full text or a line area (for zones filling,...
Definition eda_text.cpp:773
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:412
virtual void Offset(const VECTOR2I &aOffset)
Definition eda_text.cpp:595
virtual int GetTextWidth() const
Definition eda_text.h:285
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:221
virtual KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const
Definition eda_text.cpp:667
bool HasTextVars() const
Indicates the ShownText has text var references which need to be processed.
Definition eda_text.h:129
EDA_TEXT(const EDA_IU_SCALE &aIuScale, const wxString &aText=wxEmptyString)
Definition eda_text.cpp:98
virtual void ClearBoundingBoxCache()
Definition eda_text.cpp:695
double GetLineSpacing() const
Definition eda_text.h:279
double Similarity(const EDA_TEXT &aOther) const
virtual void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition eda_text.cpp:279
virtual void ClearRenderCache()
Definition eda_text.cpp:689
const TEXT_ATTRIBUTES & GetAttributes() const
Definition eda_text.h:252
bool IsMirrored() const
Definition eda_text.h:211
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:461
double GetTextAngleDegrees() const
Definition eda_text.h:175
std::shared_ptr< SHAPE_COMPOUND > GetEffectiveTextShape(bool aTriangulate=true, const BOX2I &aBBox=BOX2I(), const EDA_ANGLE &aAngle=ANGLE_0) const
build a list of segments (SHAPE_SEGMENT) to describe a text shape.
bool IsBold() const
Definition eda_text.h:205
void SetKeepUpright(bool aKeepUpright)
Definition eda_text.cpp:420
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:224
virtual wxString GetShownText(bool aAllowExtraText, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition eda_text.h:121
virtual int GetTextThickness() const
Definition eda_text.h:149
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:265
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:294
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition eda_text.cpp:302
bool operator==(const EDA_TEXT &aRhs) const
Definition eda_text.h:419
void SetMultilineAllowed(bool aAllow)
Definition eda_text.cpp:396
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:404
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:727
static ENUM_MAP< T > & Instance()
Definition property.h:721
wxPGChoices & Choices()
Definition property.h:772
bool ResolveTextVar(wxString *token, int aDepth=0) const
Resolve any references to system tokens supported by the component.
const TRANSFORM_TRS & GetTransform() const
Definition footprint.h:419
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:94
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:143
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:246
void LinebreakText(wxString &aText, int aColumnWidth, const VECTOR2I &aGlyphSize, int aThickness, bool aBold, bool aItalic) const
Insert characters into text to ensure that no lines are wider than aColumnWidth.
Definition font.cpp:605
virtual void DrawGlyphs(const std::vector< std::unique_ptr< KIFONT::GLYPH > > &aGlyphs)
Draw polygons representing font glyphs.
Contains methods for drawing PCB-specific items.
virtual PCB_RENDER_SETTINGS * GetSettings() override
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition pcb_painter.h:78
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition view_item.h:176
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition view_item.h:181
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
bool IsLayerVisibleCached(int aLayer) const
Definition view.h:437
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition view.h:225
Definition kiid.h:44
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition pcb_shape.h:151
virtual void Mirror(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Mirror this object relative to a given horizontal axis the layer is not changed.
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
VECTOR2I m_libEnd
Definition pcb_shape.h:368
virtual void syncLibCoords()
PCB_SHAPE(BOARD_ITEM *aParent, KICAD_T aItemType, SHAPE_T aShapeType)
SHAPE_T m_libShape
Definition pcb_shape.h:384
int GetWidth() const override
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition pcb_shape.h:153
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Make a set of SHAPE objects representing the PCB_SHAPE.
void SetPosition(const VECTOR2I &aPos) override
Definition pcb_shape.h:75
SHAPE_T GetLibraryShape() const
Definition pcb_shape.h:222
void SetEnd(const VECTOR2I &aEnd) override
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
STROKE_PARAMS GetStroke() const override
void Move(const VECTOR2I &aMoveVector) override
Move this object.
void OnFootprintTransformed() override
Hook for items inside a footprint to refresh after the FP transform changes (translate,...
Definition pcb_shape.h:186
void Normalize() override
Perform any normalization required after a user rotate and/or flip.
VECTOR2I m_libStart
Definition pcb_shape.h:367
VECTOR2I GetPosition() const override
Definition pcb_shape.h:76
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition pcb_shape.h:68
bool HitTest(const VECTOR2I &aPosition, int aAccuracy) const override
Test if aPosition is inside or on the boundary of this item.
virtual void swapData(BOARD_ITEM *aImage) override
void SetBorderWidth(const int aSize)
double Similarity(const BOARD_ITEM &aBoardItem) const override
Return a measure of how likely the other object is to represent the same object.
bool IsBorderEnabled() const
Disables the border, this is done by changing the stroke internally.
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
int GetMarginBottom() const
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
EDA_ANGLE GetTextAngle() const override
PCB_TEXTBOX(BOARD_ITEM *aParent, KICAD_T aType=PCB_TEXTBOX_T)
int GetTextThickness() const override
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc, bool aIgnoreLineWidth=false) const override
Convert the shape to a closed polygon.
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
bool m_borderEnabled
Controls drawing the border (as defined by the stroke members)
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
void SetBorderEnabled(bool enabled)
void Mirror(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Mirror this object relative to a given horizontal axis the layer is not changed.
void OnFootprintTransformed() override
Hook for items inside a footprint to refresh after the FP transform changes (translate,...
VECTOR2I GetMinSize() const
Return the minimum height needed to contain the textbox's wrapped text content plus margins.
void TransformTextToPolySet(SHAPE_POLY_SET &aBuffer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc) const
Function TransformTextToPolySet Convert the text to a polygonSet describing the actual character stro...
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
void OnFootprintRescaled(double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I &aAnchor, const EDA_ANGLE &aParentRotate) override
Apply a parent footprint scale to this item.
VECTOR2I GetTextSize() const override
EDA_ITEM * Clone() const override
Tests whether the border is disabled, as configured by the stroke.
void SetShape(SHAPE_T aShape) override
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Make a set of SHAPE objects representing the PCB_SHAPE.
bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const override
Compare the item against the search criteria in aSearchData.
VECTOR2I GetDrawPos() const override
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
void SetMarginTop(int aTop)
Definition pcb_textbox.h:95
void SetLeft(int aVal) override
int GetMarginLeft() const
Definition pcb_textbox.h:99
void SetMarginLeft(int aLeft)
Definition pcb_textbox.h:94
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
void SetMarginBottom(int aBottom)
Definition pcb_textbox.h:97
std::vector< VECTOR2I > GetCornersInSequence(EDA_ANGLE angle) const override
int GetMarginRight() const
void SetRight(int aVal) override
std::vector< int > ViewGetLayers() const override
void SetTop(int aVal) override
int GetMarginTop() const
wxString GetShownText(bool aAllowExtraText, int aDepth=0) const override
Return the string actually shown after processing of the base text.
void SetTextAngle(const EDA_ANGLE &aAngle) override
bool operator==(const PCB_TEXTBOX &aOther) const
void SetTextThickness(int aWidth) override
The TextThickness is that set by the user.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void SetMarginRight(int aRight)
Definition pcb_textbox.h:96
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetLegacyTextMargin() const
void syncLibCoords() override
void SetBottom(int aVal) override
EDA_ANGLE m_libTextAngle
VECTOR2I GetTopLeft() const override
VECTOR2I GetBotRight() const override
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true) override
void CopyFrom(const BOARD_ITEM *aOther) override
int GetBorderWidth() const
std::vector< VECTOR2I > GetCorners() const override
Return 4 corners for a rectangle or rotated rectangle (stored as a poly).
Provide class metadata.Helper macro to map type hashes to names.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
void Mask(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName)
Sets a base class property as masked in a derived class.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
virtual const VECTOR2I GetPoint(int aIndex) const override
int PointCount() const
Return the number of points (vertices) in this line chain.
virtual const SEG GetSegment(int aIndex) const override
int SegmentCount() const
Return the number of segments in this line chain.
Represent a set of closed polygons.
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)
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
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 BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
KIFONT::FONT * m_Font
VECTOR2I InverseApply(const VECTOR2I &aPoint) const
double GetScaleX() const
VECTOR2I Apply(const VECTOR2I &aPoint) const
double GetScaleY() const
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
wxString ResolveTextVars(const wxString &aSource, const std::function< bool(wxString *)> *aResolver, int &aDepth)
Multi-pass text variable expansion and math expression evaluation.
Definition common.cpp:296
The common library.
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.
#define _(s)
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_270
Definition eda_angle.h:416
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:415
#define PCB_EDIT_FRAME_NAME
SHAPE_T
Definition eda_shape.h:44
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:47
static FILENAME_RESOLVER * resolver
a few functions useful in geometry calculations.
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition layer_ids.h:180
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition layer_ids.h:801
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition layer_ids.h:303
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
This file contains miscellaneous commonly used macros and functions.
FLIP_DIRECTION
Definition mirror.h:23
@ LEFT_RIGHT
Flip left to right (around the Y axis)
Definition mirror.h:24
KICOMMON_API wxString EllipsizeMenuText(const wxString &aString)
Ellipsize text (at the end) to be no more than 36 characters.
KICOMMON_API wxString EllipsizeStatusText(wxWindow *aWindow, const wxString &aString)
Ellipsize text (at the end) to be no more than 1/3 of the window width.
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
#define _HKI(x)
Definition page_info.cpp:40
static struct PCB_TEXTBOX_DESC _PCB_TEXTBOX_DESC
#define TYPE_HASH(x)
Definition property.h:74
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
wxString UnescapeString(const wxString &aSource)
LINE_STYLE
Dashed line types.
KIBIS top(path, &reporter)
VECTOR2I center
int delta
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:225
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:71
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:86
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682