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{
74 VECTOR2I delta = aPos - m_pos;
75 Move( delta );
76}
77
78
80{
81 return m_pos;
82}
83
84
85void PCB_BARCODE::SetText( const wxString& aNewText )
86{
87 m_text.SetText( aNewText );
88}
89
90
91wxString PCB_BARCODE::GetText() const
92{
93 return m_text.GetText();
94}
95
96
98{
99 return m_text.GetShownText( true );
100}
101
102
104{
105 m_layer = aLayer;
106 m_text.SetLayer( aLayer );
107
109}
110
111
112void PCB_BARCODE::SetTextSize( int aTextSize )
113{
114 m_text.SetTextSize( VECTOR2I( std::max( 1, aTextSize ), std::max( 1, aTextSize ) ) );
115 m_text.SetTextThickness( std::max( 1, GetPenSizeForNormal( m_text.GetTextHeight() ) ) );
116
118}
119
120
122{
123 return m_text.GetTextHeight();
124}
125
126
127void PCB_BARCODE::Move( const VECTOR2I& offset )
128{
129 m_pos += offset;
130 m_symbolPoly.Move( offset );
131 m_textPoly.Move( offset );
132 m_poly.Move( offset );
133 m_text.Move( offset );
134 m_bbox.Move( offset );
135}
136
137
138void PCB_BARCODE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
139{
140 RotatePoint( m_pos, aRotCentre, aAngle );
141 m_angle += aAngle;
142
144}
145
146
147void PCB_BARCODE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
148{
149 MIRROR( m_pos, aCentre, aFlipDirection );
150
151 if( aFlipDirection == FLIP_DIRECTION::TOP_BOTTOM )
153
155
157}
158
159
160void PCB_BARCODE::StyleFromSettings( const BOARD_DESIGN_SETTINGS& settings, bool aCheckSide )
161{
162 SetTextSize( settings.GetTextSize( GetLayer() ).y );
163}
164
165
167{
169
170 // Scale the symbol polygon to the desired barcode width/height (property values) and center it at m_pos
171 // Note: SetRect will rescale the symbol-only polygon and then rebuild m_poly
172 SetRect( m_pos - VECTOR2I( m_width / 2, m_height / 2 ),
173 m_pos + VECTOR2I( m_width / 2, m_height / 2 ) );
174
176
177 // Build full m_poly from symbol + optional text, then apply knockout if requested
178 m_poly.RemoveAllContours();
179 m_poly.Append( m_symbolPoly );
180
181 if( m_text.IsVisible() && m_textPoly.OutlineCount() )
182 m_poly.Append( m_textPoly );
183
184 m_poly.Fracture();
185
186 if( IsKnockout() )
187 {
188 // Enforce minimum margin: at least 10% of the smallest side of the barcode, rounded up
189 // to the nearest 0.1 mm. Use this as a lower bound for both axes.
190 int minSide = std::min( m_width, m_height );
191 int tenPercent = ( minSide + 9 ) / 10; // ceil(minSide * 0.1)
192 int step01mm = std::max( 1, pcbIUScale.mmToIU( 0.1 ) );
193 int tenPercentRounded = ( ( tenPercent + step01mm - 1 ) / step01mm ) * step01mm;
194
195 // Build inversion rectangle based on the local bbox of the current combined geometry
196 BOX2I bbox = m_poly.BBox();
197 bbox.Inflate( std::max( m_margin.x, tenPercentRounded ), std::max( m_margin.y, tenPercentRounded ) );
198
199 SHAPE_LINE_CHAIN rect;
200 rect.Append( bbox.GetLeft(), bbox.GetTop() );
201 rect.Append( bbox.GetRight(), bbox.GetTop() );
202 rect.Append( bbox.GetRight(), bbox.GetBottom() );
203 rect.Append( bbox.GetLeft(), bbox.GetBottom() );
204 rect.SetClosed( true );
205
207 ko.AddOutline( rect );
209 ko.Fracture();
210 m_poly = std::move( ko );
211 }
212
215
216 if( !m_angle.IsZero() )
217 m_poly.Rotate( m_angle, m_pos );
218
219 m_poly.CacheTriangulation( false );
220 m_bbox = m_poly.BBox();
221}
222
223
225{
226 m_textPoly.RemoveAllContours();
227
228 if( !m_text.IsVisible() )
229 return;
230
231 SHAPE_POLY_SET textPoly;
232 m_text.TransformTextToPolySet( textPoly, 0, GetMaxError(), ERROR_INSIDE );
233
234 if( textPoly.OutlineCount() == 0 )
235 return;
236
237 if( m_symbolPoly.OutlineCount() == 0 )
238 return;
239
240 BOX2I textBBox = textPoly.BBox();
241 BOX2I symbolBBox = m_symbolPoly.BBox();
242 VECTOR2I textPos;
243 int textOffset = pcbIUScale.mmToIU( 1 );
244 textPos.x = symbolBBox.GetCenter().x - textBBox.GetCenter().x;
245 textPos.y = symbolBBox.GetBottom() - textBBox.GetTop() + textOffset;
246
247 textPoly.Move( textPos );
248
249 m_textPoly = std::move( textPoly );
250 m_textPoly.CacheTriangulation();
251}
252
253
255{
256 m_symbolPoly.RemoveAllContours();
257
258 std::unique_ptr<zint_symbol, decltype( &ZBarcode_Delete )> symbol( ZBarcode_Create(), &ZBarcode_Delete );
259
260 if( !symbol )
261 {
262 wxLogError( wxT( "Zint: failed to allocate symbol" ) );
263 return;
264 }
265
266 symbol->input_mode = UNICODE_MODE;
267 symbol->show_hrt = 0; // do not show HRT
268
269 switch( m_kind )
270 {
272 symbol->symbology = BARCODE_CODE39;
273 break;
275 symbol->symbology = BARCODE_CODE128;
276 break;
278 symbol->symbology = BARCODE_QRCODE;
279 symbol->option_1 = to_underlying( m_errorCorrection );
280 break;
282 symbol->symbology = BARCODE_MICROQR;
283 symbol->option_1 = to_underlying( m_errorCorrection );
284 break;
286 symbol->symbology = BARCODE_DATAMATRIX;
287 break;
288 default:
289 wxLogError( wxT( "Zint: invalid barcode type" ) );
290 return;
291 }
292
293 wxString text = GetText();
294 wxScopedCharBuffer utf8Text = text.ToUTF8();
295 size_t length = utf8Text.length();
296 unsigned char* dataPtr = reinterpret_cast<unsigned char*>( utf8Text.data() );
297
298 if( text.empty() )
299 return;
300
301 if( ZBarcode_Encode( symbol.get(), dataPtr, length ) )
302 {
303 wxLogDebug( wxT( "Zint encode error: %s" ), wxString::FromUTF8( symbol->errtxt ) );
304 return;
305 }
306
307 if( ZBarcode_Buffer_Vector( symbol.get(), 0 ) ) // 0 means success
308 {
309 wxLogDebug( wxT( "Zint render error: %s" ), wxString::FromUTF8( symbol->errtxt ) );
310 return;
311 }
312
313 for( zint_vector_rect* rect = symbol->vector->rectangles; rect != nullptr; rect = rect->next )
314 {
315 // Round using absolute edges to avoid cumulative rounding drift across modules.
316 int x1 = KiROUND( rect->x * symbol->scale );
317 int x2 = KiROUND( ( rect->x + rect->width ) * symbol->scale );
318 int y1 = KiROUND( rect->y * symbol->scale );
319 int y2 = KiROUND( ( rect->y + rect->height ) * symbol->scale );
320
321 SHAPE_LINE_CHAIN shapeline;
322 shapeline.Append( x1, y1 );
323 shapeline.Append( x2, y1 );
324 shapeline.Append( x2, y2 );
325 shapeline.Append( x1, y2 );
326 shapeline.SetClosed( true );
327
328 m_symbolPoly.AddOutline( shapeline );
329 }
330
331 for( zint_vector_hexagon* hex = symbol->vector->hexagons; hex != nullptr; hex = hex->next )
332 {
333 // Compute vertices from center using minimal-diameter (inscribed circle) radius.
334 double r = hex->diameter / 2.0; // minimal radius
335 double cx = hex->x;
336 double cy = hex->y;
337
338 // Base orientation has apex at top; hex->rotation rotates by 0/90/180/270 degrees.
339 double baseAngles[6] = { 90.0, 30.0, -30.0, -90.0, -150.0, 150.0 };
340 double rot = static_cast<double>( hex->rotation );
341
342 SHAPE_LINE_CHAIN poly;
343
344 for( int k = 0; k < 6; ++k )
345 {
346 double ang = ( baseAngles[k] + rot ) * M_PI / 180.0;
347 int vx = KiROUND( cx + r * cos( ang ) );
348 int vy = KiROUND( cy + r * sin( ang ) );
349 poly.Append( vx, vy );
350 }
351 poly.SetClosed( true );
352
353 m_symbolPoly.AddOutline( poly );
354 }
355
356 // Set the position of the barcode to the center of the symbol polygon
357 if( m_symbolPoly.OutlineCount() > 0 )
358 {
359 VECTOR2I pos = m_symbolPoly.BBox().GetCenter();
360 m_symbolPoly.Move( -pos );
361 }
362
363 m_symbolPoly.CacheTriangulation();
364}
365
366
367void PCB_BARCODE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
368{
369 FOOTPRINT* parentFP = GetParentFootprint();
370
371 if( parentFP && aFrame->GetName() == PCB_EDIT_FRAME_NAME )
372 aList.emplace_back( _( "Footprint" ), parentFP->GetReference() );
373
374 aList.emplace_back( _( "Barcode" ), ENUM_MAP<BARCODE_T>::Instance().ToString( m_kind ) );
375
376 // Don't use GetShownText() here; we want to show the user the variable references
377 aList.emplace_back( _( "Text" ), KIUI::EllipsizeStatusText( aFrame, GetText() ) );
378
379 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
380 aList.emplace_back( _( "Status" ), _( "Locked" ) );
381
382 aList.emplace_back( _( "Layer" ), GetLayerName() );
383
384 aList.emplace_back( _( "Angle" ), wxString::Format( wxT( "%g" ), m_angle.AsDegrees() ) );
385
386 aList.emplace_back( _( "Text Height" ), aFrame->MessageTextFromValue( m_text.GetTextHeight() ) );
387}
388
389
390bool PCB_BARCODE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
391{
392 if( !GetBoundingBox().Contains( aPosition ) )
393 return false;
394
395 SHAPE_POLY_SET hulls;
396
398
399 return hulls.Collide( aPosition );
400}
401
402
403bool PCB_BARCODE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
404{
405 BOX2I arect = aRect;
406 arect.Inflate( aAccuracy );
407
408 BOX2I rect = GetBoundingBox();
409
410 if( aAccuracy )
411 rect.Inflate( aAccuracy );
412
413 if( aContained )
414 return arect.Contains( rect );
415
416 return arect.Intersects( rect );
417}
418
419
420void PCB_BARCODE::SetRect( const VECTOR2I& aTopLeft, const VECTOR2I& aBotRight )
421{
422 // Rescale only the symbol polygon to the requested rectangle; text is rebuilt below
423 BOX2I bbox = m_symbolPoly.BBox();
424 int oldW = bbox.GetWidth();
425 int oldH = bbox.GetHeight();
426
427 VECTOR2I newPosition = ( aTopLeft + aBotRight ) / 2;
428 SetPosition( newPosition );
429 int newW = aBotRight.x - aTopLeft.x;
430 int newH = aBotRight.y - aTopLeft.y;
431 // Guard against zero/negative sizes from interactive edits; enforce a tiny minimum
432 int minIU = std::max( 1, pcbIUScale.mmToIU( 0.01 ) );
433 newW = std::max( newW, minIU );
434 newH = std::max( newH, minIU );
435
436 double scaleX = oldW ? static_cast<double>( newW ) / oldW : 1.0;
437 double scaleY = oldH ? static_cast<double>( newH ) / oldH : 1.0;
438
439 VECTOR2I oldCenter = bbox.GetCenter();
440 m_symbolPoly.Scale( scaleX, scaleY, oldCenter );
441
442 // After scaling, move the symbol polygon to be centered at the new position
443 VECTOR2I newCenter = m_symbolPoly.BBox().GetCenter();
444 VECTOR2I delta = newPosition - newCenter;
445
446 if( delta != VECTOR2I( 0, 0 ) )
447 m_symbolPoly.Move( delta );
448
449 // Update intended barcode symbol size (without text/margins)
450 m_width = newW;
451 m_height = newH;
452}
453
454
456{
457 return m_bbox;
458}
459
460
461wxString PCB_BARCODE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
462{
463 return wxString::Format( _( "Barcode '%s' on %s" ), GetText(), GetLayerName() );
464}
465
466
471
472
474{
475 return m_bbox;
476}
477
478
480 int aClearance, int aMaxError,
481 ERROR_LOC aErrorLoc, bool ignoreLineWidth ) const
482{
483 if( aLayer != m_layer && aLayer != UNDEFINED_LAYER )
484 return;
485
486 if( aClearance == 0 )
487 {
488 aBuffer.Append( m_poly );
489 }
490 else
491 {
492 SHAPE_POLY_SET poly = m_poly;
493 poly.Inflate( aClearance, CORNER_STRATEGY::CHAMFER_ACUTE_CORNERS, aMaxError, aErrorLoc );
494 aBuffer.Append( poly );
495 }
496}
497
498
499std::shared_ptr<SHAPE> PCB_BARCODE::GetEffectiveShape( PCB_LAYER_ID aLayer, FLASHING aFlash ) const
500{
501 SHAPE_POLY_SET poly;
502 TransformShapeToPolygon( poly, aLayer, 0, 0, ERROR_INSIDE, true );
503
504 return std::make_shared<SHAPE_POLY_SET>( std::move( poly ) );
505}
506
507
508void PCB_BARCODE::GetBoundingHull( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int aClearance,
509 int aMaxError, ERROR_LOC aErrorLoc ) const
510{
511 auto getBoundingHull =
512 [this]( SHAPE_POLY_SET& aLocBuffer, const SHAPE_POLY_SET& aSource, int aLocClearance )
513 {
514 BOX2I rect = aSource.BBox( aLocClearance );
515 VECTOR2I corners[4];
516
517 corners[0].x = rect.GetOrigin().x;
518 corners[0].y = rect.GetOrigin().y;
519 corners[1].y = corners[0].y;
520 corners[1].x = rect.GetRight();
521 corners[2].x = corners[1].x;
522 corners[2].y = rect.GetBottom();
523 corners[3].y = corners[2].y;
524 corners[3].x = corners[0].x;
525
526 aLocBuffer.NewOutline();
527
528 for( VECTOR2I& corner : corners )
529 {
530 RotatePoint( corner, m_pos, m_angle );
531 aLocBuffer.Append( corner.x, corner.y );
532 }
533 };
534
535 if( aLayer == m_layer || aLayer == UNDEFINED_LAYER )
536 {
537 getBoundingHull( aBuffer, m_symbolPoly, aClearance );
538 getBoundingHull( aBuffer, m_textPoly, aClearance );
539 }
540}
541
542
544{
545 // Micro QR codes do not support High (H) error correction level
546 if( m_kind == BARCODE_T::MICRO_QR_CODE && aErrorCorrection == BARCODE_ECC_T::H )
548 else
549 m_errorCorrection = aErrorCorrection;
550 // Don't auto-compute here as it may be called during loading
551}
552
553
555{
556 m_kind = aKind;
557
558 // When switching to Micro QR, validate and adjust ECC if needed
561
562 // Don't auto-compute here as it may be called during loading
563}
564
565
567{
568 SetErrorCorrection( aErrorCorrection );
570}
571
572
574{
575 m_width = aWidth;
576
577 if( KeepSquare() )
578 m_height = aWidth;
579
581}
582
583
585{
586 m_height = aHeight;
587
588 if( KeepSquare() )
589 m_width = aHeight;
590
592}
593
594
596{
597 SetKind( aKind );
599}
600
601
603{
604 PCB_BARCODE* item = new PCB_BARCODE( *this );
605 item->CopyFrom( this );
606 item->m_text.SetParent( item );
607 return item;
608}
609
610
612{
613 wxCHECK_RET( aImage && aImage->Type() == PCB_BARCODE_T,
614 wxT( "Cannot swap data with non-barcode item." ) );
615
616 PCB_BARCODE* other = static_cast<PCB_BARCODE*>( aImage );
617
618 std::swap( *this, *other );
619
620 m_text.SetParent( this );
621 other->m_text.SetParent( other );
622}
623
624double PCB_BARCODE::Similarity( const BOARD_ITEM& aItem ) const
625{
626 if( !ClassOf( &aItem ) )
627 return 0.0;
628
629 const PCB_BARCODE* other = static_cast<const PCB_BARCODE*>( &aItem );
630
631 // Compare text, width, height, text height, position, and kind
632 double similarity = 0.0;
633 const double weight = 1.0 / 6.0;
634
635 if( GetText() == other->GetText() )
636 similarity += weight;
637 if( m_width == other->m_width )
638 similarity += weight;
639 if( m_height == other->m_height )
640 similarity += weight;
641 if( GetTextSize() == other->GetTextSize() )
642 similarity += weight;
643 if( GetPosition() == other->GetPosition() )
644 similarity += weight;
645 if( m_kind == other->m_kind )
646 similarity += weight;
647
648 return similarity;
649}
650
651int PCB_BARCODE::Compare( const PCB_BARCODE* aBarcode, const PCB_BARCODE* aOther )
652{
653 int diff;
654
655 if( ( diff = aBarcode->GetPosition().x - aOther->GetPosition().x ) != 0 )
656 return diff;
657
658 if( ( diff = aBarcode->GetPosition().y - aOther->GetPosition().y ) != 0 )
659 return diff;
660
661 if( ( diff = aBarcode->GetText().Cmp( aOther->GetText() ) ) != 0 )
662 return diff;
663
664 if( ( diff = aBarcode->GetWidth() - aOther->GetWidth() ) != 0 )
665 return diff;
666
667 if( ( diff = aBarcode->GetHeight() - aOther->GetHeight() ) != 0 )
668 return diff;
669
670 if( ( diff = aBarcode->GetTextSize() - aOther->GetTextSize() ) != 0 )
671 return diff;
672
673 if( ( diff = (int) aBarcode->GetKind() - (int) aOther->GetKind() ) != 0 )
674 return diff;
675
676 if( ( diff = (int) aBarcode->GetErrorCorrection() - (int) aOther->GetErrorCorrection() ) != 0 )
677 return diff;
678
679 return 0;
680}
681
682
683bool PCB_BARCODE::operator==( const BOARD_ITEM& aItem ) const
684{
685 if( !ClassOf( &aItem ) )
686 return false;
687
688 const PCB_BARCODE* other = static_cast<const PCB_BARCODE*>( &aItem );
689
690 // Compare text, width, height, text height, position, and kind
691 return ( GetText() == other->GetText()
692 && m_width == other->m_width
693 && m_height == other->m_height
694 && GetTextSize() == other->GetTextSize()
695 && GetPosition() == other->GetPosition()
696 && m_kind == other->m_kind );
697}
698
699// ---- Property registration ----
700static struct PCB_BARCODE_DESC
701{
703 {
707
708 const wxString groupBarcode = _HKI( "Barcode Properties" );
709
711 if( kindMap.Choices().GetCount() == 0 )
712 {
713 kindMap.Undefined( BARCODE_T::QR_CODE );
714 kindMap.Map( BARCODE_T::CODE_39, _HKI( "CODE_39" ) )
715 .Map( BARCODE_T::CODE_128, _HKI( "CODE_128" ) )
716 .Map( BARCODE_T::DATA_MATRIX, _HKI( "DATA_MATRIX" ) )
717 .Map( BARCODE_T::QR_CODE, _HKI( "QR_CODE" ) )
718 .Map( BARCODE_T::MICRO_QR_CODE, _HKI( "MICRO_QR_CODE" ) );
719 }
720
722 if( eccMap.Choices().GetCount() == 0 )
723 {
724 eccMap.Undefined( BARCODE_ECC_T::L );
725 eccMap.Map( BARCODE_ECC_T::L, _HKI( "L (Low)" ) )
726 .Map( BARCODE_ECC_T::M, _HKI( "M (Medium)" ) )
727 .Map( BARCODE_ECC_T::Q, _HKI( "Q (Quartile)" ) )
728 .Map( BARCODE_ECC_T::H, _HKI( "H (High)" ) );
729 }
730
731 auto hasKnockout =
732 []( INSPECTABLE* aItem ) -> bool
733 {
734 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
735 return bc->IsKnockout();
736 return false;
737 };
738
739 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, wxString>( _HKI( "Text" ),
741
742 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, bool>( _HKI( "Show Text" ),
744
745 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Text Size" ),
747 PROPERTY_DISPLAY::PT_COORD ), groupBarcode );
748
749 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Width" ),
751 PROPERTY_DISPLAY::PT_COORD ), groupBarcode );
752
753 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Height" ),
755 PROPERTY_DISPLAY::PT_COORD ), groupBarcode );
756
757 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, double>( _HKI( "Orientation" ),
759
760 propMgr.AddProperty( new PROPERTY_ENUM<PCB_BARCODE, BARCODE_T>( _HKI( "Barcode Type" ),
762
763 auto isQRCode =
764 []( INSPECTABLE* aItem ) -> bool
765 {
766 if( PCB_BARCODE* bc = dynamic_cast<PCB_BARCODE*>( aItem ) )
767 return bc->GetKind() == BARCODE_T::QR_CODE || bc->GetKind() == BARCODE_T::MICRO_QR_CODE;
768
769 return false;
770 };
771
772 propMgr.AddProperty( new PROPERTY_ENUM<PCB_BARCODE, BARCODE_ECC_T>( _HKI( "Error Correction" ),
774 groupBarcode )
775 .SetAvailableFunc( isQRCode )
776 .SetChoicesFunc( []( INSPECTABLE* aItem )
777 {
778 PCB_BARCODE* barcode = static_cast<PCB_BARCODE*>( aItem );
779 wxPGChoices choices;
780
781 choices.Add( _( "L (Low)" ), static_cast<int>( BARCODE_ECC_T::L ) );
782 choices.Add( _( "M (Medium)" ), static_cast<int>( BARCODE_ECC_T::M ) );
783 choices.Add( _( "Q (Quartile)" ), static_cast<int>( BARCODE_ECC_T::Q ) );
784
785 // Only QR_CODE has High
786 if( barcode->GetKind() == BARCODE_T::QR_CODE )
787 choices.Add( _( "H (High)" ), static_cast<int>( BARCODE_ECC_T::H ) );
788
789 return choices;
790 } );
791
792 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, bool>( _HKI( "Knockout" ),
794
795 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Margin X" ),
797 PROPERTY_DISPLAY::PT_COORD ), groupBarcode ).SetAvailableFunc( hasKnockout );
798
799 propMgr.AddProperty( new PROPERTY<PCB_BARCODE, int>( _HKI( "Margin Y" ),
801 PROPERTY_DISPLAY::PT_COORD ), groupBarcode ).SetAvailableFunc( hasKnockout );
802 }
804
805// 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:79
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:81
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
Definition board_item.h:232
PCB_LAYER_ID m_layer
Definition board_item.h:453
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
The base class for create windows for drawing purpose.
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:661
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.
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:86
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:802
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