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, you may find one here:
19 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20 * or you may search the http://www.gnu.org website for the version 2 license,
21 * or you may write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24
25#include <core/type_helpers.h>
26#include <bitmaps.h>
27#include <gr_basic.h>
28#include <macros.h>
29#include <pcb_edit_frame.h>
30#include <richio.h>
31#include <trigo.h>
32
33#include <base_units.h>
34#include <pcb_barcode.h>
35#include <board.h>
37#include <pcb_text.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 <footprint.h>
49
50#include <backend/zint.h>
52
54 BOARD_ITEM( aParent, PCB_BARCODE_T ),
55 m_width( pcbIUScale.mmToIU( 40 ) ),
56 m_height( pcbIUScale.mmToIU( 40 ) ),
57 m_pos( 0, 0 ),
58 m_text( this ),
60 m_angle( 0 ),
62{
64}
65
66
70
71
73 BOARD_ITEM( aOther ),
74 m_width( aOther.m_width ),
75 m_height( aOther.m_height ),
76 m_pos( aOther.m_pos ),
77 m_margin( aOther.m_margin ),
78 m_text( aOther.m_text ),
79 m_kind( aOther.m_kind ),
80 m_angle( aOther.m_angle ),
82 m_poly( aOther.m_poly ),
83 m_symbolPoly( aOther.m_symbolPoly ),
84 m_textPoly( aOther.m_textPoly ),
85 m_bbox( aOther.m_bbox )
86{
87 m_text.SetParent( this );
88}
89
90
92{
93 if( this != &aOther )
94 {
95 BOARD_ITEM::operator=( aOther );
96
97 m_width = aOther.m_width;
98 m_height = aOther.m_height;
99 m_pos = aOther.m_pos;
100 m_margin = aOther.m_margin;
101 m_text = aOther.m_text;
102 m_kind = aOther.m_kind;
103 m_angle = aOther.m_angle;
105 m_poly = aOther.m_poly;
106 m_symbolPoly = aOther.m_symbolPoly;
107 m_textPoly = aOther.m_textPoly;
108 m_bbox = aOther.m_bbox;
109
110 m_text.SetParent( this );
111 }
112
113 return *this;
114}
115
116
118{
119 VECTOR2I delta = aPos - m_pos;
120 Move( delta );
121}
122
123
125{
126 return m_pos;
127}
128
129
130void PCB_BARCODE::SetText( const wxString& aNewText )
131{
132 m_text.SetText( aNewText );
133}
134
135
136wxString PCB_BARCODE::GetText() const
137{
138 return m_text.GetText();
139}
140
141
143{
144 return m_text.GetShownText( true );
145}
146
147
149{
150 m_layer = aLayer;
151 m_text.SetLayer( aLayer );
152
154}
155
156
157void PCB_BARCODE::SetTextSize( int aTextSize )
158{
159 m_text.SetTextSize( VECTOR2I( std::max( 1, aTextSize ), std::max( 1, aTextSize ) ) );
160 m_text.SetTextThickness( std::max( 1, GetPenSizeForNormal( m_text.GetTextHeight() ) ) );
161
163}
164
165
167{
168 return m_text.GetTextHeight();
169}
170
171
172void PCB_BARCODE::Move( const VECTOR2I& offset )
173{
174 m_pos += offset;
175 m_symbolPoly.Move( offset );
176 m_textPoly.Move( offset );
177 m_poly.Move( offset );
178 m_text.Move( offset );
179 m_bbox.Move( offset );
180}
181
182
183void PCB_BARCODE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
184{
185 RotatePoint( m_pos, aRotCentre, aAngle );
186 m_angle += aAngle;
187
189}
190
191
192void PCB_BARCODE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
193{
194 MIRROR( m_pos, aCentre, aFlipDirection );
195
196 if( aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
198
200
202}
203
204
205void PCB_BARCODE::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings, bool aCheckSide )
206{
207 SetTextSize( settings.GetTextSize( GetLayer() ).y );
208}
209
210
212{
214
215 // Scale the symbol polygon to the desired barcode width/height (property values) and center it at m_pos
216 // Note: SetRect will rescale the symbol-only polygon and then rebuild m_poly
217 SetRect( m_pos - VECTOR2I( m_width / 2, m_height / 2 ),
218 m_pos + VECTOR2I( m_width / 2, m_height / 2 ) );
219
221
222 // Build full m_poly from symbol + optional text, then apply knockout if requested
223 m_poly.RemoveAllContours();
224 m_poly.Append( m_symbolPoly );
225
226 if( m_text.IsVisible() && m_textPoly.OutlineCount() )
227 m_poly.Append( m_textPoly );
228
229 m_poly.Fracture();
230
231 if( IsKnockout() )
232 {
233 // Enforce minimum margin: at least 10% of the smallest side of the barcode, rounded up
234 // to the nearest 0.1 mm. Use this as a lower bound for both axes.
235 int minSide = std::min( m_width, m_height );
236 int tenPercent = ( minSide + 9 ) / 10; // ceil(minSide * 0.1)
237 int step01mm = std::max( 1, pcbIUScale.mmToIU( 0.1 ) );
238 int tenPercentRounded = ( ( tenPercent + step01mm - 1 ) / step01mm ) * step01mm;
239
240 // Build inversion rectangle based on the local bbox of the current combined geometry
241 BOX2I bbox = m_poly.BBox();
242 bbox.Inflate( std::max( m_margin.x, tenPercentRounded ), std::max( m_margin.y, tenPercentRounded ) );
243
244 SHAPE_LINE_CHAIN rect;
245 rect.Append( bbox.GetLeft(), bbox.GetTop() );
246 rect.Append( bbox.GetRight(), bbox.GetTop() );
247 rect.Append( bbox.GetRight(), bbox.GetBottom() );
248 rect.Append( bbox.GetLeft(), bbox.GetBottom() );
249 rect.SetClosed( true );
250
252 ko.AddOutline( rect );
254 ko.Fracture();
255 m_poly = std::move( ko );
256 }
257
260
261 if( !m_angle.IsZero() )
262 m_poly.Rotate( m_angle, m_pos );
263
264 m_poly.CacheTriangulation( false );
265 m_bbox = m_poly.BBox();
266}
267
268
270{
271 m_textPoly.RemoveAllContours();
272
273 if( !m_text.IsVisible() )
274 return;
275
276 SHAPE_POLY_SET textPoly;
277 m_text.TransformTextToPolySet( textPoly, 0, GetMaxError(), ERROR_INSIDE );
278
279 if( textPoly.OutlineCount() == 0 )
280 return;
281
282 if( m_symbolPoly.OutlineCount() == 0 )
283 return;
284
285 BOX2I textBBox = textPoly.BBox();
286 BOX2I symbolBBox = m_symbolPoly.BBox();
287 VECTOR2I textPos;
288 int textOffset = pcbIUScale.mmToIU( 1 );
289 textPos.x = symbolBBox.GetCenter().x - textBBox.GetCenter().x;
290 textPos.y = symbolBBox.GetBottom() - textBBox.GetTop() + textOffset;
291
292 textPoly.Move( textPos );
293
294 m_textPoly = std::move( textPoly );
295 m_textPoly.CacheTriangulation();
296}
297
298
300{
301 m_symbolPoly.RemoveAllContours();
302
303 std::unique_ptr<zint_symbol, decltype( &ZBarcode_Delete )> symbol( ZBarcode_Create(), &ZBarcode_Delete );
304
305 if( !symbol )
306 {
307 wxLogError( wxT( "Zint: failed to allocate symbol" ) );
308 return;
309 }
310
311 symbol->input_mode = UNICODE_MODE;
312 symbol->show_hrt = 0; // do not show HRT
313
314 switch( m_kind )
315 {
317 symbol->symbology = BARCODE_CODE39;
318 break;
320 symbol->symbology = BARCODE_CODE128;
321 break;
323 symbol->symbology = BARCODE_QRCODE;
324 symbol->option_1 = to_underlying( m_errorCorrection );
325 break;
327 symbol->symbology = BARCODE_MICROQR;
328 symbol->option_1 = to_underlying( m_errorCorrection );
329 break;
331 symbol->symbology = BARCODE_DATAMATRIX;
332 break;
333 default:
334 wxLogError( wxT( "Zint: invalid barcode type" ) );
335 return;
336 }
337
338 wxString text = GetShownText();
339 wxScopedCharBuffer utf8Text = text.ToUTF8();
340 size_t length = utf8Text.length();
341 unsigned char* dataPtr = reinterpret_cast<unsigned char*>( utf8Text.data() );
342
343 if( text.empty() )
344 return;
345
346 if( ZBarcode_Encode( symbol.get(), dataPtr, length ) )
347 return;
348
349 if( ZBarcode_Buffer_Vector( symbol.get(), 0 ) ) // 0 means success
350 return;
351
352 for( zint_vector_rect* rect = symbol->vector->rectangles; rect != nullptr; rect = rect->next )
353 {
354 // Round using absolute edges to avoid cumulative rounding drift across modules.
355 int x1 = KiROUND( rect->x * symbol->scale );
356 int x2 = KiROUND( ( rect->x + rect->width ) * symbol->scale );
357 int y1 = KiROUND( rect->y * symbol->scale );
358 int y2 = KiROUND( ( rect->y + rect->height ) * symbol->scale );
359
360 SHAPE_LINE_CHAIN shapeline;
361 shapeline.Append( x1, y1 );
362 shapeline.Append( x2, y1 );
363 shapeline.Append( x2, y2 );
364 shapeline.Append( x1, y2 );
365 shapeline.SetClosed( true );
366
367 m_symbolPoly.AddOutline( shapeline );
368 }
369
370 for( zint_vector_hexagon* hex = symbol->vector->hexagons; hex != nullptr; hex = hex->next )
371 {
372 // Compute vertices from center using minimal-diameter (inscribed circle) radius.
373 double r = hex->diameter / 2.0; // minimal radius
374 double cx = hex->x;
375 double cy = hex->y;
376
377 // Base orientation has apex at top; hex->rotation rotates by 0/90/180/270 degrees.
378 double baseAngles[6] = { 90.0, 30.0, -30.0, -90.0, -150.0, 150.0 };
379 double rot = static_cast<double>( hex->rotation );
380
381 SHAPE_LINE_CHAIN poly;
382
383 for( int k = 0; k < 6; ++k )
384 {
385 double ang = ( baseAngles[k] + rot ) * M_PI / 180.0;
386 int vx = KiROUND( cx + r * cos( ang ) );
387 int vy = KiROUND( cy + r * sin( ang ) );
388 poly.Append( vx, vy );
389 }
390 poly.SetClosed( true );
391
392 m_symbolPoly.AddOutline( poly );
393 }
394
395 // Set the position of the barcode to the center of the symbol polygon
396 if( m_symbolPoly.OutlineCount() > 0 )
397 {
398 VECTOR2I pos = m_symbolPoly.BBox().GetCenter();
399 m_symbolPoly.Move( -pos );
400 }
401
402 m_symbolPoly.CacheTriangulation();
403}
404
405
406void PCB_BARCODE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
407{
408 FOOTPRINT* parentFP = GetParentFootprint();
409
410 if( parentFP && aFrame->GetName() == PCB_EDIT_FRAME_NAME )
411 aList.emplace_back( _( "Footprint" ), parentFP->GetReference() );
412
413 aList.emplace_back( _( "Barcode" ), ENUM_MAP<BARCODE_T>::Instance().ToString( m_kind ) );
414
415 // Don't use GetShownText() here; we want to show the user the variable references
416 aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
417
418 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
419 aList.emplace_back( _( "Status" ), _( "Locked" ) );
420
421 aList.emplace_back( _( "Layer" ), GetLayerName() );
422
423 aList.emplace_back( _( "Angle" ), wxString::Format( wxT( "%g" ), m_angle.AsDegrees() ) );
424
425 aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( m_text.GetTextHeight() ) );
426}
427
428
429bool PCB_BARCODE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
430{
431 if( !GetBoundingBox().Contains( aPosition ) )
432 return false;
433
434 SHAPE_POLY_SET hulls;
435
437
438 return hulls.Collide( aPosition );
439}
440
441
442bool PCB_BARCODE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
443{
444 BOX2I arect = aRect;
445 arect.Inflate( aAccuracy );
446
447 BOX2I rect = GetBoundingBox();
448
449 if( aAccuracy )
450 rect.Inflate( aAccuracy );
451
452 if( aContained )
453 return arect.Contains( rect );
454
455 return arect.Intersects( rect );
456}
457
458
459void PCB_BARCODE::SetRect( const VECTOR2I& aTopLeft, const VECTOR2I& aBotRight )
460{
461 // Rescale only the symbol polygon to the requested rectangle; text is rebuilt below
462 BOX2I bbox = m_symbolPoly.BBox();
463 int oldW = bbox.GetWidth();
464 int oldH = bbox.GetHeight();
465
466 VECTOR2I newPosition = ( aTopLeft + aBotRight ) / 2;
467 SetPosition( newPosition );
468 int newW = aBotRight.x - aTopLeft.x;
469 int newH = aBotRight.y - aTopLeft.y;
470 // Guard against zero/negative sizes from interactive edits; enforce a tiny minimum
471 int minIU = std::max( 1, pcbIUScale.mmToIU( 0.01 ) );
472 newW = std::max( newW, minIU );
473 newH = std::max( newH, minIU );
474
475 double scaleX = oldW ? static_cast<double>( newW ) / oldW : 1.0;
476 double scaleY = oldH ? static_cast<double>( newH ) / oldH : 1.0;
477
478 VECTOR2I oldCenter = bbox.GetCenter();
479 m_symbolPoly.Scale( scaleX, scaleY, oldCenter );
480
481 // After scaling, move the symbol polygon to be centered at the new position
482 VECTOR2I newCenter = m_symbolPoly.BBox().GetCenter();
483 VECTOR2I delta = newPosition - newCenter;
484
485 if( delta != VECTOR2I( 0, 0 ) )
486 m_symbolPoly.Move( delta );
487
488 // Update intended barcode symbol size (without text/margins)
489 m_width = newW;
490 m_height = newH;
491}
492
493
495{
496 return m_bbox;
497}
498
499
500wxString PCB_BARCODE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
501{
502 return wxString::Format( _( "Barcode '%s' on %s" ), GetText(), GetLayerName() );
503}
504
505
510
511
513{
514 return m_bbox;
515}
516
517
519 int aClearance, int aMaxError,
520 ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const
521{
522 if( aLayer != m_layer && aLayer != UNDEFINED_LAYER )
523 return;
524
525 if( aClearance == 0 )
526 {
527 aBuffer.Append( m_poly );
528 }
529 else
530 {
531 SHAPE_POLY_SET poly = m_poly;
532 poly.Inflate( aClearance, CORNER_STRATEGY::CHAMFER_ACUTE_CORNERS, aMaxError, aErrorLoc );
533 aBuffer.Append( poly );
534 }
535}
536
537
538std::shared_ptr<SHAPE> PCB_BARCODE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
539{
540 SHAPE_POLY_SET poly;
541 TransformShapeToPolygon( poly, aLayer, 0, 0, ERROR_INSIDE, true );
542
543 return std::make_shared<SHAPE_POLY_SET>( std::move( poly ) );
544}
545
546
547void PCB_BARCODE::GetBoundingHull( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
548 int aMaxError, ERROR_LOC aErrorLoc ) const
549{
550 auto getBoundingHull =
551 [this]( SHAPE_POLY_SET& aLocBuffer, const SHAPE_POLY_SET& aSource, int aLocClearance )
552 {
553 BOX2I rect = aSource.BBox( aLocClearance );
554 VECTOR2I corners[4];
555
556 corners[0].x = rect.GetOrigin().x;
557 corners[0].y = rect.GetOrigin().y;
558 corners[1].y = corners[0].y;
559 corners[1].x = rect.GetRight();
560 corners[2].x = corners[1].x;
561 corners[2].y = rect.GetBottom();
562 corners[3].y = corners[2].y;
563 corners[3].x = corners[0].x;
564
565 aLocBuffer.NewOutline();
566
567 for( VECTOR2I& corner : corners )
568 {
569 RotatePoint( corner, m_pos, m_angle );
570 aLocBuffer.Append( corner.x, corner.y );
571 }
572 };
573
574 if( aLayer == m_layer || aLayer == UNDEFINED_LAYER )
575 {
576 getBoundingHull( aBuffer, m_symbolPoly, aClearance );
577 getBoundingHull( aBuffer, m_textPoly, aClearance );
578 }
579}
580
581
583{
584 // Micro QR codes do not support High (H) error correction level
585 if( m_kind == BARCODE_T::MICRO_QR_CODE && aErrorCorrection == BARCODE_ECC_T::H )
587 else
588 m_errorCorrection = aErrorCorrection;
589 // Don't auto-compute here as it may be called during loading
590}
591
592
594{
595 m_kind = aKind;
596
597 // When switching to Micro QR, validate and adjust ECC if needed
600
601 // Don't auto-compute here as it may be called during loading
602}
603
604
606{
607 SetErrorCorrection( aErrorCorrection );
609}
610
611
613{
614 m_width = aWidth;
615
616 if( KeepSquare() )
617 m_height = aWidth;
618
620}
621
622
624{
625 m_height = aHeight;
626
627 if( KeepSquare() )
628 m_width = aHeight;
629
631}
632
633
635{
636 SetKind( aKind );
638}
639
640
642{
643 PCB_BARCODE* item = new PCB_BARCODE( *this );
644 item->CopyFrom( this );
645 return item;
646}
647
648
650{
651 wxCHECK_RET( aImage && aImage->Type() == PCB_BARCODE_T,
652 wxT( "Cannot swap data with non-barcode item." ) );
653
654 PCB_BARCODE* other = static_cast<PCB_BARCODE*>( aImage );
655
656 std::swap( *this, *other );
657
658 m_text.SetParent( this );
659 other->m_text.SetParent( other );
660}
661
662double PCB_BARCODE::Similarity( const BOARD_ITEM& aItem ) const
663{
664 if( !ClassOf( &aItem ) )
665 return 0.0;
666
667 const PCB_BARCODE* other = static_cast<const PCB_BARCODE*>( &aItem );
668
669 // Compare text, width, height, text height, position, and kind
670 double similarity = 0.0;
671 const double weight = 1.0 / 6.0;
672
673 if( GetText() == other->GetText() )
674 similarity += weight;
675 if( m_width == other->m_width )
676 similarity += weight;
677 if( m_height == other->m_height )
678 similarity += weight;
679 if( GetTextSize() == other->GetTextSize() )
680 similarity += weight;
681 if( GetPosition() == other->GetPosition() )
682 similarity += weight;
683 if( m_kind == other->m_kind )
684 similarity += weight;
685
686 return similarity;
687}
688
689int PCB_BARCODE::Compare( const PCB_BARCODE* aBarcode, const PCB_BARCODE* aOther )
690{
691 int diff;
692
693 if( ( diff = aBarcode->GetPosition().x - aOther->GetPosition().x ) != 0 )
694 return diff;
695
696 if( ( diff = aBarcode->GetPosition().y - aOther->GetPosition().y ) != 0 )
697 return diff;
698
699 if( ( diff = aBarcode->GetText().Cmp( aOther->GetText() ) ) != 0 )
700 return diff;
701
702 if( ( diff = aBarcode->GetWidth() - aOther->GetWidth() ) != 0 )
703 return diff;
704
705 if( ( diff = aBarcode->GetHeight() - aOther->GetHeight() ) != 0 )
706 return diff;
707
708 if( ( diff = aBarcode->GetTextSize() - aOther->GetTextSize() ) != 0 )
709 return diff;
710
711 if( ( diff = (int) aBarcode->GetKind() - (int) aOther->GetKind() ) != 0 )
712 return diff;
713
714 if( ( diff = aBarcode->m_angle.AsTenthsOfADegree() - aOther->m_angle.AsTenthsOfADegree() ) != 0 )
715 return diff;
716
717 if( ( diff = (int) aBarcode->GetErrorCorrection() - (int) aOther->GetErrorCorrection() ) != 0 )
718 return diff;
719
720 return 0;
721}
722
723
724bool PCB_BARCODE::operator==( const BOARD_ITEM& aItem ) const
725{
726 if( !ClassOf( &aItem ) )
727 return false;
728
729 const PCB_BARCODE* other = static_cast<const PCB_BARCODE*>( &aItem );
730
731 // Compare text, width, height, text height, position, and kind
732 return ( GetText() == other->GetText()
733 && m_width == other->m_width
734 && m_height == other->m_height
735 && GetTextSize() == other->GetTextSize()
736 && GetPosition() == other->GetPosition()
737 && m_kind == other->m_kind );
738}
739
740// ---- Property registration ----
741static struct PCB_BARCODE_DESC
742{
744 {
748
749 const wxString groupBarcode = _HKI( "Barcode Properties" );
750
752 if( kindMap.Choices().GetCount() == 0 )
753 {
754 kindMap.Undefined( BARCODE_T::QR_CODE );
755 kindMap.Map( BARCODE_T::CODE_39, _HKI( "CODE_39" ) )
756 .Map( BARCODE_T::CODE_128, _HKI( "CODE_128" ) )
757 .Map( BARCODE_T::DATA_MATRIX, _HKI( "DATA_MATRIX" ) )
758 .Map( BARCODE_T::QR_CODE, _HKI( "QR_CODE" ) )
759 .Map( BARCODE_T::MICRO_QR_CODE, _HKI( "MICRO_QR_CODE" ) );
760 }
761
763 if( eccMap.Choices().GetCount() == 0 )
764 {
765 eccMap.Undefined( BARCODE_ECC_T::L );
766 eccMap.Map( BARCODE_ECC_T::L, _HKI( "L (Low)" ) )
767 .Map( BARCODE_ECC_T::M, _HKI( "M (Medium)" ) )
768 .Map( BARCODE_ECC_T::Q, _HKI( "Q (Quartile)" ) )
769 .Map( BARCODE_ECC_T::H, _HKI( "H (High)" ) );
770 }
771
772 auto hasKnockout =
773 []( INSPECTABLE* aItem ) -> bool
774 {
775 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
776 return bc->IsKnockout();
777 return false;
778 };
779
780 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, wxString>( _HKI( "Text" ),
782
783 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, bool>( _HKI( "Show Text" ),
785
786 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Text Size" ),
788 PROPERTY_DISPLAY::PT_COORD ), groupBarcode );
789
790 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Width" ),
792 PROPERTY_DISPLAY::PT_COORD ), groupBarcode );
793
794 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Height" ),
796 PROPERTY_DISPLAY::PT_COORD ), groupBarcode );
797
798 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, double>( _HKI( "Orientation" ),
800
801 propMgr.AddProperty( new PROPERTY_ENUM<PCB_BARCODE, BARCODE_T>( _HKI( "Barcode Type" ),
803
804 auto isQRCode =
805 []( INSPECTABLE* aItem ) -> bool
806 {
807 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
808 return bc->GetKind() == BARCODE_T::QR_CODE || bc->GetKind() == BARCODE_T::MICRO_QR_CODE;
809
810 return false;
811 };
812
813 propMgr.AddProperty( new PROPERTY_ENUM<PCB_BARCODE, BARCODE_ECC_T>( _HKI( "Error Correction" ),
815 groupBarcode )
816 .SetAvailableFunc( isQRCode )
817 .SetChoicesFunc( []( INSPECTABLE* aItem )
818 {
819 PCB_BARCODE* barcode = static_cast<PCB_BARCODE*>( aItem );
820 wxPGChoices choices;
821
822 choices.Add( _( "L (Low)" ), static_cast<int>( BARCODE_ECC_T::L ) );
823 choices.Add( _( "M (Medium)" ), static_cast<int>( BARCODE_ECC_T::M ) );
824 choices.Add( _( "Q (Quartile)" ), static_cast<int>( BARCODE_ECC_T::Q ) );
825
826 // Only QR_CODE has High
827 if( barcode->GetKind() == BARCODE_T::QR_CODE )
828 choices.Add( _( "H (High)" ), static_cast<int>( BARCODE_ECC_T::H ) );
829
830 return choices;
831 } );
832
833 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, bool>( _HKI( "Knockout" ),
835
836 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Margin X" ),
838 PROPERTY_DISPLAY::PT_COORD ), groupBarcode ).SetAvailableFunc( hasKnockout );
839
840 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Margin Y" ),
842 PROPERTY_DISPLAY::PT_COORD ), groupBarcode ).SetAvailableFunc( hasKnockout );
843 }
845
846// wxAny conversion implementations for enum properties (declarations in header)
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:112
constexpr int ARC_LOW_DEF
Definition base_units.h:128
BITMAPS
A list of all bitmap identifiers.
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:990
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:83
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:85
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:236
PCB_LAYER_ID m_layer
Definition board_item.h:458
bool IsLocked() const override
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)
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:558
constexpr size_type GetWidth() const
Definition box2.h:214
constexpr const Vec GetCenter() const
Definition box2.h:230
constexpr size_type GetHeight() const
Definition box2.h:215
constexpr coord_type GetLeft() const
Definition box2.h:228
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:168
constexpr const Vec & GetOrigin() const
Definition box2.h:210
constexpr coord_type GetRight() const
Definition box2.h:217
constexpr coord_type GetTop() const
Definition box2.h:229
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:311
constexpr coord_type GetBottom() const
Definition box2.h:222
int AsTenthsOfADegree() const
Definition eda_angle.h:118
The base class for create windows for drawing purpose.
EDA_ITEM & operator=(const EDA_ITEM &aItem)
Assign the members of aItem to another object.
Definition eda_item.cpp:328
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
virtual void SetParent(EDA_ITEM *aParent)
Definition eda_item.h:113
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:39
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:727
static ENUM_MAP< T > & Instance()
Definition property.h:721
ENUM_MAP & Undefined(T aValue)
Definition property.h:734
wxPGChoices & Choices()
Definition property.h:770
const wxString & GetReference() const
Definition footprint.h:751
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:37
void SetKind(BARCODE_T aKind)
void SetTextSize(int aTextSize)
Change the height of the human-readable text displayed below the barcode.
void ComputeTextPoly()
Generate the internal polygon representation for the human-readable text.
double GetOrientation() const
virtual std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Some pad shapes can be complex (rounded/chamfered rectangle), even without considering custom shapes.
~PCB_BARCODE()
Destructor.
VECTOR2I m_pos
Position of the barcode.
const BOX2I GetBoundingBox() const override
Get the axis-aligned bounding box of the barcode including text.
void SetBarcodeErrorCorrection(BARCODE_ECC_T aErrorCorrection)
void SetRect(const VECTOR2I &aTopLeft, const VECTOR2I &aBotRight)
Set the bounding rectangle of the barcode.
virtual const BOX2I ViewBBox() const override
Get the bbox used for drawing/view culling, may include additional view-only extents.
SHAPE_POLY_SET m_textPoly
Human-readable text only (cached, centered/positioned)
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.
void SetBarcodeHeight(int aHeight)
void SetShowText(bool aShow)
SHAPE_POLY_SET m_poly
Full geometry (barcode + optional text or knockout)
EDA_ANGLE m_angle
SHAPE_POLY_SET m_symbolPoly
Barcode symbol only (cached, centered at origin)
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 SetBarcodeKind(BARCODE_T aKind)
void GetBoundingHull(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aMaxError, ERROR_LOC aErrorLoc=ERROR_INSIDE) const
void AssembleBarcode()
Assemble the barcode polygon and text polygons into a single polygonal representation.
PCB_BARCODE & operator=(const PCB_BARCODE &aOther)
Copy assignment operator.
VECTOR2I GetPosition() const override
Get the position (center) of the barcode in internal units.
wxString GetText() const
void SetPosition(const VECTOR2I &aPos) override
void SetMarginX(int aX)
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)
BOX2I m_bbox
BBox of m_poly (ie: barcode + text)
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate message panel information entries (e.g.
int GetTextSize() const
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.
wxString GetShownText() const
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.
Definition pcb_barcode.h:96
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.
int m_width
Barcode width.
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...
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipLeftRight) override
Flip the barcode horizontally or vertically around a centre point.
void ComputeBarcode()
Generate the internal polygon representation for the current barcode text, kind and error correction.
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 SetText(const wxString &aText)
Set the barcode content text to encode.
void Move(const VECTOR2I &offset) override
Function Move.
PROPERTY_BASE & SetChoicesFunc(std::function< wxPGChoices(INSPECTABLE *)> aFunc)
Definition property.h:276
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:262
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.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void Fracture()
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
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 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.
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
@ CHAMFER_ACUTE_CORNERS
Acute angles are chamfered.
#define _(s)
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:415
#define PCB_EDIT_FRAME_NAME
int GetPenSizeForNormal(int aTextSize)
Definition gr_text.cpp:61
PCB_LAYER_ID FlipLayer(PCB_LAYER_ID aLayerId, int aCopperLayersCount)
Definition layer_id.cpp:172
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition layer_ids.h:184
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition layer_ids.h:803
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:60
@ Dwgs_User
Definition layer_ids.h:107
@ UNDEFINED_LAYER
Definition layer_ids.h:61
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:45
FLIP_DIRECTION
Definition mirror.h:27
@ LEFT_RIGHT
Flip left to right (around the Y axis)
Definition mirror.h:28
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
Definition mirror.h:29
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.
#define _HKI(x)
Definition page_info.cpp:44
static struct PCB_BARCODE_DESC _PCB_BARCODE_DESC
BARCODE class definition.
BARCODE_ECC_T
Definition pcb_barcode.h:52
BARCODE_T
Definition pcb_barcode.h:43
see class PGM_BASE
#define TYPE_HASH(x)
Definition property.h:74
#define IMPLEMENT_ENUM_TO_WXANY(type)
Definition property.h:821
@ 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:229
constexpr auto to_underlying(E e) noexcept
@ PCB_BARCODE_T
class PCB_BARCODE, a barcode (graphic item)
Definition typeinfo.h:101
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:695