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