Gerbview: fix some issues related to comments and primitives in macros:

- comments on more than one line were not fully skipped, creating read errors
- in macros, some primitives (not all) were incorrectly rotated: they must be
rotated around the aperture macro origin, not the primitive origin.
- a new test file with rotated primitives in macros is added.
Fixes #16049
https://gitlab.com/kicad/code/kicad/-/issues/16049
This commit is contained in:
jean-pierre charras 2023-11-08 10:45:13 +01:00
parent 7abe2e3ea0
commit 72ce955066
6 changed files with 162 additions and 30 deletions

View File

@ -92,6 +92,7 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
SHAPE_POLY_SET& aShapeBuffer ) SHAPE_POLY_SET& aShapeBuffer )
{ {
// Draw the primitive shape for flashed items. // Draw the primitive shape for flashed items.
// Note: rotation of primitives inside a macro must be always done around the macro origin.
// Create a static buffer to avoid a lot of memory reallocation. // Create a static buffer to avoid a lot of memory reallocation.
static std::vector<VECTOR2I> polybuffer; static std::vector<VECTOR2I> polybuffer;
polybuffer.clear(); polybuffer.clear();
@ -218,15 +219,17 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
for( int ii = 0; ii < 4; ii++ ) for( int ii = 0; ii < 4; ii++ )
{ {
polybuffer = subshape_poly; polybuffer = subshape_poly;
EDA_ANGLE sub_rotation = rotation + ANGLE_90 * ii; EDA_ANGLE sub_rotation = ANGLE_90 * ii;
for( unsigned jj = 0; jj < polybuffer.size(); jj++ ) for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
RotatePoint( polybuffer[jj], -sub_rotation ); RotatePoint( polybuffer[jj], -sub_rotation );
// Move to center position given by the tool: // Move to center position given by the tool, and rotate the full shape around
// the center position (origin of the macro):
for( unsigned jj = 0; jj < polybuffer.size(); jj++ ) for( unsigned jj = 0; jj < polybuffer.size(); jj++ )
{ {
polybuffer[jj] += center; polybuffer[jj] += center;
RotatePoint( polybuffer[jj], -rotation );
} }
aShapeBuffer.NewOutline(); aShapeBuffer.NewOutline();
@ -264,6 +267,8 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
VECTOR2I center( mapPt( m_Params[0].GetValueFromMacro( aApertMacro ), VECTOR2I center( mapPt( m_Params[0].GetValueFromMacro( aApertMacro ),
m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric ) ); m_Params[1].GetValueFromMacro( aApertMacro ), m_GerbMetric ) );
EDA_ANGLE rotation( m_Params[8].GetValueFromMacro( aApertMacro ), DEGREES_T );
// adjust outerDiam by this on each nested circle // adjust outerDiam by this on each nested circle
int diamAdjust = ( gap + penThickness ) * 2; int diamAdjust = ( gap + penThickness ) * 2;
@ -272,17 +277,21 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
if( outerDiam <= 0 ) if( outerDiam <= 0 )
break; break;
// calculate the rotated position of the center:
VECTOR2I circle_center = center;
RotatePoint( circle_center, -rotation );
// Note: outerDiam is the outer diameter of the ring. // Note: outerDiam is the outer diameter of the ring.
// the ring graphic diameter is (outerDiam - penThickness) // the ring graphic diameter is (outerDiam - penThickness)
if( outerDiam <= penThickness ) if( outerDiam <= penThickness )
{ // No room to draw a ring (no room for the hole): { // No room to draw a ring (no room for the hole):
// draw a circle instead (with no hole), with the right diameter // draw a circle instead (with no hole), with the right diameter
TransformCircleToPolygon( aShapeBuffer, center, outerDiam / 2, arc_to_seg_error, TransformCircleToPolygon( aShapeBuffer, circle_center, outerDiam / 2, arc_to_seg_error,
ERROR_INSIDE ); ERROR_INSIDE );
} }
else else
{ {
TransformRingToPolygon( aShapeBuffer, center, ( outerDiam - penThickness ) / 2, TransformRingToPolygon( aShapeBuffer, circle_center, ( outerDiam - penThickness ) / 2,
penThickness, arc_to_seg_error, ERROR_INSIDE ); penThickness, arc_to_seg_error, ERROR_INSIDE );
} }
} }
@ -290,13 +299,11 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
// Draw the cross: // Draw the cross:
ConvertShapeToPolygon( aApertMacro, polybuffer ); ConvertShapeToPolygon( aApertMacro, polybuffer );
EDA_ANGLE rotation( m_Params[8].GetValueFromMacro( aApertMacro ), DEGREES_T );
for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
{ {
// move crossair shape to center and rotate shape: // move crossair shape to center and rotate shape:
RotatePoint( polybuffer[ii], -rotation );
polybuffer[ii] += center; polybuffer[ii] += center;
RotatePoint( polybuffer[ii], -rotation );
} }
break; break;
@ -375,13 +382,13 @@ void AM_PRIMITIVE::ConvertBasicShapeToPolygon( APERTURE_MACRO* aApertMacro,
// Creates the shape: // Creates the shape:
ConvertShapeToPolygon( aApertMacro, polybuffer ); ConvertShapeToPolygon( aApertMacro, polybuffer );
// rotate polygon // move and rotate polygonal shape
EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T ); EDA_ANGLE rotation( m_Params[5].GetValueFromMacro( aApertMacro ), DEGREES_T );
for( unsigned ii = 0; ii < polybuffer.size(); ii++ ) for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
{ {
RotatePoint( polybuffer[ii], -rotation );
polybuffer[ii] += curPos; polybuffer[ii] += curPos;
RotatePoint( polybuffer[ii], -rotation );
} }
break; break;

View File

@ -99,6 +99,10 @@ public:
// and the actual coordinates calculation must handle this // and the actual coordinates calculation must handle this
}; };
// size of a single line of text from a gerber file.
// warning: some files can have *very long* lines, so the buffer must be large.
#define GERBER_BUFZ 1000000
/** /**
* Hold the image data and parameters for one gerber file and layer parameters. * Hold the image data and parameters for one gerber file and layer parameters.
* *
@ -469,6 +473,9 @@ public:
VECTOR2I m_DisplayOffset; VECTOR2I m_DisplayOffset;
EDA_ANGLE m_DisplayRotation; EDA_ANGLE m_DisplayRotation;
// A large buffer to store one line
static char m_LineBuffer[GERBER_BUFZ+1];
private: private:
wxArrayString m_messagesList; // A list of messages created when reading a file wxArrayString m_messagesList; // A list of messages created when reading a file

View File

@ -0,0 +1,125 @@
G04 ================================================================================================
Copyright (C) 2023 Tony Luken <tonyluken62+gerberfileparser.gmail.com>
This file is part of GerberFileParser.
GerberFileParser is free software: you can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
GerberFileParser is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with GerberFileParser. If
not, see <http://www.gnu.org/licenses/>.
===================================================================================================*
G04 Demonstrate rotation of all macro primitives*
G04 Set coordinate format and units*
%FSLAX26Y26*%
%MOMM*%
G04 Demo Circle Primitive*
%AMSomeCircles*
0 1, Exposure, Diameter, Center X, Center Y[, Rotation]*
1,1,4,8,-5,0*
1,1,4,8,-5,120*
1,1,4,8,-5,240*
%
G04 Demo Polygon Primitive*
%AMSomePolygons*
0 5, Exposure, # vertices, Center X, Center Y, Diameter, Rotation*
5,1,5,7,8,7.5,0*
5,1,5,7,8,7.5,120*
5,1,5,7,8,7.5,240*
%
G04 Demo Thermal Primitive*
%AMSomeThermals*
0 7, Center X, Center Y, Outer diameter, Inner diameter, Gap, Rotation*
7,-15,-5,3,2,0.5,0*
7,-15,-5,3,2,0.5,120*
7,-15,-5,3,2,0.5,-120*
%
G04 Demo Outline Primitive*
%AMSomeOutlines*
0 4, Exposure, # vertices, Start X, Start Y, Subsequent points..., Rotation*
4,1,3,15,2,15,5,19,2,15,2,0*
4,1,3,15,2,15,5,19,2,15,2,120*
4,1,3,15,2,15,5,19,2,15,2,240*
%
G04 Demo deprecated Lower Left Line Primitive*
%AMSomeLowerLeftLines*
0 22, Exposure, Width, Height, Lower Left X, Lower Left Y, Rotation*
22,1,20,3,-10,-25,0*
22,1,20,3,-10,-25,120*
22,1,20,3,-10,-25,240*
%
G04 Demo Center Line Primitive*
%AMSomeCenterLines*
0 21, Exposure, width, height, center X, center Y, rotation*
21,1,13,1.5,2,20,0*
21,1,13,1.5,2,20,120*
21,1,13,1.5,2,20,-120*
%
G04 Demo Vector Line Primitive including deprecated version (2)*
%AMSomeVectorLines*
0 20 (or 2), Exposure , Width, Start X, Start Y, End X, End Y, Rotation*
20,1,1.5,-2,2,-6,7,0*
20,1,1.5,-2,2,-6,7,120*
2,1,1.5,-2,2,-6,7,240*
%
G04 Demo deprecated Moire Primitive*
%AMSomeMoires*
0 6, Center X, Center Y, Outer Diameter, Ring Thickness, Ring Gap, Max #Rings,
Crosshair Thickness, Crosshair Length, Rotation*
6,3,-17,5,0.5,0.5,2,0.1,6,0*
6,3,-17,5,0.5,0.5,2,0.1,6,120*
6,3,-17,5,0.5,0.5,2,0.1,6,-120*
%
%ADD10SomeCircles*%
%ADD11SomePolygons*%
%ADD12SomeThermals*%
%ADD13SomeOutlines*%
%ADD14SomeLowerLeftLines*%
%ADD15SomeCenterLines*%
%ADD16SomeVectorLines*%
%ADD17SomeMoires*%
G01*
%LPD*%
D10*
X0Y0D03*
D11*
X0Y0D03*
D12*
X0Y0D03*
D13*
X0Y0D03*
D14*
X0Y0D03*
D15*
X0Y0D03*
D16*
X0Y0D03*
D17*
X0Y0D03*
M02*

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2007-2016 Jean-Pierre Charras jp.charras at wanadoo.fr * Copyright (C) 2007-2016 Jean-Pierre Charras jp.charras at wanadoo.fr
* Copyright (C) 1992-2016 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -224,11 +224,9 @@ bool GERBER_FILE_IMAGE::TestFileIsRS274( const wxString& aFullFileName )
return false; return false;
} }
// size of a single line of text from a gerber file.
// warning: some files can have *very long* lines, so the buffer must be large.
#define GERBER_BUFZ 1000000
// A large buffer to store one line // A large buffer to store one line
static char lineBuffer[GERBER_BUFZ+1]; char GERBER_FILE_IMAGE::m_LineBuffer[GERBER_BUFZ+1];
bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName ) bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
{ {
@ -253,11 +251,11 @@ bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
while( true ) while( true )
{ {
if( fgets( lineBuffer, GERBER_BUFZ, m_Current_File ) == nullptr ) if( fgets( m_LineBuffer, GERBER_BUFZ, m_Current_File ) == nullptr )
break; break;
m_LineNum++; m_LineNum++;
text = StrPurge( lineBuffer ); text = StrPurge( m_LineBuffer );
while( text && *text ) while( text && *text )
{ {
@ -314,7 +312,7 @@ bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
if( m_CommandState != ENTER_RS274X_CMD ) if( m_CommandState != ENTER_RS274X_CMD )
{ {
m_CommandState = ENTER_RS274X_CMD; m_CommandState = ENTER_RS274X_CMD;
ReadRS274XCommand( lineBuffer, GERBER_BUFZ, text ); ReadRS274XCommand( m_LineBuffer, GERBER_BUFZ, text );
} }
else //Error else //Error
{ {

View File

@ -1,8 +1,3 @@
/**
* @file rs274d.cpp
* @brief functions to read the rs274d commands from a rs274d/rs274x file
*/
/* /*
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
@ -26,6 +21,11 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
/**
* @brief functions to read the rs274d commands from a rs274d/rs274x file
*/
#include <gerbview.h> #include <gerbview.h>
#include <gerbview_frame.h> #include <gerbview_frame.h>
#include <trigo.h> #include <trigo.h>
@ -464,8 +464,7 @@ bool GERBER_FILE_IMAGE::Execute_G_Command( char*& text, int G_command )
ExecuteRS274XCommand( code_command, nullptr, 0, cptr ); ExecuteRS274XCommand( code_command, nullptr, 0, cptr );
} }
while( *text && (*text != '*') ) GetEndOfBlock( m_LineBuffer, GERBER_BUFZ, text, m_Current_File );
text++;
break; break;

View File

@ -2,7 +2,7 @@
* This program source code file is part of KiCad, a free EDA CAD application. * This program source code file is part of KiCad, a free EDA CAD application.
* *
* Copyright (C) 2007-2018 Jean-Pierre Charras jp.charras at wanadoo.fr * Copyright (C) 2007-2018 Jean-Pierre Charras jp.charras at wanadoo.fr
* Copyright (C) 1992-2018 KiCad Developers, see AUTHORS.txt for contributors. * Copyright (C) 1992-2023 KiCad Developers, see AUTHORS.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -22,9 +22,6 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
/**
* @file rs274x.cpp
*/
#include <base_units.h> #include <base_units.h>
#include <math/util.h> // for KiROUND #include <math/util.h> // for KiROUND
@ -1049,8 +1046,7 @@ bool GERBER_FILE_IMAGE::ReadApertureMacro( char *aBuff, unsigned int aBuffSize,
is_comment = true; is_comment = true;
// Skip comment // Skip comment
while( *aText && ( *aText != '*' ) ) GetEndOfBlock( m_LineBuffer, GERBER_BUFZ, aText, m_Current_File );
aText++;
break; break;