diff --git a/gerbview/excellon_image.h b/gerbview/excellon_image.h index cb24e0c6ec..5bda861442 100644 --- a/gerbview/excellon_image.h +++ b/gerbview/excellon_image.h @@ -53,6 +53,8 @@ enum drill_M_code_t { DRILL_RESET_CMD, DRILL_AUTOMATIC_TOOL_CHANGE, DRILL_FMT, + DRILL_FORMAT_ALTIUM, + DRILL_HEADER_SKIP, DRILL_SKIP, DRILL_TOOL_INFORMATION, DRILL_M_END_LIST // not used: sentinel @@ -164,6 +166,14 @@ private: bool Execute_EXCELLON_G_Command( char*& text ); bool Execute_Drill_Command( char*& text ); + /** + * Read an Altium-specific FILE_FORMAT=X:X attribute that specifies the length + * and mantissa of the numbers in the gerber file + * + * @param aText Text containing format and mantissa + */ + void readFileFormat( char*& aText ); + /** * Read a tool definition like T1C0.02 or T1F00S00C0.02 or T1C0.02F00S00 * and enter params in TCODE list. diff --git a/gerbview/excellon_read_drill_file.cpp b/gerbview/excellon_read_drill_file.cpp index 4b1ce3ee3f..8ef546fa1d 100644 --- a/gerbview/excellon_read_drill_file.cpp +++ b/gerbview/excellon_read_drill_file.cpp @@ -213,6 +213,9 @@ static EXCELLON_CMD excellonHeaderCmdList[] = { "DETECT", DRILL_DETECT_BROKEN, -1 }, { "ICI", DRILL_INCREMENTALHEADER, 1 }, { "FMAT", DRILL_FMT, 1 }, // Use Format command + { ";FILE_FORMAT", + DRILL_FORMAT_ALTIUM, 1 }, // Use Format command + { ";", DRILL_HEADER_SKIP, 0 }, // Other ; hints that we don't implement { "ATC", DRILL_AUTOMATIC_TOOL_CHANGE, 0 }, { "TCST", DRILL_TOOL_CHANGE_STOP, 0 }, // Tool Change Stop { "AFS", DRILL_AUTOMATIC_SPEED, 0 }, // Automatic Feeds and Speeds @@ -345,7 +348,7 @@ bool EXCELLON_IMAGE::LoadFile( const wxString & aFullFileName ) char* line = excellonReader.Line(); char* text = StrPurge( line ); - if( *text == ';' || *text == 0 ) // comment: skip line or empty malformed line + if( *text == 0 ) // Skip empty lines continue; if( m_State == EXCELLON_IMAGE::READ_HEADER_STATE ) @@ -356,6 +359,7 @@ bool EXCELLON_IMAGE::LoadFile( const wxString & aFullFileName ) { switch( *text ) { + case ';': case 'M': Execute_HEADER_And_M_Command( text ); break; @@ -474,6 +478,13 @@ bool EXCELLON_IMAGE::Execute_HEADER_And_M_Command( char*& text ) m_State = READ_PROGRAM_STATE; break; + case DRILL_FORMAT_ALTIUM: + readFileFormat( text ); + break; + + case DRILL_HEADER_SKIP: + break; + case DRILL_M_METRIC: SelectUnits( true ); break; @@ -568,6 +579,42 @@ bool EXCELLON_IMAGE::Execute_HEADER_And_M_Command( char*& text ) } +void EXCELLON_IMAGE::readFileFormat( char*& aText ) +{ + int mantissaDigits = 0; + int characteristicDigits = 0; + + // Example String: ;FILE_FORMAT=4:4 + // The ;FILE_FORMAT potion will already be stripped off. + // Parse the rest strictly as single_digit:single_digit like 4:4 or 2:4 + // Don't allow anything clever like spaces or multiple digits + if( *aText != '=' ) + return; + + aText++; + + if( !isdigit( *aText ) ) + return; + + characteristicDigits = *aText - '0'; + aText++; + + if( *aText != ':' ) + return; + + aText++; + + if( !isdigit( *aText ) ) + return; + + mantissaDigits = *aText - '0'; + + m_hasFormat = true; + m_FmtLen.x = m_FmtLen.y = characteristicDigits + mantissaDigits; + m_FmtScale.x = m_FmtScale.y = mantissaDigits; +} + + bool EXCELLON_IMAGE::readToolInformation( char*& aText ) { // Read a tool definition like T1C0.02 or T1F00S00C0.02 or T1C0.02F00S00 @@ -885,16 +932,24 @@ void EXCELLON_IMAGE::SelectUnits( bool aMetric ) if( aMetric ) { m_GerbMetric = true; - // number of digits in mantissa - m_FmtScale.x = m_FmtScale.y = fmtMantissaMM; - // number of digits (mantissa+integer) - m_FmtLen.x = m_FmtLen.y = fmtIntegerMM+fmtMantissaMM; + + if( !m_hasFormat ) + { + // number of digits in mantissa + m_FmtScale.x = m_FmtScale.y = fmtMantissaMM; + // number of digits (mantissa+integer) + m_FmtLen.x = m_FmtLen.y = fmtIntegerMM + fmtMantissaMM; + } } else { m_GerbMetric = false; - m_FmtScale.x = m_FmtScale.y = fmtMantissaInch; - m_FmtLen.x = m_FmtLen.y = fmtIntegerInch+fmtMantissaInch; + + if( !m_hasFormat ) + { + m_FmtScale.x = m_FmtScale.y = fmtMantissaInch; + m_FmtLen.x = m_FmtLen.y = fmtIntegerInch + fmtMantissaInch; + } } } diff --git a/gerbview/gerber_file_image.cpp b/gerbview/gerber_file_image.cpp index fbdc3501ab..a65130b009 100644 --- a/gerbview/gerber_file_image.cpp +++ b/gerbview/gerber_file_image.cpp @@ -183,6 +183,7 @@ void GERBER_FILE_IMAGE::ResetDefaultValues() m_ImageJustifyXCenter = false; // Image Justify Center on X axis (default = false) m_ImageJustifyYCenter = false; // Image Justify Center on Y axis (default = false) m_GerbMetric = false; // false = Inches (default), true = metric + m_hasFormat = false; m_Relative = false; // false = absolute Coord, // true = relative Coord m_NoTrailingZeros = false; // true: trailing zeros deleted diff --git a/gerbview/gerber_file_image.h b/gerbview/gerber_file_image.h index 348448a894..933a59e00e 100644 --- a/gerbview/gerber_file_image.h +++ b/gerbview/gerber_file_image.h @@ -379,6 +379,7 @@ public: ///< Image Justify Offset on XY axis (default = 0,0). wxPoint m_ImageJustifyOffset; bool m_GerbMetric; // false = Inches, true = metric + bool m_hasFormat; ///< false = absolute Coord, true = relative Coord. bool m_Relative;