void AddGerberX2Attribute( PLOTTER * aPlotter, const BOARD *aBoard, LAYER_NUM aLayer, bool aUseX1CompatibilityMode ) { AddGerberX2Header( aPlotter, aBoard, aUseX1CompatibilityMode ); wxString text; // Add the TF.FileFunction text = GetGerberFileFunctionAttribute( aBoard, aLayer ); aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) ); // Add the TF.FilePolarity (for layers which support that) text = GetGerberFilePolarityAttribute( aLayer ); if( !text.IsEmpty() ) aPlotter->AddLineToHeader( makeStringCompatX1( text, aUseX1CompatibilityMode ) ); }
int GERBER_WRITER::createDrillFile( wxString& aFullFilename, bool aIsNpth, int aLayer1, int aLayer2 ) { int holes_count; LOCALE_IO dummy; // Use the standard notation for double numbers GERBER_PLOTTER plotter; // Gerber drill file imply X2 format: plotter.UseX2Attributes( true ); plotter.UseX2NetAttributes( true ); // Add the standard X2 header, without FileFunction AddGerberX2Header( &plotter, m_pcb ); plotter.SetViewport( m_offset, IU_PER_MILS/10, /* scale */ 1.0, /* mirror */false ); // has meaning only for gerber plotter. Must be called only after SetViewport plotter.SetGerberCoordinatesFormat( 6 ); plotter.SetCreator( wxT( "PCBNEW" ) ); // Add the standard X2 FileFunction for drill files // %TF.FileFunction,Plated[NonPlated],layer1num,layer2num,PTH[NPTH][Blind][Buried],Drill[Route][Mixed]*% wxString text( "%TF.FileFunction," ); if( aIsNpth ) text << "NonPlated,"; else text << "Plated,"; // In Gerber files, layers num are 1 to copper layer count instead of F_Cu to B_Cu // (0 to copper layer count-1) // Note also for a n copper layers board, gerber layers num are 1 ... n aLayer1 += 1; if( aLayer2 == B_Cu ) aLayer2 = m_pcb->GetCopperLayerCount(); else aLayer2 += 1; text << aLayer1 << ","; text << aLayer2 << ","; // Now add PTH or NPTH or Blind or Buried attribute int toplayer = 1; int bottomlayer = m_pcb->GetCopperLayerCount(); if( aIsNpth ) text << "NPTH"; else if( aLayer1 == toplayer && aLayer2 == bottomlayer ) text << "PTH"; else if( aLayer1 == toplayer || aLayer2 == bottomlayer ) text << "Blind"; else text << "Buried"; // Now add Drill or Route or Mixed: // file containing only round holes have Drill attribute // file containing only oblong holes have Routed attribute // file containing both holes have Mixed attribute bool hasOblong = false; bool hasDrill = false; for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ ) { HOLE_INFO& hole_descr = m_holeListBuffer[ii]; if( hole_descr.m_Hole_Shape ) // m_Hole_Shape not 0 is an oblong hole) hasOblong = true; else hasDrill = true; } if( hasOblong && hasDrill ) text << ",Mixed"; else if( hasDrill ) text << ",Drill"; else if( hasOblong ) text << ",Route"; // else: empty file. // End of attribute: text << "*%"; plotter.AddLineToHeader( text ); if( !plotter.OpenFile( aFullFilename ) ) return -1; plotter.StartPlot(); holes_count = 0; wxPoint hole_pos; for( unsigned ii = 0; ii < m_holeListBuffer.size(); ii++ ) { HOLE_INFO& hole_descr = m_holeListBuffer[ii]; hole_pos = hole_descr.m_Hole_Pos; // Manage the aperture attributes: in drill files 3 attributes can be used: // "ViaDrill", only for vias, not pads // "ComponentDrill", only for Through Holes pads // "Slot" for oblong holes; GBR_METADATA gbr_metadata; if( dyn_cast<const VIA*>(hole_descr.m_ItemParent ) ) gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_VIADRILL ); else if( dyn_cast<const D_PAD*>( hole_descr.m_ItemParent ) ) { if( hole_descr.m_Hole_Shape ) gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_SLOTDRILL ); else gbr_metadata.SetApertureAttrib( GBR_APERTURE_METADATA::GBR_APERTURE_ATTRIB_COMPONENTDRILL ); // Add object attribute: component reference to pads (mainly usefull for users) const D_PAD* pad = dyn_cast<const D_PAD*>( hole_descr.m_ItemParent ); gbr_metadata.SetCmpReference( pad->GetParent()->GetReference() ); gbr_metadata.SetNetAttribType( GBR_NETLIST_METADATA::GBR_NETINFO_CMP ); } if( hole_descr.m_Hole_Shape ) { #if 0 // set to 1 to use flashed oblong holes. // Currently not possible for hole orient != 0 or 90 deg // Use flashed oblong hole plotter.FlashPadOval( hole_pos, hole_descr.m_Hole_Size, hole_descr.m_Hole_Orient, FILLED, &gbr_metadata ); #else // Use routing for oblong hole (Slots) wxPoint start, end; convertOblong2Segment( hole_descr.m_Hole_Size, hole_descr.m_Hole_Orient, start, end ); int width = std::min( hole_descr.m_Hole_Size.x, hole_descr.m_Hole_Size.y ); plotter.ThickSegment( start+hole_pos, end+hole_pos, width, FILLED, &gbr_metadata ); #endif } else { int diam = std::min( hole_descr.m_Hole_Size.x, hole_descr.m_Hole_Size.y ); plotter.FlashPadCircle( hole_pos, diam, FILLED, &gbr_metadata ); } holes_count++; } plotter.EndPlot(); return holes_count; }