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 ),
67 m_libAngle( 0 ),
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() ).Normalize();
138
139 return m_libAngle;
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
254 m_libAngle.Normalize();
255
257
258 m_width = barcode.width().value_nm();
259 m_height = barcode.height().value_nm();
260
261 m_text.SetLayer( m_layer );
262 m_text.SetVisible( barcode.show_text() );
263
264 if( barcode.has_text_height() )
265 {
266 int textSize = std::max( 1, static_cast<int>( barcode.text_height().value_nm() ) );
267 m_text.SetTextSize( VECTOR2I( textSize, textSize ) );
268 m_text.SetTextThickness( std::max( 1, GetPenSizeForNormal( m_text.GetTextHeight() ) ) );
269 }
270
271 m_margin = kiapi::common::UnpackVector2( barcode.knockout_margin() );
272 BOARD_ITEM::SetIsKnockout( barcode.knockout() );
273 SetLocked( barcode.locked() == kiapi::common::types::LockedState::LS_LOCKED );
274
275 kiapi::common::UnpackCustomProperties( barcode.custom_properties(), *this );
276
278
279 return true;
280}
281
282
284{
285 m_layer = aLayer;
286 m_text.SetLayer( aLayer );
288}
289
290
291void PCB_BARCODE::SetTextSize( int aTextSize )
292{
293 m_text.SetTextSize( VECTOR2I( std::max( 1, aTextSize ), std::max( 1, aTextSize ) ) );
294 m_text.SetTextThickness( std::max( 1, GetPenSizeForNormal( m_text.GetTextHeight() ) ) );
296}
297
298
300{
301 return m_text.GetTextHeight();
302}
303
304
305void PCB_BARCODE::Move( const VECTOR2I& offset )
306{
307 if( const FOOTPRINT* fp = GetParentFootprint() )
308 {
309 const TRANSFORM_TRS& xform = fp->GetTransform();
310 VECTOR2I libOffset = xform.InverseApply( offset ) - xform.InverseApply( VECTOR2I( 0, 0 ) );
311 m_libPos += libOffset;
312 }
313 else
314 {
315 m_libPos += offset;
316 }
317
318 // m_text is intentionally not moved, ComputeTextPoly repositions it
319 // under the symbol on the next AssembleBarcode.
320}
321
322
323void PCB_BARCODE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
324{
325 VECTOR2I boardPos = GetPosition();
326 RotatePoint( boardPos, aRotCentre, aAngle );
327
328 if( const FOOTPRINT* fp = GetParentFootprint() )
329 m_libPos = fp->GetTransform().InverseApply( boardPos );
330 else
331 m_libPos = boardPos;
332
333 m_libAngle += aAngle;
334 m_libAngle.Normalize();
335
337}
338
339
340void PCB_BARCODE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
341{
342 if( const FOOTPRINT* fp = GetParentFootprint() )
343 {
344 const VECTOR2I libAxis = fp->GetTransform().InverseApply( aCentre );
345
346 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
347 m_libPos.x = 2 * libAxis.x - m_libPos.x;
348 else
349 m_libPos.y = 2 * libAxis.y - m_libPos.y;
350
351 // Reflect the library-frame angle (rotation-independent).
352 if( aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
354 else
356
357 m_libAngle.Normalize();
358
361 return;
362 }
363
364 VECTOR2I boardPos = GetPosition();
365 MIRROR( boardPos, aCentre, aFlipDirection );
366 m_libPos = boardPos;
367
368 if( aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
370 else
372
373 m_libAngle.Normalize();
374
377}
378
379
380void PCB_BARCODE::OnFootprintRescaled( double /* aRatioX */, double /* aRatioY */, double /* aLinearFactor */,
381 const VECTOR2I& /* aAnchor */, const EDA_ANGLE& /* aParentRotate */ )
382{
383 // Board values derive on read, AssembleBarcode rebuilds on next access.
384}
385
386
387void PCB_BARCODE::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings, bool aCheckSide )
388{
389 SetTextSize( settings.GetTextSize( GetLayer() ).y );
390}
391
392
394{
395 const VECTOR2I pos = GetPosition();
396 const EDA_ANGLE angle = GetAngle();
397
398 return hash_val( GetShownText( FOR_CANVAS ), m_width, m_height, pos.x, pos.y, m_margin.x, m_margin.y,
399 static_cast<int>( m_kind ), angle.AsDegrees(), static_cast<int>( m_errorCorrection ),
400 m_text.IsVisible(), m_text.GetTextHeight(), IsKnockout(), static_cast<int>( m_layer ) );
401}
402
403
405{
406 size_t key = computeCacheKey();
407
408 if( m_cache && m_cache->keyHash == key )
409 return;
410
411 if( !m_cache )
412 m_cache = std::make_unique<PCB_BARCODE_CACHE>();
413
415
416 const VECTOR2I pos = GetPosition();
417
418 // Scale the symbol polygon to the desired barcode width/height and center it at pos.
419 rescaleSymbolPoly( pos - VECTOR2I( m_width / 2, m_height / 2 ), pos + VECTOR2I( m_width / 2, m_height / 2 ) );
420
422
423 // Build full m_poly from symbol + optional text, then apply knockout if requested
424 m_cache->poly.RemoveAllContours();
425 m_cache->poly.Append( m_cache->symbolPoly );
426
427 if( m_text.IsVisible() && m_cache->textPoly.OutlineCount() )
428 m_cache->poly.Append( m_cache->textPoly );
429
430 m_cache->poly.Fracture();
431
432 if( IsKnockout() )
433 {
434 // Enforce minimum margin: at least 10% of the smallest side of the barcode, rounded up
435 // to the nearest 0.1 mm. Use this as a lower bound for both axes.
436 int minSide = std::min( m_width, m_height );
437 int tenPercent = ( minSide + 9 ) / 10; // ceil(minSide * 0.1)
438 int step01mm = std::max( 1, pcbIUScale.mmToIU( 0.1 ) );
439 int tenPercentRounded = ( ( tenPercent + step01mm - 1 ) / step01mm ) * step01mm;
440
441 // Build inversion rectangle based on the local bbox of the current combined geometry
442 BOX2I bbox = m_cache->poly.BBox();
443 bbox.Inflate( std::max( m_margin.x, tenPercentRounded ), std::max( m_margin.y, tenPercentRounded ) );
444
445 SHAPE_LINE_CHAIN rect;
446 rect.Append( bbox.GetLeft(), bbox.GetTop() );
447 rect.Append( bbox.GetRight(), bbox.GetTop() );
448 rect.Append( bbox.GetRight(), bbox.GetBottom() );
449 rect.Append( bbox.GetLeft(), bbox.GetBottom() );
450 rect.SetClosed( true );
451
453 ko.AddOutline( rect );
454 ko.BooleanSubtract( m_cache->poly );
455 ko.Fracture();
456 m_cache->poly = std::move( ko );
457 }
458
460 m_cache->poly.Mirror( pos, FLIP_DIRECTION::LEFT_RIGHT );
461
462 const EDA_ANGLE angle = GetAngle();
463
464 if( !angle.IsZero() )
465 m_cache->poly.Rotate( angle, pos );
466
467 m_cache->poly.CacheTriangulation();
468 m_cache->bbox = m_cache->poly.BBox();
469 m_cache->keyHash = key;
470}
471
472
474{
475 if( !m_cache )
476 m_cache = std::make_unique<PCB_BARCODE_CACHE>();
477
478 m_cache->textPoly.RemoveAllContours();
479
480 if( !m_text.IsVisible() )
481 return;
482
483 SHAPE_POLY_SET textPoly;
484 m_text.TransformTextToPolySet( textPoly, 0, GetMaxError(), ERROR_INSIDE );
485
486 if( textPoly.OutlineCount() == 0 )
487 return;
488
489 // PCB_TEXT::GetDrawRotation now includes the parent FP orientation, so
490 // TransformTextToPolySet rendered the glyphs already rotated by the FP
491 // angle. The final AssembleBarcode rotation (m_cache->poly.Rotate by
492 // GetAngle = lib_angle + FP_orient) would then rotate the glyphs a
493 // second time, producing twice the intended visual rotation. Undo the
494 // m_text-side rotation here so the glyph-orientation contribution is
495 // only the lib_angle, and the final poly rotation applies the FP-orient
496 // part uniformly with the symbol.
497 if( const FOOTPRINT* fp = GetParentFootprint() )
498 {
499 EDA_ANGLE fpOrient = fp->GetOrientation();
500
501 if( !fpOrient.IsZero() )
502 textPoly.Rotate( -fpOrient, m_text.GetTextPos() );
503 }
504
505 if( m_cache->symbolPoly.OutlineCount() == 0 )
506 return;
507
508 BOX2I textBBox = textPoly.BBox();
509 BOX2I symbolBBox = m_cache->symbolPoly.BBox();
510 VECTOR2I textPos;
511 int textOffset = pcbIUScale.mmToIU( 1 );
512 textPos.x = symbolBBox.GetCenter().x - textBBox.GetCenter().x;
513 textPos.y = symbolBBox.GetBottom() - textBBox.GetTop() + textOffset;
514
515 textPoly.Move( textPos );
516
517 m_cache->textPoly = std::move( textPoly );
518 m_cache->textPoly.CacheTriangulation();
519}
520
521
523{
524 if( !m_cache )
525 m_cache = std::make_unique<PCB_BARCODE_CACHE>();
526
527 m_cache->symbolPoly.RemoveAllContours();
528 m_cache->lastError.clear();
529
530 std::unique_ptr<zint_symbol, decltype( &ZBarcode_Delete )> symbol( ZBarcode_Create(), &ZBarcode_Delete );
531
532 if( !symbol )
533 {
534 wxLogError( wxT( "Zint: failed to allocate symbol" ) );
535 return;
536 }
537
538 symbol->input_mode = UNICODE_MODE;
539 symbol->show_hrt = 0; // do not show HRT
540
541 switch( m_kind )
542 {
544 symbol->symbology = BARCODE_CODE39;
545 break;
547 symbol->symbology = BARCODE_CODE128;
548 break;
550 symbol->symbology = BARCODE_QRCODE;
551 symbol->option_1 = to_underlying( m_errorCorrection );
552 break;
554 symbol->symbology = BARCODE_MICROQR;
555 symbol->option_1 = to_underlying( m_errorCorrection );
556 break;
558 symbol->symbology = BARCODE_DATAMATRIX;
559 break;
560 default:
561 wxLogError( wxT( "Zint: invalid barcode type" ) );
562 return;
563 }
564
565 wxString text = GetShownText( FOR_CANVAS );
566 wxScopedCharBuffer utf8Text = text.ToUTF8();
567 size_t length = utf8Text.length();
568 unsigned char* dataPtr = reinterpret_cast<unsigned char*>( utf8Text.data() );
569
570 if( text.empty() )
571 return;
572
573 if( ( m_kind == BARCODE_T::QR_CODE || m_kind == BARCODE_T::DATA_MATRIX ) && !text.IsAscii() )
574 {
575 symbol->eci = ECI_UTF8;
576 }
577
578 if( ZBarcode_Encode( symbol.get(), dataPtr, length ) >= ZINT_ERROR )
579 {
580 if( !text.IsAscii() )
581 {
582 m_cache->lastError = _( "This barcode type does not support international "
583 "characters. Use QR Code or Data Matrix instead." );
584 }
585 else
586 {
587 m_cache->lastError = wxString::FromUTF8( symbol->errtxt );
588 }
589 return;
590 }
591
592 if( ZBarcode_Buffer_Vector( symbol.get(), 0 ) >= ZINT_ERROR )
593 {
594 m_cache->lastError = wxString::FromUTF8( symbol->errtxt );
595 return;
596 }
597
598 for( zint_vector_rect* rect = symbol->vector->rectangles; rect != nullptr; rect = rect->next )
599 {
600 // Round using absolute edges to avoid cumulative rounding drift across modules.
601 int x1 = KiROUND( rect->x * symbol->scale );
602 int x2 = KiROUND( ( rect->x + rect->width ) * symbol->scale );
603 int y1 = KiROUND( rect->y * symbol->scale );
604 int y2 = KiROUND( ( rect->y + rect->height ) * symbol->scale );
605
606 SHAPE_LINE_CHAIN shapeline;
607 shapeline.Append( x1, y1 );
608 shapeline.Append( x2, y1 );
609 shapeline.Append( x2, y2 );
610 shapeline.Append( x1, y2 );
611 shapeline.SetClosed( true );
612
613 m_cache->symbolPoly.AddOutline( shapeline );
614 }
615
616 for( zint_vector_hexagon* hex = symbol->vector->hexagons; hex != nullptr; hex = hex->next )
617 {
618 // Compute vertices from center using minimal-diameter (inscribed circle) radius.
619 double r = hex->diameter / 2.0; // minimal radius
620 double cx = hex->x;
621 double cy = hex->y;
622
623 // Base orientation has apex at top; hex->rotation rotates by 0/90/180/270 degrees.
624 double baseAngles[6] = { 90.0, 30.0, -30.0, -90.0, -150.0, 150.0 };
625 double rot = static_cast<double>( hex->rotation );
626
627 SHAPE_LINE_CHAIN poly;
628
629 for( int k = 0; k < 6; ++k )
630 {
631 double ang = ( baseAngles[k] + rot ) * M_PI / 180.0;
632 int vx = KiROUND( cx + r * cos( ang ) );
633 int vy = KiROUND( cy + r * sin( ang ) );
634 poly.Append( vx, vy );
635 }
636 poly.SetClosed( true );
637
638 m_cache->symbolPoly.AddOutline( poly );
639 }
640
641 // Set the position of the barcode to the center of the symbol polygon
642 if( m_cache->symbolPoly.OutlineCount() > 0 )
643 {
644 VECTOR2I pos = m_cache->symbolPoly.BBox().GetCenter();
645 m_cache->symbolPoly.Move( -pos );
646 }
647
648 m_cache->symbolPoly.CacheTriangulation();
649}
650
651
652void PCB_BARCODE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
653{
654 FOOTPRINT* parentFP = GetParentFootprint();
655
656 if( parentFP && aFrame->GetName() == PCB_EDIT_FRAME_NAME )
657 aList.emplace_back( _( "Footprint" ), parentFP->GetReference() );
658
659 aList.emplace_back( _( "Barcode" ), ENUM_MAP<BARCODE_T>::Instance().ToString( m_kind ) );
660
661 // Don't use GetShownText() here; we want to show the user the variable references
662 aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
663
664 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
665 aList.emplace_back( _( "Status" ), _( "Locked" ) );
666
667 aList.emplace_back( _( "Layer" ), GetLayerName() );
668
669 aList.emplace_back( _( "Angle" ), wxString::Format( wxT( "%g" ), GetAngle().AsDegrees() ) );
670
671 aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( m_text.GetTextHeight() ) );
672}
673
674
675bool PCB_BARCODE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
676{
678
679 if( !GetBoundingBox().Contains( aPosition ) )
680 return false;
681
682 SHAPE_POLY_SET hulls;
683
685
686 return hulls.Collide( aPosition );
687}
688
689
690bool PCB_BARCODE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
691{
692 BOX2I arect = aRect;
693 arect.Inflate( aAccuracy );
694
695 BOX2I rect = GetBoundingBox();
696
697 if( aAccuracy )
698 rect.Inflate( aAccuracy );
699
700 if( aContained )
701 return arect.Contains( rect );
702
703 return arect.Intersects( rect );
704}
705
706
707void PCB_BARCODE::rescaleSymbolPoly( const VECTOR2I& aTopLeft, const VECTOR2I& aBotRight ) const
708{
709 // Rescale only the symbol polygon to the requested rectangle
710 BOX2I bbox = m_cache->symbolPoly.BBox();
711 int oldW = bbox.GetWidth();
712 int oldH = bbox.GetHeight();
713
714 VECTOR2I newPosition = ( aTopLeft + aBotRight ) / 2;
715 int newW = aBotRight.x - aTopLeft.x;
716 int newH = aBotRight.y - aTopLeft.y;
717 // Guard against zero/negative sizes from interactive edits; enforce a tiny minimum
718 int minIU = std::max( 1, pcbIUScale.mmToIU( 0.01 ) );
719 newW = std::max( newW, minIU );
720 newH = std::max( newH, minIU );
721
722 double scaleX = oldW ? static_cast<double>( newW ) / oldW : 1.0;
723 double scaleY = oldH ? static_cast<double>( newH ) / oldH : 1.0;
724
725 VECTOR2I oldCenter = bbox.GetCenter();
726 m_cache->symbolPoly.Scale( scaleX, scaleY, oldCenter );
727
728 // After scaling, move the symbol polygon to be centered at the new position
729 VECTOR2I newCenter = m_cache->symbolPoly.BBox().GetCenter();
730 VECTOR2I delta = newPosition - newCenter;
731
732 if( delta != VECTOR2I( 0, 0 ) )
733 m_cache->symbolPoly.Move( delta );
734}
735
736
738{
740 return m_cache->bbox;
741}
742
743
744wxString PCB_BARCODE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
745{
746 return wxString::Format( _( "Barcode '%s' on %s" ), GetText(), GetLayerName() );
747}
748
749
754
755
757{
759 return m_cache->bbox;
760}
761
762
763double PCB_BARCODE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
764{
765 // Hide the locked shadow when the barcode's own layer is not shown
766 if( aLayer == LAYER_LOCKED_ITEM_SHADOW && !aView->IsLayerVisibleCached( m_layer ) )
767 return LOD_HIDE;
768
769 return LOD_SHOW;
770}
771
772
774 int aClearance, int aMaxError,
775 ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const
776{
777 if( aLayer != m_layer && aLayer != UNDEFINED_LAYER )
778 return;
779
781
782 if( aClearance == 0 )
783 {
784 aBuffer.Append( m_cache->poly );
785 }
786 else
787 {
788 SHAPE_POLY_SET poly = m_cache->poly;
789 poly.Inflate( aClearance, CORNER_STRATEGY::CHAMFER_ACUTE_CORNERS, aMaxError, aErrorLoc );
790 aBuffer.Append( poly );
791 }
792}
793
794
796{
797 SHAPE_POLY_SET poly;
798 TransformShapeToPolygon( poly, aLayer, 0, 0, ERROR_INSIDE, true );
799
800 return std::make_shared<SHAPE_POLY_SET>( std::move( poly ) );
801}
802
803
804void PCB_BARCODE::GetBoundingHull( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
805 int aMaxError, ERROR_LOC aErrorLoc ) const
806{
808
809 auto getBoundingHull =
810 [this]( SHAPE_POLY_SET& aLocBuffer, const SHAPE_POLY_SET& aSource, int aLocClearance )
811 {
812 BOX2I rect = aSource.BBox( aLocClearance );
813 VECTOR2I corners[4];
814
815 corners[0].x = rect.GetOrigin().x;
816 corners[0].y = rect.GetOrigin().y;
817 corners[1].y = corners[0].y;
818 corners[1].x = rect.GetRight();
819 corners[2].x = corners[1].x;
820 corners[2].y = rect.GetBottom();
821 corners[3].y = corners[2].y;
822 corners[3].x = corners[0].x;
823
824 aLocBuffer.NewOutline();
825
826 const VECTOR2I pos = GetPosition();
827 const EDA_ANGLE angle = GetAngle();
828
829 for( VECTOR2I& corner : corners )
830 {
831 RotatePoint( corner, pos, angle );
832 aLocBuffer.Append( corner.x, corner.y );
833 }
834 };
835
836 if( aLayer == m_layer || aLayer == UNDEFINED_LAYER )
837 {
838 getBoundingHull( aBuffer, m_cache->symbolPoly, aClearance );
839 getBoundingHull( aBuffer, m_cache->textPoly, aClearance );
840 }
841}
842
843
845{
846 // Micro QR codes do not support High (H) error correction level
847 if( m_kind == BARCODE_T::MICRO_QR_CODE && aErrorCorrection == BARCODE_ECC_T::H )
849 else
850 m_errorCorrection = aErrorCorrection;
851 // Don't auto-compute here as it may be called during loading
852}
853
854
856{
857 m_kind = aKind;
858
859 // When switching to Micro QR, validate and adjust ECC if needed
862
863 // Don't auto-compute here as it may be called during loading
864}
865
866
868{
869 SetErrorCorrection( aErrorCorrection );
871}
872
873
875{
876 m_width = aWidth;
877
878 if( KeepSquare() )
879 m_height = aWidth;
880
882}
883
884
886{
887 m_height = aHeight;
888
889 if( KeepSquare() )
890 m_width = aHeight;
891
893}
894
895
897{
898 SetKind( aKind );
900}
901
902
904{
905 PCB_BARCODE* item = new PCB_BARCODE( *this );
906 item->CopyFrom( this );
907 return item;
908}
909
910
912{
913 wxCHECK_RET( aImage && aImage->Type() == PCB_BARCODE_T,
914 wxT( "Cannot swap data with non-barcode item." ) );
915
916 PCB_BARCODE* other = static_cast<PCB_BARCODE*>( aImage );
917
918 std::swap( m_layer, other->m_layer );
919 std::swap( m_isKnockout, other->m_isKnockout );
920 std::swap( m_isLocked, other->m_isLocked );
921 std::swap( m_width, other->m_width );
922 std::swap( m_height, other->m_height );
923 std::swap( m_libPos, other->m_libPos );
924 std::swap( m_margin, other->m_margin );
925 std::swap( m_text, other->m_text );
926 std::swap( m_kind, other->m_kind );
927 std::swap( m_libAngle, other->m_libAngle );
928 std::swap( m_errorCorrection, other->m_errorCorrection );
929 std::swap( m_cache, other->m_cache );
930 std::swap( m_customProperties, other->m_customProperties );
931
932 m_text.SetParent( this );
933 other->m_text.SetParent( other );
934}
935
936double PCB_BARCODE::Similarity( const BOARD_ITEM& aItem ) const
937{
938 if( !ClassOf( &aItem ) )
939 return 0.0;
940
941 const PCB_BARCODE* other = static_cast<const PCB_BARCODE*>( &aItem );
942
943 // Compare text, width, height, text height, position, and kind
944 double similarity = 0.0;
945 const double weight = 1.0 / 6.0;
946
947 if( GetText() == other->GetText() )
948 similarity += weight;
949 if( m_width == other->m_width )
950 similarity += weight;
951 if( m_height == other->m_height )
952 similarity += weight;
953 if( GetTextSize() == other->GetTextSize() )
954 similarity += weight;
955 if( GetPosition() == other->GetPosition() )
956 similarity += weight;
957 if( m_kind == other->m_kind )
958 similarity += weight;
959
960 return similarity;
961}
962
963int PCB_BARCODE::Compare( const PCB_BARCODE* aBarcode, const PCB_BARCODE* aOther )
964{
965 int diff;
966
967 if( ( diff = aBarcode->GetPosition().x - aOther->GetPosition().x ) != 0 )
968 return diff;
969
970 if( ( diff = aBarcode->GetPosition().y - aOther->GetPosition().y ) != 0 )
971 return diff;
972
973 if( ( diff = aBarcode->GetText().Cmp( aOther->GetText() ) ) != 0 )
974 return diff;
975
976 if( ( diff = aBarcode->GetWidth() - aOther->GetWidth() ) != 0 )
977 return diff;
978
979 if( ( diff = aBarcode->GetHeight() - aOther->GetHeight() ) != 0 )
980 return diff;
981
982 if( ( diff = aBarcode->GetTextSize() - aOther->GetTextSize() ) != 0 )
983 return diff;
984
985 if( ( diff = (int) aBarcode->GetKind() - (int) aOther->GetKind() ) != 0 )
986 return diff;
987
988 if( ( diff = aBarcode->GetAngle().AsTenthsOfADegree() - aOther->GetAngle().AsTenthsOfADegree() ) != 0 )
989 return diff;
990
991 if( ( diff = (int) aBarcode->GetErrorCorrection() - (int) aOther->GetErrorCorrection() ) != 0 )
992 return diff;
993
994 return 0;
995}
996
997
998bool PCB_BARCODE::operator==( const BOARD_ITEM& aItem ) const
999{
1000 if( !ClassOf( &aItem ) )
1001 return false;
1002
1003 const PCB_BARCODE& other = static_cast<const PCB_BARCODE&>( aItem );
1004
1005 return *this == other;
1006}
1007
1008
1009bool PCB_BARCODE::operator==( const PCB_BARCODE& aOther ) const
1010{
1011 // Compare text, width, height, text height, position, and kind
1012 return ( GetText() == aOther.GetText()
1013 && m_width == aOther.m_width
1014 && m_height == aOther.m_height
1015 && GetTextSize() == aOther.GetTextSize()
1016 && GetPosition() == aOther.GetPosition()
1017 && m_kind == aOther.m_kind );
1018}
1019
1020// ---- Property registration ----
1021static struct PCB_BARCODE_DESC
1022{
1024 {
1028
1029 const wxString groupBarcode = _HKI( "Barcode Properties" );
1030
1032 if( kindMap.Choices().GetCount() == 0 )
1033 {
1034 kindMap.Undefined( BARCODE_T::QR_CODE );
1035 kindMap.Map( BARCODE_T::CODE_39, _HKI( "CODE_39" ) )
1036 .Map( BARCODE_T::CODE_128, _HKI( "CODE_128" ) )
1037 .Map( BARCODE_T::DATA_MATRIX, _HKI( "DATA_MATRIX" ) )
1038 .Map( BARCODE_T::QR_CODE, _HKI( "QR_CODE" ) )
1039 .Map( BARCODE_T::MICRO_QR_CODE, _HKI( "MICRO_QR_CODE" ) );
1040 }
1041
1043 if( eccMap.Choices().GetCount() == 0 )
1044 {
1045 eccMap.Undefined( BARCODE_ECC_T::L );
1046 eccMap.Map( BARCODE_ECC_T::L, _HKI( "L (Low)" ) )
1047 .Map( BARCODE_ECC_T::M, _HKI( "M (Medium)" ) )
1048 .Map( BARCODE_ECC_T::Q, _HKI( "Q (Quartile)" ) )
1049 .Map( BARCODE_ECC_T::H, _HKI( "H (High)" ) );
1050 }
1051
1052 auto hasKnockout =
1053 []( INSPECTABLE* aItem ) -> bool
1054 {
1055 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
1056 return bc->IsKnockout();
1057 return false;
1058 };
1059
1060 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, wxString>( _HKI( "Text" ),
1062 groupBarcode );
1063
1064 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, bool>( _HKI( "Show Text" ),
1066 groupBarcode ).SetIsCopyable();
1067
1068 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Text Size" ),
1070 groupBarcode );
1071
1072 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Width" ),
1074 groupBarcode ).SetIsCopyable();
1075
1076 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Height" ),
1078 groupBarcode ).SetIsCopyable();
1079
1080 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, double>( _HKI( "Orientation" ),
1082 groupBarcode );
1083
1084 propMgr.AddProperty( new PROPERTY_ENUM<PCB_BARCODE, BARCODE_T>( _HKI( "Barcode Type" ),
1086 groupBarcode );
1087
1088 propMgr.AddProperty( new PROPERTY_ENUM<PCB_BARCODE, BARCODE_ECC_T>( _HKI( "Error Correction" ),
1090 groupBarcode )
1091 .SetAvailableFunc( []( INSPECTABLE* aItem ) -> bool
1092 {
1093 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
1094 {
1095 return bc->GetKind() == BARCODE_T::QR_CODE
1096 || bc->GetKind() == BARCODE_T::MICRO_QR_CODE;
1097 }
1098
1099 return false;
1100 } )
1101 .SetChoicesFunc( []( INSPECTABLE* aItem )
1102 {
1103 PCB_BARCODE* barcode = static_cast<PCB_BARCODE*>( aItem );
1104 wxPGChoices choices;
1105
1106 choices.Add( _( "L (Low)" ), static_cast<int>( BARCODE_ECC_T::L ) );
1107 choices.Add( _( "M (Medium)" ), static_cast<int>( BARCODE_ECC_T::M ) );
1108 choices.Add( _( "Q (Quartile)" ), static_cast<int>( BARCODE_ECC_T::Q ) );
1109
1110 // Only QR_CODE has High
1111 if( barcode->GetKind() == BARCODE_T::QR_CODE )
1112 choices.Add( _( "H (High)" ), static_cast<int>( BARCODE_ECC_T::H ) );
1113
1114 return choices;
1115 } );
1116
1117 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, bool>( _HKI( "Knockout" ),
1119 groupBarcode ).SetIsCopyable();
1120
1121 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Margin X" ),
1123 groupBarcode )
1124 .SetAvailableFunc( hasKnockout );
1125
1126 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Margin Y" ),
1128 groupBarcode )
1129 .SetAvailableFunc( hasKnockout );
1130 }
1132
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:121
constexpr int ARC_LOW_DEF
Definition base_units.h:136
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:995
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:578
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
void SetLocked(bool aLocked) override
Definition board_item.h:417
bool m_isKnockout
Definition board_item.h:572
PCB_LAYER_ID m_layer
Definition board_item.h:571
bool m_isLocked
Definition board_item.h:573
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:414
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
EDA_ANGLE Normalize()
Definition eda_angle.h:229
int AsTenthsOfADegree() const
Definition eda_angle.h:118
double AsDegrees() const
Definition eda_angle.h:116
bool IsZero() const
Definition eda_angle.h:136
The base class for create windows for drawing purpose.
const KIID m_Uuid
Definition eda_item.h:597
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
std::map< wxString, wxString > m_customProperties
Definition eda_item.h:615
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:776
static ENUM_MAP< T > & Instance()
Definition property.h:770
ENUM_MAP & Undefined(T aValue)
Definition property.h:783
wxPGChoices & Choices()
Definition property.h:821
const wxString & GetReference() const
Definition footprint.h:901
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:439
Definition kiid.h:46
void SetKind(BARCODE_T aKind)
EDA_ANGLE m_libAngle
Angle, FP-relative when in a footprint, board absolute otherwise.
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
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
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
Function Move.
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.Helper macro to map type hashes to names.
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:87
@ FOR_CANVAS
Definition common.h:88
@ CHAMFER_ACUTE_CORNERS
Acute angles are chamfered.
DRC_CONSTRAINT_T
Definition drc_rule.h:49
#define _(s)
@ DEGREES_T
Definition eda_angle.h:31
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:426
#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:47
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)
Definition property.h:74
#define IMPLEMENT_ENUM_TO_WXANY(type)
Definition property.h:875
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
#define REGISTER_TYPE(x)
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:225
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:683