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( kiapi::board::types::BoardTextBox& boardText ) const
77{
78 using namespace kiapi::common::types;
79 using namespace kiapi::board;
81 boardText.mutable_id()->set_value( m_Uuid.AsStdString() );
82 boardText.set_locked( IsLocked() ? LockedState::LS_LOCKED : LockedState::LS_UNLOCKED );
83
84 TextBox& text = *boardText.mutable_textbox();
85
86 kiapi::common::PackVector2( *text.mutable_top_left(), GetPosition() );
87 kiapi::common::PackVector2( *text.mutable_bottom_right(), GetEnd() );
88 text.set_text( GetText().ToStdString() );
89
90 kiapi::common::PackTextAttributes( *text.mutable_attributes(), GetAttributes() );
91
92 text.set_border_enabled( IsBorderEnabled() );
93 text.mutable_margin_left()->set_value_nm( GetMarginLeft() );
94 text.mutable_margin_top()->set_value_nm( GetMarginTop() );
95 text.mutable_margin_right()->set_value_nm( GetMarginRight() );
96 text.mutable_margin_bottom()->set_value_nm( GetMarginBottom() );
97
98 boardText.set_knockout( IsKnockout() );
99
100 if( FOOTPRINT* parent = GetParentFootprint() )
101 boardText.mutable_parent()->set_value( parent->m_Uuid.AsStdString() );
102 else if( const BOARD* board = GetBoard() )
103 boardText.mutable_parent()->set_value( board->m_Uuid.AsStdString() );
104
105 kiapi::common::PackCustomProperties( boardText.mutable_custom_properties(), *this );
106}
107
108
109void PCB_TEXTBOX::Serialize( google::protobuf::Any& aContainer ) const
110{
111 kiapi::board::types::BoardTextBox boardText;
112 Serialize( boardText );
113 aContainer.PackFrom( boardText );
114}
115
116
117bool PCB_TEXTBOX::Deserialize( const kiapi::board::types::BoardTextBox& boardText )
118{
119 using namespace kiapi::board;
120
121
122 SetUuidDirect( KIID( boardText.id().value() ) );
124 SetLocked( boardText.locked() == kiapi::common::types::LockedState::LS_LOCKED );
125
126 const kiapi::common::types::TextBox& text = boardText.textbox();
127
129 SetEnd( kiapi::common::UnpackVector2( text.bottom_right() ) );
130 SetText( wxString( text.text().c_str(), wxConvUTF8 ) );
131
132 if( text.has_attributes() )
133 {
135 kiapi::common::UnpackTextAttributes( attrs, text.attributes() );
136 SetAttributes( attrs );
137
138 // Handles setting shape to rectangle or polygon
139 SetTextAngle( attrs.m_Angle.GetAngle() );
140 }
141
142 if( text.has_margin_left() )
143 SetMarginLeft( text.margin_left().value_nm() );
144 if( text.has_margin_top() )
145 SetMarginTop( text.margin_top().value_nm() );
146 if( text.has_margin_right() )
147 SetMarginRight( text.margin_right().value_nm() );
148 if( text.has_margin_bottom() )
149 SetMarginBottom( text.margin_bottom().value_nm() );
150
151 SetBorderEnabled( text.border_enabled() );
152 SetIsKnockout( boardText.knockout() );
153
154 kiapi::common::UnpackCustomProperties( boardText.custom_properties(), *this );
155
156 return true;
157}
158
159
160bool PCB_TEXTBOX::Deserialize( const google::protobuf::Any& aContainer )
161{
162 kiapi::board::types::BoardTextBox boardText;
163
164 if( !aContainer.UnpackTo( &boardText ) )
165 return false;
166
167 return Deserialize( boardText );
168}
169
170
171void PCB_TEXTBOX::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings, bool aCheckSide )
172{
173 PCB_SHAPE::StyleFromSettings( settings, aCheckSide );
174
175 SetTextSize( settings.GetTextSize( GetLayer() ) );
177 SetItalic( settings.GetTextItalic( GetLayer() ) );
178
179 if( GetParentFootprint() )
180 SetKeepUpright( settings.GetTextUpright( GetLayer() ) );
181
182 if( aCheckSide )
183 {
184 if( BOARD* board = GetBoard() )
185 SetMirrored( board->IsBackLayer( GetLayer() ) );
186 else
188 }
189}
190
191
193{
194 return KiROUND( GetStroke().GetWidth() / 2.0 ) + KiROUND( GetTextSize().y * 0.75 );
195}
196
197
199{
200 if( GetText().IsEmpty() )
201 return VECTOR2I( 0, 0 );
202
203 BOX2I textBox = GetTextBox( nullptr );
204
205 int textHeight = std::abs( textBox.GetHeight() );
206
207 if( GetTextAngle().IsHorizontal() )
208 textHeight += GetMarginTop() + GetMarginBottom();
209 else
210 textHeight += GetMarginLeft() + GetMarginRight();
211
212 // Only enforce minimum height. Width returns 0 so the user can freely shrink width
213 // (text rewraps) while height is constrained to fit the wrapped text content.
214 // GetTextBox returns dimensions in text-local coordinates. For 90/270 degree rotations,
215 // the text's natural height maps to screen x-axis.
216 EDA_ANGLE rotation = GetDrawRotation();
217
218 if( rotation == ANGLE_90 || rotation == ANGLE_270 )
219 return VECTOR2I( textHeight, 0 );
220
221 return VECTOR2I( 0, textHeight );
222}
223
224
226{
227 EDA_SHAPE::SetShape( aShape );
228 m_libShape = aShape;
229}
230
231
232std::vector<VECTOR2I> PCB_TEXTBOX::GetCorners() const
233{
235}
236
237
238std::vector<VECTOR2I> PCB_TEXTBOX::GetCornersInSequence( EDA_ANGLE angle ) const
239{
241 return EDA_SHAPE::GetCornersInSequence( angle );
242
243 const int left = std::min( m_start.x, m_end.x );
244 const int right = std::max( m_start.x, m_end.x );
245 const int top = std::min( m_start.y, m_end.y );
246 const int bottom = std::max( m_start.y, m_end.y );
247
248 const VECTOR2I center( ( left + right ) / 2, ( top + bottom ) / 2 );
249
250 std::vector<VECTOR2I> pts = {
251 VECTOR2I( left, top ),
252 VECTOR2I( right, top ),
253 VECTOR2I( right, bottom ),
254 VECTOR2I( left, bottom ),
255 };
256
257 angle.Normalize();
258
259 if( !angle.IsZero() )
260 {
261 for( VECTOR2I& p : pts )
262 RotatePoint( p, center, angle );
263 }
264
265 return pts;
266}
267
268
270{
271 EDA_ANGLE rotation = GetDrawRotation();
272
273 if( rotation == ANGLE_90 )
274 return VECTOR2I( GetStartX(), GetEndY() );
275 else if( rotation == ANGLE_180 )
276 return GetEnd();
277 else if( rotation == ANGLE_270 )
278 return VECTOR2I( GetEndX(), GetStartY() );
279 else
280 return GetStart();
281}
282
283
285{
286 EDA_ANGLE rotation = GetDrawRotation();
287
288 if( rotation == ANGLE_90 )
289 return VECTOR2I( GetEndX(), GetStartY() );
290 else if( rotation == ANGLE_180 )
291 return GetStart();
292 else if( rotation == ANGLE_270 )
293 return VECTOR2I( GetStartX(), GetEndY() );
294 else
295 return GetEnd();
296}
297
298
299void PCB_TEXTBOX::SetTop( int aVal )
300{
301 EDA_ANGLE rotation = GetDrawRotation();
302
303 if( rotation == ANGLE_90 || rotation == ANGLE_180 )
304 SetEndY( aVal );
305 else
306 SetStartY( aVal );
307}
308
309
311{
312 EDA_ANGLE rotation = GetDrawRotation();
313
314 if( rotation == ANGLE_90 || rotation == ANGLE_180 )
315 SetStartY( aVal );
316 else
317 SetEndY( aVal );
318}
319
320
321void PCB_TEXTBOX::SetLeft( int aVal )
322{
323 EDA_ANGLE rotation = GetDrawRotation();
324
325 if( rotation == ANGLE_180 || rotation == ANGLE_270 )
326 SetEndX( aVal );
327 else
328 SetStartX( aVal );
329}
330
331
332void PCB_TEXTBOX::SetRight( int aVal )
333{
334 EDA_ANGLE rotation = GetDrawRotation();
335
336 if( rotation == ANGLE_180 || rotation == ANGLE_270 )
337 SetStartX( aVal );
338 else
339 SetEndX( aVal );
340}
341
342
344{
345 if( const FOOTPRINT* fp = GetParentFootprint() )
346 {
347 EDA_ANGLE angle = m_libTextAngle.GetAngle() + fp->GetOrientation();
348 return angle.Normalized();
349 }
350
351 return m_libTextAngle.GetAngle();
352}
353
354
356{
357 EDA_ANGLE delta = aAngle.Normalized() - GetTextAngle();
359}
360
361
363{
364 return GetDrawPos( false );
365}
366
367
368VECTOR2I PCB_TEXTBOX::GetDrawPos( bool aIsFlipped ) const
369{
370 EDA_ANGLE drawAngle = GetDrawRotation();
371 std::vector<VECTOR2I> corners = GetCornersInSequence( drawAngle );
372 GR_TEXT_H_ALIGN_T horizontalAlignment = GetHorizJustify();
373 GR_TEXT_V_ALIGN_T verticalAlignment = GetVertJustify();
374 VECTOR2I textAnchor;
375 VECTOR2I offset;
376
377 // Calculate midpoints
378 VECTOR2I midTop = ( corners[0] + corners[1] ) / 2;
379 VECTOR2I midBottom = ( corners[3] + corners[2] ) / 2;
380 VECTOR2I midLeft = ( corners[0] + corners[3] ) / 2;
381 VECTOR2I midRight = ( corners[1] + corners[2] ) / 2;
382 VECTOR2I center = ( corners[0] + corners[1] + corners[2] + corners[3] ) / 4;
383
384 if( IsMirrored() != aIsFlipped )
385 {
386 switch( GetHorizJustify() )
387 {
388 case GR_TEXT_H_ALIGN_LEFT: horizontalAlignment = GR_TEXT_H_ALIGN_RIGHT; break;
389 case GR_TEXT_H_ALIGN_CENTER: horizontalAlignment = GR_TEXT_H_ALIGN_CENTER; break;
390 case GR_TEXT_H_ALIGN_RIGHT: horizontalAlignment = GR_TEXT_H_ALIGN_LEFT; break;
391 case GR_TEXT_H_ALIGN_INDETERMINATE: horizontalAlignment = GR_TEXT_H_ALIGN_INDETERMINATE; break;
392 }
393 }
394
395 wxASSERT_MSG( horizontalAlignment != GR_TEXT_H_ALIGN_INDETERMINATE
396 && verticalAlignment != GR_TEXT_V_ALIGN_INDETERMINATE,
397 wxS( "Indeterminate state legal only in dialogs. Horizontal and vertical alignment "
398 "must be set before calling PCB_TEXTBOX::GetDrawPos." ) );
399
400 if( horizontalAlignment == GR_TEXT_H_ALIGN_INDETERMINATE || verticalAlignment == GR_TEXT_V_ALIGN_INDETERMINATE )
401 {
402 return center;
403 }
404
405 if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT && verticalAlignment == GR_TEXT_V_ALIGN_TOP )
406 {
407 textAnchor = corners[0];
408 }
409 else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER && verticalAlignment == GR_TEXT_V_ALIGN_TOP )
410 {
411 textAnchor = midTop;
412 }
413 else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT && verticalAlignment == GR_TEXT_V_ALIGN_TOP )
414 {
415 textAnchor = corners[1];
416 }
417 else if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT && verticalAlignment == GR_TEXT_V_ALIGN_CENTER )
418 {
419 textAnchor = midLeft;
420 }
421 else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER && verticalAlignment == GR_TEXT_V_ALIGN_CENTER )
422 {
423 textAnchor = center;
424 }
425 else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT && verticalAlignment == GR_TEXT_V_ALIGN_CENTER )
426 {
427 textAnchor = midRight;
428 }
429 else if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM )
430 {
431 textAnchor = corners[3];
432 }
433 else if( horizontalAlignment == GR_TEXT_H_ALIGN_CENTER && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM )
434 {
435 textAnchor = midBottom;
436 }
437 else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT && verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM )
438 {
439 textAnchor = corners[2];
440 }
441
442 int marginLeft = GetMarginLeft();
443 int marginRight = GetMarginRight();
444 int marginTop = GetMarginTop();
445 int marginBottom = GetMarginBottom();
446
447 if( horizontalAlignment == GR_TEXT_H_ALIGN_LEFT )
448 offset.x = marginLeft;
449 else if( horizontalAlignment == GR_TEXT_H_ALIGN_RIGHT )
450 offset.x = -marginRight;
451
452 if( verticalAlignment == GR_TEXT_V_ALIGN_TOP )
453 offset.y = marginTop;
454 else if( verticalAlignment == GR_TEXT_V_ALIGN_BOTTOM )
455 offset.y = -marginBottom;
456
457 RotatePoint( offset, GetDrawRotation() );
458 return textAnchor + offset;
459}
460
461
462double PCB_TEXTBOX::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
463{
464 KIGFX::PCB_PAINTER& painter = static_cast<KIGFX::PCB_PAINTER&>( *aView->GetPainter() );
465 KIGFX::PCB_RENDER_SETTINGS& renderSettings = *painter.GetSettings();
466
467 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
468 {
469 // Hide shadow if the main layer is not shown
470 if( !aView->IsLayerVisibleCached( m_layer ) )
471 return LOD_HIDE;
472
473 // Hide shadow on dimmed tracks
474 if( renderSettings.GetHighContrast() )
475 {
476 if( m_layer != renderSettings.GetPrimaryHighContrastLayer() )
477 return LOD_HIDE;
478 }
479 }
480
481 return LOD_SHOW;
482}
483
484
485std::vector<int> PCB_TEXTBOX::ViewGetLayers() const
486{
489
490 return { GetLayer() };
491}
492
493
494wxString PCB_TEXTBOX::GetShownText( RESOLUTION_CONTEXT aContext, int aDepth ) const
495{
496 const FOOTPRINT* parentFootprint = GetParentFootprint();
497 const BOARD* board = GetBoard();
498
499 std::function<bool( wxString* )> resolver =
500 [&]( wxString* token ) -> bool
501 {
502 if( token->IsSameAs( wxT( "LAYER" ) ) )
503 {
504 *token = GetLayerName();
505 return true;
506 }
507
508 if( parentFootprint && parentFootprint->ResolveTextVar( token, aDepth + 1 ) )
509 return true;
510
511 if( board->ResolveTextVar( token, aDepth + 1 ) )
512 return true;
513
514 return false;
515 };
516
517 wxString text = EDA_TEXT::GetShownText( aContext, aDepth );
518
519 if( HasTextVars() && aContext != RAW_VALUE )
520 {
521 text = ResolveTextVars( text, &resolver, aDepth );
522 FinalizeTextVarExpansion( text, aContext );
523 }
524
525 KIFONT::FONT* font = GetDrawFont( nullptr );
526 EDA_ANGLE drawAngle = GetDrawRotation();
527 std::vector<VECTOR2I> corners = GetCornersInSequence( drawAngle );
528 int colWidth = ( corners[1] - corners[0] ).EuclideanNorm();
529
530 if( GetTextAngle().IsHorizontal() )
531 colWidth -= ( GetMarginLeft() + GetMarginRight() );
532 else
533 colWidth -= ( GetMarginTop() + GetMarginBottom() );
534
536
537 return text;
538}
539
540
541bool PCB_TEXTBOX::Matches( const EDA_SEARCH_DATA& aSearchData, void* aAuxData ) const
542{
543 return BOARD_ITEM::Matches( UnescapeString( GetText() ), aSearchData );
544}
545
546
547void PCB_TEXTBOX::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
548{
549 // Don't use GetShownText() here; we want to show the user the variable references
550 aList.emplace_back( _( "Text Box" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
551
552 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
553 aList.emplace_back( _( "Status" ), _( "Locked" ) );
554
555 aList.emplace_back( _( "Layer" ), GetLayerName() );
556 aList.emplace_back( _( "Mirror" ), IsMirrored() ? _( "Yes" ) : _( "No" ) );
557 aList.emplace_back( _( "Angle" ), wxString::Format( "%g", GetTextAngle().AsDegrees() ) );
558
559 aList.emplace_back( _( "Font" ), GetFont() ? GetFont()->GetName() : _( "Default" ) );
560
561 if( GetTextThickness() )
562 aList.emplace_back( _( "Text Thickness" ), aFrame->MessageTextFromValue( GetEffectiveTextPenWidth() ) );
563 else
564 aList.emplace_back( _( "Text Thickness" ), _( "Auto" ) );
565
566 aList.emplace_back( _( "Text Width" ), aFrame->MessageTextFromValue( GetTextWidth() ) );
567 aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( GetTextHeight() ) );
568
569 aList.emplace_back( _( "Box Width" ), aFrame->MessageTextFromValue( std::abs( GetEnd().x - GetStart().x ) ) );
570
571 aList.emplace_back( _( "Box Height" ), aFrame->MessageTextFromValue( std::abs( GetEnd().y - GetStart().y ) ) );
572
573 m_stroke.GetMsgPanelInfo( aFrame, aList );
574}
575
576
577void PCB_TEXTBOX::Move( const VECTOR2I& aMoveVector )
578{
579 PCB_SHAPE::Move( aMoveVector );
580 EDA_TEXT::Offset( aMoveVector );
581}
582
583
585{
587
588 if( const FOOTPRINT* fp = GetParentFootprint() )
589 {
590 const TRANSFORM_TRS& xf = fp->GetTransform();
591 return { KiROUND( libSize.x * std::abs( xf.GetScaleX() ) ), KiROUND( libSize.y * std::abs( xf.GetScaleY() ) ) };
592 }
593
594 return libSize;
595}
596
597
598void PCB_TEXTBOX::SetTextSize( VECTOR2I aNewSize, bool aEnforceMinTextSize )
599{
600 if( const FOOTPRINT* fp = GetParentFootprint() )
601 {
602 const TRANSFORM_TRS& xf = fp->GetTransform();
603 aNewSize = { KiROUND( aNewSize.x / std::abs( xf.GetScaleX() ) ),
604 KiROUND( aNewSize.y / std::abs( xf.GetScaleY() ) ) };
605 }
606
607 EDA_TEXT::SetTextSize( aNewSize, aEnforceMinTextSize );
608}
609
610
612{
613 int libThickness = EDA_TEXT::GetTextThickness();
614
615 if( const FOOTPRINT* fp = GetParentFootprint() )
616 {
617 const TRANSFORM_TRS& xf = fp->GetTransform();
618 const double factor = ( std::abs( xf.GetScaleX() ) + std::abs( xf.GetScaleY() ) ) * 0.5;
619 return KiROUND( libThickness * factor );
620 }
621
622 return libThickness;
623}
624
625
627{
628 if( const FOOTPRINT* fp = GetParentFootprint() )
629 {
630 const TRANSFORM_TRS& xf = fp->GetTransform();
631 const double factor = ( std::abs( xf.GetScaleX() ) + std::abs( xf.GetScaleY() ) ) * 0.5;
632 aWidth = KiROUND( aWidth / factor );
633 }
634
636}
637
638
639void PCB_TEXTBOX::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
640{
641 // Slide the axis-aligned box, rotation lives in the text angle.
642 const VECTOR2D oldCenter( ( m_start.x + m_end.x ) * 0.5, ( m_start.y + m_end.y ) * 0.5 );
643 VECTOR2D newCenter = oldCenter;
644 RotatePoint( newCenter, VECTOR2D( aRotCentre.x, aRotCentre.y ), aAngle );
645
646 const VECTOR2I delta( KiROUND( newCenter.x - oldCenter.x ), KiROUND( newCenter.y - oldCenter.y ) );
649
651
652 EDA_ANGLE newAbs = ( GetTextAngle() + aAngle ).Normalize();
653 EDA_TEXT::SetTextAngle( newAbs );
654
655 if( const FOOTPRINT* fp = GetParentFootprint() )
656 m_libTextAngle = newAbs - fp->GetOrientation();
657 else
658 m_libTextAngle = newAbs;
659}
660
661
662void PCB_TEXTBOX::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
663{
664 // the position and angle are mirrored, but not the text (or its justification)
665 PCB_SHAPE::Mirror( aCentre, aFlipDirection );
666
667 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
669 else
671
673}
674
675
676void PCB_TEXTBOX::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
677{
678 PCB_SHAPE::Flip( aCentre, aFlipDirection );
679
680 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
682 else
684
686
687 if( IsSideSpecific() )
689}
690
691
693{
694 if( const FOOTPRINT* fp = GetParentFootprint(); fp && GetLibraryShape() == SHAPE_T::RECTANGLE )
695 {
696 const TRANSFORM_TRS& xform = fp->GetTransform();
698
699 const VECTOR2I libCenter( ( m_libStart.x + m_libEnd.x ) / 2, ( m_libStart.y + m_libEnd.y ) / 2 );
700 const int libHalfW = std::abs( m_libEnd.x - m_libStart.x ) / 2;
701 const int libHalfH = std::abs( m_libEnd.y - m_libStart.y ) / 2;
702
703 const VECTOR2I newCenter = xform.Apply( libCenter );
704 const int newHalfW = std::abs( KiROUND( libHalfW * xform.GetScaleX() ) );
705 const int newHalfH = std::abs( KiROUND( libHalfH * xform.GetScaleY() ) );
706
707 EDA_SHAPE::SetStart( VECTOR2I( newCenter.x - newHalfW, newCenter.y - newHalfH ) );
708 EDA_SHAPE::SetEnd( VECTOR2I( newCenter.x + newHalfW, newCenter.y + newHalfH ) );
709 }
710 else
711 {
713 }
714
718}
719
720
722{
723 const FOOTPRINT* fp = GetParentFootprint();
724
725 // Only the axis-aligned rectangle case needs the textbox-specific inverse.
726 // Poly textboxes and standalone (non-FP) boxes use the base shape mapping.
727 if( !fp || GetShape() != SHAPE_T::RECTANGLE )
728 {
730 return;
731 }
732
733 const TRANSFORM_TRS& xform = fp->GetTransform();
734
735 const VECTOR2I boardCenter( ( m_start.x + m_end.x ) / 2, ( m_start.y + m_end.y ) / 2 );
736 const int boardHalfW = std::abs( m_end.x - m_start.x ) / 2;
737 const int boardHalfH = std::abs( m_end.y - m_start.y ) / 2;
738
739 const VECTOR2I libCenter = xform.InverseApply( boardCenter );
740 const int libHalfW = std::abs( KiROUND( boardHalfW / xform.GetScaleX() ) );
741 const int libHalfH = std::abs( KiROUND( boardHalfH / xform.GetScaleY() ) );
742
743 m_libStart = VECTOR2I( libCenter.x - libHalfW, libCenter.y - libHalfH );
744 m_libEnd = VECTOR2I( libCenter.x + libHalfW, libCenter.y + libHalfH );
745}
746
747
748void PCB_TEXTBOX::OnFootprintRescaled( double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I& aAnchor,
749 const EDA_ANGLE& aParentRotate )
750{
752}
753
754
756{
757 BOX2I bbox;
758
759 for( const VECTOR2I& pt : GetCorners() )
760 bbox.Merge( pt );
761
762 bbox.Inflate( std::max( 0, GetWidth() ) / 2 );
763 bbox.Normalize();
764
765 return bbox;
766}
767
768
769bool PCB_TEXTBOX::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
770{
771 BOX2I rect = GetBoundingBox();
772
773 rect.Inflate( aAccuracy );
774
775 return rect.Contains( aPosition );
776}
777
778
779bool PCB_TEXTBOX::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
780{
781 BOX2I rect = aRect;
782
783 rect.Inflate( aAccuracy );
784
785 if( aContained )
786 return rect.Contains( GetBoundingBox() );
787
788 return rect.Intersects( GetBoundingBox() );
789}
790
791
792bool PCB_TEXTBOX::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
793{
794 return PCB_SHAPE::HitTest( aPoly, aContained );
795}
796
797
798wxString PCB_TEXTBOX::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
799{
800 return wxString::Format( _( "PCB text box '%s' on %s" ),
802 GetLayerName() );
803}
804
805
810
811
813{
814 return new PCB_TEXTBOX( *this );
815}
816
817
819{
820 wxASSERT( aImage->Type() == PCB_TEXTBOX_T );
821
822 std::swap( *( (PCB_TEXTBOX*) this ), *( (PCB_TEXTBOX*) aImage ) );
823}
824
825
826std::shared_ptr<SHAPE> PCB_TEXTBOX::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash,
827 DRC_CONSTRAINT_T aUsage ) const
828{
829 std::shared_ptr<SHAPE_COMPOUND> shape = GetEffectiveTextShape();
830
831 if( PCB_SHAPE::GetStroke().GetWidth() >= 0 )
832 shape->AddShape( PCB_SHAPE::GetEffectiveShape( aLayer, aFlash, aUsage ) );
833
834 return shape;
835}
836
837
839{
840 // Build a PCB_SHAPE type POLYGON of the TEXTBOX, according to the box shape and the textbox rotation
842 dummy.SetWidth( GetBorderWidth() );
843 dummy.SetStroke( GetStroke() );
844 dummy.SetLayer( GetLayer() );
845 std::vector<VECTOR2I> poly = GetCorners(); // Already rotated
846 dummy.SetPolyPoints( poly );
847
848 return dummy;
849}
850
851
852void PCB_TEXTBOX::TransformTextToPolySet( SHAPE_POLY_SET& aBuffer, int aClearance, int aMaxError,
853 ERROR_LOC aErrorLoc ) const
854{
856 KIFONT::FONT* font = GetDrawFont( nullptr );
857 int penWidth = GetEffectiveTextPenWidth();
859 wxString shownText = GetShownText( FOR_CANVAS );
860
861 // The polygonal shape of a text can have many basic shapes, so combining these shapes can
862 // be very useful to create a final shape with a lot less vertices to speedup calculations.
863 // Simplify shapes is not usually always efficient, but in this case it is.
864 SHAPE_POLY_SET textShape;
865
866 CALLBACK_GAL callback_gal(
867 empty_opts,
868 // Stroke callback
869 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2 )
870 {
871 TransformOvalToPolygon( textShape, aPt1, aPt2, penWidth, aMaxError, aErrorLoc );
872 },
873 // Triangulation callback
874 [&]( const VECTOR2I& aPt1, const VECTOR2I& aPt2, const VECTOR2I& aPt3 )
875 {
876 textShape.NewOutline();
877
878 for( const VECTOR2I& point : { aPt1, aPt2, aPt3 } )
879 textShape.Append( point.x, point.y );
880 } );
881
882 if( auto* cache = GetRenderCache( font, shownText ) )
883 callback_gal.DrawGlyphs( *cache );
884 else
885 font->Draw( &callback_gal, shownText, GetDrawPos(), attrs, GetFontMetrics() );
886
887 textShape.Simplify();
888
889 if( IsKnockout() )
890 {
891 SHAPE_POLY_SET finalPoly;
892
893 TransformShapeToPolygon( finalPoly, GetLayer(), aClearance, aMaxError, aErrorLoc );
894
895 // A TEXTBOX can be rotated, but TransformShapeToPolygon does not handle the text rotation.
896 // so rotate the finalPoly by the text rotation
897 EDA_ANGLE angle = GetTextAngle();
898
899 if( angle != ANGLE_0 )
900 finalPoly.Rotate( angle, GetCenter() );
901
902 finalPoly.BooleanSubtract( textShape );
903
904 aBuffer.Append( finalPoly );
905 }
906 else
907 {
908 if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE )
909 {
910 if( aErrorLoc == ERROR_OUTSIDE )
911 aClearance += aMaxError;
912
913 textShape.Inflate( aClearance, CORNER_STRATEGY::ROUND_ALL_CORNERS, aMaxError, true );
914 }
915
916 aBuffer.Append( textShape );
917 }
918}
919
920
921double PCB_TEXTBOX::GetCoverageArea( int aTextMargin ) const
922{
923 SHAPE_POLY_SET poly;
924 TransformTextToPolySet( poly, aTextMargin, ARC_LOW_DEF, ERROR_INSIDE );
925 return polygonArea( poly );
926}
927
928
929void PCB_TEXTBOX::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError,
930 ERROR_LOC aErrorLoc, bool aIgnoreLineWidth ) const
931{
932 // Don't use PCB_SHAPE::TransformShapeToPolygon. We want to treat the textbox as filled even
933 // if there's no background colour.
934
935 int width = GetWidth() + ( 2 * aClearance );
936
938 {
939 std::vector<VECTOR2I> pts = GetRectCorners();
940
941 aBuffer.NewOutline();
942
943 for( const VECTOR2I& pt : pts )
944 aBuffer.Append( pt );
945
946 if( m_borderEnabled && width > 0 )
947 {
948 // Add in segments
949 TransformOvalToPolygon( aBuffer, pts[0], pts[1], width, aMaxError, aErrorLoc );
950 TransformOvalToPolygon( aBuffer, pts[1], pts[2], width, aMaxError, aErrorLoc );
951 TransformOvalToPolygon( aBuffer, pts[2], pts[3], width, aMaxError, aErrorLoc );
952 TransformOvalToPolygon( aBuffer, pts[3], pts[0], width, aMaxError, aErrorLoc );
953 }
954 }
955 else if( GetShape() == SHAPE_T::POLY ) // Non-cardinally-rotated rect
956 {
957 aBuffer.NewOutline();
958
959 const SHAPE_LINE_CHAIN& poly = GetPolyShape().Outline( 0 );
960
961 for( int ii = 0; ii < poly.PointCount(); ++ii )
962 aBuffer.Append( poly.GetPoint( ii ) );
963
964 if( m_borderEnabled && width > 0 )
965 {
966 for( int ii = 0; ii < poly.SegmentCount(); ++ii )
967 {
968 const SEG& seg = poly.GetSegment( ii );
969 TransformOvalToPolygon( aBuffer, seg.A, seg.B, width, aMaxError, aErrorLoc );
970 }
971 }
972 }
973}
974
975
977{
978 return m_borderEnabled;
979}
980
981
983{
984 m_borderEnabled = enabled;
985}
986
987
988void PCB_TEXTBOX::SetBorderWidth( const int aSize )
989{
990 m_stroke.SetWidth( aSize );
991}
992
993
994bool PCB_TEXTBOX::operator==( const BOARD_ITEM& aBoardItem ) const
995{
996 if( aBoardItem.Type() != Type() )
997 return false;
998
999 const PCB_TEXTBOX& other = static_cast<const PCB_TEXTBOX&>( aBoardItem );
1000
1001 return *this == other;
1002}
1003
1004
1005bool PCB_TEXTBOX::operator==( const PCB_TEXTBOX& aOther ) const
1006{
1007 return m_borderEnabled == aOther.m_borderEnabled && EDA_TEXT::operator==( aOther );
1008}
1009
1010
1011double PCB_TEXTBOX::Similarity( const BOARD_ITEM& aBoardItem ) const
1012{
1013 if( aBoardItem.Type() != Type() )
1014 return 0.0;
1015
1016 const PCB_TEXTBOX& other = static_cast<const PCB_TEXTBOX&>( aBoardItem );
1017
1018 double similarity = 1.0;
1019
1020 if( m_borderEnabled != other.m_borderEnabled )
1021 similarity *= 0.9;
1022
1023 if( GetMarginLeft() != other.GetMarginLeft() )
1024 similarity *= 0.9;
1025
1026 if( GetMarginTop() != other.GetMarginTop() )
1027 similarity *= 0.9;
1028
1029 if( GetMarginRight() != other.GetMarginRight() )
1030 similarity *= 0.9;
1031
1032 if( GetMarginBottom() != other.GetMarginBottom() )
1033 similarity *= 0.9;
1034
1035 similarity *= EDA_TEXT::Similarity( other );
1036
1037 return similarity;
1038}
1039
1040
1041static struct PCB_TEXTBOX_DESC
1042{
1044 {
1046
1047 if( lineStyleEnum.Choices().GetCount() == 0 )
1048 {
1049 lineStyleEnum.Map( LINE_STYLE::SOLID, _HKI( "Solid" ) )
1050 .Map( LINE_STYLE::DASH, _HKI( "Dashed" ) )
1051 .Map( LINE_STYLE::DOT, _HKI( "Dotted" ) )
1052 .Map( LINE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) )
1053 .Map( LINE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) );
1054 }
1055
1064
1065 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Shape" ) );
1066 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start X" ) );
1067 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start Y" ) );
1068 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "End X" ) );
1069 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "End Y" ) );
1070 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Width" ) );
1071 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Height" ) );
1072 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Width" ) );
1073 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Style" ) );
1074 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Filled" ) );
1075 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Color" ) );
1076 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_SHAPE ), _HKI( "Corner Radius" ) );
1077
1078 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Color" ) );
1079
1080 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( PCB_SHAPE ), _HKI( "Soldermask" ) );
1081 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( PCB_SHAPE ), _HKI( "Soldermask Margin Override" ) );
1082
1083 propMgr.AddProperty( new PROPERTY<PCB_TEXTBOX, bool, BOARD_ITEM>( _HKI( "Knockout" ),
1085 _HKI( "Text Properties" ) ).SetIsCopyable();
1086
1087 const wxString borderProps = _( "Border Properties" );
1088
1089 void ( PCB_TEXTBOX::*lineStyleSetter )( LINE_STYLE ) = &PCB_TEXTBOX::SetLineStyle;
1090 LINE_STYLE ( PCB_TEXTBOX::*lineStyleGetter )() const = &PCB_TEXTBOX::GetLineStyle;
1091
1092 propMgr.AddProperty( new PROPERTY<PCB_TEXTBOX, bool>( _HKI( "Border" ),
1094 borderProps ).SetIsCopyable();
1095
1096 propMgr.AddProperty( new PROPERTY_ENUM<PCB_TEXTBOX, LINE_STYLE>( _HKI( "Border Style" ),
1097 lineStyleSetter, lineStyleGetter ),
1098 borderProps ).SetIsCopyable();
1099
1100 propMgr.AddProperty( new PROPERTY<PCB_TEXTBOX, int>( _HKI( "Border Width" ),
1102 borderProps ).SetIsCopyable();
1103
1104 const wxString marginProps = _( "Margins" );
1105
1106 propMgr.AddProperty( new PROPERTY<PCB_TEXTBOX, int>( _HKI( "Margin Left" ),
1108 marginProps ).SetIsCopyable();
1109 propMgr.AddProperty( new PROPERTY<PCB_TEXTBOX, int>( _HKI( "Margin Top" ),
1111 marginProps ).SetIsCopyable();
1112 propMgr.AddProperty( new PROPERTY<PCB_TEXTBOX, int>( _HKI( "Margin Right" ),
1114 marginProps ).SetIsCopyable();
1115 propMgr.AddProperty( new PROPERTY<PCB_TEXTBOX, int>( _HKI( "Margin Bottom" ),
1117 marginProps ).SetIsCopyable();
1118
1119 propMgr.Mask( TYPE_HASH( PCB_TEXTBOX ), TYPE_HASH( EDA_TEXT ), _HKI( "Hyperlink" ) );
1120 }
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:55
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_OUTSIDE
@ ERROR_INSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
constexpr int ARC_LOW_DEF
Definition base_units.h:143
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
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:86
friend class BOARD
Definition board_item.h:593
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
void SetLocked(bool aLocked) override
Definition board_item.h:418
static double polygonArea(SHAPE_POLY_SET &aPolySet)
Area of aPolySet with every contour closed first, holes subtracted.
PCB_LAYER_ID m_layer
Definition board_item.h:586
virtual bool IsKnockout() const
Definition board_item.h:414
bool IsLocked() const override
virtual void SetIsKnockout(bool aKnockout)
Definition board_item.h:415
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
BOARD_ITEM_CONTAINER * GetParent() const
Definition board_item.h:266
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:553
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:143
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:594
constexpr size_type GetHeight() const
Definition box2.h:212
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:165
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:308
EDA_ANGLE Normalize()
Definition eda_angle.h:228
bool IsZero() const
Definition eda_angle.h:135
EDA_ANGLE Normalized() const
Definition eda_angle.h:241
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:98
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual bool Matches(const EDA_SEARCH_DATA &aSearchData, void *aAuxData) const
Compare the item against the search criteria in aSearchData.
Definition eda_item.h:484
EDA_ANGLE GetAngle() const
Definition eda_angle.h:533
SHAPE_T m_shape
Definition eda_shape.h:738
virtual void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:329
void SetStartX(int x)
Definition eda_shape.h:293
int GetStartY() const
Definition eda_shape.h:276
void SetEndY(int aY)
Definition eda_shape.h:336
int GetEndX() const
Definition eda_shape.h:327
void SetLineStyle(const LINE_STYLE aStyle)
void SetStartY(int y)
Definition eda_shape.h:286
SHAPE_POLY_SET & GetPolyShape()
virtual std::vector< VECTOR2I > GetCornersInSequence(EDA_ANGLE angle) const
SHAPE_T GetShape() const
Definition eda_shape.h:175
int GetEndY() const
Definition eda_shape.h:326
void SetEndX(int aX)
Definition eda_shape.h:343
VECTOR2I m_start
Definition eda_shape.h:752
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:325
LINE_STYLE GetLineStyle() const
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:275
virtual void SetShape(SHAPE_T aShape)
Definition eda_shape.h:174
std::vector< VECTOR2I > GetRectCorners() const
int GetStartX() const
Definition eda_shape.h:277
VECTOR2I m_end
Definition eda_shape.h:753
STROKE_PARAMS m_stroke
Definition eda_shape.h:739
virtual void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:279
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
virtual VECTOR2I GetTextSize() const
Definition eda_text.h:301
bool IsItalic() const
Definition eda_text.h:200
virtual void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
Definition eda_text.cpp:512
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
virtual int GetTextHeight() const
Definition eda_text.h:307
KIFONT::FONT * GetFont() const
Definition eda_text.h:286
void SetAttributes(const EDA_TEXT &aSrc, bool aSetPosition=true)
Set the text attributes from another instance.
Definition eda_text.cpp:394
void SetMirrored(bool isMirrored)
Definition eda_text.cpp:354
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:683
virtual EDA_ANGLE GetDrawRotation() const
Definition eda_text.h:425
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:754
virtual wxString GetShownText(RESOLUTION_CONTEXT aContext, int aDepth=0) const
Return the string actually shown after processing of the base text.
Definition eda_text.h:128
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition eda_text.cpp:378
virtual void Offset(const VECTOR2I &aOffset)
Definition eda_text.cpp:575
virtual int GetTextWidth() const
Definition eda_text.h:304
GR_TEXT_H_ALIGN_T GetHorizJustify() const
Definition eda_text.h:239
virtual KIFONT::FONT * GetDrawFont(const RENDER_SETTINGS *aSettings) const
Definition eda_text.cpp:647
bool HasTextVars() const
Indicates the ShownText has text var references which need to be processed.
Definition eda_text.h:139
EDA_TEXT(const EDA_IU_SCALE &aIuScale, const wxString &aText=wxEmptyString)
Definition eda_text.cpp:98
virtual void ClearBoundingBoxCache()
Definition eda_text.cpp:675
double Similarity(const EDA_TEXT &aOther) const
virtual void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition eda_text.cpp:250
virtual void ClearRenderCache()
Definition eda_text.cpp:669
const TEXT_ATTRIBUTES & GetAttributes() const
Definition eda_text.h:270
bool IsMirrored() const
Definition eda_text.h:229
int GetEffectiveTextPenWidth(int aDefaultPenWidth=0) const
The EffectiveTextPenWidth uses the text thickness if > 1 or aDefaultPenWidth.
Definition eda_text.cpp:427
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:215
void SetKeepUpright(bool aKeepUpright)
Definition eda_text.cpp:386
GR_TEXT_V_ALIGN_T GetVertJustify() const
Definition eda_text.h:242
virtual int GetTextThickness() const
Definition eda_text.h:159
virtual void SetText(const wxString &aText)
Definition eda_text.cpp:236
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
Definition eda_text.cpp:268
void SetItalic(bool aItalic)
Set the text to be italic - this will also update the font if needed.
Definition eda_text.cpp:290
bool operator==(const EDA_TEXT &aRhs) const
Definition eda_text.h:444
void SetMultilineAllowed(bool aAllow)
Definition eda_text.cpp:362
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition eda_text.cpp:370
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:789
static ENUM_MAP< T > & Instance()
Definition property.h:783
wxPGChoices & Choices()
Definition property.h:834
const TRANSFORM_TRS & GetTransform() const
Definition footprint.h:452
bool ResolveTextVar(wxString *aToken, int aDepth=0) const
Resolve any references to system tokens supported by the component.
FONT is an abstract base class for both outline and stroke fonts.
Definition font.h:94
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:240
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:609
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:84
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:441
PAINTER * GetPainter() const
Return the painter object used by the view for drawing VIEW_ITEM objects.
Definition view.h:227
Definition kiid.h:46
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:383
virtual void syncLibCoords()
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition pcb_shape.h:78
PCB_SHAPE(BOARD_ITEM *aParent, KICAD_T aItemType, SHAPE_T aShapeType)
SHAPE_T m_libShape
Definition pcb_shape.h:401
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:160
void SetPosition(const VECTOR2I &aPos) override
Definition pcb_shape.h:75
SHAPE_T GetLibraryShape() const
Definition pcb_shape.h:231
void SetEnd(const VECTOR2I &aEnd) override
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) const override
Make a set of SHAPE objects representing the PCB_SHAPE.
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:193
void Normalize() override
Perform any normalization required after a user rotate and/or flip.
VECTOR2I m_libStart
Definition pcb_shape.h:382
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
Tests whether the border is disabled, as configured by the stroke.
double GetCoverageArea(int aTextMargin) const override
Return the board area this item covers, used to rank candidates under the cursor so a click on a smal...
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)
Disables the border, this is done by changing the stroke internally.
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
Convert the text to a polygonSet describing the actual character strokes (one per segment).
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
Create a duplicate of this item with linked list members set to NULL.
void SetShape(SHAPE_T aShape) override
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)
void SetLeft(int aVal) override
int GetMarginLeft() const
EDA_ORIENTATION m_libTextAngle
void SetMarginLeft(int aLeft)
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
void SetMarginBottom(int aBottom)
std::vector< VECTOR2I > GetCornersInSequence(EDA_ANGLE angle) const override
int GetMarginRight() const
void SetRight(int aVal) override
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
void SetTop(int aVal) override
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
int GetMarginTop() const
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)
void Move(const VECTOR2I &aMoveVector) override
Move this object.
int GetLegacyTextMargin() const
void syncLibCoords() override
void SetBottom(int aVal) override
PCB_SHAPE GetPolygonalBoxShape() const
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
wxString GetShownText(RESOLUTION_CONTEXT aContext, int aDepth=0) const override
Return the string actually shown after processing of the base text.
std::vector< VECTOR2I > GetCorners() const override
Return 4 corners for a rectangle or rotated rectangle (stored as a poly).
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
PROPERTY_BASE & SetIsCopyable(bool aIsCopyable=true)
Definition property.h:359
Provide class metadata.
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 Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
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.
EDA_ORIENTATION m_Angle
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().
void FinalizeTextVarExpansion(wxString &aText, RESOLUTION_CONTEXT aContext)
Definition common.cpp:88
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:333
RESOLUTION_CONTEXT
Definition common.h:89
@ FOR_GUI
Definition common.h:91
@ FOR_CANVAS
Definition common.h:90
@ RAW_VALUE
Definition common.h:96
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.
DRC_CONSTRAINT_T
Definition drc_rule.h:49
static std::string ToStdString(const wxString &aStr)
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:448
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:450
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:453
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:452
#define PCB_EDIT_FRAME_NAME
SHAPE_T
Definition eda_shape.h:54
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
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:829
@ 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 void PackCustomProperties(google::protobuf::RepeatedPtrField< types::CustomProperty > *aOutput, const EDA_ITEM &aItem)
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)
KICOMMON_API void UnpackCustomProperties(const google::protobuf::RepeatedPtrField< types::CustomProperty > &aInput, EDA_ITEM &aItem)
void PackTextAttributes(types::TextAttributes &aOutput, const TEXT_ATTRIBUTES &aInput, const EDA_IU_SCALE &aScale)
void UnpackTextAttributes(TEXT_ATTRIBUTES &aOutput, const types::TextAttributes &aInput, const EDA_IU_SCALE &aScale)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:437
#define _HKI(x)
Definition page_info.cpp:40
static struct PCB_TEXTBOX_DESC _PCB_TEXTBOX_DESC
#define TYPE_HASH(x)
Macro to generate unique identifier for a type.
Definition property.h:74
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names.
std::vector< FAB_LAYER_COLOR > dummy
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:227
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:85
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707