KiCad PCB EDA Suite
lib_pin.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) 2016 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2015 Wayne Stambaugh <[email protected]>
6 * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, you may find one here:
20 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21 * or you may search the http://www.gnu.org website for the version 2 license,
22 * or you may write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26#include <base_units.h>
27#include <pgm_base.h>
28#include <sch_draw_panel.h>
29#include <sch_edit_frame.h>
30#include <symbol_edit_frame.h>
31#include <lib_pin.h>
34#include <trigo.h>
35#include <string_utils.h>
36#include "sch_painter.h"
37#include "plotters/plotter.h"
38
39
40// small margin in internal units between the pin text and the pin line
41#define PIN_TEXT_MARGIN 4
42
44{
45 // These strings are the canonical name of the electrictal type
46 // Not translated, no space in name, only ASCII chars.
47 // to use when the string name must be known and well defined
48 // must have same order than enum ELECTRICAL_PINTYPE (see lib_pin.h)
49 static const wxChar* msgPinElectricType[] =
50 {
51 wxT( "input" ),
52 wxT( "output" ),
53 wxT( "bidirectional" ),
54 wxT( "tri_state" ),
55 wxT( "passive" ),
56 wxT( "free" ),
57 wxT( "unspecified" ),
58 wxT( "power_in" ),
59 wxT( "power_out" ),
60 wxT( "open_collector" ),
61 wxT( "open_emitter" ),
62 wxT( "no_connect" )
63 };
64
65 return msgPinElectricType[static_cast<int>( aType )];
66}
67
68
70// i.e. the clock symbols (falling clock is actually external but is of
71// the same kind)
72
73static int internalPinDecoSize( const RENDER_SETTINGS* aSettings, const LIB_PIN &aPin )
74{
75 const KIGFX::SCH_RENDER_SETTINGS* settings = static_cast<const KIGFX::SCH_RENDER_SETTINGS*>( aSettings );
76
77 if( settings && settings->m_PinSymbolSize )
78 return settings->m_PinSymbolSize;
79
80 return aPin.GetNameTextSize() != 0 ? aPin.GetNameTextSize() / 2 : aPin.GetNumberTextSize() / 2;
81}
82
84// i.e. the negation circle, the polarity 'slopes' and the nonlogic
85// marker
86static int externalPinDecoSize( const RENDER_SETTINGS* aSettings, const LIB_PIN &aPin )
87{
88 const KIGFX::SCH_RENDER_SETTINGS* settings = static_cast<const KIGFX::SCH_RENDER_SETTINGS*>( aSettings );
89
90 if( settings && settings->m_PinSymbolSize )
91 return settings->m_PinSymbolSize;
92
93 return aPin.GetNumberTextSize() / 2;
94}
95
96
98 LIB_ITEM( LIB_PIN_T, aParent ),
99 m_orientation( PIN_RIGHT ),
100 m_shape( GRAPHIC_PINSHAPE::LINE ),
102 m_attributes( 0 )
103{
104 // Use the application settings for pin sizes if exists.
105 // pgm can be nullptr when running a shared lib from a script, not from a kicad appl
106 PGM_BASE* pgm = PgmOrNull();
107
108 if( pgm )
109 {
111 m_length = schIUScale.MilsToIU( settings->m_Defaults.pin_length );
112 m_numTextSize = schIUScale.MilsToIU( settings->m_Defaults.pin_num_size );
113 m_nameTextSize = schIUScale.MilsToIU( settings->m_Defaults.pin_name_size );
114 }
115 else // Use hardcoded eeschema defaults: symbol_editor settings are not existing.
116 {
120 }
121}
122
123
124LIB_PIN::LIB_PIN( LIB_SYMBOL* aParent, const wxString& aName, const wxString& aNumber,
125 int aOrientation, ELECTRICAL_PINTYPE aPinType, int aLength, int aNameTextSize,
126 int aNumTextSize, int aConvert, const VECTOR2I& aPos, int aUnit ) :
127 LIB_ITEM( LIB_PIN_T, aParent ),
128 m_position( aPos ),
129 m_length( aLength ),
130 m_orientation( aOrientation ),
131 m_shape( GRAPHIC_PINSHAPE::LINE ),
132 m_type( aPinType ),
133 m_attributes( 0 ),
134 m_numTextSize( aNumTextSize ),
135 m_nameTextSize( aNameTextSize )
136{
137 SetName( aName );
138 SetNumber( aNumber );
139 SetUnit( aUnit );
140 SetConvert( aConvert );
141}
142
143
144bool LIB_PIN::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
145{
146 BOX2I rect = GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE );
147
148 return rect.Inflate( aAccuracy ).Contains( aPosition );
149}
150
151
152bool LIB_PIN::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
153{
155 return false;
156
157 BOX2I sel = aRect;
158
159 if ( aAccuracy )
160 sel.Inflate( aAccuracy );
161
162 if( aContained )
163 return sel.Contains( GetBoundingBox( false, false, false ) );
164
165 return sel.Intersects( GetBoundingBox( false, true, m_flags & SHOW_ELEC_TYPE ) );
166}
167
168
170{
171 return 0;
172}
173
174
175wxString LIB_PIN::GetShownName() const
176{
177 if( m_name == wxS( "~" ) )
178 return wxEmptyString;
179 else
180 return m_name;
181}
182
183
185{
186 switch( m_orientation )
187 {
188 default:
189 case PIN_RIGHT: return VECTOR2I( m_position.x + m_length, -( m_position.y ) );
190 case PIN_LEFT: return VECTOR2I( m_position.x - m_length, -( m_position.y ) );
191 case PIN_UP: return VECTOR2I( m_position.x, -( m_position.y + m_length ) );
192 case PIN_DOWN: return VECTOR2I( m_position.x, -( m_position.y - m_length ) );
193 }
194}
195
196
197void LIB_PIN::print( const RENDER_SETTINGS* aSettings, const VECTOR2I& aOffset, void* aData,
198 const TRANSFORM& aTransform, bool aDimmed )
199{
200 LIB_SYMBOL_OPTIONS* opts = (LIB_SYMBOL_OPTIONS*) aData;
201 bool drawHiddenFields = opts ? opts->draw_hidden_fields : false;
202 bool showPinType = opts ? opts->show_elec_type : false;
203 bool show_connect_point = opts ? opts->show_connect_point : false;
204
205 LIB_SYMBOL* part = GetParent();
206
207 wxCHECK( part && opts, /* void */ );
208
209 /* Calculate pin orient taking in account the symbol orientation. */
210 int orient = PinDrawOrient( aTransform );
211
212 /* Calculate the pin position */
213 VECTOR2I pos1 = aTransform.TransformCoordinate( m_position ) + aOffset;
214
215 if( IsVisible() || drawHiddenFields )
216 {
217 printPinSymbol( aSettings, pos1, orient, aDimmed );
218
219 printPinTexts( aSettings, pos1, orient, part->GetPinNameOffset(),
220 opts->force_draw_pin_text || part->ShowPinNumbers(),
221 opts->force_draw_pin_text || part->ShowPinNames(),
222 aDimmed );
223
224 if( showPinType )
225 printPinElectricalTypeName( aSettings, pos1, orient, aDimmed );
226
227 if( show_connect_point
230 {
231 wxDC* DC = aSettings->GetPrintDC();
233
234 COLOR4D bg = aSettings->GetBackgroundColor();
235
236 if( bg == COLOR4D::UNSPECIFIED || GetGRForceBlackPenState() )
237 bg = COLOR4D::WHITE;
238
239 if( aDimmed )
240 {
241 color.Desaturate( );
242 color = color.Mix( bg, 0.5f );
243 }
244
245 GRCircle( DC, pos1, TARGET_PIN_RADIUS, 0, color );
246 }
247 }
248}
249
250
251void LIB_PIN::printPinSymbol( const RENDER_SETTINGS* aSettings, const VECTOR2I& aPos, int aOrient, bool aDimmed )
252{
253 wxDC* DC = aSettings->GetPrintDC();
254 int MapX1, MapY1, x1, y1;
255 int width = GetEffectivePenWidth( aSettings );
256 int posX = aPos.x, posY = aPos.y, len = m_length;
258 COLOR4D bg = aSettings->GetBackgroundColor();
259
260 if( bg == COLOR4D::UNSPECIFIED || GetGRForceBlackPenState() )
261 bg = COLOR4D::WHITE;
262
263 if( !IsVisible() )
264 bg = aSettings->GetLayerColor( LAYER_HIDDEN );
265
266 if( aDimmed )
267 {
268 color.Desaturate( );
269 color = color.Mix( bg, 0.5f );
270 }
271
272 MapX1 = MapY1 = 0;
273 x1 = posX;
274 y1 = posY;
275
276 switch( aOrient )
277 {
278 case PIN_UP: y1 = posY - len; MapY1 = 1; break;
279 case PIN_DOWN: y1 = posY + len; MapY1 = -1; break;
280 case PIN_LEFT: x1 = posX - len; MapX1 = 1; break;
281 case PIN_RIGHT: x1 = posX + len; MapX1 = -1; break;
282 }
283
285 {
286 const int radius = externalPinDecoSize( aSettings, *this );
287 GRCircle( DC, VECTOR2I( MapX1 * radius + x1, MapY1 * radius + y1 ), radius, width, color );
288
289 GRMoveTo( MapX1 * radius * 2 + x1, MapY1 * radius * 2 + y1 );
290 GRLineTo( DC, posX, posY, width, color );
291 }
292 else
293 {
294 GRMoveTo( x1, y1 );
295 GRLineTo( DC, posX, posY, width, color );
296 }
297
298 // Draw the clock shape (>)inside the symbol
303 {
304 const int clock_size = internalPinDecoSize( aSettings, *this );
305 if( MapY1 == 0 ) /* MapX1 = +- 1 */
306 {
307 GRMoveTo( x1, y1 + clock_size );
308 GRLineTo( DC, x1 - MapX1 * clock_size * 2, y1, width, color );
309 GRLineTo( DC, x1, y1 - clock_size, width, color );
310 }
311 else /* MapX1 = 0 */
312 {
313 GRMoveTo( x1 + clock_size, y1 );
314 GRLineTo( DC, x1, y1 - MapY1 * clock_size * 2, width, color );
315 GRLineTo( DC, x1 - clock_size, y1, width, color );
316 }
317 }
318
319 // Draw the active low (or H to L active transition)
323 {
324 const int deco_size = externalPinDecoSize( aSettings, *this );
325 if( MapY1 == 0 ) /* MapX1 = +- 1 */
326 {
327 GRMoveTo( x1 + MapX1 * deco_size * 2, y1 );
328 GRLineTo( DC, x1 + MapX1 * deco_size * 2, y1 - deco_size * 2, width, color );
329 GRLineTo( DC, x1, y1, width, color );
330 }
331 else /* MapX1 = 0 */
332 {
333 GRMoveTo( x1, y1 + MapY1 * deco_size * 2 );
334 GRLineTo( DC, x1 - deco_size * 2, y1 + MapY1 * deco_size * 2, width, color );
335 GRLineTo( DC, x1, y1, width, color );
336 }
337 }
338
339 if( m_shape == GRAPHIC_PINSHAPE::OUTPUT_LOW ) /* IEEE symbol "Active Low Output" */
340 {
341 const int deco_size = externalPinDecoSize( aSettings, *this );
342 if( MapY1 == 0 ) /* MapX1 = +- 1 */
343 {
344 GRMoveTo( x1, y1 - deco_size * 2 );
345 GRLineTo( DC, x1 + MapX1 * deco_size * 2, y1, width, color );
346 }
347 else /* MapX1 = 0 */
348 {
349 GRMoveTo( x1 - deco_size * 2, y1 );
350 GRLineTo( DC, x1, y1 + MapY1 * deco_size * 2, width, color );
351 }
352 }
353 else if( m_shape == GRAPHIC_PINSHAPE::NONLOGIC ) /* NonLogic pin symbol */
354 {
355 const int deco_size = externalPinDecoSize( aSettings, *this );
356 GRMoveTo( x1 - (MapX1 + MapY1) * deco_size, y1 - (MapY1 - MapX1) * deco_size );
357 GRLineTo( DC, x1 + (MapX1 + MapY1) * deco_size, y1 + ( MapY1 - MapX1 ) * deco_size, width,
358 color );
359 GRMoveTo( x1 - (MapX1 - MapY1) * deco_size, y1 - (MapY1 + MapX1) * deco_size );
360 GRLineTo( DC, x1 + (MapX1 - MapY1) * deco_size, y1 + ( MapY1 + MapX1 ) * deco_size, width,
361 color );
362 }
363
364 if( m_type == ELECTRICAL_PINTYPE::PT_NC ) // Draw a N.C. symbol
365 {
366 const int deco_size = TARGET_PIN_RADIUS;
367 GRLine( DC, posX - deco_size, posY - deco_size, posX + deco_size, posY + deco_size, width,
368 color );
369 GRLine( DC, posX + deco_size, posY - deco_size, posX - deco_size, posY + deco_size, width,
370 color );
371 }
372}
373
374
375void LIB_PIN::printPinTexts( const RENDER_SETTINGS* aSettings, VECTOR2I& aPinPos, int aPinOrient,
376 int aTextInside, bool aDrawPinNum, bool aDrawPinName, bool aDimmed )
377{
378 if( !aDrawPinName && !aDrawPinNum )
379 return;
380
381 int x, y;
382 wxDC* DC = aSettings->GetPrintDC();
383 KIFONT::FONT* font = KIFONT::FONT::GetFont( aSettings->GetDefaultFont(), false, false );
384
385 VECTOR2I pinNameSize( m_nameTextSize, m_nameTextSize );
386 VECTOR2I pinNumSize( m_numTextSize, m_numTextSize );
387
388 int namePenWidth = std::max( Clamp_Text_PenSize( GetPenWidth(), m_nameTextSize, true ),
389 aSettings->GetDefaultPenWidth() );
390 int numPenWidth = std::max( Clamp_Text_PenSize( GetPenWidth(), m_numTextSize, true ),
391 aSettings->GetDefaultPenWidth() );
392
393 int name_offset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + namePenWidth;
394 int num_offset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + numPenWidth;
395
396 /* Get the num and name colors */
397 COLOR4D nameColor = aSettings->GetLayerColor( IsVisible() ? LAYER_PINNAM : LAYER_HIDDEN );
398 COLOR4D numColor = aSettings->GetLayerColor( IsVisible() ? LAYER_PINNUM : LAYER_HIDDEN );
399 COLOR4D bg = aSettings->GetBackgroundColor();
400
401 if( bg == COLOR4D::UNSPECIFIED || GetGRForceBlackPenState() )
402 bg = COLOR4D::WHITE;
403
404 if( !IsVisible() )
405 bg = aSettings->GetLayerColor( LAYER_HIDDEN );
406
407 if( aDimmed )
408 {
409 nameColor.Desaturate();
410 numColor.Desaturate();
411 nameColor = nameColor.Mix( bg, 0.5f );
412 numColor = numColor.Mix( bg, 0.5f );
413 }
414
415 int x1 = aPinPos.x;
416 int y1 = aPinPos.y;
417
418 switch( aPinOrient )
419 {
420 case PIN_UP: y1 -= m_length; break;
421 case PIN_DOWN: y1 += m_length; break;
422 case PIN_LEFT: x1 -= m_length; break;
423 case PIN_RIGHT: x1 += m_length; break;
424 }
425
426 wxString name = GetShownName();
427 wxString number = GetShownNumber();
428
429 if( name.IsEmpty() || m_nameTextSize == 0 )
430 aDrawPinName = false;
431
432 if( number.IsEmpty() || m_numTextSize == 0 )
433 aDrawPinNum = false;
434
435 if( aTextInside ) // Draw the text inside, but the pin numbers outside.
436 {
437 if(( aPinOrient == PIN_LEFT) || ( aPinOrient == PIN_RIGHT) )
438 {
439 // It is an horizontal line
440 if( aDrawPinName )
441 {
442 if( aPinOrient == PIN_RIGHT )
443 {
444 x = x1 + aTextInside;
445 GRPrintText( DC, VECTOR2I( x, y1 ), nameColor, name, ANGLE_HORIZONTAL,
447 namePenWidth, false, false, font );
448 }
449 else // Orient == PIN_LEFT
450 {
451 x = x1 - aTextInside;
452 GRPrintText( DC, VECTOR2I( x, y1 ), nameColor, name, ANGLE_HORIZONTAL,
454 namePenWidth, false, false, font );
455 }
456 }
457
458 if( aDrawPinNum )
459 {
460 GRPrintText( DC, VECTOR2I(( x1 + aPinPos.x) / 2, y1 - num_offset ), numColor,
461 number, ANGLE_HORIZONTAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER,
462 GR_TEXT_V_ALIGN_BOTTOM, numPenWidth, false, false, font );
463 }
464 }
465 else /* Its a vertical line. */
466 {
467 // Text is drawn from bottom to top (i.e. to negative value for Y axis)
468 if( aPinOrient == PIN_DOWN )
469 {
470 y = y1 + aTextInside;
471
472 if( aDrawPinName )
473 {
474 GRPrintText( DC, VECTOR2I( x1, y ), nameColor, name, ANGLE_VERTICAL,
476 namePenWidth, false, false, font );
477 }
478
479 if( aDrawPinNum )
480 {
481 GRPrintText( DC, VECTOR2I( x1 - num_offset, ( y1 + aPinPos.y) / 2 ), numColor,
482 number, ANGLE_VERTICAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER,
483 GR_TEXT_V_ALIGN_BOTTOM, numPenWidth, false, false, font );
484 }
485 }
486 else /* PIN_UP */
487 {
488 y = y1 - aTextInside;
489
490 if( aDrawPinName )
491 {
492 GRPrintText( DC, VECTOR2I( x1, y ), nameColor, name, ANGLE_VERTICAL,
494 namePenWidth, false, false, font );
495 }
496
497 if( aDrawPinNum )
498 {
499 GRPrintText( DC, VECTOR2I( x1 - num_offset, ( y1 + aPinPos.y) / 2 ), numColor,
500 number, ANGLE_VERTICAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER,
501 GR_TEXT_V_ALIGN_BOTTOM, numPenWidth, false, false, font );
502 }
503 }
504 }
505 }
506 else /**** Draw num & text pin outside ****/
507 {
508 if( ( aPinOrient == PIN_LEFT) || ( aPinOrient == PIN_RIGHT) )
509 {
510 /* Its an horizontal line. */
511 if( aDrawPinName )
512 {
513 x = ( x1 + aPinPos.x) / 2;
514 GRPrintText( DC, VECTOR2I( x, y1 - name_offset ), nameColor, name, ANGLE_HORIZONTAL,
516 namePenWidth, false, false, font );
517 }
518 if( aDrawPinNum )
519 {
520 x = ( x1 + aPinPos.x) / 2;
521 GRPrintText( DC, VECTOR2I( x, y1 + num_offset ), numColor, number, ANGLE_HORIZONTAL,
523 numPenWidth, false, false, font );
524 }
525 }
526 else /* Its a vertical line. */
527 {
528 if( aDrawPinName )
529 {
530 y = ( y1 + aPinPos.y) / 2;
531 GRPrintText( DC, VECTOR2I( x1 - name_offset, y ), nameColor, name, ANGLE_VERTICAL,
533 namePenWidth, false, false, font );
534 }
535
536 if( aDrawPinNum )
537 {
538 GRPrintText( DC, VECTOR2I( x1 + num_offset, ( y1 + aPinPos.y) / 2 ), numColor,
539 number, ANGLE_VERTICAL, pinNumSize, GR_TEXT_H_ALIGN_CENTER,
540 GR_TEXT_V_ALIGN_TOP, numPenWidth, false, false, font );
541 }
542 }
543 }
544}
545
546
547
549 int aOrientation, bool aDimmed )
550{
551 wxDC* DC = aSettings->GetPrintDC();
552 wxString typeName = GetElectricalTypeName();
553
554 // Use a reasonable (small) size to draw the text
555 int textSize = ( m_nameTextSize * 3 ) / 4;
556
557 #define ETXT_MAX_SIZE schIUScale.mmToIU( 0.7 )
558
559 if( textSize > ETXT_MAX_SIZE )
560 textSize = ETXT_MAX_SIZE;
561
562 // Use a reasonable pen size to draw the text
563 int pensize = textSize/6;
564
565 // Get a suitable color
567 COLOR4D bg = aSettings->GetBackgroundColor();
568
569 if( bg == COLOR4D::UNSPECIFIED || GetGRForceBlackPenState() )
570 bg = COLOR4D::WHITE;
571
572 if( !IsVisible() )
573 bg = aSettings->GetLayerColor( LAYER_HIDDEN );
574
575 if( aDimmed )
576 {
577 color.Desaturate( );
578 color = color.Mix( bg, 0.5f );
579 }
580
581 VECTOR2I txtpos = aPosition;
582 int offset = schIUScale.mmToIU( 0.4 );
585 KIFONT::FONT* font = KIFONT::FONT::GetFont( aSettings->GetDefaultFont(), false, false );
586
587 switch( aOrientation )
588 {
589 case PIN_UP:
590 txtpos.y += offset;
591 orient = ANGLE_VERTICAL;
592 hjustify = GR_TEXT_H_ALIGN_RIGHT;
593 break;
594
595 case PIN_DOWN:
596 txtpos.y -= offset;
597 orient = ANGLE_VERTICAL;
598 break;
599
600 case PIN_LEFT:
601 txtpos.x += offset;
602 break;
603
604 case PIN_RIGHT:
605 txtpos.x -= offset;
606 hjustify = GR_TEXT_H_ALIGN_RIGHT;
607 break;
608 }
609
610 GRPrintText( DC, txtpos, color, typeName, orient, VECTOR2I( textSize, textSize ), hjustify,
611 GR_TEXT_V_ALIGN_CENTER, pensize, false, false, font );
612}
613
614
615void LIB_PIN::PlotSymbol( PLOTTER *aPlotter, const VECTOR2I &aPosition, int aOrientation,
616 bool aDimmed ) const
617{
618 int MapX1, MapY1, x1, y1;
620 COLOR4D bg = aPlotter->RenderSettings()->GetBackgroundColor();
621 int penWidth = GetEffectivePenWidth( aPlotter->RenderSettings() );
622
623 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
624 bg = COLOR4D::WHITE;
625
626 if( aDimmed )
627 {
628 color.Desaturate( );
629 color = color.Mix( bg, 0.5f );
630 }
631
632 aPlotter->SetColor( color );
633 aPlotter->SetCurrentLineWidth( penWidth );
634
635 MapX1 = MapY1 = 0;
636 x1 = aPosition.x; y1 = aPosition.y;
637
638 switch( aOrientation )
639 {
640 case PIN_UP: y1 = aPosition.y - m_length; MapY1 = 1; break;
641 case PIN_DOWN: y1 = aPosition.y + m_length; MapY1 = -1; break;
642 case PIN_LEFT: x1 = aPosition.x - m_length; MapX1 = 1; break;
643 case PIN_RIGHT: x1 = aPosition.x + m_length; MapX1 = -1; break;
644 }
645
647 {
648 const int radius = externalPinDecoSize( aPlotter->RenderSettings(), *this );
649 aPlotter->Circle( VECTOR2I( MapX1 * radius + x1, MapY1 * radius + y1 ), radius * 2,
650 FILL_T::NO_FILL, penWidth );
651
652 aPlotter->MoveTo( VECTOR2I( MapX1 * radius * 2 + x1, MapY1 * radius * 2 + y1 ) );
653 aPlotter->FinishTo( aPosition );
654 }
656 {
657 const int deco_size = internalPinDecoSize( aPlotter->RenderSettings(), *this );
658 if( MapY1 == 0 ) /* MapX1 = +- 1 */
659 {
660 aPlotter->MoveTo( VECTOR2I( x1, y1 + deco_size ) );
661 aPlotter->LineTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 ) );
662 aPlotter->FinishTo( VECTOR2I( x1, y1 - deco_size ) );
663 }
664 else /* MapX1 = 0 */
665 {
666 aPlotter->MoveTo( VECTOR2I( x1 + deco_size, y1 ) );
667 aPlotter->LineTo( VECTOR2I( x1, y1 + MapY1 * deco_size * 2 ) );
668 aPlotter->FinishTo( VECTOR2I( x1 - deco_size, y1 ) );
669 }
670
671 aPlotter->MoveTo( VECTOR2I( MapX1 * deco_size * 2 + x1, MapY1 * deco_size * 2 + y1 ) );
672 aPlotter->FinishTo( aPosition );
673 }
674 else
675 {
676 aPlotter->MoveTo( VECTOR2I( x1, y1 ) );
677 aPlotter->FinishTo( aPosition );
678 }
679
683 {
684 const int deco_size = internalPinDecoSize( aPlotter->RenderSettings(), *this );
685 if( MapY1 == 0 ) /* MapX1 = +- 1 */
686 {
687 aPlotter->MoveTo( VECTOR2I( x1, y1 + deco_size ) );
688 aPlotter->LineTo( VECTOR2I( x1 - MapX1 * deco_size * 2, y1 ) );
689 aPlotter->FinishTo( VECTOR2I( x1, y1 - deco_size ) );
690 }
691 else /* MapX1 = 0 */
692 {
693 aPlotter->MoveTo( VECTOR2I( x1 + deco_size, y1 ) );
694 aPlotter->LineTo( VECTOR2I( x1, y1 - MapY1 * deco_size * 2 ) );
695 aPlotter->FinishTo( VECTOR2I( x1 - deco_size, y1 ) );
696 }
697 }
698
700 || m_shape == GRAPHIC_PINSHAPE::CLOCK_LOW ) /* IEEE symbol "Active Low Input" */
701 {
702 const int deco_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
703
704 if( MapY1 == 0 ) /* MapX1 = +- 1 */
705 {
706 aPlotter->MoveTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 ) );
707 aPlotter->LineTo( VECTOR2I( x1 + MapX1 * deco_size * 2, y1 - deco_size * 2 ) );
708 aPlotter->FinishTo( VECTOR2I( x1, y1 ) );
709 }
710 else /* MapX1 = 0 */
711 {
712 aPlotter->MoveTo( VECTOR2I( x1, y1 + MapY1 * deco_size * 2 ) );
713 aPlotter->LineTo( VECTOR2I( x1 - deco_size * 2, y1 + MapY1 * deco_size * 2 ) );
714 aPlotter->FinishTo( VECTOR2I( x1, y1 ) );
715 }
716 }
717
718 if( m_shape == GRAPHIC_PINSHAPE::OUTPUT_LOW ) /* IEEE symbol "Active Low Output" */
719 {
720 const int symbol_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
721
722 if( MapY1 == 0 ) /* MapX1 = +- 1 */
723 {
724 aPlotter->MoveTo( VECTOR2I( x1, y1 - symbol_size * 2 ) );
725 aPlotter->FinishTo( VECTOR2I( x1 + MapX1 * symbol_size * 2, y1 ) );
726 }
727 else /* MapX1 = 0 */
728 {
729 aPlotter->MoveTo( VECTOR2I( x1 - symbol_size * 2, y1 ) );
730 aPlotter->FinishTo( VECTOR2I( x1, y1 + MapY1 * symbol_size * 2 ) );
731 }
732 }
733 else if( m_shape == GRAPHIC_PINSHAPE::NONLOGIC ) /* NonLogic pin symbol */
734 {
735 const int deco_size = externalPinDecoSize( aPlotter->RenderSettings(), *this );
736 aPlotter->MoveTo( VECTOR2I( x1 - ( MapX1 + MapY1 ) * deco_size,
737 y1 - ( MapY1 - MapX1 ) * deco_size ) );
738 aPlotter->FinishTo( VECTOR2I( x1 + ( MapX1 + MapY1 ) * deco_size,
739 y1 + ( MapY1 - MapX1 ) * deco_size ) );
740 aPlotter->MoveTo( VECTOR2I( x1 - ( MapX1 - MapY1 ) * deco_size,
741 y1 - ( MapY1 + MapX1 ) * deco_size ) );
742 aPlotter->FinishTo( VECTOR2I( x1 + ( MapX1 - MapY1 ) * deco_size,
743 y1 + ( MapY1 + MapX1 ) * deco_size ) );
744 }
745
746 if( m_type == ELECTRICAL_PINTYPE::PT_NC ) // Draw a N.C. symbol
747 {
748 const int deco_size = TARGET_PIN_RADIUS;
749 const int ex1 = aPosition.x;
750 const int ey1 = aPosition.y;
751 aPlotter->MoveTo( VECTOR2I( ex1 - deco_size, ey1 - deco_size ) );
752 aPlotter->FinishTo( VECTOR2I( ex1 + deco_size, ey1 + deco_size ) );
753 aPlotter->MoveTo( VECTOR2I( ex1 + deco_size, ey1 - deco_size ) );
754 aPlotter->FinishTo( VECTOR2I( ex1 - deco_size, ey1 + deco_size ) );
755 }
756}
757
758void LIB_PIN::PlotPinTexts( PLOTTER *aPlotter, const VECTOR2I &aPinPos, int aPinOrient,
759 int aTextInside, bool aDrawPinNum, bool aDrawPinName, bool aDimmed ) const
760{
761 RENDER_SETTINGS* settings = aPlotter->RenderSettings();
762 KIFONT::FONT* font = KIFONT::FONT::GetFont( settings->GetDefaultFont(), false, false );
763 wxString name = GetShownName();
764 wxString number = GetShownNumber();
765
766 if( name.IsEmpty() || m_nameTextSize == 0 )
767 aDrawPinName = false;
768
769 if( number.IsEmpty() || m_numTextSize == 0 )
770 aDrawPinNum = false;
771
772 if( !aDrawPinNum && !aDrawPinName )
773 return;
774
775 int x, y;
776 int namePenWidth = std::max( Clamp_Text_PenSize( GetPenWidth(), m_nameTextSize, true ),
777 settings->GetDefaultPenWidth() );
778 int numPenWidth = std::max( Clamp_Text_PenSize( GetPenWidth(), m_numTextSize, true ),
779 settings->GetDefaultPenWidth() );
780 int name_offset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + namePenWidth;
781 int num_offset = schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + numPenWidth;
782
783 /* Get the num and name colors */
784 COLOR4D nameColor = settings->GetLayerColor( LAYER_PINNAM );
785 COLOR4D numColor = settings->GetLayerColor( LAYER_PINNUM );
786 COLOR4D bg = settings->GetBackgroundColor();
787
788 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
789 bg = COLOR4D::WHITE;
790
791 if( aDimmed )
792 {
793 nameColor.Desaturate( );
794 numColor.Desaturate( );
795 nameColor = nameColor.Mix( bg, 0.5f );
796 numColor = numColor.Mix( bg, 0.5f );
797 }
798
799 int x1 = aPinPos.x;
800 int y1 = aPinPos.y;
801
802 switch( aPinOrient )
803 {
804 case PIN_UP: y1 -= m_length; break;
805 case PIN_DOWN: y1 += m_length; break;
806 case PIN_LEFT: x1 -= m_length; break;
807 case PIN_RIGHT: x1 += m_length; break;
808 }
809
810 auto plotText =
811 [&]( int px, int py, const COLOR4D& color, const wxString& text, const EDA_ANGLE& angle,
812 int size, GR_TEXT_H_ALIGN_T hJustify, GR_TEXT_V_ALIGN_T vJustify, int penWidth )
813
814 {
815 TEXT_ATTRIBUTES attrs;
816 attrs.m_StrokeWidth = std::min( penWidth, size / 5 ); // Keep text readable
817 attrs.m_Angle = angle;
818 attrs.m_Size = VECTOR2I( size, size );
819 attrs.m_Halign = hJustify;
820 attrs.m_Valign = vJustify;
821 attrs.m_Multiline = false;
822
823 aPlotter->PlotText( VECTOR2I( px, py ), color, text, attrs, font );
824 };
825
826 /* Draw the text inside, but the pin numbers outside. */
827 if( aTextInside )
828 {
829 if( ( aPinOrient == PIN_LEFT) || ( aPinOrient == PIN_RIGHT) ) /* Its an horizontal line. */
830 {
831 if( aDrawPinName )
832 {
833 GR_TEXT_H_ALIGN_T hjustify;
834 if( aPinOrient == PIN_RIGHT )
835 {
836 x = x1 + aTextInside;
837 hjustify = GR_TEXT_H_ALIGN_LEFT;
838 }
839 else // orient == PIN_LEFT
840 {
841 x = x1 - aTextInside;
842 hjustify = GR_TEXT_H_ALIGN_RIGHT;
843 }
844
845 plotText( x, y1, nameColor, name, ANGLE_HORIZONTAL, m_nameTextSize, hjustify,
846 GR_TEXT_V_ALIGN_CENTER, namePenWidth );
847 }
848
849 if( aDrawPinNum )
850 {
851 plotText( ( x1 + aPinPos.x) / 2, y1 - num_offset, numColor, number,
853 GR_TEXT_V_ALIGN_BOTTOM, numPenWidth );
854 }
855 }
856 else /* Its a vertical line. */
857 {
858 if( aPinOrient == PIN_DOWN )
859 {
860 y = y1 + aTextInside;
861
862 if( aDrawPinName )
863 {
864 plotText( x1, y, nameColor, name, ANGLE_VERTICAL, m_nameTextSize,
866 }
867
868 if( aDrawPinNum )
869 {
870 plotText( x1 - num_offset, ( y1 + aPinPos.y) / 2, numColor, number,
872 GR_TEXT_V_ALIGN_BOTTOM, numPenWidth );
873 }
874 }
875 else /* PIN_UP */
876 {
877 y = y1 - aTextInside;
878
879 if( aDrawPinName )
880 {
881 plotText( x1, y, nameColor, name, ANGLE_VERTICAL, m_nameTextSize,
883 }
884
885 if( aDrawPinNum )
886 {
887 plotText( x1 - num_offset, ( y1 + aPinPos.y) / 2, numColor, number,
889 GR_TEXT_V_ALIGN_BOTTOM, numPenWidth );
890 }
891 }
892 }
893 }
894 else /* Draw num & text pin outside */
895 {
896 if(( aPinOrient == PIN_LEFT) || ( aPinOrient == PIN_RIGHT) )
897 {
898 /* Its an horizontal line. */
899 if( aDrawPinName )
900 {
901 x = ( x1 + aPinPos.x) / 2;
902 plotText( x, y1 - name_offset, nameColor, name, ANGLE_HORIZONTAL, m_nameTextSize,
904 }
905
906 if( aDrawPinNum )
907 {
908 x = ( x1 + aPinPos.x ) / 2;
909 plotText( x, y1 + num_offset, numColor, number, ANGLE_HORIZONTAL, m_numTextSize,
911 }
912 }
913 else /* Its a vertical line. */
914 {
915 if( aDrawPinName )
916 {
917 y = ( y1 + aPinPos.y ) / 2;
918 plotText( x1 - name_offset, y, nameColor, name, ANGLE_VERTICAL, m_nameTextSize,
920 }
921
922 if( aDrawPinNum )
923 {
924 plotText( x1 + num_offset, ( y1 + aPinPos.y ) / 2, numColor, number, ANGLE_VERTICAL,
926 }
927 }
928 }
929}
930
931
932int LIB_PIN::PinDrawOrient( const TRANSFORM& aTransform ) const
933{
934 int orient;
935 VECTOR2I end; // position of pin end starting at 0,0 according to its orientation, length = 1
936
937 switch( m_orientation )
938 {
939 case PIN_UP: end.y = 1; break;
940 case PIN_DOWN: end.y = -1; break;
941 case PIN_LEFT: end.x = -1; break;
942 case PIN_RIGHT: end.x = 1; break;
943 }
944
945 // = pos of end point, according to the symbol orientation.
946 end = aTransform.TransformCoordinate( end );
947 orient = PIN_UP;
948
949 if( end.x == 0 )
950 {
951 if( end.y > 0 )
952 orient = PIN_DOWN;
953 }
954 else
955 {
956 orient = PIN_RIGHT;
957
958 if( end.x < 0 )
959 orient = PIN_LEFT;
960 }
961
962 return orient;
963}
964
965
967{
968 return new LIB_PIN( *this );
969}
970
971
972int LIB_PIN::compare( const LIB_ITEM& aOther, int aCompareFlags ) const
973{
974 wxASSERT( aOther.Type() == LIB_PIN_T );
975
976 int retv = LIB_ITEM::compare( aOther, aCompareFlags );
977
978 if( retv )
979 return retv;
980
981 const LIB_PIN* tmp = (LIB_PIN*) &aOther;
982
983 // When comparing units, we do not compare the part numbers. If everything else is
984 // identical, then we can just renumber the parts for the inherited symbol.
985 if( !( aCompareFlags & COMPARE_FLAGS::UNIT ) && m_number != tmp->m_number )
986 return m_number.Cmp( tmp->m_number );
987
988 int result = m_name.Cmp( tmp->m_name );
989
990 if( result )
991 return result;
992
993 if( m_position.x != tmp->m_position.x )
994 return m_position.x - tmp->m_position.x;
995
996 if( m_position.y != tmp->m_position.y )
997 return m_position.y - tmp->m_position.y;
998
999 if( m_length != tmp->m_length )
1000 return m_length - tmp->m_length;
1001
1002 if( m_orientation != tmp->m_orientation )
1003 return m_orientation - tmp->m_orientation;
1004
1005 if( m_shape != tmp->m_shape )
1006 return static_cast<int>( m_shape ) - static_cast<int>( tmp->m_shape );
1007
1008 if( m_type != tmp->m_type )
1009 return static_cast<int>( m_type ) - static_cast<int>( tmp->m_type );
1010
1011 if( m_attributes != tmp->m_attributes )
1012 return m_attributes - tmp->m_attributes;
1013
1014 if( m_numTextSize != tmp->m_numTextSize )
1015 return m_numTextSize - tmp->m_numTextSize;
1016
1017 if( m_nameTextSize != tmp->m_nameTextSize )
1018 return m_nameTextSize - tmp->m_nameTextSize;
1019
1020 if( m_alternates.size() != tmp->m_alternates.size() )
1021 return m_alternates.size() - tmp->m_alternates.size();
1022
1023 auto lhsItem = m_alternates.begin();
1024 auto rhsItem = tmp->m_alternates.begin();
1025
1026 while( lhsItem != m_alternates.end() )
1027 {
1028 const ALT& lhsAlt = lhsItem->second;
1029 const ALT& rhsAlt = rhsItem->second;
1030
1031 retv = lhsAlt.m_Name.Cmp( rhsAlt.m_Name );
1032
1033 if( retv )
1034 return retv;
1035
1036 if( lhsAlt.m_Type != rhsAlt.m_Type )
1037 return static_cast<int>( lhsAlt.m_Type ) - static_cast<int>( rhsAlt.m_Type );
1038
1039 if( lhsAlt.m_Shape != rhsAlt.m_Shape )
1040 return static_cast<int>( lhsAlt.m_Shape ) - static_cast<int>( rhsAlt.m_Shape );
1041
1042 ++lhsItem;
1043 ++rhsItem;
1044 }
1045
1046 return 0;
1047}
1048
1049void LIB_PIN::ChangeLength( int aLength )
1050{
1051 int lengthChange = m_length - aLength;
1052 int offsetX = 0;
1053 int offsetY = 0;
1054
1055 switch( m_orientation )
1056 {
1057 case PIN_RIGHT:
1058 offsetX = lengthChange;
1059 break;
1060 case PIN_LEFT:
1061 offsetX = -1 * lengthChange;
1062 break;
1063 case PIN_UP:
1064 offsetY = lengthChange;
1065 break;
1066 case PIN_DOWN:
1067 offsetY = -1 * lengthChange;
1068 break;
1069 }
1070
1071 VECTOR2I offset = VECTOR2I( offsetX, offsetY );
1072 Offset( offset );
1073
1074 m_length = aLength;
1075}
1076
1077void LIB_PIN::Offset( const VECTOR2I& aOffset )
1078{
1079 m_position += aOffset;
1080}
1081
1082
1083void LIB_PIN::MoveTo( const VECTOR2I& aNewPosition )
1084{
1085 if( m_position != aNewPosition )
1086 {
1087 m_position = aNewPosition;
1088 SetModified();
1089 }
1090}
1091
1092
1094{
1095 m_position.x -= aCenter.x;
1096 m_position.x *= -1;
1097 m_position.x += aCenter.x;
1098
1099 if( m_orientation == PIN_RIGHT )
1101 else if( m_orientation == PIN_LEFT )
1103}
1104
1105
1106void LIB_PIN::MirrorVertical( const VECTOR2I& aCenter )
1107{
1108 m_position.y -= aCenter.y;
1109 m_position.y *= -1;
1110 m_position.y += aCenter.y;
1111
1112 if( m_orientation == PIN_UP )
1114 else if( m_orientation == PIN_DOWN )
1116}
1117
1118
1119void LIB_PIN::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
1120{
1121 EDA_ANGLE rot_angle = aRotateCCW ? -ANGLE_90 : ANGLE_90;
1122
1123 RotatePoint( m_position, aCenter, rot_angle );
1124
1125 if( aRotateCCW )
1126 {
1127 switch( m_orientation )
1128 {
1129 case PIN_RIGHT: m_orientation = PIN_UP; break;
1130 case PIN_UP: m_orientation = PIN_LEFT; break;
1131 case PIN_LEFT: m_orientation = PIN_DOWN; break;
1132 case PIN_DOWN: m_orientation = PIN_RIGHT; break;
1133 }
1134 }
1135 else
1136 {
1137 switch( m_orientation )
1138 {
1139 case PIN_RIGHT: m_orientation = PIN_DOWN; break;
1140 case PIN_UP: m_orientation = PIN_RIGHT; break;
1141 case PIN_LEFT: m_orientation = PIN_UP; break;
1142 case PIN_DOWN: m_orientation = PIN_LEFT; break;
1143 }
1144 }
1145}
1146
1147
1148void LIB_PIN::Plot( PLOTTER* aPlotter, bool aBackground, const VECTOR2I& aOffset,
1149 const TRANSFORM& aTransform, bool aDimmed ) const
1150{
1151 if( !IsVisible() || aBackground )
1152 return;
1153
1154 int orient = PinDrawOrient( aTransform );
1155 VECTOR2I pos = aTransform.TransformCoordinate( m_position ) + aOffset;
1156
1157 PlotSymbol( aPlotter, pos, orient, aDimmed );
1158 PlotPinTexts( aPlotter, pos, orient, GetParent()->GetPinNameOffset(),
1159 GetParent()->ShowPinNumbers(), GetParent()->ShowPinNames(),
1160 aDimmed );
1161}
1162
1163
1164void LIB_PIN::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1165{
1166 LIB_ITEM::GetMsgPanelInfo( aFrame, aList );
1167
1168 aList.emplace_back( _( "Name" ), UnescapeString( GetShownName() ) );
1169 aList.emplace_back( _( "Number" ), GetShownNumber() );
1170 aList.emplace_back( _( "Type" ), ElectricalPinTypeGetText( m_type ) );
1171 aList.emplace_back( _( "Style" ), PinShapeGetText( m_shape ) );
1172
1173 aList.emplace_back( _( "Style" ), IsVisible() ? _( "Yes" ) : _( "No" ) );
1174
1175 // Display pin length
1176 aList.emplace_back( _( "Length" ), aFrame->MessageTextFromValue( m_length, true ) );
1177
1179 aList.emplace_back( _( "Orientation" ), PinOrientationName( (unsigned) i ) );
1180
1181 VECTOR2I pinpos = GetPosition();
1182 pinpos.y = -pinpos.y; // Display coords are top to bottom; lib item coords are bottom to top
1183
1184 aList.emplace_back( _( "Pos X" ), aFrame->MessageTextFromValue( pinpos.x, true ) );
1185 aList.emplace_back( _( "Pos Y" ), aFrame->MessageTextFromValue( pinpos.y, true ) );
1186}
1187
1188
1190{
1191 return GetBoundingBox( false, true, true );
1192}
1193
1194
1195void LIB_PIN::ViewGetLayers( int aLayers[], int& aCount ) const
1196{
1197 aCount = 4;
1198 aLayers[0] = LAYER_DANGLING; // We don't really show dangling vs non-dangling (since there
1199 // are no connections in the symbol editor), but it's still
1200 // a good visual indication of which end of the pin is which.
1201 aLayers[1] = LAYER_DEVICE;
1202 aLayers[2] = LAYER_SELECTION_SHADOWS;
1203 aLayers[3] = LAYER_OP_CURRENTS;
1204}
1205
1206
1207const BOX2I LIB_PIN::GetBoundingBox( bool aIncludeInvisiblePins, bool aIncludeNameAndNumber,
1208 bool aIncludeElectricalType ) const
1209{
1210 EESCHEMA_SETTINGS* cfg = Pgm().GetSettingsManager().GetAppSettings<EESCHEMA_SETTINGS>();
1212
1213 BOX2I bbox;
1214 VECTOR2I begin;
1215 VECTOR2I end;
1216 int pinNameOffset = 0;
1217 int nameTextLength = 0;
1218 int nameTextHeight = 0;
1219 int numberTextLength = 0;
1220 int numberTextHeight = 0;
1221 int typeTextLength = 0;
1222 wxString name = GetShownName();
1223 wxString number = GetShownNumber();
1224 bool includeName = aIncludeNameAndNumber && !name.IsEmpty();
1225 bool includeNumber = aIncludeNameAndNumber && !number.IsEmpty();
1226 bool includeType = aIncludeElectricalType;
1227 int minsizeV = TARGET_PIN_RADIUS;
1228 int penWidth = GetPenWidth();
1229
1230 if( !aIncludeInvisiblePins && !IsVisible() )
1231 {
1232 includeName = false;
1233 includeType = false;
1234 }
1235
1236 if( GetParent() )
1237 {
1238 if( GetParent()->ShowPinNames() )
1239 pinNameOffset = GetParent()->GetPinNameOffset();
1240 else
1241 includeName = false;
1242
1243 if( !GetParent()->ShowPinNumbers() )
1244 includeNumber = false;
1245 }
1246
1247 // Get maximum height including ascenders and descenders
1248 wxString test = wxT( "Xg" );
1249
1250 if( includeNumber )
1251 {
1253 numberTextLength = font->StringBoundaryLimits( number, fontSize, penWidth, false, false ).x;
1254 numberTextHeight = font->StringBoundaryLimits( test, fontSize, penWidth, false, false ).y;
1255 }
1256
1257 if( includeName )
1258 {
1260
1261 nameTextLength = font->StringBoundaryLimits( name, fontSize, penWidth, false, false ).x
1262 + pinNameOffset;
1263 nameTextHeight = font->StringBoundaryLimits( test, fontSize, penWidth, false, false ).y
1265 }
1266
1267 // KIFONT has to be rather tight on boundary limits for knockout text in PCBNew, but in truth
1268 // the stroke font returns a vertically under-sized bounding box (even though it *does* in fact
1269 // attempt to account for the font size being stroke centre-point to stroke centre-point).
1270 if( font->IsStroke() )
1271 {
1272 numberTextHeight += 2 * penWidth;
1273 nameTextHeight += 2 * penWidth;
1274 }
1275
1276 if( includeType )
1277 {
1278 double fontSize = std::max( m_nameTextSize * 3 / 4, schIUScale.mmToIU( 0.7 ) );
1279 double stroke = fontSize / 8.0;
1280 VECTOR2I typeTextSize = font->StringBoundaryLimits( GetElectricalTypeName(),
1281 VECTOR2D( fontSize, fontSize ),
1282 KiROUND( stroke ), false, false );
1283
1284 typeTextLength = typeTextSize.x + schIUScale.MilsToIU( PIN_TEXT_MARGIN ) + TARGET_PIN_RADIUS;
1285 minsizeV = std::max( minsizeV, typeTextSize.y / 2 );
1286 }
1287
1288 // First, calculate boundary box corners position
1290 minsizeV = std::max( TARGET_PIN_RADIUS, externalPinDecoSize( nullptr, *this ) );
1291
1292 // Attempt to mimic SCH_PAINTER's algorithm without actually knowing the schematic text
1293 // offset ratio.
1294 int PIN_TEXT_OFFSET = schIUScale.MilsToIU( 24 ) + 2 * penWidth;
1295
1296 // Calculate topLeft & bottomRight corner positions for the default pin orientation (PIN_RIGHT)
1297 if( pinNameOffset || !includeName )
1298 {
1299 // pin name is inside the body (or invisible)
1300 // pin number is above the line
1301 begin.y = std::max( minsizeV, numberTextHeight + PIN_TEXT_OFFSET );
1302 begin.x = std::min( -typeTextLength, m_length - ( numberTextLength / 2) );
1303
1304 end.x = m_length + nameTextLength;
1305 end.y = std::min( -minsizeV, -nameTextHeight / 2 );
1306 }
1307 else
1308 {
1309 // pin name is above pin line
1310 // pin number is below line
1311 begin.y = std::max( minsizeV, nameTextHeight + PIN_TEXT_OFFSET );
1312 begin.x = std::min( -typeTextLength, m_length - ( numberTextLength / 2) );
1313
1314 end.x = std::max( m_length, nameTextLength );
1315 end.y = std::min( -minsizeV, -numberTextHeight - PIN_TEXT_OFFSET );
1316 }
1317
1318 // Now, calculate boundary box corners position for the actual pin orientation
1319 int orient = PinDrawOrient( DefaultTransform );
1320
1321 /* Calculate the pin position */
1322 switch( orient )
1323 {
1324 case PIN_UP:
1325 // Pin is rotated and texts positions are mirrored
1326 RotatePoint( begin, VECTOR2I( 0, 0 ), -ANGLE_90 );
1327 RotatePoint( end, VECTOR2I( 0, 0 ), -ANGLE_90 );
1328 break;
1329
1330 case PIN_DOWN:
1331 RotatePoint( begin, VECTOR2I( 0, 0 ), ANGLE_90 );
1332 RotatePoint( end, VECTOR2I( 0, 0 ), ANGLE_90 );
1333 begin.x = -begin.x;
1334 end.x = -end.x;
1335 break;
1336
1337 case PIN_LEFT:
1338 begin.x = -begin.x;
1339 end.x = -end.x;
1340 break;
1341
1342 case PIN_RIGHT:
1343 break;
1344 }
1345
1346 begin += m_position;
1347 end += m_position;
1348
1349 bbox.SetOrigin( begin );
1350 bbox.SetEnd( end );
1351 bbox.Normalize();
1352 bbox.Inflate( ( GetPenWidth() / 2 ) + 1 );
1353
1354 // Draw Y axis is reversed in schematic:
1355 bbox.RevertYAxis();
1356
1357 return bbox;
1358}
1359
1360
1362{
1364}
1365
1366
1367wxString LIB_PIN::GetItemDescription( UNITS_PROVIDER* aUnitsProvider ) const
1368{
1369 // This code previously checked "m_name.IsEmpty()" to choose the correct
1370 // formatting path, but that check fails if the pin is called "~" which is
1371 // the default for an empty pin name. Instead we get the final display string
1372 // that will be shown and check if it's empty.
1373
1374 wxString shownName = UnescapeString( GetShownName() );
1375
1376 if( IsVisible() )
1377 {
1378 if ( !shownName.IsEmpty() )
1379 {
1380 return wxString::Format( _( "Pin %s [%s, %s, %s]" ),
1382 shownName,
1385 }
1386 else
1387 {
1388 return wxString::Format( _( "Pin %s [%s, %s]" ),
1392 }
1393 }
1394 else
1395 {
1396 if( !shownName.IsEmpty() )
1397 {
1398 return wxString::Format( _( "Hidden pin %s [%s, %s, %s]" ),
1400 shownName,
1403 }
1404 else
1405 {
1406 return wxString::Format( _( "Hidden pin %s [%s, %s]" ),
1410 }
1411 }
1412}
1413
1414
1415#if defined(DEBUG)
1416
1417void LIB_PIN::Show( int nestLevel, std::ostream& os ) const
1418{
1419 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
1420 << " num=\"" << m_number.mb_str()
1421 << '"' << "/>\n";
1422
1423// NestedSpace( nestLevel, os ) << "</" << GetClass().Lower().mb_str() << ">\n";
1424}
1425
1426#endif
1427
1428void LIB_PIN::CalcEdit( const VECTOR2I& aPosition )
1429{
1430 if( IsMoving() )
1431 MoveTo( aPosition );
1432}
int color
Definition: DXF_plotter.cpp:57
const char * name
Definition: DXF_plotter.cpp:56
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
BITMAPS
A list of all bitmap identifiers.
Definition: bitmaps_list.h:33
void SetOrigin(const Vec &pos)
Definition: box2.h:202
BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition: box2.h:119
void RevertYAxis()
Mirror the rectangle from the X axis (negate Y pos and size).
Definition: box2.h:689
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:269
bool Contains(const Vec &aPoint) const
Definition: box2.h:141
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:255
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
void SetModified()
Definition: eda_item.cpp:64
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
EDA_ITEM_FLAGS m_flags
Definition: eda_item.h:498
bool IsMoving() const
Definition: eda_item.h:104
FONT is an abstract base class for both outline and stroke fonts.
Definition: font.h:105
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
Definition: font.cpp:138
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:102
COLOR4D & Desaturate()
Removes color (in HSL model)
Definition: color4d.cpp:510
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
Definition: color4d.h:293
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
int GetDefaultPenWidth() const
const wxString & GetDefaultFont() const
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
virtual const COLOR4D & GetBackgroundColor() const =0
Return current background color settings.
wxDC * GetPrintDC() const
Store schematic specific render settings.
Definition: sch_painter.h:71
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:61
virtual int compare(const LIB_ITEM &aOther, int aCompareFlags=0) const
Provide the draw object specific comparison called by the == and < operators.
Definition: lib_item.cpp:74
virtual int GetEffectivePenWidth(const RENDER_SETTINGS *aSettings) const
Definition: lib_item.h:155
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Display basic info (type, part and convert) about the current item in message panel.
Definition: lib_item.cpp:47
LIB_SYMBOL * GetParent() const
Definition: lib_item.h:168
void SetConvert(int aConvert)
Definition: lib_item.h:275
void SetUnit(int aUnit)
Definition: lib_item.h:272
int m_attributes
Definition: lib_pin.h:301
void ViewGetLayers(int aLayers[], int &aCount) const override
Return the all the layers within the VIEW the object is painted on.
Definition: lib_pin.cpp:1195
void MirrorHorizontal(const VECTOR2I &aCenter) override
Mirror the draw object along the horizontal (X) axis about aCenter point.
Definition: lib_pin.cpp:1093
void Offset(const VECTOR2I &aOffset) override
Set the drawing object by aOffset from the current position.
Definition: lib_pin.cpp:1077
void PlotPinTexts(PLOTTER *aPlotter, const VECTOR2I &aPinPos, int aPinOrient, int aTextInside, bool aDrawPinNum, bool aDrawPinName, bool aDimmed) const
Plot the pin number and pin text info, given the pin line coordinates.
Definition: lib_pin.cpp:758
const BOX2I GetBoundingBox() const override
Definition: lib_pin.h:189
void SetName(const wxString &aName)
Definition: lib_pin.h:114
void MirrorVertical(const VECTOR2I &aCenter) override
Mirror the draw object along the MirrorVertical (Y) axis about aCenter point.
Definition: lib_pin.cpp:1106
int compare(const LIB_ITEM &aOther, int aCompareFlags=0) const override
Provide the draw object specific comparison called by the == and < operators.
Definition: lib_pin.cpp:972
wxString m_name
Definition: lib_pin.h:302
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition: lib_pin.cpp:1189
int m_nameTextSize
Definition: lib_pin.h:305
wxString GetShownNumber() const
Definition: lib_pin.h:123
LIB_PIN(LIB_SYMBOL *aParent)
Definition: lib_pin.cpp:97
int GetNumberTextSize() const
Definition: lib_pin.h:135
void printPinSymbol(const RENDER_SETTINGS *aSettings, const VECTOR2I &aPos, int aOrientation, bool aDimmed)
Print the pin symbol without text.
Definition: lib_pin.cpp:251
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Display basic info (type, part and convert) about the current item in message panel.
Definition: lib_pin.cpp:1164
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider) const override
Return a user-visible description string of this item.
Definition: lib_pin.cpp:1367
wxString GetShownName() const
Definition: lib_pin.cpp:175
int m_length
Definition: lib_pin.h:297
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW=true) override
Rotate the object about aCenter point.
Definition: lib_pin.cpp:1119
void ChangeLength(int aLength)
Change the length of a pin and adjust its position based on orientation.
Definition: lib_pin.cpp:1049
wxString const GetCanonicalElectricalTypeName() const
Definition: lib_pin.h:93
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition: lib_pin.cpp:1361
void MoveTo(const VECTOR2I &aNewPosition) override
Move a draw object to aPosition.
Definition: lib_pin.cpp:1083
wxString GetClass() const override
Return the class name.
Definition: lib_pin.h:64
VECTOR2I m_position
Definition: lib_pin.h:296
int m_orientation
Definition: lib_pin.h:298
int m_numTextSize
Definition: lib_pin.h:304
GRAPHIC_PINSHAPE m_shape
Definition: lib_pin.h:299
VECTOR2I GetPosition() const override
Definition: lib_pin.h:228
void CalcEdit(const VECTOR2I &aPosition) override
Calculate the attributes of an item at aPosition when it is being edited.
Definition: lib_pin.cpp:1428
wxString const GetElectricalTypeName() const
Definition: lib_pin.h:98
std::map< wxString, ALT > m_alternates
Definition: lib_pin.h:307
bool IsVisible() const
Definition: lib_pin.h:103
void SetNumber(const wxString &aNumber)
Definition: lib_pin.h:124
void print(const RENDER_SETTINGS *aSettings, const VECTOR2I &aOffset, void *aData, const TRANSFORM &aTransform, bool aDimmed) override
Print a pin, with or without the pin texts.
Definition: lib_pin.cpp:197
ELECTRICAL_PINTYPE m_type
Definition: lib_pin.h:300
void Plot(PLOTTER *aPlotter, bool aBackground, const VECTOR2I &aOffset, const TRANSFORM &aTransform, bool aDimmed) const override
Plot the draw item using the plot object.
Definition: lib_pin.cpp:1148
int PinDrawOrient(const TRANSFORM &aTransform) const
Return the pin real orientation (PIN_UP, PIN_DOWN, PIN_RIGHT, PIN_LEFT), according to its orientation...
Definition: lib_pin.cpp:932
wxString m_number
Definition: lib_pin.h:303
int GetNameTextSize() const
Definition: lib_pin.h:132
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition: lib_pin.cpp:966
VECTOR2I GetPinRoot() const
Definition: lib_pin.cpp:184
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition: lib_pin.cpp:144
int GetPenWidth() const override
Definition: lib_pin.cpp:169
void printPinElectricalTypeName(const RENDER_SETTINGS *aSettings, VECTOR2I &aPosition, int aOrientation, bool aDimmed)
Draw the electrical type text of the pin (only for the footprint editor)
Definition: lib_pin.cpp:548
void PlotSymbol(PLOTTER *aPlotter, const VECTOR2I &aPosition, int aOrientation, bool aDimmed) const
Definition: lib_pin.cpp:615
void printPinTexts(const RENDER_SETTINGS *aSettings, VECTOR2I &aPinPos, int aPinOrient, int aTextInside, bool aDrawPinNum, bool aDrawPinName, bool aDimmed)
Put the pin number and pin text info, given the pin line coordinates.
Definition: lib_pin.cpp:375
Define a library symbol object.
Definition: lib_symbol.h:99
int GetPinNameOffset() const
Definition: lib_symbol.h:617
bool ShowPinNames() const
Definition: lib_symbol.h:625
bool ShowPinNumbers() const
Definition: lib_symbol.h:633
Container for data for KiCad programs.
Definition: pgm_base.h:95
virtual SETTINGS_MANAGER & GetSettingsManager() const
Definition: pgm_base.h:135
Base plotter engine class.
Definition: plotter.h:110
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width=USE_DEFAULT_LINE_WIDTH)=0
void MoveTo(const VECTOR2I &pos)
Definition: plotter.h:247
void FinishTo(const VECTOR2I &pos)
Definition: plotter.h:257
RENDER_SETTINGS * RenderSettings()
Definition: plotter.h:141
virtual void PlotText(const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const TEXT_ATTRIBUTES &aAttributes, KIFONT::FONT *aFont, void *aData=nullptr)
Definition: plotter.cpp:758
bool GetColorMode() const
Definition: plotter.h:138
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
void LineTo(const VECTOR2I &pos)
Definition: plotter.h:252
virtual void SetColor(const COLOR4D &color)=0
T * GetAppSettings(bool aLoadNow=true)
Returns a handle to the a given settings by type If the settings have already been loaded,...
GR_TEXT_H_ALIGN_T m_Halign
GR_TEXT_V_ALIGN_T m_Valign
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:47
VECTOR2I TransformCoordinate(const VECTOR2I &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:46
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE)
A lower-precision version of StringFromValue().
@ WHITE
Definition: color4d.h:46
PGM_BASE * PgmOrNull()
similar to PGM_BASE& Pgm(), but return a reference that can be nullptr when running a shared lib from...
Definition: cvpcb.cpp:125
#define DEFAULT_PINNUM_SIZE
The default pin name size when creating pins(can be changed in preference menu)
#define DEFAULT_PINNAME_SIZE
The default selection highlight thickness (can be changed in preference menu)
#define DEFAULT_PIN_LENGTH
The default pin number size when creating pins(can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE & ANGLE_HORIZONTAL
Definition: eda_angle.h:425
static constexpr EDA_ANGLE & ANGLE_VERTICAL
Definition: eda_angle.h:426
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:431
#define STRUCT_DELETED
flag indication structures to be erased
#define SKIP_STRUCT
flag indicating that the structure should be ignored
#define SHOW_ELEC_TYPE
Show pin electrical type. Shared with IS_ROLLOVER.
void GRLineTo(wxDC *DC, int x, int y, int width, const COLOR4D &Color)
Definition: gr_basic.cpp:195
void GRCircle(wxDC *aDC, const VECTOR2I &aPos, int aRadius, int aWidth, const COLOR4D &aColor)
Definition: gr_basic.cpp:357
void GRMoveTo(int x, int y)
Definition: gr_basic.cpp:188
void GRLine(wxDC *DC, int x1, int y1, int x2, int y2, int width, const COLOR4D &Color, wxPenStyle aStyle)
Definition: gr_basic.cpp:171
bool GetGRForceBlackPenState(void)
Definition: gr_basic.cpp:165
void GRPrintText(wxDC *aDC, const VECTOR2I &aPos, const COLOR4D &aColor, const wxString &aText, const EDA_ANGLE &aOrient, const VECTOR2I &aSize, enum GR_TEXT_H_ALIGN_T aH_justify, enum GR_TEXT_V_ALIGN_T aV_justify, int aWidth, bool aItalic, bool aBold, KIFONT::FONT *aFont)
Print a graphic text through wxDC.
Definition: gr_text.cpp:141
int Clamp_Text_PenSize(int aPenSize, int aSize, bool aStrict)
Pen width should not allow characters to become cluttered up in their own fatness.
Definition: gr_text.cpp:87
@ LAYER_DANGLING
Definition: layer_ids.h:368
@ LAYER_PINNUM
Definition: layer_ids.h:350
@ LAYER_DEVICE
Definition: layer_ids.h:357
@ LAYER_HIDDEN
Definition: layer_ids.h:380
@ LAYER_PINNAM
Definition: layer_ids.h:351
@ LAYER_PRIVATE_NOTES
Definition: layer_ids.h:359
@ LAYER_PIN
Definition: layer_ids.h:361
@ LAYER_OP_CURRENTS
Definition: layer_ids.h:388
@ LAYER_SELECTION_SHADOWS
Definition: layer_ids.h:381
#define ETXT_MAX_SIZE
#define PIN_TEXT_MARGIN
Definition: lib_pin.cpp:41
static int externalPinDecoSize(const RENDER_SETTINGS *aSettings, const LIB_PIN &aPin)
Utility for getting the size of the 'external' pin decorators (as a radius)
Definition: lib_pin.cpp:86
static int internalPinDecoSize(const RENDER_SETTINGS *aSettings, const LIB_PIN &aPin)
Utility for getting the size of the 'internal' pin decorators (as a radius)
Definition: lib_pin.cpp:73
@ PIN_LEFT
Definition: lib_pin.h:46
@ PIN_RIGHT
Definition: lib_pin.h:45
@ PIN_UP
Definition: lib_pin.h:47
@ PIN_DOWN
Definition: lib_pin.h:48
#define TARGET_PIN_RADIUS
Definition: lib_pin.h:35
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
see class PGM_BASE
wxString PinOrientationName(unsigned aPinOrientationCode)
Definition: pin_type.cpp:119
int PinOrientationIndex(int code)
Definition: pin_type.cpp:150
wxString ElectricalPinTypeGetText(ELECTRICAL_PINTYPE aType)
Definition: pin_type.cpp:240
BITMAPS ElectricalPinTypeGetBitmap(ELECTRICAL_PINTYPE aType)
Definition: pin_type.cpp:268
wxString PinShapeGetText(GRAPHIC_PINSHAPE aShape)
Definition: pin_type.cpp:278
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:36
@ PT_NC
not connected (must be left open)
@ PT_NIC
not internally connected (may be connected to anything)
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
GRAPHIC_PINSHAPE
Definition: pin_type.h:56
Plot settings, and plotting engines (PostScript, Gerber, HPGL and DXF)
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
KIWAY Kiway & Pgm(), KFCTL_STANDALONE
The global Program "get" accessor.
Definition: single_top.cpp:111
wxString UnescapeString(const wxString &aSource)
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
constexpr int mmToIU(double mm) const
Definition: base_units.h:89
GRAPHIC_PINSHAPE m_Shape
Definition: lib_pin.h:58
ELECTRICAL_PINTYPE m_Type
Definition: lib_pin.h:59
wxString m_Name
Definition: lib_pin.h:57
bool force_draw_pin_text
Definition: lib_symbol.h:65
GR_TEXT_H_ALIGN_T
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
GR_TEXT_V_ALIGN_T
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
TRANSFORM DefaultTransform
Definition: transform.cpp:34
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
@ LIB_PIN_T
Definition: typeinfo.h:202
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85
VECTOR2< double > VECTOR2D
Definition: vector2d.h:589
VECTOR2< int > VECTOR2I
Definition: vector2d.h:590