KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_barcode.cpp
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2020 Thomas Pointhuber <[email protected]>
5 * Copyright (C) 2020 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <core/type_helpers.h>
22#include <bitmaps.h>
23#include <gr_basic.h>
24#include <macros.h>
25#include <pcb_edit_frame.h>
26#include <richio.h>
27#include <trigo.h>
28
29#include <base_units.h>
30#include <api/api_enums.h>
31#include <api/board/board_types.pb.h>
32#include <pcb_barcode.h>
33#include <board.h>
34#include <footprint.h>
36#include <pcb_text.h>
37#include <view/view.h>
38#include <math/util.h> // for KiROUND
40#include <wx/log.h>
41#include <pgm_base.h>
44#include <scoped_set_reset.h>
45#include <stdexcept>
46#include <utility>
47#include <algorithm>
48#include <api/api_utils.h>
49#include <footprint.h>
50
51#include <backend/zint.h>
53#include <hash.h>
54#include <google/protobuf/any.pb.h>
55#include <properties/property.h>
57
58constexpr int ECI_UTF8 = 26;
59
61 BOARD_ITEM( aParent, PCB_BARCODE_T ),
62 m_width( pcbIUScale.mmToIU( 40 ) ),
63 m_height( pcbIUScale.mmToIU( 40 ) ),
64 m_libPos( 0, 0 ),
65 m_text( this ),
69{
71}
72
73
77
78
80 BOARD_ITEM( aOther ),
81 m_width( aOther.m_width ),
82 m_height( aOther.m_height ),
83 m_libPos( aOther.m_libPos ),
84 m_margin( aOther.m_margin ),
85 m_text( aOther.m_text ),
86 m_kind( aOther.m_kind ),
87 m_libAngle( aOther.m_libAngle ),
89{
90 m_text.SetParent( this );
91}
92
93
95{
96 if( this != &aOther )
97 {
98 BOARD_ITEM::operator=( aOther );
99
100 m_width = aOther.m_width;
101 m_height = aOther.m_height;
102 m_libPos = aOther.m_libPos;
103 m_margin = aOther.m_margin;
104 m_text = aOther.m_text;
105 m_kind = aOther.m_kind;
106 m_libAngle = aOther.m_libAngle;
108
109 m_cache.reset();
110
111 m_text.SetParent( this );
112 }
113
114 return *this;
115}
116
117
119{
120 VECTOR2I delta = aPos - GetPosition();
121 Move( delta );
122}
123
124
126{
127 if( const FOOTPRINT* fp = GetParentFootprint() )
128 return fp->GetTransform().Apply( m_libPos );
129
130 return m_libPos;
131}
132
133
135{
136 if( const FOOTPRINT* fp = GetParentFootprint() )
137 return ( m_libAngle + fp->GetOrientation() ).GetAngle();
138
139 return m_libAngle.GetAngle();
140}
141
142
143void PCB_BARCODE::SetText( const wxString& aNewText )
144{
145 m_text.SetText( aNewText );
146}
147
148
149wxString PCB_BARCODE::GetText() const
150{
151 return m_text.GetText();
152}
153
154
156{
157 return m_text.GetShownText( aContext );
158}
159
160
161void PCB_BARCODE::Serialize( google::protobuf::Any& aContainer ) const
162{
163 using namespace kiapi::board::types;
164
165 Barcode barcode;
166
167 barcode.mutable_id()->set_value( m_Uuid.AsStdString() );
168 barcode.set_text( GetText().ToUTF8() );
169
170 switch( m_kind )
171 {
172 case BARCODE_T::CODE_39: barcode.set_kind( BK_CODE_39 ); break;
173 case BARCODE_T::CODE_128: barcode.set_kind( BK_CODE_128 ); break;
174 case BARCODE_T::DATA_MATRIX: barcode.set_kind( BK_DATA_MATRIX ); break;
175 case BARCODE_T::QR_CODE: barcode.set_kind( BK_QR_CODE ); break;
176 case BARCODE_T::MICRO_QR_CODE: barcode.set_kind( BK_MICRO_QR_CODE ); break;
177 }
178
179 switch( m_errorCorrection )
180 {
181 case BARCODE_ECC_T::L: barcode.set_error_correction( BEC_L ); break;
182 case BARCODE_ECC_T::M: barcode.set_error_correction( BEC_M ); break;
183 case BARCODE_ECC_T::Q: barcode.set_error_correction( BEC_Q ); break;
184 case BARCODE_ECC_T::H: barcode.set_error_correction( BEC_H ); break;
185 }
186
187 kiapi::common::PackVector2( *barcode.mutable_position(), GetPosition() );
188 barcode.mutable_orientation()->set_value_degrees( GetAngle().AsDegrees() );
189
190 if( FOOTPRINT* parent = GetParentFootprint() )
191 barcode.mutable_parent()->set_value( parent->m_Uuid.AsStdString() );
192 else if( const BOARD* board = GetBoard() )
193 barcode.mutable_parent()->set_value( board->m_Uuid.AsStdString() );
194
195 barcode.set_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( GetLayer() ) );
196
197 barcode.mutable_width()->set_value_nm( m_width );
198 barcode.mutable_height()->set_value_nm( m_height );
199
200 barcode.set_show_text( m_text.IsVisible() );
201 barcode.mutable_text_height()->set_value_nm( m_text.GetTextHeight() );
202
203 barcode.set_knockout( IsKnockout() );
204 kiapi::common::PackVector2( *barcode.mutable_knockout_margin(), m_margin );
205
206 barcode.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED
207 : kiapi::common::types::LockedState::LS_UNLOCKED );
208
209 kiapi::common::PackCustomProperties( barcode.mutable_custom_properties(), *this );
210 aContainer.PackFrom( barcode );
211}
212
213
214bool PCB_BARCODE::Deserialize( const google::protobuf::Any& aContainer )
215{
216 using namespace kiapi::board::types;
217
218 Barcode barcode;
219
220 if( !aContainer.UnpackTo( &barcode ) )
221 return false;
222
223 SetUuidDirect( KIID( barcode.id().value() ) );
224 SetText( wxString::FromUTF8( barcode.text() ) );
225
226 switch( barcode.kind() )
227 {
228 case BK_CODE_39: SetKind( BARCODE_T::CODE_39 ); break;
229 case BK_CODE_128: SetKind( BARCODE_T::CODE_128 ); break;
230 case BK_DATA_MATRIX: SetKind( BARCODE_T::DATA_MATRIX ); break;
231 case BK_QR_CODE: SetKind( BARCODE_T::QR_CODE ); break;
232 case BK_MICRO_QR_CODE: SetKind( BARCODE_T::MICRO_QR_CODE ); break;
233 default: SetKind( BARCODE_T::QR_CODE ); break;
234 }
235
236 switch( barcode.error_correction() )
237 {
238 case BEC_L: SetErrorCorrection( BARCODE_ECC_T::L ); break;
239 case BEC_M: SetErrorCorrection( BARCODE_ECC_T::M ); break;
240 case BEC_Q: SetErrorCorrection( BARCODE_ECC_T::Q ); break;
241 case BEC_H: SetErrorCorrection( BARCODE_ECC_T::H ); break;
242 default: SetErrorCorrection( BARCODE_ECC_T::L ); break;
243 }
244
245 SetPosition( kiapi::common::UnpackVector2( barcode.position() ) );
246
247 EDA_ANGLE newAngle( barcode.orientation().value_degrees(), DEGREES_T );
248
249 if( const FOOTPRINT* fp = GetParentFootprint() )
250 m_libAngle = newAngle - fp->GetOrientation();
251 else
252 m_libAngle = newAngle;
253
255
256 m_width = barcode.width().value_nm();
257 m_height = barcode.height().value_nm();
258
259 m_text.SetLayer( m_layer );
260 m_text.SetVisible( barcode.show_text() );
261
262 if( barcode.has_text_height() )
263 {
264 int textSize = std::max( 1, static_cast<int>( barcode.text_height().value_nm() ) );
265 m_text.SetTextSize( VECTOR2I( textSize, textSize ) );
266 m_text.SetTextThickness( std::max( 1, GetPenSizeForNormal( m_text.GetTextHeight() ) ) );
267 }
268
269 m_margin = kiapi::common::UnpackVector2( barcode.knockout_margin() );
270 BOARD_ITEM::SetIsKnockout( barcode.knockout() );
271 SetLocked( barcode.locked() == kiapi::common::types::LockedState::LS_LOCKED );
272
273 kiapi::common::UnpackCustomProperties( barcode.custom_properties(), *this );
274
276
277 return true;
278}
279
280
282{
283 m_layer = aLayer;
284 m_text.SetLayer( aLayer );
286}
287
288
289void PCB_BARCODE::SetTextSize( int aTextSize )
290{
291 m_text.SetTextSize( VECTOR2I( std::max( 1, aTextSize ), std::max( 1, aTextSize ) ) );
292 m_text.SetTextThickness( std::max( 1, GetPenSizeForNormal( m_text.GetTextHeight() ) ) );
294}
295
296
298{
299 return m_text.GetTextHeight();
300}
301
302
303void PCB_BARCODE::Move( const VECTOR2I& offset )
304{
305 if( const FOOTPRINT* fp = GetParentFootprint() )
306 {
307 const TRANSFORM_TRS& xform = fp->GetTransform();
308 VECTOR2I libOffset = xform.InverseApply( offset ) - xform.InverseApply( VECTOR2I( 0, 0 ) );
309 m_libPos += libOffset;
310 }
311 else
312 {
313 m_libPos += offset;
314 }
315
316 // m_text is intentionally not moved, ComputeTextPoly repositions it
317 // under the symbol on the next AssembleBarcode.
318}
319
320
321void PCB_BARCODE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
322{
323 VECTOR2I boardPos = GetPosition();
324 RotatePoint( boardPos, aRotCentre, aAngle );
325
326 if( const FOOTPRINT* fp = GetParentFootprint() )
327 m_libPos = fp->GetTransform().InverseApply( boardPos );
328 else
329 m_libPos = boardPos;
330
331 m_libAngle += aAngle;
332
334}
335
336
337void PCB_BARCODE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
338{
339 if( const FOOTPRINT* fp = GetParentFootprint() )
340 {
341 const VECTOR2I libAxis = fp->GetTransform().InverseApply( aCentre );
342
343 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
344 m_libPos.x = 2 * libAxis.x - m_libPos.x;
345 else
346 m_libPos.y = 2 * libAxis.y - m_libPos.y;
347
348 // Reflect the library-frame angle (rotation-independent).
349 if( aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
351 else
353
356 return;
357 }
358
359 VECTOR2I boardPos = GetPosition();
360 MIRROR( boardPos, aCentre, aFlipDirection );
361 m_libPos = boardPos;
362
363 if( aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
365 else
367
370}
371
372
373void PCB_BARCODE::OnFootprintRescaled( double /* aRatioX */, double /* aRatioY */, double /* aLinearFactor */,
374 const VECTOR2I& /* aAnchor */, const EDA_ANGLE& /* aParentRotate */ )
375{
376 // Board values derive on read, AssembleBarcode rebuilds on next access.
377}
378
379
380void PCB_BARCODE::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings, bool aCheckSide )
381{
382 SetTextSize( settings.GetTextSize( GetLayer() ).y );
383}
384
385
387{
388 const VECTOR2I pos = GetPosition();
389 const EDA_ANGLE angle = GetAngle();
390
391 return hash_val( GetShownText( FOR_CANVAS ), m_width, m_height, pos.x, pos.y, m_margin.x, m_margin.y,
392 static_cast<int>( m_kind ), angle.AsDegrees(), static_cast<int>( m_errorCorrection ),
393 m_text.IsVisible(), m_text.GetTextHeight(), IsKnockout(), static_cast<int>( m_layer ) );
394}
395
396
398{
399 size_t key = computeCacheKey();
400
401 if( m_cache && m_cache->keyHash == key )
402 return;
403
404 if( !m_cache )
405 m_cache = std::make_unique<PCB_BARCODE_CACHE>();
406
408
409 const VECTOR2I pos = GetPosition();
410
411 // Scale the symbol polygon to the desired barcode width/height and center it at pos.
412 rescaleSymbolPoly( pos - VECTOR2I( m_width / 2, m_height / 2 ), pos + VECTOR2I( m_width / 2, m_height / 2 ) );
413
415
416 // Build full m_poly from symbol + optional text, then apply knockout if requested
417 m_cache->poly.RemoveAllContours();
418 m_cache->poly.Append( m_cache->symbolPoly );
419
420 if( m_text.IsVisible() && m_cache->textPoly.OutlineCount() )
421 m_cache->poly.Append( m_cache->textPoly );
422
423 m_cache->poly.Fracture();
424
425 if( IsKnockout() )
426 {
427 // Enforce minimum margin: at least 10% of the smallest side of the barcode, rounded up
428 // to the nearest 0.1 mm. Use this as a lower bound for both axes.
429 int minSide = std::min( m_width, m_height );
430 int tenPercent = ( minSide + 9 ) / 10; // ceil(minSide * 0.1)
431 int step01mm = std::max( 1, pcbIUScale.mmToIU( 0.1 ) );
432 int tenPercentRounded = ( ( tenPercent + step01mm - 1 ) / step01mm ) * step01mm;
433
434 // Build inversion rectangle based on the local bbox of the current combined geometry
435 BOX2I bbox = m_cache->poly.BBox();
436 bbox.Inflate( std::max( m_margin.x, tenPercentRounded ), std::max( m_margin.y, tenPercentRounded ) );
437
438 SHAPE_LINE_CHAIN rect;
439 rect.Append( bbox.GetLeft(), bbox.GetTop() );
440 rect.Append( bbox.GetRight(), bbox.GetTop() );
441 rect.Append( bbox.GetRight(), bbox.GetBottom() );
442 rect.Append( bbox.GetLeft(), bbox.GetBottom() );
443 rect.SetClosed( true );
444
446 ko.AddOutline( rect );
447 ko.BooleanSubtract( m_cache->poly );
448 ko.Fracture();
449 m_cache->poly = std::move( ko );
450 }
451
453 m_cache->poly.Mirror( pos, FLIP_DIRECTION::LEFT_RIGHT );
454
455 const EDA_ANGLE angle = GetAngle();
456
457 if( !angle.IsZero() )
458 m_cache->poly.Rotate( angle, pos );
459
460 m_cache->poly.CacheTriangulation();
461 m_cache->bbox = m_cache->poly.BBox();
462 m_cache->keyHash = key;
463}
464
465
467{
468 if( !m_cache )
469 m_cache = std::make_unique<PCB_BARCODE_CACHE>();
470
471 m_cache->textPoly.RemoveAllContours();
472
473 if( !m_text.IsVisible() )
474 return;
475
476 SHAPE_POLY_SET textPoly;
477 m_text.TransformTextToPolySet( textPoly, 0, GetMaxError(), ERROR_INSIDE );
478
479 if( textPoly.OutlineCount() == 0 )
480 return;
481
482 // PCB_TEXT::GetDrawRotation now includes the parent FP orientation, so
483 // TransformTextToPolySet rendered the glyphs already rotated by the FP
484 // angle. The final AssembleBarcode rotation (m_cache->poly.Rotate by
485 // GetAngle = lib_angle + FP_orient) would then rotate the glyphs a
486 // second time, producing twice the intended visual rotation. Undo the
487 // m_text-side rotation here so the glyph-orientation contribution is
488 // only the lib_angle, and the final poly rotation applies the FP-orient
489 // part uniformly with the symbol.
490 if( const FOOTPRINT* fp = GetParentFootprint() )
491 {
492 EDA_ANGLE fpOrient = fp->GetOrientation();
493
494 if( !fpOrient.IsZero() )
495 textPoly.Rotate( -fpOrient, m_text.GetTextPos() );
496 }
497
498 if( m_cache->symbolPoly.OutlineCount() == 0 )
499 return;
500
501 BOX2I textBBox = textPoly.BBox();
502 BOX2I symbolBBox = m_cache->symbolPoly.BBox();
503 VECTOR2I textPos;
504 int textOffset = pcbIUScale.mmToIU( 1 );
505 textPos.x = symbolBBox.GetCenter().x - textBBox.GetCenter().x;
506 textPos.y = symbolBBox.GetBottom() - textBBox.GetTop() + textOffset;
507
508 textPoly.Move( textPos );
509
510 m_cache->textPoly = std::move( textPoly );
511 m_cache->textPoly.CacheTriangulation();
512}
513
514
516{
517 if( !m_cache )
518 m_cache = std::make_unique<PCB_BARCODE_CACHE>();
519
520 m_cache->symbolPoly.RemoveAllContours();
521 m_cache->lastError.clear();
522
523 std::unique_ptr<zint_symbol, decltype( &ZBarcode_Delete )> symbol( ZBarcode_Create(), &ZBarcode_Delete );
524
525 if( !symbol )
526 {
527 wxLogError( wxT( "Zint: failed to allocate symbol" ) );
528 return;
529 }
530
531 symbol->input_mode = UNICODE_MODE;
532 symbol->show_hrt = 0; // do not show HRT
533
534 switch( m_kind )
535 {
537 symbol->symbology = BARCODE_CODE39;
538 break;
540 symbol->symbology = BARCODE_CODE128;
541 break;
543 symbol->symbology = BARCODE_QRCODE;
544 symbol->option_1 = to_underlying( m_errorCorrection );
545 break;
547 symbol->symbology = BARCODE_MICROQR;
548 symbol->option_1 = to_underlying( m_errorCorrection );
549 break;
551 symbol->symbology = BARCODE_DATAMATRIX;
552 break;
553 default:
554 wxLogError( wxT( "Zint: invalid barcode type" ) );
555 return;
556 }
557
558 wxString text = GetShownText( FOR_CANVAS );
559 wxScopedCharBuffer utf8Text = text.ToUTF8();
560 size_t length = utf8Text.length();
561 unsigned char* dataPtr = reinterpret_cast<unsigned char*>( utf8Text.data() );
562
563 if( text.empty() )
564 return;
565
566 if( ( m_kind == BARCODE_T::QR_CODE || m_kind == BARCODE_T::DATA_MATRIX ) && !text.IsAscii() )
567 {
568 symbol->eci = ECI_UTF8;
569 }
570
571 if( ZBarcode_Encode( symbol.get(), dataPtr, length ) >= ZINT_ERROR )
572 {
573 if( !text.IsAscii() )
574 {
575 m_cache->lastError = _( "This barcode type does not support international "
576 "characters. Use QR Code or Data Matrix instead." );
577 }
578 else
579 {
580 m_cache->lastError = wxString::FromUTF8( symbol->errtxt );
581 }
582 return;
583 }
584
585 if( ZBarcode_Buffer_Vector( symbol.get(), 0 ) >= ZINT_ERROR )
586 {
587 m_cache->lastError = wxString::FromUTF8( symbol->errtxt );
588 return;
589 }
590
591 for( zint_vector_rect* rect = symbol->vector->rectangles; rect != nullptr; rect = rect->next )
592 {
593 // Round using absolute edges to avoid cumulative rounding drift across modules.
594 int x1 = KiROUND( rect->x * symbol->scale );
595 int x2 = KiROUND( ( rect->x + rect->width ) * symbol->scale );
596 int y1 = KiROUND( rect->y * symbol->scale );
597 int y2 = KiROUND( ( rect->y + rect->height ) * symbol->scale );
598
599 SHAPE_LINE_CHAIN shapeline;
600 shapeline.Append( x1, y1 );
601 shapeline.Append( x2, y1 );
602 shapeline.Append( x2, y2 );
603 shapeline.Append( x1, y2 );
604 shapeline.SetClosed( true );
605
606 m_cache->symbolPoly.AddOutline( shapeline );
607 }
608
609 for( zint_vector_hexagon* hex = symbol->vector->hexagons; hex != nullptr; hex = hex->next )
610 {
611 // Compute vertices from center using minimal-diameter (inscribed circle) radius.
612 double r = hex->diameter / 2.0; // minimal radius
613 double cx = hex->x;
614 double cy = hex->y;
615
616 // Base orientation has apex at top; hex->rotation rotates by 0/90/180/270 degrees.
617 double baseAngles[6] = { 90.0, 30.0, -30.0, -90.0, -150.0, 150.0 };
618 double rot = static_cast<double>( hex->rotation );
619
620 SHAPE_LINE_CHAIN poly;
621
622 for( int k = 0; k < 6; ++k )
623 {
624 double ang = ( baseAngles[k] + rot ) * M_PI / 180.0;
625 int vx = KiROUND( cx + r * cos( ang ) );
626 int vy = KiROUND( cy + r * sin( ang ) );
627 poly.Append( vx, vy );
628 }
629 poly.SetClosed( true );
630
631 m_cache->symbolPoly.AddOutline( poly );
632 }
633
634 // Set the position of the barcode to the center of the symbol polygon
635 if( m_cache->symbolPoly.OutlineCount() > 0 )
636 {
637 VECTOR2I pos = m_cache->symbolPoly.BBox().GetCenter();
638 m_cache->symbolPoly.Move( -pos );
639 }
640
641 m_cache->symbolPoly.CacheTriangulation();
642}
643
644
645void PCB_BARCODE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
646{
647 FOOTPRINT* parentFP = GetParentFootprint();
648
649 if( parentFP && aFrame->GetName() == PCB_EDIT_FRAME_NAME )
650 aList.emplace_back( _( "Footprint" ), parentFP->GetReference() );
651
652 aList.emplace_back( _( "Barcode" ), ENUM_MAP<BARCODE_T>::Instance().ToString( m_kind ) );
653
654 // Don't use GetShownText() here; we want to show the user the variable references
655 aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
656
657 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
658 aList.emplace_back( _( "Status" ), _( "Locked" ) );
659
660 aList.emplace_back( _( "Layer" ), GetLayerName() );
661
662 aList.emplace_back( _( "Angle" ), wxString::Format( wxT( "%g" ), GetAngle().AsDegrees() ) );
663
664 aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( m_text.GetTextHeight() ) );
665}
666
667
668bool PCB_BARCODE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
669{
671
672 if( !GetBoundingBox().Contains( aPosition ) )
673 return false;
674
675 SHAPE_POLY_SET hulls;
676
678
679 return hulls.Collide( aPosition );
680}
681
682
683bool PCB_BARCODE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
684{
685 BOX2I arect = aRect;
686 arect.Inflate( aAccuracy );
687
688 BOX2I rect = GetBoundingBox();
689
690 if( aAccuracy )
691 rect.Inflate( aAccuracy );
692
693 if( aContained )
694 return arect.Contains( rect );
695
696 return arect.Intersects( rect );
697}
698
699
700void PCB_BARCODE::rescaleSymbolPoly( const VECTOR2I& aTopLeft, const VECTOR2I& aBotRight ) const
701{
702 // Rescale only the symbol polygon to the requested rectangle
703 BOX2I bbox = m_cache->symbolPoly.BBox();
704 int oldW = bbox.GetWidth();
705 int oldH = bbox.GetHeight();
706
707 VECTOR2I newPosition = ( aTopLeft + aBotRight ) / 2;
708 int newW = aBotRight.x - aTopLeft.x;
709 int newH = aBotRight.y - aTopLeft.y;
710 // Guard against zero/negative sizes from interactive edits; enforce a tiny minimum
711 int minIU = std::max( 1, pcbIUScale.mmToIU( 0.01 ) );
712 newW = std::max( newW, minIU );
713 newH = std::max( newH, minIU );
714
715 double scaleX = oldW ? static_cast<double>( newW ) / oldW : 1.0;
716 double scaleY = oldH ? static_cast<double>( newH ) / oldH : 1.0;
717
718 VECTOR2I oldCenter = bbox.GetCenter();
719 m_cache->symbolPoly.Scale( scaleX, scaleY, oldCenter );
720
721 // After scaling, move the symbol polygon to be centered at the new position
722 VECTOR2I newCenter = m_cache->symbolPoly.BBox().GetCenter();
723 VECTOR2I delta = newPosition - newCenter;
724
725 if( delta != VECTOR2I( 0, 0 ) )
726 m_cache->symbolPoly.Move( delta );
727}
728
729
731{
733 return m_cache->bbox;
734}
735
736
737wxString PCB_BARCODE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
738{
739 return wxString::Format( _( "Barcode '%s' on %s" ), GetText(), GetLayerName() );
740}
741
742
747
748
750{
752 return m_cache->bbox;
753}
754
755
756double PCB_BARCODE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
757{
758 // Hide the locked shadow when the barcode's own layer is not shown
759 if( aLayer == LAYER_LOCKED_ITEM_SHADOW && !aView->IsLayerVisibleCached( m_layer ) )
760 return LOD_HIDE;
761
762 return LOD_SHOW;
763}
764
765
767 int aClearance, int aMaxError,
768 ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const
769{
770 if( aLayer != m_layer && aLayer != UNDEFINED_LAYER )
771 return;
772
774
775 if( aClearance == 0 )
776 {
777 aBuffer.Append( m_cache->poly );
778 }
779 else
780 {
781 SHAPE_POLY_SET poly = m_cache->poly;
782 poly.Inflate( aClearance, CORNER_STRATEGY::CHAMFER_ACUTE_CORNERS, aMaxError, aErrorLoc );
783 aBuffer.Append( poly );
784 }
785}
786
787
789{
790 SHAPE_POLY_SET poly;
791 TransformShapeToPolygon( poly, aLayer, 0, 0, ERROR_INSIDE, true );
792
793 return std::make_shared<SHAPE_POLY_SET>( std::move( poly ) );
794}
795
796
797void PCB_BARCODE::GetBoundingHull( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
798 int aMaxError, ERROR_LOC aErrorLoc ) const
799{
801
802 auto getBoundingHull =
803 [this]( SHAPE_POLY_SET& aLocBuffer, const SHAPE_POLY_SET& aSource, int aLocClearance )
804 {
805 BOX2I rect = aSource.BBox( aLocClearance );
806 VECTOR2I corners[4];
807
808 corners[0].x = rect.GetOrigin().x;
809 corners[0].y = rect.GetOrigin().y;
810 corners[1].y = corners[0].y;
811 corners[1].x = rect.GetRight();
812 corners[2].x = corners[1].x;
813 corners[2].y = rect.GetBottom();
814 corners[3].y = corners[2].y;
815 corners[3].x = corners[0].x;
816
817 aLocBuffer.NewOutline();
818
819 const VECTOR2I pos = GetPosition();
820 const EDA_ANGLE angle = GetAngle();
821
822 for( VECTOR2I& corner : corners )
823 {
824 RotatePoint( corner, pos, angle );
825 aLocBuffer.Append( corner.x, corner.y );
826 }
827 };
828
829 if( aLayer == m_layer || aLayer == UNDEFINED_LAYER )
830 {
831 getBoundingHull( aBuffer, m_cache->symbolPoly, aClearance );
832 getBoundingHull( aBuffer, m_cache->textPoly, aClearance );
833 }
834}
835
836
838{
839 // Micro QR codes do not support High (H) error correction level
840 if( m_kind == BARCODE_T::MICRO_QR_CODE && aErrorCorrection == BARCODE_ECC_T::H )
842 else
843 m_errorCorrection = aErrorCorrection;
844 // Don't auto-compute here as it may be called during loading
845}
846
847
849{
850 m_kind = aKind;
851
852 // When switching to Micro QR, validate and adjust ECC if needed
855
856 // Don't auto-compute here as it may be called during loading
857}
858
859
861{
862 SetErrorCorrection( aErrorCorrection );
864}
865
866
868{
869 m_width = aWidth;
870
871 if( KeepSquare() )
872 m_height = aWidth;
873
875}
876
877
879{
880 m_height = aHeight;
881
882 if( KeepSquare() )
883 m_width = aHeight;
884
886}
887
888
890{
891 SetKind( aKind );
893}
894
895
897{
898 PCB_BARCODE* item = new PCB_BARCODE( *this );
899 item->CopyFrom( this );
900 return item;
901}
902
903
905{
906 wxCHECK_RET( aImage && aImage->Type() == PCB_BARCODE_T,
907 wxT( "Cannot swap data with non-barcode item." ) );
908
909 PCB_BARCODE* other = static_cast<PCB_BARCODE*>( aImage );
910
911 std::swap( m_layer, other->m_layer );
912 std::swap( m_isKnockout, other->m_isKnockout );
913 std::swap( m_isLocked, other->m_isLocked );
914 std::swap( m_width, other->m_width );
915 std::swap( m_height, other->m_height );
916 std::swap( m_libPos, other->m_libPos );
917 std::swap( m_margin, other->m_margin );
918 std::swap( m_text, other->m_text );
919 std::swap( m_kind, other->m_kind );
920 std::swap( m_libAngle, other->m_libAngle );
921 std::swap( m_errorCorrection, other->m_errorCorrection );
922 std::swap( m_cache, other->m_cache );
923 std::swap( m_customProperties, other->m_customProperties );
924
925 m_text.SetParent( this );
926 other->m_text.SetParent( other );
927}
928
929double PCB_BARCODE::Similarity( const BOARD_ITEM& aItem ) const
930{
931 if( !ClassOf( &aItem ) )
932 return 0.0;
933
934 const PCB_BARCODE* other = static_cast<const PCB_BARCODE*>( &aItem );
935
936 // Compare text, width, height, text height, position, and kind
937 double similarity = 0.0;
938 const double weight = 1.0 / 6.0;
939
940 if( GetText() == other->GetText() )
941 similarity += weight;
942 if( m_width == other->m_width )
943 similarity += weight;
944 if( m_height == other->m_height )
945 similarity += weight;
946 if( GetTextSize() == other->GetTextSize() )
947 similarity += weight;
948 if( GetPosition() == other->GetPosition() )
949 similarity += weight;
950 if( m_kind == other->m_kind )
951 similarity += weight;
952
953 return similarity;
954}
955
956int PCB_BARCODE::Compare( const PCB_BARCODE* aBarcode, const PCB_BARCODE* aOther )
957{
958 int diff;
959
960 if( ( diff = aBarcode->GetPosition().x - aOther->GetPosition().x ) != 0 )
961 return diff;
962
963 if( ( diff = aBarcode->GetPosition().y - aOther->GetPosition().y ) != 0 )
964 return diff;
965
966 if( ( diff = aBarcode->GetText().Cmp( aOther->GetText() ) ) != 0 )
967 return diff;
968
969 if( ( diff = aBarcode->GetWidth() - aOther->GetWidth() ) != 0 )
970 return diff;
971
972 if( ( diff = aBarcode->GetHeight() - aOther->GetHeight() ) != 0 )
973 return diff;
974
975 if( ( diff = aBarcode->GetTextSize() - aOther->GetTextSize() ) != 0 )
976 return diff;
977
978 if( ( diff = (int) aBarcode->GetKind() - (int) aOther->GetKind() ) != 0 )
979 return diff;
980
981 if( ( diff = aBarcode->GetAngle().AsTenthsOfADegree() - aOther->GetAngle().AsTenthsOfADegree() ) != 0 )
982 return diff;
983
984 if( ( diff = (int) aBarcode->GetErrorCorrection() - (int) aOther->GetErrorCorrection() ) != 0 )
985 return diff;
986
987 return 0;
988}
989
990
991bool PCB_BARCODE::operator==( const BOARD_ITEM& aItem ) const
992{
993 if( !ClassOf( &aItem ) )
994 return false;
995
996 const PCB_BARCODE& other = static_cast<const PCB_BARCODE&>( aItem );
997
998 return *this == other;
999}
1000
1001
1002bool PCB_BARCODE::operator==( const PCB_BARCODE& aOther ) const
1003{
1004 // Compare text, width, height, text height, position, and kind
1005 return ( GetText() == aOther.GetText()
1006 && m_width == aOther.m_width
1007 && m_height == aOther.m_height
1008 && GetTextSize() == aOther.GetTextSize()
1009 && GetPosition() == aOther.GetPosition()
1010 && m_kind == aOther.m_kind );
1011}
1012
1013// ---- Property registration ----
1014static struct PCB_BARCODE_DESC
1015{
1017 {
1021
1022 const wxString groupBarcode = _HKI( "Barcode Properties" );
1023
1025 if( kindMap.Choices().GetCount() == 0 )
1026 {
1027 kindMap.Undefined( BARCODE_T::QR_CODE );
1028 kindMap.Map( BARCODE_T::CODE_39, _HKI( "CODE_39" ) )
1029 .Map( BARCODE_T::CODE_128, _HKI( "CODE_128" ) )
1030 .Map( BARCODE_T::DATA_MATRIX, _HKI( "DATA_MATRIX" ) )
1031 .Map( BARCODE_T::QR_CODE, _HKI( "QR_CODE" ) )
1032 .Map( BARCODE_T::MICRO_QR_CODE, _HKI( "MICRO_QR_CODE" ) );
1033 }
1034
1036 if( eccMap.Choices().GetCount() == 0 )
1037 {
1038 eccMap.Undefined( BARCODE_ECC_T::L );
1039 eccMap.Map( BARCODE_ECC_T::L, _HKI( "L (Low)" ) )
1040 .Map( BARCODE_ECC_T::M, _HKI( "M (Medium)" ) )
1041 .Map( BARCODE_ECC_T::Q, _HKI( "Q (Quartile)" ) )
1042 .Map( BARCODE_ECC_T::H, _HKI( "H (High)" ) );
1043 }
1044
1045 auto hasKnockout =
1046 []( INSPECTABLE* aItem ) -> bool
1047 {
1048 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
1049 return bc->IsKnockout();
1050 return false;
1051 };
1052
1053 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, wxString>( _HKI( "Text" ),
1055 groupBarcode );
1056
1057 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, bool>( _HKI( "Show Text" ),
1059 groupBarcode ).SetIsCopyable();
1060
1061 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Text Size" ),
1063 groupBarcode );
1064
1065 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Width" ),
1067 groupBarcode ).SetIsCopyable();
1068
1069 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Height" ),
1071 groupBarcode ).SetIsCopyable();
1072
1073 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, double>( _HKI( "Orientation" ),
1075 groupBarcode );
1076
1077 propMgr.AddProperty( new PROPERTY_ENUM<PCB_BARCODE, BARCODE_T>( _HKI( "Barcode Type" ),
1079 groupBarcode );
1080
1081 propMgr.AddProperty( new PROPERTY_ENUM<PCB_BARCODE, BARCODE_ECC_T>( _HKI( "Error Correction" ),
1083 groupBarcode )
1084 .SetAvailableFunc( []( INSPECTABLE* aItem ) -> bool
1085 {
1086 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
1087 {
1088 return bc->GetKind() == BARCODE_T::QR_CODE
1089 || bc->GetKind() == BARCODE_T::MICRO_QR_CODE;
1090 }
1091
1092 return false;
1093 } )
1094 .SetChoicesFunc( []( INSPECTABLE* aItem )
1095 {
1096 PCB_BARCODE* barcode = static_cast<PCB_BARCODE*>( aItem );
1097 wxPGChoices choices;
1098
1099 choices.Add( _( "L (Low)" ), static_cast<int>( BARCODE_ECC_T::L ) );
1100 choices.Add( _( "M (Medium)" ), static_cast<int>( BARCODE_ECC_T::M ) );
1101 choices.Add( _( "Q (Quartile)" ), static_cast<int>( BARCODE_ECC_T::Q ) );
1102
1103 // Only QR_CODE has High
1104 if( barcode->GetKind() == BARCODE_T::QR_CODE )
1105 choices.Add( _( "H (High)" ), static_cast<int>( BARCODE_ECC_T::H ) );
1106
1107 return choices;
1108 } );
1109
1110 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, bool>( _HKI( "Knockout" ),
1112 groupBarcode ).SetIsCopyable();
1113
1114 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Margin X" ),
1116 groupBarcode )
1117 .SetAvailableFunc( hasKnockout );
1118
1119 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Margin Y" ),
1121 groupBarcode )
1122 .SetAvailableFunc( hasKnockout );
1123 }
1125
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.
VECTOR2I GetTextSize(PCB_LAYER_ID aLayer) const
Return the default text size from the layer class for the given layer.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:84
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
bool m_isKnockout
Definition board_item.h:587
PCB_LAYER_ID m_layer
Definition board_item.h:586
bool m_isLocked
Definition board_item.h:588
bool IsLocked() const override
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
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
virtual void CopyFrom(const BOARD_ITEM *aOther)
BOARD_ITEM & operator=(const BOARD_ITEM &aOther)
Definition board_item.h:103
bool IsSideSpecific() const
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
int GetMaxError() const
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 size_type GetWidth() const
Definition box2.h:211
constexpr const Vec GetCenter() const
Definition box2.h:227
constexpr size_type GetHeight() const
Definition box2.h:212
constexpr coord_type GetLeft() const
Definition box2.h:225
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:165
constexpr const Vec & GetOrigin() const
Definition box2.h:207
constexpr coord_type GetRight() const
Definition box2.h:214
constexpr coord_type GetTop() const
Definition box2.h:226
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:308
constexpr coord_type GetBottom() const
Definition box2.h:219
int AsTenthsOfADegree() const
Definition eda_angle.h:117
double AsDegrees() const
Definition eda_angle.h:115
bool IsZero() const
Definition eda_angle.h:135
The base class for create windows for drawing purpose.
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
std::map< wxString, wxString > m_customProperties
Definition eda_item.h:617
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.cpp:153
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:84
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:789
static ENUM_MAP< T > & Instance()
Definition property.h:783
ENUM_MAP & Undefined(T aValue)
Definition property.h:796
wxPGChoices & Choices()
Definition property.h:834
const wxString & GetReference() const
Definition footprint.h:909
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:39
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
Definition kiid.h:46
void SetKind(BARCODE_T aKind)
void SetTextSize(int aTextSize)
Change the height of the human-readable text displayed below the barcode.
double GetOrientation() const
std::unique_ptr< PCB_BARCODE_CACHE > m_cache
~PCB_BARCODE()
Destructor.
const BOX2I GetBoundingBox() const override
Get the axis-aligned bounding box of the barcode including text.
void SetBarcodeErrorCorrection(BARCODE_ECC_T aErrorCorrection)
virtual const BOX2I ViewBBox() const override
Get the bbox used for drawing/view culling, may include additional view-only extents.
EDA_ITEM * Clone() const override
Create a copy of this item.
void SetErrorCorrection(BARCODE_ECC_T aErrorCorrection)
Set the error correction level used for QR codes.
wxString GetShownText(RESOLUTION_CONTEXT aContext) const
void SetBarcodeHeight(int aHeight)
void SetShowText(bool aShow)
void SetMarginY(int aY)
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &settings, bool aCheckSide) override
bool KeepSquare() const
void SetBarcodeText(const wxString &aText)
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Produce a short human-readable description of the item for UI lists.
void AssembleBarcode() const
Assemble the barcode polygon and text polygons into a single polygonal representation.
void SetBarcodeKind(BARCODE_T aKind)
void GetBoundingHull(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
Add two rectangular polygons separately bounding the barcode's symbol and the barcode's text.
PCB_BARCODE & operator=(const PCB_BARCODE &aOther)
Copy assignment operator.
VECTOR2I GetPosition() const override
Get the position (center) of the barcode in internal units.
void ComputeTextPoly() const
Generate the internal polygon representation for the human-readable text.
wxString GetText() const
void SetPosition(const VECTOR2I &aPos) override
void SetMarginX(int aX)
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
void SetOrientation(double aDegrees)
double Similarity(const BOARD_ITEM &aItem) const override
Compute a simple similarity score between this barcode and another board item.
int m_height
Barcode height.
PCB_TEXT m_text
void SetLayer(PCB_LAYER_ID aLayer) override
Set the drawing layer for the barcode and its text.
bool operator==(const BOARD_ITEM &aItem) const override
Equality comparison operator for board-level deduplication.
VECTOR2I m_margin
Margin around the barcode (only valid for knockout)
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate message panel information entries (e.g.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
int GetTextSize() const
void ComputeBarcode() const
Generate the internal polygon representation for the current barcode text, kind and error correction.
void SetBarcodeWidth(int aWidth)
bool IsKnockout() const override
int GetHeight() const
Get the barcode height (in internal units).
BITMAPS GetMenuImage() const override
Icon to show in context menus/toolbars for this item type.
size_t computeCacheKey() const
Compute a hash of all cache-key inputs (shown text + geometry parameters + layer).
BARCODE_ECC_T m_errorCorrection
Error correction level for QR codes.
void SetIsKnockout(bool aEnable) override
static bool ClassOf(const EDA_ITEM *aItem)
Type-check helper.
void rescaleSymbolPoly(const VECTOR2I &aTopLeft, const VECTOR2I &aBotRight) const
Scale and translate the symbol polygon to fill the given bounding rectangle.
bool HitTest(const VECTOR2I &aPosition, int aAccuracy) const override
Hit-test a point against the barcode (text and symbol area).
PCB_BARCODE(BOARD_ITEM *aParent)
Construct a PCB_BARCODE.
void OnFootprintRescaled(double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I &aAnchor, const EDA_ANGLE &aParentRotate) override
Apply a parent footprint scale to this item.
int m_width
Barcode width.
VECTOR2I m_libPos
Position, FP-relative when in a footprint, board absolute otherwise.
int GetMarginY() const
void swapData(BOARD_ITEM *aImage) override
BARCODE_ECC_T GetErrorCorrection() const
EDA_ORIENTATION m_libAngle
Angle, FP-relative when in a footprint, board absolute otherwise.
bool GetShowText() const
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate the barcode around a given centre by the given angle.
int GetMarginX() const
BARCODE_T m_kind
static int Compare(const PCB_BARCODE *aBarcode, const PCB_BARCODE *aOther)
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE, bool ignoreLineWidth=false) const override
Convert the barcode (text + symbol shapes) to polygonal geometry suitable for filling/collision tests...
EDA_ANGLE GetAngle() const
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.
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipLeftRight) override
Flip the barcode horizontally or vertically around a centre point.
BARCODE_T GetKind() const
Returns the type of the barcode (QR, CODE_39, etc.).
int GetWidth() const
Get the barcode width (in internal units).
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
void SetText(const wxString &aText)
Set the barcode content text to encode.
void Move(const VECTOR2I &offset) override
Move the barcode and its text by the given offset.
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:263
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.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the 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.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
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)
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
void Move(const VECTOR2I &aVector) override
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
VECTOR2I InverseApply(const VECTOR2I &aPoint) const
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
RESOLUTION_CONTEXT
Definition common.h:89
@ FOR_CANVAS
Definition common.h:90
@ CHAMFER_ACUTE_CORNERS
Acute angles are chamfered.
DRC_CONSTRAINT_T
Definition drc_rule.h:49
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:448
@ DEGREES_T
Definition eda_angle.h:30
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:452
#define PCB_EDIT_FRAME_NAME
int GetPenSizeForNormal(int aTextSize)
Definition gr_text.cpp:57
static constexpr std::size_t hash_val(const Types &... args)
Definition hash.h:48
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition layer_id.cpp:179
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
@ Dwgs_User
Definition layer_ids.h:103
@ UNDEFINED_LAYER
Definition layer_ids.h:57
This file contains miscellaneous commonly used macros and functions.
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition mirror.h:41
FLIP_DIRECTION
Definition mirror.h:23
@ LEFT_RIGHT
Flip left to right (around the Y axis)
Definition mirror.h:24
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
Definition mirror.h:25
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)
#define _HKI(x)
Definition page_info.cpp:40
static struct PCB_BARCODE_DESC _PCB_BARCODE_DESC
constexpr int ECI_UTF8
BARCODE class definition.
BARCODE_ECC_T
Definition pcb_barcode.h:49
BARCODE_T
Definition pcb_barcode.h:40
see class PGM_BASE
#define TYPE_HASH(x)
Macro to generate unique identifier for a type.
Definition property.h:74
#define IMPLEMENT_ENUM_TO_WXANY(type)
Definition property.h:888
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names.
int delta
#define M_PI
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
constexpr auto to_underlying(E e) noexcept
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:93
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708