7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-21 14:31:42 +00:00

Move padstack serialization to PADSTACK

Also move a few more things from pad/via
This commit is contained in:
Jon Evans 2024-06-01 16:31:50 -04:00
parent 4f4311ba57
commit 0b0a37aaf7
11 changed files with 1465 additions and 134 deletions

View File

@ -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

View File

@ -24,10 +24,44 @@
#include <wx/wx.h>
#include <padstack.h>
#include <pcb_track.h>
#include <zones.h>
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<PAD_ATTRIB>");
}
}
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<types::PadType>" );
}
}
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<PADSTACK::MODE>");
}
}
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<types::PadStackType>" );
}
}
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<VIATYPE>");
}
}
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<types::ViaType>" );
}
}
template<>
types::ZoneConnectionStyle ToProtoEnum( ZONE_CONNECTION aValue )
{

View File

@ -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<PAD_ATTRIB, PadType>( GetAttribute() ) );
kiapi::board::types::PadStack* padstack = pad.mutable_pad_stack();
padstack->set_type( kiapi::board::types::PadStackType::PST_THROUGH );
padstack->set_start_layer(
ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( m_layer ) );
padstack->set_end_layer(
ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( 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<PAD_SHAPE, kiapi::board::types::PadStackShape>( GetShape() ) );
padstack->set_unconnected_layer_removal(
ToProtoEnum<PADSTACK::UNCONNECTED_LAYER_MODE,
kiapi::board::types::UnconnectedLayerRemoval>( 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<ZONE_CONNECTION,
kiapi::board::types::ZoneConnectionStyle>( GetLocalZoneConnection() ) );
ToProtoEnum<ZONE_CONNECTION, ZoneConnectionStyle>( 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_ATTRIB>( 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<PCB_LAYER_ID, kiapi::board::types::BoardLayer>(
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<PAD_SHAPE>( layer.shape() ) );
}
SetUnconnectedLayerMode(
FromProtoEnum<PADSTACK::UNCONNECTED_LAYER_MODE>( 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<SHAPE_SEGMENT>( 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 )

View File

@ -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;

View File

@ -20,10 +20,15 @@
#include <convert_basic_shapes_to_polygon.h> // RECT_CHAMFER_POSITIONS
#include "padstack.h"
#include <api/api_enums.h>
#include <api/api_utils.h>
#include <api/api_pcb_utils.h>
#include <api/board/board_types.pb.h>
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<MODE>( 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<PCB_LAYER_ID>( padstack.start_layer() );
Drill().end = FromProtoEnum<PCB_LAYER_ID>( 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<PAD_SHAPE>( 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<UNCONNECTED_LAYER_MODE>( 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<MODE, PadStackType>( m_mode ) );
padstack.set_start_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( StartLayer() ) );
padstack.set_end_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( 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<PAD_SHAPE, PadStackShape>( 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<UNCONNECTED_LAYER_MODE, UnconnectedLayerRemoval>( 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 ),

View File

@ -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;

View File

@ -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<GR_TEXT_H_ALIGN_T, types::HorizontalAlignment>(
text.attributes().horizontal_alignment() );

View File

@ -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<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( stack.Drill().start ) );
padstack->set_end_layer(
ToProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>( 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::UNCONNECTED_LAYER_MODE,
kiapi::board::types::UnconnectedLayerRemoval>(
Padstack().UnconnectedLayerMode() ) );
via.set_type( ToProtoEnum<VIATYPE, kiapi::board::types::ViaType>( 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<PCB_LAYER_ID, kiapi::board::types::BoardLayer>(
padstack.start_layer() );
Padstack().Drill().end = FromProtoEnum<PCB_LAYER_ID, kiapi::board::types::BoardLayer>(
padstack.end_layer() );
}
else
{
Padstack().Drill().start = F_Cu;
Padstack().Drill().end = B_Cu;
}
Padstack().SetUnconnectedLayerMode( FromProtoEnum<PADSTACK::UNCONNECTED_LAYER_MODE>(
padstack.unconnected_layer_removal() ) );
SetWidth( m_padStack.Size().x );
SetViaType( FromProtoEnum<VIATYPE>( via.type() ) );
SetNetCode( via.net().code().value() );
SetLocked( via.locked() == kiapi::common::types::LockedState::LS_LOCKED );

View File

LOADING design file

View File

@ -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": {}
}

View File

@ -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<kiapi::board::types::Zone>( 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<kiapi::board::types::Via>( static_cast<PCB_VIA*>( track ) );
break;
default:
wxFAIL;
}
}
for( FOOTPRINT* footprint : m_board->Footprints() )
testProtoFromKiCadObject<kiapi::board::types::FootprintInstance>( footprint );
}
BOOST_AUTO_TEST_SUITE_END()