diff --git a/api/proto/board/board_types.proto b/api/proto/board/board_types.proto index 27fae3172f..2e0b27de67 100644 --- a/api/proto/board/board_types.proto +++ b/api/proto/board/board_types.proto @@ -132,11 +132,19 @@ message Arc Net net = 8; } +// What copper layer shape mode the padstack uses enum PadStackType { - PST_UNKNOWN = 0; - PST_THROUGH = 1; // Through all layers; same shape on all layers - PST_BLIND_BURIED = 2; // From a start layer to end layer (inclusive); same shape on all included layers + PST_UNKNOWN = 0; + + // The same shape is used on all copper layers + PST_NORMAL = 1; + + // The padstack uses up to three different shapes (F_Cu, inner layers, B_Cu) + PST_TOP_INNER_BOTTOM = 2; + + // The padstack's shape may differ on arbitrary copper layers + PST_CUSTOM = 3; } enum UnconnectedLayerRemoval @@ -189,11 +197,11 @@ message PadStackLayer // How much to round the corners of the shape by, as a fraction of min(size.x, size.y) // Only used for PSS_ROUNDRECT or PSS_CHAMFEREDRECT - float corner_rounding_ratio = 4; + double corner_rounding_ratio = 4; // How much to round the corners of the shape by, as a fraction of min(size.x, size.y) // Only used for PSS_CHAMFEREDRECT - float chamfer_ratio = 5; + double chamfer_ratio = 5; ChamferedRectCorners chamfered_corners = 6; @@ -225,6 +233,21 @@ message PadStack kiapi.common.types.Angle angle = 7; } +enum ViaType +{ + VT_UNKNOWN = 0; + + // Through vias always start on F_Cu and end on B_Cu + VT_THROUGH = 1; + + // Blind/buried vias can have arbitrary start and end layers + VT_BLIND_BURIED = 2; + + // Microvias, blind/buried vias, can have arbitrary start and end layers, but also have different + // size defaults and design rules + VT_MICRO = 3; +} + // Represents a via message Via { @@ -234,12 +257,14 @@ message Via // The location of the via's center point kiapi.common.types.Vector2 position = 2; - // The pad stack definition for this via. The via's VIATYPE (blind/buried/normal) is inferred from this. + // The pad stack definition for this via. PadStack pad_stack = 3; kiapi.common.types.LockedState locked = 4; Net net = 5; + + ViaType type = 6; } message GraphicSegmentAttributes diff --git a/pcbnew/api/api_pcb_enums.cpp b/pcbnew/api/api_pcb_enums.cpp index ecd7258391..79b2a94298 100644 --- a/pcbnew/api/api_pcb_enums.cpp +++ b/pcbnew/api/api_pcb_enums.cpp @@ -24,10 +24,44 @@ #include #include +#include #include using namespace kiapi::board; +template<> +types::PadType ToProtoEnum( PAD_ATTRIB aValue ) +{ + switch( aValue ) + { + case PAD_ATTRIB::PTH: return types::PadType::PT_PTH; + case PAD_ATTRIB::SMD: return types::PadType::PT_SMD; + case PAD_ATTRIB::CONN: return types::PadType::PT_EDGE_CONNECTOR; + case PAD_ATTRIB::NPTH: return types::PadType::PT_NPTH; + + default: + wxCHECK_MSG( false, types::PadType::PT_UNKNOWN, + "Unhandled case in ToProtoEnum"); + } +} + + +template<> +PAD_ATTRIB FromProtoEnum( types::PadType aValue ) +{ + switch( aValue ) + { + case types::PadType::PT_PTH: return PAD_ATTRIB::PTH; + case types::PadType::PT_SMD: return PAD_ATTRIB::SMD; + case types::PadType::PT_EDGE_CONNECTOR: return PAD_ATTRIB::CONN; + case types::PadType::PT_NPTH: return PAD_ATTRIB::NPTH; + + default: + wxCHECK_MSG( false, PAD_ATTRIB::PTH, + "Unhandled case in FromProtoEnum" ); + } +} + template<> types::PadStackShape ToProtoEnum( PAD_SHAPE aValue ) { @@ -68,6 +102,70 @@ PAD_SHAPE FromProtoEnum( types::PadStackShape aValue ) } +template<> +types::PadStackType ToProtoEnum( PADSTACK::MODE aValue ) +{ + switch( aValue ) + { + case PADSTACK::MODE::NORMAL: return types::PadStackType::PST_NORMAL; + case PADSTACK::MODE::TOP_INNER_BOTTOM: return types::PadStackType::PST_TOP_INNER_BOTTOM; + case PADSTACK::MODE::CUSTOM: return types::PadStackType::PST_CUSTOM; + + default: + wxCHECK_MSG( false, types::PadStackType::PST_UNKNOWN, + "Unhandled case in ToProtoEnum"); + } +} + + +template<> +PADSTACK::MODE FromProtoEnum( types::PadStackType aValue ) +{ + switch( aValue ) + { + case types::PadStackType::PST_NORMAL: return PADSTACK::MODE::NORMAL; + case types::PadStackType::PST_TOP_INNER_BOTTOM: return PADSTACK::MODE::TOP_INNER_BOTTOM; + case types::PadStackType::PST_CUSTOM: return PADSTACK::MODE::CUSTOM; + + default: + wxCHECK_MSG( false, PADSTACK::MODE::NORMAL, + "Unhandled case in FromProtoEnum" ); + } +} + + +template<> +types::ViaType ToProtoEnum( VIATYPE aValue ) +{ + switch( aValue ) + { + case VIATYPE::THROUGH: return types::ViaType::VT_THROUGH; + case VIATYPE::BLIND_BURIED: return types::ViaType::VT_BLIND_BURIED; + case VIATYPE::MICROVIA: return types::ViaType::VT_MICRO; + + default: + wxCHECK_MSG( false, types::ViaType::VT_UNKNOWN, + "Unhandled case in ToProtoEnum"); + } +} + + +template<> +VIATYPE FromProtoEnum( types::ViaType aValue ) +{ + switch( aValue ) + { + case types::ViaType::VT_THROUGH: return VIATYPE::THROUGH; + case types::ViaType::VT_BLIND_BURIED: return VIATYPE::BLIND_BURIED; + case types::ViaType::VT_MICRO: return VIATYPE::MICROVIA; + + default: + wxCHECK_MSG( false, VIATYPE::THROUGH, + "Unhandled case in FromProtoEnum" ); + } +} + + template<> types::ZoneConnectionStyle ToProtoEnum( ZONE_CONNECTION aValue ) { diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp index 22efab0338..16e05f4f01 100644 --- a/pcbnew/pad.cpp +++ b/pcbnew/pad.cpp @@ -73,7 +73,6 @@ PAD::PAD( FOOTPRINT* parent ) : VECTOR2I& size = m_padStack.Size(); size.x = size.y = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 60 ); // Default pad size 60 mils. drill.x = drill.y = EDA_UNIT_UTILS::Mils2IU( pcbIUScale, 30 ); // Default drill size 30 mils. - m_orient = ANGLE_0; m_lengthPadToDie = 0; if( m_parent && m_parent->Type() == PCB_FOOTPRINT_T ) @@ -133,7 +132,8 @@ PAD& PAD::operator=( const PAD &aOther ) void PAD::Serialize( google::protobuf::Any &aContainer ) const { - kiapi::board::types::Pad pad; + using namespace kiapi::board::types; + Pad pad; pad.mutable_id()->set_value( m_Uuid.AsStdString() ); kiapi::common::PackVector2( *pad.mutable_position(), GetPosition() ); @@ -141,29 +141,13 @@ void PAD::Serialize( google::protobuf::Any &aContainer ) const : kiapi::common::types::LockedState::LS_UNLOCKED ); pad.mutable_net()->mutable_code()->set_value( GetNetCode() ); pad.mutable_net()->set_name( GetNetname() ); + pad.set_type( ToProtoEnum( GetAttribute() ) ); - kiapi::board::types::PadStack* padstack = pad.mutable_pad_stack(); - padstack->set_type( kiapi::board::types::PadStackType::PST_THROUGH ); - padstack->set_start_layer( - ToProtoEnum( m_layer ) ); - padstack->set_end_layer( - ToProtoEnum( FlipLayer( m_layer ) ) ); - kiapi::common::PackVector2( *padstack->mutable_drill_diameter(), - { GetDrillSizeX(), GetDrillSizeY() } ); - padstack->mutable_angle()->set_value_degrees( GetOrientationDegrees() ); + google::protobuf::Any padStackMsg; + m_padStack.Serialize( padStackMsg ); + padStackMsg.UnpackTo( pad.mutable_pad_stack() ); - kiapi::board::types::PadStackLayer* stackLayer = padstack->add_layers(); - kiapi::board::PackLayerSet( *stackLayer->mutable_layers(), GetLayerSet() ); - kiapi::common::PackVector2( *stackLayer->mutable_size(), - { GetSizeX(), GetSizeY() } ); - stackLayer->set_shape( - ToProtoEnum( GetShape() ) ); - - padstack->set_unconnected_layer_removal( - ToProtoEnum( GetUnconnectedLayerMode() ) ); - - kiapi::board::types::DesignRuleOverrides* overrides = pad.mutable_overrides(); + DesignRuleOverrides* overrides = pad.mutable_overrides(); if( GetLocalClearance().has_value() ) overrides->mutable_clearance()->set_value_nm( *GetLocalClearance() ); @@ -178,10 +162,9 @@ void PAD::Serialize( google::protobuf::Any &aContainer ) const overrides->mutable_solder_paste_margin_ratio()->set_value( *GetLocalSolderPasteMarginRatio() ); overrides->set_zone_connection( - ToProtoEnum( GetLocalZoneConnection() ) ); + ToProtoEnum( GetLocalZoneConnection() ) ); - kiapi::board::types::ThermalSpokeSettings* thermals = pad.mutable_thermal_spokes(); + ThermalSpokeSettings* thermals = pad.mutable_thermal_spokes(); thermals->set_width( GetThermalSpokeWidth() ); thermals->set_gap( GetThermalGap() ); @@ -202,26 +185,13 @@ bool PAD::Deserialize( const google::protobuf::Any &aContainer ) SetPosition( kiapi::common::UnpackVector2( pad.position() ) ); SetNetCode( pad.net().code().value() ); SetLocked( pad.locked() == kiapi::common::types::LockedState::LS_LOCKED ); + SetAttribute( FromProtoEnum( pad.type() ) ); - const kiapi::board::types::PadStack& padstack = pad.pad_stack(); + google::protobuf::Any padStackWrapper; + padStackWrapper.PackFrom( pad.pad_stack() ); + m_padStack.Deserialize( padStackWrapper ); - SetLayer( FromProtoEnum( - padstack.start_layer() ) ); - - SetDrillSize( kiapi::common::UnpackVector2( padstack.drill_diameter() ) ); - SetOrientationDegrees( padstack.angle().value_degrees() ); - - // We don't yet support complex padstacks - if( padstack.layers_size() == 1 ) - { - const kiapi::board::types::PadStackLayer& layer = padstack.layers( 0 ); - SetSize( kiapi::common::UnpackVector2( layer.size() ) ); - SetLayerSet( kiapi::board::UnpackLayerSet( layer.layers() ) ); - SetShape( FromProtoEnum( layer.shape() ) ); - } - - SetUnconnectedLayerMode( - FromProtoEnum( padstack.unconnected_layer_removal() ) ); + SetLayer( m_padStack.StartLayer() ); const kiapi::board::types::DesignRuleOverrides& overrides = pad.overrides(); @@ -584,7 +554,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const VECTOR2I half_size = size / 2; int half_width = std::min( half_size.x, half_size.y ); VECTOR2I half_len( half_size.x - half_width, half_size.y - half_width ); - RotatePoint( half_len, m_orient ); + RotatePoint( half_len, GetOrientation() ); add( new SHAPE_SEGMENT( shapePos - half_len, shapePos + half_len, half_width * 2 ) ); } @@ -624,7 +594,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x ); corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x ); - corners.Rotate( m_orient ); + corners.Rotate( GetOrientation() ); corners.Move( shapePos ); // GAL renders rectangles faster than 4-point polygons so it's worth checking if our @@ -669,7 +639,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const { SHAPE_POLY_SET outline; - TransformRoundChamferedRectToPolygon( outline, shapePos, GetSize(), m_orient, + TransformRoundChamferedRectToPolygon( outline, shapePos, GetSize(), GetOrientation(), GetRoundRectCornerRadius(), GetChamferRectRatio(), GetChamferPositions(), 0, maxError, ERROR_INSIDE ); @@ -691,7 +661,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const { for( SHAPE* shape : primitive->MakeEffectiveShapes() ) { - shape->Rotate( m_orient ); + shape->Rotate( GetOrientation() ); shape->Move( shapePos ); add( shape ); } @@ -706,7 +676,7 @@ void PAD::BuildEffectiveShapes( PCB_LAYER_ID aLayer ) const int half_width = std::min( half_size.x, half_size.y ); VECTOR2I half_len( half_size.x - half_width, half_size.y - half_width ); - RotatePoint( half_len, m_orient ); + RotatePoint( half_len, GetOrientation() ); m_effectiveHoleShape = std::make_shared( m_pos - half_len, m_pos + half_len, half_width * 2 ); @@ -827,9 +797,7 @@ void PAD::SetProperty( PAD_PROP aProperty ) void PAD::SetOrientation( const EDA_ANGLE& aAngle ) { - m_orient = aAngle; - m_orient.Normalize(); - + m_padStack.SetOrientation( aAngle ); SetDirty(); } @@ -928,7 +896,7 @@ VECTOR2I PAD::ShapePos() const VECTOR2I loc_offset = m_padStack.Offset(); - RotatePoint( loc_offset, m_orient ); + RotatePoint( loc_offset, GetOrientation() ); VECTOR2I shape_pos = m_pos + loc_offset; @@ -1426,9 +1394,7 @@ int PAD::Compare( const PAD* aPadRef, const PAD* aPadCmp ) void PAD::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle ) { RotatePoint( m_pos, aRotCentre, aAngle ); - - m_orient += aAngle; - m_orient.Normalize(); + m_padStack.SetOrientation( m_padStack.GetOrientation() + aAngle ); SetDirty(); } @@ -1828,7 +1794,7 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int half_width = std::min( dx, dy ); VECTOR2I delta( dx - half_width, dy - half_width ); - RotatePoint( delta, m_orient ); + RotatePoint( delta, GetOrientation() ); TransformOvalToPolygon( aBuffer, padShapePos - delta, padShapePos + delta, ( half_width + aClearance ) * 2, aMaxError, aErrorLoc, @@ -1844,8 +1810,8 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, int ddy = GetShape() == PAD_SHAPE::TRAPEZOID ? m_padStack.TrapezoidDeltaSize().y / 2 : 0; SHAPE_POLY_SET outline; - TransformTrapezoidToPolygon( outline, padShapePos, m_padStack.Size(), m_orient, ddx, ddy, aClearance, - aMaxError, aErrorLoc ); + TransformTrapezoidToPolygon( outline, padShapePos, m_padStack.Size(), GetOrientation(), ddx, + ddy, aClearance, aMaxError, aErrorLoc ); aBuffer.Append( outline ); break; } @@ -1856,8 +1822,8 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, bool doChamfer = GetShape() == PAD_SHAPE::CHAMFERED_RECT; SHAPE_POLY_SET outline; - TransformRoundChamferedRectToPolygon( outline, padShapePos, m_padStack.Size(), m_orient, - GetRoundRectCornerRadius(), + TransformRoundChamferedRectToPolygon( outline, padShapePos, m_padStack.Size(), + GetOrientation(), GetRoundRectCornerRadius(), doChamfer ? GetChamferRectRatio() : 0, doChamfer ? GetChamferPositions() : 0, aClearance, aMaxError, aErrorLoc ); @@ -1869,7 +1835,7 @@ void PAD::TransformShapeToPolygon( SHAPE_POLY_SET& aBuffer, PCB_LAYER_ID aLayer, { SHAPE_POLY_SET outline; MergePrimitivesAsPolygon( &outline, aErrorLoc ); - outline.Rotate( m_orient ); + outline.Rotate( GetOrientation() ); outline.Move( VECTOR2I( padShapePos ) ); if( aClearance > 0 || aErrorLoc == ERROR_OUTSIDE ) diff --git a/pcbnew/pad.h b/pcbnew/pad.h index bfab03a653..9cb8dc6565 100644 --- a/pcbnew/pad.h +++ b/pcbnew/pad.h @@ -355,7 +355,7 @@ public: /** * Return the rotation angle of the pad. */ - EDA_ANGLE GetOrientation() const { return m_orient; } + EDA_ANGLE GetOrientation() const { return m_padStack.GetOrientation(); } EDA_ANGLE GetFPRelativeOrientation() const; // For property system @@ -365,7 +365,7 @@ public: } double GetOrientationDegrees() const { - return m_orient.AsDegrees(); + return m_padStack.GetOrientation().AsDegrees(); } void SetDrillShape( PAD_DRILL_SHAPE aShape ) @@ -867,8 +867,6 @@ private: PAD_PROP m_property; // Property in fab files (BGA, FIDUCIAL, TESTPOINT, etc.) - EDA_ANGLE m_orient; - int m_lengthPadToDie; // Length net from pad to die, inside the package std::mutex m_zoneLayerOverridesMutex; diff --git a/pcbnew/padstack.cpp b/pcbnew/padstack.cpp index 37ed806086..61ff43991d 100644 --- a/pcbnew/padstack.cpp +++ b/pcbnew/padstack.cpp @@ -20,10 +20,15 @@ #include // RECT_CHAMFER_POSITIONS #include "padstack.h" +#include +#include +#include +#include PADSTACK::PADSTACK() : m_mode( MODE::NORMAL ), + m_orientation( ANGLE_0 ), m_unconnectedLayerMode( UNCONNECTED_LAYER_MODE::KEEP_ALL ), m_customShapeInZoneMode( CUSTOM_SHAPE_ZONE_MODE::OUTLINE ) { @@ -83,12 +88,83 @@ bool PADSTACK::operator==( const PADSTACK& aOther ) const bool PADSTACK::Deserialize( const google::protobuf::Any& aContainer ) { - return false; + using namespace kiapi::board::types; + PadStack padstack; + + if( !aContainer.UnpackTo( &padstack ) ) + return false; + + m_mode = FromProtoEnum( padstack.type() ); + + // TODO + m_layerSet.reset(); + + m_orientation = EDA_ANGLE( padstack.angle().value_degrees(), DEGREES_T ); + + Drill().size = kiapi::common::UnpackVector2( padstack.drill_diameter() ); + Drill().start = FromProtoEnum( padstack.start_layer() ); + Drill().end = FromProtoEnum( padstack.end_layer() ); + + // We don't yet support complex padstacks + if( padstack.layers_size() == 1 ) + { + const PadStackLayer& layer = padstack.layers( 0 ); + Size() = kiapi::common::UnpackVector2( layer.size() ); + SetLayerSet( kiapi::board::UnpackLayerSet( layer.layers() ) ); + SetShape( FromProtoEnum( layer.shape() ) ); + + SHAPE_PROPS& props = CopperLayerDefaults().shape; + props.chamfered_rect_ratio = layer.chamfer_ratio(); + props.round_rect_radius_ratio = layer.corner_rounding_ratio(); + + if( layer.chamfered_corners().top_left() ) + props.chamfered_rect_positions |= RECT_CHAMFER_TOP_LEFT; + + if( layer.chamfered_corners().top_right() ) + props.chamfered_rect_positions |= RECT_CHAMFER_TOP_RIGHT; + + if( layer.chamfered_corners().bottom_left() ) + props.chamfered_rect_positions |= RECT_CHAMFER_BOTTOM_LEFT; + + if( layer.chamfered_corners().bottom_right() ) + props.chamfered_rect_positions |= RECT_CHAMFER_BOTTOM_RIGHT; + } + + SetUnconnectedLayerMode( + FromProtoEnum( padstack.unconnected_layer_removal() ) ); + + return true; } void PADSTACK::Serialize( google::protobuf::Any& aContainer ) const { + using namespace kiapi::board::types; + PadStack padstack; + + padstack.set_type( ToProtoEnum( m_mode ) ); + padstack.set_start_layer( ToProtoEnum( StartLayer() ) ); + padstack.set_end_layer( ToProtoEnum( EndLayer() ) ); + kiapi::common::PackVector2( *padstack.mutable_drill_diameter(), Drill().size ); + padstack.mutable_angle()->set_value_degrees( m_orientation.AsDegrees() ); + + PadStackLayer* stackLayer = padstack.add_layers(); + kiapi::board::PackLayerSet( *stackLayer->mutable_layers(), LayerSet() ); + kiapi::common::PackVector2( *stackLayer->mutable_size(), Size() ); + stackLayer->set_shape( ToProtoEnum( Shape() ) ); + stackLayer->set_chamfer_ratio( CopperLayerDefaults().shape.chamfered_rect_ratio ); + stackLayer->set_corner_rounding_ratio( CopperLayerDefaults().shape.round_rect_radius_ratio ); + + const int& corners = CopperLayerDefaults().shape.chamfered_rect_positions; + stackLayer->mutable_chamfered_corners()->set_top_left( corners & RECT_CHAMFER_TOP_LEFT ); + stackLayer->mutable_chamfered_corners()->set_top_right( corners & RECT_CHAMFER_TOP_RIGHT ); + stackLayer->mutable_chamfered_corners()->set_bottom_left( corners & RECT_CHAMFER_BOTTOM_LEFT ); + stackLayer->mutable_chamfered_corners()->set_bottom_right( corners & RECT_CHAMFER_BOTTOM_RIGHT ); + + padstack.set_unconnected_layer_removal( + ToProtoEnum( m_unconnectedLayerMode ) ); + + aContainer.PackFrom( padstack ); } @@ -99,6 +175,18 @@ wxString PADSTACK::Name() const } +PCB_LAYER_ID PADSTACK::StartLayer() const +{ + return m_drill.start; +} + + +PCB_LAYER_ID PADSTACK::EndLayer() const +{ + return m_drill.end; +} + + PADSTACK::SHAPE_PROPS::SHAPE_PROPS() : shape( PAD_SHAPE::CIRCLE ), anchor_shape( PAD_SHAPE::CIRCLE ), diff --git a/pcbnew/padstack.h b/pcbnew/padstack.h index 8645af51a4..cc4faf4250 100644 --- a/pcbnew/padstack.h +++ b/pcbnew/padstack.h @@ -241,9 +241,22 @@ public: LSET& LayerSet() { return m_layerSet; } void SetLayerSet( const LSET& aSet ) { m_layerSet = aSet; } + PCB_LAYER_ID StartLayer() const; + PCB_LAYER_ID EndLayer() const; + + MODE Mode() const { return m_mode; } + void SetMode( MODE aMode ) { m_mode = aMode; } + ///! Returns the name of this padstack in IPC-7351 format wxString Name() const; + EDA_ANGLE GetOrientation() const { return m_orientation; } + void SetOrientation( EDA_ANGLE aAngle ) + { + m_orientation = aAngle; + m_orientation.Normalize(); + } + DRILL_PROPS& Drill() { return m_drill; } const DRILL_PROPS& Drill() const { return m_drill; } @@ -329,6 +342,9 @@ private: ///! An override for the IPC-7351 padstack name wxString m_customName; + ///! The rotation of the pad relative to an outer reference frame + EDA_ANGLE m_orientation; + ///! The properties applied to copper layers if they aren't overridden COPPER_LAYER_PROPS m_defaultCopperProps; diff --git a/pcbnew/pcb_text.cpp b/pcbnew/pcb_text.cpp index b517abca2a..ca69b304ce 100644 --- a/pcbnew/pcb_text.cpp +++ b/pcbnew/pcb_text.cpp @@ -168,8 +168,7 @@ bool PCB_TEXT::Deserialize( const google::protobuf::Any &aContainer ) attrs.m_Angle = EDA_ANGLE( text.attributes().angle().value_degrees(), DEGREES_T ); attrs.m_LineSpacing = text.attributes().line_spacing(); - SetTextThickness( text.attributes().stroke_width().value_nm() ); - + attrs.m_StrokeWidth = text.attributes().stroke_width().value_nm(); attrs.m_Halign = FromProtoEnum( text.attributes().horizontal_alignment() ); diff --git a/pcbnew/pcb_track.cpp b/pcbnew/pcb_track.cpp index 7897c8dbed..eed629ddfe 100644 --- a/pcbnew/pcb_track.cpp +++ b/pcbnew/pcb_track.cpp @@ -90,7 +90,13 @@ PCB_VIA::PCB_VIA( BOARD_ITEM* aParent ) : Padstack().Drill().end = B_Cu; SetDrillDefault(); - Padstack().SetUnconnectedLayerMode( PADSTACK::UNCONNECTED_LAYER_MODE::KEEP_ALL ); + m_padStack.SetUnconnectedLayerMode( PADSTACK::UNCONNECTED_LAYER_MODE::KEEP_ALL ); + + // Until vias support custom padstack; their layer set should always be cleared + m_padStack.LayerSet().reset(); + + // For now, vias are always circles + m_padStack.SetShape( PAD_SHAPE::CIRCLE ); m_zoneLayerOverrides.fill( ZLO_NONE ); @@ -375,31 +381,19 @@ void PCB_VIA::Serialize( google::protobuf::Any &aContainer ) const via.mutable_position()->set_x_nm( GetPosition().x ); via.mutable_position()->set_y_nm( GetPosition().y ); - const PADSTACK& stack = Padstack(); + PADSTACK padstack = Padstack(); - kiapi::board::types::PadStack* padstack = via.mutable_pad_stack(); - padstack->set_type( GetViaType() == VIATYPE::BLIND_BURIED - ? kiapi::board::types::PadStackType::PST_BLIND_BURIED - : kiapi::board::types::PadStackType::PST_THROUGH ); - padstack->set_start_layer( - ToProtoEnum( stack.Drill().start ) ); - padstack->set_end_layer( - ToProtoEnum( stack.Drill().end ) ); - kiapi::common::PackVector2( *padstack->mutable_drill_diameter(), - { GetDrillValue(), GetDrillValue() } ); + // Via width is currently stored in PCB_TRACK::m_Width rather than in the + // padstack object; so hack it in here unless/until that changes + padstack.Size() = { m_Width, m_Width }; - kiapi::board::types::PadStackLayer* stackLayer = padstack->add_layers(); - kiapi::board::PackLayerSet( *stackLayer->mutable_layers(), GetLayerSet() ); - kiapi::common::PackVector2( *stackLayer->mutable_size(), - { GetWidth(), GetWidth() } ); + google::protobuf::Any padStackWrapper; + padstack.Serialize( padStackWrapper ); + padStackWrapper.UnpackTo( via.mutable_pad_stack() ); - // TODO: Microvia status is ignored here. Do we still need it? - padstack->set_unconnected_layer_removal( - ToProtoEnum( - Padstack().UnconnectedLayerMode() ) ); + via.set_type( ToProtoEnum( GetViaType() ) ); via.set_locked( IsLocked() ? kiapi::common::types::LockedState::LS_LOCKED : kiapi::common::types::LockedState::LS_UNLOCKED ); via.mutable_net()->mutable_code()->set_value( GetNetCode() ); @@ -421,42 +415,15 @@ bool PCB_VIA::Deserialize( const google::protobuf::Any &aContainer ) SetEnd( GetStart() ); SetDrill( via.pad_stack().drill_diameter().x_nm() ); - const kiapi::board::types::PadStack& padstack = via.pad_stack(); + google::protobuf::Any padStackWrapper; + padStackWrapper.PackFrom( via.pad_stack() ); + + if( !m_padStack.Deserialize( padStackWrapper ) ) + return false; // We don't yet support complex padstacks for vias - if( padstack.layers_size() == 1 ) - { - const kiapi::board::types::PadStackLayer& layer = padstack.layers( 0 ); - SetWidth( layer.size().x_nm() ); - } - - switch( padstack.type() ) - { - case kiapi::board::types::PadStackType::PST_BLIND_BURIED: - SetViaType( VIATYPE::BLIND_BURIED ); - break; - - default: - SetViaType( VIATYPE::THROUGH ); - break; - } - - if( GetViaType() != VIATYPE::THROUGH ) - { - Padstack().Drill().start = FromProtoEnum( - padstack.start_layer() ); - - Padstack().Drill().end = FromProtoEnum( - padstack.end_layer() ); - } - else - { - Padstack().Drill().start = F_Cu; - Padstack().Drill().end = B_Cu; - } - Padstack().SetUnconnectedLayerMode( FromProtoEnum( - padstack.unconnected_layer_removal() ) ); - + SetWidth( m_padStack.Size().x ); + SetViaType( FromProtoEnum( via.type() ) ); SetNetCode( via.net().code().value() ); SetLocked( via.locked() == kiapi::common::types::LockedState::LS_LOCKED ); diff --git a/qa/data/pcbnew/padstacks.kicad_pcb b/qa/data/pcbnew/padstacks.kicad_pcb new file mode 100644 index 0000000000..e26de35707 --- /dev/null +++ b/qa/data/pcbnew/padstacks.kicad_pcb @@ -0,0 +1,879 @@ +(kicad_pcb + (version 20240108) + (generator "pcbnew") + (generator_version "8.0") + (general + (thickness 1.6) + (legacy_teardrops no) + ) + (paper "A4") + (layers + (0 "F.Cu" signal) + (1 "In1.Cu" signal) + (2 "In2.Cu" signal) + (3 "In3.Cu" signal) + (4 "In4.Cu" signal) + (31 "B.Cu" signal) + (32 "B.Adhes" user "B.Adhesive") + (33 "F.Adhes" user "F.Adhesive") + (34 "B.Paste" user) + (35 "F.Paste" user) + (36 "B.SilkS" user "B.Silkscreen") + (37 "F.SilkS" user "F.Silkscreen") + (38 "B.Mask" user) + (39 "F.Mask" user) + (40 "Dwgs.User" user "User.Drawings") + (41 "Cmts.User" user "User.Comments") + (42 "Eco1.User" user "User.Eco1") + (43 "Eco2.User" user "User.Eco2") + (44 "Edge.Cuts" user) + (45 "Margin" user) + (46 "B.CrtYd" user "B.Courtyard") + (47 "F.CrtYd" user "F.Courtyard") + (48 "B.Fab" user) + (49 "F.Fab" user) + (50 "User.1" user) + (51 "User.2" user) + (52 "User.3" user) + (53 "User.4" user) + (54 "User.5" user) + (55 "User.6" user) + (56 "User.7" user) + (57 "User.8" user) + (58 "User.9" user) + ) + (setup + (stackup + (layer "F.SilkS" + (type "Top Silk Screen") + ) + (layer "F.Paste" + (type "Top Solder Paste") + ) + (layer "F.Mask" + (type "Top Solder Mask") + (thickness 0.01) + ) + (layer "F.Cu" + (type "copper") + (thickness 0.035) + ) + (layer "dielectric 1" + (type "prepreg") + (thickness 0.1) + (material "FR4") + (epsilon_r 4.5) + (loss_tangent 0.02) + ) + (layer "In1.Cu" + (type "copper") + (thickness 0.035) + ) + (layer "dielectric 2" + (type "core") + (thickness 0.535) + (material "FR4") + (epsilon_r 4.5) + (loss_tangent 0.02) + ) + (layer "In2.Cu" + (type "copper") + (thickness 0.035) + ) + (layer "dielectric 3" + (type "prepreg") + (thickness 0.1) + (material "FR4") + (epsilon_r 4.5) + (loss_tangent 0.02) + ) + (layer "In3.Cu" + (type "copper") + (thickness 0.035) + ) + (layer "dielectric 4" + (type "core") + (thickness 0.535) + (material "FR4") + (epsilon_r 4.5) + (loss_tangent 0.02) + ) + (layer "In4.Cu" + (type "copper") + (thickness 0.035) + ) + (layer "dielectric 5" + (type "prepreg") + (thickness 0.1) + (material "FR4") + (epsilon_r 4.5) + (loss_tangent 0.02) + ) + (layer "B.Cu" + (type "copper") + (thickness 0.035) + ) + (layer "B.Mask" + (type "Bottom Solder Mask") + (thickness 0.01) + ) + (layer "B.Paste" + (type "Bottom Solder Paste") + ) + (layer "B.SilkS" + (type "Bottom Silk Screen") + ) + (copper_finish "None") + (dielectric_constraints no) + ) + (pad_to_mask_clearance 0) + (allow_soldermask_bridges_in_footprints no) + (pcbplotparams + (layerselection 0x00010fc_ffffffff) + (plot_on_all_layers_selection 0x0000000_00000000) + (disableapertmacros no) + (usegerberextensions no) + (usegerberattributes yes) + (usegerberadvancedattributes yes) + (creategerberjobfile yes) + (dashed_line_dash_ratio 12.000000) + (dashed_line_gap_ratio 3.000000) + (svgprecision 4) + (plotframeref no) + (viasonmask no) + (mode 1) + (useauxorigin no) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (pdf_front_fp_property_popups yes) + (pdf_back_fp_property_popups yes) + (dxfpolygonmode yes) + (dxfimperialunits yes) + (dxfusepcbnewfont yes) + (psnegative no) + (psa4output no) + (plotreference yes) + (plotvalue yes) + (plotfptext yes) + (plotinvisibletext no) + (sketchpadsonfab no) + (subtractmaskfromsilk no) + (outputformat 1) + (mirror no) + (drillshape 1) + (scaleselection 1) + (outputdirectory "") + ) + ) + (net 0 "") + (net 1 "A") + (net 2 "B") + (footprint "TestPoint:TestPoint_Pad_D2.0mm" + (layer "F.Cu") + (uuid "0c12f606-2e6b-4b10-8aee-13ada275880a") + (at 125 89) + (descr "SMD pad as test Point, diameter 2.0mm") + (tags "test point SMD pad") + (property "Reference" "P2" + (at 0 -1.998 0) + (layer "F.SilkS") + (uuid "29533062-1c68-45f1-aa62-808c999e5f83") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "TestPoint_Pad_D2.0mm" + (at 0 2.05 0) + (layer "F.Fab") + (hide yes) + (uuid "fd646f0b-5dc3-467c-97d3-06db9fc43f63") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Footprint" "TestPoint:TestPoint_Pad_D2.0mm" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "77760901-137c-4ad1-95fd-8bca92e130f9") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "160cf796-ce2e-44d6-b25d-7cde236f4252") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "4a70b60d-a7c8-4815-afbf-9d244e28b40a") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (attr exclude_from_pos_files exclude_from_bom) + (fp_circle + (center 0 0) + (end 0 1.2) + (stroke + (width 0.12) + (type solid) + ) + (fill none) + (layer "F.SilkS") + (uuid "c03d6f26-7038-4706-b2fb-d9a9feae2ab3") + ) + (fp_circle + (center 0 0) + (end 1.5 0) + (stroke + (width 0.05) + (type solid) + ) + (fill none) + (layer "F.CrtYd") + (uuid "04545c49-ee36-461e-8b2e-f8747ad85b16") + ) + (fp_text user "${REFERENCE}" + (at 0 -2 0) + (layer "F.Fab") + (uuid "6387eca8-2e8b-45cc-b457-5fdbc4a80b3f") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (pad "1" smd circle + (at 0 0 90) + (size 2 2) + (layers "F.Cu" "F.Mask") + (uuid "d37584cd-2e2f-40b5-822b-12791118953d") + ) + ) + (footprint "TestPoint:TestPoint_Pad_D2.0mm" + (layer "F.Cu") + (uuid "516f904c-b21d-49d3-bbc4-a9b97f897bb1") + (at 137 89) + (descr "SMD pad as test Point, diameter 2.0mm") + (tags "test point SMD pad") + (property "Reference" "P5" + (at 0 -1.998 0) + (layer "F.SilkS") + (uuid "68cba2b6-b596-4711-a20c-f5aace777c21") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "TestPoint_Pad_D2.0mm" + (at 0 2.05 0) + (layer "F.Fab") + (hide yes) + (uuid "6f02e655-dc34-4a7e-bd71-f79a95274878") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Footprint" "TestPoint:TestPoint_Pad_D2.0mm" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "b44ac9da-098a-4f00-9ae0-9e18cb78e77b") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "9b63f67d-c7d1-440b-9109-21f26fc865ba") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "1eb2de7a-10c7-45c6-9b2b-f1878805e977") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (attr exclude_from_pos_files exclude_from_bom) + (fp_circle + (center 0 0) + (end 0 1.2) + (stroke + (width 0.12) + (type solid) + ) + (fill none) + (layer "F.SilkS") + (uuid "9cb364d6-bc28-4600-8690-1945a69b4efe") + ) + (fp_circle + (center 0 0) + (end 1.5 0) + (stroke + (width 0.05) + (type solid) + ) + (fill none) + (layer "F.CrtYd") + (uuid "2aacb056-b289-4231-8a9b-cdad899fcc6e") + ) + (fp_text user "${REFERENCE}" + (at 0 -2 0) + (layer "F.Fab") + (uuid "874081cb-e656-419e-8c45-68e819c6b71a") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (pad "2" smd trapezoid + (at 0 0 315) + (size 3 2) + (rect_delta 1 0) + (layers "F.Cu" "F.Paste" "F.Mask") + (uuid "f98951ae-c7c4-445b-a39a-a4d57888a02e") + ) + ) + (footprint "TestPoint:TestPoint_Pad_D2.0mm" + (layer "F.Cu") + (uuid "72233f75-c54b-4983-a966-c01867960037") + (at 133 89) + (descr "SMD pad as test Point, diameter 2.0mm") + (tags "test point SMD pad") + (property "Reference" "P4" + (at 0 -1.998 0) + (layer "F.SilkS") + (uuid "50769063-424e-4393-a2a5-8a4afc86a5f6") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "TestPoint_Pad_D2.0mm" + (at 0 2.05 0) + (layer "F.Fab") + (hide yes) + (uuid "a1a75197-03e0-4e76-b27f-4926bc09a754") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Footprint" "TestPoint:TestPoint_Pad_D2.0mm" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "ba936de1-036a-4248-bbb7-91ef95178a8b") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "8187b195-b69e-4768-b5fb-4705d21fdeaf") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "b711170d-a950-461d-b38d-8189914c26ae") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (attr exclude_from_pos_files exclude_from_bom) + (fp_circle + (center 0 0) + (end 0 1.2) + (stroke + (width 0.12) + (type solid) + ) + (fill none) + (layer "F.SilkS") + (uuid "92f6ddd2-345a-488f-826f-c01d36d10578") + ) + (fp_circle + (center 0 0) + (end 1.5 0) + (stroke + (width 0.05) + (type solid) + ) + (fill none) + (layer "F.CrtYd") + (uuid "81f7d7e8-fc1c-401b-9a37-f0bcb4a35e24") + ) + (fp_text user "${REFERENCE}" + (at 0 -2 0) + (layer "F.Fab") + (uuid "34183372-a393-435e-b4af-f67d0575d11d") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (pad "Pad" smd roundrect + (at 0 0 45) + (size 3 2) + (layers "F.Cu" "F.Paste" "F.Mask") + (roundrect_rratio 0.1) + (chamfer_ratio 0.21) + (chamfer top_left bottom_right) + (uuid "1ad1d3ed-e8f5-4c7f-b0f6-095051a53b11") + ) + ) + (footprint "TestPoint:TestPoint_Pad_D2.0mm" + (layer "F.Cu") + (uuid "bccaa590-e277-424e-9452-8ccb31862c88") + (at 121 89) + (descr "SMD pad as test Point, diameter 2.0mm") + (tags "test point SMD pad") + (property "Reference" "P1" + (at 0 -1.998 0) + (layer "F.SilkS") + (uuid "9c54587b-d5ae-4242-962b-6e199e7ffccc") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "TestPoint_Pad_D2.0mm" + (at 0 2.05 0) + (layer "F.Fab") + (hide yes) + (uuid "58bd7580-ca97-467b-bc98-ab9f4296c399") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Footprint" "TestPoint:TestPoint_Pad_D2.0mm" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "229a859d-ddeb-445e-b1c3-66df7fb9709f") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "a7c735ac-7821-453f-8e0c-20b4a2668cd0") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "64a3ff2b-93a4-4db6-8b1f-6626b3972c84") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (attr exclude_from_pos_files exclude_from_bom) + (fp_circle + (center 0 0) + (end 0 1.2) + (stroke + (width 0.12) + (type solid) + ) + (fill none) + (layer "F.SilkS") + (uuid "17b3c656-d3b6-4523-a217-6cc0c933bbc5") + ) + (fp_circle + (center 0 0) + (end 1.5 0) + (stroke + (width 0.05) + (type solid) + ) + (fill none) + (layer "F.CrtYd") + (uuid "bcf6e409-f396-4570-bbac-9a0bde9d6eb7") + ) + (fp_text user "${REFERENCE}" + (at 0 -2 0) + (layer "F.Fab") + (uuid "70ccb569-831d-4f12-afe4-88c6c3d4e3b0") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (pad "1" smd circle + (at 0 0) + (size 2 2) + (layers "F.Cu" "F.Mask") + (uuid "bd1ca0c2-74bb-4a01-94e6-11796af0cb7e") + ) + ) + (footprint "TestPoint:TestPoint_Pad_D2.0mm" + (layer "F.Cu") + (uuid "ecc0fb0f-74be-4cd5-a2b5-2009c7f9f73c") + (at 129 89) + (descr "SMD pad as test Point, diameter 2.0mm") + (tags "test point SMD pad") + (property "Reference" "P3" + (at 0 -1.998 0) + (layer "F.SilkS") + (uuid "58ffde45-fba5-43db-8389-e047f26aab55") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "TestPoint_Pad_D2.0mm" + (at 0 2.05 0) + (layer "F.Fab") + (hide yes) + (uuid "3f4c00bd-623b-4cdb-8124-59191148fa44") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Footprint" "TestPoint:TestPoint_Pad_D2.0mm" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "b732c943-e9ae-4147-aeb2-735f86b72eef") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "17598608-0902-4805-a022-bd8da9235d0e") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (property "Description" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "0ec04652-0134-49e1-9e4a-0e7f3dc101b0") + (effects + (font + (size 1.27 1.27) + (thickness 0.15) + ) + ) + ) + (attr exclude_from_pos_files exclude_from_bom) + (fp_circle + (center 0 0) + (end 0 1.2) + (stroke + (width 0.12) + (type solid) + ) + (fill none) + (layer "F.SilkS") + (uuid "7584de47-699d-4756-8eed-a1ffa89c7756") + ) + (fp_circle + (center 0 0) + (end 1.5 0) + (stroke + (width 0.05) + (type solid) + ) + (fill none) + (layer "F.CrtYd") + (uuid "b4644ae7-78b8-4b76-a571-5cad70b4d1ca") + ) + (fp_text user "${REFERENCE}" + (at 0 -2 0) + (layer "F.Fab") + (uuid "b7d991b5-45bd-4a62-af88-db0c92e6a949") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (pad "Pad" smd circle + (at 0 0 90) + (size 2 2) + (property pad_prop_bga) + (layers "F.Cu" "F.Paste" "F.Mask") + (die_length 1.8) + (uuid "d4769495-2985-428a-a206-5d90728f6d88") + ) + ) + (gr_rect + (start 118 78) + (end 146 106) + (stroke + (width 0.05) + (type default) + ) + (fill none) + (layer "Edge.Cuts") + (uuid "5d1e8cc9-08f0-4cd1-a676-1faf146c0408") + ) + (via blind + (at 128 80) + (size 0.6) + (drill 0.3) + (layers "F.Cu" "B.Cu") + (net 0) + (uuid "453c7569-dd77-45eb-bcc3-30db3a0f40a9") + ) + (via blind + (at 128 81) + (size 0.6) + (drill 0.3) + (layers "In1.Cu" "In4.Cu") + (net 0) + (uuid "68434c33-7a9f-42fc-987d-91fe3a581387") + ) + (via blind + (at 128 83) + (size 0.6) + (drill 0.3) + (layers "In2.Cu" "In3.Cu") + (net 0) + (uuid "13486125-e7d8-4fb9-bf37-cba2e8c45ed4") + ) + (via blind + (at 128 82) + (size 0.6) + (drill 0.3) + (layers "In2.Cu" "In3.Cu") + (net 0) + (uuid "8b2bd992-9b12-4445-b400-250bd7889789") + ) + (via + (at 120 80) + (size 0.6) + (drill 0.3) + (layers "F.Cu" "B.Cu") + (free yes) + (net 1) + (uuid "2ff08d6b-d2fa-498c-aa0a-437903b48438") + ) + (via + (at 124 80) + (size 0.6) + (drill 0.3) + (layers "F.Cu" "B.Cu") + (free yes) + (net 1) + (uuid "b86ba856-d576-4a99-a8e8-6d1c7f1f8e54") + ) + (via + (at 122 80) + (size 0.6) + (drill 0.3) + (layers "F.Cu" "B.Cu") + (free yes) + (net 2) + (uuid "4da21d74-ca51-4030-841d-9fa4271dd639") + ) + (via + (at 122 82) + (size 0.7) + (drill 0.35) + (layers "F.Cu" "B.Cu") + (remove_unused_layers yes) + (keep_end_layers no) + (free yes) + (zone_layer_connections) + (teardrops + (best_length_ratio 0.2) + (max_length 0) + (best_width_ratio 0.8) + (max_width 10) + (curve_points 10) + (filter_ratio 0.75) + (enabled yes) + (allow_two_segments yes) + (prefer_zone_connections yes) + ) + (net 2) + (uuid "c37863ac-f1db-49d4-876a-be127599ff62") + ) + (via + (at 122 81) + (size 0.7) + (drill 0.35) + (layers "F.Cu" "B.Cu") + (remove_unused_layers yes) + (keep_end_layers yes) + (free yes) + (zone_layer_connections) + (teardrops + (best_length_ratio 0.42) + (max_length 0.75) + (best_width_ratio 1.01) + (max_width 2.3) + (curve_points 0) + (filter_ratio 0.85) + (enabled yes) + (allow_two_segments no) + (prefer_zone_connections yes) + ) + (net 2) + (uuid "d8a5911f-c1d6-4713-912d-d31101496061") + ) + (via micro + (at 126 80) + (size 0.2) + (drill 0.1) + (layers "F.Cu" "B.Cu") + (locked yes) + (free yes) + (net 2) + (uuid "dab5afb6-716e-4443-b91e-13650cfba71f") + ) + (via micro + (at 126 81) + (size 0.2) + (drill 0.1) + (layers "F.Cu" "In4.Cu") + (locked yes) + (free yes) + (net 2) + (uuid "dd040225-30f9-4c79-ad3e-e43383b2fb35") + ) + (via micro + (at 126 83) + (size 0.3) + (drill 0.1) + (layers "In3.Cu" "B.Cu") + (locked yes) + (free yes) + (net 2) + (uuid "878e8a3b-77d9-402e-9019-c139f6ee7548") + ) + (via micro + (at 126 82) + (size 0.2) + (drill 0.1) + (layers "In4.Cu" "B.Cu") + (locked yes) + (free yes) + (net 2) + (uuid "c5a1f081-1841-48f2-858c-598a487445a0") + ) +) diff --git a/qa/data/pcbnew/padstacks.kicad_pro b/qa/data/pcbnew/padstacks.kicad_pro new file mode 100644 index 0000000000..e10a238e79 --- /dev/null +++ b/qa/data/pcbnew/padstacks.kicad_pro @@ -0,0 +1,273 @@ +{ + "board": { + "3dviewports": [], + "design_settings": { + "defaults": { + "apply_defaults_to_fp_fields": false, + "apply_defaults_to_fp_shapes": false, + "apply_defaults_to_fp_text": false, + "board_outline_line_width": 0.05, + "copper_line_width": 0.2, + "copper_text_italic": false, + "copper_text_size_h": 1.5, + "copper_text_size_v": 1.5, + "copper_text_thickness": 0.3, + "copper_text_upright": false, + "courtyard_line_width": 0.05, + "dimension_precision": 4, + "dimension_units": 3, + "dimensions": { + "arrow_length": 1270000, + "extension_offset": 500000, + "keep_text_aligned": true, + "suppress_zeroes": false, + "text_position": 0, + "units_format": 1 + }, + "fab_line_width": 0.1, + "fab_text_italic": false, + "fab_text_size_h": 1.0, + "fab_text_size_v": 1.0, + "fab_text_thickness": 0.15, + "fab_text_upright": false, + "other_line_width": 0.1, + "other_text_italic": false, + "other_text_size_h": 1.0, + "other_text_size_v": 1.0, + "other_text_thickness": 0.15, + "other_text_upright": false, + "pads": { + "drill": 0.0, + "height": 2.0, + "width": 3.0 + }, + "silk_line_width": 0.1, + "silk_text_italic": false, + "silk_text_size_h": 1.0, + "silk_text_size_v": 1.0, + "silk_text_thickness": 0.1, + "silk_text_upright": false, + "zones": { + "min_clearance": 0.5 + } + }, + "diff_pair_dimensions": [], + "drc_exclusions": [], + "meta": { + "version": 2 + }, + "rule_severities": { + "annular_width": "error", + "clearance": "error", + "connection_width": "warning", + "copper_edge_clearance": "error", + "copper_sliver": "warning", + "courtyards_overlap": "error", + "diff_pair_gap_out_of_range": "error", + "diff_pair_uncoupled_length_too_long": "error", + "drill_out_of_range": "error", + "duplicate_footprints": "warning", + "extra_footprint": "warning", + "footprint": "error", + "footprint_symbol_mismatch": "warning", + "footprint_type_mismatch": "ignore", + "hole_clearance": "error", + "hole_near_hole": "error", + "holes_co_located": "warning", + "invalid_outline": "error", + "isolated_copper": "warning", + "item_on_disabled_layer": "error", + "items_not_allowed": "error", + "length_out_of_range": "error", + "lib_footprint_issues": "warning", + "lib_footprint_mismatch": "warning", + "malformed_courtyard": "error", + "microvia_drill_out_of_range": "error", + "missing_courtyard": "ignore", + "missing_footprint": "warning", + "net_conflict": "warning", + "npth_inside_courtyard": "ignore", + "padstack": "warning", + "pth_inside_courtyard": "ignore", + "shorting_items": "error", + "silk_edge_clearance": "warning", + "silk_over_copper": "warning", + "silk_overlap": "warning", + "skew_out_of_range": "error", + "solder_mask_bridge": "error", + "starved_thermal": "error", + "text_height": "warning", + "text_thickness": "warning", + "through_hole_pad_without_hole": "error", + "too_many_vias": "error", + "track_dangling": "warning", + "track_width": "error", + "tracks_crossing": "error", + "unconnected_items": "error", + "unresolved_variable": "error", + "via_dangling": "warning", + "zones_intersect": "error" + }, + "rules": { + "max_error": 0.005, + "min_clearance": 0.0, + "min_connection": 0.0, + "min_copper_edge_clearance": 0.5, + "min_hole_clearance": 0.25, + "min_hole_to_hole": 0.25, + "min_microvia_diameter": 0.2, + "min_microvia_drill": 0.1, + "min_resolved_spokes": 2, + "min_silk_clearance": 0.0, + "min_text_height": 0.8, + "min_text_thickness": 0.08, + "min_through_hole_diameter": 0.3, + "min_track_width": 0.0, + "min_via_annular_width": 0.1, + "min_via_diameter": 0.5, + "solder_mask_to_copper_clearance": 0.0, + "use_height_for_length_calcs": true + }, + "teardrop_options": [ + { + "td_onpadsmd": true, + "td_onroundshapesonly": false, + "td_ontrackend": false, + "td_onviapad": true + } + ], + "teardrop_parameters": [ + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_on_pad_in_zone": false, + "td_target_name": "td_round_shape", + "td_width_to_size_filter_ratio": 0.9 + }, + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_on_pad_in_zone": false, + "td_target_name": "td_rect_shape", + "td_width_to_size_filter_ratio": 0.9 + }, + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_on_pad_in_zone": false, + "td_target_name": "td_track_end", + "td_width_to_size_filter_ratio": 0.9 + } + ], + "track_widths": [], + "tuning_pattern_settings": { + "diff_pair_defaults": { + "corner_radius_percentage": 80, + "corner_style": 1, + "max_amplitude": 1.0, + "min_amplitude": 0.2, + "single_sided": false, + "spacing": 1.0 + }, + "diff_pair_skew_defaults": { + "corner_radius_percentage": 80, + "corner_style": 1, + "max_amplitude": 1.0, + "min_amplitude": 0.2, + "single_sided": false, + "spacing": 0.6 + }, + "single_track_defaults": { + "corner_radius_percentage": 80, + "corner_style": 1, + "max_amplitude": 1.0, + "min_amplitude": 0.2, + "single_sided": false, + "spacing": 0.6 + } + }, + "via_dimensions": [], + "zones_allow_external_fillets": false + }, + "ipc2581": { + "dist": "", + "distpn": "", + "internal_id": "", + "mfg": "", + "mpn": "" + }, + "layer_presets": [], + "viewports": [] + }, + "boards": [], + "cvpcb": { + "equivalence_files": [] + }, + "libraries": { + "pinned_footprint_libs": [], + "pinned_symbol_libs": [] + }, + "meta": { + "filename": "padstacks.kicad_pro", + "version": 1 + }, + "net_settings": { + "classes": [ + { + "bus_width": 12, + "clearance": 0.2, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "name": "Default", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "schematic_color": "rgba(0, 0, 0, 0.000)", + "track_width": 0.2, + "via_diameter": 0.6, + "via_drill": 0.3, + "wire_width": 6 + } + ], + "meta": { + "version": 3 + }, + "net_colors": null, + "netclass_assignments": null, + "netclass_patterns": [] + }, + "pcbnew": { + "last_paths": { + "gencad": "", + "idf": "", + "netlist": "", + "plot": "", + "pos_files": "", + "specctra_dsn": "", + "step": "", + "svg": "", + "vrml": "" + }, + "page_layout_descr_file": "" + }, + "schematic": { + "legacy_lib_dir": "", + "legacy_lib_list": [] + }, + "sheets": [], + "text_variables": {} +} diff --git a/qa/tests/api/test_api_proto.cpp b/qa/tests/api/test_api_proto.cpp index 5028f94907..c71c0cda55 100644 --- a/qa/tests/api/test_api_proto.cpp +++ b/qa/tests/api/test_api_proto.cpp @@ -54,6 +54,8 @@ void testProtoFromKiCadObject( KiCadClass* aInput ) google::protobuf::Any any; BOOST_REQUIRE_NO_THROW( aInput->Serialize( any ) ); + BOOST_TEST_MESSAGE( "Input: " << any.Utf8DebugString() ); + ProtoClass proto; BOOST_REQUIRE_MESSAGE( any.UnpackTo( &proto ), "Any message did not unpack into the requested type" ); @@ -67,18 +69,16 @@ void testProtoFromKiCadObject( KiCadClass* aInput ) // This round-trip checks that we can create an equivalent protobuf google::protobuf::Any outputAny; BOOST_REQUIRE_NO_THROW( output.Serialize( outputAny ) ); + BOOST_TEST_MESSAGE( "Output: " << outputAny.Utf8DebugString() ); + if( !( outputAny.SerializeAsString() == any.SerializeAsString() ) ) { - BOOST_TEST_MESSAGE( "Input: " << any.Utf8DebugString() ); - BOOST_TEST_MESSAGE( "Output: " << outputAny.Utf8DebugString() ); BOOST_TEST_FAIL( "Round-tripped protobuf does not match" ); } // This round-trip checks that we can create an equivalent KiCad object if( !( output == *aInput ) ) { - if( ( output == *aInput ) ) - BOOST_TEST_MESSAGE("ha"); BOOST_TEST_FAIL( "Round-tripped object does not match" ); } } @@ -118,4 +118,26 @@ BOOST_FIXTURE_TEST_CASE( BoardTypes, PROTO_TEST_FIXTURE ) // testProtoFromKiCadObject( zone ); } + +BOOST_FIXTURE_TEST_CASE( Padstacks, PROTO_TEST_FIXTURE ) +{ + KI_TEST::LoadBoard( m_settingsManager, "padstacks", m_board ); + + for( PCB_TRACK* track : m_board->Tracks() ) + { + switch( track->Type() ) + { + case PCB_VIA_T: + testProtoFromKiCadObject( static_cast( track ) ); + break; + + default: + wxFAIL; + } + } + + for( FOOTPRINT* footprint : m_board->Footprints() ) + testProtoFromKiCadObject( footprint ); +} + BOOST_AUTO_TEST_SUITE_END()