62 fmt_text = aText.utf8_string();
105 const char* value =
nullptr;
110 case SIDE_TOP: value =
"TopOnly";
break;
130 msg.Printf(
_(
"Failed to create file '%s'." ), aFullFilename );
136 msg.Printf(
_(
"Created Gerber job file '%s'." ), aFullFilename );
148 "GenerationSoftware",
150 {
"Vendor",
"KiCad" },
151 {
"Application",
"Pcbnew" },
167 std::ofstream file( aFullFilename.ToUTF8() );
169 m_json = nlohmann::ordered_json( {} );
186 file << std::setw( 2 ) <<
m_json << std::endl;
202 sscanf( buffer,
"%Lg", &output );
211 m_json[
"GeneralSpecs"] = nlohmann::ordered_json( {} );
212 m_json[
"GeneralSpecs"][
"ProjectId"] = nlohmann::ordered_json( {} );
223 wxFileName fn =
m_pcb->GetFileName();
224 wxString msg = fn.GetFullName();
239 m_json[
"GeneralSpecs"][
"ProjectId"][
"Name"] = msg.utf8_string().c_str();
240 m_json[
"GeneralSpecs"][
"ProjectId"][
"GUID"] = guid;
241 m_json[
"GeneralSpecs"][
"ProjectId"][
"Revision"] = rev.utf8_string().c_str();
244 BOX2I brect =
m_pcb->GetBoardEdgesBoundingBox();
252 m_json[
"GeneralSpecs"][
"LayerNumber"] =
m_pcb->GetCopperLayerCount();
255 m_json[
"GeneralSpecs"][
"BoardThickness"] =
265 m_json[
"GeneralSpecs"][
"ImpedanceControlled"] =
true;
268 if( brd_stackup.m_CastellatedPads )
269 m_json[
"GeneralSpecs"][
"Castellated"] =
true;
271 if(
m_pcb->GetPadWithCastellatedAttrCount() )
272 m_json[
"GeneralSpecs"][
"Castellated"] =
true;
274 if(
m_pcb->GetPadWithPressFitAttrCount() )
275 m_json[
"GeneralSpecs"][
"Press-fit"] =
true;
278 m_json[
"GeneralSpecs"][
"EdgePlating"] =
true;
282 m_json[
"GeneralSpecs"][
"EdgeConnector"] =
true;
284 m_json[
"GeneralSpecs"][
"EdgeConnectorBevelled"] =
297 m_json[
"GeneralSpecs"][
"IPC-2221-Type"] = 4;
313 m_json[
"GeneralSpecs"][
"ViaProtection"] =
"Ib";
321 m_json[
"FilesAttributes"] = nlohmann::ordered_json::array();
323 for(
unsigned ii = 0; ii <
m_params.m_GerberFileList.GetCount(); ii++ )
327 wxString gbr_layer_id;
328 bool skip_file =
false;
329 const char* polarity =
"Positive";
331 nlohmann::ordered_json file_json;
335 gbr_layer_id = wxT(
"Copper,L" );
338 gbr_layer_id <<
m_pcb->GetCopperLayerCount();
339 else if( layer ==
F_Cu )
343 gbr_layer_id << (layer-
B_Cu) / 2 + 1;
345 gbr_layer_id << wxT(
"," );
348 gbr_layer_id << wxT(
"Bot" );
349 else if( layer ==
F_Cu )
350 gbr_layer_id << wxT(
"Top" );
352 gbr_layer_id << wxT(
"Inr" );
357 gbr_layer_id = wxT(
"Other,User" );
365 gbr_layer_id = wxT(
"Glue,Bot" );
368 gbr_layer_id = wxT(
"Glue,Top" );
372 gbr_layer_id = wxT(
"SolderPaste,Bot" );
375 gbr_layer_id = wxT(
"SolderPaste,Top" );
379 gbr_layer_id = wxT(
"Legend,Bot" );
382 gbr_layer_id = wxT(
"Legend,Top" );
386 gbr_layer_id = wxT(
"SolderMask,Bot" );
387 polarity =
"Negative";
390 gbr_layer_id = wxT(
"SolderMask,Top" );
391 polarity =
"Negative";
395 gbr_layer_id = wxT(
"Profile" );
399 gbr_layer_id = wxT(
"AssemblyDrawing,Bot" );
402 gbr_layer_id = wxT(
"AssemblyDrawing,Top" );
427 file_json[
"Path"] = strname.c_str();
428 file_json[
"FileFunction"] = gbr_layer_id;
429 file_json[
"FilePolarity"] = polarity;
431 m_json[
"FilesAttributes"] += file_json;
441 std::shared_ptr<NET_SETTINGS>& netSettings =
m_pcb->GetDesignSettings().m_NetSettings;
443 int minclearanceOuter = netSettings->GetDefaultNetclass()->GetClearance();
444 bool hasInnerLayers =
m_pcb->GetCopperLayerCount() > 2;
447 for(
const auto& [
name, netclass] : netSettings->GetNetclasses() )
449 if( netclass->HasClearance() )
450 minclearanceOuter = std::min( minclearanceOuter, netclass->GetClearance() );
455 int minclearance_track2track = minclearanceOuter;
460 int minPadClearanceOuter = netSettings->GetDefaultNetclass()->GetClearance();
461 int minPadClearanceInner = netSettings->GetDefaultNetclass()->GetClearance();
465 for(
PAD*
pad : footprint->Pads() )
469 int padClearance =
pad->GetOwnClearance( layer );
471 if( layer ==
B_Cu || layer ==
F_Cu )
472 minPadClearanceOuter = std::min( minPadClearanceOuter, padClearance );
474 minPadClearanceInner = std::min( minPadClearanceInner, padClearance );
479 m_json[
"DesignRules"] = { {
480 {
"Layers",
"Outer" },
481 {
"PadToPad",
mapValue( minPadClearanceOuter ) },
482 {
"PadToTrack",
mapValue( minPadClearanceOuter ) },
483 {
"TrackToTrack",
mapValue( minclearance_track2track ) }
487 int minclearanceInner = minclearanceOuter;
490 int mintrackWidthOuter = INT_MAX;
491 int mintrackWidthInner = INT_MAX;
498 if( track->GetLayer() ==
B_Cu || track->GetLayer() ==
F_Cu )
499 mintrackWidthOuter = std::min( mintrackWidthOuter, track->GetWidth() );
501 mintrackWidthInner = std::min( mintrackWidthInner, track->GetWidth() );
504 if( mintrackWidthOuter != INT_MAX )
505 m_json[
"DesignRules"][0][
"MinLineWidth"] =
mapValue( mintrackWidthOuter );
510 minclearanceOuter = INT_MAX;
511 minclearanceInner = INT_MAX;
515 if( zone->GetIsRuleArea() || !zone->IsOnCopperLayer() )
520 int zclerance = zone->GetOwnClearance( layer );
522 if( layer ==
B_Cu || layer ==
F_Cu )
523 minclearanceOuter = std::min( minclearanceOuter, zclerance );
525 minclearanceInner = std::min( minclearanceInner, zclerance );
529 if( minclearanceOuter != INT_MAX )
530 m_json[
"DesignRules"][0][
"TrackToRegion"] =
mapValue( minclearanceOuter );
532 if( minclearanceOuter != INT_MAX )
533 m_json[
"DesignRules"][0][
"RegionToRegion"] =
mapValue( minclearanceOuter );
537 m_json[
"DesignRules"] += nlohmann::ordered_json( {
538 {
"Layers",
"Inner" },
539 {
"PadToPad",
mapValue( minPadClearanceInner ) },
540 {
"PadToTrack",
mapValue( minPadClearanceInner ) },
541 {
"TrackToTrack",
mapValue( minclearance_track2track ) }
544 if( mintrackWidthInner != INT_MAX )
545 m_json[
"DesignRules"][1][
"MinLineWidth"] =
mapValue( mintrackWidthInner );
547 if( minclearanceInner != INT_MAX )
548 m_json[
"DesignRules"][1][
"TrackToRegion"] =
mapValue( minclearanceInner );
550 if( minclearanceInner != INT_MAX )
551 m_json[
"DesignRules"][1][
"RegionToRegion"] =
mapValue( minclearanceInner );
559 m_json[
"MaterialStackup"] = nlohmann::ordered_json::array();
568 if(
m_reporter && !uptodate &&
m_pcb->GetDesignSettings().m_HasStackup )
574 for(
int ii = 0; ii < brd_stackup.
GetCount(); ++ii )
578 int sub_layer_count =
581 for(
int sub_idx = 0; sub_idx < sub_layer_count; sub_idx++ )
586 std::string layer_name;
588 nlohmann::ordered_json layer_json;
593 layer_type = wxT(
"Copper" );
599 layer_type = wxT(
"Legend" );
604 layer_type = wxT(
"SolderMask" );
609 layer_type = wxT(
"SolderPaste" );
614 layer_type = wxT(
"Dielectric" );
617 if( sub_layer_count > 1 )
632 layer_json[
"Type"] = layer_type;
638 wxString colorName = item->
GetColor( sub_idx );
640 if( colorName.StartsWith( wxT(
"#" ) ) )
645 wxColor color(
COLOR4D( colorName ).ToColour() );
646 colorName.Printf( wxT(
"R%dG%dB%d" ),
653 const std::vector<FAB_LAYER_COLOR>& color_list =
664 if( colorName == prm_color.GetName() )
666 colorName = prm_color.GetColorAsString();
672 layer_json[
"Color"] = colorName;
677 layer_json[
"Thickness"] = thickness;
683 layer_json[
"Material"] = item->
GetMaterial( sub_idx );
694 layer_json[
"DielectricConstant"] = item->
FormatEpsilonR( sub_idx );
708 if( last_copper_layer ==
F_Cu )
709 next_copper_layer =
In1_Cu;
712 if( next_copper_layer/2 >=
m_pcb->GetCopperLayerCount() )
713 next_copper_layer =
B_Cu;
715 wxString subLayerName;
717 if( sub_layer_count > 1 )
718 subLayerName.Printf( wxT(
" (%d/%d)" ), sub_idx + 1, sub_layer_count );
720 wxString
name = wxString::Format( wxT(
"%s/%s%s" ),
725 layer_json[
"Name"] =
name;
730 note << wxString::Format( wxT(
"Type: %s" ), layer_name.c_str() );
732 note << wxString::Format( wxT(
" (from %s to %s)" ),
736 layer_json[
"Notes"] = note;
762 layer_json[
"Name"] = layer_name.c_str();
766 layer_json[
"Name"] = layer_name.c_str();
769 m_json[
"MaterialStackup"].insert(
m_json[
"MaterialStackup"].
end(), layer_json );
constexpr EDA_IU_SCALE pcbIUScale
bool IsPrmSpecified(const wxString &aPrmValue)
@ BS_EDGE_CONNECTOR_BEVELLED
@ BS_ITEM_TYPE_SILKSCREEN
@ BS_ITEM_TYPE_DIELECTRIC
@ BS_ITEM_TYPE_SOLDERPASTE
@ BS_ITEM_TYPE_SOLDERMASK
wxString GetBuildVersion()
Get the full KiCad version string.
Manage one layer needed to make a physical board.
wxString GetTypeName() const
int GetSublayersCount() const
double GetEpsilonR(int aDielectricSubLayer=0) const
wxString GetColor(int aDielectricSubLayer=0) const
bool HasMaterialValue(int aDielectricSubLayer=0) const
PCB_LAYER_ID GetBrdLayerId() const
bool IsThicknessEditable() const
int GetThickness(int aDielectricSubLayer=0) const
BOARD_STACKUP_ITEM_TYPE GetType() const
wxString GetMaterial(int aDielectricSubLayer=0) const
wxString FormatEpsilonR(int aDielectricSubLayer=0) const
int GetDielectricLayerId() const
bool IsColorEditable() const
wxString FormatLossTangent(int aDielectricSubLayer=0) const
double GetLossTangent(int aDielectricSubLayer=0) const
Manage layers needed to make a physical board.
bool SynchronizeWithBoard(BOARD_DESIGN_SETTINGS *aSettings)
Synchronize the BOARD_STACKUP_ITEM* list with the board.
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
BOARD_STACKUP_ITEM * GetStackupLayer(int aIndex)
bool m_EdgePlating
True if the edge board is plated.
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specified in job file: BS_EDGE_CONNECTO...
wxString m_FinishType
The name of external copper finish.
Information pertinent to a Pcbnew printed circuit board.
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
void addJSONHeader()
Add the job file header in JSON format to m_JSONbuffer.
void addJSONMaterialStackup()
Add the Material Stackup section in JSON format to m_JSONbuffer This is the ordered list of stackup l...
void addJSONFilesAttributes()
Add the Files Attributes section in JSON format to m_JSONbuffer.
nlohmann::ordered_json m_json
enum ONSIDE hasSilkLayers()
bool CreateJobFile(const wxString &aFullFilename)
Creates a Gerber job file.
void addJSONGeneralSpecs()
Add the General Specs in JSON format to m_JSONbuffer.
bool WriteJSONJobFile(const wxString &aFullFilename)
Creates an Gerber job file in JSON format.
enum ONSIDE hasSolderMasks()
double mapValue(double aUiValue)
A helper function to convert a double in Pcbnew internal units to a JSON double value (in mm),...
const char * sideKeyValue(enum ONSIDE aValue)
void addJSONDesignRules()
Add the Design Rules section in JSON format to m_JSONbuffer.
std::string formatStringFromUTF32(const wxString &aText)
A helper function to convert a wxString ( therefore a Unicode text ) to a JSON compatible string (a e...
GERBER_JOBFILE_WRITER(BOARD *aPcb, REPORTER *aReporter=nullptr)
A color representation with 4 components: red, green, blue, alpha.
LSET is a set of PCB_LAYER_IDs.
A pure virtual class used to derive REPORTER objects from.
Handle a list of polygons defining a copper zone.
wxString ExpandTextVars(const wxString &aSource, const PROJECT *aProject, RESOLUTION_CONTEXT aContext)
Classes used to generate a Gerber job file in JSON.
bool IsUserLayer(PCB_LAYER_ID aLayerId)
Test whether a layer is a non copper and a non tech layer.
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
PCB_LAYER_ID
A quick note on layer IDs:
const std::vector< FAB_LAYER_COLOR > & GetStandardColors(BOARD_STACKUP_ITEM_TYPE aType)
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition of file extensions used in Kicad.